@wahack/pi-coding-agent 15.11.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 (1152) hide show
  1. package/CHANGELOG.md +10031 -0
  2. package/README.md +36 -0
  3. package/examples/README.md +21 -0
  4. package/examples/custom-tools/README.md +104 -0
  5. package/examples/custom-tools/hello/index.ts +20 -0
  6. package/examples/extensions/README.md +142 -0
  7. package/examples/extensions/api-demo.ts +79 -0
  8. package/examples/extensions/chalk-logger.ts +25 -0
  9. package/examples/extensions/hello.ts +31 -0
  10. package/examples/extensions/pirate.ts +43 -0
  11. package/examples/extensions/plan-mode.ts +549 -0
  12. package/examples/extensions/reload-runtime.ts +38 -0
  13. package/examples/extensions/thinking-note.ts +13 -0
  14. package/examples/extensions/tools.ts +145 -0
  15. package/examples/extensions/with-deps/index.ts +36 -0
  16. package/examples/extensions/with-deps/package-lock.json +31 -0
  17. package/examples/extensions/with-deps/package.json +17 -0
  18. package/examples/hooks/README.md +56 -0
  19. package/examples/hooks/auto-commit-on-exit.ts +48 -0
  20. package/examples/hooks/confirm-destructive.ts +58 -0
  21. package/examples/hooks/custom-compaction.ts +115 -0
  22. package/examples/hooks/dirty-repo-guard.ts +51 -0
  23. package/examples/hooks/file-trigger.ts +40 -0
  24. package/examples/hooks/git-checkpoint.ts +52 -0
  25. package/examples/hooks/handoff.ts +149 -0
  26. package/examples/hooks/permission-gate.ts +33 -0
  27. package/examples/hooks/protected-paths.ts +29 -0
  28. package/examples/hooks/qna.ts +118 -0
  29. package/examples/hooks/status-line.ts +39 -0
  30. package/examples/sdk/01-minimal.ts +21 -0
  31. package/examples/sdk/02-custom-model.ts +49 -0
  32. package/examples/sdk/03-custom-prompt.ts +46 -0
  33. package/examples/sdk/04-skills.ts +43 -0
  34. package/examples/sdk/06-extensions.ts +82 -0
  35. package/examples/sdk/06-hooks.ts +61 -0
  36. package/examples/sdk/07-context-files.ts +35 -0
  37. package/examples/sdk/08-prompt-templates.ts +41 -0
  38. package/examples/sdk/08-slash-commands.ts +46 -0
  39. package/examples/sdk/09-api-keys-and-oauth.ts +54 -0
  40. package/examples/sdk/11-sessions.ts +47 -0
  41. package/examples/sdk/12-redis-sessions.ts +54 -0
  42. package/examples/sdk/13-sql-sessions.ts +61 -0
  43. package/examples/sdk/README.md +172 -0
  44. package/package.json +554 -0
  45. package/scripts/build-binary.ts +100 -0
  46. package/scripts/bundle-dist.ts +90 -0
  47. package/scripts/format-prompts.ts +68 -0
  48. package/scripts/generate-docs-index.ts +40 -0
  49. package/scripts/generate-template.ts +33 -0
  50. package/scripts/omp +42 -0
  51. package/scripts/omp.ts +19 -0
  52. package/src/async/index.ts +1 -0
  53. package/src/async/job-manager.ts +625 -0
  54. package/src/auto-thinking/classifier.ts +185 -0
  55. package/src/autoresearch/command-resume.md +14 -0
  56. package/src/autoresearch/dashboard.ts +436 -0
  57. package/src/autoresearch/git.ts +319 -0
  58. package/src/autoresearch/helpers.ts +218 -0
  59. package/src/autoresearch/index.ts +536 -0
  60. package/src/autoresearch/prompt-setup.md +43 -0
  61. package/src/autoresearch/prompt.md +103 -0
  62. package/src/autoresearch/resume-message.md +10 -0
  63. package/src/autoresearch/state.ts +273 -0
  64. package/src/autoresearch/storage.ts +699 -0
  65. package/src/autoresearch/tools/init-experiment.ts +272 -0
  66. package/src/autoresearch/tools/log-experiment.ts +524 -0
  67. package/src/autoresearch/tools/run-experiment.ts +407 -0
  68. package/src/autoresearch/tools/update-notes.ts +109 -0
  69. package/src/autoresearch/types.ts +168 -0
  70. package/src/bun-imports.d.ts +28 -0
  71. package/src/capability/context-file.ts +44 -0
  72. package/src/capability/extension-module.ts +34 -0
  73. package/src/capability/extension.ts +47 -0
  74. package/src/capability/fs.ts +117 -0
  75. package/src/capability/hook.ts +40 -0
  76. package/src/capability/index.ts +436 -0
  77. package/src/capability/instruction.ts +37 -0
  78. package/src/capability/mcp.ts +74 -0
  79. package/src/capability/prompt.ts +35 -0
  80. package/src/capability/rule-buckets.ts +66 -0
  81. package/src/capability/rule.ts +261 -0
  82. package/src/capability/settings.ts +34 -0
  83. package/src/capability/skill.ts +63 -0
  84. package/src/capability/slash-command.ts +40 -0
  85. package/src/capability/ssh.ts +41 -0
  86. package/src/capability/system-prompt.ts +34 -0
  87. package/src/capability/tool.ts +38 -0
  88. package/src/capability/types.ts +168 -0
  89. package/src/cli/agents-cli.ts +138 -0
  90. package/src/cli/args.ts +340 -0
  91. package/src/cli/auth-broker-cli.ts +895 -0
  92. package/src/cli/auth-gateway-cli.ts +611 -0
  93. package/src/cli/classify-install-target.ts +76 -0
  94. package/src/cli/claude-trace-cli.ts +795 -0
  95. package/src/cli/commands/init-xdg.ts +27 -0
  96. package/src/cli/completion-gen.ts +550 -0
  97. package/src/cli/config-cli.ts +418 -0
  98. package/src/cli/dry-balance-cli.ts +856 -0
  99. package/src/cli/extension-flags.ts +48 -0
  100. package/src/cli/file-processor.ts +133 -0
  101. package/src/cli/gallery-cli.ts +230 -0
  102. package/src/cli/gallery-fixtures/agentic.ts +407 -0
  103. package/src/cli/gallery-fixtures/codeintel.ts +187 -0
  104. package/src/cli/gallery-fixtures/edit.ts +194 -0
  105. package/src/cli/gallery-fixtures/fs.ts +220 -0
  106. package/src/cli/gallery-fixtures/index.ts +40 -0
  107. package/src/cli/gallery-fixtures/interaction.ts +49 -0
  108. package/src/cli/gallery-fixtures/memory.ts +81 -0
  109. package/src/cli/gallery-fixtures/misc.ts +250 -0
  110. package/src/cli/gallery-fixtures/search.ts +213 -0
  111. package/src/cli/gallery-fixtures/shell.ts +167 -0
  112. package/src/cli/gallery-fixtures/types.ts +57 -0
  113. package/src/cli/gallery-fixtures/web.ts +158 -0
  114. package/src/cli/gallery-screenshot.ts +279 -0
  115. package/src/cli/grep-cli.ts +160 -0
  116. package/src/cli/grievances-cli.ts +256 -0
  117. package/src/cli/initial-message.ts +58 -0
  118. package/src/cli/list-models.ts +194 -0
  119. package/src/cli/plugin-cli.ts +996 -0
  120. package/src/cli/read-cli.ts +57 -0
  121. package/src/cli/session-picker.ts +79 -0
  122. package/src/cli/setup-cli.ts +231 -0
  123. package/src/cli/shell-cli.ts +176 -0
  124. package/src/cli/ssh-cli.ts +179 -0
  125. package/src/cli/startup-cwd.ts +68 -0
  126. package/src/cli/stats-cli.ts +238 -0
  127. package/src/cli/tiny-models-cli.ts +127 -0
  128. package/src/cli/update-cli.ts +611 -0
  129. package/src/cli/usage-cli.ts +603 -0
  130. package/src/cli/web-search-cli.ts +132 -0
  131. package/src/cli/worktree-cli.ts +291 -0
  132. package/src/cli-commands.ts +79 -0
  133. package/src/cli.ts +200 -0
  134. package/src/commands/acp.ts +24 -0
  135. package/src/commands/agents.ts +57 -0
  136. package/src/commands/auth-broker.ts +99 -0
  137. package/src/commands/auth-gateway.ts +69 -0
  138. package/src/commands/commit.ts +46 -0
  139. package/src/commands/complete.ts +66 -0
  140. package/src/commands/completions.ts +60 -0
  141. package/src/commands/config.ts +51 -0
  142. package/src/commands/dry-balance.ts +43 -0
  143. package/src/commands/gallery.ts +52 -0
  144. package/src/commands/grep.ts +48 -0
  145. package/src/commands/grievances.ts +51 -0
  146. package/src/commands/install.ts +107 -0
  147. package/src/commands/launch.ts +169 -0
  148. package/src/commands/plugin.ts +78 -0
  149. package/src/commands/read.ts +38 -0
  150. package/src/commands/setup.ts +67 -0
  151. package/src/commands/shell.ts +29 -0
  152. package/src/commands/ssh.ts +60 -0
  153. package/src/commands/stats.ts +29 -0
  154. package/src/commands/tiny-models.ts +36 -0
  155. package/src/commands/update.ts +21 -0
  156. package/src/commands/usage.ts +35 -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 +317 -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 +146 -0
  168. package/src/commit/agentic/tools/git-file-diff.ts +191 -0
  169. package/src/commit/agentic/tools/git-hunk.ts +50 -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 +144 -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 +23 -0
  176. package/src/commit/agentic/tools/split-commit.ts +245 -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 +105 -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 +97 -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 +92 -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 +77 -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 +60 -0
  216. package/src/config/append-only-context-mode.ts +31 -0
  217. package/src/config/config-file.ts +317 -0
  218. package/src/config/file-lock.ts +164 -0
  219. package/src/config/keybindings.ts +628 -0
  220. package/src/config/mcp-schema.json +230 -0
  221. package/src/config/model-discovery.ts +554 -0
  222. package/src/config/model-registry.ts +2090 -0
  223. package/src/config/model-resolver.ts +1502 -0
  224. package/src/config/model-roles.ts +74 -0
  225. package/src/config/models-config-schema.ts +226 -0
  226. package/src/config/models-config.ts +129 -0
  227. package/src/config/prompt-templates.ts +185 -0
  228. package/src/config/resolve-config-value.ts +94 -0
  229. package/src/config/settings-schema.ts +3530 -0
  230. package/src/config/settings.ts +1178 -0
  231. package/src/config.ts +242 -0
  232. package/src/cursor.ts +340 -0
  233. package/src/dap/client.ts +760 -0
  234. package/src/dap/config.ts +189 -0
  235. package/src/dap/defaults.json +212 -0
  236. package/src/dap/index.ts +4 -0
  237. package/src/dap/session.ts +1441 -0
  238. package/src/dap/types.ts +610 -0
  239. package/src/debug/index.ts +515 -0
  240. package/src/debug/log-formatting.ts +58 -0
  241. package/src/debug/log-viewer.ts +908 -0
  242. package/src/debug/profiler.ts +162 -0
  243. package/src/debug/protocol-probe.ts +267 -0
  244. package/src/debug/raw-sse-buffer.ts +273 -0
  245. package/src/debug/raw-sse.ts +292 -0
  246. package/src/debug/report-bundle.ts +374 -0
  247. package/src/debug/system-info.ts +111 -0
  248. package/src/debug/terminal-info.ts +124 -0
  249. package/src/discovery/agents-md.ts +67 -0
  250. package/src/discovery/agents.ts +230 -0
  251. package/src/discovery/at-imports.ts +273 -0
  252. package/src/discovery/builtin-defaults.ts +39 -0
  253. package/src/discovery/builtin-rules/index.ts +54 -0
  254. package/src/discovery/builtin-rules/rs-box-leak.md +48 -0
  255. package/src/discovery/builtin-rules/rs-future-prelude.md +23 -0
  256. package/src/discovery/builtin-rules/rs-lazylock.md +51 -0
  257. package/src/discovery/builtin-rules/rs-match-ergonomics.md +67 -0
  258. package/src/discovery/builtin-rules/rs-parking-lot.md +44 -0
  259. package/src/discovery/builtin-rules/rs-result-type.md +19 -0
  260. package/src/discovery/builtin-rules/ts-bare-catch.md +38 -0
  261. package/src/discovery/builtin-rules/ts-import-type.md +42 -0
  262. package/src/discovery/builtin-rules/ts-no-any.md +56 -0
  263. package/src/discovery/builtin-rules/ts-no-deprecated-leftovers.md +44 -0
  264. package/src/discovery/builtin-rules/ts-no-dynamic-import.md +39 -0
  265. package/src/discovery/builtin-rules/ts-no-return-type.md +45 -0
  266. package/src/discovery/builtin-rules/ts-no-test-timers.md +55 -0
  267. package/src/discovery/builtin-rules/ts-no-tiny-functions.md +51 -0
  268. package/src/discovery/builtin-rules/ts-promise-with-resolvers.md +65 -0
  269. package/src/discovery/builtin-rules/ts-redundant-clear-guard.md +75 -0
  270. package/src/discovery/builtin-rules/ts-set-map.md +28 -0
  271. package/src/discovery/builtin.ts +906 -0
  272. package/src/discovery/claude-plugins.ts +386 -0
  273. package/src/discovery/claude.ts +584 -0
  274. package/src/discovery/cline.ts +83 -0
  275. package/src/discovery/codex.ts +522 -0
  276. package/src/discovery/cursor.ts +220 -0
  277. package/src/discovery/gemini.ts +383 -0
  278. package/src/discovery/github.ts +154 -0
  279. package/src/discovery/helpers.ts +1016 -0
  280. package/src/discovery/index.ts +81 -0
  281. package/src/discovery/mcp-json.ts +171 -0
  282. package/src/discovery/omp-extension-roots.ts +190 -0
  283. package/src/discovery/omp-plugins.ts +383 -0
  284. package/src/discovery/opencode.ts +398 -0
  285. package/src/discovery/plugin-dir-roots.ts +28 -0
  286. package/src/discovery/ssh.ts +153 -0
  287. package/src/discovery/substitute-plugin-root.ts +29 -0
  288. package/src/discovery/vscode.ts +105 -0
  289. package/src/discovery/windsurf.ts +147 -0
  290. package/src/edit/apply-patch/index.ts +87 -0
  291. package/src/edit/apply-patch/parser.ts +174 -0
  292. package/src/edit/diff.ts +999 -0
  293. package/src/edit/file-snapshot-store.ts +91 -0
  294. package/src/edit/hashline/block-resolver.ts +33 -0
  295. package/src/edit/hashline/diff.ts +290 -0
  296. package/src/edit/hashline/execute.ts +242 -0
  297. package/src/edit/hashline/filesystem.ts +130 -0
  298. package/src/edit/hashline/index.ts +5 -0
  299. package/src/edit/hashline/noop-loop-guard.ts +99 -0
  300. package/src/edit/hashline/params.ts +18 -0
  301. package/src/edit/index.ts +571 -0
  302. package/src/edit/modes/apply-patch.lark +19 -0
  303. package/src/edit/modes/apply-patch.ts +53 -0
  304. package/src/edit/modes/patch.ts +1891 -0
  305. package/src/edit/modes/replace.ts +1137 -0
  306. package/src/edit/normalize.ts +345 -0
  307. package/src/edit/notebook.ts +242 -0
  308. package/src/edit/read-file.ts +25 -0
  309. package/src/edit/renderer.ts +769 -0
  310. package/src/edit/streaming.ts +517 -0
  311. package/src/eval/__tests__/agent-bridge.test.ts +708 -0
  312. package/src/eval/__tests__/bridge-timeout.test.ts +64 -0
  313. package/src/eval/__tests__/budget-bridge.test.ts +69 -0
  314. package/src/eval/__tests__/completion-bridge.test.ts +412 -0
  315. package/src/eval/__tests__/helpers-local-roots.test.ts +58 -0
  316. package/src/eval/__tests__/idle-timeout.test.ts +80 -0
  317. package/src/eval/__tests__/js-context-manager.test.ts +241 -0
  318. package/src/eval/__tests__/kernel-spawn.test.ts +103 -0
  319. package/src/eval/agent-bridge.ts +319 -0
  320. package/src/eval/backend.ts +71 -0
  321. package/src/eval/bridge-timeout.ts +44 -0
  322. package/src/eval/budget-bridge.ts +48 -0
  323. package/src/eval/completion-bridge.ts +207 -0
  324. package/src/eval/concurrency-bridge.ts +34 -0
  325. package/src/eval/idle-timeout.ts +91 -0
  326. package/src/eval/index.ts +4 -0
  327. package/src/eval/js/context-manager.ts +502 -0
  328. package/src/eval/js/executor.ts +173 -0
  329. package/src/eval/js/index.ts +51 -0
  330. package/src/eval/js/shared/helpers.ts +283 -0
  331. package/src/eval/js/shared/indirect-eval.ts +30 -0
  332. package/src/eval/js/shared/local-module-loader.ts +342 -0
  333. package/src/eval/js/shared/prelude.ts +2 -0
  334. package/src/eval/js/shared/prelude.txt +246 -0
  335. package/src/eval/js/shared/rewrite-imports.ts +532 -0
  336. package/src/eval/js/shared/runtime.ts +352 -0
  337. package/src/eval/js/shared/types.ts +18 -0
  338. package/src/eval/js/tool-bridge.ts +162 -0
  339. package/src/eval/js/worker-core.ts +132 -0
  340. package/src/eval/js/worker-entry.ts +30 -0
  341. package/src/eval/js/worker-protocol.ts +47 -0
  342. package/src/eval/py/__tests__/prelude.test.ts +19 -0
  343. package/src/eval/py/display.ts +71 -0
  344. package/src/eval/py/executor.ts +742 -0
  345. package/src/eval/py/index.ts +68 -0
  346. package/src/eval/py/kernel.ts +748 -0
  347. package/src/eval/py/prelude.py +658 -0
  348. package/src/eval/py/prelude.ts +3 -0
  349. package/src/eval/py/runner.py +1133 -0
  350. package/src/eval/py/runtime.ts +276 -0
  351. package/src/eval/py/spawn-options.ts +126 -0
  352. package/src/eval/py/tool-bridge.ts +182 -0
  353. package/src/eval/session-id.ts +8 -0
  354. package/src/eval/types.ts +48 -0
  355. package/src/exa/index.ts +2 -0
  356. package/src/exa/mcp-client.ts +370 -0
  357. package/src/exa/types.ts +69 -0
  358. package/src/exec/bash-executor.ts +419 -0
  359. package/src/exec/exec.ts +53 -0
  360. package/src/exec/non-interactive-env.ts +48 -0
  361. package/src/export/custom-share.ts +65 -0
  362. package/src/export/html/index.ts +164 -0
  363. package/src/export/html/template.css +1051 -0
  364. package/src/export/html/template.generated.ts +2 -0
  365. package/src/export/html/template.html +46 -0
  366. package/src/export/html/template.js +2271 -0
  367. package/src/export/html/template.macro.ts +25 -0
  368. package/src/export/html/vendor/highlight.min.js +1213 -0
  369. package/src/export/html/vendor/marked.min.js +6 -0
  370. package/src/export/ttsr.ts +583 -0
  371. package/src/extensibility/custom-commands/bundled/ci-green/index.ts +54 -0
  372. package/src/extensibility/custom-commands/bundled/review/index.ts +489 -0
  373. package/src/extensibility/custom-commands/index.ts +2 -0
  374. package/src/extensibility/custom-commands/loader.ts +238 -0
  375. package/src/extensibility/custom-commands/types.ts +113 -0
  376. package/src/extensibility/custom-tools/index.ts +7 -0
  377. package/src/extensibility/custom-tools/loader.ts +269 -0
  378. package/src/extensibility/custom-tools/types.ts +270 -0
  379. package/src/extensibility/custom-tools/wrapper.ts +47 -0
  380. package/src/extensibility/extensions/compact-handler.ts +40 -0
  381. package/src/extensibility/extensions/get-commands-handler.ts +78 -0
  382. package/src/extensibility/extensions/index.ts +16 -0
  383. package/src/extensibility/extensions/loader.ts +572 -0
  384. package/src/extensibility/extensions/runner.ts +922 -0
  385. package/src/extensibility/extensions/types.ts +1322 -0
  386. package/src/extensibility/extensions/wrapper.ts +223 -0
  387. package/src/extensibility/hooks/index.ts +5 -0
  388. package/src/extensibility/hooks/loader.ts +257 -0
  389. package/src/extensibility/hooks/runner.ts +425 -0
  390. package/src/extensibility/hooks/tool-wrapper.ts +107 -0
  391. package/src/extensibility/hooks/types.ts +606 -0
  392. package/src/extensibility/legacy-pi-ai-shim.ts +24 -0
  393. package/src/extensibility/legacy-pi-coding-agent-shim.ts +15 -0
  394. package/src/extensibility/plugins/doctor.ts +65 -0
  395. package/src/extensibility/plugins/git-url.ts +367 -0
  396. package/src/extensibility/plugins/index.ts +9 -0
  397. package/src/extensibility/plugins/installer.ts +192 -0
  398. package/src/extensibility/plugins/legacy-pi-compat.ts +682 -0
  399. package/src/extensibility/plugins/loader.ts +313 -0
  400. package/src/extensibility/plugins/manager.ts +827 -0
  401. package/src/extensibility/plugins/marketplace/cache.ts +136 -0
  402. package/src/extensibility/plugins/marketplace/fetcher.ts +317 -0
  403. package/src/extensibility/plugins/marketplace/index.ts +6 -0
  404. package/src/extensibility/plugins/marketplace/manager.ts +770 -0
  405. package/src/extensibility/plugins/marketplace/registry.ts +196 -0
  406. package/src/extensibility/plugins/marketplace/source-resolver.ts +147 -0
  407. package/src/extensibility/plugins/marketplace/types.ts +191 -0
  408. package/src/extensibility/plugins/marketplace-auto-update.ts +49 -0
  409. package/src/extensibility/plugins/parser.ts +105 -0
  410. package/src/extensibility/plugins/types.ts +194 -0
  411. package/src/extensibility/shared-events.ts +343 -0
  412. package/src/extensibility/skills.ts +312 -0
  413. package/src/extensibility/slash-commands.ts +227 -0
  414. package/src/extensibility/tool-proxy.ts +25 -0
  415. package/src/extensibility/typebox.ts +418 -0
  416. package/src/extensibility/utils.ts +44 -0
  417. package/src/goals/index.ts +3 -0
  418. package/src/goals/runtime.ts +528 -0
  419. package/src/goals/state.ts +37 -0
  420. package/src/goals/tools/goal-tool.ts +251 -0
  421. package/src/hindsight/backend.ts +354 -0
  422. package/src/hindsight/bank.ts +156 -0
  423. package/src/hindsight/client.ts +598 -0
  424. package/src/hindsight/config.ts +175 -0
  425. package/src/hindsight/content.ts +210 -0
  426. package/src/hindsight/index.ts +8 -0
  427. package/src/hindsight/mental-models.ts +429 -0
  428. package/src/hindsight/seeds.json +32 -0
  429. package/src/hindsight/state.ts +488 -0
  430. package/src/hindsight/transcript.ts +71 -0
  431. package/src/index.ts +59 -0
  432. package/src/internal-urls/agent-protocol.ts +146 -0
  433. package/src/internal-urls/artifact-protocol.ts +107 -0
  434. package/src/internal-urls/docs-index.generated.ts +106 -0
  435. package/src/internal-urls/history-protocol.ts +113 -0
  436. package/src/internal-urls/index.ts +25 -0
  437. package/src/internal-urls/issue-pr-protocol.ts +584 -0
  438. package/src/internal-urls/json-query.ts +126 -0
  439. package/src/internal-urls/local-protocol.ts +287 -0
  440. package/src/internal-urls/mcp-protocol.ts +151 -0
  441. package/src/internal-urls/memory-protocol.ts +169 -0
  442. package/src/internal-urls/omp-protocol.ts +93 -0
  443. package/src/internal-urls/parse.ts +72 -0
  444. package/src/internal-urls/registry-helpers.ts +25 -0
  445. package/src/internal-urls/router.ts +105 -0
  446. package/src/internal-urls/rule-protocol.ts +45 -0
  447. package/src/internal-urls/skill-protocol.ts +96 -0
  448. package/src/internal-urls/types.ts +152 -0
  449. package/src/internal-urls/vault-protocol.ts +936 -0
  450. package/src/irc/bus.ts +292 -0
  451. package/src/lib/xai-http.ts +124 -0
  452. package/src/lsp/client.ts +1193 -0
  453. package/src/lsp/clients/biome-client.ts +264 -0
  454. package/src/lsp/clients/index.ts +50 -0
  455. package/src/lsp/clients/lsp-linter-client.ts +93 -0
  456. package/src/lsp/clients/swiftlint-client.ts +120 -0
  457. package/src/lsp/config.ts +502 -0
  458. package/src/lsp/defaults.json +493 -0
  459. package/src/lsp/diagnostics-ledger.ts +51 -0
  460. package/src/lsp/edits.ts +267 -0
  461. package/src/lsp/index.ts +2477 -0
  462. package/src/lsp/lspmux.ts +233 -0
  463. package/src/lsp/render.ts +694 -0
  464. package/src/lsp/startup-events.ts +13 -0
  465. package/src/lsp/types.ts +455 -0
  466. package/src/lsp/utils.ts +718 -0
  467. package/src/main.ts +1325 -0
  468. package/src/mcp/client.ts +484 -0
  469. package/src/mcp/config-writer.ts +225 -0
  470. package/src/mcp/config.ts +365 -0
  471. package/src/mcp/index.ts +29 -0
  472. package/src/mcp/json-rpc.ts +122 -0
  473. package/src/mcp/loader.ts +124 -0
  474. package/src/mcp/manager.ts +1275 -0
  475. package/src/mcp/oauth-discovery.ts +442 -0
  476. package/src/mcp/oauth-flow.ts +442 -0
  477. package/src/mcp/render.ts +132 -0
  478. package/src/mcp/smithery-auth.ts +104 -0
  479. package/src/mcp/smithery-connect.ts +145 -0
  480. package/src/mcp/smithery-registry.ts +477 -0
  481. package/src/mcp/timeout.ts +59 -0
  482. package/src/mcp/tool-bridge.ts +426 -0
  483. package/src/mcp/tool-cache.ts +117 -0
  484. package/src/mcp/transports/http.ts +519 -0
  485. package/src/mcp/transports/index.ts +6 -0
  486. package/src/mcp/transports/stdio.ts +528 -0
  487. package/src/mcp/types.ts +423 -0
  488. package/src/memories/index.ts +1150 -0
  489. package/src/memories/storage.ts +577 -0
  490. package/src/memory-backend/index.ts +18 -0
  491. package/src/memory-backend/local-backend.ts +39 -0
  492. package/src/memory-backend/off-backend.ts +25 -0
  493. package/src/memory-backend/resolve.ts +25 -0
  494. package/src/memory-backend/runtime.ts +66 -0
  495. package/src/memory-backend/types.ts +166 -0
  496. package/src/mnemopi/backend.ts +547 -0
  497. package/src/mnemopi/config.ts +160 -0
  498. package/src/mnemopi/index.ts +3 -0
  499. package/src/mnemopi/state.ts +584 -0
  500. package/src/modes/acp/acp-agent.ts +2407 -0
  501. package/src/modes/acp/acp-client-bridge.ts +154 -0
  502. package/src/modes/acp/acp-event-mapper.ts +929 -0
  503. package/src/modes/acp/acp-mode.ts +23 -0
  504. package/src/modes/acp/index.ts +2 -0
  505. package/src/modes/acp/terminal-auth.ts +37 -0
  506. package/src/modes/components/agent-dashboard.ts +1206 -0
  507. package/src/modes/components/agent-hub.ts +1071 -0
  508. package/src/modes/components/assistant-message.ts +307 -0
  509. package/src/modes/components/bash-execution.ts +220 -0
  510. package/src/modes/components/bordered-loader.ts +41 -0
  511. package/src/modes/components/branch-summary-message.ts +45 -0
  512. package/src/modes/components/btw-panel.ts +104 -0
  513. package/src/modes/components/chat-block.ts +111 -0
  514. package/src/modes/components/compaction-summary-message.ts +87 -0
  515. package/src/modes/components/copy-selector.ts +206 -0
  516. package/src/modes/components/countdown-timer.ts +75 -0
  517. package/src/modes/components/custom-editor.ts +398 -0
  518. package/src/modes/components/custom-message.ts +63 -0
  519. package/src/modes/components/diff.ts +277 -0
  520. package/src/modes/components/dynamic-border.ts +34 -0
  521. package/src/modes/components/error-banner.ts +33 -0
  522. package/src/modes/components/eval-execution.ts +158 -0
  523. package/src/modes/components/execution-shared.ts +101 -0
  524. package/src/modes/components/extensions/extension-dashboard.ts +399 -0
  525. package/src/modes/components/extensions/extension-list.ts +502 -0
  526. package/src/modes/components/extensions/index.ts +9 -0
  527. package/src/modes/components/extensions/inspector-panel.ts +317 -0
  528. package/src/modes/components/extensions/state-manager.ts +627 -0
  529. package/src/modes/components/extensions/types.ts +186 -0
  530. package/src/modes/components/footer.ts +274 -0
  531. package/src/modes/components/history-search.ts +280 -0
  532. package/src/modes/components/hook-editor.ts +167 -0
  533. package/src/modes/components/hook-input.ts +87 -0
  534. package/src/modes/components/hook-message.ts +66 -0
  535. package/src/modes/components/hook-selector.ts +660 -0
  536. package/src/modes/components/index.ts +38 -0
  537. package/src/modes/components/keybinding-hints.ts +65 -0
  538. package/src/modes/components/late-diagnostics-message.ts +60 -0
  539. package/src/modes/components/login-dialog.ts +164 -0
  540. package/src/modes/components/mcp-add-wizard.ts +1340 -0
  541. package/src/modes/components/message-frame.ts +88 -0
  542. package/src/modes/components/model-selector.ts +1271 -0
  543. package/src/modes/components/oauth-selector.ts +368 -0
  544. package/src/modes/components/omfg-panel.ts +141 -0
  545. package/src/modes/components/overlay-box.ts +108 -0
  546. package/src/modes/components/plan-review-overlay.ts +820 -0
  547. package/src/modes/components/plan-toc.ts +138 -0
  548. package/src/modes/components/plugin-selector.ts +95 -0
  549. package/src/modes/components/plugin-settings.ts +722 -0
  550. package/src/modes/components/queue-mode-selector.ts +56 -0
  551. package/src/modes/components/read-tool-group.ts +670 -0
  552. package/src/modes/components/segment-track.ts +52 -0
  553. package/src/modes/components/session-selector.ts +625 -0
  554. package/src/modes/components/settings-defs.ts +189 -0
  555. package/src/modes/components/settings-selector.ts +651 -0
  556. package/src/modes/components/show-images-selector.ts +45 -0
  557. package/src/modes/components/skill-message.ts +89 -0
  558. package/src/modes/components/status-line/component.ts +869 -0
  559. package/src/modes/components/status-line/context-thresholds.ts +79 -0
  560. package/src/modes/components/status-line/git-utils.ts +42 -0
  561. package/src/modes/components/status-line/index.ts +5 -0
  562. package/src/modes/components/status-line/presets.ts +106 -0
  563. package/src/modes/components/status-line/segments.ts +584 -0
  564. package/src/modes/components/status-line/separators.ts +55 -0
  565. package/src/modes/components/status-line/token-rate.ts +66 -0
  566. package/src/modes/components/status-line/types.ts +108 -0
  567. package/src/modes/components/theme-selector.ts +63 -0
  568. package/src/modes/components/thinking-selector.ts +52 -0
  569. package/src/modes/components/tiny-title-download-progress.ts +90 -0
  570. package/src/modes/components/tips.txt +19 -0
  571. package/src/modes/components/todo-reminder.ts +38 -0
  572. package/src/modes/components/tool-execution.ts +1024 -0
  573. package/src/modes/components/transcript-container.ts +608 -0
  574. package/src/modes/components/tree-selector.ts +978 -0
  575. package/src/modes/components/ttsr-notification.ts +122 -0
  576. package/src/modes/components/user-message-selector.ts +227 -0
  577. package/src/modes/components/user-message.ts +66 -0
  578. package/src/modes/components/visual-truncate.ts +63 -0
  579. package/src/modes/components/welcome.ts +493 -0
  580. package/src/modes/controllers/btw-controller.ts +105 -0
  581. package/src/modes/controllers/command-controller-shared.ts +109 -0
  582. package/src/modes/controllers/command-controller.ts +1566 -0
  583. package/src/modes/controllers/event-controller.ts +1054 -0
  584. package/src/modes/controllers/extension-ui-controller.ts +886 -0
  585. package/src/modes/controllers/input-controller.ts +1073 -0
  586. package/src/modes/controllers/mcp-command-controller.ts +2017 -0
  587. package/src/modes/controllers/omfg-controller.ts +283 -0
  588. package/src/modes/controllers/omfg-rule.ts +647 -0
  589. package/src/modes/controllers/selector-controller.ts +1108 -0
  590. package/src/modes/controllers/ssh-command-controller.ts +384 -0
  591. package/src/modes/controllers/streaming-reveal.ts +279 -0
  592. package/src/modes/controllers/tan-command-controller.ts +173 -0
  593. package/src/modes/controllers/todo-command-controller.ts +485 -0
  594. package/src/modes/data/emojis.json +1 -0
  595. package/src/modes/emoji-autocomplete.ts +285 -0
  596. package/src/modes/gradient-highlight.ts +87 -0
  597. package/src/modes/image-references.ts +117 -0
  598. package/src/modes/index.ts +17 -0
  599. package/src/modes/interactive-mode.ts +3370 -0
  600. package/src/modes/internal-url-autocomplete.ts +143 -0
  601. package/src/modes/loop-limit.ts +140 -0
  602. package/src/modes/magic-keywords.ts +20 -0
  603. package/src/modes/markdown-prose.ts +247 -0
  604. package/src/modes/oauth-manual-input.ts +69 -0
  605. package/src/modes/orchestrate.ts +42 -0
  606. package/src/modes/print-mode.ts +126 -0
  607. package/src/modes/prompt-action-autocomplete.ts +260 -0
  608. package/src/modes/rpc/host-tools.ts +186 -0
  609. package/src/modes/rpc/host-uris.ts +235 -0
  610. package/src/modes/rpc/rpc-client.ts +963 -0
  611. package/src/modes/rpc/rpc-mode.ts +947 -0
  612. package/src/modes/rpc/rpc-subagents.ts +265 -0
  613. package/src/modes/rpc/rpc-types.ts +458 -0
  614. package/src/modes/runtime-init.ts +116 -0
  615. package/src/modes/session-observer-registry.ts +146 -0
  616. package/src/modes/setup-version.ts +11 -0
  617. package/src/modes/setup-wizard/index.ts +99 -0
  618. package/src/modes/setup-wizard/lazy.ts +16 -0
  619. package/src/modes/setup-wizard/scenes/glyph.ts +96 -0
  620. package/src/modes/setup-wizard/scenes/outro.ts +35 -0
  621. package/src/modes/setup-wizard/scenes/providers.ts +69 -0
  622. package/src/modes/setup-wizard/scenes/sign-in.ts +205 -0
  623. package/src/modes/setup-wizard/scenes/splash.ts +201 -0
  624. package/src/modes/setup-wizard/scenes/theme.ts +299 -0
  625. package/src/modes/setup-wizard/scenes/types.ts +48 -0
  626. package/src/modes/setup-wizard/scenes/web-search.ts +129 -0
  627. package/src/modes/setup-wizard/wizard-overlay.ts +275 -0
  628. package/src/modes/shared.ts +47 -0
  629. package/src/modes/theme/dark.json +95 -0
  630. package/src/modes/theme/defaults/alabaster.json +93 -0
  631. package/src/modes/theme/defaults/amethyst.json +96 -0
  632. package/src/modes/theme/defaults/anthracite.json +93 -0
  633. package/src/modes/theme/defaults/basalt.json +91 -0
  634. package/src/modes/theme/defaults/birch.json +95 -0
  635. package/src/modes/theme/defaults/dark-abyss.json +91 -0
  636. package/src/modes/theme/defaults/dark-arctic.json +104 -0
  637. package/src/modes/theme/defaults/dark-aurora.json +95 -0
  638. package/src/modes/theme/defaults/dark-catppuccin.json +107 -0
  639. package/src/modes/theme/defaults/dark-cavern.json +91 -0
  640. package/src/modes/theme/defaults/dark-copper.json +95 -0
  641. package/src/modes/theme/defaults/dark-cosmos.json +90 -0
  642. package/src/modes/theme/defaults/dark-cyberpunk.json +102 -0
  643. package/src/modes/theme/defaults/dark-dracula.json +98 -0
  644. package/src/modes/theme/defaults/dark-eclipse.json +91 -0
  645. package/src/modes/theme/defaults/dark-ember.json +95 -0
  646. package/src/modes/theme/defaults/dark-equinox.json +90 -0
  647. package/src/modes/theme/defaults/dark-forest.json +96 -0
  648. package/src/modes/theme/defaults/dark-github.json +105 -0
  649. package/src/modes/theme/defaults/dark-gruvbox.json +112 -0
  650. package/src/modes/theme/defaults/dark-lavender.json +95 -0
  651. package/src/modes/theme/defaults/dark-lunar.json +89 -0
  652. package/src/modes/theme/defaults/dark-midnight.json +95 -0
  653. package/src/modes/theme/defaults/dark-monochrome.json +94 -0
  654. package/src/modes/theme/defaults/dark-monokai.json +98 -0
  655. package/src/modes/theme/defaults/dark-nebula.json +90 -0
  656. package/src/modes/theme/defaults/dark-nord.json +97 -0
  657. package/src/modes/theme/defaults/dark-ocean.json +101 -0
  658. package/src/modes/theme/defaults/dark-one.json +100 -0
  659. package/src/modes/theme/defaults/dark-poimandres.json +142 -0
  660. package/src/modes/theme/defaults/dark-rainforest.json +91 -0
  661. package/src/modes/theme/defaults/dark-reef.json +91 -0
  662. package/src/modes/theme/defaults/dark-retro.json +92 -0
  663. package/src/modes/theme/defaults/dark-rose-pine.json +96 -0
  664. package/src/modes/theme/defaults/dark-sakura.json +95 -0
  665. package/src/modes/theme/defaults/dark-slate.json +95 -0
  666. package/src/modes/theme/defaults/dark-solarized.json +97 -0
  667. package/src/modes/theme/defaults/dark-solstice.json +90 -0
  668. package/src/modes/theme/defaults/dark-starfall.json +91 -0
  669. package/src/modes/theme/defaults/dark-sunset.json +99 -0
  670. package/src/modes/theme/defaults/dark-swamp.json +90 -0
  671. package/src/modes/theme/defaults/dark-synthwave.json +103 -0
  672. package/src/modes/theme/defaults/dark-taiga.json +91 -0
  673. package/src/modes/theme/defaults/dark-terminal.json +95 -0
  674. package/src/modes/theme/defaults/dark-tokyo-night.json +101 -0
  675. package/src/modes/theme/defaults/dark-tundra.json +91 -0
  676. package/src/modes/theme/defaults/dark-twilight.json +91 -0
  677. package/src/modes/theme/defaults/dark-volcanic.json +91 -0
  678. package/src/modes/theme/defaults/graphite.json +92 -0
  679. package/src/modes/theme/defaults/index.ts +199 -0
  680. package/src/modes/theme/defaults/light-arctic.json +107 -0
  681. package/src/modes/theme/defaults/light-aurora-day.json +91 -0
  682. package/src/modes/theme/defaults/light-canyon.json +91 -0
  683. package/src/modes/theme/defaults/light-catppuccin.json +106 -0
  684. package/src/modes/theme/defaults/light-cirrus.json +90 -0
  685. package/src/modes/theme/defaults/light-coral.json +95 -0
  686. package/src/modes/theme/defaults/light-cyberpunk.json +96 -0
  687. package/src/modes/theme/defaults/light-dawn.json +90 -0
  688. package/src/modes/theme/defaults/light-dunes.json +91 -0
  689. package/src/modes/theme/defaults/light-eucalyptus.json +95 -0
  690. package/src/modes/theme/defaults/light-forest.json +100 -0
  691. package/src/modes/theme/defaults/light-frost.json +95 -0
  692. package/src/modes/theme/defaults/light-github.json +115 -0
  693. package/src/modes/theme/defaults/light-glacier.json +91 -0
  694. package/src/modes/theme/defaults/light-gruvbox.json +108 -0
  695. package/src/modes/theme/defaults/light-haze.json +90 -0
  696. package/src/modes/theme/defaults/light-honeycomb.json +95 -0
  697. package/src/modes/theme/defaults/light-lagoon.json +91 -0
  698. package/src/modes/theme/defaults/light-lavender.json +95 -0
  699. package/src/modes/theme/defaults/light-meadow.json +91 -0
  700. package/src/modes/theme/defaults/light-mint.json +95 -0
  701. package/src/modes/theme/defaults/light-monochrome.json +101 -0
  702. package/src/modes/theme/defaults/light-ocean.json +99 -0
  703. package/src/modes/theme/defaults/light-one.json +99 -0
  704. package/src/modes/theme/defaults/light-opal.json +91 -0
  705. package/src/modes/theme/defaults/light-orchard.json +91 -0
  706. package/src/modes/theme/defaults/light-paper.json +95 -0
  707. package/src/modes/theme/defaults/light-poimandres.json +142 -0
  708. package/src/modes/theme/defaults/light-prism.json +90 -0
  709. package/src/modes/theme/defaults/light-retro.json +98 -0
  710. package/src/modes/theme/defaults/light-sand.json +95 -0
  711. package/src/modes/theme/defaults/light-savanna.json +91 -0
  712. package/src/modes/theme/defaults/light-solarized.json +102 -0
  713. package/src/modes/theme/defaults/light-soleil.json +90 -0
  714. package/src/modes/theme/defaults/light-sunset.json +99 -0
  715. package/src/modes/theme/defaults/light-synthwave.json +98 -0
  716. package/src/modes/theme/defaults/light-tokyo-night.json +111 -0
  717. package/src/modes/theme/defaults/light-wetland.json +91 -0
  718. package/src/modes/theme/defaults/light-zenith.json +89 -0
  719. package/src/modes/theme/defaults/limestone.json +94 -0
  720. package/src/modes/theme/defaults/mahogany.json +97 -0
  721. package/src/modes/theme/defaults/marble.json +93 -0
  722. package/src/modes/theme/defaults/obsidian.json +91 -0
  723. package/src/modes/theme/defaults/onyx.json +91 -0
  724. package/src/modes/theme/defaults/pearl.json +93 -0
  725. package/src/modes/theme/defaults/porcelain.json +91 -0
  726. package/src/modes/theme/defaults/quartz.json +96 -0
  727. package/src/modes/theme/defaults/sandstone.json +95 -0
  728. package/src/modes/theme/defaults/titanium.json +90 -0
  729. package/src/modes/theme/light.json +93 -0
  730. package/src/modes/theme/mermaid-cache.ts +29 -0
  731. package/src/modes/theme/shimmer.ts +235 -0
  732. package/src/modes/theme/theme-schema.json +459 -0
  733. package/src/modes/theme/theme.ts +2676 -0
  734. package/src/modes/turn-budget.ts +31 -0
  735. package/src/modes/types.ts +359 -0
  736. package/src/modes/ultrathink.ts +41 -0
  737. package/src/modes/utils/context-usage.ts +339 -0
  738. package/src/modes/utils/copy-targets.ts +360 -0
  739. package/src/modes/utils/hotkeys-markdown.ts +61 -0
  740. package/src/modes/utils/keybinding-matchers.ts +51 -0
  741. package/src/modes/utils/tools-markdown.ts +27 -0
  742. package/src/modes/utils/ui-helpers.ts +801 -0
  743. package/src/modes/workflow.ts +42 -0
  744. package/src/plan-mode/approved-plan.ts +186 -0
  745. package/src/plan-mode/plan-handoff.ts +37 -0
  746. package/src/plan-mode/plan-protection.ts +31 -0
  747. package/src/plan-mode/state.ts +6 -0
  748. package/src/priority.json +41 -0
  749. package/src/prompts/agents/designer.md +66 -0
  750. package/src/prompts/agents/explore.md +58 -0
  751. package/src/prompts/agents/frontmatter.md +11 -0
  752. package/src/prompts/agents/init.md +33 -0
  753. package/src/prompts/agents/librarian.md +119 -0
  754. package/src/prompts/agents/oracle.md +55 -0
  755. package/src/prompts/agents/plan.md +48 -0
  756. package/src/prompts/agents/reviewer.md +140 -0
  757. package/src/prompts/agents/task.md +16 -0
  758. package/src/prompts/ci-green-request.md +36 -0
  759. package/src/prompts/dry-balance-bench.md +8 -0
  760. package/src/prompts/goals/goal-budget-limit.md +16 -0
  761. package/src/prompts/goals/goal-continuation.md +28 -0
  762. package/src/prompts/goals/goal-mode-active.md +23 -0
  763. package/src/prompts/memories/consolidation.md +30 -0
  764. package/src/prompts/memories/read-path.md +11 -0
  765. package/src/prompts/memories/stage_one_input.md +6 -0
  766. package/src/prompts/memories/stage_one_system.md +21 -0
  767. package/src/prompts/review-custom-request.md +22 -0
  768. package/src/prompts/review-headless-request.md +16 -0
  769. package/src/prompts/review-request.md +69 -0
  770. package/src/prompts/steering/user-interjection.md +10 -0
  771. package/src/prompts/system/agent-creation-architect.md +50 -0
  772. package/src/prompts/system/agent-creation-user.md +6 -0
  773. package/src/prompts/system/auto-continue.md +1 -0
  774. package/src/prompts/system/auto-thinking-difficulty-local.md +14 -0
  775. package/src/prompts/system/auto-thinking-difficulty.md +12 -0
  776. package/src/prompts/system/background-tan-dispatch.md +8 -0
  777. package/src/prompts/system/btw-user.md +8 -0
  778. package/src/prompts/system/commit-message-system.md +14 -0
  779. package/src/prompts/system/custom-system-prompt.md +64 -0
  780. package/src/prompts/system/eager-todo.md +13 -0
  781. package/src/prompts/system/empty-stop-retry.md +6 -0
  782. package/src/prompts/system/irc-incoming.md +7 -0
  783. package/src/prompts/system/manual-continue.md +7 -0
  784. package/src/prompts/system/memory-consolidation-system.md +8 -0
  785. package/src/prompts/system/memory-extraction-system.md +26 -0
  786. package/src/prompts/system/omfg-user.md +50 -0
  787. package/src/prompts/system/orchestrate-notice.md +40 -0
  788. package/src/prompts/system/plan-mode-active.md +109 -0
  789. package/src/prompts/system/plan-mode-approved.md +25 -0
  790. package/src/prompts/system/plan-mode-compact-instructions.md +16 -0
  791. package/src/prompts/system/plan-mode-reference.md +11 -0
  792. package/src/prompts/system/plan-mode-subagent.md +33 -0
  793. package/src/prompts/system/plan-mode-tool-decision-reminder.md +9 -0
  794. package/src/prompts/system/project-prompt.md +52 -0
  795. package/src/prompts/system/subagent-system-prompt.md +64 -0
  796. package/src/prompts/system/subagent-user-prompt.md +3 -0
  797. package/src/prompts/system/subagent-yield-reminder.md +12 -0
  798. package/src/prompts/system/system-prompt.md +258 -0
  799. package/src/prompts/system/tiny-title-system.md +8 -0
  800. package/src/prompts/system/title-system.md +16 -0
  801. package/src/prompts/system/ttsr-interrupt.md +7 -0
  802. package/src/prompts/system/ttsr-tool-reminder.md +5 -0
  803. package/src/prompts/system/ultrathink-notice.md +3 -0
  804. package/src/prompts/system/web-search.md +25 -0
  805. package/src/prompts/system/workflow-notice.md +70 -0
  806. package/src/prompts/tools/apply-patch.md +65 -0
  807. package/src/prompts/tools/ask.md +30 -0
  808. package/src/prompts/tools/ast-edit.md +39 -0
  809. package/src/prompts/tools/ast-grep.md +42 -0
  810. package/src/prompts/tools/async-result.md +8 -0
  811. package/src/prompts/tools/bash.md +46 -0
  812. package/src/prompts/tools/browser.md +73 -0
  813. package/src/prompts/tools/checkpoint.md +16 -0
  814. package/src/prompts/tools/debug.md +34 -0
  815. package/src/prompts/tools/eval.md +92 -0
  816. package/src/prompts/tools/find.md +36 -0
  817. package/src/prompts/tools/github.md +21 -0
  818. package/src/prompts/tools/goal.md +18 -0
  819. package/src/prompts/tools/image-gen.md +7 -0
  820. package/src/prompts/tools/inspect-image-system.md +20 -0
  821. package/src/prompts/tools/inspect-image.md +32 -0
  822. package/src/prompts/tools/irc.md +59 -0
  823. package/src/prompts/tools/job.md +19 -0
  824. package/src/prompts/tools/lsp-late-diagnostic.md +8 -0
  825. package/src/prompts/tools/lsp.md +42 -0
  826. package/src/prompts/tools/memory-edit.md +8 -0
  827. package/src/prompts/tools/patch.md +70 -0
  828. package/src/prompts/tools/read.md +84 -0
  829. package/src/prompts/tools/recall.md +5 -0
  830. package/src/prompts/tools/reflect.md +5 -0
  831. package/src/prompts/tools/render-mermaid.md +9 -0
  832. package/src/prompts/tools/replace.md +30 -0
  833. package/src/prompts/tools/resolve.md +9 -0
  834. package/src/prompts/tools/retain.md +6 -0
  835. package/src/prompts/tools/rewind.md +13 -0
  836. package/src/prompts/tools/search-tool-bm25.md +32 -0
  837. package/src/prompts/tools/search.md +24 -0
  838. package/src/prompts/tools/ssh.md +31 -0
  839. package/src/prompts/tools/task-summary.md +17 -0
  840. package/src/prompts/tools/task.md +88 -0
  841. package/src/prompts/tools/todo.md +62 -0
  842. package/src/prompts/tools/web-search.md +10 -0
  843. package/src/prompts/tools/write.md +14 -0
  844. package/src/registry/agent-lifecycle.ts +218 -0
  845. package/src/registry/agent-registry.ts +151 -0
  846. package/src/sdk.ts +2558 -0
  847. package/src/secrets/index.ts +123 -0
  848. package/src/secrets/obfuscator.ts +298 -0
  849. package/src/secrets/regex.ts +21 -0
  850. package/src/session/agent-session.ts +10121 -0
  851. package/src/session/agent-storage.ts +455 -0
  852. package/src/session/artifacts.ts +135 -0
  853. package/src/session/auth-broker-config.ts +131 -0
  854. package/src/session/auth-storage.ts +29 -0
  855. package/src/session/blob-store.ts +255 -0
  856. package/src/session/client-bridge.ts +85 -0
  857. package/src/session/history-storage.ts +348 -0
  858. package/src/session/indexed-session-storage.ts +430 -0
  859. package/src/session/messages.ts +541 -0
  860. package/src/session/redis-session-storage.ts +170 -0
  861. package/src/session/session-dump-format.ts +209 -0
  862. package/src/session/session-history-format.ts +246 -0
  863. package/src/session/session-manager.ts +3676 -0
  864. package/src/session/session-storage.ts +529 -0
  865. package/src/session/shake-types.ts +43 -0
  866. package/src/session/sql-session-storage.ts +314 -0
  867. package/src/session/streaming-output.ts +1330 -0
  868. package/src/session/tool-choice-queue.ts +213 -0
  869. package/src/session/yield-queue.ts +173 -0
  870. package/src/slash-commands/acp-builtins.ts +70 -0
  871. package/src/slash-commands/builtin-registry.ts +1798 -0
  872. package/src/slash-commands/helpers/context-report.ts +39 -0
  873. package/src/slash-commands/helpers/format.ts +46 -0
  874. package/src/slash-commands/helpers/marketplace-manager.ts +25 -0
  875. package/src/slash-commands/helpers/mcp.ts +532 -0
  876. package/src/slash-commands/helpers/parse.ts +85 -0
  877. package/src/slash-commands/helpers/ssh.ts +195 -0
  878. package/src/slash-commands/helpers/stats-dashboard.ts +85 -0
  879. package/src/slash-commands/helpers/todo.ts +279 -0
  880. package/src/slash-commands/helpers/usage-report.ts +95 -0
  881. package/src/slash-commands/marketplace-install-parser.ts +99 -0
  882. package/src/slash-commands/types.ts +135 -0
  883. package/src/ssh/config-writer.ts +183 -0
  884. package/src/ssh/connection-manager.ts +509 -0
  885. package/src/ssh/ssh-executor.ts +189 -0
  886. package/src/ssh/sshfs-mount.ts +140 -0
  887. package/src/ssh/utils.ts +8 -0
  888. package/src/stt/downloader.ts +71 -0
  889. package/src/stt/index.ts +3 -0
  890. package/src/stt/recorder.ts +351 -0
  891. package/src/stt/setup.ts +52 -0
  892. package/src/stt/stt-controller.ts +160 -0
  893. package/src/stt/transcribe.py +70 -0
  894. package/src/stt/transcriber.ts +91 -0
  895. package/src/stubs/natives/index.ts +814 -0
  896. package/src/stubs/natives/package.json +7 -0
  897. package/src/stubs/tui/index.ts +282 -0
  898. package/src/stubs/tui/package.json +7 -0
  899. package/src/system-prompt.ts +611 -0
  900. package/src/task/agents.ts +167 -0
  901. package/src/task/commands.ts +132 -0
  902. package/src/task/discovery.ts +122 -0
  903. package/src/task/executor.ts +2133 -0
  904. package/src/task/index.ts +1419 -0
  905. package/src/task/name-generator.ts +1577 -0
  906. package/src/task/omp-command.ts +26 -0
  907. package/src/task/output-manager.ts +88 -0
  908. package/src/task/parallel.ts +116 -0
  909. package/src/task/render.ts +1381 -0
  910. package/src/task/repair-args.ts +129 -0
  911. package/src/task/subprocess-tool-registry.ts +88 -0
  912. package/src/task/types.ts +336 -0
  913. package/src/task/worktree.ts +514 -0
  914. package/src/telemetry-export.ts +144 -0
  915. package/src/thinking.ts +167 -0
  916. package/src/tiny/compiled-runtime.ts +179 -0
  917. package/src/tiny/device.ts +111 -0
  918. package/src/tiny/dtype.ts +101 -0
  919. package/src/tiny/models.ts +242 -0
  920. package/src/tiny/text.ts +165 -0
  921. package/src/tiny/title-client.ts +543 -0
  922. package/src/tiny/title-protocol.ts +56 -0
  923. package/src/tiny/worker.ts +568 -0
  924. package/src/tool-discovery/mode.ts +24 -0
  925. package/src/tool-discovery/tool-index.ts +256 -0
  926. package/src/tools/approval.ts +189 -0
  927. package/src/tools/archive-reader.ts +721 -0
  928. package/src/tools/ask.ts +928 -0
  929. package/src/tools/ast-edit.ts +642 -0
  930. package/src/tools/ast-grep.ts +452 -0
  931. package/src/tools/auto-generated-guard.ts +322 -0
  932. package/src/tools/bash-command-fixup.ts +37 -0
  933. package/src/tools/bash-interactive.ts +408 -0
  934. package/src/tools/bash-interceptor.ts +67 -0
  935. package/src/tools/bash-pty-selection.ts +14 -0
  936. package/src/tools/bash-skill-urls.ts +248 -0
  937. package/src/tools/bash.ts +1386 -0
  938. package/src/tools/browser/attach.ts +175 -0
  939. package/src/tools/browser/launch.ts +660 -0
  940. package/src/tools/browser/readable.ts +112 -0
  941. package/src/tools/browser/registry.ts +197 -0
  942. package/src/tools/browser/render.ts +216 -0
  943. package/src/tools/browser/tab-protocol.ts +105 -0
  944. package/src/tools/browser/tab-supervisor.ts +628 -0
  945. package/src/tools/browser/tab-worker-entry.ts +21 -0
  946. package/src/tools/browser/tab-worker.ts +1226 -0
  947. package/src/tools/browser.ts +343 -0
  948. package/src/tools/checkpoint.ts +136 -0
  949. package/src/tools/conflict-detect.ts +718 -0
  950. package/src/tools/context.ts +39 -0
  951. package/src/tools/debug.ts +1067 -0
  952. package/src/tools/eval-backends.ts +27 -0
  953. package/src/tools/eval-render.ts +752 -0
  954. package/src/tools/eval.ts +577 -0
  955. package/src/tools/fetch.ts +1926 -0
  956. package/src/tools/file-recorder.ts +35 -0
  957. package/src/tools/find.ts +609 -0
  958. package/src/tools/fs-cache-invalidation.ts +28 -0
  959. package/src/tools/gh-cache-invalidation.ts +255 -0
  960. package/src/tools/gh-format.ts +12 -0
  961. package/src/tools/gh-renderer.ts +481 -0
  962. package/src/tools/gh.ts +3720 -0
  963. package/src/tools/github-cache.ts +637 -0
  964. package/src/tools/grouped-file-output.ts +210 -0
  965. package/src/tools/image-gen.ts +1517 -0
  966. package/src/tools/index.ts +599 -0
  967. package/src/tools/inspect-image-renderer.ts +132 -0
  968. package/src/tools/inspect-image.ts +174 -0
  969. package/src/tools/irc.ts +723 -0
  970. package/src/tools/job.ts +557 -0
  971. package/src/tools/json-tree.ts +243 -0
  972. package/src/tools/jtd-to-json-schema.ts +219 -0
  973. package/src/tools/jtd-to-typescript.ts +136 -0
  974. package/src/tools/jtd-utils.ts +102 -0
  975. package/src/tools/list-limit.ts +40 -0
  976. package/src/tools/match-line-format.ts +20 -0
  977. package/src/tools/memory-edit.ts +59 -0
  978. package/src/tools/memory-recall.ts +100 -0
  979. package/src/tools/memory-reflect.ts +88 -0
  980. package/src/tools/memory-render.ts +202 -0
  981. package/src/tools/memory-retain.ts +91 -0
  982. package/src/tools/output-meta.ts +754 -0
  983. package/src/tools/output-schema-validator.ts +132 -0
  984. package/src/tools/path-utils.ts +1054 -0
  985. package/src/tools/plan-mode-guard.ts +108 -0
  986. package/src/tools/puppeteer/00_stealth_tampering.txt +63 -0
  987. package/src/tools/puppeteer/01_stealth_activity.txt +20 -0
  988. package/src/tools/puppeteer/02_stealth_hairline.txt +11 -0
  989. package/src/tools/puppeteer/03_stealth_botd.txt +384 -0
  990. package/src/tools/puppeteer/04_stealth_iframe.txt +81 -0
  991. package/src/tools/puppeteer/05_stealth_webgl.txt +75 -0
  992. package/src/tools/puppeteer/06_stealth_screen.txt +72 -0
  993. package/src/tools/puppeteer/07_stealth_fonts.txt +97 -0
  994. package/src/tools/puppeteer/08_stealth_audio.txt +51 -0
  995. package/src/tools/puppeteer/09_stealth_locale.txt +46 -0
  996. package/src/tools/puppeteer/10_stealth_plugins.txt +206 -0
  997. package/src/tools/puppeteer/11_stealth_hardware.txt +8 -0
  998. package/src/tools/puppeteer/12_stealth_codecs.txt +40 -0
  999. package/src/tools/puppeteer/13_stealth_worker.txt +74 -0
  1000. package/src/tools/read.ts +2929 -0
  1001. package/src/tools/render-mermaid.ts +69 -0
  1002. package/src/tools/render-utils.ts +838 -0
  1003. package/src/tools/renderers.ts +77 -0
  1004. package/src/tools/report-tool-issue.ts +534 -0
  1005. package/src/tools/resolve.ts +276 -0
  1006. package/src/tools/review.ts +253 -0
  1007. package/src/tools/search-tool-bm25.ts +351 -0
  1008. package/src/tools/search.ts +1580 -0
  1009. package/src/tools/sqlite-reader.ts +828 -0
  1010. package/src/tools/ssh.ts +349 -0
  1011. package/src/tools/todo.ts +982 -0
  1012. package/src/tools/tool-errors.ts +62 -0
  1013. package/src/tools/tool-result.ts +94 -0
  1014. package/src/tools/tool-timeouts.ts +30 -0
  1015. package/src/tools/tts.ts +133 -0
  1016. package/src/tools/write.ts +1217 -0
  1017. package/src/tools/yield.ts +269 -0
  1018. package/src/tui/code-cell.ts +216 -0
  1019. package/src/tui/file-list.ts +55 -0
  1020. package/src/tui/hyperlink.ts +175 -0
  1021. package/src/tui/index.ts +12 -0
  1022. package/src/tui/output-block.ts +240 -0
  1023. package/src/tui/status-line.ts +54 -0
  1024. package/src/tui/tree-list.ts +84 -0
  1025. package/src/tui/types.ts +15 -0
  1026. package/src/tui/utils.ts +103 -0
  1027. package/src/utils/block-context.ts +312 -0
  1028. package/src/utils/changelog.ts +132 -0
  1029. package/src/utils/clipboard.ts +193 -0
  1030. package/src/utils/command-args.ts +76 -0
  1031. package/src/utils/commit-message-generator.ts +151 -0
  1032. package/src/utils/edit-mode.ts +41 -0
  1033. package/src/utils/enhanced-paste.ts +230 -0
  1034. package/src/utils/event-bus.ts +33 -0
  1035. package/src/utils/external-editor.ts +65 -0
  1036. package/src/utils/file-display-mode.ts +45 -0
  1037. package/src/utils/file-mentions.ts +281 -0
  1038. package/src/utils/git.ts +1833 -0
  1039. package/src/utils/image-loading.ts +132 -0
  1040. package/src/utils/image-resize.ts +309 -0
  1041. package/src/utils/jj.ts +248 -0
  1042. package/src/utils/lang-from-path.ts +239 -0
  1043. package/src/utils/markit.ts +89 -0
  1044. package/src/utils/open.ts +55 -0
  1045. package/src/utils/session-color.ts +68 -0
  1046. package/src/utils/shell-snapshot.ts +187 -0
  1047. package/src/utils/sixel.ts +69 -0
  1048. package/src/utils/title-generator.ts +373 -0
  1049. package/src/utils/tool-choice.ts +33 -0
  1050. package/src/utils/tools-manager.ts +363 -0
  1051. package/src/web/kagi.ts +305 -0
  1052. package/src/web/parallel.ts +353 -0
  1053. package/src/web/scrapers/artifacthub.ts +207 -0
  1054. package/src/web/scrapers/arxiv.ts +83 -0
  1055. package/src/web/scrapers/aur.ts +162 -0
  1056. package/src/web/scrapers/biorxiv.ts +133 -0
  1057. package/src/web/scrapers/bluesky.ts +262 -0
  1058. package/src/web/scrapers/brew.ts +172 -0
  1059. package/src/web/scrapers/cheatsh.ts +68 -0
  1060. package/src/web/scrapers/chocolatey.ts +196 -0
  1061. package/src/web/scrapers/choosealicense.ts +95 -0
  1062. package/src/web/scrapers/cisa-kev.ts +87 -0
  1063. package/src/web/scrapers/clojars.ts +154 -0
  1064. package/src/web/scrapers/coingecko.ts +177 -0
  1065. package/src/web/scrapers/crates-io.ts +97 -0
  1066. package/src/web/scrapers/crossref.ts +136 -0
  1067. package/src/web/scrapers/devto.ts +147 -0
  1068. package/src/web/scrapers/discogs.ts +306 -0
  1069. package/src/web/scrapers/discourse.ts +197 -0
  1070. package/src/web/scrapers/dockerhub.ts +138 -0
  1071. package/src/web/scrapers/docs-rs.ts +653 -0
  1072. package/src/web/scrapers/fdroid.ts +134 -0
  1073. package/src/web/scrapers/firefox-addons.ts +191 -0
  1074. package/src/web/scrapers/flathub.ts +223 -0
  1075. package/src/web/scrapers/github-gist.ts +58 -0
  1076. package/src/web/scrapers/github.ts +704 -0
  1077. package/src/web/scrapers/gitlab.ts +401 -0
  1078. package/src/web/scrapers/go-pkg.ts +266 -0
  1079. package/src/web/scrapers/hackage.ts +140 -0
  1080. package/src/web/scrapers/hackernews.ts +189 -0
  1081. package/src/web/scrapers/hex.ts +105 -0
  1082. package/src/web/scrapers/huggingface.ts +321 -0
  1083. package/src/web/scrapers/iacr.ts +89 -0
  1084. package/src/web/scrapers/index.ts +252 -0
  1085. package/src/web/scrapers/jetbrains-marketplace.ts +159 -0
  1086. package/src/web/scrapers/lemmy.ts +203 -0
  1087. package/src/web/scrapers/lobsters.ts +175 -0
  1088. package/src/web/scrapers/mastodon.ts +292 -0
  1089. package/src/web/scrapers/maven.ts +138 -0
  1090. package/src/web/scrapers/mdn.ts +173 -0
  1091. package/src/web/scrapers/metacpan.ts +222 -0
  1092. package/src/web/scrapers/musicbrainz.ts +250 -0
  1093. package/src/web/scrapers/npm.ts +98 -0
  1094. package/src/web/scrapers/nuget.ts +183 -0
  1095. package/src/web/scrapers/nvd.ts +222 -0
  1096. package/src/web/scrapers/ollama.ts +239 -0
  1097. package/src/web/scrapers/open-vsx.ts +106 -0
  1098. package/src/web/scrapers/opencorporates.ts +292 -0
  1099. package/src/web/scrapers/openlibrary.ts +336 -0
  1100. package/src/web/scrapers/orcid.ts +286 -0
  1101. package/src/web/scrapers/osv.ts +176 -0
  1102. package/src/web/scrapers/packagist.ts +160 -0
  1103. package/src/web/scrapers/pub-dev.ts +143 -0
  1104. package/src/web/scrapers/pubmed.ts +211 -0
  1105. package/src/web/scrapers/pypi.ts +112 -0
  1106. package/src/web/scrapers/rawg.ts +110 -0
  1107. package/src/web/scrapers/readthedocs.ts +120 -0
  1108. package/src/web/scrapers/reddit.ts +95 -0
  1109. package/src/web/scrapers/repology.ts +251 -0
  1110. package/src/web/scrapers/rfc.ts +201 -0
  1111. package/src/web/scrapers/rubygems.ts +103 -0
  1112. package/src/web/scrapers/searchcode.ts +189 -0
  1113. package/src/web/scrapers/sec-edgar.ts +261 -0
  1114. package/src/web/scrapers/semantic-scholar.ts +171 -0
  1115. package/src/web/scrapers/snapcraft.ts +187 -0
  1116. package/src/web/scrapers/sourcegraph.ts +336 -0
  1117. package/src/web/scrapers/spdx.ts +108 -0
  1118. package/src/web/scrapers/spotify.ts +198 -0
  1119. package/src/web/scrapers/stackoverflow.ts +120 -0
  1120. package/src/web/scrapers/terraform.ts +277 -0
  1121. package/src/web/scrapers/tldr.ts +47 -0
  1122. package/src/web/scrapers/twitter.ts +94 -0
  1123. package/src/web/scrapers/types.ts +397 -0
  1124. package/src/web/scrapers/utils.ts +109 -0
  1125. package/src/web/scrapers/vimeo.ts +133 -0
  1126. package/src/web/scrapers/vscode-marketplace.ts +187 -0
  1127. package/src/web/scrapers/w3c.ts +156 -0
  1128. package/src/web/scrapers/wikidata.ts +344 -0
  1129. package/src/web/scrapers/wikipedia.ts +84 -0
  1130. package/src/web/scrapers/youtube.ts +325 -0
  1131. package/src/web/search/index.ts +292 -0
  1132. package/src/web/search/provider.ts +157 -0
  1133. package/src/web/search/providers/anthropic.ts +318 -0
  1134. package/src/web/search/providers/base.ts +89 -0
  1135. package/src/web/search/providers/brave.ts +152 -0
  1136. package/src/web/search/providers/codex.ts +591 -0
  1137. package/src/web/search/providers/exa.ts +400 -0
  1138. package/src/web/search/providers/gemini.ts +460 -0
  1139. package/src/web/search/providers/jina.ts +111 -0
  1140. package/src/web/search/providers/kagi.ts +86 -0
  1141. package/src/web/search/providers/kimi.ts +196 -0
  1142. package/src/web/search/providers/parallel.ts +225 -0
  1143. package/src/web/search/providers/perplexity.ts +730 -0
  1144. package/src/web/search/providers/searxng.ts +313 -0
  1145. package/src/web/search/providers/synthetic.ts +114 -0
  1146. package/src/web/search/providers/tavily.ts +176 -0
  1147. package/src/web/search/providers/utils.ts +128 -0
  1148. package/src/web/search/providers/zai.ts +333 -0
  1149. package/src/web/search/render.ts +262 -0
  1150. package/src/web/search/types.ts +482 -0
  1151. package/src/web/search/utils.ts +17 -0
  1152. package/src/workspace-tree.ts +286 -0
