@gajae-code/coding-agent 0.13.3 → 0.14.0

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 (599) hide show
  1. package/CHANGELOG.md +184 -2
  2. package/README.md +2 -0
  3. package/bin/gajaessi.js +4 -0
  4. package/dist/types/async/job-manager.d.ts +55 -2
  5. package/dist/types/async/support.d.ts +14 -0
  6. package/dist/types/capability/mcp.d.ts +6 -0
  7. package/dist/types/capability/types.d.ts +6 -0
  8. package/dist/types/cli/accounts-cli.d.ts +19 -0
  9. package/dist/types/cli/args.d.ts +3 -0
  10. package/dist/types/cli/config-cli.d.ts +6 -0
  11. package/dist/types/cli/crash-cli.d.ts +10 -0
  12. package/dist/types/cli/customize-doctor.d.ts +145 -0
  13. package/dist/types/cli/daemon-cli.d.ts +3 -1
  14. package/dist/types/cli/mcp-cli.d.ts +11 -0
  15. package/dist/types/cli/notify-cli.d.ts +1 -1
  16. package/dist/types/cli/root-flags.d.ts +12 -0
  17. package/dist/types/cli/setup-cli.d.ts +3 -1
  18. package/dist/types/cli/skills-cli.d.ts +2 -1
  19. package/dist/types/cli/update-cli.d.ts +19 -1
  20. package/dist/types/cli.d.ts +6 -0
  21. package/dist/types/commands/accounts.d.ts +40 -0
  22. package/dist/types/commands/crash.d.ts +24 -0
  23. package/dist/types/commands/customize.d.ts +22 -0
  24. package/dist/types/commands/daemon.d.ts +1 -1
  25. package/dist/types/commands/launch.d.ts +6 -0
  26. package/dist/types/commands/setup.d.ts +6 -0
  27. package/dist/types/commands/skills.d.ts +6 -1
  28. package/dist/types/commands/update.d.ts +7 -0
  29. package/dist/types/config/atomic-yaml-patch-worker.d.ts +25 -0
  30. package/dist/types/config/atomic-yaml-patch.d.ts +62 -2
  31. package/dist/types/config/config-schema-version.d.ts +10 -0
  32. package/dist/types/config/file-lock.d.ts +18 -0
  33. package/dist/types/config/model-profile-activation.d.ts +3 -1
  34. package/dist/types/config/model-registry.d.ts +9 -1
  35. package/dist/types/config/models-config-schema.d.ts +2 -0
  36. package/dist/types/config/settings-schema.d.ts +70 -6
  37. package/dist/types/config/settings.d.ts +63 -0
  38. package/dist/types/config/skill-settings-defaults.d.ts +26 -0
  39. package/dist/types/config/task-delegation.d.ts +39 -0
  40. package/dist/types/config/update-channel.d.ts +10 -0
  41. package/dist/types/coordinator-mcp/server.d.ts +5 -1
  42. package/dist/types/crash/index-store.d.ts +87 -0
  43. package/dist/types/crash/nudge.d.ts +50 -0
  44. package/dist/types/crash/record-loader.d.ts +17 -0
  45. package/dist/types/crash/report.d.ts +134 -0
  46. package/dist/types/crash/sanitize.d.ts +25 -0
  47. package/dist/types/cursor.d.ts +13 -2
  48. package/dist/types/customization/import.d.ts +37 -0
  49. package/dist/types/customization/index.d.ts +4 -0
  50. package/dist/types/customization/inventory.d.ts +25 -0
  51. package/dist/types/customization/mutations.d.ts +32 -0
  52. package/dist/types/customization/types.d.ts +115 -0
  53. package/dist/types/daemon/control-types.d.ts +8 -1
  54. package/dist/types/daemon/operator-contract.d.ts +4 -4
  55. package/dist/types/discovery/claude.d.ts +39 -1
  56. package/dist/types/discovery/codex.d.ts +39 -1
  57. package/dist/types/discovery/index.d.ts +2 -0
  58. package/dist/types/discovery/mcp-compat.d.ts +30 -0
  59. package/dist/types/edit/renderer.d.ts +23 -0
  60. package/dist/types/extensibility/extensions/runner.d.ts +3 -0
  61. package/dist/types/extensibility/extensions/types.d.ts +21 -4
  62. package/dist/types/extensibility/gjc-plugins/observability.d.ts +6 -1
  63. package/dist/types/extensibility/gjc-plugins/registry.d.ts +8 -1
  64. package/dist/types/extensibility/hooks/loader.d.ts +19 -5
  65. package/dist/types/extensibility/runtime-skill-discovery.d.ts +22 -1
  66. package/dist/types/extensibility/skill-management.d.ts +107 -0
  67. package/dist/types/gjc-runtime/deep-interview-runtime.d.ts +3 -1
  68. package/dist/types/gjc-runtime/launch-worktree.d.ts +8 -0
  69. package/dist/types/gjc-runtime/linux-proc.d.ts +3 -0
  70. package/dist/types/gjc-runtime/ralplan-runtime.d.ts +10 -6
  71. package/dist/types/gjc-runtime/session-state-lock.d.ts +104 -0
  72. package/dist/types/gjc-runtime/session-state-sidecar.d.ts +120 -2
  73. package/dist/types/gjc-runtime/state-writer.d.ts +10 -1
  74. package/dist/types/gjc-runtime/ultragoal-guard.d.ts +4 -2
  75. package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +8 -6
  76. package/dist/types/gjc-runtime/workflow-settings.d.ts +109 -0
  77. package/dist/types/hooks/events.d.ts +60 -0
  78. package/dist/types/hooks/normalize.d.ts +83 -0
  79. package/dist/types/hooks/skill-state.d.ts +9 -2
  80. package/dist/types/main.d.ts +1 -1
  81. package/dist/types/modes/acp/abort-scope.d.ts +13 -0
  82. package/dist/types/modes/acp/acp-agent.d.ts +7 -4
  83. package/dist/types/modes/components/customization/customization-dashboard.d.ts +44 -0
  84. package/dist/types/modes/components/customization/import-wizard.d.ts +21 -0
  85. package/dist/types/modes/components/customization/index.d.ts +1 -0
  86. package/dist/types/modes/components/gajae-pet-widget.d.ts +8 -30
  87. package/dist/types/modes/components/irc-sidebar.d.ts +1 -0
  88. package/dist/types/modes/components/iterm-pet-transport.d.ts +122 -0
  89. package/dist/types/modes/components/oauth-selector.d.ts +10 -4
  90. package/dist/types/modes/components/pet-capability.d.ts +11 -25
  91. package/dist/types/modes/components/status-line/gh.d.ts +6 -2
  92. package/dist/types/modes/controllers/extension-ui-controller.d.ts +1 -1
  93. package/dist/types/modes/controllers/selector-controller.d.ts +7 -8
  94. package/dist/types/modes/controllers/stt-controller.d.ts +1 -1
  95. package/dist/types/modes/interactive-mode.d.ts +1 -0
  96. package/dist/types/modes/types.d.ts +1 -0
  97. package/dist/types/modes/utils/injected-user-submission.d.ts +10 -0
  98. package/dist/types/runtime-mcp/config.d.ts +9 -0
  99. package/dist/types/runtime-mcp/manager.d.ts +26 -1
  100. package/dist/types/runtime-mcp/oauth-discovery.d.ts +4 -0
  101. package/dist/types/runtime-mcp/oauth-flow.d.ts +24 -1
  102. package/dist/types/runtime-mcp/pool-key.d.ts +2 -0
  103. package/dist/types/runtime-mcp/protocol.d.ts +278 -0
  104. package/dist/types/runtime-mcp/scope-config.d.ts +29 -0
  105. package/dist/types/runtime-mcp/tool-bridge.d.ts +15 -13
  106. package/dist/types/runtime-mcp/transports/http.d.ts +9 -0
  107. package/dist/types/runtime-mcp/types.d.ts +102 -10
  108. package/dist/types/sdk/acp/adapter.d.ts +26 -5
  109. package/dist/types/sdk/broker/broker.d.ts +3 -55
  110. package/dist/types/sdk/broker/lifecycle.d.ts +18 -12
  111. package/dist/types/sdk/broker/session-index.d.ts +14 -5
  112. package/dist/types/sdk/broker/startup-failure.d.ts +16 -1
  113. package/dist/types/sdk/bus/chat-daemon-control.d.ts +51 -1
  114. package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +4 -41
  115. package/dist/types/sdk/bus/config.d.ts +11 -0
  116. package/dist/types/sdk/bus/conversation-store.d.ts +0 -1
  117. package/dist/types/sdk/bus/daemon-paths.d.ts +6 -0
  118. package/dist/types/sdk/bus/discord-conversation.d.ts +2 -0
  119. package/dist/types/sdk/bus/discord-daemon.d.ts +17 -12
  120. package/dist/types/sdk/bus/existing-thread-readiness.d.ts +4 -34
  121. package/dist/types/sdk/bus/inbound-reaction-ordering.d.ts +61 -0
  122. package/dist/types/sdk/bus/index.d.ts +85 -99
  123. package/dist/types/sdk/bus/kind-aware-reconciliation.d.ts +29 -7
  124. package/dist/types/sdk/bus/managed-daemon.d.ts +2 -32
  125. package/dist/types/sdk/bus/notification-service.d.ts +52 -0
  126. package/dist/types/sdk/bus/operator-runtime.d.ts +1 -1
  127. package/dist/types/sdk/bus/prompt-reconciliation.d.ts +16 -5
  128. package/dist/types/sdk/bus/reconciliation-store.d.ts +113 -5
  129. package/dist/types/sdk/bus/session-control.d.ts +25 -1
  130. package/dist/types/sdk/bus/slack-conversation.d.ts +4 -0
  131. package/dist/types/sdk/bus/slack-daemon.d.ts +9 -17
  132. package/dist/types/sdk/bus/slack-live-provider.d.ts +3 -1
  133. package/dist/types/sdk/bus/slack-provider.d.ts +4 -0
  134. package/dist/types/sdk/bus/slack-thread-binding.d.ts +6 -40
  135. package/dist/types/sdk/bus/telegram-adoption-intent.d.ts +30 -104
  136. package/dist/types/sdk/bus/telegram-daemon-cli.d.ts +10 -0
  137. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +262 -19
  138. package/dist/types/sdk/bus/telegram-daemon-orphan-reap.d.ts +125 -0
  139. package/dist/types/sdk/bus/telegram-daemon-owner-registry.d.ts +22 -0
  140. package/dist/types/sdk/bus/telegram-daemon.d.ts +119 -310
  141. package/dist/types/sdk/bus/telegram-reference.d.ts +1 -47
  142. package/dist/types/sdk/bus/threaded-render.d.ts +1 -0
  143. package/dist/types/sdk/bus/topic-registry.d.ts +33 -17
  144. package/dist/types/sdk/cli/rows.d.ts +2 -11
  145. package/dist/types/sdk/cli/session-cli.d.ts +15 -25
  146. package/dist/types/sdk/client/client.d.ts +97 -1
  147. package/dist/types/sdk/host/control/dispatch.d.ts +0 -7
  148. package/dist/types/sdk/host/control/index.d.ts +1 -1
  149. package/dist/types/sdk/host/control/operations.d.ts +18 -5
  150. package/dist/types/sdk/host/control/runtime-gate.d.ts +19 -0
  151. package/dist/types/sdk/host/host.d.ts +15 -1
  152. package/dist/types/sdk/host/query/handlers.d.ts +5 -0
  153. package/dist/types/sdk/host/reverse-leases.d.ts +1 -1
  154. package/dist/types/sdk/host/session-runtime.d.ts +127 -7
  155. package/dist/types/sdk/host/types.d.ts +1 -1
  156. package/dist/types/sdk/host/websocket-transport.d.ts +1 -1
  157. package/dist/types/sdk/index.d.ts +2 -1
  158. package/dist/types/sdk/lifecycle/broker-client.d.ts +8 -0
  159. package/dist/types/sdk/lifecycle/client.d.ts +59 -0
  160. package/dist/types/sdk/lifecycle/index.d.ts +3 -0
  161. package/dist/types/sdk/lifecycle/service.d.ts +232 -0
  162. package/dist/types/sdk/mcp/server.d.ts +9 -6
  163. package/dist/types/sdk/prompt-deadline-lease.d.ts +43 -0
  164. package/dist/types/sdk/prompt-deadline-manager.d.ts +28 -0
  165. package/dist/types/sdk/prompt-status.d.ts +10 -3
  166. package/dist/types/sdk/protocol/operation-registry.d.ts +5 -0
  167. package/dist/types/sdk/receipt-state.d.ts +17 -0
  168. package/dist/types/sdk/reconciliation-extensions.d.ts +2 -0
  169. package/dist/types/sdk/router/index.d.ts +1 -0
  170. package/dist/types/sdk/router/session-router.d.ts +152 -0
  171. package/dist/types/sdk/session-list.d.ts +22 -0
  172. package/dist/types/sdk/session-reconnect.d.ts +43 -1
  173. package/dist/types/sdk/session.d.ts +34 -1
  174. package/dist/types/sdk/transport/serve-cli.d.ts +1 -4
  175. package/dist/types/session/account-inventory.d.ts +86 -0
  176. package/dist/types/session/agent-session.d.ts +145 -6
  177. package/dist/types/session/agent-storage.d.ts +10 -0
  178. package/dist/types/session/coordinator-tool-label.d.ts +28 -0
  179. package/dist/types/session/internal/managed-session-storage.d.ts +23 -4
  180. package/dist/types/session/messages.d.ts +1 -1
  181. package/dist/types/session/secure-token-file.d.ts +3 -0
  182. package/dist/types/session/session-manager.d.ts +40 -1
  183. package/dist/types/session/startup-auth-config.d.ts +44 -0
  184. package/dist/types/session/terminal-abort.d.ts +378 -0
  185. package/dist/types/session/yield-queue.d.ts +7 -0
  186. package/dist/types/session-import/claude.d.ts +26 -0
  187. package/dist/types/session-import/codex.d.ts +88 -0
  188. package/dist/types/session-import/command.d.ts +35 -0
  189. package/dist/types/session-import/detect.d.ts +22 -0
  190. package/dist/types/session-import/index.d.ts +7 -0
  191. package/dist/types/session-import/provider-codex.d.ts +22 -0
  192. package/dist/types/session-import/provider-service.d.ts +38 -0
  193. package/dist/types/session-import/redact.d.ts +23 -0
  194. package/dist/types/session-import/service.d.ts +47 -0
  195. package/dist/types/session-import/types.d.ts +120 -0
  196. package/dist/types/setup/paseo/check.d.ts +16 -0
  197. package/dist/types/setup/paseo/install-saga.d.ts +115 -0
  198. package/dist/types/setup/paseo/json-publisher.d.ts +76 -0
  199. package/dist/types/setup/paseo/orchestration-preferences.d.ts +24 -0
  200. package/dist/types/setup/paseo/paseo-ownership.d.ts +87 -0
  201. package/dist/types/setup/paseo/paseo-setup.d.ts +29 -0
  202. package/dist/types/setup/paseo/provider-config.d.ts +35 -0
  203. package/dist/types/setup/paseo/remove.d.ts +14 -0
  204. package/dist/types/setup/paseo/result-types.d.ts +59 -0
  205. package/dist/types/setup/paseo/setup-deps.d.ts +73 -0
  206. package/dist/types/setup/paseo/skills-bridge.d.ts +44 -0
  207. package/dist/types/skill-state/active-state.d.ts +5 -1
  208. package/dist/types/slash-commands/acp-builtins.d.ts +5 -1
  209. package/dist/types/slash-commands/builtin-registry.d.ts +2 -0
  210. package/dist/types/slash-commands/helpers/credential-switch.d.ts +12 -0
  211. package/dist/types/slash-commands/helpers/usage-report.d.ts +5 -6
  212. package/dist/types/slash-commands/types.d.ts +7 -1
  213. package/dist/types/task/executor.d.ts +10 -0
  214. package/dist/types/task/index.d.ts +3 -1
  215. package/dist/types/tools/ask-answer-registry.d.ts +6 -3
  216. package/dist/types/tools/bash-sleep-advisory.d.ts +14 -0
  217. package/dist/types/tools/bash.d.ts +2 -6
  218. package/dist/types/tools/browser/attach.d.ts +11 -0
  219. package/dist/types/tools/browser/launch.d.ts +20 -0
  220. package/dist/types/tools/browser/profile-discovery.d.ts +6 -0
  221. package/dist/types/tools/browser/render.d.ts +1 -0
  222. package/dist/types/tools/browser.d.ts +3 -1
  223. package/dist/types/tools/image-gen.d.ts +9 -2
  224. package/dist/types/tools/index.d.ts +8 -0
  225. package/dist/types/tools/monitor.d.ts +1 -1
  226. package/dist/types/tools/skill-discovery.d.ts +8 -1
  227. package/dist/types/tools/subagent.d.ts +2 -0
  228. package/dist/types/tools/ultragoal-ask-guard.d.ts +2 -2
  229. package/dist/types/utils/herdr-pane.d.ts +76 -0
  230. package/package.json +19 -9
  231. package/scripts/build-binary.ts +2 -1
  232. package/scripts/build-sdk-package-smoke.ts +2 -13
  233. package/scripts/capture-sticky-viewport-showcase.ts +0 -1
  234. package/scripts/compile-args.ts +2 -0
  235. package/scripts/generate-sdk-adapter-parity-manifest.ts +31 -16
  236. package/scripts/generate-sdk-operation-inventory.ts +28 -0
  237. package/scripts/generate-telegram-baseline-manifest.ts +1 -0
  238. package/scripts/generate-tool-catalog.ts +6 -4
  239. package/scripts/verify-gjc-sdk-canonicalization.ts +5 -39
  240. package/src/async/job-manager.ts +352 -17
  241. package/src/async/support.ts +25 -0
  242. package/src/autoresearch/dashboard.ts +28 -13
  243. package/src/capability/index.ts +3 -1
  244. package/src/capability/mcp.ts +6 -0
  245. package/src/capability/types.ts +6 -0
  246. package/src/cli/accounts-cli.ts +395 -0
  247. package/src/cli/args.ts +23 -0
  248. package/src/cli/auth-broker-cli.ts +136 -66
  249. package/src/cli/auth-gateway-cli.ts +94 -70
  250. package/src/cli/config-cli.ts +27 -2
  251. package/src/cli/crash-cli.ts +78 -0
  252. package/src/cli/customize-doctor.ts +1605 -0
  253. package/src/cli/daemon-cli.ts +12 -3
  254. package/src/cli/fast-help.ts +1 -0
  255. package/src/cli/mcp-cli.ts +128 -60
  256. package/src/cli/notify-cli.ts +8 -14
  257. package/src/cli/root-flags.ts +8 -0
  258. package/src/cli/setup-cli.ts +145 -0
  259. package/src/cli/skills-cli.ts +38 -2
  260. package/src/cli/update-cli.ts +167 -12
  261. package/src/cli.ts +4 -0
  262. package/src/commands/accounts.ts +71 -0
  263. package/src/commands/crash.ts +35 -0
  264. package/src/commands/customize.ts +84 -0
  265. package/src/commands/daemon.ts +2 -2
  266. package/src/commands/deep-interview.ts +2 -0
  267. package/src/commands/launch.ts +1 -0
  268. package/src/commands/mcp.ts +12 -7
  269. package/src/commands/ralplan.ts +2 -0
  270. package/src/commands/sdk.ts +65 -32
  271. package/src/commands/setup.ts +5 -0
  272. package/src/commands/skills.ts +14 -4
  273. package/src/commands/ultragoal.ts +10 -1
  274. package/src/commands/update.ts +26 -15
  275. package/src/config/atomic-yaml-patch-worker.ts +57 -0
  276. package/src/config/atomic-yaml-patch.ts +769 -29
  277. package/src/config/config-schema-version.ts +10 -0
  278. package/src/config/file-lock.ts +70 -1
  279. package/src/config/mcp-schema.json +52 -14
  280. package/src/config/model-profile-activation.ts +20 -1
  281. package/src/config/model-profiles.ts +29 -19
  282. package/src/config/model-registry.ts +132 -21
  283. package/src/config/models-config-schema.ts +1 -1
  284. package/src/config/settings-schema.ts +76 -6
  285. package/src/config/settings.ts +4038 -199
  286. package/src/config/skill-settings-defaults.ts +41 -3
  287. package/src/config/task-delegation.ts +87 -0
  288. package/src/config/update-channel.ts +23 -0
  289. package/src/coordinator-mcp/server.ts +377 -308
  290. package/src/crash/index-store.ts +723 -0
  291. package/src/crash/nudge.ts +89 -0
  292. package/src/crash/record-loader.ts +149 -0
  293. package/src/crash/report.ts +551 -0
  294. package/src/crash/sanitize.ts +129 -0
  295. package/src/cursor.ts +36 -10
  296. package/src/customization/import.ts +946 -0
  297. package/src/customization/index.ts +4 -0
  298. package/src/customization/inventory.ts +335 -0
  299. package/src/customization/mutations.ts +141 -0
  300. package/src/customization/types.ts +223 -0
  301. package/src/daemon/control-types.ts +8 -1
  302. package/src/daemon/operator-contract.ts +6 -6
  303. package/src/defaults/gjc/skills/deep-interview/SKILL.md +11 -22
  304. package/src/defaults/gjc/skills/ralplan/SKILL.md +36 -23
  305. package/src/defaults/gjc/skills/ultragoal/SKILL.md +16 -0
  306. package/src/discovery/claude-hooks.ts +38 -0
  307. package/src/discovery/claude.ts +142 -209
  308. package/src/discovery/codex-hooks.ts +38 -0
  309. package/src/discovery/codex.ts +132 -198
  310. package/src/discovery/helpers.ts +8 -1
  311. package/src/discovery/index.ts +2 -0
  312. package/src/discovery/mcp-compat.ts +234 -0
  313. package/src/discovery/mcp-json.ts +6 -0
  314. package/src/edit/renderer.ts +40 -0
  315. package/src/edit/streaming.ts +4 -2
  316. package/src/exec/bash-executor.ts +24 -20
  317. package/src/export/html/index.ts +51 -2
  318. package/src/extensibility/extensions/loader.ts +9 -1
  319. package/src/extensibility/extensions/runner.ts +17 -4
  320. package/src/extensibility/extensions/types.ts +31 -6
  321. package/src/extensibility/gjc-plugins/constrained-hooks.ts +33 -0
  322. package/src/extensibility/gjc-plugins/installer.ts +9 -5
  323. package/src/extensibility/gjc-plugins/observability.ts +8 -2
  324. package/src/extensibility/gjc-plugins/registry.ts +13 -2
  325. package/src/extensibility/gjc-plugins/runtime-adapters.ts +3 -1
  326. package/src/extensibility/gjc-plugins/schema.ts +222 -39
  327. package/src/extensibility/hooks/loader.ts +154 -10
  328. package/src/extensibility/runtime-skill-discovery.ts +257 -60
  329. package/src/extensibility/skill-management.ts +368 -0
  330. package/src/extensibility/skills.ts +52 -16
  331. package/src/gjc-runtime/deep-interview-runtime.ts +45 -61
  332. package/src/gjc-runtime/launch-worktree.ts +56 -2
  333. package/src/gjc-runtime/linux-proc.ts +7 -1
  334. package/src/gjc-runtime/ralplan-runtime.ts +100 -164
  335. package/src/gjc-runtime/session-state-lock.ts +992 -0
  336. package/src/gjc-runtime/session-state-sidecar.ts +644 -142
  337. package/src/gjc-runtime/state-writer.ts +39 -14
  338. package/src/gjc-runtime/tmux-owner-isolation.ts +5 -4
  339. package/src/gjc-runtime/ultragoal-guard.ts +11 -4
  340. package/src/gjc-runtime/ultragoal-runtime.ts +44 -41
  341. package/src/gjc-runtime/workflow-settings.ts +596 -0
  342. package/src/goals/tools/goal-tool.ts +6 -1
  343. package/src/hooks/events.ts +291 -0
  344. package/src/hooks/native-skill-hook.ts +4 -0
  345. package/src/hooks/normalize.ts +369 -0
  346. package/src/hooks/skill-state.ts +165 -46
  347. package/src/internal-urls/docs-index.generated.ts +40 -32
  348. package/src/main.ts +32 -5
  349. package/src/migrate/mcp-mapper.ts +25 -2
  350. package/src/modes/acp/abort-scope.ts +29 -0
  351. package/src/modes/acp/acp-agent.ts +423 -98
  352. package/src/modes/components/assistant-message.ts +6 -1
  353. package/src/modes/components/customization/customization-dashboard.ts +443 -0
  354. package/src/modes/components/customization/import-wizard.ts +372 -0
  355. package/src/modes/components/customization/index.ts +1 -0
  356. package/src/modes/components/gajae-pet-widget.ts +539 -213
  357. package/src/modes/components/irc-sidebar.ts +11 -0
  358. package/src/modes/components/iterm-pet-transport.ts +585 -0
  359. package/src/modes/components/oauth-selector.ts +277 -86
  360. package/src/modes/components/pet-capability.ts +39 -40
  361. package/src/modes/components/settings-selector.ts +9 -0
  362. package/src/modes/components/status-line/gh.ts +45 -1
  363. package/src/modes/components/status-line/segments.ts +16 -1
  364. package/src/modes/components/tool-status-header.ts +13 -3
  365. package/src/modes/controllers/command-controller.ts +20 -8
  366. package/src/modes/controllers/extension-ui-controller.ts +56 -257
  367. package/src/modes/controllers/input-controller.ts +10 -0
  368. package/src/modes/controllers/runtime-mcp-command-controller.ts +16 -3
  369. package/src/modes/controllers/selector-controller.ts +177 -72
  370. package/src/modes/controllers/stt-controller.ts +3 -3
  371. package/src/modes/interactive-mode.ts +88 -16
  372. package/src/modes/print-mode.ts +35 -6
  373. package/src/modes/runtime-init.ts +21 -68
  374. package/src/modes/types.ts +1 -0
  375. package/src/modes/utils/injected-user-submission.ts +25 -0
  376. package/src/modes/utils/terminal-bell.ts +15 -1
  377. package/src/prompts/agent-fragments/ralplan-persistence.md +1 -1
  378. package/src/prompts/agent-fragments/restricted-bash.md +1 -1
  379. package/src/prompts/agents/critic.md +1 -1
  380. package/src/prompts/system/rlm-research.md +1 -1
  381. package/src/prompts/system/system-prompt.md +0 -2
  382. package/src/prompts/tools/bash.md +7 -1
  383. package/src/prompts/tools/browser.md +1 -1
  384. package/src/prompts/tools/cron.md +6 -6
  385. package/src/prompts/tools/read.md +0 -2
  386. package/src/prompts/tools/skill-discovery.md +4 -2
  387. package/src/runtime-mcp/client.ts +427 -23
  388. package/src/runtime-mcp/config.ts +37 -5
  389. package/src/runtime-mcp/manager-pool.test.ts +56 -0
  390. package/src/runtime-mcp/manager.ts +52 -2
  391. package/src/runtime-mcp/oauth-discovery.ts +13 -0
  392. package/src/runtime-mcp/oauth-flow.ts +46 -1
  393. package/src/runtime-mcp/pool-key.ts +5 -1
  394. package/src/runtime-mcp/pool.test.ts +9 -0
  395. package/src/runtime-mcp/protocol.test.ts +353 -0
  396. package/src/runtime-mcp/protocol.ts +624 -0
  397. package/src/runtime-mcp/scope-config.ts +78 -0
  398. package/src/runtime-mcp/tool-bridge.ts +44 -10
  399. package/src/runtime-mcp/transports/http.ts +84 -13
  400. package/src/runtime-mcp/types.ts +123 -12
  401. package/src/sdk/acp/adapter.ts +328 -97
  402. package/src/sdk/broker/broker.ts +160 -741
  403. package/src/sdk/broker/ensure.ts +9 -1
  404. package/src/sdk/broker/lifecycle.ts +510 -116
  405. package/src/sdk/broker/operation-receipt-ledger.ts +11 -2
  406. package/src/sdk/broker/process-incarnation.ts +19 -0
  407. package/src/sdk/broker/session-index.ts +516 -117
  408. package/src/sdk/broker/startup-failure.ts +28 -5
  409. package/src/sdk/broker/transport.ts +1 -13
  410. package/src/sdk/bus/chat-daemon-cli.ts +4 -2
  411. package/src/sdk/bus/chat-daemon-control.ts +67 -6
  412. package/src/sdk/bus/chat-daemon-runtime.ts +183 -859
  413. package/src/sdk/bus/config.ts +13 -0
  414. package/src/sdk/bus/conversation-store.ts +59 -171
  415. package/src/sdk/bus/daemon-paths.ts +20 -0
  416. package/src/sdk/bus/discord-conversation.ts +2 -0
  417. package/src/sdk/bus/discord-daemon.ts +524 -126
  418. package/src/sdk/bus/discord-live-provider.ts +206 -79
  419. package/src/sdk/bus/existing-thread-readiness.ts +4 -97
  420. package/src/sdk/bus/inbound-reaction-ordering.ts +122 -0
  421. package/src/sdk/bus/index.ts +2480 -456
  422. package/src/sdk/bus/kind-aware-reconciliation.ts +204 -34
  423. package/src/sdk/bus/lifecycle-commands.ts +2 -2
  424. package/src/sdk/bus/managed-daemon.ts +2 -145
  425. package/src/sdk/bus/notification-service.ts +196 -0
  426. package/src/sdk/bus/operator-runtime.ts +1 -1
  427. package/src/sdk/bus/prompt-reconciliation.ts +24 -15
  428. package/src/sdk/bus/reconciliation-store.ts +553 -24
  429. package/src/sdk/bus/session-control.ts +49 -3
  430. package/src/sdk/bus/slack-conversation.ts +4 -0
  431. package/src/sdk/bus/slack-daemon.ts +733 -134
  432. package/src/sdk/bus/slack-live-provider.ts +65 -15
  433. package/src/sdk/bus/slack-provider.ts +4 -0
  434. package/src/sdk/bus/slack-thread-binding.ts +9 -104
  435. package/src/sdk/bus/telegram-adoption-intent.ts +299 -209
  436. package/src/sdk/bus/telegram-daemon-cli.ts +194 -7
  437. package/src/sdk/bus/telegram-daemon-contract.ts +265 -19
  438. package/src/sdk/bus/telegram-daemon-control.ts +3 -13
  439. package/src/sdk/bus/telegram-daemon-orphan-reap.ts +498 -0
  440. package/src/sdk/bus/telegram-daemon-owner-registry.ts +176 -0
  441. package/src/sdk/bus/telegram-daemon.ts +2552 -2280
  442. package/src/sdk/bus/telegram-reference.ts +1 -226
  443. package/src/sdk/bus/telegram-setup.ts +2 -2
  444. package/src/sdk/bus/threaded-render.ts +1 -0
  445. package/src/sdk/bus/topic-registry.ts +279 -146
  446. package/src/sdk/cli/rows.ts +2 -35
  447. package/src/sdk/cli/session-cli.ts +776 -700
  448. package/src/sdk/client/client.ts +892 -1
  449. package/src/sdk/host/control/dispatch.ts +93 -58
  450. package/src/sdk/host/control/index.ts +1 -1
  451. package/src/sdk/host/control/operations.ts +18 -10
  452. package/src/sdk/host/control/runtime-gate.ts +40 -0
  453. package/src/sdk/host/host.ts +63 -12
  454. package/src/sdk/host/query/handlers.ts +66 -7
  455. package/src/sdk/host/reverse-leases.ts +2 -2
  456. package/src/sdk/host/sdk-surface-parity.test.ts +1 -1
  457. package/src/sdk/host/session-runtime.test.ts +2787 -34
  458. package/src/sdk/host/session-runtime.ts +1489 -101
  459. package/src/sdk/host/surface-policy.ts +12 -8
  460. package/src/sdk/host/types.ts +1 -1
  461. package/src/sdk/host/websocket-transport.lifecycle.test.ts +31 -59
  462. package/src/sdk/host/websocket-transport.ts +85 -50
  463. package/src/sdk/index.ts +2 -1
  464. package/src/sdk/lifecycle/broker-client.ts +53 -0
  465. package/src/sdk/lifecycle/client.ts +234 -0
  466. package/src/sdk/lifecycle/index.ts +3 -0
  467. package/src/sdk/{bus/recent-activity.ts → lifecycle/recent-sessions.ts} +5 -2
  468. package/src/sdk/lifecycle/service.ts +720 -0
  469. package/src/sdk/mcp/server.ts +226 -188
  470. package/src/sdk/prompt-deadline-lease.ts +55 -0
  471. package/src/sdk/prompt-deadline-manager.ts +148 -0
  472. package/src/sdk/prompt-status.ts +11 -3
  473. package/src/sdk/protocol/operation-inventory.generated.json +272 -129
  474. package/src/sdk/protocol/operation-registry.ts +71 -8
  475. package/src/sdk/receipt-state.ts +43 -0
  476. package/src/sdk/reconciliation-extensions.ts +14 -0
  477. package/src/sdk/router/index.ts +1 -0
  478. package/src/sdk/router/session-router.ts +1658 -0
  479. package/src/sdk/session-list.ts +93 -0
  480. package/src/sdk/session-reconnect.ts +45 -1
  481. package/src/sdk/session.ts +716 -120
  482. package/src/sdk/transport/serve-cli.ts +18 -34
  483. package/src/session/account-inventory.ts +603 -0
  484. package/src/session/agent-session.ts +2857 -582
  485. package/src/session/agent-storage.ts +35 -0
  486. package/src/session/blob-store.ts +32 -1
  487. package/src/session/coordinator-tool-label.ts +40 -0
  488. package/src/session/internal/managed-session-scope.ts +4 -0
  489. package/src/session/internal/managed-session-storage.ts +173 -12
  490. package/src/session/messages.ts +1 -1
  491. package/src/session/secure-token-file.ts +80 -0
  492. package/src/session/session-manager.ts +730 -58
  493. package/src/session/session-storage.ts +25 -16
  494. package/src/session/startup-auth-config.ts +297 -0
  495. package/src/session/terminal-abort.ts +1253 -0
  496. package/src/session/yield-queue.ts +57 -15
  497. package/src/session-import/claude.ts +334 -0
  498. package/src/session-import/codex.ts +1033 -0
  499. package/src/session-import/command.ts +77 -0
  500. package/src/session-import/detect.ts +133 -0
  501. package/src/session-import/index.ts +7 -0
  502. package/src/session-import/provider-codex.ts +327 -0
  503. package/src/session-import/provider-service.ts +457 -0
  504. package/src/session-import/redact.ts +128 -0
  505. package/src/session-import/service.ts +1264 -0
  506. package/src/session-import/types.ts +148 -0
  507. package/src/setup/paseo/check.ts +213 -0
  508. package/src/setup/paseo/install-saga.ts +293 -0
  509. package/src/setup/paseo/json-publisher.ts +263 -0
  510. package/src/setup/paseo/orchestration-preferences.ts +86 -0
  511. package/src/setup/paseo/paseo-ownership.ts +224 -0
  512. package/src/setup/paseo/paseo-setup.ts +253 -0
  513. package/src/setup/paseo/provider-config.ts +139 -0
  514. package/src/setup/paseo/remove.ts +183 -0
  515. package/src/setup/paseo/result-types.ts +79 -0
  516. package/src/setup/paseo/setup-deps.ts +175 -0
  517. package/src/setup/paseo/skills-bridge.ts +260 -0
  518. package/src/skill-state/active-state.ts +21 -11
  519. package/src/slash-commands/acp-builtins.ts +9 -1
  520. package/src/slash-commands/builtin-registry.ts +98 -16
  521. package/src/slash-commands/helpers/credential-switch.ts +143 -0
  522. package/src/slash-commands/helpers/mcp.ts +9 -3
  523. package/src/slash-commands/helpers/usage-report.ts +61 -56
  524. package/src/slash-commands/types.ts +7 -2
  525. package/src/task/executor.ts +30 -11
  526. package/src/task/index.ts +66 -7
  527. package/src/task/render.ts +23 -9
  528. package/src/tools/ask-answer-registry.ts +23 -7
  529. package/src/tools/ask.ts +8 -4
  530. package/src/tools/bash-sleep-advisory.ts +115 -0
  531. package/src/tools/bash.ts +98 -18
  532. package/src/tools/browser/attach.ts +71 -3
  533. package/src/tools/browser/launch.ts +86 -13
  534. package/src/tools/browser/profile-discovery.ts +57 -7
  535. package/src/tools/browser/render.ts +8 -1
  536. package/src/tools/browser.ts +130 -21
  537. package/src/tools/computer.enforcement.test.ts +1 -1
  538. package/src/tools/computer.ts +3 -2
  539. package/src/tools/cron.ts +12 -1
  540. package/src/tools/image-gen.ts +27 -16
  541. package/src/tools/index.ts +8 -0
  542. package/src/tools/job.ts +33 -6
  543. package/src/tools/monitor.ts +41 -2
  544. package/src/tools/skill-discovery.ts +21 -29
  545. package/src/tools/subagent.ts +142 -24
  546. package/src/tools/tool-catalog.generated.ts +6 -6
  547. package/src/tools/ultragoal-ask-guard.ts +10 -3
  548. package/src/utils/herdr-pane.ts +345 -0
  549. package/src/utils/title-generator.ts +2 -0
  550. package/src/web/scrapers/index.ts +6 -4
  551. package/dist/types/cli/malloc-env-guard.test.d.ts +0 -1
  552. package/dist/types/defaults/gjc-defaults.test.d.ts +0 -1
  553. package/dist/types/memory-backend/lazy-loading.test.d.ts +0 -1
  554. package/dist/types/runtime/boot-ordering.test.d.ts +0 -1
  555. package/dist/types/runtime/lazy-service.test.d.ts +0 -1
  556. package/dist/types/runtime/network-prewarm-service.test.d.ts +0 -1
  557. package/dist/types/runtime/workspace-tree-service.test.d.ts +0 -1
  558. package/dist/types/runtime-mcp/config.test.d.ts +0 -1
  559. package/dist/types/runtime-mcp/http.test.d.ts +0 -1
  560. package/dist/types/runtime-mcp/manager-pool.test.d.ts +0 -1
  561. package/dist/types/runtime-mcp/pool-key.test.d.ts +0 -1
  562. package/dist/types/runtime-mcp/pool.test.d.ts +0 -1
  563. package/dist/types/sdk/bus/lifecycle-control-runtime.d.ts +0 -117
  564. package/dist/types/sdk/bus/lifecycle-orchestrator.d.ts +0 -141
  565. package/dist/types/sdk/bus/telegram-cli.d.ts +0 -31
  566. package/dist/types/sdk/elevation/allowlist.d.ts +0 -20
  567. package/dist/types/sdk/elevation/audit.d.ts +0 -93
  568. package/dist/types/sdk/elevation/capability.d.ts +0 -3
  569. package/dist/types/sdk/elevation/digest.d.ts +0 -72
  570. package/dist/types/sdk/elevation/dispatch-receipt.d.ts +0 -85
  571. package/dist/types/sdk/elevation/grant-ledger.d.ts +0 -163
  572. package/dist/types/sdk/elevation/owner.d.ts +0 -48
  573. package/dist/types/sdk/host/import-graph.test.d.ts +0 -1
  574. package/dist/types/sdk/host/sdk-surface-parity.test.d.ts +0 -1
  575. package/dist/types/sdk/host/session-runtime.test.d.ts +0 -1
  576. package/dist/types/sdk/host/websocket-transport.lifecycle.test.d.ts +0 -1
  577. package/dist/types/session/auth-broker-config.d.ts +0 -13
  578. package/dist/types/session/heap-eviction-artifacts.test.d.ts +0 -1
  579. package/dist/types/skills/skills.test.d.ts +0 -1
  580. package/dist/types/slash-commands/notify-command.test.d.ts +0 -1
  581. package/dist/types/task/token-log.test.d.ts +0 -1
  582. package/dist/types/tools/computer.enforcement.test.d.ts +0 -1
  583. package/dist/types/tools/descriptors.test.d.ts +0 -1
  584. package/scripts/g005-daemon-smoke.ts +0 -180
  585. package/scripts/g011-daemon-path-smoke.ts +0 -153
  586. package/src/sdk/bus/lifecycle-control-runtime.ts +0 -1733
  587. package/src/sdk/bus/lifecycle-orchestrator.ts +0 -489
  588. package/src/sdk/bus/telegram-cli.ts +0 -212
  589. package/src/sdk/elevation/allowlist.ts +0 -54
  590. package/src/sdk/elevation/audit.ts +0 -208
  591. package/src/sdk/elevation/capability.ts +0 -41
  592. package/src/sdk/elevation/digest.ts +0 -129
  593. package/src/sdk/elevation/dispatch-receipt.ts +0 -184
  594. package/src/sdk/elevation/grant-ledger.ts +0 -1142
  595. package/src/sdk/elevation/owner.ts +0 -109
  596. package/src/session/auth-broker-config.ts +0 -109
  597. /package/dist/types/{ai-core-import-gate.test.d.ts → discovery/claude-hooks.d.ts} +0 -0
  598. /package/dist/types/{cli/fixture-report.test.d.ts → discovery/codex-hooks.d.ts} +0 -0
  599. /package/dist/types/sdk/{bus/recent-activity.d.ts → lifecycle/recent-sessions.d.ts} +0 -0
