@robinpath/cli 2.9.0 → 3.0.1

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 +65 -10
  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 ? "2.9.0" : "2.9.0";
18601
+ var CLI_VERSION = true ? "3.0.1" : "3.0.1";
18602
18602
  var FLAG_QUIET = false;
18603
18603
  var FLAG_VERBOSE = false;
18604
18604
  var FLAG_AUTO_ACCEPT = false;
@@ -24276,8 +24276,10 @@ var COMMANDS = {
24276
24276
  "/shell": "Switch shell",
24277
24277
  "/help": "All commands"
24278
24278
  };
24279
- function InputArea({ onSubmit, placeholder, statusText }) {
24279
+ function InputArea({ onSubmit, placeholder, statusText, history }) {
24280
24280
  const [value, setValue] = useState("");
24281
+ const [historyIdx, setHistoryIdx] = useState(-1);
24282
+ const [savedInput, setSavedInput] = useState("");
24281
24283
  const { exit } = useApp();
24282
24284
  const matchingCommands = useMemo(() => {
24283
24285
  if (!value.startsWith("/")) return [];
@@ -24347,6 +24349,24 @@ function InputArea({ onSubmit, placeholder, statusText }) {
24347
24349
  }
24348
24350
  return;
24349
24351
  }
24352
+ if (key.upArrow && history && history.length > 0) {
24353
+ if (historyIdx === -1) setSavedInput(value);
24354
+ const newIdx = Math.min(historyIdx + 1, history.length - 1);
24355
+ setHistoryIdx(newIdx);
24356
+ setValue(history[history.length - 1 - newIdx]);
24357
+ return;
24358
+ }
24359
+ if (key.downArrow && historyIdx >= 0) {
24360
+ const newIdx = historyIdx - 1;
24361
+ if (newIdx < 0) {
24362
+ setHistoryIdx(-1);
24363
+ setValue(savedInput);
24364
+ } else {
24365
+ setHistoryIdx(newIdx);
24366
+ setValue(history[history.length - 1 - newIdx]);
24367
+ }
24368
+ return;
24369
+ }
24350
24370
  if (ch === "") {
24351
24371
  setValue("");
24352
24372
  return;
@@ -24355,7 +24375,10 @@ function InputArea({ onSubmit, placeholder, statusText }) {
24355
24375
  setValue((p) => p.replace(/\S+\s*$/, ""));
24356
24376
  return;
24357
24377
  }
24358
- if (ch && !key.ctrl && !key.meta) setValue((p) => p + ch);
24378
+ if (ch && !key.ctrl && !key.meta) {
24379
+ setValue((p) => p + ch);
24380
+ setHistoryIdx(-1);
24381
+ }
24359
24382
  });
24360
24383
  const lines = value.split("\n");
24361
24384
  const empty = value === "";
@@ -24503,6 +24526,13 @@ function ChatApp({ engine }) {
24503
24526
  const [loading, setLoading] = useState(false);
24504
24527
  const [status, setStatus] = useState("");
24505
24528
  const [showModelPicker, setShowModelPicker] = useState(false);
24529
+ const [inputHistory, setInputHistory] = useState([]);
24530
+ const [responseTime, setResponseTime] = useState("");
24531
+ useInput((ch, key) => {
24532
+ if (loading && (key.escape || ch === "")) {
24533
+ engine.cancel();
24534
+ }
24535
+ }, { isActive: loading });
24506
24536
  useEffect(() => {
24507
24537
  engine.ui = {
24508
24538
  setStreaming,
@@ -24510,7 +24540,8 @@ function ChatApp({ engine }) {
24510
24540
  setStatus,
24511
24541
  setShowModelPicker,
24512
24542
  addMessage: (text, dim) => setMessages((p) => [...p, { id: ++nextId, text, dim }]),
24513
- clearMessages: () => setMessages([])
24543
+ clearMessages: () => setMessages([]),
24544
+ setResponseTime
24514
24545
  };
24515
24546
  engine.updateStatus();
24516
24547
  }, []);
@@ -24525,9 +24556,12 @@ function ChatApp({ engine }) {
24525
24556
  engine.updateStatus();
24526
24557
  return;
24527
24558
  }
24559
+ setInputHistory((p) => [...p, text]);
24528
24560
  setMessages((p) => [...p, { id: ++nextId, text: `\u276F ${text}` }]);
24529
24561
  setLoading(true);
24530
24562
  setStreaming("");
24563
+ setResponseTime("");
24564
+ const startTime = Date.now();
24531
24565
  try {
24532
24566
  const response = await engine.handleAIMessage(text);
24533
24567
  if (response) setMessages((p) => [...p, { id: ++nextId, text: response }]);
@@ -24536,6 +24570,9 @@ function ChatApp({ engine }) {
24536
24570
  } finally {
24537
24571
  setLoading(false);
24538
24572
  setStreaming("");
24573
+ const elapsed = Date.now() - startTime;
24574
+ const timeStr = elapsed < 1e3 ? `${elapsed}ms` : elapsed < 6e4 ? `${(elapsed / 1e3).toFixed(1)}s` : `${Math.floor(elapsed / 6e4)}m ${Math.round(elapsed % 6e4 / 1e3)}s`;
24575
+ setResponseTime(timeStr);
24539
24576
  engine.updateStatus();
24540
24577
  }
24541
24578
  }, [engine]);
@@ -24595,9 +24632,10 @@ function ChatApp({ engine }) {
24595
24632
  ] })
24596
24633
  ] })
