pi-subagents 0.72.1 → 0.73.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/docs/agents.md +1 -1
  3. package/docs/standalone-background.md +1 -1
  4. package/docs/tool-reference.md +1 -1
  5. package/docs/workflows.md +5 -1
  6. package/package.json +1 -1
  7. package/src/extension/index.d.ts.map +1 -1
  8. package/src/extension/index.js +2 -0
  9. package/src/extension/index.js.map +1 -1
  10. package/src/extension/tool-activation.js +1 -1
  11. package/src/extension/tool-activation.js.map +1 -1
  12. package/src/runs/background/run-status.d.ts.map +1 -1
  13. package/src/runs/background/run-status.js +1 -0
  14. package/src/runs/background/run-status.js.map +1 -1
  15. package/src/runs/foreground/subagent-executor.d.ts.map +1 -1
  16. package/src/runs/foreground/subagent-executor.js +142 -64
  17. package/src/runs/foreground/subagent-executor.js.map +1 -1
  18. package/src/runs/shared/async-status-projection.d.ts +3 -0
  19. package/src/runs/shared/async-status-projection.d.ts.map +1 -1
  20. package/src/runs/shared/async-status-projection.js +3 -0
  21. package/src/runs/shared/async-status-projection.js.map +1 -1
  22. package/src/runs/shared/mcp-direct-tool-allowlist.d.ts.map +1 -1
  23. package/src/runs/shared/mcp-direct-tool-allowlist.js +11 -12
  24. package/src/runs/shared/mcp-direct-tool-allowlist.js.map +1 -1
  25. package/src/shared/extension-context.d.ts +2 -0
  26. package/src/shared/extension-context.d.ts.map +1 -1
  27. package/src/shared/extension-context.js +4 -0
  28. package/src/shared/extension-context.js.map +1 -1
  29. package/src/shared/model-info.d.ts +4 -0
  30. package/src/shared/model-info.d.ts.map +1 -1
  31. package/src/shared/model-info.js +9 -0
  32. package/src/shared/model-info.js.map +1 -1
  33. package/src/shared/types.d.ts +2 -0
  34. package/src/shared/types.d.ts.map +1 -1
  35. package/src/shared/types.js.map +1 -1
  36. package/src/tui/fleet-status.d.ts.map +1 -1
  37. package/src/tui/fleet-status.js +12 -6
  38. package/src/tui/fleet-status.js.map +1 -1
  39. package/src/tui/fleet.d.ts.map +1 -1
  40. package/src/tui/fleet.js +12 -1
  41. package/src/tui/fleet.js.map +1 -1
  42. package/src/tui/render.d.ts.map +1 -1
  43. package/src/tui/render.js +54 -34
  44. package/src/tui/render.js.map +1 -1
  45. package/src/tui/running-tone.d.ts +11 -0
  46. package/src/tui/running-tone.d.ts.map +1 -0
  47. package/src/tui/running-tone.js +23 -0
  48. package/src/tui/running-tone.js.map +1 -0
  49. package/src/workflows/scripted-workflow.d.ts +6 -4
  50. package/src/workflows/scripted-workflow.d.ts.map +1 -1
  51. package/src/workflows/scripted-workflow.js +100 -35
  52. package/src/workflows/scripted-workflow.js.map +1 -1
  53. package/src/workflows/workflow-checklist.d.ts +4 -0
  54. package/src/workflows/workflow-checklist.d.ts.map +1 -1
  55. package/src/workflows/workflow-checklist.js +3 -0
  56. package/src/workflows/workflow-checklist.js.map +1 -1
package/src/tui/render.js CHANGED
@@ -16,6 +16,8 @@ import { formatNestedAggregate } from "../runs/shared/nested-render.js";
16
16
  import { aggregateStepStatus, formatActivityLabel, formatAgentRunningLabel, formatParallelOutcome } from "../shared/status-format.js";
17
17
  import { contextModeBadge, contextModePrefix } from "../runs/shared/context-mode.js";
18
18
  import { shouldSuppressSingleStep, stripRepeatedAgentPrefix, withDuplicateLabelDiscriminators } from "./render-helpers.js";
