oma-coding-agent 1.1.4

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 (1298) hide show
  1. package/CHANGELOG.md +12164 -0
  2. package/README.md +35 -0
  3. package/dist/cli.js +18266 -0
  4. package/examples/README.md +21 -0
  5. package/examples/custom-tools/README.md +104 -0
  6. package/examples/custom-tools/hello/index.ts +20 -0
  7. package/examples/extensions/README.md +142 -0
  8. package/examples/extensions/api-demo.ts +79 -0
  9. package/examples/extensions/chalk-logger.ts +25 -0
  10. package/examples/extensions/hello.ts +31 -0
  11. package/examples/extensions/pirate.ts +43 -0
  12. package/examples/extensions/plan-mode.ts +549 -0
  13. package/examples/extensions/reload-runtime.ts +38 -0
  14. package/examples/extensions/thinking-note.ts +13 -0
  15. package/examples/extensions/tools.ts +145 -0
  16. package/examples/extensions/with-deps/index.ts +36 -0
  17. package/examples/extensions/with-deps/package-lock.json +31 -0
  18. package/examples/extensions/with-deps/package.json +17 -0
  19. package/examples/hooks/README.md +56 -0
  20. package/examples/hooks/auto-commit-on-exit.ts +48 -0
  21. package/examples/hooks/confirm-destructive.ts +58 -0
  22. package/examples/hooks/custom-compaction.ts +115 -0
  23. package/examples/hooks/dirty-repo-guard.ts +51 -0
  24. package/examples/hooks/file-trigger.ts +40 -0
  25. package/examples/hooks/git-checkpoint.ts +52 -0
  26. package/examples/hooks/handoff.ts +149 -0
  27. package/examples/hooks/permission-gate.ts +33 -0
  28. package/examples/hooks/protected-paths.ts +29 -0
  29. package/examples/hooks/qna.ts +118 -0
  30. package/examples/hooks/status-line.ts +39 -0
  31. package/examples/sdk/01-minimal.ts +21 -0
  32. package/examples/sdk/02-custom-model.ts +49 -0
  33. package/examples/sdk/03-custom-prompt.ts +46 -0
  34. package/examples/sdk/04-skills.ts +43 -0
  35. package/examples/sdk/06-extensions.ts +82 -0
  36. package/examples/sdk/06-hooks.ts +61 -0
  37. package/examples/sdk/07-context-files.ts +35 -0
  38. package/examples/sdk/08-prompt-templates.ts +41 -0
  39. package/examples/sdk/08-slash-commands.ts +46 -0
  40. package/examples/sdk/09-api-keys-and-oauth.ts +54 -0
  41. package/examples/sdk/11-sessions.ts +47 -0
  42. package/examples/sdk/12-redis-sessions.ts +54 -0
  43. package/examples/sdk/13-sql-sessions.ts +61 -0
  44. package/examples/sdk/README.md +172 -0
  45. package/package.json +573 -0
  46. package/scripts/bench-guard.ts +71 -0
  47. package/scripts/build-binary.ts +108 -0
  48. package/scripts/bundle-dist.ts +110 -0
  49. package/scripts/embed-mupdf-wasm.ts +67 -0
  50. package/scripts/format-prompts.ts +68 -0
  51. package/scripts/generate-docs-index.ts +56 -0
  52. package/scripts/generate-share-viewer.ts +34 -0
  53. package/scripts/measure-prompt-tokens.ts +63 -0
  54. package/scripts/omp +42 -0
  55. package/scripts/omp.ts +19 -0
  56. package/src/advisor/__tests__/advisor.test.ts +915 -0
  57. package/src/advisor/advise-tool.ts +165 -0
  58. package/src/advisor/index.ts +4 -0
  59. package/src/advisor/runtime.ts +270 -0
  60. package/src/advisor/transcript-recorder.ts +136 -0
  61. package/src/advisor/watchdog.ts +83 -0
  62. package/src/async/index.ts +1 -0
  63. package/src/async/job-manager.ts +674 -0
  64. package/src/auto-thinking/classifier.ts +190 -0
  65. package/src/autolearn/controller.ts +139 -0
  66. package/src/autolearn/managed-skills.ts +255 -0
  67. package/src/autoresearch/command-resume.md +14 -0
  68. package/src/autoresearch/dashboard.ts +436 -0
  69. package/src/autoresearch/git.ts +319 -0
  70. package/src/autoresearch/helpers.ts +218 -0
  71. package/src/autoresearch/index.ts +536 -0
  72. package/src/autoresearch/prompt-setup.md +43 -0
  73. package/src/autoresearch/prompt.md +103 -0
  74. package/src/autoresearch/resume-message.md +10 -0
  75. package/src/autoresearch/state.ts +273 -0
  76. package/src/autoresearch/storage.ts +700 -0
  77. package/src/autoresearch/tools/init-experiment.ts +269 -0
  78. package/src/autoresearch/tools/log-experiment.ts +521 -0
  79. package/src/autoresearch/tools/run-experiment.ts +407 -0
  80. package/src/autoresearch/tools/update-notes.ts +109 -0
  81. package/src/autoresearch/types.ts +168 -0
  82. package/src/capability/context-file.ts +44 -0
  83. package/src/capability/extension-module.ts +34 -0
  84. package/src/capability/extension.ts +47 -0
  85. package/src/capability/fs.ts +117 -0
  86. package/src/capability/hook.ts +40 -0
  87. package/src/capability/index.ts +436 -0
  88. package/src/capability/instruction.ts +37 -0
  89. package/src/capability/mcp.ts +76 -0
  90. package/src/capability/prompt.ts +35 -0
  91. package/src/capability/rule-buckets.ts +66 -0
  92. package/src/capability/rule.ts +261 -0
  93. package/src/capability/settings.ts +34 -0
  94. package/src/capability/skill.ts +63 -0
  95. package/src/capability/slash-command.ts +40 -0
  96. package/src/capability/ssh.ts +41 -0
  97. package/src/capability/system-prompt.ts +34 -0
  98. package/src/capability/tool.ts +38 -0
  99. package/src/capability/types.ts +168 -0
  100. package/src/cli/agents-cli.ts +138 -0
  101. package/src/cli/args.ts +361 -0
  102. package/src/cli/auth-broker-cli.ts +893 -0
  103. package/src/cli/auth-gateway-cli.ts +608 -0
  104. package/src/cli/bench-cli.ts +552 -0
  105. package/src/cli/classify-install-target.ts +76 -0
  106. package/src/cli/claude-trace-cli.ts +795 -0
  107. package/src/cli/commands/init-xdg.ts +27 -0
  108. package/src/cli/completion-gen.ts +550 -0
  109. package/src/cli/config-cli.ts +418 -0
  110. package/src/cli/dry-balance-cli.ts +858 -0
  111. package/src/cli/extension-flags.ts +48 -0
  112. package/src/cli/file-processor.ts +133 -0
  113. package/src/cli/flag-tables.ts +280 -0
  114. package/src/cli/gallery-cli.ts +231 -0
  115. package/src/cli/gallery-fixtures/agentic.ts +407 -0
  116. package/src/cli/gallery-fixtures/codeintel.ts +187 -0
  117. package/src/cli/gallery-fixtures/edit.ts +194 -0
  118. package/src/cli/gallery-fixtures/fs.ts +220 -0
  119. package/src/cli/gallery-fixtures/index.ts +40 -0
  120. package/src/cli/gallery-fixtures/interaction.ts +49 -0
  121. package/src/cli/gallery-fixtures/memory.ts +81 -0
  122. package/src/cli/gallery-fixtures/misc.ts +250 -0
  123. package/src/cli/gallery-fixtures/search.ts +213 -0
  124. package/src/cli/gallery-fixtures/shell.ts +167 -0
  125. package/src/cli/gallery-fixtures/types.ts +57 -0
  126. package/src/cli/gallery-fixtures/web.ts +158 -0
  127. package/src/cli/gallery-screenshot.ts +279 -0
  128. package/src/cli/grep-cli.ts +160 -0
  129. package/src/cli/grievances-cli.ts +256 -0
  130. package/src/cli/initial-message.ts +58 -0
  131. package/src/cli/models-cli.ts +427 -0
  132. package/src/cli/plugin-cli.ts +996 -0
  133. package/src/cli/profile-alias.ts +338 -0
  134. package/src/cli/profile-bootstrap.ts +243 -0
  135. package/src/cli/read-cli.ts +57 -0
  136. package/src/cli/session-picker.ts +80 -0
  137. package/src/cli/setup-cli.ts +332 -0
  138. package/src/cli/setup-model-picker.ts +43 -0
  139. package/src/cli/shell-cli.ts +176 -0
  140. package/src/cli/ssh-cli.ts +179 -0
  141. package/src/cli/startup-cwd.ts +58 -0
  142. package/src/cli/stats-cli.ts +229 -0
  143. package/src/cli/tiny-models-cli.ts +127 -0
  144. package/src/cli/ttsr-cli.ts +995 -0
  145. package/src/cli/update-cli.ts +671 -0
  146. package/src/cli/usage-cli.ts +774 -0
  147. package/src/cli/web-search-cli.ts +132 -0
  148. package/src/cli/worktree-cli.ts +291 -0
  149. package/src/cli-commands.ts +85 -0
  150. package/src/cli.ts +326 -0
  151. package/src/collab/crypto.ts +63 -0
  152. package/src/collab/guest.ts +450 -0
  153. package/src/collab/host.ts +577 -0
  154. package/src/collab/protocol.ts +274 -0
  155. package/src/collab/relay-client.ts +216 -0
  156. package/src/commands/acp.ts +24 -0
  157. package/src/commands/agents.ts +57 -0
  158. package/src/commands/auth-broker.ts +99 -0
  159. package/src/commands/auth-gateway.ts +69 -0
  160. package/src/commands/bench.ts +42 -0
  161. package/src/commands/commit.ts +46 -0
  162. package/src/commands/complete.ts +66 -0
  163. package/src/commands/completions.ts +60 -0
  164. package/src/commands/config.ts +51 -0
  165. package/src/commands/dry-balance.ts +43 -0
  166. package/src/commands/gallery.ts +52 -0
  167. package/src/commands/grep.ts +48 -0
  168. package/src/commands/grievances.ts +51 -0
  169. package/src/commands/install.ts +107 -0
  170. package/src/commands/join.ts +39 -0
  171. package/src/commands/launch.ts +182 -0
  172. package/src/commands/models.ts +61 -0
  173. package/src/commands/plugin.ts +78 -0
  174. package/src/commands/read.ts +38 -0
  175. package/src/commands/say.ts +102 -0
  176. package/src/commands/setup.ts +67 -0
  177. package/src/commands/shell.ts +29 -0
  178. package/src/commands/ssh.ts +60 -0
  179. package/src/commands/stats.ts +29 -0
  180. package/src/commands/tiny-models.ts +36 -0
  181. package/src/commands/token.ts +108 -0
  182. package/src/commands/ttsr.ts +125 -0
  183. package/src/commands/update.ts +21 -0
  184. package/src/commands/usage.ts +43 -0
  185. package/src/commands/web-search.ts +42 -0
  186. package/src/commands/worktree.ts +56 -0
  187. package/src/commit/agentic/agent.ts +318 -0
  188. package/src/commit/agentic/fallback.ts +96 -0
  189. package/src/commit/agentic/index.ts +355 -0
  190. package/src/commit/agentic/prompts/analyze-file.md +22 -0
  191. package/src/commit/agentic/prompts/session-user.md +25 -0
  192. package/src/commit/agentic/prompts/split-confirm.md +1 -0
  193. package/src/commit/agentic/prompts/system.md +38 -0
  194. package/src/commit/agentic/state.ts +60 -0
  195. package/src/commit/agentic/tools/analyze-file.ts +149 -0
  196. package/src/commit/agentic/tools/git-file-diff.ts +191 -0
  197. package/src/commit/agentic/tools/git-hunk.ts +52 -0
  198. package/src/commit/agentic/tools/git-overview.ts +81 -0
  199. package/src/commit/agentic/tools/index.ts +54 -0
  200. package/src/commit/agentic/tools/propose-changelog.ts +147 -0
  201. package/src/commit/agentic/tools/propose-commit.ts +109 -0
  202. package/src/commit/agentic/tools/recent-commits.ts +81 -0
  203. package/src/commit/agentic/tools/schemas.ts +11 -0
  204. package/src/commit/agentic/tools/split-commit.ts +241 -0
  205. package/src/commit/agentic/topo-sort.ts +44 -0
  206. package/src/commit/agentic/trivial.ts +51 -0
  207. package/src/commit/agentic/validation.ts +183 -0
  208. package/src/commit/analysis/conventional.ts +64 -0
  209. package/src/commit/analysis/index.ts +4 -0
  210. package/src/commit/analysis/scope.ts +242 -0
  211. package/src/commit/analysis/summary.ts +107 -0
  212. package/src/commit/analysis/validation.ts +66 -0
  213. package/src/commit/changelog/detect.ts +40 -0
  214. package/src/commit/changelog/generate.ts +101 -0
  215. package/src/commit/changelog/index.ts +234 -0
  216. package/src/commit/changelog/parse.ts +44 -0
  217. package/src/commit/cli.ts +85 -0
  218. package/src/commit/git/diff.ts +148 -0
  219. package/src/commit/index.ts +5 -0
  220. package/src/commit/map-reduce/index.ts +69 -0
  221. package/src/commit/map-reduce/map-phase.ts +193 -0
  222. package/src/commit/map-reduce/reduce-phase.ts +49 -0
  223. package/src/commit/map-reduce/utils.ts +9 -0
  224. package/src/commit/message.ts +11 -0
  225. package/src/commit/model-selection.ts +89 -0
  226. package/src/commit/pipeline.ts +243 -0
  227. package/src/commit/prompts/analysis-system.md +148 -0
  228. package/src/commit/prompts/analysis-user.md +38 -0
  229. package/src/commit/prompts/changelog-system.md +50 -0
  230. package/src/commit/prompts/changelog-user.md +18 -0
  231. package/src/commit/prompts/file-observer-system.md +24 -0
  232. package/src/commit/prompts/file-observer-user.md +8 -0
  233. package/src/commit/prompts/reduce-system.md +50 -0
  234. package/src/commit/prompts/reduce-user.md +17 -0
  235. package/src/commit/prompts/summary-retry.md +3 -0
  236. package/src/commit/prompts/summary-system.md +38 -0
  237. package/src/commit/prompts/summary-user.md +13 -0
  238. package/src/commit/prompts/types-description.md +2 -0
  239. package/src/commit/shared-llm.ts +70 -0
  240. package/src/commit/types.ts +118 -0
  241. package/src/commit/utils/exclusions.ts +42 -0
  242. package/src/commit/utils.ts +58 -0
  243. package/src/config/api-key-resolver.ts +67 -0
  244. package/src/config/append-only-context-mode.ts +76 -0
  245. package/src/config/config-file.ts +315 -0
  246. package/src/config/file-lock.ts +164 -0
  247. package/src/config/keybindings.ts +634 -0
  248. package/src/config/mcp-schema.json +238 -0
  249. package/src/config/model-discovery.ts +589 -0
  250. package/src/config/model-registry.ts +2260 -0
  251. package/src/config/model-resolver.ts +1819 -0
  252. package/src/config/model-roles.ts +99 -0
  253. package/src/config/models-config-schema.ts +266 -0
  254. package/src/config/models-config.ts +131 -0
  255. package/src/config/prompt-templates.ts +185 -0
  256. package/src/config/resolve-config-value.ts +94 -0
  257. package/src/config/settings-schema.ts +4740 -0
  258. package/src/config/settings.ts +1243 -0
  259. package/src/config.ts +242 -0
  260. package/src/cursor.ts +340 -0
  261. package/src/dap/client.ts +760 -0
  262. package/src/dap/config.ts +189 -0
  263. package/src/dap/defaults.json +212 -0
  264. package/src/dap/index.ts +4 -0
  265. package/src/dap/session.ts +1441 -0
  266. package/src/dap/types.ts +610 -0
  267. package/src/debug/index.ts +559 -0
  268. package/src/debug/log-formatting.ts +58 -0
  269. package/src/debug/log-viewer.ts +908 -0
  270. package/src/debug/profiler.ts +162 -0
  271. package/src/debug/protocol-probe.ts +267 -0
  272. package/src/debug/raw-sse-buffer.ts +294 -0
  273. package/src/debug/raw-sse.ts +292 -0
  274. package/src/debug/remote-debugger.ts +151 -0
  275. package/src/debug/report-bundle.ts +375 -0
  276. package/src/debug/system-info.ts +111 -0
  277. package/src/debug/terminal-info.ts +124 -0
  278. package/src/discovery/agents-md.ts +67 -0
  279. package/src/discovery/agents.ts +230 -0
  280. package/src/discovery/at-imports.ts +273 -0
  281. package/src/discovery/builtin-defaults.ts +39 -0
  282. package/src/discovery/builtin-rules/index.ts +63 -0
  283. package/src/discovery/builtin-rules/low-end/no-hallucinated-apis.md +14 -0
  284. package/src/discovery/builtin-rules/low-end/no-hallucinated-paths.md +14 -0
  285. package/src/discovery/builtin-rules/low-end/no-premature-completion.md +14 -0
  286. package/src/discovery/builtin-rules/rs-box-leak.md +48 -0
  287. package/src/discovery/builtin-rules/rs-future-prelude.md +23 -0
  288. package/src/discovery/builtin-rules/rs-lazylock.md +51 -0
  289. package/src/discovery/builtin-rules/rs-match-ergonomics.md +67 -0
  290. package/src/discovery/builtin-rules/rs-parking-lot.md +44 -0
  291. package/src/discovery/builtin-rules/rs-result-type.md +19 -0
  292. package/src/discovery/builtin-rules/ts-bare-catch.md +38 -0
  293. package/src/discovery/builtin-rules/ts-import-type.md +42 -0
  294. package/src/discovery/builtin-rules/ts-no-any.md +65 -0
  295. package/src/discovery/builtin-rules/ts-no-deprecated-leftovers.md +44 -0
  296. package/src/discovery/builtin-rules/ts-no-dynamic-import.md +39 -0
  297. package/src/discovery/builtin-rules/ts-no-inline-cast-access.md +55 -0
  298. package/src/discovery/builtin-rules/ts-no-return-type.md +44 -0
  299. package/src/discovery/builtin-rules/ts-no-test-timers.md +55 -0
  300. package/src/discovery/builtin-rules/ts-no-tiny-functions.md +51 -0
  301. package/src/discovery/builtin-rules/ts-promise-with-resolvers.md +65 -0
  302. package/src/discovery/builtin-rules/ts-redundant-clear-guard.md +75 -0
  303. package/src/discovery/builtin-rules/ts-set-map.md +28 -0
  304. package/src/discovery/builtin.ts +934 -0
  305. package/src/discovery/claude-plugins.ts +386 -0
  306. package/src/discovery/claude.ts +584 -0
  307. package/src/discovery/cline.ts +83 -0
  308. package/src/discovery/codex.ts +522 -0
  309. package/src/discovery/cursor.ts +220 -0
  310. package/src/discovery/gemini.ts +383 -0
  311. package/src/discovery/github.ts +337 -0
  312. package/src/discovery/helpers.ts +1092 -0
  313. package/src/discovery/index.ts +81 -0
  314. package/src/discovery/mcp-json.ts +172 -0
  315. package/src/discovery/omp-extension-roots.ts +190 -0
  316. package/src/discovery/omp-plugins.ts +383 -0
  317. package/src/discovery/opencode.ts +398 -0
  318. package/src/discovery/plugin-dir-roots.ts +28 -0
  319. package/src/discovery/ssh.ts +153 -0
  320. package/src/discovery/substitute-plugin-root.ts +29 -0
  321. package/src/discovery/vscode.ts +105 -0
  322. package/src/discovery/windsurf.ts +147 -0
  323. package/src/edit/apply-patch/index.ts +87 -0
  324. package/src/edit/apply-patch/parser.ts +174 -0
  325. package/src/edit/diff.ts +999 -0
  326. package/src/edit/file-snapshot-store.ts +143 -0
  327. package/src/edit/hashline/block-resolver.ts +33 -0
  328. package/src/edit/hashline/diff.ts +290 -0
  329. package/src/edit/hashline/execute.ts +237 -0
  330. package/src/edit/hashline/filesystem.ts +130 -0
  331. package/src/edit/hashline/index.ts +5 -0
  332. package/src/edit/hashline/noop-loop-guard.ts +99 -0
  333. package/src/edit/hashline/params.ts +19 -0
  334. package/src/edit/index.ts +620 -0
  335. package/src/edit/modes/apply-patch.lark +19 -0
  336. package/src/edit/modes/apply-patch.ts +53 -0
  337. package/src/edit/modes/patch.ts +1888 -0
  338. package/src/edit/modes/replace.ts +1133 -0
  339. package/src/edit/normalize.ts +345 -0
  340. package/src/edit/notebook.ts +242 -0
  341. package/src/edit/read-file.ts +25 -0
  342. package/src/edit/renderer.ts +823 -0
  343. package/src/edit/streaming.ts +517 -0
  344. package/src/eval/__tests__/agent-bridge.test.ts +769 -0
  345. package/src/eval/__tests__/bridge-timeout.test.ts +64 -0
  346. package/src/eval/__tests__/budget-bridge.test.ts +69 -0
  347. package/src/eval/__tests__/completion-bridge.test.ts +412 -0
  348. package/src/eval/__tests__/helpers-local-roots.test.ts +58 -0
  349. package/src/eval/__tests__/idle-timeout.test.ts +80 -0
  350. package/src/eval/__tests__/js-context-manager.test.ts +291 -0
  351. package/src/eval/__tests__/kernel-spawn.test.ts +103 -0
  352. package/src/eval/__tests__/prelude-agent.test.ts +73 -0
  353. package/src/eval/agent-bridge.ts +319 -0
  354. package/src/eval/backend.ts +71 -0
  355. package/src/eval/bridge-timeout.ts +44 -0
  356. package/src/eval/budget-bridge.ts +48 -0
  357. package/src/eval/completion-bridge.ts +211 -0
  358. package/src/eval/concurrency-bridge.ts +34 -0
  359. package/src/eval/idle-timeout.ts +91 -0
  360. package/src/eval/index.ts +4 -0
  361. package/src/eval/js/context-manager.ts +621 -0
  362. package/src/eval/js/executor.ts +173 -0
  363. package/src/eval/js/index.ts +51 -0
  364. package/src/eval/js/shared/helpers.ts +283 -0
  365. package/src/eval/js/shared/indirect-eval.ts +30 -0
  366. package/src/eval/js/shared/local-module-loader.ts +342 -0
  367. package/src/eval/js/shared/prelude.ts +2 -0
  368. package/src/eval/js/shared/prelude.txt +307 -0
  369. package/src/eval/js/shared/rewrite-imports.ts +532 -0
  370. package/src/eval/js/shared/runtime.ts +580 -0
  371. package/src/eval/js/shared/types.ts +18 -0
  372. package/src/eval/js/tool-bridge.ts +163 -0
  373. package/src/eval/js/worker-core.ts +151 -0
  374. package/src/eval/js/worker-entry.ts +37 -0
  375. package/src/eval/js/worker-protocol.ts +47 -0
  376. package/src/eval/py/__tests__/prelude.test.ts +19 -0
  377. package/src/eval/py/display.ts +71 -0
  378. package/src/eval/py/executor.ts +742 -0
  379. package/src/eval/py/index.ts +68 -0
  380. package/src/eval/py/kernel.ts +748 -0
  381. package/src/eval/py/prelude.py +683 -0
  382. package/src/eval/py/prelude.ts +3 -0
  383. package/src/eval/py/runner.py +1177 -0
  384. package/src/eval/py/runtime.ts +276 -0
  385. package/src/eval/py/spawn-options.ts +126 -0
  386. package/src/eval/py/tool-bridge.ts +182 -0
  387. package/src/eval/session-id.ts +8 -0
  388. package/src/eval/types.ts +48 -0
  389. package/src/exa/index.ts +2 -0
  390. package/src/exa/mcp-client.ts +370 -0
  391. package/src/exa/types.ts +69 -0
  392. package/src/exec/bash-executor.ts +434 -0
  393. package/src/exec/exec.ts +53 -0
  394. package/src/exec/non-interactive-env.ts +119 -0
  395. package/src/export/custom-share.ts +65 -0
  396. package/src/export/html/index.ts +266 -0
  397. package/src/export/html/share-loader.js +102 -0
  398. package/src/export/html/template.css +1337 -0
  399. package/src/export/html/template.html +49 -0
  400. package/src/export/html/template.js +1626 -0
  401. package/src/export/html/tool-views.generated.js +37 -0
  402. package/src/export/html/vendor/highlight.min.js +1213 -0
  403. package/src/export/html/vendor/marked.min.js +6 -0
  404. package/src/export/share.ts +268 -0
  405. package/src/export/ttsr.ts +583 -0
  406. package/src/extensibility/custom-commands/bundled/ci-green/index.ts +54 -0
  407. package/src/extensibility/custom-commands/bundled/review/index.ts +698 -0
  408. package/src/extensibility/custom-commands/index.ts +2 -0
  409. package/src/extensibility/custom-commands/loader.ts +242 -0
  410. package/src/extensibility/custom-commands/types.ts +119 -0
  411. package/src/extensibility/custom-tools/index.ts +7 -0
  412. package/src/extensibility/custom-tools/loader.ts +268 -0
  413. package/src/extensibility/custom-tools/types.ts +277 -0
  414. package/src/extensibility/custom-tools/wrapper.ts +47 -0
  415. package/src/extensibility/extensions/compact-handler.ts +40 -0
  416. package/src/extensibility/extensions/get-commands-handler.ts +78 -0
  417. package/src/extensibility/extensions/index.ts +16 -0
  418. package/src/extensibility/extensions/loader.ts +587 -0
  419. package/src/extensibility/extensions/model-api.ts +41 -0
  420. package/src/extensibility/extensions/runner.ts +989 -0
  421. package/src/extensibility/extensions/types.ts +1394 -0
  422. package/src/extensibility/extensions/wrapper.ts +259 -0
  423. package/src/extensibility/hooks/index.ts +6 -0
  424. package/src/extensibility/hooks/loader.ts +262 -0
  425. package/src/extensibility/hooks/runner.ts +425 -0
  426. package/src/extensibility/hooks/tool-wrapper.ts +107 -0
  427. package/src/extensibility/hooks/types.ts +613 -0
  428. package/src/extensibility/legacy-pi-ai-shim.ts +61 -0
  429. package/src/extensibility/legacy-pi-coding-agent-shim.ts +128 -0
  430. package/src/extensibility/plugins/doctor.ts +65 -0
  431. package/src/extensibility/plugins/git-url.ts +367 -0
  432. package/src/extensibility/plugins/index.ts +9 -0
  433. package/src/extensibility/plugins/installer.ts +192 -0
  434. package/src/extensibility/plugins/legacy-pi-compat.ts +712 -0
  435. package/src/extensibility/plugins/loader.ts +458 -0
  436. package/src/extensibility/plugins/manager.ts +1026 -0
  437. package/src/extensibility/plugins/marketplace/cache.ts +136 -0
  438. package/src/extensibility/plugins/marketplace/fetcher.ts +315 -0
  439. package/src/extensibility/plugins/marketplace/index.ts +6 -0
  440. package/src/extensibility/plugins/marketplace/manager.ts +770 -0
  441. package/src/extensibility/plugins/marketplace/registry.ts +196 -0
  442. package/src/extensibility/plugins/marketplace/source-resolver.ts +147 -0
  443. package/src/extensibility/plugins/marketplace/types.ts +191 -0
  444. package/src/extensibility/plugins/marketplace-auto-update.ts +49 -0
  445. package/src/extensibility/plugins/parser.ts +105 -0
  446. package/src/extensibility/plugins/runtime-config.ts +9 -0
  447. package/src/extensibility/plugins/types.ts +194 -0
  448. package/src/extensibility/shared-events.ts +367 -0
  449. package/src/extensibility/skills.ts +408 -0
  450. package/src/extensibility/slash-commands.ts +131 -0
  451. package/src/extensibility/tool-proxy.ts +28 -0
  452. package/src/extensibility/typebox.ts +945 -0
  453. package/src/extensibility/utils.ts +44 -0
  454. package/src/goals/guided-setup.ts +142 -0
  455. package/src/goals/index.ts +3 -0
  456. package/src/goals/runtime.ts +521 -0
  457. package/src/goals/state.ts +37 -0
  458. package/src/goals/tools/goal-tool.ts +251 -0
  459. package/src/hindsight/backend.ts +354 -0
  460. package/src/hindsight/bank.ts +156 -0
  461. package/src/hindsight/client.ts +623 -0
  462. package/src/hindsight/config.ts +175 -0
  463. package/src/hindsight/content.ts +210 -0
  464. package/src/hindsight/index.ts +8 -0
  465. package/src/hindsight/mental-models.ts +429 -0
  466. package/src/hindsight/seeds.json +32 -0
  467. package/src/hindsight/state.ts +492 -0
  468. package/src/hindsight/transcript.ts +71 -0
  469. package/src/index.ts +66 -0
  470. package/src/internal-urls/agent-protocol.ts +146 -0
  471. package/src/internal-urls/artifact-protocol.ts +107 -0
  472. package/src/internal-urls/docs-index.generated.txt +2 -0
  473. package/src/internal-urls/docs-index.ts +102 -0
  474. package/src/internal-urls/history-protocol.ts +118 -0
  475. package/src/internal-urls/index.ts +25 -0
  476. package/src/internal-urls/issue-pr-protocol.ts +594 -0
  477. package/src/internal-urls/json-query.ts +126 -0
  478. package/src/internal-urls/local-protocol.ts +309 -0
  479. package/src/internal-urls/mcp-protocol.ts +151 -0
  480. package/src/internal-urls/memory-protocol.ts +169 -0
  481. package/src/internal-urls/omp-protocol.ts +94 -0
  482. package/src/internal-urls/parse.ts +72 -0
  483. package/src/internal-urls/registry-helpers.ts +25 -0
  484. package/src/internal-urls/router.ts +105 -0
  485. package/src/internal-urls/rule-protocol.ts +45 -0
  486. package/src/internal-urls/skill-protocol.ts +96 -0
  487. package/src/internal-urls/types.ts +152 -0
  488. package/src/internal-urls/vault-protocol.ts +936 -0
  489. package/src/irc/bus.ts +311 -0
  490. package/src/lib/xai-http.ts +124 -0
  491. package/src/lsp/client.ts +1217 -0
  492. package/src/lsp/clients/biome-client.ts +264 -0
  493. package/src/lsp/clients/index.ts +50 -0
  494. package/src/lsp/clients/lsp-linter-client.ts +85 -0
  495. package/src/lsp/clients/swiftlint-client.ts +120 -0
  496. package/src/lsp/config.ts +502 -0
  497. package/src/lsp/defaults.json +499 -0
  498. package/src/lsp/diagnostics-ledger.ts +51 -0
  499. package/src/lsp/edits.ts +267 -0
  500. package/src/lsp/format-options.ts +119 -0
  501. package/src/lsp/index.ts +2480 -0
  502. package/src/lsp/lspmux.ts +233 -0
  503. package/src/lsp/render.ts +668 -0
  504. package/src/lsp/startup-events.ts +13 -0
  505. package/src/lsp/types.ts +444 -0
  506. package/src/lsp/utils.ts +718 -0
  507. package/src/main.ts +1421 -0
  508. package/src/markit/NOTICE +32 -0
  509. package/src/markit/converters/docx.ts +56 -0
  510. package/src/markit/converters/epub.ts +136 -0
  511. package/src/markit/converters/mammoth.d.ts +24 -0
  512. package/src/markit/converters/pdf/columns.ts +103 -0
  513. package/src/markit/converters/pdf/extract.ts +574 -0
  514. package/src/markit/converters/pdf/grid.ts +780 -0
  515. package/src/markit/converters/pdf/headers.ts +106 -0
  516. package/src/markit/converters/pdf/index.ts +146 -0
  517. package/src/markit/converters/pdf/render.ts +501 -0
  518. package/src/markit/converters/pdf/types.ts +84 -0
  519. package/src/markit/converters/pptx.ts +325 -0
  520. package/src/markit/converters/xlsx.ts +173 -0
  521. package/src/markit/index.ts +2 -0
  522. package/src/markit/registry.ts +59 -0
  523. package/src/markit/types.ts +35 -0
  524. package/src/mcp/client.ts +509 -0
  525. package/src/mcp/config-writer.ts +229 -0
  526. package/src/mcp/config.ts +365 -0
  527. package/src/mcp/index.ts +29 -0
  528. package/src/mcp/json-rpc.ts +122 -0
  529. package/src/mcp/loader.ts +124 -0
  530. package/src/mcp/manager.ts +1326 -0
  531. package/src/mcp/oauth-credentials.ts +104 -0
  532. package/src/mcp/oauth-discovery.ts +467 -0
  533. package/src/mcp/oauth-flow.ts +555 -0
  534. package/src/mcp/render.ts +155 -0
  535. package/src/mcp/smithery-auth.ts +104 -0
  536. package/src/mcp/smithery-connect.ts +145 -0
  537. package/src/mcp/smithery-registry.ts +477 -0
  538. package/src/mcp/startup-events.ts +21 -0
  539. package/src/mcp/timeout.ts +59 -0
  540. package/src/mcp/tool-bridge.ts +429 -0
  541. package/src/mcp/tool-cache.ts +117 -0
  542. package/src/mcp/transports/http.ts +519 -0
  543. package/src/mcp/transports/index.ts +6 -0
  544. package/src/mcp/transports/stdio.ts +606 -0
  545. package/src/mcp/types.ts +427 -0
  546. package/src/memories/index.ts +1281 -0
  547. package/src/memories/storage.ts +578 -0
  548. package/src/memory-backend/index.ts +18 -0
  549. package/src/memory-backend/local-backend.ts +45 -0
  550. package/src/memory-backend/off-backend.ts +25 -0
  551. package/src/memory-backend/resolve.ts +25 -0
  552. package/src/memory-backend/runtime.ts +66 -0
  553. package/src/memory-backend/types.ts +166 -0
  554. package/src/mnemopi/backend.ts +612 -0
  555. package/src/mnemopi/config.ts +265 -0
  556. package/src/mnemopi/embed-client.ts +401 -0
  557. package/src/mnemopi/embed-protocol.ts +35 -0
  558. package/src/mnemopi/embed-worker.ts +113 -0
  559. package/src/mnemopi/index.ts +3 -0
  560. package/src/mnemopi/state.ts +657 -0
  561. package/src/modes/acp/acp-agent.ts +2362 -0
  562. package/src/modes/acp/acp-client-bridge.ts +154 -0
  563. package/src/modes/acp/acp-event-mapper.ts +933 -0
  564. package/src/modes/acp/acp-mode.ts +23 -0
  565. package/src/modes/acp/index.ts +2 -0
  566. package/src/modes/acp/terminal-auth.ts +37 -0
  567. package/src/modes/components/__tests__/skill-message.test.ts +92 -0
  568. package/src/modes/components/advisor-message.ts +99 -0
  569. package/src/modes/components/agent-dashboard.ts +1206 -0
  570. package/src/modes/components/agent-hub.ts +566 -0
  571. package/src/modes/components/agent-transcript-viewer.ts +461 -0
  572. package/src/modes/components/assistant-message.ts +612 -0
  573. package/src/modes/components/background-tan-message.ts +36 -0
  574. package/src/modes/components/bash-execution.ts +220 -0
  575. package/src/modes/components/bordered-loader.ts +41 -0
  576. package/src/modes/components/btw-panel.ts +112 -0
  577. package/src/modes/components/cache-invalidation-marker.ts +110 -0
  578. package/src/modes/components/chat-block.ts +111 -0
  579. package/src/modes/components/chat-transcript-builder.ts +476 -0
  580. package/src/modes/components/collab-prompt-message.ts +32 -0
  581. package/src/modes/components/compaction-summary-message.ts +215 -0
  582. package/src/modes/components/copy-selector.ts +206 -0
  583. package/src/modes/components/countdown-timer.ts +75 -0
  584. package/src/modes/components/custom-editor.test.ts +142 -0
  585. package/src/modes/components/custom-editor.ts +620 -0
  586. package/src/modes/components/custom-message.ts +67 -0
  587. package/src/modes/components/diff.ts +254 -0
  588. package/src/modes/components/dynamic-border.ts +34 -0
  589. package/src/modes/components/error-banner.ts +33 -0
  590. package/src/modes/components/eval-execution.ts +158 -0
  591. package/src/modes/components/execution-shared.ts +101 -0
  592. package/src/modes/components/extensions/extension-dashboard.ts +399 -0
  593. package/src/modes/components/extensions/extension-list.ts +502 -0
  594. package/src/modes/components/extensions/index.ts +9 -0
  595. package/src/modes/components/extensions/inspector-panel.ts +321 -0
  596. package/src/modes/components/extensions/state-manager.ts +627 -0
  597. package/src/modes/components/extensions/types.ts +186 -0
  598. package/src/modes/components/footer.ts +275 -0
  599. package/src/modes/components/history-search.ts +280 -0
  600. package/src/modes/components/hook-editor.ts +167 -0
  601. package/src/modes/components/hook-input.ts +87 -0
  602. package/src/modes/components/hook-message.ts +67 -0
  603. package/src/modes/components/hook-selector.ts +659 -0
  604. package/src/modes/components/index.ts +38 -0
  605. package/src/modes/components/keybinding-hints.ts +65 -0
  606. package/src/modes/components/late-diagnostics-message.ts +60 -0
  607. package/src/modes/components/login-dialog.ts +164 -0
  608. package/src/modes/components/logout-account-selector.ts +130 -0
  609. package/src/modes/components/mcp-add-wizard.ts +1360 -0
  610. package/src/modes/components/message-frame.ts +92 -0
  611. package/src/modes/components/model-selector.ts +1315 -0
  612. package/src/modes/components/oauth-selector.ts +457 -0
  613. package/src/modes/components/omfg-panel.ts +141 -0
  614. package/src/modes/components/overlay-box.ts +109 -0
  615. package/src/modes/components/plan-review-overlay.ts +847 -0
  616. package/src/modes/components/plan-toc.ts +138 -0
  617. package/src/modes/components/plugin-selector.ts +95 -0
  618. package/src/modes/components/plugin-settings.ts +739 -0
  619. package/src/modes/components/queue-mode-selector.ts +56 -0
  620. package/src/modes/components/read-tool-group.ts +676 -0
  621. package/src/modes/components/reset-usage-selector.ts +161 -0
  622. package/src/modes/components/segment-track.ts +89 -0
  623. package/src/modes/components/session-selector.ts +631 -0
  624. package/src/modes/components/settings-defs.ts +225 -0
  625. package/src/modes/components/settings-selector.ts +1095 -0
  626. package/src/modes/components/show-images-selector.ts +45 -0
  627. package/src/modes/components/skill-message.ts +110 -0
  628. package/src/modes/components/snapcompact-shape-preview-doc.md +18 -0
  629. package/src/modes/components/snapcompact-shape-preview.ts +192 -0
  630. package/src/modes/components/status-line/component.ts +1001 -0
  631. package/src/modes/components/status-line/context-thresholds.ts +78 -0
  632. package/src/modes/components/status-line/git-utils.ts +42 -0
  633. package/src/modes/components/status-line/index.ts +5 -0
  634. package/src/modes/components/status-line/presets.ts +106 -0
  635. package/src/modes/components/status-line/segments.ts +616 -0
  636. package/src/modes/components/status-line/separators.ts +55 -0
  637. package/src/modes/components/status-line/token-rate.ts +66 -0
  638. package/src/modes/components/status-line/types.ts +124 -0
  639. package/src/modes/components/theme-selector.ts +63 -0
  640. package/src/modes/components/thinking-selector.ts +52 -0
  641. package/src/modes/components/tiny-title-download-progress.ts +90 -0
  642. package/src/modes/components/tips.txt +24 -0
  643. package/src/modes/components/todo-reminder.ts +39 -0
  644. package/src/modes/components/tool-execution.ts +1165 -0
  645. package/src/modes/components/transcript-container.ts +806 -0
  646. package/src/modes/components/tree-selector.ts +994 -0
  647. package/src/modes/components/ttsr-notification.ts +123 -0
  648. package/src/modes/components/usage-row.ts +18 -0
  649. package/src/modes/components/user-message-selector.ts +227 -0
  650. package/src/modes/components/user-message.ts +68 -0
  651. package/src/modes/components/visual-truncate.ts +63 -0
  652. package/src/modes/components/welcome.ts +581 -0
  653. package/src/modes/controllers/btw-controller.ts +173 -0
  654. package/src/modes/controllers/command-controller-shared.ts +109 -0
  655. package/src/modes/controllers/command-controller.ts +1653 -0
  656. package/src/modes/controllers/event-controller.ts +1153 -0
  657. package/src/modes/controllers/extension-ui-controller.ts +893 -0
  658. package/src/modes/controllers/input-controller.ts +1627 -0
  659. package/src/modes/controllers/mcp-command-controller.ts +2162 -0
  660. package/src/modes/controllers/omfg-controller.ts +283 -0
  661. package/src/modes/controllers/omfg-rule.ts +647 -0
  662. package/src/modes/controllers/selector-controller.ts +1285 -0
  663. package/src/modes/controllers/session-focus-controller.ts +112 -0
  664. package/src/modes/controllers/ssh-command-controller.ts +384 -0
  665. package/src/modes/controllers/streaming-reveal.ts +295 -0
  666. package/src/modes/controllers/tan-command-controller.ts +190 -0
  667. package/src/modes/controllers/todo-command-controller.ts +485 -0
  668. package/src/modes/controllers/tool-args-reveal.ts +174 -0
  669. package/src/modes/data/emojis.json +1 -0
  670. package/src/modes/emoji-autocomplete.ts +285 -0
  671. package/src/modes/gradient-highlight.ts +99 -0
  672. package/src/modes/image-references.ts +137 -0
  673. package/src/modes/index.ts +17 -0
  674. package/src/modes/interactive-mode.ts +3940 -0
  675. package/src/modes/internal-url-autocomplete.ts +143 -0
  676. package/src/modes/loop-limit.ts +192 -0
  677. package/src/modes/magic-keywords.ts +42 -0
  678. package/src/modes/markdown-prose.ts +247 -0
  679. package/src/modes/oauth-manual-input.ts +69 -0
  680. package/src/modes/orchestrate.ts +42 -0
  681. package/src/modes/print-mode.ts +130 -0
  682. package/src/modes/prompt-action-autocomplete.ts +260 -0
  683. package/src/modes/rpc/host-tools.ts +186 -0
  684. package/src/modes/rpc/host-uris.ts +235 -0
  685. package/src/modes/rpc/rpc-client.ts +995 -0
  686. package/src/modes/rpc/rpc-mode.ts +1156 -0
  687. package/src/modes/rpc/rpc-subagents.ts +265 -0
  688. package/src/modes/rpc/rpc-types.ts +487 -0
  689. package/src/modes/runtime-init.ts +142 -0
  690. package/src/modes/session-observer-registry.ts +215 -0
  691. package/src/modes/setup-version.ts +11 -0
  692. package/src/modes/setup-wizard/index.ts +101 -0
  693. package/src/modes/setup-wizard/lazy.ts +16 -0
  694. package/src/modes/setup-wizard/scenes/glyph.ts +114 -0
  695. package/src/modes/setup-wizard/scenes/outro.ts +35 -0
  696. package/src/modes/setup-wizard/scenes/providers.ts +103 -0
  697. package/src/modes/setup-wizard/scenes/sign-in.ts +286 -0
  698. package/src/modes/setup-wizard/scenes/splash.ts +201 -0
  699. package/src/modes/setup-wizard/scenes/theme.ts +326 -0
  700. package/src/modes/setup-wizard/scenes/types.ts +57 -0
  701. package/src/modes/setup-wizard/scenes/web-search.ts +145 -0
  702. package/src/modes/setup-wizard/startup-splash.ts +107 -0
  703. package/src/modes/setup-wizard/wizard-overlay.ts +334 -0
  704. package/src/modes/shared.ts +49 -0
  705. package/src/modes/theme/dark.json +95 -0
  706. package/src/modes/theme/defaults/alabaster.json +93 -0
  707. package/src/modes/theme/defaults/amethyst.json +96 -0
  708. package/src/modes/theme/defaults/anthracite.json +93 -0
  709. package/src/modes/theme/defaults/basalt.json +91 -0
  710. package/src/modes/theme/defaults/birch.json +95 -0
  711. package/src/modes/theme/defaults/dark-abyss.json +91 -0
  712. package/src/modes/theme/defaults/dark-arctic.json +104 -0
  713. package/src/modes/theme/defaults/dark-aurora.json +95 -0
  714. package/src/modes/theme/defaults/dark-catppuccin.json +107 -0
  715. package/src/modes/theme/defaults/dark-cavern.json +91 -0
  716. package/src/modes/theme/defaults/dark-copper.json +95 -0
  717. package/src/modes/theme/defaults/dark-cosmos.json +90 -0
  718. package/src/modes/theme/defaults/dark-cyberpunk.json +102 -0
  719. package/src/modes/theme/defaults/dark-dracula.json +98 -0
  720. package/src/modes/theme/defaults/dark-eclipse.json +91 -0
  721. package/src/modes/theme/defaults/dark-ember.json +95 -0
  722. package/src/modes/theme/defaults/dark-equinox.json +90 -0
  723. package/src/modes/theme/defaults/dark-forest.json +96 -0
  724. package/src/modes/theme/defaults/dark-github.json +105 -0
  725. package/src/modes/theme/defaults/dark-gruvbox.json +112 -0
  726. package/src/modes/theme/defaults/dark-lavender.json +95 -0
  727. package/src/modes/theme/defaults/dark-lunar.json +89 -0
  728. package/src/modes/theme/defaults/dark-midnight.json +95 -0
  729. package/src/modes/theme/defaults/dark-monochrome.json +94 -0
  730. package/src/modes/theme/defaults/dark-monokai.json +98 -0
  731. package/src/modes/theme/defaults/dark-nebula.json +90 -0
  732. package/src/modes/theme/defaults/dark-nord.json +97 -0
  733. package/src/modes/theme/defaults/dark-ocean.json +101 -0
  734. package/src/modes/theme/defaults/dark-one.json +100 -0
  735. package/src/modes/theme/defaults/dark-poimandres.json +142 -0
  736. package/src/modes/theme/defaults/dark-rainforest.json +91 -0
  737. package/src/modes/theme/defaults/dark-reef.json +91 -0
  738. package/src/modes/theme/defaults/dark-retro.json +92 -0
  739. package/src/modes/theme/defaults/dark-rose-pine.json +96 -0
  740. package/src/modes/theme/defaults/dark-sakura.json +95 -0
  741. package/src/modes/theme/defaults/dark-slate.json +95 -0
  742. package/src/modes/theme/defaults/dark-solarized.json +97 -0
  743. package/src/modes/theme/defaults/dark-solstice.json +90 -0
  744. package/src/modes/theme/defaults/dark-starfall.json +91 -0
  745. package/src/modes/theme/defaults/dark-sunset.json +99 -0
  746. package/src/modes/theme/defaults/dark-swamp.json +90 -0
  747. package/src/modes/theme/defaults/dark-synthwave.json +103 -0
  748. package/src/modes/theme/defaults/dark-taiga.json +91 -0
  749. package/src/modes/theme/defaults/dark-terminal.json +95 -0
  750. package/src/modes/theme/defaults/dark-tokyo-night.json +101 -0
  751. package/src/modes/theme/defaults/dark-tundra.json +91 -0
  752. package/src/modes/theme/defaults/dark-twilight.json +91 -0
  753. package/src/modes/theme/defaults/dark-volcanic.json +91 -0
  754. package/src/modes/theme/defaults/graphite.json +92 -0
  755. package/src/modes/theme/defaults/index.ts +199 -0
  756. package/src/modes/theme/defaults/light-arctic.json +107 -0
  757. package/src/modes/theme/defaults/light-aurora-day.json +91 -0
  758. package/src/modes/theme/defaults/light-canyon.json +91 -0
  759. package/src/modes/theme/defaults/light-catppuccin.json +106 -0
  760. package/src/modes/theme/defaults/light-cirrus.json +90 -0
  761. package/src/modes/theme/defaults/light-coral.json +95 -0
  762. package/src/modes/theme/defaults/light-cyberpunk.json +96 -0
  763. package/src/modes/theme/defaults/light-dawn.json +90 -0
  764. package/src/modes/theme/defaults/light-dunes.json +91 -0
  765. package/src/modes/theme/defaults/light-eucalyptus.json +95 -0
  766. package/src/modes/theme/defaults/light-forest.json +100 -0
  767. package/src/modes/theme/defaults/light-frost.json +95 -0
  768. package/src/modes/theme/defaults/light-github.json +115 -0
  769. package/src/modes/theme/defaults/light-glacier.json +91 -0
  770. package/src/modes/theme/defaults/light-gruvbox.json +108 -0
  771. package/src/modes/theme/defaults/light-haze.json +90 -0
  772. package/src/modes/theme/defaults/light-honeycomb.json +95 -0
  773. package/src/modes/theme/defaults/light-lagoon.json +91 -0
  774. package/src/modes/theme/defaults/light-lavender.json +95 -0
  775. package/src/modes/theme/defaults/light-meadow.json +91 -0
  776. package/src/modes/theme/defaults/light-mint.json +95 -0
  777. package/src/modes/theme/defaults/light-monochrome.json +101 -0
  778. package/src/modes/theme/defaults/light-ocean.json +99 -0
  779. package/src/modes/theme/defaults/light-one.json +99 -0
  780. package/src/modes/theme/defaults/light-opal.json +91 -0
  781. package/src/modes/theme/defaults/light-orchard.json +91 -0
  782. package/src/modes/theme/defaults/light-paper.json +95 -0
  783. package/src/modes/theme/defaults/light-poimandres.json +142 -0
  784. package/src/modes/theme/defaults/light-prism.json +90 -0
  785. package/src/modes/theme/defaults/light-retro.json +98 -0
  786. package/src/modes/theme/defaults/light-sand.json +95 -0
  787. package/src/modes/theme/defaults/light-savanna.json +91 -0
  788. package/src/modes/theme/defaults/light-solarized.json +102 -0
  789. package/src/modes/theme/defaults/light-soleil.json +90 -0
  790. package/src/modes/theme/defaults/light-sunset.json +99 -0
  791. package/src/modes/theme/defaults/light-synthwave.json +98 -0
  792. package/src/modes/theme/defaults/light-tokyo-night.json +111 -0
  793. package/src/modes/theme/defaults/light-wetland.json +91 -0
  794. package/src/modes/theme/defaults/light-zenith.json +89 -0
  795. package/src/modes/theme/defaults/limestone.json +94 -0
  796. package/src/modes/theme/defaults/mahogany.json +97 -0
  797. package/src/modes/theme/defaults/marble.json +93 -0
  798. package/src/modes/theme/defaults/obsidian.json +91 -0
  799. package/src/modes/theme/defaults/onyx.json +91 -0
  800. package/src/modes/theme/defaults/pearl.json +93 -0
  801. package/src/modes/theme/defaults/porcelain.json +91 -0
  802. package/src/modes/theme/defaults/quartz.json +96 -0
  803. package/src/modes/theme/defaults/sandstone.json +95 -0
  804. package/src/modes/theme/defaults/titanium.json +90 -0
  805. package/src/modes/theme/light.json +93 -0
  806. package/src/modes/theme/mermaid-cache.ts +92 -0
  807. package/src/modes/theme/shimmer.ts +235 -0
  808. package/src/modes/theme/theme-schema.json +459 -0
  809. package/src/modes/theme/theme.ts +2915 -0
  810. package/src/modes/turn-budget.ts +31 -0
  811. package/src/modes/types.ts +406 -0
  812. package/src/modes/ultrathink.ts +41 -0
  813. package/src/modes/utils/context-usage.ts +432 -0
  814. package/src/modes/utils/copy-targets.ts +360 -0
  815. package/src/modes/utils/hotkeys-markdown.ts +62 -0
  816. package/src/modes/utils/keybinding-matchers.ts +51 -0
  817. package/src/modes/utils/tools-markdown.ts +27 -0
  818. package/src/modes/utils/ui-helpers.ts +886 -0
  819. package/src/modes/workflow.ts +42 -0
  820. package/src/plan-mode/approved-plan.ts +186 -0
  821. package/src/plan-mode/plan-handoff.ts +37 -0
  822. package/src/plan-mode/plan-protection.ts +31 -0
  823. package/src/plan-mode/state.ts +6 -0
  824. package/src/priority.json +45 -0
  825. package/src/prompts/advisor/advise-tool.md +3 -0
  826. package/src/prompts/advisor/system.md +113 -0
  827. package/src/prompts/agents/designer.md +74 -0
  828. package/src/prompts/agents/explore.md +58 -0
  829. package/src/prompts/agents/frontmatter.md +11 -0
  830. package/src/prompts/agents/init.md +33 -0
  831. package/src/prompts/agents/librarian.md +119 -0
  832. package/src/prompts/agents/oracle.md +54 -0
  833. package/src/prompts/agents/plan.md +48 -0
  834. package/src/prompts/agents/reviewer.md +139 -0
  835. package/src/prompts/agents/task.md +17 -0
  836. package/src/prompts/bench.md +12 -0
  837. package/src/prompts/ci-green-request.md +36 -0
  838. package/src/prompts/dry-balance-bench.md +8 -0
  839. package/src/prompts/goals/goal-budget-limit.md +16 -0
  840. package/src/prompts/goals/goal-continuation.md +28 -0
  841. package/src/prompts/goals/goal-mode-active.md +23 -0
  842. package/src/prompts/goals/guided-goal-interview.md +8 -0
  843. package/src/prompts/goals/guided-goal-system.md +12 -0
  844. package/src/prompts/low-end/system.md +47 -0
  845. package/src/prompts/memories/consolidation.md +30 -0
  846. package/src/prompts/memories/consolidation_system.md +4 -0
  847. package/src/prompts/memories/read-path.md +17 -0
  848. package/src/prompts/memories/stage_one_input.md +6 -0
  849. package/src/prompts/memories/stage_one_system.md +21 -0
  850. package/src/prompts/review-custom-request.md +22 -0
  851. package/src/prompts/review-headless-request.md +16 -0
  852. package/src/prompts/review-request.md +69 -0
  853. package/src/prompts/steering/user-interjection.md +9 -0
  854. package/src/prompts/system/agent-creation-architect.md +50 -0
  855. package/src/prompts/system/agent-creation-user.md +6 -0
  856. package/src/prompts/system/auto-continue.md +1 -0
  857. package/src/prompts/system/auto-thinking-difficulty-local.md +14 -0
  858. package/src/prompts/system/auto-thinking-difficulty.md +12 -0
  859. package/src/prompts/system/autolearn-guidance-learn.md +1 -0
  860. package/src/prompts/system/autolearn-guidance.md +7 -0
  861. package/src/prompts/system/autolearn-nudge.md +3 -0
  862. package/src/prompts/system/background-tan-dispatch.md +8 -0
  863. package/src/prompts/system/btw-user.md +8 -0
  864. package/src/prompts/system/commit-message-system.md +14 -0
  865. package/src/prompts/system/custom-system-prompt.md +64 -0
  866. package/src/prompts/system/eager-task.md +7 -0
  867. package/src/prompts/system/eager-todo.md +18 -0
  868. package/src/prompts/system/empty-stop-retry.md +4 -0
  869. package/src/prompts/system/irc-autoreply.md +6 -0
  870. package/src/prompts/system/irc-incoming.md +7 -0
  871. package/src/prompts/system/manual-continue.md +7 -0
  872. package/src/prompts/system/memory-consolidation-system.md +8 -0
  873. package/src/prompts/system/memory-extraction-system.md +26 -0
  874. package/src/prompts/system/omfg-user.md +50 -0
  875. package/src/prompts/system/orchestrate-notice.md +40 -0
  876. package/src/prompts/system/personalities/default.md +18 -0
  877. package/src/prompts/system/personalities/friendly.md +17 -0
  878. package/src/prompts/system/personalities/pragmatic.md +15 -0
  879. package/src/prompts/system/plan-mode-active.md +109 -0
  880. package/src/prompts/system/plan-mode-approved.md +25 -0
  881. package/src/prompts/system/plan-mode-compact-instructions.md +16 -0
  882. package/src/prompts/system/plan-mode-reference.md +11 -0
  883. package/src/prompts/system/plan-mode-subagent.md +33 -0
  884. package/src/prompts/system/plan-mode-tool-decision-reminder.md +9 -0
  885. package/src/prompts/system/project-prompt.md +52 -0
  886. package/src/prompts/system/snapcompact-context-frames-note.md +1 -0
  887. package/src/prompts/system/snapcompact-context-stub.md +1 -0
  888. package/src/prompts/system/snapcompact-system-frames-note.md +1 -0
  889. package/src/prompts/system/snapcompact-system-stub.md +1 -0
  890. package/src/prompts/system/snapcompact-toolresult-note.md +1 -0
  891. package/src/prompts/system/subagent-system-prompt.md +71 -0
  892. package/src/prompts/system/subagent-user-prompt.md +3 -0
  893. package/src/prompts/system/subagent-yield-reminder.md +12 -0
  894. package/src/prompts/system/system-prompt.md +251 -0
  895. package/src/prompts/system/tiny-title-system.md +8 -0
  896. package/src/prompts/system/title-marker-instruction.md +1 -0
  897. package/src/prompts/system/title-system-marker.md +16 -0
  898. package/src/prompts/system/title-system.md +16 -0
  899. package/src/prompts/system/ttsr-interrupt.md +7 -0
  900. package/src/prompts/system/ttsr-tool-reminder.md +5 -0
  901. package/src/prompts/system/ultrathink-notice.md +3 -0
  902. package/src/prompts/system/unexpected-stop-classifier.md +17 -0
  903. package/src/prompts/system/unexpected-stop-retry.md +4 -0
  904. package/src/prompts/system/web-search.md +25 -0
  905. package/src/prompts/system/workflow-notice.md +70 -0
  906. package/src/prompts/tools/apply-patch.md +65 -0
  907. package/src/prompts/tools/ask.md +22 -0
  908. package/src/prompts/tools/ast-edit.md +22 -0
  909. package/src/prompts/tools/ast-grep.md +25 -0
  910. package/src/prompts/tools/async-result.md +8 -0
  911. package/src/prompts/tools/bash.md +45 -0
  912. package/src/prompts/tools/browser.md +42 -0
  913. package/src/prompts/tools/checkpoint.md +15 -0
  914. package/src/prompts/tools/debug.md +17 -0
  915. package/src/prompts/tools/eval.md +70 -0
  916. package/src/prompts/tools/find.md +19 -0
  917. package/src/prompts/tools/github.md +17 -0
  918. package/src/prompts/tools/goal.md +11 -0
  919. package/src/prompts/tools/image-attachment-describe-system.md +8 -0
  920. package/src/prompts/tools/image-attachment-describe.md +10 -0
  921. package/src/prompts/tools/image-gen.md +7 -0
  922. package/src/prompts/tools/inspect-image-system.md +20 -0
  923. package/src/prompts/tools/inspect-image.md +22 -0
  924. package/src/prompts/tools/irc.md +33 -0
  925. package/src/prompts/tools/job.md +17 -0
  926. package/src/prompts/tools/learn.md +7 -0
  927. package/src/prompts/tools/lsp-late-diagnostic.md +8 -0
  928. package/src/prompts/tools/lsp.md +39 -0
  929. package/src/prompts/tools/manage-skill.md +9 -0
  930. package/src/prompts/tools/memory-edit.md +8 -0
  931. package/src/prompts/tools/patch.md +57 -0
  932. package/src/prompts/tools/read.md +76 -0
  933. package/src/prompts/tools/recall.md +5 -0
  934. package/src/prompts/tools/reflect.md +5 -0
  935. package/src/prompts/tools/replace.md +29 -0
  936. package/src/prompts/tools/resolve.md +4 -0
  937. package/src/prompts/tools/retain.md +6 -0
  938. package/src/prompts/tools/rewind.md +13 -0
  939. package/src/prompts/tools/search-tool-bm25.md +32 -0
  940. package/src/prompts/tools/search.md +22 -0
  941. package/src/prompts/tools/ssh.md +22 -0
  942. package/src/prompts/tools/task-summary.md +17 -0
  943. package/src/prompts/tools/task.md +91 -0
  944. package/src/prompts/tools/todo.md +39 -0
  945. package/src/prompts/tools/web-search.md +6 -0
  946. package/src/prompts/tools/write.md +14 -0
  947. package/src/registry/agent-lifecycle.ts +270 -0
  948. package/src/registry/agent-registry.ts +190 -0
  949. package/src/sdk.ts +2919 -0
  950. package/src/secrets/index.ts +123 -0
  951. package/src/secrets/obfuscator.ts +298 -0
  952. package/src/secrets/regex.ts +21 -0
  953. package/src/session/agent-session.ts +12539 -0
  954. package/src/session/agent-storage.ts +478 -0
  955. package/src/session/artifacts.ts +153 -0
  956. package/src/session/auth-broker-config.ts +92 -0
  957. package/src/session/auth-storage.ts +24 -0
  958. package/src/session/blob-store.ts +255 -0
  959. package/src/session/client-bridge.ts +85 -0
  960. package/src/session/codex-auto-reset.ts +202 -0
  961. package/src/session/compact-modes.ts +105 -0
  962. package/src/session/history-storage.ts +361 -0
  963. package/src/session/indexed-session-storage.ts +427 -0
  964. package/src/session/messages.ts +546 -0
  965. package/src/session/redis-session-storage.ts +170 -0
  966. package/src/session/session-context.ts +399 -0
  967. package/src/session/session-dump-format.ts +216 -0
  968. package/src/session/session-entries.ts +198 -0
  969. package/src/session/session-history-format.ts +308 -0
  970. package/src/session/session-listing.ts +588 -0
  971. package/src/session/session-loader.ts +93 -0
  972. package/src/session/session-manager.ts +1748 -0
  973. package/src/session/session-migrations.ts +78 -0
  974. package/src/session/session-paths.ts +193 -0
  975. package/src/session/session-persistence.ts +147 -0
  976. package/src/session/session-storage.ts +590 -0
  977. package/src/session/shake-types.ts +43 -0
  978. package/src/session/snapcompact-inline.ts +542 -0
  979. package/src/session/snapcompact-savings-journal.ts +113 -0
  980. package/src/session/sql-session-storage.ts +314 -0
  981. package/src/session/streaming-output.ts +1330 -0
  982. package/src/session/tool-choice-queue.ts +290 -0
  983. package/src/session/unexpected-stop-classifier.ts +129 -0
  984. package/src/session/yield-queue.ts +183 -0
  985. package/src/slash-commands/acp-builtins.ts +70 -0
  986. package/src/slash-commands/available-commands.ts +105 -0
  987. package/src/slash-commands/builtin-registry.ts +2332 -0
  988. package/src/slash-commands/helpers/active-oauth-account.ts +44 -0
  989. package/src/slash-commands/helpers/collab-qrcode.ts +28 -0
  990. package/src/slash-commands/helpers/context-report.ts +66 -0
  991. package/src/slash-commands/helpers/format.ts +46 -0
  992. package/src/slash-commands/helpers/logout.ts +88 -0
  993. package/src/slash-commands/helpers/marketplace-manager.ts +25 -0
  994. package/src/slash-commands/helpers/mcp.ts +532 -0
  995. package/src/slash-commands/helpers/parse.ts +85 -0
  996. package/src/slash-commands/helpers/reset-usage.ts +66 -0
  997. package/src/slash-commands/helpers/ssh.ts +195 -0
  998. package/src/slash-commands/helpers/stats-dashboard.ts +85 -0
  999. package/src/slash-commands/helpers/todo.ts +279 -0
  1000. package/src/slash-commands/helpers/usage-report.ts +128 -0
  1001. package/src/slash-commands/marketplace-install-parser.ts +99 -0
  1002. package/src/slash-commands/types.ts +135 -0
  1003. package/src/ssh/config-writer.ts +183 -0
  1004. package/src/ssh/connection-manager.ts +510 -0
  1005. package/src/ssh/ssh-executor.ts +189 -0
  1006. package/src/ssh/sshfs-mount.ts +140 -0
  1007. package/src/ssh/utils.ts +8 -0
  1008. package/src/startup-splash.ts +19 -0
  1009. package/src/stt/asr-client.ts +521 -0
  1010. package/src/stt/asr-protocol.ts +65 -0
  1011. package/src/stt/asr-worker.ts +790 -0
  1012. package/src/stt/downloader.ts +138 -0
  1013. package/src/stt/endpointer.ts +259 -0
  1014. package/src/stt/index.ts +7 -0
  1015. package/src/stt/models.ts +150 -0
  1016. package/src/stt/recorder.ts +538 -0
  1017. package/src/stt/stt-controller.ts +380 -0
  1018. package/src/stt/transcriber.ts +60 -0
  1019. package/src/stt/wav.ts +173 -0
  1020. package/src/system-prompt.ts +709 -0
  1021. package/src/task/agents.ts +166 -0
  1022. package/src/task/commands.ts +132 -0
  1023. package/src/task/discovery.ts +122 -0
  1024. package/src/task/executor.ts +2356 -0
  1025. package/src/task/index.ts +1580 -0
  1026. package/src/task/name-generator.ts +1577 -0
  1027. package/src/task/omp-command.ts +26 -0
  1028. package/src/task/output-manager.ts +93 -0
  1029. package/src/task/parallel.ts +116 -0
  1030. package/src/task/persisted-revive.ts +128 -0
  1031. package/src/task/render.ts +1558 -0
  1032. package/src/task/repair-args.ts +129 -0
  1033. package/src/task/subprocess-tool-registry.ts +88 -0
  1034. package/src/task/types.ts +401 -0
  1035. package/src/task/worktree.ts +514 -0
  1036. package/src/telemetry-export.ts +144 -0
  1037. package/src/thinking.ts +187 -0
  1038. package/src/tiny/device.ts +111 -0
  1039. package/src/tiny/dtype.ts +101 -0
  1040. package/src/tiny/models.ts +252 -0
  1041. package/src/tiny/text.ts +169 -0
  1042. package/src/tiny/title-client.ts +538 -0
  1043. package/src/tiny/title-protocol.ts +56 -0
  1044. package/src/tiny/worker.ts +491 -0
  1045. package/src/tool-discovery/mode.ts +24 -0
  1046. package/src/tool-discovery/tool-index.ts +271 -0
  1047. package/src/tools/__tests__/json-tree.test.ts +35 -0
  1048. package/src/tools/approval.ts +189 -0
  1049. package/src/tools/ask.ts +977 -0
  1050. package/src/tools/ast-edit.ts +700 -0
  1051. package/src/tools/ast-grep.ts +483 -0
  1052. package/src/tools/auto-generated-guard.ts +322 -0
  1053. package/src/tools/bash-command-fixup.ts +37 -0
  1054. package/src/tools/bash-interactive.ts +408 -0
  1055. package/src/tools/bash-interceptor.ts +67 -0
  1056. package/src/tools/bash-pty-selection.ts +14 -0
  1057. package/src/tools/bash-skill-urls.ts +248 -0
  1058. package/src/tools/bash.ts +1405 -0
  1059. package/src/tools/browser/attach.ts +194 -0
  1060. package/src/tools/browser/cmux/cmux-tab.ts +1264 -0
  1061. package/src/tools/browser/cmux/rpc.ts +156 -0
  1062. package/src/tools/browser/cmux/socket-client.ts +309 -0
  1063. package/src/tools/browser/launch.ts +673 -0
  1064. package/src/tools/browser/readable.ts +112 -0
  1065. package/src/tools/browser/registry.ts +241 -0
  1066. package/src/tools/browser/render.ts +221 -0
  1067. package/src/tools/browser/tab-protocol.ts +107 -0
  1068. package/src/tools/browser/tab-supervisor.ts +799 -0
  1069. package/src/tools/browser/tab-worker-entry.ts +29 -0
  1070. package/src/tools/browser/tab-worker.ts +1226 -0
  1071. package/src/tools/browser.ts +403 -0
  1072. package/src/tools/builtin-names.ts +34 -0
  1073. package/src/tools/checkpoint.ts +136 -0
  1074. package/src/tools/conflict-detect.ts +718 -0
  1075. package/src/tools/context.ts +39 -0
  1076. package/src/tools/debug.ts +1087 -0
  1077. package/src/tools/eval-backends.ts +27 -0
  1078. package/src/tools/eval-render.ts +762 -0
  1079. package/src/tools/eval.ts +600 -0
  1080. package/src/tools/fetch.ts +1902 -0
  1081. package/src/tools/file-recorder.ts +35 -0
  1082. package/src/tools/find.ts +629 -0
  1083. package/src/tools/fs-cache-invalidation.ts +28 -0
  1084. package/src/tools/gh-cache-invalidation.ts +255 -0
  1085. package/src/tools/gh-format.ts +12 -0
  1086. package/src/tools/gh-renderer.ts +481 -0
  1087. package/src/tools/gh.ts +3752 -0
  1088. package/src/tools/github-cache.ts +663 -0
  1089. package/src/tools/grouped-file-output.ts +210 -0
  1090. package/src/tools/image-gen.ts +1586 -0
  1091. package/src/tools/index.ts +649 -0
  1092. package/src/tools/inspect-image-renderer.ts +132 -0
  1093. package/src/tools/inspect-image.ts +260 -0
  1094. package/src/tools/irc.ts +788 -0
  1095. package/src/tools/job.ts +612 -0
  1096. package/src/tools/json-tree.ts +260 -0
  1097. package/src/tools/jtd-to-json-schema.ts +219 -0
  1098. package/src/tools/jtd-to-typescript.ts +136 -0
  1099. package/src/tools/jtd-utils.ts +102 -0
  1100. package/src/tools/learn.ts +141 -0
  1101. package/src/tools/list-limit.ts +40 -0
  1102. package/src/tools/manage-skill.ts +100 -0
  1103. package/src/tools/match-line-format.ts +20 -0
  1104. package/src/tools/memory-edit.ts +59 -0
  1105. package/src/tools/memory-recall.ts +102 -0
  1106. package/src/tools/memory-reflect.ts +88 -0
  1107. package/src/tools/memory-render.ts +202 -0
  1108. package/src/tools/memory-retain.ts +89 -0
  1109. package/src/tools/output-meta.ts +768 -0
  1110. package/src/tools/output-schema-validator.ts +132 -0
  1111. package/src/tools/path-utils.ts +1116 -0
  1112. package/src/tools/plan-mode-guard.ts +142 -0
  1113. package/src/tools/puppeteer/00_stealth_tampering.txt +63 -0
  1114. package/src/tools/puppeteer/01_stealth_activity.txt +20 -0
  1115. package/src/tools/puppeteer/02_stealth_hairline.txt +11 -0
  1116. package/src/tools/puppeteer/03_stealth_botd.txt +384 -0
  1117. package/src/tools/puppeteer/04_stealth_iframe.txt +81 -0
  1118. package/src/tools/puppeteer/05_stealth_webgl.txt +75 -0
  1119. package/src/tools/puppeteer/06_stealth_screen.txt +72 -0
  1120. package/src/tools/puppeteer/07_stealth_fonts.txt +97 -0
  1121. package/src/tools/puppeteer/08_stealth_audio.txt +51 -0
  1122. package/src/tools/puppeteer/09_stealth_locale.txt +46 -0
  1123. package/src/tools/puppeteer/10_stealth_plugins.txt +208 -0
  1124. package/src/tools/puppeteer/11_stealth_hardware.txt +8 -0
  1125. package/src/tools/puppeteer/12_stealth_codecs.txt +40 -0
  1126. package/src/tools/puppeteer/13_stealth_worker.txt +74 -0
  1127. package/src/tools/read.ts +3124 -0
  1128. package/src/tools/render-utils.ts +895 -0
  1129. package/src/tools/renderers.ts +86 -0
  1130. package/src/tools/report-tool-issue.ts +530 -0
  1131. package/src/tools/resolve.ts +302 -0
  1132. package/src/tools/review.ts +251 -0
  1133. package/src/tools/search-tool-bm25.ts +351 -0
  1134. package/src/tools/search.ts +1583 -0
  1135. package/src/tools/sqlite-reader.ts +828 -0
  1136. package/src/tools/ssh.ts +369 -0
  1137. package/src/tools/todo.ts +938 -0
  1138. package/src/tools/tool-errors.ts +62 -0
  1139. package/src/tools/tool-result.ts +102 -0
  1140. package/src/tools/tool-timeouts.ts +30 -0
  1141. package/src/tools/tts.ts +265 -0
  1142. package/src/tools/write.ts +1182 -0
  1143. package/src/tools/yield.ts +269 -0
  1144. package/src/tts/downloader.ts +64 -0
  1145. package/src/tts/index.ts +8 -0
  1146. package/src/tts/models.ts +137 -0
  1147. package/src/tts/player.ts +137 -0
  1148. package/src/tts/runtime.ts +21 -0
  1149. package/src/tts/streaming-player.ts +266 -0
  1150. package/src/tts/tts-client.ts +642 -0
  1151. package/src/tts/tts-protocol.ts +60 -0
  1152. package/src/tts/tts-worker.ts +505 -0
  1153. package/src/tts/vocalizer.ts +162 -0
  1154. package/src/tts/wav.ts +58 -0
  1155. package/src/tui/code-cell.ts +257 -0
  1156. package/src/tui/file-list.ts +55 -0
  1157. package/src/tui/hyperlink.ts +178 -0
  1158. package/src/tui/index.ts +13 -0
  1159. package/src/tui/output-block.ts +240 -0
  1160. package/src/tui/status-line.ts +54 -0
  1161. package/src/tui/tree-list.ts +133 -0
  1162. package/src/tui/types.ts +15 -0
  1163. package/src/tui/utils.ts +103 -0
  1164. package/src/tui/width-aware-text.ts +58 -0
  1165. package/src/utils/block-context.ts +312 -0
  1166. package/src/utils/changelog.ts +132 -0
  1167. package/src/utils/clipboard.ts +262 -0
  1168. package/src/utils/command-args.ts +76 -0
  1169. package/src/utils/commit-message-generator.ts +147 -0
  1170. package/src/utils/edit-mode.ts +41 -0
  1171. package/src/utils/enhanced-paste.ts +230 -0
  1172. package/src/utils/event-bus.ts +33 -0
  1173. package/src/utils/external-editor.ts +78 -0
  1174. package/src/utils/file-display-mode.ts +45 -0
  1175. package/src/utils/file-mentions.ts +284 -0
  1176. package/src/utils/git.ts +1838 -0
  1177. package/src/utils/image-loading.ts +231 -0
  1178. package/src/utils/image-resize.ts +309 -0
  1179. package/src/utils/image-vision-fallback.ts +197 -0
  1180. package/src/utils/ipc.ts +38 -0
  1181. package/src/utils/jj.ts +248 -0
  1182. package/src/utils/lang-from-path.ts +244 -0
  1183. package/src/utils/markit.ts +143 -0
  1184. package/src/utils/mupdf-wasm-embed.ts +12 -0
  1185. package/src/utils/open.ts +55 -0
  1186. package/src/utils/qrcode.ts +535 -0
  1187. package/src/utils/session-color.ts +142 -0
  1188. package/src/utils/shell-snapshot.ts +187 -0
  1189. package/src/utils/sixel.ts +69 -0
  1190. package/src/utils/thinking-display.ts +11 -0
  1191. package/src/utils/title-generator.ts +416 -0
  1192. package/src/utils/tool-choice.ts +49 -0
  1193. package/src/utils/tools-manager.ts +372 -0
  1194. package/src/utils/turndown.ts +83 -0
  1195. package/src/utils/zip.ts +1091 -0
  1196. package/src/web/kagi.ts +304 -0
  1197. package/src/web/parallel.ts +353 -0
  1198. package/src/web/scrapers/artifacthub.ts +207 -0
  1199. package/src/web/scrapers/arxiv.ts +83 -0
  1200. package/src/web/scrapers/aur.ts +162 -0
  1201. package/src/web/scrapers/biorxiv.ts +133 -0
  1202. package/src/web/scrapers/bluesky.ts +262 -0
  1203. package/src/web/scrapers/brew.ts +172 -0
  1204. package/src/web/scrapers/cheatsh.ts +68 -0
  1205. package/src/web/scrapers/chocolatey.ts +196 -0
  1206. package/src/web/scrapers/choosealicense.ts +95 -0
  1207. package/src/web/scrapers/cisa-kev.ts +87 -0
  1208. package/src/web/scrapers/clojars.ts +154 -0
  1209. package/src/web/scrapers/coingecko.ts +177 -0
  1210. package/src/web/scrapers/crates-io.ts +97 -0
  1211. package/src/web/scrapers/crossref.ts +136 -0
  1212. package/src/web/scrapers/devto.ts +147 -0
  1213. package/src/web/scrapers/discogs.ts +306 -0
  1214. package/src/web/scrapers/discourse.ts +197 -0
  1215. package/src/web/scrapers/dockerhub.ts +138 -0
  1216. package/src/web/scrapers/docs-rs.ts +652 -0
  1217. package/src/web/scrapers/fdroid.ts +134 -0
  1218. package/src/web/scrapers/firefox-addons.ts +191 -0
  1219. package/src/web/scrapers/flathub.ts +223 -0
  1220. package/src/web/scrapers/github-gist.ts +58 -0
  1221. package/src/web/scrapers/github.ts +800 -0
  1222. package/src/web/scrapers/gitlab.ts +401 -0
  1223. package/src/web/scrapers/go-pkg.ts +266 -0
  1224. package/src/web/scrapers/hackage.ts +140 -0
  1225. package/src/web/scrapers/hackernews.ts +189 -0
  1226. package/src/web/scrapers/hex.ts +105 -0
  1227. package/src/web/scrapers/huggingface.ts +321 -0
  1228. package/src/web/scrapers/iacr.ts +89 -0
  1229. package/src/web/scrapers/index.ts +252 -0
  1230. package/src/web/scrapers/jetbrains-marketplace.ts +159 -0
  1231. package/src/web/scrapers/lemmy.ts +203 -0
  1232. package/src/web/scrapers/lobsters.ts +175 -0
  1233. package/src/web/scrapers/mastodon.ts +292 -0
  1234. package/src/web/scrapers/maven.ts +138 -0
  1235. package/src/web/scrapers/mdn.ts +173 -0
  1236. package/src/web/scrapers/metacpan.ts +222 -0
  1237. package/src/web/scrapers/musicbrainz.ts +250 -0
  1238. package/src/web/scrapers/npm.ts +98 -0
  1239. package/src/web/scrapers/nuget.ts +183 -0
  1240. package/src/web/scrapers/nvd.ts +222 -0
  1241. package/src/web/scrapers/ollama.ts +239 -0
  1242. package/src/web/scrapers/open-vsx.ts +106 -0
  1243. package/src/web/scrapers/opencorporates.ts +292 -0
  1244. package/src/web/scrapers/openlibrary.ts +336 -0
  1245. package/src/web/scrapers/orcid.ts +286 -0
  1246. package/src/web/scrapers/osv.ts +176 -0
  1247. package/src/web/scrapers/packagist.ts +160 -0
  1248. package/src/web/scrapers/pub-dev.ts +143 -0
  1249. package/src/web/scrapers/pubmed.ts +211 -0
  1250. package/src/web/scrapers/pypi.ts +112 -0
  1251. package/src/web/scrapers/rawg.ts +110 -0
  1252. package/src/web/scrapers/readthedocs.ts +120 -0
  1253. package/src/web/scrapers/reddit.ts +95 -0
  1254. package/src/web/scrapers/repology.ts +251 -0
  1255. package/src/web/scrapers/rfc.ts +201 -0
  1256. package/src/web/scrapers/rubygems.ts +103 -0
  1257. package/src/web/scrapers/searchcode.ts +189 -0
  1258. package/src/web/scrapers/sec-edgar.ts +261 -0
  1259. package/src/web/scrapers/semantic-scholar.ts +171 -0
  1260. package/src/web/scrapers/snapcraft.ts +187 -0
  1261. package/src/web/scrapers/sourcegraph.ts +336 -0
  1262. package/src/web/scrapers/spdx.ts +108 -0
  1263. package/src/web/scrapers/spotify.ts +198 -0
  1264. package/src/web/scrapers/stackoverflow.ts +120 -0
  1265. package/src/web/scrapers/terraform.ts +277 -0
  1266. package/src/web/scrapers/tldr.ts +47 -0
  1267. package/src/web/scrapers/twitter.ts +94 -0
  1268. package/src/web/scrapers/types.ts +354 -0
  1269. package/src/web/scrapers/utils.ts +109 -0
  1270. package/src/web/scrapers/vimeo.ts +133 -0
  1271. package/src/web/scrapers/vscode-marketplace.ts +187 -0
  1272. package/src/web/scrapers/w3c.ts +156 -0
  1273. package/src/web/scrapers/wikidata.ts +344 -0
  1274. package/src/web/scrapers/wikipedia.ts +84 -0
  1275. package/src/web/scrapers/youtube.ts +325 -0
  1276. package/src/web/search/index.ts +317 -0
  1277. package/src/web/search/provider.ts +169 -0
  1278. package/src/web/search/providers/anthropic.ts +343 -0
  1279. package/src/web/search/providers/base.ts +90 -0
  1280. package/src/web/search/providers/brave.ts +152 -0
  1281. package/src/web/search/providers/codex.ts +593 -0
  1282. package/src/web/search/providers/exa.ts +400 -0
  1283. package/src/web/search/providers/gemini.ts +518 -0
  1284. package/src/web/search/providers/jina.ts +111 -0
  1285. package/src/web/search/providers/kagi.ts +86 -0
  1286. package/src/web/search/providers/kimi.ts +196 -0
  1287. package/src/web/search/providers/parallel.ts +225 -0
  1288. package/src/web/search/providers/perplexity-auth.ts +133 -0
  1289. package/src/web/search/providers/perplexity.ts +866 -0
  1290. package/src/web/search/providers/searxng.ts +325 -0
  1291. package/src/web/search/providers/synthetic.ts +114 -0
  1292. package/src/web/search/providers/tavily.ts +176 -0
  1293. package/src/web/search/providers/utils.ts +128 -0
  1294. package/src/web/search/providers/zai.ts +333 -0
  1295. package/src/web/search/render.ts +262 -0
  1296. package/src/web/search/types.ts +462 -0
  1297. package/src/web/search/utils.ts +17 -0
  1298. package/src/workspace-tree.ts +326 -0
