@nathapp/nax 0.67.7 → 0.67.8
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/nax.js +119 -28
- package/package.json +1 -1
package/dist/nax.js
CHANGED
|
@@ -21312,7 +21312,7 @@ class AgentManager {
|
|
|
21312
21312
|
return { result, fallbacks, finalBundle: updatedBundle, finalPrompt, finalAgent: currentAgent };
|
|
21313
21313
|
}
|
|
21314
21314
|
const isFailStale = result.adapterFailure?.outcome === "fail-stale";
|
|
21315
|
-
const maxStaleRetries = this._config.agent?.idleWatchdog?.maxRetryAttempts ??
|
|
21315
|
+
const maxStaleRetries = this._config.agent?.idleWatchdog?.maxRetryAttempts ?? 3;
|
|
21316
21316
|
if (isFailStale && result.adapterFailure?.retriable && staleRetryAttempts < maxStaleRetries) {
|
|
21317
21317
|
staleRetryAttempts++;
|
|
21318
21318
|
const retryHop = {
|
|
@@ -21330,7 +21330,8 @@ class AgentManager {
|
|
|
21330
21330
|
logger?.info("agent-manager", "fail-stale: immediate same-agent retry", {
|
|
21331
21331
|
storyId: request.runOptions.storyId,
|
|
21332
21332
|
attempt: staleRetryAttempts,
|
|
21333
|
-
agent: currentAgent
|
|
21333
|
+
agent: currentAgent,
|
|
21334
|
+
reason: result.adapterFailure?.reason
|
|
21334
21335
|
});
|
|
21335
21336
|
currentHopKind = { kind: "stale-retry", attempt: staleRetryAttempts };
|
|
21336
21337
|
continue;
|
|
@@ -21461,6 +21462,8 @@ class AgentManager {
|
|
|
21461
21462
|
const primaryAgent = primaryAgentOverride ?? this.getDefault();
|
|
21462
21463
|
let currentAgent = primaryAgent;
|
|
21463
21464
|
let hopsSoFar = 0;
|
|
21465
|
+
let staleRetryAttempts = 0;
|
|
21466
|
+
const maxStaleRetries = this._config.agent?.idleWatchdog?.maxRetryAttempts ?? 3;
|
|
21464
21467
|
const _opStartMs = Date.now();
|
|
21465
21468
|
const _agentChain = [primaryAgent];
|
|
21466
21469
|
let _finalStatus = "error";
|
|
@@ -21497,10 +21500,45 @@ class AgentManager {
|
|
|
21497
21500
|
};
|
|
21498
21501
|
}
|
|
21499
21502
|
_totalCostUsd += result.estimatedCostUsd;
|
|
21503
|
+
if (!result.adapterFailure && !result.output?.trim()) {
|
|
21504
|
+
result = {
|
|
21505
|
+
...result,
|
|
21506
|
+
adapterFailure: {
|
|
21507
|
+
outcome: "fail-stale",
|
|
21508
|
+
category: "availability",
|
|
21509
|
+
retriable: true,
|
|
21510
|
+
message: "[completeWithFallback] agent returned no output",
|
|
21511
|
+
reason: "empty-output"
|
|
21512
|
+
}
|
|
21513
|
+
};
|
|
21514
|
+
}
|
|
21500
21515
|
if (!result.adapterFailure) {
|
|
21501
21516
|
_finalStatus = "ok";
|
|
21502
21517
|
return { result, fallbacks };
|
|
21503
21518
|
}
|
|
21519
|
+
const isFailStale = result.adapterFailure.outcome === "fail-stale";
|
|
21520
|
+
if (isFailStale && result.adapterFailure.retriable && staleRetryAttempts < maxStaleRetries) {
|
|
21521
|
+
staleRetryAttempts++;
|
|
21522
|
+
const retryHop = {
|
|
21523
|
+
storyId: options.storyId,
|
|
21524
|
+
priorAgent: currentAgent,
|
|
21525
|
+
newAgent: currentAgent,
|
|
21526
|
+
hop: staleRetryAttempts,
|
|
21527
|
+
outcome: result.adapterFailure.outcome,
|
|
21528
|
+
category: result.adapterFailure.category,
|
|
21529
|
+
timestamp: new Date().toISOString(),
|
|
21530
|
+
costUsd: result.estimatedCostUsd
|
|
21531
|
+
};
|
|
21532
|
+
fallbacks.push(retryHop);
|
|
21533
|
+
this._emitter.emit("onSwapAttempt", retryHop);
|
|
21534
|
+
logger?.info("agent-manager", "completeWithFallback: fail-stale same-agent retry", {
|
|
21535
|
+
storyId: options.storyId,
|
|
21536
|
+
attempt: staleRetryAttempts,
|
|
21537
|
+
agent: currentAgent,
|
|
21538
|
+
reason: result.adapterFailure.reason
|
|
21539
|
+
});
|
|
21540
|
+
continue;
|
|
21541
|
+
}
|
|
21504
21542
|
if (!this.shouldSwap(result.adapterFailure, hopsSoFar, true)) {
|
|
21505
21543
|
_finalStatus = hopsSoFar > 0 ? "exhausted" : "error";
|
|
21506
21544
|
return { result, fallbacks };
|
|
@@ -34951,6 +34989,53 @@ var init_acceptance_fix = __esm(() => {
|
|
|
34951
34989
|
};
|
|
34952
34990
|
});
|
|
34953
34991
|
|
|
34992
|
+
// src/review/requote-response.ts
|
|
34993
|
+
function parseRequoteResponse(output) {
|
|
34994
|
+
const parsed = tryParseLLMJson(output);
|
|
34995
|
+
if (!isRecord(parsed))
|
|
34996
|
+
return null;
|
|
34997
|
+
const canonical = extractCanonical(parsed);
|
|
34998
|
+
if (canonical)
|
|
34999
|
+
return canonical;
|
|
35000
|
+
const findings = parsed.findings;
|
|
35001
|
+
if (!Array.isArray(findings) || findings.length !== 1)
|
|
35002
|
+
return null;
|
|
35003
|
+
const finding = findings[0];
|
|
35004
|
+
if (!isRecord(finding))
|
|
35005
|
+
return null;
|
|
35006
|
+
return extractCanonical(finding.verifiedBy) ?? extractCanonical(finding);
|
|
35007
|
+
}
|
|
35008
|
+
function extractCanonical(value) {
|
|
35009
|
+
if (!isRecord(value))
|
|
35010
|
+
return null;
|
|
35011
|
+
if (typeof value.file !== "string" || typeof value.observed !== "string")
|
|
35012
|
+
return null;
|
|
35013
|
+
const file3 = value.file.trim();
|
|
35014
|
+
if (!file3)
|
|
35015
|
+
return null;
|
|
35016
|
+
const line = coerceLine(value.line);
|
|
35017
|
+
if (line === null)
|
|
35018
|
+
return null;
|
|
35019
|
+
return {
|
|
35020
|
+
file: file3,
|
|
35021
|
+
line: line === undefined ? undefined : line,
|
|
35022
|
+
observed: value.observed
|
|
35023
|
+
};
|
|
35024
|
+
}
|
|
35025
|
+
function coerceLine(value) {
|
|
35026
|
+
if (value == null)
|
|
35027
|
+
return;
|
|
35028
|
+
if (typeof value === "number")
|
|
35029
|
+
return value;
|
|
35030
|
+
if (typeof value === "string" && /^\d+$/.test(value))
|
|
35031
|
+
return Number.parseInt(value, 10);
|
|
35032
|
+
return null;
|
|
35033
|
+
}
|
|
35034
|
+
function isRecord(value) {
|
|
35035
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
35036
|
+
}
|
|
35037
|
+
var init_requote_response = () => {};
|
|
35038
|
+
|
|
34954
35039
|
// src/operations/semantic-review.ts
|
|
34955
35040
|
async function requoteBlockingFindings(findings, ctx) {
|
|
34956
35041
|
const threshold = ctx.input.blockingThreshold ?? "error";
|
|
@@ -35021,18 +35106,6 @@ async function requoteBlockingFindings(findings, ctx) {
|
|
|
35021
35106
|
}
|
|
35022
35107
|
return { findings: next, changed, extraCostUsd };
|
|
35023
35108
|
}
|
|
35024
|
-
function parseRequoteResponse(output) {
|
|
35025
|
-
const parsed = tryParseLLMJson(output);
|
|
35026
|
-
if (!parsed || typeof parsed.file !== "string" || typeof parsed.observed !== "string")
|
|
35027
|
-
return null;
|
|
35028
|
-
if (parsed.line != null && typeof parsed.line !== "number")
|
|
35029
|
-
return null;
|
|
35030
|
-
return {
|
|
35031
|
-
file: parsed.file,
|
|
35032
|
-
line: typeof parsed.line === "number" ? parsed.line : undefined,
|
|
35033
|
-
observed: parsed.observed
|
|
35034
|
-
};
|
|
35035
|
-
}
|
|
35036
35109
|
var FAIL_OPEN2, SEMANTIC_REQUOTE_RECOVERED_EVENT = "review.semantic.finding.requote_recovered", SEMANTIC_REQUOTE_FAILED_EVENT = "review.semantic.finding.requote_failed", DEFAULT_MAX_REQUOTES = 5, semanticReviewHopBody = async (initialPrompt, ctx) => {
|
|
35037
35110
|
const turn = await ctx.sendWithParseRetry(initialPrompt);
|
|
35038
35111
|
const parsed = validateLLMShape(tryParseLLMJson(turn.output));
|
|
@@ -35041,9 +35114,10 @@ var FAIL_OPEN2, SEMANTIC_REQUOTE_RECOVERED_EVENT = "review.semantic.finding.requ
|
|
|
35041
35114
|
const requoted = await requoteBlockingFindings(parsed.findings, ctx);
|
|
35042
35115
|
if (!requoted.changed)
|
|
35043
35116
|
return turn;
|
|
35117
|
+
const passed = !requoted.findings.some((finding) => isBlockingSeverity(finding.severity, ctx.input.blockingThreshold ?? "error"));
|
|
35044
35118
|
return {
|
|
35045
35119
|
...turn,
|
|
35046
|
-
output: JSON.stringify({ passed
|
|
35120
|
+
output: JSON.stringify({ passed, findings: requoted.findings }),
|
|
35047
35121
|
estimatedCostUsd: (turn.estimatedCostUsd ?? 0) + requoted.extraCostUsd
|
|
35048
35122
|
};
|
|
35049
35123
|
}, semanticReviewOp;
|
|
@@ -35052,6 +35126,7 @@ var init_semantic_review = __esm(() => {
|
|
|
35052
35126
|
init_config();
|
|
35053
35127
|
init_logger2();
|
|
35054
35128
|
init_prompts();
|
|
35129
|
+
init_requote_response();
|
|
35055
35130
|
init_semantic_evidence();
|
|
35056
35131
|
init_semantic_helpers();
|
|
35057
35132
|
FAIL_OPEN2 = { passed: true, findings: [], failOpen: true };
|
|
@@ -39743,6 +39818,7 @@ var init_review = __esm(() => {
|
|
|
39743
39818
|
init_diff_utils();
|
|
39744
39819
|
init_finding_projection();
|
|
39745
39820
|
init_runner2();
|
|
39821
|
+
init_requote_response();
|
|
39746
39822
|
init_severity();
|
|
39747
39823
|
});
|
|
39748
39824
|
|
|
@@ -41251,8 +41327,8 @@ var init_prompts = __esm(() => {
|
|
|
41251
41327
|
// src/operations/build-hop-callback.ts
|
|
41252
41328
|
function turnResultToAgentResult(r) {
|
|
41253
41329
|
return {
|
|
41254
|
-
success:
|
|
41255
|
-
exitCode: 0,
|
|
41330
|
+
success: !r.adapterFailure,
|
|
41331
|
+
exitCode: r.adapterFailure ? 1 : 0,
|
|
41256
41332
|
output: r.output,
|
|
41257
41333
|
rateLimited: false,
|
|
41258
41334
|
durationMs: 0,
|
|
@@ -41260,7 +41336,8 @@ function turnResultToAgentResult(r) {
|
|
|
41260
41336
|
exactCostUsd: r.exactCostUsd,
|
|
41261
41337
|
tokenUsage: r.tokenUsage,
|
|
41262
41338
|
protocolIds: r.protocolIds,
|
|
41263
|
-
internalRoundTrips: r.internalRoundTrips
|
|
41339
|
+
internalRoundTrips: r.internalRoundTrips,
|
|
41340
|
+
...r.adapterFailure ? { adapterFailure: r.adapterFailure } : {}
|
|
41264
41341
|
};
|
|
41265
41342
|
}
|
|
41266
41343
|
function buildHopCallback(ctx, sessionId, _initialOptions) {
|
|
@@ -41629,13 +41706,26 @@ async function callOp(ctx, op, input) {
|
|
|
41629
41706
|
let lastRetryTurn;
|
|
41630
41707
|
const sendWithFileOutput = async (promptText, bodyCtx) => {
|
|
41631
41708
|
const turn = await bodyCtx.send(promptText);
|
|
41632
|
-
|
|
41633
|
-
|
|
41634
|
-
|
|
41635
|
-
|
|
41636
|
-
|
|
41709
|
+
let effective = turn;
|
|
41710
|
+
if (fileOutputPath) {
|
|
41711
|
+
const fileContent = await _callOpDeps.readFileOutput(fileOutputPath);
|
|
41712
|
+
if (fileContent !== null) {
|
|
41713
|
+
effective = { ...turn, output: fileContent };
|
|
41714
|
+
}
|
|
41715
|
+
}
|
|
41716
|
+
if (!effective.output?.trim() && !effective.adapterFailure) {
|
|
41717
|
+
return {
|
|
41718
|
+
...effective,
|
|
41719
|
+
adapterFailure: {
|
|
41720
|
+
outcome: "fail-stale",
|
|
41721
|
+
category: "availability",
|
|
41722
|
+
retriable: true,
|
|
41723
|
+
message: `[${op.name}] agent returned no output`,
|
|
41724
|
+
reason: "empty-output"
|
|
41725
|
+
}
|
|
41726
|
+
};
|
|
41637
41727
|
}
|
|
41638
|
-
return
|
|
41728
|
+
return effective;
|
|
41639
41729
|
};
|
|
41640
41730
|
const sendWithParseRetry = async (initialPrompt, bodyCtx) => {
|
|
41641
41731
|
retryFallback = undefined;
|
|
@@ -43828,7 +43918,8 @@ class SessionManager {
|
|
|
43828
43918
|
category: "availability",
|
|
43829
43919
|
outcome: "fail-stale",
|
|
43830
43920
|
retriable: true,
|
|
43831
|
-
message: "idle watchdog cancelled session \u2014 no stream activity"
|
|
43921
|
+
message: "idle watchdog cancelled session \u2014 no stream activity",
|
|
43922
|
+
reason: "idle-watchdog"
|
|
43832
43923
|
});
|
|
43833
43924
|
}
|
|
43834
43925
|
}
|
|
@@ -56753,7 +56844,7 @@ var package_default;
|
|
|
56753
56844
|
var init_package = __esm(() => {
|
|
56754
56845
|
package_default = {
|
|
56755
56846
|
name: "@nathapp/nax",
|
|
56756
|
-
version: "0.67.
|
|
56847
|
+
version: "0.67.8",
|
|
56757
56848
|
description: "AI Coding Agent Orchestrator \u2014 loops until done",
|
|
56758
56849
|
type: "module",
|
|
56759
56850
|
bin: {
|
|
@@ -56848,8 +56939,8 @@ var init_version = __esm(() => {
|
|
|
56848
56939
|
NAX_VERSION = package_default.version;
|
|
56849
56940
|
NAX_COMMIT = (() => {
|
|
56850
56941
|
try {
|
|
56851
|
-
if (/^[0-9a-f]{6,10}$/.test("
|
|
56852
|
-
return "
|
|
56942
|
+
if (/^[0-9a-f]{6,10}$/.test("1e88267c"))
|
|
56943
|
+
return "1e88267c";
|
|
56853
56944
|
} catch {}
|
|
56854
56945
|
try {
|
|
56855
56946
|
const result = Bun.spawnSync(["git", "rev-parse", "--short", "HEAD"], {
|