nexrall-code 0.5.24 → 0.5.28
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/index.js +313 -33
- package/package.json +11 -10
package/dist/index.js
CHANGED
|
@@ -12673,7 +12673,7 @@ Resolve the conflict (remove <<<<<<< / ======= / >>>>>>> markers and keep the in
|
|
|
12673
12673
|
var _bgCounter = 0;
|
|
12674
12674
|
function startBackgroundShell(command, displayCommand, workDir, note) {
|
|
12675
12675
|
const id = `bg_${++_bgCounter}`;
|
|
12676
|
-
const child = (0, child_process_1.spawn)(command, { shell: true, cwd: workDir ?? process.cwd(), env: process.env, detached: true });
|
|
12676
|
+
const child = (0, child_process_1.spawn)(command, { shell: true, cwd: workDir ?? process.cwd(), env: process.env, detached: true, stdio: ["ignore", "pipe", "pipe"] });
|
|
12677
12677
|
const shell = {
|
|
12678
12678
|
id,
|
|
12679
12679
|
command: displayCommand,
|
|
@@ -12835,7 +12835,8 @@ ${r2.output}`;
|
|
|
12835
12835
|
shell: true,
|
|
12836
12836
|
cwd: workDir ?? process.cwd(),
|
|
12837
12837
|
env: process.env,
|
|
12838
|
-
detached: true
|
|
12838
|
+
detached: true,
|
|
12839
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
12839
12840
|
});
|
|
12840
12841
|
const killTree = (sig) => {
|
|
12841
12842
|
try {
|
|
@@ -23209,22 +23210,6 @@ var icons = {
|
|
|
23209
23210
|
thinking: "\u25C6",
|
|
23210
23211
|
code: "{}"
|
|
23211
23212
|
};
|
|
23212
|
-
function banner() {
|
|
23213
|
-
const version = "0.1.1";
|
|
23214
|
-
console.log();
|
|
23215
|
-
console.log(source_default.bold.blue(" \u2588\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557"));
|
|
23216
|
-
console.log(source_default.bold.blue(" \u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u255A\u2588\u2588\u2557\u2588\u2588\u2554\u255D"));
|
|
23217
|
-
console.log(source_default.bold.blue(" \u2588\u2588\u2554\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2557 \u255A\u2588\u2588\u2588\u2554\u255D "));
|
|
23218
|
-
console.log(source_default.bold.blue(" \u2588\u2588\u2551\u255A\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2554\u2588\u2588\u2557 "));
|
|
23219
|
-
console.log(source_default.bold.blue(" \u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2554\u255D \u2588\u2588\u2557"));
|
|
23220
|
-
console.log(source_default.bold.blue(" \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D"));
|
|
23221
|
-
console.log();
|
|
23222
|
-
console.log(
|
|
23223
|
-
source_default.bold(" Nexrall Code") + source_default.dim(` v${version}`) + source_default.dim(" \xB7 ") + source_default.cyan("AI coding assistant")
|
|
23224
|
-
);
|
|
23225
|
-
console.log(source_default.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
23226
|
-
console.log();
|
|
23227
|
-
}
|
|
23228
23213
|
function visibleLen(s2) {
|
|
23229
23214
|
return s2.replace(/\x1b\[[0-9;]*m/g, "").length;
|
|
23230
23215
|
}
|
|
@@ -23468,6 +23453,77 @@ function formatUsage(outputTokens) {
|
|
|
23468
23453
|
return source_default.dim(`\u2193 ${tok} tokens`);
|
|
23469
23454
|
}
|
|
23470
23455
|
|
|
23456
|
+
// src/ui/paste.ts
|
|
23457
|
+
var PASTE_START = "\x1B[200~";
|
|
23458
|
+
var PASTE_END = "\x1B[201~";
|
|
23459
|
+
function enableBracketedPaste() {
|
|
23460
|
+
if (process.stdout.isTTY)
|
|
23461
|
+
process.stdout.write("\x1B[?2004h");
|
|
23462
|
+
}
|
|
23463
|
+
function disableBracketedPaste() {
|
|
23464
|
+
if (process.stdout.isTTY)
|
|
23465
|
+
process.stdout.write("\x1B[?2004l");
|
|
23466
|
+
}
|
|
23467
|
+
function installPasteHandling(rl, stdin) {
|
|
23468
|
+
const originalListeners = stdin.listeners("data");
|
|
23469
|
+
for (const l of originalListeners)
|
|
23470
|
+
stdin.removeListener("data", l);
|
|
23471
|
+
const forward = (buf) => {
|
|
23472
|
+
if (!buf.length)
|
|
23473
|
+
return;
|
|
23474
|
+
for (const l of originalListeners)
|
|
23475
|
+
l.call(stdin, buf);
|
|
23476
|
+
};
|
|
23477
|
+
let buffering = false;
|
|
23478
|
+
let buffer = "";
|
|
23479
|
+
const insertPastedText = (text) => {
|
|
23480
|
+
if (!text)
|
|
23481
|
+
return;
|
|
23482
|
+
const flattened = text.replace(/\r\n|\r|\n/g, " ");
|
|
23483
|
+
const anyRl = rl;
|
|
23484
|
+
if (typeof anyRl._insertString === "function") {
|
|
23485
|
+
anyRl._insertString(flattened);
|
|
23486
|
+
} else {
|
|
23487
|
+
rl.write(flattened);
|
|
23488
|
+
}
|
|
23489
|
+
};
|
|
23490
|
+
const onData = (chunk) => {
|
|
23491
|
+
let text = chunk.toString("utf-8");
|
|
23492
|
+
for (; ; ) {
|
|
23493
|
+
if (!buffering) {
|
|
23494
|
+
const startIdx = text.indexOf(PASTE_START);
|
|
23495
|
+
if (startIdx === -1) {
|
|
23496
|
+
forward(Buffer.from(text, "utf-8"));
|
|
23497
|
+
return;
|
|
23498
|
+
}
|
|
23499
|
+
const before = text.slice(0, startIdx);
|
|
23500
|
+
forward(Buffer.from(before, "utf-8"));
|
|
23501
|
+
text = text.slice(startIdx + PASTE_START.length);
|
|
23502
|
+
buffering = true;
|
|
23503
|
+
buffer = "";
|
|
23504
|
+
}
|
|
23505
|
+
const endIdx = text.indexOf(PASTE_END);
|
|
23506
|
+
if (endIdx === -1) {
|
|
23507
|
+
buffer += text;
|
|
23508
|
+
return;
|
|
23509
|
+
}
|
|
23510
|
+
buffer += text.slice(0, endIdx);
|
|
23511
|
+
insertPastedText(buffer);
|
|
23512
|
+
buffer = "";
|
|
23513
|
+
buffering = false;
|
|
23514
|
+
text = text.slice(endIdx + PASTE_END.length);
|
|
23515
|
+
if (!text)
|
|
23516
|
+
return;
|
|
23517
|
+
}
|
|
23518
|
+
};
|
|
23519
|
+
stdin.on("data", onData);
|
|
23520
|
+
return () => {
|
|
23521
|
+
stdin.removeListener("data", onData);
|
|
23522
|
+
for (const l of originalListeners)
|
|
23523
|
+
stdin.on("data", l);
|
|
23524
|
+
};
|
|
23525
|
+
}
|
|
23526
|
+
|
|
23471
23527
|
// src/permissions/handler.ts
|
|
23472
23528
|
var readline2 = __toESM(require("readline"));
|
|
23473
23529
|
var fs2 = __toESM(require("fs"));
|
|
@@ -24022,6 +24078,9 @@ function setAutoApprove(category) {
|
|
|
24022
24078
|
function isAutoApproved(category) {
|
|
24023
24079
|
return autoApproved.has("all") || autoApproved.has(category);
|
|
24024
24080
|
}
|
|
24081
|
+
function isYoloMode() {
|
|
24082
|
+
return autoApproved.has("all");
|
|
24083
|
+
}
|
|
24025
24084
|
var _replInterface = null;
|
|
24026
24085
|
function setReadlineInterface(rl) {
|
|
24027
24086
|
_replInterface = rl;
|
|
@@ -24249,7 +24308,7 @@ async function requestPermission(req) {
|
|
|
24249
24308
|
var fs3 = __toESM(require("fs"));
|
|
24250
24309
|
var path = __toESM(require("path"));
|
|
24251
24310
|
var os2 = __toESM(require("os"));
|
|
24252
|
-
var SESSIONS_DIR = path.join(os2.homedir(), ".nexrall", "cli-sessions");
|
|
24311
|
+
var SESSIONS_DIR = process.env.NEXRALL_CLI_SESSIONS_DIR || path.join(os2.homedir(), ".nexrall", "cli-sessions");
|
|
24253
24312
|
function ensureDir() {
|
|
24254
24313
|
fs3.mkdirSync(SESSIONS_DIR, { recursive: true });
|
|
24255
24314
|
}
|
|
@@ -24484,7 +24543,118 @@ async function updateCommand(opts) {
|
|
|
24484
24543
|
console.log();
|
|
24485
24544
|
}
|
|
24486
24545
|
|
|
24546
|
+
// src/ui/screen.ts
|
|
24547
|
+
function enableAltScreen() {
|
|
24548
|
+
if (process.stdout.isTTY)
|
|
24549
|
+
process.stdout.write("\x1B[?1049h");
|
|
24550
|
+
}
|
|
24551
|
+
function disableAltScreen() {
|
|
24552
|
+
if (process.stdout.isTTY)
|
|
24553
|
+
process.stdout.write("\x1B[?1049l");
|
|
24554
|
+
}
|
|
24555
|
+
var NEX_LOGO = [
|
|
24556
|
+
"\u2588\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557",
|
|
24557
|
+
"\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u255A\u2588\u2588\u2557\u2588\u2588\u2554\u255D",
|
|
24558
|
+
"\u2588\u2588\u2554\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2557 \u255A\u2588\u2588\u2588\u2554\u255D ",
|
|
24559
|
+
"\u2588\u2588\u2551\u255A\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2554\u2588\u2588\u2557 ",
|
|
24560
|
+
"\u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2554\u255D \u2588\u2588\u2557",
|
|
24561
|
+
"\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D"
|
|
24562
|
+
];
|
|
24563
|
+
function center(s2, w) {
|
|
24564
|
+
const len = visibleLen(s2);
|
|
24565
|
+
if (len >= w)
|
|
24566
|
+
return s2;
|
|
24567
|
+
const left = Math.floor((w - len) / 2);
|
|
24568
|
+
return " ".repeat(left) + s2;
|
|
24569
|
+
}
|
|
24570
|
+
function renderBanner(info) {
|
|
24571
|
+
const LEFT_W = 38;
|
|
24572
|
+
const RIGHT_W = 44;
|
|
24573
|
+
const GAP = 2;
|
|
24574
|
+
const leftLines = [];
|
|
24575
|
+
leftLines.push(source_default.bold.hex("#d97757")(`Nexrall Code `) + source_default.dim(`v${info.version}`));
|
|
24576
|
+
leftLines.push("");
|
|
24577
|
+
leftLines.push(center(source_default.bold(`Welcome back ${info.userLabel}!`), LEFT_W));
|
|
24578
|
+
leftLines.push("");
|
|
24579
|
+
for (const l of NEX_LOGO)
|
|
24580
|
+
leftLines.push(center(source_default.hex("#d97757")(l), LEFT_W));
|
|
24581
|
+
leftLines.push("");
|
|
24582
|
+
leftLines.push(source_default.dim(info.modelLabel));
|
|
24583
|
+
leftLines.push(source_default.dim(info.workDir));
|
|
24584
|
+
if (info.nexrallMdLoaded)
|
|
24585
|
+
leftLines.push(source_default.dim("nexrall.md loaded"));
|
|
24586
|
+
const rightLines = [];
|
|
24587
|
+
rightLines.push(source_default.bold.yellow("Tips for getting started"));
|
|
24588
|
+
const tips = info.tips ?? [
|
|
24589
|
+
"Run /init to create a nexrall.md file with instructions for Nexrall Code.",
|
|
24590
|
+
"Use /help to see all slash commands."
|
|
24591
|
+
];
|
|
24592
|
+
for (const t2 of tips)
|
|
24593
|
+
rightLines.push(...wrapText(t2, RIGHT_W));
|
|
24594
|
+
const whatsNew = info.whatsNew ?? [];
|
|
24595
|
+
if (whatsNew.length) {
|
|
24596
|
+
rightLines.push("");
|
|
24597
|
+
rightLines.push(source_default.bold.yellow("What's new"));
|
|
24598
|
+
for (const t2 of whatsNew)
|
|
24599
|
+
rightLines.push(...wrapText(t2, RIGHT_W));
|
|
24600
|
+
rightLines.push(source_default.dim.italic("/release-notes for more"));
|
|
24601
|
+
}
|
|
24602
|
+
const rowCount = Math.max(leftLines.length, rightLines.length);
|
|
24603
|
+
const border = source_default.hex("#d97757");
|
|
24604
|
+
const lines = [];
|
|
24605
|
+
lines.push(border("\u256D" + "\u2500".repeat(LEFT_W + GAP + RIGHT_W + 4) + "\u256E"));
|
|
24606
|
+
for (let i2 = 0; i2 < rowCount; i2++) {
|
|
24607
|
+
const l = padVis(leftLines[i2] ?? "", LEFT_W);
|
|
24608
|
+
const r2 = padVis(rightLines[i2] ?? "", RIGHT_W);
|
|
24609
|
+
lines.push(border("\u2502 ") + l + " ".repeat(GAP) + r2 + border(" \u2502"));
|
|
24610
|
+
}
|
|
24611
|
+
lines.push(border("\u2570" + "\u2500".repeat(LEFT_W + GAP + RIGHT_W + 4) + "\u256F"));
|
|
24612
|
+
return lines.join("\n");
|
|
24613
|
+
}
|
|
24614
|
+
function wrapText(text, width) {
|
|
24615
|
+
const words = text.split(" ");
|
|
24616
|
+
const out = [];
|
|
24617
|
+
let cur = "";
|
|
24618
|
+
for (const w of words) {
|
|
24619
|
+
const candidate = cur ? cur + " " + w : w;
|
|
24620
|
+
if (visibleLen(candidate) > width && cur) {
|
|
24621
|
+
out.push(cur);
|
|
24622
|
+
cur = w;
|
|
24623
|
+
} else {
|
|
24624
|
+
cur = candidate;
|
|
24625
|
+
}
|
|
24626
|
+
}
|
|
24627
|
+
if (cur)
|
|
24628
|
+
out.push(cur);
|
|
24629
|
+
return out;
|
|
24630
|
+
}
|
|
24631
|
+
var lastFooterText = "";
|
|
24632
|
+
function footerText(info) {
|
|
24633
|
+
const modeLabel = info.autoApprove ? "yolo mode on" : info.mode === "plan" ? "plan mode on" : info.mode === "edit" ? "edit mode on" : info.mode === "ask" ? "ask mode on" : "auto mode on";
|
|
24634
|
+
return `${modeLabel} \xB7 /help for shortcuts \xB7 /agents for agents`;
|
|
24635
|
+
}
|
|
24636
|
+
function drawStatusFooter(info) {
|
|
24637
|
+
if (!process.stdout.isTTY || !process.stdout.rows)
|
|
24638
|
+
return;
|
|
24639
|
+
const text = footerText(info);
|
|
24640
|
+
if (text === lastFooterText)
|
|
24641
|
+
return;
|
|
24642
|
+
lastFooterText = text;
|
|
24643
|
+
const row = process.stdout.rows;
|
|
24644
|
+
const out = `\x1B7\x1B[${row};1H\x1B[2K` + // clear the line
|
|
24645
|
+
source_default.dim(text) + "\x1B8";
|
|
24646
|
+
process.stdout.write(out);
|
|
24647
|
+
}
|
|
24648
|
+
function clearStatusFooter() {
|
|
24649
|
+
if (!process.stdout.isTTY || !process.stdout.rows)
|
|
24650
|
+
return;
|
|
24651
|
+
const row = process.stdout.rows;
|
|
24652
|
+
process.stdout.write(`\x1B7\x1B[${row};1H\x1B[2K\x1B8`);
|
|
24653
|
+
lastFooterText = "";
|
|
24654
|
+
}
|
|
24655
|
+
|
|
24487
24656
|
// src/commands/chat.ts
|
|
24657
|
+
var CLI_VERSION = "0.5.28";
|
|
24488
24658
|
var MODEL_LABELS = {
|
|
24489
24659
|
turbo: "Nexrall Turbo",
|
|
24490
24660
|
pro: "Nexrall Pro",
|
|
@@ -24517,6 +24687,14 @@ function printBalanceNotice(balance, zero) {
|
|
|
24517
24687
|
console.log(" " + source_default.yellow(hyperlink("\u2192 Top up", BILLING_URL)) + source_default.dim(` (${BILLING_URL})`));
|
|
24518
24688
|
console.log();
|
|
24519
24689
|
}
|
|
24690
|
+
function currentUserLabel() {
|
|
24691
|
+
try {
|
|
24692
|
+
const u = os4.userInfo().username;
|
|
24693
|
+
return u ? u.charAt(0).toUpperCase() + u.slice(1) : "there";
|
|
24694
|
+
} catch {
|
|
24695
|
+
return "there";
|
|
24696
|
+
}
|
|
24697
|
+
}
|
|
24520
24698
|
function collectEnv(workDir) {
|
|
24521
24699
|
return {
|
|
24522
24700
|
cwd: workDir,
|
|
@@ -24565,10 +24743,17 @@ var Spinner = class {
|
|
|
24565
24743
|
interval = null;
|
|
24566
24744
|
frames = ["\u25D0", "\u25D3", "\u25D1", "\u25D2"];
|
|
24567
24745
|
i = 0;
|
|
24746
|
+
startedAt = 0;
|
|
24747
|
+
baseText = "";
|
|
24568
24748
|
start(text) {
|
|
24569
24749
|
this.stop();
|
|
24750
|
+
this.baseText = text;
|
|
24751
|
+
this.startedAt = Date.now();
|
|
24570
24752
|
this.interval = setInterval(() => {
|
|
24571
|
-
|
|
24753
|
+
const elapsedSec = Math.floor((Date.now() - this.startedAt) / 1e3);
|
|
24754
|
+
const timer = source_default.dim(` (${elapsedSec}s)`);
|
|
24755
|
+
const hint = elapsedSec >= 15 ? source_default.dim(" \xB7 still running, no output yet is normal for quiet commands") : "";
|
|
24756
|
+
process.stdout.write(`\r\x1B[K${source_default.cyan(this.frames[this.i % this.frames.length])} ${source_default.dim(this.baseText)}${timer}${hint}`);
|
|
24572
24757
|
this.i++;
|
|
24573
24758
|
}, 100);
|
|
24574
24759
|
}
|
|
@@ -24889,6 +25074,7 @@ function printHelp() {
|
|
|
24889
25074
|
["/yolo", "Auto-approve all permissions"],
|
|
24890
25075
|
["/balance", "Show wallet balance"],
|
|
24891
25076
|
["/add <filepath>", "Add a file to conversation context"],
|
|
25077
|
+
["/image <filepath> [caption]", "Attach an image or PDF (png/jpg/gif/webp/pdf, max 10MB) and send it to the model"],
|
|
24892
25078
|
["/skills", "List skills (.nexrall/skills/<name>/SKILL.md or .nexrall/commands/*.md) \u2014 the model can also auto-invoke these"],
|
|
24893
25079
|
["/plugins", "List installed plugins (.nexrall/plugins/)"],
|
|
24894
25080
|
["/mcp", "Show MCP server connection status"],
|
|
@@ -24921,25 +25107,34 @@ function printSessions() {
|
|
|
24921
25107
|
}
|
|
24922
25108
|
async function startChatSession(options) {
|
|
24923
25109
|
const headless = options.outputFormat === "json" || options.outputFormat === "stream-json";
|
|
24924
|
-
if (options.showBanner !== false && !headless)
|
|
24925
|
-
banner();
|
|
24926
25110
|
const { workDir } = options;
|
|
24927
25111
|
let modelAlias = options.model;
|
|
24928
25112
|
const env2 = collectEnv(workDir);
|
|
24929
25113
|
const nexrallMd = readNexrallMd(workDir);
|
|
24930
|
-
|
|
24931
|
-
|
|
24932
|
-
|
|
24933
|
-
|
|
25114
|
+
const interactive = !headless && !options.prompt && !options.stdinText;
|
|
25115
|
+
if (interactive) {
|
|
25116
|
+
enableAltScreen();
|
|
25117
|
+
process.on("exit", () => {
|
|
25118
|
+
clearStatusFooter();
|
|
25119
|
+
disableAltScreen();
|
|
25120
|
+
});
|
|
25121
|
+
}
|
|
25122
|
+
if (options.showBanner !== false && !headless) {
|
|
24934
25123
|
const branch = tryExec("git branch --show-current", workDir);
|
|
24935
25124
|
const gitStatus = tryExec("git status --short", workDir);
|
|
25125
|
+
const changedLines = gitStatus ? gitStatus.split("\n").filter(Boolean).length : 0;
|
|
25126
|
+
const tips = ["Run /init to create a nexrall.md file with instructions for Nexrall Code."];
|
|
24936
25127
|
if (branch) {
|
|
24937
|
-
|
|
24938
|
-
|
|
24939
|
-
|
|
24940
|
-
|
|
24941
|
-
|
|
24942
|
-
|
|
25128
|
+
tips.push(`On branch ${branch}${changedLines > 0 ? ` (${changedLines} changed)` : ""}.`);
|
|
25129
|
+
}
|
|
25130
|
+
console.log(renderBanner({
|
|
25131
|
+
version: CLI_VERSION,
|
|
25132
|
+
userLabel: currentUserLabel(),
|
|
25133
|
+
modelLabel: resolveModelLabel(modelAlias),
|
|
25134
|
+
workDir,
|
|
25135
|
+
nexrallMdLoaded: !!nexrallMd,
|
|
25136
|
+
tips
|
|
25137
|
+
}));
|
|
24943
25138
|
console.log();
|
|
24944
25139
|
}
|
|
24945
25140
|
let messages = [];
|
|
@@ -25103,6 +25298,16 @@ ${text}` : "");
|
|
|
25103
25298
|
prompt: colors.primary.bold("> ")
|
|
25104
25299
|
});
|
|
25105
25300
|
setReadlineInterface(rl);
|
|
25301
|
+
enableBracketedPaste();
|
|
25302
|
+
process.on("exit", disableBracketedPaste);
|
|
25303
|
+
const uninstallPasteHandling = installPasteHandling(rl, process.stdin);
|
|
25304
|
+
const originalPrompt = rl.prompt.bind(rl);
|
|
25305
|
+
rl.prompt = (preserveCursor) => {
|
|
25306
|
+
if (interactive) {
|
|
25307
|
+
drawStatusFooter({ mode: agentMode, autoApprove: isYoloMode() });
|
|
25308
|
+
}
|
|
25309
|
+
return originalPrompt(preserveCursor);
|
|
25310
|
+
};
|
|
25106
25311
|
rl.prompt();
|
|
25107
25312
|
let inputBuffer = "";
|
|
25108
25313
|
rl.on("line", async (rawLine) => {
|
|
@@ -25461,6 +25666,80 @@ ${content}
|
|
|
25461
25666
|
rl.prompt();
|
|
25462
25667
|
return;
|
|
25463
25668
|
}
|
|
25669
|
+
case "/image": {
|
|
25670
|
+
if (agentRunning) {
|
|
25671
|
+
console.log(source_default.red(" Cannot attach while agent is running."));
|
|
25672
|
+
rl.prompt();
|
|
25673
|
+
return;
|
|
25674
|
+
}
|
|
25675
|
+
if (!arg) {
|
|
25676
|
+
console.log(source_default.red(" Usage: /image <filepath> [caption]"));
|
|
25677
|
+
rl.prompt();
|
|
25678
|
+
return;
|
|
25679
|
+
}
|
|
25680
|
+
const [rawPath, ...captionParts] = arg.split(/\s+/);
|
|
25681
|
+
const caption = captionParts.join(" ").trim();
|
|
25682
|
+
const filePath = path3.isAbsolute(rawPath) ? rawPath : path3.join(workDir, rawPath);
|
|
25683
|
+
const ext = path3.extname(filePath).toLowerCase();
|
|
25684
|
+
const IMAGE_MIME = {
|
|
25685
|
+
".png": "image/png",
|
|
25686
|
+
".jpg": "image/jpeg",
|
|
25687
|
+
".jpeg": "image/jpeg",
|
|
25688
|
+
".gif": "image/gif",
|
|
25689
|
+
".webp": "image/webp"
|
|
25690
|
+
};
|
|
25691
|
+
const isPdf = ext === ".pdf";
|
|
25692
|
+
const mimeType = IMAGE_MIME[ext];
|
|
25693
|
+
if (!mimeType && !isPdf) {
|
|
25694
|
+
console.log(source_default.red(` Unsupported file type: ${ext || "(none)"}. Supported: png, jpg, jpeg, gif, webp, pdf.`));
|
|
25695
|
+
rl.prompt();
|
|
25696
|
+
return;
|
|
25697
|
+
}
|
|
25698
|
+
let buf;
|
|
25699
|
+
try {
|
|
25700
|
+
buf = fs5.readFileSync(filePath);
|
|
25701
|
+
} catch (err) {
|
|
25702
|
+
console.error(source_default.red(" Failed: ") + String(err.message));
|
|
25703
|
+
rl.prompt();
|
|
25704
|
+
return;
|
|
25705
|
+
}
|
|
25706
|
+
const MAX_BYTES = 10 * 1024 * 1024;
|
|
25707
|
+
if (buf.length > MAX_BYTES) {
|
|
25708
|
+
console.log(source_default.red(` File too large (${(buf.length / 1024 / 1024).toFixed(1)}MB) \u2014 max 10MB.`));
|
|
25709
|
+
rl.prompt();
|
|
25710
|
+
return;
|
|
25711
|
+
}
|
|
25712
|
+
const rel = path3.relative(workDir, filePath);
|
|
25713
|
+
const data = buf.toString("base64");
|
|
25714
|
+
const label = caption ? `[Attached: ${rel}]
|
|
25715
|
+
${caption}` : `[Attached: ${rel}]`;
|
|
25716
|
+
const content = [{ type: "text", text: label }];
|
|
25717
|
+
content.push(
|
|
25718
|
+
isPdf ? { type: "document", source: { type: "base64", media_type: "application/pdf", data } } : { type: "image", source: { type: "base64", media_type: mimeType, data } }
|
|
25719
|
+
);
|
|
25720
|
+
console.log(source_default.dim(` Attached ${rel} (${(buf.length / 1024).toFixed(0)}KB) \u2014 sending\u2026`));
|
|
25721
|
+
checkpoints.beginTurn(`/image ${rel}${caption ? " " + caption : ""}`, messages.length);
|
|
25722
|
+
messages.push({ role: "user", content });
|
|
25723
|
+
rl.pause();
|
|
25724
|
+
abortSignal.aborted = false;
|
|
25725
|
+
agentRunning = true;
|
|
25726
|
+
try {
|
|
25727
|
+
const result = await runTurn(messages, modelAlias, workDir, abortSignal, env2, nexrallMd, agentMode, effortLevel, checkpoints, saveProgress);
|
|
25728
|
+
messages = result.messages;
|
|
25729
|
+
updateTitle();
|
|
25730
|
+
saveSession(sessionId, sessionTitle, workDir, messages);
|
|
25731
|
+
} catch (err) {
|
|
25732
|
+
messages = recoverTurn(err, messages);
|
|
25733
|
+
updateTitle();
|
|
25734
|
+
saveSession(sessionId, sessionTitle || "Untitled", workDir, messages);
|
|
25735
|
+
} finally {
|
|
25736
|
+
agentRunning = false;
|
|
25737
|
+
checkpoints.commitTurn();
|
|
25738
|
+
}
|
|
25739
|
+
rl.resume();
|
|
25740
|
+
rl.prompt();
|
|
25741
|
+
return;
|
|
25742
|
+
}
|
|
25464
25743
|
case "/update": {
|
|
25465
25744
|
rl.close();
|
|
25466
25745
|
await updateCommand({ yes: false });
|
|
@@ -25584,6 +25863,7 @@ ${content}
|
|
|
25584
25863
|
rl.prompt();
|
|
25585
25864
|
});
|
|
25586
25865
|
rl.on("close", () => {
|
|
25866
|
+
uninstallPasteHandling();
|
|
25587
25867
|
updateTitle();
|
|
25588
25868
|
if (messages.length)
|
|
25589
25869
|
saveSession(sessionId, sessionTitle || "Untitled", workDir, messages);
|
|
@@ -25797,7 +26077,7 @@ function pluginListCommand() {
|
|
|
25797
26077
|
|
|
25798
26078
|
// src/index.ts
|
|
25799
26079
|
var program2 = new Command();
|
|
25800
|
-
program2.name("nex").description("Nexrall Code \u2014 AI coding assistant (powered by Nexrall)").version("0.5.
|
|
26080
|
+
program2.name("nex").description("Nexrall Code \u2014 AI coding assistant (powered by Nexrall)").version("0.5.28");
|
|
25801
26081
|
program2.command("auth").description("Login to your Nexrall account").action(authCommand);
|
|
25802
26082
|
program2.command("logout").description("Log out of your Nexrall account").action(logoutCommand);
|
|
25803
26083
|
program2.command("update").description("Update nex to the latest version").option("-c, --check", "Check for updates without installing").option("-y, --yes", "Skip confirmation prompt").action(async (opts) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nexrall-code",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.28",
|
|
4
4
|
"description": "Nexrall Code — AI coding assistant for your terminal (headless agent for scripts, CI and automation)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -30,14 +30,21 @@
|
|
|
30
30
|
"engines": {
|
|
31
31
|
"node": ">=18"
|
|
32
32
|
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build": "node build.js",
|
|
35
|
+
"dev": "tsx src/index.ts",
|
|
36
|
+
"start": "node dist/index.js",
|
|
37
|
+
"test": "tsc --noEmit && tsc --noEmit -p test/tsconfig.json && node --import tsx --test test/*.test.ts test/*.test.mts",
|
|
38
|
+
"release": "node build.js && node scripts/upload-release.js"
|
|
39
|
+
},
|
|
33
40
|
"dependencies": {
|
|
41
|
+
"@nexrall/code-core": "workspace:*",
|
|
34
42
|
"chalk": "^5.3.0",
|
|
35
43
|
"commander": "^12.0.0",
|
|
36
44
|
"diff": "^5.2.0",
|
|
37
45
|
"ora": "^8.0.1",
|
|
38
46
|
"prompts": "^2.4.2",
|
|
39
|
-
"readline": "^1.3.0"
|
|
40
|
-
"@nexrall/code-core": "1.4.19"
|
|
47
|
+
"readline": "^1.3.0"
|
|
41
48
|
},
|
|
42
49
|
"devDependencies": {
|
|
43
50
|
"@aws-sdk/client-s3": "^3.600.0",
|
|
@@ -47,11 +54,5 @@
|
|
|
47
54
|
"esbuild": "^0.20.0",
|
|
48
55
|
"tsx": "^4.7.0",
|
|
49
56
|
"typescript": "^6.0.3"
|
|
50
|
-
},
|
|
51
|
-
"scripts": {
|
|
52
|
-
"build": "node build.js",
|
|
53
|
-
"dev": "tsx src/index.ts",
|
|
54
|
-
"start": "node dist/index.js",
|
|
55
|
-
"release": "node build.js && node scripts/upload-release.js"
|
|
56
57
|
}
|
|
57
|
-
}
|
|
58
|
+
}
|