@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/eval/py/runner.py
CHANGED
|
@@ -51,8 +51,23 @@ from typing import Any
|
|
|
51
51
|
# Frame writer
|
|
52
52
|
# ---------------------------------------------------------------------------
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
# Frames travel on a private dup of the original stdout. fd 1 itself is then
|
|
55
|
+
# repointed at a capture pipe: child processes spawned by user code without
|
|
56
|
+
# stdout=PIPE inherit fd 1, and their output is forwarded to the host as
|
|
57
|
+
# regular stdout frames by a drain thread instead of being written raw into
|
|
58
|
+
# the NDJSON channel (where it would be dropped as invalid JSON — or worse,
|
|
59
|
+
# spoof a frame). The wire protocol is unchanged: the host still reads NDJSON
|
|
60
|
+
# frames from the subprocess stdout.
|
|
55
61
|
_RAW_STDERR = sys.__stderr__
|
|
62
|
+
try:
|
|
63
|
+
_FRAME_FD = os.dup(sys.__stdout__.fileno())
|
|
64
|
+
_RAW_STDOUT = os.fdopen(_FRAME_FD, "w", encoding="utf-8", errors="backslashreplace")
|
|
65
|
+
_CAPTURE_READ_FD, _capture_write_fd = os.pipe()
|
|
66
|
+
os.dup2(_capture_write_fd, sys.__stdout__.fileno())
|
|
67
|
+
os.close(_capture_write_fd)
|
|
68
|
+
except (AttributeError, OSError, ValueError, io.UnsupportedOperation):
|
|
69
|
+
_RAW_STDOUT = sys.__stdout__
|
|
70
|
+
_CAPTURE_READ_FD = None
|
|
56
71
|
_OUT_LOCK = threading.Lock()
|
|
57
72
|
|
|
58
73
|
|
|
@@ -78,11 +93,22 @@ def _emit(frame: dict) -> None:
|
|
|
78
93
|
|
|
79
94
|
|
|
80
95
|
class _StreamProxy(io.TextIOBase):
|
|
81
|
-
"""Emit
|
|
96
|
+
"""Emit ``write()`` data as typed frames tied to the current request.
|
|
97
|
+
|
|
98
|
+
Writes are coalesced per request: a frame is emitted once the buffer holds
|
|
99
|
+
a complete line (everything up to the last newline goes out together) or
|
|
100
|
+
grows past ``_MAX_BUFFER`` bytes, so the common ``print()`` pair of
|
|
101
|
+
``write(text)`` + ``write("\\n")`` costs one frame instead of two. Partial
|
|
102
|
+
lines are bounded by ``flush()`` and the end-of-request flush.
|
|
103
|
+
"""
|
|
104
|
+
|
|
105
|
+
_MAX_BUFFER = 8192
|
|
82
106
|
|
|
83
107
|
def __init__(self, kind: str) -> None:
|
|
84
108
|
super().__init__()
|
|
85
109
|
self._kind = kind
|
|
110
|
+
self._lock = threading.Lock()
|
|
111
|
+
self._buffers: dict[str, str] = {}
|
|
86
112
|
|
|
87
113
|
def writable(self) -> bool: # noqa: D401 - protocol method
|
|
88
114
|
return True
|
|
@@ -100,12 +126,44 @@ class _StreamProxy(io.TextIOBase):
|
|
|
100
126
|
_RAW_STDERR.write(data)
|
|
101
127
|
_RAW_STDERR.flush()
|
|
102
128
|
return len(data)
|
|
103
|
-
|
|
129
|
+
emit_text = None
|
|
130
|
+
with self._lock:
|
|
131
|
+
buf = self._buffers.pop(rid, "") + data
|
|
132
|
+
if len(buf) >= self._MAX_BUFFER:
|
|
133
|
+
emit_text = buf
|
|
134
|
+
else:
|
|
135
|
+
nl = buf.rfind("\n")
|
|
136
|
+
if nl >= 0:
|
|
137
|
+
emit_text = buf[: nl + 1]
|
|
138
|
+
rest = buf[nl + 1 :]
|
|
139
|
+
if rest:
|
|
140
|
+
self._buffers[rid] = rest
|
|
141
|
+
else:
|
|
142
|
+
self._buffers[rid] = buf
|
|
143
|
+
if emit_text:
|
|
144
|
+
_emit({"type": self._kind, "id": rid, "data": emit_text})
|
|
104
145
|
return len(data)
|
|
105
146
|
|
|
106
147
|
def flush(self) -> None: # noqa: D401 - protocol method
|
|
148
|
+
rid = _CURRENT_RID.get()
|
|
149
|
+
if rid is not None:
|
|
150
|
+
self.flush_rid(rid)
|
|
107
151
|
return None
|
|
108
152
|
|
|
153
|
+
def flush_rid(self, rid: str) -> None:
|
|
154
|
+
"""Flush any buffered partial line for ``rid`` as its own frame."""
|
|
155
|
+
with self._lock:
|
|
156
|
+
buf = self._buffers.pop(rid, None)
|
|
157
|
+
if buf:
|
|
158
|
+
_emit({"type": self._kind, "id": rid, "data": buf})
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def _flush_stream_proxies(rid: str) -> None:
|
|
162
|
+
"""Drain buffered proxy output for ``rid`` (called before its done frame)."""
|
|
163
|
+
for stream in (sys.stdout, sys.stderr):
|
|
164
|
+
if isinstance(stream, _StreamProxy):
|
|
165
|
+
stream.flush_rid(rid)
|
|
166
|
+
|
|
109
167
|
|
|
110
168
|
# ---------------------------------------------------------------------------
|
|
111
169
|
# Runner state
|
|
@@ -125,6 +183,10 @@ class _RunnerState:
|
|
|
125
183
|
self.last_install_marker: int = 0
|
|
126
184
|
self.loop: asyncio.AbstractEventLoop | None = None
|
|
127
185
|
self.active_executions: int = 0
|
|
186
|
+
# Best-effort attribution target for captured fd-1 bytes (child
|
|
187
|
+
# processes inheriting stdout). With overlapping requests the most
|
|
188
|
+
# recently started one wins — strictly better than dropping the bytes.
|
|
189
|
+
self.capture_rid: str | None = None
|
|
128
190
|
|
|
129
191
|
|
|
130
192
|
_CURRENT_RID: contextvars.ContextVar[str | None] = contextvars.ContextVar("omp_current_rid", default=None)
|
|
@@ -132,6 +194,42 @@ _CURRENT_RID: contextvars.ContextVar[str | None] = contextvars.ContextVar("omp_c
|
|
|
132
194
|
_STATE = _RunnerState()
|
|
133
195
|
|
|
134
196
|
|
|
197
|
+
def _drain_captured_stdout() -> None:
|
|
198
|
+
"""Forward bytes written to the captured fd 1 as stdout frames.
|
|
199
|
+
|
|
200
|
+
Runs on a daemon thread for the life of the process. Child processes that
|
|
201
|
+
inherit fd 1 (any ``subprocess`` call without ``stdout=PIPE``) land here.
|
|
202
|
+
"""
|
|
203
|
+
if _CAPTURE_READ_FD is None:
|
|
204
|
+
return
|
|
205
|
+
import codecs
|
|
206
|
+
|
|
207
|
+
decoder = codecs.getincrementaldecoder("utf-8")("replace")
|
|
208
|
+
while True:
|
|
209
|
+
try:
|
|
210
|
+
chunk = os.read(_CAPTURE_READ_FD, 65536)
|
|
211
|
+
except OSError:
|
|
212
|
+
return
|
|
213
|
+
if not chunk:
|
|
214
|
+
return
|
|
215
|
+
text = decoder.decode(chunk)
|
|
216
|
+
if not text:
|
|
217
|
+
continue
|
|
218
|
+
rid = _STATE.capture_rid
|
|
219
|
+
if rid is None:
|
|
220
|
+
_RAW_STDERR.write(text)
|
|
221
|
+
_RAW_STDERR.flush()
|
|
222
|
+
else:
|
|
223
|
+
_emit({"type": "stdout", "id": rid, "data": text})
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def _start_capture_drain() -> None:
|
|
227
|
+
if _CAPTURE_READ_FD is None:
|
|
228
|
+
return
|
|
229
|
+
thread = threading.Thread(target=_drain_captured_stdout, name="omp-fd1-capture", daemon=True)
|
|
230
|
+
thread.start()
|
|
231
|
+
|
|
232
|
+
|
|
135
233
|
# ---------------------------------------------------------------------------
|
|
136
234
|
# Magic source transformer
|
|
137
235
|
# ---------------------------------------------------------------------------
|
|
@@ -880,6 +978,7 @@ def _start_parent_watchdog() -> None:
|
|
|
880
978
|
async def _handle_request_async(req: dict) -> None:
|
|
881
979
|
rid = str(req.get("id"))
|
|
882
980
|
token = _CURRENT_RID.set(rid)
|
|
981
|
+
_STATE.capture_rid = rid
|
|
883
982
|
_STATE.user_ns["__omp_run_id__"] = rid
|
|
884
983
|
_STATE.cancel_requested = False
|
|
885
984
|
_STATE.execution_count += 1
|
|
@@ -934,6 +1033,7 @@ async def _handle_request_async(req: dict) -> None:
|
|
|
934
1033
|
except Exception:
|
|
935
1034
|
pass
|
|
936
1035
|
|
|
1036
|
+
_flush_stream_proxies(rid)
|
|
937
1037
|
_emit({
|
|
938
1038
|
"type": "done",
|
|
939
1039
|
"id": rid,
|
|
@@ -942,6 +1042,9 @@ async def _handle_request_async(req: dict) -> None:
|
|
|
942
1042
|
"cancelled": cancelled,
|
|
943
1043
|
})
|
|
944
1044
|
finally:
|
|
1045
|
+
if _STATE.capture_rid == rid:
|
|
1046
|
+
_STATE.capture_rid = None
|
|
1047
|
+
_flush_stream_proxies(rid)
|
|
945
1048
|
_CURRENT_RID.reset(token)
|
|
946
1049
|
|
|
947
1050
|
|
|
@@ -986,6 +1089,7 @@ async def _main_async() -> None:
|
|
|
986
1089
|
sys.stderr = _StreamProxy("stderr")
|
|
987
1090
|
_install_idle_sigint()
|
|
988
1091
|
_start_parent_watchdog()
|
|
1092
|
+
_start_capture_drain()
|
|
989
1093
|
|
|
990
1094
|
stdin = sys.__stdin__
|
|
991
1095
|
if stdin is None:
|
package/src/eval/py/runtime.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* for both the shared gateway and local kernel spawning.
|
|
6
6
|
*/
|
|
7
7
|
import * as fs from "node:fs";
|
|
8
|
+
import * as os from "node:os";
|
|
8
9
|
import * as path from "node:path";
|
|
9
10
|
import { $env, $which, getPythonEnvDir } from "@oh-my-pi/pi-utils";
|
|
10
11
|
|
|
@@ -182,6 +183,42 @@ function venvBinDir(venvPath: string): string {
|
|
|
182
183
|
return process.platform === "win32" ? path.join(venvPath, "Scripts") : path.join(venvPath, "bin");
|
|
183
184
|
}
|
|
184
185
|
|
|
186
|
+
function detectExplicitVenv(pythonPath: string): { venvPath: string; binDir: string } | undefined {
|
|
187
|
+
const binDir = path.dirname(pythonPath);
|
|
188
|
+
const venvPath = path.dirname(binDir);
|
|
189
|
+
if (fs.existsSync(path.join(venvPath, "pyvenv.cfg"))) {
|
|
190
|
+
return { venvPath, binDir };
|
|
191
|
+
}
|
|
192
|
+
return undefined;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Resolve an explicitly configured interpreter (`python.interpreter`) into a
|
|
197
|
+
* runtime, bypassing discovery. Does not probe or validate the executable —
|
|
198
|
+
* callers must check it actually runs. `~` expands to the home directory and
|
|
199
|
+
* relative paths resolve against `cwd`. When the interpreter sits inside a
|
|
200
|
+
* virtualenv (a `pyvenv.cfg` above its bin dir), the venv activation env is
|
|
201
|
+
* applied so subprocesses and `pip` resolve consistently.
|
|
202
|
+
*/
|
|
203
|
+
export function resolveExplicitPythonRuntime(
|
|
204
|
+
interpreter: string,
|
|
205
|
+
cwd: string,
|
|
206
|
+
baseEnv: Record<string, string | undefined>,
|
|
207
|
+
): PythonRuntime {
|
|
208
|
+
const expanded =
|
|
209
|
+
interpreter === "~"
|
|
210
|
+
? os.homedir()
|
|
211
|
+
: interpreter.startsWith("~/")
|
|
212
|
+
? path.join(os.homedir(), interpreter.slice(2))
|
|
213
|
+
: interpreter;
|
|
214
|
+
const pythonPath = path.isAbsolute(expanded) ? expanded : path.resolve(cwd, expanded);
|
|
215
|
+
const venv = detectExplicitVenv(pythonPath);
|
|
216
|
+
if (venv) {
|
|
217
|
+
return { pythonPath, env: applyVenvEnv(baseEnv, venv.venvPath, venv.binDir), venvPath: venv.venvPath };
|
|
218
|
+
}
|
|
219
|
+
return { pythonPath, env: { ...baseEnv } };
|
|
220
|
+
}
|
|
221
|
+
|
|
185
222
|
/**
|
|
186
223
|
* Enumerate candidate Python runtimes in priority order: an active/project venv,
|
|
187
224
|
* the managed `~/.omp/python-env`, then the system interpreter on PATH. Every
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import * as fs from "node:fs/promises";
|
|
7
7
|
import { ExponentialYield } from "@oh-my-pi/pi-agent-core/utils/yield";
|
|
8
8
|
import { executeShell, type MinimizerOptions, Shell, type ShellRunResult } from "@oh-my-pi/pi-natives";
|
|
9
|
+
import { isExecutable, type ShellConfig } from "@oh-my-pi/pi-utils/procmgr";
|
|
9
10
|
import { Settings, type ShellMinimizerSettings } from "../config/settings";
|
|
10
11
|
import { OutputSink } from "../session/streaming-output";
|
|
11
12
|
import { resolveOutputMaxColumns, resolveOutputSinkHeadBytes } from "../tools/output-meta";
|
|
@@ -22,6 +23,8 @@ export interface BashExecutorOptions {
|
|
|
22
23
|
sessionKey?: string;
|
|
23
24
|
/** Additional environment variables to inject */
|
|
24
25
|
env?: Record<string, string>;
|
|
26
|
+
/** Run through the configured user shell instead of brush parsing directly. */
|
|
27
|
+
useUserShell?: boolean;
|
|
25
28
|
/** Artifact path/id for full output storage */
|
|
26
29
|
artifactPath?: string;
|
|
27
30
|
artifactId?: string;
|
|
@@ -95,13 +98,86 @@ export function buildMinimizerOptions(group: ShellMinimizerSettings): MinimizerO
|
|
|
95
98
|
only: group.only.length > 0 ? group.only : undefined,
|
|
96
99
|
except: group.except.length > 0 ? group.except : undefined,
|
|
97
100
|
maxCaptureBytes: group.maxCaptureBytes,
|
|
101
|
+
sourceOutlineLevel: group.sourceOutlineLevel === "default" ? undefined : group.sourceOutlineLevel,
|
|
102
|
+
legacyFilters: group.legacyFilters,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function shellBasename(shell: string): string {
|
|
107
|
+
return shell.replace(/\\/g, "/").split("/").pop()?.toLowerCase() ?? "";
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function isBashShell(shell: string): boolean {
|
|
111
|
+
const basename = shellBasename(shell);
|
|
112
|
+
return basename.includes("bash");
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function needsInteractiveShellArg(shell: string): boolean {
|
|
116
|
+
const basename = shellBasename(shell);
|
|
117
|
+
return basename.includes("zsh");
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function supportsAutoUserShell(shell: string): boolean {
|
|
121
|
+
const basename = shellBasename(shell);
|
|
122
|
+
return basename.includes("bash") || basename.includes("zsh") || basename.includes("fish");
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function hasInteractiveShellArg(args: string[]): boolean {
|
|
126
|
+
return args.some(arg => arg === "--interactive" || /^-[^-]*i/.test(arg));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function ensureInteractiveShellArgs(shell: string, args: string[]): string[] {
|
|
130
|
+
if (!needsInteractiveShellArg(shell) || hasInteractiveShellArg(args)) return args;
|
|
131
|
+
|
|
132
|
+
const commandIndex = args.findIndex(arg => arg === "-c" || arg === "--command");
|
|
133
|
+
if (commandIndex !== -1) {
|
|
134
|
+
return [...args.slice(0, commandIndex), "-i", ...args.slice(commandIndex)];
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const compactCommandIndex = args.findIndex(arg => /^-[^-]*c[^-]*$/.test(arg));
|
|
138
|
+
if (compactCommandIndex !== -1) {
|
|
139
|
+
return args.map((arg, index) => (index === compactCommandIndex ? arg.replace("c", "ic") : arg));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return [...args, "-i"];
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function quoteShellArg(value: string): string {
|
|
146
|
+
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function buildUserShellCommand(shell: string, args: string[], command: string): string {
|
|
150
|
+
return [shell, ...ensureInteractiveShellArgs(shell, args), command].map(quoteShellArg).join(" ");
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function resolveUserShellConfig(settings: Settings, baseConfig: ShellConfig): ShellConfig {
|
|
154
|
+
const customShellPath = settings.get("shellPath");
|
|
155
|
+
const envShell = Bun.env.SHELL;
|
|
156
|
+
if (customShellPath || process.platform === "win32" || !envShell || envShell === baseConfig.shell) {
|
|
157
|
+
return baseConfig;
|
|
158
|
+
}
|
|
159
|
+
if (!supportsAutoUserShell(envShell) || !isExecutable(envShell)) {
|
|
160
|
+
return baseConfig;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return {
|
|
164
|
+
...baseConfig,
|
|
165
|
+
shell: envShell,
|
|
166
|
+
env: {
|
|
167
|
+
...baseConfig.env,
|
|
168
|
+
SHELL: envShell,
|
|
169
|
+
},
|
|
98
170
|
};
|
|
99
171
|
}
|
|
100
172
|
|
|
101
173
|
export async function executeBash(command: string, options?: BashExecutorOptions): Promise<BashResult> {
|
|
102
174
|
const settings = await Settings.init();
|
|
103
|
-
const
|
|
104
|
-
const
|
|
175
|
+
const baseShellConfig = settings.getShellConfig();
|
|
176
|
+
const shellConfig =
|
|
177
|
+
options?.useUserShell === true ? resolveUserShellConfig(settings, baseShellConfig) : baseShellConfig;
|
|
178
|
+
const { shell, args, env: shellEnv, prefix } = shellConfig;
|
|
179
|
+
const bashShell = isBashShell(shell);
|
|
180
|
+
const snapshotPath = bashShell ? await getOrCreateSnapshot(shell, shellEnv) : null;
|
|
105
181
|
|
|
106
182
|
const minimizer = buildMinimizerOptions(settings.getGroup("shellMinimizer"));
|
|
107
183
|
|
|
@@ -110,7 +186,10 @@ export async function executeBash(command: string, options?: BashExecutorOptions
|
|
|
110
186
|
|
|
111
187
|
// Apply command prefix if configured
|
|
112
188
|
const prefixedCommand = prefix ? `${prefix} ${command}` : command;
|
|
113
|
-
const finalCommand =
|
|
189
|
+
const finalCommand =
|
|
190
|
+
options?.useUserShell === true && !bashShell
|
|
191
|
+
? buildUserShellCommand(shell, args, prefixedCommand)
|
|
192
|
+
: prefixedCommand;
|
|
114
193
|
|
|
115
194
|
// Create output sink for truncation and artifact handling
|
|
116
195
|
const sink = new OutputSink({
|
|
@@ -314,7 +393,9 @@ export async function executeBash(command: string, options?: BashExecutorOptions
|
|
|
314
393
|
if (userSignal) {
|
|
315
394
|
userSignal.removeEventListener("abort", abortHandler);
|
|
316
395
|
}
|
|
317
|
-
if (resetSession) {
|
|
396
|
+
if (resetSession || options?.sessionKey?.includes(":async:")) {
|
|
397
|
+
// `:async:` keys are per-job (jobId is unique), so the Shell would
|
|
398
|
+
// otherwise stay in the process-global map forever after completion.
|
|
318
399
|
shellSessions.delete(sessionKey);
|
|
319
400
|
}
|
|
320
401
|
}
|