@nathapp/nax 0.82.0-canary.1 → 0.82.0-canary.2

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.
Files changed (2) hide show
  1. package/dist/nax.js +299 -86
  2. package/package.json +2 -2
package/dist/nax.js CHANGED
@@ -2801,6 +2801,8 @@ function shouldDisplay(entry, mode) {
2801
2801
  }
2802
2802
  if (mode === "verbose")
2803
2803
  return true;
2804
+ if (entry.stage === "coding-tool" && entry.message === "invoked" && entry.data?.outcome === "ok")
2805
+ return false;
2804
2806
  if (entry.stage === "story.start" || entry.stage === "iteration.start")
2805
2807
  return true;
2806
2808
  return entry.level !== "debug";
@@ -4864,6 +4866,9 @@ var init_glob = __esm(() => {
4864
4866
  });
4865
4867
 
4866
4868
  // src/tools/grep.ts
4869
+ function containsRegexMetacharacter(pattern) {
4870
+ return REGEX_METACHARACTERS.test(pattern);
4871
+ }
4867
4872
  function buildGrepArgv(binary, pattern, path) {
4868
4873
  const target = path ?? ".";
4869
4874
  if (binary === "rg") {
@@ -4877,10 +4882,11 @@ function truncate2(body, maxBytes) {
4877
4882
  return `${Buffer.from(body, "utf8").subarray(0, maxBytes).toString("utf8")}
4878
4883
  ... [truncated at ${maxBytes} bytes]`;
4879
4884
  }
4880
- var GREP_TIMEOUT_MS = 15000, _grepDeps, grepTool;
4885
+ var GREP_TIMEOUT_MS = 15000, REGEX_METACHARACTERS, _grepDeps, grepTool;
4881
4886
  var init_grep = __esm(() => {
4882
4887
  init_bounded_io();
4883
4888
  init_bun_deps();
4889
+ REGEX_METACHARACTERS = /[.*+?^${}()|[\]\\]/;
4884
4890
  _grepDeps = { which, spawn };
4885
4891
  grepTool = {
4886
4892
  name: "Grep",
@@ -4918,8 +4924,15 @@ var init_grep = __esm(() => {
4918
4924
  const exitCode = await proc.exited;
4919
4925
  clearTimeout(timer);
4920
4926
  const stdout = await stdoutText;
4921
- if (exitCode === 1 && stdout.trim() === "")
4922
- return { content: `no matches for "${pattern}"` };
4927
+ if (exitCode === 1 && stdout.trim() === "") {
4928
+ const base = `no matches for "${pattern}"`;
4929
+ if (containsRegexMetacharacter(pattern)) {
4930
+ return {
4931
+ content: `${base}. The search was performed literally and regex metacharacters were not interpreted.`
4932
+ };
4933
+ }
4934
+ return { content: base };
4935
+ }
4923
4936
  if (exitCode !== 0 && stdout.trim() === "") {
4924
4937
  return { content: (await stderrText).trim() || `${binary} exited ${exitCode}`, isError: true };
4925
4938
  }
@@ -20734,7 +20747,7 @@ var init_schemas_execution = __esm(() => {
20734
20747
  });
20735
20748
 
20736
20749
  // src/config/schemas-infra.ts
20737
- var PlanConfigSchema, AcceptanceFixConfigSchema, AcceptanceConfigSchema, LlmRoutingConfigSchema, AgentRoutingProfileSchema, AgentRoutingConfigSchema, RoutingConfigSchema, OptimizerConfigSchema, PluginConfigEntrySchema, HooksConfigSchema, InteractionConfigSchema, StorySizeGateConfigSchema, PromptAuditConfigSchema, FallbackTargetSchema, AgentFallbackConfigSchema, DEFAULT_AGENT_IDLE_WATCHDOG_CONFIG, AgentIdleWatchdogConfigSchema, AgentAcpConfigSchema, AgentTimeoutRetryConfigSchema, DEFAULT_AGENT_TIMEOUT_RETRY_CONFIG, AgentConfigSchema, PrecheckConfigSchema, PromptsConfigSchema, ProjectProfileSchema, VALID_AGENT_TYPES, GenerateConfigSchema, CuratorThresholdsSchema, CuratorConfigSchema;
20750
+ var PlanConfigSchema, AcceptanceFixConfigSchema, AcceptanceConfigSchema, LlmRoutingConfigSchema, AgentRoutingProfileSchema, AgentRoutingConfigSchema, RoutingConfigSchema, OptimizerConfigSchema, PluginConfigEntrySchema, HooksConfigSchema, InteractionConfigSchema, StorySizeGateConfigSchema, PromptAuditConfigSchema, FallbackTargetSchema, AgentFallbackConfigSchema, DEFAULT_AGENT_IDLE_WATCHDOG_CONFIG, AgentIdleWatchdogConfigSchema, AgentAcpConfigSchema, AgentNativeTransportRetryConfigSchema, AgentNativeConfigSchema, AgentTimeoutRetryConfigSchema, DEFAULT_AGENT_TIMEOUT_RETRY_CONFIG, AgentConfigSchema, PrecheckConfigSchema, PromptsConfigSchema, ProjectProfileSchema, VALID_AGENT_TYPES, GenerateConfigSchema, CuratorThresholdsSchema, CuratorConfigSchema;
20738
20751
  var init_schemas_infra = __esm(() => {
20739
20752
  init_zod();
20740
20753
  init_schemas_model();
@@ -20916,6 +20929,13 @@ var init_schemas_infra = __esm(() => {
20916
20929
  trackedSpawnDeadlineMs: exports_external.number().int().positive().default(1e4),
20917
20930
  trackedSpawnStartupDeadlineMs: exports_external.number().int().positive().default(30000)
20918
20931
  });
20932
+ AgentNativeTransportRetryConfigSchema = exports_external.object({
20933
+ maxAttempts: exports_external.number().int().min(1).default(3),
20934
+ baseDelayMs: exports_external.number().int().positive().default(2000)
20935
+ });
20936
+ AgentNativeConfigSchema = exports_external.object({
20937
+ transportRetry: AgentNativeTransportRetryConfigSchema.default({ maxAttempts: 3, baseDelayMs: 2000 })
20938
+ });
20919
20939
  AgentTimeoutRetryConfigSchema = exports_external.object({
20920
20940
  maxAttempts: exports_external.number().int().nonnegative().default(1),
20921
20941
  budgetMultiplier: exports_external.number().gt(0).max(1).default(0.5)
@@ -20941,6 +20961,7 @@ var init_schemas_infra = __esm(() => {
20941
20961
  trackedSpawnDeadlineMs: 1e4,
20942
20962
  trackedSpawnStartupDeadlineMs: 30000
20943
20963
  }),
20964
+ native: AgentNativeConfigSchema.default({ transportRetry: { maxAttempts: 3, baseDelayMs: 2000 } }),
20944
20965
  idleWatchdog: AgentIdleWatchdogConfigSchema.default(DEFAULT_AGENT_IDLE_WATCHDOG_CONFIG),
20945
20966
  timeoutRetry: AgentTimeoutRetryConfigSchema.default(DEFAULT_AGENT_TIMEOUT_RETRY_CONFIG)
20946
20967
  });
@@ -21462,6 +21483,7 @@ var init_schemas3 = __esm(() => {
21462
21483
  promptAudit: { enabled: false },
21463
21484
  fallback: { enabled: false, map: {}, maxHopsPerStory: 2, onQualityFailure: false, rebuildContext: true },
21464
21485
  acp: { promptRetries: 0, trackedSpawnDeadlineMs: 1e4, trackedSpawnStartupDeadlineMs: 30000 },
21486
+ native: { transportRetry: { maxAttempts: 3, baseDelayMs: 2000 } },
21465
21487
  idleWatchdog: DEFAULT_AGENT_IDLE_WATCHDOG_CONFIG,
21466
21488
  timeoutRetry: DEFAULT_AGENT_TIMEOUT_RETRY_CONFIG
21467
21489
  }),
@@ -22946,21 +22968,24 @@ function estimateCostUsd(usage, rates) {
22946
22968
  }
22947
22969
  function buildRateCard(catalog, override) {
22948
22970
  if (override !== undefined)
22949
- return override;
22971
+ return { rates: override, source: "config-override" };
22950
22972
  return {
22951
- inputPer1M: catalog.input,
22952
- outputPer1M: catalog.output,
22953
- cacheReadPer1M: catalog.cacheRead,
22954
- cacheCreationPer1M: catalog.cacheWrite,
22955
- ...catalog.tiers !== undefined ? {
22956
- tiers: catalog.tiers.map((tier) => ({
22957
- inputPer1M: tier.input,
22958
- outputPer1M: tier.output,
22959
- cacheReadPer1M: tier.cacheRead,
22960
- cacheCreationPer1M: tier.cacheWrite,
22961
- inputTokensAbove: tier.inputTokensAbove
22962
- }))
22963
- } : {}
22973
+ rates: {
22974
+ inputPer1M: catalog.input,
22975
+ outputPer1M: catalog.output,
22976
+ cacheReadPer1M: catalog.cacheRead,
22977
+ cacheCreationPer1M: catalog.cacheWrite,
22978
+ ...catalog.tiers !== undefined ? {
22979
+ tiers: catalog.tiers.map((tier) => ({
22980
+ inputPer1M: tier.input,
22981
+ outputPer1M: tier.output,
22982
+ cacheReadPer1M: tier.cacheRead,
22983
+ cacheCreationPer1M: tier.cacheWrite,
22984
+ inputTokensAbove: tier.inputTokensAbove
22985
+ }))
22986
+ } : {}
22987
+ },
22988
+ source: "catalog-rates"
22964
22989
  };
22965
22990
  }
22966
22991
  function resolveContextWindow(override, realWindow) {
@@ -23000,12 +23025,15 @@ var ID_LENGTH = 32;
23000
23025
  var init_session_affinity = () => {};
23001
23026
 
23002
23027
  // src/agents/native/session/transcript-store.ts
23003
- import { mkdir as mkdir3, readdir, readFile as readFile4, rm, stat as stat2, writeFile as writeFile4 } from "fs/promises";
23028
+ import { mkdir as mkdir3, readdir, readFile as readFile4, rename as rename2, rm, stat as stat2, writeFile as writeFile4 } from "fs/promises";
23004
23029
  import { join as join8 } from "path";
23005
23030
  function transcriptPath(dir, sessionName) {
23006
23031
  return join8(dir, `${sessionName}.transcript.json`);
23007
23032
  }
23008
- async function loadTranscript(dir, sessionName) {
23033
+ function isLegacyTranscript(parsed) {
23034
+ return Array.isArray(parsed);
23035
+ }
23036
+ async function loadTranscript(dir, sessionName, owner) {
23009
23037
  let raw;
23010
23038
  try {
23011
23039
  raw = await readFile4(transcriptPath(dir, sessionName), "utf8");
@@ -23014,17 +23042,46 @@ async function loadTranscript(dir, sessionName) {
23014
23042
  return [];
23015
23043
  throw err;
23016
23044
  }
23045
+ let parsed;
23017
23046
  try {
23018
- return JSON.parse(raw);
23047
+ parsed = JSON.parse(raw);
23019
23048
  } catch (err) {
23020
23049
  throw new NaxError(`transcript for session "${sessionName}" is unreadable: ${err instanceof Error ? err.message : String(err)}`, "TRANSCRIPT_CORRUPT", {
23021
23050
  stage: "native-session"
23022
23051
  });
23023
23052
  }
23053
+ if (isLegacyTranscript(parsed)) {
23054
+ return owner === undefined ? parsed : [];
23055
+ }
23056
+ const file2 = parsed;
23057
+ if (owner !== undefined && file2.owner !== owner) {
23058
+ getLogger().debug("native-session", "Ignoring a transcript owned by another invocation", {
23059
+ sessionName,
23060
+ storedOwner: file2.owner,
23061
+ owner
23062
+ });
23063
+ return [];
23064
+ }
23065
+ return file2.messages ?? [];
23024
23066
  }
23025
- async function saveTranscript(dir, sessionName, messages) {
23067
+ async function saveTranscript(dir, sessionName, messages, owner) {
23026
23068
  await mkdir3(dir, { recursive: true });
23027
- await writeFile4(transcriptPath(dir, sessionName), JSON.stringify(messages, null, 2), "utf8");
23069
+ const file2 = {
23070
+ ...owner !== undefined ? { owner } : {},
23071
+ savedAt: new Date().toISOString(),
23072
+ messages: [...messages]
23073
+ };
23074
+ await writeFile4(transcriptPath(dir, sessionName), JSON.stringify(file2, null, 2), "utf8");
23075
+ }
23076
+ async function retainTranscript(dir, sessionName) {
23077
+ const stamp = new Date().toISOString().replace(/[:.]/g, "-");
23078
+ try {
23079
+ await rename2(transcriptPath(dir, sessionName), join8(dir, `${sessionName}.transcript.failed-${stamp}.json`));
23080
+ } catch (err) {
23081
+ if (err.code === "ENOENT")
23082
+ return;
23083
+ throw err;
23084
+ }
23028
23085
  }
23029
23086
  async function deleteTranscript(dir, sessionName) {
23030
23087
  await rm(transcriptPath(dir, sessionName), { force: true });
@@ -23038,7 +23095,7 @@ async function pruneRetainedTranscripts(dir, maxRetained = MAX_RETAINED_TRANSCRI
23038
23095
  return;
23039
23096
  throw err;
23040
23097
  }
23041
- const transcriptFiles = entries.filter((name) => name.endsWith(".transcript.json"));
23098
+ const transcriptFiles = entries.filter((name) => name.includes(".transcript.") && name.endsWith(".json"));
23042
23099
  if (transcriptFiles.length <= maxRetained)
23043
23100
  return;
23044
23101
  const withMtimes = await Promise.all(transcriptFiles.map(async (name) => {
@@ -23079,8 +23136,16 @@ async function openNativeSession(name, opts) {
23079
23136
  }
23080
23137
  nativeTranscriptDirs.set(name, opts.transcriptDir);
23081
23138
  nativeSessionTimeouts.set(name, opts.timeoutSeconds);
23139
+ if (opts.transcriptOwner !== undefined)
23140
+ nativeSessionTranscriptOwners.set(name, opts.transcriptOwner);
23141
+ else
23142
+ nativeSessionTranscriptOwners.delete(name);
23143
+ if (opts.resume !== true)
23144
+ await deleteTranscript(opts.transcriptDir, name);
23082
23145
  if (opts.compaction !== undefined)
23083
23146
  nativeSessionCompaction.set(name, opts.compaction);
23147
+ if (opts.transportRetry !== undefined)
23148
+ nativeSessionTransportRetry.set(name, opts.transportRetry);
23084
23149
  nativeSessionStreamHooks.set(name, {
23085
23150
  ...opts.onStreamActivity !== undefined ? { onStreamActivity: opts.onStreamActivity } : {},
23086
23151
  ...opts.onActiveCall !== undefined ? { onActiveCall: opts.onActiveCall } : {}
@@ -23098,6 +23163,7 @@ async function closeNativeSession(handle, failed) {
23098
23163
  const treatAsFailed = failed ?? nativeSessionFailed.has(handle.id);
23099
23164
  if (dir !== undefined) {
23100
23165
  if (treatAsFailed) {
23166
+ await retainTranscript(dir, handle.id);
23101
23167
  await pruneRetainedTranscripts(dir);
23102
23168
  } else {
23103
23169
  await deleteTranscript(dir, handle.id);
@@ -23105,12 +23171,14 @@ async function closeNativeSession(handle, failed) {
23105
23171
  }
23106
23172
  nativeTranscriptDirs.delete(handle.id);
23107
23173
  nativeSessionTimeouts.delete(handle.id);
23174
+ nativeSessionTranscriptOwners.delete(handle.id);
23108
23175
  nativeSessionStreamHooks.delete(handle.id);
23109
23176
  nativeSessionFailed.delete(handle.id);
23110
23177
  nativeSessionCompaction.delete(handle.id);
23178
+ nativeSessionTransportRetry.delete(handle.id);
23111
23179
  nativeSessionLastUsage.delete(handle.id);
23112
23180
  }
23113
- var nativeTranscriptDirs, nativeSessionTimeouts, nativeSessionStreamHooks, nativeSessionFailed, nativeSessionCompaction, nativeSessionLastUsage;
23181
+ var nativeTranscriptDirs, nativeSessionTimeouts, nativeSessionStreamHooks, nativeSessionFailed, nativeSessionTranscriptOwners, nativeSessionCompaction, nativeSessionTransportRetry, nativeSessionLastUsage;
23114
23182
  var init_session = __esm(() => {
23115
23183
  init_errors();
23116
23184
  init_models();
@@ -23120,7 +23188,9 @@ var init_session = __esm(() => {
23120
23188
  nativeSessionTimeouts = new Map;
23121
23189
  nativeSessionStreamHooks = new Map;
23122
23190
  nativeSessionFailed = new Set;
23191
+ nativeSessionTranscriptOwners = new Map;
23123
23192
  nativeSessionCompaction = new Map;
23193
+ nativeSessionTransportRetry = new Map;
23124
23194
  nativeSessionLastUsage = new Map;
23125
23195
  });
23126
23196
 
@@ -23273,6 +23343,78 @@ function codingToolsToDefinitions(tools) {
23273
23343
  }));
23274
23344
  }
23275
23345
 
23346
+ // src/agents/native/session/turn-retry.ts
23347
+ function isRetryableTransportFault(err) {
23348
+ if (typeof err !== "object" || err === null || !("protocolError" in err))
23349
+ return false;
23350
+ const { protocolError } = err;
23351
+ return typeof protocolError?.kind === "string" && RETRYABLE_KINDS.has(protocolError.kind);
23352
+ }
23353
+ function canAttemptTurnRetry(retryIndex, config2) {
23354
+ return retryIndex < config2.maxAttempts - 1;
23355
+ }
23356
+ function backoffMs(retryIndex, baseDelayMs, random) {
23357
+ const half = baseDelayMs * 2 ** retryIndex / 2;
23358
+ return Math.floor(half + random() * half);
23359
+ }
23360
+ function turnRetryDelayMs(err, retryIndex, config2, random = Math.random, remainingMs) {
23361
+ const { retryAfter } = err.protocolError;
23362
+ const delayMs = retryAfter !== undefined ? retryAfter * 1000 : backoffMs(retryIndex, config2.baseDelayMs, random);
23363
+ return remainingMs === undefined ? delayMs : Math.min(delayMs, remainingMs);
23364
+ }
23365
+ function abortError(signal) {
23366
+ return signal.reason ?? new DOMException("Aborted", "AbortError");
23367
+ }
23368
+ function abortableSleep(ms, sleep2, signal) {
23369
+ if (signal === undefined)
23370
+ return sleep2(ms);
23371
+ if (signal.aborted)
23372
+ return Promise.reject(abortError(signal));
23373
+ return new Promise((resolve6, reject) => {
23374
+ const onAbort = () => reject(abortError(signal));
23375
+ signal.addEventListener("abort", onAbort, { once: true });
23376
+ sleep2(ms).then(() => {
23377
+ signal.removeEventListener("abort", onAbort);
23378
+ resolve6();
23379
+ }, reject);
23380
+ });
23381
+ }
23382
+ function realSleep(ms) {
23383
+ return new Promise((resolve6) => setTimeout(resolve6, ms));
23384
+ }
23385
+ async function retryTransportFault(firstError, deps) {
23386
+ const { sleep: sleep2 } = deps;
23387
+ const random = deps.random ?? Math.random;
23388
+ let err = firstError;
23389
+ let retryIndex = 0;
23390
+ for (;; ) {
23391
+ if (!isRetryableTransportFault(err))
23392
+ throw err;
23393
+ if (!canAttemptTurnRetry(retryIndex, deps.config))
23394
+ throw err;
23395
+ if (deps.deadline?.expired() === true || deps.signal?.aborted === true)
23396
+ throw err;
23397
+ const fault = err;
23398
+ const delayMs = turnRetryDelayMs(fault, retryIndex, deps.config, random, deps.deadline?.remainingMs());
23399
+ deps.onRetry?.(retryIndex + 1, delayMs, fault);
23400
+ try {
23401
+ await abortableSleep(delayMs, sleep2, deps.signal);
23402
+ } catch {
23403
+ throw fault;
23404
+ }
23405
+ try {
23406
+ return await deps.attempt();
23407
+ } catch (nextErr) {
23408
+ err = nextErr;
23409
+ retryIndex += 1;
23410
+ }
23411
+ }
23412
+ }
23413
+ var RETRYABLE_KINDS;
23414
+ var init_turn_retry = __esm(() => {
23415
+ RETRYABLE_KINDS = new Set(["transport", "overloaded"]);
23416
+ });
23417
+
23276
23418
  // src/agents/native/session/turn-loop.ts
23277
23419
  function readNativeTurnFailureUsage(err) {
23278
23420
  return typeof err === "object" && err !== null ? failureUsageByError.get(err) : undefined;
@@ -23290,7 +23432,8 @@ async function runNativeTurn(handle, prompt, opts, deps) {
23290
23432
  stage: "native-session"
23291
23433
  });
23292
23434
  }
23293
- let messages = [...await loadTranscript(dir, handle.id)];
23435
+ const transcriptOwner = nativeSessionTranscriptOwners.get(handle.id);
23436
+ let messages = [...await loadTranscript(dir, handle.id, transcriptOwner)];
23294
23437
  messages.push({ role: "user", content: prompt });
23295
23438
  const codingTools = opts.codingTools ?? [];
23296
23439
  const codingToolNames = new Set(codingTools.map((t) => t.name));
@@ -23369,25 +23512,43 @@ async function runNativeTurn(handle, prompt, opts, deps) {
23369
23512
  res = await deps.complete(messages, tools);
23370
23513
  } catch (err) {
23371
23514
  if (!isContextOverflow(err) || summarizeFailed || deps.summarize === undefined || deps.contextWindow === undefined || deps.compaction === undefined || !deps.compaction.enabled) {
23372
- throw err;
23515
+ if (deps.transportRetry === undefined)
23516
+ throw err;
23517
+ res = await retryTransportFault(err, {
23518
+ attempt: () => deps.complete(messages, tools),
23519
+ config: deps.transportRetry,
23520
+ deadline: deps.deadline,
23521
+ signal: opts.signal,
23522
+ sleep: deps.sleep ?? realSleep,
23523
+ onRetry: (retryNumber, delayMs, fault) => {
23524
+ getSafeLogger()?.warn("native-adapter", "retrying after a transport fault", {
23525
+ sessionName: handle.id,
23526
+ retryNumber,
23527
+ delayMs,
23528
+ kind: fault.protocolError.kind
23529
+ });
23530
+ deps.onActivity?.({ kind: "usage", inputTokens: 0, outputTokens: 0, costUsd: 0 });
23531
+ }
23532
+ });
23533
+ } else {
23534
+ const plan = prepareCompaction(messages, keepBudget(deps.contextWindow, deps.compaction, true));
23535
+ if (plan === undefined)
23536
+ throw err;
23537
+ const summary = await deps.summarize(plan.toSummarize, plan.previousSummary);
23538
+ messages = applyCompaction(messages, plan, summary.text);
23539
+ inputTokens += summary.usage.inputTokens;
23540
+ outputTokens += summary.usage.outputTokens;
23541
+ costUsd += summary.costUsd;
23542
+ deps.onActivity?.({
23543
+ kind: "usage",
23544
+ inputTokens: summary.usage.inputTokens,
23545
+ outputTokens: summary.usage.outputTokens,
23546
+ costUsd: summary.costUsd
23547
+ });
23548
+ lastUsage = undefined;
23549
+ anchorIndex = undefined;
23550
+ res = await deps.complete(messages, tools);
23373
23551
  }
23374
- const plan = prepareCompaction(messages, keepBudget(deps.contextWindow, deps.compaction, true));
23375
- if (plan === undefined)
23376
- throw err;
23377
- const summary = await deps.summarize(plan.toSummarize, plan.previousSummary);
23378
- messages = applyCompaction(messages, plan, summary.text);
23379
- inputTokens += summary.usage.inputTokens;
23380
- outputTokens += summary.usage.outputTokens;
23381
- costUsd += summary.costUsd;
23382
- deps.onActivity?.({
23383
- kind: "usage",
23384
- inputTokens: summary.usage.inputTokens,
23385
- outputTokens: summary.usage.outputTokens,
23386
- costUsd: summary.costUsd
23387
- });
23388
- lastUsage = undefined;
23389
- anchorIndex = undefined;
23390
- res = await deps.complete(messages, tools);
23391
23552
  }
23392
23553
  roundTrips += 1;
23393
23554
  inputTokens += res.usage.inputTokens;
@@ -23481,7 +23642,7 @@ async function runNativeTurn(handle, prompt, opts, deps) {
23481
23642
  }
23482
23643
  }
23483
23644
  } catch (err) {
23484
- await saveTranscript(dir, handle.id, messages).catch((saveErr) => {
23645
+ await saveTranscript(dir, handle.id, messages, transcriptOwner).catch((saveErr) => {
23485
23646
  getSafeLogger()?.warn("native-adapter", "could not persist the transcript of a failed turn", {
23486
23647
  sessionName: handle.id,
23487
23648
  error: saveErr instanceof Error ? saveErr.message : String(saveErr)
@@ -23507,7 +23668,7 @@ async function runNativeTurn(handle, prompt, opts, deps) {
23507
23668
  timedOut
23508
23669
  });
23509
23670
  }
23510
- await saveTranscript(dir, handle.id, messages);
23671
+ await saveTranscript(dir, handle.id, messages, transcriptOwner);
23511
23672
  return {
23512
23673
  output,
23513
23674
  tokenUsage: {
@@ -23521,7 +23682,8 @@ async function runNativeTurn(handle, prompt, opts, deps) {
23521
23682
  ...codingTools.length > 0 ? { codingToolUse: { advertised: codingTools.length, called: codingToolsCalled } } : {},
23522
23683
  ...completedNormally ? {} : { turnIncomplete: true },
23523
23684
  ...timedOut ? { timedOut: true } : {},
23524
- ...interactions.length > 0 ? { interactions } : {}
23685
+ ...interactions.length > 0 ? { interactions } : {},
23686
+ ...deps.pricingSource !== undefined ? { pricingSource: deps.pricingSource } : {}
23525
23687
  };
23526
23688
  }
23527
23689
  var failureUsageByError;
@@ -23532,6 +23694,7 @@ var init_turn_loop = __esm(() => {
23532
23694
  init_ask_human();
23533
23695
  init_session();
23534
23696
  init_transcript_store();
23697
+ init_turn_retry();
23535
23698
  failureUsageByError = new WeakMap;
23536
23699
  });
23537
23700
 
@@ -23587,20 +23750,23 @@ class NativeAgentAdapter {
23587
23750
  const controller = new AbortController;
23588
23751
  const timer = options.timeoutMs !== undefined ? setTimeout(() => controller.abort(), options.timeoutMs) : undefined;
23589
23752
  try {
23753
+ const sessionId = nativeSessionId(this.oneShotKey);
23590
23754
  const result = await client.complete(resolved, {
23591
23755
  messages: [{ role: "user", content: prompt }],
23592
23756
  ...options.maxTokens !== undefined ? { maxTokens: options.maxTokens } : {},
23593
- sessionId: nativeSessionId(this.oneShotKey),
23757
+ sessionId,
23594
23758
  signal: controller.signal,
23595
23759
  ...thinking !== undefined ? { thinking } : {}
23596
23760
  });
23597
23761
  const tokenUsage = toNaxTokenUsage(result.usage);
23598
23762
  const catalog = client.pricing(resolved);
23599
- const rates = buildRateCard(catalog, options.modelDef.pricing);
23763
+ const { rates, source: pricingSource } = buildRateCard(catalog, options.modelDef.pricing);
23600
23764
  return {
23601
23765
  output: result.text,
23602
23766
  tokenUsage,
23603
- estimatedCostUsd: estimateCostUsd(tokenUsage, rates)
23767
+ estimatedCostUsd: estimateCostUsd(tokenUsage, rates),
23768
+ sessionId,
23769
+ pricingSource
23604
23770
  };
23605
23771
  } catch (err) {
23606
23772
  if (isProtocolStreamError(err)) {
@@ -23626,7 +23792,7 @@ class NativeAgentAdapter {
23626
23792
  const client = await getNativeClient();
23627
23793
  const resolved = await client.model(provider, model);
23628
23794
  const catalog = client.pricing(resolved);
23629
- const rates = buildRateCard(catalog, handle.modelDef?.pricing);
23795
+ const { rates, source: pricingSource } = buildRateCard(catalog, handle.modelDef?.pricing);
23630
23796
  const storedTimeoutSeconds = nativeSessionTimeouts.get(handle.id);
23631
23797
  if (storedTimeoutSeconds === undefined) {
23632
23798
  getSafeLogger()?.warn("native-adapter", "session has no recorded timeout; falling back to the default budget", {
@@ -23655,6 +23821,8 @@ class NativeAgentAdapter {
23655
23821
  deadline,
23656
23822
  contextWindow: resolveContextWindow(handle.modelDef?.contextWindow, resolved.contextWindow),
23657
23823
  ...nativeSessionCompaction.get(handle.id) !== undefined ? { compaction: nativeSessionCompaction.get(handle.id) } : {},
23824
+ ...nativeSessionTransportRetry.get(handle.id) !== undefined ? { transportRetry: nativeSessionTransportRetry.get(handle.id) } : {},
23825
+ pricingSource,
23658
23826
  onActivity: (activity) => {
23659
23827
  hooks?.onStreamActivity?.(buildNativeStreamEvent(eventBase, activity, Date.now()));
23660
23828
  },
@@ -28085,6 +28253,33 @@ var init_acp = __esm(() => {
28085
28253
  init_token_mapper();
28086
28254
  });
28087
28255
 
28256
+ // src/agents/transport-failure-message.ts
28257
+ function isTransportFailureMessage(message) {
28258
+ if (!message)
28259
+ return false;
28260
+ const haystack = message.toLowerCase();
28261
+ return TRANSPORT_FAULT_MARKERS.some((marker) => haystack.includes(marker));
28262
+ }
28263
+ var TRANSPORT_FAULT_MARKERS;
28264
+ var init_transport_failure_message = __esm(() => {
28265
+ TRANSPORT_FAULT_MARKERS = [
28266
+ "idle timeout exceeded",
28267
+ "stream idle timeout",
28268
+ "upstream timeout",
28269
+ "bad gateway",
28270
+ "service unavailable",
28271
+ "gateway timeout",
28272
+ "econnreset",
28273
+ "econnrefused",
28274
+ "econnaborted",
28275
+ "etimedout",
28276
+ "socket hang up",
28277
+ "premature close",
28278
+ "terminated: other side closed",
28279
+ "network error"
28280
+ ];
28281
+ });
28282
+
28088
28283
  // src/agents/complete-exception-classifier.ts
28089
28284
  function classifyCompleteException(err) {
28090
28285
  const fullMessage = errorMessage(err);
@@ -28111,13 +28306,14 @@ function classifyCompleteException(err) {
28111
28306
  case "crash":
28112
28307
  return { category: "quality", outcome: "fail-adapter-error", retriable: false, message };
28113
28308
  default:
28114
- return { category: "quality", outcome: "fail-unknown", retriable: false, message };
28309
+ return isTransportFailureMessage(fullMessage) ? { category: "availability", outcome: "fail-service-down", retriable: true, message } : { category: "quality", outcome: "fail-unknown", retriable: false, message };
28115
28310
  }
28116
28311
  }
28117
28312
  var MAX_FAILURE_MESSAGE_CHARS = 500;
28118
28313
  var init_complete_exception_classifier = __esm(() => {
28119
28314
  init_errors();
28120
28315
  init_acp();
28316
+ init_transport_failure_message();
28121
28317
  });
28122
28318
 
28123
28319
  // src/runtime/no-op-interaction-handler.ts
@@ -28581,6 +28777,7 @@ function buildSessionTurnEvent(input) {
28581
28777
  exactCostUsd: result.exactCostUsd,
28582
28778
  durationMs: Date.now() - startedAt,
28583
28779
  timestamp: Date.now(),
28780
+ ...result.pricingSource !== undefined ? { pricingSource: result.pricingSource } : {},
28584
28781
  roundTrips: result.internalRoundTrips ?? 1,
28585
28782
  roundTripUnit: input.agentName === NATIVE_AGENT ? "model-call" : "agent-run",
28586
28783
  protocolIds: {
@@ -28614,6 +28811,8 @@ function buildCompleteEvent(input) {
28614
28811
  exactCostUsd: input.exactCostUsd,
28615
28812
  durationMs: Date.now() - input.startedAt,
28616
28813
  timestamp: Date.now(),
28814
+ ...input.sessionId !== undefined ? { sessionId: input.sessionId } : {},
28815
+ ...input.pricingSource !== undefined ? { pricingSource: input.pricingSource } : {},
28617
28816
  ...options.callId !== undefined ? { callId: options.callId } : {},
28618
28817
  ...options.scopeId !== undefined ? { scopeId: options.scopeId } : {}
28619
28818
  };
@@ -29467,7 +29666,9 @@ class AgentManager {
29467
29666
  estimatedCostUsd: outcome.result.estimatedCostUsd,
29468
29667
  exactCostUsd: outcome.result.exactCostUsd,
29469
29668
  profile: this._config.profile,
29470
- startedAt: start
29669
+ startedAt: start,
29670
+ sessionId: outcome.result.sessionId,
29671
+ ...outcome.result.pricingSource !== undefined ? { pricingSource: outcome.result.pricingSource } : {}
29471
29672
  });
29472
29673
  this._dispatchEvents.emitDispatch(event);
29473
29674
  return outcome;
@@ -40143,6 +40344,15 @@ var init_naming = __esm(() => {
40143
40344
  init_session_name();
40144
40345
  });
40145
40346
 
40347
+ // src/session/turn-config-selection.ts
40348
+ function selectNativeTurnConfig(config2) {
40349
+ const retry = config2?.agent?.native?.transportRetry;
40350
+ return {
40351
+ compaction: config2?.execution?.compaction,
40352
+ transportRetry: { maxAttempts: retry?.maxAttempts ?? 3, baseDelayMs: retry?.baseDelayMs ?? 2000 }
40353
+ };
40354
+ }
40355
+
40146
40356
  // src/runtime/session-role.ts
40147
40357
  function isSessionRole(s) {
40148
40358
  if (KNOWN_SESSION_ROLES.includes(s))
@@ -40493,14 +40703,13 @@ class SessionManager {
40493
40703
  throw new NaxError(`SessionManager.openSession: no adapter found for agent "${opts.agentName}"`, "ADAPTER_NOT_FOUND", { stage: "session", agentName: opts.agentName });
40494
40704
  }
40495
40705
  const resolvedPermissions = resolvePermissions(opts.config ?? this._config, opts.pipelineStage);
40496
- const compaction = (opts.config ?? this._config)?.execution?.compaction;
40497
40706
  const existingDescriptor = this._findByName(name);
40498
40707
  const resume = existingDescriptor !== undefined;
40499
40708
  const handle = await adapter.openSession(name, {
40500
40709
  agentName: opts.agentName,
40501
40710
  workdir: opts.workdir,
40502
40711
  resolvedPermissions,
40503
- compaction,
40712
+ ...selectNativeTurnConfig(opts.config ?? this._config),
40504
40713
  ...selectModel(opts),
40505
40714
  timeoutSeconds: opts.timeoutSeconds,
40506
40715
  onPidSpawned: this._pidRegistry ? (pid) => this._pidRegistry?.register(pid) : undefined,
@@ -40511,6 +40720,7 @@ class SessionManager {
40511
40720
  onActiveCall: this._buildOnActiveCall(name),
40512
40721
  onStreamActivity: this._onStreamActivity,
40513
40722
  transcriptDir: opts.transcriptDir ?? deriveNativeTranscriptDir({ featureName: opts.featureName, transcriptRoot: this._transcriptRoot }),
40723
+ ...opts.transcriptOwner !== undefined ? { transcriptOwner: opts.transcriptOwner } : {},
40514
40724
  ...trackedSpawnDeadlines(this._config)
40515
40725
  });
40516
40726
  this._liveHandles.set(name, handle);
@@ -40686,7 +40896,7 @@ function recordAgentHandoff(sessionManager, sessionName, newAgent, reason) {
40686
40896
  }
40687
40897
 
40688
40898
  // src/session/scratch-purge.ts
40689
- import { mkdir as mkdir6, rename as rename2, rm as rm2 } from "fs/promises";
40899
+ import { mkdir as mkdir6, rename as rename3, rm as rm2 } from "fs/promises";
40690
40900
  import { dirname as dirname7, join as join18 } from "path";
40691
40901
  async function purgeStaleScratch(projectDir, featureName, retentionDays, archiveInsteadOfDelete = false) {
40692
40902
  const sessionsDir = join18(featureDir(projectDir, featureName), "sessions");
@@ -40741,7 +40951,7 @@ var init_scratch_purge = __esm(() => {
40741
40951
  remove: (path5) => rm2(path5, { recursive: true, force: true }),
40742
40952
  move: async (src, dest) => {
40743
40953
  await mkdir6(dirname7(dest), { recursive: true });
40744
- await rename2(src, dest);
40954
+ await rename3(src, dest);
40745
40955
  },
40746
40956
  now: () => Date.now()
40747
40957
  };
@@ -43667,7 +43877,7 @@ __export(exports_tracker, {
43667
43877
  saveRunMetrics: () => saveRunMetrics,
43668
43878
  toFallbackHops: () => toFallbackHops
43669
43879
  });
43670
- import { rename as rename3 } from "fs/promises";
43880
+ import { rename as rename4 } from "fs/promises";
43671
43881
  import path5 from "path";
43672
43882
  function _resetRunTruncationWarningForTests() {
43673
43883
  hasWarnedAboutRunTruncation = false;
@@ -43878,7 +44088,7 @@ async function loadExistingMetricsOrQuarantine(metricsPath) {
43878
44088
  } catch (err) {
43879
44089
  const quarantinePath = `${metricsPath}.corrupt-${new Date().toISOString().replace(/[:.]/g, "-")}`;
43880
44090
  try {
43881
- await rename3(metricsPath, quarantinePath);
44091
+ await rename4(metricsPath, quarantinePath);
43882
44092
  } catch (renameErr) {
43883
44093
  getLogger().warn("metrics", "Failed to quarantine corrupt metrics.json \u2014 leaving in place", {
43884
44094
  metricsPath,
@@ -47687,6 +47897,7 @@ function buildHopCallback(ctx, sessionId, _initialOptions) {
47687
47897
  role: resolvedRunOptions.sessionRole ?? "implementer",
47688
47898
  pipelineStage: stage
47689
47899
  });
47900
+ const transcriptOwner = resolvedRunOptions.scopeId ?? resolvedRunOptions.callId;
47690
47901
  const pinnedModelDef = pinnedModelAgent === undefined || pinnedModelAgent === agentName ? resolvedRunOptions.modelDef : undefined;
47691
47902
  let handle;
47692
47903
  if (hopKind.kind === "stale-retry") {
@@ -47711,6 +47922,7 @@ function buildHopCallback(ctx, sessionId, _initialOptions) {
47711
47922
  timeoutSeconds: resolvedRunOptions.timeoutSeconds ?? config2.execution?.sessionTimeoutSeconds ?? DEFAULT_CONFIG.execution.sessionTimeoutSeconds,
47712
47923
  featureName,
47713
47924
  storyId: story.id,
47925
+ ...transcriptOwner !== undefined ? { transcriptOwner } : {},
47714
47926
  signal: resolvedRunOptions.abortSignal
47715
47927
  });
47716
47928
  }
@@ -47729,6 +47941,7 @@ function buildHopCallback(ctx, sessionId, _initialOptions) {
47729
47941
  timeoutSeconds: resolvedRunOptions.timeoutSeconds ?? config2.execution?.sessionTimeoutSeconds ?? DEFAULT_CONFIG.execution.sessionTimeoutSeconds,
47730
47942
  featureName,
47731
47943
  storyId: story.id,
47944
+ ...transcriptOwner !== undefined ? { transcriptOwner } : {},
47732
47945
  signal: resolvedRunOptions.abortSignal
47733
47946
  });
47734
47947
  }
@@ -51833,7 +52046,7 @@ function allowPatternToRegex(pattern) {
51833
52046
  }
51834
52047
  continue;
51835
52048
  }
51836
- source += REGEX_METACHARACTERS.includes(char) ? `\\${char}` : char;
52049
+ source += REGEX_METACHARACTERS2.includes(char) ? `\\${char}` : char;
51837
52050
  }
51838
52051
  return new RegExp(`^${source}$`);
51839
52052
  }
@@ -51896,7 +52109,7 @@ async function verifyImplementerIsolation(workdir, beforeRef, testFilePatterns =
51896
52109
  description: "Implementer should not modify test files"
51897
52110
  };
51898
52111
  }
51899
- var GIT_TIMEOUT_MS2 = 1e4, _isolationDeps, SRC_PATTERNS, REGEX_METACHARACTERS = `.+?^\${}()|[]\\/`, LITE_STUB_ADDED_LINES_CEILING = 20;
52112
+ var GIT_TIMEOUT_MS2 = 1e4, _isolationDeps, SRC_PATTERNS, REGEX_METACHARACTERS2 = `.+?^\${}()|[]\\/`, LITE_STUB_ADDED_LINES_CEILING = 20;
51900
52113
  var init_isolation = __esm(() => {
51901
52114
  init_errors();
51902
52115
  init_logger2();
@@ -59976,7 +60189,7 @@ var package_default;
59976
60189
  var init_package = __esm(() => {
59977
60190
  package_default = {
59978
60191
  name: "@nathapp/nax",
59979
- version: "0.82.0-canary.1",
60192
+ version: "0.82.0-canary.2",
59980
60193
  description: "AI Coding Agent Orchestrator \u2014 loops until done",
59981
60194
  type: "module",
59982
60195
  bin: {
@@ -60044,7 +60257,7 @@ var init_package = __esm(() => {
60044
60257
  "spec:lint": "bun run scripts/spec-lint.ts"
60045
60258
  },
60046
60259
  dependencies: {
60047
- "@nathapp/nax-ai": "0.1.7",
60260
+ "@nathapp/nax-ai": "0.1.8",
60048
60261
  "@types/react": "^19.2.14",
60049
60262
  chalk: "^5.6.2",
60050
60263
  commander: "^13.1.0",
@@ -60097,8 +60310,8 @@ var init_version = __esm(() => {
60097
60310
  NAX_VERSION = package_default.version;
60098
60311
  NAX_COMMIT = (() => {
60099
60312
  try {
60100
- if (/^[0-9a-f]{6,10}$/.test("b2b9889d"))
60101
- return "b2b9889d";
60313
+ if (/^[0-9a-f]{6,10}$/.test("c2ee0b93"))
60314
+ return "c2ee0b93";
60102
60315
  } catch {}
60103
60316
  try {
60104
60317
  const result = Bun.spawnSync(["git", "rev-parse", "--short", "HEAD"], {
@@ -60661,7 +60874,8 @@ function attachAuditSubscriber(bus, auditor, runId) {
60661
60874
  roundTrips: event.roundTrips,
60662
60875
  roundTripUnit: event.roundTripUnit,
60663
60876
  ...event.interactions?.length ? { interactions: event.interactions } : {}
60664
- }
60877
+ },
60878
+ ...event.kind === "complete" && event.sessionId !== undefined ? { sessionId: event.sessionId } : {}
60665
60879
  };
60666
60880
  auditor.record(entry);
60667
60881
  });
@@ -60742,7 +60956,7 @@ function attachCostSubscriber(bus, aggregator, runId, projectKey) {
60742
60956
  exactCostUsd,
60743
60957
  costUsd: exactCostUsd,
60744
60958
  confidence,
60745
- pricingSource: hasWireExactCost ? "wire" : resolvePricingSource(event.model),
60959
+ pricingSource: hasWireExactCost ? "wire" : event.pricingSource ?? resolvePricingSource(event.model),
60746
60960
  durationMs: event.durationMs
60747
60961
  };
60748
60962
  aggregator.record(costEvent);
@@ -61016,8 +61230,9 @@ function deriveAuditSuffix(entry) {
61016
61230
  const stage = entry.stage ?? "run";
61017
61231
  return `${stage}-t${String(entry.turn).padStart(2, "0")}`;
61018
61232
  }
61019
- if (entry.callType === "complete")
61020
- return "complete";
61233
+ if (entry.callType === "complete") {
61234
+ return entry.stage ? `${entry.stage}-complete` : "complete";
61235
+ }
61021
61236
  return entry.stage ?? entry.callType;
61022
61237
  }
61023
61238
  function buildTxtContent(entry) {
@@ -61803,6 +62018,7 @@ function createSessionRunHop(sessionManager, getAgentManager) {
61803
62018
  role: options.sessionRole,
61804
62019
  pipelineStage: options.pipelineStage
61805
62020
  });
62021
+ const transcriptOwner = options.scopeId ?? options.callId;
61806
62022
  const handle = await sessionManager.openSession(sessionName, {
61807
62023
  agentName,
61808
62024
  role: options.sessionRole,
@@ -61813,6 +62029,7 @@ function createSessionRunHop(sessionManager, getAgentManager) {
61813
62029
  timeoutSeconds: options.timeoutSeconds,
61814
62030
  featureName: options.featureName,
61815
62031
  storyId: options.storyId,
62032
+ ...transcriptOwner !== undefined ? { transcriptOwner } : {},
61816
62033
  signal: options.abortSignal,
61817
62034
  onSessionEstablished: options.onSessionEstablished
61818
62035
  });
@@ -61965,10 +62182,7 @@ function createRuntime(config2, workdir, opts) {
61965
62182
  let promptAuditor;
61966
62183
  if (opts?.promptAuditor) {
61967
62184
  promptAuditor = opts.promptAuditor;
61968
- } else if (auditEnabled) {
61969
- if (!opts?.featureName) {
61970
- throw new NaxError("createRuntime: featureName is required when promptAudit.enabled is true", "AUDIT_FEATURE_NAME_REQUIRED", { stage: "runtime" });
61971
- }
62185
+ } else if (auditEnabled && opts?.featureName) {
61972
62186
  promptAuditor = new PromptAuditor(runId, auditDir, opts.featureName);
61973
62187
  } else {
61974
62188
  promptAuditor = createNoOpPromptAuditor();
@@ -62103,7 +62317,6 @@ var init_runtime2 = __esm(() => {
62103
62317
  init_factory();
62104
62318
  init_manager();
62105
62319
  init_config();
62106
- init_errors();
62107
62320
  init_pid_registry();
62108
62321
  init_findings();
62109
62322
  init_logger2();
@@ -76881,7 +77094,7 @@ var init_escalation = __esm(() => {
76881
77094
  });
76882
77095
 
76883
77096
  // src/execution/lock.ts
76884
- import { rename as rename4, unlink as unlink4 } from "fs/promises";
77097
+ import { rename as rename5, unlink as unlink4 } from "fs/promises";
76885
77098
  import path22 from "path";
76886
77099
  function getSafeLogger5() {
76887
77100
  try {
@@ -76998,7 +77211,7 @@ var _lockDeps;
76998
77211
  var init_lock = __esm(() => {
76999
77212
  init_logger2();
77000
77213
  _lockDeps = {
77001
- rename: rename4
77214
+ rename: rename5
77002
77215
  };
77003
77216
  });
77004
77217
 
@@ -80527,7 +80740,7 @@ var init_plugins2 = __esm(() => {
80527
80740
  });
80528
80741
 
80529
80742
  // src/execution/status-file.ts
80530
- import { rename as rename5, unlink as unlink5 } from "fs/promises";
80743
+ import { rename as rename6, unlink as unlink5 } from "fs/promises";
80531
80744
  import { resolve as resolve19 } from "path";
80532
80745
  function countProgress(prd) {
80533
80746
  const stories = prd.userStories;
@@ -80582,7 +80795,7 @@ async function writeStatusFile(filePath, status) {
80582
80795
  await unlink5(tmpPath);
80583
80796
  } catch {}
80584
80797
  await Bun.write(tmpPath, JSON.stringify(status, null, 2));
80585
- await rename5(tmpPath, resolvedPath);
80798
+ await rename6(tmpPath, resolvedPath);
80586
80799
  }
80587
80800
  var init_status_file = () => {};
80588
80801
 
@@ -80882,7 +81095,7 @@ var init_common = __esm(() => {
80882
81095
  });
80883
81096
 
80884
81097
  // src/plugins/builtin/curator/rollup-prune.ts
80885
- import { appendFile as appendFile5, rename as rename6, unlink as unlink6, writeFile as writeFile7 } from "fs/promises";
81098
+ import { appendFile as appendFile5, rename as rename7, unlink as unlink6, writeFile as writeFile7 } from "fs/promises";
80886
81099
  async function scanProjectRunIds(rollupPath, projectKey) {
80887
81100
  const maxTsByRunId = new Map;
80888
81101
  for await (const line of streamJsonlLines(Bun.file(rollupPath))) {
@@ -80954,7 +81167,7 @@ async function pruneRollupUnlocked(input) {
80954
81167
  await flush();
80955
81168
  }
80956
81169
  await flush();
80957
- await rename6(tmpPath, rollupPath);
81170
+ await rename7(tmpPath, rollupPath);
80958
81171
  } catch (err) {
80959
81172
  await unlink6(tmpPath).catch(() => {});
80960
81173
  throw err;
@@ -81691,7 +81904,7 @@ __export(exports_migrate, {
81691
81904
  migrateCommand: () => migrateCommand
81692
81905
  });
81693
81906
  import { existsSync as existsSync33 } from "fs";
81694
- import { mkdir as mkdir18, readdir as readdir7, rename as rename7 } from "fs/promises";
81907
+ import { mkdir as mkdir18, readdir as readdir7, rename as rename8 } from "fs/promises";
81695
81908
  import path25 from "path";
81696
81909
  async function detectGeneratedContent(naxDir) {
81697
81910
  if (!existsSync33(naxDir))
@@ -81780,7 +81993,7 @@ async function migrateCommand(options) {
81780
81993
  const archiveBase = path25.join(globalConfigDir(), "_archive");
81781
81994
  const archiveDest = path25.join(archiveBase, `${options.reclaim}-${Date.now()}`);
81782
81995
  await mkdir18(archiveBase, { recursive: true });
81783
- await rename7(src, archiveDest);
81996
+ await rename8(src, archiveDest);
81784
81997
  logger.info("migrate", `Reclaimed: archived to ${archiveDest}`, { storyId: "_migrate" });
81785
81998
  return;
81786
81999
  }
@@ -81859,7 +82072,7 @@ async function migrateCommand(options) {
81859
82072
  Remove the destination or run nax migrate --dry-run to inspect.`, "MIGRATE_CONFLICT", { stage: "migrate", src: candidate.srcPath, dest });
81860
82073
  }
81861
82074
  try {
81862
- await rename7(candidate.srcPath, dest);
82075
+ await rename8(candidate.srcPath, dest);
81863
82076
  } catch (err) {
81864
82077
  const isXdev = err instanceof Error && "code" in err && err.code === "EXDEV";
81865
82078
  if (isXdev) {
@@ -84941,7 +85154,7 @@ var init_queue_file_lock = __esm(() => {
84941
85154
  });
84942
85155
 
84943
85156
  // src/execution/queue-handler.ts
84944
- import { rename as rename8, unlink as unlink9 } from "fs/promises";
85157
+ import { rename as rename9, unlink as unlink9 } from "fs/promises";
84945
85158
  import path28 from "path";
84946
85159
  function getSafeLogger7() {
84947
85160
  try {
@@ -84961,7 +85174,7 @@ async function claimCommandsLocked(queuePath, processingPath, logger) {
84961
85174
  return null;
84962
85175
  }
84963
85176
  try {
84964
- await rename8(queuePath, processingPath);
85177
+ await rename9(queuePath, processingPath);
84965
85178
  } catch (error48) {
84966
85179
  logger?.warn("queue", "Failed to rename queue file for processing", {
84967
85180
  error: error48.message
@@ -90803,7 +91016,7 @@ async function promptsCommand(options) {
90803
91016
  throw new Error(`Feature "${feature}" not found or missing prd.json`);
90804
91017
  }
90805
91018
  const prd = await loadPRD(prdPath);
90806
- const runtime = _promptsMainDeps.createRuntime(config2, workdir);
91019
+ const runtime = _promptsMainDeps.createRuntime(config2, workdir, { featureName: feature });
90807
91020
  try {
90808
91021
  const stories = storyId ? prd.userStories.filter((s) => s.id === storyId) : prd.userStories;
90809
91022
  if (stories.length === 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nathapp/nax",
3
- "version": "0.82.0-canary.1",
3
+ "version": "0.82.0-canary.2",
4
4
  "description": "AI Coding Agent Orchestrator — loops until done",
5
5
  "type": "module",
6
6
  "bin": {
@@ -68,7 +68,7 @@
68
68
  "spec:lint": "bun run scripts/spec-lint.ts"
69
69
  },
70
70
  "dependencies": {
71
- "@nathapp/nax-ai": "0.1.7",
71
+ "@nathapp/nax-ai": "0.1.8",
72
72
  "@types/react": "^19.2.14",
73
73
  "chalk": "^5.6.2",
74
74
  "commander": "^13.1.0",