@selesai/code 0.5.28 → 0.5.29

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 (307) hide show
  1. package/dist/cli/args.d.ts.map +1 -1
  2. package/dist/cli/args.js +9 -1
  3. package/dist/cli/args.js.map +1 -1
  4. package/dist/cli/config-selector.d.ts.map +1 -1
  5. package/dist/cli/config-selector.js +1 -1
  6. package/dist/cli/config-selector.js.map +1 -1
  7. package/dist/cli/credential-print.d.ts +23 -0
  8. package/dist/cli/credential-print.d.ts.map +1 -0
  9. package/dist/cli/credential-print.js +117 -0
  10. package/dist/cli/credential-print.js.map +1 -0
  11. package/dist/cli/startup-ui.d.ts.map +1 -1
  12. package/dist/cli/startup-ui.js +1 -1
  13. package/dist/cli/startup-ui.js.map +1 -1
  14. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  15. package/dist/core/agent-session-runtime.js +3 -0
  16. package/dist/core/agent-session-runtime.js.map +1 -1
  17. package/dist/core/agent-session.d.ts +12 -1
  18. package/dist/core/agent-session.d.ts.map +1 -1
  19. package/dist/core/agent-session.js +20 -14
  20. package/dist/core/agent-session.js.map +1 -1
  21. package/dist/core/compaction/compaction.d.ts.map +1 -1
  22. package/dist/core/compaction/compaction.js +11 -3
  23. package/dist/core/compaction/compaction.js.map +1 -1
  24. package/dist/core/extensions/runner.d.ts +1 -0
  25. package/dist/core/extensions/runner.d.ts.map +1 -1
  26. package/dist/core/extensions/runner.js +11 -0
  27. package/dist/core/extensions/runner.js.map +1 -1
  28. package/dist/core/extensions/types.d.ts +14 -1
  29. package/dist/core/extensions/types.d.ts.map +1 -1
  30. package/dist/core/extensions/types.js.map +1 -1
  31. package/dist/core/footer-data-provider.d.ts +10 -0
  32. package/dist/core/footer-data-provider.d.ts.map +1 -1
  33. package/dist/core/footer-data-provider.js +1 -1
  34. package/dist/core/footer-data-provider.js.map +1 -1
  35. package/dist/core/llama/provider.d.ts.map +1 -1
  36. package/dist/core/llama/provider.js +8 -3
  37. package/dist/core/llama/provider.js.map +1 -1
  38. package/dist/core/model-config.d.ts +30 -0
  39. package/dist/core/model-config.d.ts.map +1 -1
  40. package/dist/core/model-config.js +6 -0
  41. package/dist/core/model-config.js.map +1 -1
  42. package/dist/core/model-registry.d.ts.map +1 -1
  43. package/dist/core/model-registry.js +2 -2
  44. package/dist/core/model-registry.js.map +1 -1
  45. package/dist/core/model-resolver.d.ts +1 -0
  46. package/dist/core/model-resolver.d.ts.map +1 -1
  47. package/dist/core/model-resolver.js +20 -3
  48. package/dist/core/model-resolver.js.map +1 -1
  49. package/dist/core/model-runtime.d.ts +2 -0
  50. package/dist/core/model-runtime.d.ts.map +1 -1
  51. package/dist/core/model-runtime.js +5 -4
  52. package/dist/core/model-runtime.js.map +1 -1
  53. package/dist/core/package-manager.d.ts.map +1 -1
  54. package/dist/core/package-manager.js +13 -6
  55. package/dist/core/package-manager.js.map +1 -1
  56. package/dist/core/remote-catalog-provider.d.ts +1 -1
  57. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  58. package/dist/core/remote-catalog-provider.js +24 -11
  59. package/dist/core/remote-catalog-provider.js.map +1 -1
  60. package/dist/core/resource-loader.d.ts +15 -0
  61. package/dist/core/resource-loader.d.ts.map +1 -1
  62. package/dist/core/resource-loader.js +66 -9
  63. package/dist/core/resource-loader.js.map +1 -1
  64. package/dist/core/settings-manager.d.ts +1 -1
  65. package/dist/core/settings-manager.d.ts.map +1 -1
  66. package/dist/core/settings-manager.js.map +1 -1
  67. package/dist/core/system-prompt.d.ts.map +1 -1
  68. package/dist/core/system-prompt.js +1 -1
  69. package/dist/core/system-prompt.js.map +1 -1
  70. package/dist/core/tools/bash.d.ts +2 -0
  71. package/dist/core/tools/bash.d.ts.map +1 -1
  72. package/dist/core/tools/bash.js +34 -5
  73. package/dist/core/tools/bash.js.map +1 -1
  74. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  75. package/dist/core/tools/tool-definition-wrapper.js +3 -1
  76. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  77. package/dist/extensions/pi-intercom/CHANGELOG.md +249 -0
  78. package/dist/extensions/pi-intercom/README.md +102 -39
  79. package/dist/extensions/pi-intercom/broker/broker.ts +1233 -36
  80. package/dist/extensions/pi-intercom/broker/client.test.ts +83 -0
  81. package/dist/extensions/pi-intercom/broker/client.ts +315 -12
  82. package/dist/extensions/pi-intercom/broker/extension-state.ts +186 -0
  83. package/dist/extensions/pi-intercom/broker/extension.test.ts +387 -0
  84. package/dist/extensions/pi-intercom/broker/framing.test.ts +114 -0
  85. package/dist/extensions/pi-intercom/broker/framing.ts +82 -24
  86. package/dist/extensions/pi-intercom/broker/paths.test.ts +153 -0
  87. package/dist/extensions/pi-intercom/broker/paths.ts +117 -8
  88. package/dist/extensions/pi-intercom/broker/runtime-claim.test.ts +34 -0
  89. package/dist/extensions/pi-intercom/broker/runtime-claim.ts +21 -0
  90. package/dist/extensions/pi-intercom/broker/spawn.test.ts +160 -23
  91. package/dist/extensions/pi-intercom/broker/spawn.ts +113 -27
  92. package/dist/extensions/pi-intercom/config.test.ts +93 -0
  93. package/dist/extensions/pi-intercom/config.ts +55 -6
  94. package/dist/extensions/pi-intercom/cwd.test.ts +40 -0
  95. package/dist/extensions/pi-intercom/cwd.ts +31 -0
  96. package/dist/extensions/pi-intercom/extension-api.ts +44 -0
  97. package/dist/extensions/pi-intercom/format-context.test.ts +31 -0
  98. package/dist/extensions/pi-intercom/format-context.ts +32 -0
  99. package/dist/extensions/pi-intercom/index.ts +742 -145
  100. package/dist/extensions/pi-intercom/intercom.integration.test.ts +2646 -0
  101. package/dist/extensions/pi-intercom/package.json +15 -5
  102. package/dist/extensions/pi-intercom/reply-tracker.test.ts +134 -0
  103. package/dist/extensions/pi-intercom/reply-tracker.ts +31 -13
  104. package/dist/extensions/pi-intercom/skills/pi-intercom/SKILL.md +13 -11
  105. package/dist/extensions/pi-intercom/test/inline-message.test.ts +184 -0
  106. package/dist/extensions/pi-intercom/test/overlay-width.test.ts +66 -0
  107. package/dist/extensions/pi-intercom/types.ts +94 -4
  108. package/dist/extensions/pi-intercom/ui/compose.ts +8 -4
  109. package/dist/extensions/pi-intercom/ui/inline-message.ts +61 -25
  110. package/dist/extensions/pi-intercom/ui/session-list.ts +7 -3
  111. package/dist/extensions/pi-subagents/CHANGELOG.md +85 -0
  112. package/dist/extensions/pi-subagents/LICENSE +21 -0
  113. package/dist/extensions/pi-subagents/README.md +146 -52
  114. package/dist/extensions/pi-subagents/agents/architect.md +1 -0
  115. package/dist/extensions/pi-subagents/agents/builder.md +1 -0
  116. package/dist/extensions/pi-subagents/package-lock.json +2 -2
  117. package/dist/extensions/pi-subagents/package.json +3 -3
  118. package/dist/extensions/pi-subagents/prompts/review-loop.md +1 -1
  119. package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +21 -989
  120. package/dist/extensions/pi-subagents/skills/pi-subagents/references/constraints-and-recipes.md +256 -0
  121. package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +430 -0
  122. package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +144 -0
  123. package/dist/extensions/pi-subagents/skills/pi-subagents/references/prompting-and-roles.md +282 -0
  124. package/dist/extensions/pi-subagents/src/agents/agent-management.ts +71 -30
  125. package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +4 -0
  126. package/dist/extensions/pi-subagents/src/agents/agents.ts +118 -9
  127. package/dist/extensions/pi-subagents/src/agents/skills.ts +14 -12
  128. package/dist/extensions/pi-subagents/src/api/delegation.ts +3 -0
  129. package/dist/extensions/pi-subagents/src/api/preflight.ts +16 -12
  130. package/dist/extensions/pi-subagents/src/extension/chain-validation.ts +17 -1
  131. package/dist/extensions/pi-subagents/src/extension/index.ts +17 -7
  132. package/dist/extensions/pi-subagents/src/extension/rpc.ts +248 -6
  133. package/dist/extensions/pi-subagents/src/extension/schemas.ts +31 -6
  134. package/dist/extensions/pi-subagents/src/extension/tool-description.ts +8 -7
  135. package/dist/extensions/pi-subagents/src/intercom/intercom-bridge.ts +9 -4
  136. package/dist/extensions/pi-subagents/src/intercom/result-intercom.ts +33 -4
  137. package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +63 -16
  138. package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +24 -13
  139. package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +7 -5
  140. package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +18 -2
  141. package/dist/extensions/pi-subagents/src/runs/background/chain-append.ts +48 -5
  142. package/dist/extensions/pi-subagents/src/runs/background/control-channel.ts +68 -1
  143. package/dist/extensions/pi-subagents/src/runs/background/notify.ts +29 -4
  144. package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +29 -6
  145. package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +29 -3
  146. package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +372 -28
  147. package/dist/extensions/pi-subagents/src/runs/foreground/async-stop-action.ts +65 -0
  148. package/dist/extensions/pi-subagents/src/runs/foreground/chain-clarify.ts +3 -3
  149. package/dist/extensions/pi-subagents/src/runs/foreground/chain-execution.ts +143 -43
  150. package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +527 -247
  151. package/dist/extensions/pi-subagents/src/runs/foreground/foreground-control.ts +42 -0
  152. package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +426 -123
  153. package/dist/extensions/pi-subagents/src/runs/shared/acceptance.ts +15 -7
  154. package/dist/extensions/pi-subagents/src/runs/shared/capability-ceiling.ts +51 -19
  155. package/dist/extensions/pi-subagents/src/runs/shared/chain-outputs.ts +3 -1
  156. package/dist/extensions/pi-subagents/src/runs/shared/dynamic-fanout.ts +1 -1
  157. package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +44 -11
  158. package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +8 -0
  159. package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +97 -20
  160. package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +43 -12
  161. package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +52 -4
  162. package/dist/extensions/pi-subagents/src/runs/shared/process-signal.ts +19 -0
  163. package/dist/extensions/pi-subagents/src/runs/shared/run-history.ts +45 -9
  164. package/dist/extensions/pi-subagents/src/runs/shared/runtime-acknowledged-extensions.ts +71 -0
  165. package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +31 -1
  166. package/dist/extensions/pi-subagents/src/runs/shared/subagent-startup-retry.ts +101 -0
  167. package/dist/extensions/pi-subagents/src/runs/shared/task-intent.ts +1 -1
  168. package/dist/extensions/pi-subagents/src/runs/shared/usage-budget.ts +65 -0
  169. package/dist/extensions/pi-subagents/src/runs/shared/workflow-graph.ts +26 -1
  170. package/dist/extensions/pi-subagents/src/shared/settings.ts +17 -1
  171. package/dist/extensions/pi-subagents/src/shared/types.ts +155 -10
  172. package/dist/extensions/pi-subagents/src/shared/utils.ts +73 -4
  173. package/dist/extensions/pi-subagents/src/slash/delegation-adapters.ts +5 -0
  174. package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +46 -4
  175. package/dist/extensions/pi-subagents/src/slash/slash-live-state.ts +5 -3
  176. package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +87 -24
  177. package/dist/extensions/pi-subagents/src/tui/fleet.ts +182 -9
  178. package/dist/extensions/pi-subagents/src/tui/render.ts +27 -28
  179. package/dist/extensions/pi-subagents/src/watchdog/register-main.ts +14 -7
  180. package/dist/extensions/pi-subagents/src/watchdog/review.ts +5 -4
  181. package/dist/extensions/pi-subagents/src/watchdog/runtime.ts +170 -17
  182. package/dist/extensions/pi-subagents/src/watchdog/scope.ts +62 -0
  183. package/dist/extensions/pi-subagents/src/watchdog/settings.ts +41 -1
  184. package/dist/extensions/pi-subagents/src/watchdog/types.ts +10 -0
  185. package/dist/extensions/pi-subagents/test/e2e/real-session-subagent.test.ts +2 -2
  186. package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +348 -7
  187. package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +84 -0
  188. package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +4 -2
  189. package/dist/extensions/pi-subagents/test/integration/chain-clarify.test.ts +51 -2
  190. package/dist/extensions/pi-subagents/test/integration/chain-execution.test.ts +26 -1
  191. package/dist/extensions/pi-subagents/test/integration/detect-error.test.ts +48 -0
  192. package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +3 -3
  193. package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +213 -13
  194. package/dist/extensions/pi-subagents/test/integration/parallel-execution.test.ts +34 -0
  195. package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +44 -0
  196. package/dist/extensions/pi-subagents/test/integration/result-watcher.test.ts +118 -12
  197. package/dist/extensions/pi-subagents/test/integration/single-execution.test.ts +850 -7
  198. package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +112 -23
  199. package/dist/extensions/pi-subagents/test/support/mock-pi-script.mjs +17 -5
  200. package/dist/extensions/pi-subagents/test/support/mock-pi.ts +2 -0
  201. package/dist/extensions/pi-subagents/test/support/register-loader.mjs +3 -3
  202. package/dist/extensions/pi-subagents/test/unit/acceptance.test.ts +3 -1
  203. package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +128 -0
  204. package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +47 -2
  205. package/dist/extensions/pi-subagents/test/unit/async-recovery-descriptor.test.ts +60 -0
  206. package/dist/extensions/pi-subagents/test/unit/async-resume.test.ts +8 -0
  207. package/dist/extensions/pi-subagents/test/unit/capability-ceiling-agent-allowlist.test.ts +102 -0
  208. package/dist/extensions/pi-subagents/test/unit/capability-ceiling.test.ts +1 -1
  209. package/dist/extensions/pi-subagents/test/unit/chain-append.test.ts +6 -0
  210. package/dist/extensions/pi-subagents/test/unit/chain-validation.test.ts +1 -1
  211. package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +48 -48
  212. package/dist/extensions/pi-subagents/test/unit/config-dir-runtime.test.ts +23 -0
  213. package/dist/extensions/pi-subagents/test/unit/control-channel.test.ts +27 -0
  214. package/dist/extensions/pi-subagents/test/unit/delegation-api.test.ts +4 -2
  215. package/dist/extensions/pi-subagents/test/unit/dynamic-fanout.test.ts +1 -0
  216. package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +176 -8
  217. package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +164 -5
  218. package/dist/extensions/pi-subagents/test/unit/foreground-control.test.ts +41 -1
  219. package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +11 -11
  220. package/dist/extensions/pi-subagents/test/unit/intercom-bridge.test.ts +18 -2
  221. package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +20 -1
  222. package/dist/extensions/pi-subagents/test/unit/nested-events.test.ts +30 -2
  223. package/dist/extensions/pi-subagents/test/unit/notify.test.ts +10 -2
  224. package/dist/extensions/pi-subagents/test/unit/parallel-utils.test.ts +22 -0
  225. package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +103 -0
  226. package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +18 -0
  227. package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +46 -0
  228. package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +13 -1
  229. package/dist/extensions/pi-subagents/test/unit/result-intercom.test.ts +29 -4
  230. package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +223 -4
  231. package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +30 -0
  232. package/dist/extensions/pi-subagents/test/unit/runtime-acknowledged-extensions.test.ts +52 -0
  233. package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +34 -2
  234. package/dist/extensions/pi-subagents/test/unit/skills-fallback.test.ts +1 -1
  235. package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +1 -1
  236. package/dist/extensions/pi-subagents/test/unit/streamed-progress-bounds.test.ts +78 -0
  237. package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +41 -0
  238. package/dist/extensions/pi-subagents/test/unit/subagent-startup-retry.test.ts +77 -0
  239. package/dist/extensions/pi-subagents/test/unit/task-intent.test.ts +3 -0
  240. package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +1 -1
  241. package/dist/extensions/pi-subagents/test/unit/total-cost.test.ts +1 -0
  242. package/dist/extensions/pi-subagents/test/unit/watchdog-runtime.test.ts +210 -1
  243. package/dist/extensions/pi-subagents/test/unit/watchdog-scope.test.ts +33 -0
  244. package/dist/extensions/pi-subagents/test/unit/watchdog-settings.test.ts +32 -0
  245. package/dist/extensions/pi-subagents/test/unit/writer-budget-guidance.test.ts +1 -1
  246. package/dist/main.d.ts.map +1 -1
  247. package/dist/main.js +43 -0
  248. package/dist/main.js.map +1 -1
  249. package/dist/modes/interactive/components/custom-message.d.ts +3 -1
  250. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  251. package/dist/modes/interactive/components/custom-message.js +10 -2
  252. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  253. package/dist/modes/interactive/components/extension-editor.d.ts +1 -2
  254. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  255. package/dist/modes/interactive/components/extension-editor.js +16 -46
  256. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  257. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  258. package/dist/modes/interactive/components/model-selector.js +4 -1
  259. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  260. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  261. package/dist/modes/interactive/components/scoped-models-selector.js +22 -13
  262. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  263. package/dist/modes/interactive/external-editor.d.ts +12 -0
  264. package/dist/modes/interactive/external-editor.d.ts.map +1 -0
  265. package/dist/modes/interactive/external-editor.js +37 -0
  266. package/dist/modes/interactive/external-editor.js.map +1 -0
  267. package/dist/modes/interactive/interactive-mode.d.ts +1 -1
  268. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  269. package/dist/modes/interactive/interactive-mode.js +72 -64
  270. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  271. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  272. package/dist/modes/rpc/rpc-mode.js +14 -0
  273. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  274. package/dist/utils/clipboard.d.ts.map +1 -1
  275. package/dist/utils/clipboard.js +19 -8
  276. package/dist/utils/clipboard.js.map +1 -1
  277. package/dist/utils/version-check.d.ts.map +1 -1
  278. package/dist/utils/version-check.js +1 -1
  279. package/dist/utils/version-check.js.map +1 -1
  280. package/docs/compaction.md +1 -1
  281. package/docs/custom-provider.md +14 -5
  282. package/docs/environment-variables.md +86 -0
  283. package/docs/extensions.md +15 -5
  284. package/docs/index.md +1 -0
  285. package/docs/models.md +9 -2
  286. package/docs/providers.md +21 -2
  287. package/docs/rpc.md +23 -6
  288. package/docs/session-format.md +2 -0
  289. package/docs/settings.md +1 -1
  290. package/docs/usage.md +0 -13
  291. package/examples/extensions/custom-compaction.ts +5 -2
  292. package/examples/extensions/custom-provider-anthropic/index.ts +9 -3
  293. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  294. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  295. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  296. package/examples/extensions/gondolin/package-lock.json +2 -2
  297. package/examples/extensions/gondolin/package.json +1 -1
  298. package/examples/extensions/handoff.ts +11 -3
  299. package/examples/extensions/message-renderer.ts +3 -3
  300. package/examples/extensions/sandbox/package-lock.json +2 -2
  301. package/examples/extensions/sandbox/package.json +1 -1
  302. package/examples/extensions/summarize.ts +5 -2
  303. package/examples/extensions/with-deps/package-lock.json +2 -2
  304. package/examples/extensions/with-deps/package.json +1 -1
  305. package/examples/sdk/12-full-control.ts +3 -1
  306. package/package.json +15 -6
  307. package/dist/extensions/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
