@nathapp/nax 0.39.0 → 0.39.1
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
CHANGED
|
@@ -20159,7 +20159,9 @@ async function tryLlmBatchRoute(config2, stories, label = "routing") {
|
|
|
20159
20159
|
const logger = getSafeLogger();
|
|
20160
20160
|
try {
|
|
20161
20161
|
logger?.debug("routing", `LLM batch routing: ${label}`, { storyCount: stories.length, mode });
|
|
20162
|
-
|
|
20162
|
+
const agentName = config2.execution?.agent ?? "claude";
|
|
20163
|
+
const adapter = getAgent(agentName);
|
|
20164
|
+
await routeBatch(stories, { config: config2, adapter });
|
|
20163
20165
|
logger?.debug("routing", "LLM batch routing complete", { label });
|
|
20164
20166
|
} catch (err) {
|
|
20165
20167
|
logger?.warn("routing", "LLM batch routing failed, falling back to individual routing", {
|
|
@@ -20169,6 +20171,7 @@ async function tryLlmBatchRoute(config2, stories, label = "routing") {
|
|
|
20169
20171
|
}
|
|
20170
20172
|
}
|
|
20171
20173
|
var init_batch_route = __esm(() => {
|
|
20174
|
+
init_registry();
|
|
20172
20175
|
init_logger2();
|
|
20173
20176
|
init_llm();
|
|
20174
20177
|
});
|
|
@@ -20793,7 +20796,7 @@ var package_default;
|
|
|
20793
20796
|
var init_package = __esm(() => {
|
|
20794
20797
|
package_default = {
|
|
20795
20798
|
name: "@nathapp/nax",
|
|
20796
|
-
version: "0.39.
|
|
20799
|
+
version: "0.39.1",
|
|
20797
20800
|
description: "AI Coding Agent Orchestrator \u2014 loops until done",
|
|
20798
20801
|
type: "module",
|
|
20799
20802
|
bin: {
|
|
@@ -20857,8 +20860,8 @@ var init_version = __esm(() => {
|
|
|
20857
20860
|
NAX_VERSION = package_default.version;
|
|
20858
20861
|
NAX_COMMIT = (() => {
|
|
20859
20862
|
try {
|
|
20860
|
-
if (/^[0-9a-f]{6,10}$/.test("
|
|
20861
|
-
return "
|
|
20863
|
+
if (/^[0-9a-f]{6,10}$/.test("91b2a1c"))
|
|
20864
|
+
return "91b2a1c";
|
|
20862
20865
|
} catch {}
|
|
20863
20866
|
try {
|
|
20864
20867
|
const result = Bun.spawnSync(["git", "rev-parse", "--short", "HEAD"], {
|
|
@@ -22813,7 +22816,7 @@ async function getChangedFiles(workdir, baseRef) {
|
|
|
22813
22816
|
}
|
|
22814
22817
|
|
|
22815
22818
|
class ReviewOrchestrator {
|
|
22816
|
-
async review(reviewConfig, workdir, executionConfig, plugins) {
|
|
22819
|
+
async review(reviewConfig, workdir, executionConfig, plugins, storyGitRef) {
|
|
22817
22820
|
const logger = getSafeLogger();
|
|
22818
22821
|
const builtIn = await runReview(reviewConfig, workdir, executionConfig);
|
|
22819
22822
|
if (!builtIn.success) {
|
|
@@ -22822,7 +22825,7 @@ class ReviewOrchestrator {
|
|
|
22822
22825
|
if (plugins) {
|
|
22823
22826
|
const reviewers = plugins.getReviewers();
|
|
22824
22827
|
if (reviewers.length > 0) {
|
|
22825
|
-
const baseRef = executionConfig?.storyGitRef;
|
|
22828
|
+
const baseRef = storyGitRef ?? executionConfig?.storyGitRef;
|
|
22826
22829
|
const changedFiles = await getChangedFiles(workdir, baseRef);
|
|
22827
22830
|
const pluginResults = [];
|
|
22828
22831
|
for (const reviewer of reviewers) {
|
|
@@ -22897,7 +22900,7 @@ var init_review = __esm(() => {
|
|
|
22897
22900
|
async execute(ctx) {
|
|
22898
22901
|
const logger = getLogger();
|
|
22899
22902
|
logger.info("review", "Running review phase", { storyId: ctx.story.id });
|
|
22900
|
-
const result = await reviewOrchestrator.review(ctx.config.review, ctx.workdir, ctx.config.execution, ctx.plugins);
|
|
22903
|
+
const result = await reviewOrchestrator.review(ctx.config.review, ctx.workdir, ctx.config.execution, ctx.plugins, ctx.storyGitRef);
|
|
22901
22904
|
ctx.reviewResult = result.builtIn;
|
|
22902
22905
|
if (!result.success) {
|
|
22903
22906
|
const allFindings = result.builtIn.pluginReviewers?.flatMap((pr) => pr.findings ?? []) ?? [];
|
|
@@ -31644,22 +31647,6 @@ function resolveMaxAttemptsOutcome(failureCategory) {
|
|
|
31644
31647
|
return "fail";
|
|
31645
31648
|
}
|
|
31646
31649
|
}
|
|
31647
|
-
async function tryLlmBatchRoute2(config2, stories, label = "routing") {
|
|
31648
|
-
const mode = config2.routing.llm?.mode ?? "hybrid";
|
|
31649
|
-
if (config2.routing.strategy !== "llm" || mode === "per-story" || stories.length === 0)
|
|
31650
|
-
return;
|
|
31651
|
-
const logger = getSafeLogger();
|
|
31652
|
-
try {
|
|
31653
|
-
logger?.debug("routing", `LLM batch routing: ${label}`, { storyCount: stories.length, mode });
|
|
31654
|
-
await routeBatch(stories, { config: config2 });
|
|
31655
|
-
logger?.debug("routing", "LLM batch routing complete", { label });
|
|
31656
|
-
} catch (err) {
|
|
31657
|
-
logger?.warn("routing", "LLM batch routing failed, falling back to individual routing", {
|
|
31658
|
-
error: err.message,
|
|
31659
|
-
label
|
|
31660
|
-
});
|
|
31661
|
-
}
|
|
31662
|
-
}
|
|
31663
31650
|
function shouldRetrySameTier(verifyResult) {
|
|
31664
31651
|
return verifyResult?.status === "RUNTIME_CRASH";
|
|
31665
31652
|
}
|
|
@@ -31739,7 +31726,7 @@ async function handleTierEscalation(ctx) {
|
|
|
31739
31726
|
clearCacheForStory(story.id);
|
|
31740
31727
|
}
|
|
31741
31728
|
if (routingMode === "hybrid") {
|
|
31742
|
-
await
|
|
31729
|
+
await tryLlmBatchRoute(ctx.config, storiesToEscalate, "hybrid-re-route-pipeline");
|
|
31743
31730
|
}
|
|
31744
31731
|
return {
|
|
31745
31732
|
outcome: "escalated",
|
|
@@ -31752,6 +31739,7 @@ var init_tier_escalation = __esm(() => {
|
|
|
31752
31739
|
init_hooks();
|
|
31753
31740
|
init_logger2();
|
|
31754
31741
|
init_prd();
|
|
31742
|
+
init_batch_route();
|
|
31755
31743
|
init_llm();
|
|
31756
31744
|
init_escalation();
|
|
31757
31745
|
init_helpers();
|
package/package.json
CHANGED
|
@@ -12,7 +12,8 @@ import { type LoadedHooksConfig, fireHook } from "../../hooks";
|
|
|
12
12
|
import { getSafeLogger } from "../../logger";
|
|
13
13
|
import type { PRD, StructuredFailure, UserStory } from "../../prd";
|
|
14
14
|
import { markStoryFailed, savePRD } from "../../prd";
|
|
15
|
-
import {
|
|
15
|
+
import { tryLlmBatchRoute } from "../../routing/batch-route";
|
|
16
|
+
import { clearCacheForStory } from "../../routing/strategies/llm";
|
|
16
17
|
import type { FailureCategory } from "../../tdd/types";
|
|
17
18
|
import { calculateMaxIterations, escalateTier, getTierConfig } from "../escalation";
|
|
18
19
|
import { hookCtx } from "../helpers";
|
|
@@ -172,25 +173,6 @@ export async function preIterationTierCheck(
|
|
|
172
173
|
return { shouldSkipIteration: true, prdDirty: true, prd: failedPrd };
|
|
173
174
|
}
|
|
174
175
|
|
|
175
|
-
/**
|
|
176
|
-
* Try LLM batch routing for ready stories. Logs and swallows errors (falls back to per-story routing).
|
|
177
|
-
*/
|
|
178
|
-
async function tryLlmBatchRoute(config: NaxConfig, stories: UserStory[], label = "routing"): Promise<void> {
|
|
179
|
-
const mode = config.routing.llm?.mode ?? "hybrid";
|
|
180
|
-
if (config.routing.strategy !== "llm" || mode === "per-story" || stories.length === 0) return;
|
|
181
|
-
const logger = getSafeLogger();
|
|
182
|
-
try {
|
|
183
|
-
logger?.debug("routing", `LLM batch routing: ${label}`, { storyCount: stories.length, mode });
|
|
184
|
-
await llmRouteBatch(stories, { config });
|
|
185
|
-
logger?.debug("routing", "LLM batch routing complete", { label });
|
|
186
|
-
} catch (err) {
|
|
187
|
-
logger?.warn("routing", "LLM batch routing failed, falling back to individual routing", {
|
|
188
|
-
error: (err as Error).message,
|
|
189
|
-
label,
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
176
|
export interface EscalationHandlerContext {
|
|
195
177
|
story: UserStory;
|
|
196
178
|
storiesToExecute: UserStory[];
|
|
@@ -25,7 +25,13 @@ export const reviewStage: PipelineStage = {
|
|
|
25
25
|
|
|
26
26
|
logger.info("review", "Running review phase", { storyId: ctx.story.id });
|
|
27
27
|
|
|
28
|
-
const result = await reviewOrchestrator.review(
|
|
28
|
+
const result = await reviewOrchestrator.review(
|
|
29
|
+
ctx.config.review,
|
|
30
|
+
ctx.workdir,
|
|
31
|
+
ctx.config.execution,
|
|
32
|
+
ctx.plugins,
|
|
33
|
+
ctx.storyGitRef,
|
|
34
|
+
);
|
|
29
35
|
|
|
30
36
|
ctx.reviewResult = result.builtIn;
|
|
31
37
|
|
|
@@ -74,6 +74,7 @@ export class ReviewOrchestrator {
|
|
|
74
74
|
workdir: string,
|
|
75
75
|
executionConfig: NaxConfig["execution"],
|
|
76
76
|
plugins?: PluginRegistry,
|
|
77
|
+
storyGitRef?: string,
|
|
77
78
|
): Promise<OrchestratorReviewResult> {
|
|
78
79
|
const logger = getSafeLogger();
|
|
79
80
|
|
|
@@ -87,7 +88,7 @@ export class ReviewOrchestrator {
|
|
|
87
88
|
const reviewers = plugins.getReviewers();
|
|
88
89
|
if (reviewers.length > 0) {
|
|
89
90
|
// Use the story's start ref if available to capture auto-committed changes
|
|
90
|
-
const baseRef = executionConfig?.storyGitRef;
|
|
91
|
+
const baseRef = storyGitRef ?? executionConfig?.storyGitRef;
|
|
91
92
|
const changedFiles = await getChangedFiles(workdir, baseRef);
|
|
92
93
|
const pluginResults: ReviewResult["pluginReviewers"] = [];
|
|
93
94
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* LLM Batch Routing Helper
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import { getAgent } from "../agents/registry";
|
|
5
6
|
import type { NaxConfig } from "../config";
|
|
6
7
|
import { getSafeLogger } from "../logger";
|
|
7
8
|
import type { UserStory } from "../prd";
|
|
@@ -21,7 +22,9 @@ export async function tryLlmBatchRoute(config: NaxConfig, stories: UserStory[],
|
|
|
21
22
|
const logger = getSafeLogger();
|
|
22
23
|
try {
|
|
23
24
|
logger?.debug("routing", `LLM batch routing: ${label}`, { storyCount: stories.length, mode });
|
|
24
|
-
|
|
25
|
+
const agentName = config.execution?.agent ?? "claude";
|
|
26
|
+
const adapter = getAgent(agentName);
|
|
27
|
+
await llmRouteBatch(stories, { config, adapter });
|
|
25
28
|
logger?.debug("routing", "LLM batch routing complete", { label });
|
|
26
29
|
} catch (err) {
|
|
27
30
|
logger?.warn("routing", "LLM batch routing failed, falling back to individual routing", {
|