lsd-pi 1.1.4 → 1.1.6
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/README.md +2 -1
- package/dist/headless-ui.js +2 -0
- package/dist/onboarding.js +11 -8
- package/dist/resources/extensions/async-jobs/async-bash-tool.js +14 -0
- package/dist/resources/extensions/async-jobs/await-tool.js +14 -0
- package/dist/resources/extensions/async-jobs/cancel-job-tool.js +7 -0
- package/dist/resources/extensions/cache-timer/index.js +5 -0
- package/dist/resources/extensions/codex-rotate/IMPLEMENTATION.md +18 -13
- package/dist/resources/extensions/codex-rotate/README.md +9 -3
- package/dist/resources/extensions/codex-rotate/commands.js +15 -8
- package/dist/resources/extensions/codex-rotate/index.js +17 -8
- package/dist/resources/extensions/memory/auto-extract.js +196 -80
- package/dist/resources/extensions/memory/dream.js +86 -19
- package/dist/resources/extensions/shared/rtk.js +89 -87
- package/dist/resources/extensions/subagent/index.js +33 -7
- package/dist/startup-model-validation.js +12 -2
- package/dist/update-check.js +2 -2
- package/dist/update-cmd.js +3 -3
- package/dist/welcome-screen.js +43 -14
- package/package.json +3 -2
- package/packages/pi-coding-agent/dist/core/agent-session.clear-queue.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/agent-session.clear-queue.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/agent-session.clear-queue.test.js +46 -0
- package/packages/pi-coding-agent/dist/core/agent-session.clear-queue.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts +8 -0
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +43 -4
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +3 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/keybindings.d.ts +1 -1
- package/packages/pi-coding-agent/dist/core/keybindings.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/keybindings.js +2 -0
- package/packages/pi-coding-agent/dist/core/keybindings.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/pty-executor.d.ts +48 -0
- package/packages/pi-coding-agent/dist/core/pty-executor.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/pty-executor.js +173 -0
- package/packages/pi-coding-agent/dist/core/pty-executor.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js +16 -3
- package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +9 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +18 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tool-approval.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tool-approval.js +2 -2
- package/packages/pi-coding-agent/dist/core/tool-approval.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/index.d.ts +7 -0
- package/packages/pi-coding-agent/dist/core/tools/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/index.js +23 -2
- package/packages/pi-coding-agent/dist/core/tools/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/pty.d.ts +50 -0
- package/packages/pi-coding-agent/dist/core/tools/pty.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/tools/pty.js +289 -0
- package/packages/pi-coding-agent/dist/core/tools/pty.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts +3 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +36 -22
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.d.ts +3 -5
- package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.js +23 -62
- package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/branch-summary-message.js +1 -4
- package/packages/pi-coding-agent/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/compaction-summary-message.js +1 -4
- package/packages/pi-coding-agent/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/embedded-terminal.d.ts +39 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/embedded-terminal.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/embedded-terminal.js +182 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/embedded-terminal.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +6 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +36 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.js +2 -4
- package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +1 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +106 -77
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts +2 -5
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js +4 -13
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts +11 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +49 -13
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/extension-ui-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/extension-ui-controller.js +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/extension-ui-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +3 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +27 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +251 -39
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +2 -2
- package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -1
- package/packages/pi-coding-agent/dist/utils/terminal-screen.d.ts +10 -0
- package/packages/pi-coding-agent/dist/utils/terminal-screen.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/utils/terminal-screen.js +67 -0
- package/packages/pi-coding-agent/dist/utils/terminal-screen.js.map +1 -0
- package/packages/pi-coding-agent/dist/utils/terminal-serializer.d.ts +7 -0
- package/packages/pi-coding-agent/dist/utils/terminal-serializer.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/utils/terminal-serializer.js +67 -0
- package/packages/pi-coding-agent/dist/utils/terminal-serializer.js.map +1 -0
- package/packages/pi-coding-agent/package.json +9 -4
- package/packages/pi-coding-agent/src/core/agent-session.clear-queue.test.ts +50 -0
- package/packages/pi-coding-agent/src/core/agent-session.ts +50 -4
- package/packages/pi-coding-agent/src/core/extensions/types.ts +1 -1
- package/packages/pi-coding-agent/src/core/keybindings.ts +4 -1
- package/packages/pi-coding-agent/src/core/pty-executor.ts +229 -0
- package/packages/pi-coding-agent/src/core/sdk.ts +16 -3
- package/packages/pi-coding-agent/src/core/settings-manager.ts +27 -0
- package/packages/pi-coding-agent/src/core/tool-approval.ts +2 -2
- package/packages/pi-coding-agent/src/core/tools/index.ts +35 -2
- package/packages/pi-coding-agent/src/core/tools/pty.ts +354 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +37 -24
- package/packages/pi-coding-agent/src/modes/interactive/components/bash-execution.ts +22 -70
- package/packages/pi-coding-agent/src/modes/interactive/components/branch-summary-message.ts +1 -3
- package/packages/pi-coding-agent/src/modes/interactive/components/compaction-summary-message.ts +1 -3
- package/packages/pi-coding-agent/src/modes/interactive/components/embedded-terminal.ts +224 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +45 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/skill-invocation-message.ts +2 -3
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +104 -81
- package/packages/pi-coding-agent/src/modes/interactive/components/user-message.ts +5 -19
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +55 -13
- package/packages/pi-coding-agent/src/modes/interactive/controllers/extension-ui-controller.ts +1 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +2 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +3 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +296 -48
- package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +2 -2
- package/packages/pi-coding-agent/src/utils/terminal-screen.ts +77 -0
- package/packages/pi-coding-agent/src/utils/terminal-serializer.ts +72 -0
- package/packages/pi-tui/dist/components/__tests__/editor-dropped-image.test.d.ts +2 -0
- package/packages/pi-tui/dist/components/__tests__/editor-dropped-image.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/__tests__/editor-dropped-image.test.js +105 -0
- package/packages/pi-tui/dist/components/__tests__/editor-dropped-image.test.js.map +1 -0
- package/packages/pi-tui/dist/components/editor.d.ts +4 -0
- package/packages/pi-tui/dist/components/editor.d.ts.map +1 -1
- package/packages/pi-tui/dist/components/editor.js +57 -3
- package/packages/pi-tui/dist/components/editor.js.map +1 -1
- package/packages/pi-tui/dist/components/loader.d.ts +26 -6
- package/packages/pi-tui/dist/components/loader.d.ts.map +1 -1
- package/packages/pi-tui/dist/components/loader.js +178 -18
- package/packages/pi-tui/dist/components/loader.js.map +1 -1
- package/packages/pi-tui/src/components/editor.ts +65 -3
- package/packages/pi-tui/src/components/loader.ts +196 -19
- package/pkg/dist/modes/interactive/theme/themes.js +2 -2
- package/pkg/dist/modes/interactive/theme/themes.js.map +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/async-jobs/async-bash-tool.ts +13 -0
- package/src/resources/extensions/async-jobs/await-tool.ts +13 -0
- package/src/resources/extensions/async-jobs/cancel-job-tool.ts +8 -0
- package/src/resources/extensions/cache-timer/index.ts +102 -96
- package/src/resources/extensions/codex-rotate/IMPLEMENTATION.md +18 -13
- package/src/resources/extensions/codex-rotate/README.md +9 -3
- package/src/resources/extensions/codex-rotate/commands.ts +335 -329
- package/src/resources/extensions/codex-rotate/index.ts +85 -75
- package/src/resources/extensions/memory/auto-extract.ts +330 -204
- package/src/resources/extensions/memory/dream.ts +88 -21
- package/src/resources/extensions/memory/tests/auto-extract.test.ts +200 -144
- package/src/resources/extensions/shared/rtk.js +112 -0
- package/src/resources/extensions/subagent/index.ts +35 -6
|
@@ -5,23 +5,16 @@ import { allTools } from "../../../core/tools/index.js";
|
|
|
5
5
|
import { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize } from "../../../core/tools/truncate.js";
|
|
6
6
|
import { convertToPng } from "../../../utils/image-convert.js";
|
|
7
7
|
import { sanitizeBinaryOutput } from "../../../utils/shell.js";
|
|
8
|
+
import { renderTerminalText } from "../../../utils/terminal-serializer.js";
|
|
8
9
|
import { getLanguageFromPath, highlightCode, theme } from "../theme/theme.js";
|
|
9
10
|
import { editorLink } from "../utils/editor-link.js";
|
|
10
11
|
import { shortenPath } from "../utils/shorten-path.js";
|
|
11
12
|
import { renderDiff } from "./diff.js";
|
|
12
|
-
import { keyHint } from "./keybinding-hints.js";
|
|
13
13
|
import { truncateToVisualLines } from "./visual-truncate.js";
|
|
14
14
|
// Preview line limit for bash when not expanded
|
|
15
15
|
const BASH_PREVIEW_LINES = 5;
|
|
16
|
-
// Flash interval for RTK badge animation (ms)
|
|
17
|
-
const RTK_FLASH_INTERVAL_MS = 400;
|
|
18
16
|
// Flash interval for tool status spinner (ms)
|
|
19
17
|
const SPINNER_INTERVAL_MS = 150;
|
|
20
|
-
/** Returns true when RTK is active in this process. */
|
|
21
|
-
function isRtkEnabled() {
|
|
22
|
-
const v = (process.env["GSD_RTK_DISABLED"] ?? "").trim().toLowerCase();
|
|
23
|
-
return v !== "1" && v !== "true" && v !== "yes";
|
|
24
|
-
}
|
|
25
18
|
// Spinner animation frames
|
|
26
19
|
const SPINNER_FRAMES = ["◯", "◔", "◑", "◕", "●"];
|
|
27
20
|
let spinnerFrame = 0;
|
|
@@ -63,9 +56,6 @@ export class ToolExecutionComponent extends Container {
|
|
|
63
56
|
this.convertedImages = new Map();
|
|
64
57
|
// When true, this component intentionally renders no lines
|
|
65
58
|
this.hideComponent = false;
|
|
66
|
-
// RTK badge flash state
|
|
67
|
-
this.rtkFlashOn = true;
|
|
68
|
-
this.rtkFlashTimer = null;
|
|
69
59
|
// Tool status spinner state
|
|
70
60
|
this.spinnerTimer = null;
|
|
71
61
|
this.spinnerFrame = 0;
|
|
@@ -78,8 +68,8 @@ export class ToolExecutionComponent extends Container {
|
|
|
78
68
|
this.ui = ui;
|
|
79
69
|
this.cwd = cwd;
|
|
80
70
|
// Always create both - contentBox for custom tools/bash, contentText for other built-ins
|
|
81
|
-
this.contentBox = new Box(1,
|
|
82
|
-
this.contentText = new Text("", 1,
|
|
71
|
+
this.contentBox = new Box(1, 0, (text) => theme.bg("toolPendingBg", text));
|
|
72
|
+
this.contentText = new Text("", 1, 0, (text) => theme.bg("toolPendingBg", text));
|
|
83
73
|
// Use contentBox for bash (visual truncation) or custom tools with custom renderers
|
|
84
74
|
// Use contentText for built-in tools (including overrides without custom renderers)
|
|
85
75
|
if (toolName === "bash" || (toolDefinition && !this.shouldUseBuiltInRenderer())) {
|
|
@@ -230,12 +220,6 @@ export class ToolExecutionComponent extends Container {
|
|
|
230
220
|
updateResult(result, isPartial = false) {
|
|
231
221
|
this.result = result;
|
|
232
222
|
this.isPartial = isPartial;
|
|
233
|
-
// Stop RTK flash when result arrives — settle to dim
|
|
234
|
-
if (!isPartial && this.rtkFlashTimer) {
|
|
235
|
-
clearInterval(this.rtkFlashTimer);
|
|
236
|
-
this.rtkFlashTimer = null;
|
|
237
|
-
this.rtkFlashOn = false;
|
|
238
|
-
}
|
|
239
223
|
if (this.toolName === "write" && !isPartial) {
|
|
240
224
|
const rawPath = str(this.args?.file_path ?? this.args?.path);
|
|
241
225
|
const fileContent = str(this.args?.content);
|
|
@@ -298,10 +282,6 @@ export class ToolExecutionComponent extends Container {
|
|
|
298
282
|
this.updateDisplay();
|
|
299
283
|
}
|
|
300
284
|
dispose() {
|
|
301
|
-
if (this.rtkFlashTimer) {
|
|
302
|
-
clearInterval(this.rtkFlashTimer);
|
|
303
|
-
this.rtkFlashTimer = null;
|
|
304
|
-
}
|
|
305
285
|
if (this.spinnerTimer) {
|
|
306
286
|
clearInterval(this.spinnerTimer);
|
|
307
287
|
this.spinnerTimer = null;
|
|
@@ -315,7 +295,7 @@ export class ToolExecutionComponent extends Container {
|
|
|
315
295
|
if (this.hideComponent) {
|
|
316
296
|
return [];
|
|
317
297
|
}
|
|
318
|
-
return super.render(width);
|
|
298
|
+
return [...super.render(width), ""];
|
|
319
299
|
}
|
|
320
300
|
updateDisplay() {
|
|
321
301
|
// Status indicator with circle
|
|
@@ -373,7 +353,7 @@ export class ToolExecutionComponent extends Container {
|
|
|
373
353
|
// Render call component
|
|
374
354
|
if (this.toolDefinition.renderCall) {
|
|
375
355
|
try {
|
|
376
|
-
const callComponent = this.toolDefinition.renderCall(this.args, theme);
|
|
356
|
+
const callComponent = this.toolDefinition.renderCall(this.args, theme, { statusIndicator });
|
|
377
357
|
if (callComponent !== undefined) {
|
|
378
358
|
this.contentBox.addChild(callComponent);
|
|
379
359
|
customRendererHasContent = true;
|
|
@@ -396,8 +376,9 @@ export class ToolExecutionComponent extends Container {
|
|
|
396
376
|
if (this.shouldHideCollapsedPreview()) {
|
|
397
377
|
const output = this.getTextOutput();
|
|
398
378
|
const hasDetails = output.trim().length > 0 || this.imageComponents.length > 0 || this.result.details !== undefined;
|
|
399
|
-
|
|
400
|
-
|
|
379
|
+
const collapsedHint = this.collapsedHintWithPrefix("\n");
|
|
380
|
+
if (hasDetails && collapsedHint) {
|
|
381
|
+
this.contentBox.addChild(new Text(collapsedHint, 0, 0));
|
|
401
382
|
customRendererHasContent = true;
|
|
402
383
|
}
|
|
403
384
|
}
|
|
@@ -423,7 +404,10 @@ export class ToolExecutionComponent extends Container {
|
|
|
423
404
|
const output = this.getTextOutput();
|
|
424
405
|
if (output) {
|
|
425
406
|
if (this.shouldHideCollapsedPreview()) {
|
|
426
|
-
this.
|
|
407
|
+
const collapsedHint = this.collapsedHintWithPrefix("\n");
|
|
408
|
+
if (collapsedHint) {
|
|
409
|
+
this.contentBox.addChild(new Text(collapsedHint, 0, 0));
|
|
410
|
+
}
|
|
427
411
|
}
|
|
428
412
|
else {
|
|
429
413
|
this.contentBox.addChild(new Text(theme.fg("toolOutput", output), 0, 0));
|
|
@@ -483,57 +467,50 @@ export class ToolExecutionComponent extends Container {
|
|
|
483
467
|
renderBashContent(statusIndicator) {
|
|
484
468
|
const command = str(this.args?.command);
|
|
485
469
|
const timeout = this.args?.timeout;
|
|
486
|
-
const
|
|
487
|
-
|
|
488
|
-
if (rtkActive && this.isPartial && !this.result && !this.rtkFlashTimer) {
|
|
489
|
-
this.rtkFlashTimer = setInterval(() => {
|
|
490
|
-
this.rtkFlashOn = !this.rtkFlashOn;
|
|
491
|
-
this.updateDisplay();
|
|
492
|
-
this.ui.requestRender();
|
|
493
|
-
}, RTK_FLASH_INTERVAL_MS);
|
|
494
|
-
}
|
|
495
|
-
// Header with status indicator
|
|
470
|
+
const body = new Container();
|
|
471
|
+
this.contentBox.addChild(body);
|
|
496
472
|
const timeoutSuffix = timeout ? theme.fg("muted", ` (timeout ${timeout}s)`) : "";
|
|
497
|
-
const commandDisplay = command === null
|
|
473
|
+
const commandDisplay = command === null
|
|
474
|
+
? theme.fg("error", "[invalid arg]")
|
|
475
|
+
: command
|
|
476
|
+
? theme.fg("toolOutput", command)
|
|
477
|
+
: theme.fg("toolOutput", "...");
|
|
498
478
|
const sandboxBadge = this.result?.details?.sandboxed ? ` ${theme.fg("success", "[sandboxed]")}` : "";
|
|
499
|
-
const
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
this.contentBox.addChild(new Text(`${statusIndicator} ${theme.fg("toolTitle", theme.bold(`$ ${commandDisplay}`))}${timeoutSuffix}${sandboxBadge}${rtkBadge}`, 0, 0));
|
|
479
|
+
const toolLabel = theme.fg("toolTitle", theme.bold("bash"));
|
|
480
|
+
const shellPrompt = theme.fg("muted", "$ ");
|
|
481
|
+
body.addChild(new Text(`${statusIndicator} ${toolLabel} ${shellPrompt}${commandDisplay}${timeoutSuffix}${sandboxBadge}`, 0, 0));
|
|
503
482
|
if (this.result) {
|
|
504
483
|
const output = this.getTextOutput().trim();
|
|
505
484
|
if (output) {
|
|
506
|
-
// Style each line for the output
|
|
507
485
|
const styledOutput = output
|
|
508
486
|
.split("\n")
|
|
509
487
|
.map((line) => theme.fg("toolOutput", line))
|
|
510
488
|
.join("\n");
|
|
511
489
|
if (this.expanded) {
|
|
512
|
-
|
|
513
|
-
this.contentBox.addChild(new Text(`\n${styledOutput}`, 0, 0));
|
|
490
|
+
body.addChild(new Text(`\n${styledOutput}`, 0, 0));
|
|
514
491
|
}
|
|
515
492
|
else if (this.renderMode === "minimal") {
|
|
516
|
-
this.
|
|
493
|
+
const collapsedHint = this.collapsedHintWithPrefix("\n");
|
|
494
|
+
if (collapsedHint) {
|
|
495
|
+
body.addChild(new Text(collapsedHint, 1, 0));
|
|
496
|
+
}
|
|
517
497
|
}
|
|
518
498
|
else {
|
|
519
|
-
// Use visual line truncation when collapsed with width-aware caching
|
|
520
499
|
let cachedWidth;
|
|
521
500
|
let cachedLines;
|
|
522
501
|
let cachedSkipped;
|
|
523
|
-
|
|
502
|
+
body.addChild({
|
|
524
503
|
render: (width) => {
|
|
525
504
|
if (cachedLines === undefined || cachedWidth !== width) {
|
|
526
|
-
const result = truncateToVisualLines(styledOutput, BASH_PREVIEW_LINES, width);
|
|
527
|
-
cachedLines = result.visualLines;
|
|
505
|
+
const result = truncateToVisualLines(styledOutput, BASH_PREVIEW_LINES, Math.max(1, width - 1));
|
|
506
|
+
cachedLines = result.visualLines.map((line) => ` ${line}`);
|
|
528
507
|
cachedSkipped = result.skippedCount;
|
|
529
508
|
cachedWidth = width;
|
|
530
509
|
}
|
|
531
510
|
if (cachedSkipped && cachedSkipped > 0) {
|
|
532
|
-
const hint = theme.fg("muted", `... (${cachedSkipped} earlier lines
|
|
533
|
-
|
|
534
|
-
return ["", truncateToWidth(hint, width, "..."), ...cachedLines];
|
|
511
|
+
const hint = theme.fg("muted", `... (${cachedSkipped} earlier lines)`);
|
|
512
|
+
return ["", truncateToWidth(` ${hint}`, width, "..."), ...cachedLines];
|
|
535
513
|
}
|
|
536
|
-
// Add blank line for spacing (matches expanded case)
|
|
537
514
|
return ["", ...cachedLines];
|
|
538
515
|
},
|
|
539
516
|
invalidate: () => {
|
|
@@ -544,7 +521,6 @@ export class ToolExecutionComponent extends Container {
|
|
|
544
521
|
});
|
|
545
522
|
}
|
|
546
523
|
}
|
|
547
|
-
// Truncation warnings
|
|
548
524
|
const truncation = this.result.details?.truncation;
|
|
549
525
|
const fullOutputPath = this.result.details?.fullOutputPath;
|
|
550
526
|
if (truncation?.truncated || fullOutputPath) {
|
|
@@ -560,7 +536,7 @@ export class ToolExecutionComponent extends Container {
|
|
|
560
536
|
warnings.push(`Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)`);
|
|
561
537
|
}
|
|
562
538
|
}
|
|
563
|
-
|
|
539
|
+
body.addChild(new Text(`\n${theme.fg("warning", `[${warnings.join(". ")}]`)}`, 0, 0));
|
|
564
540
|
}
|
|
565
541
|
}
|
|
566
542
|
}
|
|
@@ -572,9 +548,16 @@ export class ToolExecutionComponent extends Container {
|
|
|
572
548
|
let output = textBlocks
|
|
573
549
|
.map((c) => {
|
|
574
550
|
// Use sanitizeBinaryOutput to handle binary data that crashes string-width
|
|
575
|
-
return sanitizeBinaryOutput(
|
|
551
|
+
return sanitizeBinaryOutput(c.text || "");
|
|
576
552
|
})
|
|
577
553
|
.join("\n");
|
|
554
|
+
if (this.toolName === "bash") {
|
|
555
|
+
output = renderTerminalText(output);
|
|
556
|
+
}
|
|
557
|
+
else {
|
|
558
|
+
output = output.replace(/\r/g, "");
|
|
559
|
+
output = stripAnsi(output);
|
|
560
|
+
}
|
|
578
561
|
const caps = getCapabilities();
|
|
579
562
|
if (imageBlocks.length > 0 && (!caps.images || !this.showImages)) {
|
|
580
563
|
const imageIndicators = imageBlocks
|
|
@@ -594,8 +577,12 @@ export class ToolExecutionComponent extends Container {
|
|
|
594
577
|
}
|
|
595
578
|
return !this.expanded && this.renderMode === "minimal" && !this.result?.isError;
|
|
596
579
|
}
|
|
597
|
-
collapsedExpandHint(
|
|
598
|
-
return
|
|
580
|
+
collapsedExpandHint(_label) {
|
|
581
|
+
return ""; // hint is shown in editor bottom border instead
|
|
582
|
+
}
|
|
583
|
+
collapsedHintWithPrefix(prefix = "\n\n") {
|
|
584
|
+
const hint = this.collapsedExpandHint();
|
|
585
|
+
return hint ? `${prefix}${hint}` : "";
|
|
599
586
|
}
|
|
600
587
|
collapsedFirstLine(output) {
|
|
601
588
|
const first = output.split("\n").map((line) => line.trim()).find(Boolean);
|
|
@@ -631,7 +618,7 @@ export class ToolExecutionComponent extends Container {
|
|
|
631
618
|
const lines = lang ? highlightCode(replaceTabs(output), lang) : output.split("\n");
|
|
632
619
|
if (hideCollapsedPreview) {
|
|
633
620
|
if (output.trim()) {
|
|
634
|
-
text +=
|
|
621
|
+
text += this.collapsedHintWithPrefix();
|
|
635
622
|
}
|
|
636
623
|
}
|
|
637
624
|
else {
|
|
@@ -644,7 +631,7 @@ export class ToolExecutionComponent extends Container {
|
|
|
644
631
|
.map((line) => (lang ? replaceTabs(line) : theme.fg("toolOutput", replaceTabs(line))))
|
|
645
632
|
.join("\n");
|
|
646
633
|
if (remaining > 0) {
|
|
647
|
-
text +=
|
|
634
|
+
text += theme.fg("muted", `\n... (${remaining} more lines)`);
|
|
648
635
|
}
|
|
649
636
|
}
|
|
650
637
|
const truncation = this.result.details?.truncation;
|
|
@@ -705,7 +692,7 @@ export class ToolExecutionComponent extends Container {
|
|
|
705
692
|
this.writeHighlightCache = undefined;
|
|
706
693
|
}
|
|
707
694
|
if (hideCollapsedPreview) {
|
|
708
|
-
text +=
|
|
695
|
+
text += this.collapsedHintWithPrefix();
|
|
709
696
|
}
|
|
710
697
|
else {
|
|
711
698
|
const totalLines = lines.length;
|
|
@@ -716,9 +703,7 @@ export class ToolExecutionComponent extends Container {
|
|
|
716
703
|
"\n\n" +
|
|
717
704
|
displayLines.map((line) => (lang ? line : theme.fg("toolOutput", replaceTabs(line)))).join("\n");
|
|
718
705
|
if (remaining > 0) {
|
|
719
|
-
text +=
|
|
720
|
-
theme.fg("muted", `\n... (${remaining} more lines, ${totalLines} total,`) +
|
|
721
|
-
` ${keyHint("expandTools", "to expand")})`;
|
|
706
|
+
text += theme.fg("muted", `\n... (${remaining} more lines, ${totalLines} total)`);
|
|
722
707
|
}
|
|
723
708
|
}
|
|
724
709
|
}
|
|
@@ -763,7 +748,7 @@ export class ToolExecutionComponent extends Container {
|
|
|
763
748
|
// This takes priority over editDiffPreview which may have a stale error
|
|
764
749
|
// due to race condition (async preview computed after file was modified)
|
|
765
750
|
text += hideCollapsedPreview
|
|
766
|
-
?
|
|
751
|
+
? this.collapsedHintWithPrefix()
|
|
767
752
|
: `\n\n${renderDiff(this.result.details.diff, { filePath: rawPath ?? undefined })}`;
|
|
768
753
|
}
|
|
769
754
|
else if (this.editDiffPreview) {
|
|
@@ -773,7 +758,7 @@ export class ToolExecutionComponent extends Container {
|
|
|
773
758
|
}
|
|
774
759
|
else if (this.editDiffPreview.diff) {
|
|
775
760
|
text += hideCollapsedPreview
|
|
776
|
-
?
|
|
761
|
+
? this.collapsedHintWithPrefix()
|
|
777
762
|
: `\n\n${renderDiff(this.editDiffPreview.diff, { filePath: rawPath ?? undefined })}`;
|
|
778
763
|
}
|
|
779
764
|
}
|
|
@@ -794,7 +779,7 @@ export class ToolExecutionComponent extends Container {
|
|
|
794
779
|
const output = this.getTextOutput().trim();
|
|
795
780
|
if (output) {
|
|
796
781
|
if (hideCollapsedPreview) {
|
|
797
|
-
text +=
|
|
782
|
+
text += this.collapsedHintWithPrefix();
|
|
798
783
|
}
|
|
799
784
|
else {
|
|
800
785
|
const lines = output.split("\n");
|
|
@@ -803,7 +788,7 @@ export class ToolExecutionComponent extends Container {
|
|
|
803
788
|
const remaining = lines.length - maxLines;
|
|
804
789
|
text += `\n\n${displayLines.map((line) => theme.fg("toolOutput", line)).join("\n")}`;
|
|
805
790
|
if (remaining > 0) {
|
|
806
|
-
text +=
|
|
791
|
+
text += theme.fg("muted", `\n... (${remaining} more lines)`);
|
|
807
792
|
}
|
|
808
793
|
}
|
|
809
794
|
}
|
|
@@ -846,7 +831,7 @@ export class ToolExecutionComponent extends Container {
|
|
|
846
831
|
const output = this.getTextOutput().trim();
|
|
847
832
|
if (output) {
|
|
848
833
|
if (hideCollapsedPreview) {
|
|
849
|
-
text +=
|
|
834
|
+
text += this.collapsedHintWithPrefix();
|
|
850
835
|
}
|
|
851
836
|
else {
|
|
852
837
|
const lines = output.split("\n");
|
|
@@ -855,7 +840,7 @@ export class ToolExecutionComponent extends Container {
|
|
|
855
840
|
const remaining = lines.length - maxLines;
|
|
856
841
|
text += `\n\n${displayLines.map((line) => theme.fg("toolOutput", line)).join("\n")}`;
|
|
857
842
|
if (remaining > 0) {
|
|
858
|
-
text +=
|
|
843
|
+
text += theme.fg("muted", `\n... (${remaining} more lines)`);
|
|
859
844
|
}
|
|
860
845
|
}
|
|
861
846
|
}
|
|
@@ -902,7 +887,7 @@ export class ToolExecutionComponent extends Container {
|
|
|
902
887
|
const output = this.getTextOutput().trim();
|
|
903
888
|
if (output) {
|
|
904
889
|
if (hideCollapsedPreview) {
|
|
905
|
-
text +=
|
|
890
|
+
text += this.collapsedHintWithPrefix();
|
|
906
891
|
}
|
|
907
892
|
else {
|
|
908
893
|
const lines = output.split("\n");
|
|
@@ -911,7 +896,7 @@ export class ToolExecutionComponent extends Container {
|
|
|
911
896
|
const remaining = lines.length - maxLines;
|
|
912
897
|
text += `\n\n${displayLines.map((line) => theme.fg("toolOutput", line)).join("\n")}`;
|
|
913
898
|
if (remaining > 0) {
|
|
914
|
-
text +=
|
|
899
|
+
text += theme.fg("muted", `\n... (${remaining} more lines)`);
|
|
915
900
|
}
|
|
916
901
|
}
|
|
917
902
|
}
|
|
@@ -943,7 +928,7 @@ export class ToolExecutionComponent extends Container {
|
|
|
943
928
|
const output = this.getTextOutput().trim();
|
|
944
929
|
if (output) {
|
|
945
930
|
if (hideCollapsedPreview) {
|
|
946
|
-
text +=
|
|
931
|
+
text += this.collapsedHintWithPrefix();
|
|
947
932
|
}
|
|
948
933
|
else {
|
|
949
934
|
const lines = output.split("\n");
|
|
@@ -952,17 +937,61 @@ export class ToolExecutionComponent extends Container {
|
|
|
952
937
|
const remaining = lines.length - maxLines;
|
|
953
938
|
text += `\n\n${displayLines.map((line) => theme.fg("toolOutput", line)).join("\n")}`;
|
|
954
939
|
if (remaining > 0) {
|
|
955
|
-
text +=
|
|
940
|
+
text += theme.fg("muted", `\n... (${remaining} more lines)`);
|
|
956
941
|
}
|
|
957
942
|
}
|
|
958
943
|
}
|
|
959
944
|
}
|
|
960
945
|
}
|
|
946
|
+
else if (this.toolName === "lsp") {
|
|
947
|
+
const action = this.args?.action;
|
|
948
|
+
const file = this.args?.file;
|
|
949
|
+
const line = this.args?.line;
|
|
950
|
+
const symbol = this.args?.symbol;
|
|
951
|
+
const query = this.args?.query;
|
|
952
|
+
const newName = this.args?.new_name;
|
|
953
|
+
text = `${statusIndicator} ${theme.fg("toolTitle", theme.bold("lsp"))}`;
|
|
954
|
+
if (action)
|
|
955
|
+
text += ` ${theme.fg("accent", action)}`;
|
|
956
|
+
if (file) {
|
|
957
|
+
const shortFile = shortenPath(file);
|
|
958
|
+
let styledFile = theme.fg("muted", shortFile);
|
|
959
|
+
if (file && shortFile) {
|
|
960
|
+
styledFile = editorLink(file, styledFile, { cwd: this.cwd, line, scheme: this.editorScheme });
|
|
961
|
+
}
|
|
962
|
+
text += ` ${styledFile}`;
|
|
963
|
+
if (line !== undefined)
|
|
964
|
+
text += theme.fg("warning", `:${line}`);
|
|
965
|
+
}
|
|
966
|
+
if (symbol)
|
|
967
|
+
text += ` ${theme.fg("toolOutput", symbol)}`;
|
|
968
|
+
if (query)
|
|
969
|
+
text += ` ${theme.fg("muted", `"${query}"`)}`;
|
|
970
|
+
if (newName)
|
|
971
|
+
text += ` → ${theme.fg("accent", newName)}`;
|
|
972
|
+
if (this.result) {
|
|
973
|
+
const output = this.getTextOutput().trim();
|
|
974
|
+
if (output) {
|
|
975
|
+
if (hideCollapsedPreview) {
|
|
976
|
+
text += this.collapsedHintWithPrefix();
|
|
977
|
+
}
|
|
978
|
+
else {
|
|
979
|
+
const lines = output.split("\n");
|
|
980
|
+
const maxLines = this.expanded ? lines.length : 10;
|
|
981
|
+
const displayLines = lines.slice(0, maxLines);
|
|
982
|
+
const remaining = lines.length - maxLines;
|
|
983
|
+
text += `\n\n${displayLines.map((l) => theme.fg("toolOutput", l)).join("\n")}`;
|
|
984
|
+
if (remaining > 0)
|
|
985
|
+
text += theme.fg("muted", `\n... (${remaining} more lines)`);
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
}
|
|
961
990
|
else {
|
|
962
991
|
// Generic tool (shouldn't reach here for custom tools)
|
|
963
992
|
text = `${statusIndicator} ${theme.fg("toolTitle", theme.bold(this.toolName))}`;
|
|
964
993
|
const content = JSON.stringify(this.args, null, 2);
|
|
965
|
-
text += hideCollapsedPreview ?
|
|
994
|
+
text += hideCollapsedPreview ? this.collapsedHintWithPrefix() : `\n\n${content}`;
|
|
966
995
|
const output = this.getTextOutput();
|
|
967
996
|
if (output && !hideCollapsedPreview) {
|
|
968
997
|
text += `\n${output}`;
|