@gajae-code/coding-agent 0.18.11 → 0.19.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 (462) hide show
  1. package/CHANGELOG.md +760 -0
  2. package/dist/types/async/job-manager.d.ts +7 -3
  3. package/dist/types/async/result-formatting.d.ts +2 -0
  4. package/dist/types/autoresearch/git.d.ts +1 -1
  5. package/dist/types/capability/fs.d.ts +2 -2
  6. package/dist/types/capability/rule.d.ts +7 -2
  7. package/dist/types/cli/accounts-cli.d.ts +2 -2
  8. package/dist/types/cli/append-system-prompt.d.ts +6 -0
  9. package/dist/types/cli/args.d.ts +7 -2
  10. package/dist/types/cli/customize-doctor-precedence.d.ts +16 -0
  11. package/dist/types/cli/customize-doctor.d.ts +4 -3
  12. package/dist/types/cli/doctor/install-repairs.d.ts +4 -1
  13. package/dist/types/cli/install-activation.d.ts +10 -4
  14. package/dist/types/cli/public-command-errors.d.ts +2 -0
  15. package/dist/types/cli/root-flags.d.ts +0 -12
  16. package/dist/types/cli/update-cli.d.ts +21 -3
  17. package/dist/types/cli-main.d.ts +0 -6
  18. package/dist/types/cli-ordinary.d.ts +2 -2
  19. package/dist/types/commands/accounts.d.ts +2 -1
  20. package/dist/types/commands/launch.d.ts +0 -6
  21. package/dist/types/commands/migrate.d.ts +1 -1
  22. package/dist/types/commands/sdk.d.ts +13 -0
  23. package/dist/types/commit/changelog/index.d.ts +1 -0
  24. package/dist/types/commit/map-reduce/index.d.ts +4 -4
  25. package/dist/types/config/autorouting-tier-map.d.ts +53 -1
  26. package/dist/types/config/config-hot-reload-trust.d.ts +12 -0
  27. package/dist/types/config/config-hot-reload.d.ts +44 -0
  28. package/dist/types/config/file-lock.d.ts +52 -3
  29. package/dist/types/config/model-discovery-manager.d.ts +2 -0
  30. package/dist/types/config/model-profile-activation.d.ts +79 -9
  31. package/dist/types/config/model-registry.d.ts +72 -8
  32. package/dist/types/config/model-resolver.d.ts +7 -4
  33. package/dist/types/config/models-config-schema.d.ts +10 -0
  34. package/dist/types/config/settings-schema.d.ts +57 -4
  35. package/dist/types/config/settings.d.ts +33 -1
  36. package/dist/types/coordinator-mcp/server.d.ts +4 -0
  37. package/dist/types/customization/import.d.ts +2 -0
  38. package/dist/types/customization/types.d.ts +1 -1
  39. package/dist/types/dap/config.d.ts +8 -4
  40. package/dist/types/dap/session.d.ts +11 -2
  41. package/dist/types/debug/system-info.d.ts +6 -1
  42. package/dist/types/discovery/helpers.d.ts +7 -2
  43. package/dist/types/discovery/mcp-compat.d.ts +3 -1
  44. package/dist/types/edit/index.d.ts +5 -0
  45. package/dist/types/edit/modes/patch.d.ts +14 -0
  46. package/dist/types/edit/modes/replace.d.ts +3 -0
  47. package/dist/types/eval/py/runtime.d.ts +9 -0
  48. package/dist/types/exec/bash-executor.d.ts +12 -0
  49. package/dist/types/export/ttsr.d.ts +19 -0
  50. package/dist/types/extensibility/extensions/types.d.ts +5 -1
  51. package/dist/types/extensibility/slash-commands.d.ts +1 -0
  52. package/dist/types/gjc-runtime/managed-owner-admission.d.ts +3 -0
  53. package/dist/types/gjc-runtime/ralplan-current-final.d.ts +54 -0
  54. package/dist/types/gjc-runtime/ralplan-runtime.d.ts +5 -0
  55. package/dist/types/gjc-runtime/session-state-lock.d.ts +2 -0
  56. package/dist/types/gjc-runtime/state-runtime.d.ts +0 -2
  57. package/dist/types/gjc-runtime/tmux-sessions.d.ts +24 -0
  58. package/dist/types/gjc-runtime/ultragoal-change-set.d.ts +6 -0
  59. package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +1 -0
  60. package/dist/types/harness-control-plane/receipt-spool.d.ts +4 -0
  61. package/dist/types/hindsight/content.d.ts +5 -6
  62. package/dist/types/internal-urls/types.d.ts +2 -0
  63. package/dist/types/lsp/clients/swiftlint-client.d.ts +0 -4
  64. package/dist/types/main.d.ts +23 -18
  65. package/dist/types/migrate/action-planner.d.ts +10 -1
  66. package/dist/types/migrate/adapters/codex.d.ts +2 -1
  67. package/dist/types/migrate/adapters/index.d.ts +42 -1
  68. package/dist/types/migrate/executor.d.ts +3 -1
  69. package/dist/types/migrate/hook-module.d.ts +23 -0
  70. package/dist/types/migrate/report.d.ts +2 -1
  71. package/dist/types/migrate/types.d.ts +82 -3
  72. package/dist/types/modes/components/agent-dashboard.d.ts +1 -1
  73. package/dist/types/modes/components/model-selector.d.ts +43 -0
  74. package/dist/types/modes/components/settings-selector.d.ts +6 -0
  75. package/dist/types/modes/controllers/selector-controller.d.ts +2 -0
  76. package/dist/types/modes/prompt-suggestion-controller.d.ts +1 -1
  77. package/dist/types/modes/theme/theme.d.ts +1 -0
  78. package/dist/types/modes/utils/host-status.d.ts +15 -11
  79. package/dist/types/runtime-mcp/content-limits.d.ts +4 -0
  80. package/dist/types/runtime-mcp/manager.d.ts +7 -0
  81. package/dist/types/runtime-mcp/plugin-mcp-name-filter.d.ts +22 -0
  82. package/dist/types/runtime-mcp/project-host-values.d.ts +11 -5
  83. package/dist/types/runtime-mcp/tool-bridge.d.ts +4 -0
  84. package/dist/types/sdk/broker/broker-exit.d.ts +3 -3
  85. package/dist/types/sdk/broker/broker.d.ts +29 -2
  86. package/dist/types/sdk/broker/daemon-entry.d.ts +11 -1
  87. package/dist/types/sdk/broker/doctor-restart.d.ts +1 -1
  88. package/dist/types/sdk/broker/ensure.d.ts +141 -9
  89. package/dist/types/sdk/broker/hop.d.ts +45 -0
  90. package/dist/types/sdk/broker/lifecycle-ledger.d.ts +18 -10
  91. package/dist/types/sdk/broker/lifecycle.d.ts +22 -0
  92. package/dist/types/sdk/broker/lock-host-identity.d.ts +5 -0
  93. package/dist/types/sdk/broker/session-index.d.ts +6 -1
  94. package/dist/types/sdk/broker/transport.d.ts +2 -0
  95. package/dist/types/sdk/bus/chat-command-policy.d.ts +2 -1
  96. package/dist/types/sdk/bus/index.d.ts +44 -0
  97. package/dist/types/sdk/bus/reconciliation-store.d.ts +10 -0
  98. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +9 -1
  99. package/dist/types/sdk/bus/telegram-daemon.d.ts +2 -0
  100. package/dist/types/sdk/bus/threaded-render.d.ts +2 -1
  101. package/dist/types/sdk/cli/session-cli.d.ts +0 -1
  102. package/dist/types/sdk/host/control/operations.d.ts +5 -1
  103. package/dist/types/sdk/host/events.d.ts +4 -0
  104. package/dist/types/sdk/host/host.d.ts +2 -1
  105. package/dist/types/sdk/host/prompt-image-upload.d.ts +43 -0
  106. package/dist/types/sdk/host/session-runtime.d.ts +40 -8
  107. package/dist/types/sdk/host/surface-policy.d.ts +2 -1
  108. package/dist/types/sdk/lifecycle/service.d.ts +12 -0
  109. package/dist/types/sdk/prompt-deadline-flush.d.ts +42 -4
  110. package/dist/types/sdk/prompt-deadline-manager.d.ts +2 -0
  111. package/dist/types/sdk/prompt-status.d.ts +11 -4
  112. package/dist/types/sdk/protocol/adapter-validation.d.ts +10 -4
  113. package/dist/types/sdk/reconciliation-extensions.d.ts +1 -1
  114. package/dist/types/sdk/session-list.d.ts +1 -1
  115. package/dist/types/session/agent-session.d.ts +107 -9
  116. package/dist/types/session/internal/managed-session-scope.d.ts +2 -2
  117. package/dist/types/session/internal/managed-session-storage.d.ts +1 -1
  118. package/dist/types/session/internal/native-publish-outcome.d.ts +1 -1
  119. package/dist/types/session/messages.d.ts +5 -1
  120. package/dist/types/session/session-manager.d.ts +29 -3
  121. package/dist/types/session/startup-auth-config.d.ts +24 -2
  122. package/dist/types/session/streaming-output.d.ts +11 -0
  123. package/dist/types/session/terminal-abort.d.ts +3 -1
  124. package/dist/types/session-import/service.d.ts +1 -1
  125. package/dist/types/skill-state/workflow-mutation-guard.d.ts +20 -4
  126. package/dist/types/slash-commands/helpers/mcp.d.ts +5 -0
  127. package/dist/types/slash-commands/helpers/provider-auth-status.d.ts +8 -0
  128. package/dist/types/ssh/ssh-executor.d.ts +8 -1
  129. package/dist/types/system-prompt.d.ts +3 -2
  130. package/dist/types/task/executor.d.ts +19 -2
  131. package/dist/types/task/role-body.d.ts +11 -0
  132. package/dist/types/tools/ast-edit-write-path.d.ts +10 -0
  133. package/dist/types/tools/atomic-file-write.d.ts +9 -7
  134. package/dist/types/tools/awaiting-input.d.ts +28 -0
  135. package/dist/types/tools/bash-allowed-prefixes.d.ts +17 -0
  136. package/dist/types/tools/bash-skill-urls.d.ts +4 -0
  137. package/dist/types/tools/bash.d.ts +7 -0
  138. package/dist/types/tools/descriptors.d.ts +15 -2
  139. package/dist/types/tools/fetch.d.ts +7 -1
  140. package/dist/types/tools/index.d.ts +2 -0
  141. package/dist/types/tools/irc.d.ts +5 -3
  142. package/dist/types/tools/python.d.ts +1 -1
  143. package/dist/types/tools/report-issue.d.ts +41 -0
  144. package/dist/types/tools/subagent.d.ts +23 -0
  145. package/dist/types/tools/tmux-self-injection-guard.d.ts +2 -0
  146. package/dist/types/tools/ultragoal-ask-guard.d.ts +1 -1
  147. package/dist/types/tools/write.d.ts +2 -0
  148. package/dist/types/utils/file-mentions.d.ts +5 -0
  149. package/dist/types/utils/image-limits.d.ts +7 -0
  150. package/dist/types/utils/image-loading.d.ts +0 -1
  151. package/dist/types/utils/open.d.ts +0 -1
  152. package/dist/types/utils/pasted-image-loading.d.ts +1 -5
  153. package/dist/types/utils/prompt-suggestion.d.ts +2 -2
  154. package/dist/types/utils/shell-snapshot.d.ts +2 -0
  155. package/dist/types/utils/title-generator.d.ts +13 -3
  156. package/dist/types/web/scrapers/types.d.ts +8 -1
  157. package/dist/types/web/search/providers/codex.d.ts +6 -7
  158. package/dist/types/web/search/providers/insane.d.ts +7 -1
  159. package/dist/types/web/search/providers/searxng.d.ts +5 -0
  160. package/package.json +10 -9
  161. package/scripts/acp-conformance-agent.ts +12 -2
  162. package/scripts/build-binary.ts +2 -1
  163. package/scripts/capture-subagent-compact-panel-showcase.ts +105 -0
  164. package/scripts/generate-docs-index.ts +8 -1
  165. package/scripts/generate-sdk-operation-inventory.ts +38 -4
  166. package/src/async/job-manager.ts +356 -56
  167. package/src/async/result-formatting.ts +40 -0
  168. package/src/autoresearch/git.ts +9 -2
  169. package/src/autoresearch/prompts/prompt-setup.md +1 -1
  170. package/src/capability/fs.ts +58 -22
  171. package/src/capability/index.ts +2 -2
  172. package/src/capability/rule.ts +11 -2
  173. package/src/cli/accounts-cli.ts +176 -8
  174. package/src/cli/append-system-prompt.ts +12 -0
  175. package/src/cli/args.ts +11 -7
  176. package/src/cli/auth-broker-cli.ts +21 -11
  177. package/src/cli/customize-doctor-precedence.ts +31 -0
  178. package/src/cli/customize-doctor.ts +49 -39
  179. package/src/cli/doctor/install-repairs.ts +35 -5
  180. package/src/cli/fast-help.ts +1 -3
  181. package/src/cli/install-activation.ts +47 -4
  182. package/src/cli/migrate-cli.ts +19 -6
  183. package/src/cli/public-command-errors.ts +6 -0
  184. package/src/cli/root-flags.ts +2 -4
  185. package/src/cli/stats-cli.ts +9 -5
  186. package/src/cli/update-cli.ts +471 -13
  187. package/src/cli-ordinary.ts +7 -2
  188. package/src/commands/accounts.ts +10 -5
  189. package/src/commands/harness.ts +25 -15
  190. package/src/commands/migrate.ts +3 -3
  191. package/src/commands/sdk.ts +277 -50
  192. package/src/commands/ultragoal.ts +16 -8
  193. package/src/commit/agentic/agent.ts +6 -6
  194. package/src/commit/analysis/conventional.ts +14 -5
  195. package/src/commit/changelog/index.ts +39 -1
  196. package/src/commit/map-reduce/index.ts +7 -7
  197. package/src/commit/message.ts +10 -3
  198. package/src/commit/pipeline.ts +12 -12
  199. package/src/config/autorouting-tier-map.ts +50 -1
  200. package/src/config/config-file.ts +106 -3
  201. package/src/config/config-hot-reload-trust.ts +148 -0
  202. package/src/config/config-hot-reload.ts +742 -0
  203. package/src/config/file-lock.ts +1615 -328
  204. package/src/config/keybindings.ts +154 -7
  205. package/src/config/model-bindings-applier.ts +85 -47
  206. package/src/config/model-discovery-manager.ts +10 -0
  207. package/src/config/model-profile-activation.ts +889 -148
  208. package/src/config/model-registry.ts +1706 -205
  209. package/src/config/model-resolver.ts +52 -22
  210. package/src/config/models-config-schema.ts +6 -0
  211. package/src/config/settings-schema.ts +73 -4
  212. package/src/config/settings.ts +460 -24
  213. package/src/coordinator-mcp/policy.ts +26 -1
  214. package/src/coordinator-mcp/server.ts +37 -2
  215. package/src/crash/sanitize.ts +7 -1
  216. package/src/customization/import.ts +279 -8
  217. package/src/customization/inventory.ts +24 -8
  218. package/src/customization/types.ts +1 -0
  219. package/src/dap/client.ts +3 -2
  220. package/src/dap/config.ts +31 -11
  221. package/src/dap/defaults.json +1 -1
  222. package/src/dap/session.ts +161 -36
  223. package/src/debug/crash-diagnostics.ts +89 -6
  224. package/src/debug/report-bundle.ts +90 -2
  225. package/src/debug/system-info.ts +8 -3
  226. package/src/defaults/gjc/extensions/grok-cli-vendor/src/shared/base-url.ts +21 -7
  227. package/src/discovery/agents-md.ts +1 -1
  228. package/src/discovery/builtin.ts +4 -3
  229. package/src/discovery/helpers.ts +25 -16
  230. package/src/discovery/mcp-compat.ts +120 -17
  231. package/src/edit/apply-patch/index.ts +12 -1
  232. package/src/edit/index.ts +204 -22
  233. package/src/edit/modes/patch.ts +214 -8
  234. package/src/edit/modes/replace.ts +136 -0
  235. package/src/eval/js/context-manager.ts +29 -3
  236. package/src/eval/js/worker-entry.ts +51 -18
  237. package/src/eval/py/executor.ts +14 -4
  238. package/src/eval/py/runner.py +144 -5
  239. package/src/eval/py/runtime.ts +44 -4
  240. package/src/exec/bash-executor.ts +81 -4
  241. package/src/exec/bash-shell-guardian.ts +4 -1
  242. package/src/exec/bash-shell-supervisor.ts +8 -4
  243. package/src/exec/isolated-shell.ts +5 -1
  244. package/src/exec/non-interactive-env.ts +0 -1
  245. package/src/export/html/index.ts +86 -6
  246. package/src/export/ttsr.ts +176 -1
  247. package/src/extensibility/custom-tools/wrapper.ts +3 -1
  248. package/src/extensibility/extensions/loader.ts +10 -1
  249. package/src/extensibility/extensions/ouroboros-ooo-bridge.ts +63 -1
  250. package/src/extensibility/extensions/types.ts +5 -1
  251. package/src/extensibility/hooks/loader.ts +10 -2
  252. package/src/extensibility/plugins/marketplace/fetcher.ts +2 -2
  253. package/src/extensibility/plugins/marketplace/manager.ts +36 -10
  254. package/src/extensibility/slash-commands.ts +5 -0
  255. package/src/gjc-runtime/gc-runtime.ts +37 -7
  256. package/src/gjc-runtime/launch-tmux.ts +30 -15
  257. package/src/gjc-runtime/launch-worktree.test.ts +148 -0
  258. package/src/gjc-runtime/launch-worktree.ts +101 -14
  259. package/src/gjc-runtime/managed-owner-admission.ts +46 -2
  260. package/src/gjc-runtime/ralplan-current-final.ts +294 -0
  261. package/src/gjc-runtime/ralplan-runtime.ts +95 -1
  262. package/src/gjc-runtime/session-resolution.ts +38 -6
  263. package/src/gjc-runtime/session-state-lock.ts +59 -14
  264. package/src/gjc-runtime/state-runtime.ts +23 -19
  265. package/src/gjc-runtime/state-writer.ts +109 -5
  266. package/src/gjc-runtime/tmux-sessions.ts +93 -13
  267. package/src/gjc-runtime/ultragoal-change-set.ts +90 -11
  268. package/src/gjc-runtime/ultragoal-guard.ts +9 -1
  269. package/src/gjc-runtime/ultragoal-runtime.ts +15 -5
  270. package/src/harness-control-plane/finalize.ts +11 -0
  271. package/src/harness-control-plane/receipt-spool.ts +105 -28
  272. package/src/harness-control-plane/storage.ts +124 -6
  273. package/src/hindsight/content.ts +116 -16
  274. package/src/hindsight/mental-models.ts +22 -10
  275. package/src/hindsight/state.ts +7 -4
  276. package/src/hooks/native-skill-hook.ts +17 -12
  277. package/src/internal-urls/artifact-protocol.ts +3 -1
  278. package/src/internal-urls/docs-index.generated.ts +23 -22
  279. package/src/internal-urls/local-protocol.ts +167 -8
  280. package/src/internal-urls/types.ts +2 -0
  281. package/src/lsp/client.ts +2 -1
  282. package/src/lsp/clients/biome-client.ts +2 -0
  283. package/src/lsp/clients/swiftlint-client.ts +2 -0
  284. package/src/lsp/index.ts +29 -0
  285. package/src/lsp/workspace-path.ts +23 -0
  286. package/src/main.ts +330 -92
  287. package/src/memories/index.ts +25 -2
  288. package/src/migrate/action-planner.ts +574 -2
  289. package/src/migrate/adapters/claude-code.ts +162 -5
  290. package/src/migrate/adapters/codex.ts +77 -7
  291. package/src/migrate/adapters/index.ts +258 -5
  292. package/src/migrate/adapters/opencode.ts +10 -1
  293. package/src/migrate/executor.ts +222 -7
  294. package/src/migrate/hook-module.ts +193 -0
  295. package/src/migrate/report.ts +63 -2
  296. package/src/migrate/types.ts +84 -4
  297. package/src/modes/DESIGN.md +51 -0
  298. package/src/modes/acp/acp-agent.ts +10 -1
  299. package/src/modes/acp/permission-mode.ts +18 -1
  300. package/src/modes/components/agent-dashboard.ts +20 -4
  301. package/src/modes/components/assistant-message.ts +55 -1
  302. package/src/modes/components/customization/customization-dashboard.ts +7 -0
  303. package/src/modes/components/customization/import-wizard.ts +29 -3
  304. package/src/modes/components/model-selector.ts +157 -103
  305. package/src/modes/components/settings-selector.ts +103 -37
  306. package/src/modes/components/welcome.ts +3 -1
  307. package/src/modes/controllers/command-controller.ts +300 -9
  308. package/src/modes/controllers/event-controller.ts +1 -1
  309. package/src/modes/controllers/extension-ui-controller.ts +31 -1
  310. package/src/modes/controllers/goal-mode-controller.ts +79 -10
  311. package/src/modes/controllers/input-controller.ts +2 -0
  312. package/src/modes/controllers/plan-mode-controller.ts +66 -11
  313. package/src/modes/controllers/runtime-mcp-command-controller.ts +7 -6
  314. package/src/modes/controllers/selector-controller.ts +76 -7
  315. package/src/modes/interactive-mode.ts +123 -4
  316. package/src/modes/prompt-suggestion-controller.ts +1 -1
  317. package/src/modes/runtime-init.ts +5 -1
  318. package/src/modes/theme/theme.ts +15 -0
  319. package/src/modes/utils/host-status.ts +21 -10
  320. package/src/prompts/agent-fragments/browser-aside.md +2 -2
  321. package/src/prompts/system/irc-incoming.md +3 -1
  322. package/src/prompts/tools/debug.md +1 -1
  323. package/src/prompts/tools/irc.md +1 -1
  324. package/src/prompts/tools/read.md +1 -1
  325. package/src/prompts/tools/report-issue.md +13 -0
  326. package/src/prompts/tools/task.md +1 -1
  327. package/src/runtime-credential-selector.ts +2 -2
  328. package/src/runtime-mcp/content-limits.ts +7 -0
  329. package/src/runtime-mcp/manager-pool.test.ts +5 -4
  330. package/src/runtime-mcp/manager.ts +40 -3
  331. package/src/runtime-mcp/oauth-flow.ts +32 -6
  332. package/src/runtime-mcp/plugin-mcp-name-filter.ts +62 -0
  333. package/src/runtime-mcp/project-host-values.ts +12 -8
  334. package/src/runtime-mcp/render.ts +16 -1
  335. package/src/runtime-mcp/tool-bridge.ts +194 -21
  336. package/src/runtime-mcp/transports/stdio.ts +2 -1
  337. package/src/sdk/broker/broker-exit.ts +10 -5
  338. package/src/sdk/broker/broker.ts +484 -85
  339. package/src/sdk/broker/daemon-entry.ts +338 -116
  340. package/src/sdk/broker/doctor-restart.ts +2 -1
  341. package/src/sdk/broker/ensure.ts +1214 -268
  342. package/src/sdk/broker/hop.ts +286 -0
  343. package/src/sdk/broker/lifecycle-ledger.ts +38 -11
  344. package/src/sdk/broker/lifecycle.ts +102 -6
  345. package/src/sdk/broker/lock-host-identity.ts +29 -0
  346. package/src/sdk/broker/session-index.ts +91 -16
  347. package/src/sdk/broker/transport.ts +17 -1
  348. package/src/sdk/bus/chat-command-policy.ts +16 -3
  349. package/src/sdk/bus/chat-daemon-control.ts +2 -2
  350. package/src/sdk/bus/index.ts +460 -35
  351. package/src/sdk/bus/reconciliation-store.ts +201 -8
  352. package/src/sdk/bus/session-control.ts +2 -0
  353. package/src/sdk/bus/slack-daemon.ts +105 -9
  354. package/src/sdk/bus/telegram-daemon-contract.ts +9 -1
  355. package/src/sdk/bus/telegram-daemon.ts +10 -2
  356. package/src/sdk/bus/threaded-render.ts +20 -1
  357. package/src/sdk/cli/session-cli.ts +23 -6
  358. package/src/sdk/host/control/dispatch.ts +13 -1
  359. package/src/sdk/host/control/operations.ts +10 -1
  360. package/src/sdk/host/events.ts +67 -4
  361. package/src/sdk/host/host.ts +8 -2
  362. package/src/sdk/host/prompt-image-upload.ts +438 -0
  363. package/src/sdk/host/sdk-surface-parity.test.ts +15 -0
  364. package/src/sdk/host/session-runtime.test.ts +1737 -129
  365. package/src/sdk/host/session-runtime.ts +684 -83
  366. package/src/sdk/host/surface-policy.ts +4 -0
  367. package/src/sdk/host/websocket-transport.lifecycle.test.ts +90 -2
  368. package/src/sdk/host/websocket-transport.ts +19 -7
  369. package/src/sdk/lifecycle/service.ts +15 -1
  370. package/src/sdk/prompt-deadline-flush.ts +78 -5
  371. package/src/sdk/prompt-deadline-manager.ts +68 -14
  372. package/src/sdk/prompt-status.ts +6 -4
  373. package/src/sdk/protocol/adapter-validation.ts +81 -12
  374. package/src/sdk/protocol/operation-inventory.generated.json +261 -2
  375. package/src/sdk/protocol/operation-registry.ts +33 -3
  376. package/src/sdk/reconciliation-extensions.ts +1 -0
  377. package/src/sdk/session-list.ts +1 -0
  378. package/src/sdk/session.ts +237 -97
  379. package/src/session/agent-session.ts +2726 -479
  380. package/src/session/history-storage.ts +182 -12
  381. package/src/session/internal/managed-session-scope.ts +173 -57
  382. package/src/session/internal/managed-session-storage.ts +85 -12
  383. package/src/session/internal/native-publish-outcome.ts +5 -1
  384. package/src/session/messages.ts +47 -6
  385. package/src/session/session-manager.ts +326 -19
  386. package/src/session/startup-auth-config.ts +116 -8
  387. package/src/session/streaming-output.ts +262 -4
  388. package/src/session/terminal-abort.ts +14 -2
  389. package/src/session-import/redact.ts +53 -2
  390. package/src/session-import/service.ts +1 -0
  391. package/src/skill-state/workflow-mutation-guard.ts +2145 -206
  392. package/src/slash-commands/builtin-registry.ts +21 -6
  393. package/src/slash-commands/helpers/credential-switch.ts +10 -5
  394. package/src/slash-commands/helpers/mcp.ts +11 -3
  395. package/src/slash-commands/helpers/provider-auth-status.ts +456 -0
  396. package/src/ssh/ssh-executor.ts +9 -2
  397. package/src/stt/recorder.ts +26 -9
  398. package/src/system-prompt.ts +61 -16
  399. package/src/task/executor.ts +115 -20
  400. package/src/task/index.ts +389 -175
  401. package/src/task/role-body.ts +84 -0
  402. package/src/task/token-log-mode.test.ts +162 -0
  403. package/src/task/token-log.ts +91 -2
  404. package/src/tools/archive-reader.ts +650 -37
  405. package/src/tools/ask.ts +1 -0
  406. package/src/tools/ast-edit-write-path.ts +64 -0
  407. package/src/tools/ast-edit.ts +18 -1
  408. package/src/tools/ast-grep.ts +7 -2
  409. package/src/tools/atomic-file-write.ts +46 -15
  410. package/src/tools/auto-generated-guard.ts +15 -3
  411. package/src/tools/awaiting-input.ts +114 -0
  412. package/src/tools/bash-allowed-prefixes.ts +214 -6
  413. package/src/tools/bash-interactive.ts +14 -2
  414. package/src/tools/bash-skill-urls.ts +58 -5
  415. package/src/tools/bash.ts +113 -26
  416. package/src/tools/browser/tab-worker.ts +39 -13
  417. package/src/tools/browser.ts +17 -7
  418. package/src/tools/cron.ts +10 -1
  419. package/src/tools/debug.ts +16 -8
  420. package/src/tools/descriptors.test.ts +44 -0
  421. package/src/tools/descriptors.ts +50 -6
  422. package/src/tools/eval.ts +15 -0
  423. package/src/tools/fetch.ts +93 -4
  424. package/src/tools/gh.ts +27 -12
  425. package/src/tools/image-gen.ts +20 -6
  426. package/src/tools/index.ts +2 -0
  427. package/src/tools/irc.ts +5 -3
  428. package/src/tools/monitor.ts +9 -1
  429. package/src/tools/output-meta.ts +74 -5
  430. package/src/tools/python.ts +1 -1
  431. package/src/tools/read.ts +26 -37
  432. package/src/tools/recipe/runner.ts +23 -12
  433. package/src/tools/render-utils.ts +2 -2
  434. package/src/tools/report-issue.ts +184 -0
  435. package/src/tools/search.ts +3 -2
  436. package/src/tools/ssh.ts +274 -8
  437. package/src/tools/subagent-render.ts +114 -12
  438. package/src/tools/subagent.ts +118 -5
  439. package/src/tools/tmux-self-injection-guard.ts +3301 -122
  440. package/src/tools/todo-write.ts +41 -3
  441. package/src/tools/tool-catalog.generated.ts +32 -4
  442. package/src/tools/ultragoal-ask-guard.ts +13 -1
  443. package/src/tools/write.ts +42 -3
  444. package/src/tui/tree-list.ts +15 -1
  445. package/src/utils/commit-message-generator.ts +12 -4
  446. package/src/utils/external-editor.ts +21 -7
  447. package/src/utils/file-mentions.ts +75 -7
  448. package/src/utils/git.ts +38 -7
  449. package/src/utils/image-limits.ts +8 -0
  450. package/src/utils/image-loading.ts +1 -1
  451. package/src/utils/open.ts +73 -4
  452. package/src/utils/pasted-image-loading.ts +9 -8
  453. package/src/utils/prompt-suggestion.ts +5 -4
  454. package/src/utils/shell-snapshot.ts +9 -1
  455. package/src/utils/title-generator.ts +72 -22
  456. package/src/web/scrapers/index.ts +3 -1
  457. package/src/web/scrapers/types.ts +8 -0
  458. package/src/web/scrapers/youtube.ts +3 -2
  459. package/src/web/search/index.ts +2 -1
  460. package/src/web/search/providers/codex.ts +29 -32
  461. package/src/web/search/providers/insane.ts +91 -28
  462. package/src/web/search/providers/searxng.ts +62 -10
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * Shared types for `gjc migrate`.
3
3
  *
