@workflow/core 4.0.1-beta.9 → 4.1.0-beta.52

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 (184) hide show
  1. package/dist/builtins.js +1 -1
  2. package/dist/class-serialization.d.ts +26 -0
  3. package/dist/class-serialization.d.ts.map +1 -0
  4. package/dist/class-serialization.js +66 -0
  5. package/dist/create-hook.js +1 -1
  6. package/dist/define-hook.d.ts +40 -25
  7. package/dist/define-hook.d.ts.map +1 -1
  8. package/dist/define-hook.js +22 -27
  9. package/dist/events-consumer.d.ts.map +1 -1
  10. package/dist/events-consumer.js +5 -1
  11. package/dist/flushable-stream.d.ts +82 -0
  12. package/dist/flushable-stream.d.ts.map +1 -0
  13. package/dist/flushable-stream.js +214 -0
  14. package/dist/global.d.ts +4 -1
  15. package/dist/global.d.ts.map +1 -1
  16. package/dist/global.js +21 -9
  17. package/dist/index.d.ts +2 -2
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +2 -2
  20. package/dist/logger.js +1 -1
  21. package/dist/observability.d.ts +60 -0
  22. package/dist/observability.d.ts.map +1 -1
  23. package/dist/observability.js +265 -32
  24. package/dist/private.d.ts +10 -1
  25. package/dist/private.d.ts.map +1 -1
  26. package/dist/private.js +6 -1
  27. package/dist/runtime/helpers.d.ts +52 -0
  28. package/dist/runtime/helpers.d.ts.map +1 -0
  29. package/dist/runtime/helpers.js +264 -0
  30. package/dist/runtime/resume-hook.d.ts +17 -12
  31. package/dist/runtime/resume-hook.d.ts.map +1 -1
  32. package/dist/runtime/resume-hook.js +79 -64
  33. package/dist/runtime/run.d.ts +100 -0
  34. package/dist/runtime/run.d.ts.map +1 -0
  35. package/dist/runtime/run.js +132 -0
  36. package/dist/runtime/start.d.ts +15 -1
  37. package/dist/runtime/start.d.ts.map +1 -1
  38. package/dist/runtime/start.js +72 -46
  39. package/dist/runtime/step-handler.d.ts +7 -0
  40. package/dist/runtime/step-handler.d.ts.map +1 -0
  41. package/dist/runtime/step-handler.js +337 -0
  42. package/dist/runtime/suspension-handler.d.ts +25 -0
  43. package/dist/runtime/suspension-handler.d.ts.map +1 -0
  44. package/dist/runtime/suspension-handler.js +182 -0
  45. package/dist/runtime/world.d.ts.map +1 -1
  46. package/dist/runtime/world.js +20 -21
  47. package/dist/runtime.d.ts +4 -105
  48. package/dist/runtime.d.ts.map +1 -1
  49. package/dist/runtime.js +97 -531
  50. package/dist/schemas.d.ts +1 -15
  51. package/dist/schemas.d.ts.map +1 -1
  52. package/dist/schemas.js +2 -15
  53. package/dist/serialization.d.ts +112 -21
  54. package/dist/serialization.d.ts.map +1 -1
  55. package/dist/serialization.js +469 -85
  56. package/dist/sleep.d.ts +10 -0
  57. package/dist/sleep.d.ts.map +1 -1
  58. package/dist/sleep.js +1 -1
  59. package/dist/source-map.d.ts +10 -0
  60. package/dist/source-map.d.ts.map +1 -0
  61. package/dist/source-map.js +56 -0
  62. package/dist/step/context-storage.d.ts +2 -1
  63. package/dist/step/context-storage.d.ts.map +1 -1
  64. package/dist/step/context-storage.js +1 -1
  65. package/dist/step/get-closure-vars.d.ts +9 -0
  66. package/dist/step/get-closure-vars.d.ts.map +1 -0
  67. package/dist/step/get-closure-vars.js +16 -0
  68. package/dist/step/get-step-metadata.js +1 -1
  69. package/dist/step/get-workflow-metadata.js +1 -1
  70. package/dist/step/writable-stream.d.ts +10 -2
  71. package/dist/step/writable-stream.d.ts.map +1 -1
  72. package/dist/step/writable-stream.js +6 -5
  73. package/dist/step.d.ts +1 -1
  74. package/dist/step.d.ts.map +1 -1
  75. package/dist/step.js +93 -47
  76. package/dist/symbols.d.ts +6 -0
  77. package/dist/symbols.d.ts.map +1 -1
  78. package/dist/symbols.js +7 -1
  79. package/dist/telemetry/semantic-conventions.d.ts +66 -38
  80. package/dist/telemetry/semantic-conventions.d.ts.map +1 -1
  81. package/dist/telemetry/semantic-conventions.js +16 -3
  82. package/dist/telemetry.d.ts +8 -4
  83. package/dist/telemetry.d.ts.map +1 -1
  84. package/dist/telemetry.js +39 -6
  85. package/dist/types.js +1 -1
  86. package/dist/util.d.ts +5 -24
  87. package/dist/util.d.ts.map +1 -1
  88. package/dist/util.js +19 -38
  89. package/dist/version.d.ts +2 -0
  90. package/dist/version.d.ts.map +1 -0
  91. package/dist/version.js +3 -0
  92. package/dist/vm/index.js +2 -2
  93. package/dist/vm/uuid.js +1 -1
  94. package/dist/workflow/create-hook.js +1 -1
  95. package/dist/workflow/define-hook.d.ts +3 -3
  96. package/dist/workflow/define-hook.d.ts.map +1 -1
  97. package/dist/workflow/define-hook.js +1 -1
  98. package/dist/workflow/get-workflow-metadata.js +1 -1
  99. package/dist/workflow/hook.d.ts.map +1 -1
  100. package/dist/workflow/hook.js +49 -14
  101. package/dist/workflow/index.d.ts +1 -1
  102. package/dist/workflow/index.d.ts.map +1 -1
  103. package/dist/workflow/index.js +2 -2
  104. package/dist/workflow/sleep.d.ts +1 -1
  105. package/dist/workflow/sleep.d.ts.map +1 -1
  106. package/dist/workflow/sleep.js +26 -39
  107. package/dist/workflow/writable-stream.d.ts +1 -1
  108. package/dist/workflow/writable-stream.d.ts.map +1 -1
  109. package/dist/workflow/writable-stream.js +1 -1
  110. package/dist/workflow.d.ts +1 -1
  111. package/dist/workflow.d.ts.map +1 -1
  112. package/dist/workflow.js +72 -9
  113. package/docs/api-reference/create-hook.mdx +134 -0
  114. package/docs/api-reference/create-webhook.mdx +226 -0
  115. package/docs/api-reference/define-hook.mdx +207 -0
  116. package/docs/api-reference/fatal-error.mdx +38 -0
  117. package/docs/api-reference/fetch.mdx +140 -0
  118. package/docs/api-reference/get-step-metadata.mdx +77 -0
  119. package/docs/api-reference/get-workflow-metadata.mdx +45 -0
  120. package/docs/api-reference/get-writable.mdx +292 -0
  121. package/docs/api-reference/index.mdx +56 -0
  122. package/docs/api-reference/meta.json +3 -0
  123. package/docs/api-reference/retryable-error.mdx +107 -0
  124. package/docs/api-reference/sleep.mdx +60 -0
  125. package/docs/foundations/common-patterns.mdx +254 -0
  126. package/docs/foundations/errors-and-retries.mdx +191 -0
  127. package/docs/foundations/hooks.mdx +456 -0
  128. package/docs/foundations/idempotency.mdx +56 -0
  129. package/docs/foundations/index.mdx +33 -0
  130. package/docs/foundations/meta.json +14 -0
  131. package/docs/foundations/serialization.mdx +158 -0
  132. package/docs/foundations/starting-workflows.mdx +212 -0
  133. package/docs/foundations/streaming.mdx +570 -0
  134. package/docs/foundations/workflows-and-steps.mdx +198 -0
  135. package/docs/how-it-works/code-transform.mdx +335 -0
  136. package/docs/how-it-works/event-sourcing.mdx +255 -0
  137. package/docs/how-it-works/framework-integrations.mdx +438 -0
  138. package/docs/how-it-works/meta.json +10 -0
  139. package/docs/how-it-works/understanding-directives.mdx +612 -0
  140. package/package.json +31 -25
  141. package/dist/builtins.js.map +0 -1
  142. package/dist/create-hook.js.map +0 -1
  143. package/dist/define-hook.js.map +0 -1
  144. package/dist/events-consumer.js.map +0 -1
  145. package/dist/global.js.map +0 -1
  146. package/dist/index.js.map +0 -1
  147. package/dist/logger.js.map +0 -1
  148. package/dist/observability.js.map +0 -1
  149. package/dist/parse-name.d.ts +0 -25
  150. package/dist/parse-name.d.ts.map +0 -1
  151. package/dist/parse-name.js +0 -40
  152. package/dist/parse-name.js.map +0 -1
  153. package/dist/private.js.map +0 -1
  154. package/dist/runtime/resume-hook.js.map +0 -1
  155. package/dist/runtime/start.js.map +0 -1
  156. package/dist/runtime/world.js.map +0 -1
  157. package/dist/runtime.js.map +0 -1
  158. package/dist/schemas.js.map +0 -1
  159. package/dist/serialization.js.map +0 -1
  160. package/dist/sleep.js.map +0 -1
  161. package/dist/step/context-storage.js.map +0 -1
  162. package/dist/step/get-step-metadata.js.map +0 -1
  163. package/dist/step/get-workflow-metadata.js.map +0 -1
  164. package/dist/step/writable-stream.js.map +0 -1
  165. package/dist/step.js.map +0 -1
  166. package/dist/symbols.js.map +0 -1
  167. package/dist/telemetry/semantic-conventions.js.map +0 -1
  168. package/dist/telemetry.js.map +0 -1
  169. package/dist/types.js.map +0 -1
  170. package/dist/util.js.map +0 -1
  171. package/dist/vm/index.js.map +0 -1
  172. package/dist/vm/uuid.js.map +0 -1
  173. package/dist/workflow/create-hook.js.map +0 -1
  174. package/dist/workflow/define-hook.js.map +0 -1
  175. package/dist/workflow/get-workflow-metadata.js.map +0 -1
  176. package/dist/workflow/hook.js.map +0 -1
  177. package/dist/workflow/index.js.map +0 -1
  178. package/dist/workflow/sleep.js.map +0 -1
  179. package/dist/workflow/writable-stream.js.map +0 -1
  180. package/dist/workflow.js.map +0 -1
  181. package/dist/writable-stream.d.ts +0 -23
  182. package/dist/writable-stream.d.ts.map +0 -1
  183. package/dist/writable-stream.js +0 -17
  184. package/dist/writable-stream.js.map +0 -1
