@librechat/agents 3.7.6 → 3.7.7
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/cjs/eventActor/EventActorExecutor.cjs +305 -11
- package/dist/cjs/eventActor/EventActorExecutor.cjs.map +1 -1
- package/dist/esm/eventActor/EventActorExecutor.mjs +305 -11
- package/dist/esm/eventActor/EventActorExecutor.mjs.map +1 -1
- package/dist/types/eventActor/EventActorExecutor.d.ts +3 -1
- package/dist/types/eventActor/index.d.ts +1 -1
- package/dist/types/eventActor/types.d.ts +149 -5
- package/package.json +1 -1
- package/src/eventActor/EventActorExecutor.ts +545 -16
- package/src/eventActor/index.ts +17 -0
- package/src/eventActor/types.ts +182 -3
|
@@ -62,12 +62,129 @@ export type EventActorTerminalResult<TResult extends EventActorEvent> = {
|
|
|
62
62
|
status: 'completed_no_action';
|
|
63
63
|
result?: TResult;
|
|
64
64
|
};
|
|
65
|
+
/** JSON-safe interrupt descriptor retained with a suspended invocation fork. */
|
|
66
|
+
export interface EventActorInterrupt<TPayload extends EventActorEvent = EventActorEvent> {
|
|
67
|
+
id: string;
|
|
68
|
+
payload: TPayload;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Nonterminal adapter outcome. The checkpoint must already contain the pause;
|
|
72
|
+
* the SDK publishes its authority through `suspend` before exposing it.
|
|
73
|
+
*/
|
|
74
|
+
export interface EventActorAdapterSuspendedResult<TPayload extends EventActorEvent = EventActorEvent> {
|
|
75
|
+
status: 'suspended';
|
|
76
|
+
checkpoint: EventActorCheckpointFork;
|
|
77
|
+
interrupt: EventActorInterrupt<TPayload>;
|
|
78
|
+
}
|
|
79
|
+
export type EventActorAdapterInvocationResult<TResult extends EventActorEvent, TPayload extends EventActorEvent = EventActorEvent> = EventActorTerminalResult<TResult> | EventActorAdapterSuspendedResult<TPayload>;
|
|
80
|
+
/**
|
|
81
|
+
* Authenticated, versioned, JSON-safe evidence for one nonterminal invocation.
|
|
82
|
+
* Integrity does not make this evidence one-shot; the host's durable current
|
|
83
|
+
* suspension record is the replay and ownership fence. Hosts must capability-
|
|
84
|
+
* route each exact version during rolling deploys and drain or migrate current
|
|
85
|
+
* evidence before rotating away from its signing key.
|
|
86
|
+
*/
|
|
87
|
+
export interface EventActorSuspension<TPayload extends EventActorEvent = EventActorEvent> {
|
|
88
|
+
version: 1;
|
|
89
|
+
suspensionId: string;
|
|
90
|
+
attempt: number;
|
|
91
|
+
issuedAt: number;
|
|
92
|
+
expiresAt: number;
|
|
93
|
+
invocation: EventActorInvocationReference;
|
|
94
|
+
checkpoint: EventActorCheckpointFork;
|
|
95
|
+
interrupt: EventActorInterrupt<TPayload>;
|
|
96
|
+
suspensionDigest: string;
|
|
97
|
+
}
|
|
98
|
+
export interface EventActorSuspendedResult<TPayload extends EventActorEvent = EventActorEvent> {
|
|
99
|
+
status: 'suspended';
|
|
100
|
+
suspension: EventActorSuspension<TPayload>;
|
|
101
|
+
}
|
|
102
|
+
export interface EventActorSuspendRequest {
|
|
103
|
+
suspension: EventActorSuspension;
|
|
104
|
+
/** CAS predecessor required when a claimed resume pauses again. */
|
|
105
|
+
previous?: {
|
|
106
|
+
suspensionId: string;
|
|
107
|
+
attempt: number;
|
|
108
|
+
resumeAttemptId: string;
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
export type EventActorSuspendResult = {
|
|
112
|
+
status: 'stored';
|
|
113
|
+
} | {
|
|
114
|
+
status: 'stale';
|
|
115
|
+
};
|
|
116
|
+
export interface EventActorAdapterResumeRequest {
|
|
117
|
+
suspension: EventActorSuspension;
|
|
118
|
+
resumeAttemptId: string;
|
|
119
|
+
value: EventActorEvent;
|
|
120
|
+
}
|
|
121
|
+
export type EventActorAdapterResumeResult<TResult extends EventActorEvent> = {
|
|
122
|
+
status: 'claimed';
|
|
123
|
+
result: EventActorAdapterInvocationResult<TResult>;
|
|
124
|
+
} | {
|
|
125
|
+
/** The host proved no action before returning this claimed failure. */
|
|
126
|
+
status: 'claimed_failed';
|
|
127
|
+
error: Error;
|
|
128
|
+
} | {
|
|
129
|
+
status: 'stale';
|
|
130
|
+
};
|
|
131
|
+
export interface EventActorResumeRequest {
|
|
132
|
+
suspension: EventActorSuspension;
|
|
133
|
+
resumeAttemptId: string;
|
|
134
|
+
value: EventActorEvent;
|
|
135
|
+
signal?: AbortSignal;
|
|
136
|
+
}
|
|
137
|
+
export interface EventActorCancelSuspensionRequest {
|
|
138
|
+
suspension: EventActorSuspension;
|
|
139
|
+
cancelAttemptId: string;
|
|
140
|
+
reason?: 'cancelled' | 'expired';
|
|
141
|
+
signal?: AbortSignal;
|
|
142
|
+
}
|
|
143
|
+
export interface EventActorAdapterCancelSuspensionRequest {
|
|
144
|
+
suspension: EventActorSuspension;
|
|
145
|
+
cancelAttemptId: string;
|
|
146
|
+
reason: 'cancelled' | 'expired';
|
|
147
|
+
}
|
|
148
|
+
export type EventActorCancelSuspensionResult = {
|
|
149
|
+
status: 'cancelled';
|
|
150
|
+
} | EventActorIndeterminateResult<EventActorEvent>;
|
|
151
|
+
export type EventActorAdapterCancelSuspensionResult = {
|
|
152
|
+
status: 'cancelled';
|
|
153
|
+
} | {
|
|
154
|
+
status: 'stale';
|
|
155
|
+
};
|
|
156
|
+
export interface EventActorSettleSuspensionRequest {
|
|
157
|
+
suspensionId: string;
|
|
158
|
+
attempt: number;
|
|
159
|
+
resumeAttemptId: string;
|
|
160
|
+
status: 'completed_no_action' | 'failed';
|
|
161
|
+
}
|
|
162
|
+
export type EventActorSettleSuspensionResult = {
|
|
163
|
+
status: 'settled';
|
|
164
|
+
} | {
|
|
165
|
+
status: 'stale';
|
|
166
|
+
};
|
|
65
167
|
export type EventActorAppliedResult<TResult extends EventActorEvent> = Extract<EventActorTerminalResult<TResult>, {
|
|
66
168
|
status: 'applied';
|
|
67
169
|
}> & {
|
|
68
|
-
/** Executor-issued
|
|
170
|
+
/** Executor-issued settlement for the invocation that produced this action. */
|
|
69
171
|
invocation: EventActorInvocationReference;
|
|
172
|
+
/** Authenticated cross-executor authority for a resumed terminal action. */
|
|
173
|
+
settlementAuthority?: EventActorSettlementAuthority;
|
|
70
174
|
};
|
|
175
|
+
/**
|
|
176
|
+
* Authenticated fence that binds a resumed terminal result to its claimed
|
|
177
|
+
* suspension. The host must consume it atomically with the actor-head CAS.
|
|
178
|
+
*/
|
|
179
|
+
export interface EventActorSettlementAuthority {
|
|
180
|
+
version: 1;
|
|
181
|
+
suspensionId: string;
|
|
182
|
+
attempt: number;
|
|
183
|
+
resumeAttemptId: string;
|
|
184
|
+
issuedAt: number;
|
|
185
|
+
expiresAt: number;
|
|
186
|
+
settlementDigest: string;
|
|
187
|
+
}
|
|
71
188
|
export interface EventActorIndeterminateResult<TResult extends EventActorEvent> {
|
|
72
189
|
/** Applied handling cannot be proven safe to retry; retain its fork. */
|
|
73
190
|
status: 'commit_indeterminate';
|
|
@@ -75,7 +192,7 @@ export interface EventActorIndeterminateResult<TResult extends EventActorEvent>
|
|
|
75
192
|
checkpoint: EventActorCheckpointFork;
|
|
76
193
|
error: Error;
|
|
77
194
|
}
|
|
78
|
-
export type EventActorInvocationResult<TResult extends EventActorEvent> = EventActorAppliedResult<TResult> | EventActorIndeterminateResult<TResult> | Extract<EventActorTerminalResult<TResult>, {
|
|
195
|
+
export type EventActorInvocationResult<TResult extends EventActorEvent> = EventActorAppliedResult<TResult> | EventActorIndeterminateResult<TResult> | EventActorSuspendedResult | Extract<EventActorTerminalResult<TResult>, {
|
|
79
196
|
status: 'completed_no_action';
|
|
80
197
|
}>;
|
|
81
198
|
export interface EventActorInvocationContext {
|
|
@@ -101,6 +218,8 @@ export interface EventActorCommitRequest<TResult extends EventActorEvent> {
|
|
|
101
218
|
expectedHead: EventActorHead;
|
|
102
219
|
checkpoint: EventActorCheckpointFork;
|
|
103
220
|
result: TResult;
|
|
221
|
+
/** Host must consume this suspension fence atomically with the head CAS. */
|
|
222
|
+
settlementAuthority?: EventActorSettlementAuthority;
|
|
104
223
|
retention: {
|
|
105
224
|
committedCheckpoints: 2;
|
|
106
225
|
dormantCheckpointTtlMs: number;
|
|
@@ -123,7 +242,11 @@ export interface EventActorDiscardRequest {
|
|
|
123
242
|
/**
|
|
124
243
|
* Host adapter for durable actor state and the concrete agent invocation.
|
|
125
244
|
* `commit` must compare both the expected generation and checkpoint identity
|
|
126
|
-
* atomically before advancing the logical actor head.
|
|
245
|
+
* atomically before advancing the logical actor head. When settlement authority
|
|
246
|
+
* is present, that same transaction must also verify and close the exact
|
|
247
|
+
* suspension/resume-attempt fence, including stale-head outcomes. Retrying an
|
|
248
|
+
* ambiguous acknowledgement must return the durable outcome rather than apply
|
|
249
|
+
* the same terminal transition again. The host mailbox
|
|
127
250
|
* deduplicates the logical `invocationId` before entering this seam, while each
|
|
128
251
|
* SDK execution attempt receives a distinct checkpoint namespace. Preparation
|
|
129
252
|
* methods own rollback until they return a ready invocation and must treat the
|
|
@@ -137,11 +260,28 @@ export interface EventActorDiscardRequest {
|
|
|
137
260
|
* fork: the SDK retains and surfaces it as `commit_conflict` for host
|
|
138
261
|
* reconciliation. `discard` must be idempotent for the same invocation because
|
|
139
262
|
* an ambiguous cleanup failure can be retried through the public lifecycle.
|
|
263
|
+
*
|
|
264
|
+
* Suspension-capable hosts implement all optional suspension methods. `suspend`
|
|
265
|
+
* publishes an initial suspension only while its logical invocation is current;
|
|
266
|
+
* with `previous`, it atomically replaces only the exact claimed predecessor.
|
|
267
|
+
* `resume` atomically claims the current suspension before applying its value to
|
|
268
|
+
* the declared interrupt and rejects duplicate or competing claims as `stale`.
|
|
269
|
+
* It must return `claimed_failed` only when it can prove no qualifying action;
|
|
270
|
+
* any failure after an action returns `applied`. `settleSuspension` atomically
|
|
271
|
+
* discards the claimed fork and closes its fence for definite no-action
|
|
272
|
+
* outcomes. `cancelSuspension`
|
|
273
|
+
* atomically claims, discards, and closes current state, including expired
|
|
274
|
+
* evidence; expiration alone never implies a safe action outcome.
|
|
140
275
|
*/
|
|
141
276
|
export interface EventActorHostAdapter<TEvent extends EventActorEvent, TResult extends EventActorEvent> {
|
|
142
277
|
prepare(request: EventActorAdapterPrepareRequest<TEvent>, context: EventActorPreparationContext): Promise<EventActorAdapterPreparation<TEvent>>;
|
|
143
278
|
coldContinue(request: EventActorAdapterPrepareRequest<TEvent>, head: EventActorHead, context: EventActorPreparationContext): Promise<EventActorInvocation<TEvent>>;
|
|
144
|
-
invoke(invocation: EventActorInvocation<TEvent>, context: EventActorInvocationContext): Promise<
|
|
279
|
+
invoke(invocation: EventActorInvocation<TEvent>, context: EventActorInvocationContext): Promise<EventActorAdapterInvocationResult<TResult>>;
|
|
280
|
+
suspend?(request: EventActorSuspendRequest): Promise<EventActorSuspendResult>;
|
|
281
|
+
resume?(request: EventActorAdapterResumeRequest, context: EventActorInvocationContext): Promise<EventActorAdapterResumeResult<TResult>>;
|
|
282
|
+
/** Atomically claims, discards, and closes the current suspension. */
|
|
283
|
+
cancelSuspension?(request: EventActorAdapterCancelSuspensionRequest, context: EventActorPreparationContext): Promise<EventActorAdapterCancelSuspensionResult>;
|
|
284
|
+
settleSuspension?(request: EventActorSettleSuspensionRequest): Promise<EventActorSettleSuspensionResult>;
|
|
145
285
|
commit(request: EventActorCommitRequest<TResult>): Promise<EventActorCommitResult>;
|
|
146
286
|
discard(request: EventActorDiscardRequest): Promise<void>;
|
|
147
287
|
}
|
|
@@ -165,7 +305,9 @@ export type EventActorExecutionResult<TResult extends EventActorEvent> = {
|
|
|
165
305
|
} | {
|
|
166
306
|
status: 'cancelled';
|
|
167
307
|
continuation: 'warm' | 'cold';
|
|
168
|
-
} | {
|
|
308
|
+
} | (EventActorSuspendedResult & {
|
|
309
|
+
continuation: 'warm' | 'cold';
|
|
310
|
+
}) | {
|
|
169
311
|
/** The action happened, but another head won the CAS. Reconcile; do not retry. */
|
|
170
312
|
status: 'commit_conflict';
|
|
171
313
|
result: TResult;
|
|
@@ -190,4 +332,6 @@ export interface EventActorExecutorOptions {
|
|
|
190
332
|
dormantCheckpointTtlMs?: number;
|
|
191
333
|
/** Stable private key of at least 32 bytes for cross-lifetime handoffs. */
|
|
192
334
|
preparationSigningKey?: string | Uint8Array;
|
|
335
|
+
/** Maximum UTF-8 byte size of canonical suspension evidence. */
|
|
336
|
+
maxSuspensionPayloadBytes?: number;
|
|
193
337
|
}
|