nexrall-code 0.5.103 → 0.5.105
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 +47 -6
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9973,6 +9973,11 @@ var require_client = __commonJS({
|
|
|
9973
9973
|
var MAX_RETRIES = 5;
|
|
9974
9974
|
var RETRY_BASE_MS = 1e3;
|
|
9975
9975
|
var RETRY_MAX_MS = 3e4;
|
|
9976
|
+
var HOUSEKEEPING_FRAMES = /* @__PURE__ */ new Set([
|
|
9977
|
+
"resumable",
|
|
9978
|
+
"context_warning",
|
|
9979
|
+
"tool_progress"
|
|
9980
|
+
]);
|
|
9976
9981
|
var MAX_TOTAL_RETRY_MS = (() => {
|
|
9977
9982
|
const raw = Number(process.env.NEXRALL_MAX_RETRY_MS);
|
|
9978
9983
|
return Number.isFinite(raw) && raw > 0 ? raw : 5 * 6e4;
|
|
@@ -10063,7 +10068,12 @@ var require_client = __commonJS({
|
|
|
10063
10068
|
}
|
|
10064
10069
|
];
|
|
10065
10070
|
};
|
|
10066
|
-
const isRetryableStreamMsg = (m2) =>
|
|
10071
|
+
const isRetryableStreamMsg = (m2) => {
|
|
10072
|
+
const s2 = String(m2 ?? "");
|
|
10073
|
+
if (/403[\s\S]*"type"\s*:\s*"forbidden"/i.test(s2))
|
|
10074
|
+
return true;
|
|
10075
|
+
return /overloaded|rate.?limit|temporarily|unavailable|try again|internal server error/i.test(s2);
|
|
10076
|
+
};
|
|
10067
10077
|
let didRetry = false;
|
|
10068
10078
|
let totalAttemptsMade = 0;
|
|
10069
10079
|
let retryDeadline = 0;
|
|
@@ -10335,7 +10345,8 @@ var require_client = __commonJS({
|
|
|
10335
10345
|
}
|
|
10336
10346
|
const evt = parsed;
|
|
10337
10347
|
lastProgressAt = Date.now();
|
|
10338
|
-
|
|
10348
|
+
if (!HOUSEKEEPING_FRAMES.has(evt.type))
|
|
10349
|
+
sawModelEvent = true;
|
|
10339
10350
|
clearRetryIfNeeded();
|
|
10340
10351
|
switch (evt.type) {
|
|
10341
10352
|
case "text": {
|
|
@@ -10461,6 +10472,7 @@ var require_client = __commonJS({
|
|
|
10461
10472
|
case "error": {
|
|
10462
10473
|
const message = typeof evt.message === "string" ? evt.message : typeof evt.error === "string" ? evt.error : "Unknown SSE error";
|
|
10463
10474
|
const notResumable = evt.notResumable === true;
|
|
10475
|
+
const serverSaysRetryable = evt.retryable === true;
|
|
10464
10476
|
if (haveCompleteMessage()) {
|
|
10465
10477
|
clearInterval(heartbeatWatchdog);
|
|
10466
10478
|
onEvent({ type: "error", message });
|
|
@@ -10469,7 +10481,7 @@ var require_client = __commonJS({
|
|
|
10469
10481
|
clearInterval(heartbeatWatchdog);
|
|
10470
10482
|
stream.destroy?.();
|
|
10471
10483
|
reject(Object.assign(tagTransient(new Error(message)), { forceRestart: true }));
|
|
10472
|
-
} else if (isRetryableStreamMsg(message) && (!emittedToCaller || allowRestartAfterRender)) {
|
|
10484
|
+
} else if ((serverSaysRetryable || isRetryableStreamMsg(message)) && (!emittedToCaller || allowRestartAfterRender)) {
|
|
10473
10485
|
clearInterval(heartbeatWatchdog);
|
|
10474
10486
|
stream.destroy?.();
|
|
10475
10487
|
reject(tagTransient(new Error(message)));
|
|
@@ -10494,7 +10506,8 @@ var require_client = __commonJS({
|
|
|
10494
10506
|
});
|
|
10495
10507
|
stream.on("end", () => {
|
|
10496
10508
|
clearInterval(heartbeatWatchdog);
|
|
10497
|
-
|
|
10509
|
+
const producedNothing = !completedMessage && textParts.length === 0 && toolUseBlocks.length === 0;
|
|
10510
|
+
if (producedNothing) {
|
|
10498
10511
|
reject(Object.assign(new Error("Connection closed before the model responded. Retrying\u2026"), { retryable: true }));
|
|
10499
10512
|
return;
|
|
10500
10513
|
}
|
|
@@ -103387,7 +103400,9 @@ var require_loop = __commonJS({
|
|
|
103387
103400
|
};
|
|
103388
103401
|
}();
|
|
103389
103402
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
103390
|
-
exports2.VERIFY_CMD_RE = exports2.WRITE_TOOL_NAMES = exports2.ToolNotAllowedError = exports2.AGENT_MEMORY_TOOL_SCHEMA = exports2.AGENT_MEMORY_TOOL = exports2._stallLimits = exports2.bashNeedsRepoLock = void 0;
|
|
103403
|
+
exports2.VERIFY_CMD_RE = exports2.WRITE_TOOL_NAMES = exports2.ToolNotAllowedError = exports2.AGENT_MEMORY_TOOL_SCHEMA = exports2.AGENT_MEMORY_TOOL = exports2._stallLimits = exports2._emptyTurnRetry = exports2.bashNeedsRepoLock = void 0;
|
|
103404
|
+
exports2.emptyTurnBackoffMs = emptyTurnBackoffMs;
|
|
103405
|
+
exports2.shouldRetryEmptyTurn = shouldRetryEmptyTurn;
|
|
103391
103406
|
exports2.errorRoundSignature = errorRoundSignature;
|
|
103392
103407
|
exports2.executeAgentMemoryWrite = executeAgentMemoryWrite;
|
|
103393
103408
|
exports2.stopReasonNotice = stopReasonNotice;
|
|
@@ -103544,6 +103559,17 @@ var require_loop = __commonJS({
|
|
|
103544
103559
|
var HARD_ITERATIONS_CAP = Infinity;
|
|
103545
103560
|
var STALL_LIMIT = 8;
|
|
103546
103561
|
var REPEAT_STALL_LIMIT = 12;
|
|
103562
|
+
var EMPTY_TURN_RETRY_LIMIT = 3;
|
|
103563
|
+
var EMPTY_TURN_RETRY_BASE_MS = 1e3;
|
|
103564
|
+
function emptyTurnBackoffMs(attempt) {
|
|
103565
|
+
return EMPTY_TURN_RETRY_BASE_MS * Math.pow(2, Math.max(0, attempt));
|
|
103566
|
+
}
|
|
103567
|
+
function shouldRetryEmptyTurn(stopReason, attemptsSoFar) {
|
|
103568
|
+
if (stopReason === "max_tokens")
|
|
103569
|
+
return false;
|
|
103570
|
+
return attemptsSoFar < EMPTY_TURN_RETRY_LIMIT;
|
|
103571
|
+
}
|
|
103572
|
+
exports2._emptyTurnRetry = { EMPTY_TURN_RETRY_LIMIT, EMPTY_TURN_RETRY_BASE_MS };
|
|
103547
103573
|
function errorRoundSignature(errored) {
|
|
103548
103574
|
return errored.map(({ name, error }) => `${name}:${String(error).slice(0, 200)}`).sort().join("|");
|
|
103549
103575
|
}
|
|
@@ -103587,7 +103613,7 @@ var require_loop = __commonJS({
|
|
|
103587
103613
|
return null;
|
|
103588
103614
|
case "empty-response":
|
|
103589
103615
|
return `
|
|
103590
|
-
\u26A0\uFE0F The model returned an empty response, so nothing was done. This is usually a transient upstream hiccup
|
|
103616
|
+
\u26A0\uFE0F The model returned an empty response ${EMPTY_TURN_RETRY_LIMIT} times in a row, so nothing was done. This is usually a transient upstream hiccup that the agent retries by itself; it did not clear this time. Send "continue" to try again, or switch model with /model if it persists.
|
|
103591
103617
|
`;
|
|
103592
103618
|
case "output-limit":
|
|
103593
103619
|
return `
|
|
@@ -104750,6 +104776,7 @@ ${options.nexrallMd}` : "") : options.nexrallMd;
|
|
|
104750
104776
|
let stalledRepeatError = null;
|
|
104751
104777
|
let budget = maxIterations;
|
|
104752
104778
|
let iteration = 0;
|
|
104779
|
+
let emptyTurnRetries = 0;
|
|
104753
104780
|
let filesMutatedSinceVerify = false;
|
|
104754
104781
|
let ranVerificationCmd = false;
|
|
104755
104782
|
let verificationNudgeSent = false;
|
|
@@ -104941,10 +104968,24 @@ ${options.nexrallMd}` : "") : options.nexrallMd;
|
|
|
104941
104968
|
messages.push({ role: "user", content: [{ type: "text", text }] });
|
|
104942
104969
|
continue;
|
|
104943
104970
|
}
|
|
104971
|
+
if (shouldRetryEmptyTurn(assistantMessage.stopReason, emptyTurnRetries)) {
|
|
104972
|
+
const waitMs = emptyTurnBackoffMs(emptyTurnRetries);
|
|
104973
|
+
emptyTurnRetries++;
|
|
104974
|
+
options.onRetry?.(emptyTurnRetries, EMPTY_TURN_RETRY_LIMIT, "The model returned an empty response \u2014 retrying automatically");
|
|
104975
|
+
await new Promise((r2) => setTimeout(r2, waitMs));
|
|
104976
|
+
if (options.abortSignal?.aborted) {
|
|
104977
|
+
stopReason = "aborted";
|
|
104978
|
+
break;
|
|
104979
|
+
}
|
|
104980
|
+
options.onRetryResolved?.();
|
|
104981
|
+
iteration--;
|
|
104982
|
+
continue;
|
|
104983
|
+
}
|
|
104944
104984
|
runSimpleHooks(hooks.PostMessageComplete, options.workDir);
|
|
104945
104985
|
stopReason = assistantMessage.stopReason === "max_tokens" ? "output-limit" : "empty-response";
|
|
104946
104986
|
break;
|
|
104947
104987
|
}
|
|
104988
|
+
emptyTurnRetries = 0;
|
|
104948
104989
|
const { stopReason: _stopReason, ...historyMessage } = assistantMessage;
|
|
104949
104990
|
messages.push(historyMessage);
|
|
104950
104991
|
const serverSideResultIds = new Set(assistantMessage.content.filter((b) => b.type === "tool_result").map((b) => b.tool_use_id).filter((id) => !!id));
|