@robinpath/cli 1.75.0 → 1.77.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.
package/dist/cli.mjs CHANGED
@@ -18561,7 +18561,7 @@ var init_modules = __esm({
18561
18561
  });
18562
18562
 
18563
18563
  // src/index.ts
18564
- import { readFileSync as readFileSync15, existsSync as existsSync16 } from "node:fs";
18564
+ import { readFileSync as readFileSync14, existsSync as existsSync15 } from "node:fs";
18565
18565
  import { resolve as resolve12, extname as extname5, basename as basename8 } from "node:path";
18566
18566
 
18567
18567
  // src/runtime.ts
@@ -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.75.0" : "1.75.0";
18601
+ var CLI_VERSION = true ? "1.77.0" : "1.77.0";
18602
18602
  var FLAG_QUIET = false;
18603
18603
  var FLAG_VERBOSE = false;
18604
18604
  var FLAG_AUTO_ACCEPT = false;
@@ -24132,17 +24132,17 @@ ${resultSummary}`
24132
24132
  }
24133
24133
 
24134
24134
  // src/ink-repl.tsx
24135
- import { useState } from "react";
24136
- import { render, Box, Text, useInput, useApp } from "ink";
24137
- import { homedir as homedir8, platform as platform7 } from "node:os";
24135
+ import { useState, useCallback, useEffect } from "react";
24136
+ import { render, Box, Text, Static, useInput, useApp } from "ink";
24137
+ import InkSpinner from "ink-spinner";
24138
+ import { platform as platform7 } from "node:os";
24138
24139
  import { randomUUID as randomUUID4 } from "node:crypto";
24139
- import { readdirSync as readdirSync6, statSync as statSync6 } from "node:fs";
24140
- import { join as join12 } from "node:path";
24141
24140
  import { jsx, jsxs } from "react/jsx-runtime";
24142
- function InputPrompt({ placeholder, onSubmit, onExit }) {
24141
+ var nextId = 0;
24142
+ function InputBox({ onSubmit, active, placeholder }) {
24143
24143
  const [value, setValue] = useState("");
24144
- const { exit } = useApp();
24145
24144
  useInput((input, key) => {
24145
+ if (!active) return;
24146
24146
  if (key.return) {
24147
24147
  if (value.endsWith("\\")) {
24148
24148
  setValue((p) => p.slice(0, -1) + "\n");
@@ -24150,8 +24150,8 @@ function InputPrompt({ placeholder, onSubmit, onExit }) {
24150
24150
  }
24151
24151
  const text = value.trim();
24152
24152
  if (text) {
24153
- exit();
24154
24153
  onSubmit(text);
24154
+ setValue("");
24155
24155
  }
24156
24156
  return;
24157
24157
  }
@@ -24163,13 +24163,6 @@ function InputPrompt({ placeholder, onSubmit, onExit }) {
24163
24163
  setValue("");
24164
24164
  return;
24165
24165
  }
24166
- if (input === "") {
24167
- if (!value) {
24168
- exit();
24169
- onExit();
24170
- } else setValue("");
24171
- return;
24172
- }
24173
24166
  if (key.backspace || key.delete) {
24174
24167
  setValue((p) => p.slice(0, -1));
24175
24168
  return;
@@ -24184,361 +24177,272 @@ function InputPrompt({ placeholder, onSubmit, onExit }) {
24184
24177
  return;
24185
24178
  }
24186
24179
  if (input && !key.ctrl && !key.meta) setValue((p) => p + input);
24187
- });
24180
+ }, { isActive: active });
24188
24181
  const lines = value.split("\n");
24189
24182
  const empty = value === "";
24190
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
24191
- /* @__PURE__ */ jsx(Box, { borderStyle: "round", borderColor: "cyan", flexDirection: "column", paddingX: 1, marginX: 1, children: empty ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: placeholder }) : lines.map((line, i) => /* @__PURE__ */ jsxs(Text, { children: [
24183
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
24184
+ /* @__PURE__ */ jsx(Box, { borderStyle: "round", borderColor: active ? "cyan" : "gray", flexDirection: "column", paddingX: 1, marginX: 1, children: empty ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: placeholder }) : lines.map((line, i) => /* @__PURE__ */ jsxs(Text, { children: [
24192
24185
  line,
24193
- i === lines.length - 1 ? /* @__PURE__ */ jsx(Text, { color: "cyan", children: "\u2588" }) : null
24186
+ i === lines.length - 1 && active ? /* @__PURE__ */ jsx(Text, { color: "cyan", children: "\u2588" }) : null
24194
24187
  ] }, i)) }),
24195
24188
  /* @__PURE__ */ jsx(Box, { marginX: 2, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "enter send \xB7 \\ newline \xB7 esc clear \xB7 / commands" }) })
24196
24189
  ] });
24197
24190
  }
24198
- function collectInkInput(placeholder) {
24199
- if (!process.stdin.isTTY) {
24200
- return Promise.resolve(null);
24201
- }
24202
- return new Promise((resolve13) => {
24203
- let resolved = false;
24204
- const { waitUntilExit } = render(
24205
- /* @__PURE__ */ jsx(
24206
- InputPrompt,
24207
- {
24208
- placeholder,
24209
- onSubmit: (v) => {
24210
- if (!resolved) {
24211
- resolved = true;
24212
- resolve13(v);
24213
- }
24214
- },
24215
- onExit: () => {
24216
- if (!resolved) {
24217
- resolved = true;
24218
- resolve13(null);
24219
- }
24220
- }
24221
- }
24222
- )
24223
- );
24224
- waitUntilExit().then(() => {
24225
- if (!resolved) {
24226
- resolved = true;
24227
- resolve13(null);
24191
+ function App({ engine }) {
24192
+ const [messages, setMessages] = useState([]);
24193
+ const [streaming, setStreaming] = useState("");
24194
+ const [loading, setLoading] = useState(false);
24195
+ const [loadingLabel, setLoadingLabel] = useState("Thinking");
24196
+ const [status, setStatus] = useState("");
24197
+ const { exit } = useApp();
24198
+ useEffect(() => {
24199
+ engine.ui = {
24200
+ addMessage: (role, text) => setMessages((p) => [...p, { id: ++nextId, role, text }]),
24201
+ setStreaming,
24202
+ setLoading,
24203
+ setLoadingLabel,
24204
+ setStatus,
24205
+ exit
24206
+ };
24207
+ }, []);
24208
+ const handleSubmit = useCallback(async (text) => {
24209
+ if (text === "exit" || text === "quit") {
24210
+ engine.exit();
24211
+ return;
24212
+ }
24213
+ await engine.handleInput(text);
24214
+ }, [engine]);
24215
+ const isFirst = messages.length === 0;
24216
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
24217
+ /* @__PURE__ */ jsx(Box, { marginTop: 1, marginBottom: 1, marginX: 1, children: /* @__PURE__ */ jsxs(Text, { children: [
24218
+ /* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "\u25C6" }),
24219
+ " ",
24220
+ /* @__PURE__ */ jsx(Text, { bold: true, children: "RobinPath" }),
24221
+ " ",
24222
+ /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
24223
+ "v",
24224
+ CLI_VERSION
24225
+ ] })
24226
+ ] }) }),
24227
+ /* @__PURE__ */ jsx(Static, { items: messages, children: (msg) => /* @__PURE__ */ jsx(Box, { marginX: 2, marginBottom: msg.role === "assistant" ? 1 : 0, children: msg.role === "user" ? /* @__PURE__ */ jsxs(Text, { children: [
24228
+ /* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "\u276F " }),
24229
+ /* @__PURE__ */ jsx(Text, { bold: true, children: msg.text })
24230
+ ] }) : msg.role === "info" ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: msg.text }) : /* @__PURE__ */ jsx(Text, { wrap: "wrap", children: msg.text }) }, msg.id) }),
24231
+ loading && streaming ? /* @__PURE__ */ jsx(Box, { marginX: 2, marginBottom: 1, children: /* @__PURE__ */ jsxs(Text, { wrap: "wrap", children: [
24232
+ streaming,
24233
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: "\u258D" })
24234
+ ] }) }) : null,
24235
+ loading && !streaming ? /* @__PURE__ */ jsx(Box, { marginX: 2, marginBottom: 1, children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
24236
+ /* @__PURE__ */ jsx(InkSpinner, { type: "dots" }),
24237
+ " ",
24238
+ loadingLabel
24239
+ ] }) }) : null,
24240
+ /* @__PURE__ */ jsx(
24241
+ InputBox,
24242
+ {
24243
+ onSubmit: handleSubmit,
24244
+ active: !loading,
24245
+ placeholder: isFirst ? "What do you want to automate?" : "Ask anything..."
24228
24246
  }
24229
- });
24230
- });
24231
- }
24232
- function printBanner(modelShort, modeStr, cwdShort, shellName) {
24233
- log("");
24234
- log(` ${color.cyan("\u25C6")} ${color.bold("RobinPath")} ${color.dim("v" + CLI_VERSION)}`);
24235
- log(color.dim(` ${modelShort} \xB7 ${shellName} \xB7 ${modeStr}`));
24236
- log("");
24247
+ ),
24248
+ status ? /* @__PURE__ */ jsx(Box, { marginX: 2, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: status }) }) : null
24249
+ ] });
24237
24250
  }
24238
- async function startInkREPL(initialPrompt, resumeSessionId, opts = {}) {
24239
- const config = readAiConfig();
24240
- let autoAccept = opts.autoAccept || false;
24241
- const devMode = opts.devMode || false;
24242
- if (devMode) setFlags({ verbose: true });
24243
- const resolveProvider = (key) => {
24251
+ var ReplEngine = class {
24252
+ config;
24253
+ autoAccept;
24254
+ devMode;
24255
+ apiKey;
24256
+ model;
24257
+ provider;
24258
+ sessionId;
24259
+ sessionName;
24260
+ usage;
24261
+ conversationMessages;
24262
+ cliContext;
24263
+ ui = null;
24264
+ constructor(resumeSessionId, opts) {
24265
+ this.config = readAiConfig();
24266
+ this.autoAccept = opts.autoAccept || false;
24267
+ this.devMode = opts.devMode || false;
24268
+ if (this.devMode) setFlags({ verbose: true });
24269
+ this.apiKey = this.config.apiKey || null;
24270
+ this.provider = this.resolveProvider(this.apiKey);
24271
+ this.model = this.apiKey ? this.config.model || "anthropic/claude-sonnet-4.6" : "robinpath-default";
24272
+ this.sessionId = resumeSessionId || randomUUID4().slice(0, 8);
24273
+ this.sessionName = `session-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}`;
24274
+ this.usage = createUsageTracker();
24275
+ this.conversationMessages = [];
24276
+ this.cliContext = {
24277
+ platform: platform7(),
24278
+ shell: getShellConfig().name,
24279
+ cwd: process.cwd(),
24280
+ cliVersion: CLI_VERSION,
24281
+ nativeModules: getNativeModules().map((m) => m.name),
24282
+ installedModules: Object.keys(readModulesManifest())
24283
+ };
24284
+ const mem = buildMemoryContext();
24285
+ if (mem.trim()) {
24286
+ this.conversationMessages.push({ role: "user", content: `[Context] ${mem.trim()}` });
24287
+ this.conversationMessages.push({ role: "assistant", content: "Preferences loaded." });
24288
+ }
24289
+ if (resumeSessionId) {
24290
+ const session = loadSession(resumeSessionId);
24291
+ if (session) {
24292
+ this.sessionName = session.name;
24293
+ for (const msg of session.messages) this.conversationMessages.push(msg);
24294
+ if (session.usage) {
24295
+ this.usage.promptTokens = session.usage.promptTokens || 0;
24296
+ this.usage.completionTokens = session.usage.completionTokens || 0;
24297
+ this.usage.totalTokens = session.usage.totalTokens || 0;
24298
+ this.usage.requests = session.usage.requests || 0;
24299
+ }
24300
+ }
24301
+ }
24302
+ }
24303
+ resolveProvider(key) {
24244
24304
  if (!key) return "gemini";
24245
24305
  if (key.startsWith("sk-or-")) return "openrouter";
24246
24306
  if (key.startsWith("sk-ant-")) return "anthropic";
24247
24307
  if (key.startsWith("sk-")) return "openai";
24248
- return config.provider || "gemini";
24249
- };
24250
- const apiKey = config.apiKey || null;
24251
- const provider = resolveProvider(apiKey);
24252
- const model = apiKey ? config.model || "anthropic/claude-sonnet-4.6" : "robinpath-default";
24253
- const modelShort = model === "robinpath-default" ? "gemini-2.0-flash (free)" : model.includes("/") ? model.split("/").pop() : model;
24254
- const cliContext = {
24255
- platform: platform7(),
24256
- shell: getShellConfig().name,
24257
- cwd: process.cwd(),
24258
- cliVersion: CLI_VERSION,
24259
- nativeModules: getNativeModules().map((m) => m.name),
24260
- installedModules: Object.keys(readModulesManifest())
24261
- };
24262
- let sessionId = resumeSessionId || randomUUID4().slice(0, 8);
24263
- let sessionName = `session-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}`;
24264
- const usage = createUsageTracker();
24265
- const conversationMessages = [];
24266
- const history = [];
24267
- const memContext = buildMemoryContext();
24268
- if (memContext.trim()) {
24269
- conversationMessages.push({ role: "user", content: `[Context] ${memContext.trim()}` });
24270
- conversationMessages.push({ role: "assistant", content: "Got it, I have your preferences loaded." });
24308
+ return this.config.provider || "gemini";
24271
24309
  }
24272
- if (resumeSessionId) {
24273
- const session = loadSession(resumeSessionId);
24274
- if (session) {
24275
- sessionName = session.name;
24276
- for (const msg of session.messages) conversationMessages.push(msg);
24277
- if (session.usage) {
24278
- usage.promptTokens = session.usage.promptTokens || 0;
24279
- usage.completionTokens = session.usage.completionTokens || 0;
24280
- usage.totalTokens = session.usage.totalTokens || 0;
24281
- usage.requests = session.usage.requests || 0;
24282
- }
24283
- log(color.green(` Resumed: ${sessionName} (${session.messages.length} msgs)`));
24284
- }
24310
+ updateStatus() {
24311
+ const model = this.model.includes("/") ? this.model.split("/").pop() : this.model;
24312
+ const cost = this.usage.cost > 0 ? ` \xB7 $${this.usage.cost.toFixed(4)}` : "";
24313
+ const tokens = this.usage.totalTokens > 0 ? ` \xB7 ${this.usage.totalTokens.toLocaleString()} tokens` : "";
24314
+ this.ui?.setStatus(`${model} \xB7 ${getShellConfig().name} \xB7 ${this.autoAccept ? "auto" : "confirm"}${tokens}${cost}`);
24285
24315
  }
24286
- const modeStr = devMode ? "dev" : autoAccept ? "auto" : "confirm";
24287
- const cwdShort = process.cwd().replace(homedir8(), "~");
24288
- printBanner(modelShort, modeStr, cwdShort, getShellConfig().name);
24289
- try {
24290
- const entries = readdirSync6(process.cwd()).filter((e) => !e.startsWith("."));
24291
- let rpCount = 0, dirCount = 0;
24292
- for (const e of entries.slice(0, 100)) {
24293
- try {
24294
- const s = statSync6(join12(process.cwd(), e));
24295
- if (s.isDirectory() && !["node_modules", "__pycache__", "dist", "build"].includes(e)) dirCount++;
24296
- else if (e.endsWith(".rp") || e.endsWith(".robin")) rpCount++;
24297
- } catch {
24298
- }
24316
+ exit() {
24317
+ if (this.conversationMessages.length > 1) {
24318
+ saveSession(this.sessionId, this.sessionName, this.conversationMessages, this.usage);
24299
24319
  }
24300
- if (rpCount > 0 || dirCount > 0) log(color.dim(` ${rpCount} .rp file(s), ${dirCount} dir(s)`));
24301
- } catch {
24320
+ this.ui?.exit();
24302
24321
  }
24303
- let isFirst = !resumeSessionId && !initialPrompt;
24304
- while (true) {
24305
- let trimmed;
24306
- if (initialPrompt) {
24307
- trimmed = initialPrompt.trim();
24308
- initialPrompt = null;
24309
- log(color.cyan(" \u276F ") + trimmed);
24310
- } else {
24311
- const input = await collectInkInput(
24312
- isFirst ? "What do you want to automate?" : "Ask anything..."
24313
- );
24314
- isFirst = false;
24315
- if (input === null) {
24316
- exitWithSave();
24317
- break;
24318
- }
24319
- trimmed = input.trim();
24320
- if (!trimmed) continue;
24321
- log(color.cyan(" \u276F ") + color.bold(trimmed));
24322
- }
24323
- if (trimmed === "/") {
24324
- log("");
24325
- for (const [cmd, desc] of Object.entries(SLASH_CMDS)) {
24326
- log(` ${color.cyan(cmd.padEnd(14))} ${color.dim(desc)}`);
24327
- }
24328
- log("");
24329
- continue;
24322
+ async handleInput(text) {
24323
+ if (text === "/" || text === "/help") {
24324
+ const cmds = ["/model", "/shell", "/auto", "/clear", "/save", "/sessions", "/memory", "/usage", "exit"];
24325
+ this.ui?.addMessage("info", cmds.join(" "));
24326
+ return;
24330
24327
  }
24331
- if (trimmed === "exit" || trimmed === "quit") {
24332
- exitWithSave();
24333
- break;
24328
+ if (text === "/clear") {
24329
+ this.conversationMessages.length = 0;
24330
+ this.ui?.addMessage("info", "Cleared.");
24331
+ return;
24334
24332
  }
24335
- if (trimmed === "/help") {
24336
- log("");
24337
- for (const [cmd, desc] of Object.entries(SLASH_CMDS)) {
24338
- log(` ${color.cyan(cmd.padEnd(14))} ${color.dim(desc)}`);
24339
- }
24340
- log("");
24341
- continue;
24333
+ if (text === "/usage") {
24334
+ const c = this.usage.cost > 0 ? `$${this.usage.cost.toFixed(4)}` : "$0 (free)";
24335
+ this.ui?.addMessage("info", `${this.usage.totalTokens.toLocaleString()} tokens \xB7 ${this.usage.requests} requests \xB7 ${c}`);
24336
+ return;
24342
24337
  }
24343
- if (trimmed === "/clear") {
24344
- conversationMessages.length = 0;
24345
- log(color.green(" Cleared."));
24346
- continue;
24338
+ if (text === "/auto") {
24339
+ this.autoAccept = !this.autoAccept;
24340
+ this.ui?.addMessage("info", `Auto-accept: ${this.autoAccept ? "ON" : "OFF"}`);
24341
+ this.updateStatus();
24342
+ return;
24347
24343
  }
24348
- if (trimmed === "/usage") {
24349
- const cost = usage.cost > 0 ? `$${usage.cost.toFixed(4)}` : "$0.00 (free)";
24350
- log(` ${usage.totalTokens.toLocaleString()} tokens \xB7 ${usage.requests} requests \xB7 ${cost}`);
24351
- continue;
24344
+ if (text === "/model") {
24345
+ const hasKey = !!readAiConfig().apiKey;
24346
+ const models = hasKey ? AI_MODELS : AI_MODELS.filter((m) => !m.requiresKey);
24347
+ this.ui?.addMessage("info", models.map((m, i) => `${i + 1}. ${m.name} \u2014 ${m.desc}`).join("\n"));
24348
+ return;
24352
24349
  }
24353
- if (trimmed === "/model") {
24350
+ if (text.match(/^\/model \d+$/)) {
24354
24351
  const hasKey = !!readAiConfig().apiKey;
24355
24352
  const models = hasKey ? AI_MODELS : AI_MODELS.filter((m) => !m.requiresKey);
24356
- const cur = readAiConfig().model || model;
24357
- log("");
24358
- let lastGroup = "";
24359
- for (let i = 0; i < models.length; i++) {
24360
- const m = models[i];
24361
- if (m.group !== lastGroup) {
24362
- log(color.dim(` \u2500\u2500 ${m.group} \u2500\u2500`));
24363
- lastGroup = m.group;
24364
- }
24365
- const mark = m.id === cur ? color.green(" \u2713") : "";
24366
- log(` ${color.cyan(String(i + 1))}. ${m.name} ${color.dim("\u2014 " + m.desc)}${mark}`);
24367
- }
24368
- log("");
24369
- const answer = await collectInkInput("Enter number...");
24370
- if (answer) {
24371
- const idx = parseInt(answer, 10) - 1;
24372
- if (idx >= 0 && idx < models.length) {
24373
- config.model = models[idx].id;
24374
- writeAiConfig(config);
24375
- log(color.green(` Model: ${models[idx].id}`));
24376
- }
24353
+ const idx = parseInt(text.split(" ")[1], 10) - 1;
24354
+ if (idx >= 0 && idx < models.length) {
24355
+ this.config.model = models[idx].id;
24356
+ this.model = models[idx].id;
24357
+ writeAiConfig(this.config);
24358
+ this.ui?.addMessage("info", `Model: ${models[idx].id}`);
24359
+ this.updateStatus();
24377
24360
  }
24378
- continue;
24379
- }
24380
- if (trimmed === "/auto" || trimmed.startsWith("/auto ")) {
24381
- const arg = trimmed.slice(5).trim().toLowerCase();
24382
- if (arg === "on") autoAccept = true;
24383
- else if (arg === "off") autoAccept = false;
24384
- else autoAccept = !autoAccept;
24385
- log(` Auto-accept: ${autoAccept ? color.green("ON") : color.yellow("OFF")}`);
24386
- continue;
24361
+ return;
24387
24362
  }
24388
- if (trimmed === "/memory") {
24363
+ if (text === "/memory") {
24389
24364
  const mem = loadMemory();
24390
- if (mem.facts.length === 0) log(color.dim(" No memories."));
24391
- else mem.facts.forEach((f, i) => log(` ${i + 1}. ${f}`));
24392
- continue;
24393
- }
24394
- if (trimmed.startsWith("/remember ")) {
24395
- addMemoryFact(trimmed.slice(10).trim());
24396
- log(color.green(" Remembered."));
24397
- continue;
24398
- }
24399
- if (trimmed.startsWith("/forget ")) {
24400
- removeMemoryFact(parseInt(trimmed.slice(8).trim(), 10) - 1);
24401
- log(color.green(" Forgot."));
24402
- continue;
24403
- }
24404
- if (trimmed === "/save" || trimmed.startsWith("/save ")) {
24405
- if (trimmed.length > 5) sessionName = trimmed.slice(5).trim();
24406
- saveSession(sessionId, sessionName, conversationMessages, usage);
24407
- log(color.green(` Saved: ${sessionName}`));
24408
- continue;
24409
- }
24410
- if (trimmed === "/sessions") {
24411
- const sessions = listSessions();
24412
- if (sessions.length === 0) log(color.dim(" No sessions."));
24413
- else sessions.forEach((s) => log(` ${color.cyan(s.id)} ${s.name} ${color.dim(`${s.messages} msgs`)}`));
24414
- continue;
24415
- }
24416
- if (trimmed === "/shell") {
24417
- const shells = getAvailableShells();
24418
- shells.forEach((s) => {
24419
- const mark = s.current ? color.green(" \u2713") : s.available ? "" : color.dim(" (not found)");
24420
- log(` ${s.available ? color.cyan(s.name) : color.dim(s.name)}${mark}`);
24421
- });
24422
- continue;
24365
+ this.ui?.addMessage("info", mem.facts.length ? mem.facts.map((f, i) => `${i + 1}. ${f}`).join("\n") : "No memories.");
24366
+ return;
24423
24367
  }
24424
- if (trimmed.startsWith("/shell ")) {
24425
- setShellOverride(trimmed.slice(7).trim());
24426
- cliContext.shell = getShellConfig().name;
24427
- log(` Shell: ${color.cyan(getShellConfig().name)}`);
24428
- continue;
24368
+ if (text.startsWith("/save")) {
24369
+ if (text.length > 5) this.sessionName = text.slice(5).trim();
24370
+ saveSession(this.sessionId, this.sessionName, this.conversationMessages, this.usage);
24371
+ this.ui?.addMessage("info", `Saved: ${this.sessionName}`);
24372
+ return;
24429
24373
  }
24430
- if (trimmed.startsWith("/")) {
24431
- log(color.dim(` Unknown: ${trimmed}. Type / for commands.`));
24432
- continue;
24374
+ if (text.startsWith("/")) {
24375
+ this.ui?.addMessage("info", `Unknown: ${text}. Type / for help.`);
24376
+ return;
24433
24377
  }
24434
- const { expanded } = expandFileRefs(trimmed);
24435
- conversationMessages.push({ role: "user", content: expanded });
24436
- await autoCompact(conversationMessages);
24437
- const activeModel = readAiConfig().model || model;
24438
- const activeKey = readAiConfig().apiKey || apiKey;
24439
- const activeProvider = resolveProvider(activeKey);
24440
- let spinner = createSpinner("Thinking");
24378
+ this.ui?.addMessage("user", text);
24379
+ this.ui?.setLoading(true);
24380
+ this.ui?.setStreaming("");
24381
+ this.ui?.setLoadingLabel("Thinking");
24441
24382
  try {
24383
+ const { expanded } = expandFileRefs(text);
24384
+ this.conversationMessages.push({ role: "user", content: expanded });
24385
+ await autoCompact(this.conversationMessages);
24386
+ const activeModel = readAiConfig().model || this.model;
24387
+ const activeKey = readAiConfig().apiKey || this.apiKey;
24388
+ const activeProvider = this.resolveProvider(activeKey);
24389
+ let fullResponse = "";
24442
24390
  for (let loop = 0; loop < 15; loop++) {
24443
- let pending = "";
24444
- let insideMemory = false;
24445
- let insideCmd = false;
24391
+ this.ui?.setLoadingLabel(loop === 0 ? "Thinking" : "Processing");
24392
+ fullResponse = "";
24446
24393
  const result = await fetchBrainStream(
24447
- loop === 0 ? expanded : conversationMessages[conversationMessages.length - 1].content,
24394
+ loop === 0 ? expanded : this.conversationMessages[this.conversationMessages.length - 1].content,
24448
24395
  {
24449
24396
  onToken: (delta) => {
24450
- spinner.stop();
24451
24397
  if (delta === "\x1B[RETRY]") {
24452
- pending = "";
24453
- insideMemory = false;
24454
- insideCmd = false;
24455
- spinner = createSpinner("Retrying");
24398
+ fullResponse = "";
24399
+ this.ui?.setStreaming("");
24456
24400
  return;
24457
24401
  }
24458
- pending += delta;
24459
- while (true) {
24460
- if (insideMemory) {
24461
- const ci2 = pending.indexOf("</memory>");
24462
- if (ci2 === -1) break;
24463
- const fact = pending.slice(0, ci2).trim();
24464
- if (fact.length > 3 && fact.length < 300) addMemoryFact(fact);
24465
- pending = pending.slice(ci2 + 9);
24466
- insideMemory = false;
24467
- continue;
24468
- }
24469
- if (insideCmd) {
24470
- const ci2 = pending.indexOf("</cmd>");
24471
- if (ci2 === -1) break;
24472
- pending = pending.slice(ci2 + 6);
24473
- insideCmd = false;
24474
- continue;
24475
- }
24476
- const mi = pending.indexOf("<memory>");
24477
- const ci = pending.indexOf("<cmd>");
24478
- if (mi === -1 && ci === -1) {
24479
- const lt2 = pending.lastIndexOf("<");
24480
- if (lt2 !== -1 && lt2 > pending.length - 9) {
24481
- if (lt2 > 0) {
24482
- process.stdout.write(pending.slice(0, lt2).replace(/\n{3,}/g, "\n\n"));
24483
- pending = pending.slice(lt2);
24484
- }
24485
- } else {
24486
- process.stdout.write(pending.replace(/\n{3,}/g, "\n\n"));
24487
- pending = "";
24488
- }
24489
- break;
24490
- }
24491
- const first = mi === -1 ? ci : ci === -1 ? mi : Math.min(mi, ci);
24492
- if (first > 0) process.stdout.write(pending.slice(0, first).replace(/\n{3,}/g, "\n\n"));
24493
- if (first === mi) {
24494
- pending = pending.slice(first + 8);
24495
- insideMemory = true;
24496
- } else {
24497
- pending = pending.slice(first + 5);
24498
- insideCmd = true;
24499
- }
24500
- }
24402
+ fullResponse += delta;
24403
+ const clean = fullResponse.replace(/<memory>[\s\S]*?<\/memory>/g, "").replace(/<cmd>[\s\S]*?<\/cmd>/g, "").replace(/\n{3,}/g, "\n\n").trim();
24404
+ this.ui?.setStreaming(clean);
24501
24405
  },
24502
- conversationHistory: conversationMessages.slice(0, -1),
24406
+ conversationHistory: this.conversationMessages.slice(0, -1),
24503
24407
  provider: activeProvider,
24504
24408
  model: activeModel,
24505
24409
  apiKey: activeKey,
24506
- cliContext
24410
+ cliContext: this.cliContext
24507
24411
  }
24508
24412
  );
24509
- if (pending && !insideMemory && !insideCmd) process.stdout.write(pending);
24510
24413
  if (!result || !result.code) {
24511
- spinner.stop();
24512
- log(color.red("\n No response."));
24414
+ this.ui?.addMessage("assistant", fullResponse || "No response. Check connection or API key.");
24513
24415
  break;
24514
24416
  }
24515
24417
  if (result.usage) {
24516
24418
  const pt2 = result.usage.prompt_tokens || 0;
24517
24419
  const ct2 = result.usage.completion_tokens || 0;
24518
- usage.promptTokens += pt2;
24519
- usage.completionTokens += ct2;
24520
- usage.totalTokens += pt2 + ct2;
24521
- usage.requests++;
24522
- usage.cost += estimateCost(activeModel, pt2, ct2);
24420
+ this.usage.promptTokens += pt2;
24421
+ this.usage.completionTokens += ct2;
24422
+ this.usage.totalTokens += pt2 + ct2;
24423
+ this.usage.requests++;
24424
+ this.usage.cost += estimateCost(activeModel, pt2, ct2);
24425
+ this.updateStatus();
24523
24426
  }
24524
- const commands = extractCommands(result.code);
24525
24427
  const { cleaned } = extractMemoryTags(stripCommandTags(result.code));
24526
- process.stdout.write("\n");
24527
- if (cleaned) conversationMessages.push({ role: "assistant", content: cleaned });
24528
- if (commands.length === 0) break;
24428
+ const commands = extractCommands(result.code);
24429
+ if (cleaned) {
24430
+ this.conversationMessages.push({ role: "assistant", content: cleaned });
24431
+ }
24432
+ if (commands.length === 0) {
24433
+ if (cleaned) this.ui?.addMessage("assistant", cleaned);
24434
+ break;
24435
+ }
24436
+ if (cleaned) this.ui?.addMessage("assistant", cleaned);
24529
24437
  const cmdResults = [];
24530
24438
  for (const cmd of commands) {
24531
- const decision = await confirmCommand(cmd, autoAccept);
24532
- if (decision === "no") {
24533
- cmdResults.push({ command: cmd, stdout: "", stderr: "(skipped)", exitCode: -1 });
24534
- continue;
24535
- }
24536
- if (decision === "auto") {
24537
- autoAccept = true;
24538
- log(color.green(" Auto-accept ON"));
24539
- }
24439
+ this.ui?.addMessage("info", `$ ${cmd.split("\n")[0]}${cmd.includes("\n") ? ` (+${cmd.split("\n").length - 1} lines)` : ""}`);
24540
24440
  const r = await executeShellCommand(cmd);
24541
- if (r.exitCode !== 0) log(color.red(` exit ${r.exitCode}: ${(r.stderr || "").slice(0, 80)}`));
24441
+ if (r.exitCode === 0 && r.stdout?.trim()) {
24442
+ this.ui?.addMessage("info", r.stdout.trim().split("\n").slice(0, 5).join("\n"));
24443
+ } else if (r.exitCode !== 0) {
24444
+ this.ui?.addMessage("info", `exit ${r.exitCode}: ${(r.stderr || "").slice(0, 100)}`);
24445
+ }
24542
24446
  cmdResults.push({ command: cmd, stdout: r.stdout || "", stderr: r.stderr || "", exitCode: r.exitCode });
24543
24447
  }
24544
24448
  const summary = cmdResults.map((r) => {
@@ -24552,59 +24456,44 @@ async function startInkREPL(initialPrompt, resumeSessionId, opts = {}) {
24552
24456
  }
24553
24457
  return o;
24554
24458
  }).join("\n\n");
24555
- conversationMessages.push({ role: "user", content: `[Command results]
24459
+ this.conversationMessages.push({ role: "user", content: `[Command results]
24556
24460
  ${summary}` });
