@robinpath/cli 1.78.0 → 1.80.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.
Files changed (2) hide show
  1. package/dist/cli.mjs +228 -80
  2. package/package.json +1 -1
package/dist/cli.mjs CHANGED
@@ -18598,7 +18598,7 @@ function getNativeModules() {
18598
18598
  import { join as join3, basename as basename2 } from "node:path";
18599
18599
  import { homedir as homedir2, platform as platform2 } from "node:os";
18600
18600
  import { existsSync as existsSync2 } from "node:fs";
18601
- var CLI_VERSION = true ? "1.78.0" : "1.78.0";
18601
+ var CLI_VERSION = true ? "1.80.0" : "1.80.0";
18602
18602
  var FLAG_QUIET = false;
18603
18603
  var FLAG_VERBOSE = false;
18604
18604
  var FLAG_AUTO_ACCEPT = false;
@@ -21904,7 +21904,8 @@ async function fetchBrainStream(prompt, { onToken, conversationHistory, provider
21904
21904
  });
21905
21905
  if (!response.ok) {
21906
21906
  logVerbose("Brain stream returned", response.status);
21907
- return null;
21907
+ const errorHint = response.status === 401 ? "Invalid API key." : response.status === 429 ? "Rate limited. Wait a moment and try again." : response.status >= 500 ? "Brain server error. Try again." : `Brain returned HTTP ${response.status}.`;
21908
+ return { code: "", sources: [], context: {}, validation: null, usage: null, error: errorHint };
21908
21909
  }
21909
21910
  let fullText = "";
21910
21911
  let metadata = null;
@@ -21964,8 +21965,19 @@ async function fetchBrainStream(prompt, { onToken, conversationHistory, provider
21964
21965
  usage: doneData?.usage || null
21965
21966
  };
21966
21967
  } catch (err) {
21967
- logVerbose("Brain stream unreachable:", err.message);
21968
- return null;
21968
+ const msg = err.message || "";
21969
+ logVerbose("Brain stream unreachable:", msg);
21970
+ let errorHint;
21971
+ if (msg.includes("fetch failed") || msg.includes("ENOTFOUND") || msg.includes("ECONNREFUSED") || msg.includes("NetworkError") || msg.includes("getaddrinfo")) {
21972
+ errorHint = "No internet connection. Check your network and try again.";
21973
+ } else if (msg.includes("abort") || msg.includes("timeout") || msg.includes("TimeoutError")) {
21974
+ errorHint = "Request timed out. The server might be slow \u2014 try again.";
21975
+ } else if (msg.includes("CERT") || msg.includes("SSL") || msg.includes("certificate")) {
21976
+ errorHint = "SSL/certificate error. Check your network or proxy settings.";
21977
+ } else {
21978
+ errorHint = `Connection failed: ${msg.slice(0, 100)}`;
21979
+ }
21980
+ return { code: "", sources: [], context: {}, validation: null, usage: null, error: errorHint };
21969
21981
  }
21970
21982
  }
