ucode-agent 1.28.0 → 1.28.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ucode-agent",
3
- "version": "1.28.0",
3
+ "version": "1.28.1",
4
4
  "description": "ucode - a terminal coding agent that reads, edits and runs your code, on NVIDIA and Cohere models.",
5
5
  "type": "module",
6
6
  "main": "ucode.js",
package/src/ui/plain.js CHANGED
@@ -13,7 +13,7 @@ import readline from 'node:readline';
13
13
  import chalk from 'chalk';
14
14
  import {
15
15
  theme, blue, sky, dim, boxTop, boxBottom, boxRow,
16
- BANNER, BANNER_WIDTH, SPINNER, clip, shortenPath, asLabel, padVis, visLen, planLine, bannerPaint, MAX_WIDTH,
16
+ BANNER, BANNER_WIDTH, SPINNER, clip, shortenPath, asLabel, padVis, visLen, planLine, bannerPaint,
17
17
  tidyReply, trimAnswer,
18
18
  } from './theme.js';
19
19
  import { formatDuration, doneLine } from './activity.js';
@@ -66,13 +66,8 @@ export class Plain {
66
66
  });
67
67
  }
68
68
 
69
- /**
70
- * The same cap the full screen draws to, for the same reason: a header box
71
- * ruled across two hundred columns is a line, not a frame. Both surfaces are
72
- * the one product and should not disagree about how wide it is.
73
- */
74
69
  width() {
75
- return Math.max(30, Math.min(this.output.columns || 80, MAX_WIDTH));
70
+ return Math.max(30, this.output.columns || 80);
76
71
  }
77
72
 
78
73
  // -- output --------------------------------------------------------------
package/src/ui/screen.js CHANGED
@@ -40,7 +40,7 @@ import {
40
40
  theme, blue, sky, deep, dim, edge, ADDED, REMOVED, BANNER, BANNER_WIDTH, SPINNER,
41
41
  boxTop, boxBottom, boxRow, visLen, padVis, clip, wrapAnsi,
42
42
  shortenPath, asLabel, ensureColour, planLine, bare, narration, narrationMark, groupKind, groupLabel, groupTarget, runLine, planRows, tidyReply, trimAnswer,
43
- bannerPaint, answerMark, RAIL, MAX_WIDTH } from './theme.js';
43
+ bannerPaint, RAIL } from './theme.js';
44
44
  import { FRAME_MS, fitActivity, shimmer, spinnerGlyph, formatDuration, doneLine, stepPaint } from './activity.js';
45
45
  import { renderer, render, polish } from './markdown.js';
46
46
  import { VERSION } from '../core/version.js';
@@ -205,27 +205,18 @@ export class Screen {
205
205
  while (this.waiters.length) this.waiters.shift()(null);
206
206
  }
207
207
 
208
- /** Every column the terminal has. Only the start screen, which centres, uses it. */
209
- screenWidth() {
210
- return Math.max(30, this.cols);
211
- }
212
-
213
208
  /**
214
- * The width the interface actually draws to.
215
- *
216
- * On a wide monitor an uncapped frame stretched its boxes to two hundred
217
- * columns and ran prose the same distance, which is past the point a line
218
- * can be read without losing the start of it — and reads as the app not
219
- * having an opinion rather than as it filling the space. The cap is the
220
- * width the markdown renderer was already holding answers to, so prose,
221
- * boxes and diffs now end in the same column instead of three.
209
+ * Every column the terminal has.
222
210
  *
223
- * Left, not centred: the shell prompt before and after a session sits on the
224
- * left margin, and a frame that jumps to the middle of the screen reads as a
225
- * different program. What is past the cap is cleared, never written to.
211
+ * Capped at 100 for a release, and it was wrong: on a wide monitor the frame
212
+ * sat in the left half of the screen with the rest of it empty, which reads
213
+ * as the window having failed to open rather than as a measured column. The
214
+ * interface fills what it is given. Prose inside it is still held to 100 by
215
+ * the markdown renderer, which is where that limit belongs — the boxes are
216
+ * the shape of the window, not of a paragraph.
226
217
  */
227
218
  width() {
228
- return Math.min(this.screenWidth(), MAX_WIDTH);
219
+ return Math.max(30, this.cols);
229
220
  }
230
221
 
231
222
  /** Usable width inside a box: two borders and a space of padding each side. */
@@ -299,25 +290,12 @@ export class Screen {
299
290
  this.endRun();
300
291
  this.add('');
301
292
 
302
- // A bullet on the first line that has words on it, and the rest of the
303
- // answer indented to clear it. Without the mark the reply is white text at
304
- // the same margin as the narration above it, and scrolling back there is
305
- // nothing to aim at — you find where the answer starts by reading until
306
- // the sentences stop being about files.
307
- //
308
- // Wrapped here rather than left to add(), which knows nothing about the
309
- // indent: marked-terminal is told not to reflow, so a long line arrives
310
- // whole, and a row add() broke for itself came back out at column zero
311
- // with the rest of the answer sitting two columns to its right.
312
- const room = Math.max(8, this.width() - 2);
313
- let marked = false;
314
- for (const row of render(this.md, body).split('\n')) {
315
- if (!row.trim()) { this.add(''); continue; }
316
- for (const line of wrapAnsi(row, room)) {
317
- this.add(marked ? ` ${line}` : `${answerMark()} ${line}`);
318
- marked = true;
319
- }
320
- }
293
+ // No bullet, and no indent. A mark on every reply made the answer read as
294
+ // one more step in the list above it, and on "Hey! How can I help you
295
+ // today?" it was a bullet on a greeting. The answer already wins the page
296
+ // by being the only thing on it at full strength; it does not also need to
297
+ // be labelled.
298
+ this.add(render(this.md, body));
321
299
 
322
300
  this.add('');
323
301
  this.render();
@@ -1473,10 +1451,7 @@ export class Screen {
1473
1451
 
1474
1452
  /** Where everything on the start screen goes, 0-based rows. */
1475
1453
  welcomeGeometry() {
1476
- // The true width here, not the capped one: the start screen centres itself,
1477
- // and centring inside the cap would park it left of the middle of a wide
1478
- // terminal. The session frame below is the thing that is left-aligned.
1479
- const cols = this.screenWidth();
1454
+ const cols = this.width();
1480
1455
  const boxWidth = Math.max(30, Math.min(cols - 4, 84));
1481
1456
  const left = Math.max(0, Math.floor((cols - boxWidth) / 2));
1482
1457
  const big = cols >= BANNER_WIDTH + 4 && this.rows >= 18;
package/src/ui/theme.js CHANGED
@@ -67,21 +67,6 @@ export const theme = {
67
67
  export const ADDED = chalk.bgHex('#0e2a1a').hex('#7ee2a8');
68
68
  export const REMOVED = chalk.bgHex('#331319').hex('#f2939c');
69
69
 
70
- /**
71
- * The widest the interface draws, however many columns the terminal has.
72
- *
73
- * An uncapped frame stretched its boxes across two hundred columns on a wide
74
- * monitor and ran prose the same distance, which is past the point a line can
75
- * be read without losing the start of it — and reads as the app having no
76
- * opinion rather than as it filling the space. marked-terminal was already
77
- * holding answers to 100, so this is the number the prose in the transcript
78
- * has always obeyed; the boxes and the diffs now obey it too.
79
- *
80
- * Both surfaces read it from here, because a full screen and a piped one
81
- * disagreeing about how wide the product is would be the odder thing.
82
- */
83
- export const MAX_WIDTH = 100;
84
-
85
70
  export const BANNER = [
86
71
  '██╗ ██╗ ██████╗ ██████╗ ██████╗ ███████╗',
87
72
  '██║ ██║██╔════╝██╔═══██╗██╔══██╗██╔════╝',
@@ -123,16 +108,6 @@ export function bannerPaint(row, rows = BANNER.length) {
123
108
  */
124
109
  export const RAIL = '▌';
125
110
 
126
- /**
127
- * The bullet beside the answer.
128
- *
129
- * The same circle as a step, because it is the same conversation, but at full
130
- * strength against the step's faint one. U+25CF and not U+23FA: the latter
131
- * carries emoji presentation, which Windows Terminal draws as a white circle
132
- * on a blue tile.
133
- */
134
- export const answerMark = () => blue.bold('●');
135
-
136
111
  /** The spinner. Braille dots, because they animate in place without jitter. */
137
112
  export const SPINNER = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
138
113