24557
- spinner = createSpinner("Processing");
24461
+ this.ui?.setStreaming("");
24558
24462
  }
24559
24463
  } catch (err) {
24560
- spinner.stop();
24561
- log(color.red(` Error: ${err.message}`));
24464
+ this.ui?.addMessage("info", `Error: ${err.message}`);
24465
+ } finally {
24466
+ this.ui?.setLoading(false);
24467
+ this.ui?.setStreaming("");
24468
+ saveSession(this.sessionId, this.sessionName, this.conversationMessages, this.usage);
24562
24469
  }
24563
- log("");
24564
- if (usage.cost > 0) log(color.dim(` $${usage.cost.toFixed(4)} \xB7 ${usage.totalTokens.toLocaleString()} tokens`));
24565
24470
  }
24566
- function exitWithSave() {
24567
- if (conversationMessages.length > 1) {
24568
- saveSession(sessionId, sessionName, conversationMessages, usage);
24569
- log(color.dim(` Session saved: ${sessionId}`));
24570
- }
24571
- log(color.dim(" Goodbye!"));
24572
- process.exit(0);
24573
- }
24574
- process.on("SIGINT", () => {
24575
- log("");
24576
- exitWithSave();
24577
- });
24578
- }
24579
- var SLASH_CMDS = {
24580
- "/help": "Show commands",
24581
- "/model": "Switch AI model",
24582
- "/shell": "Switch shell",
24583
- "/auto": "Toggle auto-accept",
24584
- "/clear": "Clear conversation",
24585
- "/save": "Save session",
24586
- "/sessions": "List sessions",
24587
- "/memory": "Show memory",
24588
- "/remember": "Save a fact",
24589
- "/forget": "Remove a memory",
24590
- "/usage": "Token usage & cost",
24591
- "exit": "Quit"
24592
24471
  };
