lsd-pi 1.3.6 → 1.3.7

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.
Files changed (83) hide show
  1. package/dist/cli.js +2 -1
  2. package/dist/lsd-settings-manager.d.ts +2 -0
  3. package/dist/lsd-settings-manager.js +5 -0
  4. package/dist/resource-loader.js +33 -3
  5. package/dist/resources/extensions/cache-timer/index.js +3 -2
  6. package/dist/welcome-screen.js +2 -2
  7. package/package.json +1 -1
  8. package/packages/pi-coding-agent/dist/core/settings-manager.collapse-tool-calls.test.d.ts +2 -0
  9. package/packages/pi-coding-agent/dist/core/settings-manager.collapse-tool-calls.test.d.ts.map +1 -0
  10. package/packages/pi-coding-agent/dist/core/settings-manager.collapse-tool-calls.test.js +35 -0
  11. package/packages/pi-coding-agent/dist/core/settings-manager.collapse-tool-calls.test.js.map +1 -0
  12. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +6 -0
  13. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  14. package/packages/pi-coding-agent/dist/core/settings-manager.js +12 -0
  15. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  16. package/packages/pi-coding-agent/dist/core/tools/edit-diff.d.ts +5 -0
  17. package/packages/pi-coding-agent/dist/core/tools/edit-diff.d.ts.map +1 -1
  18. package/packages/pi-coding-agent/dist/core/tools/edit-diff.js +21 -0
  19. package/packages/pi-coding-agent/dist/core/tools/edit-diff.js.map +1 -1
  20. package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js +16 -1
  21. package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js.map +1 -1
  22. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-summary-line.test.js +12 -4
  23. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-summary-line.test.js.map +1 -1
  24. package/packages/pi-coding-agent/dist/modes/interactive/components/diff.d.ts +7 -5
  25. package/packages/pi-coding-agent/dist/modes/interactive/components/diff.d.ts.map +1 -1
  26. package/packages/pi-coding-agent/dist/modes/interactive/components/diff.js +86 -28
  27. package/packages/pi-coding-agent/dist/modes/interactive/components/diff.js.map +1 -1
  28. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts +2 -0
  29. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  30. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +16 -10
  31. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  32. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +4 -0
  33. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  34. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +26 -4
  35. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
  36. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +14 -1
  37. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  38. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +111 -12
  39. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  40. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-summary-line.d.ts +1 -0
  41. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-summary-line.d.ts.map +1 -1
  42. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-summary-line.js +47 -3
  43. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-summary-line.js.map +1 -1
  44. package/packages/pi-coding-agent/dist/modes/interactive/controllers/__tests__/chat-controller.collapsed-tool-summary.test.js +137 -6
  45. package/packages/pi-coding-agent/dist/modes/interactive/controllers/__tests__/chat-controller.collapsed-tool-summary.test.js.map +1 -1
  46. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  47. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +40 -14
  48. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  49. package/packages/pi-coding-agent/dist/modes/interactive/controllers/extension-ui-controller.js +1 -1
  50. package/packages/pi-coding-agent/dist/modes/interactive/controllers/extension-ui-controller.js.map +1 -1
  51. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +1 -0
  52. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  53. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  54. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +5 -1
  55. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  56. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +70 -25
  57. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  58. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +4 -4
  59. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -1
  60. package/packages/pi-coding-agent/package.json +1 -1
  61. package/packages/pi-coding-agent/src/core/settings-manager.collapse-tool-calls.test.ts +46 -0
  62. package/packages/pi-coding-agent/src/core/settings-manager.ts +18 -0
  63. package/packages/pi-coding-agent/src/core/tools/edit-diff.test.ts +20 -0
  64. package/packages/pi-coding-agent/src/core/tools/edit-diff.ts +26 -0
  65. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-summary-line.test.ts +14 -4
  66. package/packages/pi-coding-agent/src/modes/interactive/components/diff.ts +105 -28
  67. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +13 -6
  68. package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +31 -4
  69. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +119 -13
  70. package/packages/pi-coding-agent/src/modes/interactive/components/tool-summary-line.ts +59 -3
  71. package/packages/pi-coding-agent/src/modes/interactive/controllers/__tests__/chat-controller.collapsed-tool-summary.test.ts +174 -6
  72. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +50 -14
  73. package/packages/pi-coding-agent/src/modes/interactive/controllers/extension-ui-controller.ts +1 -1
  74. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +1 -0
  75. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +73 -25
  76. package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +4 -4
  77. package/packages/pi-tui/dist/components/editor.js +3 -3
  78. package/packages/pi-tui/dist/components/editor.js.map +1 -1
  79. package/packages/pi-tui/src/components/editor.ts +3 -3
  80. package/pkg/dist/modes/interactive/theme/themes.js +4 -4
  81. package/pkg/dist/modes/interactive/theme/themes.js.map +1 -1
  82. package/pkg/package.json +1 -1
  83. package/src/resources/extensions/cache-timer/index.ts +3 -2
