agentxchain 2.155.69 → 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 +1 -1
- package/src/lib/continuous-run.js +75 -0
package/package.json
CHANGED
|
@@ -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(
|