24472
+ async function startInkREPL(initialPrompt, resumeSessionId, opts = {}) {
24473
+ const engine = new ReplEngine(resumeSessionId, opts);
24474
+ const { waitUntilExit } = render(/* @__PURE__ */ jsx(App, { engine }));
24475
+ await new Promise((r) => setTimeout(r, 100));
24476
+ engine.updateStatus();
24477
+ if (initialPrompt) {
24478
+ await engine.handleInput(initialPrompt);
24479
+ }
24480
+ await waitUntilExit();
24481
+ }
24593
24482
 
24594
24483
  // src/commands-modules.ts
24595
24484
  import { createInterface as createInterface3 } from "node:readline";
24596
24485
  import {
24597
- readFileSync as readFileSync11,
24598
- existsSync as existsSync12,
24486
+ readFileSync as readFileSync10,
24487
+ existsSync as existsSync11,
24599
24488
  mkdirSync as mkdirSync6,
24600
24489
  copyFileSync as copyFileSync2,
24601
24490
  rmSync as rmSync2,
24602
24491
  writeFileSync as writeFileSync6,
24603
- readdirSync as readdirSync7,
24604
- statSync as statSync7,
24492
+ readdirSync as readdirSync6,
24493
+ statSync as statSync6,
24605
24494
  unlinkSync as unlinkSync5
24606
24495
  } from "node:fs";
