@gajae-code/coding-agent 0.11.0 → 0.11.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (418) hide show
  1. package/CHANGELOG.md +63 -1
  2. package/dist/types/async/job-manager.d.ts +46 -7
  3. package/dist/types/cli/config-cli.d.ts +11 -1
  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 +56 -1
  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-receipt-freshness.d.ts +11 -0
  54. package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +55 -33
  55. package/dist/types/gjc-runtime/workflow-cli-common.d.ts +8 -0
  56. package/dist/types/gjc-runtime/workflow-manifest.d.ts +3 -0
  57. package/dist/types/goals/continuation-timeout-guard.d.ts +22 -0
  58. package/dist/types/goals/runtime.d.ts +1 -0
  59. package/dist/types/goals/state.d.ts +8 -0
  60. package/dist/types/harness-control-plane/lifecycle-reconciliation.d.ts +17 -0
  61. package/dist/types/harness-control-plane/phase-rollup.d.ts +4 -7
  62. package/dist/types/harness-control-plane/receipt-ingest.d.ts +5 -0
  63. package/dist/types/harness-control-plane/receipt-spool.d.ts +4 -0
  64. package/dist/types/hindsight/state.d.ts +11 -4
  65. package/dist/types/lsp/lspmux.d.ts +5 -3
  66. package/dist/types/lsp/path-trust.d.ts +1 -0
  67. package/dist/types/main.d.ts +3 -2
  68. package/dist/types/memories/storage.d.ts +1 -0
  69. package/dist/types/modes/action-registry.d.ts +29 -0
  70. package/dist/types/modes/components/chrome.d.ts +14 -0
  71. package/dist/types/modes/components/command-palette.d.ts +27 -0
  72. package/dist/types/modes/components/custom-provider-wizard.d.ts +1 -0
  73. package/dist/types/modes/components/index.d.ts +2 -1
  74. package/dist/types/modes/components/pet-selector.d.ts +1 -1
  75. package/dist/types/modes/components/plan-preview-overlay.d.ts +43 -0
  76. package/dist/types/modes/components/queue-mode-selector.d.ts +1 -1
  77. package/dist/types/modes/components/queue-pane.d.ts +12 -0
  78. package/dist/types/modes/components/read-tool-group.d.ts +6 -0
  79. package/dist/types/modes/components/session-observer-overlay.d.ts +3 -4
  80. package/dist/types/modes/components/sessions-dashboard.d.ts +32 -0
  81. package/dist/types/modes/components/settings-selector.d.ts +1 -1
  82. package/dist/types/modes/components/show-images-selector.d.ts +1 -1
  83. package/dist/types/modes/components/status-line/types.d.ts +1 -1
  84. package/dist/types/modes/components/status-line.d.ts +1 -94
  85. package/dist/types/modes/components/tasks-pane.d.ts +15 -0
  86. package/dist/types/modes/components/theme-selector.d.ts +1 -1
  87. package/dist/types/modes/components/tool-execution.d.ts +15 -0
  88. package/dist/types/modes/components/tool-status-header.d.ts +111 -0
  89. package/dist/types/modes/components/transcript-viewer-overlay.d.ts +42 -0
  90. package/dist/types/modes/controllers/command-controller.d.ts +2 -2
  91. package/dist/types/modes/controllers/extension-ui-controller.d.ts +1 -0
  92. package/dist/types/modes/controllers/goal-mode-controller.d.ts +62 -0
  93. package/dist/types/modes/controllers/input-controller.d.ts +8 -1
  94. package/dist/types/modes/controllers/mode-gate.d.ts +8 -0
  95. package/dist/types/modes/controllers/plan-mode-controller.d.ts +65 -0
  96. package/dist/types/modes/controllers/selector-controller.d.ts +15 -3
  97. package/dist/types/modes/controllers/stt-controller.d.ts +26 -0
  98. package/dist/types/modes/interactive-mode.d.ts +21 -19
  99. package/dist/types/modes/jobs-observer.d.ts +2 -0
  100. package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +4 -11
  101. package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +21 -2
  102. package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +31 -0
  103. package/dist/types/modes/tasks-aggregator.d.ts +39 -0
  104. package/dist/types/modes/transcript-item-registry.d.ts +60 -0
  105. package/dist/types/modes/types.d.ts +22 -15
  106. package/dist/types/modes/utils/ui-helpers.d.ts +2 -2
  107. package/dist/types/runtime-mcp/manager.d.ts +1 -1
  108. package/dist/types/sdk/broker/broker.d.ts +78 -12
  109. package/dist/types/sdk/broker/ensure.d.ts +9 -0
  110. package/dist/types/sdk/broker/lifecycle-codec.d.ts +4 -0
  111. package/dist/types/sdk/broker/lifecycle-ledger.d.ts +15 -1
  112. package/dist/types/sdk/broker/lifecycle.d.ts +6 -2
  113. package/dist/types/sdk/broker/process-incarnation.d.ts +2 -0
  114. package/dist/types/sdk/broker/session-index.d.ts +0 -1
  115. package/dist/types/sdk/broker/state-version.d.ts +2 -0
  116. package/dist/types/sdk/bus/chat-effect-journal.d.ts +1 -0
  117. package/dist/types/sdk/bus/config-commands.d.ts +1 -1
  118. package/dist/types/sdk/bus/config.d.ts +11 -0
  119. package/dist/types/sdk/bus/daemon-paths.d.ts +1 -0
  120. package/dist/types/sdk/bus/discord-daemon.d.ts +5 -0
  121. package/dist/types/sdk/bus/html-format.d.ts +3 -2
  122. package/dist/types/sdk/bus/index.d.ts +27 -0
  123. package/dist/types/sdk/bus/lifecycle-control-runtime.d.ts +4 -0
  124. package/dist/types/sdk/bus/notification-service.d.ts +20 -0
  125. package/dist/types/sdk/bus/rate-limit-pool.d.ts +13 -2
  126. package/dist/types/sdk/bus/recent-activity.d.ts +21 -12
  127. package/dist/types/sdk/bus/rich-document.d.ts +7 -0
  128. package/dist/types/sdk/bus/rich-render.d.ts +18 -41
  129. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +9 -4
  130. package/dist/types/sdk/bus/telegram-daemon.d.ts +69 -3
  131. package/dist/types/sdk/bus/threaded-inbound.d.ts +1 -1
  132. package/dist/types/sdk/bus/threaded-render.d.ts +13 -0
  133. package/dist/types/sdk/bus/topic-registry.d.ts +24 -2
  134. package/dist/types/sdk/host/control/operations.d.ts +1 -1
  135. package/dist/types/sdk/host/host.d.ts +2 -0
  136. package/dist/types/sdk/index.d.ts +1 -0
  137. package/dist/types/sdk/session-directory.d.ts +56 -0
  138. package/dist/types/session/agent-session.d.ts +82 -47
  139. package/dist/types/session/agent-storage.d.ts +7 -0
  140. package/dist/types/session/fallback-chain-controller.d.ts +10 -2
  141. package/dist/types/session/internal/managed-session-scope.d.ts +102 -0
  142. package/dist/types/session/internal/managed-session-storage.d.ts +38 -0
  143. package/dist/types/session/messages.d.ts +16 -0
  144. package/dist/types/session/session-manager-internal.d.ts +14 -0
  145. package/dist/types/session/session-manager.d.ts +82 -12
  146. package/dist/types/session/session-storage.d.ts +43 -3
  147. package/dist/types/session/volatile-context-pruning.d.ts +15 -0
  148. package/dist/types/skill-state/{deep-interview-mutation-guard.d.ts → workflow-mutation-guard.d.ts} +24 -8
  149. package/dist/types/skill-state/workflow-state-contract.d.ts +1 -3
  150. package/dist/types/slash-commands/builtin-registry.d.ts +4 -1
  151. package/dist/types/system-prompt.d.ts +2 -11
  152. package/dist/types/task/executor.d.ts +3 -1
  153. package/dist/types/thinking.d.ts +7 -0
  154. package/dist/types/tool-discovery/tool-index.d.ts +1 -50
  155. package/dist/types/tools/ask.d.ts +64 -2
  156. package/dist/types/tools/bash.d.ts +3 -0
  157. package/dist/types/tools/browser/dead-tab-recovery.d.ts +24 -0
  158. package/dist/types/tools/browser/tab-supervisor.d.ts +21 -0
  159. package/dist/types/tools/cron.d.ts +2 -0
  160. package/dist/types/tools/fetch.d.ts +1 -0
  161. package/dist/types/tools/index.d.ts +30 -15
  162. package/dist/types/tools/output-meta.d.ts +1 -0
  163. package/dist/types/tools/read.d.ts +3 -0
  164. package/dist/types/tools/search-tool-bm25.d.ts +3 -4
  165. package/dist/types/tools/subagent-render.d.ts +1 -0
  166. package/dist/types/tools/subagent.d.ts +6 -1
  167. package/dist/types/utils/event-bus.d.ts +1 -1
  168. package/dist/types/web/search/index.d.ts +3 -1
  169. package/package.json +21 -9
  170. package/scripts/build-sdk-package-smoke.ts +39 -1
  171. package/scripts/generate-hotkeys-docs.ts +74 -0
  172. package/scripts/generate-sdk-operation-inventory.ts +64 -20
  173. package/scripts/verify-gjc-sdk-canonicalization.ts +182 -2
  174. package/src/async/job-manager.ts +455 -69
  175. package/src/cli/config-cli.ts +75 -2
  176. package/src/cli/notify-cli.ts +92 -26
  177. package/src/cli/session-picker.ts +20 -3
  178. package/src/cli/setup-cli.ts +1 -1
  179. package/src/cli.ts +1 -1
  180. package/src/commands/config.ts +1 -1
  181. package/src/commands/harness.ts +34 -106
  182. package/src/commands/launch.ts +6 -4
  183. package/src/commands/mcp-serve.ts +85 -8
  184. package/src/commands/mcp.ts +2 -2
  185. package/src/commands/notify.ts +8 -4
  186. package/src/commands/sdk.ts +61 -40
  187. package/src/commands/ultragoal.ts +4 -1
  188. package/src/config/atomic-yaml-patch.ts +80 -13
  189. package/src/config/file-lock.ts +105 -43
  190. package/src/config/keybindings.ts +64 -20
  191. package/src/config/model-auth.ts +9 -0
  192. package/src/config/model-bindings-applier.ts +139 -0
  193. package/src/config/model-discovery-manager.ts +224 -0
  194. package/src/config/model-equivalence.ts +66 -0
  195. package/src/config/model-registry.ts +169 -302
  196. package/src/config/model-resolver.ts +361 -369
  197. package/src/config/models-config-schema.ts +5 -4
  198. package/src/config/settings-schema.ts +159 -2
  199. package/src/config/settings.ts +458 -482
  200. package/src/coordinator-mcp/policy.ts +76 -11
  201. package/src/coordinator-mcp/question-gate-codec.ts +274 -0
  202. package/src/coordinator-mcp/question-state.ts +778 -0
  203. package/src/coordinator-mcp/server.ts +1702 -238
  204. package/src/debug/index.ts +1 -1
  205. package/src/defaults/gjc/skills/deep-interview/SKILL.md +13 -1
  206. package/src/defaults/gjc/skills/team/SKILL.md +16 -0
  207. package/src/discovery/helpers.ts +1 -50
  208. package/src/edit/index.ts +64 -0
  209. package/src/eval/py/env.ts +26 -0
  210. package/src/eval/py/kernel.ts +5 -3
  211. package/src/extensibility/extensions/loader.ts +9 -1
  212. package/src/extensibility/extensions/runner.ts +12 -3
  213. package/src/extensibility/extensions/types.ts +39 -1
  214. package/src/extensibility/gjc-plugins/installer.ts +16 -16
  215. package/src/extensibility/hooks/runner.ts +2 -2
  216. package/src/extensibility/runtime-skill-discovery.ts +33 -13
  217. package/src/extensibility/shared-events.ts +2 -0
  218. package/src/gjc-runtime/deep-interview-recorder.ts +63 -3
  219. package/src/gjc-runtime/deep-interview-runtime.ts +76 -27
  220. package/src/gjc-runtime/deep-interview-state.ts +317 -5
  221. package/src/gjc-runtime/goal-mode-request.ts +55 -8
  222. package/src/gjc-runtime/launch-tmux.ts +2 -5
  223. package/src/gjc-runtime/launch-worktree.ts +5 -5
  224. package/src/gjc-runtime/linux-proc.ts +71 -0
  225. package/src/gjc-runtime/ralplan-runtime.ts +74 -90
  226. package/src/gjc-runtime/session-resolution.ts +18 -3
  227. package/src/gjc-runtime/session-state-sidecar.ts +6 -107
  228. package/src/gjc-runtime/state-migrations.ts +1 -1
  229. package/src/gjc-runtime/state-runtime.ts +320 -249
  230. package/src/gjc-runtime/state-writer.ts +36 -40
  231. package/src/gjc-runtime/team-launch.ts +319 -0
  232. package/src/gjc-runtime/team-notify.ts +326 -0
  233. package/src/gjc-runtime/team-runtime.ts +1099 -1482
  234. package/src/gjc-runtime/team-store.ts +828 -0
  235. package/src/gjc-runtime/team-workers.ts +962 -0
  236. package/src/gjc-runtime/tmux-owner-isolation-cli.ts +2 -11
  237. package/src/gjc-runtime/tmux-owner-isolation.ts +14 -9
  238. package/src/gjc-runtime/tmux-sessions.ts +4 -21
  239. package/src/gjc-runtime/ultragoal-change-set.ts +172 -0
  240. package/src/gjc-runtime/ultragoal-evidence.ts +874 -0
  241. package/src/gjc-runtime/ultragoal-guard.ts +83 -12
  242. package/src/gjc-runtime/ultragoal-pipeline.ts +306 -0
  243. package/src/gjc-runtime/ultragoal-receipt-freshness.ts +102 -1
  244. package/src/gjc-runtime/ultragoal-runtime.ts +156 -1319
  245. package/src/gjc-runtime/workflow-cli-common.ts +30 -0
  246. package/src/gjc-runtime/workflow-manifest.generated.json +58 -0
  247. package/src/gjc-runtime/workflow-manifest.ts +18 -0
  248. package/src/goals/continuation-timeout-guard.ts +79 -0
  249. package/src/goals/runtime.ts +7 -5
  250. package/src/goals/state.ts +18 -0
  251. package/src/harness-control-plane/lifecycle-reconciliation.ts +64 -0
  252. package/src/harness-control-plane/phase-rollup.ts +4 -7
  253. package/src/harness-control-plane/receipt-ingest.ts +5 -0
  254. package/src/harness-control-plane/receipt-spool.ts +51 -7
  255. package/src/harness-control-plane/session-lease.ts +12 -130
  256. package/src/hindsight/backend.ts +26 -27
  257. package/src/hindsight/state.ts +101 -32
  258. package/src/hooks/skill-state.ts +17 -11
  259. package/src/internal-urls/docs-index.generated.ts +21 -18
  260. package/src/lsp/client.ts +1 -1
  261. package/src/lsp/config.ts +145 -26
  262. package/src/lsp/index.ts +1 -1
  263. package/src/lsp/lspmux.ts +39 -10
  264. package/src/lsp/path-trust.ts +81 -0
  265. package/src/main.ts +28 -8
  266. package/src/memories/index.ts +1 -0
  267. package/src/memories/storage.ts +6 -2
  268. package/src/modes/action-registry.ts +165 -0
  269. package/src/modes/components/chrome.ts +40 -0
  270. package/src/modes/components/command-palette.ts +168 -0
  271. package/src/modes/components/custom-editor.ts +1 -1
  272. package/src/modes/components/custom-provider-wizard.ts +51 -14
  273. package/src/modes/components/index.ts +2 -1
  274. package/src/modes/components/pet-selector.ts +11 -17
  275. package/src/modes/components/plan-preview-overlay.ts +295 -0
  276. package/src/modes/components/queue-mode-selector.ts +10 -27
  277. package/src/modes/components/queue-pane.ts +79 -0
  278. package/src/modes/components/read-tool-group.ts +13 -0
  279. package/src/modes/components/session-observer-overlay.ts +207 -772
  280. package/src/modes/components/sessions-dashboard.ts +181 -0
  281. package/src/modes/components/settings-selector.ts +1 -1
  282. package/src/modes/components/show-images-selector.ts +10 -24
  283. package/src/modes/components/status-line/types.ts +1 -1
  284. package/src/modes/components/status-line.ts +1 -969
  285. package/src/modes/components/tasks-pane.ts +73 -0
  286. package/src/modes/components/theme-selector.ts +11 -31
  287. package/src/modes/components/tool-execution.ts +22 -0
  288. package/src/modes/components/tool-status-header.ts +1056 -0
  289. package/src/modes/components/transcript-viewer-overlay.ts +384 -0
  290. package/src/modes/controllers/btw-controller.ts +1 -0
  291. package/src/modes/controllers/command-controller.ts +9 -15
  292. package/src/modes/controllers/event-controller.ts +3 -2
  293. package/src/modes/controllers/extension-ui-controller.ts +72 -25
  294. package/src/modes/controllers/goal-mode-controller.ts +474 -0
  295. package/src/modes/controllers/input-controller.ts +764 -229
  296. package/src/modes/controllers/mode-gate.ts +24 -0
  297. package/src/modes/controllers/plan-mode-controller.ts +517 -0
  298. package/src/modes/controllers/selector-controller.ts +225 -10
  299. package/src/modes/controllers/stt-controller.ts +125 -0
  300. package/src/modes/interactive-mode.ts +302 -1151
  301. package/src/modes/jobs-observer.ts +3 -0
  302. package/src/modes/runtime-init.ts +8 -0
  303. package/src/modes/shared/agent-wire/deep-interview-gate.ts +31 -106
  304. package/src/modes/shared/agent-wire/workflow-gate-broker.ts +78 -19
  305. package/src/modes/shared/agent-wire/workflow-gate-types.ts +177 -0
  306. package/src/modes/tasks-aggregator.ts +199 -0
  307. package/src/modes/transcript-item-registry.ts +229 -0
  308. package/src/modes/types.ts +47 -20
  309. package/src/modes/utils/ui-helpers.ts +17 -9
  310. package/src/prompts/agent-fragments/ralplan-persistence.md +6 -0
  311. package/src/prompts/agent-fragments/restricted-bash.md +1 -0
  312. package/src/prompts/agents/architect.md +2 -8
  313. package/src/prompts/agents/critic.md +2 -8
  314. package/src/prompts/agents/executor.md +3 -0
  315. package/src/prompts/agents/planner.md +4 -12
  316. package/src/prompts/system/custom-system-prompt.md +1 -23
  317. package/src/prompts/system/plan-mode-approved.md +8 -0
  318. package/src/prompts/system/system-prompt.md +17 -96
  319. package/src/prompts/tools/bash.md +4 -4
  320. package/src/prompts/tools/browser.md +15 -52
  321. package/src/prompts/tools/find.md +2 -2
  322. package/src/prompts/tools/hashline.md +13 -55
  323. package/src/prompts/tools/read.md +3 -6
  324. package/src/prompts/tools/search-tool-bm25.md +0 -2
  325. package/src/prompts/tools/search.md +2 -4
  326. package/src/prompts/tools/skill-discovery.md +1 -2
  327. package/src/prompts/tools/task.md +1 -1
  328. package/src/runtime-mcp/manager.ts +1 -1
  329. package/src/sdk/broker/broker.ts +206 -78
  330. package/src/sdk/broker/discovery.ts +21 -2
  331. package/src/sdk/broker/ensure.ts +85 -25
  332. package/src/sdk/broker/lifecycle-codec.ts +11 -0
  333. package/src/sdk/broker/lifecycle-ledger.ts +371 -74
  334. package/src/sdk/broker/lifecycle.ts +1399 -142
  335. package/src/sdk/broker/process-incarnation.ts +5 -13
  336. package/src/sdk/broker/session-index.ts +145 -56
  337. package/src/sdk/broker/state-version.ts +21 -0
  338. package/src/sdk/broker/transport.ts +1 -1
  339. package/src/sdk/bus/chat-daemon-cli.ts +2 -0
  340. package/src/sdk/bus/chat-daemon-control.ts +8 -28
  341. package/src/sdk/bus/chat-effect-journal.ts +14 -4
  342. package/src/sdk/bus/config-commands.ts +5 -4
  343. package/src/sdk/bus/config.ts +98 -0
  344. package/src/sdk/bus/conversation-store.ts +5 -29
  345. package/src/sdk/bus/daemon-paths.ts +2 -0
  346. package/src/sdk/bus/discord-daemon.ts +25 -8
  347. package/src/sdk/bus/html-format.ts +20 -3
  348. package/src/sdk/bus/index.ts +834 -113
  349. package/src/sdk/bus/lifecycle-control-runtime.ts +91 -33
  350. package/src/sdk/bus/native-runtime-compatibility.ts +1 -1
  351. package/src/sdk/bus/natives-augment.d.ts +26 -1
  352. package/src/sdk/bus/notification-service.ts +168 -20
  353. package/src/sdk/bus/rate-limit-pool.ts +58 -14
  354. package/src/sdk/bus/recent-activity.ts +188 -74
  355. package/src/sdk/bus/rich-document.ts +258 -0
  356. package/src/sdk/bus/rich-render.ts +62 -70
  357. package/src/sdk/bus/telegram-daemon-cli.ts +15 -59
  358. package/src/sdk/bus/telegram-daemon-contract.ts +9 -4
  359. package/src/sdk/bus/telegram-daemon.ts +1491 -247
  360. package/src/sdk/bus/threaded-inbound.ts +8 -3
  361. package/src/sdk/bus/threaded-render.ts +57 -1
  362. package/src/sdk/bus/topic-registry.ts +120 -13
  363. package/src/sdk/host/control/dispatch.ts +14 -2
  364. package/src/sdk/host/control/operations.ts +6 -1
  365. package/src/sdk/host/host.ts +31 -1
  366. package/src/sdk/host/query/handlers.ts +20 -22
  367. package/src/sdk/host/query/revision-store.ts +80 -57
  368. package/src/sdk/index.ts +1 -0
  369. package/src/sdk/protocol/operation-inventory.generated.json +943 -1907
  370. package/src/sdk/session-directory.ts +141 -0
  371. package/src/sdk/session.ts +458 -479
  372. package/src/session/agent-session.ts +1901 -637
  373. package/src/session/agent-storage.ts +18 -0
  374. package/src/session/cache-economics.ts +25 -8
  375. package/src/session/fallback-chain-controller.ts +53 -3
  376. package/src/session/internal/managed-session-scope.ts +2226 -0
  377. package/src/session/internal/managed-session-storage.ts +453 -0
  378. package/src/session/messages.ts +91 -2
  379. package/src/session/session-manager-internal.ts +33 -0
  380. package/src/session/session-manager.ts +1112 -333
  381. package/src/session/session-storage.ts +444 -39
  382. package/src/session/volatile-context-pruning.ts +78 -0
  383. package/src/setup/credential-auto-import.ts +2 -1
  384. package/src/setup/hermes/templates/operator-instructions.v1.md +1 -1
  385. package/src/setup/provider-onboarding.ts +36 -61
  386. package/src/setup/provider-presets.json +5 -0
  387. package/src/skill-state/active-state.ts +3 -13
  388. package/src/skill-state/{deep-interview-mutation-guard.ts → workflow-mutation-guard.ts} +47 -29
  389. package/src/skill-state/workflow-state-contract.ts +6 -41
  390. package/src/slash-commands/builtin-registry.ts +46 -11
  391. package/src/system-prompt.ts +37 -44
  392. package/src/task/agents.ts +19 -1
  393. package/src/task/executor.ts +90 -6
  394. package/src/task/index.ts +62 -37
  395. package/src/thinking.ts +21 -6
  396. package/src/tool-discovery/tool-index.ts +2 -134
  397. package/src/tools/ask.ts +157 -21
  398. package/src/tools/ast-edit.ts +1 -1
  399. package/src/tools/bash.ts +38 -0
  400. package/src/tools/browser/dead-tab-recovery.ts +78 -0
  401. package/src/tools/browser/tab-supervisor.ts +282 -36
  402. package/src/tools/computer.ts +10 -3
  403. package/src/tools/cron.ts +30 -16
  404. package/src/tools/eval.ts +1 -2
  405. package/src/tools/fetch.ts +11 -4
  406. package/src/tools/index.ts +76 -24
  407. package/src/tools/output-meta.ts +13 -5
  408. package/src/tools/read.ts +37 -1
  409. package/src/tools/resource-gc.ts +2 -2
  410. package/src/tools/search-tool-bm25.ts +11 -74
  411. package/src/tools/subagent-render.ts +19 -8
  412. package/src/tools/subagent.ts +84 -32
  413. package/src/utils/event-bus.ts +9 -4
  414. package/src/web/search/index.ts +3 -3
  415. package/dist/types/discovery/plugin-dir-roots.d.ts +0 -15
  416. package/dist/types/runtime-mcp/discoverable-tool-metadata.d.ts +0 -7
  417. package/src/discovery/plugin-dir-roots.ts +0 -28
  418. package/src/runtime-mcp/discoverable-tool-metadata.ts +0 -25