@@ -0,0 +1,1243 @@
1
+ /**
2
+ * Settings singleton with sync get/set and background persistence.
3
+ *
4
+ * Usage:
5
+ * import { settings } from "./settings";
6
+ *
7
+ * const enabled = settings.get("compaction.enabled"); // sync read
8
+ * settings.set("theme.dark", "titanium"); // sync write, saves in background
9
+ *
10
+ * For tests:
11
+ * const isolated = Settings.isolated({ "compaction.enabled": false });
12
+ */
13
+
14
+ import * as fs from "node:fs";
15
+ import * as os from "node:os";
16
+ import * as path from "node:path";
17
+ import {
18
+ getAgentDbPath,
19
+ getAgentDir,
20
+ getLastChangelogVersionPath,
21
+ getProjectDir,
22
+ isEnoent,
23
+ logger,
24
+ procmgr,
25
+ } from "@oh-my-pi/pi-utils";
26
+ import { JSONC, YAML } from "bun";
27
+ import { type Settings as SettingsCapabilityItem, settingsCapability } from "../capability/settings";
28
+ import type { ModelRole } from "../config/model-roles";
29
+ import { loadCapability } from "../discovery";
30
+ import { isLightTheme, setAutoThemeMapping, setColorBlindMode, setSymbolPreset } from "../modes/theme/theme";
31
+ import { AgentStorage } from "../session/agent-storage";
32
+ import { type EditMode, normalizeEditMode } from "../utils/edit-mode";
33
+ import { withFileLock } from "./file-lock";
34
+ import {
35
+ type BashInterceptorRule,
36
+ type GroupPrefix,
37
+ type GroupTypeMap,
38
+ getDefault,
39
+ SETTINGS_SCHEMA,
40
+ type SettingPath,
41
+ type SettingValue,
42
+ } from "./settings-schema";
43
+
44
+ // Re-export types that callers need
45
+ export type * from "./settings-schema";
46
+ export * from "./settings-schema";
47
+
48
+ // ═══════════════════════════════════════════════════════════════════════════
49
+ // Types
50
+ // ═══════════════════════════════════════════════════════════════════════════
51
+
52
+ /** Raw settings object as stored in YAML */
53
+ export interface RawSettings {
54
+ [key: string]: unknown;
55
+ }
56
+
57
+ export interface SettingsOptions {
58
+ /** Current working directory for project settings discovery */
59
+ cwd?: string;
60
+ /** Agent directory for config.yml storage */
61
+ agentDir?: string;
62
+ /** Don't persist to disk (for tests) */
63
+ inMemory?: boolean;
64
+ /** Initial overrides */
65
+ overrides?: Partial<Record<SettingPath, unknown>>;
66
+ /** Extra config.yml-style overlays loaded after global/project settings */
67
+ configFiles?: string[];
68
+ }
69
+
70
+ // ═══════════════════════════════════════════════════════════════════════════
71
+ // Path Utilities
72
+ // ═══════════════════════════════════════════════════════════════════════════
73
+
74
+ /**
75
+ * Get a nested value from an object by path segments.
76
+ */
77
+ function getByPath(obj: RawSettings, segments: readonly string[]): unknown {
78
+ let current: unknown = obj;
79
+ for (const segment of segments) {
80
+ if (current === null || current === undefined || typeof current !== "object") {
81
+ return undefined;
82
+ }
83
+ current = (current as Record<string, unknown>)[segment];
84
+ }
85
+ return current;
86
+ }
87
+
88
+ const SETTING_PATH_SEGMENTS: Record<SettingPath, readonly string[]> = Object.fromEntries(
89
+ (Object.keys(SETTINGS_SCHEMA) as SettingPath[]).map(settingPath => [settingPath, settingPath.split(".")]),
90
+ ) as unknown as Record<SettingPath, readonly string[]>;
91
+
92
+ /**
93
+ * Set a nested value in an object by path segments.
94
+ * Creates intermediate objects as needed.
95
+ */
96
+ function setByPath(obj: RawSettings, segments: string[], value: unknown): void {
97
+ let current = obj;
98
+ for (let i = 0; i < segments.length - 1; i++) {
99
+ const segment = segments[i];
100
+ if (!(segment in current) || typeof current[segment] !== "object" || current[segment] === null) {
101
+ current[segment] = {};
102
+ }
103
+ current = current[segment] as RawSettings;
104
+ }
105
+ current[segments[segments.length - 1]] = value;
106
+ }
107
+
108
+ const PATH_SCOPED_ARRAY_SETTINGS = new Set<SettingPath>(["enabledModels", "disabledProviders"]);
109
+ type PathScopedStringArrayEntry = {
110
+ path?: unknown;
111
+ paths?: unknown;
112
+ pathPrefix?: unknown;
113
+ pathPrefixes?: unknown;
114
+ values?: unknown;
115
+ items?: unknown;
116
+ models?: unknown;
117
+ providers?: unknown;
118
+ };
119
+
120
+ function expandTilde(p: string): string {
121
+ return p === "~" ? os.homedir() : p.startsWith("~/") ? path.join(os.homedir(), p.slice(2)) : p;
122
+ }
123
+
124
+ function normalizePathPrefix(prefix: string): string {
125
+ return path.resolve(expandTilde(prefix));
126
+ }
127
+
128
+ function pathMatchesPrefix(cwd: string, prefix: string): boolean {
129
+ const relative = path.relative(normalizePathPrefix(prefix), path.resolve(cwd));
130
+ return relative === "" || (!!relative && !relative.startsWith("..") && !path.isAbsolute(relative));
131
+ }
132
+
133
+ function stringArrayFromUnknown(value: unknown): string[] {
134
+ if (typeof value === "string") return [value];
135
+ if (Array.isArray(value)) return value.filter((item): item is string => typeof item === "string");
136
+ return [];
137
+ }
138
+
139
+ function shallowStringRecord(value: unknown): Record<string, string> {
140
+ if (!value || typeof value !== "object" || Array.isArray(value)) return {};
141
+
142
+ const result: Record<string, string> = {};
143
+ for (const [key, item] of Object.entries(value)) {
144
+ if (typeof item === "string") {
145
+ result[key] = item;
146
+ }
147
+ }
148
+ return result;
149
+ }
150
+
151
+ function resolvePathScopedStringArray(settingPath: SettingPath, value: unknown, cwd: string): string[] | undefined {
152
+ if (!PATH_SCOPED_ARRAY_SETTINGS.has(settingPath) || !Array.isArray(value)) return undefined;
153
+
154
+ const resolved: string[] = [];
155
+ for (const entry of value) {
156
+ if (typeof entry === "string") {
157
+ resolved.push(entry);
158
+ continue;
159
+ }
160
+ if (!entry || typeof entry !== "object" || Array.isArray(entry)) continue;
161
+
162
+ const scoped = entry as PathScopedStringArrayEntry;
163
+ const prefixes = [
164
+ ...stringArrayFromUnknown(scoped.path),
165
+ ...stringArrayFromUnknown(scoped.paths),
166
+ ...stringArrayFromUnknown(scoped.pathPrefix),
167
+ ...stringArrayFromUnknown(scoped.pathPrefixes),
168
+ ];
169
+ if (prefixes.length === 0 || !prefixes.some(prefix => pathMatchesPrefix(cwd, prefix))) continue;
170
+
171
+ const values =
172
+ settingPath === "enabledModels"
173
+ ? [
174
+ ...stringArrayFromUnknown(scoped.values),
175
+ ...stringArrayFromUnknown(scoped.items),
176
+ ...stringArrayFromUnknown(scoped.models),
177
+ ]
178
+ : [
179
+ ...stringArrayFromUnknown(scoped.values),
180
+ ...stringArrayFromUnknown(scoped.items),
181
+ ...stringArrayFromUnknown(scoped.providers),
182
+ ];
183
+ resolved.push(...values);
184
+ }
185
+
186
+ return resolved;
187
+ }
188
+
189
+ // ═══════════════════════════════════════════════════════════════════════════
190
+ // Settings Class
191
+ // ═══════════════════════════════════════════════════════════════════════════
192
+
193
+ export class Settings {
194
+ #configPath: string | null;
195
+ #cwd: string;
196
+ #agentDir: string;
197
+ #storage: AgentStorage | null = null;
198
+
199
+ #configFiles: string[] = [];
200
+ /** Global settings from config.yml */
201
+ #global: RawSettings = {};
202
+ /** Project settings from .claude/settings.yml etc */
203
+ #project: RawSettings = {};
204
+ /** Extra config.yml-style overlays passed by CLI */
205
+ #configOverlay: RawSettings = {};
206
+ /** Runtime overrides (not persisted) */
207
+ #overrides: RawSettings = {};
208
+ /** Merged view (global + project + overrides) */
209
+ #merged: RawSettings = {};
210
+ /** Cached resolved values from the merged view, including defaults/path scoping */
211
+ #resolvedCache = new Map<SettingPath, unknown>();
212
+
213
+ /** Paths modified during this session (for partial save) */
214
+ #modified = new Set<string>();
215
+
216
+ /** Legacy `lastChangelogVersion` captured from config.yml during migration (now a marker file). */
217
+ #legacyLastChangelogVersion?: string;
218
+
219
+ /** Pending save (debounced) */
220
+ #saveTimer?: NodeJS.Timeout;
221
+ #savePromise?: Promise<void>;
222
+
223
+ /** Whether to persist changes */
224
+ #persist: boolean;
225
+
226
+ private constructor(options: SettingsOptions = {}) {
227
+ this.#cwd = path.normalize(options.cwd ?? getProjectDir());
228
+ this.#agentDir = path.normalize(options.agentDir ?? getAgentDir());
229
+ this.#configPath = options.inMemory ? null : path.join(this.#agentDir, "config.yml");
230
+ this.#configFiles = options.configFiles?.map(file => path.resolve(this.#cwd, expandTilde(file))) ?? [];
231
+ this.#persist = !options.inMemory;
232
+
233
+ if (options.overrides) {
234
+ for (const [key, value] of Object.entries(options.overrides)) {
235
+ setByPath(this.#overrides, key.split("."), value);
236
+ }
237
+
238
+ this.#overrides = this.#migrateRawSettings(this.#overrides);
239
+ }
240
+ }
241
+
242
+ // ─────────────────────────────────────────────────────────────────────────
243
+ // Factory Methods
244
+ // ─────────────────────────────────────────────────────────────────────────
245
+
246
+ /**
247
+ * Initialize the global singleton.
248
+ * Call once at startup before accessing `settings`.
249
+ */
250
+ static init(options: SettingsOptions = {}): Promise<Settings> {
251
+ if (globalInstancePromise) return globalInstancePromise;
252
+
253
+ const instance = new Settings(options);
254
+ const promise = instance.#load();
255
+ globalInstancePromise = promise;
256
+
257
+ return promise.then(
258
+ instance => {
259
+ globalInstance = instance;
260
+ clearBoundSettingsMethods();
261
+ globalInstancePromise = Promise.resolve(instance);
262
+ return instance;
263
+ },
264
+ error => {
265
+ globalInstance = null;
266
+ globalInstancePromise = null;
267
+ clearBoundSettingsMethods();
268
+ throw error;
269
+ },
270
+ );
271
+ }
272
+
273
+ /**
274
+ * Create an isolated instance for testing.
275
+ * Does not affect the global singleton.
276
+ */
277
+ static isolated(overrides: Partial<Record<SettingPath, unknown>> = {}): Settings {
278
+ const instance = new Settings({ inMemory: true, overrides });
279
+ instance.#rebuildMerged();
280
+ return instance;
281
+ }
282
+
283
+ /**
284
+ * Get the global singleton.
285
+ * Throws if not initialized.
286
+ */
287
+ static get instance(): Settings {
288
+ if (!globalInstance) {
289
+ throw new Error("Settings not initialized. Call Settings.init() first.");
290
+ }
291
+ return globalInstance;
292
+ }
293
+
294
+ // ─────────────────────────────────────────────────────────────────────────
295
+ // Core API
296
+ // ─────────────────────────────────────────────────────────────────────────
297
+
298
+ /**
299
+ * Get a setting value (sync).
300
+ * Returns the merged value from global + project + overrides, or the default.
301
+ */
302
+ get<P extends SettingPath>(path: P): SettingValue<P> {
303
+ if (this.#resolvedCache.has(path)) {
304
+ return this.#resolvedCache.get(path) as SettingValue<P>;
305
+ }
306
+
307
+ const value = getByPath(this.#merged, SETTING_PATH_SEGMENTS[path]);
308
+ const resolved =
309
+ value !== undefined ? (resolvePathScopedStringArray(path, value, this.#cwd) ?? value) : getDefault(path);
310
+ this.#resolvedCache.set(path, resolved);
311
+ return resolved as SettingValue<P>;
312
+ }
313
+
314
+ /**
315
+ * Whether `path` has an explicitly configured value (global config, project
316
+ * config, or runtime override) rather than falling back to the schema default.
317
+ */
318
+ isConfigured(path: SettingPath): boolean {
319
+ return getByPath(this.#merged, SETTING_PATH_SEGMENTS[path]) !== undefined;
320
+ }
321
+
322
+ /**
323
+ * Set a setting value (sync).
324
+ * Updates global settings and queues a background save.
325
+ * Triggers hooks for settings that have side effects.
326
+ */
327
+ set<P extends SettingPath>(path: P, value: SettingValue<P>): void {
328
+ const prev = this.get(path);
329
+ const segments = path.split(".");
330
+ setByPath(this.#global, segments, value);
331
+ this.#modified.add(path);
332
+ this.#rebuildMerged();
333
+ const next = this.get(path);
334
+ this.#queueSave();
335
+
336
+ // Trigger hook if exists
337
+ const hook = SETTING_HOOKS[path];
338
+ if (hook) {
339
+ hook(value, prev);
340
+ }
341
+ this.#fireEffectiveSettingChanged(path, next, prev);
342
+ }
343
+
344
+ /**
345
+ * Apply runtime overrides (not persisted).
346
+ */
347
+ override<P extends SettingPath>(path: P, value: SettingValue<P>): void {
348
+ const prev = this.get(path);
349
+ const segments = path.split(".");
350
+ setByPath(this.#overrides, segments, value);
351
+ this.#rebuildMerged();
352
+ this.#fireEffectiveSettingChanged(path, this.get(path), prev);
353
+ }
354
+
355
+ /**
356
+ * Clear a runtime override.
357
+ */
358
+ clearOverride(path: SettingPath): void {
359
+ const prev = this.get(path);
360
+ const segments = path.split(".");
361
+ let current = this.#overrides;
362
+ for (let i = 0; i < segments.length - 1; i++) {
363
+ const segment = segments[i];
364
+ if (!(segment in current)) return;
365
+ current = current[segment] as RawSettings;
366
+ }
367
+ delete current[segments[segments.length - 1]];
368
+ this.#rebuildMerged();
369
+ this.#fireEffectiveSettingChanged(path, this.get(path), prev);
370
+ }
371
+
372
+ #fireEffectiveSettingChanged(path: SettingPath, value: unknown, prev: unknown): void {
373
+ if (Object.is(value, prev)) return;
374
+ if (path === "statusLine.sessionAccent") {
375
+ statusLineSessionAccentSignal.fire();
376
+ }
377
+ }
378
+
379
+ /**
380
+ * Flush any pending saves to disk.
381
+ * Call before exit to ensure all changes are persisted.
382
+ */
383
+ async flush(): Promise<void> {
384
+ if (this.#saveTimer) {
385
+ clearTimeout(this.#saveTimer);
386
+ this.#saveTimer = undefined;
387
+ }
388
+ if (this.#savePromise) {
389
+ await this.#savePromise;
390
+ }
391
+ if (this.#modified.size > 0) {
392
+ await this.#saveNow();
393
+ }
394
+ }
395
+
396
+ async cloneForCwd(cwd: string): Promise<Settings> {
397
+ const cloned = new Settings({
398
+ cwd,
399
+ agentDir: this.#agentDir,
400
+ inMemory: !this.#persist,
401
+ });
402
+ cloned.#storage = this.#storage;
403
+ cloned.#global = structuredClone(this.#global);
404
+ cloned.#project = this.#persist ? await cloned.#loadProjectSettings() : structuredClone(this.#project);
405
+ cloned.#configFiles = [...this.#configFiles];
406
+ cloned.#configOverlay = structuredClone(this.#configOverlay);
407
+ cloned.#overrides = structuredClone(this.#overrides);
408
+ cloned.#rebuildMerged();
409
+ cloned.#fireAllHooks();
410
+ return cloned;
411
+ }
412
+
413
+ /**
414
+ * Re-scope this instance to a new working directory *in place*: reload the
415
+ * project layer (`.claude/settings.yml` etc.) from `cwd`, re-resolve
416
+ * path-scoped settings against it, and re-fire side-effect hooks (theme,
417
+ * symbols, tab width, …). Global settings and runtime overrides are preserved.
418
+ *
419
+ * Unlike {@link cloneForCwd}, this mutates the live instance, so every holder
420
+ * (the `settings` proxy, the active session, controllers) observes the new
421
+ * project scope without swapping references — used when the process changes
422
+ * directory mid-run (`/move`, cross-project resume). No-op when `cwd` is
423
+ * already the current scope.
424
+ */
425
+ async reloadForCwd(cwd: string): Promise<void> {
426
+ const normalized = path.normalize(cwd);
427
+ if (normalized === this.#cwd) return;
428
+ this.#cwd = normalized;
429
+ if (this.#persist) {
430
+ this.#project = await this.#loadProjectSettings();
431
+ }
432
+ this.#rebuildMerged();
433
+ this.#fireAllHooks();
434
+ }
435
+
436
+ // ─────────────────────────────────────────────────────────────────────────
437
+ // Accessors
438
+ // ─────────────────────────────────────────────────────────────────────────
439
+
440
+ getStorage(): AgentStorage | null {
441
+ return this.#storage;
442
+ }
443
+
444
+ getCwd(): string {
445
+ return this.#cwd;
446
+ }
447
+
448
+ getAgentDir(): string {
449
+ return this.#agentDir;
450
+ }
451
+
452
+ getPlansDirectory(): string {
453
+ return path.join(this.#agentDir, "plans");
454
+ }
455
+
456
+ /**
457
+ * Get shell configuration based on settings.
458
+ */
459
+ getShellConfig() {
460
+ const shell = this.get("shellPath");
461
+ return procmgr.getShellConfig(shell);
462
+ }
463
+
464
+ /**
465
+ * Get all settings in a group with full type safety.
466
+ */
467
+ getGroup<G extends GroupPrefix>(prefix: G): GroupTypeMap[G] {
468
+ const result: Record<string, unknown> = {};
469
+ for (const key of Object.keys(SETTINGS_SCHEMA) as SettingPath[]) {
470
+ if (key.startsWith(`${prefix}.`)) {
471
+ const suffix = key.slice(prefix.length + 1);
472
+ result[suffix] = this.get(key);
473
+ }
474
+ }
475
+ return result as unknown as GroupTypeMap[G];
476
+ }
477
+
478
+ /**
479
+ * Get the edit variant for a specific model.
480
+ * Returns "patch", "replace", "hashline", "apply_patch", or null (use global default).
481
+ */
482
+ getEditVariantForModel(model: string | undefined): EditMode | null {
483
+ if (!model) return null;
484
+ const variants = (this.#merged.edit as { modelVariants?: Record<string, string> })?.modelVariants;
485
+ if (!variants) return null;
486
+ for (const pattern in variants) {
487
+ if (model.includes(pattern)) {
488
+ const value = normalizeEditMode(variants[pattern]);
489
+ if (value) {
490
+ return value;
491
+ }
492
+ }
493
+ }
494
+ return null;
495
+ }
496
+
497
+ /**
498
+ * Get bash interceptor rules (typed accessor for complex array config).
499
+ */
500
+ getBashInterceptorRules(): BashInterceptorRule[] {
501
+ return this.get("bashInterceptor.patterns");
502
+ }
503
+
504
+ /**
505
+ * Set a model role (helper for modelRoles record).
506
+ */
507
+ setModelRole(role: ModelRole | string, modelId: string): void {
508
+ const current = shallowStringRecord(getByPath(this.#global, ["modelRoles"]));
509
+ const runtimeOverrides = getByPath(this.#overrides, ["modelRoles"]);
510
+ const updateRuntimeOverride =
511
+ !!runtimeOverrides &&
512
+ typeof runtimeOverrides === "object" &&
513
+ !Array.isArray(runtimeOverrides) &&
514
+ Object.hasOwn(runtimeOverrides, role);
515
+
516
+ this.set("modelRoles", { ...current, [role]: modelId });
517
+
518
+ if (updateRuntimeOverride) {
519
+ this.override("modelRoles", { ...shallowStringRecord(runtimeOverrides), [role]: modelId });
520
+ }
521
+ }
522
+
523
+ /**
524
+ * Get a model role (helper for modelRoles record).
525
+ */
526
+ getModelRole(role: ModelRole | string): string | undefined {
527
+ const roles = this.get("modelRoles");
528
+ return roles[role];
529
+ }
530
+
531
+ /**
532
+ * Get all model roles (helper for modelRoles record).
533
+ */
534
+ getModelRoles(): ReadOnlyDict<string> {
535
+ return { ...this.get("modelRoles") };
536
+ }
537
+
538
+ /*
539
+ * Override model roles (helper for modelRoles record).
540
+ */
541
+ overrideModelRoles(roles: ReadOnlyDict<string>): void {
542
+ const next = shallowStringRecord(getByPath(this.#overrides, ["modelRoles"]));
543
+ for (const [role, modelId] of Object.entries(roles)) {
544
+ if (modelId) {
545
+ next[role] = modelId;
546
+ }
547
+ }
548
+ this.override("modelRoles", next);
549
+ }
550
+
551
+ /**
552
+ * Set disabled providers (for compatibility with discovery system).
553
+ */
554
+ setDisabledProviders(ids: string[]): void {
555
+ this.set("disabledProviders", ids);
556
+ }
557
+
558
+ // ─────────────────────────────────────────────────────────────────────────
559
+ // Loading
560
+ // ─────────────────────────────────────────────────────────────────────────
561
+
562
+ async #load(): Promise<Settings> {
563
+ // Project settings load (loadCapability scans cwd) is independent of the
564
+ // persist chain (storage open → legacy migration → global config.yml read),
565
+ // so kick it off first and await after the persist chain completes. The
566
+ // persist steps remain sequential: migration may write config.yml, which
567
+ // #loadYaml then reads; migration's db fallback needs #storage opened.
568
+ const projectPromise = this.#loadProjectSettings();
569
+
570
+ if (this.#persist) {
571
+ this.#storage = await AgentStorage.open(getAgentDbPath(this.#agentDir));
572
+ await this.#migrateFromLegacy();
573
+ this.#global = await this.#loadYaml(this.#configPath!);
574
+ await this.#seedLastChangelogVersionMarker();
575
+ }
576
+
577
+ this.#project = await projectPromise;
578
+ this.#configOverlay = await this.#loadConfigOverlays();
579
+
580
+ // Build merged view (global → project → overrides; project wins over global)
581
+ this.#rebuildMerged();
582
+ this.#fireAllHooks();
583
+ return this;
584
+ }
585
+
586
+ async #loadYaml(filePath: string): Promise<RawSettings> {
587
+ try {
588
+ const content = await Bun.file(filePath).text();
589
+ const parsed = YAML.parse(content);
590
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
591
+ return {};
592
+ }
593
+ return this.#migrateRawSettings(parsed as RawSettings);
594
+ } catch (error) {
595
+ if (isEnoent(error)) return {};
596
+ logger.warn("Settings: failed to load", { path: filePath, error: String(error) });
597
+ return {};
598
+ }
599
+ }
600
+
601
+ async #loadProjectSettings(): Promise<RawSettings> {
602
+ try {
603
+ const result = await loadCapability(settingsCapability.id, { cwd: this.#cwd });
604
+ let merged: RawSettings = {};
605
+ for (const item of result.items as SettingsCapabilityItem[]) {
606
+ if (item.level === "project") {
607
+ merged = this.#deepMerge(merged, item.data as RawSettings);
608
+ }
609
+ }
610
+ return this.#migrateRawSettings(merged);
611
+ } catch {
612
+ return {};
613
+ }
614
+ }
615
+
616
+ async #loadConfigOverlays(): Promise<RawSettings> {
617
+ let merged: RawSettings = {};
618
+ for (const filePath of this.#configFiles) {
619
+ merged = this.#deepMerge(merged, await this.#loadOverlayYaml(filePath));
620
+ }
621
+ return merged;
622
+ }
623
+
624
+ /**
625
+ * Strict loader for explicit `--config` overlays: unlike `#loadYaml`,
626
+ * missing or malformed files are hard errors so a typo'd path cannot
627
+ * silently fall back to the persistent settings.
628
+ */
629
+ async #loadOverlayYaml(filePath: string): Promise<RawSettings> {
630
+ let content: string;
631
+ try {
632
+ content = await Bun.file(filePath).text();
633
+ } catch (error) {
634
+ throw new Error(
635
+ isEnoent(error)
636
+ ? `Config overlay not found: ${filePath}`
637
+ : `Failed to read config overlay ${filePath}: ${String(error)}`,
638
+ );
639
+ }
640
+ let parsed: unknown;
641
+ try {
642
+ parsed = YAML.parse(content);
643
+ } catch (error) {
644
+ throw new Error(`Failed to parse config overlay ${filePath}: ${String(error)}`);
645
+ }
646
+ if (parsed === null || parsed === undefined) return {};
647
+ if (typeof parsed !== "object" || Array.isArray(parsed)) {
648
+ throw new Error(`Config overlay must be a YAML mapping: ${filePath}`);
649
+ }
650
+ return this.#migrateRawSettings(parsed as RawSettings);
651
+ }
652
+
653
+ async #migrateFromLegacy(): Promise<void> {
654
+ if (!this.#configPath) return;
655
+
656
+ // Check if config.yml already exists
657
+ try {
658
+ await Bun.file(this.#configPath).text();
659
+ return; // Already exists, no migration needed
660
+ } catch (err) {
661
+ if (!isEnoent(err)) return;
662
+ }
663
+
664
+ let settings: RawSettings = {};
665
+ let migrated = false;
666
+
667
+ // 1. Migrate from settings.json
668
+ const settingsJsonPath = path.join(this.#agentDir, "settings.json");
669
+ try {
670
+ const parsed: unknown = JSONC.parse(await Bun.file(settingsJsonPath).text());
671
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
672
+ settings = this.#deepMerge(settings, this.#migrateRawSettings(parsed as RawSettings));
673
+ migrated = true;
674
+ try {
675
+ fs.renameSync(settingsJsonPath, `${settingsJsonPath}.bak`);
676
+ } catch {}
677
+ }
678
+ } catch {}
679
+
680
+ // 2. Migrate from agent.db
681
+ try {
682
+ const dbSettings = this.#storage?.getSettings();
683
+ if (dbSettings) {
684
+ settings = this.#deepMerge(settings, this.#migrateRawSettings(dbSettings as RawSettings));
685
+ migrated = true;
686
+ }
687
+ } catch {}
688
+
689
+ // 3. Write merged settings
690
+ if (migrated && Object.keys(settings).length > 0) {
691
+ try {
692
+ await Bun.write(this.#configPath, YAML.stringify(settings, null, 2));
693
+ logger.debug("Settings: migrated to config.yml", { path: this.#configPath });
694
+ } catch {}
695
+ }
696
+ }
697
+
698
+ /** Apply schema migrations to raw settings */
699
+ #migrateRawSettings(raw: RawSettings): RawSettings {
700
+ // queueMode -> steeringMode
701
+ if ("queueMode" in raw && !("steeringMode" in raw)) {
702
+ raw.steeringMode = raw.queueMode;
703
+ delete raw.queueMode;
704
+ }
705
+
706
+ // lastChangelogVersion moved out of config.yml into the
707
+ // <agentDir>/last-changelog-version marker file so version bumps no
708
+ // longer dirty user-tracked configs. Capture for marker seeding (see
709
+ // #seedLastChangelogVersionMarker), then strip the key — the next
710
+ // config save drops it from disk.
711
+ if (typeof raw.lastChangelogVersion === "string") {
712
+ this.#legacyLastChangelogVersion ??= raw.lastChangelogVersion;
713
+ }
714
+ delete raw.lastChangelogVersion;
715
+
716
+ // ask.timeout: ms -> seconds (if value > 1000, it's old ms format)
717
+ if (raw.ask && typeof (raw.ask as Record<string, unknown>).timeout === "number") {
718
+ const oldValue = (raw.ask as Record<string, unknown>).timeout as number;
719
+ if (oldValue > 1000) {
720
+ (raw.ask as Record<string, unknown>).timeout = Math.round(oldValue / 1000);
721
+ }
722
+ }
723
+
724
+ // Migrate old flat "theme" string to nested theme.dark/theme.light
725
+ if (typeof raw.theme === "string") {
726
+ const oldTheme = raw.theme;
727
+ if (oldTheme === "light" || oldTheme === "dark") {
728
+ // Built-in defaults — just remove, let new defaults apply
729
+ delete raw.theme;
730
+ } else {
731
+ // Custom theme — detect luminance to place in correct slot
732
+ const slot = isLightTheme(oldTheme) ? "light" : "dark";
733
+ raw.theme = { [slot]: oldTheme };
734
+ }
735
+ }
736
+
737
+ // task.isolation.enabled (boolean) -> task.isolation.mode (enum)
738
+ const taskObj = raw.task as Record<string, unknown> | undefined;
739
+ const isolationObj = taskObj?.isolation as Record<string, unknown> | undefined;
740
+ if (isolationObj && "enabled" in isolationObj) {
741
+ if (typeof isolationObj.enabled === "boolean") {
742
+ isolationObj.mode = isolationObj.enabled ? "auto" : "none";
743
+ }
744
+ delete isolationObj.enabled;
745
+ }
746
+
747
+ // task.simple: removed — the task tool no longer accepts a per-call
748
+ // schema (workflows drive structured output via eval agent()) and the
749
+ // batch/context shape is gated by task.batch instead.
750
+ if (taskObj && "simple" in taskObj) {
751
+ delete taskObj.simple;
752
+ }
753
+
754
+ // task.eager / todo.eager: boolean -> enum (default | preferred | always).
755
+ // `true` reproduced the previous "on" behavior, which is now `always`.
756
+ if (taskObj && typeof taskObj.eager === "boolean") {
757
+ taskObj.eager = taskObj.eager ? "always" : "default";
758
+ }
759
+ const todoObj = raw.todo as Record<string, unknown> | undefined;
760
+ if (todoObj && typeof todoObj.eager === "boolean") {
761
+ todoObj.eager = todoObj.eager ? "always" : "default";
762
+ }
763
+
764
+ // task.isolation.mode: legacy values from before the pi-iso PAL refactor.
765
+ // `worktree` was git worktree → now lives under `rcopy`. `fuse-overlay`
766
+ // and `fuse-projfs` are now the platform-named `overlayfs` / `projfs`
767
+ // kinds; the PAL falls back internally when the chosen one isn't
768
+ // available, so we don't need the old TS-side platform guards.
769
+ if (isolationObj && typeof isolationObj.mode === "string") {
770
+ const legacy: Record<string, string> = {
771
+ worktree: "rcopy",
772
+ "fuse-overlay": "overlayfs",
773
+ "fuse-projfs": "projfs",
774
+ };
775
+ const mapped = legacy[isolationObj.mode as string];
776
+ if (mapped !== undefined) {
777
+ isolationObj.mode = mapped;
778
+ }
779
+ }
780
+
781
+ // edit.mode: removed "atom" and "vim" variants map back to "hashline"
782
+ const editObj = raw.edit as Record<string, unknown> | undefined;
783
+ if (editObj) {
784
+ if (editObj.mode === "atom" || editObj.mode === "vim") {
785
+ editObj.mode = "hashline";
786
+ }
787
+ const modelVariants = editObj.modelVariants as Record<string, unknown> | undefined;
788
+ if (modelVariants && typeof modelVariants === "object" && !Array.isArray(modelVariants)) {
789
+ for (const [pattern, variant] of Object.entries(modelVariants)) {
790
+ if (variant === "atom" || variant === "vim") {
791
+ modelVariants[pattern] = "hashline";
792
+ }
793
+ }
794
+ }
795
+ }
796
+ if (raw["edit.mode"] === "atom" || raw["edit.mode"] === "vim") {
797
+ raw["edit.mode"] = "hashline";
798
+ }
799
+
800
+ // compaction.strategy: removed local-model shake-summary mode; plain shake
801
+ // keeps the same mechanical artifact-backed reduction without background CPU.
802
+ const compactionObj = raw.compaction as Record<string, unknown> | undefined;
803
+ if (compactionObj?.strategy === "shake-summary") {
804
+ compactionObj.strategy = "shake";
805
+ }
806
+ if (raw["compaction.strategy"] === "shake-summary") {
807
+ raw["compaction.strategy"] = "shake";
808
+ }
809
+
810
+ // snapcompact.systemPrompt: boolean -> scoped enum.
811
+ const snapcompactObj = raw.snapcompact as Record<string, unknown> | undefined;
812
+ if (snapcompactObj && typeof snapcompactObj.systemPrompt === "boolean") {
813
+ snapcompactObj.systemPrompt = snapcompactObj.systemPrompt ? "all" : "none";
814
+ }
815
+ if (typeof raw["snapcompact.systemPrompt"] === "boolean") {
816
+ raw["snapcompact.systemPrompt"] = raw["snapcompact.systemPrompt"] ? "all" : "none";
817
+ }
818
+
819
+ // statusLine: rename "plan_mode" segment to "mode"
820
+ const statusLineObj = raw.statusLine as Record<string, unknown> | undefined;
821
+ if (statusLineObj) {
822
+ for (const key of ["leftSegments", "rightSegments"] as const) {
823
+ const segments = statusLineObj[key];
824
+ if (Array.isArray(segments)) {
825
+ statusLineObj[key] = segments.map(seg => (seg === "plan_mode" ? "mode" : seg));
826
+ }
827
+ }
828
+ const segmentOptions = statusLineObj.segmentOptions as Record<string, unknown> | undefined;
829
+ if (segmentOptions && "plan_mode" in segmentOptions && !("mode" in segmentOptions)) {
830
+ segmentOptions.mode = segmentOptions.plan_mode;
831
+ delete segmentOptions.plan_mode;
832
+ }
833
+ }
834
+
835
+ // providers.parallelFetch (boolean) replaced by the providers.fetch reader
836
+ // priority enum. The new default ("auto") supersedes both old values —
837
+ // Parallel is now a deep fallback in the auto chain rather than the first
838
+ // choice — so drop the legacy key (flat and nested) and let the enum
839
+ // default apply.
840
+ const providersObj = raw.providers as Record<string, unknown> | undefined;
841
+ if (providersObj && "parallelFetch" in providersObj) {
842
+ delete providersObj.parallelFetch;
843
+ }
844
+ delete raw["providers.parallelFetch"];
845
+
846
+ // codexResets.autoRedeem: boolean -> tri-state enum.
847
+ // Existing explicit false keeps the old "do not run" behavior; missing
848
+ // config now falls through to the new "unset" default, which asks before
849
+ // the first eligible spend.
850
+ const codexResetsObj = raw.codexResets as Record<string, unknown> | undefined;
851
+ if (codexResetsObj && typeof codexResetsObj.autoRedeem === "boolean") {
852
+ codexResetsObj.autoRedeem = codexResetsObj.autoRedeem ? "yes" : "no";
853
+ }
854
+ if (typeof raw["codexResets.autoRedeem"] === "boolean") {
855
+ raw["codexResets.autoRedeem"] = raw["codexResets.autoRedeem"] ? "yes" : "no";
856
+ }
857
+
858
+ // Map legacy `memories.enabled` boolean to the explicit `memory.backend`
859
+ // enum if the latter hasn't been set yet. Idempotent: subsequent
860
+ // migrations are no-ops once memory.backend is materialised.
861
+ const memoryBackendObj = raw.memory as Record<string, unknown> | undefined;
862
+ const memoryBackendSet = memoryBackendObj && typeof memoryBackendObj.backend === "string";
863
+ const memoriesObj = raw.memories as Record<string, unknown> | undefined;
864
+ if (!memoryBackendSet && memoriesObj && typeof memoriesObj.enabled === "boolean") {
865
+ const next = memoriesObj.enabled ? "local" : "off";
866
+ const memoryRoot = (memoryBackendObj ?? {}) as Record<string, unknown>;
867
+ memoryRoot.backend = next;
868
+ raw.memory = memoryRoot;
869
+ }
870
+
871
+ // Rename the legacy local `mnemosyne` memory backend to `mnemopi`.
872
+ // - `memory.backend: "mnemosyne"` now selects the renamed backend.
873
+ // - the top-level `mnemosyne` settings object becomes `mnemopi`.
874
+ // Idempotent: skips the object move once `mnemopi` is materialised.
875
+ if (memoryBackendObj && memoryBackendObj.backend === "mnemosyne") {
876
+ memoryBackendObj.backend = "mnemopi";
877
+ }
878
+ if ("mnemosyne" in raw && !("mnemopi" in raw)) {
879
+ raw.mnemopi = raw.mnemosyne;
880
+ delete raw.mnemosyne;
881
+ }
882
+
883
+ // hindsight: dynamicBankId/agentName -> scoping enum + bankId
884
+ // - dynamicBankId=true → scoping="per-project" (closest semantic match;
885
+ // the legacy `agent::project::channel::user` tuple was per-project in
886
+ // practice — the channel/user env vars were rarely set).
887
+ // - hindsight.agentName was only used as the agent slot in the legacy
888
+ // dynamic tuple; if the user customised it we surface it as the new
889
+ // bankId base when no explicit bankId is set.
890
+ const hindsightObj = raw.hindsight as Record<string, unknown> | undefined;
891
+ if (hindsightObj) {
892
+ if ("dynamicBankId" in hindsightObj) {
893
+ if (!("scoping" in hindsightObj) && hindsightObj.dynamicBankId === true) {
894
+ hindsightObj.scoping = "per-project";
895
+ }
896
+ delete hindsightObj.dynamicBankId;
897
+ }
898
+ if ("agentName" in hindsightObj) {
899
+ const agentName = hindsightObj.agentName;
900
+ if (
901
+ !("bankId" in hindsightObj) &&
902
+ typeof agentName === "string" &&
903
+ agentName.trim().length > 0 &&
904
+ agentName !== "omp"
905
+ ) {
906
+ hindsightObj.bankId = agentName;
907
+ }
908
+ delete hindsightObj.agentName;
909
+ }
910
+ }
911
+
912
+ // power.preventIdleSleep / power.preventSystemSleep / power.declareUserActive
913
+ // / power.preventDisplaySleep (four booleans) → power.sleepPrevention enum.
914
+ // The enum is cumulative: each level adds the flags of all lower levels.
915
+ // Migration picks the highest level whose condition is met, scanning from
916
+ // most to least aggressive so a single enum value captures the old state.
917
+ if (
918
+ !("sleepPrevention" in ((raw.power as Record<string, unknown>) ?? {})) &&
919
+ raw["power.sleepPrevention"] === undefined
920
+ ) {
921
+ const powerObj = raw.power as Record<string, unknown> | undefined;
922
+ const getFlag = (key: string): boolean | undefined => {
923
+ const nested = powerObj?.[key];
924
+ const flat = raw[`power.${key}`];
925
+ const value = nested ?? flat;
926
+ return typeof value === "boolean" ? value : undefined;
927
+ };
928
+ const idle = getFlag("preventIdleSleep");
929
+ const system = getFlag("preventSystemSleep");
930
+ const user = getFlag("declareUserActive");
931
+ const display = getFlag("preventDisplaySleep");
932
+ const anySet = idle !== undefined || system !== undefined || user !== undefined || display !== undefined;
933
+ if (anySet) {
934
+ const mode = system || user ? "system" : display ? "display" : idle !== false ? "idle" : "off";
935
+ const powerRoot = (powerObj ?? {}) as Record<string, unknown>;
936
+ powerRoot.sleepPrevention = mode;
937
+ raw.power = powerRoot;
938
+ }
939
+ // Clean up old keys (nested + flat)
940
+ if (powerObj) {
941
+ delete powerObj.preventIdleSleep;
942
+ delete powerObj.preventSystemSleep;
943
+ delete powerObj.declareUserActive;
944
+ delete powerObj.preventDisplaySleep;
945
+ }
946
+ delete raw["power.preventIdleSleep"];
947
+ delete raw["power.preventSystemSleep"];
948
+ delete raw["power.declareUserActive"];
949
+ delete raw["power.preventDisplaySleep"];
950
+ }
951
+
952
+ return raw;
953
+ }
954
+
955
+ /**
956
+ * One-time migration: seed the last-changelog-version marker file from the
957
+ * legacy config.yml key. An existing marker always wins — it is the newer
958
+ * source of truth.
959
+ */
960
+ async #seedLastChangelogVersionMarker(): Promise<void> {
961
+ const legacy = this.#legacyLastChangelogVersion;
962
+ if (!legacy) return;
963
+ const markerPath = getLastChangelogVersionPath(this.#agentDir);
964
+ try {
965
+ if ((await Bun.file(markerPath).text()).trim()) return;
966
+ } catch (error) {
967
+ if (!isEnoent(error)) return;
968
+ }
969
+ try {
970
+ await Bun.write(markerPath, legacy);
971
+ } catch (error) {
972
+ logger.warn("Settings: failed to seed last-changelog-version marker", { error: String(error) });
973
+ }
974
+ }
975
+
976
+ // ─────────────────────────────────────────────────────────────────────────
977
+ // Saving
978
+ // ─────────────────────────────────────────────────────────────────────────
979
+
980
+ #queueSave(): void {
981
+ if (!this.#persist || !this.#configPath) return;
982
+
983
+ // Debounce: wait 100ms for more changes
984
+ if (this.#saveTimer) {
985
+ clearTimeout(this.#saveTimer);
986
+ }
987
+ this.#saveTimer = setTimeout(() => {
988
+ this.#saveTimer = undefined;
989
+ this.#saveNow().catch(err => {
990
+ logger.warn("Settings: background save failed", { error: String(err) });
991
+ });
992
+ }, 100);
993
+ }
994
+
995
+ async #saveNow(): Promise<void> {
996
+ if (!this.#persist || !this.#configPath || this.#modified.size === 0) return;
997
+
998
+ const configPath = this.#configPath;
999
+ const modifiedPaths = [...this.#modified];
1000
+ this.#modified.clear();
1001
+
1002
+ try {
1003
+ await withFileLock(configPath, async () => {
1004
+ // Re-read to preserve external changes
1005
+ const current = await this.#loadYaml(configPath);
1006
+
1007
+ // Apply only our modified paths
1008
+ for (const modPath of modifiedPaths) {
1009
+ const segments = modPath.split(".");
1010
+ const value = getByPath(this.#global, segments);
1011
+ setByPath(current, segments, value);
1012
+ }
1013
+
1014
+ // Update our global with any external changes we preserved
1015
+ this.#global = current;
1016
+ await Bun.write(configPath, YAML.stringify(this.#global, null, 2));
1017
+ });
1018
+ } catch (error) {
1019
+ logger.warn("Settings: save failed", { error: String(error) });
1020
+ // Re-add failed paths for retry
1021
+ for (const p of modifiedPaths) {
1022
+ this.#modified.add(p);
1023
+ }
1024
+ }
1025
+
1026
+ this.#rebuildMerged();
1027
+ }
1028
+
1029
+ // ─────────────────────────────────────────────────────────────────────────
1030
+ // Utilities
1031
+ // ─────────────────────────────────────────────────────────────────────────
1032
+
1033
+ #rebuildMerged(): void {
1034
+ this.#merged = this.#deepMerge(this.#deepMerge({}, this.#global), this.#project);
1035
+ this.#merged = this.#deepMerge(this.#merged, this.#configOverlay);
1036
+ this.#merged = this.#deepMerge(this.#merged, this.#overrides);
1037
+ this.#resolvedCache.clear();
1038
+ }
1039
+
1040
+ #fireAllHooks(): void {
1041
+ for (const key of Object.keys(SETTING_HOOKS) as SettingPath[]) {
1042
+ const hook = SETTING_HOOKS[key];
1043
+ if (hook) {
1044
+ const value = this.get(key);
1045
+ hook(value, value);
1046
+ }
1047
+ }
1048
+ }
1049
+
1050
+ #deepMerge(base: RawSettings, overrides: RawSettings): RawSettings {
1051
+ const result = { ...base };
1052
+ for (const key of Object.keys(overrides)) {
1053
+ const override = overrides[key];
1054
+ const baseVal = base[key];
1055
+
1056
+ if (override === undefined) continue;
1057
+
1058
+ if (
1059
+ typeof override === "object" &&
1060
+ override !== null &&
1061
+ !Array.isArray(override) &&
1062
+ typeof baseVal === "object" &&
1063
+ baseVal !== null &&
1064
+ !Array.isArray(baseVal)
1065
+ ) {
1066
+ result[key] = this.#deepMerge(baseVal as RawSettings, override as RawSettings);
1067
+ } else {
1068
+ result[key] = override;
1069
+ }
1070
+ }
1071
+ return result;
1072
+ }
1073
+ }
1074
+
1075
+ // ═══════════════════════════════════════════════════════════════════════════
1076
+ // Setting Hooks
1077
+ // ═══════════════════════════════════════════════════════════════════════════
1078
+
1079
+ type SettingHook<P extends SettingPath> = (value: SettingValue<P>, prev: SettingValue<P>) => void;
1080
+
1081
+ /**
1082
+ * Minimal change-notification primitive backing the exported `on*Changed`
1083
+ * subscriptions. Holds a listener set, hands out unsubscribe closures, and
1084
+ * isolates errors so a single throwing listener can't abort the rest or bubble
1085
+ * out of `Settings.set()`.
1086
+ *
1087
+ * @typeParam A - argument tuple forwarded to each listener on `fire`.
1088
+ */
1089
+ class SettingSignal<A extends unknown[] = []> {
1090
+ #listeners = new Set<(...args: A) => void>();
1091
+
1092
+ constructor(private readonly label: string) {}
1093
+
1094
+ /** Subscribe `cb`; returns an unsubscribe function. */
1095
+ on(cb: (...args: A) => void): () => void {
1096
+ this.#listeners.add(cb);
1097
+ return () => {
1098
+ this.#listeners.delete(cb);
1099
+ };
1100
+ }
1101
+
1102
+ /**
1103
+ * Invoke every listener with `args`. Iterates a snapshot so a listener may
1104
+ * (un)subscribe mid-fire without re-entrancy — the Hindsight backend
1105
+ * re-registers the fresh state's listener on every rebuild — and wraps each
1106
+ * call so a throwing listener is logged and skipped instead of aborting the
1107
+ * rest.
1108
+ */
1109
+ fire(...args: A): void {
1110
+ for (const cb of [...this.#listeners]) {
1111
+ try {
1112
+ cb(...args);
1113
+ } catch (err) {
1114
+ logger.warn(`Settings: ${this.label} hook failed`, { error: String(err) });
1115
+ }
1116
+ }
1117
+ }
1118
+ }
1119
+
1120
+ const SETTING_HOOKS: Partial<Record<SettingPath, SettingHook<any>>> = {
1121
+ "theme.dark": value => {
1122
+ if (typeof value === "string") {
1123
+ setAutoThemeMapping("dark", value);
1124
+ }
1125
+ },
1126
+ "theme.light": value => {
1127
+ if (typeof value === "string") {
1128
+ setAutoThemeMapping("light", value);
1129
+ }
1130
+ },
1131
+ symbolPreset: value => {
1132
+ if (typeof value === "string" && (value === "unicode" || value === "nerd" || value === "ascii")) {
1133
+ setSymbolPreset(value).catch(err => {
1134
+ logger.warn("Settings: symbolPreset hook failed", { preset: value, error: String(err) });
1135
+ });
1136
+ }
1137
+ },
1138
+ colorBlindMode: value => {
1139
+ if (typeof value === "boolean") {
1140
+ setColorBlindMode(value).catch(err => {
1141
+ logger.warn("Settings: colorBlindMode hook failed", { enabled: value, error: String(err) });
1142
+ });
1143
+ }
1144
+ },
1145
+ "provider.appendOnlyContext": value => {
1146
+ if (typeof value === "string") {
1147
+ appendOnlyModeSignal.fire(value);
1148
+ }
1149
+ },
1150
+ "hindsight.bankId": () => hindsightScopeSignal.fire(),
1151
+ "hindsight.bankIdPrefix": () => hindsightScopeSignal.fire(),
1152
+ "hindsight.scoping": () => hindsightScopeSignal.fire(),
1153
+ };
1154
+ /** Fires when `provider.appendOnlyContext` changes at runtime. */
1155
+ const appendOnlyModeSignal = new SettingSignal<[value: string]>("provider.appendOnlyContext");
1156
+
1157
+ /**
1158
+ * Subscribe to append-only mode setting changes.
1159
+ * Returns an unsubscribe function. Multiple sessions (main + subagents)
1160
+ * can register independently without overwriting each other.
1161
+ */
1162
+ export const onAppendOnlyModeChanged = (cb: (value: string) => void) => appendOnlyModeSignal.on(cb);
1163
+
1164
+ /** Fires when `statusLine.sessionAccent` changes at runtime. */
1165
+ const statusLineSessionAccentSignal = new SettingSignal("statusLine.sessionAccent");
1166
+
1167
+ /**
1168
+ * Subscribe to session-accent setting changes.
1169
+ * Returns an unsubscribe function. Callers should re-read settings in the callback.
1170
+ */
1171
+ export const onStatusLineSessionAccentChanged = (cb: () => void) => statusLineSessionAccentSignal.on(cb);
1172
+
1173
+ /** Fires when any `hindsight.bankId` / `bankIdPrefix` / `scoping` value changes. */
1174
+ const hindsightScopeSignal = new SettingSignal("hindsight scope");
1175
+
1176
+ /**
1177
+ * Subscribe to changes in the Hindsight bank-scoping settings. Lets the
1178
+ * Hindsight backend rebuild the active `HindsightSessionState` when the
1179
+ * operator switches `hindsight.bankId`, `hindsight.bankIdPrefix`, or
1180
+ * `hindsight.scoping` mid-session so subsequent retain/recall calls land in
1181
+ * the new bank instead of the one selected at session start.
1182
+ *
1183
+ * Returns an unsubscribe function. The callback receives no arguments — the
1184
+ * caller is expected to re-read the relevant settings via `Settings.get`.
1185
+ */
1186
+ export const onHindsightScopeChanged = (cb: () => void) => hindsightScopeSignal.on(cb);
1187
+
1188
+ // ═══════════════════════════════════════════════════════════════════════════
1189
+ // Global Singleton
1190
+ // ═══════════════════════════════════════════════════════════════════════════
1191
+
1192
+ let globalInstance: Settings | null = null;
1193
+ let globalInstancePromise: Promise<Settings> | null = null;
1194
+ let boundSettingsInstance: Settings | null = null;
1195
+ let boundSettingsMethods = new Map<PropertyKey, unknown>();
1196
+
1197
+ function clearBoundSettingsMethods(): void {
1198
+ boundSettingsInstance = null;
1199
+ boundSettingsMethods = new Map<PropertyKey, unknown>();
1200
+ }
1201
+
1202
+ export function isSettingsInitialized(): boolean {
1203
+ return globalInstance !== null;
1204
+ }
1205
+
1206
+ /**
1207
+ * Reset the global singleton for testing.
1208
+ * @internal
1209
+ */
1210
+ export function resetSettingsForTest(): void {
1211
+ globalInstance = null;
1212
+ globalInstancePromise = null;
1213
+ clearBoundSettingsMethods();
1214
+ }
1215
+
1216
+ /**
1217
+ * The global settings singleton.
1218
+ * Must call `Settings.init()` before using.
1219
+ */
1220
+ export const settings = new Proxy({} as Settings, {
1221
+ get(_target, prop) {
1222
+ if (!globalInstance) {
1223
+ throw new Error("Settings not initialized. Call Settings.init() first.");
1224
+ }
1225
+ if (boundSettingsInstance !== globalInstance) {
1226
+ clearBoundSettingsMethods();
1227
+ boundSettingsInstance = globalInstance;
1228
+ }
1229
+ const value = (globalInstance as unknown as Record<PropertyKey, unknown>)[prop];
1230
+ if (typeof value === "function") {
1231
+ const cached = boundSettingsMethods.get(prop);
1232
+ if (cached) return cached;
1233
+ const bound = value.bind(globalInstance);
1234
+ boundSettingsMethods.set(prop, bound);
1235
+ return bound;
1236
+ }
1237
+ return value;
1238
+ },
1239
+ });
1240
+
1241
+ // ═══════════════════════════════════════════════════════════════════════════
1242
+ // Helpers
1243
+ // ═══════════════════════════════════════════════════════════════════════════