[aidan] fix/run-status: sync ongoing runs and heal stuck/interrupted runs

This commit is contained in:
abccodes
2026-06-23 00:02:52 -07:00
parent 5bbca981bd
commit 9da38ef3e5
3 changed files with 32 additions and 0 deletions
+13
View File
@@ -215,6 +215,19 @@ async def execute(
"last_run_id": run.id,
})
# Announce the run as running the instant it claims execution, not at the
# first step. Without this a run that fails fast (e.g. no runnable steps) or
# hasn't streamed yet never hits the Home "Ongoing runs" list, so a batch of
# missed re-runs only ever surfaced whichever one reached its first step.
try:
from backend.apps.agents.core.ws_manager import ws_manager as _wsm_start
await _wsm_start.broadcast_global("workflow:run", {
"workflow_id": wf.id,
"run": run.model_dump(mode="json"),
})
except Exception:
pass
session = None
try:
steps = [s for s in wf.steps if s.enabled and s.text and s.text.strip()]
+8
View File
@@ -362,6 +362,14 @@ def _mark_stuck_runs_failed() -> None:
error="OpenSwarm closed before this run finished.",
finished_at=now,
)
# The run row is fixed, but the workflow still summarizes this
# dead run as 'running' (that's what the detail header reads), so
# heal the summary too when this was the latest run.
if wf.last_run_id == r.id and wf.last_run_status == "running":
executor._persist_run_fields(wf, {
"last_run_status": "failure",
"last_run_at": now,
})
def record_skipped(wf: Workflow, scheduled_for: datetime, error: str) -> WorkflowRun:
@@ -230,6 +230,17 @@ function mergeRunIntoState(state: State, r: WorkflowRun) {
wf.last_run_status = r.status === 'skipped' ? wf.last_run_status : (r.status as Workflow['last_run_status']);
wf.last_run_id = r.id;
}
// Keep the live "Ongoing runs" list in sync off the WS stream: a run that's no
// longer running drops out of `active`, a freshly-running one joins. Without
// this, `active` only refreshed on the one-shot mount fetch, so finished runs
// lingered as "Working…" while the monitor already showed them done.
const activeIdx = state.active.findIndex((a) => a.run_id === r.id);
if (r.status === 'running') {
const entry: ActiveRun = { workflow_id: r.workflow_id, run_id: r.id, title: wf?.title || '', started_at: r.started_at };
if (activeIdx >= 0) state.active[activeIdx] = entry; else state.active.unshift(entry);
} else if (activeIdx >= 0) {
state.active.splice(activeIdx, 1);
}
// Auto-flip the card view on run state transitions so the user sees
// Running while it streams, Completed on success, Failed on failure.
// Only nudge from views that the user hasn't actively navigated away