@bastani/atomic 0.9.2 → 0.9.3-alpha.2

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 (606) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/README.md +2 -2
  3. package/dist/builtin/cursor/CHANGELOG.md +15 -0
  4. package/dist/builtin/cursor/README.md +2 -1
  5. package/dist/builtin/cursor/package.json +2 -2
  6. package/dist/builtin/cursor/src/cursor-models-raw.json +2 -9
  7. package/dist/builtin/cursor/src/model-mapper.ts +14 -3
  8. package/dist/builtin/cursor/src/proto/protobuf-codec-base64.ts +22 -0
  9. package/dist/builtin/cursor/src/proto/protobuf-codec-request.ts +53 -13
  10. package/dist/builtin/cursor/src/proto/protobuf-codec-wire.ts +24 -7
  11. package/dist/builtin/cursor/src/proto/protobuf-codec.ts +3 -2
  12. package/dist/builtin/cursor/src/stream.ts +5 -11
  13. package/dist/builtin/cursor/src/transport-types.ts +3 -0
  14. package/dist/builtin/cursor/src/transport.ts +1 -0
  15. package/dist/builtin/intercom/package.json +1 -1
  16. package/dist/builtin/mcp/CHANGELOG.md +6 -0
  17. package/dist/builtin/mcp/direct-tools.ts +4 -2
  18. package/dist/builtin/mcp/package.json +1 -1
  19. package/dist/builtin/mcp/proxy-call.ts +3 -1
  20. package/dist/builtin/mcp/utils.ts +18 -7
  21. package/dist/builtin/subagents/CHANGELOG.md +20 -0
  22. package/dist/builtin/subagents/README.md +6 -6
  23. package/dist/builtin/subagents/agents/code-simplifier.md +7 -6
  24. package/dist/builtin/subagents/agents/codebase-analyzer.md +5 -4
  25. package/dist/builtin/subagents/agents/codebase-locator.md +3 -3
  26. package/dist/builtin/subagents/agents/codebase-online-researcher.md +10 -10
  27. package/dist/builtin/subagents/agents/codebase-pattern-finder.md +4 -4
  28. package/dist/builtin/subagents/agents/codebase-research-analyzer.md +3 -3
  29. package/dist/builtin/subagents/agents/codebase-research-locator.md +4 -4
  30. package/dist/builtin/subagents/agents/debugger.md +5 -5
  31. package/dist/builtin/subagents/agents/worker.md +56 -0
  32. package/dist/builtin/subagents/package.json +1 -1
  33. package/dist/builtin/subagents/skills/subagent/SKILL.md +11 -11
  34. package/dist/builtin/subagents/src/agents/agent-loaders.ts +3 -5
  35. package/dist/builtin/subagents/src/agents/agent-management-helpers.ts +3 -3
  36. package/dist/builtin/subagents/src/extension/fanout-child.ts +1 -0
  37. package/dist/builtin/subagents/src/extension/index.ts +6 -3
  38. package/dist/builtin/subagents/src/extension/schemas.ts +2 -7
  39. package/dist/builtin/subagents/src/intercom/result-intercom.ts +4 -3
  40. package/dist/builtin/subagents/src/runs/background/async-job-tracker.ts +1 -4
  41. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-single.ts +15 -1
  42. package/dist/builtin/subagents/src/runs/foreground/subagent-executor.ts +35 -1
  43. package/dist/builtin/subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +1 -1
  44. package/dist/builtin/subagents/src/runs/shared/nested-render.ts +2 -2
  45. package/dist/builtin/subagents/src/runs/shared/pi-args.ts +2 -1
  46. package/dist/builtin/subagents/src/runs/shared/subagent-prompt-runtime.ts +4 -2
  47. package/dist/builtin/subagents/src/shared/types-async.ts +1 -0
  48. package/dist/builtin/subagents/src/shared/types-depth.ts +5 -5
  49. package/dist/builtin/subagents/src/shared/types-runtime.ts +2 -1
  50. package/dist/builtin/subagents/src/slash/prompt-template-bridge.ts +27 -5
  51. package/dist/builtin/subagents/src/tui/render-event-formatting.ts +2 -2
  52. package/dist/builtin/subagents/src/tui/render-layout.ts +27 -4
  53. package/dist/builtin/subagents/src/tui/render-result-animation.ts +22 -31
  54. package/dist/builtin/subagents/src/tui/render-result-compact.ts +6 -6
  55. package/dist/builtin/subagents/src/tui/render-result.ts +20 -19
  56. package/dist/builtin/subagents/src/tui/render-status-progress.ts +3 -3
  57. package/dist/builtin/subagents/src/tui/render-widget.ts +46 -7
  58. package/dist/builtin/subagents/src/tui/render.ts +2 -2
  59. package/dist/builtin/web-access/package.json +1 -1
  60. package/dist/builtin/workflows/CHANGELOG.md +56 -0
  61. package/dist/builtin/workflows/README.md +3 -3
  62. package/dist/builtin/workflows/builtin/goal-artifacts.ts +11 -6
  63. package/dist/builtin/workflows/builtin/goal-ledger.ts +33 -1
  64. package/dist/builtin/workflows/builtin/goal-prompts.ts +23 -28
  65. package/dist/builtin/workflows/builtin/goal-reducer.ts +2 -2
  66. package/dist/builtin/workflows/builtin/goal-reports.ts +2 -5
  67. package/dist/builtin/workflows/builtin/goal-review.ts +1 -1
  68. package/dist/builtin/workflows/builtin/goal-runner.ts +10 -17
  69. package/dist/builtin/workflows/builtin/open-claude-design-feedback.ts +3 -3
  70. package/dist/builtin/workflows/builtin/open-claude-design-phases.ts +1 -3
  71. package/dist/builtin/workflows/builtin/open-claude-design-setup.ts +1 -1
  72. package/dist/builtin/workflows/builtin/ralph-core.ts +7 -17
  73. package/dist/builtin/workflows/builtin/ralph-runner.ts +11 -18
  74. package/dist/builtin/workflows/builtin/shared-prompts.ts +1 -1
  75. package/dist/builtin/workflows/package.json +1 -1
  76. package/dist/builtin/workflows/src/authoring.d.ts +1 -1
  77. package/dist/builtin/workflows/src/durable/backend.ts +343 -0
  78. package/dist/builtin/workflows/src/durable/child-primitive.ts +79 -0
  79. package/dist/builtin/workflows/src/durable/dbos-backend.ts +421 -0
  80. package/dist/builtin/workflows/src/durable/dbos-envelope.ts +171 -0
  81. package/dist/builtin/workflows/src/durable/factory.ts +96 -0
  82. package/dist/builtin/workflows/src/durable/file-backend.ts +433 -0
  83. package/dist/builtin/workflows/src/durable/index.ts +73 -0
  84. package/dist/builtin/workflows/src/durable/resume-catalog.ts +217 -0
  85. package/dist/builtin/workflows/src/durable/resume-runtime.ts +299 -0
  86. package/dist/builtin/workflows/src/durable/scoped-backend.ts +171 -0
  87. package/dist/builtin/workflows/src/durable/stage-primitive.ts +284 -0
  88. package/dist/builtin/workflows/src/durable/tool-primitive.ts +180 -0
  89. package/dist/builtin/workflows/src/durable/types.ts +168 -0
  90. package/dist/builtin/workflows/src/durable/ui-primitive.ts +96 -0
  91. package/dist/builtin/workflows/src/engine/options.ts +3 -0
  92. package/dist/builtin/workflows/src/engine/primitives/parallel.ts +2 -2
  93. package/dist/builtin/workflows/src/engine/primitives/task.ts +4 -4
  94. package/dist/builtin/workflows/src/engine/primitives/ui.ts +22 -8
  95. package/dist/builtin/workflows/src/engine/primitives/workflow.ts +8 -0
  96. package/dist/builtin/workflows/src/engine/run-durable-finalize.ts +69 -0
  97. package/dist/builtin/workflows/src/engine/run-durable-stage-session.ts +31 -0
  98. package/dist/builtin/workflows/src/engine/run.ts +148 -6
  99. package/dist/builtin/workflows/src/engine/runtime.ts +8 -2
  100. package/dist/builtin/workflows/src/extension/config-loader.ts +35 -15
  101. package/dist/builtin/workflows/src/extension/discovery.ts +20 -8
  102. package/dist/builtin/workflows/src/extension/extension-factory.ts +6 -12
  103. package/dist/builtin/workflows/src/extension/extension-lifecycle.ts +5 -1
  104. package/dist/builtin/workflows/src/extension/extension-runtime-state.ts +4 -2
  105. package/dist/builtin/workflows/src/extension/runtime.ts +48 -9
  106. package/dist/builtin/workflows/src/extension/wiring.ts +1 -1
  107. package/dist/builtin/workflows/src/extension/workflow-run-control-command.ts +143 -4
  108. package/dist/builtin/workflows/src/runs/background/quit.ts +61 -0
  109. package/dist/builtin/workflows/src/runs/background/status.ts +1 -0
  110. package/dist/builtin/workflows/src/runs/foreground/executor-direct-helpers.ts +5 -5
  111. package/dist/builtin/workflows/src/runs/foreground/executor-stage-call.ts +74 -33
  112. package/dist/builtin/workflows/src/runs/foreground/executor-stage-context.ts +20 -1
  113. package/dist/builtin/workflows/src/runs/foreground/executor-stage-factory.ts +8 -7
  114. package/dist/builtin/workflows/src/runs/foreground/executor-stage-replay.ts +1 -0
  115. package/dist/builtin/workflows/src/runs/foreground/executor-stage-types.ts +1 -1
  116. package/dist/builtin/workflows/src/runs/foreground/executor-types.ts +19 -2
  117. package/dist/builtin/workflows/src/runs/foreground/stage-runner-context.ts +4 -0
  118. package/dist/builtin/workflows/src/runs/foreground/stage-runner-controller.ts +10 -10
  119. package/dist/builtin/workflows/src/runs/foreground/stage-runner-options.ts +5 -1
  120. package/dist/builtin/workflows/src/runs/foreground/stage-runner-send-user-message.ts +25 -0
  121. package/dist/builtin/workflows/src/runs/foreground/stage-runner-types.ts +3 -0
  122. package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +16 -0
  123. package/dist/builtin/workflows/src/shared/authoring-contract-stage.ts +20 -0
  124. package/dist/builtin/workflows/src/shared/authoring-contract-ui.d.ts +23 -1
  125. package/dist/builtin/workflows/src/shared/authoring-contract-ui.ts +30 -1
  126. package/dist/builtin/workflows/src/shared/store-public-types.ts +6 -2
  127. package/dist/builtin/workflows/src/shared/store-run-methods.ts +12 -6
  128. package/dist/builtin/workflows/src/shared/types.ts +55 -0
  129. package/dist/builtin/workflows/src/tui/dispatch-confirm.ts +11 -10
  130. package/dist/builtin/workflows/src/tui/graph-view-constants.ts +1 -1
  131. package/dist/builtin/workflows/src/tui/graph-view-graph-render.ts +41 -0
  132. package/dist/builtin/workflows/src/tui/graph-view-input.ts +82 -24
  133. package/dist/builtin/workflows/src/tui/graph-view-render.ts +7 -0
  134. package/dist/builtin/workflows/src/tui/graph-view-state.ts +22 -2
  135. package/dist/builtin/workflows/src/tui/graph-view-types.ts +4 -5
  136. package/dist/builtin/workflows/src/tui/overlay-adapter.ts +9 -11
  137. package/dist/builtin/workflows/src/tui/stage-chat-view-footer-status.ts +9 -3
  138. package/dist/builtin/workflows/src/tui/stage-chat-view-input.ts +11 -2
  139. package/dist/builtin/workflows/src/tui/stage-chat-view-live-events.ts +35 -0
  140. package/dist/builtin/workflows/src/tui/stage-chat-view-state.ts +51 -17
  141. package/dist/builtin/workflows/src/tui/stage-chat-view-status.ts +36 -0
  142. package/dist/builtin/workflows/src/tui/stage-chat-view-types.ts +5 -1
  143. package/dist/builtin/workflows/src/tui/stage-chat-view.ts +3 -1
  144. package/dist/builtin/workflows/src/tui/status-list.ts +14 -2
  145. package/dist/builtin/workflows/src/tui/widget.ts +23 -8
  146. package/dist/builtin/workflows/src/tui/workflow-attach-pane-types.ts +5 -4
  147. package/dist/builtin/workflows/src/tui/workflow-attach-pane.ts +8 -8
  148. package/dist/builtin/workflows/src/tui/workflow-resume-selector.ts +151 -0
  149. package/dist/cli/args.d.ts.map +1 -1
  150. package/dist/cli/args.js +9 -9
  151. package/dist/cli/args.js.map +1 -1
  152. package/dist/config-self-update.d.ts.map +1 -1
  153. package/dist/config-self-update.js +3 -4
  154. package/dist/config-self-update.js.map +1 -1
  155. package/dist/config.d.ts.map +1 -1
  156. package/dist/config.js +4 -5
  157. package/dist/config.js.map +1 -1
  158. package/dist/core/agent-session-bash.d.ts +1 -0
  159. package/dist/core/agent-session-bash.d.ts.map +1 -1
  160. package/dist/core/agent-session-bash.js +1 -0
  161. package/dist/core/agent-session-bash.js.map +1 -1
  162. package/dist/core/agent-session-tool-registry.d.ts.map +1 -1
  163. package/dist/core/agent-session-tool-registry.js +23 -0
  164. package/dist/core/agent-session-tool-registry.js.map +1 -1
  165. package/dist/core/bash-executor.d.ts +2 -0
  166. package/dist/core/bash-executor.d.ts.map +1 -1
  167. package/dist/core/bash-executor.js +1 -0
  168. package/dist/core/bash-executor.js.map +1 -1
  169. package/dist/core/compaction/compaction.d.ts +29 -0
  170. package/dist/core/compaction/compaction.d.ts.map +1 -1
  171. package/dist/core/compaction/compaction.js +36 -1
  172. package/dist/core/compaction/compaction.js.map +1 -1
  173. package/dist/core/compaction/context-compaction-metrics.d.ts +14 -2
  174. package/dist/core/compaction/context-compaction-metrics.d.ts.map +1 -1
  175. package/dist/core/compaction/context-compaction-metrics.js +50 -1
  176. package/dist/core/compaction/context-compaction-metrics.js.map +1 -1
  177. package/dist/core/compaction/context-compaction-prompt.d.ts.map +1 -1
  178. package/dist/core/compaction/context-compaction-prompt.js +2 -0
  179. package/dist/core/compaction/context-compaction-prompt.js.map +1 -1
  180. package/dist/core/compaction/context-compaction-runner.d.ts.map +1 -1
  181. package/dist/core/compaction/context-compaction-runner.js +1 -1
  182. package/dist/core/compaction/context-compaction-runner.js.map +1 -1
  183. package/dist/core/compaction/context-deletion-application.d.ts.map +1 -1
  184. package/dist/core/compaction/context-deletion-application.js +5 -5
  185. package/dist/core/compaction/context-deletion-application.js.map +1 -1
  186. package/dist/core/compaction/context-deletion-targets.d.ts +2 -0
  187. package/dist/core/compaction/context-deletion-targets.d.ts.map +1 -1
  188. package/dist/core/compaction/context-deletion-targets.js +23 -3
  189. package/dist/core/compaction/context-deletion-targets.js.map +1 -1
  190. package/dist/core/compaction/context-deletion-tool-definitions.d.ts +6 -0
  191. package/dist/core/compaction/context-deletion-tool-definitions.d.ts.map +1 -1
  192. package/dist/core/compaction/context-deletion-tool-definitions.js.map +1 -1
  193. package/dist/core/compaction/context-deletion-tools.d.ts.map +1 -1
  194. package/dist/core/compaction/context-deletion-tools.js +18 -10
  195. package/dist/core/compaction/context-deletion-tools.js.map +1 -1
  196. package/dist/core/compaction/context-transcript-analysis.d.ts.map +1 -1
  197. package/dist/core/compaction/context-transcript-analysis.js +2 -4
  198. package/dist/core/compaction/context-transcript-analysis.js.map +1 -1
  199. package/dist/core/copilot-gemini-tool-arguments.d.ts.map +1 -1
  200. package/dist/core/copilot-gemini-tool-arguments.js +2 -60
  201. package/dist/core/copilot-gemini-tool-arguments.js.map +1 -1
  202. package/dist/core/extensions/context-types.d.ts +2 -0
  203. package/dist/core/extensions/context-types.d.ts.map +1 -1
  204. package/dist/core/extensions/context-types.js.map +1 -1
  205. package/dist/core/extensions/index.d.ts +2 -2
  206. package/dist/core/extensions/index.d.ts.map +1 -1
  207. package/dist/core/extensions/index.js +1 -1
  208. package/dist/core/extensions/index.js.map +1 -1
  209. package/dist/core/extensions/loader-virtual-modules.d.ts.map +1 -1
  210. package/dist/core/extensions/loader-virtual-modules.js +57 -32
  211. package/dist/core/extensions/loader-virtual-modules.js.map +1 -1
  212. package/dist/core/extensions/runner-context.d.ts.map +1 -1
  213. package/dist/core/extensions/runner-context.js +11 -0
  214. package/dist/core/extensions/runner-context.js.map +1 -1
  215. package/dist/core/extensions/tool-events.d.ts +13 -13
  216. package/dist/core/extensions/tool-events.d.ts.map +1 -1
  217. package/dist/core/extensions/tool-events.js +3 -3
  218. package/dist/core/extensions/tool-events.js.map +1 -1
  219. package/dist/core/extensions/types.d.ts +1 -1
  220. package/dist/core/extensions/types.d.ts.map +1 -1
  221. package/dist/core/extensions/types.js +1 -1
  222. package/dist/core/extensions/types.js.map +1 -1
  223. package/dist/core/flattened-tool-arguments.d.ts +18 -0
  224. package/dist/core/flattened-tool-arguments.d.ts.map +1 -1
  225. package/dist/core/flattened-tool-arguments.js +104 -0
  226. package/dist/core/flattened-tool-arguments.js.map +1 -1
  227. package/dist/core/messages.d.ts +1 -0
  228. package/dist/core/messages.d.ts.map +1 -1
  229. package/dist/core/messages.js +46 -1
  230. package/dist/core/messages.js.map +1 -1
  231. package/dist/core/sdk-exports.d.ts +1 -1
  232. package/dist/core/sdk-exports.d.ts.map +1 -1
  233. package/dist/core/sdk-exports.js +1 -1
  234. package/dist/core/sdk-exports.js.map +1 -1
  235. package/dist/core/sdk-types.d.ts +2 -2
  236. package/dist/core/sdk-types.d.ts.map +1 -1
  237. package/dist/core/sdk-types.js.map +1 -1
  238. package/dist/core/sdk.d.ts.map +1 -1
  239. package/dist/core/sdk.js +12 -0
  240. package/dist/core/sdk.js.map +1 -1
  241. package/dist/core/session-manager-core.d.ts +15 -7
  242. package/dist/core/session-manager-core.d.ts.map +1 -1
  243. package/dist/core/session-manager-core.js +20 -9
  244. package/dist/core/session-manager-core.js.map +1 -1
  245. package/dist/core/session-manager-entries.d.ts +2 -2
  246. package/dist/core/session-manager-entries.d.ts.map +1 -1
  247. package/dist/core/session-manager-entries.js +9 -3
  248. package/dist/core/session-manager-entries.js.map +1 -1
  249. package/dist/core/session-manager-history.d.ts.map +1 -1
  250. package/dist/core/session-manager-history.js +2 -1
  251. package/dist/core/session-manager-history.js.map +1 -1
  252. package/dist/core/session-manager-list.d.ts +3 -3
  253. package/dist/core/session-manager-list.d.ts.map +1 -1
  254. package/dist/core/session-manager-list.js +27 -8
  255. package/dist/core/session-manager-list.js.map +1 -1
  256. package/dist/core/session-manager-storage.d.ts +3 -1
  257. package/dist/core/session-manager-storage.d.ts.map +1 -1
  258. package/dist/core/session-manager-storage.js +55 -12
  259. package/dist/core/session-manager-storage.js.map +1 -1
  260. package/dist/core/session-manager-tool-dependencies.d.ts +10 -0
  261. package/dist/core/session-manager-tool-dependencies.d.ts.map +1 -0
  262. package/dist/core/session-manager-tool-dependencies.js +133 -0
  263. package/dist/core/session-manager-tool-dependencies.js.map +1 -0
  264. package/dist/core/session-manager-types.d.ts +22 -0
  265. package/dist/core/session-manager-types.d.ts.map +1 -1
  266. package/dist/core/session-manager-types.js.map +1 -1
  267. package/dist/core/session-manager.d.ts +2 -2
  268. package/dist/core/session-manager.d.ts.map +1 -1
  269. package/dist/core/session-manager.js +1 -1
  270. package/dist/core/session-manager.js.map +1 -1
  271. package/dist/core/settings-manager-basic-accessors.d.ts +4 -0
  272. package/dist/core/settings-manager-basic-accessors.d.ts.map +1 -1
  273. package/dist/core/settings-manager-basic-accessors.js +18 -0
  274. package/dist/core/settings-manager-basic-accessors.js.map +1 -1
  275. package/dist/core/settings-manager-resource-accessors.d.ts +4 -0
  276. package/dist/core/settings-manager-resource-accessors.d.ts.map +1 -1
  277. package/dist/core/settings-manager-resource-accessors.js +15 -0
  278. package/dist/core/settings-manager-resource-accessors.js.map +1 -1
  279. package/dist/core/settings-types.d.ts +11 -0
  280. package/dist/core/settings-types.d.ts.map +1 -1
  281. package/dist/core/settings-types.js.map +1 -1
  282. package/dist/core/system-prompt.d.ts +1 -1
  283. package/dist/core/system-prompt.d.ts.map +1 -1
  284. package/dist/core/system-prompt.js +3 -2
  285. package/dist/core/system-prompt.js.map +1 -1
  286. package/dist/core/tools/artifact-protocol.d.ts +11 -0
  287. package/dist/core/tools/artifact-protocol.d.ts.map +1 -0
  288. package/dist/core/tools/artifact-protocol.js +76 -0
  289. package/dist/core/tools/artifact-protocol.js.map +1 -0
  290. package/dist/core/tools/artifacts.d.ts +18 -0
  291. package/dist/core/tools/artifacts.d.ts.map +1 -0
  292. package/dist/core/tools/artifacts.js +90 -0
  293. package/dist/core/tools/artifacts.js.map +1 -0
  294. package/dist/core/tools/bash-async-jobs.d.ts +20 -0
  295. package/dist/core/tools/bash-async-jobs.d.ts.map +1 -0
  296. package/dist/core/tools/bash-async-jobs.js +59 -0
  297. package/dist/core/tools/bash-async-jobs.js.map +1 -0
  298. package/dist/core/tools/bash-async-output.d.ts +10 -0
  299. package/dist/core/tools/bash-async-output.d.ts.map +1 -0
  300. package/dist/core/tools/bash-async-output.js +80 -0
  301. package/dist/core/tools/bash-async-output.js.map +1 -0
  302. package/dist/core/tools/bash-interceptor.d.ts +10 -0
  303. package/dist/core/tools/bash-interceptor.d.ts.map +1 -0
  304. package/dist/core/tools/bash-interceptor.js +39 -0
  305. package/dist/core/tools/bash-interceptor.js.map +1 -0
  306. package/dist/core/tools/bash-leading-cd.d.ts +7 -0
  307. package/dist/core/tools/bash-leading-cd.d.ts.map +1 -0
  308. package/dist/core/tools/bash-leading-cd.js +59 -0
  309. package/dist/core/tools/bash-leading-cd.js.map +1 -0
  310. package/dist/core/tools/bash-pty-native.d.ts +14 -0
  311. package/dist/core/tools/bash-pty-native.d.ts.map +1 -0
  312. package/dist/core/tools/bash-pty-native.js +71 -0
  313. package/dist/core/tools/bash-pty-native.js.map +1 -0
  314. package/dist/core/tools/bash.d.ts +28 -17
  315. package/dist/core/tools/bash.d.ts.map +1 -1
  316. package/dist/core/tools/bash.js +152 -35
  317. package/dist/core/tools/bash.js.map +1 -1
  318. package/dist/core/tools/block-resolver.d.ts +16 -0
  319. package/dist/core/tools/block-resolver.d.ts.map +1 -0
  320. package/dist/core/tools/block-resolver.js +74 -0
  321. package/dist/core/tools/block-resolver.js.map +1 -0
  322. package/dist/core/tools/conflict-registry.d.ts +16 -0
  323. package/dist/core/tools/conflict-registry.d.ts.map +1 -0
  324. package/dist/core/tools/conflict-registry.js +44 -0
  325. package/dist/core/tools/conflict-registry.js.map +1 -0
  326. package/dist/core/tools/directory-tree.d.ts +13 -0
  327. package/dist/core/tools/directory-tree.d.ts.map +1 -0
  328. package/dist/core/tools/directory-tree.js +81 -0
  329. package/dist/core/tools/directory-tree.js.map +1 -0
  330. package/dist/core/tools/edit.d.ts +4 -29
  331. package/dist/core/tools/edit.d.ts.map +1 -1
  332. package/dist/core/tools/edit.js +136 -228
  333. package/dist/core/tools/edit.js.map +1 -1
  334. package/dist/core/tools/fetch-url.d.ts +74 -0
  335. package/dist/core/tools/fetch-url.d.ts.map +1 -0
  336. package/dist/core/tools/fetch-url.js +518 -0
  337. package/dist/core/tools/fetch-url.js.map +1 -0
  338. package/dist/core/tools/find.d.ts +27 -9
  339. package/dist/core/tools/find.d.ts.map +1 -1
  340. package/dist/core/tools/find.js +400 -176
  341. package/dist/core/tools/find.js.map +1 -1
  342. package/dist/core/tools/glob-path-utils.d.ts +8 -0
  343. package/dist/core/tools/glob-path-utils.d.ts.map +1 -0
  344. package/dist/core/tools/glob-path-utils.js +26 -0
  345. package/dist/core/tools/glob-path-utils.js.map +1 -0
  346. package/dist/core/tools/grep.d.ts +12 -0
  347. package/dist/core/tools/grep.d.ts.map +1 -1
  348. package/dist/core/tools/grep.js +141 -17
  349. package/dist/core/tools/grep.js.map +1 -1
  350. package/dist/core/tools/hashline-engine/apply.d.ts +11 -0
  351. package/dist/core/tools/hashline-engine/apply.d.ts.map +1 -0
  352. package/dist/core/tools/hashline-engine/apply.js +752 -0
  353. package/dist/core/tools/hashline-engine/apply.js.map +1 -0
  354. package/dist/core/tools/hashline-engine/block.d.ts +40 -0
  355. package/dist/core/tools/hashline-engine/block.d.ts.map +1 -0
  356. package/dist/core/tools/hashline-engine/block.js +117 -0
  357. package/dist/core/tools/hashline-engine/block.js.map +1 -0
  358. package/dist/core/tools/hashline-engine/diff-preview.d.ts +15 -0
  359. package/dist/core/tools/hashline-engine/diff-preview.d.ts.map +1 -0
  360. package/dist/core/tools/hashline-engine/diff-preview.js +98 -0
  361. package/dist/core/tools/hashline-engine/diff-preview.js.map +1 -0
  362. package/dist/core/tools/hashline-engine/format.d.ts +71 -0
  363. package/dist/core/tools/hashline-engine/format.d.ts.map +1 -0
  364. package/dist/core/tools/hashline-engine/format.js +178 -0
  365. package/dist/core/tools/hashline-engine/format.js.map +1 -0
  366. package/dist/core/tools/hashline-engine/fs.d.ts +81 -0
  367. package/dist/core/tools/hashline-engine/fs.d.ts.map +1 -0
  368. package/dist/core/tools/hashline-engine/fs.js +143 -0
  369. package/dist/core/tools/hashline-engine/fs.js.map +1 -0
  370. package/dist/core/tools/hashline-engine/index.d.ts +18 -0
  371. package/dist/core/tools/hashline-engine/index.d.ts.map +1 -0
  372. package/dist/core/tools/hashline-engine/index.js +20 -0
  373. package/dist/core/tools/hashline-engine/index.js.map +1 -0
  374. package/dist/core/tools/hashline-engine/input.d.ts +101 -0
  375. package/dist/core/tools/hashline-engine/input.d.ts.map +1 -0
  376. package/dist/core/tools/hashline-engine/input.js +398 -0
  377. package/dist/core/tools/hashline-engine/input.js.map +1 -0
  378. package/dist/core/tools/hashline-engine/messages.d.ts +99 -0
  379. package/dist/core/tools/hashline-engine/messages.d.ts.map +1 -0
  380. package/dist/core/tools/hashline-engine/messages.js +144 -0
  381. package/dist/core/tools/hashline-engine/messages.js.map +1 -0
  382. package/dist/core/tools/hashline-engine/mismatch.d.ts +45 -0
  383. package/dist/core/tools/hashline-engine/mismatch.d.ts.map +1 -0
  384. package/dist/core/tools/hashline-engine/mismatch.js +90 -0
  385. package/dist/core/tools/hashline-engine/mismatch.js.map +1 -0
  386. package/dist/core/tools/hashline-engine/normalize.d.ts +21 -0
  387. package/dist/core/tools/hashline-engine/normalize.d.ts.map +1 -0
  388. package/dist/core/tools/hashline-engine/normalize.js +33 -0
  389. package/dist/core/tools/hashline-engine/normalize.js.map +1 -0
  390. package/dist/core/tools/hashline-engine/parser.d.ts +24 -0
  391. package/dist/core/tools/hashline-engine/parser.d.ts.map +1 -0
  392. package/dist/core/tools/hashline-engine/parser.js +381 -0
  393. package/dist/core/tools/hashline-engine/parser.js.map +1 -0
  394. package/dist/core/tools/hashline-engine/patcher.d.ts +118 -0
  395. package/dist/core/tools/hashline-engine/patcher.d.ts.map +1 -0
  396. package/dist/core/tools/hashline-engine/patcher.js +341 -0
  397. package/dist/core/tools/hashline-engine/patcher.js.map +1 -0
  398. package/dist/core/tools/hashline-engine/prefixes.d.ts +43 -0
  399. package/dist/core/tools/hashline-engine/prefixes.d.ts.map +1 -0
  400. package/dist/core/tools/hashline-engine/prefixes.js +135 -0
  401. package/dist/core/tools/hashline-engine/prefixes.js.map +1 -0
  402. package/dist/core/tools/hashline-engine/recovery.d.ts +41 -0
  403. package/dist/core/tools/hashline-engine/recovery.d.ts.map +1 -0
  404. package/dist/core/tools/hashline-engine/recovery.js +168 -0
  405. package/dist/core/tools/hashline-engine/recovery.js.map +1 -0
  406. package/dist/core/tools/hashline-engine/snapshots.d.ts +65 -0
  407. package/dist/core/tools/hashline-engine/snapshots.d.ts.map +1 -0
  408. package/dist/core/tools/hashline-engine/snapshots.js +108 -0
  409. package/dist/core/tools/hashline-engine/snapshots.js.map +1 -0
  410. package/dist/core/tools/hashline-engine/stream.d.ts +3 -0
  411. package/dist/core/tools/hashline-engine/stream.d.ts.map +1 -0
  412. package/dist/core/tools/hashline-engine/stream.js +111 -0
  413. package/dist/core/tools/hashline-engine/stream.js.map +1 -0
  414. package/dist/core/tools/hashline-engine/tokenizer.d.ts +69 -0
  415. package/dist/core/tools/hashline-engine/tokenizer.d.ts.map +1 -0
  416. package/dist/core/tools/hashline-engine/tokenizer.js +430 -0
  417. package/dist/core/tools/hashline-engine/tokenizer.js.map +1 -0
  418. package/dist/core/tools/hashline-engine/types.d.ts +166 -0
  419. package/dist/core/tools/hashline-engine/types.d.ts.map +1 -0
  420. package/dist/core/tools/hashline-engine/types.js +9 -0
  421. package/dist/core/tools/hashline-engine/types.js.map +1 -0
  422. package/dist/core/tools/hashline.d.ts +29 -0
  423. package/dist/core/tools/hashline.d.ts.map +1 -0
  424. package/dist/core/tools/hashline.js +110 -0
  425. package/dist/core/tools/hashline.js.map +1 -0
  426. package/dist/core/tools/index.d.ts +6 -4
  427. package/dist/core/tools/index.d.ts.map +1 -1
  428. package/dist/core/tools/index.js +52 -35
  429. package/dist/core/tools/index.js.map +1 -1
  430. package/dist/core/tools/notebook.d.ts +38 -0
  431. package/dist/core/tools/notebook.d.ts.map +1 -0
  432. package/dist/core/tools/notebook.js +125 -0
  433. package/dist/core/tools/notebook.js.map +1 -0
  434. package/dist/core/tools/read-document-extract.d.ts +9 -0
  435. package/dist/core/tools/read-document-extract.d.ts.map +1 -0
  436. package/dist/core/tools/read-document-extract.js +212 -0
  437. package/dist/core/tools/read-document-extract.js.map +1 -0
  438. package/dist/core/tools/read-selectors.d.ts +24 -0
  439. package/dist/core/tools/read-selectors.d.ts.map +1 -0
  440. package/dist/core/tools/read-selectors.js +277 -0
  441. package/dist/core/tools/read-selectors.js.map +1 -0
  442. package/dist/core/tools/read-url.d.ts +37 -0
  443. package/dist/core/tools/read-url.d.ts.map +1 -0
  444. package/dist/core/tools/read-url.js +39 -0
  445. package/dist/core/tools/read-url.js.map +1 -0
  446. package/dist/core/tools/read.d.ts +11 -11
  447. package/dist/core/tools/read.d.ts.map +1 -1
  448. package/dist/core/tools/read.js +224 -94
  449. package/dist/core/tools/read.js.map +1 -1
  450. package/dist/core/tools/resource-selectors.d.ts +44 -0
  451. package/dist/core/tools/resource-selectors.d.ts.map +1 -0
  452. package/dist/core/tools/resource-selectors.js +808 -0
  453. package/dist/core/tools/resource-selectors.js.map +1 -0
  454. package/dist/core/tools/search-details.d.ts +26 -0
  455. package/dist/core/tools/search-details.d.ts.map +1 -0
  456. package/dist/core/tools/search-details.js +24 -0
  457. package/dist/core/tools/search-details.js.map +1 -0
  458. package/dist/core/tools/search-line-ranges.d.ts +11 -0
  459. package/dist/core/tools/search-line-ranges.d.ts.map +1 -0
  460. package/dist/core/tools/search-line-ranges.js +65 -0
  461. package/dist/core/tools/search-line-ranges.js.map +1 -0
  462. package/dist/core/tools/search-native.d.ts +97 -0
  463. package/dist/core/tools/search-native.d.ts.map +1 -0
  464. package/dist/core/tools/search-native.js +27 -0
  465. package/dist/core/tools/search-native.js.map +1 -0
  466. package/dist/core/tools/search.d.ts +24 -0
  467. package/dist/core/tools/search.d.ts.map +1 -0
  468. package/dist/core/tools/search.js +573 -0
  469. package/dist/core/tools/search.js.map +1 -0
  470. package/dist/core/tools/truncate.d.ts +4 -4
  471. package/dist/core/tools/truncate.d.ts.map +1 -1
  472. package/dist/core/tools/truncate.js +3 -3
  473. package/dist/core/tools/truncate.js.map +1 -1
  474. package/dist/core/tools/url-ip-guards.d.ts +4 -0
  475. package/dist/core/tools/url-ip-guards.d.ts.map +1 -0
  476. package/dist/core/tools/url-ip-guards.js +126 -0
  477. package/dist/core/tools/url-ip-guards.js.map +1 -0
  478. package/dist/core/tools/write.d.ts +12 -2
  479. package/dist/core/tools/write.d.ts.map +1 -1
  480. package/dist/core/tools/write.js +166 -14
  481. package/dist/core/tools/write.js.map +1 -1
  482. package/dist/core/trust-manager.d.ts.map +1 -1
  483. package/dist/core/trust-manager.js +2 -3
  484. package/dist/core/trust-manager.js.map +1 -1
  485. package/dist/index-extensions.d.ts +2 -2
  486. package/dist/index-extensions.d.ts.map +1 -1
  487. package/dist/index-extensions.js +1 -1
  488. package/dist/index-extensions.js.map +1 -1
  489. package/dist/index.d.ts +3 -3
  490. package/dist/index.d.ts.map +1 -1
  491. package/dist/index.js +3 -3
  492. package/dist/index.js.map +1 -1
  493. package/dist/modes/interactive/components/chat-session-host-runtime.d.ts +1 -0
  494. package/dist/modes/interactive/components/chat-session-host-runtime.d.ts.map +1 -1
  495. package/dist/modes/interactive/components/chat-session-host-runtime.js +12 -0
  496. package/dist/modes/interactive/components/chat-session-host-runtime.js.map +1 -1
  497. package/dist/modes/interactive/components/chat-session-host-terminal-cleanup.d.ts +4 -0
  498. package/dist/modes/interactive/components/chat-session-host-terminal-cleanup.d.ts.map +1 -0
  499. package/dist/modes/interactive/components/chat-session-host-terminal-cleanup.js +131 -0
  500. package/dist/modes/interactive/components/chat-session-host-terminal-cleanup.js.map +1 -0
  501. package/dist/modes/interactive/components/chat-session-host.d.ts +2 -0
  502. package/dist/modes/interactive/components/chat-session-host.d.ts.map +1 -1
  503. package/dist/modes/interactive/components/chat-session-host.js +7 -1
  504. package/dist/modes/interactive/components/chat-session-host.js.map +1 -1
  505. package/dist/modes/interactive/components/chat-transcript.d.ts.map +1 -1
  506. package/dist/modes/interactive/components/chat-transcript.js +15 -4
  507. package/dist/modes/interactive/components/chat-transcript.js.map +1 -1
  508. package/dist/modes/interactive/components/custom-editor.d.ts +1 -0
  509. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  510. package/dist/modes/interactive/components/custom-editor.js +9 -2
  511. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  512. package/dist/modes/interactive/components/settings-selector-handlers.d.ts.map +1 -1
  513. package/dist/modes/interactive/components/settings-selector-handlers.js +3 -0
  514. package/dist/modes/interactive/components/settings-selector-handlers.js.map +1 -1
  515. package/dist/modes/interactive/components/settings-selector-items.d.ts.map +1 -1
  516. package/dist/modes/interactive/components/settings-selector-items.js +7 -0
  517. package/dist/modes/interactive/components/settings-selector-items.js.map +1 -1
  518. package/dist/modes/interactive/components/settings-selector-types.d.ts +2 -0
  519. package/dist/modes/interactive/components/settings-selector-types.d.ts.map +1 -1
  520. package/dist/modes/interactive/components/settings-selector-types.js.map +1 -1
  521. package/dist/modes/interactive/components/tool-execution.d.ts +3 -0
  522. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  523. package/dist/modes/interactive/components/tool-execution.js +26 -0
  524. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  525. package/dist/modes/interactive/components/tree-selector-content.d.ts.map +1 -1
  526. package/dist/modes/interactive/components/tree-selector-content.js +0 -5
  527. package/dist/modes/interactive/components/tree-selector-content.js.map +1 -1
  528. package/dist/modes/interactive/interactive-auth-login.d.ts.map +1 -1
  529. package/dist/modes/interactive/interactive-auth-login.js +1 -0
  530. package/dist/modes/interactive/interactive-auth-login.js.map +1 -1
  531. package/dist/modes/interactive/interactive-autocomplete.d.ts.map +1 -1
  532. package/dist/modes/interactive/interactive-autocomplete.js +80 -2
  533. package/dist/modes/interactive/interactive-autocomplete.js.map +1 -1
  534. package/dist/modes/interactive/interactive-hotkeys-debug.d.ts.map +1 -1
  535. package/dist/modes/interactive/interactive-hotkeys-debug.js +3 -0
  536. package/dist/modes/interactive/interactive-hotkeys-debug.js.map +1 -1
  537. package/dist/modes/interactive/interactive-input-handling.d.ts.map +1 -1
  538. package/dist/modes/interactive/interactive-input-handling.js +51 -0
  539. package/dist/modes/interactive/interactive-input-handling.js.map +1 -1
  540. package/dist/modes/interactive/interactive-mode-base.d.ts +5 -0
  541. package/dist/modes/interactive/interactive-mode-base.d.ts.map +1 -1
  542. package/dist/modes/interactive/interactive-mode-base.js +5 -0
  543. package/dist/modes/interactive/interactive-mode-base.js.map +1 -1
  544. package/dist/modes/interactive/interactive-mode-deps.d.ts +1 -1
  545. package/dist/modes/interactive/interactive-mode-deps.d.ts.map +1 -1
  546. package/dist/modes/interactive/interactive-mode-deps.js.map +1 -1
  547. package/dist/modes/interactive/interactive-mode-surface.d.ts +12 -0
  548. package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
  549. package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
  550. package/dist/modes/interactive/interactive-mode.d.ts +1 -0
  551. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  552. package/dist/modes/interactive/interactive-mode.js +1 -0
  553. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  554. package/dist/modes/interactive/interactive-model-routing.d.ts.map +1 -1
  555. package/dist/modes/interactive/interactive-model-routing.js +4 -1
  556. package/dist/modes/interactive/interactive-model-routing.js.map +1 -1
  557. package/dist/modes/interactive/interactive-onboarding.d.ts +11 -0
  558. package/dist/modes/interactive/interactive-onboarding.d.ts.map +1 -0
  559. package/dist/modes/interactive/interactive-onboarding.js +220 -0
  560. package/dist/modes/interactive/interactive-onboarding.js.map +1 -0
  561. package/dist/modes/interactive/interactive-selectors.d.ts.map +1 -1
  562. package/dist/modes/interactive/interactive-selectors.js +4 -0
  563. package/dist/modes/interactive/interactive-selectors.js.map +1 -1
  564. package/dist/modes/interactive/interactive-session-routing.d.ts.map +1 -1
  565. package/dist/modes/interactive/interactive-session-routing.js +6 -0
  566. package/dist/modes/interactive/interactive-session-routing.js.map +1 -1
  567. package/dist/modes/interactive/interactive-slash-commands.d.ts.map +1 -1
  568. package/dist/modes/interactive/interactive-slash-commands.js +9 -4
  569. package/dist/modes/interactive/interactive-slash-commands.js.map +1 -1
  570. package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
  571. package/dist/modes/interactive/interactive-startup.js +28 -0
  572. package/dist/modes/interactive/interactive-startup.js.map +1 -1
  573. package/dist/utils/child-process.d.ts.map +1 -1
  574. package/dist/utils/child-process.js +21 -1
  575. package/dist/utils/child-process.js.map +1 -1
  576. package/dist/utils/markit.d.ts +8 -0
  577. package/dist/utils/markit.d.ts.map +1 -0
  578. package/dist/utils/markit.js +53 -0
  579. package/dist/utils/markit.js.map +1 -0
  580. package/dist/utils/paths.d.ts +2 -1
  581. package/dist/utils/paths.d.ts.map +1 -1
  582. package/dist/utils/paths.js +14 -1
  583. package/dist/utils/paths.js.map +1 -1
  584. package/docs/compaction.md +18 -1
  585. package/docs/containerization.md +1 -1
  586. package/docs/docs.json +1 -0
  587. package/docs/extensions.md +25 -36
  588. package/docs/models.md +1 -1
  589. package/docs/providers.md +2 -1
  590. package/docs/quickstart.md +11 -6
  591. package/docs/sdk.md +5 -5
  592. package/docs/session-format.md +6 -0
  593. package/docs/sessions.md +6 -0
  594. package/docs/settings.md +7 -0
  595. package/docs/subagents.md +3 -2
  596. package/docs/tools.md +49 -0
  597. package/docs/usage.md +3 -3
  598. package/docs/workflows.md +112 -8
  599. package/examples/extensions/subagent/README.md +5 -5
  600. package/examples/extensions/subagent/agents/planner.md +1 -1
  601. package/examples/extensions/subagent/agents/reviewer.md +1 -1
  602. package/examples/extensions/subagent/agents/scout.md +2 -2
  603. package/examples/extensions/subagent/display.ts +3 -3
  604. package/examples/sdk/05-tools.ts +3 -3
  605. package/examples/sdk/README.md +1 -1
  606. package/package.json +5 -3