21971
21983
  async function resolveBrainModules(prompt) {
@@ -23941,9 +23953,20 @@ ${readFileSync9(rpJson, "utf-8")}
23941
23953
  if (pending.length > 0 && !insideMemory && !insideCmd) {
23942
23954
  process.stdout.write(pending);
23943
23955
  }
23944
- if (!brainResult || !brainResult.code) {
23956
+ if (!brainResult) {
23957
+ spinner.stop();
23958
+ log(color.red("\n No internet connection. Check your network and try again."));
23959
+ break;
23960
+ }
23961
+ if (brainResult.error) {
23962
+ spinner.stop();
23963
+ log(color.red(`
23964
+ ${brainResult.error}`));
23965
+ break;
23966
+ }
23967
+ if (!brainResult.code) {
23945
23968
  spinner.stop();
23946
- log(color.red("\n Brain returned no response. Check your connection or API key."));
23969
+ log(color.red("\n No response from AI. Try again."));
23947
23970
  break;
23948
23971
  }
23949
23972
  if (brainResult.usage) {
@@ -24132,72 +24155,145 @@ ${resultSummary}`
24132
24155
  }
24133
24156
 
24134
24157
  // src/ink-repl.tsx
24135
- import { useState, useEffect } from "react";
24158
+ import { useState, useCallback, useEffect, useMemo } from "react";
24136
24159
  import { render, Box, Text, Static, useInput, useApp } from "ink";
24137
24160
  import InkSpinner from "ink-spinner";
24138
24161
  import { platform as platform7 } from "node:os";
24139
24162
  import { randomUUID as randomUUID4 } from "node:crypto";
24140
24163
  import { jsx, jsxs } from "react/jsx-runtime";
24141
24164
  var nextId = 0;
24142
- function ChatApp({ onMessage }) {
24143
- const [input, setInput] = useState("");
24144
- const [messages, setMessages] = useState([]);
24145
- const [streaming, setStreaming] = useState("");
24146
- const [loading, setLoading] = useState(false);
24165
+ var COMMANDS = {
24166
+ "/model": "Switch AI model",
24167
+ "/auto": "Toggle auto-accept",
24168
+ "/clear": "Clear conversation",
24169
+ "/save": "Save session",
24170
+ "/sessions": "List sessions",
24171
+ "/memory": "Show memory",
24172
+ "/remember": "Save a fact",
24173
+ "/usage": "Token usage & cost",
24174
+ "/shell": "Switch shell",
24175
+ "/help": "Show commands"
24176
+ };
24177
+ function InputArea({ onSubmit, placeholder }) {
24178
+ const [value, setValue] = useState("");
24179
+ const [showHints, setShowHints] = useState(false);
24147
24180
  const { exit } = useApp();
24148
- useEffect(() => {
24149
- global.__rpUI = {
24150
- setStreaming,
24151
- setLoading,
24152
- addMessage: (text) => setMessages((prev) => [...prev, { id: ++nextId, text }])
24153
- };
24154
- }, []);
24155
- useInput((character, key) => {
24156
- if (loading) return;
24181
+ const matchingCommands = useMemo(() => {
24182
+ if (!value.startsWith("/")) return [];
24183
+ if (value === "/") return Object.entries(COMMANDS);
24184
+ return Object.entries(COMMANDS).filter(([cmd]) => cmd.startsWith(value));
24185
+ }, [value]);
24186
+ useInput((ch, key) => {
24157
24187
  if (key.return) {
24158
- if (!input.trim()) return;
24159
- if (input.endsWith("\\")) {
24160
- setInput((prev) => prev.slice(0, -1) + "\n");
24188
+ if (value.endsWith("\\")) {
24189
+ setValue((p) => p.slice(0, -1) + "\n");
24161
24190
  return;
24162
24191
  }
24163
- const text = input.trim();
24164
- setInput("");
24165
- if (text === "exit" || text === "quit") {
24166
- exit();
24167
- return;
24192
+ const text = value.trim();
24193
+ if (text) {
24194
+ onSubmit(text);
24195
+ setValue("");
24196
+ setShowHints(false);
24168
24197
  }
24169
- setMessages((prev) => [...prev, { id: ++nextId, text: `\u276F ${text}` }]);
24170
- setLoading(true);
24171
- setStreaming("");
24172
- onMessage(text).then((response) => {
24173
- if (response) {
24174
- setMessages((prev) => [...prev, { id: ++nextId, text: response }]);
24175
- }
24176
- setLoading(false);
24177
- setStreaming("");
24178
- }).catch((err) => {
24179
- setMessages((prev) => [...prev, { id: ++nextId, text: `Error: ${err.message}` }]);
24180
- setLoading(false);
24181
- setStreaming("");
24182
- });
24183
24198
  return;
24184
24199
  }
24185
- if (input.length > 0 && (key.backspace || key.delete)) {
24186
- setInput((prev) => prev.slice(0, -1));
24200
+ if (ch === "\n") {
24201
+ setValue((p) => p + "\n");
24187
24202
  return;
24188
24203
  }
24189
24204
  if (key.escape) {
24190
- setInput("");
24205
+ setValue("");
24206
+ setShowHints(false);
24191
24207
  return;
24192
24208
  }
24193
- if (key.tab) return;
24194
- if (character && !key.ctrl && !key.meta) {
24195
- setInput((prev) => prev + character);
24209
+ if (ch === "") {
24210
+ if (!value) exit();
24211
+ else {
24212
+ setValue("");
24213
+ setShowHints(false);
24214
+ }
24215
+ return;
24216
+ }
24217
+ if (key.backspace || key.delete) {
24218
+ setValue((p) => p.slice(0, -1));
24219
+ return;
24196
24220
  }
24221
+ if (key.tab) {
24222
+ if (matchingCommands.length === 1) {
24223
+ setValue(matchingCommands[0][0] + " ");
24224
+ setShowHints(false);
24225
+ }
24226
+ return;
24227
+ }
24228
+ if (ch === "") {
24229
+ setValue("");
24230
+ return;
24231
+ }
24232
+ if (ch === "") {
24233
+ setValue((p) => p.replace(/\S+\s*$/, ""));
24234
+ return;
24235
+ }
24236
+ if (ch && !key.ctrl && !key.meta) setValue((p) => p + ch);
24197
24237
  });
24198
- const lines = input.split("\n");
24238
+ useEffect(() => {
24239
+ setShowHints(value.startsWith("/") && matchingCommands.length > 0);
24240
+ }, [value, matchingCommands.length]);
24241
+ const lines = value.split("\n");
24242
+ const empty = value === "";
24243
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
24244
+ showHints && /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginX: 2, marginBottom: 1, children: matchingCommands.slice(0, 6).map(([cmd, desc]) => /* @__PURE__ */ jsxs(Text, { children: [
24245
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: cmd.padEnd(12) }),
24246
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: desc })
24247
+ ] }, cmd)) }),
24248
+ /* @__PURE__ */ jsx(Box, { borderStyle: "round", borderColor: "cyan", flexDirection: "column", paddingX: 1, marginX: 1, children: empty ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: placeholder }) : lines.map((line, i) => /* @__PURE__ */ jsxs(Text, { children: [
24249
+ line,
24250
+ i === lines.length - 1 ? /* @__PURE__ */ jsx(Text, { color: "cyan", children: "\u2588" }) : null
24251
+ ] }, i)) }),
24252
+ /* @__PURE__ */ jsx(Box, { marginX: 2, children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
24253
+ /* @__PURE__ */ jsx(Text, { color: "gray", children: "enter" }),
24254
+ " send ",
24255
+ /* @__PURE__ */ jsx(Text, { color: "gray", children: "\\" }),
24256
+ " newline ",
24257
+ /* @__PURE__ */ jsx(Text, { color: "gray", children: "esc" }),
24258
+ " clear ",
24259
+ /* @__PURE__ */ jsx(Text, { color: "gray", children: "/" }),
24260
+ " commands ",
24261
+ /* @__PURE__ */ jsx(Text, { color: "gray", children: "tab" }),
24262
+ " complete"
24263
+ ] }) })
24264
+ ] });
24265
+ }
24266
+ function ChatApp({ onMessage, statusText }) {
24267
+ const [messages, setMessages] = useState([]);
24268
+ const [streaming, setStreaming] = useState("");
24269
+ const [loading, setLoading] = useState(false);
24270
+ useEffect(() => {
24271
+ global.__rpUI = {
24272
+ setStreaming,
24273
+ setLoading,
24274
+ addMessage: (text, dim) => setMessages((p) => [...p, { id: ++nextId, text, dim }])
24275
+ };
24276
+ }, []);
24277
+ const handleSubmit = useCallback(async (text) => {
24278
+ if (text === "exit" || text === "quit") {
24279
+ global.__rpExit?.();
24280
+ return;
24281
+ }
24282
+ setMessages((p) => [...p, { id: ++nextId, text: `\u276F ${text}` }]);
24283
+ setLoading(true);
24284
+ setStreaming("");
24285
+ try {
24286
+ const response = await onMessage(text);
24287
+ if (response) setMessages((p) => [...p, { id: ++nextId, text: response }]);
24288
+ } catch (err) {
24289
+ setMessages((p) => [...p, { id: ++nextId, text: `Error: ${err.message}`, dim: true }]);
24290
+ }
24291
+ setLoading(false);
24292
+ setStreaming("");
24293
+ }, [onMessage]);
24294
+ const isFirst = messages.length === 0;
24199
24295
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", padding: 1, children: [
24200
- /* @__PURE__ */ jsxs(Text, { children: [
24296
+ /* @__PURE__ */ jsx(Box, { marginBottom: 1, children: /* @__PURE__ */ jsxs(Text, { children: [
24201
24297
  /* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "\u25C6" }),
24202
24298
  " ",
24203
24299
  /* @__PURE__ */ jsx(Text, { bold: true, children: "RobinPath" }),
@@ -24206,21 +24302,22 @@ function ChatApp({ onMessage }) {
24206
24302
  "v",
24207
24303
  CLI_VERSION
24208
24304
  ] })
24209
- ] }),
24210
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: " " }),
24211
- /* @__PURE__ */ jsx(Static, { items: messages, children: (msg) => /* @__PURE__ */ jsx(Text, { wrap: "wrap", children: msg.text }, msg.id) }),
24212
- loading && streaming ? /* @__PURE__ */ jsx(Text, { wrap: "wrap", children: streaming }) : null,
24213
- loading && !streaming ? /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
24305
+ ] }) }),
24306
+ /* @__PURE__ */ jsx(Static, { items: messages, children: (msg) => /* @__PURE__ */ jsx(Box, { paddingX: 1, marginBottom: msg.text.startsWith("\u276F") ? 0 : 1, children: msg.dim ? /* @__PURE__ */ jsx(Text, { dimColor: true, wrap: "wrap", children: msg.text }) : /* @__PURE__ */ jsx(Text, { wrap: "wrap", children: msg.text }) }, msg.id) }),
24307
+ loading ? /* @__PURE__ */ jsx(Box, { flexDirection: "column", paddingX: 1, children: streaming ? /* @__PURE__ */ jsxs(Text, { wrap: "wrap", children: [
24308
+ streaming,
24309
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: "\u258D" })
24310
+ ] }) : /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
24214
24311
  /* @__PURE__ */ jsx(InkSpinner, { type: "dots" }),
24215
24312
  " Thinking"
24216
- ] }) : null,
24217
- !loading ? /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsxs(Text, { children: [
24218
- /* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "\u276F " }),
24219
- input === "" ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: messages.length === 0 ? "What do you want to automate?" : "Ask anything..." }) : /* @__PURE__ */ jsxs(Text, { children: [
24220
- input,
24221
- /* @__PURE__ */ jsx(Text, { color: "cyan", children: "\u258E" })
24222
- ] })
24223
- ] }) }) : null
24313
+ ] }) }) : /* @__PURE__ */ jsx(
24314
+ InputArea,
24315
+ {
24316
+ onSubmit: handleSubmit,
24317
+ placeholder: isFirst ? "Anything to automate with RobinPath?" : "Ask anything..."
24318
+ }
24319
+ ),
24320
+ /* @__PURE__ */ jsx(Box, { marginTop: 1, paddingX: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: statusText }) })
24224
24321
  ] });
24225
24322
  }
24226
24323
  async function startInkREPL(initialPrompt, resumeSessionId, opts = {}) {
@@ -24237,6 +24334,7 @@ async function startInkREPL(initialPrompt, resumeSessionId, opts = {}) {
24237
24334
  };
24238
24335
  const apiKey = config.apiKey || null;
24239
24336
  const model = apiKey ? config.model || "anthropic/claude-sonnet-4.6" : "robinpath-default";
24337
+ const modelShort = (m) => m === "robinpath-default" ? "gemini-free" : m.includes("/") ? m.split("/").pop() : m;
24240
24338
  const cliContext = {
24241
24339
  platform: platform7(),
24242
24340
  shell: getShellConfig().name,
@@ -24262,15 +24360,23 @@ async function startInkREPL(initialPrompt, resumeSessionId, opts = {}) {
24262
24360
  if (session.usage) Object.assign(usage, session.usage);
24263
24361
  }
24264
24362
  }
24363
+ function getStatusText() {
24364
+ const m = modelShort(readAiConfig().model || model);
24365
+ const cost = usage.cost > 0 ? ` \xB7 $${usage.cost.toFixed(4)}` : "";
24366
+ const tokens = usage.totalTokens > 0 ? ` \xB7 ${usage.totalTokens.toLocaleString()} tok` : "";
24367
+ return `${m} \xB7 ${getShellConfig().name} \xB7 ${autoAccept ? "auto" : "confirm"}${tokens}${cost}`;
24368
+ }
24265
24369
  async function handleMessage(text) {
24266
24370
  const ui = global.__rpUI;
24267
- if (text === "/" || text === "/help") return "/model /auto /clear /save /usage /memory exit";
24371
+ if (text === "/" || text === "/help") {
24372
+ return Object.entries(COMMANDS).map(([cmd, desc]) => `${cmd.padEnd(12)} ${desc}`).join("\n");
24373
+ }
24268
24374
  if (text === "/clear") {
24269
24375
  conversationMessages.length = 0;
24270
- return "Cleared.";
24376
+ return "Conversation cleared.";
24271
24377
  }
24272
24378
  if (text === "/usage") {
24273
- const c = usage.cost > 0 ? `$${usage.cost.toFixed(4)}` : "$0 (free)";
24379
+ const c = usage.cost > 0 ? `$${usage.cost.toFixed(4)}` : "$0.00 (free)";
24274
24380
  return `${usage.totalTokens.toLocaleString()} tokens \xB7 ${usage.requests} requests \xB7 ${c}`;
24275
24381
  }
24276
24382
  if (text === "/auto") {
@@ -24280,7 +24386,11 @@ async function startInkREPL(initialPrompt, resumeSessionId, opts = {}) {
24280
24386
  if (text === "/model") {
24281
24387
  const hasKey = !!readAiConfig().apiKey;
24282
24388
  const models = hasKey ? AI_MODELS : AI_MODELS.filter((m) => !m.requiresKey);
24283
- return models.map((m, i) => `${i + 1}. ${m.name} \u2014 ${m.desc}`).join("\n");
24389
+ const cur = readAiConfig().model || model;
24390
+ return models.map((m, i) => {
24391
+ const mark = m.id === cur ? " \u2713" : "";
24392
+ return `${String(i + 1).padStart(2)}. ${m.name.padEnd(22)} ${m.desc}${mark}`;
24393
+ }).join("\n") + "\n\nType /model <number> to switch.";
24284
24394
  }
24285
24395
  if (text.match(/^\/model \d+$/)) {
24286
24396
  const hasKey = !!readAiConfig().apiKey;
@@ -24289,20 +24399,44 @@ async function startInkREPL(initialPrompt, resumeSessionId, opts = {}) {
24289
24399
  if (idx >= 0 && idx < models.length) {
24290
24400
  config.model = models[idx].id;
24291
24401
  writeAiConfig(config);
24292
- return `Model: ${models[idx].id}`;
24402
+ return `Model changed to ${models[idx].name}`;
24293
24403
  }
24294
24404
  return "Invalid number.";
24295
24405
  }
24296
24406
  if (text === "/memory") {
24297
24407
  const m = loadMemory();
24298
- return m.facts.length ? m.facts.map((f, i) => `${i + 1}. ${f}`).join("\n") : "No memories.";
24408
+ return m.facts.length ? m.facts.map((f, i) => `${i + 1}. ${f}`).join("\n") : "No memories saved.";
24409
+ }
24410
+ if (text.startsWith("/remember ")) {
24411
+ addMemoryFact(text.slice(10).trim());
24412
+ return "Remembered.";
24299
24413
  }
24300
- if (text.startsWith("/save")) {
24414
+ if (text.startsWith("/forget ")) {
24415
+ removeMemoryFact(parseInt(text.slice(8).trim(), 10) - 1);
24416
+ return "Forgotten.";
24417
+ }
24418
+ if (text === "/save" || text.startsWith("/save ")) {
24301
24419
  if (text.length > 5) sessionName = text.slice(5).trim();
24302
24420
  saveSession(sessionId, sessionName, conversationMessages, usage);
24303
- return `Saved: ${sessionName}`;
24421
+ return `Session saved: ${sessionName}`;
24422
+ }
24423
+ if (text === "/sessions") {
24424
+ const sessions = listSessions();
24425
+ if (sessions.length === 0) return "No saved sessions.";
24426
+ return sessions.map((s) => `${s.id} ${s.name} (${s.messages} msgs)`).join("\n");
24427
+ }
24428
+ if (text === "/shell") {
24429
+ return getAvailableShells().map((s) => {
24430
+ const mark = s.current ? " \u2713" : s.available ? "" : " (not found)";
24431
+ return `${s.name}${mark}`;
24432
+ }).join("\n") + "\n\nType /shell <name> to switch.";
24304
24433
  }
24305
- if (text.startsWith("/")) return `Unknown: ${text}. Type / for help.`;
24434
+ if (text.startsWith("/shell ")) {
24435
+ setShellOverride(text.slice(7).trim());
24436
+ cliContext.shell = getShellConfig().name;
24437
+ return `Shell: ${getShellConfig().name}`;
24438
+ }
24439
+ if (text.startsWith("/")) return `Unknown command: ${text}. Type / for help.`;
24306
24440
  const { expanded } = expandFileRefs(text);
24307
24441
  conversationMessages.push({ role: "user", content: expanded });
24308
24442
  await autoCompact(conversationMessages);
@@ -24332,8 +24466,16 @@ async function startInkREPL(initialPrompt, resumeSessionId, opts = {}) {
24332
24466
  cliContext
24333
24467
  }
24334
24468
  );
24335
- if (!result || !result.code) {
24336
- finalResponse = fullText || "No response.";
24469
+ if (!result) {
24470
+ finalResponse = "No internet connection. Check your network and try again.";
24471
+ break;
24472
+ }
24473
+ if (result.error) {
24474
+ finalResponse = result.error;
24475
+ break;
24476
+ }
24477
+ if (!result.code) {
24478
+ finalResponse = fullText || "No response. Try again.";
24337
24479
  break;
24338
24480
  }
24339
24481
  if (result.usage) {
@@ -24355,15 +24497,15 @@ async function startInkREPL(initialPrompt, resumeSessionId, opts = {}) {
24355
24497
  if (cleaned) ui?.addMessage(cleaned);
24356
24498
  for (const cmd of commands) {
24357
24499
  const preview = cmd.split("\n")[0].slice(0, 80);
24358
- ui?.addMessage(`$ ${preview}${cmd.includes("\n") ? " ..." : ""}`);
24500
+ ui?.addMessage(`$ ${preview}${cmd.includes("\n") ? " ..." : ""}`, true);
24359
24501
  const r = await executeShellCommand(cmd);
24360
24502
  if (r.exitCode === 0 && r.stdout?.trim()) {
24361
- ui?.addMessage(r.stdout.trim().split("\n").slice(0, 5).join("\n"));
24503
+ ui?.addMessage(r.stdout.trim().split("\n").slice(0, 5).join("\n"), true);
24362
24504
  } else if (r.exitCode !== 0) {
24363
- ui?.addMessage(`exit ${r.exitCode}: ${(r.stderr || "").slice(0, 100)}`);
24505
+ ui?.addMessage(`exit ${r.exitCode}: ${(r.stderr || "").slice(0, 100)}`, true);
24364
24506
  }
24365
24507
  }
24366
- const summary = commands.map((cmd, i) => `$ ${cmd}
24508
+ const summary = commands.map((cmd) => `$ ${cmd}
24367
24509
  (executed)`).join("\n");
24368
24510
  conversationMessages.push({ role: "user", content: `[Results]
24369
24511
  ${summary}` });
@@ -24373,7 +24515,13 @@ ${summary}` });
24373
24515
  saveSession(sessionId, sessionName, conversationMessages, usage);
24374
24516
  return finalResponse;
24375
24517
  }
24376
- const { waitUntilExit } = render(/* @__PURE__ */ jsx(ChatApp, { onMessage: handleMessage }));
24518
+ const { waitUntilExit } = render(
24519
+ /* @__PURE__ */ jsx(ChatApp, { onMessage: handleMessage, statusText: getStatusText() })
24520
+ );
24521
+ global.__rpExit = () => {
24522
+ if (conversationMessages.length > 1) saveSession(sessionId, sessionName, conversationMessages, usage);
24523
+ process.exit(0);
24524
+ };
24377
24525
  if (initialPrompt) {
24378
24526
  await new Promise((r) => setTimeout(r, 200));
24379
24527
  const ui = global.__rpUI;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@robinpath/cli",
3
- "version": "1.78.0",
3
+ "version": "1.80.0",
4
4
  "description": "AI-powered scripting CLI — automate anything from your terminal",
5
5
  "type": "module",
6
6
  "license": "MIT",