@sns-myagent/cli 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1320) hide show
  1. package/CHANGELOG.md +69 -0
  2. package/README.md +603 -0
  3. package/bin/snscoder.js +98 -0
  4. package/package.json +117 -0
  5. package/scripts/apply-pi-natives-patch.js +86 -0
  6. package/scripts/bench-guard.ts +71 -0
  7. package/scripts/build-binary.ts +108 -0
  8. package/scripts/bundle-dist.ts +117 -0
  9. package/scripts/cron-daily.sh +69 -0
  10. package/scripts/diagnose.sh +183 -0
  11. package/scripts/embed-mupdf-wasm.ts +67 -0
  12. package/scripts/fetch-binary.mjs +359 -0
  13. package/scripts/format-prompts.ts +68 -0
  14. package/scripts/generate-aria-snapshot.ts +134 -0
  15. package/scripts/generate-docs-index.ts +56 -0
  16. package/scripts/generate-share-viewer.ts +36 -0
  17. package/scripts/measure-prompt-tokens.ts +63 -0
  18. package/scripts/omp +42 -0
  19. package/scripts/omp.ts +19 -0
  20. package/scripts/pre-commit.sh +85 -0
  21. package/src/adapters/telegram/bot.ts +181 -0
  22. package/src/adapters/telegram/format.ts +215 -0
  23. package/src/adapters/telegram/handler.ts +128 -0
  24. package/src/adapters/telegram/index.ts +73 -0
  25. package/src/advisor/__tests__/advisor.test.ts +1133 -0
  26. package/src/advisor/advise-tool.ts +165 -0
  27. package/src/advisor/index.ts +4 -0
  28. package/src/advisor/runtime.ts +434 -0
  29. package/src/advisor/transcript-recorder.ts +136 -0
  30. package/src/advisor/watchdog.ts +83 -0
  31. package/src/async/index.ts +1 -0
  32. package/src/async/job-manager.ts +674 -0
  33. package/src/auto-thinking/classifier.ts +190 -0
  34. package/src/autolearn/controller.ts +139 -0
  35. package/src/autolearn/managed-skills.ts +255 -0
  36. package/src/autoresearch/command-resume.md +14 -0
  37. package/src/autoresearch/dashboard.ts +436 -0
  38. package/src/autoresearch/git.ts +331 -0
  39. package/src/autoresearch/helpers.ts +218 -0
  40. package/src/autoresearch/index.ts +536 -0
  41. package/src/autoresearch/prompt-setup.md +43 -0
  42. package/src/autoresearch/prompt.md +103 -0
  43. package/src/autoresearch/resume-message.md +10 -0
  44. package/src/autoresearch/state.ts +273 -0
  45. package/src/autoresearch/storage.ts +700 -0
  46. package/src/autoresearch/tools/init-experiment.ts +269 -0
  47. package/src/autoresearch/tools/log-experiment.ts +521 -0
  48. package/src/autoresearch/tools/run-experiment.ts +407 -0
  49. package/src/autoresearch/tools/update-notes.ts +109 -0
  50. package/src/autoresearch/types.ts +168 -0
  51. package/src/capability/context-file.ts +44 -0
  52. package/src/capability/extension-module.ts +34 -0
  53. package/src/capability/extension.ts +47 -0
  54. package/src/capability/fs.ts +117 -0
  55. package/src/capability/hook.ts +40 -0
  56. package/src/capability/index.ts +436 -0
  57. package/src/capability/instruction.ts +37 -0
  58. package/src/capability/mcp.ts +76 -0
  59. package/src/capability/prompt.ts +35 -0
  60. package/src/capability/rule-buckets.ts +66 -0
  61. package/src/capability/rule.ts +261 -0
  62. package/src/capability/settings.ts +34 -0
  63. package/src/capability/skill.ts +63 -0
  64. package/src/capability/slash-command.ts +40 -0
  65. package/src/capability/ssh.ts +41 -0
  66. package/src/capability/system-prompt.ts +34 -0
  67. package/src/capability/tool.ts +38 -0
  68. package/src/capability/types.ts +168 -0
  69. package/src/cli/agents-cli.ts +138 -0
  70. package/src/cli/args.ts +360 -0
  71. package/src/cli/auth-broker-cli.ts +893 -0
  72. package/src/cli/auth-gateway-cli.ts +608 -0
  73. package/src/cli/bench-cli.ts +552 -0
  74. package/src/cli/classify-install-target.ts +76 -0
  75. package/src/cli/claude-trace-cli.ts +795 -0
  76. package/src/cli/commands/init-xdg.ts +27 -0
  77. package/src/cli/completion-gen.ts +550 -0
  78. package/src/cli/config-cli.ts +418 -0
  79. package/src/cli/dry-balance-cli.ts +858 -0
  80. package/src/cli/entry.ts +40 -0
  81. package/src/cli/extension-flags.ts +48 -0
  82. package/src/cli/file-processor.ts +133 -0
  83. package/src/cli/flag-tables.ts +322 -0
  84. package/src/cli/gallery-cli.ts +231 -0
  85. package/src/cli/gallery-fixtures/agentic.ts +407 -0
  86. package/src/cli/gallery-fixtures/codeintel.ts +187 -0
  87. package/src/cli/gallery-fixtures/edit.ts +194 -0
  88. package/src/cli/gallery-fixtures/fs.ts +220 -0
  89. package/src/cli/gallery-fixtures/index.ts +40 -0
  90. package/src/cli/gallery-fixtures/interaction.ts +49 -0
  91. package/src/cli/gallery-fixtures/memory.ts +81 -0
  92. package/src/cli/gallery-fixtures/misc.ts +250 -0
  93. package/src/cli/gallery-fixtures/search.ts +213 -0
  94. package/src/cli/gallery-fixtures/shell.ts +167 -0
  95. package/src/cli/gallery-fixtures/types.ts +57 -0
  96. package/src/cli/gallery-fixtures/web.ts +158 -0
  97. package/src/cli/gallery-screenshot.ts +279 -0
  98. package/src/cli/grep-cli.ts +160 -0
  99. package/src/cli/grievances-cli.ts +256 -0
  100. package/src/cli/index.ts +416 -0
  101. package/src/cli/initial-message.ts +58 -0
  102. package/src/cli/models-cli.ts +427 -0
  103. package/src/cli/plugin-cli.ts +996 -0
  104. package/src/cli/profile-alias.ts +338 -0
  105. package/src/cli/profile-bootstrap.ts +233 -0
  106. package/src/cli/read-cli.ts +57 -0
  107. package/src/cli/session-picker.ts +79 -0
  108. package/src/cli/setup-cli.ts +332 -0
  109. package/src/cli/setup-model-picker.ts +43 -0
  110. package/src/cli/shell-cli.ts +176 -0
  111. package/src/cli/ssh-cli.ts +179 -0
  112. package/src/cli/startup-cwd.ts +58 -0
  113. package/src/cli/stats-cli.ts +229 -0
  114. package/src/cli/tiny-models-cli.ts +132 -0
  115. package/src/cli/ttsr-cli.ts +995 -0
  116. package/src/cli/update-cli.ts +671 -0
  117. package/src/cli/usage-cli.ts +774 -0
  118. package/src/cli/web-search-cli.ts +132 -0
  119. package/src/cli/worktree-cli.ts +291 -0
  120. package/src/cli-commands.ts +131 -0
  121. package/src/cli.ts +326 -0
  122. package/src/collab/crypto.ts +63 -0
  123. package/src/collab/guest.ts +602 -0
  124. package/src/collab/host.ts +619 -0
  125. package/src/collab/protocol.ts +289 -0
  126. package/src/collab/relay-client.ts +216 -0
  127. package/src/commands/acp.ts +24 -0
  128. package/src/commands/agents.ts +57 -0
  129. package/src/commands/auth-broker.ts +99 -0
  130. package/src/commands/auth-gateway.ts +69 -0
  131. package/src/commands/bench.ts +42 -0
  132. package/src/commands/chat.ts +24 -0
  133. package/src/commands/commit.ts +46 -0
  134. package/src/commands/complete.ts +66 -0
  135. package/src/commands/completions.ts +60 -0
  136. package/src/commands/config.ts +51 -0
  137. package/src/commands/dry-balance.ts +43 -0
  138. package/src/commands/gallery.ts +52 -0
  139. package/src/commands/grep.ts +48 -0
  140. package/src/commands/grievances.ts +51 -0
  141. package/src/commands/install.ts +107 -0
  142. package/src/commands/join.ts +39 -0
  143. package/src/commands/launch.ts +182 -0
  144. package/src/commands/models.ts +61 -0
  145. package/src/commands/plugin.ts +78 -0
  146. package/src/commands/read.ts +38 -0
  147. package/src/commands/say.ts +102 -0
  148. package/src/commands/setup.ts +67 -0
  149. package/src/commands/shell.ts +29 -0
  150. package/src/commands/ssh.ts +60 -0
  151. package/src/commands/stats.ts +29 -0
  152. package/src/commands/tiny-models.ts +36 -0
  153. package/src/commands/token.ts +108 -0
  154. package/src/commands/ttsr.ts +125 -0
  155. package/src/commands/update.ts +21 -0
  156. package/src/commands/usage.ts +43 -0
  157. package/src/commands/web-search.ts +42 -0
  158. package/src/commands/worktree.ts +56 -0
  159. package/src/commit/agentic/agent.ts +318 -0
  160. package/src/commit/agentic/fallback.ts +96 -0
  161. package/src/commit/agentic/index.ts +355 -0
  162. package/src/commit/agentic/prompts/analyze-file.md +22 -0
  163. package/src/commit/agentic/prompts/session-user.md +25 -0
  164. package/src/commit/agentic/prompts/split-confirm.md +1 -0
  165. package/src/commit/agentic/prompts/system.md +38 -0
  166. package/src/commit/agentic/state.ts +60 -0
  167. package/src/commit/agentic/tools/analyze-file.ts +149 -0
  168. package/src/commit/agentic/tools/git-file-diff.ts +191 -0
  169. package/src/commit/agentic/tools/git-hunk.ts +52 -0
  170. package/src/commit/agentic/tools/git-overview.ts +81 -0
  171. package/src/commit/agentic/tools/index.ts +54 -0
  172. package/src/commit/agentic/tools/propose-changelog.ts +147 -0
  173. package/src/commit/agentic/tools/propose-commit.ts +109 -0
  174. package/src/commit/agentic/tools/recent-commits.ts +81 -0
  175. package/src/commit/agentic/tools/schemas.ts +11 -0
  176. package/src/commit/agentic/tools/split-commit.ts +241 -0
  177. package/src/commit/agentic/topo-sort.ts +44 -0
  178. package/src/commit/agentic/trivial.ts +51 -0
  179. package/src/commit/agentic/validation.ts +183 -0
  180. package/src/commit/analysis/conventional.ts +64 -0
  181. package/src/commit/analysis/index.ts +4 -0
  182. package/src/commit/analysis/scope.ts +242 -0
  183. package/src/commit/analysis/summary.ts +107 -0
  184. package/src/commit/analysis/validation.ts +66 -0
  185. package/src/commit/changelog/detect.ts +40 -0
  186. package/src/commit/changelog/generate.ts +101 -0
  187. package/src/commit/changelog/index.ts +234 -0
  188. package/src/commit/changelog/parse.ts +44 -0
  189. package/src/commit/cli.ts +85 -0
  190. package/src/commit/git/diff.ts +148 -0
  191. package/src/commit/index.ts +5 -0
  192. package/src/commit/map-reduce/index.ts +69 -0
  193. package/src/commit/map-reduce/map-phase.ts +193 -0
  194. package/src/commit/map-reduce/reduce-phase.ts +49 -0
  195. package/src/commit/map-reduce/utils.ts +9 -0
  196. package/src/commit/message.ts +11 -0
  197. package/src/commit/model-selection.ts +89 -0
  198. package/src/commit/pipeline.ts +243 -0
  199. package/src/commit/prompts/analysis-system.md +148 -0
  200. package/src/commit/prompts/analysis-user.md +38 -0
  201. package/src/commit/prompts/changelog-system.md +50 -0
  202. package/src/commit/prompts/changelog-user.md +18 -0
  203. package/src/commit/prompts/file-observer-system.md +24 -0
  204. package/src/commit/prompts/file-observer-user.md +8 -0
  205. package/src/commit/prompts/reduce-system.md +50 -0
  206. package/src/commit/prompts/reduce-user.md +17 -0
  207. package/src/commit/prompts/summary-retry.md +3 -0
  208. package/src/commit/prompts/summary-system.md +38 -0
  209. package/src/commit/prompts/summary-user.md +13 -0
  210. package/src/commit/prompts/types-description.md +2 -0
  211. package/src/commit/shared-llm.ts +70 -0
  212. package/src/commit/types.ts +118 -0
  213. package/src/commit/utils/exclusions.ts +42 -0
  214. package/src/commit/utils.ts +58 -0
  215. package/src/config/api-key-resolver.ts +67 -0
  216. package/src/config/append-only-context-mode.ts +76 -0
  217. package/src/config/config-file.ts +315 -0
  218. package/src/config/defaults.ts +55 -0
  219. package/src/config/file-lock.ts +164 -0
  220. package/src/config/index.ts +105 -0
  221. package/src/config/keybindings.ts +634 -0
  222. package/src/config/loader.ts +93 -0
  223. package/src/config/mcp-schema.json +238 -0
  224. package/src/config/model-discovery.ts +589 -0
  225. package/src/config/model-registry.ts +2267 -0
  226. package/src/config/model-resolver.ts +1819 -0
  227. package/src/config/model-roles.ts +99 -0
  228. package/src/config/models-config-schema.ts +266 -0
  229. package/src/config/models-config.ts +131 -0
  230. package/src/config/prompt-templates.ts +185 -0
  231. package/src/config/resolve-config-value.ts +94 -0
  232. package/src/config/schema.ts +139 -0
  233. package/src/config/settings-schema.ts +4903 -0
  234. package/src/config/settings.ts +1248 -0
  235. package/src/config/sns-config.ts +126 -0
  236. package/src/config.ts +242 -0
  237. package/src/cron/__tests__/cron-parser.test.ts +147 -0
  238. package/src/cron/cron-parser.ts +228 -0
  239. package/src/cron/cron-scheduler.ts +260 -0
  240. package/src/cron/cron-store.ts +275 -0
  241. package/src/cron/index.ts +21 -0
  242. package/src/cron/types.ts +65 -0
  243. package/src/cursor.ts +340 -0
  244. package/src/dap/client.ts +666 -0
  245. package/src/dap/config.ts +189 -0
  246. package/src/dap/defaults.json +212 -0
  247. package/src/dap/index.ts +4 -0
  248. package/src/dap/session.ts +1441 -0
  249. package/src/dap/types.ts +610 -0
  250. package/src/debug/index.ts +559 -0
  251. package/src/debug/log-formatting.ts +58 -0
  252. package/src/debug/log-viewer.ts +908 -0
  253. package/src/debug/profiler.ts +162 -0
  254. package/src/debug/protocol-probe.ts +267 -0
  255. package/src/debug/raw-sse-buffer.ts +294 -0
  256. package/src/debug/raw-sse.ts +292 -0
  257. package/src/debug/remote-debugger.ts +151 -0
  258. package/src/debug/report-bundle.ts +375 -0
  259. package/src/debug/system-info.ts +111 -0
  260. package/src/debug/terminal-info.ts +124 -0
  261. package/src/discovery/agents-md.ts +67 -0
  262. package/src/discovery/agents.ts +230 -0
  263. package/src/discovery/at-imports.ts +273 -0
  264. package/src/discovery/builtin-defaults.ts +39 -0
  265. package/src/discovery/builtin-rules/index.ts +56 -0
  266. package/src/discovery/builtin-rules/rs-box-leak.md +48 -0
  267. package/src/discovery/builtin-rules/rs-future-prelude.md +23 -0
  268. package/src/discovery/builtin-rules/rs-lazylock.md +51 -0
  269. package/src/discovery/builtin-rules/rs-match-ergonomics.md +67 -0
  270. package/src/discovery/builtin-rules/rs-parking-lot.md +44 -0
  271. package/src/discovery/builtin-rules/rs-result-type.md +19 -0
  272. package/src/discovery/builtin-rules/ts-bare-catch.md +38 -0
  273. package/src/discovery/builtin-rules/ts-import-type.md +42 -0
  274. package/src/discovery/builtin-rules/ts-no-any.md +65 -0
  275. package/src/discovery/builtin-rules/ts-no-deprecated-leftovers.md +44 -0
  276. package/src/discovery/builtin-rules/ts-no-dynamic-import.md +39 -0
  277. package/src/discovery/builtin-rules/ts-no-inline-cast-access.md +55 -0
  278. package/src/discovery/builtin-rules/ts-no-return-type.md +44 -0
  279. package/src/discovery/builtin-rules/ts-no-test-timers.md +55 -0
  280. package/src/discovery/builtin-rules/ts-no-tiny-functions.md +51 -0
  281. package/src/discovery/builtin-rules/ts-promise-with-resolvers.md +65 -0
  282. package/src/discovery/builtin-rules/ts-redundant-clear-guard.md +75 -0
  283. package/src/discovery/builtin-rules/ts-set-map.md +28 -0
  284. package/src/discovery/builtin.ts +934 -0
  285. package/src/discovery/claude-plugins.ts +386 -0
  286. package/src/discovery/claude.ts +584 -0
  287. package/src/discovery/cline.ts +83 -0
  288. package/src/discovery/codex.ts +522 -0
  289. package/src/discovery/cursor.ts +220 -0
  290. package/src/discovery/gemini.ts +383 -0
  291. package/src/discovery/github.ts +337 -0
  292. package/src/discovery/helpers.ts +1092 -0
  293. package/src/discovery/index.ts +81 -0
  294. package/src/discovery/mcp-json.ts +172 -0
  295. package/src/discovery/omp-extension-roots.ts +190 -0
  296. package/src/discovery/omp-plugins.ts +383 -0
  297. package/src/discovery/opencode.ts +441 -0
  298. package/src/discovery/plugin-dir-roots.ts +28 -0
  299. package/src/discovery/ssh.ts +153 -0
  300. package/src/discovery/substitute-plugin-root.ts +29 -0
  301. package/src/discovery/vscode.ts +105 -0
  302. package/src/discovery/windsurf.ts +147 -0
  303. package/src/edit/apply-patch/index.ts +87 -0
  304. package/src/edit/apply-patch/parser.ts +174 -0
  305. package/src/edit/diff.ts +999 -0
  306. package/src/edit/file-snapshot-store.ts +143 -0
  307. package/src/edit/hashline/block-resolver.ts +33 -0
  308. package/src/edit/hashline/diff.ts +290 -0
  309. package/src/edit/hashline/execute.ts +237 -0
  310. package/src/edit/hashline/filesystem.ts +138 -0
  311. package/src/edit/hashline/index.ts +5 -0
  312. package/src/edit/hashline/noop-loop-guard.ts +99 -0
  313. package/src/edit/hashline/params.ts +19 -0
  314. package/src/edit/index.ts +620 -0
  315. package/src/edit/modes/apply-patch.lark +19 -0
  316. package/src/edit/modes/apply-patch.ts +53 -0
  317. package/src/edit/modes/patch.ts +1904 -0
  318. package/src/edit/modes/replace.ts +1136 -0
  319. package/src/edit/normalize.ts +345 -0
  320. package/src/edit/notebook.ts +242 -0
  321. package/src/edit/read-file.ts +25 -0
  322. package/src/edit/renderer.ts +819 -0
  323. package/src/edit/streaming.ts +517 -0
  324. package/src/eval/__tests__/agent-bridge.test.ts +769 -0
  325. package/src/eval/__tests__/bridge-timeout.test.ts +64 -0
  326. package/src/eval/__tests__/budget-bridge.test.ts +69 -0
  327. package/src/eval/__tests__/completion-bridge.test.ts +412 -0
  328. package/src/eval/__tests__/helpers-local-roots.test.ts +58 -0
  329. package/src/eval/__tests__/idle-timeout.test.ts +80 -0
  330. package/src/eval/__tests__/js-context-manager.test.ts +291 -0
  331. package/src/eval/__tests__/julia-prelude.test.ts +77 -0
  332. package/src/eval/__tests__/kernel-spawn.test.ts +103 -0
  333. package/src/eval/__tests__/prelude-agent.test.ts +73 -0
  334. package/src/eval/agent-bridge.ts +319 -0
  335. package/src/eval/backend-helpers.ts +48 -0
  336. package/src/eval/backend.ts +71 -0
  337. package/src/eval/bridge-timeout.ts +44 -0
  338. package/src/eval/budget-bridge.ts +48 -0
  339. package/src/eval/completion-bridge.ts +211 -0
  340. package/src/eval/concurrency-bridge.ts +34 -0
  341. package/src/eval/executor-base.ts +425 -0
  342. package/src/eval/idle-timeout.ts +91 -0
  343. package/src/eval/index.ts +6 -0
  344. package/src/eval/jl/executor.ts +540 -0
  345. package/src/eval/jl/index.ts +54 -0
  346. package/src/eval/jl/kernel.ts +235 -0
  347. package/src/eval/jl/prelude.jl +930 -0
  348. package/src/eval/jl/prelude.ts +3 -0
  349. package/src/eval/jl/runner.jl +634 -0
  350. package/src/eval/jl/runtime.ts +118 -0
  351. package/src/eval/js/context-manager.ts +621 -0
  352. package/src/eval/js/executor.ts +173 -0
  353. package/src/eval/js/index.ts +40 -0
  354. package/src/eval/js/shared/helpers.ts +283 -0
  355. package/src/eval/js/shared/indirect-eval.ts +30 -0
  356. package/src/eval/js/shared/local-module-loader.ts +342 -0
  357. package/src/eval/js/shared/prelude.ts +2 -0
  358. package/src/eval/js/shared/prelude.txt +307 -0
  359. package/src/eval/js/shared/rewrite-imports.ts +532 -0
  360. package/src/eval/js/shared/runtime.ts +580 -0
  361. package/src/eval/js/shared/types.ts +18 -0
  362. package/src/eval/js/tool-bridge.ts +163 -0
  363. package/src/eval/js/worker-core.ts +151 -0
  364. package/src/eval/js/worker-entry.ts +37 -0
  365. package/src/eval/js/worker-protocol.ts +47 -0
  366. package/src/eval/kernel-base.ts +569 -0
  367. package/src/eval/py/__tests__/prelude.test.ts +19 -0
  368. package/src/eval/py/display.ts +71 -0
  369. package/src/eval/py/executor.ts +533 -0
  370. package/src/eval/py/index.ts +57 -0
  371. package/src/eval/py/kernel.ts +233 -0
  372. package/src/eval/py/prelude.py +683 -0
  373. package/src/eval/py/prelude.ts +3 -0
  374. package/src/eval/py/runner.py +1177 -0
  375. package/src/eval/py/runtime.ts +276 -0
  376. package/src/eval/py/spawn-options.ts +126 -0
  377. package/src/eval/py/tool-bridge.ts +182 -0
  378. package/src/eval/rb/executor.ts +504 -0
  379. package/src/eval/rb/index.ts +54 -0
  380. package/src/eval/rb/kernel.ts +230 -0
  381. package/src/eval/rb/prelude.rb +721 -0
  382. package/src/eval/rb/prelude.ts +3 -0
  383. package/src/eval/rb/runner.rb +474 -0
  384. package/src/eval/rb/runtime.ts +132 -0
  385. package/src/eval/runtime-env.ts +104 -0
  386. package/src/eval/session-id.ts +8 -0
  387. package/src/eval/types.ts +48 -0
  388. package/src/exa/index.ts +2 -0
  389. package/src/exa/mcp-client.ts +370 -0
  390. package/src/exa/types.ts +69 -0
  391. package/src/exec/bash-executor.ts +478 -0
  392. package/src/exec/exec.ts +53 -0
  393. package/src/exec/non-interactive-env.ts +119 -0
  394. package/src/export/custom-share.ts +65 -0
  395. package/src/export/html/index.ts +308 -0
  396. package/src/export/html/share-loader.js +102 -0
  397. package/src/export/html/template.css +1337 -0
  398. package/src/export/html/template.html +49 -0
  399. package/src/export/html/template.js +1626 -0
  400. package/src/export/html/tool-views.generated.js +37 -0
  401. package/src/export/html/vendor/highlight.min.js +1213 -0
  402. package/src/export/html/vendor/marked.min.js +6 -0
  403. package/src/export/html/web-palette.ts +142 -0
  404. package/src/export/share.ts +481 -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 +982 -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 +244 -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 +73 -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/session-handler-types.ts +21 -0
  449. package/src/extensibility/shared-events.ts +367 -0
  450. package/src/extensibility/skills.ts +408 -0
  451. package/src/extensibility/slash-commands.ts +131 -0
  452. package/src/extensibility/tool-proxy.ts +28 -0
  453. package/src/extensibility/typebox.ts +945 -0
  454. package/src/extensibility/utils.ts +44 -0
  455. package/src/global.d.ts +57 -0
  456. package/src/goals/guided-setup.ts +142 -0
  457. package/src/goals/index.ts +3 -0
  458. package/src/goals/runtime.ts +521 -0
  459. package/src/goals/state.ts +37 -0
  460. package/src/goals/tools/goal-tool.ts +251 -0
  461. package/src/hindsight/backend.ts +354 -0
  462. package/src/hindsight/bank.ts +156 -0
  463. package/src/hindsight/client.ts +623 -0
  464. package/src/hindsight/config.ts +175 -0
  465. package/src/hindsight/content.ts +226 -0
  466. package/src/hindsight/index.ts +8 -0
  467. package/src/hindsight/mental-models.ts +429 -0
  468. package/src/hindsight/seeds.json +32 -0
  469. package/src/hindsight/state.ts +492 -0
  470. package/src/hindsight/transcript.ts +71 -0
  471. package/src/index.ts +66 -0
  472. package/src/internal-urls/agent-protocol.ts +146 -0
  473. package/src/internal-urls/artifact-protocol.ts +107 -0
  474. package/src/internal-urls/docs-index.generated.txt +2 -0
  475. package/src/internal-urls/docs-index.ts +102 -0
  476. package/src/internal-urls/filesystem-resource.ts +34 -0
  477. package/src/internal-urls/history-protocol.ts +118 -0
  478. package/src/internal-urls/index.ts +25 -0
  479. package/src/internal-urls/issue-pr-protocol.ts +594 -0
  480. package/src/internal-urls/json-query.ts +126 -0
  481. package/src/internal-urls/local-protocol.ts +315 -0
  482. package/src/internal-urls/mcp-protocol.ts +151 -0
  483. package/src/internal-urls/memory-protocol.ts +173 -0
  484. package/src/internal-urls/omp-protocol.ts +94 -0
  485. package/src/internal-urls/parse.ts +72 -0
  486. package/src/internal-urls/registry-helpers.ts +25 -0
  487. package/src/internal-urls/router.ts +105 -0
  488. package/src/internal-urls/rule-protocol.ts +45 -0
  489. package/src/internal-urls/skill-protocol.ts +112 -0
  490. package/src/internal-urls/types.ts +152 -0
  491. package/src/internal-urls/vault-protocol.ts +939 -0
  492. package/src/irc/bus.ts +311 -0
  493. package/src/jsonrpc/message-framing.ts +142 -0
  494. package/src/lib/xai-http.ts +124 -0
  495. package/src/lsp/client.ts +1135 -0
  496. package/src/lsp/clients/biome-client.ts +264 -0
  497. package/src/lsp/clients/index.ts +50 -0
  498. package/src/lsp/clients/lsp-linter-client.ts +85 -0
  499. package/src/lsp/clients/swiftlint-client.ts +120 -0
  500. package/src/lsp/config.ts +502 -0
  501. package/src/lsp/defaults.json +499 -0
  502. package/src/lsp/diagnostics-ledger.ts +51 -0
  503. package/src/lsp/edits.ts +267 -0
  504. package/src/lsp/format-options.ts +119 -0
  505. package/src/lsp/index.ts +2480 -0
  506. package/src/lsp/lspmux.ts +233 -0
  507. package/src/lsp/render.ts +668 -0
  508. package/src/lsp/startup-events.ts +13 -0
  509. package/src/lsp/types.ts +444 -0
  510. package/src/lsp/utils.ts +718 -0
  511. package/src/main.ts +1429 -0
  512. package/src/markit/NOTICE +32 -0
  513. package/src/markit/converters/docx.ts +56 -0
  514. package/src/markit/converters/epub.ts +136 -0
  515. package/src/markit/converters/mammoth.d.ts +24 -0
  516. package/src/markit/converters/pdf/columns.ts +103 -0
  517. package/src/markit/converters/pdf/extract.ts +574 -0
  518. package/src/markit/converters/pdf/grid.ts +780 -0
  519. package/src/markit/converters/pdf/headers.ts +106 -0
  520. package/src/markit/converters/pdf/index.ts +146 -0
  521. package/src/markit/converters/pdf/render.ts +501 -0
  522. package/src/markit/converters/pdf/types.ts +84 -0
  523. package/src/markit/converters/pptx.ts +325 -0
  524. package/src/markit/converters/xlsx.ts +173 -0
  525. package/src/markit/index.ts +2 -0
  526. package/src/markit/registry.ts +59 -0
  527. package/src/markit/types.ts +35 -0
  528. package/src/mcp/client.ts +509 -0
  529. package/src/mcp/config-writer.ts +229 -0
  530. package/src/mcp/config.ts +365 -0
  531. package/src/mcp/index.ts +29 -0
  532. package/src/mcp/json-rpc.ts +122 -0
  533. package/src/mcp/loader.ts +125 -0
  534. package/src/mcp/manager.ts +1346 -0
  535. package/src/mcp/oauth-credentials.ts +104 -0
  536. package/src/mcp/oauth-discovery.ts +467 -0
  537. package/src/mcp/oauth-flow.ts +555 -0
  538. package/src/mcp/render.ts +155 -0
  539. package/src/mcp/smithery-auth.ts +104 -0
  540. package/src/mcp/smithery-connect.ts +145 -0
  541. package/src/mcp/smithery-registry.ts +477 -0
  542. package/src/mcp/startup-events.ts +116 -0
  543. package/src/mcp/timeout.ts +59 -0
  544. package/src/mcp/tool-bridge.ts +429 -0
  545. package/src/mcp/tool-cache.ts +117 -0
  546. package/src/mcp/transports/http.ts +519 -0
  547. package/src/mcp/transports/index.ts +6 -0
  548. package/src/mcp/transports/stdio.ts +622 -0
  549. package/src/mcp/types.ts +427 -0
  550. package/src/memories/index.ts +1281 -0
  551. package/src/memories/storage.ts +578 -0
  552. package/src/memory-backend/index.ts +18 -0
  553. package/src/memory-backend/lcm-backend.ts +385 -0
  554. package/src/memory-backend/local-backend.ts +45 -0
  555. package/src/memory-backend/mem0-backend.ts +326 -0
  556. package/src/memory-backend/mnemosyne-backend.ts +462 -0
  557. package/src/memory-backend/off-backend.ts +25 -0
  558. package/src/memory-backend/resolve.ts +28 -0
  559. package/src/memory-backend/runtime.ts +66 -0
  560. package/src/memory-backend/types.ts +166 -0
  561. package/src/mnemopi/backend.ts +612 -0
  562. package/src/mnemopi/config.ts +267 -0
  563. package/src/mnemopi/embed-client.ts +246 -0
  564. package/src/mnemopi/embed-protocol.ts +35 -0
  565. package/src/mnemopi/embed-worker.ts +113 -0
  566. package/src/mnemopi/index.ts +3 -0
  567. package/src/mnemopi/state.ts +659 -0
  568. package/src/modes/acp/acp-agent.ts +2362 -0
  569. package/src/modes/acp/acp-client-bridge.ts +154 -0
  570. package/src/modes/acp/acp-event-mapper.ts +933 -0
  571. package/src/modes/acp/acp-mode.ts +23 -0
  572. package/src/modes/acp/index.ts +2 -0
  573. package/src/modes/acp/terminal-auth.ts +37 -0
  574. package/src/modes/components/__tests__/skill-message.test.ts +92 -0
  575. package/src/modes/components/advisor-message.ts +99 -0
  576. package/src/modes/components/agent-dashboard.ts +1183 -0
  577. package/src/modes/components/agent-hub.ts +570 -0
  578. package/src/modes/components/agent-transcript-viewer.ts +463 -0
  579. package/src/modes/components/assistant-message.ts +811 -0
  580. package/src/modes/components/background-tan-message.ts +36 -0
  581. package/src/modes/components/bash-execution.ts +220 -0
  582. package/src/modes/components/bordered-loader.ts +41 -0
  583. package/src/modes/components/btw-panel.ts +124 -0
  584. package/src/modes/components/cache-invalidation-marker.ts +110 -0
  585. package/src/modes/components/chat-block.ts +111 -0
  586. package/src/modes/components/chat-transcript-builder.ts +398 -0
  587. package/src/modes/components/collab-prompt-message.ts +32 -0
  588. package/src/modes/components/compaction-summary-message.ts +215 -0
  589. package/src/modes/components/copy-selector.ts +206 -0
  590. package/src/modes/components/countdown-timer.ts +75 -0
  591. package/src/modes/components/custom-editor.test.ts +164 -0
  592. package/src/modes/components/custom-editor.ts +648 -0
  593. package/src/modes/components/custom-message.ts +67 -0
  594. package/src/modes/components/diff.ts +254 -0
  595. package/src/modes/components/dynamic-border.ts +34 -0
  596. package/src/modes/components/error-banner.ts +33 -0
  597. package/src/modes/components/eval-execution.ts +158 -0
  598. package/src/modes/components/execution-shared.ts +101 -0
  599. package/src/modes/components/extensions/extension-dashboard.ts +390 -0
  600. package/src/modes/components/extensions/extension-list.ts +474 -0
  601. package/src/modes/components/extensions/index.ts +9 -0
  602. package/src/modes/components/extensions/inspector-panel.ts +321 -0
  603. package/src/modes/components/extensions/state-manager.ts +627 -0
  604. package/src/modes/components/extensions/types.ts +186 -0
  605. package/src/modes/components/footer.ts +276 -0
  606. package/src/modes/components/history-search.ts +268 -0
  607. package/src/modes/components/hook-editor.ts +170 -0
  608. package/src/modes/components/hook-input.ts +87 -0
  609. package/src/modes/components/hook-message.ts +67 -0
  610. package/src/modes/components/hook-selector.ts +659 -0
  611. package/src/modes/components/index.ts +38 -0
  612. package/src/modes/components/keybinding-hints.ts +65 -0
  613. package/src/modes/components/late-diagnostics-message.ts +60 -0
  614. package/src/modes/components/login-dialog.ts +164 -0
  615. package/src/modes/components/logout-account-selector.ts +130 -0
  616. package/src/modes/components/mcp-add-wizard.ts +1360 -0
  617. package/src/modes/components/message-frame.ts +92 -0
  618. package/src/modes/components/model-selector.ts +1378 -0
  619. package/src/modes/components/oauth-selector.ts +457 -0
  620. package/src/modes/components/omfg-panel.ts +141 -0
  621. package/src/modes/components/overlay-box.ts +109 -0
  622. package/src/modes/components/plan-review-overlay.ts +847 -0
  623. package/src/modes/components/plan-toc.ts +138 -0
  624. package/src/modes/components/plugin-selector.ts +95 -0
  625. package/src/modes/components/plugin-settings.ts +739 -0
  626. package/src/modes/components/queue-mode-selector.ts +56 -0
  627. package/src/modes/components/read-tool-group.ts +676 -0
  628. package/src/modes/components/reset-usage-selector.ts +161 -0
  629. package/src/modes/components/segment-track.ts +89 -0
  630. package/src/modes/components/selector-helpers.ts +129 -0
  631. package/src/modes/components/session-selector.ts +629 -0
  632. package/src/modes/components/settings-defs.ts +225 -0
  633. package/src/modes/components/settings-selector.ts +1097 -0
  634. package/src/modes/components/show-images-selector.ts +45 -0
  635. package/src/modes/components/skill-message.ts +110 -0
  636. package/src/modes/components/snapcompact-shape-preview-doc.md +18 -0
  637. package/src/modes/components/snapcompact-shape-preview.ts +192 -0
  638. package/src/modes/components/status-line/component.ts +1005 -0
  639. package/src/modes/components/status-line/context-thresholds.ts +86 -0
  640. package/src/modes/components/status-line/git-utils.ts +42 -0
  641. package/src/modes/components/status-line/index.ts +5 -0
  642. package/src/modes/components/status-line/presets.ts +106 -0
  643. package/src/modes/components/status-line/segments.ts +616 -0
  644. package/src/modes/components/status-line/separators.ts +55 -0
  645. package/src/modes/components/status-line/token-rate.ts +66 -0
  646. package/src/modes/components/status-line/types.ts +125 -0
  647. package/src/modes/components/theme-selector.ts +63 -0
  648. package/src/modes/components/thinking-selector.ts +52 -0
  649. package/src/modes/components/tiny-title-download-progress.ts +90 -0
  650. package/src/modes/components/tips.txt +24 -0
  651. package/src/modes/components/todo-reminder.ts +39 -0
  652. package/src/modes/components/tool-execution.ts +1173 -0
  653. package/src/modes/components/transcript-container.ts +806 -0
  654. package/src/modes/components/tree-selector.ts +989 -0
  655. package/src/modes/components/ttsr-notification.ts +123 -0
  656. package/src/modes/components/usage-row.ts +18 -0
  657. package/src/modes/components/user-message-selector.ts +227 -0
  658. package/src/modes/components/user-message.ts +68 -0
  659. package/src/modes/components/visual-truncate.ts +63 -0
  660. package/src/modes/components/welcome.ts +581 -0
  661. package/src/modes/controllers/btw-controller.ts +198 -0
  662. package/src/modes/controllers/command-controller-shared.ts +109 -0
  663. package/src/modes/controllers/command-controller.ts +1669 -0
  664. package/src/modes/controllers/event-controller.ts +1191 -0
  665. package/src/modes/controllers/extension-ui-controller.ts +897 -0
  666. package/src/modes/controllers/input-controller.ts +1627 -0
  667. package/src/modes/controllers/mcp-command-controller.ts +2190 -0
  668. package/src/modes/controllers/omfg-controller.ts +283 -0
  669. package/src/modes/controllers/omfg-rule.ts +647 -0
  670. package/src/modes/controllers/selector-controller.ts +1293 -0
  671. package/src/modes/controllers/session-focus-controller.ts +112 -0
  672. package/src/modes/controllers/ssh-command-controller.ts +384 -0
  673. package/src/modes/controllers/streaming-reveal.ts +353 -0
  674. package/src/modes/controllers/tan-command-controller.ts +190 -0
  675. package/src/modes/controllers/todo-command-controller.ts +484 -0
  676. package/src/modes/controllers/tool-args-reveal.ts +174 -0
  677. package/src/modes/data/emojis.json +1 -0
  678. package/src/modes/emoji-autocomplete.ts +285 -0
  679. package/src/modes/gradient-highlight.ts +99 -0
  680. package/src/modes/image-references.ts +137 -0
  681. package/src/modes/index.ts +17 -0
  682. package/src/modes/interactive-mode.ts +4053 -0
  683. package/src/modes/internal-url-autocomplete.ts +143 -0
  684. package/src/modes/loop-limit.ts +192 -0
  685. package/src/modes/magic-keywords.ts +42 -0
  686. package/src/modes/markdown-prose.ts +247 -0
  687. package/src/modes/oauth-manual-input.ts +69 -0
  688. package/src/modes/orchestrate.ts +42 -0
  689. package/src/modes/print-mode.ts +130 -0
  690. package/src/modes/prompt-action-autocomplete.ts +260 -0
  691. package/src/modes/rpc/host-tools.ts +186 -0
  692. package/src/modes/rpc/host-uris.ts +235 -0
  693. package/src/modes/rpc/rpc-client.ts +995 -0
  694. package/src/modes/rpc/rpc-mode.ts +1156 -0
  695. package/src/modes/rpc/rpc-subagents.ts +265 -0
  696. package/src/modes/rpc/rpc-types.ts +487 -0
  697. package/src/modes/runtime-init.ts +142 -0
  698. package/src/modes/session-observer-registry.ts +215 -0
  699. package/src/modes/setup-version.ts +11 -0
  700. package/src/modes/setup-wizard/index.ts +101 -0
  701. package/src/modes/setup-wizard/lazy.ts +16 -0
  702. package/src/modes/setup-wizard/scenes/glyph.ts +114 -0
  703. package/src/modes/setup-wizard/scenes/outro.ts +35 -0
  704. package/src/modes/setup-wizard/scenes/providers.ts +103 -0
  705. package/src/modes/setup-wizard/scenes/sign-in.ts +286 -0
  706. package/src/modes/setup-wizard/scenes/splash.ts +201 -0
  707. package/src/modes/setup-wizard/scenes/theme.ts +326 -0
  708. package/src/modes/setup-wizard/scenes/types.ts +57 -0
  709. package/src/modes/setup-wizard/scenes/web-search.ts +145 -0
  710. package/src/modes/setup-wizard/startup-splash.ts +107 -0
  711. package/src/modes/setup-wizard/wizard-overlay.ts +334 -0
  712. package/src/modes/shared.ts +49 -0
  713. package/src/modes/theme/dark.json +95 -0
  714. package/src/modes/theme/defaults/alabaster.json +93 -0
  715. package/src/modes/theme/defaults/amethyst.json +96 -0
  716. package/src/modes/theme/defaults/anthracite.json +93 -0
  717. package/src/modes/theme/defaults/basalt.json +91 -0
  718. package/src/modes/theme/defaults/birch.json +95 -0
  719. package/src/modes/theme/defaults/dark-abyss.json +91 -0
  720. package/src/modes/theme/defaults/dark-arctic.json +104 -0
  721. package/src/modes/theme/defaults/dark-aurora.json +95 -0
  722. package/src/modes/theme/defaults/dark-catppuccin.json +107 -0
  723. package/src/modes/theme/defaults/dark-cavern.json +91 -0
  724. package/src/modes/theme/defaults/dark-copper.json +95 -0
  725. package/src/modes/theme/defaults/dark-cosmos.json +90 -0
  726. package/src/modes/theme/defaults/dark-cyberpunk.json +102 -0
  727. package/src/modes/theme/defaults/dark-dracula.json +98 -0
  728. package/src/modes/theme/defaults/dark-eclipse.json +91 -0
  729. package/src/modes/theme/defaults/dark-ember.json +95 -0
  730. package/src/modes/theme/defaults/dark-equinox.json +90 -0
  731. package/src/modes/theme/defaults/dark-forest.json +96 -0
  732. package/src/modes/theme/defaults/dark-github.json +105 -0
  733. package/src/modes/theme/defaults/dark-gruvbox.json +112 -0
  734. package/src/modes/theme/defaults/dark-lavender.json +95 -0
  735. package/src/modes/theme/defaults/dark-lunar.json +89 -0
  736. package/src/modes/theme/defaults/dark-midnight.json +95 -0
  737. package/src/modes/theme/defaults/dark-monochrome.json +94 -0
  738. package/src/modes/theme/defaults/dark-monokai.json +98 -0
  739. package/src/modes/theme/defaults/dark-nebula.json +90 -0
  740. package/src/modes/theme/defaults/dark-nord.json +97 -0
  741. package/src/modes/theme/defaults/dark-ocean.json +101 -0
  742. package/src/modes/theme/defaults/dark-one.json +100 -0
  743. package/src/modes/theme/defaults/dark-poimandres.json +142 -0
  744. package/src/modes/theme/defaults/dark-rainforest.json +91 -0
  745. package/src/modes/theme/defaults/dark-reef.json +91 -0
  746. package/src/modes/theme/defaults/dark-retro.json +92 -0
  747. package/src/modes/theme/defaults/dark-rose-pine.json +96 -0
  748. package/src/modes/theme/defaults/dark-sakura.json +95 -0
  749. package/src/modes/theme/defaults/dark-slate.json +95 -0
  750. package/src/modes/theme/defaults/dark-solarized.json +97 -0
  751. package/src/modes/theme/defaults/dark-solstice.json +90 -0
  752. package/src/modes/theme/defaults/dark-starfall.json +91 -0
  753. package/src/modes/theme/defaults/dark-sunset.json +99 -0
  754. package/src/modes/theme/defaults/dark-swamp.json +90 -0
  755. package/src/modes/theme/defaults/dark-synthwave.json +103 -0
  756. package/src/modes/theme/defaults/dark-taiga.json +91 -0
  757. package/src/modes/theme/defaults/dark-terminal.json +95 -0
  758. package/src/modes/theme/defaults/dark-tokyo-night.json +101 -0
  759. package/src/modes/theme/defaults/dark-tundra.json +91 -0
  760. package/src/modes/theme/defaults/dark-twilight.json +91 -0
  761. package/src/modes/theme/defaults/dark-volcanic.json +91 -0
  762. package/src/modes/theme/defaults/graphite.json +92 -0
  763. package/src/modes/theme/defaults/index.ts +199 -0
  764. package/src/modes/theme/defaults/light-arctic.json +107 -0
  765. package/src/modes/theme/defaults/light-aurora-day.json +91 -0
  766. package/src/modes/theme/defaults/light-canyon.json +91 -0
  767. package/src/modes/theme/defaults/light-catppuccin.json +106 -0
  768. package/src/modes/theme/defaults/light-cirrus.json +90 -0
  769. package/src/modes/theme/defaults/light-coral.json +95 -0
  770. package/src/modes/theme/defaults/light-cyberpunk.json +96 -0
  771. package/src/modes/theme/defaults/light-dawn.json +90 -0
  772. package/src/modes/theme/defaults/light-dunes.json +91 -0
  773. package/src/modes/theme/defaults/light-eucalyptus.json +95 -0
  774. package/src/modes/theme/defaults/light-forest.json +100 -0
  775. package/src/modes/theme/defaults/light-frost.json +95 -0
  776. package/src/modes/theme/defaults/light-github.json +115 -0
  777. package/src/modes/theme/defaults/light-glacier.json +91 -0
  778. package/src/modes/theme/defaults/light-gruvbox.json +108 -0
  779. package/src/modes/theme/defaults/light-haze.json +90 -0
  780. package/src/modes/theme/defaults/light-honeycomb.json +95 -0
  781. package/src/modes/theme/defaults/light-lagoon.json +91 -0
  782. package/src/modes/theme/defaults/light-lavender.json +95 -0
  783. package/src/modes/theme/defaults/light-meadow.json +91 -0
  784. package/src/modes/theme/defaults/light-mint.json +95 -0
  785. package/src/modes/theme/defaults/light-monochrome.json +101 -0
  786. package/src/modes/theme/defaults/light-ocean.json +99 -0
  787. package/src/modes/theme/defaults/light-one.json +99 -0
  788. package/src/modes/theme/defaults/light-opal.json +91 -0
  789. package/src/modes/theme/defaults/light-orchard.json +91 -0
  790. package/src/modes/theme/defaults/light-paper.json +95 -0
  791. package/src/modes/theme/defaults/light-poimandres.json +142 -0
  792. package/src/modes/theme/defaults/light-prism.json +90 -0
  793. package/src/modes/theme/defaults/light-retro.json +98 -0
  794. package/src/modes/theme/defaults/light-sand.json +95 -0
  795. package/src/modes/theme/defaults/light-savanna.json +91 -0
  796. package/src/modes/theme/defaults/light-solarized.json +102 -0
  797. package/src/modes/theme/defaults/light-soleil.json +90 -0
  798. package/src/modes/theme/defaults/light-sunset.json +99 -0
  799. package/src/modes/theme/defaults/light-synthwave.json +98 -0
  800. package/src/modes/theme/defaults/light-tokyo-night.json +111 -0
  801. package/src/modes/theme/defaults/light-wetland.json +91 -0
  802. package/src/modes/theme/defaults/light-zenith.json +89 -0
  803. package/src/modes/theme/defaults/limestone.json +94 -0
  804. package/src/modes/theme/defaults/mahogany.json +97 -0
  805. package/src/modes/theme/defaults/marble.json +93 -0
  806. package/src/modes/theme/defaults/obsidian.json +91 -0
  807. package/src/modes/theme/defaults/onyx.json +91 -0
  808. package/src/modes/theme/defaults/pearl.json +93 -0
  809. package/src/modes/theme/defaults/porcelain.json +91 -0
  810. package/src/modes/theme/defaults/quartz.json +96 -0
  811. package/src/modes/theme/defaults/sandstone.json +95 -0
  812. package/src/modes/theme/defaults/titanium.json +90 -0
  813. package/src/modes/theme/light.json +93 -0
  814. package/src/modes/theme/mermaid-cache.ts +92 -0
  815. package/src/modes/theme/shimmer.ts +235 -0
  816. package/src/modes/theme/theme-schema.json +459 -0
  817. package/src/modes/theme/theme.ts +2950 -0
  818. package/src/modes/turn-budget.ts +31 -0
  819. package/src/modes/types.ts +425 -0
  820. package/src/modes/ultrathink.ts +41 -0
  821. package/src/modes/utils/context-usage.ts +432 -0
  822. package/src/modes/utils/copy-targets.ts +361 -0
  823. package/src/modes/utils/hotkeys-markdown.ts +62 -0
  824. package/src/modes/utils/interactive-context-helpers.ts +27 -0
  825. package/src/modes/utils/keybinding-matchers.ts +86 -0
  826. package/src/modes/utils/tools-markdown.ts +27 -0
  827. package/src/modes/utils/transcript-render-helpers.ts +157 -0
  828. package/src/modes/utils/ui-helpers.ts +783 -0
  829. package/src/modes/workflow.ts +42 -0
  830. package/src/plan-mode/approved-plan.ts +186 -0
  831. package/src/plan-mode/plan-handoff.ts +37 -0
  832. package/src/plan-mode/plan-protection.ts +31 -0
  833. package/src/plan-mode/state.ts +6 -0
  834. package/src/priority.json +45 -0
  835. package/src/prompts/advisor/advise-tool.md +3 -0
  836. package/src/prompts/advisor/system.md +75 -0
  837. package/src/prompts/agents/designer.md +74 -0
  838. package/src/prompts/agents/explore.md +58 -0
  839. package/src/prompts/agents/frontmatter.md +11 -0
  840. package/src/prompts/agents/init.md +33 -0
  841. package/src/prompts/agents/librarian.md +119 -0
  842. package/src/prompts/agents/oracle.md +54 -0
  843. package/src/prompts/agents/plan.md +48 -0
  844. package/src/prompts/agents/reviewer.md +139 -0
  845. package/src/prompts/agents/task.md +17 -0
  846. package/src/prompts/bench.md +12 -0
  847. package/src/prompts/ci-green-request.md +36 -0
  848. package/src/prompts/dry-balance-bench.md +8 -0
  849. package/src/prompts/goals/goal-budget-limit.md +16 -0
  850. package/src/prompts/goals/goal-continuation.md +28 -0
  851. package/src/prompts/goals/goal-mode-active.md +23 -0
  852. package/src/prompts/goals/guided-goal-interview.md +8 -0
  853. package/src/prompts/goals/guided-goal-system.md +12 -0
  854. package/src/prompts/memories/consolidation.md +30 -0
  855. package/src/prompts/memories/consolidation_system.md +4 -0
  856. package/src/prompts/memories/read-path.md +17 -0
  857. package/src/prompts/memories/stage_one_input.md +6 -0
  858. package/src/prompts/memories/stage_one_system.md +21 -0
  859. package/src/prompts/review-custom-request.md +22 -0
  860. package/src/prompts/review-headless-request.md +16 -0
  861. package/src/prompts/review-request.md +69 -0
  862. package/src/prompts/steering/user-interjection.md +9 -0
  863. package/src/prompts/system/agent-creation-architect.md +50 -0
  864. package/src/prompts/system/agent-creation-user.md +6 -0
  865. package/src/prompts/system/auto-continue.md +1 -0
  866. package/src/prompts/system/auto-thinking-difficulty-local.md +14 -0
  867. package/src/prompts/system/auto-thinking-difficulty.md +12 -0
  868. package/src/prompts/system/autolearn-guidance-learn.md +1 -0
  869. package/src/prompts/system/autolearn-guidance.md +7 -0
  870. package/src/prompts/system/autolearn-nudge.md +3 -0
  871. package/src/prompts/system/background-tan-dispatch.md +8 -0
  872. package/src/prompts/system/btw-user.md +8 -0
  873. package/src/prompts/system/commit-message-system.md +14 -0
  874. package/src/prompts/system/custom-system-prompt.md +64 -0
  875. package/src/prompts/system/eager-task.md +7 -0
  876. package/src/prompts/system/eager-todo.md +18 -0
  877. package/src/prompts/system/empty-stop-retry.md +4 -0
  878. package/src/prompts/system/irc-autoreply.md +6 -0
  879. package/src/prompts/system/irc-incoming.md +7 -0
  880. package/src/prompts/system/manual-continue.md +7 -0
  881. package/src/prompts/system/memory-consolidation-system.md +8 -0
  882. package/src/prompts/system/memory-extraction-system.md +26 -0
  883. package/src/prompts/system/omfg-user.md +50 -0
  884. package/src/prompts/system/orchestrate-notice.md +40 -0
  885. package/src/prompts/system/personalities/default.md +18 -0
  886. package/src/prompts/system/personalities/friendly.md +17 -0
  887. package/src/prompts/system/personalities/pragmatic.md +15 -0
  888. package/src/prompts/system/plan-mode-active.md +109 -0
  889. package/src/prompts/system/plan-mode-approved.md +25 -0
  890. package/src/prompts/system/plan-mode-compact-instructions.md +16 -0
  891. package/src/prompts/system/plan-mode-reference.md +11 -0
  892. package/src/prompts/system/plan-mode-subagent.md +33 -0
  893. package/src/prompts/system/plan-mode-tool-decision-reminder.md +9 -0
  894. package/src/prompts/system/project-prompt.md +54 -0
  895. package/src/prompts/system/side-channel-no-tools.md +3 -0
  896. package/src/prompts/system/snapcompact-context-frames-note.md +1 -0
  897. package/src/prompts/system/snapcompact-context-stub.md +1 -0
  898. package/src/prompts/system/snapcompact-system-frames-note.md +1 -0
  899. package/src/prompts/system/snapcompact-system-stub.md +1 -0
  900. package/src/prompts/system/snapcompact-toolresult-note.md +1 -0
  901. package/src/prompts/system/subagent-system-prompt.md +71 -0
  902. package/src/prompts/system/subagent-user-prompt.md +3 -0
  903. package/src/prompts/system/subagent-yield-reminder.md +12 -0
  904. package/src/prompts/system/system-prompt.md +250 -0
  905. package/src/prompts/system/tiny-title-system.md +8 -0
  906. package/src/prompts/system/title-marker-instruction.md +1 -0
  907. package/src/prompts/system/title-system-marker.md +16 -0
  908. package/src/prompts/system/title-system.md +16 -0
  909. package/src/prompts/system/ttsr-interrupt.md +7 -0
  910. package/src/prompts/system/ttsr-tool-reminder.md +5 -0
  911. package/src/prompts/system/ultrathink-notice.md +3 -0
  912. package/src/prompts/system/unexpected-stop-classifier.md +17 -0
  913. package/src/prompts/system/unexpected-stop-retry.md +4 -0
  914. package/src/prompts/system/web-search.md +25 -0
  915. package/src/prompts/system/workflow-notice.md +70 -0
  916. package/src/prompts/tools/apply-patch.md +65 -0
  917. package/src/prompts/tools/ask.md +22 -0
  918. package/src/prompts/tools/ast-edit.md +22 -0
  919. package/src/prompts/tools/ast-grep.md +25 -0
  920. package/src/prompts/tools/async-result.md +8 -0
  921. package/src/prompts/tools/bash.md +44 -0
  922. package/src/prompts/tools/browser.md +45 -0
  923. package/src/prompts/tools/checkpoint.md +15 -0
  924. package/src/prompts/tools/debug.md +17 -0
  925. package/src/prompts/tools/eval.md +72 -0
  926. package/src/prompts/tools/find.md +15 -0
  927. package/src/prompts/tools/github.md +17 -0
  928. package/src/prompts/tools/goal.md +11 -0
  929. package/src/prompts/tools/image-attachment-describe-system.md +8 -0
  930. package/src/prompts/tools/image-attachment-describe.md +10 -0
  931. package/src/prompts/tools/image-gen.md +7 -0
  932. package/src/prompts/tools/inspect-image-system.md +20 -0
  933. package/src/prompts/tools/inspect-image.md +22 -0
  934. package/src/prompts/tools/irc.md +33 -0
  935. package/src/prompts/tools/job.md +17 -0
  936. package/src/prompts/tools/learn.md +7 -0
  937. package/src/prompts/tools/lsp-late-diagnostic.md +8 -0
  938. package/src/prompts/tools/lsp.md +39 -0
  939. package/src/prompts/tools/manage-skill.md +9 -0
  940. package/src/prompts/tools/memory-edit.md +8 -0
  941. package/src/prompts/tools/patch.md +57 -0
  942. package/src/prompts/tools/read.md +75 -0
  943. package/src/prompts/tools/recall.md +5 -0
  944. package/src/prompts/tools/reflect.md +5 -0
  945. package/src/prompts/tools/replace.md +29 -0
  946. package/src/prompts/tools/resolve.md +4 -0
  947. package/src/prompts/tools/retain.md +6 -0
  948. package/src/prompts/tools/rewind.md +13 -0
  949. package/src/prompts/tools/search-tool-bm25.md +32 -0
  950. package/src/prompts/tools/search.md +22 -0
  951. package/src/prompts/tools/ssh.md +22 -0
  952. package/src/prompts/tools/task-summary.md +17 -0
  953. package/src/prompts/tools/task.md +91 -0
  954. package/src/prompts/tools/todo.md +39 -0
  955. package/src/prompts/tools/web-search.md +6 -0
  956. package/src/prompts/tools/write.md +14 -0
  957. package/src/registry/agent-lifecycle.ts +270 -0
  958. package/src/registry/agent-registry.ts +190 -0
  959. package/src/sdk.ts +2948 -0
  960. package/src/secrets/index.ts +123 -0
  961. package/src/secrets/obfuscator.ts +441 -0
  962. package/src/secrets/regex.ts +21 -0
  963. package/src/session/agent-session.ts +12886 -0
  964. package/src/session/agent-storage.ts +478 -0
  965. package/src/session/artifacts.ts +153 -0
  966. package/src/session/auth-broker-config.ts +92 -0
  967. package/src/session/auth-storage.ts +24 -0
  968. package/src/session/blob-store.ts +255 -0
  969. package/src/session/client-bridge.ts +85 -0
  970. package/src/session/codex-auto-reset.ts +202 -0
  971. package/src/session/compact-modes.ts +105 -0
  972. package/src/session/history-storage.ts +360 -0
  973. package/src/session/indexed-session-storage.ts +427 -0
  974. package/src/session/messages.ts +546 -0
  975. package/src/session/redis-session-storage.ts +170 -0
  976. package/src/session/session-context.ts +404 -0
  977. package/src/session/session-dump-format.ts +216 -0
  978. package/src/session/session-entries.ts +204 -0
  979. package/src/session/session-history-format.ts +348 -0
  980. package/src/session/session-listing.ts +588 -0
  981. package/src/session/session-loader.ts +93 -0
  982. package/src/session/session-manager.ts +1750 -0
  983. package/src/session/session-migrations.ts +78 -0
  984. package/src/session/session-paths.ts +193 -0
  985. package/src/session/session-persistence.ts +147 -0
  986. package/src/session/session-storage.ts +590 -0
  987. package/src/session/shake-types.ts +43 -0
  988. package/src/session/snapcompact-inline.ts +545 -0
  989. package/src/session/snapcompact-savings-journal.ts +113 -0
  990. package/src/session/sql-session-storage.ts +314 -0
  991. package/src/session/streaming-output.ts +1330 -0
  992. package/src/session/tool-choice-queue.ts +290 -0
  993. package/src/session/unexpected-stop-classifier.ts +129 -0
  994. package/src/session/yield-queue.ts +183 -0
  995. package/src/slash-commands/acp-builtins.ts +70 -0
  996. package/src/slash-commands/available-commands.ts +105 -0
  997. package/src/slash-commands/builtin-registry.ts +2433 -0
  998. package/src/slash-commands/helpers/active-oauth-account.ts +44 -0
  999. package/src/slash-commands/helpers/collab-qrcode.ts +28 -0
  1000. package/src/slash-commands/helpers/context-report.ts +66 -0
  1001. package/src/slash-commands/helpers/cron.ts +331 -0
  1002. package/src/slash-commands/helpers/format.ts +46 -0
  1003. package/src/slash-commands/helpers/logout.ts +88 -0
  1004. package/src/slash-commands/helpers/marketplace-manager.ts +25 -0
  1005. package/src/slash-commands/helpers/mcp.ts +532 -0
  1006. package/src/slash-commands/helpers/parse.ts +85 -0
  1007. package/src/slash-commands/helpers/reset-usage.ts +66 -0
  1008. package/src/slash-commands/helpers/ssh.ts +195 -0
  1009. package/src/slash-commands/helpers/stats-dashboard.ts +85 -0
  1010. package/src/slash-commands/helpers/todo.ts +285 -0
  1011. package/src/slash-commands/helpers/usage-report.ts +128 -0
  1012. package/src/slash-commands/marketplace-install-parser.ts +99 -0
  1013. package/src/slash-commands/types.ts +137 -0
  1014. package/src/ssh/config-writer.ts +183 -0
  1015. package/src/ssh/connection-manager.ts +510 -0
  1016. package/src/ssh/ssh-executor.ts +189 -0
  1017. package/src/ssh/sshfs-mount.ts +140 -0
  1018. package/src/ssh/utils.ts +8 -0
  1019. package/src/startup-splash.ts +19 -0
  1020. package/src/stt/asr-client.ts +341 -0
  1021. package/src/stt/asr-protocol.ts +65 -0
  1022. package/src/stt/asr-worker.ts +638 -0
  1023. package/src/stt/downloader.ts +138 -0
  1024. package/src/stt/endpointer.ts +259 -0
  1025. package/src/stt/index.ts +7 -0
  1026. package/src/stt/models.ts +150 -0
  1027. package/src/stt/recorder.ts +538 -0
  1028. package/src/stt/stt-controller.ts +380 -0
  1029. package/src/stt/transcriber.ts +60 -0
  1030. package/src/stt/wav.ts +173 -0
  1031. package/src/subprocess/worker-client.ts +297 -0
  1032. package/src/subprocess/worker-runtime.ts +277 -0
  1033. package/src/system-prompt.ts +698 -0
  1034. package/src/task/agents.ts +166 -0
  1035. package/src/task/commands.ts +132 -0
  1036. package/src/task/discovery.ts +122 -0
  1037. package/src/task/executor.ts +2356 -0
  1038. package/src/task/index.ts +1580 -0
  1039. package/src/task/name-generator.ts +1577 -0
  1040. package/src/task/omp-command.ts +26 -0
  1041. package/src/task/output-manager.ts +93 -0
  1042. package/src/task/parallel.ts +116 -0
  1043. package/src/task/persisted-revive.ts +128 -0
  1044. package/src/task/render.ts +1558 -0
  1045. package/src/task/repair-args.ts +129 -0
  1046. package/src/task/subprocess-tool-registry.ts +88 -0
  1047. package/src/task/types.ts +401 -0
  1048. package/src/task/worktree.ts +522 -0
  1049. package/src/telemetry-export.ts +144 -0
  1050. package/src/thinking.ts +187 -0
  1051. package/src/tiny/device.ts +111 -0
  1052. package/src/tiny/dtype.ts +101 -0
  1053. package/src/tiny/models.ts +256 -0
  1054. package/src/tiny/text.ts +169 -0
  1055. package/src/tiny/title-client.ts +378 -0
  1056. package/src/tiny/title-protocol.ts +56 -0
  1057. package/src/tiny/worker.ts +341 -0
  1058. package/src/tool-discovery/mode.ts +24 -0
  1059. package/src/tool-discovery/tool-index.ts +271 -0
  1060. package/src/tools/__tests__/json-tree.test.ts +35 -0
  1061. package/src/tools/acp-bridge.ts +66 -0
  1062. package/src/tools/approval.ts +189 -0
  1063. package/src/tools/ask.ts +977 -0
  1064. package/src/tools/ast-edit.ts +700 -0
  1065. package/src/tools/ast-grep.ts +483 -0
  1066. package/src/tools/auto-generated-guard.ts +322 -0
  1067. package/src/tools/bash-command-fixup.ts +37 -0
  1068. package/src/tools/bash-interactive.ts +408 -0
  1069. package/src/tools/bash-interceptor.ts +67 -0
  1070. package/src/tools/bash-pty-selection.ts +14 -0
  1071. package/src/tools/bash-skill-urls.ts +248 -0
  1072. package/src/tools/bash.ts +1405 -0
  1073. package/src/tools/browser/aria/aria-snapshot.bundle.txt +7 -0
  1074. package/src/tools/browser/aria/aria-snapshot.ts +103 -0
  1075. package/src/tools/browser/attach.ts +194 -0
  1076. package/src/tools/browser/cmux/cmux-tab.ts +1336 -0
  1077. package/src/tools/browser/cmux/rpc.ts +156 -0
  1078. package/src/tools/browser/cmux/socket-client.ts +309 -0
  1079. package/src/tools/browser/launch.ts +749 -0
  1080. package/src/tools/browser/readable.ts +112 -0
  1081. package/src/tools/browser/registry.ts +241 -0
  1082. package/src/tools/browser/render.ts +221 -0
  1083. package/src/tools/browser/tab-protocol.ts +107 -0
  1084. package/src/tools/browser/tab-supervisor.ts +799 -0
  1085. package/src/tools/browser/tab-worker-entry.ts +29 -0
  1086. package/src/tools/browser/tab-worker.ts +1421 -0
  1087. package/src/tools/browser.ts +408 -0
  1088. package/src/tools/builtin-names.ts +34 -0
  1089. package/src/tools/checkpoint.ts +136 -0
  1090. package/src/tools/conflict-detect.ts +718 -0
  1091. package/src/tools/context.ts +39 -0
  1092. package/src/tools/debug.ts +1087 -0
  1093. package/src/tools/eval-backends.ts +34 -0
  1094. package/src/tools/eval-render.ts +771 -0
  1095. package/src/tools/eval.ts +765 -0
  1096. package/src/tools/fetch.ts +1902 -0
  1097. package/src/tools/file-recorder.ts +35 -0
  1098. package/src/tools/find.ts +628 -0
  1099. package/src/tools/fs-cache-invalidation.ts +28 -0
  1100. package/src/tools/gh-cache-invalidation.ts +255 -0
  1101. package/src/tools/gh-format.ts +12 -0
  1102. package/src/tools/gh-renderer.ts +481 -0
  1103. package/src/tools/gh.ts +3752 -0
  1104. package/src/tools/github-cache.ts +663 -0
  1105. package/src/tools/grouped-file-output.ts +210 -0
  1106. package/src/tools/image-gen.ts +1586 -0
  1107. package/src/tools/index.ts +672 -0
  1108. package/src/tools/inspect-image-renderer.ts +132 -0
  1109. package/src/tools/inspect-image.ts +260 -0
  1110. package/src/tools/irc.ts +788 -0
  1111. package/src/tools/job.ts +612 -0
  1112. package/src/tools/json-tree.ts +260 -0
  1113. package/src/tools/jtd-to-json-schema.ts +219 -0
  1114. package/src/tools/jtd-to-typescript.ts +136 -0
  1115. package/src/tools/jtd-utils.ts +102 -0
  1116. package/src/tools/learn.ts +141 -0
  1117. package/src/tools/list-limit.ts +40 -0
  1118. package/src/tools/manage-skill.ts +100 -0
  1119. package/src/tools/match-line-format.ts +20 -0
  1120. package/src/tools/memory-edit.ts +59 -0
  1121. package/src/tools/memory-recall.ts +102 -0
  1122. package/src/tools/memory-reflect.ts +88 -0
  1123. package/src/tools/memory-render.ts +202 -0
  1124. package/src/tools/memory-retain.ts +89 -0
  1125. package/src/tools/output-meta.ts +768 -0
  1126. package/src/tools/output-schema-validator.ts +132 -0
  1127. package/src/tools/path-utils.ts +1116 -0
  1128. package/src/tools/plan-mode-guard.ts +142 -0
  1129. package/src/tools/puppeteer/00_stealth_tampering.txt +44 -0
  1130. package/src/tools/puppeteer/01_stealth_activity.txt +80 -0
  1131. package/src/tools/puppeteer/02_stealth_hairline.txt +57 -0
  1132. package/src/tools/puppeteer/03_stealth_botd.txt +380 -0
  1133. package/src/tools/puppeteer/04_stealth_iframe.txt +174 -0
  1134. package/src/tools/puppeteer/05_stealth_webgl.txt +233 -0
  1135. package/src/tools/puppeteer/06_stealth_screen.txt +260 -0
  1136. package/src/tools/puppeteer/07_stealth_fonts.txt +99 -0
  1137. package/src/tools/puppeteer/08_stealth_audio.txt +63 -0
  1138. package/src/tools/puppeteer/09_stealth_locale.txt +51 -0
  1139. package/src/tools/puppeteer/10_stealth_plugins.txt +212 -0
  1140. package/src/tools/puppeteer/11_stealth_hardware.txt +59 -0
  1141. package/src/tools/puppeteer/12_stealth_codecs.txt +42 -0
  1142. package/src/tools/puppeteer/13_stealth_worker.txt +235 -0
  1143. package/src/tools/read.ts +3124 -0
  1144. package/src/tools/render-utils.ts +895 -0
  1145. package/src/tools/renderers.ts +86 -0
  1146. package/src/tools/report-tool-issue.ts +530 -0
  1147. package/src/tools/resolve.ts +302 -0
  1148. package/src/tools/review.ts +251 -0
  1149. package/src/tools/search-tool-bm25.ts +351 -0
  1150. package/src/tools/search.ts +1592 -0
  1151. package/src/tools/sqlite-reader.ts +884 -0
  1152. package/src/tools/ssh.ts +369 -0
  1153. package/src/tools/todo.ts +944 -0
  1154. package/src/tools/tool-errors.ts +62 -0
  1155. package/src/tools/tool-result.ts +102 -0
  1156. package/src/tools/tool-timeouts.ts +30 -0
  1157. package/src/tools/tts.ts +265 -0
  1158. package/src/tools/write.ts +1156 -0
  1159. package/src/tools/yield.ts +269 -0
  1160. package/src/tts/downloader.ts +64 -0
  1161. package/src/tts/index.ts +8 -0
  1162. package/src/tts/models.ts +137 -0
  1163. package/src/tts/player.ts +137 -0
  1164. package/src/tts/runtime.ts +21 -0
  1165. package/src/tts/streaming-player.ts +266 -0
  1166. package/src/tts/tts-client.ts +474 -0
  1167. package/src/tts/tts-protocol.ts +60 -0
  1168. package/src/tts/tts-worker.ts +431 -0
  1169. package/src/tts/vocalizer.ts +162 -0
  1170. package/src/tts/wav.ts +58 -0
  1171. package/src/tui/code-cell.ts +268 -0
  1172. package/src/tui/file-list.ts +55 -0
  1173. package/src/tui/hyperlink.ts +178 -0
  1174. package/src/tui/index.ts +13 -0
  1175. package/src/tui/output-block.ts +240 -0
  1176. package/src/tui/status-line.ts +54 -0
  1177. package/src/tui/tree-list.ts +133 -0
  1178. package/src/tui/types.ts +15 -0
  1179. package/src/tui/utils.ts +103 -0
  1180. package/src/tui/width-aware-text.ts +58 -0
  1181. package/src/ui/banner.ts +41 -0
  1182. package/src/ui/chat-prompt.ts +34 -0
  1183. package/src/ui/colors.ts +37 -0
  1184. package/src/ui/index.ts +6 -0
  1185. package/src/ui/spinner.ts +15 -0
  1186. package/src/ui/status-bar.ts +57 -0
  1187. package/src/utils/block-context.ts +312 -0
  1188. package/src/utils/changelog.ts +132 -0
  1189. package/src/utils/clipboard.ts +262 -0
  1190. package/src/utils/command-args.ts +76 -0
  1191. package/src/utils/commit-message-generator.ts +147 -0
  1192. package/src/utils/edit-mode.ts +41 -0
  1193. package/src/utils/enhanced-paste.ts +230 -0
  1194. package/src/utils/event-bus.ts +33 -0
  1195. package/src/utils/external-editor.ts +78 -0
  1196. package/src/utils/file-display-mode.ts +44 -0
  1197. package/src/utils/file-mentions.ts +284 -0
  1198. package/src/utils/git.ts +1839 -0
  1199. package/src/utils/image-loading.ts +231 -0
  1200. package/src/utils/image-resize.ts +309 -0
  1201. package/src/utils/image-vision-fallback.ts +197 -0
  1202. package/src/utils/ipc.ts +38 -0
  1203. package/src/utils/jj.ts +295 -0
  1204. package/src/utils/lang-from-path.ts +244 -0
  1205. package/src/utils/markit.ts +143 -0
  1206. package/src/utils/mupdf-wasm-embed.ts +12 -0
  1207. package/src/utils/open.ts +55 -0
  1208. package/src/utils/qrcode.ts +535 -0
  1209. package/src/utils/session-color.ts +142 -0
  1210. package/src/utils/shell-snapshot.ts +249 -0
  1211. package/src/utils/sixel.ts +69 -0
  1212. package/src/utils/thinking-display.ts +89 -0
  1213. package/src/utils/title-generator.ts +348 -0
  1214. package/src/utils/tool-choice.ts +49 -0
  1215. package/src/utils/tools-manager.ts +372 -0
  1216. package/src/utils/turndown.ts +83 -0
  1217. package/src/utils/zip.ts +1091 -0
  1218. package/src/web/kagi.ts +304 -0
  1219. package/src/web/parallel.ts +354 -0
  1220. package/src/web/scrapers/artifacthub.ts +207 -0
  1221. package/src/web/scrapers/arxiv.ts +83 -0
  1222. package/src/web/scrapers/aur.ts +162 -0
  1223. package/src/web/scrapers/biorxiv.ts +133 -0
  1224. package/src/web/scrapers/bluesky.ts +262 -0
  1225. package/src/web/scrapers/brew.ts +172 -0
  1226. package/src/web/scrapers/cheatsh.ts +68 -0
  1227. package/src/web/scrapers/chocolatey.ts +196 -0
  1228. package/src/web/scrapers/choosealicense.ts +95 -0
  1229. package/src/web/scrapers/cisa-kev.ts +87 -0
  1230. package/src/web/scrapers/clojars.ts +154 -0
  1231. package/src/web/scrapers/coingecko.ts +177 -0
  1232. package/src/web/scrapers/crates-io.ts +97 -0
  1233. package/src/web/scrapers/crossref.ts +136 -0
  1234. package/src/web/scrapers/devto.ts +147 -0
  1235. package/src/web/scrapers/discogs.ts +306 -0
  1236. package/src/web/scrapers/discourse.ts +197 -0
  1237. package/src/web/scrapers/dockerhub.ts +138 -0
  1238. package/src/web/scrapers/docs-rs.ts +652 -0
  1239. package/src/web/scrapers/fdroid.ts +134 -0
  1240. package/src/web/scrapers/firefox-addons.ts +191 -0
  1241. package/src/web/scrapers/flathub.ts +223 -0
  1242. package/src/web/scrapers/github-gist.ts +58 -0
  1243. package/src/web/scrapers/github.ts +800 -0
  1244. package/src/web/scrapers/gitlab.ts +401 -0
  1245. package/src/web/scrapers/go-pkg.ts +266 -0
  1246. package/src/web/scrapers/hackage.ts +140 -0
  1247. package/src/web/scrapers/hackernews.ts +189 -0
  1248. package/src/web/scrapers/hex.ts +105 -0
  1249. package/src/web/scrapers/huggingface.ts +321 -0
  1250. package/src/web/scrapers/iacr.ts +89 -0
  1251. package/src/web/scrapers/index.ts +252 -0
  1252. package/src/web/scrapers/jetbrains-marketplace.ts +159 -0
  1253. package/src/web/scrapers/lemmy.ts +203 -0
  1254. package/src/web/scrapers/lobsters.ts +175 -0
  1255. package/src/web/scrapers/mastodon.ts +292 -0
  1256. package/src/web/scrapers/maven.ts +138 -0
  1257. package/src/web/scrapers/mdn.ts +173 -0
  1258. package/src/web/scrapers/metacpan.ts +222 -0
  1259. package/src/web/scrapers/musicbrainz.ts +250 -0
  1260. package/src/web/scrapers/npm.ts +98 -0
  1261. package/src/web/scrapers/nuget.ts +183 -0
  1262. package/src/web/scrapers/nvd.ts +222 -0
  1263. package/src/web/scrapers/ollama.ts +239 -0
  1264. package/src/web/scrapers/open-vsx.ts +106 -0
  1265. package/src/web/scrapers/opencorporates.ts +292 -0
  1266. package/src/web/scrapers/openlibrary.ts +336 -0
  1267. package/src/web/scrapers/orcid.ts +286 -0
  1268. package/src/web/scrapers/osv.ts +176 -0
  1269. package/src/web/scrapers/packagist.ts +160 -0
  1270. package/src/web/scrapers/pub-dev.ts +143 -0
  1271. package/src/web/scrapers/pubmed.ts +211 -0
  1272. package/src/web/scrapers/pypi.ts +112 -0
  1273. package/src/web/scrapers/rawg.ts +110 -0
  1274. package/src/web/scrapers/readthedocs.ts +120 -0
  1275. package/src/web/scrapers/reddit.ts +95 -0
  1276. package/src/web/scrapers/repology.ts +251 -0
  1277. package/src/web/scrapers/rfc.ts +201 -0
  1278. package/src/web/scrapers/rubygems.ts +103 -0
  1279. package/src/web/scrapers/searchcode.ts +189 -0
  1280. package/src/web/scrapers/sec-edgar.ts +261 -0
  1281. package/src/web/scrapers/semantic-scholar.ts +171 -0
  1282. package/src/web/scrapers/snapcraft.ts +187 -0
  1283. package/src/web/scrapers/sourcegraph.ts +336 -0
  1284. package/src/web/scrapers/spdx.ts +108 -0
  1285. package/src/web/scrapers/spotify.ts +198 -0
  1286. package/src/web/scrapers/stackoverflow.ts +120 -0
  1287. package/src/web/scrapers/terraform.ts +277 -0
  1288. package/src/web/scrapers/tldr.ts +47 -0
  1289. package/src/web/scrapers/twitter.ts +94 -0
  1290. package/src/web/scrapers/types.ts +354 -0
  1291. package/src/web/scrapers/utils.ts +109 -0
  1292. package/src/web/scrapers/vimeo.ts +133 -0
  1293. package/src/web/scrapers/vscode-marketplace.ts +187 -0
  1294. package/src/web/scrapers/w3c.ts +156 -0
  1295. package/src/web/scrapers/wikidata.ts +344 -0
  1296. package/src/web/scrapers/wikipedia.ts +84 -0
  1297. package/src/web/scrapers/youtube.ts +325 -0
  1298. package/src/web/search/index.ts +317 -0
  1299. package/src/web/search/provider.ts +169 -0
  1300. package/src/web/search/providers/anthropic.ts +343 -0
  1301. package/src/web/search/providers/base.ts +90 -0
  1302. package/src/web/search/providers/brave.ts +152 -0
  1303. package/src/web/search/providers/codex.ts +593 -0
  1304. package/src/web/search/providers/exa.ts +400 -0
  1305. package/src/web/search/providers/gemini.ts +518 -0
  1306. package/src/web/search/providers/jina.ts +111 -0
  1307. package/src/web/search/providers/kagi.ts +86 -0
  1308. package/src/web/search/providers/kimi.ts +196 -0
  1309. package/src/web/search/providers/parallel.ts +136 -0
  1310. package/src/web/search/providers/perplexity-auth.ts +133 -0
  1311. package/src/web/search/providers/perplexity.ts +878 -0
  1312. package/src/web/search/providers/searxng.ts +325 -0
  1313. package/src/web/search/providers/synthetic.ts +114 -0
  1314. package/src/web/search/providers/tavily.ts +176 -0
  1315. package/src/web/search/providers/utils.ts +128 -0
  1316. package/src/web/search/providers/zai.ts +333 -0
  1317. package/src/web/search/render.ts +262 -0
  1318. package/src/web/search/types.ts +462 -0
  1319. package/src/web/search/utils.ts +17 -0
  1320. package/src/workspace-tree.ts +326 -0
