@gajae-code/coding-agent 0.11.1 → 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 (404) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/dist/types/cli/config-cli.d.ts +11 -1
  3. package/dist/types/cli/notify-cli.d.ts +1 -0
  4. package/dist/types/cli/session-picker.d.ts +2 -1
  5. package/dist/types/cli/setup-cli.d.ts +1 -1
  6. package/dist/types/commands/mcp-serve.d.ts +33 -0
  7. package/dist/types/commands/mcp.d.ts +1 -1
  8. package/dist/types/commands/notify.d.ts +0 -2
  9. package/dist/types/commands/sdk.d.ts +1 -1
  10. package/dist/types/config/atomic-yaml-patch.d.ts +18 -0
  11. package/dist/types/config/file-lock.d.ts +14 -4
  12. package/dist/types/config/keybindings.d.ts +42 -1
  13. package/dist/types/config/model-auth.d.ts +3 -0
  14. package/dist/types/config/model-bindings-applier.d.ts +13 -0
  15. package/dist/types/config/model-discovery-manager.d.ts +49 -0
  16. package/dist/types/config/model-equivalence.d.ts +20 -0
  17. package/dist/types/config/model-registry.d.ts +16 -15
  18. package/dist/types/config/model-resolver.d.ts +28 -18
  19. package/dist/types/config/models-config-schema.d.ts +11 -0
  20. package/dist/types/config/settings-schema.d.ts +56 -1
  21. package/dist/types/config/settings.d.ts +14 -11
  22. package/dist/types/coordinator-mcp/policy.d.ts +5 -0
  23. package/dist/types/coordinator-mcp/question-gate-codec.d.ts +129 -0
  24. package/dist/types/coordinator-mcp/question-state.d.ts +356 -0
  25. package/dist/types/coordinator-mcp/server.d.ts +4 -0
  26. package/dist/types/discovery/helpers.d.ts +0 -6
  27. package/dist/types/edit/index.d.ts +3 -0
  28. package/dist/types/eval/py/env.d.ts +9 -0
  29. package/dist/types/extensibility/extensions/loader.d.ts +2 -1
  30. package/dist/types/extensibility/extensions/runner.d.ts +2 -2
  31. package/dist/types/extensibility/extensions/types.d.ts +34 -3
  32. package/dist/types/extensibility/hooks/runner.d.ts +1 -1
  33. package/dist/types/extensibility/shared-events.d.ts +2 -0
  34. package/dist/types/gjc-runtime/deep-interview-recorder.d.ts +10 -1
  35. package/dist/types/gjc-runtime/deep-interview-state.d.ts +44 -0
  36. package/dist/types/gjc-runtime/goal-mode-request.d.ts +11 -1
  37. package/dist/types/gjc-runtime/launch-worktree.d.ts +4 -2
  38. package/dist/types/gjc-runtime/linux-proc.d.ts +29 -0
  39. package/dist/types/gjc-runtime/session-resolution.d.ts +2 -2
  40. package/dist/types/gjc-runtime/state-migrations.d.ts +1 -1
  41. package/dist/types/gjc-runtime/state-writer.d.ts +2 -1
  42. package/dist/types/gjc-runtime/team-launch.d.ts +59 -0
  43. package/dist/types/gjc-runtime/team-notify.d.ts +45 -0
  44. package/dist/types/gjc-runtime/team-runtime.d.ts +29 -121
  45. package/dist/types/gjc-runtime/team-store.d.ts +160 -0
  46. package/dist/types/gjc-runtime/team-workers.d.ts +78 -0
  47. package/dist/types/gjc-runtime/tmux-owner-isolation.d.ts +8 -0
  48. package/dist/types/gjc-runtime/ultragoal-change-set.d.ts +13 -0
  49. package/dist/types/gjc-runtime/ultragoal-evidence.d.ts +38 -0
  50. package/dist/types/gjc-runtime/ultragoal-guard.d.ts +7 -0
  51. package/dist/types/gjc-runtime/ultragoal-pipeline.d.ts +23 -0
  52. package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +55 -33
  53. package/dist/types/gjc-runtime/workflow-cli-common.d.ts +8 -0
  54. package/dist/types/gjc-runtime/workflow-manifest.d.ts +3 -0
  55. package/dist/types/goals/continuation-timeout-guard.d.ts +22 -0
  56. package/dist/types/goals/runtime.d.ts +1 -0
  57. package/dist/types/goals/state.d.ts +8 -0
  58. package/dist/types/harness-control-plane/lifecycle-reconciliation.d.ts +17 -0
  59. package/dist/types/harness-control-plane/phase-rollup.d.ts +4 -7
  60. package/dist/types/harness-control-plane/receipt-ingest.d.ts +5 -0
  61. package/dist/types/harness-control-plane/receipt-spool.d.ts +4 -0
  62. package/dist/types/hindsight/state.d.ts +11 -4
  63. package/dist/types/lsp/lspmux.d.ts +5 -3
  64. package/dist/types/lsp/path-trust.d.ts +1 -0
  65. package/dist/types/main.d.ts +3 -2
  66. package/dist/types/memories/storage.d.ts +1 -0
  67. package/dist/types/modes/action-registry.d.ts +29 -0
  68. package/dist/types/modes/components/chrome.d.ts +14 -0
  69. package/dist/types/modes/components/command-palette.d.ts +27 -0
  70. package/dist/types/modes/components/custom-provider-wizard.d.ts +1 -0
  71. package/dist/types/modes/components/index.d.ts +2 -1
  72. package/dist/types/modes/components/pet-selector.d.ts +1 -1
  73. package/dist/types/modes/components/plan-preview-overlay.d.ts +43 -0
  74. package/dist/types/modes/components/queue-mode-selector.d.ts +1 -1
  75. package/dist/types/modes/components/queue-pane.d.ts +12 -0
  76. package/dist/types/modes/components/read-tool-group.d.ts +6 -0
  77. package/dist/types/modes/components/session-observer-overlay.d.ts +3 -4
  78. package/dist/types/modes/components/sessions-dashboard.d.ts +32 -0
  79. package/dist/types/modes/components/settings-selector.d.ts +1 -1
  80. package/dist/types/modes/components/show-images-selector.d.ts +1 -1
  81. package/dist/types/modes/components/status-line/types.d.ts +1 -1
  82. package/dist/types/modes/components/status-line.d.ts +1 -94
  83. package/dist/types/modes/components/tasks-pane.d.ts +15 -0
  84. package/dist/types/modes/components/theme-selector.d.ts +1 -1
  85. package/dist/types/modes/components/tool-execution.d.ts +15 -0
  86. package/dist/types/modes/components/tool-status-header.d.ts +111 -0
  87. package/dist/types/modes/components/transcript-viewer-overlay.d.ts +42 -0
  88. package/dist/types/modes/controllers/goal-mode-controller.d.ts +62 -0
  89. package/dist/types/modes/controllers/input-controller.d.ts +8 -1
  90. package/dist/types/modes/controllers/mode-gate.d.ts +8 -0
  91. package/dist/types/modes/controllers/plan-mode-controller.d.ts +65 -0
  92. package/dist/types/modes/controllers/selector-controller.d.ts +15 -3
  93. package/dist/types/modes/controllers/stt-controller.d.ts +26 -0
  94. package/dist/types/modes/interactive-mode.d.ts +19 -17
  95. package/dist/types/modes/jobs-observer.d.ts +2 -0
  96. package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +4 -11
  97. package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +20 -2
  98. package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +31 -0
  99. package/dist/types/modes/tasks-aggregator.d.ts +39 -0
  100. package/dist/types/modes/transcript-item-registry.d.ts +60 -0
  101. package/dist/types/modes/types.d.ts +20 -13
  102. package/dist/types/modes/utils/ui-helpers.d.ts +2 -2
  103. package/dist/types/runtime-mcp/manager.d.ts +1 -1
  104. package/dist/types/sdk/broker/broker.d.ts +78 -12
  105. package/dist/types/sdk/broker/lifecycle-codec.d.ts +4 -0
  106. package/dist/types/sdk/broker/lifecycle-ledger.d.ts +15 -1
  107. package/dist/types/sdk/broker/lifecycle.d.ts +6 -2
  108. package/dist/types/sdk/broker/process-incarnation.d.ts +2 -0
  109. package/dist/types/sdk/broker/session-index.d.ts +0 -1
  110. package/dist/types/sdk/broker/state-version.d.ts +2 -0
  111. package/dist/types/sdk/bus/chat-effect-journal.d.ts +1 -0
  112. package/dist/types/sdk/bus/config-commands.d.ts +1 -1
  113. package/dist/types/sdk/bus/config.d.ts +11 -0
  114. package/dist/types/sdk/bus/daemon-paths.d.ts +1 -0
  115. package/dist/types/sdk/bus/html-format.d.ts +3 -2
  116. package/dist/types/sdk/bus/index.d.ts +27 -0
  117. package/dist/types/sdk/bus/lifecycle-control-runtime.d.ts +4 -0
  118. package/dist/types/sdk/bus/notification-service.d.ts +20 -0
  119. package/dist/types/sdk/bus/rate-limit-pool.d.ts +13 -2
  120. package/dist/types/sdk/bus/recent-activity.d.ts +21 -12
  121. package/dist/types/sdk/bus/rich-document.d.ts +7 -0
  122. package/dist/types/sdk/bus/rich-render.d.ts +18 -41
  123. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +9 -4
  124. package/dist/types/sdk/bus/telegram-daemon.d.ts +46 -3
  125. package/dist/types/sdk/bus/threaded-inbound.d.ts +1 -1
  126. package/dist/types/sdk/bus/threaded-render.d.ts +13 -0
  127. package/dist/types/sdk/bus/topic-registry.d.ts +24 -2
  128. package/dist/types/sdk/host/control/operations.d.ts +1 -1
  129. package/dist/types/sdk/host/host.d.ts +2 -0
  130. package/dist/types/sdk/index.d.ts +1 -0
  131. package/dist/types/sdk/session-directory.d.ts +56 -0
  132. package/dist/types/session/agent-session.d.ts +82 -47
  133. package/dist/types/session/agent-storage.d.ts +7 -0
  134. package/dist/types/session/fallback-chain-controller.d.ts +10 -2
  135. package/dist/types/session/internal/managed-session-scope.d.ts +102 -0
  136. package/dist/types/session/internal/managed-session-storage.d.ts +38 -0
  137. package/dist/types/session/messages.d.ts +16 -0
  138. package/dist/types/session/session-manager-internal.d.ts +14 -0
  139. package/dist/types/session/session-manager.d.ts +82 -12
  140. package/dist/types/session/session-storage.d.ts +43 -3
  141. package/dist/types/session/volatile-context-pruning.d.ts +15 -0
  142. package/dist/types/skill-state/{deep-interview-mutation-guard.d.ts → workflow-mutation-guard.d.ts} +24 -8
  143. package/dist/types/skill-state/workflow-state-contract.d.ts +1 -3
  144. package/dist/types/slash-commands/builtin-registry.d.ts +4 -1
  145. package/dist/types/system-prompt.d.ts +2 -11
  146. package/dist/types/task/executor.d.ts +3 -1
  147. package/dist/types/thinking.d.ts +7 -0
  148. package/dist/types/tool-discovery/tool-index.d.ts +1 -50
  149. package/dist/types/tools/ask.d.ts +64 -2
  150. package/dist/types/tools/bash.d.ts +3 -0
  151. package/dist/types/tools/browser/dead-tab-recovery.d.ts +24 -0
  152. package/dist/types/tools/browser/tab-supervisor.d.ts +21 -0
  153. package/dist/types/tools/cron.d.ts +2 -0
  154. package/dist/types/tools/fetch.d.ts +1 -0
  155. package/dist/types/tools/index.d.ts +30 -15
  156. package/dist/types/tools/output-meta.d.ts +1 -0
  157. package/dist/types/tools/read.d.ts +3 -0
  158. package/dist/types/tools/search-tool-bm25.d.ts +3 -4
  159. package/dist/types/utils/event-bus.d.ts +1 -1
  160. package/dist/types/web/search/index.d.ts +3 -1
  161. package/package.json +21 -9
  162. package/scripts/build-sdk-package-smoke.ts +34 -1
  163. package/scripts/generate-hotkeys-docs.ts +74 -0
  164. package/scripts/generate-sdk-operation-inventory.ts +64 -20
  165. package/scripts/verify-gjc-sdk-canonicalization.ts +182 -2
  166. package/src/async/job-manager.ts +49 -6
  167. package/src/cli/config-cli.ts +75 -2
  168. package/src/cli/notify-cli.ts +92 -26
  169. package/src/cli/session-picker.ts +20 -3
  170. package/src/cli/setup-cli.ts +1 -1
  171. package/src/cli.ts +1 -1
  172. package/src/commands/config.ts +1 -1
  173. package/src/commands/harness.ts +34 -106
  174. package/src/commands/launch.ts +6 -4
  175. package/src/commands/mcp-serve.ts +85 -8
  176. package/src/commands/mcp.ts +2 -2
  177. package/src/commands/notify.ts +8 -4
  178. package/src/commands/sdk.ts +61 -40
  179. package/src/commands/ultragoal.ts +4 -1
  180. package/src/config/atomic-yaml-patch.ts +80 -13
  181. package/src/config/file-lock.ts +105 -43
  182. package/src/config/keybindings.ts +64 -20
  183. package/src/config/model-auth.ts +9 -0
  184. package/src/config/model-bindings-applier.ts +139 -0
  185. package/src/config/model-discovery-manager.ts +224 -0
  186. package/src/config/model-equivalence.ts +66 -0
  187. package/src/config/model-registry.ts +169 -302
  188. package/src/config/model-resolver.ts +361 -369
  189. package/src/config/models-config-schema.ts +5 -4
  190. package/src/config/settings-schema.ts +159 -2
  191. package/src/config/settings.ts +458 -482
  192. package/src/coordinator-mcp/policy.ts +76 -11
  193. package/src/coordinator-mcp/question-gate-codec.ts +274 -0
  194. package/src/coordinator-mcp/question-state.ts +778 -0
  195. package/src/coordinator-mcp/server.ts +1702 -238
  196. package/src/debug/index.ts +1 -1
  197. package/src/defaults/gjc/skills/deep-interview/SKILL.md +13 -1
  198. package/src/defaults/gjc/skills/team/SKILL.md +16 -0
  199. package/src/discovery/helpers.ts +1 -50
  200. package/src/edit/index.ts +64 -0
  201. package/src/eval/py/env.ts +26 -0
  202. package/src/eval/py/kernel.ts +5 -3
  203. package/src/extensibility/extensions/loader.ts +9 -1
  204. package/src/extensibility/extensions/runner.ts +12 -3
  205. package/src/extensibility/extensions/types.ts +39 -1
  206. package/src/extensibility/gjc-plugins/installer.ts +16 -16
  207. package/src/extensibility/hooks/runner.ts +2 -2
  208. package/src/extensibility/runtime-skill-discovery.ts +33 -13
  209. package/src/extensibility/shared-events.ts +2 -0
  210. package/src/gjc-runtime/deep-interview-recorder.ts +63 -3
  211. package/src/gjc-runtime/deep-interview-runtime.ts +76 -27
  212. package/src/gjc-runtime/deep-interview-state.ts +317 -5
  213. package/src/gjc-runtime/goal-mode-request.ts +55 -8
  214. package/src/gjc-runtime/launch-tmux.ts +2 -5
  215. package/src/gjc-runtime/launch-worktree.ts +5 -5
  216. package/src/gjc-runtime/linux-proc.ts +71 -0
  217. package/src/gjc-runtime/ralplan-runtime.ts +74 -90
  218. package/src/gjc-runtime/session-resolution.ts +18 -3
  219. package/src/gjc-runtime/session-state-sidecar.ts +6 -107
  220. package/src/gjc-runtime/state-migrations.ts +1 -1
  221. package/src/gjc-runtime/state-runtime.ts +320 -249
  222. package/src/gjc-runtime/state-writer.ts +36 -40
  223. package/src/gjc-runtime/team-launch.ts +319 -0
  224. package/src/gjc-runtime/team-notify.ts +326 -0
  225. package/src/gjc-runtime/team-runtime.ts +1099 -1482
  226. package/src/gjc-runtime/team-store.ts +828 -0
  227. package/src/gjc-runtime/team-workers.ts +962 -0
  228. package/src/gjc-runtime/tmux-owner-isolation-cli.ts +2 -11
  229. package/src/gjc-runtime/tmux-owner-isolation.ts +14 -9
  230. package/src/gjc-runtime/tmux-sessions.ts +4 -21
  231. package/src/gjc-runtime/ultragoal-change-set.ts +172 -0
  232. package/src/gjc-runtime/ultragoal-evidence.ts +874 -0
  233. package/src/gjc-runtime/ultragoal-guard.ts +29 -5
  234. package/src/gjc-runtime/ultragoal-pipeline.ts +306 -0
  235. package/src/gjc-runtime/ultragoal-runtime.ts +84 -1311
  236. package/src/gjc-runtime/workflow-cli-common.ts +30 -0
  237. package/src/gjc-runtime/workflow-manifest.generated.json +58 -0
  238. package/src/gjc-runtime/workflow-manifest.ts +18 -0
  239. package/src/goals/continuation-timeout-guard.ts +79 -0
  240. package/src/goals/runtime.ts +7 -5
  241. package/src/goals/state.ts +18 -0
  242. package/src/harness-control-plane/lifecycle-reconciliation.ts +64 -0
  243. package/src/harness-control-plane/phase-rollup.ts +4 -7
  244. package/src/harness-control-plane/receipt-ingest.ts +5 -0
  245. package/src/harness-control-plane/receipt-spool.ts +51 -7
  246. package/src/harness-control-plane/session-lease.ts +12 -130
  247. package/src/hindsight/backend.ts +26 -27
  248. package/src/hindsight/state.ts +101 -32
  249. package/src/hooks/skill-state.ts +17 -11
  250. package/src/internal-urls/docs-index.generated.ts +21 -18
  251. package/src/lsp/client.ts +1 -1
  252. package/src/lsp/config.ts +145 -26
  253. package/src/lsp/index.ts +1 -1
  254. package/src/lsp/lspmux.ts +39 -10
  255. package/src/lsp/path-trust.ts +81 -0
  256. package/src/main.ts +28 -8
  257. package/src/memories/index.ts +1 -0
  258. package/src/memories/storage.ts +6 -2
  259. package/src/modes/action-registry.ts +165 -0
  260. package/src/modes/components/chrome.ts +40 -0
  261. package/src/modes/components/command-palette.ts +168 -0
  262. package/src/modes/components/custom-editor.ts +1 -1
  263. package/src/modes/components/custom-provider-wizard.ts +51 -14
  264. package/src/modes/components/index.ts +2 -1
  265. package/src/modes/components/pet-selector.ts +11 -17
  266. package/src/modes/components/plan-preview-overlay.ts +295 -0
  267. package/src/modes/components/queue-mode-selector.ts +10 -27
  268. package/src/modes/components/queue-pane.ts +79 -0
  269. package/src/modes/components/read-tool-group.ts +13 -0
  270. package/src/modes/components/session-observer-overlay.ts +207 -772
  271. package/src/modes/components/sessions-dashboard.ts +181 -0
  272. package/src/modes/components/settings-selector.ts +1 -1
  273. package/src/modes/components/show-images-selector.ts +10 -24
  274. package/src/modes/components/status-line/types.ts +1 -1
  275. package/src/modes/components/status-line.ts +1 -969
  276. package/src/modes/components/tasks-pane.ts +73 -0
  277. package/src/modes/components/theme-selector.ts +11 -31
  278. package/src/modes/components/tool-execution.ts +22 -0
  279. package/src/modes/components/tool-status-header.ts +1056 -0
  280. package/src/modes/components/transcript-viewer-overlay.ts +384 -0
  281. package/src/modes/controllers/btw-controller.ts +1 -0
  282. package/src/modes/controllers/event-controller.ts +3 -2
  283. package/src/modes/controllers/extension-ui-controller.ts +24 -1
  284. package/src/modes/controllers/goal-mode-controller.ts +474 -0
  285. package/src/modes/controllers/input-controller.ts +764 -229
  286. package/src/modes/controllers/mode-gate.ts +24 -0
  287. package/src/modes/controllers/plan-mode-controller.ts +517 -0
  288. package/src/modes/controllers/selector-controller.ts +225 -10
  289. package/src/modes/controllers/stt-controller.ts +125 -0
  290. package/src/modes/interactive-mode.ts +289 -1150
  291. package/src/modes/jobs-observer.ts +3 -0
  292. package/src/modes/runtime-init.ts +8 -0
  293. package/src/modes/shared/agent-wire/deep-interview-gate.ts +31 -106
  294. package/src/modes/shared/agent-wire/workflow-gate-broker.ts +71 -16
  295. package/src/modes/shared/agent-wire/workflow-gate-types.ts +177 -0
  296. package/src/modes/tasks-aggregator.ts +199 -0
  297. package/src/modes/transcript-item-registry.ts +229 -0
  298. package/src/modes/types.ts +45 -18
  299. package/src/modes/utils/ui-helpers.ts +17 -9
  300. package/src/prompts/agent-fragments/ralplan-persistence.md +6 -0
  301. package/src/prompts/agent-fragments/restricted-bash.md +1 -0
  302. package/src/prompts/agents/architect.md +2 -8
  303. package/src/prompts/agents/critic.md +2 -8
  304. package/src/prompts/agents/executor.md +3 -0
  305. package/src/prompts/agents/planner.md +4 -12
  306. package/src/prompts/system/custom-system-prompt.md +1 -23
  307. package/src/prompts/system/plan-mode-approved.md +8 -0
  308. package/src/prompts/system/system-prompt.md +17 -96
  309. package/src/prompts/tools/bash.md +4 -4
  310. package/src/prompts/tools/browser.md +15 -52
  311. package/src/prompts/tools/find.md +2 -2
  312. package/src/prompts/tools/hashline.md +13 -55
  313. package/src/prompts/tools/read.md +3 -6
  314. package/src/prompts/tools/search-tool-bm25.md +0 -2
  315. package/src/prompts/tools/search.md +2 -4
  316. package/src/prompts/tools/skill-discovery.md +1 -2
  317. package/src/prompts/tools/task.md +1 -1
  318. package/src/runtime-mcp/manager.ts +1 -1
  319. package/src/sdk/broker/broker.ts +206 -78
  320. package/src/sdk/broker/discovery.ts +1 -1
  321. package/src/sdk/broker/ensure.ts +3 -1
  322. package/src/sdk/broker/lifecycle-codec.ts +11 -0
  323. package/src/sdk/broker/lifecycle-ledger.ts +371 -74
  324. package/src/sdk/broker/lifecycle.ts +1399 -142
  325. package/src/sdk/broker/process-incarnation.ts +5 -13
  326. package/src/sdk/broker/session-index.ts +145 -56
  327. package/src/sdk/broker/state-version.ts +21 -0
  328. package/src/sdk/broker/transport.ts +1 -1
  329. package/src/sdk/bus/chat-daemon-cli.ts +2 -0
  330. package/src/sdk/bus/chat-daemon-control.ts +8 -28
  331. package/src/sdk/bus/chat-effect-journal.ts +10 -2
  332. package/src/sdk/bus/config-commands.ts +5 -4
  333. package/src/sdk/bus/config.ts +98 -0
  334. package/src/sdk/bus/conversation-store.ts +5 -29
  335. package/src/sdk/bus/daemon-paths.ts +2 -0
  336. package/src/sdk/bus/html-format.ts +20 -3
  337. package/src/sdk/bus/index.ts +778 -93
  338. package/src/sdk/bus/lifecycle-control-runtime.ts +91 -33
  339. package/src/sdk/bus/natives-augment.d.ts +26 -1
  340. package/src/sdk/bus/notification-service.ts +168 -20
  341. package/src/sdk/bus/rate-limit-pool.ts +58 -14
  342. package/src/sdk/bus/recent-activity.ts +188 -74
  343. package/src/sdk/bus/rich-document.ts +258 -0
  344. package/src/sdk/bus/rich-render.ts +62 -70
  345. package/src/sdk/bus/telegram-daemon-cli.ts +15 -59
  346. package/src/sdk/bus/telegram-daemon-contract.ts +9 -4
  347. package/src/sdk/bus/telegram-daemon.ts +1389 -237
  348. package/src/sdk/bus/threaded-inbound.ts +8 -3
  349. package/src/sdk/bus/threaded-render.ts +57 -1
  350. package/src/sdk/bus/topic-registry.ts +120 -13
  351. package/src/sdk/host/control/dispatch.ts +14 -2
  352. package/src/sdk/host/control/operations.ts +6 -1
  353. package/src/sdk/host/host.ts +31 -1
  354. package/src/sdk/host/query/handlers.ts +20 -22
  355. package/src/sdk/host/query/revision-store.ts +80 -57
  356. package/src/sdk/index.ts +1 -0
  357. package/src/sdk/protocol/operation-inventory.generated.json +943 -1907
  358. package/src/sdk/session-directory.ts +141 -0
  359. package/src/sdk/session.ts +458 -479
  360. package/src/session/agent-session.ts +1700 -583
  361. package/src/session/agent-storage.ts +18 -0
  362. package/src/session/cache-economics.ts +25 -8
  363. package/src/session/fallback-chain-controller.ts +53 -3
  364. package/src/session/internal/managed-session-scope.ts +2226 -0
  365. package/src/session/internal/managed-session-storage.ts +453 -0
  366. package/src/session/messages.ts +91 -2
  367. package/src/session/session-manager-internal.ts +33 -0
  368. package/src/session/session-manager.ts +1112 -333
  369. package/src/session/session-storage.ts +444 -39
  370. package/src/session/volatile-context-pruning.ts +78 -0
  371. package/src/setup/credential-auto-import.ts +2 -1
  372. package/src/setup/hermes/templates/operator-instructions.v1.md +1 -1
  373. package/src/setup/provider-onboarding.ts +36 -61
  374. package/src/setup/provider-presets.json +5 -0
  375. package/src/skill-state/active-state.ts +3 -13
  376. package/src/skill-state/{deep-interview-mutation-guard.ts → workflow-mutation-guard.ts} +47 -29
  377. package/src/skill-state/workflow-state-contract.ts +6 -41
  378. package/src/slash-commands/builtin-registry.ts +46 -11
  379. package/src/system-prompt.ts +37 -44
  380. package/src/task/agents.ts +19 -1
  381. package/src/task/executor.ts +90 -6
  382. package/src/task/index.ts +36 -21
  383. package/src/thinking.ts +21 -6
  384. package/src/tool-discovery/tool-index.ts +2 -134
  385. package/src/tools/ask.ts +157 -21
  386. package/src/tools/ast-edit.ts +1 -1
  387. package/src/tools/bash.ts +38 -0
  388. package/src/tools/browser/dead-tab-recovery.ts +78 -0
  389. package/src/tools/browser/tab-supervisor.ts +282 -36
  390. package/src/tools/computer.ts +10 -3
  391. package/src/tools/cron.ts +30 -16
  392. package/src/tools/eval.ts +1 -2
  393. package/src/tools/fetch.ts +11 -4
  394. package/src/tools/index.ts +76 -24
  395. package/src/tools/output-meta.ts +13 -5
  396. package/src/tools/read.ts +37 -1
  397. package/src/tools/resource-gc.ts +2 -2
  398. package/src/tools/search-tool-bm25.ts +11 -74
  399. package/src/utils/event-bus.ts +9 -4
  400. package/src/web/search/index.ts +3 -3
  401. package/dist/types/discovery/plugin-dir-roots.d.ts +0 -15
  402. package/dist/types/runtime-mcp/discoverable-tool-metadata.d.ts +0 -7
  403. package/src/discovery/plugin-dir-roots.ts +0 -28
  404. package/src/runtime-mcp/discoverable-tool-metadata.ts +0 -25