@@ -12,9 +12,9 @@ import { createRequire } from "node:module";
12
12
  import type { ExtensionAPI } from "@selesai/code";
13
13
  import type { AgentConfig } from "../../agents/agents.ts";
14
14
  import { writePrivateAtomicJson } from "../../shared/atomic-json.ts";
15
- import { applyThinkingSuffix, resolvePiLaunchToolPlan } from "../shared/pi-args.ts";
15
+ import { applyThinkingSuffix, projectLaunchResolvedChildExtensions, resolvePiLaunchToolPlan } from "../shared/pi-args.ts";
16
16
  import { injectOutputPathSystemPrompt, injectSingleOutputInstruction, normalizeSingleOutputOverride, resolveSingleOutputPath, validateFileOnlyOutputMode } from "../shared/single-output.ts";
17
- import { buildChainInstructions, isDynamicParallelStep, isParallelStep, resolveStepBehavior, suppressProgressForReadOnlyTask, writeInitialProgressFile, type ChainStep, type ResolvedStepBehavior, type SequentialStep, type StepOverrides } from "../../shared/settings.ts";
17
+ import { buildChainInstructions, isCheckpointStep, isDynamicParallelStep, isParallelStep, resolveStepBehavior, suppressProgressForReadOnlyTask, writeInitialProgressFile, type ChainStep, type ResolvedStepBehavior, type SequentialStep, type StepOverrides } from "../../shared/settings.ts";
18
18
  import type { RunnerStep } from "../shared/parallel-utils.ts";
