nexrall-code 0.5.70 → 0.5.72
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 +124 -29
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -9973,6 +9973,36 @@ var require_client = __commonJS({
|
|
|
9973
9973
|
const raw = Number(process.env.NEXRALL_MAX_RETRY_MS);
|
|
9974
9974
|
return Number.isFinite(raw) && raw > 0 ? raw : 5 * 6e4;
|
|
9975
9975
|
})();
|
|
9976
|
+
var headerTimeoutMs = () => Number(process.env.NEXRALL_HEADER_TIMEOUT_MS) || 12e4;
|
|
9977
|
+
async function fetchWithHeaderTimeout(url, init, outerSignal, timeoutMs = headerTimeoutMs()) {
|
|
9978
|
+
const headerController = new AbortController();
|
|
9979
|
+
const onOuterAbort = () => headerController.abort();
|
|
9980
|
+
if (outerSignal.aborted)
|
|
9981
|
+
headerController.abort();
|
|
9982
|
+
else
|
|
9983
|
+
outerSignal.addEventListener("abort", onOuterAbort, { once: true });
|
|
9984
|
+
let timedOut = false;
|
|
9985
|
+
const timer = setTimeout(() => {
|
|
9986
|
+
timedOut = true;
|
|
9987
|
+
headerController.abort();
|
|
9988
|
+
}, timeoutMs);
|
|
9989
|
+
try {
|
|
9990
|
+
return await (0, node_fetch_1.default)(url, { ...init, signal: headerController.signal });
|
|
9991
|
+
} catch (err) {
|
|
9992
|
+
if (timedOut && !outerSignal.aborted) {
|
|
9993
|
+
throw Object.assign(
|
|
9994
|
+
new Error(`The server accepted the connection but sent no response within ${Math.round(timeoutMs / 1e3)} s. Reconnecting\u2026`),
|
|
9995
|
+
// Retryable by definition: nothing was received, so a fresh attempt
|
|
9996
|
+
// cannot duplicate any rendered output.
|
|
9997
|
+
{ retryable: true }
|
|
9998
|
+
);
|
|
9999
|
+
}
|
|
10000
|
+
throw err;
|
|
10001
|
+
} finally {
|
|
10002
|
+
clearTimeout(timer);
|
|
10003
|
+
outerSignal.removeEventListener("abort", onOuterAbort);
|
|
10004
|
+
}
|
|
10005
|
+
}
|
|
9976
10006
|
function backoffMs(attempt) {
|
|
9977
10007
|
const exp = Math.min(RETRY_MAX_MS, RETRY_BASE_MS * Math.pow(2, attempt));
|
|
9978
10008
|
return Math.round(exp / 2 + Math.random() * (exp / 2));
|
|
@@ -9982,7 +10012,7 @@ var require_client = __commonJS({
|
|
|
9982
10012
|
}
|
|
9983
10013
|
var MAX_TOTAL_ATTEMPTS = (MAX_RETRIES + 1) * (MAX_RETRIES + 1);
|
|
9984
10014
|
async function streamChat(messages, options, onEvent) {
|
|
9985
|
-
const { model, env: env3, editorContext, nexrallMd, mode, effort, clientType, abortSignal, extraTools, agents, skills, allowRestartAfterRender, canWriteSharedMemory, hasOwnAgentStore, canSpawnSubAgents } = options;
|
|
10015
|
+
const { model, env: env3, editorContext, nexrallMd, mode, effort, clientType, abortSignal, extraTools, agents, skills, allowRestartAfterRender, canWriteSharedMemory, hasOwnAgentStore, canSpawnSubAgents, canBrowseWeb } = options;
|
|
9986
10016
|
let turnId = (0, crypto_1.randomUUID)();
|
|
9987
10017
|
const controller = new AbortController();
|
|
9988
10018
|
if (abortSignal?.aborted)
|
|
@@ -10008,13 +10038,14 @@ var require_client = __commonJS({
|
|
|
10008
10038
|
let emittedAnythingAcrossAttempts = false;
|
|
10009
10039
|
let emittedCharsAcrossAttempts = 0;
|
|
10010
10040
|
const buildFetchArgs = () => {
|
|
10041
|
+
const signal = controller.signal;
|
|
10011
10042
|
if (resuming) {
|
|
10012
10043
|
return [
|
|
10013
10044
|
`${exports.API_BASE}/api/code/chat/resume?turnId=${encodeURIComponent(turnId)}`,
|
|
10014
10045
|
{
|
|
10015
10046
|
method: "GET",
|
|
10016
10047
|
headers: { ...authHeaders(), "Last-Event-ID": String(lastEventId) },
|
|
10017
|
-
signal
|
|
10048
|
+
signal
|
|
10018
10049
|
}
|
|
10019
10050
|
];
|
|
10020
10051
|
}
|
|
@@ -10023,8 +10054,8 @@ var require_client = __commonJS({
|
|
|
10023
10054
|
{
|
|
10024
10055
|
method: "POST",
|
|
10025
10056
|
headers: authHeaders(),
|
|
10026
|
-
body: JSON.stringify({ messages, model, env: env3, editorContext, nexrallMd, mode, effort, clientType, extraTools, agents, skills, turnId, canWriteSharedMemory, hasOwnAgentStore, canSpawnSubAgents }),
|
|
10027
|
-
signal
|
|
10057
|
+
body: JSON.stringify({ messages, model, env: env3, editorContext, nexrallMd, mode, effort, clientType, extraTools, agents, skills, turnId, canWriteSharedMemory, hasOwnAgentStore, canSpawnSubAgents, canBrowseWeb }),
|
|
10058
|
+
signal
|
|
10028
10059
|
}
|
|
10029
10060
|
];
|
|
10030
10061
|
};
|
|
@@ -10085,7 +10116,7 @@ var require_client = __commonJS({
|
|
|
10085
10116
|
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
10086
10117
|
try {
|
|
10087
10118
|
errorBodyOverride = null;
|
|
10088
|
-
response = await (
|
|
10119
|
+
response = await fetchWithHeaderTimeout(...buildFetchArgs(), controller.signal);
|
|
10089
10120
|
if (response.status === 429 && attempt < MAX_RETRIES && canRetry()) {
|
|
10090
10121
|
reportRetry("Rate limited by the API \u2014 retrying");
|
|
10091
10122
|
const retryAfter = parseInt(response.headers.get("retry-after") ?? "0", 10);
|
|
@@ -16248,6 +16279,10 @@ var require_loop = __commonJS({
|
|
|
16248
16279
|
case "empty-response":
|
|
16249
16280
|
return `
|
|
16250
16281
|
\u26A0\uFE0F The model returned an empty response, so nothing was done. This is usually a transient upstream hiccup \u2014 send "continue" to retry.
|
|
16282
|
+
`;
|
|
16283
|
+
case "output-limit":
|
|
16284
|
+
return `
|
|
16285
|
+
\u26A0\uFE0F The model used its entire output budget on internal reasoning and was cut off before it could reply, so nothing was done. This will repeat identically if you just retry \u2014 lower the reasoning effort (/effort) or split the task into smaller steps.
|
|
16251
16286
|
`;
|
|
16252
16287
|
case "no-balance":
|
|
16253
16288
|
return `
|
|
@@ -17140,6 +17175,12 @@ ${tail}`;
|
|
|
17140
17175
|
return "";
|
|
17141
17176
|
return first.content.filter((b) => b.type === "text" && b.text).map((b) => b.text).join("\n").trim();
|
|
17142
17177
|
}
|
|
17178
|
+
var CompactionUnavailableError = class extends Error {
|
|
17179
|
+
constructor() {
|
|
17180
|
+
super("Compaction summariser was unavailable");
|
|
17181
|
+
this.name = "CompactionUnavailableError";
|
|
17182
|
+
}
|
|
17183
|
+
};
|
|
17143
17184
|
async function autoCompactMessages(messages, options, ledger) {
|
|
17144
17185
|
const cut = findSafeCutIndex(messages, messages.length - COMPACT_KEEP_MIN);
|
|
17145
17186
|
if (cut < 2)
|
|
@@ -17178,7 +17219,7 @@ ${tail}`;
|
|
|
17178
17219
|
});
|
|
17179
17220
|
summary = reply.content.filter((b) => b.type === "text").map((b) => b.text ?? "").join("").trim();
|
|
17180
17221
|
} catch {
|
|
17181
|
-
|
|
17222
|
+
throw new CompactionUnavailableError();
|
|
17182
17223
|
}
|
|
17183
17224
|
if (!summary)
|
|
17184
17225
|
return false;
|
|
@@ -17253,21 +17294,28 @@ Continue the work from here.` }] });
|
|
|
17253
17294
|
let guard = 0;
|
|
17254
17295
|
while (overCompactThreshold() && messages.length > COMPACT_KEEP_MIN + 2 && guard < 5) {
|
|
17255
17296
|
guard += 1;
|
|
17256
|
-
|
|
17257
|
-
|
|
17258
|
-
|
|
17259
|
-
|
|
17260
|
-
|
|
17261
|
-
|
|
17262
|
-
|
|
17263
|
-
|
|
17264
|
-
|
|
17265
|
-
|
|
17266
|
-
|
|
17267
|
-
|
|
17268
|
-
|
|
17269
|
-
|
|
17270
|
-
|
|
17297
|
+
let did;
|
|
17298
|
+
try {
|
|
17299
|
+
did = await autoCompactMessages(messages, {
|
|
17300
|
+
workDir: opts.workDir,
|
|
17301
|
+
model: opts.model,
|
|
17302
|
+
clientType: opts.clientType,
|
|
17303
|
+
env: opts.env,
|
|
17304
|
+
onText: () => {
|
|
17305
|
+
},
|
|
17306
|
+
onToolUse: () => {
|
|
17307
|
+
},
|
|
17308
|
+
onToolResult: () => {
|
|
17309
|
+
},
|
|
17310
|
+
onUsage: () => {
|
|
17311
|
+
},
|
|
17312
|
+
requestPermission: async () => false
|
|
17313
|
+
});
|
|
17314
|
+
} catch (err) {
|
|
17315
|
+
if (err instanceof CompactionUnavailableError)
|
|
17316
|
+
break;
|
|
17317
|
+
throw err;
|
|
17318
|
+
}
|
|
17271
17319
|
if (!did)
|
|
17272
17320
|
break;
|
|
17273
17321
|
compacted = true;
|
|
@@ -17324,6 +17372,8 @@ ${options.nexrallMd}` : "") : options.nexrallMd;
|
|
|
17324
17372
|
const ledger = createLedger();
|
|
17325
17373
|
let compactFailures = 0;
|
|
17326
17374
|
let compactDisabled = false;
|
|
17375
|
+
let compactDisabledAtBytes = 0;
|
|
17376
|
+
const COMPACT_REARM_GROWTH = 1.5;
|
|
17327
17377
|
try {
|
|
17328
17378
|
for (; iteration < budget; iteration++) {
|
|
17329
17379
|
if (options.abortSignal?.aborted) {
|
|
@@ -17342,11 +17392,23 @@ ${options.nexrallMd}` : "") : options.nexrallMd;
|
|
|
17342
17392
|
(options.onNotice ?? options.onText)(`\u267B\uFE0F Trimmed ~${(reclaimed / (1024 * 1024)).toFixed(1)}MB of already-processed tool output to keep this chat cheap to continue.`);
|
|
17343
17393
|
}
|
|
17344
17394
|
}
|
|
17395
|
+
if (compactDisabled && bodyBytes > compactDisabledAtBytes * COMPACT_REARM_GROWTH) {
|
|
17396
|
+
compactDisabled = false;
|
|
17397
|
+
compactFailures = 0;
|
|
17398
|
+
}
|
|
17345
17399
|
if (autoCompact && !compactDisabled && !compacting && (tokenPressure || bytePressure) && messages.length > COMPACT_KEEP_MIN + 2) {
|
|
17346
17400
|
compacting = true;
|
|
17347
17401
|
try {
|
|
17348
17402
|
const bytesBefore = estimateBodyBytes2(messages);
|
|
17349
|
-
|
|
17403
|
+
let did = false;
|
|
17404
|
+
let unavailable = false;
|
|
17405
|
+
try {
|
|
17406
|
+
did = await autoCompactMessages(messages, options, ledger);
|
|
17407
|
+
} catch (err) {
|
|
17408
|
+
if (!(err instanceof CompactionUnavailableError))
|
|
17409
|
+
throw err;
|
|
17410
|
+
unavailable = true;
|
|
17411
|
+
}
|
|
17350
17412
|
const bytesAfter = did ? estimateBodyBytes2(messages) : bytesBefore;
|
|
17351
17413
|
const reclaimed = bytesBefore - bytesAfter;
|
|
17352
17414
|
if (did) {
|
|
@@ -17356,11 +17418,13 @@ ${options.nexrallMd}` : "") : options.nexrallMd;
|
|
|
17356
17418
|
bodyBytes = bytesAfter;
|
|
17357
17419
|
bytePressure = bodyBytes > MAX_BODY_BYTES;
|
|
17358
17420
|
}
|
|
17359
|
-
if (
|
|
17421
|
+
if (unavailable) {
|
|
17422
|
+
} else if (did && reclaimed >= COMPACT_MIN_RECLAIM_BYTES) {
|
|
17360
17423
|
compactFailures = 0;
|
|
17361
17424
|
} else if (++compactFailures >= COMPACT_MAX_FAILURES) {
|
|
17362
17425
|
compactDisabled = true;
|
|
17363
|
-
|
|
17426
|
+
compactDisabledAtBytes = bytesAfter;
|
|
17427
|
+
(options.onNotice ?? options.onText)(`\u26A0\uFE0F Auto-compaction isn't reducing this conversation any further, so it's paused to avoid repeated summarising. It will be retried automatically if the conversation grows substantially. If the context fills up before then, start a fresh chat or run /compact manually.`);
|
|
17364
17428
|
}
|
|
17365
17429
|
} finally {
|
|
17366
17430
|
compacting = false;
|
|
@@ -17441,6 +17505,16 @@ ${options.nexrallMd}` : "") : options.nexrallMd;
|
|
|
17441
17505
|
canWriteSharedMemory: options._allowedTools ? options._allowedTools.has("memory_write") : true,
|
|
17442
17506
|
// no allowlist = main agent = may write
|
|
17443
17507
|
hasOwnAgentStore: !!options._agentMemory,
|
|
17508
|
+
// Same derivation, same reason, for the network. The base prompt's
|
|
17509
|
+
// "Web search" section tells the run to reach the network, but
|
|
17510
|
+
// READ_ONLY_TOOLS (explorer, security-auditor, ...) contains neither
|
|
17511
|
+
// `fetch_url` nor `web_search`. MEASURED on the 195-trial 2026-08-10
|
|
17512
|
+
// deepseek-v4-pro benchmark: 29 of 51 `fetch_url` failures and 3 of 14
|
|
17513
|
+
// `web_search` failures were the permission gate refusing a sub-agent
|
|
17514
|
+
// that its own system prompt had just invited to browse — every one a
|
|
17515
|
+
// wasted round-trip on a paid turn.
|
|
17516
|
+
canBrowseWeb: options._allowedTools ? options._allowedTools.has("fetch_url") : true,
|
|
17517
|
+
// no allowlist = main agent = may browse
|
|
17444
17518
|
// Withholds the `task` schema and its instructions when this run cannot
|
|
17445
17519
|
// delegate — see canSpawnSubAgents.
|
|
17446
17520
|
canSpawnSubAgents: maySpawn,
|
|
@@ -17481,7 +17555,7 @@ ${options.nexrallMd}` : "") : options.nexrallMd;
|
|
|
17481
17555
|
continue;
|
|
17482
17556
|
}
|
|
17483
17557
|
runSimpleHooks(hooks.PostMessageComplete, options.workDir);
|
|
17484
|
-
stopReason = "empty-response";
|
|
17558
|
+
stopReason = assistantMessage.stopReason === "max_tokens" ? "output-limit" : "empty-response";
|
|
17485
17559
|
break;
|
|
17486
17560
|
}
|
|
17487
17561
|
const { stopReason: _stopReason, ...historyMessage } = assistantMessage;
|
|
@@ -53543,7 +53617,7 @@ var {
|
|
|
53543
53617
|
|
|
53544
53618
|
// src/index.ts
|
|
53545
53619
|
import * as path5 from "path";
|
|
53546
|
-
import { createRequire } from "module";
|
|
53620
|
+
import { createRequire as createRequire2 } from "module";
|
|
53547
53621
|
|
|
53548
53622
|
// ../../node_modules/.pnpm/chalk@5.6.2/node_modules/chalk/source/vendor/ansi-styles/index.js
|
|
53549
53623
|
var ANSI_BACKGROUND_OFFSET = 10;
|
|
@@ -54171,6 +54245,8 @@ import * as path4 from "path";
|
|
|
54171
54245
|
import * as fs8 from "fs";
|
|
54172
54246
|
import * as os4 from "os";
|
|
54173
54247
|
import * as crypto from "crypto";
|
|
54248
|
+
import { createRequire } from "module";
|
|
54249
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
54174
54250
|
import { execSync } from "child_process";
|
|
54175
54251
|
var import_code_core3 = __toESM(require_dist2(), 1);
|
|
54176
54252
|
|
|
@@ -64732,7 +64808,26 @@ var InkReadlineAdapter = class extends EventEmitter3 {
|
|
|
64732
64808
|
};
|
|
64733
64809
|
|
|
64734
64810
|
// src/commands/chat.ts
|
|
64735
|
-
var
|
|
64811
|
+
var require2 = createRequire(import.meta.url);
|
|
64812
|
+
var CLI_VERSION = (() => {
|
|
64813
|
+
let dir = path4.dirname(fileURLToPath2(import.meta.url));
|
|
64814
|
+
for (let i2 = 0; i2 < 6; i2++) {
|
|
64815
|
+
const candidate = path4.join(dir, "package.json");
|
|
64816
|
+
if (fs8.existsSync(candidate)) {
|
|
64817
|
+
try {
|
|
64818
|
+
const v = require2(candidate).version;
|
|
64819
|
+
if (typeof v === "string" && v)
|
|
64820
|
+
return v;
|
|
64821
|
+
} catch {
|
|
64822
|
+
}
|
|
64823
|
+
}
|
|
64824
|
+
const parent = path4.dirname(dir);
|
|
64825
|
+
if (parent === dir)
|
|
64826
|
+
break;
|
|
64827
|
+
dir = parent;
|
|
64828
|
+
}
|
|
64829
|
+
return "unknown";
|
|
64830
|
+
})();
|
|
64736
64831
|
var MODEL_LABELS = {
|
|
64737
64832
|
"claude-sonnet-5": "Claude Sonnet 5",
|
|
64738
64833
|
"claude-opus-5": "Claude Opus 5",
|
|
@@ -66481,8 +66576,8 @@ function pluginSourceRemoveCommand(name, opts) {
|
|
|
66481
66576
|
}
|
|
66482
66577
|
|
|
66483
66578
|
// src/index.ts
|
|
66484
|
-
var
|
|
66485
|
-
var NEX_VERSION =
|
|
66579
|
+
var require3 = createRequire2(import.meta.url);
|
|
66580
|
+
var NEX_VERSION = require3("../package.json").version;
|
|
66486
66581
|
var program2 = new Command();
|
|
66487
66582
|
program2.name("nex").description("Nexrall Code \u2014 AI coding assistant (powered by Nexrall)").version(NEX_VERSION).enablePositionalOptions();
|
|
66488
66583
|
program2.command("auth").description("Login to your Nexrall account").action(authCommand);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nexrall-code",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.72",
|
|
4
4
|
"description": "Nexrall Code — AI coding assistant for your terminal (headless agent for scripts, CI and automation)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"release": "node build.js && node scripts/upload-release.cjs"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@nexrall/code-core": "^1.4.
|
|
42
|
+
"@nexrall/code-core": "^1.4.42",
|
|
43
43
|
"chalk": "^5.3.0",
|
|
44
44
|
"commander": "^12.0.0",
|
|
45
45
|
"diff": "^5.2.0",
|