Skip to content

Commit 6b62b16

Browse files
committed
hotfix: merge activity parser fix into main for v0.30.0
2 parents 86dbc3a + 37008fc commit 6b62b16

2 files changed

Lines changed: 23 additions & 7 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ Minor release adding a unified Activity Log — a single page aggregating execut
1919
- **Nav:** new sidebar item "Activity" (`Atividade` pt-BR / `Actividad` es) under the operations group. `View all →` on the Overview Routines card now points to `/activity` for a unified journey.
2020
- **Data sources:** reuses existing backend endpoints — `GET /api/routines/logs`, `GET /api/heartbeats/{id}/runs`, `GET /api/triggers/{id}`. Client-side aggregation (N+1 fetches via `Promise.all`) — acceptable for v1 volume; server-side aggregated endpoint can come later if needed.
2121

22+
### Fixed (same release)
23+
24+
- **Activity parser — real routine log shape** — initial parser was looking for `log.name` / `log.routine_name` / `log.status` / `log.exit_code`, which don't exist in `ADWs/logs/YYYY-MM-DD.jsonl`. Real shape is `{ timestamp, run, prompt, returncode, duration_seconds, input_tokens, output_tokens, cost_usd }`. Parser now reads `run` as the routine name (so rows show `good-morning`, `end-of-day`, etc. instead of `Unknown Routine`), derives status from `returncode`, and surfaces `cost_usd` / token counts / prompt preview in the drawer.
25+
2226
### Known limitations (v1)
2327

2428
- `/api/routines/logs` only accepts `?date=`, so the period filter (7d / 30d / All) affects heartbeats and triggers only — routines always show today. The routine log endpoint will need `from`/`to` params to honor longer periods; deferred to a follow-up.

dashboard/frontend/src/pages/Activity.tsx

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -360,17 +360,29 @@ export default function ActivityPage() {
360360
const today = new Date().toISOString().slice(0, 10)
361361
const logs: any[] = await api.get(`/routines/logs?date=${today}`)
362362
for (const log of Array.isArray(logs) ? logs : []) {
363+
// Real shape (ADWs/logs/YYYY-MM-DD.jsonl lines):
364+
// { timestamp, run, prompt, returncode, duration_seconds,
365+
// stdout_lines, stderr_lines, input_tokens, output_tokens, cost_usd }
366+
const name = log.run || log.routine_name || log.name || log.script || 'Routine'
367+
const rc = log.returncode ?? log.exit_code
368+
const status = log.status || (rc === 0 ? 'success' : rc != null ? 'error' : 'success')
369+
const ts = log.timestamp || log.started_at || ''
370+
const durMs = log.duration_ms ?? (log.duration_seconds != null ? log.duration_seconds * 1000 : null)
363371
results.push({
364-
id: `routine-${log.routine_name || log.name || 'unknown'}-${log.started_at || log.timestamp || Date.now()}`,
372+
id: `routine-${name}-${ts || Date.now()}`,
365373
type: 'routine',
366-
name: log.routine_name || log.name || log.script || 'Unknown Routine',
367-
status: log.status || (log.exit_code === 0 ? 'success' : 'error'),
368-
started_at: log.started_at || log.timestamp || '',
374+
name,
375+
status,
376+
started_at: ts,
369377
ended_at: log.ended_at || log.completed_at || null,
370-
duration_ms: log.duration_ms ?? (log.duration_seconds != null ? log.duration_seconds * 1000 : null),
378+
duration_ms: durMs,
371379
triggered_by: log.triggered_by || 'schedule',
372-
error: log.error || log.stderr || null,
373-
routine_name: log.routine_name || log.name || null,
380+
error: log.error || log.stderr || (rc != null && rc !== 0 ? `Exit code ${rc}` : null),
381+
routine_name: name,
382+
cost_usd: log.cost_usd ?? null,
383+
tokens_in: log.input_tokens ?? null,
384+
tokens_out: log.output_tokens ?? null,
385+
prompt_preview: log.prompt ? String(log.prompt).slice(0, 200) : null,
374386
})
375387
}
376388
} catch { /* routines may have no logs */ }

0 commit comments

Comments
 (0)