Expand description
GET /v1/tasks/:id/runs/:run/steps* (the metadata + content debug
plane over a Run’s step OUTPUT — McpQueryAdapter, a server-side
mlua_swarm::core::projection::ProjectionAdapter impl reading through
the Data-plane OutputStore with a persisted RunRecord.result_ref
fallback). See the module doc for how this relates to
operator_ws::session’s in-flight FileProjectionAdapter hook and
worker’s Worker-axis context.steps pointer assembly.
McpQueryAdapter — server-side [ProjectionAdapter], and the REST
hierarchy that serves a Run’s step OUTPUT as metadata + content
(projection-adapter ST5’s HTTP debug plane — replaces the ST2/ST4
GET /v1/tasks/:id/ctx single-value endpoint / ProjectionResponse).
§Two consumers, two roles (ST5)
- Worker axis (
crates/mlua-swarm-server/src/worker.rs’sGET /v1/worker/prompthandler) — the primary supply path. A worker’s fetch payload carriescontext.steps: Vec<StepPointer>, aContextPolicy.steps-filtered pointer list assembled automatically at fetch time; no separate tool call needed. - HTTP debug plane (this module’s
GET /v1/tasks/:id/runs/:run/steps*routes) — the content the above pointers’content_urladdresses, plus an unfiltered metadata/content view for operators / humans debugging a run.
Both consumers share McpQueryAdapter::list_steps’s enumeration:
every distinct step_ref name in RunRecord.step_entries, resolved
through the Data-plane OutputStore (in-flight-safe — see below),
union RunRecord.result_ref’s top-level object keys (the
finalized-Run fallback) — a name present in both wins on the Data-plane
side (same rule McpQueryAdapter::resolve_run’s single-key sibling,
McpQueryAdapter::resolve_async, already applies). Name-namespace
unification (Data-plane producer names vs. flow.ir ctx-path segments)
is tracked separately (see the KNOWN LIMITATION note below); this module
does not resolve it.
§Architecture (subtask-4 rework, carried into ST5)
McpQueryAdapter reads through two backings, tried in order:
- Data-plane, in-flight-safe (subtask-4’s whole reason for being):
when
key.stepisSome(producer_agent)and no explicitrun_idpins an older Run,McpQueryAdapter::resolve_asyncfirst triesOutputStore::get_latest_by_name(producer_agent)— the same storeEngine::submit_output’s submit-time projection sink dual-writes into (seemlua_swarm::core::engine::Engine::submit_output’s doc). A hit here can be a not-yet-finalized Run’s already-submitted step — the in-flight case this rework exists for. - Persisted
RunRecord.result_reffallback (the pre-rework path, unchanged): used whenever (1) is skipped (key.stepisNone, or an explicitrun_idwas given) or comes back empty (no Data-plane record under that producer name yet — e.g. a Run that predates the engine having anOutputStorewired, orkey.stepnames a flow.ir ctx-path segment rather than an agent ref — see the KNOWN LIMITATION note below).
Unlike crate::operator_ws::session‘s spawn-time
mlua_swarm::core::projection::FileProjectionAdapter hook (which
materializes the spawning agent’s own AgentContextView), this
adapter’s Data-plane path serves prior steps’ submitted OUTPUT —
the pull-supply counterpart to Engine’s submit-time file sink.
§KNOWN LIMITATION
OutputStore::get_latest_by_name is producer-name-scoped, not
Run-scoped (see mlua_swarm::store::output’s module doc) — it returns
the single newest Final submitted anywhere under that producer name,
across every Run / Task. This adapter narrows the blast radius by only
taking this path when an explicit run_id did NOT pin an older Run
(an explicit pin always uses the Run-scoped result_ref fallback
instead), but two concurrent Runs whose flow.ir happens to dispatch
an agent of the identical name can still race each other on this path.
This is an accepted, pre-existing characteristic of the Data-plane
store (not a new race introduced here) — see
mlua_swarm::store::output::OutputStore::get_latest_by_name’s doc.
[ProjectionAdapter::fetch] is a synchronous trait method, but this
adapter’s backing stores are async. McpQueryAdapter::resolve_async
is the real, native-async implementation; [step_content] (the
content-plane HTTP handler) calls McpQueryAdapter::list_steps
directly. [ProjectionAdapter::fetch] instead bridges to
McpQueryAdapter::resolve_async via tokio::task::block_in_place +
Handle::block_on purely for trait conformance (dependency inversion —
this adapter implements the same core::projection::ProjectionAdapter
trait mlua_swarm::core::projection::FileProjectionAdapter does, so a
caller holding a dyn ProjectionAdapter can use either
polymorphically); the hot HTTP path never takes that bridge.
Structs§
- McpQuery
Adapter - Server-side
ProjectionAdapterbacked by anOutputStore(in-flight-safe, subtask-4) with aRunStore-backedresult_reffallback (see the module doc for the full narrative). - Step
List - Response body for
GET /v1/tasks/:id/runs/:run/steps. - Step
Path Query - Query params shared by the metadata and content routes: narrows a
single step’s value via
$.a.bdot-path form (the leading$.is optional) — same syntaxmlua_swarm::core::projection::ProjectionKeyalready establishes. - Step
Summary - One step’s metadata (operator / debug plane) —
GET /v1/tasks/:id/runs/:run/steps/:step, and each entry ofStepList::steps.
Enums§
- Projection
Source - Which backing produced a
StepSummary/ a Worker-axisStepPointer— Data-plane wins a name collision (module doc’s “Architecture” section).
Functions§
- step_
content GET /v1/tasks/:id/runs/:run/steps/:step/content?path=$.a.b— the raw body: full bytes, no envelope, no Range support.Content-TypeandETagfollowStepSummary::content_type/StepSummary::sha256’s same rules (module doc).- step_
get GET /v1/tasks/:id/runs/:run/steps/:step?path=$.a.b— one step’s metadata, optionally narrowed.- steps_
list GET /v1/tasks/:id/runs/:run/steps— every step visible for the addressed Run, unfiltered (see the module doc’s role split).