lsd-pi 1.2.4 → 1.3.6
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/README.md +22 -16
- package/dist/app-paths.d.ts +4 -0
- package/dist/app-paths.js +4 -0
- package/dist/bedrock-auth.d.ts +4 -0
- package/dist/bedrock-auth.js +4 -0
- package/dist/bundled-extension-paths.d.ts +4 -0
- package/dist/bundled-extension-paths.js +4 -0
- package/dist/cli-theme.d.ts +2 -2
- package/dist/cli-theme.js +13 -14
- package/dist/cli.js +43 -3
- package/dist/codex-rotate-settings.d.ts +4 -0
- package/dist/codex-rotate-settings.js +4 -0
- package/dist/help-text.d.ts +4 -0
- package/dist/help-text.js +4 -0
- package/dist/lsd-brand.d.ts +4 -0
- package/dist/lsd-brand.js +4 -0
- package/dist/onboarding-llm.d.ts +5 -0
- package/dist/onboarding-llm.js +5 -0
- package/dist/project-sessions.d.ts +4 -0
- package/dist/project-sessions.js +4 -0
- package/dist/resources/agents/generic.md +1 -0
- package/dist/resources/agents/scout.md +8 -1
- package/dist/resources/agents/worker.md +1 -0
- package/dist/resources/extensions/ask-user-questions.js +70 -0
- package/dist/resources/extensions/bg-shell/bg-shell-tool.js +6 -16
- package/dist/resources/extensions/browser-tools/tools/codegen.js +5 -5
- package/dist/resources/extensions/browser-tools/tools/navigation.js +107 -178
- package/dist/resources/extensions/browser-tools/tools/network-mock.js +112 -167
- package/dist/resources/extensions/browser-tools/tools/pages.js +182 -234
- package/dist/resources/extensions/browser-tools/tools/refs.js +202 -461
- package/dist/resources/extensions/browser-tools/tools/session.js +176 -323
- package/dist/resources/extensions/browser-tools/tools/state-persistence.js +91 -154
- package/dist/resources/extensions/browser-tools/utils.js +1 -1
- package/dist/resources/extensions/mac-tools/index.js +19 -34
- package/dist/resources/extensions/memory/index.js +20 -2
- package/dist/resources/extensions/shared/interview-ui.js +103 -20
- package/dist/resources/extensions/slash-commands/extension-manifest.json +2 -2
- package/dist/resources/extensions/slash-commands/fast.js +73 -0
- package/dist/resources/extensions/slash-commands/index.js +2 -0
- package/dist/resources/extensions/slash-commands/plan.js +54 -28
- package/dist/resources/extensions/slash-commands/tools.js +40 -4
- package/dist/resources/extensions/subagent/agent-switcher-component.js +208 -0
- package/dist/resources/extensions/subagent/agent-switcher-model.js +107 -0
- package/dist/resources/extensions/subagent/background-job-manager.js +24 -6
- package/dist/resources/extensions/subagent/background-runner.js +4 -0
- package/dist/resources/extensions/subagent/in-process-runner.js +387 -0
- package/dist/resources/extensions/subagent/index.js +715 -370
- package/dist/resources/extensions/subagent/launch-helpers.js +19 -5
- package/dist/resources/extensions/subagent/legacy-runner.js +503 -0
- package/dist/resources/extensions/voice/index.js +96 -36
- package/dist/resources/extensions/voice/push-to-talk.js +26 -0
- package/dist/shared-paths.d.ts +4 -0
- package/dist/shared-paths.js +4 -0
- package/dist/shared-preferences.d.ts +4 -0
- package/dist/shared-preferences.js +4 -0
- package/dist/startup-model-validation.d.ts +1 -1
- package/dist/startup-timings.d.ts +4 -0
- package/dist/startup-timings.js +4 -0
- package/dist/update-check.d.ts +4 -0
- package/dist/update-check.js +4 -0
- package/dist/update-cmd.d.ts +4 -0
- package/dist/update-cmd.js +4 -0
- package/dist/welcome-screen.js +4 -4
- package/dist/wizard.d.ts +4 -0
- package/dist/wizard.js +4 -0
- package/package.json +1 -1
- package/packages/pi-agent-core/dist/agent.d.ts +28 -0
- package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/agent.js +105 -5
- package/packages/pi-agent-core/dist/agent.js.map +1 -1
- package/packages/pi-agent-core/dist/types.d.ts +13 -2
- package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/types.js.map +1 -1
- package/packages/pi-agent-core/src/agent.ts +142 -6
- package/packages/pi-agent-core/src/types.ts +12 -3
- package/packages/pi-ai/dist/adaptive/classifier.d.ts +29 -0
- package/packages/pi-ai/dist/adaptive/classifier.d.ts.map +1 -0
- package/packages/pi-ai/dist/adaptive/classifier.js +72 -0
- package/packages/pi-ai/dist/adaptive/classifier.js.map +1 -0
- package/packages/pi-ai/dist/adaptive/classifier.test.d.ts +2 -0
- package/packages/pi-ai/dist/adaptive/classifier.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/adaptive/classifier.test.js +32 -0
- package/packages/pi-ai/dist/adaptive/classifier.test.js.map +1 -0
- package/packages/pi-ai/dist/index.d.ts +1 -0
- package/packages/pi-ai/dist/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/index.js +1 -0
- package/packages/pi-ai/dist/index.js.map +1 -1
- package/packages/pi-ai/dist/providers/amazon-bedrock.js +0 -2
- package/packages/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.js +0 -2
- package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
- package/packages/pi-ai/dist/providers/azure-openai-responses.d.ts +1 -1
- package/packages/pi-ai/dist/providers/azure-openai-responses.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/azure-openai-responses.js.map +1 -1
- package/packages/pi-ai/dist/providers/google-gemini-cli.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/google-gemini-cli.js +0 -4
- package/packages/pi-ai/dist/providers/google-gemini-cli.js.map +1 -1
- package/packages/pi-ai/dist/providers/google-vertex.js +0 -5
- package/packages/pi-ai/dist/providers/google-vertex.js.map +1 -1
- package/packages/pi-ai/dist/providers/google.js +0 -5
- package/packages/pi-ai/dist/providers/google.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.d.ts +35 -2
- package/packages/pi-ai/dist/providers/openai-codex-responses.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.js +32 -6
- package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.test.js +127 -16
- package/packages/pi-ai/dist/providers/openai-codex-responses.test.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.d.ts +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.js +0 -1
- package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-responses.d.ts +9 -2
- package/packages/pi-ai/dist/providers/openai-responses.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-responses.fast-mode.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/openai-responses.fast-mode.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/openai-responses.fast-mode.test.js +67 -0
- package/packages/pi-ai/dist/providers/openai-responses.fast-mode.test.js.map +1 -0
- package/packages/pi-ai/dist/providers/openai-responses.js +21 -3
- package/packages/pi-ai/dist/providers/openai-responses.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-shared.d.ts +0 -1
- package/packages/pi-ai/dist/providers/openai-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-shared.js +0 -4
- package/packages/pi-ai/dist/providers/openai-shared.js.map +1 -1
- package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/simple-options.js +2 -1
- package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
- package/packages/pi-ai/dist/types.d.ts +6 -2
- package/packages/pi-ai/dist/types.d.ts.map +1 -1
- package/packages/pi-ai/dist/types.js.map +1 -1
- package/packages/pi-ai/src/adaptive/classifier.test.ts +38 -0
- package/packages/pi-ai/src/adaptive/classifier.ts +107 -0
- package/packages/pi-ai/src/index.ts +1 -0
- package/packages/pi-ai/src/providers/amazon-bedrock.ts +0 -2
- package/packages/pi-ai/src/providers/anthropic-shared.ts +0 -2
- package/packages/pi-ai/src/providers/azure-openai-responses.ts +1 -1
- package/packages/pi-ai/src/providers/google-gemini-cli.ts +0 -4
- package/packages/pi-ai/src/providers/google-vertex.ts +0 -5
- package/packages/pi-ai/src/providers/google.ts +0 -5
- package/packages/pi-ai/src/providers/openai-codex-responses.test.ts +143 -20
- package/packages/pi-ai/src/providers/openai-codex-responses.ts +48 -7
- package/packages/pi-ai/src/providers/openai-completions.ts +1 -2
- package/packages/pi-ai/src/providers/openai-responses.fast-mode.test.ts +73 -0
- package/packages/pi-ai/src/providers/openai-responses.ts +27 -4
- package/packages/pi-ai/src/providers/openai-shared.ts +0 -3
- package/packages/pi-ai/src/providers/simple-options.ts +2 -1
- package/packages/pi-ai/src/types.ts +6 -2
- package/packages/pi-coding-agent/dist/cli/args.js +2 -2
- package/packages/pi-coding-agent/dist/cli/args.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts +7 -2
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +53 -20
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/keybindings.d.ts +1 -1
- package/packages/pi-coding-agent/dist/core/keybindings.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/keybindings.js +2 -0
- package/packages/pi-coding-agent/dist/core/keybindings.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/lsp.md +3 -1
- package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js +36 -8
- package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.test.js +37 -0
- package/packages/pi-coding-agent/dist/core/sdk.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/session-manager.d.ts +8 -0
- package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/session-manager.js +4 -0
- package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +18 -7
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.fast-mode.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.fast-mode.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.fast-mode.test.js +35 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.fast-mode.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.js +32 -2
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/skills.js +4 -1
- package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/slash-commands.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/slash-commands.js +2 -1
- package/packages/pi-coding-agent/dist/core/slash-commands.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +12 -3
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tool-priority.d.ts +4 -0
- package/packages/pi-coding-agent/dist/core/tool-priority.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/tool-priority.js +18 -0
- package/packages/pi-coding-agent/dist/core/tool-priority.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/tool-priority.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/tool-priority.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/tool-priority.test.js +27 -0
- package/packages/pi-coding-agent/dist/core/tool-priority.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/tools/grep.js +1 -1
- package/packages/pi-coding-agent/dist/core/tools/grep.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/index.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/tools/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/index.js +2 -0
- package/packages/pi-coding-agent/dist/core/tools/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/pty.d.ts +10 -1
- package/packages/pi-coding-agent/dist/core/tools/pty.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/pty.js +29 -3
- package/packages/pi-coding-agent/dist/core/tools/pty.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-summary-line.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-summary-line.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-summary-line.test.js +26 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-summary-line.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/btw-overlay.d.ts +45 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/btw-overlay.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/btw-overlay.js +314 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/btw-overlay.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/btw-overlay.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/btw-overlay.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/btw-overlay.test.js +122 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/btw-overlay.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/embedded-terminal.js +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/embedded-terminal.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +19 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +11 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +49 -6
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/thinking-selector.js +1 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/thinking-selector.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +6 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +18 -4
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-summary-line.d.ts +13 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-summary-line.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-summary-line.js +49 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-summary-line.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/__tests__/chat-controller.collapsed-tool-summary.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/__tests__/chat-controller.collapsed-tool-summary.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/__tests__/chat-controller.collapsed-tool-summary.test.js +197 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/__tests__/chat-controller.collapsed-tool-summary.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +106 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +7 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +3 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +4 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +88 -2
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +41 -0
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts +2 -2
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js +10 -6
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/print-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/print-mode.js +6 -0
- package/packages/pi-coding-agent/dist/modes/print-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js +20 -0
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/tests/path-display.test.js +15 -0
- package/packages/pi-coding-agent/dist/tests/path-display.test.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/cli/args.ts +2 -2
- package/packages/pi-coding-agent/src/core/agent-session.ts +58 -21
- package/packages/pi-coding-agent/src/core/keybindings.ts +4 -1
- package/packages/pi-coding-agent/src/core/lsp/lsp.md +3 -1
- package/packages/pi-coding-agent/src/core/sdk.test.ts +45 -0
- package/packages/pi-coding-agent/src/core/sdk.ts +39 -8
- package/packages/pi-coding-agent/src/core/session-manager.ts +12 -0
- package/packages/pi-coding-agent/src/core/settings-manager.fast-mode.test.ts +46 -0
- package/packages/pi-coding-agent/src/core/settings-manager.ts +50 -9
- package/packages/pi-coding-agent/src/core/skills.ts +4 -1
- package/packages/pi-coding-agent/src/core/slash-commands.ts +2 -1
- package/packages/pi-coding-agent/src/core/system-prompt.ts +14 -3
- package/packages/pi-coding-agent/src/core/tool-priority.test.ts +30 -0
- package/packages/pi-coding-agent/src/core/tool-priority.ts +17 -0
- package/packages/pi-coding-agent/src/core/tools/grep.ts +1 -1
- package/packages/pi-coding-agent/src/core/tools/index.ts +3 -0
- package/packages/pi-coding-agent/src/core/tools/pty.ts +45 -6
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-summary-line.test.ts +31 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/btw-overlay.test.ts +172 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/btw-overlay.ts +402 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/embedded-terminal.ts +1 -1
- package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +18 -2
- package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +63 -9
- package/packages/pi-coding-agent/src/modes/interactive/components/thinking-selector.ts +1 -2
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +1154 -1136
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-summary-line.ts +64 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/__tests__/chat-controller.collapsed-tool-summary.test.ts +228 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +494 -389
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +7 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +3 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +103 -3
- package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +60 -1
- package/packages/pi-coding-agent/src/modes/interactive/theme/theme.ts +11 -7
- package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +1 -1
- package/packages/pi-coding-agent/src/modes/print-mode.ts +6 -0
- package/packages/pi-coding-agent/src/modes/rpc/rpc-mode.ts +29 -0
- package/packages/pi-coding-agent/src/tests/path-display.test.ts +17 -0
- package/packages/pi-tui/dist/components/loader.d.ts +5 -2
- package/packages/pi-tui/dist/components/loader.d.ts.map +1 -1
- package/packages/pi-tui/dist/components/loader.js +33 -3
- package/packages/pi-tui/dist/components/loader.js.map +1 -1
- package/packages/pi-tui/src/components/loader.ts +31 -3
- package/packages/rpc-client/src/index.ts +1 -1
- package/packages/rpc-client/src/rpc-client.ts +29 -0
- package/packages/rpc-client/src/rpc-types.ts +1 -1
- package/pkg/dist/modes/interactive/theme/theme.d.ts +2 -2
- package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/pkg/dist/modes/interactive/theme/theme.js +10 -6
- package/pkg/dist/modes/interactive/theme/theme.js.map +1 -1
- package/pkg/dist/modes/interactive/theme/themes.js +1 -1
- package/pkg/dist/modes/interactive/theme/themes.js.map +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/agents/generic.md +1 -0
- package/src/resources/agents/scout.md +8 -1
- package/src/resources/agents/worker.md +1 -0
- package/src/resources/extensions/ask-user-questions.ts +88 -0
- package/src/resources/extensions/bg-shell/bg-shell-tool.ts +6 -16
- package/src/resources/extensions/browser-tools/tools/codegen.ts +5 -5
- package/src/resources/extensions/browser-tools/tools/navigation.ts +118 -196
- package/src/resources/extensions/browser-tools/tools/network-mock.ts +114 -205
- package/src/resources/extensions/browser-tools/tools/pages.ts +183 -237
- package/src/resources/extensions/browser-tools/tools/refs.ts +193 -507
- package/src/resources/extensions/browser-tools/tools/session.ts +182 -321
- package/src/resources/extensions/browser-tools/tools/state-persistence.ts +94 -172
- package/src/resources/extensions/browser-tools/utils.ts +1 -1
- package/src/resources/extensions/mac-tools/index.ts +19 -34
- package/src/resources/extensions/memory/index.ts +22 -2
- package/src/resources/extensions/shared/interview-ui.ts +108 -15
- package/src/resources/extensions/shared/tests/ask-user-freetext.test.ts +61 -0
- package/src/resources/extensions/shared/tests/custom-ui-fallbacks.test.ts +46 -0
- package/src/resources/extensions/slash-commands/extension-manifest.json +2 -2
- package/src/resources/extensions/slash-commands/fast.ts +89 -0
- package/src/resources/extensions/slash-commands/index.ts +2 -0
- package/src/resources/extensions/slash-commands/plan.ts +59 -30
- package/src/resources/extensions/slash-commands/tools.ts +43 -4
- package/src/resources/extensions/subagent/agent-switcher-component.ts +228 -0
- package/src/resources/extensions/subagent/agent-switcher-model.ts +160 -0
- package/src/resources/extensions/subagent/background-job-manager.ts +57 -6
- package/src/resources/extensions/subagent/background-runner.ts +8 -0
- package/src/resources/extensions/subagent/background-types.ts +4 -0
- package/src/resources/extensions/subagent/in-process-runner.ts +534 -0
- package/src/resources/extensions/subagent/index.ts +998 -493
- package/src/resources/extensions/subagent/launch-helpers.ts +15 -4
- package/src/resources/extensions/subagent/legacy-runner.ts +607 -0
- package/src/resources/extensions/voice/index.ts +308 -238
- package/src/resources/extensions/voice/push-to-talk.ts +42 -0
- package/src/resources/extensions/voice/tests/push-to-talk.test.ts +109 -0
|
@@ -447,7 +447,6 @@ function getGemini3ThinkingLevel(
|
|
|
447
447
|
): GoogleThinkingLevel {
|
|
448
448
|
if (isGemini3ProModel(model)) {
|
|
449
449
|
switch (effort) {
|
|
450
|
-
case "minimal":
|
|
451
450
|
case "low":
|
|
452
451
|
return "LOW";
|
|
453
452
|
case "medium":
|
|
@@ -456,8 +455,6 @@ function getGemini3ThinkingLevel(
|
|
|
456
455
|
}
|
|
457
456
|
}
|
|
458
457
|
switch (effort) {
|
|
459
|
-
case "minimal":
|
|
460
|
-
return "MINIMAL";
|
|
461
458
|
case "low":
|
|
462
459
|
return "LOW";
|
|
463
460
|
case "medium":
|
|
@@ -480,7 +477,6 @@ function getGoogleBudget(
|
|
|
480
477
|
|
|
481
478
|
if (model.id.includes("2.5-pro")) {
|
|
482
479
|
const budgets: Record<ClampedThinkingLevel, number> = {
|
|
483
|
-
minimal: 128,
|
|
484
480
|
low: 2048,
|
|
485
481
|
medium: 8192,
|
|
486
482
|
high: 32768,
|
|
@@ -490,7 +486,6 @@ function getGoogleBudget(
|
|
|
490
486
|
|
|
491
487
|
if (model.id.includes("2.5-flash")) {
|
|
492
488
|
const budgets: Record<ClampedThinkingLevel, number> = {
|
|
493
|
-
minimal: 128,
|
|
494
489
|
low: 2048,
|
|
495
490
|
medium: 8192,
|
|
496
491
|
high: 24576,
|
|
@@ -414,7 +414,6 @@ function getGemini3ThinkingLevel(
|
|
|
414
414
|
): GoogleThinkingLevel {
|
|
415
415
|
if (isGemini3ProModel(model)) {
|
|
416
416
|
switch (effort) {
|
|
417
|
-
case "minimal":
|
|
418
417
|
case "low":
|
|
419
418
|
return "LOW";
|
|
420
419
|
case "medium":
|
|
@@ -423,8 +422,6 @@ function getGemini3ThinkingLevel(
|
|
|
423
422
|
}
|
|
424
423
|
}
|
|
425
424
|
switch (effort) {
|
|
426
|
-
case "minimal":
|
|
427
|
-
return "MINIMAL";
|
|
428
425
|
case "low":
|
|
429
426
|
return "LOW";
|
|
430
427
|
case "medium":
|
|
@@ -447,7 +444,6 @@ function getGoogleBudget(
|
|
|
447
444
|
|
|
448
445
|
if (model.id.includes("2.5-pro")) {
|
|
449
446
|
const budgets: Record<ClampedThinkingLevel, number> = {
|
|
450
|
-
minimal: 128,
|
|
451
447
|
low: 2048,
|
|
452
448
|
medium: 8192,
|
|
453
449
|
high: 32768,
|
|
@@ -457,7 +453,6 @@ function getGoogleBudget(
|
|
|
457
453
|
|
|
458
454
|
if (model.id.includes("2.5-flash")) {
|
|
459
455
|
const budgets: Record<ClampedThinkingLevel, number> = {
|
|
460
|
-
minimal: 128,
|
|
461
456
|
low: 2048,
|
|
462
457
|
medium: 8192,
|
|
463
458
|
high: 24576,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
2
|
import test from "node:test";
|
|
3
3
|
|
|
4
|
-
import { streamSimpleOpenAICodexResponses } from "./openai-codex-responses.js";
|
|
4
|
+
import { __testing, streamSimpleOpenAICodexResponses } from "./openai-codex-responses.js";
|
|
5
5
|
|
|
6
6
|
function makeJwt(accountId: string): string {
|
|
7
7
|
const header = Buffer.from(JSON.stringify({ alg: "none", typ: "JWT" })).toString("base64url");
|
|
@@ -11,6 +11,24 @@ function makeJwt(accountId: string): string {
|
|
|
11
11
|
return `${header}.${payload}.sig`;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
const codexModel = {
|
|
15
|
+
id: "gpt-5.4",
|
|
16
|
+
name: "gpt-5.4",
|
|
17
|
+
api: "openai-codex-responses",
|
|
18
|
+
provider: "openai-codex",
|
|
19
|
+
baseUrl: "https://chatgpt.com/backend-api",
|
|
20
|
+
reasoning: true,
|
|
21
|
+
input: ["text"],
|
|
22
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
23
|
+
contextWindow: 128000,
|
|
24
|
+
maxTokens: 16384,
|
|
25
|
+
} as any;
|
|
26
|
+
|
|
27
|
+
const simpleContext = {
|
|
28
|
+
systemPrompt: "",
|
|
29
|
+
messages: [{ role: "user", content: [{ type: "text", text: "hi" }] }],
|
|
30
|
+
} as any;
|
|
31
|
+
|
|
14
32
|
test("codex provider does not internally retry ChatGPT usage-plan 429s", async () => {
|
|
15
33
|
const originalFetch = globalThis.fetch;
|
|
16
34
|
let fetchCalls = 0;
|
|
@@ -31,25 +49,10 @@ test("codex provider does not internally retry ChatGPT usage-plan 429s", async (
|
|
|
31
49
|
}) as typeof fetch;
|
|
32
50
|
|
|
33
51
|
try {
|
|
34
|
-
const stream = streamSimpleOpenAICodexResponses(
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
api: "openai-codex-responses",
|
|
39
|
-
provider: "openai-codex",
|
|
40
|
-
baseUrl: "https://chatgpt.com/backend-api",
|
|
41
|
-
reasoning: true,
|
|
42
|
-
input: ["text"],
|
|
43
|
-
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
44
|
-
contextWindow: 128000,
|
|
45
|
-
maxTokens: 16384,
|
|
46
|
-
} as any,
|
|
47
|
-
{
|
|
48
|
-
systemPrompt: "",
|
|
49
|
-
messages: [{ role: "user", content: [{ type: "text", text: "hi" }] }],
|
|
50
|
-
} as any,
|
|
51
|
-
{ apiKey: makeJwt("acct_123"), transport: "sse" } as any,
|
|
52
|
-
);
|
|
52
|
+
const stream = streamSimpleOpenAICodexResponses(codexModel, simpleContext, {
|
|
53
|
+
apiKey: makeJwt("acct_123"),
|
|
54
|
+
transport: "sse",
|
|
55
|
+
} as any);
|
|
53
56
|
|
|
54
57
|
let finalError = "";
|
|
55
58
|
for await (const event of stream) {
|
|
@@ -64,3 +67,123 @@ test("codex provider does not internally retry ChatGPT usage-plan 429s", async (
|
|
|
64
67
|
globalThis.fetch = originalFetch;
|
|
65
68
|
}
|
|
66
69
|
});
|
|
70
|
+
|
|
71
|
+
test("codex request body maps fast mode to service_tier=priority and omits when off", () => {
|
|
72
|
+
const onBody = __testing.buildRequestBody(codexModel, simpleContext, { fastMode: true } as any);
|
|
73
|
+
assert.equal(onBody.service_tier, "priority");
|
|
74
|
+
|
|
75
|
+
const offBody = __testing.buildRequestBody(codexModel, simpleContext, { fastMode: false } as any);
|
|
76
|
+
assert.equal("service_tier" in offBody, false);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test("codex SSE payload includes priority when fast mode is on and omits when off", async () => {
|
|
80
|
+
const originalFetch = globalThis.fetch;
|
|
81
|
+
const bodies: any[] = [];
|
|
82
|
+
|
|
83
|
+
globalThis.fetch = (async (_url, init) => {
|
|
84
|
+
const rawBody = typeof init?.body === "string" ? init.body : "{}";
|
|
85
|
+
bodies.push(JSON.parse(rawBody));
|
|
86
|
+
const sse = [
|
|
87
|
+
'data: {"type":"response.completed","response":{"status":"completed","usage":{"input_tokens":0,"output_tokens":0,"total_tokens":0}}}',
|
|
88
|
+
"",
|
|
89
|
+
].join("\n");
|
|
90
|
+
return new Response(sse, { status: 200, headers: { "content-type": "text/event-stream" } });
|
|
91
|
+
}) as typeof fetch;
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
for (const fastMode of [true, false]) {
|
|
95
|
+
const stream = streamSimpleOpenAICodexResponses(codexModel, simpleContext, {
|
|
96
|
+
apiKey: makeJwt("acct_sse"),
|
|
97
|
+
transport: "sse",
|
|
98
|
+
fastMode,
|
|
99
|
+
} as any);
|
|
100
|
+
await stream.result();
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
assert.equal(bodies[0]?.service_tier, "priority");
|
|
104
|
+
assert.equal("service_tier" in bodies[1], false);
|
|
105
|
+
} finally {
|
|
106
|
+
globalThis.fetch = originalFetch;
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
test("codex websocket cache resets when fast mode changes on same session", async () => {
|
|
111
|
+
const originalWebSocket = (globalThis as any).WebSocket;
|
|
112
|
+
const originalFetch = globalThis.fetch;
|
|
113
|
+
const sentPayloads: any[] = [];
|
|
114
|
+
let constructorCalls = 0;
|
|
115
|
+
|
|
116
|
+
class MockWebSocket {
|
|
117
|
+
public readyState = 0;
|
|
118
|
+
private listeners = new Map<string, Set<(event: any) => void>>();
|
|
119
|
+
|
|
120
|
+
constructor(_url: string, _options?: unknown) {
|
|
121
|
+
constructorCalls++;
|
|
122
|
+
queueMicrotask(() => {
|
|
123
|
+
this.readyState = 1;
|
|
124
|
+
this.emit("open", {});
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
send(data: string): void {
|
|
129
|
+
sentPayloads.push(JSON.parse(data));
|
|
130
|
+
queueMicrotask(() => {
|
|
131
|
+
this.emit("message", {
|
|
132
|
+
data: JSON.stringify({
|
|
133
|
+
type: "response.completed",
|
|
134
|
+
response: {
|
|
135
|
+
status: "completed",
|
|
136
|
+
usage: { input_tokens: 0, output_tokens: 0, total_tokens: 0 },
|
|
137
|
+
},
|
|
138
|
+
}),
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
close(): void {
|
|
144
|
+
this.readyState = 3;
|
|
145
|
+
this.emit("close", { code: 1000, reason: "closed" });
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
addEventListener(type: string, listener: (event: any) => void): void {
|
|
149
|
+
if (!this.listeners.has(type)) this.listeners.set(type, new Set());
|
|
150
|
+
this.listeners.get(type)!.add(listener);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
removeEventListener(type: string, listener: (event: any) => void): void {
|
|
154
|
+
this.listeners.get(type)?.delete(listener);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
private emit(type: string, event: any): void {
|
|
158
|
+
for (const listener of this.listeners.get(type) ?? []) {
|
|
159
|
+
listener(event);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
(globalThis as any).WebSocket = MockWebSocket as any;
|
|
165
|
+
globalThis.fetch = (async () => {
|
|
166
|
+
throw new Error("fetch should not be used in websocket transport test");
|
|
167
|
+
}) as any;
|
|
168
|
+
|
|
169
|
+
try {
|
|
170
|
+
__testing.clearWebSocketSessionCache();
|
|
171
|
+
for (const fastMode of [true, false]) {
|
|
172
|
+
const stream = streamSimpleOpenAICodexResponses(codexModel, simpleContext, {
|
|
173
|
+
apiKey: makeJwt("acct_ws"),
|
|
174
|
+
transport: "websocket",
|
|
175
|
+
sessionId: "session-fast-toggle",
|
|
176
|
+
fastMode,
|
|
177
|
+
} as any);
|
|
178
|
+
await stream.result();
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
assert.equal(constructorCalls, 2, "websocket should reconnect when service tier state changes");
|
|
182
|
+
assert.equal(sentPayloads[0]?.service_tier, "priority");
|
|
183
|
+
assert.equal("service_tier" in sentPayloads[1], false);
|
|
184
|
+
} finally {
|
|
185
|
+
__testing.clearWebSocketSessionCache();
|
|
186
|
+
(globalThis as any).WebSocket = originalWebSocket;
|
|
187
|
+
globalThis.fetch = originalFetch;
|
|
188
|
+
}
|
|
189
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type * as NodeOs from "node:os";
|
|
2
|
-
import type { Tool as OpenAITool, ResponseInput, ResponseStreamEvent } from "openai/resources/responses/responses.js";
|
|
2
|
+
import type { Tool as OpenAITool, ResponseCreateParamsStreaming, ResponseInput, ResponseStreamEvent } from "openai/resources/responses/responses.js";
|
|
3
3
|
|
|
4
4
|
// NEVER convert to top-level runtime imports - breaks browser/Vite builds (web-ui)
|
|
5
5
|
let _os: typeof NodeOs | null = null;
|
|
@@ -54,9 +54,10 @@ const CODEX_RESPONSE_STATUSES = new Set<CodexResponseStatus>([
|
|
|
54
54
|
// ============================================================================
|
|
55
55
|
|
|
56
56
|
export interface OpenAICodexResponsesOptions extends StreamOptions {
|
|
57
|
-
reasoningEffort?: "none" | "
|
|
57
|
+
reasoningEffort?: "none" | "low" | "medium" | "high" | "xhigh";
|
|
58
58
|
reasoningSummary?: "auto" | "concise" | "detailed" | "off" | "on" | null;
|
|
59
59
|
textVerbosity?: "low" | "medium" | "high";
|
|
60
|
+
serviceTier?: ResponseCreateParamsStreaming["service_tier"];
|
|
60
61
|
}
|
|
61
62
|
|
|
62
63
|
type CodexResponseStatus = "completed" | "incomplete" | "failed" | "cancelled" | "queued" | "in_progress";
|
|
@@ -73,6 +74,7 @@ interface RequestBody {
|
|
|
73
74
|
temperature?: number;
|
|
74
75
|
reasoning?: { effort?: string; summary?: string };
|
|
75
76
|
text?: { verbosity?: string };
|
|
77
|
+
service_tier?: ResponseCreateParamsStreaming["service_tier"];
|
|
76
78
|
include?: string[];
|
|
77
79
|
prompt_cache_key?: string;
|
|
78
80
|
[key: string]: unknown;
|
|
@@ -294,6 +296,13 @@ export const streamSimpleOpenAICodexResponses: StreamFunction<"openai-codex-resp
|
|
|
294
296
|
// Request Building
|
|
295
297
|
// ============================================================================
|
|
296
298
|
|
|
299
|
+
function resolveCodexServiceTier(options?: OpenAICodexResponsesOptions): ResponseCreateParamsStreaming["service_tier"] | undefined {
|
|
300
|
+
if (options?.serviceTier !== undefined) {
|
|
301
|
+
return options.serviceTier;
|
|
302
|
+
}
|
|
303
|
+
return options?.fastMode ? "priority" : undefined;
|
|
304
|
+
}
|
|
305
|
+
|
|
297
306
|
function buildRequestBody(
|
|
298
307
|
model: Model<"openai-codex-responses">,
|
|
299
308
|
context: Context,
|
|
@@ -320,6 +329,11 @@ function buildRequestBody(
|
|
|
320
329
|
body.temperature = options.temperature;
|
|
321
330
|
}
|
|
322
331
|
|
|
332
|
+
const resolvedServiceTier = resolveCodexServiceTier(options);
|
|
333
|
+
if (resolvedServiceTier !== undefined) {
|
|
334
|
+
body.service_tier = resolvedServiceTier;
|
|
335
|
+
}
|
|
336
|
+
|
|
323
337
|
if (context.tools) {
|
|
324
338
|
body.tools = convertResponsesTools(context.tools, { strict: null });
|
|
325
339
|
}
|
|
@@ -336,8 +350,6 @@ function buildRequestBody(
|
|
|
336
350
|
|
|
337
351
|
function clampReasoningEffort(modelId: string, effort: string): string {
|
|
338
352
|
const id = modelId.includes("/") ? modelId.split("/").pop()! : modelId;
|
|
339
|
-
if ((id.startsWith("gpt-5.2") || id.startsWith("gpt-5.3") || id.startsWith("gpt-5.4")) && effort === "minimal")
|
|
340
|
-
return "low";
|
|
341
353
|
if (id === "gpt-5.1" && effort === "xhigh") return "high";
|
|
342
354
|
if (id === "gpt-5.1-codex-mini") return effort === "high" || effort === "xhigh" ? "high" : "medium";
|
|
343
355
|
return effort;
|
|
@@ -476,6 +488,7 @@ interface CachedWebSocketConnection {
|
|
|
476
488
|
socket: WebSocketLike;
|
|
477
489
|
busy: boolean;
|
|
478
490
|
idleTimer?: ReturnType<typeof setTimeout>;
|
|
491
|
+
serviceTier?: ResponseCreateParamsStreaming["service_tier"];
|
|
479
492
|
}
|
|
480
493
|
|
|
481
494
|
const websocketSessionCache = new Map<string, CachedWebSocketConnection>();
|
|
@@ -591,6 +604,7 @@ async function acquireWebSocket(
|
|
|
591
604
|
url: string,
|
|
592
605
|
headers: Headers,
|
|
593
606
|
sessionId: string | undefined,
|
|
607
|
+
serviceTier: ResponseCreateParamsStreaming["service_tier"] | undefined,
|
|
594
608
|
signal?: AbortSignal,
|
|
595
609
|
): Promise<{ socket: WebSocketLike; release: (options?: { keep?: boolean }) => void }> {
|
|
596
610
|
if (!sessionId) {
|
|
@@ -613,7 +627,8 @@ async function acquireWebSocket(
|
|
|
613
627
|
clearTimeout(cached.idleTimer);
|
|
614
628
|
cached.idleTimer = undefined;
|
|
615
629
|
}
|
|
616
|
-
|
|
630
|
+
|
|
631
|
+
if (!cached.busy && isWebSocketReusable(cached.socket) && cached.serviceTier === serviceTier) {
|
|
617
632
|
cached.busy = true;
|
|
618
633
|
return {
|
|
619
634
|
socket: cached.socket,
|
|
@@ -628,6 +643,10 @@ async function acquireWebSocket(
|
|
|
628
643
|
},
|
|
629
644
|
};
|
|
630
645
|
}
|
|
646
|
+
if (!cached.busy && isWebSocketReusable(cached.socket) && cached.serviceTier !== serviceTier) {
|
|
647
|
+
closeWebSocketSilently(cached.socket, 1000, "service_tier_changed");
|
|
648
|
+
websocketSessionCache.delete(sessionId);
|
|
649
|
+
}
|
|
631
650
|
if (cached.busy) {
|
|
632
651
|
const socket = await connectWebSocket(url, headers, signal);
|
|
633
652
|
return {
|
|
@@ -644,7 +663,7 @@ async function acquireWebSocket(
|
|
|
644
663
|
}
|
|
645
664
|
|
|
646
665
|
const socket = await connectWebSocket(url, headers, signal);
|
|
647
|
-
const entry: CachedWebSocketConnection = { socket, busy: true };
|
|
666
|
+
const entry: CachedWebSocketConnection = { socket, busy: true, serviceTier };
|
|
648
667
|
|
|
649
668
|
// Evict the oldest entry if the cache is at capacity (LRU eviction).
|
|
650
669
|
if (websocketSessionCache.size >= MAX_WEBSOCKET_CACHE_SIZE) {
|
|
@@ -832,7 +851,13 @@ async function processWebSocketStream(
|
|
|
832
851
|
onStart: () => void,
|
|
833
852
|
options?: OpenAICodexResponsesOptions,
|
|
834
853
|
): Promise<void> {
|
|
835
|
-
const { socket, release } = await acquireWebSocket(
|
|
854
|
+
const { socket, release } = await acquireWebSocket(
|
|
855
|
+
url,
|
|
856
|
+
headers,
|
|
857
|
+
options?.sessionId,
|
|
858
|
+
body.service_tier,
|
|
859
|
+
options?.signal,
|
|
860
|
+
);
|
|
836
861
|
let keepConnection = true;
|
|
837
862
|
try {
|
|
838
863
|
socket.send(JSON.stringify({ type: "response.create", ...body }));
|
|
@@ -924,3 +949,19 @@ function buildHeaders(
|
|
|
924
949
|
|
|
925
950
|
return headers;
|
|
926
951
|
}
|
|
952
|
+
|
|
953
|
+
function clearWebSocketSessionCache(): void {
|
|
954
|
+
for (const [, entry] of websocketSessionCache) {
|
|
955
|
+
if (entry.idleTimer) {
|
|
956
|
+
clearTimeout(entry.idleTimer);
|
|
957
|
+
}
|
|
958
|
+
closeWebSocketSilently(entry.socket);
|
|
959
|
+
}
|
|
960
|
+
websocketSessionCache.clear();
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
export const __testing = {
|
|
964
|
+
buildRequestBody,
|
|
965
|
+
resolveCodexServiceTier,
|
|
966
|
+
clearWebSocketSessionCache,
|
|
967
|
+
};
|
|
@@ -62,7 +62,7 @@ function hasToolHistory(messages: Message[]): boolean {
|
|
|
62
62
|
|
|
63
63
|
export interface OpenAICompletionsOptions extends StreamOptions {
|
|
64
64
|
toolChoice?: "auto" | "none" | "required" | { type: "function"; function: { name: string } };
|
|
65
|
-
reasoningEffort?: "
|
|
65
|
+
reasoningEffort?: "low" | "medium" | "high" | "xhigh";
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
export const streamOpenAICompletions: StreamFunction<"openai-completions", OpenAICompletionsOptions> = (
|
|
@@ -718,7 +718,6 @@ function detectCompat(model: Model<"openai-completions">): Required<OpenAIComple
|
|
|
718
718
|
const reasoningEffortMap =
|
|
719
719
|
isGroq && model.id === "qwen/qwen3-32b"
|
|
720
720
|
? {
|
|
721
|
-
minimal: "default",
|
|
722
721
|
low: "default",
|
|
723
722
|
medium: "default",
|
|
724
723
|
high: "default",
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
|
|
4
|
+
import { __testing } from "./openai-responses.js";
|
|
5
|
+
|
|
6
|
+
test("openai-responses fast mode maps to service_tier=priority for supported models", () => {
|
|
7
|
+
const model = {
|
|
8
|
+
id: "gpt-5.4",
|
|
9
|
+
name: "gpt-5.4",
|
|
10
|
+
api: "openai-responses",
|
|
11
|
+
provider: "openai",
|
|
12
|
+
baseUrl: "https://api.openai.com/v1",
|
|
13
|
+
reasoning: true,
|
|
14
|
+
input: ["text"],
|
|
15
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
16
|
+
contextWindow: 200000,
|
|
17
|
+
maxTokens: 32768,
|
|
18
|
+
capabilities: { supportsServiceTier: true },
|
|
19
|
+
} as any;
|
|
20
|
+
const context = {
|
|
21
|
+
systemPrompt: "",
|
|
22
|
+
messages: [{ role: "user", content: [{ type: "text", text: "hi" }] }],
|
|
23
|
+
} as any;
|
|
24
|
+
|
|
25
|
+
const params = __testing.buildParams(model, context, { fastMode: true });
|
|
26
|
+
assert.equal(params.service_tier, "priority");
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test("openai-responses fast mode off omits service_tier", () => {
|
|
30
|
+
const model = {
|
|
31
|
+
id: "gpt-5.4",
|
|
32
|
+
name: "gpt-5.4",
|
|
33
|
+
api: "openai-responses",
|
|
34
|
+
provider: "openai",
|
|
35
|
+
baseUrl: "https://api.openai.com/v1",
|
|
36
|
+
reasoning: true,
|
|
37
|
+
input: ["text"],
|
|
38
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
39
|
+
contextWindow: 200000,
|
|
40
|
+
maxTokens: 32768,
|
|
41
|
+
capabilities: { supportsServiceTier: true },
|
|
42
|
+
} as any;
|
|
43
|
+
const context = {
|
|
44
|
+
systemPrompt: "",
|
|
45
|
+
messages: [{ role: "user", content: [{ type: "text", text: "hi" }] }],
|
|
46
|
+
} as any;
|
|
47
|
+
|
|
48
|
+
const params = __testing.buildParams(model, context, { fastMode: false });
|
|
49
|
+
assert.equal("service_tier" in params, false);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test("openai-responses fast mode is scoped to provider=openai", () => {
|
|
53
|
+
const model = {
|
|
54
|
+
id: "gpt-5.4",
|
|
55
|
+
name: "gpt-5.4",
|
|
56
|
+
api: "openai-responses",
|
|
57
|
+
provider: "openrouter",
|
|
58
|
+
baseUrl: "https://openrouter.ai/api/v1",
|
|
59
|
+
reasoning: true,
|
|
60
|
+
input: ["text"],
|
|
61
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
62
|
+
contextWindow: 200000,
|
|
63
|
+
maxTokens: 32768,
|
|
64
|
+
capabilities: { supportsServiceTier: true },
|
|
65
|
+
} as any;
|
|
66
|
+
const context = {
|
|
67
|
+
systemPrompt: "",
|
|
68
|
+
messages: [{ role: "user", content: [{ type: "text", text: "hi" }] }],
|
|
69
|
+
} as any;
|
|
70
|
+
|
|
71
|
+
const params = __testing.buildParams(model, context, { fastMode: true });
|
|
72
|
+
assert.equal("service_tier" in params, false);
|
|
73
|
+
});
|
|
@@ -56,7 +56,7 @@ function getPromptCacheRetention(baseUrl: string, cacheRetention: CacheRetention
|
|
|
56
56
|
|
|
57
57
|
// OpenAI Responses-specific options
|
|
58
58
|
export interface OpenAIResponsesOptions extends StreamOptions {
|
|
59
|
-
reasoningEffort?: "
|
|
59
|
+
reasoningEffort?: "low" | "medium" | "high" | "xhigh";
|
|
60
60
|
reasoningSummary?: "auto" | "detailed" | "concise" | null;
|
|
61
61
|
serviceTier?: ResponseCreateParamsStreaming["service_tier"];
|
|
62
62
|
}
|
|
@@ -86,6 +86,7 @@ export const streamOpenAIResponses: StreamFunction<"openai-responses", OpenAIRes
|
|
|
86
86
|
if (nextParams !== undefined) {
|
|
87
87
|
params = nextParams as ResponseCreateParamsStreaming;
|
|
88
88
|
}
|
|
89
|
+
const resolvedServiceTier = resolveOpenAIServiceTier(model, options);
|
|
89
90
|
const openaiStream = await client.responses.create(
|
|
90
91
|
params,
|
|
91
92
|
options?.signal ? { signal: options.signal } : undefined,
|
|
@@ -93,7 +94,7 @@ export const streamOpenAIResponses: StreamFunction<"openai-responses", OpenAIRes
|
|
|
93
94
|
stream.push({ type: "start", partial: output });
|
|
94
95
|
|
|
95
96
|
await processResponsesStream(openaiStream, output, stream, model, {
|
|
96
|
-
serviceTier:
|
|
97
|
+
serviceTier: resolvedServiceTier,
|
|
97
98
|
applyServiceTierPricing,
|
|
98
99
|
});
|
|
99
100
|
|
|
@@ -127,8 +128,25 @@ export const streamSimpleOpenAIResponses: StreamFunction<"openai-responses", Sim
|
|
|
127
128
|
} satisfies OpenAIResponsesOptions);
|
|
128
129
|
};
|
|
129
130
|
|
|
131
|
+
function resolveOpenAIServiceTier(
|
|
132
|
+
model: Model<"openai-responses">,
|
|
133
|
+
options?: OpenAIResponsesOptions,
|
|
134
|
+
): ResponseCreateParamsStreaming["service_tier"] | undefined {
|
|
135
|
+
if (options?.serviceTier !== undefined) {
|
|
136
|
+
return options.serviceTier;
|
|
137
|
+
}
|
|
138
|
+
if (options?.fastMode !== true) {
|
|
139
|
+
return undefined;
|
|
140
|
+
}
|
|
141
|
+
if (model.provider !== "openai") {
|
|
142
|
+
return undefined;
|
|
143
|
+
}
|
|
144
|
+
return model.capabilities?.supportsServiceTier ? "priority" : undefined;
|
|
145
|
+
}
|
|
146
|
+
|
|
130
147
|
function buildParams(model: Model<"openai-responses">, context: Context, options?: OpenAIResponsesOptions) {
|
|
131
148
|
const messages = convertResponsesMessages(model, context, OPENAI_TOOL_CALL_PROVIDERS);
|
|
149
|
+
const resolvedServiceTier = resolveOpenAIServiceTier(model, options);
|
|
132
150
|
|
|
133
151
|
const cacheRetention = resolveCacheRetention(options?.cacheRetention);
|
|
134
152
|
const params: ResponseCreateParamsStreaming = {
|
|
@@ -148,8 +166,8 @@ function buildParams(model: Model<"openai-responses">, context: Context, options
|
|
|
148
166
|
params.temperature = options?.temperature;
|
|
149
167
|
}
|
|
150
168
|
|
|
151
|
-
if (
|
|
152
|
-
params.service_tier =
|
|
169
|
+
if (resolvedServiceTier !== undefined) {
|
|
170
|
+
params.service_tier = resolvedServiceTier;
|
|
153
171
|
}
|
|
154
172
|
|
|
155
173
|
if (context.tools) {
|
|
@@ -204,3 +222,8 @@ function applyServiceTierPricing(usage: Usage, serviceTier: ResponseCreateParams
|
|
|
204
222
|
usage.cost.cacheWrite *= multiplier;
|
|
205
223
|
usage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;
|
|
206
224
|
}
|
|
225
|
+
|
|
226
|
+
export const __testing = {
|
|
227
|
+
buildParams,
|
|
228
|
+
resolveOpenAIServiceTier,
|
|
229
|
+
};
|
|
@@ -182,12 +182,9 @@ export function handleStreamError(
|
|
|
182
182
|
|
|
183
183
|
/**
|
|
184
184
|
* Clamp reasoning effort for models that don't support all levels.
|
|
185
|
-
* gpt-5.x models don't support "minimal" -- map to "low".
|
|
186
185
|
*
|
|
187
186
|
* Used by both openai-responses.ts and azure-openai-responses.ts.
|
|
188
187
|
*/
|
|
189
188
|
export function clampReasoningForModel(modelName: string, effort: string): string {
|
|
190
|
-
const name = modelName.includes("/") ? modelName.split("/").pop()! : modelName;
|
|
191
|
-
if (name.startsWith("gpt-5") && effort === "minimal") return "low";
|
|
192
189
|
return effort;
|
|
193
190
|
}
|
|
@@ -6,6 +6,8 @@ export function buildBaseOptions(model: Model<Api>, options?: SimpleStreamOption
|
|
|
6
6
|
maxTokens: options?.maxTokens || Math.min(model.maxTokens, 32000),
|
|
7
7
|
signal: options?.signal,
|
|
8
8
|
apiKey: apiKey || options?.apiKey,
|
|
9
|
+
transport: options?.transport,
|
|
10
|
+
fastMode: options?.fastMode,
|
|
9
11
|
cacheRetention: options?.cacheRetention,
|
|
10
12
|
sessionId: options?.sessionId,
|
|
11
13
|
headers: options?.headers,
|
|
@@ -28,7 +30,6 @@ export function adjustMaxTokensForThinking(
|
|
|
28
30
|
customBudgets?: ThinkingBudgets,
|
|
29
31
|
): { maxTokens: number; thinkingBudget: number } {
|
|
30
32
|
const defaultBudgets: ThinkingBudgets = {
|
|
31
|
-
minimal: 1024,
|
|
32
33
|
low: 2048,
|
|
33
34
|
medium: 8192,
|
|
34
35
|
high: 16384,
|
|
@@ -46,11 +46,10 @@ export type KnownProvider =
|
|
|
46
46
|
| "ollama-cloud";
|
|
47
47
|
export type Provider = KnownProvider | string;
|
|
48
48
|
|
|
49
|
-
export type ThinkingLevel = "
|
|
49
|
+
export type ThinkingLevel = "low" | "medium" | "high" | "xhigh" | "adaptive";
|
|
50
50
|
|
|
51
51
|
/** Token budgets for each thinking level (token-based providers only) */
|
|
52
52
|
export interface ThinkingBudgets {
|
|
53
|
-
minimal?: number;
|
|
54
53
|
low?: number;
|
|
55
54
|
medium?: number;
|
|
56
55
|
high?: number;
|
|
@@ -66,6 +65,11 @@ export interface StreamOptions {
|
|
|
66
65
|
maxTokens?: number;
|
|
67
66
|
signal?: AbortSignal;
|
|
68
67
|
apiKey?: string;
|
|
68
|
+
/**
|
|
69
|
+
* Enable fast mode for providers/models that support OpenAI service tiers.
|
|
70
|
+
* For OpenAI/Codex Responses, this maps to service_tier="priority".
|
|
71
|
+
*/
|
|
72
|
+
fastMode?: boolean;
|
|
69
73
|
/**
|
|
70
74
|
* Preferred transport for providers that support multiple transports.
|
|
71
75
|
* Providers that do not support this option ignore it.
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import chalk from "chalk";
|
|
5
5
|
import { APP_NAME, CONFIG_DIR_NAME, ENV_AGENT_DIR } from "../config.js";
|
|
6
6
|
import { allTools } from "../core/tools/index.js";
|
|
7
|
-
const VALID_THINKING_LEVELS = ["off", "
|
|
7
|
+
const VALID_THINKING_LEVELS = ["off", "low", "medium", "high", "xhigh", "adaptive"];
|
|
8
8
|
export function isValidThinkingLevel(level) {
|
|
9
9
|
return VALID_THINKING_LEVELS.includes(level);
|
|
10
10
|
}
|
|
@@ -210,7 +210,7 @@ ${chalk.bold("Options:")}
|
|
|
210
210
|
--no-tools Disable all built-in tools
|
|
211
211
|
--tools <tools> Comma-separated list of tools to enable (default: read,bash,edit,write)
|
|
212
212
|
Available: read, bash, edit, write, lsp, grep, find, ls
|
|
213
|
-
--thinking <level> Set thinking level: off,
|
|
213
|
+
--thinking <level> Set thinking level: off, low, medium, high, xhigh
|
|
214
214
|
--extension, -e <path> Load an extension file (can be used multiple times)
|
|
215
215
|
--no-extensions, -ne Disable extension discovery (explicit -e paths still work)
|
|
216
216
|
--skill <path> Load a skill file or directory (can be used multiple times)
|