@lostgradient/weft 0.9.0 → 0.10.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.
Files changed (87) hide show
  1. package/README.md +3 -3
  2. package/dist/alerting/alert-manager.d.ts +3 -1
  3. package/dist/alerting/alert-manager.js +5 -2
  4. package/dist/cli-main.js +63 -63
  5. package/dist/core/context/index.d.ts +2 -1
  6. package/dist/core/context/index.js +8 -0
  7. package/dist/core/context/operation-request.d.ts +2 -0
  8. package/dist/core/context/parallel-cache-entry.d.ts +1 -1
  9. package/dist/core/context/parallel-cache-entry.js +12 -8
  10. package/dist/core/context/parallel-operations.d.ts +1 -1
  11. package/dist/core/context/parallel-operations.js +50 -8
  12. package/dist/core/engine/async-activity-completion.d.ts +24 -54
  13. package/dist/core/engine/async-activity-completion.js +25 -90
  14. package/dist/core/engine/async-activity-records.d.ts +106 -0
  15. package/dist/core/engine/async-activity-records.js +124 -0
  16. package/dist/core/engine/bulk-operations-purge.js +2 -1
  17. package/dist/core/engine/callback-creators-core.js +1 -0
  18. package/dist/core/engine/construction.d.ts +1 -3
  19. package/dist/core/engine/construction.js +2 -5
  20. package/dist/core/engine/deferred-consume-envelope.d.ts +10 -1
  21. package/dist/core/engine/deferred-consume-envelope.js +9 -1
  22. package/dist/core/engine/engine-internal-types.d.ts +1 -0
  23. package/dist/core/engine/engine-runtime-helpers.d.ts +8 -0
  24. package/dist/core/engine/engine-runtime-helpers.js +9 -0
  25. package/dist/core/engine/errors.js +1 -1
  26. package/dist/core/engine/index.d.ts +12 -2
  27. package/dist/core/engine/index.js +22 -7
  28. package/dist/core/engine/internals.d.ts +2 -2
  29. package/dist/core/engine/lifecycle/recovered-services.d.ts +4 -2
  30. package/dist/core/engine/lifecycle/recovered-services.js +37 -7
  31. package/dist/core/engine/lifecycle/resume.d.ts +2 -2
  32. package/dist/core/engine/lifecycle/resume.js +39 -7
  33. package/dist/core/engine/lifecycle/shared.d.ts +34 -0
  34. package/dist/core/engine/lifecycle/transition.d.ts +1 -1
  35. package/dist/core/engine/lifecycle/transition.js +3 -3
  36. package/dist/core/engine/lifecycle.d.ts +1 -1
  37. package/dist/core/engine/memo-durable-activity.js +7 -9
  38. package/dist/core/engine/operations-activity.js +1 -1
  39. package/dist/core/engine/operations-coordination.d.ts +15 -1
  40. package/dist/core/engine/operations-coordination.js +43 -10
  41. package/dist/core/engine/ownership-options.d.ts +1 -0
  42. package/dist/core/engine/ownership-options.js +14 -0
  43. package/dist/core/engine/retention.js +4 -0
  44. package/dist/core/engine/schedule-run-metadata.d.ts +3 -0
  45. package/dist/core/engine/schedule-run-metadata.js +29 -0
  46. package/dist/core/engine/schedule-run.js +19 -4
  47. package/dist/core/engine/schedules.js +4 -3
  48. package/dist/core/engine/sub-operation.js +6 -13
  49. package/dist/core/engine/termination/cleanup.js +3 -1
  50. package/dist/core/types/options.d.ts +12 -0
  51. package/dist/core/types/services-resolution.d.ts +8 -3
  52. package/dist/core/types/workflow-builder.d.ts +2 -2
  53. package/dist/core/types/workflow-context.d.ts +27 -0
  54. package/dist/index.d.ts +2 -2
  55. package/dist/mcp/cli.js +17 -17
  56. package/dist/server/authorization.d.ts +3 -3
  57. package/dist/server/fault-to-json-rpc.d.ts +2 -1
  58. package/dist/server/handler.js +22 -22
  59. package/dist/server/index.js +15 -15
  60. package/dist/server/json-rpc-dispatch.d.ts +2 -2
  61. package/dist/server/json-rpc-parse.d.ts +1 -1
  62. package/dist/server/json-rpc-protocol.d.ts +2 -2
  63. package/dist/server/json-rpc-websocket.d.ts +1 -1
  64. package/dist/server/operation-fault.d.ts +3 -1
  65. package/dist/server/operations/async-activity.js +2 -2
  66. package/dist/server/principal.d.ts +2 -2
  67. package/dist/server/stdio-session.d.ts +4 -4
  68. package/dist/service-worker/index.js +13 -13
  69. package/dist/storage/compressed-storage.js +1 -1
  70. package/dist/storage/http.js +2 -2
  71. package/dist/storage/index.d.ts +1 -0
  72. package/dist/storage/indexeddb.js +1 -1
  73. package/dist/storage/interface.d.ts +1 -0
  74. package/dist/storage/interface.js +1 -1
  75. package/dist/storage/lmdb.js +1 -1
  76. package/dist/storage/memory.js +1 -1
  77. package/dist/storage/neon.js +1 -1
  78. package/dist/storage/resolve.js +1 -1
  79. package/dist/storage/scoped-storage.js +1 -1
  80. package/dist/storage/testing.js +1 -1
  81. package/dist/storage/turso.js +1 -1
  82. package/dist/storage/typed-storage.js +1 -1
  83. package/dist/storage/web-extension.js +1 -1
  84. package/dist/testing/index.js +26 -26
  85. package/dist/version.d.ts +1 -1
  86. package/dist/version.js +1 -1
  87. package/package.json +2 -2
@@ -1,10 +1,35 @@
1
1
  import type { ComposedWorkflowInterceptor } from '../../interceptor.ts';
2
+ import type { WorkflowServicesResolverLaunchOptions, WorkflowServicesResolverScheduleInfo } from '../../types.ts';
2
3
  import type { QueuedInlineWorkflowExecutionStart } from '../engine-internal-types.ts';
3
4
  import { type WorkflowHandle } from '../handles.ts';
4
5
  import type { EngineInternals } from '../internals.ts';
5
6
  export type RegistrationEntry = EngineInternals['registrations'] extends Map<string, infer Entry> ? Entry : never;
6
7
  export declare const FORK_LINEAGE_ATTRIBUTE = "weft:forkedFrom";
