@nathapp/nax 0.61.0 → 0.61.2-canary.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 +111 -11
- package/package.json +1 -1
package/dist/nax.js
CHANGED
|
@@ -3657,6 +3657,18 @@ function parseAcpxJsonLine(line, state) {
|
|
|
3657
3657
|
};
|
|
3658
3658
|
}
|
|
3659
3659
|
}
|
|
3660
|
+
if (event.error && typeof event.error === "object") {
|
|
3661
|
+
const err = event.error;
|
|
3662
|
+
let errorMsg = typeof err.message === "string" ? err.message : JSON.stringify(event.error);
|
|
3663
|
+
if (err.data && typeof err.data === "object") {
|
|
3664
|
+
const data = err.data;
|
|
3665
|
+
const suffix = [data.acpxCode, data.detailCode].filter(Boolean).join("/");
|
|
3666
|
+
if (suffix)
|
|
3667
|
+
errorMsg = `${errorMsg} [${suffix}]`;
|
|
3668
|
+
}
|
|
3669
|
+
if (!state.error)
|
|
3670
|
+
state.error = errorMsg;
|
|
3671
|
+
}
|
|
3660
3672
|
return;
|
|
3661
3673
|
}
|
|
3662
3674
|
if (event.content && typeof event.content === "string")
|
|
@@ -3807,12 +3819,15 @@ class SpawnAcpSession {
|
|
|
3807
3819
|
Promise.race([stderrPromise, drainB.promise]).finally(() => drainB.cancel())
|
|
3808
3820
|
]);
|
|
3809
3821
|
if (exitCode !== 0) {
|
|
3822
|
+
const parsedOnError = finalizeParseState(parseState);
|
|
3823
|
+
const errorContent = parsedOnError.error || stderr || `Exit code ${exitCode}`;
|
|
3810
3824
|
getSafeLogger()?.warn("acp-adapter", `Session prompt exited with code ${exitCode}`, {
|
|
3811
3825
|
exitCode,
|
|
3812
|
-
|
|
3826
|
+
error: errorContent.slice(0, 500),
|
|
3827
|
+
...stderr && stderr !== errorContent ? { banner: stderr.trim().slice(0, 200) } : {}
|
|
3813
3828
|
});
|
|
3814
3829
|
return {
|
|
3815
|
-
messages: [{ role: "assistant", content:
|
|
3830
|
+
messages: [{ role: "assistant", content: errorContent }],
|
|
3816
3831
|
stopReason: "error"
|
|
3817
3832
|
};
|
|
3818
3833
|
}
|
|
@@ -18070,6 +18085,7 @@ function isLegacyFlatModels(val) {
|
|
|
18070
18085
|
var TokenPricingSchema, ModelDefSchema, ModelEntrySchema, PerAgentModelMapSchema, ModelMapSchema, ModelTierSchema, TierConfigSchema, AutoModeConfigSchema, RectificationConfigSchema, RegressionGateConfigSchema, SmartTestRunnerConfigSchema, SMART_TEST_RUNNER_DEFAULT, smartTestRunnerFieldSchema, ExecutionConfigSchema, QualityConfigSchema, TddConfigSchema, ConstitutionConfigSchema, AnalyzeConfigSchema, SemanticReviewConfigSchema, ReviewDialogueConfigSchema, ReviewConfigSchema, PlanConfigSchema, AcceptanceFixConfigSchema, AcceptanceConfigSchema, TestCoverageConfigSchema, ContextAutoDetectConfigSchema, ContextConfigSchema, LlmRoutingConfigSchema, RoutingConfigSchema, OptimizerConfigSchema, PluginConfigEntrySchema, HooksConfigSchema, InteractionConfigSchema, StorySizeGateConfigSchema, PromptAuditConfigSchema, AgentConfigSchema, PrecheckConfigSchema, PromptsConfigSchema, ProjectProfileSchema, VALID_AGENT_TYPES, GenerateConfigSchema, DebaterPersonaEnum, DebaterSchema, toObject = (val) => val === undefined || val === null ? {} : val, RESOLVER_TYPES, makeResolverSchema = (defaultType) => exports_external.preprocess(toObject, exports_external.object({
|
|
18071
18086
|
type: exports_external.enum(RESOLVER_TYPES).default(defaultType),
|
|
18072
18087
|
agent: exports_external.string().min(1).optional(),
|
|
18088
|
+
model: exports_external.string().min(1).optional(),
|
|
18073
18089
|
tieBreaker: exports_external.string().min(1).optional(),
|
|
18074
18090
|
maxPromptTokens: exports_external.number().int().positive().optional()
|
|
18075
18091
|
})), DebateStageConfigSchema = (defaults) => exports_external.preprocess(toObject, exports_external.object({
|
|
@@ -19086,7 +19102,10 @@ class AcpAgentAdapter {
|
|
|
19086
19102
|
try {
|
|
19087
19103
|
const result = await this._runWithClient(options, startTime, currentAgent);
|
|
19088
19104
|
if (!result.success) {
|
|
19089
|
-
getSafeLogger()?.warn("acp-adapter", `Run failed for ${currentAgent}`, {
|
|
19105
|
+
getSafeLogger()?.warn("acp-adapter", `Run failed for ${currentAgent}`, {
|
|
19106
|
+
exitCode: result.exitCode,
|
|
19107
|
+
...result.output ? { output: result.output.slice(0, 500) } : {}
|
|
19108
|
+
});
|
|
19090
19109
|
if (result.sessionError && _acpAdapterDeps.shouldRetrySessionError && !sessionErrorRetried) {
|
|
19091
19110
|
sessionErrorRetried = true;
|
|
19092
19111
|
getSafeLogger()?.warn("acp-adapter", "Session error \u2014 retrying with fresh session", {
|
|
@@ -21694,12 +21713,16 @@ async function resolveOutcome(proposalOutputs, critiqueOutputs, stageConfig, con
|
|
|
21694
21713
|
const adapter = _debateSessionDeps.getAgent(agentName, config2);
|
|
21695
21714
|
if (adapter) {
|
|
21696
21715
|
const synthesisSessionName = workdir !== undefined ? buildSessionName(workdir, featureName, storyId, "synthesis") : undefined;
|
|
21716
|
+
const resolverDebater = { agent: agentName, model: resolverConfig.model };
|
|
21717
|
+
const resolverTier = resolverConfig.model && MODEL_SHORTHAND_TIERS[resolverConfig.model.toLowerCase()] || modelTierFromDebater(resolverDebater);
|
|
21718
|
+
const resolverModelDef = resolveModelDefForDebater(resolverDebater, resolverTier, config2);
|
|
21697
21719
|
const resolverResult = await synthesisResolver(proposalOutputs, critiqueOutputs, {
|
|
21698
21720
|
adapter,
|
|
21699
21721
|
promptSuffix,
|
|
21700
21722
|
debaters,
|
|
21701
21723
|
completeOptions: {
|
|
21702
|
-
model:
|
|
21724
|
+
model: resolverModelDef.model,
|
|
21725
|
+
modelTier: resolverTier,
|
|
21703
21726
|
config: config2,
|
|
21704
21727
|
storyId,
|
|
21705
21728
|
featureName,
|
|
@@ -21720,12 +21743,16 @@ async function resolveOutcome(proposalOutputs, critiqueOutputs, stageConfig, con
|
|
|
21720
21743
|
if (resolverConfig.type === "custom") {
|
|
21721
21744
|
const agentName = resolverConfig.agent ?? RESOLVER_FALLBACK_AGENT;
|
|
21722
21745
|
const judgeSessionName = workdir !== undefined ? buildSessionName(workdir, featureName, storyId, "judge") : undefined;
|
|
21746
|
+
const resolverDebater = { agent: agentName, model: resolverConfig.model };
|
|
21747
|
+
const resolverTier = resolverConfig.model && MODEL_SHORTHAND_TIERS[resolverConfig.model.toLowerCase()] || modelTierFromDebater(resolverDebater);
|
|
21748
|
+
const resolverModelDef = resolveModelDefForDebater(resolverDebater, resolverTier, config2);
|
|
21723
21749
|
const resolverResult = await judgeResolver(proposalOutputs, critiqueOutputs, resolverConfig, {
|
|
21724
21750
|
getAgent: (name) => _debateSessionDeps.getAgent(name, config2),
|
|
21725
21751
|
defaultAgentName: RESOLVER_FALLBACK_AGENT,
|
|
21726
21752
|
debaters,
|
|
21727
21753
|
completeOptions: {
|
|
21728
|
-
model:
|
|
21754
|
+
model: resolverModelDef.model,
|
|
21755
|
+
modelTier: resolverTier,
|
|
21729
21756
|
config: config2,
|
|
21730
21757
|
storyId,
|
|
21731
21758
|
featureName,
|
|
@@ -22719,7 +22746,8 @@ The spec above is the authoritative source for acceptance criteria.
|
|
|
22719
22746
|
- If a debater proposed criteria beyond the spec (observable edge cases, error-path behaviors), place those in a separate \`suggestedCriteria\` array on the same story object. Each element of \`suggestedCriteria\` MUST be a plain string \u2014 never an object or structured value.
|
|
22720
22747
|
- \`suggestedCriteria\` MUST contain only behavioral acceptance criteria \u2014 observable outputs, return values, state changes, or error conditions a test can assert. DO NOT include: implementation details (imports, internal structure), design suggestions ("consider X"), "not required" notes, or any criterion that cannot be expressed as a test assertion.
|
|
22721
22748
|
- Never silently merge debater-invented criteria into \`acceptanceCriteria\`. The distinction matters: \`acceptanceCriteria\` drives automated testing; \`suggestedCriteria\` gates a hardening pass.
|
|
22722
|
-
- Preserve the spec's AC wording. You may refine for clarity but must not change semantics
|
|
22749
|
+
- Preserve the spec's AC wording. You may refine for clarity but must not change semantics.
|
|
22750
|
+
- Preserve each story's \`routing\` object unchanged \u2014 especially \`routing.complexity\` and \`routing.testStrategy\`. These are required by the schema and must not be dropped or modified during synthesis.` : "";
|
|
22723
22751
|
const planSynthesisSuffix = `IMPORTANT: Your response must be a single valid JSON object in PRD format (with project, feature, branchName, userStories array, etc.). Do NOT wrap it in markdown fences. Output raw JSON only.${specAnchor}`;
|
|
22724
22752
|
const outcome = await resolveOutcome(proposalOutputs, critiqueOutputs, ctx.stageConfig, ctx.config, ctx.storyId, resolverTimeoutMs, opts.workdir, opts.feature, undefined, undefined, planSynthesisSuffix, successful.map((p) => p.debater));
|
|
22725
22753
|
const winningOutput = outcome.output ?? successful[0].output;
|
|
@@ -32371,7 +32399,8 @@ async function runTddSession(role, agent, story, config2, workdir, modelTier, be
|
|
|
32371
32399
|
role,
|
|
32372
32400
|
storyId: story.id,
|
|
32373
32401
|
durationMs: Date.now() - startTime,
|
|
32374
|
-
exitCode: result.exitCode
|
|
32402
|
+
exitCode: result.exitCode,
|
|
32403
|
+
...result.output ? { output: result.output.slice(0, 500) } : {}
|
|
32375
32404
|
});
|
|
32376
32405
|
}
|
|
32377
32406
|
await _sessionRunnerDeps.autoCommitIfDirty(workdir, "tdd", role, story.id);
|
|
@@ -36647,7 +36676,7 @@ var package_default;
|
|
|
36647
36676
|
var init_package = __esm(() => {
|
|
36648
36677
|
package_default = {
|
|
36649
36678
|
name: "@nathapp/nax",
|
|
36650
|
-
version: "0.61.
|
|
36679
|
+
version: "0.61.2-canary.1",
|
|
36651
36680
|
description: "AI Coding Agent Orchestrator \u2014 loops until done",
|
|
36652
36681
|
type: "module",
|
|
36653
36682
|
bin: {
|
|
@@ -36727,8 +36756,8 @@ var init_version = __esm(() => {
|
|
|
36727
36756
|
NAX_VERSION = package_default.version;
|
|
36728
36757
|
NAX_COMMIT = (() => {
|
|
36729
36758
|
try {
|
|
36730
|
-
if (/^[0-9a-f]{6,10}$/.test("
|
|
36731
|
-
return "
|
|
36759
|
+
if (/^[0-9a-f]{6,10}$/.test("7e54444a"))
|
|
36760
|
+
return "7e54444a";
|
|
36732
36761
|
} catch {}
|
|
36733
36762
|
try {
|
|
36734
36763
|
const result = Bun.spawnSync(["git", "rev-parse", "--short", "HEAD"], {
|
|
@@ -41071,6 +41100,68 @@ var init_run_initialization = __esm(() => {
|
|
|
41071
41100
|
};
|
|
41072
41101
|
});
|
|
41073
41102
|
|
|
41103
|
+
// src/execution/lifecycle/paused-story-prompts.ts
|
|
41104
|
+
var exports_paused_story_prompts = {};
|
|
41105
|
+
__export(exports_paused_story_prompts, {
|
|
41106
|
+
promptForPausedStories: () => promptForPausedStories
|
|
41107
|
+
});
|
|
41108
|
+
async function promptForPausedStories(prd, chain, featureName) {
|
|
41109
|
+
const logger = getSafeLogger();
|
|
41110
|
+
const summary = { resumed: [], skipped: [], kept: [] };
|
|
41111
|
+
const pausedStories = prd.userStories.filter((s) => s.status === "paused");
|
|
41112
|
+
for (const story of pausedStories) {
|
|
41113
|
+
const lastReason = (story.priorErrors?.slice(-1)[0] ?? "no reason recorded").replace(/\n/g, " ").slice(0, 200);
|
|
41114
|
+
logger?.info("run-initialization", "Paused story found \u2014 prompting user", {
|
|
41115
|
+
storyId: story.id,
|
|
41116
|
+
attempts: story.attempts
|
|
41117
|
+
});
|
|
41118
|
+
const response = await chain.prompt({
|
|
41119
|
+
id: `ix-${story.id}-paused-resume`,
|
|
41120
|
+
type: "choose",
|
|
41121
|
+
featureName,
|
|
41122
|
+
storyId: story.id,
|
|
41123
|
+
stage: "pre-flight",
|
|
41124
|
+
summary: `Story ${story.id} is paused \u2014 how to proceed?`,
|
|
41125
|
+
detail: `"${story.title}"
|
|
41126
|
+
Last reason: ${lastReason}
|
|
41127
|
+
Attempts so far: ${story.attempts}`,
|
|
41128
|
+
options: [
|
|
41129
|
+
{ key: "resume", label: "Resume", description: "Reset to pending and retry on this run" },
|
|
41130
|
+
{ key: "skip", label: "Skip", description: "Mark as skipped, won't be retried" },
|
|
41131
|
+
{ key: "keep", label: "Keep paused", description: "Leave paused, skip for this run" }
|
|
41132
|
+
],
|
|
41133
|
+
timeout: 300000,
|
|
41134
|
+
fallback: "continue",
|
|
41135
|
+
createdAt: Date.now()
|
|
41136
|
+
});
|
|
41137
|
+
const effectiveAction = chain.applyFallback(response, "continue");
|
|
41138
|
+
const resolvedKey = effectiveAction === "approve" ? "keep" : response.action;
|
|
41139
|
+
switch (resolvedKey) {
|
|
41140
|
+
case "resume": {
|
|
41141
|
+
story.status = "pending";
|
|
41142
|
+
summary.resumed.push(story.id);
|
|
41143
|
+
logger?.info("run-initialization", "User resumed paused story", { storyId: story.id });
|
|
41144
|
+
break;
|
|
41145
|
+
}
|
|
41146
|
+
case "skip": {
|
|
41147
|
+
story.status = "skipped";
|
|
41148
|
+
summary.skipped.push(story.id);
|
|
41149
|
+
logger?.info("run-initialization", "User skipped paused story", { storyId: story.id });
|
|
41150
|
+
break;
|
|
41151
|
+
}
|
|
41152
|
+
default: {
|
|
41153
|
+
summary.kept.push(story.id);
|
|
41154
|
+
logger?.info("run-initialization", "Keeping story paused", { storyId: story.id });
|
|
41155
|
+
break;
|
|
41156
|
+
}
|
|
41157
|
+
}
|
|
41158
|
+
}
|
|
41159
|
+
return summary;
|
|
41160
|
+
}
|
|
41161
|
+
var init_paused_story_prompts = __esm(() => {
|
|
41162
|
+
init_logger2();
|
|
41163
|
+
});
|
|
41164
|
+
|
|
41074
41165
|
// src/execution/lifecycle/run-setup.ts
|
|
41075
41166
|
var exports_run_setup = {};
|
|
41076
41167
|
__export(exports_run_setup, {
|
|
@@ -41199,7 +41290,16 @@ async function setupRun(options) {
|
|
|
41199
41290
|
agentGetFn: options.agentGetFn
|
|
41200
41291
|
});
|
|
41201
41292
|
prd = initResult.prd;
|
|
41202
|
-
|
|
41293
|
+
statusWriter.setPrd(prd);
|
|
41294
|
+
let counts = initResult.storyCounts;
|
|
41295
|
+
if (counts.paused > 0 && interactionChain !== null) {
|
|
41296
|
+
const { promptForPausedStories: promptForPausedStories2 } = await Promise.resolve().then(() => (init_paused_story_prompts(), exports_paused_story_prompts));
|
|
41297
|
+
const pausedSummary = await promptForPausedStories2(prd, interactionChain, feature);
|
|
41298
|
+
if (pausedSummary.resumed.length > 0 || pausedSummary.skipped.length > 0) {
|
|
41299
|
+
await savePRD(prd, prdPath);
|
|
41300
|
+
counts = countStories(prd);
|
|
41301
|
+
}
|
|
41302
|
+
}
|
|
41203
41303
|
return {
|
|
41204
41304
|
statusWriter,
|
|
41205
41305
|
pidRegistry,
|