pi-agent-zh 17.1.8

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 (1519) hide show
  1. package/CHANGELOG.md +14459 -0
  2. package/README.md +35 -0
  3. package/dist/CHANGELOG-vt8ene9g.md +14459 -0
  4. package/dist/cli.js +22079 -0
  5. package/dist/template-dys3vk5b.js +1671 -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 +79 -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 +606 -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 +133 -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 +195 -0
  62. package/scripts/measure-prompt-tokens.ts +63 -0
  63. package/scripts/omp +42 -0
  64. package/scripts/omp.ts +19 -0
  65. package/src/advisor/advise-tool.ts +216 -0
  66. package/src/advisor/config.ts +341 -0
  67. package/src/advisor/emission-guard.ts +172 -0
  68. package/src/advisor/index.ts +6 -0
  69. package/src/advisor/runtime.ts +1232 -0
  70. package/src/advisor/transcript-recorder.ts +159 -0
  71. package/src/advisor/watchdog.ts +135 -0
  72. package/src/async/index.ts +1 -0
  73. package/src/async/job-manager.ts +821 -0
  74. package/src/auto-thinking/classifier.ts +182 -0
  75. package/src/autolearn/controller.ts +152 -0
  76. package/src/autolearn/managed-skills.ts +255 -0
  77. package/src/autoresearch/command-resume.md +14 -0
  78. package/src/autoresearch/dashboard.ts +436 -0
  79. package/src/autoresearch/git.ts +331 -0
  80. package/src/autoresearch/helpers.ts +218 -0
  81. package/src/autoresearch/index.ts +541 -0
  82. package/src/autoresearch/prompt-setup.md +43 -0
  83. package/src/autoresearch/prompt.md +103 -0
  84. package/src/autoresearch/resume-message.md +10 -0
  85. package/src/autoresearch/state.ts +273 -0
  86. package/src/autoresearch/storage.ts +700 -0
  87. package/src/autoresearch/tools/init-experiment.ts +269 -0
  88. package/src/autoresearch/tools/log-experiment.ts +521 -0
  89. package/src/autoresearch/tools/run-experiment.ts +407 -0
  90. package/src/autoresearch/tools/update-notes.ts +109 -0
  91. package/src/autoresearch/types.ts +168 -0
  92. package/src/capability/context-file.ts +44 -0
  93. package/src/capability/extension-module.ts +34 -0
  94. package/src/capability/extension.ts +47 -0
  95. package/src/capability/fs.ts +117 -0
  96. package/src/capability/hook.ts +40 -0
  97. package/src/capability/index.ts +467 -0
  98. package/src/capability/instruction.ts +37 -0
  99. package/src/capability/mcp.ts +97 -0
  100. package/src/capability/prompt.ts +35 -0
  101. package/src/capability/rule-buckets.ts +66 -0
  102. package/src/capability/rule.ts +298 -0
  103. package/src/capability/settings.ts +34 -0
  104. package/src/capability/skill.ts +63 -0
  105. package/src/capability/slash-command.ts +40 -0
  106. package/src/capability/ssh.ts +41 -0
  107. package/src/capability/system-prompt.ts +34 -0
  108. package/src/capability/tool.ts +38 -0
  109. package/src/capability/types.ts +187 -0
  110. package/src/cleanse/agent.ts +226 -0
  111. package/src/cleanse/balance.ts +79 -0
  112. package/src/cleanse/checkers.ts +996 -0
  113. package/src/cleanse/index.ts +190 -0
  114. package/src/cleanse/loop.ts +51 -0
  115. package/src/cleanse/parsers.ts +726 -0
  116. package/src/cleanse/progress.ts +50 -0
  117. package/src/cleanse/prompts/assignment.md +47 -0
  118. package/src/cleanse/types.ts +72 -0
  119. package/src/cli/agents-cli.ts +138 -0
  120. package/src/cli/args.ts +420 -0
  121. package/src/cli/auth-broker-cli.ts +940 -0
  122. package/src/cli/auth-gateway-cli.ts +674 -0
  123. package/src/cli/bench-cli.ts +990 -0
  124. package/src/cli/classify-install-target.ts +76 -0
  125. package/src/cli/claude-trace-cli.ts +795 -0
  126. package/src/cli/commands/init-xdg.ts +27 -0
  127. package/src/cli/completion-gen.ts +550 -0
  128. package/src/cli/config-cli.ts +459 -0
  129. package/src/cli/dry-balance-cli.ts +864 -0
  130. package/src/cli/extension-flags.ts +48 -0
  131. package/src/cli/file-processor.ts +132 -0
  132. package/src/cli/flag-tables.ts +352 -0
  133. package/src/cli/gallery-cli.ts +272 -0
  134. package/src/cli/gallery-fixtures/agentic.ts +420 -0
  135. package/src/cli/gallery-fixtures/codeintel.ts +187 -0
  136. package/src/cli/gallery-fixtures/edit.ts +254 -0
  137. package/src/cli/gallery-fixtures/fs.ts +220 -0
  138. package/src/cli/gallery-fixtures/index.ts +40 -0
  139. package/src/cli/gallery-fixtures/interaction.ts +46 -0
  140. package/src/cli/gallery-fixtures/memory.ts +81 -0
  141. package/src/cli/gallery-fixtures/misc.ts +177 -0
  142. package/src/cli/gallery-fixtures/search.ts +135 -0
  143. package/src/cli/gallery-fixtures/shell.ts +241 -0
  144. package/src/cli/gallery-fixtures/types.ts +57 -0
  145. package/src/cli/gallery-fixtures/web.ts +158 -0
  146. package/src/cli/gallery-screenshot.ts +279 -0
  147. package/src/cli/gc-cli.ts +946 -0
  148. package/src/cli/grep-cli.ts +161 -0
  149. package/src/cli/grievances-cli.ts +256 -0
  150. package/src/cli/initial-message.ts +58 -0
  151. package/src/cli/models-cli.ts +388 -0
  152. package/src/cli/plugin-cli.ts +996 -0
  153. package/src/cli/profile-alias.ts +369 -0
  154. package/src/cli/profile-bootstrap.ts +233 -0
  155. package/src/cli/read-cli.ts +99 -0
  156. package/src/cli/session-picker.ts +93 -0
  157. package/src/cli/setup-cli.ts +320 -0
  158. package/src/cli/setup-model-picker.ts +43 -0
  159. package/src/cli/shell-cli.ts +176 -0
  160. package/src/cli/ssh-cli.ts +179 -0
  161. package/src/cli/startup-cwd.ts +58 -0
  162. package/src/cli/stats-cli.ts +229 -0
  163. package/src/cli/tiny-models-cli.ts +153 -0
  164. package/src/cli/ttsr-cli.ts +995 -0
  165. package/src/cli/update-cli.ts +1219 -0
  166. package/src/cli/usage-cli.ts +1084 -0
  167. package/src/cli/usage-error.ts +7 -0
  168. package/src/cli/web-search-cli.ts +144 -0
  169. package/src/cli/worktree-cli.ts +311 -0
  170. package/src/cli-commands.ts +166 -0
  171. package/src/cli.ts +407 -0
  172. package/src/collab/crypto.ts +63 -0
  173. package/src/collab/display-name.ts +13 -0
  174. package/src/collab/guest.ts +731 -0
  175. package/src/collab/host.ts +691 -0
  176. package/src/collab/protocol.ts +296 -0
  177. package/src/collab/relay-client.ts +282 -0
  178. package/src/collab/replication-shrink.ts +111 -0
  179. package/src/commands/acp.ts +33 -0
  180. package/src/commands/agents.ts +57 -0
  181. package/src/commands/auth-broker.ts +99 -0
  182. package/src/commands/auth-gateway.ts +69 -0
  183. package/src/commands/bench.ts +65 -0
  184. package/src/commands/cleanse.ts +45 -0
  185. package/src/commands/commit.ts +46 -0
  186. package/src/commands/complete.ts +66 -0
  187. package/src/commands/completions.ts +60 -0
  188. package/src/commands/config.ts +51 -0
  189. package/src/commands/dry-balance.ts +43 -0
  190. package/src/commands/gallery.ts +60 -0
  191. package/src/commands/gc.ts +46 -0
  192. package/src/commands/grep.ts +48 -0
  193. package/src/commands/grievances.ts +51 -0
  194. package/src/commands/install.ts +107 -0
  195. package/src/commands/join.ts +39 -0
  196. package/src/commands/launch.ts +212 -0
  197. package/src/commands/models.ts +60 -0
  198. package/src/commands/plugin.ts +78 -0
  199. package/src/commands/read.ts +38 -0
  200. package/src/commands/say.ts +145 -0
  201. package/src/commands/setup.ts +67 -0
  202. package/src/commands/shell.ts +29 -0
  203. package/src/commands/ssh.ts +60 -0
  204. package/src/commands/stats.ts +29 -0
  205. package/src/commands/tiny-models.ts +36 -0
  206. package/src/commands/token.ts +164 -0
  207. package/src/commands/ttsr.ts +125 -0
  208. package/src/commands/update.ts +33 -0
  209. package/src/commands/usage.ts +54 -0
  210. package/src/commands/web-search.ts +42 -0
  211. package/src/commands/worktree.ts +62 -0
  212. package/src/commit/agentic/agent.ts +322 -0
  213. package/src/commit/agentic/fallback.ts +96 -0
  214. package/src/commit/agentic/index.ts +382 -0
  215. package/src/commit/agentic/lock-files.ts +107 -0
  216. package/src/commit/agentic/prompts/analyze-file.md +22 -0
  217. package/src/commit/agentic/prompts/session-user.md +25 -0
  218. package/src/commit/agentic/prompts/split-confirm.md +1 -0
  219. package/src/commit/agentic/prompts/system.md +38 -0
  220. package/src/commit/agentic/state.ts +60 -0
  221. package/src/commit/agentic/tools/analyze-file.ts +148 -0
  222. package/src/commit/agentic/tools/git-file-diff.ts +191 -0
  223. package/src/commit/agentic/tools/git-hunk.ts +52 -0
  224. package/src/commit/agentic/tools/git-overview.ts +62 -0
  225. package/src/commit/agentic/tools/index.ts +54 -0
  226. package/src/commit/agentic/tools/propose-changelog.ts +147 -0
  227. package/src/commit/agentic/tools/propose-commit.ts +109 -0
  228. package/src/commit/agentic/tools/recent-commits.ts +81 -0
  229. package/src/commit/agentic/tools/schemas.ts +11 -0
  230. package/src/commit/agentic/tools/split-commit.ts +241 -0
  231. package/src/commit/agentic/topo-sort.ts +44 -0
  232. package/src/commit/agentic/trivial.ts +51 -0
  233. package/src/commit/agentic/validation.ts +183 -0
  234. package/src/commit/analysis/conventional.ts +64 -0
  235. package/src/commit/analysis/index.ts +4 -0
  236. package/src/commit/analysis/scope.ts +242 -0
  237. package/src/commit/analysis/summary.ts +107 -0
  238. package/src/commit/analysis/validation.ts +66 -0
  239. package/src/commit/changelog/detect.ts +40 -0
  240. package/src/commit/changelog/generate.ts +101 -0
  241. package/src/commit/changelog/index.ts +234 -0
  242. package/src/commit/changelog/parse.ts +44 -0
  243. package/src/commit/cli.ts +85 -0
  244. package/src/commit/git/diff.ts +148 -0
  245. package/src/commit/index.ts +5 -0
  246. package/src/commit/map-reduce/index.ts +69 -0
  247. package/src/commit/map-reduce/map-phase.ts +193 -0
  248. package/src/commit/map-reduce/reduce-phase.ts +49 -0
  249. package/src/commit/map-reduce/utils.ts +9 -0
  250. package/src/commit/message.ts +11 -0
  251. package/src/commit/model-selection.ts +95 -0
  252. package/src/commit/pipeline.ts +243 -0
  253. package/src/commit/prompts/analysis-system.md +148 -0
  254. package/src/commit/prompts/analysis-user.md +38 -0
  255. package/src/commit/prompts/changelog-system.md +50 -0
  256. package/src/commit/prompts/changelog-user.md +18 -0
  257. package/src/commit/prompts/file-observer-system.md +24 -0
  258. package/src/commit/prompts/file-observer-user.md +8 -0
  259. package/src/commit/prompts/reduce-system.md +50 -0
  260. package/src/commit/prompts/reduce-user.md +17 -0
  261. package/src/commit/prompts/summary-retry.md +3 -0
  262. package/src/commit/prompts/summary-system.md +38 -0
  263. package/src/commit/prompts/summary-user.md +13 -0
  264. package/src/commit/prompts/types-description.md +2 -0
  265. package/src/commit/shared-llm.ts +70 -0
  266. package/src/commit/types.ts +118 -0
  267. package/src/commit/utils/exclusions.ts +42 -0
  268. package/src/commit/utils.ts +58 -0
  269. package/src/config/api-key-resolver.ts +81 -0
  270. package/src/config/append-only-context-mode.ts +76 -0
  271. package/src/config/config-file.ts +347 -0
  272. package/src/config/file-lock.ts +164 -0
  273. package/src/config/inline-tool-descriptors-mode.ts +26 -0
  274. package/src/config/keybindings.ts +688 -0
  275. package/src/config/mcp-schema.json +247 -0
  276. package/src/config/model-discovery.ts +999 -0
  277. package/src/config/model-registry.ts +2725 -0
  278. package/src/config/model-resolver.ts +2068 -0
  279. package/src/config/model-roles.ts +113 -0
  280. package/src/config/models-config-schema-bundle.ts +313 -0
  281. package/src/config/models-config-schema.ts +14 -0
  282. package/src/config/models-config.ts +130 -0
  283. package/src/config/prompt-templates.ts +205 -0
  284. package/src/config/provider-globals.ts +25 -0
  285. package/src/config/resolve-config-value.ts +94 -0
  286. package/src/config/service-tier.ts +141 -0
  287. package/src/config/settings-schema.ts +5751 -0
  288. package/src/config/settings.ts +2369 -0
  289. package/src/config.ts +242 -0
  290. package/src/cursor.ts +513 -0
  291. package/src/dap/client.ts +1043 -0
  292. package/src/dap/config.ts +480 -0
  293. package/src/dap/defaults.json +212 -0
  294. package/src/dap/index.ts +4 -0
  295. package/src/dap/session.ts +1841 -0
  296. package/src/dap/types.ts +611 -0
  297. package/src/debug/index.ts +584 -0
  298. package/src/debug/log-formatting.ts +58 -0
  299. package/src/debug/log-viewer.ts +966 -0
  300. package/src/debug/profiler.ts +168 -0
  301. package/src/debug/protocol-probe.ts +267 -0
  302. package/src/debug/raw-sse-buffer.ts +421 -0
  303. package/src/debug/raw-sse.ts +312 -0
  304. package/src/debug/remote-debugger.ts +151 -0
  305. package/src/debug/report-bundle.ts +411 -0
  306. package/src/debug/system-info.ts +111 -0
  307. package/src/debug/terminal-info.ts +124 -0
  308. package/src/discovery/agents-md.ts +67 -0
  309. package/src/discovery/agents.ts +230 -0
  310. package/src/discovery/at-imports.ts +273 -0
  311. package/src/discovery/builtin-defaults.ts +39 -0
  312. package/src/discovery/builtin-rules/go-add-cleanup.md +33 -0
  313. package/src/discovery/builtin-rules/go-bench-loop.md +36 -0
  314. package/src/discovery/builtin-rules/go-exp-promoted.md +40 -0
  315. package/src/discovery/builtin-rules/go-ioutil.md +37 -0
  316. package/src/discovery/builtin-rules/go-join-hostport.md +30 -0
  317. package/src/discovery/builtin-rules/go-new-expr.md +44 -0
  318. package/src/discovery/builtin-rules/go-rand-v2.md +41 -0
  319. package/src/discovery/builtin-rules/go-range-int.md +45 -0
  320. package/src/discovery/builtin-rules/index.ts +74 -0
  321. package/src/discovery/builtin-rules/rs-box-leak.md +49 -0
  322. package/src/discovery/builtin-rules/rs-future-prelude.md +24 -0
  323. package/src/discovery/builtin-rules/rs-lazylock.md +52 -0
  324. package/src/discovery/builtin-rules/rs-match-ergonomics.md +68 -0
  325. package/src/discovery/builtin-rules/rs-parking-lot.md +45 -0
  326. package/src/discovery/builtin-rules/rs-result-type.md +20 -0
  327. package/src/discovery/builtin-rules/ts-bare-catch.md +39 -0
  328. package/src/discovery/builtin-rules/ts-import-type.md +43 -0
  329. package/src/discovery/builtin-rules/ts-no-any.md +66 -0
  330. package/src/discovery/builtin-rules/ts-no-deprecated-leftovers.md +45 -0
  331. package/src/discovery/builtin-rules/ts-no-dynamic-import.md +40 -0
  332. package/src/discovery/builtin-rules/ts-no-inline-cast-access.md +55 -0
  333. package/src/discovery/builtin-rules/ts-no-local-is-record.md +48 -0
  334. package/src/discovery/builtin-rules/ts-no-return-type.md +45 -0
  335. package/src/discovery/builtin-rules/ts-no-test-timers.md +55 -0
  336. package/src/discovery/builtin-rules/ts-no-tiny-functions.md +51 -0
  337. package/src/discovery/builtin-rules/ts-promise-with-resolvers.md +66 -0
  338. package/src/discovery/builtin-rules/ts-redundant-clear-guard.md +75 -0
  339. package/src/discovery/builtin-rules/ts-set-map.md +28 -0
  340. package/src/discovery/builtin.ts +935 -0
  341. package/src/discovery/claude-plugins.ts +624 -0
  342. package/src/discovery/claude.ts +588 -0
  343. package/src/discovery/cline.ts +83 -0
  344. package/src/discovery/codex.ts +540 -0
  345. package/src/discovery/cursor.ts +220 -0
  346. package/src/discovery/gemini.ts +383 -0
  347. package/src/discovery/github.ts +337 -0
  348. package/src/discovery/helpers.ts +1159 -0
  349. package/src/discovery/index.ts +81 -0
  350. package/src/discovery/mcp-json.ts +172 -0
  351. package/src/discovery/omp-extension-roots.ts +213 -0
  352. package/src/discovery/omp-plugins.ts +387 -0
  353. package/src/discovery/opencode.ts +441 -0
  354. package/src/discovery/plugin-dir-roots.ts +28 -0
  355. package/src/discovery/ssh.ts +153 -0
  356. package/src/discovery/substitute-plugin-root.ts +77 -0
  357. package/src/discovery/vscode.ts +105 -0
  358. package/src/discovery/windsurf.ts +147 -0
  359. package/src/edit/apply-patch/index.ts +87 -0
  360. package/src/edit/apply-patch/parser.ts +174 -0
  361. package/src/edit/diff.ts +999 -0
  362. package/src/edit/file-snapshot-store.ts +148 -0
  363. package/src/edit/hashline/block-resolver.ts +33 -0
  364. package/src/edit/hashline/diff.ts +356 -0
  365. package/src/edit/hashline/execute.ts +280 -0
  366. package/src/edit/hashline/filesystem.ts +223 -0
  367. package/src/edit/hashline/index.ts +5 -0
  368. package/src/edit/hashline/noop-loop-guard.ts +99 -0
  369. package/src/edit/hashline/params.ts +12 -0
  370. package/src/edit/index.ts +676 -0
  371. package/src/edit/modes/apply-patch.lark +19 -0
  372. package/src/edit/modes/apply-patch.ts +53 -0
  373. package/src/edit/modes/patch.ts +1958 -0
  374. package/src/edit/modes/replace.ts +1137 -0
  375. package/src/edit/normalize.ts +345 -0
  376. package/src/edit/notebook.ts +242 -0
  377. package/src/edit/read-file.ts +25 -0
  378. package/src/edit/renderer.ts +998 -0
  379. package/src/edit/snapshot-details.ts +77 -0
  380. package/src/edit/streaming.ts +698 -0
  381. package/src/eval/agent-bridge.ts +224 -0
  382. package/src/eval/backend-helpers.ts +48 -0
  383. package/src/eval/backend.ts +71 -0
  384. package/src/eval/bridge-timeout.ts +62 -0
  385. package/src/eval/budget-bridge.ts +48 -0
  386. package/src/eval/completion-bridge.ts +211 -0
  387. package/src/eval/concurrency-bridge.ts +34 -0
  388. package/src/eval/executor-base.ts +504 -0
  389. package/src/eval/idle-timeout.ts +91 -0
  390. package/src/eval/index.ts +6 -0
  391. package/src/eval/jl/executor.ts +540 -0
  392. package/src/eval/jl/index.ts +54 -0
  393. package/src/eval/jl/kernel.ts +236 -0
  394. package/src/eval/jl/prelude.jl +736 -0
  395. package/src/eval/jl/prelude.ts +3 -0
  396. package/src/eval/jl/runner.jl +666 -0
  397. package/src/eval/jl/runtime.ts +118 -0
  398. package/src/eval/js/context-manager.ts +701 -0
  399. package/src/eval/js/executor.ts +175 -0
  400. package/src/eval/js/index.ts +40 -0
  401. package/src/eval/js/process-entry.ts +31 -0
  402. package/src/eval/js/shared/helpers.ts +170 -0
  403. package/src/eval/js/shared/indirect-eval.ts +30 -0
  404. package/src/eval/js/shared/local-module-loader.ts +364 -0
  405. package/src/eval/js/shared/prelude.ts +2 -0
  406. package/src/eval/js/shared/prelude.txt +294 -0
  407. package/src/eval/js/shared/rewrite-imports.ts +550 -0
  408. package/src/eval/js/shared/runtime.ts +590 -0
  409. package/src/eval/js/shared/types.ts +18 -0
  410. package/src/eval/js/tool-bridge.ts +163 -0
  411. package/src/eval/js/worker-core.ts +380 -0
  412. package/src/eval/js/worker-entry.ts +37 -0
  413. package/src/eval/js/worker-protocol.ts +47 -0
  414. package/src/eval/kernel-base.ts +569 -0
  415. package/src/eval/py/display.ts +71 -0
  416. package/src/eval/py/executor.ts +603 -0
  417. package/src/eval/py/index.ts +57 -0
  418. package/src/eval/py/kernel.ts +234 -0
  419. package/src/eval/py/prelude.py +672 -0
  420. package/src/eval/py/prelude.ts +3 -0
  421. package/src/eval/py/runner.py +1388 -0
  422. package/src/eval/py/runtime.ts +276 -0
  423. package/src/eval/py/spawn-options.ts +139 -0
  424. package/src/eval/py/tool-bridge.ts +181 -0
  425. package/src/eval/rb/executor.ts +504 -0
  426. package/src/eval/rb/index.ts +54 -0
  427. package/src/eval/rb/kernel.ts +231 -0
  428. package/src/eval/rb/prelude.rb +552 -0
  429. package/src/eval/rb/prelude.ts +3 -0
  430. package/src/eval/rb/runner.rb +581 -0
  431. package/src/eval/rb/runtime.ts +132 -0
  432. package/src/eval/runtime-env.ts +104 -0
  433. package/src/eval/session-id.ts +8 -0
  434. package/src/eval/types.ts +48 -0
  435. package/src/exa/index.ts +2 -0
  436. package/src/exa/mcp-client.ts +370 -0
  437. package/src/exa/types.ts +69 -0
  438. package/src/exec/bash-executor.ts +627 -0
  439. package/src/exec/direnv.ts +145 -0
  440. package/src/exec/exec.ts +53 -0
  441. package/src/exec/non-interactive-env.ts +118 -0
  442. package/src/export/custom-share.ts +65 -0
  443. package/src/export/html/args.ts +20 -0
  444. package/src/export/html/index.ts +313 -0
  445. package/src/export/html/share-loader.js +102 -0
  446. package/src/export/html/template.css +1355 -0
  447. package/src/export/html/template.html +55 -0
  448. package/src/export/html/template.js +1671 -0
  449. package/src/export/html/tool-views.generated.js +35 -0
  450. package/src/export/html/vendor/highlight.min.js +1213 -0
  451. package/src/export/html/vendor/marked.min.js +6 -0
  452. package/src/export/html/web-palette.ts +126 -0
  453. package/src/export/share.ts +682 -0
  454. package/src/export/ttsr.ts +590 -0
  455. package/src/extensibility/custom-commands/bundled/ci-green/index.ts +54 -0
  456. package/src/extensibility/custom-commands/bundled/review/index.ts +698 -0
  457. package/src/extensibility/custom-commands/index.ts +2 -0
  458. package/src/extensibility/custom-commands/loader.ts +242 -0
  459. package/src/extensibility/custom-commands/types.ts +119 -0
  460. package/src/extensibility/custom-tools/index.ts +7 -0
  461. package/src/extensibility/custom-tools/loader.ts +301 -0
  462. package/src/extensibility/custom-tools/types.ts +286 -0
  463. package/src/extensibility/custom-tools/wrapper.ts +50 -0
  464. package/src/extensibility/extensions/compact-handler.ts +40 -0
  465. package/src/extensibility/extensions/get-commands-handler.ts +78 -0
  466. package/src/extensibility/extensions/index.ts +16 -0
  467. package/src/extensibility/extensions/load-errors.ts +13 -0
  468. package/src/extensibility/extensions/loader.ts +624 -0
  469. package/src/extensibility/extensions/managed-timers.ts +83 -0
  470. package/src/extensibility/extensions/model-api.ts +39 -0
  471. package/src/extensibility/extensions/runner.ts +1209 -0
  472. package/src/extensibility/extensions/types.ts +1526 -0
  473. package/src/extensibility/extensions/wrapper.ts +377 -0
  474. package/src/extensibility/hooks/index.ts +6 -0
  475. package/src/extensibility/hooks/loader.ts +244 -0
  476. package/src/extensibility/hooks/runner.ts +425 -0
  477. package/src/extensibility/hooks/tool-wrapper.ts +124 -0
  478. package/src/extensibility/hooks/types.ts +612 -0
  479. package/src/extensibility/legacy-pi-ai-shim.ts +140 -0
  480. package/src/extensibility/legacy-pi-coding-agent-shim.ts +1384 -0
  481. package/src/extensibility/legacy-pi-tui-shim.ts +43 -0
  482. package/src/extensibility/plugins/bun-git-cache.ts +91 -0
  483. package/src/extensibility/plugins/doctor.ts +65 -0
  484. package/src/extensibility/plugins/git-url.ts +367 -0
  485. package/src/extensibility/plugins/index.ts +9 -0
  486. package/src/extensibility/plugins/installer.ts +201 -0
  487. package/src/extensibility/plugins/legacy-pi-compat.ts +2532 -0
  488. package/src/extensibility/plugins/legacy-pi-virtual-modules.d.ts +4 -0
  489. package/src/extensibility/plugins/loader.ts +535 -0
  490. package/src/extensibility/plugins/manager.ts +1142 -0
  491. package/src/extensibility/plugins/marketplace/cache.ts +136 -0
  492. package/src/extensibility/plugins/marketplace/fetcher.ts +316 -0
  493. package/src/extensibility/plugins/marketplace/index.ts +6 -0
  494. package/src/extensibility/plugins/marketplace/manager.ts +926 -0
  495. package/src/extensibility/plugins/marketplace/registry.ts +196 -0
  496. package/src/extensibility/plugins/marketplace/source-resolver.ts +147 -0
  497. package/src/extensibility/plugins/marketplace/types.ts +192 -0
  498. package/src/extensibility/plugins/marketplace-auto-update.ts +49 -0
  499. package/src/extensibility/plugins/parser.ts +107 -0
  500. package/src/extensibility/plugins/runtime-config.ts +9 -0
  501. package/src/extensibility/plugins/types.ts +194 -0
  502. package/src/extensibility/session-handler-types.ts +21 -0
  503. package/src/extensibility/shared-events.ts +401 -0
  504. package/src/extensibility/skills.ts +511 -0
  505. package/src/extensibility/slash-commands.ts +131 -0
  506. package/src/extensibility/tool-event-input.ts +80 -0
  507. package/src/extensibility/tool-proxy.ts +28 -0
  508. package/src/extensibility/typebox.ts +958 -0
  509. package/src/extensibility/utils.ts +184 -0
  510. package/src/goals/index.ts +3 -0
  511. package/src/goals/runtime.ts +521 -0
  512. package/src/goals/state.ts +37 -0
  513. package/src/goals/tools/goal-tool.ts +251 -0
  514. package/src/hindsight/backend.ts +354 -0
  515. package/src/hindsight/bank.ts +156 -0
  516. package/src/hindsight/client.ts +680 -0
  517. package/src/hindsight/config.ts +193 -0
  518. package/src/hindsight/content.ts +266 -0
  519. package/src/hindsight/index.ts +8 -0
  520. package/src/hindsight/mental-models.ts +429 -0
  521. package/src/hindsight/seeds.json +32 -0
  522. package/src/hindsight/state.ts +550 -0
  523. package/src/hindsight/transcript.ts +71 -0
  524. package/src/index.ts +66 -0
  525. package/src/internal-urls/agent-protocol.ts +180 -0
  526. package/src/internal-urls/artifact-protocol.ts +151 -0
  527. package/src/internal-urls/docs-index.ts +102 -0
  528. package/src/internal-urls/filesystem-resource.ts +34 -0
  529. package/src/internal-urls/history-protocol.ts +198 -0
  530. package/src/internal-urls/index.ts +27 -0
  531. package/src/internal-urls/issue-pr-protocol.ts +594 -0
  532. package/src/internal-urls/json-query.ts +126 -0
  533. package/src/internal-urls/local-protocol.ts +470 -0
  534. package/src/internal-urls/mcp-protocol.ts +165 -0
  535. package/src/internal-urls/memory-protocol.ts +347 -0
  536. package/src/internal-urls/omp-protocol.ts +94 -0
  537. package/src/internal-urls/parse.ts +103 -0
  538. package/src/internal-urls/registry-helpers.ts +132 -0
  539. package/src/internal-urls/router.ts +150 -0
  540. package/src/internal-urls/rule-protocol.ts +45 -0
  541. package/src/internal-urls/skill-protocol.ts +117 -0
  542. package/src/internal-urls/ssh-protocol.ts +368 -0
  543. package/src/internal-urls/types.ts +196 -0
  544. package/src/internal-urls/vault-protocol.ts +940 -0
  545. package/src/internal-urls/xd-protocol.ts +46 -0
  546. package/src/irc/bus.ts +380 -0
  547. package/src/jsonrpc/message-framing.ts +142 -0
  548. package/src/launch/broker.ts +1134 -0
  549. package/src/launch/client.ts +350 -0
  550. package/src/launch/paths.ts +17 -0
  551. package/src/launch/presence.ts +82 -0
  552. package/src/launch/protocol.ts +396 -0
  553. package/src/launch/spawn-options.ts +17 -0
  554. package/src/launch/terminal-output.ts +46 -0
  555. package/src/lib/xai-http.ts +150 -0
  556. package/src/live/attestation.ts +91 -0
  557. package/src/live/controller.ts +517 -0
  558. package/src/live/prompts/agent-final-message.md +3 -0
  559. package/src/live/prompts/live-instructions.md +23 -0
  560. package/src/live/protocol.ts +233 -0
  561. package/src/live/transport.ts +422 -0
  562. package/src/live/visualizer.ts +214 -0
  563. package/src/live/voices.ts +18 -0
  564. package/src/lsp/client.ts +1429 -0
  565. package/src/lsp/clients/biome-client.ts +263 -0
  566. package/src/lsp/clients/index.ts +50 -0
  567. package/src/lsp/clients/lsp-linter-client.ts +85 -0
  568. package/src/lsp/clients/swiftlint-client.ts +120 -0
  569. package/src/lsp/config.ts +549 -0
  570. package/src/lsp/defaults.json +499 -0
  571. package/src/lsp/deferred-diagnostics.ts +66 -0
  572. package/src/lsp/diagnostics-ledger.ts +51 -0
  573. package/src/lsp/edits.ts +288 -0
  574. package/src/lsp/format-options.ts +119 -0
  575. package/src/lsp/index.ts +2766 -0
  576. package/src/lsp/lspmux.ts +233 -0
  577. package/src/lsp/render.ts +668 -0
  578. package/src/lsp/startup-events.ts +13 -0
  579. package/src/lsp/types.ts +453 -0
  580. package/src/lsp/utils.ts +718 -0
  581. package/src/main.ts +1647 -0
  582. package/src/markit/NOTICE +32 -0
  583. package/src/markit/converters/docx.ts +56 -0
  584. package/src/markit/converters/epub.ts +136 -0
  585. package/src/markit/converters/mammoth.d.ts +24 -0
  586. package/src/markit/converters/pdf/columns.ts +103 -0
  587. package/src/markit/converters/pdf/extract.ts +598 -0
  588. package/src/markit/converters/pdf/grid.ts +780 -0
  589. package/src/markit/converters/pdf/headers.ts +106 -0
  590. package/src/markit/converters/pdf/index.ts +146 -0
  591. package/src/markit/converters/pdf/render.ts +501 -0
  592. package/src/markit/converters/pdf/types.ts +84 -0
  593. package/src/markit/converters/pptx.ts +325 -0
  594. package/src/markit/converters/xlsx.ts +173 -0
  595. package/src/markit/index.ts +2 -0
  596. package/src/markit/registry.ts +59 -0
  597. package/src/markit/types.ts +35 -0
  598. package/src/mcp/client.ts +511 -0
  599. package/src/mcp/config-writer.ts +377 -0
  600. package/src/mcp/config.ts +381 -0
  601. package/src/mcp/index.ts +29 -0
  602. package/src/mcp/json-rpc.ts +122 -0
  603. package/src/mcp/loader.ts +125 -0
  604. package/src/mcp/manager.ts +1419 -0
  605. package/src/mcp/oauth-credentials.ts +104 -0
  606. package/src/mcp/oauth-discovery.ts +587 -0
  607. package/src/mcp/oauth-flow.ts +820 -0
  608. package/src/mcp/render.ts +214 -0
  609. package/src/mcp/smithery-auth.ts +108 -0
  610. package/src/mcp/smithery-connect.ts +154 -0
  611. package/src/mcp/smithery-registry.ts +500 -0
  612. package/src/mcp/startup-events.ts +116 -0
  613. package/src/mcp/timeout.ts +59 -0
  614. package/src/mcp/tool-bridge.ts +691 -0
  615. package/src/mcp/tool-cache.ts +117 -0
  616. package/src/mcp/transports/http.ts +523 -0
  617. package/src/mcp/transports/index.ts +7 -0
  618. package/src/mcp/transports/sse.ts +377 -0
  619. package/src/mcp/transports/stdio.ts +903 -0
  620. package/src/mcp/types.ts +437 -0
  621. package/src/memories/index.ts +1434 -0
  622. package/src/memories/storage.ts +578 -0
  623. package/src/memory-backend/index.ts +18 -0
  624. package/src/memory-backend/local-backend.ts +47 -0
  625. package/src/memory-backend/off-backend.ts +25 -0
  626. package/src/memory-backend/resolve.ts +25 -0
  627. package/src/memory-backend/runtime.ts +66 -0
  628. package/src/memory-backend/tool-names.ts +2 -0
  629. package/src/memory-backend/types.ts +166 -0
  630. package/src/mnemopi/backend.ts +629 -0
  631. package/src/mnemopi/config.ts +267 -0
  632. package/src/mnemopi/embed-client.ts +246 -0
  633. package/src/mnemopi/embed-protocol.ts +35 -0
  634. package/src/mnemopi/embed-worker.ts +114 -0
  635. package/src/mnemopi/index.ts +3 -0
  636. package/src/mnemopi/state.ts +906 -0
  637. package/src/modes/acp/acp-agent.ts +2577 -0
  638. package/src/modes/acp/acp-client-bridge.ts +154 -0
  639. package/src/modes/acp/acp-event-mapper.ts +1084 -0
  640. package/src/modes/acp/acp-mode.ts +48 -0
  641. package/src/modes/acp/index.ts +2 -0
  642. package/src/modes/acp/terminal-auth.ts +37 -0
  643. package/src/modes/components/advisor-config.ts +635 -0
  644. package/src/modes/components/advisor-message.ts +109 -0
  645. package/src/modes/components/agent-dashboard.ts +1252 -0
  646. package/src/modes/components/agent-hub.ts +648 -0
  647. package/src/modes/components/agent-transcript-viewer.ts +649 -0
  648. package/src/modes/components/ask-dialog.ts +975 -0
  649. package/src/modes/components/assistant-message.ts +972 -0
  650. package/src/modes/components/background-tan-message.ts +36 -0
  651. package/src/modes/components/bash-execution.ts +233 -0
  652. package/src/modes/components/bordered-loader.ts +41 -0
  653. package/src/modes/components/btw-panel.ts +124 -0
  654. package/src/modes/components/cache-invalidation-marker.ts +110 -0
  655. package/src/modes/components/chat-block.ts +111 -0
  656. package/src/modes/components/chat-transcript-builder.ts +495 -0
  657. package/src/modes/components/collab-prompt-message.ts +32 -0
  658. package/src/modes/components/compaction-summary-message.ts +221 -0
  659. package/src/modes/components/copy-selector.ts +218 -0
  660. package/src/modes/components/countdown-timer.ts +75 -0
  661. package/src/modes/components/custom-editor.ts +1027 -0
  662. package/src/modes/components/custom-message.ts +70 -0
  663. package/src/modes/components/diff.ts +254 -0
  664. package/src/modes/components/dynamic-border.ts +37 -0
  665. package/src/modes/components/error-banner.ts +33 -0
  666. package/src/modes/components/eval-execution.ts +169 -0
  667. package/src/modes/components/execution-shared.ts +101 -0
  668. package/src/modes/components/extensions/extension-dashboard.ts +492 -0
  669. package/src/modes/components/extensions/extension-list.ts +507 -0
  670. package/src/modes/components/extensions/index.ts +9 -0
  671. package/src/modes/components/extensions/inspector-panel.ts +321 -0
  672. package/src/modes/components/extensions/state-manager.ts +648 -0
  673. package/src/modes/components/extensions/types.ts +186 -0
  674. package/src/modes/components/footer.ts +276 -0
  675. package/src/modes/components/history-search.ts +268 -0
  676. package/src/modes/components/hook-editor.ts +213 -0
  677. package/src/modes/components/hook-input.ts +87 -0
  678. package/src/modes/components/hook-message.ts +67 -0
  679. package/src/modes/components/hook-selector.ts +691 -0
  680. package/src/modes/components/index.ts +42 -0
  681. package/src/modes/components/keybinding-hints.ts +65 -0
  682. package/src/modes/components/late-diagnostics-message.ts +60 -0
  683. package/src/modes/components/login-dialog.ts +197 -0
  684. package/src/modes/components/logout-account-selector.ts +130 -0
  685. package/src/modes/components/mcp-add-wizard.ts +1413 -0
  686. package/src/modes/components/message-frame.ts +98 -0
  687. package/src/modes/components/model-browser.ts +872 -0
  688. package/src/modes/components/model-hub.ts +2011 -0
  689. package/src/modes/components/model-picker.ts +233 -0
  690. package/src/modes/components/move-overlay.ts +293 -0
  691. package/src/modes/components/oauth-selector.ts +474 -0
  692. package/src/modes/components/omfg-panel.ts +141 -0
  693. package/src/modes/components/overlay-box.ts +109 -0
  694. package/src/modes/components/pause-screen.ts +208 -0
  695. package/src/modes/components/plan-review-overlay.ts +1226 -0
  696. package/src/modes/components/plan-toc.ts +138 -0
  697. package/src/modes/components/plugin-selector.ts +100 -0
  698. package/src/modes/components/plugin-settings.ts +745 -0
  699. package/src/modes/components/queue-mode-selector.ts +61 -0
  700. package/src/modes/components/read-tool-group.ts +678 -0
  701. package/src/modes/components/reset-usage-selector.ts +161 -0
  702. package/src/modes/components/segment-track.ts +89 -0
  703. package/src/modes/components/select-list-mouse-routing.ts +35 -0
  704. package/src/modes/components/selector-helpers.ts +129 -0
  705. package/src/modes/components/session-account-selector.ts +62 -0
  706. package/src/modes/components/session-selector.ts +1019 -0
  707. package/src/modes/components/settings-defs.ts +267 -0
  708. package/src/modes/components/settings-selector.ts +1445 -0
  709. package/src/modes/components/show-images-selector.ts +50 -0
  710. package/src/modes/components/skill-message.ts +110 -0
  711. package/src/modes/components/snapcompact-shape-preview-doc.md +14 -0
  712. package/src/modes/components/snapcompact-shape-preview.ts +192 -0
  713. package/src/modes/components/status-line/component.ts +1516 -0
  714. package/src/modes/components/status-line/context-thresholds.ts +86 -0
  715. package/src/modes/components/status-line/git-utils.ts +42 -0
  716. package/src/modes/components/status-line/index.ts +5 -0
  717. package/src/modes/components/status-line/presets.ts +106 -0
  718. package/src/modes/components/status-line/segments.ts +710 -0
  719. package/src/modes/components/status-line/separators.ts +55 -0
  720. package/src/modes/components/status-line/types.ts +159 -0
  721. package/src/modes/components/theme-selector.ts +68 -0
  722. package/src/modes/components/thinking-selector.ts +57 -0
  723. package/src/modes/components/tiny-title-download-progress.ts +90 -0
  724. package/src/modes/components/tips.txt +26 -0
  725. package/src/modes/components/todo-reminder.ts +43 -0
  726. package/src/modes/components/tool-execution.ts +1356 -0
  727. package/src/modes/components/transcript-container.ts +527 -0
  728. package/src/modes/components/tree-selector.ts +1008 -0
  729. package/src/modes/components/ttsr-notification.ts +123 -0
  730. package/src/modes/components/usage-row.ts +47 -0
  731. package/src/modes/components/user-message-selector.ts +227 -0
  732. package/src/modes/components/user-message.ts +167 -0
  733. package/src/modes/components/visual-truncate.ts +63 -0
  734. package/src/modes/components/welcome.ts +578 -0
  735. package/src/modes/controllers/btw-controller.ts +198 -0
  736. package/src/modes/controllers/command-controller-shared.ts +109 -0
  737. package/src/modes/controllers/command-controller.ts +1993 -0
  738. package/src/modes/controllers/event-controller.ts +1781 -0
  739. package/src/modes/controllers/extension-ui-controller.ts +1242 -0
  740. package/src/modes/controllers/input-controller.ts +2004 -0
  741. package/src/modes/controllers/live-command-controller.ts +260 -0
  742. package/src/modes/controllers/mcp-command-controller.ts +2403 -0
  743. package/src/modes/controllers/omfg-controller.ts +287 -0
  744. package/src/modes/controllers/omfg-rule.ts +647 -0
  745. package/src/modes/controllers/selector-controller.ts +1968 -0
  746. package/src/modes/controllers/session-focus-controller.ts +117 -0
  747. package/src/modes/controllers/ssh-command-controller.ts +385 -0
  748. package/src/modes/controllers/streaming-reveal.ts +399 -0
  749. package/src/modes/controllers/tan-command-controller.ts +229 -0
  750. package/src/modes/controllers/todo-command-controller.ts +487 -0
  751. package/src/modes/controllers/tool-args-reveal.ts +591 -0
  752. package/src/modes/data/emojis.json +1 -0
  753. package/src/modes/emoji-autocomplete.ts +285 -0
  754. package/src/modes/github-ref-autocomplete.ts +75 -0
  755. package/src/modes/gradient-highlight.ts +99 -0
  756. package/src/modes/image-references.ts +137 -0
  757. package/src/modes/index.ts +10 -0
  758. package/src/modes/interactive-mode.ts +4957 -0
  759. package/src/modes/internal-url-autocomplete.ts +158 -0
  760. package/src/modes/loop-limit.ts +192 -0
  761. package/src/modes/magic-keyword-boundary.ts +23 -0
  762. package/src/modes/magic-keywords.ts +42 -0
  763. package/src/modes/markdown-prose.ts +247 -0
  764. package/src/modes/oauth-manual-input.ts +69 -0
  765. package/src/modes/orchestrate.ts +43 -0
  766. package/src/modes/print-mode.ts +265 -0
  767. package/src/modes/prompt-action-autocomplete.ts +322 -0
  768. package/src/modes/queue-input.ts +132 -0
  769. package/src/modes/rpc/host-tools.ts +204 -0
  770. package/src/modes/rpc/host-uris.ts +235 -0
  771. package/src/modes/rpc/rpc-client.ts +1195 -0
  772. package/src/modes/rpc/rpc-frame.ts +316 -0
  773. package/src/modes/rpc/rpc-input.ts +38 -0
  774. package/src/modes/rpc/rpc-messages.ts +127 -0
  775. package/src/modes/rpc/rpc-mode.ts +1504 -0
  776. package/src/modes/rpc/rpc-subagents.ts +265 -0
  777. package/src/modes/rpc/rpc-types.ts +533 -0
  778. package/src/modes/running-subagent-badge.ts +13 -0
  779. package/src/modes/runtime-init.ts +144 -0
  780. package/src/modes/session-observer-registry.ts +218 -0
  781. package/src/modes/session-teardown.ts +82 -0
  782. package/src/modes/setup-version.ts +11 -0
  783. package/src/modes/setup-wizard/index.ts +103 -0
  784. package/src/modes/setup-wizard/lazy.ts +16 -0
  785. package/src/modes/setup-wizard/scenes/glyph.ts +103 -0
  786. package/src/modes/setup-wizard/scenes/model.ts +132 -0
  787. package/src/modes/setup-wizard/scenes/outro.ts +35 -0
  788. package/src/modes/setup-wizard/scenes/providers.ts +105 -0
  789. package/src/modes/setup-wizard/scenes/sign-in.ts +312 -0
  790. package/src/modes/setup-wizard/scenes/splash.ts +201 -0
  791. package/src/modes/setup-wizard/scenes/theme.ts +330 -0
  792. package/src/modes/setup-wizard/scenes/types.ts +65 -0
  793. package/src/modes/setup-wizard/scenes/web-search.ts +153 -0
  794. package/src/modes/setup-wizard/startup-splash.ts +107 -0
  795. package/src/modes/setup-wizard/wizard-overlay.ts +335 -0
  796. package/src/modes/shared.ts +49 -0
  797. package/src/modes/skill-command.ts +91 -0
  798. package/src/modes/theme/dark.json +95 -0
  799. package/src/modes/theme/defaults/alabaster.json +93 -0
  800. package/src/modes/theme/defaults/amethyst.json +96 -0
  801. package/src/modes/theme/defaults/anthracite.json +93 -0
  802. package/src/modes/theme/defaults/basalt.json +91 -0
  803. package/src/modes/theme/defaults/birch.json +95 -0
  804. package/src/modes/theme/defaults/dark-abyss.json +91 -0
  805. package/src/modes/theme/defaults/dark-arctic.json +104 -0
  806. package/src/modes/theme/defaults/dark-aurora.json +95 -0
  807. package/src/modes/theme/defaults/dark-catppuccin.json +107 -0
  808. package/src/modes/theme/defaults/dark-cavern.json +91 -0
  809. package/src/modes/theme/defaults/dark-copper.json +95 -0
  810. package/src/modes/theme/defaults/dark-cosmos.json +90 -0
  811. package/src/modes/theme/defaults/dark-cyberpunk.json +102 -0
  812. package/src/modes/theme/defaults/dark-dracula.json +98 -0
  813. package/src/modes/theme/defaults/dark-eclipse.json +91 -0
  814. package/src/modes/theme/defaults/dark-ember.json +95 -0
  815. package/src/modes/theme/defaults/dark-equinox.json +90 -0
  816. package/src/modes/theme/defaults/dark-forest.json +96 -0
  817. package/src/modes/theme/defaults/dark-github.json +105 -0
  818. package/src/modes/theme/defaults/dark-gruvbox.json +112 -0
  819. package/src/modes/theme/defaults/dark-lavender.json +95 -0
  820. package/src/modes/theme/defaults/dark-lunar.json +89 -0
  821. package/src/modes/theme/defaults/dark-midnight.json +95 -0
  822. package/src/modes/theme/defaults/dark-monochrome.json +94 -0
  823. package/src/modes/theme/defaults/dark-monokai.json +98 -0
  824. package/src/modes/theme/defaults/dark-nebula.json +90 -0
  825. package/src/modes/theme/defaults/dark-nord.json +97 -0
  826. package/src/modes/theme/defaults/dark-ocean.json +101 -0
  827. package/src/modes/theme/defaults/dark-one.json +100 -0
  828. package/src/modes/theme/defaults/dark-poimandres.json +143 -0
  829. package/src/modes/theme/defaults/dark-rainforest.json +91 -0
  830. package/src/modes/theme/defaults/dark-reef.json +91 -0
  831. package/src/modes/theme/defaults/dark-retro.json +92 -0
  832. package/src/modes/theme/defaults/dark-rose-pine.json +96 -0
  833. package/src/modes/theme/defaults/dark-sakura.json +95 -0
  834. package/src/modes/theme/defaults/dark-slate.json +95 -0
  835. package/src/modes/theme/defaults/dark-solarized.json +97 -0
  836. package/src/modes/theme/defaults/dark-solstice.json +90 -0
  837. package/src/modes/theme/defaults/dark-starfall.json +91 -0
  838. package/src/modes/theme/defaults/dark-sunset.json +99 -0
  839. package/src/modes/theme/defaults/dark-swamp.json +90 -0
  840. package/src/modes/theme/defaults/dark-synthwave.json +103 -0
  841. package/src/modes/theme/defaults/dark-taiga.json +91 -0
  842. package/src/modes/theme/defaults/dark-terminal.json +95 -0
  843. package/src/modes/theme/defaults/dark-tokyo-night.json +101 -0
  844. package/src/modes/theme/defaults/dark-tundra.json +91 -0
  845. package/src/modes/theme/defaults/dark-twilight.json +91 -0
  846. package/src/modes/theme/defaults/dark-volcanic.json +91 -0
  847. package/src/modes/theme/defaults/graphite.json +92 -0
  848. package/src/modes/theme/defaults/index.ts +199 -0
  849. package/src/modes/theme/defaults/light-arctic.json +107 -0
  850. package/src/modes/theme/defaults/light-aurora-day.json +91 -0
  851. package/src/modes/theme/defaults/light-canyon.json +91 -0
  852. package/src/modes/theme/defaults/light-catppuccin.json +106 -0
  853. package/src/modes/theme/defaults/light-cirrus.json +90 -0
  854. package/src/modes/theme/defaults/light-coral.json +95 -0
  855. package/src/modes/theme/defaults/light-cyberpunk.json +96 -0
  856. package/src/modes/theme/defaults/light-dawn.json +90 -0
  857. package/src/modes/theme/defaults/light-dunes.json +91 -0
  858. package/src/modes/theme/defaults/light-eucalyptus.json +95 -0
  859. package/src/modes/theme/defaults/light-forest.json +100 -0
  860. package/src/modes/theme/defaults/light-frost.json +95 -0
  861. package/src/modes/theme/defaults/light-github.json +115 -0
  862. package/src/modes/theme/defaults/light-glacier.json +91 -0
  863. package/src/modes/theme/defaults/light-gruvbox.json +108 -0
  864. package/src/modes/theme/defaults/light-haze.json +90 -0
  865. package/src/modes/theme/defaults/light-honeycomb.json +95 -0
  866. package/src/modes/theme/defaults/light-lagoon.json +91 -0
  867. package/src/modes/theme/defaults/light-lavender.json +95 -0
  868. package/src/modes/theme/defaults/light-meadow.json +91 -0
  869. package/src/modes/theme/defaults/light-mint.json +95 -0
  870. package/src/modes/theme/defaults/light-monochrome.json +101 -0
  871. package/src/modes/theme/defaults/light-ocean.json +99 -0
  872. package/src/modes/theme/defaults/light-one.json +99 -0
  873. package/src/modes/theme/defaults/light-opal.json +91 -0
  874. package/src/modes/theme/defaults/light-orchard.json +91 -0
  875. package/src/modes/theme/defaults/light-paper.json +95 -0
  876. package/src/modes/theme/defaults/light-poimandres.json +143 -0
  877. package/src/modes/theme/defaults/light-prism.json +90 -0
  878. package/src/modes/theme/defaults/light-retro.json +98 -0
  879. package/src/modes/theme/defaults/light-sand.json +95 -0
  880. package/src/modes/theme/defaults/light-savanna.json +91 -0
  881. package/src/modes/theme/defaults/light-solarized.json +102 -0
  882. package/src/modes/theme/defaults/light-soleil.json +90 -0
  883. package/src/modes/theme/defaults/light-sunset.json +99 -0
  884. package/src/modes/theme/defaults/light-synthwave.json +98 -0
  885. package/src/modes/theme/defaults/light-tokyo-night.json +111 -0
  886. package/src/modes/theme/defaults/light-wetland.json +91 -0
  887. package/src/modes/theme/defaults/light-zenith.json +89 -0
  888. package/src/modes/theme/defaults/limestone.json +94 -0
  889. package/src/modes/theme/defaults/mahogany.json +97 -0
  890. package/src/modes/theme/defaults/marble.json +93 -0
  891. package/src/modes/theme/defaults/obsidian.json +91 -0
  892. package/src/modes/theme/defaults/onyx.json +91 -0
  893. package/src/modes/theme/defaults/pearl.json +93 -0
  894. package/src/modes/theme/defaults/porcelain.json +91 -0
  895. package/src/modes/theme/defaults/quartz.json +96 -0
  896. package/src/modes/theme/defaults/sandstone.json +95 -0
  897. package/src/modes/theme/defaults/titanium.json +90 -0
  898. package/src/modes/theme/light.json +93 -0
  899. package/src/modes/theme/mermaid-cache.ts +92 -0
  900. package/src/modes/theme/shimmer.ts +305 -0
  901. package/src/modes/theme/theme-schema.json +463 -0
  902. package/src/modes/theme/theme.ts +3019 -0
  903. package/src/modes/turn-budget.ts +31 -0
  904. package/src/modes/types.ts +479 -0
  905. package/src/modes/ultrathink.ts +42 -0
  906. package/src/modes/utils/context-usage.ts +518 -0
  907. package/src/modes/utils/copy-targets.ts +378 -0
  908. package/src/modes/utils/hotkeys-markdown.ts +63 -0
  909. package/src/modes/utils/interactive-context-helpers.ts +30 -0
  910. package/src/modes/utils/keybinding-matchers.ts +86 -0
  911. package/src/modes/utils/tools-markdown.ts +31 -0
  912. package/src/modes/utils/transcript-render-helpers.ts +253 -0
  913. package/src/modes/utils/ui-helpers.ts +963 -0
  914. package/src/modes/warp-events.ts +232 -0
  915. package/src/modes/workflow.ts +49 -0
  916. package/src/plan-mode/approved-plan.ts +194 -0
  917. package/src/plan-mode/model-transition.ts +51 -0
  918. package/src/plan-mode/plan-files.ts +40 -0
  919. package/src/plan-mode/plan-handoff.ts +37 -0
  920. package/src/plan-mode/plan-protection.ts +31 -0
  921. package/src/plan-mode/state.ts +6 -0
  922. package/src/priority.json +60 -0
  923. package/src/prompts/advisor/active-repo-watchdog.md +6 -0
  924. package/src/prompts/advisor/advise-tool.md +3 -0
  925. package/src/prompts/advisor/context-files.md +8 -0
  926. package/src/prompts/advisor/system.md +98 -0
  927. package/src/prompts/agents/designer.md +74 -0
  928. package/src/prompts/agents/frontmatter.md +12 -0
  929. package/src/prompts/agents/init.md +33 -0
  930. package/src/prompts/agents/librarian.md +119 -0
  931. package/src/prompts/agents/reviewer.md +139 -0
  932. package/src/prompts/agents/scout.md +58 -0
  933. package/src/prompts/agents/task.md +17 -0
  934. package/src/prompts/bench/cache-prefix-chunk.md +1 -0
  935. package/src/prompts/bench/cache-prefix.md +3 -0
  936. package/src/prompts/bench/cache-suffix.md +1 -0
  937. package/src/prompts/bench.md +6 -0
  938. package/src/prompts/ci-green-request.md +36 -0
  939. package/src/prompts/dry-balance-bench.md +8 -0
  940. package/src/prompts/goals/goal-budget-limit.md +16 -0
  941. package/src/prompts/goals/goal-continuation.md +28 -0
  942. package/src/prompts/goals/goal-mode-active.md +23 -0
  943. package/src/prompts/goals/goal-mode-context.md +4 -0
  944. package/src/prompts/goals/goal-todo-context.md +12 -0
  945. package/src/prompts/goals/guided-goal-interview.md +43 -0
  946. package/src/prompts/memories/consolidation.md +30 -0
  947. package/src/prompts/memories/consolidation_system.md +4 -0
  948. package/src/prompts/memories/read-path.md +17 -0
  949. package/src/prompts/memories/stage_one_input.md +6 -0
  950. package/src/prompts/memories/stage_one_system.md +21 -0
  951. package/src/prompts/review-custom-request.md +21 -0
  952. package/src/prompts/review-headless-request.md +16 -0
  953. package/src/prompts/review-request.md +68 -0
  954. package/src/prompts/skills/autoload.md +8 -0
  955. package/src/prompts/skills/user-invocation.md +11 -0
  956. package/src/prompts/steering/parent-irc.md +5 -0
  957. package/src/prompts/steering/user-interjection.md +6 -0
  958. package/src/prompts/system/active-repo-context.md +4 -0
  959. package/src/prompts/system/agent-creation-architect.md +50 -0
  960. package/src/prompts/system/agent-creation-user.md +6 -0
  961. package/src/prompts/system/auto-continue.md +1 -0
  962. package/src/prompts/system/auto-thinking-difficulty-local.md +14 -0
  963. package/src/prompts/system/auto-thinking-difficulty.md +12 -0
  964. package/src/prompts/system/autolearn-guidance-learn.md +1 -0
  965. package/src/prompts/system/autolearn-guidance.md +7 -0
  966. package/src/prompts/system/autolearn-nudge-autocontinue.md +5 -0
  967. package/src/prompts/system/background-tan-dispatch.md +8 -0
  968. package/src/prompts/system/btw-user.md +8 -0
  969. package/src/prompts/system/commit-message-system.md +14 -0
  970. package/src/prompts/system/computer-safety.md +14 -0
  971. package/src/prompts/system/custom-system-prompt.md +64 -0
  972. package/src/prompts/system/eager-task.md +7 -0
  973. package/src/prompts/system/eager-todo.md +18 -0
  974. package/src/prompts/system/empty-stop-retry.md +4 -0
  975. package/src/prompts/system/gemini-tool-call-reminder.md +9 -0
  976. package/src/prompts/system/interrupted-thinking.md +7 -0
  977. package/src/prompts/system/irc-autoreply.md +6 -0
  978. package/src/prompts/system/irc-incoming.md +9 -0
  979. package/src/prompts/system/manual-continue.md +7 -0
  980. package/src/prompts/system/mcp-xdev-guidance.md +11 -0
  981. package/src/prompts/system/memory-consolidation-system.md +8 -0
  982. package/src/prompts/system/memory-extraction-system.md +26 -0
  983. package/src/prompts/system/mid-run-todo-nudge.md +3 -0
  984. package/src/prompts/system/omfg-user.md +50 -0
  985. package/src/prompts/system/orchestrate-notice.md +40 -0
  986. package/src/prompts/system/personalities/default.md +18 -0
  987. package/src/prompts/system/personalities/friendly.md +17 -0
  988. package/src/prompts/system/personalities/pragmatic.md +15 -0
  989. package/src/prompts/system/plan-mode-active.md +125 -0
  990. package/src/prompts/system/plan-mode-approved.md +22 -0
  991. package/src/prompts/system/plan-mode-compact-instructions.md +17 -0
  992. package/src/prompts/system/plan-mode-reference.md +10 -0
  993. package/src/prompts/system/plan-mode-subagent.md +33 -0
  994. package/src/prompts/system/plan-mode-tool-decision-reminder.md +9 -0
  995. package/src/prompts/system/plan-yolo-handoff.md +5 -0
  996. package/src/prompts/system/prewalk-checklist.md +7 -0
  997. package/src/prompts/system/prewalk-continue.md +1 -0
  998. package/src/prompts/system/prewalk-plan.md +13 -0
  999. package/src/prompts/system/project-prompt.md +61 -0
  1000. package/src/prompts/system/recap-user.md +9 -0
  1001. package/src/prompts/system/resolve-device-reminder.md +3 -0
  1002. package/src/prompts/system/rewind-report.md +6 -0
  1003. package/src/prompts/system/side-channel-no-tools.md +3 -0
  1004. package/src/prompts/system/snapcompact-context-frames-note.md +1 -0
  1005. package/src/prompts/system/snapcompact-context-stub.md +1 -0
  1006. package/src/prompts/system/snapcompact-system-frames-note.md +1 -0
  1007. package/src/prompts/system/snapcompact-system-stub.md +1 -0
  1008. package/src/prompts/system/snapcompact-toolresult-note.md +1 -0
  1009. package/src/prompts/system/speech-rewrite.md +15 -0
  1010. package/src/prompts/system/subagent-async-pending.md +6 -0
  1011. package/src/prompts/system/subagent-system-prompt.md +73 -0
  1012. package/src/prompts/system/subagent-user-prompt.md +3 -0
  1013. package/src/prompts/system/subagent-yield-reminder.md +23 -0
  1014. package/src/prompts/system/system-prompt.md +283 -0
  1015. package/src/prompts/system/tan-context-switch.md +17 -0
  1016. package/src/prompts/system/task-label.md +23 -0
  1017. package/src/prompts/system/thinking-loop-redirect.md +10 -0
  1018. package/src/prompts/system/title-marker-instruction.md +1 -0
  1019. package/src/prompts/system/title-system.md +16 -0
  1020. package/src/prompts/system/tool-call-loop-redirect.md +8 -0
  1021. package/src/prompts/system/ttsr-interrupt.md +7 -0
  1022. package/src/prompts/system/ttsr-tool-reminder.md +5 -0
  1023. package/src/prompts/system/ultrathink-notice.md +3 -0
  1024. package/src/prompts/system/unexpected-stop-classifier.md +17 -0
  1025. package/src/prompts/system/unexpected-stop-retry.md +4 -0
  1026. package/src/prompts/system/vibe-mode-active.md +26 -0
  1027. package/src/prompts/system/web-search.md +25 -0
  1028. package/src/prompts/system/workflow-notice.md +112 -0
  1029. package/src/prompts/system/xdev-mount-notice.md +20 -0
  1030. package/src/prompts/tools/apply-patch.md +65 -0
  1031. package/src/prompts/tools/ask.md +22 -0
  1032. package/src/prompts/tools/ast-edit.md +11 -0
  1033. package/src/prompts/tools/ast-grep.md +19 -0
  1034. package/src/prompts/tools/async-result.md +8 -0
  1035. package/src/prompts/tools/bash.md +25 -0
  1036. package/src/prompts/tools/browser.md +28 -0
  1037. package/src/prompts/tools/checkpoint.md +15 -0
  1038. package/src/prompts/tools/computer.md +26 -0
  1039. package/src/prompts/tools/debug.md +3 -0
  1040. package/src/prompts/tools/eval.md +45 -0
  1041. package/src/prompts/tools/github.md +22 -0
  1042. package/src/prompts/tools/glob.md +15 -0
  1043. package/src/prompts/tools/goal.md +11 -0
  1044. package/src/prompts/tools/grep.md +12 -0
  1045. package/src/prompts/tools/hub.md +34 -0
  1046. package/src/prompts/tools/image-attachment-describe-system.md +8 -0
  1047. package/src/prompts/tools/image-attachment-describe.md +10 -0
  1048. package/src/prompts/tools/image-gen.md +7 -0
  1049. package/src/prompts/tools/inspect-image-system.md +20 -0
  1050. package/src/prompts/tools/inspect-image.md +22 -0
  1051. package/src/prompts/tools/learn.md +7 -0
  1052. package/src/prompts/tools/lsp-late-diagnostic.md +8 -0
  1053. package/src/prompts/tools/lsp.md +19 -0
  1054. package/src/prompts/tools/manage-skill.md +9 -0
  1055. package/src/prompts/tools/memory-edit.md +12 -0
  1056. package/src/prompts/tools/patch.md +57 -0
  1057. package/src/prompts/tools/read.md +27 -0
  1058. package/src/prompts/tools/recall.md +7 -0
  1059. package/src/prompts/tools/reflect.md +5 -0
  1060. package/src/prompts/tools/replace.md +29 -0
  1061. package/src/prompts/tools/retain.md +6 -0
  1062. package/src/prompts/tools/rewind.md +14 -0
  1063. package/src/prompts/tools/task-async-contract.md +1 -0
  1064. package/src/prompts/tools/task-summary.md +20 -0
  1065. package/src/prompts/tools/task.md +83 -0
  1066. package/src/prompts/tools/todo.md +42 -0
  1067. package/src/prompts/tools/vibe-kill.md +3 -0
  1068. package/src/prompts/tools/vibe-list.md +3 -0
  1069. package/src/prompts/tools/vibe-send.md +9 -0
  1070. package/src/prompts/tools/vibe-spawn.md +10 -0
  1071. package/src/prompts/tools/vibe-turn-result.md +19 -0
  1072. package/src/prompts/tools/vibe-wait.md +8 -0
  1073. package/src/prompts/tools/web-search.md +8 -0
  1074. package/src/prompts/tools/write.md +14 -0
  1075. package/src/registry/agent-lifecycle.ts +455 -0
  1076. package/src/registry/agent-registry.ts +217 -0
  1077. package/src/registry/persisted-agents.ts +98 -0
  1078. package/src/sdk.ts +3553 -0
  1079. package/src/secrets/index.ts +246 -0
  1080. package/src/secrets/obfuscator.ts +2574 -0
  1081. package/src/secrets/regex.ts +21 -0
  1082. package/src/session/acp-permission-gate.ts +165 -0
  1083. package/src/session/agent-session-events.ts +66 -0
  1084. package/src/session/agent-session-types.ts +346 -0
  1085. package/src/session/agent-session.ts +8406 -0
  1086. package/src/session/agent-storage.ts +805 -0
  1087. package/src/session/artifacts.ts +154 -0
  1088. package/src/session/async-job-delivery.ts +82 -0
  1089. package/src/session/auth-broker-config.ts +92 -0
  1090. package/src/session/auth-storage.ts +25 -0
  1091. package/src/session/bash-runner.ts +326 -0
  1092. package/src/session/blob-store.ts +295 -0
  1093. package/src/session/checkpoint-entries.ts +81 -0
  1094. package/src/session/client-bridge.ts +85 -0
  1095. package/src/session/codex-auto-reset.ts +202 -0
  1096. package/src/session/compact-modes.ts +105 -0
  1097. package/src/session/eval-runner.ts +217 -0
  1098. package/src/session/exit-diagnostics.ts +310 -0
  1099. package/src/session/history-storage.ts +327 -0
  1100. package/src/session/indexed-session-storage.ts +544 -0
  1101. package/src/session/irc-bridge.ts +203 -0
  1102. package/src/session/messages.ts +1280 -0
  1103. package/src/session/model-controls.ts +750 -0
  1104. package/src/session/prewalk.ts +257 -0
  1105. package/src/session/provider-image-budget.ts +86 -0
  1106. package/src/session/queued-messages.ts +99 -0
  1107. package/src/session/redis-session-storage.ts +257 -0
  1108. package/src/session/retry-fallback-chains.ts +455 -0
  1109. package/src/session/role-models.ts +85 -0
  1110. package/src/session/session-advisors.ts +1754 -0
  1111. package/src/session/session-context.ts +554 -0
  1112. package/src/session/session-dump-format.ts +216 -0
  1113. package/src/session/session-entries.ts +260 -0
  1114. package/src/session/session-handoff.ts +308 -0
  1115. package/src/session/session-history-format.ts +459 -0
  1116. package/src/session/session-listing.ts +715 -0
  1117. package/src/session/session-loader.ts +280 -0
  1118. package/src/session/session-maintenance.ts +2983 -0
  1119. package/src/session/session-manager.ts +2557 -0
  1120. package/src/session/session-memory.ts +222 -0
  1121. package/src/session/session-metadata.ts +53 -0
  1122. package/src/session/session-migrations.ts +78 -0
  1123. package/src/session/session-paths.ts +222 -0
  1124. package/src/session/session-persistence.ts +293 -0
  1125. package/src/session/session-provider-boundary.ts +306 -0
  1126. package/src/session/session-stats.ts +293 -0
  1127. package/src/session/session-storage.ts +734 -0
  1128. package/src/session/session-title-slot.ts +141 -0
  1129. package/src/session/session-tools.ts +1226 -0
  1130. package/src/session/session-workspace.ts +53 -0
  1131. package/src/session/settings-stream-fn.ts +74 -0
  1132. package/src/session/shake-types.ts +43 -0
  1133. package/src/session/snapcompact-inline.ts +545 -0
  1134. package/src/session/snapcompact-savings-journal.ts +113 -0
  1135. package/src/session/sql-session-storage.ts +374 -0
  1136. package/src/session/stream-guards.ts +417 -0
  1137. package/src/session/streaming-output.ts +1459 -0
  1138. package/src/session/todo-tracker.ts +380 -0
  1139. package/src/session/tool-choice-queue.ts +305 -0
  1140. package/src/session/ttsr-coordinator.ts +496 -0
  1141. package/src/session/turn-persistence.ts +142 -0
  1142. package/src/session/turn-recovery.ts +1728 -0
  1143. package/src/session/unexpected-stop-classifier.ts +132 -0
  1144. package/src/session/yield-queue.ts +183 -0
  1145. package/src/slash-commands/acp-builtins.ts +70 -0
  1146. package/src/slash-commands/available-commands.ts +105 -0
  1147. package/src/slash-commands/builtin-registry.ts +2982 -0
  1148. package/src/slash-commands/helpers/active-oauth-account.ts +80 -0
  1149. package/src/slash-commands/helpers/collab-qrcode.ts +28 -0
  1150. package/src/slash-commands/helpers/context-report.ts +66 -0
  1151. package/src/slash-commands/helpers/format.ts +46 -0
  1152. package/src/slash-commands/helpers/logout.ts +108 -0
  1153. package/src/slash-commands/helpers/marketplace-manager.ts +25 -0
  1154. package/src/slash-commands/helpers/mcp.ts +533 -0
  1155. package/src/slash-commands/helpers/parse.ts +85 -0
  1156. package/src/slash-commands/helpers/reset-usage.ts +66 -0
  1157. package/src/slash-commands/helpers/session-pin.ts +44 -0
  1158. package/src/slash-commands/helpers/ssh.ts +196 -0
  1159. package/src/slash-commands/helpers/stats-dashboard.ts +85 -0
  1160. package/src/slash-commands/helpers/todo.ts +285 -0
  1161. package/src/slash-commands/helpers/usage-report.ts +198 -0
  1162. package/src/slash-commands/marketplace-install-parser.ts +99 -0
  1163. package/src/slash-commands/types.ts +139 -0
  1164. package/src/ssh/config-writer.ts +183 -0
  1165. package/src/ssh/connection-manager.ts +667 -0
  1166. package/src/ssh/file-transfer.ts +214 -0
  1167. package/src/ssh/sshfs-mount.ts +163 -0
  1168. package/src/ssh/utils.ts +51 -0
  1169. package/src/startup-splash.ts +19 -0
  1170. package/src/stt/asr-client.ts +401 -0
  1171. package/src/stt/asr-protocol.ts +65 -0
  1172. package/src/stt/asr-worker.ts +603 -0
  1173. package/src/stt/downloader.ts +142 -0
  1174. package/src/stt/endpointer.ts +259 -0
  1175. package/src/stt/index.ts +6 -0
  1176. package/src/stt/models.ts +150 -0
  1177. package/src/stt/sherpa-runtime.ts +71 -0
  1178. package/src/stt/stt-controller.ts +320 -0
  1179. package/src/stt/submit-trigger.ts +74 -0
  1180. package/src/subprocess/worker-client.ts +463 -0
  1181. package/src/subprocess/worker-runtime.ts +494 -0
  1182. package/src/system-prompt.ts +894 -0
  1183. package/src/task/agents.ts +168 -0
  1184. package/src/task/commands.ts +132 -0
  1185. package/src/task/discovery.ts +145 -0
  1186. package/src/task/executor.ts +3129 -0
  1187. package/src/task/index.ts +1519 -0
  1188. package/src/task/isolation-ownership.ts +106 -0
  1189. package/src/task/isolation-runner.ts +413 -0
  1190. package/src/task/label.ts +40 -0
  1191. package/src/task/name-generator.ts +1577 -0
  1192. package/src/task/omp-command.ts +26 -0
  1193. package/src/task/output-manager.ts +115 -0
  1194. package/src/task/parallel.ts +221 -0
  1195. package/src/task/persisted-revive.ts +141 -0
  1196. package/src/task/prewalk.ts +6 -0
  1197. package/src/task/prompt-policy.ts +8 -0
  1198. package/src/task/provider-concurrency.ts +100 -0
  1199. package/src/task/render.ts +1814 -0
  1200. package/src/task/renderer.ts +14 -0
  1201. package/src/task/repair-args.ts +118 -0
  1202. package/src/task/spawn-policy.ts +58 -0
  1203. package/src/task/structured-subagent.ts +649 -0
  1204. package/src/task/subprocess-tool-registry.ts +88 -0
  1205. package/src/task/types.ts +551 -0
  1206. package/src/task/worktree.ts +967 -0
  1207. package/src/task/yield-assembly.ts +198 -0
  1208. package/src/telemetry-export.ts +500 -0
  1209. package/src/thinking.ts +364 -0
  1210. package/src/tiny/device.ts +111 -0
  1211. package/src/tiny/dtype.ts +101 -0
  1212. package/src/tiny/message-preproc.ts +155 -0
  1213. package/src/tiny/models.ts +268 -0
  1214. package/src/tiny/text.ts +278 -0
  1215. package/src/tiny/title-client.ts +460 -0
  1216. package/src/tiny/title-protocol.ts +56 -0
  1217. package/src/tiny/worker.ts +354 -0
  1218. package/src/tools/acp-bridge.ts +81 -0
  1219. package/src/tools/approval.ts +245 -0
  1220. package/src/tools/ask.ts +1459 -0
  1221. package/src/tools/ast-edit.ts +718 -0
  1222. package/src/tools/ast-grep.ts +520 -0
  1223. package/src/tools/auto-generated-guard.ts +335 -0
  1224. package/src/tools/bash-interactive.ts +435 -0
  1225. package/src/tools/bash-interceptor.ts +67 -0
  1226. package/src/tools/bash-pty-selection.ts +14 -0
  1227. package/src/tools/bash-skill-urls.ts +335 -0
  1228. package/src/tools/bash.ts +1762 -0
  1229. package/src/tools/browser/aria/aria-snapshot.bundle.txt +7 -0
  1230. package/src/tools/browser/aria/aria-snapshot.ts +131 -0
  1231. package/src/tools/browser/attach.ts +194 -0
  1232. package/src/tools/browser/cmux/cmux-tab.ts +1400 -0
  1233. package/src/tools/browser/cmux/rpc.ts +206 -0
  1234. package/src/tools/browser/cmux/socket-client.ts +445 -0
  1235. package/src/tools/browser/launch.ts +788 -0
  1236. package/src/tools/browser/readable.ts +112 -0
  1237. package/src/tools/browser/registry.ts +287 -0
  1238. package/src/tools/browser/render.ts +226 -0
  1239. package/src/tools/browser/run-cancellation.ts +131 -0
  1240. package/src/tools/browser/run-output.ts +76 -0
  1241. package/src/tools/browser/tab-protocol.ts +115 -0
  1242. package/src/tools/browser/tab-supervisor.ts +1040 -0
  1243. package/src/tools/browser/tab-worker-entry.ts +29 -0
  1244. package/src/tools/browser/tab-worker.ts +1842 -0
  1245. package/src/tools/browser.ts +457 -0
  1246. package/src/tools/builtin-names.ts +66 -0
  1247. package/src/tools/checkpoint.ts +150 -0
  1248. package/src/tools/computer/exposure.ts +38 -0
  1249. package/src/tools/computer/protocol.ts +28 -0
  1250. package/src/tools/computer/supervisor.ts +306 -0
  1251. package/src/tools/computer/worker-entry.ts +34 -0
  1252. package/src/tools/computer/worker.ts +131 -0
  1253. package/src/tools/computer-renderer.ts +108 -0
  1254. package/src/tools/computer.ts +516 -0
  1255. package/src/tools/conflict-detect.ts +815 -0
  1256. package/src/tools/context.ts +46 -0
  1257. package/src/tools/debug.ts +1121 -0
  1258. package/src/tools/default-renderer.ts +139 -0
  1259. package/src/tools/essential-tools.ts +46 -0
  1260. package/src/tools/eval-backends.ts +34 -0
  1261. package/src/tools/eval-format/index.ts +24 -0
  1262. package/src/tools/eval-format/javascript.ts +952 -0
  1263. package/src/tools/eval-format/julia.ts +446 -0
  1264. package/src/tools/eval-format/python.ts +544 -0
  1265. package/src/tools/eval-format/ruby.ts +380 -0
  1266. package/src/tools/eval-render.ts +784 -0
  1267. package/src/tools/eval.ts +774 -0
  1268. package/src/tools/fetch.ts +1889 -0
  1269. package/src/tools/file-recorder.ts +35 -0
  1270. package/src/tools/fs-cache-invalidation.ts +28 -0
  1271. package/src/tools/gh-cache-invalidation.ts +175 -0
  1272. package/src/tools/gh-format.ts +12 -0
  1273. package/src/tools/gh-renderer.ts +484 -0
  1274. package/src/tools/gh.ts +3959 -0
  1275. package/src/tools/github-cache.ts +663 -0
  1276. package/src/tools/glob.ts +682 -0
  1277. package/src/tools/grep.ts +1858 -0
  1278. package/src/tools/grouped-file-output.ts +210 -0
  1279. package/src/tools/hub/index.ts +579 -0
  1280. package/src/tools/hub/jobs.ts +714 -0
  1281. package/src/tools/hub/launch.ts +579 -0
  1282. package/src/tools/hub/messaging.ts +735 -0
  1283. package/src/tools/hub/types.ts +117 -0
  1284. package/src/tools/image-gen.ts +1689 -0
  1285. package/src/tools/image-providers.ts +50 -0
  1286. package/src/tools/index.ts +691 -0
  1287. package/src/tools/inspect-image-renderer.ts +133 -0
  1288. package/src/tools/inspect-image.ts +290 -0
  1289. package/src/tools/json-tree.ts +260 -0
  1290. package/src/tools/jtd-to-json-schema.ts +219 -0
  1291. package/src/tools/jtd-to-typescript.ts +136 -0
  1292. package/src/tools/jtd-utils.ts +102 -0
  1293. package/src/tools/learn.ts +141 -0
  1294. package/src/tools/list-limit.ts +40 -0
  1295. package/src/tools/manage-skill.ts +102 -0
  1296. package/src/tools/match-line-format.ts +20 -0
  1297. package/src/tools/memory-edit.ts +61 -0
  1298. package/src/tools/memory-recall.ts +102 -0
  1299. package/src/tools/memory-reflect.ts +88 -0
  1300. package/src/tools/memory-render.ts +211 -0
  1301. package/src/tools/memory-retain.ts +89 -0
  1302. package/src/tools/output-meta.ts +845 -0
  1303. package/src/tools/output-schema-validator.ts +307 -0
  1304. package/src/tools/path-utils.ts +1381 -0
  1305. package/src/tools/plan-mode-guard.ts +155 -0
  1306. package/src/tools/puppeteer/00_stealth_tampering.txt +44 -0
  1307. package/src/tools/puppeteer/01_stealth_activity.txt +80 -0
  1308. package/src/tools/puppeteer/02_stealth_hairline.txt +57 -0
  1309. package/src/tools/puppeteer/03_stealth_botd.txt +380 -0
  1310. package/src/tools/puppeteer/04_stealth_iframe.txt +174 -0
  1311. package/src/tools/puppeteer/05_stealth_webgl.txt +233 -0
  1312. package/src/tools/puppeteer/06_stealth_screen.txt +260 -0
  1313. package/src/tools/puppeteer/07_stealth_fonts.txt +99 -0
  1314. package/src/tools/puppeteer/08_stealth_audio.txt +63 -0
  1315. package/src/tools/puppeteer/09_stealth_locale.txt +51 -0
  1316. package/src/tools/puppeteer/10_stealth_plugins.txt +212 -0
  1317. package/src/tools/puppeteer/11_stealth_hardware.txt +59 -0
  1318. package/src/tools/puppeteer/12_stealth_codecs.txt +42 -0
  1319. package/src/tools/puppeteer/13_stealth_worker.txt +235 -0
  1320. package/src/tools/read.ts +3742 -0
  1321. package/src/tools/render-utils.ts +924 -0
  1322. package/src/tools/renderers.ts +133 -0
  1323. package/src/tools/report-tool-issue.ts +568 -0
  1324. package/src/tools/resolve.ts +423 -0
  1325. package/src/tools/review.ts +103 -0
  1326. package/src/tools/shell-tokenize.ts +83 -0
  1327. package/src/tools/sqlite-reader.ts +884 -0
  1328. package/src/tools/terminal-output.ts +141 -0
  1329. package/src/tools/todo.ts +1226 -0
  1330. package/src/tools/tool-errors.ts +62 -0
  1331. package/src/tools/tool-result.ts +102 -0
  1332. package/src/tools/tool-timeouts.ts +37 -0
  1333. package/src/tools/tts.ts +266 -0
  1334. package/src/tools/vibe.ts +607 -0
  1335. package/src/tools/write.ts +1640 -0
  1336. package/src/tools/xdev.ts +508 -0
  1337. package/src/tools/yield.ts +486 -0
  1338. package/src/tts/downloader.ts +64 -0
  1339. package/src/tts/index.ts +10 -0
  1340. package/src/tts/models.ts +137 -0
  1341. package/src/tts/runtime.ts +21 -0
  1342. package/src/tts/speakable.ts +392 -0
  1343. package/src/tts/speech-enhancer.ts +206 -0
  1344. package/src/tts/streaming-player.ts +120 -0
  1345. package/src/tts/tts-client.ts +475 -0
  1346. package/src/tts/tts-protocol.ts +69 -0
  1347. package/src/tts/tts-worker.ts +434 -0
  1348. package/src/tts/vocalizer.ts +419 -0
  1349. package/src/tts/wav.ts +58 -0
  1350. package/src/tui/code-cell.ts +268 -0
  1351. package/src/tui/file-list.ts +55 -0
  1352. package/src/tui/hyperlink.ts +178 -0
  1353. package/src/tui/index.ts +13 -0
  1354. package/src/tui/output-block.ts +268 -0
  1355. package/src/tui/status-line.ts +54 -0
  1356. package/src/tui/tree-list.ts +172 -0
  1357. package/src/tui/types.ts +15 -0
  1358. package/src/tui/utils.ts +103 -0
  1359. package/src/tui/width-aware-text.ts +58 -0
  1360. package/src/utils/active-repo-context.ts +143 -0
  1361. package/src/utils/block-context.ts +312 -0
  1362. package/src/utils/changelog.ts +232 -0
  1363. package/src/utils/clipboard.ts +327 -0
  1364. package/src/utils/command-args.ts +76 -0
  1365. package/src/utils/commit-message-generator.ts +148 -0
  1366. package/src/utils/cpuprofile.ts +235 -0
  1367. package/src/utils/edit-mode.ts +61 -0
  1368. package/src/utils/enhanced-paste.ts +230 -0
  1369. package/src/utils/event-bus.ts +33 -0
  1370. package/src/utils/external-editor.ts +78 -0
  1371. package/src/utils/fetch-timeout.ts +10 -0
  1372. package/src/utils/file-display-mode.ts +44 -0
  1373. package/src/utils/file-mentions.ts +293 -0
  1374. package/src/utils/git.ts +2425 -0
  1375. package/src/utils/image-loading.ts +231 -0
  1376. package/src/utils/image-resize.ts +420 -0
  1377. package/src/utils/image-vision-fallback.ts +196 -0
  1378. package/src/utils/inspect-image-mode.ts +39 -0
  1379. package/src/utils/ipc.ts +38 -0
  1380. package/src/utils/jj.ts +416 -0
  1381. package/src/utils/lang-from-path.ts +251 -0
  1382. package/src/utils/local-date.ts +7 -0
  1383. package/src/utils/mac-file-urls.applescript +37 -0
  1384. package/src/utils/markit-cache.ts +166 -0
  1385. package/src/utils/markit.ts +223 -0
  1386. package/src/utils/mupdf-wasm-embed.ts +12 -0
  1387. package/src/utils/open.ts +126 -0
  1388. package/src/utils/profile-tree.ts +111 -0
  1389. package/src/utils/prompt-path.ts +3 -0
  1390. package/src/utils/qrcode.ts +535 -0
  1391. package/src/utils/sample-profile.ts +437 -0
  1392. package/src/utils/session-color.ts +142 -0
  1393. package/src/utils/shell-snapshot-fn-env.sh +63 -0
  1394. package/src/utils/shell-snapshot.ts +316 -0
  1395. package/src/utils/sixel.ts +69 -0
  1396. package/src/utils/thinking-display.ts +163 -0
  1397. package/src/utils/title-generator.ts +597 -0
  1398. package/src/utils/token-rate.ts +72 -0
  1399. package/src/utils/tool-choice.ts +63 -0
  1400. package/src/utils/tools-manager.ts +411 -0
  1401. package/src/utils/turndown.ts +83 -0
  1402. package/src/utils/zip.ts +1106 -0
  1403. package/src/vibe/runtime.ts +1540 -0
  1404. package/src/vibe/state.ts +4 -0
  1405. package/src/web/kagi.ts +304 -0
  1406. package/src/web/parallel.ts +354 -0
  1407. package/src/web/scrapers/artifacthub.ts +207 -0
  1408. package/src/web/scrapers/arxiv.ts +83 -0
  1409. package/src/web/scrapers/aur.ts +162 -0
  1410. package/src/web/scrapers/biorxiv.ts +133 -0
  1411. package/src/web/scrapers/bluesky.ts +262 -0
  1412. package/src/web/scrapers/brew.ts +172 -0
  1413. package/src/web/scrapers/cheatsh.ts +68 -0
  1414. package/src/web/scrapers/chocolatey.ts +196 -0
  1415. package/src/web/scrapers/choosealicense.ts +95 -0
  1416. package/src/web/scrapers/cisa-kev.ts +87 -0
  1417. package/src/web/scrapers/clojars.ts +154 -0
  1418. package/src/web/scrapers/coingecko.ts +177 -0
  1419. package/src/web/scrapers/crates-io.ts +97 -0
  1420. package/src/web/scrapers/crossref.ts +136 -0
  1421. package/src/web/scrapers/devto.ts +147 -0
  1422. package/src/web/scrapers/discogs.ts +306 -0
  1423. package/src/web/scrapers/discourse.ts +197 -0
  1424. package/src/web/scrapers/dockerhub.ts +138 -0
  1425. package/src/web/scrapers/docs-rs.ts +663 -0
  1426. package/src/web/scrapers/fdroid.ts +134 -0
  1427. package/src/web/scrapers/firefox-addons.ts +191 -0
  1428. package/src/web/scrapers/flathub.ts +223 -0
  1429. package/src/web/scrapers/github-gist.ts +58 -0
  1430. package/src/web/scrapers/github.ts +800 -0
  1431. package/src/web/scrapers/gitlab.ts +401 -0
  1432. package/src/web/scrapers/go-pkg.ts +266 -0
  1433. package/src/web/scrapers/hackage.ts +140 -0
  1434. package/src/web/scrapers/hackernews.ts +189 -0
  1435. package/src/web/scrapers/hex.ts +105 -0
  1436. package/src/web/scrapers/huggingface.ts +321 -0
  1437. package/src/web/scrapers/iacr.ts +89 -0
  1438. package/src/web/scrapers/index.ts +252 -0
  1439. package/src/web/scrapers/jetbrains-marketplace.ts +159 -0
  1440. package/src/web/scrapers/lemmy.ts +203 -0
  1441. package/src/web/scrapers/lobsters.ts +175 -0
  1442. package/src/web/scrapers/mastodon.ts +292 -0
  1443. package/src/web/scrapers/maven.ts +138 -0
  1444. package/src/web/scrapers/mdn.ts +173 -0
  1445. package/src/web/scrapers/metacpan.ts +222 -0
  1446. package/src/web/scrapers/musicbrainz.ts +250 -0
  1447. package/src/web/scrapers/npm.ts +98 -0
  1448. package/src/web/scrapers/nuget.ts +183 -0
  1449. package/src/web/scrapers/nvd.ts +222 -0
  1450. package/src/web/scrapers/ollama.ts +239 -0
  1451. package/src/web/scrapers/open-vsx.ts +106 -0
  1452. package/src/web/scrapers/opencorporates.ts +292 -0
  1453. package/src/web/scrapers/openlibrary.ts +336 -0
  1454. package/src/web/scrapers/orcid.ts +286 -0
  1455. package/src/web/scrapers/osv.ts +176 -0
  1456. package/src/web/scrapers/packagist.ts +160 -0
  1457. package/src/web/scrapers/pub-dev.ts +143 -0
  1458. package/src/web/scrapers/pubmed.ts +211 -0
  1459. package/src/web/scrapers/pypi.ts +112 -0
  1460. package/src/web/scrapers/rawg.ts +110 -0
  1461. package/src/web/scrapers/readthedocs.ts +120 -0
  1462. package/src/web/scrapers/reddit.ts +95 -0
  1463. package/src/web/scrapers/repology.ts +251 -0
  1464. package/src/web/scrapers/rfc.ts +201 -0
  1465. package/src/web/scrapers/rubygems.ts +103 -0
  1466. package/src/web/scrapers/searchcode.ts +189 -0
  1467. package/src/web/scrapers/sec-edgar.ts +261 -0
  1468. package/src/web/scrapers/semantic-scholar.ts +171 -0
  1469. package/src/web/scrapers/snapcraft.ts +187 -0
  1470. package/src/web/scrapers/sourcegraph.ts +336 -0
  1471. package/src/web/scrapers/spdx.ts +108 -0
  1472. package/src/web/scrapers/spotify.ts +198 -0
  1473. package/src/web/scrapers/stackoverflow.ts +120 -0
  1474. package/src/web/scrapers/terraform.ts +277 -0
  1475. package/src/web/scrapers/tldr.ts +47 -0
  1476. package/src/web/scrapers/twitter.ts +94 -0
  1477. package/src/web/scrapers/types.ts +354 -0
  1478. package/src/web/scrapers/utils.ts +109 -0
  1479. package/src/web/scrapers/vimeo.ts +133 -0
  1480. package/src/web/scrapers/vscode-marketplace.ts +187 -0
  1481. package/src/web/scrapers/w3c.ts +156 -0
  1482. package/src/web/scrapers/wikidata.ts +344 -0
  1483. package/src/web/scrapers/wikipedia.ts +84 -0
  1484. package/src/web/scrapers/youtube.ts +325 -0
  1485. package/src/web/search/index.ts +376 -0
  1486. package/src/web/search/provider.ts +272 -0
  1487. package/src/web/search/providers/anthropic.ts +401 -0
  1488. package/src/web/search/providers/base.ts +110 -0
  1489. package/src/web/search/providers/brave.ts +179 -0
  1490. package/src/web/search/providers/browser-headers.ts +109 -0
  1491. package/src/web/search/providers/browser-page.ts +123 -0
  1492. package/src/web/search/providers/codex.ts +749 -0
  1493. package/src/web/search/providers/duckduckgo.ts +213 -0
  1494. package/src/web/search/providers/ecosia.ts +182 -0
  1495. package/src/web/search/providers/exa.ts +511 -0
  1496. package/src/web/search/providers/firecrawl.ts +211 -0
  1497. package/src/web/search/providers/gemini.ts +628 -0
  1498. package/src/web/search/providers/google.ts +194 -0
  1499. package/src/web/search/providers/jina.ts +134 -0
  1500. package/src/web/search/providers/kagi.ts +95 -0
  1501. package/src/web/search/providers/kimi.ts +217 -0
  1502. package/src/web/search/providers/mojeek.ts +219 -0
  1503. package/src/web/search/providers/parallel.ts +182 -0
  1504. package/src/web/search/providers/perplexity-auth.ts +142 -0
  1505. package/src/web/search/providers/perplexity.ts +994 -0
  1506. package/src/web/search/providers/public.ts +199 -0
  1507. package/src/web/search/providers/searxng.ts +461 -0
  1508. package/src/web/search/providers/startpage.ts +219 -0
  1509. package/src/web/search/providers/synthetic.ts +120 -0
  1510. package/src/web/search/providers/tavily.ts +242 -0
  1511. package/src/web/search/providers/tinyfish.ts +164 -0
  1512. package/src/web/search/providers/utils.ts +128 -0
  1513. package/src/web/search/providers/xai.ts +372 -0
  1514. package/src/web/search/providers/zai.ts +437 -0
  1515. package/src/web/search/query.ts +850 -0
  1516. package/src/web/search/render.ts +262 -0
  1517. package/src/web/search/types.ts +507 -0
  1518. package/src/web/search/utils.ts +17 -0
  1519. package/src/workspace-tree.ts +326 -0
