@gajae-code/coding-agent 0.11.1 → 0.11.3

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 (413) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/dist/types/cli/config-cli.d.ts +11 -1
  3. package/dist/types/cli/launch-disposition.d.ts +23 -0
  4. package/dist/types/cli/notify-cli.d.ts +1 -0
  5. package/dist/types/cli/session-picker.d.ts +2 -1
  6. package/dist/types/cli/setup-cli.d.ts +1 -1
  7. package/dist/types/commands/mcp-serve.d.ts +33 -0
  8. package/dist/types/commands/mcp.d.ts +1 -1
  9. package/dist/types/commands/notify.d.ts +0 -2
  10. package/dist/types/commands/sdk.d.ts +1 -1
  11. package/dist/types/config/atomic-yaml-patch.d.ts +18 -0
  12. package/dist/types/config/file-lock.d.ts +14 -4
  13. package/dist/types/config/keybindings.d.ts +42 -1
  14. package/dist/types/config/model-auth.d.ts +3 -0
  15. package/dist/types/config/model-bindings-applier.d.ts +13 -0
  16. package/dist/types/config/model-discovery-manager.d.ts +49 -0
  17. package/dist/types/config/model-equivalence.d.ts +20 -0
  18. package/dist/types/config/model-registry.d.ts +16 -15
  19. package/dist/types/config/model-resolver.d.ts +28 -18
  20. package/dist/types/config/models-config-schema.d.ts +11 -0
  21. package/dist/types/config/settings-schema.d.ts +141 -11
  22. package/dist/types/config/settings.d.ts +14 -11
  23. package/dist/types/coordinator-mcp/policy.d.ts +5 -0
  24. package/dist/types/coordinator-mcp/question-gate-codec.d.ts +129 -0
  25. package/dist/types/coordinator-mcp/question-state.d.ts +356 -0
  26. package/dist/types/coordinator-mcp/server.d.ts +4 -0
  27. package/dist/types/discovery/helpers.d.ts +0 -6
  28. package/dist/types/edit/index.d.ts +3 -0
  29. package/dist/types/eval/py/env.d.ts +9 -0
  30. package/dist/types/extensibility/extensions/loader.d.ts +2 -1
  31. package/dist/types/extensibility/extensions/runner.d.ts +2 -2
  32. package/dist/types/extensibility/extensions/types.d.ts +34 -3
  33. package/dist/types/extensibility/hooks/runner.d.ts +1 -1
  34. package/dist/types/extensibility/shared-events.d.ts +2 -0
  35. package/dist/types/gjc-runtime/deep-interview-recorder.d.ts +10 -1
  36. package/dist/types/gjc-runtime/deep-interview-state.d.ts +44 -0
  37. package/dist/types/gjc-runtime/goal-mode-request.d.ts +11 -1
  38. package/dist/types/gjc-runtime/launch-worktree.d.ts +4 -2
  39. package/dist/types/gjc-runtime/linux-proc.d.ts +29 -0
  40. package/dist/types/gjc-runtime/session-resolution.d.ts +2 -2
  41. package/dist/types/gjc-runtime/state-migrations.d.ts +1 -1
  42. package/dist/types/gjc-runtime/state-writer.d.ts +2 -1
  43. package/dist/types/gjc-runtime/team-launch.d.ts +59 -0
  44. package/dist/types/gjc-runtime/team-notify.d.ts +45 -0
  45. package/dist/types/gjc-runtime/team-runtime.d.ts +29 -121
  46. package/dist/types/gjc-runtime/team-store.d.ts +160 -0
  47. package/dist/types/gjc-runtime/team-workers.d.ts +78 -0
  48. package/dist/types/gjc-runtime/tmux-owner-isolation.d.ts +8 -0
  49. package/dist/types/gjc-runtime/ultragoal-change-set.d.ts +13 -0
  50. package/dist/types/gjc-runtime/ultragoal-evidence.d.ts +38 -0
  51. package/dist/types/gjc-runtime/ultragoal-guard.d.ts +7 -0
  52. package/dist/types/gjc-runtime/ultragoal-pipeline.d.ts +23 -0
  53. package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +55 -33
  54. package/dist/types/gjc-runtime/workflow-cli-common.d.ts +8 -0
  55. package/dist/types/gjc-runtime/workflow-manifest.d.ts +3 -0
  56. package/dist/types/goals/continuation-timeout-guard.d.ts +22 -0
  57. package/dist/types/goals/runtime.d.ts +1 -0
  58. package/dist/types/goals/state.d.ts +8 -0
  59. package/dist/types/harness-control-plane/lifecycle-reconciliation.d.ts +17 -0
  60. package/dist/types/harness-control-plane/phase-rollup.d.ts +4 -7
  61. package/dist/types/harness-control-plane/receipt-ingest.d.ts +5 -0
  62. package/dist/types/harness-control-plane/receipt-spool.d.ts +4 -0
  63. package/dist/types/hindsight/state.d.ts +11 -4
  64. package/dist/types/lsp/lspmux.d.ts +5 -3
  65. package/dist/types/lsp/path-trust.d.ts +1 -0
  66. package/dist/types/main.d.ts +4 -2
  67. package/dist/types/memories/storage.d.ts +1 -0
  68. package/dist/types/modes/action-registry.d.ts +29 -0
  69. package/dist/types/modes/components/chrome.d.ts +14 -0
  70. package/dist/types/modes/components/command-palette.d.ts +27 -0
  71. package/dist/types/modes/components/custom-provider-wizard.d.ts +1 -0
  72. package/dist/types/modes/components/index.d.ts +2 -1
  73. package/dist/types/modes/components/pet-selector.d.ts +1 -1
  74. package/dist/types/modes/components/plan-preview-overlay.d.ts +43 -0
  75. package/dist/types/modes/components/queue-mode-selector.d.ts +1 -1
  76. package/dist/types/modes/components/queue-pane.d.ts +12 -0
  77. package/dist/types/modes/components/read-tool-group.d.ts +6 -0
  78. package/dist/types/modes/components/session-observer-overlay.d.ts +3 -4
  79. package/dist/types/modes/components/sessions-dashboard.d.ts +32 -0
  80. package/dist/types/modes/components/settings-selector.d.ts +1 -1
  81. package/dist/types/modes/components/show-images-selector.d.ts +1 -1
  82. package/dist/types/modes/components/status-line/types.d.ts +1 -1
  83. package/dist/types/modes/components/status-line.d.ts +1 -94
  84. package/dist/types/modes/components/tasks-pane.d.ts +15 -0
  85. package/dist/types/modes/components/theme-selector.d.ts +1 -1
  86. package/dist/types/modes/components/tool-execution.d.ts +15 -0
  87. package/dist/types/modes/components/tool-status-header.d.ts +111 -0
  88. package/dist/types/modes/components/transcript-viewer-overlay.d.ts +42 -0
  89. package/dist/types/modes/controllers/goal-mode-controller.d.ts +62 -0
  90. package/dist/types/modes/controllers/input-controller.d.ts +8 -1
  91. package/dist/types/modes/controllers/mode-gate.d.ts +8 -0
  92. package/dist/types/modes/controllers/plan-mode-controller.d.ts +65 -0
  93. package/dist/types/modes/controllers/selector-controller.d.ts +15 -3
  94. package/dist/types/modes/controllers/stt-controller.d.ts +26 -0
  95. package/dist/types/modes/interactive-mode.d.ts +19 -17
  96. package/dist/types/modes/jobs-observer.d.ts +2 -0
  97. package/dist/types/modes/prompt-action-autocomplete.d.ts +4 -0
  98. package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +4 -11
  99. package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +20 -2
  100. package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +31 -0
  101. package/dist/types/modes/tasks-aggregator.d.ts +39 -0
  102. package/dist/types/modes/transcript-item-registry.d.ts +60 -0
  103. package/dist/types/modes/types.d.ts +20 -13
  104. package/dist/types/modes/utils/ui-helpers.d.ts +2 -2
  105. package/dist/types/runtime-mcp/manager.d.ts +1 -1
  106. package/dist/types/sdk/broker/broker.d.ts +78 -12
  107. package/dist/types/sdk/broker/lifecycle-codec.d.ts +4 -0
  108. package/dist/types/sdk/broker/lifecycle-ledger.d.ts +15 -1
  109. package/dist/types/sdk/broker/lifecycle.d.ts +6 -2
  110. package/dist/types/sdk/broker/process-incarnation.d.ts +2 -0
  111. package/dist/types/sdk/broker/session-index.d.ts +0 -1
  112. package/dist/types/sdk/broker/state-version.d.ts +2 -0
  113. package/dist/types/sdk/bus/chat-effect-journal.d.ts +1 -0
  114. package/dist/types/sdk/bus/config-commands.d.ts +1 -1
  115. package/dist/types/sdk/bus/config.d.ts +11 -0
  116. package/dist/types/sdk/bus/daemon-paths.d.ts +1 -0
  117. package/dist/types/sdk/bus/html-format.d.ts +3 -2
  118. package/dist/types/sdk/bus/index.d.ts +29 -0
  119. package/dist/types/sdk/bus/lifecycle-control-runtime.d.ts +4 -0
  120. package/dist/types/sdk/bus/notification-service.d.ts +20 -0
  121. package/dist/types/sdk/bus/rate-limit-pool.d.ts +13 -2
  122. package/dist/types/sdk/bus/recent-activity.d.ts +21 -12
  123. package/dist/types/sdk/bus/rich-document.d.ts +7 -0
  124. package/dist/types/sdk/bus/rich-render.d.ts +18 -41
  125. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +9 -4
  126. package/dist/types/sdk/bus/telegram-daemon.d.ts +46 -3
  127. package/dist/types/sdk/bus/threaded-inbound.d.ts +1 -1
  128. package/dist/types/sdk/bus/threaded-render.d.ts +13 -0
  129. package/dist/types/sdk/bus/topic-registry.d.ts +24 -2
  130. package/dist/types/sdk/host/control/operations.d.ts +1 -1
  131. package/dist/types/sdk/host/host.d.ts +2 -0
  132. package/dist/types/sdk/index.d.ts +1 -0
  133. package/dist/types/sdk/session-directory.d.ts +56 -0
  134. package/dist/types/sdk/session.d.ts +2 -0
  135. package/dist/types/session/agent-session.d.ts +82 -47
  136. package/dist/types/session/agent-storage.d.ts +7 -0
  137. package/dist/types/session/fallback-chain-controller.d.ts +10 -2
  138. package/dist/types/session/internal/managed-session-scope.d.ts +102 -0
  139. package/dist/types/session/internal/managed-session-storage.d.ts +38 -0
  140. package/dist/types/session/messages.d.ts +16 -0
  141. package/dist/types/session/session-manager-internal.d.ts +14 -0
  142. package/dist/types/session/session-manager.d.ts +82 -12
  143. package/dist/types/session/session-storage.d.ts +43 -3
  144. package/dist/types/session/volatile-context-pruning.d.ts +15 -0
  145. package/dist/types/skill-state/{deep-interview-mutation-guard.d.ts → workflow-mutation-guard.d.ts} +24 -8
  146. package/dist/types/skill-state/workflow-state-contract.d.ts +1 -3
  147. package/dist/types/slash-commands/builtin-registry.d.ts +4 -1
  148. package/dist/types/system-prompt.d.ts +2 -11
  149. package/dist/types/task/executor.d.ts +3 -1
  150. package/dist/types/thinking.d.ts +7 -0
  151. package/dist/types/tool-discovery/tool-index.d.ts +1 -50
  152. package/dist/types/tools/ask.d.ts +64 -2
  153. package/dist/types/tools/bash.d.ts +3 -0
  154. package/dist/types/tools/browser/dead-tab-recovery.d.ts +24 -0
  155. package/dist/types/tools/browser/tab-supervisor.d.ts +21 -0
  156. package/dist/types/tools/cron.d.ts +2 -0
  157. package/dist/types/tools/fetch.d.ts +1 -0
  158. package/dist/types/tools/index.d.ts +30 -15
  159. package/dist/types/tools/output-meta.d.ts +1 -0
  160. package/dist/types/tools/read.d.ts +5 -0
  161. package/dist/types/tools/search-tool-bm25.d.ts +3 -4
  162. package/dist/types/tools/subagent.d.ts +1 -0
  163. package/dist/types/utils/event-bus.d.ts +1 -1
  164. package/dist/types/utils/file-mentions.d.ts +3 -3
  165. package/dist/types/web/search/index.d.ts +3 -1
  166. package/package.json +21 -9
  167. package/scripts/build-sdk-package-smoke.ts +34 -1
  168. package/scripts/generate-hotkeys-docs.ts +74 -0
  169. package/scripts/generate-sdk-operation-inventory.ts +64 -20
  170. package/scripts/verify-gjc-sdk-canonicalization.ts +182 -2
  171. package/src/async/job-manager.ts +49 -6
  172. package/src/cli/config-cli.ts +75 -2
  173. package/src/cli/launch-disposition.ts +42 -0
  174. package/src/cli/notify-cli.ts +92 -26
  175. package/src/cli/session-picker.ts +20 -3
  176. package/src/cli/setup-cli.ts +1 -1
  177. package/src/cli.ts +1 -1
  178. package/src/commands/config.ts +1 -1
  179. package/src/commands/harness.ts +34 -106
  180. package/src/commands/launch.ts +6 -4
  181. package/src/commands/mcp-serve.ts +85 -8
  182. package/src/commands/mcp.ts +2 -2
  183. package/src/commands/notify.ts +8 -4
  184. package/src/commands/sdk.ts +61 -40
  185. package/src/commands/ultragoal.ts +4 -1
  186. package/src/config/atomic-yaml-patch.ts +80 -13
  187. package/src/config/file-lock.ts +105 -43
  188. package/src/config/keybindings.ts +64 -20
  189. package/src/config/model-auth.ts +9 -0
  190. package/src/config/model-bindings-applier.ts +139 -0
  191. package/src/config/model-discovery-manager.ts +224 -0
  192. package/src/config/model-equivalence.ts +66 -0
  193. package/src/config/model-registry.ts +169 -302
  194. package/src/config/model-resolver.ts +361 -369
  195. package/src/config/models-config-schema.ts +5 -4
  196. package/src/config/settings-schema.ts +214 -12
  197. package/src/config/settings.ts +458 -482
  198. package/src/coordinator-mcp/policy.ts +76 -11
  199. package/src/coordinator-mcp/question-gate-codec.ts +274 -0
  200. package/src/coordinator-mcp/question-state.ts +778 -0
  201. package/src/coordinator-mcp/server.ts +1702 -238
  202. package/src/debug/index.ts +1 -1
  203. package/src/defaults/gjc/skills/deep-interview/SKILL.md +13 -1
  204. package/src/defaults/gjc/skills/team/SKILL.md +16 -0
  205. package/src/discovery/helpers.ts +1 -50
  206. package/src/edit/index.ts +64 -0
  207. package/src/eval/py/env.ts +26 -0
  208. package/src/eval/py/kernel.ts +5 -3
  209. package/src/extensibility/extensions/loader.ts +9 -1
  210. package/src/extensibility/extensions/runner.ts +12 -3
  211. package/src/extensibility/extensions/types.ts +39 -1
  212. package/src/extensibility/gjc-plugins/installer.ts +16 -16
  213. package/src/extensibility/hooks/runner.ts +2 -2
  214. package/src/extensibility/runtime-skill-discovery.ts +33 -13
  215. package/src/extensibility/shared-events.ts +2 -0
  216. package/src/gjc-runtime/deep-interview-recorder.ts +63 -3
  217. package/src/gjc-runtime/deep-interview-runtime.ts +76 -27
  218. package/src/gjc-runtime/deep-interview-state.ts +317 -5
  219. package/src/gjc-runtime/goal-mode-request.ts +55 -8
  220. package/src/gjc-runtime/launch-tmux.ts +2 -5
  221. package/src/gjc-runtime/launch-worktree.ts +5 -5
  222. package/src/gjc-runtime/linux-proc.ts +71 -0
  223. package/src/gjc-runtime/ralplan-runtime.ts +74 -90
  224. package/src/gjc-runtime/session-resolution.ts +18 -3
  225. package/src/gjc-runtime/session-state-sidecar.ts +6 -107
  226. package/src/gjc-runtime/state-migrations.ts +1 -1
  227. package/src/gjc-runtime/state-runtime.ts +327 -249
  228. package/src/gjc-runtime/state-writer.ts +36 -40
  229. package/src/gjc-runtime/team-launch.ts +319 -0
  230. package/src/gjc-runtime/team-notify.ts +326 -0
  231. package/src/gjc-runtime/team-runtime.ts +1099 -1482
  232. package/src/gjc-runtime/team-store.ts +828 -0
  233. package/src/gjc-runtime/team-workers.ts +962 -0
  234. package/src/gjc-runtime/tmux-owner-isolation-cli.ts +2 -11
  235. package/src/gjc-runtime/tmux-owner-isolation.ts +14 -9
  236. package/src/gjc-runtime/tmux-sessions.ts +4 -21
  237. package/src/gjc-runtime/ultragoal-change-set.ts +172 -0
  238. package/src/gjc-runtime/ultragoal-evidence.ts +874 -0
  239. package/src/gjc-runtime/ultragoal-guard.ts +29 -5
  240. package/src/gjc-runtime/ultragoal-pipeline.ts +306 -0
  241. package/src/gjc-runtime/ultragoal-runtime.ts +84 -1311
  242. package/src/gjc-runtime/workflow-cli-common.ts +30 -0
  243. package/src/gjc-runtime/workflow-manifest.generated.json +58 -0
  244. package/src/gjc-runtime/workflow-manifest.ts +18 -0
  245. package/src/goals/continuation-timeout-guard.ts +79 -0
  246. package/src/goals/runtime.ts +7 -5
  247. package/src/goals/state.ts +18 -0
  248. package/src/harness-control-plane/lifecycle-reconciliation.ts +64 -0
  249. package/src/harness-control-plane/phase-rollup.ts +4 -7
  250. package/src/harness-control-plane/receipt-ingest.ts +5 -0
  251. package/src/harness-control-plane/receipt-spool.ts +51 -7
  252. package/src/harness-control-plane/session-lease.ts +12 -130
  253. package/src/hindsight/backend.ts +26 -27
  254. package/src/hindsight/state.ts +101 -32
  255. package/src/hooks/skill-state.ts +17 -11
  256. package/src/internal-urls/docs-index.generated.ts +21 -18
  257. package/src/lsp/client.ts +1 -1
  258. package/src/lsp/config.ts +145 -26
  259. package/src/lsp/index.ts +1 -1
  260. package/src/lsp/lspmux.ts +39 -10
  261. package/src/lsp/path-trust.ts +81 -0
  262. package/src/main.ts +127 -30
  263. package/src/memories/index.ts +1 -0
  264. package/src/memories/storage.ts +6 -2
  265. package/src/modes/action-registry.ts +165 -0
  266. package/src/modes/components/chrome.ts +40 -0
  267. package/src/modes/components/command-palette.ts +168 -0
  268. package/src/modes/components/custom-editor.ts +1 -1
  269. package/src/modes/components/custom-provider-wizard.ts +51 -14
  270. package/src/modes/components/index.ts +2 -1
  271. package/src/modes/components/pet-selector.ts +11 -17
  272. package/src/modes/components/plan-preview-overlay.ts +295 -0
  273. package/src/modes/components/queue-mode-selector.ts +10 -27
  274. package/src/modes/components/queue-pane.ts +79 -0
  275. package/src/modes/components/read-tool-group.ts +13 -0
  276. package/src/modes/components/session-observer-overlay.ts +207 -772
  277. package/src/modes/components/sessions-dashboard.ts +181 -0
  278. package/src/modes/components/settings-selector.ts +1 -1
  279. package/src/modes/components/show-images-selector.ts +10 -24
  280. package/src/modes/components/status-line/types.ts +1 -1
  281. package/src/modes/components/status-line.ts +1 -969
  282. package/src/modes/components/tasks-pane.ts +73 -0
  283. package/src/modes/components/theme-selector.ts +11 -31
  284. package/src/modes/components/tool-execution.ts +22 -0
  285. package/src/modes/components/tool-status-header.ts +1056 -0
  286. package/src/modes/components/transcript-viewer-overlay.ts +384 -0
  287. package/src/modes/controllers/btw-controller.ts +1 -0
  288. package/src/modes/controllers/event-controller.ts +3 -2
  289. package/src/modes/controllers/extension-ui-controller.ts +24 -1
  290. package/src/modes/controllers/goal-mode-controller.ts +474 -0
  291. package/src/modes/controllers/input-controller.ts +764 -229
  292. package/src/modes/controllers/mode-gate.ts +24 -0
  293. package/src/modes/controllers/plan-mode-controller.ts +517 -0
  294. package/src/modes/controllers/selector-controller.ts +225 -10
  295. package/src/modes/controllers/stt-controller.ts +125 -0
  296. package/src/modes/interactive-mode.ts +289 -1150
  297. package/src/modes/jobs-observer.ts +3 -0
  298. package/src/modes/prompt-action-autocomplete.ts +7 -0
  299. package/src/modes/runtime-init.ts +8 -0
  300. package/src/modes/shared/agent-wire/deep-interview-gate.ts +31 -106
  301. package/src/modes/shared/agent-wire/workflow-gate-broker.ts +71 -16
  302. package/src/modes/shared/agent-wire/workflow-gate-types.ts +177 -0
  303. package/src/modes/tasks-aggregator.ts +199 -0
  304. package/src/modes/transcript-item-registry.ts +229 -0
  305. package/src/modes/types.ts +45 -18
  306. package/src/modes/utils/ui-helpers.ts +17 -9
  307. package/src/prompts/agent-fragments/ralplan-persistence.md +6 -0
  308. package/src/prompts/agent-fragments/restricted-bash.md +1 -0
  309. package/src/prompts/agents/architect.md +2 -8
  310. package/src/prompts/agents/critic.md +2 -8
  311. package/src/prompts/agents/executor.md +3 -0
  312. package/src/prompts/agents/planner.md +4 -12
  313. package/src/prompts/system/custom-system-prompt.md +1 -23
  314. package/src/prompts/system/plan-mode-approved.md +8 -0
  315. package/src/prompts/system/system-prompt.md +17 -96
  316. package/src/prompts/tools/bash.md +4 -4
  317. package/src/prompts/tools/browser.md +15 -52
  318. package/src/prompts/tools/find.md +2 -2
  319. package/src/prompts/tools/hashline.md +13 -55
  320. package/src/prompts/tools/read.md +3 -6
  321. package/src/prompts/tools/search-tool-bm25.md +0 -2
  322. package/src/prompts/tools/search.md +2 -4
  323. package/src/prompts/tools/skill-discovery.md +1 -2
  324. package/src/prompts/tools/task.md +1 -1
  325. package/src/runtime-mcp/manager.ts +1 -1
  326. package/src/sdk/broker/broker.ts +206 -78
  327. package/src/sdk/broker/discovery.ts +1 -1
  328. package/src/sdk/broker/ensure.ts +3 -1
  329. package/src/sdk/broker/lifecycle-codec.ts +11 -0
  330. package/src/sdk/broker/lifecycle-ledger.ts +371 -74
  331. package/src/sdk/broker/lifecycle.ts +1399 -142
  332. package/src/sdk/broker/process-incarnation.ts +5 -13
  333. package/src/sdk/broker/session-index.ts +145 -56
  334. package/src/sdk/broker/state-version.ts +21 -0
  335. package/src/sdk/broker/transport.ts +1 -1
  336. package/src/sdk/bus/chat-daemon-cli.ts +2 -0
  337. package/src/sdk/bus/chat-daemon-control.ts +8 -28
  338. package/src/sdk/bus/chat-effect-journal.ts +10 -2
  339. package/src/sdk/bus/config-commands.ts +5 -4
  340. package/src/sdk/bus/config.ts +98 -0
  341. package/src/sdk/bus/conversation-store.ts +5 -29
  342. package/src/sdk/bus/daemon-paths.ts +2 -0
  343. package/src/sdk/bus/html-format.ts +20 -3
  344. package/src/sdk/bus/index.ts +782 -94
  345. package/src/sdk/bus/lifecycle-control-runtime.ts +91 -33
  346. package/src/sdk/bus/natives-augment.d.ts +26 -1
  347. package/src/sdk/bus/notification-service.ts +168 -20
  348. package/src/sdk/bus/rate-limit-pool.ts +58 -14
  349. package/src/sdk/bus/recent-activity.ts +188 -74
  350. package/src/sdk/bus/rich-document.ts +258 -0
  351. package/src/sdk/bus/rich-render.ts +62 -70
  352. package/src/sdk/bus/telegram-daemon-cli.ts +15 -59
  353. package/src/sdk/bus/telegram-daemon-contract.ts +9 -4
  354. package/src/sdk/bus/telegram-daemon.ts +1389 -237
  355. package/src/sdk/bus/threaded-inbound.ts +8 -3
  356. package/src/sdk/bus/threaded-render.ts +57 -1
  357. package/src/sdk/bus/topic-registry.ts +120 -13
  358. package/src/sdk/host/control/dispatch.ts +14 -2
  359. package/src/sdk/host/control/operations.ts +6 -1
  360. package/src/sdk/host/host.ts +44 -2
  361. package/src/sdk/host/query/handlers.ts +20 -22
  362. package/src/sdk/host/query/revision-store.ts +80 -57
  363. package/src/sdk/index.ts +1 -0
  364. package/src/sdk/protocol/operation-inventory.generated.json +943 -1907
  365. package/src/sdk/session-directory.ts +141 -0
  366. package/src/sdk/session.ts +462 -480
  367. package/src/session/agent-session.ts +1700 -583
  368. package/src/session/agent-storage.ts +18 -0
  369. package/src/session/cache-economics.ts +25 -8
  370. package/src/session/fallback-chain-controller.ts +53 -3
  371. package/src/session/internal/managed-session-scope.ts +2226 -0
  372. package/src/session/internal/managed-session-storage.ts +453 -0
  373. package/src/session/messages.ts +91 -2
  374. package/src/session/session-manager-internal.ts +33 -0
  375. package/src/session/session-manager.ts +1112 -333
  376. package/src/session/session-storage.ts +444 -39
  377. package/src/session/volatile-context-pruning.ts +78 -0
  378. package/src/setup/credential-auto-import.ts +2 -1
  379. package/src/setup/hermes/templates/operator-instructions.v1.md +1 -1
  380. package/src/setup/provider-onboarding.ts +36 -61
  381. package/src/setup/provider-presets.json +5 -0
  382. package/src/skill-state/active-state.ts +3 -13
  383. package/src/skill-state/{deep-interview-mutation-guard.ts → workflow-mutation-guard.ts} +47 -29
  384. package/src/skill-state/workflow-state-contract.ts +6 -41
  385. package/src/slash-commands/builtin-registry.ts +46 -11
  386. package/src/system-prompt.ts +37 -44
  387. package/src/task/agents.ts +19 -1
  388. package/src/task/executor.ts +90 -6
  389. package/src/task/index.ts +36 -21
  390. package/src/thinking.ts +21 -6
  391. package/src/tool-discovery/tool-index.ts +2 -134
  392. package/src/tools/ask.ts +157 -21
  393. package/src/tools/ast-edit.ts +1 -1
  394. package/src/tools/bash.ts +38 -0
  395. package/src/tools/browser/dead-tab-recovery.ts +78 -0
  396. package/src/tools/browser/tab-supervisor.ts +282 -36
  397. package/src/tools/computer.ts +10 -3
  398. package/src/tools/cron.ts +30 -16
  399. package/src/tools/eval.ts +1 -2
  400. package/src/tools/fetch.ts +11 -4
  401. package/src/tools/index.ts +76 -24
  402. package/src/tools/output-meta.ts +19 -7
  403. package/src/tools/read.ts +219 -64
  404. package/src/tools/resource-gc.ts +2 -2
  405. package/src/tools/search-tool-bm25.ts +11 -74
  406. package/src/tools/subagent.ts +43 -2
  407. package/src/utils/event-bus.ts +9 -4
  408. package/src/utils/file-mentions.ts +4 -4
  409. package/src/web/search/index.ts +3 -3
  410. package/dist/types/discovery/plugin-dir-roots.d.ts +0 -15
  411. package/dist/types/runtime-mcp/discoverable-tool-metadata.d.ts +0 -7
  412. package/src/discovery/plugin-dir-roots.ts +0 -28
  413. package/src/runtime-mcp/discoverable-tool-metadata.ts +0 -25
