@kr78/pi-coding-agent 17.2.10

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 (1593) hide show
  1. package/CHANGELOG.md +14861 -0
  2. package/README.md +35 -0
  3. package/dist/CHANGELOG-chtdxh1z.md +14861 -0
  4. package/dist/cli.js +20483 -0
  5. package/dist/template-c2hyaytt.js +1653 -0
  6. package/dist/template-f8wx9vfn.css +1355 -0
  7. package/dist/template-qat058wr.html +55 -0
  8. package/dist/tool-views.generated-jdfmzwmn.js +35 -0
  9. package/examples/README.md +21 -0
  10. package/examples/custom-tools/README.md +104 -0
  11. package/examples/custom-tools/hello/index.ts +20 -0
  12. package/examples/extensions/README.md +142 -0
  13. package/examples/extensions/api-demo.ts +78 -0
  14. package/examples/extensions/chalk-logger.ts +25 -0
  15. package/examples/extensions/hello.ts +31 -0
  16. package/examples/extensions/pirate.ts +43 -0
  17. package/examples/extensions/plan-mode.ts +549 -0
  18. package/examples/extensions/reload-runtime.ts +38 -0
  19. package/examples/extensions/thinking-note.ts +13 -0
  20. package/examples/extensions/tools.ts +145 -0
  21. package/examples/extensions/with-deps/index.ts +36 -0
  22. package/examples/extensions/with-deps/package-lock.json +31 -0
  23. package/examples/extensions/with-deps/package.json +17 -0
  24. package/examples/hooks/README.md +56 -0
  25. package/examples/hooks/auto-commit-on-exit.ts +48 -0
  26. package/examples/hooks/confirm-destructive.ts +58 -0
  27. package/examples/hooks/custom-compaction.ts +115 -0
  28. package/examples/hooks/dirty-repo-guard.ts +51 -0
  29. package/examples/hooks/file-trigger.ts +40 -0
  30. package/examples/hooks/git-checkpoint.ts +52 -0
  31. package/examples/hooks/handoff.ts +149 -0
  32. package/examples/hooks/permission-gate.ts +33 -0
  33. package/examples/hooks/protected-paths.ts +29 -0
  34. package/examples/hooks/qna.ts +118 -0
  35. package/examples/hooks/status-line.ts +39 -0
  36. package/examples/sdk/01-minimal.ts +21 -0
  37. package/examples/sdk/02-custom-model.ts +49 -0
  38. package/examples/sdk/03-custom-prompt.ts +46 -0
  39. package/examples/sdk/04-skills.ts +43 -0
  40. package/examples/sdk/06-extensions.ts +82 -0
  41. package/examples/sdk/06-hooks.ts +61 -0
  42. package/examples/sdk/07-context-files.ts +35 -0
  43. package/examples/sdk/08-prompt-templates.ts +41 -0
  44. package/examples/sdk/08-slash-commands.ts +46 -0
  45. package/examples/sdk/09-api-keys-and-oauth.ts +54 -0
  46. package/examples/sdk/11-sessions.ts +47 -0
  47. package/examples/sdk/12-redis-sessions.ts +54 -0
  48. package/examples/sdk/13-sql-sessions.ts +61 -0
  49. package/examples/sdk/README.md +169 -0
  50. package/package.json +587 -0
  51. package/scripts/bench-guard.ts +71 -0
  52. package/scripts/bench-title-models.ts +332 -0
  53. package/scripts/build-binary.ts +117 -0
  54. package/scripts/bundle-dist.ts +123 -0
  55. package/scripts/compile-binary.ts +69 -0
  56. package/scripts/embed-mupdf-wasm.ts +67 -0
  57. package/scripts/format-prompts.ts +68 -0
  58. package/scripts/generate-aria-snapshot.ts +134 -0
  59. package/scripts/generate-docs-index.ts +58 -0
  60. package/scripts/generate-share-viewer.ts +34 -0
  61. package/scripts/legacy-pi-virtual-module.ts +205 -0
  62. package/scripts/measure-prompt-tokens.ts +63 -0
  63. package/scripts/omp +51 -0
  64. package/scripts/omp.ts +19 -0
  65. package/scripts/security-compare.ts +40 -0
  66. package/src/advisor/advise-tool.ts +234 -0
  67. package/src/advisor/config.ts +341 -0
  68. package/src/advisor/emission-guard.ts +172 -0
  69. package/src/advisor/index.ts +6 -0
  70. package/src/advisor/runtime.ts +1412 -0
  71. package/src/advisor/transcript-recorder.ts +215 -0
  72. package/src/advisor/watchdog.ts +135 -0
  73. package/src/async/index.ts +1 -0
  74. package/src/async/job-manager.ts +847 -0
  75. package/src/auto-thinking/classifier.ts +220 -0
  76. package/src/autolearn/controller.ts +152 -0
  77. package/src/autolearn/managed-skills.ts +255 -0
  78. package/src/autoresearch/command-resume.md +14 -0
  79. package/src/autoresearch/dashboard.ts +436 -0
  80. package/src/autoresearch/git.ts +331 -0
  81. package/src/autoresearch/helpers.ts +218 -0
  82. package/src/autoresearch/index.ts +541 -0
  83. package/src/autoresearch/prompt-setup.md +43 -0
  84. package/src/autoresearch/prompt.md +103 -0
  85. package/src/autoresearch/resume-message.md +10 -0
  86. package/src/autoresearch/state.ts +273 -0
  87. package/src/autoresearch/storage.ts +700 -0
  88. package/src/autoresearch/tools/init-experiment.ts +268 -0
  89. package/src/autoresearch/tools/log-experiment.ts +520 -0
  90. package/src/autoresearch/tools/run-experiment.ts +407 -0
  91. package/src/autoresearch/tools/update-notes.ts +109 -0
  92. package/src/autoresearch/types.ts +168 -0
  93. package/src/capability/context-file.ts +44 -0
  94. package/src/capability/extension-module.ts +34 -0
  95. package/src/capability/extension.ts +47 -0
  96. package/src/capability/fs.ts +117 -0
  97. package/src/capability/hook.ts +40 -0
  98. package/src/capability/index.ts +467 -0
  99. package/src/capability/instruction.ts +37 -0
  100. package/src/capability/mcp.ts +115 -0
  101. package/src/capability/prompt.ts +35 -0
  102. package/src/capability/rule-buckets.ts +66 -0
  103. package/src/capability/rule.ts +298 -0
  104. package/src/capability/settings.ts +34 -0
  105. package/src/capability/skill.ts +69 -0
  106. package/src/capability/slash-command.ts +40 -0
  107. package/src/capability/ssh.ts +41 -0
  108. package/src/capability/system-prompt.ts +34 -0
  109. package/src/capability/tool.ts +38 -0
  110. package/src/capability/types.ts +187 -0
  111. package/src/cleanse/agent.ts +226 -0
  112. package/src/cleanse/balance.ts +79 -0
  113. package/src/cleanse/checkers.ts +996 -0
  114. package/src/cleanse/index.ts +190 -0
  115. package/src/cleanse/loop.ts +51 -0
  116. package/src/cleanse/parsers.ts +726 -0
  117. package/src/cleanse/progress.ts +50 -0
  118. package/src/cleanse/prompts/assignment.md +47 -0
  119. package/src/cleanse/types.ts +72 -0
  120. package/src/cli/agents-cli.ts +138 -0
  121. package/src/cli/args.ts +368 -0
  122. package/src/cli/auth-broker-cli.ts +940 -0
  123. package/src/cli/auth-gateway-cli.ts +674 -0
  124. package/src/cli/bench-cli.ts +990 -0
  125. package/src/cli/browser-relay-cli.ts +119 -0
  126. package/src/cli/classify-install-target.ts +76 -0
  127. package/src/cli/claude-trace-cli.ts +795 -0
  128. package/src/cli/command-help.ts +107 -0
  129. package/src/cli/commands/init-xdg.ts +27 -0
  130. package/src/cli/completion-gen.ts +550 -0
  131. package/src/cli/config-cli.ts +459 -0
  132. package/src/cli/dry-balance-cli.ts +864 -0
  133. package/src/cli/extension-flags.ts +48 -0
  134. package/src/cli/file-processor.ts +132 -0
  135. package/src/cli/flag-tables.ts +367 -0
  136. package/src/cli/gallery-cli.ts +272 -0
  137. package/src/cli/gallery-fixtures/agentic.ts +420 -0
  138. package/src/cli/gallery-fixtures/codeintel.ts +187 -0
  139. package/src/cli/gallery-fixtures/edit.ts +254 -0
  140. package/src/cli/gallery-fixtures/fs.ts +245 -0
  141. package/src/cli/gallery-fixtures/index.ts +40 -0
  142. package/src/cli/gallery-fixtures/interaction.ts +46 -0
  143. package/src/cli/gallery-fixtures/memory.ts +81 -0
  144. package/src/cli/gallery-fixtures/misc.ts +177 -0
  145. package/src/cli/gallery-fixtures/search.ts +135 -0
  146. package/src/cli/gallery-fixtures/shell.ts +241 -0
  147. package/src/cli/gallery-fixtures/types.ts +57 -0
  148. package/src/cli/gallery-fixtures/web.ts +158 -0
  149. package/src/cli/gallery-screenshot.ts +279 -0
  150. package/src/cli/gc-cli.ts +1566 -0
  151. package/src/cli/grep-cli.ts +161 -0
  152. package/src/cli/grievances-cli.ts +256 -0
  153. package/src/cli/help-extra.ts +89 -0
  154. package/src/cli/initial-message.ts +58 -0
  155. package/src/cli/models-cli.ts +385 -0
  156. package/src/cli/plugin-cli.ts +996 -0
  157. package/src/cli/profile-alias.ts +369 -0
  158. package/src/cli/profile-bootstrap.ts +233 -0
  159. package/src/cli/read-cli.ts +99 -0
  160. package/src/cli/session-picker.ts +110 -0
  161. package/src/cli/setup-cli.ts +312 -0
  162. package/src/cli/setup-model-picker.ts +43 -0
  163. package/src/cli/shell-cli.ts +176 -0
  164. package/src/cli/ssh-cli.ts +179 -0
  165. package/src/cli/startup-cwd.ts +58 -0
  166. package/src/cli/stats-cli.ts +229 -0
  167. package/src/cli/thinking-levels.ts +7 -0
  168. package/src/cli/tiny-models-cli.ts +153 -0
  169. package/src/cli/ttsr-cli.ts +1013 -0
  170. package/src/cli/update-cli.ts +1184 -0
  171. package/src/cli/usage-cli.ts +1084 -0
  172. package/src/cli/usage-error.ts +7 -0
  173. package/src/cli/web-search-cli.ts +144 -0
  174. package/src/cli/worktree-cli.ts +311 -0
  175. package/src/cli-commands.ts +308 -0
  176. package/src/cli.ts +428 -0
  177. package/src/collab/crypto.ts +63 -0
  178. package/src/collab/display-name.ts +13 -0
  179. package/src/collab/guest.ts +764 -0
  180. package/src/collab/host.ts +692 -0
  181. package/src/collab/protocol.ts +296 -0
  182. package/src/collab/relay-client.ts +282 -0
  183. package/src/collab/replication-shrink.ts +111 -0
  184. package/src/commands/acp.ts +35 -0
  185. package/src/commands/agents.ts +58 -0
  186. package/src/commands/auth-broker.ts +100 -0
  187. package/src/commands/auth-gateway.ts +70 -0
  188. package/src/commands/bench.ts +64 -0
  189. package/src/commands/browser-relay.ts +53 -0
  190. package/src/commands/cleanse.ts +45 -0
  191. package/src/commands/commit.ts +47 -0
  192. package/src/commands/complete.ts +67 -0
  193. package/src/commands/completions.ts +61 -0
  194. package/src/commands/config.ts +52 -0
  195. package/src/commands/dry-balance.ts +43 -0
  196. package/src/commands/gallery.ts +61 -0
  197. package/src/commands/gc.ts +47 -0
  198. package/src/commands/grep.ts +49 -0
  199. package/src/commands/grievances.ts +52 -0
  200. package/src/commands/install.ts +107 -0
  201. package/src/commands/join.ts +40 -0
  202. package/src/commands/launch-help.ts +116 -0
  203. package/src/commands/launch.ts +34 -0
  204. package/src/commands/models.ts +61 -0
  205. package/src/commands/plugin.ts +79 -0
  206. package/src/commands/read.ts +39 -0
  207. package/src/commands/say.ts +146 -0
  208. package/src/commands/setup.ts +68 -0
  209. package/src/commands/share.ts +71 -0
  210. package/src/commands/shell.ts +30 -0
  211. package/src/commands/ssh.ts +61 -0
  212. package/src/commands/stats.ts +30 -0
  213. package/src/commands/tiny-models.ts +36 -0
  214. package/src/commands/token.ts +164 -0
  215. package/src/commands/ttsr.ts +125 -0
  216. package/src/commands/update.ts +34 -0
  217. package/src/commands/usage.ts +55 -0
  218. package/src/commands/web-search.ts +43 -0
  219. package/src/commands/worktree.ts +63 -0
  220. package/src/commit/agentic/agent.ts +322 -0
  221. package/src/commit/agentic/fallback.ts +96 -0
  222. package/src/commit/agentic/index.ts +383 -0
  223. package/src/commit/agentic/lock-files.ts +107 -0
  224. package/src/commit/agentic/prompts/analyze-file.md +22 -0
  225. package/src/commit/agentic/prompts/session-user.md +25 -0
  226. package/src/commit/agentic/prompts/split-confirm.md +1 -0
  227. package/src/commit/agentic/prompts/system.md +38 -0
  228. package/src/commit/agentic/state.ts +60 -0
  229. package/src/commit/agentic/tools/analyze-file.ts +148 -0
  230. package/src/commit/agentic/tools/git-file-diff.ts +191 -0
  231. package/src/commit/agentic/tools/git-hunk.ts +52 -0
  232. package/src/commit/agentic/tools/git-overview.ts +62 -0
  233. package/src/commit/agentic/tools/index.ts +54 -0
  234. package/src/commit/agentic/tools/propose-changelog.ts +147 -0
  235. package/src/commit/agentic/tools/propose-commit.ts +109 -0
  236. package/src/commit/agentic/tools/recent-commits.ts +81 -0
  237. package/src/commit/agentic/tools/schemas.ts +11 -0
  238. package/src/commit/agentic/tools/split-commit.ts +241 -0
  239. package/src/commit/agentic/topo-sort.ts +44 -0
  240. package/src/commit/agentic/trivial.ts +51 -0
  241. package/src/commit/agentic/validation.ts +183 -0
  242. package/src/commit/analysis/conventional.ts +64 -0
  243. package/src/commit/analysis/index.ts +4 -0
  244. package/src/commit/analysis/scope.ts +242 -0
  245. package/src/commit/analysis/summary.ts +107 -0
  246. package/src/commit/analysis/validation.ts +66 -0
  247. package/src/commit/changelog/detect.ts +40 -0
  248. package/src/commit/changelog/generate.ts +101 -0
  249. package/src/commit/changelog/index.ts +234 -0
  250. package/src/commit/changelog/parse.ts +44 -0
  251. package/src/commit/cli.ts +85 -0
  252. package/src/commit/git/diff.ts +148 -0
  253. package/src/commit/index.ts +5 -0
  254. package/src/commit/map-reduce/index.ts +69 -0
  255. package/src/commit/map-reduce/map-phase.ts +193 -0
  256. package/src/commit/map-reduce/reduce-phase.ts +49 -0
  257. package/src/commit/map-reduce/utils.ts +9 -0
  258. package/src/commit/message.ts +11 -0
  259. package/src/commit/model-selection.ts +95 -0
  260. package/src/commit/pipeline.ts +244 -0
  261. package/src/commit/prompts/analysis-system.md +148 -0
  262. package/src/commit/prompts/analysis-user.md +38 -0
  263. package/src/commit/prompts/changelog-system.md +50 -0
  264. package/src/commit/prompts/changelog-user.md +18 -0
  265. package/src/commit/prompts/file-observer-system.md +24 -0
  266. package/src/commit/prompts/file-observer-user.md +8 -0
  267. package/src/commit/prompts/reduce-system.md +50 -0
  268. package/src/commit/prompts/reduce-user.md +17 -0
  269. package/src/commit/prompts/summary-retry.md +3 -0
  270. package/src/commit/prompts/summary-system.md +38 -0
  271. package/src/commit/prompts/summary-user.md +13 -0
  272. package/src/commit/prompts/types-description.md +2 -0
  273. package/src/commit/shared-llm.ts +70 -0
  274. package/src/commit/types.ts +118 -0
  275. package/src/commit/utils/exclusions.ts +42 -0
  276. package/src/commit/utils.ts +58 -0
  277. package/src/config/api-key-resolver.ts +81 -0
  278. package/src/config/append-only-context-mode.ts +76 -0
  279. package/src/config/config-file.ts +347 -0
  280. package/src/config/inline-tool-descriptors-mode.ts +26 -0
  281. package/src/config/keybindings.ts +703 -0
  282. package/src/config/mcp-schema.json +252 -0
  283. package/src/config/model-discovery.ts +1077 -0
  284. package/src/config/model-registry.ts +2822 -0
  285. package/src/config/model-resolver.ts +2115 -0
  286. package/src/config/model-roles.ts +113 -0
  287. package/src/config/models-config-schema-bundle.ts +315 -0
  288. package/src/config/models-config-schema.ts +14 -0
  289. package/src/config/models-config.ts +130 -0
  290. package/src/config/prompt-templates.ts +205 -0
  291. package/src/config/provider-globals.ts +25 -0
  292. package/src/config/resolve-config-value.ts +95 -0
  293. package/src/config/service-tier.ts +146 -0
  294. package/src/config/settings-schema.ts +5887 -0
  295. package/src/config/settings.ts +2394 -0
  296. package/src/config.ts +242 -0
  297. package/src/cursor-bridge-tools.ts +81 -0
  298. package/src/cursor.ts +960 -0
  299. package/src/dap/client.ts +1043 -0
  300. package/src/dap/config.ts +480 -0
  301. package/src/dap/defaults.json +212 -0
  302. package/src/dap/index.ts +4 -0
  303. package/src/dap/session.ts +1841 -0
  304. package/src/dap/types.ts +611 -0
  305. package/src/debug/index.ts +584 -0
  306. package/src/debug/log-formatting.ts +58 -0
  307. package/src/debug/log-viewer.ts +966 -0
  308. package/src/debug/profiler.ts +168 -0
  309. package/src/debug/protocol-probe.ts +267 -0
  310. package/src/debug/raw-sse-buffer.ts +421 -0
  311. package/src/debug/raw-sse.ts +312 -0
  312. package/src/debug/remote-debugger.ts +151 -0
  313. package/src/debug/report-bundle.ts +411 -0
  314. package/src/debug/system-info.ts +111 -0
  315. package/src/debug/terminal-info.ts +124 -0
  316. package/src/discovery/agent-plugin-format.ts +551 -0
  317. package/src/discovery/agent-plugins.ts +341 -0
  318. package/src/discovery/agents-md.ts +67 -0
  319. package/src/discovery/agents.ts +300 -0
  320. package/src/discovery/at-imports.ts +273 -0
  321. package/src/discovery/builtin-defaults.ts +39 -0
  322. package/src/discovery/builtin-rules/go-add-cleanup.md +33 -0
  323. package/src/discovery/builtin-rules/go-bench-loop.md +36 -0
  324. package/src/discovery/builtin-rules/go-exp-promoted.md +40 -0
  325. package/src/discovery/builtin-rules/go-ioutil.md +37 -0
  326. package/src/discovery/builtin-rules/go-join-hostport.md +30 -0
  327. package/src/discovery/builtin-rules/go-new-expr.md +44 -0
  328. package/src/discovery/builtin-rules/go-rand-v2.md +41 -0
  329. package/src/discovery/builtin-rules/go-range-int.md +45 -0
  330. package/src/discovery/builtin-rules/index.ts +74 -0
  331. package/src/discovery/builtin-rules/rs-box-leak.md +49 -0
  332. package/src/discovery/builtin-rules/rs-future-prelude.md +24 -0
  333. package/src/discovery/builtin-rules/rs-lazylock.md +52 -0
  334. package/src/discovery/builtin-rules/rs-match-ergonomics.md +68 -0
  335. package/src/discovery/builtin-rules/rs-parking-lot.md +45 -0
  336. package/src/discovery/builtin-rules/rs-result-type.md +20 -0
  337. package/src/discovery/builtin-rules/ts-bare-catch.md +39 -0
  338. package/src/discovery/builtin-rules/ts-import-type.md +43 -0
  339. package/src/discovery/builtin-rules/ts-no-any.md +66 -0
  340. package/src/discovery/builtin-rules/ts-no-deprecated-leftovers.md +45 -0
  341. package/src/discovery/builtin-rules/ts-no-dynamic-import.md +40 -0
  342. package/src/discovery/builtin-rules/ts-no-inline-cast-access.md +56 -0
  343. package/src/discovery/builtin-rules/ts-no-local-is-record.md +48 -0
  344. package/src/discovery/builtin-rules/ts-no-return-type.md +45 -0
  345. package/src/discovery/builtin-rules/ts-no-test-timers.md +55 -0
  346. package/src/discovery/builtin-rules/ts-no-tiny-functions.md +51 -0
  347. package/src/discovery/builtin-rules/ts-promise-with-resolvers.md +66 -0
  348. package/src/discovery/builtin-rules/ts-redundant-clear-guard.md +75 -0
  349. package/src/discovery/builtin-rules/ts-set-map.md +28 -0
  350. package/src/discovery/builtin.ts +945 -0
  351. package/src/discovery/claude-plugins.ts +640 -0
  352. package/src/discovery/claude.ts +591 -0
  353. package/src/discovery/cline.ts +83 -0
  354. package/src/discovery/codex.ts +553 -0
  355. package/src/discovery/contained-path.ts +78 -0
  356. package/src/discovery/cursor.ts +223 -0
  357. package/src/discovery/gemini.ts +386 -0
  358. package/src/discovery/github.ts +337 -0
  359. package/src/discovery/helpers.ts +1183 -0
  360. package/src/discovery/index.ts +82 -0
  361. package/src/discovery/mcp-json.ts +182 -0
  362. package/src/discovery/omp-extension-roots.ts +272 -0
  363. package/src/discovery/omp-plugins.ts +409 -0
  364. package/src/discovery/opencode.ts +441 -0
  365. package/src/discovery/plugin-dir-roots.ts +28 -0
  366. package/src/discovery/ssh.ts +153 -0
  367. package/src/discovery/substitute-plugin-root.ts +77 -0
  368. package/src/discovery/vscode.ts +106 -0
  369. package/src/discovery/windsurf.ts +149 -0
  370. package/src/edit/apply-patch/index.ts +87 -0
  371. package/src/edit/apply-patch/parser.ts +174 -0
  372. package/src/edit/diff.ts +1008 -0
  373. package/src/edit/edit-clipboard.ts +23 -0
  374. package/src/edit/file-snapshot-store.ts +148 -0
  375. package/src/edit/hashline/block-resolver.ts +33 -0
  376. package/src/edit/hashline/diff.ts +402 -0
  377. package/src/edit/hashline/execute.ts +313 -0
  378. package/src/edit/hashline/filesystem.ts +247 -0
  379. package/src/edit/hashline/index.ts +5 -0
  380. package/src/edit/hashline/noop-loop-guard.ts +99 -0
  381. package/src/edit/hashline/params.ts +12 -0
  382. package/src/edit/index.ts +699 -0
  383. package/src/edit/modes/apply-patch.lark +19 -0
  384. package/src/edit/modes/apply-patch.ts +53 -0
  385. package/src/edit/modes/patch.ts +1958 -0
  386. package/src/edit/modes/replace.ts +1191 -0
  387. package/src/edit/normalize.ts +345 -0
  388. package/src/edit/notebook.ts +242 -0
  389. package/src/edit/read-file.ts +25 -0
  390. package/src/edit/renderer.ts +998 -0
  391. package/src/edit/snapshot-details.ts +77 -0
  392. package/src/edit/streaming.ts +710 -0
  393. package/src/eval/agent-bridge.ts +224 -0
  394. package/src/eval/backend-helpers.ts +48 -0
  395. package/src/eval/backend.ts +71 -0
  396. package/src/eval/bridge-timeout.ts +65 -0
  397. package/src/eval/budget-bridge.ts +48 -0
  398. package/src/eval/completion-bridge.ts +212 -0
  399. package/src/eval/concurrency-bridge.ts +34 -0
  400. package/src/eval/executor-base.ts +562 -0
  401. package/src/eval/idle-timeout.ts +91 -0
  402. package/src/eval/index.ts +6 -0
  403. package/src/eval/jl/executor.ts +551 -0
  404. package/src/eval/jl/index.ts +54 -0
  405. package/src/eval/jl/kernel.ts +236 -0
  406. package/src/eval/jl/prelude.jl +736 -0
  407. package/src/eval/jl/prelude.ts +3 -0
  408. package/src/eval/jl/runner.jl +666 -0
  409. package/src/eval/jl/runtime.ts +118 -0
  410. package/src/eval/js/context-manager.ts +872 -0
  411. package/src/eval/js/executor.ts +178 -0
  412. package/src/eval/js/index.ts +41 -0
  413. package/src/eval/js/process-entry.ts +31 -0
  414. package/src/eval/js/shared/helpers.ts +170 -0
  415. package/src/eval/js/shared/indirect-eval.ts +30 -0
  416. package/src/eval/js/shared/local-module-loader.ts +364 -0
  417. package/src/eval/js/shared/prelude.ts +2 -0
  418. package/src/eval/js/shared/prelude.txt +294 -0
  419. package/src/eval/js/shared/rewrite-imports.ts +550 -0
  420. package/src/eval/js/shared/runtime.ts +590 -0
  421. package/src/eval/js/shared/types.ts +18 -0
  422. package/src/eval/js/tool-bridge.ts +163 -0
  423. package/src/eval/js/worker-core.ts +380 -0
  424. package/src/eval/js/worker-entry.ts +37 -0
  425. package/src/eval/js/worker-protocol.ts +47 -0
  426. package/src/eval/kernel-base.ts +569 -0
  427. package/src/eval/py/display.ts +71 -0
  428. package/src/eval/py/executor.ts +643 -0
  429. package/src/eval/py/index.ts +57 -0
  430. package/src/eval/py/kernel.ts +235 -0
  431. package/src/eval/py/prelude.py +673 -0
  432. package/src/eval/py/prelude.ts +3 -0
  433. package/src/eval/py/runner.py +1425 -0
  434. package/src/eval/py/runtime.ts +276 -0
  435. package/src/eval/py/spawn-options.ts +134 -0
  436. package/src/eval/py/tool-bridge.ts +201 -0
  437. package/src/eval/rb/executor.ts +511 -0
  438. package/src/eval/rb/index.ts +54 -0
  439. package/src/eval/rb/kernel.ts +231 -0
  440. package/src/eval/rb/prelude.rb +551 -0
  441. package/src/eval/rb/prelude.ts +3 -0
  442. package/src/eval/rb/runner.rb +581 -0
  443. package/src/eval/rb/runtime.ts +132 -0
  444. package/src/eval/runtime-env.ts +104 -0
  445. package/src/eval/session-id.ts +8 -0
  446. package/src/eval/types.ts +48 -0
  447. package/src/exa/index.ts +2 -0
  448. package/src/exa/mcp-client.ts +370 -0
  449. package/src/exa/types.ts +69 -0
  450. package/src/exec/bash-executor.ts +627 -0
  451. package/src/exec/direnv.ts +145 -0
  452. package/src/exec/exec.ts +53 -0
  453. package/src/exec/non-interactive-env.ts +118 -0
  454. package/src/export/custom-share.ts +65 -0
  455. package/src/export/html/args.ts +20 -0
  456. package/src/export/html/index.ts +320 -0
  457. package/src/export/html/share-loader.js +102 -0
  458. package/src/export/html/template.css +1355 -0
  459. package/src/export/html/template.html +55 -0
  460. package/src/export/html/template.js +1653 -0
  461. package/src/export/html/tool-views.generated.js +35 -0
  462. package/src/export/html/vendor/highlight.min.js +1213 -0
  463. package/src/export/html/vendor/marked.min.js +6 -0
  464. package/src/export/html/web-palette.ts +126 -0
  465. package/src/export/share.ts +686 -0
  466. package/src/export/ttsr.ts +590 -0
  467. package/src/extensibility/custom-commands/bundled/ci-green/index.ts +54 -0
  468. package/src/extensibility/custom-commands/bundled/review/index.ts +698 -0
  469. package/src/extensibility/custom-commands/index.ts +2 -0
  470. package/src/extensibility/custom-commands/loader.ts +242 -0
  471. package/src/extensibility/custom-commands/types.ts +119 -0
  472. package/src/extensibility/custom-tools/index.ts +7 -0
  473. package/src/extensibility/custom-tools/loader.ts +301 -0
  474. package/src/extensibility/custom-tools/types.ts +287 -0
  475. package/src/extensibility/custom-tools/wrapper.ts +50 -0
  476. package/src/extensibility/extensions/compact-handler.ts +40 -0
  477. package/src/extensibility/extensions/get-commands-handler.ts +78 -0
  478. package/src/extensibility/extensions/index.ts +16 -0
  479. package/src/extensibility/extensions/load-errors.ts +13 -0
  480. package/src/extensibility/extensions/loader.ts +663 -0
  481. package/src/extensibility/extensions/managed-timers.ts +83 -0
  482. package/src/extensibility/extensions/model-api.ts +39 -0
  483. package/src/extensibility/extensions/runner.ts +1396 -0
  484. package/src/extensibility/extensions/types.ts +1603 -0
  485. package/src/extensibility/extensions/wrapper.ts +395 -0
  486. package/src/extensibility/hooks/index.ts +6 -0
  487. package/src/extensibility/hooks/loader.ts +243 -0
  488. package/src/extensibility/hooks/runner.ts +425 -0
  489. package/src/extensibility/hooks/tool-wrapper.ts +124 -0
  490. package/src/extensibility/hooks/types.ts +612 -0
  491. package/src/extensibility/legacy-pi-ai-shim.ts +161 -0
  492. package/src/extensibility/legacy-pi-coding-agent-shim.ts +1460 -0
  493. package/src/extensibility/legacy-pi-tui-shim.ts +43 -0
  494. package/src/extensibility/legacy-typebox.ts +101 -0
  495. package/src/extensibility/plugins/bun-git-cache.ts +91 -0
  496. package/src/extensibility/plugins/doctor.ts +65 -0
  497. package/src/extensibility/plugins/git-url.ts +367 -0
  498. package/src/extensibility/plugins/index.ts +9 -0
  499. package/src/extensibility/plugins/installer.ts +201 -0
  500. package/src/extensibility/plugins/legacy-pi-compat.ts +2643 -0
  501. package/src/extensibility/plugins/legacy-pi-virtual-modules.d.ts +4 -0
  502. package/src/extensibility/plugins/loader.ts +535 -0
  503. package/src/extensibility/plugins/manager.ts +1142 -0
  504. package/src/extensibility/plugins/marketplace/cache.ts +136 -0
  505. package/src/extensibility/plugins/marketplace/fetcher.ts +316 -0
  506. package/src/extensibility/plugins/marketplace/index.ts +6 -0
  507. package/src/extensibility/plugins/marketplace/manager.ts +927 -0
  508. package/src/extensibility/plugins/marketplace/registry.ts +192 -0
  509. package/src/extensibility/plugins/marketplace/source-resolver.ts +147 -0
  510. package/src/extensibility/plugins/marketplace/types.ts +192 -0
  511. package/src/extensibility/plugins/marketplace-auto-update.ts +49 -0
  512. package/src/extensibility/plugins/parser.ts +107 -0
  513. package/src/extensibility/plugins/runtime-config.ts +9 -0
  514. package/src/extensibility/plugins/types.ts +194 -0
  515. package/src/extensibility/session-handler-types.ts +21 -0
  516. package/src/extensibility/shared-events.ts +401 -0
  517. package/src/extensibility/skills.ts +531 -0
  518. package/src/extensibility/slash-commands.ts +131 -0
  519. package/src/extensibility/tool-event-input.ts +80 -0
  520. package/src/extensibility/tool-proxy.ts +28 -0
  521. package/src/extensibility/utils.ts +192 -0
  522. package/src/goals/index.ts +3 -0
  523. package/src/goals/runtime.ts +521 -0
  524. package/src/goals/state.ts +37 -0
  525. package/src/goals/tools/goal-tool.ts +251 -0
  526. package/src/hindsight/backend.ts +354 -0
  527. package/src/hindsight/bank.ts +156 -0
  528. package/src/hindsight/client.ts +680 -0
  529. package/src/hindsight/config.ts +193 -0
  530. package/src/hindsight/content.ts +266 -0
  531. package/src/hindsight/index.ts +8 -0
  532. package/src/hindsight/mental-models.ts +429 -0
  533. package/src/hindsight/seeds.json +32 -0
  534. package/src/hindsight/state.ts +530 -0
  535. package/src/hindsight/transcript.ts +71 -0
  536. package/src/index.ts +66 -0
  537. package/src/internal-urls/agent-protocol.ts +180 -0
  538. package/src/internal-urls/artifact-protocol.ts +151 -0
  539. package/src/internal-urls/docs-index.ts +102 -0
  540. package/src/internal-urls/filesystem-resource.ts +34 -0
  541. package/src/internal-urls/history-protocol.ts +198 -0
  542. package/src/internal-urls/index.ts +28 -0
  543. package/src/internal-urls/issue-pr-protocol.ts +594 -0
  544. package/src/internal-urls/json-query.ts +126 -0
  545. package/src/internal-urls/local-protocol.ts +471 -0
  546. package/src/internal-urls/mcp-protocol.ts +168 -0
  547. package/src/internal-urls/memory-protocol.ts +380 -0
  548. package/src/internal-urls/omp-protocol.ts +94 -0
  549. package/src/internal-urls/parse.ts +103 -0
  550. package/src/internal-urls/registry-helpers.ts +132 -0
  551. package/src/internal-urls/router.ts +153 -0
  552. package/src/internal-urls/rule-protocol.ts +45 -0
  553. package/src/internal-urls/security-protocol.ts +261 -0
  554. package/src/internal-urls/skill-protocol.ts +131 -0
  555. package/src/internal-urls/ssh-protocol.ts +368 -0
  556. package/src/internal-urls/types.ts +196 -0
  557. package/src/internal-urls/vault-protocol.ts +940 -0
  558. package/src/internal-urls/xd-protocol.ts +46 -0
  559. package/src/irc/bus.ts +380 -0
  560. package/src/jsonrpc/message-framing.ts +142 -0
  561. package/src/launch/broker.ts +1368 -0
  562. package/src/launch/client.ts +521 -0
  563. package/src/launch/ensure.ts +73 -0
  564. package/src/launch/paths.ts +14 -0
  565. package/src/launch/presence.ts +82 -0
  566. package/src/launch/protocol.ts +448 -0
  567. package/src/launch/spawn-options.ts +17 -0
  568. package/src/launch/terminal-output-worker-client.ts +53 -0
  569. package/src/launch/terminal-output-worker-protocol.ts +11 -0
  570. package/src/launch/terminal-output-worker.ts +23 -0
  571. package/src/launch/terminal-output.ts +46 -0
  572. package/src/lib/xai-http.ts +150 -0
  573. package/src/live/attestation.ts +91 -0
  574. package/src/live/controller.ts +517 -0
  575. package/src/live/prompts/agent-final-message.md +3 -0
  576. package/src/live/prompts/live-instructions.md +23 -0
  577. package/src/live/protocol.ts +233 -0
  578. package/src/live/transport.ts +422 -0
  579. package/src/live/visualizer.ts +221 -0
  580. package/src/live/voices.ts +18 -0
  581. package/src/lsp/client.ts +1465 -0
  582. package/src/lsp/clients/biome-client.ts +263 -0
  583. package/src/lsp/clients/index.ts +50 -0
  584. package/src/lsp/clients/lsp-linter-client.ts +85 -0
  585. package/src/lsp/clients/swiftlint-client.ts +120 -0
  586. package/src/lsp/config.ts +549 -0
  587. package/src/lsp/defaults.json +499 -0
  588. package/src/lsp/deferred-diagnostics.ts +66 -0
  589. package/src/lsp/diagnostics-ledger.ts +51 -0
  590. package/src/lsp/edits.ts +288 -0
  591. package/src/lsp/format-options.ts +119 -0
  592. package/src/lsp/index.ts +2821 -0
  593. package/src/lsp/lspmux.ts +233 -0
  594. package/src/lsp/mux/daemon.ts +348 -0
  595. package/src/lsp/mux/protocol.ts +96 -0
  596. package/src/lsp/mux/server.ts +797 -0
  597. package/src/lsp/render.ts +668 -0
  598. package/src/lsp/startup-events.ts +13 -0
  599. package/src/lsp/types.ts +479 -0
  600. package/src/lsp/utils.ts +747 -0
  601. package/src/main.ts +1799 -0
  602. package/src/markit/NOTICE +32 -0
  603. package/src/markit/converters/docx.ts +56 -0
  604. package/src/markit/converters/epub.ts +136 -0
  605. package/src/markit/converters/pdf/columns.ts +103 -0
  606. package/src/markit/converters/pdf/extract.ts +598 -0
  607. package/src/markit/converters/pdf/grid.ts +780 -0
  608. package/src/markit/converters/pdf/headers.ts +106 -0
  609. package/src/markit/converters/pdf/index.ts +146 -0
  610. package/src/markit/converters/pdf/render.ts +501 -0
  611. package/src/markit/converters/pdf/types.ts +84 -0
  612. package/src/markit/converters/pptx.ts +325 -0
  613. package/src/markit/converters/xlsx.ts +173 -0
  614. package/src/markit/index.ts +2 -0
  615. package/src/markit/registry.ts +59 -0
  616. package/src/markit/types.ts +35 -0
  617. package/src/mcp/client.ts +511 -0
  618. package/src/mcp/config-writer.ts +377 -0
  619. package/src/mcp/config.ts +385 -0
  620. package/src/mcp/index.ts +29 -0
  621. package/src/mcp/json-rpc.ts +122 -0
  622. package/src/mcp/loader.ts +125 -0
  623. package/src/mcp/manager.ts +1524 -0
  624. package/src/mcp/oauth-credentials.ts +104 -0
  625. package/src/mcp/oauth-discovery.ts +587 -0
  626. package/src/mcp/oauth-flow.ts +830 -0
  627. package/src/mcp/render.ts +214 -0
  628. package/src/mcp/request-id.ts +24 -0
  629. package/src/mcp/smithery-auth.ts +108 -0
  630. package/src/mcp/smithery-connect.ts +154 -0
  631. package/src/mcp/smithery-registry.ts +500 -0
  632. package/src/mcp/startup-events.ts +116 -0
  633. package/src/mcp/timeout.ts +59 -0
  634. package/src/mcp/tool-bridge.ts +691 -0
  635. package/src/mcp/tool-cache.ts +117 -0
  636. package/src/mcp/transports/header-policy.ts +95 -0
  637. package/src/mcp/transports/http.ts +508 -0
  638. package/src/mcp/transports/index.ts +7 -0
  639. package/src/mcp/transports/sse.ts +372 -0
  640. package/src/mcp/transports/stdio.ts +905 -0
  641. package/src/mcp/types.ts +467 -0
  642. package/src/memories/index.ts +1434 -0
  643. package/src/memories/storage.ts +578 -0
  644. package/src/memory-backend/index.ts +19 -0
  645. package/src/memory-backend/local-backend.ts +47 -0
  646. package/src/memory-backend/messages.ts +19 -0
  647. package/src/memory-backend/off-backend.ts +25 -0
  648. package/src/memory-backend/resolve.ts +25 -0
  649. package/src/memory-backend/runtime.ts +66 -0
  650. package/src/memory-backend/tool-names.ts +2 -0
  651. package/src/memory-backend/types.ts +166 -0
  652. package/src/mnemopi/backend.ts +629 -0
  653. package/src/mnemopi/config.ts +267 -0
  654. package/src/mnemopi/embed-client.ts +293 -0
  655. package/src/mnemopi/embed-protocol.ts +35 -0
  656. package/src/mnemopi/embed-worker.ts +114 -0
  657. package/src/mnemopi/index.ts +3 -0
  658. package/src/mnemopi/state.ts +940 -0
  659. package/src/modes/acp/acp-agent.ts +2595 -0
  660. package/src/modes/acp/acp-client-bridge.ts +154 -0
  661. package/src/modes/acp/acp-event-mapper.ts +1084 -0
  662. package/src/modes/acp/acp-mode.ts +48 -0
  663. package/src/modes/acp/index.ts +2 -0
  664. package/src/modes/acp/terminal-auth.ts +37 -0
  665. package/src/modes/components/advisor-config.ts +635 -0
  666. package/src/modes/components/advisor-message.ts +109 -0
  667. package/src/modes/components/agent-dashboard.ts +1252 -0
  668. package/src/modes/components/agent-hub-projection.ts +248 -0
  669. package/src/modes/components/agent-hub-renderer.ts +194 -0
  670. package/src/modes/components/agent-hub.ts +1126 -0
  671. package/src/modes/components/agent-transcript-viewer.ts +647 -0
  672. package/src/modes/components/ask-dialog.ts +1017 -0
  673. package/src/modes/components/assistant-message.ts +978 -0
  674. package/src/modes/components/background-tan-message.ts +36 -0
  675. package/src/modes/components/bash-execution.ts +233 -0
  676. package/src/modes/components/bordered-loader.ts +41 -0
  677. package/src/modes/components/btw-panel.ts +161 -0
  678. package/src/modes/components/cache-invalidation-marker.ts +110 -0
  679. package/src/modes/components/chat-block.ts +111 -0
  680. package/src/modes/components/chat-transcript-builder.ts +518 -0
  681. package/src/modes/components/codex-reset-fireworks.ts +369 -0
  682. package/src/modes/components/collab-prompt-message.ts +32 -0
  683. package/src/modes/components/compaction-summary-message.ts +221 -0
  684. package/src/modes/components/copy-selector.ts +218 -0
  685. package/src/modes/components/countdown-timer.ts +75 -0
  686. package/src/modes/components/custom-editor.ts +1036 -0
  687. package/src/modes/components/custom-message.ts +70 -0
  688. package/src/modes/components/diff.ts +254 -0
  689. package/src/modes/components/dynamic-border.ts +37 -0
  690. package/src/modes/components/error-banner.ts +33 -0
  691. package/src/modes/components/eval-execution.ts +169 -0
  692. package/src/modes/components/execution-shared.ts +101 -0
  693. package/src/modes/components/extensions/extension-dashboard.ts +492 -0
  694. package/src/modes/components/extensions/extension-list.ts +507 -0
  695. package/src/modes/components/extensions/index.ts +9 -0
  696. package/src/modes/components/extensions/inspector-panel.ts +326 -0
  697. package/src/modes/components/extensions/state-manager.ts +648 -0
  698. package/src/modes/components/extensions/types.ts +186 -0
  699. package/src/modes/components/footer.ts +274 -0
  700. package/src/modes/components/history-search.ts +268 -0
  701. package/src/modes/components/hook-editor.ts +213 -0
  702. package/src/modes/components/hook-input.ts +87 -0
  703. package/src/modes/components/hook-message.ts +67 -0
  704. package/src/modes/components/hook-selector.ts +691 -0
  705. package/src/modes/components/index.ts +42 -0
  706. package/src/modes/components/keybinding-hints.ts +56 -0
  707. package/src/modes/components/late-diagnostics-message.ts +60 -0
  708. package/src/modes/components/login-dialog.ts +197 -0
  709. package/src/modes/components/logout-account-selector.ts +130 -0
  710. package/src/modes/components/mcp-add-wizard.ts +1413 -0
  711. package/src/modes/components/message-frame.ts +98 -0
  712. package/src/modes/components/model-browser.ts +888 -0
  713. package/src/modes/components/model-hub.ts +2014 -0
  714. package/src/modes/components/model-picker.ts +237 -0
  715. package/src/modes/components/move-overlay.ts +293 -0
  716. package/src/modes/components/oauth-selector.ts +474 -0
  717. package/src/modes/components/omfg-panel.ts +141 -0
  718. package/src/modes/components/overlay-box.ts +109 -0
  719. package/src/modes/components/pause-screen.ts +208 -0
  720. package/src/modes/components/plan-review-overlay.ts +1226 -0
  721. package/src/modes/components/plan-toc.ts +138 -0
  722. package/src/modes/components/plugin-selector.ts +100 -0
  723. package/src/modes/components/plugin-settings.ts +745 -0
  724. package/src/modes/components/queue-mode-selector.ts +61 -0
  725. package/src/modes/components/read-tool-group.ts +856 -0
  726. package/src/modes/components/reset-usage-selector.ts +161 -0
  727. package/src/modes/components/segment-track.ts +89 -0
  728. package/src/modes/components/select-list-mouse-routing.ts +35 -0
  729. package/src/modes/components/selector-helpers.ts +129 -0
  730. package/src/modes/components/session-account-selector.ts +62 -0
  731. package/src/modes/components/session-selector.ts +1035 -0
  732. package/src/modes/components/settings-defs.ts +267 -0
  733. package/src/modes/components/settings-selector.ts +1445 -0
  734. package/src/modes/components/show-images-selector.ts +50 -0
  735. package/src/modes/components/skill-message.ts +110 -0
  736. package/src/modes/components/snapcompact-shape-preview-doc.md +14 -0
  737. package/src/modes/components/snapcompact-shape-preview.ts +192 -0
  738. package/src/modes/components/status-line/component.ts +1843 -0
  739. package/src/modes/components/status-line/context-thresholds.ts +86 -0
  740. package/src/modes/components/status-line/git-utils.ts +42 -0
  741. package/src/modes/components/status-line/index.ts +5 -0
  742. package/src/modes/components/status-line/presets.ts +106 -0
  743. package/src/modes/components/status-line/segments.ts +710 -0
  744. package/src/modes/components/status-line/separators.ts +55 -0
  745. package/src/modes/components/status-line/types.ts +159 -0
  746. package/src/modes/components/stripped-tool-calls-placeholder.ts +35 -0
  747. package/src/modes/components/theme-selector.ts +68 -0
  748. package/src/modes/components/thinking-selector.ts +57 -0
  749. package/src/modes/components/tiny-title-download-progress.ts +90 -0
  750. package/src/modes/components/tips.txt +26 -0
  751. package/src/modes/components/todo-reminder.ts +43 -0
  752. package/src/modes/components/tool-execution.ts +1467 -0
  753. package/src/modes/components/transcript-container.ts +527 -0
  754. package/src/modes/components/tree-selector.ts +1006 -0
  755. package/src/modes/components/ttsr-notification.ts +123 -0
  756. package/src/modes/components/usage-row.ts +52 -0
  757. package/src/modes/components/user-message-selector.ts +227 -0
  758. package/src/modes/components/user-message.ts +167 -0
  759. package/src/modes/components/visual-truncate.ts +63 -0
  760. package/src/modes/components/welcome.ts +578 -0
  761. package/src/modes/controllers/btw-controller.ts +246 -0
  762. package/src/modes/controllers/command-controller-shared.ts +109 -0
  763. package/src/modes/controllers/command-controller.ts +2024 -0
  764. package/src/modes/controllers/event-controller.ts +2173 -0
  765. package/src/modes/controllers/extension-ui-controller.ts +1243 -0
  766. package/src/modes/controllers/input-controller.ts +2037 -0
  767. package/src/modes/controllers/live-command-controller.ts +261 -0
  768. package/src/modes/controllers/mcp-command-controller.ts +2552 -0
  769. package/src/modes/controllers/omfg-controller.ts +287 -0
  770. package/src/modes/controllers/omfg-rule.ts +647 -0
  771. package/src/modes/controllers/selector-controller.ts +2058 -0
  772. package/src/modes/controllers/session-focus-controller.ts +117 -0
  773. package/src/modes/controllers/ssh-command-controller.ts +385 -0
  774. package/src/modes/controllers/streaming-reveal.ts +399 -0
  775. package/src/modes/controllers/tan-command-controller.ts +243 -0
  776. package/src/modes/controllers/todo-command-controller.ts +487 -0
  777. package/src/modes/controllers/tool-args-reveal.ts +591 -0
  778. package/src/modes/data/emojis.json +1 -0
  779. package/src/modes/emoji-autocomplete.ts +285 -0
  780. package/src/modes/github-ref-autocomplete.ts +75 -0
  781. package/src/modes/gradient-highlight.ts +99 -0
  782. package/src/modes/image-references.ts +137 -0
  783. package/src/modes/index.ts +10 -0
  784. package/src/modes/interactive-mode.ts +5055 -0
  785. package/src/modes/internal-url-autocomplete.ts +158 -0
  786. package/src/modes/loop-limit.ts +192 -0
  787. package/src/modes/magic-keyword-boundary.ts +23 -0
  788. package/src/modes/magic-keywords.ts +42 -0
  789. package/src/modes/markdown-prose.ts +247 -0
  790. package/src/modes/oauth-manual-input.ts +69 -0
  791. package/src/modes/orchestrate.ts +43 -0
  792. package/src/modes/print-mode.ts +282 -0
  793. package/src/modes/prompt-action-autocomplete.ts +322 -0
  794. package/src/modes/queue-input.ts +132 -0
  795. package/src/modes/rpc/host-tools.ts +204 -0
  796. package/src/modes/rpc/host-uris.ts +241 -0
  797. package/src/modes/rpc/rpc-client.ts +1213 -0
  798. package/src/modes/rpc/rpc-frame.ts +316 -0
  799. package/src/modes/rpc/rpc-input.ts +38 -0
  800. package/src/modes/rpc/rpc-messages.ts +127 -0
  801. package/src/modes/rpc/rpc-mode.ts +1519 -0
  802. package/src/modes/rpc/rpc-subagents.ts +265 -0
  803. package/src/modes/rpc/rpc-types.ts +544 -0
  804. package/src/modes/running-subagent-badge.ts +13 -0
  805. package/src/modes/runtime-init.ts +144 -0
  806. package/src/modes/session-observer-registry.ts +223 -0
  807. package/src/modes/session-teardown.ts +82 -0
  808. package/src/modes/setup-version.ts +11 -0
  809. package/src/modes/setup-wizard/index.ts +103 -0
  810. package/src/modes/setup-wizard/lazy.ts +16 -0
  811. package/src/modes/setup-wizard/scenes/glyph.ts +103 -0
  812. package/src/modes/setup-wizard/scenes/model.ts +132 -0
  813. package/src/modes/setup-wizard/scenes/outro.ts +35 -0
  814. package/src/modes/setup-wizard/scenes/providers.ts +105 -0
  815. package/src/modes/setup-wizard/scenes/sign-in.ts +312 -0
  816. package/src/modes/setup-wizard/scenes/splash.ts +201 -0
  817. package/src/modes/setup-wizard/scenes/theme.ts +330 -0
  818. package/src/modes/setup-wizard/scenes/types.ts +65 -0
  819. package/src/modes/setup-wizard/scenes/web-search.ts +153 -0
  820. package/src/modes/setup-wizard/startup-splash.ts +107 -0
  821. package/src/modes/setup-wizard/wizard-overlay.ts +335 -0
  822. package/src/modes/shared.ts +49 -0
  823. package/src/modes/skill-command.ts +91 -0
  824. package/src/modes/theme/dark.json +95 -0
  825. package/src/modes/theme/defaults/alabaster.json +93 -0
  826. package/src/modes/theme/defaults/amethyst.json +96 -0
  827. package/src/modes/theme/defaults/anthracite.json +93 -0
  828. package/src/modes/theme/defaults/basalt.json +91 -0
  829. package/src/modes/theme/defaults/birch.json +95 -0
  830. package/src/modes/theme/defaults/dark-abyss.json +91 -0
  831. package/src/modes/theme/defaults/dark-arctic.json +104 -0
  832. package/src/modes/theme/defaults/dark-aurora.json +95 -0
  833. package/src/modes/theme/defaults/dark-catppuccin.json +107 -0
  834. package/src/modes/theme/defaults/dark-cavern.json +91 -0
  835. package/src/modes/theme/defaults/dark-copper.json +95 -0
  836. package/src/modes/theme/defaults/dark-cosmos.json +90 -0
  837. package/src/modes/theme/defaults/dark-cyberpunk.json +102 -0
  838. package/src/modes/theme/defaults/dark-dracula.json +98 -0
  839. package/src/modes/theme/defaults/dark-eclipse.json +91 -0
  840. package/src/modes/theme/defaults/dark-ember.json +95 -0
  841. package/src/modes/theme/defaults/dark-equinox.json +90 -0
  842. package/src/modes/theme/defaults/dark-forest.json +96 -0
  843. package/src/modes/theme/defaults/dark-github.json +105 -0
  844. package/src/modes/theme/defaults/dark-gruvbox.json +112 -0
  845. package/src/modes/theme/defaults/dark-lavender.json +95 -0
  846. package/src/modes/theme/defaults/dark-lunar.json +89 -0
  847. package/src/modes/theme/defaults/dark-midnight.json +95 -0
  848. package/src/modes/theme/defaults/dark-monochrome.json +94 -0
  849. package/src/modes/theme/defaults/dark-monokai.json +98 -0
  850. package/src/modes/theme/defaults/dark-nebula.json +90 -0
  851. package/src/modes/theme/defaults/dark-nord.json +97 -0
  852. package/src/modes/theme/defaults/dark-ocean.json +101 -0
  853. package/src/modes/theme/defaults/dark-one.json +100 -0
  854. package/src/modes/theme/defaults/dark-poimandres.json +143 -0
  855. package/src/modes/theme/defaults/dark-rainforest.json +91 -0
  856. package/src/modes/theme/defaults/dark-reef.json +91 -0
  857. package/src/modes/theme/defaults/dark-retro.json +92 -0
  858. package/src/modes/theme/defaults/dark-rose-pine.json +96 -0
  859. package/src/modes/theme/defaults/dark-sakura.json +95 -0
  860. package/src/modes/theme/defaults/dark-slate.json +95 -0
  861. package/src/modes/theme/defaults/dark-solarized.json +97 -0
  862. package/src/modes/theme/defaults/dark-solstice.json +90 -0
  863. package/src/modes/theme/defaults/dark-starfall.json +91 -0
  864. package/src/modes/theme/defaults/dark-sunset.json +99 -0
  865. package/src/modes/theme/defaults/dark-swamp.json +90 -0
  866. package/src/modes/theme/defaults/dark-synthwave.json +103 -0
  867. package/src/modes/theme/defaults/dark-taiga.json +91 -0
  868. package/src/modes/theme/defaults/dark-terminal.json +95 -0
  869. package/src/modes/theme/defaults/dark-tokyo-night.json +101 -0
  870. package/src/modes/theme/defaults/dark-tundra.json +91 -0
  871. package/src/modes/theme/defaults/dark-twilight.json +91 -0
  872. package/src/modes/theme/defaults/dark-volcanic.json +91 -0
  873. package/src/modes/theme/defaults/graphite.json +92 -0
  874. package/src/modes/theme/defaults/index.ts +199 -0
  875. package/src/modes/theme/defaults/light-arctic.json +107 -0
  876. package/src/modes/theme/defaults/light-aurora-day.json +91 -0
  877. package/src/modes/theme/defaults/light-canyon.json +91 -0
  878. package/src/modes/theme/defaults/light-catppuccin.json +106 -0
  879. package/src/modes/theme/defaults/light-cirrus.json +90 -0
  880. package/src/modes/theme/defaults/light-coral.json +95 -0
  881. package/src/modes/theme/defaults/light-cyberpunk.json +96 -0
  882. package/src/modes/theme/defaults/light-dawn.json +90 -0
  883. package/src/modes/theme/defaults/light-dunes.json +91 -0
  884. package/src/modes/theme/defaults/light-eucalyptus.json +95 -0
  885. package/src/modes/theme/defaults/light-forest.json +100 -0
  886. package/src/modes/theme/defaults/light-frost.json +95 -0
  887. package/src/modes/theme/defaults/light-github.json +115 -0
  888. package/src/modes/theme/defaults/light-glacier.json +91 -0
  889. package/src/modes/theme/defaults/light-gruvbox.json +108 -0
  890. package/src/modes/theme/defaults/light-haze.json +90 -0
  891. package/src/modes/theme/defaults/light-honeycomb.json +95 -0
  892. package/src/modes/theme/defaults/light-lagoon.json +91 -0
  893. package/src/modes/theme/defaults/light-lavender.json +95 -0
  894. package/src/modes/theme/defaults/light-meadow.json +91 -0
  895. package/src/modes/theme/defaults/light-mint.json +95 -0
  896. package/src/modes/theme/defaults/light-monochrome.json +101 -0
  897. package/src/modes/theme/defaults/light-ocean.json +99 -0
  898. package/src/modes/theme/defaults/light-one.json +99 -0
  899. package/src/modes/theme/defaults/light-opal.json +91 -0
  900. package/src/modes/theme/defaults/light-orchard.json +91 -0
  901. package/src/modes/theme/defaults/light-paper.json +95 -0
  902. package/src/modes/theme/defaults/light-poimandres.json +143 -0
  903. package/src/modes/theme/defaults/light-prism.json +90 -0
  904. package/src/modes/theme/defaults/light-retro.json +98 -0
  905. package/src/modes/theme/defaults/light-sand.json +95 -0
  906. package/src/modes/theme/defaults/light-savanna.json +91 -0
  907. package/src/modes/theme/defaults/light-solarized.json +102 -0
  908. package/src/modes/theme/defaults/light-soleil.json +90 -0
  909. package/src/modes/theme/defaults/light-sunset.json +99 -0
  910. package/src/modes/theme/defaults/light-synthwave.json +98 -0
  911. package/src/modes/theme/defaults/light-tokyo-night.json +111 -0
  912. package/src/modes/theme/defaults/light-wetland.json +91 -0
  913. package/src/modes/theme/defaults/light-zenith.json +89 -0
  914. package/src/modes/theme/defaults/limestone.json +94 -0
  915. package/src/modes/theme/defaults/mahogany.json +97 -0
  916. package/src/modes/theme/defaults/marble.json +93 -0
  917. package/src/modes/theme/defaults/obsidian.json +91 -0
  918. package/src/modes/theme/defaults/onyx.json +91 -0
  919. package/src/modes/theme/defaults/pearl.json +93 -0
  920. package/src/modes/theme/defaults/porcelain.json +91 -0
  921. package/src/modes/theme/defaults/quartz.json +96 -0
  922. package/src/modes/theme/defaults/sandstone.json +95 -0
  923. package/src/modes/theme/defaults/titanium.json +90 -0
  924. package/src/modes/theme/light.json +93 -0
  925. package/src/modes/theme/mermaid-cache.ts +92 -0
  926. package/src/modes/theme/shimmer.ts +305 -0
  927. package/src/modes/theme/theme-schema.json +463 -0
  928. package/src/modes/theme/theme.ts +3171 -0
  929. package/src/modes/turn-budget.ts +31 -0
  930. package/src/modes/types.ts +494 -0
  931. package/src/modes/ultrathink.ts +42 -0
  932. package/src/modes/utils/context-usage.ts +518 -0
  933. package/src/modes/utils/copy-targets.ts +378 -0
  934. package/src/modes/utils/hotkeys-markdown.ts +65 -0
  935. package/src/modes/utils/interactive-context-helpers.ts +31 -0
  936. package/src/modes/utils/keybinding-matchers.ts +86 -0
  937. package/src/modes/utils/tools-markdown.ts +31 -0
  938. package/src/modes/utils/transcript-render-helpers.ts +253 -0
  939. package/src/modes/utils/ui-helpers.ts +976 -0
  940. package/src/modes/warp-events.ts +232 -0
  941. package/src/modes/workflow.ts +55 -0
  942. package/src/plan-mode/approved-plan.ts +194 -0
  943. package/src/plan-mode/model-transition.ts +51 -0
  944. package/src/plan-mode/plan-files.ts +40 -0
  945. package/src/plan-mode/plan-handoff.ts +37 -0
  946. package/src/plan-mode/plan-protection.ts +31 -0
  947. package/src/plan-mode/state.ts +6 -0
  948. package/src/priority.json +60 -0
  949. package/src/prompts/advisor/active-repo-watchdog.md +6 -0
  950. package/src/prompts/advisor/advise-tool.md +3 -0
  951. package/src/prompts/advisor/context-files.md +8 -0
  952. package/src/prompts/advisor/system.md +98 -0
  953. package/src/prompts/agents/designer.md +74 -0
  954. package/src/prompts/agents/frontmatter.md +12 -0
  955. package/src/prompts/agents/init.md +33 -0
  956. package/src/prompts/agents/librarian.md +119 -0
  957. package/src/prompts/agents/reviewer.md +139 -0
  958. package/src/prompts/agents/scout.md +58 -0
  959. package/src/prompts/agents/security-reviewer.md +75 -0
  960. package/src/prompts/agents/task.md +17 -0
  961. package/src/prompts/bench/cache-prefix-chunk.md +1 -0
  962. package/src/prompts/bench/cache-prefix.md +3 -0
  963. package/src/prompts/bench/cache-suffix.md +1 -0
  964. package/src/prompts/bench.md +6 -0
  965. package/src/prompts/ci-green-request.md +36 -0
  966. package/src/prompts/dry-balance-bench.md +8 -0
  967. package/src/prompts/goals/goal-budget-limit.md +16 -0
  968. package/src/prompts/goals/goal-continuation.md +28 -0
  969. package/src/prompts/goals/goal-mode-active.md +23 -0
  970. package/src/prompts/goals/goal-mode-context.md +4 -0
  971. package/src/prompts/goals/goal-todo-context.md +12 -0
  972. package/src/prompts/goals/guided-goal-interview.md +43 -0
  973. package/src/prompts/memories/consolidation.md +30 -0
  974. package/src/prompts/memories/consolidation_system.md +4 -0
  975. package/src/prompts/memories/read-path.md +17 -0
  976. package/src/prompts/memories/stage_one_input.md +6 -0
  977. package/src/prompts/memories/stage_one_system.md +21 -0
  978. package/src/prompts/review-custom-request.md +21 -0
  979. package/src/prompts/review-headless-request.md +16 -0
  980. package/src/prompts/review-request.md +68 -0
  981. package/src/prompts/security/scan-coordinator.md +7 -0
  982. package/src/prompts/security/scan-request.md +21 -0
  983. package/src/prompts/security/validate-request.md +8 -0
  984. package/src/prompts/session/launch-completion.md +1 -0
  985. package/src/prompts/skills/autoload.md +8 -0
  986. package/src/prompts/skills/user-invocation.md +11 -0
  987. package/src/prompts/steering/parent-irc.md +5 -0
  988. package/src/prompts/steering/user-interjection.md +6 -0
  989. package/src/prompts/system/active-repo-context.md +4 -0
  990. package/src/prompts/system/agent-creation-architect.md +50 -0
  991. package/src/prompts/system/agent-creation-user.md +6 -0
  992. package/src/prompts/system/auto-continue.md +1 -0
  993. package/src/prompts/system/auto-thinking-difficulty-local.md +14 -0
  994. package/src/prompts/system/auto-thinking-difficulty.md +14 -0
  995. package/src/prompts/system/autolearn-guidance-learn.md +1 -0
  996. package/src/prompts/system/autolearn-guidance.md +7 -0
  997. package/src/prompts/system/autolearn-nudge-autocontinue.md +5 -0
  998. package/src/prompts/system/background-tan-dispatch.md +8 -0
  999. package/src/prompts/system/btw-user.md +8 -0
  1000. package/src/prompts/system/commit-message-system.md +14 -0
  1001. package/src/prompts/system/computer-safety.md +14 -0
  1002. package/src/prompts/system/custom-system-prompt.md +64 -0
  1003. package/src/prompts/system/eager-task.md +7 -0
  1004. package/src/prompts/system/eager-todo.md +18 -0
  1005. package/src/prompts/system/empty-stop-retry.md +4 -0
  1006. package/src/prompts/system/gemini-tool-call-reminder.md +9 -0
  1007. package/src/prompts/system/interrupted-thinking.md +7 -0
  1008. package/src/prompts/system/irc-autoreply.md +6 -0
  1009. package/src/prompts/system/irc-incoming.md +9 -0
  1010. package/src/prompts/system/manual-continue.md +7 -0
  1011. package/src/prompts/system/mcp-xdev-guidance.md +11 -0
  1012. package/src/prompts/system/memory-consolidation-system.md +8 -0
  1013. package/src/prompts/system/memory-extraction-system.md +26 -0
  1014. package/src/prompts/system/mid-run-todo-nudge.md +3 -0
  1015. package/src/prompts/system/omfg-user.md +50 -0
  1016. package/src/prompts/system/orchestrate-notice.md +40 -0
  1017. package/src/prompts/system/personalities/default.md +18 -0
  1018. package/src/prompts/system/personalities/friendly.md +17 -0
  1019. package/src/prompts/system/personalities/pragmatic.md +15 -0
  1020. package/src/prompts/system/plan-mode-active.md +125 -0
  1021. package/src/prompts/system/plan-mode-approved.md +22 -0
  1022. package/src/prompts/system/plan-mode-compact-instructions.md +17 -0
  1023. package/src/prompts/system/plan-mode-reference.md +10 -0
  1024. package/src/prompts/system/plan-mode-subagent.md +33 -0
  1025. package/src/prompts/system/plan-mode-tool-decision-reminder.md +9 -0
  1026. package/src/prompts/system/plan-yolo-handoff.md +5 -0
  1027. package/src/prompts/system/prewalk-checklist.md +7 -0
  1028. package/src/prompts/system/prewalk-continue.md +1 -0
  1029. package/src/prompts/system/prewalk-plan.md +13 -0
  1030. package/src/prompts/system/project-prompt.md +61 -0
  1031. package/src/prompts/system/recap-user.md +9 -0
  1032. package/src/prompts/system/resolve-device-reminder.md +3 -0
  1033. package/src/prompts/system/rewind-report.md +6 -0
  1034. package/src/prompts/system/side-channel-no-tools.md +3 -0
  1035. package/src/prompts/system/snapcompact-context-frames-note.md +1 -0
  1036. package/src/prompts/system/snapcompact-context-stub.md +1 -0
  1037. package/src/prompts/system/snapcompact-system-frames-note.md +1 -0
  1038. package/src/prompts/system/snapcompact-system-stub.md +1 -0
  1039. package/src/prompts/system/snapcompact-toolresult-note.md +1 -0
  1040. package/src/prompts/system/speech-rewrite.md +15 -0
  1041. package/src/prompts/system/subagent-async-pending.md +6 -0
  1042. package/src/prompts/system/subagent-system-prompt.md +73 -0
  1043. package/src/prompts/system/subagent-user-prompt.md +3 -0
  1044. package/src/prompts/system/subagent-yield-reminder.md +23 -0
  1045. package/src/prompts/system/system-prompt.md +263 -0
  1046. package/src/prompts/system/tan-context-switch.md +17 -0
  1047. package/src/prompts/system/task-label.md +23 -0
  1048. package/src/prompts/system/thinking-loop-redirect.md +10 -0
  1049. package/src/prompts/system/title-marker-instruction.md +1 -0
  1050. package/src/prompts/system/title-system.md +16 -0
  1051. package/src/prompts/system/tool-call-loop-redirect.md +8 -0
  1052. package/src/prompts/system/ttsr-interrupt.md +7 -0
  1053. package/src/prompts/system/ttsr-tool-reminder.md +5 -0
  1054. package/src/prompts/system/ultrathink-notice.md +3 -0
  1055. package/src/prompts/system/unexpected-stop-classifier.md +17 -0
  1056. package/src/prompts/system/unexpected-stop-retry.md +4 -0
  1057. package/src/prompts/system/vibe-mode-active.md +26 -0
  1058. package/src/prompts/system/web-search.md +25 -0
  1059. package/src/prompts/system/workflow-notice.md +112 -0
  1060. package/src/prompts/system/xdev-mount-notice.md +20 -0
  1061. package/src/prompts/tools/apply-patch.md +65 -0
  1062. package/src/prompts/tools/ask.md +22 -0
  1063. package/src/prompts/tools/ast-edit.md +11 -0
  1064. package/src/prompts/tools/ast-grep.md +19 -0
  1065. package/src/prompts/tools/async-result.md +8 -0
  1066. package/src/prompts/tools/bash.md +23 -0
  1067. package/src/prompts/tools/browser.md +29 -0
  1068. package/src/prompts/tools/checkpoint.md +15 -0
  1069. package/src/prompts/tools/computer.md +26 -0
  1070. package/src/prompts/tools/debug.md +3 -0
  1071. package/src/prompts/tools/eval.md +45 -0
  1072. package/src/prompts/tools/github.md +22 -0
  1073. package/src/prompts/tools/glob.md +16 -0
  1074. package/src/prompts/tools/goal.md +11 -0
  1075. package/src/prompts/tools/grep.md +13 -0
  1076. package/src/prompts/tools/hub.md +34 -0
  1077. package/src/prompts/tools/image-attachment-describe-system.md +8 -0
  1078. package/src/prompts/tools/image-attachment-describe.md +10 -0
  1079. package/src/prompts/tools/image-gen.md +7 -0
  1080. package/src/prompts/tools/inspect-image-system.md +20 -0
  1081. package/src/prompts/tools/inspect-image.md +22 -0
  1082. package/src/prompts/tools/learn.md +7 -0
  1083. package/src/prompts/tools/lsp-late-diagnostic.md +8 -0
  1084. package/src/prompts/tools/lsp.md +19 -0
  1085. package/src/prompts/tools/manage-skill.md +9 -0
  1086. package/src/prompts/tools/memory-edit.md +12 -0
  1087. package/src/prompts/tools/patch.md +57 -0
  1088. package/src/prompts/tools/read.md +27 -0
  1089. package/src/prompts/tools/recall.md +7 -0
  1090. package/src/prompts/tools/reflect.md +5 -0
  1091. package/src/prompts/tools/replace.md +30 -0
  1092. package/src/prompts/tools/retain.md +6 -0
  1093. package/src/prompts/tools/rewind.md +14 -0
  1094. package/src/prompts/tools/security-publish.md +1 -0
  1095. package/src/prompts/tools/security-scan.md +1 -0
  1096. package/src/prompts/tools/task-async-contract.md +1 -0
  1097. package/src/prompts/tools/task-summary.md +20 -0
  1098. package/src/prompts/tools/task.md +83 -0
  1099. package/src/prompts/tools/todo.md +42 -0
  1100. package/src/prompts/tools/vibe-kill.md +3 -0
  1101. package/src/prompts/tools/vibe-list.md +3 -0
  1102. package/src/prompts/tools/vibe-send.md +9 -0
  1103. package/src/prompts/tools/vibe-spawn.md +10 -0
  1104. package/src/prompts/tools/vibe-turn-result.md +19 -0
  1105. package/src/prompts/tools/vibe-wait.md +8 -0
  1106. package/src/prompts/tools/web-search.md +8 -0
  1107. package/src/prompts/tools/write.md +14 -0
  1108. package/src/registry/agent-lifecycle.ts +505 -0
  1109. package/src/registry/agent-registry.ts +287 -0
  1110. package/src/registry/persisted-agents.ts +423 -0
  1111. package/src/sdk.ts +3820 -0
  1112. package/src/secrets/index.ts +375 -0
  1113. package/src/secrets/obfuscator.ts +2629 -0
  1114. package/src/secrets/regex.ts +21 -0
  1115. package/src/security/auth.ts +98 -0
  1116. package/src/security/cloud.ts +686 -0
  1117. package/src/security/comparison.ts +255 -0
  1118. package/src/security/contracts/ids.ts +111 -0
  1119. package/src/security/contracts/index.ts +4 -0
  1120. package/src/security/contracts/schemas.ts +219 -0
  1121. package/src/security/contracts/types.ts +254 -0
  1122. package/src/security/contracts/validation.ts +69 -0
  1123. package/src/security/coordinator.ts +708 -0
  1124. package/src/security/importers/codex-security.ts +387 -0
  1125. package/src/security/importers/index.ts +2 -0
  1126. package/src/security/importers/sarif.ts +357 -0
  1127. package/src/security/index.ts +13 -0
  1128. package/src/security/preflight.ts +405 -0
  1129. package/src/security/provenance.ts +106 -0
  1130. package/src/security/publication.ts +326 -0
  1131. package/src/security/remediation.ts +93 -0
  1132. package/src/security/resource-output.ts +50 -0
  1133. package/src/security/sarif.ts +78 -0
  1134. package/src/security/store.ts +430 -0
  1135. package/src/session/acp-permission-gate.ts +165 -0
  1136. package/src/session/agent-session-events.ts +67 -0
  1137. package/src/session/agent-session-types.ts +407 -0
  1138. package/src/session/agent-session.ts +9000 -0
  1139. package/src/session/agent-storage.ts +807 -0
  1140. package/src/session/artifacts.ts +154 -0
  1141. package/src/session/async-job-delivery.ts +82 -0
  1142. package/src/session/auth-broker-config.ts +92 -0
  1143. package/src/session/auth-storage.ts +25 -0
  1144. package/src/session/bash-runner.ts +326 -0
  1145. package/src/session/blob-store.ts +295 -0
  1146. package/src/session/checkpoint-entries.ts +81 -0
  1147. package/src/session/claude-session-store.ts +426 -0
  1148. package/src/session/client-bridge.ts +85 -0
  1149. package/src/session/codex-auto-reset.ts +673 -0
  1150. package/src/session/codex-session-store.ts +673 -0
  1151. package/src/session/compact-modes.ts +105 -0
  1152. package/src/session/credential-pin.ts +93 -0
  1153. package/src/session/eval-runner.ts +219 -0
  1154. package/src/session/exit-diagnostics.ts +310 -0
  1155. package/src/session/foreign-session-import.ts +52 -0
  1156. package/src/session/foreign-session-jsonl.ts +29 -0
  1157. package/src/session/foreign-session-store.ts +26 -0
  1158. package/src/session/history-storage.ts +329 -0
  1159. package/src/session/indexed-session-storage.ts +553 -0
  1160. package/src/session/irc-bridge.ts +203 -0
  1161. package/src/session/launch-completion.ts +37 -0
  1162. package/src/session/messages.ts +1304 -0
  1163. package/src/session/model-controls.ts +757 -0
  1164. package/src/session/prewalk.ts +279 -0
  1165. package/src/session/provider-image-budget.ts +86 -0
  1166. package/src/session/queued-messages.ts +99 -0
  1167. package/src/session/redis-session-storage.ts +257 -0
  1168. package/src/session/retry-fallback-chains.ts +455 -0
  1169. package/src/session/role-models.ts +85 -0
  1170. package/src/session/session-advisors.ts +1896 -0
  1171. package/src/session/session-context.ts +584 -0
  1172. package/src/session/session-dump-format.ts +216 -0
  1173. package/src/session/session-entries.ts +306 -0
  1174. package/src/session/session-handoff.ts +325 -0
  1175. package/src/session/session-history-format.ts +459 -0
  1176. package/src/session/session-listing.ts +715 -0
  1177. package/src/session/session-loader.ts +362 -0
  1178. package/src/session/session-maintenance.ts +3115 -0
  1179. package/src/session/session-manager.ts +2747 -0
  1180. package/src/session/session-memory.ts +222 -0
  1181. package/src/session/session-metadata.ts +53 -0
  1182. package/src/session/session-migrations.ts +78 -0
  1183. package/src/session/session-paths.ts +280 -0
  1184. package/src/session/session-persistence.ts +293 -0
  1185. package/src/session/session-provider-boundary.ts +306 -0
  1186. package/src/session/session-stats.ts +349 -0
  1187. package/src/session/session-storage.ts +774 -0
  1188. package/src/session/session-title-slot.ts +141 -0
  1189. package/src/session/session-tools.ts +1385 -0
  1190. package/src/session/session-workspace.ts +53 -0
  1191. package/src/session/settings-stream-fn.ts +79 -0
  1192. package/src/session/shake-types.ts +43 -0
  1193. package/src/session/snapcompact-inline.ts +545 -0
  1194. package/src/session/snapcompact-savings-journal.ts +113 -0
  1195. package/src/session/sql-session-storage.ts +374 -0
  1196. package/src/session/stream-guards.ts +417 -0
  1197. package/src/session/streaming-output.ts +1459 -0
  1198. package/src/session/todo-tracker.ts +380 -0
  1199. package/src/session/tool-choice-queue.ts +305 -0
  1200. package/src/session/ttsr-coordinator.ts +496 -0
  1201. package/src/session/turn-persistence.ts +142 -0
  1202. package/src/session/turn-recovery.ts +2005 -0
  1203. package/src/session/unexpected-stop-classifier.ts +141 -0
  1204. package/src/session/yield-queue.ts +288 -0
  1205. package/src/slash-commands/acp-builtins.ts +70 -0
  1206. package/src/slash-commands/available-commands.ts +105 -0
  1207. package/src/slash-commands/builtin-registry.ts +3149 -0
  1208. package/src/slash-commands/helpers/active-oauth-account.ts +80 -0
  1209. package/src/slash-commands/helpers/collab-qrcode.ts +28 -0
  1210. package/src/slash-commands/helpers/context-report.ts +66 -0
  1211. package/src/slash-commands/helpers/format.ts +46 -0
  1212. package/src/slash-commands/helpers/logout.ts +108 -0
  1213. package/src/slash-commands/helpers/marketplace-manager.ts +25 -0
  1214. package/src/slash-commands/helpers/mcp.ts +533 -0
  1215. package/src/slash-commands/helpers/parse.ts +85 -0
  1216. package/src/slash-commands/helpers/reset-usage.ts +68 -0
  1217. package/src/slash-commands/helpers/security.ts +451 -0
  1218. package/src/slash-commands/helpers/session-pin.ts +44 -0
  1219. package/src/slash-commands/helpers/ssh.ts +196 -0
  1220. package/src/slash-commands/helpers/stats-dashboard.ts +86 -0
  1221. package/src/slash-commands/helpers/todo.ts +285 -0
  1222. package/src/slash-commands/helpers/usage-report.ts +198 -0
  1223. package/src/slash-commands/marketplace-install-parser.ts +99 -0
  1224. package/src/slash-commands/types.ts +139 -0
  1225. package/src/ssh/config-writer.ts +183 -0
  1226. package/src/ssh/connection-manager.ts +667 -0
  1227. package/src/ssh/file-transfer.ts +214 -0
  1228. package/src/ssh/sshfs-mount.ts +163 -0
  1229. package/src/ssh/utils.ts +51 -0
  1230. package/src/startup-splash.ts +19 -0
  1231. package/src/stt/asr-client.ts +401 -0
  1232. package/src/stt/asr-protocol.ts +65 -0
  1233. package/src/stt/asr-worker.ts +603 -0
  1234. package/src/stt/downloader.ts +142 -0
  1235. package/src/stt/endpointer.ts +259 -0
  1236. package/src/stt/index.ts +6 -0
  1237. package/src/stt/models.ts +150 -0
  1238. package/src/stt/sherpa-runtime.ts +71 -0
  1239. package/src/stt/stt-controller.ts +320 -0
  1240. package/src/stt/submit-trigger.ts +74 -0
  1241. package/src/subprocess/worker-client.ts +463 -0
  1242. package/src/subprocess/worker-runtime.ts +494 -0
  1243. package/src/system-prompt.ts +921 -0
  1244. package/src/task/agents.ts +170 -0
  1245. package/src/task/commands.ts +132 -0
  1246. package/src/task/discovery.ts +145 -0
  1247. package/src/task/executor.ts +3431 -0
  1248. package/src/task/index.ts +1515 -0
  1249. package/src/task/isolation-ownership.ts +106 -0
  1250. package/src/task/isolation-runner.ts +444 -0
  1251. package/src/task/label.ts +40 -0
  1252. package/src/task/name-generator.ts +1577 -0
  1253. package/src/task/omp-command.ts +26 -0
  1254. package/src/task/output-manager.ts +115 -0
  1255. package/src/task/parallel.ts +221 -0
  1256. package/src/task/persisted-revive.ts +173 -0
  1257. package/src/task/prewalk.ts +6 -0
  1258. package/src/task/prompt-policy.ts +8 -0
  1259. package/src/task/provider-concurrency.ts +100 -0
  1260. package/src/task/read-only-policy.ts +27 -0
  1261. package/src/task/render.ts +1830 -0
  1262. package/src/task/renderer.ts +14 -0
  1263. package/src/task/repair-args.ts +118 -0
  1264. package/src/task/spawn-policy.ts +72 -0
  1265. package/src/task/structured-subagent.ts +676 -0
  1266. package/src/task/subprocess-tool-registry.ts +88 -0
  1267. package/src/task/types.ts +555 -0
  1268. package/src/task/worktree.ts +967 -0
  1269. package/src/task/yield-assembly.ts +198 -0
  1270. package/src/telemetry-export.ts +504 -0
  1271. package/src/thinking.ts +377 -0
  1272. package/src/tiny/device.ts +111 -0
  1273. package/src/tiny/dtype.ts +101 -0
  1274. package/src/tiny/message-preproc.ts +155 -0
  1275. package/src/tiny/models.ts +268 -0
  1276. package/src/tiny/text.ts +290 -0
  1277. package/src/tiny/title-client.ts +460 -0
  1278. package/src/tiny/title-protocol.ts +56 -0
  1279. package/src/tiny/worker.ts +354 -0
  1280. package/src/tools/acp-bridge.ts +125 -0
  1281. package/src/tools/approval.ts +245 -0
  1282. package/src/tools/ask.ts +1459 -0
  1283. package/src/tools/ast-edit.ts +718 -0
  1284. package/src/tools/ast-grep.ts +526 -0
  1285. package/src/tools/auto-generated-guard.ts +335 -0
  1286. package/src/tools/bash-interactive.ts +435 -0
  1287. package/src/tools/bash-interceptor.ts +148 -0
  1288. package/src/tools/bash-pty-selection.ts +14 -0
  1289. package/src/tools/bash-skill-urls.ts +350 -0
  1290. package/src/tools/bash.ts +1826 -0
  1291. package/src/tools/browser/aria/aria-snapshot.bundle.txt +7 -0
  1292. package/src/tools/browser/aria/aria-snapshot.ts +131 -0
  1293. package/src/tools/browser/attach.ts +219 -0
  1294. package/src/tools/browser/cmux/cmux-tab.ts +1531 -0
  1295. package/src/tools/browser/cmux/rpc.ts +200 -0
  1296. package/src/tools/browser/cmux/socket-client.ts +445 -0
  1297. package/src/tools/browser/launch.ts +939 -0
  1298. package/src/tools/browser/readable.ts +112 -0
  1299. package/src/tools/browser/registry.ts +447 -0
  1300. package/src/tools/browser/relay/bridge.ts +945 -0
  1301. package/src/tools/browser/relay/daemon.ts +117 -0
  1302. package/src/tools/browser/relay/extension-assets/background.js.txt +242 -0
  1303. package/src/tools/browser/relay/extension-assets/manifest.json.txt +14 -0
  1304. package/src/tools/browser/relay/extension-assets/options.html.txt +53 -0
  1305. package/src/tools/browser/relay/extension-assets/options.js.txt +23 -0
  1306. package/src/tools/browser/relay/kind.ts +41 -0
  1307. package/src/tools/browser/relay/protocol.ts +54 -0
  1308. package/src/tools/browser/relay/server.ts +141 -0
  1309. package/src/tools/browser/render.ts +229 -0
  1310. package/src/tools/browser/run-output.ts +76 -0
  1311. package/src/tools/browser/shared-daemon.ts +139 -0
  1312. package/src/tools/browser/tab-protocol.ts +123 -0
  1313. package/src/tools/browser/tab-supervisor.ts +1077 -0
  1314. package/src/tools/browser/tab-worker-entry.ts +29 -0
  1315. package/src/tools/browser/tab-worker.ts +1982 -0
  1316. package/src/tools/browser.ts +487 -0
  1317. package/src/tools/builtin-names.ts +67 -0
  1318. package/src/tools/checkpoint.ts +137 -0
  1319. package/src/tools/computer/exposure.ts +14 -0
  1320. package/src/tools/computer/protocol.ts +69 -0
  1321. package/src/tools/computer/supervisor.ts +409 -0
  1322. package/src/tools/computer/worker-entry.ts +39 -0
  1323. package/src/tools/computer/worker.ts +745 -0
  1324. package/src/tools/computer-renderer.ts +147 -0
  1325. package/src/tools/computer.ts +222 -0
  1326. package/src/tools/conflict-detect.ts +815 -0
  1327. package/src/tools/context.ts +49 -0
  1328. package/src/tools/debug.ts +1121 -0
  1329. package/src/tools/default-renderer.ts +154 -0
  1330. package/src/tools/essential-tools.ts +46 -0
  1331. package/src/tools/eval-backends.ts +34 -0
  1332. package/src/tools/eval-format/index.ts +24 -0
  1333. package/src/tools/eval-format/javascript.ts +952 -0
  1334. package/src/tools/eval-format/julia.ts +446 -0
  1335. package/src/tools/eval-format/python.ts +544 -0
  1336. package/src/tools/eval-format/ruby.ts +380 -0
  1337. package/src/tools/eval-render.ts +784 -0
  1338. package/src/tools/eval.ts +774 -0
  1339. package/src/tools/fetch.ts +1889 -0
  1340. package/src/tools/file-recorder.ts +35 -0
  1341. package/src/tools/fs-cache-invalidation.ts +28 -0
  1342. package/src/tools/gh-cache-invalidation.ts +175 -0
  1343. package/src/tools/gh-format.ts +12 -0
  1344. package/src/tools/gh-renderer.ts +484 -0
  1345. package/src/tools/gh.ts +3958 -0
  1346. package/src/tools/github-cache.ts +663 -0
  1347. package/src/tools/glob.ts +691 -0
  1348. package/src/tools/grep.ts +1920 -0
  1349. package/src/tools/grouped-file-output.ts +210 -0
  1350. package/src/tools/hub/index.ts +579 -0
  1351. package/src/tools/hub/jobs.ts +714 -0
  1352. package/src/tools/hub/launch.ts +690 -0
  1353. package/src/tools/hub/messaging.ts +735 -0
  1354. package/src/tools/hub/types.ts +117 -0
  1355. package/src/tools/image-gen.ts +1689 -0
  1356. package/src/tools/image-providers.ts +50 -0
  1357. package/src/tools/index.ts +736 -0
  1358. package/src/tools/inspect-image-renderer.ts +133 -0
  1359. package/src/tools/inspect-image.ts +316 -0
  1360. package/src/tools/json-tree.ts +260 -0
  1361. package/src/tools/jtd-to-json-schema.ts +219 -0
  1362. package/src/tools/jtd-to-typescript.ts +136 -0
  1363. package/src/tools/jtd-utils.ts +102 -0
  1364. package/src/tools/learn.ts +141 -0
  1365. package/src/tools/list-limit.ts +40 -0
  1366. package/src/tools/manage-skill.ts +102 -0
  1367. package/src/tools/match-line-format.ts +20 -0
  1368. package/src/tools/memory-edit.ts +61 -0
  1369. package/src/tools/memory-recall.ts +102 -0
  1370. package/src/tools/memory-reflect.ts +88 -0
  1371. package/src/tools/memory-render.ts +211 -0
  1372. package/src/tools/memory-retain.ts +89 -0
  1373. package/src/tools/output-meta.ts +860 -0
  1374. package/src/tools/output-schema-validator.ts +307 -0
  1375. package/src/tools/path-utils.ts +1489 -0
  1376. package/src/tools/plan-mode-guard.ts +155 -0
  1377. package/src/tools/puppeteer/00_stealth_tampering.txt +44 -0
  1378. package/src/tools/puppeteer/01_stealth_activity.txt +80 -0
  1379. package/src/tools/puppeteer/02_stealth_hairline.txt +57 -0
  1380. package/src/tools/puppeteer/03_stealth_botd.txt +380 -0
  1381. package/src/tools/puppeteer/04_stealth_iframe.txt +174 -0
  1382. package/src/tools/puppeteer/05_stealth_webgl.txt +233 -0
  1383. package/src/tools/puppeteer/06_stealth_screen.txt +260 -0
  1384. package/src/tools/puppeteer/07_stealth_fonts.txt +99 -0
  1385. package/src/tools/puppeteer/08_stealth_audio.txt +63 -0
  1386. package/src/tools/puppeteer/09_stealth_locale.txt +51 -0
  1387. package/src/tools/puppeteer/10_stealth_plugins.txt +212 -0
  1388. package/src/tools/puppeteer/11_stealth_hardware.txt +59 -0
  1389. package/src/tools/puppeteer/12_stealth_codecs.txt +42 -0
  1390. package/src/tools/puppeteer/13_stealth_worker.txt +235 -0
  1391. package/src/tools/read.ts +3762 -0
  1392. package/src/tools/render-utils.ts +926 -0
  1393. package/src/tools/renderers.ts +133 -0
  1394. package/src/tools/report-tool-issue.ts +568 -0
  1395. package/src/tools/resolve.ts +423 -0
  1396. package/src/tools/review.ts +103 -0
  1397. package/src/tools/run-scope.ts +417 -0
  1398. package/src/tools/security-scan.ts +287 -0
  1399. package/src/tools/shell-tokenize.ts +213 -0
  1400. package/src/tools/sqlite-reader.ts +884 -0
  1401. package/src/tools/terminal-output.ts +141 -0
  1402. package/src/tools/todo.ts +1226 -0
  1403. package/src/tools/tool-errors.ts +62 -0
  1404. package/src/tools/tool-result.ts +102 -0
  1405. package/src/tools/tool-timeouts.ts +38 -0
  1406. package/src/tools/tts.ts +266 -0
  1407. package/src/tools/vibe.ts +608 -0
  1408. package/src/tools/write.ts +1646 -0
  1409. package/src/tools/xdev.ts +560 -0
  1410. package/src/tools/yield.ts +486 -0
  1411. package/src/tts/downloader.ts +64 -0
  1412. package/src/tts/index.ts +10 -0
  1413. package/src/tts/models.ts +137 -0
  1414. package/src/tts/runtime.ts +21 -0
  1415. package/src/tts/speakable.ts +392 -0
  1416. package/src/tts/speech-enhancer.ts +206 -0
  1417. package/src/tts/streaming-player.ts +120 -0
  1418. package/src/tts/tts-client.ts +475 -0
  1419. package/src/tts/tts-protocol.ts +69 -0
  1420. package/src/tts/tts-worker.ts +434 -0
  1421. package/src/tts/vocalizer.ts +419 -0
  1422. package/src/tts/wav.ts +58 -0
  1423. package/src/tui/code-cell.ts +268 -0
  1424. package/src/tui/file-list.ts +55 -0
  1425. package/src/tui/hyperlink.ts +178 -0
  1426. package/src/tui/index.ts +13 -0
  1427. package/src/tui/output-block.ts +268 -0
  1428. package/src/tui/status-line.ts +54 -0
  1429. package/src/tui/tree-list.ts +172 -0
  1430. package/src/tui/types.ts +15 -0
  1431. package/src/tui/utils.ts +103 -0
  1432. package/src/tui/width-aware-text.ts +58 -0
  1433. package/src/utils/active-repo-context.ts +143 -0
  1434. package/src/utils/block-context.ts +312 -0
  1435. package/src/utils/changelog.ts +373 -0
  1436. package/src/utils/clipboard.ts +361 -0
  1437. package/src/utils/command-args.ts +74 -0
  1438. package/src/utils/commit-message-generator.ts +148 -0
  1439. package/src/utils/cpuprofile.ts +235 -0
  1440. package/src/utils/edit-mode.ts +61 -0
  1441. package/src/utils/enhanced-paste.ts +230 -0
  1442. package/src/utils/event-bus.ts +33 -0
  1443. package/src/utils/external-editor.ts +80 -0
  1444. package/src/utils/fetch-timeout.ts +10 -0
  1445. package/src/utils/file-display-mode.ts +44 -0
  1446. package/src/utils/file-mentions.ts +293 -0
  1447. package/src/utils/git.ts +2472 -0
  1448. package/src/utils/image-loading.ts +236 -0
  1449. package/src/utils/image-resize.ts +420 -0
  1450. package/src/utils/image-vision-fallback.ts +196 -0
  1451. package/src/utils/inspect-image-mode.ts +39 -0
  1452. package/src/utils/ipc.ts +38 -0
  1453. package/src/utils/jj.ts +422 -0
  1454. package/src/utils/lang-from-path.ts +251 -0
  1455. package/src/utils/late-cleanup.ts +17 -0
  1456. package/src/utils/local-date.ts +7 -0
  1457. package/src/utils/mac-file-urls.applescript +37 -0
  1458. package/src/utils/markit-cache.ts +166 -0
  1459. package/src/utils/markit.ts +223 -0
  1460. package/src/utils/mupdf-wasm-embed.ts +12 -0
  1461. package/src/utils/open.ts +126 -0
  1462. package/src/utils/profile-tree.ts +111 -0
  1463. package/src/utils/prompt-path.ts +3 -0
  1464. package/src/utils/qrcode.ts +535 -0
  1465. package/src/utils/sample-profile.ts +437 -0
  1466. package/src/utils/session-color.ts +142 -0
  1467. package/src/utils/shell-snapshot-fn-env.sh +63 -0
  1468. package/src/utils/shell-snapshot.ts +326 -0
  1469. package/src/utils/sixel.ts +69 -0
  1470. package/src/utils/thinking-display.ts +163 -0
  1471. package/src/utils/title-generator.ts +597 -0
  1472. package/src/utils/token-rate.ts +72 -0
  1473. package/src/utils/tool-choice.ts +50 -0
  1474. package/src/utils/tools-manager.ts +411 -0
  1475. package/src/utils/turndown.ts +82 -0
  1476. package/src/utils/zip.ts +1106 -0
  1477. package/src/vibe/runtime.ts +1684 -0
  1478. package/src/vibe/state.ts +4 -0
  1479. package/src/web/kagi.ts +305 -0
  1480. package/src/web/parallel.ts +354 -0
  1481. package/src/web/scrapers/artifacthub.ts +207 -0
  1482. package/src/web/scrapers/arxiv.ts +83 -0
  1483. package/src/web/scrapers/aur.ts +162 -0
  1484. package/src/web/scrapers/biorxiv.ts +133 -0
  1485. package/src/web/scrapers/bluesky.ts +262 -0
  1486. package/src/web/scrapers/brew.ts +172 -0
  1487. package/src/web/scrapers/cheatsh.ts +68 -0
  1488. package/src/web/scrapers/chocolatey.ts +196 -0
  1489. package/src/web/scrapers/choosealicense.ts +95 -0
  1490. package/src/web/scrapers/cisa-kev.ts +87 -0
  1491. package/src/web/scrapers/clojars.ts +154 -0
  1492. package/src/web/scrapers/coingecko.ts +177 -0
  1493. package/src/web/scrapers/crates-io.ts +97 -0
  1494. package/src/web/scrapers/crossref.ts +136 -0
  1495. package/src/web/scrapers/devto.ts +147 -0
  1496. package/src/web/scrapers/discogs.ts +306 -0
  1497. package/src/web/scrapers/discourse.ts +197 -0
  1498. package/src/web/scrapers/dockerhub.ts +138 -0
  1499. package/src/web/scrapers/docs-rs.ts +663 -0
  1500. package/src/web/scrapers/fdroid.ts +134 -0
  1501. package/src/web/scrapers/firefox-addons.ts +191 -0
  1502. package/src/web/scrapers/flathub.ts +223 -0
  1503. package/src/web/scrapers/github-gist.ts +58 -0
  1504. package/src/web/scrapers/github.ts +800 -0
  1505. package/src/web/scrapers/gitlab.ts +401 -0
  1506. package/src/web/scrapers/go-pkg.ts +266 -0
  1507. package/src/web/scrapers/hackage.ts +129 -0
  1508. package/src/web/scrapers/hackernews.ts +189 -0
  1509. package/src/web/scrapers/hex.ts +105 -0
  1510. package/src/web/scrapers/huggingface.ts +321 -0
  1511. package/src/web/scrapers/iacr.ts +89 -0
  1512. package/src/web/scrapers/index.ts +252 -0
  1513. package/src/web/scrapers/jetbrains-marketplace.ts +159 -0
  1514. package/src/web/scrapers/lemmy.ts +203 -0
  1515. package/src/web/scrapers/lobsters.ts +175 -0
  1516. package/src/web/scrapers/mastodon.ts +292 -0
  1517. package/src/web/scrapers/maven.ts +138 -0
  1518. package/src/web/scrapers/mdn.ts +173 -0
  1519. package/src/web/scrapers/metacpan.ts +222 -0
  1520. package/src/web/scrapers/musicbrainz.ts +250 -0
  1521. package/src/web/scrapers/npm.ts +98 -0
  1522. package/src/web/scrapers/nuget.ts +183 -0
  1523. package/src/web/scrapers/nvd.ts +222 -0
  1524. package/src/web/scrapers/ollama.ts +239 -0
  1525. package/src/web/scrapers/open-vsx.ts +106 -0
  1526. package/src/web/scrapers/opencorporates.ts +292 -0
  1527. package/src/web/scrapers/openlibrary.ts +336 -0
  1528. package/src/web/scrapers/orcid.ts +286 -0
  1529. package/src/web/scrapers/osv.ts +176 -0
  1530. package/src/web/scrapers/packagist.ts +160 -0
  1531. package/src/web/scrapers/pub-dev.ts +143 -0
  1532. package/src/web/scrapers/pubmed.ts +211 -0
  1533. package/src/web/scrapers/pypi.ts +112 -0
  1534. package/src/web/scrapers/rawg.ts +110 -0
  1535. package/src/web/scrapers/readthedocs.ts +121 -0
  1536. package/src/web/scrapers/reddit.ts +95 -0
  1537. package/src/web/scrapers/repology.ts +251 -0
  1538. package/src/web/scrapers/rfc.ts +201 -0
  1539. package/src/web/scrapers/rubygems.ts +103 -0
  1540. package/src/web/scrapers/searchcode.ts +189 -0
  1541. package/src/web/scrapers/sec-edgar.ts +261 -0
  1542. package/src/web/scrapers/semantic-scholar.ts +171 -0
  1543. package/src/web/scrapers/snapcraft.ts +187 -0
  1544. package/src/web/scrapers/sourcegraph.ts +336 -0
  1545. package/src/web/scrapers/spdx.ts +108 -0
  1546. package/src/web/scrapers/spotify.ts +198 -0
  1547. package/src/web/scrapers/stackoverflow.ts +120 -0
  1548. package/src/web/scrapers/terraform.ts +277 -0
  1549. package/src/web/scrapers/tldr.ts +47 -0
  1550. package/src/web/scrapers/twitter.ts +94 -0
  1551. package/src/web/scrapers/types.ts +354 -0
  1552. package/src/web/scrapers/utils.ts +109 -0
  1553. package/src/web/scrapers/vimeo.ts +133 -0
  1554. package/src/web/scrapers/vscode-marketplace.ts +187 -0
  1555. package/src/web/scrapers/w3c.ts +156 -0
  1556. package/src/web/scrapers/wikidata.ts +344 -0
  1557. package/src/web/scrapers/wikipedia.ts +84 -0
  1558. package/src/web/scrapers/youtube.ts +325 -0
  1559. package/src/web/search/index.ts +393 -0
  1560. package/src/web/search/provider.ts +272 -0
  1561. package/src/web/search/providers/anthropic.ts +406 -0
  1562. package/src/web/search/providers/base.ts +112 -0
  1563. package/src/web/search/providers/brave.ts +181 -0
  1564. package/src/web/search/providers/browser-headers.ts +82 -0
  1565. package/src/web/search/providers/browser-page.ts +125 -0
  1566. package/src/web/search/providers/codex.ts +788 -0
  1567. package/src/web/search/providers/duckduckgo.ts +382 -0
  1568. package/src/web/search/providers/ecosia.ts +183 -0
  1569. package/src/web/search/providers/exa.ts +513 -0
  1570. package/src/web/search/providers/firecrawl.ts +213 -0
  1571. package/src/web/search/providers/gemini.ts +634 -0
  1572. package/src/web/search/providers/google.ts +195 -0
  1573. package/src/web/search/providers/jina.ts +144 -0
  1574. package/src/web/search/providers/kagi.ts +98 -0
  1575. package/src/web/search/providers/kimi.ts +221 -0
  1576. package/src/web/search/providers/mojeek.ts +220 -0
  1577. package/src/web/search/providers/parallel.ts +186 -0
  1578. package/src/web/search/providers/perplexity-auth.ts +142 -0
  1579. package/src/web/search/providers/perplexity.ts +997 -0
  1580. package/src/web/search/providers/public.ts +199 -0
  1581. package/src/web/search/providers/searxng.ts +467 -0
  1582. package/src/web/search/providers/startpage.ts +225 -0
  1583. package/src/web/search/providers/synthetic.ts +126 -0
  1584. package/src/web/search/providers/tavily.ts +244 -0
  1585. package/src/web/search/providers/tinyfish.ts +166 -0
  1586. package/src/web/search/providers/utils.ts +130 -0
  1587. package/src/web/search/providers/xai.ts +372 -0
  1588. package/src/web/search/providers/zai.ts +452 -0
  1589. package/src/web/search/query.ts +850 -0
  1590. package/src/web/search/render.ts +262 -0
  1591. package/src/web/search/types.ts +518 -0
  1592. package/src/web/search/utils.ts +17 -0
  1593. package/src/workspace-tree.ts +326 -0
