@code-yeongyu/senpi 2026.6.30 → 2026.7.2
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 +42 -0
- package/dist/core/agent-session.d.ts +6 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +42 -25
- 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 +13 -5
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +5 -8
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +6 -0
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +2 -1
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +9 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +16 -2
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/http-dispatcher.d.ts.map +1 -1
- package/dist/core/http-dispatcher.js +28 -1
- package/dist/core/http-dispatcher.js.map +1 -1
- package/dist/core/model-resolver.d.ts +10 -0
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +16 -22
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/session-manager.d.ts +20 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +87 -68
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +3 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +8 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +20 -5
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/extension-system-migration.d.ts +2 -0
- package/dist/extension-system-migration.d.ts.map +1 -0
- package/dist/extension-system-migration.js +51 -0
- package/dist/extension-system-migration.js.map +1 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/legacy-senpi-dir-migration.d.ts +2 -0
- package/dist/legacy-senpi-dir-migration.d.ts.map +1 -0
- package/dist/legacy-senpi-dir-migration.js +76 -0
- package/dist/legacy-senpi-dir-migration.js.map +1 -0
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +3 -95
- package/dist/migrations.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts +3 -1
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +15 -7
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/custom-entry.d.ts +19 -0
- package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -0
- package/dist/modes/interactive/components/custom-entry.js +49 -0
- package/dist/modes/interactive/components/custom-entry.js.map +1 -0
- package/dist/modes/interactive/components/settings-selector.d.ts +2 -0
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +13 -1
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/status-indicator.d.ts +27 -0
- package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -0
- package/dist/modes/interactive/components/status-indicator.js +64 -0
- package/dist/modes/interactive/components/status-indicator.js.map +1 -0
- package/dist/modes/interactive/components/user-message.d.ts +6 -2
- package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message.js +15 -4
- package/dist/modes/interactive/components/user-message.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +14 -15
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +176 -137
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +15 -0
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +14 -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 +16 -0
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +26 -0
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/docs/extensions.md +55 -8
- package/docs/rpc.md +58 -0
- package/docs/sdk.md +28 -0
- package/docs/session-format.md +18 -8
- package/docs/settings.md +1 -0
- package/examples/extensions/README.md +1 -0
- 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/entry-renderer.ts +41 -0
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/agent.d.ts +3 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/agent.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/agent.js +9 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/agent.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/compaction.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/compaction.js +4 -6
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/compaction.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/env/nodejs.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/env/nodejs.js +20 -2
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/env/nodejs.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/package.json +2 -2
- package/node_modules/@earendil-works/pi-ai/dist/api/azure-openai-responses.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/azure-openai-responses.js +2 -14
- package/node_modules/@earendil-works/pi-ai/dist/api/azure-openai-responses.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/bedrock-converse-stream.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/bedrock-converse-stream.js +12 -4
- package/node_modules/@earendil-works/pi-ai/dist/api/bedrock-converse-stream.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/google-generative-ai.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/google-generative-ai.js +2 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/google-generative-ai.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/google-vertex.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/google-vertex.js +2 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/google-vertex.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js +56 -39
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js +8 -3
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js +2 -14
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openrouter-images.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openrouter-images.js +2 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openrouter-images.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.d.ts +15 -45
- package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js +15 -45
- package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts +375 -54
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.models.d.ts +123 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.models.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.models.js +124 -4
- package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.models.d.ts +20 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.models.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.models.js +18 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/cerebras.models.d.ts +21 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/cerebras.models.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/cerebras.models.js +18 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/cerebras.models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-ai-gateway.models.d.ts +21 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-ai-gateway.models.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-ai-gateway.models.js +18 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/cloudflare-ai-gateway.models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/fireworks.models.d.ts +10 -5
- package/node_modules/@earendil-works/pi-ai/dist/providers/fireworks.models.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/fireworks.models.js +4 -3
- package/node_modules/@earendil-works/pi-ai/dist/providers/fireworks.models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot.models.d.ts +26 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot.models.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot.models.js +19 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/github-copilot.models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/nvidia.models.d.ts +0 -28
- package/node_modules/@earendil-works/pi-ai/dist/providers/nvidia.models.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/nvidia.models.js +0 -19
- package/node_modules/@earendil-works/pi-ai/dist/providers/nvidia.models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/opencode-go.models.js +5 -5
- package/node_modules/@earendil-works/pi-ai/dist/providers/opencode-go.models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/opencode.models.d.ts +89 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/opencode.models.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/opencode.models.js +75 -2
- package/node_modules/@earendil-works/pi-ai/dist/providers/opencode.models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.d.ts +21 -21
- package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.js +49 -49
- package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.d.ts +44 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.js +37 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/error-body.d.ts +25 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/error-body.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/error-body.js +109 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/error-body.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/device-code.d.ts +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/device-code.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/device-code.js +6 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/device-code.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/github-copilot.js +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/package.json +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/tui.d.ts +13 -0
- package/node_modules/@earendil-works/pi-tui/dist/tui.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/tui.js +25 -12
- package/node_modules/@earendil-works/pi-tui/dist/tui.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/package.json +1 -1
- package/npm-shrinkwrap.json +9 -9
- package/package.json +4 -4
|
@@ -7,7 +7,7 @@ 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 { getProviders, } from "@earendil-works/pi-ai/compat";
|
|
10
|
-
import { CombinedAutocompleteProvider, Container, fuzzyFilter, getCapabilities, hyperlink,
|
|
10
|
+
import { CombinedAutocompleteProvider, Container, fuzzyFilter, getCapabilities, hyperlink, Markdown, matchesKey, ProcessTerminal, Spacer, setKeybindings, Text, TruncatedText, TUI, visibleWidth, } from "@earendil-works/pi-tui";
|
|
11
11
|
import chalk from "chalk";
|
|
12
12
|
import { spawn, spawnSync } from "child_process";
|
|
13
13
|
import { APP_NAME, APP_TITLE, CONFIG_DIR_NAME, expandTildePath, getAuthPath, getDebugLogPath, getDocsPath, getShareViewerUrl, VERSION, } from "../../config.js";
|
|
@@ -20,7 +20,7 @@ import { createCompactionSummaryMessage } from "../../core/messages.js";
|
|
|
20
20
|
import { defaultModelPerProvider, findExactModelReferenceMatch, resolveModelScope, } from "../../core/model-resolver.js";
|
|
21
21
|
import { BUILT_IN_PROVIDER_DISPLAY_NAMES } from "../../core/provider-display-names.js";
|
|
22
22
|
import { formatMissingSessionCwdPrompt, MissingSessionCwdError } from "../../core/session-cwd.js";
|
|
23
|
-
import { SessionManager } from "../../core/session-manager.js";
|
|
23
|
+
import { SessionManager, sessionEntryToContextMessages } from "../../core/session-manager.js";
|
|
24
24
|
import { BUILTIN_SLASH_COMMANDS } from "../../core/slash-commands.js";
|
|
25
25
|
import { isInstallTelemetryEnabled } from "../../core/telemetry.js";
|
|
26
26
|
import { hasTrustRequiringProjectResources, ProjectTrustStore } from "../../core/trust-manager.js";
|
|
@@ -39,8 +39,8 @@ import { BashExecutionComponent } from "./components/bash-execution.js";
|
|
|
39
39
|
import { BorderedLoader } from "./components/bordered-loader.js";
|
|
40
40
|
import { BranchSummaryMessageComponent } from "./components/branch-summary-message.js";
|
|
41
41
|
import { CompactionSummaryMessageComponent } from "./components/compaction-summary-message.js";
|
|
42
|
-
import { CountdownTimer } from "./components/countdown-timer.js";
|
|
43
42
|
import { CustomEditor } from "./components/custom-editor.js";
|
|
43
|
+
import { CustomEntryComponent } from "./components/custom-entry.js";
|
|
44
44
|
import { CustomMessageComponent } from "./components/custom-message.js";
|
|
45
45
|
import { DaxnutsComponent } from "./components/daxnuts.js";
|
|
46
46
|
import { DynamicBorder } from "./components/dynamic-border.js";
|
|
@@ -58,6 +58,7 @@ import { OAuthSelectorComponent } from "./components/oauth-selector.js";
|
|
|
58
58
|
import { SessionSelectorComponent } from "./components/session-selector.js";
|
|
59
59
|
import { SettingsSelectorComponent } from "./components/settings-selector.js";
|
|
60
60
|
import { SkillInvocationMessageComponent } from "./components/skill-invocation-message.js";
|
|
61
|
+
import { BranchSummaryStatusIndicator, CompactionStatusIndicator, IdleStatus, RetryStatusIndicator, WorkingStatusIndicator, } from "./components/status-indicator.js";
|
|
61
62
|
import { ToolExecutionComponent } from "./components/tool-execution.js";
|
|
62
63
|
import { TreeSelectorComponent } from "./components/tree-selector.js";
|
|
63
64
|
import { TrustSelectorComponent } from "./components/trust-selector.js";
|
|
@@ -87,6 +88,9 @@ function formatToolHookTerminalTitle(event) {
|
|
|
87
88
|
const statusMessage = sanitizeWorkingStatusPlainText(event.statusMessage);
|
|
88
89
|
return `${APP_TITLE} - ${hookName}: ${statusMessage}`;
|
|
89
90
|
}
|
|
91
|
+
function isCustomSessionEntry(item) {
|
|
92
|
+
return "type" in item && item.type === "custom";
|
|
93
|
+
}
|
|
90
94
|
const DEAD_TERMINAL_ERROR_CODES = new Set(["EIO", "EPIPE", "ENOTCONN"]);
|
|
91
95
|
const DEFAULT_WORKING_STATUS_REFRESH_INTERVAL_MS = 600;
|
|
92
96
|
const DEFAULT_WORKING_STATUS_MESSAGE_ANIMATION_INTERVAL_MS = 32;
|
|
@@ -197,12 +201,12 @@ export class InteractiveMode {
|
|
|
197
201
|
this.autocompleteProviderWrappers = [];
|
|
198
202
|
this.isInitialized = false;
|
|
199
203
|
this.pendingUserInputs = [];
|
|
200
|
-
this.
|
|
204
|
+
this.activeStatusIndicator = undefined;
|
|
205
|
+
this.idleStatus = new IdleStatus();
|
|
201
206
|
this.workingMessage = undefined;
|
|
202
207
|
this.workingVisible = true;
|
|
203
208
|
this.workingIndicatorOptions = undefined;
|
|
204
209
|
this.workingStartedAt = undefined;
|
|
205
|
-
this.workingElapsedIntervalId = undefined;
|
|
206
210
|
this.defaultWorkingMessage = "Working";
|
|
207
211
|
this.defaultHiddenThinkingLabel = "Thinking...";
|
|
208
212
|
this.hiddenThinkingLabel = this.defaultHiddenThinkingLabel;
|
|
@@ -230,6 +234,7 @@ export class InteractiveMode {
|
|
|
230
234
|
this.toolOutputExpanded = false;
|
|
231
235
|
// Thinking block visibility state
|
|
232
236
|
this.hideThinkingBlock = false;
|
|
237
|
+
this.outputPad = 1;
|
|
233
238
|
// Skill commands: command name -> skill file path
|
|
234
239
|
this.skillCommands = new Map();
|
|
235
240
|
this.signalCleanupHandlers = [];
|
|
@@ -239,12 +244,7 @@ export class InteractiveMode {
|
|
|
239
244
|
this.bashComponent = undefined;
|
|
240
245
|
// Track pending bash components (shown in pending area, moved to chat on submit)
|
|
241
246
|
this.pendingBashComponents = [];
|
|
242
|
-
// Auto-compaction state
|
|
243
|
-
this.autoCompactionLoader = undefined;
|
|
244
247
|
this.autoCompactionProgressText = "";
|
|
245
|
-
// Auto-retry state
|
|
246
|
-
this.retryLoader = undefined;
|
|
247
|
-
this.retryCountdown = undefined;
|
|
248
248
|
// Messages queued while compaction is running
|
|
249
249
|
this.compactionQueuedMessages = [];
|
|
250
250
|
// Shutdown state
|
|
@@ -305,6 +305,7 @@ export class InteractiveMode {
|
|
|
305
305
|
this.footer.setAutoCompactEnabled(this.session.autoCompactionEnabled);
|
|
306
306
|
// Load hide thinking block setting
|
|
307
307
|
this.hideThinkingBlock = this.settingsManager.getHideThinkingBlock();
|
|
308
|
+
this.outputPad = this.settingsManager.getOutputPad();
|
|
308
309
|
// Register themes from resource loader and initialize
|
|
309
310
|
setRegisteredThemes(this.session.resourceLoader.getThemes().themes);
|
|
310
311
|
this.themeController = new InteractiveThemeController(this.ui, this.settingsManager, (message) => this.showError(message), () => this.updateEditorBorderColor());
|
|
@@ -1200,7 +1201,7 @@ export class InteractiveMode {
|
|
|
1200
1201
|
commandContextActions: {
|
|
1201
1202
|
waitForIdle: () => this.session.agent.waitForIdle(),
|
|
1202
1203
|
newSession: async (options) => {
|
|
1203
|
-
this.
|
|
1204
|
+
this.clearStatusIndicator();
|
|
1204
1205
|
try {
|
|
1205
1206
|
return await this.runtimeHost.newSession(options);
|
|
1206
1207
|
}
|
|
@@ -1270,8 +1271,13 @@ export class InteractiveMode {
|
|
|
1270
1271
|
this.footer.setAutoCompactEnabled(this.session.autoCompactionEnabled);
|
|
1271
1272
|
this.footerDataProvider.setCwd(this.sessionManager.getCwd());
|
|
1272
1273
|
this.hideThinkingBlock = this.settingsManager.getHideThinkingBlock();
|
|
1274
|
+
this.outputPad = this.settingsManager.getOutputPad();
|
|
1273
1275
|
this.ui.setShowHardwareCursor(this.settingsManager.getShowHardwareCursor());
|
|
1274
|
-
this.
|
|
1276
|
+
const clearOnShrink = this.settingsManager.getClearOnShrink();
|
|
1277
|
+
this.ui.setClearOnShrink(clearOnShrink);
|
|
1278
|
+
if (!clearOnShrink && !this.activeStatusIndicator) {
|
|
1279
|
+
this.statusContainer.clear();
|
|
1280
|
+
}
|
|
1275
1281
|
const editorPaddingX = this.settingsManager.getEditorPaddingX();
|
|
1276
1282
|
const autocompleteMaxVisible = this.settingsManager.getAutocompleteMaxVisible();
|
|
1277
1283
|
this.defaultEditor.setPaddingX(editorPaddingX);
|
|
@@ -1387,31 +1393,6 @@ export class InteractiveMode {
|
|
|
1387
1393
|
this.footerDataProvider.setExtensionStatus(key, text);
|
|
1388
1394
|
this.ui.requestRender();
|
|
1389
1395
|
}
|
|
1390
|
-
getWorkingLoaderMessage() {
|
|
1391
|
-
return this.workingMessage ?? this.defaultWorkingMessage;
|
|
1392
|
-
}
|
|
1393
|
-
getWorkingElapsedSeconds() {
|
|
1394
|
-
if (this.workingStartedAt === undefined) {
|
|
1395
|
-
return 0;
|
|
1396
|
-
}
|
|
1397
|
-
return Math.max(0, Math.floor((Date.now() - this.workingStartedAt) / 1000));
|
|
1398
|
-
}
|
|
1399
|
-
refreshWorkingLoaderMessage() {
|
|
1400
|
-
this.loadingAnimation?.setMessage(this.getWorkingLoaderMessage());
|
|
1401
|
-
}
|
|
1402
|
-
startWorkingElapsedTimer() {
|
|
1403
|
-
this.stopWorkingElapsedTimer();
|
|
1404
|
-
this.workingStartedAt = Date.now();
|
|
1405
|
-
this.workingElapsedIntervalId = setInterval(() => {
|
|
1406
|
-
this.refreshWorkingLoaderMessage();
|
|
1407
|
-
}, DEFAULT_WORKING_STATUS_REFRESH_INTERVAL_MS);
|
|
1408
|
-
}
|
|
1409
|
-
stopWorkingElapsedTimer() {
|
|
1410
|
-
if (this.workingElapsedIntervalId) {
|
|
1411
|
-
clearInterval(this.workingElapsedIntervalId);
|
|
1412
|
-
this.workingElapsedIntervalId = undefined;
|
|
1413
|
-
}
|
|
1414
|
-
}
|
|
1415
1396
|
startToolHookStatusTimer() {
|
|
1416
1397
|
if (this.hookStatusIntervalId) {
|
|
1417
1398
|
return;
|
|
@@ -1522,6 +1503,23 @@ export class InteractiveMode {
|
|
|
1522
1503
|
this.hookStatusContainer.clear();
|
|
1523
1504
|
this.stopToolHookStatusTimer();
|
|
1524
1505
|
}
|
|
1506
|
+
getWorkingElapsedSeconds() {
|
|
1507
|
+
if (this.workingStartedAt === undefined) {
|
|
1508
|
+
return 0;
|
|
1509
|
+
}
|
|
1510
|
+
return Math.max(0, Math.floor((Date.now() - this.workingStartedAt) / 1000));
|
|
1511
|
+
}
|
|
1512
|
+
getWorkingLoaderMessage() {
|
|
1513
|
+
return this.workingMessage ?? this.defaultWorkingMessage;
|
|
1514
|
+
}
|
|
1515
|
+
refreshWorkingLoaderMessage() {
|
|
1516
|
+
if (this.activeStatusIndicator?.kind === "working") {
|
|
1517
|
+
this.activeStatusIndicator.setMessage(this.getWorkingLoaderMessage());
|
|
1518
|
+
return;
|
|
1519
|
+
}
|
|
1520
|
+
const legacyLoader = this.loadingAnimation;
|
|
1521
|
+
legacyLoader?.setMessage(this.getWorkingLoaderMessage());
|
|
1522
|
+
}
|
|
1525
1523
|
getWorkingIndicatorOptions() {
|
|
1526
1524
|
return (this.workingIndicatorOptions ?? {
|
|
1527
1525
|
frames: theme.getColorMode() === "truecolor" ? ["•"] : [theme.fg("accent", "•"), theme.fg("muted", "◦")],
|
|
@@ -1539,36 +1537,53 @@ export class InteractiveMode {
|
|
|
1539
1537
|
messageIntervalMs: DEFAULT_WORKING_STATUS_MESSAGE_ANIMATION_INTERVAL_MS,
|
|
1540
1538
|
});
|
|
1541
1539
|
}
|
|
1542
|
-
|
|
1543
|
-
|
|
1540
|
+
showStatusIndicator(indicator) {
|
|
1541
|
+
if (indicator.kind === "working") {
|
|
1542
|
+
this.workingStartedAt = Date.now();
|
|
1543
|
+
}
|
|
1544
|
+
this.activeStatusIndicator?.dispose();
|
|
1545
|
+
this.activeStatusIndicator = indicator;
|
|
1546
|
+
this.statusContainer.clear();
|
|
1547
|
+
this.statusContainer.addChild(indicator);
|
|
1544
1548
|
}
|
|
1545
|
-
|
|
1546
|
-
this.
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1549
|
+
updateWorkingIndicatorMessage() {
|
|
1550
|
+
if (this.activeStatusIndicator?.kind === "working") {
|
|
1551
|
+
this.activeStatusIndicator.setMessage(this.workingMessage ?? this.defaultWorkingMessage);
|
|
1552
|
+
}
|
|
1553
|
+
}
|
|
1554
|
+
clearStatusIndicator(kind) {
|
|
1555
|
+
if (kind && this.activeStatusIndicator?.kind !== kind) {
|
|
1556
|
+
return;
|
|
1557
|
+
}
|
|
1558
|
+
const hadActiveStatusIndicator = this.activeStatusIndicator !== undefined;
|
|
1559
|
+
const isClearingWorking = this.activeStatusIndicator?.kind === "working";
|
|
1560
|
+
this.activeStatusIndicator?.dispose();
|
|
1561
|
+
this.activeStatusIndicator = undefined;
|
|
1562
|
+
if (isClearingWorking) {
|
|
1563
|
+
this.workingStartedAt = undefined;
|
|
1551
1564
|
}
|
|
1552
1565
|
this.statusContainer.clear();
|
|
1566
|
+
if (hadActiveStatusIndicator && this.ui.getClearOnShrink()) {
|
|
1567
|
+
this.statusContainer.addChild(this.idleStatus);
|
|
1568
|
+
}
|
|
1553
1569
|
}
|
|
1554
1570
|
setWorkingVisible(visible) {
|
|
1555
1571
|
this.workingVisible = visible;
|
|
1556
1572
|
if (!visible) {
|
|
1557
|
-
this.
|
|
1573
|
+
this.clearStatusIndicator("working");
|
|
1558
1574
|
this.ui.requestRender();
|
|
1559
1575
|
return;
|
|
1560
1576
|
}
|
|
1561
|
-
if (this.session.isStreaming &&
|
|
1562
|
-
this.
|
|
1563
|
-
this.startWorkingElapsedTimer();
|
|
1564
|
-
this.loadingAnimation = this.createWorkingLoader();
|
|
1565
|
-
this.statusContainer.addChild(this.loadingAnimation);
|
|
1577
|
+
if (this.session.isStreaming && this.activeStatusIndicator?.kind !== "working") {
|
|
1578
|
+
this.showStatusIndicator(new WorkingStatusIndicator(this.ui, this.workingMessage ?? this.defaultWorkingMessage, this.getWorkingIndicatorOptions()));
|
|
1566
1579
|
}
|
|
1567
1580
|
this.ui.requestRender();
|
|
1568
1581
|
}
|
|
1569
1582
|
setWorkingIndicator(options) {
|
|
1570
1583
|
this.workingIndicatorOptions = options;
|
|
1571
|
-
this.
|
|
1584
|
+
if (this.activeStatusIndicator?.kind === "working") {
|
|
1585
|
+
this.activeStatusIndicator.setIndicator(this.getWorkingIndicatorOptions());
|
|
1586
|
+
}
|
|
1572
1587
|
this.ui.requestRender();
|
|
1573
1588
|
}
|
|
1574
1589
|
setHiddenThinkingLabel(label) {
|
|
@@ -1660,7 +1675,7 @@ export class InteractiveMode {
|
|
|
1660
1675
|
this.workingMessage = undefined;
|
|
1661
1676
|
this.workingVisible = true;
|
|
1662
1677
|
this.setWorkingIndicator();
|
|
1663
|
-
this.
|
|
1678
|
+
this.updateWorkingIndicatorMessage();
|
|
1664
1679
|
this.setHiddenThinkingLabel();
|
|
1665
1680
|
this.clearToolHookStatuses();
|
|
1666
1681
|
}
|
|
@@ -1800,7 +1815,7 @@ export class InteractiveMode {
|
|
|
1800
1815
|
setStatus: (key, text) => this.setExtensionStatus(key, text),
|
|
1801
1816
|
setWorkingMessage: (message) => {
|
|
1802
1817
|
this.workingMessage = message;
|
|
1803
|
-
this.
|
|
1818
|
+
this.updateWorkingIndicatorMessage();
|
|
1804
1819
|
},
|
|
1805
1820
|
setWorkingVisible: (visible) => this.setWorkingVisible(visible),
|
|
1806
1821
|
setWorkingIndicator: (options) => this.setWorkingIndicator(options),
|
|
@@ -2443,19 +2458,11 @@ export class InteractiveMode {
|
|
|
2443
2458
|
this.defaultEditor.onEscape = this.retryEscapeHandler;
|
|
2444
2459
|
this.retryEscapeHandler = undefined;
|
|
2445
2460
|
}
|
|
2446
|
-
if (this.retryCountdown) {
|
|
2447
|
-
this.retryCountdown.dispose();
|
|
2448
|
-
this.retryCountdown = undefined;
|
|
2449
|
-
}
|
|
2450
|
-
if (this.retryLoader) {
|
|
2451
|
-
this.retryLoader.stop();
|
|
2452
|
-
this.retryLoader = undefined;
|
|
2453
|
-
}
|
|
2454
|
-
this.stopWorkingLoader();
|
|
2455
2461
|
if (this.workingVisible) {
|
|
2456
|
-
this.
|
|
2457
|
-
|
|
2458
|
-
|
|
2462
|
+
this.showStatusIndicator(new WorkingStatusIndicator(this.ui, this.workingMessage ?? this.defaultWorkingMessage, this.getWorkingIndicatorOptions()));
|
|
2463
|
+
}
|
|
2464
|
+
else {
|
|
2465
|
+
this.clearStatusIndicator();
|
|
2459
2466
|
}
|
|
2460
2467
|
this.ui.requestRender();
|
|
2461
2468
|
break;
|
|
@@ -2466,6 +2473,12 @@ export class InteractiveMode {
|
|
|
2466
2473
|
case "system_prompt_change":
|
|
2467
2474
|
this.showStatus(event.systemPromptName ? `System prompt: ${event.systemPromptName}` : "System prompt changed");
|
|
2468
2475
|
break;
|
|
2476
|
+
case "entry_appended":
|
|
2477
|
+
if (event.entry.type === "custom") {
|
|
2478
|
+
this.addCustomEntryToChat(event.entry);
|
|
2479
|
+
this.ui.requestRender();
|
|
2480
|
+
}
|
|
2481
|
+
break;
|
|
2469
2482
|
case "session_info_changed":
|
|
2470
2483
|
this.updateTerminalTitle();
|
|
2471
2484
|
this.footer.invalidate();
|
|
@@ -2486,7 +2499,7 @@ export class InteractiveMode {
|
|
|
2486
2499
|
this.ui.requestRender();
|
|
2487
2500
|
}
|
|
2488
2501
|
else if (event.message.role === "assistant") {
|
|
2489
|
-
this.streamingComponent = new AssistantMessageComponent(undefined, this.hideThinkingBlock, this.getMarkdownThemeWithSettings(), this.hiddenThinkingLabel);
|
|
2502
|
+
this.streamingComponent = new AssistantMessageComponent(undefined, this.hideThinkingBlock, this.getMarkdownThemeWithSettings(), this.hiddenThinkingLabel, this.outputPad);
|
|
2490
2503
|
this.streamingComponent.setExpanded(this.toolOutputExpanded);
|
|
2491
2504
|
this.streamingMessage = event.message;
|
|
2492
2505
|
this.chatContainer.addChild(this.streamingComponent);
|
|
@@ -2596,7 +2609,7 @@ export class InteractiveMode {
|
|
|
2596
2609
|
if (this.settingsManager.getShowTerminalProgress()) {
|
|
2597
2610
|
this.ui.terminal.setProgress(false);
|
|
2598
2611
|
}
|
|
2599
|
-
this.
|
|
2612
|
+
this.clearStatusIndicator("working");
|
|
2600
2613
|
this.clearActiveToolExecutionStatus();
|
|
2601
2614
|
this.clearToolHookStatuses();
|
|
2602
2615
|
if (this.streamingComponent) {
|
|
@@ -2617,23 +2630,17 @@ export class InteractiveMode {
|
|
|
2617
2630
|
this.defaultEditor.onEscape = () => {
|
|
2618
2631
|
this.session.abortCompaction();
|
|
2619
2632
|
};
|
|
2633
|
+
const indicator = new CompactionStatusIndicator(this.ui, event.reason);
|
|
2634
|
+
this.activeStatusIndicator?.dispose();
|
|
2635
|
+
this.activeStatusIndicator = indicator;
|
|
2620
2636
|
this.statusContainer.clear();
|
|
2621
|
-
|
|
2622
|
-
const label = event.reason === "threshold"
|
|
2623
|
-
? `Auto-compacting... ${cancelHint}`
|
|
2624
|
-
: event.reason === "overflow"
|
|
2625
|
-
? `Context overflow detected, compacting... ${cancelHint}`
|
|
2626
|
-
: event.reason === "pre_prompt"
|
|
2627
|
-
? `Compacting before next prompt... ${cancelHint}`
|
|
2628
|
-
: `Compacting context... ${cancelHint}`;
|
|
2629
|
-
this.autoCompactionLoader = new Loader(this.ui, (spinner) => theme.fg("accent", spinner), (text) => theme.fg("muted", text), label);
|
|
2630
|
-
this.statusContainer.addChild(this.autoCompactionLoader);
|
|
2637
|
+
this.statusContainer.addChild(indicator);
|
|
2631
2638
|
this.autoCompactionProgressText = "";
|
|
2632
2639
|
this.ui.requestRender();
|
|
2633
2640
|
break;
|
|
2634
2641
|
}
|
|
2635
2642
|
case "compaction_progress": {
|
|
2636
|
-
if (
|
|
2643
|
+
if (this.activeStatusIndicator?.kind !== "compaction")
|
|
2637
2644
|
break;
|
|
2638
2645
|
const nextText = event.text !== undefined ? event.text : `${this.autoCompactionProgressText}${event.delta ?? ""}`;
|
|
2639
2646
|
if (!nextText)
|
|
@@ -2641,7 +2648,7 @@ export class InteractiveMode {
|
|
|
2641
2648
|
this.autoCompactionProgressText = nextText;
|
|
2642
2649
|
const preview = nextText.length > 4_000 ? `...${nextText.slice(nextText.length - 4_000)}` : nextText;
|
|
2643
2650
|
this.statusContainer.clear();
|
|
2644
|
-
this.statusContainer.addChild(this.
|
|
2651
|
+
this.statusContainer.addChild(this.activeStatusIndicator);
|
|
2645
2652
|
this.statusContainer.addChild(new Spacer(1));
|
|
2646
2653
|
this.statusContainer.addChild(new Text(theme.fg("muted", preview), 1, 0));
|
|
2647
2654
|
this.ui.requestRender();
|
|
@@ -2655,12 +2662,8 @@ export class InteractiveMode {
|
|
|
2655
2662
|
this.defaultEditor.onEscape = this.autoCompactionEscapeHandler;
|
|
2656
2663
|
this.autoCompactionEscapeHandler = undefined;
|
|
2657
2664
|
}
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
this.autoCompactionLoader = undefined;
|
|
2661
|
-
this.autoCompactionProgressText = "";
|
|
2662
|
-
this.statusContainer.clear();
|
|
2663
|
-
}
|
|
2665
|
+
this.clearStatusIndicator("compaction");
|
|
2666
|
+
this.autoCompactionProgressText = "";
|
|
2664
2667
|
if (event.aborted) {
|
|
2665
2668
|
if (event.reason === "manual") {
|
|
2666
2669
|
this.showError("Compaction cancelled");
|
|
@@ -2694,17 +2697,7 @@ export class InteractiveMode {
|
|
|
2694
2697
|
// no separate retry-only handler is installed (the prior one only called
|
|
2695
2698
|
// session.abortRetry() and left queued steering messages stranded).
|
|
2696
2699
|
this.retryEscapeHandler = undefined;
|
|
2697
|
-
|
|
2698
|
-
this.statusContainer.clear();
|
|
2699
|
-
this.retryCountdown?.dispose();
|
|
2700
|
-
const retryMessage = (seconds) => `Retrying (${event.attempt}/${event.maxAttempts}) in ${seconds}s... (${keyText("app.interrupt")} to cancel)`;
|
|
2701
|
-
this.retryLoader = new Loader(this.ui, (spinner) => theme.fg("warning", spinner), (text) => theme.fg("muted", text), retryMessage(Math.ceil(event.delayMs / 1000)));
|
|
2702
|
-
this.retryCountdown = new CountdownTimer(event.delayMs, this.ui, (seconds) => {
|
|
2703
|
-
this.retryLoader?.setMessage(retryMessage(seconds));
|
|
2704
|
-
}, () => {
|
|
2705
|
-
this.retryCountdown = undefined;
|
|
2706
|
-
});
|
|
2707
|
-
this.statusContainer.addChild(this.retryLoader);
|
|
2700
|
+
this.showStatusIndicator(new RetryStatusIndicator(this.ui, event.attempt, event.maxAttempts, event.delayMs));
|
|
2708
2701
|
this.ui.requestRender();
|
|
2709
2702
|
break;
|
|
2710
2703
|
}
|
|
@@ -2714,16 +2707,7 @@ export class InteractiveMode {
|
|
|
2714
2707
|
this.defaultEditor.onEscape = this.retryEscapeHandler;
|
|
2715
2708
|
this.retryEscapeHandler = undefined;
|
|
2716
2709
|
}
|
|
2717
|
-
|
|
2718
|
-
this.retryCountdown.dispose();
|
|
2719
|
-
this.retryCountdown = undefined;
|
|
2720
|
-
}
|
|
2721
|
-
// Stop loader
|
|
2722
|
-
if (this.retryLoader) {
|
|
2723
|
-
this.retryLoader.stop();
|
|
2724
|
-
this.retryLoader = undefined;
|
|
2725
|
-
this.statusContainer.clear();
|
|
2726
|
-
}
|
|
2710
|
+
this.clearStatusIndicator("retry");
|
|
2727
2711
|
// Show error only on final failure (success shows normal response)
|
|
2728
2712
|
if (!event.success) {
|
|
2729
2713
|
this.showError(`Retry failed after ${event.attempt} attempts: ${event.finalError || "Unknown error"}`);
|
|
@@ -2765,6 +2749,25 @@ export class InteractiveMode {
|
|
|
2765
2749
|
this.lastStatusText = text;
|
|
2766
2750
|
this.ui.requestRender();
|
|
2767
2751
|
}
|
|
2752
|
+
addCustomEntryToChat(entry) {
|
|
2753
|
+
const renderer = this.session.extensionRunner.getEntryRenderer(entry.customType);
|
|
2754
|
+
if (!renderer) {
|
|
2755
|
+
return;
|
|
2756
|
+
}
|
|
2757
|
+
const component = new CustomEntryComponent(entry, renderer);
|
|
2758
|
+
component.setExpanded(this.toolOutputExpanded);
|
|
2759
|
+
if (!component.hasContent()) {
|
|
2760
|
+
return;
|
|
2761
|
+
}
|
|
2762
|
+
if (this.streamingComponent) {
|
|
2763
|
+
const streamingIndex = this.chatContainer.children.indexOf(this.streamingComponent);
|
|
2764
|
+
if (streamingIndex >= 0) {
|
|
2765
|
+
this.chatContainer.children.splice(streamingIndex, 0, component);
|
|
2766
|
+
return;
|
|
2767
|
+
}
|
|
2768
|
+
}
|
|
2769
|
+
this.chatContainer.addChild(component);
|
|
2770
|
+
}
|
|
2768
2771
|
addMessageToChat(message, options) {
|
|
2769
2772
|
switch (message.role) {
|
|
2770
2773
|
case "bashExecution": {
|
|
@@ -2814,12 +2817,12 @@ export class InteractiveMode {
|
|
|
2814
2817
|
// Render user message separately if present
|
|
2815
2818
|
if (skillBlock.userMessage) {
|
|
2816
2819
|
this.chatContainer.addChild(new Spacer(1));
|
|
2817
|
-
const userComponent = new UserMessageComponent(skillBlock.userMessage, this.getMarkdownThemeWithSettings());
|
|
2820
|
+
const userComponent = new UserMessageComponent(skillBlock.userMessage, this.getMarkdownThemeWithSettings(), this.outputPad);
|
|
2818
2821
|
this.chatContainer.addChild(userComponent);
|
|
2819
2822
|
}
|
|
2820
2823
|
}
|
|
2821
2824
|
else {
|
|
2822
|
-
const userComponent = new UserMessageComponent(textContent, this.getMarkdownThemeWithSettings());
|
|
2825
|
+
const userComponent = new UserMessageComponent(textContent, this.getMarkdownThemeWithSettings(), this.outputPad);
|
|
2823
2826
|
this.chatContainer.addChild(userComponent);
|
|
2824
2827
|
}
|
|
2825
2828
|
if (options?.populateHistory) {
|
|
@@ -2829,7 +2832,7 @@ export class InteractiveMode {
|
|
|
2829
2832
|
break;
|
|
2830
2833
|
}
|
|
2831
2834
|
case "assistant": {
|
|
2832
|
-
const assistantComponent = new AssistantMessageComponent(message, this.hideThinkingBlock, this.getMarkdownThemeWithSettings(), this.hiddenThinkingLabel);
|
|
2835
|
+
const assistantComponent = new AssistantMessageComponent(message, this.hideThinkingBlock, this.getMarkdownThemeWithSettings(), this.hiddenThinkingLabel, this.outputPad);
|
|
2833
2836
|
assistantComponent.setExpanded(this.toolOutputExpanded);
|
|
2834
2837
|
this.chatContainer.addChild(assistantComponent);
|
|
2835
2838
|
break;
|
|
@@ -2844,20 +2847,19 @@ export class InteractiveMode {
|
|
|
2844
2847
|
}
|
|
2845
2848
|
}
|
|
2846
2849
|
}
|
|
2847
|
-
|
|
2848
|
-
* Render session context to chat. Used for initial load and rebuild after compaction.
|
|
2849
|
-
* @param sessionContext Session context to render
|
|
2850
|
-
* @param options.updateFooter Update footer state
|
|
2851
|
-
* @param options.populateHistory Add user messages to editor history
|
|
2852
|
-
*/
|
|
2853
|
-
renderSessionContext(sessionContext, options = {}) {
|
|
2850
|
+
renderSessionItems(items, options = {}) {
|
|
2854
2851
|
this.clearPendingTools();
|
|
2855
2852
|
const renderedPendingTools = new Map();
|
|
2856
2853
|
if (options.updateFooter) {
|
|
2857
2854
|
this.footer.invalidate();
|
|
2858
2855
|
this.updateEditorBorderColor();
|
|
2859
2856
|
}
|
|
2860
|
-
for (const
|
|
2857
|
+
for (const item of items) {
|
|
2858
|
+
if (isCustomSessionEntry(item)) {
|
|
2859
|
+
this.addCustomEntryToChat(item);
|
|
2860
|
+
continue;
|
|
2861
|
+
}
|
|
2862
|
+
const message = item;
|
|
2861
2863
|
// Assistant messages need special handling for tool calls
|
|
2862
2864
|
if (message.role === "assistant") {
|
|
2863
2865
|
this.addMessageToChat(message);
|
|
@@ -2904,10 +2906,24 @@ export class InteractiveMode {
|
|
|
2904
2906
|
}
|
|
2905
2907
|
this.ui.requestRender();
|
|
2906
2908
|
}
|
|
2909
|
+
/**
|
|
2910
|
+
* Render session entries to chat. Used for initial load and rebuild after compaction.
|
|
2911
|
+
* @param entries Compaction-aware session entries to render
|
|
2912
|
+
* @param options.updateFooter Update footer state
|
|
2913
|
+
* @param options.populateHistory Add user messages to editor history
|
|
2914
|
+
*/
|
|
2915
|
+
renderSessionEntries(entries, options = {}) {
|
|
2916
|
+
const items = entries.flatMap((entry) => {
|
|
2917
|
+
if (entry.type === "custom") {
|
|
2918
|
+
return [entry];
|
|
2919
|
+
}
|
|
2920
|
+
return sessionEntryToContextMessages(entry);
|
|
2921
|
+
});
|
|
2922
|
+
this.renderSessionItems(items, options);
|
|
2923
|
+
}
|
|
2907
2924
|
renderInitialMessages() {
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
this.renderSessionContext(context, {
|
|
2925
|
+
const entries = this.sessionManager.buildContextEntries();
|
|
2926
|
+
this.renderSessionEntries(entries, {
|
|
2911
2927
|
updateFooter: true,
|
|
2912
2928
|
populateHistory: true,
|
|
2913
2929
|
});
|
|
@@ -2942,8 +2958,7 @@ export class InteractiveMode {
|
|
|
2942
2958
|
}
|
|
2943
2959
|
rebuildChatFromMessages() {
|
|
2944
2960
|
this.chatContainer.clear();
|
|
2945
|
-
|
|
2946
|
-
this.renderSessionContext(context);
|
|
2961
|
+
this.renderSessionEntries(this.sessionManager.buildContextEntries());
|
|
2947
2962
|
}
|
|
2948
2963
|
// =========================================================================
|
|
2949
2964
|
// Key handlers
|
|
@@ -3557,6 +3572,7 @@ export class InteractiveMode {
|
|
|
3557
3572
|
showHardwareCursor: this.settingsManager.getShowHardwareCursor(),
|
|
3558
3573
|
defaultProjectTrust: this.settingsManager.getDefaultProjectTrust(),
|
|
3559
3574
|
editorPaddingX: this.settingsManager.getEditorPaddingX(),
|
|
3575
|
+
outputPad: this.settingsManager.getOutputPad(),
|
|
3560
3576
|
autocompleteMaxVisible: this.settingsManager.getAutocompleteMaxVisible(),
|
|
3561
3577
|
quietStartup: this.settingsManager.getQuietStartup(),
|
|
3562
3578
|
clearOnShrink: this.settingsManager.getClearOnShrink(),
|
|
@@ -3658,6 +3674,23 @@ export class InteractiveMode {
|
|
|
3658
3674
|
this.editor.setPaddingX(padding);
|
|
3659
3675
|
}
|
|
3660
3676
|
},
|
|
3677
|
+
onOutputPadChange: (padding) => {
|
|
3678
|
+
this.settingsManager.setOutputPad(padding);
|
|
3679
|
+
this.outputPad = padding;
|
|
3680
|
+
if (this.streamingComponent || this.session.isStreaming) {
|
|
3681
|
+
for (const child of this.chatContainer.children) {
|
|
3682
|
+
if (child instanceof AssistantMessageComponent || child instanceof UserMessageComponent) {
|
|
3683
|
+
child.setOutputPad(padding);
|
|
3684
|
+
}
|
|
3685
|
+
}
|
|
3686
|
+
if (this.streamingComponent) {
|
|
3687
|
+
this.streamingComponent.setOutputPad(padding);
|
|
3688
|
+
}
|
|
3689
|
+
this.ui.requestRender();
|
|
3690
|
+
return;
|
|
3691
|
+
}
|
|
3692
|
+
this.rebuildChatFromMessages();
|
|
3693
|
+
},
|
|
3661
3694
|
onAutocompleteMaxVisibleChange: (maxVisible) => {
|
|
3662
3695
|
this.settingsManager.setAutocompleteMaxVisible(maxVisible);
|
|
3663
3696
|
this.defaultEditor.setAutocompleteMaxVisible(maxVisible);
|
|
@@ -3668,6 +3701,9 @@ export class InteractiveMode {
|
|
|
3668
3701
|
onClearOnShrinkChange: (enabled) => {
|
|
3669
3702
|
this.settingsManager.setClearOnShrink(enabled);
|
|
3670
3703
|
this.ui.setClearOnShrink(enabled);
|
|
3704
|
+
if (!enabled && !this.activeStatusIndicator) {
|
|
3705
|
+
this.statusContainer.clear();
|
|
3706
|
+
}
|
|
3671
3707
|
},
|
|
3672
3708
|
onShowTerminalProgressChange: (enabled) => {
|
|
3673
3709
|
this.settingsManager.setShowTerminalProgress(enabled);
|
|
@@ -3999,16 +4035,16 @@ export class InteractiveMode {
|
|
|
3999
4035
|
break;
|
|
4000
4036
|
}
|
|
4001
4037
|
}
|
|
4002
|
-
// Set up escape handler and
|
|
4003
|
-
let
|
|
4038
|
+
// Set up escape handler and status indicator if summarizing
|
|
4039
|
+
let showingSummaryIndicator = false;
|
|
4004
4040
|
const originalOnEscape = this.defaultEditor.onEscape;
|
|
4005
4041
|
if (wantsSummary) {
|
|
4006
4042
|
this.defaultEditor.onEscape = () => {
|
|
4007
4043
|
this.session.abortBranchSummary();
|
|
4008
4044
|
};
|
|
4009
4045
|
this.chatContainer.addChild(new Spacer(1));
|
|
4010
|
-
|
|
4011
|
-
|
|
4046
|
+
this.showStatusIndicator(new BranchSummaryStatusIndicator(this.ui));
|
|
4047
|
+
showingSummaryIndicator = true;
|
|
4012
4048
|
this.ui.requestRender();
|
|
4013
4049
|
}
|
|
4014
4050
|
try {
|
|
@@ -4039,9 +4075,8 @@ export class InteractiveMode {
|
|
|
4039
4075
|
this.showError(error instanceof Error ? error.message : String(error));
|
|
4040
4076
|
}
|
|
4041
4077
|
finally {
|
|
4042
|
-
if (
|
|
4043
|
-
|
|
4044
|
-
this.statusContainer.clear();
|
|
4078
|
+
if (showingSummaryIndicator) {
|
|
4079
|
+
this.clearStatusIndicator("branchSummary");
|
|
4045
4080
|
}
|
|
4046
4081
|
this.defaultEditor.onEscape = originalOnEscape;
|
|
4047
4082
|
}
|
|
@@ -4082,7 +4117,7 @@ export class InteractiveMode {
|
|
|
4082
4117
|
});
|
|
4083
4118
|
}
|
|
4084
4119
|
async handleResumeSession(sessionPath, options) {
|
|
4085
|
-
this.
|
|
4120
|
+
this.clearStatusIndicator();
|
|
4086
4121
|
try {
|
|
4087
4122
|
const result = await this.runtimeHost.switchSession(sessionPath, {
|
|
4088
4123
|
withSession: options?.withSession,
|
|
@@ -4477,6 +4512,7 @@ export class InteractiveMode {
|
|
|
4477
4512
|
return;
|
|
4478
4513
|
}
|
|
4479
4514
|
this.hideThinkingBlock = this.settingsManager.getHideThinkingBlock();
|
|
4515
|
+
this.outputPad = this.settingsManager.getOutputPad();
|
|
4480
4516
|
this.rebuildChatFromMessages();
|
|
4481
4517
|
chatRestoredBeforeSessionStart = true;
|
|
4482
4518
|
};
|
|
@@ -4500,7 +4536,11 @@ export class InteractiveMode {
|
|
|
4500
4536
|
this.editor.setAutocompleteMaxVisible?.(autocompleteMaxVisible);
|
|
4501
4537
|
}
|
|
4502
4538
|
this.ui.setShowHardwareCursor(this.settingsManager.getShowHardwareCursor());
|
|
4503
|
-
this.
|
|
4539
|
+
const clearOnShrink = this.settingsManager.getClearOnShrink();
|
|
4540
|
+
this.ui.setClearOnShrink(clearOnShrink);
|
|
4541
|
+
if (!clearOnShrink && !this.activeStatusIndicator) {
|
|
4542
|
+
this.statusContainer.clear();
|
|
4543
|
+
}
|
|
4504
4544
|
this.setupAutocompleteProvider();
|
|
4505
4545
|
const runner = this.session.extensionRunner;
|
|
4506
4546
|
this.setupExtensionShortcuts(runner);
|
|
@@ -4579,7 +4619,7 @@ export class InteractiveMode {
|
|
|
4579
4619
|
return;
|
|
4580
4620
|
}
|
|
4581
4621
|
try {
|
|
4582
|
-
this.
|
|
4622
|
+
this.clearStatusIndicator();
|
|
4583
4623
|
const result = await this.runtimeHost.importFromJsonl(inputPath);
|
|
4584
4624
|
if (result.cancelled) {
|
|
4585
4625
|
this.showStatus("Import cancelled");
|
|
@@ -4882,7 +4922,7 @@ export class InteractiveMode {
|
|
|
4882
4922
|
this.ui.requestRender();
|
|
4883
4923
|
}
|
|
4884
4924
|
async handleClearCommand() {
|
|
4885
|
-
this.
|
|
4925
|
+
this.clearStatusIndicator();
|
|
4886
4926
|
try {
|
|
4887
4927
|
const result = await this.runtimeHost.newSession();
|
|
4888
4928
|
if (result.cancelled) {
|
|
@@ -5015,8 +5055,7 @@ export class InteractiveMode {
|
|
|
5015
5055
|
this.showWarning("Nothing to compact (no messages yet)");
|
|
5016
5056
|
return;
|
|
5017
5057
|
}
|
|
5018
|
-
this.
|
|
5019
|
-
this.statusContainer.clear();
|
|
5058
|
+
this.clearStatusIndicator();
|
|
5020
5059
|
try {
|
|
5021
5060
|
await this.session.compact(customInstructions);
|
|
5022
5061
|
}
|
|
@@ -5028,7 +5067,7 @@ export class InteractiveMode {
|
|
|
5028
5067
|
if (this.settingsManager.getShowTerminalProgress()) {
|
|
5029
5068
|
this.ui.terminal.setProgress(false);
|
|
5030
5069
|
}
|
|
5031
|
-
this.
|
|
5070
|
+
this.clearStatusIndicator();
|
|
5032
5071
|
this.clearPendingTools();
|
|
5033
5072
|
this.clearActiveToolExecutionStatus();
|
|
5034
5073
|
this.clearToolHookStatuses();
|