@selesai/code 0.5.27 → 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 (310) 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/extensions/question/index.ts +14 -1
  247. package/dist/extensions/question/tests/wizard.test.ts +11 -8
  248. package/dist/main.d.ts.map +1 -1
  249. package/dist/main.js +43 -0
  250. package/dist/main.js.map +1 -1
  251. package/dist/modes/interactive/components/custom-message.d.ts +3 -1
  252. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  253. package/dist/modes/interactive/components/custom-message.js +10 -2
  254. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  255. package/dist/modes/interactive/components/extension-editor.d.ts +1 -2
  256. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  257. package/dist/modes/interactive/components/extension-editor.js +16 -46
  258. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  259. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  260. package/dist/modes/interactive/components/model-selector.js +4 -1
  261. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  262. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  263. package/dist/modes/interactive/components/scoped-models-selector.js +22 -13
  264. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  265. package/dist/modes/interactive/external-editor.d.ts +12 -0
  266. package/dist/modes/interactive/external-editor.d.ts.map +1 -0
  267. package/dist/modes/interactive/external-editor.js +37 -0
  268. package/dist/modes/interactive/external-editor.js.map +1 -0
  269. package/dist/modes/interactive/interactive-mode.d.ts +1 -1
  270. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  271. package/dist/modes/interactive/interactive-mode.js +72 -64
  272. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  273. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  274. package/dist/modes/rpc/rpc-mode.js +14 -0
  275. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  276. package/dist/skills/batch-grill-me/SKILL.md +3 -1
  277. package/dist/utils/clipboard.d.ts.map +1 -1
  278. package/dist/utils/clipboard.js +19 -8
  279. package/dist/utils/clipboard.js.map +1 -1
  280. package/dist/utils/version-check.d.ts.map +1 -1
  281. package/dist/utils/version-check.js +1 -1
  282. package/dist/utils/version-check.js.map +1 -1
  283. package/docs/compaction.md +1 -1
  284. package/docs/custom-provider.md +14 -5
  285. package/docs/environment-variables.md +86 -0
  286. package/docs/extensions.md +15 -5
  287. package/docs/index.md +1 -0
  288. package/docs/models.md +9 -2
  289. package/docs/providers.md +21 -2
  290. package/docs/rpc.md +23 -6
  291. package/docs/session-format.md +2 -0
  292. package/docs/settings.md +1 -1
  293. package/docs/usage.md +0 -13
  294. package/examples/extensions/custom-compaction.ts +5 -2
  295. package/examples/extensions/custom-provider-anthropic/index.ts +9 -3
  296. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  297. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  298. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  299. package/examples/extensions/gondolin/package-lock.json +2 -2
  300. package/examples/extensions/gondolin/package.json +1 -1
  301. package/examples/extensions/handoff.ts +11 -3
  302. package/examples/extensions/message-renderer.ts +3 -3
  303. package/examples/extensions/sandbox/package-lock.json +2 -2
  304. package/examples/extensions/sandbox/package.json +1 -1
  305. package/examples/extensions/summarize.ts +5 -2
  306. package/examples/extensions/with-deps/package-lock.json +2 -2
  307. package/examples/extensions/with-deps/package.json +1 -1
  308. package/examples/sdk/12-full-control.ts +3 -1
  309. package/package.json +15 -6
  310. package/dist/extensions/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
@@ -57,6 +57,7 @@ export function defaultInheritSkills(): boolean {
57
57
  }
58
58
 
