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
|
@@ -143,6 +143,7 @@ test("AgentSession switches supported Anthropic models to adaptive when the sett
|
|
|
143
143
|
const settingsManager = SettingsManager.inMemory();
|
|
144
144
|
settingsManager.setDefaultModelAndProvider("openai", "gpt-5.4");
|
|
145
145
|
settingsManager.setDefaultThinkingLevel("high");
|
|
146
|
+
settingsManager.setClientAdaptiveByDefault(false);
|
|
146
147
|
settingsManager.setAnthropicAdaptiveByDefault(true);
|
|
147
148
|
const sessionManager = SessionManager.inMemory(tempDir);
|
|
148
149
|
const resourceLoader = new DefaultResourceLoader({
|
|
@@ -180,3 +181,47 @@ test("AgentSession switches supported Anthropic models to adaptive when the sett
|
|
|
180
181
|
assert.equal(session.thinkingLevel, "adaptive");
|
|
181
182
|
session.dispose();
|
|
182
183
|
});
|
|
184
|
+
|
|
185
|
+
test("createAgentSession defaults to adaptive for reasoning models when clientAdaptiveByDefault is enabled", async () => {
|
|
186
|
+
const tempDir = join(
|
|
187
|
+
process.cwd(),
|
|
188
|
+
".tmp-tests",
|
|
189
|
+
`sdk-client-adaptive-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
190
|
+
);
|
|
191
|
+
mkdirSync(tempDir, { recursive: true });
|
|
192
|
+
tempDirs.push(tempDir);
|
|
193
|
+
|
|
194
|
+
const authStorage = AuthStorage.inMemory({
|
|
195
|
+
openai: { type: "api_key", key: "test-openai-key" },
|
|
196
|
+
});
|
|
197
|
+
const modelRegistry = new ModelRegistry(authStorage, join(tempDir, "models.json"));
|
|
198
|
+
const settingsManager = SettingsManager.inMemory();
|
|
199
|
+
settingsManager.setDefaultModelAndProvider("openai", "gpt-5.4");
|
|
200
|
+
settingsManager.setDefaultThinkingLevel("high");
|
|
201
|
+
settingsManager.setClientAdaptiveByDefault(true);
|
|
202
|
+
const sessionManager = SessionManager.inMemory(tempDir);
|
|
203
|
+
const resourceLoader = new DefaultResourceLoader({
|
|
204
|
+
cwd: tempDir,
|
|
205
|
+
agentDir: tempDir,
|
|
206
|
+
settingsManager,
|
|
207
|
+
noExtensions: true,
|
|
208
|
+
noSkills: true,
|
|
209
|
+
noPromptTemplates: true,
|
|
210
|
+
noThemes: true,
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
const { session } = await createAgentSession({
|
|
214
|
+
cwd: tempDir,
|
|
215
|
+
agentDir: tempDir,
|
|
216
|
+
authStorage,
|
|
217
|
+
modelRegistry,
|
|
218
|
+
settingsManager,
|
|
219
|
+
sessionManager,
|
|
220
|
+
resourceLoader,
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
assert.equal(session.model?.provider, "openai");
|
|
224
|
+
assert.equal(session.model?.id, "gpt-5.4");
|
|
225
|
+
assert.equal(session.thinkingLevel, "adaptive");
|
|
226
|
+
session.dispose();
|
|
227
|
+
});
|
|
@@ -144,11 +144,15 @@ function shouldPreferAdaptiveThinkingByDefault(
|
|
|
144
144
|
model: Model<any> | undefined,
|
|
145
145
|
settingsManager: SettingsManager,
|
|
146
146
|
): boolean {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
147
|
+
if (!model || model.reasoning !== true) {
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (model.provider === "anthropic" && supportsAdaptiveThinking(model.id)) {
|
|
152
|
+
return settingsManager.getClientAdaptiveByDefault() || settingsManager.getAnthropicAdaptiveByDefault();
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return settingsManager.getClientAdaptiveByDefault() && !!settingsManager.getAdaptiveClassifierModel();
|
|
152
156
|
}
|
|
153
157
|
|
|
154
158
|
/**
|
|
@@ -278,9 +282,23 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
278
282
|
const balancedToolNames = editMode === "hashline"
|
|
279
283
|
? ["hashline_read", "bash", "hashline_edit", "write", "lsp", "bg_shell", "tool_search", "tool_enable", "Skill", "subagent", "await_subagent", "ask_user_questions"]
|
|
280
284
|
: ["read", "bash", "edit", "write", "lsp", "bg_shell", "tool_search", "tool_enable", "Skill", "subagent", "await_subagent", "ask_user_questions"];
|
|
285
|
+
const standardToolNames = [
|
|
286
|
+
"read", "bash", "edit", "write", "lsp", "grep", "find", "ls",
|
|
287
|
+
"bg_shell",
|
|
288
|
+
"web_search", "fetch_page",
|
|
289
|
+
"resolve_library", "get_library_docs",
|
|
290
|
+
"subagent", "await_subagent", "Skill",
|
|
291
|
+
"ask_user_questions", "secure_env_collect",
|
|
292
|
+
"browser_navigate", "browser_click", "browser_type", "browser_screenshot",
|
|
293
|
+
"browser_scroll", "browser_key_press", "browser_evaluate",
|
|
294
|
+
"browser_find", "browser_wait_for", "browser_close",
|
|
295
|
+
"browser_assert", "browser_batch",
|
|
296
|
+
"tool_search", "tool_enable",
|
|
297
|
+
];
|
|
298
|
+
const profileToolNames = toolProfile === "standard" ? standardToolNames : balancedToolNames;
|
|
281
299
|
const defaultActiveToolNames: string[] = toolProfile === "full"
|
|
282
300
|
? []
|
|
283
|
-
:
|
|
301
|
+
: profileToolNames;
|
|
284
302
|
const initialActiveToolNames: string[] = options.tools
|
|
285
303
|
? options.tools.map((t) => t.name).filter((n): n is string => typeof n === "string" && n in allTools)
|
|
286
304
|
: defaultActiveToolNames;
|
|
@@ -326,7 +344,17 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
326
344
|
|
|
327
345
|
const extensionRunnerRef: { current?: ExtensionRunner } = {};
|
|
328
346
|
|
|
329
|
-
|
|
347
|
+
// Resolve the adaptive classifier model for LLM-based adaptive thinking classification.
|
|
348
|
+
const adaptiveClassifierModelRef = settingsManager.getAdaptiveClassifierModel();
|
|
349
|
+
let adaptiveClassifierModel: Model<any> | undefined;
|
|
350
|
+
if (adaptiveClassifierModelRef) {
|
|
351
|
+
const parts = adaptiveClassifierModelRef.split("/");
|
|
352
|
+
if (parts.length === 2) {
|
|
353
|
+
adaptiveClassifierModel = modelRegistry.find(parts[0]!, parts[1]!) ?? undefined;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
const agentOptions: ConstructorParameters<typeof Agent>[0] & { getFastMode?: () => boolean } = {
|
|
330
358
|
initialState: {
|
|
331
359
|
systemPrompt: "",
|
|
332
360
|
model,
|
|
@@ -341,6 +369,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
341
369
|
}
|
|
342
370
|
return runner.emitBeforeProviderRequest(payload, currentModel);
|
|
343
371
|
},
|
|
372
|
+
getFastMode: () => settingsManager.getFastMode(),
|
|
344
373
|
sessionId: sessionManager.getSessionId(),
|
|
345
374
|
transformContext: async (messages) => {
|
|
346
375
|
const runner = extensionRunnerRef.current;
|
|
@@ -353,6 +382,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
353
382
|
thinkingBudgets: settingsManager.getThinkingBudgets(),
|
|
354
383
|
maxRetryDelayMs: settingsManager.getRetrySettings().maxDelayMs,
|
|
355
384
|
externalToolExecution: (m) => modelRegistry.getProviderAuthMode(m.provider) === "externalCli",
|
|
385
|
+
adaptiveClassifierModel,
|
|
356
386
|
getApiKey: async (provider) => {
|
|
357
387
|
// Use the provider argument from the in-flight request;
|
|
358
388
|
// agent.state.model may already be switched mid-turn.
|
|
@@ -422,7 +452,8 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
422
452
|
`Set an API key environment variable or run '/login ${resolvedProvider}'.`,
|
|
423
453
|
);
|
|
424
454
|
},
|
|
425
|
-
}
|
|
455
|
+
};
|
|
456
|
+
agent = new Agent(agentOptions);
|
|
426
457
|
|
|
427
458
|
// Restore messages if session has existing data
|
|
428
459
|
if (hasExistingSession) {
|
|
@@ -59,10 +59,18 @@ export interface SessionHeader {
|
|
|
59
59
|
timestamp: string;
|
|
60
60
|
cwd: string;
|
|
61
61
|
parentSession?: string;
|
|
62
|
+
subagentName?: string;
|
|
63
|
+
subagentTask?: string;
|
|
64
|
+
subagentSystemPrompt?: string;
|
|
65
|
+
subagentTools?: string[];
|
|
62
66
|
}
|
|
63
67
|
|
|
64
68
|
export interface NewSessionOptions {
|
|
65
69
|
parentSession?: string;
|
|
70
|
+
subagentName?: string;
|
|
71
|
+
subagentTask?: string;
|
|
72
|
+
subagentSystemPrompt?: string;
|
|
73
|
+
subagentTools?: string[];
|
|
66
74
|
}
|
|
67
75
|
|
|
68
76
|
export interface SessionEntryBase {
|
|
@@ -915,6 +923,10 @@ export class SessionManager {
|
|
|
915
923
|
timestamp,
|
|
916
924
|
cwd: this.cwd,
|
|
917
925
|
parentSession: options?.parentSession,
|
|
926
|
+
subagentName: options?.subagentName,
|
|
927
|
+
subagentTask: options?.subagentTask,
|
|
928
|
+
subagentSystemPrompt: options?.subagentSystemPrompt,
|
|
929
|
+
subagentTools: options?.subagentTools,
|
|
918
930
|
};
|
|
919
931
|
this.fileEntries = [header];
|
|
920
932
|
this.sessionEntries = [];
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { mkdtempSync, readFileSync, rmSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { describe, it } from "node:test";
|
|
6
|
+
|
|
7
|
+
import { SettingsManager } from "./settings-manager.js";
|
|
8
|
+
|
|
9
|
+
describe("SettingsManager fastMode", () => {
|
|
10
|
+
it("defaults fastMode to false", () => {
|
|
11
|
+
const manager = SettingsManager.inMemory();
|
|
12
|
+
assert.equal(manager.getFastMode(), false);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it("persists fastMode changes to settings.json", async () => {
|
|
16
|
+
const root = mkdtempSync(join(tmpdir(), "pi-fast-mode-settings-"));
|
|
17
|
+
const cwd = join(root, "project");
|
|
18
|
+
const agentDir = join(root, "agent");
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
const manager = SettingsManager.create(cwd, agentDir);
|
|
22
|
+
assert.equal(manager.getFastMode(), false);
|
|
23
|
+
|
|
24
|
+
manager.setFastMode(true);
|
|
25
|
+
await manager.flush();
|
|
26
|
+
|
|
27
|
+
const rawEnabled = JSON.parse(readFileSync(join(agentDir, "settings.json"), "utf8")) as {
|
|
28
|
+
fastMode?: boolean;
|
|
29
|
+
};
|
|
30
|
+
assert.equal(rawEnabled.fastMode, true);
|
|
31
|
+
|
|
32
|
+
const reloaded = SettingsManager.create(cwd, agentDir);
|
|
33
|
+
assert.equal(reloaded.getFastMode(), true);
|
|
34
|
+
|
|
35
|
+
reloaded.setFastMode(false);
|
|
36
|
+
await reloaded.flush();
|
|
37
|
+
|
|
38
|
+
const rawDisabled = JSON.parse(readFileSync(join(agentDir, "settings.json"), "utf8")) as {
|
|
39
|
+
fastMode?: boolean;
|
|
40
|
+
};
|
|
41
|
+
assert.equal(rawDisabled.fastMode, false);
|
|
42
|
+
} finally {
|
|
43
|
+
rmSync(root, { recursive: true, force: true });
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
});
|
|
@@ -41,7 +41,6 @@ export interface ImageSettings {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
export interface ThinkingBudgetsSettings {
|
|
44
|
-
minimal?: number;
|
|
45
44
|
low?: number;
|
|
46
45
|
medium?: number;
|
|
47
46
|
high?: number;
|
|
@@ -131,8 +130,10 @@ export interface Settings {
|
|
|
131
130
|
autoSwitchPlanModel?: boolean; // default: false — enable opusplan-style model switching (auto-switch to reasoning model on entry, new-session option on approval)
|
|
132
131
|
permissionMode?: "danger-full-access" | "accept-on-edit" | "auto" | "plan";
|
|
133
132
|
classifierModel?: string;
|
|
134
|
-
|
|
133
|
+
adaptiveClassifierModel?: string;
|
|
134
|
+
defaultThinkingLevel?: "off" | "low" | "medium" | "high" | "xhigh" | "adaptive";
|
|
135
135
|
anthropicAdaptiveByDefault?: boolean; // default: false — prefer adaptive thinking when using supported Anthropic models
|
|
136
|
+
clientAdaptiveByDefault?: boolean; // default: true — prefer adaptive thinking for any reasoning-capable model
|
|
136
137
|
transport?: TransportSetting; // default: "sse"
|
|
137
138
|
steeringMode?: "all" | "one-at-a-time";
|
|
138
139
|
followUpMode?: "all" | "one-at-a-time";
|
|
@@ -153,11 +154,12 @@ export interface Settings {
|
|
|
153
154
|
themes?: string[]; // Array of local theme file paths or directories
|
|
154
155
|
enableSkillCommands?: boolean; // default: true - register skills as /skill:name commands
|
|
155
156
|
toolSearch?: boolean; // legacy boolean toggle from deprecated minimal profile; retained for migration only
|
|
156
|
-
toolProfile?: "balanced" | "full"; // default: "balanced"
|
|
157
|
+
toolProfile?: "balanced" | "standard" | "full"; // default: "balanced"
|
|
157
158
|
terminal?: TerminalSettings;
|
|
158
159
|
images?: ImageSettings;
|
|
159
160
|
enabledModels?: string[]; // Model patterns for cycling (same format as --models CLI flag)
|
|
160
161
|
codexRotate?: boolean; // Enable the bundled codex-rotate extension (default: false)
|
|
162
|
+
fastMode?: boolean; // Enable OpenAI/Codex fast tier routing (priority service tier where supported)
|
|
161
163
|
cacheTimer?: boolean; // Show elapsed time since last response in the footer (default: true)
|
|
162
164
|
pinLastPrompt?: boolean; // Pin last sent prompt above the editor as a reminder (default: false)
|
|
163
165
|
doubleEscapeAction?: "fork" | "tree" | "none"; // Action for double-escape with empty editor (default: "tree")
|
|
@@ -185,6 +187,7 @@ export interface Settings {
|
|
|
185
187
|
editorScheme?: "auto" | "vscode" | "cursor" | "zed" | "jetbrains" | "sublime" | "file"; // URI scheme for Cmd+click file links (default: "auto")
|
|
186
188
|
autoDream?: boolean; // default: false — enable automatic memory consolidation (dream) after sessions
|
|
187
189
|
autoMemory?: boolean; // default: false — enable automatic memory extraction from session transcripts
|
|
190
|
+
notificationSound?: boolean; // default: false — play terminal bell when agent finishes responding
|
|
188
191
|
telegramLiveRelayAutoConnect?: boolean; // default: false — auto-run /lsd telegram connect on startup
|
|
189
192
|
}
|
|
190
193
|
|
|
@@ -752,6 +755,10 @@ export class SettingsManager {
|
|
|
752
755
|
return this.settings.classifierModel;
|
|
753
756
|
}
|
|
754
757
|
|
|
758
|
+
getAdaptiveClassifierModel(): string | undefined {
|
|
759
|
+
return this.settings.adaptiveClassifierModel;
|
|
760
|
+
}
|
|
761
|
+
|
|
755
762
|
setDefaultProvider(provider: string): void {
|
|
756
763
|
this.setScopedSetting("defaultProvider", provider);
|
|
757
764
|
}
|
|
@@ -839,6 +846,16 @@ export class SettingsManager {
|
|
|
839
846
|
this.setGlobalSetting("classifierModel", modelRef);
|
|
840
847
|
}
|
|
841
848
|
|
|
849
|
+
setAdaptiveClassifierModel(modelRef: string | undefined): void {
|
|
850
|
+
if (modelRef === undefined) {
|
|
851
|
+
delete this.globalSettings.adaptiveClassifierModel;
|
|
852
|
+
this.markModified("adaptiveClassifierModel");
|
|
853
|
+
this.save();
|
|
854
|
+
return;
|
|
855
|
+
}
|
|
856
|
+
this.setGlobalSetting("adaptiveClassifierModel", modelRef);
|
|
857
|
+
}
|
|
858
|
+
|
|
842
859
|
setDefaultModelAndProvider(provider: string, modelId: string): void {
|
|
843
860
|
if (this.hasProjectSettings()) {
|
|
844
861
|
this.projectSettings.defaultProvider = provider;
|
|
@@ -893,11 +910,11 @@ export class SettingsManager {
|
|
|
893
910
|
this.setGlobalSetting("themeAccent", accent);
|
|
894
911
|
}
|
|
895
912
|
|
|
896
|
-
getDefaultThinkingLevel(): "off" | "
|
|
913
|
+
getDefaultThinkingLevel(): "off" | "low" | "medium" | "high" | "xhigh" | "adaptive" | undefined {
|
|
897
914
|
return this.settings.defaultThinkingLevel;
|
|
898
915
|
}
|
|
899
916
|
|
|
900
|
-
setDefaultThinkingLevel(level: "off" | "
|
|
917
|
+
setDefaultThinkingLevel(level: "off" | "low" | "medium" | "high" | "xhigh" | "adaptive"): void {
|
|
901
918
|
this.setGlobalSetting("defaultThinkingLevel", level);
|
|
902
919
|
}
|
|
903
920
|
|
|
@@ -909,6 +926,14 @@ export class SettingsManager {
|
|
|
909
926
|
this.setGlobalSetting("anthropicAdaptiveByDefault", enabled);
|
|
910
927
|
}
|
|
911
928
|
|
|
929
|
+
getClientAdaptiveByDefault(): boolean {
|
|
930
|
+
return this.settings.clientAdaptiveByDefault ?? true;
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
setClientAdaptiveByDefault(enabled: boolean): void {
|
|
934
|
+
this.setGlobalSetting("clientAdaptiveByDefault", enabled);
|
|
935
|
+
}
|
|
936
|
+
|
|
912
937
|
getTransport(): TransportSetting {
|
|
913
938
|
return this.settings.transport ?? "sse";
|
|
914
939
|
}
|
|
@@ -1094,15 +1119,15 @@ export class SettingsManager {
|
|
|
1094
1119
|
this.setGlobalSetting("enableSkillCommands", enabled);
|
|
1095
1120
|
}
|
|
1096
1121
|
|
|
1097
|
-
getToolProfile(): "balanced" | "full" {
|
|
1122
|
+
getToolProfile(): "balanced" | "standard" | "full" {
|
|
1098
1123
|
const profile = this.settings.toolProfile;
|
|
1099
|
-
if (profile === "balanced" || profile === "full") return profile;
|
|
1124
|
+
if (profile === "balanced" || profile === "standard" || profile === "full") return profile;
|
|
1100
1125
|
// Migrate legacy minimal/toolSearch settings to balanced.
|
|
1101
1126
|
if (this.settings.toolSearch !== undefined) return "balanced";
|
|
1102
|
-
return "
|
|
1127
|
+
return "standard";
|
|
1103
1128
|
}
|
|
1104
1129
|
|
|
1105
|
-
setToolProfile(profile: "balanced" | "full"): void {
|
|
1130
|
+
setToolProfile(profile: "balanced" | "standard" | "full"): void {
|
|
1106
1131
|
this.setGlobalSetting("toolProfile", profile);
|
|
1107
1132
|
// Keep legacy field in sync with deprecated minimal mode removal.
|
|
1108
1133
|
this.setGlobalSetting("toolSearch", false);
|
|
@@ -1164,6 +1189,14 @@ export class SettingsManager {
|
|
|
1164
1189
|
this.setGlobalSetting("codexRotate", enabled);
|
|
1165
1190
|
}
|
|
1166
1191
|
|
|
1192
|
+
getFastMode(): boolean {
|
|
1193
|
+
return this.settings.fastMode ?? false;
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
setFastMode(enabled: boolean): void {
|
|
1197
|
+
this.setGlobalSetting("fastMode", enabled);
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1167
1200
|
getCacheTimer(): boolean {
|
|
1168
1201
|
return this.settings.cacheTimer ?? true;
|
|
1169
1202
|
}
|
|
@@ -1422,6 +1455,14 @@ export class SettingsManager {
|
|
|
1422
1455
|
this.setGlobalSetting("autoMemory", enabled);
|
|
1423
1456
|
}
|
|
1424
1457
|
|
|
1458
|
+
getNotificationSound(): boolean {
|
|
1459
|
+
return this.settings.notificationSound ?? false;
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1462
|
+
setNotificationSound(enabled: boolean): void {
|
|
1463
|
+
this.setGlobalSetting("notificationSound", enabled);
|
|
1464
|
+
}
|
|
1465
|
+
|
|
1425
1466
|
getTelegramLiveRelayAutoConnect(): boolean {
|
|
1426
1467
|
return this.settings.telegramLiveRelayAutoConnect ?? false;
|
|
1427
1468
|
}
|
|
@@ -332,9 +332,12 @@ export function formatSkillsForPrompt(skills: Skill[]): string {
|
|
|
332
332
|
];
|
|
333
333
|
|
|
334
334
|
for (const skill of visibleSkills) {
|
|
335
|
+
const cappedDescription = skill.description.length > 200
|
|
336
|
+
? skill.description.slice(0, 197) + "..."
|
|
337
|
+
: skill.description;
|
|
335
338
|
lines.push(" <skill>");
|
|
336
339
|
lines.push(` <name>${escapeXml(skill.name)}</name>`);
|
|
337
|
-
lines.push(` <description>${escapeXml(
|
|
340
|
+
lines.push(` <description>${escapeXml(cappedDescription)}</description>`);
|
|
338
341
|
lines.push(` <location>${escapeXml(skill.filePath)}</location>`);
|
|
339
342
|
lines.push(" </skill>");
|
|
340
343
|
}
|
|
@@ -27,6 +27,7 @@ export const BUILTIN_SLASH_COMMANDS: ReadonlyArray<BuiltinSlashCommand> = [
|
|
|
27
27
|
{ name: "session", description: "Show session info and stats" },
|
|
28
28
|
{ name: "changelog", description: "Show changelog entries" },
|
|
29
29
|
{ name: "hotkeys", description: "Show all keyboard shortcuts" },
|
|
30
|
+
{ name: "btw", description: "Ask a side question without interrupting the current task" },
|
|
30
31
|
{ name: "fork", description: "Create a new fork from a previous message" },
|
|
31
32
|
{ name: "tree", description: "Navigate session tree (switch branches)" },
|
|
32
33
|
{ name: "provider", description: "Manage provider configuration" },
|
|
@@ -40,7 +41,7 @@ export const BUILTIN_SLASH_COMMANDS: ReadonlyArray<BuiltinSlashCommand> = [
|
|
|
40
41
|
{ name: "compact", description: "Manually compact the session context" },
|
|
41
42
|
{ name: "resume", description: "Resume a different session" },
|
|
42
43
|
{ name: "reload", description: "Reload extensions, skills, prompts, and themes" },
|
|
43
|
-
{ name: "thinking", description: "Set thinking level (off/
|
|
44
|
+
{ name: "thinking", description: "Set thinking level (off/low/medium/high/xhigh)" },
|
|
44
45
|
{ name: "edit-mode", description: "Toggle edit mode (standard/hashline)" },
|
|
45
46
|
{ name: "terminal", description: "Run a shell command directly (e.g. /terminal ping -c3 1.1.1.1)" },
|
|
46
47
|
{ name: "quit", description: "Quit pi" },
|
|
@@ -149,14 +149,22 @@ export function buildSystemPrompt(options: BuildSystemPromptOptions = {}): strin
|
|
|
149
149
|
const hasLsp = tools.includes("lsp");
|
|
150
150
|
|
|
151
151
|
// Priority-ordered compact guidelines
|
|
152
|
-
addGuideline("
|
|
152
|
+
addGuideline("Terse output. All technical substance stays. Only fluff dies.");
|
|
153
|
+
addGuideline("Drop: articles (a/an/the), filler (just/really/basically/actually/simply), pleasantries (sure/certainly/of course/happy to), hedging (might be worth/could consider).");
|
|
154
|
+
addGuideline("Fragments OK. Short synonyms (big not extensive, fix not implement a solution for). Pattern: [thing] [action] [reason]. [next step].");
|
|
155
|
+
addGuideline("Never announce what you're about to do — just do it. Never summarize what you just did unless the user asks.");
|
|
156
|
+
addGuideline("Code blocks, error messages, file paths, and technical terms stay exact. Only compress prose.");
|
|
157
|
+
addGuideline("For security warnings, irreversible actions, or multi-step sequences where fragments risk misread — use full clear sentences. Resume terse after.");
|
|
153
158
|
addGuideline("For conceptual, product, or UX questions, answer first; inspect code only if implementation detail is needed.");
|
|
154
159
|
|
|
155
160
|
const hasSubagent = tools.includes("subagent");
|
|
156
161
|
|
|
157
162
|
if (hasLsp) {
|
|
158
163
|
addGuideline(
|
|
159
|
-
"Code navigation in typed codebases: use lsp for symbols (definition, references, implementation, hover, diagnostics, rename, format). Use grep/find/ls for text patterns, filenames, and non-code files.",
|
|
164
|
+
"Code navigation in typed codebases: use lsp first for symbols (definition, references, implementation, type info, hover, callers, diagnostics, rename, format). Do not use grep/find as a substitute for symbol navigation when LSP is available. Use grep/find/ls for raw text patterns, filenames, and non-code files. If LSP is unavailable or failing, say so briefly and then fall back to grep/read.",
|
|
165
|
+
);
|
|
166
|
+
addGuideline(
|
|
167
|
+
"Before choosing a code navigation tool, classify intent: symbol lookup (definition/reference/implementation/type/caller/rename) → lsp; raw text or filename search → grep/find.",
|
|
160
168
|
);
|
|
161
169
|
} else {
|
|
162
170
|
addGuideline("Use grep/find/ls for code search and file exploration (faster than bash, respects .gitignore)");
|
|
@@ -219,6 +227,9 @@ export function buildSystemPrompt(options: BuildSystemPromptOptions = {}): strin
|
|
|
219
227
|
}
|
|
220
228
|
|
|
221
229
|
const guidelines = guidelinesList.map((g) => `- ${g}`).join("\n");
|
|
230
|
+
const lspDecisionTable = hasLsp
|
|
231
|
+
? `\n\nTool selection — code navigation quick map:\n\n| Intent | Use | Avoid |\n| --- | --- | --- |\n| Find where a symbol is defined | \`lsp definition\` | \`grep\` |\n| Find all usages of a symbol | \`lsp references\` | \`grep\` |\n| Find implementations of an interface/type | \`lsp implementation\` | \`grep\` |\n| Get type info/docs for a symbol | \`lsp hover\` | raw text search |\n| Find callers of a function | \`lsp incoming_calls\` | \`grep\` |\n| Search literal text patterns (TODO, logs, strings) | \`grep\` | \`lsp\` |\n| Search filenames/paths | \`find\` / \`ls\` | \`lsp\` |\n| Rename a symbol across codebase | \`lsp rename\` | find-and-replace |\n| Check type errors after edits | \`lsp diagnostics\` | ad-hoc grep |\n| Format a file | \`lsp format\` | external formatter guesswork |`
|
|
232
|
+
: "";
|
|
222
233
|
|
|
223
234
|
const piDocsBlock = existsSync(readmePath)
|
|
224
235
|
? `\n\nPi documentation (read only when the user asks about pi itself, its SDK, extensions, themes, skills, or TUI):
|
|
@@ -236,7 +247,7 @@ ${toolsList}
|
|
|
236
247
|
In addition to the tools above, you may have access to other custom tools depending on the project.
|
|
237
248
|
|
|
238
249
|
Guidelines:
|
|
239
|
-
${guidelines}${piDocsBlock}`;
|
|
250
|
+
${guidelines}${lspDecisionTable}${piDocsBlock}`;
|
|
240
251
|
|
|
241
252
|
if (appendSection) {
|
|
242
253
|
prompt += appendSection;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { describe, it } from "node:test";
|
|
3
|
+
|
|
4
|
+
import { getToolPriority, shouldCollapse } from "./tool-priority.js";
|
|
5
|
+
|
|
6
|
+
describe("tool priority", () => {
|
|
7
|
+
it("keeps edit and write always visible", () => {
|
|
8
|
+
assert.equal(getToolPriority("edit"), "always");
|
|
9
|
+
assert.equal(getToolPriority("write"), "always");
|
|
10
|
+
assert.equal(shouldCollapse("edit", false), false);
|
|
11
|
+
assert.equal(shouldCollapse("write", true), false);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it("collapses bash and bg_shell only on success", () => {
|
|
15
|
+
assert.equal(getToolPriority("bash"), "on-error");
|
|
16
|
+
assert.equal(getToolPriority("bg_shell"), "on-error");
|
|
17
|
+
assert.equal(shouldCollapse("bash", false), true);
|
|
18
|
+
assert.equal(shouldCollapse("bash", true), false);
|
|
19
|
+
assert.equal(shouldCollapse("bg_shell", false), true);
|
|
20
|
+
assert.equal(shouldCollapse("bg_shell", true), false);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("collapses read, grep, and unknown tools", () => {
|
|
24
|
+
assert.equal(getToolPriority("read"), "collapse");
|
|
25
|
+
assert.equal(getToolPriority("grep"), "collapse");
|
|
26
|
+
assert.equal(getToolPriority("unknown-tool"), "collapse");
|
|
27
|
+
assert.equal(shouldCollapse("read", false), true);
|
|
28
|
+
assert.equal(shouldCollapse("unknown-tool", true), true);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type ToolPriority = "always" | "on-error" | "collapse";
|
|
2
|
+
|
|
3
|
+
const ALWAYS_VISIBLE = new Set(["edit", "write"]);
|
|
4
|
+
const ON_ERROR = new Set(["bash", "bg_shell"]);
|
|
5
|
+
|
|
6
|
+
export function getToolPriority(toolName: string): ToolPriority {
|
|
7
|
+
if (ALWAYS_VISIBLE.has(toolName)) return "always";
|
|
8
|
+
if (ON_ERROR.has(toolName)) return "on-error";
|
|
9
|
+
return "collapse";
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function shouldCollapse(toolName: string, isError: boolean): boolean {
|
|
13
|
+
const priority = getToolPriority(toolName);
|
|
14
|
+
if (priority === "always") return false;
|
|
15
|
+
if (priority === "on-error") return !isError;
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
@@ -66,7 +66,7 @@ export function createGrepTool(cwd: string, options?: GrepToolOptions): AgentToo
|
|
|
66
66
|
return {
|
|
67
67
|
name: "grep",
|
|
68
68
|
label: "grep",
|
|
69
|
-
description: `Search file contents for a text pattern. Returns matching lines with file paths and line numbers. Respects .gitignore. Output is truncated to ${DEFAULT_LIMIT} matches or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). Long lines are truncated to ${GREP_MAX_LINE_LENGTH} chars. For
|
|
69
|
+
description: `Search file contents for a text pattern. Returns matching lines with file paths and line numbers. Respects .gitignore. Output is truncated to ${DEFAULT_LIMIT} matches or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). Long lines are truncated to ${GREP_MAX_LINE_LENGTH} chars. Use this for raw text search, not semantic code navigation. For symbol definitions, references, type info, callers, implementations, or rename targets in code, use the \`lsp\` tool instead when available.`,
|
|
70
70
|
parameters: grepSchema,
|
|
71
71
|
execute: async (
|
|
72
72
|
_toolCallId: string,
|
|
@@ -148,6 +148,9 @@ export const readOnlyTools: Tool[] = [readTool, grepTool, findTool, lsTool];
|
|
|
148
148
|
|
|
149
149
|
const ptyBuiltinTools = createPtyTools(process.cwd());
|
|
150
150
|
|
|
151
|
+
/** Write raw input to an active agent PTY session. Used by the UI for user-controlled focus. */
|
|
152
|
+
export const writeToPtySession: (sessionId: string, input: string) => void = ptyBuiltinTools.writeToSession;
|
|
153
|
+
|
|
151
154
|
// All available tools (using process.cwd())
|
|
152
155
|
export const allTools = {
|
|
153
156
|
read: readTool,
|
|
@@ -81,7 +81,7 @@ export interface PtyToolDetails {
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
class PtySessionManager {
|
|
84
|
-
|
|
84
|
+
readonly sessions = new Map<string, ManagedPtySession>();
|
|
85
85
|
|
|
86
86
|
constructor(private cwd: string) {}
|
|
87
87
|
|
|
@@ -196,17 +196,34 @@ class PtySessionManager {
|
|
|
196
196
|
|
|
197
197
|
async wait(
|
|
198
198
|
sessionId: string,
|
|
199
|
-
options?: { text?: string; view?: "viewport" | "buffer"; timeoutMs?: number; stableMs?: number },
|
|
199
|
+
options?: { text?: string; view?: "viewport" | "buffer"; timeoutMs?: number; stableMs?: number; signal?: AbortSignal; onUpdate?: (result: { content: Array<{ type: string; text: string }>; details: any }) => void },
|
|
200
200
|
): Promise<{ session: ManagedPtySession; text: string }> {
|
|
201
201
|
const timeoutMs = Math.max(50, options?.timeoutMs ?? 30000);
|
|
202
202
|
const stableMs = Math.max(50, options?.stableMs ?? 800);
|
|
203
203
|
const view = options?.view ?? "viewport";
|
|
204
|
+
const signal = options?.signal;
|
|
205
|
+
const onUpdate = options?.onUpdate;
|
|
204
206
|
const start = Date.now();
|
|
205
207
|
let lastSnapshot = "";
|
|
206
208
|
let stableSince = Date.now();
|
|
209
|
+
let lastUpdateText = "";
|
|
207
210
|
|
|
208
211
|
while (Date.now() - start < timeoutMs) {
|
|
212
|
+
if (signal?.aborted) {
|
|
213
|
+
throw new Error(`pty_wait cancelled`);
|
|
214
|
+
}
|
|
209
215
|
const { text } = await this.read(sessionId, view);
|
|
216
|
+
|
|
217
|
+
// Push live screen text updates to UI
|
|
218
|
+
if (onUpdate && text !== lastUpdateText) {
|
|
219
|
+
lastUpdateText = text;
|
|
220
|
+
const session = this.get(sessionId);
|
|
221
|
+
onUpdate({
|
|
222
|
+
content: [{ type: "text", text: buildReadText(session, view, text) }],
|
|
223
|
+
details: { sessionId, pid: session.pty.handle.pid, completed: session.completed, cancelled: session.cancelled, exitCode: session.exitCode, view, screenText: text },
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
|
|
210
227
|
if (options?.text) {
|
|
211
228
|
if (text.includes(options.text)) {
|
|
212
229
|
return { session: this.get(sessionId), text };
|
|
@@ -222,7 +239,10 @@ class PtySessionManager {
|
|
|
222
239
|
return { session: this.get(sessionId), text };
|
|
223
240
|
}
|
|
224
241
|
}
|
|
225
|
-
await new Promise((resolve) =>
|
|
242
|
+
await new Promise<void>((resolve) => {
|
|
243
|
+
const t = setTimeout(resolve, 100);
|
|
244
|
+
signal?.addEventListener("abort", () => { clearTimeout(t); resolve(); }, { once: true });
|
|
245
|
+
});
|
|
226
246
|
}
|
|
227
247
|
|
|
228
248
|
await this.read(sessionId, view);
|
|
@@ -249,7 +269,17 @@ function buildReadText(session: ManagedPtySession, view: "viewport" | "buffer",
|
|
|
249
269
|
return text ? `${header}\n${text}` : `${header}\n(no visible text)`;
|
|
250
270
|
}
|
|
251
271
|
|
|
252
|
-
export
|
|
272
|
+
export interface PtyToolsResult {
|
|
273
|
+
pty_start: AgentTool<any, PtyToolDetails>;
|
|
274
|
+
pty_send: AgentTool<any, PtyToolDetails>;
|
|
275
|
+
pty_read: AgentTool<any, PtyToolDetails>;
|
|
276
|
+
pty_wait: AgentTool<any, PtyToolDetails>;
|
|
277
|
+
pty_resize: AgentTool<any, PtyToolDetails>;
|
|
278
|
+
pty_kill: AgentTool<any, PtyToolDetails>;
|
|
279
|
+
writeToSession: (sessionId: string, input: string) => void;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
export function createPtyTools(cwd: string): PtyToolsResult {
|
|
253
283
|
const manager = new PtySessionManager(cwd);
|
|
254
284
|
|
|
255
285
|
const ptyStartTool: AgentTool<typeof ptyStartSchema, PtyToolDetails> = {
|
|
@@ -302,9 +332,9 @@ export function createPtyTools(cwd: string): Record<string, AgentTool<any, PtyTo
|
|
|
302
332
|
label: "pty_wait",
|
|
303
333
|
description: "Wait until text appears in a PTY session or until the PTY screen stops changing. Useful between pty_send calls.",
|
|
304
334
|
parameters: ptyWaitSchema,
|
|
305
|
-
execute: async (_toolCallId, { sessionId, text, view, timeoutMs, stableMs }) => {
|
|
335
|
+
execute: async (_toolCallId, { sessionId, text, view, timeoutMs, stableMs }, signal, onUpdate) => {
|
|
306
336
|
const effectiveView = view ?? "viewport";
|
|
307
|
-
const result = await manager.wait(sessionId, { text, view: effectiveView, timeoutMs, stableMs });
|
|
337
|
+
const result = await manager.wait(sessionId, { text, view: effectiveView, timeoutMs, stableMs, signal, onUpdate: onUpdate as ((result: { content: Array<{ type: string; text: string }>; details: any }) => void) | undefined });
|
|
308
338
|
return {
|
|
309
339
|
content: [{ type: "text", text: buildReadText(result.session, effectiveView, result.text) }],
|
|
310
340
|
details: { sessionId, pid: result.session.pty.handle.pid, completed: result.session.completed, cancelled: result.session.cancelled, exitCode: result.session.exitCode, view: effectiveView, screenText: result.text },
|
|
@@ -341,6 +371,14 @@ export function createPtyTools(cwd: string): Record<string, AgentTool<any, PtyTo
|
|
|
341
371
|
},
|
|
342
372
|
};
|
|
343
373
|
|
|
374
|
+
/** Write raw input to an active PTY session by ID. Used by the UI when the user focuses and types into an agent PTY terminal. */
|
|
375
|
+
function writeToSession(sessionId: string, input: string): void {
|
|
376
|
+
const session = manager.sessions.get(sessionId);
|
|
377
|
+
if (session && !session.completed && session.pty.handle.isActive()) {
|
|
378
|
+
session.pty.handle.write(input);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
344
382
|
return {
|
|
345
383
|
pty_start: ptyStartTool,
|
|
346
384
|
pty_send: ptySendTool,
|
|
@@ -348,6 +386,7 @@ export function createPtyTools(cwd: string): Record<string, AgentTool<any, PtyTo
|
|
|
348
386
|
pty_wait: ptyWaitTool,
|
|
349
387
|
pty_resize: ptyResizeTool,
|
|
350
388
|
pty_kill: ptyKillTool,
|
|
389
|
+
writeToSession,
|
|
351
390
|
};
|
|
352
391
|
}
|
|
353
392
|
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { describe, it } from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import stripAnsi from "strip-ansi";
|
|
4
|
+
|
|
5
|
+
import { ToolSummaryLine } from "../tool-summary-line.js";
|
|
6
|
+
import { initTheme } from "../../theme/theme.js";
|
|
7
|
+
|
|
8
|
+
initTheme("dark");
|
|
9
|
+
|
|
10
|
+
describe("ToolSummaryLine", () => {
|
|
11
|
+
it("aggregates repeated tools with tool-row style formatting", () => {
|
|
12
|
+
const summary = new ToolSummaryLine();
|
|
13
|
+
summary.addTool("read", 600);
|
|
14
|
+
summary.addTool("lsp", 250);
|
|
15
|
+
summary.addTool("read", 150);
|
|
16
|
+
|
|
17
|
+
const rendered = stripAnsi(summary.render(160).join("\n"));
|
|
18
|
+
assert.match(rendered, /^ ● collapsed tools /);
|
|
19
|
+
assert.ok(rendered.includes("read ×2 · lsp · 1.0s"));
|
|
20
|
+
assert.equal(rendered.includes("⎯"), false);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("renders nothing when empty or hidden", () => {
|
|
24
|
+
const summary = new ToolSummaryLine();
|
|
25
|
+
assert.deepEqual(summary.render(80), []);
|
|
26
|
+
|
|
27
|
+
summary.addTool("grep", 100);
|
|
28
|
+
summary.setHidden(true);
|
|
29
|
+
assert.deepEqual(summary.render(80), []);
|
|
30
|
+
});
|
|
31
|
+
});
|