@gajae-code/coding-agent 0.11.0 → 0.11.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (418) hide show
  1. package/CHANGELOG.md +63 -1
  2. package/dist/types/async/job-manager.d.ts +46 -7
  3. package/dist/types/cli/config-cli.d.ts +11 -1
  4. package/dist/types/cli/notify-cli.d.ts +1 -0
  5. package/dist/types/cli/session-picker.d.ts +2 -1
  6. package/dist/types/cli/setup-cli.d.ts +1 -1
  7. package/dist/types/commands/mcp-serve.d.ts +33 -0
  8. package/dist/types/commands/mcp.d.ts +1 -1
  9. package/dist/types/commands/notify.d.ts +0 -2
  10. package/dist/types/commands/sdk.d.ts +1 -1
  11. package/dist/types/config/atomic-yaml-patch.d.ts +18 -0
  12. package/dist/types/config/file-lock.d.ts +14 -4
  13. package/dist/types/config/keybindings.d.ts +42 -1
  14. package/dist/types/config/model-auth.d.ts +3 -0
  15. package/dist/types/config/model-bindings-applier.d.ts +13 -0
  16. package/dist/types/config/model-discovery-manager.d.ts +49 -0
  17. package/dist/types/config/model-equivalence.d.ts +20 -0
  18. package/dist/types/config/model-registry.d.ts +16 -15
  19. package/dist/types/config/model-resolver.d.ts +28 -18
  20. package/dist/types/config/models-config-schema.d.ts +11 -0
  21. package/dist/types/config/settings-schema.d.ts +56 -1
  22. package/dist/types/config/settings.d.ts +14 -11
  23. package/dist/types/coordinator-mcp/policy.d.ts +5 -0
  24. package/dist/types/coordinator-mcp/question-gate-codec.d.ts +129 -0
  25. package/dist/types/coordinator-mcp/question-state.d.ts +356 -0
  26. package/dist/types/coordinator-mcp/server.d.ts +4 -0
  27. package/dist/types/discovery/helpers.d.ts +0 -6
  28. package/dist/types/edit/index.d.ts +3 -0
  29. package/dist/types/eval/py/env.d.ts +9 -0
  30. package/dist/types/extensibility/extensions/loader.d.ts +2 -1
  31. package/dist/types/extensibility/extensions/runner.d.ts +2 -2
  32. package/dist/types/extensibility/extensions/types.d.ts +34 -3
  33. package/dist/types/extensibility/hooks/runner.d.ts +1 -1
  34. package/dist/types/extensibility/shared-events.d.ts +2 -0
  35. package/dist/types/gjc-runtime/deep-interview-recorder.d.ts +10 -1
  36. package/dist/types/gjc-runtime/deep-interview-state.d.ts +44 -0
  37. package/dist/types/gjc-runtime/goal-mode-request.d.ts +11 -1
  38. package/dist/types/gjc-runtime/launch-worktree.d.ts +4 -2
  39. package/dist/types/gjc-runtime/linux-proc.d.ts +29 -0
  40. package/dist/types/gjc-runtime/session-resolution.d.ts +2 -2
  41. package/dist/types/gjc-runtime/state-migrations.d.ts +1 -1
  42. package/dist/types/gjc-runtime/state-writer.d.ts +2 -1
  43. package/dist/types/gjc-runtime/team-launch.d.ts +59 -0
  44. package/dist/types/gjc-runtime/team-notify.d.ts +45 -0
  45. package/dist/types/gjc-runtime/team-runtime.d.ts +29 -121
  46. package/dist/types/gjc-runtime/team-store.d.ts +160 -0
  47. package/dist/types/gjc-runtime/team-workers.d.ts +78 -0
  48. package/dist/types/gjc-runtime/tmux-owner-isolation.d.ts +8 -0
  49. package/dist/types/gjc-runtime/ultragoal-change-set.d.ts +13 -0
  50. package/dist/types/gjc-runtime/ultragoal-evidence.d.ts +38 -0
  51. package/dist/types/gjc-runtime/ultragoal-guard.d.ts +7 -0
  52. package/dist/types/gjc-runtime/ultragoal-pipeline.d.ts +23 -0
  53. package/dist/types/gjc-runtime/ultragoal-receipt-freshness.d.ts +11 -0
  54. package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +55 -33
  55. package/dist/types/gjc-runtime/workflow-cli-common.d.ts +8 -0
  56. package/dist/types/gjc-runtime/workflow-manifest.d.ts +3 -0
  57. package/dist/types/goals/continuation-timeout-guard.d.ts +22 -0
  58. package/dist/types/goals/runtime.d.ts +1 -0
  59. package/dist/types/goals/state.d.ts +8 -0
  60. package/dist/types/harness-control-plane/lifecycle-reconciliation.d.ts +17 -0
  61. package/dist/types/harness-control-plane/phase-rollup.d.ts +4 -7
  62. package/dist/types/harness-control-plane/receipt-ingest.d.ts +5 -0
  63. package/dist/types/harness-control-plane/receipt-spool.d.ts +4 -0
  64. package/dist/types/hindsight/state.d.ts +11 -4
  65. package/dist/types/lsp/lspmux.d.ts +5 -3
  66. package/dist/types/lsp/path-trust.d.ts +1 -0
  67. package/dist/types/main.d.ts +3 -2
  68. package/dist/types/memories/storage.d.ts +1 -0
  69. package/dist/types/modes/action-registry.d.ts +29 -0
  70. package/dist/types/modes/components/chrome.d.ts +14 -0
  71. package/dist/types/modes/components/command-palette.d.ts +27 -0
  72. package/dist/types/modes/components/custom-provider-wizard.d.ts +1 -0
  73. package/dist/types/modes/components/index.d.ts +2 -1
  74. package/dist/types/modes/components/pet-selector.d.ts +1 -1
  75. package/dist/types/modes/components/plan-preview-overlay.d.ts +43 -0
  76. package/dist/types/modes/components/queue-mode-selector.d.ts +1 -1
  77. package/dist/types/modes/components/queue-pane.d.ts +12 -0
  78. package/dist/types/modes/components/read-tool-group.d.ts +6 -0
  79. package/dist/types/modes/components/session-observer-overlay.d.ts +3 -4
  80. package/dist/types/modes/components/sessions-dashboard.d.ts +32 -0
  81. package/dist/types/modes/components/settings-selector.d.ts +1 -1
  82. package/dist/types/modes/components/show-images-selector.d.ts +1 -1
  83. package/dist/types/modes/components/status-line/types.d.ts +1 -1
  84. package/dist/types/modes/components/status-line.d.ts +1 -94
  85. package/dist/types/modes/components/tasks-pane.d.ts +15 -0
  86. package/dist/types/modes/components/theme-selector.d.ts +1 -1
  87. package/dist/types/modes/components/tool-execution.d.ts +15 -0
  88. package/dist/types/modes/components/tool-status-header.d.ts +111 -0
  89. package/dist/types/modes/components/transcript-viewer-overlay.d.ts +42 -0
  90. package/dist/types/modes/controllers/command-controller.d.ts +2 -2
  91. package/dist/types/modes/controllers/extension-ui-controller.d.ts +1 -0
  92. package/dist/types/modes/controllers/goal-mode-controller.d.ts +62 -0
  93. package/dist/types/modes/controllers/input-controller.d.ts +8 -1
  94. package/dist/types/modes/controllers/mode-gate.d.ts +8 -0
  95. package/dist/types/modes/controllers/plan-mode-controller.d.ts +65 -0
  96. package/dist/types/modes/controllers/selector-controller.d.ts +15 -3
  97. package/dist/types/modes/controllers/stt-controller.d.ts +26 -0
  98. package/dist/types/modes/interactive-mode.d.ts +21 -19
  99. package/dist/types/modes/jobs-observer.d.ts +2 -0
  100. package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +4 -11
  101. package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +21 -2
  102. package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +31 -0
  103. package/dist/types/modes/tasks-aggregator.d.ts +39 -0
  104. package/dist/types/modes/transcript-item-registry.d.ts +60 -0
  105. package/dist/types/modes/types.d.ts +22 -15
  106. package/dist/types/modes/utils/ui-helpers.d.ts +2 -2
  107. package/dist/types/runtime-mcp/manager.d.ts +1 -1
  108. package/dist/types/sdk/broker/broker.d.ts +78 -12
  109. package/dist/types/sdk/broker/ensure.d.ts +9 -0
  110. package/dist/types/sdk/broker/lifecycle-codec.d.ts +4 -0
  111. package/dist/types/sdk/broker/lifecycle-ledger.d.ts +15 -1
  112. package/dist/types/sdk/broker/lifecycle.d.ts +6 -2
  113. package/dist/types/sdk/broker/process-incarnation.d.ts +2 -0
  114. package/dist/types/sdk/broker/session-index.d.ts +0 -1
  115. package/dist/types/sdk/broker/state-version.d.ts +2 -0
  116. package/dist/types/sdk/bus/chat-effect-journal.d.ts +1 -0
  117. package/dist/types/sdk/bus/config-commands.d.ts +1 -1
  118. package/dist/types/sdk/bus/config.d.ts +11 -0
  119. package/dist/types/sdk/bus/daemon-paths.d.ts +1 -0
  120. package/dist/types/sdk/bus/discord-daemon.d.ts +5 -0
  121. package/dist/types/sdk/bus/html-format.d.ts +3 -2
  122. package/dist/types/sdk/bus/index.d.ts +27 -0
  123. package/dist/types/sdk/bus/lifecycle-control-runtime.d.ts +4 -0
  124. package/dist/types/sdk/bus/notification-service.d.ts +20 -0
  125. package/dist/types/sdk/bus/rate-limit-pool.d.ts +13 -2
  126. package/dist/types/sdk/bus/recent-activity.d.ts +21 -12
  127. package/dist/types/sdk/bus/rich-document.d.ts +7 -0
  128. package/dist/types/sdk/bus/rich-render.d.ts +18 -41
  129. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +9 -4
  130. package/dist/types/sdk/bus/telegram-daemon.d.ts +69 -3
  131. package/dist/types/sdk/bus/threaded-inbound.d.ts +1 -1
  132. package/dist/types/sdk/bus/threaded-render.d.ts +13 -0
  133. package/dist/types/sdk/bus/topic-registry.d.ts +24 -2
  134. package/dist/types/sdk/host/control/operations.d.ts +1 -1
  135. package/dist/types/sdk/host/host.d.ts +2 -0
  136. package/dist/types/sdk/index.d.ts +1 -0
  137. package/dist/types/sdk/session-directory.d.ts +56 -0
  138. package/dist/types/session/agent-session.d.ts +82 -47
  139. package/dist/types/session/agent-storage.d.ts +7 -0
  140. package/dist/types/session/fallback-chain-controller.d.ts +10 -2
  141. package/dist/types/session/internal/managed-session-scope.d.ts +102 -0
  142. package/dist/types/session/internal/managed-session-storage.d.ts +38 -0
  143. package/dist/types/session/messages.d.ts +16 -0
  144. package/dist/types/session/session-manager-internal.d.ts +14 -0
  145. package/dist/types/session/session-manager.d.ts +82 -12
  146. package/dist/types/session/session-storage.d.ts +43 -3
  147. package/dist/types/session/volatile-context-pruning.d.ts +15 -0
  148. package/dist/types/skill-state/{deep-interview-mutation-guard.d.ts → workflow-mutation-guard.d.ts} +24 -8
  149. package/dist/types/skill-state/workflow-state-contract.d.ts +1 -3
  150. package/dist/types/slash-commands/builtin-registry.d.ts +4 -1
  151. package/dist/types/system-prompt.d.ts +2 -11
  152. package/dist/types/task/executor.d.ts +3 -1
  153. package/dist/types/thinking.d.ts +7 -0
  154. package/dist/types/tool-discovery/tool-index.d.ts +1 -50
  155. package/dist/types/tools/ask.d.ts +64 -2
  156. package/dist/types/tools/bash.d.ts +3 -0
  157. package/dist/types/tools/browser/dead-tab-recovery.d.ts +24 -0
  158. package/dist/types/tools/browser/tab-supervisor.d.ts +21 -0
  159. package/dist/types/tools/cron.d.ts +2 -0
  160. package/dist/types/tools/fetch.d.ts +1 -0
  161. package/dist/types/tools/index.d.ts +30 -15
  162. package/dist/types/tools/output-meta.d.ts +1 -0
  163. package/dist/types/tools/read.d.ts +3 -0
  164. package/dist/types/tools/search-tool-bm25.d.ts +3 -4
  165. package/dist/types/tools/subagent-render.d.ts +1 -0
  166. package/dist/types/tools/subagent.d.ts +6 -1
  167. package/dist/types/utils/event-bus.d.ts +1 -1
  168. package/dist/types/web/search/index.d.ts +3 -1
  169. package/package.json +21 -9
  170. package/scripts/build-sdk-package-smoke.ts +39 -1
  171. package/scripts/generate-hotkeys-docs.ts +74 -0
  172. package/scripts/generate-sdk-operation-inventory.ts +64 -20
  173. package/scripts/verify-gjc-sdk-canonicalization.ts +182 -2
  174. package/src/async/job-manager.ts +455 -69
  175. package/src/cli/config-cli.ts +75 -2
  176. package/src/cli/notify-cli.ts +92 -26
  177. package/src/cli/session-picker.ts +20 -3
  178. package/src/cli/setup-cli.ts +1 -1
  179. package/src/cli.ts +1 -1
  180. package/src/commands/config.ts +1 -1
  181. package/src/commands/harness.ts +34 -106
  182. package/src/commands/launch.ts +6 -4
  183. package/src/commands/mcp-serve.ts +85 -8
  184. package/src/commands/mcp.ts +2 -2
  185. package/src/commands/notify.ts +8 -4
  186. package/src/commands/sdk.ts +61 -40
  187. package/src/commands/ultragoal.ts +4 -1
  188. package/src/config/atomic-yaml-patch.ts +80 -13
  189. package/src/config/file-lock.ts +105 -43
  190. package/src/config/keybindings.ts +64 -20
  191. package/src/config/model-auth.ts +9 -0
  192. package/src/config/model-bindings-applier.ts +139 -0
  193. package/src/config/model-discovery-manager.ts +224 -0
  194. package/src/config/model-equivalence.ts +66 -0
  195. package/src/config/model-registry.ts +169 -302
  196. package/src/config/model-resolver.ts +361 -369
  197. package/src/config/models-config-schema.ts +5 -4
  198. package/src/config/settings-schema.ts +159 -2
  199. package/src/config/settings.ts +458 -482
  200. package/src/coordinator-mcp/policy.ts +76 -11
  201. package/src/coordinator-mcp/question-gate-codec.ts +274 -0
  202. package/src/coordinator-mcp/question-state.ts +778 -0
  203. package/src/coordinator-mcp/server.ts +1702 -238
  204. package/src/debug/index.ts +1 -1
  205. package/src/defaults/gjc/skills/deep-interview/SKILL.md +13 -1
  206. package/src/defaults/gjc/skills/team/SKILL.md +16 -0
  207. package/src/discovery/helpers.ts +1 -50
  208. package/src/edit/index.ts +64 -0
  209. package/src/eval/py/env.ts +26 -0
  210. package/src/eval/py/kernel.ts +5 -3
  211. package/src/extensibility/extensions/loader.ts +9 -1
  212. package/src/extensibility/extensions/runner.ts +12 -3
  213. package/src/extensibility/extensions/types.ts +39 -1
  214. package/src/extensibility/gjc-plugins/installer.ts +16 -16
  215. package/src/extensibility/hooks/runner.ts +2 -2
  216. package/src/extensibility/runtime-skill-discovery.ts +33 -13
  217. package/src/extensibility/shared-events.ts +2 -0
  218. package/src/gjc-runtime/deep-interview-recorder.ts +63 -3
  219. package/src/gjc-runtime/deep-interview-runtime.ts +76 -27
  220. package/src/gjc-runtime/deep-interview-state.ts +317 -5
  221. package/src/gjc-runtime/goal-mode-request.ts +55 -8
  222. package/src/gjc-runtime/launch-tmux.ts +2 -5
  223. package/src/gjc-runtime/launch-worktree.ts +5 -5
  224. package/src/gjc-runtime/linux-proc.ts +71 -0
  225. package/src/gjc-runtime/ralplan-runtime.ts +74 -90
  226. package/src/gjc-runtime/session-resolution.ts +18 -3
  227. package/src/gjc-runtime/session-state-sidecar.ts +6 -107
  228. package/src/gjc-runtime/state-migrations.ts +1 -1
  229. package/src/gjc-runtime/state-runtime.ts +320 -249
  230. package/src/gjc-runtime/state-writer.ts +36 -40
  231. package/src/gjc-runtime/team-launch.ts +319 -0
  232. package/src/gjc-runtime/team-notify.ts +326 -0
  233. package/src/gjc-runtime/team-runtime.ts +1099 -1482
  234. package/src/gjc-runtime/team-store.ts +828 -0
  235. package/src/gjc-runtime/team-workers.ts +962 -0
  236. package/src/gjc-runtime/tmux-owner-isolation-cli.ts +2 -11
  237. package/src/gjc-runtime/tmux-owner-isolation.ts +14 -9
  238. package/src/gjc-runtime/tmux-sessions.ts +4 -21
  239. package/src/gjc-runtime/ultragoal-change-set.ts +172 -0
  240. package/src/gjc-runtime/ultragoal-evidence.ts +874 -0
  241. package/src/gjc-runtime/ultragoal-guard.ts +83 -12
  242. package/src/gjc-runtime/ultragoal-pipeline.ts +306 -0
  243. package/src/gjc-runtime/ultragoal-receipt-freshness.ts +102 -1
  244. package/src/gjc-runtime/ultragoal-runtime.ts +156 -1319
  245. package/src/gjc-runtime/workflow-cli-common.ts +30 -0
  246. package/src/gjc-runtime/workflow-manifest.generated.json +58 -0
  247. package/src/gjc-runtime/workflow-manifest.ts +18 -0
  248. package/src/goals/continuation-timeout-guard.ts +79 -0
  249. package/src/goals/runtime.ts +7 -5
  250. package/src/goals/state.ts +18 -0
  251. package/src/harness-control-plane/lifecycle-reconciliation.ts +64 -0
  252. package/src/harness-control-plane/phase-rollup.ts +4 -7
  253. package/src/harness-control-plane/receipt-ingest.ts +5 -0
  254. package/src/harness-control-plane/receipt-spool.ts +51 -7
  255. package/src/harness-control-plane/session-lease.ts +12 -130
  256. package/src/hindsight/backend.ts +26 -27
  257. package/src/hindsight/state.ts +101 -32
  258. package/src/hooks/skill-state.ts +17 -11
  259. package/src/internal-urls/docs-index.generated.ts +21 -18
  260. package/src/lsp/client.ts +1 -1
  261. package/src/lsp/config.ts +145 -26
  262. package/src/lsp/index.ts +1 -1
  263. package/src/lsp/lspmux.ts +39 -10
  264. package/src/lsp/path-trust.ts +81 -0
  265. package/src/main.ts +28 -8
  266. package/src/memories/index.ts +1 -0
  267. package/src/memories/storage.ts +6 -2
  268. package/src/modes/action-registry.ts +165 -0
  269. package/src/modes/components/chrome.ts +40 -0
  270. package/src/modes/components/command-palette.ts +168 -0
  271. package/src/modes/components/custom-editor.ts +1 -1
  272. package/src/modes/components/custom-provider-wizard.ts +51 -14
  273. package/src/modes/components/index.ts +2 -1
  274. package/src/modes/components/pet-selector.ts +11 -17
  275. package/src/modes/components/plan-preview-overlay.ts +295 -0
  276. package/src/modes/components/queue-mode-selector.ts +10 -27
  277. package/src/modes/components/queue-pane.ts +79 -0
  278. package/src/modes/components/read-tool-group.ts +13 -0
  279. package/src/modes/components/session-observer-overlay.ts +207 -772
  280. package/src/modes/components/sessions-dashboard.ts +181 -0
  281. package/src/modes/components/settings-selector.ts +1 -1
  282. package/src/modes/components/show-images-selector.ts +10 -24
  283. package/src/modes/components/status-line/types.ts +1 -1
  284. package/src/modes/components/status-line.ts +1 -969
  285. package/src/modes/components/tasks-pane.ts +73 -0
  286. package/src/modes/components/theme-selector.ts +11 -31
  287. package/src/modes/components/tool-execution.ts +22 -0
  288. package/src/modes/components/tool-status-header.ts +1056 -0
  289. package/src/modes/components/transcript-viewer-overlay.ts +384 -0
  290. package/src/modes/controllers/btw-controller.ts +1 -0
  291. package/src/modes/controllers/command-controller.ts +9 -15
  292. package/src/modes/controllers/event-controller.ts +3 -2
  293. package/src/modes/controllers/extension-ui-controller.ts +72 -25
  294. package/src/modes/controllers/goal-mode-controller.ts +474 -0
  295. package/src/modes/controllers/input-controller.ts +764 -229
  296. package/src/modes/controllers/mode-gate.ts +24 -0
  297. package/src/modes/controllers/plan-mode-controller.ts +517 -0
  298. package/src/modes/controllers/selector-controller.ts +225 -10
  299. package/src/modes/controllers/stt-controller.ts +125 -0
  300. package/src/modes/interactive-mode.ts +302 -1151
  301. package/src/modes/jobs-observer.ts +3 -0
  302. package/src/modes/runtime-init.ts +8 -0
  303. package/src/modes/shared/agent-wire/deep-interview-gate.ts +31 -106
  304. package/src/modes/shared/agent-wire/workflow-gate-broker.ts +78 -19
  305. package/src/modes/shared/agent-wire/workflow-gate-types.ts +177 -0
  306. package/src/modes/tasks-aggregator.ts +199 -0
  307. package/src/modes/transcript-item-registry.ts +229 -0
  308. package/src/modes/types.ts +47 -20
  309. package/src/modes/utils/ui-helpers.ts +17 -9
  310. package/src/prompts/agent-fragments/ralplan-persistence.md +6 -0
  311. package/src/prompts/agent-fragments/restricted-bash.md +1 -0
  312. package/src/prompts/agents/architect.md +2 -8
  313. package/src/prompts/agents/critic.md +2 -8
  314. package/src/prompts/agents/executor.md +3 -0
  315. package/src/prompts/agents/planner.md +4 -12
  316. package/src/prompts/system/custom-system-prompt.md +1 -23
  317. package/src/prompts/system/plan-mode-approved.md +8 -0
  318. package/src/prompts/system/system-prompt.md +17 -96
  319. package/src/prompts/tools/bash.md +4 -4
  320. package/src/prompts/tools/browser.md +15 -52
  321. package/src/prompts/tools/find.md +2 -2
  322. package/src/prompts/tools/hashline.md +13 -55
  323. package/src/prompts/tools/read.md +3 -6
  324. package/src/prompts/tools/search-tool-bm25.md +0 -2
  325. package/src/prompts/tools/search.md +2 -4
  326. package/src/prompts/tools/skill-discovery.md +1 -2
  327. package/src/prompts/tools/task.md +1 -1
  328. package/src/runtime-mcp/manager.ts +1 -1
  329. package/src/sdk/broker/broker.ts +206 -78
  330. package/src/sdk/broker/discovery.ts +21 -2
  331. package/src/sdk/broker/ensure.ts +85 -25
  332. package/src/sdk/broker/lifecycle-codec.ts +11 -0
  333. package/src/sdk/broker/lifecycle-ledger.ts +371 -74
  334. package/src/sdk/broker/lifecycle.ts +1399 -142
  335. package/src/sdk/broker/process-incarnation.ts +5 -13
  336. package/src/sdk/broker/session-index.ts +145 -56
  337. package/src/sdk/broker/state-version.ts +21 -0
  338. package/src/sdk/broker/transport.ts +1 -1
  339. package/src/sdk/bus/chat-daemon-cli.ts +2 -0
  340. package/src/sdk/bus/chat-daemon-control.ts +8 -28
  341. package/src/sdk/bus/chat-effect-journal.ts +14 -4
  342. package/src/sdk/bus/config-commands.ts +5 -4
  343. package/src/sdk/bus/config.ts +98 -0
  344. package/src/sdk/bus/conversation-store.ts +5 -29
  345. package/src/sdk/bus/daemon-paths.ts +2 -0
  346. package/src/sdk/bus/discord-daemon.ts +25 -8
  347. package/src/sdk/bus/html-format.ts +20 -3
  348. package/src/sdk/bus/index.ts +834 -113
  349. package/src/sdk/bus/lifecycle-control-runtime.ts +91 -33
  350. package/src/sdk/bus/native-runtime-compatibility.ts +1 -1
  351. package/src/sdk/bus/natives-augment.d.ts +26 -1
  352. package/src/sdk/bus/notification-service.ts +168 -20
  353. package/src/sdk/bus/rate-limit-pool.ts +58 -14
  354. package/src/sdk/bus/recent-activity.ts +188 -74
  355. package/src/sdk/bus/rich-document.ts +258 -0
  356. package/src/sdk/bus/rich-render.ts +62 -70
  357. package/src/sdk/bus/telegram-daemon-cli.ts +15 -59
  358. package/src/sdk/bus/telegram-daemon-contract.ts +9 -4
  359. package/src/sdk/bus/telegram-daemon.ts +1491 -247
  360. package/src/sdk/bus/threaded-inbound.ts +8 -3
  361. package/src/sdk/bus/threaded-render.ts +57 -1
  362. package/src/sdk/bus/topic-registry.ts +120 -13
  363. package/src/sdk/host/control/dispatch.ts +14 -2
  364. package/src/sdk/host/control/operations.ts +6 -1
  365. package/src/sdk/host/host.ts +31 -1
  366. package/src/sdk/host/query/handlers.ts +20 -22
  367. package/src/sdk/host/query/revision-store.ts +80 -57
  368. package/src/sdk/index.ts +1 -0
  369. package/src/sdk/protocol/operation-inventory.generated.json +943 -1907
  370. package/src/sdk/session-directory.ts +141 -0
  371. package/src/sdk/session.ts +458 -479
  372. package/src/session/agent-session.ts +1901 -637
  373. package/src/session/agent-storage.ts +18 -0
  374. package/src/session/cache-economics.ts +25 -8
  375. package/src/session/fallback-chain-controller.ts +53 -3
  376. package/src/session/internal/managed-session-scope.ts +2226 -0
  377. package/src/session/internal/managed-session-storage.ts +453 -0
  378. package/src/session/messages.ts +91 -2
  379. package/src/session/session-manager-internal.ts +33 -0
  380. package/src/session/session-manager.ts +1112 -333
  381. package/src/session/session-storage.ts +444 -39
  382. package/src/session/volatile-context-pruning.ts +78 -0
  383. package/src/setup/credential-auto-import.ts +2 -1
  384. package/src/setup/hermes/templates/operator-instructions.v1.md +1 -1
  385. package/src/setup/provider-onboarding.ts +36 -61
  386. package/src/setup/provider-presets.json +5 -0
  387. package/src/skill-state/active-state.ts +3 -13
  388. package/src/skill-state/{deep-interview-mutation-guard.ts → workflow-mutation-guard.ts} +47 -29
  389. package/src/skill-state/workflow-state-contract.ts +6 -41
  390. package/src/slash-commands/builtin-registry.ts +46 -11
  391. package/src/system-prompt.ts +37 -44
  392. package/src/task/agents.ts +19 -1
  393. package/src/task/executor.ts +90 -6
  394. package/src/task/index.ts +62 -37
  395. package/src/thinking.ts +21 -6
  396. package/src/tool-discovery/tool-index.ts +2 -134
  397. package/src/tools/ask.ts +157 -21
  398. package/src/tools/ast-edit.ts +1 -1
  399. package/src/tools/bash.ts +38 -0
  400. package/src/tools/browser/dead-tab-recovery.ts +78 -0
  401. package/src/tools/browser/tab-supervisor.ts +282 -36
  402. package/src/tools/computer.ts +10 -3
  403. package/src/tools/cron.ts +30 -16
  404. package/src/tools/eval.ts +1 -2
  405. package/src/tools/fetch.ts +11 -4
  406. package/src/tools/index.ts +76 -24
  407. package/src/tools/output-meta.ts +13 -5
  408. package/src/tools/read.ts +37 -1
  409. package/src/tools/resource-gc.ts +2 -2
  410. package/src/tools/search-tool-bm25.ts +11 -74
  411. package/src/tools/subagent-render.ts +19 -8
  412. package/src/tools/subagent.ts +84 -32
  413. package/src/utils/event-bus.ts +9 -4
  414. package/src/web/search/index.ts +3 -3
  415. package/dist/types/discovery/plugin-dir-roots.d.ts +0 -15
  416. package/dist/types/runtime-mcp/discoverable-tool-metadata.d.ts +0 -7
  417. package/src/discovery/plugin-dir-roots.ts +0 -28
  418. package/src/runtime-mcp/discoverable-tool-metadata.ts +0 -25