@@ -0,0 +1,337 @@
1
+ import { waitUntil } from '@vercel/functions';
2
+ import { FatalError, RetryableError, WorkflowAPIError, WorkflowRuntimeError, } from '@workflow/errors';
3
+ import { pluralize } from '@workflow/utils';
4
+ import { getPort } from '@workflow/utils/get-port';
5
+ import { SPEC_VERSION_CURRENT, StepInvokePayloadSchema } from '@workflow/world';
6
+ import { runtimeLogger } from '../logger.js';
7
+ import { getStepFunction } from '../private.js';
8
+ import { dehydrateStepReturnValue, hydrateStepArguments, } from '../serialization.js';
9
+ import { contextStorage } from '../step/context-storage.js';
10
+ import * as Attribute from '../telemetry/semantic-conventions.js';
11
+ import { getSpanKind, linkToCurrentContext, serializeTraceCarrier, trace, withTraceContext, } from '../telemetry.js';
12
+ import { getErrorName, getErrorStack } from '../types.js';
13
+ import { getQueueOverhead, handleHealthCheckMessage, parseHealthCheckPayload, queueMessage, withHealthCheck, } from './helpers.js';
14
+ import { getWorld, getWorldHandlers } from './world.js';
15
+ const DEFAULT_STEP_MAX_RETRIES = 3;
16
+ const stepHandler = getWorldHandlers().createQueueHandler('__wkf_step_', async (message_, metadata) => {
17
+ // Check if this is a health check message
18
+ // NOTE: Health check messages are intentionally unauthenticated for monitoring purposes.
19
+ // They only write a simple status response to a stream and do not expose sensitive data.
20
+ // The stream name includes a unique correlationId that must be known by the caller.
21
+ const healthCheck = parseHealthCheckPayload(message_);
22
+ if (healthCheck) {
23
+ await handleHealthCheckMessage(healthCheck, 'step');
24
+ return;
25
+ }
26
+ const { workflowName, workflowRunId, workflowStartedAt, stepId, traceCarrier: traceContext, requestedAt, } = StepInvokePayloadSchema.parse(message_);
27
+ const spanLinks = await linkToCurrentContext();
28
+ // Execute step within the propagated trace context
29
+ return await withTraceContext(traceContext, async () => {
30
+ // Extract the step name from the topic name
31
+ const stepName = metadata.queueName.slice('__wkf_step_'.length);
32
+ const world = getWorld();
33
+ // Get the port early to avoid async operations during step execution
34
+ const port = await getPort();
35
+ return trace(`STEP ${stepName}`, { kind: await getSpanKind('CONSUMER'), links: spanLinks }, async (span) => {
36
+ span?.setAttributes({
37
+ ...Attribute.StepName(stepName),
38
+ ...Attribute.StepAttempt(metadata.attempt),
39
+ ...Attribute.QueueName(metadata.queueName),
40
+ ...Attribute.QueueMessageId(metadata.messageId),
41
+ ...getQueueOverhead({ requestedAt }),
42
+ });
43
+ const stepFn = getStepFunction(stepName);
44
+ if (!stepFn) {
45
+ throw new Error(`Step "${stepName}" not found`);
46
+ }
47
+ if (typeof stepFn !== 'function') {
48
+ throw new Error(`Step "${stepName}" is not a function (got ${typeof stepFn})`);
49
+ }
50
+ const maxRetries = stepFn.maxRetries ?? DEFAULT_STEP_MAX_RETRIES;
51
+ span?.setAttributes({
52
+ ...Attribute.WorkflowName(workflowName),
53
+ ...Attribute.WorkflowRunId(workflowRunId),
54
+ ...Attribute.StepId(stepId),
55
+ ...Attribute.StepMaxRetries(maxRetries),
56
+ ...Attribute.StepTracePropagated(!!traceContext),
57
+ });
58
+ let step = await world.steps.get(workflowRunId, stepId);
59
+ runtimeLogger.debug('Step execution details', {
60
+ stepName,
61
+ stepId: step.stepId,
62
+ status: step.status,
63
+ attempt: step.attempt,
64
+ });
65
+ span?.setAttributes({
66
+ ...Attribute.StepStatus(step.status),
67
+ });
68
+ // Check if the step has a `retryAfter` timestamp that hasn't been reached yet
69
+ const now = Date.now();
70
+ if (step.retryAfter && step.retryAfter.getTime() > now) {
71
+ const timeoutSeconds = Math.ceil((step.retryAfter.getTime() - now) / 1000);
72
+ span?.setAttributes({
73
+ ...Attribute.StepRetryTimeoutSeconds(timeoutSeconds),
74
+ });
75
+ runtimeLogger.debug('Step retryAfter timestamp not yet reached', {
76
+ stepName,
77
+ stepId: step.stepId,
78
+ retryAfter: step.retryAfter,
79
+ timeoutSeconds,
80
+ });
81
+ return { timeoutSeconds };
82
+ }
83
+ let result;
84
+ // Check max retries FIRST before any state changes.
85
+ // step.attempt tracks how many times step_started has been called.
86
+ // If step.attempt >= maxRetries, we've already tried maxRetries times.
87
+ // This handles edge cases where the step handler is invoked after max retries have been exceeded
88
+ // (e.g., when the step repeatedly times out or fails before reaching the catch handler).
89
+ // Without this check, the step would retry forever.
90
+ // Note: maxRetries is the number of RETRIES after the first attempt, so total attempts = maxRetries + 1
91
+ // Use > here (not >=) because this guards against re-invocation AFTER all attempts are used.
92
+ // The post-failure check uses >= to decide whether to retry after a failure.
93
+ if (step.attempt > maxRetries + 1) {
94
+ const retryCount = step.attempt - 1;
95
+ const errorMessage = `Step "${stepName}" exceeded max retries (${retryCount} ${pluralize('retry', 'retries', retryCount)})`;
96
+ console.error(`[Workflows] "${workflowRunId}" - ${errorMessage}`);
97
+ // Fail the step via event (event-sourced architecture)
98
+ await world.events.create(workflowRunId, {
99
+ eventType: 'step_failed',
100
+ specVersion: SPEC_VERSION_CURRENT,
101
+ correlationId: stepId,
102
+ eventData: {
103
+ error: errorMessage,
104
+ stack: step.error?.stack,
105
+ },
106
+ });
107
+ span?.setAttributes({
108
+ ...Attribute.StepStatus('failed'),
109
+ ...Attribute.StepRetryExhausted(true),
110
+ });
111
+ // Re-invoke the workflow to handle the failed step
112
+ await queueMessage(world, `__wkf_workflow_${workflowName}`, {
113
+ runId: workflowRunId,
114
+ traceCarrier: await serializeTraceCarrier(),
115
+ requestedAt: new Date(),
116
+ });
117
+ return;
118
+ }
119
+ try {
120
+ if (!['pending', 'running'].includes(step.status)) {
121
+ // We should only be running the step if it's either
122
+ // a) pending - initial state, or state set on re-try
123
+ // b) running - if a step fails mid-execution, like a function timeout
124
+ // otherwise, the step has been invoked erroneously
125
+ console.error(`[Workflows] "${workflowRunId}" - Step invoked erroneously, expected status "pending" or "running", got "${step.status}" instead, skipping execution`);
126
+ span?.setAttributes({
127
+ ...Attribute.StepSkipped(true),
128
+ ...Attribute.StepSkipReason(step.status),
129
+ });
130
+ // There's a chance that a step terminates correctly, but the underlying process
131
+ // fails or gets killed before the stepEntrypoint has a chance to re-enqueue the run.
132
+ // The queue lease expires and stepEntrypoint again, which leads us here, so
133
+ // we optimistically re-enqueue the workflow if the step is in a terminal state,
134
+ // under the assumption that this edge case happened.
135
+ // Until we move to atomic entity/event updates (World V2), there _could_ be an edge case
136
+ // where the we execute this code based on the `step` entity status, but the runtime
137
+ // failed to create the `step_completed` event (due to failing between step and event update),
138
+ // in which case, this might lead to an infinite loop.
139
+ // https://vercel.slack.com/archives/C09125LC4AX/p1765313809066679
140
+ const isTerminalStep = [
141
+ 'completed',
142
+ 'failed',
143
+ 'cancelled',
144
+ ].includes(step.status);
145
+ if (isTerminalStep) {
146
+ await queueMessage(world, `__wkf_workflow_${workflowName}`, {
147
+ runId: workflowRunId,
148
+ traceCarrier: await serializeTraceCarrier(),
149
+ requestedAt: new Date(),
150
+ });
151
+ }
152
+ return;
153
+ }
154
+ // Start the step via event (event-sourced architecture)
155
+ // step_started increments the attempt counter in the World implementation
156
+ const startResult = await world.events.create(workflowRunId, {
157
+ eventType: 'step_started',
158
+ specVersion: SPEC_VERSION_CURRENT,
159
+ correlationId: stepId,
160
+ });
161
+ // Use the step entity from the event response (no extra get call needed)
162
+ if (!startResult.step) {
163
+ throw new WorkflowRuntimeError(`step_started event for "${stepId}" did not return step entity`);
164
+ }
165
+ step = startResult.step;
166
+ // step.attempt is now the current attempt number (after increment)
167
+ const attempt = step.attempt;
168
+ if (!step.startedAt) {
169
+ throw new WorkflowRuntimeError(`Step "${stepId}" has no "startedAt" timestamp`);
170
+ }
171
+ // Hydrate the step input arguments, closure variables, and thisVal
172
+ const ops = [];
173
+ const hydratedInput = hydrateStepArguments(step.input, ops, workflowRunId);
174
+ const args = hydratedInput.args;
175
+ const thisVal = hydratedInput.thisVal ?? null;
176
+ span?.setAttributes({
177
+ ...Attribute.StepArgumentsCount(args.length),
178
+ });
179
+ result = await contextStorage.run({
180
+ stepMetadata: {
181
+ stepId,
182
+ stepStartedAt: new Date(+step.startedAt),
183
+ attempt,
184
+ },
185
+ workflowMetadata: {
186
+ workflowRunId,
187
+ workflowStartedAt: new Date(+workflowStartedAt),
188
+ // TODO: there should be a getUrl method on the world interface itself. This
189
+ // solution only works for vercel + local worlds.
190
+ url: process.env.VERCEL_URL
191
+ ? `https://${process.env.VERCEL_URL}`
192
+ : `http://localhost:${port ?? 3000}`,
193
+ },
194
+ ops,
195
+ closureVars: hydratedInput.closureVars,
196
+ }, () => stepFn.apply(thisVal, args));
197
+ // NOTE: None of the code from this point is guaranteed to run
198
+ // Since the step might fail or cause a function timeout and the process might be SIGKILL'd
199
+ // The workflow runtime must be resilient to the below code not executing on a failed step
200
+ result = dehydrateStepReturnValue(result, ops, workflowRunId);
201
+ waitUntil(Promise.all(ops).catch((err) => {
202
+ // Ignore expected client disconnect errors (e.g., browser refresh during streaming)
203
+ const isAbortError = err?.name === 'AbortError' || err?.name === 'ResponseAborted';
204
+ if (!isAbortError)
205
+ throw err;
206
+ }));
207
+ // Complete the step via event (event-sourced architecture)
208
+ // The event creation atomically updates the step entity
209
+ // result was dehydrated above by dehydrateStepReturnValue, which returns Uint8Array
210
+ await world.events.create(workflowRunId, {
211
+ eventType: 'step_completed',
212
+ specVersion: SPEC_VERSION_CURRENT,
213
+ correlationId: stepId,
214
+ eventData: {
215
+ result: result,
216
+ },
217
+ });
218
+ span?.setAttributes({
219
+ ...Attribute.StepStatus('completed'),
220
+ ...Attribute.StepResultType(typeof result),
221
+ });
222
+ }
223
+ catch (err) {
224
+ span?.setAttributes({
225
+ ...Attribute.StepErrorName(getErrorName(err)),
226
+ ...Attribute.StepErrorMessage(String(err)),
227
+ });
228
+ if (WorkflowAPIError.is(err)) {
229
+ if (err.status === 410) {
230
+ // Workflow has already completed, so no-op
231
+ console.warn(`Workflow run "${workflowRunId}" has already completed, skipping step "${stepId}": ${err.message}`);
232
+ return;
233
+ }
234
+ }
235
+ if (FatalError.is(err)) {
236
+ const errorStack = getErrorStack(err);
237
+ const stackLines = errorStack.split('\n').slice(0, 4);
238
+ console.error(`[Workflows] "${workflowRunId}" - Encountered \`FatalError\` while executing step "${stepName}":\n > ${stackLines.join('\n > ')}\n\nBubbling up error to parent workflow`);
239
+ // Fail the step via event (event-sourced architecture)
240
+ await world.events.create(workflowRunId, {
241
+ eventType: 'step_failed',
242
+ specVersion: SPEC_VERSION_CURRENT,
243
+ correlationId: stepId,
244
+ eventData: {
245
+ error: String(err),
246
+ stack: errorStack,
247
+ },
248
+ });
249
+ span?.setAttributes({
250
+ ...Attribute.StepStatus('failed'),
251
+ ...Attribute.StepFatalError(true),
252
+ });
253
+ }
254
+ else {
255
+ const maxRetries = stepFn.maxRetries ?? DEFAULT_STEP_MAX_RETRIES;
256
+ // step.attempt was incremented by step_started, use it here
257
+ const currentAttempt = step.attempt;
258
+ span?.setAttributes({
259
+ ...Attribute.StepAttempt(currentAttempt),
260
+ ...Attribute.StepMaxRetries(maxRetries),
261
+ });
262
+ // Note: maxRetries is the number of RETRIES after the first attempt, so total attempts = maxRetries + 1
263
+ if (currentAttempt >= maxRetries + 1) {
264
+ // Max retries reached
265
+ const errorStack = getErrorStack(err);
266
+ const stackLines = errorStack.split('\n').slice(0, 4);
267
+ const retryCount = step.attempt - 1;
268
+ console.error(`[Workflows] "${workflowRunId}" - Encountered \`Error\` while executing step "${stepName}" (attempt ${step.attempt}, ${retryCount} ${pluralize('retry', 'retries', retryCount)}):\n > ${stackLines.join('\n > ')}\n\n Max retries reached\n Bubbling error to parent workflow`);
269
+ const errorMessage = `Step "${stepName}" failed after ${maxRetries} ${pluralize('retry', 'retries', maxRetries)}: ${String(err)}`;
270
+ // Fail the step via event (event-sourced architecture)
271
+ await world.events.create(workflowRunId, {
272
+ eventType: 'step_failed',
273
+ specVersion: SPEC_VERSION_CURRENT,
274
+ correlationId: stepId,
275
+ eventData: {
276
+ error: errorMessage,
277
+ stack: errorStack,
278
+ },
279
+ });
280
+ span?.setAttributes({
281
+ ...Attribute.StepStatus('failed'),
282
+ ...Attribute.StepRetryExhausted(true),
283
+ });
284
+ }
285
+ else {
286
+ // Not at max retries yet - log as a retryable error
287
+ if (RetryableError.is(err)) {
288
+ console.warn(`[Workflows] "${workflowRunId}" - Encountered \`RetryableError\` while executing step "${stepName}" (attempt ${currentAttempt}):\n > ${String(err.message)}\n\n This step has failed but will be retried`);
289
+ }
290
+ else {
291
+ const stackLines = getErrorStack(err).split('\n').slice(0, 4);
292
+ console.error(`[Workflows] "${workflowRunId}" - Encountered \`Error\` while executing step "${stepName}" (attempt ${currentAttempt}):\n > ${stackLines.join('\n > ')}\n\n This step has failed but will be retried`);
293
+ }
294
+ // Set step to pending for retry via event (event-sourced architecture)
295
+ // step_retrying records the error and sets status to pending
296
+ const errorStack = getErrorStack(err);
297
+ await world.events.create(workflowRunId, {
298
+ eventType: 'step_retrying',
299
+ specVersion: SPEC_VERSION_CURRENT,
300
+ correlationId: stepId,
301
+ eventData: {
302
+ error: String(err),
303
+ stack: errorStack,
304
+ ...(RetryableError.is(err) && {
305
+ retryAfter: err.retryAfter,
306
+ }),
307
+ },
308
+ });
309
+ const timeoutSeconds = Math.max(1, RetryableError.is(err)
310
+ ? Math.ceil((+err.retryAfter.getTime() - Date.now()) / 1000)
311
+ : 1);
312
+ span?.setAttributes({
313
+ ...Attribute.StepRetryTimeoutSeconds(timeoutSeconds),
314
+ ...Attribute.StepRetryWillRetry(true),
315
+ });
316
+ // It's a retryable error - so have the queue keep the message visible
317
+ // so that it gets retried.
318
+ return { timeoutSeconds };
319
+ }
320
+ }
321
+ }
322
+ await queueMessage(world, `__wkf_workflow_${workflowName}`, {
323
+ runId: workflowRunId,
324
+ traceCarrier: await serializeTraceCarrier(),
325
+ requestedAt: new Date(),
326
+ });
327
+ });
328
+ });
329
+ });
330
+ /**
331
+ * A single route that handles any step execution request and routes to the
332
+ * appropriate step function. We may eventually want to create different bundles
333
+ * for each step, this is temporary.
334
+ */
335
+ export const stepEntrypoint =
336
+ /* @__PURE__ */ withHealthCheck(stepHandler);
337
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RlcC1oYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3J1bnRpbWUvc3RlcC1oYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUM5QyxPQUFPLEVBQ0wsVUFBVSxFQUNWLGNBQWMsRUFDZCxnQkFBZ0IsRUFDaEIsb0JBQW9CLEdBQ3JCLE1BQU0sa0JBQWtCLENBQUM7QUFDMUIsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzVDLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUNuRCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNoRixPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQzdDLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDaEQsT0FBTyxFQUNMLHdCQUF3QixFQUN4QixvQkFBb0IsR0FDckIsTUFBTSxxQkFBcUIsQ0FBQztBQUM3QixPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDNUQsT0FBTyxLQUFLLFNBQVMsTUFBTSxzQ0FBc0MsQ0FBQztBQUNsRSxPQUFPLEVBQ0wsV0FBVyxFQUNYLG9CQUFvQixFQUNwQixxQkFBcUIsRUFDckIsS0FBSyxFQUNMLGdCQUFnQixHQUNqQixNQUFNLGlCQUFpQixDQUFDO0FBQ3pCLE9BQU8sRUFBRSxZQUFZLEVBQUUsYUFBYSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQzFELE9BQU8sRUFDTCxnQkFBZ0IsRUFDaEIsd0JBQXdCLEVBQ3hCLHVCQUF1QixFQUN2QixZQUFZLEVBQ1osZUFBZSxHQUNoQixNQUFNLGNBQWMsQ0FBQztBQUN0QixPQUFPLEVBQUUsUUFBUSxFQUFFLGdCQUFnQixFQUFFLE1BQU0sWUFBWSxDQUFDO0FBRXhELE1BQU0sd0JBQXdCLEdBQUcsQ0FBQyxDQUFDO0FBRW5DLE1BQU0sV0FBVyxHQUFHLGdCQUFnQixFQUFFLENBQUMsa0JBQWtCLENBQ3ZELGFBQWEsRUFDYixLQUFLLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRSxFQUFFO0lBQzNCLDBDQUEwQztJQUMxQyx5RkFBeUY7SUFDekYseUZBQXlGO0lBQ3pGLG9GQUFvRjtJQUNwRixNQUFNLFdBQVcsR0FBRyx1QkFBdUIsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUN0RCxJQUFJLFdBQVcsRUFBRSxDQUFDO1FBQ2hCLE1BQU0sd0JBQXdCLENBQUMsV0FBVyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQ3BELE9BQU87SUFDVCxDQUFDO0lBRUQsTUFBTSxFQUNKLFlBQVksRUFDWixhQUFhLEVBQ2IsaUJBQWlCLEVBQ2pCLE1BQU0sRUFDTixZQUFZLEVBQUUsWUFBWSxFQUMxQixXQUFXLEdBQ1osR0FBRyx1QkFBdUIsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDNUMsTUFBTSxTQUFTLEdBQUcsTUFBTSxvQkFBb0IsRUFBRSxDQUFDO0lBQy9DLG1EQUFtRDtJQUNuRCxPQUFPLE1BQU0sZ0JBQWdCLENBQUMsWUFBWSxFQUFFLEtBQUssSUFBSSxFQUFFO1FBQ3JELDRDQUE0QztRQUM1QyxNQUFNLFFBQVEsR0FBRyxRQUFRLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDaEUsTUFBTSxLQUFLLEdBQUcsUUFBUSxFQUFFLENBQUM7UUFFekIscUVBQXFFO1FBQ3JFLE1BQU0sSUFBSSxHQUFHLE1BQU0sT0FBTyxFQUFFLENBQUM7UUFFN0IsT0FBTyxLQUFLLENBQ1YsUUFBUSxRQUFRLEVBQUUsRUFDbEIsRUFBRSxJQUFJLEVBQUUsTUFBTSxXQUFXLENBQUMsVUFBVSxDQUFDLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxFQUN6RCxLQUFLLEVBQUUsSUFBSSxFQUFFLEVBQUU7WUFDYixJQUFJLEVBQUUsYUFBYSxDQUFDO2dCQUNsQixHQUFHLFNBQVMsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDO2dCQUMvQixHQUFHLFNBQVMsQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQztnQkFDMUMsR0FBRyxTQUFTLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUM7Z0JBQzFDLEdBQUcsU0FBUyxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDO2dCQUMvQyxHQUFHLGdCQUFnQixDQUFDLEVBQUUsV0FBVyxFQUFFLENBQUM7YUFDckMsQ0FBQyxDQUFDO1lBRUgsTUFBTSxNQUFNLEdBQUcsZUFBZSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQ3pDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztnQkFDWixNQUFNLElBQUksS0FBSyxDQUFDLFNBQVMsUUFBUSxhQUFhLENBQUMsQ0FBQztZQUNsRCxDQUFDO1lBQ0QsSUFBSSxPQUFPLE1BQU0sS0FBSyxVQUFVLEVBQUUsQ0FBQztnQkFDakMsTUFBTSxJQUFJLEtBQUssQ0FDYixTQUFTLFFBQVEsNEJBQTRCLE9BQU8sTUFBTSxHQUFHLENBQzlELENBQUM7WUFDSixDQUFDO1lBRUQsTUFBTSxVQUFVLEdBQUcsTUFBTSxDQUFDLFVBQVUsSUFBSSx3QkFBd0IsQ0FBQztZQUVqRSxJQUFJLEVBQUUsYUFBYSxDQUFDO2dCQUNsQixHQUFHLFNBQVMsQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUFDO2dCQUN2QyxHQUFHLFNBQVMsQ0FBQyxhQUFhLENBQUMsYUFBYSxDQUFDO2dCQUN6QyxHQUFHLFNBQVMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDO2dCQUMzQixHQUFHLFNBQVMsQ0FBQyxjQUFjLENBQUMsVUFBVSxDQUFDO2dCQUN2QyxHQUFHLFNBQVMsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDO2FBQ2pELENBQUMsQ0FBQztZQUVILElBQUksSUFBSSxHQUFHLE1BQU0sS0FBSyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsYUFBYSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBRXhELGFBQWEsQ0FBQyxLQUFLLENBQUMsd0JBQXdCLEVBQUU7Z0JBQzVDLFFBQVE7Z0JBQ1IsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNO2dCQUNuQixNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU07Z0JBQ25CLE9BQU8sRUFBRSxJQUFJLENBQUMsT0FBTzthQUN0QixDQUFDLENBQUM7WUFFSCxJQUFJLEVBQUUsYUFBYSxDQUFDO2dCQUNsQixHQUFHLFNBQVMsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQzthQUNyQyxDQUFDLENBQUM7WUFFSCw4RUFBOEU7WUFDOUUsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1lBQ3ZCLElBQUksSUFBSSxDQUFDLFVBQVUsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxHQUFHLEdBQUcsRUFBRSxDQUFDO2dCQUN2RCxNQUFNLGNBQWMsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUM5QixDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTyxFQUFFLEdBQUcsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUN6QyxDQUFDO2dCQUNGLElBQUksRUFBRSxhQUFhLENBQUM7b0JBQ2xCLEdBQUcsU0FBUyxDQUFDLHVCQUF1QixDQUFDLGNBQWMsQ0FBQztpQkFDckQsQ0FBQyxDQUFDO2dCQUNILGFBQWEsQ0FBQyxLQUFLLENBQUMsMkNBQTJDLEVBQUU7b0JBQy9ELFFBQVE7b0JBQ1IsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNO29CQUNuQixVQUFVLEVBQUUsSUFBSSxDQUFDLFVBQVU7b0JBQzNCLGNBQWM7aUJBQ2YsQ0FBQyxDQUFDO2dCQUNILE9BQU8sRUFBRSxjQUFjLEVBQUUsQ0FBQztZQUM1QixDQUFDO1lBRUQsSUFBSSxNQUFlLENBQUM7WUFFcEIsb0RBQW9EO1lBQ3BELG1FQUFtRTtZQUNuRSx1RUFBdUU7WUFDdkUsaUdBQWlHO1lBQ2pHLHlGQUF5RjtZQUN6RixvREFBb0Q7WUFDcEQsd0dBQXdHO1lBQ3hHLDZGQUE2RjtZQUM3Riw2RUFBNkU7WUFDN0UsSUFBSSxJQUFJLENBQUMsT0FBTyxHQUFHLFVBQVUsR0FBRyxDQUFDLEVBQUUsQ0FBQztnQkFDbEMsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLE9BQU8sR0FBRyxDQUFDLENBQUM7Z0JBQ3BDLE1BQU0sWUFBWSxHQUFHLFNBQVMsUUFBUSwyQkFBMkIsVUFBVSxJQUFJLFNBQVMsQ0FBQyxPQUFPLEVBQUUsU0FBUyxFQUFFLFVBQVUsQ0FBQyxHQUFHLENBQUM7Z0JBQzVILE9BQU8sQ0FBQyxLQUFLLENBQUMsZ0JBQWdCLGFBQWEsT0FBTyxZQUFZLEVBQUUsQ0FBQyxDQUFDO2dCQUNsRSx1REFBdUQ7Z0JBQ3ZELE1BQU0sS0FBSyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsYUFBYSxFQUFFO29CQUN2QyxTQUFTLEVBQUUsYUFBYTtvQkFDeEIsV0FBVyxFQUFFLG9CQUFvQjtvQkFDakMsYUFBYSxFQUFFLE1BQU07b0JBQ3JCLFNBQVMsRUFBRTt3QkFDVCxLQUFLLEVBQUUsWUFBWTt3QkFDbkIsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLLEVBQUUsS0FBSztxQkFDekI7aUJBQ0YsQ0FBQyxDQUFDO2dCQUVILElBQUksRUFBRSxhQUFhLENBQUM7b0JBQ2xCLEdBQUcsU0FBUyxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUM7b0JBQ2pDLEdBQUcsU0FBUyxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQztpQkFDdEMsQ0FBQyxDQUFDO2dCQUVILG1EQUFtRDtnQkFDbkQsTUFBTSxZQUFZLENBQUMsS0FBSyxFQUFFLGtCQUFrQixZQUFZLEVBQUUsRUFBRTtvQkFDMUQsS0FBSyxFQUFFLGFBQWE7b0JBQ3BCLFlBQVksRUFBRSxNQUFNLHFCQUFxQixFQUFFO29CQUMzQyxXQUFXLEVBQUUsSUFBSSxJQUFJLEVBQUU7aUJBQ3hCLENBQUMsQ0FBQztnQkFDSCxPQUFPO1lBQ1QsQ0FBQztZQUVELElBQUksQ0FBQztnQkFDSCxJQUFJLENBQUMsQ0FBQyxTQUFTLEVBQUUsU0FBUyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO29CQUNsRCxvREFBb0Q7b0JBQ3BELHFEQUFxRDtvQkFDckQsc0VBQXNFO29CQUN0RSxtREFBbUQ7b0JBQ25ELE9BQU8sQ0FBQyxLQUFLLENBQ1gsZ0JBQWdCLGFBQWEsOEVBQThFLElBQUksQ0FBQyxNQUFNLCtCQUErQixDQUN0SixDQUFDO29CQUNGLElBQUksRUFBRSxhQUFhLENBQUM7d0JBQ2xCLEdBQUcsU0FBUyxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUM7d0JBQzlCLEdBQUcsU0FBUyxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDO3FCQUN6QyxDQUFDLENBQUM7b0JBQ0gsZ0ZBQWdGO29CQUNoRixxRkFBcUY7b0JBQ3JGLDRFQUE0RTtvQkFDNUUsZ0ZBQWdGO29CQUNoRixxREFBcUQ7b0JBQ3JELHlGQUF5RjtvQkFDekYsb0ZBQW9GO29CQUNwRiw4RkFBOEY7b0JBQzlGLHNEQUFzRDtvQkFDdEQsa0VBQWtFO29CQUNsRSxNQUFNLGNBQWMsR0FBRzt3QkFDckIsV0FBVzt3QkFDWCxRQUFRO3dCQUNSLFdBQVc7cUJBQ1osQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO29CQUN4QixJQUFJLGNBQWMsRUFBRSxDQUFDO3dCQUNuQixNQUFNLFlBQVksQ0FBQyxLQUFLLEVBQUUsa0JBQWtCLFlBQVksRUFBRSxFQUFFOzRCQUMxRCxLQUFLLEVBQUUsYUFBYTs0QkFDcEIsWUFBWSxFQUFFLE1BQU0scUJBQXFCLEVBQUU7NEJBQzNDLFdBQVcsRUFBRSxJQUFJLElBQUksRUFBRTt5QkFDeEIsQ0FBQyxDQUFDO29CQUNMLENBQUM7b0JBQ0QsT0FBTztnQkFDVCxDQUFDO2dCQUVELHdEQUF3RDtnQkFDeEQsMEVBQTBFO2dCQUMxRSxNQUFNLFdBQVcsR0FBRyxNQUFNLEtBQUssQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLGFBQWEsRUFBRTtvQkFDM0QsU0FBUyxFQUFFLGNBQWM7b0JBQ3pCLFdBQVcsRUFBRSxvQkFBb0I7b0JBQ2pDLGFBQWEsRUFBRSxNQUFNO2lCQUN0QixDQUFDLENBQUM7Z0JBRUgseUVBQXlFO2dCQUN6RSxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksRUFBRSxDQUFDO29CQUN0QixNQUFNLElBQUksb0JBQW9CLENBQzVCLDJCQUEyQixNQUFNLDhCQUE4QixDQUNoRSxDQUFDO2dCQUNKLENBQUM7Z0JBQ0QsSUFBSSxHQUFHLFdBQVcsQ0FBQyxJQUFJLENBQUM7Z0JBRXhCLG1FQUFtRTtnQkFDbkUsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQztnQkFFN0IsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztvQkFDcEIsTUFBTSxJQUFJLG9CQUFvQixDQUM1QixTQUFTLE1BQU0sZ0NBQWdDLENBQ2hELENBQUM7Z0JBQ0osQ0FBQztnQkFDRCxtRUFBbUU7Z0JBQ25FLE1BQU0sR0FBRyxHQUFvQixFQUFFLENBQUM7Z0JBQ2hDLE1BQU0sYUFBYSxHQUFHLG9CQUFvQixDQUN4QyxJQUFJLENBQUMsS0FBSyxFQUNWLEdBQUcsRUFDSCxhQUFhLENBQ2QsQ0FBQztnQkFFRixNQUFNLElBQUksR0FBRyxhQUFhLENBQUMsSUFBSSxDQUFDO2dCQUNoQyxNQUFNLE9BQU8sR0FBRyxhQUFhLENBQUMsT0FBTyxJQUFJLElBQUksQ0FBQztnQkFFOUMsSUFBSSxFQUFFLGFBQWEsQ0FBQztvQkFDbEIsR0FBRyxTQUFTLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQztpQkFDN0MsQ0FBQyxDQUFDO2dCQUVILE1BQU0sR0FBRyxNQUFNLGNBQWMsQ0FBQyxHQUFHLENBQy9CO29CQUNFLFlBQVksRUFBRTt3QkFDWixNQUFNO3dCQUNOLGFBQWEsRUFBRSxJQUFJLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUM7d0JBQ3hDLE9BQU87cUJBQ1I7b0JBQ0QsZ0JBQWdCLEVBQUU7d0JBQ2hCLGFBQWE7d0JBQ2IsaUJBQWlCLEVBQUUsSUFBSSxJQUFJLENBQUMsQ0FBQyxpQkFBaUIsQ0FBQzt3QkFDL0MsNEVBQTRFO3dCQUM1RSxpREFBaUQ7d0JBQ2pELEdBQUcsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVU7NEJBQ3pCLENBQUMsQ0FBQyxXQUFXLE9BQU8sQ0FBQyxHQUFHLENBQUMsVUFBVSxFQUFFOzRCQUNyQyxDQUFDLENBQUMsb0JBQW9CLElBQUksSUFBSSxJQUFJLEVBQUU7cUJBQ3ZDO29CQUNELEdBQUc7b0JBQ0gsV0FBVyxFQUFFLGFBQWEsQ0FBQyxXQUFXO2lCQUN2QyxFQUNELEdBQUcsRUFBRSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUNsQyxDQUFDO2dCQUVGLDhEQUE4RDtnQkFDOUQsMkZBQTJGO2dCQUMzRiwwRkFBMEY7Z0JBQzFGLE1BQU0sR0FBRyx3QkFBd0IsQ0FBQyxNQUFNLEVBQUUsR0FBRyxFQUFFLGFBQWEsQ0FBQyxDQUFDO2dCQUU5RCxTQUFTLENBQ1AsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRTtvQkFDN0Isb0ZBQW9GO29CQUNwRixNQUFNLFlBQVksR0FDaEIsR0FBRyxFQUFFLElBQUksS0FBSyxZQUFZLElBQUksR0FBRyxFQUFFLElBQUksS0FBSyxpQkFBaUIsQ0FBQztvQkFDaEUsSUFBSSxDQUFDLFlBQVk7d0JBQUUsTUFBTSxHQUFHLENBQUM7Z0JBQy9CLENBQUMsQ0FBQyxDQUNILENBQUM7Z0JBRUYsMkRBQTJEO2dCQUMzRCx3REFBd0Q7Z0JBQ3hELG9GQUFvRjtnQkFDcEYsTUFBTSxLQUFLLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxhQUFhLEVBQUU7b0JBQ3ZDLFNBQVMsRUFBRSxnQkFBZ0I7b0JBQzNCLFdBQVcsRUFBRSxvQkFBb0I7b0JBQ2pDLGFBQWEsRUFBRSxNQUFNO29CQUNyQixTQUFTLEVBQUU7d0JBQ1QsTUFBTSxFQUFFLE1BQW9CO3FCQUM3QjtpQkFDRixDQUFDLENBQUM7Z0JBRUgsSUFBSSxFQUFFLGFBQWEsQ0FBQztvQkFDbEIsR0FBRyxTQUFTLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQztvQkFDcEMsR0FBRyxTQUFTLENBQUMsY0FBYyxDQUFDLE9BQU8sTUFBTSxDQUFDO2lCQUMzQyxDQUFDLENBQUM7WUFDTCxDQUFDO1lBQUMsT0FBTyxHQUFZLEVBQUUsQ0FBQztnQkFDdEIsSUFBSSxFQUFFLGFBQWEsQ0FBQztvQkFDbEIsR0FBRyxTQUFTLENBQUMsYUFBYSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQztvQkFDN0MsR0FBRyxTQUFTLENBQUMsZ0JBQWdCLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO2lCQUMzQyxDQUFDLENBQUM7Z0JBRUgsSUFBSSxnQkFBZ0IsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztvQkFDN0IsSUFBSSxHQUFHLENBQUMsTUFBTSxLQUFLLEdBQUcsRUFBRSxDQUFDO3dCQUN2QiwyQ0FBMkM7d0JBQzNDLE9BQU8sQ0FBQyxJQUFJLENBQ1YsaUJBQWlCLGFBQWEsMkNBQTJDLE1BQU0sTUFBTSxHQUFHLENBQUMsT0FBTyxFQUFFLENBQ25HLENBQUM7d0JBQ0YsT0FBTztvQkFDVCxDQUFDO2dCQUNILENBQUM7Z0JBRUQsSUFBSSxVQUFVLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7b0JBQ3ZCLE1BQU0sVUFBVSxHQUFHLGFBQWEsQ0FBQyxHQUFHLENBQUMsQ0FBQztvQkFDdEMsTUFBTSxVQUFVLEdBQUcsVUFBVSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO29CQUN0RCxPQUFPLENBQUMsS0FBSyxDQUNYLGdCQUFnQixhQUFhLHdEQUF3RCxRQUFRLFdBQVcsVUFBVSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsMENBQTBDLENBQzlLLENBQUM7b0JBQ0YsdURBQXVEO29CQUN2RCxNQUFNLEtBQUssQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLGFBQWEsRUFBRTt3QkFDdkMsU0FBUyxFQUFFLGFBQWE7d0JBQ3hCLFdBQVcsRUFBRSxvQkFBb0I7d0JBQ2pDLGFBQWEsRUFBRSxNQUFNO3dCQUNyQixTQUFTLEVBQUU7NEJBQ1QsS0FBSyxFQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUM7NEJBQ2xCLEtBQUssRUFBRSxVQUFVO3lCQUNsQjtxQkFDRixDQUFDLENBQUM7b0JBRUgsSUFBSSxFQUFFLGFBQWEsQ0FBQzt3QkFDbEIsR0FBRyxTQUFTLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQzt3QkFDakMsR0FBRyxTQUFTLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQztxQkFDbEMsQ0FBQyxDQUFDO2dCQUNMLENBQUM7cUJBQU0sQ0FBQztvQkFDTixNQUFNLFVBQVUsR0FBRyxNQUFNLENBQUMsVUFBVSxJQUFJLHdCQUF3QixDQUFDO29CQUNqRSw0REFBNEQ7b0JBQzVELE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUM7b0JBRXBDLElBQUksRUFBRSxhQUFhLENBQUM7d0JBQ2xCLEdBQUcsU0FBUyxDQUFDLFdBQVcsQ0FBQyxjQUFjLENBQUM7d0JBQ3hDLEdBQUcsU0FBUyxDQUFDLGNBQWMsQ0FBQyxVQUFVLENBQUM7cUJBQ3hDLENBQUMsQ0FBQztvQkFFSCx3R0FBd0c7b0JBQ3hHLElBQUksY0FBYyxJQUFJLFVBQVUsR0FBRyxDQUFDLEVBQUUsQ0FBQzt3QkFDckMsc0JBQXNCO3dCQUN0QixNQUFNLFVBQVUsR0FBRyxhQUFhLENBQUMsR0FBRyxDQUFDLENBQUM7d0JBQ3RDLE1BQU0sVUFBVSxHQUFHLFVBQVUsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQzt3QkFDdEQsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLE9BQU8sR0FBRyxDQUFDLENBQUM7d0JBQ3BDLE9BQU8sQ0FBQyxLQUFLLENBQ1gsZ0JBQWdCLGFBQWEsbURBQW1ELFFBQVEsY0FBYyxJQUFJLENBQUMsT0FBTyxLQUFLLFVBQVUsSUFBSSxTQUFTLENBQUMsT0FBTyxFQUFFLFNBQVMsRUFBRSxVQUFVLENBQUMsV0FBVyxVQUFVLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxnRUFBZ0UsQ0FDclIsQ0FBQzt3QkFDRixNQUFNLFlBQVksR0FBRyxTQUFTLFFBQVEsa0JBQWtCLFVBQVUsSUFBSSxTQUFTLENBQUMsT0FBTyxFQUFFLFNBQVMsRUFBRSxVQUFVLENBQUMsS0FBSyxNQUFNLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQzt3QkFDbEksdURBQXVEO3dCQUN2RCxNQUFNLEtBQUssQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLGFBQWEsRUFBRTs0QkFDdkMsU0FBUyxFQUFFLGFBQWE7NEJBQ3hCLFdBQVcsRUFBRSxvQkFBb0I7NEJBQ2pDLGFBQWEsRUFBRSxNQUFNOzRCQUNyQixTQUFTLEVBQUU7Z0NBQ1QsS0FBSyxFQUFFLFlBQVk7Z0NBQ25CLEtBQUssRUFBRSxVQUFVOzZCQUNsQjt5QkFDRixDQUFDLENBQUM7d0JBRUgsSUFBSSxFQUFFLGFBQWEsQ0FBQzs0QkFDbEIsR0FBRyxTQUFTLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQzs0QkFDakMsR0FBRyxTQUFTLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDO3lCQUN0QyxDQUFDLENBQUM7b0JBQ0wsQ0FBQzt5QkFBTSxDQUFDO3dCQUNOLG9EQUFvRDt3QkFDcEQsSUFBSSxjQUFjLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7NEJBQzNCLE9BQU8sQ0FBQyxJQUFJLENBQ1YsZ0JBQWdCLGFBQWEsNERBQTRELFFBQVEsY0FBYyxjQUFjLFdBQVcsTUFBTSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsZ0RBQWdELENBQzVNLENBQUM7d0JBQ0osQ0FBQzs2QkFBTSxDQUFDOzRCQUNOLE1BQU0sVUFBVSxHQUFHLGFBQWEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQzs0QkFDOUQsT0FBTyxDQUFDLEtBQUssQ0FDWCxnQkFBZ0IsYUFBYSxtREFBbUQsUUFBUSxjQUFjLGNBQWMsV0FBVyxVQUFVLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxnREFBZ0QsQ0FDM00sQ0FBQzt3QkFDSixDQUFDO3dCQUNELHVFQUF1RTt3QkFDdkUsNkRBQTZEO3dCQUM3RCxNQUFNLFVBQVUsR0FBRyxhQUFhLENBQUMsR0FBRyxDQUFDLENBQUM7d0JBQ3RDLE1BQU0sS0FBSyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsYUFBYSxFQUFFOzRCQUN2QyxTQUFTLEVBQUUsZUFBZTs0QkFDMUIsV0FBVyxFQUFFLG9CQUFvQjs0QkFDakMsYUFBYSxFQUFFLE1BQU07NEJBQ3JCLFNBQVMsRUFBRTtnQ0FDVCxLQUFLLEVBQUUsTUFBTSxDQUFDLEdBQUcsQ0FBQztnQ0FDbEIsS0FBSyxFQUFFLFVBQVU7Z0NBQ2pCLEdBQUcsQ0FBQyxjQUFjLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxJQUFJO29DQUM1QixVQUFVLEVBQUUsR0FBRyxDQUFDLFVBQVU7aUNBQzNCLENBQUM7NkJBQ0g7eUJBQ0YsQ0FBQyxDQUFDO3dCQUVILE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQzdCLENBQUMsRUFDRCxjQUFjLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQzs0QkFDcEIsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsT0FBTyxFQUFFLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDOzRCQUM1RCxDQUFDLENBQUMsQ0FBQyxDQUNOLENBQUM7d0JBRUYsSUFBSSxFQUFFLGFBQWEsQ0FBQzs0QkFDbEIsR0FBRyxTQUFTLENBQUMsdUJBQXVCLENBQUMsY0FBYyxDQUFDOzRCQUNwRCxHQUFHLFNBQVMsQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUM7eUJBQ3RDLENBQUMsQ0FBQzt3QkFFSCxzRUFBc0U7d0JBQ3RFLDJCQUEyQjt3QkFDM0IsT0FBTyxFQUFFLGNBQWMsRUFBRSxDQUFDO29CQUM1QixDQUFDO2dCQUNILENBQUM7WUFDSCxDQUFDO1lBRUQsTUFBTSxZQUFZLENBQUMsS0FBSyxFQUFFLGtCQUFrQixZQUFZLEVBQUUsRUFBRTtnQkFDMUQsS0FBSyxFQUFFLGFBQWE7Z0JBQ3BCLFlBQVksRUFBRSxNQUFNLHFCQUFxQixFQUFFO2dCQUMzQyxXQUFXLEVBQUUsSUFBSSxJQUFJLEVBQUU7YUFDeEIsQ0FBQyxDQUFDO1FBQ0wsQ0FBQyxDQUNGLENBQUM7SUFDSixDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FDRixDQUFDO0FBRUY7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxNQUFNLGNBQWM7QUFDekIsZUFBZSxDQUFDLGVBQWUsQ0FBQyxXQUFXLENBQUMsQ0FBQyJ9
@@ -0,0 +1,25 @@
1
+ import type { Span } from '@opentelemetry/api';
2
+ import { type World } from '@workflow/world';
3
+ import type { WorkflowSuspension } from '../global.js';
4
+ export interface SuspensionHandlerParams {
5
+ suspension: WorkflowSuspension;
6
+ world: World;
7
+ runId: string;
8
+ workflowName: string;
9
+ workflowStartedAt: number;
10
+ span?: Span;
11
+ }
12
+ export interface SuspensionHandlerResult {
13
+ timeoutSeconds?: number;
14
+ }
15
+ /**
16
+ * Handles a workflow suspension by processing all pending operations (hooks, steps, waits).
17
+ * Uses an event-sourced architecture where entities (steps, hooks) are created atomically
18
+ * with their corresponding events via events.create().
19
+ *
20
+ * Processing order:
21
+ * 1. Hooks are processed first to prevent race conditions with webhook receivers
22
+ * 2. Steps and waits are processed in parallel after hooks complete
23
+ */
24
+ export declare function handleSuspension({ suspension, world, runId, workflowName, workflowStartedAt, span, }: SuspensionHandlerParams): Promise<SuspensionHandlerResult>;
25
+ //# sourceMappingURL=suspension-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"suspension-handler.d.ts","sourceRoot":"","sources":["../../src/runtime/suspension-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAG/C,OAAO,EAIL,KAAK,KAAK,EACX,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAIV,kBAAkB,EACnB,MAAM,cAAc,CAAC;AAMtB,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,kBAAkB,CAAC;IAC/B,KAAK,EAAE,KAAK,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,IAAI,CAAC,EAAE,IAAI,CAAC;CACb;AAED,MAAM,WAAW,uBAAuB;IACtC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CAAC,EACrC,UAAU,EACV,KAAK,EACL,KAAK,EACL,YAAY,EACZ,iBAAiB,EACjB,IAAI,GACL,EAAE,uBAAuB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CA2M5D"}
@@ -0,0 +1,182 @@
1
+ import { waitUntil } from '@vercel/functions';
2
+ import { WorkflowAPIError } from '@workflow/errors';
3
+ import { SPEC_VERSION_CURRENT, } from '@workflow/world';
4
+ import { dehydrateStepArguments } from '../serialization.js';
5
+ import * as Attribute from '../telemetry/semantic-conventions.js';
6
+ import { serializeTraceCarrier } from '../telemetry.js';
7
+ import { queueMessage } from './helpers.js';
8
+ /**
9
+ * Handles a workflow suspension by processing all pending operations (hooks, steps, waits).
10
+ * Uses an event-sourced architecture where entities (steps, hooks) are created atomically
11
+ * with their corresponding events via events.create().
12
+ *
13
+ * Processing order:
14
+ * 1. Hooks are processed first to prevent race conditions with webhook receivers
15
+ * 2. Steps and waits are processed in parallel after hooks complete
16
+ */
17
+ export async function handleSuspension({ suspension, world, runId, workflowName, workflowStartedAt, span, }) {
18
+ // Separate queue items by type
19
+ const stepItems = suspension.steps.filter((item) => item.type === 'step');
20
+ const hookItems = suspension.steps.filter((item) => item.type === 'hook');
21
+ const waitItems = suspension.steps.filter((item) => item.type === 'wait');
22
+ // Build hook_created events (World will atomically create hook entities)
23
+ const hookEvents = hookItems.map((queueItem) => {
24
+ const hookMetadata = typeof queueItem.metadata === 'undefined'
25
+ ? undefined
26
+ : dehydrateStepArguments(queueItem.metadata, suspension.globalThis);
27
+ return {
28
+ eventType: 'hook_created',
29
+ specVersion: SPEC_VERSION_CURRENT,
30
+ correlationId: queueItem.correlationId,
31
+ eventData: {
32
+ token: queueItem.token,
33
+ metadata: hookMetadata,
34
+ },
35
+ };
36
+ });
37
+ // Process hooks first to prevent race conditions with webhook receivers
38
+ // All hook creations run in parallel
39
+ // Track any hook conflicts that occur - these will be handled by re-enqueueing the workflow
40
+ let hasHookConflict = false;
41
+ if (hookEvents.length > 0) {
42
+ await Promise.all(hookEvents.map(async (hookEvent) => {
43
+ try {
44
+ const result = await world.events.create(runId, hookEvent);
45
+ // Check if the world returned a hook_conflict event instead of hook_created
46
+ // The hook_conflict event is stored in the event log and will be replayed
47
+ // on the next workflow invocation, causing the hook's promise to reject
48
+ // Note: hook events always create an event (legacy runs throw, not return undefined)
49
+ if (result.event.eventType === 'hook_conflict') {
50
+ hasHookConflict = true;
51
+ }
52
+ }
53
+ catch (err) {
54
+ if (WorkflowAPIError.is(err)) {
55
+ if (err.status === 410) {
56
+ console.warn(`Workflow run "${runId}" has already completed, skipping hook: ${err.message}`);
57
+ }
58
+ else {
59
+ throw err;
60
+ }
61
+ }
62
+ else {
63
+ throw err;
64
+ }
65
+ }
66
+ }));
67
+ }
68
+ // Build a map of stepId -> step event for steps that need creation
69
+ const stepsNeedingCreation = new Set(stepItems
70
+ .filter((queueItem) => !queueItem.hasCreatedEvent)
71
+ .map((queueItem) => queueItem.correlationId));
72
+ // Process steps and waits in parallel
73
+ // Each step: create event (if needed) -> queue message
74
+ // Each wait: create event (if needed)
75
+ const ops = [];
76
+ // Steps: create event then queue message, all in parallel
77
+ for (const queueItem of stepItems) {
78
+ ops.push((async () => {
79
+ // Create step event if not already created
80
+ if (stepsNeedingCreation.has(queueItem.correlationId)) {
81
+ const dehydratedInput = dehydrateStepArguments({
82
+ args: queueItem.args,
83
+ closureVars: queueItem.closureVars,
84
+ thisVal: queueItem.thisVal,
85
+ }, suspension.globalThis);
86
+ const stepEvent = {
87
+ eventType: 'step_created',
88
+ specVersion: SPEC_VERSION_CURRENT,
89
+ correlationId: queueItem.correlationId,
90
+ eventData: {
91
+ stepName: queueItem.stepName,
92
+ input: dehydratedInput,
93
+ },
94
+ };
95
+ try {
96
+ await world.events.create(runId, stepEvent);
97
+ }
98
+ catch (err) {
99
+ if (WorkflowAPIError.is(err) && err.status === 409) {
100
+ console.warn(`Step already exists, continuing: ${err.message}`);
101
+ }
102
+ else {
103
+ throw err;
104
+ }
105
+ }
106
+ }
107
+ // Queue step execution message
108
+ await queueMessage(world, `__wkf_step_${queueItem.stepName}`, {
109
+ workflowName,
110
+ workflowRunId: runId,
111
+ workflowStartedAt,
112
+ stepId: queueItem.correlationId,
113
+ traceCarrier: await serializeTraceCarrier(),
114
+ requestedAt: new Date(),
115
+ }, {
116
+ idempotencyKey: queueItem.correlationId,
117
+ });
118
+ })());
119
+ }
120
+ // Waits: create events in parallel (no queueing needed for waits)
121
+ for (const queueItem of waitItems) {
122
+ if (!queueItem.hasCreatedEvent) {
123
+ ops.push((async () => {
124
+ const waitEvent = {
125
+ eventType: 'wait_created',
126
+ specVersion: SPEC_VERSION_CURRENT,
127
+ correlationId: queueItem.correlationId,
128
+ eventData: {
129
+ resumeAt: queueItem.resumeAt,
130
+ },
131
+ };
132
+ try {
133
+ await world.events.create(runId, waitEvent);
134
+ }
135
+ catch (err) {
136
+ if (WorkflowAPIError.is(err) && err.status === 409) {
137
+ console.warn(`Wait already exists, continuing: ${err.message}`);
138
+ }
139
+ else {
140
+ throw err;
141
+ }
142
+ }
143
+ })());
144
+ }
145
+ }
146
+ // Wait for all step and wait operations to complete
147
+ waitUntil(Promise.all(ops).catch((opErr) => {
148
+ const isAbortError = opErr?.name === 'AbortError' || opErr?.name === 'ResponseAborted';
149
+ if (!isAbortError)
150
+ throw opErr;
151
+ }));
152
+ await Promise.all(ops);
153
+ // Calculate minimum timeout from waits
154
+ const now = Date.now();
155
+ const minTimeoutSeconds = waitItems.reduce((min, queueItem) => {
156
+ const resumeAtMs = queueItem.resumeAt.getTime();
157
+ const delayMs = Math.max(1000, resumeAtMs - now);
158
+ const timeoutSeconds = Math.ceil(delayMs / 1000);
159
+ if (min === null)
160
+ return timeoutSeconds;
161
+ return Math.min(min, timeoutSeconds);
162
+ }, null);
163
+ span?.setAttributes({
164
+ ...Attribute.WorkflowRunStatus('workflow_suspended'),
165
+ ...Attribute.WorkflowStepsCreated(stepItems.length),
166
+ ...Attribute.WorkflowHooksCreated(hookItems.length),
167
+ ...Attribute.WorkflowWaitsCreated(waitItems.length),
168
+ });
169
+ // If any hook conflicts occurred, re-enqueue the workflow immediately
170
+ // On the next iteration, the hook consumer will see the hook_conflict event
171
+ // and reject the promise with a WorkflowRuntimeError
172
+ // We do this after processing all other operations (steps, waits) to ensure
173
+ // they are recorded in the event log before the re-execution
174
+ if (hasHookConflict) {
175
+ return { timeoutSeconds: 1 };
176
+ }
177
+ if (minTimeoutSeconds !== null) {
178
+ return { timeoutSeconds: minTimeoutSeconds };
179
+ }
180
+ return {};
181
+ }
182
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3VzcGVuc2lvbi1oYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3J1bnRpbWUvc3VzcGVuc2lvbi1oYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUM5QyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNwRCxPQUFPLEVBR0wsb0JBQW9CLEdBRXJCLE1BQU0saUJBQWlCLENBQUM7QUFPekIsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDN0QsT0FBTyxLQUFLLFNBQVMsTUFBTSxzQ0FBc0MsQ0FBQztBQUNsRSxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUN4RCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBZTVDOzs7Ozs7OztHQVFHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxnQkFBZ0IsQ0FBQyxFQUNyQyxVQUFVLEVBQ1YsS0FBSyxFQUNMLEtBQUssRUFDTCxZQUFZLEVBQ1osaUJBQWlCLEVBQ2pCLElBQUksR0FDb0I7SUFDeEIsK0JBQStCO0lBQy9CLE1BQU0sU0FBUyxHQUFHLFVBQVUsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUN2QyxDQUFDLElBQUksRUFBbUMsRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUNoRSxDQUFDO0lBQ0YsTUFBTSxTQUFTLEdBQUcsVUFBVSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQ3ZDLENBQUMsSUFBSSxFQUFtQyxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksS0FBSyxNQUFNLENBQ2hFLENBQUM7SUFDRixNQUFNLFNBQVMsR0FBRyxVQUFVLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FDdkMsQ0FBQyxJQUFJLEVBQW1DLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxLQUFL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
@@ -1 +1 @@
1
- {"version":3,"file":"world.d.ts","sourceRoot":"","sources":["../../src/runtime/world.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAiB7C;;;;GAIG;AACH,eAAO,MAAM,WAAW,QAAO,KAkC9B,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,QAAO,IAAI,CAAC,KAAK,EAAE,oBAAoB,CASnE,CAAC;AAEF,eAAO,MAAM,QAAQ,QAAO,KAM3B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,QAAQ,GAAI,OAAO,KAAK,GAAG,SAAS,KAAG,IAGnD,CAAC"}
1
+ {"version":3,"file":"world.d.ts","sourceRoot":"","sources":["../../src/runtime/world.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAsB7C;;;;GAIG;AACH,eAAO,MAAM,WAAW,QAAO,KAgC9B,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,QAAO,IAAI,CAAC,KAAK,EAAE,oBAAoB,CASnE,CAAC;AAEF,eAAO,MAAM,QAAQ,QAAO,KAM3B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,QAAQ,GAAI,OAAO,KAAK,GAAG,SAAS,KAAG,IAGnD,CAAC"}