@robinpath/cli 1.90.0 → 1.92.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 +58 -25
  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.90.0" : "1.90.0";
18601
+ var CLI_VERSION = true ? "1.92.0" : "1.92.0";
18602
18602
  var FLAG_QUIET = false;
18603
18603
  var FLAG_VERBOSE = false;
18604
18604
  var FLAG_AUTO_ACCEPT = false;
@@ -24403,6 +24403,34 @@ function TrustPrompt({ cwd, onAccept, onReject }) {
24403
24403
  /* @__PURE__ */ jsx2(Box2, { paddingX: 2, children: /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "\u2191\u2193 select \xB7 enter confirm \xB7 esc cancel" }) })
24404
24404
  ] });
24405
24405
  }
24406
+ function ModelSelector({ models, currentId, onSelect, onCancel }) {
24407
+ const [cursor, setCursor] = useState(() => Math.max(0, models.findIndex((m) => m.id === currentId)));
24408
+ useInput((ch, key) => {
24409
+ if (key.upArrow) setCursor((c) => Math.max(0, c - 1));
24410
+ if (key.downArrow) setCursor((c) => Math.min(models.length - 1, c + 1));
24411
+ if (key.return) onSelect(models[cursor].id);
24412
+ if (key.escape) onCancel();
24413
+ });
24414
+ let lastGroup = "";
24415
+ return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", paddingX: 2, marginY: 1, children: [
24416
+ models.map((m, i) => {
24417
+ const showGroup = m.group !== lastGroup;
24418
+ lastGroup = m.group;
24419
+ const isCurrent = m.id === currentId;
24420
+ const isSelected = i === cursor;
24421
+ return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
24422
+ showGroup && /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: `\u2500\u2500 ${m.group} \u2500\u2500` }),
24423
+ /* @__PURE__ */ jsxs2(Text2, { children: [
24424
+ isSelected ? /* @__PURE__ */ jsx2(Text2, { color: "cyan", bold: true, children: "\u276F " }) : /* @__PURE__ */ jsx2(Text2, { children: " " }),
24425
+ /* @__PURE__ */ jsx2(Text2, { bold: isSelected, children: m.name.padEnd(22) }),
24426
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: m.desc }),
24427
+ isCurrent ? /* @__PURE__ */ jsx2(Text2, { color: "green", children: " \u2713" }) : null
24428
+ ] })
24429
+ ] }, m.id);
24430
+ }),
24431
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "\n \u2191\u2193 select \xB7 enter confirm \xB7 esc cancel" })
24432
+ ] });
24433
+ }
24406
24434
  function ChatApp({ engine }) {
24407
24435
  const [trusted, setTrusted] = useState(() => {
24408
24436
  try {
@@ -24419,11 +24447,13 @@ function ChatApp({ engine }) {
24419
24447
  const [streaming, setStreaming] = useState("");
24420
24448
  const [loading, setLoading] = useState(false);
24421
24449
  const [status, setStatus] = useState("");
24450
+ const [showModelPicker, setShowModelPicker] = useState(false);
24422
24451
  useEffect(() => {
24423
24452
  engine.ui = {
24424
24453
  setStreaming,
24425
24454
  setLoading,
24426
24455
  setStatus,
24456
+ setShowModelPicker,
24427
24457
  addMessage: (text, dim) => setMessages((p) => [...p, { id: ++nextId, text, dim }])
24428
24458
  };
24429
24459
  engine.updateStatus();
@@ -24522,7 +24552,25 @@ function ChatApp({ engine }) {
24522
24552
  /* @__PURE__ */ jsx2(Text2, { color: "cyan", bold: true, children: "\u276F" }),
24523
24553
  /* @__PURE__ */ jsx2(Text2, { bold: true, children: msg.text.slice(1) })
24524
24554
  ] }) : msg.dim ? /* @__PURE__ */ jsx2(Text2, { dimColor: true, wrap: "wrap", children: msg.text }) : /* @__PURE__ */ jsx2(Markdown, { children: msg.text }) }, msg.id) }),
24525
- loading ? /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", paddingX: 1, children: streaming ? /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
24555
+ showModelPicker ? /* @__PURE__ */ jsx2(
24556
+ ModelSelector,
24557
+ {
24558
+ models: (() => {
24559
+ const hasKey = !!readAiConfig().apiKey;
24560
+ return hasKey ? AI_MODELS : AI_MODELS.filter((m) => !m.requiresKey);
24561
+ })(),
24562
+ currentId: readAiConfig().model || engine.model,
24563
+ onSelect: (id) => {
24564
+ engine.config.model = id;
24565
+ engine.model = id;
24566
+ writeAiConfig(engine.config);
24567
+ setMessages((p) => [...p, { id: ++nextId, text: `\u2713 Model: ${id.includes("/") ? id.split("/").pop() : id}`, dim: true }]);
24568
+ setShowModelPicker(false);
24569
+ engine.updateStatus();
24570
+ },
24571
+ onCancel: () => setShowModelPicker(false)
24572
+ }
24573
+ ) : loading ? /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", paddingX: 1, children: streaming ? /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
24526
24574
  /* @__PURE__ */ jsx2(Markdown, { children: streaming }),
24527
24575
  /* @__PURE__ */ jsx2(Text2, { color: "cyan", children: "\u258D" })
24528
24576
  ] }) : /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
