unofficially add wf.std as source

This commit is contained in:
lda
2026-05-09 20:34:22 +07:00 Verified
parent 47b337a9c3
commit 8dc149b12d
8 changed files with 63 additions and 3 deletions
+10 -2
View File
@@ -55,11 +55,19 @@ async def run_example() -> dict[str, object]:
"node": "fixture.personal.echo_tool", "node": "fixture.personal.echo_tool",
"in_map": {"input.text": "text"}, "in_map": {"input.text": "text"},
"out_map": {"echoed": "state.echoed"}, "out_map": {"echoed": "state.echoed"},
} },
{
"id": "raise_mcp_error",
"type": "node",
"node": "wf.std.runtime_error",
"in_map": {"input.text": "message"},
"out_map": {},
},
], ],
edges=[ edges=[
{"from": "echo", "outcome": "ok", "to": END}, {"from": "echo", "outcome": "ok", "to": END},
{"from": "echo", "outcome": "error", "to": END}, # workaround for now; i need wf_authoring.ops::runtime_error {"from": "echo", "outcome": "error", "to": "raise_mcp_error"},
{"from": "raise_mcp_error", "outcome": "ok", "to": END},
], ],
) )
+2
View File
@@ -101,6 +101,8 @@ def node(
description=description or fn.description, description=description or fn.description,
is_async=is_async if is_async is not None else fn.is_async, is_async=is_async if is_async is not None else fn.is_async,
accepts_context=fn.accepts_context, accepts_context=fn.accepts_context,
input_schema_contract=fn.input_schema_contract,
output_schema_contract=fn.output_schema_contract,
) )
inferred_input_model: type[BaseModel] | None = input_model inferred_input_model: type[BaseModel] | None = input_model
+2
View File
@@ -61,7 +61,9 @@ class NodeSpec(Generic[InputT, OutputT]):
is_async: bool = False is_async: bool = False
accepts_context: bool = True accepts_context: bool = True
input_schema_contract: dict[str, Any] | None = None input_schema_contract: dict[str, Any] | None = None
"enforced schema, if None use input_model"
output_schema_contract: dict[str, Any] | None = None output_schema_contract: dict[str, Any] | None = None
"enforced schema, if None use output_model"
def __call__( def __call__(
self, self,
+23
View File
@@ -0,0 +1,23 @@
from __future__ import annotations
from typing import Any
from wf_authoring import NodeSpec, node, runtime_error
from .specs import qualify_spec
BUILTIN_CONNECTION_ID = "wf.std"
"""Internal source id for workflow standard-library node specs."""
def builtin_specs() -> dict[str, NodeSpec[Any, Any]]:
"""Return built-in NodeSpecs available to raw broker workflow plans."""
specs = [
node(
runtime_error,
name="runtime_error",
description="Fail the current workflow branch with a runtime error.",
)
]
qualified_specs = [qualify_spec(BUILTIN_CONNECTION_ID, spec) for spec in specs]
return {spec.name: spec for spec in qualified_specs}
+7
View File
@@ -23,6 +23,7 @@ from ..catalog import CombinedCatalog, snapshot_from_specs
from ..discovery import discover_connection_capabilities, specs_from_discovered_tools from ..discovery import discover_connection_capabilities, specs_from_discovered_tools
from ..events import McpEvent, make_event from ..events import McpEvent, make_event
from .adapters import require_adapter from .adapters import require_adapter
from .builtins import BUILTIN_CONNECTION_ID, builtin_specs
from .specs import get_qualified_spec, qualify_spec from .specs import get_qualified_spec, qualify_spec
@@ -36,6 +37,12 @@ class WfMcpService:
default_factory=dict default_factory=dict
) )
events: list[McpEvent] = field(default_factory=list) events: list[McpEvent] = field(default_factory=list)
include_builtin_specs: bool = True
def __post_init__(self) -> None:
"""Install broker-local standard-library specs when enabled."""
if self.include_builtin_specs:
self.specs_by_connection.setdefault(BUILTIN_CONNECTION_ID, builtin_specs())
def register_connection(self, connection: ConnectionConfig) -> None: def register_connection(self, connection: ConnectionConfig) -> None:
parse_connection_id(connection.id) parse_connection_id(connection.id)
+2
View File
@@ -8,9 +8,11 @@ from pydantic import Field
server = FastMCP("echo-fixture") server = FastMCP("echo-fixture")
class EchoToolResult(TypedDict): class EchoToolResult(TypedDict):
echoed: str echoed: str
@server.tool(title="Echo tool") @server.tool(title="Echo tool")
async def echo_tool( async def echo_tool(
text: Annotated[str, Field(description="Text to echo")], text: Annotated[str, Field(description="Text to echo")],
+1 -1
View File
@@ -67,7 +67,7 @@ class Context(TypedDict): # dataclass support? no. i mean langgraph doesnt.
### what about us? how should we handle context? ### what about us? how should we handle context?
# #
# in the future if wed like, we could handle context. This could be useful for lda.chat! # in the future if wed like, we could handle context. This could be useful for lda.chat!
# i want lda.chat to be/have a meta-agent. So i could spin up ideas! a # i want lda.chat to be/have a meta-agent. So i could spin up ideas! a
class ContextInput(BaseModel): class ContextInput(BaseModel):
+16
View File
@@ -34,6 +34,22 @@ def test_service_builds_namespaced_catalog() -> None:
] ]
def test_service_installs_builtin_stdlib_specs_by_default() -> None:
service = WfMcpService(store=FileStore(local_temp_root() / "builtin_store"))
assert "wf.std" in service.specs_by_connection
assert "wf.std.runtime_error" in service.specs_by_connection["wf.std"]
def test_service_can_disable_builtin_stdlib_specs() -> None:
service = WfMcpService(
store=FileStore(local_temp_root() / "no_builtin_store"),
include_builtin_specs=False,
)
assert "wf.std" not in service.specs_by_connection
def test_service_compiles_and_runs_raw_plan() -> None: def test_service_compiles_and_runs_raw_plan() -> None:
service = WfMcpService(store=FileStore(local_temp_root() / "run_store")) service = WfMcpService(store=FileStore(local_temp_root() / "run_store"))
service.register_connection( service.register_connection(