24607
- import { resolve as resolve8, join as join13, dirname as dirname4, basename as basename4 } from "node:path";
24496
+ import { resolve as resolve8, join as join12, dirname as dirname4, basename as basename4 } from "node:path";
24608
24497
  import { execSync as execSync2 } from "node:child_process";
24609
24498
  import { homedir as homedir9, platform as platform8, tmpdir as tmpdir3 } from "node:os";
24610
24499
  import { createHash as createHash3 } from "node:crypto";
@@ -24695,17 +24584,17 @@ async function handleAdd(args) {
24695
24584
  process.exit(1);
24696
24585
  }
24697
24586
  const integrity = "sha256-" + createHash3("sha256").update(tarballBuffer).digest("hex");
24698
- if (!existsSync12(CACHE_DIR)) {
24587
+ if (!existsSync11(CACHE_DIR)) {
24699
24588
  mkdirSync6(CACHE_DIR, { recursive: true });
24700
24589
  }
24701
- const cacheFile = join13(CACHE_DIR, `${scope}-${name}-${resolvedVersion}.tar.gz`);
24590
+ const cacheFile = join12(CACHE_DIR, `${scope}-${name}-${resolvedVersion}.tar.gz`);
24702
24591
  writeFileSync6(cacheFile, tarballBuffer);
24703
24592
  const modDir = getModulePath(fullName);
24704
- if (existsSync12(modDir)) {
24593
+ if (existsSync11(modDir)) {
24705
24594
  rmSync2(modDir, { recursive: true, force: true });
24706
24595
  }
24707
24596
  mkdirSync6(modDir, { recursive: true });
24708
- const tmpFile = join13(tmpdir3(), `robinpath-add-${Date.now()}.tar.gz`);
24597
+ const tmpFile = join12(tmpdir3(), `robinpath-add-${Date.now()}.tar.gz`);
24709
24598
  writeFileSync6(tmpFile, tarballBuffer);
24710
24599
  try {
24711
24600
  execSync2(`tar xzf "${toTarPath(tmpFile)}" --strip-components=1 -C "${toTarPath(modDir)}"`, { stdio: "pipe" });
@@ -24722,15 +24611,15 @@ async function handleAdd(args) {
24722
24611
  unlinkSync5(tmpFile);
24723
24612
  } catch {
24724
24613
  }
24725
- const distDir = join13(modDir, "dist");
24726
- const srcDir = join13(modDir, "src");
24727
- if (!existsSync12(distDir) && existsSync12(srcDir) && existsSync12(join13(srcDir, "index.ts"))) {
24614
+ const distDir = join12(modDir, "dist");
24615
+ const srcDir = join12(modDir, "src");
24616
+ if (!existsSync11(distDir) && existsSync11(srcDir) && existsSync11(join12(srcDir, "index.ts"))) {
24728
24617
  log(color.dim(" Compiling module..."));
24729
24618
  mkdirSync6(distDir, { recursive: true });
24730
- const tsFiles = readdirSync7(srcDir).filter((f) => f.endsWith(".ts"));
24619
+ const tsFiles = readdirSync6(srcDir).filter((f) => f.endsWith(".ts"));
24731
24620
  for (const file of tsFiles) {
24732
- const srcFile = join13(srcDir, file);
24733
- const outFile = join13(distDir, file.replace(".ts", ".js"));
24621
+ const srcFile = join12(srcDir, file);
24622
+ const outFile = join12(distDir, file.replace(".ts", ".js"));
24734
24623
  try {
24735
24624
  const stripScript = `
24736
24625
  const fs = require('fs');
@@ -24746,17 +24635,17 @@ async function handleAdd(args) {
24746
24635
  }
24747
24636
  }
24748
24637
  let installedVersion = resolvedVersion;
24749
- const pkgJsonPath = join13(modDir, "package.json");
24750
- if (existsSync12(pkgJsonPath)) {
24638
+ const pkgJsonPath = join12(modDir, "package.json");
24639
+ if (existsSync11(pkgJsonPath)) {
24751
24640
  try {
24752
- const pkg = JSON.parse(readFileSync11(pkgJsonPath, "utf-8"));
24641
+ const pkg = JSON.parse(readFileSync10(pkgJsonPath, "utf-8"));
24753
24642
  installedVersion = pkg.version || installedVersion;
24754
24643
  } catch {
24755
24644
  }
24756
24645
  }
24757
- if (existsSync12(pkgJsonPath)) {
24646
+ if (existsSync11(pkgJsonPath)) {
24758
24647
  try {
24759
- const pkg = JSON.parse(readFileSync11(pkgJsonPath, "utf-8"));
24648
+ const pkg = JSON.parse(readFileSync10(pkgJsonPath, "utf-8"));
24760
24649
  const depends = pkg.robinpath?.depends || [];
24761
24650
  for (const dep of depends) {
24762
24651
  if (!manifest[dep]) {
@@ -24775,9 +24664,9 @@ async function handleAdd(args) {
24775
24664
  };
24776
24665
  writeModulesManifest(updatedManifest);
24777
24666
  const projectFile = resolve8("robinpath.json");
24778
- if (existsSync12(projectFile)) {
24667
+ if (existsSync11(projectFile)) {
24779
24668
  try {
24780
- const config = JSON.parse(readFileSync11(projectFile, "utf-8"));
24669
+ const config = JSON.parse(readFileSync10(projectFile, "utf-8"));
24781
24670
  if (!config.modules) config.modules = {};
24782
24671
  config.modules[fullName] = `^${installedVersion}`;
24783
24672
  writeFileSync6(projectFile, JSON.stringify(config, null, 2) + "\n", "utf-8");
@@ -24805,12 +24694,12 @@ async function handleRemove(args) {
24805
24694
  process.exit(1);
24806
24695
  }
24807
24696
  const modDir = getModulePath(fullName);
24808
- if (existsSync12(modDir)) {
24697
+ if (existsSync11(modDir)) {
24809
24698
  rmSync2(modDir, { recursive: true, force: true });
24810
24699
  }
24811
24700
  const scopeDir = dirname4(modDir);
24812
24701
  try {
24813
- const remaining = readdirSync7(scopeDir);
24702
+ const remaining = readdirSync6(scopeDir);
24814
24703
  if (remaining.length === 0) {
24815
24704
  rmSync2(scopeDir, { recursive: true, force: true });
24816
24705
  }
@@ -24819,9 +24708,9 @@ async function handleRemove(args) {
24819
24708
  delete manifest[fullName];
24820
24709
  writeModulesManifest(manifest);
24821
24710
  const projectFile = resolve8("robinpath.json");
24822
- if (existsSync12(projectFile)) {
24711
+ if (existsSync11(projectFile)) {
24823
24712
  try {
24824
- const config = JSON.parse(readFileSync11(projectFile, "utf-8"));
24713
+ const config = JSON.parse(readFileSync10(projectFile, "utf-8"));
24825
24714
  if (config.modules && config.modules[fullName]) {
24826
24715
  delete config.modules[fullName];
24827
24716
  writeFileSync6(projectFile, JSON.stringify(config, null, 2) + "\n", "utf-8");
@@ -24994,14 +24883,14 @@ async function handleModulesInit() {
24994
24883
  const targetDir = resolve8(moduleName);
24995
24884
  log("");
24996
24885
  log(`Creating ${color.cyan(fullName)}...`);
24997
- if (existsSync12(targetDir)) {
24886
+ if (existsSync11(targetDir)) {
24998
24887
  console.error(color.red("Error:") + ` Directory already exists: ${moduleName}/`);
24999
24888
  process.exit(1);
25000
24889
  }
25001
- mkdirSync6(join13(targetDir, "src"), { recursive: true });
25002
- mkdirSync6(join13(targetDir, "tests"), { recursive: true });
24890
+ mkdirSync6(join12(targetDir, "src"), { recursive: true });
24891
+ mkdirSync6(join12(targetDir, "tests"), { recursive: true });
25003
24892
  writeFileSync6(
25004
- join13(targetDir, "package.json"),
24893
+ join12(targetDir, "package.json"),
25005
24894
  JSON.stringify(
25006
24895
  {
25007
24896
  name: fullName,
@@ -25025,7 +24914,7 @@ async function handleModulesInit() {
25025
24914
  "utf-8"
25026
24915
  );
25027
24916
  writeFileSync6(
25028
- join13(targetDir, "src", "index.ts"),
24917
+ join12(targetDir, "src", "index.ts"),
25029
24918
  `import type { ModuleAdapter } from "@wiredwp/robinpath";
25030
24919
  import {
25031
24920
  ${pascalName}Functions,
@@ -25047,7 +24936,7 @@ export { ${pascalName}Module };
25047
24936
  "utf-8"
25048
24937
  );
25049
24938
  writeFileSync6(
25050
- join13(targetDir, "src", `${moduleName}.ts`),
24939
+ join12(targetDir, "src", `${moduleName}.ts`),
25051
24940
  `import type {
25052
24941
  BuiltinHandler,
25053
24942
  FunctionMetadata,
@@ -25118,7 +25007,7 @@ export const ${pascalName}ModuleMetadata: ModuleMetadata = {
25118
25007
  "utf-8"
25119
25008
  );
25120
25009
  writeFileSync6(
25121
- join13(targetDir, "tsconfig.json"),
25010
+ join12(targetDir, "tsconfig.json"),
25122
25011
  JSON.stringify(
25123
25012
  {
25124
25013
  compilerOptions: {
@@ -25142,7 +25031,7 @@ export const ${pascalName}ModuleMetadata: ModuleMetadata = {
25142
25031
  "utf-8"
25143
25032
  );
25144
25033
  writeFileSync6(
25145
- join13(targetDir, "tests", `${moduleName}.test.rp`),
25034
+ join12(targetDir, "tests", `${moduleName}.test.rp`),
25146
25035
  `# ${displayName} module tests
25147
25036
  # Run: robinpath test tests/
25148
25037
 
@@ -25161,7 +25050,7 @@ enddo
25161
25050
  "utf-8"
25162
25051
  );
25163
25052
  writeFileSync6(
25164
- join13(targetDir, "README.md"),
25053
+ join12(targetDir, "README.md"),
25165
25054
  `# ${fullName}
25166
25055
 
25167
25056
  ${description}
@@ -25205,7 +25094,7 @@ ${license}
25205
25094
  "utf-8"
25206
25095
  );
25207
25096
  writeFileSync6(
25208
- join13(targetDir, ".gitignore"),
25097
+ join12(targetDir, ".gitignore"),
25209
25098
  `node_modules/
25210
25099
  dist/
25211
25100
  *.tgz
@@ -25235,14 +25124,14 @@ dist/
25235
25124
  async function handlePack(args) {
25236
25125
  const targetArg = args.find((a) => !a.startsWith("-")) || ".";
25237
25126
  const targetDir = resolve8(targetArg);
25238
- const pkgPath = join13(targetDir, "package.json");
25239
- if (!existsSync12(pkgPath)) {
25127
+ const pkgPath = join12(targetDir, "package.json");
25128
+ if (!existsSync11(pkgPath)) {
25240
25129
  console.error(color.red("Error:") + ` No package.json found in ${targetDir}`);
25241
25130
  process.exit(2);
25242
25131
  }
25243
25132
  let pkg;
25244
25133
  try {
25245
- pkg = JSON.parse(readFileSync11(pkgPath, "utf-8"));
25134
+ pkg = JSON.parse(readFileSync10(pkgPath, "utf-8"));
25246
25135
  } catch (err) {
25247
25136
  console.error(color.red("Error:") + ` Invalid package.json: ${err.message}`);
25248
25137
  process.exit(2);
@@ -25263,12 +25152,12 @@ async function handlePack(args) {
25263
25152
  { stdio: "pipe" }
25264
25153
  );
25265
25154
  } catch (err) {
25266
- if (!existsSync12(outputPath)) {
25155
+ if (!existsSync11(outputPath)) {
25267
25156
  console.error(color.red("Error:") + ` Failed to create tarball: ${err.message}`);
25268
25157
  process.exit(1);
25269
25158
  }
25270
25159
  }
25271
- const size = statSync7(outputPath).size;
25160
+ const size = statSync6(outputPath).size;
25272
25161
  log(color.green("Created") + ` ${outputFile} (${(size / 1024).toFixed(1)}KB)`);
25273
25162
  }
25274
25163
  function formatCompactNumber(n) {
@@ -25417,9 +25306,9 @@ async function handleInfo(args) {
25417
25306
  path: getModulePath(packageName)
25418
25307
  };
25419
25308
  try {
25420
- const pkgPath = join13(getModulePath(packageName), "package.json");
25421
- if (existsSync12(pkgPath)) {
25422
- const pkg = JSON.parse(readFileSync11(pkgPath, "utf-8"));
25309
+ const pkgPath = join12(getModulePath(packageName), "package.json");
25310
+ if (existsSync11(pkgPath)) {
25311
+ const pkg = JSON.parse(readFileSync10(pkgPath, "utf-8"));
25423
25312
  if (pkg.description) entry.description = pkg.description;
25424
25313
  if (pkg.keywords) entry.keywords = pkg.keywords;
25425
25314
  }
@@ -25443,9 +25332,9 @@ async function handleInfo(args) {
25443
25332
  modules_manifest: MODULES_MANIFEST,
25444
25333
  cache: CACHE_DIR,
25445
25334
  auth: getAuthPath(),
25446
- history: join13(homedir9(), ".robinpath", "history"),
25447
- env: join13(homedir9(), ".robinpath", "env"),
25448
- docs: join13(getRobinPathHome(), "DOCUMENTATION.md")
25335
+ history: join12(homedir9(), ".robinpath", "history"),
25336
+ env: join12(homedir9(), ".robinpath", "env"),
25337
+ docs: join12(getRobinPathHome(), "DOCUMENTATION.md")
25449
25338
  },
25450
25339
  native_modules: modulesInfo,
25451
25340
  installed_modules: installedModulesInfo,
@@ -25834,14 +25723,14 @@ async function handleInfo(args) {
25834
25723
  }
25835
25724
 
25836
25725
  // src/commands-project.ts
25837
- import { readFileSync as readFileSync12, existsSync as existsSync13, mkdirSync as mkdirSync7, writeFileSync as writeFileSync7, readdirSync as readdirSync8, statSync as statSync8, rmSync as rmSync3, chmodSync as chmodSync3 } from "node:fs";
25838
- import { resolve as resolve9, join as join14, basename as basename5 } from "node:path";
25726
+ import { readFileSync as readFileSync11, existsSync as existsSync12, mkdirSync as mkdirSync7, writeFileSync as writeFileSync7, readdirSync as readdirSync7, statSync as statSync7, rmSync as rmSync3, chmodSync as chmodSync3 } from "node:fs";
25727
+ import { resolve as resolve9, join as join13, basename as basename5 } from "node:path";
25839
25728
  import { createInterface as createInterface4 } from "node:readline";
25840
25729
  import { platform as platform9 } from "node:os";
25841
25730
  var PLATFORM_URL3 = process.env.ROBINPATH_PLATFORM_URL || "https://api.robinpath.com";
25842
25731
  async function handleInit(args) {
25843
25732
  const projectFile = resolve9("robinpath.json");
25844
- if (existsSync13(projectFile) && !args.includes("--force")) {
25733
+ if (existsSync12(projectFile) && !args.includes("--force")) {
25845
25734
  console.error(color.red("Error:") + " robinpath.json already exists. Use --force to overwrite.");
25846
25735
  process.exit(1);
25847
25736
  }
@@ -25872,7 +25761,7 @@ async function handleInit(args) {
25872
25761
  };
25873
25762
  writeFileSync7(projectFile, JSON.stringify(config, null, 2) + "\n", "utf-8");
25874
25763
  const mainPath = resolve9(mainFile);
25875
- if (!existsSync13(mainPath)) {
25764
+ if (!existsSync12(mainPath)) {
25876
25765
  writeFileSync7(
25877
25766
  mainPath,
25878
25767
  `# ${projectName}
@@ -25883,7 +25772,7 @@ log "Hello from RobinPath!"
25883
25772
  "utf-8"
25884
25773
  );
25885
25774
  }
25886
- if (!existsSync13(resolve9(".env"))) {
25775
+ if (!existsSync12(resolve9(".env"))) {
25887
25776
  writeFileSync7(
25888
25777
  resolve9(".env"),
25889
25778
  `# Add your secrets here
@@ -25893,7 +25782,7 @@ log "Hello from RobinPath!"
25893
25782
  "utf-8"
25894
25783
  );
25895
25784
  }
25896
- if (!existsSync13(resolve9(".gitignore"))) {
25785
+ if (!existsSync12(resolve9(".gitignore"))) {
25897
25786
  writeFileSync7(
25898
25787
  resolve9(".gitignore"),
25899
25788
  `.env
@@ -25906,7 +25795,7 @@ node_modules/
25906
25795
  log("");
25907
25796
  log(color.green("Created project:"));
25908
25797
  log(` robinpath.json`);
25909
- if (!existsSync13(mainPath)) log(` ${mainFile}`);
25798
+ if (!existsSync12(mainPath)) log(` ${mainFile}`);
25910
25799
  log(` .env`);
25911
25800
  log(` .gitignore`);
25912
25801
  log("");
@@ -25915,13 +25804,13 @@ node_modules/
25915
25804
  }
25916
25805
  async function handleProjectInstall() {
25917
25806
  const projectFile = resolve9("robinpath.json");
25918
- if (!existsSync13(projectFile)) {
25807
+ if (!existsSync12(projectFile)) {
25919
25808
  handleInstall();
25920
25809
  return;
25921
25810
  }
25922
25811
  let config;
25923
25812
  try {
25924
- config = JSON.parse(readFileSync12(projectFile, "utf-8"));
25813
+ config = JSON.parse(readFileSync11(projectFile, "utf-8"));
25925
25814
  } catch (err) {
25926
25815
  console.error(color.red("Error:") + ` Invalid robinpath.json: ${err.message}`);
25927
25816
  process.exit(2);
@@ -25992,7 +25881,7 @@ async function handleDoctor() {
25992
25881
  const installDir = getInstallDir();
25993
25882
  const isWindows = platform9() === "win32";
25994
25883
  const binaryName = isWindows ? "robinpath.exe" : "robinpath";
25995
- if (existsSync13(join14(installDir, binaryName))) {
25884
+ if (existsSync12(join13(installDir, binaryName))) {
25996
25885
  log(color.green(" \u2713") + ` Installed: ${installDir}`);
25997
25886
  } else {
25998
25887
  log(color.yellow(" !") + ` Not installed to PATH. Run ${color.cyan("robinpath install")}`);
@@ -26019,21 +25908,21 @@ async function handleDoctor() {
26019
25908
  log(color.green(" \u2713") + ` ${moduleCount} module${moduleCount !== 1 ? "s" : ""} installed`);
26020
25909
  for (const [name, info] of Object.entries(manifest)) {
26021
25910
  const modDir = getModulePath(name);
26022
- const pkgPath = join14(modDir, "package.json");
26023
- if (!existsSync13(modDir)) {
25911
+ const pkgPath = join13(modDir, "package.json");
25912
+ if (!existsSync12(modDir)) {
26024
25913
  log(color.red(" \u2717") + ` ${name}: directory missing`);
26025
25914
  issues++;
26026
- } else if (!existsSync13(pkgPath)) {
25915
+ } else if (!existsSync12(pkgPath)) {
26027
25916
  log(color.red(" \u2717") + ` ${name}: package.json missing`);
26028
25917
  issues++;
26029
25918
  } else {
26030
25919
  let entryPoint = "dist/index.js";
26031
25920
  try {
26032
- const pkg = JSON.parse(readFileSync12(pkgPath, "utf-8"));
25921
+ const pkg = JSON.parse(readFileSync11(pkgPath, "utf-8"));
26033
25922
  if (pkg.main) entryPoint = pkg.main;
26034
25923
  } catch {
26035
25924
  }
26036
- if (!existsSync13(join14(modDir, entryPoint))) {
25925
+ if (!existsSync12(join13(modDir, entryPoint))) {
26037
25926
  log(color.red(" \u2717") + ` ${name}: entry point ${entryPoint} missing`);
26038
25927
  issues++;
26039
25928
  }
@@ -26043,9 +25932,9 @@ async function handleDoctor() {
26043
25932
  log(color.dim(" -") + ` No modules installed`);
26044
25933
  }
26045
25934
  const projectFile = resolve9("robinpath.json");
26046
- if (existsSync13(projectFile)) {
25935
+ if (existsSync12(projectFile)) {
26047
25936
  try {
26048
- const config = JSON.parse(readFileSync12(projectFile, "utf-8"));
25937
+ const config = JSON.parse(readFileSync11(projectFile, "utf-8"));
26049
25938
  log(color.green(" \u2713") + ` Project: ${config.name || "unnamed"} v${config.version || "?"}`);
26050
25939
  const projectModules = Object.keys(config.modules || {});
26051
25940
  for (const mod of projectModules) {
@@ -26059,12 +25948,12 @@ async function handleDoctor() {
26059
25948
  issues++;
26060
25949
  }
26061
25950
  }
26062
- if (existsSync13(CACHE_DIR)) {
25951
+ if (existsSync12(CACHE_DIR)) {
26063
25952
  try {
26064
- const cacheFiles = readdirSync8(CACHE_DIR);
25953
+ const cacheFiles = readdirSync7(CACHE_DIR);
26065
25954
  const cacheSize = cacheFiles.reduce((total, f) => {
26066
25955
  try {
26067
- return total + statSync8(join14(CACHE_DIR, f)).size;
25956
+ return total + statSync7(join13(CACHE_DIR, f)).size;
26068
25957
  } catch {
26069
25958
  return total;
26070
25959
  }
@@ -26082,12 +25971,12 @@ async function handleDoctor() {
26082
25971
  log("");
26083
25972
  }
26084
25973
  async function handleEnv(args) {
26085
- const envPath = join14(getRobinPathHome(), "env");
25974
+ const envPath = join13(getRobinPathHome(), "env");
26086
25975
  const sub = args[0];
26087
25976
  function readEnvFile() {
26088
25977
  try {
26089
- if (!existsSync13(envPath)) return {};
26090
- const lines = readFileSync12(envPath, "utf-8").split("\n");
25978
+ if (!existsSync12(envPath)) return {};
25979
+ const lines = readFileSync11(envPath, "utf-8").split("\n");
26091
25980
  const env = {};
26092
25981
  for (const line of lines) {
26093
25982
  const trimmed = line.trim();
@@ -26104,7 +25993,7 @@ async function handleEnv(args) {
26104
25993
  }
26105
25994
  function writeEnvFile(env) {
26106
25995
  const dir = getRobinPathHome();
26107
- if (!existsSync13(dir)) mkdirSync7(dir, { recursive: true });
25996
+ if (!existsSync12(dir)) mkdirSync7(dir, { recursive: true });
26108
25997
  const content = Object.entries(env).map(([k2, v]) => `${k2}=${v}`).join("\n") + "\n";
26109
25998
  writeFileSync7(envPath, content, "utf-8");
26110
25999
  if (platform9() !== "win32") {
@@ -26168,12 +26057,12 @@ async function handleEnv(args) {
26168
26057
  async function handleCache(args) {
26169
26058
  const sub = args[0];
26170
26059
  if (sub === "list") {
26171
- if (!existsSync13(CACHE_DIR)) {
26060
+ if (!existsSync12(CACHE_DIR)) {
26172
26061
  log("Cache is empty.");
26173
26062
  return;
26174
26063
  }
26175
26064
  try {
26176
- const files = readdirSync8(CACHE_DIR);
26065
+ const files = readdirSync7(CACHE_DIR);
26177
26066
  if (files.length === 0) {
26178
26067
  log("Cache is empty.");
26179
26068
  return;
@@ -26183,7 +26072,7 @@ async function handleCache(args) {
26183
26072
  log(color.dim(" " + "\u2500".repeat(50)));
26184
26073
  let totalSize = 0;
26185
26074
  for (const file of files) {
26186
- const size = statSync8(join14(CACHE_DIR, file)).size;
26075
+ const size = statSync7(join13(CACHE_DIR, file)).size;
26187
26076
  totalSize += size;
26188
26077
  log(` ${file.padEnd(45)} ${color.dim((size / 1024).toFixed(1) + "KB")}`);
26189
26078
  }
@@ -26199,15 +26088,15 @@ async function handleCache(args) {
26199
26088
  process.exit(1);
26200
26089
  }
26201
26090
  } else if (sub === "clean") {
26202
- if (!existsSync13(CACHE_DIR)) {
26091
+ if (!existsSync12(CACHE_DIR)) {
26203
26092
  log("Cache is already empty.");
26204
26093
  return;
26205
26094
  }
26206
26095
  try {
26207
- const files = readdirSync8(CACHE_DIR);
26096
+ const files = readdirSync7(CACHE_DIR);
26208
26097
  let totalSize = 0;
26209
26098
  for (const file of files) {
26210
- totalSize += statSync8(join14(CACHE_DIR, file)).size;
26099
+ totalSize += statSync7(join13(CACHE_DIR, file)).size;
26211
26100
  }
26212
26101
  rmSync3(CACHE_DIR, { recursive: true, force: true });
26213
26102
  log(
@@ -26322,8 +26211,8 @@ async function handleDeprecate(args) {
26322
26211
  }
26323
26212
 
26324
26213
  // src/commands-snippets.ts
26325
- import { readFileSync as readFileSync13, existsSync as existsSync14, mkdirSync as mkdirSync8, writeFileSync as writeFileSync8 } from "node:fs";
26326
- import { resolve as resolve10, basename as basename6, extname as extname4, join as join15 } from "node:path";
26214
+ import { readFileSync as readFileSync12, existsSync as existsSync13, mkdirSync as mkdirSync8, writeFileSync as writeFileSync8 } from "node:fs";
26215
+ import { resolve as resolve10, basename as basename6, extname as extname4, join as join14 } from "node:path";
26327
26216
  import { homedir as homedir10, platform as platform10 } from "node:os";
26328
26217
  import { createInterface as createInterface5 } from "node:readline";
26329
26218
  var PLATFORM_URL4 = process.env.ROBINPATH_PLATFORM_URL || "https://api.robinpath.com";
@@ -26559,11 +26448,11 @@ async function snippetCreate(args) {
26559
26448
  defaultName = "untitled";
26560
26449
  } else {
26561
26450
  const filePath = resolve10(fileArg);
26562
- if (!existsSync14(filePath)) {
26451
+ if (!existsSync13(filePath)) {
26563
26452
  console.error(color.red("Error:") + ` File not found: ${fileArg}`);
26564
26453
  process.exit(1);
26565
26454
  }
26566
- code = readFileSync13(filePath, "utf-8");
26455
+ code = readFileSync12(filePath, "utf-8");
26567
26456
  defaultName = basename6(filePath, extname4(filePath));
26568
26457
  }
26569
26458
  if (!code || !code.trim()) {
@@ -26585,8 +26474,8 @@ async function snippetCreate(args) {
26585
26474
  if (flags.version) payload.version = flags.version;
26586
26475
  if (flags.readme) {
26587
26476
  const readmePath = resolve10(flags.readme);
26588
- if (existsSync14(readmePath)) {
26589
- payload.readme = readFileSync13(readmePath, "utf-8");
26477
+ if (existsSync13(readmePath)) {
26478
+ payload.readme = readFileSync12(readmePath, "utf-8");
26590
26479
  }
26591
26480
  }
26592
26481
  try {
@@ -26669,12 +26558,12 @@ async function snippetInit(args) {
26669
26558
  code = codeLines.join("\n");
26670
26559
  } else {
26671
26560
  const filePath = await ask("File path", "");
26672
- if (!filePath || !existsSync14(resolve10(filePath))) {
26561
+ if (!filePath || !existsSync13(resolve10(filePath))) {
26673
26562
  console.error(color.red("Error:") + " File not found.");
26674
26563
  rl.close();
26675
26564
  process.exit(1);
26676
26565
  }
26677
- code = readFileSync13(resolve10(filePath), "utf-8");
26566
+ code = readFileSync12(resolve10(filePath), "utf-8");
26678
26567
  }
26679
26568
  rl.close();
26680
26569
  if (!code.trim()) {
@@ -26831,16 +26720,16 @@ async function snippetUpdate(args) {
26831
26720
  payload.tags = flags.tags.split(",").map((t) => t.trim()).filter(Boolean);
26832
26721
  if (flags.code) {
26833
26722
  const codePath = resolve10(flags.code);
26834
- if (!existsSync14(codePath)) {
26723
+ if (!existsSync13(codePath)) {
26835
26724
  console.error(color.red("Error:") + ` Code file not found: ${flags.code}`);
26836
26725
  process.exit(1);
26837
26726
  }
26838
- payload.code = readFileSync13(codePath, "utf-8");
26727
+ payload.code = readFileSync12(codePath, "utf-8");
26839
26728
  }
26840
26729
  if (flags.readme) {
26841
26730
  const readmePath = resolve10(flags.readme);
26842
- if (existsSync14(readmePath)) {
26843
- payload.readme = readFileSync13(readmePath, "utf-8");
26731
+ if (existsSync13(readmePath)) {
26732
+ payload.readme = readFileSync12(readmePath, "utf-8");
26844
26733
  }
26845
26734
  }
26846
26735
  if (Object.keys(payload).length === 0) {
@@ -27216,16 +27105,16 @@ async function snippetCopy(args) {
27216
27105
  process.exit(1);
27217
27106
  }
27218
27107
  }
27219
- var SNIPPET_CACHE_DIR = join15(homedir10(), ".robinpath", "cache", "snippets");
27108
+ var SNIPPET_CACHE_DIR = join14(homedir10(), ".robinpath", "cache", "snippets");
27220
27109
  var SNIPPET_CACHE_TTL = 5 * 60 * 1e3;
27221
27110
  function getSnippetCachePath(id) {
27222
- return join15(SNIPPET_CACHE_DIR, `${id}.json`);
27111
+ return join14(SNIPPET_CACHE_DIR, `${id}.json`);
27223
27112
  }
27224
27113
  function readSnippetCache(id) {
27225
27114
  try {
27226
27115
  const cachePath = getSnippetCachePath(id);
27227
- if (!existsSync14(cachePath)) return null;
27228
- const raw = JSON.parse(readFileSync13(cachePath, "utf-8"));
27116
+ if (!existsSync13(cachePath)) return null;
27117
+ const raw = JSON.parse(readFileSync12(cachePath, "utf-8"));
27229
27118
  if (Date.now() - (raw._cachedAt || 0) > SNIPPET_CACHE_TTL) return null;
27230
27119
  return raw;
27231
27120
  } catch {
@@ -27234,7 +27123,7 @@ function readSnippetCache(id) {
27234
27123
  }
27235
27124
  function writeSnippetCache(id, data) {
27236
27125
  try {
27237
- if (!existsSync14(SNIPPET_CACHE_DIR)) {
27126
+ if (!existsSync13(SNIPPET_CACHE_DIR)) {
27238
27127
  mkdirSync8(SNIPPET_CACHE_DIR, { recursive: true });
27239
27128
  }
27240
27129
  writeFileSync8(getSnippetCachePath(id), JSON.stringify({ ...data, _cachedAt: Date.now() }), "utf-8");
@@ -27348,11 +27237,11 @@ async function snippetPush(args) {
27348
27237
  }
27349
27238
  id = await resolveSnippetId(id);
27350
27239
  const filePath = resolve10(fileArg);
27351
- if (!existsSync14(filePath)) {
27240
+ if (!existsSync13(filePath)) {
27352
27241
  console.error(color.red("Error:") + ` File not found: ${fileArg}`);
27353
27242
  process.exit(1);
27354
27243
  }
27355
- const code = readFileSync13(filePath, "utf-8");
27244
+ const code = readFileSync12(filePath, "utf-8");
27356
27245
  if (!code.trim()) {
27357
27246
  console.error(color.red("Error:") + " File is empty.");
27358
27247
  process.exit(1);
@@ -27436,11 +27325,11 @@ async function snippetDiff(args) {
27436
27325
  }
27437
27326
  id = await resolveSnippetId(id);
27438
27327
  const filePath = resolve10(fileArg);
27439
- if (!existsSync14(filePath)) {
27328
+ if (!existsSync13(filePath)) {
27440
27329
  console.error(color.red("Error:") + ` File not found: ${fileArg}`);
27441
27330
  process.exit(1);
27442
27331
  }
27443
- const localCode = readFileSync13(filePath, "utf-8");
27332
+ const localCode = readFileSync12(filePath, "utf-8");
27444
27333
  try {
27445
27334
  const res = await fetchSnippet(id);
27446
27335
  if (!res.ok) {
@@ -27560,13 +27449,13 @@ async function snippetImport(args) {
27560
27449
  process.exit(2);
27561
27450
  }
27562
27451
  const filePath = resolve10(fileArg);
27563
- if (!existsSync14(filePath)) {
27452
+ if (!existsSync13(filePath)) {
27564
27453
  console.error(color.red("Error:") + ` File not found: ${fileArg}`);
27565
27454
  process.exit(1);
27566
27455
  }
27567
27456
  let importData;
27568
27457
  try {
27569
- importData = JSON.parse(readFileSync13(filePath, "utf-8"));
27458
+ importData = JSON.parse(readFileSync12(filePath, "utf-8"));
27570
27459
  } catch {
27571
27460
  console.error(color.red("Error:") + " Invalid JSON file.");
27572
27461
  process.exit(1);
@@ -27633,8 +27522,8 @@ async function snippetImport(args) {
27633
27522
 
27634
27523
  // src/commands-cloud.ts
27635
27524
  import { createServer as createServer4 } from "node:http";
27636
- import { readFileSync as readFileSync14, writeFileSync as writeFileSync9, unlinkSync as unlinkSync6, existsSync as existsSync15 } from "node:fs";
27637
- import { resolve as resolve11, join as join16, dirname as dirname5, basename as basename7 } from "node:path";
27525
+ import { readFileSync as readFileSync13, writeFileSync as writeFileSync9, unlinkSync as unlinkSync6, existsSync as existsSync14 } from "node:fs";
27526
+ import { resolve as resolve11, join as join15, dirname as dirname5, basename as basename7 } from "node:path";
27638
27527
  import { execSync as execSync3 } from "node:child_process";
27639
27528
  import { tmpdir as tmpdir4, hostname as hostname3 } from "node:os";
27640
27529
  var CLOUD_URL2 = process.env.ROBINPATH_CLOUD_URL || "https://dev.robinpath.com";
@@ -27770,14 +27659,14 @@ async function handlePublish(args) {
27770
27659
  const isDryRun = args.includes("--dry-run");
27771
27660
  const targetArg = args.find((a) => !a.startsWith("-") && !a.startsWith("--org")) || ".";
27772
27661
  const targetDir = resolve11(targetArg);
27773
- const pkgPath = join16(targetDir, "package.json");
27774
- if (!existsSync15(pkgPath)) {
27662
+ const pkgPath = join15(targetDir, "package.json");
27663
+ if (!existsSync14(pkgPath)) {
27775
27664
  console.error(color.red("Error:") + ` No package.json found in ${targetDir}`);
27776
27665
  process.exit(2);
27777
27666
  }
27778
27667
  let pkg;
27779
27668
  try {
27780
- pkg = JSON.parse(readFileSync14(pkgPath, "utf-8"));
27669
+ pkg = JSON.parse(readFileSync13(pkgPath, "utf-8"));
27781
27670
  } catch (err) {
27782
27671
  console.error(color.red("Error:") + ` Invalid package.json: ${err.message}`);
27783
27672
  process.exit(2);
@@ -27821,7 +27710,7 @@ async function handlePublish(args) {
27821
27710
  scope = emailPrefix;
27822
27711
  name = pkg.name;
27823
27712
  }
27824
- const tmpFile = join16(tmpdir4(), `robinpath-publish-${Date.now()}.tar.gz`);
27713
+ const tmpFile = join15(tmpdir4(), `robinpath-publish-${Date.now()}.tar.gz`);
27825
27714
  const parentDir = dirname5(targetDir);
27826
27715
  const dirName = basename7(targetDir);
27827
27716
  log(`Packing @${scope}/${name}@${pkg.version} (${visibility})...`);
@@ -27838,7 +27727,7 @@ async function handlePublish(args) {
27838
27727
  console.error(color.red("Error:") + ` Failed to create tarball: ${err.message}`);
27839
27728
  process.exit(1);
27840
27729
  }
27841
- const tarball = readFileSync14(tmpFile);
27730
+ const tarball = readFileSync13(tmpFile);
27842
27731
  const maxSize = 50 * 1024 * 1024;
27843
27732
  if (tarball.length > maxSize) {
27844
27733
  unlinkSync6(tmpFile);
@@ -28150,7 +28039,7 @@ async function main() {
28150
28039
  return;
28151
28040
  }
28152
28041
  if (command === "install") {
28153
- existsSync16(resolve12("robinpath.json")) ? await handleProjectInstall() : handleInstall();
28042
+ existsSync15(resolve12("robinpath.json")) ? await handleProjectInstall() : handleInstall();
28154
28043
  return;
28155
28044
  }
28156
28045
  if (command === "uninstall") {
@@ -28269,7 +28158,7 @@ async function main() {
28269
28158
  }
28270
28159
  process.exit(2);
28271
28160
  }
28272
- const script = readFileSync15(filePath, "utf-8");
28161
+ const script = readFileSync14(filePath, "utf-8");
28273
28162
  const hasWatch = args.includes("--watch");
28274
28163
  const hasShortWatch = args.includes("-w") && command !== "fmt";
28275
28164
  if (hasWatch || hasShortWatch) {