@code-yeongyu/senpi 2026.6.30 → 2026.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +70 -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/dynamic-prompt/build.d.ts +13 -0
- package/dist/core/dynamic-prompt/build.d.ts.map +1 -1
- package/dist/core/dynamic-prompt/build.js +24 -21
- package/dist/core/dynamic-prompt/build.js.map +1 -1
- package/dist/core/dynamic-prompt/exploration.d.ts.map +1 -1
- package/dist/core/dynamic-prompt/exploration.js +1 -3
- package/dist/core/dynamic-prompt/exploration.js.map +1 -1
- package/dist/core/dynamic-prompt/index.d.ts +1 -1
- package/dist/core/dynamic-prompt/index.d.ts.map +1 -1
- package/dist/core/dynamic-prompt/index.js.map +1 -1
- package/dist/core/dynamic-prompt/intent-gate.d.ts.map +1 -1
- package/dist/core/dynamic-prompt/intent-gate.js +20 -35
- package/dist/core/dynamic-prompt/intent-gate.js.map +1 -1
- package/dist/core/dynamic-prompt/parallel-tools.d.ts.map +1 -1
- package/dist/core/dynamic-prompt/parallel-tools.js +2 -4
- package/dist/core/dynamic-prompt/parallel-tools.js.map +1 -1
- package/dist/core/dynamic-prompt/style.d.ts.map +1 -1
- package/dist/core/dynamic-prompt/style.js +7 -26
- package/dist/core/dynamic-prompt/style.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/claude-fable-5.d.ts +3 -0
- package/dist/core/extensions/builtin/prompt-preset/claude-fable-5.d.ts.map +1 -0
- package/dist/core/extensions/builtin/prompt-preset/claude-fable-5.js +16 -0
- package/dist/core/extensions/builtin/prompt-preset/claude-fable-5.js.map +1 -0
- package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-5.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-5.js +3 -1
- package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-5.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-6.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-6.js +3 -1
- package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-6.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-7.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-7.js +6 -2
- package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-7.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-8.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-8.js +5 -3
- package/dist/core/extensions/builtin/prompt-preset/claude-opus-4-8.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.5.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.5.js +68 -8
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.5.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/presets.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/presets.js +9 -0
- package/dist/core/extensions/builtin/prompt-preset/presets.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/settings.d.ts +1 -1
- package/dist/core/extensions/builtin/prompt-preset/settings.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/settings.js +1 -0
- package/dist/core/extensions/builtin/prompt-preset/settings.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 +33 -1
- 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 +21 -27
- 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 +177 -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 +2 -1
- 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/question.ts +1 -0
- 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/anthropic-messages.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js +6 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js.map +1 -1
- 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 +16 -5
- 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 +456 -37
- 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 +82 -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 +57 -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 +46 -4
- 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 +91 -55
- package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/together.models.js +2 -2
- package/node_modules/@earendil-works/pi-ai/dist/providers/together.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 +41 -4
- 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/dist/utils/overflow.d.ts +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.js +3 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/package.json +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/mux.d.ts +4 -0
- package/node_modules/@earendil-works/pi-tui/dist/mux.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-tui/dist/mux.js +10 -0
- package/node_modules/@earendil-works/pi-tui/dist/mux.js.map +1 -0
- package/node_modules/@earendil-works/pi-tui/dist/tui.d.ts +42 -1
- package/node_modules/@earendil-works/pi-tui/dist/tui.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/tui.js +422 -101
- package/node_modules/@earendil-works/pi-tui/dist/tui.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/utils.d.ts +10 -0
- package/node_modules/@earendil-works/pi-tui/dist/utils.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/utils.js +53 -13
- package/node_modules/@earendil-works/pi-tui/dist/utils.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/package.json +2 -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;
|
|
@@ -1419,6 +1400,7 @@ export class InteractiveMode {
|
|
|
1419
1400
|
this.hookStatusIntervalId = setInterval(() => {
|
|
1420
1401
|
this.refreshToolHookStatuses();
|
|
1421
1402
|
}, DEFAULT_WORKING_STATUS_MESSAGE_ANIMATION_INTERVAL_MS);
|
|
1403
|
+
this.hookStatusIntervalId.unref();
|
|
1422
1404
|
}
|
|
1423
1405
|
stopToolHookStatusTimer() {
|
|
1424
1406
|
if (this.hookStatusIntervalId) {
|
|
@@ -1522,6 +1504,23 @@ export class InteractiveMode {
|
|
|
1522
1504
|
this.hookStatusContainer.clear();
|
|
1523
1505
|
this.stopToolHookStatusTimer();
|
|
1524
1506
|
}
|
|
1507
|
+
getWorkingElapsedSeconds() {
|
|
1508
|
+
if (this.workingStartedAt === undefined) {
|
|
1509
|
+
return 0;
|
|
1510
|
+
}
|
|
1511
|
+
return Math.max(0, Math.floor((Date.now() - this.workingStartedAt) / 1000));
|
|
1512
|
+
}
|
|
1513
|
+
getWorkingLoaderMessage() {
|
|
1514
|
+
return this.workingMessage ?? this.defaultWorkingMessage;
|
|
1515
|
+
}
|
|
1516
|
+
refreshWorkingLoaderMessage() {
|
|
1517
|
+
if (this.activeStatusIndicator?.kind === "working") {
|
|
1518
|
+
this.activeStatusIndicator.setMessage(this.getWorkingLoaderMessage());
|
|
1519
|
+
return;
|
|
1520
|
+
}
|
|
1521
|
+
const legacyLoader = this.loadingAnimation;
|
|
1522
|
+
legacyLoader?.setMessage(this.getWorkingLoaderMessage());
|
|
1523
|
+
}
|
|
1525
1524
|
getWorkingIndicatorOptions() {
|
|
1526
1525
|
return (this.workingIndicatorOptions ?? {
|
|
1527
1526
|
frames: theme.getColorMode() === "truecolor" ? ["•"] : [theme.fg("accent", "•"), theme.fg("muted", "◦")],
|
|
@@ -1539,36 +1538,53 @@ export class InteractiveMode {
|
|
|
1539
1538
|
messageIntervalMs: DEFAULT_WORKING_STATUS_MESSAGE_ANIMATION_INTERVAL_MS,
|
|
1540
1539
|
});
|
|
1541
1540
|
}
|
|
1542
|
-
|
|
1543
|
-
|
|
1541
|
+
showStatusIndicator(indicator) {
|
|
1542
|
+
if (indicator.kind === "working") {
|
|
1543
|
+
this.workingStartedAt = Date.now();
|
|
1544
|
+
}
|
|
1545
|
+
this.activeStatusIndicator?.dispose();
|
|
1546
|
+
this.activeStatusIndicator = indicator;
|
|
1547
|
+
this.statusContainer.clear();
|
|
1548
|
+
this.statusContainer.addChild(indicator);
|
|
1544
1549
|
}
|
|
1545
|
-
|
|
1546
|
-
this.
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1550
|
+
updateWorkingIndicatorMessage() {
|
|
1551
|
+
if (this.activeStatusIndicator?.kind === "working") {
|
|
1552
|
+
this.activeStatusIndicator.setMessage(this.workingMessage ?? this.defaultWorkingMessage);
|
|
1553
|
+
}
|
|
1554
|
+
}
|
|
1555
|
+
clearStatusIndicator(kind) {
|
|
1556
|
+
if (kind && this.activeStatusIndicator?.kind !== kind) {
|
|
1557
|
+
return;
|
|
1558
|
+
}
|
|
1559
|
+
const hadActiveStatusIndicator = this.activeStatusIndicator !== undefined;
|
|
1560
|
+
const isClearingWorking = this.activeStatusIndicator?.kind === "working";
|
|
1561
|
+
this.activeStatusIndicator?.dispose();
|
|
1562
|
+
this.activeStatusIndicator = undefined;
|
|
1563
|
+
if (isClearingWorking) {
|
|
1564
|
+
this.workingStartedAt = undefined;
|
|
1551
1565
|
}
|
|
1552
1566
|
this.statusContainer.clear();
|
|
1567
|
+
if (hadActiveStatusIndicator && this.ui.getClearOnShrink()) {
|
|
1568
|
+
this.statusContainer.addChild(this.idleStatus);
|
|
1569
|
+
}
|
|
1553
1570
|
}
|
|
1554
1571
|
setWorkingVisible(visible) {
|
|
1555
1572
|
this.workingVisible = visible;
|
|
1556
1573
|
if (!visible) {
|
|
1557
|
-
this.
|
|
1574
|
+
this.clearStatusIndicator("working");
|
|
1558
1575
|
this.ui.requestRender();
|
|
1559
1576
|
return;
|
|
1560
1577
|
}
|
|
1561
|
-
if (this.session.isStreaming &&
|
|
1562
|
-
this.
|
|
1563
|
-
this.startWorkingElapsedTimer();
|
|
1564
|
-
this.loadingAnimation = this.createWorkingLoader();
|
|
1565
|
-
this.statusContainer.addChild(this.loadingAnimation);
|
|
1578
|
+
if (this.session.isStreaming && this.activeStatusIndicator?.kind !== "working") {
|
|
1579
|
+
this.showStatusIndicator(new WorkingStatusIndicator(this.ui, this.workingMessage ?? this.defaultWorkingMessage, this.getWorkingIndicatorOptions()));
|
|
1566
1580
|
}
|
|
1567
1581
|
this.ui.requestRender();
|
|
1568
1582
|
}
|
|
1569
1583
|
setWorkingIndicator(options) {
|
|
1570
1584
|
this.workingIndicatorOptions = options;
|
|
1571
|
-
this.
|
|
1585
|
+
if (this.activeStatusIndicator?.kind === "working") {
|
|
1586
|
+
this.activeStatusIndicator.setIndicator(this.getWorkingIndicatorOptions());
|
|
1587
|
+
}
|
|
1572
1588
|
this.ui.requestRender();
|
|
1573
1589
|
}
|
|
1574
1590
|
setHiddenThinkingLabel(label) {
|
|
@@ -1660,7 +1676,7 @@ export class InteractiveMode {
|
|
|
1660
1676
|
this.workingMessage = undefined;
|
|
1661
1677
|
this.workingVisible = true;
|
|
1662
1678
|
this.setWorkingIndicator();
|
|
1663
|
-
this.
|
|
1679
|
+
this.updateWorkingIndicatorMessage();
|
|
1664
1680
|
this.setHiddenThinkingLabel();
|
|
1665
1681
|
this.clearToolHookStatuses();
|
|
1666
1682
|
}
|
|
@@ -1800,7 +1816,7 @@ export class InteractiveMode {
|
|
|
1800
1816
|
setStatus: (key, text) => this.setExtensionStatus(key, text),
|
|
1801
1817
|
setWorkingMessage: (message) => {
|
|
1802
1818
|
this.workingMessage = message;
|
|
1803
|
-
this.
|
|
1819
|
+
this.updateWorkingIndicatorMessage();
|
|
1804
1820
|
},
|
|
1805
1821
|
setWorkingVisible: (visible) => this.setWorkingVisible(visible),
|
|
1806
1822
|
setWorkingIndicator: (options) => this.setWorkingIndicator(options),
|
|
@@ -2443,19 +2459,11 @@ export class InteractiveMode {
|
|
|
2443
2459
|
this.defaultEditor.onEscape = this.retryEscapeHandler;
|
|
2444
2460
|
this.retryEscapeHandler = undefined;
|
|
2445
2461
|
}
|
|
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
2462
|
if (this.workingVisible) {
|
|
2456
|
-
this.
|
|
2457
|
-
|
|
2458
|
-
|
|
2463
|
+
this.showStatusIndicator(new WorkingStatusIndicator(this.ui, this.workingMessage ?? this.defaultWorkingMessage, this.getWorkingIndicatorOptions()));
|
|
2464
|
+
}
|
|
2465
|
+
else {
|
|
2466
|
+
this.clearStatusIndicator();
|
|
2459
2467
|
}
|
|
2460
2468
|
this.ui.requestRender();
|
|
2461
2469
|
break;
|
|
@@ -2466,6 +2474,12 @@ export class InteractiveMode {
|
|
|
2466
2474
|
case "system_prompt_change":
|
|
2467
2475
|
this.showStatus(event.systemPromptName ? `System prompt: ${event.systemPromptName}` : "System prompt changed");
|
|
2468
2476
|
break;
|
|
2477
|
+
case "entry_appended":
|
|
2478
|
+
if (event.entry.type === "custom") {
|
|
2479
|
+
this.addCustomEntryToChat(event.entry);
|
|
2480
|
+
this.ui.requestRender();
|
|
2481
|
+
}
|
|
2482
|
+
break;
|
|
2469
2483
|
case "session_info_changed":
|
|
2470
2484
|
this.updateTerminalTitle();
|
|
2471
2485
|
this.footer.invalidate();
|
|
@@ -2486,7 +2500,7 @@ export class InteractiveMode {
|
|
|
2486
2500
|
this.ui.requestRender();
|
|
2487
2501
|
}
|
|
2488
2502
|
else if (event.message.role === "assistant") {
|
|
2489
|
-
this.streamingComponent = new AssistantMessageComponent(undefined, this.hideThinkingBlock, this.getMarkdownThemeWithSettings(), this.hiddenThinkingLabel);
|
|
2503
|
+
this.streamingComponent = new AssistantMessageComponent(undefined, this.hideThinkingBlock, this.getMarkdownThemeWithSettings(), this.hiddenThinkingLabel, this.outputPad);
|
|
2490
2504
|
this.streamingComponent.setExpanded(this.toolOutputExpanded);
|
|
2491
2505
|
this.streamingMessage = event.message;
|
|
2492
2506
|
this.chatContainer.addChild(this.streamingComponent);
|
|
@@ -2596,7 +2610,7 @@ export class InteractiveMode {
|
|
|
2596
2610
|
if (this.settingsManager.getShowTerminalProgress()) {
|
|
2597
2611
|
this.ui.terminal.setProgress(false);
|
|
2598
2612
|
}
|
|
2599
|
-
this.
|
|
2613
|
+
this.clearStatusIndicator("working");
|
|
2600
2614
|
this.clearActiveToolExecutionStatus();
|
|
2601
2615
|
this.clearToolHookStatuses();
|
|
2602
2616
|
if (this.streamingComponent) {
|
|
@@ -2617,23 +2631,17 @@ export class InteractiveMode {
|
|
|
2617
2631
|
this.defaultEditor.onEscape = () => {
|
|
2618
2632
|
this.session.abortCompaction();
|
|
2619
2633
|
};
|
|
2634
|
+
const indicator = new CompactionStatusIndicator(this.ui, event.reason);
|
|
2635
|
+
this.activeStatusIndicator?.dispose();
|
|
2636
|
+
this.activeStatusIndicator = indicator;
|
|
2620
2637
|
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);
|
|
2638
|
+
this.statusContainer.addChild(indicator);
|
|
2631
2639
|
this.autoCompactionProgressText = "";
|
|
2632
2640
|
this.ui.requestRender();
|
|
2633
2641
|
break;
|
|
2634
2642
|
}
|
|
2635
2643
|
case "compaction_progress": {
|
|
2636
|
-
if (
|
|
2644
|
+
if (this.activeStatusIndicator?.kind !== "compaction")
|
|
2637
2645
|
break;
|
|
2638
2646
|
const nextText = event.text !== undefined ? event.text : `${this.autoCompactionProgressText}${event.delta ?? ""}`;
|
|
2639
2647
|
if (!nextText)
|
|
@@ -2641,7 +2649,7 @@ export class InteractiveMode {
|
|
|
2641
2649
|
this.autoCompactionProgressText = nextText;
|
|
2642
2650
|
const preview = nextText.length > 4_000 ? `...${nextText.slice(nextText.length - 4_000)}` : nextText;
|
|
2643
2651
|
this.statusContainer.clear();
|
|
2644
|
-
this.statusContainer.addChild(this.
|
|
2652
|
+
this.statusContainer.addChild(this.activeStatusIndicator);
|
|
2645
2653
|
this.statusContainer.addChild(new Spacer(1));
|
|
2646
2654
|
this.statusContainer.addChild(new Text(theme.fg("muted", preview), 1, 0));
|
|
2647
2655
|
this.ui.requestRender();
|
|
@@ -2655,12 +2663,8 @@ export class InteractiveMode {
|
|
|
2655
2663
|
this.defaultEditor.onEscape = this.autoCompactionEscapeHandler;
|
|
2656
2664
|
this.autoCompactionEscapeHandler = undefined;
|
|
2657
2665
|
}
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
this.autoCompactionLoader = undefined;
|
|
2661
|
-
this.autoCompactionProgressText = "";
|
|
2662
|
-
this.statusContainer.clear();
|
|
2663
|
-
}
|
|
2666
|
+
this.clearStatusIndicator("compaction");
|
|
2667
|
+
this.autoCompactionProgressText = "";
|
|
2664
2668
|
if (event.aborted) {
|
|
2665
2669
|
if (event.reason === "manual") {
|
|
2666
2670
|
this.showError("Compaction cancelled");
|
|
@@ -2694,17 +2698,7 @@ export class InteractiveMode {
|
|
|
2694
2698
|
// no separate retry-only handler is installed (the prior one only called
|
|
2695
2699
|
// session.abortRetry() and left queued steering messages stranded).
|
|
2696
2700
|
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);
|
|
2701
|
+
this.showStatusIndicator(new RetryStatusIndicator(this.ui, event.attempt, event.maxAttempts, event.delayMs));
|
|
2708
2702
|
this.ui.requestRender();
|
|
2709
2703
|
break;
|
|
2710
2704
|
}
|
|
@@ -2714,16 +2708,7 @@ export class InteractiveMode {
|
|
|
2714
2708
|
this.defaultEditor.onEscape = this.retryEscapeHandler;
|
|
2715
2709
|
this.retryEscapeHandler = undefined;
|
|
2716
2710
|
}
|
|
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
|
-
}
|
|
2711
|
+
this.clearStatusIndicator("retry");
|
|
2727
2712
|
// Show error only on final failure (success shows normal response)
|
|
2728
2713
|
if (!event.success) {
|
|
2729
2714
|
this.showError(`Retry failed after ${event.attempt} attempts: ${event.finalError || "Unknown error"}`);
|
|
@@ -2765,6 +2750,25 @@ export class InteractiveMode {
|
|
|
2765
2750
|
this.lastStatusText = text;
|
|
2766
2751
|
this.ui.requestRender();
|
|
2767
2752
|
}
|
|
2753
|
+
addCustomEntryToChat(entry) {
|
|
2754
|
+
const renderer = this.session.extensionRunner.getEntryRenderer(entry.customType);
|
|
2755
|
+
if (!renderer) {
|
|
2756
|
+
return;
|
|
2757
|
+
}
|
|
2758
|
+
const component = new CustomEntryComponent(entry, renderer);
|
|
2759
|
+
component.setExpanded(this.toolOutputExpanded);
|
|
2760
|
+
if (!component.hasContent()) {
|
|
2761
|
+
return;
|
|
2762
|
+
}
|
|
2763
|
+
if (this.streamingComponent) {
|
|
2764
|
+
const streamingIndex = this.chatContainer.children.indexOf(this.streamingComponent);
|
|
2765
|
+
if (streamingIndex >= 0) {
|
|
2766
|
+
this.chatContainer.children.splice(streamingIndex, 0, component);
|
|
2767
|
+
return;
|
|
2768
|
+
}
|
|
2769
|
+
}
|
|
2770
|
+
this.chatContainer.addChild(component);
|
|
2771
|
+
}
|
|
2768
2772
|
addMessageToChat(message, options) {
|
|
2769
2773
|
switch (message.role) {
|
|
2770
2774
|
case "bashExecution": {
|
|
@@ -2814,12 +2818,12 @@ export class InteractiveMode {
|
|
|
2814
2818
|
// Render user message separately if present
|
|
2815
2819
|
if (skillBlock.userMessage) {
|
|
2816
2820
|
this.chatContainer.addChild(new Spacer(1));
|
|
2817
|
-
const userComponent = new UserMessageComponent(skillBlock.userMessage, this.getMarkdownThemeWithSettings());
|
|
2821
|
+
const userComponent = new UserMessageComponent(skillBlock.userMessage, this.getMarkdownThemeWithSettings(), this.outputPad);
|
|
2818
2822
|
this.chatContainer.addChild(userComponent);
|
|
2819
2823
|
}
|
|
2820
2824
|
}
|
|
2821
2825
|
else {
|
|
2822
|
-
const userComponent = new UserMessageComponent(textContent, this.getMarkdownThemeWithSettings());
|
|
2826
|
+
const userComponent = new UserMessageComponent(textContent, this.getMarkdownThemeWithSettings(), this.outputPad);
|
|
2823
2827
|
this.chatContainer.addChild(userComponent);
|
|
2824
2828
|
}
|
|
2825
2829
|
if (options?.populateHistory) {
|
|
@@ -2829,7 +2833,7 @@ export class InteractiveMode {
|
|
|
2829
2833
|
break;
|
|
2830
2834
|
}
|
|
2831
2835
|
case "assistant": {
|
|
2832
|
-
const assistantComponent = new AssistantMessageComponent(message, this.hideThinkingBlock, this.getMarkdownThemeWithSettings(), this.hiddenThinkingLabel);
|
|
2836
|
+
const assistantComponent = new AssistantMessageComponent(message, this.hideThinkingBlock, this.getMarkdownThemeWithSettings(), this.hiddenThinkingLabel, this.outputPad);
|
|
2833
2837
|
assistantComponent.setExpanded(this.toolOutputExpanded);
|
|
2834
2838
|
this.chatContainer.addChild(assistantComponent);
|
|
2835
2839
|
break;
|
|
@@ -2844,20 +2848,19 @@ export class InteractiveMode {
|
|
|
2844
2848
|
}
|
|
2845
2849
|
}
|
|
2846
2850
|
}
|
|
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 = {}) {
|
|
2851
|
+
renderSessionItems(items, options = {}) {
|
|
2854
2852
|
this.clearPendingTools();
|
|
2855
2853
|
const renderedPendingTools = new Map();
|
|
2856
2854
|
if (options.updateFooter) {
|
|
2857
2855
|
this.footer.invalidate();
|
|
2858
2856
|
this.updateEditorBorderColor();
|
|
2859
2857
|
}
|
|
2860
|
-
for (const
|
|
2858
|
+
for (const item of items) {
|
|
2859
|
+
if (isCustomSessionEntry(item)) {
|
|
2860
|
+
this.addCustomEntryToChat(item);
|
|
2861
|
+
continue;
|
|
2862
|
+
}
|
|
2863
|
+
const message = item;
|
|
2861
2864
|
// Assistant messages need special handling for tool calls
|
|
2862
2865
|
if (message.role === "assistant") {
|
|
2863
2866
|
this.addMessageToChat(message);
|
|
@@ -2904,10 +2907,24 @@ export class InteractiveMode {
|
|
|
2904
2907
|
}
|
|
2905
2908
|
this.ui.requestRender();
|
|
2906
2909
|
}
|
|
2910
|
+
/**
|
|
2911
|
+
* Render session entries to chat. Used for initial load and rebuild after compaction.
|
|
2912
|
+
* @param entries Compaction-aware session entries to render
|
|
2913
|
+
* @param options.updateFooter Update footer state
|
|
2914
|
+
* @param options.populateHistory Add user messages to editor history
|
|
2915
|
+
*/
|
|
2916
|
+
renderSessionEntries(entries, options = {}) {
|
|
2917
|
+
const items = entries.flatMap((entry) => {
|
|
2918
|
+
if (entry.type === "custom") {
|
|
2919
|
+
return [entry];
|
|
2920
|
+
}
|
|
2921
|
+
return sessionEntryToContextMessages(entry);
|
|
2922
|
+
});
|
|
2923
|
+
this.renderSessionItems(items, options);
|
|
2924
|
+
}
|
|
2907
2925
|
renderInitialMessages() {
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
this.renderSessionContext(context, {
|
|
2926
|
+
const entries = this.sessionManager.buildContextEntries();
|
|
2927
|
+
this.renderSessionEntries(entries, {
|
|
2911
2928
|
updateFooter: true,
|
|
2912
2929
|
populateHistory: true,
|
|
2913
2930
|
});
|
|
@@ -2942,8 +2959,7 @@ export class InteractiveMode {
|
|
|
2942
2959
|
}
|
|
2943
2960
|
rebuildChatFromMessages() {
|
|
2944
2961
|
this.chatContainer.clear();
|
|
2945
|
-
|
|
2946
|
-
this.renderSessionContext(context);
|
|
2962
|
+
this.renderSessionEntries(this.sessionManager.buildContextEntries());
|
|
2947
2963
|
}
|
|
2948
2964
|
// =========================================================================
|
|
2949
2965
|
// Key handlers
|
|
@@ -3557,6 +3573,7 @@ export class InteractiveMode {
|
|
|
3557
3573
|
showHardwareCursor: this.settingsManager.getShowHardwareCursor(),
|
|
3558
3574
|
defaultProjectTrust: this.settingsManager.getDefaultProjectTrust(),
|
|
3559
3575
|
editorPaddingX: this.settingsManager.getEditorPaddingX(),
|
|
3576
|
+
outputPad: this.settingsManager.getOutputPad(),
|
|
3560
3577
|
autocompleteMaxVisible: this.settingsManager.getAutocompleteMaxVisible(),
|
|
3561
3578
|
quietStartup: this.settingsManager.getQuietStartup(),
|
|
3562
3579
|
clearOnShrink: this.settingsManager.getClearOnShrink(),
|
|
@@ -3658,6 +3675,23 @@ export class InteractiveMode {
|
|
|
3658
3675
|
this.editor.setPaddingX(padding);
|
|
3659
3676
|
}
|
|
3660
3677
|
},
|
|
3678
|
+
onOutputPadChange: (padding) => {
|
|
3679
|
+
this.settingsManager.setOutputPad(padding);
|
|
3680
|
+
this.outputPad = padding;
|
|
3681
|
+
if (this.streamingComponent || this.session.isStreaming) {
|
|
3682
|
+
for (const child of this.chatContainer.children) {
|
|
3683
|
+
if (child instanceof AssistantMessageComponent || child instanceof UserMessageComponent) {
|
|
3684
|
+
child.setOutputPad(padding);
|
|
3685
|
+
}
|
|
3686
|
+
}
|
|
3687
|
+
if (this.streamingComponent) {
|
|
3688
|
+
this.streamingComponent.setOutputPad(padding);
|
|
3689
|
+
}
|
|
3690
|
+
this.ui.requestRender();
|
|
3691
|
+
return;
|
|
3692
|
+
}
|
|
3693
|
+
this.rebuildChatFromMessages();
|
|
3694
|
+
},
|
|
3661
3695
|
onAutocompleteMaxVisibleChange: (maxVisible) => {
|
|
3662
3696
|
this.settingsManager.setAutocompleteMaxVisible(maxVisible);
|
|
3663
3697
|
this.defaultEditor.setAutocompleteMaxVisible(maxVisible);
|
|
@@ -3668,6 +3702,9 @@ export class InteractiveMode {
|
|
|
3668
3702
|
onClearOnShrinkChange: (enabled) => {
|
|
3669
3703
|
this.settingsManager.setClearOnShrink(enabled);
|
|
3670
3704
|
this.ui.setClearOnShrink(enabled);
|
|
3705
|
+
if (!enabled && !this.activeStatusIndicator) {
|
|
3706
|
+
this.statusContainer.clear();
|
|
3707
|
+
}
|
|
3671
3708
|
},
|
|
3672
3709
|
onShowTerminalProgressChange: (enabled) => {
|
|
3673
3710
|
this.settingsManager.setShowTerminalProgress(enabled);
|
|
@@ -3999,16 +4036,16 @@ export class InteractiveMode {
|
|
|
3999
4036
|
break;
|
|
4000
4037
|
}
|
|
4001
4038
|
}
|
|
4002
|
-
// Set up escape handler and
|
|
4003
|
-
let
|
|
4039
|
+
// Set up escape handler and status indicator if summarizing
|
|
4040
|
+
let showingSummaryIndicator = false;
|
|
4004
4041
|
const originalOnEscape = this.defaultEditor.onEscape;
|
|
4005
4042
|
if (wantsSummary) {
|
|
4006
4043
|
this.defaultEditor.onEscape = () => {
|
|
4007
4044
|
this.session.abortBranchSummary();
|
|
4008
4045
|
};
|
|
4009
4046
|
this.chatContainer.addChild(new Spacer(1));
|
|
4010
|
-
|
|
4011
|
-
|
|
4047
|
+
this.showStatusIndicator(new BranchSummaryStatusIndicator(this.ui));
|
|
4048
|
+
showingSummaryIndicator = true;
|
|
4012
4049
|
this.ui.requestRender();
|
|
4013
4050
|
}
|
|
4014
4051
|
try {
|
|
@@ -4039,9 +4076,8 @@ export class InteractiveMode {
|
|
|
4039
4076
|
this.showError(error instanceof Error ? error.message : String(error));
|
|
4040
4077
|
}
|
|
4041
4078
|
finally {
|
|
4042
|
-
if (
|
|
4043
|
-
|
|
4044
|
-
this.statusContainer.clear();
|
|
4079
|
+
if (showingSummaryIndicator) {
|
|
4080
|
+
this.clearStatusIndicator("branchSummary");
|
|
4045
4081
|
}
|
|
4046
4082
|
this.defaultEditor.onEscape = originalOnEscape;
|
|
4047
4083
|
}
|
|
@@ -4082,7 +4118,7 @@ export class InteractiveMode {
|
|
|
4082
4118
|
});
|
|
4083
4119
|
}
|
|
4084
4120
|
async handleResumeSession(sessionPath, options) {
|
|
4085
|
-
this.
|
|
4121
|
+
this.clearStatusIndicator();
|
|
4086
4122
|
try {
|
|
4087
4123
|
const result = await this.runtimeHost.switchSession(sessionPath, {
|
|
4088
4124
|
withSession: options?.withSession,
|
|
@@ -4477,6 +4513,7 @@ export class InteractiveMode {
|
|
|
4477
4513
|
return;
|
|
4478
4514
|
}
|
|
4479
4515
|
this.hideThinkingBlock = this.settingsManager.getHideThinkingBlock();
|
|
4516
|
+
this.outputPad = this.settingsManager.getOutputPad();
|
|
4480
4517
|
this.rebuildChatFromMessages();
|
|
4481
4518
|
chatRestoredBeforeSessionStart = true;
|
|
4482
4519
|
};
|
|
@@ -4500,7 +4537,11 @@ export class InteractiveMode {
|
|
|
4500
4537
|
this.editor.setAutocompleteMaxVisible?.(autocompleteMaxVisible);
|
|
4501
4538
|
}
|
|
4502
4539
|
this.ui.setShowHardwareCursor(this.settingsManager.getShowHardwareCursor());
|
|
4503
|
-
this.
|
|
4540
|
+
const clearOnShrink = this.settingsManager.getClearOnShrink();
|
|
4541
|
+
this.ui.setClearOnShrink(clearOnShrink);
|
|
4542
|
+
if (!clearOnShrink && !this.activeStatusIndicator) {
|
|
4543
|
+
this.statusContainer.clear();
|
|
4544
|
+
}
|
|
4504
4545
|
this.setupAutocompleteProvider();
|
|
4505
4546
|
const runner = this.session.extensionRunner;
|
|
4506
4547
|
this.setupExtensionShortcuts(runner);
|
|
@@ -4579,7 +4620,7 @@ export class InteractiveMode {
|
|
|
4579
4620
|
return;
|
|
4580
4621
|
}
|
|
4581
4622
|
try {
|
|
4582
|
-
this.
|
|
4623
|
+
this.clearStatusIndicator();
|
|
4583
4624
|
const result = await this.runtimeHost.importFromJsonl(inputPath);
|
|
4584
4625
|
if (result.cancelled) {
|
|
4585
4626
|
this.showStatus("Import cancelled");
|
|
@@ -4882,7 +4923,7 @@ export class InteractiveMode {
|
|
|
4882
4923
|
this.ui.requestRender();
|
|
4883
4924
|
}
|
|
4884
4925
|
async handleClearCommand() {
|
|
4885
|
-
this.
|
|
4926
|
+
this.clearStatusIndicator();
|
|
4886
4927
|
try {
|
|
4887
4928
|
const result = await this.runtimeHost.newSession();
|
|
4888
4929
|
if (result.cancelled) {
|
|
@@ -5015,8 +5056,7 @@ export class InteractiveMode {
|
|
|
5015
5056
|
this.showWarning("Nothing to compact (no messages yet)");
|
|
5016
5057
|
return;
|
|
5017
5058
|
}
|
|
5018
|
-
this.
|
|
5019
|
-
this.statusContainer.clear();
|
|
5059
|
+
this.clearStatusIndicator();
|
|
5020
5060
|
try {
|
|
5021
5061
|
await this.session.compact(customInstructions);
|
|
5022
5062
|
}
|
|
@@ -5028,7 +5068,7 @@ export class InteractiveMode {
|
|
|
5028
5068
|
if (this.settingsManager.getShowTerminalProgress()) {
|
|
5029
5069
|
this.ui.terminal.setProgress(false);
|
|
5030
5070
|
}
|
|
5031
|
-
this.
|
|
5071
|
+
this.clearStatusIndicator();
|
|
5032
5072
|
this.clearPendingTools();
|
|
5033
5073
|
this.clearActiveToolExecutionStatus();
|
|
5034
5074
|
this.clearToolHookStatuses();
|