@@ -2,9 +2,10 @@ import * as path from "node:path";
2
2
  import { ThinkingLevel } from "@gajae-code/agent-core";
3
3
  import { getOAuthProviders } from "@gajae-code/ai/utils/oauth";
4
4
  import type { OAuthProvider } from "@gajae-code/ai/utils/oauth/types";
5
- import type { Component, OverlayHandle } from "@gajae-code/tui";
5
+ import type { Component, OverlayHandle, SlashCommand } from "@gajae-code/tui";
6
6
  import { Input, isPetMode, Loader, Spacer, Text } from "@gajae-code/tui";
7
7
  import { getAgentDbPath, getProjectDir, logger, VERSION } from "@gajae-code/utils";
8
+ import { type AppKeybinding, formatKeyHints } from "../../config/keybindings";
8
9
  import {
9
10
  activateModelProfile,
10
11
  type MaterializeModelProfileForDeletionResult,
@@ -69,6 +70,8 @@ import {
69
70
  import { TelegramDaemonController } from "../../sdk/bus/telegram-daemon-control";
70
71
  import { runTelegramSetup, type TelegramSetupPreflight } from "../../sdk/bus/telegram-setup";
71
72
  import { type SessionInfo, SessionManager } from "../../session/session-manager";
73
+ import { getTreeForInternalRead } from "../../session/session-manager-internal";
74
+
72
75
  import { FileSessionStorage } from "../../session/session-storage";
73
76
  import {
74
77
  CREDENTIAL_AUTO_IMPORT_DISCOVERY_WARNING,
@@ -105,9 +108,15 @@ import {
105
108
  setSearchFallbackProviders,
106
109
  setSearchHardTimeoutMs,
107
110
  } from "../../tools";
111
+ import { copyToClipboard } from "../../utils/clipboard";
108
112
  import { setSessionTerminalTitle } from "../../utils/title-generator";
109
113
  import { AgentDashboard } from "../components/agent-dashboard";
110
114
  import { AssistantMessageComponent } from "../components/assistant-message";
115
+ import {
116
+ type CommandPaletteAction,
117
+ CommandPaletteComponent,
118
+ type CommandPaletteEntry,
119
+ } from "../components/command-palette";
111
120
  import {
112
121
  CustomModelPresetWizardComponent,
113
122
  type CustomModelPresetWizardSubmit,
@@ -125,6 +134,12 @@ import type {
125
134
  import { OAuthSelectorComponent } from "../components/oauth-selector";
126
135
  import { isPetAvailable } from "../components/pet-capability";
127
136
  import { PetSelectorComponent } from "../components/pet-selector";
137
+ import {
138
+ type PlanPreviewOptions,
139
+ PlanPreviewOverlay,
140
+ type PlanPreviewResult,
141
+ } from "../components/plan-preview-overlay";
142
+
128
143
  import { PluginSelectorComponent } from "../components/plugin-selector";
129
144
  import {
130
145
  type ProviderOnboardingAction,
@@ -132,15 +147,20 @@ import {
132
147
  } from "../components/provider-onboarding-selector";
133
148
  import { SessionObserverOverlayComponent } from "../components/session-observer-overlay";
134
149
  import { SessionSelectorComponent } from "../components/session-selector";
150
+ import { dashboardSessions, SessionsDashboardComponent } from "../components/sessions-dashboard";
135
151
  import { SettingsSelectorComponent } from "../components/settings-selector";
136
- import type { StatusLineSettings } from "../components/status-line";
152
+ import { TasksPaneComponent } from "../components/tasks-pane";
137
153
  import { ThemeSelectorComponent } from "../components/theme-selector";
138
154
  import { ThinkingSelectorComponent } from "../components/thinking-selector";
139
155
  import { ToolExecutionComponent } from "../components/tool-execution";
156
+ import type { StatusLineSettings } from "../components/tool-status-header";
157
+ import { TranscriptViewerOverlay, transcriptViewerEntries } from "../components/transcript-viewer-overlay";
140
158
  import { TreeSelectorComponent } from "../components/tree-selector";
141
159
  import { UserMessageSelectorComponent } from "../components/user-message-selector";
142
160
  import type { JobsObserver } from "../jobs-observer";
143
161
  import type { SessionObserverRegistry } from "../session-observer-registry";
162
+ import type { TasksAggregator } from "../tasks-aggregator";
163
+ import type { TranscriptItemRegistry } from "../transcript-item-registry";
144
164
 
145
165
  const CALLBACK_SERVER_PROVIDERS = new Set<string>([
146
166
  "anthropic",
@@ -684,15 +704,31 @@ export function createNotificationsEditorOperations(
684
704
  }
685
705
 
686
706
  export class SelectorController {
707
+ #transcriptViewerOpen = false;
708
+ #transcriptViewer?: TranscriptViewerOverlay;
709
+ #sessionsDashboardOpen = false;
710
+ #sessionsDashboard?: SessionsDashboardComponent;
711
+ #tasksPane?: TasksPaneComponent;
712
+ #closeTasksPane?: () => void;
713
+
687
714
  #credentialAutoImportStateStore?: CredentialAutoImportStateStore;
688
715
 
689
716
  constructor(
690
717
  private ctx: InteractiveModeContext,
691
718
  credentialAutoImportStateStore?: CredentialAutoImportStateStore,
719
+ private readonly clipboard: (text: string) => void = copyToClipboard,
692
720
  ) {
693
721
  this.#credentialAutoImportStateStore = credentialAutoImportStateStore;
694
722
  }
695
723
 
724
+ isTranscriptViewerOpen(): boolean {
725
+ return this.#transcriptViewerOpen;
726
+ }
727
+ refreshTranscriptViewer(identityMap?: ReadonlyMap<string, string>): void {
728
+ this.#transcriptViewer?.refresh(identityMap);
729
+ this.ctx.ui.requestRender();
730
+ }
731
+
696
732
  async #refreshOAuthProviderAuthState(): Promise<void> {
697
733
  const oauthProviders = getOAuthProviders();
698
734
  await Promise.all(
@@ -726,6 +762,52 @@ export class SelectorController {
726
762
  this.ctx.ui.requestRender();
727
763
  }
728
764
 
765
+ showCommandPalette(
766
+ commands: SlashCommand[],
767
+ actions: CommandPaletteAction[],
768
+ executeSlashCommand: (name: string) => Promise<void>,
769
+ ): void {
770
+ const seenCommands = new Set<string>();
771
+ const entries: CommandPaletteEntry[] = [
772
+ ...actions.map(action => ({
773
+ id: `action:${action.id}`,
774
+ label: action.label,
775
+ description: action.id,
776
+ keybinding: formatKeyHints(this.ctx.keybindings.getKeys(action.id as AppKeybinding)) || undefined,
777
+ searchText: action.id,
778
+ handler: action.handler,
779
+ })),
780
+ ...commands
781
+ .filter(command => {
782
+ if (seenCommands.has(command.name)) return false;
783
+ seenCommands.add(command.name);
784
+ return true;
785
+ })
786
+ .map(command => ({
787
+ id: `command:${command.name}`,
788
+ label: `/${command.name}`,
789
+ description: command.description ?? "Slash command",
790
+ searchText: command.name,
791
+ handler: () => executeSlashCommand(command.name),
792
+ })),
793
+ ];
794
+
795
+ this.showSelector(done => {
796
+ const selector = new CommandPaletteComponent(
797
+ entries,
798
+ entry => {
799
+ done();
800
+ void Promise.resolve()
801
+ .then(() => entry.handler?.())
802
+ .catch(error => {
803
+ this.ctx.showError(error instanceof Error ? error.message : String(error));
804
+ });
805
+ },
806
+ done,
807
+ );
808
+ return { component: selector, focus: selector };
809
+ });
810
+ }
729
811
  showProviderOnboarding(): void {
730
812
  this.showSelector(done => {
731
813
  const selector = new ProviderOnboardingSelectorComponent(
@@ -968,6 +1050,7 @@ export class SelectorController {
968
1050
  await this.ctx.session.modelRegistry.refresh("offline");
969
1051
  await this.ctx.notifyConfigChanged?.();
970
1052
  this.ctx.showStatus(formatProviderSetupResult(result));
1053
+ wizard.complete();
971
1054
  done();
972
1055
  this.ctx.ui.requestRender();
973
1056
  } catch (err) {
@@ -1786,7 +1869,7 @@ export class SelectorController {
1786
1869
  }
1787
1870
 
1788
1871
  showTreeSelector(): void {
1789
- const tree = this.ctx.sessionManager.getTree();
1872
+ const tree = getTreeForInternalRead(this.ctx.sessionManager);
1790
1873
  const realLeafId = this.ctx.sessionManager.getLeafId();
1791
1874
 
1792
1875
  if (tree.length === 0) {
@@ -1912,7 +1995,7 @@ export class SelectorController {
1912
1995
  }
1913
1996
 
1914
1997
  async showSessionSelector(): Promise<void> {
1915
- const sessions = await SessionManager.list(
1998
+ const sessions = await SessionManager.listForResumePickerReadOnly(
1916
1999
  this.ctx.sessionManager.getCwd(),
1917
2000
  this.ctx.sessionManager.getSessionDir(),
1918
2001
  );
@@ -1934,9 +2017,9 @@ export class SelectorController {
1934
2017
  if (!(await this.#detachActiveSessionBeforeDeletion(session.path))) {
1935
2018
  return false;
1936
2019
  }
1937
- const storage = new FileSessionStorage();
1938
2020
  try {
1939
- await storage.deleteSessionWithArtifacts(session.path);
2021
+ await this.#deleteSession(session.path);
2022
+
1940
2023
  return true;
1941
2024
  } catch (err) {
1942
2025
  throw new Error(`Failed to delete session: ${err instanceof Error ? err.message : String(err)}`, {
@@ -1972,6 +2055,15 @@ export class SelectorController {
1972
2055
  setSessionTerminalTitle(sessionManager.getSessionName?.(), sessionManager.getCwd());
1973
2056
  }
1974
2057
 
2058
+ async #deleteSession(sessionPath: string): Promise<void> {
2059
+ const sessionManager = this.ctx.sessionManager as { dropSession?: (path: string) => Promise<void> };
2060
+ if (sessionManager.dropSession) {
2061
+ await sessionManager.dropSession(sessionPath);
2062
+ return;
2063
+ }
2064
+ await new FileSessionStorage().deleteSessionWithArtifacts(sessionPath);
2065
+ }
2066
+
1975
2067
  async #detachActiveSessionBeforeDeletion(sessionPath: string): Promise<boolean> {
1976
2068
  const currentSessionFile = this.ctx.sessionManager.getSessionFile();
1977
2069
  if (currentSessionFile !== sessionPath) {
@@ -2000,9 +2092,12 @@ export class SelectorController {
2000
2092
  async handleResumeSession(sessionPath: string): Promise<void> {
2001
2093
  const previousSessionId = this.ctx.sessionManager.getSessionId();
2002
2094
  this.#clearTransientSessionUi();
2095
+ const migrationPolicy =
2096
+ this.ctx.settings?.get("session.directoryMigration") === "disabled" ? "disabled" : "copy-retain";
2097
+ const writableSessionPath = await SessionManager.prepareManagedCandidateForWrite(sessionPath, migrationPolicy);
2003
2098
 
2004
2099
  // Switch session via AgentSession (emits hook and tool session events)
2005
- if (!(await this.ctx.session.switchSession(sessionPath))) return;
2100
+ if (!(await this.ctx.session.switchSession(writableSessionPath))) return;
2006
2101
  const switchingToDifferentSession = previousSessionId !== this.ctx.sessionManager.getSessionId();
2007
2102
  if (switchingToDifferentSession) this.ctx.resetIrcSidebarSession();
2008
2103
  this.#refreshSessionTerminalTitle();
@@ -2047,8 +2142,7 @@ export class SelectorController {
2047
2142
  return;
2048
2143
  }
2049
2144
 
2050
- // Delete the session file and artifacts directory
2051
- await storage.deleteSessionWithArtifacts(sessionFile);
2145
+ await this.#deleteSession(sessionFile);
2052
2146
 
2053
2147
  // Show session selector
2054
2148
  this.ctx.showStatus("Current session transcript and artifacts deleted");
@@ -2273,7 +2367,10 @@ export class SelectorController {
2273
2367
  if (handledCandidates || (secondCandidates.length === 0 && secondSourceFailures.length === 0)) {
2274
2368
  let persisted = false;
2275
2369
  try {
2276
- persisted = await stateStore.write({ initialImportResolution: "accepted" });
2370
+ persisted = await stateStore.write({
2371
+ initialImportResolution: "accepted",
2372
+ lastImportVersion: VERSION,
2373
+ });
2277
2374
  } catch {
2278
2375
  logger.warn("Credential auto-import state persistence failed", {
2279
2376
  classification: "state-write-failed",
@@ -2385,6 +2482,94 @@ export class SelectorController {
2385
2482
  this.ctx.ui.requestRender();
2386
2483
  }
2387
2484
 
2485
+ async showSessionsDashboard(): Promise<void> {
2486
+ if (this.#sessionsDashboardOpen) {
2487
+ if (this.#sessionsDashboard) this.ctx.ui.setFocus(this.#sessionsDashboard);
2488
+ return;
2489
+ }
2490
+ this.#sessionsDashboardOpen = true;
2491
+ try {
2492
+ const sessions = dashboardSessions(await SessionManager.listAll());
2493
+ let overlayHandle: OverlayHandle | undefined;
2494
+ const dashboard = new SessionsDashboardComponent(
2495
+ sessions,
2496
+ () => {
2497
+ this.#sessionsDashboardOpen = false;
2498
+ this.#sessionsDashboard = undefined;
2499
+ overlayHandle?.hide();
2500
+ this.ctx.ui.setFocus(this.ctx.editor);
2501
+ this.ctx.ui.requestRender();
2502
+ },
2503
+ () => this.ctx.ui.requestRender(),
2504
+ );
2505
+ this.#sessionsDashboard = dashboard;
2506
+ overlayHandle = this.ctx.ui.showOverlay(dashboard, {
2507
+ anchor: "bottom-center",
2508
+ width: "100%",
2509
+ maxHeight: "100%",
2510
+ margin: 0,
2511
+ });
2512
+ this.ctx.ui.setFocus(dashboard);
2513
+ this.ctx.ui.requestRender();
2514
+ } catch (error) {
2515
+ this.#sessionsDashboardOpen = false;
2516
+ throw error;
2517
+ }
2518
+ }
2519
+
2520
+ showTranscriptViewer(registry: TranscriptItemRegistry): void {
2521
+ if (this.#transcriptViewerOpen) return;
2522
+ this.#transcriptViewerOpen = true;
2523
+ let overlayHandle: OverlayHandle | undefined;
2524
+ const viewer = new TranscriptViewerOverlay({
2525
+ title: "Transcript",
2526
+ getEntries: () => transcriptViewerEntries(registry),
2527
+ onClose: () => {
2528
+ this.#transcriptViewerOpen = false;
2529
+ this.#transcriptViewer = undefined;
2530
+ overlayHandle?.hide();
2531
+ this.ctx.ui.setFocus(this.ctx.editor);
2532
+ this.ctx.ui.requestRender(true);
2533
+ },
2534
+ requestRender: () => this.ctx.ui.requestRender(),
2535
+ copyToClipboard: this.clipboard,
2536
+ });
2537
+ this.#transcriptViewer = viewer;
2538
+ overlayHandle = this.ctx.ui.showOverlay(viewer, {
2539
+ anchor: "bottom-center",
2540
+ width: "100%",
2541
+ maxHeight: "100%",
2542
+ margin: 0,
2543
+ });
2544
+ this.ctx.ui.setFocus(viewer);
2545
+ this.ctx.ui.requestRender();
2546
+ }
2547
+
2548
+ showPlanPreview(content: string | null, options?: PlanPreviewOptions): Promise<PlanPreviewResult> {
2549
+ return new Promise(resolve => {
2550
+ let overlayHandle: OverlayHandle | undefined;
2551
+ const overlay = new PlanPreviewOverlay(
2552
+ content,
2553
+ result => {
2554
+ overlayHandle?.hide();
2555
+ this.ctx.ui.setFocus(this.ctx.editor);
2556
+ this.ctx.ui.requestRender(true);
2557
+ resolve(result);
2558
+ },
2559
+ () => this.ctx.ui.requestRender(),
2560
+ options,
2561
+ );
2562
+ overlayHandle = this.ctx.ui.showOverlay(overlay, {
2563
+ anchor: "bottom-center",
2564
+ width: "100%",
2565
+ maxHeight: "100%",
2566
+ margin: 0,
2567
+ });
2568
+ this.ctx.ui.setFocus(overlay);
2569
+ this.ctx.ui.requestRender();
2570
+ });
2571
+ }
2572
+
2388
2573
  /**
2389
2574
  * Jobs overlay: navigate ongoing monitor + cron jobs (Monitors then Crons,
2390
2575
  * newest-first), drill into per-type detail, and cancel/delete with a y/N
@@ -2411,4 +2596,34 @@ export class SelectorController {
2411
2596
  this.ctx.ui.setFocus(overlay.getFocus());
2412
2597
  this.ctx.ui.requestRender();
2413
2598
  }
2599
+
2600
+ showTasksPane(aggregator: TasksAggregator): void {
2601
+ if (this.#closeTasksPane) {
2602
+ this.#closeTasksPane();
2603
+ return;
2604
+ }
2605
+ let unsubscribe: (() => void) | undefined;
2606
+ const close = () => {
2607
+ unsubscribe?.();
2608
+ this.#tasksPane = undefined;
2609
+ this.#closeTasksPane = undefined;
2610
+ this.ctx.editorContainer.clear();
2611
+ this.ctx.editorContainer.addChild(this.ctx.editor);
2612
+ this.ctx.ui.setFocus(this.ctx.editor);
2613
+ this.ctx.ui.requestRender();
2614
+ };
2615
+ this.#closeTasksPane = close;
2616
+ this.#tasksPane = new TasksPaneComponent(aggregator, {
2617
+ close,
2618
+ requestRender: () => {
2619
+ if (this.#tasksPane) this.ctx.ui.setFocus(this.#tasksPane.getFocus());
2620
+ this.ctx.ui.requestRender();
2621
+ },
2622
+ });
2623
+ unsubscribe = aggregator.onChange(() => this.#tasksPane?.refresh());
2624
+ this.ctx.editorContainer.clear();
2625
+ this.ctx.editorContainer.addChild(this.#tasksPane);
2626
+ this.ctx.ui.setFocus(this.#tasksPane.getFocus());
2627
+ this.ctx.ui.requestRender();
2628
+ }
2414
2629
  }
@@ -0,0 +1,125 @@
1
+ import { visibleWidth } from "@gajae-code/tui";
2
+ import { STTController, type SttState } from "../../stt";
3
+ import { theme } from "../theme/theme";
4
+
5
+ interface SttEditor {
6
+ cursorOverride: string | undefined;
7
+ cursorOverrideWidth: number | undefined;
8
+ getUseTerminalCursor(): boolean;
9
+ insertText(text: string): void;
10
+ setUseTerminalCursor(enabled: boolean): void;
11
+ }
12
+
13
+ interface SttUi {
14
+ getShowHardwareCursor(): boolean;
15
+ requestRender(): void;
16
+ setShowHardwareCursor(enabled: boolean): void;
17
+ }
18
+
19
+ export interface SttModeContext {
20
+ editor: SttEditor;
21
+ showStatus(message: string): void;
22
+ showWarning(message: string): void;
23
+ ui: SttUi;
24
+ updateEditorChrome(): void;
25
+ }
26
+
27
+ /** Coordinates STT state with the interactive composer presentation. */
28
+ export class SttModeController {
29
+ readonly #stt = new STTController();
30
+ #animationInterval: NodeJS.Timeout | undefined;
31
+ #hue = 0;
32
+ #previousShowHardwareCursor: boolean | undefined;
33
+ #previousUseTerminalCursor: boolean | undefined;
34
+
35
+ async toggle(ctx: SttModeContext): Promise<void> {
36
+ await this.#stt.toggle(ctx.editor, {
37
+ showWarning: message => ctx.showWarning(message),
38
+ showStatus: message => ctx.showStatus(message),
39
+ onStateChange: state => this.#onStateChange(ctx, state),
40
+ });
41
+ }
42
+
43
+ dispose(ctx: Pick<SttModeContext, "editor" | "ui">): void {
44
+ this.#cleanupAnimation(ctx);
45
+ this.#stt.dispose();
46
+ }
47
+
48
+ #onStateChange(ctx: SttModeContext, state: SttState): void {
49
+ if (state === "recording") {
50
+ this.#previousShowHardwareCursor = ctx.ui.getShowHardwareCursor();
51
+ this.#previousUseTerminalCursor = ctx.editor.getUseTerminalCursor();
52
+ ctx.ui.setShowHardwareCursor(false);
53
+ ctx.editor.setUseTerminalCursor(false);
54
+ this.#startAnimation(ctx);
55
+ } else if (state === "transcribing") {
56
+ this.#stopAnimation();
57
+ this.#setMicCursor(ctx.editor, { r: 200, g: 200, b: 200 });
58
+ } else {
59
+ this.#cleanupAnimation(ctx);
60
+ }
61
+ ctx.updateEditorChrome();
62
+ ctx.ui.requestRender();
63
+ }
64
+
65
+ #setMicCursor(editor: SttEditor, color: { r: number; g: number; b: number }): void {
66
+ editor.cursorOverride = `\x1b[38;2;${color.r};${color.g};${color.b}m${theme.icon.mic}\x1b[0m`;
67
+ editor.cursorOverrideWidth = visibleWidth(editor.cursorOverride);
68
+ }
69
+
70
+ #startAnimation(ctx: Pick<SttModeContext, "editor" | "ui">): void {
71
+ if (this.#animationInterval) return;
72
+ this.#hue = 0;
73
+ this.#updateMicIcon(ctx.editor);
74
+ this.#animationInterval = setInterval(() => {
75
+ this.#hue = (this.#hue + 8) % 360;
76
+ this.#updateMicIcon(ctx.editor);
77
+ ctx.ui.requestRender();
78
+ }, 60);
79
+ }
80
+
81
+ #updateMicIcon(editor: SttEditor): void {
82
+ const c = hsvToRgb(this.#hue, 0.9, 1);
83
+ this.#setMicCursor(editor, c);
84
+ }
85
+
86
+ #stopAnimation(): void {
87
+ if (this.#animationInterval) {
88
+ clearInterval(this.#animationInterval);
89
+ this.#animationInterval = undefined;
90
+ }
91
+ }
92
+
93
+ #cleanupAnimation(ctx: Pick<SttModeContext, "editor" | "ui">): void {
94
+ this.#stopAnimation();
95
+ ctx.editor.cursorOverride = undefined;
96
+ ctx.editor.cursorOverrideWidth = undefined;
97
+ if (this.#previousShowHardwareCursor !== undefined) {
98
+ ctx.ui.setShowHardwareCursor(this.#previousShowHardwareCursor);
99
+ this.#previousShowHardwareCursor = undefined;
100
+ }
101
+ if (this.#previousUseTerminalCursor !== undefined) {
102
+ ctx.editor.setUseTerminalCursor(this.#previousUseTerminalCursor);
103
+ this.#previousUseTerminalCursor = undefined;
104
+ }
105
+ }
106
+ }
107
+
108
+ function hsvToRgb(h: number, s: number, v: number): { r: number; g: number; b: number } {
109
+ const c = v * s;
110
+ const x = c * (1 - Math.abs(((h / 60) % 2) - 1));
111
+ const m = v - c;
112
+ const [r, g, b] =
113
+ h < 60
114
+ ? [c, x, 0]
115
+ : h < 120
116
+ ? [x, c, 0]
117
+ : h < 180
118
+ ? [0, c, x]
119
+ : h < 240
120
+ ? [0, x, c]
121
+ : h < 300
122
+ ? [x, 0, c]
123
+ : [c, 0, x];
124
+ return { r: Math.round((r + m) * 255), g: Math.round((g + m) * 255), b: Math.round((b + m) * 255) };
125
+ }