@f5-sales-demo/xcsh 19.51.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (899) hide show
  1. package/CHANGELOG.md +7073 -0
  2. package/README.md +14 -0
  3. package/examples/README.md +21 -0
  4. package/examples/custom-tools/README.md +109 -0
  5. package/examples/custom-tools/hello/index.ts +20 -0
  6. package/examples/custom-tools/todo/index.ts +206 -0
  7. package/examples/extensions/README.md +143 -0
  8. package/examples/extensions/api-demo.ts +89 -0
  9. package/examples/extensions/chalk-logger.ts +25 -0
  10. package/examples/extensions/hello.ts +32 -0
  11. package/examples/extensions/pirate.ts +43 -0
  12. package/examples/extensions/plan-mode.ts +551 -0
  13. package/examples/extensions/reload-runtime.ts +37 -0
  14. package/examples/extensions/todo.ts +296 -0
  15. package/examples/extensions/tools.ts +145 -0
  16. package/examples/extensions/with-deps/index.ts +36 -0
  17. package/examples/extensions/with-deps/package-lock.json +31 -0
  18. package/examples/extensions/with-deps/package.json +16 -0
  19. package/examples/hooks/README.md +56 -0
  20. package/examples/hooks/auto-commit-on-exit.ts +48 -0
  21. package/examples/hooks/confirm-destructive.ts +58 -0
  22. package/examples/hooks/custom-compaction.ts +115 -0
  23. package/examples/hooks/dirty-repo-guard.ts +51 -0
  24. package/examples/hooks/file-trigger.ts +40 -0
  25. package/examples/hooks/git-checkpoint.ts +52 -0
  26. package/examples/hooks/handoff.ts +149 -0
  27. package/examples/hooks/permission-gate.ts +33 -0
  28. package/examples/hooks/protected-paths.ts +29 -0
  29. package/examples/hooks/qna.ts +118 -0
  30. package/examples/hooks/status-line.ts +39 -0
  31. package/examples/sdk/01-minimal.ts +21 -0
  32. package/examples/sdk/02-custom-model.ts +49 -0
  33. package/examples/sdk/03-custom-prompt.ts +43 -0
  34. package/examples/sdk/04-skills.ts +43 -0
  35. package/examples/sdk/06-extensions.ts +80 -0
  36. package/examples/sdk/06-hooks.ts +61 -0
  37. package/examples/sdk/07-context-files.ts +35 -0
  38. package/examples/sdk/08-prompt-templates.ts +41 -0
  39. package/examples/sdk/08-slash-commands.ts +46 -0
  40. package/examples/sdk/09-api-keys-and-oauth.ts +54 -0
  41. package/examples/sdk/11-sessions.ts +47 -0
  42. package/examples/sdk/README.md +172 -0
  43. package/package.json +539 -0
  44. package/scripts/build-info/resolvers.ts +51 -0
  45. package/scripts/capture-ax-fixture.ts +84 -0
  46. package/scripts/capture-login-fixture.ts +30 -0
  47. package/scripts/check-workflow-field-coverage.ts +101 -0
  48. package/scripts/extension-uat-harness.ts +340 -0
  49. package/scripts/format-prompts.ts +68 -0
  50. package/scripts/generate-api-spec-index.ts +580 -0
  51. package/scripts/generate-branding-index.ts +81 -0
  52. package/scripts/generate-build-info.ts +106 -0
  53. package/scripts/generate-console-catalog.ts +88 -0
  54. package/scripts/generate-console-field-metadata.ts +74 -0
  55. package/scripts/generate-docs-index.ts +40 -0
  56. package/scripts/generate-template.ts +32 -0
  57. package/scripts/generate-terraform-index.ts +81 -0
  58. package/scripts/mermaid-gallery.ts +132 -0
  59. package/scripts/uat-matrix-modalities.ts +451 -0
  60. package/scripts/uat-matrix-report.ts +175 -0
  61. package/scripts/uat-matrix.ts +353 -0
  62. package/src/async/index.ts +2 -0
  63. package/src/async/job-manager.ts +416 -0
  64. package/src/async/support.ts +5 -0
  65. package/src/autoresearch/apply-contract-to-state.ts +1 -0
  66. package/src/autoresearch/command-resume.md +17 -0
  67. package/src/autoresearch/contract.ts +205 -0
  68. package/src/autoresearch/dashboard.ts +374 -0
  69. package/src/autoresearch/git.ts +191 -0
  70. package/src/autoresearch/helpers.ts +328 -0
  71. package/src/autoresearch/index.ts +402 -0
  72. package/src/autoresearch/prompt.md +236 -0
  73. package/src/autoresearch/resume-message.md +16 -0
  74. package/src/autoresearch/state.ts +303 -0
  75. package/src/autoresearch/tools/init-experiment.ts +400 -0
  76. package/src/autoresearch/tools/log-experiment.ts +793 -0
  77. package/src/autoresearch/tools/run-experiment.ts +679 -0
  78. package/src/autoresearch/types.ts +114 -0
  79. package/src/browser/acquire.ts +249 -0
  80. package/src/browser/actions.ts +126 -0
  81. package/src/browser/auth.ts +176 -0
  82. package/src/browser/ax.ts +134 -0
  83. package/src/browser/cdp-core.ts +45 -0
  84. package/src/browser/cdp-page-actions.ts +51 -0
  85. package/src/browser/chrome-locate.ts +66 -0
  86. package/src/browser/dom-context.ts +89 -0
  87. package/src/browser/dt-context.ts +100 -0
  88. package/src/browser/extension-bridge.ts +182 -0
  89. package/src/browser/extension-page-actions.ts +397 -0
  90. package/src/browser/extension-provider.ts +373 -0
  91. package/src/browser/index.ts +17 -0
  92. package/src/browser/input-commit.ts +74 -0
  93. package/src/browser/native-messaging.ts +20 -0
  94. package/src/browser/page-actions.ts +18 -0
  95. package/src/browser/provider.ts +155 -0
  96. package/src/browser/resolver.ts +126 -0
  97. package/src/browser/selector.ts +40 -0
  98. package/src/bun-imports.d.ts +22 -0
  99. package/src/capability/context-file.ts +43 -0
  100. package/src/capability/extension-module.ts +34 -0
  101. package/src/capability/extension.ts +47 -0
  102. package/src/capability/fs.ts +107 -0
  103. package/src/capability/hook.ts +40 -0
  104. package/src/capability/index.ts +438 -0
  105. package/src/capability/instruction.ts +37 -0
  106. package/src/capability/mcp.ts +74 -0
  107. package/src/capability/prompt.ts +35 -0
  108. package/src/capability/rule.ts +224 -0
  109. package/src/capability/settings.ts +34 -0
  110. package/src/capability/skill.ts +50 -0
  111. package/src/capability/slash-command.ts +40 -0
  112. package/src/capability/ssh.ts +41 -0
  113. package/src/capability/system-prompt.ts +34 -0
  114. package/src/capability/tool.ts +38 -0
  115. package/src/capability/types.ts +168 -0
  116. package/src/cli/agents-cli.ts +138 -0
  117. package/src/cli/args.ts +286 -0
  118. package/src/cli/chrome-cli.ts +88 -0
  119. package/src/cli/classify-install-target.ts +50 -0
  120. package/src/cli/commands/init-xdg.ts +27 -0
  121. package/src/cli/config-cli.ts +418 -0
  122. package/src/cli/file-processor.ts +121 -0
  123. package/src/cli/grep-cli.ts +160 -0
  124. package/src/cli/grievances-cli.ts +78 -0
  125. package/src/cli/initial-message.ts +58 -0
  126. package/src/cli/jupyter-cli.ts +106 -0
  127. package/src/cli/list-models.ts +128 -0
  128. package/src/cli/plugin-cli.ts +964 -0
  129. package/src/cli/read-cli.ts +68 -0
  130. package/src/cli/session-picker.ts +52 -0
  131. package/src/cli/setup-cli.ts +479 -0
  132. package/src/cli/shell-cli.ts +174 -0
  133. package/src/cli/ssh-cli.ts +179 -0
  134. package/src/cli/stats-cli.ts +182 -0
  135. package/src/cli/update-cli.ts +446 -0
  136. package/src/cli/web-search-cli.ts +203 -0
  137. package/src/cli.ts +123 -0
  138. package/src/commands/agents.ts +57 -0
  139. package/src/commands/chrome-host.ts +71 -0
  140. package/src/commands/chrome.ts +28 -0
  141. package/src/commands/commit.ts +36 -0
  142. package/src/commands/config.ts +51 -0
  143. package/src/commands/grep.ts +48 -0
  144. package/src/commands/grievances.ts +20 -0
  145. package/src/commands/jupyter.ts +32 -0
  146. package/src/commands/launch.ts +144 -0
  147. package/src/commands/plugin.ts +78 -0
  148. package/src/commands/read.ts +33 -0
  149. package/src/commands/setup.ts +42 -0
  150. package/src/commands/shell.ts +29 -0
  151. package/src/commands/ssh.ts +60 -0
  152. package/src/commands/stats.ts +29 -0
  153. package/src/commands/update.ts +21 -0
  154. package/src/commands/web-search.ts +46 -0
  155. package/src/commit/agentic/agent.ts +314 -0
  156. package/src/commit/agentic/fallback.ts +96 -0
  157. package/src/commit/agentic/index.ts +354 -0
  158. package/src/commit/agentic/prompts/analyze-file.md +22 -0
  159. package/src/commit/agentic/prompts/session-user.md +25 -0
  160. package/src/commit/agentic/prompts/split-confirm.md +1 -0
  161. package/src/commit/agentic/prompts/system.md +38 -0
  162. package/src/commit/agentic/state.ts +60 -0
  163. package/src/commit/agentic/tools/analyze-file.ts +127 -0
  164. package/src/commit/agentic/tools/git-file-diff.ts +191 -0
  165. package/src/commit/agentic/tools/git-hunk.ts +50 -0
  166. package/src/commit/agentic/tools/git-overview.ts +81 -0
  167. package/src/commit/agentic/tools/index.ts +54 -0
  168. package/src/commit/agentic/tools/propose-changelog.ts +139 -0
  169. package/src/commit/agentic/tools/propose-commit.ts +122 -0
  170. package/src/commit/agentic/tools/recent-commits.ts +81 -0
  171. package/src/commit/agentic/tools/schemas.ts +31 -0
  172. package/src/commit/agentic/tools/split-commit.ts +251 -0
  173. package/src/commit/agentic/topo-sort.ts +44 -0
  174. package/src/commit/agentic/trivial.ts +51 -0
  175. package/src/commit/agentic/validation.ts +183 -0
  176. package/src/commit/analysis/conventional.ts +122 -0
  177. package/src/commit/analysis/index.ts +4 -0
  178. package/src/commit/analysis/scope.ts +242 -0
  179. package/src/commit/analysis/summary.ts +105 -0
  180. package/src/commit/analysis/validation.ts +66 -0
  181. package/src/commit/changelog/detect.ts +40 -0
  182. package/src/commit/changelog/generate.ts +101 -0
  183. package/src/commit/changelog/index.ts +234 -0
  184. package/src/commit/changelog/parse.ts +44 -0
  185. package/src/commit/cli.ts +85 -0
  186. package/src/commit/git/diff.ts +148 -0
  187. package/src/commit/index.ts +5 -0
  188. package/src/commit/map-reduce/index.ts +69 -0
  189. package/src/commit/map-reduce/map-phase.ts +193 -0
  190. package/src/commit/map-reduce/reduce-phase.ts +108 -0
  191. package/src/commit/map-reduce/utils.ts +9 -0
  192. package/src/commit/message.ts +11 -0
  193. package/src/commit/model-selection.ts +66 -0
  194. package/src/commit/pipeline.ts +242 -0
  195. package/src/commit/prompts/analysis-system.md +148 -0
  196. package/src/commit/prompts/analysis-user.md +38 -0
  197. package/src/commit/prompts/changelog-system.md +50 -0
  198. package/src/commit/prompts/changelog-user.md +18 -0
  199. package/src/commit/prompts/file-observer-system.md +24 -0
  200. package/src/commit/prompts/file-observer-user.md +8 -0
  201. package/src/commit/prompts/reduce-system.md +50 -0
  202. package/src/commit/prompts/reduce-user.md +17 -0
  203. package/src/commit/prompts/summary-retry.md +3 -0
  204. package/src/commit/prompts/summary-system.md +38 -0
  205. package/src/commit/prompts/summary-user.md +13 -0
  206. package/src/commit/prompts/types-description.md +2 -0
  207. package/src/commit/types.ts +118 -0
  208. package/src/commit/utils/exclusions.ts +42 -0
  209. package/src/commit/utils.ts +44 -0
  210. package/src/config/auto-config.ts +698 -0
  211. package/src/config/context-schema.json +115 -0
  212. package/src/config/file-lock.ts +121 -0
  213. package/src/config/keybindings.ts +493 -0
  214. package/src/config/mcp-schema.json +230 -0
  215. package/src/config/model-equivalence.ts +675 -0
  216. package/src/config/model-registry.ts +2265 -0
  217. package/src/config/model-resolver.ts +1289 -0
  218. package/src/config/prompt-templates.ts +271 -0
  219. package/src/config/resolve-config-value.ts +110 -0
  220. package/src/config/settings-schema.ts +2155 -0
  221. package/src/config/settings.ts +730 -0
  222. package/src/config.ts +418 -0
  223. package/src/cursor.ts +323 -0
  224. package/src/dap/client.ts +674 -0
  225. package/src/dap/config.ts +150 -0
  226. package/src/dap/defaults.json +211 -0
  227. package/src/dap/index.ts +4 -0
  228. package/src/dap/session.ts +1255 -0
  229. package/src/dap/types.ts +600 -0
  230. package/src/debug/index.ts +440 -0
  231. package/src/debug/log-formatting.ts +58 -0
  232. package/src/debug/log-viewer.ts +908 -0
  233. package/src/debug/profiler.ts +158 -0
  234. package/src/debug/report-bundle.ts +365 -0
  235. package/src/debug/system-info.ts +107 -0
  236. package/src/discovery/agents-md.ts +67 -0
  237. package/src/discovery/agents.ts +219 -0
  238. package/src/discovery/builtin.ts +851 -0
  239. package/src/discovery/claude-plugins.ts +297 -0
  240. package/src/discovery/claude.ts +543 -0
  241. package/src/discovery/cline.ts +83 -0
  242. package/src/discovery/codex.ts +535 -0
  243. package/src/discovery/cursor.ts +220 -0
  244. package/src/discovery/gemini.ts +396 -0
  245. package/src/discovery/github.ts +118 -0
  246. package/src/discovery/helpers.ts +934 -0
  247. package/src/discovery/index.ts +79 -0
  248. package/src/discovery/language.ts +46 -0
  249. package/src/discovery/mcp-json.ts +171 -0
  250. package/src/discovery/opencode.ts +393 -0
  251. package/src/discovery/plugin-dir-roots.ts +28 -0
  252. package/src/discovery/ssh.ts +153 -0
  253. package/src/discovery/substitute-plugin-root.ts +29 -0
  254. package/src/discovery/vscode.ts +105 -0
  255. package/src/discovery/windsurf.ts +147 -0
  256. package/src/edit/diff.ts +818 -0
  257. package/src/edit/index.ts +481 -0
  258. package/src/edit/line-hash.ts +67 -0
  259. package/src/edit/modes/chunk.ts +762 -0
  260. package/src/edit/modes/hashline.ts +1366 -0
  261. package/src/edit/modes/patch.ts +1791 -0
  262. package/src/edit/modes/replace.ts +1115 -0
  263. package/src/edit/normalize.ts +375 -0
  264. package/src/edit/renderer.ts +627 -0
  265. package/src/exa/factory.ts +61 -0
  266. package/src/exa/index.ts +27 -0
  267. package/src/exa/mcp-client.ts +293 -0
  268. package/src/exa/render.ts +232 -0
  269. package/src/exa/researcher.ts +47 -0
  270. package/src/exa/search.ts +86 -0
  271. package/src/exa/types.ts +166 -0
  272. package/src/exa/websets.ts +247 -0
  273. package/src/exec/bash-executor.ts +332 -0
  274. package/src/exec/exec.ts +53 -0
  275. package/src/exec/idle-timeout-watchdog.ts +126 -0
  276. package/src/exec/non-interactive-env.ts +48 -0
  277. package/src/export/custom-share.ts +65 -0
  278. package/src/export/html/index.ts +161 -0
  279. package/src/export/html/template.css +1001 -0
  280. package/src/export/html/template.generated.ts +2 -0
  281. package/src/export/html/template.html +46 -0
  282. package/src/export/html/template.js +1950 -0
  283. package/src/export/html/template.macro.ts +24 -0
  284. package/src/export/html/vendor/highlight.min.js +1213 -0
  285. package/src/export/html/vendor/marked.min.js +6 -0
  286. package/src/export/ttsr.ts +434 -0
  287. package/src/extensibility/custom-commands/bundled/ci-green/index.ts +25 -0
  288. package/src/extensibility/custom-commands/bundled/review/index.ts +456 -0
  289. package/src/extensibility/custom-commands/index.ts +2 -0
  290. package/src/extensibility/custom-commands/loader.ts +236 -0
  291. package/src/extensibility/custom-commands/types.ts +111 -0
  292. package/src/extensibility/custom-tools/index.ts +7 -0
  293. package/src/extensibility/custom-tools/loader.ts +238 -0
  294. package/src/extensibility/custom-tools/types.ts +251 -0
  295. package/src/extensibility/custom-tools/wrapper.ts +47 -0
  296. package/src/extensibility/extensions/index.ts +15 -0
  297. package/src/extensibility/extensions/loader.ts +572 -0
  298. package/src/extensibility/extensions/runner.ts +848 -0
  299. package/src/extensibility/extensions/types.ts +1394 -0
  300. package/src/extensibility/extensions/wrapper.ts +191 -0
  301. package/src/extensibility/hooks/index.ts +5 -0
  302. package/src/extensibility/hooks/loader.ts +255 -0
  303. package/src/extensibility/hooks/runner.ts +425 -0
  304. package/src/extensibility/hooks/tool-wrapper.ts +108 -0
  305. package/src/extensibility/hooks/types.ts +826 -0
  306. package/src/extensibility/plugins/doctor.ts +66 -0
  307. package/src/extensibility/plugins/git-url.ts +281 -0
  308. package/src/extensibility/plugins/index.ts +9 -0
  309. package/src/extensibility/plugins/installer.ts +192 -0
  310. package/src/extensibility/plugins/loader.ts +267 -0
  311. package/src/extensibility/plugins/manager.ts +731 -0
  312. package/src/extensibility/plugins/marketplace/cache.ts +136 -0
  313. package/src/extensibility/plugins/marketplace/fetcher.ts +318 -0
  314. package/src/extensibility/plugins/marketplace/index.ts +6 -0
  315. package/src/extensibility/plugins/marketplace/manager.ts +781 -0
  316. package/src/extensibility/plugins/marketplace/prerequisites.ts +255 -0
  317. package/src/extensibility/plugins/marketplace/registry.ts +196 -0
  318. package/src/extensibility/plugins/marketplace/source-resolver.ts +147 -0
  319. package/src/extensibility/plugins/marketplace/types.ts +201 -0
  320. package/src/extensibility/plugins/parser.ts +105 -0
  321. package/src/extensibility/plugins/types.ts +194 -0
  322. package/src/extensibility/skills.ts +269 -0
  323. package/src/extensibility/slash-commands.ts +246 -0
  324. package/src/extensibility/tool-proxy.ts +25 -0
  325. package/src/extensibility/utils.ts +38 -0
  326. package/src/index.ts +61 -0
  327. package/src/internal-urls/agent-protocol.ts +136 -0
  328. package/src/internal-urls/api-catalog-resolve.ts +495 -0
  329. package/src/internal-urls/api-catalog-types.ts +94 -0
  330. package/src/internal-urls/api-spec-resolve.ts +1036 -0
  331. package/src/internal-urls/api-spec-types.ts +239 -0
  332. package/src/internal-urls/artifact-protocol.ts +97 -0
  333. package/src/internal-urls/branding-index.generated.ts +88 -0
  334. package/src/internal-urls/build-info-runtime.ts +302 -0
  335. package/src/internal-urls/build-info.generated.ts +33 -0
  336. package/src/internal-urls/computer-profile.ts +692 -0
  337. package/src/internal-urls/console-catalog-types.ts +21 -0
  338. package/src/internal-urls/console-catalog.generated.ts +532 -0
  339. package/src/internal-urls/console-field-metadata-types.ts +59 -0
  340. package/src/internal-urls/console-field-metadata.generated.ts +4841 -0
  341. package/src/internal-urls/console-resolve.ts +178 -0
  342. package/src/internal-urls/docs-index.generated.ts +698 -0
  343. package/src/internal-urls/extension-api.md +147 -0
  344. package/src/internal-urls/index.ts +46 -0
  345. package/src/internal-urls/jobs-protocol.ts +119 -0
  346. package/src/internal-urls/json-query.ts +126 -0
  347. package/src/internal-urls/local-protocol.ts +206 -0
  348. package/src/internal-urls/mcp-protocol.ts +156 -0
  349. package/src/internal-urls/memory-protocol.ts +133 -0
  350. package/src/internal-urls/parse.ts +72 -0
  351. package/src/internal-urls/profile-collectors.ts +106 -0
  352. package/src/internal-urls/router.ts +55 -0
  353. package/src/internal-urls/rule-protocol.ts +55 -0
  354. package/src/internal-urls/skill-protocol.ts +111 -0
  355. package/src/internal-urls/terraform-index.generated.ts +1852 -0
  356. package/src/internal-urls/terraform-resolve.ts +184 -0
  357. package/src/internal-urls/terraform-types.ts +45 -0
  358. package/src/internal-urls/types.ts +52 -0
  359. package/src/internal-urls/user-profile.ts +363 -0
  360. package/src/internal-urls/xcsh-protocol.ts +644 -0
  361. package/src/ipy/cancellation.ts +28 -0
  362. package/src/ipy/executor.ts +1155 -0
  363. package/src/ipy/gateway-coordinator.ts +424 -0
  364. package/src/ipy/kernel.ts +1091 -0
  365. package/src/ipy/modules.ts +144 -0
  366. package/src/ipy/prelude.py +849 -0
  367. package/src/ipy/prelude.ts +3 -0
  368. package/src/ipy/runtime.ts +221 -0
  369. package/src/locales/ar.json +512 -0
  370. package/src/locales/de.json +512 -0
  371. package/src/locales/en.json +549 -0
  372. package/src/locales/es.json +512 -0
  373. package/src/locales/fr.json +512 -0
  374. package/src/locales/hi.json +512 -0
  375. package/src/locales/index.ts +29 -0
  376. package/src/locales/it.json +512 -0
  377. package/src/locales/ja.json +512 -0
  378. package/src/locales/ko.json +512 -0
  379. package/src/locales/pt-br.json +512 -0
  380. package/src/locales/th.json +512 -0
  381. package/src/locales/zh-cn.json +512 -0
  382. package/src/locales/zh-tw.json +512 -0
  383. package/src/lsp/client.ts +941 -0
  384. package/src/lsp/clients/biome-client.ts +202 -0
  385. package/src/lsp/clients/index.ts +50 -0
  386. package/src/lsp/clients/lsp-linter-client.ts +93 -0
  387. package/src/lsp/clients/swiftlint-client.ts +120 -0
  388. package/src/lsp/config.ts +418 -0
  389. package/src/lsp/defaults.json +999 -0
  390. package/src/lsp/edits.ts +109 -0
  391. package/src/lsp/index.ts +1746 -0
  392. package/src/lsp/lspmux.ts +233 -0
  393. package/src/lsp/render.ts +692 -0
  394. package/src/lsp/startup-events.ts +13 -0
  395. package/src/lsp/types.ts +444 -0
  396. package/src/lsp/utils.ts +691 -0
  397. package/src/main.ts +944 -0
  398. package/src/mcp/client.ts +482 -0
  399. package/src/mcp/config-writer.ts +225 -0
  400. package/src/mcp/config.ts +365 -0
  401. package/src/mcp/discoverable-tool-metadata.ts +202 -0
  402. package/src/mcp/index.ts +29 -0
  403. package/src/mcp/json-rpc.ts +84 -0
  404. package/src/mcp/loader.ts +124 -0
  405. package/src/mcp/manager.ts +1152 -0
  406. package/src/mcp/oauth-discovery.ts +349 -0
  407. package/src/mcp/oauth-flow.ts +387 -0
  408. package/src/mcp/render.ts +157 -0
  409. package/src/mcp/smithery-auth.ts +104 -0
  410. package/src/mcp/smithery-connect.ts +145 -0
  411. package/src/mcp/smithery-registry.ts +477 -0
  412. package/src/mcp/tool-bridge.ts +417 -0
  413. package/src/mcp/tool-cache.ts +117 -0
  414. package/src/mcp/transports/http.ts +475 -0
  415. package/src/mcp/transports/index.ts +6 -0
  416. package/src/mcp/transports/stdio.ts +325 -0
  417. package/src/mcp/types.ts +423 -0
  418. package/src/memories/index.ts +1115 -0
  419. package/src/memories/storage.ts +577 -0
  420. package/src/modes/acp/acp-agent.ts +1361 -0
  421. package/src/modes/acp/acp-event-mapper.ts +538 -0
  422. package/src/modes/acp/acp-mode.ts +15 -0
  423. package/src/modes/acp/index.ts +2 -0
  424. package/src/modes/components/agent-dashboard.ts +1124 -0
  425. package/src/modes/components/assistant-message.ts +213 -0
  426. package/src/modes/components/bash-execution.ts +345 -0
  427. package/src/modes/components/bordered-loader.ts +41 -0
  428. package/src/modes/components/branch-summary-message.ts +45 -0
  429. package/src/modes/components/btw-panel.ts +103 -0
  430. package/src/modes/components/compaction-summary-message.ts +51 -0
  431. package/src/modes/components/context-add-wizard.ts +534 -0
  432. package/src/modes/components/countdown-timer.ts +75 -0
  433. package/src/modes/components/custom-editor.ts +238 -0
  434. package/src/modes/components/custom-message.ts +91 -0
  435. package/src/modes/components/diff.ts +210 -0
  436. package/src/modes/components/dynamic-border.ts +25 -0
  437. package/src/modes/components/extensions/extension-dashboard.ts +326 -0
  438. package/src/modes/components/extensions/extension-list.ts +492 -0
  439. package/src/modes/components/extensions/index.ts +9 -0
  440. package/src/modes/components/extensions/inspector-panel.ts +317 -0
  441. package/src/modes/components/extensions/state-manager.ts +587 -0
  442. package/src/modes/components/extensions/types.ts +191 -0
  443. package/src/modes/components/footer.ts +262 -0
  444. package/src/modes/components/gutter-block.ts +315 -0
  445. package/src/modes/components/history-search.ts +158 -0
  446. package/src/modes/components/hook-editor.ts +151 -0
  447. package/src/modes/components/hook-input.ts +81 -0
  448. package/src/modes/components/hook-message.ts +100 -0
  449. package/src/modes/components/hook-selector.ts +192 -0
  450. package/src/modes/components/index.ts +36 -0
  451. package/src/modes/components/keybinding-hints.ts +65 -0
  452. package/src/modes/components/login-dialog.ts +164 -0
  453. package/src/modes/components/mcp-add-wizard.ts +1314 -0
  454. package/src/modes/components/model-selector.ts +946 -0
  455. package/src/modes/components/oauth-selector.ts +211 -0
  456. package/src/modes/components/plugin-selector.ts +95 -0
  457. package/src/modes/components/plugin-settings.ts +477 -0
  458. package/src/modes/components/plugins/index.ts +5 -0
  459. package/src/modes/components/plugins/plugin-dashboard.ts +523 -0
  460. package/src/modes/components/plugins/plugin-inspector-pane.ts +84 -0
  461. package/src/modes/components/plugins/plugin-list-pane.ts +109 -0
  462. package/src/modes/components/plugins/state-manager.ts +229 -0
  463. package/src/modes/components/plugins/types.ts +51 -0
  464. package/src/modes/components/plugins/utils.ts +6 -0
  465. package/src/modes/components/python-execution.ts +244 -0
  466. package/src/modes/components/queue-mode-selector.ts +56 -0
  467. package/src/modes/components/read-tool-group.ts +137 -0
  468. package/src/modes/components/session-observer-overlay.ts +483 -0
  469. package/src/modes/components/session-selector.ts +343 -0
  470. package/src/modes/components/settings-defs.ts +568 -0
  471. package/src/modes/components/settings-selector.ts +641 -0
  472. package/src/modes/components/show-images-selector.ts +45 -0
  473. package/src/modes/components/skill-message.ts +90 -0
  474. package/src/modes/components/status-line/context-gradient.ts +64 -0
  475. package/src/modes/components/status-line/git-utils.ts +42 -0
  476. package/src/modes/components/status-line/hex-ansi.ts +29 -0
  477. package/src/modes/components/status-line/index.ts +4 -0
  478. package/src/modes/components/status-line/presets.ts +174 -0
  479. package/src/modes/components/status-line/segments.ts +494 -0
  480. package/src/modes/components/status-line/separators.ts +55 -0
  481. package/src/modes/components/status-line/token-rate.ts +66 -0
  482. package/src/modes/components/status-line/types.ts +96 -0
  483. package/src/modes/components/status-line-segment-editor.ts +361 -0
  484. package/src/modes/components/status-line.ts +729 -0
  485. package/src/modes/components/theme-selector.ts +63 -0
  486. package/src/modes/components/thinking-selector.ts +52 -0
  487. package/src/modes/components/todo-reminder.ts +54 -0
  488. package/src/modes/components/tool-execution.ts +781 -0
  489. package/src/modes/components/tree-selector.ts +908 -0
  490. package/src/modes/components/ttsr-notification.ts +80 -0
  491. package/src/modes/components/user-message-selector.ts +141 -0
  492. package/src/modes/components/user-message.ts +100 -0
  493. package/src/modes/components/visual-truncate.ts +63 -0
  494. package/src/modes/components/welcome-checks.ts +313 -0
  495. package/src/modes/components/welcome.ts +270 -0
  496. package/src/modes/controllers/btw-controller.ts +193 -0
  497. package/src/modes/controllers/chord-routing.ts +37 -0
  498. package/src/modes/controllers/command-controller.ts +1293 -0
  499. package/src/modes/controllers/context-command-controller.ts +61 -0
  500. package/src/modes/controllers/event-controller.ts +743 -0
  501. package/src/modes/controllers/extension-ui-controller.ts +983 -0
  502. package/src/modes/controllers/input-controller.ts +877 -0
  503. package/src/modes/controllers/mcp-command-controller.ts +1940 -0
  504. package/src/modes/controllers/selector-controller.ts +1292 -0
  505. package/src/modes/controllers/ssh-command-controller.ts +421 -0
  506. package/src/modes/index.ts +34 -0
  507. package/src/modes/interactive-mode.ts +1781 -0
  508. package/src/modes/oauth-manual-input.ts +42 -0
  509. package/src/modes/print-mode.ts +196 -0
  510. package/src/modes/prompt-action-autocomplete.ts +231 -0
  511. package/src/modes/rpc/host-tools.ts +186 -0
  512. package/src/modes/rpc/rpc-client.ts +762 -0
  513. package/src/modes/rpc/rpc-mode.ts +877 -0
  514. package/src/modes/rpc/rpc-types.ts +322 -0
  515. package/src/modes/session-observer-registry.ts +146 -0
  516. package/src/modes/shared.ts +30 -0
  517. package/src/modes/theme/defaults/index.ts +7 -0
  518. package/src/modes/theme/defaults/xcsh-dark.json +113 -0
  519. package/src/modes/theme/defaults/xcsh-light.json +115 -0
  520. package/src/modes/theme/mermaid-cache.ts +151 -0
  521. package/src/modes/theme/mermaid-palette.ts +39 -0
  522. package/src/modes/theme/theme-schema.json +553 -0
  523. package/src/modes/theme/theme.ts +2563 -0
  524. package/src/modes/types.ts +273 -0
  525. package/src/modes/utils/hotkeys-markdown.ts +60 -0
  526. package/src/modes/utils/keybinding-matchers.ts +30 -0
  527. package/src/modes/utils/read-group-outcome-aggregator.ts +55 -0
  528. package/src/modes/utils/sanitize-error-message.ts +60 -0
  529. package/src/modes/utils/tools-markdown.ts +28 -0
  530. package/src/modes/utils/ui-helpers.ts +734 -0
  531. package/src/plan-mode/approved-plan.ts +55 -0
  532. package/src/plan-mode/state.ts +6 -0
  533. package/src/priority.json +37 -0
  534. package/src/prompts/agents/designer.md +67 -0
  535. package/src/prompts/agents/explore.md +61 -0
  536. package/src/prompts/agents/frontmatter.md +10 -0
  537. package/src/prompts/agents/init.md +36 -0
  538. package/src/prompts/agents/librarian.md +121 -0
  539. package/src/prompts/agents/plan.md +49 -0
  540. package/src/prompts/agents/reviewer.md +127 -0
  541. package/src/prompts/agents/task.md +16 -0
  542. package/src/prompts/ci-green-request.md +35 -0
  543. package/src/prompts/compaction/branch-summary-context.md +5 -0
  544. package/src/prompts/compaction/branch-summary-preamble.md +2 -0
  545. package/src/prompts/compaction/branch-summary.md +30 -0
  546. package/src/prompts/compaction/compaction-short-summary.md +9 -0
  547. package/src/prompts/compaction/compaction-summary-context.md +5 -0
  548. package/src/prompts/compaction/compaction-summary.md +38 -0
  549. package/src/prompts/compaction/compaction-turn-prefix.md +17 -0
  550. package/src/prompts/compaction/compaction-update-summary.md +45 -0
  551. package/src/prompts/memories/consolidation.md +30 -0
  552. package/src/prompts/memories/read-path.md +11 -0
  553. package/src/prompts/memories/stage_one_input.md +6 -0
  554. package/src/prompts/memories/stage_one_system.md +21 -0
  555. package/src/prompts/review-request.md +70 -0
  556. package/src/prompts/system/agent-creation-architect.md +65 -0
  557. package/src/prompts/system/agent-creation-user.md +6 -0
  558. package/src/prompts/system/auto-handoff-threshold-focus.md +1 -0
  559. package/src/prompts/system/btw-user.md +8 -0
  560. package/src/prompts/system/commit-message-system.md +2 -0
  561. package/src/prompts/system/custom-system-prompt.md +82 -0
  562. package/src/prompts/system/eager-todo.md +13 -0
  563. package/src/prompts/system/file-operations.md +10 -0
  564. package/src/prompts/system/handoff-document.md +48 -0
  565. package/src/prompts/system/plan-mode-active.md +114 -0
  566. package/src/prompts/system/plan-mode-approved.md +23 -0
  567. package/src/prompts/system/plan-mode-reference.md +14 -0
  568. package/src/prompts/system/plan-mode-subagent.md +34 -0
  569. package/src/prompts/system/plan-mode-tool-decision-reminder.md +9 -0
  570. package/src/prompts/system/subagent-submit-reminder.md +7 -0
  571. package/src/prompts/system/subagent-system-prompt.md +36 -0
  572. package/src/prompts/system/subagent-user-prompt.md +12 -0
  573. package/src/prompts/system/summarization-system.md +3 -0
  574. package/src/prompts/system/system-prompt.md +698 -0
  575. package/src/prompts/system/title-system.md +2 -0
  576. package/src/prompts/system/ttsr-interrupt.md +7 -0
  577. package/src/prompts/system/web-search.md +28 -0
  578. package/src/prompts/tools/ask.md +28 -0
  579. package/src/prompts/tools/ast-edit.md +48 -0
  580. package/src/prompts/tools/ast-grep.md +54 -0
  581. package/src/prompts/tools/async-result.md +5 -0
  582. package/src/prompts/tools/bash.md +67 -0
  583. package/src/prompts/tools/browser.md +26 -0
  584. package/src/prompts/tools/calculator.md +10 -0
  585. package/src/prompts/tools/cancel-job.md +5 -0
  586. package/src/prompts/tools/catalog-workflow-runner.md +13 -0
  587. package/src/prompts/tools/checkpoint.md +16 -0
  588. package/src/prompts/tools/chunk-edit.md +279 -0
  589. package/src/prompts/tools/debug.md +43 -0
  590. package/src/prompts/tools/display-image.md +23 -0
  591. package/src/prompts/tools/exit-plan-mode.md +41 -0
  592. package/src/prompts/tools/find.md +26 -0
  593. package/src/prompts/tools/gemini-image.md +7 -0
  594. package/src/prompts/tools/grep.md +29 -0
  595. package/src/prompts/tools/hashline.md +131 -0
  596. package/src/prompts/tools/inspect-image-system.md +20 -0
  597. package/src/prompts/tools/inspect-image.md +32 -0
  598. package/src/prompts/tools/lsp.md +33 -0
  599. package/src/prompts/tools/patch.md +77 -0
  600. package/src/prompts/tools/poll.md +5 -0
  601. package/src/prompts/tools/python.md +60 -0
  602. package/src/prompts/tools/read-chunk.md +35 -0
  603. package/src/prompts/tools/read.md +63 -0
  604. package/src/prompts/tools/render-mermaid.md +9 -0
  605. package/src/prompts/tools/replace.md +36 -0
  606. package/src/prompts/tools/resolve.md +8 -0
  607. package/src/prompts/tools/rewind.md +13 -0
  608. package/src/prompts/tools/search-tool-bm25.md +34 -0
  609. package/src/prompts/tools/ssh.md +44 -0
  610. package/src/prompts/tools/task-summary.md +28 -0
  611. package/src/prompts/tools/task.md +131 -0
  612. package/src/prompts/tools/todo-write.md +89 -0
  613. package/src/prompts/tools/vim.md +98 -0
  614. package/src/prompts/tools/web-search.md +10 -0
  615. package/src/prompts/tools/write.md +14 -0
  616. package/src/prompts/tools/xcsh-api.md +283 -0
  617. package/src/resource-management/index.ts +42 -0
  618. package/src/sdk.ts +2123 -0
  619. package/src/secrets/index.ts +146 -0
  620. package/src/secrets/obfuscator.ts +290 -0
  621. package/src/secrets/regex.ts +21 -0
  622. package/src/services/context-env.ts +102 -0
  623. package/src/services/xcsh-api-client.ts +230 -0
  624. package/src/services/xcsh-context-command.ts +803 -0
  625. package/src/services/xcsh-context-display.ts +49 -0
  626. package/src/services/xcsh-context-indicators.ts +17 -0
  627. package/src/services/xcsh-context-segment.ts +39 -0
  628. package/src/services/xcsh-context.ts +1410 -0
  629. package/src/services/xcsh-env.ts +107 -0
  630. package/src/services/xcsh-knowledge.ts +177 -0
  631. package/src/services/xcsh-table.ts +164 -0
  632. package/src/session/agent-session.ts +6690 -0
  633. package/src/session/agent-storage.ts +451 -0
  634. package/src/session/artifacts.ts +132 -0
  635. package/src/session/auth-storage.ts +17 -0
  636. package/src/session/blob-store.ts +135 -0
  637. package/src/session/compaction/branch-summarization.ts +322 -0
  638. package/src/session/compaction/compaction.ts +1388 -0
  639. package/src/session/compaction/index.ts +7 -0
  640. package/src/session/compaction/pruning.ts +91 -0
  641. package/src/session/compaction/utils.ts +184 -0
  642. package/src/session/history-storage.ts +253 -0
  643. package/src/session/messages.ts +597 -0
  644. package/src/session/session-dump-format.ts +203 -0
  645. package/src/session/session-manager.ts +2816 -0
  646. package/src/session/session-storage.ts +370 -0
  647. package/src/session/streaming-output.ts +770 -0
  648. package/src/session/tool-choice-queue.ts +213 -0
  649. package/src/slash-commands/builtin-registry.ts +1614 -0
  650. package/src/slash-commands/export-command.ts +178 -0
  651. package/src/slash-commands/marketplace-install-parser.ts +99 -0
  652. package/src/slash-commands/resource-commands.ts +250 -0
  653. package/src/ssh/config-writer.ts +183 -0
  654. package/src/ssh/connection-manager.ts +445 -0
  655. package/src/ssh/ssh-executor.ts +131 -0
  656. package/src/ssh/sshfs-mount.ts +137 -0
  657. package/src/ssh/utils.ts +8 -0
  658. package/src/stt/downloader.ts +71 -0
  659. package/src/stt/index.ts +3 -0
  660. package/src/stt/recorder.ts +351 -0
  661. package/src/stt/setup.ts +52 -0
  662. package/src/stt/stt-controller.ts +160 -0
  663. package/src/stt/transcribe.py +70 -0
  664. package/src/stt/transcriber.ts +91 -0
  665. package/src/system-prompt.ts +688 -0
  666. package/src/task/agents.ts +166 -0
  667. package/src/task/commands.ts +131 -0
  668. package/src/task/discovery.ts +126 -0
  669. package/src/task/executor.ts +1324 -0
  670. package/src/task/index.ts +1197 -0
  671. package/src/task/isolation-backend.ts +72 -0
  672. package/src/task/name-generator.ts +1577 -0
  673. package/src/task/output-manager.ts +107 -0
  674. package/src/task/parallel.ts +116 -0
  675. package/src/task/render.ts +1035 -0
  676. package/src/task/subprocess-tool-registry.ts +88 -0
  677. package/src/task/template.ts +33 -0
  678. package/src/task/types.ts +230 -0
  679. package/src/task/worktree.ts +580 -0
  680. package/src/task/xcsh-command.ts +26 -0
  681. package/src/thinking.ts +87 -0
  682. package/src/tools/action-renderer.ts +198 -0
  683. package/src/tools/archive-reader.ts +315 -0
  684. package/src/tools/ask.ts +791 -0
  685. package/src/tools/ast-edit.ts +492 -0
  686. package/src/tools/ast-grep.ts +453 -0
  687. package/src/tools/auto-generated-guard.ts +305 -0
  688. package/src/tools/bash-interactive.ts +383 -0
  689. package/src/tools/bash-interceptor.ts +67 -0
  690. package/src/tools/bash-normalize.ts +107 -0
  691. package/src/tools/bash-skill-urls.ts +246 -0
  692. package/src/tools/bash.ts +878 -0
  693. package/src/tools/browser-renderer.ts +129 -0
  694. package/src/tools/browser.ts +1366 -0
  695. package/src/tools/calculator.ts +543 -0
  696. package/src/tools/cancel-job.ts +100 -0
  697. package/src/tools/catalog-workflow-runner.ts +718 -0
  698. package/src/tools/checkpoint.ts +133 -0
  699. package/src/tools/context.ts +39 -0
  700. package/src/tools/debug.ts +1004 -0
  701. package/src/tools/display-image-renderer.ts +96 -0
  702. package/src/tools/display-image.ts +109 -0
  703. package/src/tools/exit-plan-mode.ts +101 -0
  704. package/src/tools/fetch.ts +1462 -0
  705. package/src/tools/find.ts +437 -0
  706. package/src/tools/fs-cache-invalidation.ts +33 -0
  707. package/src/tools/gemini-image.ts +1004 -0
  708. package/src/tools/grep.ts +705 -0
  709. package/src/tools/index.ts +442 -0
  710. package/src/tools/inspect-image-renderer.ts +101 -0
  711. package/src/tools/inspect-image.ts +176 -0
  712. package/src/tools/json-tree.ts +266 -0
  713. package/src/tools/jtd-to-json-schema.ts +199 -0
  714. package/src/tools/jtd-to-typescript.ts +136 -0
  715. package/src/tools/jtd-utils.ts +102 -0
  716. package/src/tools/list-limit.ts +40 -0
  717. package/src/tools/mermaid-renderer.ts +127 -0
  718. package/src/tools/notebook.ts +288 -0
  719. package/src/tools/output-meta.ts +588 -0
  720. package/src/tools/path-utils.ts +560 -0
  721. package/src/tools/plan-mode-guard.ts +41 -0
  722. package/src/tools/poll-tool.ts +177 -0
  723. package/src/tools/puppeteer/00_stealth_tampering.txt +63 -0
  724. package/src/tools/puppeteer/01_stealth_activity.txt +20 -0
  725. package/src/tools/puppeteer/02_stealth_hairline.txt +11 -0
  726. package/src/tools/puppeteer/03_stealth_botd.txt +384 -0
  727. package/src/tools/puppeteer/04_stealth_iframe.txt +81 -0
  728. package/src/tools/puppeteer/05_stealth_webgl.txt +75 -0
  729. package/src/tools/puppeteer/06_stealth_screen.txt +72 -0
  730. package/src/tools/puppeteer/07_stealth_fonts.txt +97 -0
  731. package/src/tools/puppeteer/08_stealth_audio.txt +51 -0
  732. package/src/tools/puppeteer/09_stealth_locale.txt +46 -0
  733. package/src/tools/puppeteer/10_stealth_plugins.txt +206 -0
  734. package/src/tools/puppeteer/11_stealth_hardware.txt +8 -0
  735. package/src/tools/puppeteer/12_stealth_codecs.txt +40 -0
  736. package/src/tools/puppeteer/13_stealth_worker.txt +74 -0
  737. package/src/tools/python.ts +1184 -0
  738. package/src/tools/read.ts +1591 -0
  739. package/src/tools/render-mermaid.ts +93 -0
  740. package/src/tools/render-utils.ts +677 -0
  741. package/src/tools/renderers.ts +82 -0
  742. package/src/tools/report-tool-issue.ts +80 -0
  743. package/src/tools/resolve.ts +196 -0
  744. package/src/tools/review.ts +238 -0
  745. package/src/tools/search-tool-bm25.ts +288 -0
  746. package/src/tools/sqlite-reader.ts +623 -0
  747. package/src/tools/ssh.ts +322 -0
  748. package/src/tools/submit-result.ts +229 -0
  749. package/src/tools/todo-render.ts +33 -0
  750. package/src/tools/todo-write.ts +440 -0
  751. package/src/tools/tool-errors.ts +62 -0
  752. package/src/tools/tool-result.ts +93 -0
  753. package/src/tools/tool-timeouts.ts +30 -0
  754. package/src/tools/vim.ts +981 -0
  755. package/src/tools/write.ts +671 -0
  756. package/src/tools/xcsh-api-renderer.ts +402 -0
  757. package/src/tools/xcsh-api.ts +887 -0
  758. package/src/tui/code-cell.ts +101 -0
  759. package/src/tui/file-list.ts +47 -0
  760. package/src/tui/index.ts +11 -0
  761. package/src/tui/output-block.ts +175 -0
  762. package/src/tui/status-line.ts +39 -0
  763. package/src/tui/tree-list.ts +84 -0
  764. package/src/tui/types.ts +15 -0
  765. package/src/tui/utils.ts +103 -0
  766. package/src/utils/changelog.ts +98 -0
  767. package/src/utils/clipboard.ts +80 -0
  768. package/src/utils/command-args.ts +76 -0
  769. package/src/utils/commit-message-generator.ts +137 -0
  770. package/src/utils/edit-mode.ts +50 -0
  771. package/src/utils/event-bus.ts +33 -0
  772. package/src/utils/external-editor.ts +65 -0
  773. package/src/utils/file-display-mode.ts +37 -0
  774. package/src/utils/file-mentions.ts +376 -0
  775. package/src/utils/fuzzy.ts +108 -0
  776. package/src/utils/git.ts +1495 -0
  777. package/src/utils/gitstatus.ts +140 -0
  778. package/src/utils/image-convert.ts +27 -0
  779. package/src/utils/image-loading.ts +98 -0
  780. package/src/utils/image-passthrough.ts +118 -0
  781. package/src/utils/image-resize.ts +272 -0
  782. package/src/utils/image-viewer.ts +17 -0
  783. package/src/utils/lang-from-path.ts +239 -0
  784. package/src/utils/markit.ts +81 -0
  785. package/src/utils/open.ts +20 -0
  786. package/src/utils/session-color.ts +55 -0
  787. package/src/utils/shell-snapshot.ts +188 -0
  788. package/src/utils/title-generator.ts +193 -0
  789. package/src/utils/tool-choice.ts +28 -0
  790. package/src/utils/tools-manager.ts +356 -0
  791. package/src/vim/buffer.ts +309 -0
  792. package/src/vim/commands.ts +382 -0
  793. package/src/vim/engine.ts +2426 -0
  794. package/src/vim/parser.ts +151 -0
  795. package/src/vim/render.ts +252 -0
  796. package/src/vim/types.ts +197 -0
  797. package/src/web/kagi.ts +174 -0
  798. package/src/web/parallel.ts +346 -0
  799. package/src/web/scrapers/artifacthub.ts +207 -0
  800. package/src/web/scrapers/arxiv.ts +83 -0
  801. package/src/web/scrapers/aur.ts +162 -0
  802. package/src/web/scrapers/biorxiv.ts +133 -0
  803. package/src/web/scrapers/bluesky.ts +262 -0
  804. package/src/web/scrapers/brew.ts +172 -0
  805. package/src/web/scrapers/cheatsh.ts +68 -0
  806. package/src/web/scrapers/chocolatey.ts +196 -0
  807. package/src/web/scrapers/choosealicense.ts +95 -0
  808. package/src/web/scrapers/cisa-kev.ts +87 -0
  809. package/src/web/scrapers/clojars.ts +154 -0
  810. package/src/web/scrapers/coingecko.ts +177 -0
  811. package/src/web/scrapers/crates-io.ts +110 -0
  812. package/src/web/scrapers/crossref.ts +136 -0
  813. package/src/web/scrapers/devto.ts +147 -0
  814. package/src/web/scrapers/discogs.ts +306 -0
  815. package/src/web/scrapers/discourse.ts +197 -0
  816. package/src/web/scrapers/dockerhub.ts +138 -0
  817. package/src/web/scrapers/docs-rs.ts +653 -0
  818. package/src/web/scrapers/fdroid.ts +134 -0
  819. package/src/web/scrapers/firefox-addons.ts +191 -0
  820. package/src/web/scrapers/flathub.ts +223 -0
  821. package/src/web/scrapers/github-gist.ts +58 -0
  822. package/src/web/scrapers/github.ts +452 -0
  823. package/src/web/scrapers/gitlab.ts +401 -0
  824. package/src/web/scrapers/go-pkg.ts +266 -0
  825. package/src/web/scrapers/hackage.ts +140 -0
  826. package/src/web/scrapers/hackernews.ts +189 -0
  827. package/src/web/scrapers/hex.ts +105 -0
  828. package/src/web/scrapers/huggingface.ts +321 -0
  829. package/src/web/scrapers/iacr.ts +89 -0
  830. package/src/web/scrapers/index.ts +252 -0
  831. package/src/web/scrapers/jetbrains-marketplace.ts +159 -0
  832. package/src/web/scrapers/lemmy.ts +203 -0
  833. package/src/web/scrapers/lobsters.ts +175 -0
  834. package/src/web/scrapers/mastodon.ts +292 -0
  835. package/src/web/scrapers/maven.ts +138 -0
  836. package/src/web/scrapers/mdn.ts +169 -0
  837. package/src/web/scrapers/metacpan.ts +222 -0
  838. package/src/web/scrapers/musicbrainz.ts +250 -0
  839. package/src/web/scrapers/npm.ts +98 -0
  840. package/src/web/scrapers/nuget.ts +183 -0
  841. package/src/web/scrapers/nvd.ts +222 -0
  842. package/src/web/scrapers/ollama.ts +239 -0
  843. package/src/web/scrapers/open-vsx.ts +106 -0
  844. package/src/web/scrapers/opencorporates.ts +292 -0
  845. package/src/web/scrapers/openlibrary.ts +336 -0
  846. package/src/web/scrapers/orcid.ts +286 -0
  847. package/src/web/scrapers/osv.ts +176 -0
  848. package/src/web/scrapers/packagist.ts +160 -0
  849. package/src/web/scrapers/pub-dev.ts +143 -0
  850. package/src/web/scrapers/pubmed.ts +211 -0
  851. package/src/web/scrapers/pypi.ts +112 -0
  852. package/src/web/scrapers/rawg.ts +110 -0
  853. package/src/web/scrapers/readthedocs.ts +120 -0
  854. package/src/web/scrapers/reddit.ts +95 -0
  855. package/src/web/scrapers/repology.ts +251 -0
  856. package/src/web/scrapers/rfc.ts +201 -0
  857. package/src/web/scrapers/rubygems.ts +103 -0
  858. package/src/web/scrapers/searchcode.ts +190 -0
  859. package/src/web/scrapers/sec-edgar.ts +261 -0
  860. package/src/web/scrapers/semantic-scholar.ts +171 -0
  861. package/src/web/scrapers/snapcraft.ts +187 -0
  862. package/src/web/scrapers/sourcegraph.ts +336 -0
  863. package/src/web/scrapers/spdx.ts +108 -0
  864. package/src/web/scrapers/spotify.ts +198 -0
  865. package/src/web/scrapers/stackoverflow.ts +120 -0
  866. package/src/web/scrapers/terraform.ts +277 -0
  867. package/src/web/scrapers/tldr.ts +47 -0
  868. package/src/web/scrapers/twitter.ts +93 -0
  869. package/src/web/scrapers/types.ts +267 -0
  870. package/src/web/scrapers/utils.ts +109 -0
  871. package/src/web/scrapers/vimeo.ts +133 -0
  872. package/src/web/scrapers/vscode-marketplace.ts +187 -0
  873. package/src/web/scrapers/w3c.ts +156 -0
  874. package/src/web/scrapers/wikidata.ts +344 -0
  875. package/src/web/scrapers/wikipedia.ts +84 -0
  876. package/src/web/scrapers/youtube.ts +313 -0
  877. package/src/web/search/errors.ts +120 -0
  878. package/src/web/search/index.ts +346 -0
  879. package/src/web/search/params.ts +129 -0
  880. package/src/web/search/provider.ts +97 -0
  881. package/src/web/search/providers/anthropic.ts +339 -0
  882. package/src/web/search/providers/base.ts +35 -0
  883. package/src/web/search/providers/brave.ts +150 -0
  884. package/src/web/search/providers/codex.ts +402 -0
  885. package/src/web/search/providers/exa.ts +264 -0
  886. package/src/web/search/providers/firecrawl.ts +115 -0
  887. package/src/web/search/providers/gemini.ts +566 -0
  888. package/src/web/search/providers/jina.ts +99 -0
  889. package/src/web/search/providers/kagi.ts +70 -0
  890. package/src/web/search/providers/kimi.ts +157 -0
  891. package/src/web/search/providers/parallel.ts +63 -0
  892. package/src/web/search/providers/perplexity.ts +546 -0
  893. package/src/web/search/providers/synthetic.ts +113 -0
  894. package/src/web/search/providers/tavily.ts +162 -0
  895. package/src/web/search/providers/utils.ts +36 -0
  896. package/src/web/search/providers/zai.ts +311 -0
  897. package/src/web/search/render.ts +348 -0
  898. package/src/web/search/types.ts +438 -0
  899. package/src/web/search/utils.ts +17 -0
@@ -0,0 +1,941 @@
1
+ import { isEnoent, logger, ptree, untilAborted } from "@f5xc-salesdemos/pi-utils";
2
+ import { ToolAbortError, throwIfAborted } from "../tools/tool-errors";
3
+ import { applyWorkspaceEdit } from "./edits";
4
+ import { getLspmuxCommand, isLspmuxSupported } from "./lspmux";
5
+ import type {
6
+ LspClient,
7
+ LspJsonRpcNotification,
8
+ LspJsonRpcRequest,
9
+ LspJsonRpcResponse,
10
+ PublishDiagnosticsParams,
11
+ ServerConfig,
12
+ WorkspaceEdit,
13
+ } from "./types";
14
+ import { detectLanguageId, fileToUri } from "./utils";
15
+
16
+ // =============================================================================
17
+ // Client State
18
+ // =============================================================================
19
+
20
+ const clients = new Map<string, LspClient>();
21
+ const clientLocks = new Map<string, Promise<LspClient>>();
22
+ const fileOperationLocks = new Map<string, Promise<void>>();
23
+
24
+ // Idle timeout configuration (disabled by default)
25
+ let idleTimeoutMs: number | null = null;
26
+ let idleCheckInterval: NodeJS.Timeout | null = null;
27
+ const IDLE_CHECK_INTERVAL_MS = 60 * 1000;
28
+
29
+ /**
30
+ * Configure the idle timeout for LSP clients.
31
+ * @param ms - Timeout in milliseconds, or null/undefined to disable
32
+ */
33
+ export function setIdleTimeout(ms: number | null | undefined): void {
34
+ idleTimeoutMs = ms ?? null;
35
+
36
+ if (idleTimeoutMs && idleTimeoutMs > 0) {
37
+ startIdleChecker();
38
+ } else {
39
+ stopIdleChecker();
40
+ }
41
+ }
42
+
43
+ function startIdleChecker(): void {
44
+ if (idleCheckInterval) return;
45
+ idleCheckInterval = setInterval(() => {
46
+ if (!idleTimeoutMs) return;
47
+ const now = Date.now();
48
+ for (const [key, client] of Array.from(clients.entries())) {
49
+ if (now - client.lastActivity > idleTimeoutMs) {
50
+ shutdownClient(key);
51
+ }
52
+ }
53
+ }, IDLE_CHECK_INTERVAL_MS);
54
+ }
55
+
56
+ function stopIdleChecker(): void {
57
+ if (idleCheckInterval) {
58
+ clearInterval(idleCheckInterval);
59
+ idleCheckInterval = null;
60
+ }
61
+ }
62
+
63
+ // =============================================================================
64
+ // Client Capabilities
65
+ // =============================================================================
66
+
67
+ const CLIENT_CAPABILITIES = {
68
+ textDocument: {
69
+ synchronization: {
70
+ didSave: true,
71
+ dynamicRegistration: false,
72
+ willSave: false,
73
+ willSaveWaitUntil: false,
74
+ },
75
+ hover: {
76
+ contentFormat: ["markdown", "plaintext"],
77
+ dynamicRegistration: false,
78
+ },
79
+ definition: {
80
+ dynamicRegistration: false,
81
+ linkSupport: true,
82
+ },
83
+ typeDefinition: {
84
+ dynamicRegistration: false,
85
+ linkSupport: true,
86
+ },
87
+ implementation: {
88
+ dynamicRegistration: false,
89
+ linkSupport: true,
90
+ },
91
+ references: {
92
+ dynamicRegistration: false,
93
+ },
94
+ documentSymbol: {
95
+ dynamicRegistration: false,
96
+ hierarchicalDocumentSymbolSupport: true,
97
+ symbolKind: {
98
+ valueSet: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26],
99
+ },
100
+ },
101
+ rename: {
102
+ dynamicRegistration: false,
103
+ prepareSupport: true,
104
+ },
105
+ codeAction: {
106
+ dynamicRegistration: false,
107
+ codeActionLiteralSupport: {
108
+ codeActionKind: {
109
+ valueSet: [
110
+ "quickfix",
111
+ "refactor",
112
+ "refactor.extract",
113
+ "refactor.inline",
114
+ "refactor.rewrite",
115
+ "source",
116
+ "source.organizeImports",
117
+ "source.fixAll",
118
+ ],
119
+ },
120
+ },
121
+ resolveSupport: {
122
+ properties: ["edit"],
123
+ },
124
+ },
125
+ formatting: {
126
+ dynamicRegistration: false,
127
+ },
128
+ rangeFormatting: {
129
+ dynamicRegistration: false,
130
+ },
131
+ publishDiagnostics: {
132
+ relatedInformation: true,
133
+ versionSupport: true,
134
+ tagSupport: { valueSet: [1, 2] },
135
+ codeDescriptionSupport: true,
136
+ dataSupport: true,
137
+ },
138
+ },
139
+ window: {
140
+ workDoneProgress: true,
141
+ },
142
+ workspace: {
143
+ applyEdit: true,
144
+ workspaceEdit: {
145
+ documentChanges: true,
146
+ resourceOperations: ["create", "rename", "delete"],
147
+ failureHandling: "textOnlyTransactional",
148
+ },
149
+ configuration: true,
150
+ symbol: {
151
+ dynamicRegistration: false,
152
+ symbolKind: {
153
+ valueSet: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26],
154
+ },
155
+ },
156
+ },
157
+ experimental: {
158
+ snippetTextEdit: true,
159
+ },
160
+ };
161
+
162
+ // =============================================================================
163
+ // LSP Message Protocol
164
+ // =============================================================================
165
+
166
+ /**
167
+ * Parse a single LSP message from a buffer.
168
+ * Returns the parsed message and remaining buffer, or null if incomplete.
169
+ */
170
+ function parseMessage(
171
+ buffer: Buffer,
172
+ ): { message: LspJsonRpcResponse | LspJsonRpcNotification; remaining: Buffer } | null {
173
+ // Only decode enough to find the header
174
+ const headerEndIndex = findHeaderEnd(buffer);
175
+ if (headerEndIndex === -1) return null;
176
+
177
+ const headerText = new TextDecoder().decode(buffer.slice(0, headerEndIndex));
178
+ const contentLengthMatch = headerText.match(/Content-Length: (\d+)/i);
179
+ if (!contentLengthMatch) return null;
180
+
181
+ const contentLength = Number.parseInt(contentLengthMatch[1], 10);
182
+ const messageStart = headerEndIndex + 4; // Skip \r\n\r\n
183
+ const messageEnd = messageStart + contentLength;
184
+
185
+ if (buffer.length < messageEnd) return null;
186
+
187
+ const messageBytes = buffer.subarray(messageStart, messageEnd);
188
+ const messageText = new TextDecoder().decode(messageBytes);
189
+ const remaining = buffer.subarray(messageEnd);
190
+
191
+ return {
192
+ message: JSON.parse(messageText),
193
+ remaining,
194
+ };
195
+ }
196
+
197
+ /**
198
+ * Find the end of the header section (before \r\n\r\n)
199
+ */
200
+ function findHeaderEnd(buffer: Uint8Array): number {
201
+ for (let i = 0; i < buffer.length - 3; i++) {
202
+ if (buffer[i] === 13 && buffer[i + 1] === 10 && buffer[i + 2] === 13 && buffer[i + 3] === 10) {
203
+ return i;
204
+ }
205
+ }
206
+ return -1;
207
+ }
208
+
209
+ async function writeMessage(
210
+ sink: Bun.FileSink,
211
+ message: LspJsonRpcRequest | LspJsonRpcNotification | LspJsonRpcResponse,
212
+ ): Promise<void> {
213
+ const content = JSON.stringify(message);
214
+ sink.write(`Content-Length: ${Buffer.byteLength(content, "utf-8")}\r\n\r\n`);
215
+ sink.write(content);
216
+ await sink.flush();
217
+ }
218
+
219
+ // =============================================================================
220
+ // Message Reader
221
+ // =============================================================================
222
+
223
+ /**
224
+ * Start background message reader for a client.
225
+ * Routes responses to pending requests and handles notifications.
226
+ */
227
+ async function startMessageReader(client: LspClient): Promise<void> {
228
+ if (client.isReading) return;
229
+ client.isReading = true;
230
+
231
+ const reader = (client.proc.stdout as ReadableStream<Uint8Array>).getReader();
232
+
233
+ try {
234
+ while (true) {
235
+ const { done, value } = await reader.read();
236
+ if (done) break;
237
+
238
+ // Atomically update buffer before processing
239
+ const currentBuffer: Buffer = Buffer.concat([client.messageBuffer, value]);
240
+ client.messageBuffer = currentBuffer;
241
+
242
+ // Process all complete messages in buffer
243
+ // Use local variable to avoid race with concurrent buffer updates
244
+ let workingBuffer = currentBuffer;
245
+ let parsed = parseMessage(workingBuffer);
246
+ while (parsed) {
247
+ const { message, remaining } = parsed;
248
+ workingBuffer = remaining;
249
+
250
+ // Route message
251
+ if ("id" in message && message.id !== undefined) {
252
+ // Response to a request
253
+ const pending = client.pendingRequests.get(message.id);
254
+ if (pending) {
255
+ client.pendingRequests.delete(message.id);
256
+ if ("error" in message && message.error) {
257
+ pending.reject(new Error(`LSP error: ${message.error.message}`));
258
+ } else {
259
+ pending.resolve(message.result);
260
+ }
261
+ } else if ("method" in message) {
262
+ await handleServerRequest(client, message as LspJsonRpcRequest);
263
+ }
264
+ } else if ("method" in message) {
265
+ // Server notification
266
+ if (message.method === "textDocument/publishDiagnostics" && message.params) {
267
+ const params = message.params as PublishDiagnosticsParams;
268
+ client.diagnostics.set(params.uri, {
269
+ diagnostics: params.diagnostics,
270
+ version: params.version ?? null,
271
+ });
272
+ client.diagnosticsVersion += 1;
273
+ } else if (message.method === "$/progress" && message.params) {
274
+ const params = message.params as { token: string | number; value?: { kind?: string } };
275
+ if (params.value?.kind === "begin") {
276
+ client.activeProgressTokens.add(params.token);
277
+ } else if (params.value?.kind === "end") {
278
+ client.activeProgressTokens.delete(params.token);
279
+ if (client.activeProgressTokens.size === 0) {
280
+ client.resolveProjectLoaded();
281
+ }
282
+ }
283
+ }
284
+ }
285
+
286
+ parsed = parseMessage(workingBuffer);
287
+ }
288
+
289
+ // Atomically commit processed buffer
290
+ client.messageBuffer = workingBuffer;
291
+ }
292
+ } catch (err) {
293
+ // Connection closed or error - reject all pending requests
294
+ for (const pending of Array.from(client.pendingRequests.values())) {
295
+ pending.reject(new Error(`LSP connection closed: ${err}`));
296
+ }
297
+ client.pendingRequests.clear();
298
+ } finally {
299
+ reader.releaseLock();
300
+ client.isReading = false;
301
+ }
302
+ }
303
+
304
+ /**
305
+ * Handle workspace/configuration requests from the server.
306
+ */
307
+ async function handleConfigurationRequest(client: LspClient, message: LspJsonRpcRequest): Promise<void> {
308
+ if (typeof message.id !== "number") return;
309
+ const params = message.params as { items?: Array<{ section?: string }> };
310
+ const items = params?.items ?? [];
311
+ const result = items.map(item => {
312
+ const section = item.section ?? "";
313
+ return client.config.settings?.[section] ?? {};
314
+ });
315
+ await sendResponse(client, message.id, result, "workspace/configuration");
316
+ }
317
+
318
+ /**
319
+ * Handle workspace/applyEdit requests from the server.
320
+ */
321
+ async function handleApplyEditRequest(client: LspClient, message: LspJsonRpcRequest): Promise<void> {
322
+ if (typeof message.id !== "number") return;
323
+ const params = message.params as { edit?: WorkspaceEdit };
324
+ if (!params?.edit) {
325
+ await sendResponse(
326
+ client,
327
+ message.id,
328
+ { applied: false, failureReason: "No edit provided" },
329
+ "workspace/applyEdit",
330
+ );
331
+ return;
332
+ }
333
+
334
+ try {
335
+ await applyWorkspaceEdit(params.edit, client.cwd);
336
+ await sendResponse(client, message.id, { applied: true }, "workspace/applyEdit");
337
+ } catch (err) {
338
+ await sendResponse(client, message.id, { applied: false, failureReason: String(err) }, "workspace/applyEdit");
339
+ }
340
+ }
341
+
342
+ /**
343
+ * Respond to a server-initiated request.
344
+ */
345
+ async function handleServerRequest(client: LspClient, message: LspJsonRpcRequest): Promise<void> {
346
+ if (message.method === "workspace/configuration") {
347
+ await handleConfigurationRequest(client, message);
348
+ return;
349
+ }
350
+ if (message.method === "workspace/applyEdit") {
351
+ await handleApplyEditRequest(client, message);
352
+ return;
353
+ }
354
+ if (message.method === "window/workDoneProgress/create") {
355
+ // Accept progress token registration from the server
356
+ if (typeof message.id === "number") {
357
+ await sendResponse(client, message.id, null, message.method);
358
+ }
359
+ return;
360
+ }
361
+ if (typeof message.id !== "number") return;
362
+ await sendResponse(client, message.id, null, message.method, {
363
+ code: -32601,
364
+ message: `Method not found: ${message.method}`,
365
+ });
366
+ }
367
+
368
+ /**
369
+ * Send an LSP response to the server.
370
+ */
371
+ async function sendResponse(
372
+ client: LspClient,
373
+ id: number,
374
+ result: unknown,
375
+ method: string,
376
+ error?: { code: number; message: string; data?: unknown },
377
+ ): Promise<void> {
378
+ const response: LspJsonRpcResponse = {
379
+ jsonrpc: "2.0",
380
+ id,
381
+ ...(error ? { error } : { result }),
382
+ };
383
+
384
+ try {
385
+ await writeMessage(client.proc.stdin, response);
386
+ } catch (err) {
387
+ logger.error("LSP failed to respond.", { method, error: String(err) });
388
+ }
389
+ }
390
+
391
+ // =============================================================================
392
+ // Client Management
393
+ // =============================================================================
394
+
395
+ /** Timeout for warmup initialize requests (5 seconds) */
396
+ export const WARMUP_TIMEOUT_MS = 5000;
397
+
398
+ /** Max time to wait for the server to report project loading completion via $/progress */
399
+ const PROJECT_LOAD_TIMEOUT_MS = 15_000;
400
+
401
+ /**
402
+ * Get or create an LSP client for the given server configuration and working directory.
403
+ * @param config - Server configuration
404
+ * @param cwd - Working directory
405
+ * @param initTimeoutMs - Optional timeout for the initialize request (defaults to 30s)
406
+ */
407
+ export async function getOrCreateClient(config: ServerConfig, cwd: string, initTimeoutMs?: number): Promise<LspClient> {
408
+ const key = `${config.command}:${cwd}`;
409
+
410
+ // Check if client already exists
411
+ const existingClient = clients.get(key);
412
+ if (existingClient) {
413
+ existingClient.lastActivity = Date.now();
414
+ return existingClient;
415
+ }
416
+
417
+ // Check if another coroutine is already creating this client
418
+ const existingLock = clientLocks.get(key);
419
+ if (existingLock) {
420
+ return existingLock;
421
+ }
422
+
423
+ // Create new client with lock
424
+ const clientPromise = (async () => {
425
+ const baseCommand = config.resolvedCommand ?? config.command;
426
+ const baseArgs = config.args ?? [];
427
+
428
+ // Wrap with lspmux if available and supported
429
+ const { command, args, env } = isLspmuxSupported(baseCommand)
430
+ ? await getLspmuxCommand(baseCommand, baseArgs)
431
+ : { command: baseCommand, args: baseArgs };
432
+
433
+ const proc = ptree.spawn([command, ...args], {
434
+ cwd,
435
+ stdin: "pipe",
436
+ env: env ? { ...Bun.env, ...env } : undefined,
437
+ });
438
+
439
+ let resolveProjectLoaded!: () => void;
440
+ const projectLoaded = new Promise<void>(resolve => {
441
+ resolveProjectLoaded = resolve;
442
+ });
443
+ // Auto-resolve after timeout in case server doesn't use progress tokens
444
+ const projectLoadTimeout = setTimeout(resolveProjectLoaded, PROJECT_LOAD_TIMEOUT_MS);
445
+ const originalResolve = resolveProjectLoaded;
446
+ resolveProjectLoaded = () => {
447
+ clearTimeout(projectLoadTimeout);
448
+ originalResolve();
449
+ };
450
+
451
+ const client: LspClient = {
452
+ name: key,
453
+ cwd,
454
+ proc,
455
+ config,
456
+ requestId: 0,
457
+ diagnostics: new Map(),
458
+ diagnosticsVersion: 0,
459
+ openFiles: new Map(),
460
+ pendingRequests: new Map(),
461
+ messageBuffer: new Uint8Array(0),
462
+ isReading: false,
463
+ lastActivity: Date.now(),
464
+ activeProgressTokens: new Set(),
465
+ projectLoaded,
466
+ resolveProjectLoaded,
467
+ };
468
+ clients.set(key, client);
469
+
470
+ // Register crash recovery - remove client on process exit
471
+ proc.exited.then(() => {
472
+ clients.delete(key);
473
+ clientLocks.delete(key);
474
+ client.resolveProjectLoaded();
475
+
476
+ // Reject any pending requests — the server is gone, they will never complete.
477
+ if (client.pendingRequests.size > 0) {
478
+ // Strip informational log lines (e.g. marksman's [INF]/[DBG] prefix)
479
+ // — they are startup noise, not actionable errors.
480
+ const rawStderr = proc.peekStderr().trim();
481
+ const stderr = rawStderr
482
+ .split("\n")
483
+ .filter(line => !/^\[\d{2}:\d{2}:\d{2} (?:INF|DBG|VRB)\]/.test(line))
484
+ .join("\n")
485
+ .trim();
486
+ const code = proc.exitCode;
487
+ const err = new Error(
488
+ stderr ? `LSP server exited (code ${code}): ${stderr}` : `LSP server exited unexpectedly (code ${code})`,
489
+ );
490
+ for (const pending of client.pendingRequests.values()) {
491
+ pending.reject(err);
492
+ }
493
+ client.pendingRequests.clear();
494
+ }
495
+ });
496
+
497
+ // Start background message reader
498
+ startMessageReader(client);
499
+
500
+ try {
501
+ // Send initialize request
502
+ const initResult = (await sendRequest(
503
+ client,
504
+ "initialize",
505
+ {
506
+ processId: process.pid,
507
+ rootUri: fileToUri(cwd),
508
+ rootPath: cwd,
509
+ capabilities: CLIENT_CAPABILITIES,
510
+ initializationOptions: config.initOptions ?? {},
511
+ workspaceFolders: [{ uri: fileToUri(cwd), name: cwd.split("/").pop() ?? "workspace" }],
512
+ },
513
+ undefined, // signal
514
+ initTimeoutMs,
515
+ )) as { capabilities?: unknown };
516
+
517
+ if (!initResult) {
518
+ throw new Error("Failed to initialize LSP: no response");
519
+ }
520
+
521
+ client.serverCapabilities = initResult.capabilities as LspClient["serverCapabilities"];
522
+
523
+ // Send initialized notification
524
+ await sendNotification(client, "initialized", {});
525
+
526
+ return client;
527
+ } catch (err) {
528
+ // Clean up on initialization failure
529
+ clients.delete(key);
530
+ clientLocks.delete(key);
531
+ proc.kill();
532
+ throw err;
533
+ } finally {
534
+ clientLocks.delete(key);
535
+ }
536
+ })();
537
+
538
+ clientLocks.set(key, clientPromise);
539
+ return clientPromise;
540
+ }
541
+
542
+ /**
543
+ * Ensure a file is opened in the LSP client.
544
+ * Sends didOpen notification if the file is not already tracked.
545
+ */
546
+ export async function ensureFileOpen(client: LspClient, filePath: string, signal?: AbortSignal): Promise<void> {
547
+ throwIfAborted(signal);
548
+ const uri = fileToUri(filePath);
549
+ const lockKey = `${client.name}:${uri}`;
550
+
551
+ // Check if file is already open
552
+ if (client.openFiles.has(uri)) {
553
+ return;
554
+ }
555
+
556
+ // Check if another operation is already opening this file
557
+ const existingLock = fileOperationLocks.get(lockKey);
558
+ if (existingLock) {
559
+ await untilAborted(signal, () => existingLock);
560
+ return;
561
+ }
562
+
563
+ // Lock and open file
564
+ const openPromise = (async () => {
565
+ throwIfAborted(signal);
566
+ // Double-check after acquiring lock
567
+ if (client.openFiles.has(uri)) {
568
+ return;
569
+ }
570
+
571
+ let content: string;
572
+ try {
573
+ content = await Bun.file(filePath).text();
574
+ throwIfAborted(signal);
575
+ } catch (err) {
576
+ if (isEnoent(err)) return;
577
+ throw err;
578
+ }
579
+ const languageId = detectLanguageId(filePath);
580
+ throwIfAborted(signal);
581
+
582
+ await sendNotification(client, "textDocument/didOpen", {
583
+ textDocument: {
584
+ uri,
585
+ languageId,
586
+ version: 1,
587
+ text: content,
588
+ },
589
+ });
590
+
591
+ client.openFiles.set(uri, { version: 1, languageId });
592
+ client.lastActivity = Date.now();
593
+ })();
594
+
595
+ fileOperationLocks.set(lockKey, openPromise);
596
+ try {
597
+ await openPromise;
598
+ } finally {
599
+ fileOperationLocks.delete(lockKey);
600
+ }
601
+ }
602
+
603
+ /**
604
+ * Wait for the server's initial project loading to complete.
605
+ * Races the server's $/progress tracking against the abort signal.
606
+ * Returns immediately if loading already completed or timed out.
607
+ */
608
+ export async function waitForProjectLoaded(client: LspClient, signal?: AbortSignal): Promise<void> {
609
+ if (signal?.aborted) return;
610
+ await Promise.race([
611
+ client.projectLoaded,
612
+ ...(signal
613
+ ? [new Promise<void>(resolve => signal.addEventListener("abort", () => resolve(), { once: true }))]
614
+ : []),
615
+ ]);
616
+ }
617
+
618
+ /**
619
+ * Sync in-memory content to the LSP client without reading from disk.
620
+ * Use this to provide instant feedback during edits before the file is saved.
621
+ */
622
+ export async function syncContent(
623
+ client: LspClient,
624
+ filePath: string,
625
+ content: string,
626
+ signal?: AbortSignal,
627
+ ): Promise<void> {
628
+ const uri = fileToUri(filePath);
629
+ const lockKey = `${client.name}:${uri}`;
630
+ throwIfAborted(signal);
631
+
632
+ const existingLock = fileOperationLocks.get(lockKey);
633
+ if (existingLock) {
634
+ await untilAborted(signal, () => existingLock);
635
+ }
636
+
637
+ const syncPromise = (async () => {
638
+ // Clear stale diagnostics before syncing new content
639
+ client.diagnostics.delete(uri);
640
+
641
+ const info = client.openFiles.get(uri);
642
+
643
+ if (!info) {
644
+ // Open file with provided content instead of reading from disk
645
+ const languageId = detectLanguageId(filePath);
646
+ throwIfAborted(signal);
647
+ await sendNotification(client, "textDocument/didOpen", {
648
+ textDocument: {
649
+ uri,
650
+ languageId,
651
+ version: 1,
652
+ text: content,
653
+ },
654
+ });
655
+ client.openFiles.set(uri, { version: 1, languageId });
656
+ client.lastActivity = Date.now();
657
+ return;
658
+ }
659
+
660
+ const version = ++info.version;
661
+ throwIfAborted(signal);
662
+ await sendNotification(client, "textDocument/didChange", {
663
+ textDocument: { uri, version },
664
+ contentChanges: [{ text: content }],
665
+ });
666
+ client.lastActivity = Date.now();
667
+ })();
668
+
669
+ fileOperationLocks.set(lockKey, syncPromise);
670
+ try {
671
+ await syncPromise;
672
+ } finally {
673
+ fileOperationLocks.delete(lockKey);
674
+ }
675
+ }
676
+
677
+ /**
678
+ * Notify LSP that a file was saved.
679
+ * Assumes content was already synced via syncContent - just sends didSave.
680
+ */
681
+ export async function notifySaved(client: LspClient, filePath: string, signal?: AbortSignal): Promise<void> {
682
+ const uri = fileToUri(filePath);
683
+ const info = client.openFiles.get(uri);
684
+ if (!info) return; // File not open, nothing to notify
685
+
686
+ throwIfAborted(signal);
687
+ await sendNotification(client, "textDocument/didSave", {
688
+ textDocument: { uri },
689
+ });
690
+ client.lastActivity = Date.now();
691
+ }
692
+
693
+ /**
694
+ * Refresh a file in the LSP client.
695
+ * Increments version, sends didChange and didSave notifications.
696
+ */
697
+ export async function refreshFile(client: LspClient, filePath: string, signal?: AbortSignal): Promise<void> {
698
+ throwIfAborted(signal);
699
+ const uri = fileToUri(filePath);
700
+ const lockKey = `${client.name}:${uri}`;
701
+
702
+ const existingLock = fileOperationLocks.get(lockKey);
703
+ if (existingLock) {
704
+ await untilAborted(signal, () => existingLock);
705
+ }
706
+
707
+ const refreshPromise = (async () => {
708
+ throwIfAborted(signal);
709
+ // Drop cached diagnostics for this URI before asking the server to recompute.
710
+ // Otherwise an unrelated publishDiagnostics notification can advance the global
711
+ // diagnostics version and cause waiters to accept stale unversioned diagnostics.
712
+ client.diagnostics.delete(uri);
713
+ const info = client.openFiles.get(uri);
714
+
715
+ if (!info) {
716
+ await ensureFileOpen(client, filePath, signal);
717
+ return;
718
+ }
719
+
720
+ let content: string;
721
+ try {
722
+ content = await Bun.file(filePath).text();
723
+ throwIfAborted(signal);
724
+ } catch (err) {
725
+ if (isEnoent(err)) return;
726
+ throw err;
727
+ }
728
+ const version = ++info.version;
729
+ throwIfAborted(signal);
730
+
731
+ await sendNotification(client, "textDocument/didChange", {
732
+ textDocument: { uri, version },
733
+ contentChanges: [{ text: content }],
734
+ });
735
+ throwIfAborted(signal);
736
+
737
+ await sendNotification(client, "textDocument/didSave", {
738
+ textDocument: { uri },
739
+ text: content,
740
+ });
741
+
742
+ client.lastActivity = Date.now();
743
+ })();
744
+
745
+ fileOperationLocks.set(lockKey, refreshPromise);
746
+ try {
747
+ await refreshPromise;
748
+ } finally {
749
+ fileOperationLocks.delete(lockKey);
750
+ }
751
+ }
752
+
753
+ /**
754
+ * Shutdown a specific client by key.
755
+ */
756
+ export function shutdownClient(key: string): void {
757
+ const client = clients.get(key);
758
+ if (!client) return;
759
+
760
+ // Reject all pending requests
761
+ for (const pending of Array.from(client.pendingRequests.values())) {
762
+ pending.reject(new Error("LSP client shutdown"));
763
+ }
764
+ client.pendingRequests.clear();
765
+
766
+ // Send shutdown request (best effort, don't wait)
767
+ sendRequest(client, "shutdown", null).catch(() => {});
768
+
769
+ // Kill process
770
+ client.proc.kill();
771
+ clients.delete(key);
772
+ }
773
+
774
+ // =============================================================================
775
+ // LSP Protocol Methods
776
+ // =============================================================================
777
+
778
+ /** Default timeout for LSP requests (30 seconds) */
779
+ const DEFAULT_REQUEST_TIMEOUT_MS = 30000;
780
+
781
+ /**
782
+ * Send an LSP request and wait for response.
783
+ */
784
+ export async function sendRequest(
785
+ client: LspClient,
786
+ method: string,
787
+ params: unknown,
788
+ signal?: AbortSignal,
789
+ timeoutMs: number = DEFAULT_REQUEST_TIMEOUT_MS,
790
+ ): Promise<unknown> {
791
+ // Atomically increment and capture request ID
792
+ const id = ++client.requestId;
793
+ if (signal?.aborted) {
794
+ const reason = signal.reason instanceof Error ? signal.reason : new ToolAbortError();
795
+ return Promise.reject(reason);
796
+ }
797
+
798
+ const request: LspJsonRpcRequest = {
799
+ jsonrpc: "2.0",
800
+ id,
801
+ method,
802
+ params,
803
+ };
804
+
805
+ client.lastActivity = Date.now();
806
+
807
+ const { promise, resolve, reject } = Promise.withResolvers<unknown>();
808
+ let timeout: NodeJS.Timeout | undefined;
809
+ const cleanup = () => {
810
+ if (signal) {
811
+ signal.removeEventListener("abort", abortHandler);
812
+ }
813
+ };
814
+ const abortHandler = () => {
815
+ if (client.pendingRequests.has(id)) {
816
+ client.pendingRequests.delete(id);
817
+ }
818
+ void sendNotification(client, "$/cancelRequest", { id }).catch(() => {});
819
+ if (timeout) clearTimeout(timeout);
820
+ cleanup();
821
+ const reason = signal?.reason instanceof Error ? signal.reason : new ToolAbortError();
822
+ reject(reason);
823
+ };
824
+
825
+ // Set timeout
826
+ timeout = setTimeout(() => {
827
+ if (client.pendingRequests.has(id)) {
828
+ client.pendingRequests.delete(id);
829
+ const err = new Error(`LSP request ${method} timed out after ${timeoutMs}ms`);
830
+ cleanup();
831
+ reject(err);
832
+ }
833
+ }, timeoutMs);
834
+ if (signal) {
835
+ signal.addEventListener("abort", abortHandler, { once: true });
836
+ if (signal.aborted) {
837
+ abortHandler();
838
+ return promise;
839
+ }
840
+ }
841
+
842
+ // Register pending request with timeout wrapper
843
+ client.pendingRequests.set(id, {
844
+ resolve: result => {
845
+ if (timeout) clearTimeout(timeout);
846
+ cleanup();
847
+ resolve(result);
848
+ },
849
+ reject: err => {
850
+ if (timeout) clearTimeout(timeout);
851
+ cleanup();
852
+ reject(err);
853
+ },
854
+ method,
855
+ });
856
+
857
+ // Write request
858
+ writeMessage(client.proc.stdin, request).catch(err => {
859
+ if (timeout) clearTimeout(timeout);
860
+ client.pendingRequests.delete(id);
861
+ cleanup();
862
+ reject(err);
863
+ });
864
+ return promise;
865
+ }
866
+
867
+ /**
868
+ * Send an LSP notification (no response expected).
869
+ */
870
+ export async function sendNotification(client: LspClient, method: string, params: unknown): Promise<void> {
871
+ const notification: LspJsonRpcNotification = {
872
+ jsonrpc: "2.0",
873
+ method,
874
+ params,
875
+ };
876
+
877
+ client.lastActivity = Date.now();
878
+ await writeMessage(client.proc.stdin, notification);
879
+ }
880
+
881
+ /**
882
+ * Shutdown all LSP clients.
883
+ */
884
+ export function shutdownAll(): void {
885
+ const clientsToShutdown = Array.from(clients.values());
886
+ clients.clear();
887
+
888
+ const err = new Error("LSP client shutdown");
889
+ for (const client of clientsToShutdown) {
890
+ /// Reject all pending requests
891
+ const reqs = Array.from(client.pendingRequests.values());
892
+ client.pendingRequests.clear();
893
+ for (const pending of reqs) {
894
+ pending.reject(err);
895
+ }
896
+
897
+ void (async () => {
898
+ // Send shutdown request (best effort, don't wait)
899
+ const timeout = Bun.sleep(5_000);
900
+ const result = sendRequest(client, "shutdown", null).catch(() => {});
901
+ await Promise.race([result, timeout]);
902
+ client.proc.kill();
903
+ })().catch(() => {});
904
+ }
905
+ }
906
+
907
+ /** Status of an LSP server */
908
+ export interface LspServerStatus {
909
+ name: string;
910
+ status: "connecting" | "ready" | "error";
911
+ fileTypes: string[];
912
+ error?: string;
913
+ }
914
+
915
+ /**
916
+ * Get status of all active LSP clients.
917
+ */
918
+ export function getActiveClients(): LspServerStatus[] {
919
+ return Array.from(clients.values()).map(client => ({
920
+ name: client.config.command,
921
+ status: "ready" as const,
922
+ fileTypes: client.config.fileTypes,
923
+ }));
924
+ }
925
+
926
+ // =============================================================================
927
+ // Process Cleanup
928
+ // =============================================================================
929
+
930
+ // Register cleanup on module unload
931
+ if (typeof process !== "undefined") {
932
+ process.on("beforeExit", shutdownAll);
933
+ process.on("SIGINT", () => {
934
+ shutdownAll();
935
+ process.exit(0);
936
+ });
937
+ process.on("SIGTERM", () => {
938
+ shutdownAll();
939
+ process.exit(0);
940
+ });
941
+ }