@robinpath/cli 3.0.2 → 3.2.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 +85 -18
  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 ? "3.0.2" : "3.0.2";
18601
+ var CLI_VERSION = true ? "3.2.0" : "3.2.0";
18602
18602
  var FLAG_QUIET = false;
18603
18603
  var FLAG_VERBOSE = false;
18604
18604
  var FLAG_AUTO_ACCEPT = false;
@@ -20076,9 +20076,7 @@ async function loadInstalledModules(rp2) {
20076
20076
  }
20077
20077
  if (FLAG_VERBOSE) logVerbose(`Loaded module: ${packageName}@${info.version}`);
20078
20078
  } catch (err) {
20079
- console.error(
20080
- color.yellow("Warning:") + ` Failed to load module ${packageName}: ${err.message}`
20081
- );
20079
+ logVerbose(`Failed to load module ${packageName}: ${err.message}`);
20082
20080
  }
20083
20081
  }
20084
20082
  }
@@ -24141,6 +24139,7 @@ import { render, Box as Box2, Text as Text2, useInput, useApp } from "ink";
24141
24139
  import InkSpinner from "ink-spinner";
24142
24140
 
24143
24141
  // src/ui/Markdown.tsx
24142
+ import React from "react";
24144
24143
  import { Box, Text } from "ink";
24145
24144
  import { jsx, jsxs } from "react/jsx-runtime";
24146
24145
  function parseBlocks(text) {
@@ -24187,11 +24186,42 @@ function renderInlineMarkdown(line) {
24187
24186
  }
24188
24187
  return parts;
24189
24188
  }
24189
+ function renderTable(tableLines) {
24190
+ const rows = tableLines.filter((l) => !l.match(/^\s*\|[-:\s|]+\|\s*$/)).map((l) => l.split("|").slice(1, -1).map((cell) => cell.trim()));
24191
+ if (rows.length === 0) return null;
24192
+ const colCount = rows[0].length;
24193
+ const widths = Array(colCount).fill(0);
24194
+ for (const row of rows) {
24195
+ for (let c = 0; c < Math.min(row.length, colCount); c++) {
24196
+ widths[c] = Math.max(widths[c], row[c].length);
24197
+ }
24198
+ }
24199
+ return /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginY: 1, children: rows.map((row, ri) => /* @__PURE__ */ jsxs(Text, { bold: ri === 0, dimColor: ri === 0, children: [
24200
+ " ",
24201
+ row.map((cell, ci) => cell.padEnd(widths[ci] || 0) + " ").join("")
24202
+ ] }, ri)) });
24203
+ }
24190
24204
  function TextBlock({ content }) {
24191
24205
  const lines = content.split("\n");
24192
- return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: lines.map((line, i) => {
24206
+ const rendered = [];
24207
+ let i = 0;
24208
+ while (i < lines.length) {
24209
+ if (lines[i].trim().startsWith("|") && lines[i].trim().endsWith("|")) {
24210
+ const tableStart = i;
24211
+ while (i < lines.length && lines[i].trim().startsWith("|")) i++;
24212
+ if (i - tableStart >= 2) {
24213
+ rendered.push(/* @__PURE__ */ jsx(React.Fragment, { children: renderTable(lines.slice(tableStart, i)) }, tableStart));
24214
+ continue;
24215
+ }
24216
+ i = tableStart;
24217
+ }
24218
+ rendered.push(/* @__PURE__ */ jsx(React.Fragment, { children: renderTextLine(lines[i], i) }, i));
24219
+ i++;
24220
+ }
24221
+ return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: rendered });
24222
+ function renderTextLine(line, idx) {
24193
24223
  const trimmed = line.trimStart();
24194
- if (!trimmed) return /* @__PURE__ */ jsx(Text, { children: " " }, i);
24224
+ if (!trimmed) return /* @__PURE__ */ jsx(Text, { children: " " }, idx);
24195
24225
  if (trimmed.startsWith("## ")) {
24196
24226
  return /* @__PURE__ */ jsx(Text, { bold: true, children: trimmed.slice(3) }, i);
24197
24227
  }
@@ -24215,8 +24245,8 @@ function TextBlock({ content }) {
24215
24245
  renderInlineMarkdown(trimmed.slice(numMatch[0].length))
24216
24246
  ] }, i);
