agent terminal: pretty-render task_started / task_notification
claude's Task tool spawns subagents whose progress lands as stream-json events with subtype=task_started or task_notification — previously fell through to the .sys catch-all and rendered as a raw json dump that wrapped per char in the live pane. now matched by subtype before the catch-all: - task_started → cyan tool-use row, ⌁ glyph, first 8 chars of task_id, description, and optional [task_type] - task_notification → row styled by status: completed → turn-end-ok (green ✓), failed → turn-end-fail (red ✗), other → tool-result (muted ◌). output_file rendered inline if present so the operator can trace where the body landed. matching on `v.subtype` rather than a particular `v.type` so the renderer survives claude wrapping these under different top-level type fields across versions.
This commit is contained in:
parent
63f5f9a2ef
commit
fd7712f5c1
1 changed files with 33 additions and 0 deletions
|
|
@ -742,12 +742,45 @@
|
|||
api.details('tool-result-block', summary, txt);
|
||||
}
|
||||
}
|
||||
// Pretty-render claude's background-task subagent events
|
||||
// (`task_started`, `task_notification`). They share the same
|
||||
// task_id so the operator can correlate start ↔ result; render
|
||||
// each as a peer of tool_use / tool_result with a `⌁` glyph to
|
||||
// mark "this happened in a subagent" rather than the main
|
||||
// session.
|
||||
function renderTaskEvent(v, api) {
|
||||
const id = (v.task_id || '').slice(0, 8);
|
||||
const kind = v.task_type ? ` [${v.task_type}]` : '';
|
||||
const desc = v.description || v.summary || '(no description)';
|
||||
if (v.subtype === 'task_started') {
|
||||
api.row('tool-use', `⌁ task ${id} started · ${desc}${kind}`);
|
||||
return true;
|
||||
}
|
||||
if (v.subtype === 'task_notification') {
|
||||
const status = v.status || 'unknown';
|
||||
const glyph = status === 'completed' ? '✓' : status === 'failed' ? '✗' : '◌';
|
||||
const cls = status === 'completed' ? 'turn-end-ok'
|
||||
: status === 'failed' ? 'turn-end-fail'
|
||||
: 'tool-result';
|
||||
const out = v.output_file ? ` · → ${v.output_file}` : '';
|
||||
api.row(cls, `⌁ task ${id} ${glyph} ${status} · ${desc}${out}`);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function renderStream(v, api) {
|
||||
// Drop session init, claude's result line, rate-limit — noise.
|
||||
// TurnEnd communicates pass/fail; session init isn't actionable.
|
||||
if (v.type === 'system' && v.subtype === 'init') return;
|
||||
if (v.type === 'rate_limit_event') return;
|
||||
if (v.type === 'result') return;
|
||||
// Background-task subagent events (claude's `Task` tool spawns
|
||||
// a separate session whose progress lands here as `task_*`
|
||||
// subtypes). Match by subtype so we don't have to track which
|
||||
// top-level `type` claude wraps them under across versions.
|
||||
if (v.subtype === 'task_started' || v.subtype === 'task_notification') {
|
||||
if (renderTaskEvent(v, api)) return;
|
||||
}
|
||||
if (v.type === 'assistant' && v.message && v.message.content) {
|
||||
for (const c of v.message.content) {
|
||||
if (c.type === 'text' && c.text && c.text.trim()) api.row('text', c.text);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue