ucode-agent 1.22.0 → 1.24.0

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/src/ui/screen.js CHANGED
@@ -39,7 +39,7 @@ import chalk from 'chalk';
39
39
  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
- shortenPath, asLabel, ensureColour, planLine, bare, narration, narrationMark, groupKind, groupLabel, groupTarget, runLine, planRows, withoutCodeBlocks } from './theme.js';
42
+ shortenPath, asLabel, ensureColour, planLine, bare, narration, narrationMark, groupKind, groupLabel, groupTarget, runLine, planRows, tidyReply } from './theme.js';
43
43
  import { FRAME_MS, fitActivity, shimmer, spinnerGlyph, formatDuration, doneLine, stepPaint } from './activity.js';
44
44
  import { renderer, render, polish } from './markdown.js';
45
45
  import { VERSION } from '../core/version.js';
@@ -258,7 +258,7 @@ export class Screen {
258
258
  if (!text?.trim()) return;
259
259
  this.endRun();
260
260
  this.add('');
261
- this.add(render(this.md, withoutCodeBlocks(text)));
261
+ this.add(render(this.md, tidyReply(text)));
262
262
  this.add('');
263
263
  this.render();
264
264
  }
@@ -541,44 +541,17 @@ export class Screen {
541
541
  // and the transcript gets one line afterwards saying how long it took.
542
542
 
543
543
  /**
544
- * The first thing the model says, as soon as it has said it.
544
+ * The model's reasoning does not go on screen.
545
545
  *
546
- * Models reach for a tool before writing any reply, so nothing appeared for
547
- * the first minute of a step. The reasoning channel streams from the first
548
- * moment, so its opening sentence goes up as one line and stays there: what
549
- * it is setting out to do, which is the thing worth knowing while you wait.
550
- *
551
- * Written once, never rewritten. Rewriting it as more arrived was the
552
- * flicker — an unfinished sentence showed as a single word, then jumped.
546
+ * It was surfaced here to fill the wait before the first tool call, and what
547
+ * it actually filled it with was the model talking to itself: "I need to
548
+ * build this", "The user wants a tasks app". Nobody needs their own request
549
+ * read back to them, and half-formed working-out is not something to publish.
550
+ * What the model *says* is its reply, and that is the only thing shown.
553
551
  */
554
- thinkingDelta(text = '') {
555
- if (this.thoughtSince === undefined) this.thoughtSince = Date.now();
556
- if (!text || this.openedWith) return;
557
-
558
- this.thought = ((this.thought ?? '') + text).slice(0, 600);
559
- const tidy = this.thought.replace(/\s+/g, ' ').trim();
560
- const finished = /^(.+?[.!?])(?:\s|$)/.exec(tidy);
561
- if (!finished) return;
552
+ thinkingDelta() {}
562
553
 
563
- const line = finished[1].trim();
564
- if (line.length < 12) return; // "Okay." tells nobody anything
565
- // Reasoning models open by restating the request to themselves — "The user
566
- // wants a tasks app called Tide" — which the user wrote, is looking at, and
567
- // does not need read back. Only a sentence about what is being done is
568
- // worth the line.
569
- if (RESTATEMENT.test(line)) { this.thought = ''; return; }
570
-
571
- this.openedWith = line;
572
- // Full strength: this is the model talking, and it is the thing on the page
573
- // worth reading. The dimmed lines around it are the machinery.
574
- this.push(' ' + chalk.white(clip(line, Math.max(30, this.width() - 6))));
575
- }
576
-
577
- thinkingEnd() {
578
- this.thought = '';
579
- this.openedWith = undefined;
580
- this.thoughtSince = undefined;
581
- }
554
+ thinkingEnd() {}
582
555
 
583
556
  error(err, { debug = false } = {}) {
584
557
  const known = err && typeof err === 'object' && err.attempted;
@@ -804,7 +777,9 @@ export class Screen {
804
777
  const a = this.activity;
805
778
  const since = a?.start ?? this.status.since ?? now;
806
779
  const meta = [];
807
- if (a?.steps) meta.push({ text: `step ${a.steps}`, paint: stepPaint(now - a.movedAt < 900) });
780
+ // No step count. It measures how much machinery ran, which is not
781
+ // something the person waiting has any use for; the elapsed time is.
782
+ void stepPaint;
808
783
  if (now - since >= 1000) meta.push({ text: formatDuration(now - since), keep: true });
809
784
  middle = fitActivity({
810
785
  glyph: spinnerGlyph(this.tick, now),
@@ -910,9 +885,13 @@ export class Screen {
910
885
  const a = this.activity;
911
886
  this.activity = null;
912
887
  if (!this.status.busy) this.stopTimer();
913
- // A turn that stopped without finishing says so. Dropping the line entirely
914
- // left the transcript looking like the work was still going.
915
- if (a && Date.now() - a.start >= 2000) this.push(` ${doneLine(Date.now() - a.start, a.steps, { ok })}`);
888
+ // Nothing is written when a turn finishes. The reply is the end of the
889
+ // turn, and a timing line under it is bookkeeping the reader did not ask
890
+ // for. A turn that stopped *without* finishing still says so, because
891
+ // silence there is indistinguishable from a crash.
892
+ if (a && !ok && Date.now() - a.start >= 2000) {
893
+ this.push(` ${doneLine(Date.now() - a.start, a.steps, { ok })}`);
894
+ }
916
895
  this.paintStatus();
917
896
  }
918
897