@@ -0,0 +1,165 @@
1
+ import type { AppKeybinding } from "../config/keybindings";
2
+
3
+ export type FocusDomain = "composer" | "selector" | "overlay" | "global";
4
+
5
+ export interface ActionMetadata {
6
+ id: AppKeybinding;
7
+ title: string;
8
+ category: string;
9
+ bindingId?: AppKeybinding;
10
+ domains: readonly FocusDomain[];
11
+ exclusiveGroup?: string | false;
12
+ }
13
+
14
+ const action = (
15
+ id: AppKeybinding,
16
+ title: string,
17
+ category: string,
18
+ domains: FocusDomain[],
19
+ exclusiveGroup?: string | false,
20
+ ): ActionMetadata => ({
21
+ id,
22
+ title,
23
+ category,
24
+ bindingId: id,
25
+ domains,
26
+ exclusiveGroup,
27
+ });
28
+
29
+ export const APP_ACTION_METADATA: readonly ActionMetadata[] = [
30
+ action("app.interrupt", "Interrupt", "Session", ["global"], false),
31
+ action("app.clear", "Clear", "Session", ["global"]),
32
+ action("app.exit", "Exit", "Session", ["global"]),
33
+ action("app.suspend", "Suspend", "Session", ["global"]),
34
+ action("app.thinking.cycle", "Cycle thinking level", "Thinking", ["composer"]),
35
+ action("app.thinking.toggle", "Toggle thinking", "Thinking", ["composer"]),
36
+ action("app.commandPalette.open", "Open command palette", "Navigation", ["composer"]),
37
+ action("app.model.cycleForward", "Next model", "Model", ["composer"]),
38
+ action("app.model.cycleBackward", "Previous model", "Model", ["composer"]),
39
+ action("app.model.select", "Select model", "Model", ["composer"]),
40
+ action("app.model.selectTemporary", "Select temporary model", "Model", ["composer"]),
41
+ action("app.tools.expand", "Toggle tool expansion", "Tools", ["composer"]),
42
+ action("app.tool.backgroundFold", "Fold foreground tool", "Tools", ["composer"]),
43
+ action("app.editor.external", "Open external editor", "Editor", ["composer"]),
44
+ action("app.message.followUp", "Send follow-up", "Messages", ["composer"]),
45
+ action("app.message.queue", "Queue message", "Messages", ["composer"]),
46
+ action("app.message.dequeue", "Edit queued message", "Messages", ["composer"]),
47
+ action("app.clipboard.pasteImage", "Paste image", "Clipboard", ["composer"]),
48
+ action("app.clipboard.copyLine", "Copy line", "Clipboard", ["composer"]),
49
+ action("app.clipboard.copyPrompt", "Copy prompt", "Clipboard", ["composer"]),
50
+ action("app.session.new", "New session", "Session", ["composer"]),
51
+ action("app.session.tree", "Session tree", "Session", ["composer"]),
52
+ action("app.session.fork", "Fork session", "Session", ["composer"]),
53
+ action("app.session.resume", "Resume session", "Session", ["composer"]),
54
+ action("app.session.observe", "Observe sessions", "Session", ["composer"]),
55
+ action("app.session.dashboard", "Show sessions dashboard", "Session", ["composer"]),
56
+ action("app.jobs.open", "Open jobs", "Jobs", ["composer"]),
57
+ action("app.session.togglePath", "Toggle session path", "Session", ["selector"]),
58
+ action("app.session.toggleSort", "Toggle session sort", "Session", ["selector"]),
59
+ action("app.session.rename", "Rename session", "Session", ["selector"]),
60
+ action("app.session.delete", "Delete session", "Session", ["selector"]),
61
+ action("app.session.deleteNoninvasive", "Delete selected session", "Session", ["selector"]),
62
+ action("app.tree.foldOrUp", "Fold tree item", "Session", ["selector"]),
63
+ action("app.tree.unfoldOrDown", "Unfold tree item", "Session", ["selector"]),
64
+ action("app.plan.toggle", "Toggle plan mode", "Mode", ["composer"]),
65
+ action("app.history.search", "Search history", "Navigation", ["composer"]),
66
+ action("app.stt.toggle", "Toggle speech-to-text", "Speech", ["composer"]),
67
+ action("app.irc.sidebar.toggle", "Toggle IRC sidebar", "IRC", ["composer"]),
68
+ action("app.transcript.browse", "Browse transcript", "Transcript", ["composer"]),
69
+ action("app.transcript.prevTurn", "Previous transcript turn", "Transcript", ["composer"]),
70
+ action("app.transcript.nextTurn", "Next transcript turn", "Transcript", ["composer"]),
71
+ action("app.mode.cycle", "Cycle mode", "Mode", ["composer"]),
72
+ action("app.tasks.toggle", "Toggle tasks pane", "Jobs", ["composer"]),
73
+ action("app.queue.togglePane", "Toggle queue pane", "Messages", ["composer"]),
74
+ action("app.message.sendNow", "Send message now", "Messages", ["composer"]),
75
+ ];
76
+
77
+ export interface ActionDefinition<Context> extends ActionMetadata {
78
+ availability(context: Context): boolean;
79
+ execute(context: Context): void | Promise<void>;
80
+ }
81
+
82
+ export interface ActionRegistryOptions<Context> {
83
+ context: Context;
84
+ showError(error: string): void;
85
+ }
86
+
87
+ export class ActionRegistry<Context> {
88
+ readonly #actions = new Map<AppKeybinding, ActionDefinition<Context>>();
89
+ readonly #busy = new Set<AppKeybinding>();
90
+ readonly #busyGroups = new Set<string>();
91
+ readonly #availability = new Map<AppKeybinding, boolean>();
92
+ #availabilityResetQueued = false;
93
+
94
+ constructor(private readonly options: ActionRegistryOptions<Context>) {}
95
+
96
+ register(action: ActionDefinition<Context>): void {
97
+ if (this.#actions.has(action.id)) throw new Error(`Action already registered: ${action.id}`);
98
+ this.#actions.set(action.id, action);
99
+ }
100
+
101
+ get(id: AppKeybinding): ActionDefinition<Context> | undefined {
102
+ return this.#actions.get(id);
103
+ }
104
+ all(): readonly ActionDefinition<Context>[] {
105
+ return [...this.#actions.values()];
106
+ }
107
+
108
+ #reportError(id: AppKeybinding, phase: "availability" | "execution", error: unknown): void {
109
+ const cause = error instanceof Error ? error.message : String(error);
110
+ try {
111
+ this.options.showError(`Action ${id} ${phase} failed: ${cause}`);
112
+ } catch {
113
+ // Error reporting must not escape an action dispatch.
114
+ }
115
+ }
116
+
117
+ #evaluateAvailability(id: AppKeybinding, action: ActionDefinition<Context>): boolean {
118
+ const cached = this.#availability.get(id);
119
+ if (cached !== undefined) return cached;
120
+ let available: boolean;
121
+ try {
122
+ available = Boolean(action.availability(this.options.context));
123
+ } catch (error) {
124
+ this.#reportError(id, "availability", error);
125
+ available = false;
126
+ }
127
+ this.#availability.set(id, available);
128
+ if (!this.#availabilityResetQueued) {
129
+ this.#availabilityResetQueued = true;
130
+ queueMicrotask(() => {
131
+ this.#availability.clear();
132
+ this.#availabilityResetQueued = false;
133
+ });
134
+ }
135
+ return available;
136
+ }
137
+
138
+ #exclusiveGroup(action: ActionDefinition<Context>): string | undefined {
139
+ return action.exclusiveGroup === false ? undefined : (action.exclusiveGroup ?? "default");
140
+ }
141
+
142
+ isAvailable(id: AppKeybinding): boolean {
143
+ const action = this.#actions.get(id);
144
+ return action ? this.#evaluateAvailability(id, action) : false;
145
+ }
146
+
147
+ async execute(id: AppKeybinding): Promise<boolean> {
148
+ const current = this.#actions.get(id);
149
+ if (!current || this.#busy.has(id) || !this.#evaluateAvailability(id, current)) return false;
150
+ const group = this.#exclusiveGroup(current);
151
+ if (group && this.#busyGroups.has(group)) return false;
152
+ this.#busy.add(id);
153
+ if (group) this.#busyGroups.add(group);
154
+ try {
155
+ await current.execute(this.options.context);
156
+ return true;
157
+ } catch (error) {
158
+ this.#reportError(id, "execution", error);
159
+ return false;
160
+ } finally {
161
+ this.#busy.delete(id);
162
+ if (group) this.#busyGroups.delete(group);
163
+ }
164
+ }
165
+ }
@@ -0,0 +1,40 @@
1
+ import { Container, type SelectItem, SelectList, Text } from "@gajae-code/tui";
2
+ import { getSelectListTheme, theme } from "../../modes/theme/theme";
3
+ import { DynamicBorder } from "./dynamic-border";
4
+
5
+ export interface FramedSelectOptions {
6
+ maxVisible?: number;
7
+ selectedValue?: string;
8
+ onSelect?: (item: SelectItem) => void;
9
+ onCancel?: () => void;
10
+ onSelectionChange?: (item: SelectItem) => void;
11
+ }
12
+
13
+ export interface FramedSelect {
14
+ container: Container;
15
+ selectList: SelectList;
16
+ }
17
+
18
+ /** Build the shared border/list selector chrome used by compact mode selectors. */
19
+ export function FramedSelect(
20
+ title: string | undefined,
21
+ items: ReadonlyArray<SelectItem>,
22
+ opts: FramedSelectOptions = {},
23
+ ): FramedSelect {
24
+ const container = new Container();
25
+ container.addChild(new DynamicBorder());
26
+ if (title) {
27
+ container.addChild(new Text(theme.bold(theme.fg("accent", title)), 0, 0));
28
+ }
29
+
30
+ const selectList = new SelectList(items, opts.maxVisible ?? Math.min(items.length, 10), getSelectListTheme());
31
+ const selectedIndex =
32
+ opts.selectedValue === undefined ? -1 : items.findIndex(item => item.value === opts.selectedValue);
33
+ if (selectedIndex !== -1) selectList.setSelectedIndex(selectedIndex);
34
+ selectList.onSelect = item => opts.onSelect?.(item);
35
+ selectList.onCancel = () => opts.onCancel?.();
36
+ if (opts.onSelectionChange) selectList.onSelectionChange = opts.onSelectionChange;
37
+ container.addChild(selectList);
38
+ container.addChild(new DynamicBorder());
39
+ return { container, selectList };
40
+ }
@@ -0,0 +1,168 @@
1
+ import {
2
+ type Component,
3
+ Container,
4
+ fuzzyFilter,
5
+ Input,
6
+ matchesKey,
7
+ padding,
8
+ truncateToWidth,
9
+ visibleWidth,
10
+ } from "@gajae-code/tui";
11
+ import { sanitizeStatusText } from "../shared";
12
+ import { theme } from "../theme/theme";
13
+ import { DynamicBorder } from "./dynamic-border";
14
+
15
+ export interface CommandPaletteAction {
16
+ id: string;
17
+ label: string;
18
+ handler: () => void | Promise<void>;
19
+ }
20
+
21
+ export interface CommandPaletteEntry {
22
+ id: string;
23
+ label: string;
24
+ description?: string;
25
+ category?: string;
26
+ keybinding?: string;
27
+ bindingHint?: string;
28
+ searchText?: string;
29
+ handler?: () => void | Promise<void>;
30
+ disabled?: boolean;
31
+ }
32
+
33
+ function sanitizePaletteText(text: string): string {
34
+ return sanitizeStatusText(text.toWellFormed());
35
+ }
36
+
37
+ function isSafePaletteEntryId(id: string): boolean {
38
+ return id.length > 0 && !/[\s\u0000-\u001f\u007f-\u009f]/u.test(id);
39
+ }
40
+
41
+ class CommandPaletteList implements Component {
42
+ #entries: CommandPaletteEntry[];
43
+ #filteredEntries: CommandPaletteEntry[];
44
+ #selectedIndex = 0;
45
+ readonly #searchInput = new Input();
46
+ onSelect?: (entry: CommandPaletteEntry) => void;
47
+ onCancel?: () => void;
48
+
49
+ constructor(entries: CommandPaletteEntry[]) {
50
+ this.#entries = entries.map(entry => ({
51
+ ...entry,
52
+ label: sanitizePaletteText(entry.label),
53
+ description: sanitizePaletteText(entry.description ?? entry.category ?? ""),
54
+ category: entry.category === undefined ? undefined : sanitizePaletteText(entry.category),
55
+ keybinding:
56
+ entry.keybinding === undefined && entry.bindingHint === undefined
57
+ ? undefined
58
+ : sanitizePaletteText(entry.keybinding ?? entry.bindingHint ?? ""),
59
+ bindingHint: entry.bindingHint === undefined ? undefined : sanitizePaletteText(entry.bindingHint),
60
+ searchText: entry.searchText === undefined ? undefined : sanitizePaletteText(entry.searchText),
61
+ }));
62
+ this.#filteredEntries = this.#entries;
63
+ }
64
+
65
+ #filter(query: string): void {
66
+ this.#filteredEntries = fuzzyFilter(this.#entries, query, entry =>
67
+ [entry.label, entry.description, entry.keybinding ?? "", entry.searchText ?? ""].join(" "),
68
+ );
69
+ this.#selectedIndex = Math.max(0, Math.min(this.#selectedIndex, this.#filteredEntries.length - 1));
70
+ }
71
+
72
+ invalidate(): void {}
73
+
74
+ getEntries(): readonly CommandPaletteEntry[] {
75
+ return this.#filteredEntries;
76
+ }
77
+
78
+ render(width: number): string[] {
79
+ const lines = [theme.fg("muted", " Search commands"), ...this.#searchInput.render(width), ""];
80
+ if (this.#filteredEntries.length === 0) {
81
+ lines.push(theme.fg("muted", " No matching commands"));
82
+ return lines;
83
+ }
84
+
85
+ const maxVisible = 8;
86
+ const start = Math.max(
87
+ 0,
88
+ Math.min(this.#selectedIndex - Math.floor(maxVisible / 2), this.#filteredEntries.length - maxVisible),
89
+ );
90
+ const end = Math.min(start + maxVisible, this.#filteredEntries.length);
91
+ for (let index = start; index < end; index += 1) {
92
+ const entry = this.#filteredEntries[index];
93
+ if (!entry) continue;
94
+ const selected = index === this.#selectedIndex;
95
+ const cursor = `${theme.nav.cursor} `;
96
+ const prefix = selected ? theme.fg("accent", cursor) : padding(visibleWidth(cursor));
97
+ const keybinding = entry.keybinding ? theme.fg("muted", entry.keybinding) : "";
98
+ const availableLabelWidth = Math.max(
99
+ 1,
100
+ width - visibleWidth(prefix) - visibleWidth(keybinding) - (keybinding ? 1 : 0),
101
+ );
102
+ const label = truncateToWidth(entry.label, availableLabelWidth);
103
+ const labelPadding = padding(Math.max(0, availableLabelWidth - visibleWidth(label)));
104
+ const renderedLabel = selected ? theme.bold(label) : label;
105
+ lines.push(
106
+ entry.disabled
107
+ ? theme.fg("muted", prefix + renderedLabel + labelPadding + (keybinding ? ` ${keybinding}` : ""))
108
+ : prefix + renderedLabel + labelPadding + (keybinding ? ` ${keybinding}` : ""),
109
+ );
110
+ lines.push(theme.fg("dim", truncateToWidth(` ${entry.description ?? ""}`, width)));
111
+ }
112
+ if (start > 0 || end < this.#filteredEntries.length) {
113
+ lines.push(theme.fg("muted", ` (${this.#selectedIndex + 1}/${this.#filteredEntries.length})`));
114
+ }
115
+ lines.push("", theme.fg("muted", " [Enter to run, Esc to close]"));
116
+ return lines;
117
+ }
118
+
119
+ handleInput(data: string): void {
120
+ if (matchesKey(data, "escape")) {
121
+ this.onCancel?.();
122
+ return;
123
+ }
124
+ if (matchesKey(data, "up")) {
125
+ this.#selectedIndex = Math.max(0, this.#selectedIndex - 1);
126
+ return;
127
+ }
128
+ if (matchesKey(data, "down")) {
129
+ this.#selectedIndex = Math.min(this.#filteredEntries.length - 1, this.#selectedIndex + 1);
130
+ return;
131
+ }
132
+ if (matchesKey(data, "enter") || matchesKey(data, "return") || data === "\n") {
133
+ const entry = this.#filteredEntries[this.#selectedIndex];
134
+ if (entry && !entry.disabled && isSafePaletteEntryId(entry.id)) this.onSelect?.(entry);
135
+ return;
136
+ }
137
+ this.#searchInput.handleInput(data);
138
+ this.#filter(this.#searchInput.getValue());
139
+ }
140
+ }
141
+
142
+ export class CommandPaletteComponent extends Container {
143
+ #list: CommandPaletteList;
144
+
145
+ constructor(entries: CommandPaletteEntry[], onSelect: (entry: CommandPaletteEntry) => void, onCancel: () => void) {
146
+ super();
147
+ this.addChild(new DynamicBorder());
148
+ this.#list = new CommandPaletteList(entries);
149
+ this.#list.onSelect = onSelect;
150
+ this.#list.onCancel = onCancel;
151
+ this.addChild(this.#list);
152
+ this.addChild(new DynamicBorder());
153
+ }
154
+
155
+ override render(width: number): string[] {
156
+ return super.render(width).map(line => truncateToWidth(line, width));
157
+ }
158
+ handleInput(data: string): void {
159
+ this.#list.handleInput(data);
160
+ }
161
+
162
+ getEntries(): readonly CommandPaletteEntry[] {
163
+ return this.#list.getEntries();
164
+ }
165
+ }
166
+
167
+ /** Backward-compatible name retained for extensions and existing call sites. */
168
+ export class CommandPalette extends CommandPaletteComponent {}
@@ -402,7 +402,7 @@ export class CustomEditor extends Editor {
402
402
  }
403
403
  }
404
404
 
405
- // Pass to parent for normal handling
405
+ // Pass to parent for normal handling.
406
406
  super.handleInput(data);
407
407
  }
408
408
  }