@@ -1,6 +1,6 @@
1
1
  import { Box, Container, getCapabilities, Image, imageFallback, Spacer, Text, truncateToWidth, } from "@gsd/pi-tui";
2
2
  import stripAnsi from "strip-ansi";
3
- import { computeEditDiff } from "../../../core/tools/edit-diff.js";
3
+ import { computeEditDiff, computeWriteDiff, } from "../../../core/tools/edit-diff.js";
4
4
  import { allTools } from "../../../core/tools/index.js";
5
5
  import { shouldCollapse } from "../../../core/tool-priority.js";
6
6
  import { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize } from "../../../core/tools/truncate.js";
@@ -10,7 +10,7 @@ import { renderTerminalText } from "../../../utils/terminal-serializer.js";
10
10
  import { getLanguageFromPath, highlightCode, theme } from "../theme/theme.js";
11
11
  import { editorLink } from "../utils/editor-link.js";
12
12
  import { shortenPath } from "../utils/shorten-path.js";
13
- import { renderDiff } from "./diff.js";
13
+ import { renderDiff, renderDiffLines } from "./diff.js";
14
14
  import { truncateToVisualLines } from "./visual-truncate.js";
15
15
  // Preview line limit for bash when not expanded
16
16
  const BASH_PREVIEW_LINES = 5;
@@ -117,6 +117,40 @@ export class ToolExecutionComponent extends Container {
117
117
  const hasCustomRenderers = this.toolDefinition?.renderCall || this.toolDefinition?.renderResult;
118
118
  return isBuiltInName && !hasCustomRenderers;
119
119
  }
