@upstash/workflow 0.2.15 → 0.2.17

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.
@@ -42,7 +42,7 @@ var WORKFLOW_PROTOCOL_VERSION_HEADER = "Upstash-Workflow-Sdk-Version";
42
42
  var DEFAULT_CONTENT_TYPE = "application/json";
43
43
  var NO_CONCURRENCY = 1;
44
44
  var DEFAULT_RETRIES = 3;
45
- var VERSION = "v0.2.15";
45
+ var VERSION = "v0.2.17";
46
46
  var SDK_TELEMETRY = `@upstash/workflow@${VERSION}`;
47
47
  var TELEMETRY_HEADER_SDK = "Upstash-Telemetry-Sdk";
48
48
  var TELEMETRY_HEADER_FRAMEWORK = "Upstash-Telemetry-Framework";
@@ -144,6 +144,7 @@ var fetchWithContextCall = async (context, agentCallParams, ...params) => {
144
144
  body,
145
145
  timeout: agentCallParams?.timeout,
146
146
  retries: agentCallParams?.retries,
147
+ retryDelay: agentCallParams?.retryDelay,
147
148
  flowControl: agentCallParams?.flowControl
148
149
  });
149
150
  const responseHeaders = new Headers(
@@ -287,7 +288,10 @@ var serveManyBase = ({
287
288
  return new Response(
288
289
  `Unexpected request in serveMany. workflowId not set. Please update the URL of your request.`,
289
290
  {
290
- status: 404
291
+ status: 404,
292
+ headers: {
293
+ [WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
294
+ }
291
295
  }
292
296
  );
293
297
  }
@@ -296,7 +300,10 @@ var serveManyBase = ({
296
300
  return new Response(
297
301
  `No workflows in serveMany found for '${pickedWorkflowId}'. Please update the URL of your request.`,
298
302
  {
299
- status: 404
303
+ status: 404,
304
+ headers: {
305
+ [WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
306
+ }
300
307
  }
301
308
  );
302
309
  }
@@ -831,6 +838,7 @@ var triggerFirstInvocation = async (params) => {
831
838
  workflowUrl: workflowContext.url,
832
839
  failureUrl: workflowContext.failureUrl,
833
840
  retries: workflowContext.retries,
841
+ retryDelay: workflowContext.retryDelay,
834
842
  telemetry,
835
843
  flowControl: workflowContext.flowControl,
836
844
  useJSONContent: useJSONContent ?? false
@@ -960,6 +968,7 @@ var handleThirdPartyCallResult = async ({
960
968
  workflowUrl,
961
969
  failureUrl,
962
970
  retries,
971
+ retryDelay,
963
972
  telemetry,
964
973
  flowControl,
965
974
  debug
@@ -1030,6 +1039,7 @@ ${atob(callbackMessage.body ?? "")}`
1030
1039
  workflowUrl,
1031
1040
  failureUrl,
1032
1041
  retries,
1042
+ retryDelay,
1033
1043
  telemetry,
1034
1044
  flowControl
1035
1045
  },
@@ -1180,7 +1190,8 @@ var BaseLazyStep = class _BaseLazyStep {
1180
1190
  workflowRunId: context.workflowRunId,
1181
1191
  workflowUrl: context.url,
1182
1192
  failureUrl: context.failureUrl,
1183
- retries: context.retries,
1193
+ retries: DEFAULT_RETRIES === context.retries ? void 0 : context.retries,
1194
+ retryDelay: context.retryDelay,
1184
1195
  useJSONContent: false,
1185
1196
  telemetry,
1186
1197
  flowControl: context.flowControl
@@ -1199,6 +1210,9 @@ var BaseLazyStep = class _BaseLazyStep {
1199
1210
  body,
1200
1211
  headers,
1201
1212
  method: "POST",
1213
+ retries: DEFAULT_RETRIES === context.retries ? void 0 : context.retries,
1214
+ retryDelay: context.retryDelay,
1215
+ flowControl: context.flowControl,
1202
1216
  url: context.url
1203
1217
  }
1204
1218
  ]);
@@ -1269,6 +1283,9 @@ var LazySleepStep = class extends BaseLazyStep {
1269
1283
  headers,
1270
1284
  method: "POST",
1271
1285
  url: context.url,
1286
+ retries: DEFAULT_RETRIES === context.retries ? void 0 : context.retries,
1287
+ retryDelay: context.retryDelay,
1288
+ flowControl: context.flowControl,
1272
1289
  delay: isParallel ? void 0 : this.sleep
1273
1290
  }
1274
1291
  ]);
@@ -1311,6 +1328,9 @@ var LazySleepUntilStep = class extends BaseLazyStep {
1311
1328
  headers,
1312
1329
  method: "POST",
1313
1330
  url: context.url,
1331
+ retries: DEFAULT_RETRIES === context.retries ? void 0 : context.retries,
1332
+ retryDelay: context.retryDelay,
1333
+ flowControl: context.flowControl,
1314
1334
  notBefore: isParallel ? void 0 : this.sleepUntil
1315
1335
  }
1316
1336
  ]);
@@ -1322,17 +1342,19 @@ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
1322
1342
  body;
1323
1343
  headers;
1324
1344
  retries;
1345
+ retryDelay;
1325
1346
  timeout;
1326
1347
  flowControl;
1327
1348
  stepType = "Call";
1328
1349
  allowUndefinedOut = false;
1329
- constructor(stepName, url, method, body, headers, retries, timeout, flowControl) {
1350
+ constructor(stepName, url, method, body, headers, retries, retryDelay, timeout, flowControl) {
1330
1351
  super(stepName);
1331
1352
  this.url = url;
1332
1353
  this.method = method;
1333
1354
  this.body = body;
1334
1355
  this.headers = headers;
1335
1356
  this.retries = retries;
1357
+ this.retryDelay = retryDelay;
1336
1358
  this.timeout = timeout;
1337
1359
  this.flowControl = flowControl;
1338
1360
  }
@@ -1407,6 +1429,9 @@ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
1407
1429
  getHeaders({ context, telemetry, invokeCount, step }) {
1408
1430
  const { headers, contentType } = super.getHeaders({ context, telemetry, invokeCount, step });
1409
1431
  headers["Upstash-Retries"] = this.retries.toString();
1432
+ if (this.retryDelay) {
1433
+ headers["Upstash-Retry-Delay"] = this.retryDelay;
1434
+ }
1410
1435
  headers[WORKFLOW_FEATURE_HEADER] = "WF_NoDelete,InitialBody";
1411
1436
  if (this.flowControl) {
1412
1437
  const { flowControlKey, flowControlValue } = prepareFlowControl(this.flowControl);
@@ -1428,7 +1453,7 @@ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
1428
1453
  "Upstash-Callback-Workflow-CallType": "fromCallback",
1429
1454
  "Upstash-Callback-Workflow-Init": "false",
1430
1455
  "Upstash-Callback-Workflow-Url": context.url,
1431
- "Upstash-Callback-Feature-Set": "LazyFetch,InitialBody",
1456
+ "Upstash-Callback-Feature-Set": "LazyFetch,InitialBody,WF_DetectTrigger",
1432
1457
  "Upstash-Callback-Forward-Upstash-Workflow-Callback": "true",
1433
1458
  "Upstash-Callback-Forward-Upstash-Workflow-StepId": step.stepId.toString(),
1434
1459
  "Upstash-Callback-Forward-Upstash-Workflow-StepName": this.stepName,
@@ -1446,7 +1471,10 @@ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
1446
1471
  headers,
1447
1472
  body: JSON.stringify(this.body),
1448
1473
  method: this.method,
1449
- url: this.url
1474
+ url: this.url,
1475
+ retries: DEFAULT_RETRIES === this.retries ? void 0 : this.retries,
1476
+ retryDelay: this.retryDelay,
1477
+ flowControl: this.flowControl
1450
1478
  }
1451
1479
  ]);
1452
1480
  }
@@ -1575,6 +1603,7 @@ var LazyInvokeStep = class extends BaseLazyStep {
1575
1603
  headers = {},
1576
1604
  workflowRunId,
1577
1605
  retries,
1606
+ retryDelay,
1578
1607
  flowControl
1579
1608
  }) {
1580
1609
  super(stepName);
@@ -1584,6 +1613,7 @@ var LazyInvokeStep = class extends BaseLazyStep {
1584
1613
  headers,
1585
1614
  workflowRunId: getWorkflowRunId(workflowRunId),
1586
1615
  retries,
1616
+ retryDelay,
1587
1617
  flowControl
1588
1618
  };
1589
1619
  const { workflowId } = workflow;
@@ -1628,6 +1658,7 @@ var LazyInvokeStep = class extends BaseLazyStep {
1628
1658
  workflowUrl: context.url,
1629
1659
  failureUrl: context.failureUrl,
1630
1660
  retries: context.retries,
1661
+ retryDelay: context.retryDelay,
1631
1662
  telemetry,
1632
1663
  flowControl: context.flowControl,
1633
1664
  useJSONContent: false
@@ -1653,11 +1684,13 @@ var LazyInvokeStep = class extends BaseLazyStep {
1653
1684
  headers = {},
1654
1685
  workflowRunId = getWorkflowRunId(),
1655
1686
  retries,
1687
+ retryDelay,
1656
1688
  flowControl
1657
1689
  } = this.params;
1658
1690
  const newUrl = context.url.replace(/[^/]+$/, this.workflowId);
1659
1691
  const {
1660
1692
  retries: workflowRetries,
1693
+ retryDelay: workflowRetryDelay,
1661
1694
  failureFunction,
1662
1695
  failureUrl,
1663
1696
  useJSONContent,
@@ -1669,6 +1702,7 @@ var LazyInvokeStep = class extends BaseLazyStep {
1669
1702
  workflowRunId,
1670
1703
  workflowUrl: newUrl,
1671
1704
  retries: retries ?? workflowRetries,
1705
+ retryDelay: retryDelay ?? workflowRetryDelay,
1672
1706
  telemetry,
1673
1707
  failureUrl: failureFunction ? newUrl : failureUrl,
1674
1708
  flowControl: flowControl ?? workflowFlowControl,
@@ -1721,6 +1755,7 @@ var WorkflowHeaders = class {
1721
1755
  getHeaders() {
1722
1756
  this.addBaseHeaders();
1723
1757
  this.addRetries();
1758
+ this.addRetryDelay();
1724
1759
  this.addFlowControl();
1725
1760
  this.addUserHeaders();
1726
1761
  this.addInvokeCount();
@@ -1734,7 +1769,7 @@ var WorkflowHeaders = class {
1734
1769
  [WORKFLOW_INIT_HEADER]: this.initHeaderValue,
1735
1770
  [WORKFLOW_ID_HEADER]: this.workflowConfig.workflowRunId,
1736
1771
  [WORKFLOW_URL_HEADER]: this.workflowConfig.workflowUrl,
1737
- [WORKFLOW_FEATURE_HEADER]: "LazyFetch,InitialBody",
1772
+ [WORKFLOW_FEATURE_HEADER]: "LazyFetch,InitialBody,WF_DetectTrigger",
1738
1773
  [WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION,
1739
1774
  ...this.workflowConfig.telemetry ? getTelemetryHeaders(this.workflowConfig.telemetry) : {},
1740
1775
  ...this.workflowConfig.telemetry && this.stepInfo?.lazyStep instanceof LazyCallStep && this.stepInfo.lazyStep.headers[AGENT_NAME_HEADER] ? { [TELEMETRY_HEADER_AGENT]: "true" } : {}
@@ -1766,6 +1801,16 @@ var WorkflowHeaders = class {
1766
1801
  this.headers.failureHeaders["Retries"] = retries;
1767
1802
  }
1768
1803
  }
1804
+ addRetryDelay() {
1805
+ if (this.workflowConfig.retryDelay === void 0 || this.workflowConfig.retryDelay === "") {
1806
+ return;
1807
+ }
1808
+ const retryDelay = this.workflowConfig.retryDelay.toString();
1809
+ this.headers.workflowHeaders["Retry-Delay"] = retryDelay;
1810
+ if (this.workflowConfig.failureUrl) {
1811
+ this.headers.failureHeaders["Retry-Delay"] = retryDelay;
1812
+ }
1813
+ }
1769
1814
  addFlowControl() {
1770
1815
  if (!this.workflowConfig.flowControl) {
1771
1816
  return;
@@ -1800,10 +1845,13 @@ var WorkflowHeaders = class {
1800
1845
  this.headers.failureHeaders["Workflow-Init"] = "false";
1801
1846
  this.headers.failureHeaders["Workflow-Url"] = this.workflowConfig.workflowUrl;
1802
1847
  this.headers.failureHeaders["Workflow-Calltype"] = "failureCall";
1803
- this.headers.failureHeaders["Feature-Set"] = "LazyFetch,InitialBody";
1848
+ this.headers.failureHeaders["Feature-Set"] = "LazyFetch,InitialBody,WF_DetectTrigger";
1804
1849
  if (this.workflowConfig.retries !== void 0 && this.workflowConfig.retries !== DEFAULT_RETRIES) {
1805
1850
  this.headers.failureHeaders["Retries"] = this.workflowConfig.retries.toString();
1806
1851
  }
1852
+ if (this.workflowConfig.retryDelay !== void 0 && this.workflowConfig.retryDelay !== "") {
1853
+ this.headers.failureHeaders["Retry-Delay"] = this.workflowConfig.retryDelay.toString();
1854
+ }
1807
1855
  }
1808
1856
  addContentType() {
1809
1857
  if (this.workflowConfig.useJSONContent) {
@@ -1885,6 +1933,7 @@ var submitParallelSteps = async ({
1885
1933
  workflowUrl: context.url,
1886
1934
  failureUrl: context.failureUrl,
1887
1935
  retries: context.retries,
1936
+ retryDelay: context.retryDelay,
1888
1937
  flowControl: context.flowControl,
1889
1938
  telemetry
1890
1939
  },
@@ -2305,7 +2354,7 @@ var BaseWorkflowApi = class {
2305
2354
  */
2306
2355
  async callApi(stepName, settings) {
2307
2356
  const { url, appendHeaders, method } = getProviderInfo(settings.api);
2308
- const { method: userMethod, body, headers = {}, retries = 0, timeout } = settings;
2357
+ const { method: userMethod, body, headers = {}, retries = 0, retryDelay, timeout } = settings;
2309
2358
  return await this.context.call(stepName, {
2310
2359
  url,
2311
2360
  method: userMethod ?? method,
@@ -2315,6 +2364,7 @@ var BaseWorkflowApi = class {
2315
2364
  ...headers
2316
2365
  },
2317
2366
  retries,
2367
+ retryDelay,
2318
2368
  timeout
2319
2369
  });
2320
2370
  }
@@ -2726,6 +2776,37 @@ var WorkflowContext = class {
2726
2776
  * Number of retries
2727
2777
  */
2728
2778
  retries;
2779
+ /**
2780
+ * Delay between retries.
2781
+ *
2782
+ * By default, the `retryDelay` is exponential backoff.
2783
+ * More details can be found in: https://upstash.com/docs/qstash/features/retry.
2784
+ *
2785
+ * The `retryDelay` option allows you to customize the delay (in milliseconds) between retry attempts when message delivery fails.
2786
+ *
2787
+ * You can use mathematical expressions and the following built-in functions to calculate the delay dynamically.
2788
+ * The special variable `retried` represents the current retry attempt count (starting from 0).
2789
+ *
2790
+ * Supported functions:
2791
+ * - `pow`
2792
+ * - `sqrt`
2793
+ * - `abs`
2794
+ * - `exp`
2795
+ * - `floor`
2796
+ * - `ceil`
2797
+ * - `round`
2798
+ * - `min`
2799
+ * - `max`
2800
+ *
2801
+ * Examples of valid `retryDelay` values:
2802
+ * ```ts
2803
+ * 1000 // 1 second
2804
+ * 1000 * (1 + retried) // 1 second multiplied by the current retry attempt
2805
+ * pow(2, retried) // 2 to the power of the current retry attempt
2806
+ * max(10, pow(2, retried)) // The greater of 10 or 2^retried
2807
+ * ```
2808
+ */
2809
+ retryDelay;
2729
2810
  /**
2730
2811
  * Settings for controlling the number of active requests
2731
2812
  * and number of requests per second with the same key.
@@ -2742,6 +2823,7 @@ var WorkflowContext = class {
2742
2823
  initialPayload,
2743
2824
  env,
2744
2825
  retries,
2826
+ retryDelay,
2745
2827
  telemetry,
2746
2828
  invokeCount,
2747
2829
  flowControl
@@ -2755,6 +2837,7 @@ var WorkflowContext = class {
2755
2837
  this.requestPayload = initialPayload;
2756
2838
  this.env = env ?? {};
2757
2839
  this.retries = retries ?? DEFAULT_RETRIES;
2840
+ this.retryDelay = retryDelay;
2758
2841
  this.flowControl = flowControl;
2759
2842
  this.executor = new AutoExecutor(this, this.steps, telemetry, invokeCount, debug);
2760
2843
  }
@@ -2836,6 +2919,7 @@ var WorkflowContext = class {
2836
2919
  settings.body,
2837
2920
  settings.headers || {},
2838
2921
  settings.retries || 0,
2922
+ settings.retryDelay,
2839
2923
  settings.timeout,
2840
2924
  settings.flowControl ?? settings.workflow.options.flowControl
2841
2925
  );
@@ -2846,6 +2930,7 @@ var WorkflowContext = class {
2846
2930
  body,
2847
2931
  headers = {},
2848
2932
  retries = 0,
2933
+ retryDelay,
2849
2934
  timeout,
2850
2935
  flowControl
2851
2936
  } = settings;
@@ -2856,6 +2941,7 @@ var WorkflowContext = class {
2856
2941
  body,
2857
2942
  headers,
2858
2943
  retries,
2944
+ retryDelay,
2859
2945
  timeout,
2860
2946
  flowControl
2861
2947
  );
@@ -2866,7 +2952,7 @@ var WorkflowContext = class {
2866
2952
  * Pauses workflow execution until a specific event occurs or a timeout is reached.
2867
2953
  *
2868
2954
  *```ts
2869
- * const result = await workflow.waitForEvent("payment-confirmed", {
2955
+ * const result = await workflow.waitForEvent("payment-confirmed", "payment.confirmed", {
2870
2956
  * timeout: "5m"
2871
2957
  * });
2872
2958
  *```
@@ -2892,7 +2978,7 @@ var WorkflowContext = class {
2892
2978
  * @param stepName
2893
2979
  * @param eventId - Unique identifier for the event to wait for
2894
2980
  * @param options - Configuration options.
2895
- * @returns `{ timeout: boolean, eventData: unknown }`.
2981
+ * @returns `{ timeout: boolean, eventData: TEventData }`.
2896
2982
  * The `timeout` property specifies if the workflow has timed out. The `eventData`
2897
2983
  * is the data passed when notifying this workflow of an event.
2898
2984
  */
@@ -3052,6 +3138,7 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
3052
3138
  initialPayload: context.requestPayload,
3053
3139
  env: context.env,
3054
3140
  retries: context.retries,
3141
+ retryDelay: context.retryDelay,
3055
3142
  flowControl: context.flowControl
3056
3143
  });
3057
3144
  try {
@@ -3060,6 +3147,9 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
3060
3147
  if (error instanceof WorkflowAbort && error.stepName === this.disabledMessage || error instanceof WorkflowNonRetryableError) {
3061
3148
  return ok("step-found");
3062
3149
  }
3150
+ console.warn(
3151
+ "Upstash Workflow: Received an error while authorizing request. Please avoid throwing errors before the first step of your workflow."
3152
+ );
3063
3153
  return err(error);
3064
3154
  }
3065
3155
  return ok("run-ended");
@@ -3201,9 +3291,9 @@ var parseRequest = async (requestPayload, isFirstInvocation, workflowRunId, requ
3201
3291
  };
3202
3292
  }
3203
3293
  };
3204
- var handleFailure = async (request, requestPayload, qstashClient, initialPayloadParser, routeFunction, failureFunction, env, retries, flowControl, debug) => {
3294
+ var handleFailure = async (request, requestPayload, qstashClient, initialPayloadParser, routeFunction, failureFunction, env, retries, retryDelay, flowControl, debug) => {
3205
3295
  if (request.headers.get(WORKFLOW_FAILURE_HEADER) !== "true") {
3206
- return ok("not-failure-callback");
3296
+ return ok({ result: "not-failure-callback" });
3207
3297
  }
3208
3298
  if (!failureFunction) {
3209
3299
  return err(
@@ -3215,7 +3305,17 @@ var handleFailure = async (request, requestPayload, qstashClient, initialPayload
3215
3305
  try {
3216
3306
  const { status, header, body, url, sourceBody, workflowRunId } = JSON.parse(requestPayload);
3217
3307
  const decodedBody = body ? decodeBase64(body) : "{}";
3218
- const errorPayload = JSON.parse(decodedBody);
3308
+ let errorMessage = "";
3309
+ try {
3310
+ const errorPayload = JSON.parse(decodedBody);
3311
+ if (errorPayload.message) {
3312
+ errorMessage = errorPayload.message;
3313
+ }
3314
+ } catch {
3315
+ }
3316
+ if (!errorMessage) {
3317
+ errorMessage = `Couldn't parse 'failResponse' in 'failureFunction', received: '${decodedBody}'`;
3318
+ }
3219
3319
  const workflowContext = new WorkflowContext({
3220
3320
  qstashClient,
3221
3321
  workflowRunId,
@@ -3227,6 +3327,7 @@ var handleFailure = async (request, requestPayload, qstashClient, initialPayload
3227
3327
  debug,
3228
3328
  env,
3229
3329
  retries,
3330
+ retryDelay,
3230
3331
  flowControl,
3231
3332
  telemetry: void 0
3232
3333
  // not going to make requests in authentication check
@@ -3241,16 +3342,16 @@ var handleFailure = async (request, requestPayload, qstashClient, initialPayload
3241
3342
  } else if (authCheck.value === "run-ended") {
3242
3343
  return err(new WorkflowError("Not authorized to run the failure function."));
3243
3344
  }
3244
- await failureFunction({
3345
+ const failureResponse = await failureFunction({
3245
3346
  context: workflowContext,
3246
3347
  failStatus: status,
3247
- failResponse: errorPayload.message,
3348
+ failResponse: errorMessage,
3248
3349
  failHeaders: header
3249
3350
  });
3351
+ return ok({ result: "is-failure-callback", response: failureResponse });
3250
3352
  } catch (error) {
3251
3353
  return err(error);
3252
3354
  }
3253
- return ok("is-failure-callback");
3254
3355
  };
3255
3356
 
3256
3357
  // src/serve/options.ts
@@ -3266,8 +3367,8 @@ var processOptions = (options) => {
3266
3367
  baseUrl: environment.QSTASH_URL,
3267
3368
  token: environment.QSTASH_TOKEN
3268
3369
  }),
3269
- onStepFinish: (workflowRunId, finishCondition) => {
3270
- if (finishCondition === "auth-fail") {
3370
+ onStepFinish: (workflowRunId, _finishCondition, detailedFinishCondition) => {
3371
+ if (detailedFinishCondition?.condition === "auth-fail") {
3271
3372
  console.error(AUTH_FAIL_MESSAGE);
3272
3373
  return new Response(
3273
3374
  JSON.stringify({
@@ -3275,19 +3376,33 @@ var processOptions = (options) => {
3275
3376
  workflowRunId
3276
3377
  }),
3277
3378
  {
3278
- status: 400
3379
+ status: 400,
3380
+ headers: {
3381
+ [WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
3382
+ }
3279
3383
  }
3280
3384
  );
3281
- } else if (finishCondition instanceof WorkflowNonRetryableError) {
3282
- return new Response(JSON.stringify(formatWorkflowError(finishCondition)), {
3385
+ } else if (detailedFinishCondition?.condition === "non-retryable-error") {
3386
+ return new Response(JSON.stringify(formatWorkflowError(detailedFinishCondition.result)), {
3283
3387
  headers: {
3284
- "Upstash-NonRetryable-Error": "true"
3388
+ "Upstash-NonRetryable-Error": "true",
3389
+ [WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
3285
3390
  },
3286
3391
  status: 489
3287
3392
  });
3393
+ } else if (detailedFinishCondition?.condition === "failure-callback") {
3394
+ return new Response(detailedFinishCondition.result ?? void 0, {
3395
+ status: 200,
3396
+ headers: {
3397
+ [WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
3398
+ }
3399
+ });
3288
3400
  }
3289
3401
  return new Response(JSON.stringify({ workflowRunId }), {
3290
- status: 200
3402
+ status: 200,
3403
+ headers: {
3404
+ [WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
3405
+ }
3291
3406
  });
3292
3407
  },
3293
3408
  initialPayloadParser: (initialRequest) => {
@@ -3361,6 +3476,7 @@ var serveBase = (routeFunction, telemetry, options) => {
3361
3476
  baseUrl,
3362
3477
  env,
3363
3478
  retries,
3479
+ retryDelay,
3364
3480
  useJSONContent,
3365
3481
  disableTelemetry,
3366
3482
  flowControl,
@@ -3391,10 +3507,14 @@ var serveBase = (routeFunction, telemetry, options) => {
3391
3507
  debug
3392
3508
  );
3393
3509
  if (workflowRunEnded) {
3394
- return onStepFinish(workflowRunId, "workflow-already-ended");
3510
+ return onStepFinish(workflowRunId, "workflow-already-ended", {
3511
+ condition: "workflow-already-ended"
3512
+ });
3395
3513
  }
3396
3514
  if (isLastDuplicate) {
3397
- return onStepFinish(workflowRunId, "duplicate-step");
3515
+ return onStepFinish(workflowRunId, "duplicate-step", {
3516
+ condition: "duplicate-step"
3517
+ });
3398
3518
  }
3399
3519
  const failureCheck = await handleFailure(
3400
3520
  request,
@@ -3405,14 +3525,18 @@ var serveBase = (routeFunction, telemetry, options) => {
3405
3525
  failureFunction,
3406
3526
  env,
3407
3527
  retries,
3528
+ retryDelay,
3408
3529
  flowControl,
3409
3530
  debug
3410
3531
  );
3411
3532
  if (failureCheck.isErr()) {
3412
3533
  throw failureCheck.error;
3413
- } else if (failureCheck.value === "is-failure-callback") {
3534
+ } else if (failureCheck.value.result === "is-failure-callback") {
3414
3535
  await debug?.log("WARN", "RESPONSE_DEFAULT", "failureFunction executed");
3415
- return onStepFinish(workflowRunId, "failure-callback");
3536
+ return onStepFinish(workflowRunId, "failure-callback", {
3537
+ condition: "failure-callback",
3538
+ result: failureCheck.value.response
3539
+ });
3416
3540
  }
3417
3541
  const invokeCount = Number(request.headers.get(WORKFLOW_INVOKE_COUNT_HEADER) ?? "0");
3418
3542
  const workflowContext = new WorkflowContext({
@@ -3426,6 +3550,7 @@ var serveBase = (routeFunction, telemetry, options) => {
3426
3550
  debug,
3427
3551
  env,
3428
3552
  retries,
3553
+ retryDelay,
3429
3554
  telemetry,
3430
3555
  invokeCount,
3431
3556
  flowControl
@@ -3441,7 +3566,8 @@ var serveBase = (routeFunction, telemetry, options) => {
3441
3566
  await debug?.log("ERROR", "ERROR", { error: AUTH_FAIL_MESSAGE });
3442
3567
  return onStepFinish(
3443
3568
  isFirstInvocation ? "no-workflow-id" : workflowContext.workflowRunId,
3444
- "auth-fail"
3569
+ "auth-fail",
3570
+ { condition: "auth-fail" }
3445
3571
  );
3446
3572
  }
3447
3573
  const callReturnCheck = await handleThirdPartyCallResult({
@@ -3451,6 +3577,7 @@ var serveBase = (routeFunction, telemetry, options) => {
3451
3577
  workflowUrl,
3452
3578
  failureUrl: workflowFailureUrl,
3453
3579
  retries,
3580
+ retryDelay,
3454
3581
  flowControl,
3455
3582
  telemetry,
3456
3583
  debug
@@ -3478,19 +3605,28 @@ var serveBase = (routeFunction, telemetry, options) => {
3478
3605
  debug
3479
3606
  });
3480
3607
  if (result.isOk() && result.value instanceof WorkflowNonRetryableError) {
3481
- return onStepFinish(workflowRunId, result.value);
3608
+ return onStepFinish(workflowRunId, result.value, {
3609
+ condition: "non-retryable-error",
3610
+ result: result.value
3611
+ });
3482
3612
  }
3483
3613
  if (result.isErr()) {
3484
3614
  await debug?.log("ERROR", "ERROR", { error: result.error.message });
3485
3615
  throw result.error;
3486
3616
  }
3487
3617
  await debug?.log("INFO", "RESPONSE_WORKFLOW");
3488
- return onStepFinish(workflowContext.workflowRunId, "success");
3618
+ return onStepFinish(workflowContext.workflowRunId, "success", {
3619
+ condition: "success"
3620
+ });
3489
3621
  } else if (callReturnCheck.value === "workflow-ended") {
3490
- return onStepFinish(workflowContext.workflowRunId, "workflow-already-ended");
3622
+ return onStepFinish(workflowContext.workflowRunId, "workflow-already-ended", {
3623
+ condition: "workflow-already-ended"
3624
+ });
3491
3625
  }
3492
3626
  await debug?.log("INFO", "RESPONSE_DEFAULT");
3493
- return onStepFinish("no-workflow-id", "fromCallback");
3627
+ return onStepFinish("no-workflow-id", "fromCallback", {
3628
+ condition: "fromCallback"
3629
+ });
3494
3630
  };
3495
3631
  const safeHandler = async (request) => {
3496
3632
  try {
@@ -3505,11 +3641,17 @@ var serveBase = (routeFunction, telemetry, options) => {
3505
3641
  Original error: '${formattedError.message}'`;
3506
3642
  console.error(errorMessage);
3507
3643
  return new Response(errorMessage, {
3508
- status: 500
3644
+ status: 500,
3645
+ headers: {
3646
+ [WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
3647
+ }
3509
3648
  });
3510
3649
  }
3511
3650
  return new Response(JSON.stringify(formattedError), {
3512
- status: 500
3651
+ status: 500,
3652
+ headers: {
3653
+ [WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
3654
+ }
3513
3655
  });
3514
3656
  }
3515
3657
  };
package/cloudflare.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { R as RouteFunction, n as PublicServeOptions, w as InvokableWorkflow } from './types-Dd-3bPoU.mjs';
2
- import { s as serveManyBase } from './serve-many-AFwJPR3S.mjs';
1
+ import { R as RouteFunction, n as PublicServeOptions, x as InvokableWorkflow } from './types--R_3XZXz.mjs';
2
+ import { s as serveManyBase } from './serve-many-DgDSOvQs.mjs';
3
3
  import '@upstash/qstash';
4
4
  import 'zod';
5
5
  import 'ai';
package/cloudflare.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { R as RouteFunction, n as PublicServeOptions, w as InvokableWorkflow } from './types-Dd-3bPoU.js';
2
- import { s as serveManyBase } from './serve-many-AaKSQyi7.js';
1
+ import { R as RouteFunction, n as PublicServeOptions, x as InvokableWorkflow } from './types--R_3XZXz.js';
2
+ import { s as serveManyBase } from './serve-many-B3DfoTFt.js';
3
3
  import '@upstash/qstash';
4
4
  import 'zod';
5
5
  import 'ai';