feat(telemetry): WORKING ON NOW shows the mission an agent is on
The last of the three declared-but-never-emitted event types. `agent.task.update` had no producer anywhere in the backend, so the card read "idle — no active task" for an agent that was mid-turn. Derived rather than newly instrumented: an agent is working on its crew's RUNNING mission, and that mission's phases are the steps (completed/skipped → done, running/evaluating → active, else pending). Nothing is emitted for an agent with no running mission, so "idle" stays truthful rather than freezing on a stale last-known task. Verified on a live mission: 116 agent.task.update events observed on /api/world/live, carrying the mission title and phase steps, with the state advancing pending → active as the phase started. That closes the set. Of the seven cards in the command centre, five were dark: three had no emitter at all and two read a table the mission path never wrote. DOORS and LOOPS were correctly wired the whole time and were reporting an honest zero. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5
parent
bf40d10064
commit
ba9d7aa185
@@ -1164,6 +1164,69 @@ pub async fn world_live(
|
||||
}
|
||||
}
|
||||
|
||||
// WORKING ON NOW — the third card that was declared, listened for,
|
||||
// and never emitted. `agent.task.update` has no producer anywhere in
|
||||
// the backend, so the card read "idle" for an agent mid-turn.
|
||||
//
|
||||
// Derived rather than newly instrumented: an agent is working on its
|
||||
// crew's RUNNING mission, and that mission's phases are the steps.
|
||||
// Nothing is emitted for an agent with no running mission, so "idle"
|
||||
// stays truthful instead of becoming a stale last-known task.
|
||||
{
|
||||
let rows = sqlx::query(
|
||||
"SELECT tm.claw_id AS agent_id, m.id AS mission_id, m.title,
|
||||
p.kind, p.status, p.order_idx
|
||||
FROM team_members tm
|
||||
JOIN mission_teams mt ON mt.team_id = tm.team_id
|
||||
JOIN missions m ON m.id = mt.mission_id
|
||||
JOIN mission_phases p ON p.mission_id = m.id
|
||||
WHERE m.workspace_id = $1 AND m.status = 'running'
|
||||
ORDER BY tm.claw_id, p.order_idx",
|
||||
)
|
||||
.bind(ws.as_uuid())
|
||||
.fetch_all(&pool)
|
||||
.await
|
||||
.unwrap_or_default();
|
||||
let mut cur: Option<(uuid::Uuid, uuid::Uuid, String)> = None;
|
||||
let mut steps: Vec<serde_json::Value> = Vec::new();
|
||||
let mut flush = |cur: &Option<(uuid::Uuid, uuid::Uuid, String)>,
|
||||
steps: &Vec<serde_json::Value>|
|
||||
-> Option<serde_json::Value> {
|
||||
let (agent_id, mission_id, title) = cur.as_ref()?;
|
||||
Some(json!({
|
||||
"agentId": agent_id.to_string(),
|
||||
"taskId": mission_id.to_string(),
|
||||
"title": title,
|
||||
"steps": steps,
|
||||
}))
|
||||
};
|
||||
for r in &rows {
|
||||
let agent_id: uuid::Uuid = r.get("agent_id");
|
||||
let mission_id: uuid::Uuid = r.get("mission_id");
|
||||
let title: String = r.get("title");
|
||||
if cur.as_ref().map(|c| c.0) != Some(agent_id) {
|
||||
if let Some(v) = flush(&cur, &steps) {
|
||||
yield sse("agent.task.update", v);
|
||||
}
|
||||
steps = Vec::new();
|
||||
cur = Some((agent_id, mission_id, title));
|
||||
}
|
||||
let status: String = r.get("status");
|
||||
let kind: String = r.get("kind");
|
||||
steps.push(json!({
|
||||
"label": kind,
|
||||
"state": match status.as_str() {
|
||||
"completed" | "skipped" => "done",
|
||||
"running" | "evaluating" => "active",
|
||||
_ => "pending",
|
||||
},
|
||||
}));
|
||||
}
|
||||
if let Some(v) = flush(&cur, &steps) {
|
||||
yield sse("agent.task.update", v);
|
||||
}
|
||||
}
|
||||
|
||||
// Workspace-wide telemetry (top-bar pills / Observe system strip).
|
||||
yield sse(
|
||||
"telemetry",
|
||||
|
||||
Reference in New Issue
Block a user