Files
lda-wf/src/wf_transport_rpc_http/app.py
T

70 lines
2.4 KiB
Python

"""JSON-RPC application composition.
Return annotations stay eagerly evaluated because fastapi-jsonrpc captures them
while registering nested handlers for response validation and OpenRPC output.
"""
import fastapi_jsonrpc as jsonrpc
from wf_api.models import HealthResult
from wf_server import WorkflowServer
from .errors import WorkflowRpcError
from .methods.admin import register_methods as register_admin_methods
from .methods.artifacts import register_methods as register_artifact_methods
from .methods.capabilities import (
register_methods as register_capability_methods,
)
from .methods.deployments import register_methods as register_deployment_methods
from .methods.drafts import register_methods as register_draft_methods
from .methods.runs import register_methods as register_run_methods
from .methods.source_registry import (
register_methods as register_source_registry_methods,
)
from .methods.sources import register_methods as register_source_methods
def create_rpc_app(
server: WorkflowServer,
*,
rpc_path: str = "/rpc",
drafts: bool = False,
) -> jsonrpc.API:
"""Build a JSON-RPC HTTP app over an existing WorkflowServer.
Transport code owns only JSON-RPC envelope handling. Workflow semantics stay
behind server.api, so this package remains swappable with WebSocket/MCP
transports later.
"""
if not rpc_path.startswith("/"):
raise ValueError("rpc_path must start with '/'")
app = jsonrpc.API()
entrypoint = jsonrpc.Entrypoint(rpc_path)
@app.get("/healthz")
async def healthz() -> dict[str, str]:
return {"status": "ok"}
@entrypoint.method(name="workflow.health", errors=[WorkflowRpcError])
async def workflow_health() -> HealthResult:
return {
"status": "ok",
"store_root": str(server.config.store_root),
}
register_capability_methods(entrypoint, server)
if drafts:
if not server.api.drafts_enabled:
raise ValueError("cannot enable draft RPC methods on a draft-disabled API")
register_draft_methods(entrypoint, server)
register_artifact_methods(entrypoint, server)
register_deployment_methods(entrypoint, server)
register_run_methods(entrypoint, server)
register_source_methods(entrypoint, server)
register_source_registry_methods(entrypoint, server)
register_admin_methods(entrypoint, server)
app.bind_entrypoint(entrypoint)
return app