pi-namespace-patch 0.85.1 → 0.86.0-namespace.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 +86 -0
- package/README.md +26 -705
- package/dist/bundle/chunks/anthropic-messages-MYU5ZMRF.js +6 -0
- package/dist/bundle/chunks/azure-openai-responses-HUSQ3GP2.js +2 -0
- package/dist/bundle/chunks/bedrock-converse-stream.js +47 -38
- 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-IS2VY2NY.js +1561 -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-SXW7XMQG.js +2 -0
- package/dist/bundle/chunks/chunk-WIUZI2CJ.js +11 -0
- 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/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-QDSOTBBO.js +10 -0
- package/dist/bundle/chunks/openai-completions-KQPOPEVM.js +7 -0
- package/dist/bundle/chunks/openai-responses-HWEUZ6WZ.js +2 -0
- package/dist/bundle/chunks/{pi-messages-PML4SPVJ.js → pi-messages-GFKBWJHZ.js} +1 -1
- package/dist/bundle/chunks/virtual-modules-UQVS3IVK.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/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 +294 -157
- 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/branch-summarization.d.ts.map +1 -1
- 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 +2 -2
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +11 -12
- 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 +1 -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 +60 -38
- 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 +10 -4
- 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 +14 -0
- package/dist/modes/interactive/bug-report.d.ts.map +1 -0
- package/dist/modes/interactive/bug-report.js +209 -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-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 +13 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +220 -84
- 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 +52 -69
- package/dist/utils/clipboard-image.js.map +1 -1
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +61 -125
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/version-check.d.ts.map +1 -1
- package/dist/utils/version-check.js +11 -4
- package/dist/utils/version-check.js.map +1 -1
- 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 +2 -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/npm-shrinkwrap.json +435 -762
- package/package.json +17 -23
- package/dist/bundle/chunks/anthropic-messages-VWZZOSJQ.js +0 -6
- package/dist/bundle/chunks/azure-openai-responses-BJLAM6CD.js +0 -2
- 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-JJ2YFCJF.js +0 -1547
- package/dist/bundle/chunks/chunk-OUXLLA64.js +0 -11
- 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-R6VYZTVY.js +0 -10
- package/dist/bundle/chunks/openai-completions-EKZT2IH2.js +0 -7
- package/dist/bundle/chunks/openai-responses-TFDINO6W.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
|
@@ -14,6 +14,8 @@ import { APP_NAME, APP_TITLE, CONFIG_DIR_NAME, getAgentDir, getAuthPath, getDebu
|
|
|
14
14
|
import { parseSkillBlock } from "../../core/agent-session.js";
|
|
15
15
|
import { SessionImportFileNotFoundError } from "../../core/agent-session-runtime.js";
|
|
16
16
|
import { CACHE_TTL_MS, collectCacheMisses, computeCacheWaste, detectCacheMiss, } from "../../core/cache-stats.js";
|
|
17
|
+
import { formatCacheWarmingStatus, formatCacheWarmingUsage } from "../../core/cache-warmer.js";
|
|
18
|
+
import { recordCrash, takeUnnotifiedCrash } from "../../core/crash-log.js";
|
|
17
19
|
import { DEFAULT_THINKING_LEVEL, THINKING_LEVEL_OPTIONS } from "../../core/defaults.js";
|
|
18
20
|
import { FooterDataProvider } from "../../core/footer-data-provider.js";
|
|
19
21
|
import { configureHttpDispatcher, formatHttpIdleTimeoutMs } from "../../core/http-dispatcher.js";
|
|
@@ -23,7 +25,7 @@ import { defaultModelPerProvider, findExactModelReferenceMatch, resolveModelScop
|
|
|
23
25
|
import { CredentialSynchronizationError } from "../../core/model-runtime.js";
|
|
24
26
|
import { DefaultPackageManager } from "../../core/package-manager.js";
|
|
25
27
|
import { formatMissingSessionCwdPrompt, MissingSessionCwdError } from "../../core/session-cwd.js";
|
|
26
|
-
import { SessionManager, sessionEntryToContextMessages } from "../../core/session-manager.js";
|
|
28
|
+
import { SessionManager, sessionEntryToContextMessages, } from "../../core/session-manager.js";
|
|
27
29
|
import { BUILTIN_SLASH_COMMANDS } from "../../core/slash-commands.js";
|
|
28
30
|
import { isInstallTelemetryEnabled } from "../../core/telemetry.js";
|
|
29
31
|
import { withBuiltInRenderers } from "../../core/tools/renderers/index.js";
|
|
@@ -39,6 +41,7 @@ import { killTrackedDetachedChildren } from "../../utils/shell.js";
|
|
|
39
41
|
import { loadAllHighlightLanguages } from "../../utils/syntax-highlight.js";
|
|
40
42
|
import { ensureTool } from "../../utils/tools-manager.js";
|
|
41
43
|
import { checkForNewPiVersion } from "../../utils/version-check.js";
|
|
44
|
+
import { reportBug } from "./bug-report.js";
|
|
42
45
|
import { createChatViewport } from "./chat-viewport.js";
|
|
43
46
|
import { ArminComponent } from "./components/armin.js";
|
|
44
47
|
import { AssistantMessageComponent } from "./components/assistant-message.js";
|
|
@@ -106,6 +109,9 @@ function isCustomSessionEntry(item) {
|
|
|
106
109
|
function isCompactionCostNotice(item) {
|
|
107
110
|
return "type" in item && item.type === "compaction_cost";
|
|
108
111
|
}
|
|
112
|
+
function isUsageSessionEntry(item) {
|
|
113
|
+
return "type" in item && item.type === "usage";
|
|
114
|
+
}
|
|
109
115
|
const DEAD_TERMINAL_ERROR_CODES = new Set(["EIO", "EPIPE", "ENOTCONN"]);
|
|
110
116
|
function isDeadTerminalError(error) {
|
|
111
117
|
if (!error || typeof error !== "object" || !("code" in error)) {
|
|
@@ -267,6 +273,8 @@ export class InteractiveMode {
|
|
|
267
273
|
compactionQueuedMessages = [];
|
|
268
274
|
// Shutdown state
|
|
269
275
|
shutdownRequested = false;
|
|
276
|
+
/** The `/bug` hint is shown at most once per session so error output stays readable. */
|
|
277
|
+
bugReportHintShown = false;
|
|
270
278
|
// Extension UI state
|
|
271
279
|
extensionSelector = undefined;
|
|
272
280
|
extensionInput = undefined;
|
|
@@ -322,6 +330,7 @@ export class InteractiveMode {
|
|
|
322
330
|
tuiMode,
|
|
323
331
|
showHardwareCursor: this.settingsManager.getShowHardwareCursor(),
|
|
324
332
|
logDirectory: getAgentDir(),
|
|
333
|
+
terminal: options.terminal,
|
|
325
334
|
onRightClickPaste: this.onRightClickPaste,
|
|
326
335
|
fullscreenCopyOnSelect: this.settingsManager.getFullscreenCopyOnSelect(),
|
|
327
336
|
});
|
|
@@ -819,6 +828,11 @@ export class InteractiveMode {
|
|
|
819
828
|
if (modelFallbackMessage) {
|
|
820
829
|
this.showWarning(modelFallbackMessage);
|
|
821
830
|
}
|
|
831
|
+
const crash = takeUnnotifiedCrash();
|
|
832
|
+
if (crash) {
|
|
833
|
+
const when = new Date(crash.timestamp).toLocaleString();
|
|
834
|
+
this.showWarning(`${APP_NAME} crashed on ${when} (${crash.message}). Run /bug to report it; the crash details are attached automatically.`);
|
|
835
|
+
}
|
|
822
836
|
void this.maybeWarnAboutAnthropicSubscriptionAuth();
|
|
823
837
|
// Process initial messages
|
|
824
838
|
if (initialMessage) {
|
|
@@ -1535,10 +1549,38 @@ export class InteractiveMode {
|
|
|
1535
1549
|
async handleFatalRuntimeError(prefix, error) {
|
|
1536
1550
|
const message = error instanceof Error ? error.message : String(error);
|
|
1537
1551
|
this.showError(`${prefix}: ${message}`);
|
|
1552
|
+
if (this.recordCrash("fatal_error", error)) {
|
|
1553
|
+
this.chatContainer.addChild(new Text(theme.fg("muted", this.crashReportInstructions()), this.outputPad, 0));
|
|
1554
|
+
}
|
|
1538
1555
|
stopThemeWatcher();
|
|
1539
1556
|
this.stop("transcript");
|
|
1540
1557
|
process.exit(1);
|
|
1541
1558
|
}
|
|
1559
|
+
/** Persist a crash so the next start can point the user at `/bug`. Returns false when nothing was written. */
|
|
1560
|
+
recordCrash(kind, error) {
|
|
1561
|
+
try {
|
|
1562
|
+
return (recordCrash({
|
|
1563
|
+
kind,
|
|
1564
|
+
error,
|
|
1565
|
+
sessionFile: this.session.sessionFile,
|
|
1566
|
+
cwd: this.session.sessionManager.getCwd(),
|
|
1567
|
+
}) !== undefined);
|
|
1568
|
+
}
|
|
1569
|
+
catch {
|
|
1570
|
+
return false;
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
crashReportInstructions() {
|
|
1574
|
+
const resume = this.session.sessionFile ? `run \`${APP_NAME} -r\` to resume the session, then` : "start pi and";
|
|
1575
|
+
return `To report this crash: ${resume} run /bug. The crash details are attached automatically.`;
|
|
1576
|
+
}
|
|
1577
|
+
suggestBugReport() {
|
|
1578
|
+
if (this.bugReportHintShown)
|
|
1579
|
+
return;
|
|
1580
|
+
this.bugReportHintShown = true;
|
|
1581
|
+
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));
|
|
1582
|
+
this.ui.requestRender();
|
|
1583
|
+
}
|
|
1542
1584
|
renderCurrentSessionState() {
|
|
1543
1585
|
this.loadedResourcesContainer.clear();
|
|
1544
1586
|
this.chatContainer.clear();
|
|
@@ -1640,7 +1682,7 @@ export class InteractiveMode {
|
|
|
1640
1682
|
this.activeWorkingIndicatorEmbedded = false;
|
|
1641
1683
|
this.statusContainer.clear();
|
|
1642
1684
|
this.setEditorWorkingStatusIndicator(undefined);
|
|
1643
|
-
if (
|
|
1685
|
+
if (this.setEditorWorkingStatusIndicator(indicator)) {
|
|
1644
1686
|
this.activeWorkingIndicatorEmbedded = true;
|
|
1645
1687
|
return;
|
|
1646
1688
|
}
|
|
@@ -1651,7 +1693,7 @@ export class InteractiveMode {
|
|
|
1651
1693
|
return;
|
|
1652
1694
|
}
|
|
1653
1695
|
const clearedIndicator = this.activeStatusIndicator;
|
|
1654
|
-
const clearedIndicatorWasEmbedded =
|
|
1696
|
+
const clearedIndicatorWasEmbedded = this.activeWorkingIndicatorEmbedded;
|
|
1655
1697
|
clearedIndicator?.dispose();
|
|
1656
1698
|
this.activeStatusIndicator = undefined;
|
|
1657
1699
|
this.activeWorkingIndicatorEmbedded = false;
|
|
@@ -2140,7 +2182,7 @@ export class InteractiveMode {
|
|
|
2140
2182
|
this.editor = this.defaultEditor;
|
|
2141
2183
|
}
|
|
2142
2184
|
this.editorContainer.addChild(this.editor);
|
|
2143
|
-
if (this.activeStatusIndicator
|
|
2185
|
+
if (this.activeStatusIndicator) {
|
|
2144
2186
|
this.statusContainer.clear();
|
|
2145
2187
|
this.activeWorkingIndicatorEmbedded = this.setEditorWorkingStatusIndicator(this.activeStatusIndicator);
|
|
2146
2188
|
if (!this.activeWorkingIndicatorEmbedded) {
|
|
@@ -2411,6 +2453,12 @@ export class InteractiveMode {
|
|
|
2411
2453
|
this.editor.setText("");
|
|
2412
2454
|
return;
|
|
2413
2455
|
}
|
|
2456
|
+
if (text === "/bug" || text.startsWith("/bug ")) {
|
|
2457
|
+
const hint = text.slice("/bug".length).trim();
|
|
2458
|
+
this.editor.setText("");
|
|
2459
|
+
await this.handleBugCommand(hint ? hint : undefined);
|
|
2460
|
+
return;
|
|
2461
|
+
}
|
|
2414
2462
|
if (text === "/copy") {
|
|
2415
2463
|
await this.handleCopyCommand();
|
|
2416
2464
|
this.editor.setText("");
|
|
@@ -2602,6 +2650,10 @@ export class InteractiveMode {
|
|
|
2602
2650
|
this.addCustomEntryToChat(event.entry);
|
|
2603
2651
|
this.ui.requestRender();
|
|
2604
2652
|
}
|
|
2653
|
+
else if (event.entry.type === "usage" && event.entry.kind === "cache_warm") {
|
|
2654
|
+
this.addCacheWarmingUsage(event.entry);
|
|
2655
|
+
this.ui.requestRender();
|
|
2656
|
+
}
|
|
2605
2657
|
break;
|
|
2606
2658
|
case "session_info_changed":
|
|
2607
2659
|
this.updateTerminalTitle();
|
|
@@ -2682,13 +2734,15 @@ export class InteractiveMode {
|
|
|
2682
2734
|
});
|
|
2683
2735
|
}
|
|
2684
2736
|
this.pendingTools.clear();
|
|
2737
|
+
if (this.streamingMessage.stopReason === "error")
|
|
2738
|
+
this.suggestBugReport();
|
|
2685
2739
|
}
|
|
2686
2740
|
else {
|
|
2687
2741
|
// Args are now complete - trigger diff computation for edit tools
|
|
2688
2742
|
for (const [, component] of this.pendingTools.entries()) {
|
|
2689
2743
|
component.setArgsComplete();
|
|
2690
2744
|
}
|
|
2691
|
-
this.
|
|
2745
|
+
this.maybeShowThinkingDropNotice(this.streamingMessage);
|
|
2692
2746
|
this.maybeShowCacheMissNotice(this.streamingMessage);
|
|
2693
2747
|
}
|
|
2694
2748
|
this.streamingComponent = undefined;
|
|
@@ -2829,6 +2883,7 @@ export class InteractiveMode {
|
|
|
2829
2883
|
// Show error only on final failure (success shows normal response)
|
|
2830
2884
|
if (!event.success) {
|
|
2831
2885
|
this.showError(`Retry failed after ${event.attempt} attempts: ${event.finalError || "Unknown error"}`);
|
|
2886
|
+
this.suggestBugReport();
|
|
2832
2887
|
}
|
|
2833
2888
|
this.ui.requestRender();
|
|
2834
2889
|
break;
|
|
@@ -2955,6 +3010,8 @@ export class InteractiveMode {
|
|
|
2955
3010
|
this.chatContainer.addChild(component);
|
|
2956
3011
|
break;
|
|
2957
3012
|
}
|
|
3013
|
+
case "system":
|
|
3014
|
+
break;
|
|
2958
3015
|
case "user": {
|
|
2959
3016
|
const textContent = this.getUserMessageText(message);
|
|
2960
3017
|
if (textContent) {
|
|
@@ -3001,8 +3058,8 @@ export class InteractiveMode {
|
|
|
3001
3058
|
renderSessionItems(items, options = {}) {
|
|
3002
3059
|
this.pendingTools.clear();
|
|
3003
3060
|
const renderedPendingTools = new Map();
|
|
3004
|
-
// Cache
|
|
3005
|
-
//
|
|
3061
|
+
// Cache misses are not persisted, unlike successful cache-warming usage.
|
|
3062
|
+
// Re-derive them and inject them after the assistant messages that paid for them.
|
|
3006
3063
|
const cacheMisses = this.settingsManager.getShowCacheMissNotices()
|
|
3007
3064
|
? collectCacheMisses(this.sessionManager.getEntries(), this.session.modelRuntime)
|
|
3008
3065
|
: new Map();
|
|
@@ -3015,6 +3072,10 @@ export class InteractiveMode {
|
|
|
3015
3072
|
this.addCustomEntryToChat(item);
|
|
3016
3073
|
continue;
|
|
3017
3074
|
}
|
|
3075
|
+
if (isUsageSessionEntry(item)) {
|
|
3076
|
+
this.addCacheWarmingUsage(item);
|
|
3077
|
+
continue;
|
|
3078
|
+
}
|
|
3018
3079
|
if (isCompactionCostNotice(item)) {
|
|
3019
3080
|
this.addCompactionCostNotice(item);
|
|
3020
3081
|
continue;
|
|
@@ -3052,7 +3113,6 @@ export class InteractiveMode {
|
|
|
3052
3113
|
}
|
|
3053
3114
|
}
|
|
3054
3115
|
if (message.stopReason !== "aborted" && message.stopReason !== "error") {
|
|
3055
|
-
this.maybeShowAssistantDiagnostics(message);
|
|
3056
3116
|
const miss = cacheMisses.get(message);
|
|
3057
3117
|
if (miss)
|
|
3058
3118
|
this.addCacheMissNotice(miss);
|
|
@@ -3084,7 +3144,7 @@ export class InteractiveMode {
|
|
|
3084
3144
|
*/
|
|
3085
3145
|
renderSessionEntries(entries, options = {}) {
|
|
3086
3146
|
const items = entries.flatMap((entry) => {
|
|
3087
|
-
if (entry.type === "custom") {
|
|
3147
|
+
if (entry.type === "custom" || (entry.type === "usage" && entry.kind === "cache_warm")) {
|
|
3088
3148
|
return [entry];
|
|
3089
3149
|
}
|
|
3090
3150
|
const messages = sessionEntryToContextMessages(entry);
|
|
@@ -3095,6 +3155,12 @@ export class InteractiveMode {
|
|
|
3095
3155
|
});
|
|
3096
3156
|
this.renderSessionItems(items, options);
|
|
3097
3157
|
}
|
|
3158
|
+
addCacheWarmingUsage(entry) {
|
|
3159
|
+
if (!this.settingsManager.getShowCacheMissNotices())
|
|
3160
|
+
return;
|
|
3161
|
+
this.chatContainer.addChild(new Spacer(1));
|
|
3162
|
+
this.chatContainer.addChild(new Text(theme.fg("dim", formatCacheWarmingUsage(entry)), 1, 0));
|
|
3163
|
+
}
|
|
3098
3164
|
/**
|
|
3099
3165
|
* Render billing usage for a compaction or branch summary. The notice is derived
|
|
3100
3166
|
* from persisted summary usage and is not stored as a separate session entry.
|
|
@@ -3109,31 +3175,42 @@ export class InteractiveMode {
|
|
|
3109
3175
|
this.chatContainer.addChild(new Spacer(1));
|
|
3110
3176
|
this.chatContainer.addChild(new Text(theme.fg("warning", `${label}: ${formatTokens(tokens)} tokens billed${cost}`), 1, 0));
|
|
3111
3177
|
}
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
return;
|
|
3178
|
+
static countDroppedThinkingBlocks(message) {
|
|
3179
|
+
let count = 0;
|
|
3115
3180
|
for (const diagnostic of message.diagnostics ?? []) {
|
|
3116
3181
|
if (diagnostic.type !== "anthropic_input_transformations")
|
|
3117
3182
|
continue;
|
|
3118
3183
|
const transformations = diagnostic.details?.transformations;
|
|
3119
3184
|
if (!Array.isArray(transformations))
|
|
3120
3185
|
continue;
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3186
|
+
count += transformations.filter((transformation) => typeof transformation === "object" &&
|
|
3187
|
+
transformation !== null &&
|
|
3188
|
+
transformation.type === "thinking_dropped").length;
|
|
3189
|
+
}
|
|
3190
|
+
return count;
|
|
3191
|
+
}
|
|
3192
|
+
maybeShowThinkingDropNotice(message) {
|
|
3193
|
+
if (!this.settingsManager.getShowCacheMissNotices())
|
|
3194
|
+
return;
|
|
3195
|
+
const droppedCount = InteractiveMode.countDroppedThinkingBlocks(message);
|
|
3196
|
+
if (droppedCount === 0)
|
|
3197
|
+
return;
|
|
3198
|
+
let previousDroppedCount = 0;
|
|
3199
|
+
// message_end reaches the UI before the current message is persisted,
|
|
3200
|
+
// so the branch's last assistant message is the previous response.
|
|
3201
|
+
const branch = this.sessionManager.getBranch();
|
|
3202
|
+
for (let i = branch.length - 1; i >= 0; i--) {
|
|
3203
|
+
const entry = branch[i];
|
|
3204
|
+
if (entry.type === "message" && entry.message.role === "assistant") {
|
|
3205
|
+
previousDroppedCount = InteractiveMode.countDroppedThinkingBlocks(entry.message);
|
|
3206
|
+
break;
|
|
3207
|
+
}
|
|
3136
3208
|
}
|
|
3209
|
+
if (droppedCount <= previousDroppedCount)
|
|
3210
|
+
return;
|
|
3211
|
+
const noun = droppedCount === 1 ? "thinking block" : "thinking blocks";
|
|
3212
|
+
this.chatContainer.addChild(new Spacer(1));
|
|
3213
|
+
this.chatContainer.addChild(new Text(theme.fg("warning", `Anthropic dropped ${droppedCount} ${noun} (details in session)`), 1, 0));
|
|
3137
3214
|
}
|
|
3138
3215
|
/**
|
|
3139
3216
|
* Show a transcript notice when a completed assistant message paid for a
|
|
@@ -3301,6 +3378,9 @@ export class InteractiveMode {
|
|
|
3301
3378
|
catch { }
|
|
3302
3379
|
console.error(`${APP_NAME} exiting due to uncaughtException:`);
|
|
3303
3380
|
console.error(error);
|
|
3381
|
+
if (this.recordCrash("uncaught_exception", error)) {
|
|
3382
|
+
console.error(`\n${this.crashReportInstructions()}`);
|
|
3383
|
+
}
|
|
3304
3384
|
process.exit(1);
|
|
3305
3385
|
}
|
|
3306
3386
|
/**
|
|
@@ -3432,9 +3512,7 @@ export class InteractiveMode {
|
|
|
3432
3512
|
const level = this.session.thinkingLevel || "off";
|
|
3433
3513
|
this.editor.borderColor = theme.getThinkingBorderColor(level);
|
|
3434
3514
|
}
|
|
3435
|
-
|
|
3436
|
-
this.activeStatusIndicator.invalidate();
|
|
3437
|
-
}
|
|
3515
|
+
this.activeStatusIndicator?.invalidate();
|
|
3438
3516
|
this.ui.requestRender();
|
|
3439
3517
|
}
|
|
3440
3518
|
cycleThinkingLevel() {
|
|
@@ -3628,7 +3706,7 @@ export class InteractiveMode {
|
|
|
3628
3706
|
if (allQueued.length === 0) {
|
|
3629
3707
|
this.updatePendingMessagesDisplay();
|
|
3630
3708
|
if (options?.abort) {
|
|
3631
|
-
this.
|
|
3709
|
+
void this.session.abort();
|
|
3632
3710
|
}
|
|
3633
3711
|
return 0;
|
|
3634
3712
|
}
|
|
@@ -3638,7 +3716,7 @@ export class InteractiveMode {
|
|
|
3638
3716
|
this.editor.setText(combinedText);
|
|
3639
3717
|
this.updatePendingMessagesDisplay();
|
|
3640
3718
|
if (options?.abort) {
|
|
3641
|
-
this.
|
|
3719
|
+
void this.session.abort();
|
|
3642
3720
|
}
|
|
3643
3721
|
return allQueued.length;
|
|
3644
3722
|
}
|
|
@@ -3792,6 +3870,7 @@ export class InteractiveMode {
|
|
|
3792
3870
|
followUpMode: this.session.followUpMode,
|
|
3793
3871
|
transport: this.settingsManager.getTransport(),
|
|
3794
3872
|
httpIdleTimeoutMs: this.settingsManager.getHttpIdleTimeoutMs(),
|
|
3873
|
+
cacheWarmingMode: this.settingsManager.getCacheWarmingMode(),
|
|
3795
3874
|
thinkingLevel: this.settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL,
|
|
3796
3875
|
availableThinkingLevels: [...THINKING_LEVEL_OPTIONS],
|
|
3797
3876
|
modelThinkingLevels: this.settingsManager.getAllModelThinkingLevels(),
|
|
@@ -3864,6 +3943,10 @@ export class InteractiveMode {
|
|
|
3864
3943
|
configureHttpDispatcher(timeoutMs);
|
|
3865
3944
|
this.showStatus(`HTTP idle timeout: ${formatHttpIdleTimeoutMs(timeoutMs)}`);
|
|
3866
3945
|
},
|
|
3946
|
+
onCacheWarmingModeChange: (mode) => {
|
|
3947
|
+
this.session.setCacheWarmingMode(mode);
|
|
3948
|
+
this.showStatus(`Cache warming: ${mode}`);
|
|
3949
|
+
},
|
|
3867
3950
|
onModelThinkingLevelChange: (provider, modelId, level) => {
|
|
3868
3951
|
this.settingsManager.setModelThinkingLevel(provider, modelId, level);
|
|
3869
3952
|
// If the override is for the current model, apply it to the session too
|
|
@@ -4415,6 +4498,11 @@ export class InteractiveMode {
|
|
|
4415
4498
|
this.restoreQueuedMessagesToEditor();
|
|
4416
4499
|
await this.session.abort();
|
|
4417
4500
|
}
|
|
4501
|
+
// Recheck after the dialogs and streaming abort, before replacing another operation's UI.
|
|
4502
|
+
if (this.session.isCompacting) {
|
|
4503
|
+
this.showError("Wait for the current compaction or tree navigation to finish before navigating the session tree.");
|
|
4504
|
+
return;
|
|
4505
|
+
}
|
|
4418
4506
|
// Set up escape handler and status indicator if summarizing
|
|
4419
4507
|
let showingSummaryIndicator = false;
|
|
4420
4508
|
const originalOnEscape = this.defaultEditor.onEscape;
|
|
@@ -4485,9 +4573,9 @@ export class InteractiveMode {
|
|
|
4485
4573
|
}
|
|
4486
4574
|
showSessionSelector() {
|
|
4487
4575
|
this.showSelector((done) => {
|
|
4488
|
-
const selector = new SessionSelectorComponent((onProgress) => SessionManager.list(this.sessionManager.getCwd(), this.sessionManager.getSessionDir(), onProgress), (onProgress) => this.sessionManager.usesDefaultSessionDir()
|
|
4489
|
-
? SessionManager.listAll(onProgress)
|
|
4490
|
-
: SessionManager.listAll(this.sessionManager.getSessionDir(), onProgress), async (sessionPath) => {
|
|
4576
|
+
const selector = new SessionSelectorComponent((onProgress, signal) => SessionManager.list(this.sessionManager.getCwd(), this.sessionManager.getSessionDir(), onProgress, signal), (onProgress, signal) => this.sessionManager.usesDefaultSessionDir()
|
|
4577
|
+
? SessionManager.listAll(onProgress, signal)
|
|
4578
|
+
: SessionManager.listAll(this.sessionManager.getSessionDir(), onProgress, signal), async (sessionPath) => {
|
|
4491
4579
|
done();
|
|
4492
4580
|
await this.handleResumeSession(sessionPath);
|
|
4493
4581
|
}, () => {
|
|
@@ -4750,67 +4838,89 @@ export class InteractiveMode {
|
|
|
4750
4838
|
}
|
|
4751
4839
|
async completeProviderAuthentication(providerId, providerName, authType, previousModel) {
|
|
4752
4840
|
const actionLabel = authType === "oauth" ? `Logged in to ${providerName}` : `Saved API key for ${providerName}`;
|
|
4753
|
-
|
|
4754
|
-
|
|
4755
|
-
|
|
4756
|
-
|
|
4757
|
-
|
|
4758
|
-
|
|
4759
|
-
|
|
4760
|
-
|
|
4761
|
-
|
|
4762
|
-
|
|
4763
|
-
|
|
4764
|
-
|
|
4765
|
-
|
|
4766
|
-
|
|
4767
|
-
|
|
4768
|
-
|
|
4769
|
-
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
|
|
4841
|
+
const session = this.session;
|
|
4842
|
+
// Dynamic catalogs may be empty until the first authenticated network refresh.
|
|
4843
|
+
const deferSelection = isUnknownModel(previousModel) &&
|
|
4844
|
+
hasDefaultModelProvider(providerId) &&
|
|
4845
|
+
!session.modelRuntime
|
|
4846
|
+
.getAvailableSnapshot()
|
|
4847
|
+
.some((model) => model.provider === providerId && model.id === defaultModelPerProvider[providerId]);
|
|
4848
|
+
const finishAuthentication = async () => {
|
|
4849
|
+
let selectedModel;
|
|
4850
|
+
let selectionError;
|
|
4851
|
+
if (isUnknownModel(previousModel)) {
|
|
4852
|
+
const availableModels = this.session.modelRuntime.getAvailableSnapshot();
|
|
4853
|
+
const providerModels = availableModels.filter((model) => model.provider === providerId);
|
|
4854
|
+
// Matches LLAMA_PROVIDER_ID from extensions/llama/provider.ts; kept inline to avoid coupling interactive mode to the built-in extension.
|
|
4855
|
+
if (providerId === "llama.cpp") {
|
|
4856
|
+
selectionError = llamaCppPostLoginGuidance(actionLabel, providerModels.length);
|
|
4857
|
+
}
|
|
4858
|
+
else if (!hasDefaultModelProvider(providerId)) {
|
|
4859
|
+
selectionError = `${actionLabel}, but no default model is configured for provider "${providerId}". Use /model to select a model.`;
|
|
4860
|
+
}
|
|
4861
|
+
else if (providerModels.length === 0) {
|
|
4862
|
+
selectionError = `${actionLabel}, but no models are available for that provider. Use /model to select a model.`;
|
|
4773
4863
|
}
|
|
4774
4864
|
else {
|
|
4775
|
-
|
|
4776
|
-
|
|
4865
|
+
const defaultModelId = defaultModelPerProvider[providerId];
|
|
4866
|
+
// Radius catalogs vary by account; prefer balanced, then use catalog order.
|
|
4867
|
+
selectedModel =
|
|
4868
|
+
providerModels.find((model) => model.id === defaultModelId) ??
|
|
4869
|
+
(providerId === "radius" ? providerModels[0] : undefined);
|
|
4870
|
+
if (!selectedModel) {
|
|
4871
|
+
selectionError = `${actionLabel}, but its default model "${defaultModelId}" is not available. Use /model to select a model.`;
|
|
4777
4872
|
}
|
|
4778
|
-
|
|
4779
|
-
|
|
4780
|
-
|
|
4781
|
-
|
|
4873
|
+
else {
|
|
4874
|
+
try {
|
|
4875
|
+
await this.session.setModel(selectedModel, { persist: true });
|
|
4876
|
+
}
|
|
4877
|
+
catch (error) {
|
|
4878
|
+
selectedModel = undefined;
|
|
4879
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
4880
|
+
selectionError = `${actionLabel}, but selecting its default model failed: ${errorMessage}. Use /model to select a model.`;
|
|
4881
|
+
}
|
|
4782
4882
|
}
|
|
4783
4883
|
}
|
|
4784
4884
|
}
|
|
4785
|
-
|
|
4786
|
-
|
|
4787
|
-
|
|
4788
|
-
|
|
4789
|
-
|
|
4790
|
-
|
|
4791
|
-
|
|
4792
|
-
this.checkDaxnutsEasterEgg(selectedModel);
|
|
4793
|
-
}
|
|
4794
|
-
else {
|
|
4795
|
-
this.showStatus(`${actionLabel}. Credentials saved to ${getAuthPath()}`);
|
|
4796
|
-
if (selectionError) {
|
|
4797
|
-
this.showError(selectionError);
|
|
4885
|
+
await this.updateAvailableProviderCount();
|
|
4886
|
+
this.footer.invalidate();
|
|
4887
|
+
this.updateEditorBorderColor();
|
|
4888
|
+
if (selectedModel) {
|
|
4889
|
+
this.showStatus(`${actionLabel}. Selected ${selectedModel.id}. Credentials saved to ${getAuthPath()}`);
|
|
4890
|
+
void this.maybeWarnAboutAnthropicSubscriptionAuth(selectedModel);
|
|
4891
|
+
this.checkDaxnutsEasterEgg(selectedModel);
|
|
4798
4892
|
}
|
|
4799
4893
|
else {
|
|
4800
|
-
|
|
4894
|
+
this.showStatus(`${actionLabel}. Credentials saved to ${getAuthPath()}`);
|
|
4895
|
+
if (selectionError) {
|
|
4896
|
+
this.showError(selectionError);
|
|
4897
|
+
}
|
|
4898
|
+
else {
|
|
4899
|
+
void this.maybeWarnAboutAnthropicSubscriptionAuth();
|
|
4900
|
+
}
|
|
4801
4901
|
}
|
|
4902
|
+
};
|
|
4903
|
+
if (deferSelection) {
|
|
4904
|
+
this.showStatus(`${actionLabel}. Credentials saved to ${getAuthPath()}. Refreshing model catalog…`);
|
|
4905
|
+
}
|
|
4906
|
+
else {
|
|
4907
|
+
await finishAuthentication();
|
|
4802
4908
|
}
|
|
4803
4909
|
const controller = new AbortController();
|
|
4804
4910
|
const timeout = setTimeout(() => controller.abort(), 15_000);
|
|
4805
|
-
void
|
|
4911
|
+
void session.modelRuntime
|
|
4806
4912
|
.refresh({ providers: [providerId], signal: controller.signal })
|
|
4807
|
-
.then((result) => {
|
|
4913
|
+
.then(async (result) => {
|
|
4808
4914
|
if (result.aborted) {
|
|
4809
4915
|
this.showWarning(`${actionLabel}, but its model catalog refresh timed out; using cached models.`);
|
|
4810
4916
|
}
|
|
4811
4917
|
else if (result.errors.size > 0) {
|
|
4812
4918
|
this.showWarning(`${actionLabel}, but its model catalog could not be refreshed; using cached models.`);
|
|
4813
4919
|
}
|
|
4920
|
+
// Do not replace a model or session selected while the refresh was running.
|
|
4921
|
+
if (deferSelection && this.session === session && session.model === previousModel) {
|
|
4922
|
+
await finishAuthentication();
|
|
4923
|
+
}
|
|
4814
4924
|
this.updateAvailableProviderCount();
|
|
4815
4925
|
this.footer.invalidate();
|
|
4816
4926
|
this.ui.requestRender();
|
|
@@ -5152,6 +5262,16 @@ export class InteractiveMode {
|
|
|
5152
5262
|
showError: (message) => this.showError(message),
|
|
5153
5263
|
});
|
|
5154
5264
|
}
|
|
5265
|
+
async handleBugCommand(hint) {
|
|
5266
|
+
await reportBug({
|
|
5267
|
+
session: this.session,
|
|
5268
|
+
ui: this.ui,
|
|
5269
|
+
editorContainer: this.editorContainer,
|
|
5270
|
+
editor: this.editor,
|
|
5271
|
+
showStatus: (message) => this.showStatus(message),
|
|
5272
|
+
showError: (message) => this.showError(message),
|
|
5273
|
+
}, hint);
|
|
5274
|
+
}
|
|
5155
5275
|
async handleCopyCommand(options = {}) {
|
|
5156
5276
|
if (options.preferSelection &&
|
|
5157
5277
|
this.ui instanceof TuiAltScreen &&
|
|
@@ -5237,6 +5357,15 @@ export class InteractiveMode {
|
|
|
5237
5357
|
}
|
|
5238
5358
|
info += `${theme.fg("dim", "Output:")} ${stats.tokens.output.toLocaleString()}\n`;
|
|
5239
5359
|
info += `${theme.fg("dim", "Total:")} ${stats.tokens.total.toLocaleString()}\n`;
|
|
5360
|
+
const cacheWarmingStatus = this.session.cacheWarmingStatus;
|
|
5361
|
+
info += `\n${theme.bold("Cache Warming")}\n`;
|
|
5362
|
+
info += `${theme.fg("dim", "Mode:")} ${this.settingsManager.getCacheWarmingMode()}\n`;
|
|
5363
|
+
info += `${theme.fg("dim", "Status:")} ${cacheWarmingStatus ? formatCacheWarmingStatus(cacheWarmingStatus) : "Inactive (cache warming unavailable)"}\n`;
|
|
5364
|
+
const decision = cacheWarmingStatus?.decision;
|
|
5365
|
+
if (decision?.economicsAvailable) {
|
|
5366
|
+
info += `${theme.fg("dim", "Cache miss penalty:")} $${decision.missCost.toFixed(3)}\n`;
|
|
5367
|
+
info += `${theme.fg("dim", "Refresh cost:")} $${decision.warmCost.toFixed(3)}\n`;
|
|
5368
|
+
}
|
|
5240
5369
|
if (stats.cost > 0 || cacheWaste.missedTokens > 0) {
|
|
5241
5370
|
info += `\n${theme.bold("Cost")}\n`;
|
|
5242
5371
|
info += `${theme.fg("dim", "Total:")} $${stats.cost.toFixed(3)}`;
|
|
@@ -5367,7 +5496,7 @@ export class InteractiveMode {
|
|
|
5367
5496
|
| \`${expandTools}\` | Toggle tool output expansion |
|
|
5368
5497
|
| \`${toggleThinking}\` | Toggle thinking block visibility |
|
|
5369
5498
|
| \`${externalEditor}\` | Edit message in external editor |
|
|
5370
|
-
| \`${copyMessage}\` | Copy last assistant message |
|
|
5499
|
+
| \`${copyMessage}\` | Copy selection or last assistant message |
|
|
5371
5500
|
| \`${followUp}\` | Queue follow-up message |
|
|
5372
5501
|
| \`${dequeue}\` | Restore queued messages |
|
|
5373
5502
|
| \`${pasteImage}\` | Paste image or text from clipboard |
|
|
@@ -5463,12 +5592,19 @@ export class InteractiveMode {
|
|
|
5463
5592
|
async handleBashCommand(command, excludeFromContext = false) {
|
|
5464
5593
|
const extensionRunner = this.session.extensionRunner;
|
|
5465
5594
|
// Emit user_bash event to let extensions intercept
|
|
5466
|
-
|
|
5467
|
-
|
|
5468
|
-
|
|
5469
|
-
|
|
5470
|
-
|
|
5471
|
-
|
|
5595
|
+
let eventResult;
|
|
5596
|
+
try {
|
|
5597
|
+
eventResult = await extensionRunner.emitUserBash({
|
|
5598
|
+
type: "user_bash",
|
|
5599
|
+
command,
|
|
5600
|
+
excludeFromContext,
|
|
5601
|
+
cwd: this.sessionManager.getCwd(),
|
|
5602
|
+
});
|
|
5603
|
+
}
|
|
5604
|
+
catch {
|
|
5605
|
+
// The extension runner already reported the error. Do not fall back to local execution.
|
|
5606
|
+
return;
|
|
5607
|
+
}
|
|
5472
5608
|
// If extension returned a full result, use it directly
|
|
5473
5609
|
if (eventResult?.result) {
|
|
5474
5610
|
const result = eventResult.result;
|