24217
24247
  }
24218
- return /* @__PURE__ */ jsx(Text, { wrap: "wrap", children: renderInlineMarkdown(line) }, i);
24219
- }) });
24248
+ return /* @__PURE__ */ jsx(Text, { wrap: "wrap", children: renderInlineMarkdown(line) }, idx);
24249
+ }
24220
24250
  }
24221
24251
  function CodeBlock({ content, lang }) {
24222
24252
  const allLines = content.split("\n");
@@ -24277,12 +24307,14 @@ var COMMANDS = {
24277
24307
  "/forget": "Remove a memory",
24278
24308
  "/usage": "Token usage & cost",
24279
24309
  "/shell": "Switch shell",
24310
+ "/init": "Create ROBINPATH.md",
24280
24311
  "/help": "All commands"
24281
24312
  };
24282
24313
  function InputArea({ onSubmit, placeholder, statusText, history }) {
24283
24314
  const [value, setValue] = useState("");
24284
24315
  const [historyIdx, setHistoryIdx] = useState(-1);
24285
24316
  const [savedInput, setSavedInput] = useState("");
24317
+ const [tabIdx, setTabIdx] = useState(-1);
24286
24318
  const { exit } = useApp();
24287
24319
  const matchingCommands = useMemo(() => {
24288
24320
  if (!value.startsWith("/")) return [];
@@ -24344,10 +24376,12 @@ function InputArea({ onSubmit, placeholder, statusText, history }) {
24344
24376
  return;
24345
24377
  }
24346
24378
  if (showFiles.length > 0) {
24379
+ const nextIdx = (tabIdx + 1) % showFiles.length;
24380
+ setTabIdx(nextIdx);
24347
24381
  const atMatch = value.match(/@(\S*)$/);
24348
24382
  if (atMatch) {
24349
24383
  const before = value.slice(0, value.length - atMatch[0].length);
24350
- setValue(before + "@" + showFiles[0].name + " ");
24384
+ setValue(before + "@" + showFiles[nextIdx].name);
24351
24385
  }
24352
24386
  }
24353
24387
  return;
@@ -24381,6 +24415,7 @@ function InputArea({ onSubmit, placeholder, statusText, history }) {
24381
24415
  if (ch && !key.ctrl && !key.meta) {
24382
24416
  setValue((p) => p + ch);
24383
24417
  setHistoryIdx(-1);
24418
+ setTabIdx(-1);
24384
24419
  }
24385
24420
  });
24386
24421
  const lines = value.split("\n");
@@ -24422,9 +24457,9 @@ function InputArea({ onSubmit, placeholder, statusText, history }) {
24422
24457
  ] }, i)) }),
24423
24458
  /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "\u2500".repeat(Math.max(process.stdout.columns || 80, 40)) })
24424
24459
  ] }),
24425
- showFiles.length > 0 && /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", paddingX: 2, marginTop: 1, children: showFiles.map((f) => /* @__PURE__ */ jsxs2(Text2, { children: [
24426
- /* @__PURE__ */ jsx2(Text2, { color: "cyan", children: "+ " }),
24427
- /* @__PURE__ */ jsx2(Text2, { bold: f.name.endsWith(".rp") || f.name.endsWith(".robin"), children: f.name }),
24460
+ showFiles.length > 0 && /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", paddingX: 2, marginTop: 1, children: showFiles.map((f, i) => /* @__PURE__ */ jsxs2(Text2, { children: [
24461
+ /* @__PURE__ */ jsx2(Text2, { color: i === tabIdx ? "cyan" : "gray", children: i === tabIdx ? "\u276F " : "+ " }),
24462
+ /* @__PURE__ */ jsx2(Text2, { bold: i === tabIdx, color: i === tabIdx ? "cyan" : void 0, children: f.name }),
24428
24463
  f.isDir ? /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "/" }) : null
24429
24464
  ] }, f.name)) }),