@@ -24618,26 +24666,9 @@ var ReplEngine = class {
24618
24666
  this.autoAccept = !this.autoAccept;
24619
24667
  return `Auto-accept: ${this.autoAccept ? "ON \u2014 commands run without asking" : "OFF \u2014 confirm each command"}`;
24620
24668
  }
24621
- if (text === "/model") {
24622
- const hasKey = !!readAiConfig().apiKey;
24623
- const models = hasKey ? AI_MODELS : AI_MODELS.filter((m) => !m.requiresKey);
24624
- const cur = readAiConfig().model || this.model;
24625
- return models.map((m, i) => {
24626
- const mark = m.id === cur ? " \u2713" : "";
24627
- return `${String(i + 1).padStart(2)}. ${m.name.padEnd(22)} ${m.desc}${mark}`;
24628
- }).join("\n") + "\n\nType /model <number> to switch.";
24629
- }
24630
- if (text.match(/^\/model \d+$/)) {
24631
- const hasKey = !!readAiConfig().apiKey;
24632
- const models = hasKey ? AI_MODELS : AI_MODELS.filter((m) => !m.requiresKey);
24633
- const idx = parseInt(text.split(" ")[1], 10) - 1;
24634
- if (idx >= 0 && idx < models.length) {
24635
- this.config.model = models[idx].id;
24636
- this.model = models[idx].id;
24637
- writeAiConfig(this.config);
24638
- return `\u2713 Model: ${models[idx].name}`;
24639
- }
24640
- return "Invalid number. Type /model to see the list.";
24669
+ if (text === "/model" || text.startsWith("/model ")) {
24670
+ this.ui?.setShowModelPicker(true);
24671
+ return "";
24641
24672
  }
24642
24673
  if (text === "/usage") {
24643
24674
  const c = this.usage.cost > 0 ? `$${this.usage.cost.toFixed(4)}` : "$0.00 (free)";
@@ -24735,15 +24766,17 @@ Type / to see available commands.`;
24735
24766
  }
24736
24767
  );
24737
24768
  if (!result) {
24738
- finalResponse = "No internet connection. Check your network and try again.";
24769
+ finalResponse = "\u26A0 No internet connection. Check your network and try again.";
24739
24770
  break;
24740
24771
  }
24741
24772
  if (result.error) {
24742
- finalResponse = result.error;
24773
+ finalResponse = `\u26A0 ${result.error}`;
24743
24774
  break;
24744
24775
  }
24745
24776
  if (!result.code) {
24746
- finalResponse = fullText || "No response. Try again.";
24777
+ const model = readAiConfig().model || this.model;
24778
+ const hint = model === "robinpath-default" ? "The free model may be temporarily unavailable. Try again or switch to a paid model with /model." : "The AI returned an empty response. Try rephrasing or check your API key with /usage.";
24779
+ finalResponse = fullText || `\u26A0 ${hint}`;
24747
24780
  break;
24748
24781
  }
24749
24782
  if (result.usage) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@robinpath/cli",
3
- "version": "1.90.0",
3
+ "version": "1.92.0",
4
4
  "description": "AI-powered scripting CLI — automate anything from your terminal",
5
5
  "type": "module",
6
6
  "license": "MIT",