@@ -0,0 +1,1054 @@
1
+ import * as fs from "node:fs";
2
+ import * as os from "node:os";
3
+ import * as path from "node:path";
4
+ import * as url from "node:url";
5
+ import { isEnoent } from "@oh-my-pi/pi-utils";
6
+ import { InternalUrlRouter, type LocalProtocolOptions } from "../internal-urls";
7
+ import { ToolError } from "./tool-errors";
8
+
9
+ const UNICODE_SPACES = /[\u00A0\u2000-\u200A\u202F\u205F\u3000]/g;
10
+ // A single line-range chunk: `N`, `N-M`, `N+K`, or open-ended `N-`. `..` is
11
+ // accepted everywhere `-` is, as a forgiving alias for Rust/Python-style ranges
12
+ // (e.g. `2724..2727` == `2724-2727`, `2724..` == `2724-`); it is normalized to
13
+ // `-` in parseLineRangeChunk. Keep this fragment and LINE_RANGE_CHUNK_RE in sync.
14
+ const RANGE_CHUNK_SRC = String.raw`L?\d+(?:(?:[-+]|\.\.)L?\d+|-|\.\.)?`;
15
+ const RANGE_LIST_SRC = `${RANGE_CHUNK_SRC}(?:,${RANGE_CHUNK_SRC})*`;
16
+ const FILE_LINE_RANGE_RE = new RegExp(`^(?:${RANGE_LIST_SRC}|raw|conflicts)$`, "i");
17
+ const FILE_LINE_RANGE_ONLY_RE = new RegExp(`^${RANGE_LIST_SRC}$`, "i");
18
+ const FILE_RAW_ONLY_RE = /^raw$/i;
19
+ // Permissive selector chunk for internal URLs — accepts well-formed selectors
20
+ // plus common malformed shapes (e.g. `:-N`) so the read tool peels the entire
21
+ // selector chain off before dispatching to a protocol handler.
22
+ const INTERNAL_URL_SELECTOR_PART_RE = new RegExp(
23
+ String.raw`^(?:raw|conflicts|${RANGE_LIST_SRC}|-\d+(?:[-+]\d+)?)$`,
24
+ "i",
25
+ );
26
+ // Schemes whose host grammar is identifier-shaped, so any trailing
27
+ // `:<selector-chunk>` is unambiguously a read-tool selector. `mcp://` is
28
+ // excluded because mcp resource URIs may legitimately contain colons.
29
+ const INTERNAL_SCHEMES_WITH_SELECTORS: Record<string, true> = {
30
+ agent: true,
31
+ artifact: true,
32
+ issue: true,
33
+ local: true,
34
+ memory: true,
35
+ omp: true,
36
+ pr: true,
37
+ rule: true,
38
+ skill: true,
39
+ vault: true,
40
+ };
41
+ // Schemes whose resource URIs are server-defined and may legitimately end
42
+ // with selector-shaped tails (e.g. `:raw`, `:conflicts`, `:1-50`, `/:raw`).
43
+ // `McpProtocolHandler` resolves by exact URI match (`r.uri === uri`), so
44
+ // peeling syntactically can make valid resources unreachable. Keep these
45
+ // schemes opaque; selector support for them needs a resolver-aware path that
46
+ // tries the exact URI before interpreting any suffix as a read selector.
47
+ const OPAQUE_RESOURCE_SCHEMES: ReadonlySet<string> = new Set(["mcp"]);
48
+ const INTERNAL_URL_SCHEME_RE = /^([a-z][a-z0-9+.-]*):\/\//i;
49
+ const NARROW_NO_BREAK_SPACE = "\u202F";
50
+ const TOP_LEVEL_INTERNAL_URL_PREFIXES = [
51
+ "agent://",
52
+ "artifact://",
53
+ "skill://",
54
+ "rule://",
55
+ "local://",
56
+ "mcp://",
57
+ "vault://",
58
+ ] as const;
59
+
60
+ function normalizeUnicodeSpaces(str: string): string {
61
+ return str.replace(UNICODE_SPACES, " ");
62
+ }
63
+
64
+ function tryMacOSScreenshotPath(filePath: string): string {
65
+ return filePath.replace(/ (AM|PM)\./g, `${NARROW_NO_BREAK_SPACE}$1.`);
66
+ }
67
+
68
+ function tryNFDVariant(filePath: string): string {
69
+ // macOS stores filenames in NFD (decomposed) form, try converting user input to NFD
70
+ return filePath.normalize("NFD");
71
+ }
72
+
73
+ function tryCurlyQuoteVariant(filePath: string): string {
74
+ // macOS uses U+2019 (right single quotation mark) in screenshot names like "Capture d'écran"
75
+ // Users typically type U+0027 (straight apostrophe)
76
+ return filePath.replace(/'/g, "\u2019");
77
+ }
78
+
79
+ function tryShellEscapedPath(filePath: string): string {
80
+ if (!filePath.includes("\\") || !filePath.includes("/")) return filePath;
81
+ return filePath.replace(/\\([ \t"'(){}[\]])/g, "$1");
82
+ }
83
+
84
+ function fileExists(filePath: string): boolean {
85
+ try {
86
+ fs.accessSync(filePath, fs.constants.F_OK);
87
+ return true;
88
+ } catch {
89
+ return false;
90
+ }
91
+ }
92
+
93
+ function normalizeAtPrefix(filePath: string): string {
94
+ if (!filePath.startsWith("@")) return filePath;
95
+
96
+ const withoutAt = filePath.slice(1);
97
+
98
+ // We only treat a leading "@" as a shorthand for a small set of well-known
99
+ // syntaxes. This avoids mangling literal paths like "@my-file.txt".
100
+ if (
101
+ withoutAt.startsWith("/") ||
102
+ withoutAt === "~" ||
103
+ withoutAt.startsWith("~/") ||
104
+ // Windows absolute paths (drive letters / UNC / root-relative)
105
+ path.win32.isAbsolute(withoutAt) ||
106
+ // Internal URL shorthands
107
+ withoutAt.startsWith("agent://") ||
108
+ withoutAt.startsWith("artifact://") ||
109
+ withoutAt.startsWith("skill://") ||
110
+ withoutAt.startsWith("rule://") ||
111
+ withoutAt.startsWith("local:") ||
112
+ withoutAt.startsWith("mcp://")
113
+ ) {
114
+ return withoutAt;
115
+ }
116
+
117
+ return filePath;
118
+ }
119
+
120
+ function stripFileUrl(filePath: string): string {
121
+ if (!filePath.toLowerCase().startsWith("file://")) return filePath;
122
+
123
+ try {
124
+ return url.fileURLToPath(filePath);
125
+ } catch {
126
+ return filePath;
127
+ }
128
+ }
129
+
130
+ export function expandTilde(filePath: string, home?: string): string {
131
+ const h = home ?? os.homedir();
132
+ if (filePath === "~") return h;
133
+ if (filePath.startsWith("~/") || filePath.startsWith("~\\")) {
134
+ return h + filePath.slice(1);
135
+ }
136
+ if (filePath.startsWith("~")) {
137
+ return path.join(h, filePath.slice(1));
138
+ }
139
+ return filePath;
140
+ }
141
+
142
+ export function expandPath(filePath: string): string {
143
+ const normalized = stripFileUrl(normalizeUnicodeSpaces(normalizeAtPrefix(filePath)));
144
+ return expandTilde(normalized);
145
+ }
146
+ /**
147
+ * Inclusive line range describing one selector segment (e.g. `50-100`,
148
+ * `301-`, or `50+10`). `endLine` is `undefined` for open-ended ranges.
149
+ */
150
+ export interface LineRange {
151
+ startLine: number;
152
+ endLine: number | undefined;
153
+ }
154
+
155
+ const LINE_RANGE_CHUNK_RE = /^L?(\d+)(?:(\.\.|[-+])L?(\d+)?)?$/i;
156
+
157
+ /** Parse a single `N`, `N-M`, `N-`, `N+K`, or `..`-aliased (`N..M`, `N..`) chunk. Throws via {@link ToolError} on invalid bounds. */
158
+ export function parseLineRangeChunk(sel: string): LineRange | null {
159
+ const lineMatch = LINE_RANGE_CHUNK_RE.exec(sel);
160
+ if (!lineMatch) return null;
161
+ const rawStart = Number.parseInt(lineMatch[1]!, 10);
162
+ if (rawStart < 1) {
163
+ throw new ToolError("Line selector 0 is invalid; lines are 1-indexed. Use :1.");
164
+ }
165
+ // `..` is a forgiving alias for `-` (e.g. `2724..2727` == `2724-2727`).
166
+ const sep = lineMatch[2] === ".." ? "-" : lineMatch[2];
167
+ const rhs = lineMatch[3] ? Number.parseInt(lineMatch[3], 10) : undefined;
168
+ let rawEnd: number | undefined;
169
+ if (sep === "+") {
170
+ if (rhs === undefined || rhs < 1) {
171
+ throw new ToolError(`Invalid range ${rawStart}+${rhs ?? 0}: count must be >= 1.`);
172
+ }
173
+ rawEnd = rawStart + rhs - 1;
174
+ } else if (sep === "-") {
175
+ // `301-` is shorthand for "from 301 onward" — equivalent to bare `301`.
176
+ if (rhs !== undefined) {
177
+ if (rhs < rawStart) {
178
+ throw new ToolError(`Invalid range ${rawStart}-${rhs}: end must be >= start.`);
179
+ }
180
+ rawEnd = rhs;
181
+ }
182
+ }
183
+ return { startLine: rawStart, endLine: rawEnd };
184
+ }
185
+
186
+ /**
187
+ * Parse a comma-separated list of line ranges (e.g. `5-16,960-973`). Returns
188
+ * the ranges in ascending order with overlapping/adjacent ranges merged so
189
+ * downstream consumers can stream the file in a single forward pass per range.
190
+ */
191
+ export function parseLineRanges(sel: string): [LineRange, ...LineRange[]] | null {
192
+ const chunks = sel.split(",");
193
+ const parsed: LineRange[] = [];
194
+ for (const chunk of chunks) {
195
+ const range = parseLineRangeChunk(chunk);
196
+ if (!range) return null;
197
+ parsed.push(range);
198
+ }
199
+ if (parsed.length === 0) return null;
200
+ parsed.sort((a, b) => a.startLine - b.startLine);
201
+
202
+ const merged: LineRange[] = [parsed[0]];
203
+ for (let i = 1; i < parsed.length; i++) {
204
+ const current = parsed[i];
205
+ const last = merged[merged.length - 1];
206
+ // Open-ended (endLine undefined) means "to EOF" — any later range is absorbed.
207
+ if (last.endLine === undefined) continue;
208
+ // Merge when current starts within (or immediately after) the last range.
209
+ if (current.startLine <= last.endLine + 1) {
210
+ if (current.endLine === undefined || current.endLine > last.endLine) {
211
+ merged[merged.length - 1] = { startLine: last.startLine, endLine: current.endLine };
212
+ }
213
+ continue;
214
+ }
215
+ merged.push(current);
216
+ }
217
+ return merged as [LineRange, ...LineRange[]];
218
+ }
219
+
220
+ /**
221
+ * Extract the line-range component from a read-tool selector that may also
222
+ * carry a verbatim/index display mode (`raw`, `conflicts`) — alone or compounded
223
+ * with a range (`raw:50-100`, `50-100:raw`). Returns the parsed ranges when the
224
+ * selector names any, otherwise `undefined` (pure `raw`/`conflicts`/none).
225
+ *
226
+ * Used by content search, which honors line ranges as a match filter but has no
227
+ * use for verbatim/conflict display modes — so those selectors are accepted and
228
+ * treated as an unfiltered, whole-resource search rather than rejected.
229
+ */
230
+ export function selectorLineRanges(sel: string | undefined): [LineRange, ...LineRange[]] | undefined {
231
+ if (!sel) return undefined;
232
+ for (const chunk of sel.split(":")) {
233
+ const lower = chunk.toLowerCase();
234
+ if (lower === "raw" || lower === "conflicts") continue;
235
+ const ranges = parseLineRanges(chunk);
236
+ if (ranges) return ranges;
237
+ }
238
+ return undefined;
239
+ }
240
+
241
+ /** Return `true` when `lineNumber` (1-indexed) falls in any of the supplied ranges. */
242
+ export function isLineInRanges(lineNumber: number, ranges: readonly LineRange[]): boolean {
243
+ for (const range of ranges) {
244
+ if (lineNumber < range.startLine) continue;
245
+ if (range.endLine === undefined || lineNumber <= range.endLine) return true;
246
+ }
247
+ return false;
248
+ }
249
+
250
+ export function splitPathAndSel(rawPath: string): { path: string; sel?: string } {
251
+ const colon = rawPath.lastIndexOf(":");
252
+ if (colon <= 0) return { path: rawPath };
253
+
254
+ const candidate = rawPath.slice(colon + 1);
255
+ if (!FILE_LINE_RANGE_RE.test(candidate)) return { path: rawPath };
256
+
257
+ let basePath = rawPath.slice(0, colon);
258
+ let sel = candidate;
259
+
260
+ // Allow a compound trailing selector: `path:1-50:raw` or `path:raw:1-50`.
261
+ // The two chunks must be one line-range plus one `raw`, in either order.
262
+ const innerColon = basePath.lastIndexOf(":");
263
+ if (innerColon > 0) {
264
+ const innerCandidate = basePath.slice(innerColon + 1);
265
+ const innerIsRaw = FILE_RAW_ONLY_RE.test(innerCandidate);
266
+ const outerIsRaw = FILE_RAW_ONLY_RE.test(candidate);
267
+ const innerIsRange = FILE_LINE_RANGE_ONLY_RE.test(innerCandidate);
268
+ const outerIsRange = FILE_LINE_RANGE_ONLY_RE.test(candidate);
269
+ if ((innerIsRaw && outerIsRange) || (innerIsRange && outerIsRaw)) {
270
+ sel = `${innerCandidate}:${candidate}`;
271
+ basePath = basePath.slice(0, innerColon);
272
+ }
273
+ }
274
+
275
+ return { path: basePath, sel };
276
+ }
277
+
278
+ /**
279
+ * Variant of {@link splitPathAndSel} for internal URLs (`scheme://...`).
280
+ *
281
+ * The filesystem-path splitter is intentionally conservative: it refuses to
282
+ * peel a trailing `:<chunk>` unless that chunk matches the strict selector
283
+ * grammar. That rule is right for filesystem paths (a file named `a:1-50` is
284
+ * legal) but wrong for internal URLs, where any trailing `:<chunk>` after the
285
+ * scheme is unambiguously a read-tool selector — even if malformed (e.g.
286
+ * `artifact://3:raw:-100`).
287
+ *
288
+ * This function iteratively peels selector-shaped chunks (well-formed plus
289
+ * common malformed shapes like `:-N`) so the rest of the read tool can pass a
290
+ * clean URL to the protocol handler and surface selector errors via parseSel
291
+ * instead of as misleading "host invalid" errors from the handler. Schemes
292
+ * whose resource URIs may legitimately contain colons (`mcp://`) are skipped.
293
+ *
294
+ * Falls back to the input unchanged when nothing matches.
295
+ */
296
+
297
+ export function splitInternalUrlSel(rawPath: string): { path: string; sel?: string } {
298
+ const schemeMatch = rawPath.match(INTERNAL_URL_SCHEME_RE);
299
+ if (!schemeMatch) return { path: rawPath };
300
+ const scheme = schemeMatch[1].toLowerCase();
301
+ // Opaque schemes (mcp://, etc.) carry server-defined resource URIs that may
302
+ // legitimately end in selector-shaped tails. Forward verbatim — see
303
+ // OPAQUE_RESOURCE_SCHEMES.
304
+ if (OPAQUE_RESOURCE_SCHEMES.has(scheme)) return { path: rawPath };
305
+ if (!INTERNAL_SCHEMES_WITH_SELECTORS[scheme]) return { path: rawPath };
306
+
307
+ const schemeEnd = schemeMatch[0].length;
308
+ let path = rawPath;
309
+ const chunks: string[] = [];
310
+ while (true) {
311
+ const colon = path.lastIndexOf(":");
312
+ // Stop before crossing into the scheme separator `://`.
313
+ if (colon < schemeEnd) break;
314
+ const tail = path.slice(colon + 1);
315
+ if (!INTERNAL_URL_SELECTOR_PART_RE.test(tail)) break;
316
+ chunks.unshift(tail);
317
+ path = path.slice(0, colon);
318
+ }
319
+ if (chunks.length === 0) return { path: rawPath };
320
+ return { path, sel: chunks.join(":") };
321
+ }
322
+
323
+ function assertNotInternalUrl(expanded: string, original: string): void {
324
+ for (const prefix of TOP_LEVEL_INTERNAL_URL_PREFIXES) {
325
+ if (expanded.startsWith(prefix)) {
326
+ throw new Error(
327
+ `Path "${original}" uses internal scheme "${prefix}" and must be resolved through the proper protocol handler, not as a filesystem path.`,
328
+ );
329
+ }
330
+ }
331
+ }
332
+
333
+ export function normalizeLocalScheme(filePath: string): string {
334
+ return filePath.replace(/^(local:)\/(?!\/)/, "$1//");
335
+ }
336
+
337
+ export function isInternalUrlPath(filePath: string): boolean {
338
+ const normalized = normalizeLocalScheme(filePath);
339
+ const expandedAndNormalized = normalizeLocalScheme(expandPath(normalized));
340
+ for (const prefix of TOP_LEVEL_INTERNAL_URL_PREFIXES) {
341
+ if (expandedAndNormalized.startsWith(prefix)) return true;
342
+ }
343
+ return false;
344
+ }
345
+
346
+ /**
347
+ * Resolve a path relative to the given cwd.
348
+ * Handles ~ expansion and absolute paths.
349
+ *
350
+ * A bare root slash is treated as a workspace-root alias for tool inputs. Users
351
+ * often pass `/` to mean “search from here”, and letting tools escape to the
352
+ * filesystem root is almost never what they intended.
353
+ */
354
+ export function resolveToCwd(filePath: string, cwd: string): string {
355
+ const normalized = normalizeLocalScheme(filePath);
356
+ const expanded = expandPath(normalized);
357
+ const expandedAndNormalized = normalizeLocalScheme(expanded);
358
+
359
+ assertNotInternalUrl(expandedAndNormalized, normalized);
360
+
361
+ if (/^\/+$/.test(expanded)) {
362
+ return cwd;
363
+ }
364
+ if (path.isAbsolute(expanded)) {
365
+ return expanded;
366
+ }
367
+ return path.resolve(cwd, expanded);
368
+ }
369
+
370
+ export function formatPathRelativeToCwd(
371
+ filePath: string,
372
+ cwd: string,
373
+ options: { trailingSlash?: boolean } = {},
374
+ ): string {
375
+ const resolvedCwd = path.resolve(cwd);
376
+ const normalized = normalizeLocalScheme(filePath);
377
+ if (isInternalUrlPath(normalized)) {
378
+ return normalized;
379
+ }
380
+ const expanded = expandPath(normalized);
381
+ const resolvedPath = path.isAbsolute(expanded) ? path.resolve(expanded) : path.resolve(cwd, expanded);
382
+ const relative = path.relative(resolvedCwd, resolvedPath);
383
+ const isWithinCwd = relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative));
384
+ let displayPath = normalizePosixPath(isWithinCwd ? relative || "." : resolvedPath);
385
+ if (options.trailingSlash && displayPath !== "." && !displayPath.endsWith("/")) {
386
+ displayPath += "/";
387
+ }
388
+ return displayPath;
389
+ }
390
+
391
+ /**
392
+ * Strip matching surrounding double quotes from a path string.
393
+ * Common when users paste quoted paths from Windows Explorer or shell copy-paste.
394
+ * Only double quotes — single quotes are valid POSIX filename characters.
395
+ * Tradeoff: a POSIX path literally starting AND ending with " would also be unquoted.
396
+ * Accepted because such names are virtually nonexistent in practice.
397
+ */
398
+ export function stripOuterDoubleQuotes(input: string): string {
399
+ return input.startsWith('"') && input.endsWith('"') && input.length > 1 ? input.slice(1, -1) : input;
400
+ }
401
+
402
+ export function normalizePathLikeInput(input: string): string {
403
+ return stripOuterDoubleQuotes(input.trim());
404
+ }
405
+
406
+ const GLOB_PATH_CHARS = ["*", "?", "[", "{"] as const;
407
+
408
+ export function hasGlobPathChars(filePath: string): boolean {
409
+ return GLOB_PATH_CHARS.some(char => filePath.includes(char));
410
+ }
411
+
412
+ type PathEntrySplitter = (item: string) => { basePath: string };
413
+
414
+ const TOP_LEVEL_WHITESPACE_RE = /\s/;
415
+
416
+ type DelimitedPathSplitMode = "comma" | "semicolon" | "whitespace" | "mixed";
417
+
418
+ function isDelimitedPathSeparator(ch: string, mode: DelimitedPathSplitMode): boolean {
419
+ if (mode === "comma") return ch === ",";
420
+ if (mode === "semicolon") return ch === ";";
421
+ if (mode === "whitespace") return TOP_LEVEL_WHITESPACE_RE.test(ch);
422
+ return ch === "," || ch === ";" || TOP_LEVEL_WHITESPACE_RE.test(ch);
423
+ }
424
+
425
+ function hasTopLevelPathDelimiter(entry: string): boolean {
426
+ let braceDepth = 0;
427
+ for (let i = 0; i < entry.length; i++) {
428
+ const ch = entry[i];
429
+ if (ch === "\\" && i + 1 < entry.length) {
430
+ i++;
431
+ continue;
432
+ }
433
+ if (ch === "{") {
434
+ braceDepth++;
435
+ continue;
436
+ }
437
+ if (ch === "}") {
438
+ if (braceDepth > 0) braceDepth--;
439
+ continue;
440
+ }
441
+ if (braceDepth === 0 && (ch === "," || ch === ";" || TOP_LEVEL_WHITESPACE_RE.test(ch))) {
442
+ return true;
443
+ }
444
+ }
445
+ return false;
446
+ }
447
+
448
+ function splitTopLevelDelimitedPath(entry: string, mode: DelimitedPathSplitMode): string[] {
449
+ const parts: string[] = [];
450
+ let braceDepth = 0;
451
+ let start = 0;
452
+ for (let i = 0; i < entry.length; i++) {
453
+ const ch = entry[i];
454
+ if (ch === "\\" && i + 1 < entry.length) {
455
+ i++;
456
+ continue;
457
+ }
458
+ if (ch === "{") {
459
+ braceDepth++;
460
+ continue;
461
+ }
462
+ if (ch === "}") {
463
+ if (braceDepth > 0) braceDepth--;
464
+ continue;
465
+ }
466
+ if (braceDepth !== 0 || !isDelimitedPathSeparator(ch, mode)) continue;
467
+ parts.push(entry.slice(start, i));
468
+ start = i + 1;
469
+ }
470
+ parts.push(entry.slice(start));
471
+ return parts;
472
+ }
473
+
474
+ async function delimitedPathPartResolves(entry: string, cwd: string, splitter: PathEntrySplitter): Promise<boolean> {
475
+ if (isInternalUrlPath(entry)) return true;
476
+ const peeled = splitPathAndSel(entry).path;
477
+ const { basePath } = splitter(peeled);
478
+ const absoluteBasePath = resolveToCwd(basePath, cwd);
479
+ try {
480
+ await fs.promises.stat(absoluteBasePath);
481
+ return true;
482
+ } catch (err) {
483
+ if (isEnoent(err)) return false;
484
+ throw err;
485
+ }
486
+ }
487
+
488
+ async function tryDelimitedPathSplit(
489
+ entry: string,
490
+ cwd: string,
491
+ splitter: PathEntrySplitter,
492
+ mode: DelimitedPathSplitMode,
493
+ requireAllParts: boolean,
494
+ ): Promise<string[] | null> {
495
+ const rawParts = splitTopLevelDelimitedPath(entry, mode);
496
+ if (rawParts.length < 2) return null;
497
+
498
+ const parts = rawParts.map(normalizePathLikeInput).filter(part => part.length > 0);
499
+ if (parts.length === 0) return null;
500
+ if (parts.length < 2 && rawParts.length === parts.length) return null;
501
+
502
+ const resolved = await Promise.all(parts.map(part => delimitedPathPartResolves(part, cwd, splitter)));
503
+ const valid = requireAllParts ? resolved.every(Boolean) : resolved.some(Boolean);
504
+ return valid ? parts : null;
505
+ }
506
+
507
+ /**
508
+ * Split one path-like entry whose multiple targets were flattened into one
509
+ * string. Existing paths are kept intact, so real filenames containing spaces,
510
+ * commas, or semicolons win over delimiter recovery.
511
+ */
512
+ export async function splitDelimitedPathEntry(
513
+ entry: string,
514
+ cwd: string,
515
+ options: { splitter?: PathEntrySplitter } = {},
516
+ ): Promise<string[] | null> {
517
+ const normalizedEntry = normalizePathLikeInput(entry);
518
+ if (!hasTopLevelPathDelimiter(normalizedEntry)) return null;
519
+ if (isInternalUrlPath(normalizedEntry)) return null;
520
+
521
+ const splitter = options.splitter ?? parseSearchPath;
522
+ const peeledEntry = splitPathAndSel(normalizedEntry).path;
523
+ if (!hasGlobPathChars(peeledEntry) && (await delimitedPathPartResolves(normalizedEntry, cwd, splitter))) {
524
+ return null;
525
+ }
526
+
527
+ return (
528
+ (await tryDelimitedPathSplit(normalizedEntry, cwd, splitter, "comma", false)) ??
529
+ (await tryDelimitedPathSplit(normalizedEntry, cwd, splitter, "semicolon", false)) ??
530
+ (await tryDelimitedPathSplit(normalizedEntry, cwd, splitter, "whitespace", true)) ??
531
+ (await tryDelimitedPathSplit(normalizedEntry, cwd, splitter, "mixed", true))
532
+ );
533
+ }
534
+
535
+ /** Expand delimited entries in-place while preserving unsplit entries. */
536
+ export async function expandDelimitedPathEntries(
537
+ entries: readonly string[],
538
+ cwd: string,
539
+ options: { splitter?: PathEntrySplitter } = {},
540
+ ): Promise<string[]> {
541
+ const expanded: string[] = [];
542
+ for (const entry of entries) {
543
+ const normalizedEntry = normalizePathLikeInput(entry);
544
+ const split = await splitDelimitedPathEntry(normalizedEntry, cwd, options);
545
+ if (split) expanded.push(...split);
546
+ else expanded.push(normalizedEntry);
547
+ }
548
+ return expanded;
549
+ }
550
+
551
+ export interface ParsedSearchPath {
552
+ basePath: string;
553
+ glob?: string;
554
+ }
555
+
556
+ export interface ParsedFindPattern {
557
+ basePath: string;
558
+ globPattern: string;
559
+ hasGlob: boolean;
560
+ }
561
+
562
+ export interface ResolvedSearchTarget {
563
+ basePath: string;
564
+ glob?: string;
565
+ }
566
+
567
+ export interface ResolvedMultiSearchPath {
568
+ basePath: string;
569
+ glob?: string;
570
+ scopePath: string;
571
+ exactFilePaths?: string[];
572
+ targets?: ResolvedSearchTarget[];
573
+ }
574
+
575
+ export interface ResolvedFindTarget {
576
+ basePath: string;
577
+ globPattern: string;
578
+ hasGlob: boolean;
579
+ }
580
+
581
+ export interface ResolvedMultiFindPattern {
582
+ targets: ResolvedFindTarget[];
583
+ scopePath: string;
584
+ }
585
+
586
+ /**
587
+ * Split a user path into a base path + glob pattern for tools that delegate to
588
+ * APIs accepting separate `path` and `glob` arguments.
589
+ */
590
+ export function parseSearchPath(filePath: string): ParsedSearchPath {
591
+ const normalizedPath = filePath.replace(/\\/g, "/");
592
+ if (!hasGlobPathChars(normalizedPath)) {
593
+ return { basePath: filePath };
594
+ }
595
+
596
+ const segments = normalizedPath.split("/");
597
+ const firstGlobIndex = segments.findIndex(segment => hasGlobPathChars(segment));
598
+
599
+ if (firstGlobIndex <= 0) {
600
+ return { basePath: ".", glob: normalizedPath };
601
+ }
602
+
603
+ return {
604
+ basePath: segments.slice(0, firstGlobIndex).join("/"),
605
+ glob: segments.slice(firstGlobIndex).join("/"),
606
+ };
607
+ }
608
+
609
+ /**
610
+ * Async sibling of {@link parseSearchPath} that prefers literal interpretation
611
+ * when a path containing glob metacharacters resolves to an existing entry on
612
+ * disk. Disambiguates Next.js/SvelteKit routes like `apps/[id]/page.tsx` —
613
+ * without this, `[id]` is parsed as a glob character class and silently
614
+ * matches nothing.
615
+ */
616
+ export async function parseSearchPathPreferringLiteral(filePath: string, cwd: string): Promise<ParsedSearchPath> {
617
+ if (!hasGlobPathChars(filePath) || isInternalUrlPath(filePath)) return parseSearchPath(filePath);
618
+ try {
619
+ await fs.promises.stat(resolveToCwd(filePath, cwd));
620
+ return { basePath: filePath };
621
+ } catch {
622
+ return parseSearchPath(filePath);
623
+ }
624
+ }
625
+
626
+ // Parse a find pattern into a base directory path and a glob pattern.
627
+ // Examples:
628
+ // src/app/**/\*.tsx -> { basePath: "src/app", globPattern: "**/*.tsx", hasGlob: true }
629
+ // src/app/\*.tsx -> { basePath: "src/app", globPattern: "*.tsx", hasGlob: true }
630
+ // \*.ts -> { basePath: ".", globPattern: "**/*.ts", hasGlob: true }
631
+ // **/\*.json -> { basePath: ".", globPattern: "**/*.json", hasGlob: true }
632
+ // /abs/path/**/\*.ts -> { basePath: "/abs/path", globPattern: "**/*.ts", hasGlob: true }
633
+ // src/app -> { basePath: "src/app", globPattern: "**/*", hasGlob: false }
634
+ export function parseFindPattern(pattern: string): ParsedFindPattern {
635
+ const segments = pattern.split("/");
636
+ let firstGlobIndex = -1;
637
+ for (let i = 0; i < segments.length; i++) {
638
+ if (hasGlobPathChars(segments[i])) {
639
+ firstGlobIndex = i;
640
+ break;
641
+ }
642
+ }
643
+
644
+ if (firstGlobIndex === -1) {
645
+ return { basePath: pattern, globPattern: "**/*", hasGlob: false };
646
+ }
647
+
648
+ if (firstGlobIndex === 0) {
649
+ const needsRecursive = !pattern.startsWith("**/");
650
+ return {
651
+ basePath: ".",
652
+ globPattern: needsRecursive ? `**/${pattern}` : pattern,
653
+ hasGlob: true,
654
+ };
655
+ }
656
+
657
+ return {
658
+ basePath: segments.slice(0, firstGlobIndex).join("/"),
659
+ globPattern: segments.slice(firstGlobIndex).join("/"),
660
+ hasGlob: true,
661
+ };
662
+ }
663
+
664
+ export function combineSearchGlobs(prefixGlob?: string, suffixGlob?: string): string | undefined {
665
+ if (!prefixGlob) return suffixGlob;
666
+ if (!suffixGlob) return prefixGlob;
667
+
668
+ const normalizedPrefix = prefixGlob.replace(/\/+$/, "");
669
+ const normalizedSuffix = suffixGlob.replace(/^\/+/, "");
670
+
671
+ return `${normalizedPrefix}/${normalizedSuffix}`;
672
+ }
673
+
674
+ function normalizePosixPath(filePath: string): string {
675
+ return filePath.replace(/\\/g, "/");
676
+ }
677
+
678
+ function joinRelativeGlob(basePath: string | undefined, globPattern: string): string {
679
+ if (!basePath || basePath === ".") return normalizePosixPath(globPattern).replace(/^\/+/, "");
680
+ const normalizedBase = normalizePosixPath(basePath).replace(/\/+$/, "");
681
+ const normalizedGlob = normalizePosixPath(globPattern).replace(/^\/+/, "");
682
+ return `${normalizedBase}/${normalizedGlob}`;
683
+ }
684
+
685
+ function buildBraceUnion(patterns: string[]): string | undefined {
686
+ const uniquePatterns = [...new Set(patterns.map(pattern => normalizePosixPath(pattern).trim()).filter(Boolean))];
687
+ if (uniquePatterns.length === 0) return undefined;
688
+ if (uniquePatterns.length === 1) return uniquePatterns[0];
689
+ return `{${uniquePatterns.join(",")}}`;
690
+ }
691
+
692
+ function findCommonBasePath(paths: string[]): string {
693
+ if (paths.length === 0) return ".";
694
+ let commonParts = path.resolve(paths[0]).split(path.sep);
695
+ for (const candidatePath of paths.slice(1)) {
696
+ const candidateParts = path.resolve(candidatePath).split(path.sep);
697
+ let sharedCount = 0;
698
+ const maxShared = Math.min(commonParts.length, candidateParts.length);
699
+ while (sharedCount < maxShared && commonParts[sharedCount] === candidateParts[sharedCount]) {
700
+ sharedCount += 1;
701
+ }
702
+ commonParts = commonParts.slice(0, sharedCount);
703
+ }
704
+ if (commonParts.length === 0) {
705
+ return path.parse(path.resolve(paths[0])).root;
706
+ }
707
+ const joined = commonParts.join(path.sep);
708
+ return joined || path.parse(path.resolve(paths[0])).root;
709
+ }
710
+
711
+ function toScopeDisplay(items: string[], cwd: string): string {
712
+ return items
713
+ .map(item =>
714
+ formatPathRelativeToCwd(item, cwd, {
715
+ trailingSlash: item.endsWith("/") || item.endsWith("\\"),
716
+ }),
717
+ )
718
+ .join(", ");
719
+ }
720
+
721
+ async function resolveSearchPathItems(
722
+ pathItems: string[],
723
+ cwd: string,
724
+ suffixGlob?: string,
725
+ ): Promise<ResolvedMultiSearchPath | undefined> {
726
+ if (pathItems.length < 1) {
727
+ return undefined;
728
+ }
729
+
730
+ const parsedItems = await Promise.all(
731
+ pathItems.map(async item => {
732
+ const parsedPath = await parseSearchPathPreferringLiteral(item, cwd);
733
+ const absoluteBasePath = resolveToCwd(parsedPath.basePath, cwd);
734
+ const stat = await fs.promises.stat(absoluteBasePath);
735
+ return { raw: item, parsedPath, absoluteBasePath, stat };
736
+ }),
737
+ );
738
+
739
+ const allExactFiles = !suffixGlob && parsedItems.every(item => !item.parsedPath.glob && item.stat.isFile());
740
+ const commonBasePath = findCommonBasePath(parsedItems.map(item => item.absoluteBasePath));
741
+ const combinedPatterns = parsedItems.map(item => {
742
+ const relativeBasePath = normalizePosixPath(path.relative(commonBasePath, item.absoluteBasePath)) || ".";
743
+ if (item.parsedPath.glob) {
744
+ const pathGlob = joinRelativeGlob(relativeBasePath, item.parsedPath.glob);
745
+ return combineSearchGlobs(pathGlob, suffixGlob) ?? pathGlob;
746
+ }
747
+ if (suffixGlob) {
748
+ const pathPrefix = relativeBasePath === "." ? undefined : relativeBasePath;
749
+ return combineSearchGlobs(pathPrefix, suffixGlob) ?? suffixGlob;
750
+ }
751
+ if (item.stat.isDirectory()) {
752
+ return joinRelativeGlob(relativeBasePath, "**/*");
753
+ }
754
+ return relativeBasePath === "." ? path.basename(item.absoluteBasePath) : relativeBasePath;
755
+ });
756
+ const rootPath = path.parse(commonBasePath).root;
757
+ const isDegenerateRoot = commonBasePath === rootPath && parsedItems.length > 1;
758
+ const targets = isDegenerateRoot
759
+ ? parsedItems.map(item => ({
760
+ basePath: item.absoluteBasePath,
761
+ glob: item.parsedPath.glob ? combineSearchGlobs(item.parsedPath.glob, suffixGlob) : suffixGlob,
762
+ }))
763
+ : undefined;
764
+
765
+ return {
766
+ basePath: commonBasePath,
767
+ glob: buildBraceUnion(combinedPatterns),
768
+ scopePath: toScopeDisplay(pathItems, cwd),
769
+ exactFilePaths: allExactFiles ? parsedItems.map(item => item.absoluteBasePath) : undefined,
770
+ targets,
771
+ };
772
+ }
773
+
774
+ export async function resolveExplicitSearchPaths(
775
+ pathItems: string[],
776
+ cwd: string,
777
+ suffixGlob?: string,
778
+ ): Promise<ResolvedMultiSearchPath | undefined> {
779
+ return resolveSearchPathItems([...new Set(pathItems)], cwd, suffixGlob);
780
+ }
781
+
782
+ async function resolveFindPatternItems(
783
+ patternItems: string[],
784
+ cwd: string,
785
+ ): Promise<ResolvedMultiFindPattern | undefined> {
786
+ if (patternItems.length <= 1) {
787
+ return undefined;
788
+ }
789
+
790
+ // Each path becomes its own walk root. Collapsing to a shared common ancestor
791
+ // (and filtering with a brace-union glob) would force the walker to traverse
792
+ // and stat every unrelated sibling under that ancestor — two paths under
793
+ // $HOME would scan all of $HOME. The find tool fans these targets out in
794
+ // parallel instead, so every scan stays bounded to exactly one requested path.
795
+ const targets = patternItems.map(item => {
796
+ const parsedPattern = parseFindPattern(item);
797
+ return {
798
+ basePath: resolveToCwd(parsedPattern.basePath, cwd),
799
+ globPattern: parsedPattern.globPattern,
800
+ hasGlob: parsedPattern.hasGlob,
801
+ };
802
+ });
803
+
804
+ return {
805
+ targets,
806
+ scopePath: toScopeDisplay(patternItems, cwd),
807
+ };
808
+ }
809
+
810
+ export async function resolveExplicitFindPatterns(
811
+ patternItems: string[],
812
+ cwd: string,
813
+ ): Promise<ResolvedMultiFindPattern | undefined> {
814
+ return resolveFindPatternItems([...new Set(patternItems)], cwd);
815
+ }
816
+
817
+ /**
818
+ * Result of partitioning a list of user-supplied paths/globs into entries whose
819
+ * base directory currently exists on disk versus those that do not.
820
+ *
821
+ * Used by multi-path tools (search, find, ast_grep, ast_edit) to tolerate one
822
+ * or more missing entries in a multi-path call: the surviving entries should
823
+ * still be searched, with the missing entries surfaced as a non-fatal warning.
824
+ */
825
+ export interface PartitionedPaths {
826
+ /** Raw input strings whose resolved base path exists. */
827
+ valid: string[];
828
+ /** Raw input strings whose resolved base path is missing (ENOENT). */
829
+ missing: string[];
830
+ }
831
+
832
+ /**
833
+ * Stat each input's base path concurrently; return entries split by existence.
834
+ *
835
+ * `splitter` is expected to be {@link parseFindPattern} or
836
+ * {@link parseSearchPath}: both return a `basePath` field that this helper
837
+ * resolves against `cwd` and stats. ENOENT is the only swallowed error — every
838
+ * other stat failure (permission, IO, etc.) propagates so callers do not silently
839
+ * skip paths that exist but are unreadable.
840
+ *
841
+ * Order of `valid` and `missing` follows the input order, so callers can rely
842
+ * on `valid[0]` matching the first surviving user-supplied entry.
843
+ */
844
+ export async function partitionExistingPaths(
845
+ items: string[],
846
+ cwd: string,
847
+ splitter: (item: string) => { basePath: string },
848
+ ): Promise<PartitionedPaths> {
849
+ const settled = await Promise.all(
850
+ items.map(async item => {
851
+ const { basePath } = splitter(item);
852
+ const absoluteBasePath = resolveToCwd(basePath, cwd);
853
+ try {
854
+ await fs.promises.stat(absoluteBasePath);
855
+ return { item, exists: true } as const;
856
+ } catch (err) {
857
+ if (isEnoent(err)) return { item, exists: false } as const;
858
+ throw err;
859
+ }
860
+ }),
861
+ );
862
+ const valid: string[] = [];
863
+ const missing: string[] = [];
864
+ for (const entry of settled) {
865
+ if (entry.exists) valid.push(entry.item);
866
+ else missing.push(entry.item);
867
+ }
868
+ return { valid, missing };
869
+ }
870
+
871
+ export function resolveReadPath(filePath: string, cwd: string): string {
872
+ const resolved = resolveToCwd(filePath, cwd);
873
+ const shellEscapedVariant = tryShellEscapedPath(resolved);
874
+ const baseCandidates = shellEscapedVariant !== resolved ? [resolved, shellEscapedVariant] : [resolved];
875
+
876
+ for (const baseCandidate of baseCandidates) {
877
+ if (fileExists(baseCandidate)) {
878
+ return baseCandidate;
879
+ }
880
+ }
881
+
882
+ for (const baseCandidate of baseCandidates) {
883
+ // Try macOS AM/PM variant (narrow no-break space before AM/PM)
884
+ const amPmVariant = tryMacOSScreenshotPath(baseCandidate);
885
+ if (amPmVariant !== baseCandidate && fileExists(amPmVariant)) {
886
+ return amPmVariant;
887
+ }
888
+
889
+ // Try NFD variant (macOS stores filenames in NFD form)
890
+ const nfdVariant = tryNFDVariant(baseCandidate);
891
+ if (nfdVariant !== baseCandidate && fileExists(nfdVariant)) {
892
+ return nfdVariant;
893
+ }
894
+
895
+ // Try curly quote variant (macOS uses U+2019 in screenshot names)
896
+ const curlyVariant = tryCurlyQuoteVariant(baseCandidate);
897
+ if (curlyVariant !== baseCandidate && fileExists(curlyVariant)) {
898
+ return curlyVariant;
899
+ }
900
+
901
+ // Try combined NFD + curly quote (for French macOS screenshots like "Capture d'écran")
902
+ const nfdCurlyVariant = tryCurlyQuoteVariant(nfdVariant);
903
+ if (nfdCurlyVariant !== baseCandidate && fileExists(nfdCurlyVariant)) {
904
+ return nfdCurlyVariant;
905
+ }
906
+ }
907
+
908
+ return resolved;
909
+ }
910
+
911
+ // =============================================================================
912
+ // Tool-scope resolution (search/ast tools)
913
+ // =============================================================================
914
+
915
+ export interface ToolScopeOptions {
916
+ rawPaths: string[];
917
+ cwd: string;
918
+ /** Verb used in the "Cannot {action} internal URL without a backing file: …" message. */
919
+ internalUrlAction: string;
920
+ /** Collect absolute paths flagged immutable by their internal-URL handler. */
921
+ trackImmutableSources?: boolean;
922
+ /** Honor `exactFilePaths` from {@link resolveExplicitSearchPaths} (search-only). */
923
+ surfaceExactFilePaths?: boolean;
924
+ /** Extra hint appended to "Path not found" when stat fails and the user supplied multiple paths. */
925
+ multipathStatHint?: string;
926
+ /** Calling session's settings — forwarded to the internal-URL router so caller-aware handlers (issue://, pr://) honor it. */
927
+ settings?: unknown;
928
+ /** Caller's abort signal — forwarded to the internal-URL router. */
929
+ signal?: AbortSignal;
930
+ /** Calling session's `local://` root mapping — pins resolutions to the calling session. */
931
+ localProtocolOptions?: LocalProtocolOptions;
932
+ }
933
+
934
+ export interface ToolScopeResolution {
935
+ searchPath: string;
936
+ scopePath: string;
937
+ globFilter: string | undefined;
938
+ isDirectory: boolean;
939
+ multiTargets?: ResolvedSearchTarget[];
940
+ exactFilePaths?: string[];
941
+ missingPaths: string[];
942
+ immutableSourcePaths: Set<string>;
943
+ }
944
+
945
+ /**
946
+ * Shared path-input pipeline for `search`, `ast_grep`, and `ast_edit`:
947
+ * 1. normalize + reject empty paths,
948
+ * 2. resolve internal URLs through {@link InternalUrlRouter} to backing files,
949
+ * 3. partition existing vs missing when multiple paths are supplied,
950
+ * 4. derive a single search base path / glob, or a multi-target list,
951
+ * 5. stat the resolved base path so callers can branch on directory vs file scope.
952
+ */
953
+ export async function resolveToolSearchScope(opts: ToolScopeOptions): Promise<ToolScopeResolution> {
954
+ const { rawPaths: inputs, cwd, internalUrlAction } = opts;
955
+ const normalizedRawPaths = inputs.map(normalizePathLikeInput);
956
+ if (normalizedRawPaths.some(rawPath => rawPath.length === 0)) {
957
+ throw new ToolError("`paths` must contain non-empty paths or globs");
958
+ }
959
+ const rawPaths = await expandDelimitedPathEntries(normalizedRawPaths, cwd);
960
+ if (rawPaths.some(rawPath => rawPath.length === 0)) {
961
+ throw new ToolError("`paths` must contain non-empty paths or globs");
962
+ }
963
+ // External (http/https/ftp/file) URLs are not searchable; route the caller
964
+ // to `read` instead of letting the path-resolver surface a confusing
965
+ // "Path not found" for a slash-stripped URL.
966
+ const externalUrl = rawPaths.find(rawPath => /^(?:https?|ftp|file|ws|wss):\/\//i.test(rawPath));
967
+ if (externalUrl) {
968
+ throw new ToolError(
969
+ `Cannot ${internalUrlAction} external URL: ${externalUrl}. Use \`read\` to fetch web content, then search the returned text.`,
970
+ );
971
+ }
972
+ const internalRouter = InternalUrlRouter.instance();
973
+ const resolvedPathInputs: string[] = [];
974
+ const immutableSourcePaths = new Set<string>();
975
+ for (const rawPath of rawPaths) {
976
+ if (!internalRouter.canHandle(rawPath)) {
977
+ resolvedPathInputs.push(rawPath);
978
+ continue;
979
+ }
980
+ if (hasGlobPathChars(rawPath)) {
981
+ throw new ToolError(`Glob patterns are not supported for internal URLs: ${rawPath}`);
982
+ }
983
+ const resource = await internalRouter.resolve(rawPath, {
984
+ cwd,
985
+ settings: opts.settings,
986
+ signal: opts.signal,
987
+ localProtocolOptions: opts.localProtocolOptions,
988
+ });
989
+ if (!resource.sourcePath) {
990
+ throw new ToolError(`Cannot ${internalUrlAction} internal URL without a backing file: ${rawPath}`);
991
+ }
992
+ if (opts.trackImmutableSources && resource.immutable) {
993
+ immutableSourcePaths.add(path.resolve(resource.sourcePath));
994
+ }
995
+ resolvedPathInputs.push(resource.sourcePath);
996
+ }
997
+
998
+ let missingPaths: string[] = [];
999
+ let effectivePaths = resolvedPathInputs;
1000
+ if (resolvedPathInputs.length > 1) {
1001
+ const partition = await partitionExistingPaths(resolvedPathInputs, cwd, parseSearchPath);
1002
+ if (partition.valid.length === 0) {
1003
+ throw new ToolError(`Path not found: ${partition.missing.join(", ")}`);
1004
+ }
1005
+ effectivePaths = partition.valid;
1006
+ missingPaths = partition.missing;
1007
+ }
1008
+
1009
+ let searchPath: string;
1010
+ let scopePath: string;
1011
+ let globFilter: string | undefined;
1012
+ let multiTargets: ResolvedSearchTarget[] | undefined;
1013
+ let exactFilePaths: string[] | undefined;
1014
+ if (effectivePaths.length === 1) {
1015
+ const parsedPath = await parseSearchPathPreferringLiteral(effectivePaths[0] ?? ".", cwd);
1016
+ searchPath = resolveToCwd(parsedPath.basePath, cwd);
1017
+ globFilter = parsedPath.glob;
1018
+ scopePath = formatPathRelativeToCwd(searchPath, cwd);
1019
+ } else {
1020
+ const multiSearchPath = await resolveExplicitSearchPaths(effectivePaths, cwd);
1021
+ if (!multiSearchPath) {
1022
+ throw new ToolError("`paths` must contain at least one path or glob");
1023
+ }
1024
+ searchPath = multiSearchPath.basePath;
1025
+ multiTargets = multiSearchPath.targets;
1026
+ if (opts.surfaceExactFilePaths) {
1027
+ exactFilePaths = multiSearchPath.exactFilePaths;
1028
+ globFilter = exactFilePaths || multiTargets ? undefined : multiSearchPath.glob;
1029
+ } else {
1030
+ globFilter = multiTargets ? undefined : multiSearchPath.glob;
1031
+ }
1032
+ scopePath = multiSearchPath.scopePath;
1033
+ }
1034
+
1035
+ let isDirectory: boolean;
1036
+ try {
1037
+ const stat = await Bun.file(searchPath).stat();
1038
+ isDirectory = stat.isDirectory();
1039
+ } catch {
1040
+ const hint = opts.multipathStatHint && rawPaths.length > 1 ? opts.multipathStatHint : "";
1041
+ throw new ToolError(`Path not found: ${scopePath}${hint}`);
1042
+ }
1043
+
1044
+ return {
1045
+ searchPath,
1046
+ scopePath,
1047
+ globFilter,
1048
+ isDirectory,
1049
+ multiTargets,
1050
+ exactFilePaths,
1051
+ missingPaths,
1052
+ immutableSourcePaths,
1053
+ };
1054
+ }