24597
24634
  ] }) : null,
24598
- messages.map((msg) => /* @__PURE__ */ jsx2(Box2, { paddingX: 1, marginBottom: msg.text.startsWith("\u276F") ? 0 : 1, flexDirection: "column", children: msg.text.startsWith("\u276F") ? /* @__PURE__ */ jsxs2(Text2, { children: [
24599
- /* @__PURE__ */ jsx2(Text2, { color: "cyan", bold: true, children: "\u276F" }),
24600
- /* @__PURE__ */ jsx2(Text2, { bold: true, children: msg.text.slice(1) })
24635
+ messages.map((msg) => /* @__PURE__ */ jsx2(Box2, { paddingX: 1, marginBottom: 1, flexDirection: "column", children: msg.text.startsWith("\u276F") ? /* @__PURE__ */ jsxs2(Text2, { backgroundColor: "gray", color: "white", bold: true, children: [
24636
+ " ",
24637
+ msg.text,
24638
+ " "
24601
24639
  ] }) : msg.text.includes("\u23BF") && msg.text.includes("Write") ? /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
24602
24640
  /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: msg.text.split("\n")[0] }),
24603
24641
  msg.text.split("\n").slice(1).map((line, li) => /* @__PURE__ */ jsx2(Text2, { backgroundColor: line.includes("+") ? "green" : void 0, color: line.includes("+") ? "white" : void 0, dimColor: !line.includes("+"), children: line }, li))
@@ -24620,15 +24658,20 @@ function ChatApp({ engine }) {
24620
24658
  },
24621
24659
  onCancel: () => setShowModelPicker(false)
24622
24660
  }
24623
- ) : loading ? /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", paddingX: 1, children: streaming ? /* @__PURE__ */ jsx2(Text2, { wrap: "wrap", children: streaming }) : /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
24661
+ ) : loading ? /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", paddingX: 1, children: streaming ? /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
24662
+ /* @__PURE__ */ jsx2(Text2, { wrap: "wrap", children: streaming }),
24663
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "\n esc to cancel" })
24664
+ ] }) : /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
24624
24665
  /* @__PURE__ */ jsx2(InkSpinner, { type: "dots" }),
24625
- " Thinking"
24666
+ " Thinking ",
24667
+ /* @__PURE__ */ jsx2(Text2, { color: "gray", children: "esc to cancel" })
24626
24668
  ] }) }) : /* @__PURE__ */ jsx2(
24627
24669
  InputArea,
24628
24670
  {
24629
24671
  onSubmit: handleSubmit,
24630
24672
  placeholder: "Message RobinPath...",
24631
- statusText: status
24673
+ statusText: responseTime ? `${status} \xB7 ${responseTime}` : status,
24674
+ history: inputHistory
24632
24675
  }
24633
24676
  )
24634
24677
  ] });
@@ -24644,6 +24687,7 @@ var ReplEngine = class {
24644
24687
  conversationMessages;
24645
24688
  cliContext;
24646
24689
  ui = null;
24690
+ abortController = null;
24647
24691
  constructor(resumeSessionId, opts) {
24648
24692
  this.config = readAiConfig();
24649
24693
  this.autoAccept = opts.autoAccept || false;
@@ -24690,6 +24734,12 @@ var ReplEngine = class {
24690
24734
  if (this.usage.cost > 0) parts.push(`$${this.usage.cost.toFixed(4)}`);
24691
24735
  this.ui?.setStatus(parts.join(" \xB7 "));
24692
24736
  }
24737
+ cancel() {
24738
+ if (this.abortController) {
24739
+ this.abortController.abort();
24740
+ this.abortController = null;
24741
+ }
24742
+ }
24693
24743
  exit() {
24694
24744
  if (this.conversationMessages.length > 1) saveSession(this.sessionId, this.sessionName, this.conversationMessages, this.usage);
24695
24745
  process.exit(0);
@@ -24792,7 +24842,12 @@ Type / to see available commands.`;
24792
24842
  const activeModel = readAiConfig().model || this.model;
24793
24843
  const activeKey = readAiConfig().apiKey || this.apiKey;
24794
24844
  const activeProvider = this.resolveProvider(activeKey);
24845
+ this.abortController = new AbortController();
24795
24846
  for (let loop = 0; loop < 5; loop++) {
24847
+ if (this.abortController?.signal.aborted) {
24848
+ finalResponse = "(cancelled)";
24849
+ break;
24850
+ }
24796
24851
  let fullText = "";
24797
24852
  let lastUpdate = 0;
24798
24853
  const result = await fetchBrainStream(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@robinpath/cli",
3
- "version": "2.9.0",
3
+ "version": "3.0.1",
4
4
  "description": "AI-powered scripting CLI — automate anything from your terminal",
5
5
  "type": "module",
6
6
  "license": "MIT",