perchai-cli 2.4.4 → 2.4.5

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 +131 -35
  2. package/package.json +1 -1
package/dist/perch.mjs CHANGED
@@ -222653,14 +222653,15 @@ async function connectCliModelProxy(input = {}) {
222653
222653
  const usableStoredSession = isStoredCliAuthSessionUsable(storedSession) ? storedSession : null;
222654
222654
  const appUrl = resolveCliAppUrl(input.appUrl, usableStoredSession?.appUrl ?? null);
222655
222655
  if (!appUrl) return noCliModelConnection();
222656
+ if (!usableStoredSession?.accessToken) return noCliModelConnection(appUrl);
222656
222657
  const fetchImpl = input.fetchImpl ?? globalThis.fetch;
222657
- if (typeof fetchImpl !== "function") return noCliModelConnection();
222658
+ if (typeof fetchImpl !== "function") return noCliModelConnection(appUrl);
222658
222659
  const selection = await fetchPublicModelDefaultSelection(
222659
222660
  appUrl,
222660
222661
  fetchImpl,
222661
222662
  usableStoredSession?.accessToken ?? null
222662
222663
  );
222663
- if (!selection) return noCliModelConnection();
222664
+ if (!selection) return noCliModelConnection(appUrl);
222664
222665
  const priorProxy = process.env[MODEL_PROXY_ENV];
222665
222666
  const priorToken = process.env[MODEL_PROXY_TOKEN_ENV];
222666
222667
  process.env[MODEL_PROXY_ENV] = appUrl;
@@ -222726,9 +222727,9 @@ async function fetchPublicModelDefaultSelection(appUrl, fetchImpl, accessToken)
222726
222727
  clearTimeout(timeout);
222727
222728
  }
222728
222729
  }
