@selesai/code 0.13.40 → 0.14.3
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 +3 -0
- package/dist/bun/runtime-setup.js +4 -1
- package/dist/cli/args.d.ts +3 -1
- package/dist/cli/args.js +76 -33
- package/dist/cli/auth-check.d.ts +18 -0
- package/dist/cli/auth-check.js +49 -0
- package/dist/cli/credential-print.d.ts +5 -15
- package/dist/cli/credential-print.js +42 -82
- package/dist/cli/file-processor.d.ts +1 -1
- package/dist/cli/file-processor.js +2 -1
- package/dist/cli/list-models.d.ts +1 -1
- package/dist/cli/list-models.js +2 -2
- package/dist/cli/startup-ui.js +38 -30
- package/dist/config.d.ts +45 -7
- package/dist/config.js +134 -18
- package/dist/core/agent-session-custom-tools.test.js +64 -0
- package/dist/core/agent-session-length-continuation.test.js +7 -3
- package/dist/core/agent-session-runtime.js +2 -2
- package/dist/core/agent-session-services.d.ts +1 -0
- package/dist/core/agent-session-services.js +14 -0
- package/dist/core/agent-session.d.ts +180 -40
- package/dist/core/agent-session.js +1061 -485
- package/dist/core/auth-storage.d.ts +25 -15
- package/dist/core/auth-storage.js +242 -66
- package/dist/core/bash-executor.js +42 -52
- package/dist/core/bug-report.js +1 -1
- package/dist/core/cache-warmer.d.ts +1 -0
- package/dist/core/cache-warmer.js +15 -1
- package/dist/core/compaction/branch-summarization.js +3 -0
- package/dist/core/compaction/compaction.d.ts +3 -1
- package/dist/core/compaction/compaction.js +156 -79
- package/dist/core/compaction/utils.d.ts +2 -1
- package/dist/core/compaction/utils.js +25 -18
- package/dist/core/crash-log.d.ts +5 -0
- package/dist/core/crash-log.js +69 -0
- package/dist/core/defaults.d.ts +1 -1
- package/dist/core/defaults.js +1 -1
- package/dist/core/export-html/template.css +10 -0
- package/dist/core/export-html/template.js +72 -18
- package/dist/core/export-html/tool-renderer.d.ts +3 -3
- package/dist/core/export-html/tool-renderer.js +5 -3
- package/dist/core/extensions/index.d.ts +2 -2
- package/dist/core/extensions/index.js +1 -1
- package/dist/core/extensions/loader.js +138 -55
- package/dist/core/extensions/runner.d.ts +38 -5
- package/dist/core/extensions/runner.js +220 -7
- package/dist/core/extensions/types.d.ts +438 -51
- package/dist/core/extensions/types.js +3 -0
- package/dist/core/extensions/virtual-modules.js +6 -0
- package/dist/core/extensions/wrapper.d.ts +2 -2
- package/dist/core/extensions/wrapper.js +3 -3
- package/dist/core/footer-data-provider.d.ts +1 -1
- package/dist/core/footer-data-provider.js +1 -1
- package/dist/core/handoff.d.ts +0 -1
- package/dist/core/handoff.js +0 -1
- package/dist/core/http-dispatcher.js +5 -0
- package/dist/core/index.d.ts +1 -1
- package/dist/core/keybindings.d.ts +25 -24
- package/dist/core/keybindings.js +27 -6
- package/dist/core/mcp-servers.d.ts +134 -0
- package/dist/core/mcp-servers.js +223 -0
- package/dist/core/model-config.d.ts +122 -5
- package/dist/core/model-config.js +35 -1
- package/dist/core/model-registry.d.ts +23 -15
- package/dist/core/model-registry.js +46 -22
- package/dist/core/model-resolver.d.ts +6 -5
- package/dist/core/model-resolver.js +51 -21
- package/dist/core/model-runtime.d.ts +73 -14
- package/dist/core/model-runtime.js +398 -104
- package/dist/core/models-store.d.ts +12 -7
- package/dist/core/models-store.js +85 -15
- package/dist/core/nested-tool-calls.d.ts +102 -0
- package/dist/core/nested-tool-calls.js +178 -0
- package/dist/core/package-manager.d.ts +8 -1
- package/dist/core/package-manager.js +144 -61
- package/dist/core/package-manager.test.js +5 -5
- package/dist/core/pi-manifest.d.ts +9 -0
- package/dist/core/pi-manifest.js +25 -0
- package/dist/core/prompt-templates.d.ts +6 -1
- package/dist/core/prompt-templates.js +61 -35
- package/dist/core/provider-composer.d.ts +44 -19
- package/dist/core/provider-composer.js +166 -64
- package/dist/core/radius.d.ts +2 -0
- package/dist/core/radius.js +2 -0
- package/dist/core/remote-catalog-provider.d.ts +8 -1
- package/dist/core/remote-catalog-provider.js +25 -13
- package/dist/core/resource-loader.d.ts +9 -1
- package/dist/core/resource-loader.js +179 -45
- package/dist/core/runtime-credentials.d.ts +5 -5
- package/dist/core/runtime-credentials.js +11 -8
- package/dist/core/sdk.d.ts +16 -7
- package/dist/core/sdk.js +57 -24
- package/dist/core/session-manager.d.ts +45 -9
- package/dist/core/session-manager.js +124 -31
- package/dist/core/settings-diagnostics.d.ts +8 -0
- package/dist/core/settings-diagnostics.js +20 -0
- package/dist/core/settings-manager.d.ts +62 -32
- package/dist/core/settings-manager.js +147 -69
- package/dist/core/skills.d.ts +5 -2
- package/dist/core/skills.js +58 -35
- package/dist/core/slash-commands.js +2 -1
- package/dist/core/source-info.d.ts +8 -0
- package/dist/core/source-info.js +16 -0
- package/dist/core/system-prompt.d.ts +9 -3
- package/dist/core/system-prompt.js +9 -12
- package/dist/core/system-prompt.test.js +2 -7
- package/dist/core/tools/bash.d.ts +12 -0
- package/dist/core/tools/bash.js +33 -2
- package/dist/core/tools/edit-diff.d.ts +0 -5
- package/dist/core/tools/edit-diff.js +2 -5
- package/dist/core/tools/edit.d.ts +4 -0
- package/dist/core/tools/edit.js +31 -11
- package/dist/core/tools/find.d.ts +7 -0
- package/dist/core/tools/find.js +16 -19
- package/dist/core/tools/grep.d.ts +4 -0
- package/dist/core/tools/grep.js +5 -1
- package/dist/core/tools/index.d.ts +1 -1
- package/dist/core/tools/index.js +11 -2
- package/dist/core/tools/ls.d.ts +4 -0
- package/dist/core/tools/ls.js +5 -1
- package/dist/core/tools/output-accumulator.d.ts +11 -0
- package/dist/core/tools/output-accumulator.js +40 -10
- package/dist/core/tools/read.d.ts +17 -2
- package/dist/core/tools/read.js +23 -2
- package/dist/core/tools/render-utils.d.ts +6 -0
- package/dist/core/tools/render-utils.js +26 -0
- package/dist/core/tools/renderers/bash.js +19 -35
- package/dist/core/tools/renderers/edit.js +5 -4
- package/dist/core/tools/renderers/index.d.ts +2 -2
- package/dist/core/tools/renderers/read.js +3 -2
- package/dist/core/tools/tool-definition-wrapper.d.ts +5 -3
- package/dist/core/tools/tool-definition-wrapper.js +3 -1
- package/dist/core/tools/truncate.d.ts +14 -0
- package/dist/core/tools/truncate.js +29 -0
- package/dist/core/tools/write.d.ts +4 -0
- package/dist/core/tools/write.js +6 -2
- package/dist/core/trust-manager.js +3 -1
- package/dist/core/usage-totals.d.ts +2 -0
- package/dist/core/usage-totals.js +23 -0
- package/dist/core/virtual-models.d.ts +116 -0
- package/dist/core/virtual-models.js +123 -0
- package/dist/defaults/models.json +32 -0
- package/dist/defaults/settings.json +1 -9
- package/dist/extensions/codemode/execute.d.ts +15 -0
- package/dist/extensions/codemode/execute.js +645 -0
- package/dist/extensions/codemode/execute.lazy.d.ts +2 -0
- package/dist/extensions/codemode/execute.lazy.js +2 -0
- package/dist/extensions/codemode/index.d.ts +20 -0
- package/dist/extensions/codemode/index.js +31 -0
- package/dist/extensions/codemode/renderer.d.ts +11 -0
- package/dist/extensions/codemode/renderer.js +136 -0
- package/dist/extensions/codemode/tool.d.ts +129 -0
- package/dist/extensions/codemode/tool.js +275 -0
- package/dist/extensions/context-compaction-reminder.ts +1 -1
- package/dist/extensions/grep-app/index.ts +2 -10
- package/dist/extensions/herdr-agent-state.ts +1 -1
- package/dist/extensions/{pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/index.d.ts → index.d.ts} +0 -1
- package/dist/extensions/index.js +12 -0
- package/dist/extensions/jev/classifier-context.ts +54 -0
- package/dist/extensions/jev/classifier.test.ts +150 -0
- package/dist/extensions/jev/classifier.ts +191 -0
- package/dist/extensions/jev/decisions.test.ts +56 -47
- package/dist/extensions/jev/decisions.ts +94 -109
- package/dist/extensions/jev/test-support.ts +33 -38
- package/dist/extensions/jev-advisory-lifecycle.test.ts +12 -12
- package/dist/extensions/jev-advisory-memory.test.ts +9 -9
- package/dist/extensions/jev-advisory-recommendations.test.ts +8 -8
- package/dist/extensions/jev-ask-tool.test.ts +41 -45
- package/dist/extensions/jev-ask-tool.ts +11 -39
- package/dist/extensions/jev-find-source.test.ts +26 -0
- package/dist/extensions/jev-find-source.ts +58 -19
- package/dist/extensions/jev-tool-ranker.test.ts +185 -0
- package/dist/extensions/jev-tool-ranker.ts +169 -0
- package/dist/{core → extensions}/llama/client.d.ts +2 -0
- package/dist/{core → extensions}/llama/client.js +7 -3
- package/dist/{core → extensions}/llama/index.js +13 -2
- package/dist/{core → extensions}/llama/provider.d.ts +1 -1
- package/dist/extensions/llama/provider.js +235 -0
- package/dist/extensions/mcp/cli.d.ts +20 -0
- package/dist/extensions/mcp/cli.js +496 -0
- package/dist/extensions/mcp/cli.lazy.d.ts +2 -0
- package/dist/extensions/mcp/cli.lazy.js +2 -0
- package/dist/extensions/mcp/config.d.ts +83 -0
- package/dist/extensions/mcp/config.js +193 -0
- package/dist/extensions/mcp/index.d.ts +78 -0
- package/dist/extensions/mcp/index.js +1201 -0
- package/dist/extensions/mcp/log.d.ts +15 -0
- package/dist/extensions/mcp/log.js +65 -0
- package/dist/extensions/mcp/oauth.d.ts +97 -0
- package/dist/extensions/mcp/oauth.js +401 -0
- package/dist/extensions/mcp/resources.d.ts +41 -0
- package/dist/extensions/mcp/resources.js +260 -0
- package/dist/extensions/mcp/runtime.d.ts +96 -0
- package/dist/extensions/mcp/runtime.js +412 -0
- package/dist/extensions/mcp/runtime.lazy.d.ts +2 -0
- package/dist/extensions/mcp/runtime.lazy.js +2 -0
- package/dist/extensions/mcp/tools.d.ts +86 -0
- package/dist/extensions/mcp/tools.js +252 -0
- package/dist/extensions/mcp/ui.d.ts +59 -0
- package/dist/extensions/mcp/ui.js +185 -0
- package/dist/extensions/package.json +2 -1
- package/dist/extensions/pi-graft/index.ts +4 -19
- package/dist/extensions/pi-graft/lifecycle.test.ts +32 -25
- package/dist/extensions/pi-graft/tools.ts +6 -0
- package/dist/extensions/pi-hermes-memory/CHANGELOG.md +25 -0
- package/dist/extensions/pi-hermes-memory/README.md +140 -4
- package/dist/extensions/pi-hermes-memory/package-lock.json +624 -2720
- package/dist/extensions/pi-hermes-memory/package.json +9 -7
- package/dist/extensions/pi-hermes-memory/scripts/benchmark-memory-startup.mjs +72 -0
- package/dist/extensions/pi-hermes-memory/scripts/check-production-install.mjs +107 -0
- package/dist/extensions/pi-hermes-memory/src/auto-consolidation-warning.ts +2 -1
- package/dist/extensions/pi-hermes-memory/src/config.ts +35 -0
- package/dist/extensions/pi-hermes-memory/src/constants.ts +62 -15
- package/dist/extensions/pi-hermes-memory/src/handlers/auto-consolidate.ts +374 -50
- package/dist/extensions/pi-hermes-memory/src/handlers/background-review.ts +7 -4
- package/dist/extensions/pi-hermes-memory/src/handlers/correction-detector.ts +19 -14
- package/dist/extensions/pi-hermes-memory/src/handlers/insights.ts +75 -1
- package/dist/extensions/pi-hermes-memory/src/handlers/review-memory-ops.ts +322 -22
- package/dist/extensions/pi-hermes-memory/src/handlers/session-backfill.ts +8 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/session-flush.ts +193 -54
- package/dist/extensions/pi-hermes-memory/src/handlers/skills-command.ts +6 -2
- package/dist/extensions/pi-hermes-memory/src/handlers/sync-markdown-memories.ts +33 -5
- package/dist/extensions/pi-hermes-memory/src/index.ts +116 -47
- package/dist/extensions/pi-hermes-memory/src/memory-initialization.ts +101 -0
- package/dist/extensions/pi-hermes-memory/src/store/atomic-lock-coordinator.ts +10 -2
- package/dist/extensions/pi-hermes-memory/src/store/db.ts +34 -9
- package/dist/extensions/pi-hermes-memory/src/store/memory-store.ts +44 -8
- package/dist/extensions/pi-hermes-memory/src/store/schema.ts +3 -1
- package/dist/extensions/pi-hermes-memory/src/store/sqlite-memory-store.ts +141 -0
- package/dist/extensions/pi-hermes-memory/src/store/standing-instructions.ts +17 -6
- package/dist/extensions/pi-hermes-memory/src/tools/memory-search-tool.ts +20 -10
- package/dist/extensions/pi-hermes-memory/src/tools/memory-tool.ts +1 -17
- package/dist/extensions/pi-hermes-memory/src/tools/session-search-tool.ts +2 -10
- package/dist/extensions/pi-hermes-memory/src/tools/skill-tool.ts +4 -8
- package/dist/extensions/pi-hermes-memory/src/types.ts +48 -0
- package/dist/extensions/pi-hermes-memory/tests/config.test.ts +108 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/auto-consolidate.test.ts +1185 -42
- package/dist/extensions/pi-hermes-memory/tests/handlers/insights.test.ts +57 -1
- package/dist/extensions/pi-hermes-memory/tests/handlers/lazy-memory-hooks.test.ts +128 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/review-memory-ops.test.ts +844 -1
- package/dist/extensions/pi-hermes-memory/tests/handlers/session-backfill.test.ts +16 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/session-flush.test.ts +512 -3
- package/dist/extensions/pi-hermes-memory/tests/handlers/skills-command.test.ts +38 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/sync-markdown-memories.test.ts +183 -2
- package/dist/extensions/pi-hermes-memory/tests/handlers/system-prompt.test.ts +1 -3
- package/dist/extensions/pi-hermes-memory/tests/index.test.ts +17 -0
- package/dist/extensions/pi-hermes-memory/tests/integration/corruption-recovery-integration.test.ts +21 -0
- package/dist/extensions/pi-hermes-memory/tests/lazy-startup.test.ts +313 -0
- package/dist/extensions/pi-hermes-memory/tests/memory-initialization.test.ts +182 -0
- package/dist/extensions/pi-hermes-memory/tests/prompt-injection.test.ts +184 -0
- package/dist/extensions/pi-hermes-memory/tests/skill-discovery-contract.test.ts +60 -0
- package/dist/extensions/pi-hermes-memory/tests/store/atomic-lock-lazy-probe.test.ts +80 -0
- package/dist/extensions/pi-hermes-memory/tests/store/db.test.ts +2 -0
- package/dist/extensions/pi-hermes-memory/tests/store/memory-store.test.ts +79 -0
- package/dist/extensions/pi-hermes-memory/tests/store/sqlite-memory-store.test.ts +268 -0
- package/dist/extensions/pi-hermes-memory/tests/store/standing-instructions.test.ts +29 -0
- package/dist/extensions/pi-hermes-memory/tests/store/usage-tracking.test.ts +170 -0
- package/dist/extensions/pi-hermes-memory/tests/tools/memory-search-tool.test.ts +80 -1
- package/dist/extensions/pi-hermes-memory/tests/tools/skill-tool.test.ts +51 -0
- package/dist/extensions/pi-intercom/CHANGELOG.md +66 -0
- package/dist/extensions/pi-intercom/README.md +100 -12
- package/dist/extensions/pi-intercom/broker/broker.ts +28 -12
- package/dist/extensions/pi-intercom/broker/client.ts +3 -0
- package/dist/extensions/pi-intercom/broker/cross-machine-provenance.test.ts +63 -0
- package/dist/extensions/pi-intercom/broker/protocol.ts +64 -0
- package/dist/extensions/pi-intercom/broker/spawn.test.ts +58 -167
- package/dist/extensions/pi-intercom/broker/spawn.ts +40 -87
- package/dist/extensions/pi-intercom/cli.mjs +6 -0
- package/dist/extensions/pi-intercom/cli.test.ts +428 -0
- package/dist/extensions/pi-intercom/cli.ts +343 -0
- package/dist/extensions/pi-intercom/config.test.ts +61 -1
- package/dist/extensions/pi-intercom/config.ts +53 -2
- package/dist/extensions/pi-intercom/cross-machine-discovery.test.ts +218 -0
- package/dist/extensions/pi-intercom/cross-machine-discovery.ts +140 -0
- package/dist/extensions/pi-intercom/cross-machine-envelope.test.ts +106 -0
- package/dist/extensions/pi-intercom/cross-machine-envelope.ts +92 -0
- package/dist/extensions/pi-intercom/cross-machine-integration.test.ts +25 -0
- package/dist/extensions/pi-intercom/cross-machine-transport.test.ts +106 -0
- package/dist/extensions/pi-intercom/cross-machine-transport.ts +110 -0
- package/dist/extensions/pi-intercom/extension-api.ts +14 -0
- package/dist/extensions/pi-intercom/handover.test.ts +88 -0
- package/dist/extensions/pi-intercom/handover.ts +115 -0
- package/dist/extensions/pi-intercom/herdr-location.test.ts +173 -0
- package/dist/extensions/pi-intercom/herdr-location.ts +137 -0
- package/dist/extensions/pi-intercom/human-priority.pi.test.ts +489 -0
- package/dist/extensions/pi-intercom/index.ts +582 -164
- package/dist/extensions/pi-intercom/intercom.integration.test.ts +590 -22
- package/dist/extensions/pi-intercom/package.json +12 -2
- package/dist/extensions/pi-intercom/project-agent.ts +1 -1
- package/dist/extensions/pi-intercom/skills/pi-intercom/SKILL.md +26 -2
- package/dist/extensions/pi-intercom/test/handover-picker.test.ts +134 -0
- package/dist/extensions/pi-intercom/test/inline-message.test.ts +43 -0
- package/dist/extensions/pi-intercom/types.d.ts +247 -0
- package/dist/extensions/pi-intercom/types.js +2 -0
- package/dist/extensions/pi-intercom/types.ts +39 -1
- package/dist/extensions/pi-intercom/ui/handover-picker.ts +318 -0
- package/dist/extensions/pi-intercom/ui/inline-message.ts +10 -3
- package/dist/extensions/pi-intercom/ui/session-list.ts +28 -15
- package/dist/extensions/pi-subagents/.github/workflows/release.yml +5 -1
- package/dist/extensions/pi-subagents/.github/workflows/test.yml +188 -18
- package/dist/extensions/pi-subagents/CHANGELOG.md +514 -1
- package/dist/extensions/pi-subagents/README.md +7 -5
- package/dist/extensions/pi-subagents/VISION.md +6 -0
- package/dist/extensions/pi-subagents/agents/reviewer.md +7 -5
- package/dist/extensions/pi-subagents/agents/worker.md +1 -1
- package/dist/extensions/pi-subagents/docs/agents.md +75 -35
- package/dist/extensions/pi-subagents/docs/configuration.md +156 -25
- package/dist/extensions/pi-subagents/docs/extension-api.md +113 -29
- package/dist/extensions/pi-subagents/docs/missions.md +46 -14
- package/dist/extensions/pi-subagents/docs/models.md +22 -84
- package/dist/extensions/pi-subagents/docs/observability.md +49 -24
- package/dist/extensions/pi-subagents/docs/standalone-background.md +59 -0
- package/dist/extensions/pi-subagents/docs/tool-reference.md +167 -116
- package/dist/extensions/pi-subagents/docs/watchdog.md +41 -10
- package/dist/extensions/pi-subagents/docs/workflows.md +239 -163
- package/dist/extensions/pi-subagents/examples/typed-gate/.pi/agents/classifier.md +14 -0
- package/dist/extensions/pi-subagents/examples/typed-gate/README.md +42 -0
- package/dist/extensions/pi-subagents/examples/typed-gate/classify +38 -0
- package/dist/extensions/pi-subagents/examples/typed-gate/workflow.js +32 -0
- package/dist/extensions/pi-subagents/index.ts +11 -3
- package/dist/extensions/pi-subagents/inspector-runner.mjs +3 -3
- package/dist/extensions/pi-subagents/package-lock.json +517 -1129
- package/dist/extensions/pi-subagents/package.json +22 -11
- package/dist/extensions/pi-subagents/prompts/council.md +7 -4
- package/dist/extensions/pi-subagents/prompts/parallel-review.md +2 -2
- package/dist/extensions/pi-subagents/prompts/review-loop.md +2 -2
- package/dist/extensions/pi-subagents/runner-peer-loader.mjs +21 -0
- package/dist/extensions/pi-subagents/runner-peer-preload.mjs +30 -0
- package/dist/extensions/pi-subagents/scripts/build-package.mjs +79 -0
- package/dist/extensions/pi-subagents/skills/council-mode/SKILL.md +2 -2
- package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +46 -27
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/constraints-and-recipes.md +11 -7
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +78 -73
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +4 -5
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/multi-lane-orchestration.md +10 -2
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/prompting-and-roles.md +69 -67
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/review-and-validation.md +3 -3
- package/dist/extensions/pi-subagents/src/agents/advertised-agent-prompt.ts +21 -10
- package/dist/extensions/pi-subagents/src/agents/agent-management.ts +113 -113
- package/dist/extensions/pi-subagents/src/agents/agent-memory.ts +91 -4
- package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +15 -9
- package/dist/extensions/pi-subagents/src/agents/agents.ts +432 -193
- package/dist/extensions/pi-subagents/src/agents/chain-serializer.ts +6 -1
- package/dist/extensions/pi-subagents/src/agents/global-npm-root.ts +58 -0
- package/dist/extensions/pi-subagents/src/agents/proactive-skills.ts +5 -2
- package/dist/extensions/pi-subagents/src/agents/runtime-agent-registry.ts +22 -18
- package/dist/extensions/pi-subagents/src/agents/skills.ts +43 -10
- package/dist/extensions/pi-subagents/src/api/delegation.ts +20 -1
- package/dist/extensions/pi-subagents/src/api/inspectors.ts +27 -0
- package/dist/extensions/pi-subagents/src/api/preflight.ts +140 -62
- package/dist/extensions/pi-subagents/src/api/required-child-extensions.ts +6 -0
- package/dist/extensions/pi-subagents/src/api/shared-types.ts +2 -0
- package/dist/extensions/pi-subagents/src/extension/config.ts +24 -40
- package/dist/extensions/pi-subagents/src/extension/control-notices.ts +4 -1
- package/dist/extensions/pi-subagents/src/extension/doctor.ts +18 -15
- package/dist/extensions/pi-subagents/src/extension/fanout-child.ts +87 -13
- package/dist/extensions/pi-subagents/src/extension/herdr-pi-bridge.ts +162 -0
- package/dist/extensions/pi-subagents/src/extension/index.ts +280 -268
- package/dist/extensions/pi-subagents/src/extension/public-execution.ts +76 -37
- package/dist/extensions/pi-subagents/src/extension/reply-workflow-script.ts +67 -0
- package/dist/extensions/pi-subagents/src/extension/rpc.ts +34 -11
- package/dist/extensions/pi-subagents/src/extension/schemas.ts +116 -205
- package/dist/extensions/pi-subagents/src/extension/subagent-guide.ts +13 -5
- package/dist/extensions/pi-subagents/src/extension/tool-activation.ts +146 -0
- package/dist/extensions/pi-subagents/src/extension/tool-description.ts +77 -90
- package/dist/extensions/pi-subagents/src/extension/upgrade-notice.ts +40 -0
- package/dist/extensions/pi-subagents/src/inspectors/actions.ts +148 -0
- package/dist/extensions/pi-subagents/src/inspectors/ghostty/actions.ts +74 -0
- package/dist/extensions/pi-subagents/src/inspectors/ghostty/plugin.ts +29 -0
- package/dist/extensions/pi-subagents/src/inspectors/herdr/actions.ts +100 -180
- package/dist/extensions/pi-subagents/src/inspectors/herdr/plugin.ts +20 -0
- package/dist/extensions/pi-subagents/src/inspectors/herdr/project-panes.ts +2 -2
- package/dist/extensions/pi-subagents/src/inspectors/{herdr/inspector-runner.ts → inspector-runner.ts} +13 -13
- package/dist/extensions/pi-subagents/src/inspectors/plugins.ts +75 -0
- package/dist/extensions/pi-subagents/src/inspectors/{herdr/session-roots-codec.ts → session-roots-codec.ts} +4 -15
- package/dist/extensions/pi-subagents/src/inspectors/{herdr/shell-command.ts → shell-command.ts} +1 -1
- package/dist/extensions/pi-subagents/src/inspectors/types.ts +51 -0
- package/dist/extensions/pi-subagents/src/integrations/herdr-status.ts +38 -53
- package/dist/extensions/pi-subagents/src/intercom/intercom-bridge.ts +53 -9
- package/dist/extensions/pi-subagents/src/intercom/native-supervisor-channel.ts +69 -55
- package/dist/extensions/pi-subagents/src/intercom/result-intercom.ts +7 -2
- package/dist/extensions/pi-subagents/src/missions/goal-driver.ts +45 -32
- package/dist/extensions/pi-subagents/src/missions/store.ts +11 -2
- package/dist/extensions/pi-subagents/src/policy/authority.ts +5 -1
- package/dist/extensions/pi-subagents/src/profiles/profiles.ts +30 -18
- package/dist/extensions/pi-subagents/src/runs/background/active-async-capacity.ts +59 -9
- package/dist/extensions/pi-subagents/src/runs/background/active-run-index.ts +18 -2
- package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +463 -248
- package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +106 -66
- package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +33 -20
- package/dist/extensions/pi-subagents/src/runs/background/async-retention.ts +47 -17
- package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +18 -5
- package/dist/extensions/pi-subagents/src/runs/background/auto-drain.ts +24 -11
- package/dist/extensions/pi-subagents/src/runs/background/await-async-run.ts +78 -0
- package/dist/extensions/pi-subagents/src/runs/background/binary-bootstrap.ts +66 -0
- package/dist/extensions/pi-subagents/src/runs/background/calendar-schedule.ts +90 -0
- package/dist/extensions/pi-subagents/src/runs/background/chain-append.ts +2 -2
- package/dist/extensions/pi-subagents/src/runs/background/chain-root-attachment.ts +19 -38
- package/dist/extensions/pi-subagents/src/runs/background/control-channel.ts +62 -3
- package/dist/extensions/pi-subagents/src/runs/background/fleet-view.ts +82 -10
- package/dist/extensions/pi-subagents/src/runs/background/notify.ts +259 -21
- package/dist/extensions/pi-subagents/src/runs/background/owned-process-tree.ts +30 -3
- package/dist/extensions/pi-subagents/src/runs/background/pid-namespace.ts +18 -0
- package/dist/extensions/pi-subagents/src/runs/background/process-terminal-candidate.ts +98 -0
- package/dist/extensions/pi-subagents/src/runs/background/process-terminal.ts +18 -97
- package/dist/extensions/pi-subagents/src/runs/background/result-files.ts +14 -5
- package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +66 -12
- package/dist/extensions/pi-subagents/src/runs/background/retained-children.ts +4 -3
- package/dist/extensions/pi-subagents/src/runs/background/run-child-session.ts +126 -45
- package/dist/extensions/pi-subagents/src/runs/background/run-id-resolver.ts +11 -6
- package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +18 -7
- package/dist/extensions/pi-subagents/src/runs/background/runner-aliases.ts +43 -51
- package/dist/extensions/pi-subagents/src/runs/background/runner-child-launch.ts +8 -1
- package/dist/extensions/pi-subagents/src/runs/background/runner-child-sessions.ts +5 -4
- package/dist/extensions/pi-subagents/src/runs/background/runner-http-dispatcher.ts +119 -0
- package/dist/extensions/pi-subagents/src/runs/background/runner-startup-failure.ts +56 -0
- package/dist/extensions/pi-subagents/src/runs/background/scheduled-runs.ts +233 -69
- package/dist/extensions/pi-subagents/src/runs/background/stale-run-reconciler.ts +67 -16
- package/dist/extensions/pi-subagents/src/runs/background/steering.ts +21 -3
- package/dist/extensions/pi-subagents/src/runs/background/subagent-runner-bootstrap.ts +276 -0
- package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +592 -573
- package/dist/extensions/pi-subagents/src/runs/background/subagent-wait.ts +177 -29
- package/dist/extensions/pi-subagents/src/runs/background/wait-completions.ts +77 -28
- package/dist/extensions/pi-subagents/src/runs/background/wait-subscriptions.ts +10 -4
- package/dist/extensions/pi-subagents/src/runs/background/wait-tool.ts +7 -13
- package/dist/extensions/pi-subagents/src/runs/background/workflow-terminal-proof.ts +41 -23
- package/dist/extensions/pi-subagents/src/runs/foreground/async-steering-action.ts +19 -8
- package/dist/extensions/pi-subagents/src/runs/foreground/async-stop-action.ts +130 -7
- package/dist/extensions/pi-subagents/src/runs/foreground/command-action.ts +41 -0
- package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +267 -385
- package/dist/extensions/pi-subagents/src/runs/foreground/foreground-history.ts +4 -2
- package/dist/extensions/pi-subagents/src/runs/foreground/prompt-audit.ts +6 -10
- package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +1158 -413
- package/dist/extensions/pi-subagents/src/runs/foreground/workflow-detach-reconcile.ts +3 -1
- package/dist/extensions/pi-subagents/src/runs/foreground/workflow-foreground-steering.ts +2 -1
- package/dist/extensions/pi-subagents/src/runs/shared/acceptance.ts +200 -74
- package/dist/extensions/pi-subagents/src/runs/shared/async-status-projection.ts +133 -34
- package/dist/extensions/pi-subagents/src/runs/shared/capability-ceiling.ts +6 -1
- package/dist/extensions/pi-subagents/src/runs/shared/child-commands.ts +228 -0
- package/dist/extensions/pi-subagents/src/runs/shared/child-hooks.ts +18 -18
- package/dist/extensions/pi-subagents/src/runs/shared/child-launch-plan.ts +16 -4
- package/dist/extensions/pi-subagents/src/runs/shared/child-launch.ts +55 -12
- package/dist/extensions/pi-subagents/src/runs/shared/child-lifecycle.ts +6 -3
- package/dist/extensions/pi-subagents/src/runs/shared/child-runtime-config.ts +11 -1
- package/dist/extensions/pi-subagents/src/runs/shared/child-session.ts +367 -74
- package/dist/extensions/pi-subagents/src/runs/shared/child-tool-plan.ts +50 -86
- package/dist/extensions/pi-subagents/src/runs/shared/claude-code-adapter.ts +288 -0
- package/dist/extensions/pi-subagents/src/runs/shared/codex-exec-adapter.ts +129 -0
- package/dist/extensions/pi-subagents/src/runs/shared/cursor-agent-adapter.ts +114 -0
- package/dist/extensions/pi-subagents/src/runs/shared/dynamic-fanout.ts +5 -5
- package/dist/extensions/pi-subagents/src/runs/shared/effective-system-prompt.ts +33 -0
- package/dist/extensions/pi-subagents/src/runs/shared/external-cli-contract.ts +49 -10
- package/dist/extensions/pi-subagents/src/runs/shared/external-cli-preflight.ts +61 -9
- package/dist/extensions/pi-subagents/src/runs/shared/external-cli-runner.ts +16 -9
- package/dist/extensions/pi-subagents/src/runs/shared/external-job-bridge.ts +55 -1
- package/dist/extensions/pi-subagents/src/runs/shared/git-environment.ts +1 -1
- package/dist/extensions/pi-subagents/src/runs/shared/herdr-connection.ts +134 -0
- package/dist/extensions/pi-subagents/src/runs/shared/herdr-external-adapters.ts +169 -0
- package/dist/extensions/pi-subagents/src/runs/shared/herdr-machine.ts +279 -0
- package/dist/extensions/pi-subagents/src/runs/shared/herdr-pi-protocol.ts +59 -0
- package/dist/extensions/pi-subagents/src/runs/shared/herdr-placed-run.ts +263 -0
- package/dist/extensions/pi-subagents/src/runs/shared/mcp-config-sources.ts +6 -2
- package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +108 -13
- package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-grant.ts +23 -7
- package/dist/extensions/pi-subagents/src/runs/shared/model-resolution-diagnostic.ts +76 -0
- package/dist/extensions/pi-subagents/src/runs/shared/{model-fallback.ts → model-resolution.ts} +65 -245
- package/dist/extensions/pi-subagents/src/runs/shared/model-scope.ts +30 -11
- package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +24 -3
- package/dist/extensions/pi-subagents/src/runs/shared/orca-progress-tabs.ts +5 -4
- package/dist/extensions/pi-subagents/src/runs/shared/parallel-handoff.ts +55 -7
- package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +14 -4
- package/dist/extensions/pi-subagents/src/runs/shared/partial-output.ts +48 -0
- package/dist/extensions/pi-subagents/src/runs/shared/pi-spawn.ts +12 -4
- package/dist/extensions/pi-subagents/src/runs/shared/run-history.ts +88 -1
- package/dist/extensions/pi-subagents/src/runs/shared/single-output.ts +12 -3
- package/dist/extensions/pi-subagents/src/runs/shared/structured-output.ts +160 -9
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-control.ts +35 -34
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +58 -19
- package/dist/extensions/pi-subagents/src/runs/shared/tool-availability.ts +2 -2
- package/dist/extensions/pi-subagents/src/runs/shared/tool-budget.ts +21 -0
- package/dist/extensions/pi-subagents/src/runs/shared/usage-reconciliation.ts +73 -0
- package/dist/extensions/pi-subagents/src/runs/shared/workflow-async-child-guidance.ts +18 -0
- package/dist/extensions/pi-subagents/src/runs/shared/worktree-cleanup-apply.ts +160 -0
- package/dist/extensions/pi-subagents/src/runs/shared/worktree-cleanup-plan.ts +42 -20
- package/dist/extensions/pi-subagents/src/runs/shared/worktree-lock.ts +29 -0
- package/dist/extensions/pi-subagents/src/runs/shared/worktree-setup-command.ts +27 -4
- package/dist/extensions/pi-subagents/src/runs/shared/worktree.ts +94 -26
- package/dist/extensions/pi-subagents/src/shared/child-cache-retention.ts +43 -0
- package/dist/extensions/pi-subagents/src/shared/child-session-name.ts +5 -3
- package/dist/extensions/pi-subagents/src/shared/disabled-features.ts +123 -0
- package/dist/extensions/pi-subagents/src/shared/extension-context.ts +14 -1
- package/dist/extensions/pi-subagents/src/shared/file-lease.ts +74 -0
- package/dist/extensions/pi-subagents/src/shared/fork-context.ts +27 -77
- package/dist/extensions/pi-subagents/src/shared/launch-contract.ts +70 -10
- package/dist/extensions/pi-subagents/src/shared/model-info.ts +10 -1
- package/dist/extensions/pi-subagents/src/shared/opencode-session-headers.ts +30 -0
- package/dist/extensions/pi-subagents/src/shared/package-version.ts +17 -0
- package/dist/extensions/pi-subagents/src/shared/parent-wake.ts +66 -0
- package/dist/extensions/pi-subagents/src/shared/pruned-fork.ts +71 -58
- package/dist/extensions/pi-subagents/src/shared/required-child-extensions.ts +115 -0
- package/dist/extensions/pi-subagents/src/shared/settings-file-lease.ts +36 -0
- package/dist/extensions/pi-subagents/src/shared/settings.ts +7 -4
- package/dist/extensions/pi-subagents/src/shared/shortcuts.ts +1 -5
- package/dist/extensions/pi-subagents/src/shared/types.ts +146 -48
- package/dist/extensions/pi-subagents/src/slash/delegation-adapters.ts +28 -2
- package/dist/extensions/pi-subagents/src/slash/delegation-request.ts +15 -1
- package/dist/extensions/pi-subagents/src/slash/prompt-template-bridge.ts +19 -4
- package/dist/extensions/pi-subagents/src/slash/prompt-workflows.ts +13 -2
- package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +15 -15
- package/dist/extensions/pi-subagents/src/slash/subagent-cost.ts +46 -9
- package/dist/extensions/pi-subagents/src/slash/subagents-admin.ts +29 -16
- package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +201 -26
- package/dist/extensions/pi-subagents/src/tui/fleet.ts +33 -16
- package/dist/extensions/pi-subagents/src/tui/render.ts +334 -103
- package/dist/extensions/pi-subagents/src/tui/running-tone.ts +28 -0
- package/dist/extensions/pi-subagents/src/watchdog/child-status.ts +27 -28
- package/dist/extensions/pi-subagents/src/watchdog/diff-tool.ts +47 -12
- package/dist/extensions/pi-subagents/src/watchdog/lsp-diagnostics.ts +2 -2
- package/dist/extensions/pi-subagents/src/watchdog/model-selection.ts +22 -2
- package/dist/extensions/pi-subagents/src/watchdog/permission-arbiter.ts +17 -17
- package/dist/extensions/pi-subagents/src/watchdog/register-child.ts +24 -8
- package/dist/extensions/pi-subagents/src/watchdog/register-main.ts +43 -39
- package/dist/extensions/pi-subagents/src/watchdog/render.ts +2 -2
- package/dist/extensions/pi-subagents/src/watchdog/review.ts +127 -78
- package/dist/extensions/pi-subagents/src/watchdog/rules.ts +1 -1
- package/dist/extensions/pi-subagents/src/watchdog/runtime.ts +107 -31
- package/dist/extensions/pi-subagents/src/watchdog/scope.ts +1 -1
- package/dist/extensions/pi-subagents/src/watchdog/settings.ts +22 -14
- package/dist/extensions/pi-subagents/src/watchdog/tool-actions.ts +14 -13
- package/dist/extensions/pi-subagents/src/watchdog/turn-delta.ts +35 -6
- package/dist/extensions/pi-subagents/src/watchdog/types.ts +6 -4
- package/dist/extensions/pi-subagents/src/watchdog/warning-format.ts +2 -2
- package/dist/extensions/pi-subagents/src/workflows/chat-progress.ts +3 -3
- package/dist/extensions/pi-subagents/src/workflows/scripted-workflow.ts +500 -65
- package/dist/extensions/pi-subagents/src/workflows/structured-workflow-scripts.ts +177 -0
- package/dist/extensions/pi-subagents/src/workflows/workflow-checklist.ts +8 -2
- package/dist/extensions/pi-subagents/src/workflows/workflow-child-summary.ts +5 -3
- package/dist/extensions/pi-subagents/src/workflows/workflow-receipt.ts +70 -10
- package/dist/extensions/pi-subagents/src/workflows/workflow-resources.ts +57 -18
- package/dist/extensions/pi-subagents/src/workflows/workflow-reuse.ts +120 -0
- package/dist/extensions/pi-subagents/src/workflows/workflow-revival.ts +123 -0
- package/dist/extensions/pi-subagents/src/workflows/workflow-settlement.ts +5 -2
- package/dist/extensions/pi-subagents/test/fixtures/cwd-workflow-child.ts +37 -0
- package/dist/extensions/pi-subagents/test/fixtures/herdr-allocation-lock-child.ts +16 -0
- package/dist/extensions/pi-subagents/test/fixtures/herdr-provision-child.ts +15 -0
- package/dist/extensions/pi-subagents/test/fixtures/native-nested-wait-provider.ts +76 -0
- package/dist/extensions/pi-subagents/test/fixtures/runner-bootstrap-harness.ts +36 -0
- package/dist/extensions/pi-subagents/test/fixtures/schedule-history-writer.mjs +48 -0
- package/dist/extensions/pi-subagents/test/fixtures/settings-race-writer.mjs +57 -0
- package/dist/extensions/pi-subagents/test/fixtures/workflow-cwd-access-failure.ts +33 -0
- package/dist/extensions/pi-subagents/test/integration/acceptance-file-report.test.ts +40 -7
- package/dist/extensions/pi-subagents/test/integration/async-attention-clearing.test.ts +9 -8
- package/dist/extensions/pi-subagents/test/integration/async-execution.part-1.test.ts +435 -276
- package/dist/extensions/pi-subagents/test/integration/async-execution.part-2.test.ts +435 -397
- package/dist/extensions/pi-subagents/test/integration/async-execution.part-3.test.ts +918 -497
- package/dist/extensions/pi-subagents/test/integration/async-execution.part-4.test.ts +264 -17
- package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +185 -22
- package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +3 -2
- package/dist/extensions/pi-subagents/test/integration/claude-code-dispatch.test.ts +127 -0
- package/dist/extensions/pi-subagents/test/integration/deadline-checkpoint.test.ts +126 -0
- package/dist/extensions/pi-subagents/test/integration/doctor-executor.test.ts +29 -1
- package/dist/extensions/pi-subagents/test/integration/error-handling.test.ts +88 -0
- package/dist/extensions/pi-subagents/test/integration/external-cli-runner.test.ts +450 -13
- package/dist/extensions/pi-subagents/test/integration/foreign-workflow-steering.test.ts +10 -6
- package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +105 -86
- package/dist/extensions/pi-subagents/test/integration/in-process-child.test.ts +403 -18
- package/dist/extensions/pi-subagents/test/integration/inline-workflow-visibility.test.ts +351 -0
- package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +195 -10
- package/dist/extensions/pi-subagents/test/integration/model-resolution-diagnostic.test.ts +108 -0
- package/dist/extensions/pi-subagents/test/integration/nested-async-wait.test.ts +61 -0
- package/dist/extensions/pi-subagents/test/integration/orca-progress-tabs.test.ts +5 -4
- package/dist/extensions/pi-subagents/test/integration/recovered-assistant-error.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +6 -4
- package/dist/extensions/pi-subagents/test/integration/render-widget-mouse.test.ts +84 -0
- package/dist/extensions/pi-subagents/test/integration/render-widget.test.ts +242 -16
- package/dist/extensions/pi-subagents/test/integration/result-publication.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/integration/result-watcher.test.ts +158 -4
- package/dist/extensions/pi-subagents/test/integration/single-execution.part-1.test.ts +1435 -248
- package/dist/extensions/pi-subagents/test/integration/single-execution.part-2.test.ts +454 -515
- package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +140 -21
- package/dist/extensions/pi-subagents/test/integration/structured-workflows.test.ts +105 -0
- package/dist/extensions/pi-subagents/test/integration/workflow-result-publication.test.ts +90 -11
- package/dist/extensions/pi-subagents/test/integration/workflow-steer-inbox.test.ts +18 -15
- package/dist/extensions/pi-subagents/test/integration/workflow-worktree-admission.test.ts +100 -0
- package/dist/extensions/pi-subagents/test/smoke/clean-install.mjs +106 -0
- package/dist/extensions/pi-subagents/test/smoke/npm-background.mjs +43 -0
- package/dist/extensions/pi-subagents/test/smoke/packed-runner-selection.mjs +42 -0
- package/dist/extensions/pi-subagents/test/smoke/runner-loader-capability.mjs +50 -0
- package/dist/extensions/pi-subagents/test/smoke/sdk-child.ts +57 -0
- package/dist/extensions/pi-subagents/test/smoke/{pi085-extension.ts → sdk-extension.ts} +2 -2
- package/dist/extensions/pi-subagents/test/smoke/standalone-background.mjs +140 -0
- package/dist/extensions/pi-subagents/test/smoke/standalone-fault.ts +43 -0
- package/dist/extensions/pi-subagents/test/smoke/standalone-matrix.mjs +65 -0
- package/dist/extensions/pi-subagents/test/smoke/standalone-observer.ts +8 -0
- package/dist/extensions/pi-subagents/test/smoke/standalone-parent.ts +220 -0
- package/dist/extensions/pi-subagents/test/smoke/standalone-provider.ts +58 -0
- package/dist/extensions/pi-subagents/test/smoke/standalone-release.json +8 -0
- package/dist/extensions/pi-subagents/test/smoke/standalone-revival.ts +109 -0
- package/dist/extensions/pi-subagents/test/smoke/standalone-shared.ts +79 -0
- package/dist/extensions/pi-subagents/test/smoke/tool-activation.test.ts +128 -0
- package/dist/extensions/pi-subagents/test/support/async-execution-fixture.ts +6 -25
- package/dist/extensions/pi-subagents/test/support/async-result-timeout-evidence.ts +61 -0
- package/dist/extensions/pi-subagents/test/support/fake-child-session.ts +122 -9
- package/dist/extensions/pi-subagents/test/support/foreign-workflow-steer-host.mjs +15 -7
- package/dist/extensions/pi-subagents/test/support/helpers.ts +11 -14
- package/dist/extensions/pi-subagents/test/support/isolated-temp-root.mjs +21 -3
- package/dist/extensions/pi-subagents/test/support/native-peer-loader.mjs +15 -0
- package/dist/extensions/pi-subagents/test/support/node-command.ts +29 -6
- package/dist/extensions/pi-subagents/test/support/notify-diagnostics-fixture.ts +5 -3
- package/dist/extensions/pi-subagents/test/support/single-execution-fixture.ts +7 -15
- package/dist/extensions/pi-subagents/test/support/watchdog-stable-host-loader.mjs +23 -0
- package/dist/extensions/pi-subagents/test/unit/acceptance-compaction.test.ts +3 -3
- package/dist/extensions/pi-subagents/test/unit/acceptance.test.ts +158 -155
- package/dist/extensions/pi-subagents/test/unit/active-async-capacity.test.ts +52 -1
- package/dist/extensions/pi-subagents/test/unit/advertised-agent-prompt.test.ts +21 -17
- package/dist/extensions/pi-subagents/test/unit/advertised-agent-refresh.test.ts +105 -36
- package/dist/extensions/pi-subagents/test/unit/advertisement-barrier.test.ts +151 -0
- package/dist/extensions/pi-subagents/test/unit/agent-disabled.test.ts +1 -2
- package/dist/extensions/pi-subagents/test/unit/agent-eject-disable.test.ts +33 -3
- package/dist/extensions/pi-subagents/test/unit/agent-end-auto-drain.test.ts +149 -0
- package/dist/extensions/pi-subagents/test/unit/agent-exclude-dirs.test.ts +246 -0
- package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +62 -87
- package/dist/extensions/pi-subagents/test/unit/agent-global-root-override.test.ts +86 -0
- package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +398 -48
- package/dist/extensions/pi-subagents/test/unit/agent-memory.test.ts +126 -1
- package/dist/extensions/pi-subagents/test/unit/agent-name-resolution.test.ts +75 -0
- package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +94 -42
- package/dist/extensions/pi-subagents/test/unit/async-execution.test.ts +73 -3
- package/dist/extensions/pi-subagents/test/unit/async-interrupt-action.test.ts +428 -2
- package/dist/extensions/pi-subagents/test/unit/async-permission-session.test.ts +4 -4
- package/dist/extensions/pi-subagents/test/unit/async-recovery-descriptor.test.ts +112 -1
- package/dist/extensions/pi-subagents/test/unit/async-result-timeout-evidence.test.ts +53 -0
- package/dist/extensions/pi-subagents/test/unit/async-resume.test.ts +92 -4
- package/dist/extensions/pi-subagents/test/unit/async-retention.test.ts +58 -6
- package/dist/extensions/pi-subagents/test/unit/async-run-history.test.ts +123 -0
- package/dist/extensions/pi-subagents/test/unit/async-spawn-package-dir.test.ts +203 -0
- package/dist/extensions/pi-subagents/test/unit/async-spawn-preload.test.ts +26 -35
- package/dist/extensions/pi-subagents/test/unit/async-status-projection.test.ts +185 -0
- package/dist/extensions/pi-subagents/test/unit/authority-policy.test.ts +9 -1
- package/dist/extensions/pi-subagents/test/unit/auto-drain.test.ts +106 -1
- package/dist/extensions/pi-subagents/test/unit/await-async-run.test.ts +202 -0
- package/dist/extensions/pi-subagents/test/unit/binary-async-spawn.test.ts +115 -0
- package/dist/extensions/pi-subagents/test/unit/binary-pi-spawn.test.ts +27 -0
- package/dist/extensions/pi-subagents/test/unit/calendar-schedule.test.ts +70 -0
- package/dist/extensions/pi-subagents/test/unit/capability-ceiling-agent-allowlist.test.ts +38 -0
- package/dist/extensions/pi-subagents/test/unit/chain-root-attachment.test.ts +10 -2
- package/dist/extensions/pi-subagents/test/unit/changelog-format.test.ts +11 -0
- package/dist/extensions/pi-subagents/test/unit/child-cache-retention.test.ts +87 -0
- package/dist/extensions/pi-subagents/test/unit/child-commands.test.ts +243 -0
- package/dist/extensions/pi-subagents/test/unit/child-external-job-bridge.test.ts +126 -0
- package/dist/extensions/pi-subagents/test/unit/child-launch-plan.test.ts +12 -1
- package/dist/extensions/pi-subagents/test/unit/child-lifecycle.test.ts +36 -0
- package/dist/extensions/pi-subagents/test/unit/child-runtime-config.test.ts +24 -0
- package/dist/extensions/pi-subagents/test/unit/child-session-commands.test.ts +162 -0
- package/dist/extensions/pi-subagents/test/unit/child-session-host-sdk.test.ts +226 -0
- package/dist/extensions/pi-subagents/test/unit/child-session-parent-providers.test.ts +200 -0
- package/dist/extensions/pi-subagents/test/unit/child-session-queued.test.ts +260 -0
- package/dist/extensions/pi-subagents/test/unit/child-tool-plan-permission-system.test.ts +3 -98
- package/dist/extensions/pi-subagents/test/unit/child-tool-plan.test.ts +222 -1
- package/dist/extensions/pi-subagents/test/unit/claude-code-adapter.test.ts +314 -0
- package/dist/extensions/pi-subagents/test/unit/claude-code-dispatch.test.ts +182 -0
- package/dist/extensions/pi-subagents/test/unit/codex-exec-adapter.test.ts +157 -0
- package/dist/extensions/pi-subagents/test/unit/command-action.test.ts +50 -0
- package/dist/extensions/pi-subagents/test/unit/compaction-resume.test.ts +25 -11
- package/dist/extensions/pi-subagents/test/unit/completion-replay.test.ts +3 -1
- package/dist/extensions/pi-subagents/test/unit/control-channel.test.ts +18 -0
- package/dist/extensions/pi-subagents/test/unit/control-notices.test.ts +7 -1
- package/dist/extensions/pi-subagents/test/unit/cursor-agent-adapter.test.ts +220 -0
- package/dist/extensions/pi-subagents/test/unit/default-extensions.test.ts +104 -32
- package/dist/extensions/pi-subagents/test/unit/delegation-api.test.ts +138 -1
- package/dist/extensions/pi-subagents/test/unit/disabled-features.test.ts +227 -0
- package/dist/extensions/pi-subagents/test/unit/doctor.test.ts +48 -9
- package/dist/extensions/pi-subagents/test/unit/dynamic-fanout.test.ts +7 -4
- package/dist/extensions/pi-subagents/test/unit/extension-lazy-loading.test.ts +21 -0
- package/dist/extensions/pi-subagents/test/unit/extension-maintenance-lifecycle.test.ts +66 -0
- package/dist/extensions/pi-subagents/test/unit/extension-module-preload.test.ts +49 -0
- package/dist/extensions/pi-subagents/test/unit/external-cli-runner.test.ts +104 -3
- package/dist/extensions/pi-subagents/test/unit/file-lease.test.ts +17 -0
- package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +316 -0
- package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +58 -7
- package/dist/extensions/pi-subagents/test/unit/fork-context.test.ts +25 -96
- package/dist/extensions/pi-subagents/test/unit/ghostty-inspector.test.ts +92 -0
- package/dist/extensions/pi-subagents/test/unit/global-npm-root.test.ts +108 -0
- package/dist/extensions/pi-subagents/test/unit/herdr-connection.test.ts +43 -0
- package/dist/extensions/pi-subagents/test/unit/herdr-external-adapters.test.ts +89 -0
- package/dist/extensions/pi-subagents/test/unit/herdr-inspector-bootstrap.test.ts +11 -20
- package/dist/extensions/pi-subagents/test/unit/herdr-inspector.test.ts +113 -19
- package/dist/extensions/pi-subagents/test/unit/herdr-machine.test.ts +161 -0
- package/dist/extensions/pi-subagents/test/unit/herdr-native-placement.test.ts +187 -0
- package/dist/extensions/pi-subagents/test/unit/herdr-session-roots-codec.test.ts +7 -12
- package/dist/extensions/pi-subagents/test/unit/herdr-shell-command.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/unit/herdr-status-bridge.test.ts +182 -87
- package/dist/extensions/pi-subagents/test/unit/host-peer-runtime-imports.test.ts +68 -49
- package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +295 -135
- package/dist/extensions/pi-subagents/test/unit/inspect-rpc.test.ts +3 -3
- package/dist/extensions/pi-subagents/test/unit/inspector-authority-policy.test.ts +144 -0
- package/dist/extensions/pi-subagents/test/unit/inspector-registration.test.ts +128 -0
- package/dist/extensions/pi-subagents/test/unit/intercom-bridge.test.ts +49 -1
- package/dist/extensions/pi-subagents/test/unit/mcp-direct-tool-grant.test.ts +74 -1
- package/dist/extensions/pi-subagents/test/unit/mcp-direct-tool-resolution.test.ts +112 -0
- package/dist/extensions/pi-subagents/test/unit/mission-global-projection.test.ts +215 -0
- package/dist/extensions/pi-subagents/test/unit/mission-goal-driver.test.ts +65 -1
- package/dist/extensions/pi-subagents/test/unit/mission-store.test.ts +2 -1
- package/dist/extensions/pi-subagents/test/unit/model-resolution-diagnostic.test.ts +78 -0
- package/dist/extensions/pi-subagents/test/unit/model-resolution.test.ts +153 -0
- package/dist/extensions/pi-subagents/test/unit/model-scope.test.ts +43 -1
- package/dist/extensions/pi-subagents/test/unit/mutation-evidence.test.ts +1 -21
- package/dist/extensions/pi-subagents/test/unit/native-supervisor-channel.test.ts +279 -2
- package/dist/extensions/pi-subagents/test/unit/nested-control-fanout.test.ts +73 -0
- package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +297 -3
- package/dist/extensions/pi-subagents/test/unit/notify-diagnostics.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/notify.test.ts +431 -23
- package/dist/extensions/pi-subagents/test/unit/opencode-session-headers.test.ts +32 -0
- package/dist/extensions/pi-subagents/test/unit/orca-progress-tabs.test.ts +89 -21
- package/dist/extensions/pi-subagents/test/unit/owned-process-tree.test.ts +31 -1
- package/dist/extensions/pi-subagents/test/unit/package-manifest.test.ts +18 -24
- package/dist/extensions/pi-subagents/test/unit/parent-wake.test.ts +206 -0
- package/dist/extensions/pi-subagents/test/unit/partial-output.test.ts +53 -0
- package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +216 -32
- package/dist/extensions/pi-subagents/test/unit/pi-spawn-host-root.test.ts +82 -0
- package/dist/extensions/pi-subagents/test/unit/pi-subagents-policy-guidance.test.ts +28 -0
- package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +193 -104
- package/dist/extensions/pi-subagents/test/unit/proactive-skills.test.ts +16 -1
- package/dist/extensions/pi-subagents/test/unit/process-terminal.test.ts +17 -1
- package/dist/extensions/pi-subagents/test/unit/profiles.test.ts +89 -9
- package/dist/extensions/pi-subagents/test/unit/prompt-audit-optional-peers.test.ts +6 -0
- package/dist/extensions/pi-subagents/test/unit/prompt-audit-provider-routing.test.ts +69 -0
- package/dist/extensions/pi-subagents/test/unit/prompt-template-bridge.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/unit/prompt-workflows.test.ts +23 -1
- package/dist/extensions/pi-subagents/test/unit/pruned-fork.test.ts +117 -3
- package/dist/extensions/pi-subagents/test/unit/public-execution.test.ts +35 -14
- package/dist/extensions/pi-subagents/test/unit/readonly-drain-observation.test.ts +3 -2
- package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +261 -9
- package/dist/extensions/pi-subagents/test/unit/reply-workflow-script.test.ts +37 -0
- package/dist/extensions/pi-subagents/test/unit/required-child-extensions.test.ts +114 -0
- package/dist/extensions/pi-subagents/test/unit/result-intercom.test.ts +11 -1
- package/dist/extensions/pi-subagents/test/unit/retained-children.test.ts +22 -2
- package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +125 -18
- package/dist/extensions/pi-subagents/test/unit/run-child-session.test.ts +230 -0
- package/dist/extensions/pi-subagents/test/unit/run-id-resolver.test.ts +50 -1
- package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +301 -4
- package/dist/extensions/pi-subagents/test/unit/runner-bootstrap.test.ts +182 -0
- package/dist/extensions/pi-subagents/test/unit/runner-http-dispatcher.test.ts +136 -0
- package/dist/extensions/pi-subagents/test/unit/runner-peer-loader.test.ts +68 -0
- package/dist/extensions/pi-subagents/test/unit/runner-peer-symlinks.test.ts +50 -0
- package/dist/extensions/pi-subagents/test/unit/running-tone.test.ts +13 -0
- package/dist/extensions/pi-subagents/test/unit/runtime-agent-registration.test.ts +155 -4
- package/dist/extensions/pi-subagents/test/unit/schedule-claim-initialization.test.ts +71 -0
- package/dist/extensions/pi-subagents/test/unit/schedule-claim-preservation.test.ts +98 -0
- package/dist/extensions/pi-subagents/test/unit/schedule-history-transactions.test.ts +201 -0
- package/dist/extensions/pi-subagents/test/unit/scheduled-mission.test.ts +317 -0
- package/dist/extensions/pi-subagents/test/unit/scheduled-runs.test.ts +412 -11
- package/dist/extensions/pi-subagents/test/unit/scheduled-store-root.test.ts +2 -8
- package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +70 -71
- package/dist/extensions/pi-subagents/test/unit/scripted-workflow.test.ts +748 -5
- package/dist/extensions/pi-subagents/test/unit/session-liveness-delivery.test.ts +337 -0
- package/dist/extensions/pi-subagents/test/unit/settings-atomic-save.test.ts +419 -0
- package/dist/extensions/pi-subagents/test/unit/settings-transactions.test.ts +88 -0
- package/dist/extensions/pi-subagents/test/unit/single-output.test.ts +13 -1
- package/dist/extensions/pi-subagents/test/unit/skills-disable-model-invocation.test.ts +164 -0
- package/dist/extensions/pi-subagents/test/unit/skills-fallback.test.ts +35 -2
- package/dist/extensions/pi-subagents/test/unit/slash-bridge.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/unit/stale-run-reconciler.test.ts +334 -9
- package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +170 -0
- package/dist/extensions/pi-subagents/test/unit/steering.test.ts +34 -5
- package/dist/extensions/pi-subagents/test/unit/structured-output-validation.test.ts +199 -0
- package/dist/extensions/pi-subagents/test/unit/structured-workflow-resources.test.ts +241 -0
- package/dist/extensions/pi-subagents/test/unit/subagent-control.test.ts +47 -38
- package/dist/extensions/pi-subagents/test/unit/subagent-cost.test.ts +97 -0
- package/dist/extensions/pi-subagents/test/unit/subagent-guide.test.ts +10 -0
- package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +343 -44
- package/dist/extensions/pi-subagents/test/unit/subagent-wait.test.ts +410 -11
- package/dist/extensions/pi-subagents/test/unit/supervisor-ask-registration.test.ts +459 -22
- package/dist/extensions/pi-subagents/test/unit/temp-paths.test.ts +43 -3
- package/dist/extensions/pi-subagents/test/unit/timeout-defaults.test.ts +11 -1
- package/dist/extensions/pi-subagents/test/unit/tool-activation-stale-peer.test.ts +32 -0
- package/dist/extensions/pi-subagents/test/unit/tool-activation.test.ts +313 -0
- package/dist/extensions/pi-subagents/test/unit/tool-budget.test.ts +14 -0
- package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +76 -89
- package/dist/extensions/pi-subagents/test/unit/typed-gate-output.test.ts +141 -0
- package/dist/extensions/pi-subagents/test/unit/upgrade-notice.test.ts +31 -0
- package/dist/extensions/pi-subagents/test/unit/usage-reconciliation-owners.test.ts +66 -0
- package/dist/extensions/pi-subagents/test/unit/usage-reconciliation.test.ts +23 -0
- package/dist/extensions/pi-subagents/test/unit/wait-completions.test.ts +195 -1
- package/dist/extensions/pi-subagents/test/unit/wait-subscriptions.test.ts +3 -1
- package/dist/extensions/pi-subagents/test/unit/watchdog-child-status.test.ts +48 -45
- package/dist/extensions/pi-subagents/test/unit/watchdog-compaction-scope.test.ts +94 -0
- package/dist/extensions/pi-subagents/test/unit/watchdog-diff-tool.test.ts +48 -3
- package/dist/extensions/pi-subagents/test/unit/watchdog-native-scheduling.test.ts +107 -0
- package/dist/extensions/pi-subagents/test/unit/watchdog-permission-arbiter.test.ts +95 -7
- package/dist/extensions/pi-subagents/test/unit/watchdog-register-child.test.ts +79 -0
- package/dist/extensions/pi-subagents/test/unit/watchdog-render.test.ts +7 -4
- package/dist/extensions/pi-subagents/test/unit/watchdog-review.test.ts +111 -24
- package/dist/extensions/pi-subagents/test/unit/watchdog-rules.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/watchdog-runtime.test.ts +283 -2
- package/dist/extensions/pi-subagents/test/unit/watchdog-scope.test.ts +3 -0
- package/dist/extensions/pi-subagents/test/unit/watchdog-settings.test.ts +12 -1
- package/dist/extensions/pi-subagents/test/unit/watchdog-stable-host-layout.test.ts +23 -0
- package/dist/extensions/pi-subagents/test/unit/watchdog-tool-actions.test.ts +30 -0
- package/dist/extensions/pi-subagents/test/unit/watchdog-turn-delta.test.ts +39 -2
- package/dist/extensions/pi-subagents/test/unit/widget-nested-render.test.ts +18 -1
- package/dist/extensions/pi-subagents/test/unit/workflow-chat-progress.test.ts +8 -4
- package/dist/extensions/pi-subagents/test/unit/workflow-child-summary.test.ts +10 -0
- package/dist/extensions/pi-subagents/test/unit/workflow-detach-reconcile.test.ts +6 -3
- package/dist/extensions/pi-subagents/test/unit/workflow-launch-params.test.ts +44 -1
- package/dist/extensions/pi-subagents/test/unit/workflow-receipt.test.ts +28 -1
- package/dist/extensions/pi-subagents/test/unit/workflow-revival.test.ts +85 -0
- package/dist/extensions/pi-subagents/test/unit/workflow-scripts-feature.test.ts +177 -0
- package/dist/extensions/pi-subagents/test/unit/workflow-terminal-proof.test.ts +8 -0
- package/dist/extensions/pi-subagents/test/unit/workflow-worktree-admission.test.ts +29 -0
- package/dist/extensions/pi-subagents/test/unit/worktree-cleanup-plan.test.ts +343 -4
- package/dist/extensions/pi-subagents/test/unit/worktree-lock.test.ts +123 -0
- package/dist/extensions/pi-subagents/test/unit/worktree.test.ts +252 -22
- package/dist/extensions/pi-subagents/tsconfig.build.json +13 -0
- package/dist/extensions/pi-tool-display/tests/custom-tool-overrides.test.ts +1 -1
- package/dist/extensions/pi-tool-display/tests/tool-overrides-config.test.ts +1 -1
- package/dist/extensions/pi-tool-display/tests/tool-overrides-mcp.test.ts +24 -1
- package/dist/extensions/pi-tool-display/tests/tool-overrides-registration.test.ts +6 -2
- package/dist/extensions/pi-web-agent/src/extension.ts +1 -5
- package/dist/extensions/pi-zentui/.github/workflows/ci.yml +67 -4
- package/dist/extensions/pi-zentui/AGENTS.md +3 -2
- package/dist/extensions/pi-zentui/README.md +60 -32
- package/dist/extensions/pi-zentui/docs/configuration.md +662 -51
- package/dist/extensions/pi-zentui/docs/footer-format.md +174 -5
- package/dist/extensions/pi-zentui/extensions/zentui/accent-rail-editor.ts +15 -4
- package/dist/extensions/pi-zentui/extensions/zentui/average-token-rate.ts +146 -0
- package/dist/extensions/pi-zentui/extensions/zentui/codex-quota-display.ts +34 -0
- package/dist/extensions/pi-zentui/extensions/zentui/codex-quota.ts +298 -0
- package/dist/extensions/pi-zentui/extensions/zentui/component-colors.ts +172 -0
- package/dist/extensions/pi-zentui/extensions/zentui/component-settings.ts +243 -0
- package/dist/extensions/pi-zentui/extensions/zentui/config.ts +851 -114
- package/dist/extensions/pi-zentui/extensions/zentui/custom-value-colors.ts +93 -0
- package/dist/extensions/pi-zentui/extensions/zentui/custom-variable-demand.ts +61 -0
- package/dist/extensions/pi-zentui/extensions/zentui/custom-variable-format.ts +80 -0
- package/dist/extensions/pi-zentui/extensions/zentui/custom-variables.ts +152 -0
- package/dist/extensions/pi-zentui/extensions/zentui/editor-metadata-format.ts +138 -23
- package/dist/extensions/pi-zentui/extensions/zentui/editor-mouse.ts +89 -0
- package/dist/extensions/pi-zentui/extensions/zentui/extension-status-controller.ts +148 -0
- package/dist/extensions/pi-zentui/extensions/zentui/extension-status-settings.ts +40 -0
- package/dist/extensions/pi-zentui/extensions/zentui/extension-status.ts +109 -1
- package/dist/extensions/pi-zentui/extensions/zentui/footer-format.ts +203 -23
- package/dist/extensions/pi-zentui/extensions/zentui/footer-layout.ts +80 -3
- package/dist/extensions/pi-zentui/extensions/zentui/footer-text.ts +1 -1
- package/dist/extensions/pi-zentui/extensions/zentui/footer.ts +432 -125
- package/dist/extensions/pi-zentui/extensions/zentui/format.ts +92 -4
- package/dist/extensions/pi-zentui/extensions/zentui/git.ts +47 -30
- package/dist/extensions/pi-zentui/extensions/zentui/github-status.ts +575 -0
- package/dist/extensions/pi-zentui/extensions/zentui/host-project-changes.ts +25 -0
- package/dist/extensions/pi-zentui/extensions/zentui/host-template-values.ts +29 -0
- package/dist/extensions/pi-zentui/extensions/zentui/icons.ts +53 -13
- package/dist/extensions/pi-zentui/extensions/zentui/index.ts +778 -258
- package/dist/extensions/pi-zentui/extensions/zentui/interaction-summary.ts +70 -5
- package/dist/extensions/pi-zentui/extensions/zentui/layered-editor.ts +55 -0
- package/dist/extensions/pi-zentui/extensions/zentui/live-context.ts +6 -1
- package/dist/extensions/pi-zentui/extensions/zentui/live-metadata-demand.ts +72 -0
- package/dist/extensions/pi-zentui/extensions/zentui/live-metadata-display.ts +21 -0
- package/dist/extensions/pi-zentui/extensions/zentui/live-metadata.ts +255 -0
- package/dist/extensions/pi-zentui/extensions/zentui/minimalist-editor.ts +476 -36
- package/dist/extensions/pi-zentui/extensions/zentui/minimalist-settings.ts +118 -0
- package/dist/extensions/pi-zentui/extensions/zentui/minimalist-template.ts +177 -0
- package/dist/extensions/pi-zentui/extensions/zentui/omp-editor-frame.ts +148 -0
- package/dist/extensions/pi-zentui/extensions/zentui/omp-statusline.ts +569 -0
- package/dist/extensions/pi-zentui/extensions/zentui/omp-template-lookups.ts +344 -0
- package/dist/extensions/pi-zentui/extensions/zentui/omp-template-metrics.ts +91 -0
- package/dist/extensions/pi-zentui/extensions/zentui/omp-template-modes.ts +323 -0
- package/dist/extensions/pi-zentui/extensions/zentui/omp-ui.ts +210 -0
- package/dist/extensions/pi-zentui/extensions/zentui/package-version.ts +30 -12
- package/dist/extensions/pi-zentui/extensions/zentui/project-demand.ts +46 -0
- package/dist/extensions/pi-zentui/extensions/zentui/project-discovery.ts +58 -0
- package/dist/extensions/pi-zentui/extensions/zentui/project-refresh.ts +10 -3
- package/dist/extensions/pi-zentui/extensions/zentui/project-state.ts +37 -0
- package/dist/extensions/pi-zentui/extensions/zentui/repository-root.ts +1 -0
- package/dist/extensions/pi-zentui/extensions/zentui/runtime.ts +119 -43
- package/dist/extensions/pi-zentui/extensions/zentui/selector-border.ts +40 -29
- package/dist/extensions/pi-zentui/extensions/zentui/settings-command.ts +1268 -722
- package/dist/extensions/pi-zentui/extensions/zentui/settings-keys.ts +59 -0
- package/dist/extensions/pi-zentui/extensions/zentui/settings-list-selection.ts +13 -0
- package/dist/extensions/pi-zentui/extensions/zentui/settings-previews.ts +11 -4
- package/dist/extensions/pi-zentui/extensions/zentui/state.ts +24 -11
- package/dist/extensions/pi-zentui/extensions/zentui/style.ts +6 -0
- package/dist/extensions/pi-zentui/extensions/zentui/telemetry.ts +113 -11
- package/dist/extensions/pi-zentui/extensions/zentui/thinking-experimental.ts +234 -46
- package/dist/extensions/pi-zentui/extensions/zentui/thinking-steps.ts +20 -5
- package/dist/extensions/pi-zentui/extensions/zentui/token-rate.ts +313 -0
- package/dist/extensions/pi-zentui/extensions/zentui/turn-summary-format.ts +59 -0
- package/dist/extensions/pi-zentui/extensions/zentui/turn-summary-rate.ts +52 -0
- package/dist/extensions/pi-zentui/extensions/zentui/ui.ts +640 -172
- package/dist/extensions/pi-zentui/extensions/zentui/user-message-styles.ts +72 -34
- package/dist/extensions/pi-zentui/extensions/zentui/user-message.ts +219 -34
- package/dist/extensions/pi-zentui/extensions/zentui/working-line.ts +495 -119
- package/dist/extensions/pi-zentui/omp.ts +157 -0
- package/dist/extensions/pi-zentui/package-lock.json +3762 -1507
- package/dist/extensions/pi-zentui/package.json +50 -12
- package/dist/extensions/pi-zentui/test/accent-rail-editor.test.ts +13 -2
- package/dist/extensions/pi-zentui/test/average-token-rate.test.ts +297 -0
- package/dist/extensions/pi-zentui/test/behavior-compatibility.mjs +89 -0
- package/dist/extensions/pi-zentui/test/codex-quota-lifecycle.test.ts +284 -0
- package/dist/extensions/pi-zentui/test/codex-quota-rendering.test.ts +466 -0
- package/dist/extensions/pi-zentui/test/codex-quota.test.ts +440 -0
- package/dist/extensions/pi-zentui/test/component-colors.test.ts +554 -0
- package/dist/extensions/pi-zentui/test/component-settings.test.ts +364 -0
- package/dist/extensions/pi-zentui/test/config-component-independence.test.ts +402 -0
- package/dist/extensions/pi-zentui/test/config-extension-status-choice.test.ts +233 -0
- package/dist/extensions/pi-zentui/test/config-hidden-extension-status-colors.test.ts +118 -0
- package/dist/extensions/pi-zentui/test/config-hidden-extension-status-placement.test.ts +142 -0
- package/dist/extensions/pi-zentui/test/config-minimalist-templates.test.ts +240 -0
- package/dist/extensions/pi-zentui/test/config-template-variables.test.ts +85 -0
- package/dist/extensions/pi-zentui/test/config.test.ts +80 -17
- package/dist/extensions/pi-zentui/test/custom-value-colors-integration.test.ts +453 -0
- package/dist/extensions/pi-zentui/test/custom-value-colors.test.ts +399 -0
- package/dist/extensions/pi-zentui/test/custom-variable-alias-prototypes.test.ts +177 -0
- package/dist/extensions/pi-zentui/test/custom-variable-consumers.test.ts +194 -0
- package/dist/extensions/pi-zentui/test/custom-variable-demand.test.ts +169 -0
- package/dist/extensions/pi-zentui/test/custom-variable-probe-reservation.test.ts +141 -0
- package/dist/extensions/pi-zentui/test/custom-variables-lifecycle.integration.test.ts +365 -0
- package/dist/extensions/pi-zentui/test/custom-variables.test.ts +330 -0
- package/dist/extensions/pi-zentui/test/editor-metadata-format.test.ts +121 -0
- package/dist/extensions/pi-zentui/test/editor-mouse.test.ts +507 -0
- package/dist/extensions/pi-zentui/test/editor-viewport-indicators.test.ts +247 -20
- package/dist/extensions/pi-zentui/test/extension-compliance.test.ts +204 -260
- package/dist/extensions/pi-zentui/test/extension-status-controller.test.ts +323 -0
- package/dist/extensions/pi-zentui/test/extension-status-lifecycle.integration.test.ts +466 -0
- package/dist/extensions/pi-zentui/test/extension-status-settings.test.ts +79 -0
- package/dist/extensions/pi-zentui/test/footer-alignment.test.ts +135 -0
- package/dist/extensions/pi-zentui/test/footer-authority.test.ts +69 -0
- package/dist/extensions/pi-zentui/test/footer-auto-compaction.test.ts +148 -0
- package/dist/extensions/pi-zentui/test/footer-format-cache.test.ts +186 -0
- package/dist/extensions/pi-zentui/test/footer-format.test.ts +154 -4
- package/dist/extensions/pi-zentui/test/footer-hidden.test.ts +312 -0
- package/dist/extensions/pi-zentui/test/footer-hyperlink.test.ts +22 -0
- package/dist/extensions/pi-zentui/test/footer-layout.test.ts +80 -0
- package/dist/extensions/pi-zentui/test/footer-thinking-level.test.ts +123 -0
- package/dist/extensions/pi-zentui/test/format.test.ts +75 -1
- package/dist/extensions/pi-zentui/test/git-probes.test.ts +182 -0
- package/dist/extensions/pi-zentui/test/github-status.test.ts +931 -0
- package/dist/extensions/pi-zentui/test/host-template-surfaces.test.ts +287 -0
- package/dist/extensions/pi-zentui/test/icons.test.ts +86 -16
- package/dist/extensions/pi-zentui/test/layered-editor.test.ts +53 -0
- package/dist/extensions/pi-zentui/test/live-context-integration.test.ts +154 -7
- package/dist/extensions/pi-zentui/test/live-context.test.ts +45 -0
- package/dist/extensions/pi-zentui/test/live-metadata-lifecycle.integration.test.ts +963 -0
- package/dist/extensions/pi-zentui/test/live-metadata.test.ts +767 -0
- package/dist/extensions/pi-zentui/test/minimalist-cache-hit-colors.test.ts +183 -0
- package/dist/extensions/pi-zentui/test/minimalist-editor.test.ts +222 -4
- package/dist/extensions/pi-zentui/test/minimalist-settings.test.ts +103 -0
- package/dist/extensions/pi-zentui/test/minimalist-templates.test.ts +489 -0
- package/dist/extensions/pi-zentui/test/omp-editor-composers.test.ts +324 -0
- package/dist/extensions/pi-zentui/test/omp-statusline.test.ts +579 -0
- package/dist/extensions/pi-zentui/test/omp-template-lookups.test.ts +630 -0
- package/dist/extensions/pi-zentui/test/omp-template-metrics.test.ts +72 -0
- package/dist/extensions/pi-zentui/test/omp-template-modes.test.ts +557 -0
- package/dist/extensions/pi-zentui/test/omp-ui.test.ts +93 -0
- package/dist/extensions/pi-zentui/test/package-contents.mjs +1 -0
- package/dist/extensions/pi-zentui/test/pi-version-policy.test.ts +37 -0
- package/dist/extensions/pi-zentui/test/project-demand-integration.test.ts +542 -0
- package/dist/extensions/pi-zentui/test/project-discovery.test.ts +412 -0
- package/dist/extensions/pi-zentui/test/project-refresh.test.ts +44 -0
- package/dist/extensions/pi-zentui/test/project-state.test.ts +38 -1
- package/dist/extensions/pi-zentui/test/responsive-dependencies.test.ts +7 -7
- package/dist/extensions/pi-zentui/test/runtime.test.ts +127 -2
- package/dist/extensions/pi-zentui/test/selesai-v030-gate.json +939 -0
- package/dist/extensions/pi-zentui/test/settings-command.test.ts +1330 -82
- package/dist/extensions/pi-zentui/test/settings-keys.test.ts +41 -0
- package/dist/extensions/pi-zentui/test/settings-list-selection.test.ts +88 -0
- package/dist/extensions/pi-zentui/test/settings-previews.test.ts +4 -1
- package/dist/extensions/pi-zentui/test/state.test.ts +15 -1
- package/dist/extensions/pi-zentui/test/telemetry-lifecycle-integration.test.ts +214 -12
- package/dist/extensions/pi-zentui/test/telemetry-snapshot.test.ts +246 -0
- package/dist/extensions/pi-zentui/test/thinking-experimental-cache.test.ts +246 -0
- package/dist/extensions/pi-zentui/test/thinking-experimental-rows.test.ts +22 -0
- package/dist/extensions/pi-zentui/test/thinking-experimental-tui.mjs +113 -51
- package/dist/extensions/pi-zentui/test/thinking-experimental.test.ts +576 -76
- package/dist/extensions/pi-zentui/test/thinking-steps.test.ts +23 -0
- package/dist/extensions/pi-zentui/test/token-rate.test.ts +450 -0
- package/dist/extensions/pi-zentui/test/turn-summary-format.test.ts +207 -0
- package/dist/extensions/pi-zentui/test/turn-summary-lifecycle.integration.test.ts +72 -5
- package/dist/extensions/pi-zentui/test/turn-summary-rate.test.ts +158 -0
- package/dist/extensions/pi-zentui/test/usage-lifecycle-integration.test.ts +421 -0
- package/dist/extensions/pi-zentui/test/usage-snapshot.test.ts +154 -0
- package/dist/extensions/pi-zentui/test/user-message-cache.test.ts +239 -0
- package/dist/extensions/pi-zentui/test/user-message-native-reduced-capabilities.test.ts +61 -0
- package/dist/extensions/pi-zentui/test/user-message-native.test.ts +447 -0
- package/dist/extensions/pi-zentui/test/user-message-styles.test.ts +2 -2
- package/dist/extensions/pi-zentui/test/working-line-editor-placement.test.ts +317 -0
- package/dist/extensions/pi-zentui/test/working-line-generation-cache.test.ts +238 -0
- package/dist/extensions/pi-zentui/test/working-line-lifecycle.integration.test.ts +674 -179
- package/dist/extensions/pi-zentui/test/working-line-message-ownership.test.ts +239 -0
- package/dist/extensions/pi-zentui/test/working-line-metric-animation.test.ts +284 -0
- package/dist/extensions/pi-zentui/test/working-line-placement.test.ts +298 -0
- package/dist/extensions/pi-zentui/test/working-line.test.ts +386 -18
- package/dist/extensions/pi-zentui/test/wrapped-editor-consumers.integration.test.ts +579 -0
- package/dist/extensions/pi-zentui/test/wrapped-editor-usage.integration.test.ts +298 -0
- package/dist/extensions/pi-zentui/tsconfig.json +1 -1
- package/dist/extensions/pi-zentui/vitest.host.config.ts +33 -0
- package/dist/extensions/question/index.ts +1 -5
- package/dist/extensions/rtk.test.ts +28 -15
- package/dist/extensions/rtk.ts +22 -22
- package/dist/extensions/skills-index/index.test.ts +99 -0
- package/dist/extensions/skills-index/index.ts +105 -0
- package/dist/extensions/skills-index/package.json +9 -0
- package/dist/extensions/tokenin-onboarding.ts +48 -208
- package/dist/extensions/tool-search/index.d.ts +11 -0
- package/dist/extensions/tool-search/index.js +14 -0
- package/dist/extensions/tool-search/tool.d.ts +91 -0
- package/dist/extensions/tool-search/tool.js +214 -0
- package/dist/index.d.ts +17 -9
- package/dist/index.js +11 -5
- package/dist/main.d.ts +4 -0
- package/dist/main.js +106 -42
- package/dist/migrations.js +4 -3
- package/dist/modes/index.d.ts +1 -0
- package/dist/modes/interactive/bug-report.js +4 -0
- package/dist/modes/interactive/components/armin.d.ts +3 -0
- package/dist/modes/interactive/components/armin.js +7 -5
- package/dist/modes/interactive/components/assistant-message.js +1 -1
- package/dist/modes/interactive/components/auth-url.d.ts +13 -0
- package/dist/modes/interactive/components/auth-url.js +36 -0
- package/dist/modes/interactive/components/bash-execution.d.ts +5 -1
- package/dist/modes/interactive/components/bash-execution.js +17 -14
- package/dist/modes/interactive/components/branch-summary-message.d.ts +2 -1
- package/dist/modes/interactive/components/branch-summary-message.js +5 -2
- package/dist/modes/interactive/components/compaction-summary-message.d.ts +2 -1
- package/dist/modes/interactive/components/compaction-summary-message.js +5 -2
- package/dist/modes/interactive/components/config-selector.js +13 -3
- package/dist/modes/interactive/components/custom-editor.js +7 -0
- package/dist/modes/interactive/components/custom-entry.d.ts +3 -1
- package/dist/modes/interactive/components/custom-entry.js +8 -2
- package/dist/modes/interactive/components/custom-message.js +1 -0
- package/dist/modes/interactive/components/first-time-setup.d.ts +4 -4
- package/dist/modes/interactive/components/first-time-setup.js +8 -2
- package/dist/modes/interactive/components/footer.d.ts +7 -0
- package/dist/modes/interactive/components/footer.js +44 -4
- package/dist/modes/interactive/components/index.d.ts +0 -1
- package/dist/modes/interactive/components/index.js +0 -1
- package/dist/modes/interactive/components/login-dialog.d.ts +2 -0
- package/dist/modes/interactive/components/login-dialog.js +11 -5
- package/dist/modes/interactive/components/mermaid.d.ts +10 -0
- package/dist/modes/interactive/components/mermaid.js +74 -0
- package/dist/modes/interactive/components/model-selector.d.ts +14 -9
- package/dist/modes/interactive/components/model-selector.js +79 -31
- package/dist/modes/interactive/components/oauth-selector.d.ts +8 -2
- package/dist/modes/interactive/components/oauth-selector.js +24 -21
- package/dist/modes/interactive/components/pi-logo.d.ts +18 -0
- package/dist/modes/interactive/components/pi-logo.js +36 -0
- package/dist/modes/interactive/components/radius-login-selector.d.ts +14 -0
- package/dist/modes/interactive/components/radius-login-selector.js +84 -0
- package/dist/modes/interactive/components/scoped-models-selector.d.ts +4 -0
- package/dist/modes/interactive/components/scoped-models-selector.js +26 -0
- package/dist/modes/interactive/components/settings-selector.d.ts +8 -11
- package/dist/modes/interactive/components/settings-selector.js +60 -102
- package/dist/modes/interactive/components/skill-invocation-message.d.ts +2 -1
- package/dist/modes/interactive/components/skill-invocation-message.js +5 -2
- package/dist/modes/interactive/components/themed-text.d.ts +16 -0
- package/dist/modes/interactive/components/themed-text.js +28 -0
- package/dist/modes/interactive/components/tool-execution.d.ts +11 -18
- package/dist/modes/interactive/components/tool-execution.js +34 -47
- package/dist/modes/interactive/components/tree-selector.js +7 -0
- package/dist/modes/interactive/components/user-message.d.ts +3 -1
- package/dist/modes/interactive/components/user-message.js +14 -6
- package/dist/modes/interactive/components/visual-truncate.d.ts +27 -3
- package/dist/modes/interactive/components/visual-truncate.js +39 -6
- package/dist/modes/interactive/external-editor.js +2 -1
- package/dist/modes/interactive/interactive-mode.d.ts +41 -8
- package/dist/modes/interactive/interactive-mode.js +854 -492
- package/dist/modes/interactive/program-status-reporter.d.ts +33 -0
- package/dist/modes/interactive/program-status-reporter.js +109 -0
- package/dist/modes/interactive/theme/dark.json +59 -72
- package/dist/modes/interactive/theme/light.json +57 -69
- package/dist/modes/interactive/theme/system-theme.d.ts +54 -0
- package/dist/modes/interactive/theme/system-theme.js +545 -0
- package/dist/modes/interactive/theme/theme-controller.d.ts +46 -6
- package/dist/modes/interactive/theme/theme-controller.js +127 -47
- package/dist/modes/interactive/theme/theme-json.d.ts +1 -0
- package/dist/modes/interactive/theme/theme-json.js +3 -1
- package/dist/modes/interactive/theme/theme-schema.json +7 -2
- package/dist/modes/interactive/theme/theme.d.ts +66 -39
- package/dist/modes/interactive/theme/theme.js +243 -320
- package/dist/modes/interactive/tui-renderer.d.ts +2 -1
- package/dist/modes/interactive/tui-renderer.js +1 -0
- package/dist/modes/json-event.d.ts +33 -0
- package/dist/modes/json-event.js +28 -0
- package/dist/modes/print-mode.js +12 -2
- package/dist/modes/rpc/rpc-client.d.ts +11 -19
- package/dist/modes/rpc/rpc-client.js +52 -35
- package/dist/modes/rpc/rpc-mode.js +11 -26
- package/dist/modes/rpc/rpc-types.d.ts +12 -23
- package/dist/package-manager-cli.js +16 -5
- package/dist/rpc-entry.js +1 -0
- package/dist/skills/pi-subagents/SKILL.md +109 -35
- package/dist/skills/pi-subagents/references/constraints-and-recipes.md +38 -238
- package/dist/skills/pi-subagents/references/execution-controls.md +181 -83
- package/dist/skills/pi-subagents/references/management-authoring-rpc.md +9 -9
- package/dist/skills/pi-subagents/references/multi-lane-orchestration.md +24 -2
- package/dist/skills/pi-subagents/references/prompting-and-roles.md +121 -91
- package/dist/skills/pi-subagents/references/review-and-validation.md +73 -0
- package/dist/utils/ansi.d.ts +8 -0
- package/dist/utils/ansi.js +30 -11
- package/dist/utils/clipboard-image.js +14 -17
- package/dist/utils/clipboard.d.ts +2 -0
- package/dist/utils/clipboard.js +17 -11
- package/dist/utils/frontmatter.js +2 -1
- package/dist/utils/image-convert.d.ts +12 -0
- package/dist/utils/image-convert.js +45 -6
- package/dist/utils/image-resize-core.d.ts +12 -0
- package/dist/utils/image-resize-core.js +5 -0
- package/dist/utils/image-resize-worker.js +3 -2
- package/dist/utils/image-resize.js +9 -10
- package/dist/utils/mime.js +1 -1
- package/dist/utils/output-files.d.ts +14 -0
- package/dist/utils/output-files.js +29 -0
- package/dist/utils/paths.d.ts +6 -3
- package/dist/utils/paths.js +28 -5
- package/dist/utils/shell.d.ts +1 -3
- package/dist/utils/shell.js +3 -30
- package/dist/utils/syntax-highlight.d.ts +1 -0
- package/dist/utils/syntax-highlight.js +68 -2
- package/dist/utils/tool-result-images.d.ts +20 -0
- package/dist/utils/tool-result-images.js +47 -0
- package/dist/utils/tools-manager.d.ts +5 -0
- package/dist/utils/tools-manager.js +6 -6
- package/dist/utils/version-check.d.ts +4 -0
- package/dist/utils/version-check.js +20 -2
- package/docs/cli-integration.md +104 -0
- package/docs/cli.md +333 -0
- package/docs/codemode.md +230 -0
- package/docs/configuration.md +47 -0
- package/docs/environment-variables.md +5 -0
- package/docs/extensions.md +107 -30
- package/docs/json.md +8 -4
- package/docs/keybindings.md +10 -10
- package/docs/mcp.md +262 -0
- package/docs/models.md +104 -3
- package/docs/providers.md +20 -2
- package/docs/rpc.md +13 -12
- package/docs/sdk.md +41 -33
- package/docs/security.md +21 -20
- package/docs/settings.md +18 -46
- package/docs/terminal-setup.md +14 -0
- package/docs/virtual-models.md +114 -0
- package/examples/extensions/jev-router.ts +113 -0
- package/examples/extensions/tokenin-usage-widget.ts +124 -0
- package/examples/rpc-client.ts +35 -0
- package/examples/sdk/14-codemode-mcp.ts +67 -0
- package/package.json +15 -8
- package/dist/core/agent-session-auto-handoff.test.js +0 -195
- package/dist/core/built-in-extensions.d.ts +0 -2
- package/dist/core/built-in-extensions.js +0 -2
- package/dist/core/llama/provider.js +0 -143
- package/dist/core/settings-manager-auto-handoff.test.d.ts +0 -1
- package/dist/core/settings-manager-auto-handoff.test.js +0 -53
- package/dist/extensions/capability-gateway/catalog.ts +0 -177
- package/dist/extensions/capability-gateway/index.test.ts +0 -226
- package/dist/extensions/capability-gateway/index.ts +0 -669
- package/dist/extensions/capability-gateway/integration.test.ts +0 -803
- package/dist/extensions/capability-gateway/package.json +0 -16
- package/dist/extensions/capability-gateway/routing.test.ts +0 -574
- package/dist/extensions/capability-gateway/routing.ts +0 -403
- package/dist/extensions/pi-subagents/runner-server-preload.mjs +0 -13
- package/dist/extensions/pi-subagents/src/runs/shared/completion-evidence.ts +0 -89
- package/dist/extensions/pi-subagents/src/runs/shared/completion-guard.ts +0 -259
- package/dist/extensions/pi-subagents/src/runs/shared/llm-intent-arbiter.ts +0 -312
- package/dist/extensions/pi-subagents/src/runs/shared/model-exclusions.ts +0 -374
- package/dist/extensions/pi-subagents/src/runs/shared/readonly-model-continuation.ts +0 -69
- package/dist/extensions/pi-subagents/src/runs/shared/readonly-session-evidence.ts +0 -307
- package/dist/extensions/pi-subagents/src/runs/shared/task-intent.ts +0 -211
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/bun/cli.d.ts +0 -3
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/bun/register-bedrock.d.ts +0 -2
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/bun/restore-sandbox-env.d.ts +0 -17
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/args.d.ts +0 -57
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/config-selector.d.ts +0 -16
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/file-processor.d.ts +0 -15
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/initial-message.d.ts +0 -18
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/list-models.d.ts +0 -9
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/project-trust.d.ts +0 -10
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/session-picker.d.ts +0 -10
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/startup-ui.d.ts +0 -20
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli.d.ts +0 -3
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/config.d.ts +0 -96
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/agent-session-runtime.d.ts +0 -119
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/agent-session-services.d.ts +0 -85
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/agent-session.d.ts +0 -620
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/auth-guidance.d.ts +0 -5
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/auth-storage.d.ts +0 -56
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/bash-executor.d.ts +0 -32
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/cache-stats.d.ts +0 -49
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/branch-summarization.d.ts +0 -93
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/compaction.d.ts +0 -128
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/index.d.ts +0 -7
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/utils.d.ts +0 -38
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/defaults.d.ts +0 -3
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/diagnostics.d.ts +0 -15
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/event-bus.d.ts +0 -9
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/exec.d.ts +0 -29
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/experimental.d.ts +0 -2
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/export-html/ansi-to-html.d.ts +0 -22
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/export-html/index.d.ts +0 -37
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/export-html/tool-renderer.d.ts +0 -34
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/index.d.ts +0 -12
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/loader.d.ts +0 -23
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/runner.d.ts +0 -171
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/types.d.ts +0 -1261
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/wrapper.d.ts +0 -20
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/footer-data-provider.d.ts +0 -54
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/http-dispatcher.d.ts +0 -22
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/index.d.ts +0 -13
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/keybindings.d.ts +0 -358
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/messages.d.ts +0 -77
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-config.d.ts +0 -512
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-registry.d.ts +0 -43
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-resolver.d.ts +0 -121
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-runtime.d.ts +0 -82
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/models-store.d.ts +0 -17
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/output-guard.d.ts +0 -7
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/package-manager.d.ts +0 -210
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/project-trust.d.ts +0 -15
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/prompt-templates.d.ts +0 -54
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/provider-attribution.d.ts +0 -4
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/provider-composer.d.ts +0 -55
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/radius.d.ts +0 -2
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/remote-catalog-provider.d.ts +0 -5
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/resolve-config-value.d.ts +0 -30
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/resource-loader.d.ts +0 -206
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/runtime-credentials.d.ts +0 -15
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/sdk.d.ts +0 -106
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/session-cwd.d.ts +0 -19
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/session-manager.d.ts +0 -356
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/settings-manager.d.ts +0 -297
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/skills.d.ts +0 -60
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/slash-commands.d.ts +0 -15
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/source-info.d.ts +0 -18
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/system-prompt.d.ts +0 -28
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/telemetry.d.ts +0 -3
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/timings.d.ts +0 -10
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/bash.d.ts +0 -68
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/edit-diff.d.ts +0 -106
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/edit.d.ts +0 -51
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/file-mutation-queue.d.ts +0 -6
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/find.d.ts +0 -35
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/grep.d.ts +0 -37
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/index.d.ts +0 -40
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/ls.d.ts +0 -37
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/output-accumulator.d.ts +0 -52
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/path-utils.d.ts +0 -10
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/read.d.ts +0 -35
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/render-utils.d.ts +0 -24
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/tool-definition-wrapper.d.ts +0 -14
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/truncate.d.ts +0 -70
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/write.d.ts +0 -26
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/trust-manager.d.ts +0 -36
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/usage-totals.d.ts +0 -19
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/client.d.ts +0 -61
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/huggingface.d.ts +0 -23
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/index.d.ts +0 -3
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/provider.d.ts +0 -10
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/ui.d.ts +0 -42
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/index.d.ts +0 -35
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/main.d.ts +0 -12
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/migrations.d.ts +0 -33
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/index.d.ts +0 -9
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/armin.d.ts +0 -34
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/assistant-message.d.ts +0 -22
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/bash-execution.d.ts +0 -34
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/bordered-loader.d.ts +0 -16
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/branch-summary-message.d.ts +0 -16
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/compaction-summary-message.d.ts +0 -16
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/config-selector.d.ts +0 -102
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/countdown-timer.d.ts +0 -14
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/custom-editor.d.ts +0 -21
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/custom-entry.d.ts +0 -19
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/custom-message.d.ts +0 -20
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/daxnuts.d.ts +0 -23
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/diff.d.ts +0 -12
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/dynamic-border.d.ts +0 -15
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/earendil-announcement.d.ts +0 -5
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/extension-editor.d.ts +0 -22
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/extension-input.d.ts +0 -23
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/extension-selector.d.ts +0 -26
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/first-time-setup.d.ts +0 -25
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/footer.d.ts +0 -32
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/index.d.ts +0 -34
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/keybinding-hints.d.ts +0 -13
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/login-dialog.d.ts +0 -52
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/model-selector.d.ts +0 -54
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/oauth-selector.d.ts +0 -33
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/scoped-models-selector.d.ts +0 -42
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/session-selector-search.d.ts +0 -23
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/session-selector.d.ts +0 -95
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/settings-selector.d.ts +0 -77
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/show-images-selector.d.ts +0 -10
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/skill-invocation-message.d.ts +0 -17
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/status-indicator.d.ts +0 -28
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/theme-selector.d.ts +0 -11
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/thinking-selector.d.ts +0 -11
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/tool-execution.d.ts +0 -63
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/tree-selector.d.ts +0 -94
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/trust-selector.d.ts +0 -23
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/user-message-selector.d.ts +0 -30
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/user-message.d.ts +0 -14
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/visual-truncate.d.ts +0 -24
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/interactive-mode.d.ts +0 -394
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/model-search.d.ts +0 -12
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/theme/theme-controller.d.ts +0 -29
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/theme/theme.d.ts +0 -120
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/print-mode.d.ts +0 -28
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/jsonl.d.ts +0 -17
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/rpc-client.d.ts +0 -246
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/rpc-mode.d.ts +0 -20
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/rpc-types.d.ts +0 -457
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/package-manager-cli.d.ts +0 -8
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/rpc-entry.d.ts +0 -3
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/ansi.d.ts +0 -2
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/changelog.d.ts +0 -22
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/child-process.d.ts +0 -18
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/clipboard-image.d.ts +0 -11
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/clipboard-native.d.ts +0 -11
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/clipboard.d.ts +0 -4
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/deprecation.d.ts +0 -4
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/exif-orientation.d.ts +0 -5
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/frontmatter.d.ts +0 -8
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/fs-watch.d.ts +0 -5
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/git.d.ts +0 -26
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/html.d.ts +0 -7
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-convert.d.ts +0 -10
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-process.d.ts +0 -18
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-resize-core.d.ts +0 -30
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-resize-worker.d.ts +0 -2
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-resize.d.ts +0 -16
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/json.d.ts +0 -3
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/mime.d.ts +0 -3
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/open-browser.d.ts +0 -9
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/paths.d.ts +0 -31
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/photon.d.ts +0 -21
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/pi-user-agent.d.ts +0 -2
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/shell.d.ts +0 -31
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/sleep.d.ts +0 -5
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/syntax-highlight.d.ts +0 -12
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/tools-manager.d.ts +0 -3
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/version-check.d.ts +0 -15
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/windows-self-update.d.ts +0 -3
- package/dist/extensions/pi-subagents/test/smoke/pi085-child.ts +0 -31
- package/dist/extensions/pi-subagents/test/smoke/pi085-clean-install.mjs +0 -74
- package/dist/extensions/pi-subagents/test/unit/completion-evidence.test.ts +0 -150
- package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +0 -766
- package/dist/extensions/pi-subagents/test/unit/llm-intent-arbiter.test.ts +0 -327
- package/dist/extensions/pi-subagents/test/unit/model-exclusions.test.ts +0 -309
- package/dist/extensions/pi-subagents/test/unit/model-fallback.test.ts +0 -1093
- package/dist/extensions/pi-subagents/test/unit/readonly-model-continuation.test.ts +0 -94
- package/dist/extensions/pi-subagents/test/unit/readonly-session-evidence.test.ts +0 -1329
- package/dist/extensions/pi-subagents/test/unit/task-intent.test.ts +0 -153
- package/dist/extensions/pi-zentui/extensions/zentui/accent-rail-layout-patch.ts +0 -457
- package/dist/extensions/pi-zentui/test/accent-rail-layout-patch.test.ts +0 -669
- package/dist/extensions/pi-zentui/test/thinking-experimental-docs.test.ts +0 -51
- package/dist/modes/interactive/components/daxnuts.d.ts +0 -22
- package/dist/modes/interactive/components/daxnuts.js +0 -139
- /package/dist/core/{agent-session-auto-handoff.test.d.ts → agent-session-custom-tools.test.d.ts} +0 -0
- /package/dist/{core → extensions}/llama/huggingface.d.ts +0 -0
- /package/dist/{core → extensions}/llama/huggingface.js +0 -0
- /package/dist/{core → extensions}/llama/index.d.ts +0 -0
- /package/dist/{core → extensions}/llama/ui.d.ts +0 -0
- /package/dist/{core → extensions}/llama/ui.js +0 -0
|
@@ -2,27 +2,30 @@
|
|
|
2
2
|
* Interactive mode for the coding agent.
|
|
3
3
|
* Handles TUI rendering and user interaction, delegating business logic to AgentSession.
|
|
4
4
|
*/
|
|
5
|
+
import * as crypto from "node:crypto";
|
|
5
6
|
import * as fs from "node:fs";
|
|
6
7
|
import * as os from "node:os";
|
|
7
8
|
import * as path from "node:path";
|
|
8
9
|
import { isRetryableAssistantError, } from "@earendil-works/pi-ai/compat";
|
|
9
10
|
import * as TuiLayouts from "@earendil-works/pi-tui";
|
|
10
|
-
import { CombinedAutocompleteProvider, Container, fuzzyFilter, Markdown, matchesKey, Spacer, setCapabilityOverrides, setKeybindings, Text, TruncatedText, TuiAltScreen, TuiMainScreen, visibleWidth, } from "@earendil-works/pi-tui";
|
|
11
|
+
import { CombinedAutocompleteProvider, Container, fuzzyFilter, getCapabilities, hyperlink, Markdown, matchesKey, Spacer, setCapabilityOverrides, setKeybindings, Text, TruncatedText, TuiAltScreen, TuiMainScreen, visibleWidth, } from "@earendil-works/pi-tui";
|
|
11
12
|
import chalk from "chalk";
|
|
12
|
-
import { spawn
|
|
13
|
-
import { APP_NAME, APP_TITLE, CONFIG_DIR_NAME, getAgentDir, getAuthPath, getBundledDefaultsDir, getDebugLogPath, getDocsPath,
|
|
13
|
+
import { spawn } from "child_process";
|
|
14
|
+
import { APP_NAME, APP_TITLE, CONFIG_DIR_NAME, detectInstallChange, getAgentDir, getAuthPath, getBundledDefaultsDir, getDebugLogPath, getDocsPath, getUpdateInstruction, PACKAGE_NAME, VERSION, } from "../../config.js";
|
|
14
15
|
import { parseSkillBlocks } from "../../core/agent-session.js";
|
|
15
16
|
import { SessionImportFileNotFoundError } from "../../core/agent-session-runtime.js";
|
|
16
17
|
import { CACHE_TTL_MS, collectCacheMisses, computeCacheWaste, detectCacheMiss, } from "../../core/cache-stats.js";
|
|
17
18
|
import { formatCacheWarmingStatus, formatCacheWarmingUsage } from "../../core/cache-warmer.js";
|
|
18
|
-
import { recordCrash, takeUnnotifiedCrash } from "../../core/crash-log.js";
|
|
19
|
+
import { findExtensionStackMatches, recordCrash, takeUnnotifiedCrash } from "../../core/crash-log.js";
|
|
19
20
|
import { DEFAULT_THINKING_LEVEL, THINKING_LEVEL_OPTIONS } from "../../core/defaults.js";
|
|
20
21
|
import { FooterDataProvider } from "../../core/footer-data-provider.js";
|
|
21
22
|
import { configureHttpDispatcher, formatHttpIdleTimeoutMs } from "../../core/http-dispatcher.js";
|
|
22
23
|
import { KeybindingsManager } from "../../core/keybindings.js";
|
|
23
|
-
import { createCompactionSummaryMessage } from "../../core/messages.js";
|
|
24
|
-
import { defaultModelPerProvider, findExactModelReferenceMatch,
|
|
24
|
+
import { createCompactionSummaryMessage, createCustomMessage } from "../../core/messages.js";
|
|
25
|
+
import { defaultModelPerProvider, findExactModelReferenceMatch, resolveModelScopeFromModels, } from "../../core/model-resolver.js";
|
|
26
|
+
import { CredentialSynchronizationError } from "../../core/model-runtime.js";
|
|
25
27
|
import { DefaultPackageManager } from "../../core/package-manager.js";
|
|
28
|
+
import { RADIUS_MCP_URL, RADIUS_PROVIDER_ID } from "../../core/radius.js";
|
|
26
29
|
import { formatMissingSessionCwdPrompt, MissingSessionCwdError } from "../../core/session-cwd.js";
|
|
27
30
|
import { SessionManager, sessionEntryToContextMessages, } from "../../core/session-manager.js";
|
|
28
31
|
import { buildGitCommandPrompt, GIT_COMMAND_MODES } from "../../core/git-command.js";
|
|
@@ -31,14 +34,16 @@ import { isInstallTelemetryEnabled } from "../../core/telemetry.js";
|
|
|
31
34
|
import { withBuiltInRenderers } from "../../core/tools/renderers/index.js";
|
|
32
35
|
import { hasTrustRequiringProjectResources, ProjectTrustStore } from "../../core/trust-manager.js";
|
|
33
36
|
import { formatCost, getUsageCostBreakdown } from "../../core/usage-totals.js";
|
|
37
|
+
import { addMcpServerConfig, loadMcpConfig } from "../../extensions/mcp/config.js";
|
|
34
38
|
import { getChangelogPath, getNewEntries, normalizeChangelogLinks, parseChangelog } from "../../utils/changelog.js";
|
|
35
|
-
import { copyToClipboard, readClipboardText } from "../../utils/clipboard.js";
|
|
39
|
+
import { copyToClipboard, readClipboardFilePaths, readClipboardText } from "../../utils/clipboard.js";
|
|
36
40
|
import { extensionForImageMimeType, readClipboardImage } from "../../utils/clipboard-image.js";
|
|
37
41
|
import { parseGitUrl } from "../../utils/git.js";
|
|
38
|
-
import {
|
|
42
|
+
import { ensurePngTranscoder } from "../../utils/image-convert.js";
|
|
39
43
|
import { getCwdRelativePath } from "../../utils/paths.js";
|
|
40
44
|
import { getPiUserAgent } from "../../utils/pi-user-agent.js";
|
|
41
45
|
import { killTrackedDetachedChildren } from "../../utils/shell.js";
|
|
46
|
+
import { loadAllHighlightLanguages } from "../../utils/syntax-highlight.js";
|
|
42
47
|
import { ensureTool } from "../../utils/tools-manager.js";
|
|
43
48
|
import { checkForNewPiVersion } from "../../utils/version-check.js";
|
|
44
49
|
import { reportBug } from "./bug-report.js";
|
|
@@ -46,13 +51,11 @@ import { createChatViewport } from "./chat-viewport.js";
|
|
|
46
51
|
import { ArminComponent } from "./components/armin.js";
|
|
47
52
|
import { AssistantMessageComponent } from "./components/assistant-message.js";
|
|
48
53
|
import { BashExecutionComponent } from "./components/bash-execution.js";
|
|
49
|
-
import { BorderedLoader } from "./components/bordered-loader.js";
|
|
50
54
|
import { BranchSummaryMessageComponent } from "./components/branch-summary-message.js";
|
|
51
55
|
import { CompactionSummaryMessageComponent } from "./components/compaction-summary-message.js";
|
|
52
56
|
import { CustomEditor } from "./components/custom-editor.js";
|
|
53
57
|
import { CustomEntryComponent } from "./components/custom-entry.js";
|
|
54
58
|
import { CustomMessageComponent } from "./components/custom-message.js";
|
|
55
|
-
import { DaxnutsComponent } from "./components/daxnuts.js";
|
|
56
59
|
import { DynamicBorder } from "./components/dynamic-border.js";
|
|
57
60
|
import { StartupBox } from "./components/startup-box.js";
|
|
58
61
|
import { EarendilAnnouncementComponent } from "./components/earendil-announcement.js";
|
|
@@ -62,22 +65,28 @@ import { ExtensionSelectorComponent } from "./components/extension-selector.js";
|
|
|
62
65
|
import { FooterComponent, formatTokens } from "./components/footer.js";
|
|
63
66
|
import { formatKeyText, keyDisplayText, keyHint, keyText, rawKeyHint } from "./components/keybinding-hints.js";
|
|
64
67
|
import { LoginDialogComponent } from "./components/login-dialog.js";
|
|
68
|
+
import { createMermaidMarkdownTransformer } from "./components/mermaid.js";
|
|
65
69
|
import { ModelSelectorComponent } from "./components/model-selector.js";
|
|
66
|
-
import { formatAuthSelectorProviderType, OAuthSelectorComponent, } from "./components/oauth-selector.js";
|
|
70
|
+
import { formatAuthSelectorProviderStatus, formatAuthSelectorProviderType, OAuthSelectorComponent, } from "./components/oauth-selector.js";
|
|
71
|
+
import { createLoginMenuSelector } from "./components/radius-login-selector.js";
|
|
67
72
|
import { ScopedModelsSelectorComponent } from "./components/scoped-models-selector.js";
|
|
68
73
|
import { SessionSelectorComponent } from "./components/session-selector.js";
|
|
69
74
|
import { SettingsSelectorComponent } from "./components/settings-selector.js";
|
|
70
75
|
import { SkillInvocationMessageComponent } from "./components/skill-invocation-message.js";
|
|
71
76
|
import { BranchSummaryStatusIndicator, CompactionStatusIndicator, IdleStatus, ImageCaptioningStatusIndicator, RetryStatusIndicator, WorkingStatusIndicator, } from "./components/status-indicator.js";
|
|
77
|
+
import { ThemedText } from "./components/themed-text.js";
|
|
78
|
+
import { ThinkingSelectorComponent } from "./components/thinking-selector.js";
|
|
72
79
|
import { ToolExecutionComponent } from "./components/tool-execution.js";
|
|
73
80
|
import { TreeSelectorComponent } from "./components/tree-selector.js";
|
|
74
81
|
import { TrustSelectorComponent } from "./components/trust-selector.js";
|
|
75
82
|
import { UserMessageComponent } from "./components/user-message.js";
|
|
76
83
|
import { UserMessageSelectorComponent } from "./components/user-message-selector.js";
|
|
77
84
|
import { editInExternalEditor } from "./external-editor.js";
|
|
78
|
-
import { getModelSearchText } from "./model-search.js";
|
|
79
85
|
import { refreshModelCatalogs } from "./model-catalog-refresh.js";
|
|
80
|
-
import {
|
|
86
|
+
import { getModelSearchText } from "./model-search.js";
|
|
87
|
+
import { ProgramStatusReporter } from "./program-status-reporter.js";
|
|
88
|
+
import { shareSession } from "./session-share.js";
|
|
89
|
+
import { getAvailableThemes, getAvailableThemesWithPaths, getEditorTheme, getMarkdownTheme, getThemeByName, onThemeChange, SYSTEM_THEME_NAME, setRegisteredThemes, stopThemeWatcher, Theme, theme, } from "./theme/theme.js";
|
|
81
90
|
import { InteractiveThemeController } from "./theme/theme-controller.js";
|
|
82
91
|
import { createInteractiveTui, createInteractiveTuiReference } from "./tui-renderer.js";
|
|
83
92
|
export { createInteractiveTui, createInteractiveTuiReference } from "./tui-renderer.js";
|
|
@@ -90,16 +99,26 @@ function isWorkingStatusEditor(editor) {
|
|
|
90
99
|
function isExpandable(obj) {
|
|
91
100
|
return typeof obj === "object" && obj !== null && "setExpanded" in obj && typeof obj.setExpanded === "function";
|
|
92
101
|
}
|
|
93
|
-
class ExpandableText extends
|
|
94
|
-
|
|
95
|
-
getExpandedText;
|
|
102
|
+
class ExpandableText extends ThemedText {
|
|
103
|
+
state;
|
|
96
104
|
constructor(getCollapsedText, getExpandedText, expanded = false, paddingX = 0, paddingY = 0) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
this.
|
|
105
|
+
const state = { expanded };
|
|
106
|
+
super(() => (state.expanded ? getExpandedText() : getCollapsedText()), paddingX, paddingY);
|
|
107
|
+
this.state = state;
|
|
100
108
|
}
|
|
101
109
|
setExpanded(expanded) {
|
|
102
|
-
this.
|
|
110
|
+
this.state.expanded = expanded;
|
|
111
|
+
this.invalidate();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/** The built-in header. Clicking its logo (the first two lines, after one column of padding) plays an easter egg. */
|
|
115
|
+
class BuiltInHeader extends ExpandableText {
|
|
116
|
+
onLogoClick;
|
|
117
|
+
handleMouse(event) {
|
|
118
|
+
if (event.type !== "click" || event.y > 1 || event.x < 1 || event.x > 4 || !this.onLogoClick)
|
|
119
|
+
return undefined;
|
|
120
|
+
this.onLogoClick(event.screenX - event.x + 1, event.screenY - event.y);
|
|
121
|
+
return { handled: true };
|
|
103
122
|
}
|
|
104
123
|
}
|
|
105
124
|
function isCustomSessionEntry(item) {
|
|
@@ -111,7 +130,9 @@ function isCompactionCostNotice(item) {
|
|
|
111
130
|
function isUsageSessionEntry(item) {
|
|
112
131
|
return "type" in item && item.type === "usage";
|
|
113
132
|
}
|
|
114
|
-
|
|
133
|
+
// EIO: tty reads/ioctls from an orphaned background process group, or writes after hangup.
|
|
134
|
+
// ENOTTY: the tty was revoked (macOS) and stdin is no longer a terminal.
|
|
135
|
+
const DEAD_TERMINAL_ERROR_CODES = new Set(["EIO", "EPIPE", "ENOTCONN", "ENOTTY"]);
|
|
115
136
|
function isDeadTerminalError(error) {
|
|
116
137
|
if (!error || typeof error !== "object" || !("code" in error)) {
|
|
117
138
|
return false;
|
|
@@ -119,6 +140,22 @@ function isDeadTerminalError(error) {
|
|
|
119
140
|
const code = error.code;
|
|
120
141
|
return code !== undefined && DEAD_TERMINAL_ERROR_CODES.has(code);
|
|
121
142
|
}
|
|
143
|
+
export function formatCrashExtensionHint(extensionMatches) {
|
|
144
|
+
const matches = Array.isArray(extensionMatches)
|
|
145
|
+
? extensionMatches.filter((match) => typeof match === "string" && match.length > 0)
|
|
146
|
+
: [];
|
|
147
|
+
if (matches.length === 0)
|
|
148
|
+
return undefined;
|
|
149
|
+
const quoted = matches.map((match) => `\`${match}\``);
|
|
150
|
+
const labels = quoted.length === 1
|
|
151
|
+
? quoted[0]
|
|
152
|
+
: quoted.length === 2
|
|
153
|
+
? quoted.join(" and ")
|
|
154
|
+
: `${quoted.slice(0, -1).join(", ")}, and ${quoted[quoted.length - 1]}`;
|
|
155
|
+
const noun = matches.length === 1 ? "extension" : "extensions";
|
|
156
|
+
const pronoun = matches.length === 1 ? "it" : "them";
|
|
157
|
+
return `A stack frame came from loaded ${noun} ${labels}, which may be involved. Try disabling ${pronoun} with \`${APP_NAME} config\`, or run \`${APP_NAME} -ne\` to confirm.`;
|
|
158
|
+
}
|
|
122
159
|
const ANTHROPIC_SUBSCRIPTION_AUTH_WARNING = "Anthropic subscription auth is active. Third-party harness usage draws from extra usage and is billed per token, not your Claude plan limits. Manage extra usage at https://claude.ai/settings/usage. Disable this warning in /settings.";
|
|
123
160
|
const SELESAI_LOGO = [
|
|
124
161
|
" ____ ____ __ ____ ____ ______ ______ ",
|
|
@@ -179,6 +216,7 @@ function llamaCppPostLoginGuidance(actionLabel, loadedModelCount) {
|
|
|
179
216
|
? `${actionLabel}. No llama.cpp models are loaded. Use /llama to load a model, then /model to select it.`
|
|
180
217
|
: `${actionLabel}. Use /model to select a loaded llama.cpp model, or /llama to manage models.`;
|
|
181
218
|
}
|
|
219
|
+
const RADIUS_LOGIN_INTRO = "Radius is a service crafted for Pi by the builders of Pi, Earendil Works";
|
|
182
220
|
const AUTH_TYPE_ORDER = { oauth: 0, api_key: 1 };
|
|
183
221
|
function createFuzzyAutocompleteItems(items, prefix, getSearchText, toAutocompleteItem) {
|
|
184
222
|
const filtered = fuzzyFilter(items, prefix, getSearchText);
|
|
@@ -201,18 +239,21 @@ function getLoginProviderCompletionOptions(providerOptions) {
|
|
|
201
239
|
id: provider.id,
|
|
202
240
|
name: provider.name,
|
|
203
241
|
authTypes: [provider.authType],
|
|
242
|
+
subscription: provider.subscription,
|
|
204
243
|
});
|
|
205
244
|
}
|
|
206
245
|
return Array.from(byId.values()).sort((a, b) => a.name.localeCompare(b.name));
|
|
207
246
|
}
|
|
208
247
|
function getLoginProviderSearchText(provider) {
|
|
209
248
|
const authTypes = provider.authTypes
|
|
210
|
-
.map((authType) => `${authType} ${formatAuthSelectorProviderType(authType)}`)
|
|
249
|
+
.map((authType) => `${authType} ${formatAuthSelectorProviderType(authType, provider.subscription)}`)
|
|
211
250
|
.join(" ");
|
|
212
251
|
return `${provider.id} ${provider.name} ${authTypes}`;
|
|
213
252
|
}
|
|
214
253
|
function formatLoginProviderCompletionDescription(provider) {
|
|
215
|
-
const authTypes = provider.authTypes
|
|
254
|
+
const authTypes = provider.authTypes
|
|
255
|
+
.map((authType) => formatAuthSelectorProviderType(authType, provider.subscription))
|
|
256
|
+
.join("/");
|
|
216
257
|
return provider.name === provider.id ? authTypes : `${provider.name} · ${authTypes}`;
|
|
217
258
|
}
|
|
218
259
|
export class InteractiveMode {
|
|
@@ -220,13 +261,13 @@ export class InteractiveMode {
|
|
|
220
261
|
renderer;
|
|
221
262
|
ui;
|
|
222
263
|
mainScreenRenderState;
|
|
223
|
-
documentContainer;
|
|
224
264
|
loadedResourcesContainer;
|
|
225
265
|
chatContainer;
|
|
226
|
-
|
|
227
|
-
statusContainer;
|
|
266
|
+
documentContainer;
|
|
228
267
|
transcriptScrollView;
|
|
229
268
|
fullscreenLayoutRoot;
|
|
269
|
+
pendingMessagesContainer;
|
|
270
|
+
statusContainer;
|
|
230
271
|
defaultEditor;
|
|
231
272
|
editor;
|
|
232
273
|
editorComponentFactory;
|
|
@@ -234,6 +275,8 @@ export class InteractiveMode {
|
|
|
234
275
|
autocompleteProviderWrappers = [];
|
|
235
276
|
fdPath;
|
|
236
277
|
editorContainer;
|
|
278
|
+
activeSelectorToken;
|
|
279
|
+
activeSelectorDispose;
|
|
237
280
|
footer;
|
|
238
281
|
footerContainer;
|
|
239
282
|
footerDataProvider;
|
|
@@ -261,16 +304,22 @@ export class InteractiveMode {
|
|
|
261
304
|
// Status line tracking (for mutating immediately-sequential status updates)
|
|
262
305
|
lastStatusSpacer = undefined;
|
|
263
306
|
lastStatusText = undefined;
|
|
307
|
+
lastStatusMessage = "";
|
|
308
|
+
managedToolStatusStarted = false;
|
|
264
309
|
// Streaming message tracking
|
|
265
310
|
streamingComponent = undefined;
|
|
311
|
+
entriesRenderedByBoundaryCompaction = new Set();
|
|
266
312
|
streamingMessage = undefined;
|
|
267
313
|
// Tool execution tracking: toolCallId -> component
|
|
268
314
|
pendingTools = new Map();
|
|
269
315
|
// Tool output expansion state
|
|
270
316
|
toolOutputExpanded = false;
|
|
271
|
-
managedToolStatusStarted = false;
|
|
272
317
|
// Thinking block visibility state
|
|
273
318
|
hideThinkingBlock = false;
|
|
319
|
+
mermaidMarkdownTransformer = createMermaidMarkdownTransformer({
|
|
320
|
+
getMode: () => this.settingsManager.getMermaidRenderingMode(),
|
|
321
|
+
theme,
|
|
322
|
+
});
|
|
274
323
|
outputPad = 1;
|
|
275
324
|
// Agent subscription unsubscribe function
|
|
276
325
|
unsubscribe;
|
|
@@ -289,15 +338,16 @@ export class InteractiveMode {
|
|
|
289
338
|
compactionQueuedMessages = [];
|
|
290
339
|
// Shutdown state
|
|
291
340
|
shutdownRequested = false;
|
|
341
|
+
/** Reports working, blocked, done, and error states to terminals that support OSC 7501. */
|
|
342
|
+
programStatus = new ProgramStatusReporter(() => this.ui.terminal, () => this.sessionManager.getSessionName());
|
|
292
343
|
/** The `/bug` hint is shown at most once per session so error output stays readable. */
|
|
293
344
|
bugReportHintShown = false;
|
|
345
|
+
installChangeWarningShown = false;
|
|
294
346
|
// Extension UI state
|
|
295
347
|
extensionSelector = undefined;
|
|
296
348
|
extensionInput = undefined;
|
|
297
349
|
extensionEditor = undefined;
|
|
298
|
-
|
|
299
|
-
// re-registered on the active renderer after a TUI mode switch.
|
|
300
|
-
extensionTerminalInputUnsubscribers = new Map();
|
|
350
|
+
extensionTerminalInputSubscriptions = new Set();
|
|
301
351
|
// Extension widgets (components rendered above/below the editor)
|
|
302
352
|
extensionWidgetsAbove = new Map();
|
|
303
353
|
extensionWidgetsBelow = new Map();
|
|
@@ -343,6 +393,7 @@ export class InteractiveMode {
|
|
|
343
393
|
});
|
|
344
394
|
this.runtimeHost.setRebindSession(async () => {
|
|
345
395
|
await this.rebindCurrentSession({ renderBeforeBind: true });
|
|
396
|
+
this.themeController.applyFromSettings();
|
|
346
397
|
});
|
|
347
398
|
this.version = VERSION;
|
|
348
399
|
this.renderer = createInteractiveTui({
|
|
@@ -352,13 +403,14 @@ export class InteractiveMode {
|
|
|
352
403
|
terminal: options.terminal,
|
|
353
404
|
onRightClickPaste: this.onRightClickPaste,
|
|
354
405
|
fullscreenCopyOnSelect: this.settingsManager.getFullscreenCopyOnSelect(),
|
|
406
|
+
fullscreenWheelScrollLines: this.settingsManager.getFullscreenWheelScrollLines(),
|
|
355
407
|
});
|
|
356
408
|
this.ui = createInteractiveTuiReference(() => this.renderer);
|
|
357
409
|
this.ui.setClearOnShrink(this.settingsManager.getClearOnShrink());
|
|
358
|
-
this.documentContainer = new Container();
|
|
359
410
|
this.headerContainer = new Container();
|
|
360
411
|
this.loadedResourcesContainer = new Container();
|
|
361
412
|
this.chatContainer = new Container();
|
|
413
|
+
this.documentContainer = new Container();
|
|
362
414
|
this.documentContainer.addChild(this.headerContainer);
|
|
363
415
|
this.documentContainer.addChild(this.loadedResourcesContainer);
|
|
364
416
|
this.documentContainer.addChild(this.chatContainer);
|
|
@@ -396,7 +448,8 @@ export class InteractiveMode {
|
|
|
396
448
|
});
|
|
397
449
|
}
|
|
398
450
|
getAutocompleteSourceTag(sourceInfo) {
|
|
399
|
-
|
|
451
|
+
// Built-in extension commands are untagged, like built-in commands.
|
|
452
|
+
if (!sourceInfo || sourceInfo.source === "builtin") {
|
|
400
453
|
return undefined;
|
|
401
454
|
}
|
|
402
455
|
const scopePrefix = sourceInfo.scope === "user" ? "u" : sourceInfo.scope === "project" ? "p" : "t";
|
|
@@ -443,11 +496,10 @@ export class InteractiveMode {
|
|
|
443
496
|
}));
|
|
444
497
|
const modelCommand = slashCommands.find((command) => command.name === "model");
|
|
445
498
|
if (modelCommand) {
|
|
446
|
-
modelCommand.getArgumentCompletions =
|
|
447
|
-
// Get available models (scoped or from registry)
|
|
499
|
+
modelCommand.getArgumentCompletions = (prefix) => {
|
|
448
500
|
const models = this.session.scopedModels.length > 0
|
|
449
501
|
? this.session.scopedModels.map((s) => s.model)
|
|
450
|
-
:
|
|
502
|
+
: this.session.modelRuntime.getAvailableSnapshot();
|
|
451
503
|
if (models.length === 0)
|
|
452
504
|
return null;
|
|
453
505
|
// Create items with provider/id format
|
|
@@ -464,6 +516,15 @@ export class InteractiveMode {
|
|
|
464
516
|
}));
|
|
465
517
|
};
|
|
466
518
|
}
|
|
519
|
+
const thinkingCommand = slashCommands.find((command) => command.name === "thinking");
|
|
520
|
+
if (thinkingCommand) {
|
|
521
|
+
thinkingCommand.getArgumentCompletions = (prefix) => {
|
|
522
|
+
return createFuzzyAutocompleteItems(this.session.getAvailableThinkingLevels(), prefix, (level) => level, (level) => ({
|
|
523
|
+
value: level,
|
|
524
|
+
label: level,
|
|
525
|
+
}));
|
|
526
|
+
};
|
|
527
|
+
}
|
|
467
528
|
const gitCommand = slashCommands.find((command) => command.name === "git");
|
|
468
529
|
if (gitCommand) {
|
|
469
530
|
gitCommand.getArgumentCompletions = (prefix) => {
|
|
@@ -538,7 +599,7 @@ export class InteractiveMode {
|
|
|
538
599
|
this.chatContainer.addChild(new Text(condensedText, 1, 0));
|
|
539
600
|
}
|
|
540
601
|
else {
|
|
541
|
-
this.chatContainer.addChild(new
|
|
602
|
+
this.chatContainer.addChild(new ThemedText(() => theme.bold(theme.fg("accent", "What's New")), 1, 0));
|
|
542
603
|
this.chatContainer.addChild(new Spacer(1));
|
|
543
604
|
this.chatContainer.addChild(new Markdown(this.changelogMarkdown.trim(), 1, 0, this.getMarkdownThemeWithSettings()));
|
|
544
605
|
this.chatContainer.addChild(new Spacer(1));
|
|
@@ -590,6 +651,7 @@ export class InteractiveMode {
|
|
|
590
651
|
terminal,
|
|
591
652
|
onRightClickPaste: this.onRightClickPaste,
|
|
592
653
|
fullscreenCopyOnSelect: this.settingsManager.getFullscreenCopyOnSelect(),
|
|
654
|
+
fullscreenWheelScrollLines: this.settingsManager.getFullscreenWheelScrollLines(),
|
|
593
655
|
});
|
|
594
656
|
nextUi.setClearOnShrink(clearOnShrink);
|
|
595
657
|
nextUi.onDebug = onDebug;
|
|
@@ -619,7 +681,7 @@ export class InteractiveMode {
|
|
|
619
681
|
this.registerSignalHandlers();
|
|
620
682
|
// Load changelog (only show new entries, skip for resumed sessions)
|
|
621
683
|
this.changelogMarkdown = this.getChangelogForDisplay();
|
|
622
|
-
if (this.session.scopedModels.length > 0 &&
|
|
684
|
+
if (this.session.scopedModels.length > 0 && this.shouldShowStartupDetails()) {
|
|
623
685
|
const modelList = this.session.scopedModels
|
|
624
686
|
.map((sm) => {
|
|
625
687
|
const thinkingStr = sm.thinkingLevel ? `:${sm.thinkingLevel}` : "";
|
|
@@ -665,38 +727,45 @@ export class InteractiveMode {
|
|
|
665
727
|
// Start the UI before initializing extensions so session_start handlers can use interactive dialogs
|
|
666
728
|
this.ui.start();
|
|
667
729
|
this.isInitialized = true;
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
//
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
hint(
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
730
|
+
this.programStatus.report();
|
|
731
|
+
this.ensurePngTranscoder();
|
|
732
|
+
this.themeController.applyFromSettings();
|
|
733
|
+
// The header and startup notices bake theme colors into their text, so build them once the terminal
|
|
734
|
+
// reported its colors. This ends at the terminal's DA1 reply, or after 100 ms if it answers nothing.
|
|
735
|
+
await this.themeController.waitForTerminalColors();
|
|
736
|
+
if (this.shouldShowStartupHeader()) {
|
|
737
|
+
// Keep the Selesai banner; upstream quietStartup controls header visibility.
|
|
738
|
+
const logo = () => `${gradientLogo(SELESAI_LOGO, "#ff6b2c", "#fb923c")}\n${theme.fg("dim", ` ${APP_NAME} v${this.version} · /help for commands`)}`;
|
|
739
|
+
// Build startup instructions using keybinding hint helpers
|
|
740
|
+
const hint = (keybinding, description) => keyHint(keybinding, description);
|
|
741
|
+
const expandedInstructions = () => [
|
|
742
|
+
hint("app.interrupt", "to interrupt"),
|
|
743
|
+
hint("app.clear", "to clear"),
|
|
744
|
+
rawKeyHint(`${keyText("app.clear")} twice`, "to exit"),
|
|
745
|
+
hint("app.exit", "to exit (empty)"),
|
|
746
|
+
hint("app.suspend", "to suspend"),
|
|
747
|
+
keyHint("tui.editor.deleteToLineEnd", "to delete to end"),
|
|
748
|
+
hint("app.thinking.cycle", "to cycle thinking level"),
|
|
749
|
+
rawKeyHint(`${keyText("app.model.cycleForward")}/${keyText("app.model.cycleBackward")}`, "to cycle models"),
|
|
750
|
+
hint("app.model.select", "to select model"),
|
|
751
|
+
hint("app.tools.expand", "to expand tools"),
|
|
752
|
+
hint("app.thinking.toggle", "to expand thinking"),
|
|
753
|
+
hint("app.editor.external", "for external editor"),
|
|
754
|
+
rawKeyHint("/", "for commands"),
|
|
755
|
+
rawKeyHint("!", "to run bash"),
|
|
756
|
+
rawKeyHint("!!", "to run bash (no context)"),
|
|
757
|
+
hint("app.message.followUp", "to queue follow-up"),
|
|
758
|
+
hint("app.message.dequeue", "to edit all queued messages"),
|
|
759
|
+
hint("app.clipboard.pasteImage", "to paste image (with text fallback)"),
|
|
760
|
+
rawKeyHint("drop files", "to attach"),
|
|
761
|
+
].join("\n");
|
|
762
|
+
this.builtInHeader = new ExpandableText(() => logo(), () => `${logo()}\n\n${expandedInstructions()}`, this.getStartupExpansionState(), 1, 0);
|
|
763
|
+
// Setup UI layout
|
|
764
|
+
this.headerContainer.addChild(new Spacer(1));
|
|
765
|
+
this.headerContainer.addChild(this.builtInHeader);
|
|
766
|
+
this.headerContainer.addChild(new Spacer(1));
|
|
767
|
+
this.ui.requestRender();
|
|
768
|
+
}
|
|
700
769
|
// Ensure fd and rg are available after mounting the TUI (downloads if missing, adds to PATH via getBinDir)
|
|
701
770
|
// so slow downloads do not make startup appear frozen.
|
|
702
771
|
// Both are needed: fd for autocomplete, rg for grep tool and bash commands.
|
|
@@ -725,6 +794,14 @@ export class InteractiveMode {
|
|
|
725
794
|
});
|
|
726
795
|
// Initialize available provider count for footer display
|
|
727
796
|
await this.updateAvailableProviderCount();
|
|
797
|
+
// Flush the completed startup state before loading the remaining syntax grammars.
|
|
798
|
+
this.ui.renderNow();
|
|
799
|
+
void loadAllHighlightLanguages().then(() => {
|
|
800
|
+
if (!this.isInitialized)
|
|
801
|
+
return;
|
|
802
|
+
this.ui.invalidate();
|
|
803
|
+
this.ui.requestRender();
|
|
804
|
+
});
|
|
728
805
|
}
|
|
729
806
|
/**
|
|
730
807
|
* Update terminal title with session name and cwd.
|
|
@@ -753,11 +830,15 @@ export class InteractiveMode {
|
|
|
753
830
|
.catch(() => { })
|
|
754
831
|
.finally(() => clearTimeout(timeout));
|
|
755
832
|
}
|
|
756
|
-
//
|
|
757
|
-
checkForNewPiVersion(this.version, PACKAGE_NAME)
|
|
833
|
+
// Update checks are best-effort: a network failure must not end the session.
|
|
834
|
+
void checkForNewPiVersion(this.version, PACKAGE_NAME)
|
|
835
|
+
.then((newRelease) => {
|
|
758
836
|
if (newRelease) {
|
|
759
837
|
this.showNewVersionNotification(newRelease);
|
|
760
838
|
}
|
|
839
|
+
})
|
|
840
|
+
.catch(() => {
|
|
841
|
+
this.showWarning(`Could not check for updates. The network may be unavailable or the request timed out. Your session is still active; try again later with \`${APP_NAME} update --self\`.`);
|
|
761
842
|
});
|
|
762
843
|
// Start package update check asynchronously
|
|
763
844
|
this.checkForPackageUpdates()
|
|
@@ -780,7 +861,18 @@ export class InteractiveMode {
|
|
|
780
861
|
}
|
|
781
862
|
});
|
|
782
863
|
// Show startup warnings
|
|
783
|
-
const { migratedProviders, modelFallbackMessage, initialMessage, initialImages, initialMessages } = this.options;
|
|
864
|
+
const { migratedProviders, startupDiagnostics, modelFallbackMessage, initialMessage, initialImages, initialMessages, } = this.options;
|
|
865
|
+
for (const diagnostic of startupDiagnostics ?? []) {
|
|
866
|
+
if (diagnostic.type === "error") {
|
|
867
|
+
this.showError(diagnostic.message);
|
|
868
|
+
}
|
|
869
|
+
else if (diagnostic.type === "warning") {
|
|
870
|
+
this.showWarning(diagnostic.message);
|
|
871
|
+
}
|
|
872
|
+
else {
|
|
873
|
+
this.showStatus(diagnostic.message);
|
|
874
|
+
}
|
|
875
|
+
}
|
|
784
876
|
if (migratedProviders && migratedProviders.length > 0) {
|
|
785
877
|
this.showWarning(`Migrated credentials to auth.json: ${migratedProviders.join(", ")}`);
|
|
786
878
|
}
|
|
@@ -965,6 +1057,14 @@ export class InteractiveMode {
|
|
|
965
1057
|
getStartupExpansionState() {
|
|
966
1058
|
return this.options.verbose || this.toolOutputExpanded;
|
|
967
1059
|
}
|
|
1060
|
+
/** Startup header (logo, version, key hints). Hidden only by quietStartup: true. */
|
|
1061
|
+
shouldShowStartupHeader() {
|
|
1062
|
+
return this.options.verbose === true || this.settingsManager.getQuietStartup() !== true;
|
|
1063
|
+
}
|
|
1064
|
+
/** Startup details (model scope, loaded resources). Hidden by quietStartup: true or "header". */
|
|
1065
|
+
shouldShowStartupDetails() {
|
|
1066
|
+
return this.options.verbose === true || this.settingsManager.getQuietStartup() === false;
|
|
1067
|
+
}
|
|
968
1068
|
/**
|
|
969
1069
|
* Get a short path relative to the package root for display.
|
|
970
1070
|
*/
|
|
@@ -1228,7 +1328,7 @@ export class InteractiveMode {
|
|
|
1228
1328
|
if (this.startupBannerDismissed)
|
|
1229
1329
|
return;
|
|
1230
1330
|
this.loadedResourcesContainer.clear();
|
|
1231
|
-
const showListing = options?.force ||
|
|
1331
|
+
const showListing = options?.force || this.shouldShowStartupDetails();
|
|
1232
1332
|
const showDiagnostics = showListing || options?.showDiagnosticsWhenQuiet === true;
|
|
1233
1333
|
if (!showListing && !showDiagnostics) {
|
|
1234
1334
|
return;
|
|
@@ -1281,22 +1381,23 @@ export class InteractiveMode {
|
|
|
1281
1381
|
if (showDiagnostics) {
|
|
1282
1382
|
const skillDiagnostics = skillsResult.diagnostics;
|
|
1283
1383
|
if (skillDiagnostics.length > 0) {
|
|
1284
|
-
const warningLines = this.formatDiagnostics(skillDiagnostics, sourceInfos);
|
|
1285
|
-
this.loadedResourcesContainer.addChild(new
|
|
1384
|
+
const warningLines = () => this.formatDiagnostics(skillDiagnostics, sourceInfos);
|
|
1385
|
+
this.loadedResourcesContainer.addChild(new ThemedText(() => `${theme.fg("warning", "[Skill conflicts]")}\n${warningLines()}`, 0, 0));
|
|
1286
1386
|
this.loadedResourcesContainer.addChild(new Spacer(1));
|
|
1287
1387
|
}
|
|
1288
1388
|
const promptDiagnostics = promptsResult.diagnostics;
|
|
1289
1389
|
if (promptDiagnostics.length > 0) {
|
|
1290
|
-
const warningLines = this.formatDiagnostics(promptDiagnostics, sourceInfos);
|
|
1291
|
-
this.loadedResourcesContainer.addChild(new
|
|
1390
|
+
const warningLines = () => this.formatDiagnostics(promptDiagnostics, sourceInfos);
|
|
1391
|
+
this.loadedResourcesContainer.addChild(new ThemedText(() => `${theme.fg("warning", "[Prompt conflicts]")}\n${warningLines()}`, 0, 0));
|
|
1292
1392
|
this.loadedResourcesContainer.addChild(new Spacer(1));
|
|
1293
1393
|
}
|
|
1294
1394
|
const extensionDiagnostics = [];
|
|
1295
|
-
const
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1395
|
+
const extensionsResult = this.session.resourceLoader.getExtensions();
|
|
1396
|
+
for (const error of extensionsResult.errors) {
|
|
1397
|
+
extensionDiagnostics.push({ type: "error", message: error.error, path: error.path });
|
|
1398
|
+
}
|
|
1399
|
+
for (const warning of extensionsResult.warnings ?? []) {
|
|
1400
|
+
extensionDiagnostics.push({ type: "warning", message: warning.warning, path: warning.path });
|
|
1300
1401
|
}
|
|
1301
1402
|
const commandDiagnostics = this.session.extensionRunner.getCommandDiagnostics();
|
|
1302
1403
|
extensionDiagnostics.push(...commandDiagnostics);
|
|
@@ -1304,14 +1405,14 @@ export class InteractiveMode {
|
|
|
1304
1405
|
const shortcutDiagnostics = this.session.extensionRunner.getShortcutDiagnostics();
|
|
1305
1406
|
extensionDiagnostics.push(...shortcutDiagnostics);
|
|
1306
1407
|
if (extensionDiagnostics.length > 0) {
|
|
1307
|
-
const warningLines = this.formatDiagnostics(extensionDiagnostics, sourceInfos);
|
|
1308
|
-
this.loadedResourcesContainer.addChild(new
|
|
1408
|
+
const warningLines = () => this.formatDiagnostics(extensionDiagnostics, sourceInfos);
|
|
1409
|
+
this.loadedResourcesContainer.addChild(new ThemedText(() => `${theme.fg("warning", "[Extension issues]")}\n${warningLines()}`, 0, 0));
|
|
1309
1410
|
this.loadedResourcesContainer.addChild(new Spacer(1));
|
|
1310
1411
|
}
|
|
1311
1412
|
const themeDiagnostics = themesResult.diagnostics;
|
|
1312
1413
|
if (themeDiagnostics.length > 0) {
|
|
1313
|
-
const warningLines = this.formatDiagnostics(themeDiagnostics, sourceInfos);
|
|
1314
|
-
this.loadedResourcesContainer.addChild(new
|
|
1414
|
+
const warningLines = () => this.formatDiagnostics(themeDiagnostics, sourceInfos);
|
|
1415
|
+
this.loadedResourcesContainer.addChild(new ThemedText(() => `${theme.fg("warning", "[Theme conflicts]")}\n${warningLines()}`, 0, 0));
|
|
1315
1416
|
this.loadedResourcesContainer.addChild(new Spacer(1));
|
|
1316
1417
|
}
|
|
1317
1418
|
}
|
|
@@ -1403,11 +1504,24 @@ export class InteractiveMode {
|
|
|
1403
1504
|
this.showLoadedResources({ force: false, showDiagnosticsWhenQuiet: true });
|
|
1404
1505
|
this.showStartupNoticesIfNeeded();
|
|
1405
1506
|
}
|
|
1507
|
+
applyFullscreenScrollbarSetting() {
|
|
1508
|
+
this.transcriptScrollView?.setScrollbar(this.settingsManager.getFullscreenScrollbar());
|
|
1509
|
+
}
|
|
1510
|
+
/** Lets extension images use the PNG transcoder; tool results register it themselves. */
|
|
1511
|
+
ensurePngTranscoder() {
|
|
1512
|
+
ensurePngTranscoder(() => {
|
|
1513
|
+
this.ui.invalidate();
|
|
1514
|
+
this.ui.requestRender();
|
|
1515
|
+
});
|
|
1516
|
+
}
|
|
1406
1517
|
applyRuntimeSettings() {
|
|
1407
1518
|
setCapabilityOverrides(this.settingsManager.getTerminalCapabilityOverrides());
|
|
1519
|
+
this.ensurePngTranscoder();
|
|
1408
1520
|
configureHttpDispatcher(this.settingsManager.getHttpIdleTimeoutMs());
|
|
1521
|
+
this.applyFullscreenScrollbarSetting();
|
|
1409
1522
|
if (this.renderer instanceof TuiAltScreen) {
|
|
1410
1523
|
this.renderer.setCopyOnSelect(this.settingsManager.getFullscreenCopyOnSelect());
|
|
1524
|
+
this.renderer.setWheelScrollLines(this.settingsManager.getFullscreenWheelScrollLines());
|
|
1411
1525
|
}
|
|
1412
1526
|
this.footer.setSession(this.session);
|
|
1413
1527
|
this.footer.setAutoCompactEnabled(this.session.autoCompactionEnabled);
|
|
@@ -1433,6 +1547,7 @@ export class InteractiveMode {
|
|
|
1433
1547
|
const session = this.session;
|
|
1434
1548
|
this.unsubscribe?.();
|
|
1435
1549
|
this.unsubscribe = undefined;
|
|
1550
|
+
this.programStatus.reset();
|
|
1436
1551
|
this.applyRuntimeSettings();
|
|
1437
1552
|
if (options.renderBeforeBind) {
|
|
1438
1553
|
this.renderCurrentSessionState();
|
|
@@ -1452,13 +1567,26 @@ export class InteractiveMode {
|
|
|
1452
1567
|
async handleFatalRuntimeError(prefix, error) {
|
|
1453
1568
|
const message = error instanceof Error ? error.message : String(error);
|
|
1454
1569
|
this.showError(`${prefix}: ${message}`);
|
|
1570
|
+
const extensionHint = this.getCrashExtensionHint(error);
|
|
1571
|
+
if (extensionHint) {
|
|
1572
|
+
this.chatContainer.addChild(new ThemedText(() => theme.fg("warning", extensionHint), this.outputPad, 0));
|
|
1573
|
+
}
|
|
1455
1574
|
if (this.recordCrash("fatal_error", error)) {
|
|
1456
|
-
|
|
1575
|
+
const instructions = this.crashReportInstructions();
|
|
1576
|
+
this.chatContainer.addChild(new ThemedText(() => theme.fg("muted", instructions), this.outputPad, 0));
|
|
1457
1577
|
}
|
|
1458
1578
|
stopThemeWatcher();
|
|
1459
1579
|
this.stop("transcript");
|
|
1460
1580
|
process.exit(1);
|
|
1461
1581
|
}
|
|
1582
|
+
getCrashExtensionHint(error) {
|
|
1583
|
+
try {
|
|
1584
|
+
return formatCrashExtensionHint(findExtensionStackMatches(error instanceof Error ? error.stack : undefined, this.session.resourceLoader.getExtensions().extensions));
|
|
1585
|
+
}
|
|
1586
|
+
catch {
|
|
1587
|
+
return undefined;
|
|
1588
|
+
}
|
|
1589
|
+
}
|
|
1462
1590
|
/** Persist a crash so the next start can point the user at `/bug`. Returns false when nothing was written. */
|
|
1463
1591
|
recordCrash(kind, error) {
|
|
1464
1592
|
try {
|
|
@@ -1481,7 +1609,7 @@ export class InteractiveMode {
|
|
|
1481
1609
|
if (this.bugReportHintShown)
|
|
1482
1610
|
return;
|
|
1483
1611
|
this.bugReportHintShown = true;
|
|
1484
|
-
this.chatContainer.addChild(new
|
|
1612
|
+
this.chatContainer.addChild(new ThemedText(() => theme.fg("muted", `If this looks like a ${APP_NAME} bug, /bug sends a report to the developers.`), this.outputPad, 0));
|
|
1485
1613
|
this.ui.requestRender();
|
|
1486
1614
|
}
|
|
1487
1615
|
maybeSuggestBugReport(message) {
|
|
@@ -1489,8 +1617,32 @@ export class InteractiveMode {
|
|
|
1489
1617
|
return;
|
|
1490
1618
|
if (/\b(?:abort(?:ed)?|cancel(?:l?ed)?)\b/i.test(message.errorMessage ?? ""))
|
|
1491
1619
|
return;
|
|
1620
|
+
if (this.maybeShowInstallChangeWarning())
|
|
1621
|
+
return;
|
|
1492
1622
|
this.suggestBugReport();
|
|
1493
1623
|
}
|
|
1624
|
+
/**
|
|
1625
|
+
* After an error, check whether an update replaced or removed this install while the session ran.
|
|
1626
|
+
* Code loaded on demand then fails with missing modules until restart (#10439). Returns true when
|
|
1627
|
+
* the install changed.
|
|
1628
|
+
*/
|
|
1629
|
+
maybeShowInstallChangeWarning() {
|
|
1630
|
+
if (this.installChangeWarningShown)
|
|
1631
|
+
return true;
|
|
1632
|
+
const change = detectInstallChange();
|
|
1633
|
+
if (!change)
|
|
1634
|
+
return false;
|
|
1635
|
+
this.installChangeWarningShown = true;
|
|
1636
|
+
const cause = change.kind === "updated"
|
|
1637
|
+
? `${APP_NAME} was updated to ${change.version} while this session was running (${VERSION})`
|
|
1638
|
+
: `The ${APP_NAME} installation this session runs from was removed or replaced`;
|
|
1639
|
+
const resumeCommand = formatResumeCommand(this.sessionManager);
|
|
1640
|
+
const restart = resumeCommand
|
|
1641
|
+
? `Restart with \`${resumeCommand}\` to continue this session.`
|
|
1642
|
+
: `Restart ${APP_NAME}.`;
|
|
1643
|
+
this.showWarning(`${cause}. Features that load code on demand can fail until restart. ${restart}`);
|
|
1644
|
+
return true;
|
|
1645
|
+
}
|
|
1494
1646
|
renderCurrentSessionState() {
|
|
1495
1647
|
this.loadedResourcesContainer.clear();
|
|
1496
1648
|
this.chatContainer.clear();
|
|
@@ -1509,7 +1661,10 @@ export class InteractiveMode {
|
|
|
1509
1661
|
* whatever this returns, so they never reach into the tool registry themselves.
|
|
1510
1662
|
*/
|
|
1511
1663
|
getRegisteredToolDefinition(toolName) {
|
|
1512
|
-
return withBuiltInRenderers(toolName, this.session.getToolDefinition(toolName));
|
|
1664
|
+
return this.session.extensionRunner.resolveToolRenderers(toolName, () => withBuiltInRenderers(toolName, this.session.getToolDefinition(toolName)));
|
|
1665
|
+
}
|
|
1666
|
+
getMarkdownTransformers() {
|
|
1667
|
+
return [this.mermaidMarkdownTransformer, ...this.session.extensionRunner.getMarkdownTransformers()];
|
|
1513
1668
|
}
|
|
1514
1669
|
/**
|
|
1515
1670
|
* Set up keyboard shortcuts registered by extensions.
|
|
@@ -1675,7 +1830,7 @@ export class InteractiveMode {
|
|
|
1675
1830
|
container.addChild(new Text(line, 1, 0));
|
|
1676
1831
|
}
|
|
1677
1832
|
if (content.length > InteractiveMode.MAX_WIDGET_LINES) {
|
|
1678
|
-
container.addChild(new
|
|
1833
|
+
container.addChild(new ThemedText(() => theme.fg("muted", "... (widget truncated)"), 1, 0));
|
|
1679
1834
|
}
|
|
1680
1835
|
component = container;
|
|
1681
1836
|
}
|
|
@@ -1818,23 +1973,23 @@ export class InteractiveMode {
|
|
|
1818
1973
|
this.ui.requestRender();
|
|
1819
1974
|
}
|
|
1820
1975
|
addExtensionTerminalInputListener(handler) {
|
|
1821
|
-
const
|
|
1822
|
-
this.
|
|
1976
|
+
const subscription = { handler, unsubscribe: this.ui.addInputListener(handler) };
|
|
1977
|
+
this.extensionTerminalInputSubscriptions.add(subscription);
|
|
1823
1978
|
return () => {
|
|
1824
|
-
unsubscribe();
|
|
1825
|
-
this.
|
|
1979
|
+
subscription.unsubscribe();
|
|
1980
|
+
this.extensionTerminalInputSubscriptions.delete(subscription);
|
|
1826
1981
|
};
|
|
1827
1982
|
}
|
|
1828
1983
|
rebindExtensionTerminalInputListeners() {
|
|
1829
|
-
for (const
|
|
1830
|
-
|
|
1984
|
+
for (const subscription of this.extensionTerminalInputSubscriptions) {
|
|
1985
|
+
subscription.unsubscribe();
|
|
1986
|
+
subscription.unsubscribe = this.ui.addInputListener(subscription.handler);
|
|
1831
1987
|
}
|
|
1832
1988
|
}
|
|
1833
1989
|
clearExtensionTerminalInputListeners() {
|
|
1834
|
-
for (const
|
|
1835
|
-
unsubscribe();
|
|
1836
|
-
|
|
1837
|
-
this.extensionTerminalInputUnsubscribers.clear();
|
|
1990
|
+
for (const subscription of this.extensionTerminalInputSubscriptions)
|
|
1991
|
+
subscription.unsubscribe();
|
|
1992
|
+
this.extensionTerminalInputSubscriptions.clear();
|
|
1838
1993
|
}
|
|
1839
1994
|
/**
|
|
1840
1995
|
* Create the ExtensionUIContext for extensions.
|
|
@@ -1909,7 +2064,7 @@ export class InteractiveMode {
|
|
|
1909
2064
|
/**
|
|
1910
2065
|
* Show a selector for extensions.
|
|
1911
2066
|
*/
|
|
1912
|
-
showExtensionSelector(title, options, opts) {
|
|
2067
|
+
showExtensionSelector(title, options, opts, blocked = { kind: "question", message: title }) {
|
|
1913
2068
|
return new Promise((resolve) => {
|
|
1914
2069
|
if (opts?.signal?.aborted) {
|
|
1915
2070
|
resolve(undefined);
|
|
@@ -1929,9 +2084,12 @@ export class InteractiveMode {
|
|
|
1929
2084
|
this.hideExtensionSelector();
|
|
1930
2085
|
resolve(undefined);
|
|
1931
2086
|
}, { tui: this.ui, timeout: opts?.timeout, onToggleToolsExpanded: () => this.toggleToolOutputExpansion() });
|
|
2087
|
+
this.disposeActiveSelector();
|
|
1932
2088
|
this.editorContainer.clear();
|
|
1933
2089
|
this.editorContainer.addChild(this.extensionSelector);
|
|
1934
2090
|
this.ui.setFocus(this.extensionSelector);
|
|
2091
|
+
// Extension dialogs share the editor slot: opening one replaces the status of a displaced one.
|
|
2092
|
+
this.programStatus.setBlocked("extension-dialog", blocked);
|
|
1935
2093
|
this.ui.requestRender();
|
|
1936
2094
|
});
|
|
1937
2095
|
}
|
|
@@ -1943,6 +2101,7 @@ export class InteractiveMode {
|
|
|
1943
2101
|
this.editorContainer.clear();
|
|
1944
2102
|
this.editorContainer.addChild(this.editor);
|
|
1945
2103
|
this.extensionSelector = undefined;
|
|
2104
|
+
this.programStatus.setBlocked("extension-dialog", undefined);
|
|
1946
2105
|
this.ui.setFocus(this.editor);
|
|
1947
2106
|
this.ui.requestRender();
|
|
1948
2107
|
}
|
|
@@ -1950,7 +2109,10 @@ export class InteractiveMode {
|
|
|
1950
2109
|
* Show a confirmation dialog for extensions.
|
|
1951
2110
|
*/
|
|
1952
2111
|
async showExtensionConfirm(title, message, opts) {
|
|
1953
|
-
const result = await this.showExtensionSelector(`${title}\n${message}`, ["Yes", "No"], opts
|
|
2112
|
+
const result = await this.showExtensionSelector(`${title}\n${message}`, ["Yes", "No"], opts, {
|
|
2113
|
+
kind: "permission",
|
|
2114
|
+
message: title,
|
|
2115
|
+
});
|
|
1954
2116
|
return result === "Yes";
|
|
1955
2117
|
}
|
|
1956
2118
|
async promptForMissingSessionCwd(error) {
|
|
@@ -1980,9 +2142,11 @@ export class InteractiveMode {
|
|
|
1980
2142
|
this.hideExtensionInput();
|
|
1981
2143
|
resolve(undefined);
|
|
1982
2144
|
}, { tui: this.ui, timeout: opts?.timeout });
|
|
2145
|
+
this.disposeActiveSelector();
|
|
1983
2146
|
this.editorContainer.clear();
|
|
1984
2147
|
this.editorContainer.addChild(this.extensionInput);
|
|
1985
2148
|
this.ui.setFocus(this.extensionInput);
|
|
2149
|
+
this.programStatus.setBlocked("extension-dialog", { kind: "question", message: title });
|
|
1986
2150
|
this.ui.requestRender();
|
|
1987
2151
|
});
|
|
1988
2152
|
}
|
|
@@ -1994,6 +2158,7 @@ export class InteractiveMode {
|
|
|
1994
2158
|
this.editorContainer.clear();
|
|
1995
2159
|
this.editorContainer.addChild(this.editor);
|
|
1996
2160
|
this.extensionInput = undefined;
|
|
2161
|
+
this.programStatus.setBlocked("extension-dialog", undefined);
|
|
1997
2162
|
this.ui.setFocus(this.editor);
|
|
1998
2163
|
this.ui.requestRender();
|
|
1999
2164
|
}
|
|
@@ -2009,9 +2174,11 @@ export class InteractiveMode {
|
|
|
2009
2174
|
this.hideExtensionEditor();
|
|
2010
2175
|
resolve(undefined);
|
|
2011
2176
|
}, undefined, this.settingsManager.getExternalEditorCommand());
|
|
2177
|
+
this.disposeActiveSelector();
|
|
2012
2178
|
this.editorContainer.clear();
|
|
2013
2179
|
this.editorContainer.addChild(this.extensionEditor);
|
|
2014
2180
|
this.ui.setFocus(this.extensionEditor);
|
|
2181
|
+
this.programStatus.setBlocked("extension-dialog", { kind: "question", message: title });
|
|
2015
2182
|
this.ui.requestRender();
|
|
2016
2183
|
});
|
|
2017
2184
|
}
|
|
@@ -2022,6 +2189,7 @@ export class InteractiveMode {
|
|
|
2022
2189
|
this.editorContainer.clear();
|
|
2023
2190
|
this.editorContainer.addChild(this.editor);
|
|
2024
2191
|
this.extensionEditor = undefined;
|
|
2192
|
+
this.programStatus.setBlocked("extension-dialog", undefined);
|
|
2025
2193
|
this.ui.setFocus(this.editor);
|
|
2026
2194
|
this.ui.requestRender();
|
|
2027
2195
|
}
|
|
@@ -2033,6 +2201,7 @@ export class InteractiveMode {
|
|
|
2033
2201
|
this.editorComponentFactory = factory;
|
|
2034
2202
|
// Save text from current editor before switching
|
|
2035
2203
|
const currentText = this.editor.getText();
|
|
2204
|
+
this.disposeActiveSelector();
|
|
2036
2205
|
this.editorContainer.clear();
|
|
2037
2206
|
if (factory) {
|
|
2038
2207
|
// Create the custom editor with tui, theme, and keybindings
|
|
@@ -2049,6 +2218,9 @@ export class InteractiveMode {
|
|
|
2049
2218
|
if (newEditor.setPaddingX !== undefined) {
|
|
2050
2219
|
newEditor.setPaddingX(this.defaultEditor.getPaddingX());
|
|
2051
2220
|
}
|
|
2221
|
+
if (newEditor.setAutocompleteMaxVisible !== undefined) {
|
|
2222
|
+
newEditor.setAutocompleteMaxVisible(this.defaultEditor.getAutocompleteMaxVisible());
|
|
2223
|
+
}
|
|
2052
2224
|
// Set autocomplete if supported
|
|
2053
2225
|
if (newEditor.setAutocompleteProvider && this.autocompleteProvider) {
|
|
2054
2226
|
newEditor.setAutocompleteProvider(this.autocompleteProvider);
|
|
@@ -2160,6 +2332,7 @@ export class InteractiveMode {
|
|
|
2160
2332
|
options?.onHandle?.(handle);
|
|
2161
2333
|
}
|
|
2162
2334
|
else {
|
|
2335
|
+
this.disposeActiveSelector();
|
|
2163
2336
|
this.editorContainer.clear();
|
|
2164
2337
|
this.editorContainer.addChild(component);
|
|
2165
2338
|
this.ui.setFocus(component);
|
|
@@ -2180,17 +2353,14 @@ export class InteractiveMode {
|
|
|
2180
2353
|
*/
|
|
2181
2354
|
showExtensionError(extensionPath, error, stack) {
|
|
2182
2355
|
const errorMsg = `Extension "${extensionPath}" error: ${error}`;
|
|
2183
|
-
const errorText = new
|
|
2356
|
+
const errorText = new ThemedText(() => theme.fg("error", errorMsg), 1, 0);
|
|
2184
2357
|
this.chatContainer.addChild(errorText);
|
|
2185
2358
|
if (stack) {
|
|
2186
2359
|
// Show stack trace in dim color, indented
|
|
2187
|
-
const stackLines = stack
|
|
2188
|
-
|
|
2189
|
-
.
|
|
2190
|
-
.
|
|
2191
|
-
.join("\n");
|
|
2192
|
-
if (stackLines) {
|
|
2193
|
-
this.chatContainer.addChild(new Text(stackLines, 1, 0));
|
|
2360
|
+
const stackLines = stack.split("\n").slice(1); // Skip first line (duplicates error message)
|
|
2361
|
+
if (stackLines.length > 0) {
|
|
2362
|
+
const renderStack = () => stackLines.map((line) => theme.fg("dim", ` ${line.trim()}`)).join("\n");
|
|
2363
|
+
this.chatContainer.addChild(new ThemedText(renderStack, 1, 0));
|
|
2194
2364
|
}
|
|
2195
2365
|
}
|
|
2196
2366
|
this.ui.requestRender();
|
|
@@ -2260,8 +2430,8 @@ export class InteractiveMode {
|
|
|
2260
2430
|
this.updateEditorBorderColor();
|
|
2261
2431
|
}
|
|
2262
2432
|
};
|
|
2263
|
-
// Handle clipboard paste (triggered on Ctrl+V).
|
|
2264
|
-
//
|
|
2433
|
+
// Handle clipboard paste (triggered on Ctrl+V). Copied files use their original paths,
|
|
2434
|
+
// images are attached via temporary files, and plain text is the final fallback.
|
|
2265
2435
|
this.defaultEditor.onPasteImage = () => {
|
|
2266
2436
|
void this.handleClipboardPaste();
|
|
2267
2437
|
};
|
|
@@ -2284,32 +2454,37 @@ export class InteractiveMode {
|
|
|
2284
2454
|
}
|
|
2285
2455
|
async handleClipboardPaste() {
|
|
2286
2456
|
try {
|
|
2457
|
+
const filePaths = await readClipboardFilePaths();
|
|
2458
|
+
if (filePaths) {
|
|
2459
|
+
if (filePaths.some((filePath) => /\p{Cc}/u.test(filePath))) {
|
|
2460
|
+
throw new Error("Clipboard file path contains control characters");
|
|
2461
|
+
}
|
|
2462
|
+
const paths = this.isBashMode ? filePaths.map(quoteIfNeeded).join(" ") : filePaths.join("\n");
|
|
2463
|
+
const cursor = this.editor.getCursor?.();
|
|
2464
|
+
const currentLine = cursor ? (this.editor.getText().split("\n")[cursor.line] ?? "") : "";
|
|
2465
|
+
const characterBeforeCursor = cursor && cursor.col > 0 ? currentLine[cursor.col - 1] : "";
|
|
2466
|
+
const characterAfterCursor = cursor ? currentLine[cursor.col] : "";
|
|
2467
|
+
const leadingSpace = characterBeforeCursor && !/\s/.test(characterBeforeCursor) ? " " : "";
|
|
2468
|
+
const trailingSpace = characterAfterCursor && !/\s/.test(characterAfterCursor) ? " " : "";
|
|
2469
|
+
this.editor.insertTextAtCursor?.(`${leadingSpace}${paths}${trailingSpace}`);
|
|
2470
|
+
this.ui.requestRender();
|
|
2471
|
+
return;
|
|
2472
|
+
}
|
|
2287
2473
|
const image = await readClipboardImage();
|
|
2288
2474
|
if (image) {
|
|
2289
2475
|
const tmpDir = os.tmpdir();
|
|
2290
2476
|
const ext = extensionForImageMimeType(image.mimeType) ?? "png";
|
|
2291
|
-
const fileName = `selesai-clipboard-${
|
|
2477
|
+
const fileName = `selesai-clipboard-${crypto.randomUUID()}.${ext}`;
|
|
2292
2478
|
const filePath = path.join(tmpDir, fileName);
|
|
2293
2479
|
fs.writeFileSync(filePath, Buffer.from(image.bytes));
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
}
|
|
2303
|
-
else {
|
|
2304
|
-
dimensionNote = formatDimensionNote(resized);
|
|
2305
|
-
attachment = { type: "image", mimeType: resized.mimeType, data: resized.data };
|
|
2306
|
-
}
|
|
2307
|
-
}
|
|
2308
|
-
else {
|
|
2309
|
-
attachment = { type: "image", mimeType: image.mimeType, data: Buffer.from(image.bytes).toString("base64") };
|
|
2310
|
-
}
|
|
2311
|
-
this.pendingInputImages.push(attachment);
|
|
2312
|
-
this.editor.insertTextAtCursor?.(dimensionNote ? `${filePath} ${dimensionNote}` : filePath);
|
|
2480
|
+
// Keep the fork caption attachment. AgentSession normalizes it after hooks
|
|
2481
|
+
// select the request model; resizing here would discard source resolution.
|
|
2482
|
+
this.pendingInputImages.push({
|
|
2483
|
+
type: "image",
|
|
2484
|
+
mimeType: image.mimeType,
|
|
2485
|
+
data: Buffer.from(image.bytes).toString("base64"),
|
|
2486
|
+
});
|
|
2487
|
+
this.editor.insertTextAtCursor?.(filePath);
|
|
2313
2488
|
this.ui.requestRender();
|
|
2314
2489
|
return;
|
|
2315
2490
|
}
|
|
@@ -2320,7 +2495,7 @@ export class InteractiveMode {
|
|
|
2320
2495
|
}
|
|
2321
2496
|
}
|
|
2322
2497
|
catch (error) {
|
|
2323
|
-
this.
|
|
2498
|
+
this.showError(`Failed to paste from clipboard: ${error instanceof Error ? error.message : String(error)}`);
|
|
2324
2499
|
}
|
|
2325
2500
|
}
|
|
2326
2501
|
consumePendingInputImages() {
|
|
@@ -2379,6 +2554,12 @@ export class InteractiveMode {
|
|
|
2379
2554
|
await this.handleModelCommand(searchTerm);
|
|
2380
2555
|
return;
|
|
2381
2556
|
}
|
|
2557
|
+
if (text === "/thinking" || text.startsWith("/thinking ")) {
|
|
2558
|
+
const searchTerm = text.startsWith("/thinking ") ? text.slice(10).trim() : undefined;
|
|
2559
|
+
this.editor.setText("");
|
|
2560
|
+
this.handleThinkingCommand(searchTerm);
|
|
2561
|
+
return;
|
|
2562
|
+
}
|
|
2382
2563
|
if (text === "/export" || text.startsWith("/export ")) {
|
|
2383
2564
|
await this.handleExportCommand(text);
|
|
2384
2565
|
this.editor.setText("");
|
|
@@ -2568,6 +2749,7 @@ export class InteractiveMode {
|
|
|
2568
2749
|
await this.init();
|
|
2569
2750
|
}
|
|
2570
2751
|
this.footer.invalidate();
|
|
2752
|
+
this.programStatus.handleEvent(event);
|
|
2571
2753
|
switch (event.type) {
|
|
2572
2754
|
case "agent_start":
|
|
2573
2755
|
this.pendingTools.clear();
|
|
@@ -2597,6 +2779,8 @@ export class InteractiveMode {
|
|
|
2597
2779
|
this.ui.requestRender();
|
|
2598
2780
|
break;
|
|
2599
2781
|
case "entry_appended":
|
|
2782
|
+
if (this.entriesRenderedByBoundaryCompaction.delete(event.entry.id))
|
|
2783
|
+
break;
|
|
2600
2784
|
if (event.entry.type === "custom") {
|
|
2601
2785
|
this.addCustomEntryToChat(event.entry);
|
|
2602
2786
|
this.ui.requestRender();
|
|
@@ -2605,6 +2789,34 @@ export class InteractiveMode {
|
|
|
2605
2789
|
this.addCacheWarmingUsage(event.entry);
|
|
2606
2790
|
this.ui.requestRender();
|
|
2607
2791
|
}
|
|
2792
|
+
else if (event.entry.type === "custom_message" && event.entry.display) {
|
|
2793
|
+
this.addMessageToChat(createCustomMessage(event.entry.customType, event.entry.content, event.entry.display, event.entry.details, event.entry.timestamp));
|
|
2794
|
+
this.ui.requestRender();
|
|
2795
|
+
}
|
|
2796
|
+
else if (event.entry.type === "compaction") {
|
|
2797
|
+
const entries = this.sessionManager.buildContextEntries();
|
|
2798
|
+
if (entries[0]?.id !== event.entry.id)
|
|
2799
|
+
break;
|
|
2800
|
+
this.chatContainer.clear();
|
|
2801
|
+
const branch = this.sessionManager.getBranch();
|
|
2802
|
+
const compactionIndex = branch.findIndex((entry) => entry.id === event.entry.id);
|
|
2803
|
+
const entriesAfterCompaction = new Set(branch.slice(compactionIndex + 1).map((entry) => entry.id));
|
|
2804
|
+
const retainedEntries = entries.slice(1);
|
|
2805
|
+
this.renderSessionEntries(retainedEntries.filter((entry) => !entriesAfterCompaction.has(entry.id)));
|
|
2806
|
+
this.addMessageToChat(createCompactionSummaryMessage(event.entry.summary, event.entry.tokensBefore, event.entry.timestamp));
|
|
2807
|
+
if (event.entry.usage) {
|
|
2808
|
+
this.addCompactionCostNotice({
|
|
2809
|
+
type: "compaction_cost",
|
|
2810
|
+
kind: "compaction",
|
|
2811
|
+
usage: event.entry.usage,
|
|
2812
|
+
});
|
|
2813
|
+
}
|
|
2814
|
+
this.renderSessionEntries(retainedEntries.filter((entry) => entriesAfterCompaction.has(entry.id)));
|
|
2815
|
+
for (const entryId of entriesAfterCompaction)
|
|
2816
|
+
this.entriesRenderedByBoundaryCompaction.add(entryId);
|
|
2817
|
+
this.footer.invalidate();
|
|
2818
|
+
this.ui.requestRender();
|
|
2819
|
+
}
|
|
2608
2820
|
break;
|
|
2609
2821
|
case "session_info_changed":
|
|
2610
2822
|
this.updateTerminalTitle();
|
|
@@ -2626,23 +2838,24 @@ export class InteractiveMode {
|
|
|
2626
2838
|
this.ui.requestRender();
|
|
2627
2839
|
}
|
|
2628
2840
|
else if (event.message.role === "assistant") {
|
|
2629
|
-
this.streamingComponent = new AssistantMessageComponent(undefined, this.hideThinkingBlock, this.getMarkdownThemeWithSettings(), this.hiddenThinkingLabel, this.outputPad);
|
|
2841
|
+
this.streamingComponent = new AssistantMessageComponent(undefined, this.hideThinkingBlock, this.getMarkdownThemeWithSettings(), this.hiddenThinkingLabel, this.outputPad, this.getMarkdownTransformers());
|
|
2630
2842
|
this.streamingMessage = event.message;
|
|
2631
2843
|
this.chatContainer.addChild(this.streamingComponent);
|
|
2632
|
-
this.streamingComponent.updateContent(this.streamingMessage);
|
|
2844
|
+
this.streamingComponent.updateContent(this.streamingMessage, true);
|
|
2633
2845
|
this.ui.requestRender();
|
|
2634
2846
|
}
|
|
2635
2847
|
break;
|
|
2636
2848
|
case "message_update":
|
|
2637
2849
|
if (this.streamingComponent && event.message.role === "assistant") {
|
|
2638
2850
|
this.streamingMessage = event.message;
|
|
2639
|
-
this.streamingComponent.updateContent(this.streamingMessage);
|
|
2851
|
+
this.streamingComponent.updateContent(this.streamingMessage, true);
|
|
2640
2852
|
for (const content of this.streamingMessage.content) {
|
|
2641
2853
|
if (content.type === "toolCall") {
|
|
2642
2854
|
if (!this.pendingTools.has(content.id)) {
|
|
2643
2855
|
const component = new ToolExecutionComponent(content.name, content.id, content.arguments, {
|
|
2644
2856
|
showImages: this.settingsManager.getShowImages(),
|
|
2645
2857
|
imageWidthCells: this.settingsManager.getImageWidthCells(),
|
|
2858
|
+
outputPad: this.outputPad,
|
|
2646
2859
|
}, this.getRegisteredToolDefinition(content.name), this.ui, this.sessionManager.getCwd());
|
|
2647
2860
|
component.setExpanded(this.toolOutputExpanded);
|
|
2648
2861
|
this.chatContainer.addChild(component);
|
|
@@ -2673,7 +2886,7 @@ export class InteractiveMode {
|
|
|
2673
2886
|
: "Operation aborted";
|
|
2674
2887
|
this.streamingMessage.errorMessage = errorMessage;
|
|
2675
2888
|
}
|
|
2676
|
-
this.streamingComponent.updateContent(this.streamingMessage);
|
|
2889
|
+
this.streamingComponent.updateContent(this.streamingMessage, false);
|
|
2677
2890
|
if (this.streamingMessage.stopReason === "aborted" || this.streamingMessage.stopReason === "error") {
|
|
2678
2891
|
if (!errorMessage) {
|
|
2679
2892
|
errorMessage = this.streamingMessage.errorMessage || "Error";
|
|
@@ -2705,11 +2918,15 @@ export class InteractiveMode {
|
|
|
2705
2918
|
// The bash execution callback handles TUI output rendering.
|
|
2706
2919
|
break;
|
|
2707
2920
|
case "tool_execution_start": {
|
|
2921
|
+
// Nested calls (from codemode scripts) are shown inside their parent's row.
|
|
2922
|
+
if (event.parentToolCallId)
|
|
2923
|
+
break;
|
|
2708
2924
|
let component = this.pendingTools.get(event.toolCallId);
|
|
2709
2925
|
if (!component) {
|
|
2710
2926
|
component = new ToolExecutionComponent(event.toolName, event.toolCallId, event.args, {
|
|
2711
2927
|
showImages: this.settingsManager.getShowImages(),
|
|
2712
2928
|
imageWidthCells: this.settingsManager.getImageWidthCells(),
|
|
2929
|
+
outputPad: this.outputPad,
|
|
2713
2930
|
}, this.getRegisteredToolDefinition(event.toolName), this.ui, this.sessionManager.getCwd());
|
|
2714
2931
|
component.setExpanded(this.toolOutputExpanded);
|
|
2715
2932
|
this.chatContainer.addChild(component);
|
|
@@ -2729,9 +2946,11 @@ export class InteractiveMode {
|
|
|
2729
2946
|
break;
|
|
2730
2947
|
}
|
|
2731
2948
|
case "tool_execution_end": {
|
|
2949
|
+
if (event.isError)
|
|
2950
|
+
this.maybeShowInstallChangeWarning();
|
|
2732
2951
|
const component = this.pendingTools.get(event.toolCallId);
|
|
2733
2952
|
if (component) {
|
|
2734
|
-
component.updateResult({ ...event.result, isError: event.isError });
|
|
2953
|
+
component.updateResult({ ...event.result, isError: event.isError, durationMs: event.durationMs });
|
|
2735
2954
|
this.pendingTools.delete(event.toolCallId);
|
|
2736
2955
|
this.ui.requestRender();
|
|
2737
2956
|
}
|
|
@@ -2795,9 +3014,21 @@ export class InteractiveMode {
|
|
|
2795
3014
|
}
|
|
2796
3015
|
}
|
|
2797
3016
|
else if (event.result) {
|
|
3017
|
+
const entries = this.sessionManager.buildContextEntries();
|
|
3018
|
+
if (entries[0]?.type !== "compaction") {
|
|
3019
|
+
throw new Error("Completed compaction is missing from the session context");
|
|
3020
|
+
}
|
|
2798
3021
|
this.chatContainer.clear();
|
|
2799
|
-
|
|
3022
|
+
// The latest compaction is prepended for model context; append it below at its chronological position.
|
|
3023
|
+
this.renderSessionEntries(entries.slice(1));
|
|
2800
3024
|
this.addMessageToChat(createCompactionSummaryMessage(event.result.summary, event.result.tokensBefore, new Date().toISOString()));
|
|
3025
|
+
if (event.result.usage) {
|
|
3026
|
+
this.addCompactionCostNotice({
|
|
3027
|
+
type: "compaction_cost",
|
|
3028
|
+
kind: "compaction",
|
|
3029
|
+
usage: event.result.usage,
|
|
3030
|
+
});
|
|
3031
|
+
}
|
|
2801
3032
|
this.footer.invalidate();
|
|
2802
3033
|
}
|
|
2803
3034
|
else if (event.errorMessage) {
|
|
@@ -2806,7 +3037,8 @@ export class InteractiveMode {
|
|
|
2806
3037
|
}
|
|
2807
3038
|
else {
|
|
2808
3039
|
this.chatContainer.addChild(new Spacer(1));
|
|
2809
|
-
|
|
3040
|
+
const errorMessage = event.errorMessage;
|
|
3041
|
+
this.chatContainer.addChild(new ThemedText(() => theme.fg("error", errorMessage), 1, 0));
|
|
2810
3042
|
}
|
|
2811
3043
|
}
|
|
2812
3044
|
void this.flushCompactionQueue({ willRetry: event.willRetry });
|
|
@@ -2878,7 +3110,7 @@ export class InteractiveMode {
|
|
|
2878
3110
|
}
|
|
2879
3111
|
const message = status.type === "warning" ? `Warning: ${status.message}` : status.message;
|
|
2880
3112
|
const color = status.type === "warning" ? "warning" : "dim";
|
|
2881
|
-
this.chatContainer.addChild(new
|
|
3113
|
+
this.chatContainer.addChild(new ThemedText(() => theme.fg(color, message), 1, 0));
|
|
2882
3114
|
this.lastStatusSpacer = undefined;
|
|
2883
3115
|
this.lastStatusText = undefined;
|
|
2884
3116
|
this.ui.requestRender();
|
|
@@ -2894,12 +3126,14 @@ export class InteractiveMode {
|
|
|
2894
3126
|
const last = children.length > 0 ? children[children.length - 1] : undefined;
|
|
2895
3127
|
const secondLast = children.length > 1 ? children[children.length - 2] : undefined;
|
|
2896
3128
|
if (last && secondLast && last === this.lastStatusText && secondLast === this.lastStatusSpacer) {
|
|
2897
|
-
this.
|
|
3129
|
+
this.lastStatusMessage = message;
|
|
3130
|
+
this.lastStatusText.invalidate();
|
|
2898
3131
|
this.ui.requestRender();
|
|
2899
3132
|
return;
|
|
2900
3133
|
}
|
|
2901
3134
|
const spacer = new Spacer(1);
|
|
2902
|
-
|
|
3135
|
+
this.lastStatusMessage = message;
|
|
3136
|
+
const text = new ThemedText(() => theme.fg("dim", this.lastStatusMessage), 1, 0);
|
|
2903
3137
|
this.chatContainer.addChild(spacer);
|
|
2904
3138
|
this.chatContainer.addChild(text);
|
|
2905
3139
|
this.lastStatusSpacer = spacer;
|
|
@@ -2911,7 +3145,7 @@ export class InteractiveMode {
|
|
|
2911
3145
|
if (!renderer) {
|
|
2912
3146
|
return;
|
|
2913
3147
|
}
|
|
2914
|
-
const component = new CustomEntryComponent(entry, renderer);
|
|
3148
|
+
const component = new CustomEntryComponent(entry, renderer, this.outputPad);
|
|
2915
3149
|
component.setExpanded(this.toolOutputExpanded);
|
|
2916
3150
|
if (!component.hasContent()) {
|
|
2917
3151
|
return;
|
|
@@ -2928,7 +3162,7 @@ export class InteractiveMode {
|
|
|
2928
3162
|
addMessageToChat(message, options) {
|
|
2929
3163
|
switch (message.role) {
|
|
2930
3164
|
case "bashExecution": {
|
|
2931
|
-
const component = new BashExecutionComponent(message.command, this.ui, message.excludeFromContext);
|
|
3165
|
+
const component = new BashExecutionComponent(message.command, this.ui, message.excludeFromContext, this.outputPad);
|
|
2932
3166
|
if (message.output) {
|
|
2933
3167
|
component.appendOutput(message.output);
|
|
2934
3168
|
}
|
|
@@ -2947,14 +3181,14 @@ export class InteractiveMode {
|
|
|
2947
3181
|
}
|
|
2948
3182
|
case "compactionSummary": {
|
|
2949
3183
|
this.chatContainer.addChild(new Spacer(1));
|
|
2950
|
-
const component = new CompactionSummaryMessageComponent(message, this.getMarkdownThemeWithSettings());
|
|
3184
|
+
const component = new CompactionSummaryMessageComponent(message, this.getMarkdownThemeWithSettings(), this.outputPad);
|
|
2951
3185
|
component.setExpanded(this.toolOutputExpanded);
|
|
2952
3186
|
this.chatContainer.addChild(component);
|
|
2953
3187
|
break;
|
|
2954
3188
|
}
|
|
2955
3189
|
case "branchSummary": {
|
|
2956
3190
|
this.chatContainer.addChild(new Spacer(1));
|
|
2957
|
-
const component = new BranchSummaryMessageComponent(message, this.getMarkdownThemeWithSettings());
|
|
3191
|
+
const component = new BranchSummaryMessageComponent(message, this.getMarkdownThemeWithSettings(), this.outputPad);
|
|
2958
3192
|
component.setExpanded(this.toolOutputExpanded);
|
|
2959
3193
|
this.chatContainer.addChild(component);
|
|
2960
3194
|
break;
|
|
@@ -2970,18 +3204,18 @@ export class InteractiveMode {
|
|
|
2970
3204
|
const skillBlocks = parseSkillBlocks(textContent);
|
|
2971
3205
|
if (skillBlocks) {
|
|
2972
3206
|
for (const skillBlock of skillBlocks.skills) {
|
|
2973
|
-
const component = new SkillInvocationMessageComponent(skillBlock, this.getMarkdownThemeWithSettings());
|
|
3207
|
+
const component = new SkillInvocationMessageComponent(skillBlock, this.getMarkdownThemeWithSettings(), this.outputPad);
|
|
2974
3208
|
component.setExpanded(this.toolOutputExpanded);
|
|
2975
3209
|
this.chatContainer.addChild(component);
|
|
2976
3210
|
}
|
|
2977
3211
|
if (skillBlocks.userMessage) {
|
|
2978
3212
|
this.chatContainer.addChild(new Spacer(1));
|
|
2979
|
-
const userComponent = new UserMessageComponent(skillBlocks.userMessage, this.getMarkdownThemeWithSettings(), this.outputPad);
|
|
3213
|
+
const userComponent = new UserMessageComponent(skillBlocks.userMessage, this.getMarkdownThemeWithSettings(), this.outputPad, this.getMarkdownTransformers());
|
|
2980
3214
|
this.chatContainer.addChild(userComponent);
|
|
2981
3215
|
}
|
|
2982
3216
|
}
|
|
2983
3217
|
else {
|
|
2984
|
-
const userComponent = new UserMessageComponent(textContent, this.getMarkdownThemeWithSettings(), this.outputPad);
|
|
3218
|
+
const userComponent = new UserMessageComponent(textContent, this.getMarkdownThemeWithSettings(), this.outputPad, this.getMarkdownTransformers());
|
|
2985
3219
|
this.chatContainer.addChild(userComponent);
|
|
2986
3220
|
}
|
|
2987
3221
|
if (options?.populateHistory) {
|
|
@@ -2991,7 +3225,7 @@ export class InteractiveMode {
|
|
|
2991
3225
|
break;
|
|
2992
3226
|
}
|
|
2993
3227
|
case "assistant": {
|
|
2994
|
-
const assistantComponent = new AssistantMessageComponent(message, this.hideThinkingBlock, this.getMarkdownThemeWithSettings(), this.hiddenThinkingLabel, this.outputPad);
|
|
3228
|
+
const assistantComponent = new AssistantMessageComponent(message, this.hideThinkingBlock, this.getMarkdownThemeWithSettings(), this.hiddenThinkingLabel, this.outputPad, this.getMarkdownTransformers());
|
|
2995
3229
|
this.chatContainer.addChild(assistantComponent);
|
|
2996
3230
|
break;
|
|
2997
3231
|
}
|
|
@@ -3043,6 +3277,7 @@ export class InteractiveMode {
|
|
|
3043
3277
|
const component = new ToolExecutionComponent(content.name, content.id, content.arguments, {
|
|
3044
3278
|
showImages: this.settingsManager.getShowImages(),
|
|
3045
3279
|
imageWidthCells: this.settingsManager.getImageWidthCells(),
|
|
3280
|
+
outputPad: this.outputPad,
|
|
3046
3281
|
}, this.getRegisteredToolDefinition(content.name), this.ui, this.sessionManager.getCwd());
|
|
3047
3282
|
component.setExpanded(this.toolOutputExpanded);
|
|
3048
3283
|
this.chatContainer.addChild(component);
|
|
@@ -3096,11 +3331,18 @@ export class InteractiveMode {
|
|
|
3096
3331
|
* @param options.populateHistory Add user messages to editor history
|
|
3097
3332
|
*/
|
|
3098
3333
|
renderSessionEntries(entries, options = {}) {
|
|
3334
|
+
// Selection coordinates point into the transcript being replaced (#9311).
|
|
3335
|
+
if (this.renderer instanceof TuiAltScreen)
|
|
3336
|
+
this.renderer.resetTextSelection();
|
|
3099
3337
|
const items = entries.flatMap((entry) => {
|
|
3100
3338
|
if (entry.type === "custom" || (entry.type === "usage" && entry.kind === "cache_warm")) {
|
|
3101
3339
|
return [entry];
|
|
3102
3340
|
}
|
|
3103
|
-
|
|
3341
|
+
const messages = sessionEntryToContextMessages(entry);
|
|
3342
|
+
if ((entry.type === "compaction" || entry.type === "branch_summary") && entry.usage && messages.length > 0) {
|
|
3343
|
+
return [...messages, { type: "compaction_cost", kind: entry.type, usage: entry.usage }];
|
|
3344
|
+
}
|
|
3345
|
+
return messages;
|
|
3104
3346
|
});
|
|
3105
3347
|
this.renderSessionItems(items, options);
|
|
3106
3348
|
}
|
|
@@ -3108,7 +3350,8 @@ export class InteractiveMode {
|
|
|
3108
3350
|
if (!this.settingsManager.getShowCacheMissNotices())
|
|
3109
3351
|
return;
|
|
3110
3352
|
this.chatContainer.addChild(new Spacer(1));
|
|
3111
|
-
|
|
3353
|
+
const usage = formatCacheWarmingUsage(entry);
|
|
3354
|
+
this.chatContainer.addChild(new ThemedText(() => theme.fg("dim", usage), 1, 0));
|
|
3112
3355
|
}
|
|
3113
3356
|
/**
|
|
3114
3357
|
* Render billing usage for a compaction or branch summary. The notice is derived
|
|
@@ -3122,7 +3365,7 @@ export class InteractiveMode {
|
|
|
3122
3365
|
const cost = usage.cost.total >= 0.01 ? ` (~$${usage.cost.total.toFixed(2)})` : "";
|
|
3123
3366
|
const label = notice.kind === "compaction" ? "Compaction" : "Branch summary";
|
|
3124
3367
|
this.chatContainer.addChild(new Spacer(1));
|
|
3125
|
-
this.chatContainer.addChild(new
|
|
3368
|
+
this.chatContainer.addChild(new ThemedText(() => theme.fg("warning", `${label}: ${formatTokens(tokens)} tokens billed${cost}`), 1, 0));
|
|
3126
3369
|
}
|
|
3127
3370
|
static countDroppedThinkingBlocks(message) {
|
|
3128
3371
|
let count = 0;
|
|
@@ -3159,7 +3402,7 @@ export class InteractiveMode {
|
|
|
3159
3402
|
return;
|
|
3160
3403
|
const noun = droppedCount === 1 ? "thinking block" : "thinking blocks";
|
|
3161
3404
|
this.chatContainer.addChild(new Spacer(1));
|
|
3162
|
-
this.chatContainer.addChild(new
|
|
3405
|
+
this.chatContainer.addChild(new ThemedText(() => theme.fg("warning", `Anthropic dropped ${droppedCount} ${noun} (details in session)`), 1, 0));
|
|
3163
3406
|
}
|
|
3164
3407
|
/**
|
|
3165
3408
|
* Show a transcript notice when a completed assistant message paid for a
|
|
@@ -3186,9 +3429,8 @@ export class InteractiveMode {
|
|
|
3186
3429
|
else if (miss.idleMs >= CACHE_TTL_MS) {
|
|
3187
3430
|
label = `Cache miss after ${Math.round(miss.idleMs / 60_000)}m idle`;
|
|
3188
3431
|
}
|
|
3189
|
-
const text = theme.fg("warning", `${label}: ${reBilled}`);
|
|
3190
3432
|
this.chatContainer.addChild(new Spacer(1));
|
|
3191
|
-
this.chatContainer.addChild(new
|
|
3433
|
+
this.chatContainer.addChild(new ThemedText(() => theme.fg("warning", `${label}: ${reBilled}`), 1, 0));
|
|
3192
3434
|
}
|
|
3193
3435
|
renderInitialMessages() {
|
|
3194
3436
|
const entries = this.sessionManager.buildContextEntries();
|
|
@@ -3216,7 +3458,7 @@ export class InteractiveMode {
|
|
|
3216
3458
|
if (this.chatContainer.children.length > 0) {
|
|
3217
3459
|
this.chatContainer.addChild(new Spacer(1));
|
|
3218
3460
|
}
|
|
3219
|
-
this.chatContainer.addChild(new
|
|
3461
|
+
this.chatContainer.addChild(new ThemedText(() => theme.fg("warning", `This project is not trusted. Project ${CONFIG_DIR_NAME} resources and packages are ignored. Use /trust to save a trust decision, then restart pi.`), 1, 0));
|
|
3220
3462
|
}
|
|
3221
3463
|
async getUserInput() {
|
|
3222
3464
|
const queuedInput = this.pendingUserInputs.shift();
|
|
@@ -3313,6 +3555,10 @@ export class InteractiveMode {
|
|
|
3313
3555
|
* paste / Kitty / modifyOtherKeys sequences.
|
|
3314
3556
|
*/
|
|
3315
3557
|
uncaughtCrash(error) {
|
|
3558
|
+
// A dead terminal is not a pi crash. Do not try to restore it or record it.
|
|
3559
|
+
if (isDeadTerminalError(error)) {
|
|
3560
|
+
this.emergencyTerminalExit();
|
|
3561
|
+
}
|
|
3316
3562
|
if (this.isShuttingDown) {
|
|
3317
3563
|
process.exit(1);
|
|
3318
3564
|
}
|
|
@@ -3331,6 +3577,9 @@ export class InteractiveMode {
|
|
|
3331
3577
|
catch { }
|
|
3332
3578
|
console.error(`${APP_NAME} exiting due to uncaughtException:`);
|
|
3333
3579
|
console.error(error);
|
|
3580
|
+
const extensionHint = this.getCrashExtensionHint(error);
|
|
3581
|
+
if (extensionHint)
|
|
3582
|
+
console.error(`\n${extensionHint}`);
|
|
3334
3583
|
if (this.recordCrash("uncaught_exception", error)) {
|
|
3335
3584
|
console.error(`\n${this.crashReportInstructions()}`);
|
|
3336
3585
|
}
|
|
@@ -3368,10 +3617,13 @@ export class InteractiveMode {
|
|
|
3368
3617
|
}
|
|
3369
3618
|
throw error;
|
|
3370
3619
|
};
|
|
3371
|
-
|
|
3372
|
-
process
|
|
3373
|
-
|
|
3374
|
-
|
|
3620
|
+
// stdin needs the handler too: once the terminal is gone, reads and setRawMode
|
|
3621
|
+
// fail with EIO (orphaned background process group) or ENOTTY (revoked tty).
|
|
3622
|
+
// Node emits these as stream errors, which are uncaught without a listener.
|
|
3623
|
+
for (const stream of [process.stdin, process.stdout, process.stderr]) {
|
|
3624
|
+
stream.on("error", terminalErrorHandler);
|
|
3625
|
+
this.signalCleanupHandlers.push(() => stream.off("error", terminalErrorHandler));
|
|
3626
|
+
}
|
|
3375
3627
|
// Restore the terminal before the process dies on any uncaught throw.
|
|
3376
3628
|
// Without this, an unhandled exception from extension code (or anywhere
|
|
3377
3629
|
// in pi) leaves the terminal in raw mode with no cursor.
|
|
@@ -3504,6 +3756,8 @@ export class InteractiveMode {
|
|
|
3504
3756
|
this.setToolsExpanded(!this.toolOutputExpanded);
|
|
3505
3757
|
}
|
|
3506
3758
|
setToolsExpanded(expanded) {
|
|
3759
|
+
if (expanded === this.toolOutputExpanded)
|
|
3760
|
+
return;
|
|
3507
3761
|
this.toolOutputExpanded = expanded;
|
|
3508
3762
|
const activeHeader = this.customHeader ?? this.builtInHeader;
|
|
3509
3763
|
if (isExpandable(activeHeader)) {
|
|
@@ -3561,20 +3815,20 @@ export class InteractiveMode {
|
|
|
3561
3815
|
}
|
|
3562
3816
|
showError(errorMessage) {
|
|
3563
3817
|
this.chatContainer.addChild(new Spacer(1));
|
|
3564
|
-
this.chatContainer.addChild(new
|
|
3818
|
+
this.chatContainer.addChild(new ThemedText(() => theme.fg("error", `Error: ${errorMessage}`), this.outputPad, 0));
|
|
3565
3819
|
this.ui.requestRender();
|
|
3566
3820
|
}
|
|
3567
3821
|
showWarning(warningMessage) {
|
|
3568
3822
|
this.chatContainer.addChild(new Spacer(1));
|
|
3569
|
-
this.chatContainer.addChild(new
|
|
3823
|
+
this.chatContainer.addChild(new ThemedText(() => theme.fg("warning", `Warning: ${warningMessage}`), 1, 0));
|
|
3570
3824
|
this.ui.requestRender();
|
|
3571
3825
|
}
|
|
3572
3826
|
showNewVersionNotification(release) {
|
|
3573
|
-
const updateInstruction = `New version ${release.version} is available. ${getUpdateInstruction(PACKAGE_NAME)}`;
|
|
3827
|
+
const updateInstruction = () => `New version ${release.version} is available. ${getUpdateInstruction(PACKAGE_NAME)}`;
|
|
3574
3828
|
const note = release.note?.trim();
|
|
3575
3829
|
this.chatContainer.addChild(new Spacer(1));
|
|
3576
3830
|
this.chatContainer.addChild(new DynamicBorder((text) => theme.fg("warning", text)));
|
|
3577
|
-
this.chatContainer.addChild(new
|
|
3831
|
+
this.chatContainer.addChild(new ThemedText(() => `${theme.bold(theme.fg("warning", "Update Available"))}\n${updateInstruction()}`, 1, 0));
|
|
3578
3832
|
if (note) {
|
|
3579
3833
|
this.chatContainer.addChild(new Spacer(1));
|
|
3580
3834
|
this.chatContainer.addChild(new Markdown(note, 1, 0, this.getMarkdownThemeWithSettings(), {
|
|
@@ -3585,12 +3839,12 @@ export class InteractiveMode {
|
|
|
3585
3839
|
this.ui.requestRender();
|
|
3586
3840
|
}
|
|
3587
3841
|
showPackageUpdateNotification(packages) {
|
|
3588
|
-
const
|
|
3589
|
-
|
|
3842
|
+
const updateInstruction = () => theme.fg("muted", "Package updates are available. Run ") +
|
|
3843
|
+
theme.fg("accent", `${APP_NAME} update --extensions`);
|
|
3590
3844
|
const packageLines = packages.map((pkg) => `- ${pkg}`).join("\n");
|
|
3591
3845
|
this.chatContainer.addChild(new Spacer(1));
|
|
3592
3846
|
this.chatContainer.addChild(new DynamicBorder((text) => theme.fg("warning", text)));
|
|
3593
|
-
this.chatContainer.addChild(new
|
|
3847
|
+
this.chatContainer.addChild(new ThemedText(() => `${theme.bold(theme.fg("warning", "Package Updates Available"))}\n${updateInstruction()}\n${theme.fg("muted", "Packages:")}\n${packageLines}`, 1, 0));
|
|
3594
3848
|
this.chatContainer.addChild(new DynamicBorder((text) => theme.fg("warning", text)));
|
|
3595
3849
|
this.ui.requestRender();
|
|
3596
3850
|
}
|
|
@@ -3763,29 +4017,43 @@ export class InteractiveMode {
|
|
|
3763
4017
|
// =========================================================================
|
|
3764
4018
|
// Selectors
|
|
3765
4019
|
// =========================================================================
|
|
4020
|
+
disposeActiveSelector() {
|
|
4021
|
+
const dispose = this.activeSelectorDispose;
|
|
4022
|
+
this.activeSelectorToken = undefined;
|
|
4023
|
+
this.activeSelectorDispose = undefined;
|
|
4024
|
+
dispose?.();
|
|
4025
|
+
}
|
|
3766
4026
|
/**
|
|
3767
4027
|
* Shows a selector component in place of the editor.
|
|
3768
4028
|
* @param create Factory that receives a `done` callback and returns the component and focus target
|
|
3769
4029
|
*/
|
|
3770
4030
|
showSelector(create) {
|
|
4031
|
+
const token = {};
|
|
4032
|
+
let dispose;
|
|
3771
4033
|
const done = () => {
|
|
4034
|
+
dispose?.();
|
|
4035
|
+
if (this.activeSelectorToken !== token)
|
|
4036
|
+
return;
|
|
4037
|
+
this.activeSelectorToken = undefined;
|
|
4038
|
+
this.activeSelectorDispose = undefined;
|
|
3772
4039
|
this.editorContainer.clear();
|
|
3773
4040
|
this.editorContainer.addChild(this.editor);
|
|
3774
4041
|
this.ui.setFocus(this.editor);
|
|
3775
4042
|
};
|
|
3776
|
-
const
|
|
4043
|
+
const created = create(done);
|
|
4044
|
+
dispose = created.dispose;
|
|
4045
|
+
this.disposeActiveSelector();
|
|
4046
|
+
this.activeSelectorToken = token;
|
|
4047
|
+
this.activeSelectorDispose = dispose;
|
|
3777
4048
|
this.editorContainer.clear();
|
|
3778
|
-
this.editorContainer.addChild(component);
|
|
3779
|
-
this.ui.setFocus(focus);
|
|
4049
|
+
this.editorContainer.addChild(created.component);
|
|
4050
|
+
this.ui.setFocus(created.focus);
|
|
3780
4051
|
this.ui.requestRender();
|
|
3781
4052
|
}
|
|
3782
4053
|
showSettingsSelector() {
|
|
3783
4054
|
this.showSelector((done) => {
|
|
3784
4055
|
const selector = new SettingsSelectorComponent({
|
|
3785
4056
|
autoCompact: this.session.autoCompactionEnabled,
|
|
3786
|
-
autoHandoffEnabled: this.settingsManager.getAutoHandoffEnabled(),
|
|
3787
|
-
autoHandoffThresholdTokens: this.settingsManager.getAutoHandoffThresholdTokens(),
|
|
3788
|
-
capabilityGatewayJevEnabled: this.settingsManager.getCapabilityGatewayJevEnabled(),
|
|
3789
4057
|
defaultModel: (() => {
|
|
3790
4058
|
const defaultProvider = this.settingsManager.getDefaultProvider();
|
|
3791
4059
|
const defaultModelId = this.settingsManager.getDefaultModel();
|
|
@@ -3803,11 +4071,11 @@ export class InteractiveMode {
|
|
|
3803
4071
|
visionModelSelector: (currentValue, selectorDone) => {
|
|
3804
4072
|
const slash = currentValue.indexOf("/");
|
|
3805
4073
|
const currentModel = slash > 0 ? this.session.modelRuntime.getModel(currentValue.slice(0, slash), currentValue.slice(slash + 1)) : undefined;
|
|
3806
|
-
return new ModelSelectorComponent(this.ui, currentModel, this.
|
|
4074
|
+
return new ModelSelectorComponent(this.ui, currentModel, this.session.modelRuntime, this.session.scopedModels, (model) => {
|
|
3807
4075
|
this.settingsManager.setImageCaptionModel(model ? `${model.provider}/${model.id}` : undefined);
|
|
3808
4076
|
selectorDone(model ? `${model.provider}/${model.id}` : "off");
|
|
3809
4077
|
this.showStatus(model ? `Vision caption model: ${model.provider}/${model.id}` : "Vision captioning disabled");
|
|
3810
|
-
}, selectorDone, undefined, { modelFilter: (model) => model.input.includes("image"), allowOff: true
|
|
4078
|
+
}, selectorDone, undefined, undefined, undefined, { modelFilter: (model) => model.input.includes("image"), allowOff: true });
|
|
3811
4079
|
},
|
|
3812
4080
|
steeringMode: this.session.steeringMode,
|
|
3813
4081
|
followUpMode: this.session.followUpMode,
|
|
@@ -3817,10 +4085,11 @@ export class InteractiveMode {
|
|
|
3817
4085
|
thinkingLevel: this.settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL,
|
|
3818
4086
|
availableThinkingLevels: [...THINKING_LEVEL_OPTIONS],
|
|
3819
4087
|
modelThinkingLevels: this.settingsManager.getAllModelThinkingLevels(),
|
|
3820
|
-
currentTheme: this.themeController.getThemeSelection() ||
|
|
4088
|
+
currentTheme: this.themeController.getThemeSelection() || SYSTEM_THEME_NAME,
|
|
3821
4089
|
terminalTheme: this.themeController.getTerminalTheme(),
|
|
3822
4090
|
availableThemes: getAvailableThemes(),
|
|
3823
4091
|
hideThinkingBlock: this.hideThinkingBlock,
|
|
4092
|
+
mermaidRenderingMode: this.settingsManager.getMermaidRenderingMode(),
|
|
3824
4093
|
collapseChangelog: this.settingsManager.getCollapseChangelog(),
|
|
3825
4094
|
enableInstallTelemetry: this.settingsManager.getEnableInstallTelemetry(),
|
|
3826
4095
|
doubleEscapeAction: this.settingsManager.getDoubleEscapeAction(),
|
|
@@ -3838,6 +4107,7 @@ export class InteractiveMode {
|
|
|
3838
4107
|
fullscreenExitOutput: this.settingsManager.getFullscreenExitOutput(),
|
|
3839
4108
|
fullscreenScrollbar: this.settingsManager.getFullscreenScrollbar(),
|
|
3840
4109
|
fullscreenCopyOnSelect: this.settingsManager.getFullscreenCopyOnSelect(),
|
|
4110
|
+
fullscreenWheelScrollLines: this.settingsManager.getFullscreenWheelScrollLines(),
|
|
3841
4111
|
warnings: this.settingsManager.getWarnings(),
|
|
3842
4112
|
skills: this.buildSkillToggleItems(),
|
|
3843
4113
|
}, {
|
|
@@ -3845,29 +4115,6 @@ export class InteractiveMode {
|
|
|
3845
4115
|
this.session.setAutoCompactionEnabled(enabled);
|
|
3846
4116
|
this.footer.setAutoCompactEnabled(enabled);
|
|
3847
4117
|
},
|
|
3848
|
-
onAutoHandoffEnabledChange: (enabled) => {
|
|
3849
|
-
this.settingsManager.setAutoHandoffEnabled(enabled);
|
|
3850
|
-
},
|
|
3851
|
-
onAutoHandoffThresholdTokensChange: (tokens) => {
|
|
3852
|
-
this.settingsManager.setAutoHandoffThresholdTokens(tokens);
|
|
3853
|
-
},
|
|
3854
|
-
onCapabilityGatewayJevChange: (enabled) => {
|
|
3855
|
-
if (enabled && !this.session.modelRuntime.getProviderAuthStatus("tokenin").configured) {
|
|
3856
|
-
this.showStatus("Token-In is required for Jev routing; starting /tokenin add");
|
|
3857
|
-
done();
|
|
3858
|
-
void this.session
|
|
3859
|
-
.prompt("/tokenin add")
|
|
3860
|
-
.then(() => {
|
|
3861
|
-
if (this.session.modelRuntime.getProviderAuthStatus("tokenin").configured) {
|
|
3862
|
-
this.settingsManager.setCapabilityGatewayJevEnabled(true);
|
|
3863
|
-
}
|
|
3864
|
-
})
|
|
3865
|
-
.catch((error) => this.showError(`Could not start Token-In setup: ${String(error)}`));
|
|
3866
|
-
return false;
|
|
3867
|
-
}
|
|
3868
|
-
this.settingsManager.setCapabilityGatewayJevEnabled(enabled);
|
|
3869
|
-
return true;
|
|
3870
|
-
},
|
|
3871
4118
|
onShowImagesChange: (enabled) => {
|
|
3872
4119
|
this.settingsManager.setShowImages(enabled);
|
|
3873
4120
|
for (const child of this.chatContainer.children) {
|
|
@@ -3919,6 +4166,7 @@ export class InteractiveMode {
|
|
|
3919
4166
|
},
|
|
3920
4167
|
onModelThinkingLevelChange: (provider, modelId, level) => {
|
|
3921
4168
|
this.settingsManager.setModelThinkingLevel(provider, modelId, level);
|
|
4169
|
+
// If the override is for the current model, apply it to the session too
|
|
3922
4170
|
const current = this.session.model;
|
|
3923
4171
|
if (current && current.provider === provider && current.id === modelId) {
|
|
3924
4172
|
this.session.setThinkingLevel(level);
|
|
@@ -3928,6 +4176,7 @@ export class InteractiveMode {
|
|
|
3928
4176
|
},
|
|
3929
4177
|
onModelThinkingLevelRemove: (provider, modelId) => {
|
|
3930
4178
|
this.settingsManager.removeModelThinkingLevel(provider, modelId);
|
|
4179
|
+
// If the override was for the current model, revert to global default
|
|
3931
4180
|
const current = this.session.model;
|
|
3932
4181
|
if (current && current.provider === provider && current.id === modelId) {
|
|
3933
4182
|
const globalDefault = this.settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL;
|
|
@@ -3936,14 +4185,9 @@ export class InteractiveMode {
|
|
|
3936
4185
|
this.updateEditorBorderColor();
|
|
3937
4186
|
}
|
|
3938
4187
|
},
|
|
3939
|
-
onThinkingLevelChange: (level) => {
|
|
3940
|
-
this.session.setThinkingLevel(level);
|
|
3941
|
-
this.footer.invalidate();
|
|
3942
|
-
this.updateEditorBorderColor();
|
|
3943
|
-
},
|
|
3944
4188
|
onThemeChange: (themeSetting) => {
|
|
3945
4189
|
this.settingsManager.setTheme(themeSetting);
|
|
3946
|
-
|
|
4190
|
+
this.themeController.setThemeSetting(themeSetting);
|
|
3947
4191
|
},
|
|
3948
4192
|
onThemePreview: (themeName) => this.themeController.preview(themeName),
|
|
3949
4193
|
onHideThinkingBlockChange: (hidden) => {
|
|
@@ -3951,6 +4195,11 @@ export class InteractiveMode {
|
|
|
3951
4195
|
this.settingsManager.setHideThinkingBlock(hidden);
|
|
3952
4196
|
this.updateThinkingBlockVisibility();
|
|
3953
4197
|
},
|
|
4198
|
+
onMermaidRenderingModeChange: (mode) => {
|
|
4199
|
+
this.settingsManager.setMermaidRenderingMode(mode);
|
|
4200
|
+
this.chatContainer.invalidate();
|
|
4201
|
+
this.ui.requestRender();
|
|
4202
|
+
},
|
|
3954
4203
|
onShowCacheMissNoticesChange: (shown) => {
|
|
3955
4204
|
this.settingsManager.setShowCacheMissNotices(shown);
|
|
3956
4205
|
this.rebuildChatFromMessages();
|
|
@@ -3961,8 +4210,8 @@ export class InteractiveMode {
|
|
|
3961
4210
|
onEnableInstallTelemetryChange: (enabled) => {
|
|
3962
4211
|
this.settingsManager.setEnableInstallTelemetry(enabled);
|
|
3963
4212
|
},
|
|
3964
|
-
onQuietStartupChange: (
|
|
3965
|
-
this.settingsManager.setQuietStartup(
|
|
4213
|
+
onQuietStartupChange: (quiet) => {
|
|
4214
|
+
this.settingsManager.setQuietStartup(quiet);
|
|
3966
4215
|
},
|
|
3967
4216
|
onDefaultProjectTrustChange: (defaultProjectTrust) => {
|
|
3968
4217
|
this.settingsManager.setDefaultProjectTrust(defaultProjectTrust);
|
|
@@ -3987,21 +4236,14 @@ export class InteractiveMode {
|
|
|
3987
4236
|
onOutputPadChange: (padding) => {
|
|
3988
4237
|
this.settingsManager.setOutputPad(padding);
|
|
3989
4238
|
this.outputPad = padding;
|
|
3990
|
-
|
|
3991
|
-
for (const child of
|
|
3992
|
-
if (child
|
|
3993
|
-
child instanceof CustomMessageComponent ||
|
|
3994
|
-
child instanceof UserMessageComponent) {
|
|
4239
|
+
for (const container of [this.chatContainer, this.pendingMessagesContainer]) {
|
|
4240
|
+
for (const child of container.children) {
|
|
4241
|
+
if ("setOutputPad" in child && typeof child.setOutputPad === "function") {
|
|
3995
4242
|
child.setOutputPad(padding);
|
|
3996
4243
|
}
|
|
3997
4244
|
}
|
|
3998
|
-
if (this.streamingComponent) {
|
|
3999
|
-
this.streamingComponent.setOutputPad(padding);
|
|
4000
|
-
}
|
|
4001
|
-
this.ui.requestRender();
|
|
4002
|
-
return;
|
|
4003
4245
|
}
|
|
4004
|
-
this.
|
|
4246
|
+
this.ui.requestRender();
|
|
4005
4247
|
},
|
|
4006
4248
|
onAutocompleteMaxVisibleChange: (maxVisible) => {
|
|
4007
4249
|
this.settingsManager.setAutocompleteMaxVisible(maxVisible);
|
|
@@ -4044,6 +4286,11 @@ export class InteractiveMode {
|
|
|
4044
4286
|
if (this.renderer instanceof TuiAltScreen)
|
|
4045
4287
|
this.renderer.setCopyOnSelect(enabled);
|
|
4046
4288
|
},
|
|
4289
|
+
onFullscreenWheelScrollLinesChange: (lines) => {
|
|
4290
|
+
this.settingsManager.setFullscreenWheelScrollLines(lines);
|
|
4291
|
+
if (this.renderer instanceof TuiAltScreen)
|
|
4292
|
+
this.renderer.setWheelScrollLines(lines);
|
|
4293
|
+
},
|
|
4047
4294
|
onWarningsChange: (warnings) => {
|
|
4048
4295
|
this.settingsManager.setWarnings(warnings);
|
|
4049
4296
|
},
|
|
@@ -4061,6 +4308,44 @@ export class InteractiveMode {
|
|
|
4061
4308
|
return { component: selector, focus: selector.getSettingsList() };
|
|
4062
4309
|
});
|
|
4063
4310
|
}
|
|
4311
|
+
handleThinkingCommand(searchTerm) {
|
|
4312
|
+
const availableLevels = this.session.getAvailableThinkingLevels();
|
|
4313
|
+
if (!searchTerm) {
|
|
4314
|
+
this.showThinkingSelector();
|
|
4315
|
+
return;
|
|
4316
|
+
}
|
|
4317
|
+
const normalized = searchTerm.trim().toLowerCase();
|
|
4318
|
+
const level = availableLevels.find((candidate) => candidate.toLowerCase() === normalized);
|
|
4319
|
+
if (!level) {
|
|
4320
|
+
this.showError(`Unknown thinking level "${searchTerm}". Available levels: ${availableLevels.join(", ")}.`);
|
|
4321
|
+
return;
|
|
4322
|
+
}
|
|
4323
|
+
this.selectThinkingLevel(level, false);
|
|
4324
|
+
}
|
|
4325
|
+
selectThinkingLevel(level, persist) {
|
|
4326
|
+
try {
|
|
4327
|
+
this.session.setThinkingLevel(level, { persist });
|
|
4328
|
+
this.footer.invalidate();
|
|
4329
|
+
this.updateEditorBorderColor();
|
|
4330
|
+
this.showStatus(persist ? `Default thinking level: ${level}` : `Thinking level: ${level}`);
|
|
4331
|
+
}
|
|
4332
|
+
catch (error) {
|
|
4333
|
+
this.showError(error instanceof Error ? error.message : String(error));
|
|
4334
|
+
}
|
|
4335
|
+
}
|
|
4336
|
+
showThinkingSelector() {
|
|
4337
|
+
this.showSelector((done) => {
|
|
4338
|
+
const selectLevel = (level, persist) => {
|
|
4339
|
+
this.selectThinkingLevel(level, persist);
|
|
4340
|
+
done();
|
|
4341
|
+
};
|
|
4342
|
+
const selector = new ThinkingSelectorComponent(this.session.thinkingLevel ?? DEFAULT_THINKING_LEVEL, this.session.getAvailableThinkingLevels(), (level) => selectLevel(level, false), () => {
|
|
4343
|
+
done();
|
|
4344
|
+
this.ui.requestRender();
|
|
4345
|
+
}, (level) => selectLevel(level, true), this.settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL);
|
|
4346
|
+
return { component: selector, focus: selector };
|
|
4347
|
+
});
|
|
4348
|
+
}
|
|
4064
4349
|
getVisionModels() {
|
|
4065
4350
|
try {
|
|
4066
4351
|
const models = this.session.scopedModels.length > 0
|
|
@@ -4136,12 +4421,11 @@ export class InteractiveMode {
|
|
|
4136
4421
|
const model = await this.findExactModelMatch(searchTerm);
|
|
4137
4422
|
if (model) {
|
|
4138
4423
|
try {
|
|
4139
|
-
await this.session.setModel(model);
|
|
4424
|
+
await this.session.setModel(model, { persist: false });
|
|
4140
4425
|
this.footer.invalidate();
|
|
4141
4426
|
this.updateEditorBorderColor();
|
|
4142
4427
|
this.showStatus(`Model: ${model.id}`);
|
|
4143
4428
|
void this.maybeWarnAboutAnthropicSubscriptionAuth(model);
|
|
4144
|
-
this.checkDaxnutsEasterEgg(model);
|
|
4145
4429
|
}
|
|
4146
4430
|
catch (error) {
|
|
4147
4431
|
this.showError(error instanceof Error ? error.message : String(error));
|
|
@@ -4151,21 +4435,37 @@ export class InteractiveMode {
|
|
|
4151
4435
|
this.showModelSelector(searchTerm);
|
|
4152
4436
|
}
|
|
4153
4437
|
async findExactModelMatch(searchTerm) {
|
|
4154
|
-
const
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
if (this.session.scopedModels.length > 0)
|
|
4159
|
-
return
|
|
4160
|
-
|
|
4438
|
+
const cachedModels = this.session.scopedModels.length > 0
|
|
4439
|
+
? this.session.scopedModels.map((scoped) => scoped.model)
|
|
4440
|
+
: [...this.session.modelRuntime.getAvailableSnapshot()];
|
|
4441
|
+
const cachedMatch = findExactModelReferenceMatch(searchTerm, cachedModels);
|
|
4442
|
+
if (cachedMatch || this.session.scopedModels.length > 0)
|
|
4443
|
+
return cachedMatch;
|
|
4444
|
+
this.showStatus("Refreshing model catalogs…");
|
|
4445
|
+
const controller = new AbortController();
|
|
4446
|
+
let timedOut = false;
|
|
4447
|
+
const timeout = setTimeout(() => {
|
|
4448
|
+
timedOut = true;
|
|
4449
|
+
controller.abort();
|
|
4450
|
+
}, 15_000);
|
|
4161
4451
|
try {
|
|
4162
|
-
const
|
|
4163
|
-
|
|
4164
|
-
|
|
4452
|
+
const result = await refreshModelCatalogs(this.session.modelRuntime, controller.signal);
|
|
4453
|
+
if (result.aborted && timedOut) {
|
|
4454
|
+
this.showWarning("Model refresh timed out; searching cached models.");
|
|
4455
|
+
}
|
|
4456
|
+
else if (result.errors.size > 0) {
|
|
4457
|
+
this.showWarning(`Could not refresh ${[...result.errors.keys()].join(", ")}; searching cached models.`);
|
|
4458
|
+
}
|
|
4165
4459
|
}
|
|
4166
|
-
catch {
|
|
4167
|
-
|
|
4460
|
+
catch (error) {
|
|
4461
|
+
this.showWarning(timedOut
|
|
4462
|
+
? "Model refresh timed out; searching cached models."
|
|
4463
|
+
: `Could not refresh model catalogs: ${error instanceof Error ? error.message : String(error)}`);
|
|
4168
4464
|
}
|
|
4465
|
+
finally {
|
|
4466
|
+
clearTimeout(timeout);
|
|
4467
|
+
}
|
|
4468
|
+
return findExactModelReferenceMatch(searchTerm, [...this.session.modelRuntime.getAvailableSnapshot()]);
|
|
4169
4469
|
}
|
|
4170
4470
|
/** Update the footer's available provider count from the current snapshot without refreshing catalogs. */
|
|
4171
4471
|
updateAvailableProviderCount() {
|
|
@@ -4249,95 +4549,91 @@ export class InteractiveMode {
|
|
|
4249
4549
|
}
|
|
4250
4550
|
showModelSelector(initialSearchInput) {
|
|
4251
4551
|
this.showSelector((done) => {
|
|
4252
|
-
const
|
|
4253
|
-
if (!model)
|
|
4254
|
-
return;
|
|
4552
|
+
const selectModel = async (model, persist) => {
|
|
4255
4553
|
try {
|
|
4256
|
-
await this.session.setModel(model);
|
|
4554
|
+
await this.session.setModel(model, { persist });
|
|
4257
4555
|
this.updateAvailableProviderCount();
|
|
4258
4556
|
this.footer.invalidate();
|
|
4259
4557
|
this.updateEditorBorderColor();
|
|
4260
4558
|
done();
|
|
4261
|
-
this.showStatus(`Model: ${model.id}`);
|
|
4559
|
+
this.showStatus(persist ? `Default model: ${model.provider}/${model.id}` : `Model: ${model.id}`);
|
|
4262
4560
|
void this.maybeWarnAboutAnthropicSubscriptionAuth(model);
|
|
4263
|
-
this.checkDaxnutsEasterEgg(model);
|
|
4264
4561
|
}
|
|
4265
4562
|
catch (error) {
|
|
4266
4563
|
done();
|
|
4267
4564
|
this.showError(error instanceof Error ? error.message : String(error));
|
|
4268
4565
|
}
|
|
4566
|
+
};
|
|
4567
|
+
const defaultProvider = this.settingsManager.getDefaultProvider();
|
|
4568
|
+
const defaultModel = this.settingsManager.getDefaultModel();
|
|
4569
|
+
const selector = new ModelSelectorComponent(this.ui, this.session.model, this.session.modelRuntime, this.session.scopedModels, (model) => {
|
|
4570
|
+
if (model)
|
|
4571
|
+
selectModel(model, false);
|
|
4269
4572
|
}, () => {
|
|
4270
4573
|
done();
|
|
4271
4574
|
this.ui.requestRender();
|
|
4272
|
-
}, initialSearchInput);
|
|
4273
|
-
return { component: selector, focus: selector };
|
|
4575
|
+
}, initialSearchInput, (model) => selectModel(model, true), defaultProvider && defaultModel ? { provider: defaultProvider, id: defaultModel } : undefined);
|
|
4576
|
+
return { component: selector, focus: selector, dispose: () => selector.dispose() };
|
|
4274
4577
|
});
|
|
4275
4578
|
}
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
await refreshModelCatalogs(this.session.modelRuntime, controller.signal);
|
|
4280
|
-
const allModels = [...(await this.session.modelRuntime.getAvailable())];
|
|
4281
|
-
const allModelIds = new Set(allModels.map((model) => `${model.provider}/${model.id}`));
|
|
4579
|
+
showModelsSelector() {
|
|
4580
|
+
let availableModels = [...this.session.modelRuntime.getAvailableSnapshot()];
|
|
4581
|
+
let availableModelIds = new Set(availableModels.map((model) => `${model.provider}/${model.id}`));
|
|
4282
4582
|
const configuredPatterns = this.settingsManager.getEnabledModels();
|
|
4283
4583
|
const sessionScopedModels = this.session.scopedModels;
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
|
|
4292
|
-
|
|
4293
|
-
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
currentEnabledIds = configuredScope.scopedModels.map((scoped) => `${scoped.model.provider}/${scoped.model.id}`);
|
|
4301
|
-
}
|
|
4302
|
-
for (const diagnostic of configuredScope?.diagnostics ?? []) {
|
|
4303
|
-
if (diagnostic.code !== "no-match")
|
|
4304
|
-
continue;
|
|
4305
|
-
currentEnabledIds ??= [];
|
|
4306
|
-
if (!currentEnabledIds.includes(diagnostic.pattern))
|
|
4307
|
-
currentEnabledIds.push(diagnostic.pattern);
|
|
4308
|
-
}
|
|
4309
|
-
// Helper to update session's scoped models (session-only, no persist)
|
|
4310
|
-
const updateSessionModels = async (enabledIds) => {
|
|
4584
|
+
const configuredEnabledIds = (models) => {
|
|
4585
|
+
if (!configuredPatterns?.length)
|
|
4586
|
+
return null;
|
|
4587
|
+
const resolved = resolveModelScopeFromModels(configuredPatterns, models);
|
|
4588
|
+
const ids = resolved.scopedModels.map((scoped) => `${scoped.model.provider}/${scoped.model.id}`);
|
|
4589
|
+
for (const diagnostic of resolved.diagnostics) {
|
|
4590
|
+
if (diagnostic.code === "no-match" && !ids.includes(diagnostic.pattern))
|
|
4591
|
+
ids.push(diagnostic.pattern);
|
|
4592
|
+
}
|
|
4593
|
+
return ids;
|
|
4594
|
+
};
|
|
4595
|
+
let currentEnabledIds = sessionScopedModels.length > 0
|
|
4596
|
+
? sessionScopedModels.map((scoped) => `${scoped.model.provider}/${scoped.model.id}`)
|
|
4597
|
+
: configuredEnabledIds(availableModels);
|
|
4598
|
+
let selectionChanged = false;
|
|
4599
|
+
const updateSessionModels = (enabledIds) => {
|
|
4311
4600
|
currentEnabledIds = enabledIds === null ? null : [...enabledIds];
|
|
4312
|
-
const hasEnabledAvailableModel = enabledIds?.some((id) =>
|
|
4313
|
-
const allAvailableModelsEnabled = enabledIds !== null && [...
|
|
4601
|
+
const hasEnabledAvailableModel = enabledIds?.some((id) => availableModelIds.has(id)) ?? false;
|
|
4602
|
+
const allAvailableModelsEnabled = enabledIds !== null && [...availableModelIds].every((id) => enabledIds.includes(id));
|
|
4314
4603
|
if (enabledIds && hasEnabledAvailableModel && !allAvailableModelsEnabled) {
|
|
4315
|
-
const newScopedModels =
|
|
4316
|
-
this.session.setScopedModels(newScopedModels.map((
|
|
4317
|
-
model:
|
|
4318
|
-
thinkingLevel:
|
|
4604
|
+
const newScopedModels = resolveModelScopeFromModels(enabledIds, availableModels).scopedModels;
|
|
4605
|
+
this.session.setScopedModels(newScopedModels.map((scoped) => ({
|
|
4606
|
+
model: scoped.model,
|
|
4607
|
+
thinkingLevel: scoped.thinkingLevel,
|
|
4319
4608
|
})));
|
|
4320
4609
|
}
|
|
4321
4610
|
else {
|
|
4322
|
-
// All enabled or none enabled = no filter
|
|
4323
4611
|
this.session.setScopedModels([]);
|
|
4324
4612
|
}
|
|
4325
|
-
|
|
4613
|
+
this.updateAvailableProviderCount();
|
|
4326
4614
|
this.ui.requestRender();
|
|
4327
4615
|
};
|
|
4328
4616
|
this.showSelector((done) => {
|
|
4617
|
+
let disposed = false;
|
|
4618
|
+
let timedOut = false;
|
|
4619
|
+
const controller = new AbortController();
|
|
4620
|
+
const timeout = setTimeout(() => {
|
|
4621
|
+
timedOut = true;
|
|
4622
|
+
controller.abort();
|
|
4623
|
+
}, 15_000);
|
|
4329
4624
|
const selector = new ScopedModelsSelectorComponent({
|
|
4330
|
-
allModels,
|
|
4625
|
+
allModels: availableModels,
|
|
4331
4626
|
enabledModelIds: currentEnabledIds,
|
|
4627
|
+
refreshStatus: "Refreshing model catalogs…",
|
|
4332
4628
|
}, {
|
|
4333
|
-
onChange:
|
|
4334
|
-
|
|
4629
|
+
onChange: (enabledIds) => {
|
|
4630
|
+
selectionChanged = true;
|
|
4631
|
+
updateSessionModels(enabledIds);
|
|
4335
4632
|
},
|
|
4336
4633
|
onPersist: (enabledIds) => {
|
|
4337
|
-
// Persist to settings
|
|
4338
4634
|
const allEnabled = enabledIds !== null &&
|
|
4339
|
-
enabledIds.length ===
|
|
4340
|
-
enabledIds.every((id) =>
|
|
4635
|
+
enabledIds.length === availableModels.length &&
|
|
4636
|
+
enabledIds.every((id) => availableModelIds.has(id));
|
|
4341
4637
|
const newPatterns = enabledIds === null || allEnabled ? undefined : enabledIds;
|
|
4342
4638
|
this.settingsManager.setEnabledModels(newPatterns ? [...newPatterns] : undefined);
|
|
4343
4639
|
this.showStatus("Model selection saved to settings");
|
|
@@ -4347,7 +4643,50 @@ export class InteractiveMode {
|
|
|
4347
4643
|
this.ui.requestRender();
|
|
4348
4644
|
},
|
|
4349
4645
|
});
|
|
4350
|
-
|
|
4646
|
+
void refreshModelCatalogs(this.session.modelRuntime, controller.signal)
|
|
4647
|
+
.then((result) => {
|
|
4648
|
+
if (disposed)
|
|
4649
|
+
return;
|
|
4650
|
+
availableModels = [...this.session.modelRuntime.getAvailableSnapshot()];
|
|
4651
|
+
availableModelIds = new Set(availableModels.map((model) => `${model.provider}/${model.id}`));
|
|
4652
|
+
if (!selectionChanged && sessionScopedModels.length === 0) {
|
|
4653
|
+
currentEnabledIds = configuredEnabledIds(availableModels);
|
|
4654
|
+
selector.updateModels(availableModels, currentEnabledIds);
|
|
4655
|
+
}
|
|
4656
|
+
else {
|
|
4657
|
+
selector.updateModels(availableModels);
|
|
4658
|
+
}
|
|
4659
|
+
if (currentEnabledIds !== null)
|
|
4660
|
+
updateSessionModels(currentEnabledIds);
|
|
4661
|
+
if (result.aborted && timedOut) {
|
|
4662
|
+
selector.setRefreshStatus("Model refresh timed out; showing cached models.", "warning");
|
|
4663
|
+
}
|
|
4664
|
+
else if (result.errors.size > 0) {
|
|
4665
|
+
selector.setRefreshStatus(`Could not refresh ${[...result.errors.keys()].join(", ")}; showing cached models.`, "warning");
|
|
4666
|
+
}
|
|
4667
|
+
else {
|
|
4668
|
+
selector.setRefreshStatus("Model catalogs refreshed.", "success");
|
|
4669
|
+
}
|
|
4670
|
+
this.ui.requestRender();
|
|
4671
|
+
})
|
|
4672
|
+
.catch((error) => {
|
|
4673
|
+
if (disposed)
|
|
4674
|
+
return;
|
|
4675
|
+
selector.setRefreshStatus(timedOut
|
|
4676
|
+
? "Model refresh timed out; showing cached models."
|
|
4677
|
+
: `Could not refresh model catalogs: ${error instanceof Error ? error.message : String(error)}`, "warning");
|
|
4678
|
+
this.ui.requestRender();
|
|
4679
|
+
})
|
|
4680
|
+
.finally(() => clearTimeout(timeout));
|
|
4681
|
+
return {
|
|
4682
|
+
component: selector,
|
|
4683
|
+
focus: selector,
|
|
4684
|
+
dispose: () => {
|
|
4685
|
+
disposed = true;
|
|
4686
|
+
clearTimeout(timeout);
|
|
4687
|
+
controller.abort();
|
|
4688
|
+
},
|
|
4689
|
+
};
|
|
4351
4690
|
});
|
|
4352
4691
|
}
|
|
4353
4692
|
showUserMessageSelector() {
|
|
@@ -4592,6 +4931,7 @@ export class InteractiveMode {
|
|
|
4592
4931
|
source: authStatus.label ?? authStatus.source,
|
|
4593
4932
|
}
|
|
4594
4933
|
: undefined;
|
|
4934
|
+
const subscription = provider.auth.oauth?.isSubscription === true;
|
|
4595
4935
|
if ((!authType || authType === "oauth") && provider.auth.oauth) {
|
|
4596
4936
|
options.push({
|
|
4597
4937
|
id: provider.id,
|
|
@@ -4599,6 +4939,7 @@ export class InteractiveMode {
|
|
|
4599
4939
|
authType: "oauth",
|
|
4600
4940
|
method: provider.auth.oauth,
|
|
4601
4941
|
status,
|
|
4942
|
+
subscription,
|
|
4602
4943
|
});
|
|
4603
4944
|
}
|
|
4604
4945
|
if ((!authType || authType === "api_key") && provider.auth.apiKey) {
|
|
@@ -4608,19 +4949,24 @@ export class InteractiveMode {
|
|
|
4608
4949
|
authType: "api_key",
|
|
4609
4950
|
method: provider.auth.apiKey,
|
|
4610
4951
|
status,
|
|
4952
|
+
subscription,
|
|
4611
4953
|
});
|
|
4612
4954
|
}
|
|
4613
4955
|
}
|
|
4614
4956
|
return options.sort((a, b) => a.name.localeCompare(b.name));
|
|
4615
4957
|
}
|
|
4616
4958
|
async getLogoutProviderOptions() {
|
|
4617
|
-
return (await this.session.modelRuntime.listCredentials())
|
|
4618
|
-
.map(({ providerId, type }) =>
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
|
|
4622
|
-
|
|
4623
|
-
|
|
4959
|
+
return (await this.session.modelRuntime.listCredentials({ signal: AbortSignal.timeout(15_000) }))
|
|
4960
|
+
.map(({ providerId, type }) => {
|
|
4961
|
+
const provider = this.session.modelRuntime.getProvider(providerId);
|
|
4962
|
+
return {
|
|
4963
|
+
id: providerId,
|
|
4964
|
+
name: provider?.name ?? providerId,
|
|
4965
|
+
authType: type,
|
|
4966
|
+
status: { type, source: "stored credential" },
|
|
4967
|
+
subscription: provider?.auth.oauth?.isSubscription === true,
|
|
4968
|
+
};
|
|
4969
|
+
})
|
|
4624
4970
|
.sort((a, b) => a.name.localeCompare(b.name));
|
|
4625
4971
|
}
|
|
4626
4972
|
findLoginProviderOptions(providerRef) {
|
|
@@ -4632,7 +4978,6 @@ export class InteractiveMode {
|
|
|
4632
4978
|
provider.name.toLowerCase() === normalizedProviderRef);
|
|
4633
4979
|
}
|
|
4634
4980
|
async handleLoginCommand(providerRef) {
|
|
4635
|
-
await this.session.modelRuntime.getAvailable();
|
|
4636
4981
|
if (!providerRef) {
|
|
4637
4982
|
this.showLoginAuthTypeSelector();
|
|
4638
4983
|
return;
|
|
@@ -4651,18 +4996,25 @@ export class InteractiveMode {
|
|
|
4651
4996
|
}
|
|
4652
4997
|
this.showLoginProviderSelector(undefined, providerRef);
|
|
4653
4998
|
}
|
|
4654
|
-
|
|
4999
|
+
/** `onBack` reopens the selector the login was started from when the user cancels it. */
|
|
5000
|
+
async startProviderLogin(providerOption, onBack) {
|
|
4655
5001
|
if (providerOption.authType === "oauth") {
|
|
4656
|
-
await this.showLoginDialog(providerOption.id, providerOption.name);
|
|
5002
|
+
await this.showLoginDialog(providerOption.id, providerOption.name, onBack);
|
|
4657
5003
|
}
|
|
4658
5004
|
else if (providerOption.method?.login) {
|
|
4659
|
-
await this.showApiKeyLoginDialog(providerOption.id, providerOption.name);
|
|
5005
|
+
await this.showApiKeyLoginDialog(providerOption.id, providerOption.name, onBack);
|
|
4660
5006
|
}
|
|
4661
5007
|
else {
|
|
4662
|
-
this.showAmbientAuthDialog(providerOption);
|
|
5008
|
+
this.showAmbientAuthDialog(providerOption, onBack);
|
|
4663
5009
|
}
|
|
4664
5010
|
}
|
|
4665
5011
|
showLoginAuthTypeSelector(providerOptions) {
|
|
5012
|
+
// The top-level selector offers Radius directly, as its last option.
|
|
5013
|
+
const radiusOption = providerOptions
|
|
5014
|
+
? undefined
|
|
5015
|
+
: this.getLoginProviderOptions("oauth").find((provider) => provider.id === RADIUS_PROVIDER_ID);
|
|
5016
|
+
const radiusText = radiusOption ? `Sign in with ${radiusOption.name}` : undefined;
|
|
5017
|
+
const radiusLabel = radiusOption ? `${radiusText}${formatAuthSelectorProviderStatus(radiusOption)}` : undefined;
|
|
4666
5018
|
const oauthProvider = providerOptions?.find((provider) => provider.authType === "oauth");
|
|
4667
5019
|
const oauthLoginLabel = oauthProvider?.method && "loginLabel" in oauthProvider.method ? oauthProvider.method.loginLabel : undefined;
|
|
4668
5020
|
const subscriptionLabel = oauthLoginLabel ?? "Sign in with an account";
|
|
@@ -4677,6 +5029,8 @@ export class InteractiveMode {
|
|
|
4677
5029
|
if (availableAuthTypes.has("api_key")) {
|
|
4678
5030
|
options.push(apiKeyLabel);
|
|
4679
5031
|
}
|
|
5032
|
+
if (radiusLabel)
|
|
5033
|
+
options.push(radiusLabel);
|
|
4680
5034
|
if (options.length === 0) {
|
|
4681
5035
|
this.showStatus("No login methods available.");
|
|
4682
5036
|
return;
|
|
@@ -4692,29 +5046,37 @@ export class InteractiveMode {
|
|
|
4692
5046
|
? `Select authentication method for ${providerOptions[0].name}:`
|
|
4693
5047
|
: "Select authentication method:";
|
|
4694
5048
|
this.showSelector((done) => {
|
|
4695
|
-
const
|
|
5049
|
+
const onSelect = (option) => {
|
|
4696
5050
|
done();
|
|
5051
|
+
if (radiusOption && option === radiusLabel) {
|
|
5052
|
+
void this.startProviderLogin(radiusOption, () => this.showLoginAuthTypeSelector());
|
|
5053
|
+
return;
|
|
5054
|
+
}
|
|
4697
5055
|
const authType = option === subscriptionLabel ? "oauth" : "api_key";
|
|
4698
5056
|
if (providerOptions) {
|
|
4699
5057
|
const providerOption = providerOptions.find((provider) => provider.authType === authType);
|
|
4700
5058
|
if (providerOption) {
|
|
4701
|
-
void this.startProviderLogin(providerOption);
|
|
5059
|
+
void this.startProviderLogin(providerOption, () => this.showLoginAuthTypeSelector(providerOptions));
|
|
4702
5060
|
}
|
|
4703
5061
|
return;
|
|
4704
5062
|
}
|
|
4705
5063
|
this.showLoginProviderSelector(authType);
|
|
4706
|
-
}
|
|
5064
|
+
};
|
|
5065
|
+
const onCancel = () => {
|
|
4707
5066
|
done();
|
|
4708
5067
|
this.ui.requestRender();
|
|
4709
|
-
}
|
|
4710
|
-
|
|
5068
|
+
};
|
|
5069
|
+
const selector = radiusLabel && radiusText
|
|
5070
|
+
? createLoginMenuSelector(this.ui, title, options, { label: radiusLabel, text: radiusText }, onSelect, onCancel)
|
|
5071
|
+
: new ExtensionSelectorComponent(title, options, onSelect, onCancel);
|
|
5072
|
+
return { component: selector, focus: selector, dispose: () => selector.dispose() };
|
|
4711
5073
|
});
|
|
4712
5074
|
}
|
|
4713
5075
|
showLoginProviderSelector(authType, initialSearchInput) {
|
|
4714
5076
|
const providerOptions = this.getLoginProviderOptions(authType);
|
|
4715
5077
|
if (providerOptions.length === 0) {
|
|
4716
5078
|
const message = authType === "oauth"
|
|
4717
|
-
? "No
|
|
5079
|
+
? "No account providers available."
|
|
4718
5080
|
: authType === "api_key"
|
|
4719
5081
|
? "No API key providers available."
|
|
4720
5082
|
: "No login providers available.";
|
|
@@ -4728,7 +5090,7 @@ export class InteractiveMode {
|
|
|
4728
5090
|
if (!providerOption) {
|
|
4729
5091
|
return;
|
|
4730
5092
|
}
|
|
4731
|
-
await this.startProviderLogin(providerOption);
|
|
5093
|
+
await this.startProviderLogin(providerOption, () => this.showLoginProviderSelector(authType, initialSearchInput));
|
|
4732
5094
|
}, () => {
|
|
4733
5095
|
done();
|
|
4734
5096
|
if (authType) {
|
|
@@ -4746,7 +5108,14 @@ export class InteractiveMode {
|
|
|
4746
5108
|
this.showLoginAuthTypeSelector();
|
|
4747
5109
|
return;
|
|
4748
5110
|
}
|
|
4749
|
-
|
|
5111
|
+
let providerOptions;
|
|
5112
|
+
try {
|
|
5113
|
+
providerOptions = await this.getLogoutProviderOptions();
|
|
5114
|
+
}
|
|
5115
|
+
catch (error) {
|
|
5116
|
+
this.showError(`Could not read stored credentials: ${error instanceof Error ? error.message : String(error)}`);
|
|
5117
|
+
return;
|
|
5118
|
+
}
|
|
4750
5119
|
if (providerOptions.length === 0) {
|
|
4751
5120
|
this.showStatus("No stored credentials to remove. /logout only removes credentials saved by /login; environment variables and models.json config are unchanged.");
|
|
4752
5121
|
return;
|
|
@@ -4759,7 +5128,9 @@ export class InteractiveMode {
|
|
|
4759
5128
|
return;
|
|
4760
5129
|
}
|
|
4761
5130
|
try {
|
|
4762
|
-
await this.session.modelRuntime.logout(providerOption.id
|
|
5131
|
+
await this.session.modelRuntime.logout(providerOption.id, {
|
|
5132
|
+
signal: AbortSignal.timeout(15_000),
|
|
5133
|
+
});
|
|
4763
5134
|
await this.updateAvailableProviderCount();
|
|
4764
5135
|
const message = providerOption.authType === "oauth"
|
|
4765
5136
|
? `Logged out of ${providerOption.name}`
|
|
@@ -4767,7 +5138,10 @@ export class InteractiveMode {
|
|
|
4767
5138
|
this.showStatus(message);
|
|
4768
5139
|
}
|
|
4769
5140
|
catch (error) {
|
|
4770
|
-
|
|
5141
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
5142
|
+
this.showError(error instanceof CredentialSynchronizationError
|
|
5143
|
+
? `Credentials removed for ${providerOption.name}, but local model state could not be synchronized: ${message}`
|
|
5144
|
+
: `Logout failed: ${message}`);
|
|
4771
5145
|
}
|
|
4772
5146
|
}, () => {
|
|
4773
5147
|
done();
|
|
@@ -4777,8 +5151,8 @@ export class InteractiveMode {
|
|
|
4777
5151
|
});
|
|
4778
5152
|
}
|
|
4779
5153
|
async completeProviderAuthentication(providerId, providerName, authType, previousModel) {
|
|
4780
|
-
const session = this.session;
|
|
4781
5154
|
const actionLabel = authType === "oauth" ? `Logged in to ${providerName}` : `Saved API key for ${providerName}`;
|
|
5155
|
+
const session = this.session;
|
|
4782
5156
|
// Dynamic catalogs may be empty until the first authenticated network refresh.
|
|
4783
5157
|
const deferSelection = isUnknownModel(previousModel) &&
|
|
4784
5158
|
hasDefaultModelProvider(providerId) &&
|
|
@@ -4789,10 +5163,9 @@ export class InteractiveMode {
|
|
|
4789
5163
|
let selectedModel;
|
|
4790
5164
|
let selectionError;
|
|
4791
5165
|
if (isUnknownModel(previousModel)) {
|
|
4792
|
-
const availableModels =
|
|
5166
|
+
const availableModels = this.session.modelRuntime.getAvailableSnapshot();
|
|
4793
5167
|
const providerModels = availableModels.filter((model) => model.provider === providerId);
|
|
4794
|
-
// Matches LLAMA_PROVIDER_ID from
|
|
4795
|
-
// coupling interactive mode to the built-in extension.
|
|
5168
|
+
// Matches LLAMA_PROVIDER_ID from extensions/llama/provider.ts; kept inline to avoid coupling interactive mode to the built-in extension.
|
|
4796
5169
|
if (providerId === "llama.cpp") {
|
|
4797
5170
|
selectionError = llamaCppPostLoginGuidance(actionLabel, providerModels.length);
|
|
4798
5171
|
}
|
|
@@ -4829,7 +5202,6 @@ export class InteractiveMode {
|
|
|
4829
5202
|
if (selectedModel) {
|
|
4830
5203
|
this.showStatus(`${actionLabel}. Selected ${selectedModel.id}. Credentials saved to ${getAuthPath()}`);
|
|
4831
5204
|
void this.maybeWarnAboutAnthropicSubscriptionAuth(selectedModel);
|
|
4832
|
-
this.checkDaxnutsEasterEgg(selectedModel);
|
|
4833
5205
|
}
|
|
4834
5206
|
else {
|
|
4835
5207
|
this.showStatus(`${actionLabel}. Credentials saved to ${getAuthPath()}`);
|
|
@@ -4871,21 +5243,24 @@ export class InteractiveMode {
|
|
|
4871
5243
|
})
|
|
4872
5244
|
.finally(() => clearTimeout(timeout));
|
|
4873
5245
|
}
|
|
4874
|
-
showAmbientAuthDialog(providerOption) {
|
|
5246
|
+
showAmbientAuthDialog(providerOption, onBack) {
|
|
4875
5247
|
const restoreEditor = () => {
|
|
4876
5248
|
this.editorContainer.clear();
|
|
4877
5249
|
this.editorContainer.addChild(this.editor);
|
|
4878
5250
|
this.ui.setFocus(this.editor);
|
|
4879
5251
|
this.ui.requestRender();
|
|
4880
5252
|
};
|
|
4881
|
-
const dialog = new LoginDialogComponent(this.ui, providerOption.id, () =>
|
|
5253
|
+
const dialog = new LoginDialogComponent(this.ui, providerOption.id, () => {
|
|
5254
|
+
restoreEditor();
|
|
5255
|
+
onBack?.();
|
|
5256
|
+
}, providerOption.name, `${providerOption.name} setup`);
|
|
4882
5257
|
dialog.showInfo(`${providerOption.method?.name ?? "Authentication"} is configured outside ${APP_NAME}.`, [], true);
|
|
4883
5258
|
this.editorContainer.clear();
|
|
4884
5259
|
this.editorContainer.addChild(dialog);
|
|
4885
5260
|
this.ui.setFocus(dialog);
|
|
4886
5261
|
this.ui.requestRender();
|
|
4887
5262
|
}
|
|
4888
|
-
async showApiKeyLoginDialog(providerId, providerName) {
|
|
5263
|
+
async showApiKeyLoginDialog(providerId, providerName, onBack) {
|
|
4889
5264
|
const previousModel = this.session.model;
|
|
4890
5265
|
const dialog = new LoginDialogComponent(this.ui, providerId, (_success, _message) => {
|
|
4891
5266
|
// Completion handled below
|
|
@@ -4908,19 +5283,25 @@ export class InteractiveMode {
|
|
|
4908
5283
|
this.ui.requestRender();
|
|
4909
5284
|
};
|
|
4910
5285
|
try {
|
|
4911
|
-
await this.loginProvider(dialog, providerId, "api_key");
|
|
5286
|
+
await this.loginProvider(dialog, providerId, providerName, "api_key");
|
|
4912
5287
|
restoreEditor();
|
|
4913
5288
|
await this.completeProviderAuthentication(providerId, providerName, "api_key", previousModel);
|
|
4914
5289
|
}
|
|
4915
5290
|
catch (error) {
|
|
4916
5291
|
restoreEditor();
|
|
4917
5292
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
4918
|
-
if (
|
|
5293
|
+
if (error instanceof CredentialSynchronizationError) {
|
|
5294
|
+
this.showError(`Saved API key for ${providerName}, but local model state could not be synchronized: ${errorMsg}`);
|
|
5295
|
+
}
|
|
5296
|
+
else if (errorMsg === "Login cancelled") {
|
|
5297
|
+
onBack?.();
|
|
5298
|
+
}
|
|
5299
|
+
else {
|
|
4919
5300
|
this.showError(`Failed to save API key for ${providerName}: ${errorMsg}`);
|
|
4920
5301
|
}
|
|
4921
5302
|
}
|
|
4922
5303
|
}
|
|
4923
|
-
showAuthSelect(dialog, prompt) {
|
|
5304
|
+
showAuthSelect(dialog, prompt, providerId) {
|
|
4924
5305
|
return new Promise((resolve, reject) => {
|
|
4925
5306
|
const restoreDialog = () => {
|
|
4926
5307
|
this.editorContainer.clear();
|
|
@@ -4939,17 +5320,17 @@ export class InteractiveMode {
|
|
|
4939
5320
|
}, () => {
|
|
4940
5321
|
restoreDialog();
|
|
4941
5322
|
reject(new Error("Login cancelled"));
|
|
4942
|
-
});
|
|
5323
|
+
}, { description: providerId === RADIUS_PROVIDER_ID ? RADIUS_LOGIN_INTRO : undefined });
|
|
4943
5324
|
this.editorContainer.clear();
|
|
4944
5325
|
this.editorContainer.addChild(selector);
|
|
4945
5326
|
this.ui.setFocus(selector);
|
|
4946
5327
|
this.ui.requestRender();
|
|
4947
5328
|
});
|
|
4948
5329
|
}
|
|
4949
|
-
async showAuthPrompt(dialog, prompt) {
|
|
5330
|
+
async showAuthPrompt(dialog, prompt, providerId) {
|
|
4950
5331
|
let response;
|
|
4951
5332
|
if (prompt.type === "select") {
|
|
4952
|
-
response = this.showAuthSelect(dialog, prompt);
|
|
5333
|
+
response = this.showAuthSelect(dialog, prompt, providerId);
|
|
4953
5334
|
}
|
|
4954
5335
|
else if (prompt.type === "manual_code") {
|
|
4955
5336
|
response = dialog.showManualInput(prompt.message);
|
|
@@ -4990,14 +5371,20 @@ export class InteractiveMode {
|
|
|
4990
5371
|
dialog.showProgress(event.message);
|
|
4991
5372
|
}
|
|
4992
5373
|
}
|
|
4993
|
-
async loginProvider(dialog, providerId, method) {
|
|
4994
|
-
|
|
4995
|
-
|
|
4996
|
-
|
|
4997
|
-
|
|
4998
|
-
|
|
5374
|
+
async loginProvider(dialog, providerId, providerName, method) {
|
|
5375
|
+
this.programStatus.setBlocked("login", { kind: "auth", message: `Log in to ${providerName}` });
|
|
5376
|
+
try {
|
|
5377
|
+
await this.session.modelRuntime.login(providerId, method, {
|
|
5378
|
+
signal: dialog.signal,
|
|
5379
|
+
prompt: (prompt) => this.showAuthPrompt(dialog, prompt, providerId),
|
|
5380
|
+
notify: (event) => this.notifyAuthDialog(dialog, event),
|
|
5381
|
+
}, { getDeviceId: () => this.settingsManager.getOrCreateDeviceId() });
|
|
5382
|
+
}
|
|
5383
|
+
finally {
|
|
5384
|
+
this.programStatus.setBlocked("login", undefined);
|
|
5385
|
+
}
|
|
4999
5386
|
}
|
|
5000
|
-
async showLoginDialog(providerId, providerName) {
|
|
5387
|
+
async showLoginDialog(providerId, providerName, onBack) {
|
|
5001
5388
|
const previousModel = this.session.model;
|
|
5002
5389
|
const dialog = new LoginDialogComponent(this.ui, providerId, (_success, _message) => { }, providerName);
|
|
5003
5390
|
this.editorContainer.clear();
|
|
@@ -5011,18 +5398,70 @@ export class InteractiveMode {
|
|
|
5011
5398
|
this.ui.requestRender();
|
|
5012
5399
|
};
|
|
5013
5400
|
try {
|
|
5014
|
-
await this.loginProvider(dialog, providerId, "oauth");
|
|
5401
|
+
await this.loginProvider(dialog, providerId, providerName, "oauth");
|
|
5015
5402
|
restoreEditor();
|
|
5016
5403
|
await this.completeProviderAuthentication(providerId, providerName, "oauth", previousModel);
|
|
5404
|
+
if (providerId === RADIUS_PROVIDER_ID)
|
|
5405
|
+
this.offerRadiusMcpServer(providerId, providerName);
|
|
5017
5406
|
}
|
|
5018
5407
|
catch (error) {
|
|
5019
5408
|
restoreEditor();
|
|
5020
5409
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
5021
|
-
if (
|
|
5410
|
+
if (error instanceof CredentialSynchronizationError) {
|
|
5411
|
+
this.showError(`Logged in to ${providerName}, but local model state could not be synchronized: ${errorMsg}`);
|
|
5412
|
+
}
|
|
5413
|
+
else if (errorMsg === "Login cancelled") {
|
|
5414
|
+
onBack?.();
|
|
5415
|
+
}
|
|
5416
|
+
else {
|
|
5022
5417
|
this.showError(`Failed to login to ${providerName}: ${errorMsg}`);
|
|
5023
5418
|
}
|
|
5024
5419
|
}
|
|
5025
5420
|
}
|
|
5421
|
+
/**
|
|
5422
|
+
* Offer to point the Radius MCP server in the global mcp.json at the Radius login, adding the server
|
|
5423
|
+
* when missing. Nothing is asked when a global server already uses this login.
|
|
5424
|
+
*/
|
|
5425
|
+
offerRadiusMcpServer(providerId, providerName) {
|
|
5426
|
+
const mcpPath = path.join(getAgentDir(), "mcp.json");
|
|
5427
|
+
const normalizeUrl = (url) => url.replace(/\/+$/u, "");
|
|
5428
|
+
const { servers } = loadMcpConfig({
|
|
5429
|
+
agentDir: getAgentDir(),
|
|
5430
|
+
cwd: this.sessionManager.getCwd(),
|
|
5431
|
+
projectTrusted: false,
|
|
5432
|
+
});
|
|
5433
|
+
const existing = servers.find((server) => "url" in server.config && normalizeUrl(server.config.url) === normalizeUrl(RADIUS_MCP_URL));
|
|
5434
|
+
if (existing && "url" in existing.config && existing.config.auth?.provider === providerId)
|
|
5435
|
+
return;
|
|
5436
|
+
let name = existing?.name ?? "radius";
|
|
5437
|
+
if (!existing && servers.some((server) => server.name === name))
|
|
5438
|
+
name = "radius-mcp";
|
|
5439
|
+
const config = existing && "url" in existing.config
|
|
5440
|
+
? { ...existing.config, auth: { provider: providerId } }
|
|
5441
|
+
: { url: RADIUS_MCP_URL, auth: { provider: providerId } };
|
|
5442
|
+
// `auth` replaces the MCP OAuth sign-in.
|
|
5443
|
+
delete config.oauth;
|
|
5444
|
+
this.showSelector((done) => {
|
|
5445
|
+
const selector = new ExtensionSelectorComponent(`Configure ${providerName} MCP in ${mcpPath}?`, ["Yes", "No"], (option) => {
|
|
5446
|
+
done();
|
|
5447
|
+
if (option !== "Yes")
|
|
5448
|
+
return;
|
|
5449
|
+
try {
|
|
5450
|
+
addMcpServerConfig(mcpPath, name, config);
|
|
5451
|
+
}
|
|
5452
|
+
catch (error) {
|
|
5453
|
+
this.showError(`Could not update ${mcpPath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
5454
|
+
return;
|
|
5455
|
+
}
|
|
5456
|
+
// The MCP extension reads mcp.json when the session starts.
|
|
5457
|
+
void this.handleReloadCommand();
|
|
5458
|
+
}, () => {
|
|
5459
|
+
done();
|
|
5460
|
+
this.ui.requestRender();
|
|
5461
|
+
});
|
|
5462
|
+
return { component: selector, focus: selector };
|
|
5463
|
+
});
|
|
5464
|
+
}
|
|
5026
5465
|
// =========================================================================
|
|
5027
5466
|
// Command handlers
|
|
5028
5467
|
// =========================================================================
|
|
@@ -5082,7 +5521,7 @@ export class InteractiveMode {
|
|
|
5082
5521
|
const borderColor = (s) => theme.fg("border", s);
|
|
5083
5522
|
reloadBox.addChild(new DynamicBorder(borderColor));
|
|
5084
5523
|
reloadBox.addChild(new Spacer(1));
|
|
5085
|
-
reloadBox.addChild(new
|
|
5524
|
+
reloadBox.addChild(new ThemedText(() => theme.fg("muted", "Reloading keybindings, extensions, skills, prompts, themes, and context files..."), 1, 0));
|
|
5086
5525
|
reloadBox.addChild(new Spacer(1));
|
|
5087
5526
|
reloadBox.addChild(new DynamicBorder(borderColor));
|
|
5088
5527
|
const previousEditor = this.editor;
|
|
@@ -5119,7 +5558,7 @@ export class InteractiveMode {
|
|
|
5119
5558
|
}
|
|
5120
5559
|
setRegisteredThemes(this.session.resourceLoader.getThemes().themes);
|
|
5121
5560
|
this.applyRuntimeSettings();
|
|
5122
|
-
|
|
5561
|
+
this.themeController.applyFromSettings();
|
|
5123
5562
|
this.setupAutocompleteProvider();
|
|
5124
5563
|
const runner = this.session.extensionRunner;
|
|
5125
5564
|
this.setupExtensionShortcuts(runner);
|
|
@@ -5231,91 +5670,14 @@ export class InteractiveMode {
|
|
|
5231
5670
|
}
|
|
5232
5671
|
}
|
|
5233
5672
|
async handleShareCommand() {
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
|
|
5238
|
-
|
|
5239
|
-
|
|
5240
|
-
|
|
5241
|
-
}
|
|
5242
|
-
catch {
|
|
5243
|
-
this.showError("GitHub CLI (gh) is not installed. Install it from https://cli.github.com/");
|
|
5244
|
-
return;
|
|
5245
|
-
}
|
|
5246
|
-
// Export to a temp file
|
|
5247
|
-
const tmpFile = path.join(os.tmpdir(), "session.html");
|
|
5248
|
-
try {
|
|
5249
|
-
await this.session.exportToHtml(tmpFile, { themeName: theme.name });
|
|
5250
|
-
}
|
|
5251
|
-
catch (error) {
|
|
5252
|
-
this.showError(`Failed to export session: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
5253
|
-
return;
|
|
5254
|
-
}
|
|
5255
|
-
// Show cancellable loader, replacing the editor
|
|
5256
|
-
const loader = new BorderedLoader(this.ui, theme, "Creating gist...");
|
|
5257
|
-
this.editorContainer.clear();
|
|
5258
|
-
this.editorContainer.addChild(loader);
|
|
5259
|
-
this.ui.setFocus(loader);
|
|
5260
|
-
this.ui.requestRender();
|
|
5261
|
-
const restoreEditor = () => {
|
|
5262
|
-
loader.dispose();
|
|
5263
|
-
this.editorContainer.clear();
|
|
5264
|
-
this.editorContainer.addChild(this.editor);
|
|
5265
|
-
this.ui.setFocus(this.editor);
|
|
5266
|
-
try {
|
|
5267
|
-
fs.unlinkSync(tmpFile);
|
|
5268
|
-
}
|
|
5269
|
-
catch {
|
|
5270
|
-
// Ignore cleanup errors
|
|
5271
|
-
}
|
|
5272
|
-
};
|
|
5273
|
-
// Create a secret gist asynchronously
|
|
5274
|
-
let proc = null;
|
|
5275
|
-
loader.onAbort = () => {
|
|
5276
|
-
proc?.kill();
|
|
5277
|
-
restoreEditor();
|
|
5278
|
-
this.showStatus("Share cancelled");
|
|
5279
|
-
};
|
|
5280
|
-
try {
|
|
5281
|
-
const result = await new Promise((resolve) => {
|
|
5282
|
-
proc = spawn("gh", ["gist", "create", "--public=false", tmpFile]);
|
|
5283
|
-
let stdout = "";
|
|
5284
|
-
let stderr = "";
|
|
5285
|
-
proc.stdout?.on("data", (data) => {
|
|
5286
|
-
stdout += data.toString();
|
|
5287
|
-
});
|
|
5288
|
-
proc.stderr?.on("data", (data) => {
|
|
5289
|
-
stderr += data.toString();
|
|
5290
|
-
});
|
|
5291
|
-
proc.on("close", (code) => resolve({ stdout, stderr, code }));
|
|
5292
|
-
});
|
|
5293
|
-
if (loader.signal.aborted)
|
|
5294
|
-
return;
|
|
5295
|
-
restoreEditor();
|
|
5296
|
-
if (result.code !== 0) {
|
|
5297
|
-
const errorMsg = result.stderr?.trim() || "Unknown error";
|
|
5298
|
-
this.showError(`Failed to create gist: ${errorMsg}`);
|
|
5299
|
-
return;
|
|
5300
|
-
}
|
|
5301
|
-
// Extract gist ID from the URL returned by gh
|
|
5302
|
-
// gh returns something like: https://gist.github.com/username/GIST_ID
|
|
5303
|
-
const gistUrl = result.stdout?.trim();
|
|
5304
|
-
const gistId = gistUrl?.split("/").pop();
|
|
5305
|
-
if (!gistId) {
|
|
5306
|
-
this.showError("Failed to parse gist ID from gh output");
|
|
5307
|
-
return;
|
|
5308
|
-
}
|
|
5309
|
-
// Create the preview URL
|
|
5310
|
-
const previewUrl = getShareViewerUrl(gistId);
|
|
5311
|
-
this.showStatus(`Share URL: ${previewUrl}\nGist: ${gistUrl}`);
|
|
5312
|
-
}
|
|
5313
|
-
catch (error) {
|
|
5314
|
-
if (!loader.signal.aborted) {
|
|
5315
|
-
restoreEditor();
|
|
5316
|
-
this.showError(`Failed to create gist: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
5317
|
-
}
|
|
5318
|
-
}
|
|
5673
|
+
await shareSession({
|
|
5674
|
+
session: this.session,
|
|
5675
|
+
ui: this.ui,
|
|
5676
|
+
editorContainer: this.editorContainer,
|
|
5677
|
+
editor: this.editor,
|
|
5678
|
+
showStatus: (message) => this.showStatus(message),
|
|
5679
|
+
showError: (message) => this.showError(message),
|
|
5680
|
+
});
|
|
5319
5681
|
}
|
|
5320
5682
|
async handleBugCommand(hint) {
|
|
5321
5683
|
await reportBug({
|
|
@@ -5360,7 +5722,7 @@ export class InteractiveMode {
|
|
|
5360
5722
|
const currentName = this.sessionManager.getSessionName();
|
|
5361
5723
|
if (currentName) {
|
|
5362
5724
|
this.chatContainer.addChild(new Spacer(1));
|
|
5363
|
-
this.chatContainer.addChild(new
|
|
5725
|
+
this.chatContainer.addChild(new ThemedText(() => theme.fg("dim", `Session name: ${currentName}`), 1, 0));
|
|
5364
5726
|
}
|
|
5365
5727
|
else {
|
|
5366
5728
|
this.showWarning("Usage: /name <name>");
|
|
@@ -5374,7 +5736,8 @@ export class InteractiveMode {
|
|
|
5374
5736
|
this.showWarning(`Session name was normalized from ${JSON.stringify(name)} to ${JSON.stringify(sessionName)}`);
|
|
5375
5737
|
}
|
|
5376
5738
|
this.chatContainer.addChild(new Spacer(1));
|
|
5377
|
-
|
|
5739
|
+
const displayName = sessionName ?? name;
|
|
5740
|
+
this.chatContainer.addChild(new ThemedText(() => theme.fg("dim", `Session name set: ${displayName}`), 1, 0));
|
|
5378
5741
|
this.ui.requestRender();
|
|
5379
5742
|
}
|
|
5380
5743
|
handleSessionCommand() {
|
|
@@ -5386,61 +5749,69 @@ export class InteractiveMode {
|
|
|
5386
5749
|
// resolves to a concrete responseModel). Usage without model attribution is
|
|
5387
5750
|
// grouped separately so the breakdown reconciles with the session total.
|
|
5388
5751
|
const usageBreakdown = getUsageCostBreakdown(entries);
|
|
5389
|
-
|
|
5390
|
-
if (sessionName) {
|
|
5391
|
-
info += `${theme.fg("dim", "Name:")} ${sessionName}\n`;
|
|
5392
|
-
}
|
|
5393
|
-
info += `${theme.fg("dim", "File:")} ${stats.sessionFile ?? "In-memory"}\n`;
|
|
5394
|
-
info += `${theme.fg("dim", "ID:")} ${stats.sessionId}\n\n`;
|
|
5395
|
-
info += `${theme.bold("Messages")}\n`;
|
|
5396
|
-
info += `${theme.fg("dim", "Total:")} ${stats.totalMessages}\n`;
|
|
5397
|
-
info += `${theme.fg("dim", "User:")} ${stats.userMessages}\n`;
|
|
5398
|
-
info += `${theme.fg("dim", "Assistant:")} ${stats.assistantMessages}\n`;
|
|
5399
|
-
info += `${theme.fg("dim", "Tools:")} ${stats.toolCalls} calls, ${stats.toolResults} results\n\n`;
|
|
5400
|
-
info += `${theme.bold("Tokens")}\n`;
|
|
5401
|
-
// "Input" is the full prompt volume. With cache activity, split it into
|
|
5402
|
-
// cached (served from cache) vs uncached (everything else) - the only
|
|
5403
|
-
// provider-independent split. Cache writes, where reported, are a detail
|
|
5404
|
-
// of the uncached portion.
|
|
5405
|
-
const { input, cacheRead, cacheWrite } = stats.tokens;
|
|
5406
|
-
const promptTokens = input + cacheRead + cacheWrite;
|
|
5407
|
-
info += `${theme.fg("dim", "Input:")} ${promptTokens.toLocaleString()}\n`;
|
|
5408
|
-
if (promptTokens > 0 && (cacheRead > 0 || cacheWrite > 0)) {
|
|
5409
|
-
const hitRate = theme.fg("dim", `(${((cacheRead / promptTokens) * 100).toFixed(1)}%)`);
|
|
5410
|
-
info += ` ${theme.fg("dim", "Cached:")} ${cacheRead.toLocaleString()} ${hitRate}\n`;
|
|
5411
|
-
const written = cacheWrite > 0 ? ` ${theme.fg("dim", `(${cacheWrite.toLocaleString()} written to cache)`)}` : "";
|
|
5412
|
-
info += ` ${theme.fg("dim", "Uncached:")} ${(input + cacheWrite).toLocaleString()}${written}\n`;
|
|
5413
|
-
}
|
|
5414
|
-
info += `${theme.fg("dim", "Output:")} ${stats.tokens.output.toLocaleString()}\n`;
|
|
5415
|
-
info += `${theme.fg("dim", "Total:")} ${stats.tokens.total.toLocaleString()}\n`;
|
|
5752
|
+
// Snapshot the stats; the text is built on demand so it follows theme changes.
|
|
5416
5753
|
const cacheWarmingStatus = this.session.cacheWarmingStatus;
|
|
5417
|
-
|
|
5418
|
-
|
|
5419
|
-
|
|
5420
|
-
const
|
|
5421
|
-
|
|
5422
|
-
|
|
5423
|
-
|
|
5424
|
-
|
|
5425
|
-
|
|
5426
|
-
info +=
|
|
5427
|
-
info += `${theme.
|
|
5428
|
-
|
|
5429
|
-
|
|
5430
|
-
|
|
5754
|
+
const cacheWarmingMode = this.settingsManager.getCacheWarmingMode();
|
|
5755
|
+
const model = this.session.model;
|
|
5756
|
+
const selectedModelKey = `${model?.provider}/${model?.id}`;
|
|
5757
|
+
const renderInfo = () => {
|
|
5758
|
+
let info = `${theme.bold("Session Info")}\n\n`;
|
|
5759
|
+
if (sessionName) {
|
|
5760
|
+
info += `${theme.fg("dim", "Name:")} ${sessionName}\n`;
|
|
5761
|
+
}
|
|
5762
|
+
info += `${theme.fg("dim", "File:")} ${stats.sessionFile ?? "In-memory"}\n`;
|
|
5763
|
+
info += `${theme.fg("dim", "ID:")} ${stats.sessionId}\n\n`;
|
|
5764
|
+
info += `${theme.bold("Messages")}\n`;
|
|
5765
|
+
info += `${theme.fg("dim", "Total:")} ${stats.totalMessages}\n`;
|
|
5766
|
+
info += `${theme.fg("dim", "User:")} ${stats.userMessages}\n`;
|
|
5767
|
+
info += `${theme.fg("dim", "Assistant:")} ${stats.assistantMessages}\n`;
|
|
5768
|
+
info += `${theme.fg("dim", "Tools:")} ${stats.toolCalls} calls, ${stats.toolResults} results\n\n`;
|
|
5769
|
+
info += `${theme.bold("Tokens")}\n`;
|
|
5770
|
+
// "Input" is the full prompt volume. With cache activity, split it into
|
|
5771
|
+
// cached (served from cache) vs uncached (everything else) - the only
|
|
5772
|
+
// provider-independent split. Cache writes, where reported, are a detail
|
|
5773
|
+
// of the uncached portion.
|
|
5774
|
+
const { input, cacheRead, cacheWrite } = stats.tokens;
|
|
5775
|
+
const promptTokens = input + cacheRead + cacheWrite;
|
|
5776
|
+
info += `${theme.fg("dim", "Input:")} ${promptTokens.toLocaleString()}\n`;
|
|
5777
|
+
if (promptTokens > 0 && (cacheRead > 0 || cacheWrite > 0)) {
|
|
5778
|
+
const hitRate = theme.fg("dim", `(${((cacheRead / promptTokens) * 100).toFixed(1)}%)`);
|
|
5779
|
+
info += ` ${theme.fg("dim", "Cached:")} ${cacheRead.toLocaleString()} ${hitRate}\n`;
|
|
5780
|
+
const written = cacheWrite > 0 ? ` ${theme.fg("dim", `(${cacheWrite.toLocaleString()} written to cache)`)}` : "";
|
|
5781
|
+
info += ` ${theme.fg("dim", "Uncached:")} ${(input + cacheWrite).toLocaleString()}${written}\n`;
|
|
5782
|
+
}
|
|
5783
|
+
info += `${theme.fg("dim", "Output:")} ${stats.tokens.output.toLocaleString()}\n`;
|
|
5784
|
+
info += `${theme.fg("dim", "Total:")} ${stats.tokens.total.toLocaleString()}\n`;
|
|
5785
|
+
info += `\n${theme.bold("Cache Warming")}\n`;
|
|
5786
|
+
info += `${theme.fg("dim", "Mode:")} ${cacheWarmingMode}\n`;
|
|
5787
|
+
info += `${theme.fg("dim", "Status:")} ${cacheWarmingStatus ? formatCacheWarmingStatus(cacheWarmingStatus) : "Inactive (cache warming unavailable)"}\n`;
|
|
5788
|
+
const decision = cacheWarmingStatus?.decision;
|
|
5789
|
+
if (decision?.economicsAvailable) {
|
|
5790
|
+
info += `${theme.fg("dim", "Cache miss penalty:")} ${formatCost(decision.missCost)}\n`;
|
|
5791
|
+
info += `${theme.fg("dim", "Refresh cost:")} ${formatCost(decision.warmCost)}\n`;
|
|
5792
|
+
}
|
|
5793
|
+
if (stats.cost > 0 || cacheWaste.missedTokens > 0) {
|
|
5794
|
+
info += `\n${theme.bold("Cost")}\n`;
|
|
5795
|
+
info += `${theme.fg("dim", "Total:")} ${formatCost(stats.cost)}`;
|
|
5796
|
+
// A single entry repeats the total, unless it names a model other than the selected one.
|
|
5797
|
+
if (usageBreakdown.length > 1 || usageBreakdown[0]?.key !== selectedModelKey) {
|
|
5798
|
+
for (const entry of usageBreakdown) {
|
|
5799
|
+
info += `\n ${theme.fg("dim", `${entry.key}:`)} ${formatCost(entry.cost)} ${theme.fg("dim", `(${formatTokens(entry.tokens)} tokens)`)}`;
|
|
5800
|
+
}
|
|
5801
|
+
}
|
|
5802
|
+
if (cacheWaste.missedTokens > 0) {
|
|
5803
|
+
const missLabel = cacheWaste.missCount === 1 ? "1 miss" : `${cacheWaste.missCount} misses`;
|
|
5804
|
+
const detail = `${cacheWaste.missedTokens.toLocaleString()} tokens, ${missLabel}`;
|
|
5805
|
+
info +=
|
|
5806
|
+
cacheWaste.missedCost >= 0.0001
|
|
5807
|
+
? `\n${theme.fg("dim", "Cache Re-billed:")} ${formatCost(cacheWaste.missedCost)} ${theme.fg("dim", `(${detail})`)}`
|
|
5808
|
+
: `\n${theme.fg("dim", "Cache Re-billed:")} ${detail}`;
|
|
5431
5809
|
}
|
|
5432
5810
|
}
|
|
5433
|
-
|
|
5434
|
-
|
|
5435
|
-
const detail = `${cacheWaste.missedTokens.toLocaleString()} tokens, ${missLabel}`;
|
|
5436
|
-
info +=
|
|
5437
|
-
cacheWaste.missedCost >= 0.0001
|
|
5438
|
-
? `\n${theme.fg("dim", "Cache Re-billed:")} ${formatCost(cacheWaste.missedCost)} ${theme.fg("dim", `(${detail})`)}`
|
|
5439
|
-
: `\n${theme.fg("dim", "Cache Re-billed:")} ${detail}`;
|
|
5440
|
-
}
|
|
5441
|
-
}
|
|
5811
|
+
return info;
|
|
5812
|
+
};
|
|
5442
5813
|
this.chatContainer.addChild(new Spacer(1));
|
|
5443
|
-
this.chatContainer.addChild(new
|
|
5814
|
+
this.chatContainer.addChild(new ThemedText(renderInfo, 1, 0));
|
|
5444
5815
|
this.ui.requestRender();
|
|
5445
5816
|
}
|
|
5446
5817
|
handleChangelogCommand() {
|
|
@@ -5454,7 +5825,7 @@ export class InteractiveMode {
|
|
|
5454
5825
|
: "No changelog entries found.";
|
|
5455
5826
|
this.chatContainer.addChild(new Spacer(1));
|
|
5456
5827
|
this.chatContainer.addChild(new DynamicBorder());
|
|
5457
|
-
this.chatContainer.addChild(new
|
|
5828
|
+
this.chatContainer.addChild(new ThemedText(() => theme.bold(theme.fg("accent", "What's New")), 1, 0));
|
|
5458
5829
|
this.chatContainer.addChild(new Spacer(1));
|
|
5459
5830
|
this.chatContainer.addChild(new Markdown(changelogMarkdown, 1, 1, this.getMarkdownThemeWithSettings()));
|
|
5460
5831
|
this.chatContainer.addChild(new DynamicBorder());
|
|
@@ -5555,7 +5926,7 @@ export class InteractiveMode {
|
|
|
5555
5926
|
| \`${copyMessage}\` | Copy selection or last assistant message |
|
|
5556
5927
|
| \`${followUp}\` | Queue follow-up message |
|
|
5557
5928
|
| \`${dequeue}\` | Restore queued messages |
|
|
5558
|
-
| \`${pasteImage}\` | Paste
|
|
5929
|
+
| \`${pasteImage}\` | Paste files on macOS, images, or text from clipboard |
|
|
5559
5930
|
| \`/\` | Slash commands |
|
|
5560
5931
|
| \`!\` | Run bash command |
|
|
5561
5932
|
| \`!!\` | Run bash command (excluded from context) |
|
|
@@ -5577,7 +5948,7 @@ export class InteractiveMode {
|
|
|
5577
5948
|
}
|
|
5578
5949
|
this.chatContainer.addChild(new Spacer(1));
|
|
5579
5950
|
this.chatContainer.addChild(new DynamicBorder());
|
|
5580
|
-
this.chatContainer.addChild(new
|
|
5951
|
+
this.chatContainer.addChild(new ThemedText(() => theme.bold(theme.fg("accent", "Keyboard Shortcuts")), 1, 0));
|
|
5581
5952
|
this.chatContainer.addChild(new Spacer(1));
|
|
5582
5953
|
this.chatContainer.addChild(new Markdown(hotkeys.trim(), 1, 1, this.getMarkdownThemeWithSettings()));
|
|
5583
5954
|
this.chatContainer.addChild(new DynamicBorder());
|
|
@@ -5591,7 +5962,7 @@ export class InteractiveMode {
|
|
|
5591
5962
|
return;
|
|
5592
5963
|
}
|
|
5593
5964
|
this.chatContainer.addChild(new Spacer(1));
|
|
5594
|
-
this.chatContainer.addChild(new
|
|
5965
|
+
this.chatContainer.addChild(new ThemedText(() => theme.fg("accent", "✓ New session started"), 1, 1));
|
|
5595
5966
|
this.ui.requestRender();
|
|
5596
5967
|
}
|
|
5597
5968
|
catch (error) {
|
|
@@ -5622,7 +5993,7 @@ export class InteractiveMode {
|
|
|
5622
5993
|
fs.mkdirSync(path.dirname(debugLogPath), { recursive: true });
|
|
5623
5994
|
fs.writeFileSync(debugLogPath, debugData);
|
|
5624
5995
|
this.chatContainer.addChild(new Spacer(1));
|
|
5625
|
-
this.chatContainer.addChild(new
|
|
5996
|
+
this.chatContainer.addChild(new ThemedText(() => `${theme.fg("accent", "✓ Debug log written")}\n${theme.fg("muted", debugLogPath)}`, 1, 1));
|
|
5626
5997
|
this.ui.requestRender();
|
|
5627
5998
|
}
|
|
5628
5999
|
handleArminSaysHi() {
|
|
@@ -5635,16 +6006,6 @@ export class InteractiveMode {
|
|
|
5635
6006
|
this.chatContainer.addChild(new EarendilAnnouncementComponent());
|
|
5636
6007
|
this.ui.requestRender();
|
|
5637
6008
|
}
|
|
5638
|
-
handleDaxnuts() {
|
|
5639
|
-
this.chatContainer.addChild(new Spacer(1));
|
|
5640
|
-
this.chatContainer.addChild(new DaxnutsComponent(this.ui));
|
|
5641
|
-
this.ui.requestRender();
|
|
5642
|
-
}
|
|
5643
|
-
checkDaxnutsEasterEgg(model) {
|
|
5644
|
-
if (model.provider === "opencode" && model.id.toLowerCase().includes("kimi-k2.5")) {
|
|
5645
|
-
this.handleDaxnuts();
|
|
5646
|
-
}
|
|
5647
|
-
}
|
|
5648
6009
|
async handleBashCommand(command, excludeFromContext = false) {
|
|
5649
6010
|
const extensionRunner = this.session.extensionRunner;
|
|
5650
6011
|
// Emit user_bash event to let extensions intercept
|
|
@@ -5665,7 +6026,7 @@ export class InteractiveMode {
|
|
|
5665
6026
|
if (eventResult?.result) {
|
|
5666
6027
|
const result = eventResult.result;
|
|
5667
6028
|
// Create UI component for display
|
|
5668
|
-
this.bashComponent = new BashExecutionComponent(command, this.ui, excludeFromContext);
|
|
6029
|
+
this.bashComponent = new BashExecutionComponent(command, this.ui, excludeFromContext, this.outputPad);
|
|
5669
6030
|
if (this.session.isStreaming) {
|
|
5670
6031
|
this.pendingMessagesContainer.addChild(this.bashComponent);
|
|
5671
6032
|
this.pendingBashComponents.push(this.bashComponent);
|
|
@@ -5686,7 +6047,7 @@ export class InteractiveMode {
|
|
|
5686
6047
|
}
|
|
5687
6048
|
// Normal execution path (possibly with custom operations)
|
|
5688
6049
|
const isDeferred = this.session.isStreaming;
|
|
5689
|
-
this.bashComponent = new BashExecutionComponent(command, this.ui, excludeFromContext);
|
|
6050
|
+
this.bashComponent = new BashExecutionComponent(command, this.ui, excludeFromContext, this.outputPad);
|
|
5690
6051
|
if (isDeferred) {
|
|
5691
6052
|
// Show in pending area when agent is streaming
|
|
5692
6053
|
this.pendingMessagesContainer.addChild(this.bashComponent);
|
|
@@ -5727,6 +6088,7 @@ export class InteractiveMode {
|
|
|
5727
6088
|
}
|
|
5728
6089
|
}
|
|
5729
6090
|
stop(fullscreenExitOutput = this.settingsManager.getFullscreenExitOutput()) {
|
|
6091
|
+
this.disposeActiveSelector();
|
|
5730
6092
|
if (this.settingsManager.getShowTerminalProgress()) {
|
|
5731
6093
|
this.ui.terminal.setProgress(false);
|
|
5732
6094
|
}
|