agent.libx.js 0.93.28 → 0.93.29

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/cli/cli.ts CHANGED
@@ -314,14 +314,19 @@ function makeHost(format: 'text' | 'json' | 'stream-json' = 'text', opts?: { str
314
314
  const md = format === 'text' && useColor && opts?.stream ? new MarkdownStream({ bold, dim, cyan }, process.stdout.columns ?? 80) : null;
315
315
  if (md) process.on('SIGWINCH', () => md.resize(process.stdout.columns ?? 80)); // reflow streamed markdown on resize
316
316
  const flushText = () => { if (md && md.pending()) process.stdout.write(md.flush()); };
317
+ // `thinking_delta` streams to stderr WITHOUT a trailing newline (a continuous dimmed reasoning flow).
318
+ // Any other output that follows (the answer on stdout, a `· notice`, the next step header) must first
319
+ // close that open line — else it collides mid-word into the reasoning tail (`· step 2` → `step ya`).
320
+ let openReasonLine = false;
321
+ const closeReasonLine = () => { if (openReasonLine) { process.stderr.write('\n'); openReasonLine = false; } };
317
322
  return {
318
323
  flushText,
319
324
  notify(e) {
320
325
  spinner.stop(); // real output arriving → clear the spinner first
321
326
  if (e.kind === 'text_delta') {
322
327
  if (streamJson) process.stdout.write(JSON.stringify({ type: 'text', text: e.message }) + '\n');
323
- else if (md) process.stdout.write(md.feed(e.message)); // line-buffered markdown render
324
- else (cleanStdout ? process.stderr : process.stdout).write(e.message); // json keeps stdout clean → stderr
328
+ else if (md) { closeReasonLine(); process.stdout.write(md.feed(e.message)); } // line-buffered markdown render
329
+ else { if (!cleanStdout) closeReasonLine(); (cleanStdout ? process.stderr : process.stdout).write(e.message); } // json keeps stdout clean → stderr
325
330
  return;
326
331
  }
327
332
  // extended-thinking (reasoning-native models): a dimmed stderr flow in text mode; a typed event in
@@ -333,12 +338,17 @@ function makeHost(format: 'text' | 'json' | 'stream-json' = 'text', opts?: { str
333
338
  // stay in order — otherwise late-flushed markdown lands after the thinking it preceded.
334
339
  if (md && md.pending()) process.stdout.write(md.flush() + '\n');
335
340
  process.stderr.write(dim(e.message));
341
+ openReasonLine = true; // unterminated reasoning line — next output must close it
336
342
  }
337
343
  return;
338
344
  }
345
+ // Structural events (tool_use/tool_result/tool_result_image/turn_start) have dedicated renderers
346
+ // (displayHooks ⚙ chrome, the step header) — never dump their raw `kind` as a `· notice`, or the
347
+ // result preview gets sandwiched between junk `· tool_use`/`· tool_result` labels.
348
+ if (!('message' in e)) return;
349
+ closeReasonLine(); // close an open reasoning line so the notice starts fresh (not glued mid-word)
339
350
  if (md && md.pending()) process.stdout.write(md.flush() + '\n'); // finish the in-progress line before a notice
340
- const notice = 'message' in e ? e.message : e.kind; // not every HostEvent variant carries `message`
341
- err(dim(` · ${notice}\n`)); // tool-activity notices stay on stderr (human chrome) for every format
351
+ err(dim(` · ${e.message}\n`)); // tool-activity notices stay on stderr (human chrome) for every format
342
352
  },
343
353
  async confirm(prompt) {
344
354
  // arrow-select on a TTY; fall back to a typed y/N when piped (selectMenu → null)
package/dist/cli.js CHANGED
@@ -7993,14 +7993,26 @@ function makeHost(format = "text", opts) {
7993
7993
  const flushText = () => {
7994
7994
  if (md && md.pending()) process.stdout.write(md.flush());
7995
7995
  };
7996
+ let openReasonLine = false;
7997
+ const closeReasonLine = () => {
7998
+ if (openReasonLine) {
7999
+ process.stderr.write("\n");
8000
+ openReasonLine = false;
8001
+ }
8002
+ };
7996
8003
  return {
7997
8004
  flushText,
7998
8005
  notify(e) {
7999
8006
  spinner.stop();
8000
8007
  if (e.kind === "text_delta") {
8001
8008
  if (streamJson) process.stdout.write(JSON.stringify({ type: "text", text: e.message }) + "\n");
8002
- else if (md) process.stdout.write(md.feed(e.message));
8003
- else (cleanStdout ? process.stderr : process.stdout).write(e.message);
8009
+ else if (md) {
8010
+ closeReasonLine();
8011
+ process.stdout.write(md.feed(e.message));
8012
+ } else {
8013
+ if (!cleanStdout) closeReasonLine();
8014
+ (cleanStdout ? process.stderr : process.stdout).write(e.message);
8015
+ }
8004
8016
  return;
8005
8017
  }
8006
8018
  if (e.kind === "thinking_delta") {
@@ -8008,12 +8020,14 @@ function makeHost(format = "text", opts) {
8008
8020
  else if (!cleanStdout) {
8009
8021
  if (md && md.pending()) process.stdout.write(md.flush() + "\n");
8010
8022
  process.stderr.write(dim(e.message));
8023
+ openReasonLine = true;
8011
8024
  }
8012
8025
  return;
8013
8026
  }
8027
+ if (!("message" in e)) return;
8028
+ closeReasonLine();
8014
8029
  if (md && md.pending()) process.stdout.write(md.flush() + "\n");
8015
- const notice = "message" in e ? e.message : e.kind;
8016
- err(dim(` \xB7 ${notice}
8030
+ err(dim(` \xB7 ${e.message}
8017
8031
  `));
8018
8032
  },
8019
8033
  async confirm(prompt) {