@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
|
@@ -79,14 +79,14 @@ import {
|
|
|
79
79
|
clearAnthropicFastModeFallback,
|
|
80
80
|
deriveClaudeDeviceId,
|
|
81
81
|
Effort,
|
|
82
|
-
getSupportedEfforts,
|
|
83
82
|
isContextOverflow,
|
|
84
83
|
isUsageLimitError,
|
|
85
|
-
modelsAreEqual,
|
|
86
84
|
parseRateLimitReason,
|
|
87
85
|
resolveServiceTier,
|
|
88
86
|
streamSimple,
|
|
89
87
|
} from "@oh-my-pi/pi-ai";
|
|
88
|
+
import { getSupportedEfforts } from "@oh-my-pi/pi-catalog/model-thinking";
|
|
89
|
+
import { modelsAreEqual } from "@oh-my-pi/pi-catalog/models";
|
|
90
90
|
import { countTokens, MacOSPowerAssertion } from "@oh-my-pi/pi-natives";
|
|
91
91
|
import {
|
|
92
92
|
extractRetryHint,
|
|
@@ -105,9 +105,10 @@ import { classifyDifficulty } from "../auto-thinking/classifier";
|
|
|
105
105
|
import { reset as resetCapabilities } from "../capability";
|
|
106
106
|
import type { Rule } from "../capability/rule";
|
|
107
107
|
import { shouldEnableAppendOnlyContext } from "../config/append-only-context-mode";
|
|
108
|
-
import {
|
|
108
|
+
import type { ModelRegistry } from "../config/model-registry";
|
|
109
109
|
import {
|
|
110
110
|
extractExplicitThinkingSelector,
|
|
111
|
+
filterAvailableModelsByEnabledPatterns,
|
|
111
112
|
formatModelSelectorValue,
|
|
112
113
|
formatModelString,
|
|
113
114
|
getModelMatchPreferences,
|
|
@@ -115,6 +116,7 @@ import {
|
|
|
115
116
|
type ResolvedModelRoleValue,
|
|
116
117
|
resolveModelRoleValue,
|
|
117
118
|
} from "../config/model-resolver";
|
|
119
|
+
import { MODEL_ROLE_IDS } from "../config/model-roles";
|
|
118
120
|
import { expandPromptTemplate, type PromptTemplate } from "../config/prompt-templates";
|
|
119
121
|
import type { Settings, SkillsSettings } from "../config/settings";
|
|
120
122
|
import { onAppendOnlyModeChanged } from "../config/settings";
|
|
@@ -183,7 +185,12 @@ import planModeToolDecisionReminderPrompt from "../prompts/system/plan-mode-tool
|
|
|
183
185
|
import ttsrInterruptTemplate from "../prompts/system/ttsr-interrupt.md" with { type: "text" };
|
|
184
186
|
import ttsrToolReminderTemplate from "../prompts/system/ttsr-tool-reminder.md" with { type: "text" };
|
|
185
187
|
import { type AgentRegistry, MAIN_AGENT_ID } from "../registry/agent-registry";
|
|
186
|
-
import {
|
|
188
|
+
import {
|
|
189
|
+
deobfuscateSessionContext,
|
|
190
|
+
obfuscateProviderContext,
|
|
191
|
+
obfuscateProviderTools,
|
|
192
|
+
type SecretObfuscator,
|
|
193
|
+
} from "../secrets/obfuscator";
|
|
187
194
|
import { invalidateHostMetadata } from "../ssh/connection-manager";
|
|
188
195
|
import {
|
|
189
196
|
AUTO_THINKING,
|
|
@@ -191,6 +198,7 @@ import {
|
|
|
191
198
|
clampAutoThinkingEffort,
|
|
192
199
|
resolveProvisionalAutoLevel,
|
|
193
200
|
resolveThinkingLevelForModel,
|
|
201
|
+
shouldDisableReasoning,
|
|
194
202
|
toReasoningEffort,
|
|
195
203
|
} from "../thinking";
|
|
196
204
|
import { shutdownTinyTitleClient } from "../tiny/title-client";
|
|
@@ -287,6 +295,20 @@ export type AgentSessionEventListener = (event: AgentSessionEvent) => void;
|
|
|
287
295
|
export type AsyncJobSnapshotItem = Pick<AsyncJob, "id" | "type" | "status" | "label" | "startTime">;
|
|
288
296
|
|
|
289
297
|
const EMPTY_STOP_MAX_RETRIES = 3;
|
|
298
|
+
const RETRY_BACKOFF_MAX_DELAY_MS = 8_000;
|
|
299
|
+
const RETRY_BACKOFF_JITTER_RATIO = 0.25;
|
|
300
|
+
|
|
301
|
+
function calculateRetryBackoffDelayMs(baseDelayMs: number, attempt: number): number {
|
|
302
|
+
const cappedDelayMs = Math.min(Math.max(0, baseDelayMs) * 2 ** Math.max(0, attempt - 1), RETRY_BACKOFF_MAX_DELAY_MS);
|
|
303
|
+
const jitter = 1 - Math.random() * RETRY_BACKOFF_JITTER_RATIO;
|
|
304
|
+
return cappedDelayMs * jitter;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Slack added past a sibling credential's block expiry before retrying, so
|
|
309
|
+
* the next getApiKey lands after the block has actually lapsed.
|
|
310
|
+
*/
|
|
311
|
+
const SIBLING_UNBLOCK_BUFFER_MS = 1_000;
|
|
290
312
|
const NON_WHITESPACE_RE = /\S/;
|
|
291
313
|
|
|
292
314
|
function hasNonWhitespace(value: string): boolean {
|
|
@@ -309,6 +331,8 @@ export interface AgentSessionConfig {
|
|
|
309
331
|
agent: Agent;
|
|
310
332
|
sessionManager: SessionManager;
|
|
311
333
|
settings: Settings;
|
|
334
|
+
/** Whether the caller explicitly requested yolo/auto-approve behavior for this session. */
|
|
335
|
+
autoApprove?: boolean;
|
|
312
336
|
/** Models to cycle through with Ctrl+P (from --models flag) */
|
|
313
337
|
scopedModels?: Array<{ model: Model; thinkingLevel?: ThinkingLevel }>;
|
|
314
338
|
/** Initial session thinking selector. */
|
|
@@ -824,6 +848,7 @@ export class AgentSession {
|
|
|
824
848
|
readonly settings: Settings;
|
|
825
849
|
readonly yieldQueue: YieldQueue;
|
|
826
850
|
fileSnapshotStore?: InMemorySnapshotStore;
|
|
851
|
+
#autoApprove: boolean;
|
|
827
852
|
|
|
828
853
|
#powerAssertion: MacOSPowerAssertion | undefined;
|
|
829
854
|
|
|
@@ -1103,6 +1128,7 @@ export class AgentSession {
|
|
|
1103
1128
|
this.agent = config.agent;
|
|
1104
1129
|
this.sessionManager = config.sessionManager;
|
|
1105
1130
|
this.settings = config.settings;
|
|
1131
|
+
this.#autoApprove = config.autoApprove === true;
|
|
1106
1132
|
// Power assertions are taken per turn (see #beginInFlight); nothing acquired here.
|
|
1107
1133
|
this.#evalKernelOwnerId = config.evalKernelOwnerId ?? `agent-session:${Snowflake.next()}`;
|
|
1108
1134
|
this.#parentEvalSessionId = config.parentEvalSessionId;
|
|
@@ -1118,6 +1144,7 @@ export class AgentSession {
|
|
|
1118
1144
|
} else {
|
|
1119
1145
|
this.#thinkingLevel = config.thinkingLevel;
|
|
1120
1146
|
}
|
|
1147
|
+
this.#applyThinkingLevelToAgent(this.#thinkingLevel);
|
|
1121
1148
|
this.#promptTemplates = config.promptTemplates ?? [];
|
|
1122
1149
|
this.#slashCommands = config.slashCommands ?? [];
|
|
1123
1150
|
this.#extensionRunner = config.extensionRunner;
|
|
@@ -3514,12 +3541,26 @@ export class AgentSession {
|
|
|
3514
3541
|
* Wrap a tool with a permission-gate proxy when an ACP client is connected.
|
|
3515
3542
|
* Only wraps tools whose name is in PERMISSION_REQUIRED_TOOLS and only when
|
|
3516
3543
|
* the bridge exposes `requestPermission`. No-ops for all other cases.
|
|
3544
|
+
*
|
|
3545
|
+
* When the user has explicitly opted into `yolo` / auto-approve behavior (via
|
|
3546
|
+
* the SDK/CLI `autoApprove` flag or a configured `tools.approvalMode: yolo`),
|
|
3547
|
+
* skips the gate unless the per-tool policy explicitly requires a prompt or
|
|
3548
|
+
* deny. The schema default is also `yolo`, so an explicit configuration or
|
|
3549
|
+
* explicit session flag is required: default-config ACP sessions keep the
|
|
3550
|
+
* client-side permission gate.
|
|
3517
3551
|
*/
|
|
3518
3552
|
#wrapToolForAcpPermission<T extends AgentTool>(tool: T): T {
|
|
3519
3553
|
const bridge = this.#clientBridge;
|
|
3520
3554
|
// Match the capability+method gating pattern used by read/write/bash.
|
|
3521
3555
|
if (!bridge?.capabilities.requestPermission || !bridge.requestPermission) return tool;
|
|
3522
3556
|
if (!PERMISSION_REQUIRED_TOOLS.has(tool.name)) return tool;
|
|
3557
|
+
// Skip the gate only on explicit yolo opt-in; honour per-tool policies
|
|
3558
|
+
// that require a prompt or deny (matching the normal approval wrapper).
|
|
3559
|
+
if (this.#isExplicitAutoApproveMode()) {
|
|
3560
|
+
const userPolicies = (this.settings.get("tools.approval") ?? {}) as Record<string, unknown>;
|
|
3561
|
+
const toolPolicy = userPolicies[tool.name];
|
|
3562
|
+
if (!toolPolicy || toolPolicy === "allow") return tool;
|
|
3563
|
+
}
|
|
3523
3564
|
return new Proxy(tool, {
|
|
3524
3565
|
get: (target, prop) => {
|
|
3525
3566
|
if (prop !== "execute") return Reflect.get(target, prop, target);
|
|
@@ -3607,6 +3648,13 @@ export class AgentSession {
|
|
|
3607
3648
|
}) as T;
|
|
3608
3649
|
}
|
|
3609
3650
|
|
|
3651
|
+
#isExplicitAutoApproveMode(): boolean {
|
|
3652
|
+
return (
|
|
3653
|
+
this.#autoApprove ||
|
|
3654
|
+
(this.settings.isConfigured("tools.approvalMode") && this.settings.get("tools.approvalMode") === "yolo")
|
|
3655
|
+
);
|
|
3656
|
+
}
|
|
3657
|
+
|
|
3610
3658
|
async #applyActiveToolsByName(
|
|
3611
3659
|
toolNames: string[],
|
|
3612
3660
|
options?: { persistMCPSelection?: boolean; previousSelectedMCPToolNames?: string[] },
|
|
@@ -3984,6 +4032,47 @@ export class AgentSession {
|
|
|
3984
4032
|
return deobfuscateSessionContext(this.sessionManager.buildSessionContext(), this.#obfuscator);
|
|
3985
4033
|
}
|
|
3986
4034
|
|
|
4035
|
+
#obfuscateForProvider<T>(value: T): T {
|
|
4036
|
+
if (!this.#obfuscator?.hasSecrets()) return value;
|
|
4037
|
+
return this.#obfuscator.obfuscateObject(value);
|
|
4038
|
+
}
|
|
4039
|
+
|
|
4040
|
+
#obfuscateTextForProvider(text: string | undefined): string | undefined {
|
|
4041
|
+
if (!text || !this.#obfuscator?.hasSecrets()) return text;
|
|
4042
|
+
return this.#obfuscator.obfuscate(text);
|
|
4043
|
+
}
|
|
4044
|
+
|
|
4045
|
+
#obfuscatePreparationForProvider(preparation: CompactionPreparation): CompactionPreparation {
|
|
4046
|
+
if (!this.#obfuscator?.hasSecrets()) return preparation;
|
|
4047
|
+
if (!preparation.previousSummary && !preparation.previousPreserveData) return preparation;
|
|
4048
|
+
return {
|
|
4049
|
+
...preparation,
|
|
4050
|
+
previousSummary: preparation.previousSummary
|
|
4051
|
+
? this.#obfuscator.obfuscate(preparation.previousSummary)
|
|
4052
|
+
: preparation.previousSummary,
|
|
4053
|
+
previousPreserveData: preparation.previousPreserveData
|
|
4054
|
+
? this.#obfuscator.obfuscateObject(preparation.previousPreserveData)
|
|
4055
|
+
: preparation.previousPreserveData,
|
|
4056
|
+
};
|
|
4057
|
+
}
|
|
4058
|
+
|
|
4059
|
+
#deobfuscateFromProvider(text: string): string {
|
|
4060
|
+
if (!this.#obfuscator?.hasSecrets()) return text;
|
|
4061
|
+
return this.#obfuscator.deobfuscate(text);
|
|
4062
|
+
}
|
|
4063
|
+
|
|
4064
|
+
#deobfuscatedProviderTextReadyForDelta(text: string): string {
|
|
4065
|
+
const deobfuscated = this.#deobfuscateFromProvider(text);
|
|
4066
|
+
if (!this.#obfuscator?.hasSecrets()) return deobfuscated;
|
|
4067
|
+
const pendingPlaceholderStart = deobfuscated.match(/#[A-Z0-9]{0,4}$/);
|
|
4068
|
+
if (pendingPlaceholderStart?.index === undefined) return deobfuscated;
|
|
4069
|
+
return deobfuscated.slice(0, pendingPlaceholderStart.index);
|
|
4070
|
+
}
|
|
4071
|
+
|
|
4072
|
+
#convertToLlmForSideRequest(messages: AgentMessage[]): Message[] {
|
|
4073
|
+
return this.#obfuscateForProvider(convertToLlm(messages));
|
|
4074
|
+
}
|
|
4075
|
+
|
|
3987
4076
|
/** Convert session messages using the same pre-LLM pipeline as the active session. */
|
|
3988
4077
|
async convertMessagesToLlm(messages: AgentMessage[], signal?: AbortSignal): Promise<Message[]> {
|
|
3989
4078
|
const transformedMessages = await this.#transformContext(messages, signal);
|
|
@@ -4383,21 +4472,28 @@ export class AgentSession {
|
|
|
4383
4472
|
* @throws Error if streaming and no streamingBehavior specified
|
|
4384
4473
|
* @throws Error if no model selected or no API key available (when not streaming)
|
|
4385
4474
|
*/
|
|
4386
|
-
|
|
4475
|
+
/**
|
|
4476
|
+
* Returns `false` when the command was fully handled locally (extension or
|
|
4477
|
+
* custom-TS command consumed without calling the LLM). Returns `true` when
|
|
4478
|
+
* the prompt was forwarded to the agent — either directly or queued as a
|
|
4479
|
+
* steer/follow-up. Callers that render a UI or manage turn lifecycle (e.g.
|
|
4480
|
+
* the ACP agent) use this to know whether to expect an `agent_end` event.
|
|
4481
|
+
*/
|
|
4482
|
+
async prompt(text: string, options?: PromptOptions): Promise<boolean> {
|
|
4387
4483
|
const expandPromptTemplates = options?.expandPromptTemplates ?? true;
|
|
4388
4484
|
|
|
4389
4485
|
// Handle extension commands first (execute immediately, even during streaming)
|
|
4390
4486
|
if (expandPromptTemplates && text.startsWith("/")) {
|
|
4391
4487
|
const handled = await this.#tryExecuteExtensionCommand(text);
|
|
4392
4488
|
if (handled) {
|
|
4393
|
-
return;
|
|
4489
|
+
return false;
|
|
4394
4490
|
}
|
|
4395
4491
|
|
|
4396
4492
|
// Try custom commands (TypeScript slash commands)
|
|
4397
4493
|
const customResult = await this.#tryExecuteCustomCommand(text);
|
|
4398
4494
|
if (customResult !== null) {
|
|
4399
4495
|
if (customResult === "") {
|
|
4400
|
-
return;
|
|
4496
|
+
return false;
|
|
4401
4497
|
}
|
|
4402
4498
|
text = customResult;
|
|
4403
4499
|
}
|
|
@@ -4431,7 +4527,7 @@ export class AgentSession {
|
|
|
4431
4527
|
for (const notice of keywordNotices) {
|
|
4432
4528
|
await this.sendCustomMessage(notice, { deliverAs: options.streamingBehavior });
|
|
4433
4529
|
}
|
|
4434
|
-
return;
|
|
4530
|
+
return true;
|
|
4435
4531
|
}
|
|
4436
4532
|
|
|
4437
4533
|
// Skip eager todo prelude when the user has already queued a directive
|
|
@@ -4471,6 +4567,7 @@ export class AgentSession {
|
|
|
4471
4567
|
if (!options?.synthetic) {
|
|
4472
4568
|
await this.#enforcePlanModeToolDecision();
|
|
4473
4569
|
}
|
|
4570
|
+
return true;
|
|
4474
4571
|
}
|
|
4475
4572
|
|
|
4476
4573
|
async promptCustomMessage<T = unknown>(
|
|
@@ -5679,16 +5776,25 @@ export class AgentSession {
|
|
|
5679
5776
|
}
|
|
5680
5777
|
|
|
5681
5778
|
/**
|
|
5682
|
-
* Get all available models with valid API keys.
|
|
5779
|
+
* Get all available models with valid API keys, filtered by `enabledModels` when configured.
|
|
5780
|
+
* See {@link filterAvailableModelsByEnabledPatterns} for supported pattern forms and limitations.
|
|
5683
5781
|
*/
|
|
5684
5782
|
getAvailableModels(): Model[] {
|
|
5685
|
-
|
|
5783
|
+
const all = this.#modelRegistry.getAvailable();
|
|
5784
|
+
const patterns = this.settings.get("enabledModels");
|
|
5785
|
+
if (!patterns || patterns.length === 0) return all;
|
|
5786
|
+
return filterAvailableModelsByEnabledPatterns(all, patterns, this.#modelRegistry);
|
|
5686
5787
|
}
|
|
5687
5788
|
|
|
5688
5789
|
// =========================================================================
|
|
5689
5790
|
// Thinking Level Management
|
|
5690
5791
|
// =========================================================================
|
|
5691
5792
|
|
|
5793
|
+
#applyThinkingLevelToAgent(level: ThinkingLevel | undefined): void {
|
|
5794
|
+
this.agent.setThinkingLevel(toReasoningEffort(level));
|
|
5795
|
+
this.agent.setDisableReasoning(shouldDisableReasoning(level));
|
|
5796
|
+
}
|
|
5797
|
+
|
|
5692
5798
|
/**
|
|
5693
5799
|
* Set the thinking level. `auto` enables per-turn classification; the selector
|
|
5694
5800
|
* itself is never written to the session log, but resolved concrete levels are
|
|
@@ -5702,7 +5808,7 @@ export class AgentSession {
|
|
|
5702
5808
|
this.#autoThinking = true;
|
|
5703
5809
|
this.#autoResolvedLevel = undefined;
|
|
5704
5810
|
this.#thinkingLevel = provisional;
|
|
5705
|
-
this
|
|
5811
|
+
this.#applyThinkingLevelToAgent(provisional);
|
|
5706
5812
|
if (persist) {
|
|
5707
5813
|
this.settings.set("defaultThinkingLevel", AUTO_THINKING);
|
|
5708
5814
|
}
|
|
@@ -5718,7 +5824,7 @@ export class AgentSession {
|
|
|
5718
5824
|
const isChanging = effectiveLevel !== this.#thinkingLevel;
|
|
5719
5825
|
|
|
5720
5826
|
this.#thinkingLevel = effectiveLevel;
|
|
5721
|
-
this
|
|
5827
|
+
this.#applyThinkingLevelToAgent(effectiveLevel);
|
|
5722
5828
|
|
|
5723
5829
|
if (isChanging) {
|
|
5724
5830
|
this.sessionManager.appendThinkingLevelChange(effectiveLevel);
|
|
@@ -5808,7 +5914,7 @@ export class AgentSession {
|
|
|
5808
5914
|
const shouldPersistResolution = this.#autoResolvedLevel !== effort;
|
|
5809
5915
|
this.#autoResolvedLevel = effort;
|
|
5810
5916
|
this.#thinkingLevel = effort;
|
|
5811
|
-
this
|
|
5917
|
+
this.#applyThinkingLevelToAgent(effort);
|
|
5812
5918
|
if (shouldPersistResolution) {
|
|
5813
5919
|
this.sessionManager.appendThinkingLevelChange(effort);
|
|
5814
5920
|
}
|
|
@@ -6162,10 +6268,10 @@ export class AgentSession {
|
|
|
6162
6268
|
customInstructions,
|
|
6163
6269
|
compactionAbortController.signal,
|
|
6164
6270
|
{
|
|
6165
|
-
promptOverride: compactionPrep.hookPrompt,
|
|
6166
|
-
extraContext: compactionPrep.hookContext,
|
|
6167
|
-
remoteInstructions: this.#baseSystemPrompt.join("\n\n"),
|
|
6168
|
-
convertToLlm,
|
|
6271
|
+
promptOverride: this.#obfuscateTextForProvider(compactionPrep.hookPrompt),
|
|
6272
|
+
extraContext: this.#obfuscateForProvider(compactionPrep.hookContext),
|
|
6273
|
+
remoteInstructions: this.#obfuscateForProvider(this.#baseSystemPrompt.join("\n\n")),
|
|
6274
|
+
convertToLlm: messages => this.#convertToLlmForSideRequest(messages),
|
|
6169
6275
|
},
|
|
6170
6276
|
);
|
|
6171
6277
|
summary = result.summary;
|
|
@@ -6348,15 +6454,15 @@ export class AgentSession {
|
|
|
6348
6454
|
throw new Error(`No API key for ${model.provider}`);
|
|
6349
6455
|
}
|
|
6350
6456
|
|
|
6351
|
-
const
|
|
6457
|
+
const rawHandoffText = await generateHandoff(
|
|
6352
6458
|
this.agent.state.messages,
|
|
6353
6459
|
model,
|
|
6354
6460
|
apiKey,
|
|
6355
6461
|
{
|
|
6356
|
-
systemPrompt: this.#baseSystemPrompt,
|
|
6357
|
-
tools: this.agent.state.tools,
|
|
6358
|
-
customInstructions,
|
|
6359
|
-
convertToLlm,
|
|
6462
|
+
systemPrompt: this.#obfuscateForProvider(this.#baseSystemPrompt),
|
|
6463
|
+
tools: obfuscateProviderTools(this.#obfuscator, this.agent.state.tools),
|
|
6464
|
+
customInstructions: this.#obfuscateTextForProvider(customInstructions),
|
|
6465
|
+
convertToLlm: messages => this.#convertToLlmForSideRequest(messages),
|
|
6360
6466
|
initiatorOverride: "agent",
|
|
6361
6467
|
metadata: this.agent.metadataForProvider(model.provider),
|
|
6362
6468
|
telemetry: resolveTelemetry(this.agent.telemetry, this.sessionId),
|
|
@@ -6368,6 +6474,7 @@ export class AgentSession {
|
|
|
6368
6474
|
},
|
|
6369
6475
|
handoffSignal,
|
|
6370
6476
|
);
|
|
6477
|
+
const handoffText = this.#deobfuscateFromProvider(rawHandoffText);
|
|
6371
6478
|
|
|
6372
6479
|
if (handoffSignal.aborted) {
|
|
6373
6480
|
throw new Error("Handoff cancelled");
|
|
@@ -7329,17 +7436,24 @@ export class AgentSession {
|
|
|
7329
7436
|
if (!apiKey) continue;
|
|
7330
7437
|
|
|
7331
7438
|
try {
|
|
7332
|
-
return await compact(
|
|
7333
|
-
|
|
7334
|
-
|
|
7335
|
-
|
|
7336
|
-
|
|
7337
|
-
|
|
7338
|
-
|
|
7339
|
-
|
|
7340
|
-
|
|
7341
|
-
|
|
7342
|
-
|
|
7439
|
+
return await compact(
|
|
7440
|
+
this.#obfuscatePreparationForProvider(preparation),
|
|
7441
|
+
candidate,
|
|
7442
|
+
apiKey,
|
|
7443
|
+
this.#obfuscateTextForProvider(customInstructions),
|
|
7444
|
+
signal,
|
|
7445
|
+
{
|
|
7446
|
+
...options,
|
|
7447
|
+
metadata: this.agent.metadataForProvider(candidate.provider),
|
|
7448
|
+
convertToLlm: messages => this.#convertToLlmForSideRequest(messages),
|
|
7449
|
+
telemetry,
|
|
7450
|
+
// Honor the user's /model thinking selection (incl. `off`) on
|
|
7451
|
+
// the manual `/compact` path. Clamped per-model inside compact()
|
|
7452
|
+
// via resolveCompactionEffort so unsupported-effort models
|
|
7453
|
+
// (xai-oauth/grok-build) don't trip requireSupportedEffort.
|
|
7454
|
+
thinkingLevel: this.thinkingLevel,
|
|
7455
|
+
},
|
|
7456
|
+
);
|
|
7343
7457
|
} catch (error) {
|
|
7344
7458
|
if (!this.#isCompactionAuthFailure(error)) {
|
|
7345
7459
|
throw error;
|
|
@@ -7619,20 +7733,27 @@ export class AgentSession {
|
|
|
7619
7733
|
let attempt = 0;
|
|
7620
7734
|
while (true) {
|
|
7621
7735
|
try {
|
|
7622
|
-
compactResult = await compact(
|
|
7623
|
-
|
|
7624
|
-
|
|
7625
|
-
|
|
7626
|
-
|
|
7627
|
-
|
|
7628
|
-
|
|
7629
|
-
|
|
7630
|
-
|
|
7631
|
-
|
|
7632
|
-
|
|
7633
|
-
|
|
7634
|
-
|
|
7635
|
-
|
|
7736
|
+
compactResult = await compact(
|
|
7737
|
+
this.#obfuscatePreparationForProvider(preparation),
|
|
7738
|
+
candidate,
|
|
7739
|
+
apiKey,
|
|
7740
|
+
undefined,
|
|
7741
|
+
autoCompactionSignal,
|
|
7742
|
+
{
|
|
7743
|
+
promptOverride: this.#obfuscateTextForProvider(compactionPrep.hookPrompt),
|
|
7744
|
+
extraContext: this.#obfuscateForProvider(compactionPrep.hookContext),
|
|
7745
|
+
remoteInstructions: this.#obfuscateForProvider(this.#baseSystemPrompt.join("\n\n")),
|
|
7746
|
+
metadata: this.agent.metadataForProvider(candidate.provider),
|
|
7747
|
+
initiatorOverride: "agent",
|
|
7748
|
+
convertToLlm: messages => this.#convertToLlmForSideRequest(messages),
|
|
7749
|
+
telemetry,
|
|
7750
|
+
// Honor the user's /model thinking selection on the
|
|
7751
|
+
// auto-compaction path — the most-fired compaction
|
|
7752
|
+
// site. Clamped per-model inside compact() via
|
|
7753
|
+
// resolveCompactionEffort.
|
|
7754
|
+
thinkingLevel: this.thinkingLevel,
|
|
7755
|
+
},
|
|
7756
|
+
);
|
|
7636
7757
|
break;
|
|
7637
7758
|
} catch (error) {
|
|
7638
7759
|
if (autoCompactionSignal.aborted) {
|
|
@@ -8307,26 +8428,46 @@ export class AgentSession {
|
|
|
8307
8428
|
|
|
8308
8429
|
const errorMessage = message.errorMessage || "Unknown error";
|
|
8309
8430
|
const parsedRetryAfterMs = this.#parseRetryAfterMsFromError(errorMessage);
|
|
8310
|
-
let delayMs = retrySettings.baseDelayMs
|
|
8431
|
+
let delayMs = calculateRetryBackoffDelayMs(retrySettings.baseDelayMs, this.#retryAttempt);
|
|
8311
8432
|
let switchedCredential = false;
|
|
8312
8433
|
let switchedModel = false;
|
|
8434
|
+
// Set when a usage-limit error pinned the wait to credential
|
|
8435
|
+
// availability — suppresses the generic retry-after bump below.
|
|
8436
|
+
let usageLimitWaitMs: number | undefined;
|
|
8313
8437
|
|
|
8314
8438
|
if (this.model && isUsageLimitError(errorMessage)) {
|
|
8315
8439
|
const retryAfterMs = parsedRetryAfterMs ?? calculateRateLimitBackoffMs(parseRateLimitReason(errorMessage));
|
|
8316
|
-
const
|
|
8440
|
+
const outcome = await this.#modelRegistry.authStorage.markUsageLimitReached(
|
|
8317
8441
|
this.model.provider,
|
|
8318
8442
|
this.sessionId,
|
|
8319
8443
|
{
|
|
8320
8444
|
retryAfterMs,
|
|
8321
8445
|
baseUrl: this.model.baseUrl,
|
|
8446
|
+
modelId: this.model.id,
|
|
8322
8447
|
},
|
|
8323
8448
|
);
|
|
8324
|
-
if (switched) {
|
|
8449
|
+
if (outcome.switched) {
|
|
8325
8450
|
switchedCredential = true;
|
|
8326
8451
|
delayMs = 0;
|
|
8327
|
-
} else
|
|
8328
|
-
// No
|
|
8329
|
-
|
|
8452
|
+
} else {
|
|
8453
|
+
// No sibling credential is usable right now. Wait for whichever
|
|
8454
|
+
// comes first: the provider's retry-after window for the current
|
|
8455
|
+
// account, or the earliest moment a temporarily blocked sibling
|
|
8456
|
+
// frees up (e.g. a 60s post-401 block or a 5-min usage-probe
|
|
8457
|
+
// block) — the next attempt's getApiKey re-ranks and picks it up.
|
|
8458
|
+
// Without this, one short-lived sibling block escalates a
|
|
8459
|
+
// recoverable situation into the provider's multi-hour wait and
|
|
8460
|
+
// trips the fail-fast cap below.
|
|
8461
|
+
usageLimitWaitMs = retryAfterMs;
|
|
8462
|
+
if (outcome.retryAtMs !== undefined) {
|
|
8463
|
+
const siblingWaitMs = Math.max(0, outcome.retryAtMs - Date.now()) + SIBLING_UNBLOCK_BUFFER_MS;
|
|
8464
|
+
if (siblingWaitMs < usageLimitWaitMs) {
|
|
8465
|
+
usageLimitWaitMs = siblingWaitMs;
|
|
8466
|
+
}
|
|
8467
|
+
}
|
|
8468
|
+
if (usageLimitWaitMs > delayMs) {
|
|
8469
|
+
delayMs = usageLimitWaitMs;
|
|
8470
|
+
}
|
|
8330
8471
|
}
|
|
8331
8472
|
}
|
|
8332
8473
|
|
|
@@ -8338,7 +8479,7 @@ export class AgentSession {
|
|
|
8338
8479
|
}
|
|
8339
8480
|
if (switchedModel) {
|
|
8340
8481
|
delayMs = 0;
|
|
8341
|
-
} else if (parsedRetryAfterMs && parsedRetryAfterMs > delayMs) {
|
|
8482
|
+
} else if (usageLimitWaitMs === undefined && parsedRetryAfterMs && parsedRetryAfterMs > delayMs) {
|
|
8342
8483
|
delayMs = parsedRetryAfterMs;
|
|
8343
8484
|
}
|
|
8344
8485
|
}
|
|
@@ -8499,11 +8640,12 @@ export class AgentSession {
|
|
|
8499
8640
|
* @param command The bash command to execute
|
|
8500
8641
|
* @param onChunk Optional streaming callback for output
|
|
8501
8642
|
* @param options.excludeFromContext If true, command output won't be sent to LLM (!! prefix)
|
|
8643
|
+
* @param options.useUserShell If true, allow caller to request configured user-shell routing
|
|
8502
8644
|
*/
|
|
8503
8645
|
async executeBash(
|
|
8504
8646
|
command: string,
|
|
8505
8647
|
onChunk?: (chunk: string) => void,
|
|
8506
|
-
options?: { excludeFromContext?: boolean },
|
|
8648
|
+
options?: { excludeFromContext?: boolean; useUserShell?: boolean },
|
|
8507
8649
|
): Promise<BashResult> {
|
|
8508
8650
|
const excludeFromContext = options?.excludeFromContext === true;
|
|
8509
8651
|
const cwd = this.sessionManager.getCwd();
|
|
@@ -8531,6 +8673,7 @@ export class AgentSession {
|
|
|
8531
8673
|
sessionKey: this.sessionId,
|
|
8532
8674
|
timeout: clampTimeout("bash") * 1000,
|
|
8533
8675
|
onMinimizedSave: originalText => this.#saveBashOriginalArtifact(originalText),
|
|
8676
|
+
useUserShell: options?.useUserShell,
|
|
8534
8677
|
});
|
|
8535
8678
|
|
|
8536
8679
|
this.recordBashResult(command, result, options);
|
|
@@ -8656,6 +8799,7 @@ export class AgentSession {
|
|
|
8656
8799
|
sessionId: namespacePythonSessionId(sessionId),
|
|
8657
8800
|
kernelOwnerId: this.#evalKernelOwnerId,
|
|
8658
8801
|
kernelMode: this.settings.get("python.kernelMode"),
|
|
8802
|
+
interpreter: this.settings.get("python.interpreter")?.trim() || undefined,
|
|
8659
8803
|
onChunk,
|
|
8660
8804
|
signal: abortController.signal,
|
|
8661
8805
|
});
|
|
@@ -8948,6 +9092,7 @@ export class AgentSession {
|
|
|
8948
9092
|
promptCacheKey: cacheSessionId,
|
|
8949
9093
|
preferWebsockets: false,
|
|
8950
9094
|
reasoning: toReasoningEffort(this.thinkingLevel),
|
|
9095
|
+
disableReasoning: shouldDisableReasoning(this.thinkingLevel),
|
|
8951
9096
|
hideThinkingSummary: this.agent.hideThinkingSummary,
|
|
8952
9097
|
serviceTier: this.serviceTier,
|
|
8953
9098
|
signal: args.signal,
|
|
@@ -8956,17 +9101,27 @@ export class AgentSession {
|
|
|
8956
9101
|
model.provider,
|
|
8957
9102
|
);
|
|
8958
9103
|
|
|
8959
|
-
let
|
|
9104
|
+
let providerReplyText = "";
|
|
9105
|
+
let emittedReplyText = "";
|
|
8960
9106
|
let assistantMessage: AssistantMessage | undefined;
|
|
8961
|
-
const stream = streamSimple(model, context, options);
|
|
9107
|
+
const stream = streamSimple(model, obfuscateProviderContext(this.#obfuscator, context), options);
|
|
8962
9108
|
for await (const event of stream) {
|
|
8963
9109
|
if (event.type === "text_delta") {
|
|
8964
|
-
|
|
8965
|
-
if (args.onTextDelta)
|
|
9110
|
+
providerReplyText += event.delta;
|
|
9111
|
+
if (args.onTextDelta) {
|
|
9112
|
+
const readyText = this.#deobfuscatedProviderTextReadyForDelta(providerReplyText);
|
|
9113
|
+
if (readyText.length > emittedReplyText.length) {
|
|
9114
|
+
const delta = readyText.slice(emittedReplyText.length);
|
|
9115
|
+
emittedReplyText = readyText;
|
|
9116
|
+
args.onTextDelta(delta);
|
|
9117
|
+
}
|
|
9118
|
+
}
|
|
8966
9119
|
continue;
|
|
8967
9120
|
}
|
|
8968
9121
|
if (event.type === "done") {
|
|
8969
|
-
assistantMessage =
|
|
9122
|
+
assistantMessage = this.#obfuscator?.hasSecrets()
|
|
9123
|
+
? { ...event.message, content: this.#obfuscator.deobfuscateObject(event.message.content) }
|
|
9124
|
+
: event.message;
|
|
8970
9125
|
break;
|
|
8971
9126
|
}
|
|
8972
9127
|
if (event.type === "error") {
|
|
@@ -8977,6 +9132,10 @@ export class AgentSession {
|
|
|
8977
9132
|
if (!assistantMessage) {
|
|
8978
9133
|
throw new Error("Ephemeral turn ended without a final message");
|
|
8979
9134
|
}
|
|
9135
|
+
const replyText = this.#deobfuscateFromProvider(providerReplyText);
|
|
9136
|
+
if (args.onTextDelta && replyText.length > emittedReplyText.length) {
|
|
9137
|
+
args.onTextDelta(replyText.slice(emittedReplyText.length));
|
|
9138
|
+
}
|
|
8980
9139
|
return {
|
|
8981
9140
|
replyText: args.dedupeReply === false ? replyText.trim() : dedupeIrcReply(replyText.trim()),
|
|
8982
9141
|
assistantMessage,
|
|
@@ -9236,7 +9395,7 @@ export class AgentSession {
|
|
|
9236
9395
|
this.#autoResolvedLevel = undefined;
|
|
9237
9396
|
this.#thinkingLevel = resolveThinkingLevelForModel(this.model, restoredThinkingLevel);
|
|
9238
9397
|
}
|
|
9239
|
-
this
|
|
9398
|
+
this.#applyThinkingLevelToAgent(this.#thinkingLevel);
|
|
9240
9399
|
this.agent.serviceTier = hasServiceTierEntry
|
|
9241
9400
|
? sessionContext.serviceTier
|
|
9242
9401
|
: configuredServiceTier === "none"
|
|
@@ -9293,7 +9452,7 @@ export class AgentSession {
|
|
|
9293
9452
|
this.#thinkingLevel = previousThinkingLevel;
|
|
9294
9453
|
this.#autoThinking = previousAutoThinking;
|
|
9295
9454
|
this.#autoResolvedLevel = previousAutoResolvedLevel;
|
|
9296
|
-
this
|
|
9455
|
+
this.#applyThinkingLevelToAgent(previousThinkingLevel);
|
|
9297
9456
|
this.agent.serviceTier = previousServiceTier;
|
|
9298
9457
|
this.#syncTodoPhasesFromBranch();
|
|
9299
9458
|
this.#reconnectToAgent();
|
|
@@ -9477,10 +9636,10 @@ export class AgentSession {
|
|
|
9477
9636
|
model,
|
|
9478
9637
|
apiKey,
|
|
9479
9638
|
signal: this.#branchSummaryAbortController.signal,
|
|
9480
|
-
customInstructions: options.customInstructions,
|
|
9639
|
+
customInstructions: this.#obfuscateTextForProvider(options.customInstructions),
|
|
9481
9640
|
reserveTokens: branchSummarySettings.reserveTokens,
|
|
9482
9641
|
metadata: this.agent.metadataForProvider(model.provider),
|
|
9483
|
-
convertToLlm,
|
|
9642
|
+
convertToLlm: messages => this.#convertToLlmForSideRequest(messages),
|
|
9484
9643
|
telemetry: resolveTelemetry(this.agent.telemetry, this.sessionId),
|
|
9485
9644
|
});
|
|
9486
9645
|
this.#branchSummaryAbortController = undefined;
|
|
@@ -65,13 +65,42 @@ async function readConfigYaml(): Promise<ConfigSnapshot> {
|
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
/**
|
|
69
|
+
* Process-lifetime memo for {@link resolveAuthBrokerConfig}. Keyed on the env
|
|
70
|
+
* inputs (plus agent dir, which decides which config.yml is read) so tests
|
|
71
|
+
* that flip `OMP_AUTH_BROKER_*` between cases still observe the change, while
|
|
72
|
+
* repeated resolution within one CLI invocation (startup, subagent sessions)
|
|
73
|
+
* skips the config.yml read and any `!command` token resolution.
|
|
74
|
+
*/
|
|
75
|
+
let cachedConfigKey: string | null = null;
|
|
76
|
+
let cachedConfigPromise: Promise<AuthBrokerClientConfig | null> | null = null;
|
|
77
|
+
|
|
68
78
|
/**
|
|
69
79
|
* Read broker configuration. Returns null when the URL is missing
|
|
70
80
|
* (broker disabled — local store is used). Throws when URL is set but no
|
|
71
81
|
* token is available — the caller cannot fall back silently because the
|
|
72
82
|
* user explicitly asked to use the broker.
|
|
83
|
+
*
|
|
84
|
+
* Successful resolutions (including "no broker configured") are memoized for
|
|
85
|
+
* the process lifetime; failures are not, so a missing token can be fixed and
|
|
86
|
+
* retried. Concurrent callers share one in-flight resolution.
|
|
73
87
|
*/
|
|
74
|
-
export
|
|
88
|
+
export function resolveAuthBrokerConfig(): Promise<AuthBrokerClientConfig | null> {
|
|
89
|
+
const key = `${process.env.OMP_AUTH_BROKER_URL ?? ""}\u0000${process.env.OMP_AUTH_BROKER_TOKEN ?? ""}\u0000${getAgentDir()}`;
|
|
90
|
+
if (cachedConfigPromise && cachedConfigKey === key) return cachedConfigPromise;
|
|
91
|
+
const promise = resolveAuthBrokerConfigUncached();
|
|
92
|
+
cachedConfigKey = key;
|
|
93
|
+
cachedConfigPromise = promise;
|
|
94
|
+
promise.catch(() => {
|
|
95
|
+
if (cachedConfigPromise === promise) {
|
|
96
|
+
cachedConfigPromise = null;
|
|
97
|
+
cachedConfigKey = null;
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
return promise;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async function resolveAuthBrokerConfigUncached(): Promise<AuthBrokerClientConfig | null> {
|
|
75
104
|
const envUrl = process.env.OMP_AUTH_BROKER_URL;
|
|
76
105
|
const envToken = process.env.OMP_AUTH_BROKER_TOKEN;
|
|
77
106
|
|
|
@@ -1516,10 +1516,10 @@ class NdjsonFileWriter {
|
|
|
1516
1516
|
}
|
|
1517
1517
|
}
|
|
1518
1518
|
|
|
1519
|
-
/** Get recent sessions for display in welcome screen */
|
|
1519
|
+
/** Get recent sessions for display in welcome screen (which reserves WELCOME_SESSION_SLOTS rows) */
|
|
1520
1520
|
export async function getRecentSessions(
|
|
1521
1521
|
sessionDir: string,
|
|
1522
|
-
limit =
|
|
1522
|
+
limit = 4,
|
|
1523
1523
|
storage: SessionStorage = new FileSessionStorage(),
|
|
1524
1524
|
): Promise<RecentSessionInfo[]> {
|
|
1525
1525
|
const sessions = await getSortedSessions(sessionDir, storage);
|