@@ -0,0 +1,1346 @@
1
+ /**
2
+ * MCP Server Manager.
3
+ *
4
+ * Discovers, connects to, and manages MCP servers.
5
+ * Handles tool loading and lifecycle.
6
+ */
7
+ import * as path from "node:path";
8
+ import * as url from "node:url";
9
+ import { isDefinitiveOAuthFailure, type TSchema } from "@oh-my-pi/pi-ai";
10
+ import { logger } from "@oh-my-pi/pi-utils";
11
+ import type { SourceMeta } from "../capability/types";
12
+ import { resolveConfigValue } from "../config/resolve-config-value";
13
+ import type { CustomTool } from "../extensibility/custom-tools/types";
14
+ import type { AuthStorage } from "../session/auth-storage";
15
+ import {
16
+ connectToServer,
17
+ disconnectServer,
18
+ getPrompt,
19
+ listPrompts,
20
+ listResources,
21
+ listResourceTemplates,
22
+ listTools,
23
+ readResource,
24
+ serverSupportsPrompts,
25
+ serverSupportsResources,
26
+ subscribeToResources,
27
+ unsubscribeFromResources,
28
+ } from "./client";
29
+ import { type LoadMCPConfigsResult, loadAllMCPConfigs, validateServerConfig } from "./config";
30
+ import {
31
+ lookupMcpOAuthCredential,
32
+ type MCPOAuthCredentialLookup,
33
+ selectMcpOAuthRefreshMaterial,
34
+ } from "./oauth-credentials";
35
+ import { type MCPStoredOAuthCredential, refreshMCPOAuthToken } from "./oauth-flow";
36
+ import type { McpConnectionStatusEvent } from "./startup-events";
37
+ import type { MCPToolDetails } from "./tool-bridge";
38
+ import { DeferredMCPTool, MCPTool } from "./tool-bridge";
39
+ import type { MCPToolCache } from "./tool-cache";
40
+ import { HttpTransport } from "./transports/http";
41
+ import type {
42
+ MCPGetPromptResult,
43
+ MCPPrompt,
44
+ MCPRequestOptions,
45
+ MCPResource,
46
+ MCPResourceReadResult,
47
+ MCPResourceTemplate,
48
+ MCPServerConfig,
49
+ MCPServerConnection,
50
+ MCPToolDefinition,
51
+ } from "./types";
52
+ import { MCPNotificationMethods } from "./types";
53
+
54
+ type ToolLoadResult = {
55
+ connection: MCPServerConnection;
56
+ serverTools: MCPToolDefinition[];
57
+ };
58
+
59
+ type TrackedPromise<T> = {
60
+ promise: Promise<T>;
61
+ status: "pending" | "fulfilled" | "rejected";
62
+ value?: T;
63
+ reason?: unknown;
64
+ };
65
+
66
+ const STARTUP_TIMEOUT_MS = 250;
67
+
68
+ /**
69
+ * Per-server reconnect-storm circuit breaker.
70
+ *
71
+ * `transport.onClose` (wired in {@link MCPManager.connectServers} and
72
+ * {@link MCPManager.#connectAndWireServer}) fires `reconnectServer` on every
73
+ * clean process exit, so a stdio MCP server that completes the
74
+ * `initialize` + `tools/list` handshake and then exits will pull the agent
75
+ * into a fork loop with no rate limit. That pathology shipped in issue #1592
76
+ * (a `php`-shebang MCP fork-bombing macOS, parented directly to the agent's
77
+ * `bun` PID via shebang exec).
78
+ *
79
+ * We keep the sliding window short — older crashes age out so a single
80
+ * transient failure stays cheap — but cap the burst tightly enough that the
81
+ * agent never spawns more than `RECONNECT_BURST_LIMIT * #doReconnect retries`
82
+ * (≤ 25) processes per stuck server per window. Manual `/mcp reconnect`
83
+ * resets the window so users can recover after fixing the underlying
84
+ * misconfiguration.
85
+ */
86
+ const RECONNECT_BURST_WINDOW_MS = 30_000;
87
+ const RECONNECT_BURST_LIMIT = 5;
88
+
89
+ function trackPromise<T>(promise: Promise<T>): TrackedPromise<T> {
90
+ const tracked: TrackedPromise<T> = { promise, status: "pending" };
91
+ promise.then(
92
+ value => {
93
+ tracked.status = "fulfilled";
94
+ tracked.value = value;
95
+ },
96
+ reason => {
97
+ tracked.status = "rejected";
98
+ tracked.reason = reason;
99
+ },
100
+ );
101
+ return tracked;
102
+ }
103
+
104
+ function delay(ms: number): Promise<void> {
105
+ return Bun.sleep(ms);
106
+ }
107
+
108
+ /**
109
+ * Stable, total ordering on MCP tools by name.
110
+ *
111
+ * Anthropic prompt caching keys on byte-identical tool definitions: any reorder
112
+ * of the tools array invalidates the tools cache breakpoint and forces a full
113
+ * prefix rebuild on the next request. MCP servers connect/reconnect at arbitrary
114
+ * times, so the natural "insertion order" of `#tools` is non-deterministic.
115
+ * Sorting after every mutation makes the array bytes independent of connection
116
+ * sequence.
117
+ */
118
+ export function sortMCPToolsByName<T extends { name: string }>(tools: T[]): T[] {
119
+ tools.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
120
+ return tools;
121
+ }
122
+
123
+ export function resolveSubscriptionPostAction(
124
+ notificationsEnabled: boolean,
125
+ currentEpoch: number,
126
+ subscriptionEpoch: number,
127
+ ): "rollback" | "ignore" | "apply" {
128
+ if (!notificationsEnabled) return "rollback";
129
+ if (currentEpoch !== subscriptionEpoch) return "ignore";
130
+ return "apply";
131
+ }
132
+ /** Result of loading MCP tools */
133
+ export interface MCPLoadResult {
134
+ /** Loaded tools as CustomTool instances */
135
+ tools: CustomTool<TSchema, MCPToolDetails>[];
136
+ /** Connection errors by server name */
137
+ errors: Map<string, string>;
138
+ /** Connected server names */
139
+ connectedServers: string[];
140
+ /** Extracted Exa API keys from filtered MCP servers */
141
+ exaApiKeys: string[];
142
+ }
143
+
144
+ /** Options for discovering and connecting to MCP servers */
145
+ export interface MCPDiscoverOptions {
146
+ /** Whether to load project-level config (default: true) */
147
+ enableProjectConfig?: boolean;
148
+ /** Whether to filter out Exa MCP servers (default: true) */
149
+ filterExa?: boolean;
150
+ /** Whether to filter out browser MCP servers when builtin browser tool is enabled (default: false) */
151
+ filterBrowser?: boolean;
152
+ /** Called when MCP server connection state changes. */
153
+ onStatus?: (event: McpConnectionStatusEvent) => void;
154
+ }
155
+
156
+ /**
157
+ * MCP Server Manager.
158
+ *
159
+ * Manages connections to MCP servers and provides tools to the agent.
160
+ */
161
+ export class MCPManager {
162
+ static #instance: MCPManager | undefined;
163
+
164
+ /** Process-global instance shared by internal URL protocol handlers and tools. */
165
+ static instance(): MCPManager | undefined {
166
+ return MCPManager.#instance;
167
+ }
168
+
169
+ /** Install or clear the process-global instance. */
170
+ static setInstance(value: MCPManager | undefined): void {
171
+ MCPManager.#instance = value;
172
+ }
173
+
174
+ /** Reset the process-global instance. Test-only. */
175
+ static resetForTests(): void {
176
+ MCPManager.#instance = undefined;
177
+ }
178
+
179
+ #connections = new Map<string, MCPServerConnection>();
180
+ #tools: CustomTool<TSchema, MCPToolDetails>[] = [];
181
+ #pendingConnections = new Map<string, Promise<MCPServerConnection>>();
182
+ #pendingToolLoads = new Map<string, Promise<ToolLoadResult>>();
183
+ #sources = new Map<string, SourceMeta>();
184
+ #authStorage: AuthStorage | null = null;
185
+ #onNotification?: (serverName: string, method: string, params: unknown) => void;
186
+ #onToolsChanged?: (tools: CustomTool<TSchema, MCPToolDetails>[]) => void;
187
+ #onResourcesChanged?: (serverName: string, uri: string) => void;
188
+ #onPromptsChanged?: (serverName: string) => void;
189
+ #notificationsEnabled = false;
190
+ #notificationsEpoch = 0;
191
+ #subscribedResources = new Map<string, Set<string>>();
192
+ #pendingResourceRefresh = new Map<string, { connection: MCPServerConnection; promise: Promise<void> }>();
193
+ #pendingReconnections = new Map<string, Promise<MCPServerConnection | null>>();
194
+ /** Preserved configs for reconnection after connection loss. */
195
+ #serverConfigs = new Map<string, MCPServerConfig>();
196
+ /**
197
+ * Timestamps of recent `reconnectServer` invocations per server, used by the
198
+ * crash-storm circuit breaker (see {@link RECONNECT_BURST_LIMIT}).
199
+ */
200
+ #reconnectHistory = new Map<string, number[]>();
201
+ /** Monotonic epoch incremented on disconnectAll to invalidate stale reconnections. */
202
+ #epoch = 0;
203
+
204
+ constructor(
205
+ private cwd: string,
206
+ private toolCache: MCPToolCache | null = null,
207
+ ) {}
208
+
209
+ /**
210
+ * Set a callback to receive all server notifications.
211
+ */
212
+ setOnNotification(handler: (serverName: string, method: string, params: unknown) => void): void {
213
+ this.#onNotification = handler;
214
+ }
215
+
216
+ /**
217
+ * Set a callback to fire when any server's tools change.
218
+ */
219
+ setOnToolsChanged(handler: (tools: CustomTool<TSchema, MCPToolDetails>[]) => void): void {
220
+ this.#onToolsChanged = handler;
221
+ }
222
+
223
+ /**
224
+ * Set a callback to fire when any server's resources change.
225
+ */
226
+ setOnResourcesChanged(handler: (serverName: string, uri: string) => void): void {
227
+ this.#onResourcesChanged = handler;
228
+ }
229
+
230
+ /**
231
+ * Set a callback to fire when any server's prompts change.
232
+ */
233
+ setOnPromptsChanged(handler: (serverName: string) => void): void {
234
+ this.#onPromptsChanged = handler;
235
+ // Fire immediately for servers that already have prompts loaded
236
+ for (const [name, connection] of this.#connections) {
237
+ if (connection.prompts?.length) {
238
+ handler(name);
239
+ }
240
+ }
241
+ }
242
+
243
+ #subscribeAndTrack(name: string, connection: MCPServerConnection, uris: string[], notificationEpoch: number): void {
244
+ void subscribeToResources(connection, uris)
245
+ .then(() => {
246
+ const action = resolveSubscriptionPostAction(
247
+ this.#notificationsEnabled,
248
+ this.#notificationsEpoch,
249
+ notificationEpoch,
250
+ );
251
+ if (action === "rollback") {
252
+ void unsubscribeFromResources(connection, uris).catch(error => {
253
+ logger.debug("Failed to rollback stale MCP resource subscription", {
254
+ path: `mcp:${name}`,
255
+ error,
256
+ });
257
+ });
258
+ return;
259
+ }
260
+ if (action === "ignore") {
261
+ return;
262
+ }
263
+ this.#subscribedResources.set(name, new Set(uris));
264
+ })
265
+ .catch(error => {
266
+ logger.debug("Failed to subscribe to MCP resources", { path: `mcp:${name}`, error });
267
+ });
268
+ }
269
+
270
+ setNotificationsEnabled(enabled: boolean): void {
271
+ const wasEnabled = this.#notificationsEnabled;
272
+ this.#notificationsEnabled = enabled;
273
+ if (enabled === wasEnabled) return;
274
+
275
+ this.#notificationsEpoch += 1;
276
+ const notificationEpoch = this.#notificationsEpoch;
277
+
278
+ if (enabled) {
279
+ // Subscribe to all connected servers that support it
280
+ for (const [name, connection] of this.#connections) {
281
+ if (connection.capabilities.resources?.subscribe && connection.resources) {
282
+ const uris = connection.resources.map(r => r.uri);
283
+ this.#subscribeAndTrack(name, connection, uris, notificationEpoch);
284
+ }
285
+ }
286
+ return;
287
+ }
288
+
289
+ // Unsubscribe from all servers
290
+ for (const [name, connection] of this.#connections) {
291
+ const uris = this.#subscribedResources.get(name);
292
+ if (uris && uris.size > 0) {
293
+ void unsubscribeFromResources(connection, Array.from(uris)).catch(error => {
294
+ logger.debug("Failed to unsubscribe MCP resources", { path: `mcp:${name}`, error });
295
+ });
296
+ }
297
+ }
298
+ this.#subscribedResources.clear();
299
+ }
300
+
301
+ /**
302
+ * Set the auth storage for resolving OAuth credentials.
303
+ */
304
+ setAuthStorage(authStorage: AuthStorage): void {
305
+ this.#authStorage = authStorage;
306
+ }
307
+
308
+ /**
309
+ * Discover and connect to all MCP servers from .mcp.json files.
310
+ * Returns tools and any connection errors.
311
+ */
312
+ async discoverAndConnect(options?: MCPDiscoverOptions): Promise<MCPLoadResult> {
313
+ let loadedConfigs: LoadMCPConfigsResult;
314
+ try {
315
+ loadedConfigs = await loadAllMCPConfigs(this.cwd, {
316
+ enableProjectConfig: options?.enableProjectConfig,
317
+ filterExa: options?.filterExa,
318
+ filterBrowser: options?.filterBrowser,
319
+ });
320
+ } catch (error) {
321
+ const message = error instanceof Error ? error.message : String(error);
322
+ options?.onStatus?.({ type: "failed", serverName: ".mcp.json", error: message });
323
+ throw error;
324
+ }
325
+ const { configs, exaApiKeys, sources } = loadedConfigs;
326
+ const result = await this.connectServers(configs, sources, options?.onStatus);
327
+ result.exaApiKeys = exaApiKeys;
328
+ return result;
329
+ }
330
+
331
+ /**
332
+ * Connect to specific MCP servers.
333
+ * Connections are made in parallel for faster startup.
334
+ */
335
+ async connectServers(
336
+ configs: Record<string, MCPServerConfig>,
337
+ sources: Record<string, SourceMeta>,
338
+ onStatus?: (event: McpConnectionStatusEvent) => void,
339
+ ): Promise<MCPLoadResult> {
340
+ type ConnectionTask = {
341
+ name: string;
342
+ config: MCPServerConfig;
343
+ tracked: TrackedPromise<ToolLoadResult>;
344
+ toolsPromise: Promise<ToolLoadResult>;
345
+ };
346
+
347
+ const errors = new Map<string, string>();
348
+ const connectedServers = new Set<string>();
349
+ const allTools: CustomTool<TSchema, MCPToolDetails>[] = [];
350
+ const reportedErrors = new Set<string>();
351
+ let allowBackgroundLogging = false;
352
+ const statusServerNames: string[] = [];
353
+ const validationFailures: Array<{ name: string; message: string }> = [];
354
+
355
+ // Prepare connection tasks
356
+ const connectionTasks: ConnectionTask[] = [];
357
+
358
+ for (const [name, config] of Object.entries(configs)) {
359
+ if (sources[name]) {
360
+ this.#sources.set(name, sources[name]);
361
+ const existing = this.#connections.get(name);
362
+ if (existing) {
363
+ existing._source = sources[name];
364
+ }
365
+ }
366
+
367
+ // Skip if already connected
368
+ if (this.#connections.has(name)) {
369
+ connectedServers.add(name);
370
+ continue;
371
+ }
372
+
373
+ if (
374
+ this.#pendingConnections.has(name) ||
375
+ this.#pendingToolLoads.has(name) ||
376
+ this.#pendingReconnections.has(name)
377
+ ) {
378
+ continue;
379
+ }
380
+
381
+ statusServerNames.push(name);
382
+
383
+ // Validate config
384
+ const validationErrors = validateServerConfig(name, config);
385
+ if (validationErrors.length > 0) {
386
+ const message = validationErrors.join("; ");
387
+ errors.set(name, message);
388
+ validationFailures.push({ name, message });
389
+ reportedErrors.add(name);
390
+ continue;
391
+ }
392
+
393
+ // Save config early so reconnection works even if the initial connect times out
394
+ // and falls back to cached/deferred tools.
395
+ this.#serverConfigs.set(name, config);
396
+
397
+ // Resolve auth config before connecting, but do so per-server in parallel.
398
+ const connectionPromise = (async () => {
399
+ const resolvedConfig = await this.#resolveAuthConfig(config);
400
+ return connectToServer(name, resolvedConfig, {
401
+ onNotification: (method, params) => {
402
+ this.#handleServerNotification(name, method, params);
403
+ },
404
+ onRequest: (method, params) => {
405
+ return this.#handleServerRequest(method, params);
406
+ },
407
+ });
408
+ })().then(
409
+ connection => {
410
+ // Store original config (without resolved tokens) to keep
411
+ // cache keys stable and avoid leaking rotating credentials.
412
+ connection.config = config;
413
+ this.#serverConfigs.set(name, config);
414
+ if (sources[name]) {
415
+ connection._source = sources[name];
416
+ }
417
+ if (this.#pendingConnections.get(name) === connectionPromise) {
418
+ this.#pendingConnections.delete(name);
419
+ this.#connections.set(name, connection);
420
+ }
421
+
422
+ // Wire auth refresh for HTTP transports so 401s trigger token refresh.
423
+ // Gate on a resolvable managed credential, not on the auth block:
424
+ // definition-only configs (url-keyed fallback) get Bearer injection
425
+ // too and need the same mid-session refresh hook.
426
+ if (
427
+ connection.transport instanceof HttpTransport &&
428
+ lookupMcpOAuthCredential(this.#authStorage, config)
429
+ ) {
430
+ connection.transport.onAuthError = async () => {
431
+ const refreshed = await this.#resolveAuthConfig(config, { forceRefresh: true });
432
+ if (refreshed.type === "http" || refreshed.type === "sse") {
433
+ return refreshed.headers ?? null;
434
+ }
435
+ return null;
436
+ };
437
+ }
438
+
439
+ // Re-establish connection if the transport closes (server restart,
440
+ // network interruption).
441
+ connection.transport.onClose = () => {
442
+ logger.debug("MCP transport lost, triggering reconnect", { path: `mcp:${name}` });
443
+ void this.reconnectServer(name);
444
+ };
445
+
446
+ return connection;
447
+ },
448
+ error => {
449
+ if (this.#pendingConnections.get(name) === connectionPromise) {
450
+ this.#pendingConnections.delete(name);
451
+ }
452
+ throw error;
453
+ },
454
+ );
455
+ this.#pendingConnections.set(name, connectionPromise);
456
+
457
+ const toolsPromise = connectionPromise.then(async connection => {
458
+ const serverTools = await listTools(connection);
459
+ return { connection, serverTools };
460
+ });
461
+ this.#pendingToolLoads.set(name, toolsPromise);
462
+
463
+ const tracked = trackPromise(toolsPromise);
464
+ connectionTasks.push({ name, config, tracked, toolsPromise });
465
+
466
+ void toolsPromise
467
+ .then(async ({ connection, serverTools }) => {
468
+ if (this.#pendingToolLoads.get(name) !== toolsPromise) return;
469
+ this.#pendingToolLoads.delete(name);
470
+ const reconnect = () => this.reconnectServer(name);
471
+ const customTools = MCPTool.fromTools(connection, serverTools, reconnect);
472
+ this.#replaceServerTools(name, customTools);
473
+ this.#onToolsChanged?.(this.#tools);
474
+ void this.toolCache?.set(name, config, serverTools);
475
+
476
+ onStatus?.({ type: "connected", serverName: name });
477
+ await this.#loadServerResourcesAndPrompts(name, connection);
478
+ })
479
+ .catch(error => {
480
+ if (this.#pendingToolLoads.get(name) !== toolsPromise) return;
481
+ this.#pendingToolLoads.delete(name);
482
+ const message = error instanceof Error ? error.message : String(error);
483
+ onStatus?.({ type: "failed", serverName: name, error: message });
484
+ if (!allowBackgroundLogging || reportedErrors.has(name)) return;
485
+ logger.error("MCP tool load failed", { path: `mcp:${name}`, error: message });
486
+ });
487
+ }
488
+
489
+ // Notify about servers we're connecting to, including configs that fail fast.
490
+ if (statusServerNames.length > 0 && onStatus) {
491
+ onStatus({ type: "connecting", serverNames: statusServerNames });
492
+ for (const { name, message } of validationFailures) {
493
+ onStatus({ type: "failed", serverName: name, error: message });
494
+ }
495
+ }
496
+
497
+ if (connectionTasks.length > 0) {
498
+ await Promise.race([
499
+ Promise.allSettled(connectionTasks.map(task => task.tracked.promise)),
500
+ delay(STARTUP_TIMEOUT_MS),
501
+ ]);
502
+
503
+ const cachedTools = new Map<string, MCPToolDefinition[]>();
504
+ const pendingTasks = connectionTasks.filter(task => task.tracked.status === "pending");
505
+
506
+ if (pendingTasks.length > 0 && this.toolCache) {
507
+ await Promise.all(
508
+ pendingTasks.map(async task => {
509
+ const cached = await this.toolCache?.get(task.name, task.config);
510
+ if (cached) {
511
+ cachedTools.set(task.name, cached);
512
+ }
513
+ }),
514
+ );
515
+ }
516
+
517
+ // Pending tasks without cached tools used to be awaited synchronously here,
518
+ // which gated the entire UI on the slowest server's per-request timeout
519
+ // (issue #2100: a single unresponsive MCP server blocked startup for the
520
+ // full 30 s `OMP_MCP_TIMEOUT_MS`). Leave them in flight — the background
521
+ // `void toolsPromise.then(...)` chain above registers their tools and
522
+ // fires `#onToolsChanged` once the connect finishes, or logs the failure
523
+ // after `allowBackgroundLogging` flips below.
524
+
525
+ for (const task of connectionTasks) {
526
+ const { name } = task;
527
+ if (task.tracked.status === "fulfilled") {
528
+ const value = task.tracked.value;
529
+ if (!value) continue;
530
+ const { connection, serverTools } = value;
531
+ connectedServers.add(name);
532
+ const reconnect = () => this.reconnectServer(name);
533
+ allTools.push(...MCPTool.fromTools(connection, serverTools, reconnect));
534
+ } else if (task.tracked.status === "rejected") {
535
+ const message =
536
+ task.tracked.reason instanceof Error ? task.tracked.reason.message : String(task.tracked.reason);
537
+ errors.set(name, message);
538
+ reportedErrors.add(name);
539
+ } else {
540
+ const cached = cachedTools.get(name);
541
+ if (cached) {
542
+ const source = this.#sources.get(name);
543
+ const reconnect = () => this.reconnectServer(name);
544
+ allTools.push(
545
+ ...DeferredMCPTool.fromTools(name, cached, () => this.waitForConnection(name), source, reconnect),
546
+ );
547
+ }
548
+ }
549
+ }
550
+ }
551
+
552
+ // Stable sort by name so the order is independent of connection completion.
553
+ // See `sortMCPToolsByName` for the cache-stability rationale.
554
+ sortMCPToolsByName(allTools);
555
+
556
+ // Update cached tools
557
+ this.#tools = allTools;
558
+ allowBackgroundLogging = true;
559
+
560
+ return {
561
+ tools: allTools,
562
+ errors,
563
+ connectedServers: Array.from(connectedServers),
564
+ exaApiKeys: [], // Will be populated by discoverAndConnect
565
+ };
566
+ }
567
+
568
+ #replaceServerTools(name: string, tools: CustomTool<TSchema, MCPToolDetails>[]): void {
569
+ this.#tools = this.#tools.filter(t => !t.name.startsWith(`mcp__${name}_`));
570
+ this.#tools.push(...tools);
571
+ // Stable sort by name so reconnect order does not perturb the array.
572
+ // See `sortMCPToolsByName` for the cache-stability rationale.
573
+ sortMCPToolsByName(this.#tools);
574
+ }
575
+
576
+ #triggerNotificationRefresh(serverName: string, kind: "tools" | "resources" | "prompts"): void {
577
+ const refresh = (() => {
578
+ switch (kind) {
579
+ case "tools":
580
+ return this.refreshServerTools(serverName);
581
+ case "resources":
582
+ return this.refreshServerResources(serverName);
583
+ case "prompts":
584
+ return this.refreshServerPrompts(serverName);
585
+ }
586
+ })();
587
+ void refresh.catch(error => {
588
+ logger.debug("Failed MCP notification refresh", { path: `mcp:${serverName}`, kind, error });
589
+ });
590
+ }
591
+ #handleServerNotification(serverName: string, method: string, params: unknown): void {
592
+ logger.debug("MCP notification received", { path: `mcp:${serverName}`, method });
593
+
594
+ switch (method) {
595
+ case MCPNotificationMethods.TOOLS_LIST_CHANGED:
596
+ this.#triggerNotificationRefresh(serverName, "tools");
597
+ break;
598
+ case MCPNotificationMethods.RESOURCES_LIST_CHANGED:
599
+ this.#triggerNotificationRefresh(serverName, "resources");
600
+ break;
601
+ case MCPNotificationMethods.RESOURCES_UPDATED: {
602
+ const uri = (params as { uri?: string })?.uri;
603
+ const subscribed = this.#subscribedResources.get(serverName);
604
+ if (uri && subscribed?.has(uri)) {
605
+ this.#onResourcesChanged?.(serverName, uri);
606
+ }
607
+ break;
608
+ }
609
+ case MCPNotificationMethods.PROMPTS_LIST_CHANGED:
610
+ this.#triggerNotificationRefresh(serverName, "prompts");
611
+ break;
612
+ default:
613
+ break;
614
+ }
615
+
616
+ this.#onNotification?.(serverName, method, params);
617
+ }
618
+
619
+ /** Handle server-to-client JSON-RPC requests (e.g. ping, roots/list). */
620
+ async #handleServerRequest(method: string, _params: unknown): Promise<unknown> {
621
+ switch (method) {
622
+ case "ping":
623
+ return {};
624
+ case "roots/list":
625
+ return this.#getRoots();
626
+ default:
627
+ throw Object.assign(new Error(`Unsupported server request: ${method}`), { code: -32601 });
628
+ }
629
+ }
630
+
631
+ #getRoots(): { roots: Array<{ uri: string; name: string }> } {
632
+ return {
633
+ roots: [
634
+ {
635
+ uri: url.pathToFileURL(this.cwd).href,
636
+ name: path.basename(this.cwd),
637
+ },
638
+ ],
639
+ };
640
+ }
641
+
642
+ /**
643
+ * Get all loaded tools.
644
+ */
645
+ getTools(): CustomTool<TSchema, MCPToolDetails>[] {
646
+ return this.#tools;
647
+ }
648
+
649
+ /**
650
+ * Get a specific connection.
651
+ */
652
+ getConnection(name: string): MCPServerConnection | undefined {
653
+ return this.#connections.get(name);
654
+ }
655
+
656
+ /**
657
+ * Get current connection status for a server.
658
+ */
659
+ getConnectionStatus(name: string): "connected" | "connecting" | "disconnected" {
660
+ if (this.#connections.has(name)) return "connected";
661
+ if (
662
+ this.#pendingConnections.has(name) ||
663
+ this.#pendingToolLoads.has(name) ||
664
+ this.#pendingReconnections.has(name)
665
+ )
666
+ return "connecting";
667
+ return "disconnected";
668
+ }
669
+
670
+ /**
671
+ * Get the source metadata for a server.
672
+ */
673
+ getSource(name: string): SourceMeta | undefined {
674
+ return this.#sources.get(name) ?? this.#connections.get(name)?._source;
675
+ }
676
+
677
+ /**
678
+ * Get the preserved (pre-auth) config for a known server — whether currently
679
+ * connected or merely discovered (a connect was attempted but may have failed,
680
+ * e.g. an OAuth server that has not been authorized yet). Mirrors the
681
+ * reconnect lookup at {@link reconnectServer} so callers like `/mcp reauth`
682
+ * can recover a discovered server's config without re-reading config files.
683
+ */
684
+ getServerConfig(name: string): MCPServerConfig | undefined {
685
+ return this.#connections.get(name)?.config ?? this.#serverConfigs.get(name);
686
+ }
687
+
688
+ /**
689
+ * Wait for a connection to complete (or fail).
690
+ */
691
+ async waitForConnection(name: string): Promise<MCPServerConnection> {
692
+ const connection = this.#connections.get(name);
693
+ if (connection) return connection;
694
+ const pending = this.#pendingConnections.get(name);
695
+ if (pending) return pending;
696
+ // If a reconnection is in flight, wait for it to complete
697
+ const reconnecting = this.#pendingReconnections.get(name);
698
+ if (reconnecting) {
699
+ const result = await reconnecting;
700
+ if (result) return result;
701
+ }
702
+ throw new Error(`MCP server not connected: ${name}`);
703
+ }
704
+
705
+ /**
706
+ * Resolve auth and shell-command substitutions in config before connecting.
707
+ * Pass `oauth: false` to skip OAuth credential injection (used by reauth's
708
+ * unauthenticated probe, which must observe the server's bare 401).
709
+ */
710
+ async prepareConfig(config: MCPServerConfig, options?: { oauth?: boolean }): Promise<MCPServerConfig> {
711
+ return this.#resolveAuthConfig(config, options);
712
+ }
713
+
714
+ /**
715
+ * Get all connected server names.
716
+ */
717
+ getConnectedServers(): string[] {
718
+ return Array.from(this.#connections.keys());
719
+ }
720
+
721
+ /**
722
+ * Get all known server names (connected, connecting, or discovered).
723
+ */
724
+ getAllServerNames(): string[] {
725
+ return Array.from(
726
+ new Set([...this.#sources.keys(), ...this.#connections.keys(), ...this.#pendingConnections.keys()]),
727
+ );
728
+ }
729
+
730
+ /**
731
+ * Disconnect from a specific server.
732
+ */
733
+ async disconnectServer(name: string): Promise<void> {
734
+ this.#pendingConnections.delete(name);
735
+ this.#pendingToolLoads.delete(name);
736
+ this.#pendingReconnections.delete(name);
737
+ this.#sources.delete(name);
738
+ this.#serverConfigs.delete(name);
739
+ this.#pendingResourceRefresh.delete(name);
740
+ this.#reconnectHistory.delete(name);
741
+
742
+ const connection = this.#connections.get(name);
743
+
744
+ const subscribedUris = this.#subscribedResources.get(name);
745
+ if (subscribedUris && subscribedUris.size > 0 && connection) {
746
+ void unsubscribeFromResources(connection, Array.from(subscribedUris)).catch(() => {});
747
+ }
748
+ this.#subscribedResources.delete(name);
749
+
750
+ if (connection) {
751
+ // Detach onClose to prevent spurious reconnect from close()
752
+ connection.transport.onClose = undefined;
753
+ await disconnectServer(connection);
754
+ this.#connections.delete(name);
755
+ }
756
+
757
+ // Remove tools from this server and notify consumers
758
+ const hadTools = this.#tools.some(t => t.name.startsWith(`mcp__${name}_`));
759
+ this.#tools = this.#tools.filter(t => !t.name.startsWith(`mcp__${name}_`));
760
+ if (hadTools) this.#onToolsChanged?.(this.#tools);
761
+
762
+ // Notify prompt consumers so stale commands are cleared
763
+ if (connection?.prompts?.length) this.#onPromptsChanged?.(name);
764
+ }
765
+
766
+ /**
767
+ * Disconnect from all servers.
768
+ */
769
+ async disconnectAll(): Promise<void> {
770
+ // Invalidate any in-flight reconnection attempts that outlive this call.
771
+ // They captured the old epoch; after increment they'll detect staleness.
772
+ this.#epoch++;
773
+ // Detach onClose before closing to prevent spurious reconnect attempts
774
+ for (const conn of this.#connections.values()) {
775
+ conn.transport.onClose = undefined;
776
+ }
777
+ const promises = Array.from(this.#connections.values()).map(conn => disconnectServer(conn));
778
+ await Promise.allSettled(promises);
779
+
780
+ this.#pendingConnections.clear();
781
+ this.#pendingToolLoads.clear();
782
+ this.#pendingReconnections.clear();
783
+ this.#pendingResourceRefresh.clear();
784
+ this.#sources.clear();
785
+ this.#serverConfigs.clear();
786
+ this.#connections.clear();
787
+ this.#tools = [];
788
+ this.#subscribedResources.clear();
789
+ this.#reconnectHistory.clear();
790
+ }
791
+
792
+ /**
793
+ * Reconnect to a server after a connection failure.
794
+ *
795
+ * Tears down the stale connection, re-resolves auth, establishes a new
796
+ * connection, reloads tools, and notifies consumers. Concurrent calls for
797
+ * the same server share one reconnection attempt. Returns the new
798
+ * connection, or `null` if reconnection failed or the per-server crash
799
+ * burst limit (see {@link RECONNECT_BURST_LIMIT}) is exceeded.
800
+ *
801
+ * @param options.manual - When `true`, resets the crash-burst window so a
802
+ * user-driven retry (e.g. `/mcp reconnect`) is never blocked by an
803
+ * earlier storm. Defaults to `false`; the transport `onClose` callback
804
+ * and the per-tool-call retry path in `tool-bridge` MUST NOT set it.
805
+ */
806
+ async reconnectServer(name: string, options?: { manual?: boolean }): Promise<MCPServerConnection | null> {
807
+ if (options?.manual) {
808
+ this.#reconnectHistory.delete(name);
809
+ }
810
+
811
+ const pending = this.#pendingReconnections.get(name);
812
+ if (pending) return pending;
813
+
814
+ if (this.#tripReconnectBreaker(name)) {
815
+ return null;
816
+ }
817
+
818
+ const attempt = this.#doReconnect(name);
819
+ this.#pendingReconnections.set(name, attempt);
820
+ return attempt.finally(() => this.#pendingReconnections.delete(name));
821
+ }
822
+
823
+ /**
824
+ * Record a reconnect attempt against the per-server crash window and report
825
+ * whether the circuit breaker is now open. Sliding window: entries older
826
+ * than {@link RECONNECT_BURST_WINDOW_MS} are pruned before the new
827
+ * timestamp is appended, so a single transient failure ages out cheaply
828
+ * but repeated rapid crashes accumulate until the limit is hit.
829
+ */
830
+ #tripReconnectBreaker(name: string): boolean {
831
+ const now = Date.now();
832
+ const previous = this.#reconnectHistory.get(name) ?? [];
833
+ const recent = previous.filter(ts => now - ts < RECONNECT_BURST_WINDOW_MS);
834
+ recent.push(now);
835
+ this.#reconnectHistory.set(name, recent);
836
+
837
+ if (recent.length > RECONNECT_BURST_LIMIT) {
838
+ logger.error("MCP server crashed too many times; suspending automatic reconnects", {
839
+ path: `mcp:${name}`,
840
+ crashes: recent.length,
841
+ windowMs: RECONNECT_BURST_WINDOW_MS,
842
+ });
843
+ // Tear down the stale connection so `getConnectionStatus()` no
844
+ // longer reports it as "connected" and `waitForConnection()` does
845
+ // not hand a closed transport to callers. Tools stay registered
846
+ // in `#tools` — the user can recover with `/mcp reconnect <name>`
847
+ // once they've fixed the underlying misconfiguration. Mirrors the
848
+ // teardown in `#doReconnect`: detach `onClose` first so the
849
+ // transport's own `close()` cannot re-arm this path.
850
+ const stale = this.#connections.get(name);
851
+ if (stale) {
852
+ stale.transport.onClose = undefined;
853
+ void stale.transport.close().catch(() => {});
854
+ this.#connections.delete(name);
855
+ }
856
+ this.#pendingConnections.delete(name);
857
+ this.#pendingToolLoads.delete(name);
858
+ return true;
859
+ }
860
+ return false;
861
+ }
862
+
863
+ async #doReconnect(name: string): Promise<MCPServerConnection | null> {
864
+ const oldConnection = this.#connections.get(name);
865
+ const config = oldConnection?.config ?? this.#serverConfigs.get(name);
866
+ const source = this.#sources.get(name) ?? oldConnection?._source;
867
+ if (!config) return null;
868
+
869
+ logger.debug("MCP reconnecting", { path: `mcp:${name}` });
870
+
871
+ // Close the old transport without removing tools or notifying consumers.
872
+ // Tools stay available (stale) while we establish the new connection.
873
+ // Fire-and-forget: don't await the close — HttpTransport.close() sends a
874
+ // DELETE with config.timeout (30s default), and blocking here delays the
875
+ // reconnect loop by that amount on every server restart.
876
+ const reconnectEpoch = this.#epoch;
877
+ if (oldConnection) {
878
+ // Detach onClose to prevent re-entrant reconnect from the close itself
879
+ oldConnection.transport.onClose = undefined;
880
+ void oldConnection.transport.close().catch(() => {});
881
+ this.#connections.delete(name);
882
+ }
883
+ this.#pendingConnections.delete(name);
884
+ this.#pendingToolLoads.delete(name);
885
+
886
+ // Retry with backoff — the server may still be starting up.
887
+ const delays = [500, 1000, 2000, 4000];
888
+ for (let attempt = 0; attempt <= delays.length; attempt++) {
889
+ if (this.#epoch !== reconnectEpoch) {
890
+ logger.debug("MCP reconnect aborted before attempt after configuration changed", {
891
+ path: `mcp:${name}`,
892
+ storedEpoch: reconnectEpoch,
893
+ currentEpoch: this.#epoch,
894
+ });
895
+ return null;
896
+ }
897
+ try {
898
+ const connection = await this.#connectAndWireServer(name, config, source, reconnectEpoch);
899
+ logger.debug("MCP reconnected", { path: `mcp:${name}`, tools: connection.tools?.length ?? 0 });
900
+ return connection;
901
+ } catch (error) {
902
+ if (this.#epoch !== reconnectEpoch) {
903
+ logger.debug("MCP reconnect aborted after configuration changed", {
904
+ path: `mcp:${name}`,
905
+ storedEpoch: reconnectEpoch,
906
+ currentEpoch: this.#epoch,
907
+ });
908
+ return null;
909
+ }
910
+
911
+ const msg = error instanceof Error ? error.message : String(error);
912
+ if (attempt < delays.length) {
913
+ logger.debug("MCP reconnect attempt failed, retrying", {
914
+ path: `mcp:${name}`,
915
+ attempt: attempt + 1,
916
+ error: msg,
917
+ });
918
+ await Bun.sleep(delays[attempt]);
919
+ } else {
920
+ logger.error("MCP reconnect failed after retries", { path: `mcp:${name}`, error: msg });
921
+ // Don't remove stale tools — keep them in the registry so they
922
+ // remain selected. Calls will fail with MCP errors, which
923
+ // triggers the tool-level reconnect, or the user can run
924
+ // /mcp reconnect <name> manually.
925
+ }
926
+ }
927
+ }
928
+ return null;
929
+ }
930
+
931
+ /** Establish a new connection to a server, wire handlers, load tools. */
932
+ async #connectAndWireServer(
933
+ name: string,
934
+ config: MCPServerConfig,
935
+ source: SourceMeta | undefined,
936
+ reconnectEpoch: number,
937
+ ): Promise<MCPServerConnection> {
938
+ const resolvedConfig = await this.#resolveAuthConfig(config);
939
+ const connection = await connectToServer(name, resolvedConfig, {
940
+ onNotification: (method, params) => {
941
+ this.#handleServerNotification(name, method, params);
942
+ },
943
+ onRequest: (method, params) => {
944
+ return this.#handleServerRequest(method, params);
945
+ },
946
+ });
947
+
948
+ connection.config = config;
949
+ if (source) connection._source = source;
950
+
951
+ // Bail out if the server was disconnected or the manager was reset
952
+ // while we were connecting (e.g. /mcp reload called disconnectAll).
953
+ if (!this.#serverConfigs.has(name) || this.#epoch !== reconnectEpoch) {
954
+ await connection.transport.close().catch(() => {});
955
+ throw new Error(`Server "${name}" was disconnected during reconnection`);
956
+ }
957
+
958
+ this.#connections.set(name, connection);
959
+
960
+ // Wire auth refresh for HTTP transports, and reconnect for any transport.
961
+ // Same gate as connectServers: any resolvable managed credential.
962
+ if (connection.transport instanceof HttpTransport && lookupMcpOAuthCredential(this.#authStorage, config)) {
963
+ connection.transport.onAuthError = async () => {
964
+ const refreshed = await this.#resolveAuthConfig(config, { forceRefresh: true });
965
+ if (refreshed.type === "http" || refreshed.type === "sse") {
966
+ return refreshed.headers ?? null;
967
+ }
968
+ return null;
969
+ };
970
+ }
971
+ connection.transport.onClose = () => {
972
+ logger.debug("MCP transport lost, triggering reconnect", { path: `mcp:${name}` });
973
+ void this.reconnectServer(name);
974
+ };
975
+ try {
976
+ const serverTools = await listTools(connection);
977
+ const reconnect = () => this.reconnectServer(name);
978
+ const customTools = MCPTool.fromTools(connection, serverTools, reconnect);
979
+ void this.toolCache?.set(name, config, serverTools);
980
+ this.#replaceServerTools(name, customTools);
981
+ this.#onToolsChanged?.(this.#tools);
982
+ void this.#loadServerResourcesAndPrompts(name, connection);
983
+ return connection;
984
+ } catch (error) {
985
+ // Clean up the connection to avoid zombie transports
986
+ connection.transport.onClose = undefined;
987
+ await connection.transport.close().catch(() => {});
988
+ this.#connections.delete(name);
989
+ throw error;
990
+ }
991
+ }
992
+
993
+ /**
994
+ * Best-effort loading of resources, resource subscriptions, and prompts.
995
+ * Shared between initial connection and reconnection.
996
+ */
997
+ async #loadServerResourcesAndPrompts(name: string, connection: MCPServerConnection): Promise<void> {
998
+ if (serverSupportsResources(connection.capabilities)) {
999
+ try {
1000
+ const [resources] = await Promise.all([listResources(connection), listResourceTemplates(connection)]);
1001
+
1002
+ if (this.#notificationsEnabled && connection.capabilities.resources?.subscribe) {
1003
+ const uris = resources.map(r => r.uri);
1004
+ const notificationEpoch = this.#notificationsEpoch;
1005
+ this.#subscribeAndTrack(name, connection, uris, notificationEpoch);
1006
+ }
1007
+ } catch (error) {
1008
+ logger.debug("Failed to load MCP resources", { path: `mcp:${name}`, error });
1009
+ }
1010
+ }
1011
+
1012
+ if (serverSupportsPrompts(connection.capabilities)) {
1013
+ try {
1014
+ await listPrompts(connection);
1015
+ this.#onPromptsChanged?.(name);
1016
+ } catch (error) {
1017
+ logger.debug("Failed to load MCP prompts", { path: `mcp:${name}`, error });
1018
+ }
1019
+ }
1020
+ }
1021
+
1022
+ /**
1023
+ * Refresh tools from a specific server.
1024
+ */
1025
+ async refreshServerTools(name: string): Promise<void> {
1026
+ const connection = this.#connections.get(name);
1027
+ if (!connection) return;
1028
+
1029
+ // Clear cached tools
1030
+ connection.tools = undefined;
1031
+
1032
+ // Reload tools
1033
+ const serverTools = await listTools(connection);
1034
+ const reconnect = () => this.reconnectServer(name);
1035
+ const customTools = MCPTool.fromTools(connection, serverTools, reconnect);
1036
+ void this.toolCache?.set(name, connection.config, serverTools);
1037
+
1038
+ // Replace tools from this server
1039
+ this.#replaceServerTools(name, customTools);
1040
+ this.#onToolsChanged?.(this.#tools);
1041
+ }
1042
+
1043
+ /**
1044
+ * Refresh tools from all servers.
1045
+ */
1046
+ async refreshAllTools(): Promise<void> {
1047
+ const promises = Array.from(this.#connections.keys()).map(name => this.refreshServerTools(name));
1048
+ await Promise.allSettled(promises);
1049
+ }
1050
+
1051
+ /**
1052
+ * Refresh resources from a specific server.
1053
+ */
1054
+ async refreshServerResources(name: string): Promise<void> {
1055
+ const connection = this.#connections.get(name);
1056
+ if (!connection || !serverSupportsResources(connection.capabilities)) return;
1057
+
1058
+ const existing = this.#pendingResourceRefresh.get(name);
1059
+ if (existing && existing.connection === connection) return existing.promise;
1060
+
1061
+ const doRefresh = async (): Promise<void> => {
1062
+ // Clear cached resources
1063
+ connection.resources = undefined;
1064
+ connection.resourceTemplates = undefined;
1065
+
1066
+ // Reload
1067
+ const [resources] = await Promise.all([listResources(connection), listResourceTemplates(connection)]);
1068
+ if (this.#notificationsEnabled && connection.capabilities.resources?.subscribe) {
1069
+ const newUris = new Set(resources.map(r => r.uri));
1070
+ const oldUris = this.#subscribedResources.get(name);
1071
+ const notificationEpoch = this.#notificationsEpoch;
1072
+
1073
+ // Unsubscribe URIs that were removed
1074
+ if (oldUris) {
1075
+ const removed = [...oldUris].filter(uri => !newUris.has(uri));
1076
+ if (removed.length > 0) {
1077
+ try {
1078
+ await unsubscribeFromResources(connection, removed);
1079
+ } catch (error) {
1080
+ logger.debug("Failed to unsubscribe stale MCP resources", { path: `mcp:${name}`, error });
1081
+ }
1082
+ }
1083
+ }
1084
+
1085
+ // Subscribe to the current set and update tracking atomically
1086
+ try {
1087
+ const allUris = [...newUris];
1088
+ await subscribeToResources(connection, allUris);
1089
+ const action = resolveSubscriptionPostAction(
1090
+ this.#notificationsEnabled,
1091
+ this.#notificationsEpoch,
1092
+ notificationEpoch,
1093
+ );
1094
+ if (action === "rollback") {
1095
+ await unsubscribeFromResources(connection, allUris).catch(error => {
1096
+ logger.debug("Failed to rollback stale MCP resource subscription", { path: `mcp:${name}`, error });
1097
+ });
1098
+ return;
1099
+ }
1100
+ if (action === "ignore") {
1101
+ return;
1102
+ }
1103
+ this.#subscribedResources.set(name, newUris);
1104
+ } catch (error) {
1105
+ logger.debug("Failed to re-subscribe to MCP resources", { path: `mcp:${name}`, error });
1106
+ }
1107
+ }
1108
+ };
1109
+
1110
+ const promise = doRefresh().finally(() => {
1111
+ const pending = this.#pendingResourceRefresh.get(name);
1112
+ if (pending?.promise === promise) {
1113
+ this.#pendingResourceRefresh.delete(name);
1114
+ }
1115
+ });
1116
+ this.#pendingResourceRefresh.set(name, { connection, promise });
1117
+ return promise;
1118
+ }
1119
+
1120
+ /**
1121
+ * Refresh prompts from a specific server.
1122
+ */
1123
+ async refreshServerPrompts(name: string): Promise<void> {
1124
+ const connection = this.#connections.get(name);
1125
+ if (!connection || !serverSupportsPrompts(connection.capabilities)) return;
1126
+
1127
+ connection.prompts = undefined;
1128
+ await listPrompts(connection);
1129
+
1130
+ this.#onPromptsChanged?.(name);
1131
+ }
1132
+
1133
+ /**
1134
+ * Get resources and templates for a specific server.
1135
+ */
1136
+ getServerResources(name: string): { resources: MCPResource[]; templates: MCPResourceTemplate[] } | undefined {
1137
+ const connection = this.#connections.get(name);
1138
+ if (!connection) return undefined;
1139
+ return {
1140
+ resources: connection.resources ?? [],
1141
+ templates: connection.resourceTemplates ?? [],
1142
+ };
1143
+ }
1144
+
1145
+ /**
1146
+ * Read a specific resource from a server.
1147
+ */
1148
+ async readServerResource(
1149
+ name: string,
1150
+ uri: string,
1151
+ options?: MCPRequestOptions,
1152
+ ): Promise<MCPResourceReadResult | undefined> {
1153
+ const connection = this.#connections.get(name);
1154
+ if (!connection) return undefined;
1155
+ return readResource(connection, uri, options);
1156
+ }
1157
+
1158
+ /**
1159
+ * Get prompts for a specific server.
1160
+ */
1161
+ getServerPrompts(name: string): MCPPrompt[] | undefined {
1162
+ const connection = this.#connections.get(name);
1163
+ if (!connection) return undefined;
1164
+ return connection.prompts ?? [];
1165
+ }
1166
+
1167
+ /**
1168
+ * Get a specific prompt from a server.
1169
+ */
1170
+ async executePrompt(
1171
+ name: string,
1172
+ promptName: string,
1173
+ args?: Record<string, string>,
1174
+ options?: MCPRequestOptions,
1175
+ ): Promise<MCPGetPromptResult | undefined> {
1176
+ const connection = this.#connections.get(name);
1177
+ if (!connection) return undefined;
1178
+ return getPrompt(connection, promptName, args, options);
1179
+ }
1180
+
1181
+ /**
1182
+ * Get all server instructions (for system prompt injection).
1183
+ */
1184
+ getServerInstructions(): Map<string, string> {
1185
+ const instructions = new Map<string, string>();
1186
+ for (const [name, connection] of this.#connections) {
1187
+ if (connection.instructions) {
1188
+ instructions.set(name, connection.instructions);
1189
+ }
1190
+ }
1191
+ return instructions;
1192
+ }
1193
+
1194
+ /**
1195
+ * Get notification state for display.
1196
+ */
1197
+ getNotificationState(): { enabled: boolean; subscriptions: Map<string, ReadonlySet<string>> } {
1198
+ return {
1199
+ enabled: this.#notificationsEnabled,
1200
+ subscriptions: this.#subscribedResources as Map<string, ReadonlySet<string>>,
1201
+ };
1202
+ }
1203
+
1204
+ /**
1205
+ * Resolve OAuth credentials and shell commands in config.
1206
+ * `oauth: false` skips credential injection (reauth's unauthenticated probe);
1207
+ * `forceRefresh` bypasses the expiry buffer (401/403 auth-error hook).
1208
+ */
1209
+ async #resolveAuthConfig(
1210
+ config: MCPServerConfig,
1211
+ opts?: { forceRefresh?: boolean; oauth?: boolean },
1212
+ ): Promise<MCPServerConfig> {
1213
+ let resolved: MCPServerConfig = { ...config };
1214
+
1215
+ const auth = config.auth;
1216
+ const lookup: MCPOAuthCredentialLookup | undefined =
1217
+ opts?.oauth !== false ? lookupMcpOAuthCredential(this.#authStorage, config) : undefined;
1218
+ if (lookup && this.#authStorage) {
1219
+ const { credentialId } = lookup;
1220
+ try {
1221
+ let credential: MCPStoredOAuthCredential | undefined = lookup.credential;
1222
+ // Refresh material comes from ONE source: the credential's embedded
1223
+ // fields (written atomically with the tokens they minted — tokenUrl
1224
+ // always present) or, for legacy rows that predate embedding, the
1225
+ // config auth block. Never mix the two: a shared file's auth block
1226
+ // can belong to another profile, whose client the grant is NOT
1227
+ // bound to.
1228
+ const material = selectMcpOAuthRefreshMaterial(credential, auth);
1229
+ const tokenUrl = material?.tokenUrl;
1230
+ const clientId = material?.clientId;
1231
+ const clientSecret = material?.clientSecret;
1232
+ const resource =
1233
+ material?.resource ?? (config.type === "http" || config.type === "sse" ? config.url : undefined);
1234
+ // Proactive refresh: 5-minute buffer before expiry
1235
+ // Force refresh: on 401/403 auth errors (revoked tokens, clock skew, missing expires)
1236
+ const REFRESH_BUFFER_MS = 5 * 60_000;
1237
+ const shouldRefresh =
1238
+ opts?.forceRefresh || (credential.expires && Date.now() >= credential.expires - REFRESH_BUFFER_MS);
1239
+ if (shouldRefresh && credential.refresh && tokenUrl) {
1240
+ try {
1241
+ const refreshed = await refreshMCPOAuthToken(
1242
+ tokenUrl,
1243
+ credential.refresh,
1244
+ clientId,
1245
+ clientSecret,
1246
+ resource,
1247
+ );
1248
+ // Spread the old credential first so embedded refresh material survives rotation.
1249
+ const refreshedCredential: MCPStoredOAuthCredential = {
1250
+ ...credential,
1251
+ ...refreshed,
1252
+ tokenUrl,
1253
+ clientId,
1254
+ clientSecret,
1255
+ resource,
1256
+ };
1257
+ await this.#authStorage.set(credentialId, refreshedCredential);
1258
+ credential = refreshedCredential;
1259
+ } catch (refreshError) {
1260
+ const errorMsg = refreshError instanceof Error ? refreshError.message : String(refreshError);
1261
+ if (isDefinitiveOAuthFailure(errorMsg)) {
1262
+ // `invalid_grant` / `invalid_token` / 401 from the token endpoint means
1263
+ // the server has retired this credential — keeping the stale access
1264
+ // token would just re-fail with 401 on every MCP request and leave a
1265
+ // poisoned row in agent.db that survives restarts. Drop it now so the
1266
+ // next connect attempt surfaces a clean "needs reauth" failure and
1267
+ // the user can recover with `/mcp reauth <server>` (or `/mcp unauth`
1268
+ // to forget the server entirely).
1269
+ logger.warn("MCP OAuth refresh failed definitively; cleared credential", {
1270
+ credentialId,
1271
+ error: errorMsg,
1272
+ });
1273
+ await this.#authStorage.remove(credentialId);
1274
+ credential = undefined;
1275
+ } else {
1276
+ logger.warn("MCP OAuth refresh failed, using existing token", {
1277
+ credentialId,
1278
+ error: refreshError,
1279
+ });
1280
+ }
1281
+ }
1282
+ }
1283
+
1284
+ if (credential) {
1285
+ if (resolved.type === "http" || resolved.type === "sse") {
1286
+ resolved = {
1287
+ ...resolved,
1288
+ headers: {
1289
+ ...resolved.headers,
1290
+ Authorization: `Bearer ${credential.access}`,
1291
+ },
1292
+ };
1293
+ } else {
1294
+ resolved = {
1295
+ ...resolved,
1296
+ env: {
1297
+ ...resolved.env,
1298
+ OAUTH_ACCESS_TOKEN: credential.access,
1299
+ },
1300
+ };
1301
+ }
1302
+ }
1303
+ } catch (error) {
1304
+ logger.warn("Failed to resolve OAuth credential", { credentialId, error });
1305
+ }
1306
+ }
1307
+
1308
+ if (resolved.type !== "http" && resolved.type !== "sse") {
1309
+ if (resolved.env) {
1310
+ const nextEnv: Record<string, string> = {};
1311
+ for (const [key, value] of Object.entries(resolved.env)) {
1312
+ const resolvedValue = await resolveConfigValue(value);
1313
+ if (resolvedValue) nextEnv[key] = resolvedValue;
1314
+ }
1315
+ resolved = { ...resolved, env: nextEnv };
1316
+ }
1317
+ } else {
1318
+ if (resolved.headers) {
1319
+ const nextHeaders: Record<string, string> = {};
1320
+ for (const [key, value] of Object.entries(resolved.headers)) {
1321
+ const resolvedValue = await resolveConfigValue(value);
1322
+ if (resolvedValue) nextHeaders[key] = resolvedValue;
1323
+ }
1324
+ resolved = { ...resolved, headers: nextHeaders };
1325
+ }
1326
+ }
1327
+
1328
+ return resolved;
1329
+ }
1330
+ }
1331
+
1332
+ /**
1333
+ * Create an MCP manager and discover servers.
1334
+ * Convenience function for quick setup.
1335
+ */
1336
+ export async function createMCPManager(
1337
+ cwd: string,
1338
+ options?: MCPDiscoverOptions,
1339
+ ): Promise<{
1340
+ manager: MCPManager;
1341
+ result: MCPLoadResult;
1342
+ }> {
1343
+ const manager = new MCPManager(cwd);
1344
+ const result = await manager.discoverAndConnect(options);
1345
+ return { manager, result };
1346
+ }