@@ -1,9 +1,10 @@
1
1
  import type { AgentTelemetryConfig, AgentTool } from "@gajae-code/agent-core";
2
2
  import type { Model, ServiceTier, ToolChoice } from "@gajae-code/ai";
3
- import { $env, $flag, logger } from "@gajae-code/utils";
3
+ import { $env, logger } from "@gajae-code/utils";
4
4
  import type { PromptTemplate } from "../config/prompt-templates";
5
5
  import type { Settings } from "../config/settings";
6
6
  import { EditTool } from "../edit";
7
+ import { isTruthyPythonFlag } from "../eval/py/env";
7
8
  import { checkPythonKernelAvailability } from "../eval/py/kernel";
8
9
  import type { Skill } from "../extensibility/skills";
9
10
  import type { GoalModeState, GoalRuntime } from "../goals";
@@ -114,7 +115,6 @@ export type ContextFileEntry = {
114
115
  depth?: number;
115
116
  };
116
117
 
117
- export type { DiscoverableMCPTool } from "../runtime-mcp/discoverable-tool-metadata";
118
118
  export type {
119
119
  DiscoverableTool,
120
120
  DiscoverableToolSearchIndex,
@@ -278,6 +278,8 @@ export interface ToolSession {
278
278
  bashRestrictionProfile?: BashRestrictionProfile;
279
279
  /** Optional per-session allowlist for tools exposed through search_tool_bm25. */
280
280
  discoverableToolAllowedNames?: readonly string[];
281
+ /** Throw instead of warn when toolNames contains an unknown name. */
282
+ strictToolNames?: boolean;
281
283
  /** Get artifacts directory for artifact:// URLs */
282
284
  getArtifactsDir?: () => string | null;
283
285
  /** Get the ArtifactManager backing this session (shared across parent + subagents). */
@@ -326,18 +328,6 @@ export interface ToolSession {
326
328
  getTodoPhases?: () => TodoPhase[];
327
329
  /** Replace cached todo phases for this session. */
328
330
  setTodoPhases?: (phases: TodoPhase[]) => void;
329
- /** Whether MCP tool discovery is active for this session. */
330
- isMCPDiscoveryEnabled?: () => boolean;
331
- /** Get hidden-but-discoverable MCP tools for search_tool_bm25 prompts and fallbacks.
332
- * @deprecated Use getDiscoverableTools with source filter instead. */
333
- getDiscoverableMCPTools?: () => import("../runtime-mcp/discoverable-tool-metadata").DiscoverableMCPTool[];
334
- /** Get the cached discoverable MCP search index for search_tool_bm25 execution.
335
- * @deprecated Use getDiscoverableToolSearchIndex instead. */
336
- getDiscoverableMCPSearchIndex?: () => import("../tool-discovery/tool-index").DiscoverableMCPSearchIndex;
337
- /** Get MCP tools activated by prior search_tool_bm25 calls. */
338
- getSelectedMCPToolNames?: () => string[];
339
- /** Merge MCP tool selections into the active session tool set. */
340
- activateDiscoveredMCPTools?: (toolNames: string[]) => Promise<string[]>;
341
331
  // ── Generic tool discovery (unified — covers built-in + MCP + extension) ──
342
332
  /** Whether any form of tool discovery is active (tools.discoveryMode !== "off" or mcp.discoveryMode). */
343
333
  isToolDiscoveryEnabled?: () => boolean;
@@ -511,20 +501,67 @@ export interface EvalBackendsAllowance {
511
501
  }
512
502
 
513
503
  /**
514
- * Parse PI_PY / PI_JS environment variables. Each is a boolean flag; unset
515
- * means "not specified, defer to settings". Returns null when neither is set
504
+ * Parse the `GJC_PY` multi-value token into per-backend booleans.
505
+ *
506
+ * Tokens (case-insensitive):
507
+ * - `0` / `bash` → JavaScript only (`{ py: false, js: true }`)
508
+ * - `1` / `py` → Python only (`{ py: true, js: false }`)
509
+ * - `js` → JavaScript only (`{ py: false, js: true }`)
510
+ * - `mix` / `both` → both backends (`{ py: true, js: true }`)
511
+ *
512
+ * Returns `null` when `GJC_PY` is unset, empty, or holds an unrecognized
513
+ * token, so the caller can fall back to the legacy `PI_PY` / `PI_JS` flags or
514
+ * per-key settings. This matches the documented contract that invalid values
515
+ * are ignored.
516
+ */
517
+ export function parseGjcPy(env: Record<string, string | undefined>): { py: boolean; js: boolean } | null {
518
+ const raw = env.GJC_PY;
519
+ if (raw === undefined) return null;
520
+ const token = raw.trim().toLowerCase();
521
+ if (token === "") return null;
522
+ switch (token) {
523
+ case "0":
524
+ case "bash":
525
+ return { py: false, js: true };
526
+ case "1":
527
+ case "py":
528
+ return { py: true, js: false };
529
+ case "js":
530
+ return { py: false, js: true };
531
+ case "mix":
532
+ case "both":
533
+ return { py: true, js: true };
534
+ default:
535
+ return null;
536
+ }
537
+ }
538
+
539
+ /**
540
+ * Parse legacy `PI_PY` / `PI_JS` boolean flags. Each is a boolean flag; unset
541
+ * means "not specified, defer to settings". Returns `null` when neither is set
516
542
  * so the caller can fall through to `readEvalBackendsAllowance` per key.
517
543
  */
518
- function getEvalBackendsFromEnv(): EvalBackendsAllowance | null {
519
- const pyEnv = $env.PI_PY;
520
- const jsEnv = $env.PI_JS;
544
+ function parseLegacyEvalEnvFlags(env: Record<string, string | undefined>): EvalBackendsAllowance | null {
545
+ const pyEnv = env.PI_PY;
546
+ const jsEnv = env.PI_JS;
521
547
  if (pyEnv === undefined && jsEnv === undefined) return null;
522
548
  return {
523
- python: pyEnv === undefined ? true : $flag("PI_PY"),
524
- js: jsEnv === undefined ? true : $flag("PI_JS"),
549
+ python: pyEnv === undefined ? true : isTruthyPythonFlag(pyEnv),
550
+ js: jsEnv === undefined ? true : isTruthyPythonFlag(jsEnv),
525
551
  };
526
552
  }
527
553
 
554
+ /**
555
+ * Resolve eval-backend allowance from environment only. `GJC_PY` wins when set
556
+ * to a recognized token; otherwise the legacy `PI_PY` / `PI_JS` flags apply.
557
+ * Returns `null` when no env override is set so the caller can defer to settings.
558
+ */
559
+ export function resolveEvalBackendsFromEnv(env: Record<string, string | undefined>): EvalBackendsAllowance | null {
560
+ const gjc = parseGjcPy(env);
561
+ if (gjc) return { python: gjc.py, js: gjc.js };
562
+ return parseLegacyEvalEnvFlags(env);
563
+ }
564
+
528
565
  /** Read per-backend allowance from settings (defaults true). */
529
566
  export function readEvalBackendsAllowance(session: ToolSession): EvalBackendsAllowance {
530
567
  return {
@@ -534,13 +571,20 @@ export function readEvalBackendsAllowance(session: ToolSession): EvalBackendsAll
534
571
  }
535
572
 
536
573
  /**
537
- * Materialize the active eval backend allowance: PI_PY / PI_JS env flags
538
- * override the per-key settings; otherwise settings (defaults true) win.
574
+ * Materialize the active eval backend allowance. `GJC_PY` takes precedence
575
+ * over the legacy `PI_PY` / `PI_JS` env flags, which in turn override the
576
+ * per-key settings (defaults true). When no env override is set, settings win.
539
577
  */
540
578
  export function resolveEvalBackends(session: ToolSession): EvalBackendsAllowance {
541
- return getEvalBackendsFromEnv() ?? readEvalBackendsAllowance(session);
579
+ return resolveEvalBackendsFromEnv($env) ?? readEvalBackendsAllowance(session);
542
580
  }
543
581
 
582
+ export {
583
+ resolvePythonIntegrationGate,
584
+ resolvePythonIpcTrace,
585
+ resolvePythonSkipCheck,
586
+ } from "../eval/py/env";
587
+
544
588
  /**
545
589
  * Create tools from BUILTIN_TOOLS registry.
546
590
  */
@@ -670,6 +714,14 @@ export async function createTools(session: ToolSession, toolNames?: string[]): P
670
714
  requestedTools.push("yield");
671
715
  }
672
716
 
717
+ if (requestedTools) {
718
+ const unknownToolNames = requestedTools.filter(name => !allToolsByRequestName.has(name));
719
+ if (unknownToolNames.length > 0) {
720
+ const message = `Unknown tool name${unknownToolNames.length === 1 ? "" : "s"}: ${unknownToolNames.join(", ")}`;
721
+ if (session.strictToolNames) throw new Error(message);
722
+ logger.warn(message);
723
+ }
724
+ }
673
725
  const filteredRequestedTools = requestedTools
674
726
  ?.map(name => allToolsByRequestName.get(name))
675
727
  .filter((entry): entry is [string, ToolFactory] => entry !== undefined)
@@ -15,6 +15,7 @@ import type { ImageContent, TextContent } from "@gajae-code/ai";
15
15
  import { getDefault, type Settings } from "../config/settings";
16
16
  import { formatGroupedDiagnosticMessages } from "../lsp/utils";
17
17
  import type { Theme } from "../modes/theme/theme";
18
+ import { sessionArtifactCapability } from "../session/session-manager";
18
19
  import { type OutputSummary, type TruncationResult, truncateMiddle, truncateTail } from "../session/streaming-output";
19
20
  import { formatBytes, wrapBrackets } from "./render-utils";
20
21
  import { renderError } from "./tool-errors";
@@ -103,6 +104,7 @@ export interface TruncationTextOptions {
103
104
  totalLines?: number;
104
105
  totalBytes?: number;
105
106
  maxBytes?: number;
107
+ artifactId?: string;
106
108
  }
107
109
 
108
110
  /**
@@ -288,6 +290,7 @@ export class OutputMetaBuilder {
288
290
  outputLines,
289
291
  outputBytes,
290
292
  maxBytes: options.maxBytes,
293
+ artifactId: options.artifactId,
291
294
  shownRange: { start: shownStart, end: shownEnd },
292
295
  nextOffset: options.direction === "head" ? shownEnd + 1 : undefined,
293
296
  };
@@ -593,13 +596,17 @@ export function resolveOutputMaxColumns(s: Settings | undefined): number {
593
596
  * is 0, falls back to tail-only truncation. Skips when the tool already
594
597
  * saved its own artifact (e.g. bash/python via OutputSink).
595
598
  */
599
+ function artifactCapabilityForContext(context: AgentToolContext | undefined) {
600
+ return sessionArtifactCapability(context?.sessionManager);
601
+ }
602
+
596
603
  async function spillLargeResultToArtifact(
597
604
  result: AgentToolResult,
598
605
  toolName: string,
599
606
  context: AgentToolContext | undefined,
600
607
  ): Promise<AgentToolResult> {
601
- const sessionManager = context?.sessionManager;
602
- if (!sessionManager) return result;
608
+ const artifactCapability = artifactCapabilityForContext(context);
609
+ if (!artifactCapability) return result;
603
610
  const { threshold, readThreshold, tailBytes, tailLines, headBytes } = getSpillConfig(context?.settings);
604
611
  // `read` manages its own per-range truncation, but the combined multi-range
605
612
  // output has no cap — enforce a read-specific (higher) combined threshold
@@ -625,7 +632,7 @@ async function spillLargeResultToArtifact(
625
632
  if (totalBytes <= effectiveThreshold) return result;
626
633
 
627
634
  // Save full output as artifact
628
- const artifactId = await sessionManager.saveArtifact(fullText, toolName);
635
+ const artifactId = await artifactCapability.saveArtifact(fullText, toolName);
629
636
  if (!artifactId) return result;
630
637
 
631
638
  // Truncate: middle elision when a head budget is configured, otherwise tail-only.
@@ -735,8 +742,9 @@ async function enforceInlineResultBackstop(
735
742
  // full output so the truncated view keeps a reference to the complete text.
736
743
  const existingMeta: OutputMeta | undefined = result.details?.meta;
737
744
  let artifactId = existingMeta?.truncation?.artifactId;
738
- if (!artifactId) {
739
- artifactId = (await context?.sessionManager?.saveArtifact(fullText, toolName)) ?? undefined;
745
+ const artifactCapability = artifactCapabilityForContext(context);
746
+ if (!artifactId && artifactCapability) {
747
+ artifactId = (await artifactCapability.saveArtifact(fullText, toolName)) ?? undefined;
740
748
  }
741
749
 
742
750
  // Budget head+tail below the cap, reserving room for the elision marker so the
package/src/tools/read.ts CHANGED
@@ -53,6 +53,7 @@ import {
53
53
  type ReadUrlToolDetails,
54
54
  renderReadUrlCall,
55
55
  renderReadUrlResult,
56
+ wrapUntrustedContent,
56
57
  } from "./fetch";
57
58
  import { applyListLimit } from "./list-limit";
58
59
  import {
@@ -487,6 +488,38 @@ const readSchema = z
487
488
 
488
489
  export type ReadToolInput = z.infer<typeof readSchema>;
489
490
 
491
+ const UNSAFE_SUMMARY_PATH =
492
+ /(?:\b(?:https?|wss?):\/\/|\b(?:api[-_ ]?key|access[-_ ]?token|bearer|secret|password)\b|\b(?:sk|pk|rk)-[A-Za-z0-9_-]{12,})/i;
493
+
494
+ /** Project paths and output sizes without exposing read content or remote URLs. */
495
+ export function summarizeReadToolActivity(kind: "args" | "result", value: unknown): string | undefined {
496
+ if (!value || typeof value !== "object" || Array.isArray(value)) return undefined;
497
+ const record = value as Record<string, unknown>;
498
+ if (kind === "args") {
499
+ const readPath = record.path;
500
+ if (
501
+ typeof readPath !== "string" ||
502
+ readPath.length === 0 ||
503
+ readPath.length > 100 ||
504
+ UNSAFE_SUMMARY_PATH.test(readPath)
505
+ ) {
506
+ return undefined;
507
+ }
508
+ return readPath;
509
+ }
510
+ if (!Array.isArray(record.content)) return undefined;
511
+ const text = record.content
512
+ .filter(
513
+ (block): block is { type: unknown; text: unknown } =>
514
+ typeof block === "object" && block !== null && "type" in block && "text" in block,
515
+ )
516
+ .filter(block => block.type === "text" && typeof block.text === "string")
517
+ .map(block => block.text as string)
518
+ .join("\n");
519
+ const lines = text.length === 0 ? 0 : text.split("\n").length;
520
+ return `${lines} lines, ${Buffer.byteLength(text, "utf-8")} bytes`;
521
+ }
522
+
490
523
  export interface ReadToolDetails {
491
524
  kind?: "file" | "url";
492
525
  truncation?: TruncationResult;
@@ -667,6 +700,7 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
667
700
  readonly parameters = readSchema;
668
701
  readonly nonAbortable = true;
669
702
  readonly strict = true;
703
+ readonly safeSummary = summarizeReadToolActivity;
670
704
 
671
705
  readonly #autoResizeImages: boolean;
672
706
  readonly #defaultLimit: number;
@@ -788,6 +822,7 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
788
822
  ignoreResultLimits?: boolean;
789
823
  raw?: boolean;
790
824
  immutable?: boolean;
825
+ wrapUntrusted?: boolean;
791
826
  },
792
827
  ): AgentToolResult<ReadToolDetails> {
793
828
  const displayMode = resolveFileDisplayMode(this.session, { raw: options.raw, immutable: options.immutable });
@@ -893,7 +928,7 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
893
928
  outputText = formatText(truncation.content, startLineDisplay);
894
929
  }
895
930
 
896
- resultBuilder.text(outputText);
931
+ resultBuilder.text(options.wrapUntrusted ? wrapUntrustedContent(outputText) : outputText);
897
932
  if (truncationInfo) {
898
933
  resultBuilder.truncation(truncationInfo.result, truncationInfo.options);
899
934
  }
@@ -1469,6 +1504,7 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
1469
1504
  sourceUrl: cached.details.finalUrl,
1470
1505
  entityLabel: "URL output",
1471
1506
  immutable: true,
1507
+ wrapUntrusted: true,
1472
1508
  });
1473
1509
  }
1474
1510
  return executeReadUrl(this.session, { path: parsedUrlTarget.path, raw: parsedUrlTarget.raw }, signal);
@@ -177,7 +177,7 @@ function ownerBrowserPolicy(snapshot: TabGcSnapshot): BrowserGcPolicy | null {
177
177
  /** Coarse, ordering-only eligibility; the live recheck in releaseTabIfGcEligible is authoritative. */
178
178
  function isCoarselyEligible(snapshot: TabGcSnapshot): boolean {
179
179
  return (
180
- snapshot.state === "alive" &&
180
+ (snapshot.state === "alive" || snapshot.state === "dead") &&
181
181
  snapshot.pendingCount === 0 &&
182
182
  (snapshot.kindTag === "headless" || snapshot.kindTag === "spawned")
183
183
  );
@@ -230,7 +230,7 @@ function evaluateRssPressureWarning(d: ResourceGcDeps): void {
230
230
  return;
231
231
  }
232
232
  const reclaimableRemains = collectIdleCandidates(d).some(
233
- c => c.snapshot.ownerId !== undefined && pressured.has(c.snapshot.ownerId),
233
+ c => c.snapshot.state === "alive" && c.snapshot.ownerId !== undefined && pressured.has(c.snapshot.ownerId),
234
234
  );
235
235
  if (reclaimableRemains) {
236
236
  rssWarningActive = false;
@@ -10,21 +10,13 @@ import {
10
10
  buildDiscoverableToolSearchIndex,
11
11
  type DiscoverableTool,
12
12
  type DiscoverableToolSearchIndex,
13
- formatDiscoverableToolServerSummary,
14
13
  searchDiscoverableTools,
15
- summarizeDiscoverableTools,
16
14
  } from "../tool-discovery/tool-index";
17
15
  import { renderStatusLine, renderTreeList, truncateToWidth } from "../tui";
18
16
  import type { ToolSession } from ".";
19
17
  import { formatCount, replaceTabs, TRUNCATE_LENGTHS } from "./render-utils";
20
18
  import { ToolError } from "./tool-errors";
21
19
 
22
- // Re-export legacy MCP types for back-compat (tests and external callers may reference them)
23
- export type {
24
- DiscoverableMCPSearchIndex,
25
- DiscoverableMCPTool,
26
- } from "../runtime-mcp/discoverable-tool-metadata";
27
-
28
20
  const DEFAULT_LIMIT = 8;
29
21
  const TOOL_DISCOVERY_TITLE = "Tool Discovery";
30
22
  const COLLAPSED_MATCH_LIMIT = 5;
@@ -78,24 +70,9 @@ function buildSearchToolBm25Content(details: SearchToolBm25Details): string {
78
70
  });
79
71
  }
80
72
 
81
- /** Get discoverable tools for description rendering. Falls back to empty array on error. */
82
73
  function getDiscoverableToolsForDescription(session: ToolSession): DiscoverableTool[] {
83
74
  try {
84
- // Prefer generic method; fall back to legacy MCP-only
85
- if (session.getDiscoverableTools) {
86
- return session.getDiscoverableTools();
87
- }
88
- // Legacy MCP path — adapt DiscoverableMCPTool (with `description`) → DiscoverableTool.
89
- const legacy = session.getDiscoverableMCPTools?.() ?? [];
90
- return legacy.map(t => ({
91
- name: t.name,
92
- label: t.label,
93
- summary: t.description,
94
- source: "mcp" as const,
95
- serverName: t.serverName,
96
- mcpToolName: t.mcpToolName,
97
- schemaKeys: t.schemaKeys,
98
- }));
75
+ return session.getDiscoverableTools?.() ?? [];
99
76
  } catch {
100
77
  return [];
101
78
  }
@@ -103,36 +80,18 @@ function getDiscoverableToolsForDescription(session: ToolSession): DiscoverableT
103
80
 
104
81
  function getDiscoverableToolSearchIndexForExecution(session: ToolSession): DiscoverableToolSearchIndex {
105
82
  try {
106
- // Prefer generic cached index
107
- if (session.getDiscoverableToolSearchIndex) {
108
- const cached = session.getDiscoverableToolSearchIndex();
109
- if (cached) return cached;
110
- }
111
- // Legacy MCP: use cached MCP index. Its documents expose `tool.description` as well as
112
- // `tool.summary`, so it is structurally compatible with DiscoverableToolSearchIndex.
113
- const mcpCached = session.getDiscoverableMCPSearchIndex?.();
114
- if (mcpCached) return mcpCached as unknown as DiscoverableToolSearchIndex;
83
+ const cached = session.getDiscoverableToolSearchIndex?.();
84
+ if (cached) return cached;
115
85
  } catch {}
116
86
  return buildDiscoverableToolSearchIndex(getDiscoverableToolsForDescription(session));
117
87
  }
118
88
 
119
- /** Resolve the effective selected tool names (generic or legacy MCP). */
120
89
  function getSelectedToolNames(session: ToolSession): string[] {
121
- if (session.getSelectedDiscoveredToolNames) {
122
- return session.getSelectedDiscoveredToolNames();
123
- }
124
- return session.getSelectedMCPToolNames?.() ?? [];
90
+ return session.getSelectedDiscoveredToolNames?.() ?? [];
125
91
  }
126
92
 
127
- /** Activate tools (generic or legacy MCP fallback). */
128
93
  async function activateTools(session: ToolSession, toolNames: string[]): Promise<string[]> {
129
- if (session.activateDiscoveredTools) {
130
- return session.activateDiscoveredTools(toolNames);
131
- }
132
- if (session.activateDiscoveredMCPTools) {
133
- return session.activateDiscoveredMCPTools(toolNames);
134
- }
135
- return [];
94
+ return (await session.activateDiscoveredTools?.(toolNames)) ?? [];
136
95
  }
137
96
 
138
97
  type DiscoveryExecutionSession = ToolSession & {
@@ -140,39 +99,19 @@ type DiscoveryExecutionSession = ToolSession & {
140
99
  };
141
100
 
142
101
  function supportsToolDiscoveryExecution(session: ToolSession): session is DiscoveryExecutionSession {
143
- // Supports generic discovery
144
- if (
102
+ return (
145
103
  typeof session.isToolDiscoveryEnabled === "function" &&
146
104
  typeof session.getSelectedDiscoveredToolNames === "function" &&
147
105
  typeof session.activateDiscoveredTools === "function"
148
- ) {
149
- return true;
150
- }
151
- // Supports legacy MCP discovery
152
- if (
153
- typeof session.isMCPDiscoveryEnabled === "function" &&
154
- typeof session.getSelectedMCPToolNames === "function" &&
155
- typeof session.activateDiscoveredMCPTools === "function"
156
- ) {
157
- return true;
158
- }
159
- return false;
106
+ );
160
107
  }
161
108
 
162
109
  function isDiscoveryEnabled(session: ToolSession): boolean {
163
- if (typeof session.isToolDiscoveryEnabled === "function") {
164
- return session.isToolDiscoveryEnabled();
165
- }
166
- return session.isMCPDiscoveryEnabled?.() ?? false;
110
+ return session.isToolDiscoveryEnabled?.() ?? false;
167
111
  }
168
112
 
169
- export function renderSearchToolBm25Description(discoverableTools: DiscoverableTool[] = []): string {
170
- const summary = summarizeDiscoverableTools(discoverableTools);
171
- return prompt.render(searchToolBm25Description, {
172
- discoverableMCPToolCount: summary.toolCount,
173
- discoverableMCPServerSummaries: summary.servers.map(formatDiscoverableToolServerSummary),
174
- hasDiscoverableMCPServers: summary.servers.length > 0,
175
- });
113
+ export function renderSearchToolBm25Description(): string {
114
+ return prompt.render(searchToolBm25Description, {});
176
115
  }
177
116
 
178
117
  function renderMatchLines(match: SearchToolBm25Match, theme: Theme): string[] {
@@ -209,9 +148,7 @@ export class SearchToolBm25Tool implements AgentTool<typeof searchToolBm25Schema
209
148
  readonly name = "search_tool_bm25";
210
149
  readonly label = "SearchTools";
211
150
  readonly loadMode = "essential";
212
- get description(): string {
213
- return renderSearchToolBm25Description(getDiscoverableToolsForDescription(this.session));
214
- }
151
+ readonly description = renderSearchToolBm25Description();
215
152
  readonly parameters = searchToolBm25Schema;
216
153
  readonly strict = true;
217
154
 
@@ -23,6 +23,8 @@ import {
23
23
  } from "./render-utils";
24
24
  import { type SubagentSnapshot, type SubagentToolDetails, subagentAwaitRenderedStateSignature } from "./subagent";
25
25
 
26
+ export { subagentAwaitRenderedStateSignature } from "./subagent";
27
+
26
28
  const PREVIEW_LINES_COLLAPSED = 1;
27
29
  const PREVIEW_LINES_EXPANDED = 4;
28
30
  const PREVIEW_LINE_WIDTH = 80;
@@ -128,7 +130,7 @@ function renderSubagentStatusLine(snapshot: SubagentSnapshot, theme: Theme, spin
128
130
  theme,
129
131
  snapshot.status === "running" ? spinnerFrame : undefined,
130
132
  );
131
- const id = theme.fg("muted", snapshot.id);
133
+ const id = theme.fg("muted", truncateToWidth(replaceTabs(snapshot.id), PREVIEW_LINE_WIDTH, Ellipsis.Unicode));
132
134
  const status = theme.fg("dim", snapshot.status);
133
135
  const duration = theme.fg("dim", formatDuration(snapshot.durationMs));
134
136
  return `${icon} ${id} ${status} ${duration}`;
@@ -195,7 +197,12 @@ function renderSubagentSnapshotBody(snapshot: SubagentSnapshot, expanded: boolea
195
197
  }
196
198
  }
197
199
 
198
- if (snapshot.guidance) lines.push(` ${theme.fg("dim", snapshot.guidance)}`);
200
+ if (snapshot.guidance) {
201
+ for (const line of getPreviewLines(snapshot.guidance, 1, PREVIEW_LINE_WIDTH, Ellipsis.Unicode)) {
202
+ lines.push(` ${theme.fg("dim", replaceTabs(line))}`);
203
+ }
204
+ }
205
+
199
206
  return lines;
200
207
  }
201
208
 
@@ -218,6 +225,7 @@ export const subagentToolRenderer = {
218
225
  }
219
226
 
220
227
  const runningCount = subagents.filter(s => s.status === "running").length;
228
+ const interrupted = result.details?.interrupted === true;
221
229
 
222
230
  // Each snapshot's rendered-state signature is constant for this component
223
231
  // instance, so compute them at most once; the heavy per-subagent bodies are
@@ -232,11 +240,12 @@ export const subagentToolRenderer = {
232
240
  // it is never gated by the heavy body cache.
233
241
  const header = renderStatusLine(
234
242
  {
235
- icon: runningCount > 0 ? "info" : "success",
236
- spinnerFrame: runningCount > 0 ? options.spinnerFrame : undefined,
237
- title: "Subagent",
238
- description:
239
- runningCount > 0
243
+ icon: interrupted ? "warning" : runningCount > 0 ? "info" : "success",
244
+ spinnerFrame: !interrupted && runningCount > 0 ? options.spinnerFrame : undefined,
245
+ title: interrupted ? "Subagent await interrupted" : "Subagent",
246
+ description: interrupted
247
+ ? "child subagents continue"
248
+ : runningCount > 0
240
249
  ? `awaiting ${runningCount} of ${subagents.length}`
241
250
  : `${subagents.length} ${subagents.length === 1 ? "subagent" : "subagents"}`,
242
251
  },
@@ -249,7 +258,9 @@ export const subagentToolRenderer = {
249
258
  out.push(truncateToWidth(` ${theme.fg("dim", "(ctrl+s to observe sessions)")}`, width, Ellipsis.Omit));
250
259
  }
251
260
 
252
- snapshotSignatures ??= subagents.map(snapshot => subagentAwaitRenderedStateSignature([snapshot]));
261
+ snapshotSignatures ??= subagents.map(snapshot =>
262
+ subagentAwaitRenderedStateSignature([snapshot], result.details),
263
+ );
253
264
  subagents.forEach((snapshot, index) => {
254
265
  // Fresh per-subagent status line (cheap), then the cached heavy body.
255
266
  out.push(