7
8
  export declare const EMPTY_STORAGE_VALUE: Uint8Array<ArrayBuffer>;
9
+ /**
10
+ * Durable run context passed to {@link RecoverAllOptions.onRecoveredWorkflow}
11
+ * before recovered user code advances.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * import type { RecoveredWorkflowInfo } from '@lostgradient/weft';
16
+ *
17
+ * function registerSurface(info: RecoveredWorkflowInfo): void {
18
+ * console.log(`Recovered ${info.workflowType}/${info.workflowId}`);
19
+ * }
20
+ * ```
21
+ */
22
+ export interface RecoveredWorkflowInfo {
23
+ /** Handle for the recovered run. */
24
+ handle: WorkflowHandle;
25
+ workflowId: string;
26
+ workflowType: string;
27
+ input: unknown;
28
+ launchOptions: WorkflowServicesResolverLaunchOptions;
29
+ schedule?: WorkflowServicesResolverScheduleInfo;
30
+ /** Re-provided host services, or `undefined` when the run did not use services. */
31
+ services: unknown;
32
+ }
8
33
  /**
9
34
  * Options for {@link Engine.recoverAll}. The acknowledgement flag is an
10
35
  * explicit escape hatch for deployments that intentionally skip stored
@@ -25,6 +50,13 @@ export type RecoverAllOptions = {
25
50
  * rolling deploys or explicit operator storage repair.
26
51
  */
27
52
  acknowledgeUnknownWorkflowTypes?: boolean;
53
+ /**
54
+ * Register consumer-owned live state for each recovered run after services
55
+ * are re-provided but before the workflow generator advances. The callback is
56
+ * awaited. If it throws, only that run fails with a `system` failure and
57
+ * recovery continues with its siblings.
58
+ */
59
+ onRecoveredWorkflow?: (info: RecoveredWorkflowInfo) => void | Promise<void>;
28
60
  };