@@ -1,4 +1,4 @@
1
- import { Container, Input, matchesKey, Spacer, Text, TruncatedText } from "@gajae-code/tui";
1
+ import { Container, Input, matchesKey, SecretInput, Spacer, Text, TruncatedText } from "@gajae-code/tui";
2
2
  import type { ProviderCompatibility, ProviderSetupInput } from "../../setup/provider-onboarding";
3
3
  import { theme } from "../theme/theme";
4
4
  import { matchesAppInterrupt } from "../utils/keybinding-matchers";
@@ -29,7 +29,7 @@ export type CustomProviderWizardSubmit = ProviderSetupInput;
29
29
 
30
30
  export class CustomProviderWizardComponent extends Container {
31
31
  #contentContainer: Container;
32
- #input: Input | null = null;
32
+ #input: Input | SecretInput | null = null;
33
33
  #step: WizardStep = "compatibility";
34
34
  #selectedIndex = 0;
35
35
  #lastSubmitError: string | null = null;
@@ -82,6 +82,7 @@ export class CustomProviderWizardComponent extends Container {
82
82
  handleInput(keyData: string): void {
83
83
  if (matchesAppInterrupt(keyData)) {
84
84
  if (this.#step === "compatibility") {
85
+ this.#clearLiteralCredential();
85
86
  this.#onCancel();
86
87
  return;
87
88
  }
@@ -90,6 +91,10 @@ export class CustomProviderWizardComponent extends Container {
90
91
  }
91
92
 
92
93
  if (this.#input) {
94
+ if (this.#input instanceof SecretInput) {
95
+ this.#input.handleInput(keyData);
96
+ return;
97
+ }
93
98
  if (matchesKey(keyData, "enter") || matchesKey(keyData, "return") || keyData === "\n") {
94
99
  this.#saveInputAndProceed();
95
100
  return;
@@ -138,16 +143,16 @@ export class CustomProviderWizardComponent extends Container {
138
143
  this.#renderCredentialSourceStep();
139
144
  break;
140
145
  case "credential":
141
- this.#renderInputStep(
142
- "Step 5: Credential",
143
- this.#state.credentialSource === "env"
144
- ? "Enter the API key environment variable name:"
145
- : "Paste the API key:",
146
- this.#state.credential,
147
- this.#state.credentialSource === "env"
148
- ? "e.g. OPENAI_API_KEY"
149
- : "The key will be stored in models.yml and redacted in output.",
150
- );
146
+ if (this.#state.credentialSource === "env") {
147
+ this.#renderInputStep(
148
+ "Step 5: Credential",
149
+ "Enter the API key environment variable name:",
150
+ this.#state.credential,
151
+ "e.g. OPENAI_API_KEY",
152
+ );
153
+ } else {
154
+ this.#renderSecretInputStep();
155
+ }
151
156
  break;
152
157
  case "models":
153
158
  this.#renderInputStep(
@@ -198,6 +203,27 @@ export class CustomProviderWizardComponent extends Container {
198
203
  this.#addHelp("[Enter to continue, Esc to go back]");
199
204
  }
200
205
 
206
+ #renderSecretInputStep(): void {
207
+ this.#contentContainer.addChild(new Text(theme.fg("accent", "Step 5: Credential")));
208
+ this.#contentContainer.addChild(new Spacer(1));
209
+ this.#contentContainer.addChild(new Text("Paste the API key:", 0, 0));
210
+ this.#contentContainer.addChild(new Spacer(1));
211
+ const input = new SecretInput();
212
+ input.onSubmit = secret => {
213
+ const credential = secret.consume().trim();
214
+ if (!credential) return;
215
+ this.#state.credential = credential;
216
+ this.#step = "models";
217
+ this.#renderStep();
218
+ this.#onRender();
219
+ };
220
+ this.#input = input;
221
+ this.#contentContainer.addChild(input);
222
+ this.#contentContainer.addChild(new Spacer(1));
223
+ this.#addHelp("The key will be stored securely and redacted in output.");
224
+ this.#addHelp("[Enter to continue, Esc to go back]");
225
+ }
226
+
201
227
  #renderConfirmStep(force: boolean): void {
202
228
  this.#contentContainer.addChild(
203
229
  new Text(theme.fg("accent", force ? "Provider exists — replace it?" : "Confirm custom provider")),
@@ -235,7 +261,8 @@ export class CustomProviderWizardComponent extends Container {
235
261
  }
236
262
 
237
263
  #saveInputAndProceed(): void {
238
- const value = this.#input?.getValue().trim() ?? "";
264
+ if (!(this.#input instanceof Input)) return;
265
+ const value = this.#input.getValue().trim();
239
266
  if (!value) return;
240
267
  if (this.#step === "provider-id") {
241
268
  this.#state.providerId = value;
@@ -277,7 +304,7 @@ export class CustomProviderWizardComponent extends Container {
277
304
  }
278
305
 
279
306
  #buildInput(force: boolean): CustomProviderWizardSubmit {
280
- return {
307
+ const input = {
281
308
  compatibility: this.#state.compatibility,
282
309
  providerId: this.#state.providerId,
283
310
  baseUrl: this.#state.baseUrl,
@@ -289,6 +316,16 @@ export class CustomProviderWizardComponent extends Container {
289
316
  .filter(Boolean),
290
317
  force,
291
318
  };
319
+
320
+ return input;
321
+ }
322
+
323
+ complete(): void {
324
+ this.#clearLiteralCredential();
325
+ }
326
+
327
+ #clearLiteralCredential(): void {
328
+ if (this.#state.credentialSource === "literal") this.#state.credential = "";
292
329
  }
293
330
 
294
331
  #moveSelection(delta: number): void {
@@ -3,6 +3,7 @@ export * from "./assistant-message";
3
3
  export * from "./bash-execution";
4
4
  export * from "./bordered-loader";
5
5
  export * from "./branch-summary-message";
6
+ export * from "./chrome";
6
7
  export * from "./compaction-summary-message";
7
8
  export * from "./countdown-timer";
8
9
  export * from "./custom-editor";
@@ -23,11 +24,11 @@ export * from "./read-tool-group";
23
24
  export * from "./session-selector";
24
25
  export * from "./settings-selector";
25
26
  export * from "./show-images-selector";
26
- export * from "./status-line";
27
27
  export * from "./theme-selector";
28
28
  export * from "./thinking-selector";
29
29
  export * from "./todo-reminder";
30
30
  export * from "./tool-execution";
31
+ export * from "./tool-status-header";
31
32
  export * from "./tree-selector";
32
33
  export * from "./ttsr-notification";
33
34
  export * from "./user-message";
@@ -1,6 +1,5 @@
1
- import { Container, PET_SKIN_IDS, PET_SKINS, SelectList } from "@gajae-code/tui";
2
- import { getSelectListTheme } from "../theme/theme";
3
- import { DynamicBorder } from "./dynamic-border";
1
+ import { Container, PET_SKIN_IDS, PET_SKINS, type SelectList } from "@gajae-code/tui";
2
+ import { FramedSelect } from "./chrome";
4
3
  import type { PetMode } from "./gajae-pet-widget";
5
4
  import { createPetSelectItems } from "./pet-capability";
6
5
 
@@ -31,20 +30,15 @@ export class PetSelectorComponent extends Container {
31
30
 
32
31
  const items = createPetSelectItems(PET_OPTIONS, current, available);
33
32
 
34
- this.addChild(new DynamicBorder());
35
-
36
- this.#selectList = new SelectList(items, 10, getSelectListTheme());
37
- const currentIndex = PET_OPTIONS.findIndex(option => option.value === current);
38
- if (currentIndex !== -1) {
39
- this.#selectList.setSelectedIndex(currentIndex);
40
- }
41
-
42
- this.#selectList.onSelect = item => onSelect(item.value as PetMode);
43
- this.#selectList.onCancel = () => onCancel();
44
- this.#selectList.onSelectionChange = item => onPreview(item.value as PetMode);
45
-
46
- this.addChild(this.#selectList);
47
- this.addChild(new DynamicBorder());
33
+ const framed = FramedSelect(undefined, items, {
34
+ maxVisible: 10,
35
+ selectedValue: current,
36
+ onSelect: item => onSelect(item.value as PetMode),
37
+ onCancel,
38
+ onSelectionChange: item => onPreview(item.value as PetMode),
39
+ });
40
+ this.#selectList = framed.selectList;
41
+ this.addChild(framed.container);
48
42
  }
49
43
 
50
44
  getSelectList(): SelectList {