fix: opt draft storage into real callers
This commit is contained in:
+12
-3
@@ -22,12 +22,21 @@ class WorkflowStores:
|
||||
run_store: RunStore
|
||||
|
||||
|
||||
def file_workflow_stores(root: str | Path) -> WorkflowStores:
|
||||
"""Create process-local file-backed workflow stores under one root."""
|
||||
def file_workflow_stores(
|
||||
root: str | Path,
|
||||
*,
|
||||
drafts: bool = False,
|
||||
) -> WorkflowStores:
|
||||
"""Create file-backed workflow stores, opting into draft persistence.
|
||||
|
||||
Artifact and run stores are needed by every durable workflow server. Draft
|
||||
workspaces are a separate product surface, so avoid constructing their
|
||||
store (which creates its directory) unless a caller explicitly enables it.
|
||||
"""
|
||||
store_root = Path(root)
|
||||
return WorkflowStores(
|
||||
artifact_store=FileWorkflowArtifactStore(store_root),
|
||||
draft_workspace_store=FileDraftWorkspaceStore(store_root),
|
||||
draft_workspace_store=(FileDraftWorkspaceStore(store_root) if drafts else None),
|
||||
run_store=FileRunStore(store_root),
|
||||
)
|
||||
|
||||
|
||||
@@ -97,7 +97,9 @@ def build_workflow_server_from_workflow_config(
|
||||
"""Build the local server without importing the server runtime at CLI startup."""
|
||||
from wf_server.config import build_workflow_server_from_workflow_config as build
|
||||
|
||||
return build(config)
|
||||
# Local CLI exposes the full draft command group, so it is an explicit
|
||||
# draft-bearing composition even though the neutral server default is not.
|
||||
return build(config, drafts=True)
|
||||
|
||||
|
||||
def load_cli_context(
|
||||
@@ -150,7 +152,8 @@ def load_cli_context(
|
||||
return CliContext(
|
||||
config_path=resolved_config_path,
|
||||
service=service,
|
||||
handlers=WorkflowApi(context_from_service(service)),
|
||||
# Legacy MCP CLI commands include draft authoring operations.
|
||||
handlers=WorkflowApi(context_from_service(service), drafts=True),
|
||||
source_admin=WorkflowSourceAdminApi(context_from_service(service)),
|
||||
admin=WorkflowAdminApi(
|
||||
connections=service.connection_service,
|
||||
|
||||
@@ -163,7 +163,9 @@ def build_service_from_config(config: BrokerConfig) -> WfMcpService:
|
||||
"""Create a broker service with SDK adapters for configured connections."""
|
||||
runtime_factory = PersistentSessionFactory()
|
||||
store_roots = config.store_roots
|
||||
workflow_stores = file_workflow_stores(store_roots.workflow_root)
|
||||
# The broker's documented workflow/draft tools are a draft-bearing
|
||||
# composition, so opt into the otherwise disabled draft store explicitly.
|
||||
workflow_stores = file_workflow_stores(store_roots.workflow_root, drafts=True)
|
||||
# Keep FileStore as the compatibility facade on WfMcpService.store while
|
||||
# focused services receive role-specific stores.
|
||||
auth_store = FileAuthStore(store_roots.auth_root)
|
||||
|
||||
@@ -64,7 +64,8 @@ def workflow_server_from_service(
|
||||
raise ValueError("MCP-backed WorkflowServer requires workflow stores")
|
||||
|
||||
context = context_from_service(service)
|
||||
api: WorkflowApi = durable_workflow_api(context)
|
||||
# MCP's documented workflow server includes mutable draft operations.
|
||||
api: WorkflowApi = durable_workflow_api(context, drafts=True)
|
||||
source_diagnostics = SourceDiagnosticsProvider(
|
||||
connection_lookup=service.connections.get,
|
||||
auth_store=service.auth_store or service.store,
|
||||
|
||||
@@ -13,14 +13,16 @@ if TYPE_CHECKING:
|
||||
class WorkflowSurfaceHandlers(WorkflowApi):
|
||||
"""Compatibility wrapper for old wf_mcp.workflow_surface imports.
|
||||
|
||||
New code should construct `WorkflowApi(context_from_service(service))`
|
||||
New code should construct `WorkflowApi(context_from_service(service), drafts=True)`
|
||||
directly. This shim keeps tests and legacy broker artifact tools working
|
||||
for legacy callers.
|
||||
"""
|
||||
|
||||
def __init__(self, service: WfMcpService) -> None:
|
||||
self.service = service
|
||||
super().__init__(context_from_service(service))
|
||||
# This compatibility surface exposes the draft methods used by the
|
||||
# workflow-surface tests and legacy broker artifact tools.
|
||||
super().__init__(context_from_service(service), drafts=True)
|
||||
|
||||
|
||||
__all__ = ["WorkflowSurfaceHandlers"]
|
||||
|
||||
@@ -71,7 +71,9 @@ from .models import (
|
||||
|
||||
def register_workflow_tools(server: FastMCP[Any], service: WfMcpService) -> None:
|
||||
"""Register stable workflow tools on the public MCP server surface."""
|
||||
handlers = WorkflowApi(context_from_service(service))
|
||||
# This MCP surface registers the draft authoring tools below, so its API
|
||||
# composition must explicitly opt into the draft services.
|
||||
handlers = WorkflowApi(context_from_service(service), drafts=True)
|
||||
|
||||
@server.tool(
|
||||
name="wf.workflow.list_artifacts",
|
||||
|
||||
@@ -68,7 +68,11 @@ def serve(
|
||||
workflow_config = load_workflow_config(config)
|
||||
store = workflow_config.server.workflow_store
|
||||
if server is None and store_root is None:
|
||||
server = build_workflow_server_from_workflow_config(workflow_config)
|
||||
# The server CLI exposes the full draft RPC surface.
|
||||
server = build_workflow_server_from_workflow_config(
|
||||
workflow_config,
|
||||
drafts=True,
|
||||
)
|
||||
elif server is None:
|
||||
has_mcp_sources = any(
|
||||
getattr(source, "kind", None) == "mcp"
|
||||
@@ -101,9 +105,11 @@ def serve(
|
||||
raise typer.BadParameter(
|
||||
"--store-root is required when --config is not supplied"
|
||||
)
|
||||
server = build_local_static_workflow_server(resolved_store_root)
|
||||
# The standalone server CLI is the documented draft-capable RPC
|
||||
# endpoint; opt into its persistence explicitly at this boundary.
|
||||
server = build_local_static_workflow_server(resolved_store_root, drafts=True)
|
||||
|
||||
rpc_app = create_rpc_app(server, rpc_path=resolved_rpc_path)
|
||||
rpc_app = create_rpc_app(server, rpc_path=resolved_rpc_path, drafts=True)
|
||||
uvicorn.run(
|
||||
rpc_app,
|
||||
host=resolved_host or "127.0.0.1",
|
||||
|
||||
@@ -53,11 +53,15 @@ def _build_mcp_workflow_server_from_legacy_config(path: Path) -> WorkflowServer:
|
||||
|
||||
def build_workflow_server_from_workflow_config(
|
||||
config: WorkflowConfigFile,
|
||||
*,
|
||||
drafts: bool = False,
|
||||
) -> WorkflowServer:
|
||||
"""Build a WorkflowServer from neutral workflow config.
|
||||
|
||||
Local/static configs use built-in sources. Configs with ``kind: "mcp"``
|
||||
sources delegate to the MCP provider adapter.
|
||||
sources delegate to the MCP provider adapter. Draft persistence is opt-in
|
||||
for static composition; MCP broker composition owns its draft-bearing
|
||||
workflow surface.
|
||||
"""
|
||||
if _has_mcp_sources(config):
|
||||
return _build_mcp_workflow_server_from_workflow_config(config)
|
||||
@@ -68,6 +72,7 @@ def build_workflow_server_from_workflow_config(
|
||||
raise ValueError("wf-rpc-server currently requires filesystem store")
|
||||
return build_local_static_workflow_server(
|
||||
store.root,
|
||||
drafts=drafts,
|
||||
extra_sources=collect_static_sources(_static_source_providers(config)),
|
||||
)
|
||||
|
||||
|
||||
@@ -299,7 +299,7 @@ def build_local_static_workflow_server(
|
||||
) -> WorkflowServer:
|
||||
"""Build a durable local/static server, with drafts as an explicit opt-in."""
|
||||
config = WorkflowServerConfig(store_root=Path(root))
|
||||
stores = file_workflow_stores(config.store_root)
|
||||
stores = file_workflow_stores(config.store_root, drafts=drafts)
|
||||
events = InMemoryWorkflowEventRecorder()
|
||||
sources = builtin_sources()
|
||||
if extra_sources:
|
||||
|
||||
Reference in New Issue
Block a user