@astralyn/pi 0.82.7 → 0.84.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 +78 -5099
- package/README.md +12 -111
- package/dist/bun/cli.d.ts.map +1 -1
- package/dist/bun/cli.js.map +1 -1
- package/dist/bun/register-bedrock.d.ts.map +1 -1
- package/dist/bun/restore-sandbox-env.d.ts.map +1 -1
- package/dist/bun/restore-sandbox-env.js.map +1 -1
- package/dist/cli/args.d.ts +2 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +28 -2
- package/dist/cli/args.js.map +1 -1
- 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 +23 -0
- package/dist/cli/credential-print.d.ts.map +1 -0
- package/dist/cli/credential-print.js +117 -0
- package/dist/cli/credential-print.js.map +1 -0
- 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 +127 -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/file-processor.d.ts.map +1 -1
- package/dist/cli/file-processor.js.map +1 -1
- package/dist/cli/initial-message.d.ts +1 -1
- package/dist/cli/initial-message.d.ts.map +1 -1
- package/dist/cli/initial-message.js.map +1 -1
- 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/project-trust.d.ts.map +1 -1
- package/dist/cli/project-trust.js.map +1 -1
- package/dist/cli/session-picker.d.ts.map +1 -1
- package/dist/cli/session-picker.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/cli.d.ts.map +1 -1
- package/dist/cli.js +1 -0
- package/dist/cli.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/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +3 -8
- package/dist/core/agent-session-runtime.js.map +1 -1
- 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 +31 -11
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +189 -192
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-guidance.d.ts.map +1 -1
- package/dist/core/auth-guidance.js.map +1 -1
- package/dist/core/auth-storage.d.ts +15 -9
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +159 -41
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/cache-stats.d.ts.map +1 -1
- package/dist/core/cache-stats.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/compaction/index.d.ts.map +1 -1
- package/dist/core/compaction/utils.d.ts.map +1 -1
- package/dist/core/compaction/utils.js.map +1 -1
- package/dist/core/defaults.d.ts.map +1 -1
- package/dist/core/diagnostics.d.ts.map +1 -1
- package/dist/core/event-bus.d.ts.map +1 -1
- package/dist/core/event-bus.js.map +1 -1
- package/dist/core/exec.d.ts.map +1 -1
- package/dist/core/exec.js.map +1 -1
- package/dist/core/experimental.d.ts.map +1 -1
- package/dist/core/experimental.js.map +1 -1
- package/dist/core/export-html/ansi-to-html.d.ts.map +1 -1
- package/dist/core/export-html/ansi-to-html.js.map +1 -1
- package/dist/core/export-html/index.d.ts.map +1 -1
- package/dist/core/export-html/index.js.map +1 -1
- package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
- package/dist/core/export-html/tool-renderer.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 +43 -20
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +3 -1
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +31 -28
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +28 -3
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/extensions/wrapper.d.ts.map +1 -1
- package/dist/core/extensions/wrapper.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts +10 -0
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +18 -19
- package/dist/core/footer-data-provider.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/index.d.ts.map +1 -1
- package/dist/core/keybindings.d.ts +157 -125
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +0 -1
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js.map +1 -1
- package/dist/core/model-config.d.ts +37 -13
- package/dist/core/model-config.d.ts.map +1 -1
- package/dist/core/model-config.js +4 -2
- 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 -11
- 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 +41 -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 +239 -91
- 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 +84 -16
- package/dist/core/models-store.js.map +1 -1
- package/dist/core/output-guard.d.ts.map +1 -1
- package/dist/core/output-guard.js.map +1 -1
- package/dist/core/package-manager.d.ts +4 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +76 -48
- 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 +25 -0
- package/dist/core/pi-manifest.js.map +1 -0
- package/dist/core/project-trust.d.ts.map +1 -1
- package/dist/core/project-trust.js.map +1 -1
- package/dist/core/prompt-templates.d.ts.map +1 -1
- package/dist/core/prompt-templates.js.map +1 -1
- package/dist/core/provider-attribution.d.ts.map +1 -1
- package/dist/core/provider-attribution.js.map +1 -1
- 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/radius.d.ts.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/resolve-config-value.d.ts.map +1 -1
- package/dist/core/resolve-config-value.js.map +1 -1
- package/dist/core/resource-loader.d.ts +15 -0
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +68 -51
- 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 +12 -10
- package/dist/core/runtime-credentials.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-cwd.d.ts.map +1 -1
- package/dist/core/session-cwd.js +0 -1
- package/dist/core/session-cwd.js.map +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +10 -12
- 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 +47 -33
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/source-info.d.ts.map +1 -1
- package/dist/core/source-info.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/telemetry.d.ts.map +1 -1
- package/dist/core/telemetry.js.map +1 -1
- package/dist/core/timings.d.ts.map +1 -1
- package/dist/core/timings.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +12 -10
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit-diff.d.ts.map +1 -1
- package/dist/core/tools/edit-diff.js.map +1 -1
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +4 -3
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
- package/dist/core/tools/file-mutation-queue.js.map +1 -1
- package/dist/core/tools/find.d.ts +3 -0
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +47 -20
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/output-accumulator.d.ts.map +1 -1
- package/dist/core/tools/output-accumulator.js +12 -18
- package/dist/core/tools/output-accumulator.js.map +1 -1
- package/dist/core/tools/path-utils.d.ts.map +1 -1
- package/dist/core/tools/path-utils.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +1 -1
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/render-utils.d.ts.map +1 -1
- package/dist/core/tools/render-utils.js.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
- package/dist/core/tools/truncate.d.ts.map +1 -1
- package/dist/core/tools/truncate.js.map +1 -1
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +0 -1
- package/dist/core/tools/write.js.map +1 -1
- package/dist/core/trust-manager.d.ts.map +1 -1
- package/dist/core/trust-manager.js +48 -10
- package/dist/core/trust-manager.js.map +1 -1
- package/dist/core/usage-totals.d.ts.map +1 -1
- package/dist/core/usage-totals.js.map +1 -1
- package/dist/extensions/biu/index.d.ts +19 -0
- package/dist/extensions/biu/index.d.ts.map +1 -0
- package/dist/extensions/biu/index.js +350 -0
- package/dist/extensions/biu/index.js.map +1 -0
- package/dist/extensions/biu/prompts.d.ts +26 -0
- package/dist/extensions/biu/prompts.d.ts.map +1 -0
- package/dist/extensions/biu/prompts.js +260 -0
- package/dist/extensions/biu/prompts.js.map +1 -0
- package/dist/extensions/biu/workspace.d.ts +122 -0
- package/dist/extensions/biu/workspace.d.ts.map +1 -0
- package/dist/extensions/biu/workspace.js +404 -0
- package/dist/extensions/biu/workspace.js.map +1 -0
- package/dist/extensions/deepwiki/client.d.ts.map +1 -1
- package/dist/extensions/deepwiki/client.js.map +1 -1
- package/dist/extensions/deepwiki/constants.d.ts.map +1 -1
- package/dist/extensions/deepwiki/constants.js.map +1 -1
- package/dist/extensions/deepwiki/contents.d.ts.map +1 -1
- package/dist/extensions/deepwiki/contents.js.map +1 -1
- package/dist/extensions/deepwiki/execute.d.ts.map +1 -1
- package/dist/extensions/deepwiki/execute.js.map +1 -1
- package/dist/extensions/deepwiki/http.d.ts.map +1 -1
- package/dist/extensions/deepwiki/http.js.map +1 -1
- package/dist/extensions/deepwiki/index.d.ts.map +1 -1
- package/dist/extensions/deepwiki/index.js.map +1 -1
- package/dist/extensions/deepwiki/render.d.ts.map +1 -1
- package/dist/extensions/deepwiki/render.js.map +1 -1
- package/dist/extensions/deepwiki/schema.d.ts +1 -1
- package/dist/extensions/deepwiki/schema.d.ts.map +1 -1
- package/dist/extensions/deepwiki/schema.js.map +1 -1
- package/dist/extensions/index.d.ts.map +1 -1
- package/dist/extensions/index.js +2 -2
- package/dist/extensions/index.js.map +1 -1
- package/dist/extensions/llama/client.d.ts.map +1 -1
- package/dist/extensions/llama/client.js +0 -2
- package/dist/extensions/llama/client.js.map +1 -1
- package/dist/extensions/llama/huggingface.d.ts.map +1 -1
- package/dist/extensions/llama/huggingface.js +0 -2
- package/dist/extensions/llama/huggingface.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 +22 -8
- package/dist/extensions/llama/provider.js.map +1 -1
- package/dist/extensions/llama/ui.d.ts.map +1 -1
- package/dist/extensions/llama/ui.js +12 -28
- package/dist/extensions/llama/ui.js.map +1 -1
- package/dist/extensions/question/constants.d.ts.map +1 -1
- package/dist/extensions/question/constants.js.map +1 -1
- package/dist/extensions/question/dialog-primitives.d.ts.map +1 -1
- package/dist/extensions/question/dialog-primitives.js.map +1 -1
- package/dist/extensions/question/dialog.d.ts.map +1 -1
- package/dist/extensions/question/dialog.js.map +1 -1
- package/dist/extensions/question/index.d.ts.map +1 -1
- package/dist/extensions/question/index.js.map +1 -1
- package/dist/extensions/question/limits.d.ts.map +1 -1
- package/dist/extensions/question/render-cache.d.ts.map +1 -1
- package/dist/extensions/question/render-cache.js +3 -4
- package/dist/extensions/question/render-cache.js.map +1 -1
- package/dist/extensions/question/render.d.ts.map +1 -1
- package/dist/extensions/question/render.js.map +1 -1
- package/dist/extensions/question/results.d.ts.map +1 -1
- package/dist/extensions/question/results.js.map +1 -1
- package/dist/extensions/question/schema.d.ts.map +1 -1
- package/dist/extensions/question/schema.js.map +1 -1
- package/dist/extensions/question/state.d.ts.map +1 -1
- package/dist/extensions/question/state.js.map +1 -1
- package/dist/extensions/question/types.d.ts.map +1 -1
- package/dist/extensions/rewind/anchor.d.ts.map +1 -1
- package/dist/extensions/rewind/anchor.js.map +1 -1
- package/dist/extensions/rewind/config.d.ts.map +1 -1
- package/dist/extensions/rewind/config.js.map +1 -1
- package/dist/extensions/rewind/engine.d.ts.map +1 -1
- package/dist/extensions/rewind/engine.js.map +1 -1
- package/dist/extensions/rewind/gc.d.ts.map +1 -1
- package/dist/extensions/rewind/gc.js.map +1 -1
- package/dist/extensions/rewind/index.d.ts.map +1 -1
- package/dist/extensions/rewind/index.js.map +1 -1
- package/dist/extensions/rewind/menu.d.ts.map +1 -1
- package/dist/extensions/rewind/menu.js.map +1 -1
- package/dist/extensions/rewind/paths.d.ts.map +1 -1
- package/dist/extensions/rewind/paths.js.map +1 -1
- package/dist/extensions/rewind/restore.d.ts.map +1 -1
- package/dist/extensions/rewind/restore.js.map +1 -1
- package/dist/extensions/rewind/snapshot.d.ts.map +1 -1
- package/dist/extensions/rewind/snapshot.js.map +1 -1
- package/dist/extensions/rewind/storage.d.ts.map +1 -1
- package/dist/extensions/rewind/storage.js.map +1 -1
- package/dist/extensions/rewind/text.d.ts.map +1 -1
- package/dist/extensions/rewind/text.js.map +1 -1
- package/dist/extensions/rewind/tool-path.d.ts.map +1 -1
- package/dist/extensions/rewind/tool-path.js.map +1 -1
- package/dist/extensions/router/constants.d.ts +3 -0
- package/dist/extensions/router/constants.d.ts.map +1 -1
- package/dist/extensions/router/constants.js +3 -0
- package/dist/extensions/router/constants.js.map +1 -1
- package/dist/extensions/router/dialog.d.ts +14 -7
- package/dist/extensions/router/dialog.d.ts.map +1 -1
- package/dist/extensions/router/dialog.js +70 -132
- package/dist/extensions/router/dialog.js.map +1 -1
- package/dist/extensions/router/index.d.ts.map +1 -1
- package/dist/extensions/router/index.js.map +1 -1
- package/dist/extensions/router/presets.d.ts +8 -3
- package/dist/extensions/router/presets.d.ts.map +1 -1
- package/dist/extensions/router/presets.js +33 -17
- package/dist/extensions/router/presets.js.map +1 -1
- package/dist/extensions/router/probe.d.ts.map +1 -1
- package/dist/extensions/router/probe.js.map +1 -1
- package/dist/extensions/router/register.d.ts +3 -3
- package/dist/extensions/router/register.d.ts.map +1 -1
- package/dist/extensions/router/register.js.map +1 -1
- package/dist/extensions/router/store.d.ts.map +1 -1
- package/dist/extensions/router/store.js.map +1 -1
- package/dist/extensions/router/stream.d.ts.map +1 -1
- package/dist/extensions/router/stream.js.map +1 -1
- package/dist/extensions/router/types.d.ts.map +1 -1
- package/dist/extensions/router/ui.d.ts +11 -2
- package/dist/extensions/router/ui.d.ts.map +1 -1
- package/dist/extensions/router/ui.js +316 -171
- package/dist/extensions/router/ui.js.map +1 -1
- package/dist/extensions/statusline/index.d.ts.map +1 -1
- package/dist/extensions/statusline/index.js +17 -9
- package/dist/extensions/statusline/index.js.map +1 -1
- package/dist/extensions/subagent/activity.d.ts.map +1 -1
- package/dist/extensions/subagent/activity.js.map +1 -1
- package/dist/extensions/subagent/agents.d.ts.map +1 -1
- package/dist/extensions/subagent/agents.js.map +1 -1
- package/dist/extensions/subagent/constants.d.ts.map +1 -1
- package/dist/extensions/subagent/index.d.ts +3 -0
- package/dist/extensions/subagent/index.d.ts.map +1 -1
- package/dist/extensions/subagent/index.js +83 -12
- package/dist/extensions/subagent/index.js.map +1 -1
- package/dist/extensions/subagent/picker.d.ts.map +1 -1
- package/dist/extensions/subagent/picker.js +2 -9
- package/dist/extensions/subagent/picker.js.map +1 -1
- package/dist/extensions/subagent/render.d.ts.map +1 -1
- package/dist/extensions/subagent/render.js +33 -9
- package/dist/extensions/subagent/render.js.map +1 -1
- package/dist/extensions/subagent/resolve.d.ts.map +1 -1
- package/dist/extensions/subagent/resolve.js.map +1 -1
- package/dist/extensions/subagent/retry.d.ts.map +1 -1
- package/dist/extensions/subagent/retry.js.map +1 -1
- package/dist/extensions/subagent/runner.d.ts +2 -1
- package/dist/extensions/subagent/runner.d.ts.map +1 -1
- package/dist/extensions/subagent/runner.js +10 -12
- package/dist/extensions/subagent/runner.js.map +1 -1
- package/dist/extensions/subagent/schema.d.ts.map +1 -1
- package/dist/extensions/subagent/schema.js.map +1 -1
- package/dist/extensions/subagent/sdk-runner.d.ts.map +1 -1
- package/dist/extensions/subagent/sdk-runner.js +41 -1
- package/dist/extensions/subagent/sdk-runner.js.map +1 -1
- package/dist/extensions/subagent/settings.d.ts.map +1 -1
- package/dist/extensions/subagent/settings.js +46 -36
- package/dist/extensions/subagent/settings.js.map +1 -1
- package/dist/extensions/subagent/types.d.ts +0 -1
- package/dist/extensions/subagent/types.d.ts.map +1 -1
- package/dist/extensions/subagent/types.js.map +1 -1
- package/dist/extensions/todo/constants.d.ts.map +1 -1
- package/dist/extensions/todo/constants.js.map +1 -1
- package/dist/extensions/todo/index.d.ts.map +1 -1
- package/dist/extensions/todo/index.js.map +1 -1
- package/dist/extensions/todo/overlay.d.ts.map +1 -1
- package/dist/extensions/todo/overlay.js +6 -10
- package/dist/extensions/todo/overlay.js.map +1 -1
- package/dist/extensions/todo/schema.d.ts +2 -2
- package/dist/extensions/todo/schema.d.ts.map +1 -1
- package/dist/extensions/todo/state.d.ts.map +1 -1
- package/dist/extensions/todo/state.js.map +1 -1
- package/dist/extensions/todo/view.d.ts.map +1 -1
- package/dist/extensions/todo/view.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +57 -5
- package/dist/main.js.map +1 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js.map +1 -1
- package/dist/modes/index.d.ts +1 -0
- package/dist/modes/index.d.ts.map +1 -1
- package/dist/modes/index.js.map +1 -1
- package/dist/modes/interactive/components/armin.d.ts.map +1 -1
- package/dist/modes/interactive/components/armin.js +6 -10
- package/dist/modes/interactive/components/armin.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 -11
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +4 -10
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.js +0 -3
- package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.js +1 -3
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.js +1 -3
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/config-selector.js +5 -22
- package/dist/modes/interactive/components/config-selector.js.map +1 -1
- package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -1
- package/dist/modes/interactive/components/countdown-timer.js +1 -7
- package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js +8 -8
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-entry.js +1 -4
- package/dist/modes/interactive/components/custom-entry.js.map +1 -1
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-message.js +1 -7
- package/dist/modes/interactive/components/custom-message.js.map +1 -1
- package/dist/modes/interactive/components/daxnuts.d.ts.map +1 -1
- package/dist/modes/interactive/components/daxnuts.js +6 -8
- package/dist/modes/interactive/components/daxnuts.js.map +1 -1
- package/dist/modes/interactive/components/diff.d.ts.map +1 -1
- package/dist/modes/interactive/components/diff.js.map +1 -1
- package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
- package/dist/modes/interactive/components/dynamic-border.js +0 -1
- package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
- package/dist/modes/interactive/components/earendil-announcement.d.ts.map +1 -1
- package/dist/modes/interactive/components/earendil-announcement.js.map +1 -1
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-editor.js +1 -7
- package/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-input.js +2 -8
- package/dist/modes/interactive/components/extension-input.js.map +1 -1
- package/dist/modes/interactive/components/extension-selector.d.ts +1 -1
- package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-selector.js +1 -9
- package/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -1
- package/dist/modes/interactive/components/first-time-setup.js +2 -4
- package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +2 -4
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +3 -9
- package/dist/modes/interactive/components/login-dialog.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 +32 -30
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.js +3 -11
- package/dist/modes/interactive/components/oauth-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 +34 -13
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
- package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +35 -60
- package/dist/modes/interactive/components/session-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 -14
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/show-images-selector.js +0 -1
- package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.js +1 -3
- package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
- package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -1
- package/dist/modes/interactive/components/status-indicator.js +0 -2
- package/dist/modes/interactive/components/status-indicator.js.map +1 -1
- package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/theme-selector.js +0 -2
- package/dist/modes/interactive/components/theme-selector.js.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.js +0 -1
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +18 -36
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tool-group.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-group.js +2 -3
- package/dist/modes/interactive/components/tool-group.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js +19 -39
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/components/trust-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/trust-selector.js +0 -6
- package/dist/modes/interactive/components/trust-selector.js.map +1 -1
- package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message-selector.js +3 -6
- package/dist/modes/interactive/components/user-message-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 +8 -5
- package/dist/modes/interactive/components/user-message.js.map +1 -1
- package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -1
- package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
- package/dist/modes/interactive/external-editor.d.ts.map +1 -1
- package/dist/modes/interactive/external-editor.js +40 -3
- package/dist/modes/interactive/external-editor.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +46 -4
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +538 -275
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/model-search.d.ts.map +1 -1
- package/dist/modes/interactive/model-search.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 +11 -8
- 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 +4 -4
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +13 -9
- 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/jsonl.d.ts.map +1 -1
- package/dist/modes/rpc/jsonl.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +5 -4
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +7 -8
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +17 -3
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts.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 +1 -0
- package/dist/rpc-entry.js.map +1 -1
- 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/ansi.d.ts.map +1 -1
- package/dist/utils/ansi.js.map +1 -1
- package/dist/utils/changelog.d.ts.map +1 -1
- package/dist/utils/changelog.js.map +1 -1
- package/dist/utils/child-process.d.ts.map +1 -1
- package/dist/utils/child-process.js.map +1 -1
- package/dist/utils/clipboard-image.d.ts.map +1 -1
- package/dist/utils/clipboard-image.js.map +1 -1
- package/dist/utils/clipboard-native.d.ts.map +1 -1
- package/dist/utils/clipboard-native.js.map +1 -1
- 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/coalescing-terminal.d.ts +1 -0
- package/dist/utils/coalescing-terminal.d.ts.map +1 -1
- package/dist/utils/coalescing-terminal.js +16 -8
- package/dist/utils/coalescing-terminal.js.map +1 -1
- package/dist/utils/deprecation.d.ts.map +1 -1
- package/dist/utils/deprecation.js.map +1 -1
- package/dist/utils/exif-orientation.d.ts.map +1 -1
- package/dist/utils/exif-orientation.js.map +1 -1
- package/dist/utils/frontmatter.d.ts.map +1 -1
- package/dist/utils/frontmatter.js.map +1 -1
- package/dist/utils/fs-watch.d.ts.map +1 -1
- package/dist/utils/fs-watch.js.map +1 -1
- package/dist/utils/git.d.ts.map +1 -1
- package/dist/utils/git.js.map +1 -1
- package/dist/utils/html.d.ts.map +1 -1
- package/dist/utils/html.js.map +1 -1
- package/dist/utils/image-convert.d.ts.map +1 -1
- package/dist/utils/image-convert.js.map +1 -1
- package/dist/utils/image-process.d.ts.map +1 -1
- package/dist/utils/image-process.js.map +1 -1
- package/dist/utils/image-resize-core.d.ts.map +1 -1
- package/dist/utils/image-resize-core.js.map +1 -1
- package/dist/utils/image-resize-worker.d.ts.map +1 -1
- package/dist/utils/image-resize-worker.js.map +1 -1
- package/dist/utils/image-resize.d.ts.map +1 -1
- package/dist/utils/image-resize.js.map +1 -1
- package/dist/utils/json.d.ts.map +1 -1
- package/dist/utils/json.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/mime.d.ts.map +1 -1
- package/dist/utils/mime.js.map +1 -1
- package/dist/utils/open-browser.d.ts.map +1 -1
- package/dist/utils/open-browser.js.map +1 -1
- package/dist/utils/paths.d.ts +5 -3
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +25 -4
- package/dist/utils/paths.js.map +1 -1
- package/dist/utils/photon.d.ts.map +1 -1
- package/dist/utils/photon.js.map +1 -1
- package/dist/utils/pi-user-agent.d.ts.map +1 -1
- package/dist/utils/pi-user-agent.js.map +1 -1
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js.map +1 -1
- package/dist/utils/sleep.d.ts.map +1 -1
- package/dist/utils/sleep.js.map +1 -1
- package/dist/utils/syntax-highlight.d.ts.map +1 -1
- package/dist/utils/syntax-highlight.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 +4 -6
- 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 +20 -2
- package/dist/utils/version-check.js.map +1 -1
- package/dist/utils/windows-self-update.d.ts.map +1 -1
- package/dist/utils/windows-self-update.js.map +1 -1
- package/docs/bundled/README.md +14 -16
- package/docs/bundled/extensions/biu.md +63 -0
- package/docs/bundled/extensions/router.md +20 -14
- package/docs/bundled/extensions/statusline.md +7 -5
- package/docs/bundled/themes.md +1 -1
- package/docs/compaction.md +25 -30
- package/docs/custom-provider.md +303 -467
- package/docs/development.md +83 -0
- package/docs/docs.json +6 -10
- package/docs/extensions.md +139 -119
- package/docs/index.md +18 -74
- package/docs/json.md +40 -15
- package/docs/keybindings.md +38 -10
- package/docs/models.md +210 -150
- package/docs/providers.md +3 -1
- package/docs/quickstart.md +5 -3
- package/docs/rpc.md +177 -134
- package/docs/sdk.md +165 -178
- package/docs/security.md +2 -2
- package/docs/session-format.md +139 -119
- package/docs/settings.md +4 -1
- package/docs/skills.md +0 -1
- package/docs/themes.md +5 -3
- package/docs/tui.md +411 -549
- package/docs/usage.md +11 -11
- package/examples/README.md +6 -1
- package/examples/extensions/README.md +13 -33
- package/examples/extensions/custom-compaction.ts +1 -16
- package/examples/extensions/custom-provider-anthropic/index.ts +11 -4
- package/examples/extensions/custom-provider-gitlab-duo/index.ts +2 -1
- package/examples/extensions/doom-overlay/wad-finder.ts +7 -3
- package/examples/extensions/handoff.ts +2 -11
- package/examples/extensions/qna.ts +3 -7
- package/examples/extensions/summarize.ts +8 -18
- package/examples/extensions/truncated-tool.ts +2 -2
- package/examples/rpc-extension-ui.ts +11 -2
- package/examples/sdk/02-custom-model.ts +1 -2
- package/examples/sdk/09-api-keys-and-oauth.ts +1 -1
- package/examples/sdk/12-full-control.ts +3 -1
- package/examples/sdk/README.md +1 -0
- package/npm-shrinkwrap.json +199 -270
- package/package.json +16 -9
- package/dist/extensions/plan/constants.d.ts +0 -68
- package/dist/extensions/plan/constants.d.ts.map +0 -1
- package/dist/extensions/plan/constants.js +0 -100
- package/dist/extensions/plan/constants.js.map +0 -1
- package/dist/extensions/plan/index.d.ts +0 -30
- package/dist/extensions/plan/index.d.ts.map +0 -1
- package/dist/extensions/plan/index.js +0 -429
- package/dist/extensions/plan/index.js.map +0 -1
- package/dist/extensions/plan/schema.d.ts +0 -20
- package/dist/extensions/plan/schema.d.ts.map +0 -1
- package/dist/extensions/plan/schema.js +0 -13
- package/dist/extensions/plan/schema.js.map +0 -1
- package/dist/extensions/plan/state.d.ts +0 -38
- package/dist/extensions/plan/state.d.ts.map +0 -1
- package/dist/extensions/plan/state.js +0 -96
- package/dist/extensions/plan/state.js.map +0 -1
- package/dist/extensions/plan/storage.d.ts +0 -26
- package/dist/extensions/plan/storage.d.ts.map +0 -1
- package/dist/extensions/plan/storage.js +0 -83
- package/dist/extensions/plan/storage.js.map +0 -1
- package/dist/extensions/plan/view.d.ts +0 -44
- package/dist/extensions/plan/view.d.ts.map +0 -1
- package/dist/extensions/plan/view.js +0 -149
- package/dist/extensions/plan/view.js.map +0 -1
- package/docs/bundled/extensions/README.md +0 -19
- package/docs/bundled/extensions/plan.md +0 -34
- package/examples/extensions/plan-mode/README.md +0 -66
- package/examples/extensions/plan-mode/index.ts +0 -390
- package/examples/extensions/plan-mode/utils.ts +0 -168
|
@@ -6,7 +6,8 @@ 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, 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
13
|
import { APP_NAME, APP_TITLE, CONFIG_DIR_NAME, getAgentDir, getAuthPath, getDebugLogPath, getDocsPath, getShareViewerUrl, VERSION, } from "../../config.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,7 @@ import { copyToClipboard, readClipboardText } from "../../utils/clipboard.js";
|
|
|
29
31
|
import { extensionForImageMimeType, readClipboardImage } from "../../utils/clipboard-image.js";
|
|
30
32
|
import { CoalescingTerminal } from "../../utils/coalescing-terminal.js";
|
|
31
33
|
import { parseGitUrl } from "../../utils/git.js";
|
|
34
|
+
import { openBrowser } from "../../utils/open-browser.js";
|
|
32
35
|
import { getCwdRelativePath } from "../../utils/paths.js";
|
|
33
36
|
import { killTrackedDetachedChildren } from "../../utils/shell.js";
|
|
34
37
|
import { ensureTool } from "../../utils/tools-manager.js";
|
|
@@ -51,6 +54,7 @@ import { ExtensionSelectorComponent } from "./components/extension-selector.js";
|
|
|
51
54
|
import { FooterComponent, formatTokens } from "./components/footer.js";
|
|
52
55
|
import { formatKeyText, keyDisplayText, keyHint, keyText, rawKeyHint } from "./components/keybinding-hints.js";
|
|
53
56
|
import { LoginDialogComponent } from "./components/login-dialog.js";
|
|
57
|
+
import { createMermaidMarkdownTransformer } from "./components/mermaid.js";
|
|
54
58
|
import { ModelSelectorComponent } from "./components/model-selector.js";
|
|
55
59
|
import { formatAuthSelectorProviderType, OAuthSelectorComponent, } from "./components/oauth-selector.js";
|
|
56
60
|
import { ScopedModelsSelectorComponent } from "./components/scoped-models-selector.js";
|
|
@@ -72,8 +76,6 @@ function isExpandable(obj) {
|
|
|
72
76
|
return typeof obj === "object" && obj !== null && "setExpanded" in obj && typeof obj.setExpanded === "function";
|
|
73
77
|
}
|
|
74
78
|
class ExpandableText extends Text {
|
|
75
|
-
getCollapsedText;
|
|
76
|
-
getExpandedText;
|
|
77
79
|
constructor(getCollapsedText, getExpandedText, expanded = false, paddingX = 0, paddingY = 0) {
|
|
78
80
|
super(expanded ? getExpandedText() : getCollapsedText(), paddingX, paddingY);
|
|
79
81
|
this.getCollapsedText = getCollapsedText;
|
|
@@ -161,98 +163,39 @@ function formatLoginProviderCompletionDescription(provider) {
|
|
|
161
163
|
const authTypes = provider.authTypes.map(formatAuthSelectorProviderType).join("/");
|
|
162
164
|
return provider.name === provider.id ? authTypes : `${provider.name} · ${authTypes}`;
|
|
163
165
|
}
|
|
166
|
+
/** Composition root for selecting the interactive terminal renderer. */
|
|
167
|
+
export function createInteractiveTui(options) {
|
|
168
|
+
const terminal = options.terminal ?? new ProcessTerminal();
|
|
169
|
+
if (options.tuiMode === "fullscreen") {
|
|
170
|
+
return new TuiAltScreen(terminal, options.showHardwareCursor, options.logDirectory, { openUrl: openBrowser });
|
|
171
|
+
}
|
|
172
|
+
return new TuiMainScreen(terminal, options.showHardwareCursor, options.logDirectory);
|
|
173
|
+
}
|
|
174
|
+
/** Stable reference for components while InteractiveMode replaces the active renderer. */
|
|
175
|
+
export function createInteractiveTuiReference(getTui) {
|
|
176
|
+
return new Proxy({}, {
|
|
177
|
+
get: (_target, property) => {
|
|
178
|
+
const tui = getTui();
|
|
179
|
+
const value = Reflect.get(tui, property, tui);
|
|
180
|
+
if (typeof value !== "function")
|
|
181
|
+
return value;
|
|
182
|
+
return (...args) => {
|
|
183
|
+
const tui = getTui();
|
|
184
|
+
const method = Reflect.get(tui, property, tui);
|
|
185
|
+
if (typeof method !== "function")
|
|
186
|
+
throw new TypeError(`TUI property ${String(property)} is not callable`);
|
|
187
|
+
return Reflect.apply(method, tui, args);
|
|
188
|
+
};
|
|
189
|
+
},
|
|
190
|
+
set: (_target, property, value) => {
|
|
191
|
+
const tui = getTui();
|
|
192
|
+
return Reflect.set(tui, property, value, tui);
|
|
193
|
+
},
|
|
194
|
+
has: (_target, property) => Reflect.has(getTui(), property),
|
|
195
|
+
getPrototypeOf: () => Reflect.getPrototypeOf(getTui()),
|
|
196
|
+
});
|
|
197
|
+
}
|
|
164
198
|
export class InteractiveMode {
|
|
165
|
-
runtimeHost;
|
|
166
|
-
ui;
|
|
167
|
-
coalescingTerminal;
|
|
168
|
-
agentRunActive = false;
|
|
169
|
-
loadedResourcesContainer;
|
|
170
|
-
chatContainer;
|
|
171
|
-
pendingMessagesContainer;
|
|
172
|
-
statusContainer;
|
|
173
|
-
defaultEditor;
|
|
174
|
-
editor;
|
|
175
|
-
editorComponentFactory;
|
|
176
|
-
autocompleteProvider;
|
|
177
|
-
autocompleteProviderWrappers = [];
|
|
178
|
-
fdPath;
|
|
179
|
-
editorContainer;
|
|
180
|
-
footer;
|
|
181
|
-
footerDataProvider;
|
|
182
|
-
// Stored so the same manager can be injected into custom editors, selectors, and extension UI.
|
|
183
|
-
keybindings;
|
|
184
|
-
version;
|
|
185
|
-
isInitialized = false;
|
|
186
|
-
onInputCallback;
|
|
187
|
-
pendingUserInputs = [];
|
|
188
|
-
activeStatusIndicator = undefined;
|
|
189
|
-
activeSelector = null;
|
|
190
|
-
activeSelectorCleanup = null;
|
|
191
|
-
idleStatus = new IdleStatus();
|
|
192
|
-
workingMessage = undefined;
|
|
193
|
-
workingVisible = true;
|
|
194
|
-
workingIndicatorOptions = undefined;
|
|
195
|
-
defaultWorkingMessage = "Working...";
|
|
196
|
-
defaultHiddenThinkingLabel = "Thinking...";
|
|
197
|
-
hiddenThinkingLabel = this.defaultHiddenThinkingLabel;
|
|
198
|
-
lastSigintTime = 0;
|
|
199
|
-
lastEscapeTime = 0;
|
|
200
|
-
changelogMarkdown = undefined;
|
|
201
|
-
startupNoticesShown = false;
|
|
202
|
-
anthropicSubscriptionWarningShown = false;
|
|
203
|
-
// Status line tracking (for mutating immediately-sequential status updates)
|
|
204
|
-
lastStatusSpacer = undefined;
|
|
205
|
-
lastStatusText = undefined;
|
|
206
|
-
// Streaming message tracking
|
|
207
|
-
streamingComponent = undefined;
|
|
208
|
-
streamingMessage = undefined;
|
|
209
|
-
// Tool execution tracking: toolCallId -> component
|
|
210
|
-
pendingTools = new Map();
|
|
211
|
-
// Tool output expansion state
|
|
212
|
-
toolOutputExpanded = false;
|
|
213
|
-
// Thinking block visibility state
|
|
214
|
-
hideThinkingBlock = false;
|
|
215
|
-
outputPad = 1;
|
|
216
|
-
// Skill commands: command name -> skill file path
|
|
217
|
-
skillCommands = new Map();
|
|
218
|
-
// Agent subscription unsubscribe function
|
|
219
|
-
unsubscribe;
|
|
220
|
-
signalCleanupHandlers = [];
|
|
221
|
-
// Track if editor is in bash mode (text starts with !)
|
|
222
|
-
isBashMode = false;
|
|
223
|
-
// Track current bash execution component
|
|
224
|
-
bashComponent = undefined;
|
|
225
|
-
// Track pending bash components (shown in pending area, moved to chat on submit)
|
|
226
|
-
pendingBashComponents = [];
|
|
227
|
-
// Auto-compaction state
|
|
228
|
-
autoCompactionEscapeHandler;
|
|
229
|
-
// Auto-retry state
|
|
230
|
-
retryEscapeHandler;
|
|
231
|
-
// Messages queued while compaction is running
|
|
232
|
-
compactionQueuedMessages = [];
|
|
233
|
-
// Shutdown state
|
|
234
|
-
shutdownRequested = false;
|
|
235
|
-
// Extension UI state
|
|
236
|
-
extensionSelector = undefined;
|
|
237
|
-
extensionInput = undefined;
|
|
238
|
-
extensionEditor = undefined;
|
|
239
|
-
extensionTerminalInputUnsubscribers = new Set();
|
|
240
|
-
// Extension widgets (components rendered above/below the editor)
|
|
241
|
-
extensionWidgetsAbove = new Map();
|
|
242
|
-
extensionWidgetsBelow = new Map();
|
|
243
|
-
widgetContainerAbove;
|
|
244
|
-
widgetContainerBelow;
|
|
245
|
-
// Custom footer from extension (undefined = use built-in footer)
|
|
246
|
-
customFooter = undefined;
|
|
247
|
-
// Header container that holds the built-in or custom header
|
|
248
|
-
headerContainer;
|
|
249
|
-
// Built-in header (logo + keybinding hints + changelog)
|
|
250
|
-
builtInHeader = undefined;
|
|
251
|
-
// Custom header from extension (undefined = use built-in header)
|
|
252
|
-
customHeader = undefined;
|
|
253
|
-
options;
|
|
254
|
-
autoTrustOnReloadCwd;
|
|
255
|
-
themeController;
|
|
256
199
|
// Convenience accessors
|
|
257
200
|
get session() {
|
|
258
201
|
return this.runtimeHost.session;
|
|
@@ -267,8 +210,85 @@ export class InteractiveMode {
|
|
|
267
210
|
return this.session.settingsManager;
|
|
268
211
|
}
|
|
269
212
|
constructor(runtimeHost, options = {}) {
|
|
213
|
+
// Input listeners live on the TUI renderer instance, which switchTuiMode
|
|
214
|
+
// replaces; this pair tracks the scrollback-preservation listener so it
|
|
215
|
+
// can be unsubscribed from the outgoing renderer and re-registered on the
|
|
216
|
+
// incoming one without duplicates.
|
|
217
|
+
this.scrollbackPreservationInputHandler = () => {
|
|
218
|
+
if (!this.agentRunActive)
|
|
219
|
+
this.coalescingTerminal.setScrollbackPreservation(false);
|
|
220
|
+
return undefined;
|
|
221
|
+
};
|
|
222
|
+
this.agentRunActive = false;
|
|
223
|
+
this.autocompleteProviderWrappers = [];
|
|
224
|
+
this.isInitialized = false;
|
|
225
|
+
this.pendingUserInputs = [];
|
|
226
|
+
this.activeStatusIndicator = undefined;
|
|
227
|
+
this.idleStatus = new IdleStatus();
|
|
228
|
+
this.workingMessage = undefined;
|
|
229
|
+
this.workingVisible = true;
|
|
230
|
+
this.workingIndicatorOptions = undefined;
|
|
231
|
+
this.defaultWorkingMessage = "Working...";
|
|
232
|
+
this.defaultHiddenThinkingLabel = "Thinking...";
|
|
233
|
+
this.hiddenThinkingLabel = this.defaultHiddenThinkingLabel;
|
|
234
|
+
this.lastSigintTime = 0;
|
|
235
|
+
this.lastEscapeTime = 0;
|
|
236
|
+
this.changelogMarkdown = undefined;
|
|
237
|
+
this.startupNoticesShown = false;
|
|
238
|
+
this.anthropicSubscriptionWarningShown = false;
|
|
239
|
+
// Status line tracking (for mutating immediately-sequential status updates)
|
|
240
|
+
this.lastStatusSpacer = undefined;
|
|
241
|
+
this.lastStatusText = undefined;
|
|
242
|
+
// Streaming message tracking
|
|
243
|
+
this.streamingComponent = undefined;
|
|
244
|
+
this.streamingMessage = undefined;
|
|
245
|
+
// Tool execution tracking: toolCallId -> component
|
|
246
|
+
this.pendingTools = new Map();
|
|
247
|
+
// Tool output expansion state
|
|
248
|
+
this.toolOutputExpanded = false;
|
|
249
|
+
// Thinking block visibility state
|
|
250
|
+
this.hideThinkingBlock = false;
|
|
251
|
+
this.outputPad = 1;
|
|
252
|
+
this.mermaidMarkdownTransformer = createMermaidMarkdownTransformer({
|
|
253
|
+
getMode: () => this.settingsManager.getMermaidRenderingMode(),
|
|
254
|
+
theme,
|
|
255
|
+
});
|
|
256
|
+
// Skill commands: command name -> skill file path
|
|
257
|
+
this.skillCommands = new Map();
|
|
258
|
+
this.signalCleanupHandlers = [];
|
|
259
|
+
// Track if editor is in bash mode (text starts with !)
|
|
260
|
+
this.isBashMode = false;
|
|
261
|
+
// Track current bash execution component
|
|
262
|
+
this.bashComponent = undefined;
|
|
263
|
+
// Track pending bash components (shown in pending area, moved to chat on submit)
|
|
264
|
+
this.pendingBashComponents = [];
|
|
265
|
+
// Messages queued while compaction is running
|
|
266
|
+
this.compactionQueuedMessages = [];
|
|
267
|
+
// Shutdown state
|
|
268
|
+
this.shutdownRequested = false;
|
|
269
|
+
// Extension UI state
|
|
270
|
+
this.extensionSelector = undefined;
|
|
271
|
+
this.extensionInput = undefined;
|
|
272
|
+
this.extensionEditor = undefined;
|
|
273
|
+
this.extensionTerminalInputSubscriptions = new Set();
|
|
274
|
+
// Extension widgets (components rendered above/below the editor)
|
|
275
|
+
this.extensionWidgetsAbove = new Map();
|
|
276
|
+
this.extensionWidgetsBelow = new Map();
|
|
277
|
+
// Custom footer from extension (undefined = use built-in footer)
|
|
278
|
+
this.customFooter = undefined;
|
|
279
|
+
// Built-in header (logo + keybinding hints + changelog)
|
|
280
|
+
this.builtInHeader = undefined;
|
|
281
|
+
// Custom header from extension (undefined = use built-in header)
|
|
282
|
+
this.customHeader = undefined;
|
|
283
|
+
/**
|
|
284
|
+
* Gracefully shutdown the agent.
|
|
285
|
+
* Stops the TUI before emitting shutdown events so extension UI cleanup cannot
|
|
286
|
+
* repaint the final frame while the process is exiting.
|
|
287
|
+
*/
|
|
288
|
+
this.isShuttingDown = false;
|
|
270
289
|
this.runtimeHost = runtimeHost;
|
|
271
|
-
|
|
290
|
+
const tuiMode = options.tuiMode ?? this.settingsManager.getTuiMode();
|
|
291
|
+
this.options = { ...options, tuiMode };
|
|
272
292
|
this.autoTrustOnReloadCwd = options.autoTrustOnReloadCwd;
|
|
273
293
|
this.runtimeHost.setBeforeSessionInvalidate(() => {
|
|
274
294
|
this.resetExtensionUI();
|
|
@@ -279,7 +299,13 @@ export class InteractiveMode {
|
|
|
279
299
|
this.version = VERSION;
|
|
280
300
|
const terminal = new CoalescingTerminal();
|
|
281
301
|
this.coalescingTerminal = terminal;
|
|
282
|
-
this.
|
|
302
|
+
this.renderer = createInteractiveTui({
|
|
303
|
+
tuiMode,
|
|
304
|
+
showHardwareCursor: this.settingsManager.getShowHardwareCursor(),
|
|
305
|
+
logDirectory: getAgentDir(),
|
|
306
|
+
terminal,
|
|
307
|
+
});
|
|
308
|
+
this.ui = createInteractiveTuiReference(() => this.renderer);
|
|
283
309
|
// Lets full-redraw rewrites scroll grown content into scrollback
|
|
284
310
|
// instead of dropping the lines pushed above the screen.
|
|
285
311
|
// previousViewportTop is TS-private but a plain runtime field, and
|
|
@@ -291,15 +317,17 @@ export class InteractiveMode {
|
|
|
291
317
|
// next input after the run settles: post-run reflow frames must not
|
|
292
318
|
// yank a reader who is still scrolled up, but once the user acts they
|
|
293
319
|
// are back at the bottom and upstream's clean wipe-and-replay wins.
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
return undefined;
|
|
298
|
-
});
|
|
320
|
+
// The listener is registered on the initial renderer and rebound by
|
|
321
|
+
// switchTuiMode whenever the renderer is replaced.
|
|
322
|
+
this.scrollbackPreservationInputUnsubscribe = this.ui.addInputListener(this.scrollbackPreservationInputHandler);
|
|
299
323
|
this.ui.setClearOnShrink(this.settingsManager.getClearOnShrink());
|
|
300
324
|
this.headerContainer = new Container();
|
|
301
325
|
this.loadedResourcesContainer = new Container();
|
|
302
326
|
this.chatContainer = new Container();
|
|
327
|
+
this.documentContainer = new Container();
|
|
328
|
+
this.documentContainer.addChild(this.headerContainer);
|
|
329
|
+
this.documentContainer.addChild(this.loadedResourcesContainer);
|
|
330
|
+
this.documentContainer.addChild(this.chatContainer);
|
|
303
331
|
this.pendingMessagesContainer = new Container();
|
|
304
332
|
this.statusContainer = new Container();
|
|
305
333
|
this.widgetContainerAbove = new Container();
|
|
@@ -318,6 +346,8 @@ export class InteractiveMode {
|
|
|
318
346
|
this.footerDataProvider = new FooterDataProvider(this.sessionManager.getCwd());
|
|
319
347
|
this.footer = new FooterComponent(this.session, this.footerDataProvider);
|
|
320
348
|
this.footer.setAutoCompactEnabled(this.session.autoCompactionEnabled);
|
|
349
|
+
this.footerContainer = new Container();
|
|
350
|
+
this.footerContainer.addChild(this.footer);
|
|
321
351
|
// Load hide thinking block setting
|
|
322
352
|
this.hideThinkingBlock = this.settingsManager.getHideThinkingBlock();
|
|
323
353
|
this.outputPad = this.settingsManager.getOutputPad();
|
|
@@ -373,11 +403,10 @@ export class InteractiveMode {
|
|
|
373
403
|
}));
|
|
374
404
|
const modelCommand = slashCommands.find((command) => command.name === "model");
|
|
375
405
|
if (modelCommand) {
|
|
376
|
-
modelCommand.getArgumentCompletions =
|
|
377
|
-
// Get available models (scoped or from registry)
|
|
406
|
+
modelCommand.getArgumentCompletions = (prefix) => {
|
|
378
407
|
const models = this.session.scopedModels.length > 0
|
|
379
408
|
? this.session.scopedModels.map((s) => s.model)
|
|
380
|
-
:
|
|
409
|
+
: this.session.modelRuntime.getAvailableSnapshot();
|
|
381
410
|
if (models.length === 0)
|
|
382
411
|
return null;
|
|
383
412
|
// Create items with provider/id format
|
|
@@ -478,6 +507,75 @@ export class InteractiveMode {
|
|
|
478
507
|
}
|
|
479
508
|
this.chatContainer.addChild(new DynamicBorder());
|
|
480
509
|
}
|
|
510
|
+
mountInteractiveTui(tui, components) {
|
|
511
|
+
for (const component of components)
|
|
512
|
+
tui.addChild(component);
|
|
513
|
+
if (TuiLayouts.isViewportTUI(tui)) {
|
|
514
|
+
if (!this.fullscreenLayoutRoot)
|
|
515
|
+
throw new Error("Fullscreen layout is not initialized");
|
|
516
|
+
tui.setLayoutRoot(this.fullscreenLayoutRoot);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
stopInteractiveTui() {
|
|
520
|
+
if (this.renderer.mode === "fullscreen") {
|
|
521
|
+
while (this.renderer.hasOverlayEntries)
|
|
522
|
+
this.renderer.hideOverlay();
|
|
523
|
+
this.switchTuiMode("regular", false, false);
|
|
524
|
+
this.renderer.renderNow();
|
|
525
|
+
}
|
|
526
|
+
this.ui.stop();
|
|
527
|
+
}
|
|
528
|
+
switchTuiMode(mode, restoreProgress = true, startRenderer = true) {
|
|
529
|
+
const previousUi = this.renderer;
|
|
530
|
+
if (mode === previousUi.mode)
|
|
531
|
+
return true;
|
|
532
|
+
if (previousUi.hasOverlayEntries)
|
|
533
|
+
return false;
|
|
534
|
+
const components = [...previousUi.children];
|
|
535
|
+
const focus = previousUi.getFocusedComponent();
|
|
536
|
+
const terminal = previousUi.terminal;
|
|
537
|
+
const showHardwareCursor = previousUi.getShowHardwareCursor();
|
|
538
|
+
const clearOnShrink = previousUi.getClearOnShrink();
|
|
539
|
+
const onDebug = previousUi.onDebug;
|
|
540
|
+
if (previousUi instanceof TuiMainScreen) {
|
|
541
|
+
this.mainScreenRenderState = previousUi.captureRenderState();
|
|
542
|
+
}
|
|
543
|
+
previousUi.stop({ preserveScreen: true });
|
|
544
|
+
previousUi.setFocus(null);
|
|
545
|
+
previousUi.clear();
|
|
546
|
+
if (TuiLayouts.isViewportTUI(previousUi))
|
|
547
|
+
previousUi.setLayoutRoot(undefined);
|
|
548
|
+
const nextUi = createInteractiveTui({
|
|
549
|
+
tuiMode: mode,
|
|
550
|
+
showHardwareCursor,
|
|
551
|
+
logDirectory: getAgentDir(),
|
|
552
|
+
terminal,
|
|
553
|
+
});
|
|
554
|
+
nextUi.setClearOnShrink(clearOnShrink);
|
|
555
|
+
nextUi.onDebug = onDebug;
|
|
556
|
+
if (nextUi instanceof TuiMainScreen && this.mainScreenRenderState) {
|
|
557
|
+
nextUi.restoreRenderState(this.mainScreenRenderState);
|
|
558
|
+
}
|
|
559
|
+
this.renderer = nextUi;
|
|
560
|
+
// Renderers own their input-listener sets; move the preservation
|
|
561
|
+
// listener onto the incoming renderer before anything else touches it.
|
|
562
|
+
this.rebindScrollbackPreservationInputListener();
|
|
563
|
+
this.options.tuiMode = mode;
|
|
564
|
+
this.mountInteractiveTui(nextUi, components);
|
|
565
|
+
nextUi.invalidate();
|
|
566
|
+
nextUi.setFocus(focus);
|
|
567
|
+
if (!startRenderer)
|
|
568
|
+
return true;
|
|
569
|
+
nextUi.start();
|
|
570
|
+
this.themeController.rebindTui();
|
|
571
|
+
this.rebindExtensionTerminalInputListeners();
|
|
572
|
+
if (restoreProgress &&
|
|
573
|
+
this.settingsManager.getShowTerminalProgress() &&
|
|
574
|
+
(this.session.isStreaming || this.session.isCompacting)) {
|
|
575
|
+
terminal.setProgress(true);
|
|
576
|
+
}
|
|
577
|
+
return true;
|
|
578
|
+
}
|
|
481
579
|
async init() {
|
|
482
580
|
if (this.isInitialized)
|
|
483
581
|
return;
|
|
@@ -501,18 +599,36 @@ export class InteractiveMode {
|
|
|
501
599
|
: "";
|
|
502
600
|
console.log(theme.fg("dim", `Model scope: ${modelList}${cycleHint}`));
|
|
503
601
|
}
|
|
504
|
-
//
|
|
505
|
-
// Keep loaded resources before chat so restored session messages never precede them.
|
|
506
|
-
this.ui.addChild(this.headerContainer);
|
|
507
|
-
this.ui.addChild(this.loadedResourcesContainer);
|
|
508
|
-
this.ui.addChild(this.chatContainer);
|
|
509
|
-
this.ui.addChild(this.pendingMessagesContainer);
|
|
510
|
-
this.ui.addChild(this.statusContainer);
|
|
602
|
+
// Keep one component tree and remount it when changing renderers.
|
|
511
603
|
this.renderWidgets(); // Initialize with default spacer
|
|
512
|
-
this.
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
604
|
+
this.transcriptScrollView = new TuiLayouts.ScrollView(this.documentContainer, {
|
|
605
|
+
follow: "end",
|
|
606
|
+
primary: true,
|
|
607
|
+
overscroll: "chain",
|
|
608
|
+
scrollbar: this.settingsManager.getFullscreenScrollbar(),
|
|
609
|
+
scrollbarStyle: (text) => theme.bg("scrollbarThumb", text),
|
|
610
|
+
});
|
|
611
|
+
const dock = new TuiLayouts.VStack([
|
|
612
|
+
{ component: this.pendingMessagesContainer, shrink: 1, minSize: 0 },
|
|
613
|
+
{ component: this.statusContainer, shrink: 1, minSize: 0 },
|
|
614
|
+
{ component: this.widgetContainerAbove, shrink: 1, minSize: 0 },
|
|
615
|
+
{ component: this.editorContainer, shrink: 1, minSize: 3 },
|
|
616
|
+
{ component: this.widgetContainerBelow, shrink: 1, minSize: 0 },
|
|
617
|
+
{ component: this.footerContainer, shrink: 1, minSize: 1 },
|
|
618
|
+
]);
|
|
619
|
+
this.fullscreenLayoutRoot = new TuiLayouts.VStack([
|
|
620
|
+
{ component: this.transcriptScrollView, basis: 0, grow: 1, shrink: 1, minSize: 1 },
|
|
621
|
+
{ component: dock, basis: "auto", grow: 0, shrink: 1, minSize: 1 },
|
|
622
|
+
]);
|
|
623
|
+
this.mountInteractiveTui(this.renderer, [
|
|
624
|
+
this.documentContainer,
|
|
625
|
+
this.pendingMessagesContainer,
|
|
626
|
+
this.statusContainer,
|
|
627
|
+
this.widgetContainerAbove,
|
|
628
|
+
this.editorContainer,
|
|
629
|
+
this.widgetContainerBelow,
|
|
630
|
+
this.footerContainer,
|
|
631
|
+
]);
|
|
516
632
|
this.ui.setFocus(this.editor);
|
|
517
633
|
this.setupKeyHandlers();
|
|
518
634
|
this.setupEditorSubmitHandler();
|
|
@@ -604,10 +720,13 @@ export class InteractiveMode {
|
|
|
604
720
|
async run() {
|
|
605
721
|
await this.init();
|
|
606
722
|
if (!process.env.PI_OFFLINE) {
|
|
723
|
+
const controller = new AbortController();
|
|
724
|
+
const timeout = setTimeout(() => controller.abort(), 15_000);
|
|
607
725
|
void this.session.modelRuntime
|
|
608
|
-
.refresh()
|
|
726
|
+
.refresh({ signal: controller.signal })
|
|
609
727
|
.then(() => this.updateAvailableProviderCount())
|
|
610
|
-
.catch(() => { })
|
|
728
|
+
.catch(() => { })
|
|
729
|
+
.finally(() => clearTimeout(timeout));
|
|
611
730
|
}
|
|
612
731
|
// Start version check asynchronously
|
|
613
732
|
checkForNewPiVersion(this.version).then((newRelease) => {
|
|
@@ -1110,7 +1229,12 @@ export class InteractiveMode {
|
|
|
1110
1229
|
}
|
|
1111
1230
|
}
|
|
1112
1231
|
if (showListing) {
|
|
1113
|
-
const
|
|
1232
|
+
const systemPromptSource = this.session.resourceLoader.getSystemPromptSource();
|
|
1233
|
+
const contextFiles = [
|
|
1234
|
+
...(systemPromptSource ? [systemPromptSource] : []),
|
|
1235
|
+
...this.session.resourceLoader.getAppendSystemPromptSources(),
|
|
1236
|
+
...this.session.resourceLoader.getAgentsFiles().agentsFiles,
|
|
1237
|
+
];
|
|
1114
1238
|
if (contextFiles.length > 0) {
|
|
1115
1239
|
this.loadedResourcesContainer.addChild(new Spacer(1));
|
|
1116
1240
|
const contextList = contextFiles
|
|
@@ -1254,6 +1378,7 @@ export class InteractiveMode {
|
|
|
1254
1378
|
if (result.cancelled) {
|
|
1255
1379
|
return { cancelled: true };
|
|
1256
1380
|
}
|
|
1381
|
+
this.coalescingTerminal.passNextFullRedraw();
|
|
1257
1382
|
this.clearChat();
|
|
1258
1383
|
this.renderInitialMessages();
|
|
1259
1384
|
if (result.editorText && !this.editor.getText().trim()) {
|
|
@@ -1287,8 +1412,12 @@ export class InteractiveMode {
|
|
|
1287
1412
|
this.showLoadedResources({ force: false, showDiagnosticsWhenQuiet: true });
|
|
1288
1413
|
this.showStartupNoticesIfNeeded();
|
|
1289
1414
|
}
|
|
1415
|
+
applyFullscreenScrollbarSetting() {
|
|
1416
|
+
this.transcriptScrollView?.setScrollbar(this.settingsManager.getFullscreenScrollbar());
|
|
1417
|
+
}
|
|
1290
1418
|
applyRuntimeSettings() {
|
|
1291
1419
|
configureHttpDispatcher(this.settingsManager.getHttpIdleTimeoutMs());
|
|
1420
|
+
this.applyFullscreenScrollbarSetting();
|
|
1292
1421
|
this.footer.setSession(this.session);
|
|
1293
1422
|
this.footer.setAutoCompactEnabled(this.session.autoCompactionEnabled);
|
|
1294
1423
|
this.footerDataProvider.setCwd(this.sessionManager.getCwd());
|
|
@@ -1310,16 +1439,19 @@ export class InteractiveMode {
|
|
|
1310
1439
|
}
|
|
1311
1440
|
}
|
|
1312
1441
|
async rebindCurrentSession(options = {}) {
|
|
1442
|
+
const session = this.session;
|
|
1313
1443
|
this.unsubscribe?.();
|
|
1314
1444
|
this.unsubscribe = undefined;
|
|
1315
1445
|
this.applyRuntimeSettings();
|
|
1316
1446
|
if (options.renderBeforeBind) {
|
|
1317
1447
|
this.renderCurrentSessionState();
|
|
1318
1448
|
this.subscribeToAgent();
|
|
1319
|
-
await this.bindCurrentSessionExtensions();
|
|
1320
1449
|
}
|
|
1321
|
-
|
|
1322
|
-
|
|
1450
|
+
await this.bindCurrentSessionExtensions();
|
|
1451
|
+
if (this.session !== session) {
|
|
1452
|
+
return;
|
|
1453
|
+
}
|
|
1454
|
+
if (!options.renderBeforeBind) {
|
|
1323
1455
|
this.subscribeToAgent();
|
|
1324
1456
|
}
|
|
1325
1457
|
await this.updateAvailableProviderCount();
|
|
@@ -1354,6 +1486,10 @@ export class InteractiveMode {
|
|
|
1354
1486
|
this.pendingTools.clear();
|
|
1355
1487
|
}
|
|
1356
1488
|
renderCurrentSessionState() {
|
|
1489
|
+
// Resuming, forking, or starting a new session rebuilds the transcript
|
|
1490
|
+
// at the user's request; the rebuild's full redraw keeps the clean
|
|
1491
|
+
// wipe-and-replay even if preservation is still windowed on.
|
|
1492
|
+
this.coalescingTerminal.passNextFullRedraw();
|
|
1357
1493
|
this.loadedResourcesContainer.clear();
|
|
1358
1494
|
this.clearChat();
|
|
1359
1495
|
this.pendingMessagesContainer.clear();
|
|
@@ -1397,6 +1533,9 @@ export class InteractiveMode {
|
|
|
1397
1533
|
}
|
|
1398
1534
|
this.chatContainer.addChild(component);
|
|
1399
1535
|
}
|
|
1536
|
+
getMarkdownTransformers() {
|
|
1537
|
+
return [this.mermaidMarkdownTransformer, ...this.session.extensionRunner.getMarkdownTransformers()];
|
|
1538
|
+
}
|
|
1400
1539
|
/**
|
|
1401
1540
|
* Set up keyboard shortcuts registered by extensions.
|
|
1402
1541
|
*/
|
|
@@ -1413,6 +1552,7 @@ export class InteractiveMode {
|
|
|
1413
1552
|
sessionManager: this.sessionManager,
|
|
1414
1553
|
modelRegistry: extensionRunner.getModelRegistry(),
|
|
1415
1554
|
model: this.session.model,
|
|
1555
|
+
scopedModels: this.session.scopedModels,
|
|
1416
1556
|
thinkingLevel: this.session.thinkingLevel,
|
|
1417
1557
|
isIdle: () => this.session.isIdle,
|
|
1418
1558
|
isProjectTrusted: () => this.settingsManager.isProjectTrusted(),
|
|
@@ -1475,7 +1615,7 @@ export class InteractiveMode {
|
|
|
1475
1615
|
this.activeStatusIndicator?.dispose();
|
|
1476
1616
|
this.activeStatusIndicator = undefined;
|
|
1477
1617
|
this.statusContainer.clear();
|
|
1478
|
-
if (hadActiveStatusIndicator && this.ui.getClearOnShrink()) {
|
|
1618
|
+
if (hadActiveStatusIndicator && this.options.tuiMode === "regular" && this.ui.getClearOnShrink()) {
|
|
1479
1619
|
this.statusContainer.addChild(this.idleStatus);
|
|
1480
1620
|
}
|
|
1481
1621
|
}
|
|
@@ -1589,7 +1729,7 @@ export class InteractiveMode {
|
|
|
1589
1729
|
this.setHiddenThinkingLabel();
|
|
1590
1730
|
}
|
|
1591
1731
|
// Maximum total widget lines to prevent viewport overflow
|
|
1592
|
-
static MAX_WIDGET_LINES = 10;
|
|
1732
|
+
static { this.MAX_WIDGET_LINES = 10; }
|
|
1593
1733
|
/**
|
|
1594
1734
|
* Render all extension widgets to the widget container.
|
|
1595
1735
|
*/
|
|
@@ -1623,22 +1763,16 @@ export class InteractiveMode {
|
|
|
1623
1763
|
if (this.customFooter?.dispose) {
|
|
1624
1764
|
this.customFooter.dispose();
|
|
1625
1765
|
}
|
|
1626
|
-
|
|
1627
|
-
if (this.customFooter) {
|
|
1628
|
-
this.ui.removeChild(this.customFooter);
|
|
1629
|
-
}
|
|
1630
|
-
else {
|
|
1631
|
-
this.ui.removeChild(this.footer);
|
|
1632
|
-
}
|
|
1766
|
+
this.footerContainer.clear();
|
|
1633
1767
|
if (factory) {
|
|
1634
1768
|
// Create and add custom footer, passing the data provider
|
|
1635
1769
|
this.customFooter = factory(this.ui, theme, this.footerDataProvider);
|
|
1636
|
-
this.
|
|
1770
|
+
this.footerContainer.addChild(this.customFooter);
|
|
1637
1771
|
}
|
|
1638
1772
|
else {
|
|
1639
1773
|
// Restore built-in footer
|
|
1640
1774
|
this.customFooter = undefined;
|
|
1641
|
-
this.
|
|
1775
|
+
this.footerContainer.addChild(this.footer);
|
|
1642
1776
|
}
|
|
1643
1777
|
this.ui.requestRender();
|
|
1644
1778
|
}
|
|
@@ -1684,18 +1818,27 @@ export class InteractiveMode {
|
|
|
1684
1818
|
this.ui.requestRender();
|
|
1685
1819
|
}
|
|
1686
1820
|
addExtensionTerminalInputListener(handler) {
|
|
1687
|
-
const
|
|
1688
|
-
this.
|
|
1821
|
+
const subscription = { handler, unsubscribe: this.ui.addInputListener(handler) };
|
|
1822
|
+
this.extensionTerminalInputSubscriptions.add(subscription);
|
|
1689
1823
|
return () => {
|
|
1690
|
-
unsubscribe();
|
|
1691
|
-
this.
|
|
1824
|
+
subscription.unsubscribe();
|
|
1825
|
+
this.extensionTerminalInputSubscriptions.delete(subscription);
|
|
1692
1826
|
};
|
|
1693
1827
|
}
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1828
|
+
rebindScrollbackPreservationInputListener() {
|
|
1829
|
+
this.scrollbackPreservationInputUnsubscribe?.();
|
|
1830
|
+
this.scrollbackPreservationInputUnsubscribe = this.ui.addInputListener(this.scrollbackPreservationInputHandler);
|
|
1831
|
+
}
|
|
1832
|
+
rebindExtensionTerminalInputListeners() {
|
|
1833
|
+
for (const subscription of this.extensionTerminalInputSubscriptions) {
|
|
1834
|
+
subscription.unsubscribe();
|
|
1835
|
+
subscription.unsubscribe = this.ui.addInputListener(subscription.handler);
|
|
1697
1836
|
}
|
|
1698
|
-
|
|
1837
|
+
}
|
|
1838
|
+
clearExtensionTerminalInputListeners() {
|
|
1839
|
+
for (const subscription of this.extensionTerminalInputSubscriptions)
|
|
1840
|
+
subscription.unsubscribe();
|
|
1841
|
+
this.extensionTerminalInputSubscriptions.clear();
|
|
1699
1842
|
}
|
|
1700
1843
|
/**
|
|
1701
1844
|
* Create the ExtensionUIContext for extensions.
|
|
@@ -1796,6 +1939,7 @@ export class InteractiveMode {
|
|
|
1796
1939
|
cancelHint: opts?.cancelHint,
|
|
1797
1940
|
onToggleToolsExpanded: () => this.toggleToolOutputExpansion(),
|
|
1798
1941
|
});
|
|
1942
|
+
this.disposeActiveSelector();
|
|
1799
1943
|
this.editorContainer.clear();
|
|
1800
1944
|
this.editorContainer.addChild(this.extensionSelector);
|
|
1801
1945
|
this.ui.setFocus(this.extensionSelector);
|
|
@@ -1817,7 +1961,9 @@ export class InteractiveMode {
|
|
|
1817
1961
|
* Show a confirmation dialog for extensions.
|
|
1818
1962
|
*/
|
|
1819
1963
|
async showExtensionConfirm(title, message, opts) {
|
|
1820
|
-
|
|
1964
|
+
// The message is context, not a heading: render it as the selector's muted
|
|
1965
|
+
// subtitle instead of folding it into the accent-bold title.
|
|
1966
|
+
const result = await this.showExtensionSelector(title, ["Yes", "No"], { ...opts, subtitle: message });
|
|
1821
1967
|
return result === "Yes";
|
|
1822
1968
|
}
|
|
1823
1969
|
async promptForMissingSessionCwd(error) {
|
|
@@ -1847,6 +1993,7 @@ export class InteractiveMode {
|
|
|
1847
1993
|
this.hideExtensionInput();
|
|
1848
1994
|
resolve(undefined);
|
|
1849
1995
|
}, { tui: this.ui, timeout: opts?.timeout });
|
|
1996
|
+
this.disposeActiveSelector();
|
|
1850
1997
|
this.editorContainer.clear();
|
|
1851
1998
|
this.editorContainer.addChild(this.extensionInput);
|
|
1852
1999
|
this.ui.setFocus(this.extensionInput);
|
|
@@ -1876,6 +2023,7 @@ export class InteractiveMode {
|
|
|
1876
2023
|
this.hideExtensionEditor();
|
|
1877
2024
|
resolve(undefined);
|
|
1878
2025
|
}, undefined, this.settingsManager.getExternalEditorCommand());
|
|
2026
|
+
this.disposeActiveSelector();
|
|
1879
2027
|
this.editorContainer.clear();
|
|
1880
2028
|
this.editorContainer.addChild(this.extensionEditor);
|
|
1881
2029
|
this.ui.setFocus(this.extensionEditor);
|
|
@@ -1900,6 +2048,7 @@ export class InteractiveMode {
|
|
|
1900
2048
|
this.editorComponentFactory = factory;
|
|
1901
2049
|
// Save text from current editor before switching
|
|
1902
2050
|
const currentText = this.editor.getText();
|
|
2051
|
+
this.disposeActiveSelector();
|
|
1903
2052
|
this.editorContainer.clear();
|
|
1904
2053
|
if (factory) {
|
|
1905
2054
|
// Create the custom editor with tui, theme, and keybindings
|
|
@@ -1916,6 +2065,9 @@ export class InteractiveMode {
|
|
|
1916
2065
|
if (newEditor.setPaddingX !== undefined) {
|
|
1917
2066
|
newEditor.setPaddingX(this.defaultEditor.getPaddingX());
|
|
1918
2067
|
}
|
|
2068
|
+
if (newEditor.setAutocompleteMaxVisible !== undefined) {
|
|
2069
|
+
newEditor.setAutocompleteMaxVisible(this.defaultEditor.getAutocompleteMaxVisible());
|
|
2070
|
+
}
|
|
1919
2071
|
// Set autocomplete if supported
|
|
1920
2072
|
if (newEditor.setAutocompleteProvider && this.autocompleteProvider) {
|
|
1921
2073
|
newEditor.setAutocompleteProvider(this.autocompleteProvider);
|
|
@@ -2020,6 +2172,7 @@ export class InteractiveMode {
|
|
|
2020
2172
|
options?.onHandle?.(handle);
|
|
2021
2173
|
}
|
|
2022
2174
|
else {
|
|
2175
|
+
this.disposeActiveSelector();
|
|
2023
2176
|
this.editorContainer.clear();
|
|
2024
2177
|
this.editorContainer.addChild(component);
|
|
2025
2178
|
this.ui.setFocus(component);
|
|
@@ -2106,7 +2259,7 @@ export class InteractiveMode {
|
|
|
2106
2259
|
this.defaultEditor.onAction("app.tools.expand", () => this.toggleToolOutputExpansion());
|
|
2107
2260
|
this.defaultEditor.onAction("app.thinking.toggle", () => this.toggleThinkingBlockVisibility());
|
|
2108
2261
|
this.defaultEditor.onAction("app.editor.external", () => void this.handleOpenExternalEditor());
|
|
2109
|
-
this.defaultEditor.onAction("app.message.copy", () => void this.handleCopyCommand());
|
|
2262
|
+
this.defaultEditor.onAction("app.message.copy", () => void this.handleCopyCommand({ flashConfirmation: true }));
|
|
2110
2263
|
this.defaultEditor.onAction("app.message.followUp", () => this.handleFollowUp());
|
|
2111
2264
|
this.defaultEditor.onAction("app.message.dequeue", () => this.handleDequeue());
|
|
2112
2265
|
this.defaultEditor.onAction("app.session.new", () => this.handleClearCommand());
|
|
@@ -2407,17 +2560,17 @@ export class InteractiveMode {
|
|
|
2407
2560
|
this.ui.requestRender();
|
|
2408
2561
|
}
|
|
2409
2562
|
else if (event.message.role === "assistant") {
|
|
2410
|
-
this.streamingComponent = new AssistantMessageComponent(undefined, this.hideThinkingBlock, this.getMarkdownThemeWithSettings(), this.hiddenThinkingLabel, this.outputPad);
|
|
2563
|
+
this.streamingComponent = new AssistantMessageComponent(undefined, this.hideThinkingBlock, this.getMarkdownThemeWithSettings(), this.hiddenThinkingLabel, this.outputPad, this.getMarkdownTransformers());
|
|
2411
2564
|
this.streamingMessage = event.message;
|
|
2412
2565
|
this.chatContainer.addChild(this.streamingComponent);
|
|
2413
|
-
this.streamingComponent.updateContent(this.streamingMessage);
|
|
2566
|
+
this.streamingComponent.updateContent(this.streamingMessage, true);
|
|
2414
2567
|
this.ui.requestRender();
|
|
2415
2568
|
}
|
|
2416
2569
|
break;
|
|
2417
2570
|
case "message_update":
|
|
2418
2571
|
if (this.streamingComponent && event.message.role === "assistant") {
|
|
2419
2572
|
this.streamingMessage = event.message;
|
|
2420
|
-
this.streamingComponent.updateContent(this.streamingMessage);
|
|
2573
|
+
this.streamingComponent.updateContent(this.streamingMessage, true);
|
|
2421
2574
|
for (const content of this.streamingMessage.content) {
|
|
2422
2575
|
if (content.type === "toolCall") {
|
|
2423
2576
|
if (!this.pendingTools.has(content.id)) {
|
|
@@ -2450,7 +2603,7 @@ export class InteractiveMode {
|
|
|
2450
2603
|
: "Operation aborted";
|
|
2451
2604
|
this.streamingMessage.errorMessage = errorMessage;
|
|
2452
2605
|
}
|
|
2453
|
-
this.streamingComponent.updateContent(this.streamingMessage);
|
|
2606
|
+
this.streamingComponent.updateContent(this.streamingMessage, false);
|
|
2454
2607
|
if (this.streamingMessage.stopReason === "aborted" || this.streamingMessage.stopReason === "error") {
|
|
2455
2608
|
if (!errorMessage) {
|
|
2456
2609
|
errorMessage = this.streamingMessage.errorMessage || "Error";
|
|
@@ -2726,12 +2879,12 @@ export class InteractiveMode {
|
|
|
2726
2879
|
// Render user message separately if present
|
|
2727
2880
|
if (skillBlock.userMessage) {
|
|
2728
2881
|
this.chatContainer.addChild(new Spacer(1));
|
|
2729
|
-
const userComponent = new UserMessageComponent(skillBlock.userMessage, this.getMarkdownThemeWithSettings(), this.outputPad);
|
|
2882
|
+
const userComponent = new UserMessageComponent(skillBlock.userMessage, this.getMarkdownThemeWithSettings(), this.outputPad, this.getMarkdownTransformers());
|
|
2730
2883
|
this.chatContainer.addChild(userComponent);
|
|
2731
2884
|
}
|
|
2732
2885
|
}
|
|
2733
2886
|
else {
|
|
2734
|
-
const userComponent = new UserMessageComponent(textContent, this.getMarkdownThemeWithSettings(), this.outputPad);
|
|
2887
|
+
const userComponent = new UserMessageComponent(textContent, this.getMarkdownThemeWithSettings(), this.outputPad, this.getMarkdownTransformers());
|
|
2735
2888
|
this.chatContainer.addChild(userComponent);
|
|
2736
2889
|
}
|
|
2737
2890
|
if (options?.populateHistory) {
|
|
@@ -2741,7 +2894,7 @@ export class InteractiveMode {
|
|
|
2741
2894
|
break;
|
|
2742
2895
|
}
|
|
2743
2896
|
case "assistant": {
|
|
2744
|
-
const assistantComponent = new AssistantMessageComponent(message, this.hideThinkingBlock, this.getMarkdownThemeWithSettings(), this.hiddenThinkingLabel, this.outputPad);
|
|
2897
|
+
const assistantComponent = new AssistantMessageComponent(message, this.hideThinkingBlock, this.getMarkdownThemeWithSettings(), this.hiddenThinkingLabel, this.outputPad, this.getMarkdownTransformers());
|
|
2745
2898
|
this.chatContainer.addChild(assistantComponent);
|
|
2746
2899
|
break;
|
|
2747
2900
|
}
|
|
@@ -2924,12 +3077,6 @@ export class InteractiveMode {
|
|
|
2924
3077
|
// Only called when editor is empty (enforced by CustomEditor)
|
|
2925
3078
|
void this.shutdown();
|
|
2926
3079
|
}
|
|
2927
|
-
/**
|
|
2928
|
-
* Gracefully shutdown the agent.
|
|
2929
|
-
* Stops the TUI before emitting shutdown events so extension UI cleanup cannot
|
|
2930
|
-
* repaint the final frame while the process is exiting.
|
|
2931
|
-
*/
|
|
2932
|
-
isShuttingDown = false;
|
|
2933
3080
|
async shutdown(options) {
|
|
2934
3081
|
if (this.isShuttingDown)
|
|
2935
3082
|
return;
|
|
@@ -3171,6 +3318,8 @@ export class InteractiveMode {
|
|
|
3171
3318
|
this.setToolsExpanded(!this.toolOutputExpanded);
|
|
3172
3319
|
}
|
|
3173
3320
|
setToolsExpanded(expanded) {
|
|
3321
|
+
if (expanded === this.toolOutputExpanded)
|
|
3322
|
+
return;
|
|
3174
3323
|
this.toolOutputExpanded = expanded;
|
|
3175
3324
|
// An explicit toggle prefers upstream's clean wipe-and-replay even
|
|
3176
3325
|
// mid-run: the user just pressed the key, so they are interacting at
|
|
@@ -3188,7 +3337,7 @@ export class InteractiveMode {
|
|
|
3188
3337
|
}
|
|
3189
3338
|
}
|
|
3190
3339
|
}
|
|
3191
|
-
this.
|
|
3340
|
+
this.showStatus(`Tool output: ${expanded ? "expanded" : "collapsed"}`);
|
|
3192
3341
|
}
|
|
3193
3342
|
toggleThinkingBlockVisibility() {
|
|
3194
3343
|
this.hideThinkingBlock = !this.hideThinkingBlock;
|
|
@@ -3233,7 +3382,7 @@ export class InteractiveMode {
|
|
|
3233
3382
|
}
|
|
3234
3383
|
showError(errorMessage) {
|
|
3235
3384
|
this.chatContainer.addChild(new Spacer(1));
|
|
3236
|
-
this.chatContainer.addChild(new Text(theme.fg("error", `Error: ${errorMessage}`),
|
|
3385
|
+
this.chatContainer.addChild(new Text(theme.fg("error", `Error: ${errorMessage}`), this.outputPad, 0));
|
|
3237
3386
|
this.ui.requestRender();
|
|
3238
3387
|
}
|
|
3239
3388
|
showWarning(warningMessage) {
|
|
@@ -3439,52 +3588,50 @@ export class InteractiveMode {
|
|
|
3439
3588
|
// =========================================================================
|
|
3440
3589
|
// Selectors
|
|
3441
3590
|
// =========================================================================
|
|
3591
|
+
disposeActiveSelector() {
|
|
3592
|
+
const dispose = this.activeSelectorDispose;
|
|
3593
|
+
this.activeSelectorToken = undefined;
|
|
3594
|
+
this.activeSelectorDispose = undefined;
|
|
3595
|
+
dispose?.();
|
|
3596
|
+
}
|
|
3442
3597
|
/**
|
|
3443
3598
|
* Shows a selector component in place of the editor.
|
|
3444
3599
|
* @param create Factory that receives a `done` callback and returns the component and focus target
|
|
3445
3600
|
*/
|
|
3446
3601
|
showSelector(create) {
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
this.activeSelector = null;
|
|
3450
|
-
let selector;
|
|
3602
|
+
const token = {};
|
|
3603
|
+
let dispose;
|
|
3451
3604
|
let disposed = false;
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
if (disposed || !selector)
|
|
3605
|
+
const disposeOnce = () => {
|
|
3606
|
+
if (disposed)
|
|
3455
3607
|
return;
|
|
3456
3608
|
disposed = true;
|
|
3457
|
-
|
|
3609
|
+
dispose?.();
|
|
3458
3610
|
};
|
|
3459
3611
|
const done = () => {
|
|
3460
|
-
|
|
3612
|
+
disposeOnce();
|
|
3613
|
+
if (this.activeSelectorToken !== token)
|
|
3461
3614
|
return;
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
this.editorContainer.clear();
|
|
3468
|
-
this.editorContainer.addChild(this.editor);
|
|
3469
|
-
this.ui.setFocus(this.editor);
|
|
3470
|
-
}
|
|
3615
|
+
this.activeSelectorToken = undefined;
|
|
3616
|
+
this.activeSelectorDispose = undefined;
|
|
3617
|
+
this.editorContainer.clear();
|
|
3618
|
+
this.editorContainer.addChild(this.editor);
|
|
3619
|
+
this.ui.setFocus(this.editor);
|
|
3471
3620
|
};
|
|
3472
3621
|
const created = create(done);
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
}
|
|
3478
|
-
this.activeSelector = selector;
|
|
3479
|
-
this.activeSelectorCleanup = dispose;
|
|
3622
|
+
dispose = created.dispose;
|
|
3623
|
+
this.disposeActiveSelector();
|
|
3624
|
+
this.activeSelectorToken = token;
|
|
3625
|
+
this.activeSelectorDispose = disposeOnce;
|
|
3480
3626
|
this.editorContainer.clear();
|
|
3481
|
-
this.editorContainer.addChild(
|
|
3627
|
+
this.editorContainer.addChild(created.component);
|
|
3482
3628
|
this.ui.setFocus(created.focus);
|
|
3483
3629
|
this.ui.requestRender();
|
|
3484
3630
|
}
|
|
3485
3631
|
showSettingsSelector() {
|
|
3486
3632
|
this.showSelector((done) => {
|
|
3487
|
-
|
|
3633
|
+
let selector;
|
|
3634
|
+
selector = new SettingsSelectorComponent({
|
|
3488
3635
|
autoCompact: this.session.autoCompactionEnabled,
|
|
3489
3636
|
showImages: this.settingsManager.getShowImages(),
|
|
3490
3637
|
imageWidthCells: this.settingsManager.getImageWidthCells(),
|
|
@@ -3501,6 +3648,7 @@ export class InteractiveMode {
|
|
|
3501
3648
|
terminalTheme: this.themeController.getTerminalTheme(),
|
|
3502
3649
|
availableThemes: getAvailableThemes(),
|
|
3503
3650
|
hideThinkingBlock: this.hideThinkingBlock,
|
|
3651
|
+
mermaidRenderingMode: this.settingsManager.getMermaidRenderingMode(),
|
|
3504
3652
|
collapseChangelog: this.settingsManager.getCollapseChangelog(),
|
|
3505
3653
|
enableInstallTelemetry: this.settingsManager.getEnableInstallTelemetry(),
|
|
3506
3654
|
doubleEscapeAction: this.settingsManager.getDoubleEscapeAction(),
|
|
@@ -3514,6 +3662,8 @@ export class InteractiveMode {
|
|
|
3514
3662
|
quietStartup: this.settingsManager.getQuietStartup(),
|
|
3515
3663
|
clearOnShrink: this.settingsManager.getClearOnShrink(),
|
|
3516
3664
|
showTerminalProgress: this.settingsManager.getShowTerminalProgress(),
|
|
3665
|
+
tuiMode: this.ui.mode,
|
|
3666
|
+
fullscreenScrollbar: this.settingsManager.getFullscreenScrollbar(),
|
|
3517
3667
|
warnings: this.settingsManager.getWarnings(),
|
|
3518
3668
|
}, {
|
|
3519
3669
|
onAutoCompactChange: (enabled) => {
|
|
@@ -3582,6 +3732,11 @@ export class InteractiveMode {
|
|
|
3582
3732
|
this.clearChat();
|
|
3583
3733
|
this.rebuildChatFromMessages();
|
|
3584
3734
|
},
|
|
3735
|
+
onMermaidRenderingModeChange: (mode) => {
|
|
3736
|
+
this.settingsManager.setMermaidRenderingMode(mode);
|
|
3737
|
+
this.chatContainer.invalidate();
|
|
3738
|
+
this.ui.requestRender();
|
|
3739
|
+
},
|
|
3585
3740
|
onShowCacheMissNoticesChange: (shown) => {
|
|
3586
3741
|
this.settingsManager.setShowCacheMissNotices(shown);
|
|
3587
3742
|
this.rebuildChatFromMessages();
|
|
@@ -3651,6 +3806,21 @@ export class InteractiveMode {
|
|
|
3651
3806
|
onShowTerminalProgressChange: (enabled) => {
|
|
3652
3807
|
this.settingsManager.setShowTerminalProgress(enabled);
|
|
3653
3808
|
},
|
|
3809
|
+
onTuiModeChange: (mode) => {
|
|
3810
|
+
if (!this.switchTuiMode(mode)) {
|
|
3811
|
+
selector?.getSettingsList().updateValue("tui-mode", this.ui.mode);
|
|
3812
|
+
this.showStatus("Close active overlays before changing TUI mode");
|
|
3813
|
+
return;
|
|
3814
|
+
}
|
|
3815
|
+
this.settingsManager.setTuiMode(mode);
|
|
3816
|
+
if (!this.activeStatusIndicator)
|
|
3817
|
+
this.statusContainer.clear();
|
|
3818
|
+
this.showStatus(`TUI mode: ${mode}`);
|
|
3819
|
+
},
|
|
3820
|
+
onFullscreenScrollbarChange: (mode) => {
|
|
3821
|
+
this.settingsManager.setFullscreenScrollbar(mode);
|
|
3822
|
+
this.applyFullscreenScrollbarSetting();
|
|
3823
|
+
},
|
|
3654
3824
|
onWarningsChange: (warnings) => {
|
|
3655
3825
|
this.settingsManager.setWarnings(warnings);
|
|
3656
3826
|
},
|
|
@@ -3685,20 +3855,37 @@ export class InteractiveMode {
|
|
|
3685
3855
|
this.showModelSelector(searchTerm);
|
|
3686
3856
|
}
|
|
3687
3857
|
async findExactModelMatch(searchTerm) {
|
|
3688
|
-
const
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
if (this.session.scopedModels.length > 0)
|
|
3693
|
-
return
|
|
3694
|
-
|
|
3858
|
+
const cachedModels = this.session.scopedModels.length > 0
|
|
3859
|
+
? this.session.scopedModels.map((scoped) => scoped.model)
|
|
3860
|
+
: [...this.session.modelRuntime.getAvailableSnapshot()];
|
|
3861
|
+
const cachedMatch = findExactModelReferenceMatch(searchTerm, cachedModels);
|
|
3862
|
+
if (cachedMatch || this.session.scopedModels.length > 0)
|
|
3863
|
+
return cachedMatch;
|
|
3864
|
+
this.showStatus("Refreshing model catalogs…");
|
|
3865
|
+
const controller = new AbortController();
|
|
3866
|
+
let timedOut = false;
|
|
3867
|
+
const timeout = setTimeout(() => {
|
|
3868
|
+
timedOut = true;
|
|
3869
|
+
controller.abort();
|
|
3870
|
+
}, 15_000);
|
|
3695
3871
|
try {
|
|
3696
|
-
await this.session.modelRuntime.refresh();
|
|
3697
|
-
|
|
3872
|
+
const result = await this.session.modelRuntime.refresh({ signal: controller.signal });
|
|
3873
|
+
if (result.aborted && timedOut) {
|
|
3874
|
+
this.showWarning("Model refresh timed out; searching cached models.");
|
|
3875
|
+
}
|
|
3876
|
+
else if (result.errors.size > 0) {
|
|
3877
|
+
this.showWarning(`Could not refresh ${[...result.errors.keys()].join(", ")}; searching cached models.`);
|
|
3878
|
+
}
|
|
3698
3879
|
}
|
|
3699
|
-
catch {
|
|
3700
|
-
|
|
3880
|
+
catch (error) {
|
|
3881
|
+
this.showWarning(timedOut
|
|
3882
|
+
? "Model refresh timed out; searching cached models."
|
|
3883
|
+
: `Could not refresh model catalogs: ${error instanceof Error ? error.message : String(error)}`);
|
|
3884
|
+
}
|
|
3885
|
+
finally {
|
|
3886
|
+
clearTimeout(timeout);
|
|
3701
3887
|
}
|
|
3888
|
+
return findExactModelReferenceMatch(searchTerm, [...this.session.modelRuntime.getAvailableSnapshot()]);
|
|
3702
3889
|
}
|
|
3703
3890
|
/** Update the footer's available provider count from the current snapshot without refreshing catalogs. */
|
|
3704
3891
|
updateAvailableProviderCount() {
|
|
@@ -3800,73 +3987,67 @@ export class InteractiveMode {
|
|
|
3800
3987
|
done();
|
|
3801
3988
|
this.ui.requestRender();
|
|
3802
3989
|
}, initialSearchInput);
|
|
3803
|
-
return { component: selector, focus: selector };
|
|
3990
|
+
return { component: selector, focus: selector, dispose: () => selector.dispose() };
|
|
3804
3991
|
});
|
|
3805
3992
|
}
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
const allModels = [...(await this.session.modelRuntime.getAvailable())];
|
|
3810
|
-
const allModelIds = new Set(allModels.map((model) => `${model.provider}/${model.id}`));
|
|
3993
|
+
showModelsSelector() {
|
|
3994
|
+
let availableModels = [...this.session.modelRuntime.getAvailableSnapshot()];
|
|
3995
|
+
let availableModelIds = new Set(availableModels.map((model) => `${model.provider}/${model.id}`));
|
|
3811
3996
|
const configuredPatterns = this.settingsManager.getEnabledModels();
|
|
3812
3997
|
const sessionScopedModels = this.session.scopedModels;
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
|
|
3822
|
-
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
|
|
3829
|
-
currentEnabledIds = configuredScope.scopedModels.map((scoped) => `${scoped.model.provider}/${scoped.model.id}`);
|
|
3830
|
-
}
|
|
3831
|
-
for (const diagnostic of configuredScope?.diagnostics ?? []) {
|
|
3832
|
-
if (diagnostic.code !== "no-match")
|
|
3833
|
-
continue;
|
|
3834
|
-
currentEnabledIds ??= [];
|
|
3835
|
-
if (!currentEnabledIds.includes(diagnostic.pattern))
|
|
3836
|
-
currentEnabledIds.push(diagnostic.pattern);
|
|
3837
|
-
}
|
|
3838
|
-
// Helper to update session's scoped models (session-only, no persist)
|
|
3839
|
-
const updateSessionModels = async (enabledIds) => {
|
|
3998
|
+
const configuredEnabledIds = (models) => {
|
|
3999
|
+
if (!configuredPatterns?.length)
|
|
4000
|
+
return null;
|
|
4001
|
+
const resolved = resolveModelScopeFromModels(configuredPatterns, models);
|
|
4002
|
+
const ids = resolved.scopedModels.map((scoped) => `${scoped.model.provider}/${scoped.model.id}`);
|
|
4003
|
+
for (const diagnostic of resolved.diagnostics) {
|
|
4004
|
+
if (diagnostic.code === "no-match" && !ids.includes(diagnostic.pattern))
|
|
4005
|
+
ids.push(diagnostic.pattern);
|
|
4006
|
+
}
|
|
4007
|
+
return ids;
|
|
4008
|
+
};
|
|
4009
|
+
let currentEnabledIds = sessionScopedModels.length > 0
|
|
4010
|
+
? sessionScopedModels.map((scoped) => `${scoped.model.provider}/${scoped.model.id}`)
|
|
4011
|
+
: configuredEnabledIds(availableModels);
|
|
4012
|
+
let selectionChanged = false;
|
|
4013
|
+
const updateSessionModels = (enabledIds) => {
|
|
3840
4014
|
currentEnabledIds = enabledIds === null ? null : [...enabledIds];
|
|
3841
|
-
const hasEnabledAvailableModel = enabledIds?.some((id) =>
|
|
3842
|
-
const allAvailableModelsEnabled = enabledIds !== null && [...
|
|
4015
|
+
const hasEnabledAvailableModel = enabledIds?.some((id) => availableModelIds.has(id)) ?? false;
|
|
4016
|
+
const allAvailableModelsEnabled = enabledIds !== null && [...availableModelIds].every((id) => enabledIds.includes(id));
|
|
3843
4017
|
if (enabledIds && hasEnabledAvailableModel && !allAvailableModelsEnabled) {
|
|
3844
|
-
const newScopedModels =
|
|
3845
|
-
this.session.setScopedModels(newScopedModels.map((
|
|
3846
|
-
model:
|
|
3847
|
-
thinkingLevel:
|
|
4018
|
+
const newScopedModels = resolveModelScopeFromModels(enabledIds, availableModels).scopedModels;
|
|
4019
|
+
this.session.setScopedModels(newScopedModels.map((scoped) => ({
|
|
4020
|
+
model: scoped.model,
|
|
4021
|
+
thinkingLevel: scoped.thinkingLevel,
|
|
3848
4022
|
})));
|
|
3849
4023
|
}
|
|
3850
4024
|
else {
|
|
3851
|
-
// All enabled or none enabled = no filter
|
|
3852
4025
|
this.session.setScopedModels([]);
|
|
3853
4026
|
}
|
|
3854
|
-
|
|
4027
|
+
this.updateAvailableProviderCount();
|
|
3855
4028
|
this.ui.requestRender();
|
|
3856
4029
|
};
|
|
3857
4030
|
this.showSelector((done) => {
|
|
4031
|
+
let disposed = false;
|
|
4032
|
+
let timedOut = false;
|
|
4033
|
+
const controller = new AbortController();
|
|
4034
|
+
const timeout = setTimeout(() => {
|
|
4035
|
+
timedOut = true;
|
|
4036
|
+
controller.abort();
|
|
4037
|
+
}, 15_000);
|
|
3858
4038
|
const selector = new ScopedModelsSelectorComponent({
|
|
3859
|
-
allModels,
|
|
4039
|
+
allModels: availableModels,
|
|
3860
4040
|
enabledModelIds: currentEnabledIds,
|
|
4041
|
+
refreshStatus: "Refreshing model catalogs…",
|
|
3861
4042
|
}, {
|
|
3862
|
-
onChange:
|
|
3863
|
-
|
|
4043
|
+
onChange: (enabledIds) => {
|
|
4044
|
+
selectionChanged = true;
|
|
4045
|
+
updateSessionModels(enabledIds);
|
|
3864
4046
|
},
|
|
3865
4047
|
onPersist: (enabledIds) => {
|
|
3866
|
-
// Persist to settings
|
|
3867
4048
|
const allEnabled = enabledIds !== null &&
|
|
3868
|
-
enabledIds.length ===
|
|
3869
|
-
enabledIds.every((id) =>
|
|
4049
|
+
enabledIds.length === availableModels.length &&
|
|
4050
|
+
enabledIds.every((id) => availableModelIds.has(id));
|
|
3870
4051
|
const newPatterns = enabledIds === null || allEnabled ? undefined : enabledIds;
|
|
3871
4052
|
this.settingsManager.setEnabledModels(newPatterns ? [...newPatterns] : undefined);
|
|
3872
4053
|
this.showStatus("Model selection saved to settings");
|
|
@@ -3876,7 +4057,51 @@ export class InteractiveMode {
|
|
|
3876
4057
|
this.ui.requestRender();
|
|
3877
4058
|
},
|
|
3878
4059
|
});
|
|
3879
|
-
|
|
4060
|
+
void this.session.modelRuntime
|
|
4061
|
+
.refresh({ signal: controller.signal })
|
|
4062
|
+
.then((result) => {
|
|
4063
|
+
if (disposed)
|
|
4064
|
+
return;
|
|
4065
|
+
availableModels = [...this.session.modelRuntime.getAvailableSnapshot()];
|
|
4066
|
+
availableModelIds = new Set(availableModels.map((model) => `${model.provider}/${model.id}`));
|
|
4067
|
+
if (!selectionChanged && sessionScopedModels.length === 0) {
|
|
4068
|
+
currentEnabledIds = configuredEnabledIds(availableModels);
|
|
4069
|
+
selector.updateModels(availableModels, currentEnabledIds);
|
|
4070
|
+
}
|
|
4071
|
+
else {
|
|
4072
|
+
selector.updateModels(availableModels);
|
|
4073
|
+
}
|
|
4074
|
+
if (currentEnabledIds !== null)
|
|
4075
|
+
updateSessionModels(currentEnabledIds);
|
|
4076
|
+
if (result.aborted && timedOut) {
|
|
4077
|
+
selector.setRefreshStatus("Model refresh timed out; showing cached models.", "warning");
|
|
4078
|
+
}
|
|
4079
|
+
else if (result.errors.size > 0) {
|
|
4080
|
+
selector.setRefreshStatus(`Could not refresh ${[...result.errors.keys()].join(", ")}; showing cached models.`, "warning");
|
|
4081
|
+
}
|
|
4082
|
+
else {
|
|
4083
|
+
selector.setRefreshStatus("Model catalogs refreshed.", "success");
|
|
4084
|
+
}
|
|
4085
|
+
this.ui.requestRender();
|
|
4086
|
+
})
|
|
4087
|
+
.catch((error) => {
|
|
4088
|
+
if (disposed)
|
|
4089
|
+
return;
|
|
4090
|
+
selector.setRefreshStatus(timedOut
|
|
4091
|
+
? "Model refresh timed out; showing cached models."
|
|
4092
|
+
: `Could not refresh model catalogs: ${error instanceof Error ? error.message : String(error)}`, "warning");
|
|
4093
|
+
this.ui.requestRender();
|
|
4094
|
+
})
|
|
4095
|
+
.finally(() => clearTimeout(timeout));
|
|
4096
|
+
return {
|
|
4097
|
+
component: selector,
|
|
4098
|
+
focus: selector,
|
|
4099
|
+
dispose: () => {
|
|
4100
|
+
disposed = true;
|
|
4101
|
+
clearTimeout(timeout);
|
|
4102
|
+
controller.abort();
|
|
4103
|
+
},
|
|
4104
|
+
};
|
|
3880
4105
|
});
|
|
3881
4106
|
}
|
|
3882
4107
|
showUserMessageSelector() {
|
|
@@ -3938,7 +4163,7 @@ export class InteractiveMode {
|
|
|
3938
4163
|
this.showSelector((done) => {
|
|
3939
4164
|
const selector = new TreeSelectorComponent(tree, realLeafId, this.ui.terminal.rows, async (entryId) => {
|
|
3940
4165
|
// Selecting the current leaf is a no-op (already there)
|
|
3941
|
-
if (entryId ===
|
|
4166
|
+
if (entryId === this.sessionManager.getLeafId()) {
|
|
3942
4167
|
done();
|
|
3943
4168
|
this.showStatus("Already at this point");
|
|
3944
4169
|
return;
|
|
@@ -3973,6 +4198,11 @@ export class InteractiveMode {
|
|
|
3973
4198
|
break;
|
|
3974
4199
|
}
|
|
3975
4200
|
}
|
|
4201
|
+
// The user committed to navigating: stop the active response first.
|
|
4202
|
+
if (this.session.isStreaming) {
|
|
4203
|
+
this.restoreQueuedMessagesToEditor();
|
|
4204
|
+
await this.session.abort();
|
|
4205
|
+
}
|
|
3976
4206
|
// Set up escape handler and status indicator if summarizing
|
|
3977
4207
|
let showingSummaryIndicator = false;
|
|
3978
4208
|
const originalOnEscape = this.defaultEditor.onEscape;
|
|
@@ -4000,6 +4230,9 @@ export class InteractiveMode {
|
|
|
4000
4230
|
this.showStatus("Navigation cancelled");
|
|
4001
4231
|
return;
|
|
4002
4232
|
}
|
|
4233
|
+
// User-committed tree navigation rebuilds the transcript; its
|
|
4234
|
+
// full redraw bypasses scrollback preservation.
|
|
4235
|
+
this.coalescingTerminal.passNextFullRedraw();
|
|
4003
4236
|
// Update UI
|
|
4004
4237
|
this.clearChat();
|
|
4005
4238
|
this.renderInitialMessages();
|
|
@@ -4133,7 +4366,7 @@ export class InteractiveMode {
|
|
|
4133
4366
|
return options.sort((a, b) => a.name.localeCompare(b.name));
|
|
4134
4367
|
}
|
|
4135
4368
|
async getLogoutProviderOptions() {
|
|
4136
|
-
return (await this.session.modelRuntime.listCredentials())
|
|
4369
|
+
return (await this.session.modelRuntime.listCredentials({ signal: AbortSignal.timeout(15_000) }))
|
|
4137
4370
|
.map(({ providerId, type }) => ({
|
|
4138
4371
|
id: providerId,
|
|
4139
4372
|
name: this.session.modelRuntime.getProvider(providerId)?.name ?? providerId,
|
|
@@ -4151,7 +4384,6 @@ export class InteractiveMode {
|
|
|
4151
4384
|
provider.name.toLowerCase() === normalizedProviderRef);
|
|
4152
4385
|
}
|
|
4153
4386
|
async handleLoginCommand(providerRef) {
|
|
4154
|
-
await this.session.modelRuntime.getAvailable();
|
|
4155
4387
|
if (!providerRef) {
|
|
4156
4388
|
this.showLoginAuthTypeSelector();
|
|
4157
4389
|
return;
|
|
@@ -4265,7 +4497,14 @@ export class InteractiveMode {
|
|
|
4265
4497
|
this.showLoginAuthTypeSelector();
|
|
4266
4498
|
return;
|
|
4267
4499
|
}
|
|
4268
|
-
|
|
4500
|
+
let providerOptions;
|
|
4501
|
+
try {
|
|
4502
|
+
providerOptions = await this.getLogoutProviderOptions();
|
|
4503
|
+
}
|
|
4504
|
+
catch (error) {
|
|
4505
|
+
this.showError(`Could not read stored credentials: ${error instanceof Error ? error.message : String(error)}`);
|
|
4506
|
+
return;
|
|
4507
|
+
}
|
|
4269
4508
|
if (providerOptions.length === 0) {
|
|
4270
4509
|
this.showStatus("No stored credentials to remove. /logout only removes credentials saved by /login; environment variables and models.json config are unchanged.");
|
|
4271
4510
|
return;
|
|
@@ -4278,7 +4517,9 @@ export class InteractiveMode {
|
|
|
4278
4517
|
return;
|
|
4279
4518
|
}
|
|
4280
4519
|
try {
|
|
4281
|
-
await this.session.modelRuntime.logout(providerOption.id
|
|
4520
|
+
await this.session.modelRuntime.logout(providerOption.id, {
|
|
4521
|
+
signal: AbortSignal.timeout(15_000),
|
|
4522
|
+
});
|
|
4282
4523
|
await this.updateAvailableProviderCount();
|
|
4283
4524
|
const message = providerOption.authType === "oauth"
|
|
4284
4525
|
? `Logged out of ${providerOption.name}`
|
|
@@ -4286,7 +4527,10 @@ export class InteractiveMode {
|
|
|
4286
4527
|
this.showStatus(message);
|
|
4287
4528
|
}
|
|
4288
4529
|
catch (error) {
|
|
4289
|
-
|
|
4530
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
4531
|
+
this.showError(error instanceof CredentialSynchronizationError
|
|
4532
|
+
? `Credentials removed for ${providerOption.name}, but local model state could not be synchronized: ${message}`
|
|
4533
|
+
: `Logout failed: ${message}`);
|
|
4290
4534
|
}
|
|
4291
4535
|
}, () => {
|
|
4292
4536
|
done();
|
|
@@ -4296,12 +4540,11 @@ export class InteractiveMode {
|
|
|
4296
4540
|
});
|
|
4297
4541
|
}
|
|
4298
4542
|
async completeProviderAuthentication(providerId, providerName, authType, previousModel) {
|
|
4299
|
-
await this.session.modelRuntime.getAvailable();
|
|
4300
4543
|
const actionLabel = authType === "oauth" ? `Logged in to ${providerName}` : `Saved API key for ${providerName}`;
|
|
4301
4544
|
let selectedModel;
|
|
4302
4545
|
let selectionError;
|
|
4303
4546
|
if (isUnknownModel(previousModel)) {
|
|
4304
|
-
const availableModels =
|
|
4547
|
+
const availableModels = this.session.modelRuntime.getAvailableSnapshot();
|
|
4305
4548
|
const providerModels = availableModels.filter((model) => model.provider === providerId);
|
|
4306
4549
|
if (!hasDefaultModelProvider(providerId)) {
|
|
4307
4550
|
selectionError = `${actionLabel}, but no default model is configured for provider "${providerId}". Use /model to select a model.`;
|
|
@@ -4344,6 +4587,25 @@ export class InteractiveMode {
|
|
|
4344
4587
|
void this.maybeWarnAboutAnthropicSubscriptionAuth();
|
|
4345
4588
|
}
|
|
4346
4589
|
}
|
|
4590
|
+
const controller = new AbortController();
|
|
4591
|
+
const timeout = setTimeout(() => controller.abort(), 15_000);
|
|
4592
|
+
void this.session.modelRuntime
|
|
4593
|
+
.refresh({ providers: [providerId], signal: controller.signal })
|
|
4594
|
+
.then((result) => {
|
|
4595
|
+
if (result.aborted) {
|
|
4596
|
+
this.showWarning(`${actionLabel}, but its model catalog refresh timed out; using cached models.`);
|
|
4597
|
+
}
|
|
4598
|
+
else if (result.errors.size > 0) {
|
|
4599
|
+
this.showWarning(`${actionLabel}, but its model catalog could not be refreshed; using cached models.`);
|
|
4600
|
+
}
|
|
4601
|
+
this.updateAvailableProviderCount();
|
|
4602
|
+
this.footer.invalidate();
|
|
4603
|
+
this.ui.requestRender();
|
|
4604
|
+
})
|
|
4605
|
+
.catch((error) => {
|
|
4606
|
+
this.showWarning(`${actionLabel}, but its model catalog could not be refreshed: ${error instanceof Error ? error.message : String(error)}`);
|
|
4607
|
+
})
|
|
4608
|
+
.finally(() => clearTimeout(timeout));
|
|
4347
4609
|
}
|
|
4348
4610
|
showAmbientAuthDialog(providerOption) {
|
|
4349
4611
|
const restoreEditor = () => {
|
|
@@ -4389,7 +4651,10 @@ export class InteractiveMode {
|
|
|
4389
4651
|
catch (error) {
|
|
4390
4652
|
restoreEditor();
|
|
4391
4653
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
4392
|
-
if (
|
|
4654
|
+
if (error instanceof CredentialSynchronizationError) {
|
|
4655
|
+
this.showError(`Saved API key for ${providerName}, but local model state could not be synchronized: ${errorMsg}`);
|
|
4656
|
+
}
|
|
4657
|
+
else if (errorMsg !== "Login cancelled") {
|
|
4393
4658
|
this.showError(`Failed to save API key for ${providerName}: ${errorMsg}`);
|
|
4394
4659
|
}
|
|
4395
4660
|
}
|
|
@@ -4492,7 +4757,10 @@ export class InteractiveMode {
|
|
|
4492
4757
|
catch (error) {
|
|
4493
4758
|
restoreEditor();
|
|
4494
4759
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
4495
|
-
if (
|
|
4760
|
+
if (error instanceof CredentialSynchronizationError) {
|
|
4761
|
+
this.showError(`Logged in to ${providerName}, but local model state could not be synchronized: ${errorMsg}`);
|
|
4762
|
+
}
|
|
4763
|
+
else if (errorMsg !== "Login cancelled") {
|
|
4496
4764
|
this.showError(`Failed to login to ${providerName}: ${errorMsg}`);
|
|
4497
4765
|
}
|
|
4498
4766
|
}
|
|
@@ -4537,13 +4805,16 @@ export class InteractiveMode {
|
|
|
4537
4805
|
}
|
|
4538
4806
|
this.hideThinkingBlock = this.settingsManager.getHideThinkingBlock();
|
|
4539
4807
|
this.outputPad = this.settingsManager.getOutputPad();
|
|
4808
|
+
// The user asked for this rebuild; its full redraw keeps the
|
|
4809
|
+
// upstream wipe-and-replay even if preservation is still windowed
|
|
4810
|
+
// on from the previous run.
|
|
4811
|
+
this.coalescingTerminal.passNextFullRedraw();
|
|
4540
4812
|
this.rebuildChatFromMessages();
|
|
4541
4813
|
chatRestoredBeforeSessionStart = true;
|
|
4542
4814
|
};
|
|
4543
4815
|
try {
|
|
4544
4816
|
await this.session.reload({ beforeSessionStart: restoreChatBeforeSessionStart });
|
|
4545
4817
|
restoreChatBeforeSessionStart();
|
|
4546
|
-
configureHttpDispatcher(this.settingsManager.getHttpIdleTimeoutMs());
|
|
4547
4818
|
this.keybindings.reload();
|
|
4548
4819
|
const activeHeader = this.customHeader ?? this.builtInHeader;
|
|
4549
4820
|
if (isExpandable(activeHeader)) {
|
|
@@ -4551,20 +4822,7 @@ export class InteractiveMode {
|
|
|
4551
4822
|
}
|
|
4552
4823
|
setRegisteredThemes(this.session.resourceLoader.getThemes().themes);
|
|
4553
4824
|
await this.themeController.applyFromSettings();
|
|
4554
|
-
|
|
4555
|
-
const autocompleteMaxVisible = this.settingsManager.getAutocompleteMaxVisible();
|
|
4556
|
-
this.defaultEditor.setPaddingX(editorPaddingX);
|
|
4557
|
-
this.defaultEditor.setAutocompleteMaxVisible(autocompleteMaxVisible);
|
|
4558
|
-
if (this.editor !== this.defaultEditor) {
|
|
4559
|
-
this.editor.setPaddingX?.(editorPaddingX);
|
|
4560
|
-
this.editor.setAutocompleteMaxVisible?.(autocompleteMaxVisible);
|
|
4561
|
-
}
|
|
4562
|
-
this.ui.setShowHardwareCursor(this.settingsManager.getShowHardwareCursor());
|
|
4563
|
-
const clearOnShrink = this.settingsManager.getClearOnShrink();
|
|
4564
|
-
this.ui.setClearOnShrink(clearOnShrink);
|
|
4565
|
-
if (!clearOnShrink && !this.activeStatusIndicator) {
|
|
4566
|
-
this.statusContainer.clear();
|
|
4567
|
-
}
|
|
4825
|
+
this.applyRuntimeSettings();
|
|
4568
4826
|
this.setupAutocompleteProvider();
|
|
4569
4827
|
const runner = this.session.extensionRunner;
|
|
4570
4828
|
this.setupExtensionShortcuts(runner);
|
|
@@ -4760,7 +5018,7 @@ export class InteractiveMode {
|
|
|
4760
5018
|
}
|
|
4761
5019
|
}
|
|
4762
5020
|
}
|
|
4763
|
-
async handleCopyCommand() {
|
|
5021
|
+
async handleCopyCommand(options = {}) {
|
|
4764
5022
|
const text = this.session.getLastAssistantText();
|
|
4765
5023
|
if (!text) {
|
|
4766
5024
|
this.showError("No agent messages to copy yet.");
|
|
@@ -4768,7 +5026,12 @@ export class InteractiveMode {
|
|
|
4768
5026
|
}
|
|
4769
5027
|
try {
|
|
4770
5028
|
await copyToClipboard(text);
|
|
4771
|
-
|
|
5029
|
+
if (options.flashConfirmation && this.ui instanceof TuiAltScreen) {
|
|
5030
|
+
this.ui.flash("Copied!");
|
|
5031
|
+
}
|
|
5032
|
+
else {
|
|
5033
|
+
this.showStatus("Copied last agent message to clipboard");
|
|
5034
|
+
}
|
|
4772
5035
|
}
|
|
4773
5036
|
catch (error) {
|
|
4774
5037
|
this.showError(error instanceof Error ? error.message : String(error));
|
|
@@ -5131,15 +5394,15 @@ export class InteractiveMode {
|
|
|
5131
5394
|
}
|
|
5132
5395
|
}
|
|
5133
5396
|
stop() {
|
|
5134
|
-
this.
|
|
5135
|
-
this.activeSelectorCleanup = null;
|
|
5136
|
-
this.activeSelector = null;
|
|
5397
|
+
this.disposeActiveSelector();
|
|
5137
5398
|
if (this.settingsManager.getShowTerminalProgress()) {
|
|
5138
5399
|
this.ui.terminal.setProgress(false);
|
|
5139
5400
|
}
|
|
5140
5401
|
this.clearStatusIndicator();
|
|
5141
5402
|
this.themeController.disableAutoSync();
|
|
5142
5403
|
this.clearExtensionTerminalInputListeners();
|
|
5404
|
+
this.scrollbackPreservationInputUnsubscribe?.();
|
|
5405
|
+
this.scrollbackPreservationInputUnsubscribe = undefined;
|
|
5143
5406
|
this.clearPendingTools();
|
|
5144
5407
|
this.disposeChatToolComponents();
|
|
5145
5408
|
this.footer.dispose();
|
|
@@ -5148,7 +5411,7 @@ export class InteractiveMode {
|
|
|
5148
5411
|
this.unsubscribe();
|
|
5149
5412
|
}
|
|
5150
5413
|
if (this.isInitialized) {
|
|
5151
|
-
this.
|
|
5414
|
+
this.stopInteractiveTui();
|
|
5152
5415
|
this.isInitialized = false;
|
|
5153
5416
|
}
|
|
5154
5417
|
this.unregisterSignalHandlers();
|