runs and deployment: first slice
uhh
This commit is contained in:
+2
-3
@@ -15,6 +15,7 @@ app = typer.Typer(
|
||||
|
||||
@app.callback()
|
||||
def root(
|
||||
ctx: typer.Context,
|
||||
config: Annotated[
|
||||
str,
|
||||
typer.Option(
|
||||
@@ -24,9 +25,7 @@ def root(
|
||||
] = "wf_mcp.config.json",
|
||||
) -> None:
|
||||
"""Run workflow platform commands."""
|
||||
# The root callback owns global options only. Command modules should load
|
||||
# context explicitly so tests can call command functions without Typer state.
|
||||
_ = config
|
||||
ctx.obj = {"config_path": config}
|
||||
|
||||
|
||||
app.add_typer(caps.app, name="cap")
|
||||
|
||||
@@ -1,9 +1,38 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from typing import Annotated
|
||||
|
||||
import typer
|
||||
|
||||
from wf_cli.context import config_path_from_context, load_cli_context
|
||||
from wf_cli.io import emit_json
|
||||
|
||||
app = typer.Typer(
|
||||
name="deploy",
|
||||
help="Save, inspect, validate, and delete workflow deployments.",
|
||||
no_args_is_help=True,
|
||||
)
|
||||
|
||||
|
||||
@app.command("validate")
|
||||
def validate_deployment(
|
||||
ctx: typer.Context,
|
||||
deployment_id: Annotated[str, typer.Argument(help="Deployment id to validate.")],
|
||||
live: Annotated[
|
||||
bool,
|
||||
typer.Option(
|
||||
"--live",
|
||||
help="Also perform opt-in upstream liveness checks.",
|
||||
),
|
||||
] = False,
|
||||
) -> None:
|
||||
"""Validate one saved workflow deployment."""
|
||||
context = load_cli_context(config_path_from_context(ctx))
|
||||
payload = asyncio.run(
|
||||
context.handlers.validate_deployment(
|
||||
deployment_id=deployment_id,
|
||||
live_check=live,
|
||||
)
|
||||
)
|
||||
emit_json(payload)
|
||||
|
||||
@@ -1,9 +1,101 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from pathlib import Path
|
||||
from typing import Annotated
|
||||
|
||||
import typer
|
||||
|
||||
from wf_cli.context import config_path_from_context, load_cli_context
|
||||
from wf_cli.io import CliInputError, emit_json, parse_json_input
|
||||
from wf_mcp.workflow_surface import TraceRange
|
||||
|
||||
app = typer.Typer(
|
||||
name="run",
|
||||
help="Run workflow deployments and inspect durable runs.",
|
||||
no_args_is_help=True,
|
||||
)
|
||||
|
||||
|
||||
@app.command("start")
|
||||
def start_run(
|
||||
ctx: typer.Context,
|
||||
deployment_id: Annotated[str, typer.Argument(help="Deployment id to run.")],
|
||||
input_json: Annotated[
|
||||
str | None,
|
||||
typer.Option("--input", help="Workflow input JSON object."),
|
||||
] = None,
|
||||
input_file: Annotated[
|
||||
Path | None,
|
||||
typer.Option("--input-file", help="Path to workflow input JSON object."),
|
||||
] = None,
|
||||
trace_from: Annotated[
|
||||
int | None,
|
||||
typer.Option("--trace-from", min=0, help="Optional trace slice start."),
|
||||
] = None,
|
||||
trace_limit: Annotated[
|
||||
int | None,
|
||||
typer.Option(
|
||||
"--trace-limit", min=1, max=100, help="Optional trace slice limit."
|
||||
),
|
||||
] = None,
|
||||
) -> None:
|
||||
"""Start one workflow deployment."""
|
||||
try:
|
||||
workflow_input = parse_json_input(input_json=input_json, input_file=input_file)
|
||||
except CliInputError as exc:
|
||||
raise typer.BadParameter(str(exc)) from exc
|
||||
context = load_cli_context(config_path_from_context(ctx))
|
||||
trace_range = _optional_trace_range(start=trace_from, limit=trace_limit)
|
||||
payload = asyncio.run(
|
||||
context.handlers.run_deployment(
|
||||
deployment_id=deployment_id,
|
||||
workflow_input=workflow_input,
|
||||
trace_range=trace_range,
|
||||
)
|
||||
)
|
||||
emit_json(payload)
|
||||
|
||||
|
||||
@app.command("inspect")
|
||||
def inspect_run(
|
||||
ctx: typer.Context,
|
||||
run_id: Annotated[str, typer.Argument(help="Durable run id to inspect.")],
|
||||
) -> None:
|
||||
"""Inspect a durable run without trace entries."""
|
||||
context = load_cli_context(config_path_from_context(ctx))
|
||||
emit_json(asyncio.run(context.handlers.inspect_run(run_id=run_id)))
|
||||
|
||||
|
||||
@app.command("trace")
|
||||
def trace_run(
|
||||
ctx: typer.Context,
|
||||
run_id: Annotated[str, typer.Argument(help="Durable run id to trace.")],
|
||||
trace_from: Annotated[
|
||||
int,
|
||||
typer.Option("--from", min=0, help="Zero-based trace start offset."),
|
||||
] = 0,
|
||||
limit: Annotated[
|
||||
int,
|
||||
typer.Option("--limit", min=1, max=100, help="Maximum trace entries."),
|
||||
] = 25,
|
||||
) -> None:
|
||||
"""Read a bounded debug trace slice."""
|
||||
context = load_cli_context(config_path_from_context(ctx))
|
||||
payload = asyncio.run(
|
||||
context.handlers.read_run_trace(
|
||||
run_id=run_id,
|
||||
trace_range=TraceRange(start=trace_from, limit=limit),
|
||||
)
|
||||
)
|
||||
emit_json(payload)
|
||||
|
||||
|
||||
def _optional_trace_range(*, start: int | None, limit: int | None) -> TraceRange | None:
|
||||
"""Build a trace range only when the caller requested trace detail."""
|
||||
if start is None and limit is None:
|
||||
return None
|
||||
return TraceRange(
|
||||
start=start if start is not None else 0,
|
||||
limit=limit if limit is not None else 25,
|
||||
)
|
||||
|
||||
@@ -3,6 +3,8 @@ from __future__ import annotations
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
|
||||
import typer
|
||||
|
||||
from wf_mcp.broker import build_service_from_config, load_broker_config
|
||||
from wf_mcp.broker.service import WfMcpService
|
||||
from wf_mcp.workflow_surface import WorkflowSurfaceHandlers
|
||||
@@ -23,6 +25,13 @@ class CliContext:
|
||||
handlers: WorkflowSurfaceHandlers
|
||||
|
||||
|
||||
def config_path_from_context(ctx: typer.Context) -> str:
|
||||
"""Return the root --config path captured by the Typer callback."""
|
||||
obj = ctx.obj if isinstance(ctx.obj, dict) else {}
|
||||
value = obj.get("config_path", "wf_mcp.config.json")
|
||||
return value if isinstance(value, str) else "wf_mcp.config.json"
|
||||
|
||||
|
||||
def load_cli_context(config_path: str | Path) -> CliContext:
|
||||
"""Load config and build workflow-surface handlers for CLI commands."""
|
||||
resolved_config_path = Path(config_path)
|
||||
|
||||
Reference in New Issue
Block a user