@@ -10,7 +10,7 @@ import { discoverAgents } from "../agents/agents.ts";
10
10
  import { cleanupAllArtifactDirs, cleanupOldArtifacts, getArtifactsDir } from "../shared/artifacts.ts";
11
11
  import { resolveCurrentSessionId } from "../shared/session-identity.ts";
12
12
  import { cleanupOldChainDirs } from "../shared/settings.ts";
13
- import { renderLiveSubagentResult, renderSubagentResult, stopResultAnimations, stopWidgetAnimation, type SubagentResultRenderState } from "../tui/render.ts";
13
+ import { advanceResultPulseFrame, renderLiveSubagentResult, renderSubagentResult, stopResultAnimations, stopWidgetAnimation, type SubagentResultRenderState } from "../tui/render.ts";
14
14
  import { SubagentParams } from "./schemas.ts";
15
15
  import { createSubagentExecutor, type SubagentParamsLike } from "../runs/foreground/subagent-executor.ts";
16
16
  import { createAsyncJobTracker } from "../runs/background/async-job-tracker.ts";
@@ -69,7 +69,7 @@ type SubagentToolRenderState = SubagentResultRenderState;
69
69
  function rebuildSlashResultContainer(
70
70
  container: Container,
71
71
  result: AgentToolResult<Details>,
72
- options: { expanded: boolean; now?: number },
72
+ options: { expanded: boolean; now?: number; pulseFrame?: number },
73
73
  theme: ExtensionContext["ui"]["theme"],
74
74
  ): void {
75
75
  container.clear();
@@ -87,12 +87,14 @@ function createSlashResultComponent(
87
87
  const container = new Container();
88
88
  let lastVersion = -1;
89
89
  let lastSnapshotNow = 0;
90
+ let pulseFrame = 0;
90
91
  container.render = (width: number): string[] => {
91
92
  const snapshot = getSlashRenderableSnapshot(details);
92
93
  if (snapshot.version !== lastVersion) {
93
94
  lastVersion = snapshot.version;
94
95
  lastSnapshotNow = Date.now();
95
- rebuildSlashResultContainer(container, snapshot.result, { ...options, now: lastSnapshotNow }, theme);
96
+ pulseFrame = advanceResultPulseFrame(pulseFrame);
97
+ rebuildSlashResultContainer(container, snapshot.result, { ...options, now: lastSnapshotNow, pulseFrame }, theme);
96
98
  }
97
99
  return Container.prototype.render.call(container, width);
98
100
  };
@@ -179,6 +181,7 @@ export default function registerSubagentExtension(pi: ExtensionAPI): void {
179
181
  baseCwd: "",
180
182
  currentSessionId: null,
181
183
  asyncJobs: new Map(),
184
+ subagentInProgress: false,
182
185
  foregroundRuns: new Map(),
183
186
  foregroundControls: new Map(),
184
187
  lastForegroundControlId: null,
@@ -3,7 +3,7 @@
3
3
  */
4
4
 
5
5
  import { Type } from "typebox";
6
- import { SUBAGENT_ACTIONS } from "../shared/types.ts";
6
+ import { MAX_SUBAGENT_NESTING_DEPTH, SUBAGENT_ACTIONS } from "../shared/types.ts";
7
7
 
8
8
  const SkillOverride = Type.Unsafe({
9
9
  anyOf: [
@@ -137,11 +137,6 @@ const ChainItem = Type.Object({
137
137
  }, {
138
138
  description: "Chain step: use {agent, task?, ...} for sequential, {parallel: [...]} for static concurrent execution, or {expand, parallel: {...}, collect} for dynamic fanout.",
139
139
  additionalProperties: false,
140
- allOf: [
141
- { if: { required: ["expand"] }, then: { required: ["parallel", "collect"], properties: { parallel: { type: "object" } } } },
142
- { if: { required: ["collect"] }, then: { required: ["expand", "parallel"], properties: { parallel: { type: "object" } } } },
143
- { not: { required: ["expand"], properties: { parallel: { type: "array", items: {} } } } },
144
- ],
145
140
  });
146
141
 
147
142
  const ControlOverrides = Type.Object({
@@ -188,7 +183,7 @@ export const SubagentParams = Type.Object({
188
183
  { type: "object", additionalProperties: true },
189
184
  { type: "string" },
190
185
  ],
191
- description: "Agent or chain config for create/update. Agent: name, package (optional namespace; runtime name becomes package.name), description, scope ('user'|'project', default 'user'), systemPrompt, systemPromptMode, inheritProjectContext, inheritSkills, defaultContext ('fresh'|'fork'), model, tools (comma-separated), extensions (comma-separated), skills (comma-separated), thinking, output, reads, progress, maxSubagentDepth. Chain: name, package, description, scope, steps (array of {agent, task?, output?, outputMode?, reads?, model?, skill?, progress?}). Presence of 'steps' creates a chain instead of an agent. String values must be valid JSON."
186
+ description: `Agent or chain config for create/update. Agent: name, package (optional namespace; runtime name becomes package.name), description, scope ('user'|'project', default 'user'), systemPrompt, systemPromptMode, inheritProjectContext, inheritSkills, defaultContext ('fresh'|'fork'), model, tools (comma-separated), extensions (comma-separated), skills (comma-separated), thinking, output, reads, progress, maxSubagentDepth (integer >= 0, clamped to ${MAX_SUBAGENT_NESTING_DEPTH}). Chain: name, package, description, scope, steps (array of {agent, task?, output?, outputMode?, reads?, model?, skill?, progress?}). Presence of 'steps' creates a chain instead of an agent. String values must be valid JSON.`
192
187
  })),
193
188
  tasks: Type.Optional(Type.Array(TaskItem, { description: "PARALLEL mode: [{agent, task, count?, output?, outputMode?, reads?, progress?}, ...]" })),
194
189
  concurrency: Type.Optional(Type.Integer({ minimum: 1, description: "Top-level PARALLEL mode only: max concurrent tasks. Defaults to config.parallel.concurrency or 4." })),
@@ -10,6 +10,7 @@ import {
10
10
  type SubagentResultIntercomPayload,
11
11
  type SubagentResultStatus,
12
12
  type SubagentRunMode,
13
+ MAX_SUBAGENT_NESTING_DEPTH,
13
14
  SUBAGENT_RESULT_INTERCOM_DELIVERY_EVENT,
14
15
  SUBAGENT_RESULT_INTERCOM_EVENT,
15
16
  } from "../shared/types.ts";
@@ -69,7 +70,7 @@ function compactNestedRun(run: NestedRunSummary | PublicNestedRunSummary, depth
69
70
  ...(run.parentStepIndex !== undefined ? { parentStepIndex: run.parentStepIndex } : {}),
70
71
  ...(run.parentAgent ? { parentAgent: run.parentAgent } : {}),
71
72
  depth: run.depth,
72
- path: run.path.slice(0, 4).map((part) => ({
73
+ path: run.path.slice(0, MAX_SUBAGENT_NESTING_DEPTH + 1).map((part) => ({
73
74
  runId: part.runId,
74
75
  ...(part.stepIndex !== undefined ? { stepIndex: part.stepIndex } : {}),
75
76
  ...(part.agent ? { agent: part.agent } : {}),
@@ -114,9 +115,9 @@ function compactNestedRun(run: NestedRunSummary | PublicNestedRunSummary, depth
114
115
  ...(step.startedAt !== undefined ? { startedAt: step.startedAt } : {}),
115
116
  ...(step.endedAt !== undefined ? { endedAt: step.endedAt } : {}),
116
117
  ...(step.error ? { error: step.error } : {}),
117
- ...(depth < 2 && step.children?.length ? { children: step.children.slice(0, 8).map((child) => compactNestedRun(child, depth + 1)) } : {}),
118
+ ...(depth < MAX_SUBAGENT_NESTING_DEPTH && step.children?.length ? { children: step.children.slice(0, 8).map((child) => compactNestedRun(child, depth + 1)) } : {}),
118
119
  })) } : {}),
119
- ...(depth < 2 && run.children?.length ? { children: run.children.slice(0, 8).map((child) => compactNestedRun(child, depth + 1)) } : {}),
120
+ ...(depth < MAX_SUBAGENT_NESTING_DEPTH && run.children?.length ? { children: run.children.slice(0, 8).map((child) => compactNestedRun(child, depth + 1)) } : {}),
120
121
  };
121
122
  }
122
123
 
@@ -395,10 +395,7 @@ export function createAsyncJobTracker(pi: Pick<ExtensionAPI, "events">, state: S
395
395
  state.foregroundControls?.clear();
396
396
  state.lastForegroundControlId = null;
397
397
  state.resultFileCoalescer.clear();
398
- if (ctx?.hasUI) {
399
- state.lastUiContext = ctx;
400
- rerenderWidget(ctx, []);
401
- }
398
+ if (ctx?.hasUI) state.lastUiContext = ctx;
402
399
  };
403
400
 
404
401
  return { ensurePoller, handleStarted, handleComplete, resetJobs, hydrateActiveJobs };
@@ -25,11 +25,25 @@ import {
25
25
  wrapForkTask,
26
26
  type AgentProgress,
27
27
  type ArtifactPaths,
28
+ type SingleResult,
28
29
  type SubagentToolResult,
29
30
  } from "../../shared/types.ts";
30
31
  import type { ExecutionContextData, ResolvedExecutorDeps } from "./subagent-executor-types.ts";
31
32
  import { createForegroundControlNotifier, maybeBuildForegroundIntercomReceipt, rememberForegroundRun } from "./subagent-executor-status.ts";
32
33
 
34
+ function formatFailedSingleRunOutput(result: SingleResult, displayOutput: string): string {
35
+ const error = result.error || "Failed";
36
+ const output = displayOutput.trim();
37
+ const lines = [error];
38
+ if (output && output !== error.trim()) {
39
+ lines.push("", "Output:", output);
40
+ }
41
+ if (result.artifactPaths?.outputPath) {
42
+ lines.push("", `Output artifact: ${result.artifactPaths.outputPath}`);
43
+ }
44
+ return lines.join("\n");
45
+ }
46
+
33
47
  export async function runSinglePath(data: ExecutionContextData, deps: ResolvedExecutorDeps): Promise<SubagentToolResult> {
34
48
  const {
35
49
  params,
@@ -309,7 +323,7 @@ export async function runSinglePath(data: ExecutionContextData, deps: ResolvedEx
309
323
 
310
324
  if (r.exitCode !== 0)
311
325
  return {
312
- content: [{ type: "text", text: r.error || "Failed" }],
326
+ content: [{ type: "text", text: formatFailedSingleRunOutput(r, finalizedOutput.displayOutput) }],
313
327
  details,
314
328
  isError: true,
315
329
  };
@@ -172,6 +172,23 @@ async function handleInterruptRequest(input: {
172
172
  };
173
173
  }
174
174
 
175
+ function inferExecutionMode(params: SubagentParamsLike): "single" | "parallel" | "chain" {
176
+ if ((params.chain?.length ?? 0) > 0) return "chain";
177
+ if ((params.tasks?.length ?? 0) > 0) return "parallel";
178
+ return "single";
179
+ }
180
+
181
+ function duplicateSubagentCallResult(params: SubagentParamsLike): SubagentToolResult {
182
+ return {
183
+ content: [{
184
+ type: "text",
185
+ text: "Rejected: a subagent call is already in progress. Issue exactly ONE subagent call per turn.",
186
+ }],
187
+ isError: true,
188
+ details: { mode: inferExecutionMode(params), results: [] },
189
+ };
190
+ }
191
+
175
192
  export function createSubagentExecutor(rawDeps: ExecutorDeps): {
176
193
  execute: (
177
194
  id: string,
@@ -249,5 +266,22 @@ export function createSubagentExecutor(rawDeps: ExecutorDeps): {
249
266
  }, prepared.effectiveParams.context);
250
267
  };
251
268
 
252
- return { execute };
269
+ const executeWithSingleDispatchGuard = async (
270
+ id: string,
271
+ params: SubagentParamsLike,
272
+ signal: AbortSignal,
273
+ onUpdate: ((r: SubagentToolResult) => void) | undefined,
274
+ ctx: ExtensionContext,
275
+ ): Promise<SubagentToolResult> => {
276
+ if (params.action) return execute(id, params, signal, onUpdate, ctx);
277
+ if (deps.state.subagentInProgress === true) return duplicateSubagentCallResult(params);
278
+ deps.state.subagentInProgress = true;
279
+ try {
280
+ return await execute(id, params, signal, onUpdate, ctx);
281
+ } finally {
282
+ deps.state.subagentInProgress = false;
283
+ }
284
+ };
285
+
286
+ return { execute: executeWithSingleDispatchGuard };
253
287
  }
@@ -7,7 +7,7 @@ import { getAgentDir } from "../../shared/utils.ts";
7
7
 
8
8
  const CACHE_VERSION = 1;
9
9
  const CACHE_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;
10
- const BUILTIN_TOOL_NAMES = new Set(["read", "bash", "edit", "write", "grep", "find", "ls", "mcp"]);
10
+ const BUILTIN_TOOL_NAMES = new Set(["read", "bash", "edit", "write", "grep", "find", "search", "ls", "mcp"]);
11
11
  const GENERIC_GLOBAL_CONFIG_PATH = path.join(os.homedir(), ".config", "mcp", "mcp.json");
12
12
  const IMPORT_PATHS = {
13
13
  cursor: [path.join(os.homedir(), ".cursor", "mcp.json")],
@@ -1,6 +1,6 @@
1
1
  import { formatDuration, formatTokens, shortenPath } from "../../shared/formatters.ts";
2
2
  import { formatActivityLabel } from "../../shared/status-format.ts";
3
- import type { ActivityState, NestedRunSummary } from "../../shared/types.ts";
3
+ import { MAX_SUBAGENT_NESTING_DEPTH, type ActivityState, type NestedRunSummary } from "../../shared/types.ts";
4
4
 
5
5
  export interface NestedRunCounts {
6
6
  total: number;
@@ -108,7 +108,7 @@ function formatNestedRunLines(children: NestedRunSummary[] | undefined, options:
108
108
  export function formatNestedRunStatusLines(children: NestedRunSummary[] | undefined, options: { indent?: string; maxDepth?: number; maxLines?: number; commandHints?: boolean } = {}): string[] {
109
109
  return formatNestedRunLines(children, {
110
110
  indent: options.indent ?? " ",
111
- maxDepth: options.maxDepth ?? 2,
111
+ maxDepth: options.maxDepth ?? MAX_SUBAGENT_NESTING_DEPTH,
112
112
  maxLines: options.maxLines ?? 40,
113
113
  commandHints: options.commandHints ?? false,
114
114
  });
@@ -13,10 +13,11 @@ import { encodeNestedPathEnv, parseNestedPathEnv, type NestedPathEntry } from ".
13
13
  import { resolveMcpDirectToolNames } from "./mcp-direct-tool-allowlist.ts";
14
14
  import { STRUCTURED_OUTPUT_CAPTURE_ENV, STRUCTURED_OUTPUT_SCHEMA_ENV } from "./structured-output.ts";
15
15
  import type { JsonSchemaObject } from "../../shared/types.ts";
16
+ import { MAX_SUBAGENT_NESTING_DEPTH } from "../../shared/types-runtime.ts";
16
17
 
17
18
  const THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh"];
18
19
  const TASK_ARG_LIMIT = 8000;
19
- export const SUBAGENT_PARENT_MAX_DEPTH = 3;
20
+ export const SUBAGENT_PARENT_MAX_DEPTH = MAX_SUBAGENT_NESTING_DEPTH;
20
21
  export const PROMPT_RUNTIME_EXTENSION_PATH = path.join(path.dirname(fileURLToPath(import.meta.url)), "subagent-prompt-runtime.ts");
21
22
  const ENV_PREFIX = APP_NAME.toUpperCase();
22
23
  export const FANOUT_CHILD_EXTENSION_PATH = path.join(path.dirname(fileURLToPath(import.meta.url)), "..", "..", "extension", "fanout-child.ts");
@@ -31,6 +31,7 @@ export const CHILD_FANOUT_BOUNDARY_INSTRUCTIONS = [
31
31
  const PARENT_ONLY_CUSTOM_MESSAGE_TYPES = new Set([
32
32
  "subagent-orchestration-instructions",
33
33
  "subagent-slash-result",
34
+ "subagent-slash-text-result",
34
35
  "subagent-notify",
35
36
  "subagent_control_notice",
36
37
  "subagent-control",
@@ -130,14 +131,15 @@ function stripAssistantSubagentToolCallBlocks(message: unknown): unknown | undef
130
131
  }
131
132
 
132
133
  export function stripParentOnlySubagentMessages(messages: unknown[]): unknown[] {
134
+ const preserveCurrentFanoutToolHistory = process.env[SUBAGENT_FANOUT_CHILD_ENV] === "1";
133
135
  let changed = false;
134
136
  const filtered: unknown[] = [];
135
137
  for (const message of messages) {
136
- if (isParentOnlySubagentMessage(message) || isSubagentToolResultMessage(message)) {
138
+ if (isParentOnlySubagentMessage(message) || (!preserveCurrentFanoutToolHistory && isSubagentToolResultMessage(message))) {
137
139
  changed = true;
138
140
  continue;
139
141
  }
140
- const stripped = stripAssistantSubagentToolCallBlocks(message);
142
+ const stripped = preserveCurrentFanoutToolHistory ? message : stripAssistantSubagentToolCallBlocks(message);
141
143
  if (stripped === undefined) {
142
144
  changed = true;
143
145
  continue;
@@ -230,6 +230,7 @@ export interface SubagentState {
230
230
  baseCwd: string;
231
231
  currentSessionId: string | null;
232
232
  asyncJobs: Map<string, AsyncJobState>;
233
+ subagentInProgress?: boolean;
233
234
  foregroundRuns?: Map<string, ForegroundResumeRun>;
234
235
  foregroundControls: Map<string, {
235
236
  runId: string;
@@ -4,7 +4,7 @@
4
4
 
5
5
  import type { ExtensionContext } from "@bastani/atomic";
6
6
  import { APP_NAME, getEnvValue, WORKFLOW_STAGE_SUBAGENT_GUARD_ENV } from "@bastani/atomic";
7
- import { DEFAULT_SUBAGENT_MAX_DEPTH } from "./types-runtime.ts";
7
+ import { DEFAULT_SUBAGENT_MAX_DEPTH, MAX_SUBAGENT_NESTING_DEPTH } from "./types-runtime.ts";
8
8
 
9
9
  const ENV_PREFIX = APP_NAME.toUpperCase();
10
10
  const SUBAGENT_MAX_DEPTH_ENV = `${ENV_PREFIX}_SUBAGENT_MAX_DEPTH`;
@@ -16,7 +16,7 @@ export { WORKFLOW_STAGE_SUBAGENT_GUARD_ENV };
16
16
  export function normalizeMaxSubagentDepth(value: unknown): number | undefined {
17
17
  const parsed = typeof value === "number" ? value : typeof value === "string" ? Number(value) : NaN;
18
18
  if (!Number.isInteger(parsed) || parsed < 0) return undefined;
19
- return parsed;
19
+ return Math.min(parsed, MAX_SUBAGENT_NESTING_DEPTH);
20
20
  }
21
21
 
22
22
  export function resolveCurrentMaxSubagentDepth(configMaxDepth?: number): number {
@@ -45,9 +45,9 @@ export function resolveWorkflowStageMaxSubagentDepth(
45
45
  ): number {
46
46
  const maxDepth = resolveCurrentMaxSubagentDepth(configMaxDepth);
47
47
  return isWorkflowStageOrchestrationContext(ctx)
48
- // Workflow stages use the same two-hop default as main chat. A 0-depth
49
- // constraint still preserves one child-subagent hop so configured workflow
50
- // stages can delegate at least once.
48
+ // Workflow stages receive an explicit host constraint, clamped by the
49
+ // inherited/global nesting ceiling. A 0-depth workflow constraint still
50
+ // preserves one child-subagent hop so configured stages can delegate once.
51
51
  ? Math.min(maxDepth, Math.max(1, ctx.orchestrationContext?.constraints.maxSubagentDepth ?? 1))
52
52
  : maxDepth;
53
53
  }
@@ -93,7 +93,8 @@ export const SLASH_SUBAGENT_UPDATE_EVENT = "subagent:slash:update";
93
93
  export const SLASH_SUBAGENT_CANCEL_EVENT = "subagent:slash:cancel";
94
94
  export const POLL_INTERVAL_MS = 250;
95
95
  export const MAX_WIDGET_JOBS = 4;
96
- export const DEFAULT_SUBAGENT_MAX_DEPTH = 2;
96
+ export const MAX_SUBAGENT_NESTING_DEPTH = 5;
97
+ export const DEFAULT_SUBAGENT_MAX_DEPTH = MAX_SUBAGENT_NESTING_DEPTH;
97
98
  export const SUBAGENT_ACTIONS = ["list", "get", "create", "update", "delete", "status", "interrupt", "resume", "doctor"] as const;
98
99
 
99
100
  export const DEFAULT_FORK_PREAMBLE =
@@ -82,6 +82,7 @@ interface PromptTemplateBridgeResult {
82
82
  exitCode?: number;
83
83
  error?: string;
84
84
  model?: string;
85
+ toolCalls?: Array<{ text?: string; expandedText?: string }>;
85
86
  }>;
86
87
  progress?: Array<{
87
88
  index?: number;
@@ -147,10 +148,13 @@ function parsePromptTemplateRequest(data: unknown): PromptTemplateDelegationRequ
147
148
  if (!hasSingle && tasks.length === 0) return undefined;
148
149
 
149
150
  const fallbackTask = tasks[0];
151
+ const agent = hasSingle ? value.agent : fallbackTask?.agent;
152
+ const task = hasSingle ? value.task : fallbackTask?.task;
153
+ if (!agent || !task) return undefined;
150
154
  return {
151
155
  requestId: value.requestId,
152
- agent: hasSingle ? value.agent : fallbackTask!.agent,
153
- task: hasSingle ? value.task : fallbackTask!.task,
156
+ agent,
157
+ task,
154
158
  ...(tasks.length > 0 ? { tasks } : {}),
155
159
  context: value.context,
156
160
  model: value.model,
@@ -209,13 +213,31 @@ function resolveProgressModel(
209
213
  return firstWithModel?.model;
210
214
  }
211
215
 
212
- function buildDelegationMessages(result: { messages?: unknown[]; finalOutput?: string }, fallbackText?: string): unknown[] {
216
+ function toolCallSummaryText(summary: { text?: string; expandedText?: string }): string | undefined {
217
+ const text = typeof summary.expandedText === "string" && summary.expandedText.trim().length > 0
218
+ ? summary.expandedText.trim()
219
+ : typeof summary.text === "string"
220
+ ? summary.text.trim()
221
+ : "";
222
+ return text || undefined;
223
+ }
224
+
225
+ function buildDelegationMessages(
226
+ result: { messages?: unknown[]; finalOutput?: string; toolCalls?: Array<{ text?: string; expandedText?: string }> },
227
+ fallbackText?: string,
228
+ ): unknown[] {
213
229
  if (Array.isArray(result.messages) && result.messages.length > 0) return result.messages;
230
+ const toolCallSummaries = (result.toolCalls ?? []).flatMap((summary) => {
231
+ const text = toolCallSummaryText(summary);
232
+ return text ? [`- ${text}`] : [];
233
+ });
234
+ const toolCallText = toolCallSummaries.length > 0 ? `Tool calls:\n${toolCallSummaries.join("\n")}` : undefined;
214
235
  const text = typeof result.finalOutput === "string" && result.finalOutput.trim().length > 0
215
236
  ? result.finalOutput.trim()
216
237
  : fallbackText;
217
- if (!text) return [];
218
- return [{ role: "assistant", content: [{ type: "text", text }] }];
238
+ const contentText = [toolCallText, text].filter((part): part is string => Boolean(part)).join("\n\n");
239
+ if (!contentText) return [];
240
+ return [{ role: "assistant", content: [{ type: "text", text: contentText }] }];
219
241
  }
220
242
 
221
243
  function toDelegationUpdate(requestId: string, update: PromptTemplateBridgeResult): PromptTemplateDelegationUpdate | undefined {
@@ -1,5 +1,5 @@
1
1
  import * as path from "node:path";
2
- import type { AsyncJobState, AsyncJobStep, NestedRunSummary, NestedStepSummary } from "../shared/types.ts";
2
+ import { MAX_SUBAGENT_NESTING_DEPTH, type AsyncJobState, type AsyncJobStep, type NestedRunSummary, type NestedStepSummary } from "../shared/types.ts";
3
3
  import { flatToLogicalStepIndex } from "../runs/background/parallel-groups.ts";
4
4
  import { formatDuration, formatModelThinking, shortenPath } from "../shared/formatters.ts";
5
5
  import { formatNestedAggregate } from "../runs/shared/nested-render.ts";
@@ -223,7 +223,7 @@ export function formatNestedWidgetLines(children: NestedRunSummary[] | undefined
223
223
  return aggregate ? [theme.fg("dim", `↳ ${aggregate}`)] : [];
224
224
  }
225
225
  const lines: string[] = [];
226
- const maxDepth = 2;
226
+ const maxDepth = MAX_SUBAGENT_NESTING_DEPTH;
227
227
  const append = (items: NestedRunSummary[] | undefined, depth: number, prefix: string): void => {
228
228
  if (!items?.length || lines.length >= lineBudget) return;
229
229
  if (depth > maxDepth) {
@@ -66,16 +66,22 @@ export function truncLine(text: string, maxWidth: number): string {
66
66
  return result + activeStyles.join("") + "…";
67
67
  }
68
68
 
69
- const RUNNING_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
69
+ export const RUNNING_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
70
70
 
71
71
  /**
72
72
  * Spinner cadence (ms per frame). The running glyph is derived from wall-clock
73
73
  * time so every active spinner advances smoothly and in lockstep, independent
74
74
  * of how often (or how irregularly) progress data updates arrive. The animation
75
75
  * timers below only schedule re-renders; the displayed frame always comes from
76
- * the clock. This fixes the frozen/stuttering spinner from issue #1084 while
77
- * keeping per-frame diffs to a single glyph cell so the differential renderer
78
- * never needs a full-clear (no flicker).
76
+ * the clock. This fixes the frozen/stuttering spinner from issue #1084.
77
+ *
78
+ * IMPORTANT: a wall-clock spinner only stays flicker-free for widgets pinned to
79
+ * the bottom of the buffer (e.g. the below-editor async widget), where every
80
+ * tick stays inside the viewport. Content rendered into chat scrollback (live
81
+ * foreground subagent results) can scroll above the viewport fold; there, even
82
+ * a single-cell spinner diff forces pi-tui into a destructive full-screen +
83
+ * scrollback clear on every tick. Such surfaces must NOT animate on a timer —
84
+ * see pulseGlyph(), which is advanced once per real progress update instead.
79
85
  */
80
86
  export const RUNNING_ANIMATION_MS = 80;
81
87
 
@@ -106,6 +112,23 @@ export function runningGlyph(seed?: number, now?: number): string {
106
112
  return RUNNING_FRAMES[Math.abs(animatedSeed) % RUNNING_FRAMES.length]!;
107
113
  }
108
114
 
115
+ export const PULSE_FRAMES = ["·", "•", "●", "•"];
116
+
117
+ /**
118
+ * Activity "heartbeat" glyph for live foreground subagent results. Unlike
119
+ * runningGlyph(), the frame is NOT derived from wall-clock time: the caller
120
+ * advances `frame` exactly once per real progress update (see
121
+ * renderLiveSubagentResult). With no animation timer, the only line diffs this
122
+ * produces coincide with progress data that genuinely changed, so the pulse can
123
+ * live in chat scrollback (above or below the fold) without ever triggering
124
+ * pi-tui's full-screen/scrollback clear. Returns a steady breathing dot that
125
+ * grows and settles as the subagent reports activity.
126
+ */
127
+ export function pulseGlyph(frame?: number): string {
128
+ const index = Number.isFinite(frame) ? Math.abs(Math.trunc(frame as number)) : 0;
129
+ return PULSE_FRAMES[index % PULSE_FRAMES.length]!;
130
+ }
131
+
109
132
  export function progressRunningSeed(progress: ProgressSeedSource | undefined): number | undefined {
110
133
  if (!progress) return undefined;
111
134
  return runningSeed(
@@ -1,56 +1,47 @@
1
- import { RUNNING_ANIMATION_MS } from "./render-layout.ts";
2
-
3
1
  type ResultAnimationTimer = ReturnType<typeof setInterval>;
4
2
 
5
3
  export interface SubagentResultRenderState {
6
4
  subagentResultAnimationTimer?: ResultAnimationTimer;
5
+ subagentResultAnimationCleanup?: () => void;
7
6
  subagentResultSnapshotKey?: string;
8
7
  /** Stable semantic/content timestamp used for durations and activity text. */
9
8
  subagentResultSnapshotNow?: number;
10
- /** Timer-driven timestamp used only for spinner glyph frames. */
11
- subagentResultSpinnerFrameNow?: number;
9
+ /** Monotonic pulse frame, advanced once per progress update (no timer). */
10
+ subagentResultPulseFrame?: number;
12
11
  }
13
12
 
14
13
  export type ResultAnimationContext = {
15
14
  state: SubagentResultRenderState;
16
15
  invalidate: () => void;
17
16
  };
18
- type LegacyResultAnimationContext = { state: { subagentResultAnimationTimer?: ResultAnimationTimer } };
19
-
20
- const activeResultAnimationTimers = new Map<ResultAnimationTimer, SubagentResultRenderState>();
17
+ type LegacyResultAnimationContext = {
18
+ state: {
19
+ subagentResultAnimationTimer?: ResultAnimationTimer;
20
+ subagentResultAnimationCleanup?: () => void;
21
+ };
22
+ };
21
23
 
24
+ /**
25
+ * Legacy safety net for render state objects created by earlier timer-driven
26
+ * foreground result rendering. New code never schedules result timers, but
27
+ * clearing the field prevents a stale interval from surviving across upgrades.
28
+ */
22
29
  export function clearResultAnimationTimer(context: LegacyResultAnimationContext): void {
23
30
  const timer = context.state.subagentResultAnimationTimer;
24
- if (timer) {
25
- clearInterval(timer);
26
- activeResultAnimationTimers.delete(timer);
27
- }
31
+ if (timer) clearInterval(timer);
28
32
  context.state.subagentResultAnimationTimer = undefined;
33
+ context.state.subagentResultAnimationCleanup = undefined;
29
34
  }
30
35
 
31
- export function clearLegacyResultAnimationTimer(context: LegacyResultAnimationContext): void {
32
- clearResultAnimationTimer(context);
36
+ export function advanceResultPulseFrame(frame: number | undefined): number {
37
+ return (frame ?? 0) + 1;
33
38
  }
34
39
 
35
- export function ensureResultAnimation(context: ResultAnimationContext): void {
36
- if (context.state.subagentResultAnimationTimer) return;
37
- const timer = setInterval(() => {
38
- context.state.subagentResultSpinnerFrameNow = Date.now();
39
- try {
40
- context.invalidate();
41
- } catch {
42
- clearResultAnimationTimer(context);
43
- }
44
- }, RUNNING_ANIMATION_MS);
45
- timer.unref?.();
46
- context.state.subagentResultAnimationTimer = timer;
47
- activeResultAnimationTimers.set(timer, context.state);
40
+ export function clearLegacyResultAnimationTimer(context: LegacyResultAnimationContext): void {
41
+ clearResultAnimationTimer(context);
48
42
  }
49
43
 
50
44
  export function stopResultAnimations(): void {
51
- for (const [timer, state] of activeResultAnimationTimers) {
52
- clearInterval(timer);
53
- if (state.subagentResultAnimationTimer === timer) state.subagentResultAnimationTimer = undefined;
54
- }
55
- activeResultAnimationTimers.clear();
45
+ // Retained for extension teardown compatibility; result rendering no longer
46
+ // registers global animation timers.
56
47
  }
@@ -2,7 +2,7 @@ import { Container, Text, type Component } from "@earendil-works/pi-tui";
2
2
  import type { AgentProgress, AsyncJobStep, Details } from "../shared/types.ts";
3
3
  import { shortenPath } from "../shared/formatters.ts";
4
4
  import { getSingleResultOutput } from "../shared/utils.ts";
5
- import { getTermWidth, progressRunningSeed, runningGlyph, runningSeed, truncLine, type Theme } from "./render-layout.ts";
5
+ import { getTermWidth, pulseGlyph, truncLine, type Theme } from "./render-layout.ts";
6
6
  import {
7
7
  buildLiveStatusLine,
8
8
  compactCurrentActivity,
@@ -25,7 +25,7 @@ import {
25
25
  } from "./render-chain-graph.ts";
26
26
  import { modelThinkingBadge, widgetStepGlyph, widgetStepStatus } from "./render-event-formatting.ts";
27
27
 
28
- export function renderSingleCompact(d: Details, r: Details["results"][number], theme: Theme, now?: number, spinnerNow?: number): Component {
28
+ export function renderSingleCompact(d: Details, r: Details["results"][number], theme: Theme, now?: number, pulseFrame?: number): Component {
29
29
  const output = r.truncation?.text || getSingleResultOutput(r);
30
30
  const progress = r.progress || r.progressSummary;
31
31
  const isRunning = r.progress?.status === "running";
@@ -37,7 +37,7 @@ export function renderSingleCompact(d: Details, r: Details["results"][number], t
37
37
  const c = new Container();
38
38
  const width = getTermWidth() - 4;
39
39
  const modelDisplay = modelThinkingBadge(theme, r.model, undefined, r.fastMode);
40
- c.addChild(new Text(truncLine(`${resultGlyph(r, output, theme, isRunning, progressRunningSeed(r.progress ?? r.progressSummary), spinnerNow ?? now)} ${theme.fg("toolTitle", theme.bold(r.agent))}${modelDisplay}${contextBadge}${stats ? ` ${theme.fg("dim", "·")} ${stats}` : ""}`, width), 0, 0));
40
+ c.addChild(new Text(truncLine(`${resultGlyph(r, output, theme, isRunning, pulseFrame)} ${theme.fg("toolTitle", theme.bold(r.agent))}${modelDisplay}${contextBadge}${stats ? ` ${theme.fg("dim", "·")} ${stats}` : ""}`, width), 0, 0));
41
41
 
42
42
  if (isRunning && r.progress) {
43
43
  const progressSnapshotNow = snapshotNowForProgress(r.progress, now);
@@ -61,7 +61,7 @@ export function renderSingleCompact(d: Details, r: Details["results"][number], t
61
61
  return c;
62
62
  }
63
63
 
64
- export function renderMultiCompact(d: Details, theme: Theme, now?: number, spinnerNow?: number): Component {
64
+ export function renderMultiCompact(d: Details, theme: Theme, now?: number, pulseFrame?: number): Component {
65
65
  const hasRunning = d.progress?.some((p) => p.status === "running")
66
66
  || d.results.some((r) => r.progress?.status === "running")
67
67
  || workflowGraphHasStatus(d, ["running"]);
@@ -87,7 +87,7 @@ export function renderMultiCompact(d: Details, theme: Theme, now?: number, spinn
87
87
  const itemTitle = multiLabel.itemTitle;
88
88
  const stats = statJoin(theme, [multiLabel.headerLabel, formatProgressStats(theme, totalSummary, true, now)]);
89
89
  const glyph = hasRunning
90
- ? theme.fg("accent", runningGlyph(runningSeed(progressRunningSeed(totalSummary), d.currentStepIndex), spinnerNow ?? now))
90
+ ? theme.fg("accent", pulseGlyph(pulseFrame))
91
91
  : failed
92
92
  ? theme.fg("error", "✗")
93
93
  : paused
@@ -133,7 +133,7 @@ export function renderMultiCompact(d: Details, theme: Theme, now?: number, spinn
133
133
  const rPending = rProg && "status" in rProg && rProg.status === "pending";
134
134
  const stepNumber = r.progress?.index !== undefined ? r.progress.index + 1 : progressFromArray?.index !== undefined ? progressFromArray.index + 1 : i + 1;
135
135
  const stepStats = formatProgressStats(theme, rProg, true, now);
136
- const glyph = rPending ? theme.fg("dim", "◦") : resultGlyph(r, output, theme, rRunning, progressRunningSeed(rProg), spinnerNow ?? now);
136
+ const glyph = rPending ? theme.fg("dim", "◦") : resultGlyph(r, output, theme, rRunning, pulseFrame);
137
137
  const pendingLabel = rPending ? ` ${theme.fg("dim", "· pending")}` : "";
138
138
  const stepLabel = resultRowLabel(d, multiLabel, i, stepNumber);
139
139
  const line = `${glyph} ${stepLabel}: ${themeBold(theme, agentName)}${stepStats ? ` ${theme.fg("dim", "·")} ${stepStats}` : ""}${pendingLabel}`;