@@ -0,0 +1,2532 @@
1
+ /// <reference path="./legacy-pi-virtual-modules.d.ts" />
2
+
3
+ import * as fs from "node:fs";
4
+ import { createRequire, isBuiltin } from "node:module";
5
+ import * as path from "node:path";
6
+ import * as url from "node:url";
7
+ import type { ParseResult, ParserPlugin } from "@babel/parser";
8
+ import { parse as parseBabel } from "@babel/parser";
9
+ import { isCompiledBinary, stripWindowsExtendedLengthPathPrefix } from "@oh-my-pi/pi-utils";
10
+ import { registerPluginCacheInvalidator } from "../../discovery/helpers";
11
+
12
+ const IS_COMPILED_BINARY = isCompiledBinary();
13
+
14
+ // === Bundled host modules (issue #3423) ===
15
+ //
16
+ // Bun 1.3.14 stopped exposing `--compile` extras through any filesystem-style
17
+ // API: `fs.existsSync`, `Bun.file().exists()`, `Bun.resolveSync`, and even
18
+ // `import("/$bunfs/...")` / `import("file:///$bunfs/...")` all fail for the
19
+ // embedded entries. Bun.plugin `onResolve` also no longer fires for transitive
20
+ // imports inside runtime-loaded extensions.
21
+ //
22
+ // Compiled builds retain lazy loaders for host packages and serve requested
23
+ // surfaces through `omp-legacy-pi-bundled:<key>` synthetic modules.
24
+ // `scripts/legacy-pi-virtual-module.ts` derives literal dynamic-import edges
25
+ // from current package exports inside a Bun build plugin: no generated source
26
+ // or duplicate key list exists on disk. Deferring each host module evaluation
27
+ // avoids cycles with an extension-loading command that is itself in the
28
+ // retained package graph.
29
+ const BUNDLED_VIRTUAL_SCHEME = "omp-legacy-pi-bundled:";
30
+ const BUNDLED_VIRTUAL_NAMESPACE = "omp-legacy-pi-bundled";
31
+ const BUNDLED_MODULES_GLOBAL = "__ompLegacyPiBundledModules";
32
+ const TYPEBOX_BUNDLED_MODULE_KEY = "typebox";
33
+
34
+ type BundledModule = Readonly<Record<string, unknown>>;
35
+ type BundledModules = Readonly<Record<string, BundledModule>>;
36
+ type BundledModuleLoaders = Readonly<Record<string, () => Promise<BundledModule>>>;
37
+
38
+ interface LegacyPiResolveResult {
39
+ path: string;
40
+ namespace?: string;
41
+ }
42
+
43
+ interface BundledVirtualResolveResult {
44
+ path: string;
45
+ namespace: typeof BUNDLED_VIRTUAL_NAMESPACE;
46
+ }
47
+
48
+ interface ExtensionSpecifierReference {
49
+ readonly kind: "import" | "require";
50
+ readonly specifier: string;
51
+ readonly start: number;
52
+ readonly end: number;
53
+ }
54
+
55
+ function parseExtensionSource(source: string, importerPath: string): ParseResult {
56
+ const extension = path.extname(importerPath).toLowerCase();
57
+ const plugins: ParserPlugin[] = ["decorators-legacy", "explicitResourceManagement"];
58
+ if (extension === ".ts" || extension === ".mts" || extension === ".cts" || extension === ".tsx") {
59
+ plugins.push("typescript");
60
+ }
61
+ if (extension === ".jsx" || extension === ".tsx") {
62
+ plugins.push("jsx");
63
+ }
64
+
65
+ try {
66
+ return parseBabel(source, {
67
+ sourceType: "unambiguous",
68
+ allowAwaitOutsideFunction: true,
69
+ allowReturnOutsideFunction: true,
70
+ allowImportExportEverywhere: true,
71
+ allowNewTargetOutsideFunction: true,
72
+ allowSuperOutsideMethod: true,
73
+ allowUndeclaredExports: true,
74
+ errorRecovery: true,
75
+ plugins,
76
+ });
77
+ } catch (error) {
78
+ throw new Error(
79
+ `Failed to parse extension source for dependency rewriting: ${importerPath}: ${error instanceof Error ? error.message : String(error)}`,
80
+ { cause: error },
81
+ );
82
+ }
83
+ }
84
+
85
+ const REQUIRE_BINDING = 1 << 0;
86
+ const OBJECT_BINDING = 1 << 1;
87
+ const EXPORTS_BINDING = 1 << 2;
88
+ const MODULE_BINDING = 1 << 3;
89
+
90
+ interface StructuralAstNode {
91
+ readonly type: string;
92
+ readonly [key: string]: unknown;
93
+ }
94
+
95
+ interface BindingScope {
96
+ readonly parent: BindingScope | null;
97
+ readonly ownsVarBindings: boolean;
98
+ bindings: number;
99
+ }
100
+
101
+ interface ScopedAstNode {
102
+ readonly node: StructuralAstNode;
103
+ readonly scope: BindingScope;
104
+ readonly order: number;
105
+ }
106
+
107
+ interface ScopeWalkItem {
108
+ readonly node: StructuralAstNode;
109
+ readonly scope: BindingScope | null;
110
+ readonly parent: StructuralAstNode | null;
111
+ readonly parentKey: string | null;
112
+ }
113
+
114
+ function asAstNode(value: unknown): StructuralAstNode | null {
115
+ if (!value || typeof value !== "object" || Array.isArray(value)) return null;
116
+ const candidate = value as { readonly type?: unknown };
117
+ return typeof candidate.type === "string" ? (candidate as StructuralAstNode) : null;
118
+ }
119
+
120
+ function nodeArray(node: StructuralAstNode, key: string): readonly unknown[] | null {
121
+ const value = node[key];
122
+ return Array.isArray(value) ? value : null;
123
+ }
124
+
125
+ function nodeArgument(node: StructuralAstNode | null, index: number): StructuralAstNode | null {
126
+ if (!node) return null;
127
+ const values = nodeArray(node, "arguments");
128
+ return values ? asAstNode(values[index]) : null;
129
+ }
130
+
131
+ function isIdentifier(node: StructuralAstNode | null, name: string): boolean {
132
+ return node?.type === "Identifier" && node.name === name;
133
+ }
134
+
135
+ function trackedBinding(name: unknown): number {
136
+ switch (name) {
137
+ case "require":
138
+ return REQUIRE_BINDING;
139
+ case "Object":
140
+ return OBJECT_BINDING;
141
+ case "exports":
142
+ return EXPORTS_BINDING;
143
+ case "module":
144
+ return MODULE_BINDING;
145
+ default:
146
+ return 0;
147
+ }
148
+ }
149
+
150
+ function addPatternBindings(scope: BindingScope, pattern: unknown): void {
151
+ const stack: unknown[] = [pattern];
152
+ while (stack.length > 0) {
153
+ const node = asAstNode(stack.pop());
154
+ if (!node) continue;
155
+ switch (node.type) {
156
+ case "Identifier":
157
+ scope.bindings |= trackedBinding(node.name);
158
+ break;
159
+ case "AssignmentPattern":
160
+ stack.push(node.left);
161
+ break;
162
+ case "RestElement":
163
+ stack.push(node.argument);
164
+ break;
165
+ case "ArrayPattern": {
166
+ const elements = nodeArray(node, "elements");
167
+ if (elements) stack.push(...elements);
168
+ break;
169
+ }
170
+ case "ObjectPattern": {
171
+ const properties = nodeArray(node, "properties");
172
+ if (!properties) break;
173
+ for (const value of properties) {
174
+ const property = asAstNode(value);
175
+ if (!property) continue;
176
+ stack.push(property.type === "RestElement" ? property.argument : property.value);
177
+ }
178
+ break;
179
+ }
180
+ case "TSParameterProperty":
181
+ stack.push(node.parameter);
182
+ break;
183
+ }
184
+ }
185
+ }
186
+
187
+ function isFunctionScopeNode(node: StructuralAstNode): boolean {
188
+ switch (node.type) {
189
+ case "FunctionDeclaration":
190
+ case "FunctionExpression":
191
+ case "ArrowFunctionExpression":
192
+ case "ObjectMethod":
193
+ case "ClassMethod":
194
+ case "ClassPrivateMethod":
195
+ case "TSDeclareFunction":
196
+ case "TSDeclareMethod":
197
+ case "DeclareFunction":
198
+ return true;
199
+ default:
200
+ return false;
201
+ }
202
+ }
203
+
204
+ function isFunctionDeclarationNode(node: StructuralAstNode): boolean {
205
+ return node.type === "FunctionDeclaration" || node.type === "TSDeclareFunction" || node.type === "DeclareFunction";
206
+ }
207
+
208
+ function isClassScopeNode(node: StructuralAstNode): boolean {
209
+ return node.type === "ClassDeclaration" || node.type === "ClassExpression";
210
+ }
211
+
212
+ function scopeKind(node: StructuralAstNode, parent: StructuralAstNode | null, parentKey: string | null): 0 | 1 | 2 {
213
+ if (
214
+ node.type === "Program" ||
215
+ isFunctionScopeNode(node) ||
216
+ node.type === "StaticBlock" ||
217
+ node.type === "TSModuleBlock"
218
+ ) {
219
+ return 2;
220
+ }
221
+ if (
222
+ isClassScopeNode(node) ||
223
+ node.type === "CatchClause" ||
224
+ node.type === "ForStatement" ||
225
+ node.type === "ForInStatement" ||
226
+ node.type === "ForOfStatement" ||
227
+ node.type === "SwitchStatement"
228
+ ) {
229
+ return 1;
230
+ }
231
+ if (node.type === "BlockStatement" && !(parent && isFunctionScopeNode(parent) && parentKey === "body")) {
232
+ return 1;
233
+ }
234
+ return 0;
235
+ }
236
+
237
+ function nearestVarScope(scope: BindingScope): BindingScope {
238
+ let current = scope;
239
+ while (!current.ownsVarBindings && current.parent) current = current.parent;
240
+ return current;
241
+ }
242
+
243
+ function registerOuterDeclaration(node: StructuralAstNode, scope: BindingScope | null): void {
244
+ if (!scope) return;
245
+ if (
246
+ (isFunctionDeclarationNode(node) && node.type !== "TSDeclareFunction" && node.type !== "DeclareFunction") ||
247
+ (node.type === "ClassDeclaration" && node.declare !== true)
248
+ ) {
249
+ addPatternBindings(scope, node.id);
250
+ }
251
+ }
252
+
253
+ function registerScopeBindings(node: StructuralAstNode, scope: BindingScope): void {
254
+ if (isFunctionScopeNode(node)) {
255
+ addPatternBindings(scope, node.id);
256
+ const parameters = nodeArray(node, "params");
257
+ if (parameters) {
258
+ for (const parameter of parameters) addPatternBindings(scope, parameter);
259
+ }
260
+ }
261
+ if (isClassScopeNode(node)) addPatternBindings(scope, node.id);
262
+ if (node.type === "CatchClause") addPatternBindings(scope, node.param);
263
+
264
+ if (node.type === "ImportDeclaration") {
265
+ const specifiers = nodeArray(node, "specifiers");
266
+ if (specifiers) {
267
+ for (const value of specifiers) {
268
+ const specifier = asAstNode(value);
269
+ if (specifier) addPatternBindings(scope, specifier.local);
270
+ }
271
+ }
272
+ } else if (node.type === "TSImportEqualsDeclaration") {
273
+ addPatternBindings(scope, node.id);
274
+ } else if (node.type === "VariableDeclaration") {
275
+ const target = node.kind === "var" ? nearestVarScope(scope) : scope;
276
+ const declarations = nodeArray(node, "declarations");
277
+ if (declarations) {
278
+ for (const value of declarations) {
279
+ const declaration = asAstNode(value);
280
+ if (declaration) addPatternBindings(target, declaration.id);
281
+ }
282
+ }
283
+ }
284
+ }
285
+
286
+ function isAstMetadataKey(key: string): boolean {
287
+ switch (key) {
288
+ case "loc":
289
+ case "extra":
290
+ case "range":
291
+ case "comments":
292
+ case "tokens":
293
+ case "errors":
294
+ case "leadingComments":
295
+ case "trailingComments":
296
+ case "innerComments":
297
+ case "parent":
298
+ case "parentPath":
299
+ case "scope":
300
+ case "hub":
301
+ return true;
302
+ default:
303
+ return false;
304
+ }
305
+ }
306
+
307
+ function scopeForChild(
308
+ node: StructuralAstNode,
309
+ key: string,
310
+ outerScope: BindingScope | null,
311
+ nodeScope: BindingScope,
312
+ ): BindingScope {
313
+ if (node.type === "SwitchStatement" && key === "discriminant") {
314
+ return outerScope ?? nodeScope;
315
+ }
316
+ if (isFunctionScopeNode(node) && (key === "key" || key === "decorators")) {
317
+ return outerScope ?? nodeScope;
318
+ }
319
+ if (isClassScopeNode(node) && key === "decorators") {
320
+ return outerScope ?? nodeScope;
321
+ }
322
+ return nodeScope;
323
+ }
324
+
325
+ /**
326
+ * Builds only the lexical information needed by legacy extension rewriting.
327
+ * Scope frames are fully populated before selected nodes are returned, so
328
+ * hoisted and TDZ bindings behave independently of textual declaration order.
329
+ */
330
+ function collectScopedAstNodes(root: unknown, select: (node: StructuralAstNode) => boolean): ScopedAstNode[] {
331
+ const rootNode = asAstNode(root);
332
+ if (!rootNode) return [];
333
+
334
+ const selected: ScopedAstNode[] = [];
335
+ const stack: ScopeWalkItem[] = [{ node: rootNode, scope: null, parent: null, parentKey: null }];
336
+ const seen = new WeakSet<object>();
337
+ let order = 0;
338
+ while (stack.length > 0) {
339
+ const item = stack.pop();
340
+ if (!item || seen.has(item.node)) continue;
341
+ seen.add(item.node);
342
+
343
+ registerOuterDeclaration(item.node, item.scope);
344
+ const kind = scopeKind(item.node, item.parent, item.parentKey);
345
+ const activeScope: BindingScope | null =
346
+ kind === 0
347
+ ? item.scope
348
+ : {
349
+ parent: item.scope,
350
+ ownsVarBindings: kind === 2,
351
+ bindings: 0,
352
+ };
353
+ if (activeScope) {
354
+ registerScopeBindings(item.node, activeScope);
355
+ if (select(item.node)) selected.push({ node: item.node, scope: activeScope, order });
356
+ }
357
+ order++;
358
+
359
+ for (const key in item.node) {
360
+ if (isAstMetadataKey(key)) continue;
361
+ const childScope = activeScope ? scopeForChild(item.node, key, item.scope, activeScope) : null;
362
+ const value = item.node[key];
363
+ if (Array.isArray(value)) {
364
+ for (const element of value) {
365
+ const child = asAstNode(element);
366
+ if (child) stack.push({ node: child, scope: childScope, parent: item.node, parentKey: key });
367
+ }
368
+ } else {
369
+ const child = asAstNode(value);
370
+ if (child) stack.push({ node: child, scope: childScope, parent: item.node, parentKey: key });
371
+ }
372
+ }
373
+ }
374
+
375
+ selected.sort((left, right) => {
376
+ const leftStart = typeof left.node.start === "number" ? left.node.start : Number.MAX_SAFE_INTEGER;
377
+ const rightStart = typeof right.node.start === "number" ? right.node.start : Number.MAX_SAFE_INTEGER;
378
+ return leftStart - rightStart || left.order - right.order;
379
+ });
380
+ return selected;
381
+ }
382
+
383
+ function scopeHasBinding(scope: BindingScope, binding: number): boolean {
384
+ let current: BindingScope | null = scope;
385
+ while (current) {
386
+ if ((current.bindings & binding) !== 0) return true;
387
+ current = current.parent;
388
+ }
389
+ return false;
390
+ }
391
+
392
+ function isSpecifierReferenceNode(node: StructuralAstNode): boolean {
393
+ switch (node.type) {
394
+ case "ImportDeclaration":
395
+ case "ExportNamedDeclaration":
396
+ case "ExportAllDeclaration":
397
+ case "ImportExpression":
398
+ case "TSImportEqualsDeclaration":
399
+ case "CallExpression":
400
+ return true;
401
+ default:
402
+ return false;
403
+ }
404
+ }
405
+
406
+ function isUncomputedMember(node: StructuralAstNode | null, objectName: string, propertyName: string): boolean {
407
+ if (node?.type !== "MemberExpression" || node.computed === true) return false;
408
+ return isIdentifier(asAstNode(node.object), objectName) && isIdentifier(asAstNode(node.property), propertyName);
409
+ }
410
+
411
+ function isUnshadowedExportsTarget(node: StructuralAstNode | null, scope: BindingScope): boolean {
412
+ return (
413
+ (isIdentifier(node, "exports") && !scopeHasBinding(scope, EXPORTS_BINDING)) ||
414
+ (isUncomputedMember(node, "module", "exports") && !scopeHasBinding(scope, MODULE_BINDING))
415
+ );
416
+ }
417
+
418
+ function isGlobalRequireCall(node: StructuralAstNode | null, scope: BindingScope): boolean {
419
+ return (
420
+ node?.type === "CallExpression" &&
421
+ isIdentifier(asAstNode(node.callee), "require") &&
422
+ !scopeHasBinding(scope, REQUIRE_BINDING)
423
+ );
424
+ }
425
+
426
+ function staticMemberPropertyName(node: StructuralAstNode): string | null {
427
+ const property = asAstNode(node.property);
428
+ if (node.computed !== true && property?.type === "Identifier" && typeof property.name === "string") {
429
+ return property.name;
430
+ }
431
+ if (node.computed === true && property?.type === "StringLiteral" && typeof property.value === "string") {
432
+ return property.value;
433
+ }
434
+ return null;
435
+ }
436
+
437
+ function staticObjectPropertyName(node: StructuralAstNode): string | null {
438
+ if (node.computed === true) return null;
439
+ const key = asAstNode(node.key);
440
+ if (key?.type === "Identifier" && typeof key.name === "string") return key.name;
441
+ return key?.type === "StringLiteral" && typeof key.value === "string" ? key.value : null;
442
+ }
443
+
444
+ function collectExtensionSpecifierReferences(
445
+ source: string,
446
+ importerPath: string,
447
+ ast: ParseResult = parseExtensionSource(source, importerPath),
448
+ ): ExtensionSpecifierReference[] {
449
+ const references: ExtensionSpecifierReference[] = [];
450
+ const record = (kind: ExtensionSpecifierReference["kind"], literal: unknown): void => {
451
+ const node = asAstNode(literal);
452
+ if (
453
+ node?.type === "StringLiteral" &&
454
+ typeof node.value === "string" &&
455
+ typeof node.start === "number" &&
456
+ typeof node.end === "number"
457
+ ) {
458
+ references.push({ kind, specifier: node.value, start: node.start, end: node.end });
459
+ }
460
+ };
461
+ for (const { node, scope } of collectScopedAstNodes(ast, isSpecifierReferenceNode)) {
462
+ if (
463
+ node.type === "ImportDeclaration" ||
464
+ node.type === "ExportNamedDeclaration" ||
465
+ node.type === "ExportAllDeclaration"
466
+ ) {
467
+ record("import", node.source);
468
+ } else if (node.type === "ImportExpression") {
469
+ record("import", node.source);
470
+ } else if (node.type === "TSImportEqualsDeclaration") {
471
+ const moduleReference = asAstNode(node.moduleReference);
472
+ if (moduleReference?.type === "TSExternalModuleReference") {
473
+ record("require", moduleReference.expression);
474
+ }
475
+ } else if (node.type === "CallExpression") {
476
+ const callee = asAstNode(node.callee);
477
+ if (callee?.type === "Import") {
478
+ record("import", nodeArgument(node, 0));
479
+ } else if (isIdentifier(callee, "require") && !scopeHasBinding(scope, REQUIRE_BINDING)) {
480
+ record("require", nodeArgument(node, 0));
481
+ }
482
+ }
483
+ }
484
+ return references;
485
+ }
486
+
487
+ function applySpecifierReplacements(
488
+ source: string,
489
+ replacements: ReadonlyArray<ExtensionSpecifierReference & { readonly replacement: string }>,
490
+ ): string {
491
+ let rewritten = source;
492
+ for (const reference of [...replacements].sort((left, right) => right.start - left.start)) {
493
+ rewritten = `${rewritten.slice(0, reference.start)}${JSON.stringify(reference.replacement)}${rewritten.slice(reference.end)}`;
494
+ }
495
+ return rewritten;
496
+ }
497
+
498
+ const loadedBundledModules: Record<string, BundledModule> = {};
499
+ let bundledModuleLoadersPromise: Promise<BundledModuleLoaders> | null = null;
500
+
501
+ /**
502
+ * Load the build-supplied module registry without evaluating its host modules.
503
+ *
504
+ * `globalThis` bridges the synthetic ES modules, which cannot close over this
505
+ * file's lexical scope. Dev/test runs never execute the conditional import;
506
+ * binary builds resolve it through the in-memory build plugin.
507
+ */
508
+ function ensureBundledModuleLoadersLoaded(): Promise<BundledModuleLoaders> {
509
+ if (!IS_COMPILED_BINARY) {
510
+ return Promise.reject(new Error("omp:legacy-pi-shim: bundled modules are only available in compiled mode"));
511
+ }
512
+ if (!bundledModuleLoadersPromise) {
513
+ bundledModuleLoadersPromise = import("omp-legacy-pi-modules").then(module => {
514
+ Reflect.set(globalThis, BUNDLED_MODULES_GLOBAL, loadedBundledModules);
515
+ return module.BUNDLED_PI_MODULE_LOADERS;
516
+ });
517
+ }
518
+ return bundledModuleLoadersPromise;
519
+ }
520
+
521
+ async function loadBundledModule(moduleKey: string): Promise<void> {
522
+ const loaders = await ensureBundledModuleLoadersLoaded();
523
+ const loader = loaders[moduleKey];
524
+ if (!loader) {
525
+ throw new Error(`omp:legacy-pi-shim: no bundled module registered for ${moduleKey}`);
526
+ }
527
+ loadedBundledModules[moduleKey] = await loader();
528
+ }
529
+
530
+ function bundledModuleVirtualSpecifier(moduleKey: string): string {
531
+ return `${BUNDLED_VIRTUAL_SCHEME}${moduleKey}`;
532
+ }
533
+
534
+ function isBundledVirtualSpecifier(value: string): boolean {
535
+ return value.startsWith(BUNDLED_VIRTUAL_SCHEME);
536
+ }
537
+
538
+ function toLegacyPiResolveResult(resolvedPath: string): LegacyPiResolveResult {
539
+ if (isBundledVirtualSpecifier(resolvedPath)) {
540
+ const registryKey = resolvedPath.slice(BUNDLED_VIRTUAL_SCHEME.length);
541
+ return { path: registryKey, namespace: BUNDLED_VIRTUAL_NAMESPACE };
542
+ }
543
+ return { path: resolvedPath };
544
+ }
545
+
546
+ /** Maps a bundled virtual specifier or registry key to Bun's plugin namespace shape. */
547
+ export function resolveBundledVirtualSpecifier(specifier: string): BundledVirtualResolveResult {
548
+ const registryKey = isBundledVirtualSpecifier(specifier)
549
+ ? specifier.slice(BUNDLED_VIRTUAL_SCHEME.length)
550
+ : specifier;
551
+ if (!registryKey) {
552
+ throw new Error("omp:legacy-pi-shim: bundled virtual specifier has no registry key");
553
+ }
554
+ return { path: registryKey, namespace: BUNDLED_VIRTUAL_NAMESPACE };
555
+ }
556
+
557
+ /**
558
+ * Build a synthetic ES module for one live bundled namespace. Every export
559
+ * reads through the global bridge; no bunfs path or copied package is involved.
560
+ */
561
+ function synthesizeBundledModuleSourceFromModules(moduleKey: string, modules: BundledModules): string {
562
+ const mod = modules[moduleKey];
563
+ if (!mod) {
564
+ throw new Error(`omp:legacy-pi-shim: no bundled module registered for ${moduleKey}`);
565
+ }
566
+ const lines: string[] = [
567
+ `const __omp_bundled = globalThis[${JSON.stringify(BUNDLED_MODULES_GLOBAL)}][${JSON.stringify(moduleKey)}];`,
568
+ ];
569
+ let hasDefault = false;
570
+ for (const exportName in mod) {
571
+ if (exportName === "default") {
572
+ hasDefault = true;
573
+ continue;
574
+ }
575
+ lines.push(`export const ${exportName} = __omp_bundled[${JSON.stringify(exportName)}];`);
576
+ }
577
+ if (hasDefault) {
578
+ lines.push("export default __omp_bundled.default;");
579
+ }
580
+ lines.push("");
581
+ return lines.join("\n");
582
+ }
583
+
584
+ /**
585
+ * Build the synthetic source served for one
586
+ * `omp-legacy-pi-bundled:<key>` import.
587
+ */
588
+ async function synthesizeBundledModuleSource(moduleKey: string): Promise<string> {
589
+ await loadBundledModule(moduleKey);
590
+ return synthesizeBundledModuleSourceFromModules(moduleKey, loadedBundledModules);
591
+ }
592
+
593
+ /** Test seam for the virtual module's named/default export forwarding. */
594
+ export function __synthesizeLegacyPiBundledSourceWithModules(
595
+ moduleKey: string,
596
+ modules: Readonly<Record<string, Readonly<Record<string, unknown>>>>,
597
+ ): string {
598
+ return synthesizeBundledModuleSourceFromModules(moduleKey, modules);
599
+ }
600
+
601
+ /** Test seam for the global bridge key shared with synthetic module source. */
602
+ export function __getLegacyPiBundledModulesGlobal(): string {
603
+ return BUNDLED_MODULES_GLOBAL;
604
+ }
605
+
606
+ // Canonical scope for in-process pi packages. Plugins published against any of
607
+ // the aliased scopes below (mariozechner's original publish, earendil-works'
608
+ // fork, or the canonical @oh-my-pi scope itself) are remapped to this scope and
609
+ // resolved against the bundled copy that ships inside the omp binary. This
610
+ // keeps plugins running against the exact runtime state of the host (single
611
+ // module registry, single tool registry, etc.) regardless of which historical
612
+ // scope name they happened to declare in their peerDependencies.
613
+ const CANONICAL_PI_SCOPE = "@oh-my-pi";
614
+
615
+ // Scopes that have historically been used to publish (or alias) the same set
616
+ // of internal pi-* packages. `@oh-my-pi` is intentionally included so direct
617
+ // canonical imports still pass through the same host-bundled package resolution
618
+ // path instead of pulling a duplicate copy from plugin node_modules.
619
+ const PI_SCOPE_ALIASES = ["oh-my-pi", "mariozechner", "earendil-works"] as const;
620
+
621
+ // Internal pi-* package basenames bundled inside the omp binary.
622
+ const PI_PACKAGE_NAMES = ["pi-agent-core", "pi-ai", "pi-coding-agent", "pi-natives", "pi-tui", "pi-utils"] as const;
623
+
624
+ const PI_SCOPE_ALTERNATION = PI_SCOPE_ALIASES.join("|");
625
+ const PI_PACKAGE_ALTERNATION = PI_PACKAGE_NAMES.join("|");
626
+
627
+ // Upstream `@mariozechner/*` packages exposed a few subpaths at the package
628
+ // root that we relocated under a different folder. Each entry rewrites
629
+ // `<pkg>/<from>` → `<pkg>/<to>` after the scope has been canonicalised, so
630
+ // plugins importing the upstream layout still resolve to a real file in our
631
+ // bundled copy. Entries ending in `/` rewrite the whole subtree; add new
632
+ // `pkg/from -> pkg/to` pairs whenever an upstream-only subpath breaks resolution.
633
+ const PI_SUBPATH_REMAPS: ReadonlyMap<string, string> = new Map<string, string>([
634
+ ["pi-ai/utils/oauth", "pi-ai/oauth"],
635
+ ["pi-ai/utils/oauth/", "pi-ai/oauth/"],
636
+ ["pi-ai/compat", "pi-ai"],
637
+ ]);
638
+
639
+ function remapLegacyPiSubpath(rest: string): string {
640
+ const exact = PI_SUBPATH_REMAPS.get(rest);
641
+ if (exact) {
642
+ return exact;
643
+ }
644
+
645
+ for (const [from, to] of PI_SUBPATH_REMAPS) {
646
+ if (from.endsWith("/") && rest.startsWith(from)) {
647
+ return `${to}${rest.slice(from.length)}`;
648
+ }
649
+ }
650
+
651
+ return rest;
652
+ }
653
+
654
+ const LEGACY_PI_SPECIFIER_FILTER = new RegExp(`^@(?:${PI_SCOPE_ALTERNATION})/(?:${PI_PACKAGE_ALTERNATION})(?:/.*)?$`);
655
+ const resolvedSpecifierFallbacks = new Map<string, string>();
656
+ const SOURCE_MODULE_EXTENSIONS = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"] as const;
657
+ const SUPPORTED_PACKAGE_IMPORT_CONDITIONS = new Set(["bun", "node", "import", "default"]);
658
+ const SUPPORTED_PACKAGE_REQUIRE_CONDITIONS = new Set(["bun", "node", "require", "default"]);
659
+ const packageRootCache = new Map<string, string | null>();
660
+ const packageImportsCache = new Map<string, Record<string, unknown> | null>();
661
+ const nodePackageRootCache = new Map<string, Promise<string | null>>();
662
+ const packageManifestCache = new Map<string, Promise<Record<string, unknown> | null>>();
663
+ const bareDependencyResolutionCache = new Map<string, Promise<string | null>>();
664
+ const bareRequireResolutionCache = new Map<string, Promise<string | null>>();
665
+ const realpathCache = new Map<string, Promise<string>>();
666
+ const nativeAddonResolutionCache = new Map<string, Promise<string | null>>();
667
+ const nativeAddonRequireScanCache = new Map<string, Promise<boolean>>();
668
+ const nativeAddonLoaderModulePaths = new Set<string>();
669
+
670
+ function clearLegacyPiResolutionCaches(): void {
671
+ resolvedSpecifierFallbacks.clear();
672
+ packageRootCache.clear();
673
+ packageImportsCache.clear();
674
+ nodePackageRootCache.clear();
675
+ packageManifestCache.clear();
676
+ bareDependencyResolutionCache.clear();
677
+ bareRequireResolutionCache.clear();
678
+ nativeAddonResolutionCache.clear();
679
+ nativeAddonRequireScanCache.clear();
680
+ nativeAddonLoaderModulePaths.clear();
681
+ realpathCache.clear();
682
+ }
683
+
684
+ registerPluginCacheInvalidator(clearLegacyPiResolutionCaches);
685
+ const PACKAGE_IMPORT_EXCLUDED = Symbol("packageImportExcluded");
686
+
687
+ // Extensions that imported TypeBox directly used to resolve against a real
688
+ // `@sinclair/typebox` or `typebox` install. The runtime dep was replaced with
689
+ // the Zod-backed shim under `extensibility/typebox.ts`; plugins still importing
690
+ // either public name are redirected to that shim so existing extensions keep
691
+ // working without code changes. Submodules like `@sinclair/typebox/compiler`
692
+ // are intentionally not remapped — those expose TypeBox-only APIs the shim does
693
+ // not provide and plugins relying on them must vendor TypeBox directly.
694
+ const TYPEBOX_SPECIFIER_FILTER = /^(?:@sinclair\/typebox|typebox)$/;
695
+
696
+ // Compat-shim path resolution. In compiled-binary mode every bundled surface
697
+ // is served through the `omp-legacy-pi-bundled:` virtual namespace (see the
698
+ // bundled-module block above) — bunfs paths are unreachable on Bun 1.3.14+, so the
699
+ // pre-#3423 helpers that derived `/$bunfs/root/...` paths from
700
+ // `import.meta.dir` are gone. Dev / source-link / installed-package modes
701
+ // still need a real filesystem path for the source shims, which
702
+ // `sourceShimPath` computes either from the npm prebuilt `dist/cli.js`
703
+ // bundle (`PI_BUNDLED=true`) or directly from the monorepo source tree.
704
+
705
+ /**
706
+ * Compute the package root for the npm prebuilt `dist/cli.js` bundle.
707
+ *
708
+ * `bundle-dist.ts` defines `process.env.PI_BUNDLED="true"`; after bundling,
709
+ * `import.meta.dir` points at `<package>/dist`. Do not resolve the package via
710
+ * bare `@oh-my-pi/pi-coding-agent` here: from a global install Bun can pick an
711
+ * older cache entry, recreating mixed-runtime plugin loading.
712
+ */
713
+ export function __computeBundledSelfPackageRoot(metaDir: string, pathImpl: typeof path = path): string {
714
+ const normalizedMetaDir = pathImpl.normalize(metaDir);
715
+ if (pathImpl.basename(normalizedMetaDir) === "dist") {
716
+ return pathImpl.resolve(metaDir, "..");
717
+ }
718
+
719
+ const pluginsDirSuffix = pathImpl.join("src", "extensibility", "plugins");
720
+ if (normalizedMetaDir.endsWith(pluginsDirSuffix)) {
721
+ return pathImpl.resolve(metaDir, "..", "..", "..");
722
+ }
723
+
724
+ return pathImpl.resolve(metaDir);
725
+ }
726
+
727
+ function resolveBundledSelfPackageRoot(): string | undefined {
728
+ if (!process.env.PI_BUNDLED) return undefined;
729
+ return __computeBundledSelfPackageRoot(import.meta.dir);
730
+ }
731
+
732
+ const BUNDLED_SELF_PACKAGE_ROOT = resolveBundledSelfPackageRoot();
733
+
734
+ function sourceShimPath(file: string): string {
735
+ return BUNDLED_SELF_PACKAGE_ROOT
736
+ ? path.join(BUNDLED_SELF_PACKAGE_ROOT, "src", "extensibility", file)
737
+ : path.resolve(import.meta.dir, "..", file);
738
+ }
739
+
740
+ /**
741
+ * Resolve the path the TypeBox compatibility shim ships at, then drop it when
742
+ * the source file is missing.
743
+ *
744
+ * In compiled-binary mode the shim is served through the
745
+ * `omp-legacy-pi-bundled:` virtual namespace (issue #3423) — bunfs paths are
746
+ * unreachable on Bun 1.3.14+, so the virtual specifier is always available and
747
+ * needs no filesystem probe. In dev / source-link / installed-package mode the
748
+ * shim is an on-disk source file; validation mirrors
749
+ * `__validateLegacyPiPackageRootOverrides` (#2168): if the computed candidate
750
+ * doesn't exist (e.g. an install that dropped the source — issue #3414),
751
+ * `resolveTypeBoxSpecifier` returns `undefined` and
752
+ * `rewriteLegacyExtensionSource` leaves bare `typebox` / `@sinclair/typebox`
753
+ * specifiers alone, so Bun falls through to native resolution against the
754
+ * extension's own `node_modules`.
755
+ *
756
+ * Exported for tests; production callers use `TYPEBOX_SHIM_PATH`.
757
+ */
758
+ export function __resolveTypeBoxShimPath(
759
+ isCompiled: boolean,
760
+ sourcePath: string,
761
+ pathExistsSync: (p: string) => boolean = fs.existsSync,
762
+ ): string | null {
763
+ if (isCompiled) {
764
+ return bundledModuleVirtualSpecifier(TYPEBOX_BUNDLED_MODULE_KEY);
765
+ }
766
+ return pathExistsSync(sourcePath) ? sourcePath : null;
767
+ }
768
+
769
+ const TYPEBOX_SHIM_PATH = __resolveTypeBoxShimPath(IS_COMPILED_BINARY, sourceShimPath("typebox.ts"));
770
+
771
+ // Legacy extensions historically imported `Type` (and `Static`/`TSchema`) from
772
+ // the package root of `@(scope)/pi-ai`. pi-ai 15.1.0 removed the runtime `Type`
773
+ // export (see `packages/ai/CHANGELOG.md`), so the bare canonical specifier no
774
+ // longer satisfies those imports. The override below redirects only the bare
775
+ // pi-ai package root onto a sibling shim that re-exports the canonical surface
776
+ // plus the borrowed `Type` runtime from the Zod-backed TypeBox shim. Subpath
777
+ // imports such as `@oh-my-pi/pi-ai/oauth` continue to resolve directly
778
+ // against the bundled pi-ai package.
779
+ const LEGACY_PI_AI_SHIM_PATH = IS_COMPILED_BINARY
780
+ ? bundledModuleVirtualSpecifier(`${CANONICAL_PI_SCOPE}/pi-ai`)
781
+ : sourceShimPath("legacy-pi-ai-shim.ts");
782
+
783
+ // The coding-agent's own `./src/index.ts` cannot be listed as an extra
784
+ // `bun --compile` entrypoint alongside the CLI entry without breaking binary
785
+ // startup (issue #1474 follow-up). In compiled-binary mode the legacy
786
+ // `@(scope)/pi-coding-agent` root therefore resolves through the bundled
787
+ // module shim; in dev / source-link / installed-package mode it points at the
788
+ // sibling source shim whose distinct file path avoids the #1474 collision
789
+ // while still re-exporting the canonical package surface.
790
+ const LEGACY_PI_CODING_AGENT_SHIM_PATH = IS_COMPILED_BINARY
791
+ ? bundledModuleVirtualSpecifier(`${CANONICAL_PI_SCOPE}/pi-coding-agent`)
792
+ : sourceShimPath("legacy-pi-coding-agent-shim.ts");
793
+
794
+ // Legacy pi-tui exported `decodeKittyPrintable` from its package root. The
795
+ // canonical TUI replaced it with the broader `decodePrintableKey`; route only
796
+ // legacy root imports through a sibling shim that preserves the old name.
797
+ const LEGACY_PI_TUI_SHIM_PATH = IS_COMPILED_BINARY
798
+ ? bundledModuleVirtualSpecifier(`${CANONICAL_PI_SCOPE}/pi-tui`)
799
+ : sourceShimPath("legacy-pi-tui-shim.ts");
800
+
801
+ // Package-root overrides. Shim entries (`pi-ai`, `pi-coding-agent`, `pi-tui`)
802
+ // always replace the canonical surface so legacy helpers stay reachable. The
803
+ // other bundled host packages (`pi-agent-core`, `pi-natives`, `pi-utils`) are
804
+ // added only in compiled-binary mode to route extensions onto the in-process
805
+ // module instance — in dev / source-link / installed-package mode the canonical
806
+ // specifier resolves cleanly through `Bun.resolveSync` and hardcoding a
807
+ // source-tree path would miss installs where bundled packages live at
808
+ // `node_modules/@oh-my-pi/pi-*`.
809
+ //
810
+ // Compiled-binary entries are `omp-legacy-pi-bundled:<key>` specifiers handed
811
+ // to the synthetic onLoad in `installLegacyPiSpecifierShim()` — bunfs paths
812
+ // are unusable on Bun 1.3.14+ (issue #3423). Filesystem-shaped overrides are
813
+ // still validated against on-disk presence so a missing dev-mode shim falls
814
+ // through to `getResolvedSpecifier`.
815
+
816
+ /**
817
+ * Drop overrides whose filesystem targets are missing so they can fall
818
+ * through to the canonical-resolution path. Virtual `omp-legacy-pi-bundled:`
819
+ * entries always pass — live bundled module references are the source of truth
820
+ * in compiled mode where bunfs paths are unreachable (issue #3423).
821
+ *
822
+ * `pathExistsSync` defaults to `fs.existsSync`; tests inject a stub to
823
+ * simulate the missing-entrypoint failure mode without touching the real FS.
824
+ */
825
+ export function __validateLegacyPiPackageRootOverrides(
826
+ candidates: Record<string, string>,
827
+ pathExistsSync: (p: string) => boolean = fs.existsSync,
828
+ ): Record<string, string> {
829
+ const valid: Record<string, string> = {};
830
+ for (const key in candidates) {
831
+ const candidate = candidates[key];
832
+ if (candidate && (isBundledVirtualSpecifier(candidate) || pathExistsSync(candidate))) {
833
+ valid[key] = candidate;
834
+ }
835
+ }
836
+ return valid;
837
+ }
838
+
839
+ /**
840
+ * Compute the override map keyed by every canonical specifier the host serves
841
+ * directly: the pi-ai / pi-coding-agent roots (compat shims that re-attach
842
+ * legacy helpers) plus, in compiled mode, every build-supplied module key.
843
+ * Subpath coverage stops `@(scope)/pi-ai/oauth` and friends from falling
844
+ * through to the extension's absent peer install when bunfs walks fail.
845
+ */
846
+ export function __buildLegacyPiPackageRootOverrides(
847
+ isCompiled: boolean,
848
+ bundledModuleKeys: Iterable<string> = [],
849
+ ): Record<string, string> {
850
+ const candidates: Record<string, string> = {
851
+ [`${CANONICAL_PI_SCOPE}/pi-ai`]: LEGACY_PI_AI_SHIM_PATH,
852
+ [`${CANONICAL_PI_SCOPE}/pi-coding-agent`]: LEGACY_PI_CODING_AGENT_SHIM_PATH,
853
+ [`${CANONICAL_PI_SCOPE}/pi-tui`]: LEGACY_PI_TUI_SHIM_PATH,
854
+ };
855
+ if (isCompiled) {
856
+ for (const key of bundledModuleKeys) {
857
+ // Shim-bearing roots already map to their compat surfaces; TypeBox
858
+ // has a dedicated TYPEBOX_SHIM_PATH route.
859
+ if (key in candidates || key === TYPEBOX_BUNDLED_MODULE_KEY) continue;
860
+ candidates[key] = bundledModuleVirtualSpecifier(key);
861
+ }
862
+ }
863
+ return __validateLegacyPiPackageRootOverrides(candidates);
864
+ }
865
+
866
+ // Seeded with compat roots at module init; first compiled extension load adds
867
+ // every key supplied by the in-memory build module.
868
+ let legacyPiPackageRootOverrides = __buildLegacyPiPackageRootOverrides(IS_COMPILED_BINARY);
869
+ let legacyPiOverridesReadyPromise: Promise<void> | null = null;
870
+
871
+ /** Complete compiled-mode overrides from the lazy host-module registry. */
872
+ function ensureLegacyPiOverridesReady(): Promise<void> {
873
+ if (!IS_COMPILED_BINARY) {
874
+ return Promise.resolve();
875
+ }
876
+ if (!legacyPiOverridesReadyPromise) {
877
+ legacyPiOverridesReadyPromise = ensureBundledModuleLoadersLoaded().then(loaders => {
878
+ legacyPiPackageRootOverrides = __buildLegacyPiPackageRootOverrides(true, Object.keys(loaders));
879
+ });
880
+ }
881
+ return legacyPiOverridesReadyPromise;
882
+ }
883
+
884
+ let isLegacyPiSpecifierShimInstalled = false;
885
+
886
+ function remapLegacyPiSpecifier(specifier: string): string | null {
887
+ if (!LEGACY_PI_SPECIFIER_FILTER.test(specifier)) {
888
+ return null;
889
+ }
890
+ const slashIdx = specifier.indexOf("/", 1);
891
+ // Filter guarantees a slash exists, but guard anyway to keep the type narrow.
892
+ if (slashIdx === -1) {
893
+ return null;
894
+ }
895
+ const rest = specifier.slice(slashIdx + 1);
896
+ const remappedSubpath = remapLegacyPiSubpath(rest);
897
+ return `${CANONICAL_PI_SCOPE}/${remappedSubpath}`;
898
+ }
899
+
900
+ function getResolvedSpecifier(specifier: string): string {
901
+ const cached = resolvedSpecifierFallbacks.get(specifier);
902
+ if (cached) {
903
+ return cached;
904
+ }
905
+
906
+ const resolved = Bun.resolveSync(specifier, import.meta.dir);
907
+ resolvedSpecifierFallbacks.set(specifier, resolved);
908
+ return resolved;
909
+ }
910
+
911
+ /**
912
+ * Resolve a canonical `@oh-my-pi/*` specifier to a filesystem path, preferring
913
+ * a bundled compat shim when one is registered for the package root.
914
+ *
915
+ * Falls back to `getResolvedSpecifier` (which may throw under compiled binary
916
+ * mode); callers handle that the same way they would for non-overridden
917
+ * specifiers.
918
+ */
919
+ function resolveCanonicalPiSpecifier(remappedSpecifier: string): string {
920
+ const override = legacyPiPackageRootOverrides[remappedSpecifier];
921
+ if (override) {
922
+ return override;
923
+ }
924
+ return getResolvedSpecifier(remappedSpecifier);
925
+ }
926
+
927
+ function toImportSpecifier(resolvedPath: string): string {
928
+ // Virtual `omp-legacy-pi-bundled:` specifiers are served by the synthetic
929
+ // onLoad in `installLegacyPiSpecifierShim()`; wrapping them as `file://`
930
+ // would corrupt the scheme.
931
+ if (isBundledVirtualSpecifier(resolvedPath)) {
932
+ return resolvedPath;
933
+ }
934
+ return url.pathToFileURL(stripWindowsExtendedLengthPathPrefix(resolvedPath)).href;
935
+ }
936
+
937
+ /**
938
+ * Rewrite the extension-owned specifiers OMP must host-resolve — legacy
939
+ * `@(scope)/pi-*`, bare TypeBox packages, package `imports` aliases like
940
+ * `#src/*`, and extension-local bare dependencies — to absolute `file://` URLs
941
+ * or compiled-mode virtual specifiers. Relative siblings and built-in modules
942
+ * are left untouched so Bun resolves them from the extension's real on-disk
943
+ * location.
944
+ *
945
+ * When `mtimeTag` is provided, extension-owned relative graph specifiers
946
+ * (`./`/`../`) and, by default, resolved package `#alias/*` and extension-local
947
+ * bare deps also carry a `?mtime=<tag>` cache-bust so Bun rekeys them on
948
+ * same-process reloads. `resolvedImportMtimeTag` can disable the tag for
949
+ * resolved package and bare ESM imports inside third-party dependencies, whose
950
+ * transitive ESM imports retain a query-free importer path for Bun's runtime
951
+ * `node_modules` resolution. Host package rewrites (legacy
952
+ * `@(scope)/pi-*`, TypeBox shim) always emit `file://` URLs because they resolve
953
+ * to in-process host code that never changes between reloads.
954
+ */
955
+ async function rewriteLegacyExtensionSource(
956
+ source: string,
957
+ importerPath: string,
958
+ mtimeTag: string | null = null,
959
+ resolvedImportMtimeTag: string | null = mtimeTag,
960
+ ): Promise<string> {
961
+ // Compiled mode completes the override map from the build-supplied module
962
+ // keys on first use; every rewrite path must see the full map.
963
+ await ensureLegacyPiOverridesReady();
964
+ const references = collectExtensionSpecifierReferences(source, importerPath);
965
+ const replacements: Array<ExtensionSpecifierReference & { replacement: string }> = [];
966
+ for (const reference of references) {
967
+ if (reference.kind !== "import") continue;
968
+
969
+ const specifier = reference.specifier;
970
+ let replacement: string | null = null;
971
+ const remappedSpecifier = remapLegacyPiSpecifier(specifier);
972
+ if (remappedSpecifier) {
973
+ try {
974
+ replacement = toImportSpecifier(resolveCanonicalPiSpecifier(remappedSpecifier));
975
+ } catch {
976
+ // Compiled fallback may be absent from a malformed build. Continue to
977
+ // the extension's on-disk peer dependency resolution below.
978
+ }
979
+ }
980
+ if (!replacement && TYPEBOX_SHIM_PATH && (specifier === "typebox" || specifier === "@sinclair/typebox")) {
981
+ replacement = toImportSpecifier(TYPEBOX_SHIM_PATH);
982
+ }
983
+ if (!replacement && specifier.startsWith("#")) {
984
+ const resolved = await resolvePackageImportSpecifier(specifier, importerPath);
985
+ if (resolved) replacement = toGraphImportSpecifier(resolved, resolvedImportMtimeTag);
986
+ }
987
+ if (!replacement && isBareExtensionDependencySpecifier(specifier)) {
988
+ const resolved = await resolveExtensionBareDependency(specifier, importerPath);
989
+ if (resolved) replacement = toGraphImportSpecifier(resolved, resolvedImportMtimeTag);
990
+ }
991
+ if (!replacement && mtimeTag && /^\.\.?\//.test(specifier) && !specifier.includes("?")) {
992
+ replacement = `${specifier}?mtime=${mtimeTag}`;
993
+ }
994
+ if (replacement && replacement !== specifier) {
995
+ replacements.push({ ...reference, replacement });
996
+ }
997
+ }
998
+ const withImports = applySpecifierReplacements(source, replacements);
999
+ return rewriteExtensionSpecifiers(withImports, importerPath);
1000
+ }
1001
+
1002
+ /** Test seam for compiled-binary legacy extension source rewriting. */
1003
+ export async function __rewriteLegacyExtensionSourceForTests(
1004
+ source: string,
1005
+ importerPath: string,
1006
+ mtimeTag: string | null = null,
1007
+ resolvedImportMtimeTag: string | null = mtimeTag,
1008
+ ): Promise<string> {
1009
+ return rewriteLegacyExtensionSource(source, importerPath, mtimeTag, resolvedImportMtimeTag);
1010
+ }
1011
+
1012
+ /**
1013
+ * Build the import specifier for a graph-resolved absolute path. POSIX
1014
+ * emits a bare filesystem path with an optional `?mtime=<tag>` (Bun keys
1015
+ * query strings for bare-path specifiers), so same-process extension
1016
+ * reloads pick up edits to package-alias (`#foo/*`) and extension-local
1017
+ * bare deps. Windows and bundled virtual specifiers keep the current
1018
+ * `file://` / virtual form — Bun ignores queries on `file://` URLs, so
1019
+ * cache-bust does not reach Windows extensions until Bun changes that.
1020
+ */
1021
+ function toGraphImportSpecifier(resolvedPath: string, mtimeTag: string | null): string {
1022
+ if (isBundledVirtualSpecifier(resolvedPath)) {
1023
+ return resolvedPath;
1024
+ }
1025
+ if (process.platform === "win32" || !mtimeTag) {
1026
+ return url.pathToFileURL(stripWindowsExtendedLengthPathPrefix(resolvedPath)).href;
1027
+ }
1028
+ return `${stripWindowsExtendedLengthPathPrefix(resolvedPath)}?mtime=${mtimeTag}`;
1029
+ }
1030
+
1031
+ function isRecord(value: unknown): value is Record<string, unknown> {
1032
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1033
+ }
1034
+
1035
+ async function pathExists(p: string): Promise<boolean> {
1036
+ try {
1037
+ await fs.promises.stat(p);
1038
+ return true;
1039
+ } catch {
1040
+ return false;
1041
+ }
1042
+ }
1043
+
1044
+ function hasSourceModuleExtension(p: string): boolean {
1045
+ const ext = path.extname(p).toLowerCase();
1046
+ return (SOURCE_MODULE_EXTENSIONS as readonly string[]).includes(ext);
1047
+ }
1048
+
1049
+ async function resolveSourceModuleFile(basePath: string): Promise<string | null> {
1050
+ try {
1051
+ const stats = await fs.promises.stat(basePath);
1052
+ if (stats.isFile()) {
1053
+ // Non-source files (JSON, WASM, text assets, etc.) bypass the on-load
1054
+ // rewrite hook so Bun's native loaders handle them; our hook would
1055
+ // otherwise pass them through `getLoader()` which falls back to `js`.
1056
+ return hasSourceModuleExtension(basePath) ? realpathOrSelf(basePath) : null;
1057
+ }
1058
+ if (stats.isDirectory()) {
1059
+ for (const extension of SOURCE_MODULE_EXTENSIONS) {
1060
+ const resolved = await resolveSourceModuleFile(path.join(basePath, `index${extension}`));
1061
+ if (resolved) return resolved;
1062
+ }
1063
+ }
1064
+ } catch {
1065
+ // Fall through to extension candidates below.
1066
+ }
1067
+
1068
+ if (path.extname(basePath)) {
1069
+ return null;
1070
+ }
1071
+
1072
+ for (const extension of SOURCE_MODULE_EXTENSIONS) {
1073
+ const resolved = await resolveSourceModuleFile(`${basePath}${extension}`);
1074
+ if (resolved) return resolved;
1075
+ }
1076
+ return null;
1077
+ }
1078
+
1079
+ function isPathInsideRoot(rootPath: string, candidatePath: string): boolean {
1080
+ const relative = path.relative(rootPath, candidatePath);
1081
+ return relative === "" || (relative !== ".." && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative));
1082
+ }
1083
+
1084
+ async function resolvePackageSourceTarget(packageRoot: string, targetPath: string): Promise<string | null> {
1085
+ const candidate = path.resolve(targetPath);
1086
+ if (!isPathInsideRoot(path.resolve(packageRoot), candidate)) {
1087
+ return null;
1088
+ }
1089
+ const resolved = await resolveSourceModuleFile(candidate);
1090
+ if (!resolved) {
1091
+ return null;
1092
+ }
1093
+ const realPackageRoot = await realpathOrSelf(packageRoot);
1094
+ return isPathInsideRoot(realPackageRoot, resolved) ? resolved : null;
1095
+ }
1096
+
1097
+ async function resolvePackageFileTarget(packageRoot: string, targetPath: string): Promise<string | null> {
1098
+ const candidate = path.resolve(targetPath);
1099
+ if (!isPathInsideRoot(path.resolve(packageRoot), candidate) || !(await pathExists(candidate))) {
1100
+ return null;
1101
+ }
1102
+ const [realPackageRoot, resolved] = await Promise.all([realpathOrSelf(packageRoot), realpathOrSelf(candidate)]);
1103
+ return isPathInsideRoot(realPackageRoot, resolved) ? resolved : null;
1104
+ }
1105
+
1106
+ async function findPackageRoot(importerPath: string): Promise<string | null> {
1107
+ let dir = path.dirname(importerPath);
1108
+ while (true) {
1109
+ const cached = packageRootCache.get(dir);
1110
+ if (cached !== undefined) {
1111
+ return cached;
1112
+ }
1113
+
1114
+ if (await pathExists(path.join(dir, "package.json"))) {
1115
+ packageRootCache.set(path.dirname(importerPath), dir);
1116
+ return dir;
1117
+ }
1118
+
1119
+ const parent = path.dirname(dir);
1120
+ if (parent === dir) {
1121
+ packageRootCache.set(path.dirname(importerPath), null);
1122
+ return null;
1123
+ }
1124
+ dir = parent;
1125
+ }
1126
+ }
1127
+
1128
+ async function readPackageImports(packageRoot: string): Promise<Record<string, unknown> | null> {
1129
+ const cached = packageImportsCache.get(packageRoot);
1130
+ if (cached !== undefined) {
1131
+ return cached;
1132
+ }
1133
+
1134
+ let imports: Record<string, unknown> | null = null;
1135
+ try {
1136
+ const pkg = await Bun.file(path.join(packageRoot, "package.json")).json();
1137
+ if (isRecord(pkg) && isRecord(pkg.imports)) {
1138
+ imports = pkg.imports;
1139
+ }
1140
+ } catch {
1141
+ imports = null;
1142
+ }
1143
+ packageImportsCache.set(packageRoot, imports);
1144
+ return imports;
1145
+ }
1146
+
1147
+ type PackageImportTargetSelection = string | typeof PACKAGE_IMPORT_EXCLUDED | null;
1148
+ type ResolvedPackageImportTargetSelection = string | typeof PACKAGE_IMPORT_EXCLUDED;
1149
+
1150
+ function selectPackageImportTarget(
1151
+ entry: unknown,
1152
+ conditions: ReadonlySet<string> = SUPPORTED_PACKAGE_IMPORT_CONDITIONS,
1153
+ ): PackageImportTargetSelection {
1154
+ if (entry === null) {
1155
+ return PACKAGE_IMPORT_EXCLUDED;
1156
+ }
1157
+ if (typeof entry === "string") {
1158
+ return entry;
1159
+ }
1160
+ if (Array.isArray(entry)) {
1161
+ for (const item of entry) {
1162
+ const target = selectPackageImportTarget(item, conditions);
1163
+ if (target !== null) return target;
1164
+ }
1165
+ return null;
1166
+ }
1167
+ if (!isRecord(entry)) {
1168
+ return null;
1169
+ }
1170
+ for (const [condition, value] of Object.entries(entry)) {
1171
+ if (!conditions.has(condition)) {
1172
+ continue;
1173
+ }
1174
+ const target = selectPackageImportTarget(value, conditions);
1175
+ if (target !== null) return target;
1176
+ }
1177
+ return null;
1178
+ }
1179
+
1180
+ async function resolvePackageImportTarget(
1181
+ packageRoot: string,
1182
+ target: string,
1183
+ wildcard: string | null,
1184
+ ): Promise<string | null> {
1185
+ if (!target.startsWith("./")) {
1186
+ return null;
1187
+ }
1188
+ const substituted = wildcard === null ? target : target.replaceAll("*", wildcard);
1189
+ return resolvePackageSourceTarget(packageRoot, path.resolve(packageRoot, substituted));
1190
+ }
1191
+
1192
+ async function resolvePackageImportSpecifier(specifier: string, importerPath: string): Promise<string | null> {
1193
+ if (!specifier.startsWith("#")) {
1194
+ return null;
1195
+ }
1196
+
1197
+ const packageRoot = await findPackageRoot(importerPath);
1198
+ if (!packageRoot) {
1199
+ return null;
1200
+ }
1201
+
1202
+ const imports = await readPackageImports(packageRoot);
1203
+ if (!imports) {
1204
+ return null;
1205
+ }
1206
+
1207
+ const exactTarget = selectPackageImportTarget(imports[specifier]);
1208
+ if (exactTarget === PACKAGE_IMPORT_EXCLUDED) {
1209
+ return null;
1210
+ }
1211
+ if (exactTarget !== null) {
1212
+ return resolvePackageImportTarget(packageRoot, exactTarget, null);
1213
+ }
1214
+
1215
+ let bestMatch: { keyLength: number; target: ResolvedPackageImportTargetSelection; wildcard: string } | null = null;
1216
+ for (const [key, entry] of Object.entries(imports)) {
1217
+ const starIndex = key.indexOf("*");
1218
+ if (starIndex === -1) continue;
1219
+
1220
+ const prefix = key.slice(0, starIndex);
1221
+ const suffix = key.slice(starIndex + 1);
1222
+ if (!specifier.startsWith(prefix) || !specifier.endsWith(suffix)) {
1223
+ continue;
1224
+ }
1225
+
1226
+ const target = selectPackageImportTarget(entry);
1227
+ if (target === null) {
1228
+ continue;
1229
+ }
1230
+
1231
+ if (!bestMatch || key.length > bestMatch.keyLength) {
1232
+ bestMatch = {
1233
+ keyLength: key.length,
1234
+ target,
1235
+ wildcard: specifier.slice(prefix.length, specifier.length - suffix.length),
1236
+ };
1237
+ }
1238
+ }
1239
+
1240
+ if (!bestMatch || bestMatch.target === PACKAGE_IMPORT_EXCLUDED) {
1241
+ return null;
1242
+ }
1243
+ return resolvePackageImportTarget(packageRoot, bestMatch.target, bestMatch.wildcard);
1244
+ }
1245
+
1246
+ function isBareExtensionDependencySpecifier(specifier: string): boolean {
1247
+ if (
1248
+ specifier.startsWith(".") ||
1249
+ specifier.startsWith("/") ||
1250
+ specifier.startsWith("#") ||
1251
+ specifier.startsWith("node:") ||
1252
+ specifier.startsWith("bun:") ||
1253
+ /^[a-z][a-z0-9+.-]*:/i.test(specifier)
1254
+ ) {
1255
+ return false;
1256
+ }
1257
+ const packageName = specifier.startsWith("@") ? specifier.split("/").slice(0, 2).join("/") : specifier.split("/")[0];
1258
+ return Boolean(packageName && !isBuiltin(packageName));
1259
+ }
1260
+
1261
+ interface BarePackageSpecifier {
1262
+ readonly name: string;
1263
+ readonly subpath: string | null;
1264
+ }
1265
+
1266
+ function splitBarePackageSpecifier(specifier: string): BarePackageSpecifier | null {
1267
+ const parts = specifier.split("/");
1268
+ if (specifier.startsWith("@")) {
1269
+ const [scope, name, ...rest] = parts;
1270
+ if (!scope || !name) return null;
1271
+ return { name: `${scope}/${name}`, subpath: rest.length > 0 ? rest.join("/") : null };
1272
+ }
1273
+ const [name, ...rest] = parts;
1274
+ if (!name) return null;
1275
+ return { name, subpath: rest.length > 0 ? rest.join("/") : null };
1276
+ }
1277
+
1278
+ async function findNodePackageRoot(packageName: string, importerPath: string): Promise<string | null> {
1279
+ const cacheKey = `${packageName}\0${path.resolve(path.dirname(importerPath))}`;
1280
+ const cached = nodePackageRootCache.get(cacheKey);
1281
+ if (cached) return cached;
1282
+
1283
+ const promise = findNodePackageRootUncached(packageName, importerPath);
1284
+ nodePackageRootCache.set(cacheKey, promise);
1285
+ return promise;
1286
+ }
1287
+
1288
+ async function findNodePackageRootUncached(packageName: string, importerPath: string): Promise<string | null> {
1289
+ let dir = path.dirname(importerPath);
1290
+ while (true) {
1291
+ const candidate = path.join(dir, "node_modules", packageName);
1292
+ if (await pathExists(path.join(candidate, "package.json"))) {
1293
+ return candidate;
1294
+ }
1295
+ const parent = path.dirname(dir);
1296
+ if (parent === dir) {
1297
+ return null;
1298
+ }
1299
+ dir = parent;
1300
+ }
1301
+ }
1302
+
1303
+ async function readPackageManifest(packageRoot: string): Promise<Record<string, unknown> | null> {
1304
+ const cached = packageManifestCache.get(packageRoot);
1305
+ if (cached) return cached;
1306
+
1307
+ const promise = readPackageManifestUncached(packageRoot);
1308
+ packageManifestCache.set(packageRoot, promise);
1309
+ return promise;
1310
+ }
1311
+
1312
+ async function readPackageManifestUncached(packageRoot: string): Promise<Record<string, unknown> | null> {
1313
+ try {
1314
+ const manifest = await Bun.file(path.join(packageRoot, "package.json")).json();
1315
+ return isRecord(manifest) ? manifest : null;
1316
+ } catch {
1317
+ return null;
1318
+ }
1319
+ }
1320
+
1321
+ type ExtensionModuleKind = "commonjs" | "esm";
1322
+ class ExtensionModuleKindConflictError extends Error {}
1323
+
1324
+ async function isCommonJsModulePath(
1325
+ modulePath: string,
1326
+ sourceType?: "script" | "module",
1327
+ inheritedKind?: ExtensionModuleKind,
1328
+ ): Promise<boolean> {
1329
+ const extension = path.extname(modulePath).toLowerCase();
1330
+ if (extension === ".cjs" || extension === ".cts") {
1331
+ return true;
1332
+ }
1333
+ if (extension !== ".js" && extension !== ".jsx") {
1334
+ return false;
1335
+ }
1336
+
1337
+ const packageRoot = await findPackageRoot(modulePath);
1338
+ const manifest = packageRoot ? await readPackageManifest(packageRoot) : null;
1339
+ if (manifest?.type === "module") {
1340
+ return false;
1341
+ }
1342
+ if (manifest?.type === "commonjs") {
1343
+ return true;
1344
+ }
1345
+ const parsedSourceType =
1346
+ sourceType ?? parseExtensionSource(await Bun.file(modulePath).text(), modulePath).program.sourceType;
1347
+ if (parsedSourceType === "module") {
1348
+ return false;
1349
+ }
1350
+ if (inheritedKind) {
1351
+ return inheritedKind === "commonjs";
1352
+ }
1353
+ const declaredModuleEntry =
1354
+ packageRoot && typeof manifest?.module === "string"
1355
+ ? await resolvePackageSourceTarget(packageRoot, path.resolve(packageRoot, manifest.module))
1356
+ : null;
1357
+ return !declaredModuleEntry || path.resolve(modulePath) !== path.resolve(declaredModuleEntry);
1358
+ }
1359
+
1360
+ async function isGraphOwnedCommonJsModule(
1361
+ modulePath: string,
1362
+ entryRealPath: string,
1363
+ sourceType?: "script" | "module",
1364
+ inheritedKind?: ExtensionModuleKind,
1365
+ ): Promise<boolean> {
1366
+ const extension = path.extname(modulePath).toLowerCase();
1367
+ if (modulePath === entryRealPath && extension !== ".cjs" && extension !== ".cts") {
1368
+ return false;
1369
+ }
1370
+ return isCommonJsModulePath(modulePath, sourceType, inheritedKind);
1371
+ }
1372
+
1373
+ async function resolvePackageExportTarget(
1374
+ packageRoot: string,
1375
+ target: string,
1376
+ wildcard: string | null,
1377
+ ): Promise<string | null> {
1378
+ if (!target.startsWith("./")) {
1379
+ return null;
1380
+ }
1381
+ const substituted = wildcard === null ? target : target.replaceAll("*", wildcard);
1382
+ return resolvePackageSourceTarget(packageRoot, path.resolve(packageRoot, substituted));
1383
+ }
1384
+
1385
+ async function resolveNodePackageExport(
1386
+ packageRoot: string,
1387
+ subpath: string | null,
1388
+ manifest: Record<string, unknown>,
1389
+ conditions: ReadonlySet<string> = SUPPORTED_PACKAGE_IMPORT_CONDITIONS,
1390
+ ): Promise<string | null> {
1391
+ const exportsField = manifest.exports;
1392
+ const rootTarget = subpath === null ? selectPackageImportTarget(exportsField, conditions) : null;
1393
+ if (rootTarget !== null && rootTarget !== PACKAGE_IMPORT_EXCLUDED) {
1394
+ return resolvePackageExportTarget(packageRoot, rootTarget, null);
1395
+ }
1396
+ if (!isRecord(exportsField)) {
1397
+ return null;
1398
+ }
1399
+
1400
+ const exactKey = subpath === null ? "." : `./${subpath}`;
1401
+ if (Object.hasOwn(exportsField, exactKey)) {
1402
+ const exactTarget = selectPackageImportTarget(exportsField[exactKey], conditions);
1403
+ return exactTarget !== null && exactTarget !== PACKAGE_IMPORT_EXCLUDED
1404
+ ? resolvePackageExportTarget(packageRoot, exactTarget, null)
1405
+ : null;
1406
+ }
1407
+
1408
+ let bestMatch: {
1409
+ keyLength: number;
1410
+ prefixLength: number;
1411
+ target: PackageImportTargetSelection;
1412
+ wildcard: string;
1413
+ } | null = null;
1414
+ for (const [key, entry] of Object.entries(exportsField)) {
1415
+ const starIndex = key.indexOf("*");
1416
+ if (starIndex === -1 || subpath === null || !key.startsWith("./")) continue;
1417
+ const prefix = key.slice(2, starIndex);
1418
+ const suffix = key.slice(starIndex + 1);
1419
+ if (!subpath.startsWith(prefix) || !subpath.endsWith(suffix)) continue;
1420
+ if (
1421
+ !bestMatch ||
1422
+ prefix.length > bestMatch.prefixLength ||
1423
+ (prefix.length === bestMatch.prefixLength && key.length > bestMatch.keyLength)
1424
+ ) {
1425
+ bestMatch = {
1426
+ keyLength: key.length,
1427
+ prefixLength: prefix.length,
1428
+ target: selectPackageImportTarget(entry, conditions),
1429
+ wildcard: subpath.slice(prefix.length, subpath.length - suffix.length),
1430
+ };
1431
+ }
1432
+ }
1433
+ return bestMatch?.target && bestMatch.target !== PACKAGE_IMPORT_EXCLUDED
1434
+ ? resolvePackageExportTarget(packageRoot, bestMatch.target, bestMatch.wildcard)
1435
+ : null;
1436
+ }
1437
+
1438
+ async function resolveNodePackageFallback(
1439
+ packageRoot: string,
1440
+ subpath: string | null,
1441
+ manifest: Record<string, unknown>,
1442
+ ): Promise<string | null> {
1443
+ if (subpath !== null) {
1444
+ return resolvePackageSourceTarget(packageRoot, path.join(packageRoot, subpath));
1445
+ }
1446
+ for (const field of ["module", "main"]) {
1447
+ const target = manifest[field];
1448
+ if (typeof target === "string") {
1449
+ const resolved = await resolvePackageSourceTarget(packageRoot, path.resolve(packageRoot, target));
1450
+ if (resolved) return resolved;
1451
+ }
1452
+ }
1453
+ return resolvePackageSourceTarget(packageRoot, path.join(packageRoot, "index"));
1454
+ }
1455
+
1456
+ async function resolveNodePackageDependency(specifier: string, importerPath: string): Promise<string | null> {
1457
+ const parsed = splitBarePackageSpecifier(specifier);
1458
+ if (!parsed) return null;
1459
+ const packageRoot = await findNodePackageRoot(parsed.name, importerPath);
1460
+ if (!packageRoot) return null;
1461
+ const manifest = await readPackageManifest(packageRoot);
1462
+ if (!manifest) return null;
1463
+ return Object.hasOwn(manifest, "exports")
1464
+ ? resolveNodePackageExport(packageRoot, parsed.subpath, manifest)
1465
+ : resolveNodePackageFallback(packageRoot, parsed.subpath, manifest);
1466
+ }
1467
+
1468
+ async function resolveNodePackageRequire(specifier: string, importerPath: string): Promise<string | null> {
1469
+ const parsed = splitBarePackageSpecifier(specifier);
1470
+ if (!parsed) return null;
1471
+ const packageRoot = await findNodePackageRoot(parsed.name, importerPath);
1472
+ if (!packageRoot) return null;
1473
+ const manifest = await readPackageManifest(packageRoot);
1474
+ if (!manifest) return null;
1475
+
1476
+ if (Object.hasOwn(manifest, "exports")) {
1477
+ return resolveNodePackageExport(packageRoot, parsed.subpath, manifest, SUPPORTED_PACKAGE_REQUIRE_CONDITIONS);
1478
+ }
1479
+ if (parsed.subpath !== null) {
1480
+ return resolvePackageSourceTarget(packageRoot, path.join(packageRoot, parsed.subpath));
1481
+ }
1482
+ const main = manifest.main;
1483
+ return typeof main === "string"
1484
+ ? await resolvePackageSourceTarget(packageRoot, path.resolve(packageRoot, main))
1485
+ : await resolvePackageSourceTarget(packageRoot, path.join(packageRoot, "index"));
1486
+ }
1487
+
1488
+ async function validateResolvedBarePackagePath(
1489
+ specifier: string,
1490
+ importerPath: string,
1491
+ resolvedPath: string,
1492
+ ): Promise<string | null> {
1493
+ const parsed = splitBarePackageSpecifier(specifier);
1494
+ const packageRoot = parsed ? await findNodePackageRoot(parsed.name, importerPath) : null;
1495
+ return packageRoot ? resolvePackageFileTarget(packageRoot, resolvedPath) : null;
1496
+ }
1497
+
1498
+ async function isSelectedNoTypeEsmPackageBranch(
1499
+ specifier: string,
1500
+ importerPath: string,
1501
+ resolvedPath: string,
1502
+ ): Promise<boolean> {
1503
+ const parsed = splitBarePackageSpecifier(specifier);
1504
+ const packageRoot = parsed ? await findNodePackageRoot(parsed.name, importerPath) : null;
1505
+ const manifest = packageRoot ? await readPackageManifest(packageRoot) : null;
1506
+ if (!packageRoot || !manifest || manifest.type !== undefined) {
1507
+ return false;
1508
+ }
1509
+ if (parsed?.subpath === null && typeof manifest.module === "string") {
1510
+ const moduleEntry = await resolvePackageSourceTarget(packageRoot, path.resolve(packageRoot, manifest.module));
1511
+ if (moduleEntry && path.resolve(moduleEntry) === path.resolve(resolvedPath)) {
1512
+ return true;
1513
+ }
1514
+ }
1515
+ if (!Object.hasOwn(manifest, "exports")) {
1516
+ return false;
1517
+ }
1518
+ const importTarget = await resolveNodePackageExport(packageRoot, parsed?.subpath ?? null, manifest);
1519
+ const requireTarget = await resolveNodePackageExport(
1520
+ packageRoot,
1521
+ parsed?.subpath ?? null,
1522
+ manifest,
1523
+ SUPPORTED_PACKAGE_REQUIRE_CONDITIONS,
1524
+ );
1525
+ return Boolean(
1526
+ importTarget &&
1527
+ path.resolve(importTarget) === path.resolve(resolvedPath) &&
1528
+ (!requireTarget || path.resolve(requireTarget) !== path.resolve(importTarget)),
1529
+ );
1530
+ }
1531
+
1532
+ async function resolveExtensionBareDependency(specifier: string, importerPath: string): Promise<string | null> {
1533
+ if (!isBareExtensionDependencySpecifier(specifier)) {
1534
+ return null;
1535
+ }
1536
+
1537
+ const cacheKey = `${specifier}\0${path.resolve(path.dirname(importerPath))}`;
1538
+ const cached = bareDependencyResolutionCache.get(cacheKey);
1539
+ if (cached) return cached;
1540
+
1541
+ const promise = resolveExtensionBareDependencyUncached(specifier, importerPath);
1542
+ bareDependencyResolutionCache.set(cacheKey, promise);
1543
+ return promise;
1544
+ }
1545
+
1546
+ async function resolveExtensionBareDependencyUncached(specifier: string, importerPath: string): Promise<string | null> {
1547
+ // Resolve against the runtime package manifest first. Besides working in a
1548
+ // compiled binary, this preserves the package's ESM `import` condition when
1549
+ // the absolute target is later loaded outside normal package resolution.
1550
+ const packageResolved = await resolveNodePackageDependency(specifier, importerPath);
1551
+ if (packageResolved) {
1552
+ return packageResolved;
1553
+ }
1554
+ try {
1555
+ const resolved = Bun.resolveSync(specifier, path.dirname(importerPath));
1556
+ if (resolved && resolved !== specifier && !resolved.startsWith("node:") && !resolved.startsWith("bun:")) {
1557
+ return validateResolvedBarePackagePath(specifier, importerPath, resolved);
1558
+ }
1559
+ } catch {
1560
+ // Compiled binaries do not reliably resolve runtime extension node_modules.
1561
+ }
1562
+ return null;
1563
+ }
1564
+
1565
+ const NATIVE_ADDON_EXTENSION = ".node";
1566
+
1567
+ /**
1568
+ * Resolve a bare specifier whose target is a native `.node` addon — either a
1569
+ * package subpath ending in `.node`, or a package whose `main` points at an
1570
+ * addon (the napi-rs per-platform package convention, e.g.
1571
+ * `@yuuang/ffi-rs-darwin-arm64` → `ffi-rs.darwin-arm64.node`). Returns the
1572
+ * addon's absolute realpath, or null when the specifier is not a native addon.
1573
+ */
1574
+ async function resolveExtensionNativeAddon(specifier: string, importerPath: string): Promise<string | null> {
1575
+ if (!isBareExtensionDependencySpecifier(specifier)) {
1576
+ return null;
1577
+ }
1578
+
1579
+ const cacheKey = `${specifier}\0${path.resolve(path.dirname(importerPath))}`;
1580
+ const cached = nativeAddonResolutionCache.get(cacheKey);
1581
+ if (cached) return cached;
1582
+
1583
+ const promise = resolveExtensionNativeAddonUncached(specifier, importerPath);
1584
+ nativeAddonResolutionCache.set(cacheKey, promise);
1585
+ return promise;
1586
+ }
1587
+
1588
+ async function resolveExtensionNativeAddonUncached(specifier: string, importerPath: string): Promise<string | null> {
1589
+ const parsed = splitBarePackageSpecifier(specifier);
1590
+ if (!parsed) return null;
1591
+ const packageRoot = await findNodePackageRoot(parsed.name, importerPath);
1592
+ if (!packageRoot) return null;
1593
+
1594
+ let target: string | null = null;
1595
+ if (parsed.subpath !== null) {
1596
+ target = parsed.subpath.endsWith(NATIVE_ADDON_EXTENSION) ? path.join(packageRoot, parsed.subpath) : null;
1597
+ } else {
1598
+ const manifest = await readPackageManifest(packageRoot);
1599
+ const main = manifest?.main;
1600
+ target =
1601
+ typeof main === "string" && main.endsWith(NATIVE_ADDON_EXTENSION) ? path.resolve(packageRoot, main) : null;
1602
+ }
1603
+ if (!target) {
1604
+ return null;
1605
+ }
1606
+ return resolvePackageFileTarget(packageRoot, target);
1607
+ }
1608
+
1609
+ async function resolveExtensionBareRequire(specifier: string, importerPath: string): Promise<string | null> {
1610
+ if (!isBareExtensionDependencySpecifier(specifier)) {
1611
+ return null;
1612
+ }
1613
+
1614
+ const cacheKey = `${specifier}\0${path.resolve(path.dirname(importerPath))}`;
1615
+ const cached = bareRequireResolutionCache.get(cacheKey);
1616
+ if (cached) return cached;
1617
+
1618
+ const resolution = (async () => {
1619
+ const nativeAddon = await resolveExtensionNativeAddon(specifier, importerPath);
1620
+ if (nativeAddon) {
1621
+ return nativeAddon;
1622
+ }
1623
+ const packageResolved = await resolveNodePackageRequire(specifier, importerPath);
1624
+ if (packageResolved) {
1625
+ return realpathOrSelf(packageResolved);
1626
+ }
1627
+ try {
1628
+ const resolved = createRequire(importerPath).resolve(specifier);
1629
+ return resolved === specifier || resolved.startsWith("node:") || resolved.startsWith("bun:")
1630
+ ? null
1631
+ : await validateResolvedBarePackagePath(specifier, importerPath, resolved);
1632
+ } catch {
1633
+ return null;
1634
+ }
1635
+ })();
1636
+ bareRequireResolutionCache.set(cacheKey, resolution);
1637
+ return resolution;
1638
+ }
1639
+
1640
+ async function resolveExtensionCommonJsRequire(specifier: string, importerPath: string): Promise<string | null> {
1641
+ const remappedSpecifier = remapLegacyPiSpecifier(specifier);
1642
+ if (remappedSpecifier) {
1643
+ try {
1644
+ const resolved = resolveCanonicalPiSpecifier(remappedSpecifier);
1645
+ if (isBundledVirtualSpecifier(resolved)) {
1646
+ const moduleKey = resolved.slice(BUNDLED_VIRTUAL_SCHEME.length);
1647
+ if (!(moduleKey in loadedBundledModules)) {
1648
+ await loadBundledModule(moduleKey);
1649
+ }
1650
+ }
1651
+ return resolved;
1652
+ } catch {
1653
+ // A malformed compiled registry can still fall through to an
1654
+ // extension-installed legacy peer dependency.
1655
+ }
1656
+ }
1657
+ return resolveExtensionBareRequire(specifier, importerPath);
1658
+ }
1659
+
1660
+ /**
1661
+ * Rewrite CommonJS graph specifiers that cannot resolve from the bridge's
1662
+ * generated function: bare `require()` calls and, for graph-owned CommonJS
1663
+ * sources, import specifiers. Resolved targets are retained for synchronous
1664
+ * lazy hydration after load-time source caches clear.
1665
+ */
1666
+ async function rewriteExtensionSpecifiers(
1667
+ source: string,
1668
+ importerPath: string,
1669
+ rewriteImports = false,
1670
+ ): Promise<string> {
1671
+ const references = collectExtensionSpecifierReferences(source, importerPath);
1672
+ const resolvedSpecifierTargets = new Map<string, string>();
1673
+ const replacements: Array<ExtensionSpecifierReference & { replacement: string }> = [];
1674
+ for (const reference of references) {
1675
+ let resolved: string | null = null;
1676
+ if (reference.kind === "require") {
1677
+ resolved = await resolveExtensionCommonJsRequire(reference.specifier, importerPath);
1678
+ } else if (rewriteImports) {
1679
+ if (reference.specifier.startsWith(".")) {
1680
+ const candidate = Bun.resolveSync(reference.specifier, path.dirname(importerPath));
1681
+ resolved = hasSourceModuleExtension(candidate) ? await realpathOrSelf(candidate) : null;
1682
+ } else if (reference.specifier.startsWith("#")) {
1683
+ resolved = await resolvePackageImportSpecifier(reference.specifier, importerPath);
1684
+ } else {
1685
+ resolved = await resolveExtensionBareDependency(reference.specifier, importerPath);
1686
+ }
1687
+ }
1688
+ if (!resolved) continue;
1689
+ const replacement = stripWindowsExtendedLengthPathPrefix(resolved).replaceAll("\\", "/");
1690
+ resolvedSpecifierTargets.set(`${reference.kind}\0${reference.specifier}`, replacement);
1691
+ replacements.push({ ...reference, replacement });
1692
+ }
1693
+ extensionSynchronousSpecifierTargets.set(importerPath, resolvedSpecifierTargets);
1694
+ return applySpecifierReplacements(source, replacements);
1695
+ }
1696
+
1697
+ function rewriteExtensionSpecifiersFromCache(source: string, importerPath: string): string {
1698
+ const resolvedSpecifierTargets = extensionSynchronousSpecifierTargets.get(importerPath);
1699
+ if (!resolvedSpecifierTargets || resolvedSpecifierTargets.size === 0) {
1700
+ return source;
1701
+ }
1702
+ const replacements: Array<ExtensionSpecifierReference & { replacement: string }> = [];
1703
+ for (const reference of collectExtensionSpecifierReferences(source, importerPath)) {
1704
+ const replacement = resolvedSpecifierTargets.get(`${reference.kind}\0${reference.specifier}`);
1705
+ if (replacement) {
1706
+ replacements.push({ ...reference, replacement });
1707
+ }
1708
+ }
1709
+ return applySpecifierReplacements(source, replacements);
1710
+ }
1711
+
1712
+ /**
1713
+ * Whether a module's source contains a bare require that resolves to a native
1714
+ * `.node` addon — i.e. a napi-rs style loader that must be hooked into the
1715
+ * extension graph so {@link rewriteExtensionSpecifiers} can pin its
1716
+ * platform-package requires to absolute paths.
1717
+ */
1718
+ async function moduleRequiresNativeAddon(modulePath: string): Promise<boolean> {
1719
+ const cached = nativeAddonRequireScanCache.get(modulePath);
1720
+ if (cached) return cached;
1721
+
1722
+ const promise = moduleRequiresNativeAddonUncached(modulePath);
1723
+ nativeAddonRequireScanCache.set(modulePath, promise);
1724
+ return promise;
1725
+ }
1726
+
1727
+ async function moduleRequiresNativeAddonUncached(modulePath: string): Promise<boolean> {
1728
+ let source: string;
1729
+ try {
1730
+ source = await Bun.file(modulePath).text();
1731
+ } catch {
1732
+ return false;
1733
+ }
1734
+ for (const reference of collectExtensionSpecifierReferences(source, modulePath)) {
1735
+ if (reference.kind === "require" && (await resolveExtensionNativeAddon(reference.specifier, modulePath))) {
1736
+ return true;
1737
+ }
1738
+ }
1739
+ return false;
1740
+ }
1741
+
1742
+ function escapeRegExp(value: string): string {
1743
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1744
+ }
1745
+
1746
+ // Source modules in an extension graph are discovered from parsed static,
1747
+ // dynamic, re-export, and direct CommonJS require specifiers. Parsing keeps
1748
+ // import-looking text in strings, templates, regex literals, and comments out
1749
+ // of dependency resolution.
1750
+
1751
+ // Extension source realpaths already covered by an installed load-time hook for
1752
+ // each entry. `Bun.plugin()` registrations are process-global and permanent, so
1753
+ // reloads install supplemental hooks only for modules added to the graph since
1754
+ // the previous load.
1755
+ const extensionGraphHookModules = new Map<string, Set<string>>();
1756
+ const extensionGraphCacheBustResolvedImportModules = new Map<string, Set<string>>();
1757
+ const commonJsModuleSources = new Map<string, string>();
1758
+ const commonJsFallbackModulePaths = new Map<string, string>();
1759
+ const extensionSynchronousSpecifierTargets = new Map<string, Map<string, string>>();
1760
+ const commonJsGraphModulePaths = new Set<string>();
1761
+ const COMMONJS_REQUIRE_GLOBAL = "__ompLegacyPiRequireGraphModule";
1762
+ const commonJsModuleDefinitions = new Map<string, { source: string; filename: string; dirname: string }>();
1763
+ const commonJsModuleCache = new Map<
1764
+ string,
1765
+ {
1766
+ exports: unknown;
1767
+ filename: string;
1768
+ id: string;
1769
+ path: string;
1770
+ require: NodeJS.Require;
1771
+ loaded: boolean;
1772
+ }
1773
+ >();
1774
+ const commonJsTypeScriptTranspiler = new Bun.Transpiler({ loader: "ts" });
1775
+
1776
+ function evaluateGraphCommonJs(modulePath: string): unknown {
1777
+ const cached = commonJsModuleCache.get(modulePath);
1778
+ if (cached) {
1779
+ return cached.exports;
1780
+ }
1781
+ let definition = commonJsModuleDefinitions.get(modulePath);
1782
+ if (!definition && commonJsGraphModulePaths.has(modulePath)) {
1783
+ const targetPath = commonJsFallbackModulePaths.get(modulePath) ?? modulePath;
1784
+ const source = rewriteExtensionSpecifiersFromCache(fs.readFileSync(targetPath, "utf8"), modulePath);
1785
+ synthesizeCommonJsDefaultModule(modulePath, source, targetPath);
1786
+ definition = commonJsModuleDefinitions.get(modulePath);
1787
+ }
1788
+ if (!definition) {
1789
+ throw new Error(`Missing graph-owned CommonJS definition: ${modulePath}`);
1790
+ }
1791
+
1792
+ const nativeRequire = createRequire(definition.filename);
1793
+ const module = {
1794
+ exports: {},
1795
+ filename: definition.filename,
1796
+ id: definition.filename,
1797
+ path: definition.dirname,
1798
+ require: nativeRequire,
1799
+ loaded: false,
1800
+ };
1801
+ commonJsModuleCache.set(modulePath, module);
1802
+ const graphRequire: NodeJS.Require = Object.assign(
1803
+ (specifier: string) => {
1804
+ if (isBundledVirtualSpecifier(specifier)) {
1805
+ const moduleKey = specifier.slice(BUNDLED_VIRTUAL_SCHEME.length);
1806
+ const bundledModule = loadedBundledModules[moduleKey];
1807
+ if (!bundledModule) {
1808
+ throw new Error(`Missing bundled CommonJS host module: ${moduleKey}`);
1809
+ }
1810
+ return bundledModule;
1811
+ }
1812
+ const resolved = nativeRequire.resolve(specifier);
1813
+ let graphPath = resolved;
1814
+ try {
1815
+ graphPath = fs.realpathSync(resolved);
1816
+ } catch {
1817
+ // Builtins and virtual modules have no filesystem realpath.
1818
+ }
1819
+ return commonJsGraphModulePaths.has(graphPath) ? evaluateGraphCommonJs(graphPath) : nativeRequire(specifier);
1820
+ },
1821
+ {
1822
+ resolve: nativeRequire.resolve,
1823
+ cache: nativeRequire.cache,
1824
+ extensions: nativeRequire.extensions,
1825
+ main: nativeRequire.main,
1826
+ },
1827
+ );
1828
+ module.require = graphRequire;
1829
+ const execute = new Function("exports", "require", "module", "__filename", "__dirname", definition.source);
1830
+ try {
1831
+ execute.call(module.exports, module.exports, graphRequire, module, definition.filename, definition.dirname);
1832
+ module.loaded = true;
1833
+ return module.exports;
1834
+ } catch (error) {
1835
+ commonJsModuleCache.delete(modulePath);
1836
+ throw error;
1837
+ }
1838
+ }
1839
+
1840
+ /**
1841
+ * Register {@link evaluateGraphCommonJs} as the graph-owned CommonJS require
1842
+ * bridge on `globalThis`, first-wins.
1843
+ *
1844
+ * On source-link installs the `@(scope)/pi-coding-agent` root shim is served
1845
+ * from `src/`, so an extension import can evaluate a second instance of this
1846
+ * module with empty graph state. An unconditional set would let that empty
1847
+ * instance clobber the host bundle's populated bridge and break transitive
1848
+ * CommonJS resolution (#6449); guarding preserves the first (host-owned)
1849
+ * registration. Idempotent: a subsequent call with a value already present is a
1850
+ * no-op.
1851
+ */
1852
+ export function ensureGraphCommonJsRequireRegistered(): void {
1853
+ if (!Reflect.get(globalThis, COMMONJS_REQUIRE_GLOBAL)) {
1854
+ Reflect.set(globalThis, COMMONJS_REQUIRE_GLOBAL, evaluateGraphCommonJs);
1855
+ }
1856
+ }
1857
+
1858
+ ensureGraphCommonJsRequireRegistered();
1859
+
1860
+ let legacyPiLoadTag = 0;
1861
+
1862
+ function nextLegacyPiLoadTag(): string {
1863
+ legacyPiLoadTag = Math.max(legacyPiLoadTag + 1, Date.now());
1864
+ return String(legacyPiLoadTag);
1865
+ }
1866
+
1867
+ /** Resolve symlinks in a path, falling back to the input if realpath fails. */
1868
+ async function realpathOrSelf(p: string): Promise<string> {
1869
+ const cached = realpathCache.get(p);
1870
+ if (cached) return cached;
1871
+
1872
+ const promise = realpathOrSelfUncached(p);
1873
+ realpathCache.set(p, promise);
1874
+ return promise;
1875
+ }
1876
+
1877
+ async function realpathOrSelfUncached(p: string): Promise<string> {
1878
+ try {
1879
+ return await fs.promises.realpath(p);
1880
+ } catch {
1881
+ return p;
1882
+ }
1883
+ }
1884
+
1885
+ interface ExtensionModuleGraph {
1886
+ readonly modules: Map<string, string>;
1887
+ readonly cacheBustResolvedImportModules: Set<string>;
1888
+ readonly commonJsPaths: Set<string>;
1889
+ }
1890
+
1891
+ /**
1892
+ * Walk the extension's import graph starting at `entryRealPath`, returning the
1893
+ * realpath of every reachable source module OMP must rewrite at load time.
1894
+ * Relative imports, package `imports` aliases, and ESM bare dependencies are
1895
+ * graph-owned recursively because compiled Bun cannot resolve runtime
1896
+ * `node_modules` from those modules. Graph-owned CommonJS modules also own
1897
+ * their relative and bare CommonJS descendants, which are evaluated by the
1898
+ * synchronous bridge. Resolved ESM imports inside third-party dependencies
1899
+ * omit the reload tag so their importer paths stay query-free.
1900
+ */
1901
+ async function collectExtensionModules(entryRealPath: string): Promise<ExtensionModuleGraph> {
1902
+ const modules = new Map<string, string>();
1903
+ const commonJsPaths = new Set<string>();
1904
+ const queuedCacheBustResolvedImports = new Map<string, boolean>([[entryRealPath, true]]);
1905
+ const queuedModuleKinds = new Map<string, ExtensionModuleKind>([[entryRealPath, "esm"]]);
1906
+ const queuedEsmBranchPaths = new Set<string>();
1907
+ const queue: Array<{
1908
+ file: string;
1909
+ cacheBustResolvedImports: boolean;
1910
+ moduleKind?: ExtensionModuleKind;
1911
+ esmBranch?: boolean;
1912
+ }> = [{ file: entryRealPath, cacheBustResolvedImports: true, moduleKind: "esm" }];
1913
+ while (queue.length > 0) {
1914
+ const item = queue.pop();
1915
+ if (!item) {
1916
+ continue;
1917
+ }
1918
+ const file = item.file;
1919
+ const cacheBustResolvedImports = queuedCacheBustResolvedImports.get(file) ?? item.cacheBustResolvedImports;
1920
+ const inheritedModuleKind = queuedModuleKinds.get(file) ?? item.moduleKind;
1921
+ const esmBranch = queuedEsmBranchPaths.has(file) || item.esmBranch === true;
1922
+ if (modules.has(file)) {
1923
+ continue;
1924
+ }
1925
+ let source: string;
1926
+ try {
1927
+ source = await Bun.file(file).text();
1928
+ } catch {
1929
+ continue;
1930
+ }
1931
+ modules.set(file, source);
1932
+ const ast = parseExtensionSource(source, file);
1933
+ const sourceIsCommonJs = await isGraphOwnedCommonJsModule(
1934
+ file,
1935
+ entryRealPath,
1936
+ ast.program.sourceType,
1937
+ inheritedModuleKind,
1938
+ );
1939
+ if (sourceIsCommonJs) {
1940
+ commonJsPaths.add(file);
1941
+ }
1942
+ const dir = path.dirname(file);
1943
+ const references = collectExtensionSpecifierReferences(source, file, ast);
1944
+ for (const reference of references) {
1945
+ const specifier = reference.specifier;
1946
+ try {
1947
+ let resolved: string | null = null;
1948
+ let nextCacheBustResolvedImports = cacheBustResolvedImports;
1949
+ let resolvedModuleKind: ExtensionModuleKind | undefined;
1950
+ let resolvedEsmBranch = false;
1951
+ let requiresNativeAddonRewrite = false;
1952
+ const isRequired = reference.kind === "require";
1953
+ if (specifier.startsWith(".")) {
1954
+ const candidate = Bun.resolveSync(specifier, dir);
1955
+ if (hasSourceModuleExtension(candidate)) {
1956
+ const inheritedTargetKind = isRequired
1957
+ ? sourceIsCommonJs
1958
+ ? "commonjs"
1959
+ : undefined
1960
+ : sourceIsCommonJs
1961
+ ? "commonjs"
1962
+ : esmBranch
1963
+ ? "esm"
1964
+ : undefined;
1965
+ const targetIsCommonJs = await isCommonJsModulePath(candidate, undefined, inheritedTargetKind);
1966
+ const isCommonJsDescendant = isRequired && sourceIsCommonJs && targetIsCommonJs;
1967
+ requiresNativeAddonRewrite =
1968
+ isRequired && !isCommonJsDescendant && (await moduleRequiresNativeAddon(candidate));
1969
+ if (!isRequired || isCommonJsDescendant || requiresNativeAddonRewrite) {
1970
+ resolved = await realpathOrSelf(candidate);
1971
+ resolvedModuleKind = targetIsCommonJs ? "commonjs" : "esm";
1972
+ resolvedEsmBranch = !targetIsCommonJs && esmBranch;
1973
+ }
1974
+ }
1975
+ } else if (specifier.startsWith("#")) {
1976
+ const candidate = await resolvePackageImportSpecifier(specifier, file);
1977
+ if (candidate) {
1978
+ const inheritedTargetKind = isRequired
1979
+ ? sourceIsCommonJs
1980
+ ? "commonjs"
1981
+ : undefined
1982
+ : sourceIsCommonJs
1983
+ ? "commonjs"
1984
+ : esmBranch
1985
+ ? "esm"
1986
+ : undefined;
1987
+ const targetIsCommonJs = await isCommonJsModulePath(candidate, undefined, inheritedTargetKind);
1988
+ const isCommonJsDescendant = isRequired && sourceIsCommonJs && targetIsCommonJs;
1989
+ requiresNativeAddonRewrite =
1990
+ isRequired && !isCommonJsDescendant && (await moduleRequiresNativeAddon(candidate));
1991
+ if (!isRequired || isCommonJsDescendant || requiresNativeAddonRewrite) {
1992
+ resolved = candidate;
1993
+ resolvedModuleKind = targetIsCommonJs ? "commonjs" : "esm";
1994
+ resolvedEsmBranch = !targetIsCommonJs && esmBranch;
1995
+ }
1996
+ }
1997
+ } else if (
1998
+ isBareExtensionDependencySpecifier(specifier) &&
1999
+ !remapLegacyPiSpecifier(specifier) &&
2000
+ specifier !== "typebox" &&
2001
+ specifier !== "@sinclair/typebox"
2002
+ ) {
2003
+ const dependencyEntry = isRequired
2004
+ ? await resolveExtensionBareRequire(specifier, file)
2005
+ : await resolveExtensionBareDependency(specifier, file);
2006
+ const isHookableEntry = Boolean(dependencyEntry && hasSourceModuleExtension(dependencyEntry));
2007
+ const selectedEsmBranch =
2008
+ !isRequired &&
2009
+ isHookableEntry &&
2010
+ dependencyEntry !== null &&
2011
+ (await isSelectedNoTypeEsmPackageBranch(specifier, file, dependencyEntry));
2012
+ const inheritedTargetKind = isRequired
2013
+ ? sourceIsCommonJs
2014
+ ? "commonjs"
2015
+ : undefined
2016
+ : selectedEsmBranch
2017
+ ? "esm"
2018
+ : undefined;
2019
+ const isCommonJsEntry =
2020
+ isHookableEntry && dependencyEntry
2021
+ ? await isCommonJsModulePath(dependencyEntry, undefined, inheritedTargetKind)
2022
+ : false;
2023
+ if (isHookableEntry && dependencyEntry && (!isRequired || (sourceIsCommonJs && isCommonJsEntry))) {
2024
+ resolved = await realpathOrSelf(dependencyEntry);
2025
+ } else if (isHookableEntry && dependencyEntry && isRequired) {
2026
+ requiresNativeAddonRewrite = await moduleRequiresNativeAddon(dependencyEntry);
2027
+ if (requiresNativeAddonRewrite) {
2028
+ resolved = await realpathOrSelf(dependencyEntry);
2029
+ }
2030
+ }
2031
+ if (resolved) {
2032
+ resolvedModuleKind = isCommonJsEntry ? "commonjs" : "esm";
2033
+ resolvedEsmBranch = selectedEsmBranch && !isCommonJsEntry;
2034
+ }
2035
+ nextCacheBustResolvedImports = false;
2036
+ }
2037
+ if (resolved && requiresNativeAddonRewrite) {
2038
+ nativeAddonLoaderModulePaths.add(resolved);
2039
+ }
2040
+ if (resolved) {
2041
+ const queuedCacheBust = queuedCacheBustResolvedImports.get(resolved) ?? false;
2042
+ const mergedCacheBust = queuedCacheBust || nextCacheBustResolvedImports;
2043
+ queuedCacheBustResolvedImports.set(resolved, mergedCacheBust);
2044
+ const queuedModuleKind = queuedModuleKinds.get(resolved);
2045
+ if (queuedModuleKind && resolvedModuleKind && queuedModuleKind !== resolvedModuleKind) {
2046
+ throw new ExtensionModuleKindConflictError(
2047
+ `Conflicting extension module kinds for ${resolved}: ${queuedModuleKind} and ${resolvedModuleKind}`,
2048
+ );
2049
+ }
2050
+ const mergedModuleKind = queuedModuleKind ?? resolvedModuleKind;
2051
+ if (mergedModuleKind) {
2052
+ queuedModuleKinds.set(resolved, mergedModuleKind);
2053
+ }
2054
+ if (resolvedEsmBranch) {
2055
+ queuedEsmBranchPaths.add(resolved);
2056
+ }
2057
+ if (!modules.has(resolved)) {
2058
+ queue.push({
2059
+ file: resolved,
2060
+ cacheBustResolvedImports: mergedCacheBust,
2061
+ moduleKind: mergedModuleKind,
2062
+ esmBranch: resolvedEsmBranch,
2063
+ });
2064
+ }
2065
+ }
2066
+ } catch (error) {
2067
+ if (error instanceof ExtensionModuleKindConflictError) {
2068
+ throw error;
2069
+ }
2070
+ // Unresolvable import (e.g. a type-only path); skip it.
2071
+ }
2072
+ }
2073
+ }
2074
+ for (const [modulePath, source] of modules) {
2075
+ if (commonJsPaths.has(modulePath) || nativeAddonLoaderModulePaths.has(modulePath)) {
2076
+ modules.set(modulePath, await rewriteExtensionSpecifiers(source, modulePath, commonJsPaths.has(modulePath)));
2077
+ }
2078
+ }
2079
+ return {
2080
+ modules,
2081
+ commonJsPaths,
2082
+ cacheBustResolvedImportModules: new Set(
2083
+ [...queuedCacheBustResolvedImports]
2084
+ .filter(([modulePath, enabled]) => enabled && modules.has(modulePath))
2085
+ .map(([modulePath]) => modulePath),
2086
+ ),
2087
+ };
2088
+ }
2089
+
2090
+ /**
2091
+ * Discovers CommonJS export names Bun normally exposes to ESM importers. The
2092
+ * bridge must declare them statically because its default export is synthetic.
2093
+ */
2094
+ const COMMONJS_NAMED_EXPORT_IDENTIFIER = /^[A-Za-z_$][\w$]*$/;
2095
+
2096
+ function collectCommonJsNamedExports(source: string, modulePath: string, visited = new Set<string>()): string[] {
2097
+ let realModulePath = modulePath;
2098
+ try {
2099
+ realModulePath = fs.realpathSync(modulePath);
2100
+ } catch {
2101
+ // The caller's path remains the stable cycle key when realpath fails.
2102
+ }
2103
+ if (visited.has(realModulePath)) {
2104
+ return [];
2105
+ }
2106
+ visited.add(realModulePath);
2107
+
2108
+ const names = new Set<string>();
2109
+
2110
+ const reexportSpecifiers = new Set<string>();
2111
+ const ast = parseExtensionSource(source, modulePath);
2112
+ for (const { node, scope } of collectScopedAstNodes(
2113
+ ast,
2114
+ candidate => candidate.type === "CallExpression" || candidate.type === "AssignmentExpression",
2115
+ )) {
2116
+ if (node.type === "CallExpression") {
2117
+ const callee = asAstNode(node.callee);
2118
+ if (isUncomputedMember(callee, "Object", "defineProperty") && !scopeHasBinding(scope, OBJECT_BINDING)) {
2119
+ const target = nodeArgument(node, 0);
2120
+ const property = nodeArgument(node, 1);
2121
+ if (
2122
+ isUnshadowedExportsTarget(target, scope) &&
2123
+ property?.type === "StringLiteral" &&
2124
+ typeof property.value === "string" &&
2125
+ property.value !== "default" &&
2126
+ COMMONJS_NAMED_EXPORT_IDENTIFIER.test(property.value)
2127
+ ) {
2128
+ names.add(property.value);
2129
+ }
2130
+ continue;
2131
+ }
2132
+ if (isIdentifier(callee, "__exportStar")) {
2133
+ const sourceCall = nodeArgument(node, 0);
2134
+ const target = nodeArgument(node, 1);
2135
+ if (isUnshadowedExportsTarget(target, scope) && isGlobalRequireCall(sourceCall, scope)) {
2136
+ const argument = nodeArgument(sourceCall, 0);
2137
+ if (argument?.type === "StringLiteral" && typeof argument.value === "string") {
2138
+ reexportSpecifiers.add(argument.value);
2139
+ }
2140
+ }
2141
+ continue;
2142
+ }
2143
+ }
2144
+ if (node.type !== "AssignmentExpression" || node.operator !== "=") continue;
2145
+ const left = asAstNode(node.left);
2146
+ if (left?.type !== "MemberExpression") continue;
2147
+
2148
+ const propertyName = staticMemberPropertyName(left);
2149
+ const object = asAstNode(left.object);
2150
+ if (propertyName !== null && isUnshadowedExportsTarget(object, scope)) {
2151
+ if (propertyName !== "default" && COMMONJS_NAMED_EXPORT_IDENTIFIER.test(propertyName)) {
2152
+ names.add(propertyName);
2153
+ }
2154
+ continue;
2155
+ }
2156
+ if (!isUncomputedMember(left, "module", "exports") || scopeHasBinding(scope, MODULE_BINDING)) continue;
2157
+
2158
+ const right = asAstNode(node.right);
2159
+ if (right?.type === "ObjectExpression") {
2160
+ const properties = nodeArray(right, "properties");
2161
+ if (properties) {
2162
+ for (const value of properties) {
2163
+ const property = asAstNode(value);
2164
+ if (!property || (property.type !== "ObjectProperty" && property.type !== "ObjectMethod")) continue;
2165
+ const name = staticObjectPropertyName(property);
2166
+ if (name && name !== "default" && COMMONJS_NAMED_EXPORT_IDENTIFIER.test(name)) {
2167
+ names.add(name);
2168
+ }
2169
+ }
2170
+ }
2171
+ continue;
2172
+ }
2173
+ if (isGlobalRequireCall(right, scope)) {
2174
+ const argument = nodeArgument(right, 0);
2175
+ if (argument?.type === "StringLiteral" && typeof argument.value === "string") {
2176
+ reexportSpecifiers.add(argument.value);
2177
+ }
2178
+ }
2179
+ }
2180
+ const nativeRequire = createRequire(modulePath);
2181
+ for (const specifier of reexportSpecifiers) {
2182
+ try {
2183
+ const resolved = fs.realpathSync(nativeRequire.resolve(specifier));
2184
+ const reexportedSource = rewriteExtensionSpecifiersFromCache(fs.readFileSync(resolved, "utf8"), resolved);
2185
+ for (const name of collectCommonJsNamedExports(reexportedSource, resolved, visited)) {
2186
+ names.add(name);
2187
+ }
2188
+ } catch {
2189
+ // Native modules and non-source re-exports do not expose analyzable names.
2190
+ }
2191
+ }
2192
+ return [...names];
2193
+ }
2194
+
2195
+ /**
2196
+ * The shared evaluator gives ESM imports and sibling `require()` calls the
2197
+ * same `module.exports` value and cycle-aware cache.
2198
+ */
2199
+ function synthesizeCommonJsDefaultModule(modulePath: string, source: string, targetPath = modulePath): string {
2200
+ let commonJsSource = source;
2201
+ if (commonJsSource.startsWith("#!")) {
2202
+ const firstLineEnd = commonJsSource.indexOf("\n");
2203
+ commonJsSource = firstLineEnd === -1 ? "" : commonJsSource.slice(firstLineEnd + 1);
2204
+ }
2205
+
2206
+ const executableSource = targetPath.endsWith(".cts")
2207
+ ? commonJsTypeScriptTranspiler.transformSync(commonJsSource)
2208
+ : commonJsSource;
2209
+ commonJsModuleDefinitions.set(modulePath, {
2210
+ source: executableSource,
2211
+ filename: targetPath,
2212
+ dirname: path.dirname(targetPath),
2213
+ });
2214
+ commonJsModuleCache.delete(modulePath);
2215
+ const exportsBinding = "__ompLegacyPiCommonJsExports";
2216
+ const namedExports = collectCommonJsNamedExports(executableSource, targetPath)
2217
+ .map(
2218
+ (name, index) =>
2219
+ `const __ompLegacyPiCommonJsExport${index} = ${exportsBinding}[${JSON.stringify(name)}]; export { __ompLegacyPiCommonJsExport${index} as ${name} };`,
2220
+ )
2221
+ .join("\n");
2222
+ return `const ${exportsBinding} = globalThis[${JSON.stringify(COMMONJS_REQUIRE_GLOBAL)}](${JSON.stringify(modulePath)});\nexport default ${exportsBinding};\n${namedExports}\n`;
2223
+ }
2224
+
2225
+ /**
2226
+ * Linkedom's canvas bridge uses its bundled fallback because OMP does not ship
2227
+ * native canvas.
2228
+ */
2229
+ async function prepareCommonJsDefaultModule(modulePath: string, source: string): Promise<string> {
2230
+ const packageRoot = await findPackageRoot(modulePath);
2231
+ if (!packageRoot) {
2232
+ return synthesizeCommonJsDefaultModule(modulePath, source);
2233
+ }
2234
+ const manifest = await readPackageManifest(packageRoot);
2235
+ const packageRelativePath = path.relative(packageRoot, modulePath).split(path.sep).join("/");
2236
+ if (manifest?.name !== "linkedom" || packageRelativePath !== "commonjs/canvas.cjs") {
2237
+ return synthesizeCommonJsDefaultModule(modulePath, source);
2238
+ }
2239
+
2240
+ const targetPath = path.join(packageRoot, "commonjs", "canvas-shim.cjs");
2241
+ commonJsFallbackModulePaths.set(modulePath, targetPath);
2242
+ return synthesizeCommonJsDefaultModule(modulePath, await Bun.file(targetPath).text(), targetPath);
2243
+ }
2244
+
2245
+ /**
2246
+ * Install exact-path load hooks for the current extension graph. ESM/TS source
2247
+ * retains the async rewrite path. Graph-owned CommonJS modules and native-addon
2248
+ * loaders stay synchronous because Bun rejects `require()` targets backed by
2249
+ * async `onLoad` callbacks.
2250
+ */
2251
+ async function installExtensionGraphHook(
2252
+ entryRealPath: string,
2253
+ modules: Map<string, string>,
2254
+ commonJsPaths: Set<string>,
2255
+ cacheBustResolvedImportModules: ReadonlySet<string>,
2256
+ ): Promise<{ asyncModules: Map<string, string>; syncSourceModules: Map<string, string> }> {
2257
+ const asyncModules = new Map<string, string>();
2258
+ const syncSourceModules = new Map<string, string>();
2259
+ for (const [modulePath, source] of modules) {
2260
+ if (commonJsPaths.has(modulePath)) {
2261
+ continue;
2262
+ }
2263
+ if (nativeAddonLoaderModulePaths.has(modulePath)) {
2264
+ syncSourceModules.set(modulePath, source);
2265
+ } else {
2266
+ asyncModules.set(modulePath, source);
2267
+ }
2268
+ }
2269
+
2270
+ if (asyncModules.size > 0) {
2271
+ const alternation = [...asyncModules.keys()].map(escapeRegExp).join("|");
2272
+ const filter = new RegExp(`^(?:${alternation})(?:\\?mtime=\\d+)?$`);
2273
+ const hookId = Bun.hash(`${entryRealPath}\0async\0${[...asyncModules.keys()].join("\0")}`).toString(36);
2274
+ Bun.plugin({
2275
+ name: `omp:legacy-pi-ext:${hookId}`,
2276
+ setup(build) {
2277
+ build.onLoad({ filter, namespace: "file" }, async args => {
2278
+ const queryIndex = args.path.indexOf("?mtime=");
2279
+ const sourcePath = queryIndex >= 0 ? args.path.slice(0, queryIndex) : args.path;
2280
+ const mtimeTag = queryIndex >= 0 ? args.path.slice(queryIndex + "?mtime=".length) : null;
2281
+ const cached = asyncModules.get(sourcePath);
2282
+ let raw: string;
2283
+ if (cached !== undefined) {
2284
+ // consume-once: preserves ?mtime edit-pickup for re-imports
2285
+ asyncModules.delete(sourcePath);
2286
+ raw = cached;
2287
+ } else {
2288
+ raw = await Bun.file(sourcePath).text();
2289
+ }
2290
+ const resolvedImportMtimeTag = cacheBustResolvedImportModules.has(sourcePath) ? mtimeTag : null;
2291
+ return {
2292
+ contents: await rewriteLegacyExtensionSource(raw, sourcePath, mtimeTag, resolvedImportMtimeTag),
2293
+ loader: getLoader(sourcePath),
2294
+ };
2295
+ });
2296
+ },
2297
+ });
2298
+ }
2299
+
2300
+ if (commonJsPaths.size > 0) {
2301
+ const alternation = [...commonJsPaths].map(escapeRegExp).join("|");
2302
+ const filter = new RegExp(`^(?:${alternation})(?:\\?mtime=\\d+)?$`);
2303
+ const hookId = Bun.hash(`${entryRealPath}\0commonjs\0${[...commonJsPaths].join("\0")}`).toString(36);
2304
+ Bun.plugin({
2305
+ name: `omp:legacy-pi-ext:${hookId}`,
2306
+ setup(build) {
2307
+ build.onLoad({ filter, namespace: "file" }, args => {
2308
+ const queryIndex = args.path.indexOf("?mtime=");
2309
+ const sourcePath = queryIndex >= 0 ? args.path.slice(0, queryIndex) : args.path;
2310
+ let source = commonJsModuleSources.get(sourcePath);
2311
+ if (source === undefined) {
2312
+ const targetPath = commonJsFallbackModulePaths.get(sourcePath) ?? sourcePath;
2313
+ const raw = rewriteExtensionSpecifiersFromCache(fs.readFileSync(targetPath, "utf8"), sourcePath);
2314
+ source = synthesizeCommonJsDefaultModule(sourcePath, raw, targetPath);
2315
+ }
2316
+ return { contents: source, loader: getLoader(sourcePath) };
2317
+ });
2318
+ },
2319
+ });
2320
+ }
2321
+
2322
+ if (syncSourceModules.size > 0) {
2323
+ const alternation = [...syncSourceModules.keys()].map(escapeRegExp).join("|");
2324
+ const filter = new RegExp(`^(?:${alternation})(?:\\?mtime=\\d+)?$`);
2325
+ const hookId = Bun.hash(`${entryRealPath}\0sync-source\0${[...syncSourceModules.keys()].join("\0")}`).toString(
2326
+ 36,
2327
+ );
2328
+ Bun.plugin({
2329
+ name: `omp:legacy-pi-ext:${hookId}`,
2330
+ setup(build) {
2331
+ build.onLoad({ filter, namespace: "file" }, args => {
2332
+ const queryIndex = args.path.indexOf("?mtime=");
2333
+ const sourcePath = queryIndex >= 0 ? args.path.slice(0, queryIndex) : args.path;
2334
+ const source = syncSourceModules.get(sourcePath);
2335
+ if (source === undefined) {
2336
+ throw new Error(`Missing pre-rewritten CommonJS extension source: ${sourcePath}`);
2337
+ }
2338
+ return { contents: source, loader: getLoader(sourcePath) };
2339
+ });
2340
+ },
2341
+ });
2342
+ }
2343
+ return { asyncModules, syncSourceModules };
2344
+ }
2345
+
2346
+ /**
2347
+ * Ensure every currently reachable extension source module has a load-time
2348
+ * rewrite hook. The entry graph can grow across reloads, so each call collects
2349
+ * the current graph and registers hooks for paths not covered by earlier loads.
2350
+ *
2351
+ * Returns a clearable handle to drop cached sources that weren't consumed
2352
+ * during the initial load; `undefined` when no new modules were discovered.
2353
+ */
2354
+ async function ensureExtensionGraphHook(entryRealPath: string): Promise<{ clear(): void } | undefined> {
2355
+ const {
2356
+ modules: currentModules,
2357
+ commonJsPaths,
2358
+ cacheBustResolvedImportModules: discoveredCacheBustModules,
2359
+ } = await collectExtensionModules(entryRealPath);
2360
+ let cacheBustResolvedImportModules = extensionGraphCacheBustResolvedImportModules.get(entryRealPath);
2361
+ if (!cacheBustResolvedImportModules) {
2362
+ cacheBustResolvedImportModules = new Set<string>();
2363
+ extensionGraphCacheBustResolvedImportModules.set(entryRealPath, cacheBustResolvedImportModules);
2364
+ }
2365
+ for (const modulePath of discoveredCacheBustModules) {
2366
+ cacheBustResolvedImportModules.add(modulePath);
2367
+ }
2368
+ for (const [modulePath, source] of currentModules) {
2369
+ if (commonJsPaths.has(modulePath)) {
2370
+ commonJsModuleSources.set(modulePath, await prepareCommonJsDefaultModule(modulePath, source));
2371
+ commonJsGraphModulePaths.add(modulePath);
2372
+ }
2373
+ }
2374
+ let hookedModules = extensionGraphHookModules.get(entryRealPath);
2375
+ if (!hookedModules) {
2376
+ hookedModules = new Set<string>();
2377
+ extensionGraphHookModules.set(entryRealPath, hookedModules);
2378
+ }
2379
+
2380
+ const pendingModules = new Map<string, string>();
2381
+ const pendingCommonJsPaths = new Set<string>();
2382
+ for (const [modulePath, source] of currentModules) {
2383
+ if (!hookedModules.has(modulePath)) {
2384
+ pendingModules.set(modulePath, source);
2385
+ if (commonJsPaths.has(modulePath)) {
2386
+ pendingCommonJsPaths.add(modulePath);
2387
+ }
2388
+ }
2389
+ }
2390
+ if (pendingModules.size === 0 && commonJsPaths.size === 0) {
2391
+ return undefined;
2392
+ }
2393
+
2394
+ let asyncModules = new Map<string, string>();
2395
+ let syncSourceModules = new Map<string, string>();
2396
+ if (pendingModules.size > 0) {
2397
+ ({ asyncModules, syncSourceModules } = await installExtensionGraphHook(
2398
+ entryRealPath,
2399
+ pendingModules,
2400
+ pendingCommonJsPaths,
2401
+ cacheBustResolvedImportModules,
2402
+ ));
2403
+ for (const modulePath of pendingModules.keys()) {
2404
+ hookedModules.add(modulePath);
2405
+ }
2406
+ }
2407
+ return {
2408
+ clear() {
2409
+ asyncModules.clear();
2410
+ syncSourceModules.clear();
2411
+ for (const modulePath of commonJsPaths) {
2412
+ commonJsModuleSources.delete(modulePath);
2413
+ commonJsModuleDefinitions.delete(modulePath);
2414
+ commonJsModuleCache.delete(modulePath);
2415
+ }
2416
+ },
2417
+ };
2418
+ }
2419
+
2420
+ /**
2421
+ * Load a legacy Pi extension module from its real on-disk location.
2422
+ *
2423
+ * The extension runs in place, so its `import.meta.url` is the real source file
2424
+ * and `__dirname`-relative `readFileSync` asset loads (HTML/CSS bundled next to
2425
+ * the entry) resolve exactly as they do under the original Pi runtime — no
2426
+ * temp-directory mirroring and no asset copying. An `onLoad` hook scoped to the
2427
+ * entry's source graph rewrites only host-resolved compatibility imports in the
2428
+ * extension's own source; everything else resolves natively.
2429
+ */
2430
+ export async function loadLegacyPiModule(resolvedPath: string): Promise<unknown> {
2431
+ // Bun reports the realpath of a loaded module to `onLoad` and exposes it as
2432
+ // `import.meta.url`. Resolve symlinks here too (macOS `/var`→`/private/var`,
2433
+ // `bun link`/pnpm installs) so the rewrite filter matches the path Bun
2434
+ // actually hands the hook.
2435
+ const entryRealPath = await realpathOrSelf(path.resolve(resolvedPath));
2436
+ await ensureLegacyPiOverridesReady();
2437
+ const pendingSources = await ensureExtensionGraphHook(entryRealPath);
2438
+ try {
2439
+ // Dynamic import is required: legacy extension entry paths are user/plugin supplied at runtime.
2440
+ // On POSIX, use the raw filesystem path so Bun keys the `?mtime`
2441
+ // suffix as part of the module identity; Bun ignores query strings on
2442
+ // `file://` specifiers, which would serve stale edited source.
2443
+ const entrySpecifier =
2444
+ process.platform === "win32" || isBundledVirtualSpecifier(entryRealPath)
2445
+ ? toImportSpecifier(entryRealPath)
2446
+ : entryRealPath;
2447
+ return await import(`${entrySpecifier}?mtime=${nextLegacyPiLoadTag()}`);
2448
+ } finally {
2449
+ // Drop whatever the initial import didn't consume: graph modules only
2450
+ // reached by lazy dynamic imports must be read from disk at their actual
2451
+ // import time, not served from this load-time snapshot.
2452
+ pendingSources?.clear();
2453
+ }
2454
+ }
2455
+
2456
+ function getLoader(path: string): "js" | "jsx" | "ts" | "tsx" {
2457
+ if (path.endsWith(".tsx")) {
2458
+ return "tsx";
2459
+ }
2460
+ if (path.endsWith(".jsx")) {
2461
+ return "jsx";
2462
+ }
2463
+ if (path.endsWith(".ts") || path.endsWith(".mts") || path.endsWith(".cts")) {
2464
+ return "ts";
2465
+ }
2466
+ return "js";
2467
+ }
2468
+
2469
+ function resolveLegacyPiSpecifier(args: { path: string; importer: string }): LegacyPiResolveResult | undefined {
2470
+ const remappedSpecifier = remapLegacyPiSpecifier(args.path);
2471
+ if (!remappedSpecifier) {
2472
+ return undefined;
2473
+ }
2474
+
2475
+ // Primary: resolve the canonical @oh-my-pi/* specifier from the host binary
2476
+ // location. Works in dev mode and in source-link installs.
2477
+ try {
2478
+ return toLegacyPiResolveResult(resolveCanonicalPiSpecifier(remappedSpecifier));
2479
+ } catch {
2480
+ // Fallback for compiled binary mode: the bundled packages live inside
2481
+ // /$bunfs/root and aren't reachable by filesystem resolution. Prefer the
2482
+ // canonical specifier against the importing file's directory when the
2483
+ // plugin installed @oh-my-pi peer deps, then try the original legacy
2484
+ // specifier for plugins that still vendor only @mariozechner or
2485
+ // @earendil-works peer deps.
2486
+ const importerDir = path.dirname(args.importer);
2487
+ try {
2488
+ return toLegacyPiResolveResult(Bun.resolveSync(remappedSpecifier, importerDir));
2489
+ } catch {
2490
+ try {
2491
+ return toLegacyPiResolveResult(Bun.resolveSync(args.path, importerDir));
2492
+ } catch {
2493
+ return undefined;
2494
+ }
2495
+ }
2496
+ }
2497
+ }
2498
+
2499
+ function resolveTypeBoxSpecifier(): LegacyPiResolveResult | undefined {
2500
+ return TYPEBOX_SHIM_PATH ? toLegacyPiResolveResult(TYPEBOX_SHIM_PATH) : undefined;
2501
+ }
2502
+
2503
+ export function installLegacyPiSpecifierShim(): void {
2504
+ if (isLegacyPiSpecifierShimInstalled) {
2505
+ return;
2506
+ }
2507
+ isLegacyPiSpecifierShimInstalled = true;
2508
+
2509
+ Bun.plugin({
2510
+ name: "omp:legacy-pi-shim",
2511
+ setup(build) {
2512
+ build.onResolve({ filter: LEGACY_PI_SPECIFIER_FILTER, namespace: "file" }, resolveLegacyPiSpecifier);
2513
+ build.onResolve({ filter: TYPEBOX_SPECIFIER_FILTER, namespace: "file" }, resolveTypeBoxSpecifier);
2514
+ build.onResolve({ filter: /^omp-legacy-pi-bundled:.+$/, namespace: "file" }, args =>
2515
+ resolveBundledVirtualSpecifier(args.path),
2516
+ );
2517
+ build.onResolve({ filter: /.*/, namespace: BUNDLED_VIRTUAL_NAMESPACE }, args =>
2518
+ resolveBundledVirtualSpecifier(args.path),
2519
+ );
2520
+ // Compiled mode serves `omp-legacy-pi-bundled:<key>` imports from
2521
+ // live host module references. No bunfs path leaves this loader.
2522
+ build.onLoad({ filter: /.*/, namespace: BUNDLED_VIRTUAL_NAMESPACE }, async args => {
2523
+ return { contents: await synthesizeBundledModuleSource(args.path), loader: "js" };
2524
+ });
2525
+ },
2526
+ });
2527
+ }
2528
+
2529
+ /** Test seam: clears the memoized canonical specifier resolutions. */
2530
+ export function __resetLegacyPiResolutionCache(): void {
2531
+ clearLegacyPiResolutionCaches();
2532
+ }