feat: add wf source resource refs

This commit is contained in:
lda
2026-06-13 23:04:28 +07:00 Verified
parent 97b0f5b052
commit 4983033b7b
24 changed files with 682 additions and 48 deletions
@@ -265,3 +265,40 @@ async def test_content_access_uses_stateful_runtime_for_upstream_content() -> No
assert prompt["messages"][0]["content"]["text"] == "stateful prompt"
assert runtime.resources == ["demo://docs/welcome"]
assert runtime.prompts == ["prompt.summarize"]
async def test_read_resource_by_source_uri_reads_upstream() -> None:
service = WfMcpService(
store=FileStore(local_temp_root() / "content_source_uri")
)
service.register_connection(
ConnectionConfig(id="demo.personal", server="demo", account="personal")
)
service.register_adapter("demo", FakeAdapter())
await service.refresh_connection_catalog("demo.personal")
result = await service.content_access.read_resource_by_source_uri(
source_id="demo.personal",
uri="demo://docs/welcome",
max_chars=4000,
)
assert result["contents"][0]["text"] == "Welcome from the fake adapter resource."
async def test_read_resource_by_source_uri_rejects_unknown_resource() -> None:
service = WfMcpService(
store=FileStore(local_temp_root() / "content_source_uri_unknown")
)
service.register_connection(
ConnectionConfig(id="demo.personal", server="demo", account="personal")
)
service.register_adapter("demo", FakeAdapter())
await service.refresh_connection_catalog("demo.personal")
with pytest.raises(KeyError, match="unknown resource"):
await service.content_access.read_resource_by_source_uri(
source_id="demo.personal",
uri="demo://nonexistent",
max_chars=4000,
)
+92 -2
View File
@@ -1,5 +1,6 @@
from __future__ import annotations
from wf_artifacts import WorkflowDeployment
from wf_core import END, NodeUse, RunStatus
from wf_mcp.broker import WfMcpService
from wf_mcp.broker.service.source_catalog import SourceCatalogService
@@ -9,7 +10,7 @@ from wf_mcp.models import ConnectionConfig
from wf_mcp.storage import FileStore
from wf_platform import CapabilityBuckets, CapabilitySource, SourceVisibility
from ..test_support import echo_tool, local_temp_root
from ..test_support import FakeAdapter, echo_tool, local_temp_root, output_binding
from .conftest import raw_plan, single_echo_plan
@@ -70,6 +71,7 @@ def test_wfmcpservice_constructs_workflow_runtime_with_source_catalog() -> None:
assert service.workflow_runtime.source_catalog is service.source_catalog
assert service.workflow_runtime.artifact_store is service.artifact_store
assert service.workflow_runtime.read_resource_handler is not None
def test_wfmcpservice_compile_plan_delegates_to_workflow_runtime() -> None:
@@ -98,7 +100,7 @@ def test_workflow_runtime_service_prepares_node_registry_and_reducers() -> None:
emit_event=lambda event: None,
)
workflow, registry, reducers, prepared_subgraphs = runtime.prepare_workflow_runtime(
workflow, registry, reducers, prepared_subgraphs, platform_context = runtime.prepare_workflow_runtime(
single_echo_plan("runtime_prepare", "demo.personal.echo_tool"),
deployment=None,
artifact=None,
@@ -108,6 +110,27 @@ def test_workflow_runtime_service_prepares_node_registry_and_reducers() -> None:
assert "demo.personal.echo_tool" in registry
assert isinstance(reducers, dict)
assert prepared_subgraphs == {}
assert platform_context.source_bindings == {}
assert isinstance(platform_context.platform_sources, set)
assert platform_context.read_resource_handler is None
def test_wfmcpservice_prepares_platform_context_with_resource_handler() -> None:
service = WfMcpService(
store=FileStore(local_temp_root() / "runtime_platform_context")
)
service.register_connection(
ConnectionConfig(id="demo.personal", server="demo", account="personal")
)
service.register_specs("demo.personal", echo_tool)
*_runtime, platform_context = service.workflow_runtime.prepare_workflow_runtime(
single_echo_plan("runtime_platform_context", "demo.personal.echo_tool"),
deployment=None,
artifact=None,
)
assert platform_context.read_resource_handler is not None
async def test_workflow_runtime_service_runs_plan_and_emits_events() -> None:
@@ -131,6 +154,73 @@ async def test_workflow_runtime_service_runs_plan_and_emits_events() -> None:
assert events[1].payload["status"] == "completed"
async def test_wf_source_read_resource_runs_through_platform_context() -> None:
service = WfMcpService(
store=FileStore(local_temp_root() / "runtime_source_resource")
)
service.register_connection(
ConnectionConfig(id="demo.personal", server="demo", account="personal")
)
service.register_adapter("demo", FakeAdapter())
await service.refresh_connection_catalog("demo.personal")
run = await service.workflow_runtime.run_workflow_from_plan(
raw_plan(
name="runtime_source_resource",
input_schema={"type": "object", "properties": {}},
state_schema={
"type": "object",
"properties": {"text": {"type": "string"}},
},
output_schema={
"type": "object",
"properties": {"text": {"type": "string"}},
"required": ["text"],
},
start="read",
nodes=[
{
"id": "read",
"type": "node",
"node": "wf.source.read_resource",
"input": [
{
"value": {
"kind": "source_resource_ref",
"logical_source": "drive",
"uri": "demo://docs/welcome",
},
"target": {"root": "local", "parts": ["ref"]},
},
{
"value": 7,
"target": {"root": "local", "parts": ["max_chars"]},
},
],
"output": [output_binding("text", "state.text")],
}
],
edges=[{"from": "read", "outcome": "ok", "to": END}],
output=[
{
"path": {"root": "state", "parts": ["text"]},
"target": {"root": "local", "parts": ["text"]},
}
],
),
{},
deployment=WorkflowDeployment(
id="runtime_source_resource.default",
artifact_id="runtime_source_resource",
artifact_version=1,
bindings={"drive": "demo.personal"},
),
)
assert run.status == RunStatus.COMPLETED
assert run.output == {"text": "Welcome"}
async def test_workflow_runtime_service_emits_failed_event_for_failed_run() -> None:
service = WfMcpService(store=FileStore(local_temp_root() / "runtime_failed_event"))