19
19
  import type { ContextMode } from "../shared/context-mode.ts";
20
20
  import { resolvePiPackageRoot } from "../shared/pi-spawn.ts";
@@ -42,6 +42,7 @@ import {
42
42
  type ResolvedToolBudget,
43
43
  type SubagentRunMode,
44
44
  type SteeringRecoveryDescriptor,
45
+ type UsageBudgetConfig,
45
46
  ASYNC_DIR,
46
47
  RESULTS_DIR,
47
48
  SUBAGENT_ASYNC_STARTED_EVENT,
@@ -53,11 +54,12 @@ import {
53
54
  import { nestedResultsPath, nestedSummaryFromAsyncStatus, resolveInheritedNestedRouteFromEnv, resolveNestedParentAddressFromEnv, writeNestedEvent } from "../shared/nested-events.ts";
54
55
  import { appendTurnBudgetSystemPrompt, initialTurnBudgetState } from "../shared/turn-budget.ts";
55
56
  import { validateToolBudgetConfig } from "../shared/tool-budget.ts";
57
+ import { usageBudgetState } from "../shared/usage-budget.ts";
56
58
  import type { ImportedAsyncRoot } from "./chain-root-attachment.ts";
57
59
  import type { SessionLeaseRequest } from "../shared/session-lease.ts";
58
60
  import { finalizeProcessTerminal, readProcessTerminal } from "./process-terminal.ts";
59
61
  import { SUBAGENT_PROCESS_TERMINAL_EVENT } from "../../shared/types.ts";
60
- import { decodeSubagentCapabilityCeiling, resolveCurrentSubagentCapabilityCeiling, SUBAGENT_CAPABILITY_CEILING_ENV, type ResolvedSubagentCapabilityCeiling } from "../shared/capability-ceiling.ts";
62
+ import { assertAgentAllowedByCapabilityCeiling, decodeSubagentCapabilityCeiling, intersectSubagentCapabilityCeilings, resolveCurrentSubagentCapabilityCeiling, SUBAGENT_CAPABILITY_CEILING_ENV, type ResolvedSubagentCapabilityCeiling } from "../shared/capability-ceiling.ts";
61
63
  import { agentDefinitionDigest, launchBindingDigest } from "../../shared/launch-contract.ts";
62
64
 
63
65
  const require = createRequire(import.meta.url);
@@ -159,6 +161,7 @@ interface AsyncChainParams {
159
161
  timeoutMs?: number;
160
162
  turnBudget?: ResolvedTurnBudget;
161
163
  toolBudget?: ResolvedToolBudget;
164
+ usageBudget?: UsageBudgetConfig;
162
165
  configToolBudget?: ResolvedToolBudget;
163
166
  /** Global cap on simultaneously-running subagent tasks within the async run. */
164
167
  globalConcurrencyLimit?: number;
@@ -205,6 +208,7 @@ interface AsyncSingleParams {
205
208
  absoluteDeadlineAt?: number;
206
209
  turnBudget?: ResolvedTurnBudget;
207
210
  toolBudget?: ResolvedToolBudget;
211
+ usageBudget?: UsageBudgetConfig;
208
212
  configToolBudget?: ResolvedToolBudget;
209
213
  capabilityCeiling?: ResolvedSubagentCapabilityCeiling;
210
214
  }
@@ -592,11 +596,13 @@ export function buildAsyncRunnerSteps(id: string, params: AsyncRunnerStepBuildPa
592
596
  : chain;
593
597
  const firstStep = chain[0];
594
598
  const originalTask = params.task ?? (firstStep
595
- ? (isParallelStep(firstStep)
596
- ? firstStep.parallel[0]?.task
597
- : isDynamicParallelStep(firstStep)
598
- ? firstStep.parallel.task
599
- : (firstStep as SequentialStep).task)
599
+ ? (isCheckpointStep(firstStep)
600
+ ? undefined
601
+ : isParallelStep(firstStep)
602
+ ? firstStep.parallel[0]?.task
603
+ : isDynamicParallelStep(firstStep)
604
+ ? firstStep.parallel.task
605
+ : (firstStep as SequentialStep).task)
600
606
  : undefined);
601
607
  try {
602
608
  if (params.validateOutputBindings !== false) {
@@ -609,11 +615,13 @@ export function buildAsyncRunnerSteps(id: string, params: AsyncRunnerStepBuildPa
609
615
  const workflowGraph = buildWorkflowGraphSnapshot({ runId: id, mode: resultMode, steps: graphChain });
610
616
 
611
617
  for (const s of chain) {
612
- const stepAgents = isParallelStep(s)
613
- ? s.parallel.map((t) => t.agent)
614
- : isDynamicParallelStep(s)
615
- ? [s.parallel.agent]
616
- : [(s as SequentialStep).agent];
618
+ const stepAgents = isCheckpointStep(s)
619
+ ? []
620
+ : isParallelStep(s)
621
+ ? s.parallel.map((t) => t.agent)
622
+ : isDynamicParallelStep(s)
623
+ ? [s.parallel.agent]
624
+ : [(s as SequentialStep).agent];
617
625
  for (const agentName of stepAgents) {
618
626
  if (!agents.find((x) => x.name === agentName)) {
619
627
  return { error: `Unknown agent: ${agentName}` };
@@ -635,6 +643,11 @@ export function buildAsyncRunnerSteps(id: string, params: AsyncRunnerStepBuildPa
635
643
  };
636
644
  const buildSeqStep = (s: SequentialStep, sessionFile?: string, behaviorCwd?: string, progressPrecreated = false, resolvedBehavior?: ResolvedStepBehavior, flatIndex?: number, parallelOutputNamespace?: { stepIndex: number; taskIndex?: number }) => {
637
645
  const a = agents.find((x) => x.name === s.agent)!;
646
+ try {
647
+ assertAgentAllowedByCapabilityCeiling(a.name, intersectSubagentCapabilityCeilings(params.capabilityCeiling, decodeSubagentCapabilityCeiling(process.env[SUBAGENT_CAPABILITY_CEILING_ENV])));
648
+ } catch (error) {
649
+ throw new AsyncStartValidationError(error instanceof Error ? error.message : String(error));
650
+ }
638
651
  const toolBudgetInput = s.toolBudget ?? params.toolBudget ?? a.toolBudget ?? params.configToolBudget;
639
652
  const resolvedToolBudget = validateToolBudgetConfig(toolBudgetInput, s.toolBudget ? "toolBudget" : a.toolBudget ? "agent.toolBudget" : "config.toolBudget");
640
653
  if (resolvedToolBudget.error) throw new AsyncStartValidationError(resolvedToolBudget.error);
@@ -695,6 +708,19 @@ export function buildAsyncRunnerSteps(id: string, params: AsyncRunnerStepBuildPa
695
708
  const effectiveThinking = thinkingOverride ?? a.thinking;
696
709
  const model = applyThinkingSuffix(primaryModel, effectiveThinking, thinkingOverride !== undefined);
697
710
  const agentContract = s.agentContract ?? params.agentContract;
711
+ const toolPlan = resolvePiLaunchToolPlan({
712
+ tools: a.tools,
713
+ extensions: a.extensions,
714
+ subagentOnlyExtensions: a.subagentOnlyExtensions,
715
+ mcpDirectTools: a.mcpDirectTools,
716
+ cwd: stepCwd,
717
+ requireReadTool: Boolean(resolvedSkills.length),
718
+ structuredOutput: Boolean(s.outputSchema),
719
+ capabilityCeiling: params.capabilityCeiling,
720
+ inheritedCapabilityCeiling: decodeSubagentCapabilityCeiling(process.env[SUBAGENT_CAPABILITY_CEILING_ENV]),
721
+ agentName: a.name,
722
+ });
723
+ const launchResolvedExtensions = projectLaunchResolvedChildExtensions(toolPlan);
698
724
  return {
699
725
  parentSessionId: ctx.parentSessionId ?? ctx.currentSessionId,
700
726
  ...(params.capabilityCeiling ? { capabilityCeiling: params.capabilityCeiling } : {}),
@@ -709,6 +735,7 @@ export function buildAsyncRunnerSteps(id: string, params: AsyncRunnerStepBuildPa
709
735
  cwd: stepCwd,
710
736
  model,
711
737
  thinking: resolveEffectiveThinking(model, effectiveThinking),
738
+ launchResolvedExtensions,
712
739
  modelCandidates: buildModelCandidates(primaryModel, a.fallbackModels, availableModels, ctx.currentModelProvider, { scope: ctx.modelScope }).map((candidate) =>
713
740
  applyThinkingSuffix(candidate, effectiveThinking, thinkingOverride !== undefined),
714
741
  ),
@@ -762,6 +789,9 @@ export function buildAsyncRunnerSteps(id: string, params: AsyncRunnerStepBuildPa
762
789
 
763
790
  try {
764
791
  const builtSteps = chain.map((s, stepIndex) => {
792
+ if (isCheckpointStep(s)) {
793
+ return { checkpoint: s.checkpoint, ...(s.message ? { message: s.message } : {}), phase: s.phase, label: s.label };
794
+ }
765
795
  if (isParallelStep(s)) {
766
796
  const parallelBehaviors = s.parallel.map((task) => {
767
797
  const agent = agents.find((candidate) => candidate.name === task.agent)!;
@@ -948,6 +978,7 @@ export function executeAsyncChain(
948
978
  const { steps, runnerCwd, workflowGraph, eventChain } = built;
949
979
  const deadlineAt = params.timeoutMs !== undefined ? Date.now() + params.timeoutMs : undefined;
950
980
  const initialTurnBudget = params.turnBudget ? initialTurnBudgetState(params.turnBudget) : undefined;
981
+ const initialUsageBudget = usageBudgetState(params.usageBudget, undefined);
951
982
  let childTargetIndex = 0;
952
983
  const childIntercomTargets = childIntercomTarget ? steps.flatMap((step) => {
953
984
  if (!("parallel" in step) && step.importAsyncRoot) {
@@ -989,6 +1020,7 @@ export function executeAsyncChain(
989
1020
  controlConfig,
990
1021
  turnBudget: params.turnBudget,
991
1022
  toolBudget: params.toolBudget,
1023
+ usageBudget: params.usageBudget,
992
1024
  controlIntercomTarget,
993
1025
  childIntercomTargets,
994
1026
  resultMode,
@@ -1106,6 +1138,7 @@ export function executeAsyncChain(
1106
1138
  asyncDir,
1107
1139
  ...(params.timeoutMs !== undefined ? { timeoutMs: params.timeoutMs, deadlineAt } : {}),
1108
1140
  ...(initialTurnBudget ? { turnBudget: initialTurnBudget } : {}),
1141
+ ...(initialUsageBudget ? { usageBudget: initialUsageBudget } : {}),
1109
1142
  ...(capabilityCeiling ? { capabilityCeiling } : {}),
1110
1143
  nestedRoute,
1111
1144
  });
@@ -1119,7 +1152,7 @@ export function executeAsyncChain(
1119
1152
 
1120
1153
  return {
1121
1154
  content: [{ type: "text", text: formatAsyncStartedMessage(`Async ${resultMode}: ${chainDesc} [${id}]`, ctx.interactive === true) }],
1122
- details: { mode: resultMode, runId: id, results: [], asyncId: id, asyncDir, workflowGraph, ...(capabilityCeiling ? { capabilityCeiling } : {}), ...(params.timeoutMs !== undefined ? { timeoutMs: params.timeoutMs, deadlineAt } : {}), ...(params.turnBudget ? { turnBudget: params.turnBudget } : {}), ...(params.toolBudget ? { toolBudget: params.toolBudget } : {}) },
1155
+ details: { mode: resultMode, runId: id, results: [], asyncId: id, asyncDir, workflowGraph, ...(capabilityCeiling ? { capabilityCeiling } : {}), ...(params.timeoutMs !== undefined ? { timeoutMs: params.timeoutMs, deadlineAt } : {}), ...(params.turnBudget ? { turnBudget: params.turnBudget } : {}), ...(params.toolBudget ? { toolBudget: params.toolBudget } : {}), ...(initialUsageBudget ? { usageBudget: initialUsageBudget } : {}) },
1123
1156
  };
1124
1157
  }
1125
1158
 
@@ -1151,7 +1184,12 @@ export function executeAsyncSingle(
1151
1184
  nestedRoute,
1152
1185
  } = params;
1153
1186
  const task = params.task ?? "";
1154
- const capabilityCeiling = params.capabilityCeiling ?? resolveCurrentSubagentCapabilityCeiling(ctx.currentSessionId);
1187
+ const capabilityCeiling = intersectSubagentCapabilityCeilings(params.capabilityCeiling ?? resolveCurrentSubagentCapabilityCeiling(ctx.currentSessionId), decodeSubagentCapabilityCeiling(process.env[SUBAGENT_CAPABILITY_CEILING_ENV]));
1188
+ try {
1189
+ assertAgentAllowedByCapabilityCeiling(agentConfig.name, capabilityCeiling);
1190
+ } catch (error) {
1191
+ return formatAsyncStartError("single", error instanceof Error ? error.message : String(error));
1192
+ }
1155
1193
  const runnerCwd = resolveChildCwd(ctx.cwd, cwd);
1156
1194
  const skillNames = params.skills ?? agentConfig.skills ?? [];
1157
1195
  const availableModels = params.availableModels;
@@ -1213,6 +1251,7 @@ export function executeAsyncSingle(
1213
1251
  : params.timeoutMs;
1214
1252
  if (timeoutMs !== undefined && timeoutMs <= 0) return formatAsyncStartError("single", "The source run's absolute deadline expired before recovery could launch.");
1215
1253
  const initialTurnBudget = params.turnBudget ? initialTurnBudgetState(params.turnBudget) : undefined;
1254
+ const initialUsageBudget = usageBudgetState(params.usageBudget, undefined);
1216
1255
  const resolvedSessionDir = params.sessionDir ?? (sessionRoot ? path.join(sessionRoot, `async-${id}`) : undefined);
1217
1256
  const structuredOutput = params.structuredOutputSchema
1218
1257
  ? createStructuredOutputRuntime(params.structuredOutputSchema, path.join(asyncDir, "structured-output"))
@@ -1231,7 +1270,9 @@ export function executeAsyncSingle(
1231
1270
  structuredOutput: Boolean(params.structuredOutputSchema),
1232
1271
  capabilityCeiling,
1233
1272
  inheritedCapabilityCeiling: decodeSubagentCapabilityCeiling(process.env[SUBAGENT_CAPABILITY_CEILING_ENV]),
1273
+ agentName: agentConfig.name,
1234
1274
  });
1275
+ const launchResolvedExtensions = projectLaunchResolvedChildExtensions(toolPlan);
1235
1276
  const launchContractDigest = launchBindingDigest({
1236
1277
  definitionDigest: agentDefinitionDigest(agentConfig),
1237
1278
  task,
@@ -1265,6 +1306,7 @@ export function executeAsyncSingle(
1265
1306
  sourceRunId: id,
1266
1307
  ...(params.agentContract ? { agentContract: params.agentContract } : {}),
1267
1308
  agent,
1309
+ launchResolvedExtensions,
1268
1310
  ...(sessionFile ? { sessionFile } : {}),
1269
1311
  cwd: runnerCwd,
1270
1312
  ...(model ? { model } : {}),
@@ -1339,6 +1381,7 @@ export function executeAsyncSingle(
1339
1381
  definitionDigest: agentDefinitionDigest(agentConfig),
1340
1382
  launchBindingTask: task,
1341
1383
  launchContractDigest,
1384
+ launchResolvedExtensions,
1342
1385
  effectiveAcceptance: resolvedAcceptance,
1343
1386
  ...(structuredOutput ? { structuredOutput } : {}),
1344
1387
  ...(params.structuredOutputSchema ? { structuredOutputSchema: params.structuredOutputSchema } : {}),
@@ -1366,10 +1409,12 @@ export function executeAsyncSingle(
1366
1409
  deadlineAt,
1367
1410
  turnBudget: params.turnBudget,
1368
1411
  toolBudget: params.toolBudget,
1412
+ usageBudget: params.usageBudget,
1369
1413
  controlIntercomTarget,
1370
1414
  childIntercomTargets: childIntercomTarget ? [childIntercomTarget(agent, 0)] : undefined,
1371
1415
  resultMode: "single",
1372
1416
  launchContractDigest,
1417
+ launchResolvedExtensions,
1373
1418
  ...(params.revivalLease ? { revivalLease: params.revivalLease } : {}),
1374
1419
  nestedRoute: nestedRoute ?? inheritedNestedRoute,
1375
1420
  nestedSelf: inheritedNestedRoute && nestedAddress ? {
@@ -1441,8 +1486,10 @@ export function executeAsyncSingle(
1441
1486
  cwd: runnerCwd,
1442
1487
  asyncDir,
1443
1488
  launchContractDigest,
1489
+ launchResolvedExtensions,
1444
1490
  ...(timeoutMs !== undefined ? { timeoutMs, deadlineAt } : {}),
1445
1491
  ...(initialTurnBudget ? { turnBudget: initialTurnBudget } : {}),
1492
+ ...(initialUsageBudget ? { usageBudget: initialUsageBudget } : {}),
1446
1493
  ...(capabilityCeiling ? { capabilityCeiling } : {}),
1447
1494
  nestedRoute,
1448
1495
  });
@@ -1450,6 +1497,6 @@ export function executeAsyncSingle(
1450
1497
 
1451
1498
  return {
1452
1499
  content: [{ type: "text", text: formatAsyncStartedMessage(`Async: ${agent} [${id}]`, ctx.interactive === true) }],
1453
- details: { mode: "single", runId: id, results: [], asyncId: id, asyncDir, launchContractDigest, ...(capabilityCeiling ? { capabilityCeiling } : {}), ...(params.context ? { context: params.context } : {}), ...(timeoutMs !== undefined ? { timeoutMs, deadlineAt } : {}), ...(params.turnBudget ? { turnBudget: params.turnBudget } : {}), ...(params.toolBudget ? { toolBudget: params.toolBudget } : {}) },
1500
+ details: { mode: "single", runId: id, results: [], asyncId: id, asyncDir, launchContractDigest, launchResolvedExtensions, ...(capabilityCeiling ? { capabilityCeiling } : {}), ...(params.context ? { context: params.context } : {}), ...(timeoutMs !== undefined ? { timeoutMs, deadlineAt } : {}), ...(params.turnBudget ? { turnBudget: params.turnBudget } : {}), ...(params.toolBudget ? { toolBudget: params.toolBudget } : {}), ...(initialUsageBudget ? { usageBudget: initialUsageBudget } : {}) },
1454
1501
  };
1455
1502
  }
@@ -60,6 +60,19 @@ export function createAsyncJobTracker(pi: Pick<ExtensionAPI, "events">, state: S
60
60
  renderWidget(ctx, options.widgetEnabled === false ? [] : jobs);
61
61
  ctx.ui.requestRender?.();
62
62
  };
63
+ const rerenderLastWidget = (jobs = Array.from(state.asyncJobs.values())) => {
64
+ const ctx = state.lastUiContext;
65
+ if (!ctx) return;
66
+ try {
67
+ if (ctx.hasUI) rerenderWidget(ctx, jobs);
68
+ } catch (error) {
69
+ if (error instanceof Error && error.message.includes("extension ctx is stale")) {
70
+ state.lastUiContext = null;
71
+ return;
72
+ }
73
+ throw error;
74
+ }
75
+ };
63
76
  const refreshWidget = (ctx: ExtensionContext) => rerenderWidget(ctx);
64
77
  const restoredControlEventCursor = (asyncDir: string) => {
65
78
  try {
@@ -131,9 +144,7 @@ export function createAsyncJobTracker(pi: Pick<ExtensionAPI, "events">, state: S
131
144
  const timer = setTimeout(() => {
132
145
  state.cleanupTimers.delete(asyncId);
133
146
  state.asyncJobs.delete(asyncId);
134
- if (state.lastUiContext) {
135
- rerenderWidget(state.lastUiContext);
136
- }
147
+ rerenderLastWidget();
137
148
  }, completionRetentionMs);
138
149
  state.cleanupTimers.set(asyncId, timer);
139
150
  };
@@ -154,6 +165,10 @@ export function createAsyncJobTracker(pi: Pick<ExtensionAPI, "events">, state: S
154
165
  const startedFromTail = savedCursor === undefined && stat.size > CONTROL_EVENT_SCAN_WINDOW_BYTES;
155
166
  if (startedFromTail) cursor = stat.size - CONTROL_EVENT_SCAN_WINDOW_BYTES;
156
167
  if (stat.size <= cursor) return;
168
+ const previousByte = Buffer.alloc(1);
169
+ const startsMidLine = cursor > 0
170
+ && fs.readSync(fd, previousByte, 0, 1, cursor - 1) === 1
171
+ && previousByte[0] !== 0x0a;
157
172
  const scanEnd = Math.min(stat.size, cursor + CONTROL_EVENT_SCAN_WINDOW_BYTES);
158
173
  const handleLine = (line: string) => {
159
174
  if (!line.trim()) return;
@@ -206,7 +221,7 @@ export function createAsyncJobTracker(pi: Pick<ExtensionAPI, "events">, state: S
206
221
  let lastCompleteCursor = cursor;
207
222
  let lineParts: Buffer[] = [];
208
223
  let lineBytes = 0;
209
- let skippingOversizedLine = startedFromTail;
224
+ let skippingOversizedLine = startedFromTail || startsMidLine;
210
225
  const appendLineSegment = (segment: Buffer) => {
211
226
  if (segment.length === 0 || skippingOversizedLine) return;
212
227
  if (lineBytes + segment.length > MAX_CONTROL_EVENT_LINE_BYTES) {
@@ -254,7 +269,7 @@ export function createAsyncJobTracker(pi: Pick<ExtensionAPI, "events">, state: S
254
269
  if (state.poller) return;
255
270
  state.poller = setInterval(() => {
256
271
  if (state.asyncJobs.size === 0) {
257
- if (state.lastUiContext?.hasUI) rerenderWidget(state.lastUiContext, []);
272
+ rerenderLastWidget([]);
258
273
  if (state.poller) {
259
274
  clearInterval(state.poller);
260
275
  state.poller = null;
@@ -378,7 +393,7 @@ export function createAsyncJobTracker(pi: Pick<ExtensionAPI, "events">, state: S
378
393
  if (widgetRenderKey(job) !== widgetStateBefore) widgetChanged = true;
379
394
  }
380
395
 
381
- if (widgetChanged && state.lastUiContext?.hasUI) rerenderWidget(state.lastUiContext);
396
+ if (widgetChanged) rerenderLastWidget();
382
397
  }, pollIntervalMs);
383
398
  state.poller.unref?.();
384
399
  };
@@ -421,9 +436,7 @@ export function createAsyncJobTracker(pi: Pick<ExtensionAPI, "events">, state: S
421
436
  });
422
437
  rememberFleetJob(state, state.asyncJobs.get(info.id)!);
423
438
  ensurePoller();
424
- if (state.lastUiContext) {
425
- rerenderWidget(state.lastUiContext);
426
- }
439
+ rerenderLastWidget();
427
440
  };
428
441
 
429
442
  const handleComplete = (data: unknown) => {
@@ -446,9 +459,7 @@ export function createAsyncJobTracker(pi: Pick<ExtensionAPI, "events">, state: S
446
459
  }
447
460
  }
448
461
  if (job) rememberFleetJob(state, job);
449
- if (state.lastUiContext) {
450
- rerenderWidget(state.lastUiContext);
451
- }
462
+ rerenderLastWidget();
452
463
  if (!nestedRefreshFailed && !hasLiveNestedDescendants(job?.nestedChildren)) scheduleCleanup(asyncId);
453
464
  };
454
465
 
@@ -485,7 +496,7 @@ export function createAsyncJobTracker(pi: Pick<ExtensionAPI, "events">, state: S
485
496
  }
486
497
  if (runs.length === 0) return;
487
498
  ensurePoller();
488
- if (state.lastUiContext?.hasUI) rerenderWidget(state.lastUiContext);
499
+ rerenderLastWidget();
489
500
  };
490
501
 
491
502
  return { ensurePoller, refreshWidget, handleStarted, handleComplete, resetJobs, restoreActiveJobs };
@@ -256,6 +256,7 @@ function validateStatusForResume(status: AsyncStatus | null, source: string): vo
256
256
  if (stepRecord.sessionFile !== undefined && typeof stepRecord.sessionFile !== "string") throw new Error(`Invalid async status '${source}': steps[${index}].sessionFile must be a string.`);
257
257
  if (stepRecord.model !== undefined && typeof stepRecord.model !== "string") throw new Error(`Invalid async status '${source}': steps[${index}].model must be a string.`);
258
258
  if (stepRecord.thinking !== undefined && typeof stepRecord.thinking !== "string") throw new Error(`Invalid async status '${source}': steps[${index}].thinking must be a string.`);
259
+ if (stepRecord.launchContractDigest !== undefined && typeof stepRecord.launchContractDigest !== "string") throw new Error(`Invalid async status '${source}': steps[${index}].launchContractDigest must be a string.`);
259
260
  if (stepRecord.capabilityCeiling !== undefined) stepRecord.capabilityCeiling = parseSubagentCapabilityCeiling(stepRecord.capabilityCeiling, `async status '${source}' steps[${index}].capabilityCeiling`);
260
261
  });
261
262
  }
@@ -285,10 +286,11 @@ export function readAsyncRecoveryDescriptor(asyncDir: string | undefined): Steer
285
286
  if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': expected an object.`);
286
287
  const parsed = value as Record<string, unknown>;
287
288
  const allowedFields = new Set([
288
- "version", "sourceRunId", "agentContract", "agent", "sessionFile", "cwd", "model", "fallbackModels", "thinking", "tools", "extensions",
289
+ "version", "launchContractDigest", "sourceRunId", "agentContract", "agent", "sessionFile", "cwd", "model", "fallbackModels", "thinking", "tools", "extensions",
289
290
  "subagentOnlyExtensions", "mcpDirectTools", "systemPrompt", "systemPromptMode", "inheritProjectContext", "inheritSkills", "skills",
290
291
  "skillPath", "agentFilePath", "completionGuard", "memory", "outputPath", "outputMode", "structuredOutputSchema", "acceptance", "sessionDir", "artifactConfig",
291
292
  "artifactsDir", "maxOutput", "controlConfig", "absoluteDeadlineAt", "initialTurnBudget", "initialToolBudget", "maxSubagentDepth", "share", "capabilityCeiling",
293
+ "launchResolvedExtensions",
292
294
  ]);
293
295
  for (const field of Object.keys(parsed)) {
294
296
  if (!allowedFields.has(field)) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': unknown field '${field}'.`);
@@ -315,7 +317,7 @@ export function readAsyncRecoveryDescriptor(asyncDir: string | undefined): Steer
315
317
  if (item !== undefined && (!Array.isArray(item) || item.some((entry) => typeof entry !== "string" || !entry.trim()))) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': ${field} must contain non-empty strings.`);
316
318
  }
317
319
  if (parsed.systemPrompt !== undefined && typeof parsed.systemPrompt !== "string") throw new Error(`Invalid async recovery descriptor '${descriptorPath}': systemPrompt must be a string.`);
318
- for (const field of ["sessionFile", "model", "thinking", "agentFilePath", "outputPath", "sessionDir", "artifactsDir"] as const) {
320
+ for (const field of ["launchContractDigest", "sessionFile", "model", "thinking", "agentFilePath", "outputPath", "sessionDir", "artifactsDir"] as const) {
319
321
  if (parsed[field] !== undefined && (typeof parsed[field] !== "string" || !(parsed[field] as string).trim())) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': ${field} must be a non-empty string.`);
320
322
  }
321
323
  if (parsed.completionGuard !== undefined && typeof parsed.completionGuard !== "boolean") throw new Error(`Invalid async recovery descriptor '${descriptorPath}': completionGuard must be a boolean.`);
@@ -427,7 +429,7 @@ export function resolveAsyncResumeTarget(params: AsyncResumeParams, deps: AsyncR
427
429
  sessionFile: selectedStep.sessionFile ?? status?.sessionFile ?? result?.sessionFile,
428
430
  model: selectedStep.model,
429
431
  thinking: selectedStep.thinking,
430
- launchContractDigest: selectedStep.launchContractDigest ?? result?.results?.[requestedIndex]?.launchContractDigest ?? result?.launchContractDigest,
432
+ launchContractDigest: selectedStep.launchContractDigest ?? result?.results?.[requestedIndex]?.launchContractDigest ?? result?.launchContractDigest ?? recoveryDescriptor?.launchContractDigest,
431
433
  ...(capabilityCeiling ? { capabilityCeiling } : {}),
432
434
  ...(recoveryDescriptor ? { recoveryDescriptor } : {}),
433
435
  };
@@ -454,7 +456,7 @@ export function resolveAsyncResumeTarget(params: AsyncResumeParams, deps: AsyncR
454
456
  sessionFile: selected.step.sessionFile ?? status?.sessionFile ?? result?.sessionFile,
455
457
  model: selected.step.model,
456
458
  thinking: selected.step.thinking,
457
- launchContractDigest: selected.step.launchContractDigest ?? result?.results?.[selected.index]?.launchContractDigest ?? result?.launchContractDigest,
459
+ launchContractDigest: selected.step.launchContractDigest ?? result?.results?.[selected.index]?.launchContractDigest ?? result?.launchContractDigest ?? recoveryDescriptor?.launchContractDigest,
458
460
  ...(capabilityCeiling ? { capabilityCeiling } : {}),
459
461
  ...(recoveryDescriptor ? { recoveryDescriptor } : {}),
460
462
  };
@@ -490,7 +492,7 @@ export function resolveAsyncResumeTarget(params: AsyncResumeParams, deps: AsyncR
490
492
  ...(resolvedSessionFile ? { sessionFile: resolvedSessionFile } : {}),
491
493
  ...(stepModel ? { model: stepModel } : {}),
492
494
  ...(stepThinking ? { thinking: stepThinking } : {}),
493
- launchContractDigest: statusSteps[index]?.launchContractDigest ?? resultSteps[index]?.launchContractDigest ?? result?.launchContractDigest,
495
+ launchContractDigest: statusSteps[index]?.launchContractDigest ?? resultSteps[index]?.launchContractDigest ?? result?.launchContractDigest ?? recoveryDescriptor?.launchContractDigest,
494
496
  ...(capabilityCeiling ? { capabilityCeiling } : {}),
495
497
  ...(recoveryDescriptor ? { recoveryDescriptor } : {}),
496
498
  };
@@ -2,7 +2,7 @@ import * as fs from "node:fs";
2
2
  import * as path from "node:path";
3
3
  import { formatDuration, formatModelThinking, formatTokens, shortenPath } from "../../shared/formatters.ts";
4
4
  import { formatActivityLabel, formatParallelOutcome } from "../../shared/status-format.ts";
5
- import { type ActivityState, type AsyncJobStep, type AsyncParallelGroupStatus, type AsyncStatus, type CostSummary, type NestedRunSummary, type SteeringStatus, type SubagentRunMode, type TokenUsage, type TurnBudgetState } from "../../shared/types.ts";
5
+ import { type ActivityState, type AsyncJobStep, type AsyncParallelGroupStatus, type AsyncStatus, type CostSummary, type LaunchResolvedChildExtensionsV1, type RuntimeAcknowledgedChildExtensionsV1, type NestedRunSummary, type SteeringStatus, type SubagentRunMode, type TokenUsage, type TurnBudgetState, type UsageBudgetState, type ChainCheckpointState } from "../../shared/types.ts";
6
6
  import type { ResolvedSubagentCapabilityCeiling, SubagentCapabilityAudit } from "../shared/capability-ceiling.ts";
7
7
  import { readStatus } from "../../shared/utils.ts";
8
8
  import { attachRootChildrenToSteps, buildNestedRouteIndex, type NestedRoute, projectNestedEvents } from "../shared/nested-events.ts";
@@ -17,9 +17,11 @@ interface AsyncRunStepSummary {
17
17
  agent: string;
18
18
  context?: ContextMode;
19
19
  label?: string;
20
+ description?: string;
20
21
  phase?: string;
21
22
  outputName?: string;
22
23
  structured?: boolean;
24
+ checkpoint?: ChainCheckpointState;
23
25
  status: AsyncJobStep["status"];
24
26
  activityState?: ActivityState;
25
27
  lastActivityAt?: number;
@@ -53,6 +55,8 @@ interface AsyncRunStepSummary {
53
55
  review?: AsyncJobStep["review"];
54
56
  effects?: AsyncJobStep["effects"];
55
57
  processTerminal?: AsyncJobStep["processTerminal"];
58
+ launchResolvedExtensions?: LaunchResolvedChildExtensionsV1;
59
+ runtimeAcknowledgedExtensions?: RuntimeAcknowledgedChildExtensionsV1;
56
60
  capabilityCeiling?: ResolvedSubagentCapabilityCeiling;
57
61
  capabilityAudit?: SubagentCapabilityAudit;
58
62
  children?: NestedRunSummary[];
@@ -62,7 +66,7 @@ export interface AsyncRunSummary {
62
66
  id: string;
63
67
  asyncDir: string;
64
68
  sessionId?: string;
65
- state: "queued" | "running" | "complete" | "failed" | "paused" | "stopped";
69
+ state: "queued" | "running" | "complete" | "failed" | "paused" | "stopped" | "rejected";
66
70
  error?: string;
67
71
  activityState?: ActivityState;
68
72
  lastActivityAt?: number;
@@ -90,14 +94,18 @@ export interface AsyncRunSummary {
90
94
  pendingAppends?: number;
91
95
  parallelGroups?: AsyncParallelGroupStatus[];
92
96
  steps: AsyncRunStepSummary[];
97
+ checkpoint?: ChainCheckpointState;
93
98
  sessionDir?: string;
94
99
  outputFile?: string;
95
100
  totalTokens?: TokenUsage;
96
101
  totalCost?: CostSummary;
102
+ usageBudget?: UsageBudgetState;
97
103
  sessionFile?: string;
98
104
  nestedChildren?: NestedRunSummary[];
99
105
  nestedWarnings?: string[];
100
106
  processTerminal?: AsyncStatus["processTerminal"];
107
+ launchResolvedExtensions?: LaunchResolvedChildExtensionsV1;
108
+ runtimeAcknowledgedExtensions?: RuntimeAcknowledgedChildExtensionsV1;
101
109
  capabilityCeiling?: ResolvedSubagentCapabilityCeiling;
102
110
  capabilityAudit?: SubagentCapabilityAudit;
103
111
  }
@@ -225,9 +233,11 @@ function statusToSummary(asyncDir: string, status: AsyncStatus & { cwd?: string
225
233
  agent: step.agent,
226
234
  ...(step.context ? { context: step.context } : {}),
227
235
  ...(step.label ? { label: step.label } : {}),
236
+ ...(step.description ? { description: step.description } : {}),
228
237
  ...(step.phase ? { phase: step.phase } : {}),
229
238
  ...(step.outputName ? { outputName: step.outputName } : {}),
230
239
  ...(step.structured ? { structured: step.structured } : {}),
240
+ ...(step.checkpoint ? { checkpoint: step.checkpoint } : {}),
231
241
  status: step.status,
232
242
  ...(stepActivityState ? { activityState: stepActivityState } : {}),
233
243
  ...(stepLastActivityAt ? { lastActivityAt: stepLastActivityAt } : {}),
@@ -258,6 +268,8 @@ function statusToSummary(asyncDir: string, status: AsyncStatus & { cwd?: string
258
268
  ...(step.acceptance ? { acceptance: step.acceptance } : {}),
259
269
  ...(step.agentContract ? { agentContract: step.agentContract } : {}),
260
270
  ...(step.launchContractDigest ? { launchContractDigest: step.launchContractDigest } : {}),
271
+ ...(step.launchResolvedExtensions ? { launchResolvedExtensions: step.launchResolvedExtensions } : {}),
272
+ ...(step.runtimeAcknowledgedExtensions ? { runtimeAcknowledgedExtensions: step.runtimeAcknowledgedExtensions } : {}),
261
273
  ...(step.execution ? { execution: step.execution } : {}),
262
274
  ...(step.review ? { review: step.review } : {}),
263
275
  ...(step.effects ? { effects: step.effects } : {}),
@@ -300,16 +312,20 @@ function statusToSummary(asyncDir: string, status: AsyncStatus & { cwd?: string
300
312
  ...(status.pendingAppends !== undefined ? { pendingAppends: status.pendingAppends } : {}),
301
313
  ...(parallelGroups.length ? { parallelGroups } : {}),
302
314
  steps: summarizedSteps,
315
+ ...(status.checkpoint ? { checkpoint: status.checkpoint } : {}),
303
316
  ...(nestedChildren.length ? { nestedChildren } : {}),
304
317
  ...(nestedWarnings.length ? { nestedWarnings } : {}),
305
318
  ...(processTerminal ? { processTerminal } : {}),
306
319
  ...(status.launchContractDigest ? { launchContractDigest: status.launchContractDigest } : {}),
320
+ ...(status.launchResolvedExtensions ? { launchResolvedExtensions: status.launchResolvedExtensions } : {}),
321
+ ...(status.runtimeAcknowledgedExtensions ? { runtimeAcknowledgedExtensions: status.runtimeAcknowledgedExtensions } : {}),
307
322
  ...(status.capabilityCeiling ? { capabilityCeiling: status.capabilityCeiling } : {}),
308
323
  ...(status.capabilityAudit ? { capabilityAudit: status.capabilityAudit } : {}),
309
324
  ...(status.sessionDir ? { sessionDir: status.sessionDir } : {}),
310
325
  ...(status.outputFile ? { outputFile: status.outputFile } : {}),
311
326
  ...(status.totalTokens ? { totalTokens: status.totalTokens } : {}),
312
327
  ...(status.totalCost ? { totalCost: status.totalCost } : {}),
328
+ ...(status.usageBudget ? { usageBudget: status.usageBudget } : {}),
313
329
  ...(status.sessionFile ? { sessionFile: status.sessionFile } : {}),
314
330
  };
315
331
  }
@@ -5,8 +5,8 @@ import { writeAtomicJson } from "../../shared/atomic-json.ts";
5
5
  import { appendJsonl } from "../../shared/artifacts.ts";
6
6
  import type { AsyncParallelGroupStatus, AsyncStatus, WorkflowGraphNode, WorkflowGraphSnapshot } from "../../shared/types.ts";
7
7
  import { readStatus } from "../../shared/utils.ts";
8
- import type { DynamicRunnerGroup, ParallelStepGroup, RunnerStep, RunnerSubagentStep } from "../shared/parallel-utils.ts";
9
- import { isDynamicRunnerGroup, isParallelGroup } from "../shared/parallel-utils.ts";
8
+ import type { DynamicRunnerGroup, ParallelStepGroup, RunnerStep, RunnerSubagentStep, RunnerCheckpointStep } from "../shared/parallel-utils.ts";
9
+ import { isCheckpointRunnerStep, isDynamicRunnerGroup, isParallelGroup } from "../shared/parallel-utils.ts";
10
10
 
11
11
  const APPEND_REQUESTS_DIR = "append-requests";
12
12
 
@@ -51,7 +51,9 @@ export function countPendingChainAppendRequests(asyncDir: string): number {
51
51
  export function runnerStepOutputNames(steps: RunnerStep[]): string[] {
52
52
  const names: string[] = [];
53
53
  for (const step of steps) {
54
- if (isParallelGroup(step)) {
54
+ if (isCheckpointRunnerStep(step)) {
55
+ continue;
56
+ } else if (isParallelGroup(step)) {
55
57
  names.push(...step.parallel.map((task) => task.outputName).filter((name): name is string => Boolean(name)));
56
58
  } else if (isDynamicRunnerGroup(step)) {
57
59
  if (step.collect.as) names.push(step.collect.as);
@@ -128,9 +130,22 @@ export function consumeChainAppendRequests(asyncDir: string): ChainAppendRequest
128
130
  return requests.sort((left, right) => left.createdAt - right.createdAt || left.id.localeCompare(right.id));
129
131
  }
130
132
 
133
+ const MAX_STATUS_STEP_DESCRIPTION_CHARS = 160;
134
+
135
+ /** Bounded one-line per-step task description persisted into status.json for fleet display. */
136
+ export function statusStepDescription(task: string | undefined): string | undefined {
137
+ const description = task?.replace(/\s+/g, " ").trim();
138
+ if (!description) return undefined;
139
+ return description.length > MAX_STATUS_STEP_DESCRIPTION_CHARS
140
+ ? `${description.slice(0, MAX_STATUS_STEP_DESCRIPTION_CHARS - 1)}…`
141
+ : description;
142
+ }
143
+
131
144
  function statusStepForTask(task: RunnerSubagentStep): StatusStep {
145
+ const description = statusStepDescription(task.task);
132
146
  return {
133
147
  agent: task.agent,
148
+ ...(description ? { description } : {}),
134
149
  ...(task.context ? { context: task.context } : {}),
135
150
  phase: task.phase,
136
151
  label: task.label,
@@ -147,7 +162,20 @@ function statusStepForTask(task: RunnerSubagentStep): StatusStep {
147
162
  };
148
163
  }
149
164
 
150
- function statusStepsForRunnerStep(step: RunnerStep): StatusStep[] {
165
+ function statusStepForCheckpoint(step: RunnerCheckpointStep, stepIndex: number): StatusStep {
166
+ return {
167
+ agent: `checkpoint:${step.checkpoint}`,
168
+ phase: step.phase,
169
+ label: step.label ?? step.checkpoint,
170
+ status: "pending",
171
+ checkpoint: { name: step.checkpoint, ...(step.message ? { message: step.message } : {}), status: "pending", stepIndex },
172
+ recentTools: [],
173
+ recentOutput: [],
174
+ };
175
+ }
176
+
177
+ function statusStepsForRunnerStep(step: RunnerStep, stepIndex: number): StatusStep[] {
178
+ if (isCheckpointRunnerStep(step)) return [statusStepForCheckpoint(step, stepIndex)];
151
179
  if (isParallelGroup(step)) return step.parallel.map(statusStepForTask);
152
180
  if (isDynamicRunnerGroup(step)) {
153
181
  return [{
@@ -239,6 +267,21 @@ function graphNodeForDynamic(step: DynamicRunnerGroup, stepIndex: number): Workf
239
267
 
240
268
  function appendWorkflowNode(graph: WorkflowGraphSnapshot | undefined, step: RunnerStep, stepIndex: number, flatIndex: number): void {
241
269
  if (!graph) return;
270
+ if (isCheckpointRunnerStep(step)) {
271
+ const node: WorkflowGraphNode = {
272
+ id: `step-${stepIndex}`,
273
+ kind: "checkpoint",
274
+ phase: step.phase,
275
+ label: step.label?.trim() || step.checkpoint,
276
+ status: "pending",
277
+ flatIndex,
278
+ stepIndex,
279
+ checkpoint: { name: step.checkpoint, ...(step.message ? { message: step.message } : {}), status: "pending", stepIndex },
280
+ };
281
+ graph.nodes.push(node);
282
+ pushPhase(graph, step.phase, node.id);
283
+ return;
284
+ }
242
285
  if (isParallelGroup(step)) {
243
286
  graph.nodes.push(graphNodeForParallel(step, stepIndex, flatIndex, graph));
244
287
  return;
@@ -263,7 +306,7 @@ export function appendRunnerStepsToStatus(input: {
263
306
  for (const step of input.steps) {
264
307
  const stepIndex = input.status.chainStepCount ?? input.status.steps?.length ?? 0;
265
308
  const flatIndex = input.status.steps?.length ?? 0;
266
- const statusSteps = statusStepsForRunnerStep(step);
309
+ const statusSteps = statusStepsForRunnerStep(step, stepIndex);
267
310
  input.status.steps ??= [];
268
311
  input.status.steps.push(...statusSteps);
269
312
  if (isParallelGroup(step)) {