@@ -10,11 +10,13 @@ import { contextFileCapability } from "./capability/context-file";
10
10
  import { systemPromptCapability } from "./capability/system-prompt";
11
11
  import type { SkillsSettings } from "./config/settings";
12
12
  import { type ContextFile, loadCapability, type SystemPrompt as SystemPromptFile } from "./discovery";
13
- import { loadSkills, type Skill } from "./extensibility/skills";
13
+ import type { Skill } from "./extensibility/skills";
14
14
  import customSystemPromptTemplate from "./prompts/system/custom-system-prompt.md" with { type: "text" };
15
15
  import projectPromptTemplate from "./prompts/system/project-prompt.md" with { type: "text" };
16
16
  import systemPromptTemplate from "./prompts/system/system-prompt.md" with { type: "text" };
17
17
  import volatileProjectContextTemplate from "./prompts/system/volatile-project-context.md" with { type: "text" };
18
+ import { escapePromptMetadata } from "./session/messages";
19
+ import { DEFAULT_ESSENTIAL_TOOL_NAMES } from "./tools";
18
20
  import { shortenPath } from "./tools/render-utils";
19
21
  import { AGENTS_MD_LIMIT, buildWorkspaceTree, type WorkspaceTree } from "./workspace-tree";
20
22
 
@@ -68,6 +70,11 @@ function dedupePromptSource(source: string | null | undefined, otherSources: Arr
68
70
  return otherSources.some(otherSource => promptSourceContainsRule(otherSource, resolvedSource)) ? "" : resolvedSource;
69
71
  }
