@dudousxd/nestjs-durable-core 0.80.1 → 0.82.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/dist/index.d.cts CHANGED
@@ -1150,6 +1150,16 @@ interface StepError {
1150
1150
  retryable?: boolean | undefined;
1151
1151
  stack?: string | undefined;
1152
1152
  }
1153
+ /**
1154
+ * See {@link StateStore.listOrphanedRuns}: the live leases a rebooted engine instance may take back
1155
+ * immediately, i.e. those its previous incarnation (same `instanceId`) held when it died.
1156
+ */
1157
+ interface OwnedLeaseReclaim {
1158
+ /** The engine instance id the lease must be held by. */
1159
+ owner: string;
1160
+ /** Only leases expiring strictly before this epoch ms (the caller's boot time + `leaseMs`). */
1161
+ lockedBefore: number;
1162
+ }
1153
1163
  interface StateStore {
1154
1164
  /**
1155
1165
  * Provision the tables/collections this store needs, idempotently. Called on boot when the
@@ -1251,8 +1261,16 @@ interface StateStore {
1251
1261
  * Optional but recommended: without it the engine lists every incomplete run and filters the
1252
1262
  * leases in process, which on a busy fleet reads every healthy running run once per tick per
1253
1263
  * worker.
1254
- */
1255
- listOrphanedRuns?(nowMs: number, limit: number, namespace?: string): Promise<WorkflowRun[]>;
1264
+ *
1265
+ * When `ownedBy` is given, ALSO return the runs whose lease is still live but held by
1266
+ * `ownedBy.owner` with `lockedUntil < ownedBy.lockedBefore` (strictly), under the same status,
1267
+ * namespace, order and `limit`. The engine passes its own `instanceId` and its boot time plus
1268
+ * `leaseMs`: a lease that expires before then was taken by a PREVIOUS process with the same stable
1269
+ * `instanceId` (one killed without a graceful shutdown), never by this one, so it reclaims those
1270
+ * at once instead of waiting out the lease. A store that ignores the argument keeps the plain
1271
+ * behaviour: those runs are reclaimed once their lease expires.
1272
+ */
1273
+ listOrphanedRuns?(nowMs: number, limit: number, namespace?: string, ownedBy?: OwnedLeaseReclaim): Promise<WorkflowRun[]>;
1256
1274
  /** The oldest `pending` runs awaiting dispatch (FIFO, by `createdAt`), capped at `limit`. */
1257
1275
  listPendingRuns(limit: number, namespace?: string): Promise<WorkflowRun[]>;
1258
1276
  /**
@@ -1267,8 +1285,15 @@ interface StateStore {
1267
1285
  * acquired — so concurrent engine instances never recover the same run twice.
1268
1286
  */
1269
1287
  tryLockRun(runId: string, owner: string, leaseUntilMs: number, nowMs: number): Promise<boolean>;
1270
- /** Release a run's recovery lease so another instance can pick it up (e.g. once it suspends). */
1271
- releaseRunLock(runId: string): Promise<void>;
1288
+ /**
1289
+ * Release a run's recovery lease so another instance can pick it up (e.g. once it suspends).
1290
+ *
1291
+ * `owner`, when given, makes the release owner-scoped: clear the lease ONLY if `owner` still holds
1292
+ * it, so an instance releasing a lease it may have lost (a drain that timed out) never frees the
1293
+ * lease another instance took over. Without it the release is unconditional. A store that ignores
1294
+ * the argument stays correct, only less precise in that race.
1295
+ */
1296
+ releaseRunLock(runId: string, owner?: string): Promise<void>;
1272
1297
  /**
1273
1298
  * Extend a run's lease to `leaseUntilMs`, but ONLY if `owner` still holds it — so a live worker
1274
1299
  * heartbeating its long run keeps the lease, while a dead worker's lease still expires and gets
@@ -1568,6 +1593,13 @@ interface ScheduleQuery {
1568
1593
  /** The terminal run statuses — a run in one of these is finished and will never change on its own.
1569
1594
  * Only these are eligible for retention pruning (a {@link RetentionPolicy} targeting a non-terminal
1570
1595
  * status would race the engine and delete live work). */
1596
+ /**
1597
+ * Normalise a namespace to the worker pool it names: `''` is the default pool, exactly like
1598
+ * `'default'` (the transport already maps both to the bare token), so it is stamped, polled and
1599
+ * compared as `'default'`. `undefined` passes through untouched: an UNSET engine namespace is the
1600
+ * operator (drives every namespace), and an unset run namespace belongs to everyone.
1601
+ */
1602
+ declare function poolNamespace(namespace: string | undefined): string | undefined;
1571
1603
  declare const TERMINAL_RUN_STATUSES: readonly RunStatus[];
1572
1604
  /**
1573
1605
  * One retention rule for hard-pruning terminal run history. Within `statuses` (terminal only), a run
@@ -3218,6 +3250,20 @@ interface EntityHost {
3218
3250
  getEvent<T>(runId: string, key: string): Promise<T | undefined>;
3219
3251
  signal(token: string, payload: unknown): Promise<unknown>;
3220
3252
  }
3253
+ /**
3254
+ * What a workflow-side send needs on top of {@link EntityHost}: a durable buffer write it can AWAIT
3255
+ * inside its turn, and a way to wake an entity run that is parked on its wait. Optional so a bare
3256
+ * {@link EntityHost} (tests, older hosts) still works through {@link Entities.dispatch}.
3257
+ */
3258
+ interface EntityWorkflowHost {
3259
+ /** Durably buffer `payload` on `token` (the store's `bufferSignal`). */
3260
+ bufferSignal(token: string, payload: unknown): Promise<void>;
3261
+ /** If a run is parked on `token`, wake it with `payload`; if none is, do nothing (no buffering). */
3262
+ wakeWaiter(token: string, payload: unknown): Promise<unknown>;
3263
+ /** Start `runId` of `workflow` if it doesn't exist yet (idempotent by run id). */
3264
+ ensureStarted(workflow: string, input: unknown, runId: string): Promise<unknown>;
3265
+ }
3266
+ declare const ENTITY_WORKFLOW = "__entity";
3221
3267
  /**
3222
3268
  * Durable keyed **entities** (virtual objects): a keyed actor whose handlers run **serialized per
3223
3269
  * key** over **durable state**, exactly once. Each key is one long-lived run (`entity:<name>:<key>`)
@@ -3226,14 +3272,35 @@ interface EntityHost {
3226
3272
  */
3227
3273
  declare class Entities {
3228
3274
  private readonly host;
3275
+ private readonly workflowHost?;
3229
3276
  private readonly configs;
3230
- constructor(host: EntityHost);
3277
+ constructor(host: EntityHost, workflowHost?: EntityWorkflowHost | undefined);
3231
3278
  register<S>(name: string, config: EntityConfig<S>): void;
3232
3279
  /** Deliver an op to an entity's runner, starting it on first contact. `reply` (a signal token)
3233
3280
  * receives the handler's result, for `ctx.callEntity`. */
3234
3281
  dispatch(name: string, key: string, op: string, arg: unknown, reply?: string): Promise<{
3235
3282
  runId: string;
3236
3283
  }>;
3284
+ /**
3285
+ * The durable half of a send from INSIDE a workflow (`ctx.callEntity` / `ctx.signalEntity`): write
3286
+ * the op to the entity's signal buffer and return once it is stored, so the caller can checkpoint
3287
+ * after it. The op carries `id`, the caller's stable `<runId>:<seq>`, so if the caller dies between
3288
+ * this write and its checkpoint and sends again on replay, the entity skips the second copy. The
3289
+ * entity's run is also ensured here, awaited (`start` only enqueues, it never runs the body
3290
+ * inline), so an op sent on first contact can't be stranded in a buffer no run will ever read if
3291
+ * the process dies right after. The wake-up ({@link kick}) is separate and may be lost: a busy
3292
+ * entity reads the buffer at its next wait, and a parked one is paired with it by the engine's
3293
+ * `reconcileMs` sweep. Returns `false` on a host without a workflow host.
3294
+ */
3295
+ enqueue(name: string, key: string, op: string, arg: unknown, id: string, reply?: string): Promise<boolean>;
3296
+ /**
3297
+ * Make the entity act on what {@link enqueue} buffered: wake its run if it is parked on its wait
3298
+ * (the run itself was ensured by `enqueue`; ensured again here, idempotently, for a caller replay
3299
+ * that only re-kicks). A run that is busy needs nothing: its next wait reads the buffer before
3300
+ * suspending. The wake carries a no-op `nudge`, never the op itself, so the op stays in
3301
+ * the buffer in arrival order and a lost or repeated kick costs at most one empty iteration.
3302
+ */
3303
+ kick(name: string, key: string): Promise<void>;
3237
3304
  signal(name: string, key: string, op: string, arg?: unknown): Promise<void>;
3238
3305
  getState<S = unknown>(name: string, key: string): Promise<S | undefined>;
3239
3306
  /** The built-in runner: one long-lived run per key, processing ops serially over state. */
@@ -3943,6 +4010,60 @@ declare class ScheduleClient {
3943
4010
  private write;
3944
4011
  }
3945
4012
 
4013
+ /** Default idle threshold for a stranded run: 15 minutes. */
4014
+ declare const DEFAULT_STALLED_AFTER_MS: number;
4015
+ /** The oldest unresolved remote step of a run — the lost-dispatch signature when it is old. */
4016
+ interface StalePendingStep {
4017
+ seq: number;
4018
+ name: string;
4019
+ /** How many times this step has been (re-)dispatched. A lost dispatch typically sits at 1. */
4020
+ attempts: number;
4021
+ /** Milliseconds since the step was enqueued to the transport. */
4022
+ ageMs: number;
4023
+ /**
4024
+ * The step's lease (`wakeAt`, epoch ms) when it has one: a step with a `timeoutMs`, a heartbeat
4025
+ * renewing it, or `remoteRedispatchMs`. `null` when nothing is leasing the step.
4026
+ */
4027
+ leaseUntil: number | null;
4028
+ }
4029
+ /** What an `engine.onStalled` listener (and {@link findStalledRuns}) receives: a stranded run and why. */
4030
+ interface StalledRunInfo {
4031
+ run: WorkflowRun;
4032
+ /** Milliseconds since the run's last activity (`updatedAt`). */
4033
+ ageMs: number;
4034
+ /** Suspended with NO wake timer — nothing will re-drive it (the `reconcileMs: 0` hazard). */
4035
+ wakeForever: boolean;
4036
+ /** The oldest pending remote step with no live lease, when that is the stranding signature. */
4037
+ stalePending: StalePendingStep | null;
4038
+ }
4039
+ /** Options for {@link findStalledRuns}. */
4040
+ interface FindStalledRunsOptions {
4041
+ /** Idle threshold in ms. Default {@link DEFAULT_STALLED_AFTER_MS}. */
4042
+ thresholdMs?: number | undefined;
4043
+ /** Max candidate runs inspected (newest first). Default 1000. */
4044
+ scan?: number | undefined;
4045
+ /** Evaluate as of this time (epoch ms). Default `Date.now()`. */
4046
+ now?: number | undefined;
4047
+ /** Only runs in this namespace. Omit for every namespace. */
4048
+ namespace?: string | undefined;
4049
+ }
4050
+ /**
4051
+ * The stranded runs in a store right now — the query behind `engine.sweepStalled`/`onStalled`,
4052
+ * `engine.listStalledRuns` and the CLI's `durable inspect --stale`. Works on a bare store, so an
4053
+ * ops script or a CLI can run it without an engine.
4054
+ *
4055
+ * A `running`/`suspended` run qualifies when it has been untouched for `thresholdMs` AND either:
4056
+ *
4057
+ * - it is suspended with NO wake timer (`wakeForever`): nothing will ever re-drive it; or
4058
+ * - its oldest pending REMOTE step is older than the threshold and has no lease in the future
4059
+ * (`stalePending`): the dispatch was most likely lost.
4060
+ *
4061
+ * Healthy long work is excluded: a long `ctx.sleep` has a future `wakeAt` and no pending step, and a
4062
+ * remote step with a `timeoutMs`, a heartbeat or `remoteRedispatchMs` carries a future lease. Issues
4063
+ * one `listCheckpoints` per idle candidate, bounded by `scan`: an operator read, not a hot path.
4064
+ */
4065
+ declare function findStalledRuns(store: Pick<StateStore, 'listRuns' | 'listCheckpoints'>, options?: FindStalledRunsOptions): Promise<StalledRunInfo[]>;
4066
+
3946
4067
  type WorkflowFn = (ctx: InternalWorkflowCtx, input: unknown) => Promise<unknown>;
3947
4068
  /**
3948
4069
  * Options for {@link WorkflowEngine.start}.
@@ -4119,6 +4240,14 @@ interface WorkflowEngineDeps {
4119
4240
  * for a genuinely-orphaned run. Default 5min; set `0` to disable (the prior wake-forever behavior).
4120
4241
  */
4121
4242
  reconcileMs?: number | undefined;
4243
+ /**
4244
+ * How long an in-flight run must sit untouched, with the stranded signature (a wake-forever
4245
+ * suspension, or an old pending remote step with no live lease), before the
4246
+ * {@link WorkflowEngine.onStalled} listeners are notified. Default 900 000 (15 min); floored at
4247
+ * 60 000. The sweep ({@link WorkflowEngine.sweepStalled}) only does work when a listener is
4248
+ * registered.
4249
+ */
4250
+ stalledAfterMs?: number | undefined;
4122
4251
  /**
4123
4252
  * The most due timers one {@link WorkflowEngine.resumeDueTimers} pass loads and drives, most
4124
4253
  * overdue first. Every driving instance runs that pass each tick, so a wave of thousands of due
@@ -4226,6 +4355,15 @@ interface WorkflowEngineDeps {
4226
4355
  */
4227
4356
  runDispatcher?: RunDispatcher | undefined;
4228
4357
  }
4358
+ /** Options for {@link WorkflowEngine.listStalledRuns}. */
4359
+ interface ListStalledRunsOptions {
4360
+ /** Idle threshold in ms. Defaults to the engine's `stalledAfterMs` (15 min). */
4361
+ thresholdMs?: number | undefined;
4362
+ /** Max candidate runs inspected (newest first). Default 1000. */
4363
+ scan?: number | undefined;
4364
+ /** Evaluate as of this clock time. Defaults to the engine clock. */
4365
+ now?: number | undefined;
4366
+ }
4229
4367
  /**
4230
4368
  * The orchestrator. Owns workflow state and replays runs deterministically: each step's
4231
4369
  * result is checkpointed, so on resume a completed step returns its saved output instead of
@@ -4241,6 +4379,12 @@ declare class WorkflowEngine {
4241
4379
  private readonly instanceId;
4242
4380
  private readonly namespace;
4243
4381
  private readonly leaseMs;
4382
+ /**
4383
+ * Leases held by this `instanceId` that expire strictly before this epoch ms were taken by a
4384
+ * PREVIOUS process with the same id (every lease this one takes or renews expires at
4385
+ * `clock() + leaseMs`, so at or after it). See {@link orphanedRuns}.
4386
+ */
4387
+ private readonly ownLeaseCutoffMs;
4244
4388
  private readonly maxRecoveryAttempts?;
4245
4389
  private readonly remoteAdvanceSilenceMs?;
4246
4390
  private readonly reconcileMs;
@@ -4344,6 +4488,18 @@ declare class WorkflowEngine {
4344
4488
  private readonly stepQueue;
4345
4489
  /** Executions currently in flight, so a graceful shutdown can wait for them to settle. */
4346
4490
  private readonly inflight;
4491
+ /**
4492
+ * The run lease of each execution in flight on THIS instance, by run id — renewed while it runs
4493
+ * and checked by every settle (the zombie fence, see {@link ExecutionLease}). Also what `drain()`
4494
+ * releases when its budget runs out.
4495
+ */
4496
+ private readonly executionLeases;
4497
+ /** Pager hooks for stranded runs (see {@link onStalled}). */
4498
+ private readonly stalledListeners;
4499
+ /** Runs already paged about, by id → the `updatedAt` of the paged episode (see {@link sweepStalled}). */
4500
+ private readonly notifiedStalled;
4501
+ private lastStalledSweepAt;
4502
+ private readonly stalledAfterMs;
4347
4503
  private draining;
4348
4504
  /** Wait already spent on this shutdown before `drain()` (see `beginDrain`). */
4349
4505
  private drainSpentMs;
@@ -4509,6 +4665,33 @@ declare class WorkflowEngine {
4509
4665
  * Returns an unsubscribe function.
4510
4666
  */
4511
4667
  onDead(listener: (run: WorkflowRun) => void): () => void;
4668
+ /**
4669
+ * Register a pager hook for STRANDED runs: an in-flight run untouched past `stalledAfterMs` that is
4670
+ * either suspended with NO wake timer (wake-forever: nothing will ever re-drive it) or parked on an
4671
+ * old pending remote step with no live lease (dispatched and, most likely, lost). The timer poller
4672
+ * sweeps for these ({@link sweepStalled}, throttled to one pass a minute) and notifies each episode
4673
+ * ONCE per instance: a run is paged again only after it makes progress and strands again. Wire your
4674
+ * alerting here like {@link onDead}. A listener that throws never breaks the sweep. Returns an
4675
+ * unsubscribe function.
4676
+ */
4677
+ onStalled(listener: (info: StalledRunInfo) => void): () => void;
4678
+ /**
4679
+ * Detect stranded in-flight runs and notify the {@link onStalled} listeners. Self-throttled to one
4680
+ * pass a minute, skipped while draining, and a no-op without listeners — call it every tick (the
4681
+ * NestJS timer poller does). Scoped to this engine's `namespace` (an operator engine with no
4682
+ * namespace sweeps every namespace). Returns the runs notified THIS pass.
4683
+ */
4684
+ sweepStalled(now?: number): Promise<StalledRunInfo[]>;
4685
+ /**
4686
+ * The stranded runs right now, without notifying anyone: the query behind {@link sweepStalled} and
4687
+ * the CLI's `durable inspect --stale`. A `running`/`suspended` run qualifies when it has been
4688
+ * untouched for `thresholdMs` (default `stalledAfterMs`) AND either it is suspended with no wake
4689
+ * timer, or its oldest pending remote step is older than the threshold with no lease in the future
4690
+ * (a step with a `timeoutMs`, a heartbeat or `remoteRedispatchMs` keeps a lease; a long
4691
+ * `ctx.sleep` has a future `wakeAt`; neither is stranded). Scans up to `scan` candidates (default
4692
+ * 1000), newest first, in this engine's namespace.
4693
+ */
4694
+ listStalledRuns(options?: ListStalledRunsOptions): Promise<StalledRunInfo[]>;
4512
4695
  private notifyDead;
4513
4696
  /** Emit a locally-produced lifecycle event: deliver to subscribers AND broadcast it on the
4514
4697
  * control plane so other instances (e.g. a dashboard pod) can live-tail this run. */
@@ -4520,6 +4703,9 @@ declare class WorkflowEngine {
4520
4703
  start<TInput>(workflow: string, input: TInput, runId: string, opts?: StartOptions): Promise<RunResult>;
4521
4704
  /** Read a run's current persisted state (or null if unknown). A thin pass-through to the store. */
4522
4705
  getRun(runId: string): Promise<WorkflowRun | null>;
4706
+ /** A run's full checkpoint timeline, ordered by seq. A thin pass-through to the store (it is what
4707
+ * the testing kit's `captureHistory` reads, next to {@link getRun}). */
4708
+ listCheckpoints(runId: string): Promise<StepCheckpoint[]>;
4523
4709
  /**
4524
4710
  * Re-execute a run's body (replaying its checkpoints). This is the EXPLICIT entry point: besides
4525
4711
  * driving a live run, it re-drives a `failed` run — the manual retry (prefer {@link requeue}, which
@@ -4671,12 +4857,31 @@ declare class WorkflowEngine {
4671
4857
  * for part of it waits only for the remainder. With nothing reported, the full `timeoutMs` applies.
4672
4858
  */
4673
4859
  drain(timeoutMs?: number): Promise<void>;
4860
+ /**
4861
+ * The drain budget ran out with executions still in flight: release their recovery leases so
4862
+ * another instance re-drives those runs on its next recovery pass, instead of waiting out
4863
+ * `leaseMs` after this process exits. Each still-running turn is FENCED first, so whatever it
4864
+ * computes after this point is never written over the new owner's work (see settleRun). Its
4865
+ * completed steps are checkpointed, so the new owner replays them; a step still executing here
4866
+ * may run again there, exactly as after a crash. The release is owner-scoped where the store
4867
+ * supports it (only a lease this instance still holds is cleared). Best effort: never throws.
4868
+ */
4869
+ private releaseInflightLeases;
4674
4870
  /**
4675
4871
  * Cancel in-flight runs that have outlived their workflow's `executionTimeout`. Call it from the
4676
4872
  * timer poller alongside {@link resumeDueTimers}. A timed-out run is moved to `cancelled` with an
4677
4873
  * `execution_timeout` error (terminal, so a late step result can't resurrect it), AND its children
4678
4874
  * are cascaded exactly as an explicit {@link cancel} cascades them.
4679
4875
  *
4876
+ * WHICH RUNS. Every run not yet finished, counted from `createdAt`: `pending` and `blocked` as well
4877
+ * as `running` and `suspended`. A run nobody picks up (no worker on its queue) or nobody can run (no
4878
+ * worker with its capabilities) is as stuck as one that hangs mid-body, and the cap is the backstop
4879
+ * for exactly that — leaving them out meant a run that never started lived forever while one that
4880
+ * started and hung was cut off. Cancelling one a worker is picking up at that moment is safe: the
4881
+ * worker's settle only writes over a live status ({@link SETTLE_ELIGIBLE_STATUSES}), so it can't
4882
+ * bring the run back. `cancelling` is left alone on purpose — a compensating cancel's saga undo is
4883
+ * running, it ends `cancelled` by itself, and cutting it short would skip the undo.
4884
+ *
4680
4885
  * WHY THE TERMINAL WRITE IS DIRECT, not a call to {@link cancel}. Two reasons, both still standing:
4681
4886
  * the run must land with the `execution_timeout` error `cancel` knows nothing about (`cancel` writes
4682
4887
  * a plain `cancelled`, and the code is what a dashboard/alert distinguishes a timeout by), and this
@@ -4689,8 +4894,8 @@ declare class WorkflowEngine {
4689
4894
  * children kept running with the parent gone and nothing pointing at them — a silent orphan you
4690
4895
  * could only find by reading the runs table by hand. {@link cancelChildren} is the SAME recursive
4691
4896
  * walk `cancel` uses, so children of children go too, and it inherits that path's two guards:
4692
- * `cancel` returns early on a run that is already `completed`/`cancelled`/`dead` (a child that beat
4693
- * the sweep to the finish is never clobbered, and a re-cancel is a no-op), and it writes the
4897
+ * `cancel` returns early on a run that is already terminal (a child that beat the sweep to the
4898
+ * finish is never clobbered, and a re-cancel is a no-op), and it writes the
4694
4899
  * parent's terminal status BEFORE recursing, so a cyclic parent→child graph terminates on the
4695
4900
  * second visit instead of looping. Two pollers sweeping the same run concurrently therefore write
4696
4901
  * the same terminal state twice and cascade into already-cancelled children — idempotent, not
@@ -4707,6 +4912,27 @@ declare class WorkflowEngine {
4707
4912
  * replay from their checkpoints, so only the work that had not finished runs again.
4708
4913
  */
4709
4914
  recoverIncomplete(nowMs?: number): Promise<RunResult[]>;
4915
+ /** A run whose still-live lease is held by this very `instanceId` (see {@link reclaimOwnLease}). */
4916
+ private isOwnLiveLease;
4917
+ /**
4918
+ * Recover a run whose lease is still live but held by THIS `instanceId` and predates this process
4919
+ * (listed by {@link orphanedRuns}): the previous process with this stable id died without a
4920
+ * graceful shutdown (OOM, SIGKILL), so nothing is renewing that lease and waiting for it to expire
4921
+ * only delays the run. The lease is taken back with `renewRunLock` (a compare-and-set on the
4922
+ * owner; `tryLockRun` refuses a live lease), so the lease alone cannot fence a live execution in
4923
+ * THIS process from its own recovery: the in-process run gate does. A run with a
4924
+ * gate is executing (or about to) here and is skipped; otherwise a gate is held while the run is
4925
+ * recovered, so a resume landing meanwhile queues behind the recovery instead of running beside it.
4926
+ * The gate is released before the re-dispatch, which may resume the run on this instance.
4927
+ */
4928
+ private reclaimOwnLease;
4929
+ /**
4930
+ * One run of a {@link recoverIncomplete} pass: take its lease and decide on it. Resolves the
4931
+ * pass's result for it and whether it must be re-dispatched, or `undefined` when it was not ours.
4932
+ * `ownLease`: the run's live lease is this instance id's own, left by a previous process (see
4933
+ * {@link reclaimOwnLease}), so it is taken back by owner rather than acquired as a free one.
4934
+ */
4935
+ private recoverOrphan;
4710
4936
  /**
4711
4937
  * The runs {@link recoverIncomplete} should try to reclaim: incomplete runs whose lease is free or
4712
4938
  * expired, never the healthy ones a live turn is renewing. Every worker runs recovery on every
@@ -4715,6 +4941,10 @@ declare class WorkflowEngine {
4715
4941
  * ({@link StateStore.listOrphanedRuns}, bounded by {@link RECOVERY_BATCH}); else the full list is
4716
4942
  * filtered here, which still spares the probes. Shuffled, like the due-timer pass, so instances
4717
4943
  * recovering at once spread over the batch instead of contending for the same leases.
4944
+ *
4945
+ * Also listed: runs still leased by THIS `instanceId` with a lease taken before this process
4946
+ * booted ({@link ownLeaseCutoffMs}). With a stable `instanceId` (pinned to the pod identity), that
4947
+ * is the previous process, killed without a graceful shutdown; see {@link reclaimOwnLease}.
4718
4948
  */
4719
4949
  private orphanedRuns;
4720
4950
  /**
@@ -4947,6 +5177,13 @@ declare class WorkflowEngine {
4947
5177
  * side actually removes the row is the one that delivers, so a signal is never delivered twice.
4948
5178
  */
4949
5179
  signal(token: string, payload: unknown): Promise<RunResult | null>;
5180
+ /**
5181
+ * Wake the run parked on `token` with `payload`, if there is one; otherwise do nothing — unlike
5182
+ * {@link signal}, it never buffers. For a wake-up whose real payload is ALREADY buffered on the
5183
+ * token (an entity op, see `Entities.kick`): a run that isn't parked reads that buffer at its next
5184
+ * wait, so there is nothing to keep.
5185
+ */
5186
+ private wakeSignalWaiter;
4950
5187
  /**
4951
5188
  * Ensure a run exists for `runId`, then deliver a signal to it — atomically race-free thanks to
4952
5189
  * signal buffering: if the run is new (or busy / not yet waiting), the signal is buffered and
@@ -5165,8 +5402,35 @@ declare class WorkflowEngine {
5165
5402
  /** Checkpoint a step that failed terminally, so the failure point is visible (not just the run). */
5166
5403
  private failStep;
5167
5404
  /** Admission persists the wait atomically; never overwrite a cancellation after it returns. */
5405
+ /**
5406
+ * A run's first execution: `pending` -> `running`. A singleton run not yet admitted is stamped
5407
+ * {@link SINGLETON_TRACKED_TAG} in the same write, BEFORE it competes for a slot, so a run this
5408
+ * replica is about to admit or deny is never mistaken for a holder admitted by a replica older
5409
+ * than 0.73 (see `legacySingletonHolders`).
5410
+ */
5411
+ private markStarted;
5168
5412
  private singletonWaitResult;
5169
5413
  private execute;
5414
+ /**
5415
+ * Renew `runId`'s lease for as long as this execution holds it, and register it in
5416
+ * {@link executionLeases} so settles can check the zombie fence and `drain()` can release it.
5417
+ *
5418
+ * A renewal that returns `false` means the lease is gone: this turn stalled past `leaseMs` and
5419
+ * another instance reclaimed the run, so this executor is now a zombie. It is FENCED (`lost`): its
5420
+ * settles degrade to an echo of the store's state instead of clobbering the new owner's writes, and
5421
+ * its own lease release is skipped (it would free the new owner's lease). A renewal that THROWS (a
5422
+ * transient store error) is not evidence of a takeover, so it stays swallowed and the next
5423
+ * interval retries. A lease this execution released on purpose (`handedOff`) is not renewed, and a
5424
+ * renewal resolving after the execution ended (`done`) fences nothing.
5425
+ */
5426
+ private holdExecutionLease;
5427
+ /** Whether `runId`'s execution on this instance lost its lease (see {@link holdExecutionLease}). */
5428
+ private isFenced;
5429
+ /**
5430
+ * Mark `runId`'s lease as given away on purpose by its own execution (released mid-turn), so a
5431
+ * renewal that now fails is not read as a takeover.
5432
+ */
5433
+ private handOffLease;
5170
5434
  /**
5171
5435
  * Advance a remote (cross-SDK) workflow one turn: hand its history to the executor (which dispatches
5172
5436
  * a workflow task to the worker and awaits its replay) and apply the decision. Mirrors
@@ -5680,6 +5944,14 @@ declare class DurableWorkflow {
5680
5944
  */
5681
5945
  declare function parseDuration(duration: string | number): number;
5682
5946
 
5947
+ /**
5948
+ * Format marker of a run-history replay fixture (`{ version, run, checkpoints }`). Written by the
5949
+ * testing kit's `serializeRunHistory` and the CLI's `durable export`, checked by `parseRunHistory`.
5950
+ * Lives in core so both writers (which already depend on core, not on each other) share one value.
5951
+ * Bump it only when the fixture shape changes incompatibly.
5952
+ */
5953
+ declare const RUN_HISTORY_FIXTURE_VERSION = 1;
5954
+
5683
5955
  /**
5684
5956
  * Thrown inside a step to signal an unrecoverable failure: the engine will NOT retry it,
5685
5957
  * regardless of the step's `retries` setting, and fails the run immediately. Use it for
@@ -6086,6 +6358,15 @@ declare function fanPageEtag(group: string, stats: CheckpointStat[], query: FanP
6086
6358
  /** Whether an `If-None-Match` header value names `etag` (weak comparison, as RFC 9110 asks for). */
6087
6359
  declare function etagMatches(ifNoneMatch: string | undefined, etag: string): boolean;
6088
6360
 
6361
+ /**
6362
+ * Split a `ctx.webhook()` token (`wh:<runId>:<seq>`) into its run id and logical position, or `null`
6363
+ * for any other token. The run id may itself contain `:` (an entity run is `entity:<name>:<key>`), so
6364
+ * the seq is the LAST segment.
6365
+ */
6366
+ declare function parseWebhookToken(token: string): {
6367
+ runId: string;
6368
+ seq: number;
6369
+ } | null;
6089
6370
  /**
6090
6371
  * Resolve WHAT a suspended run is parked on from the token of the {@link SignalWaiter} it registered.
6091
6372
  * The token prefix carries the kind — no extra store lookup and no new persisted field. Used by the
@@ -6133,26 +6414,45 @@ interface PayloadCodec {
6133
6414
  encode(value: unknown): unknown;
6134
6415
  decode(value: unknown): unknown;
6135
6416
  }
6417
+ /** What {@link CodecStateStore} runs through the codec. */
6418
+ interface CodecStateStoreOptions {
6419
+ /**
6420
+ * `'payloads'` (default, the historical behaviour): run/step `input` + `output` only (plus a
6421
+ * schedule's `input` and buffered signal/event payloads, which are always encoded). **Know what
6422
+ * that leaves in the clear**: step `events` (everything step code passes to `ctx.log` and every
6423
+ * sub-step outcome) and the structured step/run `error` (message, stack, details). A deployment
6424
+ * sold as "encrypted payloads" still leaks whatever its steps log or throw.
6425
+ *
6426
+ * `'extended'`: also encode step `events`, step `error` and run `error`. Searchable metadata (ids,
6427
+ * status, workflow, tags, search attributes, namespace, origin, timestamps) stays clear — it must
6428
+ * remain queryable. ONLY enable on a FRESH table, or with a codec whose `decode` recognizes its own
6429
+ * ciphertext and passes other values through: rows written before the switch hold those fields as
6430
+ * plaintext, and a decode that can't tell would garble them.
6431
+ */
6432
+ coverage?: 'payloads' | 'extended';
6433
+ }
6136
6434
  /**
6137
- * A `StateStore` decorator that runs run/step **payloads** (input + output) through a
6138
- * {@link PayloadCodec} — encoded on write, decoded on read — so they're never stored in the clear.
6139
- * Adapter-agnostic: wrap any store. Searchable metadata (id, status, workflow, tags, timestamps) and
6140
- * the structured `error` are left untouched so the dashboard, queries, and recovery still work.
6435
+ * A `StateStore` decorator that runs run/step **payloads** through a {@link PayloadCodec} — encoded
6436
+ * on write, decoded on read — so they're never stored in the clear. Adapter-agnostic: wrap any
6437
+ * store. Searchable metadata (id, status, workflow, tags, timestamps) is left untouched so the
6438
+ * dashboard, queries, and recovery still work. See {@link CodecStateStoreOptions.coverage} for
6439
+ * exactly which fields are covered — the default covers `input`/`output` only.
6141
6440
  *
6142
6441
  * ```ts
6143
- * const store = new CodecStateStore(new TypeOrmStateStore(ds), aesCodec);
6442
+ * const store = new CodecStateStore(new TypeOrmStateStore(ds), aesCodec, { coverage: 'extended' });
6144
6443
  * ```
6145
6444
  */
6146
6445
  declare class CodecStateStore implements StateStore {
6147
6446
  private readonly inner;
6148
6447
  private readonly codec;
6448
+ private readonly extended;
6149
6449
  /** Atomic claims touch only searchable metadata and bypass payload encoding. */
6150
6450
  readonly tryAdmitSingleton?: (runId: string, tag: string, workflow: string, limit: number, retryWakeAt?: number) => Promise<boolean>;
6151
6451
  /**
6152
6452
  * Forwarded verbatim — a facet cell counts `status`/`origin`, neither of which the codec touches
6153
- * (it encodes payloads: input/output/error). Bound as a PROPERTY, and only when the inner store
6154
- * actually aggregates, so `store.runFacets?.()` still reports absence through the wrapper instead
6155
- * of resolving to a silently wrong empty result.
6453
+ * (it encodes payloads: input/output, plus events/error under `extended` coverage). Bound as a
6454
+ * PROPERTY, and only when the inner store actually aggregates, so `store.runFacets?.()` still
6455
+ * reports absence through the wrapper instead of resolving to a silently wrong empty result.
6156
6456
  */
6157
6457
  readonly runFacets?: (query: RunFacetQuery) => Promise<RunFacetRow[]>;
6158
6458
  /**
@@ -6166,7 +6466,7 @@ declare class CodecStateStore implements StateStore {
6166
6466
  readonly deleteRuns?: (runIds: string[]) => Promise<void>;
6167
6467
  /** Decodes the runs like {@link listIncompleteRuns}. Bound only when the inner store has it, so
6168
6468
  * the engine's list-and-filter fallback still kicks in through the wrapper. */
6169
- readonly listOrphanedRuns?: (nowMs: number, limit: number, namespace?: string) => Promise<WorkflowRun[]>;
6469
+ readonly listOrphanedRuns?: (nowMs: number, limit: number, namespace?: string, ownedBy?: OwnedLeaseReclaim) => Promise<WorkflowRun[]>;
6170
6470
  /** Encodes the patch like {@link updateRun}. Bound only when the inner store has it, so the
6171
6471
  * engine's read-then-write fallback still kicks in through the wrapper. */
6172
6472
  readonly updateRunIf?: (runId: string, expectedStatuses: RunStatus[], patch: Partial<WorkflowRun>) => Promise<boolean>;
@@ -6206,7 +6506,7 @@ declare class CodecStateStore implements StateStore {
6206
6506
  readonly updateSchedule?: (id: string, patch: Partial<Omit<ScheduleRecord, 'id' | 'createdAt'>>, expectedNextFireAt?: number | null) => Promise<boolean>;
6207
6507
  readonly deleteSchedule?: (id: string) => Promise<boolean>;
6208
6508
  readonly listSchedules?: (query: ScheduleQuery) => Promise<ScheduleRecord[]>;
6209
- constructor(inner: StateStore, codec: PayloadCodec);
6509
+ constructor(inner: StateStore, codec: PayloadCodec, options?: CodecStateStoreOptions);
6210
6510
  private enc;
6211
6511
  private dec;
6212
6512
  private encRun;
@@ -6232,7 +6532,7 @@ declare class CodecStateStore implements StateStore {
6232
6532
  listPendingRuns(limit: number, namespace?: string): Promise<WorkflowRun[]>;
6233
6533
  listDueTimers(nowMs: number, namespace?: string, limit?: number): Promise<WorkflowRun[]>;
6234
6534
  tryLockRun(runId: string, owner: string, leaseUntilMs: number, nowMs: number): Promise<boolean>;
6235
- releaseRunLock(runId: string): Promise<void>;
6535
+ releaseRunLock(runId: string, owner?: string): Promise<void>;
6236
6536
  renewRunLock(runId: string, owner: string, leaseUntilMs: number): Promise<boolean>;
6237
6537
  putSignalWaiter(waiter: SignalWaiter): Promise<void>;
6238
6538
  takeSignalWaiter(token: string): Promise<SignalWaiter | null>;
@@ -6669,12 +6969,12 @@ declare class InMemoryStateStore implements StateStore {
6669
6969
  saveCheckpoint(checkpoint: StepCheckpoint): Promise<void>;
6670
6970
  saveCheckpointIfPending(checkpoint: StepCheckpoint): Promise<boolean>;
6671
6971
  saveCheckpointsIfPending(checkpoints: StepCheckpoint[]): Promise<boolean[]>;
6672
- listOrphanedRuns(nowMs: number, limit: number, namespace?: string): Promise<WorkflowRun[]>;
6972
+ listOrphanedRuns(nowMs: number, limit: number, namespace?: string, ownedBy?: OwnedLeaseReclaim): Promise<WorkflowRun[]>;
6673
6973
  listIncompleteRuns(namespace?: string): Promise<WorkflowRun[]>;
6674
6974
  listPendingRuns(limit: number, namespace?: string): Promise<WorkflowRun[]>;
6675
6975
  listDueTimers(nowMs: number, namespace?: string, limit?: number): Promise<WorkflowRun[]>;
6676
6976
  tryLockRun(runId: string, owner: string, leaseUntilMs: number, nowMs: number): Promise<boolean>;
6677
- releaseRunLock(runId: string): Promise<void>;
6977
+ releaseRunLock(runId: string, owner?: string): Promise<void>;
6678
6978
  renewRunLock(runId: string, owner: string, leaseUntilMs: number): Promise<boolean>;
6679
6979
  putSignalWaiter(waiter: SignalWaiter): Promise<void>;
6680
6980
  takeSignalWaiter(token: string): Promise<SignalWaiter | null>;
@@ -6769,7 +7069,42 @@ declare class InMemoryTransport implements Transport, ControlPlane {
6769
7069
 
6770
7070
  /** Reserved engine metadata: a durable singleton slot, independent of the execution lease. */
6771
7071
  declare const SINGLETON_ADMITTED_TAG = "durable:singleton:admitted";
7072
+ /**
7073
+ * Reserved engine metadata: this not-yet-admitted run's admission is decided by the tag scheme, so
7074
+ * it holds no slot unless it carries {@link SINGLETON_ADMITTED_TAG}. Stamped on a run's first
7075
+ * execution (`pending` -> `running`) and on every denial. An untagged run WITHOUT it that a
7076
+ * replica has executed was executed by a replica older than 0.73: see
7077
+ * {@link legacySingletonHolders}. Admission and terminal settlement remove it.
7078
+ */
7079
+ declare const SINGLETON_TRACKED_TAG = "durable:singleton:tracked";
7080
+ /** Tags only the engine/store may write; stripped from user-supplied start tags. */
7081
+ declare const SINGLETON_RESERVED_TAGS: readonly string[];
6772
7082
  declare const SINGLETON_ACTIVE_STATUSES: RunStatus[];
7083
+ /** `tags` without the engine's singleton admission metadata. */
7084
+ declare function withoutSingletonMarkers(tags: string[] | undefined): string[] | undefined;
7085
+ /** `tags` carrying {@link SINGLETON_TRACKED_TAG} (unchanged when admitted or already tracked). */
7086
+ declare function withSingletonTracked(tags: string[] | undefined): string[];
7087
+ /**
7088
+ * The runs other than `runId` that may hold a slot of this key WITHOUT carrying
7089
+ * {@link SINGLETON_ADMITTED_TAG}: holders admitted by a replica older than 0.73, during a rolling
7090
+ * upgrade that mixes old and new replicas.
7091
+ *
7092
+ * Old replicas admit by a scan: a run may execute when it is among the `limit` oldest
7093
+ * `running`/`suspended`/`cancelling` runs sharing the key, by `(createdAt, id)`, and they write no
7094
+ * tag. Among those statuses, an untagged run counts as a legacy holder when either:
7095
+ *
7096
+ * - it lacks {@link SINGLETON_TRACKED_TAG}. A new replica stamps that marker on a run's first
7097
+ * execution and on every denial, so an untagged executed run without it was executed (admitted)
7098
+ * by an old replica. A denial alone cannot be told apart from a holder (both old and new denials
7099
+ * park the run `suspended` with a retry `wakeAt`, exactly like a holder sleeping in `ctx.sleep`),
7100
+ * which is why the marker exists. Waiters an old replica parked count too until a new replica
7101
+ * re-checks them (one retry, ~1s), which only delays, never over-admits.
7102
+ * - it sits inside the old scan's own window (the `limit` oldest of those runs). An old replica can
7103
+ * admit a run a new replica had marked, without clearing the marker; the window is what it
7104
+ * admitted it on. Without old replicas this never changes a `limit: 1` decision (a run inside the
7105
+ * window is the head of the FIFO, admitted next anyway); with a larger limit it can only delay one.
7106
+ */
7107
+ declare function legacySingletonHolders(active: WorkflowRun[], runId: string, limit: number): WorkflowRun[];
6773
7108
  /** Call only inside a store's atomic admission transaction/critical section. */
6774
7109
  declare function singletonAdmissionTags(runs: WorkflowRun[], runId: string, tag: string, workflow: string, limit: number): string[] | null;
6775
7110
  /** Terminal runs release admission, including when later resumed directly rather than requeued. */
@@ -6778,7 +7113,8 @@ declare function clearTerminalSingletonAdmission(runId: string, patch: Partial<W
6778
7113
  declare function singletonAdmissionDenialPatch(runs: WorkflowRun[], runId: string, tag: string, workflow: string, retryWakeAt?: number): {
6779
7114
  status: 'suspended';
6780
7115
  wakeAt: number;
7116
+ tags: string[];
6781
7117
  updatedAt: Date;
6782
7118
  } | undefined;
6783
7119
 
6784
- export { type AccumulatorHost, type Admission, type AdmissionBackend, type AdmissionItem, type AllOptions, type AllSettledOptions, type AllStepsOptions, type AllStepsSettledOptions, type AnnouncedWorkflow, type AnnouncementEvidence, type AttributeFilter, type AttributeOp, type AttributePredicateOperand, type AttributeValue, type BackoffStrategy, type BlockedDispatch, type BlockedResolution, CHILD_EDGE_PREFIXES, CONTROL_FLOW_SIGNAL, CURRENT_PROTOCOL_VERSION, type CapabilityRequirement, type CheckpointAggregatingStore, type CheckpointNameKind, type CheckpointQuery, type CheckpointStat, type ChildCallOptions, type ChildWait, CodecStateStore, type ConcurrencyConfig, ConcurrencyLimitError, type ConcurrencyQuota, ContinueAsNew, type ControlMessage, type ControlPlane, DEFAULT_CONCURRENCY_STATUSES, DEFAULT_PARTITION, DURABLE_OPTIONS, DURABLE_OPTIONS_CANONICAL, DURABLE_STEP_CONFIG, DURABLE_STEP_NAME, type Disagreement, type DispatchDiagnostics, type DispatchPlan, type DurableExecution, type DurableExecutionWrapper, type DurableTopology, type DurableWebhook, DurableWorkflow, type DynamicWorkflowCtx, ENGINE_MINTED_TAG_PREFIXES, EVENT_BUFFER_SCAN_LIMIT, EVENT_TOKEN_PREFIX, type EngineEvent, type EngineEventType, type EngineListener, Entities, type EntityConfig, type EntityHandler, type EntityHost, EventAccumulators, type EventBatchConfig, FAN_SUMMARY_FAILURES, type FanJoin, type FanPage, type FanPageQuery, type FanSummary, type FanWait, FatalError, GatherError, type GatherItemFailure, type GroupHealth, HANDOFF_SEQ_BASE, type Heartbeat, type HeartbeatSighting, type HeartbeatStatus, type HistoryEvent, InMemoryAdmissionBackend, InMemoryStateStore, InMemoryTransport, type InferSearchAttributes, LEGACY_V1_CAPABILITIES, LEGACY_V1_PROTOCOL, type MetricsCollector, type MetricsSnapshot, type NamedTransport, type NegotiateOptions, type NegotiationOutcome, type NegotiationReason, type NegotiationResult, NestedWorkflowCallError, NonDeterminismError, type OnErrorInput, type OnErrorRoute, type PartitionSighting, type PayloadCodec, type QueueConfig, QueueController, RUN_VALUE_FACET_LIMIT, RUN_VALUE_FACET_SCAN, type RawWorkerDescriptor, RemoteStepError, RemoteStepTimeout, type RemoteTask, RemoteWorkflowExecutor, RemoteWorkflowTimeout, type RetentionPolicy, type RoutableDispatch, type RoutableResolution, type RoutingResolution, type RunAttributeRow, type RunDetail, type RunDetailOptions, type RunDispatcher, type RunFacetQuery, type RunFacetRow, RunGateway, type RunListItem, type RunQuery, type RunReply, type RunReplyResult, type RunRequest, type RunRequestKind, type RunResult, type RunSchedulesOptions, type RunScope, type RunStatus, type RunValueAxis, type RunValueFacetOptions, type RunValueFacetOrder, type RunValueFacetRow, type RunWaiting, SINGLETON_ACTIVE_STATUSES, SINGLETON_ADMITTED_TAG, STATE_STORE, STATE_STORE_CANONICAL, SUMMARY_CHILD_LIMIT, type ScalarAttributeFilter, ScheduleAlreadyExistsError, ScheduleClient, type ScheduleClientOptions, type ScheduleDescription, type ScheduleHost, type ScheduleListQuery, ScheduleNotFoundError, type ScheduleOptions, type ScheduleQuery, type ScheduleRecord, type ScheduledWorkflow, type SearchAttributes, type SearchAttributesSchema, type Settled, SignalTimeoutError, type SignalWaiter, type SingletonConfig, SingletonQueueFullError, StandardSchemaV1, type StartOptions, type StartRunMessage, type StateStore, type StepCheckpoint, type StepConfig, type StepDef, type StepDispatchOpts, type StepError, type StepEvent, type StepHandler, type StepInterceptor, type StepInvocation, type StepKind, type StepLogger, type StepOptions, type StepRef, type StepResult, type StepScope, type StepUndo, type StoreTransaction, type SubProcessHandle, TERMINAL_RUN_STATUSES, TRANSPORT, TRANSPORT_CANONICAL, type TenantEvent, type Transport, type UndoOf, type UpdateResult, type UpdateValidator, VERSION_UNDECLARED_TAG, WORKFLOW_NAME_KEY, type WireDates, type WorkerAdjust, type WorkerConcurrencyStatus, type WorkerDescriptor, type WorkerHeartbeat, type WorkerLifecycle, type WorkerStatus, type WorkflowAnnouncement, WorkflowBlocked, type WorkflowClass, type WorkflowCommand, type WorkflowCtx, type WorkflowDecision, type WorkflowDirectory, WorkflowEngine, type WorkflowEngineDeps, type WorkflowExecutor, type WorkflowHandler, type WorkflowInputOf, type WorkflowOutputOf, type WorkflowRef, type WorkflowRegistration, type WorkflowRun, type WorkflowStartClient, type WorkflowStepEvent, WorkflowSuspended, type WorkflowTask, aggregateAnnouncements, aggregatesCheckpoints, announcementsOf, applyAttributeQuery, assertConcurrency, assertRoutes, attributeColumnFor, attributeOperand, attributePredicateOperands, axisIsRunColumn, bindWorkflowClass, breakpointToken, buildWorkflowDirectory, canRoute, capableWorkers, checkpointNameKind, checkpointStatsOf, childIdsOf, classifyWaiterToken, clearDurableExecutionWrappers, clearTerminalSingletonAdmission, codeAndDetails, codeOf, collectMetrics, concurrencyTag, controlPlaneDescriptor, countRuns, coveredTokens, createStepLogger, currentStep, currentStepScope, currentWorkflowCtx, debug, describeWorker, descriptorHash, detailsOf, error, etagMatches, eventMatchOf, eventMatches, eventNameOf, eventPrefix, eventToken, facetOrigin, fanPageBounds, fanPageEtag, foldedCount, handoffHandlerId, handoffName, hasDurableExecutionWrappers, heartbeatStatus, indexWaitersByRun, info, isEngineMintedTag, isEventToken, isFailedMember, isLegacyDescriptor, isNonEmptyRunScope, isWorkflowControlFlowSignal, listSignalWaitersOfRuns, liveHandoff, log, matchesAttributes, mergeRunFacetRows, mergeRunValueFacetRows, missingCapabilities, negotiate, nextCronFireMs, normalizeAttributeRows, normalizeDescriptor, observedAnnouncements, onErrorRunId, pageFan, pageFanFromStore, parentRunIdOf, parseDuration, partitionOfToken, planDispatch, prevCronFireMs, queryCheckpointsOf, readSearchAttributes, requiredCapabilities, resolveConcurrency, resolveRouting, resolveRunWaiting, retiredHandoffName, routeFor, runDetailEtag, runDurableExecution, runInStepLogger, runInStepScope, runInWorkflowCtx, runOutsideWorkflowCtx, runSchedules, runStepHandler, runValueFacetsFromRuns, sanitizeQueueToken, scheduledRunId, singletonAdmissionDenialPatch, singletonAdmissionTags, sqlComparator, stepConfigOf, stepId, stepNameOf, sub, subEvent, subProcess, summarizeFan, summarizeRunFromStore, summarizeTimeline, tenantGroup, useDurableExecution, warn, workflowName };
7120
+ export { type AccumulatorHost, type Admission, type AdmissionBackend, type AdmissionItem, type AllOptions, type AllSettledOptions, type AllStepsOptions, type AllStepsSettledOptions, type AnnouncedWorkflow, type AnnouncementEvidence, type AttributeFilter, type AttributeOp, type AttributePredicateOperand, type AttributeValue, type BackoffStrategy, type BlockedDispatch, type BlockedResolution, CHILD_EDGE_PREFIXES, CONTROL_FLOW_SIGNAL, CURRENT_PROTOCOL_VERSION, type CapabilityRequirement, type CheckpointAggregatingStore, type CheckpointNameKind, type CheckpointQuery, type CheckpointStat, type ChildCallOptions, type ChildWait, CodecStateStore, type CodecStateStoreOptions, type ConcurrencyConfig, ConcurrencyLimitError, type ConcurrencyQuota, ContinueAsNew, type ControlMessage, type ControlPlane, DEFAULT_CONCURRENCY_STATUSES, DEFAULT_PARTITION, DEFAULT_STALLED_AFTER_MS, DURABLE_OPTIONS, DURABLE_OPTIONS_CANONICAL, DURABLE_STEP_CONFIG, DURABLE_STEP_NAME, type Disagreement, type DispatchDiagnostics, type DispatchPlan, type DurableExecution, type DurableExecutionWrapper, type DurableTopology, type DurableWebhook, DurableWorkflow, type DynamicWorkflowCtx, ENGINE_MINTED_TAG_PREFIXES, ENTITY_WORKFLOW, EVENT_BUFFER_SCAN_LIMIT, EVENT_TOKEN_PREFIX, type EngineEvent, type EngineEventType, type EngineListener, Entities, type EntityConfig, type EntityHandler, type EntityHost, type EntityWorkflowHost, EventAccumulators, type EventBatchConfig, FAN_SUMMARY_FAILURES, type FanJoin, type FanPage, type FanPageQuery, type FanSummary, type FanWait, FatalError, type FindStalledRunsOptions, GatherError, type GatherItemFailure, type GroupHealth, HANDOFF_SEQ_BASE, type Heartbeat, type HeartbeatSighting, type HeartbeatStatus, type HistoryEvent, InMemoryAdmissionBackend, InMemoryStateStore, InMemoryTransport, type InferSearchAttributes, LEGACY_V1_CAPABILITIES, LEGACY_V1_PROTOCOL, type ListStalledRunsOptions, type MetricsCollector, type MetricsSnapshot, type NamedTransport, type NegotiateOptions, type NegotiationOutcome, type NegotiationReason, type NegotiationResult, NestedWorkflowCallError, NonDeterminismError, type OnErrorInput, type OnErrorRoute, type OwnedLeaseReclaim, type PartitionSighting, type PayloadCodec, type QueueConfig, QueueController, RUN_HISTORY_FIXTURE_VERSION, RUN_VALUE_FACET_LIMIT, RUN_VALUE_FACET_SCAN, type RawWorkerDescriptor, RemoteStepError, RemoteStepTimeout, type RemoteTask, RemoteWorkflowExecutor, RemoteWorkflowTimeout, type RetentionPolicy, type RoutableDispatch, type RoutableResolution, type RoutingResolution, type RunAttributeRow, type RunDetail, type RunDetailOptions, type RunDispatcher, type RunFacetQuery, type RunFacetRow, RunGateway, type RunListItem, type RunQuery, type RunReply, type RunReplyResult, type RunRequest, type RunRequestKind, type RunResult, type RunSchedulesOptions, type RunScope, type RunStatus, type RunValueAxis, type RunValueFacetOptions, type RunValueFacetOrder, type RunValueFacetRow, type RunWaiting, SINGLETON_ACTIVE_STATUSES, SINGLETON_ADMITTED_TAG, SINGLETON_RESERVED_TAGS, SINGLETON_TRACKED_TAG, STATE_STORE, STATE_STORE_CANONICAL, SUMMARY_CHILD_LIMIT, type ScalarAttributeFilter, ScheduleAlreadyExistsError, ScheduleClient, type ScheduleClientOptions, type ScheduleDescription, type ScheduleHost, type ScheduleListQuery, ScheduleNotFoundError, type ScheduleOptions, type ScheduleQuery, type ScheduleRecord, type ScheduledWorkflow, type SearchAttributes, type SearchAttributesSchema, type Settled, SignalTimeoutError, type SignalWaiter, type SingletonConfig, SingletonQueueFullError, type StalePendingStep, type StalledRunInfo, StandardSchemaV1, type StartOptions, type StartRunMessage, type StateStore, type StepCheckpoint, type StepConfig, type StepDef, type StepDispatchOpts, type StepError, type StepEvent, type StepHandler, type StepInterceptor, type StepInvocation, type StepKind, type StepLogger, type StepOptions, type StepRef, type StepResult, type StepScope, type StepUndo, type StoreTransaction, type SubProcessHandle, TERMINAL_RUN_STATUSES, TRANSPORT, TRANSPORT_CANONICAL, type TenantEvent, type Transport, type UndoOf, type UpdateResult, type UpdateValidator, VERSION_UNDECLARED_TAG, WORKFLOW_NAME_KEY, type WireDates, type WorkerAdjust, type WorkerConcurrencyStatus, type WorkerDescriptor, type WorkerHeartbeat, type WorkerLifecycle, type WorkerStatus, type WorkflowAnnouncement, WorkflowBlocked, type WorkflowClass, type WorkflowCommand, type WorkflowCtx, type WorkflowDecision, type WorkflowDirectory, WorkflowEngine, type WorkflowEngineDeps, type WorkflowExecutor, type WorkflowHandler, type WorkflowInputOf, type WorkflowOutputOf, type WorkflowRef, type WorkflowRegistration, type WorkflowRun, type WorkflowStartClient, type WorkflowStepEvent, WorkflowSuspended, type WorkflowTask, aggregateAnnouncements, aggregatesCheckpoints, announcementsOf, applyAttributeQuery, assertConcurrency, assertRoutes, attributeColumnFor, attributeOperand, attributePredicateOperands, axisIsRunColumn, bindWorkflowClass, breakpointToken, buildWorkflowDirectory, canRoute, capableWorkers, checkpointNameKind, checkpointStatsOf, childIdsOf, classifyWaiterToken, clearDurableExecutionWrappers, clearTerminalSingletonAdmission, codeAndDetails, codeOf, collectMetrics, concurrencyTag, controlPlaneDescriptor, countRuns, coveredTokens, createStepLogger, currentStep, currentStepScope, currentWorkflowCtx, debug, describeWorker, descriptorHash, detailsOf, error, etagMatches, eventMatchOf, eventMatches, eventNameOf, eventPrefix, eventToken, facetOrigin, fanPageBounds, fanPageEtag, findStalledRuns, foldedCount, handoffHandlerId, handoffName, hasDurableExecutionWrappers, heartbeatStatus, indexWaitersByRun, info, isEngineMintedTag, isEventToken, isFailedMember, isLegacyDescriptor, isNonEmptyRunScope, isWorkflowControlFlowSignal, legacySingletonHolders, listSignalWaitersOfRuns, liveHandoff, log, matchesAttributes, mergeRunFacetRows, mergeRunValueFacetRows, missingCapabilities, negotiate, nextCronFireMs, normalizeAttributeRows, normalizeDescriptor, observedAnnouncements, onErrorRunId, pageFan, pageFanFromStore, parentRunIdOf, parseDuration, parseWebhookToken, partitionOfToken, planDispatch, poolNamespace, prevCronFireMs, queryCheckpointsOf, readSearchAttributes, requiredCapabilities, resolveConcurrency, resolveRouting, resolveRunWaiting, retiredHandoffName, routeFor, runDetailEtag, runDurableExecution, runInStepLogger, runInStepScope, runInWorkflowCtx, runOutsideWorkflowCtx, runSchedules, runStepHandler, runValueFacetsFromRuns, sanitizeQueueToken, scheduledRunId, singletonAdmissionDenialPatch, singletonAdmissionTags, sqlComparator, stepConfigOf, stepId, stepNameOf, sub, subEvent, subProcess, summarizeFan, summarizeRunFromStore, summarizeTimeline, tenantGroup, useDurableExecution, warn, withSingletonTracked, withoutSingletonMarkers, workflowName };