@oh-my-pi/pi-coding-agent 15.9.67 → 15.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +136 -0
- package/dist/types/cli/args.d.ts +1 -1
- package/dist/types/cli/dry-balance-cli.d.ts +15 -1
- package/dist/types/cli/gallery-cli.d.ts +43 -0
- package/dist/types/cli/gallery-fixtures/agentic.d.ts +2 -0
- package/dist/types/cli/gallery-fixtures/codeintel.d.ts +3 -0
- package/dist/types/cli/gallery-fixtures/edit.d.ts +3 -0
- package/dist/types/cli/gallery-fixtures/fs.d.ts +2 -0
- package/dist/types/cli/gallery-fixtures/index.d.ts +4 -0
- package/dist/types/cli/gallery-fixtures/interaction.d.ts +3 -0
- package/dist/types/cli/gallery-fixtures/memory.d.ts +2 -0
- package/dist/types/cli/gallery-fixtures/misc.d.ts +3 -0
- package/dist/types/cli/gallery-fixtures/search.d.ts +3 -0
- package/dist/types/cli/gallery-fixtures/shell.d.ts +3 -0
- package/dist/types/cli/gallery-fixtures/types.d.ts +44 -0
- package/dist/types/cli/gallery-fixtures/web.d.ts +2 -0
- package/dist/types/cli/gallery-screenshot.d.ts +35 -0
- package/dist/types/commands/gallery.d.ts +47 -0
- package/dist/types/commit/analysis/conventional.d.ts +2 -2
- package/dist/types/commit/analysis/summary.d.ts +2 -2
- package/dist/types/commit/changelog/generate.d.ts +2 -2
- package/dist/types/commit/changelog/index.d.ts +2 -2
- package/dist/types/commit/map-reduce/index.d.ts +3 -3
- package/dist/types/commit/map-reduce/map-phase.d.ts +2 -2
- package/dist/types/commit/map-reduce/reduce-phase.d.ts +2 -2
- package/dist/types/commit/model-selection.d.ts +10 -4
- package/dist/types/config/api-key-resolver.d.ts +34 -0
- package/dist/types/config/keybindings.d.ts +6 -1
- package/dist/types/config/model-id-affixes.d.ts +2 -0
- package/dist/types/config/model-registry.d.ts +25 -2
- package/dist/types/config/settings-schema.d.ts +41 -6
- package/dist/types/dap/config.d.ts +14 -1
- package/dist/types/dap/types.d.ts +10 -0
- package/dist/types/extensibility/plugins/marketplace-auto-update.d.ts +8 -0
- package/dist/types/lsp/types.d.ts +10 -0
- package/dist/types/lsp/utils.d.ts +3 -2
- package/dist/types/main.d.ts +3 -2
- package/dist/types/memory-backend/index.d.ts +2 -1
- package/dist/types/memory-backend/resolve.d.ts +1 -1
- package/dist/types/memory-backend/types.d.ts +1 -1
- package/dist/types/modes/components/chat-block.d.ts +64 -0
- package/dist/types/modes/components/custom-editor.d.ts +5 -1
- package/dist/types/modes/components/overlay-box.d.ts +17 -0
- package/dist/types/modes/components/plan-review-overlay.d.ts +59 -0
- package/dist/types/modes/components/plan-toc.d.ts +41 -0
- package/dist/types/modes/components/read-tool-group.d.ts +2 -0
- package/dist/types/modes/components/tool-execution.d.ts +18 -0
- package/dist/types/modes/components/transcript-container.d.ts +11 -0
- package/dist/types/modes/controllers/command-controller.d.ts +1 -0
- package/dist/types/modes/controllers/event-controller.d.ts +0 -1
- package/dist/types/modes/controllers/extension-ui-controller.d.ts +0 -1
- package/dist/types/modes/controllers/input-controller.d.ts +1 -1
- package/dist/types/modes/controllers/selector-controller.d.ts +1 -1
- package/dist/types/modes/controllers/streaming-reveal.d.ts +22 -0
- package/dist/types/modes/controllers/tan-command-controller.d.ts +6 -0
- package/dist/types/modes/index.d.ts +5 -4
- package/dist/types/modes/interactive-mode.d.ts +16 -6
- package/dist/types/modes/setup-version.d.ts +11 -0
- package/dist/types/modes/setup-wizard/index.d.ts +2 -1
- package/dist/types/modes/setup-wizard/scenes/web-search.d.ts +2 -1
- package/dist/types/modes/theme/theme.d.ts +1 -1
- package/dist/types/modes/types.d.ts +19 -6
- package/dist/types/modes/utils/copy-targets.d.ts +21 -1
- package/dist/types/plan-mode/approved-plan.d.ts +27 -8
- package/dist/types/plan-mode/plan-protection.d.ts +4 -4
- package/dist/types/sdk.d.ts +3 -1
- package/dist/types/session/agent-session.d.ts +21 -0
- package/dist/types/session/messages.d.ts +12 -0
- package/dist/types/session/session-manager.d.ts +3 -1
- package/dist/types/slash-commands/types.d.ts +4 -6
- package/dist/types/task/executor.d.ts +14 -0
- package/dist/types/task/index.d.ts +1 -0
- package/dist/types/task/render.d.ts +3 -2
- package/dist/types/telemetry-export.d.ts +1 -1
- package/dist/types/tools/archive-reader.d.ts +5 -0
- package/dist/types/tools/ast-edit.d.ts +3 -0
- package/dist/types/tools/ast-grep.d.ts +3 -0
- package/dist/types/tools/bash.d.ts +1 -0
- package/dist/types/tools/eval-render.d.ts +1 -8
- package/dist/types/tools/fetch.d.ts +15 -7
- package/dist/types/tools/find.d.ts +8 -4
- package/dist/types/tools/grouped-file-output.d.ts +95 -12
- package/dist/types/tools/memory-render.d.ts +4 -1
- package/dist/types/tools/plan-mode-guard.d.ts +8 -9
- package/dist/types/tools/render-utils.d.ts +13 -9
- package/dist/types/tools/renderers.d.ts +16 -2
- package/dist/types/tools/search.d.ts +5 -1
- package/dist/types/tools/sqlite-reader.d.ts +1 -0
- package/dist/types/tools/todo.d.ts +3 -2
- package/dist/types/tools/write.d.ts +5 -0
- package/dist/types/tui/output-block.d.ts +16 -4
- package/dist/types/tui/status-line.d.ts +3 -0
- package/dist/types/utils/enhanced-paste.d.ts +20 -0
- package/dist/types/web/scrapers/github.d.ts +22 -0
- package/dist/types/web/search/providers/kimi.d.ts +1 -1
- package/dist/types/web/search/providers/perplexity.d.ts +8 -1
- package/dist/types/web/search/types.d.ts +1 -1
- package/package.json +9 -9
- package/scripts/dev-launch +42 -0
- package/scripts/dev-launch-preload.ts +19 -0
- package/src/auto-thinking/classifier.ts +5 -1
- package/src/cli/args.ts +2 -2
- package/src/cli/dry-balance-cli.ts +52 -17
- package/src/cli/gallery-cli.ts +226 -0
- package/src/cli/gallery-fixtures/agentic.ts +292 -0
- package/src/cli/gallery-fixtures/codeintel.ts +188 -0
- package/src/cli/gallery-fixtures/edit.ts +194 -0
- package/src/cli/gallery-fixtures/fs.ts +153 -0
- package/src/cli/gallery-fixtures/index.ts +40 -0
- package/src/cli/gallery-fixtures/interaction.ts +49 -0
- package/src/cli/gallery-fixtures/memory.ts +81 -0
- package/src/cli/gallery-fixtures/misc.ts +250 -0
- package/src/cli/gallery-fixtures/search.ts +213 -0
- package/src/cli/gallery-fixtures/shell.ts +167 -0
- package/src/cli/gallery-fixtures/types.ts +41 -0
- package/src/cli/gallery-fixtures/web.ts +158 -0
- package/src/cli/gallery-screenshot.ts +279 -0
- package/src/cli-commands.ts +1 -0
- package/src/commands/gallery.ts +52 -0
- package/src/commands/launch.ts +1 -1
- package/src/commit/analysis/conventional.ts +2 -2
- package/src/commit/analysis/summary.ts +2 -2
- package/src/commit/changelog/generate.ts +2 -2
- package/src/commit/changelog/index.ts +2 -2
- package/src/commit/map-reduce/index.ts +3 -3
- package/src/commit/map-reduce/map-phase.ts +2 -2
- package/src/commit/map-reduce/reduce-phase.ts +2 -2
- package/src/commit/model-selection.ts +33 -9
- package/src/commit/pipeline.ts +4 -4
- package/src/config/api-key-resolver.ts +58 -0
- package/src/config/keybindings.ts +15 -6
- package/src/config/model-equivalence.ts +35 -12
- package/src/config/model-id-affixes.ts +39 -22
- package/src/config/model-registry.ts +41 -18
- package/src/config/settings-schema.ts +28 -5
- package/src/config/settings.ts +31 -2
- package/src/dap/client.ts +14 -16
- package/src/dap/config.ts +41 -2
- package/src/dap/defaults.json +1 -0
- package/src/dap/session.ts +1 -0
- package/src/dap/types.ts +10 -0
- package/src/debug/index.ts +40 -54
- package/src/edit/renderer.ts +111 -119
- package/src/eval/__tests__/agent-bridge.test.ts +75 -32
- package/src/eval/__tests__/llm-bridge.test.ts +90 -31
- package/src/eval/agent-bridge.ts +34 -7
- package/src/eval/llm-bridge.ts +8 -3
- package/src/extensibility/extensions/runner.ts +1 -0
- package/src/extensibility/plugins/doctor.ts +0 -1
- package/src/extensibility/plugins/marketplace-auto-update.ts +49 -0
- package/src/goals/tools/goal-tool.ts +37 -27
- package/src/internal-urls/docs-index.generated.ts +10 -10
- package/src/lsp/client.ts +104 -55
- package/src/lsp/types.ts +10 -0
- package/src/lsp/utils.ts +3 -2
- package/src/main.ts +53 -56
- package/src/memories/index.ts +12 -5
- package/src/memory-backend/index.ts +13 -1
- package/src/memory-backend/resolve.ts +3 -5
- package/src/memory-backend/types.ts +1 -1
- package/src/mnemopi/backend.ts +5 -1
- package/src/modes/acp/acp-agent.ts +33 -26
- package/src/modes/components/assistant-message.ts +2 -9
- package/src/modes/components/chat-block.ts +111 -0
- package/src/modes/components/copy-selector.ts +1 -44
- package/src/modes/components/custom-editor.ts +33 -1
- package/src/modes/components/custom-message.ts +1 -3
- package/src/modes/components/execution-shared.ts +1 -2
- package/src/modes/components/hook-message.ts +1 -3
- package/src/modes/components/overlay-box.ts +108 -0
- package/src/modes/components/plan-review-overlay.ts +799 -0
- package/src/modes/components/plan-toc.ts +138 -0
- package/src/modes/components/read-tool-group.ts +20 -4
- package/src/modes/components/skill-message.ts +0 -1
- package/src/modes/components/status-line.ts +3 -5
- package/src/modes/components/tips.txt +1 -0
- package/src/modes/components/todo-reminder.ts +0 -2
- package/src/modes/components/tool-execution.ts +115 -90
- package/src/modes/components/transcript-container.ts +84 -24
- package/src/modes/components/user-message.ts +1 -2
- package/src/modes/controllers/command-controller-shared.ts +7 -6
- package/src/modes/controllers/command-controller.ts +70 -57
- package/src/modes/controllers/event-controller.ts +41 -40
- package/src/modes/controllers/extension-ui-controller.ts +10 -73
- package/src/modes/controllers/input-controller.ts +135 -122
- package/src/modes/controllers/mcp-command-controller.ts +69 -60
- package/src/modes/controllers/selector-controller.ts +25 -27
- package/src/modes/controllers/streaming-reveal.ts +212 -0
- package/src/modes/controllers/tan-command-controller.ts +173 -0
- package/src/modes/index.ts +5 -4
- package/src/modes/interactive-mode.ts +171 -82
- package/src/modes/setup-version.ts +11 -0
- package/src/modes/setup-wizard/index.ts +3 -2
- package/src/modes/setup-wizard/scenes/web-search.ts +3 -2
- package/src/modes/setup-wizard/wizard-overlay.ts +1 -1
- package/src/modes/theme/theme-schema.json +1 -1
- package/src/modes/theme/theme.ts +8 -4
- package/src/modes/types.ts +19 -8
- package/src/modes/utils/context-usage.ts +10 -6
- package/src/modes/utils/copy-targets.ts +133 -27
- package/src/modes/utils/hotkeys-markdown.ts +1 -0
- package/src/modes/utils/ui-helpers.ts +44 -46
- package/src/plan-mode/approved-plan.ts +66 -43
- package/src/plan-mode/plan-protection.ts +4 -4
- package/src/prompts/system/background-tan-dispatch.md +8 -0
- package/src/prompts/system/plan-mode-active.md +67 -58
- package/src/prompts/system/plan-mode-approved.md +1 -1
- package/src/sdk.ts +32 -60
- package/src/session/agent-session.ts +89 -13
- package/src/session/messages.ts +26 -0
- package/src/session/session-manager.ts +13 -5
- package/src/slash-commands/builtin-registry.ts +37 -10
- package/src/slash-commands/helpers/usage-report.ts +2 -0
- package/src/slash-commands/types.ts +4 -6
- package/src/task/executor.ts +25 -4
- package/src/task/index.ts +4 -0
- package/src/task/render.ts +212 -148
- package/src/telemetry-export.ts +25 -7
- package/src/tools/archive-reader.ts +64 -0
- package/src/tools/ask.ts +119 -164
- package/src/tools/ast-edit.ts +98 -71
- package/src/tools/ast-grep.ts +37 -43
- package/src/tools/bash.ts +50 -6
- package/src/tools/debug.ts +20 -8
- package/src/tools/eval-backends.ts +6 -17
- package/src/tools/eval-render.ts +21 -18
- package/src/tools/eval.ts +5 -4
- package/src/tools/fetch.ts +391 -91
- package/src/tools/find.ts +44 -30
- package/src/tools/gh-renderer.ts +81 -42
- package/src/tools/grouped-file-output.ts +272 -48
- package/src/tools/image-gen.ts +150 -103
- package/src/tools/inspect-image-renderer.ts +63 -41
- package/src/tools/inspect-image.ts +8 -1
- package/src/tools/job.ts +3 -4
- package/src/tools/memory-render.ts +4 -1
- package/src/tools/plan-mode-guard.ts +21 -39
- package/src/tools/read.ts +23 -16
- package/src/tools/render-utils.ts +38 -40
- package/src/tools/renderers.ts +16 -1
- package/src/tools/report-tool-issue.ts +1 -1
- package/src/tools/resolve.ts +14 -0
- package/src/tools/search-tool-bm25.ts +36 -23
- package/src/tools/search.ts +189 -95
- package/src/tools/sqlite-reader.ts +9 -12
- package/src/tools/todo.ts +138 -59
- package/src/tools/write.ts +100 -60
- package/src/tui/output-block.ts +60 -13
- package/src/tui/status-line.ts +5 -1
- package/src/utils/commit-message-generator.ts +9 -1
- package/src/utils/enhanced-paste.ts +202 -0
- package/src/utils/title-generator.ts +2 -1
- package/src/web/scrapers/github.ts +255 -3
- package/src/web/scrapers/youtube.ts +3 -2
- package/src/web/search/providers/anthropic.ts +25 -19
- package/src/web/search/providers/exa.ts +11 -3
- package/src/web/search/providers/kimi.ts +28 -17
- package/src/web/search/providers/parallel.ts +35 -24
- package/src/web/search/providers/perplexity.ts +199 -51
- package/src/web/search/providers/synthetic.ts +8 -6
- package/src/web/search/providers/tavily.ts +9 -8
- package/src/web/search/providers/zai.ts +8 -6
- package/src/web/search/render.ts +39 -54
- package/src/web/search/types.ts +5 -1
- package/dist/types/eval/__tests__/shared-executors.test.d.ts +0 -1
- package/src/eval/__tests__/shared-executors.test.ts +0 -609
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as fs from "node:fs/promises";
|
|
2
|
+
import type { ImageContent } from "@oh-my-pi/pi-ai";
|
|
2
3
|
import type { AutocompleteProvider, SlashCommand } from "@oh-my-pi/pi-tui";
|
|
3
4
|
import { $env, logger, sanitizeText } from "@oh-my-pi/pi-utils";
|
|
4
5
|
import { getRoleInfo } from "../../config/model-registry";
|
|
@@ -9,16 +10,16 @@ import { expandEmoticons } from "../../modes/emoji-autocomplete";
|
|
|
9
10
|
import { materializeImageReferenceLinks } from "../../modes/image-references";
|
|
10
11
|
import { createPromptActionAutocompleteProvider } from "../../modes/prompt-action-autocomplete";
|
|
11
12
|
import type { InteractiveModeContext } from "../../modes/types";
|
|
12
|
-
import type
|
|
13
|
-
import { SKILL_PROMPT_MESSAGE_TYPE, type SkillPromptDetails } from "../../session/messages";
|
|
13
|
+
import { SKILL_PROMPT_MESSAGE_TYPE, type SkillPromptDetails, USER_INTERRUPT_LABEL } from "../../session/messages";
|
|
14
14
|
import { executeBuiltinSlashCommand } from "../../slash-commands/builtin-registry";
|
|
15
15
|
import { isTinyTitleLocalModelKey } from "../../tiny/models";
|
|
16
16
|
import { isLowSignalTitleInput } from "../../tiny/text";
|
|
17
17
|
import { tinyTitleClient } from "../../tiny/title-client";
|
|
18
18
|
import type { TinyTitleProgressEvent } from "../../tiny/title-protocol";
|
|
19
19
|
import { copyToClipboard, readImageFromClipboard, readTextFromClipboard } from "../../utils/clipboard";
|
|
20
|
+
import { EnhancedPasteController } from "../../utils/enhanced-paste";
|
|
20
21
|
import { getEditorCommand, openInEditor } from "../../utils/external-editor";
|
|
21
|
-
import { ensureSupportedImageInput } from "../../utils/image-loading";
|
|
22
|
+
import { ensureSupportedImageInput, ImageInputTooLargeError, loadImageInput } from "../../utils/image-loading";
|
|
22
23
|
import { resizeImage } from "../../utils/image-resize";
|
|
23
24
|
import { generateSessionTitle, setSessionTerminalTitle } from "../../utils/title-generator";
|
|
24
25
|
|
|
@@ -40,8 +41,10 @@ const TINY_TITLE_PROGRESS_REVEAL_DELAY_MS = 1_000;
|
|
|
40
41
|
export class InputController {
|
|
41
42
|
constructor(private ctx: InteractiveModeContext) {}
|
|
42
43
|
|
|
44
|
+
#enhancedPaste?: EnhancedPasteController;
|
|
45
|
+
|
|
43
46
|
#showTinyTitleDownloadProgress(modelKey: string): void {
|
|
44
|
-
if (!isTinyTitleLocalModelKey(modelKey)
|
|
47
|
+
if (!isTinyTitleLocalModelKey(modelKey)) return;
|
|
45
48
|
const component = new TinyTitleDownloadProgressComponent(modelKey);
|
|
46
49
|
let added = false;
|
|
47
50
|
let disposed = false;
|
|
@@ -91,7 +94,7 @@ export class InputController {
|
|
|
91
94
|
if (this.ctx.loopModeEnabled) {
|
|
92
95
|
this.ctx.pauseLoop();
|
|
93
96
|
if (this.ctx.session.isStreaming) {
|
|
94
|
-
void this.ctx.session.abort();
|
|
97
|
+
void this.ctx.session.abort({ reason: USER_INTERRUPT_LABEL });
|
|
95
98
|
} else {
|
|
96
99
|
this.ctx.cancelPendingSubmission();
|
|
97
100
|
}
|
|
@@ -121,7 +124,7 @@ export class InputController {
|
|
|
121
124
|
this.ctx.isPythonMode = false;
|
|
122
125
|
this.ctx.updateEditorBorderColor();
|
|
123
126
|
} else if (this.ctx.session.isStreaming) {
|
|
124
|
-
void this.ctx.session.abort();
|
|
127
|
+
void this.ctx.session.abort({ reason: USER_INTERRUPT_LABEL });
|
|
125
128
|
} else if (!this.ctx.editor.getText().trim()) {
|
|
126
129
|
// Double-interrupt with empty editor triggers /tree, /branch, or nothing based on setting
|
|
127
130
|
const action = settings.get("doubleEscapeAction");
|
|
@@ -144,6 +147,8 @@ export class InputController {
|
|
|
144
147
|
this.ctx.editor.setActionKeys("app.clear", this.ctx.keybindings.getKeys("app.clear"));
|
|
145
148
|
this.ctx.editor.onClear = () => this.handleCtrlC();
|
|
146
149
|
this.ctx.editor.setActionKeys("app.exit", this.ctx.keybindings.getKeys("app.exit"));
|
|
150
|
+
this.ctx.editor.setActionKeys("app.display.reset", this.ctx.keybindings.getKeys("app.display.reset"));
|
|
151
|
+
this.ctx.editor.onDisplayReset = () => this.ctx.ui.resetDisplay();
|
|
147
152
|
this.ctx.editor.onExit = () => this.handleCtrlD();
|
|
148
153
|
this.ctx.editor.setActionKeys("app.suspend", this.ctx.keybindings.getKeys("app.suspend"));
|
|
149
154
|
this.ctx.editor.onSuspend = () => this.handleCtrlZ();
|
|
@@ -174,6 +179,7 @@ export class InputController {
|
|
|
174
179
|
this.ctx.keybindings.getKeys("app.clipboard.pasteImage"),
|
|
175
180
|
);
|
|
176
181
|
this.ctx.editor.onPasteImage = () => this.handleImagePaste();
|
|
182
|
+
this.ctx.editor.onPasteImagePath = path => void this.handleImagePathPaste(path);
|
|
177
183
|
this.ctx.editor.setActionKeys(
|
|
178
184
|
"app.clipboard.pasteTextRaw",
|
|
179
185
|
this.ctx.keybindings.getKeys("app.clipboard.pasteTextRaw"),
|
|
@@ -188,11 +194,9 @@ export class InputController {
|
|
|
188
194
|
this.ctx.editor.onExpandTools = () => this.toggleToolOutputExpansion();
|
|
189
195
|
this.ctx.editor.setActionKeys("app.message.dequeue", this.ctx.keybindings.getKeys("app.message.dequeue"));
|
|
190
196
|
this.ctx.editor.onDequeue = () => this.handleDequeue();
|
|
191
|
-
|
|
192
197
|
this.ctx.editor.clearCustomKeyHandlers();
|
|
193
198
|
// Wire up extension shortcuts
|
|
194
199
|
this.registerExtensionShortcuts();
|
|
195
|
-
|
|
196
200
|
const planModeKeys = this.ctx.keybindings.getKeys("app.plan.toggle");
|
|
197
201
|
for (const key of planModeKeys) {
|
|
198
202
|
this.ctx.editor.setCustomKeyHandler(key, () => void this.ctx.handlePlanModeCommand());
|
|
@@ -223,6 +227,8 @@ export class InputController {
|
|
|
223
227
|
this.ctx.editor.setCustomKeyHandler(key, () => this.ctx.showSessionObserver());
|
|
224
228
|
}
|
|
225
229
|
|
|
230
|
+
this.#setupEnhancedPaste();
|
|
231
|
+
|
|
226
232
|
this.ctx.editor.onChange = (text: string) => {
|
|
227
233
|
const wasBashMode = this.ctx.isBashMode;
|
|
228
234
|
const wasPythonMode = this.ctx.isPythonMode;
|
|
@@ -235,16 +241,45 @@ export class InputController {
|
|
|
235
241
|
};
|
|
236
242
|
}
|
|
237
243
|
|
|
244
|
+
#setupEnhancedPaste(): void {
|
|
245
|
+
if (this.#enhancedPaste) return;
|
|
246
|
+
|
|
247
|
+
this.#enhancedPaste = new EnhancedPasteController({
|
|
248
|
+
write: data => this.ctx.ui.terminal.write(data),
|
|
249
|
+
pasteText: text => {
|
|
250
|
+
this.ctx.editor.pasteText(text);
|
|
251
|
+
this.ctx.ui.requestRender(false, { allowUnknownViewportMutation: true });
|
|
252
|
+
},
|
|
253
|
+
pasteImage: async image => {
|
|
254
|
+
await this.#normalizeAndInsertPastedImage(image, `Unsupported pasted image format: ${image.mimeType}`);
|
|
255
|
+
},
|
|
256
|
+
showStatus: message => this.ctx.showStatus(message),
|
|
257
|
+
});
|
|
258
|
+
this.ctx.ui.addInputListener(data => (this.#enhancedPaste?.handleInput(data) ? { consume: true } : undefined));
|
|
259
|
+
this.ctx.ui.addStartListener(() => this.#enhancedPaste?.enable());
|
|
260
|
+
}
|
|
261
|
+
|
|
238
262
|
setupEditorSubmitHandler(): void {
|
|
239
263
|
this.ctx.editor.onSubmit = async (text: string) => {
|
|
240
264
|
text = text.trim();
|
|
241
265
|
if ((!isSettingsInitialized() || settings.get("emojiAutocomplete")) && text) text = expandEmoticons(text);
|
|
242
266
|
|
|
243
|
-
// Empty submit while streaming with queued
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
267
|
+
// Empty submit while streaming with queued steering: interrupt now and
|
|
268
|
+
// immediately resume so the visible `Steer:` entry is sent without
|
|
269
|
+
// waiting for the current tool/model boundary.
|
|
270
|
+
if (!text && this.ctx.session.isStreaming) {
|
|
271
|
+
const queuedMessages = this.ctx.session.getQueuedMessages();
|
|
272
|
+
if (queuedMessages.steering.length > 0) {
|
|
273
|
+
await this.ctx.session.interruptAndFlushQueuedMessages({ reason: USER_INTERRUPT_LABEL });
|
|
274
|
+
this.ctx.updatePendingMessagesDisplay();
|
|
275
|
+
this.ctx.ui.requestRender();
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
if (this.ctx.session.queuedMessageCount > 0) {
|
|
279
|
+
// Preserve the existing empty-submit flush for non-steer queues.
|
|
280
|
+
await this.ctx.session.abort({ reason: USER_INTERRUPT_LABEL });
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
248
283
|
}
|
|
249
284
|
|
|
250
285
|
if (!text) return;
|
|
@@ -291,7 +326,6 @@ export class InputController {
|
|
|
291
326
|
// Handle built-in slash commands
|
|
292
327
|
const slashResult = await executeBuiltinSlashCommand(text, {
|
|
293
328
|
ctx: this.ctx,
|
|
294
|
-
handleBackgroundCommand: () => this.handleBackgroundCommand(),
|
|
295
329
|
});
|
|
296
330
|
if (slashResult === true) {
|
|
297
331
|
return;
|
|
@@ -600,7 +634,7 @@ export class InputController {
|
|
|
600
634
|
if (allQueued.length === 0) {
|
|
601
635
|
this.ctx.updatePendingMessagesDisplay();
|
|
602
636
|
if (options?.abort) {
|
|
603
|
-
this.ctx.session.abort();
|
|
637
|
+
this.ctx.session.abort({ reason: USER_INTERRUPT_LABEL });
|
|
604
638
|
}
|
|
605
639
|
return 0;
|
|
606
640
|
}
|
|
@@ -610,128 +644,99 @@ export class InputController {
|
|
|
610
644
|
this.ctx.editor.setText(combinedText);
|
|
611
645
|
this.ctx.updatePendingMessagesDisplay();
|
|
612
646
|
if (options?.abort) {
|
|
613
|
-
this.ctx.session.abort();
|
|
647
|
+
this.ctx.session.abort({ reason: USER_INTERRUPT_LABEL });
|
|
614
648
|
}
|
|
615
649
|
return allQueued.length;
|
|
616
650
|
}
|
|
617
651
|
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
const backgroundUiContext = this.ctx.createBackgroundUiContext();
|
|
636
|
-
|
|
637
|
-
// Background mode disables interactive UI so tools like ask fail fast.
|
|
638
|
-
this.ctx.setToolUIContext(backgroundUiContext, false);
|
|
639
|
-
this.ctx.initializeHookRunner(backgroundUiContext, false);
|
|
640
|
-
|
|
641
|
-
if (this.ctx.loadingAnimation) {
|
|
642
|
-
this.ctx.loadingAnimation.stop();
|
|
643
|
-
this.ctx.loadingAnimation = undefined;
|
|
644
|
-
}
|
|
645
|
-
if (this.ctx.autoCompactionLoader) {
|
|
646
|
-
this.ctx.autoCompactionLoader.stop();
|
|
647
|
-
this.ctx.autoCompactionLoader = undefined;
|
|
648
|
-
}
|
|
649
|
-
if (this.ctx.retryLoader) {
|
|
650
|
-
this.ctx.retryLoader.stop();
|
|
651
|
-
this.ctx.retryLoader = undefined;
|
|
652
|
-
}
|
|
653
|
-
this.ctx.statusContainer.clear();
|
|
654
|
-
this.ctx.statusLine.dispose();
|
|
655
|
-
|
|
656
|
-
if (this.ctx.unsubscribe) {
|
|
657
|
-
this.ctx.unsubscribe();
|
|
658
|
-
}
|
|
659
|
-
this.ctx.unsubscribe = this.ctx.session.subscribe(async (event: AgentSessionEvent) => {
|
|
660
|
-
await this.ctx.handleBackgroundEvent(event);
|
|
652
|
+
async #insertPendingImage(imageData: ImageContent): Promise<void> {
|
|
653
|
+
const imageLink = (
|
|
654
|
+
await materializeImageReferenceLinks(
|
|
655
|
+
[
|
|
656
|
+
{
|
|
657
|
+
type: "image",
|
|
658
|
+
data: imageData.data,
|
|
659
|
+
mimeType: imageData.mimeType,
|
|
660
|
+
},
|
|
661
|
+
],
|
|
662
|
+
this.ctx.sessionManager.putBlob.bind(this.ctx.sessionManager),
|
|
663
|
+
)
|
|
664
|
+
)?.[0];
|
|
665
|
+
this.ctx.pendingImages.push({
|
|
666
|
+
type: "image",
|
|
667
|
+
data: imageData.data,
|
|
668
|
+
mimeType: imageData.mimeType,
|
|
661
669
|
});
|
|
670
|
+
this.ctx.pendingImageLinks.push(imageLink);
|
|
671
|
+
this.ctx.editor.imageLinks = this.ctx.pendingImageLinks;
|
|
672
|
+
const imageNum = this.ctx.pendingImages.length;
|
|
673
|
+
this.ctx.editor.insertText(`[Image #${imageNum}] `);
|
|
674
|
+
this.ctx.ui.requestRender(false, { allowUnknownViewportMutation: true });
|
|
675
|
+
}
|
|
662
676
|
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
this.ctx.
|
|
677
|
+
async #normalizeAndInsertPastedImage(image: ImageContent, unsupportedMessage: string): Promise<boolean> {
|
|
678
|
+
let imageData = await ensureSupportedImageInput(image);
|
|
679
|
+
if (!imageData) {
|
|
680
|
+
this.ctx.showStatus(unsupportedMessage);
|
|
681
|
+
return false;
|
|
667
682
|
}
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
683
|
+
if (settings.get("images.autoResize")) {
|
|
684
|
+
try {
|
|
685
|
+
const resized = await resizeImage({
|
|
686
|
+
type: "image",
|
|
687
|
+
data: imageData.data,
|
|
688
|
+
mimeType: imageData.mimeType,
|
|
689
|
+
});
|
|
690
|
+
imageData = { type: "image", data: resized.data, mimeType: resized.mimeType };
|
|
691
|
+
} catch {
|
|
692
|
+
// Keep the normalized image when resize fails.
|
|
693
|
+
}
|
|
674
694
|
}
|
|
695
|
+
await this.#insertPendingImage(imageData);
|
|
696
|
+
return true;
|
|
697
|
+
}
|
|
675
698
|
|
|
676
|
-
|
|
699
|
+
async handleImagePathPaste(path: string): Promise<void> {
|
|
700
|
+
try {
|
|
701
|
+
const image = await loadImageInput({
|
|
702
|
+
path,
|
|
703
|
+
cwd: this.ctx.sessionManager.getCwd(),
|
|
704
|
+
autoResize: false,
|
|
705
|
+
});
|
|
706
|
+
if (!image) {
|
|
707
|
+
this.ctx.editor.pasteText(path);
|
|
708
|
+
this.ctx.ui.requestRender(false, { allowUnknownViewportMutation: true });
|
|
709
|
+
this.ctx.showStatus("Pasted path is not a supported image");
|
|
710
|
+
return;
|
|
711
|
+
}
|
|
712
|
+
await this.#normalizeAndInsertPastedImage(
|
|
713
|
+
{ type: "image", data: image.data, mimeType: image.mimeType },
|
|
714
|
+
`Unsupported pasted image format: ${image.mimeType}`,
|
|
715
|
+
);
|
|
716
|
+
} catch (error) {
|
|
717
|
+
this.ctx.editor.pasteText(path);
|
|
718
|
+
this.ctx.ui.requestRender(false, { allowUnknownViewportMutation: true });
|
|
719
|
+
this.ctx.showStatus(
|
|
720
|
+
error instanceof ImageInputTooLargeError ? error.message : "Failed to read pasted image path",
|
|
721
|
+
);
|
|
722
|
+
}
|
|
677
723
|
}
|
|
678
724
|
|
|
679
725
|
async handleImagePaste(): Promise<boolean> {
|
|
680
726
|
try {
|
|
681
727
|
const image = await readImageFromClipboard();
|
|
682
|
-
if (image) {
|
|
683
|
-
|
|
684
|
-
|
|
728
|
+
if (!image) {
|
|
729
|
+
this.ctx.showStatus("No image in clipboard (use terminal paste for text)");
|
|
730
|
+
return false;
|
|
731
|
+
}
|
|
732
|
+
return await this.#normalizeAndInsertPastedImage(
|
|
733
|
+
{
|
|
685
734
|
type: "image",
|
|
686
|
-
data:
|
|
735
|
+
data: image.data.toBase64(),
|
|
687
736
|
mimeType: image.mimeType,
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
return false;
|
|
692
|
-
}
|
|
693
|
-
if (settings.get("images.autoResize")) {
|
|
694
|
-
try {
|
|
695
|
-
const resized = await resizeImage({
|
|
696
|
-
type: "image",
|
|
697
|
-
data: imageData.data,
|
|
698
|
-
mimeType: imageData.mimeType,
|
|
699
|
-
});
|
|
700
|
-
imageData = { type: "image", data: resized.data, mimeType: resized.mimeType };
|
|
701
|
-
} catch {
|
|
702
|
-
// Keep the normalized image when resize fails.
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
|
|
706
|
-
const imageLink = (
|
|
707
|
-
await materializeImageReferenceLinks(
|
|
708
|
-
[
|
|
709
|
-
{
|
|
710
|
-
type: "image",
|
|
711
|
-
data: imageData.data,
|
|
712
|
-
mimeType: imageData.mimeType,
|
|
713
|
-
},
|
|
714
|
-
],
|
|
715
|
-
this.ctx.sessionManager.putBlob.bind(this.ctx.sessionManager),
|
|
716
|
-
)
|
|
717
|
-
)?.[0];
|
|
718
|
-
this.ctx.pendingImages.push({
|
|
719
|
-
type: "image",
|
|
720
|
-
data: imageData.data,
|
|
721
|
-
mimeType: imageData.mimeType,
|
|
722
|
-
});
|
|
723
|
-
this.ctx.pendingImageLinks.push(imageLink);
|
|
724
|
-
this.ctx.editor.imageLinks = this.ctx.pendingImageLinks;
|
|
725
|
-
// Insert placeholder at cursor like Claude does
|
|
726
|
-
const imageNum = this.ctx.pendingImages.length;
|
|
727
|
-
const placeholder = `[Image #${imageNum}]`;
|
|
728
|
-
this.ctx.editor.insertText(`${placeholder} `);
|
|
729
|
-
this.ctx.ui.requestRender();
|
|
730
|
-
return true;
|
|
731
|
-
}
|
|
732
|
-
// No image in clipboard - show hint
|
|
733
|
-
this.ctx.showStatus("No image in clipboard (use terminal paste for text)");
|
|
734
|
-
return false;
|
|
737
|
+
},
|
|
738
|
+
`Unsupported clipboard image format: ${image.mimeType}`,
|
|
739
|
+
);
|
|
735
740
|
} catch {
|
|
736
741
|
this.ctx.showStatus("Failed to read clipboard");
|
|
737
742
|
return false;
|
|
@@ -846,7 +851,15 @@ export class InputController {
|
|
|
846
851
|
child.setExpanded(expanded);
|
|
847
852
|
}
|
|
848
853
|
}
|
|
849
|
-
|
|
854
|
+
// Toggling expansion mutates every block, but on ED3-risk terminals the
|
|
855
|
+
// transcript freezes a snapshot of each block once it scrolls past the live
|
|
856
|
+
// region (committed native scrollback is immutable there). A plain repaint
|
|
857
|
+
// replays those stale snapshots, so the toggle appears to do nothing above
|
|
858
|
+
// the live block. resetDisplay() invalidates the snapshots and forces a
|
|
859
|
+
// full clear + replay — the keyboard-accessible resize-reset equivalent —
|
|
860
|
+
// which is the only path that re-emits the whole transcript at its new
|
|
861
|
+
// heights.
|
|
862
|
+
this.ctx.ui.resetDisplay();
|
|
850
863
|
}
|
|
851
864
|
|
|
852
865
|
toggleThinkingBlockVisibility(): void {
|
|
@@ -37,7 +37,9 @@ import type { MCPAuthConfig, MCPServerConfig, MCPServerConnection } from "../../
|
|
|
37
37
|
import type { OAuthCredential } from "../../session/auth-storage";
|
|
38
38
|
import { shortenPath } from "../../tools/render-utils";
|
|
39
39
|
import { openPath } from "../../utils/open";
|
|
40
|
+
import { ChatBlock } from "../components/chat-block";
|
|
40
41
|
import { MCPAddWizard } from "../components/mcp-add-wizard";
|
|
42
|
+
import { TranscriptBlock } from "../components/transcript-container";
|
|
41
43
|
import { parseCommandArgs } from "../shared";
|
|
42
44
|
import { theme } from "../theme/theme";
|
|
43
45
|
import type { InteractiveModeContext } from "../types";
|
|
@@ -49,6 +51,42 @@ function withTimeout<T>(promise: Promise<T>, timeoutMs: number, message: string)
|
|
|
49
51
|
return Promise.race([promise, timeoutPromise]).finally(() => clearTimeout(timer));
|
|
50
52
|
}
|
|
51
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Animated "Connecting to …" transcript block. Owns its spinner interval: it
|
|
56
|
+
* starts on mount and is cleared on {@link ChatBlock.finish}/dispose, so callers
|
|
57
|
+
* never juggle `setInterval`/`clearInterval` or `requestRender` by hand.
|
|
58
|
+
*/
|
|
59
|
+
class McpConnectingBlock extends ChatBlock {
|
|
60
|
+
readonly #text: Text;
|
|
61
|
+
|
|
62
|
+
constructor(private readonly serverName: string) {
|
|
63
|
+
super();
|
|
64
|
+
this.addChild(new Spacer(1));
|
|
65
|
+
const frame = theme.spinnerFrames[0] ?? "|";
|
|
66
|
+
this.#text = new Text(theme.fg("muted", `${frame} Connecting to "${serverName}"...`), 1, 0);
|
|
67
|
+
this.addChild(this.#text);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
protected override onMount(): void {
|
|
71
|
+
const frames = theme.spinnerFrames;
|
|
72
|
+
let frame = 0;
|
|
73
|
+
const interval = setInterval(() => {
|
|
74
|
+
frame++;
|
|
75
|
+
this.#text.setText(
|
|
76
|
+
theme.fg("muted", `${frames[frame % frames.length] ?? "|"} Connecting to "${this.serverName}"...`),
|
|
77
|
+
);
|
|
78
|
+
this.requestRender();
|
|
79
|
+
}, 80);
|
|
80
|
+
this.onCleanup(() => clearInterval(interval));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Replace the spinner line with a terminal status; pair with {@link finish}. */
|
|
84
|
+
setStatus(text: string): void {
|
|
85
|
+
this.#text.setText(text);
|
|
86
|
+
this.requestRender();
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
52
90
|
/**
|
|
53
91
|
* Outcome of {@link MCPCommandController}'s OAuth handler.
|
|
54
92
|
*
|
|
@@ -547,63 +585,45 @@ export class MCPCommandController {
|
|
|
547
585
|
},
|
|
548
586
|
{
|
|
549
587
|
onAuth: (info: { url: string; instructions?: string }) => {
|
|
550
|
-
// Show auth URL prominently in chat
|
|
551
|
-
|
|
552
|
-
this.ctx.
|
|
553
|
-
|
|
554
|
-
);
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
);
|
|
559
|
-
this.ctx.chatContainer.addChild(new Spacer(1));
|
|
560
|
-
this.ctx.chatContainer.addChild(
|
|
588
|
+
// Show auth URL prominently in chat as one block
|
|
589
|
+
const block = new TranscriptBlock();
|
|
590
|
+
this.ctx.present(block);
|
|
591
|
+
block.addChild(new Text(theme.fg("accent", "━━━ OAuth Authorization Required ━━━"), 1, 0));
|
|
592
|
+
block.addChild(new Spacer(1));
|
|
593
|
+
block.addChild(new Text(theme.fg("muted", "Preparing browser authorization..."), 1, 0));
|
|
594
|
+
block.addChild(new Spacer(1));
|
|
595
|
+
block.addChild(
|
|
561
596
|
new Text(
|
|
562
597
|
theme.fg("muted", "Waiting for authorization... (Press Ctrl+C to cancel, 5 minute timeout)"),
|
|
563
598
|
1,
|
|
564
599
|
0,
|
|
565
600
|
),
|
|
566
601
|
);
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
new Text(theme.fg("accent", "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"), 1, 0),
|
|
570
|
-
);
|
|
571
|
-
this.ctx.ui.requestRender();
|
|
602
|
+
block.addChild(new Spacer(1));
|
|
603
|
+
block.addChild(new Text(theme.fg("accent", "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"), 1, 0));
|
|
572
604
|
// Try to open browser automatically
|
|
573
605
|
try {
|
|
574
606
|
openPath(info.url);
|
|
575
607
|
|
|
576
608
|
// Show confirmation that browser should open
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
);
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
new Text(theme.fg("muted", "Alternative if browser did not open:"), 1, 0),
|
|
584
|
-
);
|
|
585
|
-
this.ctx.chatContainer.addChild(
|
|
586
|
-
new Text(theme.fg("success", "Copy this exact URL in your browser:"), 1, 0),
|
|
587
|
-
);
|
|
588
|
-
this.ctx.chatContainer.addChild(new Text(theme.fg("accent", info.url), 1, 0));
|
|
609
|
+
block.addChild(new Spacer(1));
|
|
610
|
+
block.addChild(new Text(theme.fg("success", "→ Opening browser automatically..."), 1, 0));
|
|
611
|
+
block.addChild(new Spacer(1));
|
|
612
|
+
block.addChild(new Text(theme.fg("muted", "Alternative if browser did not open:"), 1, 0));
|
|
613
|
+
block.addChild(new Text(theme.fg("success", "Copy this exact URL in your browser:"), 1, 0));
|
|
614
|
+
block.addChild(new Text(theme.fg("accent", info.url), 1, 0));
|
|
589
615
|
this.ctx.ui.requestRender();
|
|
590
616
|
} catch (_error) {
|
|
591
617
|
// Show error if browser doesn't open
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
);
|
|
596
|
-
this.ctx.chatContainer.addChild(
|
|
597
|
-
new Text(theme.fg("success", "Copy this exact URL in your browser:"), 1, 0),
|
|
598
|
-
);
|
|
599
|
-
this.ctx.chatContainer.addChild(new Text(theme.fg("accent", info.url), 1, 0));
|
|
618
|
+
block.addChild(new Spacer(1));
|
|
619
|
+
block.addChild(new Text(theme.fg("warning", "→ Could not open browser automatically"), 1, 0));
|
|
620
|
+
block.addChild(new Text(theme.fg("success", "Copy this exact URL in your browser:"), 1, 0));
|
|
621
|
+
block.addChild(new Text(theme.fg("accent", info.url), 1, 0));
|
|
600
622
|
this.ctx.ui.requestRender();
|
|
601
623
|
}
|
|
602
624
|
},
|
|
603
625
|
onProgress: (message: string) => {
|
|
604
|
-
this.ctx.
|
|
605
|
-
this.ctx.chatContainer.addChild(new Text(theme.fg("muted", message), 1, 0));
|
|
606
|
-
this.ctx.ui.requestRender();
|
|
626
|
+
this.ctx.present([new Spacer(1), new Text(theme.fg("muted", message), 1, 0)]);
|
|
607
627
|
},
|
|
608
628
|
},
|
|
609
629
|
);
|
|
@@ -611,9 +631,10 @@ export class MCPCommandController {
|
|
|
611
631
|
// Execute OAuth flow with 5 minute timeout
|
|
612
632
|
const credentials = await withTimeout(flow.login(), 5 * 60 * 1000, "OAuth flow timed out after 5 minutes");
|
|
613
633
|
|
|
614
|
-
this.ctx.
|
|
615
|
-
|
|
616
|
-
|
|
634
|
+
this.ctx.present([
|
|
635
|
+
new Spacer(1),
|
|
636
|
+
new Text(theme.fg("success", "✓ Authorization completed in browser."), 1, 0),
|
|
637
|
+
]);
|
|
617
638
|
|
|
618
639
|
// Generate a unique credential ID
|
|
619
640
|
const credentialId = `mcp_oauth_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`;
|
|
@@ -766,19 +787,8 @@ export class MCPCommandController {
|
|
|
766
787
|
): Promise<"connected" | "connecting" | "disconnected"> {
|
|
767
788
|
if (!this.ctx.mcpManager) return "disconnected";
|
|
768
789
|
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
const initialFrame = frames[0] ?? "|";
|
|
772
|
-
const statusText = new Text(theme.fg("muted", `${initialFrame} Connecting to "${name}"...`), 1, 0);
|
|
773
|
-
this.ctx.chatContainer.addChild(statusText);
|
|
774
|
-
this.ctx.ui.requestRender();
|
|
775
|
-
|
|
776
|
-
let frame = 0;
|
|
777
|
-
const interval = setInterval(() => {
|
|
778
|
-
statusText.setText(theme.fg("muted", `${frames[frame % frames.length]} Connecting to "${name}"...`));
|
|
779
|
-
frame++;
|
|
780
|
-
this.ctx.ui.requestRender();
|
|
781
|
-
}, 80);
|
|
790
|
+
const block = new McpConnectingBlock(name);
|
|
791
|
+
this.ctx.present(block);
|
|
782
792
|
|
|
783
793
|
try {
|
|
784
794
|
try {
|
|
@@ -792,20 +802,19 @@ export class MCPCommandController {
|
|
|
792
802
|
await this.ctx.session.refreshMCPTools(this.ctx.mcpManager.getTools());
|
|
793
803
|
}
|
|
794
804
|
if (state === "connected") {
|
|
795
|
-
|
|
805
|
+
block.setStatus(theme.fg("success", `✓ Connected to "${name}"`));
|
|
796
806
|
} else if (state === "connecting") {
|
|
797
|
-
|
|
807
|
+
block.setStatus(theme.fg("muted", `◌ "${name}" is still connecting...`));
|
|
798
808
|
} else {
|
|
799
|
-
|
|
809
|
+
block.setStatus(
|
|
800
810
|
options?.suppressDisconnectedWarning
|
|
801
811
|
? theme.fg("muted", `◌ Connection check complete for "${name}"`)
|
|
802
812
|
: theme.fg("warning", `⚠ Could not connect to "${name}" yet`),
|
|
803
813
|
);
|
|
804
814
|
}
|
|
805
|
-
this.ctx.ui.requestRender();
|
|
806
815
|
return state;
|
|
807
816
|
} finally {
|
|
808
|
-
|
|
817
|
+
block.finish();
|
|
809
818
|
}
|
|
810
819
|
}
|
|
811
820
|
|