@f5xc-salesdemos/xcsh 18.18.2 → 18.18.4

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 CHANGED
@@ -2,7 +2,13 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
- ## [18.18.0] - 2026-04-25
5
+ ## [18.18.4] - 2026-04-26
6
+
7
+
8
+ ### Fixed
9
+
10
+ - Fixed gutter width propagation in the fallback tool renderer: `#formatToolExecution()` now receives the actual available width at render-time and uses it for line truncation instead of a hardcoded 80-column limit. On narrow terminals (<82 cols) this prevents content wider than the gutter-adjusted viewport; on wide terminals it allows longer output lines. ([#117](https://github.com/f5xc-salesdemos/xcsh/issues/117))
11
+
6
12
 
7
13
  ### Changed
8
14
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@f5xc-salesdemos/xcsh",
4
- "version": "18.18.2",
4
+ "version": "18.18.4",
5
5
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
6
6
  "homepage": "https://github.com/f5xc-salesdemos/xcsh",
7
7
  "author": "Can Boluk",
@@ -47,12 +47,12 @@
47
47
  "dependencies": {
48
48
  "@agentclientprotocol/sdk": "0.16.1",
49
49
  "@mozilla/readability": "^0.6",
50
- "@f5xc-salesdemos/xcsh-stats": "18.18.2",
51
- "@f5xc-salesdemos/pi-agent-core": "18.18.2",
52
- "@f5xc-salesdemos/pi-ai": "18.18.2",
53
- "@f5xc-salesdemos/pi-natives": "18.18.2",
54
- "@f5xc-salesdemos/pi-tui": "18.18.2",
55
- "@f5xc-salesdemos/pi-utils": "18.18.2",
50
+ "@f5xc-salesdemos/xcsh-stats": "18.18.4",
51
+ "@f5xc-salesdemos/pi-agent-core": "18.18.4",
52
+ "@f5xc-salesdemos/pi-ai": "18.18.4",
53
+ "@f5xc-salesdemos/pi-natives": "18.18.4",
54
+ "@f5xc-salesdemos/pi-tui": "18.18.4",
55
+ "@f5xc-salesdemos/pi-utils": "18.18.4",
56
56
  "@sinclair/typebox": "^0.34",
57
57
  "@xterm/headless": "^6.0",
58
58
  "ajv": "^8.18",
@@ -17,17 +17,17 @@ export interface BuildInfo {
17
17
  }
18
18
 
19
19
  export const BUILD_INFO: BuildInfo = {
20
- "version": "18.18.2",
21
- "commit": "3d0fb36250f738a3d5e215ba4840b84cf6ff2904",
22
- "shortCommit": "3d0fb36",
20
+ "version": "18.18.4",
21
+ "commit": "fdf87bd352c603cc95ae0a1e911549955d08dcf5",
22
+ "shortCommit": "fdf87bd",
23
23
  "branch": "main",
24
- "tag": "v18.18.2",
25
- "commitDate": "2026-04-25T19:45:57Z",
26
- "buildDate": "2026-04-25T20:04:16.409Z",
24
+ "tag": "v18.18.4",
25
+ "commitDate": "2026-04-26T09:55:27Z",
26
+ "buildDate": "2026-04-26T10:18:20.791Z",
27
27
  "dirty": false,
28
28
  "prNumber": "",
29
29
  "repoUrl": "https://github.com/f5xc-salesdemos/xcsh",
30
30
  "repoSlug": "f5xc-salesdemos/xcsh",
31
- "commitUrl": "https://github.com/f5xc-salesdemos/xcsh/commit/3d0fb36250f738a3d5e215ba4840b84cf6ff2904",
32
- "releaseUrl": "https://github.com/f5xc-salesdemos/xcsh/releases/tag/v18.18.2"
31
+ "commitUrl": "https://github.com/f5xc-salesdemos/xcsh/commit/fdf87bd352c603cc95ae0a1e911549955d08dcf5",
32
+ "releaseUrl": "https://github.com/f5xc-salesdemos/xcsh/releases/tag/v18.18.4"
33
33
  };
@@ -62,7 +62,7 @@ export class StatusLineComponent implements Component {
62
62
  #subagentCount: number = 0;
63
63
  #sessionStartTime: number = Date.now();
64
64
  #planModeStatus: { enabled: boolean; paused: boolean } | null = null;
65
- #cwd: string = getShellPwd();
65
+ #cwd: string;
66
66
  // Display text for a pending chord leader (e.g. "Ctrl+X-") or null when no
67
67
  // chord is pending. Populated by the InputController's ChordDispatcher
68
68
  // callbacks; rendered as a dim right-aligned segment in the top border.
@@ -91,6 +91,7 @@ export class StatusLineComponent implements Component {
91
91
  #lastTokensPerSecondTimestamp: number | null = null;
92
92
 
93
93
  constructor(private readonly session: AgentSession) {
94
+ this.#cwd = session.sessionManager?.getCwd() ?? getShellPwd();
94
95
  this.#settings = {
95
96
  preset: settings.get("statusLine.preset"),
96
97
  leftSegments: settings.get("statusLine.leftSegments"),
@@ -110,6 +110,8 @@ export class ToolExecutionComponent extends Container {
110
110
  #spinnerInterval?: NodeJS.Timeout;
111
111
  // Track if args are still being streamed (for edit/write spinner)
112
112
  #argsComplete = false;
113
+ // True when this component uses #contentText (fallback path, no custom renderer)
114
+ #usesFallbackText = false;
113
115
  #renderState: {
114
116
  spinnerFrame?: number;
115
117
  expanded: boolean;
@@ -149,6 +151,7 @@ export class ToolExecutionComponent extends Container {
149
151
  if (hasCustomRenderer || hasRenderer) {
150
152
  this.addChild(this.#contentBox);
151
153
  } else {
154
+ this.#usesFallbackText = true;
152
155
  this.addChild(this.#contentText);
153
156
  }
154
157
 
@@ -359,6 +362,15 @@ export class ToolExecutionComponent extends Container {
359
362
  this.#updateDisplay();
360
363
  }
361
364
 
365
+ override render(width: number): string[] {
366
+ // For fallback tools (no custom renderer), regenerate text with the
367
+ // correct width at render-time instead of using the hardcoded default.
368
+ if (this.#usesFallbackText) {
369
+ this.#contentText.setText(this.#formatToolExecution(width));
370
+ }
371
+ return super.render(width);
372
+ }
373
+
362
374
  #updateDisplay(): void {
363
375
  // Set background based on state
364
376
  const bgFn = this.#isPartial
@@ -563,9 +575,9 @@ export class ToolExecutionComponent extends Container {
563
575
  }
564
576
  }
565
577
  } else {
566
- // Other built-in tools: use Text directly with caching
578
+ // Other built-in tools: bg is set eagerly; text content is generated
579
+ // lazily in render(width) so truncation respects the actual available width.
567
580
  this.#contentText.setCustomBgFn(bgFn);
568
- this.#contentText.setText(this.#formatToolExecution());
569
581
  }
570
582
 
571
583
  // Handle images (same for both custom and built-in)
@@ -682,16 +694,17 @@ export class ToolExecutionComponent extends Container {
682
694
  }
683
695
 
684
696
  /**
685
- * Format a generic tool execution (fallback for tools without custom renderers)
697
+ * Format a generic tool execution (fallback for tools without custom renderers).
698
+ * @param width Available content width (from GutterBlock), used for truncation.
686
699
  */
687
- #formatToolExecution(): string {
700
+ #formatToolExecution(width = 80): string {
688
701
  const lines: string[] = [];
689
702
  const icon = this.#isPartial ? "pending" : undefined;
690
703
  lines.push(renderStatusLine({ icon, title: this.#toolLabel }, theme));
691
704
 
692
705
  const argsObject = this.#args && typeof this.#args === "object" ? (this.#args as Record<string, unknown>) : null;
693
706
  if (!this.#expanded && argsObject && Object.keys(argsObject).length > 0) {
694
- const preview = formatArgsInline(argsObject, 70);
707
+ const preview = formatArgsInline(argsObject, Math.max(20, width - 10));
695
708
  if (preview) {
696
709
  lines.push(` ${theme.fg("dim", theme.tree.last)} ${theme.fg("dim", preview)}`);
697
710
  }
@@ -753,7 +766,7 @@ export class ToolExecutionComponent extends Container {
753
766
  const displayLines = outputLines.slice(0, maxOutputLines);
754
767
 
755
768
  for (const line of displayLines) {
756
- lines.push(theme.fg("toolOutput", truncateToWidth(replaceTabs(line), 80)));
769
+ lines.push(theme.fg("toolOutput", truncateToWidth(replaceTabs(line), width)));
757
770
  }
758
771
 
759
772
  if (outputLines.length > maxOutputLines) {
@@ -681,7 +681,8 @@ export class CommandController {
681
681
  resetCapabilities();
682
682
  await this.ctx.refreshSlashCommandState(resolvedPath);
683
683
 
684
- this.ctx.statusLine.invalidate();
684
+ setShellPwd(resolvedPath);
685
+ this.ctx.statusLine.setCwd(resolvedPath);
685
686
  this.ctx.updateEditorTopBorder();
686
687
 
687
688
  this.ctx.chatContainer.addChild(new Spacer(1));