oma-coding-agent 1.1.4
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 +12164 -0
- package/README.md +35 -0
- package/dist/cli.js +18266 -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 +79 -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 +172 -0
- package/package.json +573 -0
- package/scripts/bench-guard.ts +71 -0
- package/scripts/build-binary.ts +108 -0
- package/scripts/bundle-dist.ts +110 -0
- package/scripts/embed-mupdf-wasm.ts +67 -0
- package/scripts/format-prompts.ts +68 -0
- package/scripts/generate-docs-index.ts +56 -0
- package/scripts/generate-share-viewer.ts +34 -0
- package/scripts/measure-prompt-tokens.ts +63 -0
- package/scripts/omp +42 -0
- package/scripts/omp.ts +19 -0
- package/src/advisor/__tests__/advisor.test.ts +915 -0
- package/src/advisor/advise-tool.ts +165 -0
- package/src/advisor/index.ts +4 -0
- package/src/advisor/runtime.ts +270 -0
- package/src/advisor/transcript-recorder.ts +136 -0
- package/src/advisor/watchdog.ts +83 -0
- package/src/async/index.ts +1 -0
- package/src/async/job-manager.ts +674 -0
- package/src/auto-thinking/classifier.ts +190 -0
- package/src/autolearn/controller.ts +139 -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 +319 -0
- package/src/autoresearch/helpers.ts +218 -0
- package/src/autoresearch/index.ts +536 -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 +269 -0
- package/src/autoresearch/tools/log-experiment.ts +521 -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 +436 -0
- package/src/capability/instruction.ts +37 -0
- package/src/capability/mcp.ts +76 -0
- package/src/capability/prompt.ts +35 -0
- package/src/capability/rule-buckets.ts +66 -0
- package/src/capability/rule.ts +261 -0
- package/src/capability/settings.ts +34 -0
- package/src/capability/skill.ts +63 -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 +168 -0
- package/src/cli/agents-cli.ts +138 -0
- package/src/cli/args.ts +361 -0
- package/src/cli/auth-broker-cli.ts +893 -0
- package/src/cli/auth-gateway-cli.ts +608 -0
- package/src/cli/bench-cli.ts +552 -0
- package/src/cli/classify-install-target.ts +76 -0
- package/src/cli/claude-trace-cli.ts +795 -0
- package/src/cli/commands/init-xdg.ts +27 -0
- package/src/cli/completion-gen.ts +550 -0
- package/src/cli/config-cli.ts +418 -0
- package/src/cli/dry-balance-cli.ts +858 -0
- package/src/cli/extension-flags.ts +48 -0
- package/src/cli/file-processor.ts +133 -0
- package/src/cli/flag-tables.ts +280 -0
- package/src/cli/gallery-cli.ts +231 -0
- package/src/cli/gallery-fixtures/agentic.ts +407 -0
- package/src/cli/gallery-fixtures/codeintel.ts +187 -0
- package/src/cli/gallery-fixtures/edit.ts +194 -0
- package/src/cli/gallery-fixtures/fs.ts +220 -0
- package/src/cli/gallery-fixtures/index.ts +40 -0
- package/src/cli/gallery-fixtures/interaction.ts +49 -0
- package/src/cli/gallery-fixtures/memory.ts +81 -0
- package/src/cli/gallery-fixtures/misc.ts +250 -0
- package/src/cli/gallery-fixtures/search.ts +213 -0
- package/src/cli/gallery-fixtures/shell.ts +167 -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/grep-cli.ts +160 -0
- package/src/cli/grievances-cli.ts +256 -0
- package/src/cli/initial-message.ts +58 -0
- package/src/cli/models-cli.ts +427 -0
- package/src/cli/plugin-cli.ts +996 -0
- package/src/cli/profile-alias.ts +338 -0
- package/src/cli/profile-bootstrap.ts +243 -0
- package/src/cli/read-cli.ts +57 -0
- package/src/cli/session-picker.ts +80 -0
- package/src/cli/setup-cli.ts +332 -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/tiny-models-cli.ts +127 -0
- package/src/cli/ttsr-cli.ts +995 -0
- package/src/cli/update-cli.ts +671 -0
- package/src/cli/usage-cli.ts +774 -0
- package/src/cli/web-search-cli.ts +132 -0
- package/src/cli/worktree-cli.ts +291 -0
- package/src/cli-commands.ts +85 -0
- package/src/cli.ts +326 -0
- package/src/collab/crypto.ts +63 -0
- package/src/collab/guest.ts +450 -0
- package/src/collab/host.ts +577 -0
- package/src/collab/protocol.ts +274 -0
- package/src/collab/relay-client.ts +216 -0
- package/src/commands/acp.ts +24 -0
- package/src/commands/agents.ts +57 -0
- package/src/commands/auth-broker.ts +99 -0
- package/src/commands/auth-gateway.ts +69 -0
- package/src/commands/bench.ts +42 -0
- package/src/commands/commit.ts +46 -0
- package/src/commands/complete.ts +66 -0
- package/src/commands/completions.ts +60 -0
- package/src/commands/config.ts +51 -0
- package/src/commands/dry-balance.ts +43 -0
- package/src/commands/gallery.ts +52 -0
- package/src/commands/grep.ts +48 -0
- package/src/commands/grievances.ts +51 -0
- package/src/commands/install.ts +107 -0
- package/src/commands/join.ts +39 -0
- package/src/commands/launch.ts +182 -0
- package/src/commands/models.ts +61 -0
- package/src/commands/plugin.ts +78 -0
- package/src/commands/read.ts +38 -0
- package/src/commands/say.ts +102 -0
- package/src/commands/setup.ts +67 -0
- package/src/commands/shell.ts +29 -0
- package/src/commands/ssh.ts +60 -0
- package/src/commands/stats.ts +29 -0
- package/src/commands/tiny-models.ts +36 -0
- package/src/commands/token.ts +108 -0
- package/src/commands/ttsr.ts +125 -0
- package/src/commands/update.ts +21 -0
- package/src/commands/usage.ts +43 -0
- package/src/commands/web-search.ts +42 -0
- package/src/commands/worktree.ts +56 -0
- package/src/commit/agentic/agent.ts +318 -0
- package/src/commit/agentic/fallback.ts +96 -0
- package/src/commit/agentic/index.ts +355 -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 +149 -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 +81 -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 +89 -0
- package/src/commit/pipeline.ts +243 -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 +67 -0
- package/src/config/append-only-context-mode.ts +76 -0
- package/src/config/config-file.ts +315 -0
- package/src/config/file-lock.ts +164 -0
- package/src/config/keybindings.ts +634 -0
- package/src/config/mcp-schema.json +238 -0
- package/src/config/model-discovery.ts +589 -0
- package/src/config/model-registry.ts +2260 -0
- package/src/config/model-resolver.ts +1819 -0
- package/src/config/model-roles.ts +99 -0
- package/src/config/models-config-schema.ts +266 -0
- package/src/config/models-config.ts +131 -0
- package/src/config/prompt-templates.ts +185 -0
- package/src/config/resolve-config-value.ts +94 -0
- package/src/config/settings-schema.ts +4740 -0
- package/src/config/settings.ts +1243 -0
- package/src/config.ts +242 -0
- package/src/cursor.ts +340 -0
- package/src/dap/client.ts +760 -0
- package/src/dap/config.ts +189 -0
- package/src/dap/defaults.json +212 -0
- package/src/dap/index.ts +4 -0
- package/src/dap/session.ts +1441 -0
- package/src/dap/types.ts +610 -0
- package/src/debug/index.ts +559 -0
- package/src/debug/log-formatting.ts +58 -0
- package/src/debug/log-viewer.ts +908 -0
- package/src/debug/profiler.ts +162 -0
- package/src/debug/protocol-probe.ts +267 -0
- package/src/debug/raw-sse-buffer.ts +294 -0
- package/src/debug/raw-sse.ts +292 -0
- package/src/debug/remote-debugger.ts +151 -0
- package/src/debug/report-bundle.ts +375 -0
- package/src/debug/system-info.ts +111 -0
- package/src/debug/terminal-info.ts +124 -0
- package/src/discovery/agents-md.ts +67 -0
- package/src/discovery/agents.ts +230 -0
- package/src/discovery/at-imports.ts +273 -0
- package/src/discovery/builtin-defaults.ts +39 -0
- package/src/discovery/builtin-rules/index.ts +63 -0
- package/src/discovery/builtin-rules/low-end/no-hallucinated-apis.md +14 -0
- package/src/discovery/builtin-rules/low-end/no-hallucinated-paths.md +14 -0
- package/src/discovery/builtin-rules/low-end/no-premature-completion.md +14 -0
- package/src/discovery/builtin-rules/rs-box-leak.md +48 -0
- package/src/discovery/builtin-rules/rs-future-prelude.md +23 -0
- package/src/discovery/builtin-rules/rs-lazylock.md +51 -0
- package/src/discovery/builtin-rules/rs-match-ergonomics.md +67 -0
- package/src/discovery/builtin-rules/rs-parking-lot.md +44 -0
- package/src/discovery/builtin-rules/rs-result-type.md +19 -0
- package/src/discovery/builtin-rules/ts-bare-catch.md +38 -0
- package/src/discovery/builtin-rules/ts-import-type.md +42 -0
- package/src/discovery/builtin-rules/ts-no-any.md +65 -0
- package/src/discovery/builtin-rules/ts-no-deprecated-leftovers.md +44 -0
- package/src/discovery/builtin-rules/ts-no-dynamic-import.md +39 -0
- package/src/discovery/builtin-rules/ts-no-inline-cast-access.md +55 -0
- package/src/discovery/builtin-rules/ts-no-return-type.md +44 -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 +65 -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 +934 -0
- package/src/discovery/claude-plugins.ts +386 -0
- package/src/discovery/claude.ts +584 -0
- package/src/discovery/cline.ts +83 -0
- package/src/discovery/codex.ts +522 -0
- package/src/discovery/cursor.ts +220 -0
- package/src/discovery/gemini.ts +383 -0
- package/src/discovery/github.ts +337 -0
- package/src/discovery/helpers.ts +1092 -0
- package/src/discovery/index.ts +81 -0
- package/src/discovery/mcp-json.ts +172 -0
- package/src/discovery/omp-extension-roots.ts +190 -0
- package/src/discovery/omp-plugins.ts +383 -0
- package/src/discovery/opencode.ts +398 -0
- package/src/discovery/plugin-dir-roots.ts +28 -0
- package/src/discovery/ssh.ts +153 -0
- package/src/discovery/substitute-plugin-root.ts +29 -0
- package/src/discovery/vscode.ts +105 -0
- package/src/discovery/windsurf.ts +147 -0
- package/src/edit/apply-patch/index.ts +87 -0
- package/src/edit/apply-patch/parser.ts +174 -0
- package/src/edit/diff.ts +999 -0
- package/src/edit/file-snapshot-store.ts +143 -0
- package/src/edit/hashline/block-resolver.ts +33 -0
- package/src/edit/hashline/diff.ts +290 -0
- package/src/edit/hashline/execute.ts +237 -0
- package/src/edit/hashline/filesystem.ts +130 -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 +19 -0
- package/src/edit/index.ts +620 -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 +1888 -0
- package/src/edit/modes/replace.ts +1133 -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 +823 -0
- package/src/edit/streaming.ts +517 -0
- package/src/eval/__tests__/agent-bridge.test.ts +769 -0
- package/src/eval/__tests__/bridge-timeout.test.ts +64 -0
- package/src/eval/__tests__/budget-bridge.test.ts +69 -0
- package/src/eval/__tests__/completion-bridge.test.ts +412 -0
- package/src/eval/__tests__/helpers-local-roots.test.ts +58 -0
- package/src/eval/__tests__/idle-timeout.test.ts +80 -0
- package/src/eval/__tests__/js-context-manager.test.ts +291 -0
- package/src/eval/__tests__/kernel-spawn.test.ts +103 -0
- package/src/eval/__tests__/prelude-agent.test.ts +73 -0
- package/src/eval/agent-bridge.ts +319 -0
- package/src/eval/backend.ts +71 -0
- package/src/eval/bridge-timeout.ts +44 -0
- package/src/eval/budget-bridge.ts +48 -0
- package/src/eval/completion-bridge.ts +211 -0
- package/src/eval/concurrency-bridge.ts +34 -0
- package/src/eval/idle-timeout.ts +91 -0
- package/src/eval/index.ts +4 -0
- package/src/eval/js/context-manager.ts +621 -0
- package/src/eval/js/executor.ts +173 -0
- package/src/eval/js/index.ts +51 -0
- package/src/eval/js/shared/helpers.ts +283 -0
- package/src/eval/js/shared/indirect-eval.ts +30 -0
- package/src/eval/js/shared/local-module-loader.ts +342 -0
- package/src/eval/js/shared/prelude.ts +2 -0
- package/src/eval/js/shared/prelude.txt +307 -0
- package/src/eval/js/shared/rewrite-imports.ts +532 -0
- package/src/eval/js/shared/runtime.ts +580 -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 +151 -0
- package/src/eval/js/worker-entry.ts +37 -0
- package/src/eval/js/worker-protocol.ts +47 -0
- package/src/eval/py/__tests__/prelude.test.ts +19 -0
- package/src/eval/py/display.ts +71 -0
- package/src/eval/py/executor.ts +742 -0
- package/src/eval/py/index.ts +68 -0
- package/src/eval/py/kernel.ts +748 -0
- package/src/eval/py/prelude.py +683 -0
- package/src/eval/py/prelude.ts +3 -0
- package/src/eval/py/runner.py +1177 -0
- package/src/eval/py/runtime.ts +276 -0
- package/src/eval/py/spawn-options.ts +126 -0
- package/src/eval/py/tool-bridge.ts +182 -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 +434 -0
- package/src/exec/exec.ts +53 -0
- package/src/exec/non-interactive-env.ts +119 -0
- package/src/export/custom-share.ts +65 -0
- package/src/export/html/index.ts +266 -0
- package/src/export/html/share-loader.js +102 -0
- package/src/export/html/template.css +1337 -0
- package/src/export/html/template.html +49 -0
- package/src/export/html/template.js +1626 -0
- package/src/export/html/tool-views.generated.js +37 -0
- package/src/export/html/vendor/highlight.min.js +1213 -0
- package/src/export/html/vendor/marked.min.js +6 -0
- package/src/export/share.ts +268 -0
- package/src/export/ttsr.ts +583 -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 +268 -0
- package/src/extensibility/custom-tools/types.ts +277 -0
- package/src/extensibility/custom-tools/wrapper.ts +47 -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/loader.ts +587 -0
- package/src/extensibility/extensions/model-api.ts +41 -0
- package/src/extensibility/extensions/runner.ts +989 -0
- package/src/extensibility/extensions/types.ts +1394 -0
- package/src/extensibility/extensions/wrapper.ts +259 -0
- package/src/extensibility/hooks/index.ts +6 -0
- package/src/extensibility/hooks/loader.ts +262 -0
- package/src/extensibility/hooks/runner.ts +425 -0
- package/src/extensibility/hooks/tool-wrapper.ts +107 -0
- package/src/extensibility/hooks/types.ts +613 -0
- package/src/extensibility/legacy-pi-ai-shim.ts +61 -0
- package/src/extensibility/legacy-pi-coding-agent-shim.ts +128 -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 +192 -0
- package/src/extensibility/plugins/legacy-pi-compat.ts +712 -0
- package/src/extensibility/plugins/loader.ts +458 -0
- package/src/extensibility/plugins/manager.ts +1026 -0
- package/src/extensibility/plugins/marketplace/cache.ts +136 -0
- package/src/extensibility/plugins/marketplace/fetcher.ts +315 -0
- package/src/extensibility/plugins/marketplace/index.ts +6 -0
- package/src/extensibility/plugins/marketplace/manager.ts +770 -0
- package/src/extensibility/plugins/marketplace/registry.ts +196 -0
- package/src/extensibility/plugins/marketplace/source-resolver.ts +147 -0
- package/src/extensibility/plugins/marketplace/types.ts +191 -0
- package/src/extensibility/plugins/marketplace-auto-update.ts +49 -0
- package/src/extensibility/plugins/parser.ts +105 -0
- package/src/extensibility/plugins/runtime-config.ts +9 -0
- package/src/extensibility/plugins/types.ts +194 -0
- package/src/extensibility/shared-events.ts +367 -0
- package/src/extensibility/skills.ts +408 -0
- package/src/extensibility/slash-commands.ts +131 -0
- package/src/extensibility/tool-proxy.ts +28 -0
- package/src/extensibility/typebox.ts +945 -0
- package/src/extensibility/utils.ts +44 -0
- package/src/goals/guided-setup.ts +142 -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 +623 -0
- package/src/hindsight/config.ts +175 -0
- package/src/hindsight/content.ts +210 -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 +492 -0
- package/src/hindsight/transcript.ts +71 -0
- package/src/index.ts +66 -0
- package/src/internal-urls/agent-protocol.ts +146 -0
- package/src/internal-urls/artifact-protocol.ts +107 -0
- package/src/internal-urls/docs-index.generated.txt +2 -0
- package/src/internal-urls/docs-index.ts +102 -0
- package/src/internal-urls/history-protocol.ts +118 -0
- package/src/internal-urls/index.ts +25 -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 +309 -0
- package/src/internal-urls/mcp-protocol.ts +151 -0
- package/src/internal-urls/memory-protocol.ts +169 -0
- package/src/internal-urls/omp-protocol.ts +94 -0
- package/src/internal-urls/parse.ts +72 -0
- package/src/internal-urls/registry-helpers.ts +25 -0
- package/src/internal-urls/router.ts +105 -0
- package/src/internal-urls/rule-protocol.ts +45 -0
- package/src/internal-urls/skill-protocol.ts +96 -0
- package/src/internal-urls/types.ts +152 -0
- package/src/internal-urls/vault-protocol.ts +936 -0
- package/src/irc/bus.ts +311 -0
- package/src/lib/xai-http.ts +124 -0
- package/src/lsp/client.ts +1217 -0
- package/src/lsp/clients/biome-client.ts +264 -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 +502 -0
- package/src/lsp/defaults.json +499 -0
- package/src/lsp/diagnostics-ledger.ts +51 -0
- package/src/lsp/edits.ts +267 -0
- package/src/lsp/format-options.ts +119 -0
- package/src/lsp/index.ts +2480 -0
- package/src/lsp/lspmux.ts +233 -0
- package/src/lsp/render.ts +668 -0
- package/src/lsp/startup-events.ts +13 -0
- package/src/lsp/types.ts +444 -0
- package/src/lsp/utils.ts +718 -0
- package/src/main.ts +1421 -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/mammoth.d.ts +24 -0
- package/src/markit/converters/pdf/columns.ts +103 -0
- package/src/markit/converters/pdf/extract.ts +574 -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 +509 -0
- package/src/mcp/config-writer.ts +229 -0
- package/src/mcp/config.ts +365 -0
- package/src/mcp/index.ts +29 -0
- package/src/mcp/json-rpc.ts +122 -0
- package/src/mcp/loader.ts +124 -0
- package/src/mcp/manager.ts +1326 -0
- package/src/mcp/oauth-credentials.ts +104 -0
- package/src/mcp/oauth-discovery.ts +467 -0
- package/src/mcp/oauth-flow.ts +555 -0
- package/src/mcp/render.ts +155 -0
- package/src/mcp/smithery-auth.ts +104 -0
- package/src/mcp/smithery-connect.ts +145 -0
- package/src/mcp/smithery-registry.ts +477 -0
- package/src/mcp/startup-events.ts +21 -0
- package/src/mcp/timeout.ts +59 -0
- package/src/mcp/tool-bridge.ts +429 -0
- package/src/mcp/tool-cache.ts +117 -0
- package/src/mcp/transports/http.ts +519 -0
- package/src/mcp/transports/index.ts +6 -0
- package/src/mcp/transports/stdio.ts +606 -0
- package/src/mcp/types.ts +427 -0
- package/src/memories/index.ts +1281 -0
- package/src/memories/storage.ts +578 -0
- package/src/memory-backend/index.ts +18 -0
- package/src/memory-backend/local-backend.ts +45 -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/types.ts +166 -0
- package/src/mnemopi/backend.ts +612 -0
- package/src/mnemopi/config.ts +265 -0
- package/src/mnemopi/embed-client.ts +401 -0
- package/src/mnemopi/embed-protocol.ts +35 -0
- package/src/mnemopi/embed-worker.ts +113 -0
- package/src/mnemopi/index.ts +3 -0
- package/src/mnemopi/state.ts +657 -0
- package/src/modes/acp/acp-agent.ts +2362 -0
- package/src/modes/acp/acp-client-bridge.ts +154 -0
- package/src/modes/acp/acp-event-mapper.ts +933 -0
- package/src/modes/acp/acp-mode.ts +23 -0
- package/src/modes/acp/index.ts +2 -0
- package/src/modes/acp/terminal-auth.ts +37 -0
- package/src/modes/components/__tests__/skill-message.test.ts +92 -0
- package/src/modes/components/advisor-message.ts +99 -0
- package/src/modes/components/agent-dashboard.ts +1206 -0
- package/src/modes/components/agent-hub.ts +566 -0
- package/src/modes/components/agent-transcript-viewer.ts +461 -0
- package/src/modes/components/assistant-message.ts +612 -0
- package/src/modes/components/background-tan-message.ts +36 -0
- package/src/modes/components/bash-execution.ts +220 -0
- package/src/modes/components/bordered-loader.ts +41 -0
- package/src/modes/components/btw-panel.ts +112 -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 +476 -0
- package/src/modes/components/collab-prompt-message.ts +32 -0
- package/src/modes/components/compaction-summary-message.ts +215 -0
- package/src/modes/components/copy-selector.ts +206 -0
- package/src/modes/components/countdown-timer.ts +75 -0
- package/src/modes/components/custom-editor.test.ts +142 -0
- package/src/modes/components/custom-editor.ts +620 -0
- package/src/modes/components/custom-message.ts +67 -0
- package/src/modes/components/diff.ts +254 -0
- package/src/modes/components/dynamic-border.ts +34 -0
- package/src/modes/components/error-banner.ts +33 -0
- package/src/modes/components/eval-execution.ts +158 -0
- package/src/modes/components/execution-shared.ts +101 -0
- package/src/modes/components/extensions/extension-dashboard.ts +399 -0
- package/src/modes/components/extensions/extension-list.ts +502 -0
- package/src/modes/components/extensions/index.ts +9 -0
- package/src/modes/components/extensions/inspector-panel.ts +321 -0
- package/src/modes/components/extensions/state-manager.ts +627 -0
- package/src/modes/components/extensions/types.ts +186 -0
- package/src/modes/components/footer.ts +275 -0
- package/src/modes/components/history-search.ts +280 -0
- package/src/modes/components/hook-editor.ts +167 -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 +659 -0
- package/src/modes/components/index.ts +38 -0
- package/src/modes/components/keybinding-hints.ts +65 -0
- package/src/modes/components/late-diagnostics-message.ts +60 -0
- package/src/modes/components/login-dialog.ts +164 -0
- package/src/modes/components/logout-account-selector.ts +130 -0
- package/src/modes/components/mcp-add-wizard.ts +1360 -0
- package/src/modes/components/message-frame.ts +92 -0
- package/src/modes/components/model-selector.ts +1315 -0
- package/src/modes/components/oauth-selector.ts +457 -0
- package/src/modes/components/omfg-panel.ts +141 -0
- package/src/modes/components/overlay-box.ts +109 -0
- package/src/modes/components/plan-review-overlay.ts +847 -0
- package/src/modes/components/plan-toc.ts +138 -0
- package/src/modes/components/plugin-selector.ts +95 -0
- package/src/modes/components/plugin-settings.ts +739 -0
- package/src/modes/components/queue-mode-selector.ts +56 -0
- package/src/modes/components/read-tool-group.ts +676 -0
- package/src/modes/components/reset-usage-selector.ts +161 -0
- package/src/modes/components/segment-track.ts +89 -0
- package/src/modes/components/session-selector.ts +631 -0
- package/src/modes/components/settings-defs.ts +225 -0
- package/src/modes/components/settings-selector.ts +1095 -0
- package/src/modes/components/show-images-selector.ts +45 -0
- package/src/modes/components/skill-message.ts +110 -0
- package/src/modes/components/snapcompact-shape-preview-doc.md +18 -0
- package/src/modes/components/snapcompact-shape-preview.ts +192 -0
- package/src/modes/components/status-line/component.ts +1001 -0
- package/src/modes/components/status-line/context-thresholds.ts +78 -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 +616 -0
- package/src/modes/components/status-line/separators.ts +55 -0
- package/src/modes/components/status-line/token-rate.ts +66 -0
- package/src/modes/components/status-line/types.ts +124 -0
- package/src/modes/components/theme-selector.ts +63 -0
- package/src/modes/components/thinking-selector.ts +52 -0
- package/src/modes/components/tiny-title-download-progress.ts +90 -0
- package/src/modes/components/tips.txt +24 -0
- package/src/modes/components/todo-reminder.ts +39 -0
- package/src/modes/components/tool-execution.ts +1165 -0
- package/src/modes/components/transcript-container.ts +806 -0
- package/src/modes/components/tree-selector.ts +994 -0
- package/src/modes/components/ttsr-notification.ts +123 -0
- package/src/modes/components/usage-row.ts +18 -0
- package/src/modes/components/user-message-selector.ts +227 -0
- package/src/modes/components/user-message.ts +68 -0
- package/src/modes/components/visual-truncate.ts +63 -0
- package/src/modes/components/welcome.ts +581 -0
- package/src/modes/controllers/btw-controller.ts +173 -0
- package/src/modes/controllers/command-controller-shared.ts +109 -0
- package/src/modes/controllers/command-controller.ts +1653 -0
- package/src/modes/controllers/event-controller.ts +1153 -0
- package/src/modes/controllers/extension-ui-controller.ts +893 -0
- package/src/modes/controllers/input-controller.ts +1627 -0
- package/src/modes/controllers/mcp-command-controller.ts +2162 -0
- package/src/modes/controllers/omfg-controller.ts +283 -0
- package/src/modes/controllers/omfg-rule.ts +647 -0
- package/src/modes/controllers/selector-controller.ts +1285 -0
- package/src/modes/controllers/session-focus-controller.ts +112 -0
- package/src/modes/controllers/ssh-command-controller.ts +384 -0
- package/src/modes/controllers/streaming-reveal.ts +295 -0
- package/src/modes/controllers/tan-command-controller.ts +190 -0
- package/src/modes/controllers/todo-command-controller.ts +485 -0
- package/src/modes/controllers/tool-args-reveal.ts +174 -0
- package/src/modes/data/emojis.json +1 -0
- package/src/modes/emoji-autocomplete.ts +285 -0
- package/src/modes/gradient-highlight.ts +99 -0
- package/src/modes/image-references.ts +137 -0
- package/src/modes/index.ts +17 -0
- package/src/modes/interactive-mode.ts +3940 -0
- package/src/modes/internal-url-autocomplete.ts +143 -0
- package/src/modes/loop-limit.ts +192 -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 +42 -0
- package/src/modes/print-mode.ts +130 -0
- package/src/modes/prompt-action-autocomplete.ts +260 -0
- package/src/modes/rpc/host-tools.ts +186 -0
- package/src/modes/rpc/host-uris.ts +235 -0
- package/src/modes/rpc/rpc-client.ts +995 -0
- package/src/modes/rpc/rpc-mode.ts +1156 -0
- package/src/modes/rpc/rpc-subagents.ts +265 -0
- package/src/modes/rpc/rpc-types.ts +487 -0
- package/src/modes/runtime-init.ts +142 -0
- package/src/modes/session-observer-registry.ts +215 -0
- package/src/modes/setup-version.ts +11 -0
- package/src/modes/setup-wizard/index.ts +101 -0
- package/src/modes/setup-wizard/lazy.ts +16 -0
- package/src/modes/setup-wizard/scenes/glyph.ts +114 -0
- package/src/modes/setup-wizard/scenes/outro.ts +35 -0
- package/src/modes/setup-wizard/scenes/providers.ts +103 -0
- package/src/modes/setup-wizard/scenes/sign-in.ts +286 -0
- package/src/modes/setup-wizard/scenes/splash.ts +201 -0
- package/src/modes/setup-wizard/scenes/theme.ts +326 -0
- package/src/modes/setup-wizard/scenes/types.ts +57 -0
- package/src/modes/setup-wizard/scenes/web-search.ts +145 -0
- package/src/modes/setup-wizard/startup-splash.ts +107 -0
- package/src/modes/setup-wizard/wizard-overlay.ts +334 -0
- package/src/modes/shared.ts +49 -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 +142 -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 +142 -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 +235 -0
- package/src/modes/theme/theme-schema.json +459 -0
- package/src/modes/theme/theme.ts +2915 -0
- package/src/modes/turn-budget.ts +31 -0
- package/src/modes/types.ts +406 -0
- package/src/modes/ultrathink.ts +41 -0
- package/src/modes/utils/context-usage.ts +432 -0
- package/src/modes/utils/copy-targets.ts +360 -0
- package/src/modes/utils/hotkeys-markdown.ts +62 -0
- package/src/modes/utils/keybinding-matchers.ts +51 -0
- package/src/modes/utils/tools-markdown.ts +27 -0
- package/src/modes/utils/ui-helpers.ts +886 -0
- package/src/modes/workflow.ts +42 -0
- package/src/plan-mode/approved-plan.ts +186 -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 +45 -0
- package/src/prompts/advisor/advise-tool.md +3 -0
- package/src/prompts/advisor/system.md +113 -0
- package/src/prompts/agents/designer.md +74 -0
- package/src/prompts/agents/explore.md +58 -0
- package/src/prompts/agents/frontmatter.md +11 -0
- package/src/prompts/agents/init.md +33 -0
- package/src/prompts/agents/librarian.md +119 -0
- package/src/prompts/agents/oracle.md +54 -0
- package/src/prompts/agents/plan.md +48 -0
- package/src/prompts/agents/reviewer.md +139 -0
- package/src/prompts/agents/task.md +17 -0
- package/src/prompts/bench.md +12 -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/guided-goal-interview.md +8 -0
- package/src/prompts/goals/guided-goal-system.md +12 -0
- package/src/prompts/low-end/system.md +47 -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 +22 -0
- package/src/prompts/review-headless-request.md +16 -0
- package/src/prompts/review-request.md +69 -0
- package/src/prompts/steering/user-interjection.md +9 -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 +12 -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.md +3 -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/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/irc-autoreply.md +6 -0
- package/src/prompts/system/irc-incoming.md +7 -0
- package/src/prompts/system/manual-continue.md +7 -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/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 +109 -0
- package/src/prompts/system/plan-mode-approved.md +25 -0
- package/src/prompts/system/plan-mode-compact-instructions.md +16 -0
- package/src/prompts/system/plan-mode-reference.md +11 -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/project-prompt.md +52 -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/subagent-system-prompt.md +71 -0
- package/src/prompts/system/subagent-user-prompt.md +3 -0
- package/src/prompts/system/subagent-yield-reminder.md +12 -0
- package/src/prompts/system/system-prompt.md +251 -0
- package/src/prompts/system/tiny-title-system.md +8 -0
- package/src/prompts/system/title-marker-instruction.md +1 -0
- package/src/prompts/system/title-system-marker.md +16 -0
- package/src/prompts/system/title-system.md +16 -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/web-search.md +25 -0
- package/src/prompts/system/workflow-notice.md +70 -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 +22 -0
- package/src/prompts/tools/ast-grep.md +25 -0
- package/src/prompts/tools/async-result.md +8 -0
- package/src/prompts/tools/bash.md +45 -0
- package/src/prompts/tools/browser.md +42 -0
- package/src/prompts/tools/checkpoint.md +15 -0
- package/src/prompts/tools/debug.md +17 -0
- package/src/prompts/tools/eval.md +70 -0
- package/src/prompts/tools/find.md +19 -0
- package/src/prompts/tools/github.md +17 -0
- package/src/prompts/tools/goal.md +11 -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/irc.md +33 -0
- package/src/prompts/tools/job.md +17 -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 +39 -0
- package/src/prompts/tools/manage-skill.md +9 -0
- package/src/prompts/tools/memory-edit.md +8 -0
- package/src/prompts/tools/patch.md +57 -0
- package/src/prompts/tools/read.md +76 -0
- package/src/prompts/tools/recall.md +5 -0
- package/src/prompts/tools/reflect.md +5 -0
- package/src/prompts/tools/replace.md +29 -0
- package/src/prompts/tools/resolve.md +4 -0
- package/src/prompts/tools/retain.md +6 -0
- package/src/prompts/tools/rewind.md +13 -0
- package/src/prompts/tools/search-tool-bm25.md +32 -0
- package/src/prompts/tools/search.md +22 -0
- package/src/prompts/tools/ssh.md +22 -0
- package/src/prompts/tools/task-summary.md +17 -0
- package/src/prompts/tools/task.md +91 -0
- package/src/prompts/tools/todo.md +39 -0
- package/src/prompts/tools/web-search.md +6 -0
- package/src/prompts/tools/write.md +14 -0
- package/src/registry/agent-lifecycle.ts +270 -0
- package/src/registry/agent-registry.ts +190 -0
- package/src/sdk.ts +2919 -0
- package/src/secrets/index.ts +123 -0
- package/src/secrets/obfuscator.ts +298 -0
- package/src/secrets/regex.ts +21 -0
- package/src/session/agent-session.ts +12539 -0
- package/src/session/agent-storage.ts +478 -0
- package/src/session/artifacts.ts +153 -0
- package/src/session/auth-broker-config.ts +92 -0
- package/src/session/auth-storage.ts +24 -0
- package/src/session/blob-store.ts +255 -0
- package/src/session/client-bridge.ts +85 -0
- package/src/session/codex-auto-reset.ts +202 -0
- package/src/session/compact-modes.ts +105 -0
- package/src/session/history-storage.ts +361 -0
- package/src/session/indexed-session-storage.ts +427 -0
- package/src/session/messages.ts +546 -0
- package/src/session/redis-session-storage.ts +170 -0
- package/src/session/session-context.ts +399 -0
- package/src/session/session-dump-format.ts +216 -0
- package/src/session/session-entries.ts +198 -0
- package/src/session/session-history-format.ts +308 -0
- package/src/session/session-listing.ts +588 -0
- package/src/session/session-loader.ts +93 -0
- package/src/session/session-manager.ts +1748 -0
- package/src/session/session-migrations.ts +78 -0
- package/src/session/session-paths.ts +193 -0
- package/src/session/session-persistence.ts +147 -0
- package/src/session/session-storage.ts +590 -0
- package/src/session/shake-types.ts +43 -0
- package/src/session/snapcompact-inline.ts +542 -0
- package/src/session/snapcompact-savings-journal.ts +113 -0
- package/src/session/sql-session-storage.ts +314 -0
- package/src/session/streaming-output.ts +1330 -0
- package/src/session/tool-choice-queue.ts +290 -0
- package/src/session/unexpected-stop-classifier.ts +129 -0
- package/src/session/yield-queue.ts +183 -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 +2332 -0
- package/src/slash-commands/helpers/active-oauth-account.ts +44 -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 +88 -0
- package/src/slash-commands/helpers/marketplace-manager.ts +25 -0
- package/src/slash-commands/helpers/mcp.ts +532 -0
- package/src/slash-commands/helpers/parse.ts +85 -0
- package/src/slash-commands/helpers/reset-usage.ts +66 -0
- package/src/slash-commands/helpers/ssh.ts +195 -0
- package/src/slash-commands/helpers/stats-dashboard.ts +85 -0
- package/src/slash-commands/helpers/todo.ts +279 -0
- package/src/slash-commands/helpers/usage-report.ts +128 -0
- package/src/slash-commands/marketplace-install-parser.ts +99 -0
- package/src/slash-commands/types.ts +135 -0
- package/src/ssh/config-writer.ts +183 -0
- package/src/ssh/connection-manager.ts +510 -0
- package/src/ssh/ssh-executor.ts +189 -0
- package/src/ssh/sshfs-mount.ts +140 -0
- package/src/ssh/utils.ts +8 -0
- package/src/startup-splash.ts +19 -0
- package/src/stt/asr-client.ts +521 -0
- package/src/stt/asr-protocol.ts +65 -0
- package/src/stt/asr-worker.ts +790 -0
- package/src/stt/downloader.ts +138 -0
- package/src/stt/endpointer.ts +259 -0
- package/src/stt/index.ts +7 -0
- package/src/stt/models.ts +150 -0
- package/src/stt/recorder.ts +538 -0
- package/src/stt/stt-controller.ts +380 -0
- package/src/stt/transcriber.ts +60 -0
- package/src/stt/wav.ts +173 -0
- package/src/system-prompt.ts +709 -0
- package/src/task/agents.ts +166 -0
- package/src/task/commands.ts +132 -0
- package/src/task/discovery.ts +122 -0
- package/src/task/executor.ts +2356 -0
- package/src/task/index.ts +1580 -0
- package/src/task/name-generator.ts +1577 -0
- package/src/task/omp-command.ts +26 -0
- package/src/task/output-manager.ts +93 -0
- package/src/task/parallel.ts +116 -0
- package/src/task/persisted-revive.ts +128 -0
- package/src/task/render.ts +1558 -0
- package/src/task/repair-args.ts +129 -0
- package/src/task/subprocess-tool-registry.ts +88 -0
- package/src/task/types.ts +401 -0
- package/src/task/worktree.ts +514 -0
- package/src/telemetry-export.ts +144 -0
- package/src/thinking.ts +187 -0
- package/src/tiny/device.ts +111 -0
- package/src/tiny/dtype.ts +101 -0
- package/src/tiny/models.ts +252 -0
- package/src/tiny/text.ts +169 -0
- package/src/tiny/title-client.ts +538 -0
- package/src/tiny/title-protocol.ts +56 -0
- package/src/tiny/worker.ts +491 -0
- package/src/tool-discovery/mode.ts +24 -0
- package/src/tool-discovery/tool-index.ts +271 -0
- package/src/tools/__tests__/json-tree.test.ts +35 -0
- package/src/tools/approval.ts +189 -0
- package/src/tools/ask.ts +977 -0
- package/src/tools/ast-edit.ts +700 -0
- package/src/tools/ast-grep.ts +483 -0
- package/src/tools/auto-generated-guard.ts +322 -0
- package/src/tools/bash-command-fixup.ts +37 -0
- package/src/tools/bash-interactive.ts +408 -0
- package/src/tools/bash-interceptor.ts +67 -0
- package/src/tools/bash-pty-selection.ts +14 -0
- package/src/tools/bash-skill-urls.ts +248 -0
- package/src/tools/bash.ts +1405 -0
- package/src/tools/browser/attach.ts +194 -0
- package/src/tools/browser/cmux/cmux-tab.ts +1264 -0
- package/src/tools/browser/cmux/rpc.ts +156 -0
- package/src/tools/browser/cmux/socket-client.ts +309 -0
- package/src/tools/browser/launch.ts +673 -0
- package/src/tools/browser/readable.ts +112 -0
- package/src/tools/browser/registry.ts +241 -0
- package/src/tools/browser/render.ts +221 -0
- package/src/tools/browser/tab-protocol.ts +107 -0
- package/src/tools/browser/tab-supervisor.ts +799 -0
- package/src/tools/browser/tab-worker-entry.ts +29 -0
- package/src/tools/browser/tab-worker.ts +1226 -0
- package/src/tools/browser.ts +403 -0
- package/src/tools/builtin-names.ts +34 -0
- package/src/tools/checkpoint.ts +136 -0
- package/src/tools/conflict-detect.ts +718 -0
- package/src/tools/context.ts +39 -0
- package/src/tools/debug.ts +1087 -0
- package/src/tools/eval-backends.ts +27 -0
- package/src/tools/eval-render.ts +762 -0
- package/src/tools/eval.ts +600 -0
- package/src/tools/fetch.ts +1902 -0
- package/src/tools/file-recorder.ts +35 -0
- package/src/tools/find.ts +629 -0
- package/src/tools/fs-cache-invalidation.ts +28 -0
- package/src/tools/gh-cache-invalidation.ts +255 -0
- package/src/tools/gh-format.ts +12 -0
- package/src/tools/gh-renderer.ts +481 -0
- package/src/tools/gh.ts +3752 -0
- package/src/tools/github-cache.ts +663 -0
- package/src/tools/grouped-file-output.ts +210 -0
- package/src/tools/image-gen.ts +1586 -0
- package/src/tools/index.ts +649 -0
- package/src/tools/inspect-image-renderer.ts +132 -0
- package/src/tools/inspect-image.ts +260 -0
- package/src/tools/irc.ts +788 -0
- package/src/tools/job.ts +612 -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 +100 -0
- package/src/tools/match-line-format.ts +20 -0
- package/src/tools/memory-edit.ts +59 -0
- package/src/tools/memory-recall.ts +102 -0
- package/src/tools/memory-reflect.ts +88 -0
- package/src/tools/memory-render.ts +202 -0
- package/src/tools/memory-retain.ts +89 -0
- package/src/tools/output-meta.ts +768 -0
- package/src/tools/output-schema-validator.ts +132 -0
- package/src/tools/path-utils.ts +1116 -0
- package/src/tools/plan-mode-guard.ts +142 -0
- package/src/tools/puppeteer/00_stealth_tampering.txt +63 -0
- package/src/tools/puppeteer/01_stealth_activity.txt +20 -0
- package/src/tools/puppeteer/02_stealth_hairline.txt +11 -0
- package/src/tools/puppeteer/03_stealth_botd.txt +384 -0
- package/src/tools/puppeteer/04_stealth_iframe.txt +81 -0
- package/src/tools/puppeteer/05_stealth_webgl.txt +75 -0
- package/src/tools/puppeteer/06_stealth_screen.txt +72 -0
- package/src/tools/puppeteer/07_stealth_fonts.txt +97 -0
- package/src/tools/puppeteer/08_stealth_audio.txt +51 -0
- package/src/tools/puppeteer/09_stealth_locale.txt +46 -0
- package/src/tools/puppeteer/10_stealth_plugins.txt +208 -0
- package/src/tools/puppeteer/11_stealth_hardware.txt +8 -0
- package/src/tools/puppeteer/12_stealth_codecs.txt +40 -0
- package/src/tools/puppeteer/13_stealth_worker.txt +74 -0
- package/src/tools/read.ts +3124 -0
- package/src/tools/render-utils.ts +895 -0
- package/src/tools/renderers.ts +86 -0
- package/src/tools/report-tool-issue.ts +530 -0
- package/src/tools/resolve.ts +302 -0
- package/src/tools/review.ts +251 -0
- package/src/tools/search-tool-bm25.ts +351 -0
- package/src/tools/search.ts +1583 -0
- package/src/tools/sqlite-reader.ts +828 -0
- package/src/tools/ssh.ts +369 -0
- package/src/tools/todo.ts +938 -0
- package/src/tools/tool-errors.ts +62 -0
- package/src/tools/tool-result.ts +102 -0
- package/src/tools/tool-timeouts.ts +30 -0
- package/src/tools/tts.ts +265 -0
- package/src/tools/write.ts +1182 -0
- package/src/tools/yield.ts +269 -0
- package/src/tts/downloader.ts +64 -0
- package/src/tts/index.ts +8 -0
- package/src/tts/models.ts +137 -0
- package/src/tts/player.ts +137 -0
- package/src/tts/runtime.ts +21 -0
- package/src/tts/streaming-player.ts +266 -0
- package/src/tts/tts-client.ts +642 -0
- package/src/tts/tts-protocol.ts +60 -0
- package/src/tts/tts-worker.ts +505 -0
- package/src/tts/vocalizer.ts +162 -0
- package/src/tts/wav.ts +58 -0
- package/src/tui/code-cell.ts +257 -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 +240 -0
- package/src/tui/status-line.ts +54 -0
- package/src/tui/tree-list.ts +133 -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/block-context.ts +312 -0
- package/src/utils/changelog.ts +132 -0
- package/src/utils/clipboard.ts +262 -0
- package/src/utils/command-args.ts +76 -0
- package/src/utils/commit-message-generator.ts +147 -0
- package/src/utils/edit-mode.ts +41 -0
- package/src/utils/enhanced-paste.ts +230 -0
- package/src/utils/event-bus.ts +33 -0
- package/src/utils/external-editor.ts +78 -0
- package/src/utils/file-display-mode.ts +45 -0
- package/src/utils/file-mentions.ts +284 -0
- package/src/utils/git.ts +1838 -0
- package/src/utils/image-loading.ts +231 -0
- package/src/utils/image-resize.ts +309 -0
- package/src/utils/image-vision-fallback.ts +197 -0
- package/src/utils/ipc.ts +38 -0
- package/src/utils/jj.ts +248 -0
- package/src/utils/lang-from-path.ts +244 -0
- package/src/utils/markit.ts +143 -0
- package/src/utils/mupdf-wasm-embed.ts +12 -0
- package/src/utils/open.ts +55 -0
- package/src/utils/qrcode.ts +535 -0
- package/src/utils/session-color.ts +142 -0
- package/src/utils/shell-snapshot.ts +187 -0
- package/src/utils/sixel.ts +69 -0
- package/src/utils/thinking-display.ts +11 -0
- package/src/utils/title-generator.ts +416 -0
- package/src/utils/tool-choice.ts +49 -0
- package/src/utils/tools-manager.ts +372 -0
- package/src/utils/turndown.ts +83 -0
- package/src/utils/zip.ts +1091 -0
- package/src/web/kagi.ts +304 -0
- package/src/web/parallel.ts +353 -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 +652 -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 +140 -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 +120 -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 +317 -0
- package/src/web/search/provider.ts +169 -0
- package/src/web/search/providers/anthropic.ts +343 -0
- package/src/web/search/providers/base.ts +90 -0
- package/src/web/search/providers/brave.ts +152 -0
- package/src/web/search/providers/codex.ts +593 -0
- package/src/web/search/providers/exa.ts +400 -0
- package/src/web/search/providers/gemini.ts +518 -0
- package/src/web/search/providers/jina.ts +111 -0
- package/src/web/search/providers/kagi.ts +86 -0
- package/src/web/search/providers/kimi.ts +196 -0
- package/src/web/search/providers/parallel.ts +225 -0
- package/src/web/search/providers/perplexity-auth.ts +133 -0
- package/src/web/search/providers/perplexity.ts +866 -0
- package/src/web/search/providers/searxng.ts +325 -0
- package/src/web/search/providers/synthetic.ts +114 -0
- package/src/web/search/providers/tavily.ts +176 -0
- package/src/web/search/providers/utils.ts +128 -0
- package/src/web/search/providers/zai.ts +333 -0
- package/src/web/search/render.ts +262 -0
- package/src/web/search/types.ts +462 -0
- package/src/web/search/utils.ts +17 -0
- package/src/workspace-tree.ts +326 -0
package/src/utils/zip.ts
ADDED
|
@@ -0,0 +1,1091 @@
|
|
|
1
|
+
// The single archive boundary for the codebase: ZIP (framed here, over the raw
|
|
2
|
+
// DEFLATE codec in `node:zlib`) and tar / tar.gz (via `Bun.Archive`). This is
|
|
3
|
+
// the ONLY module that frames ZIP containers or touches `Bun.Archive`; the
|
|
4
|
+
// markit document converters, the read/search/write tools, the URL fetcher, the
|
|
5
|
+
// debug report bundler, and the tool-binary installer all go through here so
|
|
6
|
+
// there is exactly one archive implementation to reason about. Do not parse or
|
|
7
|
+
// build ZIP/tar, or call `Bun.Archive`, anywhere else.
|
|
8
|
+
import * as path from "node:path";
|
|
9
|
+
import * as zlib from "node:zlib";
|
|
10
|
+
import { formatBytes } from "@oh-my-pi/pi-utils";
|
|
11
|
+
import { ToolError } from "../tools/tool-errors";
|
|
12
|
+
|
|
13
|
+
/** A ZIP archive decoded to a `path → bytes` map of its file members. */
|
|
14
|
+
export type Unzipped = Record<string, Uint8Array>;
|
|
15
|
+
|
|
16
|
+
const ENCODER = new TextEncoder();
|
|
17
|
+
// `node:zlib` is only the DEFLATE codec; ZIP container framing is ours (see
|
|
18
|
+
// `unzip` / `zip` below). Entry names use the platform text decoders.
|
|
19
|
+
const UTF8_DECODER = new TextDecoder();
|
|
20
|
+
// ZIP central-directory names without the UTF-8 flag carry no reliable encoding;
|
|
21
|
+
// decode them as their legacy code page (windows-1252) as a stable best effort.
|
|
22
|
+
const LEGACY_NAME_DECODER = new TextDecoder("windows-1252");
|
|
23
|
+
|
|
24
|
+
/** Read a single ZIP entry as UTF-8 text, or `undefined` when the entry is absent. */
|
|
25
|
+
export function unzipText(entries: Unzipped, entryPath: string): string | undefined {
|
|
26
|
+
const data = entries[entryPath];
|
|
27
|
+
return data ? UTF8_DECODER.decode(data) : undefined;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Decode an in-memory ZIP archive into a `path → bytes` map of its file members
|
|
32
|
+
* (directory entries and `..`-escaping names are dropped). Shares the
|
|
33
|
+
* central-directory record parser with the lazy, file-backed reader.
|
|
34
|
+
*/
|
|
35
|
+
export function unzip(bytes: Uint8Array): Unzipped {
|
|
36
|
+
const info = readCentralDirectoryInfoSync(bytes);
|
|
37
|
+
const centralDirectory = readMemoryRange(bytes, info.offset, info.offset + info.size);
|
|
38
|
+
const out: Unzipped = {};
|
|
39
|
+
for (const entry of parseZipCentralDirectory(memoryByteSource(bytes), centralDirectory, info.entries)) {
|
|
40
|
+
if (entry.isDirectory || entry.storage?.type !== "zip") continue;
|
|
41
|
+
out[entry.path] = extractZipMember(bytes, entry.storage, entry.size);
|
|
42
|
+
}
|
|
43
|
+
return out;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Cap on the on-disk size of tar/tar.gz archives, which are loaded fully into
|
|
48
|
+
* memory (and decompressed by `Bun.Archive`) just to index entries. ZIP is
|
|
49
|
+
* exempt: it is read via ranged central-directory access.
|
|
50
|
+
*/
|
|
51
|
+
const MAX_TAR_ARCHIVE_BYTES = 256 * 1024 * 1024;
|
|
52
|
+
/**
|
|
53
|
+
* Cap on a single archive member's declared (uncompressed) size. The declared
|
|
54
|
+
* size is attacker-controlled metadata — a crafted ZIP entry can claim
|
|
55
|
+
* multi-GB sizes that would be allocated up front before any data inflates.
|
|
56
|
+
*/
|
|
57
|
+
const MAX_ARCHIVE_MEMBER_BYTES = 64 * 1024 * 1024;
|
|
58
|
+
|
|
59
|
+
/** Inflate one raw DEFLATE stream, bounded to its declared uncompressed size. */
|
|
60
|
+
function inflateRaw(bytes: Uint8Array, declaredSize: number): Uint8Array {
|
|
61
|
+
return zlib.inflateRawSync(bytes, { maxOutputLength: Math.max(declaredSize, 1) });
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export type ArchiveFormat = "zip" | "tar" | "tar.gz";
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Where to read an archive from: a filesystem path (format inferred from the
|
|
68
|
+
* extension; ZIP is read lazily via ranged central-directory access) or
|
|
69
|
+
* in-memory bytes with an explicit format.
|
|
70
|
+
*/
|
|
71
|
+
export type ArchiveSource = string | { bytes: Uint8Array; format: ArchiveFormat };
|
|
72
|
+
|
|
73
|
+
/** Content for a member when packing or extracting an archive. */
|
|
74
|
+
export type ArchiveMemberContent = string | Uint8Array | Blob;
|
|
75
|
+
|
|
76
|
+
export interface ArchivePathCandidate {
|
|
77
|
+
archivePath: string;
|
|
78
|
+
subPath: string;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface ArchiveNode {
|
|
82
|
+
path: string;
|
|
83
|
+
isDirectory: boolean;
|
|
84
|
+
size: number;
|
|
85
|
+
mtimeMs?: number;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export interface ArchiveDirectoryEntry extends ArchiveNode {
|
|
89
|
+
name: string;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export interface ExtractedArchiveFile extends ArchiveNode {
|
|
93
|
+
bytes: Uint8Array;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** A byte window into an archive — file-backed (lazy) or in-memory. */
|
|
97
|
+
interface ByteSource {
|
|
98
|
+
readonly size: number;
|
|
99
|
+
read(start: number, end: number): Promise<Uint8Array>;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function assertValidRange(start: number, end: number): void {
|
|
103
|
+
if (!Number.isSafeInteger(start) || !Number.isSafeInteger(end) || start < 0 || end < start) {
|
|
104
|
+
throw new ToolError("Invalid ZIP archive range");
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** Read an exact in-memory range, throwing (not clamping) when it runs past the buffer. */
|
|
109
|
+
function readMemoryRange(buffer: Uint8Array, start: number, end: number): Uint8Array {
|
|
110
|
+
assertValidRange(start, end);
|
|
111
|
+
if (end > buffer.byteLength) {
|
|
112
|
+
throw new ToolError("Invalid ZIP archive: truncated data");
|
|
113
|
+
}
|
|
114
|
+
return buffer.subarray(start, end);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function fileByteSource(filePath: string): ByteSource {
|
|
118
|
+
const file = Bun.file(filePath);
|
|
119
|
+
const size = file.size;
|
|
120
|
+
if (!Number.isSafeInteger(size)) {
|
|
121
|
+
throw new ToolError("ZIP archive is too large to read safely");
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
size,
|
|
125
|
+
async read(start, end) {
|
|
126
|
+
assertValidRange(start, end);
|
|
127
|
+
const bytes = await file.slice(start, end).bytes();
|
|
128
|
+
if (bytes.byteLength !== end - start) {
|
|
129
|
+
throw new ToolError("Invalid ZIP archive: truncated data");
|
|
130
|
+
}
|
|
131
|
+
return bytes;
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function memoryByteSource(buffer: Uint8Array): ByteSource {
|
|
137
|
+
return {
|
|
138
|
+
size: buffer.byteLength,
|
|
139
|
+
async read(start, end) {
|
|
140
|
+
return readMemoryRange(buffer, start, end);
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
interface TarStorage {
|
|
146
|
+
type: "tar";
|
|
147
|
+
file: File;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
interface ZipStorage {
|
|
151
|
+
type: "zip";
|
|
152
|
+
source: ByteSource;
|
|
153
|
+
compressedSize: number;
|
|
154
|
+
compression: number;
|
|
155
|
+
flags: number;
|
|
156
|
+
localHeaderOffset: number;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
type EntryStorage = TarStorage | ZipStorage;
|
|
160
|
+
|
|
161
|
+
interface ArchiveIndexEntry extends ArchiveNode {
|
|
162
|
+
storage?: EntryStorage;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function normalizeArchiveLookupPath(rawPath?: string): string | undefined {
|
|
166
|
+
if (!rawPath) return "";
|
|
167
|
+
|
|
168
|
+
const parts = rawPath.replace(/\\/g, "/").split("/");
|
|
169
|
+
const normalizedParts: string[] = [];
|
|
170
|
+
for (const part of parts) {
|
|
171
|
+
if (!part || part === ".") continue;
|
|
172
|
+
if (part === "..") return undefined;
|
|
173
|
+
normalizedParts.push(part);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return normalizedParts.join("/");
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function normalizeArchiveEntryPath(rawPath: string): string | undefined {
|
|
180
|
+
const parts = rawPath.replace(/\\/g, "/").split("/");
|
|
181
|
+
const normalizedParts: string[] = [];
|
|
182
|
+
for (const part of parts) {
|
|
183
|
+
if (!part || part === ".") continue;
|
|
184
|
+
if (part === "..") return undefined;
|
|
185
|
+
normalizedParts.push(part);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (normalizedParts.length === 0) return undefined;
|
|
189
|
+
return normalizedParts.join("/");
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function isArchiveDirectoryName(rawPath: string): boolean {
|
|
193
|
+
return rawPath.endsWith("/") || rawPath.endsWith("\\");
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function upsertArchiveEntry(map: Map<string, ArchiveIndexEntry>, entry: ArchiveIndexEntry): void {
|
|
197
|
+
const existing = map.get(entry.path);
|
|
198
|
+
if (!existing) {
|
|
199
|
+
map.set(entry.path, entry);
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
if (existing.isDirectory && !entry.isDirectory) {
|
|
204
|
+
map.set(entry.path, entry);
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (!existing.isDirectory && entry.isDirectory) {
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
map.set(entry.path, {
|
|
213
|
+
...existing,
|
|
214
|
+
size: existing.size || entry.size,
|
|
215
|
+
mtimeMs: existing.mtimeMs ?? entry.mtimeMs,
|
|
216
|
+
storage: existing.storage ?? entry.storage,
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function ensureParentDirectories(map: Map<string, ArchiveIndexEntry>): void {
|
|
221
|
+
for (const entry of [...map.values()]) {
|
|
222
|
+
const parts = entry.path.split("/");
|
|
223
|
+
const stop = parts.length - 1;
|
|
224
|
+
for (let index = 1; index <= stop; index++) {
|
|
225
|
+
const dirPath = parts.slice(0, index).join("/");
|
|
226
|
+
if (!dirPath || map.has(dirPath)) continue;
|
|
227
|
+
map.set(dirPath, {
|
|
228
|
+
path: dirPath,
|
|
229
|
+
isDirectory: true,
|
|
230
|
+
size: 0,
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/** Infer an archive format from a filesystem path's extension. */
|
|
237
|
+
export function archiveFormatFromPath(filePath: string): ArchiveFormat | undefined {
|
|
238
|
+
const normalized = filePath.toLowerCase();
|
|
239
|
+
if (normalized.endsWith(".tar.gz") || normalized.endsWith(".tgz")) return "tar.gz";
|
|
240
|
+
if (normalized.endsWith(".tar")) return "tar";
|
|
241
|
+
if (normalized.endsWith(".zip")) return "zip";
|
|
242
|
+
return undefined;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export function formatArchiveEntryLines(entries: readonly ArchiveDirectoryEntry[]): string[] {
|
|
246
|
+
return entries.map(entry => {
|
|
247
|
+
if (entry.isDirectory) return `${entry.name}/`;
|
|
248
|
+
|
|
249
|
+
const sizeSuffix = entry.size > 0 ? ` (${formatBytes(entry.size)})` : "";
|
|
250
|
+
return `${entry.name}${sizeSuffix}`;
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
const ZIP_LOCAL_FILE_HEADER_SIGNATURE = 0x04034b50;
|
|
255
|
+
const ZIP_CENTRAL_DIRECTORY_HEADER_SIGNATURE = 0x02014b50;
|
|
256
|
+
const ZIP64_EOCD_SIGNATURE = 0x06064b50;
|
|
257
|
+
const ZIP64_EOCD_LOCATOR_SIGNATURE = 0x07064b50;
|
|
258
|
+
const ZIP_EOCD_SIGNATURE = 0x06054b50;
|
|
259
|
+
const ZIP_DATA_DESCRIPTOR_SIGNATURE = 0x08074b50;
|
|
260
|
+
const ZIP_EOCD_MIN_LENGTH = 22;
|
|
261
|
+
const ZIP_EOCD_MAX_COMMENT_LENGTH = 0xffff;
|
|
262
|
+
const ZIP64_EOCD_LOCATOR_LENGTH = 20;
|
|
263
|
+
const ZIP_STORED_COMPRESSION = 0;
|
|
264
|
+
const ZIP_DEFLATE_COMPRESSION = 8;
|
|
265
|
+
const ZIP_UTF8_FLAG = 0x0800;
|
|
266
|
+
const ZIP_ENCRYPTED_FLAG = 0x0001;
|
|
267
|
+
const ZIP_UINT16_MAX = 0xffff;
|
|
268
|
+
const ZIP_UINT32_MAX = 0xffffffff;
|
|
269
|
+
const ZIP_UINT32_RANGE = 0x100000000;
|
|
270
|
+
|
|
271
|
+
interface ZipCentralDirectoryInfo {
|
|
272
|
+
entries: number;
|
|
273
|
+
offset: number;
|
|
274
|
+
size: number;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
interface Zip64EntryValues {
|
|
278
|
+
compressedSize: number;
|
|
279
|
+
uncompressedSize: number;
|
|
280
|
+
localHeaderOffset: number;
|
|
281
|
+
diskStart: number;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
interface Zip64EntryPlaceholders {
|
|
285
|
+
compressedSize: boolean;
|
|
286
|
+
uncompressedSize: boolean;
|
|
287
|
+
localHeaderOffset: boolean;
|
|
288
|
+
diskStart: boolean;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function readUInt16LE(bytes: Uint8Array, offset: number): number {
|
|
292
|
+
return bytes[offset]! | (bytes[offset + 1]! << 8);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
function readUInt32LE(bytes: Uint8Array, offset: number): number {
|
|
296
|
+
return (bytes[offset]! | (bytes[offset + 1]! << 8) | (bytes[offset + 2]! << 16) | (bytes[offset + 3]! << 24)) >>> 0;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
function bytesMatchAscii(bytes: Uint8Array, offset: number, value: string): boolean {
|
|
300
|
+
if (bytes.byteLength < offset + value.length) return false;
|
|
301
|
+
for (let index = 0; index < value.length; index++) {
|
|
302
|
+
if (bytes[offset + index] !== value.charCodeAt(index)) return false;
|
|
303
|
+
}
|
|
304
|
+
return true;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
export function sniffArchiveFormat(bytes: Uint8Array): ArchiveFormat | undefined {
|
|
308
|
+
if (bytes.byteLength >= 4) {
|
|
309
|
+
const signature = readUInt32LE(bytes, 0);
|
|
310
|
+
if (
|
|
311
|
+
signature === ZIP_LOCAL_FILE_HEADER_SIGNATURE ||
|
|
312
|
+
signature === ZIP_EOCD_SIGNATURE ||
|
|
313
|
+
signature === ZIP_DATA_DESCRIPTOR_SIGNATURE
|
|
314
|
+
) {
|
|
315
|
+
return "zip";
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
if (bytes.byteLength >= 2 && bytes[0] === 0x1f && bytes[1] === 0x8b) {
|
|
320
|
+
return "tar.gz";
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
if (bytesMatchAscii(bytes, 257, "ustar")) {
|
|
324
|
+
return "tar";
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
return undefined;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
function readUInt64LEAsNumber(bytes: Uint8Array, offset: number): number {
|
|
331
|
+
const value = readUInt32LE(bytes, offset) + readUInt32LE(bytes, offset + 4) * ZIP_UINT32_RANGE;
|
|
332
|
+
if (!Number.isSafeInteger(value)) {
|
|
333
|
+
throw new ToolError("ZIP archive uses offsets or sizes too large to read safely");
|
|
334
|
+
}
|
|
335
|
+
return value;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
function findEndOfCentralDirectory(tail: Uint8Array): number {
|
|
339
|
+
for (let offset = tail.byteLength - ZIP_EOCD_MIN_LENGTH; offset >= 0; offset--) {
|
|
340
|
+
if (readUInt32LE(tail, offset) !== ZIP_EOCD_SIGNATURE) continue;
|
|
341
|
+
const commentLength = readUInt16LE(tail, offset + 20);
|
|
342
|
+
if (offset + ZIP_EOCD_MIN_LENGTH + commentLength === tail.byteLength) return offset;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
throw new ToolError("Invalid ZIP archive: missing end of central directory");
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
async function readZip64CentralDirectoryInfo(
|
|
349
|
+
source: ByteSource,
|
|
350
|
+
tail: Uint8Array,
|
|
351
|
+
tailStart: number,
|
|
352
|
+
eocdOffset: number,
|
|
353
|
+
): Promise<ZipCentralDirectoryInfo | undefined> {
|
|
354
|
+
const locatorOffset = eocdOffset - ZIP64_EOCD_LOCATOR_LENGTH;
|
|
355
|
+
if (locatorOffset < 0) return undefined;
|
|
356
|
+
|
|
357
|
+
const locator =
|
|
358
|
+
locatorOffset >= tailStart
|
|
359
|
+
? tail.subarray(locatorOffset - tailStart, locatorOffset - tailStart + ZIP64_EOCD_LOCATOR_LENGTH)
|
|
360
|
+
: await source.read(locatorOffset, eocdOffset);
|
|
361
|
+
if (readUInt32LE(locator, 0) !== ZIP64_EOCD_LOCATOR_SIGNATURE) return undefined;
|
|
362
|
+
|
|
363
|
+
const zip64EocdDisk = readUInt32LE(locator, 4);
|
|
364
|
+
const zip64EocdOffset = readUInt64LEAsNumber(locator, 8);
|
|
365
|
+
const totalDisks = readUInt32LE(locator, 16);
|
|
366
|
+
if (zip64EocdDisk !== 0 || totalDisks > 1) {
|
|
367
|
+
throw new ToolError("Multi-disk ZIP archives are not supported");
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
const record = await source.read(zip64EocdOffset, zip64EocdOffset + 56);
|
|
371
|
+
if (readUInt32LE(record, 0) !== ZIP64_EOCD_SIGNATURE) {
|
|
372
|
+
throw new ToolError("Invalid ZIP archive: missing ZIP64 end of central directory");
|
|
373
|
+
}
|
|
374
|
+
if (readUInt32LE(record, 16) !== 0 || readUInt32LE(record, 20) !== 0) {
|
|
375
|
+
throw new ToolError("Multi-disk ZIP archives are not supported");
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
return {
|
|
379
|
+
entries: readUInt64LEAsNumber(record, 32),
|
|
380
|
+
size: readUInt64LEAsNumber(record, 40),
|
|
381
|
+
offset: readUInt64LEAsNumber(record, 48),
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
async function readZipCentralDirectoryInfo(source: ByteSource): Promise<ZipCentralDirectoryInfo> {
|
|
386
|
+
const fileSize = source.size;
|
|
387
|
+
if (fileSize < ZIP_EOCD_MIN_LENGTH) {
|
|
388
|
+
throw new ToolError("Invalid ZIP archive: missing end of central directory");
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
const tailLength = Math.min(fileSize, ZIP_EOCD_MIN_LENGTH + ZIP_EOCD_MAX_COMMENT_LENGTH);
|
|
392
|
+
const tailStart = fileSize - tailLength;
|
|
393
|
+
const tail = await source.read(tailStart, fileSize);
|
|
394
|
+
const eocdIndex = findEndOfCentralDirectory(tail);
|
|
395
|
+
const eocdOffset = tailStart + eocdIndex;
|
|
396
|
+
|
|
397
|
+
if (readUInt16LE(tail, eocdIndex + 4) !== 0 || readUInt16LE(tail, eocdIndex + 6) !== 0) {
|
|
398
|
+
throw new ToolError("Multi-disk ZIP archives are not supported");
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
let entries = readUInt16LE(tail, eocdIndex + 10);
|
|
402
|
+
let size = readUInt32LE(tail, eocdIndex + 12);
|
|
403
|
+
let offset = readUInt32LE(tail, eocdIndex + 16);
|
|
404
|
+
const needsZip64 = entries === ZIP_UINT16_MAX || size === ZIP_UINT32_MAX || offset === ZIP_UINT32_MAX;
|
|
405
|
+
const zip64Info = await readZip64CentralDirectoryInfo(source, tail, tailStart, eocdOffset);
|
|
406
|
+
if (zip64Info) {
|
|
407
|
+
({ entries, size, offset } = zip64Info);
|
|
408
|
+
} else if (needsZip64) {
|
|
409
|
+
throw new ToolError("Invalid ZIP archive: missing ZIP64 central directory metadata");
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
if (offset + size > fileSize) {
|
|
413
|
+
throw new ToolError("Invalid ZIP archive: central directory exceeds file size");
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
return { entries, offset, size };
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
function readZip64EntryValues(
|
|
420
|
+
extra: Uint8Array,
|
|
421
|
+
placeholders: Zip64EntryPlaceholders,
|
|
422
|
+
current: Zip64EntryValues,
|
|
423
|
+
): Zip64EntryValues {
|
|
424
|
+
if (
|
|
425
|
+
!placeholders.compressedSize &&
|
|
426
|
+
!placeholders.uncompressedSize &&
|
|
427
|
+
!placeholders.localHeaderOffset &&
|
|
428
|
+
!placeholders.diskStart
|
|
429
|
+
) {
|
|
430
|
+
return current;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
let offset = 0;
|
|
434
|
+
while (offset + 4 <= extra.byteLength) {
|
|
435
|
+
const headerId = readUInt16LE(extra, offset);
|
|
436
|
+
const dataSize = readUInt16LE(extra, offset + 2);
|
|
437
|
+
const dataStart = offset + 4;
|
|
438
|
+
const dataEnd = dataStart + dataSize;
|
|
439
|
+
if (dataEnd > extra.byteLength) {
|
|
440
|
+
throw new ToolError("Invalid ZIP archive: malformed extra field");
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
if (headerId === 0x0001) {
|
|
444
|
+
let cursor = dataStart;
|
|
445
|
+
let uncompressedSize = current.uncompressedSize;
|
|
446
|
+
let compressedSize = current.compressedSize;
|
|
447
|
+
let localHeaderOffset = current.localHeaderOffset;
|
|
448
|
+
let diskStart = current.diskStart;
|
|
449
|
+
|
|
450
|
+
if (placeholders.uncompressedSize) {
|
|
451
|
+
if (cursor + 8 > dataEnd) throw new ToolError("Invalid ZIP archive: malformed ZIP64 extra field");
|
|
452
|
+
uncompressedSize = readUInt64LEAsNumber(extra, cursor);
|
|
453
|
+
cursor += 8;
|
|
454
|
+
}
|
|
455
|
+
if (placeholders.compressedSize) {
|
|
456
|
+
if (cursor + 8 > dataEnd) throw new ToolError("Invalid ZIP archive: malformed ZIP64 extra field");
|
|
457
|
+
compressedSize = readUInt64LEAsNumber(extra, cursor);
|
|
458
|
+
cursor += 8;
|
|
459
|
+
}
|
|
460
|
+
if (placeholders.localHeaderOffset) {
|
|
461
|
+
if (cursor + 8 > dataEnd) throw new ToolError("Invalid ZIP archive: malformed ZIP64 extra field");
|
|
462
|
+
localHeaderOffset = readUInt64LEAsNumber(extra, cursor);
|
|
463
|
+
cursor += 8;
|
|
464
|
+
}
|
|
465
|
+
if (placeholders.diskStart) {
|
|
466
|
+
if (cursor + 4 > dataEnd) throw new ToolError("Invalid ZIP archive: malformed ZIP64 extra field");
|
|
467
|
+
diskStart = readUInt32LE(extra, cursor);
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
return { compressedSize, uncompressedSize, localHeaderOffset, diskStart };
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
offset = dataEnd;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
throw new ToolError("Invalid ZIP archive: missing ZIP64 extra field");
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
function parseZipCentralDirectory(
|
|
480
|
+
source: ByteSource,
|
|
481
|
+
centralDirectory: Uint8Array,
|
|
482
|
+
expectedEntries: number,
|
|
483
|
+
): ArchiveIndexEntry[] {
|
|
484
|
+
const entries: ArchiveIndexEntry[] = [];
|
|
485
|
+
let offset = 0;
|
|
486
|
+
|
|
487
|
+
for (let index = 0; index < expectedEntries; index++) {
|
|
488
|
+
if (offset + 46 > centralDirectory.byteLength) {
|
|
489
|
+
throw new ToolError("Invalid ZIP archive: truncated central directory");
|
|
490
|
+
}
|
|
491
|
+
if (readUInt32LE(centralDirectory, offset) !== ZIP_CENTRAL_DIRECTORY_HEADER_SIGNATURE) {
|
|
492
|
+
throw new ToolError("Invalid ZIP archive: malformed central directory");
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
const flags = readUInt16LE(centralDirectory, offset + 8);
|
|
496
|
+
const compression = readUInt16LE(centralDirectory, offset + 10);
|
|
497
|
+
const compressedSizeRaw = readUInt32LE(centralDirectory, offset + 20);
|
|
498
|
+
const uncompressedSizeRaw = readUInt32LE(centralDirectory, offset + 24);
|
|
499
|
+
const fileNameLength = readUInt16LE(centralDirectory, offset + 28);
|
|
500
|
+
const extraLength = readUInt16LE(centralDirectory, offset + 30);
|
|
501
|
+
const commentLength = readUInt16LE(centralDirectory, offset + 32);
|
|
502
|
+
const diskStartRaw = readUInt16LE(centralDirectory, offset + 34);
|
|
503
|
+
const localHeaderOffsetRaw = readUInt32LE(centralDirectory, offset + 42);
|
|
504
|
+
const nameStart = offset + 46;
|
|
505
|
+
const extraStart = nameStart + fileNameLength;
|
|
506
|
+
const entryEnd = extraStart + extraLength + commentLength;
|
|
507
|
+
if (entryEnd > centralDirectory.byteLength) {
|
|
508
|
+
throw new ToolError("Invalid ZIP archive: truncated central directory entry");
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
const useLegacyEncoding = (flags & ZIP_UTF8_FLAG) === 0;
|
|
512
|
+
const rawPath = (useLegacyEncoding ? LEGACY_NAME_DECODER : UTF8_DECODER).decode(
|
|
513
|
+
centralDirectory.subarray(nameStart, extraStart),
|
|
514
|
+
);
|
|
515
|
+
const normalizedPath = normalizeArchiveEntryPath(rawPath);
|
|
516
|
+
if (normalizedPath) {
|
|
517
|
+
const values = readZip64EntryValues(
|
|
518
|
+
centralDirectory.subarray(extraStart, extraStart + extraLength),
|
|
519
|
+
{
|
|
520
|
+
compressedSize: compressedSizeRaw === ZIP_UINT32_MAX,
|
|
521
|
+
uncompressedSize: uncompressedSizeRaw === ZIP_UINT32_MAX,
|
|
522
|
+
localHeaderOffset: localHeaderOffsetRaw === ZIP_UINT32_MAX,
|
|
523
|
+
diskStart: diskStartRaw === ZIP_UINT16_MAX,
|
|
524
|
+
},
|
|
525
|
+
{
|
|
526
|
+
compressedSize: compressedSizeRaw,
|
|
527
|
+
uncompressedSize: uncompressedSizeRaw,
|
|
528
|
+
localHeaderOffset: localHeaderOffsetRaw,
|
|
529
|
+
diskStart: diskStartRaw,
|
|
530
|
+
},
|
|
531
|
+
);
|
|
532
|
+
if (values.diskStart !== 0) {
|
|
533
|
+
throw new ToolError("Multi-disk ZIP archives are not supported");
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
const isDirectory = isArchiveDirectoryName(rawPath);
|
|
537
|
+
entries.push({
|
|
538
|
+
path: normalizedPath,
|
|
539
|
+
isDirectory,
|
|
540
|
+
size: isDirectory ? 0 : values.uncompressedSize,
|
|
541
|
+
storage: isDirectory
|
|
542
|
+
? undefined
|
|
543
|
+
: {
|
|
544
|
+
type: "zip",
|
|
545
|
+
source,
|
|
546
|
+
compressedSize: values.compressedSize,
|
|
547
|
+
compression,
|
|
548
|
+
flags,
|
|
549
|
+
localHeaderOffset: values.localHeaderOffset,
|
|
550
|
+
},
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
offset = entryEnd;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
return entries;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
/** Decode a single ZIP member's already-read payload, bounded to its declared size. */
|
|
561
|
+
function decodeZipMember(compressed: Uint8Array, compression: number, declaredSize: number): Uint8Array {
|
|
562
|
+
if (compression === ZIP_STORED_COMPRESSION) {
|
|
563
|
+
return compressed;
|
|
564
|
+
}
|
|
565
|
+
if (compression !== ZIP_DEFLATE_COMPRESSION) {
|
|
566
|
+
throw new ToolError(`Unsupported ZIP compression method: ${compression}`);
|
|
567
|
+
}
|
|
568
|
+
try {
|
|
569
|
+
return inflateRaw(compressed, declaredSize);
|
|
570
|
+
} catch (error) {
|
|
571
|
+
throw new ToolError(error instanceof Error ? error.message : String(error));
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
async function readZipFileBytes(storage: ZipStorage, uncompressedSize: number): Promise<Uint8Array> {
|
|
576
|
+
if ((storage.flags & ZIP_ENCRYPTED_FLAG) !== 0) {
|
|
577
|
+
throw new ToolError("Encrypted ZIP entries are not supported");
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
const localHeader = await storage.source.read(storage.localHeaderOffset, storage.localHeaderOffset + 30);
|
|
581
|
+
if (readUInt32LE(localHeader, 0) !== ZIP_LOCAL_FILE_HEADER_SIGNATURE) {
|
|
582
|
+
throw new ToolError("Invalid ZIP archive: malformed local file header");
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
const fileNameLength = readUInt16LE(localHeader, 26);
|
|
586
|
+
const extraLength = readUInt16LE(localHeader, 28);
|
|
587
|
+
const dataStart = storage.localHeaderOffset + 30 + fileNameLength + extraLength;
|
|
588
|
+
const compressedBytes = await storage.source.read(dataStart, dataStart + storage.compressedSize);
|
|
589
|
+
return decodeZipMember(compressedBytes, storage.compression, uncompressedSize);
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
async function readTarEntries(bytes: Uint8Array): Promise<ArchiveIndexEntry[]> {
|
|
593
|
+
let archive: Bun.Archive;
|
|
594
|
+
try {
|
|
595
|
+
archive = new Bun.Archive(bytes);
|
|
596
|
+
} catch (error) {
|
|
597
|
+
throw new ToolError(error instanceof Error ? error.message : String(error));
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
let files: Map<string, File>;
|
|
601
|
+
try {
|
|
602
|
+
files = await archive.files();
|
|
603
|
+
} catch (error) {
|
|
604
|
+
throw new ToolError(error instanceof Error ? error.message : String(error));
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
const entries: ArchiveIndexEntry[] = [];
|
|
608
|
+
for (const [rawPath, file] of files) {
|
|
609
|
+
const normalizedPath = normalizeArchiveEntryPath(rawPath);
|
|
610
|
+
if (!normalizedPath) continue;
|
|
611
|
+
const mtimeMs = file.lastModified > 0 ? file.lastModified : undefined;
|
|
612
|
+
entries.push({
|
|
613
|
+
path: normalizedPath,
|
|
614
|
+
isDirectory: false,
|
|
615
|
+
size: file.size,
|
|
616
|
+
mtimeMs,
|
|
617
|
+
storage: { type: "tar", file },
|
|
618
|
+
});
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
return entries;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
async function readZipEntries(source: ByteSource): Promise<ArchiveIndexEntry[]> {
|
|
625
|
+
const directoryInfo = await readZipCentralDirectoryInfo(source);
|
|
626
|
+
const centralDirectory = await source.read(directoryInfo.offset, directoryInfo.offset + directoryInfo.size);
|
|
627
|
+
return parseZipCentralDirectory(source, centralDirectory, directoryInfo.entries);
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
/**
|
|
631
|
+
* Split an `archive.ext:inner/path` reference into every plausible
|
|
632
|
+
* `{ archivePath, subPath }` pair, longest archive prefix first. A path may
|
|
633
|
+
* contain more than one archive extension, so each candidate is a guess at
|
|
634
|
+
* where the archive ends and the member portion begins.
|
|
635
|
+
*/
|
|
636
|
+
export function parseArchivePathCandidates(filePath: string): ArchivePathCandidate[] {
|
|
637
|
+
const normalized = filePath.replace(/\\/g, "/");
|
|
638
|
+
const pattern = /\.(?:tar\.gz|tgz|zip|tar)(?=(?::|$))/gi;
|
|
639
|
+
const seen = new Set<string>();
|
|
640
|
+
const candidates: ArchivePathCandidate[] = [];
|
|
641
|
+
|
|
642
|
+
let match: RegExpExecArray | null;
|
|
643
|
+
while (true) {
|
|
644
|
+
match = pattern.exec(normalized);
|
|
645
|
+
if (match === null) {
|
|
646
|
+
break;
|
|
647
|
+
}
|
|
648
|
+
const end = match.index + match[0].length;
|
|
649
|
+
const archivePath = filePath.slice(0, end);
|
|
650
|
+
const subPath = normalized.slice(end).replace(/^:+/, "");
|
|
651
|
+
const key = `${archivePath}\0${subPath}`;
|
|
652
|
+
if (seen.has(key)) continue;
|
|
653
|
+
seen.add(key);
|
|
654
|
+
candidates.push({ archivePath, subPath });
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
return candidates.sort((left, right) => right.archivePath.length - left.archivePath.length);
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
/**
|
|
661
|
+
* An indexed, read-only view over a single archive. ZIP archives are indexed
|
|
662
|
+
* from the central directory and members are inflated on demand; tar archives
|
|
663
|
+
* are fully materialized by `Bun.Archive` up front.
|
|
664
|
+
*/
|
|
665
|
+
export class ArchiveReader {
|
|
666
|
+
readonly format: ArchiveFormat;
|
|
667
|
+
#entries = new Map<string, ArchiveIndexEntry>();
|
|
668
|
+
|
|
669
|
+
constructor(format: ArchiveFormat, entries: ArchiveIndexEntry[]) {
|
|
670
|
+
this.format = format;
|
|
671
|
+
for (const entry of entries) {
|
|
672
|
+
upsertArchiveEntry(this.#entries, entry);
|
|
673
|
+
}
|
|
674
|
+
ensureParentDirectories(this.#entries);
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
getNode(subPath?: string): ArchiveNode | undefined {
|
|
678
|
+
const normalizedPath = normalizeArchiveLookupPath(subPath);
|
|
679
|
+
if (normalizedPath === undefined) return undefined;
|
|
680
|
+
if (normalizedPath === "") {
|
|
681
|
+
return { path: "", isDirectory: true, size: 0 };
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
const entry = this.#entries.get(normalizedPath);
|
|
685
|
+
if (!entry) return undefined;
|
|
686
|
+
return {
|
|
687
|
+
path: entry.path,
|
|
688
|
+
isDirectory: entry.isDirectory,
|
|
689
|
+
size: entry.size,
|
|
690
|
+
mtimeMs: entry.mtimeMs,
|
|
691
|
+
};
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
listDirectory(subPath?: string): ArchiveDirectoryEntry[] {
|
|
695
|
+
const normalizedPath = normalizeArchiveLookupPath(subPath);
|
|
696
|
+
if (normalizedPath === undefined) {
|
|
697
|
+
throw new ToolError("Archive path cannot contain '..'");
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
if (normalizedPath) {
|
|
701
|
+
const entry = this.#entries.get(normalizedPath);
|
|
702
|
+
if (!entry) {
|
|
703
|
+
throw new ToolError(`Archive path '${normalizedPath}' not found`);
|
|
704
|
+
}
|
|
705
|
+
if (!entry.isDirectory) {
|
|
706
|
+
throw new ToolError(`Archive path '${normalizedPath}' is not a directory`);
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
const prefix = normalizedPath ? `${normalizedPath}/` : "";
|
|
711
|
+
const children = new Map<string, ArchiveDirectoryEntry>();
|
|
712
|
+
|
|
713
|
+
for (const entry of this.#entries.values()) {
|
|
714
|
+
if (normalizedPath) {
|
|
715
|
+
if (!entry.path.startsWith(prefix) || entry.path === normalizedPath) continue;
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
const relativePath = normalizedPath ? entry.path.slice(prefix.length) : entry.path;
|
|
719
|
+
const nextSegment = relativePath.split("/")[0];
|
|
720
|
+
if (!nextSegment) continue;
|
|
721
|
+
|
|
722
|
+
const childPath = normalizedPath ? `${normalizedPath}/${nextSegment}` : nextSegment;
|
|
723
|
+
if (children.has(childPath)) continue;
|
|
724
|
+
|
|
725
|
+
const childEntry = this.#entries.get(childPath);
|
|
726
|
+
const isDirectory = childEntry?.isDirectory ?? relativePath.includes("/");
|
|
727
|
+
children.set(childPath, {
|
|
728
|
+
name: nextSegment,
|
|
729
|
+
path: childPath,
|
|
730
|
+
isDirectory,
|
|
731
|
+
size: isDirectory ? 0 : (childEntry?.size ?? entry.size),
|
|
732
|
+
mtimeMs: childEntry?.mtimeMs ?? entry.mtimeMs,
|
|
733
|
+
});
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
return [...children.values()].sort((left, right) =>
|
|
737
|
+
left.name.toLowerCase().localeCompare(right.name.toLowerCase()),
|
|
738
|
+
);
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
async readFile(subPath: string): Promise<ExtractedArchiveFile> {
|
|
742
|
+
const normalizedPath = normalizeArchiveLookupPath(subPath);
|
|
743
|
+
if (!normalizedPath) {
|
|
744
|
+
throw new ToolError("Archive file path is required");
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
const entry = this.#entries.get(normalizedPath);
|
|
748
|
+
if (!entry) {
|
|
749
|
+
throw new ToolError(`Archive file '${normalizedPath}' not found`);
|
|
750
|
+
}
|
|
751
|
+
if (entry.isDirectory) {
|
|
752
|
+
throw new ToolError(`Archive path '${normalizedPath}' is a directory`);
|
|
753
|
+
}
|
|
754
|
+
if (!entry.storage) {
|
|
755
|
+
throw new ToolError(`Archive file '${normalizedPath}' has no readable storage`);
|
|
756
|
+
}
|
|
757
|
+
if (entry.size > MAX_ARCHIVE_MEMBER_BYTES) {
|
|
758
|
+
throw new ToolError(
|
|
759
|
+
`Archive member '${normalizedPath}' is too large to extract in memory (${formatBytes(entry.size)} > ${formatBytes(MAX_ARCHIVE_MEMBER_BYTES)} limit)`,
|
|
760
|
+
);
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
const bytes =
|
|
764
|
+
entry.storage.type === "tar"
|
|
765
|
+
? await entry.storage.file.bytes()
|
|
766
|
+
: await readZipFileBytes(entry.storage, entry.size);
|
|
767
|
+
|
|
768
|
+
return {
|
|
769
|
+
path: entry.path,
|
|
770
|
+
isDirectory: false,
|
|
771
|
+
size: entry.size,
|
|
772
|
+
mtimeMs: entry.mtimeMs,
|
|
773
|
+
bytes,
|
|
774
|
+
};
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
/**
|
|
779
|
+
* Open an archive for reading. ZIP archives opened from a path are indexed
|
|
780
|
+
* lazily via ranged central-directory reads (members inflate on demand); tar
|
|
781
|
+
* archives and in-memory ZIPs are read from a single buffer.
|
|
782
|
+
*/
|
|
783
|
+
export async function openArchive(source: ArchiveSource): Promise<ArchiveReader> {
|
|
784
|
+
if (typeof source === "string") {
|
|
785
|
+
const format = archiveFormatFromPath(source);
|
|
786
|
+
if (!format) {
|
|
787
|
+
throw new ToolError(`Unsupported archive format: ${source}`);
|
|
788
|
+
}
|
|
789
|
+
if (format === "zip") {
|
|
790
|
+
return new ArchiveReader(format, await readZipEntries(fileByteSource(source)));
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
const file = Bun.file(source);
|
|
794
|
+
const archiveSize = file.size;
|
|
795
|
+
if (archiveSize > MAX_TAR_ARCHIVE_BYTES) {
|
|
796
|
+
throw new ToolError(
|
|
797
|
+
`Archive is too large to read in memory (${formatBytes(archiveSize)} > ${formatBytes(MAX_TAR_ARCHIVE_BYTES)} limit)`,
|
|
798
|
+
);
|
|
799
|
+
}
|
|
800
|
+
return new ArchiveReader(format, await readTarEntries(await file.bytes()));
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
const { bytes, format } = source;
|
|
804
|
+
if (format === "zip") {
|
|
805
|
+
return new ArchiveReader(format, await readZipEntries(memoryByteSource(bytes)));
|
|
806
|
+
}
|
|
807
|
+
if (bytes.byteLength > MAX_TAR_ARCHIVE_BYTES) {
|
|
808
|
+
throw new ToolError(
|
|
809
|
+
`Archive is too large to read in memory (${formatBytes(bytes.byteLength)} > ${formatBytes(MAX_TAR_ARCHIVE_BYTES)} limit)`,
|
|
810
|
+
);
|
|
811
|
+
}
|
|
812
|
+
return new ArchiveReader(format, await readTarEntries(bytes));
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
/** Render the top-level entries of an in-memory archive as one line each. */
|
|
816
|
+
export async function listArchiveRoot(
|
|
817
|
+
bytes: Uint8Array,
|
|
818
|
+
format: ArchiveFormat,
|
|
819
|
+
opts: { limit?: number } = {},
|
|
820
|
+
): Promise<string> {
|
|
821
|
+
const archive = await openArchive({ bytes, format });
|
|
822
|
+
const entries = archive.listDirectory("");
|
|
823
|
+
const limitedEntries = opts.limit !== undefined && opts.limit > 0 ? entries.slice(0, opts.limit) : entries;
|
|
824
|
+
const lines = formatArchiveEntryLines(limitedEntries);
|
|
825
|
+
return lines.length > 0 ? lines.join("\n") : "(empty archive directory)";
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
async function resolveArchiveBytes(source: ArchiveSource): Promise<{ bytes: Uint8Array; format: ArchiveFormat }> {
|
|
829
|
+
if (typeof source !== "string") return source;
|
|
830
|
+
const format = archiveFormatFromPath(source);
|
|
831
|
+
if (!format) {
|
|
832
|
+
throw new ToolError(`Unsupported archive format: ${source}`);
|
|
833
|
+
}
|
|
834
|
+
return { bytes: await Bun.file(source).bytes(), format };
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
async function memberToBytes(content: ArchiveMemberContent): Promise<Uint8Array> {
|
|
838
|
+
if (typeof content === "string") return ENCODER.encode(content);
|
|
839
|
+
if (content instanceof Uint8Array) return content;
|
|
840
|
+
return new Uint8Array(await content.arrayBuffer());
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
/**
|
|
844
|
+
* Fully materialize every file member into a `path → content` map: ZIP members
|
|
845
|
+
* are inflated in memory, tar members are returned as lazy `File`s. Use this
|
|
846
|
+
* when you need every entry (rewrite, extract); for browsing or single-member
|
|
847
|
+
* reads prefer `openArchive`, which is lazy for ZIP.
|
|
848
|
+
*/
|
|
849
|
+
export async function readArchiveEntries(source: ArchiveSource): Promise<Map<string, ArchiveMemberContent>> {
|
|
850
|
+
const { bytes, format } = await resolveArchiveBytes(source);
|
|
851
|
+
const entries = new Map<string, ArchiveMemberContent>();
|
|
852
|
+
if (format === "zip") {
|
|
853
|
+
const unzipped = unzip(bytes);
|
|
854
|
+
for (const name in unzipped) {
|
|
855
|
+
entries.set(name, unzipped[name]!);
|
|
856
|
+
}
|
|
857
|
+
return entries;
|
|
858
|
+
}
|
|
859
|
+
const files = await new Bun.Archive(bytes).files();
|
|
860
|
+
for (const [name, file] of files) {
|
|
861
|
+
entries.set(name.replace(/\\/g, "/"), file);
|
|
862
|
+
}
|
|
863
|
+
return entries;
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
/**
|
|
867
|
+
* Serialize `entries` into an archive of `format` and write it to `destPath`.
|
|
868
|
+
* ZIP is framed in memory, tar / tar.gz via `Bun.Archive` (gzip for tar.gz).
|
|
869
|
+
* String members are encoded as UTF-8.
|
|
870
|
+
*/
|
|
871
|
+
export async function writeArchive(
|
|
872
|
+
destPath: string,
|
|
873
|
+
format: ArchiveFormat,
|
|
874
|
+
entries: Iterable<readonly [string, ArchiveMemberContent]>,
|
|
875
|
+
): Promise<void> {
|
|
876
|
+
if (format === "zip") {
|
|
877
|
+
const record: Record<string, Uint8Array> = {};
|
|
878
|
+
for (const [name, content] of entries) {
|
|
879
|
+
record[name.replace(/\\/g, "/")] = await memberToBytes(content);
|
|
880
|
+
}
|
|
881
|
+
await Bun.write(destPath, zip(record));
|
|
882
|
+
return;
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
const record: Record<string, ArchiveMemberContent> = {};
|
|
886
|
+
for (const [name, content] of entries) {
|
|
887
|
+
record[name.replace(/\\/g, "/")] = content;
|
|
888
|
+
}
|
|
889
|
+
await Bun.Archive.write(destPath, record, format === "tar.gz" ? { compress: "gzip" } : undefined);
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
/**
|
|
893
|
+
* Extract every file member to `destDir`, creating parent directories as
|
|
894
|
+
* needed. Entries that would escape `destDir` (via `..` or an absolute path)
|
|
895
|
+
* are rejected. Returns the number of files written.
|
|
896
|
+
*/
|
|
897
|
+
export async function extractArchive(source: ArchiveSource, destDir: string): Promise<number> {
|
|
898
|
+
const extractRoot = path.resolve(destDir);
|
|
899
|
+
const entries = await readArchiveEntries(source);
|
|
900
|
+
let count = 0;
|
|
901
|
+
for (const [name, content] of entries) {
|
|
902
|
+
if (name.endsWith("/")) continue;
|
|
903
|
+
const outputPath = path.resolve(extractRoot, name);
|
|
904
|
+
if (!outputPath.startsWith(extractRoot + path.sep)) {
|
|
905
|
+
throw new ToolError(`Archive entry escapes extraction dir: ${name}`);
|
|
906
|
+
}
|
|
907
|
+
await Bun.write(outputPath, content);
|
|
908
|
+
count++;
|
|
909
|
+
}
|
|
910
|
+
return count;
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
function writeUInt16LE(buf: Uint8Array, offset: number, value: number): void {
|
|
914
|
+
buf[offset] = value & 0xff;
|
|
915
|
+
buf[offset + 1] = (value >>> 8) & 0xff;
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
function writeUInt32LE(buf: Uint8Array, offset: number, value: number): void {
|
|
919
|
+
buf[offset] = value & 0xff;
|
|
920
|
+
buf[offset + 1] = (value >>> 8) & 0xff;
|
|
921
|
+
buf[offset + 2] = (value >>> 16) & 0xff;
|
|
922
|
+
buf[offset + 3] = (value >>> 24) & 0xff;
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
/**
|
|
926
|
+
* Frame a `path → bytes` map into a ZIP archive in memory. Each member is raw
|
|
927
|
+
* DEFLATE unless that would not shrink it, in which case it is stored. ZIP64 is
|
|
928
|
+
* not emitted; archives beyond the 32-bit limits throw rather than corrupt.
|
|
929
|
+
*/
|
|
930
|
+
export function zip(entries: Unzipped): Uint8Array {
|
|
931
|
+
const localParts: Uint8Array[] = [];
|
|
932
|
+
const centralParts: Uint8Array[] = [];
|
|
933
|
+
let offset = 0;
|
|
934
|
+
let count = 0;
|
|
935
|
+
|
|
936
|
+
for (const name in entries) {
|
|
937
|
+
const data = entries[name]!;
|
|
938
|
+
const nameBytes = ENCODER.encode(name);
|
|
939
|
+
const crc = zlib.crc32(data) >>> 0;
|
|
940
|
+
const uncompressedSize = data.byteLength;
|
|
941
|
+
const deflated = zlib.deflateRawSync(data);
|
|
942
|
+
const stored = deflated.byteLength >= uncompressedSize;
|
|
943
|
+
const method = stored ? ZIP_STORED_COMPRESSION : ZIP_DEFLATE_COMPRESSION;
|
|
944
|
+
const payload = stored ? data : deflated;
|
|
945
|
+
|
|
946
|
+
// Without ZIP64 the name length is a u16 and offsets/sizes are u32 (with
|
|
947
|
+
// 0xffff/0xffffffff reserved as ZIP64 sentinels); reject anything that
|
|
948
|
+
// would silently wrap a header field instead of producing a valid archive.
|
|
949
|
+
if (
|
|
950
|
+
count + 1 >= ZIP_UINT16_MAX ||
|
|
951
|
+
nameBytes.byteLength > ZIP_UINT16_MAX ||
|
|
952
|
+
uncompressedSize >= ZIP_UINT32_MAX ||
|
|
953
|
+
offset + 30 + nameBytes.byteLength + payload.byteLength >= ZIP_UINT32_MAX
|
|
954
|
+
) {
|
|
955
|
+
throw new ToolError("ZIP archive is too large to write (ZIP64 is not supported)");
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
const header = new Uint8Array(30 + nameBytes.byteLength);
|
|
959
|
+
writeUInt32LE(header, 0, ZIP_LOCAL_FILE_HEADER_SIGNATURE);
|
|
960
|
+
writeUInt16LE(header, 4, 20);
|
|
961
|
+
writeUInt16LE(header, 6, ZIP_UTF8_FLAG);
|
|
962
|
+
writeUInt16LE(header, 8, method);
|
|
963
|
+
// Fixed 1980-01-01 timestamp keeps the output deterministic.
|
|
964
|
+
writeUInt16LE(header, 12, 0x21);
|
|
965
|
+
writeUInt32LE(header, 14, crc);
|
|
966
|
+
writeUInt32LE(header, 18, payload.byteLength);
|
|
967
|
+
writeUInt32LE(header, 22, uncompressedSize);
|
|
968
|
+
writeUInt16LE(header, 26, nameBytes.byteLength);
|
|
969
|
+
header.set(nameBytes, 30);
|
|
970
|
+
localParts.push(header, payload);
|
|
971
|
+
|
|
972
|
+
const record = new Uint8Array(46 + nameBytes.byteLength);
|
|
973
|
+
writeUInt32LE(record, 0, ZIP_CENTRAL_DIRECTORY_HEADER_SIGNATURE);
|
|
974
|
+
writeUInt16LE(record, 4, 20);
|
|
975
|
+
writeUInt16LE(record, 6, 20);
|
|
976
|
+
writeUInt16LE(record, 8, ZIP_UTF8_FLAG);
|
|
977
|
+
writeUInt16LE(record, 10, method);
|
|
978
|
+
writeUInt16LE(record, 14, 0x21);
|
|
979
|
+
writeUInt32LE(record, 16, crc);
|
|
980
|
+
writeUInt32LE(record, 20, payload.byteLength);
|
|
981
|
+
writeUInt32LE(record, 24, uncompressedSize);
|
|
982
|
+
writeUInt16LE(record, 28, nameBytes.byteLength);
|
|
983
|
+
writeUInt32LE(record, 42, offset);
|
|
984
|
+
record.set(nameBytes, 46);
|
|
985
|
+
centralParts.push(record);
|
|
986
|
+
|
|
987
|
+
offset += header.byteLength + payload.byteLength;
|
|
988
|
+
count++;
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
const centralSize = centralParts.reduce((sum, part) => sum + part.byteLength, 0);
|
|
992
|
+
if (centralSize >= ZIP_UINT32_MAX || offset + centralSize + ZIP_EOCD_MIN_LENGTH >= ZIP_UINT32_MAX) {
|
|
993
|
+
throw new ToolError("ZIP archive is too large to write (ZIP64 is not supported)");
|
|
994
|
+
}
|
|
995
|
+
const eocd = new Uint8Array(ZIP_EOCD_MIN_LENGTH);
|
|
996
|
+
writeUInt32LE(eocd, 0, ZIP_EOCD_SIGNATURE);
|
|
997
|
+
writeUInt16LE(eocd, 8, count);
|
|
998
|
+
writeUInt16LE(eocd, 10, count);
|
|
999
|
+
writeUInt32LE(eocd, 12, centralSize);
|
|
1000
|
+
writeUInt32LE(eocd, 16, offset);
|
|
1001
|
+
|
|
1002
|
+
const out = new Uint8Array(offset + centralSize + ZIP_EOCD_MIN_LENGTH);
|
|
1003
|
+
let pos = 0;
|
|
1004
|
+
for (const part of localParts) {
|
|
1005
|
+
out.set(part, pos);
|
|
1006
|
+
pos += part.byteLength;
|
|
1007
|
+
}
|
|
1008
|
+
for (const part of centralParts) {
|
|
1009
|
+
out.set(part, pos);
|
|
1010
|
+
pos += part.byteLength;
|
|
1011
|
+
}
|
|
1012
|
+
out.set(eocd, pos);
|
|
1013
|
+
return out;
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
function readZip64CentralDirectoryInfoSync(bytes: Uint8Array, eocdOffset: number): ZipCentralDirectoryInfo | undefined {
|
|
1017
|
+
const locatorOffset = eocdOffset - ZIP64_EOCD_LOCATOR_LENGTH;
|
|
1018
|
+
if (locatorOffset < 0) return undefined;
|
|
1019
|
+
|
|
1020
|
+
const locator = readMemoryRange(bytes, locatorOffset, locatorOffset + ZIP64_EOCD_LOCATOR_LENGTH);
|
|
1021
|
+
if (readUInt32LE(locator, 0) !== ZIP64_EOCD_LOCATOR_SIGNATURE) return undefined;
|
|
1022
|
+
if (readUInt32LE(locator, 4) !== 0 || readUInt32LE(locator, 16) > 1) {
|
|
1023
|
+
throw new ToolError("Multi-disk ZIP archives are not supported");
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
const zip64EocdOffset = readUInt64LEAsNumber(locator, 8);
|
|
1027
|
+
const record = readMemoryRange(bytes, zip64EocdOffset, zip64EocdOffset + 56);
|
|
1028
|
+
if (readUInt32LE(record, 0) !== ZIP64_EOCD_SIGNATURE) {
|
|
1029
|
+
throw new ToolError("Invalid ZIP archive: missing ZIP64 end of central directory");
|
|
1030
|
+
}
|
|
1031
|
+
if (readUInt32LE(record, 16) !== 0 || readUInt32LE(record, 20) !== 0) {
|
|
1032
|
+
throw new ToolError("Multi-disk ZIP archives are not supported");
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
return {
|
|
1036
|
+
entries: readUInt64LEAsNumber(record, 32),
|
|
1037
|
+
size: readUInt64LEAsNumber(record, 40),
|
|
1038
|
+
offset: readUInt64LEAsNumber(record, 48),
|
|
1039
|
+
};
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
function readCentralDirectoryInfoSync(bytes: Uint8Array): ZipCentralDirectoryInfo {
|
|
1043
|
+
const fileSize = bytes.byteLength;
|
|
1044
|
+
if (fileSize < ZIP_EOCD_MIN_LENGTH) {
|
|
1045
|
+
throw new ToolError("Invalid ZIP archive: missing end of central directory");
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
const tailLength = Math.min(fileSize, ZIP_EOCD_MIN_LENGTH + ZIP_EOCD_MAX_COMMENT_LENGTH);
|
|
1049
|
+
const tailStart = fileSize - tailLength;
|
|
1050
|
+
const tail = readMemoryRange(bytes, tailStart, fileSize);
|
|
1051
|
+
const eocdIndex = findEndOfCentralDirectory(tail);
|
|
1052
|
+
|
|
1053
|
+
if (readUInt16LE(tail, eocdIndex + 4) !== 0 || readUInt16LE(tail, eocdIndex + 6) !== 0) {
|
|
1054
|
+
throw new ToolError("Multi-disk ZIP archives are not supported");
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
let entries = readUInt16LE(tail, eocdIndex + 10);
|
|
1058
|
+
let size = readUInt32LE(tail, eocdIndex + 12);
|
|
1059
|
+
let offset = readUInt32LE(tail, eocdIndex + 16);
|
|
1060
|
+
const needsZip64 = entries === ZIP_UINT16_MAX || size === ZIP_UINT32_MAX || offset === ZIP_UINT32_MAX;
|
|
1061
|
+
const zip64Info = readZip64CentralDirectoryInfoSync(bytes, tailStart + eocdIndex);
|
|
1062
|
+
if (zip64Info) {
|
|
1063
|
+
({ entries, size, offset } = zip64Info);
|
|
1064
|
+
} else if (needsZip64) {
|
|
1065
|
+
throw new ToolError("Invalid ZIP archive: missing ZIP64 central directory metadata");
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
if (offset + size > fileSize) {
|
|
1069
|
+
throw new ToolError("Invalid ZIP archive: central directory exceeds file size");
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
return { entries, offset, size };
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
function extractZipMember(bytes: Uint8Array, storage: ZipStorage, uncompressedSize: number): Uint8Array {
|
|
1076
|
+
if ((storage.flags & ZIP_ENCRYPTED_FLAG) !== 0) {
|
|
1077
|
+
throw new ToolError("Encrypted ZIP entries are not supported");
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
const headerStart = storage.localHeaderOffset;
|
|
1081
|
+
const localHeader = readMemoryRange(bytes, headerStart, headerStart + 30);
|
|
1082
|
+
if (readUInt32LE(localHeader, 0) !== ZIP_LOCAL_FILE_HEADER_SIGNATURE) {
|
|
1083
|
+
throw new ToolError("Invalid ZIP archive: malformed local file header");
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
const fileNameLength = readUInt16LE(localHeader, 26);
|
|
1087
|
+
const extraLength = readUInt16LE(localHeader, 28);
|
|
1088
|
+
const dataStart = headerStart + 30 + fileNameLength + extraLength;
|
|
1089
|
+
const compressed = readMemoryRange(bytes, dataStart, dataStart + storage.compressedSize);
|
|
1090
|
+
return decodeZipMember(compressed, storage.compression, uncompressedSize);
|
|
1091
|
+
}
|