eve 0.29.5 → 0.30.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/CHANGELOG.md +15 -0
- package/dist/src/cli/dev/tui/message-queue.d.ts +7 -7
- package/dist/src/cli/dev/tui/message-queue.js +1 -1
- package/dist/src/cli/dev/tui/prompt-commands.d.ts +4 -4
- package/dist/src/cli/dev/tui/prompt-commands.js +1 -1
- package/dist/src/cli/dev/tui/runner.d.ts +1 -1
- package/dist/src/cli/dev/tui/setup-panel.js +4 -1
- package/dist/src/cli/dev/tui/subagent-pump.d.ts +2 -2
- package/dist/src/cli/dev/tui/terminal-renderer.js +12 -12
- package/dist/src/compiled/.vendor-stamp.json +6 -6
- package/dist/src/compiled/@workflow/core/_devalue.d.ts +8 -0
- package/dist/src/compiled/@workflow/core/capabilities.d.ts +5 -0
- package/dist/src/compiled/@workflow/core/index.js +2 -2
- package/dist/src/compiled/@workflow/core/replay-payload-cache.d.ts +11 -0
- package/dist/src/compiled/@workflow/core/runtime/compute-instance.d.ts +12 -0
- package/dist/src/compiled/@workflow/core/runtime/constants.d.ts +18 -0
- package/dist/src/compiled/@workflow/core/runtime/helpers.d.ts +103 -31
- package/dist/src/compiled/@workflow/core/runtime/replay-recovery-reporter.d.ts +36 -0
- package/dist/src/compiled/@workflow/core/runtime/resume-hook.d.ts +22 -2
- package/dist/src/compiled/@workflow/core/runtime/step-executor.d.ts +17 -13
- package/dist/src/compiled/@workflow/core/runtime/suspension-handler.d.ts +13 -8
- package/dist/src/compiled/@workflow/core/runtime.d.ts +1 -1
- package/dist/src/compiled/@workflow/core/runtime.js +3 -3
- package/dist/src/compiled/@workflow/core/serialization/codec.d.ts +17 -0
- package/dist/src/compiled/@workflow/core/serialization/hardened.d.ts +155 -0
- package/dist/src/compiled/@workflow/core/serialization/index.d.ts +2 -1
- package/dist/src/compiled/@workflow/core/serialization/reducers/common.d.ts +1 -1
- package/dist/src/compiled/@workflow/core/serialization.d.ts +13 -9
- package/dist/src/compiled/@workflow/core/step/context-storage.d.ts +1 -1
- package/dist/src/compiled/@workflow/core/telemetry/semantic-conventions.d.ts +41 -0
- package/dist/src/compiled/@workflow/core/version.d.ts +1 -1
- package/dist/src/compiled/@workflow/core/workflow.js +1 -1
- package/dist/src/compiled/@workflow/errors/index.d.ts +16 -8
- package/dist/src/compiled/@workflow/errors/index.js +1 -1
- package/dist/src/compiled/@workflow/world/analytics.d.ts +2 -0
- package/dist/src/compiled/@workflow/world/events.d.ts +87 -0
- package/dist/src/compiled/@workflow/world/hooks.d.ts +39 -0
- package/dist/src/compiled/@workflow/world/index.d.ts +1 -1
- package/dist/src/compiled/@workflow/world/interfaces.d.ts +61 -0
- package/dist/src/compiled/@workflow/world/queue.d.ts +40 -0
- package/dist/src/compiled/@workflow/world-local/index.js +3 -3
- package/dist/src/compiled/@workflow/world-vercel/index.js +14 -14
- package/dist/src/compiled/_chunks/workflow/{attribute-changes-1LmTKuTT.js → attribute-changes-DROfGk6l.js} +3 -3
- package/dist/src/compiled/_chunks/workflow/{dist-WjtNsOyf.js → dist-D5bR13zs.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/{dist-BeQ_csYA.js → dist-dNxTT6nO.js} +2 -2
- package/dist/src/compiled/_chunks/workflow/resume-hook-bc-OQVI0.js +1 -0
- package/dist/src/compiled/_chunks/workflow/run-DM3ouA3U.js +1 -0
- package/dist/src/compiled/_chunks/workflow/sleep-D5iWly6-.js +1 -0
- package/dist/src/compiled/_chunks/workflow/wait-until-DoW76jdb.js +15 -0
- package/dist/src/compiler/normalize-subagent.js +1 -1
- package/dist/src/context/dynamic-subagent-lifecycle.js +1 -1
- package/dist/src/context/keys.d.ts +8 -0
- package/dist/src/execution/cancel-descendant-turns-step.js +1 -1
- package/dist/src/execution/dispatch-runtime-actions-step.js +1 -1
- package/dist/src/execution/remote-agent-dispatch.d.ts +3 -1
- package/dist/src/execution/remote-agent-dispatch.js +1 -1
- package/dist/src/execution/workflow-steps.js +1 -1
- package/dist/src/harness/tool-loop.js +1 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/authored-module-loader.js +1 -1
- package/dist/src/internal/nitro/host/create-application-nitro.js +1 -1
- package/dist/src/internal/workflow-bundle/dynamic-capability-transform-plugin.d.ts +10 -0
- package/dist/src/internal/workflow-bundle/dynamic-capability-transform-plugin.js +1 -0
- package/dist/src/internal/workflow-bundle/dynamic-remote-agent-transform.d.ts +7 -0
- package/dist/src/internal/workflow-bundle/dynamic-remote-agent-transform.js +3 -0
- package/dist/src/internal/workflow-bundle/dynamic-tool-ast-references.d.ts +2 -0
- package/dist/src/internal/workflow-bundle/dynamic-tool-ast-references.js +1 -1
- package/dist/src/internal/workflow-bundle/dynamic-tool-transform.js +2 -2
- package/dist/src/public/channels/auth.d.ts +11 -25
- package/dist/src/public/channels/auth.js +1 -1
- package/dist/src/public/definitions/agent.d.ts +5 -2
- package/dist/src/public/index.d.ts +1 -1
- package/dist/src/runtime/framework-channels/index.js +1 -1
- package/dist/src/runtime/subagents/dynamic-agent-config.js +1 -1
- package/dist/src/runtime/subagents/dynamic-remote-agent-config.d.ts +13 -0
- package/dist/src/runtime/subagents/dynamic-remote-agent-config.js +1 -0
- package/dist/src/setup/scaffold/channels-catalog.d.ts +2 -2
- package/dist/src/setup/scaffold/channels-catalog.js +1 -1
- package/dist/src/setup/scaffold/connections/catalog.d.ts +2 -2
- package/dist/src/setup/scaffold/create/project.js +1 -1
- package/docs/channels/eve.mdx +1 -1
- package/docs/concepts/sessions-runs-and-streaming.md +1 -1
- package/docs/guides/auth-and-route-protection.md +13 -13
- package/docs/guides/dev-tui.md +4 -4
- package/docs/guides/dynamic-capabilities.md +26 -1
- package/docs/guides/frontend/nextjs.mdx +1 -1
- package/docs/guides/frontend/nuxt.mdx +1 -1
- package/docs/guides/frontend/sveltekit.mdx +1 -1
- package/docs/guides/remote-agents.md +33 -0
- package/package.json +7 -7
- package/dist/src/compiled/_chunks/workflow/resume-hook-D1_5NCZ6.js +0 -1
- package/dist/src/compiled/_chunks/workflow/run-C240Ctf4.js +0 -1
- package/dist/src/compiled/_chunks/workflow/sleep-De802yfX.js +0 -1
- package/dist/src/compiled/_chunks/workflow/wait-until-z48sPUjU.js +0 -15
|
@@ -201,4 +201,22 @@ export declare const REPLAY_DIVERGENCE_MAX_RETRIES = 3;
|
|
|
201
201
|
* `WORKFLOW_REPLAY_DIVERGENCE_MAX_RETRIES`.
|
|
202
202
|
*/
|
|
203
203
|
export declare function getReplayDivergenceMaxRetries(): number;
|
|
204
|
+
export declare const PRECONDITION_MAX_INPROCESS_RESTARTS = 3;
|
|
205
|
+
/**
|
|
206
|
+
* Effective in-process replay-restart budget for stale-snapshot rejections.
|
|
207
|
+
* Override via `WORKFLOW_PRECONDITION_MAX_INPROCESS_RESTARTS`.
|
|
208
|
+
*/
|
|
209
|
+
export declare function getPreconditionMaxInProcessRestarts(): number;
|
|
210
|
+
export declare const PRECONDITION_MAX_REINVOCATIONS = 5;
|
|
211
|
+
/**
|
|
212
|
+
* Effective per-run budget for re-invocations caused by stale-snapshot
|
|
213
|
+
* rejections. Override via `WORKFLOW_PRECONDITION_MAX_REINVOCATIONS`.
|
|
214
|
+
*/
|
|
215
|
+
export declare function getPreconditionMaxReinvocations(): number;
|
|
216
|
+
export declare const PRECONDITION_REINVOKE_DELAY_SECONDS = 2;
|
|
217
|
+
/**
|
|
218
|
+
* Effective delay before a precondition re-invocation. Override via
|
|
219
|
+
* `WORKFLOW_PRECONDITION_REINVOKE_DELAY_SECONDS`.
|
|
220
|
+
*/
|
|
221
|
+
export declare function getPreconditionReinvokeDelaySeconds(): number;
|
|
204
222
|
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Event, HealthCheckPayload, ValidQueueName, WorkflowRun, World } from '#compiled/@workflow/world/index.js';
|
|
1
|
+
import type { CreateEventParams, CreateEventRequest, Event, EventResult, HealthCheckPayload, ValidQueueName, WorkflowRun, World } from '#compiled/@workflow/world/index.js';
|
|
2
2
|
import { type PayloadKey } from '../serialization/encryption.js';
|
|
3
3
|
/**
|
|
4
4
|
* Validates a workflow name and returns the corresponding queue name.
|
|
@@ -34,6 +34,18 @@ export interface HealthCheckResult {
|
|
|
34
34
|
* key-lookup request.
|
|
35
35
|
*/
|
|
36
36
|
encryptionPublicKey?: string;
|
|
37
|
+
/**
|
|
38
|
+
* The responding deployment's `HOOK_RESUME_INPUT_VERSION` — the protocol
|
|
39
|
+
* version at which the *consumer* (queue-message target) re-ensures the
|
|
40
|
+
* `hook_received` event from `hookInput` on replay. A cross-deployment
|
|
41
|
+
* `start()` stamps the *target's* value (not the caller's) into the new
|
|
42
|
+
* run's `executionContext.hookResumeInputVersion` so that `resumeHook()`
|
|
43
|
+
* only takes the parallel path when the deployment that will actually
|
|
44
|
+
* consume the queue message is known to honor `hookInput`. Omitted when the
|
|
45
|
+
* responding deployment predates this field (an older consumer that ignores
|
|
46
|
+
* `hookInput`), which fails the gate closed.
|
|
47
|
+
*/
|
|
48
|
+
hookResumeInputVersion?: number;
|
|
37
49
|
}
|
|
38
50
|
/**
|
|
39
51
|
* Checks if the given message is a health check payload.
|
|
@@ -76,8 +88,29 @@ export declare function healthCheck(world: World, options?: HealthCheckOptions):
|
|
|
76
88
|
*
|
|
77
89
|
* Pass the IDs currently present in `target` when appending repeatedly to the
|
|
78
90
|
* same array. The set is updated alongside `target`.
|
|
91
|
+
*
|
|
92
|
+
* Events are appended in the order the World returned them, and are not
|
|
93
|
+
* re-sorted: a World's canonical order is its own, and the runtime cannot
|
|
94
|
+
* reproduce it from event ids alone. `world-vercel` orders by event id, while
|
|
95
|
+
* `world-local` orders by `(createdAt, eventId)` and deliberately re-mints keys
|
|
96
|
+
* so that the two diverge. Every append source is already in canonical order
|
|
97
|
+
* relative to the tail (a cursor-delimited page, or a write-response delta), so
|
|
98
|
+
* receipt order is the order to keep. Nothing downstream may assume the tail is
|
|
99
|
+
* the newest event — see {@link latestEventStateUpdatedAt}.
|
|
79
100
|
*/
|
|
80
101
|
export declare function appendUniqueEvents(target: Event[], events: readonly Event[], targetIds?: Set<string>): void;
|
|
102
|
+
/**
|
|
103
|
+
* Inserts `event` into `target` at the position that keeps `target` ordered by
|
|
104
|
+
* ascending `eventId`, or no-ops if an event with the same `eventId` is already
|
|
105
|
+
* present (idempotent).
|
|
106
|
+
*
|
|
107
|
+
* `preloadedEvents` is loaded `sortOrder: 'asc'` and is never re-sorted
|
|
108
|
+
* client-side, so a `hook_received` spliced in by the lazy-resume consumer must
|
|
109
|
+
* land in `eventId` order — a plain `push` would place a late-committing
|
|
110
|
+
* earlier event after events that sort before it, corrupting replay. Event IDs
|
|
111
|
+
* are ULIDs, so lexicographic string order matches commit order.
|
|
112
|
+
*/
|
|
113
|
+
export declare function insertEventByEventId(target: Event[], event: Event): void;
|
|
81
114
|
/**
|
|
82
115
|
* Loads workflow run events by iterating through all pages of paginated
|
|
83
116
|
* results. Events are returned in chronological (ascending) order for
|
|
@@ -94,18 +127,11 @@ export declare function loadWorkflowRunEvents(runId: string, afterCursor?: strin
|
|
|
94
127
|
cursor: string | null;
|
|
95
128
|
}>;
|
|
96
129
|
/**
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
* re-invoked from the queue with a fresh replay.
|
|
101
|
-
*/
|
|
102
|
-
export declare const PRECONDITION_MAX_RELOAD_RETRIES = 2;
|
|
103
|
-
/**
|
|
104
|
-
* A mutable view of the runtime's in-memory event log. `withPreconditionRetry`
|
|
105
|
-
* appends freshly-loaded events to `events` (in place) and advances `cursor`
|
|
106
|
-
* when it reloads, so the caller's loaded snapshot stays current.
|
|
130
|
+
* The runtime's loaded event-log snapshot: the events replayed so far and the
|
|
131
|
+
* cursor positioned after them. Handed to helpers that derive the precondition
|
|
132
|
+
* snapshot from it; they do not mutate it.
|
|
107
133
|
*/
|
|
108
|
-
export interface
|
|
134
|
+
export interface LoadedEventLog {
|
|
109
135
|
events: Event[];
|
|
110
136
|
cursor: string | null;
|
|
111
137
|
}
|
|
@@ -120,36 +146,82 @@ export interface MutableEventLog {
|
|
|
120
146
|
export declare function isPreconditionGuardEnabled(): boolean;
|
|
121
147
|
/**
|
|
122
148
|
* The `stateUpdatedAt` value to send with a replay-context event creation: the
|
|
123
|
-
* ULID time (epoch ms)
|
|
124
|
-
*
|
|
125
|
-
*
|
|
149
|
+
* *maximum* ULID time (epoch ms) over the events the runtime has loaded. Returns
|
|
150
|
+
* `undefined` when there are no events or that id is not a decodable ULID.
|
|
151
|
+
*
|
|
152
|
+
* It is the maximum rather than the tail's because the loaded log is in the
|
|
153
|
+
* World's canonical order, which is not necessarily event-id order (see
|
|
154
|
+
* {@link appendUniqueEvents}). The maximum is what lets the count sent alongside
|
|
155
|
+
* it be read as "events at or below this watermark": every loaded event is at or
|
|
156
|
+
* below it, so the count is exactly `events.length`. Reading the tail instead
|
|
157
|
+
* would understate the watermark on a World whose order is not id-ordered, which
|
|
158
|
+
* is safe (it can only weaken detection) but needlessly imprecise.
|
|
159
|
+
*
|
|
160
|
+
* The maximum is found by lexicographic id comparison, decoding only once: the
|
|
161
|
+
* 26-character Crockford ULID encodes its timestamp in the leading 10
|
|
162
|
+
* characters, so the greatest id also carries the greatest time.
|
|
126
163
|
*
|
|
127
164
|
* Granularity: snapshots are epoch-milliseconds, and the backend allows an
|
|
128
165
|
* equal-timestamp snapshot (an up-to-date client must not be rejected). Two
|
|
129
166
|
* out-of-band events landing in the same millisecond where only the first was
|
|
130
|
-
* loaded therefore pass the guard undetected —
|
|
131
|
-
*
|
|
167
|
+
* loaded therefore pass this half of the guard undetected — that is exactly
|
|
168
|
+
* the hole `stateEventCount` closes, since the count of events at or below the
|
|
169
|
+
* watermark differs even when the watermarks are equal.
|
|
132
170
|
*/
|
|
133
171
|
export declare function latestEventStateUpdatedAt(events: Event[]): number | undefined;
|
|
134
172
|
/**
|
|
135
|
-
* The
|
|
136
|
-
* the
|
|
137
|
-
*
|
|
173
|
+
* The precondition snapshot a replay-context event creation sends, describing
|
|
174
|
+
* the event log the replay derived the event from.
|
|
175
|
+
*
|
|
176
|
+
* The three fields are one indivisible unit: the backend reads the count only
|
|
177
|
+
* relative to the watermark, and returns its inline delta only relative to the
|
|
178
|
+
* cursor. Passing them as a single object is what keeps them from drifting
|
|
179
|
+
* apart at a call site.
|
|
180
|
+
*/
|
|
181
|
+
export interface PreconditionSnapshotParams {
|
|
182
|
+
stateUpdatedAt?: number;
|
|
183
|
+
stateEventCount?: number;
|
|
184
|
+
stateCursor?: string;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Build the precondition snapshot to attach to a replay-context event creation.
|
|
188
|
+
*
|
|
189
|
+
* Returns an empty object — no guard, backend behaves as before — when the
|
|
190
|
+
* guard is disabled or the watermark is not derivable. All three fields fail
|
|
191
|
+
* open together: a count without a watermark is meaningless to the backend, and
|
|
192
|
+
* a cursor without either would invite a delta nobody asked for.
|
|
193
|
+
*
|
|
194
|
+
* `stateEventCount` is `events.length` because the watermark is the log's
|
|
195
|
+
* *maximum* ULID time, so every loaded event is at or below it regardless of the
|
|
196
|
+
* order the World returned them in.
|
|
197
|
+
*
|
|
198
|
+
* Both fields are therefore invariant under permutation of the log: a maximum is
|
|
199
|
+
* order-independent, and the length is set cardinality once `appendUniqueEvents`
|
|
200
|
+
* has deduped by event id. Two replays that consume the same events in different
|
|
201
|
+
* orders send an identical snapshot, so this guard detects that a log is missing
|
|
202
|
+
* an event and can never detect that a replay consumed one in a different order.
|
|
138
203
|
*/
|
|
139
|
-
export declare function
|
|
204
|
+
export declare function preconditionSnapshotParams(events: Event[], cursor?: string | null): PreconditionSnapshotParams;
|
|
140
205
|
/**
|
|
141
|
-
*
|
|
206
|
+
* The events a rejecting World attached to a `PreconditionFailedError`, when it
|
|
207
|
+
* returned the ones the client's snapshot was missing inline.
|
|
208
|
+
*
|
|
209
|
+
* Returns `null` for anything else — no details, a World that did not implement
|
|
210
|
+
* this, or a payload that does not narrow cleanly. Callers fall back to
|
|
211
|
+
* reloading the event log, which is always correct; this is untrusted-shaped
|
|
212
|
+
* data on a failure path, so nothing here is repaired.
|
|
142
213
|
*
|
|
143
|
-
* `
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
* `op` is retried with the now-newer snapshot — up to
|
|
148
|
-
* `PRECONDITION_MAX_RELOAD_RETRIES` times. If it still fails, the error is
|
|
149
|
-
* rethrown so the run falls back to a queue re-invocation. Non-precondition
|
|
150
|
-
* errors are rethrown immediately.
|
|
214
|
+
* `runId` is the caller's run. Every event must belong to it: the delta is
|
|
215
|
+
* merged straight into the replay's log, and one foreign event there is a
|
|
216
|
+
* corrupt log rather than a corrected one — the replay would consume a
|
|
217
|
+
* correlation id for an event that does not exist on this run.
|
|
151
218
|
*/
|
|
152
|
-
export declare function
|
|
219
|
+
export declare function preconditionEventDelta(error: unknown, runId: string): {
|
|
220
|
+
events: Event[];
|
|
221
|
+
cursor: string | null;
|
|
222
|
+
} | null;
|
|
223
|
+
/** Creates one event on a bound run, carrying replay-recovery telemetry. */
|
|
224
|
+
export type EventCreator = (data: CreateEventRequest, params?: CreateEventParams) => Promise<EventResult>;
|
|
153
225
|
/**
|
|
154
226
|
* Wraps a request/response handler and adds a health check "mode"
|
|
155
227
|
* based on the presence of a `__health` query parameter.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { CreateEventParams } from '#compiled/@workflow/world/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Invocation-scoped, one-shot reporter for a replay-divergence recovery.
|
|
4
|
+
*
|
|
5
|
+
* The reporter stays dormant until replay reaches a valid deterministic
|
|
6
|
+
* boundary. The first subsequent event write carries the telemetry for free.
|
|
7
|
+
* A recovered invocation with no natural event write intentionally reports
|
|
8
|
+
* nothing.
|
|
9
|
+
*/
|
|
10
|
+
export declare class ReplayRecoveryReporter {
|
|
11
|
+
private readonly divergenceCount;
|
|
12
|
+
private active;
|
|
13
|
+
private reported;
|
|
14
|
+
constructor(divergenceCount: number);
|
|
15
|
+
/**
|
|
16
|
+
* A reporter for an invocation that never diverged: `activate()` cannot arm
|
|
17
|
+
* it, so `withEventCreate` always passes writes through untouched. Lets every
|
|
18
|
+
* call site hold a non-optional reporter instead of branching on one.
|
|
19
|
+
*
|
|
20
|
+
* Structurally inert rather than a zero-count reporter on purpose — the
|
|
21
|
+
* server rejects a count below 1 as out-of-range and emits a
|
|
22
|
+
* `telemetry_rejected` metric, so a reporter that *can* report zero is a
|
|
23
|
+
* live footgun.
|
|
24
|
+
*/
|
|
25
|
+
static inert(): ReplayRecoveryReporter;
|
|
26
|
+
activate(): void;
|
|
27
|
+
/**
|
|
28
|
+
* Decorate one natural event write with recovery telemetry.
|
|
29
|
+
*
|
|
30
|
+
* The claim is taken synchronously, so concurrent suspension writes cannot
|
|
31
|
+
* all carry the same count. A failed request releases it for a later natural
|
|
32
|
+
* write in the same invocation.
|
|
33
|
+
*/
|
|
34
|
+
withEventCreate<T>(params: CreateEventParams | undefined, create: (params: CreateEventParams | undefined) => Promise<T>): Promise<T>;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=replay-recovery-reporter.d.ts.map
|
|
@@ -11,6 +11,26 @@ import { type PayloadKey } from '../serialization.js';
|
|
|
11
11
|
* @param token - The unique token identifying the hook
|
|
12
12
|
*/
|
|
13
13
|
export declare function getHookByToken(token: string): Promise<Hook>;
|
|
14
|
+
/**
|
|
15
|
+
* The result of {@link resumeHook}: a {@link Hook} augmented with an optional
|
|
16
|
+
* resilience signal.
|
|
17
|
+
*
|
|
18
|
+
* On the parallel fast path, `resumeHook()` writes the `hook_received` event and
|
|
19
|
+
* dispatches the workflow queue message concurrently. When the direct event
|
|
20
|
+
* write fails *transiently* — a 429/5xx, a transport error, or an expected
|
|
21
|
+
* `(runId, resumeId)` conflict with its own re-ensuring consumer — but the queue
|
|
22
|
+
* dispatch succeeds, the resume is still guaranteed: the queue consumer
|
|
23
|
+
* idempotently materializes the `hook_received` event from the payload carried
|
|
24
|
+
* on the message before replay. In that recovered case the returned hook carries
|
|
25
|
+
* `resilientResume: true`.
|
|
26
|
+
*
|
|
27
|
+
* On the happy path (the direct write landed) and on the sequential fallback
|
|
28
|
+
* path, the flag is absent (`undefined`). Callers that don't care about the
|
|
29
|
+
* distinction can treat the result as a plain {@link Hook}.
|
|
30
|
+
*/
|
|
31
|
+
export type ResumedHook = Hook & {
|
|
32
|
+
resilientResume?: boolean;
|
|
33
|
+
};
|
|
14
34
|
/**
|
|
15
35
|
* Resumes a workflow run by sending a payload to a hook identified by its token.
|
|
16
36
|
*
|
|
@@ -19,7 +39,7 @@ export declare function getHookByToken(token: string): Promise<Hook>;
|
|
|
19
39
|
*
|
|
20
40
|
* @param tokenOrHook - The unique token identifying the hook, or the hook object itself
|
|
21
41
|
* @param payload - The data payload to send to the hook
|
|
22
|
-
* @returns Promise resolving to the
|
|
42
|
+
* @returns Promise resolving to the {@link ResumedHook}
|
|
23
43
|
* @throws {HookNotFoundError} If the Hook does not exist or its run has ended
|
|
24
44
|
*
|
|
25
45
|
* @example
|
|
@@ -40,7 +60,7 @@ export declare function getHookByToken(token: string): Promise<Hook>;
|
|
|
40
60
|
* }
|
|
41
61
|
* ```
|
|
42
62
|
*/
|
|
43
|
-
export declare function resumeHook<T = any>(tokenOrHook: string | Hook, payload: T, encryptionKeyOverride?: PayloadKey): Promise<
|
|
63
|
+
export declare function resumeHook<T = any>(tokenOrHook: string | Hook, payload: T, encryptionKeyOverride?: PayloadKey): Promise<ResumedHook>;
|
|
44
64
|
/**
|
|
45
65
|
* Resumes a webhook by sending a {@link https://developer.mozilla.org/en-US/docs/Web/API/Request | Request}
|
|
46
66
|
* object to a hook identified by its token.
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { Event, SerializedData, World } from '#compiled/@workflow/world/index.js';
|
|
2
2
|
import type { PayloadKey } from '../serialization/encryption.js';
|
|
3
|
+
import { type PreconditionSnapshotParams } from './helpers.js';
|
|
4
|
+
import { ReplayRecoveryReporter } from './replay-recovery-reporter.js';
|
|
3
5
|
import { type StepLatencyTracking } from './step-latency.js';
|
|
4
6
|
export declare const DEFAULT_STEP_MAX_RETRIES = 3;
|
|
5
7
|
export interface StepExecutorParams {
|
|
@@ -57,20 +59,20 @@ export interface StepExecutorParams {
|
|
|
57
59
|
*/
|
|
58
60
|
inlineDeltaSinceCursor?: string;
|
|
59
61
|
/**
|
|
60
|
-
* Precondition-guard snapshot
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
62
|
+
* Precondition-guard snapshot of the event log the caller's replay loaded, to
|
|
63
|
+
* attach to this step's `step_started` claim. On the lazy inline path the
|
|
64
|
+
* claim is the step's FIRST durable write (its `step_created` is deferred),
|
|
65
|
+
* so without this the claim would bypass the optimistic-concurrency guard
|
|
66
|
+
* entirely: a replay working from a stale view could claim — and then commit
|
|
67
|
+
* — a step scheduled without observing an event it never loaded. A
|
|
68
|
+
* guard-enforcing World rejects a stale claim with `PreconditionFailedError`
|
|
69
|
+
* (412); executeStep does NOT translate that rejection (re-claiming in place
|
|
70
|
+
* would still commit the stale schedule), so it propagates for the caller to
|
|
71
|
+
* abandon the batch and restart its replay. Undefined when the guard is
|
|
72
|
+
* disabled or the caller has no snapshot; Worlds that don't enforce the guard
|
|
73
|
+
* ignore it.
|
|
72
74
|
*/
|
|
73
|
-
|
|
75
|
+
preconditionSnapshot?: PreconditionSnapshotParams;
|
|
74
76
|
/**
|
|
75
77
|
* Suppress optimistic inline start for this step regardless of
|
|
76
78
|
* `WORKFLOW_OPTIMISTIC_INLINE_START` / `forceOptimisticStart`: take the
|
|
@@ -120,6 +122,8 @@ export interface StepExecutorParams {
|
|
|
120
122
|
* (`metadata.attempt`), which increments on every redelivery.
|
|
121
123
|
*/
|
|
122
124
|
authoritativeAttempt?: number;
|
|
125
|
+
/** One-shot recovery telemetry activated by the orchestrator replay. */
|
|
126
|
+
replayRecoveryReporter?: ReplayRecoveryReporter;
|
|
123
127
|
}
|
|
124
128
|
/**
|
|
125
129
|
* Inline-delta returned by a step-terminal write when the caller passed
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Span } from '#compiled/@opentelemetry/api/index.js';
|
|
2
2
|
import { type SerializedData, type WorkflowRun, type World } from '#compiled/@workflow/world/index.js';
|
|
3
3
|
import type { StepInvocationQueueItem, WorkflowSuspension } from '../global.js';
|
|
4
|
-
import { type
|
|
4
|
+
import { type LoadedEventLog } from './helpers.js';
|
|
5
|
+
import { ReplayRecoveryReporter } from './replay-recovery-reporter.js';
|
|
5
6
|
export interface SuspensionHandlerParams {
|
|
6
7
|
suspension: WorkflowSuspension;
|
|
7
8
|
world: World;
|
|
@@ -9,13 +10,15 @@ export interface SuspensionHandlerParams {
|
|
|
9
10
|
span?: Span;
|
|
10
11
|
requestId?: string;
|
|
11
12
|
/**
|
|
12
|
-
* The runtime's loaded event log.
|
|
13
|
-
*
|
|
14
|
-
* the
|
|
15
|
-
*
|
|
16
|
-
*
|
|
13
|
+
* The runtime's loaded event log. Every event creation this suspension makes
|
|
14
|
+
* is sent with the precondition snapshot derived from it, so a backend that
|
|
15
|
+
* has recorded an event the replay did not see rejects the write with a 412
|
|
16
|
+
* instead of accepting a divergent event. The rejection is not retried here:
|
|
17
|
+
* the event's correlation id was minted by *this* replay's seeded sequence,
|
|
18
|
+
* so re-committing it against a corrected log would persist an event no
|
|
19
|
+
* correct replay produces. The caller restarts the replay instead.
|
|
17
20
|
*/
|
|
18
|
-
eventLog?:
|
|
21
|
+
eventLog?: LoadedEventLog;
|
|
19
22
|
/**
|
|
20
23
|
* Turbo mode only: a promise that resolves once the backgrounded
|
|
21
24
|
* `run_started` has landed (the run exists). When present, every world write
|
|
@@ -26,6 +29,8 @@ export interface SuspensionHandlerParams {
|
|
|
26
29
|
* where `run_started` was already awaited up front.
|
|
27
30
|
*/
|
|
28
31
|
runReadyBarrier?: Promise<unknown>;
|
|
32
|
+
/** One-shot telemetry reporter, activated only after replay has recovered. */
|
|
33
|
+
replayRecoveryReporter?: ReplayRecoveryReporter;
|
|
29
34
|
}
|
|
30
35
|
/**
|
|
31
36
|
* Result of handling a suspension. Returns pending step items so the caller
|
|
@@ -103,5 +108,5 @@ export interface SuspensionHandlerResult {
|
|
|
103
108
|
* 1. Hooks are processed first to prevent race conditions with webhook receivers
|
|
104
109
|
* 2. Step events and wait events are created in parallel
|
|
105
110
|
*/
|
|
106
|
-
export declare function handleSuspension({ suspension, world, run, span, requestId, eventLog, runReadyBarrier, }: SuspensionHandlerParams): Promise<SuspensionHandlerResult>;
|
|
111
|
+
export declare function handleSuspension({ suspension, world, run, span, requestId, eventLog, runReadyBarrier, replayRecoveryReporter, }: SuspensionHandlerParams): Promise<SuspensionHandlerResult>;
|
|
107
112
|
//# sourceMappingURL=suspension-handler.d.ts.map
|
|
@@ -2,7 +2,7 @@ import { type Event, type WorkflowRun } from '#compiled/@workflow/world/index.js
|
|
|
2
2
|
export type { Event, WorkflowRun };
|
|
3
3
|
export { WorkflowSuspension } from './global.js';
|
|
4
4
|
export { type HealthCheckOptions, type HealthCheckResult, healthCheck, } from './runtime/helpers.js';
|
|
5
|
-
export { getHookByToken, resumeHook, resumeWebhook, } from './runtime/resume-hook.js';
|
|
5
|
+
export { getHookByToken, type ResumedHook, resumeHook, resumeWebhook, } from './runtime/resume-hook.js';
|
|
6
6
|
export { getRun, Run, type WorkflowReadableStream, type WorkflowReadableStreamOptions, } from './runtime/run.js';
|
|
7
7
|
export { type CancelRunOptions, cancelRun, listStreams, type ReadStreamOptions, type RecreateRunOptions, type ReenqueueRunOptions, readStream, recreateRunFromExisting, reenqueueRun, type StopSleepOptions, type StopSleepResult, wakeUpRun, } from './runtime/runs.js';
|
|
8
8
|
export { type StartOptions, type StartOptionsBase, type StartOptionsWithDeploymentId, type StartOptionsWithoutDeploymentId, start, } from './runtime/start.js';
|