@oh-my-pi/pi-coding-agent 15.10.10 → 15.10.12
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 +142 -7
- package/dist/cli.js +23108 -0
- package/dist/tokenizers.linux-x64-gnu-xcjh3jwk.node +0 -0
- package/dist/types/async/job-manager.d.ts +18 -0
- package/dist/types/cli/args.d.ts +2 -1
- package/dist/types/cli/dry-balance-cli.d.ts +1 -1
- package/dist/types/cli/gallery-cli.d.ts +1 -1
- package/dist/types/cli/gallery-fixtures/types.d.ts +1 -1
- package/dist/types/cli/usage-cli.d.ts +72 -0
- package/dist/types/cli-commands.d.ts +12 -0
- package/dist/types/commands/launch.d.ts +5 -1
- package/dist/types/commands/read.d.ts +1 -1
- package/dist/types/commands/usage.d.ts +25 -0
- package/dist/types/config/api-key-resolver.d.ts +3 -0
- package/dist/types/config/append-only-context-mode.d.ts +2 -1
- package/dist/types/config/model-discovery.d.ts +55 -0
- package/dist/types/config/model-registry.d.ts +8 -219
- package/dist/types/config/model-resolver.d.ts +34 -10
- package/dist/types/config/model-roles.d.ts +28 -0
- package/dist/types/config/models-config-schema.d.ts +523 -42
- package/dist/types/config/models-config.d.ts +385 -0
- package/dist/types/config/settings-schema.d.ts +41 -8
- package/dist/types/config/settings.d.ts +8 -1
- package/dist/types/debug/log-viewer.d.ts +1 -1
- package/dist/types/debug/raw-sse.d.ts +1 -1
- package/dist/types/edit/hashline/noop-loop-guard.d.ts +72 -0
- package/dist/types/eval/backend.d.ts +0 -2
- package/dist/types/eval/idle-timeout.d.ts +0 -4
- package/dist/types/eval/js/shared/rewrite-imports.d.ts +6 -6
- package/dist/types/eval/py/executor.d.ts +5 -0
- package/dist/types/eval/py/kernel.d.ts +6 -1
- package/dist/types/eval/py/runtime.d.ts +9 -0
- package/dist/types/exec/bash-executor.d.ts +2 -0
- package/dist/types/export/html/template.generated.d.ts +1 -1
- package/dist/types/extensibility/extensions/runner.d.ts +3 -2
- package/dist/types/extensibility/extensions/types.d.ts +6 -3
- package/dist/types/hindsight/mental-models.d.ts +17 -8
- package/dist/types/internal-urls/artifact-protocol.d.ts +2 -2
- package/dist/types/internal-urls/types.d.ts +1 -1
- package/dist/types/lsp/edits.d.ts +9 -0
- package/dist/types/lsp/index.d.ts +2 -2
- package/dist/types/lsp/types.d.ts +2 -0
- package/dist/types/lsp/utils.d.ts +3 -0
- package/dist/types/mcp/json-rpc.d.ts +5 -0
- package/dist/types/memory-backend/index.d.ts +1 -0
- package/dist/types/memory-backend/runtime.d.ts +4 -0
- package/dist/types/memory-backend/types.d.ts +66 -1
- package/dist/types/mnemopi/state.d.ts +11 -1
- package/dist/types/modes/components/agent-dashboard.d.ts +1 -1
- package/dist/types/modes/components/assistant-message.d.ts +3 -1
- package/dist/types/modes/components/bash-execution.d.ts +1 -1
- package/dist/types/modes/components/copy-selector.d.ts +1 -1
- package/dist/types/modes/components/dynamic-border.d.ts +1 -1
- package/dist/types/modes/components/extensions/extension-dashboard.d.ts +1 -1
- package/dist/types/modes/components/extensions/extension-list.d.ts +1 -1
- package/dist/types/modes/components/extensions/inspector-panel.d.ts +1 -1
- package/dist/types/modes/components/footer.d.ts +1 -1
- package/dist/types/modes/components/hook-editor.d.ts +5 -0
- package/dist/types/modes/components/hook-input.d.ts +4 -0
- package/dist/types/modes/components/hook-selector.d.ts +1 -1
- package/dist/types/modes/components/model-selector.d.ts +1 -1
- package/dist/types/modes/components/plan-review-overlay.d.ts +1 -1
- package/dist/types/modes/components/session-observer-overlay.d.ts +1 -1
- package/dist/types/modes/components/session-selector.d.ts +1 -1
- package/dist/types/modes/components/status-line/component.d.ts +1 -1
- package/dist/types/modes/components/tiny-title-download-progress.d.ts +1 -1
- package/dist/types/modes/components/transcript-container.d.ts +25 -6
- package/dist/types/modes/components/tree-selector.d.ts +1 -1
- package/dist/types/modes/components/user-message-selector.d.ts +1 -1
- package/dist/types/modes/components/user-message.d.ts +2 -1
- package/dist/types/modes/components/visual-truncate.d.ts +1 -1
- package/dist/types/modes/components/welcome.d.ts +19 -3
- package/dist/types/modes/controllers/mcp-command-controller.d.ts +1 -1
- package/dist/types/modes/controllers/streaming-reveal.d.ts +1 -1
- package/dist/types/modes/index.d.ts +3 -3
- package/dist/types/modes/interactive-mode.d.ts +8 -3
- package/dist/types/modes/oauth-manual-input.d.ts +7 -0
- package/dist/types/modes/rpc/rpc-client.d.ts +39 -2
- package/dist/types/modes/rpc/rpc-mode.d.ts +31 -2
- package/dist/types/modes/rpc/rpc-subagents.d.ts +24 -0
- package/dist/types/modes/rpc/rpc-types.d.ts +75 -1
- package/dist/types/modes/setup-wizard/index.d.ts +5 -1
- package/dist/types/modes/setup-wizard/lazy.d.ts +2 -0
- package/dist/types/modes/setup-wizard/scenes/sign-in.d.ts +1 -1
- package/dist/types/modes/setup-wizard/scenes/types.d.ts +1 -1
- package/dist/types/modes/setup-wizard/scenes/web-search.d.ts +1 -1
- package/dist/types/modes/setup-wizard/wizard-overlay.d.ts +1 -1
- package/dist/types/modes/types.d.ts +4 -1
- package/dist/types/secrets/index.d.ts +1 -1
- package/dist/types/secrets/obfuscator.d.ts +8 -2
- package/dist/types/session/agent-session.d.ts +15 -3
- package/dist/types/session/auth-broker-config.d.ts +4 -0
- package/dist/types/session/session-manager.d.ts +1 -1
- package/dist/types/session/streaming-output.d.ts +23 -0
- package/dist/types/slash-commands/acp-builtins.d.ts +16 -0
- package/dist/types/slash-commands/builtin-registry.d.ts +1 -0
- package/dist/types/slash-commands/helpers/stats-dashboard.d.ts +13 -0
- package/dist/types/slash-commands/types.d.ts +1 -1
- package/dist/types/ssh/connection-manager.d.ts +8 -0
- package/dist/types/system-prompt.d.ts +2 -0
- package/dist/types/task/executor.d.ts +1 -0
- package/dist/types/task/index.d.ts +2 -2
- package/dist/types/task/parallel.d.ts +2 -2
- package/dist/types/task/types.d.ts +8 -0
- package/dist/types/task/worktree.d.ts +2 -0
- package/dist/types/thinking.d.ts +4 -0
- package/dist/types/tiny/title-client.d.ts +11 -0
- package/dist/types/tiny/title-protocol.d.ts +1 -0
- package/dist/types/tools/ask.d.ts +4 -0
- package/dist/types/tools/conflict-detect.d.ts +16 -0
- package/dist/types/tools/github-cache.d.ts +7 -0
- package/dist/types/tools/index.d.ts +6 -0
- package/dist/types/tools/sqlite-reader.d.ts +3 -0
- package/dist/types/tui/output-block.d.ts +3 -3
- package/dist/types/utils/changelog.d.ts +8 -0
- package/dist/types/utils/git.d.ts +15 -2
- package/dist/types/utils/title-generator.d.ts +3 -2
- package/dist/types/web/scrapers/readthedocs.d.ts +3 -0
- package/dist/types/web/scrapers/types.d.ts +12 -0
- package/dist/types/web/search/providers/codex.d.ts +1 -1
- package/dist/types/web/search/providers/gemini.d.ts +1 -1
- package/examples/extensions/tools.ts +5 -4
- package/package.json +14 -11
- package/scripts/build-binary.ts +18 -23
- package/scripts/bundle-dist.ts +81 -0
- package/scripts/{dev-launch → omp} +1 -1
- package/scripts/{dev-launch-preload.ts → omp.ts} +1 -1
- package/src/async/job-manager.ts +57 -3
- package/src/auto-thinking/classifier.ts +1 -0
- package/src/autoresearch/dashboard.ts +1 -1
- package/src/autoresearch/prompt-setup.md +6 -6
- package/src/autoresearch/prompt.md +6 -6
- package/src/capability/fs.ts +10 -0
- package/src/cli/args.ts +4 -1
- package/src/cli/auth-gateway-cli.ts +1 -3
- package/src/cli/dry-balance-cli.ts +1 -1
- package/src/cli/gallery-cli.ts +1 -1
- package/src/cli/gallery-fixtures/fs.ts +1 -1
- package/src/cli/gallery-fixtures/types.ts +5 -1
- package/src/cli/list-models.ts +2 -1
- package/src/cli/usage-cli.ts +603 -0
- package/src/cli-commands.ts +30 -0
- package/src/cli.ts +76 -13
- package/src/commands/complete.ts +1 -1
- package/src/commands/launch.ts +5 -1
- package/src/commands/read.ts +6 -3
- package/src/commands/usage.ts +35 -0
- package/src/commit/agentic/agent.ts +1 -1
- package/src/commit/model-selection.ts +4 -3
- package/src/config/api-key-resolver.ts +8 -6
- package/src/config/append-only-context-mode.ts +6 -12
- package/src/config/model-discovery.ts +554 -0
- package/src/config/model-registry.ts +320 -1041
- package/src/config/model-resolver.ts +173 -156
- package/src/config/model-roles.ts +74 -0
- package/src/config/models-config-schema.ts +57 -8
- package/src/config/models-config.ts +129 -0
- package/src/config/settings-schema.ts +61 -19
- package/src/config/settings.ts +98 -4
- package/src/dap/client.ts +124 -37
- package/src/dap/session.ts +259 -158
- package/src/debug/log-viewer.ts +1 -1
- package/src/debug/raw-sse.ts +1 -1
- package/src/edit/diff.ts +47 -3
- package/src/edit/hashline/block-resolver.ts +20 -1
- package/src/edit/hashline/diff.ts +36 -1
- package/src/edit/hashline/execute.ts +47 -4
- package/src/edit/hashline/noop-loop-guard.ts +99 -0
- package/src/edit/index.ts +16 -1
- package/src/edit/modes/patch.ts +52 -0
- package/src/edit/modes/replace.ts +56 -22
- package/src/edit/notebook.ts +22 -2
- package/src/edit/renderer.ts +36 -10
- package/src/eval/__tests__/completion-bridge.test.ts +1 -1
- package/src/eval/backend.ts +0 -2
- package/src/eval/completion-bridge.ts +3 -1
- package/src/eval/idle-timeout.ts +2 -9
- package/src/eval/js/context-manager.ts +6 -8
- package/src/eval/js/executor.ts +6 -2
- package/src/eval/js/index.ts +0 -2
- package/src/eval/js/shared/helpers.ts +5 -6
- package/src/eval/js/shared/local-module-loader.ts +1 -1
- package/src/eval/js/shared/prelude.txt +62 -1
- package/src/eval/js/shared/rewrite-imports.ts +40 -22
- package/src/eval/js/shared/runtime.ts +1 -1
- package/src/eval/py/executor.ts +29 -7
- package/src/eval/py/index.ts +6 -3
- package/src/eval/py/kernel.ts +43 -4
- package/src/eval/py/runner.py +107 -3
- package/src/eval/py/runtime.ts +37 -0
- package/src/exec/bash-executor.ts +85 -4
- package/src/export/html/template.generated.ts +1 -1
- package/src/export/html/template.js +3 -1
- package/src/extensibility/extensions/get-commands-handler.ts +2 -1
- package/src/extensibility/extensions/runner.ts +6 -1
- package/src/extensibility/extensions/types.ts +6 -2
- package/src/extensibility/plugins/legacy-pi-compat.ts +20 -3
- package/src/hindsight/bank.ts +17 -2
- package/src/hindsight/mental-models.ts +59 -12
- package/src/hindsight/state.ts +6 -1
- package/src/internal-urls/artifact-protocol.ts +11 -2
- package/src/internal-urls/docs-index.generated.ts +11 -11
- package/src/internal-urls/issue-pr-protocol.ts +12 -5
- package/src/internal-urls/router.ts +1 -1
- package/src/internal-urls/types.ts +1 -1
- package/src/lib/xai-http.ts +1 -1
- package/src/lsp/client.ts +118 -38
- package/src/lsp/clients/biome-client.ts +101 -39
- package/src/lsp/edits.ts +143 -95
- package/src/lsp/index.ts +31 -22
- package/src/lsp/render.ts +1 -1
- package/src/lsp/types.ts +2 -0
- package/src/lsp/utils.ts +28 -10
- package/src/main.ts +183 -23
- package/src/mcp/json-rpc.ts +35 -5
- package/src/mcp/transports/stdio.ts +7 -1
- package/src/memories/index.ts +4 -1
- package/src/memory-backend/index.ts +1 -0
- package/src/memory-backend/local-backend.ts +9 -0
- package/src/memory-backend/off-backend.ts +9 -0
- package/src/memory-backend/runtime.ts +66 -0
- package/src/memory-backend/types.ts +81 -1
- package/src/mnemopi/backend.ts +176 -7
- package/src/mnemopi/state.ts +38 -2
- package/src/modes/acp/acp-agent.ts +119 -11
- package/src/modes/components/agent-dashboard.ts +10 -7
- package/src/modes/components/assistant-message.ts +32 -28
- package/src/modes/components/bash-execution.ts +1 -1
- package/src/modes/components/copy-selector.ts +1 -1
- package/src/modes/components/diff.ts +13 -2
- package/src/modes/components/dynamic-border.ts +12 -3
- package/src/modes/components/extensions/extension-dashboard.ts +8 -5
- package/src/modes/components/extensions/extension-list.ts +1 -1
- package/src/modes/components/extensions/inspector-panel.ts +1 -1
- package/src/modes/components/footer.ts +4 -2
- package/src/modes/components/history-search.ts +1 -1
- package/src/modes/components/hook-editor.ts +8 -0
- package/src/modes/components/hook-input.ts +8 -0
- package/src/modes/components/hook-selector.ts +2 -2
- package/src/modes/components/model-selector.ts +4 -2
- package/src/modes/components/plan-review-overlay.ts +1 -1
- package/src/modes/components/session-observer-overlay.ts +2 -2
- package/src/modes/components/session-selector.ts +1 -1
- package/src/modes/components/settings-selector.ts +5 -1
- package/src/modes/components/status-line/component.ts +119 -35
- package/src/modes/components/tiny-title-download-progress.ts +1 -1
- package/src/modes/components/transcript-container.ts +258 -53
- package/src/modes/components/tree-selector.ts +3 -3
- package/src/modes/components/user-message-selector.ts +1 -1
- package/src/modes/components/user-message.ts +17 -5
- package/src/modes/components/visual-truncate.ts +1 -1
- package/src/modes/components/welcome.ts +108 -26
- package/src/modes/controllers/command-controller.ts +11 -4
- package/src/modes/controllers/event-controller.ts +73 -4
- package/src/modes/controllers/input-controller.ts +2 -1
- package/src/modes/controllers/mcp-command-controller.ts +39 -4
- package/src/modes/controllers/selector-controller.ts +1 -1
- package/src/modes/controllers/streaming-reveal.ts +85 -18
- package/src/modes/index.ts +3 -21
- package/src/modes/interactive-mode.ts +42 -18
- package/src/modes/oauth-manual-input.ts +30 -3
- package/src/modes/rpc/rpc-client.ts +154 -3
- package/src/modes/rpc/rpc-mode.ts +97 -12
- package/src/modes/rpc/rpc-subagents.ts +265 -0
- package/src/modes/rpc/rpc-types.ts +81 -1
- package/src/modes/setup-wizard/index.ts +12 -2
- package/src/modes/setup-wizard/lazy.ts +16 -0
- package/src/modes/setup-wizard/scenes/glyph.ts +1 -1
- package/src/modes/setup-wizard/scenes/providers.ts +1 -1
- package/src/modes/setup-wizard/scenes/sign-in.ts +1 -1
- package/src/modes/setup-wizard/scenes/theme.ts +1 -1
- package/src/modes/setup-wizard/scenes/types.ts +1 -1
- package/src/modes/setup-wizard/scenes/web-search.ts +1 -1
- package/src/modes/setup-wizard/wizard-overlay.ts +1 -1
- package/src/modes/types.ts +4 -1
- package/src/prompts/agents/explore.md +2 -2
- package/src/prompts/agents/librarian.md +1 -2
- package/src/prompts/agents/oracle.md +1 -1
- package/src/prompts/agents/plan.md +5 -5
- package/src/prompts/agents/task.md +5 -5
- package/src/prompts/ci-green-request.md +5 -7
- package/src/prompts/goals/goal-budget-limit.md +2 -2
- package/src/prompts/goals/goal-continuation.md +4 -4
- package/src/prompts/goals/goal-mode-active.md +1 -1
- package/src/prompts/memories/read-path.md +1 -1
- package/src/prompts/memories/stage_one_system.md +2 -2
- package/src/prompts/review-custom-request.md +1 -1
- package/src/prompts/system/agent-creation-architect.md +2 -2
- package/src/prompts/system/auto-continue.md +1 -1
- package/src/prompts/system/background-tan-dispatch.md +1 -1
- package/src/prompts/system/btw-user.md +2 -2
- package/src/prompts/system/commit-message-system.md +13 -1
- package/src/prompts/system/custom-system-prompt.md +1 -1
- package/src/prompts/system/eager-todo.md +2 -2
- package/src/prompts/system/irc-incoming.md +1 -1
- package/src/prompts/system/manual-continue.md +1 -1
- package/src/prompts/system/omfg-user.md +3 -4
- package/src/prompts/system/orchestrate-notice.md +9 -9
- package/src/prompts/system/plan-mode-active.md +4 -4
- package/src/prompts/system/plan-mode-subagent.md +4 -5
- package/src/prompts/system/plan-mode-tool-decision-reminder.md +1 -1
- package/src/prompts/system/project-prompt.md +2 -2
- package/src/prompts/system/subagent-system-prompt.md +4 -4
- package/src/prompts/system/system-prompt.md +13 -24
- package/src/prompts/system/title-system.md +2 -2
- package/src/prompts/system/ttsr-tool-reminder.md +1 -1
- package/src/prompts/system/workflow-notice.md +1 -1
- package/src/prompts/tools/ast-edit.md +1 -1
- package/src/prompts/tools/ast-grep.md +2 -2
- package/src/prompts/tools/bash.md +5 -7
- package/src/prompts/tools/browser.md +7 -7
- package/src/prompts/tools/debug.md +1 -1
- package/src/prompts/tools/eval.md +3 -3
- package/src/prompts/tools/find.md +0 -1
- package/src/prompts/tools/github.md +8 -7
- package/src/prompts/tools/goal.md +1 -1
- package/src/prompts/tools/image-gen.md +1 -1
- package/src/prompts/tools/inspect-image-system.md +1 -1
- package/src/prompts/tools/irc.md +15 -15
- package/src/prompts/tools/lsp.md +2 -2
- package/src/prompts/tools/patch.md +2 -2
- package/src/prompts/tools/read.md +3 -4
- package/src/prompts/tools/recall.md +1 -1
- package/src/prompts/tools/reflect.md +1 -1
- package/src/prompts/tools/render-mermaid.md +2 -2
- package/src/prompts/tools/replace.md +4 -10
- package/src/prompts/tools/rewind.md +2 -2
- package/src/prompts/tools/search-tool-bm25.md +1 -9
- package/src/prompts/tools/search.md +0 -1
- package/src/prompts/tools/ssh.md +0 -4
- package/src/prompts/tools/task.md +2 -3
- package/src/prompts/tools/todo.md +1 -1
- package/src/sdk.ts +31 -11
- package/src/secrets/index.ts +8 -1
- package/src/secrets/obfuscator.ts +39 -18
- package/src/session/agent-session.ts +223 -64
- package/src/session/auth-broker-config.ts +30 -1
- package/src/session/session-manager.ts +2 -2
- package/src/session/streaming-output.ts +188 -11
- package/src/slash-commands/acp-builtins.ts +24 -0
- package/src/slash-commands/builtin-registry.ts +40 -0
- package/src/slash-commands/helpers/stats-dashboard.ts +85 -0
- package/src/slash-commands/types.ts +1 -1
- package/src/ssh/connection-manager.ts +27 -0
- package/src/system-prompt.ts +14 -0
- package/src/task/commands.ts +2 -1
- package/src/task/executor.ts +74 -65
- package/src/task/index.ts +146 -68
- package/src/task/parallel.ts +3 -3
- package/src/task/render.ts +20 -5
- package/src/task/types.ts +9 -0
- package/src/task/worktree.ts +64 -56
- package/src/thinking.ts +9 -1
- package/src/tiny/title-client.ts +60 -16
- package/src/tiny/title-protocol.ts +1 -1
- package/src/tiny/worker.ts +6 -4
- package/src/tools/archive-reader.ts +30 -2
- package/src/tools/ask.ts +104 -21
- package/src/tools/ast-edit.ts +25 -5
- package/src/tools/auto-generated-guard.ts +20 -3
- package/src/tools/bash-interactive.ts +27 -7
- package/src/tools/bash.ts +100 -18
- package/src/tools/browser/launch.ts +11 -2
- package/src/tools/browser/readable.ts +19 -2
- package/src/tools/browser/registry.ts +4 -1
- package/src/tools/browser/render.ts +2 -2
- package/src/tools/browser/tab-supervisor.ts +55 -16
- package/src/tools/conflict-detect.ts +50 -4
- package/src/tools/debug.ts +1 -1
- package/src/tools/eval-render.ts +5 -5
- package/src/tools/eval.ts +0 -2
- package/src/tools/fetch.ts +33 -10
- package/src/tools/gh-cache-invalidation.ts +63 -8
- package/src/tools/gh-renderer.ts +1 -1
- package/src/tools/gh.ts +172 -29
- package/src/tools/github-cache.ts +70 -6
- package/src/tools/image-gen.ts +14 -13
- package/src/tools/index.ts +13 -1
- package/src/tools/inspect-image.ts +1 -0
- package/src/tools/irc.ts +5 -1
- package/src/tools/job.ts +1 -1
- package/src/tools/read.ts +202 -61
- package/src/tools/render-utils.ts +3 -3
- package/src/tools/resolve.ts +1 -1
- package/src/tools/search.ts +92 -29
- package/src/tools/sqlite-reader.ts +17 -5
- package/src/tools/ssh.ts +8 -8
- package/src/tools/todo.ts +38 -8
- package/src/tools/write.ts +118 -18
- package/src/tui/output-block.ts +4 -4
- package/src/utils/changelog.ts +27 -1
- package/src/utils/commit-message-generator.ts +1 -0
- package/src/utils/file-mentions.ts +2 -1
- package/src/utils/git.ts +267 -13
- package/src/utils/title-generator.ts +24 -5
- package/src/web/scrapers/arxiv.ts +1 -1
- package/src/web/scrapers/go-pkg.ts +1 -1
- package/src/web/scrapers/iacr.ts +1 -1
- package/src/web/scrapers/readthedocs.ts +1 -1
- package/src/web/scrapers/twitter.ts +2 -1
- package/src/web/scrapers/types.ts +87 -8
- package/src/web/scrapers/wikipedia.ts +1 -1
- package/src/web/scrapers/youtube.ts +6 -1
- package/src/web/search/index.ts +1 -1
- package/src/web/search/providers/codex.ts +2 -1
- package/src/web/search/providers/gemini.ts +2 -3
- package/src/web/search/render.ts +8 -6
- package/dist/types/config/model-equivalence.d.ts +0 -24
- package/dist/types/config/model-id-affixes.d.ts +0 -12
- package/dist/types/config/model-provider-priority.d.ts +0 -1
- package/dist/types/exec/idle-timeout-watchdog.d.ts +0 -18
- package/src/config/model-equivalence.ts +0 -875
- package/src/config/model-id-affixes.ts +0 -81
- package/src/config/model-provider-priority.ts +0 -56
- package/src/exec/idle-timeout-watchdog.ts +0 -126
package/src/task/types.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
|
|
|
2
2
|
import type { Usage } from "@oh-my-pi/pi-ai";
|
|
3
3
|
import { $env } from "@oh-my-pi/pi-utils";
|
|
4
4
|
import * as z from "zod/v4";
|
|
5
|
+
import type { AgentSessionEvent } from "../session/agent-session";
|
|
5
6
|
import { getTaskSimpleModeCapabilities, type TaskSimpleMode } from "./simple-mode";
|
|
6
7
|
import type { NestedRepoPatch } from "./worktree";
|
|
7
8
|
|
|
@@ -41,11 +42,18 @@ export interface SubagentProgressPayload {
|
|
|
41
42
|
agent: string;
|
|
42
43
|
agentSource: AgentSource;
|
|
43
44
|
task: string;
|
|
45
|
+
parentToolCallId?: string;
|
|
44
46
|
assignment?: string;
|
|
45
47
|
progress: AgentProgress;
|
|
46
48
|
sessionFile?: string;
|
|
47
49
|
}
|
|
48
50
|
|
|
51
|
+
/** Payload emitted on TASK_SUBAGENT_EVENT_CHANNEL */
|
|
52
|
+
export interface SubagentEventPayload {
|
|
53
|
+
id: string;
|
|
54
|
+
event: AgentSessionEvent;
|
|
55
|
+
}
|
|
56
|
+
|
|
49
57
|
/** Payload emitted on TASK_SUBAGENT_LIFECYCLE_CHANNEL */
|
|
50
58
|
export interface SubagentLifecyclePayload {
|
|
51
59
|
id: string;
|
|
@@ -54,6 +62,7 @@ export interface SubagentLifecyclePayload {
|
|
|
54
62
|
description?: string;
|
|
55
63
|
status: "started" | "completed" | "failed" | "aborted";
|
|
56
64
|
sessionFile?: string;
|
|
65
|
+
parentToolCallId?: string;
|
|
57
66
|
index: number;
|
|
58
67
|
}
|
|
59
68
|
|
package/src/task/worktree.ts
CHANGED
|
@@ -5,6 +5,7 @@ import * as path from "node:path";
|
|
|
5
5
|
import * as natives from "@oh-my-pi/pi-natives";
|
|
6
6
|
import { getWorktreeDir, hashPath, logger, Snowflake } from "@oh-my-pi/pi-utils";
|
|
7
7
|
import * as git from "../utils/git";
|
|
8
|
+
import { mapWithConcurrencyLimit } from "./parallel";
|
|
8
9
|
|
|
9
10
|
const { IsoBackendKind } = natives;
|
|
10
11
|
type IsoBackendKind = natives.IsoBackendKind;
|
|
@@ -82,16 +83,16 @@ async function discoverNestedRepos(repoRoot: string): Promise<string[]> {
|
|
|
82
83
|
async function captureUntrackedPatch(repoRoot: string, untracked: readonly string[]): Promise<string> {
|
|
83
84
|
if (untracked.length === 0) return "";
|
|
84
85
|
const nullPath = getGitNoIndexNullPath();
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
),
|
|
86
|
+
// Bound concurrent git spawns; large untracked sets would otherwise fork one
|
|
87
|
+
// process per file at once.
|
|
88
|
+
const { results: untrackedDiffs } = await mapWithConcurrencyLimit([...untracked], 8, entry =>
|
|
89
|
+
git.diff(repoRoot, {
|
|
90
|
+
allowFailure: true,
|
|
91
|
+
binary: true,
|
|
92
|
+
noIndex: { left: nullPath, right: entry },
|
|
93
|
+
}),
|
|
93
94
|
);
|
|
94
|
-
return untrackedDiffs.filter(diff => diff
|
|
95
|
+
return untrackedDiffs.filter((diff): diff is string => !!diff?.trim()).join("\n");
|
|
95
96
|
}
|
|
96
97
|
|
|
97
98
|
async function captureRepoBaseline(repoRoot: string): Promise<RepoBaseline> {
|
|
@@ -427,6 +428,8 @@ export interface MergeBranchResult {
|
|
|
427
428
|
merged: string[];
|
|
428
429
|
failed: string[];
|
|
429
430
|
conflict?: string;
|
|
431
|
+
/** Set when cherry-picks landed on HEAD but restoring the stashed working tree failed. */
|
|
432
|
+
stashConflict?: string;
|
|
430
433
|
}
|
|
431
434
|
|
|
432
435
|
/**
|
|
@@ -438,64 +441,69 @@ export async function mergeTaskBranches(
|
|
|
438
441
|
repoRoot: string,
|
|
439
442
|
branches: Array<{ branchName: string; taskId: string; description?: string }>,
|
|
440
443
|
): Promise<MergeBranchResult> {
|
|
441
|
-
|
|
442
|
-
|
|
444
|
+
// Serialize against other in-process git mutations on this repo: concurrent
|
|
445
|
+
// background merges interleaving stash push/pop + cherry-pick would corrupt
|
|
446
|
+
// the working tree (lost uncommitted changes, mixed-up stash entries).
|
|
447
|
+
return git.withRepoLock(repoRoot, async () => {
|
|
448
|
+
const merged: string[] = [];
|
|
449
|
+
const failed: string[] = [];
|
|
443
450
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
451
|
+
// Stash dirty working tree so cherry-pick can operate on a clean HEAD.
|
|
452
|
+
// Without this, cherry-pick refuses to run when uncommitted changes exist.
|
|
453
|
+
const didStash = await git.stash.push(repoRoot, "omp-task-merge");
|
|
447
454
|
|
|
448
|
-
|
|
455
|
+
let conflictResult: MergeBranchResult | undefined;
|
|
449
456
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
try {
|
|
453
|
-
await git.cherryPick(repoRoot, branchName);
|
|
454
|
-
} catch (err) {
|
|
457
|
+
try {
|
|
458
|
+
for (const { branchName } of branches) {
|
|
455
459
|
try {
|
|
456
|
-
await git.cherryPick
|
|
457
|
-
} catch {
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
failed
|
|
470
|
-
conflict: `${branchName}: ${stderr}`,
|
|
471
|
-
};
|
|
472
|
-
break;
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
merged.push(branchName);
|
|
476
|
-
}
|
|
477
|
-
} finally {
|
|
478
|
-
if (didStash) {
|
|
479
|
-
try {
|
|
480
|
-
await git.stash.pop(repoRoot, { index: true });
|
|
481
|
-
} catch {
|
|
482
|
-
// Stash-pop conflicts mean the replayed changes clash with the user's
|
|
483
|
-
// uncommitted edits. Treat this as a merge failure so the caller preserves
|
|
484
|
-
// recovery branches instead of reporting success and deleting them.
|
|
485
|
-
logger.warn("Failed to restore stashed changes after task merge; stash entry preserved");
|
|
486
|
-
if (!conflictResult) {
|
|
460
|
+
await git.cherryPick(repoRoot, branchName);
|
|
461
|
+
} catch (err) {
|
|
462
|
+
try {
|
|
463
|
+
await git.cherryPick.abort(repoRoot);
|
|
464
|
+
} catch {
|
|
465
|
+
/* no state to abort */
|
|
466
|
+
}
|
|
467
|
+
const stderr =
|
|
468
|
+
err instanceof git.GitCommandError
|
|
469
|
+
? err.result.stderr.trim()
|
|
470
|
+
: err instanceof Error
|
|
471
|
+
? err.message
|
|
472
|
+
: String(err);
|
|
473
|
+
failed.push(branchName);
|
|
487
474
|
conflictResult = {
|
|
488
475
|
merged,
|
|
489
|
-
failed: merged,
|
|
490
|
-
conflict:
|
|
491
|
-
"stash pop: cherry-picked changes conflict with uncommitted edits. Run `git stash pop` and resolve manually.",
|
|
476
|
+
failed: [...failed, ...branches.slice(merged.length + failed.length).map(b => b.branchName)],
|
|
477
|
+
conflict: `${branchName}: ${stderr}`,
|
|
492
478
|
};
|
|
479
|
+
break;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
merged.push(branchName);
|
|
483
|
+
}
|
|
484
|
+
} finally {
|
|
485
|
+
if (didStash) {
|
|
486
|
+
try {
|
|
487
|
+
await git.stash.pop(repoRoot, { index: true });
|
|
488
|
+
} catch {
|
|
489
|
+
// Stash-pop conflicts mean the replayed changes clash with the user's
|
|
490
|
+
// uncommitted edits. The cherry-picked commits are already on HEAD, so
|
|
491
|
+
// the merged branches DID land — report them as merged and surface the
|
|
492
|
+
// stash conflict separately instead of claiming they are unmerged.
|
|
493
|
+
logger.warn("Failed to restore stashed changes after task merge; stash entry preserved");
|
|
494
|
+
const stashConflict =
|
|
495
|
+
"stash pop: cherry-picked changes conflict with uncommitted edits. The merged commits are on HEAD; run `git stash pop` and resolve manually.";
|
|
496
|
+
if (conflictResult) {
|
|
497
|
+
conflictResult.stashConflict = stashConflict;
|
|
498
|
+
} else {
|
|
499
|
+
conflictResult = { merged, failed: [], stashConflict };
|
|
500
|
+
}
|
|
493
501
|
}
|
|
494
502
|
}
|
|
495
503
|
}
|
|
496
|
-
}
|
|
497
504
|
|
|
498
|
-
|
|
505
|
+
return conflictResult ?? { merged, failed };
|
|
506
|
+
});
|
|
499
507
|
}
|
|
500
508
|
|
|
501
509
|
/** Clean up temporary task branches. */
|
package/src/thinking.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type ResolvedThinkingLevel, ThinkingLevel } from "@oh-my-pi/pi-agent-core";
|
|
2
|
-
import {
|
|
2
|
+
import { Effort, type Model, THINKING_EFFORTS } from "@oh-my-pi/pi-ai";
|
|
3
|
+
import { clampThinkingLevelForModel, getSupportedEfforts } from "@oh-my-pi/pi-catalog/model-thinking";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Metadata used to render thinking selector values in the coding-agent UI.
|
|
@@ -70,6 +71,13 @@ export function toReasoningEffort(level: ThinkingLevel | undefined): Effort | un
|
|
|
70
71
|
return level;
|
|
71
72
|
}
|
|
72
73
|
|
|
74
|
+
/**
|
|
75
|
+
* True when a selector explicitly requests provider-side reasoning disablement.
|
|
76
|
+
*/
|
|
77
|
+
export function shouldDisableReasoning(level: ThinkingLevel | undefined): boolean {
|
|
78
|
+
return level === ThinkingLevel.Off;
|
|
79
|
+
}
|
|
80
|
+
|
|
73
81
|
/**
|
|
74
82
|
* Resolves a selector against the current model while preserving explicit "off".
|
|
75
83
|
*/
|
package/src/tiny/title-client.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as path from "node:path";
|
|
2
|
-
import { $env, isCompiledBinary, logger } from "@oh-my-pi/pi-utils";
|
|
2
|
+
import { $env, isBunTestRuntime, isCompiledBinary, logger, workerHostEntry } from "@oh-my-pi/pi-utils";
|
|
3
3
|
import type { Subprocess } from "bun";
|
|
4
4
|
import { settings } from "../config/settings";
|
|
5
5
|
import { tinyModelDeviceSettingToEnv } from "./device";
|
|
@@ -39,6 +39,17 @@ export interface TinyTitleDownloadOptions {
|
|
|
39
39
|
onProgress?: (event: TinyTitleProgressEvent) => void;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Per-request controls for {@link TinyTitleClient.generate}.
|
|
44
|
+
*
|
|
45
|
+
* Carries the optional abort signal and title-system-prompt override used by
|
|
46
|
+
* callers that customize automatic session-title generation.
|
|
47
|
+
*/
|
|
48
|
+
export interface TinyTitleGenerateOptions {
|
|
49
|
+
signal?: AbortSignal;
|
|
50
|
+
systemPrompt?: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
42
53
|
// Cold-starting the worker subprocess from a compiled binary (decompress + module
|
|
43
54
|
// graph load) is slow on contended CI runners — the macos-15-intel release smoke
|
|
44
55
|
// blew past 5s while arm64/linux/win passed. The probe only needs to prove the
|
|
@@ -46,6 +57,14 @@ export interface TinyTitleDownloadOptions {
|
|
|
46
57
|
// generous bound removes the flake without weakening the check.
|
|
47
58
|
const SMOKE_TEST_TIMEOUT_MS = 30_000;
|
|
48
59
|
|
|
60
|
+
function normalizeTinyTitleGenerateOptions(
|
|
61
|
+
options: AbortSignal | TinyTitleGenerateOptions | undefined,
|
|
62
|
+
): TinyTitleGenerateOptions {
|
|
63
|
+
if (!options) return {};
|
|
64
|
+
if ("aborted" in options && "addEventListener" in options) return { signal: options };
|
|
65
|
+
return options;
|
|
66
|
+
}
|
|
67
|
+
|
|
49
68
|
/**
|
|
50
69
|
* Hidden subcommand on the main CLI that boots the tiny-model worker in the
|
|
51
70
|
* spawned subprocess. Kept in sync with the dispatch in `cli.ts`.
|
|
@@ -108,17 +127,28 @@ function tinyWorkerEnv(): Record<string, string> {
|
|
|
108
127
|
for (const key in overlay) merged[key] = overlay[key];
|
|
109
128
|
return merged;
|
|
110
129
|
}
|
|
130
|
+
interface TinyWorkerSpawnCommand {
|
|
131
|
+
cmd: string[];
|
|
132
|
+
cwd?: string;
|
|
133
|
+
}
|
|
111
134
|
|
|
112
135
|
/**
|
|
113
|
-
* Resolve the
|
|
114
|
-
* compiled binary the entry point is the binary itself
|
|
115
|
-
*
|
|
116
|
-
*
|
|
136
|
+
* Resolve the command used to relaunch the agent CLI into tiny-worker mode.
|
|
137
|
+
* In a compiled binary the entry point is the binary itself (no script arg).
|
|
138
|
+
* Otherwise re-enter the declared worker-host entry (source cli.ts or
|
|
139
|
+
* npm-bundle cli.js) with a cwd-relative script path — Bun's subprocess IPC
|
|
140
|
+
* is more reliable that way than with an absolute `.ts` entry under
|
|
141
|
+
* `bun test` — and fall back to this package's own `src/cli.ts` when no host
|
|
142
|
+
* entry is declared (bun test, SDK embedding).
|
|
117
143
|
*/
|
|
118
|
-
function tinyWorkerSpawnCmd():
|
|
119
|
-
if (isCompiledBinary()) return [process.execPath, TINY_WORKER_ARG];
|
|
120
|
-
const
|
|
121
|
-
|
|
144
|
+
function tinyWorkerSpawnCmd(): TinyWorkerSpawnCommand {
|
|
145
|
+
if (isCompiledBinary()) return { cmd: [process.execPath, TINY_WORKER_ARG] };
|
|
146
|
+
const hostEntry = workerHostEntry();
|
|
147
|
+
if (hostEntry) {
|
|
148
|
+
return { cmd: [process.execPath, path.basename(hostEntry), TINY_WORKER_ARG], cwd: path.dirname(hostEntry) };
|
|
149
|
+
}
|
|
150
|
+
const packageRoot = path.resolve(import.meta.dir, "..", "..");
|
|
151
|
+
return { cmd: [process.execPath, "src/cli.ts", TINY_WORKER_ARG], cwd: packageRoot };
|
|
122
152
|
}
|
|
123
153
|
|
|
124
154
|
interface SpawnedSubprocess {
|
|
@@ -143,8 +173,10 @@ export function createTinyTitleSubprocess(): SpawnedSubprocess {
|
|
|
143
173
|
const inbound = new Set<(message: TinyTitleWorkerOutbound) => void>();
|
|
144
174
|
const errors = new Set<(error: Error) => void>();
|
|
145
175
|
const intentionalExit = { value: false };
|
|
176
|
+
const spawnCommand = tinyWorkerSpawnCmd();
|
|
146
177
|
const proc = Bun.spawn({
|
|
147
|
-
cmd:
|
|
178
|
+
cmd: spawnCommand.cmd,
|
|
179
|
+
cwd: spawnCommand.cwd,
|
|
148
180
|
env: tinyWorkerEnv(),
|
|
149
181
|
stdin: "ignore",
|
|
150
182
|
stdout: "ignore",
|
|
@@ -175,7 +207,9 @@ export function createTinyTitleSubprocess(): SpawnedSubprocess {
|
|
|
175
207
|
});
|
|
176
208
|
// Don't keep the parent event loop alive on account of an idle worker; the
|
|
177
209
|
// agent dispose path calls `terminate()` explicitly when shutting down.
|
|
178
|
-
|
|
210
|
+
// Bun's test runner can starve IPC delivery for unref'd subprocesses, so
|
|
211
|
+
// keep it referenced only under tests that assert the ping/pong contract.
|
|
212
|
+
if (!isBunTestRuntime()) proc.unref();
|
|
179
213
|
return { proc, inbound, errors, intentionalExit };
|
|
180
214
|
}
|
|
181
215
|
|
|
@@ -280,9 +314,16 @@ export class TinyTitleClient {
|
|
|
280
314
|
return () => this.#progressListeners.delete(listener);
|
|
281
315
|
}
|
|
282
316
|
|
|
283
|
-
async generate(modelKey: string, message: string, signal?: AbortSignal): Promise<string | null
|
|
317
|
+
async generate(modelKey: string, message: string, signal?: AbortSignal): Promise<string | null>;
|
|
318
|
+
async generate(modelKey: string, message: string, options?: TinyTitleGenerateOptions): Promise<string | null>;
|
|
319
|
+
async generate(
|
|
320
|
+
modelKey: string,
|
|
321
|
+
message: string,
|
|
322
|
+
optionsOrSignal?: AbortSignal | TinyTitleGenerateOptions,
|
|
323
|
+
): Promise<string | null> {
|
|
324
|
+
const options = normalizeTinyTitleGenerateOptions(optionsOrSignal);
|
|
284
325
|
if (!isTinyTitleLocalModelKey(modelKey)) return null;
|
|
285
|
-
if (signal?.aborted) return null;
|
|
326
|
+
if (options.signal?.aborted) return null;
|
|
286
327
|
|
|
287
328
|
try {
|
|
288
329
|
const worker = this.#ensureWorker();
|
|
@@ -295,12 +336,15 @@ export class TinyTitleClient {
|
|
|
295
336
|
this.#pending.delete(id);
|
|
296
337
|
pending.resolve(null);
|
|
297
338
|
};
|
|
298
|
-
signal?.addEventListener("abort", abort, { once: true });
|
|
339
|
+
options.signal?.addEventListener("abort", abort, { once: true });
|
|
299
340
|
try {
|
|
300
|
-
|
|
341
|
+
const request: TinyTitleWorkerInbound = options.systemPrompt
|
|
342
|
+
? { type: "generate", id, modelKey, message, systemPrompt: options.systemPrompt }
|
|
343
|
+
: { type: "generate", id, modelKey, message };
|
|
344
|
+
worker.send(request);
|
|
301
345
|
return await promise;
|
|
302
346
|
} finally {
|
|
303
|
-
signal?.removeEventListener("abort", abort);
|
|
347
|
+
options.signal?.removeEventListener("abort", abort);
|
|
304
348
|
this.#pending.delete(id);
|
|
305
349
|
}
|
|
306
350
|
} catch (error) {
|
|
@@ -29,7 +29,7 @@ export interface TinyTitleProgressEvent {
|
|
|
29
29
|
|
|
30
30
|
export type TinyTitleWorkerInbound =
|
|
31
31
|
| { type: "ping"; id: string }
|
|
32
|
-
| { type: "generate"; id: string; modelKey: TinyTitleLocalModelKey; message: string }
|
|
32
|
+
| { type: "generate"; id: string; modelKey: TinyTitleLocalModelKey; message: string; systemPrompt?: string }
|
|
33
33
|
| { type: "complete"; id: string; modelKey: TinyLocalModelKey; prompt: string; maxTokens?: number }
|
|
34
34
|
| { type: "download"; id: string; modelKey: TinyLocalModelKey };
|
|
35
35
|
|
package/src/tiny/worker.ts
CHANGED
|
@@ -436,9 +436,10 @@ async function loadPipeline(
|
|
|
436
436
|
return loaded;
|
|
437
437
|
}
|
|
438
438
|
|
|
439
|
-
function buildPrompt(generator: TextGenerationPipeline, message: string): string {
|
|
439
|
+
function buildPrompt(generator: TextGenerationPipeline, message: string, systemPrompt?: string): string {
|
|
440
|
+
const selectedSystemPrompt = systemPrompt?.trim() || TINY_TITLE_SYSTEM_PROMPT;
|
|
440
441
|
const chat = [
|
|
441
|
-
{ role: "system", content:
|
|
442
|
+
{ role: "system", content: selectedSystemPrompt },
|
|
442
443
|
{ role: "user", content: formatTitleUserMessage(message) },
|
|
443
444
|
];
|
|
444
445
|
const chatTemplateOptions = {
|
|
@@ -464,9 +465,10 @@ async function generateTitle(
|
|
|
464
465
|
requestId: string,
|
|
465
466
|
modelKey: TinyTitleLocalModelKey,
|
|
466
467
|
message: string,
|
|
468
|
+
systemPrompt?: string,
|
|
467
469
|
): Promise<string | null> {
|
|
468
470
|
const generator = await loadPipeline(modelKey, transport, requestId);
|
|
469
|
-
const promptText = buildPrompt(generator, message);
|
|
471
|
+
const promptText = buildPrompt(generator, message, systemPrompt);
|
|
470
472
|
const transformers = await loadTransformers(transport, requestId, modelKey);
|
|
471
473
|
const output = (await generator(promptText, {
|
|
472
474
|
max_new_tokens: TITLE_MAX_NEW_TOKENS,
|
|
@@ -548,7 +550,7 @@ async function handleQueuedRequest(
|
|
|
548
550
|
transport.send({ type: "completion", id: request.id, text });
|
|
549
551
|
return;
|
|
550
552
|
}
|
|
551
|
-
const title = await generateTitle(transport, request.id, request.modelKey, request.message);
|
|
553
|
+
const title = await generateTitle(transport, request.id, request.modelKey, request.message, request.systemPrompt);
|
|
552
554
|
transport.send({ type: "title", id: request.id, title });
|
|
553
555
|
} catch (error) {
|
|
554
556
|
transport.send({ type: "error", id: request.id, error: errorText(error) });
|
|
@@ -6,6 +6,19 @@ import { inflateSync, strFromU8 } from "fflate";
|
|
|
6
6
|
import { formatBytes } from "./render-utils";
|
|
7
7
|
import { ToolError } from "./tool-errors";
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Cap on the on-disk size of tar/tar.gz archives, which are loaded fully into
|
|
11
|
+
* memory (and decompressed by `Bun.Archive`) just to index entries. ZIP is
|
|
12
|
+
* exempt: it is read via ranged central-directory access.
|
|
13
|
+
*/
|
|
14
|
+
const MAX_TAR_ARCHIVE_BYTES = 256 * 1024 * 1024;
|
|
15
|
+
/**
|
|
16
|
+
* Cap on a single archive member's declared (uncompressed) size. The declared
|
|
17
|
+
* size is attacker-controlled metadata — a crafted ZIP entry can claim
|
|
18
|
+
* multi-GB sizes that would be allocated up front before any data inflates.
|
|
19
|
+
*/
|
|
20
|
+
const MAX_ARCHIVE_MEMBER_BYTES = 64 * 1024 * 1024;
|
|
21
|
+
|
|
9
22
|
export type ArchiveFormat = "zip" | "tar" | "tar.gz";
|
|
10
23
|
|
|
11
24
|
export interface ArchivePathCandidate {
|
|
@@ -646,6 +659,11 @@ export class ArchiveReader {
|
|
|
646
659
|
if (!entry.storage) {
|
|
647
660
|
throw new ToolError(`Archive file '${normalizedPath}' has no readable storage`);
|
|
648
661
|
}
|
|
662
|
+
if (entry.size > MAX_ARCHIVE_MEMBER_BYTES) {
|
|
663
|
+
throw new ToolError(
|
|
664
|
+
`Archive member '${normalizedPath}' is too large to extract in memory (${formatBytes(entry.size)} > ${formatBytes(MAX_ARCHIVE_MEMBER_BYTES)} limit)`,
|
|
665
|
+
);
|
|
666
|
+
}
|
|
649
667
|
|
|
650
668
|
const bytes =
|
|
651
669
|
entry.storage.type === "tar"
|
|
@@ -668,8 +686,18 @@ export async function openArchive(filePath: string): Promise<ArchiveReader> {
|
|
|
668
686
|
throw new ToolError(`Unsupported archive format: ${filePath}`);
|
|
669
687
|
}
|
|
670
688
|
|
|
671
|
-
|
|
672
|
-
|
|
689
|
+
if (format === "zip") {
|
|
690
|
+
return new ArchiveReader(format, await readZipEntries(filePath));
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
const file = Bun.file(filePath);
|
|
694
|
+
const archiveSize = file.size;
|
|
695
|
+
if (archiveSize > MAX_TAR_ARCHIVE_BYTES) {
|
|
696
|
+
throw new ToolError(
|
|
697
|
+
`Archive is too large to read in memory (${formatBytes(archiveSize)} > ${formatBytes(MAX_TAR_ARCHIVE_BYTES)} limit)`,
|
|
698
|
+
);
|
|
699
|
+
}
|
|
700
|
+
const entries = await readTarEntries(await file.bytes());
|
|
673
701
|
return new ArchiveReader(format, entries);
|
|
674
702
|
}
|
|
675
703
|
|