artifacts. store and some models. For deployment

This commit is contained in:
lda
2026-05-11 15:11:18 +07:00 Verified
parent 090ff0208b
commit 958195ddce
6 changed files with 761 additions and 0 deletions
+20
View File
@@ -0,0 +1,20 @@
from .models import (
DependencyDiagnostic,
DiagnosticSeverity,
DriftPolicy,
RequiredCapability,
WorkflowArtifact,
WorkflowDeployment,
)
from .store import FileWorkflowArtifactStore, WorkflowArtifactStore
__all__ = [
"DependencyDiagnostic",
"DiagnosticSeverity",
"DriftPolicy",
"FileWorkflowArtifactStore",
"RequiredCapability",
"WorkflowArtifact",
"WorkflowArtifactStore",
"WorkflowDeployment",
]
+74
View File
@@ -0,0 +1,74 @@
from __future__ import annotations
from enum import StrEnum
from typing import Any, Literal
from pydantic import BaseModel, Field
JsonObject = dict[str, Any]
class DriftPolicy(StrEnum):
"""Policy for dependency drift that is detected but not proven unsafe."""
BLOCK = "block"
WARN = "warn"
ALLOW = "allow"
class DiagnosticSeverity(StrEnum):
"""Severity level for dependency validation diagnostics."""
ERROR = "error"
WARNING = "warning"
class RequiredCapability(BaseModel):
"""Saved contract for one capability an artifact references."""
logical_source: str
capability_name: str
kind: Literal["tool", "resource", "prompt", "node_spec", "workflow"]
input_schema_hash: str | None = None
input_schema_snapshot: JsonObject | None = None
output_schema_hash: str | None = None
output_schema_snapshot: JsonObject | None = None
observed_concrete_source: str | None = None
observed_at_epoch_ms: int | None = Field(default=None, ge=0)
class DependencyDiagnostic(BaseModel):
"""Machine-readable reason a deployment is degraded or unrunnable."""
severity: DiagnosticSeverity
code: str
logical_ref: str
bound_source: str | None = None
message: str
repair_hint: str | None = None
class WorkflowArtifact(BaseModel):
"""Immutable saved workflow definition plus dependency contract snapshots."""
id: str
version: int = Field(ge=1)
title: str
description: str | None = None
input_schema: JsonObject
output_schema: JsonObject
outcomes: tuple[str, ...]
plan: JsonObject
required_capabilities: dict[str, RequiredCapability] = Field(default_factory=dict)
workflow_dependencies: dict[str, int] = Field(default_factory=dict)
created_from_catalog_version: str | None = None
class WorkflowDeployment(BaseModel):
"""One configured way to run an artifact version in an environment."""
id: str
artifact_id: str
artifact_version: int = Field(ge=1)
bindings: dict[str, str] = Field(default_factory=dict)
drift_policy: DriftPolicy = DriftPolicy.BLOCK
+91
View File
@@ -0,0 +1,91 @@
from __future__ import annotations
import json
from pathlib import Path
from .models import WorkflowArtifact, WorkflowDeployment
class WorkflowArtifactStore:
"""Storage boundary for workflow artifacts and deployments."""
def save_artifact(self, artifact: WorkflowArtifact) -> None:
raise NotImplementedError
def get_artifact(self, artifact_id: str, version: int) -> WorkflowArtifact:
raise NotImplementedError
def list_artifacts(self) -> list[WorkflowArtifact]:
raise NotImplementedError
def resolve_latest(self, artifact_id: str) -> WorkflowArtifact:
raise NotImplementedError
def save_deployment(self, deployment: WorkflowDeployment) -> None:
raise NotImplementedError
def get_deployment(self, deployment_id: str) -> WorkflowDeployment:
raise NotImplementedError
class FileWorkflowArtifactStore(WorkflowArtifactStore):
"""JSON file-backed artifact store for local development and tests."""
def __init__(self, root: Path) -> None:
self.root = root
self.artifacts_dir.mkdir(parents=True, exist_ok=True)
self.deployments_dir.mkdir(parents=True, exist_ok=True)
@property
def artifacts_dir(self) -> Path:
return self.root / "workflows"
@property
def deployments_dir(self) -> Path:
return self.root / "deployments"
def save_artifact(self, artifact: WorkflowArtifact) -> None:
artifact_dir = self.artifacts_dir / artifact.id
artifact_dir.mkdir(parents=True, exist_ok=True)
path = artifact_dir / f"{artifact.version}.json"
path.write_text(
json.dumps(artifact.model_dump(mode="json"), indent=2),
encoding="utf-8",
)
def get_artifact(self, artifact_id: str, version: int) -> WorkflowArtifact:
path = self.artifacts_dir / artifact_id / f"{version}.json"
if not path.exists():
raise KeyError(f"unknown workflow artifact {artifact_id}@{version}")
return WorkflowArtifact.model_validate_json(path.read_text(encoding="utf-8"))
def list_artifacts(self) -> list[WorkflowArtifact]:
artifacts: list[WorkflowArtifact] = []
for path in sorted(self.artifacts_dir.glob("*/*.json")):
artifacts.append(
WorkflowArtifact.model_validate_json(path.read_text(encoding="utf-8"))
)
return artifacts
def resolve_latest(self, artifact_id: str) -> WorkflowArtifact:
versions = [
int(path.stem)
for path in (self.artifacts_dir / artifact_id).glob("*.json")
if path.stem.isdecimal()
]
if not versions:
raise KeyError(f"unknown workflow artifact {artifact_id!r}")
return self.get_artifact(artifact_id, max(versions))
def save_deployment(self, deployment: WorkflowDeployment) -> None:
path = self.deployments_dir / f"{deployment.id}.json"
path.write_text(
json.dumps(deployment.model_dump(mode="json"), indent=2),
encoding="utf-8",
)
def get_deployment(self, deployment_id: str) -> WorkflowDeployment:
path = self.deployments_dir / f"{deployment_id}.json"
if not path.exists():
raise KeyError(f"unknown workflow deployment {deployment_id!r}")
return WorkflowDeployment.model_validate_json(path.read_text(encoding="utf-8"))