in-memory MCP resuming an interrupted deployment
This commit is contained in:
@@ -415,7 +415,7 @@ def test_broker_run_deployment_returns_unrunnable_for_dependency_errors() -> Non
|
||||
assert payload["diagnostics"][0]["code"] == "source_missing"
|
||||
|
||||
|
||||
def test_broker_run_deployment_rejects_interrupting_artifacts() -> None:
|
||||
def test_broker_run_deployment_pauses_and_resumes_interrupting_artifacts() -> None:
|
||||
artifact_store = FileWorkflowArtifactStore(
|
||||
local_temp_root() / "broker_run_interrupt_artifacts"
|
||||
)
|
||||
@@ -445,9 +445,25 @@ def test_broker_run_deployment_rejects_interrupting_artifacts() -> None:
|
||||
)
|
||||
payload = cast(dict[str, Any], cast(object, structured))
|
||||
|
||||
assert payload["status"] == "unsupported"
|
||||
assert payload["output"] is None
|
||||
assert payload["diagnostics"][0]["code"] == "interrupting_artifact_unsupported"
|
||||
assert payload["status"] == "interrupted"
|
||||
assert payload["output"] == {}
|
||||
assert isinstance(payload["run_id"], str)
|
||||
assert payload["interrupt"]["payload"]["message"] == "send?"
|
||||
|
||||
_content, structured = asyncio.run(
|
||||
server.call_tool(
|
||||
"resume_workflow_run",
|
||||
{
|
||||
"run_id": payload["run_id"],
|
||||
"resume_payload": {},
|
||||
},
|
||||
)
|
||||
)
|
||||
resumed = cast(dict[str, Any], cast(object, structured))
|
||||
|
||||
assert resumed["status"] == "completed"
|
||||
assert resumed["outcome"] == "submitted"
|
||||
assert resumed["run_id"] is None
|
||||
|
||||
|
||||
def test_build_service_from_config_uses_store_root_for_artifacts() -> None:
|
||||
@@ -556,6 +572,7 @@ def _interrupt_artifact() -> WorkflowArtifact:
|
||||
},
|
||||
"state_schema": {"fields": {}},
|
||||
"output_schema": {"type": "object", "properties": {}},
|
||||
"outcomes": ["submitted"],
|
||||
"start": "approval",
|
||||
"nodes": [
|
||||
{
|
||||
@@ -565,8 +582,11 @@ def _interrupt_artifact() -> WorkflowArtifact:
|
||||
"request": [input_binding("input.message", "message")],
|
||||
"resume": [],
|
||||
"outcomes": ["submitted"],
|
||||
}
|
||||
},
|
||||
{"id": "end_submitted", "type": "end", "outcome": "submitted"},
|
||||
],
|
||||
"edges": [
|
||||
{"from": "approval", "outcome": "submitted", "to": "end_submitted"}
|
||||
],
|
||||
"edges": [{"from": "approval", "outcome": "submitted", "to": "__end__"}],
|
||||
},
|
||||
)
|
||||
|
||||
@@ -94,18 +94,44 @@ def test_saved_child_missing_parent_binding_is_unrunnable() -> None:
|
||||
assert result["diagnostics"][0]["logical_ref"] == "demo.echo_tool"
|
||||
|
||||
|
||||
def test_interrupting_saved_child_remains_unrunnable_on_deployment_surface() -> None:
|
||||
def test_interrupting_saved_child_pauses_and_resumes_through_deployment_surface() -> (
|
||||
None
|
||||
):
|
||||
store = FileWorkflowArtifactStore(local_temp_root() / "saved_subgraph_interrupt")
|
||||
store.save_artifact(_parent_artifact())
|
||||
store.save_artifact(_interrupting_child_artifact())
|
||||
store.save_deployment(_deployment())
|
||||
handlers = _handlers(store)
|
||||
|
||||
result = asyncio.run(handlers.validate_deployment(deployment_id="parent.personal"))
|
||||
validation = asyncio.run(
|
||||
handlers.validate_deployment(deployment_id="parent.personal")
|
||||
)
|
||||
|
||||
assert result["status"] == "unrunnable"
|
||||
assert result["diagnostics"][0]["code"] == "interrupting_artifact_unsupported"
|
||||
assert result["diagnostics"][0]["logical_ref"] == "workflow.child.v1"
|
||||
assert validation["status"] == "runnable"
|
||||
assert validation["diagnostics"] == []
|
||||
|
||||
paused = asyncio.run(
|
||||
handlers.run_deployment(
|
||||
deployment_id="parent.personal",
|
||||
workflow_input={"text": "hello"},
|
||||
)
|
||||
)
|
||||
|
||||
assert paused["status"] == "interrupted"
|
||||
assert isinstance(paused["run_id"], str)
|
||||
assert paused["interrupt"]["node_id"] == "child_step"
|
||||
assert paused["interrupt"]["payload"]["question"] == "hello"
|
||||
|
||||
resumed = asyncio.run(
|
||||
handlers.resume_run(
|
||||
run_id=paused["run_id"],
|
||||
resume_payload={"answer": "world"},
|
||||
)
|
||||
)
|
||||
|
||||
assert resumed["status"] == "completed"
|
||||
assert resumed["outcome"] == "ok"
|
||||
assert resumed["output"]["echoed"] == "world"
|
||||
|
||||
|
||||
def test_missing_saved_child_is_unrunnable_on_deployment_surface() -> None:
|
||||
|
||||
Reference in New Issue
Block a user