@astralyn/pi 0.85.3 → 0.86.1
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 +52 -0
- package/dist/bundle/chunks/anthropic-messages-R2LYJUDD.js +6 -0
- package/dist/bundle/chunks/azure-openai-responses-HS35BQV6.js +2 -0
- package/dist/bundle/chunks/bedrock-converse-stream.js +36 -32
- package/dist/bundle/chunks/{chunk-S2DJQQI2.js → chunk-2IO5GDBS.js} +10 -1
- package/dist/bundle/chunks/chunk-DAEM5JIZ.js +2 -0
- package/dist/bundle/chunks/{chunk-LB4P77SH.js → chunk-GTBMYBFG.js} +777 -762
- package/dist/bundle/chunks/{chunk-7LO5Z4WE.js → chunk-I5IVW2WS.js} +1 -1
- package/dist/bundle/chunks/chunk-JI4WGISU.js +2 -0
- package/dist/bundle/chunks/chunk-LPQCB2VJ.js +44 -0
- package/dist/bundle/chunks/chunk-NW5FIDD7.js +11 -0
- package/dist/bundle/chunks/chunk-PJVFYVHE.js +42 -0
- package/dist/bundle/chunks/github-copilot.js +1 -1
- package/dist/bundle/chunks/google-generative-ai-NOVAJBFC.js +2 -0
- package/dist/bundle/chunks/google-vertex-4VHCZJV5.js +2 -0
- package/dist/bundle/chunks/https-proxy-agent-JOOPB4RE.js +16 -0
- package/dist/bundle/chunks/jiti-loader-BFSSLU7G.js +21 -0
- package/dist/bundle/chunks/jiti-static-loader-CLT3YR3B.js +2 -0
- package/dist/bundle/chunks/mistral-conversations-WC6A2WCJ.js +5 -0
- package/dist/bundle/chunks/{node-G4XOIDPH.js → node-CXWYTK2I.js} +1 -1
- package/dist/bundle/chunks/openai-codex-responses-XCDG75W2.js +10 -0
- package/dist/bundle/chunks/openai-completions-6SMWQWQN.js +7 -0
- package/dist/bundle/chunks/openai-responses-UT6XFKC7.js +2 -0
- package/dist/bundle/chunks/{pi-messages-PE6B42TG.js → pi-messages-MQMPIPNC.js} +1 -1
- package/dist/bundle/chunks/virtual-modules-OHUZ2T7X.js +2 -0
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +1 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/session-picker.d.ts +1 -1
- package/dist/cli/session-picker.d.ts.map +1 -1
- package/dist/cli/session-picker.js +13 -11
- package/dist/cli/session-picker.js.map +1 -1
- package/dist/config.js +1 -1
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session.d.ts +56 -14
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +305 -176
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/bug-report-upload.d.ts +12 -0
- package/dist/core/bug-report-upload.d.ts.map +1 -0
- package/dist/core/bug-report-upload.js +22 -0
- package/dist/core/bug-report-upload.js.map +1 -0
- package/dist/core/bug-report.d.ts +176 -0
- package/dist/core/bug-report.d.ts.map +1 -0
- package/dist/core/bug-report.js +292 -0
- package/dist/core/bug-report.js.map +1 -0
- package/dist/core/cache-stats.d.ts.map +1 -1
- package/dist/core/cache-stats.js +12 -1
- package/dist/core/cache-stats.js.map +1 -1
- package/dist/core/cache-warmer.d.ts +102 -0
- package/dist/core/cache-warmer.d.ts.map +1 -0
- package/dist/core/cache-warmer.js +333 -0
- package/dist/core/cache-warmer.js.map +1 -0
- package/dist/core/compaction/branch-summarization.js +2 -2
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +14 -9
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +30 -23
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/compaction/settings.d.ts +17 -20
- package/dist/core/compaction/settings.d.ts.map +1 -1
- package/dist/core/compaction/settings.js +19 -26
- package/dist/core/compaction/settings.js.map +1 -1
- package/dist/core/context-snapshot.d.ts +16 -5
- package/dist/core/context-snapshot.d.ts.map +1 -1
- package/dist/core/context-snapshot.js +20 -10
- package/dist/core/context-snapshot.js.map +1 -1
- package/dist/core/crash-log.d.ts +22 -0
- package/dist/core/crash-log.d.ts.map +1 -0
- package/dist/core/crash-log.js +71 -0
- package/dist/core/crash-log.js.map +1 -0
- package/dist/core/experimental.d.ts +0 -4
- package/dist/core/experimental.d.ts.map +1 -1
- package/dist/core/experimental.js +0 -4
- package/dist/core/experimental.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/jiti-loader.d.ts +2 -0
- package/dist/core/extensions/jiti-loader.d.ts.map +1 -0
- package/dist/core/extensions/jiti-loader.js +4 -0
- package/dist/core/extensions/jiti-loader.js.map +1 -0
- package/dist/core/extensions/jiti-static-loader.d.ts +2 -0
- package/dist/core/extensions/jiti-static-loader.d.ts.map +1 -0
- package/dist/core/extensions/jiti-static-loader.js +4 -0
- package/dist/core/extensions/jiti-static-loader.js.map +1 -0
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +38 -51
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +10 -7
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +85 -67
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +60 -50
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/extensions/virtual-modules.d.ts +3 -0
- package/dist/core/extensions/virtual-modules.d.ts.map +1 -0
- package/dist/core/extensions/virtual-modules.js +39 -0
- package/dist/core/extensions/virtual-modules.js.map +1 -0
- package/dist/core/extensions/wrapper.d.ts.map +1 -1
- package/dist/core/extensions/wrapper.js +1 -20
- package/dist/core/extensions/wrapper.js.map +1 -1
- package/dist/core/index.d.ts +2 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/keybindings.d.ts +1 -1
- package/dist/core/keybindings.js +1 -1
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js +1 -0
- package/dist/core/messages.js.map +1 -1
- package/dist/core/model-config.d.ts +101 -20
- package/dist/core/model-config.d.ts.map +1 -1
- package/dist/core/model-config.js +25 -18
- package/dist/core/model-config.js.map +1 -1
- package/dist/core/model-registry.d.ts +5 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +8 -0
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +2 -1
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +5 -3
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/provider-composer.d.ts +3 -2
- package/dist/core/provider-composer.d.ts.map +1 -1
- package/dist/core/provider-composer.js +2 -0
- package/dist/core/provider-composer.js.map +1 -1
- package/dist/core/radius.d.ts +3 -0
- package/dist/core/radius.d.ts.map +1 -1
- package/dist/core/radius.js +6 -0
- package/dist/core/radius.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +46 -18
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-export.d.ts +6 -2
- package/dist/core/session-export.d.ts.map +1 -1
- package/dist/core/session-export.js +14 -13
- package/dist/core/session-export.js.map +1 -1
- package/dist/core/session-manager.d.ts +29 -6
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +159 -96
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +31 -4
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +65 -8
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +1 -0
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/system-prompt.d.ts +49 -6
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +121 -92
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts +2 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +6 -3
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +1 -2
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +1 -2
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/shell-execution.js +2 -2
- package/dist/core/tools/shell-execution.js.map +1 -1
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +1 -2
- package/dist/core/tools/write.js.map +1 -1
- package/dist/core/usage-totals.d.ts +1 -1
- package/dist/core/usage-totals.d.ts.map +1 -1
- package/dist/core/usage-totals.js +4 -1
- package/dist/core/usage-totals.js.map +1 -1
- package/dist/extensions/background/schema.d.ts +1 -1
- package/dist/extensions/btw/agent.d.ts.map +1 -1
- package/dist/extensions/btw/agent.js +3 -2
- package/dist/extensions/btw/agent.js.map +1 -1
- package/dist/extensions/llama/client.d.ts +2 -0
- package/dist/extensions/llama/client.d.ts.map +1 -1
- package/dist/extensions/llama/client.js +7 -3
- package/dist/extensions/llama/client.js.map +1 -1
- package/dist/extensions/llama/provider.d.ts.map +1 -1
- package/dist/extensions/llama/provider.js +20 -5
- package/dist/extensions/llama/provider.js.map +1 -1
- package/dist/extensions/provider/compat-fields.d.ts.map +1 -1
- package/dist/extensions/provider/compat-fields.js +5 -2
- package/dist/extensions/provider/compat-fields.js.map +1 -1
- package/dist/extensions/provider/ui/app.js +2 -2
- package/dist/extensions/provider/ui/app.js.map +1 -1
- package/dist/extensions/todo/schema.d.ts +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +13 -9
- package/dist/main.js.map +1 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +2 -2
- package/dist/migrations.js.map +1 -1
- package/dist/modes/interactive/bug-report.d.ts +16 -0
- package/dist/modes/interactive/bug-report.d.ts.map +1 -0
- package/dist/modes/interactive/bug-report.js +206 -0
- package/dist/modes/interactive/bug-report.js.map +1 -0
- package/dist/modes/interactive/chat-viewport.js +1 -1
- package/dist/modes/interactive/chat-viewport.js.map +1 -1
- package/dist/modes/interactive/components/armin.d.ts.map +1 -1
- package/dist/modes/interactive/components/armin.js +0 -5
- package/dist/modes/interactive/components/armin.js.map +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts +0 -1
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +2 -3
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.js +12 -5
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.js +12 -5
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/countdown-timer.d.ts +6 -13
- package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -1
- package/dist/modes/interactive/components/countdown-timer.js +15 -51
- package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts +3 -3
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- package/dist/modes/interactive/components/extension-editor.d.ts +4 -1
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-editor.js +7 -2
- package/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/dist/modes/interactive/components/extension-input.d.ts +2 -0
- package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-input.js +6 -0
- package/dist/modes/interactive/components/extension-input.js.map +1 -1
- package/dist/modes/interactive/components/extension-selector.d.ts +1 -2
- package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-selector.js +4 -2
- package/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts +5 -8
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +72 -95
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +3 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +11 -0
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.js +11 -4
- package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
- package/dist/modes/interactive/components/status-indicator.d.ts +2 -2
- package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -1
- package/dist/modes/interactive/components/status-indicator.js +7 -7
- package/dist/modes/interactive/components/status-indicator.js.map +1 -1
- package/dist/modes/interactive/components/tool-chrome.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-chrome.js +4 -1
- package/dist/modes/interactive/components/tool-chrome.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +4 -3
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts +1 -10
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js +4 -51
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +15 -2
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +234 -91
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/session-share.d.ts +2 -0
- package/dist/modes/interactive/session-share.d.ts.map +1 -1
- package/dist/modes/interactive/session-share.js +8 -4
- package/dist/modes/interactive/session-share.js.map +1 -1
- package/dist/modes/interactive/tui-renderer.js +2 -2
- package/dist/modes/interactive/tui-renderer.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +2 -2
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/utils/clipboard-command.d.ts +7 -0
- package/dist/utils/clipboard-command.d.ts.map +1 -0
- package/dist/utils/clipboard-command.js +45 -0
- package/dist/utils/clipboard-command.js.map +1 -0
- package/dist/utils/clipboard-image.d.ts.map +1 -1
- package/dist/utils/clipboard-image.js +53 -81
- package/dist/utils/clipboard-image.js.map +1 -1
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +111 -121
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/wsl.d.ts +3 -0
- package/dist/utils/wsl.d.ts.map +1 -0
- package/dist/utils/wsl.js +15 -0
- package/dist/utils/wsl.js.map +1 -0
- package/dist/utils/zip.d.ts +7 -0
- package/dist/utils/zip.d.ts.map +1 -0
- package/dist/utils/zip.js +60 -0
- package/dist/utils/zip.js.map +1 -0
- package/docs/compaction.md +32 -11
- package/docs/custom-provider.md +19 -8
- package/docs/environment-variables.md +1 -0
- package/docs/extensions.md +50 -34
- package/docs/models.md +38 -3
- package/docs/providers.md +9 -1
- package/docs/sdk.md +4 -2
- package/docs/session-format.md +63 -24
- package/docs/sessions.md +28 -1
- package/docs/settings.md +58 -4
- package/docs/termux.md +0 -1
- package/docs/tui.md +2 -0
- package/docs/usage.md +1 -0
- package/examples/extensions/README.md +0 -1
- package/examples/extensions/custom-provider-anthropic/index.ts +18 -12
- package/examples/extensions/custom-provider-gitlab-duo/index.ts +2 -2
- package/examples/extensions/prompt-customizer.ts +19 -67
- package/npm-shrinkwrap.json +275 -1028
- package/package.json +17 -23
- package/dist/bundle/chunks/anthropic-messages-IHRRITCV.js +0 -6
- package/dist/bundle/chunks/azure-openai-responses-QXBIDYXO.js +0 -2
- package/dist/bundle/chunks/chunk-JSJPY26N.js +0 -2
- package/dist/bundle/chunks/chunk-KI6LC764.js +0 -42
- package/dist/bundle/chunks/chunk-OWESLY5T.js +0 -11
- package/dist/bundle/chunks/chunk-RRBI7OUG.js +0 -50
- package/dist/bundle/chunks/chunk-YZJWMPUI.js +0 -2
- package/dist/bundle/chunks/google-generative-ai-NBOR3IQR.js +0 -2
- package/dist/bundle/chunks/google-vertex-VTHX3SUB.js +0 -2
- package/dist/bundle/chunks/https-proxy-agent-2VXB7436.js +0 -13
- package/dist/bundle/chunks/mistral-conversations-NO4ANAA5.js +0 -5
- package/dist/bundle/chunks/openai-codex-responses-5S3T3HMA.js +0 -10
- package/dist/bundle/chunks/openai-completions-CXRRTRWE.js +0 -7
- package/dist/bundle/chunks/openai-responses-CV3MH6VP.js +0 -2
- package/dist/utils/clipboard-native.d.ts +0 -11
- package/dist/utils/clipboard-native.d.ts.map +0 -1
- package/dist/utils/clipboard-native.js +0 -20
- package/dist/utils/clipboard-native.js.map +0 -1
- package/examples/extensions/kimi-deferred-tools.ts +0 -61
|
@@ -6,6 +6,7 @@ import * as crypto from "node:crypto";
|
|
|
6
6
|
import * as fs from "node:fs";
|
|
7
7
|
import * as os from "node:os";
|
|
8
8
|
import * as path from "node:path";
|
|
9
|
+
import { isRetryableAssistantError, } from "@earendil-works/pi-ai/compat";
|
|
9
10
|
import * as TuiLayouts from "@earendil-works/pi-tui";
|
|
10
11
|
import { CombinedAutocompleteProvider, Container, fuzzyFilter, Markdown, matchesKey, Spacer, setCapabilityOverrides, setKeybindings, Text, TruncatedText, TuiAltScreen, TuiMainScreen, visibleWidth, } from "@earendil-works/pi-tui";
|
|
11
12
|
import chalk from "chalk";
|
|
@@ -14,6 +15,8 @@ import { APP_NAME, APP_TITLE, CONFIG_DIR_NAME, getAgentDir, getAuthPath, getDebu
|
|
|
14
15
|
import { parseSkillBlock } 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";
|
|
18
|
+
import { formatCacheWarmingStatus, formatCacheWarmingUsage } from "../../core/cache-warmer.js";
|
|
19
|
+
import { recordCrash, takeUnnotifiedCrash } from "../../core/crash-log.js";
|
|
17
20
|
import { DEFAULT_THINKING_LEVEL, THINKING_LEVEL_OPTIONS } from "../../core/defaults.js";
|
|
18
21
|
import { FooterDataProvider } from "../../core/footer-data-provider.js";
|
|
19
22
|
import { configureHttpDispatcher, formatHttpIdleTimeoutMs } from "../../core/http-dispatcher.js";
|
|
@@ -23,7 +26,7 @@ import { defaultModelPerProvider, findExactModelReferenceMatch, resolveModelScop
|
|
|
23
26
|
import { CredentialSynchronizationError } from "../../core/model-runtime.js";
|
|
24
27
|
import { DefaultPackageManager } from "../../core/package-manager.js";
|
|
25
28
|
import { formatMissingSessionCwdPrompt, MissingSessionCwdError } from "../../core/session-cwd.js";
|
|
26
|
-
import { SessionManager, sessionEntryToContextMessages } from "../../core/session-manager.js";
|
|
29
|
+
import { SessionManager, sessionEntryToContextMessages, } from "../../core/session-manager.js";
|
|
27
30
|
import { BUILTIN_SLASH_COMMANDS } from "../../core/slash-commands.js";
|
|
28
31
|
import { isInstallTelemetryEnabled } from "../../core/telemetry.js";
|
|
29
32
|
import { withBuiltInRenderers } from "../../core/tools/renderers/index.js";
|
|
@@ -38,6 +41,7 @@ import { getPiUserAgent } from "../../utils/pi-user-agent.js";
|
|
|
38
41
|
import { killTrackedDetachedChildren } from "../../utils/shell.js";
|
|
39
42
|
import { ensureTool } from "../../utils/tools-manager.js";
|
|
40
43
|
import { checkForNewPiVersion } from "../../utils/version-check.js";
|
|
44
|
+
import { reportBug } from "./bug-report.js";
|
|
41
45
|
import { createChatViewport } from "./chat-viewport.js";
|
|
42
46
|
import { ArminComponent } from "./components/armin.js";
|
|
43
47
|
import { AssistantMessageComponent } from "./components/assistant-message.js";
|
|
@@ -104,6 +108,9 @@ function isCustomSessionEntry(item) {
|
|
|
104
108
|
function isCompactionCostNotice(item) {
|
|
105
109
|
return "type" in item && item.type === "compaction_cost";
|
|
106
110
|
}
|
|
111
|
+
function isUsageSessionEntry(item) {
|
|
112
|
+
return "type" in item && item.type === "usage";
|
|
113
|
+
}
|
|
107
114
|
const DEAD_TERMINAL_ERROR_CODES = new Set(["EIO", "EPIPE", "ENOTCONN"]);
|
|
108
115
|
function isDeadTerminalError(error) {
|
|
109
116
|
if (!error || typeof error !== "object" || !("code" in error)) {
|
|
@@ -251,6 +258,8 @@ export class InteractiveMode {
|
|
|
251
258
|
this.compactionQueuedMessages = [];
|
|
252
259
|
// Shutdown state
|
|
253
260
|
this.shutdownRequested = false;
|
|
261
|
+
/** The `/bug` hint is shown at most once per session so error output stays readable. */
|
|
262
|
+
this.bugReportHintShown = false;
|
|
254
263
|
// Extension UI state
|
|
255
264
|
this.extensionSelector = undefined;
|
|
256
265
|
this.extensionInput = undefined;
|
|
@@ -292,6 +301,7 @@ export class InteractiveMode {
|
|
|
292
301
|
tuiMode,
|
|
293
302
|
showHardwareCursor: this.settingsManager.getShowHardwareCursor(),
|
|
294
303
|
logDirectory: getAgentDir(),
|
|
304
|
+
terminal: options.terminal,
|
|
295
305
|
onRightClickPaste: this.onRightClickPaste,
|
|
296
306
|
fullscreenCopyOnSelect: this.settingsManager.getFullscreenCopyOnSelect(),
|
|
297
307
|
});
|
|
@@ -772,6 +782,11 @@ export class InteractiveMode {
|
|
|
772
782
|
if (modelFallbackMessage) {
|
|
773
783
|
this.showWarning(modelFallbackMessage);
|
|
774
784
|
}
|
|
785
|
+
const crash = takeUnnotifiedCrash();
|
|
786
|
+
if (crash) {
|
|
787
|
+
const when = new Date(crash.timestamp).toLocaleString();
|
|
788
|
+
this.showWarning(`${APP_NAME} crashed on ${when} (${crash.message}). Run /bug to report it; the crash details are attached automatically.`);
|
|
789
|
+
}
|
|
775
790
|
void this.maybeWarnAboutAnthropicSubscriptionAuth();
|
|
776
791
|
// Process initial messages
|
|
777
792
|
if (initialMessage) {
|
|
@@ -1492,10 +1507,45 @@ export class InteractiveMode {
|
|
|
1492
1507
|
async handleFatalRuntimeError(prefix, error) {
|
|
1493
1508
|
const message = error instanceof Error ? error.message : String(error);
|
|
1494
1509
|
this.showError(`${prefix}: ${message}`);
|
|
1510
|
+
if (this.recordCrash("fatal_error", error)) {
|
|
1511
|
+
this.chatContainer.addChild(new Text(theme.fg("muted", this.crashReportInstructions()), this.outputPad, 0));
|
|
1512
|
+
}
|
|
1495
1513
|
stopThemeWatcher();
|
|
1496
1514
|
this.stop("transcript");
|
|
1497
1515
|
process.exit(1);
|
|
1498
1516
|
}
|
|
1517
|
+
/** Persist a crash so the next start can point the user at `/bug`. Returns false when nothing was written. */
|
|
1518
|
+
recordCrash(kind, error) {
|
|
1519
|
+
try {
|
|
1520
|
+
return (recordCrash({
|
|
1521
|
+
kind,
|
|
1522
|
+
error,
|
|
1523
|
+
sessionFile: this.session.sessionFile,
|
|
1524
|
+
cwd: this.session.sessionManager.getCwd(),
|
|
1525
|
+
}) !== undefined);
|
|
1526
|
+
}
|
|
1527
|
+
catch {
|
|
1528
|
+
return false;
|
|
1529
|
+
}
|
|
1530
|
+
}
|
|
1531
|
+
crashReportInstructions() {
|
|
1532
|
+
const resume = this.session.sessionFile ? `run \`${APP_NAME} -r\` to resume the session, then` : "start pi and";
|
|
1533
|
+
return `To report this crash: ${resume} run /bug. The crash details are attached automatically.`;
|
|
1534
|
+
}
|
|
1535
|
+
suggestBugReport() {
|
|
1536
|
+
if (this.bugReportHintShown)
|
|
1537
|
+
return;
|
|
1538
|
+
this.bugReportHintShown = true;
|
|
1539
|
+
this.chatContainer.addChild(new Text(theme.fg("muted", `If this looks like a ${APP_NAME} bug, /bug sends a report to the developers.`), this.outputPad, 0));
|
|
1540
|
+
this.ui.requestRender();
|
|
1541
|
+
}
|
|
1542
|
+
maybeSuggestBugReport(message) {
|
|
1543
|
+
if (message.stopReason !== "error" || isRetryableAssistantError(message))
|
|
1544
|
+
return;
|
|
1545
|
+
if (/\b(?:abort(?:ed)?|cancel(?:l?ed)?)\b/i.test(message.errorMessage ?? ""))
|
|
1546
|
+
return;
|
|
1547
|
+
this.suggestBugReport();
|
|
1548
|
+
}
|
|
1499
1549
|
disposeChatToolComponents() {
|
|
1500
1550
|
for (const child of this.chatContainer.children) {
|
|
1501
1551
|
const disposable = child;
|
|
@@ -1612,7 +1662,7 @@ export class InteractiveMode {
|
|
|
1612
1662
|
this.activeWorkingIndicatorEmbedded = false;
|
|
1613
1663
|
this.statusContainer.clear();
|
|
1614
1664
|
this.setEditorWorkingStatusIndicator(undefined);
|
|
1615
|
-
if (
|
|
1665
|
+
if (this.setEditorWorkingStatusIndicator(indicator)) {
|
|
1616
1666
|
this.activeWorkingIndicatorEmbedded = true;
|
|
1617
1667
|
return;
|
|
1618
1668
|
}
|
|
@@ -1623,7 +1673,7 @@ export class InteractiveMode {
|
|
|
1623
1673
|
return;
|
|
1624
1674
|
}
|
|
1625
1675
|
const clearedIndicator = this.activeStatusIndicator;
|
|
1626
|
-
const clearedIndicatorWasEmbedded =
|
|
1676
|
+
const clearedIndicatorWasEmbedded = this.activeWorkingIndicatorEmbedded;
|
|
1627
1677
|
clearedIndicator?.dispose();
|
|
1628
1678
|
this.activeStatusIndicator = undefined;
|
|
1629
1679
|
this.activeWorkingIndicatorEmbedded = false;
|
|
@@ -1974,7 +2024,7 @@ export class InteractiveMode {
|
|
|
1974
2024
|
}, {
|
|
1975
2025
|
tui: this.ui,
|
|
1976
2026
|
timeout: opts?.timeout,
|
|
1977
|
-
|
|
2027
|
+
description: opts?.description,
|
|
1978
2028
|
onToggleToolsExpanded: () => this.toggleToolOutputExpansion(),
|
|
1979
2029
|
});
|
|
1980
2030
|
this.disposeActiveSelector();
|
|
@@ -1999,9 +2049,9 @@ export class InteractiveMode {
|
|
|
1999
2049
|
* Show a confirmation dialog for extensions.
|
|
2000
2050
|
*/
|
|
2001
2051
|
async showExtensionConfirm(title, message, opts) {
|
|
2002
|
-
// The message is context, not a heading: render it as the selector's
|
|
2003
|
-
//
|
|
2004
|
-
const result = await this.showExtensionSelector(title, ["Yes", "No"], { ...opts,
|
|
2052
|
+
// The message is context, not a heading: render it as the selector's
|
|
2053
|
+
// description instead of folding it into the accent-bold title.
|
|
2054
|
+
const result = await this.showExtensionSelector(title, ["Yes", "No"], { ...opts, description: message });
|
|
2005
2055
|
return result === "Yes";
|
|
2006
2056
|
}
|
|
2007
2057
|
async promptForMissingSessionCwd(error) {
|
|
@@ -2139,7 +2189,7 @@ export class InteractiveMode {
|
|
|
2139
2189
|
this.editor = this.defaultEditor;
|
|
2140
2190
|
}
|
|
2141
2191
|
this.editorContainer.addChild(this.editor);
|
|
2142
|
-
if (this.activeStatusIndicator
|
|
2192
|
+
if (this.activeStatusIndicator) {
|
|
2143
2193
|
this.statusContainer.clear();
|
|
2144
2194
|
this.activeWorkingIndicatorEmbedded = this.setEditorWorkingStatusIndicator(this.activeStatusIndicator);
|
|
2145
2195
|
if (!this.activeWorkingIndicatorEmbedded) {
|
|
@@ -2464,6 +2514,12 @@ export class InteractiveMode {
|
|
|
2464
2514
|
this.editor.setText("");
|
|
2465
2515
|
return;
|
|
2466
2516
|
}
|
|
2517
|
+
if (text === "/bug" || text.startsWith("/bug ")) {
|
|
2518
|
+
const hint = text.slice("/bug".length).trim();
|
|
2519
|
+
this.editor.setText("");
|
|
2520
|
+
await this.handleBugCommand(hint ? hint : undefined);
|
|
2521
|
+
return;
|
|
2522
|
+
}
|
|
2467
2523
|
if (text === "/copy") {
|
|
2468
2524
|
await this.handleCopyCommand();
|
|
2469
2525
|
this.editor.setText("");
|
|
@@ -2654,6 +2710,10 @@ export class InteractiveMode {
|
|
|
2654
2710
|
this.addCustomEntryToChat(event.entry);
|
|
2655
2711
|
this.ui.requestRender();
|
|
2656
2712
|
}
|
|
2713
|
+
else if (event.entry.type === "usage" && event.entry.kind === "cache_warm") {
|
|
2714
|
+
this.addCacheWarmingUsage(event.entry);
|
|
2715
|
+
this.ui.requestRender();
|
|
2716
|
+
}
|
|
2657
2717
|
break;
|
|
2658
2718
|
case "session_info_changed":
|
|
2659
2719
|
this.updateTerminalTitle();
|
|
@@ -2730,13 +2790,14 @@ export class InteractiveMode {
|
|
|
2730
2790
|
});
|
|
2731
2791
|
}
|
|
2732
2792
|
this.pendingTools.clear();
|
|
2793
|
+
this.maybeSuggestBugReport(this.streamingMessage);
|
|
2733
2794
|
}
|
|
2734
2795
|
else {
|
|
2735
2796
|
// Args are now complete - trigger diff computation for edit tools
|
|
2736
2797
|
for (const [, component] of this.pendingTools.entries()) {
|
|
2737
2798
|
component.setArgsComplete();
|
|
2738
2799
|
}
|
|
2739
|
-
this.
|
|
2800
|
+
this.maybeShowThinkingDropNotice(this.streamingMessage);
|
|
2740
2801
|
this.maybeShowCacheMissNotice(this.streamingMessage);
|
|
2741
2802
|
}
|
|
2742
2803
|
this.streamingComponent = undefined;
|
|
@@ -2999,6 +3060,8 @@ export class InteractiveMode {
|
|
|
2999
3060
|
this.chatContainer.addChild(component);
|
|
3000
3061
|
break;
|
|
3001
3062
|
}
|
|
3063
|
+
case "system":
|
|
3064
|
+
break;
|
|
3002
3065
|
case "user": {
|
|
3003
3066
|
const textContent = this.getUserMessageText(message);
|
|
3004
3067
|
if (textContent) {
|
|
@@ -3045,8 +3108,8 @@ export class InteractiveMode {
|
|
|
3045
3108
|
renderSessionItems(items, options = {}) {
|
|
3046
3109
|
this.clearPendingTools();
|
|
3047
3110
|
const renderedPendingTools = new Map();
|
|
3048
|
-
// Cache
|
|
3049
|
-
//
|
|
3111
|
+
// Cache misses are not persisted, unlike successful cache-warming usage.
|
|
3112
|
+
// Re-derive them and inject them after the assistant messages that paid for them.
|
|
3050
3113
|
const cacheMisses = this.settingsManager.getShowCacheMissNotices()
|
|
3051
3114
|
? collectCacheMisses(this.sessionManager.getEntries(), this.session.modelRuntime)
|
|
3052
3115
|
: new Map();
|
|
@@ -3059,6 +3122,10 @@ export class InteractiveMode {
|
|
|
3059
3122
|
this.addCustomEntryToChat(item);
|
|
3060
3123
|
continue;
|
|
3061
3124
|
}
|
|
3125
|
+
if (isUsageSessionEntry(item)) {
|
|
3126
|
+
this.addCacheWarmingUsage(item);
|
|
3127
|
+
continue;
|
|
3128
|
+
}
|
|
3062
3129
|
if (isCompactionCostNotice(item)) {
|
|
3063
3130
|
this.addCompactionCostNotice(item);
|
|
3064
3131
|
continue;
|
|
@@ -3092,7 +3159,6 @@ export class InteractiveMode {
|
|
|
3092
3159
|
}
|
|
3093
3160
|
}
|
|
3094
3161
|
if (message.stopReason !== "aborted" && message.stopReason !== "error") {
|
|
3095
|
-
this.maybeShowAssistantDiagnostics(message);
|
|
3096
3162
|
const miss = cacheMisses.get(message);
|
|
3097
3163
|
if (miss)
|
|
3098
3164
|
this.addCacheMissNotice(miss);
|
|
@@ -3124,7 +3190,7 @@ export class InteractiveMode {
|
|
|
3124
3190
|
*/
|
|
3125
3191
|
renderSessionEntries(entries, options = {}) {
|
|
3126
3192
|
const items = entries.flatMap((entry) => {
|
|
3127
|
-
if (entry.type === "custom") {
|
|
3193
|
+
if (entry.type === "custom" || (entry.type === "usage" && entry.kind === "cache_warm")) {
|
|
3128
3194
|
return [entry];
|
|
3129
3195
|
}
|
|
3130
3196
|
const messages = sessionEntryToContextMessages(entry);
|
|
@@ -3135,6 +3201,12 @@ export class InteractiveMode {
|
|
|
3135
3201
|
});
|
|
3136
3202
|
this.renderSessionItems(items, options);
|
|
3137
3203
|
}
|
|
3204
|
+
addCacheWarmingUsage(entry) {
|
|
3205
|
+
if (!this.settingsManager.getShowCacheMissNotices())
|
|
3206
|
+
return;
|
|
3207
|
+
this.chatContainer.addChild(new Spacer(1));
|
|
3208
|
+
this.chatContainer.addChild(new Text(theme.fg("dim", formatCacheWarmingUsage(entry)), 1, 0));
|
|
3209
|
+
}
|
|
3138
3210
|
/**
|
|
3139
3211
|
* Render billing usage for a compaction or branch summary. The notice is derived
|
|
3140
3212
|
* from persisted summary usage and is not stored as a separate session entry.
|
|
@@ -3149,31 +3221,42 @@ export class InteractiveMode {
|
|
|
3149
3221
|
this.chatContainer.addChild(new Spacer(1));
|
|
3150
3222
|
this.chatContainer.addChild(new Text(theme.fg("warning", `${label}: ${formatTokens(tokens)} tokens billed${cost}`), 1, 0));
|
|
3151
3223
|
}
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
return;
|
|
3224
|
+
static countDroppedThinkingBlocks(message) {
|
|
3225
|
+
let count = 0;
|
|
3155
3226
|
for (const diagnostic of message.diagnostics ?? []) {
|
|
3156
3227
|
if (diagnostic.type !== "anthropic_input_transformations")
|
|
3157
3228
|
continue;
|
|
3158
3229
|
const transformations = diagnostic.details?.transformations;
|
|
3159
3230
|
if (!Array.isArray(transformations))
|
|
3160
3231
|
continue;
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3232
|
+
count += transformations.filter((transformation) => typeof transformation === "object" &&
|
|
3233
|
+
transformation !== null &&
|
|
3234
|
+
transformation.type === "thinking_dropped").length;
|
|
3235
|
+
}
|
|
3236
|
+
return count;
|
|
3237
|
+
}
|
|
3238
|
+
maybeShowThinkingDropNotice(message) {
|
|
3239
|
+
if (!this.settingsManager.getShowCacheMissNotices())
|
|
3240
|
+
return;
|
|
3241
|
+
const droppedCount = InteractiveMode.countDroppedThinkingBlocks(message);
|
|
3242
|
+
if (droppedCount === 0)
|
|
3243
|
+
return;
|
|
3244
|
+
let previousDroppedCount = 0;
|
|
3245
|
+
// message_end reaches the UI before the current message is persisted,
|
|
3246
|
+
// so the branch's last assistant message is the previous response.
|
|
3247
|
+
const branch = this.sessionManager.getBranch();
|
|
3248
|
+
for (let i = branch.length - 1; i >= 0; i--) {
|
|
3249
|
+
const entry = branch[i];
|
|
3250
|
+
if (entry.type === "message" && entry.message.role === "assistant") {
|
|
3251
|
+
previousDroppedCount = InteractiveMode.countDroppedThinkingBlocks(entry.message);
|
|
3252
|
+
break;
|
|
3253
|
+
}
|
|
3176
3254
|
}
|
|
3255
|
+
if (droppedCount <= previousDroppedCount)
|
|
3256
|
+
return;
|
|
3257
|
+
const noun = droppedCount === 1 ? "thinking block" : "thinking blocks";
|
|
3258
|
+
this.chatContainer.addChild(new Spacer(1));
|
|
3259
|
+
this.chatContainer.addChild(new Text(theme.fg("warning", `Anthropic dropped ${droppedCount} ${noun} (details in session)`), 1, 0));
|
|
3177
3260
|
}
|
|
3178
3261
|
/**
|
|
3179
3262
|
* Show a transcript notice when a completed assistant message paid for a
|
|
@@ -3336,6 +3419,9 @@ export class InteractiveMode {
|
|
|
3336
3419
|
catch { }
|
|
3337
3420
|
console.error(`${APP_NAME} exiting due to uncaughtException:`);
|
|
3338
3421
|
console.error(error);
|
|
3422
|
+
if (this.recordCrash("uncaught_exception", error)) {
|
|
3423
|
+
console.error(`\n${this.crashReportInstructions()}`);
|
|
3424
|
+
}
|
|
3339
3425
|
process.exit(1);
|
|
3340
3426
|
}
|
|
3341
3427
|
/**
|
|
@@ -3443,9 +3529,7 @@ export class InteractiveMode {
|
|
|
3443
3529
|
const level = this.session.thinkingLevel || "off";
|
|
3444
3530
|
this.editor.borderColor = theme.getThinkingBorderColor(level);
|
|
3445
3531
|
}
|
|
3446
|
-
|
|
3447
|
-
this.activeStatusIndicator.invalidate();
|
|
3448
|
-
}
|
|
3532
|
+
this.activeStatusIndicator?.invalidate();
|
|
3449
3533
|
this.ui.requestRender();
|
|
3450
3534
|
}
|
|
3451
3535
|
cycleThinkingLevel() {
|
|
@@ -3635,7 +3719,7 @@ export class InteractiveMode {
|
|
|
3635
3719
|
if (allQueued.length === 0) {
|
|
3636
3720
|
this.updatePendingMessagesDisplay();
|
|
3637
3721
|
if (options?.abort) {
|
|
3638
|
-
this.
|
|
3722
|
+
void this.session.abort();
|
|
3639
3723
|
}
|
|
3640
3724
|
return 0;
|
|
3641
3725
|
}
|
|
@@ -3645,7 +3729,7 @@ export class InteractiveMode {
|
|
|
3645
3729
|
this.editor.setText(combinedText);
|
|
3646
3730
|
this.updatePendingMessagesDisplay();
|
|
3647
3731
|
if (options?.abort) {
|
|
3648
|
-
this.
|
|
3732
|
+
void this.session.abort();
|
|
3649
3733
|
}
|
|
3650
3734
|
return allQueued.length;
|
|
3651
3735
|
}
|
|
@@ -3806,6 +3890,7 @@ export class InteractiveMode {
|
|
|
3806
3890
|
followUpMode: this.session.followUpMode,
|
|
3807
3891
|
transport: this.settingsManager.getTransport(),
|
|
3808
3892
|
httpIdleTimeoutMs: this.settingsManager.getHttpIdleTimeoutMs(),
|
|
3893
|
+
cacheWarmingMode: this.settingsManager.getCacheWarmingMode(),
|
|
3809
3894
|
thinkingLevel: this.settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL,
|
|
3810
3895
|
availableThinkingLevels: [...THINKING_LEVEL_OPTIONS],
|
|
3811
3896
|
modelThinkingLevels: this.settingsManager.getAllModelThinkingLevels(),
|
|
@@ -3878,6 +3963,10 @@ export class InteractiveMode {
|
|
|
3878
3963
|
configureHttpDispatcher(timeoutMs);
|
|
3879
3964
|
this.showStatus(`HTTP idle timeout: ${formatHttpIdleTimeoutMs(timeoutMs)}`);
|
|
3880
3965
|
},
|
|
3966
|
+
onCacheWarmingModeChange: (mode) => {
|
|
3967
|
+
this.session.setCacheWarmingMode(mode);
|
|
3968
|
+
this.showStatus(`Cache warming: ${mode}`);
|
|
3969
|
+
},
|
|
3881
3970
|
onModelThinkingLevelChange: (provider, modelId, level) => {
|
|
3882
3971
|
this.settingsManager.setModelThinkingLevel(provider, modelId, level);
|
|
3883
3972
|
// If the override is for the current model, apply it to the session too
|
|
@@ -4429,6 +4518,11 @@ export class InteractiveMode {
|
|
|
4429
4518
|
this.restoreQueuedMessagesToEditor();
|
|
4430
4519
|
await this.session.abort();
|
|
4431
4520
|
}
|
|
4521
|
+
// Recheck after the dialogs and streaming abort, before replacing another operation's UI.
|
|
4522
|
+
if (this.session.isCompacting) {
|
|
4523
|
+
this.showError("Wait for the current compaction or tree navigation to finish before navigating the session tree.");
|
|
4524
|
+
return;
|
|
4525
|
+
}
|
|
4432
4526
|
// Set up escape handler and status indicator if summarizing
|
|
4433
4527
|
let showingSummaryIndicator = false;
|
|
4434
4528
|
const originalOnEscape = this.defaultEditor.onEscape;
|
|
@@ -4480,7 +4574,7 @@ export class InteractiveMode {
|
|
|
4480
4574
|
}, (entryId, label) => {
|
|
4481
4575
|
this.sessionManager.appendLabelChange(entryId, label);
|
|
4482
4576
|
this.ui.requestRender();
|
|
4483
|
-
}, initialSelectedId, initialFilterMode
|
|
4577
|
+
}, initialSelectedId, initialFilterMode);
|
|
4484
4578
|
selector.onCopy = async (text) => {
|
|
4485
4579
|
if (!text) {
|
|
4486
4580
|
this.showError("Selected entry has no text to copy");
|
|
@@ -4494,14 +4588,14 @@ export class InteractiveMode {
|
|
|
4494
4588
|
this.showError(error instanceof Error ? error.message : String(error));
|
|
4495
4589
|
}
|
|
4496
4590
|
};
|
|
4497
|
-
return { component: selector, focus: selector
|
|
4591
|
+
return { component: selector, focus: selector };
|
|
4498
4592
|
});
|
|
4499
4593
|
}
|
|
4500
4594
|
showSessionSelector() {
|
|
4501
4595
|
this.showSelector((done) => {
|
|
4502
|
-
const selector = new SessionSelectorComponent((onProgress) => SessionManager.list(this.sessionManager.getCwd(), this.sessionManager.getSessionDir(), onProgress), (onProgress) => this.sessionManager.usesDefaultSessionDir()
|
|
4503
|
-
? SessionManager.listAll(onProgress)
|
|
4504
|
-
: SessionManager.listAll(this.sessionManager.getSessionDir(), onProgress), async (sessionPath) => {
|
|
4596
|
+
const selector = new SessionSelectorComponent((onProgress, signal) => SessionManager.list(this.sessionManager.getCwd(), this.sessionManager.getSessionDir(), onProgress, signal), (onProgress, signal) => this.sessionManager.usesDefaultSessionDir()
|
|
4597
|
+
? SessionManager.listAll(onProgress, signal)
|
|
4598
|
+
: SessionManager.listAll(this.sessionManager.getSessionDir(), onProgress, signal), async (sessionPath) => {
|
|
4505
4599
|
done();
|
|
4506
4600
|
await this.handleResumeSession(sessionPath);
|
|
4507
4601
|
}, () => {
|
|
@@ -4520,7 +4614,7 @@ export class InteractiveMode {
|
|
|
4520
4614
|
showRenameHint: true,
|
|
4521
4615
|
keybindings: this.keybindings,
|
|
4522
4616
|
}, this.sessionManager.getSessionFile());
|
|
4523
|
-
return { component: selector, focus: selector
|
|
4617
|
+
return { component: selector, focus: selector };
|
|
4524
4618
|
});
|
|
4525
4619
|
}
|
|
4526
4620
|
async handleResumeSession(sessionPath, options) {
|
|
@@ -4764,67 +4858,89 @@ export class InteractiveMode {
|
|
|
4764
4858
|
}
|
|
4765
4859
|
async completeProviderAuthentication(providerId, providerName, authType, previousModel) {
|
|
4766
4860
|
const actionLabel = authType === "oauth" ? `Logged in to ${providerName}` : `Saved API key for ${providerName}`;
|
|
4767
|
-
|
|
4768
|
-
|
|
4769
|
-
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
|
|
4773
|
-
|
|
4774
|
-
|
|
4775
|
-
|
|
4776
|
-
|
|
4777
|
-
|
|
4778
|
-
|
|
4779
|
-
|
|
4780
|
-
|
|
4781
|
-
|
|
4782
|
-
|
|
4783
|
-
|
|
4784
|
-
|
|
4785
|
-
|
|
4786
|
-
|
|
4861
|
+
const session = this.session;
|
|
4862
|
+
// Dynamic catalogs may be empty until the first authenticated network refresh.
|
|
4863
|
+
const deferSelection = isUnknownModel(previousModel) &&
|
|
4864
|
+
hasDefaultModelProvider(providerId) &&
|
|
4865
|
+
!session.modelRuntime
|
|
4866
|
+
.getAvailableSnapshot()
|
|
4867
|
+
.some((model) => model.provider === providerId && model.id === defaultModelPerProvider[providerId]);
|
|
4868
|
+
const finishAuthentication = async () => {
|
|
4869
|
+
let selectedModel;
|
|
4870
|
+
let selectionError;
|
|
4871
|
+
if (isUnknownModel(previousModel)) {
|
|
4872
|
+
const availableModels = this.session.modelRuntime.getAvailableSnapshot();
|
|
4873
|
+
const providerModels = availableModels.filter((model) => model.provider === providerId);
|
|
4874
|
+
// Matches LLAMA_PROVIDER_ID from extensions/llama/provider.ts; kept inline to avoid coupling interactive mode to the built-in extension.
|
|
4875
|
+
if (providerId === "llama.cpp") {
|
|
4876
|
+
selectionError = llamaCppPostLoginGuidance(actionLabel, providerModels.length);
|
|
4877
|
+
}
|
|
4878
|
+
else if (!hasDefaultModelProvider(providerId)) {
|
|
4879
|
+
selectionError = `${actionLabel}, but no default model is configured for provider "${providerId}". Use /model to select a model.`;
|
|
4880
|
+
}
|
|
4881
|
+
else if (providerModels.length === 0) {
|
|
4882
|
+
selectionError = `${actionLabel}, but no models are available for that provider. Use /model to select a model.`;
|
|
4787
4883
|
}
|
|
4788
4884
|
else {
|
|
4789
|
-
|
|
4790
|
-
|
|
4885
|
+
const defaultModelId = defaultModelPerProvider[providerId];
|
|
4886
|
+
// Radius catalogs vary by account; prefer balanced, then use catalog order.
|
|
4887
|
+
selectedModel =
|
|
4888
|
+
providerModels.find((model) => model.id === defaultModelId) ??
|
|
4889
|
+
(providerId === "radius" ? providerModels[0] : undefined);
|
|
4890
|
+
if (!selectedModel) {
|
|
4891
|
+
selectionError = `${actionLabel}, but its default model "${defaultModelId}" is not available. Use /model to select a model.`;
|
|
4791
4892
|
}
|
|
4792
|
-
|
|
4793
|
-
|
|
4794
|
-
|
|
4795
|
-
|
|
4893
|
+
else {
|
|
4894
|
+
try {
|
|
4895
|
+
await this.session.setModel(selectedModel, { persist: true });
|
|
4896
|
+
}
|
|
4897
|
+
catch (error) {
|
|
4898
|
+
selectedModel = undefined;
|
|
4899
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
4900
|
+
selectionError = `${actionLabel}, but selecting its default model failed: ${errorMessage}. Use /model to select a model.`;
|
|
4901
|
+
}
|
|
4796
4902
|
}
|
|
4797
4903
|
}
|
|
4798
4904
|
}
|
|
4799
|
-
|
|
4800
|
-
|
|
4801
|
-
|
|
4802
|
-
|
|
4803
|
-
|
|
4804
|
-
|
|
4805
|
-
|
|
4806
|
-
this.checkDaxnutsEasterEgg(selectedModel);
|
|
4807
|
-
}
|
|
4808
|
-
else {
|
|
4809
|
-
this.showStatus(`${actionLabel}. Credentials saved to ${getAuthPath()}`);
|
|
4810
|
-
if (selectionError) {
|
|
4811
|
-
this.showError(selectionError);
|
|
4905
|
+
await this.updateAvailableProviderCount();
|
|
4906
|
+
this.footer.invalidate();
|
|
4907
|
+
this.updateEditorBorderColor();
|
|
4908
|
+
if (selectedModel) {
|
|
4909
|
+
this.showStatus(`${actionLabel}. Selected ${selectedModel.id}. Credentials saved to ${getAuthPath()}`);
|
|
4910
|
+
void this.maybeWarnAboutAnthropicSubscriptionAuth(selectedModel);
|
|
4911
|
+
this.checkDaxnutsEasterEgg(selectedModel);
|
|
4812
4912
|
}
|
|
4813
4913
|
else {
|
|
4814
|
-
|
|
4914
|
+
this.showStatus(`${actionLabel}. Credentials saved to ${getAuthPath()}`);
|
|
4915
|
+
if (selectionError) {
|
|
4916
|
+
this.showError(selectionError);
|
|
4917
|
+
}
|
|
4918
|
+
else {
|
|
4919
|
+
void this.maybeWarnAboutAnthropicSubscriptionAuth();
|
|
4920
|
+
}
|
|
4815
4921
|
}
|
|
4922
|
+
};
|
|
4923
|
+
if (deferSelection) {
|
|
4924
|
+
this.showStatus(`${actionLabel}. Credentials saved to ${getAuthPath()}. Refreshing model catalog…`);
|
|
4925
|
+
}
|
|
4926
|
+
else {
|
|
4927
|
+
await finishAuthentication();
|
|
4816
4928
|
}
|
|
4817
4929
|
const controller = new AbortController();
|
|
4818
4930
|
const timeout = setTimeout(() => controller.abort(), 15_000);
|
|
4819
|
-
void
|
|
4931
|
+
void session.modelRuntime
|
|
4820
4932
|
.refresh({ providers: [providerId], signal: controller.signal })
|
|
4821
|
-
.then((result) => {
|
|
4933
|
+
.then(async (result) => {
|
|
4822
4934
|
if (result.aborted) {
|
|
4823
4935
|
this.showWarning(`${actionLabel}, but its model catalog refresh timed out; using cached models.`);
|
|
4824
4936
|
}
|
|
4825
4937
|
else if (result.errors.size > 0) {
|
|
4826
4938
|
this.showWarning(`${actionLabel}, but its model catalog could not be refreshed; using cached models.`);
|
|
4827
4939
|
}
|
|
4940
|
+
// Do not replace a model or session selected while the refresh was running.
|
|
4941
|
+
if (deferSelection && this.session === session && session.model === previousModel) {
|
|
4942
|
+
await finishAuthentication();
|
|
4943
|
+
}
|
|
4828
4944
|
this.updateAvailableProviderCount();
|
|
4829
4945
|
this.footer.invalidate();
|
|
4830
4946
|
this.ui.requestRender();
|
|
@@ -5166,6 +5282,17 @@ export class InteractiveMode {
|
|
|
5166
5282
|
showError: (message) => this.showError(message),
|
|
5167
5283
|
});
|
|
5168
5284
|
}
|
|
5285
|
+
async handleBugCommand(hint) {
|
|
5286
|
+
await reportBug({
|
|
5287
|
+
session: this.session,
|
|
5288
|
+
ui: this.ui,
|
|
5289
|
+
editorContainer: this.editorContainer,
|
|
5290
|
+
editor: this.editor,
|
|
5291
|
+
keybindings: this.keybindings,
|
|
5292
|
+
showStatus: (message) => this.showStatus(message),
|
|
5293
|
+
showError: (message) => this.showError(message),
|
|
5294
|
+
}, hint);
|
|
5295
|
+
}
|
|
5169
5296
|
async handleCopyCommand(options = {}) {
|
|
5170
5297
|
if (options.preferSelection &&
|
|
5171
5298
|
this.ui instanceof TuiAltScreen &&
|
|
@@ -5251,6 +5378,15 @@ export class InteractiveMode {
|
|
|
5251
5378
|
}
|
|
5252
5379
|
info += `${theme.fg("dim", "Output:")} ${stats.tokens.output.toLocaleString()}\n`;
|
|
5253
5380
|
info += `${theme.fg("dim", "Total:")} ${stats.tokens.total.toLocaleString()}\n`;
|
|
5381
|
+
const cacheWarmingStatus = this.session.cacheWarmingStatus;
|
|
5382
|
+
info += `\n${theme.bold("Cache Warming")}\n`;
|
|
5383
|
+
info += `${theme.fg("dim", "Mode:")} ${this.settingsManager.getCacheWarmingMode()}\n`;
|
|
5384
|
+
info += `${theme.fg("dim", "Status:")} ${cacheWarmingStatus ? formatCacheWarmingStatus(cacheWarmingStatus) : "Inactive (cache warming unavailable)"}\n`;
|
|
5385
|
+
const decision = cacheWarmingStatus?.decision;
|
|
5386
|
+
if (decision?.economicsAvailable) {
|
|
5387
|
+
info += `${theme.fg("dim", "Cache miss penalty:")} $${decision.missCost.toFixed(3)}\n`;
|
|
5388
|
+
info += `${theme.fg("dim", "Refresh cost:")} $${decision.warmCost.toFixed(3)}\n`;
|
|
5389
|
+
}
|
|
5254
5390
|
if (stats.cost > 0 || cacheWaste.missedTokens > 0) {
|
|
5255
5391
|
info += `\n${theme.bold("Cost")}\n`;
|
|
5256
5392
|
info += `${theme.fg("dim", "Total:")} $${stats.cost.toFixed(3)}`;
|
|
@@ -5381,7 +5517,7 @@ export class InteractiveMode {
|
|
|
5381
5517
|
| \`${expandTools}\` | Toggle tool output expansion |
|
|
5382
5518
|
| \`${toggleThinking}\` | Toggle thinking block visibility |
|
|
5383
5519
|
| \`${externalEditor}\` | Edit message in external editor |
|
|
5384
|
-
| \`${copyMessage}\` | Copy last assistant message |
|
|
5520
|
+
| \`${copyMessage}\` | Copy selection or last assistant message |
|
|
5385
5521
|
| \`${followUp}\` | Queue follow-up message |
|
|
5386
5522
|
| \`${dequeue}\` | Restore queued messages |
|
|
5387
5523
|
| \`${pasteImage}\` | Paste image or text from clipboard |
|
|
@@ -5477,12 +5613,19 @@ export class InteractiveMode {
|
|
|
5477
5613
|
async handleBashCommand(command, excludeFromContext = false) {
|
|
5478
5614
|
const extensionRunner = this.session.extensionRunner;
|
|
5479
5615
|
// Emit user_bash event to let extensions intercept
|
|
5480
|
-
|
|
5481
|
-
|
|
5482
|
-
|
|
5483
|
-
|
|
5484
|
-
|
|
5485
|
-
|
|
5616
|
+
let eventResult;
|
|
5617
|
+
try {
|
|
5618
|
+
eventResult = await extensionRunner.emitUserBash({
|
|
5619
|
+
type: "user_bash",
|
|
5620
|
+
command,
|
|
5621
|
+
excludeFromContext,
|
|
5622
|
+
cwd: this.sessionManager.getCwd(),
|
|
5623
|
+
});
|
|
5624
|
+
}
|
|
5625
|
+
catch {
|
|
5626
|
+
// The extension runner already reported the error. Do not fall back to local execution.
|
|
5627
|
+
return;
|
|
5628
|
+
}
|
|
5486
5629
|
// If extension returned a full result, use it directly
|
|
5487
5630
|
if (eventResult?.result) {
|
|
5488
5631
|
const result = eventResult.result;
|