19
+ import { runningTone } from "./running-tone.js";
20
+ import { childThinkingLevel } from "../shared/model-info.js";
19
21
  import { buildWorkflowChatProgressRows } from "../workflows/chat-progress.js";
20
22
  import { formatWorkflowPreflight, formatWorkflowPreflightPlanSummary, formatWorkflowPreflightWarningSummary, formatWorkflowPreflightWarnings } from "../workflows/workflow-preflight.js";
21
23
  import { encodeAsyncStatusSnapshotWidget } from "../runs/background/async-status-snapshot.js";
@@ -820,7 +822,7 @@ function resultStatusLine(result, output) {
820
822
  function semanticResultPresentation(input) {
821
823
  if (input.running) {
822
824
  const glyph = input.frame !== undefined ? runningGlyph((input.seed ?? 0) + input.frame) : runningGlyph(input.seed);
823
- return { glyph, label: "running", tone: "accent" };
825
+ return { glyph, label: "running", tone: "accent", ...(input.thinking ? { thinking: input.thinking } : {}) };
824
826
  }
825
827
  if (input.detached)
826
828
  return { glyph: "■", label: "detached", tone: "warning" };
@@ -868,16 +870,21 @@ function resultPresentation(result, output, running = isResultRunning(result), s
868
870
  completedWithoutOutput: hasEmptyTextOutputWithoutOutputTarget(result.task, output),
869
871
  seed,
870
872
  frame,
873
+ thinking: childThinkingLevel(result, result.progress),
871
874
  });
872
875
  }
876
+ function presentationTone(presentation, theme) {
877
+ return presentation.label === "running" ? runningTone(theme, presentation.thinking) : (text) => theme.fg(presentation.tone, text);
878
+ }
873
879
  function resultGlyph(result, output, theme, running = isResultRunning(result), seed = progressRunningSeed(result.progress ?? result.progressSummary), frame) {
874
880
  const presentation = resultPresentation(result, output, running, seed, frame);
875
- return theme.fg(presentation.tone, presentation.glyph);
881
+ return presentationTone(presentation, theme)(presentation.glyph);
876
882
  }
877
883
  function styledResultPresentation(presentation, theme) {
884
+ const tone = presentationTone(presentation, theme);
878
885
  return {
879
- glyph: theme.fg(presentation.tone, presentation.glyph),
880
- label: theme.fg(presentation.tone, presentation.label),
886
+ glyph: tone(presentation.glyph),
887
+ label: tone(presentation.label),
881
888
  };
882
889
  }
