simplest categorical addition
This commit is contained in:
@@ -85,7 +85,8 @@ how did the original provider happen to expose this thing?
|
||||
### Wrapper / Adapter Artifact
|
||||
|
||||
A wrapper artifact is a saved reusable bridge from a raw capability to a
|
||||
workflow capability.
|
||||
workflow capability. In storage it is not a second artifact family: it is a
|
||||
`WorkflowArtifact` with `kind="wrapper"`.
|
||||
|
||||
Examples:
|
||||
|
||||
@@ -264,10 +265,10 @@ Today:
|
||||
- `wf.std` owns local reusable workflow node specs
|
||||
- `wf.mcp` owns workflow-facing MCP runtime helpers
|
||||
- discovered upstream tools can already become workflow node specs
|
||||
- saved artifacts can be tagged with `kind="workflow"` or `kind="wrapper"`
|
||||
|
||||
Not yet implemented:
|
||||
|
||||
- a saved wrapper artifact model
|
||||
- a direct public tool for calling arbitrary workflow node specs for authoring
|
||||
tests
|
||||
- per-outcome output schemas
|
||||
|
||||
@@ -5,6 +5,7 @@ from .catalog import (
|
||||
)
|
||||
from .factory import create_workflow_artifact_from_plan
|
||||
from .models import (
|
||||
ArtifactKind,
|
||||
AvailableCapability,
|
||||
AvailableSource,
|
||||
DependencyDiagnostic,
|
||||
@@ -19,6 +20,7 @@ from .validation import validate_deployment_dependencies
|
||||
|
||||
__all__ = [
|
||||
"AvailableCapability",
|
||||
"ArtifactKind",
|
||||
"AvailableSource",
|
||||
"DependencyDiagnostic",
|
||||
"DiagnosticSeverity",
|
||||
|
||||
@@ -4,7 +4,7 @@ from collections.abc import Mapping
|
||||
|
||||
from wf_core import Workflow
|
||||
|
||||
from .models import JsonObject, RequiredCapability, WorkflowArtifact
|
||||
from .models import ArtifactKind, JsonObject, RequiredCapability, WorkflowArtifact
|
||||
|
||||
|
||||
def create_workflow_artifact_from_plan(
|
||||
@@ -14,6 +14,7 @@ def create_workflow_artifact_from_plan(
|
||||
title: str,
|
||||
plan: JsonObject,
|
||||
outcomes: tuple[str, ...],
|
||||
kind: ArtifactKind = "workflow",
|
||||
description: str | None = None,
|
||||
required_capabilities: Mapping[str, RequiredCapability] | None = None,
|
||||
created_from_catalog_version: str | None = None,
|
||||
@@ -24,6 +25,7 @@ def create_workflow_artifact_from_plan(
|
||||
id=artifact_id,
|
||||
version=version,
|
||||
title=title,
|
||||
kind=kind,
|
||||
description=description,
|
||||
input_schema=_required_object_field(plan, "input_schema"),
|
||||
output_schema=_required_object_field(plan, "output_schema"),
|
||||
|
||||
@@ -6,6 +6,7 @@ from typing import Any, Literal
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
JsonObject = dict[str, Any]
|
||||
ArtifactKind = Literal["workflow", "wrapper"]
|
||||
|
||||
|
||||
class DriftPolicy(StrEnum):
|
||||
@@ -71,6 +72,7 @@ class WorkflowArtifact(BaseModel):
|
||||
id: str
|
||||
version: int = Field(ge=1)
|
||||
title: str
|
||||
kind: ArtifactKind = "workflow"
|
||||
description: str | None = None
|
||||
input_schema: JsonObject
|
||||
output_schema: JsonObject
|
||||
|
||||
@@ -22,6 +22,7 @@ def test_create_workflow_artifact_from_plan_derives_boundary_schemas() -> None:
|
||||
)
|
||||
|
||||
assert artifact.id == "echo"
|
||||
assert artifact.kind == "workflow"
|
||||
assert artifact.version == 1
|
||||
assert artifact.title == "Echo"
|
||||
assert artifact.input_schema["properties"]["text"]["type"] == "string"
|
||||
@@ -32,6 +33,19 @@ def test_create_workflow_artifact_from_plan_derives_boundary_schemas() -> None:
|
||||
assert artifact.created_from_catalog_version == "catalog-1"
|
||||
|
||||
|
||||
def test_create_workflow_artifact_from_plan_accepts_wrapper_kind() -> None:
|
||||
artifact = create_workflow_artifact_from_plan(
|
||||
artifact_id="normalize_status",
|
||||
version=1,
|
||||
title="Normalize Status",
|
||||
plan=_plan(),
|
||||
outcomes=("done",),
|
||||
kind="wrapper",
|
||||
)
|
||||
|
||||
assert artifact.kind == "wrapper"
|
||||
|
||||
|
||||
def test_create_workflow_artifact_from_plan_rejects_missing_boundary_schema() -> None:
|
||||
plan = _plan()
|
||||
plan.pop("output_schema")
|
||||
|
||||
@@ -38,6 +38,7 @@ def test_workflow_artifact_serializes_required_capability_contract() -> None:
|
||||
dumped = artifact.model_dump(mode="json")
|
||||
|
||||
assert dumped["id"] == "summarize_docs"
|
||||
assert dumped["kind"] == "workflow"
|
||||
assert dumped["version"] == 1
|
||||
assert dumped["outcomes"] == ["done", "failed"]
|
||||
required = dumped["required_capabilities"]["context7.query-docs"]
|
||||
@@ -45,6 +46,23 @@ def test_workflow_artifact_serializes_required_capability_contract() -> None:
|
||||
assert required["input_schema_hash"] == "sha256:input"
|
||||
|
||||
|
||||
def test_workflow_artifact_can_be_marked_as_wrapper_intent() -> None:
|
||||
artifact = WorkflowArtifact(
|
||||
id="normalize_status",
|
||||
version=1,
|
||||
title="Normalize Status",
|
||||
kind="wrapper",
|
||||
input_schema={"type": "object", "properties": {}},
|
||||
output_schema={"type": "object", "properties": {}},
|
||||
outcomes=("done", "needs_input"),
|
||||
plan={"name": "normalize_status", "nodes": [], "edges": []},
|
||||
)
|
||||
|
||||
dumped = artifact.model_dump(mode="json")
|
||||
|
||||
assert dumped["kind"] == "wrapper"
|
||||
|
||||
|
||||
def test_workflow_deployment_binds_logical_sources_to_concrete_sources() -> None:
|
||||
deployment = WorkflowDeployment(
|
||||
id="summarize_docs.personal",
|
||||
|
||||
Reference in New Issue
Block a user