feat: show live activity line on delegated task cards - #1873
Conversation
Fast-session task cards were static while a task ran (title + Working). Surface the latest meaningful assistant message for the in-flight run — the same data source behind the Slack live task card's activity line — as one truncated line on the card, updating with the existing 2s poll and falling back to the plain status when no activity exists yet.
|
1 issue outstanding. See task
Reviewed 364696c |
| ), | ||
| ) | ||
| .orderBy(desc(taskMessages.ts), desc(taskMessages.createdAt)) | ||
| .limit(10); |
There was a problem hiding this comment.
Limiting this to 10 rows means the card becomes blank whenever ten transient retry/provider-error messages follow the last eligible update. Those rows are intentionally skipped, while the Slack card retains its prior eligible message. Continue scanning until an eligible row is found (and add a regression test with more than ten transient rows) so the card does not lose its activity line during repeated recovery.
There was a problem hiding this comment.
Fixed in 364696c: the lookup now scans newest-first in batches until it finds an eligible assistant message instead of stopping at 10 rows, so the card keeps its prior activity line through long retry storms. Added a regression test with 25 transient rows stacked on top of the eligible message (crossing the batch boundary).
A hard 10-row limit blanked the card whenever more transient provider-error/retry messages than that followed the last eligible assistant message. Scan newest-first in batches until an eligible message is found, so the card keeps its prior line like Slack does.
| // eligible one; scan newest-first in batches until an eligible message is | ||
| // found so the card keeps its prior activity line, matching Slack. | ||
| const batchSize = 20; | ||
| for (let offset = 0; ; offset += batchSize) { |
There was a problem hiding this comment.
Offset pagination is unstable while the retry storm is still writing rows. If a new transient message lands after the first batch, it shifts the remaining rows down: the next offset(20) can re-read a row from the first batch, then return a short page and null without ever visiting the formerly 21st eligible message. That recreates the blank activity line this change is meant to prevent. Use a stable keyset cursor (including a deterministic tie-breaker) or a single-query approach, and cover an insert between batches.
Summary
Fast-session delegated-task cards were static while a task ran — just a title and a Working status. Slack task messages already surface a line of recent activity; this brings the same signal to the web card so the wait during setup-session starter tasks no longer feels dead.
getLatestTaskActivityLine(runId)inapps/web/src/lib/server/task-activity.tsderives the line from the same data source behind the Slack live task card: the most recent meaningfulroomote_runtime.assistant_messageintask_messagesfor the run. Reasoning, tool calls, and transient "provider error"/"retrying" narration are excluded (parity with the worker'sprovisional-completionfilter that gates the Slack card).sandboxSession.byTaskIdnow returnsactivityLinefor in-flight runs only (null once the run exits), so the card's existing 2s poll picks it up with no new client query.DelegatedTaskCardrenders it as one truncatedtext-xsline under the title; when no activity exists yet the card looks exactly as before (plain status fallback). Assistant markdown is flattened to plain text for the single-line render, leaving intra-word underscores (identifiers) intact.How Slack derives its line (investigated)
The Slack activity line is pushed live from the worker callback stream (
apps/worker/src/callbacks/slack-live-task-stream.ts): latest assistanttextevent, reasoning excluded, todo updates ignored, transient messages filtered. The web can't tap that in-process stream, so this reuses the persisted form of the same events — the run'stask_messagesrows — matching the query shape ofgetPersistedConflictResolutionCompletion.Tests
task-activity.test.ts(server, real DB): latest eligible message wins; prompts/reasoning ignored; transient retry/provider-error narration skipped; run isolation; markdown flattening, identifier underscores, truncation.DelegatedTaskCard.client.test.tsx: renders the activity line while working; falls back to the plain status when absent.pnpm lint,pnpm check-types,pnpm knip, and the surrounding sandbox-session / fast-sessions / SessionWorkspace suites pass.