@humain/terminal 0.0.2 → 0.0.3-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +241 -24
- package/README.md +143 -119
- package/dist/cli/args.d.ts +4 -2
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +37 -39
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/auth-check.d.ts +19 -0
- package/dist/cli/auth-check.d.ts.map +1 -0
- package/dist/cli/auth-check.js +50 -0
- package/dist/cli/auth-check.js.map +1 -0
- package/dist/cli/auth-command.d.ts +24 -0
- package/dist/cli/auth-command.d.ts.map +1 -0
- package/dist/cli/auth-command.js +103 -0
- package/dist/cli/auth-command.js.map +1 -0
- package/dist/cli/config-selector.d.ts.map +1 -1
- package/dist/cli/config-selector.js +2 -2
- package/dist/cli/config-selector.js.map +1 -1
- package/dist/cli/credential-print.d.ts +5 -15
- package/dist/cli/credential-print.d.ts.map +1 -1
- package/dist/cli/credential-print.js +42 -83
- package/dist/cli/credential-print.js.map +1 -1
- package/dist/cli/experimental/auth.d.ts +16 -0
- package/dist/cli/experimental/auth.d.ts.map +1 -0
- package/dist/cli/experimental/auth.js +13 -0
- package/dist/cli/experimental/auth.js.map +1 -0
- package/dist/cli/experimental/cli.d.ts +6 -0
- package/dist/cli/experimental/cli.d.ts.map +1 -0
- package/dist/cli/experimental/cli.js +5 -0
- package/dist/cli/experimental/cli.js.map +1 -0
- package/dist/cli/experimental/command-options.d.ts +17 -0
- package/dist/cli/experimental/command-options.d.ts.map +1 -0
- package/dist/cli/experimental/command-options.js +35 -0
- package/dist/cli/experimental/command-options.js.map +1 -0
- package/dist/cli/experimental/command.d.ts +63 -0
- package/dist/cli/experimental/command.d.ts.map +1 -0
- package/dist/cli/experimental/command.js +130 -0
- package/dist/cli/experimental/command.js.map +1 -0
- package/dist/cli/experimental/commands/client.d.ts +13 -0
- package/dist/cli/experimental/commands/client.d.ts.map +1 -0
- package/dist/cli/experimental/commands/client.js +25 -0
- package/dist/cli/experimental/commands/client.js.map +1 -0
- package/dist/cli/experimental/commands/pi.d.ts +15 -0
- package/dist/cli/experimental/commands/pi.d.ts.map +1 -0
- package/dist/cli/experimental/commands/pi.js +28 -0
- package/dist/cli/experimental/commands/pi.js.map +1 -0
- package/dist/cli/experimental/commands/server.d.ts +13 -0
- package/dist/cli/experimental/commands/server.d.ts.map +1 -0
- package/dist/cli/experimental/commands/server.js +25 -0
- package/dist/cli/experimental/commands/server.js.map +1 -0
- package/dist/cli/experimental/transport-address.d.ts +10 -0
- package/dist/cli/experimental/transport-address.d.ts.map +1 -0
- package/dist/cli/experimental/transport-address.js +38 -0
- package/dist/cli/experimental/transport-address.js.map +1 -0
- package/dist/cli/list-models.d.ts +1 -1
- package/dist/cli/list-models.d.ts.map +1 -1
- package/dist/cli/list-models.js +2 -2
- package/dist/cli/list-models.js.map +1 -1
- package/dist/cli/startup-ui.d.ts +1 -1
- package/dist/cli/startup-ui.d.ts.map +1 -1
- package/dist/cli/startup-ui.js +2 -2
- package/dist/cli/startup-ui.js.map +1 -1
- package/dist/client/index.d.ts +3 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +3 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/remote-session.d.ts +53 -0
- package/dist/client/remote-session.d.ts.map +1 -0
- package/dist/client/remote-session.js +340 -0
- package/dist/client/remote-session.js.map +1 -0
- package/dist/client/transcript.d.ts +12 -0
- package/dist/client/transcript.d.ts.map +1 -0
- package/dist/client/transcript.js +98 -0
- package/dist/client/transcript.js.map +1 -0
- package/dist/core/agent-session-services.d.ts +1 -0
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +1 -0
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +1 -10
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +72 -70
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.d.ts +25 -9
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +237 -39
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +60 -41
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +2 -1
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +3 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +27 -4
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/http-dispatcher.d.ts.map +1 -1
- package/dist/core/http-dispatcher.js +5 -0
- package/dist/core/http-dispatcher.js.map +1 -1
- package/dist/core/keybindings.d.ts +45 -5
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/model-config.d.ts +29 -5
- package/dist/core/model-config.d.ts.map +1 -1
- package/dist/core/model-config.js +4 -0
- package/dist/core/model-config.js.map +1 -1
- package/dist/core/model-registry.d.ts +5 -3
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +13 -10
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts +4 -3
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +42 -10
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/model-runtime.d.ts +30 -13
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +233 -73
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/models-store.d.ts +12 -7
- package/dist/core/models-store.d.ts.map +1 -1
- package/dist/core/models-store.js +83 -14
- package/dist/core/models-store.js.map +1 -1
- package/dist/core/package-manager.d.ts +6 -3
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +80 -61
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/pi-manifest.d.ts +8 -0
- package/dist/core/pi-manifest.d.ts.map +1 -0
- package/dist/core/pi-manifest.js +28 -0
- package/dist/core/pi-manifest.js.map +1 -0
- package/dist/core/provider-composer.d.ts +4 -1
- package/dist/core/provider-composer.d.ts.map +1 -1
- package/dist/core/provider-composer.js +36 -15
- package/dist/core/provider-composer.js.map +1 -1
- package/dist/core/remote-catalog-provider.d.ts.map +1 -1
- package/dist/core/remote-catalog-provider.js +73 -67
- package/dist/core/remote-catalog-provider.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +2 -2
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/runtime-credentials.d.ts +5 -5
- package/dist/core/runtime-credentials.d.ts.map +1 -1
- package/dist/core/runtime-credentials.js +11 -8
- package/dist/core/runtime-credentials.js.map +1 -1
- package/dist/core/sdk.d.ts +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +2 -2
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +3 -1
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +12 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +40 -16
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +8 -0
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts +5 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +16 -15
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit.d.ts +4 -0
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +11 -7
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/find.d.ts +7 -0
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +16 -19
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.d.ts +4 -0
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +5 -1
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/ls.d.ts +4 -0
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js +5 -1
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/read.d.ts +4 -0
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +7 -3
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/write.d.ts +4 -0
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +6 -2
- package/dist/core/tools/write.js.map +1 -1
- package/dist/extensions/llama/index.d.ts.map +1 -1
- package/dist/extensions/llama/index.js +11 -2
- package/dist/extensions/llama/index.js.map +1 -1
- package/dist/extensions/llama/provider.d.ts.map +1 -1
- package/dist/extensions/llama/provider.js +21 -7
- package/dist/extensions/llama/provider.js.map +1 -1
- package/dist/humain/agent-execution-protocol.d.ts +218 -0
- package/dist/humain/agent-execution-protocol.d.ts.map +1 -0
- package/dist/humain/agent-execution-protocol.js +204 -0
- package/dist/humain/agent-execution-protocol.js.map +1 -0
- package/dist/humain/agent-execution-runtime.d.ts +35 -0
- package/dist/humain/agent-execution-runtime.d.ts.map +1 -0
- package/dist/humain/agent-execution-runtime.js +170 -0
- package/dist/humain/agent-execution-runtime.js.map +1 -0
- package/dist/humain/index.d.ts.map +1 -1
- package/dist/humain/index.js +8 -7
- package/dist/humain/index.js.map +1 -1
- package/dist/humain/mcp-adapter/vendor/CHANGELOG.md +660 -0
- package/dist/humain/mcp-adapter/vendor/LICENSE +21 -0
- package/dist/humain/mcp-adapter/vendor/README.md +733 -0
- package/dist/humain/mcp-adapter/vendor/abort.ts +34 -0
- package/dist/humain/mcp-adapter/vendor/agent-dir.ts +60 -0
- package/dist/humain/mcp-adapter/vendor/agent-plugin-loader.ts +377 -0
- package/dist/humain/mcp-adapter/vendor/app-bridge.bundle.js +67 -0
- package/dist/humain/mcp-adapter/vendor/banner.png +0 -0
- package/dist/humain/mcp-adapter/vendor/cli.js +209 -0
- package/dist/humain/mcp-adapter/vendor/commands.ts +627 -0
- package/dist/humain/mcp-adapter/vendor/config.ts +1226 -0
- package/dist/humain/mcp-adapter/vendor/consent-manager.ts +64 -0
- package/dist/humain/mcp-adapter/vendor/direct-tools.ts +604 -0
- package/dist/humain/mcp-adapter/vendor/elicitation-handler.ts +348 -0
- package/dist/humain/mcp-adapter/vendor/error-signal.ts +21 -0
- package/dist/humain/mcp-adapter/vendor/errors.ts +223 -0
- package/dist/humain/mcp-adapter/vendor/glimpse-ui.ts +80 -0
- package/dist/humain/mcp-adapter/vendor/host-html-template.ts +461 -0
- package/dist/humain/mcp-adapter/vendor/index.bundle.d.mts +4 -0
- package/dist/humain/mcp-adapter/vendor/index.bundle.mjs +15923 -0
- package/dist/humain/mcp-adapter/vendor/index.ts +898 -0
- package/dist/humain/mcp-adapter/vendor/init.ts +649 -0
- package/dist/humain/mcp-adapter/vendor/json-schema-validator.ts +69 -0
- package/dist/humain/mcp-adapter/vendor/lifecycle.ts +147 -0
- package/dist/humain/mcp-adapter/vendor/logger.ts +169 -0
- package/dist/humain/mcp-adapter/vendor/mcp-auth-flow.ts +993 -0
- package/dist/humain/mcp-adapter/vendor/mcp-auth.ts +1000 -0
- package/dist/humain/mcp-adapter/vendor/mcp-callback-server.ts +510 -0
- package/dist/humain/mcp-adapter/vendor/mcp-code.ts +354 -0
- package/dist/humain/mcp-adapter/vendor/mcp-keyring-helper.cjs +89 -0
- package/dist/humain/mcp-adapter/vendor/mcp-oauth-provider.ts +616 -0
- package/dist/humain/mcp-adapter/vendor/mcp-output-guard.ts +408 -0
- package/dist/humain/mcp-adapter/vendor/mcp-panel.ts +1015 -0
- package/dist/humain/mcp-adapter/vendor/mcp-probe.ts +187 -0
- package/dist/humain/mcp-adapter/vendor/mcp-script-worker.mjs +130 -0
- package/dist/humain/mcp-adapter/vendor/mcp-setup-panel.ts +666 -0
- package/dist/humain/mcp-adapter/vendor/mcp-status.ts +109 -0
- package/dist/humain/mcp-adapter/vendor/mcp-trace.ts +306 -0
- package/dist/humain/mcp-adapter/vendor/metadata-cache.ts +353 -0
- package/dist/humain/mcp-adapter/vendor/npx-resolver.ts +543 -0
- package/dist/humain/mcp-adapter/vendor/oauth-handler.ts +30 -0
- package/dist/humain/mcp-adapter/vendor/oauth.ts +48 -0
- package/dist/humain/mcp-adapter/vendor/onboarding-state.ts +76 -0
- package/dist/humain/mcp-adapter/vendor/package.json +178 -0
- package/dist/humain/mcp-adapter/vendor/panel-keys.ts +53 -0
- package/dist/humain/mcp-adapter/vendor/prompts.ts +353 -0
- package/dist/humain/mcp-adapter/vendor/proxy-modes.ts +1331 -0
- package/dist/humain/mcp-adapter/vendor/resource-tools.ts +17 -0
- package/dist/humain/mcp-adapter/vendor/runtime-owner.ts +91 -0
- package/dist/humain/mcp-adapter/vendor/sampling-handler.ts +284 -0
- package/dist/humain/mcp-adapter/vendor/search-ranking.ts +206 -0
- package/dist/humain/mcp-adapter/vendor/server-manager.ts +1124 -0
- package/dist/humain/mcp-adapter/vendor/session-recovery.ts +151 -0
- package/dist/humain/mcp-adapter/vendor/skills/mcp-scripting/SKILL.md +38 -0
- package/dist/humain/mcp-adapter/vendor/state.ts +62 -0
- package/dist/humain/mcp-adapter/vendor/tool-approval.ts +182 -0
- package/dist/humain/mcp-adapter/vendor/tool-metadata.ts +276 -0
- package/dist/humain/mcp-adapter/vendor/tool-registrar.ts +253 -0
- package/dist/humain/mcp-adapter/vendor/tool-result-renderer.ts +423 -0
- package/dist/humain/mcp-adapter/vendor/ts-shape.ts +149 -0
- package/dist/humain/mcp-adapter/vendor/types.ts +859 -0
- package/dist/humain/mcp-adapter/vendor/ui-app-bridge-helpers.ts +40 -0
- package/dist/humain/mcp-adapter/vendor/ui-resource-handler.ts +250 -0
- package/dist/humain/mcp-adapter/vendor/ui-server.ts +866 -0
- package/dist/humain/mcp-adapter/vendor/ui-session.ts +570 -0
- package/dist/humain/mcp-adapter/vendor/ui-stream-types.ts +89 -0
- package/dist/humain/mcp-adapter/vendor/ui-tool-visibility.ts +25 -0
- package/dist/humain/mcp-adapter/vendor/unix-socket-transport.ts +85 -0
- package/dist/humain/mcp-adapter/vendor/utils.ts +310 -0
- package/dist/humain/mcp-adapter.d.ts +3 -0
- package/dist/humain/mcp-adapter.d.ts.map +1 -0
- package/dist/humain/mcp-adapter.js +5 -0
- package/dist/humain/mcp-adapter.js.map +1 -0
- package/dist/humain/pi-agent-execution-host.d.ts +34 -0
- package/dist/humain/pi-agent-execution-host.d.ts.map +1 -0
- package/dist/humain/pi-agent-execution-host.js +77 -0
- package/dist/humain/pi-agent-execution-host.js.map +1 -0
- package/dist/humain/web-access/host.d.ts +4 -0
- package/dist/humain/web-access/host.d.ts.map +1 -0
- package/dist/humain/web-access/host.js +3 -0
- package/dist/humain/web-access/host.js.map +1 -0
- package/dist/humain/web-access/index.d.ts +3 -0
- package/dist/humain/web-access/index.d.ts.map +1 -0
- package/dist/humain/web-access/index.js +5 -0
- package/dist/humain/web-access/index.js.map +1 -0
- package/dist/humain/web-access/vendor/activity.d.ts +34 -0
- package/dist/humain/web-access/vendor/activity.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/activity.js +68 -0
- package/dist/humain/web-access/vendor/activity.js.map +1 -0
- package/dist/humain/web-access/vendor/anysearch.d.ts +8 -0
- package/dist/humain/web-access/vendor/anysearch.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/anysearch.js +167 -0
- package/dist/humain/web-access/vendor/anysearch.js.map +1 -0
- package/dist/humain/web-access/vendor/bocha.d.ts +4 -0
- package/dist/humain/web-access/vendor/bocha.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/bocha.js +219 -0
- package/dist/humain/web-access/vendor/bocha.js.map +1 -0
- package/dist/humain/web-access/vendor/brave.d.ts +4 -0
- package/dist/humain/web-access/vendor/brave.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/brave.js +194 -0
- package/dist/humain/web-access/vendor/brave.js.map +1 -0
- package/dist/humain/web-access/vendor/brightdata-unlocker.d.ts +12 -0
- package/dist/humain/web-access/vendor/brightdata-unlocker.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/brightdata-unlocker.js +230 -0
- package/dist/humain/web-access/vendor/brightdata-unlocker.js.map +1 -0
- package/dist/humain/web-access/vendor/brightdata.d.ts +8 -0
- package/dist/humain/web-access/vendor/brightdata.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/brightdata.js +519 -0
- package/dist/humain/web-access/vendor/brightdata.js.map +1 -0
- package/dist/humain/web-access/vendor/chrome-cookies.d.ts +10 -0
- package/dist/humain/web-access/vendor/chrome-cookies.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/chrome-cookies.js +438 -0
- package/dist/humain/web-access/vendor/chrome-cookies.js.map +1 -0
- package/dist/humain/web-access/vendor/content-find.d.ts +11 -0
- package/dist/humain/web-access/vendor/content-find.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/content-find.js +117 -0
- package/dist/humain/web-access/vendor/content-find.js.map +1 -0
- package/dist/humain/web-access/vendor/credential-source.d.ts +28 -0
- package/dist/humain/web-access/vendor/credential-source.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/credential-source.js +151 -0
- package/dist/humain/web-access/vendor/credential-source.js.map +1 -0
- package/dist/humain/web-access/vendor/curator-page.d.ts +29 -0
- package/dist/humain/web-access/vendor/curator-page.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/curator-page.js +3554 -0
- package/dist/humain/web-access/vendor/curator-page.js.map +1 -0
- package/dist/humain/web-access/vendor/curator-server.d.ts +93 -0
- package/dist/humain/web-access/vendor/curator-server.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/curator-server.js +688 -0
- package/dist/humain/web-access/vendor/curator-server.js.map +1 -0
- package/dist/humain/web-access/vendor/datalab-pdf-extract.d.ts +60 -0
- package/dist/humain/web-access/vendor/datalab-pdf-extract.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/datalab-pdf-extract.js +416 -0
- package/dist/humain/web-access/vendor/datalab-pdf-extract.js.map +1 -0
- package/dist/humain/web-access/vendor/declared-web-links.d.ts +16 -0
- package/dist/humain/web-access/vendor/declared-web-links.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/declared-web-links.js +168 -0
- package/dist/humain/web-access/vendor/declared-web-links.js.map +1 -0
- package/dist/humain/web-access/vendor/duckduckgo.d.ts +4 -0
- package/dist/humain/web-access/vendor/duckduckgo.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/duckduckgo.js +123 -0
- package/dist/humain/web-access/vendor/duckduckgo.js.map +1 -0
- package/dist/humain/web-access/vendor/exa.d.ts +10 -0
- package/dist/humain/web-access/vendor/exa.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/exa.js +426 -0
- package/dist/humain/web-access/vendor/exa.js.map +1 -0
- package/dist/humain/web-access/vendor/extract.d.ts +46 -0
- package/dist/humain/web-access/vendor/extract.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/extract.js +1064 -0
- package/dist/humain/web-access/vendor/extract.js.map +1 -0
- package/dist/humain/web-access/vendor/feature-config.d.ts +3 -0
- package/dist/humain/web-access/vendor/feature-config.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/feature-config.js +27 -0
- package/dist/humain/web-access/vendor/feature-config.js.map +1 -0
- package/dist/humain/web-access/vendor/fetch-params.d.ts +25 -0
- package/dist/humain/web-access/vendor/fetch-params.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/fetch-params.js +57 -0
- package/dist/humain/web-access/vendor/fetch-params.js.map +1 -0
- package/dist/humain/web-access/vendor/firecrawl.d.ts +12 -0
- package/dist/humain/web-access/vendor/firecrawl.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/firecrawl.js +239 -0
- package/dist/humain/web-access/vendor/firecrawl.js.map +1 -0
- package/dist/humain/web-access/vendor/gemini-api.d.ts +27 -0
- package/dist/humain/web-access/vendor/gemini-api.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/gemini-api.js +230 -0
- package/dist/humain/web-access/vendor/gemini-api.js.map +1 -0
- package/dist/humain/web-access/vendor/gemini-pdf-extract.d.ts +9 -0
- package/dist/humain/web-access/vendor/gemini-pdf-extract.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/gemini-pdf-extract.js +85 -0
- package/dist/humain/web-access/vendor/gemini-pdf-extract.js.map +1 -0
- package/dist/humain/web-access/vendor/gemini-search.d.ts +40 -0
- package/dist/humain/web-access/vendor/gemini-search.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/gemini-search.js +814 -0
- package/dist/humain/web-access/vendor/gemini-search.js.map +1 -0
- package/dist/humain/web-access/vendor/gemini-url-context.d.ts +4 -0
- package/dist/humain/web-access/vendor/gemini-url-context.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/gemini-url-context.js +101 -0
- package/dist/humain/web-access/vendor/gemini-url-context.js.map +1 -0
- package/dist/humain/web-access/vendor/gemini-web-config.d.ts +4 -0
- package/dist/humain/web-access/vendor/gemini-web-config.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/gemini-web-config.js +42 -0
- package/dist/humain/web-access/vendor/gemini-web-config.js.map +1 -0
- package/dist/humain/web-access/vendor/gemini-web.d.ts +18 -0
- package/dist/humain/web-access/vendor/gemini-web.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/gemini-web.js +385 -0
- package/dist/humain/web-access/vendor/gemini-web.js.map +1 -0
- package/dist/humain/web-access/vendor/github-api.d.ts +7 -0
- package/dist/humain/web-access/vendor/github-api.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/github-api.js +160 -0
- package/dist/humain/web-access/vendor/github-api.js.map +1 -0
- package/dist/humain/web-access/vendor/github-extract.d.ts +13 -0
- package/dist/humain/web-access/vendor/github-extract.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/github-extract.js +635 -0
- package/dist/humain/web-access/vendor/github-extract.js.map +1 -0
- package/dist/humain/web-access/vendor/index.d.ts +4 -0
- package/dist/humain/web-access/vendor/index.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/index.js +3002 -0
- package/dist/humain/web-access/vendor/index.js.map +1 -0
- package/dist/humain/web-access/vendor/jina-search.d.ts +8 -0
- package/dist/humain/web-access/vendor/jina-search.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/jina-search.js +255 -0
- package/dist/humain/web-access/vendor/jina-search.js.map +1 -0
- package/dist/humain/web-access/vendor/kagi.d.ts +15 -0
- package/dist/humain/web-access/vendor/kagi.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/kagi.js +262 -0
- package/dist/humain/web-access/vendor/kagi.js.map +1 -0
- package/dist/humain/web-access/vendor/ollama.d.ts +15 -0
- package/dist/humain/web-access/vendor/ollama.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/ollama.js +216 -0
- package/dist/humain/web-access/vendor/ollama.js.map +1 -0
- package/dist/humain/web-access/vendor/openai-search.d.ts +15 -0
- package/dist/humain/web-access/vendor/openai-search.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/openai-search.js +459 -0
- package/dist/humain/web-access/vendor/openai-search.js.map +1 -0
- package/dist/humain/web-access/vendor/page-query.d.ts +16 -0
- package/dist/humain/web-access/vendor/page-query.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/page-query.js +79 -0
- package/dist/humain/web-access/vendor/page-query.js.map +1 -0
- package/dist/humain/web-access/vendor/parallel.d.ts +12 -0
- package/dist/humain/web-access/vendor/parallel.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/parallel.js +343 -0
- package/dist/humain/web-access/vendor/parallel.js.map +1 -0
- package/dist/humain/web-access/vendor/pdf-extract.d.ts +44 -0
- package/dist/humain/web-access/vendor/pdf-extract.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/pdf-extract.js +298 -0
- package/dist/humain/web-access/vendor/pdf-extract.js.map +1 -0
- package/dist/humain/web-access/vendor/perplexity.d.ts +20 -0
- package/dist/humain/web-access/vendor/perplexity.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/perplexity.js +159 -0
- package/dist/humain/web-access/vendor/perplexity.js.map +1 -0
- package/dist/humain/web-access/vendor/querit.d.ts +10 -0
- package/dist/humain/web-access/vendor/querit.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/querit.js +335 -0
- package/dist/humain/web-access/vendor/querit.js.map +1 -0
- package/dist/humain/web-access/vendor/render-search-error.d.ts +57 -0
- package/dist/humain/web-access/vendor/render-search-error.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/render-search-error.js +130 -0
- package/dist/humain/web-access/vendor/render-search-error.js.map +1 -0
- package/dist/humain/web-access/vendor/rsc-extract.d.ts +12 -0
- package/dist/humain/web-access/vendor/rsc-extract.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/rsc-extract.js +329 -0
- package/dist/humain/web-access/vendor/rsc-extract.js.map +1 -0
- package/dist/humain/web-access/vendor/search1api.d.ts +10 -0
- package/dist/humain/web-access/vendor/search1api.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/search1api.js +251 -0
- package/dist/humain/web-access/vendor/search1api.js.map +1 -0
- package/dist/humain/web-access/vendor/searchinfinity.d.ts +8 -0
- package/dist/humain/web-access/vendor/searchinfinity.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/searchinfinity.js +229 -0
- package/dist/humain/web-access/vendor/searchinfinity.js.map +1 -0
- package/dist/humain/web-access/vendor/searxng.d.ts +4 -0
- package/dist/humain/web-access/vendor/searxng.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/searxng.js +238 -0
- package/dist/humain/web-access/vendor/searxng.js.map +1 -0
- package/dist/humain/web-access/vendor/serpbase.d.ts +4 -0
- package/dist/humain/web-access/vendor/serpbase.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/serpbase.js +211 -0
- package/dist/humain/web-access/vendor/serpbase.js.map +1 -0
- package/dist/humain/web-access/vendor/serpdive.d.ts +8 -0
- package/dist/humain/web-access/vendor/serpdive.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/serpdive.js +267 -0
- package/dist/humain/web-access/vendor/serpdive.js.map +1 -0
- package/dist/humain/web-access/vendor/source-check.d.ts +99 -0
- package/dist/humain/web-access/vendor/source-check.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/source-check.js +205 -0
- package/dist/humain/web-access/vendor/source-check.js.map +1 -0
- package/dist/humain/web-access/vendor/ssrf-protection.d.ts +50 -0
- package/dist/humain/web-access/vendor/ssrf-protection.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/ssrf-protection.js +466 -0
- package/dist/humain/web-access/vendor/ssrf-protection.js.map +1 -0
- package/dist/humain/web-access/vendor/storage.d.ts +55 -0
- package/dist/humain/web-access/vendor/storage.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/storage.js +485 -0
- package/dist/humain/web-access/vendor/storage.js.map +1 -0
- package/dist/humain/web-access/vendor/summary-model-scope.d.ts +25 -0
- package/dist/humain/web-access/vendor/summary-model-scope.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/summary-model-scope.js +98 -0
- package/dist/humain/web-access/vendor/summary-model-scope.js.map +1 -0
- package/dist/humain/web-access/vendor/summary-review.d.ts +24 -0
- package/dist/humain/web-access/vendor/summary-review.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/summary-review.js +341 -0
- package/dist/humain/web-access/vendor/summary-review.js.map +1 -0
- package/dist/humain/web-access/vendor/tavily.d.ts +8 -0
- package/dist/humain/web-access/vendor/tavily.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/tavily.js +194 -0
- package/dist/humain/web-access/vendor/tavily.js.map +1 -0
- package/dist/humain/web-access/vendor/tinyfish.d.ts +11 -0
- package/dist/humain/web-access/vendor/tinyfish.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/tinyfish.js +331 -0
- package/dist/humain/web-access/vendor/tinyfish.js.map +1 -0
- package/dist/humain/web-access/vendor/utils.d.ts +20 -0
- package/dist/humain/web-access/vendor/utils.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/utils.js +91 -0
- package/dist/humain/web-access/vendor/utils.js.map +1 -0
- package/dist/humain/web-access/vendor/video-extract.d.ts +16 -0
- package/dist/humain/web-access/vendor/video-extract.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/video-extract.js +335 -0
- package/dist/humain/web-access/vendor/video-extract.js.map +1 -0
- package/dist/humain/web-access/vendor/xai-search.d.ts +13 -0
- package/dist/humain/web-access/vendor/xai-search.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/xai-search.js +331 -0
- package/dist/humain/web-access/vendor/xai-search.js.map +1 -0
- package/dist/humain/web-access/vendor/youtube-extract.d.ts +27 -0
- package/dist/humain/web-access/vendor/youtube-extract.d.ts.map +1 -0
- package/dist/humain/web-access/vendor/youtube-extract.js +282 -0
- package/dist/humain/web-access/vendor/youtube-extract.js.map +1 -0
- package/dist/index.d.ts +7 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts +2 -2
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +169 -102
- package/dist/main.js.map +1 -1
- package/dist/modes/agent-exec-mode.d.ts +14 -0
- package/dist/modes/agent-exec-mode.d.ts.map +1 -0
- package/dist/modes/agent-exec-mode.js +92 -0
- package/dist/modes/agent-exec-mode.js.map +1 -0
- package/dist/modes/index.d.ts +4 -2
- package/dist/modes/index.d.ts.map +1 -1
- package/dist/modes/index.js +2 -1
- package/dist/modes/index.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts +5 -2
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +13 -4
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js +7 -0
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- package/dist/modes/interactive/components/earendil-announcement.d.ts +5 -0
- package/dist/modes/interactive/components/earendil-announcement.d.ts.map +1 -0
- package/dist/modes/interactive/components/earendil-announcement.js +40 -0
- package/dist/modes/interactive/components/earendil-announcement.js.map +1 -0
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +1 -1
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/markdown-transform.d.ts +3 -0
- package/dist/modes/interactive/components/markdown-transform.d.ts.map +1 -0
- package/dist/modes/interactive/components/markdown-transform.js +19 -0
- package/dist/modes/interactive/components/markdown-transform.js.map +1 -0
- package/dist/modes/interactive/components/mermaid.d.ts +11 -0
- package/dist/modes/interactive/components/mermaid.d.ts.map +1 -0
- package/dist/modes/interactive/components/mermaid.js +75 -0
- package/dist/modes/interactive/components/mermaid.js.map +1 -0
- package/dist/modes/interactive/components/model-selector.d.ts +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +16 -4
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.d.ts +4 -0
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.js +26 -0
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +8 -2
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +30 -0
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/user-message.d.ts +3 -1
- package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message.js +9 -2
- package/dist/modes/interactive/components/user-message.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +45 -9
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +581 -211
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/dark.json +1 -0
- package/dist/modes/interactive/theme/light.json +1 -0
- package/dist/modes/interactive/theme/theme-controller.d.ts +3 -0
- package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme-controller.js +10 -1
- package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
- package/dist/modes/interactive/theme/theme-schema.json +5 -1
- package/dist/modes/interactive/theme/theme.d.ts +2 -2
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +24 -6
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/json-event.d.ts +28 -0
- package/dist/modes/json-event.d.ts.map +1 -0
- package/dist/modes/json-event.js +12 -0
- package/dist/modes/json-event.js.map +1 -0
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +12 -2
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +12 -5
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +55 -1
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +13 -3
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +15 -0
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js +11 -9
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/rpc-entry.d.ts.map +1 -1
- package/dist/rpc-entry.js +3 -2
- package/dist/rpc-entry.js.map +1 -1
- package/dist/server/create-harness.d.ts +26 -0
- package/dist/server/create-harness.d.ts.map +1 -0
- package/dist/server/create-harness.js +104 -0
- package/dist/server/create-harness.js.map +1 -0
- package/dist/utils/abort.d.ts +5 -0
- package/dist/utils/abort.d.ts.map +1 -0
- package/dist/utils/abort.js +48 -0
- package/dist/utils/abort.js.map +1 -0
- package/dist/utils/clipboard.d.ts +1 -1
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +22 -2
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/management-http.d.ts +23 -0
- package/dist/utils/management-http.d.ts.map +1 -0
- package/dist/utils/management-http.js +50 -0
- package/dist/utils/management-http.js.map +1 -0
- package/dist/utils/paths.d.ts +3 -0
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +23 -1
- package/dist/utils/paths.js.map +1 -1
- package/dist/utils/tool-result-images.d.ts +19 -0
- package/dist/utils/tool-result-images.d.ts.map +1 -0
- package/dist/utils/tool-result-images.js +45 -0
- package/dist/utils/tool-result-images.js.map +1 -0
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +13 -25
- package/dist/utils/tools-manager.js.map +1 -1
- package/dist/utils/version-check.d.ts +4 -0
- package/dist/utils/version-check.d.ts.map +1 -1
- package/dist/utils/version-check.js +23 -5
- package/dist/utils/version-check.js.map +1 -1
- package/docs/compaction.md +2 -2
- package/docs/custom-provider.md +7 -5
- package/docs/extensions.md +30 -5
- package/docs/humain-terminal.md +21 -1
- package/docs/json.md +24 -19
- package/docs/keybindings.md +46 -14
- package/docs/models.md +32 -11
- package/docs/providers.md +9 -1
- package/docs/quickstart.md +39 -37
- package/docs/rpc.md +31 -11
- package/docs/sdk.md +21 -2
- package/docs/security.md +21 -21
- package/docs/session-format.md +14 -14
- package/docs/settings.md +4 -1
- package/docs/themes.md +5 -3
- package/docs/usage.md +7 -0
- package/examples/extensions/custom-compaction.ts +3 -18
- package/examples/extensions/custom-provider-anthropic/index.ts +5 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/index.ts +5 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/doom-overlay/wad-finder.ts +7 -3
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/handoff.ts +4 -13
- package/examples/extensions/qna.ts +5 -9
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/summarize.ts +9 -20
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/rpc-extension-ui.ts +11 -2
- package/examples/sdk/02-custom-model.ts +2 -3
- package/examples/sdk/09-api-keys-and-oauth.ts +1 -1
- package/examples/sdk/12-full-control.ts +1 -1
- package/examples/sdk/README.md +1 -1
- package/npm-shrinkwrap.json +2771 -535
- package/package.json +40 -11
- package/src/humain/mcp-adapter/UPSTREAM.md +15 -0
- package/src/humain/mcp-adapter/upstream.json +7 -0
- package/src/humain/mcp-adapter/vendor/CHANGELOG.md +660 -0
- package/src/humain/mcp-adapter/vendor/LICENSE +21 -0
- package/src/humain/web-access/UPSTREAM.md +17 -0
- package/src/humain/web-access/upstream.json +23 -0
- package/src/humain/web-access/vendor/LICENSE +21 -0
|
@@ -6,10 +6,11 @@ import * as crypto from "node:crypto";
|
|
|
6
6
|
import * as fs from "node:fs";
|
|
7
7
|
import * as os from "node:os";
|
|
8
8
|
import * as path from "node:path";
|
|
9
|
-
import
|
|
9
|
+
import * as TuiLayouts from "@earendil-works/pi-tui";
|
|
10
|
+
import { CombinedAutocompleteProvider, Container, fuzzyFilter, getCapabilities, hyperlink, Markdown, matchesKey, ProcessTerminal, Spacer, setKeybindings, Text, TruncatedText, TuiAltScreen, TuiMainScreen, visibleWidth, } from "@earendil-works/pi-tui";
|
|
10
11
|
import chalk from "chalk";
|
|
11
12
|
import { spawn, spawnSync } from "child_process";
|
|
12
|
-
import { APP_NAME, APP_TITLE, CONFIG_DIR_NAME,
|
|
13
|
+
import { APP_NAME, APP_TITLE, CONFIG_DIR_NAME, getAgentDir, getAuthPath, getDebugLogPath, getDocsPath, getShareViewerUrl, VERSION, } from "../../config.js";
|
|
13
14
|
import { parseSkillBlock } from "../../core/agent-session.js";
|
|
14
15
|
import { SessionImportFileNotFoundError } from "../../core/agent-session-runtime.js";
|
|
15
16
|
import { CACHE_TTL_MS, collectCacheMisses, computeCacheWaste, detectCacheMiss, } from "../../core/cache-stats.js";
|
|
@@ -17,7 +18,8 @@ import { FooterDataProvider } from "../../core/footer-data-provider.js";
|
|
|
17
18
|
import { configureHttpDispatcher, formatHttpIdleTimeoutMs } from "../../core/http-dispatcher.js";
|
|
18
19
|
import { KeybindingsManager } from "../../core/keybindings.js";
|
|
19
20
|
import { createCompactionSummaryMessage } from "../../core/messages.js";
|
|
20
|
-
import { defaultModelPerProvider, findExactModelReferenceMatch,
|
|
21
|
+
import { defaultModelPerProvider, findExactModelReferenceMatch, resolveModelScopeFromModels, } from "../../core/model-resolver.js";
|
|
22
|
+
import { CredentialSynchronizationError } from "../../core/model-runtime.js";
|
|
21
23
|
import { DefaultPackageManager } from "../../core/package-manager.js";
|
|
22
24
|
import { formatMissingSessionCwdPrompt, MissingSessionCwdError } from "../../core/session-cwd.js";
|
|
23
25
|
import { SessionManager, sessionEntryToContextMessages } from "../../core/session-manager.js";
|
|
@@ -29,6 +31,8 @@ import { getChangelogPath, getNewEntries, normalizeChangelogLinks, parseChangelo
|
|
|
29
31
|
import { copyToClipboard, readClipboardText } from "../../utils/clipboard.js";
|
|
30
32
|
import { extensionForImageMimeType, readClipboardImage } from "../../utils/clipboard-image.js";
|
|
31
33
|
import { parseGitUrl } from "../../utils/git.js";
|
|
34
|
+
import { openBrowser } from "../../utils/open-browser.js";
|
|
35
|
+
import { getCwdRelativePath } from "../../utils/paths.js";
|
|
32
36
|
import { getPiUserAgent } from "../../utils/pi-user-agent.js";
|
|
33
37
|
import { killTrackedDetachedChildren } from "../../utils/shell.js";
|
|
34
38
|
import { ensureTool } from "../../utils/tools-manager.js";
|
|
@@ -44,12 +48,14 @@ import { CustomEntryComponent } from "./components/custom-entry.js";
|
|
|
44
48
|
import { CustomMessageComponent } from "./components/custom-message.js";
|
|
45
49
|
import { DaxnutsComponent } from "./components/daxnuts.js";
|
|
46
50
|
import { DynamicBorder } from "./components/dynamic-border.js";
|
|
51
|
+
import { EarendilAnnouncementComponent } from "./components/earendil-announcement.js";
|
|
47
52
|
import { ExtensionEditorComponent } from "./components/extension-editor.js";
|
|
48
53
|
import { ExtensionInputComponent } from "./components/extension-input.js";
|
|
49
54
|
import { ExtensionSelectorComponent } from "./components/extension-selector.js";
|
|
50
55
|
import { FooterComponent, formatTokens } from "./components/footer.js";
|
|
51
56
|
import { formatKeyText, keyDisplayText, keyHint, keyText, rawKeyHint } from "./components/keybinding-hints.js";
|
|
52
57
|
import { LoginDialogComponent } from "./components/login-dialog.js";
|
|
58
|
+
import { createMermaidMarkdownTransformer } from "./components/mermaid.js";
|
|
53
59
|
import { ModelSelectorComponent } from "./components/model-selector.js";
|
|
54
60
|
import { formatAuthSelectorProviderType, OAuthSelectorComponent, } from "./components/oauth-selector.js";
|
|
55
61
|
import { ScopedModelsSelectorComponent } from "./components/scoped-models-selector.js";
|
|
@@ -159,11 +165,58 @@ function formatLoginProviderCompletionDescription(provider) {
|
|
|
159
165
|
const authTypes = provider.authTypes.map(formatAuthSelectorProviderType).join("/");
|
|
160
166
|
return provider.name === provider.id ? authTypes : `${provider.name} · ${authTypes}`;
|
|
161
167
|
}
|
|
168
|
+
/** Composition root for selecting the interactive terminal renderer. */
|
|
169
|
+
export function createInteractiveTui(options) {
|
|
170
|
+
const terminal = options.terminal ?? new ProcessTerminal();
|
|
171
|
+
if (options.tuiMode === "fullscreen") {
|
|
172
|
+
return new TuiAltScreen(terminal, options.showHardwareCursor, options.logDirectory, {
|
|
173
|
+
openUrl: openBrowser,
|
|
174
|
+
onRightClickPaste: options.onRightClickPaste,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
return new TuiMainScreen(terminal, options.showHardwareCursor, options.logDirectory);
|
|
178
|
+
}
|
|
179
|
+
/** Stable reference for components while InteractiveMode replaces the active renderer. */
|
|
180
|
+
export function createInteractiveTuiReference(getTui) {
|
|
181
|
+
return new Proxy({}, {
|
|
182
|
+
get: (_target, property) => {
|
|
183
|
+
const tui = getTui();
|
|
184
|
+
const value = Reflect.get(tui, property, tui);
|
|
185
|
+
if (typeof value !== "function")
|
|
186
|
+
return value;
|
|
187
|
+
let methodTui = tui;
|
|
188
|
+
let method = value;
|
|
189
|
+
return (...args) => {
|
|
190
|
+
const currentTui = getTui();
|
|
191
|
+
if (currentTui !== methodTui) {
|
|
192
|
+
const currentMethod = Reflect.get(currentTui, property, currentTui);
|
|
193
|
+
if (typeof currentMethod !== "function") {
|
|
194
|
+
throw new TypeError(`TUI property ${String(property)} is not callable`);
|
|
195
|
+
}
|
|
196
|
+
methodTui = currentTui;
|
|
197
|
+
method = currentMethod;
|
|
198
|
+
}
|
|
199
|
+
return Reflect.apply(method, methodTui, args);
|
|
200
|
+
};
|
|
201
|
+
},
|
|
202
|
+
set: (_target, property, value) => {
|
|
203
|
+
const tui = getTui();
|
|
204
|
+
return Reflect.set(tui, property, value, tui);
|
|
205
|
+
},
|
|
206
|
+
has: (_target, property) => Reflect.has(getTui(), property),
|
|
207
|
+
getPrototypeOf: () => Reflect.getPrototypeOf(getTui()),
|
|
208
|
+
});
|
|
209
|
+
}
|
|
162
210
|
export class InteractiveMode {
|
|
163
211
|
runtimeHost;
|
|
212
|
+
renderer;
|
|
164
213
|
ui;
|
|
214
|
+
mainScreenRenderState;
|
|
165
215
|
loadedResourcesContainer;
|
|
166
216
|
chatContainer;
|
|
217
|
+
documentContainer;
|
|
218
|
+
transcriptScrollView;
|
|
219
|
+
fullscreenLayoutRoot;
|
|
167
220
|
pendingMessagesContainer;
|
|
168
221
|
statusContainer;
|
|
169
222
|
defaultEditor;
|
|
@@ -173,7 +226,10 @@ export class InteractiveMode {
|
|
|
173
226
|
autocompleteProviderWrappers = [];
|
|
174
227
|
fdPath;
|
|
175
228
|
editorContainer;
|
|
229
|
+
activeSelectorToken;
|
|
230
|
+
activeSelectorDispose;
|
|
176
231
|
footer;
|
|
232
|
+
footerContainer;
|
|
177
233
|
footerDataProvider;
|
|
178
234
|
// Stored so the same manager can be injected into custom editors, selectors, and extension UI.
|
|
179
235
|
keybindings;
|
|
@@ -207,6 +263,10 @@ export class InteractiveMode {
|
|
|
207
263
|
// Thinking block visibility state
|
|
208
264
|
hideThinkingBlock = false;
|
|
209
265
|
outputPad = 1;
|
|
266
|
+
mermaidMarkdownTransformer = createMermaidMarkdownTransformer({
|
|
267
|
+
getMode: () => this.settingsManager.getMermaidRenderingMode(),
|
|
268
|
+
theme,
|
|
269
|
+
});
|
|
210
270
|
// Skill commands: command name -> skill file path
|
|
211
271
|
skillCommands = new Map();
|
|
212
272
|
// Agent subscription unsubscribe function
|
|
@@ -230,7 +290,7 @@ export class InteractiveMode {
|
|
|
230
290
|
extensionSelector = undefined;
|
|
231
291
|
extensionInput = undefined;
|
|
232
292
|
extensionEditor = undefined;
|
|
233
|
-
|
|
293
|
+
extensionTerminalInputSubscriptions = new Set();
|
|
234
294
|
// Extension widgets (components rendered above/below the editor)
|
|
235
295
|
extensionWidgetsAbove = new Map();
|
|
236
296
|
extensionWidgetsBelow = new Map();
|
|
@@ -245,6 +305,9 @@ export class InteractiveMode {
|
|
|
245
305
|
// Custom header from extension (undefined = use built-in header)
|
|
246
306
|
customHeader = undefined;
|
|
247
307
|
options;
|
|
308
|
+
onRightClickPaste = () => {
|
|
309
|
+
void this.handleRightClickPaste();
|
|
310
|
+
};
|
|
248
311
|
autoTrustOnReloadCwd;
|
|
249
312
|
themeController;
|
|
250
313
|
// Convenience accessors
|
|
@@ -262,7 +325,8 @@ export class InteractiveMode {
|
|
|
262
325
|
}
|
|
263
326
|
constructor(runtimeHost, options = {}) {
|
|
264
327
|
this.runtimeHost = runtimeHost;
|
|
265
|
-
|
|
328
|
+
const tuiMode = options.tuiMode ?? this.settingsManager.getTuiMode();
|
|
329
|
+
this.options = { ...options, tuiMode };
|
|
266
330
|
this.autoTrustOnReloadCwd = options.autoTrustOnReloadCwd;
|
|
267
331
|
this.runtimeHost.setBeforeSessionInvalidate(() => {
|
|
268
332
|
this.resetExtensionUI();
|
|
@@ -271,11 +335,21 @@ export class InteractiveMode {
|
|
|
271
335
|
await this.rebindCurrentSession({ renderBeforeBind: true });
|
|
272
336
|
});
|
|
273
337
|
this.version = VERSION;
|
|
274
|
-
this.
|
|
338
|
+
this.renderer = createInteractiveTui({
|
|
339
|
+
tuiMode,
|
|
340
|
+
showHardwareCursor: this.settingsManager.getShowHardwareCursor(),
|
|
341
|
+
logDirectory: getAgentDir(),
|
|
342
|
+
onRightClickPaste: this.onRightClickPaste,
|
|
343
|
+
});
|
|
344
|
+
this.ui = createInteractiveTuiReference(() => this.renderer);
|
|
275
345
|
this.ui.setClearOnShrink(this.settingsManager.getClearOnShrink());
|
|
276
346
|
this.headerContainer = new Container();
|
|
277
347
|
this.loadedResourcesContainer = new Container();
|
|
278
348
|
this.chatContainer = new Container();
|
|
349
|
+
this.documentContainer = new Container();
|
|
350
|
+
this.documentContainer.addChild(this.headerContainer);
|
|
351
|
+
this.documentContainer.addChild(this.loadedResourcesContainer);
|
|
352
|
+
this.documentContainer.addChild(this.chatContainer);
|
|
279
353
|
this.pendingMessagesContainer = new Container();
|
|
280
354
|
this.statusContainer = new Container();
|
|
281
355
|
this.widgetContainerAbove = new Container();
|
|
@@ -294,6 +368,8 @@ export class InteractiveMode {
|
|
|
294
368
|
this.footerDataProvider = new FooterDataProvider(this.sessionManager.getCwd());
|
|
295
369
|
this.footer = new FooterComponent(this.session, this.footerDataProvider);
|
|
296
370
|
this.footer.setAutoCompactEnabled(this.session.autoCompactionEnabled);
|
|
371
|
+
this.footerContainer = new Container();
|
|
372
|
+
this.footerContainer.addChild(this.footer);
|
|
297
373
|
// Load hide thinking block setting
|
|
298
374
|
this.hideThinkingBlock = this.settingsManager.getHideThinkingBlock();
|
|
299
375
|
this.outputPad = this.settingsManager.getOutputPad();
|
|
@@ -349,11 +425,10 @@ export class InteractiveMode {
|
|
|
349
425
|
}));
|
|
350
426
|
const modelCommand = slashCommands.find((command) => command.name === "model");
|
|
351
427
|
if (modelCommand) {
|
|
352
|
-
modelCommand.getArgumentCompletions =
|
|
353
|
-
// Get available models (scoped or from registry)
|
|
428
|
+
modelCommand.getArgumentCompletions = (prefix) => {
|
|
354
429
|
const models = this.session.scopedModels.length > 0
|
|
355
430
|
? this.session.scopedModels.map((s) => s.model)
|
|
356
|
-
:
|
|
431
|
+
: this.session.modelRuntime.getAvailableSnapshot();
|
|
357
432
|
if (models.length === 0)
|
|
358
433
|
return null;
|
|
359
434
|
// Create items with provider/id format
|
|
@@ -454,6 +529,73 @@ export class InteractiveMode {
|
|
|
454
529
|
}
|
|
455
530
|
this.chatContainer.addChild(new DynamicBorder());
|
|
456
531
|
}
|
|
532
|
+
mountInteractiveTui(tui, components) {
|
|
533
|
+
for (const component of components)
|
|
534
|
+
tui.addChild(component);
|
|
535
|
+
if (TuiLayouts.isViewportTUI(tui)) {
|
|
536
|
+
if (!this.fullscreenLayoutRoot)
|
|
537
|
+
throw new Error("Fullscreen layout is not initialized");
|
|
538
|
+
tui.setLayoutRoot(this.fullscreenLayoutRoot);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
stopInteractiveTui() {
|
|
542
|
+
if (this.renderer.mode === "fullscreen") {
|
|
543
|
+
while (this.renderer.hasOverlayEntries)
|
|
544
|
+
this.renderer.hideOverlay();
|
|
545
|
+
this.switchTuiMode("regular", false, false);
|
|
546
|
+
this.renderer.renderNow();
|
|
547
|
+
}
|
|
548
|
+
this.ui.stop();
|
|
549
|
+
}
|
|
550
|
+
switchTuiMode(mode, restoreProgress = true, startRenderer = true) {
|
|
551
|
+
const previousUi = this.renderer;
|
|
552
|
+
if (mode === previousUi.mode)
|
|
553
|
+
return true;
|
|
554
|
+
if (previousUi.hasOverlayEntries)
|
|
555
|
+
return false;
|
|
556
|
+
const components = [...previousUi.children];
|
|
557
|
+
const focus = previousUi.getFocusedComponent();
|
|
558
|
+
const terminal = previousUi.terminal;
|
|
559
|
+
const showHardwareCursor = previousUi.getShowHardwareCursor();
|
|
560
|
+
const clearOnShrink = previousUi.getClearOnShrink();
|
|
561
|
+
const onDebug = previousUi.onDebug;
|
|
562
|
+
if (previousUi instanceof TuiMainScreen) {
|
|
563
|
+
this.mainScreenRenderState = previousUi.captureRenderState();
|
|
564
|
+
}
|
|
565
|
+
previousUi.stop({ preserveScreen: true });
|
|
566
|
+
previousUi.setFocus(null);
|
|
567
|
+
previousUi.clear();
|
|
568
|
+
if (TuiLayouts.isViewportTUI(previousUi))
|
|
569
|
+
previousUi.setLayoutRoot(undefined);
|
|
570
|
+
const nextUi = createInteractiveTui({
|
|
571
|
+
tuiMode: mode,
|
|
572
|
+
showHardwareCursor,
|
|
573
|
+
logDirectory: getAgentDir(),
|
|
574
|
+
terminal,
|
|
575
|
+
onRightClickPaste: this.onRightClickPaste,
|
|
576
|
+
});
|
|
577
|
+
nextUi.setClearOnShrink(clearOnShrink);
|
|
578
|
+
nextUi.onDebug = onDebug;
|
|
579
|
+
if (nextUi instanceof TuiMainScreen && this.mainScreenRenderState) {
|
|
580
|
+
nextUi.restoreRenderState(this.mainScreenRenderState);
|
|
581
|
+
}
|
|
582
|
+
this.renderer = nextUi;
|
|
583
|
+
this.options.tuiMode = mode;
|
|
584
|
+
this.mountInteractiveTui(nextUi, components);
|
|
585
|
+
nextUi.invalidate();
|
|
586
|
+
nextUi.setFocus(focus);
|
|
587
|
+
if (!startRenderer)
|
|
588
|
+
return true;
|
|
589
|
+
nextUi.start();
|
|
590
|
+
this.themeController.rebindTui();
|
|
591
|
+
this.rebindExtensionTerminalInputListeners();
|
|
592
|
+
if (restoreProgress &&
|
|
593
|
+
this.settingsManager.getShowTerminalProgress() &&
|
|
594
|
+
(this.session.isStreaming || this.session.isCompacting)) {
|
|
595
|
+
terminal.setProgress(true);
|
|
596
|
+
}
|
|
597
|
+
return true;
|
|
598
|
+
}
|
|
457
599
|
async init() {
|
|
458
600
|
if (this.isInitialized)
|
|
459
601
|
return;
|
|
@@ -477,18 +619,36 @@ export class InteractiveMode {
|
|
|
477
619
|
: "";
|
|
478
620
|
console.log(theme.fg("dim", `Model scope: ${modelList}${cycleHint}`));
|
|
479
621
|
}
|
|
480
|
-
//
|
|
481
|
-
// Keep loaded resources before chat so restored session messages never precede them.
|
|
482
|
-
this.ui.addChild(this.headerContainer);
|
|
483
|
-
this.ui.addChild(this.loadedResourcesContainer);
|
|
484
|
-
this.ui.addChild(this.chatContainer);
|
|
485
|
-
this.ui.addChild(this.pendingMessagesContainer);
|
|
486
|
-
this.ui.addChild(this.statusContainer);
|
|
622
|
+
// Keep one component tree and remount it when changing renderers.
|
|
487
623
|
this.renderWidgets(); // Initialize with default spacer
|
|
488
|
-
this.
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
624
|
+
this.transcriptScrollView = new TuiLayouts.ScrollView(this.documentContainer, {
|
|
625
|
+
follow: "end",
|
|
626
|
+
primary: true,
|
|
627
|
+
overscroll: "chain",
|
|
628
|
+
scrollbar: this.settingsManager.getFullscreenScrollbar(),
|
|
629
|
+
scrollbarStyle: (text) => theme.bg("scrollbarThumb", text),
|
|
630
|
+
});
|
|
631
|
+
const dock = new TuiLayouts.VStack([
|
|
632
|
+
{ component: this.pendingMessagesContainer, shrink: 1, minSize: 0 },
|
|
633
|
+
{ component: this.statusContainer, shrink: 1, minSize: 0 },
|
|
634
|
+
{ component: this.widgetContainerAbove, shrink: 1, minSize: 0 },
|
|
635
|
+
{ component: this.editorContainer, shrink: 1, minSize: 3 },
|
|
636
|
+
{ component: this.widgetContainerBelow, shrink: 1, minSize: 0 },
|
|
637
|
+
{ component: this.footerContainer, shrink: 1, minSize: 1 },
|
|
638
|
+
]);
|
|
639
|
+
this.fullscreenLayoutRoot = new TuiLayouts.VStack([
|
|
640
|
+
{ component: this.transcriptScrollView, basis: 0, grow: 1, shrink: 1, minSize: 1 },
|
|
641
|
+
{ component: dock, basis: "auto", grow: 0, shrink: 1, minSize: 1 },
|
|
642
|
+
]);
|
|
643
|
+
this.mountInteractiveTui(this.renderer, [
|
|
644
|
+
this.documentContainer,
|
|
645
|
+
this.pendingMessagesContainer,
|
|
646
|
+
this.statusContainer,
|
|
647
|
+
this.widgetContainerAbove,
|
|
648
|
+
this.editorContainer,
|
|
649
|
+
this.widgetContainerBelow,
|
|
650
|
+
this.footerContainer,
|
|
651
|
+
]);
|
|
492
652
|
this.ui.setFocus(this.editor);
|
|
493
653
|
this.setupKeyHandlers();
|
|
494
654
|
this.setupEditorSubmitHandler();
|
|
@@ -498,7 +658,7 @@ export class InteractiveMode {
|
|
|
498
658
|
await this.themeController.applyFromSettings();
|
|
499
659
|
// Add header with keybindings from config (unless silenced)
|
|
500
660
|
if (this.options.verbose || !this.settingsManager.getQuietStartup()) {
|
|
501
|
-
const logo = theme.fg("accent",
|
|
661
|
+
const logo = theme.bold(theme.fg("accent", APP_NAME)) + theme.fg("dim", ` v${this.version}`);
|
|
502
662
|
// Build startup instructions using keybinding hint helpers
|
|
503
663
|
const hint = (keybinding, description) => keyHint(keybinding, description);
|
|
504
664
|
const expandedInstructions = [
|
|
@@ -530,7 +690,7 @@ export class InteractiveMode {
|
|
|
530
690
|
hint("app.tools.expand", "more"),
|
|
531
691
|
].join(theme.fg("muted", " · "));
|
|
532
692
|
const compactOnboarding = theme.fg("dim", `Press ${keyText("app.tools.expand")} to show full startup help and loaded resources.`);
|
|
533
|
-
const onboarding = theme.fg("dim",
|
|
693
|
+
const onboarding = theme.fg("dim", `Pi can explain its own features and look up its docs. Ask it how to use or extend Pi.`);
|
|
534
694
|
this.builtInHeader = new ExpandableText(() => `${logo}\n${compactInstructions}\n${compactOnboarding}\n\n${onboarding}`, () => `${logo}\n${expandedInstructions}\n\n${onboarding}`, this.getStartupExpansionState(), 1, 0);
|
|
535
695
|
// Setup UI layout
|
|
536
696
|
this.headerContainer.addChild(new Spacer(1));
|
|
@@ -580,10 +740,13 @@ export class InteractiveMode {
|
|
|
580
740
|
async run() {
|
|
581
741
|
await this.init();
|
|
582
742
|
if (!process.env.PI_OFFLINE) {
|
|
743
|
+
const controller = new AbortController();
|
|
744
|
+
const timeout = setTimeout(() => controller.abort(), 15_000);
|
|
583
745
|
void this.session.modelRuntime
|
|
584
|
-
.refresh()
|
|
746
|
+
.refresh({ signal: controller.signal })
|
|
585
747
|
.then(() => this.updateAvailableProviderCount())
|
|
586
|
-
.catch(() => { })
|
|
748
|
+
.catch(() => { })
|
|
749
|
+
.finally(() => clearTimeout(timeout));
|
|
587
750
|
}
|
|
588
751
|
// Start version check asynchronously
|
|
589
752
|
checkForNewPiVersion(this.version).then((newRelease) => {
|
|
@@ -620,7 +783,7 @@ export class InteractiveMode {
|
|
|
620
783
|
if (modelsJsonError) {
|
|
621
784
|
this.showError(`models.json error: ${modelsJsonError}`);
|
|
622
785
|
}
|
|
623
|
-
if (modelFallbackMessage
|
|
786
|
+
if (modelFallbackMessage) {
|
|
624
787
|
this.showWarning(modelFallbackMessage);
|
|
625
788
|
}
|
|
626
789
|
void this.maybeWarnAboutAnthropicSubscriptionAuth();
|
|
@@ -658,7 +821,7 @@ export class InteractiveMode {
|
|
|
658
821
|
}
|
|
659
822
|
}
|
|
660
823
|
async checkForPackageUpdates() {
|
|
661
|
-
if (process.env
|
|
824
|
+
if (process.env.PI_OFFLINE) {
|
|
662
825
|
return [];
|
|
663
826
|
}
|
|
664
827
|
try {
|
|
@@ -711,7 +874,7 @@ export class InteractiveMode {
|
|
|
711
874
|
return "tmux extended-keys is off. Modified Enter keys may not work. Add `set -g extended-keys on` to ~/.tmux.conf and restart tmux.";
|
|
712
875
|
}
|
|
713
876
|
if (extendedKeysFormat === "xterm") {
|
|
714
|
-
return
|
|
877
|
+
return "tmux extended-keys-format is xterm. Pi works best with csi-u. Add `set -g extended-keys-format csi-u` to ~/.tmux.conf and restart tmux.";
|
|
715
878
|
}
|
|
716
879
|
return undefined;
|
|
717
880
|
}
|
|
@@ -742,13 +905,13 @@ export class InteractiveMode {
|
|
|
742
905
|
return undefined;
|
|
743
906
|
}
|
|
744
907
|
reportInstallTelemetry(version) {
|
|
745
|
-
if (process.env
|
|
908
|
+
if (process.env.PI_OFFLINE) {
|
|
746
909
|
return;
|
|
747
910
|
}
|
|
748
911
|
if (!isInstallTelemetryEnabled(this.settingsManager)) {
|
|
749
912
|
return;
|
|
750
913
|
}
|
|
751
|
-
void fetch(
|
|
914
|
+
void fetch(`https://pi.dev/api/report-install?version=${encodeURIComponent(version)}`, {
|
|
752
915
|
headers: {
|
|
753
916
|
"User-Agent": getPiUserAgent(version),
|
|
754
917
|
},
|
|
@@ -763,20 +926,6 @@ export class InteractiveMode {
|
|
|
763
926
|
codeBlockIndent: this.settingsManager.getCodeBlockIndent(),
|
|
764
927
|
};
|
|
765
928
|
}
|
|
766
|
-
isNoModelsAvailableMessage(message) {
|
|
767
|
-
return message?.startsWith("No models available.") ?? false;
|
|
768
|
-
}
|
|
769
|
-
getNoModelsStartupNotice() {
|
|
770
|
-
if (!this.isNoModelsAvailableMessage(this.options.modelFallbackMessage)) {
|
|
771
|
-
return undefined;
|
|
772
|
-
}
|
|
773
|
-
return [
|
|
774
|
-
theme.bold(theme.fg("warning", "Model setup required")),
|
|
775
|
-
`${theme.fg("muted", "No models are available yet. Run ")}${theme.bold("/login")}${theme.fg("muted", " to add a provider.")}`,
|
|
776
|
-
`${theme.fg("dim", "Then use ")}${theme.bold("/model")}${theme.fg("dim", " if you want to switch models.")}`,
|
|
777
|
-
`${theme.fg("dim", "Docs: ")}${theme.fg("accent", "docs/providers.md")}${theme.fg("dim", ", ")}${theme.fg("accent", "docs/models.md")}`,
|
|
778
|
-
].join("\n");
|
|
779
|
-
}
|
|
780
929
|
// =========================================================================
|
|
781
930
|
// Extension System
|
|
782
931
|
// =========================================================================
|
|
@@ -794,6 +943,15 @@ export class InteractiveMode {
|
|
|
794
943
|
result = result.replace(/\/index\.ts$/, "").replace(/\/index\.js$/, "");
|
|
795
944
|
return result;
|
|
796
945
|
}
|
|
946
|
+
formatContextPath(p) {
|
|
947
|
+
const cwd = path.resolve(this.sessionManager.getCwd());
|
|
948
|
+
const absolutePath = path.isAbsolute(p) ? path.resolve(p) : path.resolve(cwd, p);
|
|
949
|
+
const relativePath = getCwdRelativePath(absolutePath, cwd);
|
|
950
|
+
if (relativePath !== undefined) {
|
|
951
|
+
return relativePath;
|
|
952
|
+
}
|
|
953
|
+
return this.formatDisplayPath(absolutePath);
|
|
954
|
+
}
|
|
797
955
|
getStartupExpansionState() {
|
|
798
956
|
return this.options.verbose || this.toolOutputExpanded;
|
|
799
957
|
}
|
|
@@ -830,43 +988,92 @@ export class InteractiveMode {
|
|
|
830
988
|
}
|
|
831
989
|
return this.formatDisplayPath(fullPath);
|
|
832
990
|
}
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
return versionStart === -1 ? packageSpec : packageSpec.slice(0, versionStart);
|
|
840
|
-
}
|
|
841
|
-
stripLegacyPackagePrefix(packageName) {
|
|
842
|
-
const scopedMatch = /^(@[^/]+)\/(.+)$/.exec(packageName);
|
|
843
|
-
if (scopedMatch) {
|
|
844
|
-
return `${scopedMatch[1]}/${this.stripLegacyPackagePrefix(scopedMatch[2])}`;
|
|
991
|
+
getCompactPathLabel(resourcePath, sourceInfo) {
|
|
992
|
+
const shortPath = this.getShortPath(resourcePath, sourceInfo);
|
|
993
|
+
const normalizedPath = shortPath.replace(/\\/g, "/");
|
|
994
|
+
const segments = normalizedPath.split("/").filter((segment) => segment.length > 0 && segment !== "~");
|
|
995
|
+
if (segments.length > 0) {
|
|
996
|
+
return segments[segments.length - 1];
|
|
845
997
|
}
|
|
846
|
-
|
|
847
|
-
return sanitized || packageName;
|
|
998
|
+
return shortPath;
|
|
848
999
|
}
|
|
849
|
-
|
|
1000
|
+
getCompactPackageSourceLabel(sourceInfo) {
|
|
1001
|
+
const source = sourceInfo?.source ?? "";
|
|
850
1002
|
if (source.startsWith("npm:")) {
|
|
851
|
-
return
|
|
1003
|
+
return source.slice("npm:".length) || source;
|
|
852
1004
|
}
|
|
853
1005
|
const gitSource = parseGitUrl(source);
|
|
854
|
-
if (gitSource
|
|
855
|
-
return gitSource.path
|
|
856
|
-
.split("/")
|
|
857
|
-
.map((segment, index, segments) => index === segments.length - 1 ? this.stripLegacyPackagePrefix(segment) : segment)
|
|
858
|
-
.join("/");
|
|
1006
|
+
if (gitSource) {
|
|
1007
|
+
return gitSource.path || source;
|
|
859
1008
|
}
|
|
860
1009
|
return source;
|
|
861
1010
|
}
|
|
862
|
-
|
|
863
|
-
if (
|
|
864
|
-
return
|
|
865
|
-
}
|
|
866
|
-
|
|
867
|
-
|
|
1011
|
+
getCompactExtensionLabel(resourcePath, sourceInfo) {
|
|
1012
|
+
if (!this.isPackageSource(sourceInfo)) {
|
|
1013
|
+
return this.getCompactPathLabel(resourcePath, sourceInfo);
|
|
1014
|
+
}
|
|
1015
|
+
const sourceLabel = this.getCompactPackageSourceLabel(sourceInfo);
|
|
1016
|
+
if (!sourceLabel) {
|
|
1017
|
+
return this.getCompactPathLabel(resourcePath, sourceInfo);
|
|
1018
|
+
}
|
|
1019
|
+
const shortPath = this.getShortPath(resourcePath, sourceInfo).replace(/\\/g, "/");
|
|
1020
|
+
const packagePath = shortPath.startsWith("extensions/") ? shortPath.slice("extensions/".length) : shortPath;
|
|
1021
|
+
const parsedPath = path.posix.parse(packagePath);
|
|
1022
|
+
if (parsedPath.name === "index") {
|
|
1023
|
+
return !parsedPath.dir || parsedPath.dir === "." ? sourceLabel : `${sourceLabel}:${parsedPath.dir}`;
|
|
1024
|
+
}
|
|
1025
|
+
return `${sourceLabel}:${packagePath}`;
|
|
1026
|
+
}
|
|
1027
|
+
getCompactDisplayPathSegments(resourcePath) {
|
|
1028
|
+
return this.formatDisplayPath(resourcePath)
|
|
1029
|
+
.replace(/\\/g, "/")
|
|
1030
|
+
.split("/")
|
|
1031
|
+
.filter((segment) => segment.length > 0 && segment !== "~");
|
|
1032
|
+
}
|
|
1033
|
+
getCompactNonPackageExtensionLabel(resourcePath, index, allPaths) {
|
|
1034
|
+
const segments = allPaths[index]?.segments;
|
|
1035
|
+
if (!segments || segments.length === 0) {
|
|
1036
|
+
return this.getCompactPathLabel(resourcePath);
|
|
1037
|
+
}
|
|
1038
|
+
for (let segmentCount = 1; segmentCount <= segments.length; segmentCount += 1) {
|
|
1039
|
+
const candidate = segments.slice(-segmentCount).join("/");
|
|
1040
|
+
const isUnique = allPaths.every((item, itemIndex) => {
|
|
1041
|
+
if (itemIndex === index) {
|
|
1042
|
+
return true;
|
|
1043
|
+
}
|
|
1044
|
+
return item.segments.slice(-segmentCount).join("/") !== candidate;
|
|
1045
|
+
});
|
|
1046
|
+
if (isUnique) {
|
|
1047
|
+
return candidate;
|
|
1048
|
+
}
|
|
868
1049
|
}
|
|
869
|
-
return
|
|
1050
|
+
return segments.join("/");
|
|
1051
|
+
}
|
|
1052
|
+
getCompactExtensionLabels(extensions) {
|
|
1053
|
+
const nonPackageExtensions = extensions
|
|
1054
|
+
.map((extension) => {
|
|
1055
|
+
const segments = this.getCompactDisplayPathSegments(extension.path);
|
|
1056
|
+
const lastSegment = segments[segments.length - 1];
|
|
1057
|
+
if (segments.length > 1 && (lastSegment === "index.ts" || lastSegment === "index.js")) {
|
|
1058
|
+
segments.pop();
|
|
1059
|
+
}
|
|
1060
|
+
return {
|
|
1061
|
+
path: extension.path,
|
|
1062
|
+
sourceInfo: extension.sourceInfo,
|
|
1063
|
+
segments,
|
|
1064
|
+
};
|
|
1065
|
+
})
|
|
1066
|
+
.filter((extension) => !this.isPackageSource(extension.sourceInfo));
|
|
1067
|
+
return extensions.map((extension) => {
|
|
1068
|
+
if (this.isPackageSource(extension.sourceInfo)) {
|
|
1069
|
+
return this.getCompactExtensionLabel(extension.path, extension.sourceInfo);
|
|
1070
|
+
}
|
|
1071
|
+
const nonPackageIndex = nonPackageExtensions.findIndex((item) => item.path === extension.path);
|
|
1072
|
+
if (nonPackageIndex === -1) {
|
|
1073
|
+
return this.getCompactPathLabel(extension.path, extension.sourceInfo);
|
|
1074
|
+
}
|
|
1075
|
+
return this.getCompactNonPackageExtensionLabel(extension.path, nonPackageIndex, nonPackageExtensions);
|
|
1076
|
+
});
|
|
870
1077
|
}
|
|
871
1078
|
getDisplaySourceInfo(sourceInfo) {
|
|
872
1079
|
const source = sourceInfo?.source ?? "local";
|
|
@@ -887,7 +1094,7 @@ export class InteractiveMode {
|
|
|
887
1094
|
return { label: "path", scopeLabel: scope === "temporary" ? "temp" : undefined, color: "muted" };
|
|
888
1095
|
}
|
|
889
1096
|
const scopeLabel = scope === "user" ? "user" : scope === "project" ? "project" : scope === "temporary" ? "temp" : undefined;
|
|
890
|
-
return { label:
|
|
1097
|
+
return { label: source, scopeLabel, color: "accent" };
|
|
891
1098
|
}
|
|
892
1099
|
getScopeGroup(sourceInfo) {
|
|
893
1100
|
const source = sourceInfo?.source ?? "local";
|
|
@@ -935,7 +1142,7 @@ export class InteractiveMode {
|
|
|
935
1142
|
}
|
|
936
1143
|
const sortedPackages = Array.from(group.packages.entries()).sort(([a], [b]) => a.localeCompare(b));
|
|
937
1144
|
for (const [source, items] of sortedPackages) {
|
|
938
|
-
lines.push(` ${theme.fg("mdLink",
|
|
1145
|
+
lines.push(` ${theme.fg("mdLink", source)}`);
|
|
939
1146
|
const sortedPackagePaths = [...items].sort((a, b) => a.path.localeCompare(b.path));
|
|
940
1147
|
for (const item of sortedPackagePaths) {
|
|
941
1148
|
lines.push(theme.fg("dim", ` ${options.formatPackagePath(item, source)}`));
|
|
@@ -1011,24 +1218,22 @@ export class InteractiveMode {
|
|
|
1011
1218
|
this.loadedResourcesContainer.clear();
|
|
1012
1219
|
const showListing = options?.force || this.options.verbose || !this.settingsManager.getQuietStartup();
|
|
1013
1220
|
const showDiagnostics = showListing || options?.showDiagnosticsWhenQuiet === true;
|
|
1014
|
-
|
|
1015
|
-
if (!showListing && !showDiagnostics && !noModelsStartupNotice) {
|
|
1221
|
+
if (!showListing && !showDiagnostics) {
|
|
1016
1222
|
return;
|
|
1017
1223
|
}
|
|
1018
1224
|
const sectionHeader = (name, color = "mdHeading") => theme.fg(color, `[${name}]`);
|
|
1019
|
-
const
|
|
1225
|
+
const formatCompactList = (items, options) => {
|
|
1226
|
+
const labels = items.map((item) => item.trim()).filter((item) => item.length > 0);
|
|
1227
|
+
if (options?.sort !== false) {
|
|
1228
|
+
labels.sort((a, b) => a.localeCompare(b));
|
|
1229
|
+
}
|
|
1230
|
+
return theme.fg("dim", ` ${labels.join(", ")}`);
|
|
1231
|
+
};
|
|
1020
1232
|
const addLoadedSection = (name, collapsedBody, expandedBody = collapsedBody, color = "mdHeading") => {
|
|
1021
1233
|
const section = new ExpandableText(() => `${sectionHeader(name, color)}\n${collapsedBody}`, () => `${sectionHeader(name, color)}\n${expandedBody}`, this.getStartupExpansionState(), 0, 0);
|
|
1022
1234
|
this.loadedResourcesContainer.addChild(section);
|
|
1023
1235
|
this.loadedResourcesContainer.addChild(new Spacer(1));
|
|
1024
1236
|
};
|
|
1025
|
-
if (noModelsStartupNotice) {
|
|
1026
|
-
this.loadedResourcesContainer.addChild(new Spacer(1));
|
|
1027
|
-
this.loadedResourcesContainer.addChild(new DynamicBorder((text) => theme.fg("warning", text)));
|
|
1028
|
-
this.loadedResourcesContainer.addChild(new Text(noModelsStartupNotice, 1, 0));
|
|
1029
|
-
this.loadedResourcesContainer.addChild(new DynamicBorder((text) => theme.fg("warning", text)));
|
|
1030
|
-
this.loadedResourcesContainer.addChild(new Spacer(1));
|
|
1031
|
-
}
|
|
1032
1237
|
const skillsResult = this.session.resourceLoader.getSkills();
|
|
1033
1238
|
const promptsResult = this.session.resourceLoader.getPrompts();
|
|
1034
1239
|
const themesResult = this.session.resourceLoader.getThemes();
|
|
@@ -1073,7 +1278,7 @@ export class InteractiveMode {
|
|
|
1073
1278
|
const contextList = contextFiles
|
|
1074
1279
|
.map((f) => theme.fg("dim", ` ${this.formatDisplayPath(f.path)}`))
|
|
1075
1280
|
.join("\n");
|
|
1076
|
-
const contextCompactList =
|
|
1281
|
+
const contextCompactList = formatCompactList(contextFiles.map((contextFile) => this.formatContextPath(contextFile.path)), { sort: false });
|
|
1077
1282
|
addLoadedSection("Context", contextCompactList, contextList);
|
|
1078
1283
|
}
|
|
1079
1284
|
const skills = skillsResult.skills;
|
|
@@ -1083,7 +1288,7 @@ export class InteractiveMode {
|
|
|
1083
1288
|
formatPath: (item) => this.formatDisplayPath(item.path),
|
|
1084
1289
|
formatPackagePath: (item) => this.getShortPath(item.path, item.sourceInfo),
|
|
1085
1290
|
});
|
|
1086
|
-
const skillCompactList =
|
|
1291
|
+
const skillCompactList = formatCompactList(skills.map((skill) => skill.name));
|
|
1087
1292
|
addLoadedSection("Skills", skillCompactList, skillList);
|
|
1088
1293
|
}
|
|
1089
1294
|
const templates = this.session.promptTemplates;
|
|
@@ -1100,7 +1305,7 @@ export class InteractiveMode {
|
|
|
1100
1305
|
return template ? `/${template.name}` : this.formatDisplayPath(item.path);
|
|
1101
1306
|
},
|
|
1102
1307
|
});
|
|
1103
|
-
const promptCompactList =
|
|
1308
|
+
const promptCompactList = formatCompactList(templates.map((template) => `/${template.name}`));
|
|
1104
1309
|
addLoadedSection("Prompts", promptCompactList, templateList);
|
|
1105
1310
|
}
|
|
1106
1311
|
if (extensions.length > 0) {
|
|
@@ -1109,7 +1314,7 @@ export class InteractiveMode {
|
|
|
1109
1314
|
formatPath: (item) => this.formatExtensionDisplayPath(item.path),
|
|
1110
1315
|
formatPackagePath: (item) => this.formatExtensionDisplayPath(this.getShortPath(item.path, item.sourceInfo)),
|
|
1111
1316
|
});
|
|
1112
|
-
const extensionCompactList =
|
|
1317
|
+
const extensionCompactList = formatCompactList(this.getCompactExtensionLabels(extensions));
|
|
1113
1318
|
addLoadedSection("Extensions", extensionCompactList, extList, "mdHeading");
|
|
1114
1319
|
}
|
|
1115
1320
|
// Show loaded themes (excluding built-in)
|
|
@@ -1124,7 +1329,7 @@ export class InteractiveMode {
|
|
|
1124
1329
|
formatPath: (item) => this.formatDisplayPath(item.path),
|
|
1125
1330
|
formatPackagePath: (item) => this.getShortPath(item.path, item.sourceInfo),
|
|
1126
1331
|
});
|
|
1127
|
-
const themeCompactList =
|
|
1332
|
+
const themeCompactList = formatCompactList(customThemes.map((loadedTheme) => loadedTheme.name ?? this.getCompactPathLabel(loadedTheme.sourcePath, loadedTheme.sourceInfo)));
|
|
1128
1333
|
addLoadedSection("Themes", themeCompactList, themeList);
|
|
1129
1334
|
}
|
|
1130
1335
|
}
|
|
@@ -1244,8 +1449,12 @@ export class InteractiveMode {
|
|
|
1244
1449
|
this.showLoadedResources({ force: false, showDiagnosticsWhenQuiet: true });
|
|
1245
1450
|
this.showStartupNoticesIfNeeded();
|
|
1246
1451
|
}
|
|
1452
|
+
applyFullscreenScrollbarSetting() {
|
|
1453
|
+
this.transcriptScrollView?.setScrollbar(this.settingsManager.getFullscreenScrollbar());
|
|
1454
|
+
}
|
|
1247
1455
|
applyRuntimeSettings() {
|
|
1248
1456
|
configureHttpDispatcher(this.settingsManager.getHttpIdleTimeoutMs());
|
|
1457
|
+
this.applyFullscreenScrollbarSetting();
|
|
1249
1458
|
this.footer.setSession(this.session);
|
|
1250
1459
|
this.footer.setAutoCompactEnabled(this.session.autoCompactionEnabled);
|
|
1251
1460
|
this.footerDataProvider.setCwd(this.sessionManager.getCwd());
|
|
@@ -1309,6 +1518,9 @@ export class InteractiveMode {
|
|
|
1309
1518
|
getRegisteredToolDefinition(toolName) {
|
|
1310
1519
|
return this.session.getToolDefinition(toolName);
|
|
1311
1520
|
}
|
|
1521
|
+
getMarkdownTransformers() {
|
|
1522
|
+
return [this.mermaidMarkdownTransformer, ...this.session.extensionRunner.getMarkdownTransformers()];
|
|
1523
|
+
}
|
|
1312
1524
|
/**
|
|
1313
1525
|
* Set up keyboard shortcuts registered by extensions.
|
|
1314
1526
|
*/
|
|
@@ -1388,7 +1600,7 @@ export class InteractiveMode {
|
|
|
1388
1600
|
this.activeStatusIndicator?.dispose();
|
|
1389
1601
|
this.activeStatusIndicator = undefined;
|
|
1390
1602
|
this.statusContainer.clear();
|
|
1391
|
-
if (hadActiveStatusIndicator && this.ui.getClearOnShrink()) {
|
|
1603
|
+
if (hadActiveStatusIndicator && this.options.tuiMode === "regular" && this.ui.getClearOnShrink()) {
|
|
1392
1604
|
this.statusContainer.addChild(this.idleStatus);
|
|
1393
1605
|
}
|
|
1394
1606
|
}
|
|
@@ -1536,22 +1748,16 @@ export class InteractiveMode {
|
|
|
1536
1748
|
if (this.customFooter?.dispose) {
|
|
1537
1749
|
this.customFooter.dispose();
|
|
1538
1750
|
}
|
|
1539
|
-
|
|
1540
|
-
if (this.customFooter) {
|
|
1541
|
-
this.ui.removeChild(this.customFooter);
|
|
1542
|
-
}
|
|
1543
|
-
else {
|
|
1544
|
-
this.ui.removeChild(this.footer);
|
|
1545
|
-
}
|
|
1751
|
+
this.footerContainer.clear();
|
|
1546
1752
|
if (factory) {
|
|
1547
1753
|
// Create and add custom footer, passing the data provider
|
|
1548
1754
|
this.customFooter = factory(this.ui, theme, this.footerDataProvider);
|
|
1549
|
-
this.
|
|
1755
|
+
this.footerContainer.addChild(this.customFooter);
|
|
1550
1756
|
}
|
|
1551
1757
|
else {
|
|
1552
1758
|
// Restore built-in footer
|
|
1553
1759
|
this.customFooter = undefined;
|
|
1554
|
-
this.
|
|
1760
|
+
this.footerContainer.addChild(this.footer);
|
|
1555
1761
|
}
|
|
1556
1762
|
this.ui.requestRender();
|
|
1557
1763
|
}
|
|
@@ -1597,18 +1803,23 @@ export class InteractiveMode {
|
|
|
1597
1803
|
this.ui.requestRender();
|
|
1598
1804
|
}
|
|
1599
1805
|
addExtensionTerminalInputListener(handler) {
|
|
1600
|
-
const
|
|
1601
|
-
this.
|
|
1806
|
+
const subscription = { handler, unsubscribe: this.ui.addInputListener(handler) };
|
|
1807
|
+
this.extensionTerminalInputSubscriptions.add(subscription);
|
|
1602
1808
|
return () => {
|
|
1603
|
-
unsubscribe();
|
|
1604
|
-
this.
|
|
1809
|
+
subscription.unsubscribe();
|
|
1810
|
+
this.extensionTerminalInputSubscriptions.delete(subscription);
|
|
1605
1811
|
};
|
|
1606
1812
|
}
|
|
1607
|
-
|
|
1608
|
-
for (const
|
|
1609
|
-
unsubscribe();
|
|
1813
|
+
rebindExtensionTerminalInputListeners() {
|
|
1814
|
+
for (const subscription of this.extensionTerminalInputSubscriptions) {
|
|
1815
|
+
subscription.unsubscribe();
|
|
1816
|
+
subscription.unsubscribe = this.ui.addInputListener(subscription.handler);
|
|
1610
1817
|
}
|
|
1611
|
-
|
|
1818
|
+
}
|
|
1819
|
+
clearExtensionTerminalInputListeners() {
|
|
1820
|
+
for (const subscription of this.extensionTerminalInputSubscriptions)
|
|
1821
|
+
subscription.unsubscribe();
|
|
1822
|
+
this.extensionTerminalInputSubscriptions.clear();
|
|
1612
1823
|
}
|
|
1613
1824
|
/**
|
|
1614
1825
|
* Create the ExtensionUIContext for extensions.
|
|
@@ -1703,6 +1914,7 @@ export class InteractiveMode {
|
|
|
1703
1914
|
this.hideExtensionSelector();
|
|
1704
1915
|
resolve(undefined);
|
|
1705
1916
|
}, { tui: this.ui, timeout: opts?.timeout, onToggleToolsExpanded: () => this.toggleToolOutputExpansion() });
|
|
1917
|
+
this.disposeActiveSelector();
|
|
1706
1918
|
this.editorContainer.clear();
|
|
1707
1919
|
this.editorContainer.addChild(this.extensionSelector);
|
|
1708
1920
|
this.ui.setFocus(this.extensionSelector);
|
|
@@ -1754,6 +1966,7 @@ export class InteractiveMode {
|
|
|
1754
1966
|
this.hideExtensionInput();
|
|
1755
1967
|
resolve(undefined);
|
|
1756
1968
|
}, { tui: this.ui, timeout: opts?.timeout });
|
|
1969
|
+
this.disposeActiveSelector();
|
|
1757
1970
|
this.editorContainer.clear();
|
|
1758
1971
|
this.editorContainer.addChild(this.extensionInput);
|
|
1759
1972
|
this.ui.setFocus(this.extensionInput);
|
|
@@ -1783,6 +1996,7 @@ export class InteractiveMode {
|
|
|
1783
1996
|
this.hideExtensionEditor();
|
|
1784
1997
|
resolve(undefined);
|
|
1785
1998
|
}, undefined, this.settingsManager.getExternalEditorCommand());
|
|
1999
|
+
this.disposeActiveSelector();
|
|
1786
2000
|
this.editorContainer.clear();
|
|
1787
2001
|
this.editorContainer.addChild(this.extensionEditor);
|
|
1788
2002
|
this.ui.setFocus(this.extensionEditor);
|
|
@@ -1807,6 +2021,7 @@ export class InteractiveMode {
|
|
|
1807
2021
|
this.editorComponentFactory = factory;
|
|
1808
2022
|
// Save text from current editor before switching
|
|
1809
2023
|
const currentText = this.editor.getText();
|
|
2024
|
+
this.disposeActiveSelector();
|
|
1810
2025
|
this.editorContainer.clear();
|
|
1811
2026
|
if (factory) {
|
|
1812
2027
|
// Create the custom editor with tui, theme, and keybindings
|
|
@@ -1823,6 +2038,9 @@ export class InteractiveMode {
|
|
|
1823
2038
|
if (newEditor.setPaddingX !== undefined) {
|
|
1824
2039
|
newEditor.setPaddingX(this.defaultEditor.getPaddingX());
|
|
1825
2040
|
}
|
|
2041
|
+
if (newEditor.setAutocompleteMaxVisible !== undefined) {
|
|
2042
|
+
newEditor.setAutocompleteMaxVisible(this.defaultEditor.getAutocompleteMaxVisible());
|
|
2043
|
+
}
|
|
1826
2044
|
// Set autocomplete if supported
|
|
1827
2045
|
if (newEditor.setAutocompleteProvider && this.autocompleteProvider) {
|
|
1828
2046
|
newEditor.setAutocompleteProvider(this.autocompleteProvider);
|
|
@@ -1927,6 +2145,7 @@ export class InteractiveMode {
|
|
|
1927
2145
|
options?.onHandle?.(handle);
|
|
1928
2146
|
}
|
|
1929
2147
|
else {
|
|
2148
|
+
this.disposeActiveSelector();
|
|
1930
2149
|
this.editorContainer.clear();
|
|
1931
2150
|
this.editorContainer.addChild(component);
|
|
1932
2151
|
this.ui.setFocus(component);
|
|
@@ -2013,7 +2232,7 @@ export class InteractiveMode {
|
|
|
2013
2232
|
this.defaultEditor.onAction("app.tools.expand", () => this.toggleToolOutputExpansion());
|
|
2014
2233
|
this.defaultEditor.onAction("app.thinking.toggle", () => this.toggleThinkingBlockVisibility());
|
|
2015
2234
|
this.defaultEditor.onAction("app.editor.external", () => void this.handleOpenExternalEditor());
|
|
2016
|
-
this.defaultEditor.onAction("app.message.copy", () => void this.handleCopyCommand());
|
|
2235
|
+
this.defaultEditor.onAction("app.message.copy", () => void this.handleCopyCommand({ flashConfirmation: true }));
|
|
2017
2236
|
this.defaultEditor.onAction("app.message.followUp", () => this.handleFollowUp());
|
|
2018
2237
|
this.defaultEditor.onAction("app.message.dequeue", () => this.handleDequeue());
|
|
2019
2238
|
this.defaultEditor.onAction("app.session.new", () => this.handleClearCommand());
|
|
@@ -2033,13 +2252,29 @@ export class InteractiveMode {
|
|
|
2033
2252
|
void this.handleClipboardPaste();
|
|
2034
2253
|
};
|
|
2035
2254
|
}
|
|
2255
|
+
async handleRightClickPaste() {
|
|
2256
|
+
const target = this.renderer.getFocusedComponent();
|
|
2257
|
+
const handleInput = target?.handleInput;
|
|
2258
|
+
if (!target || !handleInput)
|
|
2259
|
+
return;
|
|
2260
|
+
try {
|
|
2261
|
+
const text = await readClipboardText();
|
|
2262
|
+
if (!text || this.renderer.getFocusedComponent() !== target)
|
|
2263
|
+
return;
|
|
2264
|
+
handleInput.call(target, `\x1b[200~${text}\x1b[201~`);
|
|
2265
|
+
this.ui.requestRender();
|
|
2266
|
+
}
|
|
2267
|
+
catch {
|
|
2268
|
+
// Silently ignore clipboard errors (may not have permission, etc.)
|
|
2269
|
+
}
|
|
2270
|
+
}
|
|
2036
2271
|
async handleClipboardPaste() {
|
|
2037
2272
|
try {
|
|
2038
2273
|
const image = await readClipboardImage();
|
|
2039
2274
|
if (image) {
|
|
2040
2275
|
const tmpDir = os.tmpdir();
|
|
2041
2276
|
const ext = extensionForImageMimeType(image.mimeType) ?? "png";
|
|
2042
|
-
const fileName = `
|
|
2277
|
+
const fileName = `pi-clipboard-${crypto.randomUUID()}.${ext}`;
|
|
2043
2278
|
const filePath = path.join(tmpDir, fileName);
|
|
2044
2279
|
fs.writeFileSync(filePath, Buffer.from(image.bytes));
|
|
2045
2280
|
this.editor.insertTextAtCursor?.(filePath);
|
|
@@ -2175,6 +2410,11 @@ export class InteractiveMode {
|
|
|
2175
2410
|
this.editor.setText("");
|
|
2176
2411
|
return;
|
|
2177
2412
|
}
|
|
2413
|
+
if (text === "/dementedelves") {
|
|
2414
|
+
this.handleDementedDelves();
|
|
2415
|
+
this.editor.setText("");
|
|
2416
|
+
return;
|
|
2417
|
+
}
|
|
2178
2418
|
if (text === "/resume") {
|
|
2179
2419
|
this.showSessionSelector();
|
|
2180
2420
|
this.editor.setText("");
|
|
@@ -2296,17 +2536,17 @@ export class InteractiveMode {
|
|
|
2296
2536
|
this.ui.requestRender();
|
|
2297
2537
|
}
|
|
2298
2538
|
else if (event.message.role === "assistant") {
|
|
2299
|
-
this.streamingComponent = new AssistantMessageComponent(undefined, this.hideThinkingBlock, this.getMarkdownThemeWithSettings(), this.hiddenThinkingLabel, this.outputPad);
|
|
2539
|
+
this.streamingComponent = new AssistantMessageComponent(undefined, this.hideThinkingBlock, this.getMarkdownThemeWithSettings(), this.hiddenThinkingLabel, this.outputPad, this.getMarkdownTransformers());
|
|
2300
2540
|
this.streamingMessage = event.message;
|
|
2301
2541
|
this.chatContainer.addChild(this.streamingComponent);
|
|
2302
|
-
this.streamingComponent.updateContent(this.streamingMessage);
|
|
2542
|
+
this.streamingComponent.updateContent(this.streamingMessage, true);
|
|
2303
2543
|
this.ui.requestRender();
|
|
2304
2544
|
}
|
|
2305
2545
|
break;
|
|
2306
2546
|
case "message_update":
|
|
2307
2547
|
if (this.streamingComponent && event.message.role === "assistant") {
|
|
2308
2548
|
this.streamingMessage = event.message;
|
|
2309
|
-
this.streamingComponent.updateContent(this.streamingMessage);
|
|
2549
|
+
this.streamingComponent.updateContent(this.streamingMessage, true);
|
|
2310
2550
|
for (const content of this.streamingMessage.content) {
|
|
2311
2551
|
if (content.type === "toolCall") {
|
|
2312
2552
|
if (!this.pendingTools.has(content.id)) {
|
|
@@ -2343,7 +2583,7 @@ export class InteractiveMode {
|
|
|
2343
2583
|
: "Operation aborted";
|
|
2344
2584
|
this.streamingMessage.errorMessage = errorMessage;
|
|
2345
2585
|
}
|
|
2346
|
-
this.streamingComponent.updateContent(this.streamingMessage);
|
|
2586
|
+
this.streamingComponent.updateContent(this.streamingMessage, false);
|
|
2347
2587
|
if (this.streamingMessage.stopReason === "aborted" || this.streamingMessage.stopReason === "error") {
|
|
2348
2588
|
if (!errorMessage) {
|
|
2349
2589
|
errorMessage = this.streamingMessage.errorMessage || "Error";
|
|
@@ -2617,12 +2857,12 @@ export class InteractiveMode {
|
|
|
2617
2857
|
// Render user message separately if present
|
|
2618
2858
|
if (skillBlock.userMessage) {
|
|
2619
2859
|
this.chatContainer.addChild(new Spacer(1));
|
|
2620
|
-
const userComponent = new UserMessageComponent(skillBlock.userMessage, this.getMarkdownThemeWithSettings(), this.outputPad);
|
|
2860
|
+
const userComponent = new UserMessageComponent(skillBlock.userMessage, this.getMarkdownThemeWithSettings(), this.outputPad, this.getMarkdownTransformers());
|
|
2621
2861
|
this.chatContainer.addChild(userComponent);
|
|
2622
2862
|
}
|
|
2623
2863
|
}
|
|
2624
2864
|
else {
|
|
2625
|
-
const userComponent = new UserMessageComponent(textContent, this.getMarkdownThemeWithSettings(), this.outputPad);
|
|
2865
|
+
const userComponent = new UserMessageComponent(textContent, this.getMarkdownThemeWithSettings(), this.outputPad, this.getMarkdownTransformers());
|
|
2626
2866
|
this.chatContainer.addChild(userComponent);
|
|
2627
2867
|
}
|
|
2628
2868
|
if (options?.populateHistory) {
|
|
@@ -2632,7 +2872,7 @@ export class InteractiveMode {
|
|
|
2632
2872
|
break;
|
|
2633
2873
|
}
|
|
2634
2874
|
case "assistant": {
|
|
2635
|
-
const assistantComponent = new AssistantMessageComponent(message, this.hideThinkingBlock, this.getMarkdownThemeWithSettings(), this.hiddenThinkingLabel, this.outputPad);
|
|
2875
|
+
const assistantComponent = new AssistantMessageComponent(message, this.hideThinkingBlock, this.getMarkdownThemeWithSettings(), this.hiddenThinkingLabel, this.outputPad, this.getMarkdownTransformers());
|
|
2636
2876
|
this.chatContainer.addChild(assistantComponent);
|
|
2637
2877
|
break;
|
|
2638
2878
|
}
|
|
@@ -2784,7 +3024,7 @@ export class InteractiveMode {
|
|
|
2784
3024
|
if (this.chatContainer.children.length > 0) {
|
|
2785
3025
|
this.chatContainer.addChild(new Spacer(1));
|
|
2786
3026
|
}
|
|
2787
|
-
this.chatContainer.addChild(new Text(theme.fg("warning", `This project is not trusted. Project ${CONFIG_DIR_NAME} resources and packages are ignored. Use /trust to save a trust decision, then restart
|
|
3027
|
+
this.chatContainer.addChild(new Text(theme.fg("warning", `This project is not trusted. Project ${CONFIG_DIR_NAME} resources and packages are ignored. Use /trust to save a trust decision, then restart pi.`), 1, 0));
|
|
2788
3028
|
}
|
|
2789
3029
|
async getUserInput() {
|
|
2790
3030
|
const queuedInput = this.pendingUserInputs.shift();
|
|
@@ -2897,7 +3137,7 @@ export class InteractiveMode {
|
|
|
2897
3137
|
this.ui.stop();
|
|
2898
3138
|
}
|
|
2899
3139
|
catch { }
|
|
2900
|
-
console.error(
|
|
3140
|
+
console.error("pi exiting due to uncaughtException:");
|
|
2901
3141
|
console.error(error);
|
|
2902
3142
|
process.exit(1);
|
|
2903
3143
|
}
|
|
@@ -2939,7 +3179,7 @@ export class InteractiveMode {
|
|
|
2939
3179
|
this.signalCleanupHandlers.push(() => process.stderr.off("error", terminalErrorHandler));
|
|
2940
3180
|
// Restore the terminal before the process dies on any uncaught throw.
|
|
2941
3181
|
// Without this, an unhandled exception from extension code (or anywhere
|
|
2942
|
-
// in
|
|
3182
|
+
// in pi) leaves the terminal in raw mode with no cursor.
|
|
2943
3183
|
const uncaughtExceptionHandler = (error) => this.uncaughtCrash(error);
|
|
2944
3184
|
process.prependListener("uncaughtException", uncaughtExceptionHandler);
|
|
2945
3185
|
this.signalCleanupHandlers.push(() => process.off("uncaughtException", uncaughtExceptionHandler));
|
|
@@ -3066,6 +3306,8 @@ export class InteractiveMode {
|
|
|
3066
3306
|
this.setToolsExpanded(!this.toolOutputExpanded);
|
|
3067
3307
|
}
|
|
3068
3308
|
setToolsExpanded(expanded) {
|
|
3309
|
+
if (expanded === this.toolOutputExpanded)
|
|
3310
|
+
return;
|
|
3069
3311
|
this.toolOutputExpanded = expanded;
|
|
3070
3312
|
const activeHeader = this.customHeader ?? this.builtInHeader;
|
|
3071
3313
|
if (isExpandable(activeHeader)) {
|
|
@@ -3121,7 +3363,7 @@ export class InteractiveMode {
|
|
|
3121
3363
|
}
|
|
3122
3364
|
showError(errorMessage) {
|
|
3123
3365
|
this.chatContainer.addChild(new Spacer(1));
|
|
3124
|
-
this.chatContainer.addChild(new Text(theme.fg("error", `Error: ${errorMessage}`),
|
|
3366
|
+
this.chatContainer.addChild(new Text(theme.fg("error", `Error: ${errorMessage}`), this.outputPad, 0));
|
|
3125
3367
|
this.ui.requestRender();
|
|
3126
3368
|
}
|
|
3127
3369
|
showWarning(warningMessage) {
|
|
@@ -3132,7 +3374,7 @@ export class InteractiveMode {
|
|
|
3132
3374
|
showNewVersionNotification(release) {
|
|
3133
3375
|
const action = theme.fg("accent", `${APP_NAME} update`);
|
|
3134
3376
|
const updateInstruction = theme.fg("muted", `New version ${release.version} is available. Run `) + action;
|
|
3135
|
-
const changelogUrl =
|
|
3377
|
+
const changelogUrl = "https://pi.dev/changelog";
|
|
3136
3378
|
const changelogLink = getCapabilities().hyperlinks
|
|
3137
3379
|
? hyperlink(theme.fg("accent", changelogUrl), changelogUrl)
|
|
3138
3380
|
: theme.fg("accent", changelogUrl);
|
|
@@ -3331,25 +3573,43 @@ export class InteractiveMode {
|
|
|
3331
3573
|
// =========================================================================
|
|
3332
3574
|
// Selectors
|
|
3333
3575
|
// =========================================================================
|
|
3576
|
+
disposeActiveSelector() {
|
|
3577
|
+
const dispose = this.activeSelectorDispose;
|
|
3578
|
+
this.activeSelectorToken = undefined;
|
|
3579
|
+
this.activeSelectorDispose = undefined;
|
|
3580
|
+
dispose?.();
|
|
3581
|
+
}
|
|
3334
3582
|
/**
|
|
3335
3583
|
* Shows a selector component in place of the editor.
|
|
3336
3584
|
* @param create Factory that receives a `done` callback and returns the component and focus target
|
|
3337
3585
|
*/
|
|
3338
3586
|
showSelector(create) {
|
|
3587
|
+
const token = {};
|
|
3588
|
+
let dispose;
|
|
3339
3589
|
const done = () => {
|
|
3590
|
+
dispose?.();
|
|
3591
|
+
if (this.activeSelectorToken !== token)
|
|
3592
|
+
return;
|
|
3593
|
+
this.activeSelectorToken = undefined;
|
|
3594
|
+
this.activeSelectorDispose = undefined;
|
|
3340
3595
|
this.editorContainer.clear();
|
|
3341
3596
|
this.editorContainer.addChild(this.editor);
|
|
3342
3597
|
this.ui.setFocus(this.editor);
|
|
3343
3598
|
};
|
|
3344
|
-
const
|
|
3599
|
+
const created = create(done);
|
|
3600
|
+
dispose = created.dispose;
|
|
3601
|
+
this.disposeActiveSelector();
|
|
3602
|
+
this.activeSelectorToken = token;
|
|
3603
|
+
this.activeSelectorDispose = dispose;
|
|
3345
3604
|
this.editorContainer.clear();
|
|
3346
|
-
this.editorContainer.addChild(component);
|
|
3347
|
-
this.ui.setFocus(focus);
|
|
3605
|
+
this.editorContainer.addChild(created.component);
|
|
3606
|
+
this.ui.setFocus(created.focus);
|
|
3348
3607
|
this.ui.requestRender();
|
|
3349
3608
|
}
|
|
3350
3609
|
showSettingsSelector() {
|
|
3351
3610
|
this.showSelector((done) => {
|
|
3352
|
-
|
|
3611
|
+
let selector;
|
|
3612
|
+
selector = new SettingsSelectorComponent({
|
|
3353
3613
|
autoCompact: this.session.autoCompactionEnabled,
|
|
3354
3614
|
showImages: this.settingsManager.getShowImages(),
|
|
3355
3615
|
imageWidthCells: this.settingsManager.getImageWidthCells(),
|
|
@@ -3366,6 +3626,7 @@ export class InteractiveMode {
|
|
|
3366
3626
|
terminalTheme: this.themeController.getTerminalTheme(),
|
|
3367
3627
|
availableThemes: getAvailableThemes(),
|
|
3368
3628
|
hideThinkingBlock: this.hideThinkingBlock,
|
|
3629
|
+
mermaidRenderingMode: this.settingsManager.getMermaidRenderingMode(),
|
|
3369
3630
|
collapseChangelog: this.settingsManager.getCollapseChangelog(),
|
|
3370
3631
|
enableInstallTelemetry: this.settingsManager.getEnableInstallTelemetry(),
|
|
3371
3632
|
doubleEscapeAction: this.settingsManager.getDoubleEscapeAction(),
|
|
@@ -3379,6 +3640,8 @@ export class InteractiveMode {
|
|
|
3379
3640
|
quietStartup: this.settingsManager.getQuietStartup(),
|
|
3380
3641
|
clearOnShrink: this.settingsManager.getClearOnShrink(),
|
|
3381
3642
|
showTerminalProgress: this.settingsManager.getShowTerminalProgress(),
|
|
3643
|
+
tuiMode: this.ui.mode,
|
|
3644
|
+
fullscreenScrollbar: this.settingsManager.getFullscreenScrollbar(),
|
|
3382
3645
|
warnings: this.settingsManager.getWarnings(),
|
|
3383
3646
|
}, {
|
|
3384
3647
|
onAutoCompactChange: (enabled) => {
|
|
@@ -3447,6 +3710,11 @@ export class InteractiveMode {
|
|
|
3447
3710
|
this.chatContainer.clear();
|
|
3448
3711
|
this.rebuildChatFromMessages();
|
|
3449
3712
|
},
|
|
3713
|
+
onMermaidRenderingModeChange: (mode) => {
|
|
3714
|
+
this.settingsManager.setMermaidRenderingMode(mode);
|
|
3715
|
+
this.chatContainer.invalidate();
|
|
3716
|
+
this.ui.requestRender();
|
|
3717
|
+
},
|
|
3450
3718
|
onShowCacheMissNoticesChange: (shown) => {
|
|
3451
3719
|
this.settingsManager.setShowCacheMissNotices(shown);
|
|
3452
3720
|
this.rebuildChatFromMessages();
|
|
@@ -3516,6 +3784,21 @@ export class InteractiveMode {
|
|
|
3516
3784
|
onShowTerminalProgressChange: (enabled) => {
|
|
3517
3785
|
this.settingsManager.setShowTerminalProgress(enabled);
|
|
3518
3786
|
},
|
|
3787
|
+
onTuiModeChange: (mode) => {
|
|
3788
|
+
if (!this.switchTuiMode(mode)) {
|
|
3789
|
+
selector?.getSettingsList().updateValue("tui-mode", this.ui.mode);
|
|
3790
|
+
this.showStatus("Close active overlays before changing TUI mode");
|
|
3791
|
+
return;
|
|
3792
|
+
}
|
|
3793
|
+
this.settingsManager.setTuiMode(mode);
|
|
3794
|
+
if (!this.activeStatusIndicator)
|
|
3795
|
+
this.statusContainer.clear();
|
|
3796
|
+
this.showStatus(`TUI mode: ${mode}`);
|
|
3797
|
+
},
|
|
3798
|
+
onFullscreenScrollbarChange: (mode) => {
|
|
3799
|
+
this.settingsManager.setFullscreenScrollbar(mode);
|
|
3800
|
+
this.applyFullscreenScrollbarSetting();
|
|
3801
|
+
},
|
|
3519
3802
|
onWarningsChange: (warnings) => {
|
|
3520
3803
|
this.settingsManager.setWarnings(warnings);
|
|
3521
3804
|
},
|
|
@@ -3550,20 +3833,37 @@ export class InteractiveMode {
|
|
|
3550
3833
|
this.showModelSelector(searchTerm);
|
|
3551
3834
|
}
|
|
3552
3835
|
async findExactModelMatch(searchTerm) {
|
|
3553
|
-
const
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
if (this.session.scopedModels.length > 0)
|
|
3558
|
-
return
|
|
3559
|
-
|
|
3836
|
+
const cachedModels = this.session.scopedModels.length > 0
|
|
3837
|
+
? this.session.scopedModels.map((scoped) => scoped.model)
|
|
3838
|
+
: [...this.session.modelRuntime.getAvailableSnapshot()];
|
|
3839
|
+
const cachedMatch = findExactModelReferenceMatch(searchTerm, cachedModels);
|
|
3840
|
+
if (cachedMatch || this.session.scopedModels.length > 0)
|
|
3841
|
+
return cachedMatch;
|
|
3842
|
+
this.showStatus("Refreshing model catalogs…");
|
|
3843
|
+
const controller = new AbortController();
|
|
3844
|
+
let timedOut = false;
|
|
3845
|
+
const timeout = setTimeout(() => {
|
|
3846
|
+
timedOut = true;
|
|
3847
|
+
controller.abort();
|
|
3848
|
+
}, 15_000);
|
|
3560
3849
|
try {
|
|
3561
|
-
await this.session.modelRuntime.refresh();
|
|
3562
|
-
|
|
3850
|
+
const result = await this.session.modelRuntime.refresh({ signal: controller.signal });
|
|
3851
|
+
if (result.aborted && timedOut) {
|
|
3852
|
+
this.showWarning("Model refresh timed out; searching cached models.");
|
|
3853
|
+
}
|
|
3854
|
+
else if (result.errors.size > 0) {
|
|
3855
|
+
this.showWarning(`Could not refresh ${[...result.errors.keys()].join(", ")}; searching cached models.`);
|
|
3856
|
+
}
|
|
3563
3857
|
}
|
|
3564
|
-
catch {
|
|
3565
|
-
|
|
3858
|
+
catch (error) {
|
|
3859
|
+
this.showWarning(timedOut
|
|
3860
|
+
? "Model refresh timed out; searching cached models."
|
|
3861
|
+
: `Could not refresh model catalogs: ${error instanceof Error ? error.message : String(error)}`);
|
|
3566
3862
|
}
|
|
3863
|
+
finally {
|
|
3864
|
+
clearTimeout(timeout);
|
|
3865
|
+
}
|
|
3866
|
+
return findExactModelReferenceMatch(searchTerm, [...this.session.modelRuntime.getAvailableSnapshot()]);
|
|
3567
3867
|
}
|
|
3568
3868
|
/** Update the footer's available provider count from the current snapshot without refreshing catalogs. */
|
|
3569
3869
|
updateAvailableProviderCount() {
|
|
@@ -3635,7 +3935,7 @@ export class InteractiveMode {
|
|
|
3635
3935
|
onSelect: (selection) => {
|
|
3636
3936
|
trustStore.setMany(selection.updates);
|
|
3637
3937
|
done();
|
|
3638
|
-
this.showStatus(`Saved trust decision: ${selection.trusted ? "trusted" : "untrusted"}. Restart
|
|
3938
|
+
this.showStatus(`Saved trust decision: ${selection.trusted ? "trusted" : "untrusted"}. Restart pi for this to take effect.`);
|
|
3639
3939
|
},
|
|
3640
3940
|
onCancel: () => {
|
|
3641
3941
|
done();
|
|
@@ -3665,73 +3965,67 @@ export class InteractiveMode {
|
|
|
3665
3965
|
done();
|
|
3666
3966
|
this.ui.requestRender();
|
|
3667
3967
|
}, initialSearchInput);
|
|
3668
|
-
return { component: selector, focus: selector };
|
|
3968
|
+
return { component: selector, focus: selector, dispose: () => selector.dispose() };
|
|
3669
3969
|
});
|
|
3670
3970
|
}
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
const allModels = [...(await this.session.modelRuntime.getAvailable())];
|
|
3675
|
-
const allModelIds = new Set(allModels.map((model) => `${model.provider}/${model.id}`));
|
|
3971
|
+
showModelsSelector() {
|
|
3972
|
+
let availableModels = [...this.session.modelRuntime.getAvailableSnapshot()];
|
|
3973
|
+
let availableModelIds = new Set(availableModels.map((model) => `${model.provider}/${model.id}`));
|
|
3676
3974
|
const configuredPatterns = this.settingsManager.getEnabledModels();
|
|
3677
3975
|
const sessionScopedModels = this.session.scopedModels;
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
currentEnabledIds = configuredScope.scopedModels.map((scoped) => `${scoped.model.provider}/${scoped.model.id}`);
|
|
3695
|
-
}
|
|
3696
|
-
for (const diagnostic of configuredScope?.diagnostics ?? []) {
|
|
3697
|
-
if (diagnostic.code !== "no-match")
|
|
3698
|
-
continue;
|
|
3699
|
-
currentEnabledIds ??= [];
|
|
3700
|
-
if (!currentEnabledIds.includes(diagnostic.pattern))
|
|
3701
|
-
currentEnabledIds.push(diagnostic.pattern);
|
|
3702
|
-
}
|
|
3703
|
-
// Helper to update session's scoped models (session-only, no persist)
|
|
3704
|
-
const updateSessionModels = async (enabledIds) => {
|
|
3976
|
+
const configuredEnabledIds = (models) => {
|
|
3977
|
+
if (!configuredPatterns?.length)
|
|
3978
|
+
return null;
|
|
3979
|
+
const resolved = resolveModelScopeFromModels(configuredPatterns, models);
|
|
3980
|
+
const ids = resolved.scopedModels.map((scoped) => `${scoped.model.provider}/${scoped.model.id}`);
|
|
3981
|
+
for (const diagnostic of resolved.diagnostics) {
|
|
3982
|
+
if (diagnostic.code === "no-match" && !ids.includes(diagnostic.pattern))
|
|
3983
|
+
ids.push(diagnostic.pattern);
|
|
3984
|
+
}
|
|
3985
|
+
return ids;
|
|
3986
|
+
};
|
|
3987
|
+
let currentEnabledIds = sessionScopedModels.length > 0
|
|
3988
|
+
? sessionScopedModels.map((scoped) => `${scoped.model.provider}/${scoped.model.id}`)
|
|
3989
|
+
: configuredEnabledIds(availableModels);
|
|
3990
|
+
let selectionChanged = false;
|
|
3991
|
+
const updateSessionModels = (enabledIds) => {
|
|
3705
3992
|
currentEnabledIds = enabledIds === null ? null : [...enabledIds];
|
|
3706
|
-
const hasEnabledAvailableModel = enabledIds?.some((id) =>
|
|
3707
|
-
const allAvailableModelsEnabled = enabledIds !== null && [...
|
|
3993
|
+
const hasEnabledAvailableModel = enabledIds?.some((id) => availableModelIds.has(id)) ?? false;
|
|
3994
|
+
const allAvailableModelsEnabled = enabledIds !== null && [...availableModelIds].every((id) => enabledIds.includes(id));
|
|
3708
3995
|
if (enabledIds && hasEnabledAvailableModel && !allAvailableModelsEnabled) {
|
|
3709
|
-
const newScopedModels =
|
|
3710
|
-
this.session.setScopedModels(newScopedModels.map((
|
|
3711
|
-
model:
|
|
3712
|
-
thinkingLevel:
|
|
3996
|
+
const newScopedModels = resolveModelScopeFromModels(enabledIds, availableModels).scopedModels;
|
|
3997
|
+
this.session.setScopedModels(newScopedModels.map((scoped) => ({
|
|
3998
|
+
model: scoped.model,
|
|
3999
|
+
thinkingLevel: scoped.thinkingLevel,
|
|
3713
4000
|
})));
|
|
3714
4001
|
}
|
|
3715
4002
|
else {
|
|
3716
|
-
// All enabled or none enabled = no filter
|
|
3717
4003
|
this.session.setScopedModels([]);
|
|
3718
4004
|
}
|
|
3719
|
-
|
|
4005
|
+
this.updateAvailableProviderCount();
|
|
3720
4006
|
this.ui.requestRender();
|
|
3721
4007
|
};
|
|
3722
4008
|
this.showSelector((done) => {
|
|
4009
|
+
let disposed = false;
|
|
4010
|
+
let timedOut = false;
|
|
4011
|
+
const controller = new AbortController();
|
|
4012
|
+
const timeout = setTimeout(() => {
|
|
4013
|
+
timedOut = true;
|
|
4014
|
+
controller.abort();
|
|
4015
|
+
}, 15_000);
|
|
3723
4016
|
const selector = new ScopedModelsSelectorComponent({
|
|
3724
|
-
allModels,
|
|
4017
|
+
allModels: availableModels,
|
|
3725
4018
|
enabledModelIds: currentEnabledIds,
|
|
4019
|
+
refreshStatus: "Refreshing model catalogs…",
|
|
3726
4020
|
}, {
|
|
3727
|
-
onChange:
|
|
3728
|
-
|
|
4021
|
+
onChange: (enabledIds) => {
|
|
4022
|
+
selectionChanged = true;
|
|
4023
|
+
updateSessionModels(enabledIds);
|
|
3729
4024
|
},
|
|
3730
4025
|
onPersist: (enabledIds) => {
|
|
3731
|
-
// Persist to settings
|
|
3732
4026
|
const allEnabled = enabledIds !== null &&
|
|
3733
|
-
enabledIds.length ===
|
|
3734
|
-
enabledIds.every((id) =>
|
|
4027
|
+
enabledIds.length === availableModels.length &&
|
|
4028
|
+
enabledIds.every((id) => availableModelIds.has(id));
|
|
3735
4029
|
const newPatterns = enabledIds === null || allEnabled ? undefined : enabledIds;
|
|
3736
4030
|
this.settingsManager.setEnabledModels(newPatterns ? [...newPatterns] : undefined);
|
|
3737
4031
|
this.showStatus("Model selection saved to settings");
|
|
@@ -3741,7 +4035,51 @@ export class InteractiveMode {
|
|
|
3741
4035
|
this.ui.requestRender();
|
|
3742
4036
|
},
|
|
3743
4037
|
});
|
|
3744
|
-
|
|
4038
|
+
void this.session.modelRuntime
|
|
4039
|
+
.refresh({ signal: controller.signal })
|
|
4040
|
+
.then((result) => {
|
|
4041
|
+
if (disposed)
|
|
4042
|
+
return;
|
|
4043
|
+
availableModels = [...this.session.modelRuntime.getAvailableSnapshot()];
|
|
4044
|
+
availableModelIds = new Set(availableModels.map((model) => `${model.provider}/${model.id}`));
|
|
4045
|
+
if (!selectionChanged && sessionScopedModels.length === 0) {
|
|
4046
|
+
currentEnabledIds = configuredEnabledIds(availableModels);
|
|
4047
|
+
selector.updateModels(availableModels, currentEnabledIds);
|
|
4048
|
+
}
|
|
4049
|
+
else {
|
|
4050
|
+
selector.updateModels(availableModels);
|
|
4051
|
+
}
|
|
4052
|
+
if (currentEnabledIds !== null)
|
|
4053
|
+
updateSessionModels(currentEnabledIds);
|
|
4054
|
+
if (result.aborted && timedOut) {
|
|
4055
|
+
selector.setRefreshStatus("Model refresh timed out; showing cached models.", "warning");
|
|
4056
|
+
}
|
|
4057
|
+
else if (result.errors.size > 0) {
|
|
4058
|
+
selector.setRefreshStatus(`Could not refresh ${[...result.errors.keys()].join(", ")}; showing cached models.`, "warning");
|
|
4059
|
+
}
|
|
4060
|
+
else {
|
|
4061
|
+
selector.setRefreshStatus("Model catalogs refreshed.", "success");
|
|
4062
|
+
}
|
|
4063
|
+
this.ui.requestRender();
|
|
4064
|
+
})
|
|
4065
|
+
.catch((error) => {
|
|
4066
|
+
if (disposed)
|
|
4067
|
+
return;
|
|
4068
|
+
selector.setRefreshStatus(timedOut
|
|
4069
|
+
? "Model refresh timed out; showing cached models."
|
|
4070
|
+
: `Could not refresh model catalogs: ${error instanceof Error ? error.message : String(error)}`, "warning");
|
|
4071
|
+
this.ui.requestRender();
|
|
4072
|
+
})
|
|
4073
|
+
.finally(() => clearTimeout(timeout));
|
|
4074
|
+
return {
|
|
4075
|
+
component: selector,
|
|
4076
|
+
focus: selector,
|
|
4077
|
+
dispose: () => {
|
|
4078
|
+
disposed = true;
|
|
4079
|
+
clearTimeout(timeout);
|
|
4080
|
+
controller.abort();
|
|
4081
|
+
},
|
|
4082
|
+
};
|
|
3745
4083
|
});
|
|
3746
4084
|
}
|
|
3747
4085
|
showUserMessageSelector() {
|
|
@@ -4003,7 +4341,7 @@ export class InteractiveMode {
|
|
|
4003
4341
|
return options.sort((a, b) => a.name.localeCompare(b.name));
|
|
4004
4342
|
}
|
|
4005
4343
|
async getLogoutProviderOptions() {
|
|
4006
|
-
return (await this.session.modelRuntime.listCredentials())
|
|
4344
|
+
return (await this.session.modelRuntime.listCredentials({ signal: AbortSignal.timeout(15_000) }))
|
|
4007
4345
|
.map(({ providerId, type }) => ({
|
|
4008
4346
|
id: providerId,
|
|
4009
4347
|
name: this.session.modelRuntime.getProvider(providerId)?.name ?? providerId,
|
|
@@ -4021,7 +4359,6 @@ export class InteractiveMode {
|
|
|
4021
4359
|
provider.name.toLowerCase() === normalizedProviderRef);
|
|
4022
4360
|
}
|
|
4023
4361
|
async handleLoginCommand(providerRef) {
|
|
4024
|
-
await this.session.modelRuntime.getAvailable();
|
|
4025
4362
|
if (!providerRef) {
|
|
4026
4363
|
this.showLoginAuthTypeSelector();
|
|
4027
4364
|
return;
|
|
@@ -4135,7 +4472,14 @@ export class InteractiveMode {
|
|
|
4135
4472
|
this.showLoginAuthTypeSelector();
|
|
4136
4473
|
return;
|
|
4137
4474
|
}
|
|
4138
|
-
|
|
4475
|
+
let providerOptions;
|
|
4476
|
+
try {
|
|
4477
|
+
providerOptions = await this.getLogoutProviderOptions();
|
|
4478
|
+
}
|
|
4479
|
+
catch (error) {
|
|
4480
|
+
this.showError(`Could not read stored credentials: ${error instanceof Error ? error.message : String(error)}`);
|
|
4481
|
+
return;
|
|
4482
|
+
}
|
|
4139
4483
|
if (providerOptions.length === 0) {
|
|
4140
4484
|
this.showStatus("No stored credentials to remove. /logout only removes credentials saved by /login; environment variables and models.json config are unchanged.");
|
|
4141
4485
|
return;
|
|
@@ -4148,7 +4492,9 @@ export class InteractiveMode {
|
|
|
4148
4492
|
return;
|
|
4149
4493
|
}
|
|
4150
4494
|
try {
|
|
4151
|
-
await this.session.modelRuntime.logout(providerOption.id
|
|
4495
|
+
await this.session.modelRuntime.logout(providerOption.id, {
|
|
4496
|
+
signal: AbortSignal.timeout(15_000),
|
|
4497
|
+
});
|
|
4152
4498
|
await this.updateAvailableProviderCount();
|
|
4153
4499
|
const message = providerOption.authType === "oauth"
|
|
4154
4500
|
? `Logged out of ${providerOption.name}`
|
|
@@ -4156,7 +4502,10 @@ export class InteractiveMode {
|
|
|
4156
4502
|
this.showStatus(message);
|
|
4157
4503
|
}
|
|
4158
4504
|
catch (error) {
|
|
4159
|
-
|
|
4505
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
4506
|
+
this.showError(error instanceof CredentialSynchronizationError
|
|
4507
|
+
? `Credentials removed for ${providerOption.name}, but local model state could not be synchronized: ${message}`
|
|
4508
|
+
: `Logout failed: ${message}`);
|
|
4160
4509
|
}
|
|
4161
4510
|
}, () => {
|
|
4162
4511
|
done();
|
|
@@ -4166,12 +4515,11 @@ export class InteractiveMode {
|
|
|
4166
4515
|
});
|
|
4167
4516
|
}
|
|
4168
4517
|
async completeProviderAuthentication(providerId, providerName, authType, previousModel) {
|
|
4169
|
-
await this.session.modelRuntime.getAvailable();
|
|
4170
4518
|
const actionLabel = authType === "oauth" ? `Logged in to ${providerName}` : `Saved API key for ${providerName}`;
|
|
4171
4519
|
let selectedModel;
|
|
4172
4520
|
let selectionError;
|
|
4173
4521
|
if (isUnknownModel(previousModel)) {
|
|
4174
|
-
const availableModels =
|
|
4522
|
+
const availableModels = this.session.modelRuntime.getAvailableSnapshot();
|
|
4175
4523
|
const providerModels = availableModels.filter((model) => model.provider === providerId);
|
|
4176
4524
|
if (!hasDefaultModelProvider(providerId)) {
|
|
4177
4525
|
selectionError = `${actionLabel}, but no default model is configured for provider "${providerId}". Use /model to select a model.`;
|
|
@@ -4214,6 +4562,25 @@ export class InteractiveMode {
|
|
|
4214
4562
|
void this.maybeWarnAboutAnthropicSubscriptionAuth();
|
|
4215
4563
|
}
|
|
4216
4564
|
}
|
|
4565
|
+
const controller = new AbortController();
|
|
4566
|
+
const timeout = setTimeout(() => controller.abort(), 15_000);
|
|
4567
|
+
void this.session.modelRuntime
|
|
4568
|
+
.refresh({ providers: [providerId], signal: controller.signal })
|
|
4569
|
+
.then((result) => {
|
|
4570
|
+
if (result.aborted) {
|
|
4571
|
+
this.showWarning(`${actionLabel}, but its model catalog refresh timed out; using cached models.`);
|
|
4572
|
+
}
|
|
4573
|
+
else if (result.errors.size > 0) {
|
|
4574
|
+
this.showWarning(`${actionLabel}, but its model catalog could not be refreshed; using cached models.`);
|
|
4575
|
+
}
|
|
4576
|
+
this.updateAvailableProviderCount();
|
|
4577
|
+
this.footer.invalidate();
|
|
4578
|
+
this.ui.requestRender();
|
|
4579
|
+
})
|
|
4580
|
+
.catch((error) => {
|
|
4581
|
+
this.showWarning(`${actionLabel}, but its model catalog could not be refreshed: ${error instanceof Error ? error.message : String(error)}`);
|
|
4582
|
+
})
|
|
4583
|
+
.finally(() => clearTimeout(timeout));
|
|
4217
4584
|
}
|
|
4218
4585
|
showAmbientAuthDialog(providerOption) {
|
|
4219
4586
|
const restoreEditor = () => {
|
|
@@ -4259,7 +4626,10 @@ export class InteractiveMode {
|
|
|
4259
4626
|
catch (error) {
|
|
4260
4627
|
restoreEditor();
|
|
4261
4628
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
4262
|
-
if (
|
|
4629
|
+
if (error instanceof CredentialSynchronizationError) {
|
|
4630
|
+
this.showError(`Saved API key for ${providerName}, but local model state could not be synchronized: ${errorMsg}`);
|
|
4631
|
+
}
|
|
4632
|
+
else if (errorMsg !== "Login cancelled") {
|
|
4263
4633
|
this.showError(`Failed to save API key for ${providerName}: ${errorMsg}`);
|
|
4264
4634
|
}
|
|
4265
4635
|
}
|
|
@@ -4362,7 +4732,10 @@ export class InteractiveMode {
|
|
|
4362
4732
|
catch (error) {
|
|
4363
4733
|
restoreEditor();
|
|
4364
4734
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
4365
|
-
if (
|
|
4735
|
+
if (error instanceof CredentialSynchronizationError) {
|
|
4736
|
+
this.showError(`Logged in to ${providerName}, but local model state could not be synchronized: ${errorMsg}`);
|
|
4737
|
+
}
|
|
4738
|
+
else if (errorMsg !== "Login cancelled") {
|
|
4366
4739
|
this.showError(`Failed to login to ${providerName}: ${errorMsg}`);
|
|
4367
4740
|
}
|
|
4368
4741
|
}
|
|
@@ -4413,7 +4786,6 @@ export class InteractiveMode {
|
|
|
4413
4786
|
try {
|
|
4414
4787
|
await this.session.reload({ beforeSessionStart: restoreChatBeforeSessionStart });
|
|
4415
4788
|
restoreChatBeforeSessionStart();
|
|
4416
|
-
configureHttpDispatcher(this.settingsManager.getHttpIdleTimeoutMs());
|
|
4417
4789
|
this.keybindings.reload();
|
|
4418
4790
|
const activeHeader = this.customHeader ?? this.builtInHeader;
|
|
4419
4791
|
if (isExpandable(activeHeader)) {
|
|
@@ -4421,20 +4793,7 @@ export class InteractiveMode {
|
|
|
4421
4793
|
}
|
|
4422
4794
|
setRegisteredThemes(this.session.resourceLoader.getThemes().themes);
|
|
4423
4795
|
await this.themeController.applyFromSettings();
|
|
4424
|
-
|
|
4425
|
-
const autocompleteMaxVisible = this.settingsManager.getAutocompleteMaxVisible();
|
|
4426
|
-
this.defaultEditor.setPaddingX(editorPaddingX);
|
|
4427
|
-
this.defaultEditor.setAutocompleteMaxVisible(autocompleteMaxVisible);
|
|
4428
|
-
if (this.editor !== this.defaultEditor) {
|
|
4429
|
-
this.editor.setPaddingX?.(editorPaddingX);
|
|
4430
|
-
this.editor.setAutocompleteMaxVisible?.(autocompleteMaxVisible);
|
|
4431
|
-
}
|
|
4432
|
-
this.ui.setShowHardwareCursor(this.settingsManager.getShowHardwareCursor());
|
|
4433
|
-
const clearOnShrink = this.settingsManager.getClearOnShrink();
|
|
4434
|
-
this.ui.setClearOnShrink(clearOnShrink);
|
|
4435
|
-
if (!clearOnShrink && !this.activeStatusIndicator) {
|
|
4436
|
-
this.statusContainer.clear();
|
|
4437
|
-
}
|
|
4796
|
+
this.applyRuntimeSettings();
|
|
4438
4797
|
this.setupAutocompleteProvider();
|
|
4439
4798
|
const runner = this.session.extensionRunner;
|
|
4440
4799
|
this.setupExtensionShortcuts(runner);
|
|
@@ -4630,7 +4989,7 @@ export class InteractiveMode {
|
|
|
4630
4989
|
}
|
|
4631
4990
|
}
|
|
4632
4991
|
}
|
|
4633
|
-
async handleCopyCommand() {
|
|
4992
|
+
async handleCopyCommand(options = {}) {
|
|
4634
4993
|
const text = this.session.getLastAssistantText();
|
|
4635
4994
|
if (!text) {
|
|
4636
4995
|
this.showError("No agent messages to copy yet.");
|
|
@@ -4638,7 +4997,12 @@ export class InteractiveMode {
|
|
|
4638
4997
|
}
|
|
4639
4998
|
try {
|
|
4640
4999
|
await copyToClipboard(text);
|
|
4641
|
-
|
|
5000
|
+
if (options.flashConfirmation && this.ui instanceof TuiAltScreen) {
|
|
5001
|
+
this.ui.flash("Copied!");
|
|
5002
|
+
}
|
|
5003
|
+
else {
|
|
5004
|
+
this.showStatus("Copied last agent message to clipboard");
|
|
5005
|
+
}
|
|
4642
5006
|
}
|
|
4643
5007
|
catch (error) {
|
|
4644
5008
|
this.showError(error instanceof Error ? error.message : String(error));
|
|
@@ -4911,6 +5275,11 @@ export class InteractiveMode {
|
|
|
4911
5275
|
this.chatContainer.addChild(new ArminComponent(this.ui));
|
|
4912
5276
|
this.ui.requestRender();
|
|
4913
5277
|
}
|
|
5278
|
+
handleDementedDelves() {
|
|
5279
|
+
this.chatContainer.addChild(new Spacer(1));
|
|
5280
|
+
this.chatContainer.addChild(new EarendilAnnouncementComponent());
|
|
5281
|
+
this.ui.requestRender();
|
|
5282
|
+
}
|
|
4914
5283
|
handleDaxnuts() {
|
|
4915
5284
|
this.chatContainer.addChild(new Spacer(1));
|
|
4916
5285
|
this.chatContainer.addChild(new DaxnutsComponent(this.ui));
|
|
@@ -4996,6 +5365,7 @@ export class InteractiveMode {
|
|
|
4996
5365
|
}
|
|
4997
5366
|
}
|
|
4998
5367
|
stop() {
|
|
5368
|
+
this.disposeActiveSelector();
|
|
4999
5369
|
if (this.settingsManager.getShowTerminalProgress()) {
|
|
5000
5370
|
this.ui.terminal.setProgress(false);
|
|
5001
5371
|
}
|
|
@@ -5008,7 +5378,7 @@ export class InteractiveMode {
|
|
|
5008
5378
|
this.unsubscribe();
|
|
5009
5379
|
}
|
|
5010
5380
|
if (this.isInitialized) {
|
|
5011
|
-
this.
|
|
5381
|
+
this.stopInteractiveTui();
|
|
5012
5382
|
this.isInitialized = false;
|
|
5013
5383
|
}
|
|
5014
5384
|
this.unregisterSignalHandlers();
|