@averyyy/pi-coding-agent 0.84.2-piclient.3 → 0.84.4-piclient.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +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-B2RCCN5N.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-AP7VCR6I.js +1633 -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-LRBSW3NQ.js +11 -0
- package/dist/bundle/chunks/chunk-MNAIPA3J.js +2 -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/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-MJHX7NXI.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-CP4VKB27.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 +27 -9
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +150 -58
- 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 +8 -1
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +9 -4
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +42 -22
- 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/exec.d.ts.map +1 -1
- package/dist/core/exec.js +3 -1
- package/dist/core/exec.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/index.d.ts +1 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -0
- package/dist/core/index.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-client-cli-adapter.d.ts +11 -0
- package/dist/core/pi-client-cli-adapter.d.ts.map +1 -0
- package/dist/core/pi-client-cli-adapter.js +91 -0
- package/dist/core/pi-client-cli-adapter.js.map +1 -0
- 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 +13 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +30 -14
- 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 +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- 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 +22 -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/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +2 -1
- package/dist/modes/interactive/components/bash-execution.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 +17 -12
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +244 -250
- 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/child-process.d.ts.map +1 -1
- package/dist/utils/child-process.js +8 -3
- package/dist/utils/child-process.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 +27 -11
- 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/dist/utils/version-check.d.ts.map +1 -1
- package/dist/utils/version-check.js +2 -1
- package/dist/utils/version-check.js.map +1 -1
- 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/package.json +12 -14
|
@@ -7,20 +7,22 @@ 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";
|
|
21
|
+
import { createCompactionSummaryMessage } from "../../core/messages.js";
|
|
20
22
|
import { defaultModelPerProvider, findExactModelReferenceMatch, resolveModelScopeFromModels, } from "../../core/model-resolver.js";
|
|
21
23
|
import { CredentialSynchronizationError } from "../../core/model-runtime.js";
|
|
22
24
|
import { DefaultPackageManager } from "../../core/package-manager.js";
|
|
23
|
-
import {
|
|
25
|
+
import { getCliBinName } from "../../core/pi-client-cli-adapter.js";
|
|
24
26
|
import { formatMissingSessionCwdPrompt, MissingSessionCwdError } from "../../core/session-cwd.js";
|
|
25
27
|
import { SessionManager, sessionEntryToContextMessages } from "../../core/session-manager.js";
|
|
26
28
|
import { BUILTIN_SLASH_COMMANDS } from "../../core/slash-commands.js";
|
|
@@ -35,12 +37,12 @@ import { openBrowser } from "../../utils/open-browser.js";
|
|
|
35
37
|
import { getCwdRelativePath } from "../../utils/paths.js";
|
|
36
38
|
import { getPiUserAgent } from "../../utils/pi-user-agent.js";
|
|
37
39
|
import { killTrackedDetachedChildren } from "../../utils/shell.js";
|
|
40
|
+
import { loadAllHighlightLanguages } from "../../utils/syntax-highlight.js";
|
|
38
41
|
import { ensureTool } from "../../utils/tools-manager.js";
|
|
39
42
|
import { checkForNewPiVersion } from "../../utils/version-check.js";
|
|
40
43
|
import { ArminComponent } from "./components/armin.js";
|
|
41
44
|
import { AssistantMessageComponent } from "./components/assistant-message.js";
|
|
42
45
|
import { BashExecutionComponent } from "./components/bash-execution.js";
|
|
43
|
-
import { BorderedLoader } from "./components/bordered-loader.js";
|
|
44
46
|
import { BranchSummaryMessageComponent } from "./components/branch-summary-message.js";
|
|
45
47
|
import { CompactionSummaryMessageComponent } from "./components/compaction-summary-message.js";
|
|
46
48
|
import { CustomEditor } from "./components/custom-editor.js";
|
|
@@ -63,6 +65,7 @@ import { SessionSelectorComponent } from "./components/session-selector.js";
|
|
|
63
65
|
import { SettingsSelectorComponent } from "./components/settings-selector.js";
|
|
64
66
|
import { SkillInvocationMessageComponent } from "./components/skill-invocation-message.js";
|
|
65
67
|
import { BranchSummaryStatusIndicator, CompactionStatusIndicator, IdleStatus, RetryStatusIndicator, WorkingStatusIndicator, } from "./components/status-indicator.js";
|
|
68
|
+
import { ThinkingSelectorComponent } from "./components/thinking-selector.js";
|
|
66
69
|
import { ToolExecutionComponent } from "./components/tool-execution.js";
|
|
67
70
|
import { TreeSelectorComponent } from "./components/tree-selector.js";
|
|
68
71
|
import { TrustSelectorComponent } from "./components/trust-selector.js";
|
|
@@ -71,9 +74,9 @@ import { UserMessageSelectorComponent } from "./components/user-message-selector
|
|
|
71
74
|
import { editInExternalEditor } from "./external-editor.js";
|
|
72
75
|
import { refreshModelCatalogs } from "./model-catalog-refresh.js";
|
|
73
76
|
import { getModelSearchText } from "./model-search.js";
|
|
77
|
+
import { shareSession } from "./session-share.js";
|
|
74
78
|
import { getAvailableThemes, getAvailableThemesWithPaths, getEditorTheme, getMarkdownTheme, getThemeByName, onThemeChange, setRegisteredThemes, stopThemeWatcher, Theme, theme, } from "./theme/theme.js";
|
|
75
79
|
import { InteractiveThemeController } from "./theme/theme-controller.js";
|
|
76
|
-
const TRANSCRIPT_LAZY_LOAD_BATCH_SIZE = 20;
|
|
77
80
|
function isExpandable(obj) {
|
|
78
81
|
return typeof obj === "object" && obj !== null && "setExpanded" in obj && typeof obj.setExpanded === "function";
|
|
79
82
|
}
|
|
@@ -92,6 +95,9 @@ class ExpandableText extends Text {
|
|
|
92
95
|
function isCustomSessionEntry(item) {
|
|
93
96
|
return "type" in item && item.type === "custom";
|
|
94
97
|
}
|
|
98
|
+
function isCompactionCostNotice(item) {
|
|
99
|
+
return "type" in item && item.type === "compaction_cost";
|
|
100
|
+
}
|
|
95
101
|
const DEAD_TERMINAL_ERROR_CODES = new Set(["EIO", "EPIPE", "ENOTCONN"]);
|
|
96
102
|
function isDeadTerminalError(error) {
|
|
97
103
|
if (!error || typeof error !== "object" || !("code" in error)) {
|
|
@@ -121,7 +127,7 @@ export function formatResumeCommand(sessionManager) {
|
|
|
121
127
|
const sessionFile = sessionManager.getSessionFile();
|
|
122
128
|
if (!sessionFile || !fs.existsSync(sessionFile))
|
|
123
129
|
return undefined;
|
|
124
|
-
const args = [
|
|
130
|
+
const args = [getCliBinName()];
|
|
125
131
|
if (!sessionManager.usesDefaultSessionDir()) {
|
|
126
132
|
args.push("--session-dir", quoteIfNeeded(sessionManager.getSessionDir()));
|
|
127
133
|
}
|
|
@@ -131,6 +137,11 @@ export function formatResumeCommand(sessionManager) {
|
|
|
131
137
|
function hasDefaultModelProvider(providerId) {
|
|
132
138
|
return providerId in defaultModelPerProvider;
|
|
133
139
|
}
|
|
140
|
+
function llamaCppPostLoginGuidance(actionLabel, loadedModelCount) {
|
|
141
|
+
return loadedModelCount === 0
|
|
142
|
+
? `${actionLabel}. No llama.cpp models are loaded. Use /llama to load a model, then /model to select it.`
|
|
143
|
+
: `${actionLabel}. Use /model to select a loaded llama.cpp model, or /llama to manage models.`;
|
|
144
|
+
}
|
|
134
145
|
const AUTH_TYPE_ORDER = { oauth: 0, api_key: 1 };
|
|
135
146
|
function createFuzzyAutocompleteItems(items, prefix, getSearchText, toAutocompleteItem) {
|
|
136
147
|
const filtered = fuzzyFilter(items, prefix, getSearchText);
|
|
@@ -177,6 +188,7 @@ export function createInteractiveTui(options) {
|
|
|
177
188
|
searchCurrentMatchStyle: (text) => theme.bold(theme.inverse(styleSearchMatch(text))),
|
|
178
189
|
openUrl: openBrowser,
|
|
179
190
|
onRightClickPaste: options.onRightClickPaste,
|
|
191
|
+
copyOnSelect: options.fullscreenCopyOnSelect,
|
|
180
192
|
copySelection: async (text) => {
|
|
181
193
|
try {
|
|
182
194
|
await copyToClipboard(text);
|
|
@@ -230,11 +242,6 @@ export class InteractiveMode {
|
|
|
230
242
|
chatContainer;
|
|
231
243
|
documentContainer;
|
|
232
244
|
transcriptScrollView;
|
|
233
|
-
transcriptLazyEntries = [];
|
|
234
|
-
loadedTranscriptEntryIds = new Set();
|
|
235
|
-
transcriptWindowInitialized = false;
|
|
236
|
-
transcriptLatestCompactionId;
|
|
237
|
-
loadingEarlierTranscript = false;
|
|
238
245
|
fullscreenLayoutRoot;
|
|
239
246
|
pendingMessagesContainer;
|
|
240
247
|
statusContainer;
|
|
@@ -345,6 +352,7 @@ export class InteractiveMode {
|
|
|
345
352
|
}
|
|
346
353
|
constructor(runtimeHost, options = {}) {
|
|
347
354
|
this.runtimeHost = runtimeHost;
|
|
355
|
+
setCapabilityOverrides(this.settingsManager.getTerminalCapabilityOverrides());
|
|
348
356
|
const tuiMode = options.tuiMode ?? this.settingsManager.getTuiMode();
|
|
349
357
|
this.options = { ...options, tuiMode };
|
|
350
358
|
this.autoTrustOnReloadCwd = options.autoTrustOnReloadCwd;
|
|
@@ -361,6 +369,7 @@ export class InteractiveMode {
|
|
|
361
369
|
showHardwareCursor: this.settingsManager.getShowHardwareCursor(),
|
|
362
370
|
logDirectory: getAgentDir(),
|
|
363
371
|
onRightClickPaste: this.onRightClickPaste,
|
|
372
|
+
fullscreenCopyOnSelect: this.settingsManager.getFullscreenCopyOnSelect(),
|
|
364
373
|
});
|
|
365
374
|
this.ui = createInteractiveTuiReference(() => this.renderer);
|
|
366
375
|
this.ui.setClearOnShrink(this.settingsManager.getClearOnShrink());
|
|
@@ -471,6 +480,15 @@ export class InteractiveMode {
|
|
|
471
480
|
}));
|
|
472
481
|
};
|
|
473
482
|
}
|
|
483
|
+
const thinkingCommand = slashCommands.find((command) => command.name === "thinking");
|
|
484
|
+
if (thinkingCommand) {
|
|
485
|
+
thinkingCommand.getArgumentCompletions = (prefix) => {
|
|
486
|
+
return createFuzzyAutocompleteItems(this.session.getAvailableThinkingLevels(), prefix, (level) => level, (level) => ({
|
|
487
|
+
value: level,
|
|
488
|
+
label: level,
|
|
489
|
+
}));
|
|
490
|
+
};
|
|
491
|
+
}
|
|
474
492
|
const loginCommand = slashCommands.find((command) => command.name === "login");
|
|
475
493
|
if (loginCommand) {
|
|
476
494
|
loginCommand.getArgumentCompletions = (prefix) => {
|
|
@@ -599,6 +617,7 @@ export class InteractiveMode {
|
|
|
599
617
|
logDirectory: getAgentDir(),
|
|
600
618
|
terminal,
|
|
601
619
|
onRightClickPaste: this.onRightClickPaste,
|
|
620
|
+
fullscreenCopyOnSelect: this.settingsManager.getFullscreenCopyOnSelect(),
|
|
602
621
|
});
|
|
603
622
|
nextUi.setClearOnShrink(clearOnShrink);
|
|
604
623
|
nextUi.onDebug = onDebug;
|
|
@@ -647,7 +666,6 @@ export class InteractiveMode {
|
|
|
647
666
|
follow: "end",
|
|
648
667
|
primary: true,
|
|
649
668
|
overscroll: "chain",
|
|
650
|
-
onScroll: (scrollTop) => this.handleTranscriptScroll(scrollTop),
|
|
651
669
|
scrollbar: this.settingsManager.getFullscreenScrollbar(),
|
|
652
670
|
scrollbarStyle: (text) => theme.bg("scrollbarThumb", text),
|
|
653
671
|
});
|
|
@@ -756,6 +774,14 @@ export class InteractiveMode {
|
|
|
756
774
|
});
|
|
757
775
|
// Initialize available provider count for footer display
|
|
758
776
|
await this.updateAvailableProviderCount();
|
|
777
|
+
// Flush the completed startup state before loading the remaining syntax grammars.
|
|
778
|
+
this.ui.renderNow();
|
|
779
|
+
void loadAllHighlightLanguages().then(() => {
|
|
780
|
+
if (!this.isInitialized)
|
|
781
|
+
return;
|
|
782
|
+
this.ui.invalidate();
|
|
783
|
+
this.ui.requestRender();
|
|
784
|
+
});
|
|
759
785
|
}
|
|
760
786
|
/**
|
|
761
787
|
* Update terminal title with session name and cwd.
|
|
@@ -785,7 +811,7 @@ export class InteractiveMode {
|
|
|
785
811
|
.finally(() => clearTimeout(timeout));
|
|
786
812
|
}
|
|
787
813
|
// Start version check asynchronously
|
|
788
|
-
checkForNewPiVersion(this.version).then((newRelease) => {
|
|
814
|
+
checkForNewPiVersion(process.env.PI_CLIENT_VERSION ?? this.version).then((newRelease) => {
|
|
789
815
|
if (newRelease) {
|
|
790
816
|
this.showNewVersionNotification(newRelease);
|
|
791
817
|
}
|
|
@@ -811,7 +837,18 @@ export class InteractiveMode {
|
|
|
811
837
|
}
|
|
812
838
|
});
|
|
813
839
|
// Show startup warnings
|
|
814
|
-
const { migratedProviders, modelFallbackMessage, initialMessage, initialImages, initialMessages } = this.options;
|
|
840
|
+
const { migratedProviders, startupDiagnostics, modelFallbackMessage, initialMessage, initialImages, initialMessages, } = this.options;
|
|
841
|
+
for (const diagnostic of startupDiagnostics ?? []) {
|
|
842
|
+
if (diagnostic.type === "error") {
|
|
843
|
+
this.showError(diagnostic.message);
|
|
844
|
+
}
|
|
845
|
+
else if (diagnostic.type === "warning") {
|
|
846
|
+
this.showWarning(diagnostic.message);
|
|
847
|
+
}
|
|
848
|
+
else {
|
|
849
|
+
this.showStatus(diagnostic.message);
|
|
850
|
+
}
|
|
851
|
+
}
|
|
815
852
|
if (migratedProviders && migratedProviders.length > 0) {
|
|
816
853
|
this.showWarning(`Migrated credentials to auth.json: ${migratedProviders.join(", ")}`);
|
|
817
854
|
}
|
|
@@ -966,14 +1003,13 @@ export class InteractiveMode {
|
|
|
966
1003
|
// Extension System
|
|
967
1004
|
// =========================================================================
|
|
968
1005
|
formatDisplayPath(p) {
|
|
969
|
-
const
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
return `~/${normalizedPath.slice(normalizedHome.length + 1)}`;
|
|
1006
|
+
const home = os.homedir();
|
|
1007
|
+
let result = p;
|
|
1008
|
+
// Replace home directory with ~
|
|
1009
|
+
if (result.startsWith(home)) {
|
|
1010
|
+
result = `~${result.slice(home.length)}`;
|
|
975
1011
|
}
|
|
976
|
-
return
|
|
1012
|
+
return result;
|
|
977
1013
|
}
|
|
978
1014
|
formatExtensionDisplayPath(path) {
|
|
979
1015
|
let result = this.formatDisplayPath(path);
|
|
@@ -1490,8 +1526,12 @@ export class InteractiveMode {
|
|
|
1490
1526
|
this.transcriptScrollView?.setScrollbar(this.settingsManager.getFullscreenScrollbar());
|
|
1491
1527
|
}
|
|
1492
1528
|
applyRuntimeSettings() {
|
|
1529
|
+
setCapabilityOverrides(this.settingsManager.getTerminalCapabilityOverrides());
|
|
1493
1530
|
configureHttpDispatcher(this.settingsManager.getHttpIdleTimeoutMs());
|
|
1494
1531
|
this.applyFullscreenScrollbarSetting();
|
|
1532
|
+
if (this.renderer instanceof TuiAltScreen) {
|
|
1533
|
+
this.renderer.setCopyOnSelect(this.settingsManager.getFullscreenCopyOnSelect());
|
|
1534
|
+
}
|
|
1495
1535
|
this.footer.setSession(this.session);
|
|
1496
1536
|
this.footer.setAutoCompactEnabled(this.session.autoCompactionEnabled);
|
|
1497
1537
|
this.footerDataProvider.setCwd(this.sessionManager.getCwd());
|
|
@@ -1641,6 +1681,9 @@ export class InteractiveMode {
|
|
|
1641
1681
|
this.statusContainer.addChild(this.idleStatus);
|
|
1642
1682
|
}
|
|
1643
1683
|
}
|
|
1684
|
+
showWorkingStatusIndicator() {
|
|
1685
|
+
this.showStatusIndicator(new WorkingStatusIndicator(this.ui, this.workingMessage ?? this.defaultWorkingMessage, this.workingIndicatorOptions));
|
|
1686
|
+
}
|
|
1644
1687
|
setWorkingVisible(visible) {
|
|
1645
1688
|
this.workingVisible = visible;
|
|
1646
1689
|
if (!visible) {
|
|
@@ -1649,7 +1692,7 @@ export class InteractiveMode {
|
|
|
1649
1692
|
return;
|
|
1650
1693
|
}
|
|
1651
1694
|
if (this.session.isStreaming && this.activeStatusIndicator?.kind !== "working") {
|
|
1652
|
-
this.
|
|
1695
|
+
this.showWorkingStatusIndicator();
|
|
1653
1696
|
}
|
|
1654
1697
|
this.ui.requestRender();
|
|
1655
1698
|
}
|
|
@@ -1660,15 +1703,6 @@ export class InteractiveMode {
|
|
|
1660
1703
|
}
|
|
1661
1704
|
this.ui.requestRender();
|
|
1662
1705
|
}
|
|
1663
|
-
restoreWorkingIndicator() {
|
|
1664
|
-
if (!this.session.isStreaming || !this.workingVisible) {
|
|
1665
|
-
return;
|
|
1666
|
-
}
|
|
1667
|
-
if (this.settingsManager.getShowTerminalProgress()) {
|
|
1668
|
-
this.ui.terminal.setProgress(true);
|
|
1669
|
-
}
|
|
1670
|
-
this.showStatusIndicator(new WorkingStatusIndicator(this.ui, this.workingMessage ?? this.defaultWorkingMessage, this.workingIndicatorOptions));
|
|
1671
|
-
}
|
|
1672
1706
|
setHiddenThinkingLabel(label) {
|
|
1673
1707
|
this.hiddenThinkingLabel = label ?? this.defaultHiddenThinkingLabel;
|
|
1674
1708
|
for (const child of this.chatContainer.children) {
|
|
@@ -2278,14 +2312,13 @@ export class InteractiveMode {
|
|
|
2278
2312
|
this.defaultEditor.onAction("app.tools.expand", () => this.toggleToolOutputExpansion());
|
|
2279
2313
|
this.defaultEditor.onAction("app.thinking.toggle", () => this.toggleThinkingBlockVisibility());
|
|
2280
2314
|
this.defaultEditor.onAction("app.editor.external", () => void this.handleOpenExternalEditor());
|
|
2281
|
-
this.defaultEditor.onAction("app.message.copy", () => void this.handleCopyCommand({ flashConfirmation: true }));
|
|
2315
|
+
this.defaultEditor.onAction("app.message.copy", () => void this.handleCopyCommand({ flashConfirmation: true, preferSelection: true }));
|
|
2282
2316
|
this.defaultEditor.onAction("app.message.followUp", () => this.handleFollowUp());
|
|
2283
2317
|
this.defaultEditor.onAction("app.message.dequeue", () => this.handleDequeue());
|
|
2284
2318
|
this.defaultEditor.onAction("app.session.new", () => this.handleClearCommand());
|
|
2285
2319
|
this.defaultEditor.onAction("app.session.tree", () => this.showTreeSelector());
|
|
2286
2320
|
this.defaultEditor.onAction("app.session.fork", () => this.showUserMessageSelector());
|
|
2287
2321
|
this.defaultEditor.onAction("app.session.resume", () => this.showSessionSelector());
|
|
2288
|
-
this.defaultEditor.onAction("app.session.loadEarlier", () => this.loadEarlierTranscript());
|
|
2289
2322
|
this.defaultEditor.onChange = (text) => {
|
|
2290
2323
|
const wasBashMode = this.isBashMode;
|
|
2291
2324
|
this.isBashMode = text.trimStart().startsWith("!");
|
|
@@ -2364,6 +2397,12 @@ export class InteractiveMode {
|
|
|
2364
2397
|
await this.handleModelCommand(searchTerm);
|
|
2365
2398
|
return;
|
|
2366
2399
|
}
|
|
2400
|
+
if (text === "/thinking" || text.startsWith("/thinking ")) {
|
|
2401
|
+
const searchTerm = text.startsWith("/thinking ") ? text.slice(10).trim() : undefined;
|
|
2402
|
+
this.editor.setText("");
|
|
2403
|
+
this.handleThinkingCommand(searchTerm);
|
|
2404
|
+
return;
|
|
2405
|
+
}
|
|
2367
2406
|
if (text === "/export" || text.startsWith("/export ")) {
|
|
2368
2407
|
await this.handleExportCommand(text);
|
|
2369
2408
|
this.editor.setText("");
|
|
@@ -2451,12 +2490,6 @@ export class InteractiveMode {
|
|
|
2451
2490
|
await this.handleReloadCommand();
|
|
2452
2491
|
return;
|
|
2453
2492
|
}
|
|
2454
|
-
const pendingPiClientUpdate = readPiClientUpdateMarker();
|
|
2455
|
-
if (pendingPiClientUpdate) {
|
|
2456
|
-
this.showWarning(`pi-client ${pendingPiClientUpdate.version} is installed. Run /reload to continue this session with the new version.`);
|
|
2457
|
-
this.editor.setText(text);
|
|
2458
|
-
return;
|
|
2459
|
-
}
|
|
2460
2493
|
if (text === "/debug") {
|
|
2461
2494
|
this.handleDebugCommand();
|
|
2462
2495
|
this.editor.setText("");
|
|
@@ -2546,17 +2579,21 @@ export class InteractiveMode {
|
|
|
2546
2579
|
switch (event.type) {
|
|
2547
2580
|
case "agent_start":
|
|
2548
2581
|
this.pendingTools.clear();
|
|
2549
|
-
if (this.settingsManager.getShowTerminalProgress()) {
|
|
2550
|
-
this.ui.terminal.setProgress(true);
|
|
2551
|
-
}
|
|
2552
2582
|
// Restore main escape handler if retry handler is still active
|
|
2553
2583
|
// (retry success event fires later, but we need main handler now)
|
|
2554
2584
|
if (this.retryEscapeHandler) {
|
|
2555
2585
|
this.defaultEditor.onEscape = this.retryEscapeHandler;
|
|
2556
2586
|
this.retryEscapeHandler = undefined;
|
|
2557
2587
|
}
|
|
2588
|
+
break;
|
|
2589
|
+
case "turn_start":
|
|
2590
|
+
if (this.settingsManager.getShowTerminalProgress()) {
|
|
2591
|
+
this.ui.terminal.setProgress(true);
|
|
2592
|
+
}
|
|
2558
2593
|
if (this.workingVisible) {
|
|
2559
|
-
|
|
2594
|
+
if (this.activeStatusIndicator?.kind !== "working") {
|
|
2595
|
+
this.showWorkingStatusIndicator();
|
|
2596
|
+
}
|
|
2560
2597
|
}
|
|
2561
2598
|
else {
|
|
2562
2599
|
this.clearStatusIndicator();
|
|
@@ -2702,6 +2739,10 @@ export class InteractiveMode {
|
|
|
2702
2739
|
break;
|
|
2703
2740
|
}
|
|
2704
2741
|
case "agent_end":
|
|
2742
|
+
if (this.settingsManager.getShowTerminalProgress()) {
|
|
2743
|
+
this.ui.terminal.setProgress(false);
|
|
2744
|
+
}
|
|
2745
|
+
this.clearStatusIndicator("working");
|
|
2705
2746
|
if (this.streamingComponent) {
|
|
2706
2747
|
this.chatContainer.removeChild(this.streamingComponent);
|
|
2707
2748
|
this.streamingComponent = undefined;
|
|
@@ -2711,12 +2752,7 @@ export class InteractiveMode {
|
|
|
2711
2752
|
this.ui.requestRender();
|
|
2712
2753
|
break;
|
|
2713
2754
|
case "agent_settled":
|
|
2714
|
-
if (this.settingsManager.getShowTerminalProgress()) {
|
|
2715
|
-
this.ui.terminal.setProgress(false);
|
|
2716
|
-
}
|
|
2717
|
-
this.clearStatusIndicator("working");
|
|
2718
2755
|
await this.checkShutdownRequested();
|
|
2719
|
-
this.ui.requestRender();
|
|
2720
2756
|
break;
|
|
2721
2757
|
case "compaction_start": {
|
|
2722
2758
|
if (this.settingsManager.getShowTerminalProgress()) {
|
|
@@ -2749,7 +2785,21 @@ export class InteractiveMode {
|
|
|
2749
2785
|
}
|
|
2750
2786
|
}
|
|
2751
2787
|
else if (event.result) {
|
|
2752
|
-
this.
|
|
2788
|
+
const entries = this.sessionManager.buildContextEntries();
|
|
2789
|
+
if (entries[0]?.type !== "compaction") {
|
|
2790
|
+
throw new Error("Completed compaction is missing from the session context");
|
|
2791
|
+
}
|
|
2792
|
+
this.chatContainer.clear();
|
|
2793
|
+
// The latest compaction is prepended for model context; append it below at its chronological position.
|
|
2794
|
+
this.renderSessionEntries(entries.slice(1));
|
|
2795
|
+
this.addMessageToChat(createCompactionSummaryMessage(event.result.summary, event.result.tokensBefore, new Date().toISOString()));
|
|
2796
|
+
if (event.result.usage) {
|
|
2797
|
+
this.addCompactionCostNotice({
|
|
2798
|
+
type: "compaction_cost",
|
|
2799
|
+
kind: "compaction",
|
|
2800
|
+
usage: event.result.usage,
|
|
2801
|
+
});
|
|
2802
|
+
}
|
|
2753
2803
|
this.footer.invalidate();
|
|
2754
2804
|
}
|
|
2755
2805
|
else if (event.errorMessage) {
|
|
@@ -2761,7 +2811,6 @@ export class InteractiveMode {
|
|
|
2761
2811
|
this.chatContainer.addChild(new Text(theme.fg("error", event.errorMessage), 1, 0));
|
|
2762
2812
|
}
|
|
2763
2813
|
}
|
|
2764
|
-
this.restoreWorkingIndicator();
|
|
2765
2814
|
void this.flushCompactionQueue({ willRetry: event.willRetry });
|
|
2766
2815
|
this.ui.requestRender();
|
|
2767
2816
|
break;
|
|
@@ -2787,7 +2836,6 @@ export class InteractiveMode {
|
|
|
2787
2836
|
if (!event.success) {
|
|
2788
2837
|
this.showError(`Retry failed after ${event.attempt} attempts: ${event.finalError || "Unknown error"}`);
|
|
2789
2838
|
}
|
|
2790
|
-
this.restoreWorkingIndicator();
|
|
2791
2839
|
this.ui.requestRender();
|
|
2792
2840
|
break;
|
|
2793
2841
|
}
|
|
@@ -2973,6 +3021,10 @@ export class InteractiveMode {
|
|
|
2973
3021
|
this.addCustomEntryToChat(item);
|
|
2974
3022
|
continue;
|
|
2975
3023
|
}
|
|
3024
|
+
if (isCompactionCostNotice(item)) {
|
|
3025
|
+
this.addCompactionCostNotice(item);
|
|
3026
|
+
continue;
|
|
3027
|
+
}
|
|
2976
3028
|
const message = item;
|
|
2977
3029
|
// Assistant messages need special handling for tool calls
|
|
2978
3030
|
if (message.role === "assistant") {
|
|
@@ -3030,8 +3082,8 @@ export class InteractiveMode {
|
|
|
3030
3082
|
this.ui.requestRender();
|
|
3031
3083
|
}
|
|
3032
3084
|
/**
|
|
3033
|
-
* Render session entries to chat. Used for initial load and
|
|
3034
|
-
* @param entries
|
|
3085
|
+
* Render session entries to chat. Used for initial load and rebuild after compaction.
|
|
3086
|
+
* @param entries Compaction-aware session entries to render
|
|
3035
3087
|
* @param options.updateFooter Update footer state
|
|
3036
3088
|
* @param options.populateHistory Add user messages to editor history
|
|
3037
3089
|
*/
|
|
@@ -3040,10 +3092,28 @@ export class InteractiveMode {
|
|
|
3040
3092
|
if (entry.type === "custom") {
|
|
3041
3093
|
return [entry];
|
|
3042
3094
|
}
|
|
3043
|
-
|
|
3095
|
+
const messages = sessionEntryToContextMessages(entry);
|
|
3096
|
+
if ((entry.type === "compaction" || entry.type === "branch_summary") && entry.usage && messages.length > 0) {
|
|
3097
|
+
return [...messages, { type: "compaction_cost", kind: entry.type, usage: entry.usage }];
|
|
3098
|
+
}
|
|
3099
|
+
return messages;
|
|
3044
3100
|
});
|
|
3045
3101
|
this.renderSessionItems(items, options);
|
|
3046
3102
|
}
|
|
3103
|
+
/**
|
|
3104
|
+
* Render billing usage for a compaction or branch summary. The notice is derived
|
|
3105
|
+
* from persisted summary usage and is not stored as a separate session entry.
|
|
3106
|
+
*/
|
|
3107
|
+
addCompactionCostNotice(notice) {
|
|
3108
|
+
if (!this.settingsManager.getShowCacheMissNotices())
|
|
3109
|
+
return;
|
|
3110
|
+
const { usage } = notice;
|
|
3111
|
+
const tokens = usage.input + usage.output + usage.cacheRead + usage.cacheWrite;
|
|
3112
|
+
const cost = usage.cost.total >= 0.01 ? ` (~$${usage.cost.total.toFixed(2)})` : "";
|
|
3113
|
+
const label = notice.kind === "compaction" ? "Compaction" : "Branch summary";
|
|
3114
|
+
this.chatContainer.addChild(new Spacer(1));
|
|
3115
|
+
this.chatContainer.addChild(new Text(theme.fg("warning", `${label}: ${formatTokens(tokens)} tokens billed${cost}`), 1, 0));
|
|
3116
|
+
}
|
|
3047
3117
|
/**
|
|
3048
3118
|
* Show a transcript notice when a completed assistant message paid for a
|
|
3049
3119
|
* significant cache miss. Only states observable facts: the miss itself,
|
|
@@ -3073,66 +3143,9 @@ export class InteractiveMode {
|
|
|
3073
3143
|
this.chatContainer.addChild(new Spacer(1));
|
|
3074
3144
|
this.chatContainer.addChild(new Text(text, 1, 0));
|
|
3075
3145
|
}
|
|
3076
|
-
getTranscriptEntriesForRender(reset = false) {
|
|
3077
|
-
const branch = this.sessionManager.getBranch();
|
|
3078
|
-
const contextEntries = this.sessionManager.buildContextEntries();
|
|
3079
|
-
let latestCompactionId;
|
|
3080
|
-
for (let index = branch.length - 1; index >= 0; index--) {
|
|
3081
|
-
const entry = branch[index];
|
|
3082
|
-
if (entry?.type === "compaction") {
|
|
3083
|
-
latestCompactionId = entry.id;
|
|
3084
|
-
break;
|
|
3085
|
-
}
|
|
3086
|
-
}
|
|
3087
|
-
if (reset || (this.transcriptWindowInitialized && this.transcriptLatestCompactionId !== latestCompactionId)) {
|
|
3088
|
-
this.loadedTranscriptEntryIds.clear();
|
|
3089
|
-
}
|
|
3090
|
-
this.transcriptWindowInitialized = true;
|
|
3091
|
-
this.transcriptLatestCompactionId = latestCompactionId;
|
|
3092
|
-
const contextEntryIds = new Set(contextEntries.map((entry) => entry.id));
|
|
3093
|
-
const earlierEntries = branch.filter((entry) => !contextEntryIds.has(entry.id));
|
|
3094
|
-
const loadedEntries = earlierEntries.filter((entry) => this.loadedTranscriptEntryIds.has(entry.id));
|
|
3095
|
-
this.transcriptLazyEntries = earlierEntries.filter((entry) => !this.loadedTranscriptEntryIds.has(entry.id));
|
|
3096
|
-
return [...loadedEntries, ...contextEntries];
|
|
3097
|
-
}
|
|
3098
|
-
renderTranscriptEntries(entries, options = {}) {
|
|
3099
|
-
if (this.transcriptLazyEntries.length > 0) {
|
|
3100
|
-
const count = this.transcriptLazyEntries.length.toLocaleString();
|
|
3101
|
-
this.chatContainer.addChild(new Text(theme.fg("dim", `${count} earlier transcript entries hidden (${keyText("app.session.loadEarlier")} to load)`), 1, 0));
|
|
3102
|
-
this.chatContainer.addChild(new Spacer(1));
|
|
3103
|
-
}
|
|
3104
|
-
this.renderSessionEntries(entries, options);
|
|
3105
|
-
}
|
|
3106
|
-
handleTranscriptScroll(scrollTop) {
|
|
3107
|
-
if (scrollTop === 0) {
|
|
3108
|
-
this.loadEarlierTranscript();
|
|
3109
|
-
}
|
|
3110
|
-
}
|
|
3111
|
-
loadEarlierTranscript() {
|
|
3112
|
-
if (this.loadingEarlierTranscript || this.session.isStreaming || this.transcriptLazyEntries.length === 0) {
|
|
3113
|
-
return;
|
|
3114
|
-
}
|
|
3115
|
-
this.loadingEarlierTranscript = true;
|
|
3116
|
-
try {
|
|
3117
|
-
const firstLoadedIndex = Math.max(0, this.transcriptLazyEntries.length - TRANSCRIPT_LAZY_LOAD_BATCH_SIZE);
|
|
3118
|
-
const entriesToLoad = this.transcriptLazyEntries.slice(firstLoadedIndex);
|
|
3119
|
-
for (const entry of entriesToLoad) {
|
|
3120
|
-
this.loadedTranscriptEntryIds.add(entry.id);
|
|
3121
|
-
}
|
|
3122
|
-
this.rebuildChatFromMessages();
|
|
3123
|
-
const remaining = this.transcriptLazyEntries.length;
|
|
3124
|
-
this.showStatus(remaining > 0
|
|
3125
|
-
? `Loaded ${entriesToLoad.length} earlier transcript entries (${remaining} remaining)`
|
|
3126
|
-
: "Loaded the beginning of the transcript");
|
|
3127
|
-
this.ui.requestRender();
|
|
3128
|
-
}
|
|
3129
|
-
finally {
|
|
3130
|
-
this.loadingEarlierTranscript = false;
|
|
3131
|
-
}
|
|
3132
|
-
}
|
|
3133
3146
|
renderInitialMessages() {
|
|
3134
|
-
const entries = this.
|
|
3135
|
-
this.
|
|
3147
|
+
const entries = this.sessionManager.buildContextEntries();
|
|
3148
|
+
this.renderSessionEntries(entries, {
|
|
3136
3149
|
updateFooter: true,
|
|
3137
3150
|
populateHistory: true,
|
|
3138
3151
|
});
|
|
@@ -3168,7 +3181,7 @@ export class InteractiveMode {
|
|
|
3168
3181
|
}
|
|
3169
3182
|
rebuildChatFromMessages() {
|
|
3170
3183
|
this.chatContainer.clear();
|
|
3171
|
-
this.
|
|
3184
|
+
this.renderSessionEntries(this.sessionManager.buildContextEntries());
|
|
3172
3185
|
}
|
|
3173
3186
|
// =========================================================================
|
|
3174
3187
|
// Key handlers
|
|
@@ -3450,18 +3463,19 @@ export class InteractiveMode {
|
|
|
3450
3463
|
}
|
|
3451
3464
|
this.showStatus(`Tool output: ${expanded ? "expanded" : "collapsed"}`);
|
|
3452
3465
|
}
|
|
3466
|
+
/** Update rendered assistant messages without rebuilding live tool components. */
|
|
3467
|
+
updateThinkingBlockVisibility() {
|
|
3468
|
+
for (const child of this.chatContainer.children) {
|
|
3469
|
+
if (child instanceof AssistantMessageComponent) {
|
|
3470
|
+
child.setHideThinkingBlock(this.hideThinkingBlock);
|
|
3471
|
+
}
|
|
3472
|
+
}
|
|
3473
|
+
this.ui.requestRender();
|
|
3474
|
+
}
|
|
3453
3475
|
toggleThinkingBlockVisibility() {
|
|
3454
3476
|
this.hideThinkingBlock = !this.hideThinkingBlock;
|
|
3455
3477
|
this.settingsManager.setHideThinkingBlock(this.hideThinkingBlock);
|
|
3456
|
-
|
|
3457
|
-
this.chatContainer.clear();
|
|
3458
|
-
this.rebuildChatFromMessages();
|
|
3459
|
-
// If streaming, re-add the streaming component with updated visibility and re-render
|
|
3460
|
-
if (this.streamingComponent && this.streamingMessage) {
|
|
3461
|
-
this.streamingComponent.setHideThinkingBlock(this.hideThinkingBlock);
|
|
3462
|
-
this.streamingComponent.updateContent(this.streamingMessage);
|
|
3463
|
-
this.chatContainer.addChild(this.streamingComponent);
|
|
3464
|
-
}
|
|
3478
|
+
this.updateThinkingBlockVisibility();
|
|
3465
3479
|
this.showStatus(`Thinking blocks: ${this.hideThinkingBlock ? "hidden" : "visible"}`);
|
|
3466
3480
|
}
|
|
3467
3481
|
async handleOpenExternalEditor() {
|
|
@@ -3737,8 +3751,14 @@ export class InteractiveMode {
|
|
|
3737
3751
|
showSettingsSelector() {
|
|
3738
3752
|
this.showSelector((done) => {
|
|
3739
3753
|
let selector;
|
|
3754
|
+
const defaultProvider = this.settingsManager.getDefaultProvider();
|
|
3755
|
+
const defaultModelId = this.settingsManager.getDefaultModel();
|
|
3756
|
+
const defaultModel = defaultProvider && defaultModelId ? `${defaultProvider}/${defaultModelId}` : "not set";
|
|
3740
3757
|
selector = new SettingsSelectorComponent({
|
|
3741
3758
|
autoCompact: this.session.autoCompactionEnabled,
|
|
3759
|
+
defaultModel,
|
|
3760
|
+
currentModel: this.session.model,
|
|
3761
|
+
availableDefaultModels: this.session.modelRuntime.getAvailableSnapshot(),
|
|
3742
3762
|
showImages: this.settingsManager.getShowImages(),
|
|
3743
3763
|
imageWidthCells: this.settingsManager.getImageWidthCells(),
|
|
3744
3764
|
autoResizeImages: this.settingsManager.getImageAutoResize(),
|
|
@@ -3748,8 +3768,9 @@ export class InteractiveMode {
|
|
|
3748
3768
|
followUpMode: this.session.followUpMode,
|
|
3749
3769
|
transport: this.settingsManager.getTransport(),
|
|
3750
3770
|
httpIdleTimeoutMs: this.settingsManager.getHttpIdleTimeoutMs(),
|
|
3751
|
-
thinkingLevel: this.
|
|
3752
|
-
availableThinkingLevels:
|
|
3771
|
+
thinkingLevel: this.settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL,
|
|
3772
|
+
availableThinkingLevels: [...THINKING_LEVEL_OPTIONS],
|
|
3773
|
+
modelThinkingLevels: this.settingsManager.getAllModelThinkingLevels(),
|
|
3753
3774
|
currentTheme: this.themeController.getThemeSelection() || "dark",
|
|
3754
3775
|
terminalTheme: this.themeController.getTerminalTheme(),
|
|
3755
3776
|
availableThemes: getAvailableThemes(),
|
|
@@ -3771,6 +3792,7 @@ export class InteractiveMode {
|
|
|
3771
3792
|
tuiMode: this.ui.mode,
|
|
3772
3793
|
fullscreenExitOutput: this.settingsManager.getFullscreenExitOutput(),
|
|
3773
3794
|
fullscreenScrollbar: this.settingsManager.getFullscreenScrollbar(),
|
|
3795
|
+
fullscreenCopyOnSelect: this.settingsManager.getFullscreenCopyOnSelect(),
|
|
3774
3796
|
warnings: this.settingsManager.getWarnings(),
|
|
3775
3797
|
}, {
|
|
3776
3798
|
onAutoCompactChange: (enabled) => {
|
|
@@ -3818,10 +3840,26 @@ export class InteractiveMode {
|
|
|
3818
3840
|
configureHttpDispatcher(timeoutMs);
|
|
3819
3841
|
this.showStatus(`HTTP idle timeout: ${formatHttpIdleTimeoutMs(timeoutMs)}`);
|
|
3820
3842
|
},
|
|
3821
|
-
|
|
3822
|
-
this.
|
|
3823
|
-
|
|
3824
|
-
this.
|
|
3843
|
+
onModelThinkingLevelChange: (provider, modelId, level) => {
|
|
3844
|
+
this.settingsManager.setModelThinkingLevel(provider, modelId, level);
|
|
3845
|
+
// If the override is for the current model, apply it to the session too
|
|
3846
|
+
const current = this.session.model;
|
|
3847
|
+
if (current && current.provider === provider && current.id === modelId) {
|
|
3848
|
+
this.session.setThinkingLevel(level);
|
|
3849
|
+
this.footer.invalidate();
|
|
3850
|
+
this.updateEditorBorderColor();
|
|
3851
|
+
}
|
|
3852
|
+
},
|
|
3853
|
+
onModelThinkingLevelRemove: (provider, modelId) => {
|
|
3854
|
+
this.settingsManager.removeModelThinkingLevel(provider, modelId);
|
|
3855
|
+
// If the override was for the current model, revert to global default
|
|
3856
|
+
const current = this.session.model;
|
|
3857
|
+
if (current && current.provider === provider && current.id === modelId) {
|
|
3858
|
+
const globalDefault = this.settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL;
|
|
3859
|
+
this.session.setThinkingLevel(globalDefault);
|
|
3860
|
+
this.footer.invalidate();
|
|
3861
|
+
this.updateEditorBorderColor();
|
|
3862
|
+
}
|
|
3825
3863
|
},
|
|
3826
3864
|
onThemeChange: (themeSetting) => {
|
|
3827
3865
|
this.settingsManager.setTheme(themeSetting);
|
|
@@ -3831,13 +3869,7 @@ export class InteractiveMode {
|
|
|
3831
3869
|
onHideThinkingBlockChange: (hidden) => {
|
|
3832
3870
|
this.hideThinkingBlock = hidden;
|
|
3833
3871
|
this.settingsManager.setHideThinkingBlock(hidden);
|
|
3834
|
-
|
|
3835
|
-
if (child instanceof AssistantMessageComponent) {
|
|
3836
|
-
child.setHideThinkingBlock(hidden);
|
|
3837
|
-
}
|
|
3838
|
-
}
|
|
3839
|
-
this.chatContainer.clear();
|
|
3840
|
-
this.rebuildChatFromMessages();
|
|
3872
|
+
this.updateThinkingBlockVisibility();
|
|
3841
3873
|
},
|
|
3842
3874
|
onMermaidRenderingModeChange: (mode) => {
|
|
3843
3875
|
this.settingsManager.setMermaidRenderingMode(mode);
|
|
@@ -3931,6 +3963,11 @@ export class InteractiveMode {
|
|
|
3931
3963
|
this.settingsManager.setFullscreenScrollbar(mode);
|
|
3932
3964
|
this.applyFullscreenScrollbarSetting();
|
|
3933
3965
|
},
|
|
3966
|
+
onFullscreenCopyOnSelectChange: (enabled) => {
|
|
3967
|
+
this.settingsManager.setFullscreenCopyOnSelect(enabled);
|
|
3968
|
+
if (this.renderer instanceof TuiAltScreen)
|
|
3969
|
+
this.renderer.setCopyOnSelect(enabled);
|
|
3970
|
+
},
|
|
3934
3971
|
onWarningsChange: (warnings) => {
|
|
3935
3972
|
this.settingsManager.setWarnings(warnings);
|
|
3936
3973
|
},
|
|
@@ -3942,6 +3979,44 @@ export class InteractiveMode {
|
|
|
3942
3979
|
return { component: selector, focus: selector.getSettingsList() };
|
|
3943
3980
|
});
|
|
3944
3981
|
}
|
|
3982
|
+
handleThinkingCommand(searchTerm) {
|
|
3983
|
+
const availableLevels = this.session.getAvailableThinkingLevels();
|
|
3984
|
+
if (!searchTerm) {
|
|
3985
|
+
this.showThinkingSelector();
|
|
3986
|
+
return;
|
|
3987
|
+
}
|
|
3988
|
+
const normalized = searchTerm.trim().toLowerCase();
|
|
3989
|
+
const level = availableLevels.find((candidate) => candidate.toLowerCase() === normalized);
|
|
3990
|
+
if (!level) {
|
|
3991
|
+
this.showError(`Unknown thinking level "${searchTerm}". Available levels: ${availableLevels.join(", ")}.`);
|
|
3992
|
+
return;
|
|
3993
|
+
}
|
|
3994
|
+
this.selectThinkingLevel(level, false);
|
|
3995
|
+
}
|
|
3996
|
+
selectThinkingLevel(level, persist) {
|
|
3997
|
+
try {
|
|
3998
|
+
this.session.setThinkingLevel(level, { persist });
|
|
3999
|
+
this.footer.invalidate();
|
|
4000
|
+
this.updateEditorBorderColor();
|
|
4001
|
+
this.showStatus(persist ? `Default thinking level: ${level}` : `Thinking level: ${level}`);
|
|
4002
|
+
}
|
|
4003
|
+
catch (error) {
|
|
4004
|
+
this.showError(error instanceof Error ? error.message : String(error));
|
|
4005
|
+
}
|
|
4006
|
+
}
|
|
4007
|
+
showThinkingSelector() {
|
|
4008
|
+
this.showSelector((done) => {
|
|
4009
|
+
const selectLevel = (level, persist) => {
|
|
4010
|
+
this.selectThinkingLevel(level, persist);
|
|
4011
|
+
done();
|
|
4012
|
+
};
|
|
4013
|
+
const selector = new ThinkingSelectorComponent(this.session.thinkingLevel ?? DEFAULT_THINKING_LEVEL, this.session.getAvailableThinkingLevels(), (level) => selectLevel(level, false), () => {
|
|
4014
|
+
done();
|
|
4015
|
+
this.ui.requestRender();
|
|
4016
|
+
}, (level) => selectLevel(level, true), this.settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL);
|
|
4017
|
+
return { component: selector, focus: selector };
|
|
4018
|
+
});
|
|
4019
|
+
}
|
|
3945
4020
|
async handleModelCommand(searchTerm) {
|
|
3946
4021
|
if (!searchTerm) {
|
|
3947
4022
|
this.showModelSelector();
|
|
@@ -3950,7 +4025,7 @@ export class InteractiveMode {
|
|
|
3950
4025
|
const model = await this.findExactModelMatch(searchTerm);
|
|
3951
4026
|
if (model) {
|
|
3952
4027
|
try {
|
|
3953
|
-
await this.session.setModel(model);
|
|
4028
|
+
await this.session.setModel(model, { persist: false });
|
|
3954
4029
|
this.footer.invalidate();
|
|
3955
4030
|
this.updateEditorBorderColor();
|
|
3956
4031
|
this.showStatus(`Model: ${model.id}`);
|
|
@@ -4079,13 +4154,14 @@ export class InteractiveMode {
|
|
|
4079
4154
|
}
|
|
4080
4155
|
showModelSelector(initialSearchInput) {
|
|
4081
4156
|
this.showSelector((done) => {
|
|
4082
|
-
const
|
|
4157
|
+
const selectModel = async (model, persist) => {
|
|
4083
4158
|
try {
|
|
4084
|
-
await this.session.setModel(model);
|
|
4159
|
+
await this.session.setModel(model, { persist });
|
|
4160
|
+
this.updateAvailableProviderCount();
|
|
4085
4161
|
this.footer.invalidate();
|
|
4086
4162
|
this.updateEditorBorderColor();
|
|
4087
4163
|
done();
|
|
4088
|
-
this.showStatus(`Model: ${model.id}`);
|
|
4164
|
+
this.showStatus(persist ? `Default model: ${model.provider}/${model.id}` : `Model: ${model.id}`);
|
|
4089
4165
|
void this.maybeWarnAboutAnthropicSubscriptionAuth(model);
|
|
4090
4166
|
this.checkDaxnutsEasterEgg(model);
|
|
4091
4167
|
}
|
|
@@ -4093,10 +4169,13 @@ export class InteractiveMode {
|
|
|
4093
4169
|
done();
|
|
4094
4170
|
this.showError(error instanceof Error ? error.message : String(error));
|
|
4095
4171
|
}
|
|
4096
|
-
}
|
|
4172
|
+
};
|
|
4173
|
+
const defaultProvider = this.settingsManager.getDefaultProvider();
|
|
4174
|
+
const defaultModel = this.settingsManager.getDefaultModel();
|
|
4175
|
+
const selector = new ModelSelectorComponent(this.ui, this.session.model, this.session.modelRuntime, this.session.scopedModels, (model) => selectModel(model, false), () => {
|
|
4097
4176
|
done();
|
|
4098
4177
|
this.ui.requestRender();
|
|
4099
|
-
}, initialSearchInput);
|
|
4178
|
+
}, initialSearchInput, (model) => selectModel(model, true), defaultProvider && defaultModel ? { provider: defaultProvider, id: defaultModel } : undefined);
|
|
4100
4179
|
return { component: selector, focus: selector, dispose: () => selector.dispose() };
|
|
4101
4180
|
});
|
|
4102
4181
|
}
|
|
@@ -4652,7 +4731,11 @@ export class InteractiveMode {
|
|
|
4652
4731
|
if (isUnknownModel(previousModel)) {
|
|
4653
4732
|
const availableModels = this.session.modelRuntime.getAvailableSnapshot();
|
|
4654
4733
|
const providerModels = availableModels.filter((model) => model.provider === providerId);
|
|
4655
|
-
|
|
4734
|
+
// Matches LLAMA_PROVIDER_ID from extensions/llama/provider.ts; kept inline to avoid coupling interactive mode to the built-in extension.
|
|
4735
|
+
if (providerId === "llama.cpp") {
|
|
4736
|
+
selectionError = llamaCppPostLoginGuidance(actionLabel, providerModels.length);
|
|
4737
|
+
}
|
|
4738
|
+
else if (!hasDefaultModelProvider(providerId)) {
|
|
4656
4739
|
selectionError = `${actionLabel}, but no default model is configured for provider "${providerId}". Use /model to select a model.`;
|
|
4657
4740
|
}
|
|
4658
4741
|
else if (providerModels.length === 0) {
|
|
@@ -4666,7 +4749,7 @@ export class InteractiveMode {
|
|
|
4666
4749
|
}
|
|
4667
4750
|
else {
|
|
4668
4751
|
try {
|
|
4669
|
-
await this.session.setModel(selectedModel);
|
|
4752
|
+
await this.session.setModel(selectedModel, { persist: true });
|
|
4670
4753
|
}
|
|
4671
4754
|
catch (error) {
|
|
4672
4755
|
selectedModel = undefined;
|
|
@@ -4883,25 +4966,6 @@ export class InteractiveMode {
|
|
|
4883
4966
|
this.showWarning("Wait for compaction to finish before reloading.");
|
|
4884
4967
|
return;
|
|
4885
4968
|
}
|
|
4886
|
-
const pendingPiClientUpdate = readPiClientUpdateMarker();
|
|
4887
|
-
if (pendingPiClientUpdate) {
|
|
4888
|
-
const reloadStatePath = process.env.PI_CLIENT_RELOAD_STATE_PATH;
|
|
4889
|
-
if (!reloadStatePath) {
|
|
4890
|
-
this.showWarning(`pi-client ${pendingPiClientUpdate.version} is installed. Restart pi-client to load the new runtime.`);
|
|
4891
|
-
return;
|
|
4892
|
-
}
|
|
4893
|
-
writePiClientRuntimeReloadState(reloadStatePath, {
|
|
4894
|
-
sessionId: this.sessionManager.getSessionId(),
|
|
4895
|
-
sessionDir: this.sessionManager.usesDefaultSessionDir() ? undefined : this.sessionManager.getSessionDir(),
|
|
4896
|
-
updateMarkerPath: getPiClientUpdateMarkerPath(),
|
|
4897
|
-
});
|
|
4898
|
-
this.isShuttingDown = true;
|
|
4899
|
-
this.themeController.disableAutoSync();
|
|
4900
|
-
await this.ui.terminal.drainInput(1000);
|
|
4901
|
-
this.stop();
|
|
4902
|
-
await this.runtimeHost.dispose();
|
|
4903
|
-
process.exit(PI_CLIENT_RUNTIME_RELOAD_EXIT_CODE);
|
|
4904
|
-
}
|
|
4905
4969
|
this.resetExtensionUI();
|
|
4906
4970
|
const reloadBox = new Container();
|
|
4907
4971
|
const borderColor = (s) => theme.fg("border", s);
|
|
@@ -4942,8 +5006,8 @@ export class InteractiveMode {
|
|
|
4942
5006
|
activeHeader.setExpanded(this.toolOutputExpanded);
|
|
4943
5007
|
}
|
|
4944
5008
|
setRegisteredThemes(this.session.resourceLoader.getThemes().themes);
|
|
4945
|
-
await this.themeController.applyFromSettings();
|
|
4946
5009
|
this.applyRuntimeSettings();
|
|
5010
|
+
await this.themeController.applyFromSettings();
|
|
4947
5011
|
this.setupAutocompleteProvider();
|
|
4948
5012
|
const runner = this.session.extensionRunner;
|
|
4949
5013
|
this.setupExtensionShortcuts(runner);
|
|
@@ -5055,93 +5119,23 @@ export class InteractiveMode {
|
|
|
5055
5119
|
}
|
|
5056
5120
|
}
|
|
5057
5121
|
async handleShareCommand() {
|
|
5058
|
-
|
|
5059
|
-
|
|
5060
|
-
|
|
5061
|
-
|
|
5062
|
-
|
|
5063
|
-
|
|
5064
|
-
|
|
5065
|
-
}
|
|
5066
|
-
catch {
|
|
5067
|
-
this.showError("GitHub CLI (gh) is not installed. Install it from https://cli.github.com/");
|
|
5068
|
-
return;
|
|
5069
|
-
}
|
|
5070
|
-
// Export to a temp file
|
|
5071
|
-
const tmpFile = path.join(os.tmpdir(), "session.html");
|
|
5072
|
-
try {
|
|
5073
|
-
await this.session.exportToHtml(tmpFile, { themeName: theme.name });
|
|
5074
|
-
}
|
|
5075
|
-
catch (error) {
|
|
5076
|
-
this.showError(`Failed to export session: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
5077
|
-
return;
|
|
5078
|
-
}
|
|
5079
|
-
// Show cancellable loader, replacing the editor
|
|
5080
|
-
const loader = new BorderedLoader(this.ui, theme, "Creating gist...");
|
|
5081
|
-
this.editorContainer.clear();
|
|
5082
|
-
this.editorContainer.addChild(loader);
|
|
5083
|
-
this.ui.setFocus(loader);
|
|
5084
|
-
this.ui.requestRender();
|
|
5085
|
-
const restoreEditor = () => {
|
|
5086
|
-
loader.dispose();
|
|
5087
|
-
this.editorContainer.clear();
|
|
5088
|
-
this.editorContainer.addChild(this.editor);
|
|
5089
|
-
this.ui.setFocus(this.editor);
|
|
5090
|
-
try {
|
|
5091
|
-
fs.unlinkSync(tmpFile);
|
|
5092
|
-
}
|
|
5093
|
-
catch {
|
|
5094
|
-
// Ignore cleanup errors
|
|
5095
|
-
}
|
|
5096
|
-
};
|
|
5097
|
-
// Create a secret gist asynchronously
|
|
5098
|
-
let proc = null;
|
|
5099
|
-
loader.onAbort = () => {
|
|
5100
|
-
proc?.kill();
|
|
5101
|
-
restoreEditor();
|
|
5102
|
-
this.showStatus("Share cancelled");
|
|
5103
|
-
};
|
|
5104
|
-
try {
|
|
5105
|
-
const result = await new Promise((resolve) => {
|
|
5106
|
-
proc = spawn("gh", ["gist", "create", "--public=false", tmpFile]);
|
|
5107
|
-
let stdout = "";
|
|
5108
|
-
let stderr = "";
|
|
5109
|
-
proc.stdout?.on("data", (data) => {
|
|
5110
|
-
stdout += data.toString();
|
|
5111
|
-
});
|
|
5112
|
-
proc.stderr?.on("data", (data) => {
|
|
5113
|
-
stderr += data.toString();
|
|
5114
|
-
});
|
|
5115
|
-
proc.on("close", (code) => resolve({ stdout, stderr, code }));
|
|
5116
|
-
});
|
|
5117
|
-
if (loader.signal.aborted)
|
|
5118
|
-
return;
|
|
5119
|
-
restoreEditor();
|
|
5120
|
-
if (result.code !== 0) {
|
|
5121
|
-
const errorMsg = result.stderr?.trim() || "Unknown error";
|
|
5122
|
-
this.showError(`Failed to create gist: ${errorMsg}`);
|
|
5123
|
-
return;
|
|
5124
|
-
}
|
|
5125
|
-
// Extract gist ID from the URL returned by gh
|
|
5126
|
-
// gh returns something like: https://gist.github.com/username/GIST_ID
|
|
5127
|
-
const gistUrl = result.stdout?.trim();
|
|
5128
|
-
const gistId = gistUrl?.split("/").pop();
|
|
5129
|
-
if (!gistId) {
|
|
5130
|
-
this.showError("Failed to parse gist ID from gh output");
|
|
5131
|
-
return;
|
|
5132
|
-
}
|
|
5133
|
-
// Create the preview URL
|
|
5134
|
-
const previewUrl = getShareViewerUrl(gistId);
|
|
5135
|
-
this.showStatus(`Share URL: ${previewUrl}\nGist: ${gistUrl}`);
|
|
5136
|
-
}
|
|
5137
|
-
catch (error) {
|
|
5138
|
-
if (!loader.signal.aborted) {
|
|
5139
|
-
restoreEditor();
|
|
5140
|
-
this.showError(`Failed to create gist: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
5141
|
-
}
|
|
5142
|
-
}
|
|
5122
|
+
await shareSession({
|
|
5123
|
+
session: this.session,
|
|
5124
|
+
ui: this.ui,
|
|
5125
|
+
editorContainer: this.editorContainer,
|
|
5126
|
+
editor: this.editor,
|
|
5127
|
+
showStatus: (message) => this.showStatus(message),
|
|
5128
|
+
showError: (message) => this.showError(message),
|
|
5129
|
+
});
|
|
5143
5130
|
}
|
|
5144
5131
|
async handleCopyCommand(options = {}) {
|
|
5132
|
+
if (options.preferSelection &&
|
|
5133
|
+
this.ui instanceof TuiAltScreen &&
|
|
5134
|
+
!this.ui.getCopyOnSelect() &&
|
|
5135
|
+
this.ui.hasActiveSelection()) {
|
|
5136
|
+
await this.ui.copyActiveSelectionToClipboard();
|
|
5137
|
+
return;
|
|
5138
|
+
}
|
|
5145
5139
|
const text = this.session.getLastAssistantText();
|
|
5146
5140
|
if (!text) {
|
|
5147
5141
|
this.showError("No agent messages to copy yet.");
|