@robinpath/cli 1.89.0 → 1.91.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 +60 -38
  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.89.0" : "1.89.0";
18601
+ var CLI_VERSION = true ? "1.91.0" : "1.91.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();
@@ -24476,29 +24506,25 @@ function ChatApp({ engine }) {
24476
24506
  const cwdShort = process.cwd().replace(homedir8(), "~");
24477
24507
  const isFirst = messages.length === 0;
24478
24508
  return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", paddingY: 1, children: [
24479
- isFirst && !loading ? /* @__PURE__ */ jsxs2(Box2, { borderStyle: "round", borderColor: "gray", marginBottom: 1, paddingX: 2, paddingY: 1, children: [
24509
+ isFirst && !loading ? /* @__PURE__ */ jsxs2(Box2, { borderStyle: "round", borderColor: "gray", paddingX: 1, children: [
24480
24510
  /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", width: "50%", children: [
24481
- /* @__PURE__ */ jsx2(Text2, { children: " " }),
24482
- /* @__PURE__ */ jsx2(Text2, { bold: true, children: " Welcome to RobinPath!" }),
24483
- /* @__PURE__ */ jsx2(Text2, { children: " " }),
24511
+ /* @__PURE__ */ jsx2(Text2, { bold: true, children: " Welcome to RobinPath!" }),
24484
24512
  /* @__PURE__ */ jsxs2(Text2, { children: [
24485
- " ",
24513
+ " ",
24486
24514
  /* @__PURE__ */ jsx2(Text2, { color: "cyan", bold: true, children: "\u25C6" }),
24487
24515
  " ",
24488
24516
  /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: modelName })
24489
24517
  ] }),
24490
24518
  /* @__PURE__ */ jsxs2(Text2, { children: [
24491
- " ",
24519
+ " ",
24492
24520
  /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: cwdShort })
24493
- ] }),
24494
- /* @__PURE__ */ jsx2(Text2, { children: " " })
24521
+ ] })
24495
24522
  ] }),
24496
24523
  /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", width: "50%", children: [
24497
- /* @__PURE__ */ jsx2(Text2, { bold: true, children: "Tips" }),
24498
24524
  /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
24499
24525
  "Type ",
24500
24526
  /* @__PURE__ */ jsx2(Text2, { color: "cyan", children: "/" }),
24501
- " to see all commands"
24527
+ " to see commands"
24502
24528
  ] }),
24503
24529
  /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
24504
24530
  "Use ",
@@ -24508,12 +24534,7 @@ function ChatApp({ engine }) {
24508
24534
  /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
24509
24535
  "Use ",
24510
24536
  /* @__PURE__ */ jsx2(Text2, { color: "cyan", children: "\\" }),
24511
- " at end for multiline"
24512
- ] }),
24513
- /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
24514
- "Type ",
24515
- /* @__PURE__ */ jsx2(Text2, { color: "cyan", children: "exit" }),
24516
- " to quit"
24537
+ " for multiline"
24517
24538
  ] })
24518
24539
  ] })
24519
24540
  ] }) : null,
@@ -24531,7 +24552,25 @@ function ChatApp({ engine }) {
24531
24552
  /* @__PURE__ */ jsx2(Text2, { color: "cyan", bold: true, children: "\u276F" }),
24532
24553
  /* @__PURE__ */ jsx2(Text2, { bold: true, children: msg.text.slice(1) })
24533
24554
  ] }) : msg.dim ? /* @__PURE__ */ jsx2(Text2, { dimColor: true, wrap: "wrap", children: msg.text }) : /* @__PURE__ */ jsx2(Markdown, { children: msg.text }) }, msg.id) }),
24534
- 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: [
24535
24574
  /* @__PURE__ */ jsx2(Markdown, { children: streaming }),
24536
24575
  /* @__PURE__ */ jsx2(Text2, { color: "cyan", children: "\u258D" })
24537
24576
  ] }) : /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
@@ -24627,26 +24666,9 @@ var ReplEngine = class {
24627
24666
  this.autoAccept = !this.autoAccept;
24628
24667
  return `Auto-accept: ${this.autoAccept ? "ON \u2014 commands run without asking" : "OFF \u2014 confirm each command"}`;
24629
24668
  }
24630
- if (text === "/model") {
24631
- const hasKey = !!readAiConfig().apiKey;
24632
- const models = hasKey ? AI_MODELS : AI_MODELS.filter((m) => !m.requiresKey);
24633
- const cur = readAiConfig().model || this.model;
24634
- return models.map((m, i) => {
24635
- const mark = m.id === cur ? " \u2713" : "";
24636
- return `${String(i + 1).padStart(2)}. ${m.name.padEnd(22)} ${m.desc}${mark}`;
24637
- }).join("\n") + "\n\nType /model <number> to switch.";
24638
- }
24639
- if (text.match(/^\/model \d+$/)) {
24640
- const hasKey = !!readAiConfig().apiKey;
24641
- const models = hasKey ? AI_MODELS : AI_MODELS.filter((m) => !m.requiresKey);
24642
- const idx = parseInt(text.split(" ")[1], 10) - 1;
24643
- if (idx >= 0 && idx < models.length) {
24644
- this.config.model = models[idx].id;
24645
- this.model = models[idx].id;
24646
- writeAiConfig(this.config);
24647
- return `\u2713 Model: ${models[idx].name}`;
24648
- }
24649
- return "Invalid number. Type /model to see the list.";
24669
+ if (text === "/model" || text.startsWith("/model ")) {
24670
+ this.ui?.setShowModelPicker(true);
24671
+ return "";
24650
24672
  }
24651
24673
  if (text === "/usage") {
24652
24674
  const c = this.usage.cost > 0 ? `$${this.usage.cost.toFixed(4)}` : "$0.00 (free)";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@robinpath/cli",
3
- "version": "1.89.0",
3
+ "version": "1.91.0",
4
4
  "description": "AI-powered scripting CLI — automate anything from your terminal",
5
5
  "type": "module",
6
6
  "license": "MIT",