29
61
  export type LifecycleCallbacks = {
30
62
  dispatchEvent: (event: Event) => void;
@@ -56,6 +88,8 @@ export type LifecycleCallbacks = {
56
88
  * `error` is the canonical {@link unavailableServicesError}.
57
89
  */
58
90
  failWorkflowForUnavailableServices: (workflowId: string, error: Error) => Promise<void>;
91
+ /** Fail one recovered workflow whose pre-resume consumer hook threw. */
92
+ failWorkflowForRecoveryHook: (workflowId: string, error: Error) => Promise<void>;
59
93
  /**
60
94
  * Force a recovered workflow to a terminal `failed` state because its
61
95
  * persisted checkpoint cannot be decoded on this runtime. The failure is
@@ -3,6 +3,6 @@ import { type WorkflowHandle } from '../handles.ts';
3
3
  import type { EngineInternals } from '../internals.ts';
4
4
  import { type LifecycleCallbacks, type RecoverAllOptions, type RegistrationEntry } from './shared.ts';
5
5
  export declare function recoverAll(internals: EngineInternals, callbacks: LifecycleCallbacks, options?: RecoverAllOptions): Promise<WorkflowHandle[]>;
6
- export declare function resume(internals: EngineInternals, workflowId: string, callbacks: LifecycleCallbacks): Promise<WorkflowHandle>;
6
+ export declare function resume(internals: EngineInternals, workflowId: string, callbacks: LifecycleCallbacks, onRecoveredWorkflow?: RecoverAllOptions['onRecoveredWorkflow']): Promise<WorkflowHandle>;
7
7
  export declare function fork(internals: EngineInternals, sourceWorkflowId: string, options: ForkOptions | undefined, callbacks: LifecycleCallbacks): Promise<WorkflowHandle>;
8
8
  export declare function launchWorkflowFromCheckpoint(internals: EngineInternals, workflowId: string, state: WorkflowState, checkpoint: Checkpoint, registration: RegistrationEntry, callbacks: LifecycleCallbacks): WorkflowHandle;
@@ -77,7 +77,7 @@ export async function recoverAll(internals, callbacks, options) {
77
77
  continue;
78
78
  }
79
79
  try {
80
- handles.push(await resume(internals, entry.workflowId, callbacks));
80
+ handles.push(await resume(internals, entry.workflowId, callbacks, options?.onRecoveredWorkflow));
81
81
  } catch (error) {
82
82
  if (error instanceof RegExpExtensionDecodeError) {
83
83
  await callbacks.failWorkflowForCheckpointDecodeError(entry.workflowId, error);
@@ -88,7 +88,7 @@ export async function recoverAll(internals, callbacks, options) {
88
88
  }
89
89
  return handles;
90
90
  }
91
- export async function resume(internals, workflowId, callbacks) {
91
+ export async function resume(internals, workflowId, callbacks, onRecoveredWorkflow) {
92
92
  const workflowState = await loadWorkflowState(internals, workflowId);
93
93
  if (workflowState !== null) {
94
94
  if (callbacks.isInlineWorkflowLocallyOwned(workflowId, workflowState.status) || callbacks.hasLocalCheckpointOwnership(workflowId, workflowState.status)) {
@@ -96,7 +96,7 @@ export async function resume(internals, workflowId, callbacks) {
96
96
  return callbacks.getHandle(workflowId);
97
97
  }
98
98
  }
99
- return resumeWorkflowFromStorage(internals, workflowId, !0, callbacks);
99
+ return resumeWorkflowFromStorage(internals, workflowId, !0, callbacks, onRecoveredWorkflow);
100
100
  }
101
101
  export async function fork(internals, sourceWorkflowId, options, callbacks) {
102
102
  const sourceState = await loadWorkflowState(internals, sourceWorkflowId);
@@ -1,4 +1,4 @@
1
- export { EMPTY_STORAGE_VALUE, createWorkflowHandle, loadTerminalCleanupTrackedState, loadWorkflowStartHeaders, normalizeStartWorkflowTags, processPendingUpdatesAfterReplay, setWorkflowStartHeaders, type LifecycleCallbacks, type RecoverAllOptions, } from './lifecycle/shared.ts';
1
+ export { EMPTY_STORAGE_VALUE, createWorkflowHandle, loadTerminalCleanupTrackedState, loadWorkflowStartHeaders, normalizeStartWorkflowTags, processPendingUpdatesAfterReplay, setWorkflowStartHeaders, type LifecycleCallbacks, type RecoverAllOptions, type RecoveredWorkflowInfo, } from './lifecycle/shared.ts';
2
2
  export { createWorkflowVersionTuple, derivePreparedExecutionState, prepareResumeState, throwVersionMismatch, workflowStateWithVersionTuple, workflowVersionTupleFromState, } from './lifecycle/persist.ts';
3
3
  export { createInitialCheckpoint, createInitialWorkflowState, parseStartOptionDuration, resolveScheduledStartAt, start, startWorkflow, } from './lifecycle/start.ts';
4
4
  export { startOrSignal, startWithIdempotency, type StartOrSignalCallbacks, type StartOrSignalResult, } from './lifecycle/start-or-signal.ts';
@@ -198,15 +198,13 @@ class MemoDurableActivityScope {
198
198
  onAbort();
199
199
  return;
200
200
  }
201
- operation.then((value) => {
202
- settle(() => {
203
- if (this.#closed || signal.aborted) {
204
- reject(this.#abortError());
205
- return;
206
- }
207
- resolve(value);
208
- });
209
- }).catch((error) => {
201
+ operation.then((value) => settle(() => {
202
+ if (this.#closed || signal.aborted) {
203
+ reject(this.#abortError());
204
+ return;
205
+ }
206
+ resolve(value);
207
+ })).catch((error) => {
210
208
  settle(() => reject(error));
211
209
  });
212
210
  });
@@ -18,10 +18,10 @@ import {
18
18
  import { getActivityFunctionWithMetadata, resolveActivityFunction } from "./activity-resolution.js";
19
19
  import {
20
20
  AsyncActivityDeferral,
21
- deriveAsyncActivityToken,
22
21
  driveWorkflowInterceptorGenerator,
23
22
  parkDeferredAsyncActivity
24
23
  } from "./async-activity-completion.js";
24
+ import { deriveAsyncActivityToken } from "./async-activity-records.js";
25
25
  import { callActivityFunction } from "./state-utilities.js";
26
26
  export function buildActivityVerification(_internals, activityName, verify, context, result) {
27
27
  return (async () => {
@@ -33,7 +33,21 @@ export type CoordinationOperationCallbacks = {
33
33
  };
34
34
  export declare function processWaitSignalOperation(internals: EngineInternals, workflowId: string, operation: WaitSignalOperation, callbacks: Pick<CoordinationOperationCallbacks, 'completeOperation'>): Promise<void>;
35
35
  export declare function processParallelOperation(internals: EngineInternals, workflowId: string, operation: ParallelOperation, callbacks: Pick<CoordinationOperationCallbacks, 'executeSubOperation' | 'runOperationWithResult'>): Promise<void>;
36
- export declare function processRaceOperation(_internals: EngineInternals, workflowId: string, operation: RaceOperation, callbacks: Pick<CoordinationOperationCallbacks, 'executeSubOperation' | 'runOperationWithResult'>): Promise<void>;
36
+ export declare function processRaceOperation(internals: EngineInternals, workflowId: string, operation: RaceOperation, callbacks: Pick<CoordinationOperationCallbacks, 'executeSubOperation' | 'runOperationWithResult'>): Promise<void>;
37
+ export declare function assertValidRaceBranchNames(operation: RaceOperation): void;
38
+ export declare function wrapRaceWinner(operation: RaceOperation, winnerIndex: number, value: unknown): unknown;
39
+ /**
40
+ * Execute race branches while giving an already-buffered signal priority over a
41
+ * literal zero-duration sleep. The preflight is non-destructive: the selected
42
+ * wait-signal branch still returns its deferred-consume envelope, so the owning
43
+ * coordinator remains the only place that consumes the durable record.
44
+ *
45
+ * Positive-duration sleeps deliberately bypass this preflight, including when
46
+ * their deadline becomes past-due before dispatch. That keeps ordinary timeout
47
+ * races on the existing Promise.race path and limits the stronger ordering
48
+ * guarantee to the explicit non-blocking-drain idiom.
49
+ */
50
+ export declare function executeRaceSubOperations(internals: EngineInternals, workflowId: string, operations: readonly ContextOperationRequest[], execute: (operation: ContextOperationRequest, signal: AbortSignal) => Promise<unknown>, parentSignal?: AbortSignal, wrapWinner?: (winnerIndex: number, value: unknown) => unknown): Promise<unknown>;
37
51
  export declare function processRunAllOperation(internals: EngineInternals, workflowId: string, operation: RunAllOperation, callbacks: Pick<CoordinationOperationCallbacks, 'runOperationWithResult'>): Promise<void>;
38
52
  export declare function isConfiguredInlineActivity(fn: Function): fn is RunAllOperation['branches'][string][0] & ActivityFunctionWithMetadata;
39
53
  /**
@@ -5,7 +5,7 @@ import {
5
5
  executeRunAllBranches,
6
6
  executeRunAllBranchesSettled
7
7
  } from "../engine-helpers.js";
8
- import { finalizeAndUnwrap } from "./deferred-consume-envelope.js";
8
+ import { createKeyedRaceResultEnvelope, finalizeAndUnwrap } from "./deferred-consume-envelope.js";
9
9
  import {
10
10
  executeActivityOperationResult as executeActivityOperationResultFromInternals
11
11
  } from "./operations-activity.js";
@@ -16,6 +16,7 @@ import {
16
16
  } from "./parallel-dispatch.js";
17
17
  import {
18
18
  consumeSignalWithAtomicWorkflowCommit,
19
+ peekSignal,
19
20
  trackWaiterKey,
20
21
  untrackWaiterKey
21
22
  } from "./signals.js";
@@ -106,20 +107,52 @@ function assertPartialFailurePersistenceSupported(partialEntryWritten, slots, op
106
107
  return;
107
108
  throw Error(`${operationName} partial-failure preservation is not supported in ${executionMode}: the engine cannot persist fulfilled branch slots after a sibling branch fails. Run the workflow inline or make branch side effects idempotent.`);
108
109
  }
109
- export async function processRaceOperation(_internals, workflowId, operation, callbacks) {
110
+ export async function processRaceOperation(internals, workflowId, operation, callbacks) {
110
111
  return callbacks.runOperationWithResult(workflowId, operation, async () => {
111
112
  assertSupportedSignalBranches(operation.operations);
112
- const controller = new AbortController, subOperations = operation.operations.map((subOperation) => callbacks.executeSubOperation(workflowId, subOperation, controller.signal));
113
- Promise.allSettled(subOperations);
114
- let winner;
115
- try {
116
- winner = await Promise.race(subOperations);
117
- } finally {
118
- controller.abort();
119
- }
113
+ assertValidRaceBranchNames(operation);
114
+ const winner = await executeRaceSubOperations(internals, workflowId, operation.operations, (subOperation, signal) => callbacks.executeSubOperation(workflowId, subOperation, signal), void 0, (winnerIndex, value) => wrapRaceWinner(operation, winnerIndex, value));
120
115
  return finalizeAndUnwrap(winner);
121
116
  });
122
117
  }
118
+ export function assertValidRaceBranchNames(operation) {
119
+ if (operation.branchNames !== void 0 && operation.branchNames.length !== operation.operations.length)
120
+ throw Error("ctx.raceKeyed branch names must match its operation count");
121
+ }
122
+ export function wrapRaceWinner(operation, winnerIndex, value) {
123
+ const key = operation.branchNames?.[winnerIndex];
124
+ return key === void 0 ? value : createKeyedRaceResultEnvelope(key, value);
125
+ }
126
+ export async function executeRaceSubOperations(internals, workflowId, operations, execute, parentSignal, wrapWinner) {
127
+ parentSignal?.throwIfAborted();
128
+ const controller = new AbortController, abortFromParent = () => controller.abort(parentSignal?.reason);
129
+ parentSignal?.addEventListener("abort", abortFromParent, { once: !0 });
130
+ try {
131
+ const bufferedSignal = await findBufferedSignalDrainBranch(internals, workflowId, operations);
132
+ parentSignal?.throwIfAborted();
133
+ if (bufferedSignal !== void 0) {
134
+ const value = await execute(bufferedSignal.operation, controller.signal);
135
+ return wrapWinner === void 0 ? value : wrapWinner(bufferedSignal.index, value);
136
+ }
137
+ const subOperations = operations.map((operation, index) => execute(operation, controller.signal).then((value) => ({ index, value })));
138
+ Promise.allSettled(subOperations);
139
+ const winner = await Promise.race(subOperations);
140
+ return wrapWinner === void 0 ? winner.value : wrapWinner(winner.index, winner.value);
141
+ } finally {
142
+ parentSignal?.removeEventListener("abort", abortFromParent);
143
+ controller.abort();
144
+ }
145
+ }
146
+ async function findBufferedSignalDrainBranch(internals, workflowId, operations) {
147
+ if (operations.length !== 2)
148
+ return;
149
+ const waitSignalOperation = operations.find((operation) => operation.type === "wait-signal"), zeroDurationSleep = operations.find((operation) => operation.type === "sleep" && operation.duration === 0);
150
+ if (waitSignalOperation === void 0 || zeroDurationSleep === void 0)
151
+ return;
152
+ if (!(await peekSignal(internals, workflowId, waitSignalOperation.signalName)).found)
153
+ return;
154
+ return { index: operations.indexOf(waitSignalOperation), operation: waitSignalOperation };
155
+ }
123
156
  export async function processRunAllOperation(internals, workflowId, operation, callbacks) {
124
157
  return callbacks.runOperationWithResult(workflowId, operation, async () => {
125
158
  const branchNames = Object.keys(operation.branches), operationIds = branchNames.map((name) => `run-all:${operation.step}:${name}`), resumedSlots = extractResumedSlots(operation.resumedCacheEntry), resumedSlotsByName = mapResumedSlotsByName(resumedSlots, branchNames), branchesToRun = filterBranchesToRun(operation.branches, branchNames, resumedSlotsByName), { outcomes, hasFirstError, firstError } = await executeRunAllBranchesSettled(branchesToRun, (fn, input) => callActivityFunction(fn, input)), slots = mergeRunAllSlots(branchNames, operationIds, resumedSlotsByName, outcomes), entry = buildEntryFromSlots("run-all", slots, branchNames), partialEntryWritten = writePartialEntry(internals, workflowId, operation.step, entry);
@@ -13,6 +13,7 @@ export declare const DEFAULT_LEASE_TTL_MS = 30000;
13
13
  export declare const DEFAULT_LEASE_RENEW_INTERVAL_MS = 5000;
14
14
  /** Default boot-time lease acquisition wait window for `ownership: 'lease'`. */
15
15
  export declare const DEFAULT_LEASE_WAIT_TIMEOUT_MS = 60000;
16
+ export declare function resolveBackgroundTaskMode(options: EngineConstructorOptions | undefined): ResolvedOptions['backgroundTaskMode'];
16
17
  /**
17
18
  * Resolve the ownership posture and lease tuning into their `ResolvedOptions`
18
19
  * fields. Defaults to `'none'`. The lease durations are documented as "ignored
@@ -1,5 +1,19 @@
1
1
  import { normalizeRetentionDuration } from "./validation.js";
2
2
  export const DEFAULT_LEASE_TTL_MS = 30000, DEFAULT_LEASE_RENEW_INTERVAL_MS = 5000, DEFAULT_LEASE_WAIT_TIMEOUT_MS = 60000;
3
+ export function resolveBackgroundTaskMode(options) {
4
+ const mode = options?.backgroundTasks ?? "automatic";
5
+ if (mode !== "automatic" && mode !== "manual")
6
+ throw Error('options.backgroundTasks must be "automatic" or "manual" when provided');
7
+ if (mode === "manual")
8
+ assertManualBackgroundTaskCompatibility(options);
9
+ return mode;
10
+ }
11
+ function assertManualBackgroundTaskCompatibility(options) {
12
+ if (options?.detectSecondInstance === !0)
13
+ throw Error('detectSecondInstance cannot be enabled when backgroundTasks is "manual"');
14
+ if (options?.ownership === "lease")
15
+ throw Error('ownership cannot be "lease" when backgroundTasks is "manual"');
16
+ }
3
17
  export function resolveOwnershipFields(options) {
4
18
  const ownershipMode = assertKnownOwnershipMode(options?.ownership ?? "none");
5
19
  if (ownershipMode !== "lease")
@@ -11,6 +11,10 @@ export function setNextRetentionSweepAt(internals) {
11
11
  internals.nextRetentionSweepAt = internals.options.getNow() + internals.options.retentionSweepIntervalMs;
12
12
  }
13
13
  export function ensureRetentionSweepInterval(internals, callbacks) {
14
+ if (internals.options.backgroundTaskMode === "manual") {
15
+ internals.nextRetentionSweepAt = null;
16
+ return;
17
+ }
14
18
  if (!callbacks.hasConfiguredRetention()) {
15
19
  if (internals.retentionSweepInterval !== null) {
16
20
  clearInterval(internals.retentionSweepInterval ?? void 0);
@@ -0,0 +1,3 @@
1
+ import type { WorkflowServicesResolverScheduleInfo } from '../types.ts';
2
+ export declare function encodeScheduleRunMetadata(scheduleId: string, occurrence: number | undefined): Uint8Array;
3
+ export declare function decodeScheduleRunMetadata(bytes: Uint8Array): WorkflowServicesResolverScheduleInfo | null;
@@ -0,0 +1,29 @@
1
+ import { decode, encode } from "../codec.js";
2
+ import { isRecord } from "../debug-output.js";
3
+ import { isValidScheduleIdentifier } from "./validation/schedule.js";
4
+ export function encodeScheduleRunMetadata(scheduleId, occurrence) {
5
+ return encode({
6
+ id: scheduleId,
7
+ ...occurrence !== void 0 ? { occurrence } : {}
8
+ });
9
+ }
10
+ export function decodeScheduleRunMetadata(bytes) {
11
+ let decoded;
12
+ try {
13
+ decoded = decode(bytes);
14
+ } catch {
15
+ return null;
16
+ }
17
+ if (typeof decoded === "string")
18
+ return isValidScheduleIdentifier(decoded) ? { id: decoded } : null;
19
+ if (!isRecord(decoded))
20
+ return null;
21
+ const { id, occurrence } = decoded;
22
+ if (!isValidScheduleIdentifier(id))
23
+ return null;
24
+ if (occurrence === void 0)
25
+ return { id };
26
+ if (typeof occurrence !== "number" || !Number.isSafeInteger(occurrence))
27
+ return null;
28
+ return { id, occurrence };
29
+ }
@@ -1,16 +1,31 @@
1
1
  import { KEYS } from "../../storage/interface.js";
2
- import { encode } from "../codec.js";
3
2
  import { ScheduleFiredEvent } from "../events.js";
4
3
  import { unavailableServicesError } from "./lifecycle/recovered-services.js";
5
4
  import { EMPTY_STORAGE_VALUE } from "./lifecycle/shared.js";
5
+ import { encodeScheduleRunMetadata } from "./schedule-run-metadata.js";
6
6
  export async function startScheduledRun(internals, state, callbacks, occurrence) {
7
- const workflowId = crypto.randomUUID(), scheduleRunOperations = state.overlap === "allow" ? [] : [{ type: "put", key: KEYS.scheduleRun(workflowId), value: encode(state.id) }], resolution = await resolveScheduledRunServices(internals, workflowId, state, occurrence);
7
+ const workflowId = crypto.randomUUID(), scheduleRunOperations = [
8
+ {
9
+ type: "put",
10
+ key: KEYS.scheduleRun(workflowId),
11
+ value: encodeScheduleRunMetadata(state.id, occurrence)
12
+ },
13
+ {
14
+ type: "put",
15
+ key: KEYS.terminalCleanupNeeded(workflowId),
16
+ value: EMPTY_STORAGE_VALUE
17
+ }
18
+ ], resolution = await resolveScheduledRunServices(internals, workflowId, state, occurrence);
8
19
  if (resolution !== null) {
9
- scheduleRunOperations.push({ type: "put", key: KEYS.workflowHasServices(workflowId), value: EMPTY_STORAGE_VALUE }, { type: "put", key: KEYS.terminalCleanupNeeded(workflowId), value: EMPTY_STORAGE_VALUE });
10
- internals.workflowsNeedingTerminalCleanup.add(workflowId);
20
+ scheduleRunOperations.push({
21
+ type: "put",
22
+ key: KEYS.workflowHasServices(workflowId),
23
+ value: EMPTY_STORAGE_VALUE
24
+ });
11
25
  if (resolution.status === "available")
12
26
  internals.workflowServices.set(workflowId, resolution.services);
13
27
  }
28
+ internals.workflowsNeedingTerminalCleanup.add(workflowId);
14
29
  await callbacks.startWorkflow(state.workflowType, state.input, { id: workflowId }, scheduleRunOperations);
15
30
  internals.engine.dispatchEvent(new ScheduleFiredEvent(state.id, workflowId, internals.options.getNow(), occurrence));
16
31
  if (resolution !== null && resolution.status === "unavailable") {
@@ -4,6 +4,7 @@ import { WorkflowNotRegisteredError } from "./errors.js";
4
4
  import { ScheduleHandle } from "./schedule-handle.js";
5
5
  import { resolveEffectiveScheduleFireAt } from "./schedule-jitter.js";
6
6
  import { getNextScheduleOccurrence } from "./schedule-occurrence.js";
7
+ import { decodeScheduleRunMetadata } from "./schedule-run-metadata.js";
7
8
  import {
8
9
  clearScheduleCurrentWorkflow,
9
10
  createScheduleTimerId,
@@ -208,10 +209,10 @@ export async function handleScheduledWorkflowTerminal(internals, workflowId, cal
208
209
  if (!scheduleRunBytes)
209
210
  return;
210
211
  await internals.storage.delete(KEYS.scheduleRun(workflowId));
211
- const decodedScheduleId = decode(scheduleRunBytes);
212
- if (!isValidScheduleIdentifier(decodedScheduleId))
212
+ const metadata = decodeScheduleRunMetadata(scheduleRunBytes);
213
+ if (metadata === null || !isValidScheduleIdentifier(metadata.id))
213
214
  return;
214
- const state = await loadScheduleState(internals, decodedScheduleId);
215
+ const scheduleId = metadata.id, state = await loadScheduleState(internals, scheduleId);
215
216
  if (!state || state.currentWorkflowId !== workflowId)
216
217
  return;
217
218
  const now = internals.options.getNow(), clearedState = {
@@ -16,7 +16,10 @@ import {
16
16
  executeActivityOperationResult
17
17
  } from "./operations-activity.js";
18
18
  import {
19
- executeRunAllOperationResult
19
+ assertValidRaceBranchNames,
20
+ executeRaceSubOperations,
21
+ executeRunAllOperationResult,
22
+ wrapRaceWinner
20
23
  } from "./operations-coordination.js";
21
24
  import { callMemoFunction } from "./state-utilities.js";
22
25
  export async function processWaitReviewOperation(_internals, workflowId, operation, callbacks) {
@@ -82,16 +85,6 @@ async function executeParallelSubOperation(internals, workflowId, operation, cal
82
85
  }
83
86
  async function executeRaceSubOperation(internals, workflowId, operation, callbacks, signal, speculativeState) {
84
87
  signal?.throwIfAborted();
85
- const controller = new AbortController, abortNestedRace = () => {
86
- controller.abort(signal?.reason);
87
- };
88
- signal?.addEventListener("abort", abortNestedRace, { once: !0 });
89
- const subOperations = operation.operations.map((subOperation) => executeSubOperation(internals, workflowId, subOperation, callbacks, controller.signal, speculativeState));
90
- Promise.allSettled(subOperations);
91
- try {
92
- return await Promise.race(subOperations);
93
- } finally {
94
- signal?.removeEventListener("abort", abortNestedRace);
95
- controller.abort();
96
- }
88
+ assertValidRaceBranchNames(operation);
89
+ return executeRaceSubOperations(internals, workflowId, operation.operations, (subOperation, branchSignal) => executeSubOperation(internals, workflowId, subOperation, callbacks, branchSignal, speculativeState), signal, (winnerIndex, value) => wrapRaceWinner(operation, winnerIndex, value));
97
90
  }
@@ -1,6 +1,6 @@
1
1
  import { KEYS, encodeStorageKeyComponent, storageHas } from "../../../storage/interface.js";
2
2
  import { CleanupWarningEvent } from "../../events.js";
3
- import { asyncActivityWorkflowPrefix } from "../async-activity-completion.js";
3
+ import { asyncActivityWorkflowPrefix } from "../async-activity-records.js";
4
4
  import { forgetCommittedCheckpointBytes } from "../checkpoint-commit-snapshots.js";
5
5
  import { parseTerminalCleanupTimerId, workflowFeedListenerKey } from "../state-utilities.js";
6
6
  import { releaseWorkflowConcurrencySlot } from "../workflow-concurrency.js";
@@ -194,7 +194,9 @@ export async function runDeferredTerminalCleanup(internals, workflowId, timerId,
194
194
  if (state.terminalCleanupToken !== parsedTimer.terminalCleanupToken)
195
195
  return;
196
196
  try {
197
+ await finalizeScheduledWorkflowTerminal(internals, workflowId, callbacks);
197
198
  await cleanupTerminalWorkflowDurableState(internals, workflowId, parsedTimer.includeOutputArtifacts, callbacks);
199
+ await internals.storage.delete(KEYS.scheduleRun(workflowId));
198
200
  } catch (error) {
199
201
  callbacks.handleCleanupError("cleanupTerminalWorkflowDurableState", error, workflowId);
200
202
  throw error;
@@ -218,6 +218,18 @@ export interface ForkOptions {
218
218
  export interface EngineOptions<TServices = unknown> {
219
219
  storage?: WeftStorage;
220
220
  development?: boolean;
221
+ /**
222
+ * Select how engine-owned periodic work is driven. The default `'automatic'`
223
+ * profile starts in-process intervals for update-response cleanup, configured
224
+ * retention sweeps, alert re-evaluation, and the durable-timer scheduler used
225
+ * by {@link Engine.create}. Use `'manual'` in runtimes such as Cloudflare
226
+ * Durable Objects where the host must wake the engine through alarms or Cron
227
+ * triggers, then call {@link Engine.runMaintenance} from each wake-up.
228
+ *
229
+ * Manual mode rejects interval-dependent ownership and second-instance
230
+ * detection options instead of silently starting background work.
231
+ */
232
+ backgroundTasks?: 'automatic' | 'manual';
221
233
  serializer?: Serializer;
222
234
  retention?: RetentionPolicy;
223
235
  retentionSweepInterval?: Duration;
@@ -50,7 +50,11 @@ export interface WorkflowServicesResolverLaunchOptions {
50
50
  }
51
51
  /**
52
52
  * Schedule context passed to {@link EngineOptions.resolveWorkflowServices} for
53
- * scheduled occurrences.
53
+ * scheduled occurrences. New scheduled runs persist this context with the
54
+ * workflow record, so a fresh-process recovery receives the same schedule id and
55
+ * known occurrence timestamp as the live launch path. Runs from older stores
56
+ * that predate the metadata may omit it, and queue-drained runs may omit
57
+ * `occurrence` because their original grid timestamp was not retained.
54
58
  *
55
59
  * @example
56
60
  * ```ts
@@ -72,8 +76,9 @@ export interface WorkflowServicesResolverScheduleInfo {
72
76
  * recovered workflow or scheduled occurrence. `input` is the original durable
73
77
  * launch input, available at resume time — typically enough to rebuild the run's
74
78
  * dependencies (tenant, model, tool registry) without a side table. When tags or
75
- * schedule identity are part of the durable launch context, they are exposed so
76
- * resolvers do not need parallel side channels for the same classification.
79
+ * schedule identity are part of the durable launch context, they are exposed on
80
+ * both live scheduled launches and recovery so resolvers do not need parallel
81
+ * side channels for the same classification.
77
82
  *
78
83
  * @example
79
84
  * ```ts
@@ -50,8 +50,8 @@ export type WorkflowGenerator<TInput, TOutput, TActivities extends ActivityMap,
50
50
  * Bare-`WorkflowContext` callers (no declared activity/signal/etc. maps)
51
51
  * typecheck because the interface's generics all default to permissive shapes:
52
52
  * the typed overloads de-prioritise to `never` and the dynamic string-name /
53
- * callable overloads match instead. This permissive path is current API — it is
54
- * how untyped, ad-hoc-name authoring is supported, not a compatibility shim.
53
+ * callable overloads match instead. This permissive path is the current API for
54
+ * untyped, ad-hoc-name authoring.
55
55
  */
56
56
  export type WorkflowContextOf<TActivities extends ActivityMap = ActivityMap, TSignals extends SignalMap = SignalMap, TUpdates extends UpdateMap = UpdateMap, TQueries extends QueryMap = QueryMap, TSearchAttributes extends SearchAttributeSchema = SearchAttributeSchema, TServices = unknown> = WorkflowContext<TActivities, TSignals, TUpdates, TQueries, TSearchAttributes, TServices>;
57
57
  /**
@@ -15,6 +15,32 @@ export type WorkflowOperationResult<TOperation> = TOperation extends Generator<u
15
15
  export type WorkflowOperationTupleResult<TOperations extends readonly WorkflowOperation<unknown>[]> = {
16
16
  -readonly [TIndex in keyof TOperations]: WorkflowOperationResult<TOperations[TIndex]>;
17
17
  };
18
+ /**
19
+ * Discriminated winner returned by {@link WorkflowContext.raceKeyed}. Checking
20
+ * `key` narrows `value` to the result type of that named workflow operation.
21
+ * Numeric object keys are returned as strings, matching JavaScript object
22
+ * enumeration; symbol keys are rejected at runtime.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * import type { WorkflowKeyedRaceResult, WorkflowOperation } from '@lostgradient/weft';
27
+ *
28
+ * type Winner = WorkflowKeyedRaceResult<{
29
+ * event: WorkflowOperation<string>;
30
+ * idle: WorkflowOperation<void>;
31
+ * }>;
32
+ *
33
+ * function handleWinner(winner: Winner): string {
34
+ * return winner.key === 'event' ? winner.value : 'timed out';
35
+ * }
36
+ * ```
37
+ */
38
+ export type WorkflowKeyedRaceResult<TOperations extends Readonly<Record<string, WorkflowOperation<unknown>>>> = {
39
+ [TKey in keyof TOperations]: {
40
+ key: TKey extends string | number ? `${TKey}` : never;
41
+ value: WorkflowOperationResult<TOperations[TKey]>;
42
+ };
43
+ }[keyof TOperations];
18
44
  type RunAllBranchResult<TBranch> = TBranch extends readonly [
19
45
  execute: infer TExecute,
20
46
  ...rest: unknown[]
@@ -180,6 +206,7 @@ export interface WorkflowContext<TActivities extends ActivityMap = {}, TSignals
180
206
  review(options: HumanReviewOptions): WorkflowOperation<HumanReviewResult>;
181
207
  all<const TOperations extends readonly WorkflowOperation<unknown>[]>(operations: TOperations): WorkflowOperation<WorkflowOperationTupleResult<TOperations>>;
182
208
  race<const TOperations extends readonly WorkflowOperation<unknown>[]>(operations: TOperations): WorkflowOperation<WorkflowOperationTupleResult<TOperations>[number]>;
209
+ raceKeyed<const TOperations extends Readonly<Record<string, WorkflowOperation<unknown>>>>(operations: TOperations): WorkflowOperation<WorkflowKeyedRaceResult<TOperations>>;
183
210
  memo<T>(key: string, fn: () => T | Promise<T>): WorkflowOperation<T>;
184
211
  offload<T>(key: string, fn: () => Promise<T>): WorkflowOperation<OffloadReference>;
185
212
  stream(key: string, fn: (sink: StreamSink) => AsyncGenerator<unknown, void, unknown>): WorkflowOperation<StreamReference>;
package/dist/index.d.ts CHANGED
@@ -22,9 +22,9 @@ export { FAULT_CODE_TO_FAILURE_CATEGORY, failureCategoryForFaultCode, isFaultCod
22
22
  export type { FaultCode } from './core/fault-code.ts';
23
23
  export { DurableActivityScopeError, DurableActivityUnsupportedError, durableActivity, } from './core/context/durable-activity.ts';
24
24
  export { ActivityReconciliationCapabilityError, ActivityReconciliationConflictError, ActivityReconciliationIndeterminateError, ActivityResolutionError, AsyncActivityTokenNotFoundError, BulkDeleteRequiresTerminalWorkflowsError, BulkOperationConfirmationError, ENGINE_LEASE_LOST_WARNING_NAME, ENGINE_LEASE_SYNCHRONOUS_DISPOSE_WARNING_NAME, Engine, EngineCreateNameMismatchError, EngineDisposedError, EngineLeaseAcquisitionTimeoutError, EngineLeaseCorruptedError, EngineLeaseNotHeldError, IdempotencyKeyPurgedError, PersistedDataIncompatibleError, ScheduleHandle, StartOrSignalConflictError, WorkflowAlreadyExistsError, WorkflowConcurrencyLimitExceededError, WorkflowHandle, WorkflowNotFoundError, WorkflowNotRegisteredError, WorkflowSuspendNotSupportedError, WorkflowTeardownPendingError, WorkflowTypeNotRegisteredForRecoveryError, } from './core/engine';
25
- export type { EngineCreateOptions, EngineStateNamespace, RecoverAllOptions } from './core/engine';
25
+ export type { EngineCreateOptions, EngineStateNamespace, RecoverAllOptions, RecoveredWorkflowInfo, } from './core/engine';
26
26
  export { DEFAULT_CHECKPOINT_SIZE_WARNING_THRESHOLD, DEFAULT_MAX_NESTING_DEPTH, DEFAULT_POLL_INTERVAL_MS, DEFAULT_RETRY_POLICY, DEFAULT_VISIBILITY_TIMEOUT_MS, HISTORY_CIRCUIT_BREAKER_REASON, WorkflowBuilderError, query, schedule, signal, update, workflow, } from './core/types';
27
- export type { ActivityArgsFor, ActivityCallOptions, ActivityCallable, ActivityContext, ActivityDefinition, ActivityEntryInput, ActivityFunction, ActivityMap, ActivityMapInput, ActivityObjectInput, ActivityResultFor, ActivityVerificationContext, ActivityVerificationPhase, ActivityVerificationResult, AnyActivityDefinition, AnyWorkflowDefinition, ArchiveAdapter, BuilderState, BuiltWorkflowDefinition, BulkCancelResult, BulkDeleteResult, BulkOperationAction, BulkOperationAuditEvent, BulkOperationCommitOptions, BulkOperationDryRunOptions, BulkOperationDryRunResult, BulkOperationError, BulkOperationFilterSummary, BulkOperationOptions, BulkOperationPrincipal, BulkOperationScopeSummary, BulkRetryFailedResult, BulkSignalAllCommitOptions, BulkSignalAllDryRunOptions, BulkSignalAllOptions, BulkSignalResult, BulkTagResult, Checkpoint, CheckpointState, CheckpointSummary, CompletedReviewEntry, CoordinatedUpdateResult, DefinitionSchema, Duration, EngineOptions, FailureCategory, ForkLineage, ForkOptions, HistoryPolicy, InferActivityEntries, InferActivityEntry, InferWorkflowEntries, InferWorkflowEntry, InitialBuilderState, LaunchMetadata, ListFilter, ListOptions, MarkBuilderState, NormalizeActivities, NormalizedActivityEntry, NormalizedRetentionPolicy, PaginatedResult, PayloadSizePolicy, PendingReviewEntry, PurgeResult, QueryDefinition, QueryMap, QueryShape, RegisteredWorkflowDefinition, RetentionOverview, RetentionPolicy, RetryPolicy, ReviewListEntry, ReviewListFilter, ReviewStatus, ScheduleDefinition, ScheduleFilter, ScheduleOptions, ScheduleOverlapPolicy, ScheduleSpec, ScheduleState, ScheduleStatus, ScheduleSummary, SearchAttributeDefinition, SearchAttributeHandle, SearchAttributeSchema, SearchAttributeValue, Serializer, SignalDefinition, SignalDeliveryOptions, SignalMap, SignalPayload, StartOptions, StartOrSignalOptions, StartOrSignalSignal, SubmitReviewOptions, TerminationReason, UpdateDefinition, UpdateMap, UpdatePayload, WorkerReplayOperationFailure, WorkerReplayOperationSignature, WorkflowAlreadyRegistered, WorkflowAtomicState, WorkflowAtomicStateOptions, WorkflowBuilder, WorkflowBuilderOptions, WorkflowConcurrencyOptions, WorkflowContext, WorkflowDefinition, WorkflowEvent, WorkflowFunction, WorkflowGenerator, WorkflowId, WorkflowLogLevel, WorkflowLogRecord, WorkflowLogger, WorkflowRegistry, WorkflowReplay, WorkflowServicesResolution, WorkflowServicesResolverInfo, WorkflowServicesResolverLaunchOptions, WorkflowServicesResolverScheduleInfo, WorkflowSessionState, WorkflowSnapshot, WorkflowState, WorkflowStateNamespace, WorkflowStatus, WorkflowSummary, WorkflowTimelineEntry, WorkflowTimelineStatus, WorkflowTypeRetentionPolicy, } from './core/types';
27
+ export type { ActivityArgsFor, ActivityCallOptions, ActivityCallable, ActivityContext, ActivityDefinition, ActivityEntryInput, ActivityFunction, ActivityMap, ActivityMapInput, ActivityObjectInput, ActivityResultFor, ActivityVerificationContext, ActivityVerificationPhase, ActivityVerificationResult, AnyActivityDefinition, AnyWorkflowDefinition, ArchiveAdapter, BuilderState, BuiltWorkflowDefinition, BulkCancelResult, BulkDeleteResult, BulkOperationAction, BulkOperationAuditEvent, BulkOperationCommitOptions, BulkOperationDryRunOptions, BulkOperationDryRunResult, BulkOperationError, BulkOperationFilterSummary, BulkOperationOptions, BulkOperationPrincipal, BulkOperationScopeSummary, BulkRetryFailedResult, BulkSignalAllCommitOptions, BulkSignalAllDryRunOptions, BulkSignalAllOptions, BulkSignalResult, BulkTagResult, Checkpoint, CheckpointState, CheckpointSummary, CompletedReviewEntry, CoordinatedUpdateResult, DefinitionSchema, Duration, EngineOptions, FailureCategory, ForkLineage, ForkOptions, HistoryPolicy, InferActivityEntries, InferActivityEntry, InferWorkflowEntries, InferWorkflowEntry, InitialBuilderState, LaunchMetadata, ListFilter, ListOptions, MarkBuilderState, NormalizeActivities, NormalizedActivityEntry, NormalizedRetentionPolicy, PaginatedResult, PayloadSizePolicy, PendingReviewEntry, PurgeResult, QueryDefinition, QueryMap, QueryShape, RegisteredWorkflowDefinition, RetentionOverview, RetentionPolicy, RetryPolicy, ReviewListEntry, ReviewListFilter, ReviewStatus, ScheduleDefinition, ScheduleFilter, ScheduleOptions, ScheduleOverlapPolicy, ScheduleSpec, ScheduleState, ScheduleStatus, ScheduleSummary, SearchAttributeDefinition, SearchAttributeHandle, SearchAttributeSchema, SearchAttributeValue, Serializer, SignalDefinition, SignalDeliveryOptions, SignalMap, SignalPayload, StartOptions, StartOrSignalOptions, StartOrSignalSignal, SubmitReviewOptions, TerminationReason, UpdateDefinition, UpdateMap, UpdatePayload, WorkerReplayOperationFailure, WorkerReplayOperationSignature, WorkflowAlreadyRegistered, WorkflowAtomicState, WorkflowAtomicStateOptions, WorkflowBuilder, WorkflowBuilderOptions, WorkflowConcurrencyOptions, WorkflowContext, WorkflowDefinition, WorkflowEvent, WorkflowFunction, WorkflowGenerator, WorkflowId, WorkflowKeyedRaceResult, WorkflowLogLevel, WorkflowLogRecord, WorkflowLogger, WorkflowRegistry, WorkflowReplay, WorkflowServicesResolution, WorkflowServicesResolverInfo, WorkflowServicesResolverLaunchOptions, WorkflowServicesResolverScheduleInfo, WorkflowSessionState, WorkflowSnapshot, WorkflowState, WorkflowStateNamespace, WorkflowStatus, WorkflowSummary, WorkflowTimelineEntry, WorkflowTimelineStatus, WorkflowTypeRetentionPolicy, } from './core/types';
28
28
  export { AlertManager } from './alerting/index';
29
29
  export type { AlertAction, AlertMetric, AlertRule, AlertState, AlertStatus, AlertingOptions, WebhookTarget, } from './alerting/types';
30
30
  export { ActivityAsyncPendingEvent, ActivityCompletedEvent, ActivityFailedEvent, ActivityStartedEvent, AlertFiredEvent, AlertResolvedEvent, AttributesChangedEvent, CheckpointSizeWarningEvent, ConstraintViolatedEvent, DevelopmentWarningEvent, ScheduleFiredEvent, ScheduleMissedFireEvent, SignalDeliveredEvent, SignalReceivedEvent, StorageSizeReportedEvent, TaskResultDeadLetteredEvent, UpdateCompletedEvent, UpdateReceivedEvent, WorkflowCancelledEvent, WorkflowCompletedEvent, WorkflowDefinitionRegisteredEvent, WorkflowFailedEvent, WorkflowRecoverySkippedEvent, WorkflowResumedEvent, WorkflowStartedEvent, WorkflowSuspendedEvent, WorkflowTeardownEvent, WorkflowTimedOutEvent, } from './core/events';