120
+ setPrimaryContent(useBox) {
121
+ const hasBox = this.children.includes(this.contentBox);
122
+ const hasText = this.children.includes(this.contentText);
123
+ if (useBox) {
124
+ if (hasText)
125
+ this.removeChild(this.contentText);
126
+ if (!hasBox)
127
+ this.addChild(this.contentBox);
128
+ }
129
+ else {
130
+ if (hasBox)
131
+ this.removeChild(this.contentBox);
132
+ if (!hasText)
133
+ this.addChild(this.contentText);
134
+ }
135
+ }
136
+ getDiffTextToRender() {
137
+ if (this.toolName === "write") {
138
+ if (!this.isPartial && this.writeDiffPreview && !("error" in this.writeDiffPreview) && this.writeDiffPreview.diff) {
139
+ return this.writeDiffPreview.diff;
140
+ }
141
+ return undefined;
142
+ }
143
+ if (this.toolName !== "edit" || this.result?.isError) {
144
+ return undefined;
145
+ }
146
+ if (this.result?.details?.diff) {
147
+ return this.result.details.diff;
148
+ }
149
+ if (this.editDiffPreview && !("error" in this.editDiffPreview) && this.editDiffPreview.diff) {
150
+ return this.editDiffPreview.diff;
151
+ }
152
+ return undefined;
153
+ }
120
154
  updateArgs(args) {
121
155
  this.args = args;
122
156
  if (this.toolName === "write" && this.isPartial) {
@@ -212,9 +246,33 @@ export class ToolExecutionComponent extends Container {
212
246
  if (rawPath !== null && fileContent !== null) {
213
247
  this.rebuildWriteHighlightCacheFull(rawPath, fileContent);
214
248
  }
249
+ this.maybeComputeWriteDiff();
215
250
  }
216
251
  this.maybeComputeEditDiff();
217
252
  }
253
+ /**
254
+ * Compute write diff preview when we have complete args.
255
+ * This runs async and updates display when done.
256
+ */
257
+ maybeComputeWriteDiff() {
258
+ if (this.toolName !== "write")
259
+ return;
260
+ const path = this.args?.path ?? this.args?.file_path;
261
+ const content = this.args?.content;
262
+ if (!path || content === undefined)
263
+ return;
264
+ const argsKey = JSON.stringify({ path, content });
265
+ if (this.writeDiffArgsKey === argsKey)
266
+ return;
267
+ this.writeDiffArgsKey = argsKey;
268
+ computeWriteDiff(path, content, this.cwd).then((result) => {
269
+ if (this.writeDiffArgsKey === argsKey) {
270
+ this.writeDiffPreview = result;
271
+ this.updateDisplay();
272
+ this.ui.requestRender();
273
+ }
274
+ });
275
+ }
218
276
  /**
219
277
  * Compute edit diff preview when we have complete args.
220
278
  * This runs async and updates display when done.
@@ -304,8 +362,8 @@ export class ToolExecutionComponent extends Container {
304
362
  getElapsed() {
305
363
  return Date.now() - this.startTime;
306
364
  }
307
- shouldHideWhenCollapsed() {
308
- return !this.isPartial && shouldCollapse(this.toolName, this.result?.isError ?? false);
365
+ shouldHideWhenCollapsed(collapseToolCalls = true) {
366
+ return collapseToolCalls && !this.isPartial && shouldCollapse(this.toolName, this.result?.isError ?? false);
309
367
  }
310
368
  setRenderMode(mode) {
311
369
  if (this.renderMode !== mode) {
@@ -370,15 +428,23 @@ export class ToolExecutionComponent extends Container {
370
428
  }
371
429
  }
372
430
  const useBuiltInRenderer = this.shouldUseBuiltInRenderer();
431
+ const diffTextToRender = this.getDiffTextToRender();
373
432
  let customRendererHasContent = false;
374
433
  // Use built-in rendering for built-in tools (or overrides without custom renderers)
375
434
  if (useBuiltInRenderer) {
435
+ const useDiffBox = !!diffTextToRender && !this.shouldHideCollapsedPreview();
436
+ this.setPrimaryContent(this.toolName === "bash" || useDiffBox);
376
437
  if (this.toolName === "bash") {
377
438
  // Bash uses Box with visual line truncation - no background
378
439
  this.contentBox.setBgFn((text) => text);
379
440
  this.contentBox.clear();
380
441
  this.renderBashContent(statusIndicator);
381
442
  }
443
+ else if (useDiffBox && diffTextToRender) {
444
+ this.contentBox.setBgFn((text) => text);
445
+ this.contentBox.clear();
446
+ this.renderBuiltInDiffContent(statusIndicator, diffTextToRender);
447
+ }
382
448
  else {
383
449
  // Other built-in tools: use Text directly with caching - no background
384
450
  this.contentText.setCustomBgFn((text) => text);
@@ -507,6 +573,20 @@ export class ToolExecutionComponent extends Container {
507
573
  const computedHidden = !useBuiltInRenderer && this.toolDefinition ? !customRendererHasContent && this.imageComponents.length === 0 : false;
508
574
  this.hideComponent = this.manuallyHidden || computedHidden;
509
575
  }
576
+ /**
577
+ * Render built-in edit/write diff blocks with width-aware full-line backgrounds.
578
+ */
579
+ renderBuiltInDiffContent(statusIndicator, diffText) {
580
+ const header = this.formatToolExecution(statusIndicator).split("\n\n", 1)[0] ?? "";
581
+ this.contentBox.addChild(new Text(header, 0, 0));
582
+ this.contentBox.addChild({
583
+ render: (width) => {
584
+ const contentWidth = Math.max(1, width - 2);
585
+ return ["", ...renderDiffLines(diffText, contentWidth).map((line) => ` ${line} `)];
586
+ },
587
+ invalidate: () => { },
588
+ });
589
+ }
510
590
  /**
511
591
  * Render bash content using visual line truncation (like bash-execution.ts)
512
592
  */
@@ -726,14 +806,40 @@ export class ToolExecutionComponent extends Container {
726
806
  const rawPath = str(this.args?.file_path ?? this.args?.path);
727
807
  const fileContent = str(this.args?.content);
728
808
  const path = rawPath !== null ? shortenPath(rawPath) : null;
809
+ const firstChangedLine = this.writeDiffPreview && "firstChangedLine" in this.writeDiffPreview
810
+ ? this.writeDiffPreview.firstChangedLine
811
+ : undefined;
729
812
  let writePathDisplay = path === null ? invalidArg : path ? theme.fg("accent", path) : theme.fg("toolOutput", "...");
730
813
  if (rawPath && path) {
731
- writePathDisplay = editorLink(rawPath, writePathDisplay, { cwd: this.cwd, scheme: this.editorScheme });
814
+ writePathDisplay = editorLink(rawPath, writePathDisplay, {
815
+ cwd: this.cwd,
816
+ line: firstChangedLine ?? undefined,
817
+ scheme: this.editorScheme,
818
+ });
819
+ }
820
+ if (firstChangedLine) {
821
+ writePathDisplay += theme.fg("warning", `:${firstChangedLine}`);
732
822
  }
733
823
  text = `${statusIndicator} ${theme.fg("toolTitle", theme.bold("write"))} ${writePathDisplay}`;
734
824
  if (fileContent === null) {
735
825
  text += `\n\n${theme.fg("error", "[invalid content arg - expected string]")}`;
736
826
  }
827
+ else if (this.result?.isError) {
828
+ const errorText = this.getTextOutput();
829
+ if (errorText) {
830
+ text += `\n\n${theme.fg("error", errorText)}`;
831
+ }
832
+ }
833
+ else if (!this.isPartial && this.writeDiffPreview) {
834
+ if ("error" in this.writeDiffPreview) {
835
+ text += `\n\n${theme.fg("error", this.writeDiffPreview.error)}`;
836
+ }
837
+ else if (this.writeDiffPreview.diff) {
838
+ text += hideCollapsedPreview
839
+ ? this.collapsedHintWithPrefix()
840
+ : `\n\n${renderDiff(this.writeDiffPreview.diff, { filePath: rawPath ?? undefined })}`;
841
+ }
842
+ }
737
843
  else if (fileContent) {
738
844
  const lang = rawPath ? getLanguageFromPath(rawPath) : undefined;
739
845
  let lines;
@@ -775,13 +881,6 @@ export class ToolExecutionComponent extends Container {
775
881
  }
776
882
  }
777
883
  }
778
- // Show error if tool execution failed
779
- if (this.result?.isError) {
780
- const errorText = this.getTextOutput();
781
- if (errorText) {
782
- text += `\n\n${theme.fg("error", errorText)}`;
783
- }
784
- }
785
884
  }
786
885
  else if (this.toolName === "edit") {
787
886
  const rawPath = str(this.args?.file_path ?? this.args?.path);