@ashx-j/lunr 0.2.20 → 0.2.21

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 (172) hide show
  1. package/CHANGELOG.md +13 -1
  2. package/dist/builtin-extensions/lunr-todos.d.ts +6 -5
  3. package/dist/builtin-extensions/lunr-todos.d.ts.map +1 -1
  4. package/dist/builtin-extensions/lunr-todos.js +9 -7
  5. package/dist/builtin-extensions/lunr-todos.js.map +1 -1
  6. package/dist/builtin-extensions/pi-intercom/broker/spawn.d.ts.map +1 -1
  7. package/dist/builtin-extensions/pi-intercom/broker/spawn.js +30 -21
  8. package/dist/builtin-extensions/pi-intercom/broker/spawn.js.map +1 -1
  9. package/dist/builtin-extensions/pi-intercom/index.d.ts.map +1 -1
  10. package/dist/builtin-extensions/pi-intercom/index.js +12 -3
  11. package/dist/builtin-extensions/pi-intercom/index.js.map +1 -1
  12. package/dist/builtin-extensions/pi-subagents/src/extension/fanout-child.d.ts.map +1 -1
  13. package/dist/builtin-extensions/pi-subagents/src/extension/fanout-child.js +2 -2
  14. package/dist/builtin-extensions/pi-subagents/src/extension/fanout-child.js.map +1 -1
  15. package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts +7 -6
  16. package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts.map +1 -1
  17. package/dist/builtin-extensions/pi-subagents/src/extension/index.js +63 -29
  18. package/dist/builtin-extensions/pi-subagents/src/extension/index.js.map +1 -1
  19. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.d.ts.map +1 -1
  20. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js +2 -2
  21. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js.map +1 -1
  22. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts +3 -3
  23. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts.map +1 -1
  24. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js +3 -2
  25. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js.map +1 -1
  26. package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.d.ts +1 -0
  27. package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.d.ts.map +1 -1
  28. package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.js +26 -7
  29. package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.js.map +1 -1
  30. package/dist/builtin-extensions/pi-subagents/src/intercom/result-intercom.d.ts +1 -0
  31. package/dist/builtin-extensions/pi-subagents/src/intercom/result-intercom.d.ts.map +1 -1
  32. package/dist/builtin-extensions/pi-subagents/src/intercom/result-intercom.js +1 -1
  33. package/dist/builtin-extensions/pi-subagents/src/intercom/result-intercom.js.map +1 -1
  34. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.d.ts +2 -0
  35. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.d.ts.map +1 -1
  36. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.js +4 -3
  37. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.js.map +1 -1
  38. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-job-tracker.d.ts.map +1 -1
  39. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-job-tracker.js +2 -0
  40. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-job-tracker.js.map +1 -1
  41. package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.d.ts +6 -2
  42. package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.d.ts.map +1 -1
  43. package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.js +23 -1
  44. package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.js.map +1 -1
  45. package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.d.ts.map +1 -1
  46. package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.js +1 -0
  47. package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.js.map +1 -1
  48. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.d.ts +100 -0
  49. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.d.ts.map +1 -1
  50. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.js +46 -31
  51. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.js.map +1 -1
  52. package/dist/builtin-extensions/pi-subagents/src/runs/background/top-level-async.d.ts +15 -2
  53. package/dist/builtin-extensions/pi-subagents/src/runs/background/top-level-async.d.ts.map +1 -1
  54. package/dist/builtin-extensions/pi-subagents/src/runs/background/top-level-async.js +14 -4
  55. package/dist/builtin-extensions/pi-subagents/src/runs/background/top-level-async.js.map +1 -1
  56. package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.d.ts.map +1 -1
  57. package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.js +1 -1
  58. package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.js.map +1 -1
  59. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.d.ts.map +1 -1
  60. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.js +1 -1
  61. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.js.map +1 -1
  62. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.d.ts +0 -1
  63. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.d.ts.map +1 -1
  64. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js +9 -9
  65. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js.map +1 -1
  66. package/dist/builtin-extensions/pi-subagents/src/runs/shared/completion-guard.d.ts +1 -1
  67. package/dist/builtin-extensions/pi-subagents/src/runs/shared/completion-guard.d.ts.map +1 -1
  68. package/dist/builtin-extensions/pi-subagents/src/runs/shared/completion-guard.js +1 -1
  69. package/dist/builtin-extensions/pi-subagents/src/runs/shared/completion-guard.js.map +1 -1
  70. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.d.ts +1 -0
  71. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.d.ts.map +1 -1
  72. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.js.map +1 -1
  73. package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.d.ts +3 -0
  74. package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.d.ts.map +1 -1
  75. package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.js +2 -0
  76. package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.js.map +1 -1
  77. package/dist/builtin-extensions/pi-subagents/src/runs/shared/task-intent.d.ts +2 -2
  78. package/dist/builtin-extensions/pi-subagents/src/runs/shared/task-intent.d.ts.map +1 -1
  79. package/dist/builtin-extensions/pi-subagents/src/runs/shared/task-intent.js +5 -10
  80. package/dist/builtin-extensions/pi-subagents/src/runs/shared/task-intent.js.map +1 -1
  81. package/dist/builtin-extensions/pi-subagents/src/shared/async-guidance.d.ts +2 -0
  82. package/dist/builtin-extensions/pi-subagents/src/shared/async-guidance.d.ts.map +1 -0
  83. package/dist/builtin-extensions/pi-subagents/src/shared/async-guidance.js +3 -0
  84. package/dist/builtin-extensions/pi-subagents/src/shared/async-guidance.js.map +1 -0
  85. package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts +5 -0
  86. package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts.map +1 -1
  87. package/dist/builtin-extensions/pi-subagents/src/shared/types.js.map +1 -1
  88. package/dist/builtin-extensions/pi-subagents/src/slash/delegation-adapters.d.ts.map +1 -1
  89. package/dist/builtin-extensions/pi-subagents/src/slash/delegation-adapters.js.map +1 -1
  90. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.d.ts +7 -0
  91. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.d.ts.map +1 -1
  92. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.js +11 -7
  93. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.js.map +1 -1
  94. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.d.ts +4 -0
  95. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.d.ts.map +1 -1
  96. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.js +22 -23
  97. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.js.map +1 -1
  98. package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts +2 -0
  99. package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts.map +1 -1
  100. package/dist/builtin-extensions/pi-subagents/src/tui/render.js +237 -374
  101. package/dist/builtin-extensions/pi-subagents/src/tui/render.js.map +1 -1
  102. package/dist/core/customize.d.ts +2 -0
  103. package/dist/core/customize.d.ts.map +1 -1
  104. package/dist/core/customize.js +3 -0
  105. package/dist/core/customize.js.map +1 -1
  106. package/dist/core/settings-manager.d.ts +4 -0
  107. package/dist/core/settings-manager.d.ts.map +1 -1
  108. package/dist/core/settings-manager.js +11 -0
  109. package/dist/core/settings-manager.js.map +1 -1
  110. package/dist/core/subagent-spinner-setting.d.ts +6 -0
  111. package/dist/core/subagent-spinner-setting.d.ts.map +1 -0
  112. package/dist/core/subagent-spinner-setting.js +12 -0
  113. package/dist/core/subagent-spinner-setting.js.map +1 -0
  114. package/dist/core/subagent-spinner.d.ts +4 -0
  115. package/dist/core/subagent-spinner.d.ts.map +1 -0
  116. package/dist/core/subagent-spinner.js +6 -0
  117. package/dist/core/subagent-spinner.js.map +1 -0
  118. package/dist/modes/interactive/components/settings-selector.d.ts +4 -0
  119. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  120. package/dist/modes/interactive/components/settings-selector.js +73 -1
  121. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  122. package/dist/modes/interactive/extension-widget-order.d.ts +8 -0
  123. package/dist/modes/interactive/extension-widget-order.d.ts.map +1 -0
  124. package/dist/modes/interactive/extension-widget-order.js +37 -0
  125. package/dist/modes/interactive/extension-widget-order.js.map +1 -0
  126. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  127. package/dist/modes/interactive/interactive-mode.js +15 -22
  128. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  129. package/dist/node-runtime/{agent-session-services-75JKASCW.js → agent-session-services-C743TYQE.js} +4 -3
  130. package/dist/node-runtime/{builtin-extensions-X4JMM4ZS.js → builtin-extensions-JCOPAAB5.js} +2 -1
  131. package/dist/node-runtime/{chunk-QKFMBRAL.js → chunk-2BUAYZ7K.js} +94 -25
  132. package/dist/node-runtime/chunk-5ZH3ZFIZ.js +308 -0
  133. package/dist/node-runtime/{chunk-BBUVIEZB.js → chunk-A3KMVBZV.js} +10 -1
  134. package/dist/node-runtime/{chunk-K3646JTM.js → chunk-AWVD5IEY.js} +7 -307
  135. package/dist/node-runtime/{chunk-ELWEXVO5.js → chunk-GB2MGFLI.js} +11 -11
  136. package/dist/node-runtime/chunk-LISUTZS3.js +19 -0
  137. package/dist/node-runtime/{chunk-AL2FMKKM.js → chunk-PDNXVXMD.js} +12 -12
  138. package/dist/node-runtime/{chunk-46ECNOLF.js → chunk-SY2TFMLO.js} +57 -17
  139. package/dist/node-runtime/{chunk-HQCKFM2O.js → chunk-VGYZ3APQ.js} +3 -0
  140. package/dist/node-runtime/{chunk-4DJ6HEGH.js → chunk-VZR3NCM7.js} +3 -3
  141. package/dist/node-runtime/{chunk-AOFXZQKA.js → chunk-W3SILANP.js} +1 -1
  142. package/dist/node-runtime/{chunk-CBGB57XT.js → chunk-WLLDXJRT.js} +10 -0
  143. package/dist/node-runtime/{chunk-JYNNB7DU.js → chunk-XI77KVKA.js} +2 -2
  144. package/dist/node-runtime/{chunk-4CSFRBCN.js → chunk-Y5KOEMBH.js} +1 -1
  145. package/dist/node-runtime/{chunk-AROOY4BB.js → chunk-YMEAYRBE.js} +1 -1
  146. package/dist/node-runtime/{command-RBTRL55A.js → command-P4NYCJ2M.js} +1 -1
  147. package/dist/node-runtime/{customize-XEXL2DGQ.js → customize-LF5VST47.js} +1 -1
  148. package/dist/node-runtime/{gateway-L4ANRTVE.js → gateway-BM6NLOH4.js} +1 -1
  149. package/dist/node-runtime/index.js +13 -11
  150. package/dist/node-runtime/{interactive-mode-HPUNH7SV.js → interactive-mode-EVVBA64D.js} +9 -7
  151. package/dist/node-runtime/{lunr-cron-NNYTWTGF.js → lunr-cron-4VHP4E4B.js} +1 -1
  152. package/dist/node-runtime/main.js +11 -9
  153. package/dist/node-runtime/{package-manager-cli-7RKSZGEN.js → package-manager-cli-N37546V5.js} +5 -4
  154. package/dist/node-runtime/{pi-intercom-DDQMRNPJ.js → pi-intercom-NV2LW6X7.js} +34 -33
  155. package/dist/node-runtime/{pi-subagents-T5WMMLBB.js → pi-subagents-6MUIFNDM.js} +286 -345
  156. package/dist/node-runtime/rpc-entry.js +11 -9
  157. package/dist/node-runtime/{runtime-bridges-NJQERQ72.js → runtime-bridges-2VQTLPOZ.js} +2 -2
  158. package/dist/node-runtime/{settings-manager-GHPTUN7R.js → settings-manager-CUGAZWAB.js} +2 -1
  159. package/dist/node-runtime/{subagent-executor-SRFC26SJ.js → subagent-executor-MH4A7CCF.js} +14 -46
  160. package/dist/node-runtime/{update-cli-L3JIBH2U.js → update-cli-XTZMZGOL.js} +2 -1
  161. package/docs/features.md +6 -2
  162. package/docs/settings.md +2 -1
  163. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  164. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  165. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  166. package/examples/extensions/gondolin/package-lock.json +2 -2
  167. package/examples/extensions/gondolin/package.json +1 -1
  168. package/examples/extensions/sandbox/package-lock.json +2 -2
  169. package/examples/extensions/sandbox/package.json +1 -1
  170. package/examples/extensions/with-deps/package-lock.json +2 -2
  171. package/examples/extensions/with-deps/package.json +1 -1
  172. package/package.json +4 -4
