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
|
@@ -51,6 +51,14 @@ const OptionSchema = Type.Object({
|
|
|
51
51
|
description: Type.String({ description: "One short sentence explaining impact/tradeoff if selected" }),
|
|
52
52
|
});
|
|
53
53
|
|
|
54
|
+
const ShowWhenSchema = Type.Object({
|
|
55
|
+
questionId: Type.String({ description: "Earlier question id this question depends on" }),
|
|
56
|
+
selectedAnyOf: Type.Array(Type.String(), {
|
|
57
|
+
description: "Show this question only when the earlier question selection includes one of these labels",
|
|
58
|
+
minItems: 1,
|
|
59
|
+
}),
|
|
60
|
+
});
|
|
61
|
+
|
|
54
62
|
const QuestionSchema = Type.Object({
|
|
55
63
|
id: Type.String({ description: "Stable identifier for mapping answers (snake_case)" }),
|
|
56
64
|
header: Type.String({ description: "Short header label shown in the UI (12 or fewer chars)" }),
|
|
@@ -65,6 +73,7 @@ const QuestionSchema = Type.Object({
|
|
|
65
73
|
"If true, the user can select multiple options using SPACE to toggle and ENTER to confirm. No 'None of the above' option is added. Default: false.",
|
|
66
74
|
}),
|
|
67
75
|
),
|
|
76
|
+
showWhen: Type.Optional(ShowWhenSchema),
|
|
68
77
|
});
|
|
69
78
|
|
|
70
79
|
const AskUserQuestionsParams = Type.Object({
|
|
@@ -88,6 +97,40 @@ function errorResult(
|
|
|
88
97
|
}
|
|
89
98
|
|
|
90
99
|
/** Convert the shared RoundResult into the JSON the LLM expects. */
|
|
100
|
+
function selectedLabels(answer: { answers: string[] } | undefined): string[] {
|
|
101
|
+
if (!answer) return [];
|
|
102
|
+
return answer.answers.filter((item) => typeof item === "string" && !item.startsWith("user_note:"));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function shouldAskQuestion(
|
|
106
|
+
question: Question,
|
|
107
|
+
answers: Record<string, { answers: string[] }>,
|
|
108
|
+
): boolean {
|
|
109
|
+
if (!question.showWhen) return true;
|
|
110
|
+
const controlling = answers[question.showWhen.questionId];
|
|
111
|
+
if (!controlling) return false;
|
|
112
|
+
const selected = selectedLabels(controlling);
|
|
113
|
+
return selected.some((label) => question.showWhen?.selectedAnyOf.includes(label));
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function selectedRoundLabels(answer: { selected: string | string[]; notes: string } | undefined): string[] {
|
|
117
|
+
if (!answer) return [];
|
|
118
|
+
return (Array.isArray(answer.selected) ? answer.selected : [answer.selected]).filter(
|
|
119
|
+
(item): item is string => typeof item === "string" && item.length > 0,
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function shouldRenderRoundQuestion(
|
|
124
|
+
question: Question,
|
|
125
|
+
answers: RoundResult["answers"],
|
|
126
|
+
): boolean {
|
|
127
|
+
if (!question.showWhen) return true;
|
|
128
|
+
const controlling = answers[question.showWhen.questionId];
|
|
129
|
+
if (!controlling) return false;
|
|
130
|
+
const selected = selectedRoundLabels(controlling);
|
|
131
|
+
return selected.some((label) => question.showWhen?.selectedAnyOf.includes(label));
|
|
132
|
+
}
|
|
133
|
+
|
|
91
134
|
function formatForLLM(result: RoundResult): string {
|
|
92
135
|
const answers: Record<string, { answers: string[] }> = {};
|
|
93
136
|
for (const [id, answer] of Object.entries(result.answers)) {
|
|
@@ -118,6 +161,7 @@ export default function AskUserQuestions(pi: ExtensionAPI) {
|
|
|
118
161
|
"Keep questions to 1 when possible; never exceed 3.",
|
|
119
162
|
"For single-select: each question must have 2-3 options. Put the recommended option first with '(Recommended)' suffix. Do not include an 'Other' or 'None of the above' option - the client adds one automatically.",
|
|
120
163
|
"For multi-select: set allowMultiple: true. The user can pick any number of options. No 'None of the above' is added.",
|
|
164
|
+
"For conditional follow-ups, use showWhen.questionId and showWhen.selectedAnyOf on a later question so it only appears after the matching earlier answer.",
|
|
121
165
|
],
|
|
122
166
|
parameters: AskUserQuestionsParams,
|
|
123
167
|
|
|
@@ -136,6 +180,45 @@ export default function AskUserQuestions(pi: ExtensionAPI) {
|
|
|
136
180
|
}
|
|
137
181
|
}
|
|
138
182
|
|
|
183
|
+
for (let i = 0; i < params.questions.length; i++) {
|
|
184
|
+
const q = params.questions[i];
|
|
185
|
+
if (!q.showWhen) continue;
|
|
186
|
+
const controllerIndex = params.questions.findIndex((candidate) => candidate.id === q.showWhen?.questionId);
|
|
187
|
+
if (controllerIndex < 0 || controllerIndex >= i) {
|
|
188
|
+
return errorResult(
|
|
189
|
+
`Error: question "${q.id}" has invalid showWhen.questionId "${q.showWhen.questionId}" (must reference an earlier question id)`,
|
|
190
|
+
params.questions,
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
if (!q.showWhen.selectedAnyOf || q.showWhen.selectedAnyOf.length === 0) {
|
|
194
|
+
return errorResult(
|
|
195
|
+
`Error: question "${q.id}" showWhen.selectedAnyOf must include at least one option label`,
|
|
196
|
+
params.questions,
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
const controller = params.questions[controllerIndex];
|
|
200
|
+
const validLabels = [
|
|
201
|
+
...controller.options.map((option) => option.label),
|
|
202
|
+
...(!controller.allowMultiple ? [OTHER_OPTION_LABEL] : []),
|
|
203
|
+
];
|
|
204
|
+
const invalidLabels = q.showWhen.selectedAnyOf.filter((label) => !validLabels.includes(label));
|
|
205
|
+
if (invalidLabels.length > 0) {
|
|
206
|
+
return errorResult(
|
|
207
|
+
`Error: question "${q.id}" showWhen.selectedAnyOf contains unknown option labels: ${invalidLabels.join(", ")}`,
|
|
208
|
+
params.questions,
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Subagents have no human to respond — fail fast and tell the model to decide autonomously.
|
|
214
|
+
if (process.argv.includes('--subagent-name')) {
|
|
215
|
+
return errorResult(
|
|
216
|
+
"Error: ask_user_questions cannot be used inside a subagent. " +
|
|
217
|
+
"There is no human available. Make a reasonable autonomous decision and proceed.",
|
|
218
|
+
params.questions,
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
|
|
139
222
|
if (!ctx.hasUI) {
|
|
140
223
|
return errorResult("Error: UI not available (non-interactive mode)", params.questions);
|
|
141
224
|
}
|
|
@@ -149,6 +232,9 @@ export default function AskUserQuestions(pi: ExtensionAPI) {
|
|
|
149
232
|
if (!result) {
|
|
150
233
|
const answers: Record<string, { answers: string[] }> = {};
|
|
151
234
|
for (const q of params.questions) {
|
|
235
|
+
if (!shouldAskQuestion(q, answers)) {
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
152
238
|
const options = q.options.map((o) => o.label);
|
|
153
239
|
if (!q.allowMultiple) {
|
|
154
240
|
options.push(OTHER_OPTION_LABEL);
|
|
@@ -262,6 +348,7 @@ export default function AskUserQuestions(pi: ExtensionAPI) {
|
|
|
262
348
|
lines.push(theme.fg("dim", details.channel));
|
|
263
349
|
if (details.response) {
|
|
264
350
|
for (const q of questions) {
|
|
351
|
+
if (!shouldAskQuestion(q, details.response.answers)) continue;
|
|
265
352
|
const answer = details.response.answers[q.id];
|
|
266
353
|
if (!answer) {
|
|
267
354
|
lines.push(`${theme.fg("accent", q.header)}: ${theme.fg("dim", "(no answer)")}`);
|
|
@@ -284,6 +371,7 @@ export default function AskUserQuestions(pi: ExtensionAPI) {
|
|
|
284
371
|
|
|
285
372
|
const lines: string[] = [];
|
|
286
373
|
for (const q of details.questions) {
|
|
374
|
+
if (!shouldRenderRoundQuestion(q, details.response.answers)) continue;
|
|
287
375
|
const answer = (details.response as RoundResult).answers[q.id];
|
|
288
376
|
if (!answer) {
|
|
289
377
|
lines.push(`${theme.fg("accent", q.header)}: ${theme.fg("dim", "(no answer)")}`);
|
|
@@ -44,22 +44,12 @@ export function registerBgShellTool(pi: ExtensionAPI, state: BgShellSharedState)
|
|
|
44
44
|
"group_status (health of a process group), highlights (significant output lines only).",
|
|
45
45
|
|
|
46
46
|
promptGuidelines: [
|
|
47
|
-
"Use bg_shell
|
|
48
|
-
"
|
|
49
|
-
"Use '
|
|
50
|
-
"Use '
|
|
51
|
-
"Use '
|
|
52
|
-
"
|
|
53
|
-
"Set type:'server' and ready_port:3000 for dev servers so readiness detection is automatic.",
|
|
54
|
-
"Set group:'my-stack' on related processes to manage them together with 'group_status'.",
|
|
55
|
-
"Use 'run' to execute a command on a persistent shell session and block until it completes — returns structured output + exit code. Shell state (env vars, cwd, virtualenvs) persists across runs.",
|
|
56
|
-
"Use 'send_and_wait' for interactive CLIs: send input and wait for expected output pattern.",
|
|
57
|
-
"Use 'env' to check the current working directory and active environment variables of a shell session — useful after cd, source, or export commands.",
|
|
58
|
-
"Background processes are session-scoped by default: a new session reaps them unless you set persist_across_sessions:true.",
|
|
59
|
-
"Use 'restart' to kill and relaunch with the same config — preserves restart count.",
|
|
60
|
-
"Background processes are auto-classified (server/build/test/watcher) based on the command.",
|
|
61
|
-
"Process crashes and errors are automatically surfaced as alerts at the start of your next turn — you don't need to poll.",
|
|
62
|
-
"To create a persistent shell session: bg_shell start with type:'shell'. The session stays alive for interactive use with 'send', 'send_and_wait', or 'run'.",
|
|
47
|
+
"Use bg_shell for long-running processes (servers, watchers, builds). Set type:'server' and ready_port for dev servers.",
|
|
48
|
+
"Use 'digest' for status (~30 tokens), 'highlights' for key output, 'output' only for raw debugging. All are incremental.",
|
|
49
|
+
"Use 'run' to execute a command on a persistent shell (state persists). Use 'send_and_wait' for interactive CLIs.",
|
|
50
|
+
"Use 'wait_for_ready' after starting a server — blocks until the port/pattern matches.",
|
|
51
|
+
"Use group:'name' to manage related processes together; 'group_status' for health.",
|
|
52
|
+
"Crashes are auto-surfaced next turn. Use persist_across_sessions:true to survive session restarts.",
|
|
63
53
|
],
|
|
64
54
|
|
|
65
55
|
parameters: Type.Object({
|
|
@@ -84,9 +84,10 @@ export function registerCodegenTools(pi: ExtensionAPI, deps: ToolDeps): void {
|
|
|
84
84
|
break;
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
case "
|
|
87
|
+
case "browser_ref": {
|
|
88
88
|
// Refs are session-specific — add comment
|
|
89
|
-
|
|
89
|
+
const refAction = params.action ?? "click";
|
|
90
|
+
testLines.push(` // browser_ref (${refAction}): ${entry.paramsSummary} — replace with stable selector`);
|
|
90
91
|
actionCount++;
|
|
91
92
|
break;
|
|
92
93
|
}
|
|
@@ -101,9 +102,8 @@ export function registerCodegenTools(pi: ExtensionAPI, deps: ToolDeps): void {
|
|
|
101
102
|
break;
|
|
102
103
|
}
|
|
103
104
|
|
|
104
|
-
case "
|
|
105
|
-
|
|
106
|
-
actionCount++;
|
|
105
|
+
case "browser_fill_ref_handled": {
|
|
106
|
+
// Already handled by browser_ref above
|
|
107
107
|
break;
|
|
108
108
|
}
|
|
109
109
|
|
|
@@ -17,216 +17,138 @@ export function registerNavigationTools(pi: ExtensionAPI, deps: ToolDeps): void
|
|
|
17
17
|
name: "browser_navigate",
|
|
18
18
|
label: "Browser Navigate",
|
|
19
19
|
description:
|
|
20
|
-
"
|
|
20
|
+
"Navigate to a URL, go back/forward in history, or reload the page. " +
|
|
21
|
+
"Use ONLY for locally-running web apps (e.g. http://localhost:3000). " +
|
|
22
|
+
"Do NOT use for documentation sites, GitHub, or external URLs — use web_search instead.",
|
|
21
23
|
parameters: Type.Object({
|
|
22
|
-
|
|
24
|
+
action: Type.Union([
|
|
25
|
+
Type.Literal("goto"),
|
|
26
|
+
Type.Literal("go_back"),
|
|
27
|
+
Type.Literal("go_forward"),
|
|
28
|
+
Type.Literal("reload"),
|
|
29
|
+
], { description: "'goto' — navigate to url (default), 'go_back'/'go_forward' — history, 'reload' — refresh page" }),
|
|
30
|
+
url: Type.Optional(Type.String({ description: "URL to navigate to (required for goto action)." })),
|
|
23
31
|
screenshot: Type.Optional(Type.Boolean({ description: "Capture and return a screenshot (default: false)", default: false })),
|
|
24
32
|
}),
|
|
25
33
|
|
|
26
34
|
async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
|
|
27
|
-
|
|
28
|
-
let beforeState: CompactPageState | null = null;
|
|
29
|
-
try {
|
|
30
|
-
const { page: p } = await deps.ensureBrowser();
|
|
31
|
-
beforeState = await deps.captureCompactPageState(p, { includeBodyText: true });
|
|
32
|
-
actionId = deps.beginTrackedAction("browser_navigate", params, beforeState.url).id;
|
|
33
|
-
await p.goto(params.url, { waitUntil: "domcontentloaded", timeout: 30000 });
|
|
34
|
-
await p.waitForLoadState("networkidle", { timeout: 5000 }).catch(() => { /* networkidle timeout — non-fatal, page may still be usable */ });
|
|
35
|
-
await new Promise(resolve => setTimeout(resolve, 300));
|
|
36
|
-
|
|
37
|
-
const title = await p.title();
|
|
38
|
-
const url = p.url();
|
|
39
|
-
const viewport = p.viewportSize();
|
|
40
|
-
const vpText = viewport ? `${viewport.width}x${viewport.height}` : "unknown";
|
|
41
|
-
const afterState = await deps.captureCompactPageState(p, { includeBodyText: true });
|
|
42
|
-
const summary = deps.formatCompactStateSummary(afterState);
|
|
43
|
-
const jsErrors = deps.getRecentErrors(p.url());
|
|
44
|
-
const diff = diffCompactStates(beforeState, afterState);
|
|
45
|
-
setLastActionBeforeState(beforeState);
|
|
46
|
-
setLastActionAfterState(afterState);
|
|
47
|
-
deps.finishTrackedAction(actionId, {
|
|
48
|
-
status: "success",
|
|
49
|
-
afterUrl: afterState.url,
|
|
50
|
-
warningSummary: jsErrors.trim() || undefined,
|
|
51
|
-
diffSummary: diff.summary,
|
|
52
|
-
changed: diff.changed,
|
|
53
|
-
beforeState,
|
|
54
|
-
afterState,
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
let screenshotContent: any[] = [];
|
|
58
|
-
if (params.screenshot) {
|
|
59
|
-
try {
|
|
60
|
-
let buf = await p.screenshot({ type: "jpeg", quality: 80, scale: "css" });
|
|
61
|
-
buf = await deps.constrainScreenshot(p, buf, "image/jpeg", 80);
|
|
62
|
-
screenshotContent = [{ type: "image", data: buf.toString("base64"), mimeType: "image/jpeg" }];
|
|
63
|
-
} catch { /* non-fatal — screenshot is optional, navigation result is still valid */ }
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return {
|
|
67
|
-
content: [
|
|
68
|
-
{ type: "text", text: `Navigated to: ${url}\nTitle: ${title}\nViewport: ${vpText}\nAction: ${actionId}${jsErrors}\n\nDiff:\n${deps.formatDiffText(diff)}\n\nPage summary:\n${summary}` },
|
|
69
|
-
...screenshotContent,
|
|
70
|
-
],
|
|
71
|
-
details: { title, url, status: "loaded", viewport: vpText, actionId, diff },
|
|
72
|
-
};
|
|
73
|
-
} catch (err: any) {
|
|
74
|
-
if (actionId !== null) {
|
|
75
|
-
deps.finishTrackedAction(actionId, { status: "error", afterUrl: deps.getActivePageOrNull()?.url() ?? "", error: err.message, beforeState: beforeState ?? undefined });
|
|
76
|
-
}
|
|
77
|
-
const errorShot = await deps.captureErrorScreenshot(deps.getActivePageOrNull());
|
|
78
|
-
const content: any[] = [{ type: "text", text: `Navigation failed: ${err.message}` }];
|
|
79
|
-
if (errorShot) {
|
|
80
|
-
content.push({ type: "image", data: errorShot.data, mimeType: errorShot.mimeType });
|
|
81
|
-
}
|
|
82
|
-
return {
|
|
83
|
-
content,
|
|
84
|
-
details: { status: "error", error: err.message, actionId },
|
|
85
|
-
isError: true,
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
},
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
// -------------------------------------------------------------------------
|
|
92
|
-
// browser_go_back
|
|
93
|
-
// -------------------------------------------------------------------------
|
|
94
|
-
pi.registerTool({
|
|
95
|
-
name: "browser_go_back",
|
|
96
|
-
label: "Browser Go Back",
|
|
97
|
-
description: "Navigate back in browser history. Returns a compact page summary after navigation.",
|
|
98
|
-
parameters: Type.Object({}),
|
|
99
|
-
|
|
100
|
-
async execute(_toolCallId, _params, _signal, _onUpdate, _ctx) {
|
|
101
|
-
try {
|
|
102
|
-
const { page: p } = await deps.ensureBrowser();
|
|
103
|
-
const response = await p.goBack({ waitUntil: "domcontentloaded", timeout: 10000 });
|
|
104
|
-
|
|
105
|
-
if (!response) {
|
|
106
|
-
return {
|
|
107
|
-
content: [{ type: "text", text: "No previous page in history." }],
|
|
108
|
-
details: {},
|
|
109
|
-
isError: true,
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
await p.waitForLoadState("networkidle", { timeout: 5000 }).catch(() => { /* networkidle timeout — non-fatal, page may still be usable */ });
|
|
114
|
-
|
|
115
|
-
const title = await p.title();
|
|
116
|
-
const url = p.url();
|
|
117
|
-
const summary = await deps.postActionSummary(p);
|
|
118
|
-
const jsErrors = deps.getRecentErrors(p.url());
|
|
119
|
-
|
|
120
|
-
return {
|
|
121
|
-
content: [{ type: "text", text: `Navigated back to: ${url}\nTitle: ${title}${jsErrors}\n\nPage summary:\n${summary}` }],
|
|
122
|
-
details: { title, url },
|
|
123
|
-
};
|
|
124
|
-
} catch (err: any) {
|
|
125
|
-
const errorShot = await deps.captureErrorScreenshot(deps.getActivePageOrNull());
|
|
126
|
-
const content: any[] = [{ type: "text", text: `Go back failed: ${err.message}` }];
|
|
127
|
-
if (errorShot) {
|
|
128
|
-
content.push({ type: "image", data: errorShot.data, mimeType: errorShot.mimeType });
|
|
129
|
-
}
|
|
130
|
-
return { content, details: { error: err.message }, isError: true };
|
|
131
|
-
}
|
|
132
|
-
},
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
// -------------------------------------------------------------------------
|
|
136
|
-
// browser_go_forward
|
|
137
|
-
// -------------------------------------------------------------------------
|
|
138
|
-
pi.registerTool({
|
|
139
|
-
name: "browser_go_forward",
|
|
140
|
-
label: "Browser Go Forward",
|
|
141
|
-
description: "Navigate forward in browser history. Returns a compact page summary after navigation.",
|
|
142
|
-
parameters: Type.Object({}),
|
|
35
|
+
const action = params.action ?? "goto";
|
|
143
36
|
|
|
144
|
-
async execute(_toolCallId, _params, _signal, _onUpdate, _ctx) {
|
|
145
37
|
try {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
};
|
|
38
|
+
if (action === "goto") {
|
|
39
|
+
return await gotoAction(params);
|
|
40
|
+
} else if (action === "go_back") {
|
|
41
|
+
return await goBackForward("back");
|
|
42
|
+
} else if (action === "go_forward") {
|
|
43
|
+
return await goBackForward("forward");
|
|
44
|
+
} else {
|
|
45
|
+
return await reloadAction();
|
|
155
46
|
}
|
|
156
|
-
|
|
157
|
-
await p.waitForLoadState("networkidle", { timeout: 5000 }).catch(() => { /* networkidle timeout — non-fatal, page may still be usable */ });
|
|
158
|
-
|
|
159
|
-
const title = await p.title();
|
|
160
|
-
const url = p.url();
|
|
161
|
-
const summary = await deps.postActionSummary(p);
|
|
162
|
-
const jsErrors = deps.getRecentErrors(p.url());
|
|
163
|
-
|
|
164
|
-
return {
|
|
165
|
-
content: [{ type: "text", text: `Navigated forward to: ${url}\nTitle: ${title}${jsErrors}\n\nPage summary:\n${summary}` }],
|
|
166
|
-
details: { title, url },
|
|
167
|
-
};
|
|
168
47
|
} catch (err: any) {
|
|
169
48
|
const errorShot = await deps.captureErrorScreenshot(deps.getActivePageOrNull());
|
|
170
|
-
const content: any[] = [{ type: "text", text: `
|
|
171
|
-
if (errorShot) {
|
|
172
|
-
content.push({ type: "image", data: errorShot.data, mimeType: errorShot.mimeType });
|
|
173
|
-
}
|
|
49
|
+
const content: any[] = [{ type: "text" as const, text: `Navigation '${action}' failed: ${err.message}` }];
|
|
50
|
+
if (errorShot) content.push({ type: "image" as const, data: errorShot.data, mimeType: errorShot.mimeType });
|
|
174
51
|
return { content, details: { error: err.message }, isError: true };
|
|
175
52
|
}
|
|
176
53
|
},
|
|
177
54
|
});
|
|
178
55
|
|
|
179
|
-
//
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
56
|
+
// ── action implementations ──
|
|
57
|
+
|
|
58
|
+
async function gotoAction(params: { url?: string; screenshot?: boolean }) {
|
|
59
|
+
if (!params.url) {
|
|
60
|
+
return { content: [{ type: "text" as const, text: "Goto requires a 'url' parameter." }], details: { error: "missing_url" }, isError: true };
|
|
61
|
+
}
|
|
62
|
+
let actionId: number | null = null;
|
|
63
|
+
let beforeState: CompactPageState | null = null;
|
|
64
|
+
const { page: p } = await deps.ensureBrowser();
|
|
65
|
+
beforeState = await deps.captureCompactPageState(p, { includeBodyText: true });
|
|
66
|
+
actionId = deps.beginTrackedAction("browser_navigate", params, beforeState.url).id;
|
|
67
|
+
await p.goto(params.url, { waitUntil: "domcontentloaded", timeout: 30000 });
|
|
68
|
+
await p.waitForLoadState("networkidle", { timeout: 5000 }).catch(() => { /* non-fatal */ });
|
|
69
|
+
await new Promise(resolve => setTimeout(resolve, 300));
|
|
70
|
+
|
|
71
|
+
const title = await p.title();
|
|
72
|
+
const url = p.url();
|
|
73
|
+
const viewport = p.viewportSize();
|
|
74
|
+
const vpText = viewport ? `${viewport.width}x${viewport.height}` : "unknown";
|
|
75
|
+
const afterState = await deps.captureCompactPageState(p, { includeBodyText: true });
|
|
76
|
+
const summary = deps.formatCompactStateSummary(afterState);
|
|
77
|
+
const jsErrors = deps.getRecentErrors(p.url());
|
|
78
|
+
const diff = diffCompactStates(beforeState, afterState);
|
|
79
|
+
setLastActionBeforeState(beforeState);
|
|
80
|
+
setLastActionAfterState(afterState);
|
|
81
|
+
deps.finishTrackedAction(actionId, {
|
|
82
|
+
status: "success", afterUrl: afterState.url, warningSummary: jsErrors.trim() || undefined,
|
|
83
|
+
diffSummary: diff.summary, changed: diff.changed, beforeState, afterState,
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
let screenshotContent: any[] = [];
|
|
87
|
+
if (params.screenshot) {
|
|
189
88
|
try {
|
|
190
|
-
|
|
191
|
-
await
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
89
|
+
let buf = await p.screenshot({ type: "jpeg", quality: 80, scale: "css" });
|
|
90
|
+
buf = await deps.constrainScreenshot(p, buf, "image/jpeg", 80);
|
|
91
|
+
screenshotContent = [{ type: "image" as const, data: buf.toString("base64"), mimeType: "image/jpeg" }];
|
|
92
|
+
} catch { /* non-fatal */ }
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
content: [
|
|
97
|
+
{ type: "text" as const, text: `Navigated to: ${url}\nTitle: ${title}\nViewport: ${vpText}\nAction: ${actionId}${jsErrors}\n\nDiff:\n${deps.formatDiffText(diff)}\n\nPage summary:\n${summary}` },
|
|
98
|
+
...screenshotContent,
|
|
99
|
+
],
|
|
100
|
+
details: { title, url, status: "loaded", viewport: vpText, actionId, diff },
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async function goBackForward(direction: "back" | "forward") {
|
|
105
|
+
const { page: p } = await deps.ensureBrowser();
|
|
106
|
+
const response = direction === "back"
|
|
107
|
+
? await p.goBack({ waitUntil: "domcontentloaded", timeout: 10000 })
|
|
108
|
+
: await p.goForward({ waitUntil: "domcontentloaded", timeout: 10000 });
|
|
109
|
+
|
|
110
|
+
if (!response) {
|
|
111
|
+
return {
|
|
112
|
+
content: [{ type: "text" as const, text: `No ${direction} page in history.` }],
|
|
113
|
+
details: {},
|
|
114
|
+
isError: true,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
await p.waitForLoadState("networkidle", { timeout: 5000 }).catch(() => { /* non-fatal */ });
|
|
119
|
+
const title = await p.title();
|
|
120
|
+
const url = p.url();
|
|
121
|
+
const summary = await deps.postActionSummary(p);
|
|
122
|
+
const jsErrors = deps.getRecentErrors(p.url());
|
|
123
|
+
|
|
124
|
+
return {
|
|
125
|
+
content: [{ type: "text" as const, text: `Navigated ${direction} to: ${url}\nTitle: ${title}${jsErrors}\n\nPage summary:\n${summary}` }],
|
|
126
|
+
details: { title, url },
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
async function reloadAction() {
|
|
131
|
+
const { page: p } = await deps.ensureBrowser();
|
|
132
|
+
await p.reload({ waitUntil: "domcontentloaded", timeout: 30000 });
|
|
133
|
+
await p.waitForLoadState("networkidle", { timeout: 5000 }).catch(() => { /* non-fatal */ });
|
|
134
|
+
|
|
135
|
+
const title = await p.title();
|
|
136
|
+
const url = p.url();
|
|
137
|
+
const viewport = p.viewportSize();
|
|
138
|
+
const vpText = viewport ? `${viewport.width}x${viewport.height}` : "unknown";
|
|
139
|
+
const summary = await deps.postActionSummary(p);
|
|
140
|
+
const jsErrors = deps.getRecentErrors(p.url());
|
|
141
|
+
|
|
142
|
+
let screenshotContent: any[] = [];
|
|
143
|
+
try {
|
|
144
|
+
let buf = await p.screenshot({ type: "jpeg", quality: 80, scale: "css" });
|
|
145
|
+
buf = await deps.constrainScreenshot(p, buf, "image/jpeg", 80);
|
|
146
|
+
screenshotContent = [{ type: "image" as const, data: buf.toString("base64"), mimeType: "image/jpeg" }];
|
|
147
|
+
} catch { /* non-fatal */ }
|
|
148
|
+
|
|
149
|
+
return {
|
|
150
|
+
content: [{ type: "text" as const, text: `Reloaded: ${url}\nTitle: ${title}\nViewport: ${vpText}${jsErrors}\n\nPage summary:\n${summary}` }, ...screenshotContent],
|
|
151
|
+
details: { title, url, viewport: vpText },
|
|
152
|
+
};
|
|
153
|
+
}
|
|
232
154
|
}
|