70
72
 
73
+ /** Neutralize tag-like sequences in embedded project context so file bodies cannot escape framing. */
74
+ function sanitizeEmbeddedPromptContent(content: string): string {
75
+ return escapePromptMetadata(content, { preserveNewlines: true });
76
+ }
77
+
71
78
  function firstNonEmpty(...values: (string | undefined | null)[]): string | null {
72
79
  for (const value of values) {
73
80
  const trimmed = value?.trim();
@@ -360,14 +367,8 @@ export interface BuildSystemPromptOptions {
360
367
  rules?: Array<{ name: string; description?: string; path: string; globs?: string[] }>;
361
368
  /** Intent field name injected into every tool schema. If set, explains the field in the prompt. */
362
369
  intentField?: string;
363
- /** Whether MCP tool discovery is active for this prompt build. */
364
- mcpDiscoveryMode?: boolean;
365
- /** Discoverable MCP server summaries to advertise when discovery mode is active. */
366
- mcpDiscoveryServerSummaries?: string[];
367
- /** Whether built-in tool discovery ("all" mode) is active; enables the tool-discovery prompt block. */
370
+ /** Whether built-in tool discovery is active; enables the tool-discovery prompt block. */
368
371
  toolDiscoveryActive?: boolean;
369
- /** Hidden discoverable tools to advertise (name + one-line summary) when tool discovery is active. */
370
- discoverableTools?: Array<{ name: string; summary: string }>;
371
372
  /** Encourage the agent to delegate via tasks unless changes are trivial. */
372
373
  eagerTasks?: boolean;
373
374
  /** Rules with alwaysApply=true — their full content is injected into the prompt. */
@@ -402,13 +403,16 @@ export function buildVolatileProjectContext(options: BuildVolatileProjectContext
402
403
  return prompt
403
404
  .render(volatileProjectContextTemplate, {
404
405
  date,
405
- cwd: shortenPath(resolvedCwd.replace(/\\/g, "/")),
406
- workspaceTree: options.workspaceTree ?? {
407
- rootPath: resolvedCwd,
408
- rendered: "",
409
- truncated: false,
410
- totalLines: 0,
411
- agentsMdFiles: [],
406
+ cwd: escapePromptMetadata(shortenPath(resolvedCwd.replace(/\\/g, "/"))),
407
+ workspaceTree: {
408
+ ...(options.workspaceTree ?? {
409
+ rootPath: resolvedCwd,
410
+ rendered: "",
411
+ truncated: false,
412
+ totalLines: 0,
413
+ agentsMdFiles: [],
414
+ }),
415
+ rendered: escapePromptMetadata(options.workspaceTree?.rendered ?? "", { preserveNewlines: true }),
412
416
  },
413
417
  })
414
418
  .trim();
@@ -426,18 +430,13 @@ export async function buildSystemPrompt(options: BuildSystemPromptOptions = {}):
426
430
  appendSystemPrompt,
427
431
  pluginAppendices,
428
432
  repeatToolDescriptions = false,
429
- skillsSettings,
430
433
  toolNames: providedToolNames,
431
434
  cwd,
432
435
  contextFiles: providedContextFiles,
433
- skills: providedSkills,
434
436
  rules,
435
437
  alwaysApplyRules,
436
438
  intentField,
437
- mcpDiscoveryMode = false,
438
- mcpDiscoveryServerSummaries = [],
439
439
  toolDiscoveryActive = false,
440
- discoverableTools = [],
441
440
  eagerTasks = false,
442
441
  secretsEnabled = false,
443
442
  workspaceTree: providedWorkspaceTree,
@@ -450,7 +449,6 @@ export async function buildSystemPrompt(options: BuildSystemPromptOptions = {}):
450
449
  resolvedAppendPrompt: undefined as string | undefined,
451
450
  systemPromptCustomization: null as string | null,
452
451
  contextFiles: dedupeExactContextFiles(providedContextFiles ?? []),
453
- skills: providedSkills ?? ([] as Skill[]),
454
452
  workspaceTree: {
455
453
  rootPath: resolvedCwd,
456
454
  rendered: "",
@@ -500,14 +498,8 @@ export async function buildSystemPrompt(options: BuildSystemPromptOptions = {}):
500
498
  : logger.time("buildWorkspaceTree", () =>
501
499
  buildWorkspaceTree(resolvedCwd, { timeoutMs: SYSTEM_PROMPT_PREP_TIMEOUT_MS }),
502
500
  );
503
- const skillsPromise: Promise<Skill[]> =
504
- providedSkills !== undefined
505
- ? Promise.resolve(providedSkills)
506
- : skillsSettings?.enabled !== false
507
- ? loadSkills({ ...skillsSettings, cwd: resolvedCwd }).then(result => result.skills)
508
- : Promise.resolve([]);
509
-
510
- const [resolvedCustomPrompt, resolvedAppendPrompt, systemPromptCustomization, contextFiles, , workspaceTree] =
501
+
502
+ const [resolvedCustomPrompt, resolvedAppendPrompt, systemPromptCustomization, contextFiles, workspaceTree] =
511
503
  await Promise.all([
512
504
  withDeadline(
513
505
  "customPrompt",
@@ -527,7 +519,6 @@ export async function buildSystemPrompt(options: BuildSystemPromptOptions = {}):
527
519
  withDeadline("loadProjectContextFiles", contextFilesPromise, prepDefaults.contextFiles).then(
528
520
  dedupeExactContextFiles,
529
521
  ),
530
- withDeadline("loadSkills", skillsPromise, prepDefaults.skills),
531
522
  withDeadline("buildWorkspaceTree", workspaceTreePromise, prepDefaults.workspaceTree),
532
523
  ]);
533
524
  const agentsMdFiles = Array.from(new Set(workspaceTree.agentsMdFiles)).sort().slice(0, AGENTS_MD_LIMIT);
@@ -565,8 +556,8 @@ export async function buildSystemPrompt(options: BuildSystemPromptOptions = {}):
565
556
  // Tools map provided
566
557
  toolNames = Array.from(tools.keys());
567
558
  } else {
568
- // Use defaults
569
- toolNames = ["read", "bash", "eval", "edit", "write"]; // TODO: Why?
559
+ // Use the same essential-tool baseline as a default session.
560
+ toolNames = [...DEFAULT_ESSENTIAL_TOOL_NAMES];
570
561
  }
571
562
  }
572
563
 
@@ -581,10 +572,6 @@ export async function buildSystemPrompt(options: BuildSystemPromptOptions = {}):
581
572
  description: tools?.get(name)?.description ?? "",
582
573
  }));
583
574
 
584
- // Runtime skills are discovered by `skill_discovery` and loaded narrowly through
585
- // `skill`; do not dump the full custom skill catalog into the core prompt.
586
- const filteredSkills: Skill[] = [];
587
-
588
575
  const effectiveSystemPromptCustomization = dedupePromptSource(systemPromptCustomization, [
589
576
  resolvedCustomPrompt,
590
577
  resolvedAppendPrompt,
@@ -593,6 +580,17 @@ export async function buildSystemPrompt(options: BuildSystemPromptOptions = {}):
593
580
  const injectedAlwaysApplyRules = dedupeAlwaysApplyRules(alwaysApplyRules, promptSources);
594
581
 
595
582
  const environment = await logger.time("getEnvironmentInfo", getEnvironmentInfo);
583
+ const sanitizedContextFiles = contextFiles.map(file => ({
584
+ ...file,
585
+ path: escapePromptMetadata(file.path),
586
+ content: sanitizeEmbeddedPromptContent(file.content),
587
+ }));
588
+ const sanitizedAlwaysApplyRules = injectedAlwaysApplyRules.map(rule => ({
589
+ ...rule,
590
+ name: escapePromptMetadata(rule.name),
591
+ path: escapePromptMetadata(rule.path),
592
+ content: sanitizeEmbeddedPromptContent(rule.content),
593
+ }));
596
594
  const data = {
597
595
  systemPromptCustomization: effectiveSystemPromptCustomization,
598
596
  customPrompt: resolvedCustomPrompt,
@@ -602,22 +600,17 @@ export async function buildSystemPrompt(options: BuildSystemPromptOptions = {}):
602
600
  repeatToolDescriptions,
603
601
  toolRefs,
604
602
  environment,
605
- contextFiles,
606
- agentsMdSearch: { files: agentsMdFiles },
603
+ contextFiles: sanitizedContextFiles,
604
+ agentsMdSearch: { files: agentsMdFiles.map(file => escapePromptMetadata(file)) },
607
605
  workspaceTree,
608
- skills: filteredSkills,
609
606
  rules: rules ?? [],
610
- alwaysApplyRules: injectedAlwaysApplyRules,
607
+ alwaysApplyRules: sanitizedAlwaysApplyRules,
611
608
  date,
612
609
  dateTime,
613
610
  cwd: promptCwd,
614
611
  intentTracing: !!intentField,
615
612
  intentField: intentField ?? "",
616
- mcpDiscoveryMode: mcpDiscoveryMode && hasHiddenToolDiscoveryTool,
617
- hasMCPDiscoveryServers: mcpDiscoveryServerSummaries.length > 0,
618
- mcpDiscoveryServerSummaries,
619
613
  toolDiscoveryActive: toolDiscoveryActive && hasHiddenToolDiscoveryTool,
620
- discoverableTools,
621
614
  eagerTasks,
622
615
  secretsEnabled,
623
616
  subagent,
@@ -5,6 +5,8 @@
5
5
  */
6
6
  import { parseFrontmatter, prompt } from "@gajae-code/utils";
7
7
  import { parseAgentFields } from "../discovery/helpers";
8
+ import ralplanPersistenceTemplate from "../prompts/agent-fragments/ralplan-persistence.md" with { type: "text" };
9
+ import restrictedBashTemplate from "../prompts/agent-fragments/restricted-bash.md" with { type: "text" };
8
10
  // Embed agent markdown files at build time
9
11
  import architectMd from "../prompts/agents/architect.md" with { type: "text" };
10
12
  import criticMd from "../prompts/agents/critic.md" with { type: "text" };
@@ -33,8 +35,24 @@ interface EmbeddedAgentDef {
33
35
  template: string;
34
36
  }
35
37
 
38
+ const ULTRAGOAL_RED_TEAM_OPEN = "__GJC_ULTRAGOAL_RED_TEAM_OPEN__";
39
+ const ULTRAGOAL_RED_TEAM_CLOSE = "__GJC_ULTRAGOAL_RED_TEAM_CLOSE__";
40
+
36
41
  function buildAgentContent(def: EmbeddedAgentDef): string {
37
- const body = prompt.render(def.template);
42
+ const restrictedBash = prompt.render(restrictedBashTemplate);
43
+ const ralplanPersistence = prompt.render(ralplanPersistenceTemplate, {
44
+ stage: def.frontmatter?.name ?? def.fileName.replace(/\.md$/, ""),
45
+ });
46
+ const template =
47
+ def.fileName === "executor.md"
48
+ ? def.template
49
+ .replace("{{#if ultragoalRedTeam}}", ULTRAGOAL_RED_TEAM_OPEN)
50
+ .replace("{{/if}}", ULTRAGOAL_RED_TEAM_CLOSE)
51
+ : def.template;
52
+ const body = prompt
53
+ .render(template, { restrictedBash, ralplanPersistence })
54
+ .replace(ULTRAGOAL_RED_TEAM_OPEN, "{{#if ultragoalRedTeam}}")
55
+ .replace(ULTRAGOAL_RED_TEAM_CLOSE, "{{/if}}");
38
56
  if (!def.frontmatter) return body;
39
57
  return prompt.render(agentFrontmatterTemplate, { ...def.frontmatter, body });
40
58
  }
@@ -7,9 +7,16 @@
7
7
  import { createHash } from "node:crypto";
8
8
  import * as fs from "node:fs/promises";
9
9
  import path from "node:path";
10
- import type { AgentEvent, AgentIdentity, AgentTelemetryConfig, ThinkingLevel } from "@gajae-code/agent-core";
10
+ import type {
11
+ AgentEvent,
12
+ AgentIdentity,
13
+ AgentMessage,
14
+ AgentTelemetryConfig,
15
+ ThinkingLevel,
16
+ } from "@gajae-code/agent-core";
11
17
  import { recordHandoff, resolveTelemetry } from "@gajae-code/agent-core";
12
- import type { ServiceTier } from "@gajae-code/ai";
18
+ import { estimateMessageTokensHeuristic } from "@gajae-code/agent-core/compaction";
19
+ import type { Message, Model, ServiceTier } from "@gajae-code/ai";
13
20
  import { type JsonSchemaValidationIssue, validateJsonSchemaValue } from "@gajae-code/ai/utils/schema";
14
21
  import { logger, prompt, untilAborted } from "@gajae-code/utils";
15
22
  import { AsyncJobManager } from "../async";
@@ -26,6 +33,7 @@ import { sessionRoot } from "../gjc-runtime/session-layout";
26
33
  import type { HindsightSessionState } from "../hindsight/state";
27
34
  import type { LocalProtocolOptions } from "../internal-urls";
28
35
  import subagentSystemPromptTemplate from "../prompts/system/subagent-system-prompt.md" with { type: "text" };
36
+ import subagentUserPromptTemplate from "../prompts/system/subagent-user-prompt.md" with { type: "text" };
29
37
  import submitReminderTemplate from "../prompts/system/subagent-yield-reminder.md" with { type: "text" };
30
38
  import { AgentRegistry } from "../registry/agent-registry";
31
39
  import { createAgentSession, discoverAuthStorage } from "../sdk";
@@ -87,6 +95,11 @@ function normalizeModelPatterns(value: string | string[] | undefined): string[]
87
95
  .filter(Boolean);
88
96
  }
89
97
 
98
+ function getSubagentCanonicalScope(parentSessionId: string | undefined, subagentId: string): string | undefined {
99
+ if (!parentSessionId) return undefined;
100
+ return JSON.stringify(["subagent-canonical", parentSessionId, subagentId]);
101
+ }
102
+
90
103
  function renderIrcPeerRoster(agentRegistry: AgentRegistry, selfId: string): string {
91
104
  const peers = agentRegistry
92
105
  .list()
@@ -109,6 +122,51 @@ function getReportFindingKey(value: unknown): string | null {
109
122
  return `${filePath}:${lineStart}:${lineEnd}:${priority ?? ""}:${title}`;
110
123
  }
111
124
 
125
+ const FORK_CONTEXT_MINIMUM_RESERVED_OUTPUT_TOKENS = 4_096;
126
+ const FORK_CONTEXT_FIXED_PROMPT_AND_TOOL_OVERHEAD_TOKENS = 4_096;
127
+
128
+ export function trimForkContextSeedForModel(seed: ForkContextSeed, model: Model | undefined): ForkContextSeed {
129
+ const contextWindow = model?.contextWindow;
130
+ if (!contextWindow || contextWindow <= 0) return seed;
131
+ const reservedOutputTokens = Math.max(
132
+ FORK_CONTEXT_MINIMUM_RESERVED_OUTPUT_TOKENS,
133
+ model && Number.isFinite(model.maxTokens) ? Math.max(0, Math.trunc(model.maxTokens)) : 0,
134
+ );
135
+ const ceiling = Math.max(
136
+ 0,
137
+ Math.trunc(contextWindow) - reservedOutputTokens - FORK_CONTEXT_FIXED_PROMPT_AND_TOOL_OVERHEAD_TOKENS,
138
+ );
139
+ const maxTokens = Math.min(seed.metadata.maxTokens, ceiling);
140
+ const skippedReasons = { ...seed.metadata.skippedReasons };
141
+ let skippedMessages = seed.metadata.skippedMessages;
142
+ let approximateTokens = 0;
143
+ const messages: Message[] = [];
144
+ for (let i = seed.messages.length - 1; i >= 0; i--) {
145
+ const message = seed.messages[i]!;
146
+ const tokens = estimateMessageTokensHeuristic(message);
147
+ if (maxTokens <= 0 || approximateTokens + tokens > maxTokens) {
148
+ skippedMessages++;
149
+ skippedReasons["child-context-ceiling"] = (skippedReasons["child-context-ceiling"] ?? 0) + 1;
150
+ continue;
151
+ }
152
+ messages.unshift(message);
153
+ approximateTokens += tokens;
154
+ }
155
+ return {
156
+ ...seed,
157
+ messages,
158
+ agentMessages: messages.map(message => structuredClone(message) as AgentMessage),
159
+ metadata: {
160
+ ...seed.metadata,
161
+ includedMessages: messages.length,
162
+ skippedMessages,
163
+ approximateTokens,
164
+ maxTokens,
165
+ skippedReasons,
166
+ },
167
+ };
168
+ }
169
+
112
170
  /** Options for subagent execution */
113
171
  export interface ExecutorOptions {
114
172
  cwd: string;
@@ -184,6 +242,10 @@ export interface ExecutorOptions {
184
242
  forkContextSeed?: ForkContextSeed;
185
243
  }
186
244
 
245
+ export function renderSubagentUserPrompt(assignment: string, independentMode: boolean): string {
246
+ return prompt.render(subagentUserPromptTemplate, { assignment: assignment.trim(), independentMode });
247
+ }
248
+
187
249
  function parseStringifiedJson(value: unknown): unknown {
188
250
  if (typeof value !== "string") return value;
189
251
  const trimmed = value.trim();
@@ -1232,6 +1294,8 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
1232
1294
  }
1233
1295
  checkAbort();
1234
1296
 
1297
+ const canonicalChildScope = getSubagentCanonicalScope(options.parentSessionId, options.subagentId ?? id);
1298
+
1235
1299
  const {
1236
1300
  model,
1237
1301
  thinkingLevel: resolvedThinkingLevel,
@@ -1250,6 +1314,7 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
1250
1314
  settings,
1251
1315
  options.parentSessionId,
1252
1316
  { managedFallback: true },
1317
+ canonicalChildScope,
1253
1318
  ),
1254
1319
  );
1255
1320
  if (model) {
@@ -1281,6 +1346,9 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
1281
1346
  if (model?.contextWindow && model.contextWindow > 0) {
1282
1347
  progress.contextWindow = model.contextWindow;
1283
1348
  }
1349
+ const forkContextSeed = options.forkContextSeed
1350
+ ? trimForkContextSeedForModel(options.forkContextSeed, model)
1351
+ : undefined;
1284
1352
  const effectiveThinkingLevel = explicitThinkingLevel
1285
1353
  ? resolvedThinkingLevel
1286
1354
  : (thinkingLevel ?? resolvedThinkingLevel);
@@ -1354,8 +1422,8 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
1354
1422
  const { normalized: normalizedOutputSchema } = normalizeSchema(outputSchema);
1355
1423
 
1356
1424
  const forkContextNotice =
1357
- options.forkContextSeed && options.forkContextSeed.metadata.includedMessages > 0
1358
- ? `This subagent was started with a forked snapshot of the parent conversation. Included ${options.forkContextSeed.metadata.includedMessages} message(s), skipped ${options.forkContextSeed.metadata.skippedMessages}, approximately ${options.forkContextSeed.metadata.approximateTokens} tokens. The snapshot is not live.${ircEnabled ? " Use IRC for live coordination." : " Rely on the explicit assignment and supplied context for coordination."}`
1425
+ forkContextSeed && forkContextSeed.metadata.includedMessages > 0
1426
+ ? `This subagent was started with a forked snapshot of the parent conversation. Included ${forkContextSeed.metadata.includedMessages} message(s), skipped ${forkContextSeed.metadata.skippedMessages}, approximately ${forkContextSeed.metadata.approximateTokens} tokens. The snapshot is not live.${ircEnabled ? " Use IRC for live coordination." : " Rely on the explicit assignment and supplied context for coordination."}`
1359
1427
  : "";
1360
1428
 
1361
1429
  const agentSubskillBlock = await buildAgentSubskillInjection({
@@ -1392,7 +1460,11 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
1392
1460
  workspaceTree: options.workspaceTree,
1393
1461
  systemPrompt: defaultPrompt => {
1394
1462
  const subagentPrompt = prompt.render(subagentSystemPromptTemplate, {
1395
- agent: agent.systemPrompt,
1463
+ agent: prompt.render(agent.systemPrompt, {
1464
+ ultragoalRedTeam: /ultragoal\s+completion\s+(?:qa|red-team)|executorQa/i.test(
1465
+ options.assignment ?? task,
1466
+ ),
1467
+ }),
1396
1468
  context: options.context?.trim() ?? "",
1397
1469
  worktree: worktree ?? "",
1398
1470
  outputSchema: normalizedOutputSchema,
@@ -1433,7 +1505,7 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
1433
1505
  enableMCP,
1434
1506
  localProtocolOptions: options.localProtocolOptions,
1435
1507
  telemetry: subagentTelemetry,
1436
- forkContextSeed: options.forkContextSeed,
1508
+ forkContextSeed,
1437
1509
  agentRegistry,
1438
1510
  shouldPause: () => pauseRequested,
1439
1511
  }),
@@ -1549,6 +1621,12 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
1549
1621
  },
1550
1622
  getActiveTools: () => session.getActiveToolNames(),
1551
1623
  getAllTools: () => session.getAllToolNames(),
1624
+ resolveTool: name => {
1625
+ const tool = session.getToolByName(name);
1626
+ return tool
1627
+ ? { safeSummary: tool.safeSummary, safeSummaryFields: tool.safeSummaryFields }
1628
+ : undefined;
1629
+ },
1552
1630
  setActiveTools: (toolNames: string[]) =>
1553
1631
  session.setActiveToolsByName(toolNames.filter(name => !parentOwnedToolNames.has(name))),
1554
1632
  getCommands: () => getSessionSlashCommands(session),
@@ -1583,6 +1661,12 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
1583
1661
  getQueuedMessages: () => session.getQueuedMessageEntries(),
1584
1662
  getActiveTools: () => session.getActiveToolNames(),
1585
1663
  getAllTools: () => session.getAllToolNames(),
1664
+ resolveTool: name => {
1665
+ const tool = session.getToolByName(name);
1666
+ return tool
1667
+ ? { safeSummary: tool.safeSummary, safeSummaryFields: tool.safeSummaryFields }
1668
+ : undefined;
1669
+ },
1586
1670
  shutdown: () => {},
1587
1671
  getContextUsage: () => session.getContextUsage(),
1588
1672
  getSystemPrompt: () => session.systemPrompt,
package/src/task/index.ts CHANGED
@@ -23,7 +23,6 @@ import { AsyncJobManager, OwnerSubagentShutdownError, type ResumeRunner } from "
23
23
  import { resolveAgentModelPatterns } from "../config/model-resolver";
24
24
  import type { Theme } from "../modes/theme/theme";
25
25
  import planModeSubagentPrompt from "../prompts/system/plan-mode-subagent.md" with { type: "text" };
26
- import subagentUserPromptTemplate from "../prompts/system/subagent-user-prompt.md" with { type: "text" };
27
26
  import taskDescriptionTemplate from "../prompts/tools/task.md" with { type: "text" };
28
27
  import taskSummaryTemplate from "../prompts/tools/task-summary.md" with { type: "text" };
29
28
  import type { ForkContextSeed } from "../session/agent-session";
@@ -48,7 +47,7 @@ import type { LocalProtocolOptions } from "../internal-urls";
48
47
  import { generateCommitMessage } from "../utils/commit-message-generator";
49
48
  import * as git from "../utils/git";
50
49
  import { discoverAgents, filterVisibleAgents, getAgent } from "./discovery";
51
- import { runSubprocess } from "./executor";
50
+ import { renderSubagentUserPrompt, runSubprocess } from "./executor";
52
51
  import { adviseForkContextMode } from "./fork-context-advisory";
53
52
  import { FORK_CONTEXT_TOKEN_BUDGET_BY_MODE } from "./fork-context-budget";
54
53
  import { getTaskIdValidationError, validateAllocatedTaskId } from "./id";
@@ -87,11 +86,8 @@ interface TaskResumeDescriptor {
87
86
  function isTaskResumeDescriptor(value: unknown): value is TaskResumeDescriptor {
88
87
  return typeof value === "object" && value !== null && "task" in value && "params" in value;
89
88
  }
90
- function renderSubagentUserPrompt(assignment: string, simpleMode: TaskSimpleMode): string {
91
- return prompt.render(subagentUserPromptTemplate, {
92
- assignment: assignment.trim(),
93
- independentMode: simpleMode === "independent",
94
- });
89
+ function renderTaskAssignment(assignment: string, simpleMode: TaskSimpleMode): string {
90
+ return renderSubagentUserPrompt(assignment, simpleMode === "independent");
95
91
  }
96
92
  function createUsageTotals(): Usage {
97
93
  return {
@@ -293,23 +289,30 @@ function requestsForkContext(
293
289
  return FORK_CONTEXT_REQUEST_MODE_SET.has(task.inheritContext);
294
290
  }
295
291
 
292
+ function normalizeForkContextCap(value: number | undefined, fallback: number, maximum: number): number {
293
+ if (value === undefined || !Number.isFinite(value) || value <= 0) return fallback;
294
+ return Math.min(maximum, Math.max(1, Math.trunc(value)));
295
+ }
296
+
296
297
  function resolveForkSeedParamsForMode(
297
298
  mode: ForkContextMode,
298
299
  configuredMaxMessages: number | undefined,
299
300
  configuredMaxTokens: number,
300
301
  model: Model | undefined,
301
- ): { maxMessages: number; maxTokens: number } | undefined {
302
+ ): { maxMessages: number; maxTokens: number; preserveLatestUser?: boolean } | undefined {
302
303
  const capMessages = (defaultMaxMessages: number): number =>
303
- configuredMaxMessages === undefined
304
- ? defaultMaxMessages
305
- : Math.min(defaultMaxMessages, Math.max(0, Math.trunc(configuredMaxMessages)));
304
+ normalizeForkContextCap(configuredMaxMessages, defaultMaxMessages, defaultMaxMessages);
306
305
  switch (mode) {
307
306
  case "none":
308
307
  return undefined;
309
308
  case "receipt":
310
309
  return { maxMessages: 1, maxTokens: FORK_CONTEXT_TOKEN_BUDGET_BY_MODE.receipt };
311
310
  case "last-turn":
312
- return { maxMessages: 2, maxTokens: FORK_CONTEXT_TOKEN_BUDGET_BY_MODE["last-turn"] };
311
+ return {
312
+ maxMessages: 2,
313
+ maxTokens: FORK_CONTEXT_TOKEN_BUDGET_BY_MODE["last-turn"],
314
+ preserveLatestUser: true,
315
+ };
313
316
  case "bounded":
314
317
  return { maxMessages: capMessages(50), maxTokens: FORK_CONTEXT_TOKEN_BUDGET_BY_MODE.bounded };
315
318
  case "full":
@@ -343,9 +346,12 @@ function validateForkContextRequests(
343
346
  }
344
347
 
345
348
  export function resolveForkContextMaxTokens(configured: number, model: Model | undefined): number {
346
- if (configured > 0) return Math.trunc(configured);
347
- const contextWindow = model?.contextWindow ?? 0;
348
- return contextWindow > 0 ? Math.max(1, Math.floor(contextWindow * 0.15)) : 15_000;
349
+ const contextWindow = model?.contextWindow;
350
+ const fallback =
351
+ contextWindow && Number.isFinite(contextWindow) && contextWindow > 0
352
+ ? Math.max(1, Math.floor(contextWindow * 0.15))
353
+ : 15_000;
354
+ return normalizeForkContextCap(configured, fallback, Number.MAX_SAFE_INTEGER);
349
355
  }
350
356
 
351
357
  // ═══════════════════════════════════════════════════════════════════════════
@@ -507,7 +513,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
507
513
  agent: params.agent,
508
514
  agentSource: fallbackAgentSource,
509
515
  status: "pending",
510
- task: renderSubagentUserPrompt(assignment, simpleMode),
516
+ task: renderTaskAssignment(assignment, simpleMode),
511
517
  assignment,
512
518
  description: taskItem.description,
513
519
  recentTools: [],
@@ -633,6 +639,15 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
633
639
 
634
640
  const uniqueId = validateAllocatedTaskId(uniqueIds[i] ?? "");
635
641
  const frozenForkSeed = await buildForkContextSeedForTask(taskItem);
642
+ if (signal?.aborted) {
643
+ for (let skippedIndex = i; skippedIndex < taskItems.length; skippedIndex++) {
644
+ const skippedTask = taskItems[skippedIndex]!;
645
+ failedSchedules.push(`${skippedTask.id}: cancelled before scheduling`);
646
+ const skippedProgress = progressByTaskId.get(skippedTask.id);
647
+ if (skippedProgress) skippedProgress.status = "aborted";
648
+ }
649
+ break;
650
+ }
636
651
  if (frozenForkSeed) frozenForkSeeds.set(uniqueId, frozenForkSeed);
637
652
  const singleParams: TaskParams = { ...params, tasks: [taskItem] };
638
653
  const label = uniqueId;
@@ -1232,7 +1247,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
1232
1247
  agent: agentName,
1233
1248
  agentSource: agent.source,
1234
1249
  status: "pending",
1235
- task: renderSubagentUserPrompt(assignment, simpleMode),
1250
+ task: renderTaskAssignment(assignment, simpleMode),
1236
1251
  assignment,
1237
1252
  recentTools: [],
1238
1253
  recentOutput: [],
@@ -1297,7 +1312,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
1297
1312
  const result = await runSubprocess({
1298
1313
  cwd: this.session.cwd,
1299
1314
  agent: effectiveAgent,
1300
- task: renderSubagentUserPrompt(task.assignment, simpleMode),
1315
+ task: renderTaskAssignment(task.assignment, simpleMode),
1301
1316
  assignment: task.assignment.trim(),
1302
1317
  context: sharedContext,
1303
1318
  description: task.description,
@@ -1361,7 +1376,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
1361
1376
  cwd: this.session.cwd,
1362
1377
  worktree: isolationDir,
1363
1378
  agent: effectiveAgent,
1364
- task: renderSubagentUserPrompt(task.assignment, simpleMode),
1379
+ task: renderTaskAssignment(task.assignment, simpleMode),
1365
1380
  assignment: task.assignment.trim(),
1366
1381
  context: sharedContext,
1367
1382
  description: task.description,
@@ -1474,7 +1489,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
1474
1489
  id: task.id,
1475
1490
  agent: agent.name,
1476
1491
  agentSource: agent.source,
1477
- task: renderSubagentUserPrompt(assignment, simpleMode),
1492
+ task: renderTaskAssignment(assignment, simpleMode),
1478
1493
  assignment,
1479
1494
  description: task.description,
1480
1495
  exitCode: 1,
@@ -1514,7 +1529,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
1514
1529
  id: task.id,
1515
1530
  agent: agentName,
1516
1531
  agentSource: agent.source,
1517
- task: renderSubagentUserPrompt(assignment, simpleMode),
1532
+ task: renderTaskAssignment(assignment, simpleMode),
1518
1533
  assignment,
1519
1534
  description: task.description,
1520
1535
  exitCode: 1,
package/src/thinking.ts CHANGED
@@ -57,17 +57,32 @@ export function clampExplicitThinkingLevelForModel(
57
57
  return clampThinkingLevelForModel(model, level);
58
58
  }
59
59
 
60
+ export interface SelectorThinkingSuffix {
61
+ selector: string;
62
+ thinkingLevel?: ThinkingLevel;
63
+ invalidSuffix?: string;
64
+ }
65
+
66
+ /** Split the final selector suffix once, preserving colons in model IDs. */
67
+ export function splitSelectorThinkingSuffix(selector: string): SelectorThinkingSuffix {
68
+ const colonIndex = selector.lastIndexOf(":");
69
+ if (colonIndex === -1) return { selector };
70
+
71
+ const suffix = selector.slice(colonIndex + 1);
72
+ const thinkingLevel = parseThinkingLevel(suffix);
73
+ return thinkingLevel
74
+ ? { selector: selector.slice(0, colonIndex), thinkingLevel }
75
+ : { selector: selector.slice(0, colonIndex), invalidSuffix: suffix };
76
+ }
77
+
60
78
  export function formatClampedModelSelector(selector: string, model: Model | undefined): string {
61
79
  const slashIdx = selector.indexOf("/");
62
80
  if (slashIdx <= 0) return selector;
63
81
  const id = selector.slice(slashIdx + 1);
64
- const colonIdx = id.lastIndexOf(":");
65
- if (colonIdx === -1) return selector;
66
- const suffix = id.slice(colonIdx + 1);
67
- const thinkingLevel = parseThinkingLevel(suffix);
82
+ const { selector: baseId, thinkingLevel } = splitSelectorThinkingSuffix(id);
68
83
  if (!thinkingLevel) return selector;
69
84
  const clamped = clampExplicitThinkingLevelForModel(model, thinkingLevel);
70
85
  return clamped && clamped !== ThinkingLevel.Inherit
71
- ? `${selector.slice(0, slashIdx + 1)}${id.slice(0, colonIdx)}:${clamped}`
72
- : selector.slice(0, slashIdx + 1) + id.slice(0, colonIdx);
86
+ ? `${selector.slice(0, slashIdx + 1)}${baseId}:${clamped}`
87
+ : selector.slice(0, slashIdx + 1) + baseId;
73
88
  }