222729
- function noCliModelConnection() {
222730
+ function noCliModelConnection(appUrl = null) {
222730
222731
  return {
222731
- appUrl: null,
222732
+ appUrl,
222732
222733
  authenticated: false,
222733
222734
  userId: null,
222734
222735
  email: null,
@@ -277559,7 +277560,8 @@ async function runReadlineInteractivePerchCli(writer, deps, options) {
277559
277560
  input: prompt,
277560
277561
  state,
277561
277562
  writer,
277562
- reconnect
277563
+ reconnect,
277564
+ getConnection: () => connection
277563
277565
  });
277564
277566
  if (commandResult === "exit") break;
277565
277567
  } catch (error) {
@@ -277660,7 +277662,11 @@ async function runInkInteractivePerchCli(writer, deps, options) {
277660
277662
  const commandWriter = {
277661
277663
  stdout: (text) => {
277662
277664
  const clean = text.trim();
277663
- if (clean) addItem({ label: "mode", text: clean, tone: "muted" });
277665
+ if (clean) addItem({
277666
+ label: prompt === "/status" ? "status" : "system",
277667
+ text: clean,
277668
+ tone: "muted"
277669
+ });
277664
277670
  },
277665
277671
  stderr: (text) => {
277666
277672
  const clean = text.trim();
@@ -277672,7 +277678,8 @@ async function runInkInteractivePerchCli(writer, deps, options) {
277672
277678
  input: prompt,
277673
277679
  state,
277674
277680
  writer: commandWriter,
277675
- reconnect
277681
+ reconnect,
277682
+ getConnection: () => connection
277676
277683
  });
277677
277684
  refresh((value) => value + 1);
277678
277685
  if (result2 === "exit") {
@@ -277689,6 +277696,14 @@ async function runInkInteractivePerchCli(writer, deps, options) {
277689
277696
  setLiveText("");
277690
277697
  const toolNamesById = /* @__PURE__ */ new Map();
277691
277698
  try {
277699
+ if (!isCliModelConnectionReady(connection)) {
277700
+ addItem({
277701
+ label: "need",
277702
+ text: "Sign in with /login before chatting. Hosted model calls require an authenticated Perch session.",
277703
+ tone: "danger"
277704
+ });
277705
+ return;
277706
+ }
277692
277707
  const result2 = await runTurn({
277693
277708
  prompt,
277694
277709
  cwd: state.cwd,
@@ -277803,47 +277818,104 @@ async function runInkInteractivePerchCli(writer, deps, options) {
277803
277818
  }
277804
277819
  if (input && !key.escape) setDraft((value) => value + input);
277805
277820
  });
277806
- const pulseGlyph = working ? "P".slice(0, 1) : "P";
277807
277821
  const pulseColor = pulse % 2 === 0 ? "#c45000" : "#8e857d";
277808
- const auth = connection.authenticated ? `signed in${connection.email ? ` as ${connection.email}` : ""}` : "public/anonymous";
277822
+ const auth = renderCliAuthSummary(connection);
277823
+ const meta = `${state.personaId} \xB7 ${state.chatMode} \xB7 ${state.permissionMode}`;
277824
+ const route = connection.authenticated && connection.appUrl ? connection.appUrl.replace(/^https?:\/\//, "") : "run /login";
277825
+ const renderTranscriptItem = (item, index) => {
277826
+ const lines = item.text.split(/\r?\n/);
277827
+ const previous = items[index - 1];
277828
+ const separateFromUser = previous?.label === "you" && item.label !== "you";
277829
+ return React11.createElement(
277830
+ Ink2.Box,
277831
+ { key: item.id, flexDirection: "column", marginTop: separateFromUser ? 1 : 0 },
277832
+ separateFromUser ? React11.createElement(
277833
+ Ink2.Box,
277834
+ null,
277835
+ React11.createElement(Ink2.Box, { width: INK_LABEL_WIDTH, flexShrink: 0 }),
277836
+ React11.createElement(Ink2.Text, { color: "#2a211c" }, "------------------------------")
277837
+ ) : 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
+ )
277859
+ ))
277860
+ );
277861
+ };
277809
277862
  return React11.createElement(
277810
277863
  Ink2.Box,
277811
277864
  { flexDirection: "column", width: "100%" },
277812
277865
  React11.createElement(
277813
277866
  Ink2.Box,
277814
- { flexDirection: "column", alignItems: "center", marginBottom: 1 },
277815
- React11.createElement(Ink2.Text, { color: "#c45000", bold: true }, "P"),
277816
- React11.createElement(Ink2.Text, { bold: true }, "Perch | Terminal"),
277867
+ { flexDirection: "column", alignItems: "center", marginBottom: 1, paddingY: 1 },
277868
+ ...PERCH_CLI_MARK.map(
277869
+ (line, index) => React11.createElement(
277870
+ Ink2.Text,
277871
+ { key: `mark-${index}`, color: index === 1 && working ? pulseColor : "#c45000", bold: true },
277872
+ line
277873
+ )
277874
+ ),
277817
277875
  React11.createElement(
277818
- Ink2.Text,
277819
- { color: "#8e857d" },
277820
- `${CLI_PACKAGE_VERSION} \xB7 ${auth} \xB7 ${state.personaId} \xB7 ${state.chatMode} \xB7 ${state.permissionMode} \xB7 ${shortCwd(state.cwd)}`
277821
- )
277822
- ),
277823
- ...items.map(
277824
- (item) => React11.createElement(
277825
277876
  Ink2.Box,
277826
- { key: item.id },
277827
- React11.createElement(Ink2.Text, { color: colorForInkTone(item.tone), bold: item.tone === "accent" }, item.label.padEnd(7)),
277828
- React11.createElement(Ink2.Text, { color: bodyColorForInkTone(item.tone) }, ` ${item.text}`)
277877
+ { 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")
277881
+ ),
277882
+ React11.createElement(Ink2.Text, { color: "#8e857d" }, CLI_PACKAGE_VERSION),
277883
+ React11.createElement(
277884
+ Ink2.Text,
277885
+ { color: "#8e857d", wrap: "truncate-middle" },
277886
+ `${auth} \xB7 ${meta}`
277887
+ ),
277888
+ React11.createElement(
277889
+ Ink2.Text,
277890
+ { color: "#8e857d", wrap: "truncate-middle" },
277891
+ `${route} \xB7 ${shortCwd(state.cwd)}`
277829
277892
  )
277830
277893
  ),
277894
+ ...items.map(renderTranscriptItem),
277831
277895
  liveText ? React11.createElement(
277832
277896
  Ink2.Box,
277833
277897
  { key: "live-text" },
277834
- React11.createElement(Ink2.Text, { color: "#c45000" }, state.personaId.padEnd(7)),
277898
+ React11.createElement(
277899
+ Ink2.Box,
277900
+ { width: INK_LABEL_WIDTH, flexShrink: 0 },
277901
+ React11.createElement(Ink2.Text, { color: "#c45000" }, state.personaId)
277902
+ ),
277835
277903
  React11.createElement(Ink2.Text, null, ` ${liveText}`)
277836
277904
  ) : null,
277837
277905
  working ? React11.createElement(
277838
277906
  Ink2.Box,
277839
277907
  { key: "working", marginTop: items.length || liveText ? 1 : 0 },
277840
- React11.createElement(Ink2.Text, { color: pulseColor, bold: true }, pulseGlyph.padEnd(7)),
277908
+ React11.createElement(
277909
+ Ink2.Box,
277910
+ { width: INK_LABEL_WIDTH, flexShrink: 0 },
277911
+ React11.createElement(Ink2.Text, { color: pulseColor, bold: true }, "perch")
277912
+ ),
277841
277913
  React11.createElement(Ink2.Text, { color: "#8e857d" }, ` ${workingText}\u2026`)
277842
277914
  ) : null,
277843
277915
  React11.createElement(
277844
277916
  Ink2.Box,
277845
277917
  { key: "prompt", marginTop: 1 },
277846
- React11.createElement(Ink2.Text, { color: "#c45000", bold: true }, `${state.personaId}\u203A `),
277918
+ React11.createElement(Ink2.Text, { color: "#c45000", bold: true }, "you\u203A "),
277847
277919
  React11.createElement(Ink2.Text, null, draft),
277848
277920
  React11.createElement(Ink2.Text, { backgroundColor: "#c45000", color: "#100d0b" }, " ")
277849
277921
  )
@@ -277872,7 +277944,7 @@ async function runInteractiveSlashCommand(input) {
277872
277944
  return "continue";
277873
277945
  case "status": {
277874
277946
  const session = await readStoredCliAuthSession();
277875
- input.writer.stdout(renderInteractiveStatus(input.state, null, session));
277947
+ input.writer.stdout(renderInteractiveStatus(input.state, input.getConnection?.() ?? null, session));
277876
277948
  return "continue";
277877
277949
  }
277878
277950
  case "cwd":
@@ -278006,32 +278078,39 @@ function parseInteractiveSlashCommand(input) {
278006
278078
  }
278007
278079
  }
278008
278080
  function renderInteractiveStatus(state, connection, session) {
278009
- 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";
278081
+ const storedAuth = session === void 0 ? renderCliAuthSummary(connection) : isStoredCliAuthSessionUsable(session) ? `signed in${session.email ? ` as ${session.email}` : ""}` : "not signed in";
278082
+ const modelRoute = isCliModelConnectionReady(connection) ? `connected \xB7 ${connection.appUrl ?? "(unknown)"}` : "locked \xB7 run /login";
278010
278083
  const color = shouldUseCliColor();
278011
278084
  const lines = [
278012
278085
  ["cwd", state.cwd],
278086
+ ["auth", storedAuth],
278087
+ ["model-route", modelRoute],
278013
278088
  ["permission", state.permissionMode],
278014
278089
  ["mode", state.chatMode],
278015
278090
  ["persona", state.personaId],
278016
278091
  ["thread", state.threadId],
278017
278092
  ["local-tools", state.cliLocalTools ? "on" : "off"],
278018
- ["app-url", state.appUrl ?? connection?.appUrl ?? "(none)"],
278019
- ["auth", auth]
278093
+ ["app-url", state.appUrl ?? connection?.appUrl ?? "(none)"]
278020
278094
  ];
278021
278095
  return lines.map(([key, value]) => `${paint(key.padEnd(11), "muted", color)} ${value}`).join("\n") + "\n";
278022
278096
  }
278023
278097
  function renderInteractiveStartup(state, connection) {
278024
278098
  const color = shouldUseCliColor();
278025
- const auth = connection.authenticated ? `signed in${connection.email ? ` as ${connection.email}` : ""}` : "public/anonymous";
278099
+ const auth = renderCliAuthSummary(connection);
278026
278100
  return [
278027
- `${paint("P", "orange", color)} ${paint("Perch CLI", "cream", color)} ${paint(CLI_PACKAGE_VERSION, "muted", color)}`,
278028
- ` ${[auth, state.personaId, state.chatMode, state.permissionMode, shortCwd(state.cwd)].join(" \xB7 ")}`,
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 ")}`,
278029
278108
  ""
278030
278109
  ].join("\n");
278031
278110
  }
278032
- function renderInteractivePrompt(state) {
278111
+ function renderInteractivePrompt(_state) {
278033
278112
  const color = shouldUseCliColor();
278034
- return `${paint(state.personaId, "orange", color)}${paint("\u203A", "orange", color)} `;
278113
+ return `${paint("you", "orange", color)}${paint("\u203A", "orange", color)} `;
278035
278114
  }
278036
278115
  function writeModeLine(writer, key, value) {
278037
278116
  const color = shouldUseCliColor();
@@ -278054,6 +278133,15 @@ function createInteractiveCliState(options) {
278054
278133
  function humanizeCliToolName(name) {
278055
278134
  return name.replace(/^mcp__/, "").replace(/_/g, " ");
278056
278135
  }
278136
+ function isCliModelConnectionReady(connection) {
278137
+ return Boolean(connection?.authenticated && connection.founderModelSelection);
278138
+ }
278139
+ function renderCliAuthSummary(connection) {
278140
+ if (isCliModelConnectionReady(connection)) {
278141
+ return `signed in${connection.email ? ` as ${connection.email}` : ""}`;
278142
+ }
278143
+ return "not signed in";
278144
+ }
278057
278145
  function errorMessage(error) {
278058
278146
  return error instanceof Error ? error.message : String(error);
278059
278147
  }
@@ -278372,7 +278460,7 @@ function defaultWriter() {
278372
278460
  stderr: (text) => process.stderr.write(text)
278373
278461
  };
278374
278462
  }
278375
- var execFileAsync3, DEFAULT_CLI_LOGIN_APP_URL, CLI_PACKAGE_VERSION, ANSI2, HELP_TEXT, INTERACTIVE_HELP_TEXT;
278463
+ var execFileAsync3, DEFAULT_CLI_LOGIN_APP_URL, CLI_PACKAGE_VERSION, ANSI2, HELP_TEXT, INTERACTIVE_HELP_TEXT, INK_LABEL_WIDTH, PERCH_CLI_MARK;
278376
278464
  var init_perch_cli = __esm({
278377
278465
  "scripts/perch-cli.ts"() {
278378
278466
  "use strict";
@@ -278434,6 +278522,14 @@ Model connection:
278434
278522
  /logout Clear saved CLI auth.
278435
278523
  /exit Leave Perch CLI.
278436
278524
  `;
278525
+ INK_LABEL_WIDTH = 10;
278526
+ PERCH_CLI_MARK = [
278527
+ " .----.",
278528
+ " | .-. |--",
278529
+ " | '-' |",
278530
+ " | .--'",
278531
+ " | |"
278532
+ ];
278437
278533
  if (!process.env.PERCH_CLI_BUNDLE_ENTRY && process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
278438
278534
  runPerchCli(process.argv.slice(2)).then((code) => {
278439
278535
  process.exitCode = code;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "perchai-cli",
3
- "version": "2.4.4",
3
+ "version": "2.4.5",
4
4
  "description": "Perch AI command-line interface",
5
5
  "bin": {
6
6
  "perch": "bin/perch"