@@ -0,0 +1,1489 @@
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 { glob } from "@oh-my-pi/pi-natives";
6
+ import { hasFsCode, isEnoent, isEnotdir, stripWindowsExtendedLengthPathPrefix, untilAborted } from "@oh-my-pi/pi-utils";
7
+ import type { Skill } from "../extensibility/skills";
8
+ import { InternalUrlRouter, type LocalProtocolOptions } from "../internal-urls";
9
+ import { ToolAbortError, ToolError } from "./tool-errors";
10
+
11
+ const UNICODE_SPACES = /[\u00A0\u2000-\u200A\u202F\u205F\u3000]/g;
12
+ // A single line-range chunk: `N`, `N-M`, `N+K`, or open-ended `N-`. `..` is
13
+ // accepted everywhere `-` is, as a forgiving alias for Rust/Python-style ranges
14
+ // (e.g. `2724..2727` == `2724-2727`, `2724..` == `2724-`); it is normalized to
15
+ // `-` in parseLineRangeChunk. Keep this fragment and LINE_RANGE_CHUNK_RE in sync.
16
+ const RANGE_CHUNK_SRC = String.raw`L?\d+(?:(?:[-+]|\.\.)L?\d+|-|\.\.)?`;
17
+ const RANGE_LIST_SRC = `${RANGE_CHUNK_SRC}(?:,${RANGE_CHUNK_SRC})*`;
18
+ const FILE_LINE_RANGE_RE = new RegExp(`^(?:${RANGE_LIST_SRC}|raw|conflicts)$`, "i");
19
+ const FILE_LINE_RANGE_ONLY_RE = new RegExp(`^${RANGE_LIST_SRC}$`, "i");
20
+ const FILE_RAW_ONLY_RE = /^raw$/i;
21
+ // Permissive selector chunk for internal URLs — accepts well-formed selectors
22
+ // plus common malformed shapes (e.g. `:-N`) so the read tool peels the entire
23
+ // selector chain off before dispatching to a protocol handler.
24
+ const INTERNAL_URL_SELECTOR_PART_RE = new RegExp(
25
+ String.raw`^(?:raw|conflicts|${RANGE_LIST_SRC}|-\d+(?:[-+]\d+)?)$`,
26
+ "i",
27
+ );
28
+ // Schemes whose host grammar is identifier-shaped, so any trailing
29
+ // `:<selector-chunk>` is unambiguously a read-tool selector. `mcp://` is
30
+ // excluded because mcp resource URIs may legitimately contain colons. `ssh://`
31
+ // is included despite an optional `:port`; `splitInternalUrlSel` skips the peel
32
+ // for an `ssh://host:port` that has no `/path`, so the port colon is never
33
+ // mistaken for a selector (a real ssh selector trails the `/path`, e.g.
34
+ // `ssh://h/f:1-5`).
35
+ const INTERNAL_SCHEMES_WITH_SELECTORS: Record<string, true> = {
36
+ agent: true,
37
+ artifact: true,
38
+ issue: true,
39
+ history: true,
40
+ local: true,
41
+ memory: true,
42
+ omp: true,
43
+ pr: true,
44
+ rule: true,
45
+ security: true,
46
+ skill: true,
47
+ ssh: true,
48
+ vault: true,
49
+ };
50
+ // Schemes whose resource URIs are server-defined and may legitimately end
51
+ // with selector-shaped tails (e.g. `:raw`, `:conflicts`, `:1-50`, `/:raw`).
52
+ // `McpProtocolHandler` resolves by exact URI match (`r.uri === uri`), so
53
+ // peeling syntactically can make valid resources unreachable. Keep these
54
+ // schemes opaque; selector support for them needs a resolver-aware path that
55
+ // tries the exact URI before interpreting any suffix as a read selector.
56
+ const OPAQUE_RESOURCE_SCHEMES: ReadonlySet<string> = new Set(["mcp"]);
57
+ const INTERNAL_URL_SCHEME_RE = /^([a-z][a-z0-9+.-]*):\/\//i;
58
+ const NARROW_NO_BREAK_SPACE = "\u202F";
59
+ const TOP_LEVEL_INTERNAL_URL_PREFIXES = [
60
+ "agent://",
61
+ "artifact://",
62
+ "skill://",
63
+ "rule://",
64
+ "security://",
65
+ "local://",
66
+ "mcp://",
67
+ "ssh://",
68
+ "vault://",
69
+ ] as const;
70
+
71
+ function normalizeUnicodeSpaces(str: string): string {
72
+ return str.replace(UNICODE_SPACES, " ");
73
+ }
74
+
75
+ function tryMacOSScreenshotPath(filePath: string): string {
76
+ return filePath.replace(/ (AM|PM)\./g, `${NARROW_NO_BREAK_SPACE}$1.`);
77
+ }
78
+
79
+ function tryNFDVariant(filePath: string): string {
80
+ // macOS stores filenames in NFD (decomposed) form, try converting user input to NFD
81
+ return filePath.normalize("NFD");
82
+ }
83
+
84
+ function tryCurlyQuoteVariant(filePath: string): string {
85
+ // macOS uses U+2019 (right single quotation mark) in screenshot names like "Capture d'écran"
86
+ // Users typically type U+0027 (straight apostrophe)
87
+ return filePath.replace(/'/g, "\u2019");
88
+ }
89
+
90
+ function tryShellEscapedPath(filePath: string): string {
91
+ if (!filePath.includes("\\") || !filePath.includes("/")) return filePath;
92
+ return filePath.replace(/\\([ \t"'(){}[\]])/g, "$1");
93
+ }
94
+
95
+ function fileExists(filePath: string): boolean {
96
+ try {
97
+ fs.accessSync(filePath, fs.constants.F_OK);
98
+ return true;
99
+ } catch {
100
+ return false;
101
+ }
102
+ }
103
+
104
+ function normalizeAtPrefix(filePath: string): string {
105
+ if (!filePath.startsWith("@")) return filePath;
106
+
107
+ const withoutAt = filePath.slice(1);
108
+
109
+ // We only treat a leading "@" as a shorthand for a small set of well-known
110
+ // syntaxes. This avoids mangling literal paths like "@my-file.txt".
111
+ if (
112
+ withoutAt.startsWith("/") ||
113
+ withoutAt === "~" ||
114
+ withoutAt.startsWith("~/") ||
115
+ // Windows absolute paths (drive letters / UNC / root-relative)
116
+ path.win32.isAbsolute(withoutAt) ||
117
+ // Internal URL shorthands
118
+ withoutAt.startsWith("agent://") ||
119
+ withoutAt.startsWith("artifact://") ||
120
+ withoutAt.startsWith("skill://") ||
121
+ withoutAt.startsWith("rule://") ||
122
+ withoutAt.startsWith("security://") ||
123
+ withoutAt.startsWith("local:") ||
124
+ withoutAt.startsWith("mcp://")
125
+ ) {
126
+ return withoutAt;
127
+ }
128
+
129
+ return filePath;
130
+ }
131
+
132
+ function stripFileUrl(filePath: string): string {
133
+ if (!filePath.toLowerCase().startsWith("file://")) return filePath;
134
+
135
+ try {
136
+ return url.fileURLToPath(filePath);
137
+ } catch {
138
+ return filePath;
139
+ }
140
+ }
141
+
142
+ export function expandTilde(filePath: string, home?: string): string {
143
+ const h = home ?? os.homedir();
144
+ if (filePath === "~") return h;
145
+ if (filePath.startsWith("~/") || filePath.startsWith("~\\")) {
146
+ return h + filePath.slice(1);
147
+ }
148
+ if (filePath.startsWith("~")) {
149
+ return path.join(h, filePath.slice(1));
150
+ }
151
+ return filePath;
152
+ }
153
+
154
+ export function expandPath(filePath: string): string {
155
+ // Some models intermittently prefix an otherwise-valid path with a stray
156
+ // `:` (e.g. `:/abs/path`, `:../rel`, or the Windows forms `:C:\repo\file`
157
+ // and `:.\src`). No real path starts with `:` and it never begins a
158
+ // selector against an absolute/relative path, so strip it before
159
+ // resolution — mirroring the `@`-prefix normalization above and the
160
+ // implicit stripping `write` already tolerates (issues #5508, #5624). The
161
+ // lookahead admits POSIX (`/`, `~`, `./`, `../`) and Windows (`\`, `.\`,
162
+ // `..\`, drive-letter `C:`) path shapes.
163
+ const deColoned = /^:(?=[/\\~]|\.\.?[/\\]|[A-Za-z]:)/.test(filePath) ? filePath.slice(1) : filePath;
164
+ const normalized = stripWindowsExtendedLengthPathPrefix(
165
+ stripFileUrl(normalizeUnicodeSpaces(normalizeAtPrefix(deColoned))),
166
+ );
167
+ return expandTilde(normalized);
168
+ }
169
+
170
+ function isAsciiDriveLetter(value: string): boolean {
171
+ if (value.length !== 1) return false;
172
+ const code = value.charCodeAt(0);
173
+ return (code >= 65 && code <= 90) || (code >= 97 && code <= 122);
174
+ }
175
+
176
+ function windowsDriveAliasPath(filePath: string): string | undefined {
177
+ if (!filePath.startsWith("/")) return undefined;
178
+ const parts = filePath.split("/");
179
+ if (parts[0] !== "") return undefined;
180
+
181
+ let drive: string | undefined;
182
+ let tailStart = 2;
183
+ if (parts.length >= 2 && isAsciiDriveLetter(parts[1] ?? "")) {
184
+ drive = parts[1]!.toUpperCase();
185
+ } else if (parts.length >= 3 && (parts[1] ?? "").toLowerCase() === "mnt" && isAsciiDriveLetter(parts[2] ?? "")) {
186
+ drive = parts[2]!.toUpperCase();
187
+ tailStart = 3;
188
+ }
189
+ if (!drive) return undefined;
190
+
191
+ const tail = parts.slice(tailStart).filter(Boolean).join("\\");
192
+ return tail ? `${drive}:\\${tail}` : `${drive}:\\`;
193
+ }
194
+
195
+ export function normalizeWindowsDriveAliasPath(filePath: string, platform: NodeJS.Platform = process.platform): string {
196
+ if (platform !== "win32") return filePath;
197
+ return windowsDriveAliasPath(filePath) ?? filePath;
198
+ }
199
+
200
+ /**
201
+ * Inclusive line range describing one selector segment (e.g. `50-100`,
202
+ * `301-`, or `50+10`). `endLine` is `undefined` for open-ended ranges.
203
+ */
204
+ export interface LineRange {
205
+ startLine: number;
206
+ endLine: number | undefined;
207
+ }
208
+
209
+ const LINE_RANGE_CHUNK_RE = /^L?(\d+)(?:(\.\.|[-+])L?(\d+)?)?$/i;
210
+
211
+ /** Parse a single `N`, `N-M`, `N-`, `N+K`, or `..`-aliased (`N..M`, `N..`) chunk. Throws via {@link ToolError} on invalid bounds. */
212
+ export function parseLineRangeChunk(sel: string): LineRange | null {
213
+ const lineMatch = LINE_RANGE_CHUNK_RE.exec(sel);
214
+ if (!lineMatch) return null;
215
+ const rawStart = Number.parseInt(lineMatch[1]!, 10);
216
+ if (rawStart < 1) {
217
+ throw new ToolError("Line selector 0 is invalid; lines are 1-indexed. Use :1.");
218
+ }
219
+ // `..` is a forgiving alias for `-` (e.g. `2724..2727` == `2724-2727`).
220
+ const sep = lineMatch[2] === ".." ? "-" : lineMatch[2];
221
+ const rhs = lineMatch[3] ? Number.parseInt(lineMatch[3], 10) : undefined;
222
+ let rawEnd: number | undefined;
223
+ if (sep === "+") {
224
+ if (rhs === undefined || rhs < 1) {
225
+ throw new ToolError(`Invalid range ${rawStart}+${rhs ?? 0}: count must be >= 1.`);
226
+ }
227
+ rawEnd = rawStart + rhs - 1;
228
+ } else if (sep === "-") {
229
+ // `301-` is shorthand for "from 301 onward" — equivalent to bare `301`.
230
+ if (rhs !== undefined) {
231
+ if (rhs < rawStart) {
232
+ throw new ToolError(`Invalid range ${rawStart}-${rhs}: end must be >= start.`);
233
+ }
234
+ rawEnd = rhs;
235
+ }
236
+ }
237
+ return { startLine: rawStart, endLine: rawEnd };
238
+ }
239
+
240
+ /**
241
+ * Parse a comma-separated list of line ranges (e.g. `5-16,960-973`). Returns
242
+ * the ranges in ascending order with overlapping/adjacent ranges merged so
243
+ * downstream consumers can stream the file in a single forward pass per range.
244
+ */
245
+ export function parseLineRanges(sel: string): [LineRange, ...LineRange[]] | null {
246
+ const chunks = sel.split(",");
247
+ const parsed: LineRange[] = [];
248
+ for (const chunk of chunks) {
249
+ const range = parseLineRangeChunk(chunk);
250
+ if (!range) return null;
251
+ parsed.push(range);
252
+ }
253
+ if (parsed.length === 0) return null;
254
+ parsed.sort((a, b) => a.startLine - b.startLine);
255
+
256
+ const merged: LineRange[] = [parsed[0]];
257
+ for (let i = 1; i < parsed.length; i++) {
258
+ const current = parsed[i];
259
+ const last = merged[merged.length - 1];
260
+ // Open-ended (endLine undefined) means "to EOF" — any later range is absorbed.
261
+ if (last.endLine === undefined) continue;
262
+ // Merge when current starts within (or immediately after) the last range.
263
+ if (current.startLine <= last.endLine + 1) {
264
+ if (current.endLine === undefined || current.endLine > last.endLine) {
265
+ merged[merged.length - 1] = { startLine: last.startLine, endLine: current.endLine };
266
+ }
267
+ continue;
268
+ }
269
+ merged.push(current);
270
+ }
271
+ return merged as [LineRange, ...LineRange[]];
272
+ }
273
+
274
+ /**
275
+ * Extract the line-range component from a read-tool selector that may also
276
+ * carry a verbatim/index display mode (`raw`, `conflicts`) — alone or compounded
277
+ * with a range (`raw:50-100`, `50-100:raw`). Returns the parsed ranges when the
278
+ * selector names any, otherwise `undefined` (pure `raw`/`conflicts`/none).
279
+ *
280
+ * Used by content search, which honors line ranges as a match filter but has no
281
+ * use for verbatim/conflict display modes — so those selectors are accepted and
282
+ * treated as an unfiltered, whole-resource search rather than rejected.
283
+ */
284
+ export function selectorLineRanges(sel: string | undefined): [LineRange, ...LineRange[]] | undefined {
285
+ if (!sel) return undefined;
286
+ for (const chunk of sel.split(":")) {
287
+ const lower = chunk.toLowerCase();
288
+ if (lower === "raw" || lower === "conflicts") continue;
289
+ const ranges = parseLineRanges(chunk);
290
+ if (ranges) return ranges;
291
+ }
292
+ return undefined;
293
+ }
294
+
295
+ /** Return `true` when `lineNumber` (1-indexed) falls in any of the supplied ranges. */
296
+ export function isLineInRanges(lineNumber: number, ranges: readonly LineRange[]): boolean {
297
+ for (const range of ranges) {
298
+ if (lineNumber < range.startLine) continue;
299
+ if (range.endLine === undefined || lineNumber <= range.endLine) return true;
300
+ }
301
+ return false;
302
+ }
303
+
304
+ export function splitPathAndSel(rawPath: string): { path: string; sel?: string } {
305
+ const colon = rawPath.lastIndexOf(":");
306
+ if (colon <= 0) return { path: rawPath };
307
+
308
+ const candidate = rawPath.slice(colon + 1);
309
+ if (!FILE_LINE_RANGE_RE.test(candidate)) return { path: rawPath };
310
+
311
+ let basePath = rawPath.slice(0, colon);
312
+ let sel = candidate;
313
+
314
+ // Allow a compound trailing selector: `path:1-50:raw` or `path:raw:1-50`.
315
+ // The two chunks must be one line-range plus one `raw`, in either order.
316
+ const innerColon = basePath.lastIndexOf(":");
317
+ if (innerColon > 0) {
318
+ const innerCandidate = basePath.slice(innerColon + 1);
319
+ const innerIsRaw = FILE_RAW_ONLY_RE.test(innerCandidate);
320
+ const outerIsRaw = FILE_RAW_ONLY_RE.test(candidate);
321
+ const innerIsRange = FILE_LINE_RANGE_ONLY_RE.test(innerCandidate);
322
+ const outerIsRange = FILE_LINE_RANGE_ONLY_RE.test(candidate);
323
+ if ((innerIsRaw && outerIsRange) || (innerIsRange && outerIsRaw)) {
324
+ sel = `${innerCandidate}:${candidate}`;
325
+ basePath = basePath.slice(0, innerColon);
326
+ }
327
+ }
328
+
329
+ return { path: basePath, sel };
330
+ }
331
+
332
+ /**
333
+ * Three-way probe for whether the exact filesystem entry named by `filePath`
334
+ * exists. `stat` (used earlier) failed for reasons other than "no such file"
335
+ * (dangling symlink, `EACCES` on a parent, transient I/O), and each of those
336
+ * silently reinterpreted a real literal path such as `test:1-2` as `test`
337
+ * plus selector `1-2` (issue #4618). `lstat` inspects the entry itself, so a
338
+ * dangling symlink is still detected as present; ambiguous errors resolve to
339
+ * `"unknown"` so callers keep the raw path instead of guessing.
340
+ *
341
+ * `ENAMETOOLONG` resolves to `"missing"` rather than `"unknown"`: a path whose
342
+ * component or whole length exceeds the OS limit can never name a real single
343
+ * entry, so it is strictly stronger evidence of non-existence than `ENOENT`.
344
+ * Without this, a semicolon-joined `path` list long enough to trip the limit
345
+ * (bare filenames past `NAME_MAX`, or a total past `PATH_MAX`) was read as one
346
+ * literal path and the delimited split was suppressed (issue #7597).
347
+ */
348
+ export async function probeLiteralPathExists(filePath: string, cwd: string): Promise<"exists" | "missing" | "unknown"> {
349
+ const resolved = resolveReadPath(filePath, cwd);
350
+ try {
351
+ await fs.promises.lstat(resolved);
352
+ return "exists";
353
+ } catch (err) {
354
+ if (isEnoent(err) || isEnotdir(err) || hasFsCode(err, "ENAMETOOLONG")) return "missing";
355
+ return "unknown";
356
+ }
357
+ }
358
+
359
+ /**
360
+ * Async sibling of {@link splitPathAndSel} that prefers a literal filesystem
361
+ * path over selector interpretation. Filenames whose tail matches the selector
362
+ * grammar (e.g. `test:1-2`, `log:raw`) are legal on POSIX; without this the
363
+ * strict splitter peels the tail and both `read` and `grep` refuse to open the
364
+ * real file (issue #4618). The literal wins on a confirmed `lstat`, and also
365
+ * on `"unknown"` (`EACCES` on a parent, transient I/O), so an unreachable
366
+ * literal is never silently reinterpreted as `path + selector`. Only a
367
+ * definitive `ENOENT`/`ENOTDIR` falls back to the strict split.
368
+ */
369
+ export async function splitPathAndSelPreferringLiteral(
370
+ rawPath: string,
371
+ cwd: string,
372
+ ): Promise<{ path: string; sel?: string }> {
373
+ const strict = splitPathAndSel(rawPath);
374
+ if (strict.sel === undefined) return strict;
375
+ const probe = await probeLiteralPathExists(rawPath, cwd);
376
+ return probe === "missing" ? strict : { path: rawPath };
377
+ }
378
+
379
+ /**
380
+ * Variant of {@link splitPathAndSel} for internal URLs (`scheme://...`).
381
+ *
382
+ * The filesystem-path splitter is intentionally conservative: it refuses to
383
+ * peel a trailing `:<chunk>` unless that chunk matches the strict selector
384
+ * grammar. That rule is right for filesystem paths (a file named `a:1-50` is
385
+ * legal) but wrong for internal URLs, where any trailing `:<chunk>` after the
386
+ * scheme is unambiguously a read-tool selector — even if malformed (e.g.
387
+ * `artifact://3:raw:-100`).
388
+ *
389
+ * This function iteratively peels selector-shaped chunks (well-formed plus
390
+ * common malformed shapes like `:-N`) so the rest of the read tool can pass a
391
+ * clean URL to the protocol handler and surface selector errors via parseSel
392
+ * instead of as misleading "host invalid" errors from the handler. Schemes
393
+ * whose resource URIs may legitimately contain colons (`mcp://`) are skipped.
394
+ *
395
+ * Falls back to the input unchanged when nothing matches.
396
+ */
397
+
398
+ export function splitInternalUrlSel(rawPath: string): { path: string; sel?: string } {
399
+ const schemeMatch = rawPath.match(INTERNAL_URL_SCHEME_RE);
400
+ if (!schemeMatch) return { path: rawPath };
401
+ const scheme = schemeMatch[1].toLowerCase();
402
+ // Opaque schemes (mcp://, etc.) carry server-defined resource URIs that may
403
+ // legitimately end in selector-shaped tails. Forward verbatim — see
404
+ // OPAQUE_RESOURCE_SCHEMES.
405
+ if (OPAQUE_RESOURCE_SCHEMES.has(scheme)) return { path: rawPath };
406
+ if (!INTERNAL_SCHEMES_WITH_SELECTORS[scheme]) return { path: rawPath };
407
+
408
+ const schemeEnd = schemeMatch[0].length;
409
+ // ssh:// authority carries an optional `:port`; with no `/path` after the
410
+ // authority, a trailing `:NNNN` is the port, not a read selector
411
+ // (e.g. ssh://host:2222). Other schemes' authority-trailing selectors
412
+ // (artifact://5:1-50) still peel, so this guard is ssh-specific.
413
+ if (scheme === "ssh" && rawPath.indexOf("/", schemeEnd) === -1) {
414
+ return { path: rawPath };
415
+ }
416
+ let path = rawPath;
417
+ const chunks: string[] = [];
418
+ while (true) {
419
+ const colon = path.lastIndexOf(":");
420
+ // Stop before crossing into the scheme separator `://`.
421
+ if (colon < schemeEnd) break;
422
+ const tail = path.slice(colon + 1);
423
+ if (!INTERNAL_URL_SELECTOR_PART_RE.test(tail)) break;
424
+ chunks.unshift(tail);
425
+ path = path.slice(0, colon);
426
+ }
427
+ if (chunks.length === 0) return { path: rawPath };
428
+ return { path, sel: chunks.join(":") };
429
+ }
430
+
431
+ /**
432
+ * Peel a read-tool selector off an internal-URL write target so `write` resolves
433
+ * the same file `read` does (e.g. `ssh://h/f:raw` -> `ssh://h/f`). Only the
434
+ * whole-file display modes `raw`/`conflicts` are accepted (they do not change
435
+ * which bytes are written); any other selector-shaped tail `splitInternalUrlSel`
436
+ * peels — a line range, a compound like `raw:1-20`, or a malformed `:-N` — throws,
437
+ * because `write` addresses a whole file, not a partial range, and silently
438
+ * stripping it would write to a path the caller never named. Non-URL paths and
439
+ * URLs without a selector pass through unchanged.
440
+ */
441
+ export function peelWriteUrlSelector(rawPath: string): string {
442
+ const { path, sel } = splitInternalUrlSel(rawPath);
443
+ if (sel === undefined) return rawPath;
444
+ // Case-insensitive to match read's selector grammar (parseSel + the /i regexes above).
445
+ if (/^(?:raw|conflicts)$/i.test(sel)) return path;
446
+ throw new ToolError(
447
+ `write does not accept the trailing selector ":${sel}" — it writes a whole file. ` +
448
+ `Remove ":${sel}", or if the filename truly ends with it, percent-encode the ":" as %3A.`,
449
+ );
450
+ }
451
+
452
+ function assertNotInternalUrl(expanded: string, original: string): void {
453
+ for (const prefix of TOP_LEVEL_INTERNAL_URL_PREFIXES) {
454
+ if (expanded.startsWith(prefix)) {
455
+ throw new Error(
456
+ `Path "${original}" uses internal scheme "${prefix}" and must be resolved through the proper protocol handler, not as a filesystem path.`,
457
+ );
458
+ }
459
+ }
460
+ }
461
+
462
+ export function normalizeLocalScheme(filePath: string): string {
463
+ return filePath.replace(/^(local:)\/(?!\/)/, "$1//");
464
+ }
465
+
466
+ export function isInternalUrlPath(filePath: string): boolean {
467
+ const normalized = normalizeLocalScheme(filePath);
468
+ const expandedAndNormalized = normalizeLocalScheme(expandPath(normalized));
469
+ for (const prefix of TOP_LEVEL_INTERNAL_URL_PREFIXES) {
470
+ if (expandedAndNormalized.startsWith(prefix)) return true;
471
+ }
472
+ return false;
473
+ }
474
+
475
+ /**
476
+ * True when a tool path argument references the `ssh://` scheme anywhere.
477
+ *
478
+ * Substring (not anchored) on purpose: it feeds the read/search/write approval
479
+ * tier, which runs synchronously on the raw args. `search` only flattens a
480
+ * delimited `paths: "a,ssh://h/x"` into separate entries *after* approval, so an
481
+ * anchored check would let an embedded `ssh://` slip through at the read tier.
482
+ * Matching the literal `ssh://` substring also tracks exactly what routes to the
483
+ * SSH handler; over-matching only over-prompts (fail-closed).
484
+ */
485
+ export function pathTargetsSsh(path: string): boolean {
486
+ return /ssh:\/\//i.test(path);
487
+ }
488
+
489
+ /**
490
+ * True when a path is specifically an `ssh://` URL (anchored scheme match).
491
+ * Unlike {@link pathTargetsSsh} (substring, for the pre-expansion approval
492
+ * scan), this is the exact per-entry check used to reject `ssh://` *before* a
493
+ * side-effecting `InternalUrlRouter.resolve` in tools that need a local file.
494
+ */
495
+ export function isSshUrl(path: string): boolean {
496
+ return /^ssh:\/\//i.test(path.trim());
497
+ }
498
+
499
+ /**
500
+ * True when the read tool's URL parser (`parseReadUrlTarget` in fetch.ts) would
501
+ * recognize this path as a readable external URL: a strict `http(s)://`, a
502
+ * collapsed `http(s):/host` (Node path normalization folds `//` → `/`), or a
503
+ * scheme-less `www.` spelling. Keep in sync with `parseReadUrlTarget`.
504
+ */
505
+ export function isReadableUrlPath(value: string): boolean {
506
+ return /^https?:\/\/?/i.test(value) || /^www\./i.test(value);
507
+ }
508
+
509
+ /**
510
+ * Resolve a path relative to the given cwd.
511
+ * Handles ~ expansion and absolute paths.
512
+ *
513
+ * A bare root slash is treated as a workspace-root alias for tool inputs. Users
514
+ * often pass `/` to mean “search from here”, and letting tools escape to the
515
+ * filesystem root is almost never what they intended.
516
+ */
517
+ export function resolveToCwd(filePath: string, cwd: string): string {
518
+ const normalized = normalizeLocalScheme(filePath);
519
+ const expanded = normalizeWindowsDriveAliasPath(expandPath(normalized));
520
+ const expandedAndNormalized = normalizeLocalScheme(expanded);
521
+
522
+ assertNotInternalUrl(expandedAndNormalized, normalized);
523
+
524
+ if (/^\/+$/.test(expanded)) {
525
+ return cwd;
526
+ }
527
+ if (path.isAbsolute(expanded)) {
528
+ return expanded;
529
+ }
530
+ return path.resolve(cwd, expanded);
531
+ }
532
+
533
+ /**
534
+ * Resolve a path that MUST stay inside `cwd`, or `null` when it would escape.
535
+ *
536
+ * {@link resolveToCwd} deliberately honors absolute paths, `~`, and `..` —
537
+ * correct for a path a user typed, wrong for one a remote peer supplied.
538
+ * Callers handling untrusted input (Cursor's `download_path`) use this instead:
539
+ * only a non-empty relative path landing under the live cwd is accepted, so
540
+ * neither `/etc/passwd` nor `../../escape` can be written through.
541
+ *
542
+ * The lexical check alone is not containment: a symlink inside the workspace
543
+ * can point anywhere, so `out/config` under a `ws/out -> /elsewhere` link is
544
+ * relative, `..`-free, and still writes outside. Both the target and its
545
+ * deepest existing ancestor are therefore realpath-resolved — the ancestor
546
+ * because a download names a file that does not exist yet, so the link in its
547
+ * path is the only thing that can be resolved before the write.
548
+ *
549
+ * The cwd itself is rejected: a download names a file, never the directory.
550
+ */
551
+ export function confineToWorkspace(filePath: string, cwd: string): string | null {
552
+ if (!filePath || path.isAbsolute(filePath)) return null;
553
+ // `~` expands to an absolute path, and an internal URL is not a filesystem
554
+ // target at all; neither is a relative workspace path.
555
+ if (filePath.startsWith("~") || isInternalUrlPath(filePath)) return null;
556
+ const root = path.resolve(cwd);
557
+ const resolved = path.resolve(root, filePath);
558
+ if (!isUnderRootLexical(resolved, root)) return null;
559
+
560
+ // A workspace reached through a link of its own is legitimate (/tmp on
561
+ // macOS), so the real root is the comparison basis. An unresolvable root is
562
+ // not a workspace to contain anything in.
563
+ const realRoot = tryRealpath(root);
564
+ if (!realRoot) return null;
565
+
566
+ // An existing target is authoritative: resolve it outright.
567
+ const realTarget = tryRealpath(resolved);
568
+ if (realTarget) return isUnderRootLexical(realTarget, realRoot) ? resolved : null;
569
+
570
+ // `realpath` also fails on a *dangling* link, and a write follows that link
571
+ // to wherever it points. Chasing the chain to decide would mean
572
+ // reimplementing symlink resolution (multi-hop, relative hops, loops, and
573
+ // a TOCTOU window against a link that can be re-pointed between the check
574
+ // and the write). A download names a file to create, so a path that is
575
+ // already an unresolvable link is refused outright — the one shape where
576
+ // "cannot tell where this lands" is the whole answer.
577
+ if (isSymlink(resolved)) return null;
578
+
579
+ // Otherwise walk up to the deepest ancestor that does exist and check that,
580
+ // then re-apply the segments below it. Those segments are `..`-free by the
581
+ // lexical check above, so they cannot climb back out.
582
+ let ancestor = path.dirname(resolved);
583
+ const tail: string[] = [path.basename(resolved)];
584
+ for (;;) {
585
+ const real = tryRealpath(ancestor);
586
+ if (real) {
587
+ return isUnderRootLexical(path.join(real, ...tail.reverse()), realRoot) ? resolved : null;
588
+ }
589
+ const parent = path.dirname(ancestor);
590
+ // Ran past the root without finding anything real: the workspace itself
591
+ // resolved above, so this cannot happen unless it vanished mid-check.
592
+ if (parent === ancestor || !isUnderRootLexical(ancestor, root)) return null;
593
+ tail.push(path.basename(ancestor));
594
+ ancestor = parent;
595
+ }
596
+ }
597
+
598
+ /** Whether `target` is a strict descendant of `root`, ignoring symlinks. */
599
+ function isUnderRootLexical(target: string, root: string): boolean {
600
+ const relative = path.relative(root, target);
601
+ return !!relative && !relative.startsWith("..") && !path.isAbsolute(relative);
602
+ }
603
+
604
+ function tryRealpath(target: string): string | null {
605
+ try {
606
+ return fs.realpathSync.native(target);
607
+ } catch {
608
+ return null;
609
+ }
610
+ }
611
+
612
+ /** Whether the path itself is a symlink, without following it. */
613
+ function isSymlink(target: string): boolean {
614
+ try {
615
+ return fs.lstatSync(target).isSymbolicLink();
616
+ } catch {
617
+ return false;
618
+ }
619
+ }
620
+
621
+ export function formatPathRelativeToCwd(
622
+ filePath: string,
623
+ cwd: string,
624
+ options: { trailingSlash?: boolean } = {},
625
+ ): string {
626
+ const resolvedCwd = path.resolve(cwd);
627
+ const normalized = normalizeLocalScheme(filePath);
628
+ if (isInternalUrlPath(normalized)) {
629
+ return normalized;
630
+ }
631
+ const expanded = expandPath(normalized);
632
+ const resolvedPath = path.isAbsolute(expanded) ? path.resolve(expanded) : path.resolve(cwd, expanded);
633
+ const relative = path.relative(resolvedCwd, resolvedPath);
634
+ const isWithinCwd = relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative));
635
+ let displayPath = normalizePosixPath(isWithinCwd ? relative || "." : resolvedPath);
636
+ if (options.trailingSlash && displayPath !== "." && !displayPath.endsWith("/")) {
637
+ displayPath += "/";
638
+ }
639
+ return displayPath;
640
+ }
641
+
642
+ /**
643
+ * Strip matching surrounding double quotes from a path string.
644
+ * Common when users paste quoted paths from Windows Explorer or shell copy-paste.
645
+ * Only double quotes — single quotes are valid POSIX filename characters.
646
+ * Tradeoff: a POSIX path literally starting AND ending with " would also be unquoted.
647
+ * Accepted because such names are virtually nonexistent in practice.
648
+ */
649
+ export function stripOuterDoubleQuotes(input: string): string {
650
+ return input.startsWith('"') && input.endsWith('"') && input.length > 1 ? input.slice(1, -1) : input;
651
+ }
652
+ function normalizePathSeparators(input: string): string {
653
+ if (isInternalUrlPath(input)) return input;
654
+ if (!input.includes("\\")) return input;
655
+ return input.replace(/\\/g, "/");
656
+ }
657
+
658
+ export function normalizePathLikeInput(input: string): string {
659
+ return stripOuterDoubleQuotes(input.trim());
660
+ }
661
+
662
+ /**
663
+ * Parse a JSON-encoded array of path strings (e.g. `'["a.ts","b.ts"]'`).
664
+ * Returns `null` when the input is not a bracketed JSON string array, so the
665
+ * caller can fall back to treating the input as a single literal path.
666
+ */
667
+ function parseStringEncodedPathArray(input: string): string[] | null {
668
+ const trimmed = input.trim();
669
+ if (!trimmed.startsWith("[") || !trimmed.endsWith("]")) return null;
670
+
671
+ let parsed: unknown;
672
+ try {
673
+ parsed = JSON.parse(trimmed);
674
+ } catch {
675
+ return null;
676
+ }
677
+
678
+ if (!Array.isArray(parsed) || parsed.some(entry => typeof entry !== "string")) {
679
+ return null;
680
+ }
681
+ return parsed;
682
+ }
683
+
684
+ /**
685
+ * Normalize a path argument that may arrive as a single string, a JSON-encoded
686
+ * string array (`'["a.ts"]'`), or an actual array into a flat `string[]`.
687
+ * Delimited single strings (`"a.ts b.ts"`) are left for
688
+ * {@link expandDelimitedPathEntries} to split.
689
+ */
690
+ export function toPathList(input: string | string[] | undefined): string[] {
691
+ if (typeof input === "string") return parseStringEncodedPathArray(input) ?? [input];
692
+ return input ?? [];
693
+ }
694
+
695
+ const GLOB_PATH_CHARS = ["*", "?", "[", "{"] as const;
696
+
697
+ export function hasGlobPathChars(filePath: string): boolean {
698
+ return GLOB_PATH_CHARS.some(char => filePath.includes(char));
699
+ }
700
+
701
+ type PathEntrySplitter = (item: string) => { basePath: string };
702
+
703
+ const TOP_LEVEL_WHITESPACE_RE = /\s/;
704
+
705
+ type DelimitedPathSplitMode = "comma" | "semicolon" | "whitespace" | "mixed";
706
+
707
+ function isDelimitedPathSeparator(ch: string, mode: DelimitedPathSplitMode): boolean {
708
+ if (mode === "comma") return ch === ",";
709
+ if (mode === "semicolon") return ch === ";";
710
+ if (mode === "whitespace") return TOP_LEVEL_WHITESPACE_RE.test(ch);
711
+ return ch === "," || ch === ";" || TOP_LEVEL_WHITESPACE_RE.test(ch);
712
+ }
713
+
714
+ function hasTopLevelPathDelimiter(entry: string): boolean {
715
+ let braceDepth = 0;
716
+ for (let i = 0; i < entry.length; i++) {
717
+ const ch = entry[i];
718
+ if (ch === "\\" && i + 1 < entry.length) {
719
+ i++;
720
+ continue;
721
+ }
722
+ if (ch === "{") {
723
+ braceDepth++;
724
+ continue;
725
+ }
726
+ if (ch === "}") {
727
+ if (braceDepth > 0) braceDepth--;
728
+ continue;
729
+ }
730
+ if (braceDepth === 0 && (ch === "," || ch === ";" || TOP_LEVEL_WHITESPACE_RE.test(ch))) {
731
+ return true;
732
+ }
733
+ }
734
+ return false;
735
+ }
736
+
737
+ function splitTopLevelDelimitedPath(entry: string, mode: DelimitedPathSplitMode): string[] {
738
+ const parts: string[] = [];
739
+ let braceDepth = 0;
740
+ let start = 0;
741
+ for (let i = 0; i < entry.length; i++) {
742
+ const ch = entry[i];
743
+ if (ch === "\\" && i + 1 < entry.length) {
744
+ i++;
745
+ continue;
746
+ }
747
+ if (ch === "{") {
748
+ braceDepth++;
749
+ continue;
750
+ }
751
+ if (ch === "}") {
752
+ if (braceDepth > 0) braceDepth--;
753
+ continue;
754
+ }
755
+ if (braceDepth !== 0 || !isDelimitedPathSeparator(ch, mode)) continue;
756
+ parts.push(entry.slice(start, i));
757
+ start = i + 1;
758
+ }
759
+ parts.push(entry.slice(start));
760
+ return parts;
761
+ }
762
+
763
+ async function delimitedPathPartResolves(entry: string, cwd: string, splitter: PathEntrySplitter): Promise<boolean> {
764
+ if (isInternalUrlPath(entry)) return true;
765
+ const peeled = splitPathAndSel(entry).path;
766
+ const { basePath } = splitter(peeled);
767
+ const absoluteBasePath = resolveToCwd(basePath, cwd);
768
+ try {
769
+ await fs.promises.stat(absoluteBasePath);
770
+ return true;
771
+ } catch (err) {
772
+ // ENOENT and ENAMETOOLONG both mean this string cannot name an existing
773
+ // path, so the whole entry does not resolve and the delimited split may
774
+ // proceed (issue #7597). Other errors (EACCES, transient I/O) stay fatal.
775
+ if (isEnoent(err) || hasFsCode(err, "ENAMETOOLONG")) return false;
776
+ throw err;
777
+ }
778
+ }
779
+
780
+ /**
781
+ * How many split parts must resolve to an existing path for the split to win.
782
+ * Semicolon is the documented list delimiter, so it splits unconditionally
783
+ * (`"none"`) — an all-missing list must still fan out so multi-path missing
784
+ * semantics can name every entry. Comma is legacy recovery (`"some"`), and
785
+ * whitespace/mixed are aggressive heuristics gated on every part existing.
786
+ */
787
+ type DelimitedResolveRequirement = "all" | "some" | "none";
788
+
789
+ async function tryDelimitedPathSplit(
790
+ entry: string,
791
+ cwd: string,
792
+ splitter: PathEntrySplitter,
793
+ mode: DelimitedPathSplitMode,
794
+ requirement: DelimitedResolveRequirement,
795
+ ): Promise<string[] | null> {
796
+ const rawParts = splitTopLevelDelimitedPath(entry, mode);
797
+ if (rawParts.length < 2) return null;
798
+
799
+ const parts = rawParts.map(normalizePathLikeInput).filter(part => part.length > 0);
800
+ if (parts.length === 0) return null;
801
+ if (parts.length < 2 && rawParts.length === parts.length) return null;
802
+
803
+ if (requirement !== "none") {
804
+ const resolved = await Promise.all(parts.map(part => delimitedPathPartResolves(part, cwd, splitter)));
805
+ const valid = requirement === "all" ? resolved.every(Boolean) : resolved.some(Boolean);
806
+ if (!valid) return null;
807
+ }
808
+ return parts;
809
+ }
810
+
811
+ /**
812
+ * Split one path-like entry whose multiple targets were flattened into one
813
+ * string. Existing paths are kept intact, so real filenames containing spaces,
814
+ * commas, or semicolons win over delimiter recovery.
815
+ */
816
+ export async function splitDelimitedPathEntry(
817
+ entry: string,
818
+ cwd: string,
819
+ options: {
820
+ splitter?: PathEntrySplitter;
821
+ routedUrlPredicate?: (entry: string) => boolean;
822
+ } = {},
823
+ ): Promise<string[] | null> {
824
+ const normalizedEntry = normalizePathLikeInput(entry);
825
+ if (!hasTopLevelPathDelimiter(normalizedEntry)) return null;
826
+ const splitter = options.splitter ?? parseSearchPath;
827
+ if (options.routedUrlPredicate?.(normalizedEntry)) {
828
+ const parts = await tryDelimitedPathSplit(normalizedEntry, cwd, splitter, "semicolon", "none");
829
+ return parts?.every(options.routedUrlPredicate) ? parts : null;
830
+ }
831
+ if (isInternalUrlPath(normalizedEntry)) return null;
832
+ // A real POSIX file may contain the delimiter and a selector-shaped tail
833
+ // (`a;b:1-2`, `a b:1-2`). Preserve the raw entry whenever the full literal
834
+ // resolves — or is only ambiguous — so downstream literal-preferring
835
+ // splitters see it before delimiter expansion peels or splits (issue #4618
836
+ // reviewer feedback: delimited expansion ran before the literal check).
837
+ if ((await probeLiteralPathExists(normalizedEntry, cwd)) !== "missing") return null;
838
+ const peeledEntry = splitPathAndSel(normalizedEntry).path;
839
+ if (!hasGlobPathChars(peeledEntry) && (await delimitedPathPartResolves(normalizedEntry, cwd, splitter))) {
840
+ return null;
841
+ }
842
+
843
+ return (
844
+ (await tryDelimitedPathSplit(normalizedEntry, cwd, splitter, "semicolon", "none")) ??
845
+ (await tryDelimitedPathSplit(normalizedEntry, cwd, splitter, "comma", "some")) ??
846
+ (await tryDelimitedPathSplit(normalizedEntry, cwd, splitter, "whitespace", "all")) ??
847
+ (await tryDelimitedPathSplit(normalizedEntry, cwd, splitter, "mixed", "all"))
848
+ );
849
+ }
850
+
851
+ /** Expand delimited entries in-place while preserving unsplit entries. */
852
+ export async function expandDelimitedPathEntries(
853
+ entries: readonly string[],
854
+ cwd: string,
855
+ options: { splitter?: PathEntrySplitter } = {},
856
+ ): Promise<string[]> {
857
+ const expanded: string[] = [];
858
+ for (const entry of entries) {
859
+ const normalizedEntry = normalizePathLikeInput(entry);
860
+ const split = await splitDelimitedPathEntry(normalizedEntry, cwd, options);
861
+ if (split) expanded.push(...split);
862
+ else expanded.push(normalizedEntry);
863
+ }
864
+ return expanded;
865
+ }
866
+
867
+ export interface ParsedSearchPath {
868
+ basePath: string;
869
+ glob?: string;
870
+ }
871
+
872
+ export interface ParsedFindPattern {
873
+ basePath: string;
874
+ globPattern: string;
875
+ hasGlob: boolean;
876
+ }
877
+
878
+ export interface ResolvedSearchTarget {
879
+ basePath: string;
880
+ glob?: string;
881
+ }
882
+
883
+ export interface ResolvedMultiSearchPath {
884
+ basePath: string;
885
+ glob?: string;
886
+ scopePath: string;
887
+ exactFilePaths?: string[];
888
+ targets?: ResolvedSearchTarget[];
889
+ }
890
+
891
+ export interface ResolvedFindTarget {
892
+ basePath: string;
893
+ globPattern: string;
894
+ hasGlob: boolean;
895
+ }
896
+
897
+ export interface ResolvedMultiFindPattern {
898
+ targets: ResolvedFindTarget[];
899
+ scopePath: string;
900
+ }
901
+ export function parseSearchPath(filePath: string): ParsedSearchPath {
902
+ const normalizedPath = normalizePathSeparators(filePath);
903
+ const segments = normalizedPath.split("/");
904
+ let firstGlobIndex = -1;
905
+ for (let i = 0; i < segments.length; i++) {
906
+ if (hasGlobPathChars(segments[i])) {
907
+ firstGlobIndex = i;
908
+ break;
909
+ }
910
+ }
911
+
912
+ if (firstGlobIndex === -1) {
913
+ return { basePath: normalizedPath };
914
+ }
915
+
916
+ if (firstGlobIndex <= 0) {
917
+ return { basePath: ".", glob: normalizedPath };
918
+ }
919
+
920
+ return {
921
+ basePath: segments.slice(0, firstGlobIndex).join("/"),
922
+ glob: segments.slice(firstGlobIndex).join("/"),
923
+ };
924
+ }
925
+
926
+ /**
927
+ * Async sibling of {@link parseSearchPath} that prefers literal interpretation
928
+ * when a path containing glob metacharacters resolves to an existing entry on
929
+ * disk. Disambiguates Next.js/SvelteKit routes like `apps/[id]/page.tsx` —
930
+ * without this, `[id]` is parsed as a glob character class and silently
931
+ * matches nothing.
932
+ */
933
+ export async function parseSearchPathPreferringLiteral(filePath: string, cwd: string): Promise<ParsedSearchPath> {
934
+ if (!hasGlobPathChars(filePath) || isInternalUrlPath(filePath)) return parseSearchPath(filePath);
935
+ try {
936
+ await fs.promises.stat(resolveToCwd(filePath, cwd));
937
+ return { basePath: normalizePathSeparators(filePath) };
938
+ } catch {
939
+ return parseSearchPath(filePath);
940
+ }
941
+ }
942
+
943
+ // Parse a find pattern into a base directory path and a glob pattern.
944
+ // Examples:
945
+ // src/app/**/\*.tsx -> { basePath: "src/app", globPattern: "**/*.tsx", hasGlob: true }
946
+ // src/app/\*.tsx -> { basePath: "src/app", globPattern: "*.tsx", hasGlob: true }
947
+ // \*.ts -> { basePath: ".", globPattern: "**/*.ts", hasGlob: true }
948
+ // **/\*.json -> { basePath: ".", globPattern: "**/*.json", hasGlob: true }
949
+ // /abs/path/**/\*.ts -> { basePath: "/abs/path", globPattern: "**/*.ts", hasGlob: true }
950
+ // src/app -> { basePath: "src/app", globPattern: "**/*", hasGlob: false }
951
+ export function parseFindPattern(pattern: string): ParsedFindPattern {
952
+ const normalizedPattern = normalizePathSeparators(pattern);
953
+ const segments = normalizedPattern.split("/");
954
+ let firstGlobIndex = -1;
955
+ for (let i = 0; i < segments.length; i++) {
956
+ if (hasGlobPathChars(segments[i])) {
957
+ firstGlobIndex = i;
958
+ break;
959
+ }
960
+ }
961
+
962
+ if (firstGlobIndex === -1) {
963
+ return { basePath: normalizedPattern, globPattern: "**/*", hasGlob: false };
964
+ }
965
+
966
+ if (firstGlobIndex === 0) {
967
+ const needsRecursive = !normalizedPattern.startsWith("**/");
968
+ return {
969
+ basePath: ".",
970
+ globPattern: needsRecursive ? `**/${normalizedPattern}` : normalizedPattern,
971
+ hasGlob: true,
972
+ };
973
+ }
974
+
975
+ return {
976
+ basePath: segments.slice(0, firstGlobIndex).join("/"),
977
+ globPattern: segments.slice(firstGlobIndex).join("/"),
978
+ hasGlob: true,
979
+ };
980
+ }
981
+
982
+ export function combineSearchGlobs(prefixGlob?: string, suffixGlob?: string): string | undefined {
983
+ if (!prefixGlob) return suffixGlob;
984
+ if (!suffixGlob) return prefixGlob;
985
+
986
+ const normalizedPrefix = prefixGlob.replace(/\/+$/, "");
987
+ const normalizedSuffix = suffixGlob.replace(/^\/+/, "");
988
+
989
+ return `${normalizedPrefix}/${normalizedSuffix}`;
990
+ }
991
+
992
+ function normalizePosixPath(filePath: string): string {
993
+ return filePath.replace(/\\/g, "/");
994
+ }
995
+
996
+ function joinRelativeGlob(basePath: string | undefined, globPattern: string): string {
997
+ if (!basePath || basePath === ".") return normalizePosixPath(globPattern).replace(/^\/+/, "");
998
+ const normalizedBase = normalizePosixPath(basePath).replace(/\/+$/, "");
999
+ const normalizedGlob = normalizePosixPath(globPattern).replace(/^\/+/, "");
1000
+ return `${normalizedBase}/${normalizedGlob}`;
1001
+ }
1002
+
1003
+ function buildBraceUnion(patterns: string[]): string | undefined {
1004
+ const uniquePatterns = [...new Set(patterns.map(pattern => normalizePosixPath(pattern).trim()).filter(Boolean))];
1005
+ if (uniquePatterns.length === 0) return undefined;
1006
+ if (uniquePatterns.length === 1) return uniquePatterns[0];
1007
+ return `{${uniquePatterns.join(",")}}`;
1008
+ }
1009
+
1010
+ function findCommonBasePath(paths: string[]): string {
1011
+ if (paths.length === 0) return ".";
1012
+ let commonParts = path.resolve(paths[0]).split(path.sep);
1013
+ for (const candidatePath of paths.slice(1)) {
1014
+ const candidateParts = path.resolve(candidatePath).split(path.sep);
1015
+ let sharedCount = 0;
1016
+ const maxShared = Math.min(commonParts.length, candidateParts.length);
1017
+ while (sharedCount < maxShared && commonParts[sharedCount] === candidateParts[sharedCount]) {
1018
+ sharedCount += 1;
1019
+ }
1020
+ commonParts = commonParts.slice(0, sharedCount);
1021
+ }
1022
+ if (commonParts.length === 0) {
1023
+ return path.parse(path.resolve(paths[0])).root;
1024
+ }
1025
+ const joined = commonParts.join(path.sep);
1026
+ return joined || path.parse(path.resolve(paths[0])).root;
1027
+ }
1028
+
1029
+ function toScopeDisplay(items: string[], cwd: string): string {
1030
+ return items
1031
+ .map(item =>
1032
+ formatPathRelativeToCwd(item, cwd, {
1033
+ trailingSlash: item.endsWith("/") || item.endsWith("\\"),
1034
+ }),
1035
+ )
1036
+ .join(", ");
1037
+ }
1038
+
1039
+ async function resolveSearchPathItems(
1040
+ pathItems: string[],
1041
+ cwd: string,
1042
+ suffixGlob?: string,
1043
+ fanOutFileItems = false,
1044
+ ): Promise<ResolvedMultiSearchPath | undefined> {
1045
+ if (pathItems.length < 1) {
1046
+ return undefined;
1047
+ }
1048
+
1049
+ const parsedItems = await Promise.all(
1050
+ pathItems.map(async item => {
1051
+ const parsedPath = await parseSearchPathPreferringLiteral(item, cwd);
1052
+ const absoluteBasePath = resolveToCwd(parsedPath.basePath, cwd);
1053
+ const stat = await fs.promises.stat(absoluteBasePath);
1054
+ return { raw: item, parsedPath, absoluteBasePath, stat };
1055
+ }),
1056
+ );
1057
+
1058
+ const allExactFiles = !suffixGlob && parsedItems.every(item => !item.parsedPath.glob && item.stat.isFile());
1059
+ const commonBasePath = findCommonBasePath(parsedItems.map(item => item.absoluteBasePath));
1060
+ const combinedPatterns = parsedItems.map(item => {
1061
+ const relativeBasePath = normalizePosixPath(path.relative(commonBasePath, item.absoluteBasePath)) || ".";
1062
+ if (item.parsedPath.glob) {
1063
+ const pathGlob = joinRelativeGlob(relativeBasePath, item.parsedPath.glob);
1064
+ return combineSearchGlobs(pathGlob, suffixGlob) ?? pathGlob;
1065
+ }
1066
+ if (suffixGlob) {
1067
+ const pathPrefix = relativeBasePath === "." ? undefined : relativeBasePath;
1068
+ return combineSearchGlobs(pathPrefix, suffixGlob) ?? suffixGlob;
1069
+ }
1070
+ if (item.stat.isDirectory()) {
1071
+ return joinRelativeGlob(relativeBasePath, "**/*");
1072
+ }
1073
+ return relativeBasePath === "." ? path.basename(item.absoluteBasePath) : relativeBasePath;
1074
+ });
1075
+ // A single walk rooted at the common ancestor is only safe when that
1076
+ // ancestor is itself one of the requested scopes (e.g. `.` + `src/foo.ts`):
1077
+ // the walk then covers exactly what the caller asked for. When the common
1078
+ // ancestor is an unrequested parent (`.` + `~/.gitconfig` → `$HOME`, or
1079
+ // disjoint trees → `/`), a collapsed walk traverses every unrelated sibling
1080
+ // under it — fan out into per-item targets so each scan stays bounded to a
1081
+ // requested path.
1082
+ const commonIsRequestedScope = parsedItems.some(item => item.absoluteBasePath === commonBasePath);
1083
+ // Walkers prune `.git` unconditionally and honor gitignore, so a plain-file
1084
+ // item folded into a directory walk's glob union (`.` + `.git/config`) can
1085
+ // silently never match. Callers that dedupe overlapping results opt in via
1086
+ // `fanOutFileItems` to get explicit file targets, which bypass the walker.
1087
+ const demotesFileItem =
1088
+ fanOutFileItems && !allExactFiles && parsedItems.some(item => !item.parsedPath.glob && item.stat.isFile());
1089
+ const targets =
1090
+ parsedItems.length > 1 && (!commonIsRequestedScope || demotesFileItem)
1091
+ ? parsedItems.map(item => ({
1092
+ basePath: item.absoluteBasePath,
1093
+ glob: item.parsedPath.glob ? combineSearchGlobs(item.parsedPath.glob, suffixGlob) : suffixGlob,
1094
+ }))
1095
+ : undefined;
1096
+
1097
+ return {
1098
+ basePath: commonBasePath,
1099
+ glob: buildBraceUnion(combinedPatterns),
1100
+ scopePath: toScopeDisplay(pathItems, cwd),
1101
+ exactFilePaths: allExactFiles ? parsedItems.map(item => item.absoluteBasePath) : undefined,
1102
+ targets,
1103
+ };
1104
+ }
1105
+
1106
+ export async function resolveExplicitSearchPaths(
1107
+ pathItems: string[],
1108
+ cwd: string,
1109
+ suffixGlob?: string,
1110
+ fanOutFileItems = false,
1111
+ ): Promise<ResolvedMultiSearchPath | undefined> {
1112
+ return resolveSearchPathItems([...new Set(pathItems)], cwd, suffixGlob, fanOutFileItems);
1113
+ }
1114
+
1115
+ async function resolveFindPatternItems(
1116
+ patternItems: string[],
1117
+ cwd: string,
1118
+ ): Promise<ResolvedMultiFindPattern | undefined> {
1119
+ if (patternItems.length <= 1) {
1120
+ return undefined;
1121
+ }
1122
+
1123
+ // Each path becomes its own walk root. Collapsing to a shared common ancestor
1124
+ // (and filtering with a brace-union glob) would force the walker to traverse
1125
+ // and stat every unrelated sibling under that ancestor — two paths under
1126
+ // $HOME would scan all of $HOME. The find tool fans these targets out in
1127
+ // parallel instead, so every scan stays bounded to exactly one requested path.
1128
+ const targets = patternItems.map(item => {
1129
+ const parsedPattern = parseFindPattern(item);
1130
+ return {
1131
+ basePath: resolveToCwd(parsedPattern.basePath, cwd),
1132
+ globPattern: parsedPattern.globPattern,
1133
+ hasGlob: parsedPattern.hasGlob,
1134
+ };
1135
+ });
1136
+
1137
+ return {
1138
+ targets,
1139
+ scopePath: toScopeDisplay(patternItems, cwd),
1140
+ };
1141
+ }
1142
+
1143
+ export async function resolveExplicitFindPatterns(
1144
+ patternItems: string[],
1145
+ cwd: string,
1146
+ ): Promise<ResolvedMultiFindPattern | undefined> {
1147
+ return resolveFindPatternItems([...new Set(patternItems)], cwd);
1148
+ }
1149
+
1150
+ /**
1151
+ * Result of partitioning a list of user-supplied paths/globs into entries whose
1152
+ * base directory currently exists on disk versus those that do not.
1153
+ *
1154
+ * Used by multi-path tools (search, find, ast_grep, ast_edit) to tolerate one
1155
+ * or more missing entries in a multi-path call: the surviving entries should
1156
+ * still be searched, with the missing entries surfaced as a non-fatal warning.
1157
+ */
1158
+ export interface PartitionedPaths {
1159
+ /** Raw input strings whose resolved base path exists. */
1160
+ valid: string[];
1161
+ /** Raw input strings whose resolved base path is missing (ENOENT). */
1162
+ missing: string[];
1163
+ }
1164
+
1165
+ /**
1166
+ * Stat each input's base path concurrently; return entries split by existence.
1167
+ *
1168
+ * `splitter` is expected to be {@link parseFindPattern} or
1169
+ * {@link parseSearchPath}: both return a `basePath` field that this helper
1170
+ * resolves against `cwd` and stats. ENOENT is the only swallowed error — every
1171
+ * other stat failure (permission, IO, etc.) propagates so callers do not silently
1172
+ * skip paths that exist but are unreadable.
1173
+ *
1174
+ * Order of `valid` and `missing` follows the input order, so callers can rely
1175
+ * on `valid[0]` matching the first surviving user-supplied entry.
1176
+ */
1177
+ export async function partitionExistingPaths(
1178
+ items: string[],
1179
+ cwd: string,
1180
+ splitter: (item: string) => { basePath: string },
1181
+ ): Promise<PartitionedPaths> {
1182
+ const settled = await Promise.all(
1183
+ items.map(async item => {
1184
+ const { basePath } = splitter(item);
1185
+ const absoluteBasePath = resolveToCwd(basePath, cwd);
1186
+ try {
1187
+ await fs.promises.stat(absoluteBasePath);
1188
+ return { item, exists: true } as const;
1189
+ } catch (err) {
1190
+ if (isEnoent(err)) return { item, exists: false } as const;
1191
+ throw err;
1192
+ }
1193
+ }),
1194
+ );
1195
+ const valid: string[] = [];
1196
+ const missing: string[] = [];
1197
+ for (const entry of settled) {
1198
+ if (entry.exists) valid.push(entry.item);
1199
+ else missing.push(entry.item);
1200
+ }
1201
+ return { valid, missing };
1202
+ }
1203
+
1204
+ export function resolveReadPath(filePath: string, cwd: string): string {
1205
+ const resolved = resolveToCwd(filePath, cwd);
1206
+ const shellEscapedVariant = tryShellEscapedPath(resolved);
1207
+ const baseCandidates = shellEscapedVariant !== resolved ? [resolved, shellEscapedVariant] : [resolved];
1208
+
1209
+ for (const baseCandidate of baseCandidates) {
1210
+ if (fileExists(baseCandidate)) {
1211
+ return baseCandidate;
1212
+ }
1213
+ }
1214
+
1215
+ for (const baseCandidate of baseCandidates) {
1216
+ // Try macOS AM/PM variant (narrow no-break space before AM/PM)
1217
+ const amPmVariant = tryMacOSScreenshotPath(baseCandidate);
1218
+ if (amPmVariant !== baseCandidate && fileExists(amPmVariant)) {
1219
+ return amPmVariant;
1220
+ }
1221
+
1222
+ // Try NFD variant (macOS stores filenames in NFD form)
1223
+ const nfdVariant = tryNFDVariant(baseCandidate);
1224
+ if (nfdVariant !== baseCandidate && fileExists(nfdVariant)) {
1225
+ return nfdVariant;
1226
+ }
1227
+
1228
+ // Try curly quote variant (macOS uses U+2019 in screenshot names)
1229
+ const curlyVariant = tryCurlyQuoteVariant(baseCandidate);
1230
+ if (curlyVariant !== baseCandidate && fileExists(curlyVariant)) {
1231
+ return curlyVariant;
1232
+ }
1233
+
1234
+ // Try combined NFD + curly quote (for French macOS screenshots like "Capture d'écran")
1235
+ const nfdCurlyVariant = tryCurlyQuoteVariant(nfdVariant);
1236
+ if (nfdCurlyVariant !== baseCandidate && fileExists(nfdCurlyVariant)) {
1237
+ return nfdCurlyVariant;
1238
+ }
1239
+ }
1240
+
1241
+ return resolved;
1242
+ }
1243
+
1244
+ const WORKSPACE_SUFFIX_TIMEOUT_MS = 5000;
1245
+
1246
+ function escapeGlobMetachars(value: string): string {
1247
+ return value.replace(/[*?[{]/g, "[$&]");
1248
+ }
1249
+
1250
+ /**
1251
+ * Find a unique workspace entry whose trailing path matches a missing authored path.
1252
+ * Returns `null` for no match, ambiguity, timeout, or scan failure.
1253
+ */
1254
+ export async function findUniqueWorkspaceSuffix(
1255
+ rawPath: string,
1256
+ cwd: string,
1257
+ signal?: AbortSignal,
1258
+ ): Promise<{ absolutePath: string; displayPath: string } | null> {
1259
+ const normalized = rawPath.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/+$/, "");
1260
+ if (!normalized) return null;
1261
+
1262
+ const timeoutSignal = AbortSignal.timeout(WORKSPACE_SUFFIX_TIMEOUT_MS);
1263
+ const combinedSignal = signal ? AbortSignal.any([signal, timeoutSignal]) : timeoutSignal;
1264
+
1265
+ let matches: string[];
1266
+ try {
1267
+ const result = await untilAborted(combinedSignal, () =>
1268
+ glob({
1269
+ pattern: `**/${escapeGlobMetachars(normalized)}`,
1270
+ path: cwd,
1271
+ hidden: true,
1272
+ }),
1273
+ );
1274
+ matches = result.matches.map(match => match.path);
1275
+ } catch (error) {
1276
+ if (error instanceof Error && error.name === "AbortError") {
1277
+ if (!signal?.aborted) return null;
1278
+ throw new ToolAbortError();
1279
+ }
1280
+ return null;
1281
+ }
1282
+
1283
+ if (matches.length !== 1) return null;
1284
+ return {
1285
+ absolutePath: path.resolve(cwd, matches[0]),
1286
+ displayPath: matches[0],
1287
+ };
1288
+ }
1289
+
1290
+ // =============================================================================
1291
+ // Tool-scope resolution (search/ast tools)
1292
+ // =============================================================================
1293
+
1294
+ /** Local file materialized from a readable external URL for shared tool-scope resolution. */
1295
+ export interface ResolvedExternalSearchUrl {
1296
+ /** Absolute or cwd-relative file path to search. */
1297
+ sourcePath: string;
1298
+ /** True when the materialized file must not mint editable anchors. */
1299
+ immutable?: boolean;
1300
+ }
1301
+
1302
+ export interface ToolScopeOptions {
1303
+ rawPaths: string[];
1304
+ cwd: string;
1305
+ /** Verb used in the "Cannot {action} internal URL without a backing file: …" message. */
1306
+ internalUrlAction: string;
1307
+ /** Collect absolute paths flagged immutable by their internal-URL handler. */
1308
+ trackImmutableSources?: boolean;
1309
+ /** Honor `exactFilePaths` from {@link resolveExplicitSearchPaths} (search-only). */
1310
+ surfaceExactFilePaths?: boolean;
1311
+ /** Fan plain-file entries out into per-target scans instead of folding them
1312
+ * into a directory walk's glob union (search-only: the caller must dedupe
1313
+ * matches from overlapping targets). */
1314
+ fanOutFileTargets?: boolean;
1315
+ /** Extra hint appended to "Path not found" when stat fails and the user supplied multiple paths. */
1316
+ multipathStatHint?: string;
1317
+ /** Calling session's settings — forwarded to the internal-URL router so caller-aware handlers (issue://, pr://) honor it. */
1318
+ settings?: unknown;
1319
+ /** Caller's abort signal — forwarded to the internal-URL router. */
1320
+ signal?: AbortSignal;
1321
+ /** Calling session's `local://` root mapping — pins resolutions to the calling session. */
1322
+ localProtocolOptions?: LocalProtocolOptions;
1323
+ /** Calling session's loaded skills — lets skill:// resolve without process-global state. */
1324
+ skills?: readonly Skill[];
1325
+ /** Materialize readable external URLs to local text files before scope derivation. */
1326
+ resolveExternalUrl?: (rawPath: string) => Promise<ResolvedExternalSearchUrl | undefined>;
1327
+ }
1328
+
1329
+ export interface ToolScopeResolution {
1330
+ searchPath: string;
1331
+ scopePath: string;
1332
+ globFilter: string | undefined;
1333
+ isDirectory: boolean;
1334
+ multiTargets?: ResolvedSearchTarget[];
1335
+ exactFilePaths?: string[];
1336
+ missingPaths: string[];
1337
+ immutableSourcePaths: Set<string>;
1338
+ }
1339
+
1340
+ /**
1341
+ * Shared path-input pipeline for `search`, `ast_grep`, and `ast_edit`:
1342
+ * 1. normalize + reject empty paths,
1343
+ * 2. resolve internal URLs through {@link InternalUrlRouter} to backing files,
1344
+ * 3. partition existing vs missing when multiple paths are supplied,
1345
+ * 4. derive a single search base path / glob, or a multi-target list,
1346
+ * 5. stat the resolved base path so callers can branch on directory vs file scope.
1347
+ */
1348
+ export async function resolveToolSearchScope(opts: ToolScopeOptions): Promise<ToolScopeResolution> {
1349
+ const { rawPaths: inputs, cwd, internalUrlAction } = opts;
1350
+ const normalizedRawPaths = inputs.map(normalizePathLikeInput);
1351
+ if (normalizedRawPaths.some(rawPath => rawPath.length === 0)) {
1352
+ throw new ToolError("Search scope entries must be non-empty paths or globs");
1353
+ }
1354
+ const rawPaths = await expandDelimitedPathEntries(normalizedRawPaths, cwd);
1355
+ if (rawPaths.some(rawPath => rawPath.length === 0)) {
1356
+ throw new ToolError("Search scope entries must be non-empty paths or globs");
1357
+ }
1358
+ // Strict external-URL schemes. `file://` is intentionally absent: it has
1359
+ // local-path semantics (expandPath strips it downstream), so it flows through
1360
+ // the ordinary filesystem pipeline instead of the external-URL resolver.
1361
+ const strictExternalUrlRe = /^(?:https?|ftp|ws|wss):\/\//i;
1362
+ const internalRouter = InternalUrlRouter.instance();
1363
+ const resolvedPathInputs: string[] = [];
1364
+ const immutableSourcePaths = new Set<string>();
1365
+ for (const rawPath of rawPaths) {
1366
+ let externalUrl = strictExternalUrlRe.test(rawPath);
1367
+ if (!externalUrl && isReadableUrlPath(rawPath) && !hasGlobPathChars(rawPath)) {
1368
+ // Fuzzy spelling the read parser accepts (`www.host/…`, collapsed
1369
+ // `https:/host/…`). An existing local path wins over URL
1370
+ // interpretation so a directory literally named `www.foo` stays
1371
+ // searchable; only a definitive ENOENT/ENOTDIR flips to URL handling
1372
+ // (any other stat error means the path exists — let the local
1373
+ // pipeline surface it).
1374
+ try {
1375
+ await fs.promises.stat(resolveToCwd(rawPath, cwd));
1376
+ } catch (err) {
1377
+ externalUrl = isEnoent(err) || isEnotdir(err);
1378
+ }
1379
+ }
1380
+ if (externalUrl) {
1381
+ const resolved = opts.resolveExternalUrl ? await opts.resolveExternalUrl(rawPath) : undefined;
1382
+ if (resolved) {
1383
+ resolvedPathInputs.push(resolved.sourcePath);
1384
+ if (opts.trackImmutableSources && resolved.immutable) {
1385
+ immutableSourcePaths.add(path.resolve(resolved.sourcePath));
1386
+ }
1387
+ continue;
1388
+ }
1389
+ // Resolver missing or declined (e.g. ftp/ws/wss): fail explicitly
1390
+ // instead of letting the local-path fallthrough surface a confusing
1391
+ // "Path not found" for a URL-shaped input.
1392
+ throw new ToolError(
1393
+ `Cannot ${internalUrlAction} external URL: ${rawPath}. Use \`read\` to fetch web content, then search the returned text.`,
1394
+ );
1395
+ }
1396
+ if (!internalRouter.canHandle(rawPath)) {
1397
+ resolvedPathInputs.push(rawPath);
1398
+ continue;
1399
+ }
1400
+ if (isSshUrl(rawPath)) {
1401
+ throw new ToolError(
1402
+ `Cannot ${internalUrlAction} a remote ssh:// path (no local file): ${rawPath}. Use \`read ${rawPath}\` to view it, or the \`search\` tool to grep remote files.`,
1403
+ );
1404
+ }
1405
+ if (hasGlobPathChars(rawPath)) {
1406
+ throw new ToolError(`Glob patterns are not supported for internal URLs: ${rawPath}`);
1407
+ }
1408
+ const resource = await internalRouter.resolve(rawPath, {
1409
+ cwd,
1410
+ settings: opts.settings,
1411
+ signal: opts.signal,
1412
+ localProtocolOptions: opts.localProtocolOptions,
1413
+ skills: opts.skills,
1414
+ // Tool-scope resolution only needs `sourcePath`; skip content
1415
+ // materialization so large artifacts (or any handler that separates
1416
+ // path from content) stay searchable without OOM risk.
1417
+ pathOnly: true,
1418
+ });
1419
+ if (!resource.sourcePath) {
1420
+ throw new ToolError(`Cannot ${internalUrlAction} internal URL without a backing file: ${rawPath}`);
1421
+ }
1422
+ if (opts.trackImmutableSources && resource.immutable) {
1423
+ immutableSourcePaths.add(path.resolve(resource.sourcePath));
1424
+ }
1425
+ resolvedPathInputs.push(resource.sourcePath);
1426
+ }
1427
+
1428
+ let missingPaths: string[] = [];
1429
+ let effectivePaths = resolvedPathInputs;
1430
+ if (resolvedPathInputs.length > 1) {
1431
+ const partition = await partitionExistingPaths(resolvedPathInputs, cwd, parseSearchPath);
1432
+ if (partition.valid.length === 0) {
1433
+ throw new ToolError(`Path not found: ${partition.missing.join(", ")}`);
1434
+ }
1435
+ effectivePaths = partition.valid;
1436
+ missingPaths = partition.missing;
1437
+ }
1438
+
1439
+ let searchPath: string;
1440
+ let scopePath: string;
1441
+ let globFilter: string | undefined;
1442
+ let multiTargets: ResolvedSearchTarget[] | undefined;
1443
+ let exactFilePaths: string[] | undefined;
1444
+ if (effectivePaths.length === 1) {
1445
+ const parsedPath = await parseSearchPathPreferringLiteral(effectivePaths[0] ?? ".", cwd);
1446
+ searchPath = resolveToCwd(parsedPath.basePath, cwd);
1447
+ globFilter = parsedPath.glob;
1448
+ scopePath = formatPathRelativeToCwd(searchPath, cwd);
1449
+ } else {
1450
+ const multiSearchPath = await resolveExplicitSearchPaths(
1451
+ effectivePaths,
1452
+ cwd,
1453
+ undefined,
1454
+ opts.fanOutFileTargets === true,
1455
+ );
1456
+ if (!multiSearchPath) {
1457
+ throw new ToolError("`paths` must contain at least one path or glob");
1458
+ }
1459
+ searchPath = multiSearchPath.basePath;
1460
+ multiTargets = multiSearchPath.targets;
1461
+ if (opts.surfaceExactFilePaths) {
1462
+ exactFilePaths = multiSearchPath.exactFilePaths;
1463
+ globFilter = exactFilePaths || multiTargets ? undefined : multiSearchPath.glob;
1464
+ } else {
1465
+ globFilter = multiTargets ? undefined : multiSearchPath.glob;
1466
+ }
1467
+ scopePath = multiSearchPath.scopePath;
1468
+ }
1469
+
1470
+ let isDirectory: boolean;
1471
+ try {
1472
+ const stat = await Bun.file(searchPath).stat();
1473
+ isDirectory = stat.isDirectory();
1474
+ } catch {
1475
+ const hint = opts.multipathStatHint && rawPaths.length > 1 ? opts.multipathStatHint : "";
1476
+ throw new ToolError(`Path not found: ${scopePath}${hint}`);
1477
+ }
1478
+
1479
+ return {
1480
+ searchPath,
1481
+ scopePath,
1482
+ globFilter,
1483
+ isDirectory,
1484
+ multiTargets,
1485
+ exactFilePaths,
1486
+ missingPaths,
1487
+ immutableSourcePaths,
1488
+ };
1489
+ }