agentxchain 2.67.0 → 2.69.0
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/commands/events.js +11 -1
- package/src/lib/governed-state.js +59 -3
- package/src/lib/run-events.js +1 -0
package/package.json
CHANGED
package/src/commands/events.js
CHANGED
|
@@ -61,7 +61,16 @@ function printEvent(evt) {
|
|
|
61
61
|
const runId = evt.run_id ? evt.run_id.slice(0, 12) : '—';
|
|
62
62
|
const phase = evt.phase || '—';
|
|
63
63
|
const turnInfo = evt.turn?.role_id ? ` [${evt.turn.role_id}]` : '';
|
|
64
|
-
|
|
64
|
+
const rejectionDetail = evt.event_type === 'turn_rejected' && evt.payload?.reason
|
|
65
|
+
? ` — ${evt.payload.reason}${evt.payload.failed_stage ? ` (${evt.payload.failed_stage})` : ''}`
|
|
66
|
+
: '';
|
|
67
|
+
const phaseTransitionDetail = evt.event_type === 'phase_entered' && evt.payload?.from && evt.payload?.to
|
|
68
|
+
? ` ${evt.payload.from} → ${evt.payload.to}${evt.payload.trigger ? ` (${evt.payload.trigger})` : ''}`
|
|
69
|
+
: '';
|
|
70
|
+
const gateFailedDetail = evt.event_type === 'gate_failed' && evt.payload?.from_phase
|
|
71
|
+
? ` ${evt.payload.from_phase} → ${evt.payload.to_phase || '?'}${evt.payload.reasons?.length ? ` — ${evt.payload.reasons[0]}` : ''}${evt.payload.gate_id ? ` (${evt.payload.gate_id})` : ''}`
|
|
72
|
+
: '';
|
|
73
|
+
console.log(`${chalk.dim(ts)} ${type} ${chalk.cyan(runId)} ${phase}${turnInfo}${rejectionDetail}${phaseTransitionDetail}${gateFailedDetail}`);
|
|
65
74
|
}
|
|
66
75
|
|
|
67
76
|
function colorEventType(type) {
|
|
@@ -77,6 +86,7 @@ function colorEventType(type) {
|
|
|
77
86
|
escalation_resolved: chalk.green,
|
|
78
87
|
gate_pending: chalk.yellow,
|
|
79
88
|
gate_approved: chalk.green,
|
|
89
|
+
gate_failed: chalk.red,
|
|
80
90
|
};
|
|
81
91
|
const colorFn = colors[type] || chalk.white;
|
|
82
92
|
return colorFn(pad(type, 22));
|
|
@@ -2853,6 +2853,7 @@ function _acceptGovernedTurnLocked(root, config, opts) {
|
|
|
2853
2853
|
});
|
|
2854
2854
|
|
|
2855
2855
|
if (gateResult.action === 'advance') {
|
|
2856
|
+
const prevPhase = updatedState.phase;
|
|
2856
2857
|
updatedState.phase = gateResult.next_phase;
|
|
2857
2858
|
updatedState.phase_entered_at = now;
|
|
2858
2859
|
updatedState.last_gate_failure = null;
|
|
@@ -2861,6 +2862,18 @@ function _acceptGovernedTurnLocked(root, config, opts) {
|
|
|
2861
2862
|
[gateResult.gate_id || 'no_gate']: 'passed',
|
|
2862
2863
|
};
|
|
2863
2864
|
updatedState.queued_phase_transition = null;
|
|
2865
|
+
emitRunEvent(root, 'phase_entered', {
|
|
2866
|
+
run_id: updatedState.run_id,
|
|
2867
|
+
phase: updatedState.phase,
|
|
2868
|
+
status: updatedState.status,
|
|
2869
|
+
turn: { turn_id: currentTurn.turn_id, role_id: currentTurn.assigned_role },
|
|
2870
|
+
payload: {
|
|
2871
|
+
from: prevPhase,
|
|
2872
|
+
to: gateResult.next_phase,
|
|
2873
|
+
gate_id: gateResult.gate_id || 'no_gate',
|
|
2874
|
+
trigger: 'auto',
|
|
2875
|
+
},
|
|
2876
|
+
});
|
|
2864
2877
|
} else if (gateResult.action === 'awaiting_human_approval') {
|
|
2865
2878
|
// Evaluate approval policy — may auto-approve
|
|
2866
2879
|
const approvalResult = evaluateApprovalPolicy({
|
|
@@ -2871,6 +2884,7 @@ function _acceptGovernedTurnLocked(root, config, opts) {
|
|
|
2871
2884
|
});
|
|
2872
2885
|
|
|
2873
2886
|
if (approvalResult.action === 'auto_approve') {
|
|
2887
|
+
const prevPhase = updatedState.phase;
|
|
2874
2888
|
updatedState.phase = gateResult.next_phase;
|
|
2875
2889
|
updatedState.phase_entered_at = now;
|
|
2876
2890
|
updatedState.last_gate_failure = null;
|
|
@@ -2890,6 +2904,18 @@ function _acceptGovernedTurnLocked(root, config, opts) {
|
|
|
2890
2904
|
gate_id: gateResult.gate_id,
|
|
2891
2905
|
timestamp: now,
|
|
2892
2906
|
});
|
|
2907
|
+
emitRunEvent(root, 'phase_entered', {
|
|
2908
|
+
run_id: updatedState.run_id,
|
|
2909
|
+
phase: updatedState.phase,
|
|
2910
|
+
status: updatedState.status,
|
|
2911
|
+
turn: { turn_id: currentTurn.turn_id, role_id: currentTurn.assigned_role },
|
|
2912
|
+
payload: {
|
|
2913
|
+
from: prevPhase,
|
|
2914
|
+
to: gateResult.next_phase,
|
|
2915
|
+
gate_id: gateResult.gate_id || 'no_gate',
|
|
2916
|
+
trigger: 'auto_approved',
|
|
2917
|
+
},
|
|
2918
|
+
});
|
|
2893
2919
|
} else {
|
|
2894
2920
|
updatedState.status = 'paused';
|
|
2895
2921
|
updatedState.blocked_on = `human_approval:${gateResult.gate_id}`;
|
|
@@ -2926,6 +2952,18 @@ function _acceptGovernedTurnLocked(root, config, opts) {
|
|
|
2926
2952
|
type: 'gate_failure',
|
|
2927
2953
|
...gateFailure,
|
|
2928
2954
|
});
|
|
2955
|
+
emitRunEvent(root, 'gate_failed', {
|
|
2956
|
+
run_id: updatedState.run_id,
|
|
2957
|
+
phase: updatedState.phase,
|
|
2958
|
+
status: updatedState.status,
|
|
2959
|
+
turn: { turn_id: currentTurn.turn_id, role_id: currentTurn.assigned_role },
|
|
2960
|
+
payload: {
|
|
2961
|
+
gate_id: gateResult.gate_id || 'no_gate',
|
|
2962
|
+
from_phase: state.phase,
|
|
2963
|
+
to_phase: gateResult.transition_request || state.queued_phase_transition?.to || null,
|
|
2964
|
+
reasons: gateFailure.reasons || [],
|
|
2965
|
+
},
|
|
2966
|
+
});
|
|
2929
2967
|
} else if (state.queued_phase_transition) {
|
|
2930
2968
|
updatedState.queued_phase_transition = null;
|
|
2931
2969
|
}
|
|
@@ -3331,7 +3369,13 @@ export function rejectGovernedTurn(root, config, validationResult, reasonOrOptio
|
|
|
3331
3369
|
phase: updatedState.phase,
|
|
3332
3370
|
status: updatedState.status,
|
|
3333
3371
|
turn: { turn_id: currentTurn.turn_id, role_id: currentTurn.assigned_role },
|
|
3334
|
-
payload: {
|
|
3372
|
+
payload: {
|
|
3373
|
+
attempt: currentAttempt,
|
|
3374
|
+
retrying: true,
|
|
3375
|
+
reason: rejectionContext.reason,
|
|
3376
|
+
failed_stage: rejectionContext.failed_stage,
|
|
3377
|
+
...(rejectionContext.validation_errors?.length ? { validation_errors: rejectionContext.validation_errors } : {}),
|
|
3378
|
+
},
|
|
3335
3379
|
});
|
|
3336
3380
|
return {
|
|
3337
3381
|
ok: true,
|
|
@@ -3398,7 +3442,14 @@ export function rejectGovernedTurn(root, config, validationResult, reasonOrOptio
|
|
|
3398
3442
|
phase: updatedState.phase,
|
|
3399
3443
|
status: 'blocked',
|
|
3400
3444
|
turn: { turn_id: currentTurn.turn_id, role_id: currentTurn.assigned_role },
|
|
3401
|
-
payload: {
|
|
3445
|
+
payload: {
|
|
3446
|
+
attempt: currentAttempt,
|
|
3447
|
+
retrying: false,
|
|
3448
|
+
escalated: true,
|
|
3449
|
+
reason: rejectionContext.reason,
|
|
3450
|
+
failed_stage: rejectionContext.failed_stage,
|
|
3451
|
+
...(rejectionContext.validation_errors?.length ? { validation_errors: rejectionContext.validation_errors } : {}),
|
|
3452
|
+
},
|
|
3402
3453
|
});
|
|
3403
3454
|
emitRunEvent(root, 'run_blocked', {
|
|
3404
3455
|
run_id: updatedState.run_id,
|
|
@@ -3527,7 +3578,12 @@ export function approvePhaseTransition(root, config) {
|
|
|
3527
3578
|
run_id: updatedState.run_id,
|
|
3528
3579
|
phase: updatedState.phase,
|
|
3529
3580
|
status: 'active',
|
|
3530
|
-
payload: {
|
|
3581
|
+
payload: {
|
|
3582
|
+
from: transition.from,
|
|
3583
|
+
to: transition.to,
|
|
3584
|
+
gate_id: transition.gate || 'no_gate',
|
|
3585
|
+
trigger: 'human_approved',
|
|
3586
|
+
},
|
|
3531
3587
|
});
|
|
3532
3588
|
|
|
3533
3589
|
// Session checkpoint — non-fatal
|