@robinpath/cli 1.90.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 +53 -22
  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.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();
@@ -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)";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@robinpath/cli",
3
- "version": "1.90.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",