24430
24465
  /* @__PURE__ */ jsxs2(Box2, { paddingX: 2, justifyContent: "space-between", children: [
@@ -24576,6 +24611,7 @@ function ChatApp({ engine }) {
24576
24611
  const elapsed = Date.now() - startTime;
24577
24612
  const timeStr = elapsed < 1e3 ? `${elapsed}ms` : elapsed < 6e4 ? `${(elapsed / 1e3).toFixed(1)}s` : `${Math.floor(elapsed / 6e4)}m ${Math.round(elapsed % 6e4 / 1e3)}s`;
24578
24613
  setResponseTime(timeStr);
24614
+ if (elapsed > 1e4) process.stdout.write("\x07");
24579
24615
  engine.updateStatus();
24580
24616
  }
24581
24617
  }, [engine]);
@@ -24618,6 +24654,11 @@ function ChatApp({ engine }) {
24618
24654
  ] })
24619
24655
  ] }),
24620
24656
  /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", width: "50%", children: [
24657
+ /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
24658
+ "Run ",
24659
+ /* @__PURE__ */ jsx2(Text2, { color: "cyan", children: "/init" }),
24660
+ " to create ROBINPATH.md"
24661
+ ] }),
24621
24662
  /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
24622
24663
  "Type ",
24623
24664
  /* @__PURE__ */ jsx2(Text2, { color: "cyan", children: "/" }),
@@ -24625,13 +24666,8 @@ function ChatApp({ engine }) {
24625
24666
  ] }),
24626
24667
  /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
24627
24668
  "Use ",
24628
- /* @__PURE__ */ jsx2(Text2, { color: "cyan", children: "@/file" }),
24669
+ /* @__PURE__ */ jsx2(Text2, { color: "cyan", children: "@" }),
24629
24670
  " to include files"
24630
- ] }),
24631
- /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
24632
- "Use ",
24633
- /* @__PURE__ */ jsx2(Text2, { color: "cyan", children: "\\" }),
24634
- " for multiline"
24635
24671
  ] })
24636
24672
  ] })
24637
24673
  ] }) : null,
@@ -24709,6 +24745,20 @@ var ReplEngine = class {
24709
24745
  nativeModules: getNativeModules().map((m) => m.name),
24710
24746
  installedModules: Object.keys(readModulesManifest())
24711
24747
  };
24748
+ const projectFiles = ["ROBINPATH.md", "robinpath.md", ".robinpath.md"];
24749
+ for (const pf of projectFiles) {
24750
+ try {
24751
+ const projectPath = join12(process.cwd(), pf);
24752
+ if (existsSync11(projectPath)) {
24753
+ const content = readFileSync10(projectPath, "utf-8").slice(0, 1e4);
24754
+ this.conversationMessages.push({ role: "user", content: `[Project Instructions \u2014 ${pf}]
24755
+ ${content}` });
24756
+ this.conversationMessages.push({ role: "assistant", content: "Project instructions loaded." });
24757
+ break;
24758
+ }
24759
+ } catch {
24760
+ }
24761
+ }
24712
24762
  const mem = buildMemoryContext();
24713
24763
  if (mem.trim()) {
24714
24764
  this.conversationMessages.push({ role: "user", content: `[Context] ${mem.trim()}` });
@@ -24757,6 +24807,23 @@ var ReplEngine = class {
24757
24807
  this.ui?.clearMessages();
24758
24808
  return "";
24759
24809
  }
24810
+ if (text === "/init") {
24811
+ const mdPath = join12(process.cwd(), "ROBINPATH.md");
24812
+ if (existsSync11(mdPath)) return "ROBINPATH.md already exists. Edit it to update project instructions.";
24813
+ writeFileSync6(mdPath, `# Project Instructions
24814
+
24815
+ ## About
24816
+ Describe your project here.
24817
+
24818
+ ## Rules
24819
+ - Use RobinPath scripting language for automation
24820
+ - Follow the project structure
24821
+
24822
+ ## Context
24823
+ Any context the AI should know about this project.
24824
+ `);
24825
+ return "\u2713 Created ROBINPATH.md \u2014 edit it to customize AI behavior for this project.";
24826
+ }
24760
24827
  if (text === "/compact") {
24761
24828
  if (this.conversationMessages.length > 12) {
24762
24829
  this.conversationMessages.splice(1, this.conversationMessages.length - 11);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@robinpath/cli",
3
- "version": "3.0.2",
3
+ "version": "3.2.0",
4
4
  "description": "AI-powered scripting CLI — automate anything from your terminal",
5
5
  "type": "module",
6
6
  "license": "MIT",