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