4
- * Imports MCP servers and skills from other coding agents (Claude Code, Codex,
5
- * OpenCode) into native GJC config. See the consensus plan under
4
+ * Imports MCP servers, skills, slash commands, and instruction files from other coding agents
5
+ * (Claude Code, Codex, OpenCode) into native GJC config. See the consensus plan under
6
6
  * `.gjc/plans/ralplan/` for the full taxonomy and force/collision semantics.
7
7
  */
8
8
  import type { MCPServerConfig } from "../runtime-mcp/types";
@@ -16,7 +16,7 @@ export const MIGRATE_SOURCES: readonly MigrateSource[] = ["claude-code", "codex"
16
16
  export const CANONICAL_SOURCE_ORDER: readonly MigrateSource[] = MIGRATE_SOURCES;
17
17
 
18
18
  /** What kind of thing an action/coverage row is about. */
19
- export type MigrateItemType = "mcp" | "skill" | "source";
19
+ export type MigrateItemType = "mcp" | "skill" | "command" | "agent" | "hook" | "instruction" | "source";
20
20
 
21
21
  /**
22
22
  * Per-item outcome taxonomy.
@@ -77,6 +77,31 @@ export interface SkillCandidate {
77
77
  warnings: string[];
78
78
  }
79
79
 
80
+ /** An instructions file imported as the active GJC AGENTS.md for its scope. */
81
+ export interface InstructionCandidate {
82
+ source: MigrateSource;
83
+ name: string;
84
+ content: string;
85
+ }
86
+
87
+ /** A Markdown subagent collected from a foreign coding-agent setup. */
88
+ export interface AgentCandidate {
89
+ source: MigrateSource;
90
+ /** Agent name exactly as it will be loaded from `<agentsDir>/<name>.md`. */
91
+ name: string;
92
+ /** Full Markdown content with normalized GJC frontmatter. */
93
+ content: string;
94
+ warnings: string[];
95
+ }
96
+
97
+ /** A Markdown slash command collected from a foreign coding-agent setup. */
98
+ export interface SlashCommandCandidate {
99
+ source: MigrateSource;
100
+ /** Name without the leading slash; nested path components use `:`. */
101
+ name: string;
102
+ content: string;
103
+ }
104
+
80
105
  /**
81
106
  * Source-level diagnostic for a single source/type pair (e.g. "codex mcp config
82
107
  * was malformed"). Distinct from per-item actions so absent/unreadable sources
@@ -89,11 +114,48 @@ export interface SourceDiagnostic {
89
114
  message: string;
90
115
  }
91
116
 
117
+ /**
118
+ * A foreign hook command that maps onto a gjc hook event.
119
+ *
120
+ * Claude Code hooks are shell commands that receive a JSON payload on stdin and
121
+ * signal a block with exit code 2; gjc hooks are TypeScript modules. The
122
+ * importer generates a module that reproduces that contract for the events whose
123
+ * semantics are unambiguous.
124
+ */
125
+ export interface HookCandidate {
126
+ source: MigrateSource;
127
+ /** Foreign event name, e.g. `PreToolUse`. */
128
+ event: string;
129
+ /** Tool-name matcher; empty or absent means every tool. */
130
+ matcher?: string;
131
+ /** Shell command exactly as the source declared it. */
132
+ command: string;
133
+ }
134
+
135
+ /**
136
+ * A source setting the migration cannot express in gjc. Reported instead of
137
+ * guessed at: silently translating an approval or hook policy would change what
138
+ * the agent is allowed to do. Secret values are never read, so detail may name
139
+ * keys but never their contents.
140
+ */
141
+ export interface ManualAction {
142
+ source: MigrateSource;
143
+ /** Setting area, e.g. `hooks`, `settings.model`, `env`. */
144
+ area: string;
145
+ /** One-line instruction naming the concrete follow-up. */
146
+ detail: string;
147
+ }
148
+
92
149
  /** Normalized candidates + diagnostics returned by an adapter. */
93
150
  export interface AdapterResult {
94
151
  mcpCandidates: McpCandidate[];
95
152
  skillCandidates: SkillCandidate[];
153
+ slashCommandCandidates: SlashCommandCandidate[];
154
+ agentCandidates: AgentCandidate[];
155
+ hookCandidates: HookCandidate[];
156
+ instructionCandidates: InstructionCandidate[];
96
157
  diagnostics: SourceDiagnostic[];
158
+ manualActions: ManualAction[];
97
159
  }
98
160
 
99
161
  /** A single planned action consumed identically by dry-run and live execution. */
@@ -112,6 +174,10 @@ export interface MigrateAction {
112
174
  /** Resolved payload the executor needs; never serialized to the report. */
113
175
  mcp?: { config: MCPServerConfig; force: boolean };
114
176
  skill?: { content: string };
177
+ command?: { content: string };
178
+ agent?: { content: string };
179
+ hook?: { content: string };
180
+ instruction?: { content: string };
115
181
  }
116
182
 
117
183
  export interface MigrateWarning {
@@ -126,6 +192,11 @@ export type StatusCounts = Record<MigrationStatus, number>;
126
192
  export interface MigrateDestinations {
127
193
  mcpConfigPath: string;
128
194
  skillsDir: string;
195
+ commandsDir: string;
196
+ agentsDir: string;
197
+ /** Directory that receives generated hook modules. */
198
+ hooksDir: string;
199
+ instructionsPath: string;
129
200
  }
130
201
 
131
202
  /** The full machine-readable report emitted with `--json`. */
@@ -138,7 +209,15 @@ export interface MigrateReport {
138
209
  destinations: MigrateDestinations;
139
210
  summary: {
140
211
  total: StatusCounts;
141
- byType: { mcp: StatusCounts; skill: StatusCounts; source: StatusCounts };
212
+ byType: {
213
+ mcp: StatusCounts;
214
+ skill: StatusCounts;
215
+ command: StatusCounts;
216
+ agent: StatusCounts;
217
+ hook: StatusCounts;
218
+ instruction: StatusCounts;
219
+ source: StatusCounts;
220
+ };
142
221
  bySource: Record<MigrateSource, StatusCounts>;
143
222
  };
144
223
  actions: Array<{
@@ -153,6 +232,7 @@ export interface MigrateReport {
153
232
  warnings?: string[];
154
233
  }>;
155
234
  warnings: MigrateWarning[];
235
+ manualActions: ManualAction[];
156
236
  }
157
237
 
158
238
  /** Create a zeroed status-count record. */
@@ -112,6 +112,11 @@ condition in prose. Error guidance states the safe recovery action without
112
112
  showing credentials. Confirmations are explicit focused choices; destructive
113
113
  remove/disable actions are never the default side effect of navigation.
114
114
 
115
+ Guidance the user must act on (for example the subagent await-timeout
116
+ "inspect before cancelling" instruction) wraps to the terminal width instead of
117
+ being clipped to one preview line, so the action survives narrow terminals. It
118
+ stays bounded: at most 12 wrapped rows, the last ending in `…` if cut.
119
+
115
120
  A non-cancellable action visibly locks navigation and names the reason. A
116
121
  cancellable action names cancellation while it is pending, aborts on exit, and
117
122
  must not render a late completion after disposal. This follows the selector's
@@ -469,3 +474,49 @@ differently named bundles, and a stored `uri#ref` differs from a bare `uri`, so
469
474
  locator-based refusal would refuse installs that should proceed. Refusing on a
470
475
  guess is worse than reporting the real failure, so identity must be readable for
471
476
  refusal to apply.
477
+
478
+ ## Subagent compact await panel
479
+
480
+ Source: `tools/subagent-render.ts` (the `subagent` await panel), behind the
481
+ `task.compactSubagentPanel` setting (default off). This section extends the
482
+ existing tool-panel grammar; it adds no tokens.
483
+
484
+ - **Scope:** live await progress only. A final result (timeout guidance,
485
+ failure and completion receipts, status/steer/resume replies) always keeps the
486
+ full per-subagent rendering, so nothing the user must act on is summarized.
487
+ - **Anatomy (collapsed, setting on):** a height independent of the number of
488
+ subagents — the existing status header, one `dim` summary row of group counts
489
+ joined by ` · `, at most one `warning` row naming the most-degraded provider and
490
+ how many more providers degrade (the expanded view keeps one row per provider), and one `dim` hint row in parentheses
491
+ naming the effective `app.tools.expand` key and, while anything runs, the
492
+ existing `ctrl+s to observe sessions` hint.
493
+ - **Count order:** `N subagents running`, then `failed`, `retrying`,
494
+ `idle >30s`, `queued`, `paused`, `done`, `cancelled`. Zero counts are omitted.
495
+ Attention states come first because a narrow terminal truncates the row end;
496
+ truncation shows `…` so a dropped count is visible.
497
+ - **States:** collapsed → summary; expanded (the existing tool-output toggle)
498
+ → the unchanged per-subagent list. With the setting off the panel is the
499
+ unchanged per-subagent list in both states. Status is carried by words and
500
+ counts, never by color or the spinner alone; ASCII/no-color keeps the same
501
+ text.
502
+ - **Motion:** no new animation. With the setting on, await progress re-emits
503
+ only when the summary counts or per-provider retry counts change (plus the
504
+ existing liveness interval).
505
+ - **International text:** the summary and hint are fixed English labels and
506
+ numbers; subagent descriptions (which may be CJK) appear only in the expanded
507
+ list, whose layout is unchanged.
508
+
509
+ Capture command (fixture-backed, real renderer, fixed clock):
510
+
511
+ ```sh
512
+ bun packages/coding-agent/scripts/capture-subagent-compact-panel-showcase.ts --out .gjc/qa/subagent-compact-panel-<run>
513
+ ```
514
+
515
+ The matrix is every state at `80x24`, `120x36`, and `160x48` in
516
+ `unicode-color` (including `compact-final-timeout`, a final timeout receipt
517
+ with the setting on), plus `compact-collapsed-15-live` and `compact-collapsed-mixed`
518
+ at `80x24/ascii-no-color`, `compact-collapsed-mixed/48x36/unicode-color`, and
519
+ `narrow-cjk/48x36` in both render modes: 26 entries. An entry whose panel fits
520
+ the viewport is captured once (`top`); an overflowing entry is captured at
521
+ `top`, `middle`, and `bottom` so no tail is hidden. Every capture has
522
+ `terminal.txt`, `terminal-ansi.txt`, `terminal.html`, and `metadata.json`.
@@ -631,6 +631,11 @@ function isAbortNoEffect(value: unknown): boolean {
631
631
  const result = object(candidate?.result) ?? candidate;
632
632
  return result?.turn === "no_active_turn" || result?.turn === "no_effect" || result?.turn === "no_store";
633
633
  }
634
+ function isAbortUncertain(value: unknown): boolean {
635
+ const candidate = object(value);
636
+ const result = object(candidate?.result) ?? candidate;
637
+ return result?.turn === "uncertain";
638
+ }
634
639
 
635
640
  function strictCorrelationFrom(...values: unknown[]): PromptCorrelation | undefined {
636
641
  const correlation: PromptCorrelation = {};
@@ -3064,12 +3069,16 @@ export class AcpAgent implements Agent {
3064
3069
  let acknowledgementScope = scope;
3065
3070
  if (
3066
3071
  !isAbortAcknowledged(acknowledgement, scope) &&
3067
- isAbortNoEffect(acknowledgement) &&
3072
+ (isAbortNoEffect(acknowledgement) || isAbortUncertain(acknowledgement)) &&
3068
3073
  (waiterWasUnacknowledged || waiterWasBeforeActivity) &&
3069
3074
  waiter &&
3070
3075
  record.activePrompt === waiter &&
3071
3076
  !waiter.settled
3072
3077
  ) {
3078
+ // An uncertain replay result is not proof that the worker stopped, but it
3079
+ // also must not erase a cancellation that arrived before prompt admission.
3080
+ // Retain the intent and retry once the prompt acknowledgement/start gives
3081
+ // the abort a concrete active turn to target.
3073
3082
  waiter.cancelBeforeAdmission = true;
3074
3083
  waiter.cancelBeforeAdmissionScope =
3075
3084
  waiter.cancelBeforeAdmissionScope === "owned" || scope === "owned" ? "owned" : "turn";
@@ -1,4 +1,6 @@
1
1
  import type { ClientCapabilities } from "@agentclientprotocol/sdk";
2
+ import { startupProjectEnvSnapshot } from "@gajae-code/utils/env";
3
+ import { canonicalEnvKey } from "@gajae-code/utils/env-file";
2
4
 
3
5
  export type AcpPermissionMode = "auto" | "prompt" | "always-allow";
4
6
 
@@ -9,6 +11,21 @@ function parseAcpPermissionMode(value: unknown): AcpPermissionMode {
9
11
  return "prompt";
10
12
  }
11
13
 
14
+ /**
15
+ * The default process environment includes the cwd `.env` merge. A live value
16
+ * equal to that startup declaration is the overlay and fails safe. A different
17
+ * live value is the launching environment, including when the declaration is
18
+ * dynamic (`$` or backticks) and is not that value. An explicit env map is
19
+ * the caller's value. The raw string is parsed so padding still fails safe.
20
+ */
21
+ function permissionModeFromEnv(env: NodeJS.ProcessEnv): unknown {
22
+ const raw = env[ACP_PERMISSION_MODE_ENV];
23
+ if (env !== process.env || typeof raw !== "string") return raw;
24
+ const declared = startupProjectEnvSnapshot().values[canonicalEnvKey(ACP_PERMISSION_MODE_ENV)];
25
+ if (declared !== undefined && raw.trim() === declared.trim()) return undefined;
26
+ return raw;
27
+ }
28
+
12
29
  /** Client metadata is authoritative; the process environment is only a fallback when that field is absent. */
13
30
  export function resolveAcpPermissionMode(
14
31
  clientCapabilities: ClientCapabilities | undefined,
@@ -21,5 +38,5 @@ export function resolveAcpPermissionMode(
21
38
  return parseAcpPermissionMode((gjc as { permissionHandling?: unknown }).permissionHandling);
22
39
  }
23
40
  }
24
- return parseAcpPermissionMode(env[ACP_PERMISSION_MODE_ENV]);
41
+ return parseAcpPermissionMode(permissionModeFromEnv(env));
25
42
  }
@@ -90,14 +90,22 @@ export function resolveAgentCreationModel(
90
90
  modelPatterns: string[],
91
91
  modelRegistry: ModelRegistry,
92
92
  settings: Settings | undefined,
93
+ credentialSessionId?: string,
93
94
  ) {
94
- const { model } = resolveModelOverride(modelPatterns, modelRegistry, settings);
95
+ const { model } = resolveModelOverride(
96
+ modelPatterns,
97
+ modelRegistry,
98
+ settings,
99
+ undefined,
100
+ undefined,
101
+ credentialSessionId,
102
+ );
95
103
  if (model) return model;
96
104
  if (modelPatterns.length > 0) {
97
105
  throw new Error(`Configured model selector(s) did not resolve: ${modelPatterns.join(", ")}.`);
98
106
  }
99
107
 
100
- const fallbackModel = modelRegistry.getAvailable()[0];
108
+ const fallbackModel = modelRegistry.getAvailable(credentialSessionId)[0];
101
109
  if (!fallbackModel) {
102
110
  throw new Error("No available model to generate agent specification.");
103
111
  }
@@ -612,7 +620,12 @@ export class AgentDashboard extends Container {
612
620
  settings?.getModelRole("default"),
613
621
  settings,
614
622
  );
615
- const selectedModel = resolveAgentCreationModel(modelPatterns, modelRegistry, settings);
623
+ const selectedModel = resolveAgentCreationModel(
624
+ modelPatterns,
625
+ modelRegistry,
626
+ settings,
627
+ this.modelContext.credentialSessionId,
628
+ );
616
629
 
617
630
  const systemPrompt = prompt.render(agentCreationArchitectPrompt, { TASK_TOOL_NAME: "task" });
618
631
  const userPrompt = prompt.render(agentCreationUserPrompt, { request: description });
@@ -701,7 +714,7 @@ export class AgentDashboard extends Container {
701
714
  if (!modelRegistry) return [];
702
715
  const query = input.trim().toLowerCase();
703
716
  if (!query) return [];
704
- const available = modelRegistry.getAvailable();
717
+ const available = modelRegistry.getAvailable(this.modelContext.credentialSessionId);
705
718
  const seen = new Set<string>();
706
719
  const matches: string[] = [];
707
720
  for (const model of available) {
@@ -757,6 +770,9 @@ export class AgentDashboard extends Container {
757
770
  patterns,
758
771
  modelRegistry,
759
772
  this.#settingsManager ?? undefined,
773
+ undefined,
774
+ undefined,
775
+ this.modelContext.credentialSessionId,
760
776
  );
761
777
  if (!model) return undefined;
762
778
  return {
@@ -4,13 +4,17 @@ import {
4
4
  Container,
5
5
  Image,
6
6
  ImageProtocol,
7
+ isCursorNeutralImagePermittedInFallback,
8
+ isTerminalGraphicsFallbackActive,
7
9
  isViewportAnchorSourceRenderer,
8
10
  Markdown,
11
+ type MarkdownTheme,
9
12
  Spacer,
10
13
  TERMINAL,
11
14
  Text,
12
15
  type ViewportAnchorSource,
13
16
  } from "@gajae-code/tui";
17
+ import { SvgFigure } from "@gajae-code/tui/chat/svg-figure";
14
18
  import { formatNumber } from "@gajae-code/utils";
15
19
  import { settings } from "../../config/settings";
16
20
  import { renderDeepInterviewAssistantText } from "../../deep-interview/render-middleware";
@@ -27,6 +31,44 @@ const THINKING_REPETITION_ELIDE_MIN_RUN = 24;
27
31
  const THINKING_REPETITION_VISIBLE_TOKENS = 3;
28
32
  const THINKING_REPETITION_TOKEN_PATTERN = /[\p{L}\p{N}_'-]{1,32}/gu;
29
33
 
34
+ let assistantMarkdownThemeBase: MarkdownTheme | undefined;
35
+ let cachedAssistantMarkdownTheme: MarkdownTheme | undefined;
36
+
37
+ function getAssistantMarkdownTheme(): MarkdownTheme {
38
+ const base = getMarkdownTheme();
39
+ if (base === assistantMarkdownThemeBase && cachedAssistantMarkdownTheme) return cachedAssistantMarkdownTheme;
40
+ assistantMarkdownThemeBase = base;
41
+ cachedAssistantMarkdownTheme = {
42
+ ...base,
43
+ resolveSvgFigure: (source, context) => {
44
+ if (!settings.get("terminal.showImages")) return null;
45
+ const graphicsSuppressed =
46
+ isTerminalGraphicsFallbackActive() &&
47
+ !(TERMINAL.imageProtocol === ImageProtocol.Kitty && isCursorNeutralImagePermittedInFallback());
48
+ if (!TERMINAL.imageProtocol) return null; // Stable environment: cache the code fallback.
49
+ if (graphicsSuppressed) return undefined; // The suppression scope can end; retry on repaint.
50
+ const palette = theme.getSvgPalette();
51
+ const previous = context.previous instanceof SvgFigure ? context.previous : undefined;
52
+ const figure =
53
+ previous ??
54
+ new SvgFigure({
55
+ theme: { fallbackColor: (text: string) => theme.fg("toolOutput", text) },
56
+ palette,
57
+ onChange: context.onChange,
58
+ });
59
+ figure.update(source, context.closed || !context.streaming, context.closed, palette);
60
+ if (figure.retryable) {
61
+ // A failed preview remains a code block, but must observe layout changes
62
+ // so a smaller terminal canvas can retry the same source.
63
+ figure.render(context.width);
64
+ return undefined;
65
+ }
66
+ return figure.failed ? null : figure;
67
+ },
68
+ };
69
+ return cachedAssistantMarkdownTheme;
70
+ }
71
+
30
72
  interface ThinkingRepetitionToken {
31
73
  text: string;
32
74
  normalized: string;
@@ -92,6 +134,7 @@ export class AssistantMessageComponent extends Container {
92
134
  #convertedKittyImages = new Map<string, ImageContent & { source: string }>();
93
135
  #kittyConversionsInFlight = new Map<string, string>();
94
136
  #toolImageGenerations = new Map<string, number>();
137
+ #unsubscribeSettings?: () => void;
95
138
 
96
139
  #responseHeader = new Text(theme.bold(theme.fg("statusLineModel", "gajae")), 1, 0);
97
140
  #contentBlocksCache = new WeakMap<object, { source: string; component: Component }>();
@@ -133,6 +176,15 @@ export class AssistantMessageComponent extends Container {
133
176
  }
134
177
  this.#visibleSignature = this.#visibleContentSignature();
135
178
  this.#visibleSignatureInitialized = true;
179
+ this.#unsubscribeSettings = settings.onChanged(path => {
180
+ if (path !== "terminal.showImages") return;
181
+ for (const block of this.#lastMessage?.content ?? []) {
182
+ if (block.type !== "text") continue;
183
+ const cached = this.#contentBlocksCache.get(block);
184
+ if (cached?.component instanceof Markdown) cached.component.invalidate();
185
+ }
186
+ this.#requestRepaint?.();
187
+ });
136
188
  }
137
189
 
138
190
  #visibleContentSignature(): string {
@@ -339,7 +391,7 @@ export class AssistantMessageComponent extends Container {
339
391
  cached.source = content.text;
340
392
  return cached.component;
341
393
  }
342
- const component = deepInterview ?? new Markdown(trimmed, 1, 0, getMarkdownTheme());
394
+ const component = deepInterview ?? new Markdown(trimmed, 1, 0, getAssistantMarkdownTheme());
343
395
  if (component instanceof Markdown) {
344
396
  component.setOnStaleThrottle(this.#requestRepaint);
345
397
  component.setStreaming(streaming);
@@ -626,6 +678,8 @@ export class AssistantMessageComponent extends Container {
626
678
  override dispose(): void {
627
679
  if (this.#disposed) return;
628
680
  this.#disposed = true;
681
+ this.#unsubscribeSettings?.();
682
+ this.#unsubscribeSettings = undefined;
629
683
  this.#toolImageGenerations.clear();
630
684
  this.#kittyConversionsInFlight.clear();
631
685
  this.#convertedKittyImages.clear();
@@ -59,6 +59,7 @@ function safe(text: string): string {
59
59
 
60
60
  const STATUS_COLORS: Record<InventoryRow["status"], (text: string) => string> = {
61
61
  enabled: text => theme.fg("success", text),
62
+ "stored-only": text => theme.fg("warning", text),
62
63
  disabled: text => theme.fg("muted", text),
63
64
  invalid: text => theme.fg("error", text),
64
65
  shadowed: text => theme.fg("warning", text),
@@ -281,6 +282,12 @@ export class CustomizationDashboard extends Container {
281
282
  async #toggleSelected(): Promise<void> {
282
283
  const row = this.#selectedRow();
283
284
  if (!row || !this.#guardScope(row)) return;
285
+ if (row.status === "stored-only") {
286
+ this.#flashStatus(
287
+ "project hooks are stored-only; import into Global .gjc or configure an explicit hook path to load them",
288
+ );
289
+ return;
290
+ }
284
291
  if (row.status === "invalid" || row.status === "shadowed" || row.status === "quarantined") {
285
292
  this.#flashStatus(`cannot toggle a ${row.status} entry; resolve its diagnostics first`);
286
293
  return;
@@ -313,20 +313,46 @@ export class ImportWizard extends Container {
313
313
  counts.set(entry.outcome, (counts.get(entry.outcome) ?? 0) + 1);
314
314
  }
315
315
  const summary = [...counts.entries()].map(([outcome, count]) => `${count} ${outcome}`).join(", ");
316
+ const storedOnlyProjectHooks =
317
+ this.#result.ok &&
318
+ this.#plan?.preview.destinationScope === "project" &&
319
+ this.#result.entries.some(
320
+ entry =>
321
+ entry.surface === "hooks" &&
322
+ (entry.outcome === "imported" || entry.outcome === "renamed" || entry.outcome === "overwritten"),
323
+ );
316
324
  this.#headerText.setText(
317
325
  this.#result.ok
318
326
  ? theme.bold(theme.fg("success", "Import complete"))
319
327
  : theme.bold(theme.fg("error", "Import failed — rolled back, no partial import")),
320
328
  );
321
329
  const failed = this.#result.entries.filter(e => e.outcome === "failed").slice(0, 5);
330
+ const completionMessages: string[] = [];
331
+ if (this.#result.ok) {
332
+ if (storedOnlyProjectHooks) {
333
+ completionMessages.push(
334
+ theme.fg(
335
+ "warning",
336
+ "Project-scope hooks are stored-only; ordinary sessions do not load repository hook modules.",
337
+ ),
338
+ theme.fg("muted", "Import hooks into Global .gjc or configure an explicit hook path to activate them."),
339
+ theme.fg(
340
+ "muted",
341
+ "Other imported entries take effect after the documented reload/new-session boundary.",
342
+ ),
343
+ );
344
+ } else {
345
+ completionMessages.push(
346
+ theme.fg("muted", "Imported entries take effect after the documented reload/new-session boundary."),
347
+ );
348
+ }
349
+ }
322
350
  this.#bodyText.setText(
323
351
  [
324
352
  summary,
325
353
  "",
326
354
  ...failed.map(e => theme.fg("error", ` ✗ ${e.surface}: ${safe(e.sourceName)} — ${safe(e.reason ?? "")}`)),
327
- ...(this.#result.ok
328
- ? [theme.fg("muted", "Imported entries take effect after the documented reload/new-session boundary.")]
329
- : []),
355
+ ...completionMessages,
330
356
  ].join("\n"),
331
357
  );
332
358
  this.#footerText.setText(theme.fg("muted", "enter/esc: close"));