@@ -34,6 +34,7 @@ import {
34
34
  // import graph; the /notify handlers import them lazily at first use.
35
35
  import type { NotificationProvider } from "../sdk/bus/config";
36
36
  import { computeCacheMissCostSummary, formatCacheMissSummaryLines } from "../session/cache-economics";
37
+ import { formatProviderSessionImportSummary, runSessionImportCommand } from "../session-import";
37
38
  import { formatModelOnboardingGuidance } from "../setup/model-onboarding-guidance";
38
39
  import {
39
40
  addApiCompatibleProvider,
@@ -44,6 +45,7 @@ import {
44
45
  import { parseThinkingLevel } from "../thinking";
45
46
  import { getDisplayChangelogEntries } from "../utils/changelog";
46
47
  import { buildContextReportText } from "./helpers/context-report";
48
+ import { switchSessionCredentialCommand } from "./helpers/credential-switch";
47
49
  import { buildFastStatusReport } from "./helpers/fast-status-report";
48
50
  import { formatDuration } from "./helpers/format";
49
51
  import { commandConsumed, errorMessage, parseSlashCommand, parseSubcommand, usage } from "./helpers/parse";
@@ -91,7 +93,12 @@ const PET_COMMAND_DEPRECATED_INPUTS: Readonly<Record<string, PetMode>> = {
91
93
  type GjcModelBatchAssignmentTargetId = "all-role-agents" | "all-targets";
92
94
  type ParsedModelCommandArgs =
93
95
  | { kind: "summary" }
94
- | { kind: "assign"; targetId: GjcModelAssignmentTargetId | GjcModelBatchAssignmentTargetId; selector: string };
96
+ | {
97
+ kind: "assign";
98
+ targetId: GjcModelAssignmentTargetId | GjcModelBatchAssignmentTargetId;
99
+ selector: string;
100
+ hasExplicitTarget: boolean;
101
+ };
95
102
 
96
103
  const GJC_MODEL_ROLE_AGENT_TARGET_IDS: GjcModelAssignmentTargetId[] = ["executor", "architect", "planner", "critic"];
97
104
 
@@ -234,19 +241,19 @@ function parseModelCommandArgs(args: string): ParsedModelCommandArgs {
234
241
 
235
242
  if (first === "assign") {
236
243
  const targetId = parseTarget(tokens[1]);
237
- if (targetId) return { kind: "assign", targetId, selector: tokens.slice(2).join(" ") };
238
- return { kind: "assign", targetId: "default", selector: tokens.slice(1).join(" ") };
244
+ if (targetId) return { kind: "assign", targetId, selector: tokens.slice(2).join(" "), hasExplicitTarget: true };
245
+ return { kind: "assign", targetId: "default", selector: tokens.slice(1).join(" "), hasExplicitTarget: false };
239
246
  }
240
247
 
241
248
  const explicitTarget = parseTarget(first);
242
249
  if (explicitTarget) {
243
- return { kind: "assign", targetId: explicitTarget, selector: tokens.slice(1).join(" ") };
250
+ return { kind: "assign", targetId: explicitTarget, selector: tokens.slice(1).join(" "), hasExplicitTarget: true };
244
251
  }
245
252
  if (first === "set") {
246
253
  const targetId = parseTarget(tokens[1]);
247
- if (targetId) return { kind: "assign", targetId, selector: tokens.slice(2).join(" ") };
254
+ if (targetId) return { kind: "assign", targetId, selector: tokens.slice(2).join(" "), hasExplicitTarget: true };
248
255
  }
249
- return { kind: "assign", targetId: "default", selector: args.trim() };
256
+ return { kind: "assign", targetId: "default", selector: args.trim(), hasExplicitTarget: false };
250
257
  }
251
258
  /**
252
259
  * Optional namespace prefix accepted on `/model <preset>` selectors so users
@@ -597,7 +604,28 @@ const shutdownHandlerTui = (_command: ParsedSlashCommand, runtime: TuiSlashComma
597
604
  return commandConsumed();
598
605
  };
599
606
 
607
+ const IMPORT_SESSION_RETAINED_DESCRIPTOR_AUTHORITY_AVAILABLE = process.platform === "linux";
608
+
600
609
  const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
610
+ {
611
+ name: "import-session",
612
+ priority: 29,
613
+ description: "Import a Codex or Claude transcript into native GJC history",
614
+ inlineHint: "<transcript-file> [--provider codex|claude]",
615
+ allowArgs: true,
616
+ acp: false,
617
+ localHeadless: true,
618
+ handle: async (command, runtime) => {
619
+ if (runtime.session?.isStreaming) return usage("Cannot import a session while streaming.", runtime);
620
+ const outcome = await runSessionImportCommand(command.args, runtime.cwd);
621
+ if (outcome.kind === "error") {
622
+ await runtime.output(outcome.message);
623
+ return { consumed: true, exitCode: 1 };
624
+ }
625
+ await runtime.output(formatProviderSessionImportSummary(outcome.result));
626
+ return { consumed: true };
627
+ },
628
+ },
601
629
  {
602
630
  name: "notify",
603
631
  priority: 30,
@@ -840,11 +868,11 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
840
868
  );
841
869
  }
842
870
  // Preset shortcut: when the selector names a known model profile
843
- // (optionally `gajae-code/`-prefixed) and no explicit role target
844
- // was given, activate the profile immediately instead of treating
845
- // the preset name as a model id and failing with "Unknown model".
846
- // `/model <role> <preset>` keeps assigning to the named role.
847
- if (parsedArgs.targetId === "default") {
871
+ // (optionally `gajae-code/`-prefixed) and the target is implicit,
872
+ // activate the profile immediately instead of treating the preset name
873
+ // as a model id and failing with "Unknown model". Explicit targets,
874
+ // including `/model default <preset>`, remain ordinary assignments.
875
+ if (parsedArgs.targetId === "default" && !parsedArgs.hasExplicitTarget) {
848
876
  const presetName = resolvePresetSelector(modelId, runtime.session.modelRegistry);
849
877
  if (presetName) {
850
878
  try {
@@ -1304,12 +1332,43 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
1304
1332
  name: "usage",
1305
1333
  description: "Show provider usage and limits",
1306
1334
  acpDescription: "Show token usage",
1307
- handle: async (_command, runtime) => {
1308
- await runtime.output(await buildUsageReportText(runtime));
1335
+ subcommands: [{ name: "check", description: "Explicitly check account health and usage" }],
1336
+ inlineHint: "[check]",
1337
+ acpInputHint: "[check]",
1338
+ allowArgs: true,
1339
+ handle: async (command, runtime) => {
1340
+ const args = command.args.trim().toLowerCase();
1341
+ if (args !== "" && args !== "check") return usage("Usage: /usage [check]", runtime);
1342
+ await runtime.output(await buildUsageReportText(runtime, { check: args === "check" }));
1309
1343
  return commandConsumed();
1310
1344
  },
1311
- handleTui: async (_command, runtime) => {
1312
- await runtime.ctx.handleUsageCommand();
1345
+ handleTui: async (command, runtime) => {
1346
+ const args = command.args.trim().toLowerCase();
1347
+ if (args !== "" && args !== "check") {
1348
+ runtime.ctx.showError("Usage: /usage [check]");
1349
+ } else {
1350
+ const adapted = toSlashCommandRuntime(runtime);
1351
+ await adapted.output(await buildUsageReportText(adapted, { check: args === "check" }));
1352
+ }
1353
+ runtime.ctx.editor.setText("");
1354
+ },
1355
+ },
1356
+ {
1357
+ name: "credential",
1358
+ aliases: ["account"],
1359
+ description: "Switch this session's active stored account, or list accounts",
1360
+ acpDescription: "Switch or list stored credentials for this session",
1361
+ inlineHint: "[email:<addr>|id:<n>|account:<id>|project:<id>|provider/<selector>]",
1362
+ acpInputHint: "[selector]",
1363
+ allowArgs: true,
1364
+ handle: async (command, runtime) => {
1365
+ await runtime.output(await switchSessionCredentialCommand(runtime, command.args));
1366
+ return commandConsumed();
1367
+ },
1368
+ handleTui: async (command, runtime) => {
1369
+ const result = await switchSessionCredentialCommand(toSlashCommandRuntime(runtime), command.args);
1370
+ refreshStatusLine(runtime.ctx);
1371
+ runtime.ctx.showStatus(result);
1313
1372
  runtime.ctx.editor.setText("");
1314
1373
  },
1315
1374
  },
@@ -1380,6 +1439,15 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
1380
1439
  runtime.ctx.editor.setText("");
1381
1440
  },
1382
1441
  },
1442
+
1443
+ {
1444
+ name: "extensions",
1445
+ description: "Configure skills, hooks, and MCPs.",
1446
+ handleTui: (_command, runtime) => {
1447
+ runtime.ctx.showCustomizationDashboard();
1448
+ runtime.ctx.editor.setText("");
1449
+ },
1450
+ },
1383
1451
  {
1384
1452
  name: "monitors",
1385
1453
  description: "Open the monitor/cron jobs overlay",
@@ -1938,7 +2006,9 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
1938
2006
  const QUARANTINED_UTILITY_SLASH_COMMANDS = new Set(["agents"]);
1939
2007
 
1940
2008
  const ACTIVE_BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = BUILTIN_SLASH_COMMAND_REGISTRY.filter(
1941
- command => !QUARANTINED_UTILITY_SLASH_COMMANDS.has(command.name),
2009
+ command =>
2010
+ !QUARANTINED_UTILITY_SLASH_COMMANDS.has(command.name) &&
2011
+ (command.name !== "import-session" || IMPORT_SESSION_RETAINED_DESCRIPTOR_AUTHORITY_AVAILABLE),
1942
2012
  );
1943
2013
 
1944
2014
  const BUILTIN_SLASH_COMMAND_LOOKUP = new Map<string, SlashCommandSpec>();
@@ -2021,6 +2091,18 @@ export async function executeBuiltinSlashCommand(
2021
2091
  return false;
2022
2092
  }
2023
2093
 
2094
+ /** Dispatch a command explicitly authorized for trusted local non-interactive mode. */
2095
+ export async function executeLocalHeadlessBuiltinSlashCommand(
2096
+ text: string,
2097
+ runtime: SlashCommandRuntime,
2098
+ ): Promise<false | Exclude<SlashCommandResult, undefined>> {
2099
+ const parsed = parseSlashCommand(text);
2100
+ if (!parsed) return false;
2101
+ const command = BUILTIN_SLASH_COMMAND_LOOKUP.get(parsed.name);
2102
+ if (!command?.handle || command.localHeadless !== true) return false;
2103
+ if (parsed.args.length > 0 && !command.allowArgs) return false;
2104
+ return (await command.handle(parsed, runtime)) ?? { consumed: true };
2105
+ }
2024
2106
  /** Look up a unified spec by name or alias. Used by the ACP dispatcher. */
2025
2107
  export function lookupBuiltinSlashCommand(name: string): SlashCommandSpec | undefined {
2026
2108
  return BUILTIN_SLASH_COMMAND_LOOKUP.get(name);
@@ -0,0 +1,143 @@
1
+ import type { AuthCredentialSelector, AuthCredentialSnapshotEntry } from "@gajae-code/ai/core";
2
+ import { parseCliCredentialSelector } from "../../runtime-credential-selector";
3
+ import type { SlashCommandRuntime } from "../types";
4
+
5
+ /** Human-readable label for one stored OAuth credential row. */
6
+ function describeCredentialRow(entry: AuthCredentialSnapshotEntry): string {
7
+ if (entry.credential.type !== "oauth") return `id:${entry.id} (api key)`;
8
+ const email = entry.credential.email;
9
+ const accountId = entry.credential.accountId;
10
+ const label = email ?? accountId ?? `row ${entry.id}`;
11
+ return `id:${entry.id} — ${label}`;
12
+ }
13
+
14
+ function formatProviderName(provider: string): string {
15
+ return provider
16
+ .split(/[-_]/g)
17
+ .map(part => (part ? part[0].toUpperCase() + part.slice(1) : ""))
18
+ .join(" ");
19
+ }
20
+
21
+ /** Whether a stored OAuth snapshot row matches a credential selector. */
22
+ function selectorMatchesRow(selector: AuthCredentialSelector, entry: AuthCredentialSnapshotEntry): boolean {
23
+ if (entry.credential.type !== "oauth") return false;
24
+ switch (selector.kind) {
25
+ case "id":
26
+ return String(entry.id) === selector.value;
27
+ case "email":
28
+ return (
29
+ typeof entry.credential.email === "string" &&
30
+ entry.credential.email.toLowerCase() === selector.value.toLowerCase()
31
+ );
32
+ case "account":
33
+ return entry.credential.accountId === selector.value;
34
+ case "project":
35
+ return entry.credential.projectId === selector.value;
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Resolve which provider a bare (unqualified) `/credential <selector>`
41
+ * targets. Prefers the current session model's provider when it actually has
42
+ * a matching OAuth row (the common case: switching among a provider's own
43
+ * accounts while that provider is active). Falls back to scanning every
44
+ * provider's stored OAuth rows for a unique match, so `/credential
45
+ * email:me@example.com` still works when the selector uniquely matches a
46
+ * provider other than the active one. Ambiguous or absent matches return an
47
+ * explanatory string instead of a provider id.
48
+ */
49
+ function inferProvider(
50
+ runtime: SlashCommandRuntime,
51
+ oauthRows: AuthCredentialSnapshotEntry[],
52
+ selector: AuthCredentialSelector,
53
+ selectorRaw: string,
54
+ ): { provider: string } | { error: string } {
55
+ const currentProvider = runtime.session.model?.provider;
56
+ if (
57
+ currentProvider &&
58
+ oauthRows.some(entry => entry.provider === currentProvider && selectorMatchesRow(selector, entry))
59
+ ) {
60
+ return { provider: currentProvider };
61
+ }
62
+ const matchingProviders = [
63
+ ...new Set(oauthRows.filter(entry => selectorMatchesRow(selector, entry)).map(entry => entry.provider)),
64
+ ];
65
+ if (matchingProviders.length === 1) return { provider: matchingProviders[0]! };
66
+ if (oauthRows.length === 0) {
67
+ return { error: "No provider has any stored OAuth credentials to switch between." };
68
+ }
69
+ if (matchingProviders.length === 0) {
70
+ return { error: `No stored OAuth credential matches ${selector.kind}:${selector.value}.` };
71
+ }
72
+ return {
73
+ error: `"${selectorRaw}" is ambiguous across providers (${matchingProviders.join(", ")}). Use provider/${selectorRaw}.`,
74
+ };
75
+ }
76
+
77
+ /**
78
+ * List every provider's stored OAuth accounts, marking which row each
79
+ * currently-tracked session is using.
80
+ */
81
+ export async function buildCredentialListText(runtime: SlashCommandRuntime): Promise<string> {
82
+ const authStorage = runtime.session.modelRegistry.authStorage;
83
+ const snapshot = authStorage.exportSnapshot();
84
+ const oauthRows = snapshot.credentials.filter(entry => entry.credential.type === "oauth");
85
+ if (oauthRows.length === 0) {
86
+ return "No stored OAuth credentials. Use /login <provider> to add one.";
87
+ }
88
+ const grouped = new Map<string, AuthCredentialSnapshotEntry[]>();
89
+ for (const entry of oauthRows) {
90
+ const rows = grouped.get(entry.provider) ?? [];
91
+ rows.push(entry);
92
+ grouped.set(entry.provider, rows);
93
+ }
94
+ const lines = ["Stored accounts (/credential <selector> to switch this session):"];
95
+ for (const [provider, rows] of [...grouped.entries()].sort(([left], [right]) => left.localeCompare(right))) {
96
+ lines.push("", formatProviderName(provider));
97
+ const activeRowId = authStorage.getSessionCredentialRowId(provider, runtime.session.credentialSessionId);
98
+ for (const entry of rows) {
99
+ const active = entry.id === activeRowId ? " (active this session)" : "";
100
+ lines.push(`- ${describeCredentialRow(entry)}${active}`);
101
+ }
102
+ }
103
+ return lines.join("\n");
104
+ }
105
+
106
+ /**
107
+ * Switch the running session's stored OAuth credential for a provider,
108
+ * independent of quota state. Returns the confirmation/error text to show
109
+ * the user; never throws.
110
+ */
111
+ export async function switchSessionCredentialCommand(runtime: SlashCommandRuntime, args: string): Promise<string> {
112
+ const trimmed = args.trim();
113
+ if (!trimmed) return await buildCredentialListText(runtime);
114
+
115
+ let parsed: ReturnType<typeof parseCliCredentialSelector>;
116
+ try {
117
+ parsed = parseCliCredentialSelector(trimmed);
118
+ } catch {
119
+ return `Invalid selector "${trimmed}". Use email:name@example.com, id:15, account:<id>, project:<id>, or provider/<selector>.`;
120
+ }
121
+
122
+ const authStorage = runtime.session.modelRegistry.authStorage;
123
+ const snapshot = authStorage.exportSnapshot();
124
+ const oauthRows = snapshot.credentials.filter(entry => entry.credential.type === "oauth");
125
+
126
+ let provider = parsed.provider;
127
+ if (!provider) {
128
+ const inferred = inferProvider(runtime, oauthRows, parsed.selector, trimmed);
129
+ if ("error" in inferred) return inferred.error;
130
+ provider = inferred.provider;
131
+ }
132
+
133
+ try {
134
+ authStorage.switchSessionCredential(provider, runtime.session.credentialSessionId, parsed.selector);
135
+ } catch (error) {
136
+ return error instanceof Error ? error.message : String(error);
137
+ }
138
+
139
+ const rowId = authStorage.getSessionCredentialRowId(provider, runtime.session.credentialSessionId);
140
+ const matchedRow = oauthRows.find(entry => entry.id === rowId);
141
+ const label = matchedRow ? describeCredentialRow(matchedRow) : `${provider} (${trimmed})`;
142
+ return `Switched this session to ${label}. Takes effect on the next request to ${formatProviderName(provider)}.`;
143
+ }
@@ -351,7 +351,11 @@ async function handleListCommand(runtime: SlashCommandRuntime): Promise<SlashCom
351
351
  readMCPConfigFile(userPath),
352
352
  readMCPConfigFile(projectPath),
353
353
  ]);
354
- const disabledSet = new Set(await readDisabledServers(userPath));
354
+ const [userDisabled, projectDisabled] = await Promise.all([
355
+ readDisabledServers(userPath),
356
+ readDisabledServers(projectPath),
357
+ ]);
358
+ const disabledSet = new Set([...userDisabled, ...projectDisabled]);
355
359
  const entries: Array<{ name: string; config: MCPServerConfig; scope: string }> = [];
356
360
  for (const [name, config] of Object.entries(userConfig.mcpServers ?? {})) {
357
361
  entries.push({ name, config, scope: "user" });
@@ -367,7 +371,9 @@ async function handleListCommand(runtime: SlashCommandRuntime): Promise<SlashCom
367
371
  entries
368
372
  .map(({ name, config, scope }) => {
369
373
  const type = config.type ?? "stdio";
370
- const enabled = config.enabled !== false && !disabledSet.has(name) ? "enabled" : "disabled";
374
+ const disabled = config.enabled === false || disabledSet.has(name);
375
+ const autoloadOff = !disabled && config.autoload === false;
376
+ const status = disabled ? "disabled" : autoloadOff ? "autoload-off" : "autoload";
371
377
  let location: string | undefined;
372
378
  if (config.type === "http" || config.type === "sse") {
373
379
  // Strip query string and userinfo from URLs to avoid leaking
@@ -388,7 +394,7 @@ async function handleListCommand(runtime: SlashCommandRuntime): Promise<SlashCom
388
394
  } else {
389
395
  location = (config as { command: string }).command;
390
396
  }
391
- return `${name} | ${type} | ${enabled} | ${location ?? "(unknown)"} [${scope}]`;
397
+ return `${name} | ${type} | ${status} | ${location ?? "(unknown)"} [${scope}]`;
392
398
  })
393
399
  .join("\n"),
394
400
  );
@@ -1,12 +1,17 @@
1
- import type { UsageLimit, UsageReport } from "@gajae-code/ai/core";
1
+ import type { UsageLimit } from "@gajae-code/ai/core";
2
+ import { sanitizeText } from "@gajae-code/utils";
3
+ import {
4
+ type AccountInventoryRow,
5
+ buildAccountInventorySnapshot,
6
+ checkAccountInventory,
7
+ } from "../../session/account-inventory";
8
+ import { truncateHead } from "../../session/streaming-output";
2
9
  import type { SlashCommandRuntime } from "../types";
3
- import { formatDuration, renderAsciiBar } from "./format";
10
+ import { formatDuration } from "./format";
4
11
 
5
- function formatProviderName(provider: string): string {
6
- return provider
7
- .split(/[-_]/g)
8
- .map(part => (part ? part[0].toUpperCase() + part.slice(1) : ""))
9
- .join(" ");
12
+ function sanitizeAndTruncateOutput(text: string): string {
13
+ const sanitized = sanitizeText(text);
14
+ return truncateHead(sanitized, { maxBytes: 32_768, maxLines: 1_000 }).content;
10
15
  }
11
16
 
12
17
  function formatUsageAmount(limit: UsageLimit): string {
@@ -21,63 +26,40 @@ function formatUsageAmount(limit: UsageLimit): string {
21
26
  return `${usedText}${remainingText}`;
22
27
  }
23
28
 
24
- function formatUsageReportAccount(report: UsageReport, limit: UsageLimit, index: number): string {
25
- const email = report.metadata?.email;
26
- if (typeof email === "string" && email) return email;
27
- const accountId = report.metadata?.accountId ?? limit.scope.accountId;
28
- if (typeof accountId === "string" && accountId) return accountId;
29
- return `account ${index + 1}`;
29
+ function healthLabel(row: AccountInventoryRow): string {
30
+ if (row.disabled) return `disabled${row.disabledCause ? `: ${row.disabledCause}` : ""}`;
31
+ if (row.health.status === "ok") return "ok";
32
+ if (row.health.status === "failed") return `failed${row.health.reason ? `: ${row.health.reason}` : ""}`;
33
+ if (row.health.status === "unverifiable") return `unverifiable${row.health.reason ? `: ${row.health.reason}` : ""}`;
34
+ return "unknown";
30
35
  }
31
36
 
32
- function renderUsageReports(reports: UsageReport[], nowMs: number): string {
33
- const latestFetchedAt = Math.max(...reports.map(report => report.fetchedAt ?? 0));
34
- const lines = [`Usage${latestFetchedAt ? ` (${formatDuration(nowMs - latestFetchedAt)} ago)` : ""}`];
35
- const grouped = new Map<string, UsageReport[]>();
36
- for (const report of reports) {
37
- const providerReports = grouped.get(report.provider) ?? [];
38
- providerReports.push(report);
39
- grouped.set(report.provider, providerReports);
37
+ function renderAccountRows(rows: AccountInventoryRow[], nowMs: number, checked: boolean): string {
38
+ const lines = [`Accounts${checked ? " (checked)" : " (cache only)"}`];
39
+ if (rows.length === 0) {
40
+ lines.push("No configured accounts or API-key sources discovered.");
41
+ return lines.join("\n");
40
42
  }
41
-
42
- for (const [provider, providerReports] of [...grouped.entries()].sort(([left], [right]) =>
43
- left.localeCompare(right),
44
- )) {
45
- lines.push("", formatProviderName(provider));
46
- for (const report of providerReports) {
47
- if (report.limits.length === 0) {
48
- const email = typeof report.metadata?.email === "string" ? report.metadata.email : "account";
49
- lines.push(`- ${email}: no limits reported`);
50
- continue;
51
- }
52
- for (let index = 0; index < report.limits.length; index++) {
53
- const limit = report.limits[index]!;
54
- const window = limit.window?.label ?? limit.scope.windowId;
55
- const tier = limit.scope.tier ? ` (${limit.scope.tier})` : "";
56
- lines.push(`- ${limit.label}${tier}${window ? ` — ${window}` : ""}`);
57
- lines.push(` ${formatUsageReportAccount(report, limit, index)}: ${formatUsageAmount(limit)}`);
58
- lines.push(` ${renderAsciiBar(limit.amount.usedFraction)}`);
59
- if (limit.window?.resetsAt) lines.push(` resets in ${formatDuration(limit.window.resetsAt - nowMs)}`);
60
- if (limit.notes && limit.notes.length > 0) lines.push(` ${limit.notes.join(" • ")}`);
43
+ for (const row of rows) {
44
+ const identity = row.identityLabel ? ` — ${row.identityLabel}` : "";
45
+ const marker =
46
+ row.routing.marker === "active" ? " [active]" : row.routing.marker === "selected" ? " [selected]" : "";
47
+ const cache = row.usage
48
+ ? `, usage ${row.usage.freshness}${formatDuration(Math.max(0, nowMs - row.usage.fetchedAt)) ? ` ${formatDuration(Math.max(0, nowMs - row.usage.fetchedAt))} ago` : ""}`
49
+ : "";
50
+ lines.push(
51
+ `- ${row.id}: ${row.provider}/${row.credentialKind} (${row.sourceLabel})${identity}${marker} — ${healthLabel(row)}${cache}`,
52
+ );
53
+ if (row.usage?.report.limits.length) {
54
+ for (const limit of row.usage.report.limits.slice(0, 8)) {
55
+ lines.push(` ${sanitizeText(limit.label)}: ${formatUsageAmount(limit)}`);
61
56
  }
62
57
  }
63
58
  }
64
- return ["```", ...lines, "```"].join("\n");
59
+ return lines.join("\n");
65
60
  }
66
61
 
67
- /**
68
- * Build the `/usage` ACP-mode text. Prefers provider-reported limits when the
69
- * session exposes `fetchUsageReports`; otherwise falls back to the local
70
- * session-manager tallies.
71
- */
72
- export async function buildUsageReportText(runtime: SlashCommandRuntime): Promise<string> {
73
- const provider = runtime.session as SlashCommandRuntime["session"] & {
74
- fetchUsageReports?: () => Promise<UsageReport[] | null>;
75
- };
76
- if (provider.fetchUsageReports) {
77
- const reports = await provider.fetchUsageReports();
78
- if (reports && reports.length > 0) return renderUsageReports(reports, Date.now());
79
- }
80
-
62
+ function buildLegacyUsage(runtime: SlashCommandRuntime): string {
81
63
  const stats = runtime.session.sessionManager.getUsageStatistics();
82
64
  return [
83
65
  "Usage",
@@ -89,3 +71,26 @@ export async function buildUsageReportText(runtime: SlashCommandRuntime): Promis
89
71
  `Cost: $${stats.cost.toFixed(6)}`,
90
72
  ].join("\n");
91
73
  }
74
+
75
+ export interface UsageReportOptions {
76
+ check?: boolean;
77
+ }
78
+
79
+ /** Build `/usage`; plain mode is cache-only and never fetches or probes. */
80
+ export async function buildUsageReportText(
81
+ runtime: SlashCommandRuntime,
82
+ options: UsageReportOptions = {},
83
+ ): Promise<string> {
84
+ const session = runtime.session;
85
+ const modelRegistry = session.modelRegistry;
86
+ const input = {
87
+ authStorage: modelRegistry.authStorage,
88
+ modelRegistry,
89
+ sessionId: session.credentialSessionId ?? session.sessionId,
90
+ };
91
+ const snapshot = options.check ? await checkAccountInventory(input) : buildAccountInventorySnapshot(input);
92
+ const report = renderAccountRows(snapshot.rows, Date.now(), options.check === true);
93
+ const legacy = buildLegacyUsage(runtime);
94
+
95
+ return sanitizeAndTruncateOutput(`${report}\n\n${legacy}`);
96
+ }
@@ -34,11 +34,12 @@ export interface ParsedSlashCommand {
34
34
  * Result returned by a slash-command handler.
35
35
  *
36
36
  * - `void` / `undefined` — command was handled and consumed; no further input.
37
- * - `{ consumed: true }` — explicit equivalent of the above (ACP shape).
37
+ * - `{ consumed: true, exitCode?: number }` — explicit equivalent of the above;
38
+ * trusted local headless mode applies an optional non-zero process status.
38
39
  * - `{ prompt: string }` — command handled, pass `prompt` through as the new
39
40
  * user input (e.g. `/force <tool> <prompt>` keeps `<prompt>` as the message).
40
41
  */
41
- export type SlashCommandResult = undefined | { consumed: true } | { prompt: string };
42
+ export type SlashCommandResult = undefined | { consumed: true; exitCode?: number } | { prompt: string };
42
43
 
43
44
  /**
44
45
  * Runtime visible to slash-command handlers that run in text/ACP mode.
@@ -98,6 +99,10 @@ export interface SlashCommandSpec extends BuiltinSlashCommand {
98
99
  * not silently drop it from `available_commands_update`.
99
100
  */
100
101
  acpInputHint?: string;
102
+ /** Set false for trusted local commands that must never be advertised or dispatched through ACP. */
103
+ acp?: boolean;
104
+ /** Explicitly authorizes this handler in trusted local non-interactive print mode. */
105
+ localHeadless?: boolean;
101
106
  /**
102
107
  * Text/ACP-mode handler. The same body is invoked from the ACP dispatcher
103
108
  * and, via the TUI adapter, when no `handleTui` override is provided.
@@ -24,6 +24,7 @@ import {
24
24
  type ServiceTier,
25
25
  } from "@gajae-code/ai/core";
26
26
  import { type JsonSchemaValidationIssue, validateJsonSchemaValue } from "@gajae-code/ai/utils/schema";
27
+ import * as canonicalSdk from "@gajae-code/coding-agent/sdk";
27
28
  import { logger, prompt, untilAborted } from "@gajae-code/utils";
28
29
  import { AsyncJobManager } from "../async";
29
30
  import { ModelRegistry } from "../config/model-registry";
@@ -42,7 +43,7 @@ import subagentSystemPromptTemplate from "../prompts/system/subagent-system-prom
42
43
  import subagentUserPromptTemplate from "../prompts/system/subagent-user-prompt.md" with { type: "text" };
43
44
  import submitReminderTemplate from "../prompts/system/subagent-yield-reminder.md" with { type: "text" };
44
45
  import { AgentRegistry } from "../registry/agent-registry";
45
- import { createAgentSession, discoverAuthStorage } from "../sdk";
46
+ import { discoverAuthStorage } from "../sdk";
46
47
  import type { AgentSession, AgentSessionEvent, ForkContextSeed } from "../session/agent-session";
47
48
  import type { ArtifactManager } from "../session/artifacts";
48
49
  import type { AuthStorage } from "../session/auth-storage";
@@ -269,6 +270,15 @@ export interface ExecutorOptions {
269
270
  */
270
271
  parentArtifactManager?: ArtifactManager;
271
272
  managedPersistence?: ManagedTaskPersistence;
273
+ /**
274
+ * The parent session's ENDPOINT-owned AsyncJobManager (resolved by the
275
+ * TaskTool via forEndpoint(sessionId) ?? instance()). Model metadata and
276
+ * live-handle state for THIS subagent are recorded in the SAME manager the
277
+ * task job runs in — with concurrent top-level sessions the process-global
278
+ * instance belongs to a different session and would surface this subagent
279
+ * under the wrong session's record (review thread P1).
280
+ */
281
+ asyncJobManager?: AsyncJobManager;
272
282
  parentHindsightSessionState?: HindsightSessionState;
273
283
  /**
274
284
  * Parent agent's OpenTelemetry configuration. When defined, the subagent's
@@ -1560,7 +1570,7 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
1560
1570
  // Record which model the subagent actually runs on (and any auth fallback,
1561
1571
  // see #985) so the subagent panel can surface it to the user.
1562
1572
  if (model) {
1563
- AsyncJobManager.instance()?.updateSubagentModel?.(options.subagentId ?? id, {
1573
+ (options.asyncJobManager ?? AsyncJobManager.instance())?.updateSubagentModel?.(options.subagentId ?? id, {
1564
1574
  requestedModel: modelSubstitutionWarning?.requested ?? resolvedModelString,
1565
1575
  effectiveModel: resolvedModelString,
1566
1576
  modelFellBack: authFallbackUsed === true,
@@ -1676,7 +1686,7 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
1676
1686
  }
1677
1687
 
1678
1688
  const { session } = await awaitAbortable(
1679
- createAgentSession({
1689
+ canonicalSdk.createAgentSession({
1680
1690
  cwd: worktree ?? cwd,
1681
1691
  authStorage,
1682
1692
  modelRegistry,
@@ -1738,6 +1748,7 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
1738
1748
  },
1739
1749
  parentHindsightSessionState: options.parentHindsightSessionState,
1740
1750
  parentTaskPrefix: id,
1751
+ inheritedAsyncJobManager: options.asyncJobManager,
1741
1752
  inheritedMcpManager: options.parentMcpManager,
1742
1753
  agentId: id,
1743
1754
  agentDisplayName: agent.name,
@@ -1761,7 +1772,7 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
1761
1772
  session.seedDefaultFallbackResolution(activeIndex ?? 0, skips);
1762
1773
  }
1763
1774
  const liveSubagentId = options.subagentId ?? id;
1764
- const manager = AsyncJobManager.instance();
1775
+ const manager = options.asyncJobManager ?? AsyncJobManager.instance();
1765
1776
  if (manager) {
1766
1777
  manager.registerLiveHandle(liveSubagentId, {
1767
1778
  requestPause: () => {
@@ -1964,12 +1975,20 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
1964
1975
  if (event.type === "model_fallback_switched") {
1965
1976
  activeProviderModelString = event.to;
1966
1977
  progress.fastMode = isFastForModel(session.model);
1967
- AsyncJobManager.instance()?.updateSubagentModel?.(options.subagentId ?? id, {
1968
- requestedModel: modelSubstitutionWarning?.requested ?? resolvedModelString,
1969
- effectiveModel: event.to,
1970
- modelFellBack: true,
1971
- fastMode: progress.fastMode,
1972
- });
1978
+ // Keep the fallback metadata on the SAME manager the initial
1979
+ // update used: another session may have become the
1980
+ // process-global instance, and writing to it would leave this
1981
+ // session's subagent metadata stale or overwrite an unrelated
1982
+ // same-ID record (review thread P2).
1983
+ (options.asyncJobManager ?? AsyncJobManager.instance())?.updateSubagentModel?.(
1984
+ options.subagentId ?? id,
1985
+ {
1986
+ requestedModel: modelSubstitutionWarning?.requested ?? resolvedModelString,
1987
+ effectiveModel: event.to,
1988
+ modelFellBack: true,
1989
+ fastMode: progress.fastMode,
1990
+ },
1991
+ );
1973
1992
  scheduleProgress(true);
1974
1993
  forwardSubagentEvent(event);
1975
1994
  return;
@@ -2108,7 +2127,7 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
2108
2127
  if (exitCode === 0) exitCode = 1;
2109
2128
  }
2110
2129
  sessionAbortController.abort();
2111
- AsyncJobManager.instance()?.removeLiveHandle(options.subagentId ?? id);
2130
+ (options.asyncJobManager ?? AsyncJobManager.instance())?.removeLiveHandle(options.subagentId ?? id);
2112
2131
  if (unsubscribe) {
2113
2132
  try {
2114
2133
  unsubscribe();