perchai-cli 2.4.5 → 2.4.6

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.mjs +129 -63
  2. package/package.json +1 -1
package/dist/perch.mjs CHANGED
@@ -277628,21 +277628,22 @@ async function runInkInteractivePerchCli(writer, deps, options) {
277628
277628
  const [workingText, setWorkingText] = React11.useState("ready");
277629
277629
  const [pulse, setPulse] = React11.useState(0);
277630
277630
  const [, refresh] = React11.useState(0);
277631
+ const liveTextRef = React11.useRef("");
277631
277632
  React11.useEffect(() => {
277632
277633
  if (!working) return void 0;
277633
- const timer = setInterval(() => setPulse((value) => (value + 1) % 4), 280);
277634
+ const timer = setInterval(() => setPulse((value) => value + 1), 120);
277634
277635
  return () => clearInterval(timer);
277635
277636
  }, [working]);
277636
277637
  const addItem = React11.useCallback((item) => {
277637
277638
  setItems((current) => [
277638
277639
  ...current,
277639
277640
  { id: `cli-item-${Date.now()}-${current.length}`, ...item }
277640
- ].slice(-80));
277641
+ ].slice(-INK_ROW_LIMIT));
277641
277642
  }, []);
277642
277643
  const updateToolItem = React11.useCallback((id, item) => {
277643
277644
  setItems((current) => {
277644
277645
  const index = current.findIndex((entry) => entry.id === id);
277645
- if (index < 0) return [...current, { id, ...item }].slice(-80);
277646
+ if (index < 0) return [...current, { id, ...item }].slice(-INK_ROW_LIMIT);
277646
277647
  const next = current.slice();
277647
277648
  next[index] = { id, ...item };
277648
277649
  return next;
@@ -277694,6 +277695,7 @@ async function runInkInteractivePerchCli(writer, deps, options) {
277694
277695
  setWorking(true);
277695
277696
  setWorkingText("thinking");
277696
277697
  setLiveText("");
277698
+ liveTextRef.current = "";
277697
277699
  const toolNamesById = /* @__PURE__ */ new Map();
277698
277700
  try {
277699
277701
  if (!isCliModelConnectionReady(connection)) {
@@ -277719,13 +277721,14 @@ async function runInkInteractivePerchCli(writer, deps, options) {
277719
277721
  switch (event.type) {
277720
277722
  case "content_delta":
277721
277723
  case "streaming_text":
277722
- setLiveText((text) => text + event.text);
277724
+ liveTextRef.current += event.text;
277725
+ setLiveText(liveTextRef.current);
277723
277726
  break;
277724
277727
  case "assistant_preamble":
277725
277728
  case "activity_delta":
277726
277729
  case "workflow_narration":
277727
277730
  if (event.text.trim()) {
277728
- addItem({ label: "perch", text: event.text.trim(), tone: "normal" });
277731
+ addItem({ label: state.personaId, text: event.text.trim(), tone: "normal" });
277729
277732
  }
277730
277733
  break;
277731
277734
  case "model_call_started":
@@ -277777,7 +277780,7 @@ async function runInkInteractivePerchCli(writer, deps, options) {
277777
277780
  }
277778
277781
  });
277779
277782
  setLiveText("");
277780
- const assistantText = result2.assistantText.trim() || liveText.trim();
277783
+ const assistantText = result2.assistantText.trim() || liveTextRef.current.trim();
277781
277784
  if (assistantText) {
277782
277785
  addItem({ label: state.personaId, text: assistantText, tone: "normal" });
277783
277786
  }
@@ -277799,8 +277802,9 @@ async function runInkInteractivePerchCli(writer, deps, options) {
277799
277802
  setWorking(false);
277800
277803
  setWorkingText("ready");
277801
277804
  setLiveText("");
277805
+ liveTextRef.current = "";
277802
277806
  }
277803
- }, [addItem, app, draft, liveText, reconnect, runTurn, updateToolItem, working]);
277807
+ }, [addItem, app, reconnect, runTurn, updateToolItem, working]);
277804
277808
  Ink2.useInput((input, key) => {
277805
277809
  if (working) return;
277806
277810
  if (key.return) {
@@ -277819,13 +277823,35 @@ async function runInkInteractivePerchCli(writer, deps, options) {
277819
277823
  if (input && !key.escape) setDraft((value) => value + input);
277820
277824
  });
277821
277825
  const pulseColor = pulse % 2 === 0 ? "#c45000" : "#8e857d";
277826
+ const spinnerGlyph = inkSpinnerFrame(pulse);
277822
277827
  const auth = renderCliAuthSummary(connection);
277823
277828
  const meta = `${state.personaId} \xB7 ${state.chatMode} \xB7 ${state.permissionMode}`;
277824
277829
  const route = connection.authenticated && connection.appUrl ? connection.appUrl.replace(/^https?:\/\//, "") : "run /login";
277830
+ const renderTranscriptRow = (key, label, line, tone, showLabel) => React11.createElement(
277831
+ Ink2.Box,
277832
+ { key },
277833
+ React11.createElement(
277834
+ Ink2.Box,
277835
+ { width: INK_LABEL_WIDTH, flexShrink: 0 },
277836
+ React11.createElement(
277837
+ Ink2.Text,
277838
+ {
277839
+ color: colorForInkTone(tone),
277840
+ bold: tone === "accent"
277841
+ },
277842
+ showLabel ? renderInkSpeakerLabel(label) : ""
277843
+ )
277844
+ ),
277845
+ React11.createElement(
277846
+ Ink2.Box,
277847
+ { flexGrow: 1 },
277848
+ React11.createElement(Ink2.Text, { color: bodyColorForInkTone(tone) }, line)
277849
+ )
277850
+ );
277825
277851
  const renderTranscriptItem = (item, index) => {
277826
277852
  const lines = item.text.split(/\r?\n/);
277827
277853
  const previous = items[index - 1];
277828
- const separateFromUser = previous?.label === "you" && item.label !== "you";
277854
+ const separateFromUser = previous?.label === "you" && item.label !== "you" && item.tone !== "danger";
277829
277855
  return React11.createElement(
277830
277856
  Ink2.Box,
277831
277857
  { key: item.id, flexDirection: "column", marginTop: separateFromUser ? 1 : 0 },
@@ -277833,29 +277859,14 @@ async function runInkInteractivePerchCli(writer, deps, options) {
277833
277859
  Ink2.Box,
277834
277860
  null,
277835
277861
  React11.createElement(Ink2.Box, { width: INK_LABEL_WIDTH, flexShrink: 0 }),
277836
- React11.createElement(Ink2.Text, { color: "#2a211c" }, "------------------------------")
277862
+ React11.createElement(Ink2.Text, { color: "#2a211c" }, INK_DIVIDER)
277837
277863
  ) : null,
277838
- lines.map((line, lineIndex) => React11.createElement(
277839
- Ink2.Box,
277840
- { key: `${item.id}-${lineIndex}` },
277841
- React11.createElement(
277842
- Ink2.Box,
277843
- { width: INK_LABEL_WIDTH, flexShrink: 0 },
277844
- React11.createElement(
277845
- Ink2.Text,
277846
- {
277847
- color: colorForInkTone(item.tone),
277848
- bold: item.tone === "accent",
277849
- wrap: "truncate"
277850
- },
277851
- lineIndex === 0 ? item.label : ""
277852
- )
277853
- ),
277854
- React11.createElement(
277855
- Ink2.Box,
277856
- { flexGrow: 1 },
277857
- React11.createElement(Ink2.Text, { color: bodyColorForInkTone(item.tone) }, line)
277858
- )
277864
+ lines.map((line, lineIndex) => renderTranscriptRow(
277865
+ `${item.id}-${lineIndex}`,
277866
+ item.label,
277867
+ line,
277868
+ item.tone,
277869
+ lineIndex === 0
277859
277870
  ))
277860
277871
  );
277861
277872
  };
@@ -277865,42 +277876,58 @@ async function runInkInteractivePerchCli(writer, deps, options) {
277865
277876
  React11.createElement(
277866
277877
  Ink2.Box,
277867
277878
  { flexDirection: "column", alignItems: "center", marginBottom: 1, paddingY: 1 },
277868
- ...PERCH_CLI_MARK.map(
277879
+ React11.createElement(
277880
+ Ink2.Box,
277881
+ { width: PERCH_SPLASH_WIDTH, justifyContent: "space-between", marginBottom: 1 },
277882
+ React11.createElement(Ink2.Text, { color: "#7a6f66" }, "perch \xB7 field terminal"),
277883
+ React11.createElement(Ink2.Text, { color: "#7a6f66" }, `v${CLI_PACKAGE_VERSION}`)
277884
+ ),
277885
+ ...PERCH_SPLASH_SCENE.map(
277869
277886
  (line, index) => React11.createElement(
277870
- Ink2.Text,
277871
- { key: `mark-${index}`, color: index === 1 && working ? pulseColor : "#c45000", bold: true },
277872
- line
277887
+ Ink2.Box,
277888
+ { key: `field-${index}`, width: PERCH_SPLASH_WIDTH },
277889
+ React11.createElement(
277890
+ Ink2.Text,
277891
+ { color: working && index === 11 ? pulseColor : "#c45000", bold: true },
277892
+ line
277893
+ )
277873
277894
  )
277874
277895
  ),
277875
277896
  React11.createElement(
277876
277897
  Ink2.Box,
277877
277898
  { marginTop: 1 },
277878
- React11.createElement(Ink2.Text, { color: "#c45000", bold: true }, "Perch"),
277879
- React11.createElement(Ink2.Text, { color: "#8e857d" }, " | "),
277880
- React11.createElement(Ink2.Text, { bold: true }, "Terminal")
277899
+ React11.createElement(Ink2.Text, { color: "#c45000" }, "perched"),
277900
+ React11.createElement(Ink2.Text, { color: "#8e857d" }, " in "),
277901
+ React11.createElement(Ink2.Text, { color: "#fff8f0", bold: true }, shortCwd(state.cwd))
277881
277902
  ),
277882
- React11.createElement(Ink2.Text, { color: "#8e857d" }, CLI_PACKAGE_VERSION),
277883
277903
  React11.createElement(
277884
277904
  Ink2.Text,
277885
277905
  { color: "#8e857d", wrap: "truncate-middle" },
277886
277906
  `${auth} \xB7 ${meta}`
277887
277907
  ),
277908
+ React11.createElement(
277909
+ Ink2.Box,
277910
+ { flexDirection: "column", marginTop: 1 },
277911
+ ...PERCH_SPLASH_COMMANDS.map(
277912
+ ([command, description]) => React11.createElement(
277913
+ Ink2.Box,
277914
+ { key: command },
277915
+ React11.createElement(Ink2.Box, { width: 16 }, React11.createElement(Ink2.Text, { color: "#c45000" }, command)),
277916
+ React11.createElement(Ink2.Text, { color: "#8e857d" }, description)
277917
+ )
277918
+ )
277919
+ ),
277888
277920
  React11.createElement(
277889
277921
  Ink2.Text,
277890
- { color: "#8e857d", wrap: "truncate-middle" },
277891
- `${route} \xB7 ${shortCwd(state.cwd)}`
277922
+ { color: "#5e554d", wrap: "truncate-middle" },
277923
+ route
277892
277924
  )
277893
277925
  ),
277894
277926
  ...items.map(renderTranscriptItem),
277895
277927
  liveText ? React11.createElement(
277896
277928
  Ink2.Box,
277897
277929
  { key: "live-text" },
277898
- React11.createElement(
277899
- Ink2.Box,
277900
- { width: INK_LABEL_WIDTH, flexShrink: 0 },
277901
- React11.createElement(Ink2.Text, { color: "#c45000" }, state.personaId)
277902
- ),
277903
- React11.createElement(Ink2.Text, null, ` ${liveText}`)
277930
+ renderTranscriptRow("live-text-row", state.personaId, liveText, "normal", true)
277904
277931
  ) : null,
277905
277932
  working ? React11.createElement(
277906
277933
  Ink2.Box,
@@ -277908,9 +277935,13 @@ async function runInkInteractivePerchCli(writer, deps, options) {
277908
277935
  React11.createElement(
277909
277936
  Ink2.Box,
277910
277937
  { width: INK_LABEL_WIDTH, flexShrink: 0 },
277911
- React11.createElement(Ink2.Text, { color: pulseColor, bold: true }, "perch")
277938
+ React11.createElement(Ink2.Text, { color: pulseColor, bold: true }, spinnerGlyph)
277912
277939
  ),
277913
- React11.createElement(Ink2.Text, { color: "#8e857d" }, ` ${workingText}\u2026`)
277940
+ React11.createElement(
277941
+ Ink2.Text,
277942
+ { color: "#8e857d" },
277943
+ `${state.personaId} \xB7 ${workingText}\u2026`
277944
+ )
277914
277945
  ) : null,
277915
277946
  React11.createElement(
277916
277947
  Ink2.Box,
@@ -278097,14 +278128,21 @@ function renderInteractiveStatus(state, connection, session) {
278097
278128
  function renderInteractiveStartup(state, connection) {
278098
278129
  const color = shouldUseCliColor();
278099
278130
  const auth = renderCliAuthSummary(connection);
278131
+ const route = connection.authenticated && connection.appUrl ? connection.appUrl.replace(/^https?:\/\//, "") : connection.appUrl ?? state.appUrl ?? "run /login";
278132
+ const commandLines = PERCH_SPLASH_COMMANDS.map(
278133
+ ([command, description]) => ` ${paint(command.padEnd(13), "orange", color)}${paint(description, "muted", color)}`
278134
+ );
278100
278135
  return [
278101
- `${paint(" .----.", "orange", color)}`,
278102
- `${paint(" | .-. |--", "orange", color)}`,
278103
- `${paint(" | '-' |", "orange", color)}`,
278104
- `${paint(" | .--'", "orange", color)} ${paint("Perch", "orange", color)} ${paint("|", "muted", color)} ${paint("Terminal", "cream", color)}`,
278105
- `${paint(" | |", "orange", color)} ${paint(CLI_PACKAGE_VERSION, "muted", color)}`,
278106
- ` ${[auth, state.personaId, state.chatMode, state.permissionMode].join(" \xB7 ")}`,
278107
- ` ${[connection.appUrl ?? state.appUrl ?? "run /login", shortCwd(state.cwd)].join(" \xB7 ")}`,
278136
+ `${paint("perch \xB7 field terminal", "muted", color)}${" ".repeat(24)}${paint(`v${CLI_PACKAGE_VERSION}`, "muted", color)}`,
278137
+ "",
278138
+ ...PERCH_SPLASH_SCENE.map((line) => paint(line, "orange", color)),
278139
+ "",
278140
+ ` ${paint("perched", "orange", color)} ${paint("in", "muted", color)} ${paint(shortCwd(state.cwd), "cream", color)}`,
278141
+ ` ${paint([auth, state.personaId, state.chatMode, state.permissionMode].join(" \xB7 "), "muted", color)}`,
278142
+ "",
278143
+ ...commandLines,
278144
+ "",
278145
+ ` ${paint(route, "muted", color)}`,
278108
278146
  ""
278109
278147
  ].join("\n");
278110
278148
  }
@@ -278117,6 +278155,14 @@ function writeModeLine(writer, key, value) {
278117
278155
  writer.stdout(`${paint("mode".padEnd(7), "muted", color)} ${key} \u2192 ${value}
278118
278156
  `);
278119
278157
  }
278158
+ function inkSpinnerFrame(frame) {
278159
+ return INK_SPINNER_FRAMES[Math.abs(frame) % INK_SPINNER_FRAMES.length] ?? "\xB7";
278160
+ }
278161
+ function renderInkSpeakerLabel(label) {
278162
+ if (!label.trim()) return "";
278163
+ if (label === "tool" || label === "status" || label === "system") return `${label}\xB7`;
278164
+ return `${label}\u203A`;
278165
+ }
278120
278166
  function createInteractiveCliState(options) {
278121
278167
  return {
278122
278168
  cwd: resolveExistingDirectory(options.cwd ?? process.cwd()),
@@ -278460,7 +278506,7 @@ function defaultWriter() {
278460
278506
  stderr: (text) => process.stderr.write(text)
278461
278507
  };
278462
278508
  }
278463
- var execFileAsync3, DEFAULT_CLI_LOGIN_APP_URL, CLI_PACKAGE_VERSION, ANSI2, HELP_TEXT, INTERACTIVE_HELP_TEXT, INK_LABEL_WIDTH, PERCH_CLI_MARK;
278509
+ var execFileAsync3, DEFAULT_CLI_LOGIN_APP_URL, CLI_PACKAGE_VERSION, ANSI2, HELP_TEXT, INTERACTIVE_HELP_TEXT, INK_LABEL_WIDTH, INK_ROW_LIMIT, INK_DIVIDER, INK_SPINNER_FRAMES, PERCH_SPLASH_WIDTH, PERCH_SPLASH_SCENE, PERCH_SPLASH_COMMANDS;
278464
278510
  var init_perch_cli = __esm({
278465
278511
  "scripts/perch-cli.ts"() {
278466
278512
  "use strict";
@@ -278522,13 +278568,33 @@ Model connection:
278522
278568
  /logout Clear saved CLI auth.
278523
278569
  /exit Leave Perch CLI.
278524
278570
  `;
278525
- INK_LABEL_WIDTH = 10;
278526
- PERCH_CLI_MARK = [
278527
- " .----.",
278528
- " | .-. |--",
278529
- " | '-' |",
278530
- " | .--'",
278531
- " | |"
278571
+ INK_LABEL_WIDTH = 12;
278572
+ INK_ROW_LIMIT = 100;
278573
+ INK_DIVIDER = "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500";
278574
+ INK_SPINNER_FRAMES = process.platform === "darwin" ? ["\xB7", "\u2722", "\u2733", "\u2736", "\u273B", "\u273D", "\u273B", "\u2736", "\u2733", "\u2722"] : ["\xB7", "\u2722", "*", "\u2736", "\u273B", "\u273D", "\u273B", "\u2736", "*", "\u2722"];
278575
+ PERCH_SPLASH_WIDTH = 76;
278576
+ PERCH_SPLASH_SCENE = [
278577
+ " \xB7 \xB7 ",
278578
+ " \xB7 ",
278579
+ " \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 ",
278580
+ " \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \xB7 ",
278581
+ " \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 ",
278582
+ " \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 ",
278583
+ " \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \xB7 ",
278584
+ " \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 ",
278585
+ " \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 ",
278586
+ " \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \xB7 ",
278587
+ " \u2588\u2588\u2588\u2588 ",
278588
+ " \u2588\u2588\u2588\u2588 <( o)> ",
278589
+ " \u2588\u2588\u2588\u2588 /|\\ ",
278590
+ " \u2588\u2588\u2588\u2588 / \\ ",
278591
+ " \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2588\u2588\u2588\u2588\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501 "
278592
+ ];
278593
+ PERCH_SPLASH_COMMANDS = [
278594
+ ["/status", "show auth, route, tools, and thread"],
278595
+ ["/persona", "swap saffron or quill"],
278596
+ ["/permission", "change autonomy for the next turns"],
278597
+ ["/login", "connect your Perch account"]
278532
278598
  ];
278533
278599
  if (!process.env.PERCH_CLI_BUNDLE_ENTRY && process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
278534
278600
  runPerchCli(process.argv.slice(2)).then((code) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "perchai-cli",
3
- "version": "2.4.5",
3
+ "version": "2.4.6",
4
4
  "description": "Perch AI command-line interface",
5
5
  "bin": {
6
6
  "perch": "bin/perch"