59
59
  export interface BuiltinAgentOverrideBase {
60
+ description?: string;
60
61
  model?: string;
61
62
  fallbackModels?: string[];
62
63
  thinking?: string | false;
@@ -78,6 +79,7 @@ export interface BuiltinAgentOverrideBase {
78
79
  }
79
80
 
80
81
  interface BuiltinAgentOverrideConfig {
82
+ description?: string;
81
83
  model?: string | false;
82
84
  fallbackModels?: string[] | false;
83
85
  thinking?: string | false;
@@ -114,6 +116,7 @@ export interface AgentConfig {
114
116
  localName?: string;
115
117
  packageName?: string;
116
118
  description: string;
119
+ aliases?: string[];
117
120
  tools?: string[];
118
121
  mcpDirectTools?: string[];
119
122
  model?: string;
@@ -150,6 +153,8 @@ export interface AgentConfig {
150
153
  modelSource?: AgentModelSourceInfo;
151
154
  }
152
155
 
156
+ type ProjectRootResolution = "nearest" | "git-root";
157
+
153
158
  interface SubagentSettings {
154
159
  overrides: Record<string, BuiltinAgentOverrideConfig>;
155
160
  defaultModel?: string;
@@ -420,7 +425,7 @@ function collectSettingsPackageRoots(settingsFile: string, baseDir: string): str
420
425
 
421
426
  function collectPackageSubagentPaths(cwd: string, options: { includeUser: boolean; includeProject: boolean } = { includeUser: true, includeProject: true }): PackageSubagentPaths {
422
427
  const agentDir = getAgentDir();
423
- const projectRoot = findNearestProjectRoot(cwd) ?? cwd;
428
+ const projectRoot = findConfiguredProjectRoot(cwd) ?? cwd;
424
429
  const packageRoots = [
425
430
  projectRoot,
426
431
  ];
@@ -469,6 +474,41 @@ function collectPackageSubagentPaths(cwd: string, options: { includeUser: boolea
469
474
  return { agents, chains };
470
475
  }
471
476
 
477
+ function normalizeAgentAliases(rawAliases: string[] | undefined, agentName: string): string[] | undefined {
478
+ const aliases = [...new Set((rawAliases ?? []).map((alias) => alias.trim()).filter(Boolean))]
479
+ .filter((alias) => alias !== agentName);
480
+ return aliases.length > 0 ? aliases : undefined;
481
+ }
482
+
483
+ function effectiveAgentMatch(matches: AgentConfig[]): { agent?: AgentConfig; error?: string } {
484
+ const distinctNames = [...new Set(matches.map((agent) => agent.name))];
485
+ if (distinctNames.length === 1) {
486
+ const sourceRank = new Map<AgentConfig["source"], number>([["builtin", 0], ["package", 1], ["user", 2], ["project", 3]]);
487
+ return { agent: [...matches].sort((a, b) => (sourceRank.get(b.source) ?? 0) - (sourceRank.get(a.source) ?? 0))[0] };
488
+ }
489
+ return {};
490
+ }
491
+
492
+ export function resolveAgentName(name: string, agents: AgentConfig[]): { agent?: AgentConfig; error?: string } {
493
+ const raw = name.trim();
494
+ const exact = agents.filter((agent) => agent.name === raw || agent.localName === raw);
495
+ if (exact.length === 1) return { agent: exact[0] };
496
+ if (exact.length > 1) {
497
+ const effective = effectiveAgentMatch(exact);
498
+ if (effective.agent) return effective;
499
+ return { error: `Ambiguous agent name '${name}': ${exact.map((agent) => agent.name).join(", ")}` };
500
+ }
501
+
502
+ const aliases = agents.filter((agent) => agent.aliases?.includes(raw));
503
+ if (aliases.length === 1) return { agent: aliases[0] };
504
+ if (aliases.length > 1) {
505
+ const effective = effectiveAgentMatch(aliases);
506
+ if (effective.agent) return effective;
507
+ return { error: `Ambiguous agent alias '${name}': ${aliases.map((agent) => agent.name).join(", ")}` };
508
+ }
509
+ return {};
510
+ }
511
+
472
512
  function splitToolList(rawTools: string[] | undefined): { tools?: string[]; mcpDirectTools?: string[] } {
473
513
  const mcpDirectTools: string[] = [];
474
514
  const tools: string[] = [];
@@ -505,6 +545,7 @@ function arraysEqual(a: string[] | undefined, b: string[] | undefined): boolean
505
545
 
506
546
  function cloneOverrideBase(agent: AgentConfig): BuiltinAgentOverrideBase {
507
547
  return {
548
+ description: agent.description,
508
549
  model: agent.model,
509
550
  fallbackModels: agent.fallbackModels ? [...agent.fallbackModels] : undefined,
510
551
  thinking: agent.thinking,
@@ -528,6 +569,7 @@ function cloneOverrideBase(agent: AgentConfig): BuiltinAgentOverrideBase {
528
569
 
529
570
  function cloneOverrideValue(override: BuiltinAgentOverrideConfig): BuiltinAgentOverrideConfig {
530
571
  return {
572
+ ...(override.description !== undefined ? { description: override.description } : {}),
531
573
  ...(override.model !== undefined ? { model: override.model } : {}),
532
574
  ...(override.fallbackModels !== undefined
533
575
  ? { fallbackModels: override.fallbackModels === false ? false : [...override.fallbackModels] }
@@ -549,12 +591,26 @@ function cloneOverrideValue(override: BuiltinAgentOverrideConfig): BuiltinAgentO
549
591
  };
550
592
  }
551
593
 
552
- export function findNearestProjectRoot(cwd: string): string | null {
594
+ function isProjectRootCandidate(dir: string): boolean {
595
+ return isDirectory(getProjectConfigDir(dir)) || isDirectory(path.join(dir, ".agents"));
596
+ }
597
+
598
+ function findProjectRootCandidates(cwd: string): string[] {
599
+ const roots: string[] = [];
553
600
  let currentDir = cwd;
554
601
  while (true) {
555
- if (isDirectory(getProjectConfigDir(currentDir)) || isDirectory(path.join(currentDir, ".agents"))) {
556
- return currentDir;
557
- }
602
+ if (isProjectRootCandidate(currentDir)) roots.push(currentDir);
603
+
604
+ const parentDir = path.dirname(currentDir);
605
+ if (parentDir === currentDir) return roots;
606
+ currentDir = parentDir;
607
+ }
608
+ }
609
+
610
+ function findNearestGitRoot(cwd: string): string | null {
611
+ let currentDir = cwd;
612
+ while (true) {
613
+ if (fs.existsSync(path.join(currentDir, ".git"))) return currentDir;
558
614
 
559
615
  const parentDir = path.dirname(currentDir);
560
616
  if (parentDir === currentDir) return null;
@@ -562,12 +618,46 @@ export function findNearestProjectRoot(cwd: string): string | null {
562
618
  }
563
619
  }
564
620
 
621
+ function readProjectRootResolution(projectRoot: string): ProjectRootResolution | undefined {
622
+ const settingsPath = path.join(getProjectConfigDir(projectRoot), "settings.json");
623
+ if (!fs.existsSync(settingsPath)) return undefined;
624
+ const settings = readSettingsFileStrict(settingsPath);
625
+ const subagents = settings.subagents;
626
+ if (!subagents || typeof subagents !== "object" || Array.isArray(subagents)) return undefined;
627
+
628
+ const value = (subagents as Record<string, unknown>).projectRootResolution;
629
+ if (value === undefined) return undefined;
630
+ if (value === "nearest" || value === "git-root") return value;
631
+ throw new Error(`Subagent settings in '${settingsPath}' have invalid 'projectRootResolution'; expected 'nearest' or 'git-root'.`);
632
+ }
633
+
634
+ export function findNearestProjectRoot(cwd: string): string | null {
635
+ return findProjectRootCandidates(cwd)[0] ?? null;
636
+ }
637
+
638
+ function findConfiguredProjectRoot(cwd: string): string | null {
639
+ const candidates = findProjectRootCandidates(cwd);
640
+ const nearestRoot = candidates[0];
641
+ if (!nearestRoot) return null;
642
+
643
+ const nearestMode = readProjectRootResolution(nearestRoot);
644
+ if (nearestMode === "nearest") return nearestRoot;
645
+
646
+ const gitRoot = findNearestGitRoot(cwd);
647
+ const gitProjectRoot = gitRoot ? candidates.find((candidate) => path.resolve(candidate) === path.resolve(gitRoot)) : undefined;
648
+ if (gitProjectRoot && (nearestMode === "git-root" || readProjectRootResolution(gitProjectRoot) === "git-root")) {
649
+ return gitProjectRoot;
650
+ }
651
+
652
+ return nearestRoot;
653
+ }
654
+
565
655
  function getUserAgentSettingsPath(): string {
566
656
  return path.join(getAgentDir(), "settings.json");
567
657
  }
568
658
 
569
659
  function getProjectAgentSettingsPath(cwd: string): string | null {
570
- const projectRoot = findNearestProjectRoot(cwd);
660
+ const projectRoot = findConfiguredProjectRoot(cwd);
571
661
  return projectRoot ? path.join(getProjectConfigDir(projectRoot), "settings.json") : null;
572
662
  }
573
663
 
@@ -632,6 +722,14 @@ function parseBuiltinOverrideEntry(
632
722
  const input = value as Record<string, unknown>;
633
723
  const override: BuiltinAgentOverrideConfig = {};
634
724
 
725
+ if ("description" in input) {
726
+ if (typeof input.description === "string" && input.description.trim()) {
727
+ override.description = input.description.trim();
728
+ } else {
729
+ throw new Error(`Builtin override '${name}' in '${filePath}' has invalid 'description'; expected a non-empty string.`);
730
+ }
731
+ }
732
+
635
733
  if ("model" in input) {
636
734
  if (typeof input.model === "string" || input.model === false) override.model = input.model;
637
735
  else throw new Error(`Builtin override '${name}' in '${filePath}' has invalid 'model'; expected a string or false.`);
@@ -879,6 +977,7 @@ function applyBuiltinOverride(
879
977
  override: { ...meta, base: cloneOverrideBase(agent) },
880
978
  };
881
979
 
980
+ if (override.description !== undefined) next.description = override.description;
882
981
  if (override.model !== undefined) next.model = override.model === false ? undefined : override.model;
883
982
  if (override.fallbackModels !== undefined) {
884
983
  next.fallbackModels = override.fallbackModels === false ? undefined : [...override.fallbackModels];
@@ -999,6 +1098,10 @@ function applyCustomAgentOverride(
999
1098
  anyFilled = true;
1000
1099
  };
1001
1100
 
1101
+ if (override.description !== undefined) {
1102
+ mutable().description = override.description;
1103
+ anyFilled = true;
1104
+ }
1002
1105
  if (override.model !== undefined) {
1003
1106
  fill("model", ["model"], override.model === false ? undefined : override.model);
1004
1107
  }
@@ -1089,10 +1192,14 @@ function applyCustomAgentOverrides(
1089
1192
 
1090
1193
  export function buildBuiltinOverrideConfig(
1091
1194
  base: BuiltinAgentOverrideBase,
1092
- draft: Pick<AgentConfig, "model" | "fallbackModels" | "thinking" | "systemPromptMode" | "inheritProjectContext" | "inheritSkills" | "defaultContext" | "acceptanceRole" | "disabled" | "systemPrompt" | "skills" | "tools" | "mcpDirectTools" | "extensions" | "subagentOnlyExtensions" | "completionGuard" | "toolBudget">,
1195
+ draft: Pick<AgentConfig, "model" | "fallbackModels" | "thinking" | "systemPromptMode" | "inheritProjectContext" | "inheritSkills" | "defaultContext" | "acceptanceRole" | "disabled" | "systemPrompt" | "skills" | "tools" | "mcpDirectTools" | "extensions" | "subagentOnlyExtensions" | "completionGuard" | "toolBudget"> & Partial<Pick<AgentConfig, "description">>,
1093
1196
  ): BuiltinAgentOverrideConfig | undefined {
1094
1197
  const override: BuiltinAgentOverrideConfig = {};
1095
1198
 
1199
+ if (draft.description !== undefined) {
1200
+ const description = draft.description.trim();
1201
+ if (description && description !== base.description) override.description = description;
1202
+ }
1096
1203
  if (draft.model !== base.model) override.model = draft.model ?? false;
1097
1204
  if (!arraysEqual(draft.fallbackModels, base.fallbackModels)) override.fallbackModels = draft.fallbackModels ? [...draft.fallbackModels] : false;
1098
1205
  if (draft.thinking !== base.thinking) override.thinking = draft.thinking ?? false;
@@ -1333,6 +1440,7 @@ function loadAgentsFromDir(dir: string, source: AgentSource): AgentConfig[] {
1333
1440
  const tools = parsedTools.tools ?? [];
1334
1441
  const mcpDirectTools = parsedTools.mcpDirectTools ?? [];
1335
1442
  const defaultReads = parseFrontmatterList(frontmatter.defaultReads);
1443
+ const aliases = normalizeAgentAliases(parseFrontmatterList(frontmatter.aliases ?? frontmatter.alias), runtimeName);
1336
1444
  const skillStr = frontmatter.skill || frontmatter.skills;
1337
1445
  const skills = parseFrontmatterList(skillStr);
1338
1446
  const skillPath = parseFrontmatterList(frontmatter.skillPath);
@@ -1413,6 +1521,7 @@ function loadAgentsFromDir(dir: string, source: AgentSource): AgentConfig[] {
1413
1521
  localName,
1414
1522
  packageName,
1415
1523
  description: frontmatter.description,
1524
+ aliases,
1416
1525
  tools: rawTools !== undefined ? tools : undefined,
1417
1526
  mcpDirectTools: mcpDirectTools.length > 0 ? mcpDirectTools : undefined,
1418
1527
  model: frontmatter.model,
@@ -1489,7 +1598,7 @@ function isDirectory(p: string): boolean {
1489
1598
  }
1490
1599
 
1491
1600
  function resolveNearestProjectAgentDirs(cwd: string): { readDirs: string[]; preferredDir: string | null } {
1492
- const projectRoot = findNearestProjectRoot(cwd);
1601
+ const projectRoot = findConfiguredProjectRoot(cwd);
1493
1602
  if (!projectRoot) return { readDirs: [], preferredDir: null };
1494
1603
 
1495
1604
  const legacyDir = path.join(projectRoot, ".agents");
@@ -1505,7 +1614,7 @@ function resolveNearestProjectAgentDirs(cwd: string): { readDirs: string[]; pref
1505
1614
  }
1506
1615
 
1507
1616
  function resolveNearestProjectChainDirs(cwd: string): { readDirs: string[]; preferredDir: string | null } {
1508
- const projectRoot = findNearestProjectRoot(cwd);
1617
+ const projectRoot = findConfiguredProjectRoot(cwd);
1509
1618
  if (!projectRoot) return { readDirs: [], preferredDir: null };
1510
1619
 
1511
1620
  const preferredDir = path.join(getProjectConfigDir(projectRoot), "chains");
@@ -379,19 +379,21 @@ function chooseHigherPrioritySkill(existing: CachedSkillEntry | undefined, candi
379
379
  return candidate.order < existing.order ? candidate : existing;
380
380
  }
381
381
 
382
- function maybeReadSkillDescription(filePath: string): string | undefined {
383
- try {
384
- const content = fs.readFileSync(filePath, "utf-8");
385
- const normalized = content.replace(/\r\n/g, "\n");
386
- if (!normalized.startsWith("---")) return undefined;
382
+ function parseSkillDescription(content: string): string | undefined {
383
+ const normalized = content.replace(/\r\n/g, "\n");
384
+ if (!normalized.startsWith("---")) return undefined;
385
+
386
+ const endIndex = normalized.indexOf("\n---", 3);
387
+ if (endIndex === -1) return undefined;
387
388
 
388
- const endIndex = normalized.indexOf("\n---", 3);
389
- if (endIndex === -1) return undefined;
389
+ const frontmatter = normalized.slice(3, endIndex).trim();
390
+ const match = frontmatter.match(/^description:\s*(.+)$/m);
391
+ return match?.[1]?.trim().replace(/^['\"]|['\"]$/g, "");
392
+ }
390
393
 
391
- const frontmatter = normalized.slice(3, endIndex).trim();
392
- const match = frontmatter.match(/^description:\s*(.+)$/m);
393
- if (!match) return undefined;
394
- return match[1]?.trim().replace(/^['\"]|['\"]$/g, "");
394
+ function maybeReadSkillDescription(filePath: string): string | undefined {
395
+ try {
396
+ return parseSkillDescription(fs.readFileSync(filePath, "utf-8"));
395
397
  } catch {
396
398
  // Description parsing is best-effort metadata extraction.
397
399
  return undefined;
@@ -585,7 +587,7 @@ function readSkill(
585
587
 
586
588
  const raw = fs.readFileSync(skillPath, "utf-8");
587
589
  const content = stripSkillFrontmatter(raw);
588
- const description = maybeReadSkillDescription(skillPath);
590
+ const description = parseSkillDescription(raw);
589
591
  const skill: ResolvedSkill = {
590
592
  name: skillName,
591
593
  path: skillPath,
@@ -131,6 +131,7 @@ export interface SubagentDelegationStarted {
131
131
  }
132
132
 
133
133
  export interface SubagentDelegationUpdate extends SubagentDelegationStarted {
134
+ runId?: string;
134
135
  currentTool?: string;
135
136
  currentToolArgs?: string;
136
137
  recentOutput?: string;
@@ -230,6 +231,7 @@ export interface SubagentDelegationV2Started {
230
231
  }
231
232
 
232
233
  export interface SubagentDelegationV2Update extends SubagentDelegationV2Started {
234
+ runId?: string;
233
235
  currentTool?: string;
234
236
  currentToolArgs?: string;
235
237
  recentOutput?: string;
@@ -266,6 +268,7 @@ export interface SubagentDelegationV2TerminalResponse extends SubagentDelegation
266
268
  model?: string;
267
269
  thinking?: string;
268
270
  exitCode?: number;
271
+ launchContractDigest?: string;
269
272
  result?: SubagentDelegationV2Value;
270
273
  usage?: SubagentDelegationV2Usage;
271
274
  }
@@ -2,7 +2,7 @@ import { createHash } from "node:crypto";
2
2
  import * as fs from "node:fs";
3
3
  import * as path from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
- import { discoverAgents, discoverAgentsAll, type AgentConfig, type AgentScope, type AgentSource } from "../agents/agents.ts";
5
+ import { discoverAgents, discoverAgentsAll, resolveAgentName, type AgentConfig, type AgentScope, type AgentSource } from "../agents/agents.ts";
6
6
  import { resolveExecutionAgentScope } from "../agents/agent-scope.ts";
7
7
  import { buildSkillInjection, normalizeSkillInput, resolveSkillsWithFallback } from "../agents/skills.ts";
8
8
  import { buildAgentMemoryInjection } from "../agents/agent-memory.ts";
@@ -12,7 +12,7 @@ import { injectOutputPathSystemPrompt, normalizeSingleOutputOverride, resolveSin
12
12
  import { getArtifactPaths, getArtifactsDir } from "../shared/artifacts.ts";
13
13
  import { resolveEffectiveThinking } from "../shared/model-info.ts";
14
14
  import { SUBAGENT_LIFECYCLE_ARTIFACT_VERSION, type ArtifactDirPreference, type ArtifactPaths, type JsonSchemaObject, type OutputMode } from "../shared/types.ts";
15
- import type { ResolvedSubagentCapabilityCeiling, SubagentCapabilityAudit } from "../runs/shared/capability-ceiling.ts";
15
+ import { capabilityCeilingAgentRestrictionMessage, intersectSubagentCapabilityCeilings, type ResolvedSubagentCapabilityCeiling, type SubagentCapabilityAudit } from "../runs/shared/capability-ceiling.ts";
16
16
  import { appendTurnBudgetSystemPrompt } from "../runs/shared/turn-budget.ts";
17
17
  import type { ResolvedTurnBudget } from "../shared/types.ts";
18
18
  import type { ResolvedMcpDirectToolSelection } from "../runs/shared/mcp-direct-tool-allowlist.ts";
@@ -31,7 +31,8 @@ export type SubagentLaunchContractReasonCode =
31
31
  | "denied_required_tool"
32
32
  | "invalid_artifact_dir"
33
33
  | "invalid_cwd"
34
- | "unsupported_mode";
34
+ | "unsupported_mode"
35
+ | "restricted_agent";
35
36
 
36
37
  export interface SubagentLaunchContractDiagnostic {
37
38
  code: SubagentLaunchContractReasonCode | "host_required" | "snapshot_warning";
@@ -191,7 +192,7 @@ function normalizeAvailableModels(models: SubagentLaunchContractInput["available
191
192
  function candidateList(inputAgent: string, selected: AgentConfig | undefined, cwd: string): SubagentLaunchContractAgentCandidate[] {
192
193
  const all = discoverAgentsAll(cwd);
193
194
  return [...all.builtin, ...all.package, ...all.user, ...all.project]
194
- .filter((agent) => agent.name === inputAgent || agent.localName === inputAgent)
195
+ .filter((agent) => Boolean(resolveAgentName(inputAgent, [agent]).agent))
195
196
  .map((agent) => ({
196
197
  name: agent.name,
197
198
  ...(agent.localName ? { localName: agent.localName } : {}),
@@ -225,14 +226,17 @@ export async function resolveSubagentLaunchContract(input: SubagentLaunchContrac
225
226
  }
226
227
  const scope = resolveExecutionAgentScope(input.agentScope);
227
228
  const discovered = discoverAgents(effectiveCwd, scope);
228
- const matches = discovered.agents.filter((agent) => agent.name === input.agent || agent.localName === input.agent);
229
- if (matches.length === 0) {
230
- return { ok: false, code: "missing_agent", message: `Unknown agent: ${input.agent}`, diagnostics };
229
+ const resolvedAgent = resolveAgentName(input.agent, discovered.agents);
230
+ if (resolvedAgent.error) {
231
+ return { ok: false, code: "ambiguous_agent", message: resolvedAgent.error, diagnostics };
231
232
  }
232
- if (matches.length > 1) {
233
- return { ok: false, code: "ambiguous_agent", message: `Ambiguous agent: ${input.agent}`, diagnostics };
233
+ if (!resolvedAgent.agent) {
234
+ return { ok: false, code: "missing_agent", message: `Unknown agent: ${input.agent}`, diagnostics };
234
235
  }
235
- const agent = matches[0]!;
236
+ const agent = resolvedAgent.agent;
237
+ const effectiveCapabilityCeiling = intersectSubagentCapabilityCeilings(input.capabilityCeiling, input.inheritedCapabilityCeiling);
238
+ const restrictionMessage = capabilityCeilingAgentRestrictionMessage(agent.name, effectiveCapabilityCeiling);
239
+ if (restrictionMessage) return { ok: false, code: "restricted_agent", message: restrictionMessage, diagnostics };
236
240
  const runId = input.runId ?? "preflight";
237
241
  const skillInput = normalizeSkillInput(input.skill);
238
242
  const outputOverride = normalizeSingleOutputOverride(input.output, agent.output);
@@ -272,8 +276,8 @@ export async function resolveSubagentLaunchContract(input: SubagentLaunchContrac
272
276
  cwd: effectiveCwd,
273
277
  requireReadTool: resolvedSkills.resolved.length > 0,
274
278
  structuredOutput: Boolean(input.outputSchema),
275
- capabilityCeiling: input.capabilityCeiling,
276
- inheritedCapabilityCeiling: input.inheritedCapabilityCeiling,
279
+ capabilityCeiling: effectiveCapabilityCeiling,
280
+ agentName: agent.name,
277
281
  });
278
282
  } catch (error) {
279
283
  const message = error instanceof Error ? error.message : String(error);
@@ -43,7 +43,7 @@ export const EXPAND_KEYS = allowedKeysOf(DynamicExpandSchema);
43
43
  export const EXPAND_FROM_KEYS = allowedKeysOf(ExpandFromSchema);
44
44
  export const COLLECT_KEYS = allowedKeysOf(DynamicCollectSchema);
45
45
 
46
- const CHAIN_STEP_EXAMPLE = '{"agent": "builder", "task": "do X"}';
46
+ const CHAIN_STEP_EXAMPLE = '{"agent": "builder", "task": "do X"} or {"checkpoint": "review", "message": "Approve before implementation?"}';
47
47
  const PARALLEL_TASK_EXAMPLE = '{"agent": "builder", "task": "do X"}';
48
48
  const DYNAMIC_TEMPLATE_EXAMPLE = '{"agent": "builder", "task": "Review {item.path}"}';
49
49
  const EXPAND_EXAMPLE = '{"from": {"output": "targets", "path": "/items"}, "maxItems": 4}';
@@ -58,6 +58,21 @@ function disallowedKeys(value: Record<string, unknown>, allowed: readonly string
58
58
  return Object.keys(value).filter((key) => !allowed.includes(key));
59
59
  }
60
60
 
61
+ function validateCheckpointShape(step: Record<string, unknown>, path: string): void {
62
+ if (step.checkpoint === undefined) return;
63
+ const allowed = new Set(["checkpoint", "message", "phase", "label"]);
64
+ const mixed = Object.keys(step).filter((key) => !allowed.has(key));
65
+ if (mixed.length > 0) {
66
+ throw new Error(`subagent ${path}: checkpoint steps cannot be mixed with child-launch properties ${quoteList(mixed)}.\n\nExample: {"checkpoint": "review", "message": "Approve before implementation?"}`);
67
+ }
68
+ if (typeof step.checkpoint !== "string" || !step.checkpoint.trim()) {
69
+ throw new Error(`subagent ${path}.checkpoint: expected a non-empty string.`);
70
+ }
71
+ if (step.message !== undefined && typeof step.message !== "string") {
72
+ throw new Error(`subagent ${path}.message: expected a string.`);
73
+ }
74
+ }
75
+
61
76
  function typeName(value: unknown): string {
62
77
  if (Array.isArray(value)) return "array";
63
78
  return typeof value;
@@ -120,6 +135,7 @@ export function validateChainInput(args: unknown): void {
120
135
  const stepPath = `chain step validation failed at chain[${index}]`;
121
136
  expectObject(step, stepPath, CHAIN_STEP_KEYS, CHAIN_STEP_EXAMPLE);
122
137
  checkNoExtraKeys(step, stepPath, ChainItem, CHAIN_STEP_KEYS, CHAIN_STEP_EXAMPLE);
138
+ validateCheckpointShape(step, stepPath);
123
139
 
124
140
  if (step.expand !== undefined) {
125
141
  const expandPath = `${stepPath}.expand`;
@@ -27,7 +27,7 @@ import { resolveCurrentSessionId } from "../shared/session-identity.ts";
27
27
  import { cleanupOldChainDirs } from "../shared/settings.ts";
28
28
  import { clearLegacyResultAnimationTimer, renderSubagentResult } from "../tui/render.ts";
29
29
  import { openSubagentFleet } from "../tui/fleet.ts";
30
- import { SubagentFleetStatus } from "../tui/fleet-status.ts";
30
+ import { SubagentFleetStatus, resolveFleetViewPlacement } from "../tui/fleet-status.ts";
31
31
  import { SubagentParams } from "./schemas.ts";
32
32
  import { validateChainInput } from "./chain-validation.ts";
33
33
  import { createSubagentExecutor, type SubagentParamsLike } from "../runs/foreground/subagent-executor.ts";
@@ -144,10 +144,13 @@ function createSlashResultComponent(
144
144
  }
145
145
 
146
146
  class SubagentControlNoticeComponent implements Component {
147
- constructor(
148
- private readonly details: SubagentControlMessageDetails,
149
- private readonly theme: ExtensionContext["ui"]["theme"],
150
- ) {}
147
+ private readonly details: SubagentControlMessageDetails;
148
+ private readonly theme: ExtensionContext["ui"]["theme"];
149
+
150
+ constructor(details: SubagentControlMessageDetails, theme: ExtensionContext["ui"]["theme"]) {
151
+ this.details = details;
152
+ this.theme = theme;
153
+ }
151
154
 
152
155
  invalidate(): void {}
153
156
 
@@ -194,6 +197,7 @@ export default function registerSubagentExtension(pi: ExtensionAPI): void {
194
197
  const waitToolConfig = resolveWaitToolConfig(config.waitTool);
195
198
  const asyncByDefault = config.asyncByDefault === true;
196
199
  const fleetViewEnabled = config.fleetView !== false;
200
+ const fleetViewPlacement = resolveFleetViewPlacement(config.fleetViewPlacement);
197
201
  const asyncWidgetEnabled = config.asyncWidget === true || (!fleetViewEnabled && config.asyncWidget !== false);
198
202
  const tempArtifactsDir = getArtifactsDir(null);
199
203
  cleanupAllArtifactDirs(DEFAULT_ARTIFACT_CONFIG.cleanupDays);
@@ -237,14 +241,17 @@ export default function registerSubagentExtension(pi: ExtensionAPI): void {
237
241
  const ctx = state.lastUiContext;
238
242
  if (!ctx?.hasUI) return;
239
243
  await openSubagentFleet(ctx, state, { initialKey: itemKey });
240
- })
244
+ }, { placement: fleetViewPlacement })
241
245
  : undefined;
242
246
  const { startResultWatcher, primeExistingResults, stopResultWatcher } = createResultWatcher(
243
247
  pi,
244
248
  state,
245
249
  RESULTS_DIR,
246
250
  10 * 60 * 1000,
247
- { notifier: completionNotifier },
251
+ {
252
+ notifier: completionNotifier,
253
+ deliverIntercomResults: config.intercomBridge?.resultDelivery !== false,
254
+ },
248
255
  );
249
256
 
250
257
  const runtimeCleanup = () => {
@@ -383,6 +390,7 @@ export default function registerSubagentExtension(pi: ExtensionAPI): void {
383
390
  events: pi.events,
384
391
  getContext: () => state.lastUiContext,
385
392
  execute: (id, params, signal, onUpdate, ctx) => executor.execute(id, params, signal, onUpdate, ctx),
393
+ state,
386
394
  });
387
395
 
388
396
  function effectiveParallelTaskCount(tasks: Array<{ count?: unknown }> | undefined): number {
@@ -551,6 +559,8 @@ export default function registerSubagentExtension(pi: ExtensionAPI): void {
551
559
  state.lastUiContext = ctx;
552
560
  cleanupSessionArtifacts(ctx);
553
561
  clearPendingForegroundControlNotices(state);
562
+ state.foregroundControls.clear();
563
+ state.lastForegroundControlId = null;
554
564
  resetJobs(ctx);
555
565
  restoreActiveJobs(ctx);
556
566
  scheduledRunManager.bindSession(ctx);