perchai-cli 2.4.1 → 2.4.3

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.
Files changed (2) hide show
  1. package/dist/perch.cjs +197 -89
  2. package/package.json +1 -1
package/dist/perch.cjs CHANGED
@@ -48438,23 +48438,23 @@ var require_html2canvas = __commonJS({
48438
48438
  });
48439
48439
  });
48440
48440
  };
48441
- CanvasRenderer2.prototype.renderNode = function(paint) {
48441
+ CanvasRenderer2.prototype.renderNode = function(paint2) {
48442
48442
  return __awaiter3(this, void 0, void 0, function() {
48443
48443
  return __generator2(this, function(_a) {
48444
48444
  switch (_a.label) {
48445
48445
  case 0:
48446
48446
  if (contains2(
48447
- paint.container.flags,
48447
+ paint2.container.flags,
48448
48448
  16
48449
48449
  /* DEBUG_RENDER */
48450
48450
  )) {
48451
48451
  debugger;
48452
48452
  }
48453
- if (!paint.container.styles.isVisible()) return [3, 3];
48454
- return [4, this.renderNodeBackgroundAndBorders(paint)];
48453
+ if (!paint2.container.styles.isVisible()) return [3, 3];
48454
+ return [4, this.renderNodeBackgroundAndBorders(paint2)];
48455
48455
  case 1:
48456
48456
  _a.sent();
48457
- return [4, this.renderNodeContent(paint)];
48457
+ return [4, this.renderNodeContent(paint2)];
48458
48458
  case 2:
48459
48459
  _a.sent();
48460
48460
  _a.label = 3;
@@ -48572,18 +48572,18 @@ var require_html2canvas = __commonJS({
48572
48572
  this.ctx.restore();
48573
48573
  }
48574
48574
  };
48575
- CanvasRenderer2.prototype.renderNodeContent = function(paint) {
48575
+ CanvasRenderer2.prototype.renderNodeContent = function(paint2) {
48576
48576
  return __awaiter3(this, void 0, void 0, function() {
48577
48577
  var container, curves, styles, _i, _a, child, image2, image2, iframeRenderer, canvas, size2, _b, fontFamily2, fontSize2, baseline, bounds, x, textBounds, img, image2, url, fontFamily2, bounds;
48578
48578
  return __generator2(this, function(_c) {
48579
48579
  switch (_c.label) {
48580
48580
  case 0:
48581
- this.applyEffects(paint.getEffects(
48581
+ this.applyEffects(paint2.getEffects(
48582
48582
  4
48583
48583
  /* CONTENT */
48584
48584
  ));
48585
- container = paint.container;
48586
- curves = paint.curves;
48585
+ container = paint2.container;
48586
+ curves = paint2.curves;
48587
48587
  styles = container.styles;
48588
48588
  _i = 0, _a = container.textNodes;
48589
48589
  _c.label = 1;
@@ -48731,14 +48731,14 @@ var require_html2canvas = __commonJS({
48731
48731
  case 18:
48732
48732
  return [3, 20];
48733
48733
  case 19:
48734
- if (paint.listValue && container.styles.listStyleType !== -1) {
48734
+ if (paint2.listValue && container.styles.listStyleType !== -1) {
48735
48735
  fontFamily2 = this.createFontStyle(styles)[0];
48736
48736
  this.ctx.font = fontFamily2;
48737
48737
  this.ctx.fillStyle = asString(styles.color);
48738
48738
  this.ctx.textBaseline = "middle";
48739
48739
  this.ctx.textAlign = "right";
48740
48740
  bounds = new Bounds(container.bounds.left, container.bounds.top + getAbsoluteValue(container.styles.paddingTop, container.bounds.width), container.bounds.width, computeLineHeight(styles.lineHeight, styles.fontSize.number) / 2 + 1);
48741
- this.renderTextWithLetterSpacing(new TextBounds(paint.listValue, bounds), styles.letterSpacing, computeLineHeight(styles.lineHeight, styles.fontSize.number) / 2 + 2);
48741
+ this.renderTextWithLetterSpacing(new TextBounds(paint2.listValue, bounds), styles.letterSpacing, computeLineHeight(styles.lineHeight, styles.fontSize.number) / 2 + 2);
48742
48742
  this.ctx.textBaseline = "bottom";
48743
48743
  this.ctx.textAlign = "left";
48744
48744
  }
@@ -49082,18 +49082,18 @@ var require_html2canvas = __commonJS({
49082
49082
  });
49083
49083
  });
49084
49084
  };
49085
- CanvasRenderer2.prototype.renderNodeBackgroundAndBorders = function(paint) {
49085
+ CanvasRenderer2.prototype.renderNodeBackgroundAndBorders = function(paint2) {
49086
49086
  return __awaiter3(this, void 0, void 0, function() {
49087
49087
  var styles, hasBackground, borders, backgroundPaintingArea, side, _i, borders_1, border;
49088
49088
  var _this = this;
49089
49089
  return __generator2(this, function(_a) {
49090
49090
  switch (_a.label) {
49091
49091
  case 0:
49092
- this.applyEffects(paint.getEffects(
49092
+ this.applyEffects(paint2.getEffects(
49093
49093
  2
49094
49094
  /* BACKGROUND_BORDERS */
49095
49095
  ));
49096
- styles = paint.container.styles;
49096
+ styles = paint2.container.styles;
49097
49097
  hasBackground = !isTransparent(styles.backgroundColor) || styles.backgroundImage.length;
49098
49098
  borders = [
49099
49099
  { style: styles.borderTopStyle, color: styles.borderTopColor, width: styles.borderTopWidth },
@@ -49101,7 +49101,7 @@ var require_html2canvas = __commonJS({
49101
49101
  { style: styles.borderBottomStyle, color: styles.borderBottomColor, width: styles.borderBottomWidth },
49102
49102
  { style: styles.borderLeftStyle, color: styles.borderLeftColor, width: styles.borderLeftWidth }
49103
49103
  ];
49104
- backgroundPaintingArea = calculateBackgroundCurvedPaintingArea(getBackgroundValueForIndex(styles.backgroundClip, 0), paint.curves);
49104
+ backgroundPaintingArea = calculateBackgroundCurvedPaintingArea(getBackgroundValueForIndex(styles.backgroundClip, 0), paint2.curves);
49105
49105
  if (!(hasBackground || styles.boxShadow.length)) return [3, 2];
49106
49106
  this.ctx.save();
49107
49107
  this.path(backgroundPaintingArea);
@@ -49110,13 +49110,13 @@ var require_html2canvas = __commonJS({
49110
49110
  this.ctx.fillStyle = asString(styles.backgroundColor);
49111
49111
  this.ctx.fill();
49112
49112
  }
49113
- return [4, this.renderBackgroundImage(paint.container)];
49113
+ return [4, this.renderBackgroundImage(paint2.container)];
49114
49114
  case 1:
49115
49115
  _a.sent();
49116
49116
  this.ctx.restore();
49117
49117
  styles.boxShadow.slice(0).reverse().forEach(function(shadow2) {
49118
49118
  _this.ctx.save();
49119
- var borderBoxArea = calculateBorderBoxPath(paint.curves);
49119
+ var borderBoxArea = calculateBorderBoxPath(paint2.curves);
49120
49120
  var maskOffset = shadow2.inset ? 0 : MASK_OFFSET;
49121
49121
  var shadowPaintingArea = transformPath(borderBoxArea, -maskOffset + (shadow2.inset ? 1 : -1) * shadow2.spread.number, (shadow2.inset ? 1 : -1) * shadow2.spread.number, shadow2.spread.number * (shadow2.inset ? -2 : 2), shadow2.spread.number * (shadow2.inset ? -2 : 2));
49122
49122
  if (shadow2.inset) {
@@ -49150,7 +49150,7 @@ var require_html2canvas = __commonJS({
49150
49150
  border.color,
49151
49151
  border.width,
49152
49152
  side,
49153
- paint.curves,
49153
+ paint2.curves,
49154
49154
  2
49155
49155
  /* DASHED */
49156
49156
  )];
@@ -49163,7 +49163,7 @@ var require_html2canvas = __commonJS({
49163
49163
  border.color,
49164
49164
  border.width,
49165
49165
  side,
49166
- paint.curves,
49166
+ paint2.curves,
49167
49167
  3
49168
49168
  /* DOTTED */
49169
49169
  )];
@@ -49172,12 +49172,12 @@ var require_html2canvas = __commonJS({
49172
49172
  return [3, 11];
49173
49173
  case 7:
49174
49174
  if (!(border.style === 4)) return [3, 9];
49175
- return [4, this.renderDoubleBorder(border.color, border.width, side, paint.curves)];
49175
+ return [4, this.renderDoubleBorder(border.color, border.width, side, paint2.curves)];
49176
49176
  case 8:
49177
49177
  _a.sent();
49178
49178
  return [3, 11];
49179
49179
  case 9:
49180
- return [4, this.renderSolidBorder(border.color, side, paint.curves)];
49180
+ return [4, this.renderSolidBorder(border.color, side, paint2.curves)];
49181
49181
  case 10:
49182
49182
  _a.sent();
49183
49183
  _a.label = 11;
@@ -213565,7 +213565,7 @@ function isSameTurnDuplicateExecution(execution) {
213565
213565
  }
213566
213566
 
213567
213567
  // features/perchTerminal/runtime/toolLoop.ts
213568
- var MAX_ITERATIONS = 10;
213568
+ var MAX_ITERATIONS = 32;
213569
213569
  var MAX_WORKER_ITERATIONS = 32;
213570
213570
  var SOURCE_ANALYSIS_MAX_ITERATIONS = 64;
213571
213571
  var MAX_PARALLEL_TOOL_CALLS = 8;
@@ -215387,7 +215387,7 @@ function addModelUsageSnapshots(current, next) {
215387
215387
  };
215388
215388
  }
215389
215389
  function sanitizeMaxIterations(value, cap = MAX_ITERATIONS) {
215390
- const defaultIterations = cap === MAX_WORKER_ITERATIONS ? 20 : MAX_ITERATIONS;
215390
+ const defaultIterations = cap === MAX_WORKER_ITERATIONS && MAX_WORKER_ITERATIONS > MAX_ITERATIONS ? 20 : MAX_ITERATIONS;
215391
215391
  if (typeof value !== "number" || !Number.isFinite(value) || value <= 0)
215392
215392
  return defaultIterations;
215393
215393
  return Math.min(Math.floor(value), cap);
@@ -220726,23 +220726,44 @@ function findRunId(events) {
220726
220726
  }
220727
220727
 
220728
220728
  // features/perchTerminal/runtime/cliHost/renderCliTurn.ts
220729
- function renderCliTurnText(result2) {
220729
+ var ANSI = {
220730
+ reset: "\x1B[0m",
220731
+ orange: "\x1B[38;2;196;80;0m",
220732
+ cream: "\x1B[38;2;255;248;240m",
220733
+ muted: "\x1B[38;2;142;133;125m",
220734
+ green: "\x1B[38;2;110;191;130m",
220735
+ red: "\x1B[38;2;208;107;85m"
220736
+ };
220737
+ function renderCliTurnText(result2, options = {}) {
220730
220738
  const lines = [];
220731
220739
  const seen = /* @__PURE__ */ new Set();
220732
220740
  for (const event of result2.events) {
220733
220741
  const line = renderEventLine(event);
220734
220742
  if (!line) continue;
220735
- if (seen.has(line)) continue;
220736
- seen.add(line);
220737
- lines.push(line);
220743
+ const lineKey = `${line.label}:${line.text}`;
220744
+ if (seen.has(lineKey)) continue;
220745
+ seen.add(lineKey);
220746
+ lines.push(renderStreamLine(line.label, line.text, options));
220738
220747
  }
220739
220748
  if (result2.assistantText.trim()) {
220740
220749
  if (lines.length) lines.push("");
220741
- lines.push(result2.assistantText.trim());
220750
+ lines.push(
220751
+ renderStreamLine(
220752
+ personaLabel(options.personaId),
220753
+ result2.assistantText.trim(),
220754
+ options
220755
+ )
220756
+ );
220742
220757
  }
220743
220758
  if (!result2.ok) {
220744
220759
  if (lines.length) lines.push("");
220745
- lines.push(`Perch stopped: ${result2.error ?? result2.status}`);
220760
+ lines.push(
220761
+ renderStreamLine(
220762
+ "stop",
220763
+ `Perch stopped: ${result2.error ?? result2.status}`,
220764
+ { ...options, color: options.color }
220765
+ )
220766
+ );
220746
220767
  }
220747
220768
  return `${lines.join("\n").trim()}
220748
220769
  `;
@@ -220759,33 +220780,36 @@ function renderEventLine(event) {
220759
220780
  case "assistant_preamble":
220760
220781
  case "activity_delta":
220761
220782
  case "workflow_narration":
220762
- return event.text.trim() || null;
220783
+ return event.text.trim() ? { label: "perch", text: event.text.trim() } : null;
220763
220784
  case "model_call_started":
220764
- return event.lane ? `Working (${event.lane})` : "Working";
220785
+ return { label: "work", text: event.lane ? `Working (${event.lane})` : "Working" };
220765
220786
  case "tool_call_started":
220766
- return `Running ${humanizeToolName(event.toolName)}`;
220787
+ return { label: "tool", text: `Running ${humanizeToolName(event.toolName)}` };
220767
220788
  case "tool_call_failed":
220768
- return `Needs attention: ${humanizeToolName(event.toolName)}${event.error ? ` \u2014 ${event.error}` : ""}`;
220789
+ return {
220790
+ label: "need",
220791
+ text: `Needs attention: ${humanizeToolName(event.toolName)}${event.error ? ` \u2014 ${event.error}` : ""}`
220792
+ };
220769
220793
  case "live_card_start":
220770
- return event.subtitle ? `${event.title} \u2014 ${event.subtitle}` : event.title;
220794
+ return { label: "tool", text: event.subtitle ? `${event.title} \xB7 ${event.subtitle}` : event.title };
220771
220795
  case "live_step":
220772
- return `${event.label} ${event.status}`;
220796
+ return { label: "tool", text: `${event.label} ${event.status}` };
220773
220797
  case "live_card_end":
220774
- return event.receipt?.summary ?? event.error ?? null;
220798
+ return event.receipt?.summary || event.error ? { label: event.error ? "need" : "tool", text: event.receipt?.summary ?? event.error ?? "" } : null;
220775
220799
  case "workflow_card_start":
220776
- return `${event.personaName}: ${event.workflowLabel}`;
220800
+ return { label: "tool", text: `${event.personaName}: ${event.workflowLabel}` };
220777
220801
  case "workflow_step":
220778
- return `${event.label} ${event.status}`;
220802
+ return { label: "tool", text: `${event.label} ${event.status}` };
220779
220803
  case "managed_workflow_started":
220780
- return event.title;
220804
+ return { label: "tool", text: event.title };
220781
220805
  case "managed_workflow_completed":
220782
- return event.summary;
220806
+ return { label: "tool", text: event.summary };
220783
220807
  case "capability_required":
220784
- return `Action needed: ${event.message}`;
220808
+ return { label: "need", text: `Action needed: ${event.message}` };
220785
220809
  case "executor_waiting_for_user":
220786
- return `Waiting: ${event.prompt}`;
220810
+ return { label: "wait", text: `Waiting: ${event.prompt}` };
220787
220811
  case "executor_result_summary":
220788
- return event.summary;
220812
+ return { label: "tool", text: event.summary };
220789
220813
  default:
220790
220814
  return null;
220791
220815
  }
@@ -220793,6 +220817,35 @@ function renderEventLine(event) {
220793
220817
  function humanizeToolName(name) {
220794
220818
  return name.replace(/^mcp__/, "").replace(/_/g, " ");
220795
220819
  }
220820
+ function renderStreamLine(label, text, options) {
220821
+ if (!options.streamLabels) return text;
220822
+ const rawLabel = label.toLowerCase().slice(0, 7);
220823
+ const padded = rawLabel.padEnd(7, " ");
220824
+ const labelText = colorize(padded, colorForLabel(rawLabel), options.color);
220825
+ const body = colorizeMultiline(text, colorForBody(rawLabel), options.color, " ".repeat(7));
220826
+ return `${labelText} ${body}`;
220827
+ }
220828
+ function colorize(text, color, enabled) {
220829
+ return enabled ? `${ANSI[color]}${text}${ANSI.reset}` : text;
220830
+ }
220831
+ function colorizeMultiline(text, color, enabled, continuationIndent) {
220832
+ const painted = colorize(text, color, enabled);
220833
+ return painted.replace(/\n/g, `
220834
+ ${continuationIndent} `);
220835
+ }
220836
+ function colorForLabel(label) {
220837
+ if (label === "need" || label === "stop") return "red";
220838
+ if (label === "tool" || label === "work" || label === "wait") return "muted";
220839
+ return "orange";
220840
+ }
220841
+ function colorForBody(label) {
220842
+ if (label === "need" || label === "stop") return "red";
220843
+ if (label === "tool" || label === "work" || label === "wait") return "muted";
220844
+ return "cream";
220845
+ }
220846
+ function personaLabel(personaId) {
220847
+ return personaId === "quill" ? "quill" : personaId === "saffron" ? "saffron" : "perch";
220848
+ }
220796
220849
 
220797
220850
  // features/perchTerminal/runtime/publicModelDefault.ts
220798
220851
  init_modelRegistry();
@@ -221198,6 +221251,15 @@ async function openExternal(url) {
221198
221251
  var import_meta2 = {};
221199
221252
  var execFileAsync3 = (0, import_node_util3.promisify)(import_node_child_process5.execFile);
221200
221253
  var DEFAULT_CLI_LOGIN_APP_URL = "https://app.perchai.app";
221254
+ var CLI_PACKAGE_VERSION = readCliPackageVersion();
221255
+ var ANSI2 = {
221256
+ reset: "\x1B[0m",
221257
+ orange: "\x1B[38;2;196;80;0m",
221258
+ cream: "\x1B[38;2;255;248;240m",
221259
+ muted: "\x1B[38;2;142;133;125m",
221260
+ green: "\x1B[38;2;110;191;130m",
221261
+ red: "\x1B[38;2;208;107;85m"
221262
+ };
221201
221263
  var HELP_TEXT = `Perch CLI
221202
221264
 
221203
221265
  Usage:
@@ -221273,7 +221335,10 @@ ${HELP_TEXT}`);
221273
221335
  desktopConnected: parsed.desktopConnected,
221274
221336
  cliLocalTools: parsed.cliLocalTools
221275
221337
  });
221276
- writeCliTurnResult(result3, parsed.json, writer);
221338
+ writeCliTurnResult(result3, parsed.json, writer, {
221339
+ personaId: parsed.personaId,
221340
+ color: shouldUseCliColor()
221341
+ });
221277
221342
  return cliExitCodeForTurn(result3);
221278
221343
  } finally {
221279
221344
  connection.restore();
@@ -221556,11 +221621,10 @@ async function runInteractivePerchCli(writer, deps, options) {
221556
221621
  connection = await connectCliModelProxy({ appUrl: state.appUrl });
221557
221622
  if (!state.appUrl && connection.appUrl) state.appUrl = connection.appUrl;
221558
221623
  };
221559
- writer.stdout("Perch CLI chat. Type /help for commands, /exit to quit.\n");
221560
- writer.stdout(renderInteractiveStatus(state, connection));
221624
+ writer.stdout(renderInteractiveStartup(state, connection));
221561
221625
  try {
221562
221626
  while (true) {
221563
- const prompt = (await rl.question("perch> ")).trim();
221627
+ const prompt = (await rl.question(renderInteractivePrompt(state))).trim();
221564
221628
  if (!prompt) continue;
221565
221629
  if (prompt === "/exit" || prompt === "exit" || prompt === "quit") break;
221566
221630
  if (prompt.startsWith("/")) {
@@ -221591,7 +221655,10 @@ async function runInteractivePerchCli(writer, deps, options) {
221591
221655
  desktopConnected: state.desktopConnected,
221592
221656
  cliLocalTools: state.cliLocalTools
221593
221657
  });
221594
- writeCliTurnResult(result2, false, writer);
221658
+ writeCliTurnResult(result2, false, writer, {
221659
+ personaId: state.personaId,
221660
+ color: shouldUseCliColor()
221661
+ });
221595
221662
  appendRecentMessage(state.recentMessages, "user", prompt);
221596
221663
  if (result2.assistantText.trim()) {
221597
221664
  appendRecentMessage(state.recentMessages, "assistant", result2.assistantText.trim());
@@ -221626,79 +221693,65 @@ async function runInteractiveSlashCommand(input) {
221626
221693
  }
221627
221694
  case "cwd":
221628
221695
  if (!parsed.value) {
221629
- input.writer.stdout(`cwd: ${input.state.cwd}
221630
- `);
221696
+ writeModeLine(input.writer, "cwd", input.state.cwd);
221631
221697
  return "continue";
221632
221698
  }
221633
221699
  input.state.cwd = resolveExistingDirectory(parsed.value);
221634
- input.writer.stdout(`cwd: ${input.state.cwd}
221635
- `);
221700
+ writeModeLine(input.writer, "cwd", input.state.cwd);
221636
221701
  return "continue";
221637
221702
  case "permission":
221638
221703
  if (!parsed.value) {
221639
- input.writer.stdout(`permission: ${input.state.permissionMode}
221640
- `);
221704
+ writeModeLine(input.writer, "permission", input.state.permissionMode);
221641
221705
  return "continue";
221642
221706
  }
221643
221707
  input.state.permissionMode = parsed.value;
221644
- input.writer.stdout(`permission: ${input.state.permissionMode}
221645
- `);
221708
+ writeModeLine(input.writer, "permission", input.state.permissionMode);
221646
221709
  return "continue";
221647
221710
  case "mode":
221648
221711
  if (!parsed.value) {
221649
- input.writer.stdout(`mode: ${input.state.chatMode}
221650
- `);
221712
+ writeModeLine(input.writer, "mode", input.state.chatMode);
221651
221713
  return "continue";
221652
221714
  }
221653
221715
  input.state.chatMode = parsed.value;
221654
- input.writer.stdout(`mode: ${input.state.chatMode}
221655
- `);
221716
+ writeModeLine(input.writer, "mode", input.state.chatMode);
221656
221717
  return "continue";
221657
221718
  case "persona":
221658
221719
  if (!parsed.value) {
221659
- input.writer.stdout(`persona: ${input.state.personaId}
221660
- `);
221720
+ writeModeLine(input.writer, "persona", input.state.personaId);
221661
221721
  return "continue";
221662
221722
  }
221663
221723
  input.state.personaId = parsed.value;
221664
- input.writer.stdout(`persona: ${input.state.personaId}
221665
- `);
221724
+ writeModeLine(input.writer, "persona", input.state.personaId);
221666
221725
  return "continue";
221667
221726
  case "appUrl":
221668
221727
  if (!parsed.value) {
221669
- input.writer.stdout(`app-url: ${input.state.appUrl ?? "(none)"}
221670
- `);
221728
+ writeModeLine(input.writer, "app-url", input.state.appUrl ?? "(none)");
221671
221729
  return "continue";
221672
221730
  }
221673
221731
  input.state.appUrl = requireCliAppUrl(parsed.value);
221674
221732
  await input.reconnect();
221675
- input.writer.stdout(`app-url: ${input.state.appUrl}
221676
- `);
221733
+ writeModeLine(input.writer, "app-url", input.state.appUrl);
221677
221734
  return "continue";
221678
221735
  case "localTools":
221679
221736
  if (parsed.value === void 0) {
221680
- input.writer.stdout(`local-tools: ${input.state.cliLocalTools ? "on" : "off"}
221681
- `);
221737
+ writeModeLine(input.writer, "local-tools", input.state.cliLocalTools ? "on" : "off");
221682
221738
  return "continue";
221683
221739
  }
221684
221740
  input.state.cliLocalTools = parsed.value;
221685
- input.writer.stdout(`local-tools: ${input.state.cliLocalTools ? "on" : "off"}
221686
- `);
221741
+ writeModeLine(input.writer, "local-tools", input.state.cliLocalTools ? "on" : "off");
221687
221742
  return "continue";
221688
221743
  case "thread":
221689
221744
  if (!parsed.value) {
221690
- input.writer.stdout(`thread: ${input.state.threadId}
221691
- `);
221745
+ writeModeLine(input.writer, "thread", input.state.threadId);
221692
221746
  return "continue";
221693
221747
  }
221694
221748
  input.state.threadId = parsed.value === "new" ? `cli-${Date.now()}` : parsed.value;
221695
221749
  input.state.recentMessages = [];
221696
- input.writer.stdout(`thread: ${input.state.threadId}
221697
- `);
221750
+ writeModeLine(input.writer, "thread", input.state.threadId);
221698
221751
  return "continue";
221699
221752
  case "clear":
221700
221753
  input.state.recentMessages = [];
221701
- input.writer.stdout("Conversation memory cleared for this terminal session.\n");
221754
+ writeModeLine(input.writer, "memory", "cleared");
221702
221755
  return "continue";
221703
221756
  case "login":
221704
221757
  await runAuthCommand({
@@ -221712,7 +221765,7 @@ async function runInteractiveSlashCommand(input) {
221712
221765
  case "logout":
221713
221766
  await clearStoredCliAuthSession();
221714
221767
  await input.reconnect();
221715
- input.writer.stdout("Perch CLI session cleared.\n");
221768
+ writeModeLine(input.writer, "auth", "signed out");
221716
221769
  return "continue";
221717
221770
  case "exit":
221718
221771
  return "exit";
@@ -221770,16 +221823,36 @@ function parseInteractiveSlashCommand(input) {
221770
221823
  }
221771
221824
  function renderInteractiveStatus(state, connection, session) {
221772
221825
  const auth = session === void 0 ? connection?.authenticated ? `signed in${connection.email ? ` as ${connection.email}` : ""}` : "public/anonymous" : isStoredCliAuthSessionUsable(session) ? `signed in${session.email ? ` as ${session.email}` : ""}` : "not signed in";
221826
+ const color = shouldUseCliColor();
221827
+ const lines = [
221828
+ ["cwd", state.cwd],
221829
+ ["permission", state.permissionMode],
221830
+ ["mode", state.chatMode],
221831
+ ["persona", state.personaId],
221832
+ ["thread", state.threadId],
221833
+ ["local-tools", state.cliLocalTools ? "on" : "off"],
221834
+ ["app-url", state.appUrl ?? connection?.appUrl ?? "(none)"],
221835
+ ["auth", auth]
221836
+ ];
221837
+ return lines.map(([key, value]) => `${paint(key.padEnd(11), "muted", color)} ${value}`).join("\n") + "\n";
221838
+ }
221839
+ function renderInteractiveStartup(state, connection) {
221840
+ const color = shouldUseCliColor();
221841
+ const auth = connection.authenticated ? `signed in${connection.email ? ` as ${connection.email}` : ""}` : "public/anonymous";
221773
221842
  return [
221774
- `cwd: ${state.cwd}`,
221775
- `permission: ${state.permissionMode}`,
221776
- `mode: ${state.chatMode}`,
221777
- `persona: ${state.personaId}`,
221778
- `thread: ${state.threadId}`,
221779
- `local-tools: ${state.cliLocalTools ? "on" : "off"}`,
221780
- `app-url: ${state.appUrl ?? connection?.appUrl ?? "(none)"}`,
221781
- `auth: ${auth}`
221782
- ].join(" \xB7 ") + "\n";
221843
+ `${paint("P", "orange", color)} ${paint("Perch CLI", "cream", color)} ${paint(CLI_PACKAGE_VERSION, "muted", color)}`,
221844
+ ` ${[auth, state.personaId, state.chatMode, state.permissionMode, shortCwd(state.cwd)].join(" \xB7 ")}`,
221845
+ ""
221846
+ ].join("\n");
221847
+ }
221848
+ function renderInteractivePrompt(state) {
221849
+ const color = shouldUseCliColor();
221850
+ return `${paint(state.personaId, "orange", color)}${paint("\u203A", "orange", color)} `;
221851
+ }
221852
+ function writeModeLine(writer, key, value) {
221853
+ const color = shouldUseCliColor();
221854
+ writer.stdout(`${paint("mode".padEnd(7), "muted", color)} ${key} \u2192 ${value}
221855
+ `);
221783
221856
  }
221784
221857
  function parseGlobalFlags(argv) {
221785
221858
  const args = [];
@@ -221907,13 +221980,17 @@ function parseTestApCommand(folderPath, rest2) {
221907
221980
  }
221908
221981
  return { ok: true, domain: "test", action: "ap", folderPath, json, outputRoot, timestamp, profile, expectations, includePacket };
221909
221982
  }
221910
- function writeCliTurnResult(result2, json, writer) {
221983
+ function writeCliTurnResult(result2, json, writer, options = {}) {
221911
221984
  if (json) {
221912
221985
  writer.stdout(`${JSON.stringify(result2, null, 2)}
221913
221986
  `);
221914
221987
  return;
221915
221988
  }
221916
- writer.stdout(renderCliTurnText(result2));
221989
+ writer.stdout(renderCliTurnText(result2, {
221990
+ personaId: options.personaId,
221991
+ color: options.color,
221992
+ streamLabels: true
221993
+ }));
221917
221994
  }
221918
221995
  function writeAPEvidenceResult(result2, json, writer) {
221919
221996
  if (json) {
@@ -222017,6 +222094,37 @@ function parseExpectation(input) {
222017
222094
  if (Number.isFinite(numeric) && rawValue !== "") return { key, value: numeric };
222018
222095
  return { key, value: rawValue };
222019
222096
  }
222097
+ function readCliPackageVersion() {
222098
+ const candidates = [
222099
+ import_node_path15.default.resolve(__dirname, "../packages/cli/package.json"),
222100
+ import_node_path15.default.resolve(__dirname, "../package.json")
222101
+ ];
222102
+ for (const candidate of candidates) {
222103
+ try {
222104
+ const raw = import_node_fs10.default.readFileSync(candidate, "utf8");
222105
+ const parsed = JSON.parse(raw);
222106
+ if (typeof parsed.version === "string" && parsed.version.trim()) {
222107
+ return parsed.version.trim();
222108
+ }
222109
+ } catch {
222110
+ }
222111
+ }
222112
+ return "dev";
222113
+ }
222114
+ function shortCwd(cwd) {
222115
+ const home = process.env.HOME;
222116
+ if (home && cwd === home) return "~";
222117
+ if (home && cwd.startsWith(`${home}${import_node_path15.default.sep}`)) {
222118
+ return `~/${cwd.slice(home.length + 1)}`;
222119
+ }
222120
+ return cwd;
222121
+ }
222122
+ function shouldUseCliColor() {
222123
+ return Boolean(process.stdout.isTTY) && process.env.NO_COLOR !== "1";
222124
+ }
222125
+ function paint(text, color, enabled) {
222126
+ return enabled ? `${ANSI2[color]}${text}${ANSI2.reset}` : text;
222127
+ }
222020
222128
  function defaultWriter() {
222021
222129
  return {
222022
222130
  stdout: (text) => process.stdout.write(text),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "perchai-cli",
3
- "version": "2.4.1",
3
+ "version": "2.4.3",
4
4
  "description": "Perch AI command-line interface",
5
5
  "bin": {
6
6
  "perch": "bin/perch"