@@ -6,7 +6,6 @@ import {
6
6
  ASYNC_DIR,
7
7
  DEFAULT_ARTIFACT_CONFIG,
8
8
  INTERCOM_DETACH_REQUEST_EVENT,
9
- MAX_WIDGET_JOBS,
10
9
  POLL_INTERVAL_MS,
11
10
  RESULTS_DIR,
12
11
  SLASH_RESULT_TYPE,
@@ -17,6 +16,7 @@ import {
17
16
  SLASH_SUBAGENT_UPDATE_EVENT,
18
17
  SLASH_TEXT_RESULT_TYPE,
19
18
  SUBAGENT_ASYNC_COMPLETE_EVENT,
19
+ SUBAGENT_ASYNC_GUIDANCE,
20
20
  SUBAGENT_ASYNC_STARTED_EVENT,
21
21
  SUBAGENT_CHILD_ENV,
22
22
  SUBAGENT_CONTROL_EVENT,
@@ -29,10 +29,10 @@ import {
29
29
  SUBAGENT_STEERING_NOTICE_EVENT,
30
30
  TEMP_ROOT_DIR,
31
31
  WIDGET_KEY,
32
- aggregateStepStatus,
33
32
  assertJsonSchemaObject,
34
33
  attachNestedChildrenToResultChildren,
35
34
  buildSubagentResultIntercomPayload,
35
+ childRowLabel,
36
36
  cleanupAllArtifactDirs,
37
37
  cleanupOldArtifacts,
38
38
  cleanupOldChainDirs,
@@ -49,7 +49,7 @@ import {
49
49
  formatDuration,
50
50
  formatModelSelection,
51
51
  formatNestedAggregate,
52
- formatParallelOutcome,
52
+ formatNestedResultLines,
53
53
  formatTokens,
54
54
  formatToolCall,
55
55
  formatUsage,
@@ -60,7 +60,9 @@ import {
60
60
  getSingleResultOutput,
61
61
  handleSubagentControlNotice,
62
62
  hasLiveNestedDescendants,
63
+ isAsyncSubagentExecution,
63
64
  listAsyncRuns,
65
+ normalizeAsyncLaunchConfig,
64
66
  normalizeParallelGroups,
65
67
  projectNestedRegistryForRoot,
66
68
  readStatus,
@@ -71,6 +73,7 @@ import {
71
73
  requestAsyncSteer,
72
74
  resolveAsyncRunLocation,
73
75
  resolveCurrentSessionId,
76
+ resolveSubagentRequestParams,
74
77
  resolveSubagentResultStatus,
75
78
  resolveSubagentRunId,
76
79
  resolveTurnBudgetConfig,
@@ -79,22 +82,26 @@ import {
79
82
  sanitizeChildDescription,
80
83
  sanitizeSummary,
81
84
  shortenPath,
85
+ subagentLaunchRunsAsync,
82
86
  summarizeAsyncStatus,
83
87
  updateAsyncJobNestedProjection,
84
88
  validateAcceptanceInput,
85
89
  validateExecutionAcceptance,
86
90
  validateToolBudgetConfig,
87
91
  writeAtomicJson
88
- } from "./chunk-46ECNOLF.js";
92
+ } from "./chunk-SY2TFMLO.js";
89
93
  import {
90
94
  createSubagentCancellation,
95
+ getSubagentSpinnerDefinition,
91
96
  registerSubagentCancellation
92
- } from "./chunk-BBUVIEZB.js";
97
+ } from "./chunk-A3KMVBZV.js";
98
+ import "./chunk-5ZH3ZFIZ.js";
93
99
  import "./chunk-25I2BHAA.js";
94
100
  import "./chunk-WKDK4C5P.js";
95
101
  import "./chunk-53YJI7JU.js";
96
102
  import "./chunk-KBKMCJDU.js";
97
103
  import "./chunk-CSFI6YXL.js";
104
+ import "./chunk-LISUTZS3.js";
98
105
  import "./chunk-FVDOXRUD.js";
99
106
  import "./chunk-AD6VXAO7.js";
100
107
  import "./chunk-6N22HULO.js";
@@ -177,7 +184,11 @@ function wrapPlainText(text, maxWidth) {
177
184
  }
178
185
  return lines;
179
186
  }
180
- var RUNNING_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"], STATIC_RUNNING_GLYPH = "\u25CF";
187
+ var STATIC_RUNNING_GLYPH = "\u25CF", SUBAGENT_PAINT_INTERVAL_MS = 80;
188
+ function selectedSubagentSpinner() {
189
+ let bridge = globalThis[/* @__PURE__ */ Symbol.for("@lunr/customize")];
190
+ return getSubagentSpinnerDefinition(bridge?.getSubagentSpinner?.() ?? "braille");
191
+ }
181
192
  function runningSeed(...values) {
182
193
  let seed;
183
194
  for (let value of values)
@@ -185,7 +196,14 @@ function runningSeed(...values) {
185
196
  return seed;
186
197
  }
187
198
  function runningGlyph(seed) {
188
- return seed === void 0 ? STATIC_RUNNING_GLYPH : RUNNING_FRAMES[Math.abs(seed) % RUNNING_FRAMES.length];
199
+ if (seed === void 0)
200
+ return STATIC_RUNNING_GLYPH;
201
+ let frames = selectedSubagentSpinner().frames;
202
+ return frames[Math.abs(seed) % frames.length];
203
+ }
204
+ function foregroundSpinnerFrame(timerFrame) {
205
+ let { interval } = selectedSubagentSpinner();
206
+ return Math.floor(Math.max(0, timerFrame) * SUBAGENT_PAINT_INTERVAL_MS / interval);
189
207
  }
190
208
  function progressRunningSeed(progress) {
191
209
  if (progress)
@@ -315,7 +333,8 @@ function formatCompactSubagentRow(theme, width, parts) {
315
333
  let stats = formatCompactRowStats(parts.tokens, parts.durationMs), body = [
316
334
  `${parts.prefix ?? ""}${parts.glyph} ${themeBold(theme, parts.description)}`,
317
335
  parts.modelBadge ? theme.fg("dim", parts.modelBadge) : "",
318
- theme.fg("dim", stats)
336
+ theme.fg("dim", stats),
337
+ parts.terminalStatus ? theme.fg("dim", parts.terminalStatus) : ""
319
338
  ].filter(Boolean).join(` ${theme.fg("dim", "\xB7")} `);
320
339
  return truncLine(body, width);
321
340
  }
@@ -353,6 +372,12 @@ function formatWidgetAgents(agents) {
353
372
  function widgetJobName(job) {
354
373
  return job.mode === "parallel" ? "parallel" : job.mode === "chain" ? "chain" : job.mode === "single" && job.agents?.length === 1 ? job.agents[0] : job.agents?.length ? formatWidgetAgents(job.agents) : job.mode ?? "subagent";
355
374
  }
375
+ function widgetActivity(job, now = Date.now()) {
376
+ let facts = [], snapshotNow = job.status === "running" ? now : job.updatedAt;
377
+ job.currentTool && job.currentToolStartedAt !== void 0 && snapshotNow !== void 0 ? facts.push(`${job.currentTool} ${formatDuration(Math.max(0, snapshotNow - job.currentToolStartedAt))}`) : job.currentTool && facts.push(job.currentTool), job.currentPath && facts.push(shortenPath(job.currentPath)), job.turnCount !== void 0 && facts.push(`${job.turnCount} turns`), job.toolCount !== void 0 && facts.push(`${job.toolCount} tools`);
378
+ let activity = buildLiveStatusLine(job, snapshotNow);
379
+ return activity && facts.length ? `${activity} \xB7 ${facts.join(" \xB7 ")}` : activity || (facts.length ? facts.join(" \xB7 ") : job.status === "running" ? "thinking\u2026" : job.status === "queued" ? "queued\u2026" : job.status === "paused" ? "Paused" : job.status === "stopped" ? "Stopped" : job.status === "failed" ? "Failed" : "Done");
380
+ }
356
381
  function widgetStepRunningSeed(step, fallbackIndex) {
357
382
  return runningSeed(fallbackIndex, step.index);
358
383
  }
@@ -365,14 +390,9 @@ function widgetStepsRunningSeed(steps) {
365
390
  function widgetJobRunningSeed(job) {
366
391
  return runningSeed(job.currentStep, job.runningSteps, widgetStepsRunningSeed(job.steps));
367
392
  }
368
- function widgetJobsRunningSeed(jobs) {
369
- let seed;
370
- for (let job of jobs)
371
- seed = runningSeed(seed, widgetJobRunningSeed(job));
372
- return seed;
373
- }
374
393
  function widgetAnimFrame(now = Date.now()) {
375
- return Math.floor(now / 80) % RUNNING_FRAMES.length;
394
+ let definition = selectedSubagentSpinner();
395
+ return Math.floor(now / definition.interval) % definition.frames.length;
376
396
  }
377
397
  function widgetStatusGlyph(job, theme, now = Date.now()) {
378
398
  return job.status === "running" ? theme.fg("accent", runningGlyph((widgetJobRunningSeed(job) ?? 0) + widgetAnimFrame(now))) : job.status === "queued" ? theme.fg("muted", "\u25E6") : job.status === "complete" ? theme.fg("success", "\u2713") : job.status === "paused" || job.status === "stopped" ? theme.fg("warning", "\u25A0") : theme.fg("error", "\u2717");
@@ -383,48 +403,6 @@ function widgetStepGlyph(status, theme, seed) {
383
403
  function widgetStepStatus(status, theme) {
384
404
  return status === "running" ? theme.fg("accent", "running") : status === "complete" || status === "completed" ? theme.fg("success", "complete") : status === "failed" ? theme.fg("error", "failed") : status === "paused" ? theme.fg("warning", "paused") : status === "stopped" ? theme.fg("warning", "stopped") : theme.fg("dim", status);
385
405
  }
386
- function widgetStepActivity(step, snapshotNow) {
387
- let facts = [];
388
- step.currentTool && step.currentToolStartedAt !== void 0 && snapshotNow !== void 0 ? facts.push(`${step.currentTool} ${formatDuration(Math.max(0, snapshotNow - step.currentToolStartedAt))}`) : step.currentTool && facts.push(step.currentTool), step.currentPath && facts.push(shortenPath(step.currentPath)), step.turnCount !== void 0 && facts.push(`${step.turnCount} turns`), step.toolCount !== void 0 && facts.push(`${step.toolCount} tools`), step.tokens?.total && facts.push(formatTokenStat(step.tokens.total));
389
- let activity = buildLiveStatusLine(step, snapshotNow);
390
- return activity && facts.length ? `${activity} \xB7 ${facts.join(" \xB7 ")}` : activity || facts.join(" \xB7 ");
391
- }
392
- function widgetChainDetails(job, theme, expanded = !1, width = getTermWidth()) {
393
- if (!job.steps?.length)
394
- return [];
395
- let total = job.chainStepCount ?? job.steps.length, lines = [];
396
- for (let span of buildAsyncChainStepSpans(total, job.steps.length, job.parallelGroups)) {
397
- let steps = job.steps.slice(span.start, span.start + span.count);
398
- if (span.isParallel) {
399
- let status = aggregateStepStatus(steps);
400
- lines.push(` ${widgetStepGlyph(status, theme, widgetStepsRunningSeed(steps))} Step ${span.stepIndex + 1}/${total}: ${themeBold(theme, "parallel group")} ${theme.fg("dim", "\xB7")} ${theme.fg("dim", formatParallelOutcome(steps, span.count))}`);
401
- continue;
402
- }
403
- let step = steps[0];
404
- if (!step) {
405
- lines.push(` ${theme.fg("dim", `\u25E6 Step ${span.stepIndex + 1}/${total}: pending`)}`);
406
- continue;
407
- }
408
- lines.push(...foregroundStyleWidgetStepLines(job, theme, step, "Step", span.stepIndex + 1, total, expanded, width));
409
- }
410
- return lines;
411
- }
412
- function widgetParallelAgentDetails(job, theme, expanded = !1, width = getTermWidth()) {
413
- if (!job.steps?.length)
414
- return [];
415
- if (job.mode !== "parallel" && job.mode !== "chain")
416
- return [];
417
- if (job.mode === "chain" && !job.activeParallelGroup && job.parallelGroups?.length)
418
- return widgetChainDetails(job, theme, expanded, width);
419
- let total = job.stepsTotal ?? job.steps.length, lines = [];
420
- for (let [index, step] of job.steps.entries()) {
421
- let marker = index === job.steps.length - 1 ? "\u2514" : "\u251C", activity = widgetStepActivity(step, job.updatedAt), itemTitle = job.mode === "parallel" || job.activeParallelGroup ? "Agent" : "Step", modelDisplay = modelThinkingBadge(theme, step.model, step.thinking, step.modelSelection);
422
- lines.push(` ${theme.fg("dim", `${marker} ${widgetStepGlyph(step.status, theme, widgetStepRunningSeed(step, index))} ${itemTitle} ${index + 1}/${total}: ${step.agent} \xB7 ${widgetStepStatus(step.status, theme)}${modelDisplay}${activity ? ` \xB7 ${activity}` : ""}`)}`);
423
- for (let nestedLine of formatNestedWidgetLines(step.children, theme, width, expanded, job.updatedAt, expanded ? 8 : 1))
424
- lines.push(` ${nestedLine}`);
425
- }
426
- return lines;
427
- }
428
406
  function parseParallelGroupAgentCount(label) {
429
407
  if (!label || !label.startsWith("[") || !label.endsWith("]"))
430
408
  return;
@@ -460,24 +438,16 @@ function buildChainStepSpans(details) {
460
438
  function isChainParallelGroupActive(details) {
461
439
  return details.mode !== "chain" || details.currentStepIndex === void 0 ? !1 : buildChainStepSpans(details).some((span) => span.stepIndex === details.currentStepIndex && span.isParallel);
462
440
  }
463
- function buildAsyncChainStepSpans(total, stepCount, parallelGroups = []) {
464
- let spans = [], flatIndex = 0;
465
- for (let stepIndex = 0; stepIndex < total; stepIndex++) {
466
- let group = parallelGroups.find((candidate) => candidate.stepIndex === stepIndex);
467
- if (group) {
468
- spans.push({ stepIndex, start: group.start, count: group.count, isParallel: !0 }), flatIndex = Math.max(flatIndex, group.start + group.count);
469
- continue;
470
- }
471
- spans.push({ stepIndex, start: flatIndex, count: flatIndex < stepCount ? 1 : 0, isParallel: !1 }), flatIndex++;
472
- }
473
- return spans;
474
- }
475
441
  function isDoneResult(result2) {
476
442
  let status = result2.progress?.status;
477
443
  return status === "completed" ? !0 : status === "running" || status === "pending" || result2.interrupted || result2.detached ? !1 : result2.exitCode === 0;
478
444
  }
479
445
  function workflowGraphHasStatus(details, statuses) {
480
- return details.workflowGraph?.nodes.some((node) => statuses.includes(node.status)) ?? !1;
446
+ let matches = (nodes) => nodes.some((node) => statuses.includes(node.status) || matches(node.children ?? []));
447
+ return matches(details.workflowGraph?.nodes ?? []);
448
+ }
449
+ function resultAtFlatIndex(details, flatIndex) {
450
+ return details.results.find((result2, arrayIndex) => (result2.progress?.index ?? result2.progressSummary?.index ?? arrayIndex) === flatIndex);
481
451
  }
482
452
  function buildChainRenderEntries(details, label) {
483
453
  if (details.mode !== "chain" || !label.hasParallelInChain || label.showActiveGroupOnly)
@@ -495,13 +465,17 @@ function buildChainRenderEntries(details, label) {
495
465
  });
496
466
  continue;
497
467
  }
498
- for (let index = span.start; index < span.start + span.count; index++)
468
+ for (let index = span.start; index < span.start + span.count; index++) {
469
+ let workflowStep = details.workflowGraph?.nodes.find((node) => node.stepIndex === span.stepIndex), workflowNode = workflowStep?.children?.find((node) => node.flatIndex === index) ?? (workflowStep?.flatIndex === index ? workflowStep : void 0), result2 = resultAtFlatIndex(details, index);
499
470
  entries.push({
500
471
  kind: "result",
501
472
  resultIndex: index,
502
473
  rowNumber: index + 1,
503
- agentName: details.results[index]?.agent ?? details.chainAgents?.[span.stepIndex] ?? `step-${span.stepIndex + 1}`
474
+ agentName: result2?.agent ?? workflowNode?.label ?? details.chainAgents?.[span.stepIndex] ?? `step-${span.stepIndex + 1}`,
475
+ status: workflowNode?.status ?? span.status,
476
+ error: workflowNode?.error ?? span.error
504
477
  });
478
+ }
505
479
  }
506
480
  return entries;
507
481
  }
@@ -566,15 +540,6 @@ function resultRowLabel(details, label, resultIndex, stepNumber) {
566
540
  }
567
541
  return label.itemTitle === "Agent" ? `Agent ${label.activeParallelGroup ? Math.max(1, stepNumber - label.groupStartIndex) : stepNumber}/${label.totalCount}` : `Step ${stepNumber}`;
568
542
  }
569
- function widgetStepStats(theme, step, now = Date.now()) {
570
- let running = step.status === "running", durationMs = step.durationMs !== void 0 ? step.durationMs + (running && step.lastActivityAt !== void 0 ? Math.max(0, now - step.lastActivityAt) : 0) : step.startedAt !== void 0 ? Math.max(0, (running ? now : step.endedAt ?? step.lastActivityAt ?? now) - step.startedAt) : void 0;
571
- return statJoin(theme, [
572
- step.turnCount !== void 0 ? `${step.turnCount} turns` : "",
573
- step.toolCount !== void 0 ? formatToolUseStat(step.toolCount) : "",
574
- step.tokens?.total ? formatTokenStat(step.tokens.total) : "",
575
- durationMs !== void 0 ? `${running ? "" : "ran for "}${formatDuration(durationMs)}` : ""
576
- ]);
577
- }
578
543
  function modelThinkingBadge(theme, model, thinking, selection) {
579
544
  let label = formatModelSelection(selection, model, thinking);
580
545
  return label ? theme.fg("dim", ` (${label})`) : "";
@@ -639,22 +604,15 @@ function formatNestedWidgetLines(children, theme, width, expanded, snapshotNow,
639
604
  };
640
605
  return append(children, 0, ""), lines.map((line) => truncLine(line, width));
641
606
  }
642
- function foregroundStyleWidgetStepLines(job, theme, step, itemTitle, index, total, expanded, width) {
643
- let status = widgetStepStatus(step.status, theme), stats = widgetStepStats(theme, step), modelDisplay = modelThinkingBadge(theme, step.model, step.thinking, step.modelSelection), lines = [` ${widgetStepGlyph(step.status, theme, widgetStepRunningSeed(step, index - 1))} ${itemTitle} ${index}/${total}: ${themeBold(theme, step.agent)} ${theme.fg("dim", "\xB7")} ${status}${modelDisplay}${stats ? ` ${theme.fg("dim", "\xB7")} ${stats}` : ""}`], activity = widgetStepActivityLine(step, width, expanded, job.updatedAt);
644
- activity && lines.push(` ${theme.fg("dim", `\u23BF ${activity}`)}`);
645
- for (let nestedLine of formatNestedWidgetLines(step.children, theme, width, expanded, job.updatedAt))
646
- lines.push(` ${nestedLine}`);
647
- if (step.status === "running" && (expanded || lines.push(` ${theme.fg("accent", liveDetailHintText())}`), expanded)) {
648
- let liveStatus = buildLiveStatusLine(step, job.updatedAt);
649
- liveStatus && liveStatus !== activity && lines.push(` ${theme.fg("accent", liveStatus)}`);
650
- for (let tool of step.recentTools?.slice(-3) ?? []) {
651
- let maxArgsLen = Math.max(40, width - 30), argsPreview = tool.args.length <= maxArgsLen ? tool.args : `${tool.args.slice(0, maxArgsLen)}...`;
652
- lines.push(` ${theme.fg("dim", `${tool.tool}${argsPreview ? `: ${argsPreview}` : ""}`)}`);
653
- }
654
- for (let line of step.recentOutput?.slice(-5) ?? [])
655
- lines.push(` ${theme.fg("dim", line)}`);
656
- }
657
- return lines;
607
+ function compactTerminalStatus(status) {
608
+ if (status === "failed")
609
+ return "failed";
610
+ if (status === "paused")
611
+ return "paused";
612
+ if (status === "stopped")
613
+ return "stopped";
614
+ if (status === "detached")
615
+ return "detached";
658
616
  }
659
617
  function compactJobProgress(job, step, now = Date.now()) {
660
618
  let running = (step?.status ?? job.status) === "running", tokens = step?.tokens?.total ?? job.totalTokens?.total ?? 0;
@@ -675,14 +633,6 @@ function compactJobLead(job, step) {
675
633
  task: step?.description ?? step?.agent
676
634
  }) || widgetJobName(job);
677
635
  }
678
- function activeJobStep(job) {
679
- let steps = job.steps ?? [];
680
- return steps.find((step) => step.status === "running") ?? steps.find((step) => step.status === "pending" || step.status === "queued") ?? steps[steps.length - 1];
681
- }
682
- function compactJobChildRows(job, theme, width, now = Date.now()) {
683
- let steps = job.steps ?? [];
684
- return steps.length <= 1 ? compactJobLines(job, steps[0], theme, width, now) : steps.flatMap((step) => compactJobLines(job, step, theme, width, now));
685
- }
686
636
  function compactJobLines(job, step, theme, width, now = Date.now()) {
687
637
  let running = (step?.status ?? job.status) === "running", lead = compactJobLead(job, step), modelBadge = formatCompactModelBadge(step?.modelSelection, step?.model), glyph = step ? widgetStepGlyph(step.status, theme, running ? (widgetStepRunningSeed(step, step.index) ?? 0) + widgetAnimFrame(now) : widgetStepRunningSeed(step, step.index)) : widgetStatusGlyph(job, theme, now), progress = compactJobProgress(job, step, now);
688
638
  return [formatCompactSubagentRow(theme, width, {
@@ -690,16 +640,10 @@ function compactJobLines(job, step, theme, width, now = Date.now()) {
690
640
  description: lead,
691
641
  modelBadge,
692
642
  tokens: progress.tokens,
693
- durationMs: progress.durationMs
643
+ durationMs: progress.durationMs,
644
+ terminalStatus: compactTerminalStatus(step?.status ?? job.status)
694
645
  })];
695
646
  }
696
- function buildSingleWidgetLines(job, theme, width, _expanded, now = Date.now()) {
697
- let steps = job.steps ?? [];
698
- return steps.length <= 1 ? compactJobLines(job, steps[0], theme, width, now) : steps.flatMap((step) => compactJobLines(job, step, theme, width, now));
699
- }
700
- function compactSingleWidgetLines(job, theme, width, now = Date.now()) {
701
- return buildSingleWidgetLines(job, theme, width, !1, now);
702
- }
703
647
  var RESERVED_NON_WIDGET_ROWS = 19, widgetLayoutSession;
704
648
  function resetWidgetLayoutSession() {
705
649
  widgetLayoutSession = void 0;
@@ -717,20 +661,6 @@ function currentTerminalColumns() {
717
661
  function widgetSessionMatches(expanded) {
718
662
  return widgetLayoutSession?.expanded === expanded && widgetLayoutSession.rows === currentTerminalRows() && widgetLayoutSession.columns === currentTerminalColumns();
719
663
  }
720
- function widgetHeaderCounts(jobs) {
721
- return {
722
- running: jobs.filter((job) => job.status === "running"),
723
- queued: jobs.filter((job) => job.status === "queued"),
724
- complete: jobs.filter((job) => job.status === "complete"),
725
- failed: jobs.filter((job) => job.status === "failed"),
726
- paused: jobs.filter((job) => job.status === "paused"),
727
- stopped: jobs.filter((job) => job.status === "stopped")
728
- };
729
- }
730
- function buildSingleLineWidgetLines(jobs, theme, width) {
731
- let counts = widgetHeaderCounts(jobs), hasActive = counts.running.length > 0 || counts.queued.length > 0, glyph = counts.running.length > 0 ? runningGlyph((widgetJobsRunningSeed(counts.running) ?? 0) + widgetAnimFrame()) : hasActive ? "\u25CF" : "\u25CB", parts = [];
732
- return counts.running.length > 0 && parts.push(`${counts.running.length}/${jobs.length} running`), counts.queued.length > 0 && parts.push(`${counts.queued.length} queued`), counts.failed.length > 0 && parts.push(`${counts.failed.length} failed`), counts.stopped.length > 0 && parts.push(`${counts.stopped.length} stopped`), counts.paused.length > 0 && parts.push(`${counts.paused.length} paused`), !hasActive && counts.complete.length > 0 && parts.push(`${counts.complete.length}/${jobs.length} done`), [truncLine(`${theme.fg(hasActive ? "accent" : "dim", glyph)} ${theme.fg(hasActive ? "accent" : "dim", "subagents")} (${parts.join(", ") || `${jobs.length} total`})`, width)];
733
- }
734
664
  function orderedWidgetJobs(jobs) {
735
665
  return [
736
666
  ...jobs.filter((job) => job.status === "running"),
@@ -738,68 +668,6 @@ function orderedWidgetJobs(jobs) {
738
668
  ...jobs.filter((job) => job.status !== "running" && job.status !== "queued")
739
669
  ];
740
670
  }
741
- function progressiveJobKey(job) {
742
- return job.asyncId;
743
- }
744
- function isProgressiveActiveJob(job) {
745
- return job?.status === "running" || job?.status === "queued";
746
- }
747
- function selectProgressiveJobKeys(jobs, previousKeys, bodyRows) {
748
- if (bodyRows <= 0)
749
- return [];
750
- let jobsByKey = new Map(jobs.map((job) => [progressiveJobKey(job), job])), selected = [], append = (key) => {
751
- selected.includes(key) || !jobsByKey.has(key) || selected.push(key);
752
- };
753
- for (let key of previousKeys)
754
- if (isProgressiveActiveJob(jobsByKey.get(key)) && (append(key), selected.length >= bodyRows))
755
- return selected;
756
- for (let job of orderedWidgetJobs(jobs)) {
757
- if (!isProgressiveActiveJob(job))
758
- continue;
759
- let key = progressiveJobKey(job);
760
- if (append(key), selected.length >= bodyRows)
761
- break;
762
- }
763
- if (selected.length >= bodyRows)
764
- return selected;
765
- for (let key of previousKeys)
766
- if (!isProgressiveActiveJob(jobsByKey.get(key)) && (append(key), selected.length >= bodyRows))
767
- return selected;
768
- for (let job of orderedWidgetJobs(jobs)) {
769
- let key = progressiveJobKey(job);
770
- if (append(key), selected.length >= bodyRows)
771
- break;
772
- }
773
- return selected;
774
- }
775
- function progressiveHeaderLine(jobs, theme, width) {
776
- let counts = widgetHeaderCounts(jobs), hasActive = counts.running.length > 0 || counts.queued.length > 0, glyph = counts.running.length > 0 ? runningGlyph((widgetJobsRunningSeed(counts.running) ?? 0) + widgetAnimFrame()) : hasActive ? "\u25CF" : "\u25CB", parts = [];
777
- return counts.running.length > 0 && parts.push(formatAgentRunningLabel(counts.running.length)), counts.queued.length > 0 && parts.push(`${counts.queued.length} queued`), hasActive || (counts.failed.length > 0 && parts.push(`${counts.failed.length} failed`), counts.stopped.length > 0 && parts.push(`${counts.stopped.length} stopped`), counts.paused.length > 0 && parts.push(`${counts.paused.length} paused`), counts.complete.length > 0 && parts.push(`${counts.complete.length}/${jobs.length} done`)), truncLine(`${theme.fg(hasActive ? "accent" : "dim", glyph)} ${theme.fg(hasActive ? "accent" : "dim", "Async agents")} ${theme.fg("dim", "\xB7")} ${theme.fg("dim", parts.join(", ") || `${jobs.length} total`)}`, width);
778
- }
779
- function progressiveJobLine(job, theme, width, now = Date.now()) {
780
- let row = compactJobLines(job, activeJobStep(job), theme, Math.max(1, width - 2), now)[0] ?? "";
781
- return row ? ` ${row}` : "";
782
- }
783
- function progressiveHiddenLine(hiddenJobs, theme, width) {
784
- let counts = widgetHeaderCounts(hiddenJobs), parts = [];
785
- counts.running.length > 0 && parts.push(`${counts.running.length} running`), counts.queued.length > 0 && parts.push(`${counts.queued.length} queued`);
786
- let finished = counts.complete.length + counts.failed.length + counts.paused.length + counts.stopped.length;
787
- return finished > 0 && parts.push(`${finished} finished`), truncLine(theme.fg("dim", ` +${hiddenJobs.length} more${parts.length ? ` (${parts.join(", ")})` : ""}`), width);
788
- }
789
- function buildProgressiveWidgetLines(jobs, theme, width, lockedRows, previousKeys) {
790
- let rowCount = Math.max(1, lockedRows);
791
- if (rowCount === 1)
792
- return { lines: buildSingleLineWidgetLines(jobs, theme, width), visibleJobKeys: [] };
793
- let bodyRows = rowCount - 1, visibleJobKeys = selectProgressiveJobKeys(jobs, previousKeys, bodyRows), jobsByKey = new Map(jobs.map((job) => [progressiveJobKey(job), job])), visibleJobs = visibleJobKeys.map((key) => jobsByKey.get(key)).filter((job) => !!job), hiddenJobs = jobs.filter((job) => !visibleJobKeys.includes(progressiveJobKey(job)));
794
- hiddenJobs.length > 0 && visibleJobs.length >= bodyRows && bodyRows > 0 && (visibleJobs = visibleJobs.slice(0, bodyRows - 1), visibleJobKeys = visibleJobs.map(progressiveJobKey), hiddenJobs = jobs.filter((job) => !visibleJobKeys.includes(progressiveJobKey(job))));
795
- let lines = [
796
- progressiveHeaderLine(jobs, theme, width),
797
- ...visibleJobs.map((job) => progressiveJobLine(job, theme, width))
798
- ];
799
- for (hiddenJobs.length > 0 && lines.length < rowCount && lines.push(progressiveHiddenLine(hiddenJobs, theme, width)); lines.length < rowCount; )
800
- lines.push(" ");
801
- return { lines: lines.slice(0, rowCount), visibleJobKeys };
802
- }
803
671
  function collapsedWidgetLineBudget(rows) {
804
672
  return Math.max(10, Math.min(14, Math.floor(rows * 0.35)));
805
673
  }
@@ -810,58 +678,41 @@ function fitWidgetLineBudget(lines, theme, width, expanded) {
810
678
  let visibleLines = Math.max(1, budget - 1), hiddenCount = lines.length - visibleLines, hint = expanded ? `\u2026 ${hiddenCount} live-detail lines hidden` : `\u2026 ${hiddenCount} lines hidden \xB7 ${liveDetailKeyText()} expands`;
811
679
  return [...lines.slice(0, visibleLines), truncLine(theme.fg("dim", hint), width)];
812
680
  }
813
- function fitAdaptiveWidgetLines(jobs, lines, theme, width, expanded) {
681
+ function fitAdaptiveWidgetLines(_jobs, lines, theme, width, expanded) {
814
682
  if (expanded)
815
683
  return resetWidgetLayoutSession(), fitWidgetLineBudget(lines, theme, width, !0);
816
- let hasMatchingSession = widgetSessionMatches(expanded), rows = currentTerminalRows(), columns = currentTerminalColumns(), availableRows = estimateAvailableWidgetRows();
817
- if (hasMatchingSession && widgetLayoutSession?.tier === "single-line")
818
- return buildSingleLineWidgetLines(jobs, theme, width);
819
- if (hasMatchingSession && widgetLayoutSession?.tier === "progressive" && widgetLayoutSession.lockedRows !== void 0) {
820
- let rendered2 = buildProgressiveWidgetLines(jobs, theme, width, widgetLayoutSession.lockedRows, widgetLayoutSession.visibleJobKeys);
821
- return widgetLayoutSession.visibleJobKeys = rendered2.visibleJobKeys, rendered2.lines;
822
- }
684
+ let rows = currentTerminalRows(), columns = currentTerminalColumns(), availableRows = estimateAvailableWidgetRows();
823
685
  if (lines.length <= availableRows)
824
- return widgetLayoutSession = { expanded, rows, columns, tier: "full", visibleJobKeys: [] }, fitWidgetLineBudget(lines, theme, width, !1);
825
- if (availableRows <= 2)
826
- return widgetLayoutSession = { expanded, rows, columns, tier: "single-line", visibleJobKeys: [] }, buildSingleLineWidgetLines(jobs, theme, width);
827
- let lockedRows = Math.min(availableRows, collapsedWidgetLineBudget(rows)), rendered = buildProgressiveWidgetLines(jobs, theme, width, lockedRows, []);
828
- return widgetLayoutSession = { expanded, rows, columns, tier: "progressive", lockedRows, visibleJobKeys: rendered.visibleJobKeys }, rendered.lines;
686
+ return widgetLayoutSession = { expanded, rows, columns, tier: "full" }, fitWidgetLineBudget(lines, theme, width, !1);
687
+ let lockedRows = widgetSessionMatches(expanded) && widgetLayoutSession?.tier === "progressive" ? widgetLayoutSession.lockedRows ?? 1 : Math.max(1, Math.min(availableRows, collapsedWidgetLineBudget(rows)));
688
+ if (widgetLayoutSession = { expanded, rows, columns, tier: "progressive", lockedRows }, lockedRows === 1)
689
+ return lines.slice(0, 1);
690
+ let visibleCount = Math.max(1, lockedRows - 1), visible = lines.slice(0, visibleCount), hidden = lines.length - visible.length;
691
+ for (hidden > 0 && visible.push(truncLine(theme.fg("dim", `+${hidden} more`), width)); visible.length < lockedRows; )
692
+ visible.push(" ");
693
+ return visible.slice(0, lockedRows);
694
+ }
695
+ function widgetExpandedDiagnostics(job, step, index, theme, width, now) {
696
+ let lines = [], status = step?.status ?? job.status, runLabel = step ? `${job.asyncId}:${step.index ?? index}` : job.asyncId;
697
+ lines.push(truncLine(theme.fg("dim", ` \u23BF run ${runLabel} \xB7 ${status}`), width));
698
+ let error = step?.error;
699
+ error && lines.push(truncLine(theme.fg("error", ` ${error}`), width));
700
+ let snapshotNow = status === "running" ? now : step?.endedAt ?? job.updatedAt, activity = step ? widgetStepActivityLine(step, Math.max(1, width - 4), !0, snapshotNow) : widgetActivity(job, now);
701
+ activity && lines.push(truncLine(theme.fg("dim", ` ${activity}`), width));
702
+ for (let tool of step?.recentTools?.slice(-3) ?? [])
703
+ lines.push(truncLine(theme.fg("dim", ` ${tool.tool}${tool.args ? `: ${tool.args}` : ""}`), width));
704
+ for (let output of step?.recentOutput?.slice(-5) ?? [])
705
+ lines.push(truncLine(theme.fg("dim", ` ${output}`), width));
706
+ for (let nestedLine of formatNestedWidgetLines(step?.children ?? job.nestedChildren, theme, width, !0, snapshotNow))
707
+ lines.push(truncLine(` ${nestedLine}`, width));
708
+ return lines;
829
709
  }
830
710
  function buildWidgetLines(jobs, theme, width = getTermWidth(), expanded = !1, now = Date.now()) {
831
- if (jobs.length === 0)
832
- return [];
833
- if (jobs.length === 1)
834
- return buildSingleWidgetLines(jobs[0], theme, width, expanded, now);
835
- let running = jobs.filter((job) => job.status === "running"), queued = jobs.filter((job) => job.status === "queued"), finished = jobs.filter((job) => job.status !== "running" && job.status !== "queued"), lines = [], hasActive = running.length > 0 || queued.length > 0, headerGlyph = running.length > 0 ? runningGlyph((widgetJobsRunningSeed(running) ?? 0) + widgetAnimFrame(now)) : hasActive ? "\u25CF" : "\u25CB";
836
- lines.push(truncLine(`${theme.fg(hasActive ? "accent" : "dim", headerGlyph)} ${theme.fg(hasActive ? "accent" : "dim", "Async agents")} ${theme.fg("dim", "\xB7 background")}`, width));
837
- let items = [], hiddenRunning = 0, hiddenFinished = 0, queuedSummaryShown = !1, slots = MAX_WIDGET_JOBS;
838
- for (let job of running) {
839
- if (slots <= 0) {
840
- hiddenRunning++;
841
- continue;
842
- }
843
- let row = compactJobChildRows(job, theme, Math.max(1, width - 3), now);
844
- items.push(expanded ? [...row, ...widgetParallelAgentDetails(job, theme, !0, width)] : row), slots--;
845
- }
846
- queued.length > 0 && slots > 0 && (items.push([`${theme.fg("muted", "\u25E6")} ${theme.fg("dim", `${queued.length} queued`)}`]), queuedSummaryShown = !0, slots--);
847
- for (let job of finished) {
848
- if (slots <= 0) {
849
- hiddenFinished++;
850
- continue;
851
- }
852
- let row = compactJobChildRows(job, theme, Math.max(1, width - 3), now);
853
- items.push(expanded ? [...row, ...widgetParallelAgentDetails(job, theme, !0, width)] : row), slots--;
854
- }
855
- let hiddenQueued = queued.length > 0 && !queuedSummaryShown ? queued.length : 0, hiddenTotal = hiddenRunning + hiddenFinished + hiddenQueued;
856
- if (hiddenTotal > 0) {
857
- let parts = [];
858
- hiddenRunning > 0 && parts.push(`${hiddenRunning} running`), hiddenQueued > 0 && parts.push(`${hiddenQueued} queued`), hiddenFinished > 0 && parts.push(`${hiddenFinished} finished`), items.push([theme.fg("dim", `+${hiddenTotal} more (${parts.join(", ")})`)]);
859
- }
860
- for (let i = 0; i < items.length; i++) {
861
- let item = items[i], last = i === items.length - 1, branch = last ? "\u2514\u2500" : "\u251C\u2500", continuation = last ? " " : "\u2502 ";
862
- lines.push(truncLine(`${theme.fg("dim", branch)} ${item[0]}`, width));
863
- for (let detail of item.slice(1))
864
- lines.push(truncLine(`${theme.fg("dim", continuation)} ${detail}`, width));
711
+ let lines = [];
712
+ for (let job of orderedWidgetJobs(jobs)) {
713
+ let steps = job.steps?.length ? job.steps : job.agents?.length ? job.agents.map((agent, index) => ({ agent, description: agent, status: job.status, index })) : [void 0];
714
+ for (let [index, step] of steps.entries())
715
+ lines.push(...compactJobLines(job, step, theme, width, now)), expanded && lines.push(...widgetExpandedDiagnostics(job, step, index, theme, width, now));
865
716
  }
866
717
  return lines;
867
718
  }
@@ -899,7 +750,7 @@ var activeWidget, SubagentAsyncWidget = class {
899
750
  startTimer() {
900
751
  this.timer || (this.timer = setInterval(() => {
901
752
  this.disposed || (this.invalidate(), this.requestRender?.());
902
- }, 80), this.timer.unref?.());
753
+ }, SUBAGENT_PAINT_INTERVAL_MS), this.timer.unref?.());
903
754
  }
904
755
  stopTimer() {
905
756
  this.timer && (clearInterval(this.timer), this.timer = void 0);
@@ -916,7 +767,7 @@ var activeWidget, SubagentAsyncWidget = class {
916
767
  return [];
917
768
  if (this.cachedLines && this.cachedWidth === width && !this.hasRunning())
918
769
  return this.cachedLines;
919
- let now = this.nowFn(), innerWidth = Math.max(1, width - 2), lines = this.expanded ? buildWidgetLines(this.jobs, theme, innerWidth, !0, now) : this.jobs.length === 1 ? compactSingleWidgetLines(this.jobs[0], theme, innerWidth, now) : buildWidgetLines(this.jobs, theme, innerWidth, !1, now), padded = fitAdaptiveWidgetLines(this.jobs, lines, theme, innerWidth, this.expanded).map((line) => {
770
+ let now = this.nowFn(), innerWidth = Math.max(1, width - 2), lines = buildWidgetLines(this.jobs, theme, innerWidth, this.expanded, now), padded = fitAdaptiveWidgetLines(this.jobs, lines, theme, innerWidth, this.expanded).map((line) => {
920
771
  let withPad = ` ${line}`, vis = visibleWidth(withPad);
921
772
  return withPad + " ".repeat(Math.max(0, width - vis));
922
773
  });
@@ -941,65 +792,71 @@ function renderWidget(ctx, jobs) {
941
792
  let widget = new SubagentAsyncWidget(jobs, void 0, { expanded, requestRender });
942
793
  activeWidget = widget, ctx.ui.setWidget(WIDGET_KEY, (_tui, theme) => (widget.setTheme(theme), widget));
943
794
  }
795
+ function compactResultTerminalStatus(result2) {
796
+ if (result2.stopped)
797
+ return "stopped";
798
+ if (result2.detached)
799
+ return "detached";
800
+ if (result2.interrupted)
801
+ return "paused";
802
+ if (result2.exitCode !== 0)
803
+ return "failed";
804
+ }
944
805
  function renderSingleCompact(d, r, theme, frame) {
945
- let output = r.truncation?.text || getSingleResultOutput(r), progress = r.progress || r.progressSummary, isRunning = r.progress?.status === "running", c = new Container(), width = getTermWidth() - 4, lead = compactRowLead({ description: r.description ?? r.agent, task: r.task }), modelBadge = formatCompactModelBadge(r.modelSelection ?? progress?.modelSelection, r.model ?? progress?.model);
946
- return c.addChild(animatedLine((f, now) => formatCompactSubagentRow(theme, width, {
947
- glyph: resultGlyph(r, output, theme, isRunning, void 0, f),
806
+ let output = r.truncation?.text || getSingleResultOutput(r), progress = r.progress || r.progressSummary, isRunning = r.progress?.status === "running", width = getTermWidth() - 4, lead = compactRowLead({ description: r.description ?? r.agent, task: r.task }), modelBadge = formatCompactModelBadge(r.modelSelection ?? progress?.modelSelection, r.model ?? progress?.model);
807
+ return animatedLine((animationTick, now) => formatCompactSubagentRow(theme, width, {
808
+ glyph: resultGlyph(r, output, theme, isRunning, void 0, foregroundSpinnerFrame(animationTick)),
948
809
  description: lead,
949
810
  modelBadge,
950
811
  tokens: compactResultTokens(r),
951
- durationMs: liveDurationMs(progress, isRunning, now)
952
- }), frame, isRunning)), !isRunning && (r.exitCode !== 0 || r.interrupted || r.detached || r.stopped) && c.addChild(new Text(truncLine(theme.fg(r.exitCode !== 0 ? "error" : "dim", ` \u23BF ${resultStatusLine(r, output)}`), width), 0, 0)), c;
812
+ durationMs: liveDurationMs(progress, isRunning, now),
813
+ terminalStatus: compactResultTerminalStatus(r)
814
+ }), frame, isRunning);
815
+ }
816
+ function progressStatusGlyph(progress, theme, frame) {
817
+ return !progress || progress.status === "pending" ? theme.fg("muted", "\u25E6") : progress.status === "running" ? theme.fg("accent", runningGlyph((progressRunningSeed(progress) ?? 0) + (frame ?? 0))) : progress.status === "completed" ? theme.fg("success", "\u2713") : progress.status === "failed" ? theme.fg("error", "\u2717") : theme.fg("warning", "\u25A0");
818
+ }
819
+ function flattenCompactWorkflowNodes(nodes) {
820
+ let rows = [];
821
+ for (let node of nodes)
822
+ node.children?.length ? rows.push(...flattenCompactWorkflowNodes(node.children)) : rows.push(node);
823
+ return rows;
824
+ }
825
+ function compactForegroundEntries(d) {
826
+ let workflowNodes = flattenCompactWorkflowNodes(d.workflowGraph?.nodes ?? []);
827
+ if (workflowNodes.length === 0) {
828
+ let progressCount2 = d.progress?.reduce((count2, entry) => Math.max(count2, entry.index + 1), 0) ?? 0, chainCount = d.mode === "chain" ? buildChainStepSpans(d).reduce((count2, span) => Math.max(count2, span.start + span.count), 0) : 0, count = Math.max(d.results.length, progressCount2, d.chainChildren?.length ?? 0, d.chainAgents?.length ?? 0, chainCount);
829
+ return Array.from({ length: count }, (_, flatIndex) => ({ flatIndex }));
830
+ }
831
+ let entries = workflowNodes.map((node) => ({ flatIndex: node.flatIndex, node })), seen = new Set(entries.flatMap((entry) => entry.flatIndex === void 0 ? [] : [entry.flatIndex])), progressCount = d.progress?.reduce((count, entry) => Math.max(count, entry.index + 1), 0) ?? 0, dataCount = Math.max(d.results.length, progressCount, d.chainChildren?.length ?? 0);
832
+ for (let flatIndex = 0; flatIndex < dataCount; flatIndex++)
833
+ seen.has(flatIndex) || entries.push({ flatIndex });
834
+ return entries;
953
835
  }
954
836
  function renderMultiCompact(d, theme, frame) {
955
- let hasRunning = d.progress?.some((p) => p.status === "running") || d.results.some((r) => r.progress?.status === "running") || workflowGraphHasStatus(d, ["running"]), stopped = d.results.some((r) => r.stopped && r.progress?.status !== "running") || workflowGraphHasStatus(d, ["stopped"]), failed = d.results.some((r) => !r.stopped && r.exitCode !== 0 && r.progress?.status !== "running") || workflowGraphHasStatus(d, ["failed"]), paused = d.results.some((r) => (r.interrupted || r.detached) && r.progress?.status !== "running") || workflowGraphHasStatus(d, ["paused", "detached"]), totalSummary = d.progressSummary;
956
- if (!totalSummary) {
957
- let sawProgress = !1, summary = { toolCount: 0, tokens: 0, durationMs: 0, lastActivityAt: void 0 };
958
- for (let r of d.results) {
959
- let prog = r.progress || r.progressSummary;
960
- prog && (sawProgress = !0, summary.toolCount += prog.toolCount, summary.tokens += prog.tokens, summary.durationMs = d.mode === "chain" ? summary.durationMs + prog.durationMs : Math.max(summary.durationMs, prog.durationMs), prog.status === "running" && prog.lastActivityAt !== void 0 && (summary.lastActivityAt = Math.max(summary.lastActivityAt ?? 0, prog.lastActivityAt)));
961
- }
962
- sawProgress && (totalSummary = summary);
963
- }
964
- let multiLabel = buildMultiProgressLabel(d, hasRunning), itemTitle = multiLabel.itemTitle, glyph = (f) => hasRunning ? theme.fg("accent", runningGlyph(f !== void 0 ? (runningSeed(progressRunningSeed(totalSummary), d.currentStepIndex) ?? 0) + f : runningSeed(progressRunningSeed(totalSummary), d.currentStepIndex))) : stopped ? theme.fg("warning", "\u25A0") : failed ? theme.fg("error", "\u2717") : paused ? theme.fg("warning", "\u25A0") : theme.fg("success", "\u2713"), contextBadge = d.context === "fork" ? theme.fg("warning", " [fork]") : "", c = new Container(), width = getTermWidth() - 4;
965
- c.addChild(animatedLine((f) => {
966
- let stats = statJoin(theme, [multiLabel.headerLabel, formatTotalCostStat(d.totalCost)]);
967
- return truncLine(`${glyph(f)} ${theme.fg("toolTitle", theme.bold(d.mode))}${contextBadge}${stats ? ` ${theme.fg("dim", "\xB7")} ${stats}` : ""}`, width);
968
- }, frame, hasRunning));
969
- let useResultsDirectly = multiLabel.hasParallelInChain || !d.chainAgents?.length, displayStart = multiLabel.showActiveGroupOnly ? multiLabel.groupStartIndex : 0, displayEnd = multiLabel.showActiveGroupOnly ? multiLabel.groupEndIndex : useResultsDirectly ? d.results.length : d.chainAgents.length, chainEntries = buildChainRenderEntries(d, multiLabel), renderEntries = chainEntries ?? Array.from({ length: displayEnd - displayStart }, (_, offset) => {
970
- let i = displayStart + offset, r = d.results[i], fallbackLabel = itemTitle.toLowerCase(), rowNumber = multiLabel.showActiveGroupOnly ? i - multiLabel.groupStartIndex + 1 : i + 1;
971
- return { kind: "result", resultIndex: i, rowNumber, agentName: useResultsDirectly ? r?.agent || `${fallbackLabel}-${rowNumber}` : d.chainAgents[i] || r?.agent || `${fallbackLabel}-${rowNumber}` };
972
- });
973
- for (let entry of renderEntries) {
974
- if (entry.kind === "placeholder") {
975
- let glyph2 = widgetStepGlyph(entry.status, theme), statusLabel = widgetStepStatus(entry.status, theme);
976
- c.addChild(new Text(truncLine(` ${glyph2} ${entry.stepLabel}: ${themeBold(theme, entry.agentName)} ${theme.fg("dim", "\xB7")} ${statusLabel}`, width), 0, 0)), entry.error && c.addChild(new Text(truncLine(theme.fg("error", ` \u23BF Error: ${entry.error}`), width), 0, 0));
977
- continue;
978
- }
979
- let i = entry.resultIndex, r = d.results[i], rowNumber = entry.rowNumber, agentName = entry.agentName;
980
- if (!r) {
981
- let pendingLabel = chainEntries ? resultRowLabel(d, multiLabel, i, rowNumber) : `${itemTitle} ${rowNumber}`;
982
- c.addChild(new Text(truncLine(theme.fg("dim", ` \u25E6 ${pendingLabel}: ${agentName} \xB7 pending`), width), 0, 0));
983
- continue;
984
- }
985
- let output = getSingleResultOutput(r), progressFromArray = d.progress?.find((p) => p.index === i) || d.progress?.find((p) => p.agent === r.agent && p.status === "running"), rProg = r.progress || progressFromArray || r.progressSummary, rRunning = rProg && "status" in rProg && rProg.status === "running", rPending = rProg && "status" in rProg && rProg.status === "pending", lead = compactRowLead({ description: r.description ?? agentName, task: r.task }), modelBadge = formatCompactModelBadge(r.modelSelection ?? (rProg && "modelSelection" in rProg ? rProg.modelSelection : void 0), r.model ?? (rProg && "model" in rProg ? rProg.model : void 0));
986
- c.addChild(animatedLine((f, now) => {
987
- let rowGlyph = rPending ? theme.fg("dim", "\u25E6") : resultGlyph(r, output, theme, rRunning, progressRunningSeed(rProg), f);
837
+ let c = new Container(), width = getTermWidth() - 4, entries = compactForegroundEntries(d);
838
+ for (let [rowIndex, entry] of entries.entries()) {
839
+ let flatIndex = entry.flatIndex, result2 = flatIndex === void 0 ? void 0 : resultAtFlatIndex(d, flatIndex), progress = result2?.progress ?? (flatIndex === void 0 ? void 0 : d.progress?.find((candidate) => candidate.index === flatIndex)) ?? result2?.progressSummary, status = progress?.status ?? entry.node?.status ?? "pending", description = compactRowLead({
840
+ description: result2?.description ?? progress?.description ?? entry.node?.label ?? (flatIndex === void 0 ? void 0 : d.chainChildren?.[flatIndex]?.description) ?? (flatIndex === void 0 ? void 0 : d.chainAgents?.[flatIndex]) ?? result2?.agent ?? progress?.agent,
841
+ task: result2?.task ?? progress?.task
842
+ }) || `child ${rowIndex + 1}`, running = status === "running", output = result2 ? getSingleResultOutput(result2) : "", modelBadge = formatCompactModelBadge(result2?.modelSelection ?? progress?.modelSelection, result2?.model ?? progress?.model);
843
+ c.addChild(animatedLine((animationTick, now) => {
844
+ let animationFrame = foregroundSpinnerFrame(animationTick);
988
845
  return formatCompactSubagentRow(theme, width, {
989
- glyph: rowGlyph,
990
- description: lead,
846
+ glyph: result2 ? resultGlyph(result2, output, theme, running, progressRunningSeed(progress), animationFrame) : progressStatusGlyph({ ...progress, status, index: flatIndex }, theme, animationFrame),
847
+ description,
991
848
  modelBadge,
992
- tokens: compactResultTokens(r),
993
- durationMs: liveDurationMs(rProg, !!rRunning, now),
994
- prefix: " "
849
+ tokens: result2 ? compactResultTokens(result2) : progress?.tokens ?? 0,
850
+ durationMs: liveDurationMs(progress, running, now),
851
+ terminalStatus: result2 ? compactResultTerminalStatus(result2) : compactTerminalStatus(status)
995
852
  });
996
- }, frame, !!rRunning)), !rPending && !rRunning && (r.exitCode !== 0 || r.interrupted || r.detached || r.stopped) && c.addChild(new Text(truncLine(theme.fg(r.exitCode !== 0 ? "error" : "dim", ` \u23BF ${resultStatusLine(r, output)}`), width), 0, 0));
853
+ }, frame, running));
997
854
  }
998
855
  return c;
999
856
  }
1000
857
  function renderSubagentResult(result2, options, theme, frame) {
1001
- let d = result2.details;
1002
- if (!d || !d.results.length) {
858
+ let d = result2.details, hasWorkflowRows = d?.mode !== "management" && !!(d?.workflowGraph?.nodes.length || d?.progress?.length || d?.chainChildren?.length);
859
+ if (!d || !d.results.length && !hasWorkflowRows) {
1003
860
  let t = result2.content[0], text = t?.type === "text" ? t.text : "(no output)", contextPrefix = d?.context === "fork" ? `${theme.fg("warning", "[fork]")} ` : "", width = getTermWidth() - 4;
1004
861
  if (!text.includes(`
1005
862
  `))
@@ -1020,7 +877,7 @@ function renderSubagentResult(result2, options, theme, frame) {
1020
877
  return fit3(`${icon2} ${theme.fg("toolTitle", theme.bold(r.agent))}${modelDisplay}${contextBadge2}${stats ? ` | ${stats}` : ""}`);
1021
878
  }, frame, isRunning)), c2.addChild(new Spacer(1));
1022
879
  let taskMaxLen = Math.max(20, w2 - 8), taskPreview = expanded || r.task.length <= taskMaxLen ? r.task : `${r.task.slice(0, taskMaxLen)}...`;
1023
- if (c2.addChild(new Text(fit3(theme.fg("dim", `Task: ${taskPreview}`)), 0, 0)), c2.addChild(new Spacer(1)), isRunning && r.progress) {
880
+ if (c2.addChild(new Text(fit3(theme.fg("dim", `Task: ${taskPreview}`)), 0, 0)), !isRunning && compactResultTerminalStatus(r) && c2.addChild(new Text(fit3(theme.fg(r.exitCode !== 0 ? "error" : "warning", resultStatusLine(r, output))), 0, 0)), c2.addChild(new Spacer(1)), isRunning && r.progress) {
1024
881
  let progressSnapshotNow = snapshotNowForProgress(r.progress), toolLine = formatCurrentToolLine(r.progress, w2, expanded, progressSnapshotNow);
1025
882
  toolLine && c2.addChild(new Text(fit3(theme.fg("warning", `> ${toolLine}`)), 0, 0));
1026
883
  let liveStatusLine = buildLiveStatusLine(r.progress, progressSnapshotNow);
@@ -1042,7 +899,7 @@ function renderSubagentResult(result2, options, theme, frame) {
1042
899
  }
1043
900
  if (!expanded)
1044
901
  return renderMultiCompact(d, theme, frame);
1045
- let hasRunning = d.progress?.some((p) => p.status === "running") || d.results.some((r) => r.progress?.status === "running") || workflowGraphHasStatus(d, ["running"]), ok = d.results.filter((r) => r.progress?.status === "completed" || r.exitCode === 0 && r.progress?.status !== "running").length, hasEmptyWithoutTarget = d.results.some((r) => r.exitCode === 0 && r.progress?.status !== "running" && hasEmptyTextOutputWithoutOutputTarget(r.task, getSingleResultOutput(r))), hasWorkflowFailure = workflowGraphHasStatus(d, ["failed"]), hasWorkflowStop = d.results.some((r) => r.stopped && r.progress?.status !== "running") || workflowGraphHasStatus(d, ["stopped"]), hasWorkflowPause = workflowGraphHasStatus(d, ["paused", "detached"]), icon = hasRunning ? theme.fg("warning", "running") : hasEmptyWithoutTarget ? theme.fg("warning", "warning") : hasWorkflowFailure ? theme.fg("error", "failed") : hasWorkflowStop ? theme.fg("warning", "stopped") : hasWorkflowPause ? theme.fg("warning", "paused") : ok === d.results.length ? theme.fg("success", "ok") : theme.fg("error", "failed"), totalSummary = d.progressSummary || d.results.reduce((acc, r) => {
902
+ let hasRunning = d.progress?.some((p) => p.status === "running") || d.results.some((r) => r.progress?.status === "running") || workflowGraphHasStatus(d, ["running"]), ok = d.results.filter((r) => r.progress?.status === "completed" || r.exitCode === 0 && r.progress?.status !== "running").length, hasEmptyWithoutTarget = d.results.some((r) => r.exitCode === 0 && r.progress?.status !== "running" && hasEmptyTextOutputWithoutOutputTarget(r.task, getSingleResultOutput(r))), hasWorkflowFailure = workflowGraphHasStatus(d, ["failed"]), hasWorkflowStop = d.results.some((r) => r.stopped && r.progress?.status !== "running") || workflowGraphHasStatus(d, ["stopped"]), hasWorkflowPause = workflowGraphHasStatus(d, ["paused", "detached"]), hasWorkflowPending = workflowGraphHasStatus(d, ["pending"]), icon = hasRunning ? theme.fg("warning", "running") : hasEmptyWithoutTarget ? theme.fg("warning", "warning") : hasWorkflowFailure ? theme.fg("error", "failed") : hasWorkflowStop ? theme.fg("warning", "stopped") : hasWorkflowPause ? theme.fg("warning", "paused") : hasWorkflowPending ? theme.fg("dim", "pending") : ok === d.results.length ? theme.fg("success", "ok") : theme.fg("error", "failed"), totalSummary = d.progressSummary || d.results.reduce((acc, r) => {
1046
903
  let prog = r.progress || r.progressSummary;
1047
904
  return prog && (acc.toolCount += prog.toolCount, acc.tokens += prog.tokens, acc.durationMs = d.mode === "chain" ? acc.durationMs + prog.durationMs : Math.max(acc.durationMs, prog.durationMs)), acc;
1048
905
  }, { toolCount: 0, tokens: 0, durationMs: 0 }), modeLabel = d.mode, contextBadge = d.context === "fork" ? theme.fg("warning", " [fork]") : "", multiLabel = buildMultiProgressLabel(d, hasRunning), itemTitle = multiLabel.itemTitle, chainVis = d.chainAgents?.length && !multiLabel.hasParallelInChain ? d.chainAgents.map((agent, i) => {
@@ -1056,10 +913,26 @@ function renderSubagentResult(result2, options, theme, frame) {
1056
913
  ].filter(Boolean), summaryStr = summaryParts.length ? ` | ${summaryParts.join(", ")}` : "";
1057
914
  return fit2(`${icon} ${theme.fg("toolTitle", theme.bold(modeLabel))}${contextBadge} \xB7 ${multiLabel.headerLabel}${summaryStr}`);
1058
915
  }, frame, hasRunning)), chainVis && c.addChild(new Text(fit2(` ${chainVis}`), 0, 0));
1059
- let useResultsDirectly = multiLabel.hasParallelInChain || !d.chainAgents?.length, displayStart = multiLabel.showActiveGroupOnly ? multiLabel.groupStartIndex : 0, displayEnd = multiLabel.showActiveGroupOnly ? multiLabel.groupEndIndex : useResultsDirectly ? d.results.length : d.chainAgents.length, chainEntries = buildChainRenderEntries(d, multiLabel), renderEntries = chainEntries ?? Array.from({ length: displayEnd - displayStart }, (_, offset) => {
1060
- let i = displayStart + offset, r = d.results[i], rowNumber = multiLabel.showActiveGroupOnly ? i - multiLabel.groupStartIndex + 1 : i + 1;
1061
- return { kind: "result", resultIndex: i, rowNumber, agentName: useResultsDirectly ? r?.agent || `step-${rowNumber}` : d.chainAgents[i] || r?.agent || `step-${rowNumber}` };
1062
- });
916
+ let chainEntries = buildChainRenderEntries(d, multiLabel), fallbackEntries = compactForegroundEntries(d).filter((entry) => !multiLabel.showActiveGroupOnly || entry.flatIndex === void 0 || entry.flatIndex >= multiLabel.groupStartIndex && entry.flatIndex < multiLabel.groupEndIndex).map((entry, rowIndex) => {
917
+ if (entry.flatIndex === void 0)
918
+ return {
919
+ kind: "placeholder",
920
+ rowNumber: entry.node?.stepIndex !== void 0 ? entry.node.stepIndex + 1 : rowIndex + 1,
921
+ stepLabel: `Step ${entry.node?.stepIndex !== void 0 ? entry.node.stepIndex + 1 : rowIndex + 1}`,
922
+ agentName: entry.node?.label ?? `step-${rowIndex + 1}`,
923
+ status: entry.node?.status ?? "pending",
924
+ error: entry.node?.error
925
+ };
926
+ let result3 = resultAtFlatIndex(d, entry.flatIndex), rowNumber = multiLabel.showActiveGroupOnly ? entry.flatIndex - multiLabel.groupStartIndex + 1 : entry.flatIndex + 1;
927
+ return {
928
+ kind: "result",
929
+ resultIndex: entry.flatIndex,
930
+ rowNumber,
931
+ agentName: result3?.agent ?? entry.node?.label ?? d.chainChildren?.[entry.flatIndex]?.description ?? d.chainAgents?.[entry.flatIndex] ?? `step-${rowNumber}`,
932
+ status: entry.node?.status,
933
+ error: entry.node?.error
934
+ };
935
+ }), renderEntries = chainEntries ?? fallbackEntries;
1063
936
  c.addChild(new Spacer(1));
1064
937
  for (let entry of renderEntries) {
1065
938
  if (entry.kind === "placeholder") {
@@ -1067,10 +940,10 @@ function renderSubagentResult(result2, options, theme, frame) {
1067
940
  c.addChild(new Text(fit2(` ${statusLabel} ${entry.stepLabel}: ${theme.bold(entry.agentName)}`), 0, 0)), c.addChild(new Text(theme.fg(entry.status === "failed" ? "error" : "dim", ` status: ${entry.status}`), 0, 0)), entry.error && c.addChild(new Text(theme.fg("error", ` error: ${entry.error}`), 0, 0)), c.addChild(new Spacer(1));
1068
941
  continue;
1069
942
  }
1070
- let i = entry.resultIndex, r = d.results[i], rowNumber = entry.rowNumber, agentName = entry.agentName;
943
+ let i = entry.resultIndex, r = resultAtFlatIndex(d, i), rowNumber = entry.rowNumber, agentName = entry.agentName;
1071
944
  if (!r) {
1072
- let pendingLabel = chainEntries ? resultRowLabel(d, multiLabel, i, rowNumber) : `${itemTitle} ${rowNumber}`;
1073
- c.addChild(new Text(fit2(theme.fg("dim", ` ${pendingLabel}: ${agentName}`)), 0, 0)), c.addChild(new Text(theme.fg("dim", " status: pending"), 0, 0)), c.addChild(new Spacer(1));
945
+ let rowLabel = chainEntries ? resultRowLabel(d, multiLabel, i, rowNumber) : `${itemTitle} ${rowNumber}`, status = entry.status ?? "pending";
946
+ c.addChild(new Text(fit2(theme.fg(status === "failed" ? "error" : "dim", ` ${rowLabel}: ${agentName}`)), 0, 0)), c.addChild(new Text(theme.fg(status === "failed" ? "error" : "dim", ` status: ${status}`), 0, 0)), entry.error && c.addChild(new Text(theme.fg("error", ` error: ${entry.error}`), 0, 0)), c.addChild(new Spacer(1));
1074
947
  continue;
1075
948
  }
1076
949
  let progressFromArray = d.progress?.find((p) => p.index === i) || d.progress?.find((p) => p.agent === r.agent && p.status === "running"), rProg = r.progress || progressFromArray || r.progressSummary, rRunning = rProg?.status === "running", stepNumber = typeof rProg?.index == "number" ? rProg.index + 1 : i + 1, resultOutput = getSingleResultOutput(r), statusIcon = rRunning ? theme.fg("warning", "running") : r.exitCode !== 0 ? theme.fg("error", "failed") : hasEmptyTextOutputWithoutOutputTarget(r.task, resultOutput) ? theme.fg("warning", "warning") : theme.fg("success", "done"), modelDisplay = modelThinkingBadge(theme, r.model, r.thinking ?? (rProg && "thinking" in rProg ? rProg.thinking : void 0), r.modelSelection ?? (rProg && "modelSelection" in rProg ? rProg.modelSelection : void 0)), stepLabel = resultRowLabel(d, multiLabel, i, stepNumber), toolCallLines = getToolCallLines(r, expanded);
@@ -1079,7 +952,7 @@ function renderSubagentResult(result2, options, theme, frame) {
1079
952
  return fit2(rRunning ? `${statusIcon} ${stepLabel}: ${theme.bold(theme.fg("warning", r.agent))}${modelDisplay}${stats ? ` | ${stats}` : ""}` : `${statusIcon} ${stepLabel}: ${theme.bold(r.agent)}${modelDisplay}${stats ? ` | ${stats}` : ""}`);
1080
953
  }, frame, rRunning));
1081
954
  let taskMaxLen = Math.max(20, w - 12), taskPreview = expanded || r.task.length <= taskMaxLen ? r.task : `${r.task.slice(0, taskMaxLen)}...`;
1082
- if (c.addChild(new Text(fit2(theme.fg("dim", ` task: ${taskPreview}`)), 0, 0)), r.skills?.length && c.addChild(new Text(fit2(theme.fg("dim", ` skills: ${r.skills.join(", ")}`)), 0, 0)), r.skillsWarning && c.addChild(new Text(fit2(theme.fg("warning", ` Warning: ${r.skillsWarning}`)), 0, 0)), r.attemptedModels && r.attemptedModels.length > 1 && c.addChild(new Text(fit2(theme.fg("dim", ` fallbacks: ${r.attemptedModels.join(" \u2192 ")}`)), 0, 0)), rRunning && rProg) {
955
+ if (c.addChild(new Text(fit2(theme.fg("dim", ` task: ${taskPreview}`)), 0, 0)), !rRunning && compactResultTerminalStatus(r) && c.addChild(new Text(fit2(theme.fg(r.exitCode !== 0 ? "error" : "warning", ` ${resultStatusLine(r, resultOutput)}`)), 0, 0)), r.skills?.length && c.addChild(new Text(fit2(theme.fg("dim", ` skills: ${r.skills.join(", ")}`)), 0, 0)), r.skillsWarning && c.addChild(new Text(fit2(theme.fg("warning", ` Warning: ${r.skillsWarning}`)), 0, 0)), r.attemptedModels && r.attemptedModels.length > 1 && c.addChild(new Text(fit2(theme.fg("dim", ` fallbacks: ${r.attemptedModels.join(" \u2192 ")}`)), 0, 0)), rRunning && rProg) {
1083
956
  rProg.skills?.length && c.addChild(new Text(fit2(theme.fg("accent", ` skills: ${rProg.skills.join(", ")}`)), 0, 0));
1084
957
  let progressSnapshotNow = snapshotNowForProgress(rProg), toolLine = formatCurrentToolLine(rProg, w, expanded, progressSnapshotNow);
1085
958
  toolLine && c.addChild(new Text(fit2(theme.fg("warning", ` > ${toolLine}`)), 0, 0));
@@ -1349,7 +1222,7 @@ var SkillOverride = Type.Unsafe({
1349
1222
  description: "Children always start with a fresh session. Fork context is not available."
1350
1223
  })),
1351
1224
  chainDir: Type.Optional(Type.String({ description: "Persistent chain artifact directory; defaults to user-scoped temp storage." })),
1352
- async: Type.Optional(Type.Boolean({ description: "Run in background (default: false, or per config)" })),
1225
+ async: Type.Optional(Type.Boolean({ description: "Run async in the background. Defaults to true when omitted; set false for immediate foreground results." })),
1353
1226
  timeoutMs: Type.Optional(Type.Integer({ minimum: 1, description: "Optional run-level timeout in ms for foreground and async/background runs. Alias of maxRuntimeMs." })),
1354
1227
  maxRuntimeMs: Type.Optional(Type.Integer({ minimum: 1, description: "Alias of timeoutMs for optional run-level timeout in foreground and async/background runs." })),
1355
1228
  turnBudget: Type.Optional(TurnBudgetOverride),
@@ -1360,7 +1233,7 @@ var SkillOverride = Type.Unsafe({
1360
1233
  share: Type.Optional(Type.Boolean({ description: "Upload session to GitHub Gist for sharing (default: false)" })),
1361
1234
  sessionDir: Type.Optional(Type.String({ description: "Directory to store session logs (default: temp; enables sessions even if share=false)" })),
1362
1235
  // Clarification TUI
1363
- clarify: Type.Optional(Type.Boolean({ description: "Show TUI to preview/edit before execution. Explicit clarify: true keeps the run foreground for the clarify UI; omitted clarify can still run in the background when async: true is set." })),
1236
+ clarify: Type.Optional(Type.Boolean({ description: "Show the interactive TUI preview/editor before execution. clarify:true keeps the run foreground even when async is omitted or true." })),
1364
1237
  control: Type.Optional(ControlOverrides),
1365
1238
  output: Type.Optional(Type.Unsafe({
1366
1239
  anyOf: [
@@ -1596,7 +1469,7 @@ function createAsyncJobTracker(pi, state, asyncDirRoot, options = {}) {
1596
1469
  if (parsed.type !== "subagent.control")
1597
1470
  return;
1598
1471
  let record = parsed;
1599
- if (!record.event || !Array.isArray(record.channels))
1472
+ if (!record.event || !Array.isArray(record.channels) || record.event.reason === "completion_guard")
1600
1473
  return;
1601
1474
  let payload = {
1602
1475
  event: record.event,
@@ -1922,7 +1795,7 @@ ${baseOutput}` : ""}` : output, sessionPath = result2.sessionFile ?? (resultChil
1922
1795
  asyncId: data.id,
1923
1796
  asyncDir: data.asyncDir
1924
1797
  });
1925
- payload.requestId = `async-result:${sessionId}:${completionKey}`, attempts.set(file, (attempts.get(file) ?? 0) + 1);
1798
+ payload.requestId = `async-result:${sessionId}:${completionKey}`, payload.ownerNotificationSessionId = sessionId, attempts.set(file, (attempts.get(file) ?? 0) + 1);
1926
1799
  let delivered = await deliverSubagentResultIntercomEvent(pi.events, payload);
1927
1800
  if (!isCurrent())
1928
1801
  return;
@@ -2527,7 +2400,7 @@ function substituteArgs(template, args) {
2527
2400
  return template.replace(/\$ARGUMENTS/g, all).replace(/\$@/g, all).replace(/\$\{(\d+):-([^}]*)\}/g, (_match, index, fallback) => args[Number(index) - 1] || fallback).replace(/\$(\d+)/g, (_match, index) => args[Number(index) - 1] ?? "");
2528
2401
  }
2529
2402
  function parseRuntimeOptions(words) {
2530
- let args = [], descriptionOverride, permissions, worktree = !1, bg = !1;
2403
+ let args = [], descriptionOverride, permissions, worktree = !1, async;
2531
2404
  for (let i = 0; i < words.length; i++) {
2532
2405
  let word = words[i];
2533
2406
  if (word === "--read-only") {
@@ -2543,7 +2416,11 @@ function parseRuntimeOptions(words) {
2543
2416
  continue;
2544
2417
  }
2545
2418
  if (word === "--bg" || word === "--async") {
2546
- bg = !0;
2419
+ async = !0;
2420
+ continue;
2421
+ }
2422
+ if (word === "--fg" || word === "--foreground") {
2423
+ async = !1;
2547
2424
  continue;
2548
2425
  }
2549
2426
  if (word === "--description") {
@@ -2557,7 +2434,7 @@ function parseRuntimeOptions(words) {
2557
2434
  }
2558
2435
  args.push(word);
2559
2436
  }
2560
- return { args, descriptionOverride, permissions, worktree, bg };
2437
+ return { args, descriptionOverride, permissions, worktree, async };
2561
2438
  }
2562
2439
  function splitChainDeclaration(input) {
2563
2440
  let delimiter = input.indexOf(" -- ");
@@ -2576,7 +2453,7 @@ function workflowParams(workflow, args, runtime) {
2576
2453
  ...workflow.skill !== void 0 ? { skill: workflow.skill } : {},
2577
2454
  ...workflow.cwd ? { cwd: workflow.cwd } : {},
2578
2455
  ...runtime.worktree || workflow.worktree ? { worktree: !0 } : {},
2579
- ...runtime.bg ? { async: !0 } : {}
2456
+ ...runtime.async !== void 0 ? { async: runtime.async } : {}
2580
2457
  };
2581
2458
  }
2582
2459
  function workflowChainStep(workflow, args, runtime) {
@@ -2624,7 +2501,7 @@ function registerPromptWorkflowCommands(input) {
2624
2501
  throw new Error(`Unknown prompt workflow in chain '${workflow.name}': ${stepName}`);
2625
2502
  return workflowChainStep(step, runtime.args, runtime);
2626
2503
  });
2627
- await run({ chain, task: runtime.args.join(" "), clarify: !1, ...runtime.bg ? { async: !0 } : {} }, ctx);
2504
+ await run({ chain, task: runtime.args.join(" "), clarify: !1, ...runtime.async !== void 0 ? { async: runtime.async } : {} }, ctx);
2628
2505
  return;
2629
2506
  }
2630
2507
  await run(workflowParams(workflow, runtime.args, runtime), ctx);
@@ -2652,7 +2529,7 @@ function registerPromptWorkflowCommands(input) {
2652
2529
  throw new Error(`Unknown prompt workflow: ${name}`);
2653
2530
  return workflowChainStep(workflow, runtime.args, runtime);
2654
2531
  });
2655
- await run({ chain, task: runtime.args.join(" "), clarify: !1, ...runtime.bg ? { async: !0 } : {} }, ctx);
2532
+ await run({ chain, task: runtime.args.join(" "), clarify: !1, ...runtime.async !== void 0 ? { async: runtime.async } : {} }, ctx);
2656
2533
  } catch (error) {
2657
2534
  ctx.ui.notify(error instanceof Error ? error.message : String(error), "error");
2658
2535
  }
@@ -3232,15 +3109,14 @@ var parseInlineConfig = (raw) => {
3232
3109
  let end = token.lastIndexOf("]");
3233
3110
  return { name: token.slice(0, bracket), config: parseInlineConfig(token.slice(bracket + 1, end !== -1 ? end : void 0)) };
3234
3111
  }, extractExecutionFlags = (rawArgs) => {
3235
- let args = rawArgs.trim(), bg = !1;
3112
+ let args = rawArgs.trim(), async;
3236
3113
  for (; ; ) {
3237
- if (args.endsWith(" --bg") || args === "--bg") {
3238
- bg = !0, args = args === "--bg" ? "" : args.slice(0, -5).trim();
3239
- continue;
3240
- }
3241
- break;
3114
+ let match = args.match(/(?:^|\s)(--bg|--async|--fg|--foreground)$/);
3115
+ if (!match)
3116
+ break;
3117
+ async ??= match[1] === "--bg" || match[1] === "--async", args = args.slice(0, match.index).trim();
3242
3118
  }
3243
- return { args, bg };
3119
+ return { args, async };
3244
3120
  };
3245
3121
  function sendSlashText(pi, text) {
3246
3122
  pi.sendMessage({ customType: SLASH_TEXT_RESULT_TYPE, content: text, display: !0 });
@@ -3821,16 +3697,16 @@ function registerSlashCommands(pi, state) {
3821
3697
  }
3822
3698
  };
3823
3699
  pi.registerCommand("run", {
3824
- description: "Run a prompt-defined child: /run description[tier=standard] task [--bg]",
3700
+ description: "Run an async prompt-defined child; add --foreground to wait inline",
3825
3701
  handler: async (args, ctx) => {
3826
- let { args: cleanedArgs, bg } = extractExecutionFlags(args), input = cleanedArgs.trim(), firstSpace = input.indexOf(" ");
3702
+ let { args: cleanedArgs, async } = extractExecutionFlags(args), input = cleanedArgs.trim(), firstSpace = input.indexOf(" ");
3827
3703
  if (!input) {
3828
- ctx.ui.notify("Usage: /run <description> <task> [--bg]", "error");
3704
+ ctx.ui.notify("Usage: /run <description> <task> [--foreground]", "error");
3829
3705
  return;
3830
3706
  }
3831
3707
  let { name: description, config: inline } = parseAgentToken(firstSpace === -1 ? input : input.slice(0, firstSpace)), task = firstSpace === -1 ? "" : input.slice(firstSpace + 1).trim();
3832
3708
  if (!description || !task || !inline.tier) {
3833
- ctx.ui.notify("Usage: /run <description>[tier=light|standard|heavy] <task> [--bg]", "error");
3709
+ ctx.ui.notify("Usage: /run <description>[tier=light|standard|heavy] <task> [--foreground]", "error");
3834
3710
  return;
3835
3711
  }
3836
3712
  let finalTask = task;
@@ -3838,21 +3714,21 @@ function registerSlashCommands(pi, state) {
3838
3714
 
3839
3715
  ${finalTask}`);
3840
3716
  let params = { description, permissions: inline.permissions ?? "full", tier: inline.tier, task: finalTask, clarify: !1 };
3841
- inline.output !== void 0 && (params.output = inline.output), inline.outputMode !== void 0 && (params.outputMode = inline.outputMode), inline.skill !== void 0 && (params.skill = inline.skill), bg && (params.async = !0), await runSlashSubagent(pi, ctx, params);
3717
+ inline.output !== void 0 && (params.output = inline.output), inline.outputMode !== void 0 && (params.outputMode = inline.outputMode), inline.skill !== void 0 && (params.skill = inline.skill), async !== void 0 && (params.async = async), await runSlashSubagent(pi, ctx, params);
3842
3718
  }
3843
3719
  }), pi.registerCommand("chain", {
3844
- description: 'Run prompt-defined children in sequence: /chain inspect "task" -> implement [--bg]',
3720
+ description: "Run prompt-defined children as an async sequence; add --foreground to wait inline",
3845
3721
  handler: async (args, ctx) => {
3846
- let { args: cleanedArgs, bg } = extractExecutionFlags(args), built = buildChainExpressionSteps(state, cleanedArgs, ctx);
3722
+ let { args: cleanedArgs, async } = extractExecutionFlags(args), built = buildChainExpressionSteps(state, cleanedArgs, ctx);
3847
3723
  if (!built)
3848
3724
  return;
3849
3725
  let params = { chain: built.chain, task: built.task, clarify: !1 };
3850
- bg && (params.async = !0), await runSlashSubagent(pi, ctx, params);
3726
+ async !== void 0 && (params.async = async), await runSlashSubagent(pi, ctx, params);
3851
3727
  }
3852
3728
  }), pi.registerCommand("parallel", {
3853
- description: 'Run prompt-defined children in parallel: /parallel inspect "task1" -> review "task2" [--bg]',
3729
+ description: "Run prompt-defined children async in parallel; add --foreground to wait inline",
3854
3730
  handler: async (args, ctx) => {
3855
- let { args: cleanedArgs, bg } = extractExecutionFlags(args), parsed = parseAgentArgs(state, cleanedArgs, "parallel", ctx);
3731
+ let { args: cleanedArgs, async } = extractExecutionFlags(args), parsed = parseAgentArgs(state, cleanedArgs, "parallel", ctx);
3856
3732
  if (!parsed)
3857
3733
  return;
3858
3734
  let tasks = parsed.steps.map(({ name, config, task: stepTask }) => ({
@@ -3877,7 +3753,7 @@ ${finalTask}`);
3877
3753
  return;
3878
3754
  }
3879
3755
  let params = { tasks, clarify: !1 };
3880
- bg && (params.async = !0), await runSlashSubagent(pi, ctx, params);
3756
+ async !== void 0 && (params.async = async), await runSlashSubagent(pi, ctx, params);
3881
3757
  }
3882
3758
  }), pi.registerCommand("subagent-cost", {
3883
3759
  description: "Show parent and subagent child usage cost for this session",
@@ -5012,7 +4888,7 @@ function hasTool(pi, name) {
5012
4888
  function parseRequestFile(file, channelDir) {
5013
4889
  try {
5014
4890
  let parsed = JSON.parse(fs7.readFileSync(file, "utf-8"));
5015
- return parsed.type !== "subagent.supervisor.request" || typeof parsed.id != "string" || !parsed.id || parsed.reason !== "need_decision" && parsed.reason !== "interview_request" && parsed.reason !== "progress_update" || typeof parsed.message != "string" || !parsed.message || typeof parsed.runId != "string" || typeof parsed.agent != "string" || typeof parsed.childIndex != "number" ? void 0 : { ...parsed, channelDir, requestFile: file };
4891
+ return parsed.type !== "subagent.supervisor.request" || parsed.supervisorSessionId !== void 0 && (typeof parsed.supervisorSessionId != "string" || !parsed.supervisorSessionId.trim()) || typeof parsed.id != "string" || !parsed.id || parsed.reason !== "need_decision" && parsed.reason !== "interview_request" && parsed.reason !== "progress_update" || typeof parsed.message != "string" || !parsed.message || typeof parsed.runId != "string" || typeof parsed.agent != "string" || typeof parsed.childIndex != "number" ? void 0 : { ...parsed, channelDir, requestFile: file };
5016
4892
  } catch {
5017
4893
  return;
5018
4894
  }
@@ -5022,7 +4898,7 @@ function hasPendingBlockingSupervisorRequest(runId, sessionId, now = Date.now())
5022
4898
  return !1;
5023
4899
  for (let { channelDir, file } of listRequestFiles()) {
5024
4900
  let request = parseRequestFile(file, channelDir);
5025
- if (request?.expectsReply && request.runId === runId && !(sessionId && request.orchestratorSessionId && request.orchestratorSessionId !== sessionId) && !fs7.existsSync(replyPath(request.channelDir, request.id)) && !(now > requestExpiresAt(request, now)))
4901
+ if (request?.expectsReply && request.runId === runId && !(sessionId && (request.supervisorSessionId ?? request.orchestratorSessionId) !== sessionId) && !fs7.existsSync(replyPath(request.channelDir, request.id)) && !(now > requestExpiresAt(request, now)))
5026
4902
  return !0;
5027
4903
  }
5028
4904
  return !1;
@@ -5117,9 +4993,16 @@ function currentContextSessionId(state, ctx) {
5117
4993
  }
5118
4994
  return state.currentSessionId ?? void 0;
5119
4995
  }
4996
+ function currentSupervisorSessionId(state, ctx) {
4997
+ try {
4998
+ return ctx.sessionManager.getSessionFile?.() ?? currentContextSessionId(state, ctx);
4999
+ } catch {
5000
+ return state.currentSessionId ?? void 0;
5001
+ }
5002
+ }
5120
5003
  function requestMatchesContext(request, state, ctx) {
5121
- let currentSessionId = currentContextSessionId(state, ctx);
5122
- return !!(currentSessionId && request.orchestratorSessionId === currentSessionId);
5004
+ let currentSessionId = request.supervisorSessionId !== void 0 ? currentSupervisorSessionId(state, ctx) : currentContextSessionId(state, ctx);
5005
+ return !!(currentSessionId && (request.supervisorSessionId ?? request.orchestratorSessionId) === currentSessionId);
5123
5006
  }
5124
5007
  function removeRequestFile(file) {
5125
5008
  try {
@@ -5244,7 +5127,7 @@ function buildParentIntercomTool(pending, state, name = "intercom") {
5244
5127
  };
5245
5128
  }
5246
5129
  function questionMatchesParentContext(question, state, ctx) {
5247
- let sessionId = currentContextSessionId(state, ctx);
5130
+ let sessionId = currentSupervisorSessionId(state, ctx);
5248
5131
  return !(!sessionId || question.parentSessionId !== sessionId || (state.sessionGeneration ?? 0) !== question.parentGeneration);
5249
5132
  }
5250
5133
  function notifyQuestionTerminal(pi, question, channelDir) {
@@ -5965,7 +5848,7 @@ function registerWaitTool(pi, state, enabled = resolveWaitToolConfig().enabled,
5965
5848
  label: "Subagent Wait",
5966
5849
  description: `Block until background work owned by this session changes, then return.
5967
5850
 
5968
- In an interactive chat, do not call this merely to wait: return control to the user and let Pi wake the session on completion. Call it when the current request must run to completion in this turn, when a skill cannot return before its work finishes, or in a non-interactive run where there is no next turn.
5851
+ Call this when the current turn or skill must finish after its children. For normal interactive completion, yield and let lunR wake the session. Headless sessions auto-drain current-session work after the agent turn.
5969
5852
 
5970
5853
  \u2022 { } \u2014 return when the first initially active async run or registered provider item finishes, or when a subagent needs attention.
5971
5854
  \u2022 { all: true } \u2014 wait for every async run and provider item that was active when the call began.
@@ -6165,7 +6048,32 @@ function buildCompletionDetails(result2) {
6165
6048
  status,
6166
6049
  ...result2.source ? { source: result2.source } : {},
6167
6050
  ...taskInfo ? { taskInfo } : {},
6168
- resultPreview: summary,
6051
+ resultPreview: [
6052
+ result2.id ? `Run: ${result2.id}` : void 0,
6053
+ result2.asyncDir ? `Async dir: ${result2.asyncDir}` : void 0,
6054
+ result2.results?.length ? result2.results.map((child, index) => {
6055
+ let output = child.summary ?? (child.error ? `${child.error}
6056
+
6057
+ Output:
6058
+ ${child.output}` : child.output), report = child.acceptance?.childReport, childIndex = child.index ?? index;
6059
+ return [
6060
+ `${childIndex + 1}. ${child.agent} [${child.status ?? resolveSubagentResultStatus({ success: child.success, state: result2.state })}]`,
6061
+ child.artifactPath ? `Output artifact: ${child.artifactPath}` : void 0,
6062
+ child.sessionPath ? `Session: ${child.sessionPath}` : void 0,
6063
+ child.sessionPath && result2.id && result2.source !== "foreground" ? `Revive: subagent({ action: "resume", id: ${JSON.stringify(result2.id)}, index: ${childIndex}, message: "..." })` : void 0,
6064
+ ...formatNestedResultLines(child.children),
6065
+ output,
6066
+ report ? `\`\`\`acceptance-report
6067
+ ${JSON.stringify(report, null, 2)}
6068
+ \`\`\`` : void 0
6069
+ ].filter((line) => line !== void 0).join(`
6070
+ `);
6071
+ }).join(`
6072
+
6073
+ `) : summary
6074
+ ].filter((line) => line !== void 0).join(`
6075
+
6076
+ `),
6169
6077
  ...typeof result2.durationMs == "number" ? { durationMs: result2.durationMs } : {},
6170
6078
  ...session ? { sessionLabel: session.label, sessionValue: session.value } : {}
6171
6079
  };
@@ -6285,7 +6193,7 @@ var CUSTOM_TOOL_DESCRIPTION_FILE = "subagent-tool-description.md", CUSTOM_TOOL_D
6285
6193
  ${SUBAGENT_TIER_GUIDANCE}
6286
6194
  \u2022 permissions is "full" or "read-only". Omitted permissions means full. Plan-mode parents must pass permissions: "read-only"; full or omitted launches are rejected.
6287
6195
  \u2022 Keep execution and control separate: omit action for SINGLE/PARALLEL/CHAIN execution; use action only for status/interrupt/stop/resume/steer/append-step/doctor/watchdog.status|check|recommend-model/schedule*.
6288
- \u2022 Async/background runs: launch with async:true only when work can proceed independently. Do not sleep or poll status just to wait. In an interactive session, normally return control and let lunR wake you; use subagent_wait when this request must run to completion in the current turn or skill. Headless sessions auto-drain current-session work.
6196
+ \u2022 ${SUBAGENT_ASYNC_GUIDANCE}
6289
6197
  \u2022 Child-safety boundary: ordinary children are not orchestrators and must not run subagents. Only explicitly configured fanout children may use the child-safe subagent tool, still bounded by depth/session limits.
6290
6198
  \u2022 Writing/review safety: keep one full-access writer for the same cwd/worktree. Use fresh-context permissions: "read-only" children for independent review, then have the parent synthesize and apply fixes as the sole writer unless an isolated worktree was intentionally requested.
6291
6199
  \u2022 Artifacts/status essentials: chain outputs live under {chain_dir}; async runs expose asyncId/asyncDir with status.json, events.jsonl, output logs, and status via { action: "status", id }. Include output paths and residual risks when reporting results.`, FULL_SUBAGENT_TOOL_DESCRIPTION = `Delegate work to generic children by prompting them directly. There are no named agent types.
@@ -6348,7 +6256,7 @@ CONTROL:
6348
6256
  \u2022 Opt-in schedule actions: schedule, schedule-list, schedule-status, schedule-cancel. Schedule only explicit delayed runs the user asked for.
6349
6257
 
6350
6258
  ASYNC / WAIT:
6351
- \u2022 async:true detaches background work. Do not sleep or poll just to wait. Interactive sessions normally yield for completion notifications; use subagent_wait for run-to-completion turns or skills. Headless sessions auto-drain current-session work.
6259
+ \u2022 ${SUBAGENT_ASYNC_GUIDANCE}
6352
6260
  \u2022 Status and artifacts live under asyncId/asyncDir with status.json, events.jsonl, output logs, session files, and { action:"status", id:"..." }.
6353
6261
 
6354
6262
  SAFETY:
@@ -6478,15 +6386,43 @@ function effectiveParallelTaskCount(tasks) {
6478
6386
  return total + count;
6479
6387
  }, 0);
6480
6388
  }
6481
- function callIsAsync(args, asyncByDefault) {
6482
- return args?.clarify === !0 ? !1 : args?.async === !0 ? !0 : args?.async === !1 ? !1 : asyncByDefault === !0;
6483
- }
6484
- function renderSubagentCall(args, theme, context, options) {
6389
+ function matchingActionJobs(state, requestedId) {
6390
+ let jobs = /* @__PURE__ */ new Map();
6391
+ for (let job of state.asyncJobs.values())
6392
+ jobs.set(job.asyncId, job);
6393
+ for (let job of state.fleetJobs?.values() ?? [])
6394
+ jobs.set(job.asyncId, job);
6395
+ let exact = jobs.get(requestedId);
6396
+ return exact ? [exact] : [...jobs.values()].filter((job) => job.asyncId.startsWith(requestedId));
6397
+ }
6398
+ function resolveSubagentActionDisplayTitle(args, state) {
6399
+ let requestedId = (args.id || args.runId || "").trim();
6400
+ if (!requestedId)
6401
+ return;
6402
+ let matches = matchingActionJobs(state, requestedId);
6403
+ if (matches.length !== 1)
6404
+ return;
6405
+ let job = matches[0], steps = job.steps ?? [];
6406
+ if (Number.isInteger(args.index)) {
6407
+ let step = steps.find((candidate) => candidate.index === args.index) ?? steps[args.index];
6408
+ return step ? childRowLabel(step) : void 0;
6409
+ }
6410
+ if (steps.length === 1)
6411
+ return childRowLabel(steps[0]);
6412
+ if (steps.length > 1)
6413
+ return `${job.mode ?? "subagent"} run`;
6414
+ if (job.agents?.length === 1)
6415
+ return job.agents[0];
6416
+ if (job.agents?.length)
6417
+ return `${job.mode ?? "subagent"} run`;
6418
+ }
6419
+ function renderSubagentCall(rawArgs, theme, context, options) {
6420
+ let args = resolveSubagentRequestParams(rawArgs);
6485
6421
  if (args.action) {
6486
- let target = args.id || args.runId || "";
6422
+ let target = context?.result?.details?.displayTitle || options?.resolveActionTitle?.(args) || args.id || args.runId || "";
6487
6423
  return new Text2(`${theme.fg("toolTitle", theme.bold("subagent "))}${args.action}${target ? ` ${theme.fg("accent", target)}` : ""}`, 0, 0);
6488
6424
  }
6489
- let isParallel = (args.tasks?.length ?? 0) > 0, parallelCount = effectiveParallelTaskCount(args.tasks), asyncMark = callIsAsync(args, options?.asyncByDefault) ? `${theme.fg("warning", "async")} ` : "";
6425
+ let isParallel = (args.tasks?.length ?? 0) > 0, parallelCount = effectiveParallelTaskCount(args.tasks), asyncMark = subagentLaunchRunsAsync(args) ? `${theme.fg("warning", "async")} ` : "";
6490
6426
  if (args.chain?.length)
6491
6427
  return new Text2(`${theme.fg("toolTitle", theme.bold("subagent "))}${asyncMark}chain (${args.chain.length})`, 0, 0);
6492
6428
  if (isParallel)
@@ -6501,7 +6437,7 @@ function renderSubagentNotify(details, theme) {
6501
6437
  function ensureSubagentResultAnimation(context) {
6502
6438
  let state = context.state;
6503
6439
  state.subagentResultAnimationTimer || typeof context.invalidate == "function" && (state.frame === void 0 && (state.frame = 0), state.subagentResultAnimationTimer = setInterval(() => {
6504
- state.frame = ((state.frame ?? 0) + 1) % 10;
6440
+ state.frame = (state.frame ?? 0) + 1;
6505
6441
  try {
6506
6442
  let entries = state.animEntries;
6507
6443
  if (entries?.length && typeof context.requestRender == "function") {
@@ -6513,7 +6449,7 @@ function ensureSubagentResultAnimation(context) {
6513
6449
  context.invalidate();
6514
6450
  } catch {
6515
6451
  }
6516
- }, 80));
6452
+ }, SUBAGENT_PAINT_INTERVAL_MS));
6517
6453
  }
6518
6454
  function isSlashResultError(result2) {
6519
6455
  return result2.details?.results.some((entry) => entry.exitCode !== 0 && entry.progress?.status !== "running") || !1;
@@ -6543,7 +6479,7 @@ function registerSubagentExtension(pi) {
6543
6479
  } catch {
6544
6480
  }
6545
6481
  ensureAccessibleDir(RESULTS_DIR), ensureAccessibleDir(ASYNC_DIR), cleanupOldChainDirs();
6546
- let config = loadConfig(), waitToolConfig = resolveWaitToolConfig(config.waitTool), asyncByDefault = config.asyncByDefault === !0, tempArtifactsDir = getArtifactsDir(null);
6482
+ let config = normalizeAsyncLaunchConfig(loadConfig()), waitToolConfig = resolveWaitToolConfig(config.waitTool), tempArtifactsDir = getArtifactsDir(null);
6547
6483
  cleanupAllArtifactDirs(DEFAULT_ARTIFACT_CONFIG.cleanupDays);
6548
6484
  let state = {
6549
6485
  baseCwd: "",
@@ -6594,18 +6530,17 @@ function registerSubagentExtension(pi) {
6594
6530
  }), markLaunchReady = () => {
6595
6531
  launchReady || (launchReady = !0, pendingLaunches.delete(launchReadyPromise), pendingAsyncLaunches.delete(launchReadyPromise), resolveLaunchReady());
6596
6532
  };
6597
- pendingLaunches.add(launchReadyPromise), (params.task || params.tasks || params.chain) && !params.clarify && (params.async === !0 || params.async === void 0 && asyncByDefault || config.forceTopLevelAsync === !0) && pendingAsyncLaunches.add(launchReadyPromise);
6533
+ pendingLaunches.add(launchReadyPromise), isAsyncSubagentExecution(resolveSubagentRequestParams(params)) && pendingAsyncLaunches.add(launchReadyPromise);
6598
6534
  try {
6599
6535
  let currentGeneration = generation;
6600
6536
  if (signal?.throwIfAborted(), !executorPromise) {
6601
- let pending = import("./subagent-executor-SRFC26SJ.js").then(({ createSubagentExecutor }) => {
6537
+ let pending = import("./subagent-executor-MH4A7CCF.js").then(({ createSubagentExecutor }) => {
6602
6538
  if (generation !== currentGeneration)
6603
6539
  throw new Error("Subagent session changed before initialization");
6604
6540
  return createSubagentExecutor({
6605
6541
  pi,
6606
6542
  state,
6607
6543
  config,
6608
- asyncByDefault,
6609
6544
  waitToolEnabled: waitToolConfig.enabled,
6610
6545
  handleScheduledRunAction: (params2, ctx2) => scheduledRunManager.handleToolCall(params2, ctx2),
6611
6546
  watchdog: mainWatchdog,
@@ -6645,7 +6580,11 @@ function registerSubagentExtension(pi) {
6645
6580
  return new Text2(theme.fg(details.state === "recovered" ? "warning" : "error", formatSteeringNotice(details)), 0, 0);
6646
6581
  }), pi.registerMessageRenderer(SUBAGENT_CONTROL_MESSAGE_TYPE, () => {
6647
6582
  });
6648
- let executeSubagentCollapsed = (id, params, signal, onUpdate, ctx) => (ctx.hasUI && ctx.ui.setToolsExpanded(!1), executor.execute(id, params, signal, onUpdate, ctx)), slashBridge = registerSlashSubagentBridge({
6583
+ let executeSubagentCollapsed = async (id, params, signal, onUpdate, ctx) => {
6584
+ ctx.hasUI && ctx.ui.setToolsExpanded(!1);
6585
+ let displayTitle = params.action === "steer" ? resolveSubagentActionDisplayTitle(params, state) : void 0, result2 = await executor.execute(id, params, signal, onUpdate, ctx);
6586
+ return displayTitle && result2.details && (result2.details.displayTitle = displayTitle), result2;
6587
+ }, slashBridge = registerSlashSubagentBridge({
6649
6588
  events: pi.events,
6650
6589
  getContext: () => state.lastUiContext,
6651
6590
  execute: (id, params, signal, onUpdate, ctx) => executeSubagentCollapsed(id, params, signal, onUpdate, ctx)
@@ -6670,7 +6609,9 @@ function registerSubagentExtension(pi) {
6670
6609
  execute(id, params, signal, onUpdate, ctx) {
6671
6610
  return executeSubagentCollapsed(id, params, signal, onUpdate, ctx);
6672
6611
  },
6673
- renderCall: (args, theme, context) => renderSubagentCall(args, theme, context, { asyncByDefault }),
6612
+ renderCall: (args, theme, context) => renderSubagentCall(args, theme, context, {
6613
+ resolveActionTitle: (params) => resolveSubagentActionDisplayTitle(params, state)
6614
+ }),
6674
6615
  renderResult(result2, options, theme, context) {
6675
6616
  subagentResultIsRunning(result2) ? ensureSubagentResultAnimation(context) : clearLegacyResultAnimationTimer(context);
6676
6617
  let state2 = context.state, entries = [];