@lostgradient/weft 0.12.0 → 0.14.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 (226) hide show
  1. package/README.md +1 -1
  2. package/dist/cli/api.d.ts +2 -0
  3. package/dist/cli/api.js +3 -4
  4. package/dist/cli/generated/operation-catalog.snapshot.json +508 -12
  5. package/dist/cli/generated/operation-client.generated.d.ts +118 -10
  6. package/dist/cli/generated/operation-client.generated.js +74 -1
  7. package/dist/cli/help-text.d.ts +3 -3
  8. package/dist/cli/help-text.js +4 -4
  9. package/dist/cli/operation-catalog-snapshot.d.ts +12 -3
  10. package/dist/cli/operation-catalog-snapshot.js +14 -5
  11. package/dist/cli/operation-client-runtime.d.ts +29 -0
  12. package/dist/cli/schedule.js +1 -3
  13. package/dist/cli/serve-registrations.d.ts +3 -3
  14. package/dist/cli/serve-registrations.js +2 -2
  15. package/dist/cli/shutdown.d.ts +11 -0
  16. package/dist/cli/shutdown.js +25 -0
  17. package/dist/cli/validate.d.ts +1 -1
  18. package/dist/cli/version-check.d.ts +1 -1
  19. package/dist/cli/version-check.js +1 -1
  20. package/dist/cli-main.js +10 -29
  21. package/dist/client/client-storage.d.ts +24 -0
  22. package/dist/client/client-storage.js +14 -0
  23. package/dist/client/handle-delegation.d.ts +3 -3
  24. package/dist/client/handle-delegation.js +2 -2
  25. package/dist/client/http-client-requests.d.ts +5 -3
  26. package/dist/client/http-client-requests.js +20 -2
  27. package/dist/client/http-client-storage.d.ts +3 -0
  28. package/dist/client/http-client-storage.js +82 -0
  29. package/dist/client/http-client.d.ts +9 -6
  30. package/dist/client/http-client.js +13 -18
  31. package/dist/client/http-operations.d.ts +3 -1
  32. package/dist/client/http-operations.js +77 -1
  33. package/dist/client/http-request.d.ts +20 -14
  34. package/dist/client/http-request.js +21 -31
  35. package/dist/client/in-process-operations.d.ts +2 -2
  36. package/dist/client/in-process-operations.js +2 -2
  37. package/dist/client/index.d.ts +5 -1
  38. package/dist/client/index.js +13 -2
  39. package/dist/client/interface.d.ts +26 -26
  40. package/dist/client/local.d.ts +9 -6
  41. package/dist/client/local.js +9 -4
  42. package/dist/client/search-params.js +10 -6
  43. package/dist/client/start-body.d.ts +3 -1
  44. package/dist/client/start-body.js +9 -0
  45. package/dist/core/bulk-workflow-filter.d.ts +2 -1
  46. package/dist/core/bulk-workflow-filter.js +5 -1
  47. package/dist/core/context/parallel-operations.d.ts +0 -2
  48. package/dist/core/context/parallel-operations.js +0 -7
  49. package/dist/core/engine/async-activity-records.d.ts +12 -1
  50. package/dist/core/engine/async-activity-records.js +81 -2
  51. package/dist/core/engine/bulk-operations-purge.js +16 -1
  52. package/dist/core/engine/bulk-operations-shared.js +2 -0
  53. package/dist/core/engine/callback-checkpoint-persistence.d.ts +2 -0
  54. package/dist/core/engine/callback-checkpoint-persistence.js +6 -3
  55. package/dist/core/engine/callback-creators-schedule.d.ts +2 -1
  56. package/dist/core/engine/callback-creators-schedule.js +3 -3
  57. package/dist/core/engine/callback-creators.js +4 -22
  58. package/dist/core/engine/checkpoint-io.d.ts +1 -1
  59. package/dist/core/engine/checkpoint-reads.js +11 -1
  60. package/dist/core/engine/child-workflow.js +15 -6
  61. package/dist/core/engine/construction.js +3 -0
  62. package/dist/core/engine/disposal.js +2 -0
  63. package/dist/core/engine/engine-internal-types.d.ts +4 -1
  64. package/dist/core/engine/fenced-write.d.ts +5 -3
  65. package/dist/core/engine/finalizer-status.d.ts +10 -0
  66. package/dist/core/engine/finalizer-status.js +82 -0
  67. package/dist/core/engine/index.d.ts +26 -2
  68. package/dist/core/engine/index.js +71 -8
  69. package/dist/core/engine/internals.d.ts +3 -0
  70. package/dist/core/engine/lease-health.d.ts +64 -0
  71. package/dist/core/engine/lease-health.js +0 -0
  72. package/dist/core/engine/lease-manager.d.ts +4 -2
  73. package/dist/core/engine/lease-manager.js +32 -4
  74. package/dist/core/engine/lifecycle/recovered-services.js +0 -2
  75. package/dist/core/engine/lifecycle/shared.d.ts +11 -8
  76. package/dist/core/engine/lifecycle/start-batch.js +12 -0
  77. package/dist/core/engine/lifecycle/start.d.ts +1 -1
  78. package/dist/core/engine/lifecycle/start.js +34 -5
  79. package/dist/core/engine/operations-coordination.d.ts +1 -12
  80. package/dist/core/engine/operations-coordination.js +58 -11
  81. package/dist/core/engine/operations-speculate.d.ts +1 -1
  82. package/dist/core/engine/operations-speculate.js +19 -5
  83. package/dist/core/engine/parallel-dispatch.d.ts +1 -1
  84. package/dist/core/engine/parallel-dispatch.js +1 -1
  85. package/dist/core/engine/registration.js +14 -0
  86. package/dist/core/engine/review-list-entries.d.ts +1 -1
  87. package/dist/core/engine/review-list-entries.js +6 -30
  88. package/dist/core/engine/schedule-handle.d.ts +4 -4
  89. package/dist/core/engine/schedule-handle.js +2 -2
  90. package/dist/core/engine/schedule-overlap.d.ts +11 -0
  91. package/dist/core/engine/schedule-overlap.js +50 -0
  92. package/dist/core/engine/schedule-run.d.ts +11 -3
  93. package/dist/core/engine/schedule-run.js +27 -4
  94. package/dist/core/engine/schedule-timer.js +10 -1
  95. package/dist/core/engine/schedules.d.ts +5 -4
  96. package/dist/core/engine/schedules.js +62 -56
  97. package/dist/core/engine/state-utilities.js +1 -1
  98. package/dist/core/engine/storage-io.d.ts +12 -0
  99. package/dist/core/engine/storage-io.js +49 -10
  100. package/dist/core/engine/termination/finalizer-claim.d.ts +8 -6
  101. package/dist/core/engine/termination/finalizer-claim.js +2 -1
  102. package/dist/core/engine/termination/finalizer.js +10 -14
  103. package/dist/core/engine/timeline-coordinator-constants.d.ts +3 -0
  104. package/dist/core/engine/timeline-coordinator-constants.js +1 -0
  105. package/dist/core/engine/timeline-coordinator-detail.d.ts +13 -0
  106. package/dist/core/engine/timeline-coordinator-detail.js +76 -0
  107. package/dist/core/engine/validation/schedule-options.d.ts +8 -1
  108. package/dist/core/engine/validation/schedule-options.js +18 -0
  109. package/dist/core/engine/validation/schedule.d.ts +1 -1
  110. package/dist/core/engine/validation/schedule.js +27 -3
  111. package/dist/core/engine/validation.js +66 -2
  112. package/dist/core/engine/workflow-state-stream.d.ts +5 -1
  113. package/dist/core/engine/workflow-state-stream.js +37 -14
  114. package/dist/core/events/schedule-events.d.ts +3 -4
  115. package/dist/core/events/workflow-events.d.ts +2 -1
  116. package/dist/core/list-filter-validation.d.ts +3 -0
  117. package/dist/core/list-filter-validation.js +11 -0
  118. package/dist/core/registry-snapshot.d.ts +32 -0
  119. package/dist/core/registry-snapshot.js +28 -0
  120. package/dist/core/review/index.d.ts +91 -4
  121. package/dist/core/review/index.js +29 -0
  122. package/dist/core/types/activity.d.ts +52 -5
  123. package/dist/core/types/bulk.d.ts +1 -0
  124. package/dist/core/types/list-options.d.ts +6 -0
  125. package/dist/core/types/options.d.ts +6 -5
  126. package/dist/core/types/reviews.d.ts +2 -2
  127. package/dist/core/types/schedules.d.ts +45 -2
  128. package/dist/core/types/services-resolution.d.ts +5 -5
  129. package/dist/core/types/state.d.ts +64 -0
  130. package/dist/core/types/workflow-log.d.ts +3 -2
  131. package/dist/core/types/workflow-observability.d.ts +50 -0
  132. package/dist/core/types/workflow-observability.js +0 -0
  133. package/dist/core/types/workflow-registry.d.ts +7 -0
  134. package/dist/core/types.d.ts +1 -0
  135. package/dist/core/types.js +1 -0
  136. package/dist/diagnostics/validate.d.ts +9 -30
  137. package/dist/diagnostics/validate.js +83 -21
  138. package/dist/diagnostics/version-check.d.ts +2 -2
  139. package/dist/http.js +2 -2
  140. package/dist/index.d.ts +4 -3
  141. package/dist/indexeddb.js +1 -1
  142. package/dist/server/access-policy-metadata.d.ts +92 -0
  143. package/dist/server/access-policy-metadata.js +78 -0
  144. package/dist/server/fault-to-http.d.ts +3 -7
  145. package/dist/server/fault-to-http.js +2 -34
  146. package/dist/server/handler/index.js +1 -1
  147. package/dist/server/handler/route-dispatch.d.ts +10 -3
  148. package/dist/server/handler/route-dispatch.js +19 -4
  149. package/dist/server/index.d.ts +1 -1
  150. package/dist/server/index.js +1 -0
  151. package/dist/server/interactive-operations.js +2 -0
  152. package/dist/server/openapi-error-responses.js +41 -4
  153. package/dist/server/openapi.d.ts +3 -1
  154. package/dist/server/openapi.js +4 -0
  155. package/dist/server/openrpc-document-schema.d.ts +64 -0
  156. package/dist/server/openrpc-document-schema.js +6 -26
  157. package/dist/server/openrpc.d.ts +4 -0
  158. package/dist/server/openrpc.js +9 -33
  159. package/dist/server/operation-catalog/index.d.ts +1 -1
  160. package/dist/server/operation-catalog/raise-fault.d.ts +2 -1
  161. package/dist/server/operation-catalog/types.d.ts +2 -1
  162. package/dist/server/operation-fault.d.ts +22 -8
  163. package/dist/server/operation-fault.js +65 -13
  164. package/dist/server/operation-registry.d.ts +1 -1
  165. package/dist/server/operations/aggregate-workflows.d.ts +6 -0
  166. package/dist/server/operations/aggregate-workflows.js +3 -2
  167. package/dist/server/operations/async-activity.d.ts +14 -0
  168. package/dist/server/operations/async-activity.js +88 -4
  169. package/dist/server/operations/bulk-filter-helpers.d.ts +3 -0
  170. package/dist/server/operations/bulk-filter-helpers.js +27 -3
  171. package/dist/server/operations/bulk-mutate-workflow-tags.d.ts +6 -0
  172. package/dist/server/operations/bulk-signal-workflows.d.ts +6 -0
  173. package/dist/server/operations/get-stream-chunks.js +2 -7
  174. package/dist/server/operations/get-system-lease.d.ts +19 -0
  175. package/dist/server/operations/get-system-lease.js +48 -0
  176. package/dist/server/operations/get-workflow-observability.d.ts +24 -0
  177. package/dist/server/operations/get-workflow-observability.js +80 -0
  178. package/dist/server/operations/get-workflow-result.js +2 -2
  179. package/dist/server/operations/get-workflow.d.ts +2 -2
  180. package/dist/server/operations/list-filter-query-extractor.js +15 -0
  181. package/dist/server/operations/list-reviews.js +2 -19
  182. package/dist/server/operations/list-workflows.d.ts +6 -0
  183. package/dist/server/operations/list-workflows.js +12 -3
  184. package/dist/server/operations/operation-helpers.d.ts +9 -18
  185. package/dist/server/operations/operation-helpers.js +5 -23
  186. package/dist/server/operations/purge-workflows.d.ts +3 -0
  187. package/dist/server/operations/recover-all.js +1 -9
  188. package/dist/server/operations/single-workflow-control-operation.d.ts +2 -1
  189. package/dist/server/operations/single-workflow-tag-mutation.js +2 -2
  190. package/dist/server/operations/sse-stream.js +2 -7
  191. package/dist/server/operations/storage-capabilities.d.ts +34 -0
  192. package/dist/server/operations/storage-capabilities.js +38 -0
  193. package/dist/server/operations/storage.js +8 -17
  194. package/dist/server/operations/stream-workflow-sse.js +3 -9
  195. package/dist/server/operations/update-schedule.d.ts +8 -0
  196. package/dist/server/operations/update-schedule.js +70 -7
  197. package/dist/server/operations/workflow-events-sse.js +2 -2
  198. package/dist/server/rest-binding.d.ts +7 -6
  199. package/dist/server/rest-bindings.d.ts +2 -13
  200. package/dist/server/rest-bindings.js +19 -10
  201. package/dist/server/task-queue.d.ts +7 -5
  202. package/dist/storage/bounded-ndjson-response.d.ts +5 -0
  203. package/dist/storage/bounded-ndjson-response.js +33 -0
  204. package/dist/storage/capabilities.d.ts +1 -1
  205. package/dist/storage/cloudflare-value-codec.d.ts +5 -3
  206. package/dist/storage/cloudflare-value-codec.js +1 -1
  207. package/dist/storage/compressed-storage.js +1 -1
  208. package/dist/storage/http.js +5 -37
  209. package/dist/storage/index.d.ts +7 -1
  210. package/dist/storage/interface.d.ts +16 -4
  211. package/dist/storage/interface.js +1 -1
  212. package/dist/storage/key-prefixes.d.ts +1 -1
  213. package/dist/storage/key-prefixes.js +4 -0
  214. package/dist/storage/lmdb.js +1 -1
  215. package/dist/storage/memory.js +1 -1
  216. package/dist/storage/neon.d.ts +3 -16
  217. package/dist/storage/neon.js +4 -4
  218. package/dist/storage/postgres.js +4 -4
  219. package/dist/storage/resolve.js +1 -1
  220. package/dist/storage/scoped-storage.js +1 -1
  221. package/dist/storage/testing.js +1 -1
  222. package/dist/storage/turso.js +2 -2
  223. package/dist/version.d.ts +1 -1
  224. package/dist/version.js +1 -1
  225. package/dist/web-extension.js +1 -1
  226. package/package.json +1 -1
