agentxchain 2.155.68 → 2.155.70

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentxchain",
3
- "version": "2.155.68",
3
+ "version": "2.155.70",
4
4
  "description": "CLI for AgentXchain — governed multi-agent software delivery",
5
5
  "type": "module",
6
6
  "bin": {
@@ -12,7 +12,8 @@ const CLAUDE_ENV_AUTH_KEYS = [
12
12
  const DEFAULT_SMOKE_PROBE_TIMEOUT_MS = 10_000;
13
13
  const DEFAULT_SMOKE_PROBE_STDIN = 'ok';
14
14
  const CLAUDE_AUTH_FAILURE_RE = /authentication_failed|authentication_error|invalid authentication credentials|unauthorized|API Error:\s*401/i;
15
- const CLAUDE_NODE_INCOMPATIBILITY_RE = /TypeError:\s*Object not disposable|Object not disposable[\s\S]{0,2000}Node\.js v(?:1[0-9]|20\.[0-4]\.)/i;
15
+ const CLAUDE_NODE_INCOMPATIBILITY_RE =
16
+ /TypeError:\s*Object not disposable|TypeError\(["']Object not disposable["']\)|Object not disposable[\s\S]{0,2000}Node\.js v(?:1[0-9]|20\.[0-4]\.)/i;
16
17
  const CLAUDE_COMPATIBLE_NODE_MIN = { major: 20, minor: 5, patch: 0 };
17
18
 
18
19
  function normalizeCommandTokens(runtime) {
@@ -54,6 +54,7 @@ import {
54
54
  } from './intent-startup-migration.js';
55
55
  import { checkpointAcceptedTurn } from './turn-checkpoint.js';
56
56
  import {
57
+ hasClaudeEnvAuth,
57
58
  hasClaudeAuthenticationFailureText,
58
59
  hasClaudeNodeIncompatibilityText,
59
60
  isClaudeLocalCliRuntime,
@@ -497,6 +498,78 @@ function reclassifyRetainedClaudeNodeIncompatGhost(context, session, state, cand
497
498
  return nextState;
498
499
  }
499
500
 
501
+ function findRetainedClaudeAuthDispatchBlocker(root, state, config) {
502
+ if (!state || state.status !== 'blocked') return null;
503
+ if (state.blocked_on !== 'dispatch:claude_auth_failed') return null;
504
+ if (state.blocked_reason?.category !== 'dispatch_error') return null;
505
+ const activeTurns = state.active_turns || {};
506
+ const turnId = state.blocked_reason?.turn_id || null;
507
+ const candidateIds = turnId && activeTurns[turnId] ? [turnId] : Object.keys(activeTurns);
508
+ for (const candidateId of candidateIds) {
509
+ const turn = activeTurns[candidateId];
510
+ if (!turn) continue;
511
+ const runtime = config?.runtimes?.[turn.runtime_id];
512
+ if (!isClaudeLocalCliRuntime(runtime)) continue;
513
+ const logPath = join(root, getDispatchLogPath(candidateId));
514
+ if (!existsSync(logPath)) continue;
515
+ let logText = '';
516
+ try {
517
+ logText = readFileSync(logPath, 'utf8');
518
+ } catch {
519
+ continue;
520
+ }
521
+ if (!hasClaudeAuthenticationFailureText(logText)) continue;
522
+ return { turn_id: candidateId, turn, previous_blocked_on: state.blocked_on || null };
523
+ }
524
+ return null;
525
+ }
526
+
527
+ function maybeAutoRetryRetainedClaudeAuthDispatch(context, session, state, log = console.log) {
528
+ const { root, config } = context;
529
+ if (!hasClaudeEnvAuth(process.env)) return null;
530
+ const candidate = findRetainedClaudeAuthDispatchBlocker(root, state, config);
531
+ if (!candidate) return null;
532
+
533
+ const reissued = reissueTurn(root, config, {
534
+ turnId: candidate.turn_id,
535
+ reason: 'auto_retry_claude_auth_refreshed',
536
+ });
537
+ if (!reissued.ok) {
538
+ log(`Claude auth auto-retry skipped: ${reissued.error}`);
539
+ return null;
540
+ }
541
+
542
+ const runId = session.current_run_id || state.run_id || reissued.state?.run_id || null;
543
+ const nextState = clearGhostBlockerAfterReissue(root, reissued.state);
544
+ Object.assign(session, {
545
+ status: 'running',
546
+ current_run_id: runId,
547
+ });
548
+ writeContinuousSession(root, session);
549
+ emitRunEvent(root, 'auto_retried_ghost', {
550
+ run_id: runId,
551
+ phase: nextState.phase || state.phase || null,
552
+ status: 'active',
553
+ turn: { turn_id: reissued.newTurn.turn_id, role_id: reissued.newTurn.assigned_role || null },
554
+ payload: {
555
+ old_turn_id: candidate.turn_id,
556
+ new_turn_id: reissued.newTurn.turn_id,
557
+ failure_type: 'claude_auth_failed',
558
+ recovery_class: 'claude_auth_refreshed',
559
+ runtime_id: candidate.turn.runtime_id || null,
560
+ },
561
+ });
562
+ log(`Claude auth refreshed; auto-retried ${candidate.turn_id} -> ${reissued.newTurn.turn_id}.`);
563
+ return {
564
+ ok: true,
565
+ status: 'running',
566
+ action: 'auto_retried_claude_auth_refreshed',
567
+ run_id: runId,
568
+ old_turn_id: candidate.turn_id,
569
+ new_turn_id: reissued.newTurn.turn_id,
570
+ };
571
+ }
572
+
500
573
  const RECOVERABLE_ACTIVE_TURN_STATUSES = new Set(['assigned', 'dispatched', 'starting', 'running']);
501
574
 
502
575
  function hasOnlyRecoverableActiveTurns(activeTurns = {}) {
@@ -1913,6 +1986,8 @@ export async function advanceContinuousRunOnce(context, session, contOpts, execu
1913
1986
  if (startupGovernedState?.status === 'blocked') {
1914
1987
  const reclassifiedState = maybeReclassifyRetainedClaudeAuthEscalation(context, session, startupGovernedState, log);
1915
1988
  let effectiveBlockedState = reclassifiedState || startupGovernedState;
1989
+ const authRetry = maybeAutoRetryRetainedClaudeAuthDispatch(context, session, effectiveBlockedState, log);
1990
+ if (authRetry?.status === 'running') return authRetry;
1916
1991
  const nodeCandidate = findRetainedClaudeNodeIncompatGhost(root, effectiveBlockedState, context.config);
1917
1992
  if (nodeCandidate) {
1918
1993
  const nodeRecovery = reclassifyRetainedClaudeNodeIncompatGhost(