@astralyn/pi 0.85.3 → 0.86.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +35 -0
- package/dist/bundle/chunks/anthropic-messages-R2LYJUDD.js +6 -0
- package/dist/bundle/chunks/azure-openai-responses-HS35BQV6.js +2 -0
- package/dist/bundle/chunks/bedrock-converse-stream.js +36 -32
- package/dist/bundle/chunks/{chunk-S2DJQQI2.js → chunk-2IO5GDBS.js} +10 -1
- package/dist/bundle/chunks/{chunk-7LO5Z4WE.js → chunk-I5IVW2WS.js} +1 -1
- package/dist/bundle/chunks/chunk-JI4WGISU.js +2 -0
- package/dist/bundle/chunks/chunk-LPQCB2VJ.js +44 -0
- package/dist/bundle/chunks/chunk-M2YWW37K.js +2 -0
- package/dist/bundle/chunks/{chunk-LB4P77SH.js → chunk-MSHHFVMD.js} +776 -762
- package/dist/bundle/chunks/chunk-NW5FIDD7.js +11 -0
- package/dist/bundle/chunks/chunk-PJVFYVHE.js +42 -0
- package/dist/bundle/chunks/github-copilot.js +1 -1
- package/dist/bundle/chunks/google-generative-ai-NOVAJBFC.js +2 -0
- package/dist/bundle/chunks/google-vertex-4VHCZJV5.js +2 -0
- package/dist/bundle/chunks/https-proxy-agent-JOOPB4RE.js +16 -0
- package/dist/bundle/chunks/jiti-loader-BFSSLU7G.js +21 -0
- package/dist/bundle/chunks/jiti-static-loader-CLT3YR3B.js +2 -0
- package/dist/bundle/chunks/mistral-conversations-WC6A2WCJ.js +5 -0
- package/dist/bundle/chunks/{node-G4XOIDPH.js → node-CXWYTK2I.js} +1 -1
- package/dist/bundle/chunks/openai-codex-responses-XCDG75W2.js +10 -0
- package/dist/bundle/chunks/openai-completions-WJIA7NEB.js +7 -0
- package/dist/bundle/chunks/openai-responses-UT6XFKC7.js +2 -0
- package/dist/bundle/chunks/{pi-messages-PE6B42TG.js → pi-messages-MQMPIPNC.js} +1 -1
- package/dist/bundle/chunks/virtual-modules-B4BILEXT.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 +13 -11
- package/dist/cli/session-picker.js.map +1 -1
- package/dist/config.js +1 -1
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session.d.ts +56 -14
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +305 -176
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/bug-report-upload.d.ts +12 -0
- package/dist/core/bug-report-upload.d.ts.map +1 -0
- package/dist/core/bug-report-upload.js +22 -0
- package/dist/core/bug-report-upload.js.map +1 -0
- package/dist/core/bug-report.d.ts +176 -0
- package/dist/core/bug-report.d.ts.map +1 -0
- package/dist/core/bug-report.js +292 -0
- package/dist/core/bug-report.js.map +1 -0
- package/dist/core/cache-stats.d.ts.map +1 -1
- package/dist/core/cache-stats.js +12 -1
- package/dist/core/cache-stats.js.map +1 -1
- package/dist/core/cache-warmer.d.ts +102 -0
- package/dist/core/cache-warmer.d.ts.map +1 -0
- package/dist/core/cache-warmer.js +333 -0
- package/dist/core/cache-warmer.js.map +1 -0
- package/dist/core/compaction/branch-summarization.js +2 -2
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +14 -9
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +30 -23
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/compaction/settings.d.ts +17 -20
- package/dist/core/compaction/settings.d.ts.map +1 -1
- package/dist/core/compaction/settings.js +19 -26
- package/dist/core/compaction/settings.js.map +1 -1
- package/dist/core/context-snapshot.d.ts +16 -5
- package/dist/core/context-snapshot.d.ts.map +1 -1
- package/dist/core/context-snapshot.js +20 -10
- package/dist/core/context-snapshot.js.map +1 -1
- package/dist/core/crash-log.d.ts +22 -0
- package/dist/core/crash-log.d.ts.map +1 -0
- package/dist/core/crash-log.js +71 -0
- package/dist/core/crash-log.js.map +1 -0
- package/dist/core/experimental.d.ts +0 -4
- package/dist/core/experimental.d.ts.map +1 -1
- package/dist/core/experimental.js +0 -4
- package/dist/core/experimental.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/jiti-loader.d.ts +2 -0
- package/dist/core/extensions/jiti-loader.d.ts.map +1 -0
- package/dist/core/extensions/jiti-loader.js +4 -0
- package/dist/core/extensions/jiti-loader.js.map +1 -0
- package/dist/core/extensions/jiti-static-loader.d.ts +2 -0
- package/dist/core/extensions/jiti-static-loader.d.ts.map +1 -0
- package/dist/core/extensions/jiti-static-loader.js +4 -0
- package/dist/core/extensions/jiti-static-loader.js.map +1 -0
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +38 -51
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +10 -7
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +85 -67
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +60 -50
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/extensions/virtual-modules.d.ts +3 -0
- package/dist/core/extensions/virtual-modules.d.ts.map +1 -0
- package/dist/core/extensions/virtual-modules.js +39 -0
- package/dist/core/extensions/virtual-modules.js.map +1 -0
- package/dist/core/extensions/wrapper.d.ts.map +1 -1
- package/dist/core/extensions/wrapper.js +1 -20
- package/dist/core/extensions/wrapper.js.map +1 -1
- package/dist/core/index.d.ts +2 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/keybindings.d.ts +1 -1
- package/dist/core/keybindings.js +1 -1
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js +1 -0
- package/dist/core/messages.js.map +1 -1
- package/dist/core/model-config.d.ts +101 -20
- package/dist/core/model-config.d.ts.map +1 -1
- package/dist/core/model-config.js +25 -18
- package/dist/core/model-config.js.map +1 -1
- package/dist/core/model-registry.d.ts +5 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +8 -0
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.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 +46 -18
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-export.d.ts +6 -2
- package/dist/core/session-export.d.ts.map +1 -1
- package/dist/core/session-export.js +14 -13
- package/dist/core/session-export.js.map +1 -1
- package/dist/core/session-manager.d.ts +29 -6
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +159 -96
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +31 -4
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +65 -8
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +1 -0
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/system-prompt.d.ts +49 -6
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +121 -92
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts +2 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +6 -3
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +1 -2
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +1 -2
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/shell-execution.js +2 -2
- package/dist/core/tools/shell-execution.js.map +1 -1
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +1 -2
- package/dist/core/tools/write.js.map +1 -1
- package/dist/core/usage-totals.d.ts +1 -1
- package/dist/core/usage-totals.d.ts.map +1 -1
- package/dist/core/usage-totals.js +4 -1
- package/dist/core/usage-totals.js.map +1 -1
- package/dist/extensions/background/schema.d.ts +1 -1
- package/dist/extensions/btw/agent.d.ts.map +1 -1
- package/dist/extensions/btw/agent.js +3 -2
- package/dist/extensions/btw/agent.js.map +1 -1
- package/dist/extensions/llama/client.d.ts +2 -0
- package/dist/extensions/llama/client.d.ts.map +1 -1
- package/dist/extensions/llama/client.js +7 -3
- package/dist/extensions/llama/client.js.map +1 -1
- package/dist/extensions/llama/provider.d.ts.map +1 -1
- package/dist/extensions/llama/provider.js +20 -5
- package/dist/extensions/llama/provider.js.map +1 -1
- package/dist/extensions/provider/compat-fields.d.ts.map +1 -1
- package/dist/extensions/provider/compat-fields.js +5 -2
- package/dist/extensions/provider/compat-fields.js.map +1 -1
- package/dist/extensions/provider/ui/app.js +2 -2
- package/dist/extensions/provider/ui/app.js.map +1 -1
- package/dist/extensions/todo/schema.d.ts +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +13 -9
- package/dist/main.js.map +1 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +2 -2
- package/dist/migrations.js.map +1 -1
- package/dist/modes/interactive/bug-report.d.ts +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.js +1 -1
- package/dist/modes/interactive/chat-viewport.js.map +1 -1
- package/dist/modes/interactive/components/armin.d.ts.map +1 -1
- package/dist/modes/interactive/components/armin.js +0 -5
- package/dist/modes/interactive/components/armin.js.map +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts +0 -1
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +2 -3
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.js +12 -5
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.js +12 -5
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/countdown-timer.d.ts +6 -13
- package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -1
- package/dist/modes/interactive/components/countdown-timer.js +15 -51
- package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts +3 -3
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- package/dist/modes/interactive/components/extension-input.d.ts +2 -0
- package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-input.js +6 -0
- package/dist/modes/interactive/components/extension-input.js.map +1 -1
- package/dist/modes/interactive/components/extension-selector.d.ts +1 -2
- package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-selector.js +4 -2
- package/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts +5 -8
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +72 -95
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +3 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +11 -0
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.js +11 -4
- package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
- package/dist/modes/interactive/components/status-indicator.d.ts +2 -2
- package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -1
- package/dist/modes/interactive/components/status-indicator.js +7 -7
- package/dist/modes/interactive/components/status-indicator.js.map +1 -1
- package/dist/modes/interactive/components/tool-chrome.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-chrome.js +4 -1
- package/dist/modes/interactive/components/tool-chrome.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +4 -3
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts +1 -10
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js +4 -51
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +13 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +227 -91
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/session-share.d.ts +2 -0
- package/dist/modes/interactive/session-share.d.ts.map +1 -1
- package/dist/modes/interactive/session-share.js +8 -4
- package/dist/modes/interactive/session-share.js.map +1 -1
- package/dist/modes/interactive/tui-renderer.js +2 -2
- package/dist/modes/interactive/tui-renderer.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +2 -2
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/utils/clipboard-command.d.ts +7 -0
- package/dist/utils/clipboard-command.d.ts.map +1 -0
- package/dist/utils/clipboard-command.js +45 -0
- package/dist/utils/clipboard-command.js.map +1 -0
- package/dist/utils/clipboard-image.d.ts.map +1 -1
- package/dist/utils/clipboard-image.js +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/zip.d.ts +7 -0
- package/dist/utils/zip.d.ts.map +1 -0
- package/dist/utils/zip.js +60 -0
- package/dist/utils/zip.js.map +1 -0
- package/docs/compaction.md +32 -11
- package/docs/custom-provider.md +19 -8
- package/docs/environment-variables.md +1 -0
- package/docs/extensions.md +50 -34
- package/docs/models.md +38 -3
- package/docs/providers.md +1 -1
- package/docs/sdk.md +4 -2
- package/docs/session-format.md +63 -24
- package/docs/sessions.md +28 -1
- package/docs/settings.md +58 -4
- package/docs/termux.md +0 -1
- package/docs/tui.md +2 -0
- package/docs/usage.md +1 -0
- package/examples/extensions/README.md +0 -1
- package/examples/extensions/custom-provider-anthropic/index.ts +18 -12
- package/examples/extensions/custom-provider-gitlab-duo/index.ts +2 -2
- package/examples/extensions/prompt-customizer.ts +19 -67
- package/npm-shrinkwrap.json +275 -1028
- package/package.json +17 -23
- package/dist/bundle/chunks/anthropic-messages-IHRRITCV.js +0 -6
- package/dist/bundle/chunks/azure-openai-responses-QXBIDYXO.js +0 -2
- package/dist/bundle/chunks/chunk-JSJPY26N.js +0 -2
- package/dist/bundle/chunks/chunk-KI6LC764.js +0 -42
- package/dist/bundle/chunks/chunk-OWESLY5T.js +0 -11
- package/dist/bundle/chunks/chunk-RRBI7OUG.js +0 -50
- package/dist/bundle/chunks/chunk-YZJWMPUI.js +0 -2
- package/dist/bundle/chunks/google-generative-ai-NBOR3IQR.js +0 -2
- package/dist/bundle/chunks/google-vertex-VTHX3SUB.js +0 -2
- package/dist/bundle/chunks/https-proxy-agent-2VXB7436.js +0 -13
- package/dist/bundle/chunks/mistral-conversations-NO4ANAA5.js +0 -5
- package/dist/bundle/chunks/openai-codex-responses-5S3T3HMA.js +0 -10
- package/dist/bundle/chunks/openai-completions-CXRRTRWE.js +0 -7
- package/dist/bundle/chunks/openai-responses-CV3MH6VP.js +0 -2
- package/dist/utils/clipboard-native.d.ts +0 -11
- package/dist/utils/clipboard-native.d.ts.map +0 -1
- package/dist/utils/clipboard-native.js +0 -20
- package/dist/utils/clipboard-native.js.map +0 -1
- package/examples/extensions/kimi-deferred-tools.ts +0 -61
|
@@ -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";
|
|
@@ -38,6 +40,7 @@ import { getPiUserAgent } from "../../utils/pi-user-agent.js";
|
|
|
38
40
|
import { killTrackedDetachedChildren } from "../../utils/shell.js";
|
|
39
41
|
import { ensureTool } from "../../utils/tools-manager.js";
|
|
40
42
|
import { checkForNewPiVersion } from "../../utils/version-check.js";
|
|
43
|
+
import { reportBug } from "./bug-report.js";
|
|
41
44
|
import { createChatViewport } from "./chat-viewport.js";
|
|
42
45
|
import { ArminComponent } from "./components/armin.js";
|
|
43
46
|
import { AssistantMessageComponent } from "./components/assistant-message.js";
|
|
@@ -104,6 +107,9 @@ function isCustomSessionEntry(item) {
|
|
|
104
107
|
function isCompactionCostNotice(item) {
|
|
105
108
|
return "type" in item && item.type === "compaction_cost";
|
|
106
109
|
}
|
|
110
|
+
function isUsageSessionEntry(item) {
|
|
111
|
+
return "type" in item && item.type === "usage";
|
|
112
|
+
}
|
|
107
113
|
const DEAD_TERMINAL_ERROR_CODES = new Set(["EIO", "EPIPE", "ENOTCONN"]);
|
|
108
114
|
function isDeadTerminalError(error) {
|
|
109
115
|
if (!error || typeof error !== "object" || !("code" in error)) {
|
|
@@ -251,6 +257,8 @@ export class InteractiveMode {
|
|
|
251
257
|
this.compactionQueuedMessages = [];
|
|
252
258
|
// Shutdown state
|
|
253
259
|
this.shutdownRequested = false;
|
|
260
|
+
/** The `/bug` hint is shown at most once per session so error output stays readable. */
|
|
261
|
+
this.bugReportHintShown = false;
|
|
254
262
|
// Extension UI state
|
|
255
263
|
this.extensionSelector = undefined;
|
|
256
264
|
this.extensionInput = undefined;
|
|
@@ -292,6 +300,7 @@ export class InteractiveMode {
|
|
|
292
300
|
tuiMode,
|
|
293
301
|
showHardwareCursor: this.settingsManager.getShowHardwareCursor(),
|
|
294
302
|
logDirectory: getAgentDir(),
|
|
303
|
+
terminal: options.terminal,
|
|
295
304
|
onRightClickPaste: this.onRightClickPaste,
|
|
296
305
|
fullscreenCopyOnSelect: this.settingsManager.getFullscreenCopyOnSelect(),
|
|
297
306
|
});
|
|
@@ -772,6 +781,11 @@ export class InteractiveMode {
|
|
|
772
781
|
if (modelFallbackMessage) {
|
|
773
782
|
this.showWarning(modelFallbackMessage);
|
|
774
783
|
}
|
|
784
|
+
const crash = takeUnnotifiedCrash();
|
|
785
|
+
if (crash) {
|
|
786
|
+
const when = new Date(crash.timestamp).toLocaleString();
|
|
787
|
+
this.showWarning(`${APP_NAME} crashed on ${when} (${crash.message}). Run /bug to report it; the crash details are attached automatically.`);
|
|
788
|
+
}
|
|
775
789
|
void this.maybeWarnAboutAnthropicSubscriptionAuth();
|
|
776
790
|
// Process initial messages
|
|
777
791
|
if (initialMessage) {
|
|
@@ -1492,10 +1506,38 @@ export class InteractiveMode {
|
|
|
1492
1506
|
async handleFatalRuntimeError(prefix, error) {
|
|
1493
1507
|
const message = error instanceof Error ? error.message : String(error);
|
|
1494
1508
|
this.showError(`${prefix}: ${message}`);
|
|
1509
|
+
if (this.recordCrash("fatal_error", error)) {
|
|
1510
|
+
this.chatContainer.addChild(new Text(theme.fg("muted", this.crashReportInstructions()), this.outputPad, 0));
|
|
1511
|
+
}
|
|
1495
1512
|
stopThemeWatcher();
|
|
1496
1513
|
this.stop("transcript");
|
|
1497
1514
|
process.exit(1);
|
|
1498
1515
|
}
|
|
1516
|
+
/** Persist a crash so the next start can point the user at `/bug`. Returns false when nothing was written. */
|
|
1517
|
+
recordCrash(kind, error) {
|
|
1518
|
+
try {
|
|
1519
|
+
return (recordCrash({
|
|
1520
|
+
kind,
|
|
1521
|
+
error,
|
|
1522
|
+
sessionFile: this.session.sessionFile,
|
|
1523
|
+
cwd: this.session.sessionManager.getCwd(),
|
|
1524
|
+
}) !== undefined);
|
|
1525
|
+
}
|
|
1526
|
+
catch {
|
|
1527
|
+
return false;
|
|
1528
|
+
}
|
|
1529
|
+
}
|
|
1530
|
+
crashReportInstructions() {
|
|
1531
|
+
const resume = this.session.sessionFile ? `run \`${APP_NAME} -r\` to resume the session, then` : "start pi and";
|
|
1532
|
+
return `To report this crash: ${resume} run /bug. The crash details are attached automatically.`;
|
|
1533
|
+
}
|
|
1534
|
+
suggestBugReport() {
|
|
1535
|
+
if (this.bugReportHintShown)
|
|
1536
|
+
return;
|
|
1537
|
+
this.bugReportHintShown = true;
|
|
1538
|
+
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));
|
|
1539
|
+
this.ui.requestRender();
|
|
1540
|
+
}
|
|
1499
1541
|
disposeChatToolComponents() {
|
|
1500
1542
|
for (const child of this.chatContainer.children) {
|
|
1501
1543
|
const disposable = child;
|
|
@@ -1612,7 +1654,7 @@ export class InteractiveMode {
|
|
|
1612
1654
|
this.activeWorkingIndicatorEmbedded = false;
|
|
1613
1655
|
this.statusContainer.clear();
|
|
1614
1656
|
this.setEditorWorkingStatusIndicator(undefined);
|
|
1615
|
-
if (
|
|
1657
|
+
if (this.setEditorWorkingStatusIndicator(indicator)) {
|
|
1616
1658
|
this.activeWorkingIndicatorEmbedded = true;
|
|
1617
1659
|
return;
|
|
1618
1660
|
}
|
|
@@ -1623,7 +1665,7 @@ export class InteractiveMode {
|
|
|
1623
1665
|
return;
|
|
1624
1666
|
}
|
|
1625
1667
|
const clearedIndicator = this.activeStatusIndicator;
|
|
1626
|
-
const clearedIndicatorWasEmbedded =
|
|
1668
|
+
const clearedIndicatorWasEmbedded = this.activeWorkingIndicatorEmbedded;
|
|
1627
1669
|
clearedIndicator?.dispose();
|
|
1628
1670
|
this.activeStatusIndicator = undefined;
|
|
1629
1671
|
this.activeWorkingIndicatorEmbedded = false;
|
|
@@ -1974,7 +2016,7 @@ export class InteractiveMode {
|
|
|
1974
2016
|
}, {
|
|
1975
2017
|
tui: this.ui,
|
|
1976
2018
|
timeout: opts?.timeout,
|
|
1977
|
-
|
|
2019
|
+
description: opts?.description,
|
|
1978
2020
|
onToggleToolsExpanded: () => this.toggleToolOutputExpansion(),
|
|
1979
2021
|
});
|
|
1980
2022
|
this.disposeActiveSelector();
|
|
@@ -1999,9 +2041,9 @@ export class InteractiveMode {
|
|
|
1999
2041
|
* Show a confirmation dialog for extensions.
|
|
2000
2042
|
*/
|
|
2001
2043
|
async showExtensionConfirm(title, message, opts) {
|
|
2002
|
-
// The message is context, not a heading: render it as the selector's
|
|
2003
|
-
//
|
|
2004
|
-
const result = await this.showExtensionSelector(title, ["Yes", "No"], { ...opts,
|
|
2044
|
+
// The message is context, not a heading: render it as the selector's
|
|
2045
|
+
// description instead of folding it into the accent-bold title.
|
|
2046
|
+
const result = await this.showExtensionSelector(title, ["Yes", "No"], { ...opts, description: message });
|
|
2005
2047
|
return result === "Yes";
|
|
2006
2048
|
}
|
|
2007
2049
|
async promptForMissingSessionCwd(error) {
|
|
@@ -2139,7 +2181,7 @@ export class InteractiveMode {
|
|
|
2139
2181
|
this.editor = this.defaultEditor;
|
|
2140
2182
|
}
|
|
2141
2183
|
this.editorContainer.addChild(this.editor);
|
|
2142
|
-
if (this.activeStatusIndicator
|
|
2184
|
+
if (this.activeStatusIndicator) {
|
|
2143
2185
|
this.statusContainer.clear();
|
|
2144
2186
|
this.activeWorkingIndicatorEmbedded = this.setEditorWorkingStatusIndicator(this.activeStatusIndicator);
|
|
2145
2187
|
if (!this.activeWorkingIndicatorEmbedded) {
|
|
@@ -2464,6 +2506,12 @@ export class InteractiveMode {
|
|
|
2464
2506
|
this.editor.setText("");
|
|
2465
2507
|
return;
|
|
2466
2508
|
}
|
|
2509
|
+
if (text === "/bug" || text.startsWith("/bug ")) {
|
|
2510
|
+
const hint = text.slice("/bug".length).trim();
|
|
2511
|
+
this.editor.setText("");
|
|
2512
|
+
await this.handleBugCommand(hint ? hint : undefined);
|
|
2513
|
+
return;
|
|
2514
|
+
}
|
|
2467
2515
|
if (text === "/copy") {
|
|
2468
2516
|
await this.handleCopyCommand();
|
|
2469
2517
|
this.editor.setText("");
|
|
@@ -2654,6 +2702,10 @@ export class InteractiveMode {
|
|
|
2654
2702
|
this.addCustomEntryToChat(event.entry);
|
|
2655
2703
|
this.ui.requestRender();
|
|
2656
2704
|
}
|
|
2705
|
+
else if (event.entry.type === "usage" && event.entry.kind === "cache_warm") {
|
|
2706
|
+
this.addCacheWarmingUsage(event.entry);
|
|
2707
|
+
this.ui.requestRender();
|
|
2708
|
+
}
|
|
2657
2709
|
break;
|
|
2658
2710
|
case "session_info_changed":
|
|
2659
2711
|
this.updateTerminalTitle();
|
|
@@ -2730,13 +2782,15 @@ export class InteractiveMode {
|
|
|
2730
2782
|
});
|
|
2731
2783
|
}
|
|
2732
2784
|
this.pendingTools.clear();
|
|
2785
|
+
if (this.streamingMessage.stopReason === "error")
|
|
2786
|
+
this.suggestBugReport();
|
|
2733
2787
|
}
|
|
2734
2788
|
else {
|
|
2735
2789
|
// Args are now complete - trigger diff computation for edit tools
|
|
2736
2790
|
for (const [, component] of this.pendingTools.entries()) {
|
|
2737
2791
|
component.setArgsComplete();
|
|
2738
2792
|
}
|
|
2739
|
-
this.
|
|
2793
|
+
this.maybeShowThinkingDropNotice(this.streamingMessage);
|
|
2740
2794
|
this.maybeShowCacheMissNotice(this.streamingMessage);
|
|
2741
2795
|
}
|
|
2742
2796
|
this.streamingComponent = undefined;
|
|
@@ -2873,6 +2927,7 @@ export class InteractiveMode {
|
|
|
2873
2927
|
// Show error only on final failure (success shows normal response)
|
|
2874
2928
|
if (!event.success) {
|
|
2875
2929
|
this.showError(`Retry failed after ${event.attempt} attempts: ${event.finalError || "Unknown error"}`);
|
|
2930
|
+
this.suggestBugReport();
|
|
2876
2931
|
}
|
|
2877
2932
|
this.ui.requestRender();
|
|
2878
2933
|
break;
|
|
@@ -2999,6 +3054,8 @@ export class InteractiveMode {
|
|
|
2999
3054
|
this.chatContainer.addChild(component);
|
|
3000
3055
|
break;
|
|
3001
3056
|
}
|
|
3057
|
+
case "system":
|
|
3058
|
+
break;
|
|
3002
3059
|
case "user": {
|
|
3003
3060
|
const textContent = this.getUserMessageText(message);
|
|
3004
3061
|
if (textContent) {
|
|
@@ -3045,8 +3102,8 @@ export class InteractiveMode {
|
|
|
3045
3102
|
renderSessionItems(items, options = {}) {
|
|
3046
3103
|
this.clearPendingTools();
|
|
3047
3104
|
const renderedPendingTools = new Map();
|
|
3048
|
-
// Cache
|
|
3049
|
-
//
|
|
3105
|
+
// Cache misses are not persisted, unlike successful cache-warming usage.
|
|
3106
|
+
// Re-derive them and inject them after the assistant messages that paid for them.
|
|
3050
3107
|
const cacheMisses = this.settingsManager.getShowCacheMissNotices()
|
|
3051
3108
|
? collectCacheMisses(this.sessionManager.getEntries(), this.session.modelRuntime)
|
|
3052
3109
|
: new Map();
|
|
@@ -3059,6 +3116,10 @@ export class InteractiveMode {
|
|
|
3059
3116
|
this.addCustomEntryToChat(item);
|
|
3060
3117
|
continue;
|
|
3061
3118
|
}
|
|
3119
|
+
if (isUsageSessionEntry(item)) {
|
|
3120
|
+
this.addCacheWarmingUsage(item);
|
|
3121
|
+
continue;
|
|
3122
|
+
}
|
|
3062
3123
|
if (isCompactionCostNotice(item)) {
|
|
3063
3124
|
this.addCompactionCostNotice(item);
|
|
3064
3125
|
continue;
|
|
@@ -3092,7 +3153,6 @@ export class InteractiveMode {
|
|
|
3092
3153
|
}
|
|
3093
3154
|
}
|
|
3094
3155
|
if (message.stopReason !== "aborted" && message.stopReason !== "error") {
|
|
3095
|
-
this.maybeShowAssistantDiagnostics(message);
|
|
3096
3156
|
const miss = cacheMisses.get(message);
|
|
3097
3157
|
if (miss)
|
|
3098
3158
|
this.addCacheMissNotice(miss);
|
|
@@ -3124,7 +3184,7 @@ export class InteractiveMode {
|
|
|
3124
3184
|
*/
|
|
3125
3185
|
renderSessionEntries(entries, options = {}) {
|
|
3126
3186
|
const items = entries.flatMap((entry) => {
|
|
3127
|
-
if (entry.type === "custom") {
|
|
3187
|
+
if (entry.type === "custom" || (entry.type === "usage" && entry.kind === "cache_warm")) {
|
|
3128
3188
|
return [entry];
|
|
3129
3189
|
}
|
|
3130
3190
|
const messages = sessionEntryToContextMessages(entry);
|
|
@@ -3135,6 +3195,12 @@ export class InteractiveMode {
|
|
|
3135
3195
|
});
|
|
3136
3196
|
this.renderSessionItems(items, options);
|
|
3137
3197
|
}
|
|
3198
|
+
addCacheWarmingUsage(entry) {
|
|
3199
|
+
if (!this.settingsManager.getShowCacheMissNotices())
|
|
3200
|
+
return;
|
|
3201
|
+
this.chatContainer.addChild(new Spacer(1));
|
|
3202
|
+
this.chatContainer.addChild(new Text(theme.fg("dim", formatCacheWarmingUsage(entry)), 1, 0));
|
|
3203
|
+
}
|
|
3138
3204
|
/**
|
|
3139
3205
|
* Render billing usage for a compaction or branch summary. The notice is derived
|
|
3140
3206
|
* from persisted summary usage and is not stored as a separate session entry.
|
|
@@ -3149,31 +3215,42 @@ export class InteractiveMode {
|
|
|
3149
3215
|
this.chatContainer.addChild(new Spacer(1));
|
|
3150
3216
|
this.chatContainer.addChild(new Text(theme.fg("warning", `${label}: ${formatTokens(tokens)} tokens billed${cost}`), 1, 0));
|
|
3151
3217
|
}
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
return;
|
|
3218
|
+
static countDroppedThinkingBlocks(message) {
|
|
3219
|
+
let count = 0;
|
|
3155
3220
|
for (const diagnostic of message.diagnostics ?? []) {
|
|
3156
3221
|
if (diagnostic.type !== "anthropic_input_transformations")
|
|
3157
3222
|
continue;
|
|
3158
3223
|
const transformations = diagnostic.details?.transformations;
|
|
3159
3224
|
if (!Array.isArray(transformations))
|
|
3160
3225
|
continue;
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
const details = transformation;
|
|
3165
|
-
if (details.type !== "thinking_dropped")
|
|
3166
|
-
return [];
|
|
3167
|
-
const reason = typeof details.reason === "string" ? details.reason : "unknown reason";
|
|
3168
|
-
const location = typeof details.path === "string" ? ` at ${details.path}` : "";
|
|
3169
|
-
return [`${reason}${location}`];
|
|
3170
|
-
});
|
|
3171
|
-
if (dropped.length === 0)
|
|
3172
|
-
continue;
|
|
3173
|
-
const noun = dropped.length === 1 ? "thinking block" : `${dropped.length} thinking blocks`;
|
|
3174
|
-
this.chatContainer.addChild(new Spacer(1));
|
|
3175
|
-
this.chatContainer.addChild(new Text(theme.fg("warning", `Anthropic dropped ${noun}: ${dropped.join("; ")}`), 1, 0));
|
|
3226
|
+
count += transformations.filter((transformation) => typeof transformation === "object" &&
|
|
3227
|
+
transformation !== null &&
|
|
3228
|
+
transformation.type === "thinking_dropped").length;
|
|
3176
3229
|
}
|
|
3230
|
+
return count;
|
|
3231
|
+
}
|
|
3232
|
+
maybeShowThinkingDropNotice(message) {
|
|
3233
|
+
if (!this.settingsManager.getShowCacheMissNotices())
|
|
3234
|
+
return;
|
|
3235
|
+
const droppedCount = InteractiveMode.countDroppedThinkingBlocks(message);
|
|
3236
|
+
if (droppedCount === 0)
|
|
3237
|
+
return;
|
|
3238
|
+
let previousDroppedCount = 0;
|
|
3239
|
+
// message_end reaches the UI before the current message is persisted,
|
|
3240
|
+
// so the branch's last assistant message is the previous response.
|
|
3241
|
+
const branch = this.sessionManager.getBranch();
|
|
3242
|
+
for (let i = branch.length - 1; i >= 0; i--) {
|
|
3243
|
+
const entry = branch[i];
|
|
3244
|
+
if (entry.type === "message" && entry.message.role === "assistant") {
|
|
3245
|
+
previousDroppedCount = InteractiveMode.countDroppedThinkingBlocks(entry.message);
|
|
3246
|
+
break;
|
|
3247
|
+
}
|
|
3248
|
+
}
|
|
3249
|
+
if (droppedCount <= previousDroppedCount)
|
|
3250
|
+
return;
|
|
3251
|
+
const noun = droppedCount === 1 ? "thinking block" : "thinking blocks";
|
|
3252
|
+
this.chatContainer.addChild(new Spacer(1));
|
|
3253
|
+
this.chatContainer.addChild(new Text(theme.fg("warning", `Anthropic dropped ${droppedCount} ${noun} (details in session)`), 1, 0));
|
|
3177
3254
|
}
|
|
3178
3255
|
/**
|
|
3179
3256
|
* Show a transcript notice when a completed assistant message paid for a
|
|
@@ -3336,6 +3413,9 @@ export class InteractiveMode {
|
|
|
3336
3413
|
catch { }
|
|
3337
3414
|
console.error(`${APP_NAME} exiting due to uncaughtException:`);
|
|
3338
3415
|
console.error(error);
|
|
3416
|
+
if (this.recordCrash("uncaught_exception", error)) {
|
|
3417
|
+
console.error(`\n${this.crashReportInstructions()}`);
|
|
3418
|
+
}
|
|
3339
3419
|
process.exit(1);
|
|
3340
3420
|
}
|
|
3341
3421
|
/**
|
|
@@ -3443,9 +3523,7 @@ export class InteractiveMode {
|
|
|
3443
3523
|
const level = this.session.thinkingLevel || "off";
|
|
3444
3524
|
this.editor.borderColor = theme.getThinkingBorderColor(level);
|
|
3445
3525
|
}
|
|
3446
|
-
|
|
3447
|
-
this.activeStatusIndicator.invalidate();
|
|
3448
|
-
}
|
|
3526
|
+
this.activeStatusIndicator?.invalidate();
|
|
3449
3527
|
this.ui.requestRender();
|
|
3450
3528
|
}
|
|
3451
3529
|
cycleThinkingLevel() {
|
|
@@ -3635,7 +3713,7 @@ export class InteractiveMode {
|
|
|
3635
3713
|
if (allQueued.length === 0) {
|
|
3636
3714
|
this.updatePendingMessagesDisplay();
|
|
3637
3715
|
if (options?.abort) {
|
|
3638
|
-
this.
|
|
3716
|
+
void this.session.abort();
|
|
3639
3717
|
}
|
|
3640
3718
|
return 0;
|
|
3641
3719
|
}
|
|
@@ -3645,7 +3723,7 @@ export class InteractiveMode {
|
|
|
3645
3723
|
this.editor.setText(combinedText);
|
|
3646
3724
|
this.updatePendingMessagesDisplay();
|
|
3647
3725
|
if (options?.abort) {
|
|
3648
|
-
this.
|
|
3726
|
+
void this.session.abort();
|
|
3649
3727
|
}
|
|
3650
3728
|
return allQueued.length;
|
|
3651
3729
|
}
|
|
@@ -3806,6 +3884,7 @@ export class InteractiveMode {
|
|
|
3806
3884
|
followUpMode: this.session.followUpMode,
|
|
3807
3885
|
transport: this.settingsManager.getTransport(),
|
|
3808
3886
|
httpIdleTimeoutMs: this.settingsManager.getHttpIdleTimeoutMs(),
|
|
3887
|
+
cacheWarmingMode: this.settingsManager.getCacheWarmingMode(),
|
|
3809
3888
|
thinkingLevel: this.settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL,
|
|
3810
3889
|
availableThinkingLevels: [...THINKING_LEVEL_OPTIONS],
|
|
3811
3890
|
modelThinkingLevels: this.settingsManager.getAllModelThinkingLevels(),
|
|
@@ -3878,6 +3957,10 @@ export class InteractiveMode {
|
|
|
3878
3957
|
configureHttpDispatcher(timeoutMs);
|
|
3879
3958
|
this.showStatus(`HTTP idle timeout: ${formatHttpIdleTimeoutMs(timeoutMs)}`);
|
|
3880
3959
|
},
|
|
3960
|
+
onCacheWarmingModeChange: (mode) => {
|
|
3961
|
+
this.session.setCacheWarmingMode(mode);
|
|
3962
|
+
this.showStatus(`Cache warming: ${mode}`);
|
|
3963
|
+
},
|
|
3881
3964
|
onModelThinkingLevelChange: (provider, modelId, level) => {
|
|
3882
3965
|
this.settingsManager.setModelThinkingLevel(provider, modelId, level);
|
|
3883
3966
|
// If the override is for the current model, apply it to the session too
|
|
@@ -4429,6 +4512,11 @@ export class InteractiveMode {
|
|
|
4429
4512
|
this.restoreQueuedMessagesToEditor();
|
|
4430
4513
|
await this.session.abort();
|
|
4431
4514
|
}
|
|
4515
|
+
// Recheck after the dialogs and streaming abort, before replacing another operation's UI.
|
|
4516
|
+
if (this.session.isCompacting) {
|
|
4517
|
+
this.showError("Wait for the current compaction or tree navigation to finish before navigating the session tree.");
|
|
4518
|
+
return;
|
|
4519
|
+
}
|
|
4432
4520
|
// Set up escape handler and status indicator if summarizing
|
|
4433
4521
|
let showingSummaryIndicator = false;
|
|
4434
4522
|
const originalOnEscape = this.defaultEditor.onEscape;
|
|
@@ -4480,7 +4568,7 @@ export class InteractiveMode {
|
|
|
4480
4568
|
}, (entryId, label) => {
|
|
4481
4569
|
this.sessionManager.appendLabelChange(entryId, label);
|
|
4482
4570
|
this.ui.requestRender();
|
|
4483
|
-
}, initialSelectedId, initialFilterMode
|
|
4571
|
+
}, initialSelectedId, initialFilterMode);
|
|
4484
4572
|
selector.onCopy = async (text) => {
|
|
4485
4573
|
if (!text) {
|
|
4486
4574
|
this.showError("Selected entry has no text to copy");
|
|
@@ -4494,14 +4582,14 @@ export class InteractiveMode {
|
|
|
4494
4582
|
this.showError(error instanceof Error ? error.message : String(error));
|
|
4495
4583
|
}
|
|
4496
4584
|
};
|
|
4497
|
-
return { component: selector, focus: selector
|
|
4585
|
+
return { component: selector, focus: selector };
|
|
4498
4586
|
});
|
|
4499
4587
|
}
|
|
4500
4588
|
showSessionSelector() {
|
|
4501
4589
|
this.showSelector((done) => {
|
|
4502
|
-
const selector = new SessionSelectorComponent((onProgress) => SessionManager.list(this.sessionManager.getCwd(), this.sessionManager.getSessionDir(), onProgress), (onProgress) => this.sessionManager.usesDefaultSessionDir()
|
|
4503
|
-
? SessionManager.listAll(onProgress)
|
|
4504
|
-
: SessionManager.listAll(this.sessionManager.getSessionDir(), onProgress), async (sessionPath) => {
|
|
4590
|
+
const selector = new SessionSelectorComponent((onProgress, signal) => SessionManager.list(this.sessionManager.getCwd(), this.sessionManager.getSessionDir(), onProgress, signal), (onProgress, signal) => this.sessionManager.usesDefaultSessionDir()
|
|
4591
|
+
? SessionManager.listAll(onProgress, signal)
|
|
4592
|
+
: SessionManager.listAll(this.sessionManager.getSessionDir(), onProgress, signal), async (sessionPath) => {
|
|
4505
4593
|
done();
|
|
4506
4594
|
await this.handleResumeSession(sessionPath);
|
|
4507
4595
|
}, () => {
|
|
@@ -4520,7 +4608,7 @@ export class InteractiveMode {
|
|
|
4520
4608
|
showRenameHint: true,
|
|
4521
4609
|
keybindings: this.keybindings,
|
|
4522
4610
|
}, this.sessionManager.getSessionFile());
|
|
4523
|
-
return { component: selector, focus: selector
|
|
4611
|
+
return { component: selector, focus: selector };
|
|
4524
4612
|
});
|
|
4525
4613
|
}
|
|
4526
4614
|
async handleResumeSession(sessionPath, options) {
|
|
@@ -4764,67 +4852,89 @@ export class InteractiveMode {
|
|
|
4764
4852
|
}
|
|
4765
4853
|
async completeProviderAuthentication(providerId, providerName, authType, previousModel) {
|
|
4766
4854
|
const actionLabel = authType === "oauth" ? `Logged in to ${providerName}` : `Saved API key for ${providerName}`;
|
|
4767
|
-
|
|
4768
|
-
|
|
4769
|
-
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
|
|
4773
|
-
|
|
4774
|
-
|
|
4775
|
-
|
|
4776
|
-
|
|
4777
|
-
|
|
4778
|
-
|
|
4779
|
-
|
|
4780
|
-
|
|
4781
|
-
|
|
4782
|
-
|
|
4783
|
-
|
|
4784
|
-
|
|
4785
|
-
|
|
4786
|
-
|
|
4855
|
+
const session = this.session;
|
|
4856
|
+
// Dynamic catalogs may be empty until the first authenticated network refresh.
|
|
4857
|
+
const deferSelection = isUnknownModel(previousModel) &&
|
|
4858
|
+
hasDefaultModelProvider(providerId) &&
|
|
4859
|
+
!session.modelRuntime
|
|
4860
|
+
.getAvailableSnapshot()
|
|
4861
|
+
.some((model) => model.provider === providerId && model.id === defaultModelPerProvider[providerId]);
|
|
4862
|
+
const finishAuthentication = async () => {
|
|
4863
|
+
let selectedModel;
|
|
4864
|
+
let selectionError;
|
|
4865
|
+
if (isUnknownModel(previousModel)) {
|
|
4866
|
+
const availableModels = this.session.modelRuntime.getAvailableSnapshot();
|
|
4867
|
+
const providerModels = availableModels.filter((model) => model.provider === providerId);
|
|
4868
|
+
// Matches LLAMA_PROVIDER_ID from extensions/llama/provider.ts; kept inline to avoid coupling interactive mode to the built-in extension.
|
|
4869
|
+
if (providerId === "llama.cpp") {
|
|
4870
|
+
selectionError = llamaCppPostLoginGuidance(actionLabel, providerModels.length);
|
|
4871
|
+
}
|
|
4872
|
+
else if (!hasDefaultModelProvider(providerId)) {
|
|
4873
|
+
selectionError = `${actionLabel}, but no default model is configured for provider "${providerId}". Use /model to select a model.`;
|
|
4874
|
+
}
|
|
4875
|
+
else if (providerModels.length === 0) {
|
|
4876
|
+
selectionError = `${actionLabel}, but no models are available for that provider. Use /model to select a model.`;
|
|
4787
4877
|
}
|
|
4788
4878
|
else {
|
|
4789
|
-
|
|
4790
|
-
|
|
4879
|
+
const defaultModelId = defaultModelPerProvider[providerId];
|
|
4880
|
+
// Radius catalogs vary by account; prefer balanced, then use catalog order.
|
|
4881
|
+
selectedModel =
|
|
4882
|
+
providerModels.find((model) => model.id === defaultModelId) ??
|
|
4883
|
+
(providerId === "radius" ? providerModels[0] : undefined);
|
|
4884
|
+
if (!selectedModel) {
|
|
4885
|
+
selectionError = `${actionLabel}, but its default model "${defaultModelId}" is not available. Use /model to select a model.`;
|
|
4791
4886
|
}
|
|
4792
|
-
|
|
4793
|
-
|
|
4794
|
-
|
|
4795
|
-
|
|
4887
|
+
else {
|
|
4888
|
+
try {
|
|
4889
|
+
await this.session.setModel(selectedModel, { persist: true });
|
|
4890
|
+
}
|
|
4891
|
+
catch (error) {
|
|
4892
|
+
selectedModel = undefined;
|
|
4893
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
4894
|
+
selectionError = `${actionLabel}, but selecting its default model failed: ${errorMessage}. Use /model to select a model.`;
|
|
4895
|
+
}
|
|
4796
4896
|
}
|
|
4797
4897
|
}
|
|
4798
4898
|
}
|
|
4799
|
-
|
|
4800
|
-
|
|
4801
|
-
|
|
4802
|
-
|
|
4803
|
-
|
|
4804
|
-
|
|
4805
|
-
|
|
4806
|
-
this.checkDaxnutsEasterEgg(selectedModel);
|
|
4807
|
-
}
|
|
4808
|
-
else {
|
|
4809
|
-
this.showStatus(`${actionLabel}. Credentials saved to ${getAuthPath()}`);
|
|
4810
|
-
if (selectionError) {
|
|
4811
|
-
this.showError(selectionError);
|
|
4899
|
+
await this.updateAvailableProviderCount();
|
|
4900
|
+
this.footer.invalidate();
|
|
4901
|
+
this.updateEditorBorderColor();
|
|
4902
|
+
if (selectedModel) {
|
|
4903
|
+
this.showStatus(`${actionLabel}. Selected ${selectedModel.id}. Credentials saved to ${getAuthPath()}`);
|
|
4904
|
+
void this.maybeWarnAboutAnthropicSubscriptionAuth(selectedModel);
|
|
4905
|
+
this.checkDaxnutsEasterEgg(selectedModel);
|
|
4812
4906
|
}
|
|
4813
4907
|
else {
|
|
4814
|
-
|
|
4908
|
+
this.showStatus(`${actionLabel}. Credentials saved to ${getAuthPath()}`);
|
|
4909
|
+
if (selectionError) {
|
|
4910
|
+
this.showError(selectionError);
|
|
4911
|
+
}
|
|
4912
|
+
else {
|
|
4913
|
+
void this.maybeWarnAboutAnthropicSubscriptionAuth();
|
|
4914
|
+
}
|
|
4815
4915
|
}
|
|
4916
|
+
};
|
|
4917
|
+
if (deferSelection) {
|
|
4918
|
+
this.showStatus(`${actionLabel}. Credentials saved to ${getAuthPath()}. Refreshing model catalog…`);
|
|
4919
|
+
}
|
|
4920
|
+
else {
|
|
4921
|
+
await finishAuthentication();
|
|
4816
4922
|
}
|
|
4817
4923
|
const controller = new AbortController();
|
|
4818
4924
|
const timeout = setTimeout(() => controller.abort(), 15_000);
|
|
4819
|
-
void
|
|
4925
|
+
void session.modelRuntime
|
|
4820
4926
|
.refresh({ providers: [providerId], signal: controller.signal })
|
|
4821
|
-
.then((result) => {
|
|
4927
|
+
.then(async (result) => {
|
|
4822
4928
|
if (result.aborted) {
|
|
4823
4929
|
this.showWarning(`${actionLabel}, but its model catalog refresh timed out; using cached models.`);
|
|
4824
4930
|
}
|
|
4825
4931
|
else if (result.errors.size > 0) {
|
|
4826
4932
|
this.showWarning(`${actionLabel}, but its model catalog could not be refreshed; using cached models.`);
|
|
4827
4933
|
}
|
|
4934
|
+
// Do not replace a model or session selected while the refresh was running.
|
|
4935
|
+
if (deferSelection && this.session === session && session.model === previousModel) {
|
|
4936
|
+
await finishAuthentication();
|
|
4937
|
+
}
|
|
4828
4938
|
this.updateAvailableProviderCount();
|
|
4829
4939
|
this.footer.invalidate();
|
|
4830
4940
|
this.ui.requestRender();
|
|
@@ -5166,6 +5276,16 @@ export class InteractiveMode {
|
|
|
5166
5276
|
showError: (message) => this.showError(message),
|
|
5167
5277
|
});
|
|
5168
5278
|
}
|
|
5279
|
+
async handleBugCommand(hint) {
|
|
5280
|
+
await reportBug({
|
|
5281
|
+
session: this.session,
|
|
5282
|
+
ui: this.ui,
|
|
5283
|
+
editorContainer: this.editorContainer,
|
|
5284
|
+
editor: this.editor,
|
|
5285
|
+
showStatus: (message) => this.showStatus(message),
|
|
5286
|
+
showError: (message) => this.showError(message),
|
|
5287
|
+
}, hint);
|
|
5288
|
+
}
|
|
5169
5289
|
async handleCopyCommand(options = {}) {
|
|
5170
5290
|
if (options.preferSelection &&
|
|
5171
5291
|
this.ui instanceof TuiAltScreen &&
|
|
@@ -5251,6 +5371,15 @@ export class InteractiveMode {
|
|
|
5251
5371
|
}
|
|
5252
5372
|
info += `${theme.fg("dim", "Output:")} ${stats.tokens.output.toLocaleString()}\n`;
|
|
5253
5373
|
info += `${theme.fg("dim", "Total:")} ${stats.tokens.total.toLocaleString()}\n`;
|
|
5374
|
+
const cacheWarmingStatus = this.session.cacheWarmingStatus;
|
|
5375
|
+
info += `\n${theme.bold("Cache Warming")}\n`;
|
|
5376
|
+
info += `${theme.fg("dim", "Mode:")} ${this.settingsManager.getCacheWarmingMode()}\n`;
|
|
5377
|
+
info += `${theme.fg("dim", "Status:")} ${cacheWarmingStatus ? formatCacheWarmingStatus(cacheWarmingStatus) : "Inactive (cache warming unavailable)"}\n`;
|
|
5378
|
+
const decision = cacheWarmingStatus?.decision;
|
|
5379
|
+
if (decision?.economicsAvailable) {
|
|
5380
|
+
info += `${theme.fg("dim", "Cache miss penalty:")} $${decision.missCost.toFixed(3)}\n`;
|
|
5381
|
+
info += `${theme.fg("dim", "Refresh cost:")} $${decision.warmCost.toFixed(3)}\n`;
|
|
5382
|
+
}
|
|
5254
5383
|
if (stats.cost > 0 || cacheWaste.missedTokens > 0) {
|
|
5255
5384
|
info += `\n${theme.bold("Cost")}\n`;
|
|
5256
5385
|
info += `${theme.fg("dim", "Total:")} $${stats.cost.toFixed(3)}`;
|
|
@@ -5381,7 +5510,7 @@ export class InteractiveMode {
|
|
|
5381
5510
|
| \`${expandTools}\` | Toggle tool output expansion |
|
|
5382
5511
|
| \`${toggleThinking}\` | Toggle thinking block visibility |
|
|
5383
5512
|
| \`${externalEditor}\` | Edit message in external editor |
|
|
5384
|
-
| \`${copyMessage}\` | Copy last assistant message |
|
|
5513
|
+
| \`${copyMessage}\` | Copy selection or last assistant message |
|
|
5385
5514
|
| \`${followUp}\` | Queue follow-up message |
|
|
5386
5515
|
| \`${dequeue}\` | Restore queued messages |
|
|
5387
5516
|
| \`${pasteImage}\` | Paste image or text from clipboard |
|
|
@@ -5477,12 +5606,19 @@ export class InteractiveMode {
|
|
|
5477
5606
|
async handleBashCommand(command, excludeFromContext = false) {
|
|
5478
5607
|
const extensionRunner = this.session.extensionRunner;
|
|
5479
5608
|
// Emit user_bash event to let extensions intercept
|
|
5480
|
-
|
|
5481
|
-
|
|
5482
|
-
|
|
5483
|
-
|
|
5484
|
-
|
|
5485
|
-
|
|
5609
|
+
let eventResult;
|
|
5610
|
+
try {
|
|
5611
|
+
eventResult = await extensionRunner.emitUserBash({
|
|
5612
|
+
type: "user_bash",
|
|
5613
|
+
command,
|
|
5614
|
+
excludeFromContext,
|
|
5615
|
+
cwd: this.sessionManager.getCwd(),
|
|
5616
|
+
});
|
|
5617
|
+
}
|
|
5618
|
+
catch {
|
|
5619
|
+
// The extension runner already reported the error. Do not fall back to local execution.
|
|
5620
|
+
return;
|
|
5621
|
+
}
|
|
5486
5622
|
// If extension returned a full result, use it directly
|
|
5487
5623
|
if (eventResult?.result) {
|
|
5488
5624
|
const result = eventResult.result;
|