@earendil-works/pi-coding-agent 0.84.2 → 0.84.4
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 +127 -0
- package/README.md +13 -8
- package/dist/bundle/chunks/anthropic-messages-JWX2WP65.js +45 -0
- package/dist/bundle/chunks/anthropic.js +75 -0
- package/dist/bundle/chunks/azure-openai-responses-5ENVCQ7U.js +2 -0
- package/dist/bundle/chunks/bedrock-converse-stream.js +74 -0
- package/dist/bundle/chunks/chunk-2KVJKXS2.js +50 -0
- package/dist/bundle/chunks/chunk-4L3WN2XY.js +2 -0
- package/dist/bundle/chunks/chunk-6CYCI3EJ.js +12 -0
- package/dist/bundle/chunks/chunk-6R7UI4IY.js +2 -0
- package/dist/bundle/chunks/chunk-AXIIZGTV.js +2 -0
- package/dist/bundle/chunks/chunk-DRQDKNXA.js +2 -0
- package/dist/bundle/chunks/chunk-GMWCTUPB.js +2 -0
- package/dist/bundle/chunks/chunk-JUUC5AZY.js +2 -0
- package/dist/bundle/chunks/chunk-L2ZPNLYD.js +2 -0
- package/dist/bundle/chunks/chunk-MNAIPA3J.js +2 -0
- package/dist/bundle/chunks/chunk-NBBFIJUL.js +11 -0
- package/dist/bundle/chunks/chunk-NUHFSC37.js +25 -0
- package/dist/bundle/chunks/chunk-OMWWHBTG.js +1548 -0
- package/dist/bundle/chunks/chunk-PGXDEOVV.js +2 -0
- package/dist/bundle/chunks/chunk-PJACZCIR.js +2 -0
- package/dist/bundle/chunks/chunk-PRRNXB7S.js +2 -0
- package/dist/bundle/chunks/chunk-TEPMHNKQ.js +2 -0
- package/dist/bundle/chunks/chunk-TRDNDS6A.js +4 -0
- package/dist/bundle/chunks/chunk-UAQELI3K.js +2 -0
- package/dist/bundle/chunks/chunk-XDUWOHPL.js +6 -0
- package/dist/bundle/chunks/chunk-XNGRGP62.js +2 -0
- package/dist/bundle/chunks/github-copilot.js +2 -0
- package/dist/bundle/chunks/google-generative-ai-YMUPJBKR.js +2 -0
- package/dist/bundle/chunks/google-vertex-MPWMV4OF.js +2 -0
- package/dist/bundle/chunks/https-proxy-agent-2VXB7436.js +13 -0
- package/dist/bundle/chunks/image-resize-worker.js +2 -0
- package/dist/bundle/chunks/kimi-coding.js +2 -0
- package/dist/bundle/chunks/lib-HGQMNYVT.js +9 -0
- package/dist/bundle/chunks/mistral-conversations-Q3AWZJAZ.js +5 -0
- package/dist/bundle/chunks/multipart-parser-SQ6GDJL7.js +3 -0
- package/dist/bundle/chunks/openai-codex-responses-GJVBJXLB.js +8 -0
- package/dist/bundle/chunks/openai-codex.js +75 -0
- package/dist/bundle/chunks/openai-completions-ERMU2SS7.js +7 -0
- package/dist/bundle/chunks/openai-responses-BSOJMSEV.js +2 -0
- package/dist/bundle/chunks/openrouter-images-N4XVVFSD.js +2 -0
- package/dist/bundle/chunks/openrouter.js +75 -0
- package/dist/bundle/chunks/pi-messages-TPFH44NP.js +8 -0
- package/dist/bundle/chunks/radius.js +75 -0
- package/dist/bundle/chunks/src-UK77SYZE.js +4 -0
- package/dist/bundle/chunks/xai.js +2 -0
- package/dist/bundle/cli.js +3 -0
- package/dist/bundle/client.js +2 -0
- package/dist/bundle/index.js +2 -0
- package/dist/bundle/rpc-entry.js +3 -0
- package/dist/cli/args.d.ts +1 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +29 -9
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/file-processor.d.ts.map +1 -1
- package/dist/cli/file-processor.js +2 -1
- package/dist/cli/file-processor.js.map +1 -1
- package/dist/cli/startup-ui.d.ts.map +1 -1
- package/dist/cli/startup-ui.js +2 -1
- package/dist/cli/startup-ui.js.map +1 -1
- package/dist/config.d.ts +4 -3
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +22 -14
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session.d.ts +38 -8
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +240 -104
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +6 -7
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +7 -3
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +9 -3
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +59 -36
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/defaults.d.ts +1 -0
- package/dist/core/defaults.d.ts.map +1 -1
- package/dist/core/defaults.js +9 -0
- package/dist/core/defaults.js.map +1 -1
- package/dist/core/extensions/index.d.ts +2 -2
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +115 -48
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +5 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +45 -1
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +56 -10
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js +3 -0
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts +1 -1
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +1 -1
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/keybindings.d.ts +20 -19
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +26 -5
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/model-config.d.ts +5 -0
- package/dist/core/model-config.d.ts.map +1 -1
- package/dist/core/model-config.js +3 -1
- package/dist/core/model-config.js.map +1 -1
- package/dist/core/model-resolver.d.ts +1 -0
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +14 -8
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/models-store.d.ts.map +1 -1
- package/dist/core/models-store.js +2 -1
- package/dist/core/models-store.js.map +1 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +22 -14
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/pi-manifest.d.ts.map +1 -1
- package/dist/core/pi-manifest.js +2 -1
- package/dist/core/pi-manifest.js.map +1 -1
- package/dist/core/remote-catalog-provider.d.ts.map +1 -1
- package/dist/core/remote-catalog-provider.js +2 -1
- package/dist/core/remote-catalog-provider.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +3 -2
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/sdk.d.ts +2 -2
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +10 -3
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-export.d.ts +4 -0
- package/dist/core/session-export.d.ts.map +1 -0
- package/dist/core/session-export.js +32 -0
- package/dist/core/session-export.js.map +1 -0
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +6 -3
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-diagnostics.d.ts +9 -0
- package/dist/core/settings-diagnostics.d.ts.map +1 -0
- package/dist/core/settings-diagnostics.js +21 -0
- package/dist/core/settings-diagnostics.js.map +1 -0
- package/dist/core/settings-manager.d.ts +17 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +69 -10
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +51 -33
- package/dist/core/skills.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +2 -1
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +11 -2
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts +14 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +36 -20
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit-diff.d.ts +0 -5
- package/dist/core/tools/edit-diff.d.ts.map +1 -1
- package/dist/core/tools/edit-diff.js +2 -5
- package/dist/core/tools/edit-diff.js.map +1 -1
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +20 -4
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/index.d.ts +4 -1
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +18 -1
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/powershell.d.ts +16 -0
- package/dist/core/tools/powershell.d.ts.map +1 -0
- package/dist/core/tools/powershell.js +39 -0
- package/dist/core/tools/powershell.js.map +1 -0
- package/dist/core/trust-manager.d.ts.map +1 -1
- package/dist/core/trust-manager.js +2 -1
- package/dist/core/trust-manager.js.map +1 -1
- package/dist/extensions/llama/client.d.ts +6 -0
- package/dist/extensions/llama/client.d.ts.map +1 -1
- package/dist/extensions/llama/client.js +7 -0
- package/dist/extensions/llama/client.js.map +1 -1
- package/dist/extensions/llama/index.d.ts.map +1 -1
- package/dist/extensions/llama/index.js +2 -0
- package/dist/extensions/llama/index.js.map +1 -1
- package/dist/extensions/llama/provider.d.ts +3 -1
- package/dist/extensions/llama/provider.d.ts.map +1 -1
- package/dist/extensions/llama/provider.js +29 -4
- package/dist/extensions/llama/provider.js.map +1 -1
- package/dist/index.d.ts +6 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -4
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts +4 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +20 -15
- package/dist/main.js.map +1 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +4 -3
- package/dist/migrations.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts +9 -3
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +56 -12
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +9 -2
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +128 -56
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-submenu.d.ts +72 -0
- package/dist/modes/interactive/components/settings-submenu.d.ts.map +1 -0
- package/dist/modes/interactive/components/settings-submenu.js +165 -0
- package/dist/modes/interactive/components/settings-submenu.js.map +1 -0
- package/dist/modes/interactive/components/thinking-selector.d.ts +15 -3
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.js +74 -17
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
- package/dist/modes/interactive/external-editor.d.ts.map +1 -1
- package/dist/modes/interactive/external-editor.js +2 -1
- package/dist/modes/interactive/external-editor.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +15 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +223 -129
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/session-share.d.ts +16 -0
- package/dist/modes/interactive/session-share.d.ts.map +1 -0
- package/dist/modes/interactive/session-share.js +188 -0
- package/dist/modes/interactive/session-share.js.map +1 -0
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +4 -3
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/json-event.d.ts +16 -13
- package/dist/modes/json-event.d.ts.map +1 -1
- package/dist/modes/json-event.js +20 -6
- package/dist/modes/json-event.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +7 -0
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +7 -0
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +3 -0
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +12 -0
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/package-manager-cli.d.ts +1 -0
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js +186 -2
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/utils/frontmatter.d.ts.map +1 -1
- package/dist/utils/frontmatter.js +2 -1
- package/dist/utils/frontmatter.js.map +1 -1
- package/dist/utils/management-http.d.ts +5 -3
- package/dist/utils/management-http.d.ts.map +1 -1
- package/dist/utils/management-http.js +14 -10
- package/dist/utils/management-http.js.map +1 -1
- package/dist/utils/shell.d.ts +3 -0
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js +23 -9
- package/dist/utils/shell.js.map +1 -1
- package/dist/utils/syntax-highlight.d.ts +1 -0
- package/dist/utils/syntax-highlight.d.ts.map +1 -1
- package/dist/utils/syntax-highlight.js +60 -1
- package/dist/utils/syntax-highlight.js.map +1 -1
- package/dist/utils/text.d.ts +8 -0
- package/dist/utils/text.d.ts.map +1 -0
- package/dist/utils/text.js +9 -0
- package/dist/utils/text.js.map +1 -0
- package/docs/compaction.md +17 -0
- package/docs/custom-provider.md +12 -9
- package/docs/environment-variables.md +11 -8
- package/docs/extensions.md +35 -7
- package/docs/json.md +7 -2
- package/docs/keybindings.md +9 -9
- package/docs/llama-cpp.md +2 -0
- package/docs/models.md +8 -2
- package/docs/packages.md +2 -2
- package/docs/quickstart.md +1 -1
- package/docs/rpc.md +32 -3
- package/docs/sdk.md +7 -2
- package/docs/settings.md +23 -7
- package/docs/skills.md +4 -3
- package/docs/terminal-setup.md +23 -9
- package/docs/usage.md +10 -5
- package/docs/windows.md +24 -2
- package/examples/extensions/border-status-editor.ts +1 -1
- 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/package.json +1 -1
- package/examples/extensions/git-checkpoint.ts +2 -2
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/notify.ts +3 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/subagent/README.md +1 -1
- package/examples/extensions/subagent/index.ts +6 -1
- package/examples/extensions/titlebar-spinner.ts +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/rpc-extension-ui.ts +1 -1
- package/examples/sdk/06-extensions.ts +1 -1
- package/examples/sdk/README.md +1 -1
- package/npm-shrinkwrap.json +24 -77
- package/package.json +12 -14
|
@@ -7,13 +7,14 @@ import * as fs from "node:fs";
|
|
|
7
7
|
import * as os from "node:os";
|
|
8
8
|
import * as path from "node:path";
|
|
9
9
|
import * as TuiLayouts from "@earendil-works/pi-tui";
|
|
10
|
-
import { CombinedAutocompleteProvider, Container, fuzzyFilter, getCapabilities, hyperlink, Markdown, matchesKey, ProcessTerminal, Spacer, setKeybindings, Text, TruncatedText, TuiAltScreen, TuiMainScreen, visibleWidth, } from "@earendil-works/pi-tui";
|
|
10
|
+
import { CombinedAutocompleteProvider, Container, fuzzyFilter, getCapabilities, hyperlink, Markdown, matchesKey, ProcessTerminal, Spacer, setCapabilityOverrides, setKeybindings, Text, TruncatedText, TuiAltScreen, TuiMainScreen, visibleWidth, } from "@earendil-works/pi-tui";
|
|
11
11
|
import chalk from "chalk";
|
|
12
|
-
import { spawn
|
|
13
|
-
import { APP_NAME, APP_TITLE, CONFIG_DIR_NAME, getAgentDir, getAuthPath, getDebugLogPath, getDocsPath,
|
|
12
|
+
import { spawn } from "child_process";
|
|
13
|
+
import { APP_NAME, APP_TITLE, CONFIG_DIR_NAME, getAgentDir, getAuthPath, getDebugLogPath, getDocsPath, VERSION, } from "../../config.js";
|
|
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 { DEFAULT_THINKING_LEVEL, THINKING_LEVEL_OPTIONS } from "../../core/defaults.js";
|
|
17
18
|
import { FooterDataProvider } from "../../core/footer-data-provider.js";
|
|
18
19
|
import { configureHttpDispatcher, formatHttpIdleTimeoutMs } from "../../core/http-dispatcher.js";
|
|
19
20
|
import { KeybindingsManager } from "../../core/keybindings.js";
|
|
@@ -35,12 +36,12 @@ import { openBrowser } from "../../utils/open-browser.js";
|
|
|
35
36
|
import { getCwdRelativePath } from "../../utils/paths.js";
|
|
36
37
|
import { getPiUserAgent } from "../../utils/pi-user-agent.js";
|
|
37
38
|
import { killTrackedDetachedChildren } from "../../utils/shell.js";
|
|
39
|
+
import { loadAllHighlightLanguages } from "../../utils/syntax-highlight.js";
|
|
38
40
|
import { ensureTool } from "../../utils/tools-manager.js";
|
|
39
41
|
import { checkForNewPiVersion } from "../../utils/version-check.js";
|
|
40
42
|
import { ArminComponent } from "./components/armin.js";
|
|
41
43
|
import { AssistantMessageComponent } from "./components/assistant-message.js";
|
|
42
44
|
import { BashExecutionComponent } from "./components/bash-execution.js";
|
|
43
|
-
import { BorderedLoader } from "./components/bordered-loader.js";
|
|
44
45
|
import { BranchSummaryMessageComponent } from "./components/branch-summary-message.js";
|
|
45
46
|
import { CompactionSummaryMessageComponent } from "./components/compaction-summary-message.js";
|
|
46
47
|
import { CustomEditor } from "./components/custom-editor.js";
|
|
@@ -63,6 +64,7 @@ import { SessionSelectorComponent } from "./components/session-selector.js";
|
|
|
63
64
|
import { SettingsSelectorComponent } from "./components/settings-selector.js";
|
|
64
65
|
import { SkillInvocationMessageComponent } from "./components/skill-invocation-message.js";
|
|
65
66
|
import { BranchSummaryStatusIndicator, CompactionStatusIndicator, IdleStatus, RetryStatusIndicator, WorkingStatusIndicator, } from "./components/status-indicator.js";
|
|
67
|
+
import { ThinkingSelectorComponent } from "./components/thinking-selector.js";
|
|
66
68
|
import { ToolExecutionComponent } from "./components/tool-execution.js";
|
|
67
69
|
import { TreeSelectorComponent } from "./components/tree-selector.js";
|
|
68
70
|
import { TrustSelectorComponent } from "./components/trust-selector.js";
|
|
@@ -71,6 +73,7 @@ import { UserMessageSelectorComponent } from "./components/user-message-selector
|
|
|
71
73
|
import { editInExternalEditor } from "./external-editor.js";
|
|
72
74
|
import { refreshModelCatalogs } from "./model-catalog-refresh.js";
|
|
73
75
|
import { getModelSearchText } from "./model-search.js";
|
|
76
|
+
import { shareSession } from "./session-share.js";
|
|
74
77
|
import { getAvailableThemes, getAvailableThemesWithPaths, getEditorTheme, getMarkdownTheme, getThemeByName, onThemeChange, setRegisteredThemes, stopThemeWatcher, Theme, theme, } from "./theme/theme.js";
|
|
75
78
|
import { InteractiveThemeController } from "./theme/theme-controller.js";
|
|
76
79
|
function isExpandable(obj) {
|
|
@@ -91,6 +94,9 @@ class ExpandableText extends Text {
|
|
|
91
94
|
function isCustomSessionEntry(item) {
|
|
92
95
|
return "type" in item && item.type === "custom";
|
|
93
96
|
}
|
|
97
|
+
function isCompactionCostNotice(item) {
|
|
98
|
+
return "type" in item && item.type === "compaction_cost";
|
|
99
|
+
}
|
|
94
100
|
const DEAD_TERMINAL_ERROR_CODES = new Set(["EIO", "EPIPE", "ENOTCONN"]);
|
|
95
101
|
function isDeadTerminalError(error) {
|
|
96
102
|
if (!error || typeof error !== "object" || !("code" in error)) {
|
|
@@ -130,6 +136,11 @@ export function formatResumeCommand(sessionManager) {
|
|
|
130
136
|
function hasDefaultModelProvider(providerId) {
|
|
131
137
|
return providerId in defaultModelPerProvider;
|
|
132
138
|
}
|
|
139
|
+
function llamaCppPostLoginGuidance(actionLabel, loadedModelCount) {
|
|
140
|
+
return loadedModelCount === 0
|
|
141
|
+
? `${actionLabel}. No llama.cpp models are loaded. Use /llama to load a model, then /model to select it.`
|
|
142
|
+
: `${actionLabel}. Use /model to select a loaded llama.cpp model, or /llama to manage models.`;
|
|
143
|
+
}
|
|
133
144
|
const AUTH_TYPE_ORDER = { oauth: 0, api_key: 1 };
|
|
134
145
|
function createFuzzyAutocompleteItems(items, prefix, getSearchText, toAutocompleteItem) {
|
|
135
146
|
const filtered = fuzzyFilter(items, prefix, getSearchText);
|
|
@@ -176,6 +187,7 @@ export function createInteractiveTui(options) {
|
|
|
176
187
|
searchCurrentMatchStyle: (text) => theme.bold(theme.inverse(styleSearchMatch(text))),
|
|
177
188
|
openUrl: openBrowser,
|
|
178
189
|
onRightClickPaste: options.onRightClickPaste,
|
|
190
|
+
copyOnSelect: options.fullscreenCopyOnSelect,
|
|
179
191
|
copySelection: async (text) => {
|
|
180
192
|
try {
|
|
181
193
|
await copyToClipboard(text);
|
|
@@ -339,6 +351,7 @@ export class InteractiveMode {
|
|
|
339
351
|
}
|
|
340
352
|
constructor(runtimeHost, options = {}) {
|
|
341
353
|
this.runtimeHost = runtimeHost;
|
|
354
|
+
setCapabilityOverrides(this.settingsManager.getTerminalCapabilityOverrides());
|
|
342
355
|
const tuiMode = options.tuiMode ?? this.settingsManager.getTuiMode();
|
|
343
356
|
this.options = { ...options, tuiMode };
|
|
344
357
|
this.autoTrustOnReloadCwd = options.autoTrustOnReloadCwd;
|
|
@@ -355,6 +368,7 @@ export class InteractiveMode {
|
|
|
355
368
|
showHardwareCursor: this.settingsManager.getShowHardwareCursor(),
|
|
356
369
|
logDirectory: getAgentDir(),
|
|
357
370
|
onRightClickPaste: this.onRightClickPaste,
|
|
371
|
+
fullscreenCopyOnSelect: this.settingsManager.getFullscreenCopyOnSelect(),
|
|
358
372
|
});
|
|
359
373
|
this.ui = createInteractiveTuiReference(() => this.renderer);
|
|
360
374
|
this.ui.setClearOnShrink(this.settingsManager.getClearOnShrink());
|
|
@@ -465,6 +479,15 @@ export class InteractiveMode {
|
|
|
465
479
|
}));
|
|
466
480
|
};
|
|
467
481
|
}
|
|
482
|
+
const thinkingCommand = slashCommands.find((command) => command.name === "thinking");
|
|
483
|
+
if (thinkingCommand) {
|
|
484
|
+
thinkingCommand.getArgumentCompletions = (prefix) => {
|
|
485
|
+
return createFuzzyAutocompleteItems(this.session.getAvailableThinkingLevels(), prefix, (level) => level, (level) => ({
|
|
486
|
+
value: level,
|
|
487
|
+
label: level,
|
|
488
|
+
}));
|
|
489
|
+
};
|
|
490
|
+
}
|
|
468
491
|
const loginCommand = slashCommands.find((command) => command.name === "login");
|
|
469
492
|
if (loginCommand) {
|
|
470
493
|
loginCommand.getArgumentCompletions = (prefix) => {
|
|
@@ -593,6 +616,7 @@ export class InteractiveMode {
|
|
|
593
616
|
logDirectory: getAgentDir(),
|
|
594
617
|
terminal,
|
|
595
618
|
onRightClickPaste: this.onRightClickPaste,
|
|
619
|
+
fullscreenCopyOnSelect: this.settingsManager.getFullscreenCopyOnSelect(),
|
|
596
620
|
});
|
|
597
621
|
nextUi.setClearOnShrink(clearOnShrink);
|
|
598
622
|
nextUi.onDebug = onDebug;
|
|
@@ -749,6 +773,14 @@ export class InteractiveMode {
|
|
|
749
773
|
});
|
|
750
774
|
// Initialize available provider count for footer display
|
|
751
775
|
await this.updateAvailableProviderCount();
|
|
776
|
+
// Flush the completed startup state before loading the remaining syntax grammars.
|
|
777
|
+
this.ui.renderNow();
|
|
778
|
+
void loadAllHighlightLanguages().then(() => {
|
|
779
|
+
if (!this.isInitialized)
|
|
780
|
+
return;
|
|
781
|
+
this.ui.invalidate();
|
|
782
|
+
this.ui.requestRender();
|
|
783
|
+
});
|
|
752
784
|
}
|
|
753
785
|
/**
|
|
754
786
|
* Update terminal title with session name and cwd.
|
|
@@ -804,7 +836,18 @@ export class InteractiveMode {
|
|
|
804
836
|
}
|
|
805
837
|
});
|
|
806
838
|
// Show startup warnings
|
|
807
|
-
const { migratedProviders, modelFallbackMessage, initialMessage, initialImages, initialMessages } = this.options;
|
|
839
|
+
const { migratedProviders, startupDiagnostics, modelFallbackMessage, initialMessage, initialImages, initialMessages, } = this.options;
|
|
840
|
+
for (const diagnostic of startupDiagnostics ?? []) {
|
|
841
|
+
if (diagnostic.type === "error") {
|
|
842
|
+
this.showError(diagnostic.message);
|
|
843
|
+
}
|
|
844
|
+
else if (diagnostic.type === "warning") {
|
|
845
|
+
this.showWarning(diagnostic.message);
|
|
846
|
+
}
|
|
847
|
+
else {
|
|
848
|
+
this.showStatus(diagnostic.message);
|
|
849
|
+
}
|
|
850
|
+
}
|
|
808
851
|
if (migratedProviders && migratedProviders.length > 0) {
|
|
809
852
|
this.showWarning(`Migrated credentials to auth.json: ${migratedProviders.join(", ")}`);
|
|
810
853
|
}
|
|
@@ -1482,8 +1525,12 @@ export class InteractiveMode {
|
|
|
1482
1525
|
this.transcriptScrollView?.setScrollbar(this.settingsManager.getFullscreenScrollbar());
|
|
1483
1526
|
}
|
|
1484
1527
|
applyRuntimeSettings() {
|
|
1528
|
+
setCapabilityOverrides(this.settingsManager.getTerminalCapabilityOverrides());
|
|
1485
1529
|
configureHttpDispatcher(this.settingsManager.getHttpIdleTimeoutMs());
|
|
1486
1530
|
this.applyFullscreenScrollbarSetting();
|
|
1531
|
+
if (this.renderer instanceof TuiAltScreen) {
|
|
1532
|
+
this.renderer.setCopyOnSelect(this.settingsManager.getFullscreenCopyOnSelect());
|
|
1533
|
+
}
|
|
1487
1534
|
this.footer.setSession(this.session);
|
|
1488
1535
|
this.footer.setAutoCompactEnabled(this.session.autoCompactionEnabled);
|
|
1489
1536
|
this.footerDataProvider.setCwd(this.sessionManager.getCwd());
|
|
@@ -1633,6 +1680,9 @@ export class InteractiveMode {
|
|
|
1633
1680
|
this.statusContainer.addChild(this.idleStatus);
|
|
1634
1681
|
}
|
|
1635
1682
|
}
|
|
1683
|
+
showWorkingStatusIndicator() {
|
|
1684
|
+
this.showStatusIndicator(new WorkingStatusIndicator(this.ui, this.workingMessage ?? this.defaultWorkingMessage, this.workingIndicatorOptions));
|
|
1685
|
+
}
|
|
1636
1686
|
setWorkingVisible(visible) {
|
|
1637
1687
|
this.workingVisible = visible;
|
|
1638
1688
|
if (!visible) {
|
|
@@ -1641,7 +1691,7 @@ export class InteractiveMode {
|
|
|
1641
1691
|
return;
|
|
1642
1692
|
}
|
|
1643
1693
|
if (this.session.isStreaming && this.activeStatusIndicator?.kind !== "working") {
|
|
1644
|
-
this.
|
|
1694
|
+
this.showWorkingStatusIndicator();
|
|
1645
1695
|
}
|
|
1646
1696
|
this.ui.requestRender();
|
|
1647
1697
|
}
|
|
@@ -2261,7 +2311,7 @@ export class InteractiveMode {
|
|
|
2261
2311
|
this.defaultEditor.onAction("app.tools.expand", () => this.toggleToolOutputExpansion());
|
|
2262
2312
|
this.defaultEditor.onAction("app.thinking.toggle", () => this.toggleThinkingBlockVisibility());
|
|
2263
2313
|
this.defaultEditor.onAction("app.editor.external", () => void this.handleOpenExternalEditor());
|
|
2264
|
-
this.defaultEditor.onAction("app.message.copy", () => void this.handleCopyCommand({ flashConfirmation: true }));
|
|
2314
|
+
this.defaultEditor.onAction("app.message.copy", () => void this.handleCopyCommand({ flashConfirmation: true, preferSelection: true }));
|
|
2265
2315
|
this.defaultEditor.onAction("app.message.followUp", () => this.handleFollowUp());
|
|
2266
2316
|
this.defaultEditor.onAction("app.message.dequeue", () => this.handleDequeue());
|
|
2267
2317
|
this.defaultEditor.onAction("app.session.new", () => this.handleClearCommand());
|
|
@@ -2346,6 +2396,12 @@ export class InteractiveMode {
|
|
|
2346
2396
|
await this.handleModelCommand(searchTerm);
|
|
2347
2397
|
return;
|
|
2348
2398
|
}
|
|
2399
|
+
if (text === "/thinking" || text.startsWith("/thinking ")) {
|
|
2400
|
+
const searchTerm = text.startsWith("/thinking ") ? text.slice(10).trim() : undefined;
|
|
2401
|
+
this.editor.setText("");
|
|
2402
|
+
this.handleThinkingCommand(searchTerm);
|
|
2403
|
+
return;
|
|
2404
|
+
}
|
|
2349
2405
|
if (text === "/export" || text.startsWith("/export ")) {
|
|
2350
2406
|
await this.handleExportCommand(text);
|
|
2351
2407
|
this.editor.setText("");
|
|
@@ -2522,17 +2578,21 @@ export class InteractiveMode {
|
|
|
2522
2578
|
switch (event.type) {
|
|
2523
2579
|
case "agent_start":
|
|
2524
2580
|
this.pendingTools.clear();
|
|
2525
|
-
if (this.settingsManager.getShowTerminalProgress()) {
|
|
2526
|
-
this.ui.terminal.setProgress(true);
|
|
2527
|
-
}
|
|
2528
2581
|
// Restore main escape handler if retry handler is still active
|
|
2529
2582
|
// (retry success event fires later, but we need main handler now)
|
|
2530
2583
|
if (this.retryEscapeHandler) {
|
|
2531
2584
|
this.defaultEditor.onEscape = this.retryEscapeHandler;
|
|
2532
2585
|
this.retryEscapeHandler = undefined;
|
|
2533
2586
|
}
|
|
2587
|
+
break;
|
|
2588
|
+
case "turn_start":
|
|
2589
|
+
if (this.settingsManager.getShowTerminalProgress()) {
|
|
2590
|
+
this.ui.terminal.setProgress(true);
|
|
2591
|
+
}
|
|
2534
2592
|
if (this.workingVisible) {
|
|
2535
|
-
|
|
2593
|
+
if (this.activeStatusIndicator?.kind !== "working") {
|
|
2594
|
+
this.showWorkingStatusIndicator();
|
|
2595
|
+
}
|
|
2536
2596
|
}
|
|
2537
2597
|
else {
|
|
2538
2598
|
this.clearStatusIndicator();
|
|
@@ -2724,9 +2784,21 @@ export class InteractiveMode {
|
|
|
2724
2784
|
}
|
|
2725
2785
|
}
|
|
2726
2786
|
else if (event.result) {
|
|
2787
|
+
const entries = this.sessionManager.buildContextEntries();
|
|
2788
|
+
if (entries[0]?.type !== "compaction") {
|
|
2789
|
+
throw new Error("Completed compaction is missing from the session context");
|
|
2790
|
+
}
|
|
2727
2791
|
this.chatContainer.clear();
|
|
2728
|
-
|
|
2792
|
+
// The latest compaction is prepended for model context; append it below at its chronological position.
|
|
2793
|
+
this.renderSessionEntries(entries.slice(1));
|
|
2729
2794
|
this.addMessageToChat(createCompactionSummaryMessage(event.result.summary, event.result.tokensBefore, new Date().toISOString()));
|
|
2795
|
+
if (event.result.usage) {
|
|
2796
|
+
this.addCompactionCostNotice({
|
|
2797
|
+
type: "compaction_cost",
|
|
2798
|
+
kind: "compaction",
|
|
2799
|
+
usage: event.result.usage,
|
|
2800
|
+
});
|
|
2801
|
+
}
|
|
2730
2802
|
this.footer.invalidate();
|
|
2731
2803
|
}
|
|
2732
2804
|
else if (event.errorMessage) {
|
|
@@ -2948,6 +3020,10 @@ export class InteractiveMode {
|
|
|
2948
3020
|
this.addCustomEntryToChat(item);
|
|
2949
3021
|
continue;
|
|
2950
3022
|
}
|
|
3023
|
+
if (isCompactionCostNotice(item)) {
|
|
3024
|
+
this.addCompactionCostNotice(item);
|
|
3025
|
+
continue;
|
|
3026
|
+
}
|
|
2951
3027
|
const message = item;
|
|
2952
3028
|
// Assistant messages need special handling for tool calls
|
|
2953
3029
|
if (message.role === "assistant") {
|
|
@@ -3015,10 +3091,28 @@ export class InteractiveMode {
|
|
|
3015
3091
|
if (entry.type === "custom") {
|
|
3016
3092
|
return [entry];
|
|
3017
3093
|
}
|
|
3018
|
-
|
|
3094
|
+
const messages = sessionEntryToContextMessages(entry);
|
|
3095
|
+
if ((entry.type === "compaction" || entry.type === "branch_summary") && entry.usage && messages.length > 0) {
|
|
3096
|
+
return [...messages, { type: "compaction_cost", kind: entry.type, usage: entry.usage }];
|
|
3097
|
+
}
|
|
3098
|
+
return messages;
|
|
3019
3099
|
});
|
|
3020
3100
|
this.renderSessionItems(items, options);
|
|
3021
3101
|
}
|
|
3102
|
+
/**
|
|
3103
|
+
* Render billing usage for a compaction or branch summary. The notice is derived
|
|
3104
|
+
* from persisted summary usage and is not stored as a separate session entry.
|
|
3105
|
+
*/
|
|
3106
|
+
addCompactionCostNotice(notice) {
|
|
3107
|
+
if (!this.settingsManager.getShowCacheMissNotices())
|
|
3108
|
+
return;
|
|
3109
|
+
const { usage } = notice;
|
|
3110
|
+
const tokens = usage.input + usage.output + usage.cacheRead + usage.cacheWrite;
|
|
3111
|
+
const cost = usage.cost.total >= 0.01 ? ` (~$${usage.cost.total.toFixed(2)})` : "";
|
|
3112
|
+
const label = notice.kind === "compaction" ? "Compaction" : "Branch summary";
|
|
3113
|
+
this.chatContainer.addChild(new Spacer(1));
|
|
3114
|
+
this.chatContainer.addChild(new Text(theme.fg("warning", `${label}: ${formatTokens(tokens)} tokens billed${cost}`), 1, 0));
|
|
3115
|
+
}
|
|
3022
3116
|
/**
|
|
3023
3117
|
* Show a transcript notice when a completed assistant message paid for a
|
|
3024
3118
|
* significant cache miss. Only states observable facts: the miss itself,
|
|
@@ -3368,18 +3462,19 @@ export class InteractiveMode {
|
|
|
3368
3462
|
}
|
|
3369
3463
|
this.showStatus(`Tool output: ${expanded ? "expanded" : "collapsed"}`);
|
|
3370
3464
|
}
|
|
3465
|
+
/** Update rendered assistant messages without rebuilding live tool components. */
|
|
3466
|
+
updateThinkingBlockVisibility() {
|
|
3467
|
+
for (const child of this.chatContainer.children) {
|
|
3468
|
+
if (child instanceof AssistantMessageComponent) {
|
|
3469
|
+
child.setHideThinkingBlock(this.hideThinkingBlock);
|
|
3470
|
+
}
|
|
3471
|
+
}
|
|
3472
|
+
this.ui.requestRender();
|
|
3473
|
+
}
|
|
3371
3474
|
toggleThinkingBlockVisibility() {
|
|
3372
3475
|
this.hideThinkingBlock = !this.hideThinkingBlock;
|
|
3373
3476
|
this.settingsManager.setHideThinkingBlock(this.hideThinkingBlock);
|
|
3374
|
-
|
|
3375
|
-
this.chatContainer.clear();
|
|
3376
|
-
this.rebuildChatFromMessages();
|
|
3377
|
-
// If streaming, re-add the streaming component with updated visibility and re-render
|
|
3378
|
-
if (this.streamingComponent && this.streamingMessage) {
|
|
3379
|
-
this.streamingComponent.setHideThinkingBlock(this.hideThinkingBlock);
|
|
3380
|
-
this.streamingComponent.updateContent(this.streamingMessage);
|
|
3381
|
-
this.chatContainer.addChild(this.streamingComponent);
|
|
3382
|
-
}
|
|
3477
|
+
this.updateThinkingBlockVisibility();
|
|
3383
3478
|
this.showStatus(`Thinking blocks: ${this.hideThinkingBlock ? "hidden" : "visible"}`);
|
|
3384
3479
|
}
|
|
3385
3480
|
async handleOpenExternalEditor() {
|
|
@@ -3655,8 +3750,14 @@ export class InteractiveMode {
|
|
|
3655
3750
|
showSettingsSelector() {
|
|
3656
3751
|
this.showSelector((done) => {
|
|
3657
3752
|
let selector;
|
|
3753
|
+
const defaultProvider = this.settingsManager.getDefaultProvider();
|
|
3754
|
+
const defaultModelId = this.settingsManager.getDefaultModel();
|
|
3755
|
+
const defaultModel = defaultProvider && defaultModelId ? `${defaultProvider}/${defaultModelId}` : "not set";
|
|
3658
3756
|
selector = new SettingsSelectorComponent({
|
|
3659
3757
|
autoCompact: this.session.autoCompactionEnabled,
|
|
3758
|
+
defaultModel,
|
|
3759
|
+
currentModel: this.session.model,
|
|
3760
|
+
availableDefaultModels: this.session.modelRuntime.getAvailableSnapshot(),
|
|
3660
3761
|
showImages: this.settingsManager.getShowImages(),
|
|
3661
3762
|
imageWidthCells: this.settingsManager.getImageWidthCells(),
|
|
3662
3763
|
autoResizeImages: this.settingsManager.getImageAutoResize(),
|
|
@@ -3666,8 +3767,9 @@ export class InteractiveMode {
|
|
|
3666
3767
|
followUpMode: this.session.followUpMode,
|
|
3667
3768
|
transport: this.settingsManager.getTransport(),
|
|
3668
3769
|
httpIdleTimeoutMs: this.settingsManager.getHttpIdleTimeoutMs(),
|
|
3669
|
-
thinkingLevel: this.
|
|
3670
|
-
availableThinkingLevels:
|
|
3770
|
+
thinkingLevel: this.settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL,
|
|
3771
|
+
availableThinkingLevels: [...THINKING_LEVEL_OPTIONS],
|
|
3772
|
+
modelThinkingLevels: this.settingsManager.getAllModelThinkingLevels(),
|
|
3671
3773
|
currentTheme: this.themeController.getThemeSelection() || "dark",
|
|
3672
3774
|
terminalTheme: this.themeController.getTerminalTheme(),
|
|
3673
3775
|
availableThemes: getAvailableThemes(),
|
|
@@ -3689,6 +3791,7 @@ export class InteractiveMode {
|
|
|
3689
3791
|
tuiMode: this.ui.mode,
|
|
3690
3792
|
fullscreenExitOutput: this.settingsManager.getFullscreenExitOutput(),
|
|
3691
3793
|
fullscreenScrollbar: this.settingsManager.getFullscreenScrollbar(),
|
|
3794
|
+
fullscreenCopyOnSelect: this.settingsManager.getFullscreenCopyOnSelect(),
|
|
3692
3795
|
warnings: this.settingsManager.getWarnings(),
|
|
3693
3796
|
}, {
|
|
3694
3797
|
onAutoCompactChange: (enabled) => {
|
|
@@ -3736,10 +3839,26 @@ export class InteractiveMode {
|
|
|
3736
3839
|
configureHttpDispatcher(timeoutMs);
|
|
3737
3840
|
this.showStatus(`HTTP idle timeout: ${formatHttpIdleTimeoutMs(timeoutMs)}`);
|
|
3738
3841
|
},
|
|
3739
|
-
|
|
3740
|
-
this.
|
|
3741
|
-
|
|
3742
|
-
this.
|
|
3842
|
+
onModelThinkingLevelChange: (provider, modelId, level) => {
|
|
3843
|
+
this.settingsManager.setModelThinkingLevel(provider, modelId, level);
|
|
3844
|
+
// If the override is for the current model, apply it to the session too
|
|
3845
|
+
const current = this.session.model;
|
|
3846
|
+
if (current && current.provider === provider && current.id === modelId) {
|
|
3847
|
+
this.session.setThinkingLevel(level);
|
|
3848
|
+
this.footer.invalidate();
|
|
3849
|
+
this.updateEditorBorderColor();
|
|
3850
|
+
}
|
|
3851
|
+
},
|
|
3852
|
+
onModelThinkingLevelRemove: (provider, modelId) => {
|
|
3853
|
+
this.settingsManager.removeModelThinkingLevel(provider, modelId);
|
|
3854
|
+
// If the override was for the current model, revert to global default
|
|
3855
|
+
const current = this.session.model;
|
|
3856
|
+
if (current && current.provider === provider && current.id === modelId) {
|
|
3857
|
+
const globalDefault = this.settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL;
|
|
3858
|
+
this.session.setThinkingLevel(globalDefault);
|
|
3859
|
+
this.footer.invalidate();
|
|
3860
|
+
this.updateEditorBorderColor();
|
|
3861
|
+
}
|
|
3743
3862
|
},
|
|
3744
3863
|
onThemeChange: (themeSetting) => {
|
|
3745
3864
|
this.settingsManager.setTheme(themeSetting);
|
|
@@ -3749,13 +3868,7 @@ export class InteractiveMode {
|
|
|
3749
3868
|
onHideThinkingBlockChange: (hidden) => {
|
|
3750
3869
|
this.hideThinkingBlock = hidden;
|
|
3751
3870
|
this.settingsManager.setHideThinkingBlock(hidden);
|
|
3752
|
-
|
|
3753
|
-
if (child instanceof AssistantMessageComponent) {
|
|
3754
|
-
child.setHideThinkingBlock(hidden);
|
|
3755
|
-
}
|
|
3756
|
-
}
|
|
3757
|
-
this.chatContainer.clear();
|
|
3758
|
-
this.rebuildChatFromMessages();
|
|
3871
|
+
this.updateThinkingBlockVisibility();
|
|
3759
3872
|
},
|
|
3760
3873
|
onMermaidRenderingModeChange: (mode) => {
|
|
3761
3874
|
this.settingsManager.setMermaidRenderingMode(mode);
|
|
@@ -3849,6 +3962,11 @@ export class InteractiveMode {
|
|
|
3849
3962
|
this.settingsManager.setFullscreenScrollbar(mode);
|
|
3850
3963
|
this.applyFullscreenScrollbarSetting();
|
|
3851
3964
|
},
|
|
3965
|
+
onFullscreenCopyOnSelectChange: (enabled) => {
|
|
3966
|
+
this.settingsManager.setFullscreenCopyOnSelect(enabled);
|
|
3967
|
+
if (this.renderer instanceof TuiAltScreen)
|
|
3968
|
+
this.renderer.setCopyOnSelect(enabled);
|
|
3969
|
+
},
|
|
3852
3970
|
onWarningsChange: (warnings) => {
|
|
3853
3971
|
this.settingsManager.setWarnings(warnings);
|
|
3854
3972
|
},
|
|
@@ -3860,6 +3978,44 @@ export class InteractiveMode {
|
|
|
3860
3978
|
return { component: selector, focus: selector.getSettingsList() };
|
|
3861
3979
|
});
|
|
3862
3980
|
}
|
|
3981
|
+
handleThinkingCommand(searchTerm) {
|
|
3982
|
+
const availableLevels = this.session.getAvailableThinkingLevels();
|
|
3983
|
+
if (!searchTerm) {
|
|
3984
|
+
this.showThinkingSelector();
|
|
3985
|
+
return;
|
|
3986
|
+
}
|
|
3987
|
+
const normalized = searchTerm.trim().toLowerCase();
|
|
3988
|
+
const level = availableLevels.find((candidate) => candidate.toLowerCase() === normalized);
|
|
3989
|
+
if (!level) {
|
|
3990
|
+
this.showError(`Unknown thinking level "${searchTerm}". Available levels: ${availableLevels.join(", ")}.`);
|
|
3991
|
+
return;
|
|
3992
|
+
}
|
|
3993
|
+
this.selectThinkingLevel(level, false);
|
|
3994
|
+
}
|
|
3995
|
+
selectThinkingLevel(level, persist) {
|
|
3996
|
+
try {
|
|
3997
|
+
this.session.setThinkingLevel(level, { persist });
|
|
3998
|
+
this.footer.invalidate();
|
|
3999
|
+
this.updateEditorBorderColor();
|
|
4000
|
+
this.showStatus(persist ? `Default thinking level: ${level}` : `Thinking level: ${level}`);
|
|
4001
|
+
}
|
|
4002
|
+
catch (error) {
|
|
4003
|
+
this.showError(error instanceof Error ? error.message : String(error));
|
|
4004
|
+
}
|
|
4005
|
+
}
|
|
4006
|
+
showThinkingSelector() {
|
|
4007
|
+
this.showSelector((done) => {
|
|
4008
|
+
const selectLevel = (level, persist) => {
|
|
4009
|
+
this.selectThinkingLevel(level, persist);
|
|
4010
|
+
done();
|
|
4011
|
+
};
|
|
4012
|
+
const selector = new ThinkingSelectorComponent(this.session.thinkingLevel ?? DEFAULT_THINKING_LEVEL, this.session.getAvailableThinkingLevels(), (level) => selectLevel(level, false), () => {
|
|
4013
|
+
done();
|
|
4014
|
+
this.ui.requestRender();
|
|
4015
|
+
}, (level) => selectLevel(level, true), this.settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL);
|
|
4016
|
+
return { component: selector, focus: selector };
|
|
4017
|
+
});
|
|
4018
|
+
}
|
|
3863
4019
|
async handleModelCommand(searchTerm) {
|
|
3864
4020
|
if (!searchTerm) {
|
|
3865
4021
|
this.showModelSelector();
|
|
@@ -3868,7 +4024,7 @@ export class InteractiveMode {
|
|
|
3868
4024
|
const model = await this.findExactModelMatch(searchTerm);
|
|
3869
4025
|
if (model) {
|
|
3870
4026
|
try {
|
|
3871
|
-
await this.session.setModel(model);
|
|
4027
|
+
await this.session.setModel(model, { persist: false });
|
|
3872
4028
|
this.footer.invalidate();
|
|
3873
4029
|
this.updateEditorBorderColor();
|
|
3874
4030
|
this.showStatus(`Model: ${model.id}`);
|
|
@@ -3997,13 +4153,14 @@ export class InteractiveMode {
|
|
|
3997
4153
|
}
|
|
3998
4154
|
showModelSelector(initialSearchInput) {
|
|
3999
4155
|
this.showSelector((done) => {
|
|
4000
|
-
const
|
|
4156
|
+
const selectModel = async (model, persist) => {
|
|
4001
4157
|
try {
|
|
4002
|
-
await this.session.setModel(model);
|
|
4158
|
+
await this.session.setModel(model, { persist });
|
|
4159
|
+
this.updateAvailableProviderCount();
|
|
4003
4160
|
this.footer.invalidate();
|
|
4004
4161
|
this.updateEditorBorderColor();
|
|
4005
4162
|
done();
|
|
4006
|
-
this.showStatus(`Model: ${model.id}`);
|
|
4163
|
+
this.showStatus(persist ? `Default model: ${model.provider}/${model.id}` : `Model: ${model.id}`);
|
|
4007
4164
|
void this.maybeWarnAboutAnthropicSubscriptionAuth(model);
|
|
4008
4165
|
this.checkDaxnutsEasterEgg(model);
|
|
4009
4166
|
}
|
|
@@ -4011,10 +4168,13 @@ export class InteractiveMode {
|
|
|
4011
4168
|
done();
|
|
4012
4169
|
this.showError(error instanceof Error ? error.message : String(error));
|
|
4013
4170
|
}
|
|
4014
|
-
}
|
|
4171
|
+
};
|
|
4172
|
+
const defaultProvider = this.settingsManager.getDefaultProvider();
|
|
4173
|
+
const defaultModel = this.settingsManager.getDefaultModel();
|
|
4174
|
+
const selector = new ModelSelectorComponent(this.ui, this.session.model, this.session.modelRuntime, this.session.scopedModels, (model) => selectModel(model, false), () => {
|
|
4015
4175
|
done();
|
|
4016
4176
|
this.ui.requestRender();
|
|
4017
|
-
}, initialSearchInput);
|
|
4177
|
+
}, initialSearchInput, (model) => selectModel(model, true), defaultProvider && defaultModel ? { provider: defaultProvider, id: defaultModel } : undefined);
|
|
4018
4178
|
return { component: selector, focus: selector, dispose: () => selector.dispose() };
|
|
4019
4179
|
});
|
|
4020
4180
|
}
|
|
@@ -4570,7 +4730,11 @@ export class InteractiveMode {
|
|
|
4570
4730
|
if (isUnknownModel(previousModel)) {
|
|
4571
4731
|
const availableModels = this.session.modelRuntime.getAvailableSnapshot();
|
|
4572
4732
|
const providerModels = availableModels.filter((model) => model.provider === providerId);
|
|
4573
|
-
|
|
4733
|
+
// Matches LLAMA_PROVIDER_ID from extensions/llama/provider.ts; kept inline to avoid coupling interactive mode to the built-in extension.
|
|
4734
|
+
if (providerId === "llama.cpp") {
|
|
4735
|
+
selectionError = llamaCppPostLoginGuidance(actionLabel, providerModels.length);
|
|
4736
|
+
}
|
|
4737
|
+
else if (!hasDefaultModelProvider(providerId)) {
|
|
4574
4738
|
selectionError = `${actionLabel}, but no default model is configured for provider "${providerId}". Use /model to select a model.`;
|
|
4575
4739
|
}
|
|
4576
4740
|
else if (providerModels.length === 0) {
|
|
@@ -4584,7 +4748,7 @@ export class InteractiveMode {
|
|
|
4584
4748
|
}
|
|
4585
4749
|
else {
|
|
4586
4750
|
try {
|
|
4587
|
-
await this.session.setModel(selectedModel);
|
|
4751
|
+
await this.session.setModel(selectedModel, { persist: true });
|
|
4588
4752
|
}
|
|
4589
4753
|
catch (error) {
|
|
4590
4754
|
selectedModel = undefined;
|
|
@@ -4841,8 +5005,8 @@ export class InteractiveMode {
|
|
|
4841
5005
|
activeHeader.setExpanded(this.toolOutputExpanded);
|
|
4842
5006
|
}
|
|
4843
5007
|
setRegisteredThemes(this.session.resourceLoader.getThemes().themes);
|
|
4844
|
-
await this.themeController.applyFromSettings();
|
|
4845
5008
|
this.applyRuntimeSettings();
|
|
5009
|
+
await this.themeController.applyFromSettings();
|
|
4846
5010
|
this.setupAutocompleteProvider();
|
|
4847
5011
|
const runner = this.session.extensionRunner;
|
|
4848
5012
|
this.setupExtensionShortcuts(runner);
|
|
@@ -4954,93 +5118,23 @@ export class InteractiveMode {
|
|
|
4954
5118
|
}
|
|
4955
5119
|
}
|
|
4956
5120
|
async handleShareCommand() {
|
|
4957
|
-
|
|
4958
|
-
|
|
4959
|
-
|
|
4960
|
-
|
|
4961
|
-
|
|
4962
|
-
|
|
4963
|
-
|
|
4964
|
-
}
|
|
4965
|
-
catch {
|
|
4966
|
-
this.showError("GitHub CLI (gh) is not installed. Install it from https://cli.github.com/");
|
|
4967
|
-
return;
|
|
4968
|
-
}
|
|
4969
|
-
// Export to a temp file
|
|
4970
|
-
const tmpFile = path.join(os.tmpdir(), "session.html");
|
|
4971
|
-
try {
|
|
4972
|
-
await this.session.exportToHtml(tmpFile, { themeName: theme.name });
|
|
4973
|
-
}
|
|
4974
|
-
catch (error) {
|
|
4975
|
-
this.showError(`Failed to export session: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
4976
|
-
return;
|
|
4977
|
-
}
|
|
4978
|
-
// Show cancellable loader, replacing the editor
|
|
4979
|
-
const loader = new BorderedLoader(this.ui, theme, "Creating gist...");
|
|
4980
|
-
this.editorContainer.clear();
|
|
4981
|
-
this.editorContainer.addChild(loader);
|
|
4982
|
-
this.ui.setFocus(loader);
|
|
4983
|
-
this.ui.requestRender();
|
|
4984
|
-
const restoreEditor = () => {
|
|
4985
|
-
loader.dispose();
|
|
4986
|
-
this.editorContainer.clear();
|
|
4987
|
-
this.editorContainer.addChild(this.editor);
|
|
4988
|
-
this.ui.setFocus(this.editor);
|
|
4989
|
-
try {
|
|
4990
|
-
fs.unlinkSync(tmpFile);
|
|
4991
|
-
}
|
|
4992
|
-
catch {
|
|
4993
|
-
// Ignore cleanup errors
|
|
4994
|
-
}
|
|
4995
|
-
};
|
|
4996
|
-
// Create a secret gist asynchronously
|
|
4997
|
-
let proc = null;
|
|
4998
|
-
loader.onAbort = () => {
|
|
4999
|
-
proc?.kill();
|
|
5000
|
-
restoreEditor();
|
|
5001
|
-
this.showStatus("Share cancelled");
|
|
5002
|
-
};
|
|
5003
|
-
try {
|
|
5004
|
-
const result = await new Promise((resolve) => {
|
|
5005
|
-
proc = spawn("gh", ["gist", "create", "--public=false", tmpFile]);
|
|
5006
|
-
let stdout = "";
|
|
5007
|
-
let stderr = "";
|
|
5008
|
-
proc.stdout?.on("data", (data) => {
|
|
5009
|
-
stdout += data.toString();
|
|
5010
|
-
});
|
|
5011
|
-
proc.stderr?.on("data", (data) => {
|
|
5012
|
-
stderr += data.toString();
|
|
5013
|
-
});
|
|
5014
|
-
proc.on("close", (code) => resolve({ stdout, stderr, code }));
|
|
5015
|
-
});
|
|
5016
|
-
if (loader.signal.aborted)
|
|
5017
|
-
return;
|
|
5018
|
-
restoreEditor();
|
|
5019
|
-
if (result.code !== 0) {
|
|
5020
|
-
const errorMsg = result.stderr?.trim() || "Unknown error";
|
|
5021
|
-
this.showError(`Failed to create gist: ${errorMsg}`);
|
|
5022
|
-
return;
|
|
5023
|
-
}
|
|
5024
|
-
// Extract gist ID from the URL returned by gh
|
|
5025
|
-
// gh returns something like: https://gist.github.com/username/GIST_ID
|
|
5026
|
-
const gistUrl = result.stdout?.trim();
|
|
5027
|
-
const gistId = gistUrl?.split("/").pop();
|
|
5028
|
-
if (!gistId) {
|
|
5029
|
-
this.showError("Failed to parse gist ID from gh output");
|
|
5030
|
-
return;
|
|
5031
|
-
}
|
|
5032
|
-
// Create the preview URL
|
|
5033
|
-
const previewUrl = getShareViewerUrl(gistId);
|
|
5034
|
-
this.showStatus(`Share URL: ${previewUrl}\nGist: ${gistUrl}`);
|
|
5035
|
-
}
|
|
5036
|
-
catch (error) {
|
|
5037
|
-
if (!loader.signal.aborted) {
|
|
5038
|
-
restoreEditor();
|
|
5039
|
-
this.showError(`Failed to create gist: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
5040
|
-
}
|
|
5041
|
-
}
|
|
5121
|
+
await shareSession({
|
|
5122
|
+
session: this.session,
|
|
5123
|
+
ui: this.ui,
|
|
5124
|
+
editorContainer: this.editorContainer,
|
|
5125
|
+
editor: this.editor,
|
|
5126
|
+
showStatus: (message) => this.showStatus(message),
|
|
5127
|
+
showError: (message) => this.showError(message),
|
|
5128
|
+
});
|
|
5042
5129
|
}
|
|
5043
5130
|
async handleCopyCommand(options = {}) {
|
|
5131
|
+
if (options.preferSelection &&
|
|
5132
|
+
this.ui instanceof TuiAltScreen &&
|
|
5133
|
+
!this.ui.getCopyOnSelect() &&
|
|
5134
|
+
this.ui.hasActiveSelection()) {
|
|
5135
|
+
await this.ui.copyActiveSelectionToClipboard();
|
|
5136
|
+
return;
|
|
5137
|
+
}
|
|
5044
5138
|
const text = this.session.getLastAssistantText();
|
|
5045
5139
|
if (!text) {
|
|
5046
5140
|
this.showError("No agent messages to copy yet.");
|