@@ -12,6 +12,7 @@ import { asyncActivityWorkflowPrefix } from "./async-activity-records.js";
12
12
  import { forgetCommittedCheckpointBytes } from "./checkpoint-commit-snapshots.js";
13
13
  import { commitFencedEngineWrite } from "./fenced-write.js";
14
14
  import { streamWorkflowStates } from "./listing.js";
15
+ import { decodeScheduleRunMetadata } from "./schedule-run-metadata.js";
15
16
  import { createTerminalCleanupTimerId } from "./state-utilities.js";
16
17
  import {
17
18
  decodeWorkflowState,
@@ -181,12 +182,22 @@ async function collectWorkflowPurgeDeleteKeys(internals, state) {
181
182
  const workflowId = state.id, deleteKeys = buildBaseWorkflowDeleteKeys(state);
182
183
  addExecutionDeadlineDeleteKeys(deleteKeys, state);
183
184
  addTerminalCleanupDeleteKey(deleteKeys, state);
185
+ await addScheduleRunHistoryDeleteKeys(internals.storage, deleteKeys, workflowId);
184
186
  await addUpdateRequestDeleteKeys(internals.storage, deleteKeys, workflowId);
185
187
  await addWorkflowPrefixDeleteKeys(internals.storage, deleteKeys, workflowId);
186
188
  return deleteKeys;
187
189
  }
190
+ async function addScheduleRunHistoryDeleteKeys(storage, deleteKeys, workflowId) {
191
+ const linkKey = KEYS.scheduleRunLink(workflowId), linkBytes = await storage.get(linkKey);
192
+ deleteKeys.add(linkKey);
193
+ if (linkBytes === null)
194
+ return;
195
+ const metadata = decodeScheduleRunMetadata(linkBytes);
196
+ if (metadata !== null)
197
+ deleteKeys.add(KEYS.scheduleRunBySchedule(metadata.id, workflowId));
198
+ }
188
199
  function buildBaseWorkflowDeleteKeys(state) {
189
- return new Set([
200
+ const keys = new Set([
190
201
  KEYS.workflow(state.id),
191
202
  KEYS.checkpoint(state.id),
192
203
  KEYS.workflowHeaders(state.id),
@@ -196,9 +207,13 @@ function buildBaseWorkflowDeleteKeys(state) {
196
207
  KEYS.workflowHasServices(state.id),
197
208
  KEYS.finalizerState(state.id),
198
209
  KEYS.teardownOwed(state.id),
210
+ KEYS.teardownSucceeded(state.id),
199
211
  KEYS.attribute(state.id),
200
212
  KEYS.terminalWorkflow(state.updatedAt, state.id)
201
213
  ]);
214
+ if (state.parentWorkflowId !== void 0)
215
+ keys.add(KEYS.childWorkflowByParent(state.parentWorkflowId, state.parentWorkflowExecutionToken, state.id));
216
+ return keys;
202
217
  }
203
218
  function addExecutionDeadlineDeleteKeys(deleteKeys, state) {
204
219
  if (state.executionDeadline === void 0)
@@ -63,6 +63,8 @@ function summarizeBulkFilter(filter) {
63
63
  summary.status = Array.isArray(filter.status) ? uniqueSorted(filter.status) : filter.status;
64
64
  if (filter.type !== void 0)
65
65
  summary.type = filter.type;
66
+ if (filter.scheduleId !== void 0)
67
+ summary.scheduleId = filter.scheduleId;
66
68
  const normalizedTags = normalizeWorkflowTags(filter.tags);
67
69
  if (normalizedTags !== void 0)
68
70
  summary.tags = normalizedTags;
@@ -1,3 +1,5 @@
1
1
  import type { ContextOperationRequest } from '../context.ts';
2
+ import { type PersistCheckpointCallbacks } from './checkpoint-io.ts';
2
3
  import type { Engine } from './index.ts';
4
+ export declare function createCheckpointPersistenceCallbacks<TWorkflows extends object, TActivities extends object>(engine: Engine<TWorkflows, TActivities>): PersistCheckpointCallbacks;
3
5
  export declare function persistCheckpointForDataOperation<TWorkflows extends object, TActivities extends object>(engine: Engine<TWorkflows, TActivities>, workflowId: string, operation: ContextOperationRequest): Promise<void>;
@@ -9,8 +9,8 @@ import {
9
9
  import { getInternals } from "./internals.js";
10
10
  import { swallowPromiseRejection } from "./strategy-helpers.js";
11
11
  import { terminateWorkflow } from "./termination.js";
12
- export function persistCheckpointForDataOperation(engine, workflowId, operation) {
13
- return persistCheckpoint(getInternals(engine), workflowId, operation, void 0, {
12
+ export function createCheckpointPersistenceCallbacks(engine) {
13
+ return {
14
14
  appendTimelineBatchOperations: (id, checkpointOperation, step, timestamp, operations) => appendTimelineBatchOperations(getInternals(engine), id, checkpointOperation, step, timestamp, operations),
15
15
  swallowPromiseRejection: (promise) => {
16
16
  swallowPromiseRejection(promise);
@@ -21,5 +21,8 @@ export function persistCheckpointForDataOperation(engine, workflowId, operation)
21
21
  engine.dispatchEvent(event);
22
22
  },
23
23
  enforceHistoryCircuitBreaker: (id) => terminateWorkflow(getInternals(engine), id, "timed-out", createTerminationCallbacks(engine), HISTORY_CIRCUIT_BREAKER_REASON)
24
- }, { timeline: "preserve-pending" });
24
+ };
25
+ }
26
+ export function persistCheckpointForDataOperation(engine, workflowId, operation) {
27
+ return persistCheckpoint(getInternals(engine), workflowId, operation, void 0, createCheckpointPersistenceCallbacks(engine), { timeline: "preserve-pending" });
25
28
  }
@@ -1,12 +1,13 @@
1
1
  import type { ScheduleState, TimerEntry } from '../types.ts';
2
2
  import type { Engine } from './index.ts';
3
3
  import type { ReviewOperationCallbacks, SubmitReviewCallbacks } from './reviews.ts';
4
+ import type { ScheduledRunStartOptions } from './schedule-run.ts';
4
5
  import { type RefreshedScheduleState, type ScheduleCallbacks } from './schedules.ts';
5
6
  export declare function createScheduleCallbacks<TWorkflows extends object, TActivities extends object>(engine: Engine<TWorkflows, TActivities>): ScheduleCallbacks;
6
7
  export declare function createReviewOperationCallbacks<TWorkflows extends object, TActivities extends object>(engine: Engine<TWorkflows, TActivities>): ReviewOperationCallbacks;
7
8
  export declare function createSubmitReviewCallbacks<TWorkflows extends object, TActivities extends object>(engine: Engine<TWorkflows, TActivities>): SubmitReviewCallbacks;
8
9
  export declare function refreshScheduledWorkflowStateForEngine<TWorkflows extends object, TActivities extends object>(engine: Engine<TWorkflows, TActivities>, state: ScheduleState): Promise<RefreshedScheduleState>;
9
- export declare function startScheduledRunForEngine<TWorkflows extends object, TActivities extends object>(engine: Engine<TWorkflows, TActivities>, state: ScheduleState, occurrence?: number): Promise<string>;
10
+ export declare function startScheduledRunForEngine<TWorkflows extends object, TActivities extends object>(engine: Engine<TWorkflows, TActivities>, state: ScheduleState, options?: ScheduledRunStartOptions): Promise<string>;
10
11
  export declare function applyScheduleOccurrenceForEngine<TWorkflows extends object, TActivities extends object>(engine: Engine<TWorkflows, TActivities>, state: ScheduleState, occurrence?: number): Promise<ScheduleState>;
11
12
  export declare function settleBackfillScheduleStateForEngine<TWorkflows extends object, TActivities extends object>(engine: Engine<TWorkflows, TActivities>, state: ScheduleState): Promise<ScheduleState>;
12
13
  export declare function handleScheduleTimerForEngine<TWorkflows extends object, TActivities extends object>(engine: Engine<TWorkflows, TActivities>, entry: TimerEntry): Promise<void>;
@@ -27,7 +27,7 @@ export function createScheduleCallbacks(engine) {
27
27
  cancelWorkflow: (workflowId) => engine.cancel(workflowId),
28
28
  getWorkflowResult: (workflowId) => engine.getHandle(workflowId).result(),
29
29
  refreshScheduledWorkflowState: (state) => refreshScheduledWorkflowStateForEngine(engine, state),
30
- startScheduledRun: (state, occurrence) => startScheduledRunForEngine(engine, state, occurrence),
30
+ startScheduledRun: (state, options) => startScheduledRunForEngine(engine, state, options),
31
31
  applyScheduleOccurrence: (state, occurrence) => applyScheduleOccurrenceForEngine(engine, state, occurrence),
32
32
  settleBackfillScheduleState: (state) => settleBackfillScheduleStateForEngine(engine, state),
33
33
  flushQueuedInlineWorkflowStartsDirectly: () => flushQueuedInlineWorkflowStartsDirectly(getInternals(engine), createInlineLaunchQueueCallbacks(engine)),
@@ -51,8 +51,8 @@ export function createSubmitReviewCallbacks(engine) {
51
51
  export async function refreshScheduledWorkflowStateForEngine(engine, state) {
52
52
  return refreshScheduledWorkflowState(getInternals(engine), state, createScheduleCallbacks(engine));
53
53
  }
54
- export async function startScheduledRunForEngine(engine, state, occurrence) {
55
- return startScheduledRun(getInternals(engine), state, createScheduleCallbacks(engine), occurrence);
54
+ export async function startScheduledRunForEngine(engine, state, options) {
55
+ return startScheduledRun(getInternals(engine), state, createScheduleCallbacks(engine), options);
56
56
  }
57
57
  export async function applyScheduleOccurrenceForEngine(engine, state, occurrence) {
58
58
  return applyScheduleOccurrence(getInternals(engine), state, createScheduleCallbacks(engine), occurrence);
@@ -1,6 +1,5 @@
1
1
  import { KEYS } from "../../storage/interface.js";
2
- import { HISTORY_CIRCUIT_BREAKER_REASON } from "../types.js";
3
- import { validateAttributeValueSizes } from "./attributes-tags.js";
2
+ import { createCheckpointPersistenceCallbacks } from "./callback-checkpoint-persistence.js";
4
3
  import {
5
4
  createConstraintCallbacks,
6
5
  createLifecycleCallbacks,
@@ -8,12 +7,7 @@ import {
8
7
  registerEnsureRetentionSweepInterval
9
8
  } from "./callback-creators-core.js";
10
9
  import { createOperationRouterCallbacks } from "./callback-creators-router.js";
11
- import {
12
- appendTimelineBatchOperations,
13
- persistCheckpoint,
14
- pruneCheckpointHistory,
15
- validateDevelopmentCheckpoint
16
- } from "./checkpoint-io.js";
10
+ import { persistCheckpoint, validateDevelopmentCheckpoint } from "./checkpoint-io.js";
17
11
  import { evaluateConstraints } from "./constraints.js";
18
12
  import {
19
13
  getParkedWorkflowResumeDisposition,
@@ -30,8 +24,7 @@ import {
30
24
  } from "./retention.js";
31
25
  import { hasBufferedSignal } from "./signals.js";
32
26
  import { loadWorkflowState, runSerializedWorkflowStateWrite } from "./storage-io.js";
33
- import { swallowPromiseRejection } from "./strategy-helpers.js";
34
- import { cleanupWaiters, terminateWorkflow } from "./termination.js";
27
+ import { cleanupWaiters } from "./termination.js";
35
28
  export { createUpdateCallbacks } from "./callback-creators-bundles.js";
36
29
  export {
37
30
  createBroadcastCallbacks,
@@ -64,18 +57,7 @@ export function createInlineParkingCallbacks(engine) {
64
57
  };
65
58
  }
66
59
  export function persistCheckpointForEngine(engine, workflowId, operation, workerCheckpointBytes) {
67
- return persistCheckpoint(getInternals(engine), workflowId, operation, workerCheckpointBytes, {
68
- appendTimelineBatchOperations: (id, checkpointOperation, step, timestamp, operations) => appendTimelineBatchOperations(getInternals(engine), id, checkpointOperation, step, timestamp, operations),
69
- swallowPromiseRejection: (promise) => {
70
- swallowPromiseRejection(promise);
71
- },
72
- validateAttributeValueSizes,
73
- pruneCheckpointHistory: (id, step) => pruneCheckpointHistory(getInternals(engine), id, step),
74
- dispatchEvent: (event) => {
75
- engine.dispatchEvent(event);
76
- },
77
- enforceHistoryCircuitBreaker: (id) => terminateWorkflow(getInternals(engine), id, "timed-out", createTerminationCallbacks(engine), HISTORY_CIRCUIT_BREAKER_REASON)
78
- });
60
+ return persistCheckpoint(getInternals(engine), workflowId, operation, workerCheckpointBytes, createCheckpointPersistenceCallbacks(engine));
79
61
  }
80
62
  function ensureRetentionSweepIntervalForEngine(engine) {
81
63
  ensureRetentionSweepInterval(getInternals(engine), {
@@ -9,7 +9,7 @@ type PendingTimelineEntryValue = {
9
9
  export type PersistCheckpointOptions = {
10
10
  timeline?: 'record-operation' | 'preserve-pending';
11
11
  };
12
- type PersistCheckpointCallbacks = {
12
+ export type PersistCheckpointCallbacks = {
13
13
  appendTimelineBatchOperations: (workflowId: string, operation: ContextOperationRequest, step: number, timestamp: number, operations: BatchOperation[]) => PendingTimelineEntryValue;
14
14
  swallowPromiseRejection: (promise: Promise<void>) => void;
15
15
  validateAttributeValueSizes: (attributes: Record<string, SearchAttributeValue>) => void;
@@ -66,12 +66,22 @@ export async function getTimeline(internals, workflowId) {
66
66
  inputSummary: sanitizeTimelineSummary(decoded.inputSummary) ?? decoded.inputSummary,
67
67
  ...decoded.outputSummary !== void 0 ? {
68
68
  outputSummary: sanitizeTimelineSummary(decoded.outputSummary) ?? decoded.outputSummary
69
- } : {}
69
+ } : {},
70
+ ...decoded.branches === void 0 ? {} : { branches: decoded.branches.map(sanitizeTimelineOperationDetail) },
71
+ ...decoded.children === void 0 ? {} : { children: decoded.children.map(sanitizeTimelineOperationDetail) }
70
72
  });
71
73
  }
72
74
  timeline.sort((left, right) => left.step - right.step);
73
75
  return timeline;
74
76
  }
77
+ function sanitizeTimelineOperationDetail(detail) {
78
+ if (detail.errorSummary === void 0)
79
+ return detail;
80
+ return {
81
+ ...detail,
82
+ errorSummary: sanitizeTimelineSummary(detail.errorSummary) ?? detail.errorSummary
83
+ };
84
+ }
75
85
  export async function replayTo(internals, workflowId, step) {
76
86
  const bytes = await internals.storage.get(KEYS.checkpointHistory(workflowId, step));
77
87
  if (!bytes)
@@ -22,6 +22,8 @@ function applyPendingChildExecutionContext(internals, context) {
22
22
  internals.pendingNestingDepth = context.pendingNestingDepth;
23
23
  internals.pendingParentHeaders = context.pendingParentHeaders;
24
24
  internals.pendingExecutionStateOwnerId = context.pendingExecutionStateOwnerId;
25
+ internals.pendingParentWorkflowId = context.pendingParentWorkflowId;
26
+ internals.pendingParentWorkflowExecutionToken = context.pendingParentWorkflowExecutionToken;
25
27
  }
26
28
  function clearPendingChildExecutionContext(internals, context) {
27
29
  if (internals.pendingNestingDepth === context.pendingNestingDepth)
@@ -30,15 +32,20 @@ function clearPendingChildExecutionContext(internals, context) {
30
32
  internals.pendingParentHeaders = void 0;
31
33
  if (internals.pendingExecutionStateOwnerId === context.pendingExecutionStateOwnerId)
32
34
  internals.pendingExecutionStateOwnerId = void 0;
35
+ if (internals.pendingParentWorkflowId === context.pendingParentWorkflowId)
36
+ internals.pendingParentWorkflowId = void 0;
37
+ if (internals.pendingParentWorkflowExecutionToken === context.pendingParentWorkflowExecutionToken)
38
+ internals.pendingParentWorkflowExecutionToken = void 0;
33
39
  }
34
- function existingChildMatchesRequest(existingState, operation, executionStateOwnerId) {
35
- return existingState.type === operation.workflowType && encodedValuesEqual(existingState.input, operation.input) && existingState.executionStateOwnerId === executionStateOwnerId;
40
+ function existingChildMatchesRequest(existingState, operation, executionStateOwnerId, parentWorkflowId, parentWorkflowExecutionToken) {
41
+ const lineageMatches = existingState.parentWorkflowId === void 0 && existingState.parentWorkflowExecutionToken === void 0 || existingState.parentWorkflowId === parentWorkflowId && existingState.parentWorkflowExecutionToken === parentWorkflowExecutionToken;
42
+ return existingState.type === operation.workflowType && encodedValuesEqual(existingState.input, operation.input) && existingState.executionStateOwnerId === executionStateOwnerId && lineageMatches;
36
43
  }
37
- async function resolveCollisionChildHandle(childWorkflowId, operation, executionStateOwnerId, collisionError, callbacks) {
44
+ async function resolveCollisionChildHandle(childWorkflowId, operation, executionStateOwnerId, parentWorkflowId, parentWorkflowExecutionToken, collisionError, callbacks) {
38
45
  const existingState = await callbacks.loadWorkflowState(childWorkflowId);
39
46
  if (!existingState)
40
47
  throw collisionError;
41
- if (!existingChildMatchesRequest(existingState, operation, executionStateOwnerId))
48
+ if (!existingChildMatchesRequest(existingState, operation, executionStateOwnerId, parentWorkflowId, parentWorkflowExecutionToken))
42
49
  throw Error(`Child workflow id collision for "${childWorkflowId}" does not match the requested child workflow`, { cause: collisionError });
43
50
  return callbacks.getHandle(childWorkflowId);
44
51
  }
@@ -52,7 +59,7 @@ async function dispatchChildWorkflowStart(internals, childWorkflowId, operation,
52
59
  } catch (error) {
53
60
  if (!(error instanceof WorkflowAlreadyExistsError))
54
61
  throw error;
55
- return resolveCollisionChildHandle(childWorkflowId, operation, context.pendingExecutionStateOwnerId ?? void 0, error, callbacks);
62
+ return resolveCollisionChildHandle(childWorkflowId, operation, context.pendingExecutionStateOwnerId ?? void 0, context.pendingParentWorkflowId, context.pendingParentWorkflowExecutionToken, error, callbacks);
56
63
  } finally {
57
64
  clearPendingChildExecutionContext(internals, context);
58
65
  }
@@ -62,7 +69,9 @@ export async function executeChildWorkflow(internals, workflowId, operation, cur
62
69
  const context = {
63
70
  pendingNestingDepth: currentDepth + 1,
64
71
  pendingParentHeaders: internals.workflowHeaders.get(workflowId),
65
- pendingExecutionStateOwnerId: executionStateOwnerId
72
+ pendingExecutionStateOwnerId: executionStateOwnerId,
73
+ pendingParentWorkflowId: workflowId,
74
+ pendingParentWorkflowExecutionToken: parentState?.workflowExecutionToken
66
75
  }, childHandle = await dispatchChildWorkflowStart(internals, childWorkflowId, operation, context, callbacks);
67
76
  if (parentClosePolicy === "abandon")
68
77
  return createChildWorkflowHandleReference(childHandle.id);
@@ -72,6 +72,9 @@ export function copyWorkflowDefinition(type, registration) {
72
72
  ...registration.description === void 0 ? {} : { description: registration.description },
73
73
  ...registration.inputSchema === void 0 ? {} : { inputSchema: registration.inputSchema },
74
74
  ...registration.outputSchema === void 0 ? {} : { outputSchema: registration.outputSchema },
75
+ ...registration.signals === void 0 ? {} : { signals: { ...registration.signals } },
76
+ ...registration.updates === void 0 ? {} : { updates: { ...registration.updates } },
77
+ ...registration.queries === void 0 ? {} : { queries: { ...registration.queries } },
75
78
  ...registration.searchAttributes === void 0 ? {} : { searchAttributes: registration.searchAttributes },
76
79
  ...registration.concurrency === void 0 ? {} : { concurrency: registration.concurrency }
77
80
  };
@@ -53,6 +53,8 @@ export function disposeEngine(internals) {
53
53
  internals.sleepTimersFiredWithoutResolver.clear();
54
54
  internals.checkpoints.clear();
55
55
  internals.pendingExecutionStateOwnerId = void 0;
56
+ internals.pendingParentWorkflowId = void 0;
57
+ internals.pendingParentWorkflowExecutionToken = void 0;
56
58
  internals.workflowNestingDepths.clear();
57
59
  internals.workflowServices.clear();
58
60
  internals.workflowHeaders.clear();
@@ -2,7 +2,7 @@ import type { Storage as WeftStorage } from '../../storage/interface.ts';
2
2
  import type { ConstraintDefinition } from '../constraint.ts';
3
3
  import type { ExecutionStrategy } from '../execution-strategy.ts';
4
4
  import type { InlineExecutionStrategy } from '../inline-execution-strategy.ts';
5
- import type { AnyActivityDefinition, ArchiveAdapter, Checkpoint, DefinitionSchema, EngineOptions, NormalizedHistoryPolicy, NormalizedPayloadSizePolicy, NormalizedRetentionPolicy, SearchAttributeSchema, WorkflowConcurrencyOptions, WorkflowFunction, WorkflowTimelineEntry } from '../types.ts';
5
+ import type { AnyActivityDefinition, ArchiveAdapter, Checkpoint, DefinitionSchema, EngineOptions, NormalizedHistoryPolicy, NormalizedPayloadSizePolicy, NormalizedRetentionPolicy, QueryDefinition, SearchAttributeSchema, SignalDefinition, UpdateDefinition, WorkflowConcurrencyOptions, WorkflowFunction, WorkflowTimelineEntry } from '../types.ts';
6
6
  export interface RegistrationEntry {
7
7
  handler: WorkflowFunction;
8
8
  version: string;
@@ -10,6 +10,9 @@ export interface RegistrationEntry {
10
10
  tags?: ReadonlyArray<string>;
11
11
  inputSchema?: DefinitionSchema;
12
12
  outputSchema?: DefinitionSchema;
13
+ signals?: Readonly<Record<string, Readonly<SignalDefinition<unknown>>>>;
14
+ updates?: Readonly<Record<string, Readonly<UpdateDefinition<unknown>>>>;
15
+ queries?: Readonly<Record<string, Readonly<QueryDefinition<unknown>>>>;
13
16
  searchAttributes?: SearchAttributeSchema;
14
17
  retention?: NormalizedRetentionPolicy;
15
18
  concurrency?: WorkflowConcurrencyOptions;
@@ -27,9 +27,11 @@ import type { EngineInternals } from './internals.ts';
27
27
  * work before `recoverAll()` would otherwise durably write workflow state without
28
28
  * single-writer ownership and without having recovered existing runs. Placed at
29
29
  * each public awaited entry so the caller gets a clean {@link EngineLeaseNotHeldError}
30
- * — without this, fork/resume would reach `resolveFenceEpochOrHalt` with no held
31
- * epoch and be misreported as a deposition (warn + teardown) rather than the true
32
- * "lease not held yet" condition. A no-op under `ownership: 'none'`.
30
+ * — without this, fork, resume, and the schedule mutators (`schedule`,
31
+ * `pauseSchedule`, `resumeSchedule`, `cancelSchedule`, and `updateSchedule`) would
32
+ * reach `resolveFenceEpochOrHalt` with no held epoch and be misreported as a
33
+ * deposition (warn + teardown) rather than the true "lease not held yet"
34
+ * condition. A no-op under `ownership: 'none'`.
33
35
  */
34
36
  export declare function assertLeaseHeldForEngineWork(internals: EngineInternals): void;
35
37
  /**
@@ -0,0 +1,10 @@
1
+ import { type BatchOperation } from '../../storage/interface.ts';
2
+ import type { WorkflowFinalizerStatus, WorkflowState } from '../types.ts';
3
+ import type { EngineInternals } from './internals.ts';
4
+ export interface TeardownSucceededRecord {
5
+ attempts: number;
6
+ completedAt: number;
7
+ workflowExecutionToken?: string;
8
+ }
9
+ export declare function buildTeardownSuccessOperations(workflowId: string, attempts: number, completedAt: number, workflowExecutionToken: string | undefined): BatchOperation[];
10
+ export declare function getFinalizerStatus(internals: EngineInternals, workflowId: string, state: WorkflowState | null): Promise<WorkflowFinalizerStatus | null>;
@@ -0,0 +1,82 @@
1
+ import { KEYS } from "../../storage/interface.js";
2
+ import { decode, encode } from "../codec.js";
3
+ import { isRecord } from "../debug-output.js";
4
+ import { isTeardownClaim } from "./state-utilities.js";
5
+ export function buildTeardownSuccessOperations(workflowId, attempts, completedAt, workflowExecutionToken) {
6
+ const outcome = {
7
+ attempts,
8
+ completedAt,
9
+ ...workflowExecutionToken === void 0 ? {} : { workflowExecutionToken }
10
+ };
11
+ return [
12
+ { type: "delete", key: KEYS.teardownOwed(workflowId) },
13
+ { type: "delete", key: KEYS.finalizerState(workflowId) },
14
+ { type: "put", key: KEYS.teardownSucceeded(workflowId), value: encode(outcome) }
15
+ ];
16
+ }
17
+ function decodeUnknown(bytes) {
18
+ try {
19
+ return decode(bytes);
20
+ } catch {
21
+ return null;
22
+ }
23
+ }
24
+ function isNonNegativeSafeInteger(value) {
25
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
26
+ }
27
+ function isNonNegativeFiniteNumber(value) {
28
+ return typeof value === "number" && Number.isFinite(value) && value >= 0;
29
+ }
30
+ function recordBelongsToRun(record, state) {
31
+ const recordToken = record.workflowExecutionToken;
32
+ if (recordToken !== void 0 && typeof recordToken !== "string")
33
+ return !1;
34
+ if (state === null)
35
+ return !0;
36
+ return recordToken === state.workflowExecutionToken;
37
+ }
38
+ export async function getFinalizerStatus(internals, workflowId, state) {
39
+ const claimBytes = await internals.storage.get(KEYS.teardownOwed(workflowId)), claimStatus = decodeClaimStatus(claimBytes);
40
+ if (claimStatus !== null)
41
+ return claimStatus;
42
+ const deadLetterBytes = await internals.storage.get(KEYS.teardownDeadLetter(workflowId)), failedStatus = decodeFailedStatus(deadLetterBytes, state);
43
+ if (failedStatus !== null)
44
+ return failedStatus;
45
+ const succeededBytes = await internals.storage.get(KEYS.teardownSucceeded(workflowId));
46
+ return decodeSucceededStatus(succeededBytes, state);
47
+ }
48
+ function decodeClaimStatus(bytes) {
49
+ if (bytes === null)
50
+ return null;
51
+ const claim = decodeUnknown(bytes);
52
+ if (!isTeardownClaim(claim))
53
+ return null;
54
+ if (claim.status === "running" && claim.claimedAt !== void 0)
55
+ return { status: "running", attempts: claim.attempts + 1, startedAt: claim.claimedAt };
56
+ return { status: "pending", attempts: claim.attempts };
57
+ }
58
+ function decodeFailedStatus(bytes, state) {
59
+ if (bytes === null)
60
+ return null;
61
+ const record = decodeUnknown(bytes);
62
+ if (!isRecord(record) || !recordBelongsToRun(record, state) || typeof record.lastError !== "string" || !isNonNegativeSafeInteger(record.attempts) || !isNonNegativeFiniteNumber(record.deadLetteredAt))
63
+ return null;
64
+ return {
65
+ status: "failed",
66
+ attempts: record.attempts,
67
+ failedAt: record.deadLetteredAt,
68
+ error: record.lastError
69
+ };
70
+ }
71
+ function decodeSucceededStatus(bytes, state) {
72
+ if (bytes === null)
73
+ return null;
74
+ const record = decodeUnknown(bytes);
75
+ if (!isRecord(record) || !recordBelongsToRun(record, state) || !isNonNegativeSafeInteger(record.attempts) || !isNonNegativeFiniteNumber(record.completedAt))
76
+ return null;
77
+ return {
78
+ status: "succeeded",
79
+ attempts: record.attempts,
80
+ completedAt: record.completedAt
81
+ };
82
+ }
@@ -5,7 +5,7 @@ import type { TypedEventTarget, WeftEventMap } from '../events.ts';
5
5
  import type { Interceptor } from '../interceptor.ts';
6
6
  import { type ReviewRequest } from '../review/index.ts';
7
7
  import { Scheduler } from '../scheduler.ts';
8
- import { type AnyActivityDefinition, type AnyWorkflowDefinition, type AttributeFilterKey, type BulkCancelResult, type BulkDeleteResult, type BulkOperationCommitOptions, type BulkOperationDryRunOptions, type BulkOperationDryRunResult, type BulkRetryFailedResult, type BulkSignalAllCommitOptions, type BulkSignalAllDryRunOptions, type BulkSignalResult, type BulkTagResult, type CheckpointState, type CheckpointSummary, type CoordinatedUpdateResult, type DefaultActivityTypes, type DefaultWorkflowRegistry, type ForkOptions, type InferActivityEntries, type InferActivityEntry, type InferWorkflowEntries, type InferWorkflowEntry, type ListFilter, type ListOptions, type PaginatedResult, type PurgeResult, type QueryDefinition, type RegisteredWorkflowDefinition, type RetentionOverview, type ReviewListEntry, type ReviewListFilter, type ScheduleDefinition, type ScheduleFilter, type ScheduleOptions, type ScheduleSpec, type ScheduleSummary, type SearchAttributeValue, type SignalDefinition, type SignalDeliveryOptions, type StartOrSignalOptions, type StartOrSignalSignal, type StartWorkflowOptions, type SubmitReviewOptions, type TypedListFilter, type UpdateDefinition, type WorkflowEvent, type WorkflowInput, type WorkflowOutput, type WorkflowReplay, type WorkflowServices, type WorkflowServicesUnion, type WorkflowState, type WorkflowSummary, type WorkflowTimelineEntry } from '../types.ts';
8
+ import { type AnyActivityDefinition, type AnyWorkflowDefinition, type AttributeFilterKey, type BulkCancelResult, type BulkDeleteResult, type BulkOperationCommitOptions, type BulkOperationDryRunOptions, type BulkOperationDryRunResult, type BulkRetryFailedResult, type BulkSignalAllCommitOptions, type BulkSignalAllDryRunOptions, type BulkSignalResult, type BulkTagResult, type CheckpointState, type CheckpointSummary, type CoordinatedUpdateResult, type DefaultActivityTypes, type DefaultWorkflowRegistry, type ForkOptions, type InferActivityEntries, type InferActivityEntry, type InferWorkflowEntries, type InferWorkflowEntry, type ListFilter, type ListOptions, type PaginatedResult, type PendingAsyncActivityListOptions, type PendingAsyncActivityPage, type PurgeResult, type QueryDefinition, type RegisteredWorkflowDefinition, type RetentionOverview, type ReviewListEntry, type ReviewListFilter, type ScheduleDefinition, type ScheduleFilter, type ScheduleOptions, type ScheduleSpec, type ScheduleSummary, type ScheduleUpdateOptions, type SearchAttributeValue, type SignalDefinition, type SignalDeliveryOptions, type StartOrSignalOptions, type StartOrSignalSignal, type StartWorkflowOptions, type SubmitReviewOptions, type TypedListFilter, type UpdateDefinition, type WorkflowEvent, type WorkflowFinalizerStatus, type WorkflowInput, type WorkflowOutput, type WorkflowReplay, type WorkflowScheduleProvenance, type WorkflowServices, type WorkflowServicesUnion, type WorkflowState, type WorkflowSummary, type WorkflowTimelineEntry } from '../types.ts';
9
9
  import type { TimerEntry } from '../types/checkpoint.ts';
10
10
  import type { WorkflowAlreadyRegistered } from '../types/workflow-builder.ts';
11
11
  import { type AggregateOptions, type AggregateResult } from './aggregate.ts';
@@ -15,6 +15,7 @@ import type { EngineConstructorOptions } from './engine-internal-types.ts';
15
15
  import type { EngineStateNamespace } from './engine-state-namespace.ts';
16
16
  import { HANDLE_RESULT_PROMISE, WorkflowHandle } from './handles.ts';
17
17
  import { ENGINE_LEASE_LOST_WARNING_NAME } from './lease-deposition.ts';
18
+ import type { EngineLeaseHealth } from './lease-health.ts';
18
19
  import { type RecoverAllOptions, type StartOrSignalResult } from './lifecycle.ts';
19
20
  import { assertCompatiblePersistedDataVersion } from './persisted-data-version.ts';
20
21
  import { ScheduleHandle } from './schedule-handle.ts';
@@ -26,6 +27,7 @@ export type { PendingTimelineEntry, RegistrationEntry, ResolvedOptions, TrackedW
26
27
  export { ActivityResolutionError, BulkDeleteRequiresTerminalWorkflowsError, BulkOperationConfirmationError, EngineCreateNameMismatchError, EngineDisposedError, IdempotencyKeyPurgedError, PersistedDataIncompatibleError, StartOrSignalConflictError, WorkflowAlreadyExistsError, WorkflowConcurrencyLimitExceededError, WorkflowNotFoundError, WorkflowNotRegisteredError, WorkflowSuspendNotSupportedError, WorkflowTeardownPendingError, WorkflowTypeNotRegisteredForRecoveryError, } from './errors.ts';
27
28
  export { HANDLE_RESULT_PROMISE, WorkflowHandle } from './handles.ts';
28
29
  export { EngineLeaseAcquisitionTimeoutError, EngineLeaseCorruptedError, EngineLeaseNotHeldError, } from './lease-errors.ts';
30
+ export type { EngineLeaseHealth, LeaseLostReason } from './lease-health.ts';
29
31
  export type { RecoverAllOptions, RecoveredWorkflowInfo } from './lifecycle.ts';
30
32
  export { ScheduleHandle } from './schedule-handle.ts';
31
33
  export type { WorkflowFeedListener, WorkflowFeedRecord, WorkflowFeedSelector, } from './workflow-feed.ts';
@@ -304,7 +306,7 @@ export declare class Engine<TWorkflows extends object = DefaultWorkflowRegistry,
304
306
  pauseSchedule(scheduleId: string): Promise<void>;
305
307
  resumeSchedule(scheduleId: string): Promise<void>;
306
308
  cancelSchedule(scheduleId: string): Promise<void>;
307
- updateSchedule(scheduleId: string, newSpec: string | ScheduleSpec): Promise<void>;
309
+ updateSchedule(scheduleId: string, newSpec: string | ScheduleSpec, options?: ScheduleUpdateOptions): Promise<void>;
308
310
  [HANDLE_RESULT_PROMISE](workflowId: string): Promise<unknown>;
309
311
  [ENGINE_PARKED_WORKFLOW_COUNT_FOR_TESTING](): number;
310
312
  [ENGINE_SIGNAL_WAITER_COUNT_FOR_TESTING](): number;
@@ -394,6 +396,13 @@ export declare class Engine<TWorkflows extends object = DefaultWorkflowRegistry,
394
396
  * the token (unknown, or already completed/failed — tokens are single-use).
395
397
  */
396
398
  completeAsyncActivity(token: string, result: unknown): Promise<void>;
399
+ /**
400
+ * List a bounded page of durable async activities awaiting out-of-band
401
+ * completion for one workflow. This reads storage directly, so callers can
402
+ * recover tokens after a process restart before `recoverAll()` repopulates
403
+ * the in-memory completion map.
404
+ */
405
+ listPendingAsyncActivities(workflowId: string, options?: PendingAsyncActivityListOptions): Promise<PendingAsyncActivityPage>;
397
406
  /**
398
407
  * Fail a deferred activity out-of-band with `error`. The error is thrown into
399
408
  * the workflow generator at the parked step — identical to an inline activity
@@ -425,6 +434,21 @@ export declare class Engine<TWorkflows extends object = DefaultWorkflowRegistry,
425
434
  suspend(workflowId: string): Promise<void>;
426
435
  timeout(workflowId: string): Promise<void>;
427
436
  get(workflowId: string): Promise<WorkflowState | null>;
437
+ /** Return the schedule occurrence that launched a workflow, when applicable. */
438
+ getScheduleProvenance(workflowId: string): Promise<WorkflowScheduleProvenance | null>;
439
+ /** Return durable post-terminal finalizer progress or outcome, when applicable. */
440
+ getFinalizerStatus(workflowId: string): Promise<WorkflowFinalizerStatus | null>;
441
+ /**
442
+ * Return this process's last-known ownership-lease health.
443
+ *
444
+ * This is a synchronous diagnostic snapshot: it never performs a storage read
445
+ * and therefore remains available to operator transports after a confirmed
446
+ * deposition has detached the lease manager. Holder identifiers and timestamps
447
+ * are present only while the manager still has its own last-written holder
448
+ * record; a detached deposed engine reports the confirmed loss without
449
+ * inventing successor details.
450
+ */
451
+ getLeaseHealth(): EngineLeaseHealth;
428
452
  getCurrentCheckpointStep(workflowId: string): Promise<number | null>;
429
453
  getAttributes(workflowId: string): Promise<Record<string, SearchAttributeValue> | null>;
430
454
  setAttributes(workflowId: string, attributes: Record<string, SearchAttributeValue>): Promise<void>;
@@ -22,7 +22,10 @@ import {
22
22
  completeAsyncActivity as completeAsyncActivityFromInternals,
23
23
  failAsyncActivity as failAsyncActivityFromInternals
24
24
  } from "./async-activity-completion.js";
25
- import { recoverPendingAsyncActivities } from "./async-activity-records.js";
25
+ import {
26
+ listPendingAsyncActivities as listPendingAsyncActivitiesFromInternals,
27
+ recoverPendingAsyncActivities
28
+ } from "./async-activity-records.js";
26
29
  import { broadcast as broadcastFromInternals } from "./broadcast.js";
27
30
  import {
28
31
  cancelAll as cancelAllWorkflows,
@@ -81,6 +84,7 @@ import {
81
84
  } from "./errors.js";
82
85
  import { assertLeaseHeldForEngineWork, commitFencedEngineWrite } from "./fenced-write.js";
83
86
  import { recordFinalizerState } from "./finalizer-state.js";
87
+ import { getFinalizerStatus as getFinalizerStatusFromInternals } from "./finalizer-status.js";
84
88
  import {
85
89
  createWorkflowHandleWithResultPromise as createWorkflowHandleWithResultPromiseFromInternals,
86
90
  getWorkflowResultPromise as getWorkflowResultPromiseFromInternals
@@ -134,6 +138,7 @@ import {
134
138
  submitReview as submitReviewFromInternals
135
139
  } from "./reviews.js";
136
140
  import { ScheduleHandle } from "./schedule-handle.js";
141
+ import { decodeScheduleRunMetadata } from "./schedule-run-metadata.js";
137
142
  import {
138
143
  cancelSchedule as cancelScheduleFromInternals,
139
144
  listSchedules as listSchedulesFromInternals,
@@ -306,9 +311,12 @@ export class Engine extends EventTarget {
306
311
  getInternals(this).pendingNestingDepth = void 0;
307
312
  getInternals(this).pendingParentHeaders = void 0;
308
313
  getInternals(this).pendingExecutionStateOwnerId = void 0;
314
+ getInternals(this).pendingParentWorkflowId = void 0;
315
+ getInternals(this).pendingParentWorkflowExecutionToken = void 0;
309
316
  getInternals(this).workflowNestingDepths = new Map;
310
317
  getInternals(this).workflowHeaders = new Map;
311
318
  getInternals(this).workflowStateWriteChains = new Map;
319
+ getInternals(this).scheduleStateOperationChains = new Map;
312
320
  getInternals(this).finalizationRegistry = new FinalizationRegistry(createHandleCacheFinalizer(getInternals(this).handleCache));
313
321
  getInternals(this).options = resolvedOptions;
314
322
  getInternals(this).scheduler = new Scheduler({
@@ -641,11 +649,13 @@ export class Engine extends EventTarget {
641
649
  return untagAllWorkflows(getInternals(this), filter, tags, options);
642
650
  }
643
651
  async schedule(typeOrDefinition, input, spec, options) {
652
+ const internals = getInternals(this);
653
+ assertLeaseHeldForEngineWork(internals);
644
654
  if (typeof typeOrDefinition === "object")
645
- return scheduleDefinitionFromInternals(getInternals(this), typeOrDefinition);
655
+ return scheduleDefinitionFromInternals(internals, typeOrDefinition);
646
656
  if (spec === void 0)
647
657
  throw Error("A cron string or schedule spec must be provided when scheduling by workflow type.");
648
- return scheduleFromInternals(getInternals(this), typeOrDefinition, input, spec, options);
658
+ return scheduleFromInternals(internals, typeOrDefinition, input, spec, options);
649
659
  }
650
660
  async getSchedule(scheduleId) {
651
661
  const normalizedScheduleId = coerceScheduleId(scheduleId, "scheduleId"), state = await loadScheduleState(getInternals(this), normalizedScheduleId);
@@ -655,16 +665,24 @@ export class Engine extends EventTarget {
655
665
  return listSchedulesFromInternals(getInternals(this), filter);
656
666
  }
657
667
  async pauseSchedule(scheduleId) {
658
- return pauseScheduleFromInternals(getInternals(this), scheduleId);
668
+ const internals = getInternals(this);
669
+ assertLeaseHeldForEngineWork(internals);
670
+ return pauseScheduleFromInternals(internals, scheduleId);
659
671
  }
660
672
  async resumeSchedule(scheduleId) {
661
- return resumeScheduleFromInternals(getInternals(this), scheduleId);
673
+ const internals = getInternals(this);
674
+ assertLeaseHeldForEngineWork(internals);
675
+ return resumeScheduleFromInternals(internals, scheduleId);
662
676
  }
663
677
  async cancelSchedule(scheduleId) {
664
- return cancelScheduleFromInternals(getInternals(this), scheduleId);
678
+ const internals = getInternals(this);
679
+ assertLeaseHeldForEngineWork(internals);
680
+ return cancelScheduleFromInternals(internals, scheduleId);
665
681
  }
666
- async updateSchedule(scheduleId, newSpec) {
667
- return updateScheduleFromInternals(getInternals(this), scheduleId, newSpec);
682
+ async updateSchedule(scheduleId, newSpec, options) {
683
+ const internals = getInternals(this);
684
+ assertLeaseHeldForEngineWork(internals);
685
+ return updateScheduleFromInternals(internals, scheduleId, newSpec, options);
668
686
  }
669
687
  [HANDLE_RESULT_PROMISE](workflowId) {
670
688
  return getWorkflowResultPromiseFromInternals(getInternals(this), workflowId);
@@ -721,6 +739,9 @@ export class Engine extends EventTarget {
721
739
  finalizeTimeline: (workflowId, status, output) => finalizePendingTimelineEntry(getInternals(this), workflowId, status, output)
722
740
  });
723
741
  }
742
+ async listPendingAsyncActivities(workflowId, options) {
743
+ return listPendingAsyncActivitiesFromInternals(getInternals(this), workflowId, options);
744
+ }
724
745
  async failAsyncActivity(token, error) {
725
746
  await failAsyncActivityFromInternals(getInternals(this), token, error, {
726
747
  feedOperationResult: (workflowId, outcome, originalReason) => feedOperationResult(getInternals(this), workflowId, outcome, originalReason),
@@ -742,6 +763,48 @@ export class Engine extends EventTarget {
742
763
  return { ...state, status: "pending" };
743
764
  return state;
744
765
  }
766
+ async getScheduleProvenance(workflowId) {
767
+ const bytes = await getInternals(this).storage.get(KEYS.scheduleRunLink(workflowId));
768
+ if (bytes === null)
769
+ return null;
770
+ const metadata = decodeScheduleRunMetadata(bytes);
771
+ if (metadata === null)
772
+ return null;
773
+ return {
774
+ scheduleId: metadata.id,
775
+ ...metadata.occurrence === void 0 ? {} : { occurrence: metadata.occurrence }
776
+ };
777
+ }
778
+ async getFinalizerStatus(workflowId) {
779
+ const internals = getInternals(this), state = await loadWorkflowState(internals, workflowId);
780
+ return getFinalizerStatusFromInternals(internals, workflowId, state);
781
+ }
782
+ getLeaseHealth() {
783
+ const internals = getInternals(this);
784
+ if (internals.options.ownershipMode === "none")
785
+ return { mode: "none", status: "disabled", holdsLease: !1 };
786
+ if (internals.deposed) {
787
+ const lastKnownLease = internals.leaseManager?.health();
788
+ if (lastKnownLease !== void 0 && lastKnownLease.status !== "no-lease")
789
+ return {
790
+ mode: "lease",
791
+ ...lastKnownLease,
792
+ status: "contested",
793
+ holdsLease: !1,
794
+ lossReason: "deposed"
795
+ };
796
+ return {
797
+ mode: "lease",
798
+ status: "contested",
799
+ holdsLease: !1,
800
+ lossReason: "deposed"
801
+ };
802
+ }
803
+ return {
804
+ mode: "lease",
805
+ ...internals.leaseManager?.health() ?? { status: "no-lease", holdsLease: !1 }
806
+ };
807
+ }
745
808
  async getCurrentCheckpointStep(workflowId) {
746
809
  const inMemory = getInternals(this).checkpoints.get(workflowId);
747
810
  if (inMemory !== void 0)