@upstash/workflow 0.2.22-rc → 0.2.23-rc

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -27,13 +27,102 @@ __export(src_exports, {
27
27
  WorkflowError: () => WorkflowError,
28
28
  WorkflowLogger: () => WorkflowLogger,
29
29
  WorkflowNonRetryableError: () => WorkflowNonRetryableError,
30
+ WorkflowRetryAfterError: () => WorkflowRetryAfterError,
30
31
  WorkflowTool: () => WorkflowTool,
31
32
  serve: () => serve
32
33
  });
33
34
  module.exports = __toCommonJS(src_exports);
34
35
 
35
36
  // src/client/utils.ts
37
+ var import_qstash2 = require("@upstash/qstash");
38
+
39
+ // src/error.ts
36
40
  var import_qstash = require("@upstash/qstash");
41
+ var WorkflowError = class extends import_qstash.QstashError {
42
+ constructor(message) {
43
+ super(message);
44
+ this.name = "WorkflowError";
45
+ }
46
+ };
47
+ var WorkflowAbort = class extends Error {
48
+ stepInfo;
49
+ stepName;
50
+ /**
51
+ * whether workflow is to be canceled on abort
52
+ */
53
+ cancelWorkflow;
54
+ /**
55
+ *
56
+ * @param stepName name of the aborting step
57
+ * @param stepInfo step information
58
+ * @param cancelWorkflow
59
+ */
60
+ constructor(stepName, stepInfo, cancelWorkflow = false) {
61
+ super(
62
+ `This is an Upstash Workflow error thrown after a step executes. It is expected to be raised. Make sure that you await for each step. Also, if you are using try/catch blocks, you should not wrap context.run/sleep/sleepUntil/call methods with try/catch. Aborting workflow after executing step '${stepName}'.`
63
+ );
64
+ this.name = "WorkflowAbort";
65
+ this.stepName = stepName;
66
+ this.stepInfo = stepInfo;
67
+ this.cancelWorkflow = cancelWorkflow;
68
+ }
69
+ };
70
+ var WorkflowNonRetryableError = class extends WorkflowAbort {
71
+ /**
72
+ * @param message error message to be displayed
73
+ */
74
+ constructor(message) {
75
+ super("fail", void 0, false);
76
+ this.name = "WorkflowNonRetryableError";
77
+ if (message) this.message = message;
78
+ }
79
+ };
80
+ var WorkflowRetryAfterError = class extends WorkflowAbort {
81
+ retryAfter;
82
+ /**
83
+ * @param retryAfter time in seconds after which the workflow should be retried
84
+ * @param message error message to be displayed
85
+ */
86
+ constructor(message, retryAfter) {
87
+ super("retry", void 0, false);
88
+ this.name = "WorkflowRetryAfterError";
89
+ this.retryAfter = retryAfter;
90
+ if (message) this.message = message;
91
+ }
92
+ };
93
+ var formatWorkflowError = (error) => {
94
+ return error instanceof Error ? {
95
+ error: error.name,
96
+ message: error.message,
97
+ stack: error.stack
98
+ } : {
99
+ error: "Error",
100
+ message: `An error occured while executing workflow: '${typeof error === "string" ? error : JSON.stringify(error)}'`
101
+ };
102
+ };
103
+ function getConstructorName(obj) {
104
+ if (obj === null || obj === void 0) {
105
+ return null;
106
+ }
107
+ const ctor = obj.constructor;
108
+ if (!ctor || ctor.name === "Object") {
109
+ return null;
110
+ }
111
+ return ctor.name;
112
+ }
113
+ function getConstructorNames(obj) {
114
+ const proto = Object.getPrototypeOf(obj);
115
+ const name = getConstructorName(proto);
116
+ if (name === null) {
117
+ return [];
118
+ }
119
+ return [name, ...getConstructorNames(proto)];
120
+ }
121
+ function isInstanceOf(v, ctor) {
122
+ return getConstructorNames(v).includes(ctor.name);
123
+ }
124
+
125
+ // src/client/utils.ts
37
126
  var makeNotifyRequest = async (requester, eventId, eventData) => {
38
127
  const result = await requester.request({
39
128
  path: ["v2", "notify", eventId],
@@ -80,7 +169,7 @@ var getSteps = async (requester, workflowRunId, messageId, debug) => {
80
169
  return { steps: filteredSteps, workflowRunEnded: false };
81
170
  }
82
171
  } catch (error) {
83
- if (error instanceof import_qstash.QstashError && error.status === 404) {
172
+ if (isInstanceOf(error, import_qstash2.QstashError) && error.status === 404) {
84
173
  await debug?.log("WARN", "ENDPOINT_START", {
85
174
  message: "Couldn't fetch workflow run steps. This can happen if the workflow run succesfully ends before some callback is executed.",
86
175
  error
@@ -105,65 +194,13 @@ var WORKFLOW_PROTOCOL_VERSION_HEADER = "Upstash-Workflow-Sdk-Version";
105
194
  var DEFAULT_CONTENT_TYPE = "application/json";
106
195
  var NO_CONCURRENCY = 1;
107
196
  var DEFAULT_RETRIES = 3;
108
- var VERSION = "v0.2.21";
197
+ var VERSION = "v0.2.22";
109
198
  var SDK_TELEMETRY = `@upstash/workflow@${VERSION}`;
110
199
  var TELEMETRY_HEADER_SDK = "Upstash-Telemetry-Sdk";
111
200
  var TELEMETRY_HEADER_FRAMEWORK = "Upstash-Telemetry-Framework";
112
201
  var TELEMETRY_HEADER_RUNTIME = "Upstash-Telemetry-Runtime";
113
202
  var TELEMETRY_HEADER_AGENT = "Upstash-Telemetry-Agent";
114
203
 
115
- // src/error.ts
116
- var import_qstash2 = require("@upstash/qstash");
117
- var WorkflowError = class extends import_qstash2.QstashError {
118
- constructor(message) {
119
- super(message);
120
- this.name = "WorkflowError";
121
- }
122
- };
123
- var WorkflowAbort = class extends Error {
124
- stepInfo;
125
- stepName;
126
- /**
127
- * whether workflow is to be canceled on abort
128
- */
129
- cancelWorkflow;
130
- /**
131
- *
132
- * @param stepName name of the aborting step
133
- * @param stepInfo step information
134
- * @param cancelWorkflow
135
- */
136
- constructor(stepName, stepInfo, cancelWorkflow = false) {
137
- super(
138
- `This is an Upstash Workflow error thrown after a step executes. It is expected to be raised. Make sure that you await for each step. Also, if you are using try/catch blocks, you should not wrap context.run/sleep/sleepUntil/call methods with try/catch. Aborting workflow after executing step '${stepName}'.`
139
- );
140
- this.name = "WorkflowAbort";
141
- this.stepName = stepName;
142
- this.stepInfo = stepInfo;
143
- this.cancelWorkflow = cancelWorkflow;
144
- }
145
- };
146
- var WorkflowNonRetryableError = class extends WorkflowAbort {
147
- /**
148
- * @param message error message to be displayed
149
- */
150
- constructor(message) {
151
- super("fail", void 0, false);
152
- this.name = "WorkflowNonRetryableError";
153
- if (message) this.message = message;
154
- }
155
- };
156
- var formatWorkflowError = (error) => {
157
- return error instanceof Error ? {
158
- error: error.name,
159
- message: error.message,
160
- stack: error.stack
161
- } : {
162
- error: "Error",
163
- message: `An error occured while executing workflow: '${typeof error === "string" ? error : JSON.stringify(error)}'`
164
- };
165
- };
166
-
167
204
  // src/context/auto-executor.ts
168
205
  var import_qstash5 = require("@upstash/qstash");
169
206
 
@@ -176,8 +213,8 @@ var NANOID_LENGTH = 21;
176
213
  function getRandomInt() {
177
214
  return Math.floor(Math.random() * NANOID_CHARS.length);
178
215
  }
179
- function nanoid() {
180
- return Array.from({ length: NANOID_LENGTH }).map(() => NANOID_CHARS[getRandomInt()]).join("");
216
+ function nanoid(length = NANOID_LENGTH) {
217
+ return Array.from({ length }).map(() => NANOID_CHARS[getRandomInt()]).join("");
181
218
  }
182
219
  function getWorkflowRunId(id) {
183
220
  return `wfr_${id ?? nanoid()}`;
@@ -194,6 +231,37 @@ function decodeBase64(base64) {
194
231
  return binString;
195
232
  }
196
233
  }
234
+ function getUserIdFromToken(qstashClient) {
235
+ try {
236
+ const token = qstashClient.token;
237
+ const decodedToken = decodeBase64(token);
238
+ const tokenPayload = JSON.parse(decodedToken);
239
+ const userId = tokenPayload.UserID;
240
+ if (!userId) {
241
+ throw new WorkflowError("QStash token payload does not contain userId");
242
+ }
243
+ return userId;
244
+ } catch (error) {
245
+ throw new WorkflowError(
246
+ `Failed to decode QStash token while running create webhook step: ${error.message}`
247
+ );
248
+ }
249
+ }
250
+ function getQStashUrl(qstashClient) {
251
+ try {
252
+ const requester = qstashClient.http;
253
+ const baseUrl = requester.baseUrl;
254
+ if (!baseUrl) {
255
+ throw new WorkflowError("QStash client does not have a baseUrl");
256
+ }
257
+ return baseUrl;
258
+ } catch (error) {
259
+ throw new WorkflowError(`Failed to get QStash URL from client: ${error.message}`);
260
+ }
261
+ }
262
+ function getEventId() {
263
+ return `evt_${nanoid(15)}`;
264
+ }
197
265
 
198
266
  // node_modules/neverthrow/dist/index.es.js
199
267
  var defaultErrorConfig = {
@@ -619,7 +687,9 @@ var StepTypes = [
619
687
  "Call",
620
688
  "Wait",
621
689
  "Notify",
622
- "Invoke"
690
+ "Invoke",
691
+ "CreateWebhook",
692
+ "WaitForWebhook"
623
693
  ];
624
694
 
625
695
  // src/workflow-requests.ts
@@ -723,17 +793,17 @@ var triggerRouteFunction = async ({
723
793
  return ok("workflow-finished");
724
794
  } catch (error) {
725
795
  const error_ = error;
726
- if (error instanceof import_qstash3.QstashError && error.status === 400) {
796
+ if (isInstanceOf(error, import_qstash3.QstashError) && error.status === 400) {
727
797
  await debug?.log("WARN", "RESPONSE_WORKFLOW", {
728
798
  message: `tried to append to a cancelled workflow. exiting without publishing.`,
729
799
  name: error.name,
730
800
  errorMessage: error.message
731
801
  });
732
802
  return ok("workflow-was-finished");
733
- } else if (!(error_ instanceof WorkflowAbort)) {
734
- return err(error_);
735
- } else if (error_ instanceof WorkflowNonRetryableError) {
803
+ } else if (isInstanceOf(error_, WorkflowNonRetryableError) || isInstanceOf(error_, WorkflowRetryAfterError)) {
736
804
  return ok(error_);
805
+ } else if (!isInstanceOf(error_, WorkflowAbort)) {
806
+ return err(error_);
737
807
  } else if (error_.cancelWorkflow) {
738
808
  await onCancel();
739
809
  return ok("workflow-finished");
@@ -931,7 +1001,9 @@ If you want to disable QStash Verification, you should clear env variables QSTAS
931
1001
  // src/context/steps.ts
932
1002
  var BaseLazyStep = class _BaseLazyStep {
933
1003
  stepName;
934
- constructor(stepName) {
1004
+ context;
1005
+ constructor(context, stepName) {
1006
+ this.context = context;
935
1007
  if (!stepName) {
936
1008
  throw new WorkflowError(
937
1009
  "A workflow step name cannot be undefined or an empty string. Please provide a name for your workflow step."
@@ -949,13 +1021,14 @@ var BaseLazyStep = class _BaseLazyStep {
949
1021
  *
950
1022
  * will be called when returning the steps to the context from auto executor
951
1023
  *
952
- * @param out field of the step
1024
+ * @param step step
953
1025
  * @returns parsed out field
954
1026
  */
955
- parseOut(out) {
1027
+ parseOut(step) {
1028
+ const out = step.out;
956
1029
  if (out === void 0) {
957
1030
  if (this.allowUndefinedOut) {
958
- return void 0;
1031
+ return this.handleUndefinedOut(step);
959
1032
  } else {
960
1033
  throw new WorkflowError(
961
1034
  `Error while parsing output of ${this.stepType} step. Expected a string, but got: undefined`
@@ -963,27 +1036,26 @@ var BaseLazyStep = class _BaseLazyStep {
963
1036
  }
964
1037
  }
965
1038
  if (typeof out === "object") {
966
- if (this.stepType !== "Wait") {
967
- console.warn(
968
- `Error while parsing ${this.stepType} step output. Expected a string, but got object. Please reach out to Upstash Support.`
969
- );
970
- return out;
971
- }
972
- return {
973
- ...out,
974
- eventData: _BaseLazyStep.tryParsing(out.eventData)
975
- };
1039
+ console.warn(
1040
+ `Error while parsing ${this.stepType} step output. Expected a string, but got object. Please reach out to Upstash Support.`
1041
+ );
1042
+ return out;
976
1043
  }
977
1044
  if (typeof out !== "string") {
978
1045
  throw new WorkflowError(
979
1046
  `Error while parsing output of ${this.stepType} step. Expected a string or undefined, but got: ${typeof out}`
980
1047
  );
981
1048
  }
982
- return this.safeParseOut(out);
1049
+ return this.safeParseOut(out, step);
983
1050
  }
984
- safeParseOut(out) {
1051
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1052
+ safeParseOut(out, step) {
985
1053
  return _BaseLazyStep.tryParsing(out);
986
1054
  }
1055
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1056
+ handleUndefinedOut(step) {
1057
+ return void 0;
1058
+ }
987
1059
  static tryParsing(stepOut) {
988
1060
  try {
989
1061
  return JSON.parse(stepOut);
@@ -1034,8 +1106,8 @@ var LazyFunctionStep = class extends BaseLazyStep {
1034
1106
  stepFunction;
1035
1107
  stepType = "Run";
1036
1108
  allowUndefinedOut = true;
1037
- constructor(stepName, stepFunction) {
1038
- super(stepName);
1109
+ constructor(context, stepName, stepFunction) {
1110
+ super(context, stepName);
1039
1111
  this.stepFunction = stepFunction;
1040
1112
  }
1041
1113
  getPlanStep(concurrent, targetStep) {
@@ -1065,8 +1137,8 @@ var LazySleepStep = class extends BaseLazyStep {
1065
1137
  sleep;
1066
1138
  stepType = "SleepFor";
1067
1139
  allowUndefinedOut = true;
1068
- constructor(stepName, sleep) {
1069
- super(stepName);
1140
+ constructor(context, stepName, sleep) {
1141
+ super(context, stepName);
1070
1142
  this.sleep = sleep;
1071
1143
  }
1072
1144
  getPlanStep(concurrent, targetStep) {
@@ -1107,8 +1179,8 @@ var LazySleepUntilStep = class extends BaseLazyStep {
1107
1179
  sleepUntil;
1108
1180
  stepType = "SleepUntil";
1109
1181
  allowUndefinedOut = true;
1110
- constructor(stepName, sleepUntil) {
1111
- super(stepName);
1182
+ constructor(context, stepName, sleepUntil) {
1183
+ super(context, stepName);
1112
1184
  this.sleepUntil = sleepUntil;
1113
1185
  }
1114
1186
  getPlanStep(concurrent, targetStep) {
@@ -1160,8 +1232,8 @@ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
1160
1232
  stringifyBody;
1161
1233
  stepType = "Call";
1162
1234
  allowUndefinedOut = false;
1163
- constructor(stepName, url, method, body, headers, retries, retryDelay, timeout, flowControl, stringifyBody) {
1164
- super(stepName);
1235
+ constructor(context, stepName, url, method, body, headers, retries, retryDelay, timeout, flowControl, stringifyBody) {
1236
+ super(context, stepName);
1165
1237
  this.url = url;
1166
1238
  this.method = method;
1167
1239
  this.body = body;
@@ -1305,13 +1377,12 @@ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
1305
1377
  ]);
1306
1378
  }
1307
1379
  };
1308
- var LazyWaitForEventStep = class extends BaseLazyStep {
1380
+ var LazyWaitEventStep = class extends BaseLazyStep {
1309
1381
  eventId;
1310
1382
  timeout;
1311
- stepType = "Wait";
1312
1383
  allowUndefinedOut = false;
1313
- constructor(stepName, eventId, timeout) {
1314
- super(stepName);
1384
+ constructor(context, stepName, eventId, timeout) {
1385
+ super(context, stepName);
1315
1386
  this.eventId = eventId;
1316
1387
  this.timeout = timeout;
1317
1388
  }
@@ -1336,13 +1407,6 @@ var LazyWaitForEventStep = class extends BaseLazyStep {
1336
1407
  concurrent
1337
1408
  });
1338
1409
  }
1339
- safeParseOut(out) {
1340
- const result = JSON.parse(out);
1341
- return {
1342
- ...result,
1343
- eventData: BaseLazyStep.tryParsing(result.eventData)
1344
- };
1345
- }
1346
1410
  getHeaders({ context, telemetry, invokeCount, step }) {
1347
1411
  const headers = super.getHeaders({ context, telemetry, invokeCount, step });
1348
1412
  headers.headers["Upstash-Workflow-CallType"] = "step";
@@ -1376,7 +1440,7 @@ var LazyWaitForEventStep = class extends BaseLazyStep {
1376
1440
  timeoutHeaders,
1377
1441
  step: {
1378
1442
  stepId: step.stepId,
1379
- stepType: "Wait",
1443
+ stepType: this.stepType,
1380
1444
  stepName: step.stepName,
1381
1445
  concurrent: step.concurrent,
1382
1446
  targetStep: step.targetStep
@@ -1397,8 +1461,8 @@ var LazyWaitForEventStep = class extends BaseLazyStep {
1397
1461
  };
1398
1462
  var LazyNotifyStep = class extends LazyFunctionStep {
1399
1463
  stepType = "Notify";
1400
- constructor(stepName, eventId, eventData, requester) {
1401
- super(stepName, async () => {
1464
+ constructor(context, stepName, eventId, eventData, requester) {
1465
+ super(context, stepName, async () => {
1402
1466
  const notifyResponse = await makeNotifyRequest(requester, eventId, eventData);
1403
1467
  return {
1404
1468
  eventId,
@@ -1423,7 +1487,7 @@ var LazyInvokeStep = class extends BaseLazyStep {
1423
1487
  * workflow id of the invoked workflow
1424
1488
  */
1425
1489
  workflowId;
1426
- constructor(stepName, {
1490
+ constructor(context, stepName, {
1427
1491
  workflow,
1428
1492
  body,
1429
1493
  headers = {},
@@ -1433,7 +1497,7 @@ var LazyInvokeStep = class extends BaseLazyStep {
1433
1497
  flowControl,
1434
1498
  stringifyBody = true
1435
1499
  }) {
1436
- super(stepName);
1500
+ super(context, stepName);
1437
1501
  this.params = {
1438
1502
  workflow,
1439
1503
  body,
@@ -1494,6 +1558,9 @@ var LazyInvokeStep = class extends BaseLazyStep {
1494
1558
  userHeaders: context.headers,
1495
1559
  invokeCount
1496
1560
  });
1561
+ context.qstashClient.http.headers?.forEach((value, key) => {
1562
+ invokerHeaders[key] = value;
1563
+ });
1497
1564
  invokerHeaders["Upstash-Workflow-Runid"] = context.workflowRunId;
1498
1565
  let invokeBody;
1499
1566
  if (this.params.stringifyBody) {
@@ -1565,6 +1632,91 @@ var LazyInvokeStep = class extends BaseLazyStep {
1565
1632
  return [result];
1566
1633
  }
1567
1634
  };
1635
+ var LazyCreateWebhookStep = class extends BaseLazyStep {
1636
+ stepType = "CreateWebhook";
1637
+ allowUndefinedOut = false;
1638
+ getPlanStep(concurrent, targetStep) {
1639
+ return {
1640
+ stepId: 0,
1641
+ stepName: this.stepName,
1642
+ stepType: this.stepType,
1643
+ concurrent,
1644
+ targetStep
1645
+ };
1646
+ }
1647
+ async getResultStep(concurrent, stepId) {
1648
+ return {
1649
+ stepId,
1650
+ stepName: this.stepName,
1651
+ stepType: this.stepType,
1652
+ out: void 0,
1653
+ concurrent
1654
+ };
1655
+ }
1656
+ getBody({ step, context }) {
1657
+ const userId = getUserIdFromToken(context.qstashClient);
1658
+ const out = [userId, context.workflowRunId, getEventId()].join("/");
1659
+ return JSON.stringify({
1660
+ ...step,
1661
+ out
1662
+ });
1663
+ }
1664
+ safeParseOut(out) {
1665
+ const [userId, workflowRunId, eventId] = out.split("/");
1666
+ const qstashUrl = getQStashUrl(this.context.qstashClient);
1667
+ return {
1668
+ webhookUrl: `${qstashUrl}/v2/workflows/hooks/${userId}/${workflowRunId}/${eventId}`,
1669
+ eventId
1670
+ };
1671
+ }
1672
+ };
1673
+ var LazyWaitForWebhookStep = class extends LazyWaitEventStep {
1674
+ stepType = "WaitForWebhook";
1675
+ allowUndefinedOut = true;
1676
+ constructor(context, stepName, webhook, timeout) {
1677
+ super(context, stepName, webhook.eventId, timeout);
1678
+ }
1679
+ safeParseOut(out) {
1680
+ const eventData = decodeBase64(out);
1681
+ const parsedEventData = BaseLazyStep.tryParsing(eventData);
1682
+ const body = parsedEventData.body;
1683
+ const parsedBody = typeof body === "string" ? decodeBase64(body) : void 0;
1684
+ const request = new Request(
1685
+ `${parsedEventData.proto}://${parsedEventData.host}${parsedEventData.url}`,
1686
+ {
1687
+ method: parsedEventData.method,
1688
+ headers: parsedEventData.header,
1689
+ body: parsedBody
1690
+ }
1691
+ );
1692
+ return {
1693
+ request,
1694
+ timeout: false
1695
+ };
1696
+ }
1697
+ handleUndefinedOut() {
1698
+ return {
1699
+ timeout: true,
1700
+ request: void 0
1701
+ };
1702
+ }
1703
+ };
1704
+ var LazyWaitForEventStep = class extends LazyWaitEventStep {
1705
+ stepType = "Wait";
1706
+ allowUndefinedOut = true;
1707
+ parseWaitForEventOut(out, waitTimeout) {
1708
+ return {
1709
+ eventData: out ? BaseLazyStep.tryParsing(decodeBase64(out)) : void 0,
1710
+ timeout: waitTimeout ?? false
1711
+ };
1712
+ }
1713
+ safeParseOut(out, step) {
1714
+ return this.parseWaitForEventOut(out, step.waitTimeout);
1715
+ }
1716
+ handleUndefinedOut(step) {
1717
+ return this.parseWaitForEventOut(void 0, step.waitTimeout);
1718
+ }
1719
+ };
1568
1720
 
1569
1721
  // src/agents/constants.ts
1570
1722
  var AGENT_NAME_HEADER = "upstash-agent-name";
@@ -1969,7 +2121,7 @@ var AutoExecutor = class _AutoExecutor {
1969
2121
  step,
1970
2122
  stepCount: this.stepCount
1971
2123
  });
1972
- return lazyStep.parseOut(step.out);
2124
+ return lazyStep.parseOut(step);
1973
2125
  }
1974
2126
  const resultStep = await submitSingleStep({
1975
2127
  context: this.context,
@@ -2040,7 +2192,7 @@ var AutoExecutor = class _AutoExecutor {
2040
2192
  });
2041
2193
  throw new WorkflowAbort(parallelStep.stepName, resultStep);
2042
2194
  } catch (error) {
2043
- if (error instanceof WorkflowAbort || error instanceof import_qstash5.QstashError && error.status === 400) {
2195
+ if (isInstanceOf(error, WorkflowAbort) || isInstanceOf(error, import_qstash5.QstashError) && error.status === 400) {
2044
2196
  throw error;
2045
2197
  }
2046
2198
  throw new WorkflowError(
@@ -2056,7 +2208,7 @@ var AutoExecutor = class _AutoExecutor {
2056
2208
  const parallelResultSteps = sortedSteps.filter((step) => step.stepId >= initialStepCount).slice(0, parallelSteps.length);
2057
2209
  validateParallelSteps(parallelSteps, parallelResultSteps);
2058
2210
  return parallelResultSteps.map(
2059
- (step, index) => parallelSteps[index].parseOut(step.out)
2211
+ (step, index) => parallelSteps[index].parseOut(step)
2060
2212
  );
2061
2213
  }
2062
2214
  }
@@ -2112,7 +2264,6 @@ var AutoExecutor = class _AutoExecutor {
2112
2264
  * @param index index of the current step
2113
2265
  * @returns result[index] if lazyStepList > 1, otherwise result
2114
2266
  */
2115
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
2116
2267
  static getResult(lazyStepList, result, index) {
2117
2268
  if (lazyStepList.length === 1) {
2118
2269
  return result;
@@ -2147,7 +2298,7 @@ var validateParallelSteps = (lazySteps, stepsFromRequest) => {
2147
2298
  validateStep(lazySteps[index], stepFromRequest);
2148
2299
  }
2149
2300
  } catch (error) {
2150
- if (error instanceof WorkflowError) {
2301
+ if (isInstanceOf(error, WorkflowError)) {
2151
2302
  const lazyStepNames = lazySteps.map((lazyStep) => lazyStep.stepName);
2152
2303
  const lazyStepTypes = lazySteps.map((lazyStep) => lazyStep.stepType);
2153
2304
  const requestStepNames = stepsFromRequest.map((step) => step.stepName);
@@ -2328,7 +2479,7 @@ var fetchWithContextCall = async (context, agentCallParams, ...params) => {
2328
2479
  headers: responseHeaders
2329
2480
  });
2330
2481
  } catch (error) {
2331
- if (error instanceof Error && error.name === "WorkflowAbort") {
2482
+ if (error instanceof Error && isInstanceOf(error, WorkflowAbort)) {
2332
2483
  throw error;
2333
2484
  } else {
2334
2485
  console.error("Error in fetch implementation:", error);
@@ -2461,10 +2612,10 @@ var Agent = class {
2461
2612
  });
2462
2613
  return { text: result.text };
2463
2614
  } catch (error) {
2464
- if (error instanceof import_ai2.ToolExecutionError) {
2465
- if (error.cause instanceof Error && error.cause.name === "WorkflowAbort") {
2615
+ if (isInstanceOf(error, import_ai2.ToolExecutionError)) {
2616
+ if (error.cause instanceof Error && isInstanceOf(error.cause, WorkflowAbort)) {
2466
2617
  throw error.cause;
2467
- } else if (error.cause instanceof import_ai2.ToolExecutionError && error.cause.cause instanceof Error && error.cause.cause.name === "WorkflowAbort") {
2618
+ } else if (isInstanceOf(error.cause, import_ai2.ToolExecutionError) && isInstanceOf(error.cause.cause, WorkflowAbort)) {
2468
2619
  throw error.cause.cause;
2469
2620
  } else {
2470
2621
  throw error;
@@ -2868,7 +3019,7 @@ var WorkflowContext = class {
2868
3019
  */
2869
3020
  async run(stepName, stepFunction) {
2870
3021
  const wrappedStepFunction = () => this.executor.wrapStep(stepName, stepFunction);
2871
- return await this.addStep(new LazyFunctionStep(stepName, wrappedStepFunction));
3022
+ return await this.addStep(new LazyFunctionStep(this, stepName, wrappedStepFunction));
2872
3023
  }
2873
3024
  /**
2874
3025
  * Stops the execution for the duration provided.
@@ -2882,7 +3033,7 @@ var WorkflowContext = class {
2882
3033
  * @returns undefined
2883
3034
  */
2884
3035
  async sleep(stepName, duration) {
2885
- await this.addStep(new LazySleepStep(stepName, duration));
3036
+ await this.addStep(new LazySleepStep(this, stepName, duration));
2886
3037
  }
2887
3038
  /**
2888
3039
  * Stops the execution until the date time provided.
@@ -2904,13 +3055,14 @@ var WorkflowContext = class {
2904
3055
  datetime = typeof datetime === "string" ? new Date(datetime) : datetime;
2905
3056
  time = Math.round(datetime.getTime() / 1e3);
2906
3057
  }
2907
- await this.addStep(new LazySleepUntilStep(stepName, time));
3058
+ await this.addStep(new LazySleepUntilStep(this, stepName, time));
2908
3059
  }
2909
3060
  async call(stepName, settings) {
2910
3061
  let callStep;
2911
3062
  if ("workflow" in settings) {
2912
3063
  const url = getNewUrlFromWorkflowId(this.url, settings.workflow.workflowId);
2913
3064
  callStep = new LazyCallStep(
3065
+ this,
2914
3066
  stepName,
2915
3067
  url,
2916
3068
  "POST",
@@ -2935,6 +3087,7 @@ var WorkflowContext = class {
2935
3087
  stringifyBody = true
2936
3088
  } = settings;
2937
3089
  callStep = new LazyCallStep(
3090
+ this,
2938
3091
  stepName,
2939
3092
  url,
2940
3093
  method,
@@ -2986,7 +3139,9 @@ var WorkflowContext = class {
2986
3139
  async waitForEvent(stepName, eventId, options = {}) {
2987
3140
  const { timeout = "7d" } = options;
2988
3141
  const timeoutStr = typeof timeout === "string" ? timeout : `${timeout}s`;
2989
- return await this.addStep(new LazyWaitForEventStep(stepName, eventId, timeoutStr));
3142
+ return await this.addStep(
3143
+ new LazyWaitForEventStep(this, stepName, eventId, timeoutStr)
3144
+ );
2990
3145
  }
2991
3146
  /**
2992
3147
  * Notify workflow runs waiting for an event
@@ -3011,11 +3166,19 @@ var WorkflowContext = class {
3011
3166
  */
3012
3167
  async notify(stepName, eventId, eventData) {
3013
3168
  return await this.addStep(
3014
- new LazyNotifyStep(stepName, eventId, eventData, this.qstashClient.http)
3169
+ new LazyNotifyStep(this, stepName, eventId, eventData, this.qstashClient.http)
3015
3170
  );
3016
3171
  }
3017
3172
  async invoke(stepName, settings) {
3018
- return await this.addStep(new LazyInvokeStep(stepName, settings));
3173
+ return await this.addStep(
3174
+ new LazyInvokeStep(this, stepName, settings)
3175
+ );
3176
+ }
3177
+ async createWebhook(stepName) {
3178
+ return await this.addStep(new LazyCreateWebhookStep(this, stepName));
3179
+ }
3180
+ async waitForWebhook(stepName, webhook, timeout) {
3181
+ return await this.addStep(new LazyWaitForWebhookStep(this, stepName, webhook, timeout));
3019
3182
  }
3020
3183
  /**
3021
3184
  * Cancel the current workflow run
@@ -3146,7 +3309,7 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
3146
3309
  try {
3147
3310
  await routeFunction(disabledContext);
3148
3311
  } catch (error) {
3149
- if (error instanceof WorkflowAbort && error.stepName === this.disabledMessage || error instanceof WorkflowNonRetryableError) {
3312
+ if (isInstanceOf(error, WorkflowAbort) && error.stepName === this.disabledMessage || isInstanceOf(error, WorkflowNonRetryableError) || isInstanceOf(error, WorkflowRetryAfterError)) {
3150
3313
  return ok("step-found");
3151
3314
  }
3152
3315
  console.warn(
@@ -3179,13 +3342,6 @@ var processRawSteps = (rawSteps) => {
3179
3342
  const stepsToDecode = encodedSteps.filter((step) => step.callType === "step");
3180
3343
  const otherSteps = stepsToDecode.map((rawStep) => {
3181
3344
  const step = JSON.parse(decodeBase64(rawStep.body));
3182
- if (step.waitEventId) {
3183
- const newOut = {
3184
- eventData: step.out ? decodeBase64(step.out) : void 0,
3185
- timeout: step.waitTimeout ?? false
3186
- };
3187
- step.out = newOut;
3188
- }
3189
3345
  return step;
3190
3346
  });
3191
3347
  const steps = [initialStep, ...otherSteps];
@@ -3399,13 +3555,24 @@ var processOptions = (options) => {
3399
3555
  },
3400
3556
  status: 489
3401
3557
  });
3402
- } else if (detailedFinishCondition?.condition === "failure-callback") {
3403
- return new Response(detailedFinishCondition.result ?? void 0, {
3404
- status: 200,
3558
+ } else if (detailedFinishCondition?.condition === "retry-after-error") {
3559
+ return new Response(JSON.stringify(formatWorkflowError(detailedFinishCondition.result)), {
3405
3560
  headers: {
3561
+ "Retry-After": detailedFinishCondition.result.retryAfter.toString(),
3406
3562
  [WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
3407
- }
3563
+ },
3564
+ status: 429
3408
3565
  });
3566
+ } else if (detailedFinishCondition?.condition === "failure-callback") {
3567
+ return new Response(
3568
+ JSON.stringify({ result: detailedFinishCondition.result ?? void 0 }),
3569
+ {
3570
+ status: 200,
3571
+ headers: {
3572
+ [WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
3573
+ }
3574
+ }
3575
+ );
3409
3576
  }
3410
3577
  return new Response(JSON.stringify({ workflowRunId }), {
3411
3578
  status: 200,
@@ -3615,12 +3782,18 @@ var serveBase = (routeFunction, telemetry, options) => {
3615
3782
  },
3616
3783
  debug
3617
3784
  });
3618
- if (result.isOk() && result.value instanceof WorkflowNonRetryableError) {
3785
+ if (result.isOk() && isInstanceOf(result.value, WorkflowNonRetryableError)) {
3619
3786
  return onStepFinish(workflowRunId, result.value, {
3620
3787
  condition: "non-retryable-error",
3621
3788
  result: result.value
3622
3789
  });
3623
3790
  }
3791
+ if (result.isOk() && isInstanceOf(result.value, WorkflowRetryAfterError)) {
3792
+ return onStepFinish(workflowRunId, result.value, {
3793
+ condition: "retry-after-error",
3794
+ result: result.value
3795
+ });
3796
+ }
3624
3797
  if (result.isErr()) {
3625
3798
  await debug?.log("ERROR", "ERROR", { error: result.error.message });
3626
3799
  throw result.error;
@@ -3651,7 +3824,7 @@ var serveBase = (routeFunction, telemetry, options) => {
3651
3824
  const errorMessage = `Error while running onError callback: '${formattedOnErrorError.message}'.
3652
3825
  Original error: '${formattedError.message}'`;
3653
3826
  console.error(errorMessage);
3654
- return new Response(errorMessage, {
3827
+ return new Response(JSON.stringify({ error: errorMessage }), {
3655
3828
  status: 500,
3656
3829
  headers: {
3657
3830
  [WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
@@ -3920,14 +4093,14 @@ var Client4 = class {
3920
4093
  workflowRunId: finalWorkflowRunId,
3921
4094
  retries: option.retries,
3922
4095
  retryDelay: option.retryDelay,
3923
- telemetry: { sdk: SDK_TELEMETRY },
4096
+ telemetry: option.disableTelemetry ? void 0 : { sdk: SDK_TELEMETRY },
3924
4097
  flowControl: option.flowControl,
3925
4098
  failureUrl,
3926
4099
  label: option.label
3927
4100
  });
3928
4101
  return {
3929
4102
  workflowContext: context,
3930
- telemetry: { sdk: SDK_TELEMETRY },
4103
+ telemetry: option.disableTelemetry ? void 0 : { sdk: SDK_TELEMETRY },
3931
4104
  delay: option.delay,
3932
4105
  notBefore: option.notBefore,
3933
4106
  keepTriggerConfig: option.keepTriggerConfig
@@ -4012,6 +4185,7 @@ var Client4 = class {
4012
4185
  WorkflowError,
4013
4186
  WorkflowLogger,
4014
4187
  WorkflowNonRetryableError,
4188
+ WorkflowRetryAfterError,
4015
4189
  WorkflowTool,
4016
4190
  serve
4017
4191
  });