Skip to main content

Module tasks

Module tasks 

Source
Expand description

HTTP surface for the Task/Run persistence axis (issue #13 ID hierarchy; GET /v1/tasks, GET /v1/tasks/:id, POST /v1/tasks/:id/runs, GET /v1/runs/:id). POST /v1/tasks itself stays in this module (it is the entry point tasks_start shares with the flow-eval path) — see the tasks module doc for the split rationale. HTTP surface for the Task/Run persistence axis (issue #13 ID-hierarchy reconciliation: Blueprint → Task → Run → Step → Attempt).

  • GET /v1/tasks — list every persisted TaskRecord, newest first.
  • GET /v1/tasks/:id — a TaskRecord plus every RunRecord kicked from it.
  • POST /v1/tasks/:id/runs — re-kick an existing Task: mints a fresh RunId, re-resolves the stored blueprint_ref (refreshing Blueprint.default_init_ctx exactly like original launch time — issue #19 ST4), 3-layer-merges it with TaskRecord.input_ctx and an optional RunKickRequest body’s init_ctx_override (see [merge_init_ctx_3layer]), dispatches through TaskApplication::handle_with_run, and returns the new {task_id, run_id} pair. A body-less request (or one that omits both fields) preserves the pre-#19 rekick behavior byte-for-byte.
  • GET /v1/runs/:id — a single RunRecord (step_entries trace included).
  • POST /v1/runs/:id/resume — resume an Interrupted Run under the SAME run_id (replay cursor + stored launch-input snapshot).
  • POST /v1/runs/:id/rerun-from — GH #71 Layer A. Rerun a terminal Run (Done / Failed / Interrupted) from a caller-specified step under the SAME run_id; physically truncates the replay log at the cut point so re-dispatch does not collide with the pre-rerun rows. See [run_rerun_from] for the full contract + Known Limitations.

POST /v1/tasks itself (the flow-eval entry point, tasks_start / run_flow_form) stays in crate::lib — it is the pre-existing Operator-inject-aware dispatch path this module’s handlers re-kick through, not a new one. This module owns the read/list/re-kick surface plus the [finalize_run] persistence helper both paths share.

Authorization follows the same convention as the existing POST /v1/tasks entry: no Authorization header is required (the route is open), and the only Operator-session correlation available is the request-body-level operator_sid (see crate::TaskLaunchRequest doc) — this module invents no new auth mechanism.

Structs§

RunKickRequest
Request body for POST /v1/tasks/:id/runs (issue #19 ST4) — every field is optional, and the body itself is optional (see task_rekick’s Option<Json<Self>> parameter); a caller that sends no body, or {}, or omits a field gets exactly today’s rekick behavior for that layer.
RunKickResponse
Response body for POST /v1/tasks/:id/runs.
RunRerunFromRequest
Request body for POST /v1/runs/:id/rerun-from (GH #71 Layer A).
RunRerunFromResponse
Response body for POST /v1/runs/:id/rerun-from (GH #71 Layer A).
RunResumeResponse
Response body for POST /v1/runs/:id/resume.
TaskDetailResponse
Response body for GET /v1/tasks/:id.
TasksListQuery
Query params for GET /v1/tasks.

Functions§

run_get
GET /v1/runs/:id. Returns a single RunRecord (its step_entries trace included).
run_rerun_from
POST /v1/runs/:id/rerun-from — GH #71 Layer A. Re-executes a specific step (and every downstream step) of a terminal Run under the SAME run_id. Mirrors run_resume, with two deltas: it accepts any terminal status (Done / Failed / Interrupted) rather than only Interrupted, and it physically truncates the replay log at the cut point (via crate::AppState::replay_store’s delete_from) so that re-dispatch’s append does not collide with the pre-rerun row and so list_by_run reflects the rerun’s real history rather than the pre-rerun ghost.
run_resume
POST /v1/runs/:id/resume. Resumes an Interrupted Run under the SAME run_id (no new RunId is minted): the stored launch-input snapshot (RunRecord.input_json) is rebuilt into a TaskApplicationInput, a ReplayCursor is built from the Run’s logged step snapshots (ReplayStore::list_by_run), and the flow is re-dispatched with both wired into a fresh RunContext. On dispatch the engine’s replay path returns each already-completed step’s stored value verbatim (cursor hit, no Adapter spawn) and dispatches only the steps that never finished — reconstructing the same final Ctx a restart-free run would have reached.
task_get
GET /v1/tasks/:id. Returns the TaskRecord plus every RunRecord kicked from it (RunStore::list_by_task, oldest kick first).
task_rekick
POST /v1/tasks/:id/runs. Re-kicks an existing Task: reads its stored blueprint_ref, re-resolves it through [TaskApplication::resolve] (issue #19 ST4 — refreshes Blueprint.default_init_ctx exactly like original launch time, rather than replaying a launch-time-only snapshot), 3-layer-merges {bp default, TaskRecord.input_ctx, an optional per-Run override} via merge_init_ctx_3layer, resolves the Task-level canonical fields (RunKickRequest.task_input_override, falling back to TaskRecord.task_input_spec), mints a fresh RunId, dispatches through TaskApplication::handle_with_run (the unadorned Operator-default path — no per-request Operator override support here, unlike POST /v1/tasks; the stored Task carries no such preferences) plus a freshly-built RunContext (issue #13 run_id propagation, so this kick’s steps get their own step_entries trace), and persists the outcome via [finalize_run].
tasks_list
GET /v1/tasks?limit=N. Lists every persisted TaskRecord, newest first.