reducer as wf_mcp capability
This commit is contained in:
@@ -33,6 +33,26 @@ 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_adds_reducer_dependencies() -> None:
|
||||
plan = _plan()
|
||||
plan["state_schema"] = {
|
||||
"fields": {"best_score": {"type": "integer", "reducer": "wf.std.max"}}
|
||||
}
|
||||
|
||||
artifact = create_workflow_artifact_from_plan(
|
||||
artifact_id="score",
|
||||
version=1,
|
||||
title="Score",
|
||||
plan=plan,
|
||||
outcomes=("done",),
|
||||
)
|
||||
|
||||
reducer = artifact.required_capabilities["wf.std.max"]
|
||||
assert reducer.logical_source == "wf.std"
|
||||
assert reducer.capability_name == "max"
|
||||
assert reducer.kind == "reducer"
|
||||
|
||||
|
||||
def test_create_workflow_artifact_from_plan_accepts_wrapper_kind() -> None:
|
||||
artifact = create_workflow_artifact_from_plan(
|
||||
artifact_id="normalize_status",
|
||||
|
||||
@@ -176,3 +176,28 @@ def test_validate_deployment_allows_changed_schema_when_policy_allows() -> None:
|
||||
)
|
||||
|
||||
assert diagnostics == []
|
||||
|
||||
|
||||
def test_validate_deployment_accepts_reducer_capability() -> None:
|
||||
reducer = RequiredCapability(
|
||||
logical_source="wf.std",
|
||||
capability_name="set_union",
|
||||
kind="reducer",
|
||||
)
|
||||
diagnostics = validate_deployment_dependencies(
|
||||
artifact=artifact_with(reducer),
|
||||
deployment=deployment(bindings={"wf.std": "wf.std"}),
|
||||
sources=[
|
||||
AvailableSource(
|
||||
id="wf.std",
|
||||
capabilities={
|
||||
"set_union": AvailableCapability(
|
||||
name="set_union",
|
||||
kind="reducer",
|
||||
)
|
||||
},
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
assert diagnostics == []
|
||||
|
||||
@@ -40,7 +40,9 @@ def test_state_field_defaults_to_replace_reducer() -> None:
|
||||
|
||||
|
||||
def test_unknown_state_reducer_fails_clearly() -> None:
|
||||
workflow = _workflow(fields={"person.tags": StateField(type="array", reducer="x.nope")})
|
||||
workflow = _workflow(
|
||||
fields={"person.tags": StateField(type="array", reducer="x.nope")}
|
||||
)
|
||||
state = {"person": {"tags": ["seed"]}}
|
||||
|
||||
try:
|
||||
@@ -51,6 +53,28 @@ def test_unknown_state_reducer_fails_clearly() -> None:
|
||||
raise AssertionError("expected unknown reducer to fail")
|
||||
|
||||
|
||||
def test_set_union_reducer_preserves_first_seen_order() -> None:
|
||||
workflow = _workflow(
|
||||
fields={"person.tags": StateField(type="array", reducer="wf.std.set_union")}
|
||||
)
|
||||
state = {"person": {"tags": ["alpha", "beta"]}}
|
||||
|
||||
write_state_value(workflow, state, "state.person.tags", ["beta", "gamma"])
|
||||
|
||||
assert state["person"]["tags"] == ["alpha", "beta", "gamma"]
|
||||
|
||||
|
||||
def test_max_reducer_keeps_larger_value() -> None:
|
||||
workflow = _workflow(
|
||||
fields={"best_score": StateField(type="integer", reducer="wf.std.max")}
|
||||
)
|
||||
state = {"best_score": 7}
|
||||
|
||||
write_state_value(workflow, state, "state.best_score", 9)
|
||||
|
||||
assert state["best_score"] == 9
|
||||
|
||||
|
||||
def _workflow(*, fields: dict[str, StateField]) -> Workflow:
|
||||
return Workflow(
|
||||
name="nested_state_paths",
|
||||
|
||||
@@ -125,9 +125,7 @@ class PartialRates(SophisticatedRates, total=False):
|
||||
|
||||
|
||||
class Rates(BaseModel):
|
||||
rates: Annotated[
|
||||
PartialRates, state_field(reducer="wf.std.merge_object")
|
||||
] # or_!
|
||||
rates: Annotated[PartialRates, state_field(reducer="wf.std.merge_object")] # or_!
|
||||
|
||||
|
||||
class CurrentPools(BaseModel):
|
||||
|
||||
@@ -113,11 +113,13 @@ def test_service_lists_all_capability_sources_with_owned_capability_names() -> N
|
||||
assert "wf.std.runtime_error" in std_source["capabilities"]["node_specs"]
|
||||
assert std_source["capabilities"]["reducers"] == [
|
||||
"wf.std.append",
|
||||
"wf.std.max",
|
||||
"wf.std.merge_object",
|
||||
"wf.std.replace",
|
||||
"wf.std.set_union",
|
||||
]
|
||||
assert std_source["capabilities"]["tools"] == []
|
||||
assert std_source["reducer_count"] == 3
|
||||
assert std_source["reducer_count"] == 5
|
||||
|
||||
mcp_source = sources_by_id["wf.mcp"]
|
||||
assert mcp_source["capabilities"]["node_specs"] == ["wf.mcp.call_tool"]
|
||||
@@ -159,7 +161,9 @@ def test_wf_std_source_contains_builtin_reducers() -> None:
|
||||
assert set(reducers) == {
|
||||
"wf.std.replace",
|
||||
"wf.std.append",
|
||||
"wf.std.max",
|
||||
"wf.std.merge_object",
|
||||
"wf.std.set_union",
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user