883
890
  function compactCurrentActivity(progress) {
@@ -1159,9 +1166,12 @@ function widgetJobsRunningSeed(jobs) {
1159
1166
  seed = runningSeed(seed, widgetJobRunningSeed(job));
1160
1167
  return seed;
1161
1168
  }
1169
+ function activeHeaderTone(theme, hasActive) {
1170
+ return hasActive ? runningTone(theme) : (text) => theme.fg("dim", text);
1171
+ }
1162
1172
  function widgetStatusGlyph(job, theme, frame) {
1163
1173
  if (job.status === "running")
1164
- return theme.fg("accent", runningGlyph(animatedSeed(widgetJobRunningSeed(job), frame)));
1174
+ return runningTone(theme, job.mode === "single" ? childThinkingLevel(job.steps?.[0]) : undefined)(runningGlyph(animatedSeed(widgetJobRunningSeed(job), frame)));
1165
1175
  if (job.status === "queued")
1166
1176
  return theme.fg("muted", "◦");
1167
1177
  if (job.status === "complete")
@@ -1172,9 +1182,9 @@ function widgetStatusGlyph(job, theme, frame) {
1172
1182
  return theme.fg("warning", "■");
1173
1183
  return theme.fg("error", "✗");
1174
1184
  }
1175
- function widgetStepGlyph(status, theme, seed, frame) {
1185
+ function widgetStepGlyph(status, theme, seed, frame, thinking) {
1176
1186
  if (status === "running")
1177
- return theme.fg("accent", runningGlyph(animatedSeed(seed, frame)));
1187
+ return runningTone(theme, thinking)(runningGlyph(animatedSeed(seed, frame)));
1178
1188
  if (status === "complete" || status === "completed")
1179
1189
  return theme.fg("success", "✓");
1180
1190
  if (status === "failed")
@@ -1185,9 +1195,9 @@ function widgetStepGlyph(status, theme, seed, frame) {
1185
1195
  return theme.fg("warning", "■");
1186
1196
  return theme.fg("muted", "◦");
1187
1197
  }
1188
- function widgetStepStatus(status, theme) {
1198
+ function widgetStepStatus(status, theme, thinking) {
1189
1199
  if (status === "running")
1190
- return theme.fg("accent", "running");
1200
+ return runningTone(theme, thinking)("running");
1191
1201
  if (status === "complete" || status === "completed")
1192
1202
  return theme.fg("success", "complete");
1193
1203
  if (status === "failed")
@@ -1207,7 +1217,7 @@ function workflowChecklistStateLabel(state) {
1207
1217
  }
1208
1218
  function workflowChecklistGlyph(item, theme, frame) {
1209
1219
  if (item.state === "running")
1210
- return theme.fg("accent", runningGlyph(animatedSeed(runningSeed(item.startedAt, item.durationMs, item.toolCount, item.currentToolStartedAt), frame)));
1220
+ return runningTone(theme, item.thinking)(runningGlyph(animatedSeed(runningSeed(item.startedAt, item.durationMs, item.toolCount, item.currentToolStartedAt), frame)));
1211
1221
  if (item.state === "complete")
1212
1222
  return theme.fg("success", "✓");
1213
1223
  if (item.state === "blocked")
@@ -1318,6 +1328,7 @@ function compactWorkflowLaneRow(key, items, lane = items.find((item) => item.pre
1318
1328
  key: boundedLaneValue(key, 40) ?? key,
1319
1329
  state,
1320
1330
  agent: compactWorkflowLaneOwner(items),
1331
+ ...(items.length === 1 && items[0]?.thinking ? { thinking: items[0].thinking } : {}),
1321
1332
  ...(lane?.mode ? { mode: lane.mode } : {}),
1322
1333
  ...(lane?.decision ? { decision: boundedLaneValue(lane.decision, 56) } : {}),
1323
1334
  ...(lane?.claims?.length ? { claims: boundedLaneValue(lane.claims.join(", "), 56) } : {}),
@@ -1403,7 +1414,7 @@ function compactWorkflowLaneLine(row, theme, indent, frame) {
1403
1414
  row.expectedOutput,
1404
1415
  !row.mode && row.label ? row.label : undefined,
1405
1416
  ].filter((value) => Boolean(value));
1406
- return `${indent}${workflowChecklistGlyph({ state: row.state, durationMs: row.durationMs, toolCount: row.toolUses }, theme, frame)} ${theme.bold(row.key)}${owner ? ` ${theme.fg("dim", `· ${owner}`)}` : ""}${state ? ` ${theme.fg("dim", `· ${state}`)}` : ""}${intent.length ? ` ${theme.fg("dim", `· ${intent.join(" · ")}`)}` : ""}`;
1417
+ return `${indent}${workflowChecklistGlyph({ state: row.state, durationMs: row.durationMs, toolCount: row.toolUses, thinking: row.thinking }, theme, frame)} ${theme.bold(row.key)}${owner ? ` ${theme.fg("dim", `· ${owner}`)}` : ""}${state ? ` ${theme.fg("dim", `· ${state}`)}` : ""}${intent.length ? ` ${theme.fg("dim", `· ${intent.join(" · ")}`)}` : ""}`;
1407
1418
  }
1408
1419
  function compactWorkflowShortId(job) {
1409
1420
  return job.asyncId.slice(0, 8);
@@ -1543,7 +1554,8 @@ function widgetParallelAgentDetails(job, theme, expanded = false, width = getTer
1543
1554
  const modelDisplay = modelThinkingBadge(theme, step.model, step.thinking);
1544
1555
  const label = compactTaskText(step.description, step.label);
1545
1556
  const display = step.sessionName?.trim() || (label ? `${label} (${step.agent})` : step.agent);
1546
- lines.push(` ${theme.fg("dim", `${marker} ${widgetStepGlyph(step.status, theme, widgetStepRunningSeed(step, index), frame)} ${itemTitle} ${index + 1}/${total}: ${display} · ${widgetStepStatus(step.status, theme)}${modelDisplay}${activity ? ` · ${activity}` : ""}`)}`);
1557
+ const thinking = childThinkingLevel(step);
1558
+ lines.push(` ${theme.fg("dim", `${marker} ${widgetStepGlyph(step.status, theme, widgetStepRunningSeed(step, index), frame, thinking)} ${itemTitle} ${index + 1}/${total}: ${display} · ${widgetStepStatus(step.status, theme, thinking)}${modelDisplay}${activity ? ` · ${activity}` : ""}`)}`);
1547
1559
  const lane = projectAsyncLane(job, step);
1548
1560
  if (lane)
1549
1561
  lines.push(...formatLaneProjectionLines(lane, theme, " "));
@@ -2022,9 +2034,9 @@ function nestedRunName(run) {
2022
2034
  return formatWidgetAgents(run.agents);
2023
2035
  return run.id;
2024
2036
  }
2025
- function nestedStatusGlyph(state, theme, seed) {
2037
+ function nestedStatusGlyph(state, theme, seed, thinking) {
2026
2038
  if (state === "running")
2027
- return theme.fg("accent", runningGlyph(seed));
2039
+ return runningTone(theme, thinking)(runningGlyph(seed));
2028
2040
  if (state === "complete" || state === "completed")
2029
2041
  return theme.fg("success", "✓");
2030
2042
  if (state === "failed")
@@ -2116,7 +2128,7 @@ function formatNestedWidgetLines(children, theme, width, expanded, snapshotNow,
2116
2128
  const name = "status" in step ? childDisplayName(step) : nestedRunName(step);
2117
2129
  rows.push({
2118
2130
  prefix,
2119
- text: `${nestedTimestampPrefix(timestamp)}${nestedStatusGlyph(state, theme)} ${name} · ${state}${modelThinking ? ` · ${modelThinking}` : ""}${activity ? ` · ${activity}` : ""}${error}`,
2131
+ text: `${nestedTimestampPrefix(timestamp)}${nestedStatusGlyph(state, theme, undefined, childThinkingLevel(step))} ${name} · ${state}${modelThinking ? ` · ${modelThinking}` : ""}${activity ? ` · ${activity}` : ""}${error}`,
2120
2132
  });
2121
2133
  };
2122
2134
  for (const child of children) {
@@ -2127,7 +2139,7 @@ function formatNestedWidgetLines(children, theme, width, expanded, snapshotNow,
2127
2139
  const ownerError = child.error ? ` · ${child.error}` : "";
2128
2140
  rows.push({
2129
2141
  prefix: "↳ ",
2130
- text: `OWNER ${nestedStatusGlyph(child.state, theme, nestedRunSeed(child))} ${nestedRunName(child)} · ${child.state}${ownerModelThinking ? ` · ${ownerModelThinking}` : ""}${ownerActivity ? ` · ${ownerActivity}` : ""}${ownerError}`,
2142
+ text: `OWNER ${nestedStatusGlyph(child.state, theme, nestedRunSeed(child), childThinkingLevel(child))} ${nestedRunName(child)} · ${child.state}${ownerModelThinking ? ` · ${ownerModelThinking}` : ""}${ownerActivity ? ` · ${ownerActivity}` : ""}${ownerError}`,
2131
2143
  });
2132
2144
  for (const step of steps)
2133
2145
  appendLeaf(step, "↳ │ ", child.lastUpdate);
@@ -2172,7 +2184,7 @@ function formatNestedWidgetLines(children, theme, width, expanded, snapshotNow,
2172
2184
  const activity = nestedActivity(child, child.state, snapshotNow ?? child.lastUpdate);
2173
2185
  const error = child.error ? ` · ${child.error}` : "";
2174
2186
  const modelThinking = formatModelThinking(child.model, child.thinking);
2175
- lines.push(theme.fg("dim", `${prefix}↳ ${nestedTimestampPrefix(formatClockTime(nestedRunEventTime(child)))}${nestedStatusGlyph(child.state, theme, nestedRunSeed(child))} ${nestedRunName(child)} · ${child.state}${modelThinking ? ` · ${modelThinking}` : ""} · ${activity}${error}`));
2187
+ lines.push(theme.fg("dim", `${prefix}↳ ${nestedTimestampPrefix(formatClockTime(nestedRunEventTime(child)))}${nestedStatusGlyph(child.state, theme, nestedRunSeed(child), childThinkingLevel(child))} ${nestedRunName(child)} · ${child.state}${modelThinking ? ` · ${modelThinking}` : ""} · ${activity}${error}`));
2176
2188
  if (depth === maxDepth) {
2177
2189
  const aggregate = formatNestedAggregate([...(child.steps?.flatMap((step) => step.children ?? []) ?? []), ...(child.children ?? [])]);
2178
2190
  if (aggregate && lines.length < lineBudget)
@@ -2183,7 +2195,7 @@ function formatNestedWidgetLines(children, theme, width, expanded, snapshotNow,
2183
2195
  if (lines.length >= lineBudget)
2184
2196
  return;
2185
2197
  const modelThinking = formatModelThinking(step.model, step.thinking);
2186
- lines.push(theme.fg("dim", `${prefix} ↳ ${nestedTimestampPrefix(nestedStepTimestamp(step, child.lastUpdate))}${nestedStatusGlyph(step.status, theme)} ${childDisplayName(step)} · ${step.status}${modelThinking ? ` · ${modelThinking}` : ""} · ${nestedActivity(step, step.status, snapshotNow ?? child.lastUpdate)}`));
2198
+ lines.push(theme.fg("dim", `${prefix} ↳ ${nestedTimestampPrefix(nestedStepTimestamp(step, child.lastUpdate))}${nestedStatusGlyph(step.status, theme, undefined, childThinkingLevel(step))} ${childDisplayName(step)} · ${step.status}${modelThinking ? ` · ${modelThinking}` : ""} · ${nestedActivity(step, step.status, snapshotNow ?? child.lastUpdate)}`));
2187
2199
  append(step.children, depth + 1, `${prefix} `);
2188
2200
  }
2189
2201
  append(child.children, depth + 1, `${prefix} `);
@@ -2195,7 +2207,8 @@ function formatNestedWidgetLines(children, theme, width, expanded, snapshotNow,
2195
2207
  function foregroundStyleWidgetStepLines(job, theme, step, itemTitle, index, total, expanded, width, frame, options) {
2196
2208
  const rowIndent = options?.rowIndent ?? " ";
2197
2209
  const detailIndent = options?.detailIndent ?? " ";
2198
- const status = widgetStepStatus(step.status, theme);
2210
+ const thinking = childThinkingLevel(step);
2211
+ const status = widgetStepStatus(step.status, theme, thinking);
2199
2212
  const stats = widgetStepStats(theme, step, job.updatedAt);
2200
2213
  const modelDisplay = modelThinkingBadge(theme, step.model, step.thinking);
2201
2214
  const collapseDetails = shouldCollapseSingleChildDetails(job, step);
@@ -2206,7 +2219,7 @@ function foregroundStyleWidgetStepLines(job, theme, step, itemTitle, index, tota
2206
2219
  const stageIdentity = stageName && stageName !== displayName ? `${stageName} (${displayName})` : stageName ?? displayName;
2207
2220
  const rowLabel = collapseDetails ? displayName : (options?.rowLabel ?? `${itemTitle} ${index}/${total}: ${itemTitle === "Stage" ? stageIdentity : displayName}`);
2208
2221
  const rowMarker = options?.rowMarker ? `${options.rowMarker} ` : "";
2209
- const lines = [`${rowIndent}${rowMarker}${widgetStepGlyph(step.status, theme, widgetStepRunningSeed(step, index - 1), frame)} ${themeBold(theme, rowLabel)}${contextModeBadge(theme, step.context)} ${theme.fg("dim", "·")} ${status}${modelDisplay}${stats ? ` ${theme.fg("dim", "·")} ${stats}` : ""}`];
2222
+ const lines = [`${rowIndent}${rowMarker}${widgetStepGlyph(step.status, theme, widgetStepRunningSeed(step, index - 1), frame, thinking)} ${themeBold(theme, rowLabel)}${contextModeBadge(theme, step.context)} ${theme.fg("dim", "·")} ${status}${modelDisplay}${stats ? ` ${theme.fg("dim", "·")} ${stats}` : ""}`];
2210
2223
  const lane = projectAsyncLane(job, step);
2211
2224
  if (lane)
2212
2225
  lines.push(...formatLaneProjectionLines(lane, theme, detailIndent));
@@ -2358,7 +2371,8 @@ function compactSingleWidgetLines(job, theme, width, frame, projection = buildWo
2358
2371
  lines.push(parallelWidgetGroupHeader(group, theme, frame));
2359
2372
  for (const [rowIndex, row] of rows.entries()) {
2360
2373
  const step = row.step;
2361
- const status = widgetStepStatus(step.status, theme);
2374
+ const thinking = childThinkingLevel(step);
2375
+ const status = widgetStepStatus(step.status, theme, thinking);
2362
2376
  const activity = widgetStepActivityLine(step, width, false, job.updatedAt);
2363
2377
  const stepStats = widgetStepStats(theme, step, job.updatedAt);
2364
2378
  const activitySuffix = activity ? ` ${theme.fg("dim", "·")} ${theme.fg("dim", activity)}` : "";
@@ -2366,7 +2380,7 @@ function compactSingleWidgetLines(job, theme, width, frame, projection = buildWo
2366
2380
  const task = compactTaskText(step.description, step.label);
2367
2381
  const taskSuffix = task ? ` ${theme.fg("dim", "·")} ${theme.fg("dim", `task: ${task}`)}` : "";
2368
2382
  const marker = rowIndex === rows.length - 1 && rowIndex >= group.total - 1 ? "└─" : "├─";
2369
- lines.push(` ${marker} ${widgetStepGlyph(step.status, theme, widgetStepRunningSeed(step, row.index), frame)} ${themeBold(theme, row.rowLabel)}${contextModeBadge(theme, step.context)} ${theme.fg("dim", "·")} ${status}${modelDisplay}${taskSuffix}${activitySuffix}${stepStats ? ` ${theme.fg("dim", "·")} ${stepStats}` : ""}`);
2383
+ lines.push(` ${marker} ${widgetStepGlyph(step.status, theme, widgetStepRunningSeed(step, row.index), frame, thinking)} ${themeBold(theme, row.rowLabel)}${contextModeBadge(theme, step.context)} ${theme.fg("dim", "·")} ${status}${modelDisplay}${taskSuffix}${activitySuffix}${stepStats ? ` ${theme.fg("dim", "·")} ${stepStats}` : ""}`);
2370
2384
  const lane = projectAsyncLane(job, step);
2371
2385
  if (lane)
2372
2386
  lines.push(...formatLaneProjectionLines(lane, theme, " "));
@@ -2430,7 +2444,8 @@ function buildSingleLineWidgetLines(jobs, theme, width, frame) {
2430
2444
  }
2431
2445
  if (!hasActive && counts.complete.length > 0)
2432
2446
  parts.push(`${counts.complete.length}/${jobs.length} done`);
2433
- return [truncLine(`${theme.fg(hasActive ? "accent" : "dim", glyph)} ${theme.fg(hasActive ? "accent" : "dim", "subagents")} (${parts.join(", ") || `${jobs.length} total`})`, width)];
2447
+ const tone = activeHeaderTone(theme, hasActive);
2448
+ return [truncLine(`${tone(glyph)} ${tone("subagents")} (${parts.join(", ") || `${jobs.length} total`})`, width)];
2434
2449
  }
2435
2450
  function orderedWidgetJobs(jobs) {
2436
2451
  return [
@@ -2506,7 +2521,8 @@ function progressiveHeaderLine(jobs, theme, width, frame) {
2506
2521
  if (counts.complete.length > 0)
2507
2522
  parts.push(`${counts.complete.length}/${jobs.length} done`);
2508
2523
  }
2509
- return truncLine(`${theme.fg(hasActive ? "accent" : "dim", glyph)} ${theme.fg(hasActive ? "accent" : "dim", "Async agents")} ${theme.fg("dim", "·")} ${theme.fg("dim", parts.join(", ") || `${jobs.length} total`)}`, width);
2524
+ const tone = activeHeaderTone(theme, hasActive);
2525
+ return truncLine(`${tone(glyph)} ${tone("Async agents")} ${theme.fg("dim", "·")} ${theme.fg("dim", parts.join(", ") || `${jobs.length} total`)}`, width);
2510
2526
  }
2511
2527
  function progressiveJobLine(job, theme, width, frame, projection = buildWorkflowWidgetProjection(job)) {
2512
2528
  const compactWorkflow = job.mode === "workflow";
@@ -2830,7 +2846,8 @@ function buildWidgetLinesWithProjection(jobs, theme, width = getTermWidth(), exp
2830
2846
  const lines = [];
2831
2847
  const hasActive = running.length > 0 || queued.length > 0;
2832
2848
  const headerGlyph = running.length > 0 ? runningGlyph(animatedSeed(widgetJobsRunningSeed(running), frame)) : hasActive ? "●" : "○";
2833
- lines.push(truncLine(`${theme.fg(hasActive ? "accent" : "dim", headerGlyph)} ${theme.fg(hasActive ? "accent" : "dim", "Async agents")} ${theme.fg("dim", "· background")}`, width));
2849
+ const tone = activeHeaderTone(theme, hasActive);
2850
+ lines.push(truncLine(`${tone(headerGlyph)} ${tone("Async agents")} ${theme.fg("dim", "· background")}`, width));
2834
2851
  const items = [];
2835
2852
  let hiddenRunning = 0;
2836
2853
  let hiddenFinished = 0;
@@ -2981,23 +2998,23 @@ function renderSingleCompact(d, r, theme, layout, frame, foregroundDetachShortcu
2981
2998
  c.addChild(new Text(truncLine(theme.fg("dim", `${detailIndent}full output: ${shortenPath(r.truncation.artifactPath)}`), width), 0, 0));
2982
2999
  return c;
2983
3000
  }
2984
- function workflowRowGlyph(row, theme, frame) {
3001
+ function workflowRowGlyph(row, theme, frame, thinking) {
2985
3002
  if (row.state === "planned")
2986
3003
  return theme.fg("muted", "◦");
2987
3004
  if (row.state === "running")
2988
- return theme.fg("accent", runningGlyph(frame));
3005
+ return runningTone(theme, thinking)(runningGlyph(frame));
2989
3006
  if (row.state === "complete")
2990
3007
  return theme.fg("success", "✓");
2991
3008
  if (row.state === "detached" || row.state === "stopped")
2992
3009
  return theme.fg("warning", "■");
2993
3010
  return theme.fg("error", "✗");
2994
3011
  }
2995
- function workflowRowStateLabel(row, theme) {
3012
+ function workflowRowStateLabel(row, theme, thinking) {
2996
3013
  const label = (row.state === "complete" ? "complete" : row.state).padEnd(8);
2997
3014
  if (row.state === "planned")
2998
3015
  return theme.fg("dim", label);
2999
3016
  if (row.state === "running")
3000
- return theme.fg("accent", label);
3017
+ return runningTone(theme, thinking)(label);
3001
3018
  if (row.state === "complete")
3002
3019
  return theme.fg("success", label);
3003
3020
  if (row.state === "detached" || row.state === "stopped")
@@ -3042,6 +3059,7 @@ function foregroundWorkflowChecklist(details) {
3042
3059
  label: node?.label ?? workflowLabelForResult(details, resultIndex) ?? result.task ?? result.agent,
3043
3060
  phase: node?.phase,
3044
3061
  agent: result.agent,
3062
+ thinking: result.thinking ?? progress?.thinking,
3045
3063
  status,
3046
3064
  context: result.context,
3047
3065
  activityState: progress?.activityState,
@@ -3076,7 +3094,7 @@ function renderWorkflowChatProgress(d, result, theme, layout, frame, expanded =
3076
3094
  const workflow = d.workflow;
3077
3095
  const rows = workflow ? buildWorkflowChatProgressRows(workflow.trace, d.preflight) : d.preflight ? buildWorkflowChatProgressRows([], d.preflight) : [];
3078
3096
  const state = workflowOverallState(rows, workflow?.value !== undefined, result.isError);
3079
- const glyph = state === "running" ? theme.fg("accent", runningGlyph(frame)) : state === "complete" ? theme.fg("success", "✓") : state === "paused" ? theme.fg("warning", "■") : theme.fg("error", "✗");
3097
+ const glyph = state === "running" ? runningTone(theme)(runningGlyph(frame)) : state === "complete" ? theme.fg("success", "✓") : state === "paused" ? theme.fg("warning", "■") : theme.fg("error", "✗");
3080
3098
  const width = getTermWidth() - 4;
3081
3099
  const runId = d.runId ? d.runId.slice(0, 12) : "workflow";
3082
3100
  const repoLabel = d.chatProgress?.repoLabel ?? (d.chatProgress?.repoRelation === "same" ? "same repo" : "other repo");
@@ -3100,8 +3118,10 @@ function renderWorkflowChatProgress(d, result, theme, layout, frame, expanded =
3100
3118
  const visible = visibleWorkflowRows(rows);
3101
3119
  if (visible.hiddenRows > 0)
3102
3120
  c.addChild(new Text(truncLine(theme.fg("dim", `${rowIndent}… ${visible.hiddenRows} older workflow rows hidden`), width), 0, 0));
3121
+ const childLevels = new Map((d.workflowChildren?.children ?? []).map((child) => [child.childId, childThinkingLevel(child)]));
3103
3122
  for (const row of visible.rows) {
3104
- const status = workflowRowStateLabel(row, theme);
3123
+ const thinking = childLevels.get(row.key);
3124
+ const status = workflowRowStateLabel(row, theme, thinking);
3105
3125
  const label = row.label && row.label !== row.key ? ` ${oneLine(row.label)}` : "";
3106
3126
  const duration = row.durationMs !== undefined ? ` ${theme.fg("dim", `· ${formatDuration(row.durationMs)}`)}` : "";
3107
3127
  const run = row.runId ? ` ${theme.fg("dim", `[${row.runId.slice(0, 8)}]`)}` : "";
@@ -3113,7 +3133,7 @@ function renderWorkflowChatProgress(d, result, theme, layout, frame, expanded =
3113
3133
  row.preflight.expectedOutput ? `expected:${row.preflight.expectedOutput}` : undefined,
3114
3134
  row.preflight.independence ? `independence:${row.preflight.independence}` : undefined,
3115
3135
  ].filter((value) => Boolean(value)).join(" · ") : "";
3116
- c.addChild(new Text(truncLine(`${rowIndent}${workflowRowGlyph(row, theme, frame)} ${status} ${theme.bold(row.key)}${label}${run}${duration}${error}${hints ? ` ${theme.fg("dim", `· ${hints}`)}` : ""}`, width), 0, 0));
3136
+ c.addChild(new Text(truncLine(`${rowIndent}${workflowRowGlyph(row, theme, frame, thinking)} ${status} ${theme.bold(row.key)}${label}${run}${duration}${error}${hints ? ` ${theme.fg("dim", `· ${hints}`)}` : ""}`, width), 0, 0));
3117
3137
  }
3118
3138
  if (workflow?.preflightWarnings?.length) {
3119
3139
  const warningLines = expanded
@@ -3168,7 +3188,7 @@ function renderMultiCompact(d, theme, layout, frame) {
3168
3188
  seed: runningSeed(progressRunningSeed(totalSummary), d.currentStepIndex),
3169
3189
  frame,
3170
3190
  });
3171
- const glyph = theme.fg(aggregatePresentation.tone, aggregatePresentation.glyph);
3191
+ const glyph = presentationTone(aggregatePresentation, theme)(aggregatePresentation.glyph);
3172
3192
  const contextBadge = contextModeBadge(theme, d.context);
3173
3193
  const c = new Container();
3174
3194
  const width = getTermWidth() - 4;
@@ -3275,7 +3295,7 @@ export function renderSubagentSummary(result, options, theme) {
3275
3295
  const partial = Boolean(details && workflowGraphHasStatus(details, ["partial"]));
3276
3296
  const state = running ? "running" : failed ? "failed" : stopped ? "stopped" : paused ? "paused" : partial ? "partial" : "completed";
3277
3297
  const glyph = state === "running"
3278
- ? theme.fg("accent", STATIC_RUNNING_GLYPH)
3298
+ ? runningTone(theme, details?.mode === "single" && results.length === 1 ? childThinkingLevel(results[0], results[0]?.progress) : undefined)(STATIC_RUNNING_GLYPH)
3279
3299
  : state === "completed"
3280
3300
  ? theme.fg("success", "✓")
3281
3301
  : state === "failed"