@averyyy/pi-coding-agent 0.85.1-piclient.9 → 0.86.1-piclient.2
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 +109 -0
- package/README.md +3 -1
- package/dist/bundle/chunks/anthropic-messages-MYU5ZMRF.js +6 -0
- package/dist/bundle/chunks/azure-openai-responses-QJ7SPP5M.js +2 -0
- package/dist/bundle/chunks/bedrock-converse-stream.js +47 -38
- package/dist/bundle/chunks/chunk-7L6OAVKC.js +1663 -0
- package/dist/bundle/chunks/chunk-A3JYRWB6.js +2 -0
- package/dist/bundle/chunks/chunk-DTD7JQ7Y.js +42 -0
- package/dist/bundle/chunks/chunk-FUXEF6JQ.js +44 -0
- package/dist/bundle/chunks/{chunk-IDDQWTHI.js → chunk-RCZIEVGO.js} +10 -1
- package/dist/bundle/chunks/chunk-S7SZN6Z3.js +2 -0
- package/dist/bundle/chunks/chunk-UZNGGY6N.js +11 -0
- package/dist/bundle/chunks/chunk-XREANBOX.js +2 -0
- package/dist/bundle/chunks/devin-runtime.js +7 -2
- package/dist/bundle/chunks/github-copilot.js +1 -1
- package/dist/bundle/chunks/google-generative-ai-IMS5EK2Y.js +2 -0
- package/dist/bundle/chunks/google-vertex-O4YJEQUW.js +2 -0
- package/dist/bundle/chunks/jiti-loader-C3NU2SDH.js +21 -0
- package/dist/bundle/chunks/jiti-static-loader-E6ANQD5T.js +2 -0
- package/dist/bundle/chunks/meta.js +2 -0
- package/dist/bundle/chunks/mistral-conversations-NOSQHBEY.js +5 -0
- package/dist/bundle/chunks/{node-KG362ECQ.js → node-O3RIBJRH.js} +1 -1
- package/dist/bundle/chunks/openai-codex-responses-SG7PGUUZ.js +10 -0
- package/dist/bundle/chunks/openai-completions-CYGM3XXP.js +7 -0
- package/dist/bundle/chunks/openai-responses-AH7QTG23.js +2 -0
- package/dist/bundle/chunks/{pi-messages-PML4SPVJ.js → pi-messages-GFKBWJHZ.js} +1 -1
- package/dist/bundle/chunks/virtual-modules-SC5AFIK5.js +2 -0
- package/dist/bundle/cli-runtime.js +3 -0
- package/dist/bundle/cli.js +4 -2
- 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.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -1
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session.d.ts +56 -6
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +362 -183
- 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 +342 -0
- package/dist/core/cache-warmer.js.map +1 -0
- package/dist/core/compaction/compaction.d.ts +2 -2
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +23 -18
- package/dist/core/compaction/compaction.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 +38 -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.d.ts.map +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 +61 -41
- 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 +20 -4
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +43 -7
- 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 +19 -5
- 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/renderers/bash.d.ts.map +1 -1
- package/dist/core/tools/renderers/bash.js +9 -1
- package/dist/core/tools/renderers/bash.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 +5 -1
- package/dist/core/usage-totals.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/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.d.ts.map +1 -1
- package/dist/modes/interactive/chat-viewport.js +1 -1
- package/dist/modes/interactive/chat-viewport.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/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 -0
- package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-selector.js +4 -0
- package/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +4 -1
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts +5 -5
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +74 -48
- 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-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +18 -9
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js +2 -0
- 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 +235 -86
- 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.d.ts.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.d.ts.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 +39 -13
- package/docs/custom-provider.md +22 -13
- package/docs/development.md +4 -4
- package/docs/docs.json +4 -0
- package/docs/environment-variables.md +1 -0
- package/docs/extensions.md +57 -43
- package/docs/json.md +4 -4
- package/docs/models.md +33 -2
- package/docs/providers.md +10 -2
- package/docs/sdk.md +4 -2
- package/docs/security.md +1 -1
- package/docs/session-format.md +82 -40
- package/docs/sessions.md +27 -0
- package/docs/settings.md +60 -1
- package/docs/termux.md +0 -1
- package/docs/tui.md +2 -2
- 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-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/index.ts +2 -2
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/prompt-customizer.ts +19 -67
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/package.json +17 -23
- package/dist/bundle/chunks/anthropic-messages-VWZZOSJQ.js +0 -6
- package/dist/bundle/chunks/azure-openai-responses-B467Y57F.js +0 -2
- package/dist/bundle/chunks/chunk-6WPJTKUF.js +0 -11
- package/dist/bundle/chunks/chunk-AXIIZGTV.js +0 -2
- package/dist/bundle/chunks/chunk-CLNPYIDP.js +0 -42
- package/dist/bundle/chunks/chunk-GMWCTUPB.js +0 -2
- package/dist/bundle/chunks/chunk-ORJJLIYM.js +0 -1648
- package/dist/bundle/chunks/chunk-U6ZMQKGD.js +0 -50
- package/dist/bundle/chunks/chunk-UAQELI3K.js +0 -2
- package/dist/bundle/chunks/google-generative-ai-Q2K7FBDI.js +0 -2
- package/dist/bundle/chunks/google-vertex-7UJBF4S7.js +0 -2
- package/dist/bundle/chunks/mistral-conversations-4M6BZBX6.js +0 -5
- package/dist/bundle/chunks/openai-codex-responses-MERYAUSE.js +0 -10
- package/dist/bundle/chunks/openai-completions-EKZT2IH2.js +0 -7
- package/dist/bundle/chunks/openai-responses-YZ6M7S4X.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, getCapabilities, hyperlink, 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";
|
|
@@ -24,7 +27,7 @@ import { CredentialSynchronizationError } from "../../core/model-runtime.js";
|
|
|
24
27
|
import { DefaultPackageManager } from "../../core/package-manager.js";
|
|
25
28
|
import { getCliBinName } from "../../core/pi-client-cli-adapter.js";
|
|
26
29
|
import { formatMissingSessionCwdPrompt, MissingSessionCwdError } from "../../core/session-cwd.js";
|
|
27
|
-
import { SessionManager, sessionEntryToContextMessages } from "../../core/session-manager.js";
|
|
30
|
+
import { SessionManager, sessionEntryToContextMessages, } from "../../core/session-manager.js";
|
|
28
31
|
import { BUILTIN_SLASH_COMMANDS } from "../../core/slash-commands.js";
|
|
29
32
|
import { isInstallTelemetryEnabled } from "../../core/telemetry.js";
|
|
30
33
|
import { withBuiltInRenderers } from "../../core/tools/renderers/index.js";
|
|
@@ -40,6 +43,7 @@ import { killTrackedDetachedChildren } from "../../utils/shell.js";
|
|
|
40
43
|
import { loadAllHighlightLanguages } from "../../utils/syntax-highlight.js";
|
|
41
44
|
import { ensureTool } from "../../utils/tools-manager.js";
|
|
42
45
|
import { checkForNewPiVersion } from "../../utils/version-check.js";
|
|
46
|
+
import { reportBug } from "./bug-report.js";
|
|
43
47
|
import { createChatViewport } from "./chat-viewport.js";
|
|
44
48
|
import { ArminComponent } from "./components/armin.js";
|
|
45
49
|
import { AssistantMessageComponent } from "./components/assistant-message.js";
|
|
@@ -107,6 +111,9 @@ function isCustomSessionEntry(item) {
|
|
|
107
111
|
function isCompactionCostNotice(item) {
|
|
108
112
|
return "type" in item && item.type === "compaction_cost";
|
|
109
113
|
}
|
|
114
|
+
function isUsageSessionEntry(item) {
|
|
115
|
+
return "type" in item && item.type === "usage";
|
|
116
|
+
}
|
|
110
117
|
const DEAD_TERMINAL_ERROR_CODES = new Set(["EIO", "EPIPE", "ENOTCONN"]);
|
|
111
118
|
function isDeadTerminalError(error) {
|
|
112
119
|
if (!error || typeof error !== "object" || !("code" in error)) {
|
|
@@ -270,6 +277,8 @@ export class InteractiveMode {
|
|
|
270
277
|
compactionQueuedMessages = [];
|
|
271
278
|
// Shutdown state
|
|
272
279
|
shutdownRequested = false;
|
|
280
|
+
/** The `/bug` hint is shown at most once per session so error output stays readable. */
|
|
281
|
+
bugReportHintShown = false;
|
|
273
282
|
// Extension UI state
|
|
274
283
|
extensionSelector = undefined;
|
|
275
284
|
extensionInput = undefined;
|
|
@@ -328,6 +337,7 @@ export class InteractiveMode {
|
|
|
328
337
|
tuiMode,
|
|
329
338
|
showHardwareCursor: this.settingsManager.getShowHardwareCursor(),
|
|
330
339
|
logDirectory: getAgentDir(),
|
|
340
|
+
terminal: options.terminal,
|
|
331
341
|
onRightClickPaste: this.onRightClickPaste,
|
|
332
342
|
fullscreenCopyOnSelect: this.settingsManager.getFullscreenCopyOnSelect(),
|
|
333
343
|
});
|
|
@@ -831,6 +841,11 @@ export class InteractiveMode {
|
|
|
831
841
|
if (modelFallbackMessage) {
|
|
832
842
|
this.showWarning(modelFallbackMessage);
|
|
833
843
|
}
|
|
844
|
+
const crash = takeUnnotifiedCrash();
|
|
845
|
+
if (crash) {
|
|
846
|
+
const when = new Date(crash.timestamp).toLocaleString();
|
|
847
|
+
this.showWarning(`${APP_NAME} crashed on ${when} (${crash.message}). Run /bug to report it; the crash details are attached automatically.`);
|
|
848
|
+
}
|
|
834
849
|
void this.maybeWarnAboutAnthropicSubscriptionAuth();
|
|
835
850
|
// Process initial messages
|
|
836
851
|
if (initialMessage) {
|
|
@@ -1547,10 +1562,45 @@ export class InteractiveMode {
|
|
|
1547
1562
|
async handleFatalRuntimeError(prefix, error) {
|
|
1548
1563
|
const message = error instanceof Error ? error.message : String(error);
|
|
1549
1564
|
this.showError(`${prefix}: ${message}`);
|
|
1565
|
+
if (this.recordCrash("fatal_error", error)) {
|
|
1566
|
+
this.chatContainer.addChild(new Text(theme.fg("muted", this.crashReportInstructions()), this.outputPad, 0));
|
|
1567
|
+
}
|
|
1550
1568
|
stopThemeWatcher();
|
|
1551
1569
|
this.stop("transcript");
|
|
1552
1570
|
process.exit(1);
|
|
1553
1571
|
}
|
|
1572
|
+
/** Persist a crash so the next start can point the user at `/bug`. Returns false when nothing was written. */
|
|
1573
|
+
recordCrash(kind, error) {
|
|
1574
|
+
try {
|
|
1575
|
+
return (recordCrash({
|
|
1576
|
+
kind,
|
|
1577
|
+
error,
|
|
1578
|
+
sessionFile: this.session.sessionFile,
|
|
1579
|
+
cwd: this.session.sessionManager.getCwd(),
|
|
1580
|
+
}) !== undefined);
|
|
1581
|
+
}
|
|
1582
|
+
catch {
|
|
1583
|
+
return false;
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
crashReportInstructions() {
|
|
1587
|
+
const resume = this.session.sessionFile ? `run \`${APP_NAME} -r\` to resume the session, then` : "start pi and";
|
|
1588
|
+
return `To report this crash: ${resume} run /bug. The crash details are attached automatically.`;
|
|
1589
|
+
}
|
|
1590
|
+
suggestBugReport() {
|
|
1591
|
+
if (this.bugReportHintShown)
|
|
1592
|
+
return;
|
|
1593
|
+
this.bugReportHintShown = true;
|
|
1594
|
+
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));
|
|
1595
|
+
this.ui.requestRender();
|
|
1596
|
+
}
|
|
1597
|
+
maybeSuggestBugReport(message) {
|
|
1598
|
+
if (message.stopReason !== "error" || isRetryableAssistantError(message))
|
|
1599
|
+
return;
|
|
1600
|
+
if (/\b(?:abort(?:ed)?|cancel(?:l?ed)?)\b/i.test(message.errorMessage ?? ""))
|
|
1601
|
+
return;
|
|
1602
|
+
this.suggestBugReport();
|
|
1603
|
+
}
|
|
1554
1604
|
renderCurrentSessionState() {
|
|
1555
1605
|
this.loadedResourcesContainer.clear();
|
|
1556
1606
|
this.chatContainer.clear();
|
|
@@ -1640,7 +1690,7 @@ export class InteractiveMode {
|
|
|
1640
1690
|
this.ui.requestRender();
|
|
1641
1691
|
}
|
|
1642
1692
|
showStatusIndicator(indicator, force = false) {
|
|
1643
|
-
if (this.session
|
|
1693
|
+
if (this.session?.isAborting && !force) {
|
|
1644
1694
|
indicator.dispose();
|
|
1645
1695
|
if (!this.abortingStatusActive) {
|
|
1646
1696
|
this.showAbortingStatusIndicator();
|
|
@@ -1652,7 +1702,7 @@ export class InteractiveMode {
|
|
|
1652
1702
|
this.activeWorkingIndicatorEmbedded = false;
|
|
1653
1703
|
this.statusContainer.clear();
|
|
1654
1704
|
this.setEditorWorkingStatusIndicator(undefined);
|
|
1655
|
-
if (
|
|
1705
|
+
if (this.setEditorWorkingStatusIndicator(indicator)) {
|
|
1656
1706
|
this.activeWorkingIndicatorEmbedded = true;
|
|
1657
1707
|
return;
|
|
1658
1708
|
}
|
|
@@ -1680,7 +1730,7 @@ export class InteractiveMode {
|
|
|
1680
1730
|
this.ui.requestRender();
|
|
1681
1731
|
}
|
|
1682
1732
|
clearStatusIndicator(kind, force = false) {
|
|
1683
|
-
if (this.session
|
|
1733
|
+
if (this.session?.isAborting && !force) {
|
|
1684
1734
|
this.showAbortingStatusIndicator();
|
|
1685
1735
|
return;
|
|
1686
1736
|
}
|
|
@@ -1688,7 +1738,7 @@ export class InteractiveMode {
|
|
|
1688
1738
|
return;
|
|
1689
1739
|
}
|
|
1690
1740
|
const clearedIndicator = this.activeStatusIndicator;
|
|
1691
|
-
const clearedIndicatorWasEmbedded =
|
|
1741
|
+
const clearedIndicatorWasEmbedded = this.activeWorkingIndicatorEmbedded;
|
|
1692
1742
|
this.abortingStatusActive = false;
|
|
1693
1743
|
clearedIndicator?.dispose();
|
|
1694
1744
|
this.activeStatusIndicator = undefined;
|
|
@@ -2226,7 +2276,7 @@ export class InteractiveMode {
|
|
|
2226
2276
|
this.editor = this.defaultEditor;
|
|
2227
2277
|
}
|
|
2228
2278
|
this.editorContainer.addChild(this.editor);
|
|
2229
|
-
if (this.activeStatusIndicator
|
|
2279
|
+
if (this.activeStatusIndicator) {
|
|
2230
2280
|
this.statusContainer.clear();
|
|
2231
2281
|
this.activeWorkingIndicatorEmbedded = this.setEditorWorkingStatusIndicator(this.activeStatusIndicator);
|
|
2232
2282
|
if (!this.activeWorkingIndicatorEmbedded) {
|
|
@@ -2556,6 +2606,12 @@ export class InteractiveMode {
|
|
|
2556
2606
|
this.editor.setText("");
|
|
2557
2607
|
return;
|
|
2558
2608
|
}
|
|
2609
|
+
if (text === "/bug" || text.startsWith("/bug ")) {
|
|
2610
|
+
const hint = text.slice("/bug".length).trim();
|
|
2611
|
+
this.editor.setText("");
|
|
2612
|
+
await this.handleBugCommand(hint ? hint : undefined);
|
|
2613
|
+
return;
|
|
2614
|
+
}
|
|
2559
2615
|
if (text === "/copy") {
|
|
2560
2616
|
await this.handleCopyCommand();
|
|
2561
2617
|
this.editor.setText("");
|
|
@@ -2769,6 +2825,10 @@ export class InteractiveMode {
|
|
|
2769
2825
|
this.addCustomEntryToChat(event.entry);
|
|
2770
2826
|
this.ui.requestRender();
|
|
2771
2827
|
}
|
|
2828
|
+
else if (event.entry.type === "usage" && event.entry.kind === "cache_warm") {
|
|
2829
|
+
this.addCacheWarmingUsage(event.entry);
|
|
2830
|
+
this.ui.requestRender();
|
|
2831
|
+
}
|
|
2772
2832
|
break;
|
|
2773
2833
|
case "session_info_changed":
|
|
2774
2834
|
this.updateTerminalTitle();
|
|
@@ -2849,13 +2909,14 @@ export class InteractiveMode {
|
|
|
2849
2909
|
});
|
|
2850
2910
|
}
|
|
2851
2911
|
this.pendingTools.clear();
|
|
2912
|
+
this.maybeSuggestBugReport(this.streamingMessage);
|
|
2852
2913
|
}
|
|
2853
2914
|
else {
|
|
2854
2915
|
// Args are now complete - trigger diff computation for edit tools
|
|
2855
2916
|
for (const [, component] of this.pendingTools.entries()) {
|
|
2856
2917
|
component.setArgsComplete();
|
|
2857
2918
|
}
|
|
2858
|
-
this.
|
|
2919
|
+
this.maybeShowThinkingDropNotice(this.streamingMessage);
|
|
2859
2920
|
this.maybeShowCacheMissNotice(this.streamingMessage);
|
|
2860
2921
|
}
|
|
2861
2922
|
this.streamingComponent = undefined;
|
|
@@ -3147,6 +3208,8 @@ export class InteractiveMode {
|
|
|
3147
3208
|
this.chatContainer.addChild(component);
|
|
3148
3209
|
break;
|
|
3149
3210
|
}
|
|
3211
|
+
case "system":
|
|
3212
|
+
break;
|
|
3150
3213
|
case "user": {
|
|
3151
3214
|
const textContent = this.getUserMessageText(message);
|
|
3152
3215
|
if (textContent) {
|
|
@@ -3193,8 +3256,8 @@ export class InteractiveMode {
|
|
|
3193
3256
|
renderSessionItems(items, options = {}) {
|
|
3194
3257
|
this.pendingTools.clear();
|
|
3195
3258
|
const renderedPendingTools = new Map();
|
|
3196
|
-
// Cache
|
|
3197
|
-
//
|
|
3259
|
+
// Cache misses are not persisted, unlike successful cache-warming usage.
|
|
3260
|
+
// Re-derive them and inject them after the assistant messages that paid for them.
|
|
3198
3261
|
const cacheMisses = this.settingsManager.getShowCacheMissNotices()
|
|
3199
3262
|
? collectCacheMisses(this.sessionManager.getEntries(), this.session.modelRuntime)
|
|
3200
3263
|
: new Map();
|
|
@@ -3207,6 +3270,10 @@ export class InteractiveMode {
|
|
|
3207
3270
|
this.addCustomEntryToChat(item);
|
|
3208
3271
|
continue;
|
|
3209
3272
|
}
|
|
3273
|
+
if (isUsageSessionEntry(item)) {
|
|
3274
|
+
this.addCacheWarmingUsage(item);
|
|
3275
|
+
continue;
|
|
3276
|
+
}
|
|
3210
3277
|
if (isCompactionCostNotice(item)) {
|
|
3211
3278
|
this.addCompactionCostNotice(item);
|
|
3212
3279
|
continue;
|
|
@@ -3244,7 +3311,6 @@ export class InteractiveMode {
|
|
|
3244
3311
|
}
|
|
3245
3312
|
}
|
|
3246
3313
|
if (message.stopReason !== "aborted" && message.stopReason !== "error") {
|
|
3247
|
-
this.maybeShowAssistantDiagnostics(message);
|
|
3248
3314
|
const miss = cacheMisses.get(message);
|
|
3249
3315
|
if (miss)
|
|
3250
3316
|
this.addCacheMissNotice(miss);
|
|
@@ -3276,7 +3342,7 @@ export class InteractiveMode {
|
|
|
3276
3342
|
*/
|
|
3277
3343
|
renderSessionEntries(entries, options = {}) {
|
|
3278
3344
|
const items = entries.flatMap((entry) => {
|
|
3279
|
-
if (entry.type === "custom") {
|
|
3345
|
+
if (entry.type === "custom" || (entry.type === "usage" && entry.kind === "cache_warm")) {
|
|
3280
3346
|
return [entry];
|
|
3281
3347
|
}
|
|
3282
3348
|
const messages = sessionEntryToContextMessages(entry);
|
|
@@ -3287,6 +3353,12 @@ export class InteractiveMode {
|
|
|
3287
3353
|
});
|
|
3288
3354
|
this.renderSessionItems(items, options);
|
|
3289
3355
|
}
|
|
3356
|
+
addCacheWarmingUsage(entry) {
|
|
3357
|
+
if (!this.settingsManager.getShowCacheMissNotices())
|
|
3358
|
+
return;
|
|
3359
|
+
this.chatContainer.addChild(new Spacer(1));
|
|
3360
|
+
this.chatContainer.addChild(new Text(theme.fg("dim", formatCacheWarmingUsage(entry)), 1, 0));
|
|
3361
|
+
}
|
|
3290
3362
|
/**
|
|
3291
3363
|
* Render billing usage for a compaction or branch summary. The notice is derived
|
|
3292
3364
|
* from persisted summary usage and is not stored as a separate session entry.
|
|
@@ -3301,31 +3373,42 @@ export class InteractiveMode {
|
|
|
3301
3373
|
this.chatContainer.addChild(new Spacer(1));
|
|
3302
3374
|
this.chatContainer.addChild(new Text(theme.fg("warning", `${label}: ${formatTokens(tokens)} tokens billed${cost}`), 1, 0));
|
|
3303
3375
|
}
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
return;
|
|
3376
|
+
static countDroppedThinkingBlocks(message) {
|
|
3377
|
+
let count = 0;
|
|
3307
3378
|
for (const diagnostic of message.diagnostics ?? []) {
|
|
3308
3379
|
if (diagnostic.type !== "anthropic_input_transformations")
|
|
3309
3380
|
continue;
|
|
3310
3381
|
const transformations = diagnostic.details?.transformations;
|
|
3311
3382
|
if (!Array.isArray(transformations))
|
|
3312
3383
|
continue;
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3384
|
+
count += transformations.filter((transformation) => typeof transformation === "object" &&
|
|
3385
|
+
transformation !== null &&
|
|
3386
|
+
transformation.type === "thinking_dropped").length;
|
|
3387
|
+
}
|
|
3388
|
+
return count;
|
|
3389
|
+
}
|
|
3390
|
+
maybeShowThinkingDropNotice(message) {
|
|
3391
|
+
if (!this.settingsManager.getShowCacheMissNotices())
|
|
3392
|
+
return;
|
|
3393
|
+
const droppedCount = InteractiveMode.countDroppedThinkingBlocks(message);
|
|
3394
|
+
if (droppedCount === 0)
|
|
3395
|
+
return;
|
|
3396
|
+
let previousDroppedCount = 0;
|
|
3397
|
+
// message_end reaches the UI before the current message is persisted,
|
|
3398
|
+
// so the branch's last assistant message is the previous response.
|
|
3399
|
+
const branch = this.sessionManager.getBranch();
|
|
3400
|
+
for (let i = branch.length - 1; i >= 0; i--) {
|
|
3401
|
+
const entry = branch[i];
|
|
3402
|
+
if (entry.type === "message" && entry.message.role === "assistant") {
|
|
3403
|
+
previousDroppedCount = InteractiveMode.countDroppedThinkingBlocks(entry.message);
|
|
3404
|
+
break;
|
|
3405
|
+
}
|
|
3328
3406
|
}
|
|
3407
|
+
if (droppedCount <= previousDroppedCount)
|
|
3408
|
+
return;
|
|
3409
|
+
const noun = droppedCount === 1 ? "thinking block" : "thinking blocks";
|
|
3410
|
+
this.chatContainer.addChild(new Spacer(1));
|
|
3411
|
+
this.chatContainer.addChild(new Text(theme.fg("warning", `Anthropic dropped ${droppedCount} ${noun} (details in session)`), 1, 0));
|
|
3329
3412
|
}
|
|
3330
3413
|
/**
|
|
3331
3414
|
* Show a transcript notice when a completed assistant message paid for a
|
|
@@ -3493,6 +3576,9 @@ export class InteractiveMode {
|
|
|
3493
3576
|
catch { }
|
|
3494
3577
|
console.error(`${APP_NAME} exiting due to uncaughtException:`);
|
|
3495
3578
|
console.error(error);
|
|
3579
|
+
if (this.recordCrash("uncaught_exception", error)) {
|
|
3580
|
+
console.error(`\n${this.crashReportInstructions()}`);
|
|
3581
|
+
}
|
|
3496
3582
|
process.exit(1);
|
|
3497
3583
|
}
|
|
3498
3584
|
/**
|
|
@@ -3628,9 +3714,7 @@ export class InteractiveMode {
|
|
|
3628
3714
|
const level = this.session.thinkingLevel || "off";
|
|
3629
3715
|
this.editor.borderColor = theme.getThinkingBorderColor(level);
|
|
3630
3716
|
}
|
|
3631
|
-
|
|
3632
|
-
this.activeStatusIndicator.invalidate();
|
|
3633
|
-
}
|
|
3717
|
+
this.activeStatusIndicator?.invalidate();
|
|
3634
3718
|
this.ui.requestRender();
|
|
3635
3719
|
}
|
|
3636
3720
|
cycleThinkingLevel() {
|
|
@@ -3827,7 +3911,10 @@ export class InteractiveMode {
|
|
|
3827
3911
|
if (allQueued.length === 0) {
|
|
3828
3912
|
this.updatePendingMessagesDisplay();
|
|
3829
3913
|
if (options?.abort) {
|
|
3830
|
-
this.requestAbort
|
|
3914
|
+
if (typeof this.requestAbort === "function")
|
|
3915
|
+
this.requestAbort();
|
|
3916
|
+
else
|
|
3917
|
+
void this.session.abort();
|
|
3831
3918
|
}
|
|
3832
3919
|
return 0;
|
|
3833
3920
|
}
|
|
@@ -3837,7 +3924,10 @@ export class InteractiveMode {
|
|
|
3837
3924
|
this.editor.setText(combinedText);
|
|
3838
3925
|
this.updatePendingMessagesDisplay();
|
|
3839
3926
|
if (options?.abort) {
|
|
3840
|
-
this.requestAbort
|
|
3927
|
+
if (typeof this.requestAbort === "function")
|
|
3928
|
+
this.requestAbort();
|
|
3929
|
+
else
|
|
3930
|
+
void this.session.abort();
|
|
3841
3931
|
}
|
|
3842
3932
|
return allQueued.length;
|
|
3843
3933
|
}
|
|
@@ -4000,6 +4090,7 @@ export class InteractiveMode {
|
|
|
4000
4090
|
followUpMode: this.session.followUpMode,
|
|
4001
4091
|
transport: this.settingsManager.getTransport(),
|
|
4002
4092
|
httpIdleTimeoutMs: this.settingsManager.getHttpIdleTimeoutMs(),
|
|
4093
|
+
cacheWarmingMode: this.settingsManager.getCacheWarmingMode(),
|
|
4003
4094
|
thinkingLevel: this.settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL,
|
|
4004
4095
|
availableThinkingLevels: [...THINKING_LEVEL_OPTIONS],
|
|
4005
4096
|
modelThinkingLevels: this.settingsManager.getAllModelThinkingLevels(),
|
|
@@ -4072,6 +4163,10 @@ export class InteractiveMode {
|
|
|
4072
4163
|
configureHttpDispatcher(timeoutMs);
|
|
4073
4164
|
this.showStatus(`HTTP idle timeout: ${formatHttpIdleTimeoutMs(timeoutMs)}`);
|
|
4074
4165
|
},
|
|
4166
|
+
onCacheWarmingModeChange: (mode) => {
|
|
4167
|
+
this.session.setCacheWarmingMode(mode);
|
|
4168
|
+
this.showStatus(`Cache warming: ${mode}`);
|
|
4169
|
+
},
|
|
4075
4170
|
onModelThinkingLevelChange: (provider, modelId, level) => {
|
|
4076
4171
|
this.settingsManager.setModelThinkingLevel(provider, modelId, level);
|
|
4077
4172
|
// If the override is for the current model, apply it to the session too
|
|
@@ -4623,6 +4718,11 @@ export class InteractiveMode {
|
|
|
4623
4718
|
this.restoreQueuedMessagesToEditor();
|
|
4624
4719
|
await this.session.abort();
|
|
4625
4720
|
}
|
|
4721
|
+
// Recheck after the dialogs and streaming abort, before replacing another operation's UI.
|
|
4722
|
+
if (this.session.isCompacting) {
|
|
4723
|
+
this.showError("Wait for the current compaction or tree navigation to finish before navigating the session tree.");
|
|
4724
|
+
return;
|
|
4725
|
+
}
|
|
4626
4726
|
// Set up escape handler and status indicator if summarizing
|
|
4627
4727
|
let showingSummaryIndicator = false;
|
|
4628
4728
|
const originalOnEscape = this.defaultEditor.onEscape;
|
|
@@ -4693,9 +4793,9 @@ export class InteractiveMode {
|
|
|
4693
4793
|
}
|
|
4694
4794
|
showSessionSelector() {
|
|
4695
4795
|
this.showSelector((done) => {
|
|
4696
|
-
const selector = new SessionSelectorComponent((onProgress) => SessionManager.list(this.sessionManager.getCwd(), this.sessionManager.getSessionDir(), onProgress), (onProgress) => this.sessionManager.usesDefaultSessionDir()
|
|
4697
|
-
? SessionManager.listAll(onProgress)
|
|
4698
|
-
: SessionManager.listAll(this.sessionManager.getSessionDir(), onProgress), async (sessionPath) => {
|
|
4796
|
+
const selector = new SessionSelectorComponent((onProgress, signal) => SessionManager.list(this.sessionManager.getCwd(), this.sessionManager.getSessionDir(), onProgress, signal), (onProgress, signal) => this.sessionManager.usesDefaultSessionDir()
|
|
4797
|
+
? SessionManager.listAll(onProgress, signal)
|
|
4798
|
+
: SessionManager.listAll(this.sessionManager.getSessionDir(), onProgress, signal), async (sessionPath) => {
|
|
4699
4799
|
done();
|
|
4700
4800
|
await this.handleResumeSession(sessionPath);
|
|
4701
4801
|
}, () => {
|
|
@@ -4958,67 +5058,89 @@ export class InteractiveMode {
|
|
|
4958
5058
|
}
|
|
4959
5059
|
async completeProviderAuthentication(providerId, providerName, authType, previousModel) {
|
|
4960
5060
|
const actionLabel = authType === "oauth" ? `Logged in to ${providerName}` : `Saved API key for ${providerName}`;
|
|
4961
|
-
|
|
4962
|
-
|
|
4963
|
-
|
|
4964
|
-
|
|
4965
|
-
|
|
4966
|
-
|
|
4967
|
-
|
|
4968
|
-
|
|
4969
|
-
|
|
4970
|
-
|
|
4971
|
-
|
|
4972
|
-
|
|
4973
|
-
|
|
4974
|
-
|
|
4975
|
-
|
|
4976
|
-
|
|
4977
|
-
|
|
4978
|
-
|
|
4979
|
-
|
|
4980
|
-
|
|
5061
|
+
const session = this.session;
|
|
5062
|
+
// Dynamic catalogs may be empty until the first authenticated network refresh.
|
|
5063
|
+
const deferSelection = isUnknownModel(previousModel) &&
|
|
5064
|
+
hasDefaultModelProvider(providerId) &&
|
|
5065
|
+
!session.modelRuntime
|
|
5066
|
+
.getAvailableSnapshot()
|
|
5067
|
+
.some((model) => model.provider === providerId && model.id === defaultModelPerProvider[providerId]);
|
|
5068
|
+
const finishAuthentication = async () => {
|
|
5069
|
+
let selectedModel;
|
|
5070
|
+
let selectionError;
|
|
5071
|
+
if (isUnknownModel(previousModel)) {
|
|
5072
|
+
const availableModels = this.session.modelRuntime.getAvailableSnapshot();
|
|
5073
|
+
const providerModels = availableModels.filter((model) => model.provider === providerId);
|
|
5074
|
+
// Matches LLAMA_PROVIDER_ID from extensions/llama/provider.ts; kept inline to avoid coupling interactive mode to the built-in extension.
|
|
5075
|
+
if (providerId === "llama.cpp") {
|
|
5076
|
+
selectionError = llamaCppPostLoginGuidance(actionLabel, providerModels.length);
|
|
5077
|
+
}
|
|
5078
|
+
else if (!hasDefaultModelProvider(providerId)) {
|
|
5079
|
+
selectionError = `${actionLabel}, but no default model is configured for provider "${providerId}". Use /model to select a model.`;
|
|
5080
|
+
}
|
|
5081
|
+
else if (providerModels.length === 0) {
|
|
5082
|
+
selectionError = `${actionLabel}, but no models are available for that provider. Use /model to select a model.`;
|
|
4981
5083
|
}
|
|
4982
5084
|
else {
|
|
4983
|
-
|
|
4984
|
-
|
|
5085
|
+
const defaultModelId = defaultModelPerProvider[providerId];
|
|
5086
|
+
// Radius catalogs vary by account; prefer balanced, then use catalog order.
|
|
5087
|
+
selectedModel =
|
|
5088
|
+
providerModels.find((model) => model.id === defaultModelId) ??
|
|
5089
|
+
(providerId === "radius" ? providerModels[0] : undefined);
|
|
5090
|
+
if (!selectedModel) {
|
|
5091
|
+
selectionError = `${actionLabel}, but its default model "${defaultModelId}" is not available. Use /model to select a model.`;
|
|
4985
5092
|
}
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
|
|
4989
|
-
|
|
5093
|
+
else {
|
|
5094
|
+
try {
|
|
5095
|
+
await this.session.setModel(selectedModel, { persist: true });
|
|
5096
|
+
}
|
|
5097
|
+
catch (error) {
|
|
5098
|
+
selectedModel = undefined;
|
|
5099
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
5100
|
+
selectionError = `${actionLabel}, but selecting its default model failed: ${errorMessage}. Use /model to select a model.`;
|
|
5101
|
+
}
|
|
4990
5102
|
}
|
|
4991
5103
|
}
|
|
4992
5104
|
}
|
|
4993
|
-
|
|
4994
|
-
|
|
4995
|
-
|
|
4996
|
-
|
|
4997
|
-
|
|
4998
|
-
|
|
4999
|
-
|
|
5000
|
-
this.checkDaxnutsEasterEgg(selectedModel);
|
|
5001
|
-
}
|
|
5002
|
-
else {
|
|
5003
|
-
this.showStatus(`${actionLabel}. Credentials saved to ${getAuthPath()}`);
|
|
5004
|
-
if (selectionError) {
|
|
5005
|
-
this.showError(selectionError);
|
|
5105
|
+
await this.updateAvailableProviderCount();
|
|
5106
|
+
this.footer.invalidate();
|
|
5107
|
+
this.updateEditorBorderColor();
|
|
5108
|
+
if (selectedModel) {
|
|
5109
|
+
this.showStatus(`${actionLabel}. Selected ${selectedModel.id}. Credentials saved to ${getAuthPath()}`);
|
|
5110
|
+
void this.maybeWarnAboutAnthropicSubscriptionAuth(selectedModel);
|
|
5111
|
+
this.checkDaxnutsEasterEgg(selectedModel);
|
|
5006
5112
|
}
|
|
5007
5113
|
else {
|
|
5008
|
-
|
|
5114
|
+
this.showStatus(`${actionLabel}. Credentials saved to ${getAuthPath()}`);
|
|
5115
|
+
if (selectionError) {
|
|
5116
|
+
this.showError(selectionError);
|
|
5117
|
+
}
|
|
5118
|
+
else {
|
|
5119
|
+
void this.maybeWarnAboutAnthropicSubscriptionAuth();
|
|
5120
|
+
}
|
|
5009
5121
|
}
|
|
5122
|
+
};
|
|
5123
|
+
if (deferSelection) {
|
|
5124
|
+
this.showStatus(`${actionLabel}. Credentials saved to ${getAuthPath()}. Refreshing model catalog…`);
|
|
5125
|
+
}
|
|
5126
|
+
else {
|
|
5127
|
+
await finishAuthentication();
|
|
5010
5128
|
}
|
|
5011
5129
|
const controller = new AbortController();
|
|
5012
5130
|
const timeout = setTimeout(() => controller.abort(), 15_000);
|
|
5013
|
-
void
|
|
5131
|
+
void session.modelRuntime
|
|
5014
5132
|
.refresh({ providers: [providerId], signal: controller.signal })
|
|
5015
|
-
.then((result) => {
|
|
5133
|
+
.then(async (result) => {
|
|
5016
5134
|
if (result.aborted) {
|
|
5017
5135
|
this.showWarning(`${actionLabel}, but its model catalog refresh timed out; using cached models.`);
|
|
5018
5136
|
}
|
|
5019
5137
|
else if (result.errors.size > 0) {
|
|
5020
5138
|
this.showWarning(`${actionLabel}, but its model catalog could not be refreshed; using cached models.`);
|
|
5021
5139
|
}
|
|
5140
|
+
// Do not replace a model or session selected while the refresh was running.
|
|
5141
|
+
if (deferSelection && this.session === session && session.model === previousModel) {
|
|
5142
|
+
await finishAuthentication();
|
|
5143
|
+
}
|
|
5022
5144
|
this.updateAvailableProviderCount();
|
|
5023
5145
|
this.footer.invalidate();
|
|
5024
5146
|
this.ui.requestRender();
|
|
@@ -5360,6 +5482,17 @@ export class InteractiveMode {
|
|
|
5360
5482
|
showError: (message) => this.showError(message),
|
|
5361
5483
|
});
|
|
5362
5484
|
}
|
|
5485
|
+
async handleBugCommand(hint) {
|
|
5486
|
+
await reportBug({
|
|
5487
|
+
session: this.session,
|
|
5488
|
+
ui: this.ui,
|
|
5489
|
+
editorContainer: this.editorContainer,
|
|
5490
|
+
editor: this.editor,
|
|
5491
|
+
keybindings: this.keybindings,
|
|
5492
|
+
showStatus: (message) => this.showStatus(message),
|
|
5493
|
+
showError: (message) => this.showError(message),
|
|
5494
|
+
}, hint);
|
|
5495
|
+
}
|
|
5363
5496
|
async handleCopyCommand(options = {}) {
|
|
5364
5497
|
if (options.preferSelection &&
|
|
5365
5498
|
this.ui instanceof TuiAltScreen &&
|
|
@@ -5445,6 +5578,15 @@ export class InteractiveMode {
|
|
|
5445
5578
|
}
|
|
5446
5579
|
info += `${theme.fg("dim", "Output:")} ${stats.tokens.output.toLocaleString()}\n`;
|
|
5447
5580
|
info += `${theme.fg("dim", "Total:")} ${stats.tokens.total.toLocaleString()}\n`;
|
|
5581
|
+
const cacheWarmingStatus = this.session.cacheWarmingStatus;
|
|
5582
|
+
info += `\n${theme.bold("Cache Warming")}\n`;
|
|
5583
|
+
info += `${theme.fg("dim", "Mode:")} ${this.settingsManager.getCacheWarmingMode()}\n`;
|
|
5584
|
+
info += `${theme.fg("dim", "Status:")} ${cacheWarmingStatus ? formatCacheWarmingStatus(cacheWarmingStatus) : "Inactive (cache warming unavailable)"}\n`;
|
|
5585
|
+
const decision = cacheWarmingStatus?.decision;
|
|
5586
|
+
if (decision?.economicsAvailable) {
|
|
5587
|
+
info += `${theme.fg("dim", "Cache miss penalty:")} $${decision.missCost.toFixed(3)}\n`;
|
|
5588
|
+
info += `${theme.fg("dim", "Refresh cost:")} $${decision.warmCost.toFixed(3)}\n`;
|
|
5589
|
+
}
|
|
5448
5590
|
if (stats.cost > 0 || cacheWaste.missedTokens > 0) {
|
|
5449
5591
|
info += `\n${theme.bold("Cost")}\n`;
|
|
5450
5592
|
info += `${theme.fg("dim", "Total:")} $${stats.cost.toFixed(3)}`;
|
|
@@ -5575,7 +5717,7 @@ export class InteractiveMode {
|
|
|
5575
5717
|
| \`${expandTools}\` | Toggle tool output expansion |
|
|
5576
5718
|
| \`${toggleThinking}\` | Toggle thinking block visibility |
|
|
5577
5719
|
| \`${externalEditor}\` | Edit message in external editor |
|
|
5578
|
-
| \`${copyMessage}\` | Copy last assistant message |
|
|
5720
|
+
| \`${copyMessage}\` | Copy selection or last assistant message |
|
|
5579
5721
|
| \`${followUp}\` | Queue follow-up message |
|
|
5580
5722
|
| \`${dequeue}\` | Restore queued messages |
|
|
5581
5723
|
| \`${pasteImage}\` | Paste image or text from clipboard |
|
|
@@ -5671,12 +5813,19 @@ export class InteractiveMode {
|
|
|
5671
5813
|
async handleBashCommand(command, excludeFromContext = false) {
|
|
5672
5814
|
const extensionRunner = this.session.extensionRunner;
|
|
5673
5815
|
// Emit user_bash event to let extensions intercept
|
|
5674
|
-
|
|
5675
|
-
|
|
5676
|
-
|
|
5677
|
-
|
|
5678
|
-
|
|
5679
|
-
|
|
5816
|
+
let eventResult;
|
|
5817
|
+
try {
|
|
5818
|
+
eventResult = await extensionRunner.emitUserBash({
|
|
5819
|
+
type: "user_bash",
|
|
5820
|
+
command,
|
|
5821
|
+
excludeFromContext,
|
|
5822
|
+
cwd: this.sessionManager.getCwd(),
|
|
5823
|
+
});
|
|
5824
|
+
}
|
|
5825
|
+
catch {
|
|
5826
|
+
// The extension runner already reported the error. Do not fall back to local execution.
|
|
5827
|
+
return;
|
|
5828
|
+
}
|
|
5680
5829
|
// If extension returned a full result, use it directly
|
|
5681
5830
|
if (eventResult?.result) {
|
|
5682
5831
|
const result = eventResult.result;
|