@robinpath/cli 1.76.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 +347 -462
- package/package.json +1 -1
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
|
|
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.
|
|
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
|
|
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
|
-
|
|
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,365 +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
|
|
24199
|
-
|
|
24200
|
-
|
|
24201
|
-
|
|
24202
|
-
|
|
24203
|
-
|
|
24204
|
-
|
|
24205
|
-
|
|
24206
|
-
|
|
24207
|
-
|
|
24208
|
-
|
|
24209
|
-
|
|
24210
|
-
|
|
24211
|
-
|
|
24212
|
-
|
|
24213
|
-
|
|
24214
|
-
|
|
24215
|
-
|
|
24216
|
-
|
|
24217
|
-
|
|
24218
|
-
|
|
24219
|
-
|
|
24220
|
-
|
|
24221
|
-
|
|
24222
|
-
|
|
24223
|
-
|
|
24224
|
-
|
|
24225
|
-
|
|
24226
|
-
|
|
24227
|
-
|
|
24228
|
-
|
|
24229
|
-
|
|
24230
|
-
|
|
24231
|
-
|
|
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..."
|
|
24232
24246
|
}
|
|
24233
|
-
|
|
24234
|
-
|
|
24235
|
-
}
|
|
24236
|
-
function printBanner(modelShort, modeStr, cwdShort, shellName) {
|
|
24237
|
-
log("");
|
|
24238
|
-
log(` ${color.cyan("\u25C6")} ${color.bold("RobinPath")} ${color.dim("v" + CLI_VERSION)}`);
|
|
24239
|
-
log(color.dim(` ${modelShort} \xB7 ${shellName} \xB7 ${modeStr}`));
|
|
24240
|
-
log("");
|
|
24247
|
+
),
|
|
24248
|
+
status ? /* @__PURE__ */ jsx(Box, { marginX: 2, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: status }) }) : null
|
|
24249
|
+
] });
|
|
24241
24250
|
}
|
|
24242
|
-
|
|
24243
|
-
|
|
24244
|
-
|
|
24245
|
-
|
|
24246
|
-
|
|
24247
|
-
|
|
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) {
|
|
24248
24304
|
if (!key) return "gemini";
|
|
24249
24305
|
if (key.startsWith("sk-or-")) return "openrouter";
|
|
24250
24306
|
if (key.startsWith("sk-ant-")) return "anthropic";
|
|
24251
24307
|
if (key.startsWith("sk-")) return "openai";
|
|
24252
|
-
return config.provider || "gemini";
|
|
24253
|
-
};
|
|
24254
|
-
const apiKey = config.apiKey || null;
|
|
24255
|
-
const provider = resolveProvider(apiKey);
|
|
24256
|
-
const model = apiKey ? config.model || "anthropic/claude-sonnet-4.6" : "robinpath-default";
|
|
24257
|
-
const modelShort = model === "robinpath-default" ? "gemini-2.0-flash (free)" : model.includes("/") ? model.split("/").pop() : model;
|
|
24258
|
-
const cliContext = {
|
|
24259
|
-
platform: platform7(),
|
|
24260
|
-
shell: getShellConfig().name,
|
|
24261
|
-
cwd: process.cwd(),
|
|
24262
|
-
cliVersion: CLI_VERSION,
|
|
24263
|
-
nativeModules: getNativeModules().map((m) => m.name),
|
|
24264
|
-
installedModules: Object.keys(readModulesManifest())
|
|
24265
|
-
};
|
|
24266
|
-
let sessionId = resumeSessionId || randomUUID4().slice(0, 8);
|
|
24267
|
-
let sessionName = `session-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}`;
|
|
24268
|
-
const usage = createUsageTracker();
|
|
24269
|
-
const conversationMessages = [];
|
|
24270
|
-
const history = [];
|
|
24271
|
-
const memContext = buildMemoryContext();
|
|
24272
|
-
if (memContext.trim()) {
|
|
24273
|
-
conversationMessages.push({ role: "user", content: `[Context] ${memContext.trim()}` });
|
|
24274
|
-
conversationMessages.push({ role: "assistant", content: "Got it, I have your preferences loaded." });
|
|
24308
|
+
return this.config.provider || "gemini";
|
|
24275
24309
|
}
|
|
24276
|
-
|
|
24277
|
-
const
|
|
24278
|
-
|
|
24279
|
-
|
|
24280
|
-
|
|
24281
|
-
if (session.usage) {
|
|
24282
|
-
usage.promptTokens = session.usage.promptTokens || 0;
|
|
24283
|
-
usage.completionTokens = session.usage.completionTokens || 0;
|
|
24284
|
-
usage.totalTokens = session.usage.totalTokens || 0;
|
|
24285
|
-
usage.requests = session.usage.requests || 0;
|
|
24286
|
-
}
|
|
24287
|
-
log(color.green(` Resumed: ${sessionName} (${session.messages.length} msgs)`));
|
|
24288
|
-
}
|
|
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}`);
|
|
24289
24315
|
}
|
|
24290
|
-
|
|
24291
|
-
|
|
24292
|
-
|
|
24293
|
-
try {
|
|
24294
|
-
const entries = readdirSync6(process.cwd()).filter((e) => !e.startsWith("."));
|
|
24295
|
-
let rpCount = 0, dirCount = 0;
|
|
24296
|
-
for (const e of entries.slice(0, 100)) {
|
|
24297
|
-
try {
|
|
24298
|
-
const s = statSync6(join12(process.cwd(), e));
|
|
24299
|
-
if (s.isDirectory() && !["node_modules", "__pycache__", "dist", "build"].includes(e)) dirCount++;
|
|
24300
|
-
else if (e.endsWith(".rp") || e.endsWith(".robin")) rpCount++;
|
|
24301
|
-
} catch {
|
|
24302
|
-
}
|
|
24316
|
+
exit() {
|
|
24317
|
+
if (this.conversationMessages.length > 1) {
|
|
24318
|
+
saveSession(this.sessionId, this.sessionName, this.conversationMessages, this.usage);
|
|
24303
24319
|
}
|
|
24304
|
-
|
|
24305
|
-
} catch {
|
|
24320
|
+
this.ui?.exit();
|
|
24306
24321
|
}
|
|
24307
|
-
|
|
24308
|
-
|
|
24309
|
-
|
|
24310
|
-
|
|
24311
|
-
|
|
24312
|
-
initialPrompt = null;
|
|
24313
|
-
log(color.cyan(" \u276F ") + trimmed);
|
|
24314
|
-
} else {
|
|
24315
|
-
const input = await collectInkInput(
|
|
24316
|
-
isFirst ? "What do you want to automate?" : "Ask anything..."
|
|
24317
|
-
);
|
|
24318
|
-
isFirst = false;
|
|
24319
|
-
if (input === null) {
|
|
24320
|
-
exitWithSave();
|
|
24321
|
-
break;
|
|
24322
|
-
}
|
|
24323
|
-
trimmed = input.trim();
|
|
24324
|
-
if (!trimmed) continue;
|
|
24325
|
-
log(color.cyan(" \u276F ") + color.bold(trimmed));
|
|
24326
|
-
}
|
|
24327
|
-
if (trimmed === "/") {
|
|
24328
|
-
log("");
|
|
24329
|
-
for (const [cmd, desc] of Object.entries(SLASH_CMDS)) {
|
|
24330
|
-
log(` ${color.cyan(cmd.padEnd(14))} ${color.dim(desc)}`);
|
|
24331
|
-
}
|
|
24332
|
-
log("");
|
|
24333
|
-
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;
|
|
24334
24327
|
}
|
|
24335
|
-
if (
|
|
24336
|
-
|
|
24337
|
-
|
|
24328
|
+
if (text === "/clear") {
|
|
24329
|
+
this.conversationMessages.length = 0;
|
|
24330
|
+
this.ui?.addMessage("info", "Cleared.");
|
|
24331
|
+
return;
|
|
24338
24332
|
}
|
|
24339
|
-
if (
|
|
24340
|
-
|
|
24341
|
-
|
|
24342
|
-
|
|
24343
|
-
}
|
|
24344
|
-
log("");
|
|
24345
|
-
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;
|
|
24346
24337
|
}
|
|
24347
|
-
if (
|
|
24348
|
-
|
|
24349
|
-
|
|
24350
|
-
|
|
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;
|
|
24351
24343
|
}
|
|
24352
|
-
if (
|
|
24353
|
-
const
|
|
24354
|
-
|
|
24355
|
-
|
|
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;
|
|
24356
24349
|
}
|
|
24357
|
-
if (
|
|
24350
|
+
if (text.match(/^\/model \d+$/)) {
|
|
24358
24351
|
const hasKey = !!readAiConfig().apiKey;
|
|
24359
24352
|
const models = hasKey ? AI_MODELS : AI_MODELS.filter((m) => !m.requiresKey);
|
|
24360
|
-
const
|
|
24361
|
-
|
|
24362
|
-
|
|
24363
|
-
|
|
24364
|
-
|
|
24365
|
-
|
|
24366
|
-
|
|
24367
|
-
lastGroup = m.group;
|
|
24368
|
-
}
|
|
24369
|
-
const mark = m.id === cur ? color.green(" \u2713") : "";
|
|
24370
|
-
log(` ${color.cyan(String(i + 1))}. ${m.name} ${color.dim("\u2014 " + m.desc)}${mark}`);
|
|
24371
|
-
}
|
|
24372
|
-
log("");
|
|
24373
|
-
const answer = await collectInkInput("Enter number...");
|
|
24374
|
-
if (answer) {
|
|
24375
|
-
const idx = parseInt(answer, 10) - 1;
|
|
24376
|
-
if (idx >= 0 && idx < models.length) {
|
|
24377
|
-
config.model = models[idx].id;
|
|
24378
|
-
writeAiConfig(config);
|
|
24379
|
-
log(color.green(` Model: ${models[idx].id}`));
|
|
24380
|
-
}
|
|
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();
|
|
24381
24360
|
}
|
|
24382
|
-
|
|
24383
|
-
}
|
|
24384
|
-
if (trimmed === "/auto" || trimmed.startsWith("/auto ")) {
|
|
24385
|
-
const arg = trimmed.slice(5).trim().toLowerCase();
|
|
24386
|
-
if (arg === "on") autoAccept = true;
|
|
24387
|
-
else if (arg === "off") autoAccept = false;
|
|
24388
|
-
else autoAccept = !autoAccept;
|
|
24389
|
-
log(` Auto-accept: ${autoAccept ? color.green("ON") : color.yellow("OFF")}`);
|
|
24390
|
-
continue;
|
|
24361
|
+
return;
|
|
24391
24362
|
}
|
|
24392
|
-
if (
|
|
24363
|
+
if (text === "/memory") {
|
|
24393
24364
|
const mem = loadMemory();
|
|
24394
|
-
|
|
24395
|
-
|
|
24396
|
-
continue;
|
|
24397
|
-
}
|
|
24398
|
-
if (trimmed.startsWith("/remember ")) {
|
|
24399
|
-
addMemoryFact(trimmed.slice(10).trim());
|
|
24400
|
-
log(color.green(" Remembered."));
|
|
24401
|
-
continue;
|
|
24402
|
-
}
|
|
24403
|
-
if (trimmed.startsWith("/forget ")) {
|
|
24404
|
-
removeMemoryFact(parseInt(trimmed.slice(8).trim(), 10) - 1);
|
|
24405
|
-
log(color.green(" Forgot."));
|
|
24406
|
-
continue;
|
|
24407
|
-
}
|
|
24408
|
-
if (trimmed === "/save" || trimmed.startsWith("/save ")) {
|
|
24409
|
-
if (trimmed.length > 5) sessionName = trimmed.slice(5).trim();
|
|
24410
|
-
saveSession(sessionId, sessionName, conversationMessages, usage);
|
|
24411
|
-
log(color.green(` Saved: ${sessionName}`));
|
|
24412
|
-
continue;
|
|
24413
|
-
}
|
|
24414
|
-
if (trimmed === "/sessions") {
|
|
24415
|
-
const sessions = listSessions();
|
|
24416
|
-
if (sessions.length === 0) log(color.dim(" No sessions."));
|
|
24417
|
-
else sessions.forEach((s) => log(` ${color.cyan(s.id)} ${s.name} ${color.dim(`${s.messages} msgs`)}`));
|
|
24418
|
-
continue;
|
|
24419
|
-
}
|
|
24420
|
-
if (trimmed === "/shell") {
|
|
24421
|
-
const shells = getAvailableShells();
|
|
24422
|
-
shells.forEach((s) => {
|
|
24423
|
-
const mark = s.current ? color.green(" \u2713") : s.available ? "" : color.dim(" (not found)");
|
|
24424
|
-
log(` ${s.available ? color.cyan(s.name) : color.dim(s.name)}${mark}`);
|
|
24425
|
-
});
|
|
24426
|
-
continue;
|
|
24365
|
+
this.ui?.addMessage("info", mem.facts.length ? mem.facts.map((f, i) => `${i + 1}. ${f}`).join("\n") : "No memories.");
|
|
24366
|
+
return;
|
|
24427
24367
|
}
|
|
24428
|
-
if (
|
|
24429
|
-
|
|
24430
|
-
|
|
24431
|
-
|
|
24432
|
-
|
|
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;
|
|
24433
24373
|
}
|
|
24434
|
-
if (
|
|
24435
|
-
|
|
24436
|
-
|
|
24374
|
+
if (text.startsWith("/")) {
|
|
24375
|
+
this.ui?.addMessage("info", `Unknown: ${text}. Type / for help.`);
|
|
24376
|
+
return;
|
|
24437
24377
|
}
|
|
24438
|
-
|
|
24439
|
-
|
|
24440
|
-
|
|
24441
|
-
|
|
24442
|
-
const activeKey = readAiConfig().apiKey || apiKey;
|
|
24443
|
-
const activeProvider = resolveProvider(activeKey);
|
|
24444
|
-
let spinner = createSpinner("Thinking");
|
|
24378
|
+
this.ui?.addMessage("user", text);
|
|
24379
|
+
this.ui?.setLoading(true);
|
|
24380
|
+
this.ui?.setStreaming("");
|
|
24381
|
+
this.ui?.setLoadingLabel("Thinking");
|
|
24445
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 = "";
|
|
24446
24390
|
for (let loop = 0; loop < 15; loop++) {
|
|
24447
|
-
|
|
24448
|
-
|
|
24449
|
-
let insideCmd = false;
|
|
24391
|
+
this.ui?.setLoadingLabel(loop === 0 ? "Thinking" : "Processing");
|
|
24392
|
+
fullResponse = "";
|
|
24450
24393
|
const result = await fetchBrainStream(
|
|
24451
|
-
loop === 0 ? expanded : conversationMessages[conversationMessages.length - 1].content,
|
|
24394
|
+
loop === 0 ? expanded : this.conversationMessages[this.conversationMessages.length - 1].content,
|
|
24452
24395
|
{
|
|
24453
24396
|
onToken: (delta) => {
|
|
24454
|
-
spinner.stop();
|
|
24455
24397
|
if (delta === "\x1B[RETRY]") {
|
|
24456
|
-
|
|
24457
|
-
|
|
24458
|
-
insideCmd = false;
|
|
24459
|
-
spinner = createSpinner("Retrying");
|
|
24398
|
+
fullResponse = "";
|
|
24399
|
+
this.ui?.setStreaming("");
|
|
24460
24400
|
return;
|
|
24461
24401
|
}
|
|
24462
|
-
|
|
24463
|
-
|
|
24464
|
-
|
|
24465
|
-
const ci2 = pending.indexOf("</memory>");
|
|
24466
|
-
if (ci2 === -1) break;
|
|
24467
|
-
const fact = pending.slice(0, ci2).trim();
|
|
24468
|
-
if (fact.length > 3 && fact.length < 300) addMemoryFact(fact);
|
|
24469
|
-
pending = pending.slice(ci2 + 9);
|
|
24470
|
-
insideMemory = false;
|
|
24471
|
-
continue;
|
|
24472
|
-
}
|
|
24473
|
-
if (insideCmd) {
|
|
24474
|
-
const ci2 = pending.indexOf("</cmd>");
|
|
24475
|
-
if (ci2 === -1) break;
|
|
24476
|
-
pending = pending.slice(ci2 + 6);
|
|
24477
|
-
insideCmd = false;
|
|
24478
|
-
continue;
|
|
24479
|
-
}
|
|
24480
|
-
const mi = pending.indexOf("<memory>");
|
|
24481
|
-
const ci = pending.indexOf("<cmd>");
|
|
24482
|
-
if (mi === -1 && ci === -1) {
|
|
24483
|
-
const lt2 = pending.lastIndexOf("<");
|
|
24484
|
-
if (lt2 !== -1 && lt2 > pending.length - 9) {
|
|
24485
|
-
if (lt2 > 0) {
|
|
24486
|
-
process.stdout.write(pending.slice(0, lt2).replace(/\n{3,}/g, "\n\n"));
|
|
24487
|
-
pending = pending.slice(lt2);
|
|
24488
|
-
}
|
|
24489
|
-
} else {
|
|
24490
|
-
process.stdout.write(pending.replace(/\n{3,}/g, "\n\n"));
|
|
24491
|
-
pending = "";
|
|
24492
|
-
}
|
|
24493
|
-
break;
|
|
24494
|
-
}
|
|
24495
|
-
const first = mi === -1 ? ci : ci === -1 ? mi : Math.min(mi, ci);
|
|
24496
|
-
if (first > 0) process.stdout.write(pending.slice(0, first).replace(/\n{3,}/g, "\n\n"));
|
|
24497
|
-
if (first === mi) {
|
|
24498
|
-
pending = pending.slice(first + 8);
|
|
24499
|
-
insideMemory = true;
|
|
24500
|
-
} else {
|
|
24501
|
-
pending = pending.slice(first + 5);
|
|
24502
|
-
insideCmd = true;
|
|
24503
|
-
}
|
|
24504
|
-
}
|
|
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);
|
|
24505
24405
|
},
|
|
24506
|
-
conversationHistory: conversationMessages.slice(0, -1),
|
|
24406
|
+
conversationHistory: this.conversationMessages.slice(0, -1),
|
|
24507
24407
|
provider: activeProvider,
|
|
24508
24408
|
model: activeModel,
|
|
24509
24409
|
apiKey: activeKey,
|
|
24510
|
-
cliContext
|
|
24410
|
+
cliContext: this.cliContext
|
|
24511
24411
|
}
|
|
24512
24412
|
);
|
|
24513
|
-
if (pending && !insideMemory && !insideCmd) process.stdout.write(pending);
|
|
24514
24413
|
if (!result || !result.code) {
|
|
24515
|
-
|
|
24516
|
-
log(color.red("\n No response."));
|
|
24414
|
+
this.ui?.addMessage("assistant", fullResponse || "No response. Check connection or API key.");
|
|
24517
24415
|
break;
|
|
24518
24416
|
}
|
|
24519
24417
|
if (result.usage) {
|
|
24520
24418
|
const pt2 = result.usage.prompt_tokens || 0;
|
|
24521
24419
|
const ct2 = result.usage.completion_tokens || 0;
|
|
24522
|
-
usage.promptTokens += pt2;
|
|
24523
|
-
usage.completionTokens += ct2;
|
|
24524
|
-
usage.totalTokens += pt2 + ct2;
|
|
24525
|
-
usage.requests++;
|
|
24526
|
-
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();
|
|
24527
24426
|
}
|
|
24528
|
-
const commands = extractCommands(result.code);
|
|
24529
24427
|
const { cleaned } = extractMemoryTags(stripCommandTags(result.code));
|
|
24530
|
-
|
|
24531
|
-
if (cleaned)
|
|
24532
|
-
|
|
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);
|
|
24533
24437
|
const cmdResults = [];
|
|
24534
24438
|
for (const cmd of commands) {
|
|
24535
|
-
|
|
24536
|
-
if (decision === "no") {
|
|
24537
|
-
cmdResults.push({ command: cmd, stdout: "", stderr: "(skipped)", exitCode: -1 });
|
|
24538
|
-
continue;
|
|
24539
|
-
}
|
|
24540
|
-
if (decision === "auto") {
|
|
24541
|
-
autoAccept = true;
|
|
24542
|
-
log(color.green(" Auto-accept ON"));
|
|
24543
|
-
}
|
|
24439
|
+
this.ui?.addMessage("info", `$ ${cmd.split("\n")[0]}${cmd.includes("\n") ? ` (+${cmd.split("\n").length - 1} lines)` : ""}`);
|
|
24544
24440
|
const r = await executeShellCommand(cmd);
|
|
24545
|
-
if (r.exitCode
|
|
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
|
+
}
|
|
24546
24446
|
cmdResults.push({ command: cmd, stdout: r.stdout || "", stderr: r.stderr || "", exitCode: r.exitCode });
|
|
24547
24447
|
}
|
|
24548
24448
|
const summary = cmdResults.map((r) => {
|
|
@@ -24556,59 +24456,44 @@ async function startInkREPL(initialPrompt, resumeSessionId, opts = {}) {
|
|
|
24556
24456
|
}
|
|
24557
24457
|
return o;
|
|
24558
24458
|
}).join("\n\n");
|
|
24559
|
-
conversationMessages.push({ role: "user", content: `[Command results]
|
|
24459
|
+
this.conversationMessages.push({ role: "user", content: `[Command results]
|
|
24560
24460
|
${summary}` });
|
|
24561
|
-
|
|
24461
|
+
this.ui?.setStreaming("");
|
|
24562
24462
|
}
|
|
24563
24463
|
} catch (err) {
|
|
24564
|
-
|
|
24565
|
-
|
|
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);
|
|
24566
24469
|
}
|
|
24567
|
-
log("");
|
|
24568
|
-
if (usage.cost > 0) log(color.dim(` $${usage.cost.toFixed(4)} \xB7 ${usage.totalTokens.toLocaleString()} tokens`));
|
|
24569
24470
|
}
|
|
24570
|
-
function exitWithSave() {
|
|
24571
|
-
if (conversationMessages.length > 1) {
|
|
24572
|
-
saveSession(sessionId, sessionName, conversationMessages, usage);
|
|
24573
|
-
log(color.dim(` Session saved: ${sessionId}`));
|
|
24574
|
-
}
|
|
24575
|
-
log(color.dim(" Goodbye!"));
|
|
24576
|
-
process.exit(0);
|
|
24577
|
-
}
|
|
24578
|
-
process.on("SIGINT", () => {
|
|
24579
|
-
log("");
|
|
24580
|
-
exitWithSave();
|
|
24581
|
-
});
|
|
24582
|
-
}
|
|
24583
|
-
var SLASH_CMDS = {
|
|
24584
|
-
"/help": "Show commands",
|
|
24585
|
-
"/model": "Switch AI model",
|
|
24586
|
-
"/shell": "Switch shell",
|
|
24587
|
-
"/auto": "Toggle auto-accept",
|
|
24588
|
-
"/clear": "Clear conversation",
|
|
24589
|
-
"/save": "Save session",
|
|
24590
|
-
"/sessions": "List sessions",
|
|
24591
|
-
"/memory": "Show memory",
|
|
24592
|
-
"/remember": "Save a fact",
|
|
24593
|
-
"/forget": "Remove a memory",
|
|
24594
|
-
"/usage": "Token usage & cost",
|
|
24595
|
-
"exit": "Quit"
|
|
24596
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
|
+
}
|
|
24597
24482
|
|
|
24598
24483
|
// src/commands-modules.ts
|
|
24599
24484
|
import { createInterface as createInterface3 } from "node:readline";
|
|
24600
24485
|
import {
|
|
24601
|
-
readFileSync as
|
|
24602
|
-
existsSync as
|
|
24486
|
+
readFileSync as readFileSync10,
|
|
24487
|
+
existsSync as existsSync11,
|
|
24603
24488
|
mkdirSync as mkdirSync6,
|
|
24604
24489
|
copyFileSync as copyFileSync2,
|
|
24605
24490
|
rmSync as rmSync2,
|
|
24606
24491
|
writeFileSync as writeFileSync6,
|
|
24607
|
-
readdirSync as
|
|
24608
|
-
statSync as
|
|
24492
|
+
readdirSync as readdirSync6,
|
|
24493
|
+
statSync as statSync6,
|
|
24609
24494
|
unlinkSync as unlinkSync5
|
|
24610
24495
|
} from "node:fs";
|
|
24611
|
-
import { resolve as resolve8, join as
|
|
24496
|
+
import { resolve as resolve8, join as join12, dirname as dirname4, basename as basename4 } from "node:path";
|
|
24612
24497
|
import { execSync as execSync2 } from "node:child_process";
|
|
24613
24498
|
import { homedir as homedir9, platform as platform8, tmpdir as tmpdir3 } from "node:os";
|
|
24614
24499
|
import { createHash as createHash3 } from "node:crypto";
|
|
@@ -24699,17 +24584,17 @@ async function handleAdd(args) {
|
|
|
24699
24584
|
process.exit(1);
|
|
24700
24585
|
}
|
|
24701
24586
|
const integrity = "sha256-" + createHash3("sha256").update(tarballBuffer).digest("hex");
|
|
24702
|
-
if (!
|
|
24587
|
+
if (!existsSync11(CACHE_DIR)) {
|
|
24703
24588
|
mkdirSync6(CACHE_DIR, { recursive: true });
|
|
24704
24589
|
}
|
|
24705
|
-
const cacheFile =
|
|
24590
|
+
const cacheFile = join12(CACHE_DIR, `${scope}-${name}-${resolvedVersion}.tar.gz`);
|
|
24706
24591
|
writeFileSync6(cacheFile, tarballBuffer);
|
|
24707
24592
|
const modDir = getModulePath(fullName);
|
|
24708
|
-
if (
|
|
24593
|
+
if (existsSync11(modDir)) {
|
|
24709
24594
|
rmSync2(modDir, { recursive: true, force: true });
|
|
24710
24595
|
}
|
|
24711
24596
|
mkdirSync6(modDir, { recursive: true });
|
|
24712
|
-
const tmpFile =
|
|
24597
|
+
const tmpFile = join12(tmpdir3(), `robinpath-add-${Date.now()}.tar.gz`);
|
|
24713
24598
|
writeFileSync6(tmpFile, tarballBuffer);
|
|
24714
24599
|
try {
|
|
24715
24600
|
execSync2(`tar xzf "${toTarPath(tmpFile)}" --strip-components=1 -C "${toTarPath(modDir)}"`, { stdio: "pipe" });
|
|
@@ -24726,15 +24611,15 @@ async function handleAdd(args) {
|
|
|
24726
24611
|
unlinkSync5(tmpFile);
|
|
24727
24612
|
} catch {
|
|
24728
24613
|
}
|
|
24729
|
-
const distDir =
|
|
24730
|
-
const srcDir =
|
|
24731
|
-
if (!
|
|
24614
|
+
const distDir = join12(modDir, "dist");
|
|
24615
|
+
const srcDir = join12(modDir, "src");
|
|
24616
|
+
if (!existsSync11(distDir) && existsSync11(srcDir) && existsSync11(join12(srcDir, "index.ts"))) {
|
|
24732
24617
|
log(color.dim(" Compiling module..."));
|
|
24733
24618
|
mkdirSync6(distDir, { recursive: true });
|
|
24734
|
-
const tsFiles =
|
|
24619
|
+
const tsFiles = readdirSync6(srcDir).filter((f) => f.endsWith(".ts"));
|
|
24735
24620
|
for (const file of tsFiles) {
|
|
24736
|
-
const srcFile =
|
|
24737
|
-
const outFile =
|
|
24621
|
+
const srcFile = join12(srcDir, file);
|
|
24622
|
+
const outFile = join12(distDir, file.replace(".ts", ".js"));
|
|
24738
24623
|
try {
|
|
24739
24624
|
const stripScript = `
|
|
24740
24625
|
const fs = require('fs');
|
|
@@ -24750,17 +24635,17 @@ async function handleAdd(args) {
|
|
|
24750
24635
|
}
|
|
24751
24636
|
}
|
|
24752
24637
|
let installedVersion = resolvedVersion;
|
|
24753
|
-
const pkgJsonPath =
|
|
24754
|
-
if (
|
|
24638
|
+
const pkgJsonPath = join12(modDir, "package.json");
|
|
24639
|
+
if (existsSync11(pkgJsonPath)) {
|
|
24755
24640
|
try {
|
|
24756
|
-
const pkg = JSON.parse(
|
|
24641
|
+
const pkg = JSON.parse(readFileSync10(pkgJsonPath, "utf-8"));
|
|
24757
24642
|
installedVersion = pkg.version || installedVersion;
|
|
24758
24643
|
} catch {
|
|
24759
24644
|
}
|
|
24760
24645
|
}
|
|
24761
|
-
if (
|
|
24646
|
+
if (existsSync11(pkgJsonPath)) {
|
|
24762
24647
|
try {
|
|
24763
|
-
const pkg = JSON.parse(
|
|
24648
|
+
const pkg = JSON.parse(readFileSync10(pkgJsonPath, "utf-8"));
|
|
24764
24649
|
const depends = pkg.robinpath?.depends || [];
|
|
24765
24650
|
for (const dep of depends) {
|
|
24766
24651
|
if (!manifest[dep]) {
|
|
@@ -24779,9 +24664,9 @@ async function handleAdd(args) {
|
|
|
24779
24664
|
};
|
|
24780
24665
|
writeModulesManifest(updatedManifest);
|
|
24781
24666
|
const projectFile = resolve8("robinpath.json");
|
|
24782
|
-
if (
|
|
24667
|
+
if (existsSync11(projectFile)) {
|
|
24783
24668
|
try {
|
|
24784
|
-
const config = JSON.parse(
|
|
24669
|
+
const config = JSON.parse(readFileSync10(projectFile, "utf-8"));
|
|
24785
24670
|
if (!config.modules) config.modules = {};
|
|
24786
24671
|
config.modules[fullName] = `^${installedVersion}`;
|
|
24787
24672
|
writeFileSync6(projectFile, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
@@ -24809,12 +24694,12 @@ async function handleRemove(args) {
|
|
|
24809
24694
|
process.exit(1);
|
|
24810
24695
|
}
|
|
24811
24696
|
const modDir = getModulePath(fullName);
|
|
24812
|
-
if (
|
|
24697
|
+
if (existsSync11(modDir)) {
|
|
24813
24698
|
rmSync2(modDir, { recursive: true, force: true });
|
|
24814
24699
|
}
|
|
24815
24700
|
const scopeDir = dirname4(modDir);
|
|
24816
24701
|
try {
|
|
24817
|
-
const remaining =
|
|
24702
|
+
const remaining = readdirSync6(scopeDir);
|
|
24818
24703
|
if (remaining.length === 0) {
|
|
24819
24704
|
rmSync2(scopeDir, { recursive: true, force: true });
|
|
24820
24705
|
}
|
|
@@ -24823,9 +24708,9 @@ async function handleRemove(args) {
|
|
|
24823
24708
|
delete manifest[fullName];
|
|
24824
24709
|
writeModulesManifest(manifest);
|
|
24825
24710
|
const projectFile = resolve8("robinpath.json");
|
|
24826
|
-
if (
|
|
24711
|
+
if (existsSync11(projectFile)) {
|
|
24827
24712
|
try {
|
|
24828
|
-
const config = JSON.parse(
|
|
24713
|
+
const config = JSON.parse(readFileSync10(projectFile, "utf-8"));
|
|
24829
24714
|
if (config.modules && config.modules[fullName]) {
|
|
24830
24715
|
delete config.modules[fullName];
|
|
24831
24716
|
writeFileSync6(projectFile, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
@@ -24998,14 +24883,14 @@ async function handleModulesInit() {
|
|
|
24998
24883
|
const targetDir = resolve8(moduleName);
|
|
24999
24884
|
log("");
|
|
25000
24885
|
log(`Creating ${color.cyan(fullName)}...`);
|
|
25001
|
-
if (
|
|
24886
|
+
if (existsSync11(targetDir)) {
|
|
25002
24887
|
console.error(color.red("Error:") + ` Directory already exists: ${moduleName}/`);
|
|
25003
24888
|
process.exit(1);
|
|
25004
24889
|
}
|
|
25005
|
-
mkdirSync6(
|
|
25006
|
-
mkdirSync6(
|
|
24890
|
+
mkdirSync6(join12(targetDir, "src"), { recursive: true });
|
|
24891
|
+
mkdirSync6(join12(targetDir, "tests"), { recursive: true });
|
|
25007
24892
|
writeFileSync6(
|
|
25008
|
-
|
|
24893
|
+
join12(targetDir, "package.json"),
|
|
25009
24894
|
JSON.stringify(
|
|
25010
24895
|
{
|
|
25011
24896
|
name: fullName,
|
|
@@ -25029,7 +24914,7 @@ async function handleModulesInit() {
|
|
|
25029
24914
|
"utf-8"
|
|
25030
24915
|
);
|
|
25031
24916
|
writeFileSync6(
|
|
25032
|
-
|
|
24917
|
+
join12(targetDir, "src", "index.ts"),
|
|
25033
24918
|
`import type { ModuleAdapter } from "@wiredwp/robinpath";
|
|
25034
24919
|
import {
|
|
25035
24920
|
${pascalName}Functions,
|
|
@@ -25051,7 +24936,7 @@ export { ${pascalName}Module };
|
|
|
25051
24936
|
"utf-8"
|
|
25052
24937
|
);
|
|
25053
24938
|
writeFileSync6(
|
|
25054
|
-
|
|
24939
|
+
join12(targetDir, "src", `${moduleName}.ts`),
|
|
25055
24940
|
`import type {
|
|
25056
24941
|
BuiltinHandler,
|
|
25057
24942
|
FunctionMetadata,
|
|
@@ -25122,7 +25007,7 @@ export const ${pascalName}ModuleMetadata: ModuleMetadata = {
|
|
|
25122
25007
|
"utf-8"
|
|
25123
25008
|
);
|
|
25124
25009
|
writeFileSync6(
|
|
25125
|
-
|
|
25010
|
+
join12(targetDir, "tsconfig.json"),
|
|
25126
25011
|
JSON.stringify(
|
|
25127
25012
|
{
|
|
25128
25013
|
compilerOptions: {
|
|
@@ -25146,7 +25031,7 @@ export const ${pascalName}ModuleMetadata: ModuleMetadata = {
|
|
|
25146
25031
|
"utf-8"
|
|
25147
25032
|
);
|
|
25148
25033
|
writeFileSync6(
|
|
25149
|
-
|
|
25034
|
+
join12(targetDir, "tests", `${moduleName}.test.rp`),
|
|
25150
25035
|
`# ${displayName} module tests
|
|
25151
25036
|
# Run: robinpath test tests/
|
|
25152
25037
|
|
|
@@ -25165,7 +25050,7 @@ enddo
|
|
|
25165
25050
|
"utf-8"
|
|
25166
25051
|
);
|
|
25167
25052
|
writeFileSync6(
|
|
25168
|
-
|
|
25053
|
+
join12(targetDir, "README.md"),
|
|
25169
25054
|
`# ${fullName}
|
|
25170
25055
|
|
|
25171
25056
|
${description}
|
|
@@ -25209,7 +25094,7 @@ ${license}
|
|
|
25209
25094
|
"utf-8"
|
|
25210
25095
|
);
|
|
25211
25096
|
writeFileSync6(
|
|
25212
|
-
|
|
25097
|
+
join12(targetDir, ".gitignore"),
|
|
25213
25098
|
`node_modules/
|
|
25214
25099
|
dist/
|
|
25215
25100
|
*.tgz
|
|
@@ -25239,14 +25124,14 @@ dist/
|
|
|
25239
25124
|
async function handlePack(args) {
|
|
25240
25125
|
const targetArg = args.find((a) => !a.startsWith("-")) || ".";
|
|
25241
25126
|
const targetDir = resolve8(targetArg);
|
|
25242
|
-
const pkgPath =
|
|
25243
|
-
if (!
|
|
25127
|
+
const pkgPath = join12(targetDir, "package.json");
|
|
25128
|
+
if (!existsSync11(pkgPath)) {
|
|
25244
25129
|
console.error(color.red("Error:") + ` No package.json found in ${targetDir}`);
|
|
25245
25130
|
process.exit(2);
|
|
25246
25131
|
}
|
|
25247
25132
|
let pkg;
|
|
25248
25133
|
try {
|
|
25249
|
-
pkg = JSON.parse(
|
|
25134
|
+
pkg = JSON.parse(readFileSync10(pkgPath, "utf-8"));
|
|
25250
25135
|
} catch (err) {
|
|
25251
25136
|
console.error(color.red("Error:") + ` Invalid package.json: ${err.message}`);
|
|
25252
25137
|
process.exit(2);
|
|
@@ -25267,12 +25152,12 @@ async function handlePack(args) {
|
|
|
25267
25152
|
{ stdio: "pipe" }
|
|
25268
25153
|
);
|
|
25269
25154
|
} catch (err) {
|
|
25270
|
-
if (!
|
|
25155
|
+
if (!existsSync11(outputPath)) {
|
|
25271
25156
|
console.error(color.red("Error:") + ` Failed to create tarball: ${err.message}`);
|
|
25272
25157
|
process.exit(1);
|
|
25273
25158
|
}
|
|
25274
25159
|
}
|
|
25275
|
-
const size =
|
|
25160
|
+
const size = statSync6(outputPath).size;
|
|
25276
25161
|
log(color.green("Created") + ` ${outputFile} (${(size / 1024).toFixed(1)}KB)`);
|
|
25277
25162
|
}
|
|
25278
25163
|
function formatCompactNumber(n) {
|
|
@@ -25421,9 +25306,9 @@ async function handleInfo(args) {
|
|
|
25421
25306
|
path: getModulePath(packageName)
|
|
25422
25307
|
};
|
|
25423
25308
|
try {
|
|
25424
|
-
const pkgPath =
|
|
25425
|
-
if (
|
|
25426
|
-
const pkg = JSON.parse(
|
|
25309
|
+
const pkgPath = join12(getModulePath(packageName), "package.json");
|
|
25310
|
+
if (existsSync11(pkgPath)) {
|
|
25311
|
+
const pkg = JSON.parse(readFileSync10(pkgPath, "utf-8"));
|
|
25427
25312
|
if (pkg.description) entry.description = pkg.description;
|
|
25428
25313
|
if (pkg.keywords) entry.keywords = pkg.keywords;
|
|
25429
25314
|
}
|
|
@@ -25447,9 +25332,9 @@ async function handleInfo(args) {
|
|
|
25447
25332
|
modules_manifest: MODULES_MANIFEST,
|
|
25448
25333
|
cache: CACHE_DIR,
|
|
25449
25334
|
auth: getAuthPath(),
|
|
25450
|
-
history:
|
|
25451
|
-
env:
|
|
25452
|
-
docs:
|
|
25335
|
+
history: join12(homedir9(), ".robinpath", "history"),
|
|
25336
|
+
env: join12(homedir9(), ".robinpath", "env"),
|
|
25337
|
+
docs: join12(getRobinPathHome(), "DOCUMENTATION.md")
|
|
25453
25338
|
},
|
|
25454
25339
|
native_modules: modulesInfo,
|
|
25455
25340
|
installed_modules: installedModulesInfo,
|
|
@@ -25838,14 +25723,14 @@ async function handleInfo(args) {
|
|
|
25838
25723
|
}
|
|
25839
25724
|
|
|
25840
25725
|
// src/commands-project.ts
|
|
25841
|
-
import { readFileSync as
|
|
25842
|
-
import { resolve as resolve9, join as
|
|
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";
|
|
25843
25728
|
import { createInterface as createInterface4 } from "node:readline";
|
|
25844
25729
|
import { platform as platform9 } from "node:os";
|
|
25845
25730
|
var PLATFORM_URL3 = process.env.ROBINPATH_PLATFORM_URL || "https://api.robinpath.com";
|
|
25846
25731
|
async function handleInit(args) {
|
|
25847
25732
|
const projectFile = resolve9("robinpath.json");
|
|
25848
|
-
if (
|
|
25733
|
+
if (existsSync12(projectFile) && !args.includes("--force")) {
|
|
25849
25734
|
console.error(color.red("Error:") + " robinpath.json already exists. Use --force to overwrite.");
|
|
25850
25735
|
process.exit(1);
|
|
25851
25736
|
}
|
|
@@ -25876,7 +25761,7 @@ async function handleInit(args) {
|
|
|
25876
25761
|
};
|
|
25877
25762
|
writeFileSync7(projectFile, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
25878
25763
|
const mainPath = resolve9(mainFile);
|
|
25879
|
-
if (!
|
|
25764
|
+
if (!existsSync12(mainPath)) {
|
|
25880
25765
|
writeFileSync7(
|
|
25881
25766
|
mainPath,
|
|
25882
25767
|
`# ${projectName}
|
|
@@ -25887,7 +25772,7 @@ log "Hello from RobinPath!"
|
|
|
25887
25772
|
"utf-8"
|
|
25888
25773
|
);
|
|
25889
25774
|
}
|
|
25890
|
-
if (!
|
|
25775
|
+
if (!existsSync12(resolve9(".env"))) {
|
|
25891
25776
|
writeFileSync7(
|
|
25892
25777
|
resolve9(".env"),
|
|
25893
25778
|
`# Add your secrets here
|
|
@@ -25897,7 +25782,7 @@ log "Hello from RobinPath!"
|
|
|
25897
25782
|
"utf-8"
|
|
25898
25783
|
);
|
|
25899
25784
|
}
|
|
25900
|
-
if (!
|
|
25785
|
+
if (!existsSync12(resolve9(".gitignore"))) {
|
|
25901
25786
|
writeFileSync7(
|
|
25902
25787
|
resolve9(".gitignore"),
|
|
25903
25788
|
`.env
|
|
@@ -25910,7 +25795,7 @@ node_modules/
|
|
|
25910
25795
|
log("");
|
|
25911
25796
|
log(color.green("Created project:"));
|
|
25912
25797
|
log(` robinpath.json`);
|
|
25913
|
-
if (!
|
|
25798
|
+
if (!existsSync12(mainPath)) log(` ${mainFile}`);
|
|
25914
25799
|
log(` .env`);
|
|
25915
25800
|
log(` .gitignore`);
|
|
25916
25801
|
log("");
|
|
@@ -25919,13 +25804,13 @@ node_modules/
|
|
|
25919
25804
|
}
|
|
25920
25805
|
async function handleProjectInstall() {
|
|
25921
25806
|
const projectFile = resolve9("robinpath.json");
|
|
25922
|
-
if (!
|
|
25807
|
+
if (!existsSync12(projectFile)) {
|
|
25923
25808
|
handleInstall();
|
|
25924
25809
|
return;
|
|
25925
25810
|
}
|
|
25926
25811
|
let config;
|
|
25927
25812
|
try {
|
|
25928
|
-
config = JSON.parse(
|
|
25813
|
+
config = JSON.parse(readFileSync11(projectFile, "utf-8"));
|
|
25929
25814
|
} catch (err) {
|
|
25930
25815
|
console.error(color.red("Error:") + ` Invalid robinpath.json: ${err.message}`);
|
|
25931
25816
|
process.exit(2);
|
|
@@ -25996,7 +25881,7 @@ async function handleDoctor() {
|
|
|
25996
25881
|
const installDir = getInstallDir();
|
|
25997
25882
|
const isWindows = platform9() === "win32";
|
|
25998
25883
|
const binaryName = isWindows ? "robinpath.exe" : "robinpath";
|
|
25999
|
-
if (
|
|
25884
|
+
if (existsSync12(join13(installDir, binaryName))) {
|
|
26000
25885
|
log(color.green(" \u2713") + ` Installed: ${installDir}`);
|
|
26001
25886
|
} else {
|
|
26002
25887
|
log(color.yellow(" !") + ` Not installed to PATH. Run ${color.cyan("robinpath install")}`);
|
|
@@ -26023,21 +25908,21 @@ async function handleDoctor() {
|
|
|
26023
25908
|
log(color.green(" \u2713") + ` ${moduleCount} module${moduleCount !== 1 ? "s" : ""} installed`);
|
|
26024
25909
|
for (const [name, info] of Object.entries(manifest)) {
|
|
26025
25910
|
const modDir = getModulePath(name);
|
|
26026
|
-
const pkgPath =
|
|
26027
|
-
if (!
|
|
25911
|
+
const pkgPath = join13(modDir, "package.json");
|
|
25912
|
+
if (!existsSync12(modDir)) {
|
|
26028
25913
|
log(color.red(" \u2717") + ` ${name}: directory missing`);
|
|
26029
25914
|
issues++;
|
|
26030
|
-
} else if (!
|
|
25915
|
+
} else if (!existsSync12(pkgPath)) {
|
|
26031
25916
|
log(color.red(" \u2717") + ` ${name}: package.json missing`);
|
|
26032
25917
|
issues++;
|
|
26033
25918
|
} else {
|
|
26034
25919
|
let entryPoint = "dist/index.js";
|
|
26035
25920
|
try {
|
|
26036
|
-
const pkg = JSON.parse(
|
|
25921
|
+
const pkg = JSON.parse(readFileSync11(pkgPath, "utf-8"));
|
|
26037
25922
|
if (pkg.main) entryPoint = pkg.main;
|
|
26038
25923
|
} catch {
|
|
26039
25924
|
}
|
|
26040
|
-
if (!
|
|
25925
|
+
if (!existsSync12(join13(modDir, entryPoint))) {
|
|
26041
25926
|
log(color.red(" \u2717") + ` ${name}: entry point ${entryPoint} missing`);
|
|
26042
25927
|
issues++;
|
|
26043
25928
|
}
|
|
@@ -26047,9 +25932,9 @@ async function handleDoctor() {
|
|
|
26047
25932
|
log(color.dim(" -") + ` No modules installed`);
|
|
26048
25933
|
}
|
|
26049
25934
|
const projectFile = resolve9("robinpath.json");
|
|
26050
|
-
if (
|
|
25935
|
+
if (existsSync12(projectFile)) {
|
|
26051
25936
|
try {
|
|
26052
|
-
const config = JSON.parse(
|
|
25937
|
+
const config = JSON.parse(readFileSync11(projectFile, "utf-8"));
|
|
26053
25938
|
log(color.green(" \u2713") + ` Project: ${config.name || "unnamed"} v${config.version || "?"}`);
|
|
26054
25939
|
const projectModules = Object.keys(config.modules || {});
|
|
26055
25940
|
for (const mod of projectModules) {
|
|
@@ -26063,12 +25948,12 @@ async function handleDoctor() {
|
|
|
26063
25948
|
issues++;
|
|
26064
25949
|
}
|
|
26065
25950
|
}
|
|
26066
|
-
if (
|
|
25951
|
+
if (existsSync12(CACHE_DIR)) {
|
|
26067
25952
|
try {
|
|
26068
|
-
const cacheFiles =
|
|
25953
|
+
const cacheFiles = readdirSync7(CACHE_DIR);
|
|
26069
25954
|
const cacheSize = cacheFiles.reduce((total, f) => {
|
|
26070
25955
|
try {
|
|
26071
|
-
return total +
|
|
25956
|
+
return total + statSync7(join13(CACHE_DIR, f)).size;
|
|
26072
25957
|
} catch {
|
|
26073
25958
|
return total;
|
|
26074
25959
|
}
|
|
@@ -26086,12 +25971,12 @@ async function handleDoctor() {
|
|
|
26086
25971
|
log("");
|
|
26087
25972
|
}
|
|
26088
25973
|
async function handleEnv(args) {
|
|
26089
|
-
const envPath =
|
|
25974
|
+
const envPath = join13(getRobinPathHome(), "env");
|
|
26090
25975
|
const sub = args[0];
|
|
26091
25976
|
function readEnvFile() {
|
|
26092
25977
|
try {
|
|
26093
|
-
if (!
|
|
26094
|
-
const lines =
|
|
25978
|
+
if (!existsSync12(envPath)) return {};
|
|
25979
|
+
const lines = readFileSync11(envPath, "utf-8").split("\n");
|
|
26095
25980
|
const env = {};
|
|
26096
25981
|
for (const line of lines) {
|
|
26097
25982
|
const trimmed = line.trim();
|
|
@@ -26108,7 +25993,7 @@ async function handleEnv(args) {
|
|
|
26108
25993
|
}
|
|
26109
25994
|
function writeEnvFile(env) {
|
|
26110
25995
|
const dir = getRobinPathHome();
|
|
26111
|
-
if (!
|
|
25996
|
+
if (!existsSync12(dir)) mkdirSync7(dir, { recursive: true });
|
|
26112
25997
|
const content = Object.entries(env).map(([k2, v]) => `${k2}=${v}`).join("\n") + "\n";
|
|
26113
25998
|
writeFileSync7(envPath, content, "utf-8");
|
|
26114
25999
|
if (platform9() !== "win32") {
|
|
@@ -26172,12 +26057,12 @@ async function handleEnv(args) {
|
|
|
26172
26057
|
async function handleCache(args) {
|
|
26173
26058
|
const sub = args[0];
|
|
26174
26059
|
if (sub === "list") {
|
|
26175
|
-
if (!
|
|
26060
|
+
if (!existsSync12(CACHE_DIR)) {
|
|
26176
26061
|
log("Cache is empty.");
|
|
26177
26062
|
return;
|
|
26178
26063
|
}
|
|
26179
26064
|
try {
|
|
26180
|
-
const files =
|
|
26065
|
+
const files = readdirSync7(CACHE_DIR);
|
|
26181
26066
|
if (files.length === 0) {
|
|
26182
26067
|
log("Cache is empty.");
|
|
26183
26068
|
return;
|
|
@@ -26187,7 +26072,7 @@ async function handleCache(args) {
|
|
|
26187
26072
|
log(color.dim(" " + "\u2500".repeat(50)));
|
|
26188
26073
|
let totalSize = 0;
|
|
26189
26074
|
for (const file of files) {
|
|
26190
|
-
const size =
|
|
26075
|
+
const size = statSync7(join13(CACHE_DIR, file)).size;
|
|
26191
26076
|
totalSize += size;
|
|
26192
26077
|
log(` ${file.padEnd(45)} ${color.dim((size / 1024).toFixed(1) + "KB")}`);
|
|
26193
26078
|
}
|
|
@@ -26203,15 +26088,15 @@ async function handleCache(args) {
|
|
|
26203
26088
|
process.exit(1);
|
|
26204
26089
|
}
|
|
26205
26090
|
} else if (sub === "clean") {
|
|
26206
|
-
if (!
|
|
26091
|
+
if (!existsSync12(CACHE_DIR)) {
|
|
26207
26092
|
log("Cache is already empty.");
|
|
26208
26093
|
return;
|
|
26209
26094
|
}
|
|
26210
26095
|
try {
|
|
26211
|
-
const files =
|
|
26096
|
+
const files = readdirSync7(CACHE_DIR);
|
|
26212
26097
|
let totalSize = 0;
|
|
26213
26098
|
for (const file of files) {
|
|
26214
|
-
totalSize +=
|
|
26099
|
+
totalSize += statSync7(join13(CACHE_DIR, file)).size;
|
|
26215
26100
|
}
|
|
26216
26101
|
rmSync3(CACHE_DIR, { recursive: true, force: true });
|
|
26217
26102
|
log(
|
|
@@ -26326,8 +26211,8 @@ async function handleDeprecate(args) {
|
|
|
26326
26211
|
}
|
|
26327
26212
|
|
|
26328
26213
|
// src/commands-snippets.ts
|
|
26329
|
-
import { readFileSync as
|
|
26330
|
-
import { resolve as resolve10, basename as basename6, extname as extname4, join as
|
|
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";
|
|
26331
26216
|
import { homedir as homedir10, platform as platform10 } from "node:os";
|
|
26332
26217
|
import { createInterface as createInterface5 } from "node:readline";
|
|
26333
26218
|
var PLATFORM_URL4 = process.env.ROBINPATH_PLATFORM_URL || "https://api.robinpath.com";
|
|
@@ -26563,11 +26448,11 @@ async function snippetCreate(args) {
|
|
|
26563
26448
|
defaultName = "untitled";
|
|
26564
26449
|
} else {
|
|
26565
26450
|
const filePath = resolve10(fileArg);
|
|
26566
|
-
if (!
|
|
26451
|
+
if (!existsSync13(filePath)) {
|
|
26567
26452
|
console.error(color.red("Error:") + ` File not found: ${fileArg}`);
|
|
26568
26453
|
process.exit(1);
|
|
26569
26454
|
}
|
|
26570
|
-
code =
|
|
26455
|
+
code = readFileSync12(filePath, "utf-8");
|
|
26571
26456
|
defaultName = basename6(filePath, extname4(filePath));
|
|
26572
26457
|
}
|
|
26573
26458
|
if (!code || !code.trim()) {
|
|
@@ -26589,8 +26474,8 @@ async function snippetCreate(args) {
|
|
|
26589
26474
|
if (flags.version) payload.version = flags.version;
|
|
26590
26475
|
if (flags.readme) {
|
|
26591
26476
|
const readmePath = resolve10(flags.readme);
|
|
26592
|
-
if (
|
|
26593
|
-
payload.readme =
|
|
26477
|
+
if (existsSync13(readmePath)) {
|
|
26478
|
+
payload.readme = readFileSync12(readmePath, "utf-8");
|
|
26594
26479
|
}
|
|
26595
26480
|
}
|
|
26596
26481
|
try {
|
|
@@ -26673,12 +26558,12 @@ async function snippetInit(args) {
|
|
|
26673
26558
|
code = codeLines.join("\n");
|
|
26674
26559
|
} else {
|
|
26675
26560
|
const filePath = await ask("File path", "");
|
|
26676
|
-
if (!filePath || !
|
|
26561
|
+
if (!filePath || !existsSync13(resolve10(filePath))) {
|
|
26677
26562
|
console.error(color.red("Error:") + " File not found.");
|
|
26678
26563
|
rl.close();
|
|
26679
26564
|
process.exit(1);
|
|
26680
26565
|
}
|
|
26681
|
-
code =
|
|
26566
|
+
code = readFileSync12(resolve10(filePath), "utf-8");
|
|
26682
26567
|
}
|
|
26683
26568
|
rl.close();
|
|
26684
26569
|
if (!code.trim()) {
|
|
@@ -26835,16 +26720,16 @@ async function snippetUpdate(args) {
|
|
|
26835
26720
|
payload.tags = flags.tags.split(",").map((t) => t.trim()).filter(Boolean);
|
|
26836
26721
|
if (flags.code) {
|
|
26837
26722
|
const codePath = resolve10(flags.code);
|
|
26838
|
-
if (!
|
|
26723
|
+
if (!existsSync13(codePath)) {
|
|
26839
26724
|
console.error(color.red("Error:") + ` Code file not found: ${flags.code}`);
|
|
26840
26725
|
process.exit(1);
|
|
26841
26726
|
}
|
|
26842
|
-
payload.code =
|
|
26727
|
+
payload.code = readFileSync12(codePath, "utf-8");
|
|
26843
26728
|
}
|
|
26844
26729
|
if (flags.readme) {
|
|
26845
26730
|
const readmePath = resolve10(flags.readme);
|
|
26846
|
-
if (
|
|
26847
|
-
payload.readme =
|
|
26731
|
+
if (existsSync13(readmePath)) {
|
|
26732
|
+
payload.readme = readFileSync12(readmePath, "utf-8");
|
|
26848
26733
|
}
|
|
26849
26734
|
}
|
|
26850
26735
|
if (Object.keys(payload).length === 0) {
|
|
@@ -27220,16 +27105,16 @@ async function snippetCopy(args) {
|
|
|
27220
27105
|
process.exit(1);
|
|
27221
27106
|
}
|
|
27222
27107
|
}
|
|
27223
|
-
var SNIPPET_CACHE_DIR =
|
|
27108
|
+
var SNIPPET_CACHE_DIR = join14(homedir10(), ".robinpath", "cache", "snippets");
|
|
27224
27109
|
var SNIPPET_CACHE_TTL = 5 * 60 * 1e3;
|
|
27225
27110
|
function getSnippetCachePath(id) {
|
|
27226
|
-
return
|
|
27111
|
+
return join14(SNIPPET_CACHE_DIR, `${id}.json`);
|
|
27227
27112
|
}
|
|
27228
27113
|
function readSnippetCache(id) {
|
|
27229
27114
|
try {
|
|
27230
27115
|
const cachePath = getSnippetCachePath(id);
|
|
27231
|
-
if (!
|
|
27232
|
-
const raw = JSON.parse(
|
|
27116
|
+
if (!existsSync13(cachePath)) return null;
|
|
27117
|
+
const raw = JSON.parse(readFileSync12(cachePath, "utf-8"));
|
|
27233
27118
|
if (Date.now() - (raw._cachedAt || 0) > SNIPPET_CACHE_TTL) return null;
|
|
27234
27119
|
return raw;
|
|
27235
27120
|
} catch {
|
|
@@ -27238,7 +27123,7 @@ function readSnippetCache(id) {
|
|
|
27238
27123
|
}
|
|
27239
27124
|
function writeSnippetCache(id, data) {
|
|
27240
27125
|
try {
|
|
27241
|
-
if (!
|
|
27126
|
+
if (!existsSync13(SNIPPET_CACHE_DIR)) {
|
|
27242
27127
|
mkdirSync8(SNIPPET_CACHE_DIR, { recursive: true });
|
|
27243
27128
|
}
|
|
27244
27129
|
writeFileSync8(getSnippetCachePath(id), JSON.stringify({ ...data, _cachedAt: Date.now() }), "utf-8");
|
|
@@ -27352,11 +27237,11 @@ async function snippetPush(args) {
|
|
|
27352
27237
|
}
|
|
27353
27238
|
id = await resolveSnippetId(id);
|
|
27354
27239
|
const filePath = resolve10(fileArg);
|
|
27355
|
-
if (!
|
|
27240
|
+
if (!existsSync13(filePath)) {
|
|
27356
27241
|
console.error(color.red("Error:") + ` File not found: ${fileArg}`);
|
|
27357
27242
|
process.exit(1);
|
|
27358
27243
|
}
|
|
27359
|
-
const code =
|
|
27244
|
+
const code = readFileSync12(filePath, "utf-8");
|
|
27360
27245
|
if (!code.trim()) {
|
|
27361
27246
|
console.error(color.red("Error:") + " File is empty.");
|
|
27362
27247
|
process.exit(1);
|
|
@@ -27440,11 +27325,11 @@ async function snippetDiff(args) {
|
|
|
27440
27325
|
}
|
|
27441
27326
|
id = await resolveSnippetId(id);
|
|
27442
27327
|
const filePath = resolve10(fileArg);
|
|
27443
|
-
if (!
|
|
27328
|
+
if (!existsSync13(filePath)) {
|
|
27444
27329
|
console.error(color.red("Error:") + ` File not found: ${fileArg}`);
|
|
27445
27330
|
process.exit(1);
|
|
27446
27331
|
}
|
|
27447
|
-
const localCode =
|
|
27332
|
+
const localCode = readFileSync12(filePath, "utf-8");
|
|
27448
27333
|
try {
|
|
27449
27334
|
const res = await fetchSnippet(id);
|
|
27450
27335
|
if (!res.ok) {
|
|
@@ -27564,13 +27449,13 @@ async function snippetImport(args) {
|
|
|
27564
27449
|
process.exit(2);
|
|
27565
27450
|
}
|
|
27566
27451
|
const filePath = resolve10(fileArg);
|
|
27567
|
-
if (!
|
|
27452
|
+
if (!existsSync13(filePath)) {
|
|
27568
27453
|
console.error(color.red("Error:") + ` File not found: ${fileArg}`);
|
|
27569
27454
|
process.exit(1);
|
|
27570
27455
|
}
|
|
27571
27456
|
let importData;
|
|
27572
27457
|
try {
|
|
27573
|
-
importData = JSON.parse(
|
|
27458
|
+
importData = JSON.parse(readFileSync12(filePath, "utf-8"));
|
|
27574
27459
|
} catch {
|
|
27575
27460
|
console.error(color.red("Error:") + " Invalid JSON file.");
|
|
27576
27461
|
process.exit(1);
|
|
@@ -27637,8 +27522,8 @@ async function snippetImport(args) {
|
|
|
27637
27522
|
|
|
27638
27523
|
// src/commands-cloud.ts
|
|
27639
27524
|
import { createServer as createServer4 } from "node:http";
|
|
27640
|
-
import { readFileSync as
|
|
27641
|
-
import { resolve as resolve11, join as
|
|
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";
|
|
27642
27527
|
import { execSync as execSync3 } from "node:child_process";
|
|
27643
27528
|
import { tmpdir as tmpdir4, hostname as hostname3 } from "node:os";
|
|
27644
27529
|
var CLOUD_URL2 = process.env.ROBINPATH_CLOUD_URL || "https://dev.robinpath.com";
|
|
@@ -27774,14 +27659,14 @@ async function handlePublish(args) {
|
|
|
27774
27659
|
const isDryRun = args.includes("--dry-run");
|
|
27775
27660
|
const targetArg = args.find((a) => !a.startsWith("-") && !a.startsWith("--org")) || ".";
|
|
27776
27661
|
const targetDir = resolve11(targetArg);
|
|
27777
|
-
const pkgPath =
|
|
27778
|
-
if (!
|
|
27662
|
+
const pkgPath = join15(targetDir, "package.json");
|
|
27663
|
+
if (!existsSync14(pkgPath)) {
|
|
27779
27664
|
console.error(color.red("Error:") + ` No package.json found in ${targetDir}`);
|
|
27780
27665
|
process.exit(2);
|
|
27781
27666
|
}
|
|
27782
27667
|
let pkg;
|
|
27783
27668
|
try {
|
|
27784
|
-
pkg = JSON.parse(
|
|
27669
|
+
pkg = JSON.parse(readFileSync13(pkgPath, "utf-8"));
|
|
27785
27670
|
} catch (err) {
|
|
27786
27671
|
console.error(color.red("Error:") + ` Invalid package.json: ${err.message}`);
|
|
27787
27672
|
process.exit(2);
|
|
@@ -27825,7 +27710,7 @@ async function handlePublish(args) {
|
|
|
27825
27710
|
scope = emailPrefix;
|
|
27826
27711
|
name = pkg.name;
|
|
27827
27712
|
}
|
|
27828
|
-
const tmpFile =
|
|
27713
|
+
const tmpFile = join15(tmpdir4(), `robinpath-publish-${Date.now()}.tar.gz`);
|
|
27829
27714
|
const parentDir = dirname5(targetDir);
|
|
27830
27715
|
const dirName = basename7(targetDir);
|
|
27831
27716
|
log(`Packing @${scope}/${name}@${pkg.version} (${visibility})...`);
|
|
@@ -27842,7 +27727,7 @@ async function handlePublish(args) {
|
|
|
27842
27727
|
console.error(color.red("Error:") + ` Failed to create tarball: ${err.message}`);
|
|
27843
27728
|
process.exit(1);
|
|
27844
27729
|
}
|
|
27845
|
-
const tarball =
|
|
27730
|
+
const tarball = readFileSync13(tmpFile);
|
|
27846
27731
|
const maxSize = 50 * 1024 * 1024;
|
|
27847
27732
|
if (tarball.length > maxSize) {
|
|
27848
27733
|
unlinkSync6(tmpFile);
|
|
@@ -28154,7 +28039,7 @@ async function main() {
|
|
|
28154
28039
|
return;
|
|
28155
28040
|
}
|
|
28156
28041
|
if (command === "install") {
|
|
28157
|
-
|
|
28042
|
+
existsSync15(resolve12("robinpath.json")) ? await handleProjectInstall() : handleInstall();
|
|
28158
28043
|
return;
|
|
28159
28044
|
}
|
|
28160
28045
|
if (command === "uninstall") {
|
|
@@ -28273,7 +28158,7 @@ async function main() {
|
|
|
28273
28158
|
}
|
|
28274
28159
|
process.exit(2);
|
|
28275
28160
|
}
|
|
28276
|
-
const script =
|
|
28161
|
+
const script = readFileSync14(filePath, "utf-8");
|
|
28277
28162
|
const hasWatch = args.includes("--watch");
|
|
28278
28163
|
const hasShortWatch = args.includes("-w") && command !== "fmt";
|
|
28279
28164
|
if (hasWatch || hasShortWatch) {
|