@agi-fans/dsh-tui 0.24.0 → 0.24.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.
@@ -20,7 +20,7 @@ import { createTheme, paintSurface, SPINNER, SYMBOL, BOX } from "../chrome/theme
20
20
  import { highlightToolText, toolPayloadLanguage } from "../chrome/code-highlight.js";
21
21
  import { renderGoalBar } from "../chrome/goal-bar.js";
22
22
  import { padToWidth, sliceCells, stripAnsi, truncateToWidth, visibleWidth, wrapCode, wrapTextStable } from "../chrome/width.js";
23
- import { alignFileDiffs, wrapPaintedDiffRows, } from "../chrome/diff-render.js";
23
+ import { alignFileDiffs, paintDiffStats, wrapPaintedDiffRows, } from "../chrome/diff-render.js";
24
24
  import { workspaceBlockLines, WORKSPACE_COLLAPSED_LINES } from "./workspace-changes.js";
25
25
  import { blockFileAction } from "./file-actions.js";
26
26
  import { renderTool, toolArgSubject } from "../chrome/tool-renderers.js";
@@ -137,10 +137,10 @@ function assistantMarkdown(source, theme, width, style, streaming = false) {
137
137
  * everything else, so nothing on the screen is held off by a gutter.
138
138
  */
139
139
  function userBubble(text, theme, width) {
140
- const gutter = ' ';
140
+ const gutter = width > ASSISTANT_PADDING_X * 2 ? ' '.repeat(ASSISTANT_PADDING_X) : '';
141
141
  // Drawn masked, stored plain: the key still reaches the model and the copy
142
142
  // action still returns what the reader sent, but a shared screen shows stars.
143
- const wrapped = renderPathMentionRows(maskSecrets(text), Math.max(1, width - gutter.length), theme);
143
+ const wrapped = renderPathMentionRows(maskSecrets(text), Math.max(1, width - gutter.length * 2), theme);
144
144
  const rows = ['', ...wrapped, ''];
145
145
  // The padding rows share the prompt's tint, so the prompt is one slab that
146
146
  // opens the turn. Unpainted, they were two blank rows of their own on top of
@@ -150,7 +150,7 @@ function userBubble(text, theme, width) {
150
150
  if (row === '')
151
151
  return paintSurface(theme, 'userMessageBg', 'userMessageText', padToWidth('', width));
152
152
  const promptMark = index === 1 && theme.colors ? '\x1b]133;A\x07' : '';
153
- const content = padToWidth((index === 1 ? promptMark + gutter : '') + row, width);
153
+ const content = padToWidth(promptMark + gutter + row, width);
154
154
  return paintSurface(theme, 'userMessageBg', 'userMessageText', content);
155
155
  });
156
156
  }
@@ -261,7 +261,9 @@ function toolRowLine(block, theme, width, spinnerFrame, open = false) {
261
261
  const text = labelText + (detailText === '' ? '' : (descriptionLed ? '' : ROW_JOIN) + detailText) + (tailText === '' ? '' : ROW_JOIN);
262
262
  // A failure is the one line in a run that has to stay findable while scrolling
263
263
  // past, so its fact carries the error colour rather than the row's dim.
264
- const tail = tailText === '' ? '' : block.status === 'error' ? theme.fg('error', tailText) : theme.dim(tailText);
264
+ const tail = tailText === '' ? '' : block.status === 'error' ? theme.fg('error', tailText)
265
+ : presentation.diffStats === undefined ? theme.dim(tailText)
266
+ : truncateToWidth(paintDiffStats(presentation.diffStats.added, presentation.diffStats.removed, theme), factRoom);
265
267
  return [padToWidth(truncateToWidth(head + theme.fg('muted', text) + tail, Math.max(1, width - 2)), width)];
266
268
  }
267
269
  /** Separator between a process subject and its outcome. */
@@ -336,7 +338,7 @@ function toolOutputLines(block, output, subject, theme, width) {
336
338
  return painted.flatMap(line => wrapTextStable(line, width));
337
339
  }
338
340
  /** Tool content shared by a running turn and a completed turn opened for reading. */
339
- function toolBlockLines(block, theme, width, mode = 'preview', detailsKey = 'Alt+O', surface = 'toolSuccessBg', showTitle = true) {
341
+ function toolBlockLines(block, theme, width, mode = 'preview', detailsKey = 'Alt+O', showTitle = true) {
340
342
  const full = mode !== 'preview';
341
343
  const presentation = renderTool({
342
344
  name: block.name, arguments: prettyArgs(block.args), output: block.output,
@@ -449,7 +451,7 @@ function toolBlockLines(block, theme, width, mode = 'preview', detailsKey = 'Alt
449
451
  rows.push('');
450
452
  rows.push(...wrapTextStable(theme.fg(block.status === 'error' ? 'error' : 'muted', `Job ${block.job.id} · ${block.job.detail ?? block.job.status}`), room));
451
453
  }
452
- const bg = !showTitle ? 'toolAltBg' : block.status === 'running' ? 'toolPendingBg' : block.status === 'error' ? 'toolErrorBg' : surface;
454
+ const bg = block.status === 'running' ? 'toolPendingBg' : block.status === 'error' ? 'toolErrorBg' : 'toolSuccessBg';
453
455
  return ['', ...rows, ''].map(row => paintSurface(theme, bg, 'toolOutput', padToWidth(' '.repeat(padding + nest) + row, width)));
454
456
  }
455
457
  function firstLineOf(text) {
@@ -484,7 +486,7 @@ function reasoningSummaryRow(block, theme, width) {
484
486
  function toolDisclosureLines(block, theme, width, open, detailsKey = 'Alt+O', spinnerFrame = 0, raw = false) {
485
487
  const rows = toolRowLine(block, theme, width, spinnerFrame, open);
486
488
  if (open)
487
- rows.push(...toolBlockLines(block, theme, width, raw ? 'details' : 'full', detailsKey, 'toolAltBg', false));
489
+ rows.push(...toolBlockLines(block, theme, width, raw ? 'details' : 'full', detailsKey, false));
488
490
  return rows;
489
491
  }
490
492
  function reasoningDisclosureLines(block, theme, width, open, mathMode = 'auto') {