@earendil-works/pi-coding-agent 0.84.2 → 0.84.3
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 +83 -0
- package/README.md +8 -4
- 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-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-E5KXRMZK.js +1547 -0
- package/dist/bundle/chunks/chunk-GMWCTUPB.js +2 -0
- package/dist/bundle/chunks/chunk-GPPBJGBU.js +50 -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-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/dist-RDWOYWHR.js +13 -0
- package/dist/bundle/chunks/github-copilot.js +2 -0
- package/dist/bundle/chunks/google-generative-ai-XDKMGBCJ.js +2 -0
- package/dist/bundle/chunks/google-vertex-D5FGEO3Y.js +2 -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-YK73UAOZ.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-JD4WAC3R.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/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 +26 -7
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +163 -95
- 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 +3 -0
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +4 -3
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +41 -32
- 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/types.d.ts +38 -9
- 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 +2 -1
- 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 +9 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +52 -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/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.map +1 -1
- package/dist/extensions/llama/provider.js +6 -2
- package/dist/extensions/llama/provider.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -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 +18 -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 +7 -2
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +118 -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 +11 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +175 -105
- 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/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 +17 -5
- 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 +15 -0
- package/docs/custom-provider.md +5 -2
- package/docs/environment-variables.md +8 -8
- package/docs/extensions.md +17 -7
- package/docs/json.md +7 -2
- package/docs/keybindings.md +8 -8
- package/docs/llama-cpp.md +2 -0
- package/docs/models.md +8 -2
- package/docs/packages.md +2 -2
- package/docs/rpc.md +9 -3
- package/docs/sdk.md +7 -2
- package/docs/settings.md +11 -3
- package/docs/skills.md +4 -3
- package/docs/terminal-setup.md +11 -9
- package/docs/usage.md +6 -2
- 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
|
@@ -9,11 +9,12 @@ import * as path from "node:path";
|
|
|
9
9
|
import * as TuiLayouts from "@earendil-works/pi-tui";
|
|
10
10
|
import { CombinedAutocompleteProvider, Container, fuzzyFilter, getCapabilities, hyperlink, Markdown, matchesKey, ProcessTerminal, Spacer, 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);
|
|
@@ -465,6 +476,15 @@ export class InteractiveMode {
|
|
|
465
476
|
}));
|
|
466
477
|
};
|
|
467
478
|
}
|
|
479
|
+
const thinkingCommand = slashCommands.find((command) => command.name === "thinking");
|
|
480
|
+
if (thinkingCommand) {
|
|
481
|
+
thinkingCommand.getArgumentCompletions = (prefix) => {
|
|
482
|
+
return createFuzzyAutocompleteItems(this.session.getAvailableThinkingLevels(), prefix, (level) => level, (level) => ({
|
|
483
|
+
value: level,
|
|
484
|
+
label: level,
|
|
485
|
+
}));
|
|
486
|
+
};
|
|
487
|
+
}
|
|
468
488
|
const loginCommand = slashCommands.find((command) => command.name === "login");
|
|
469
489
|
if (loginCommand) {
|
|
470
490
|
loginCommand.getArgumentCompletions = (prefix) => {
|
|
@@ -749,6 +769,14 @@ export class InteractiveMode {
|
|
|
749
769
|
});
|
|
750
770
|
// Initialize available provider count for footer display
|
|
751
771
|
await this.updateAvailableProviderCount();
|
|
772
|
+
// Flush the completed startup state before loading the remaining syntax grammars.
|
|
773
|
+
this.ui.renderNow();
|
|
774
|
+
void loadAllHighlightLanguages().then(() => {
|
|
775
|
+
if (!this.isInitialized)
|
|
776
|
+
return;
|
|
777
|
+
this.ui.invalidate();
|
|
778
|
+
this.ui.requestRender();
|
|
779
|
+
});
|
|
752
780
|
}
|
|
753
781
|
/**
|
|
754
782
|
* Update terminal title with session name and cwd.
|
|
@@ -804,7 +832,18 @@ export class InteractiveMode {
|
|
|
804
832
|
}
|
|
805
833
|
});
|
|
806
834
|
// Show startup warnings
|
|
807
|
-
const { migratedProviders, modelFallbackMessage, initialMessage, initialImages, initialMessages } = this.options;
|
|
835
|
+
const { migratedProviders, startupDiagnostics, modelFallbackMessage, initialMessage, initialImages, initialMessages, } = this.options;
|
|
836
|
+
for (const diagnostic of startupDiagnostics ?? []) {
|
|
837
|
+
if (diagnostic.type === "error") {
|
|
838
|
+
this.showError(diagnostic.message);
|
|
839
|
+
}
|
|
840
|
+
else if (diagnostic.type === "warning") {
|
|
841
|
+
this.showWarning(diagnostic.message);
|
|
842
|
+
}
|
|
843
|
+
else {
|
|
844
|
+
this.showStatus(diagnostic.message);
|
|
845
|
+
}
|
|
846
|
+
}
|
|
808
847
|
if (migratedProviders && migratedProviders.length > 0) {
|
|
809
848
|
this.showWarning(`Migrated credentials to auth.json: ${migratedProviders.join(", ")}`);
|
|
810
849
|
}
|
|
@@ -2346,6 +2385,12 @@ export class InteractiveMode {
|
|
|
2346
2385
|
await this.handleModelCommand(searchTerm);
|
|
2347
2386
|
return;
|
|
2348
2387
|
}
|
|
2388
|
+
if (text === "/thinking" || text.startsWith("/thinking ")) {
|
|
2389
|
+
const searchTerm = text.startsWith("/thinking ") ? text.slice(10).trim() : undefined;
|
|
2390
|
+
this.editor.setText("");
|
|
2391
|
+
this.handleThinkingCommand(searchTerm);
|
|
2392
|
+
return;
|
|
2393
|
+
}
|
|
2349
2394
|
if (text === "/export" || text.startsWith("/export ")) {
|
|
2350
2395
|
await this.handleExportCommand(text);
|
|
2351
2396
|
this.editor.setText("");
|
|
@@ -2724,9 +2769,21 @@ export class InteractiveMode {
|
|
|
2724
2769
|
}
|
|
2725
2770
|
}
|
|
2726
2771
|
else if (event.result) {
|
|
2772
|
+
const entries = this.sessionManager.buildContextEntries();
|
|
2773
|
+
if (entries[0]?.type !== "compaction") {
|
|
2774
|
+
throw new Error("Completed compaction is missing from the session context");
|
|
2775
|
+
}
|
|
2727
2776
|
this.chatContainer.clear();
|
|
2728
|
-
|
|
2777
|
+
// The latest compaction is prepended for model context; append it below at its chronological position.
|
|
2778
|
+
this.renderSessionEntries(entries.slice(1));
|
|
2729
2779
|
this.addMessageToChat(createCompactionSummaryMessage(event.result.summary, event.result.tokensBefore, new Date().toISOString()));
|
|
2780
|
+
if (event.result.usage) {
|
|
2781
|
+
this.addCompactionCostNotice({
|
|
2782
|
+
type: "compaction_cost",
|
|
2783
|
+
kind: "compaction",
|
|
2784
|
+
usage: event.result.usage,
|
|
2785
|
+
});
|
|
2786
|
+
}
|
|
2730
2787
|
this.footer.invalidate();
|
|
2731
2788
|
}
|
|
2732
2789
|
else if (event.errorMessage) {
|
|
@@ -2948,6 +3005,10 @@ export class InteractiveMode {
|
|
|
2948
3005
|
this.addCustomEntryToChat(item);
|
|
2949
3006
|
continue;
|
|
2950
3007
|
}
|
|
3008
|
+
if (isCompactionCostNotice(item)) {
|
|
3009
|
+
this.addCompactionCostNotice(item);
|
|
3010
|
+
continue;
|
|
3011
|
+
}
|
|
2951
3012
|
const message = item;
|
|
2952
3013
|
// Assistant messages need special handling for tool calls
|
|
2953
3014
|
if (message.role === "assistant") {
|
|
@@ -3015,10 +3076,28 @@ export class InteractiveMode {
|
|
|
3015
3076
|
if (entry.type === "custom") {
|
|
3016
3077
|
return [entry];
|
|
3017
3078
|
}
|
|
3018
|
-
|
|
3079
|
+
const messages = sessionEntryToContextMessages(entry);
|
|
3080
|
+
if ((entry.type === "compaction" || entry.type === "branch_summary") && entry.usage && messages.length > 0) {
|
|
3081
|
+
return [...messages, { type: "compaction_cost", kind: entry.type, usage: entry.usage }];
|
|
3082
|
+
}
|
|
3083
|
+
return messages;
|
|
3019
3084
|
});
|
|
3020
3085
|
this.renderSessionItems(items, options);
|
|
3021
3086
|
}
|
|
3087
|
+
/**
|
|
3088
|
+
* Render billing usage for a compaction or branch summary. The notice is derived
|
|
3089
|
+
* from persisted summary usage and is not stored as a separate session entry.
|
|
3090
|
+
*/
|
|
3091
|
+
addCompactionCostNotice(notice) {
|
|
3092
|
+
if (!this.settingsManager.getShowCacheMissNotices())
|
|
3093
|
+
return;
|
|
3094
|
+
const { usage } = notice;
|
|
3095
|
+
const tokens = usage.input + usage.output + usage.cacheRead + usage.cacheWrite;
|
|
3096
|
+
const cost = usage.cost.total >= 0.01 ? ` (~$${usage.cost.total.toFixed(2)})` : "";
|
|
3097
|
+
const label = notice.kind === "compaction" ? "Compaction" : "Branch summary";
|
|
3098
|
+
this.chatContainer.addChild(new Spacer(1));
|
|
3099
|
+
this.chatContainer.addChild(new Text(theme.fg("warning", `${label}: ${formatTokens(tokens)} tokens billed${cost}`), 1, 0));
|
|
3100
|
+
}
|
|
3022
3101
|
/**
|
|
3023
3102
|
* Show a transcript notice when a completed assistant message paid for a
|
|
3024
3103
|
* significant cache miss. Only states observable facts: the miss itself,
|
|
@@ -3655,8 +3734,14 @@ export class InteractiveMode {
|
|
|
3655
3734
|
showSettingsSelector() {
|
|
3656
3735
|
this.showSelector((done) => {
|
|
3657
3736
|
let selector;
|
|
3737
|
+
const defaultProvider = this.settingsManager.getDefaultProvider();
|
|
3738
|
+
const defaultModelId = this.settingsManager.getDefaultModel();
|
|
3739
|
+
const defaultModel = defaultProvider && defaultModelId ? `${defaultProvider}/${defaultModelId}` : "not set";
|
|
3658
3740
|
selector = new SettingsSelectorComponent({
|
|
3659
3741
|
autoCompact: this.session.autoCompactionEnabled,
|
|
3742
|
+
defaultModel,
|
|
3743
|
+
currentModel: this.session.model,
|
|
3744
|
+
availableDefaultModels: this.session.modelRuntime.getAvailableSnapshot(),
|
|
3660
3745
|
showImages: this.settingsManager.getShowImages(),
|
|
3661
3746
|
imageWidthCells: this.settingsManager.getImageWidthCells(),
|
|
3662
3747
|
autoResizeImages: this.settingsManager.getImageAutoResize(),
|
|
@@ -3666,8 +3751,9 @@ export class InteractiveMode {
|
|
|
3666
3751
|
followUpMode: this.session.followUpMode,
|
|
3667
3752
|
transport: this.settingsManager.getTransport(),
|
|
3668
3753
|
httpIdleTimeoutMs: this.settingsManager.getHttpIdleTimeoutMs(),
|
|
3669
|
-
thinkingLevel: this.
|
|
3670
|
-
availableThinkingLevels:
|
|
3754
|
+
thinkingLevel: this.settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL,
|
|
3755
|
+
availableThinkingLevels: [...THINKING_LEVEL_OPTIONS],
|
|
3756
|
+
modelThinkingLevels: this.settingsManager.getAllModelThinkingLevels(),
|
|
3671
3757
|
currentTheme: this.themeController.getThemeSelection() || "dark",
|
|
3672
3758
|
terminalTheme: this.themeController.getTerminalTheme(),
|
|
3673
3759
|
availableThemes: getAvailableThemes(),
|
|
@@ -3736,10 +3822,26 @@ export class InteractiveMode {
|
|
|
3736
3822
|
configureHttpDispatcher(timeoutMs);
|
|
3737
3823
|
this.showStatus(`HTTP idle timeout: ${formatHttpIdleTimeoutMs(timeoutMs)}`);
|
|
3738
3824
|
},
|
|
3739
|
-
|
|
3740
|
-
this.
|
|
3741
|
-
|
|
3742
|
-
this.
|
|
3825
|
+
onModelThinkingLevelChange: (provider, modelId, level) => {
|
|
3826
|
+
this.settingsManager.setModelThinkingLevel(provider, modelId, level);
|
|
3827
|
+
// If the override is for the current model, apply it to the session too
|
|
3828
|
+
const current = this.session.model;
|
|
3829
|
+
if (current && current.provider === provider && current.id === modelId) {
|
|
3830
|
+
this.session.setThinkingLevel(level);
|
|
3831
|
+
this.footer.invalidate();
|
|
3832
|
+
this.updateEditorBorderColor();
|
|
3833
|
+
}
|
|
3834
|
+
},
|
|
3835
|
+
onModelThinkingLevelRemove: (provider, modelId) => {
|
|
3836
|
+
this.settingsManager.removeModelThinkingLevel(provider, modelId);
|
|
3837
|
+
// If the override was for the current model, revert to global default
|
|
3838
|
+
const current = this.session.model;
|
|
3839
|
+
if (current && current.provider === provider && current.id === modelId) {
|
|
3840
|
+
const globalDefault = this.settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL;
|
|
3841
|
+
this.session.setThinkingLevel(globalDefault);
|
|
3842
|
+
this.footer.invalidate();
|
|
3843
|
+
this.updateEditorBorderColor();
|
|
3844
|
+
}
|
|
3743
3845
|
},
|
|
3744
3846
|
onThemeChange: (themeSetting) => {
|
|
3745
3847
|
this.settingsManager.setTheme(themeSetting);
|
|
@@ -3860,6 +3962,44 @@ export class InteractiveMode {
|
|
|
3860
3962
|
return { component: selector, focus: selector.getSettingsList() };
|
|
3861
3963
|
});
|
|
3862
3964
|
}
|
|
3965
|
+
handleThinkingCommand(searchTerm) {
|
|
3966
|
+
const availableLevels = this.session.getAvailableThinkingLevels();
|
|
3967
|
+
if (!searchTerm) {
|
|
3968
|
+
this.showThinkingSelector();
|
|
3969
|
+
return;
|
|
3970
|
+
}
|
|
3971
|
+
const normalized = searchTerm.trim().toLowerCase();
|
|
3972
|
+
const level = availableLevels.find((candidate) => candidate.toLowerCase() === normalized);
|
|
3973
|
+
if (!level) {
|
|
3974
|
+
this.showError(`Unknown thinking level "${searchTerm}". Available levels: ${availableLevels.join(", ")}.`);
|
|
3975
|
+
return;
|
|
3976
|
+
}
|
|
3977
|
+
this.selectThinkingLevel(level, false);
|
|
3978
|
+
}
|
|
3979
|
+
selectThinkingLevel(level, persist) {
|
|
3980
|
+
try {
|
|
3981
|
+
this.session.setThinkingLevel(level, { persist });
|
|
3982
|
+
this.footer.invalidate();
|
|
3983
|
+
this.updateEditorBorderColor();
|
|
3984
|
+
this.showStatus(persist ? `Default thinking level: ${level}` : `Thinking level: ${level}`);
|
|
3985
|
+
}
|
|
3986
|
+
catch (error) {
|
|
3987
|
+
this.showError(error instanceof Error ? error.message : String(error));
|
|
3988
|
+
}
|
|
3989
|
+
}
|
|
3990
|
+
showThinkingSelector() {
|
|
3991
|
+
this.showSelector((done) => {
|
|
3992
|
+
const selectLevel = (level, persist) => {
|
|
3993
|
+
this.selectThinkingLevel(level, persist);
|
|
3994
|
+
done();
|
|
3995
|
+
};
|
|
3996
|
+
const selector = new ThinkingSelectorComponent(this.session.thinkingLevel ?? DEFAULT_THINKING_LEVEL, this.session.getAvailableThinkingLevels(), (level) => selectLevel(level, false), () => {
|
|
3997
|
+
done();
|
|
3998
|
+
this.ui.requestRender();
|
|
3999
|
+
}, (level) => selectLevel(level, true), this.settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL);
|
|
4000
|
+
return { component: selector, focus: selector };
|
|
4001
|
+
});
|
|
4002
|
+
}
|
|
3863
4003
|
async handleModelCommand(searchTerm) {
|
|
3864
4004
|
if (!searchTerm) {
|
|
3865
4005
|
this.showModelSelector();
|
|
@@ -3868,7 +4008,7 @@ export class InteractiveMode {
|
|
|
3868
4008
|
const model = await this.findExactModelMatch(searchTerm);
|
|
3869
4009
|
if (model) {
|
|
3870
4010
|
try {
|
|
3871
|
-
await this.session.setModel(model);
|
|
4011
|
+
await this.session.setModel(model, { persist: false });
|
|
3872
4012
|
this.footer.invalidate();
|
|
3873
4013
|
this.updateEditorBorderColor();
|
|
3874
4014
|
this.showStatus(`Model: ${model.id}`);
|
|
@@ -3997,13 +4137,13 @@ export class InteractiveMode {
|
|
|
3997
4137
|
}
|
|
3998
4138
|
showModelSelector(initialSearchInput) {
|
|
3999
4139
|
this.showSelector((done) => {
|
|
4000
|
-
const
|
|
4140
|
+
const selectModel = async (model, persist) => {
|
|
4001
4141
|
try {
|
|
4002
|
-
await this.session.setModel(model);
|
|
4142
|
+
await this.session.setModel(model, { persist });
|
|
4003
4143
|
this.footer.invalidate();
|
|
4004
4144
|
this.updateEditorBorderColor();
|
|
4005
4145
|
done();
|
|
4006
|
-
this.showStatus(`Model: ${model.id}`);
|
|
4146
|
+
this.showStatus(persist ? `Default model: ${model.provider}/${model.id}` : `Model: ${model.id}`);
|
|
4007
4147
|
void this.maybeWarnAboutAnthropicSubscriptionAuth(model);
|
|
4008
4148
|
this.checkDaxnutsEasterEgg(model);
|
|
4009
4149
|
}
|
|
@@ -4011,10 +4151,13 @@ export class InteractiveMode {
|
|
|
4011
4151
|
done();
|
|
4012
4152
|
this.showError(error instanceof Error ? error.message : String(error));
|
|
4013
4153
|
}
|
|
4014
|
-
}
|
|
4154
|
+
};
|
|
4155
|
+
const defaultProvider = this.settingsManager.getDefaultProvider();
|
|
4156
|
+
const defaultModel = this.settingsManager.getDefaultModel();
|
|
4157
|
+
const selector = new ModelSelectorComponent(this.ui, this.session.model, this.session.modelRuntime, this.session.scopedModels, (model) => selectModel(model, false), () => {
|
|
4015
4158
|
done();
|
|
4016
4159
|
this.ui.requestRender();
|
|
4017
|
-
}, initialSearchInput);
|
|
4160
|
+
}, initialSearchInput, (model) => selectModel(model, true), defaultProvider && defaultModel ? { provider: defaultProvider, id: defaultModel } : undefined);
|
|
4018
4161
|
return { component: selector, focus: selector, dispose: () => selector.dispose() };
|
|
4019
4162
|
});
|
|
4020
4163
|
}
|
|
@@ -4570,7 +4713,11 @@ export class InteractiveMode {
|
|
|
4570
4713
|
if (isUnknownModel(previousModel)) {
|
|
4571
4714
|
const availableModels = this.session.modelRuntime.getAvailableSnapshot();
|
|
4572
4715
|
const providerModels = availableModels.filter((model) => model.provider === providerId);
|
|
4573
|
-
|
|
4716
|
+
// Matches LLAMA_PROVIDER_ID from extensions/llama/provider.ts; kept inline to avoid coupling interactive mode to the built-in extension.
|
|
4717
|
+
if (providerId === "llama.cpp") {
|
|
4718
|
+
selectionError = llamaCppPostLoginGuidance(actionLabel, providerModels.length);
|
|
4719
|
+
}
|
|
4720
|
+
else if (!hasDefaultModelProvider(providerId)) {
|
|
4574
4721
|
selectionError = `${actionLabel}, but no default model is configured for provider "${providerId}". Use /model to select a model.`;
|
|
4575
4722
|
}
|
|
4576
4723
|
else if (providerModels.length === 0) {
|
|
@@ -4584,7 +4731,7 @@ export class InteractiveMode {
|
|
|
4584
4731
|
}
|
|
4585
4732
|
else {
|
|
4586
4733
|
try {
|
|
4587
|
-
await this.session.setModel(selectedModel);
|
|
4734
|
+
await this.session.setModel(selectedModel, { persist: true });
|
|
4588
4735
|
}
|
|
4589
4736
|
catch (error) {
|
|
4590
4737
|
selectedModel = undefined;
|
|
@@ -4954,91 +5101,14 @@ export class InteractiveMode {
|
|
|
4954
5101
|
}
|
|
4955
5102
|
}
|
|
4956
5103
|
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
|
-
}
|
|
5104
|
+
await shareSession({
|
|
5105
|
+
session: this.session,
|
|
5106
|
+
ui: this.ui,
|
|
5107
|
+
editorContainer: this.editorContainer,
|
|
5108
|
+
editor: this.editor,
|
|
5109
|
+
showStatus: (message) => this.showStatus(message),
|
|
5110
|
+
showError: (message) => this.showError(message),
|
|
5111
|
+
});
|
|
5042
5112
|
}
|
|
5043
5113
|
async handleCopyCommand(options = {}) {
|
|
5044
5114
|
const text = this.session.getLastAssistantText();
|