@upstash/workflow 0.2.11 → 0.2.13

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
@@ -103,11 +103,12 @@ var WORKFLOW_PROTOCOL_VERSION_HEADER = "Upstash-Workflow-Sdk-Version";
103
103
  var DEFAULT_CONTENT_TYPE = "application/json";
104
104
  var NO_CONCURRENCY = 1;
105
105
  var DEFAULT_RETRIES = 3;
106
- var VERSION = "v0.2.7";
106
+ var VERSION = "v0.2.13";
107
107
  var SDK_TELEMETRY = `@upstash/workflow@${VERSION}`;
108
108
  var TELEMETRY_HEADER_SDK = "Upstash-Telemetry-Sdk";
109
109
  var TELEMETRY_HEADER_FRAMEWORK = "Upstash-Telemetry-Framework";
110
110
  var TELEMETRY_HEADER_RUNTIME = "Upstash-Telemetry-Runtime";
111
+ var TELEMETRY_HEADER_AGENT = "Upstash-Telemetry-Agent";
111
112
 
112
113
  // src/error.ts
113
114
  var import_qstash2 = require("@upstash/qstash");
@@ -146,10 +147,16 @@ var formatWorkflowError = (error) => {
146
147
  message: error.message
147
148
  } : {
148
149
  error: "Error",
149
- message: "An error occured while executing workflow."
150
+ message: `An error occured while executing workflow: '${typeof error === "string" ? error : JSON.stringify(error)}'`
150
151
  };
151
152
  };
152
153
 
154
+ // src/context/auto-executor.ts
155
+ var import_qstash5 = require("@upstash/qstash");
156
+
157
+ // src/qstash/headers.ts
158
+ var import_qstash4 = require("@upstash/qstash");
159
+
153
160
  // src/utils.ts
154
161
  var NANOID_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
155
162
  var NANOID_LENGTH = 21;
@@ -175,574 +182,231 @@ function decodeBase64(base64) {
175
182
  }
176
183
  }
177
184
 
178
- // src/context/steps.ts
179
- var BaseLazyStep = class _BaseLazyStep {
180
- stepName;
181
- constructor(stepName) {
182
- if (!stepName) {
183
- throw new WorkflowError(
184
- "A workflow step name cannot be undefined or an empty string. Please provide a name for your workflow step."
185
- );
186
- }
187
- this.stepName = stepName;
185
+ // node_modules/neverthrow/dist/index.es.js
186
+ var defaultErrorConfig = {
187
+ withStackTrace: false
188
+ };
189
+ var createNeverThrowError = (message, result, config = defaultErrorConfig) => {
190
+ const data = result.isOk() ? { type: "Ok", value: result.value } : { type: "Err", value: result.error };
191
+ const maybeStack = config.withStackTrace ? new Error().stack : void 0;
192
+ return {
193
+ data,
194
+ message,
195
+ stack: maybeStack
196
+ };
197
+ };
198
+ function __awaiter(thisArg, _arguments, P, generator) {
199
+ function adopt(value) {
200
+ return value instanceof P ? value : new P(function(resolve) {
201
+ resolve(value);
202
+ });
188
203
  }
189
- /**
190
- * parse the out field of a step result.
191
- *
192
- * will be called when returning the steps to the context from auto executor
193
- *
194
- * @param out field of the step
195
- * @returns parsed out field
196
- */
197
- parseOut(out) {
198
- if (out === void 0) {
199
- if (this.allowUndefinedOut) {
200
- return void 0;
201
- } else {
202
- throw new WorkflowError(
203
- `Error while parsing output of ${this.stepType} step. Expected a string, but got: undefined`
204
- );
204
+ return new (P || (P = Promise))(function(resolve, reject) {
205
+ function fulfilled(value) {
206
+ try {
207
+ step(generator.next(value));
208
+ } catch (e) {
209
+ reject(e);
205
210
  }
206
211
  }
207
- if (typeof out === "object") {
208
- if (this.stepType !== "Wait") {
209
- console.warn(
210
- `Error while parsing ${this.stepType} step output. Expected a string, but got object. Please reach out to Upstash Support.`
211
- );
212
- return out;
212
+ function rejected(value) {
213
+ try {
214
+ step(generator["throw"](value));
215
+ } catch (e) {
216
+ reject(e);
213
217
  }
214
- return {
215
- ...out,
216
- eventData: _BaseLazyStep.tryParsing(out.eventData)
217
- };
218
218
  }
219
- if (typeof out !== "string") {
220
- throw new WorkflowError(
221
- `Error while parsing output of ${this.stepType} step. Expected a string or undefined, but got: ${typeof out}`
222
- );
219
+ function step(result) {
220
+ result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
223
221
  }
224
- return this.safeParseOut(out);
225
- }
226
- safeParseOut(out) {
227
- return _BaseLazyStep.tryParsing(out);
222
+ step((generator = generator.apply(thisArg, [])).next());
223
+ });
224
+ }
225
+ function __values(o) {
226
+ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
227
+ if (m) return m.call(o);
228
+ if (o && typeof o.length === "number") return {
229
+ next: function() {
230
+ if (o && i >= o.length) o = void 0;
231
+ return { value: o && o[i++], done: !o };
232
+ }
233
+ };
234
+ throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
235
+ }
236
+ function __await(v) {
237
+ return this instanceof __await ? (this.v = v, this) : new __await(v);
238
+ }
239
+ function __asyncGenerator(thisArg, _arguments, generator) {
240
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
241
+ var g = generator.apply(thisArg, _arguments || []), i, q = [];
242
+ return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function() {
243
+ return this;
244
+ }, i;
245
+ function verb(n) {
246
+ if (g[n]) i[n] = function(v) {
247
+ return new Promise(function(a, b) {
248
+ q.push([n, v, a, b]) > 1 || resume(n, v);
249
+ });
250
+ };
228
251
  }
229
- static tryParsing(stepOut) {
252
+ function resume(n, v) {
230
253
  try {
231
- return JSON.parse(stepOut);
232
- } catch {
233
- return stepOut;
254
+ step(g[n](v));
255
+ } catch (e) {
256
+ settle(q[0][3], e);
234
257
  }
235
258
  }
236
- };
237
- var LazyFunctionStep = class extends BaseLazyStep {
238
- stepFunction;
239
- stepType = "Run";
240
- allowUndefinedOut = true;
241
- constructor(stepName, stepFunction) {
242
- super(stepName);
243
- this.stepFunction = stepFunction;
259
+ function step(r) {
260
+ r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r);
244
261
  }
245
- getPlanStep(concurrent, targetStep) {
246
- return {
247
- stepId: 0,
248
- stepName: this.stepName,
249
- stepType: this.stepType,
250
- concurrent,
251
- targetStep
252
- };
262
+ function fulfill(value) {
263
+ resume("next", value);
253
264
  }
254
- async getResultStep(concurrent, stepId) {
255
- let result = this.stepFunction();
256
- if (result instanceof Promise) {
257
- result = await result;
258
- }
259
- return {
260
- stepId,
261
- stepName: this.stepName,
262
- stepType: this.stepType,
263
- out: result,
264
- concurrent
265
- };
265
+ function reject(value) {
266
+ resume("throw", value);
266
267
  }
267
- };
268
- var LazySleepStep = class extends BaseLazyStep {
269
- sleep;
270
- stepType = "SleepFor";
271
- allowUndefinedOut = true;
272
- constructor(stepName, sleep) {
273
- super(stepName);
274
- this.sleep = sleep;
268
+ function settle(f, v) {
269
+ if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]);
275
270
  }
276
- getPlanStep(concurrent, targetStep) {
277
- return {
278
- stepId: 0,
279
- stepName: this.stepName,
280
- stepType: this.stepType,
281
- sleepFor: this.sleep,
282
- concurrent,
283
- targetStep
271
+ }
272
+ function __asyncDelegator(o) {
273
+ var i, p;
274
+ return i = {}, verb("next"), verb("throw", function(e) {
275
+ throw e;
276
+ }), verb("return"), i[Symbol.iterator] = function() {
277
+ return this;
278
+ }, i;
279
+ function verb(n, f) {
280
+ i[n] = o[n] ? function(v) {
281
+ return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v;
282
+ } : f;
283
+ }
284
+ }
285
+ function __asyncValues(o) {
286
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
287
+ var m = o[Symbol.asyncIterator], i;
288
+ return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function() {
289
+ return this;
290
+ }, i);
291
+ function verb(n) {
292
+ i[n] = o[n] && function(v) {
293
+ return new Promise(function(resolve, reject) {
294
+ v = o[n](v), settle(resolve, reject, v.done, v.value);
295
+ });
284
296
  };
285
297
  }
286
- async getResultStep(concurrent, stepId) {
287
- return await Promise.resolve({
288
- stepId,
289
- stepName: this.stepName,
290
- stepType: this.stepType,
291
- sleepFor: this.sleep,
292
- concurrent
293
- });
298
+ function settle(resolve, reject, d, v) {
299
+ Promise.resolve(v).then(function(v2) {
300
+ resolve({ value: v2, done: d });
301
+ }, reject);
294
302
  }
295
- };
296
- var LazySleepUntilStep = class extends BaseLazyStep {
297
- sleepUntil;
298
- stepType = "SleepUntil";
299
- allowUndefinedOut = true;
300
- constructor(stepName, sleepUntil) {
301
- super(stepName);
302
- this.sleepUntil = sleepUntil;
303
+ }
304
+ var ResultAsync = class _ResultAsync {
305
+ constructor(res) {
306
+ this._promise = res;
303
307
  }
304
- getPlanStep(concurrent, targetStep) {
305
- return {
306
- stepId: 0,
307
- stepName: this.stepName,
308
- stepType: this.stepType,
309
- sleepUntil: this.sleepUntil,
310
- concurrent,
311
- targetStep
312
- };
308
+ static fromSafePromise(promise) {
309
+ const newPromise = promise.then((value) => new Ok(value));
310
+ return new _ResultAsync(newPromise);
313
311
  }
314
- async getResultStep(concurrent, stepId) {
315
- return await Promise.resolve({
316
- stepId,
317
- stepName: this.stepName,
318
- stepType: this.stepType,
319
- sleepUntil: this.sleepUntil,
320
- concurrent
321
- });
312
+ static fromPromise(promise, errorFn) {
313
+ const newPromise = promise.then((value) => new Ok(value)).catch((e) => new Err(errorFn(e)));
314
+ return new _ResultAsync(newPromise);
322
315
  }
323
- safeParseOut() {
324
- return void 0;
316
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
317
+ static fromThrowable(fn, errorFn) {
318
+ return (...args) => {
319
+ return new _ResultAsync((() => __awaiter(this, void 0, void 0, function* () {
320
+ try {
321
+ return new Ok(yield fn(...args));
322
+ } catch (error) {
323
+ return new Err(errorFn ? errorFn(error) : error);
324
+ }
325
+ }))());
326
+ };
325
327
  }
326
- };
327
- var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
328
- url;
329
- method;
330
- body;
331
- headers;
332
- retries;
333
- timeout;
334
- flowControl;
335
- stepType = "Call";
336
- allowUndefinedOut = false;
337
- constructor(stepName, url, method, body, headers, retries, timeout, flowControl) {
338
- super(stepName);
339
- this.url = url;
340
- this.method = method;
341
- this.body = body;
342
- this.headers = headers;
343
- this.retries = retries;
344
- this.timeout = timeout;
345
- this.flowControl = flowControl;
346
- }
347
- getPlanStep(concurrent, targetStep) {
348
- return {
349
- stepId: 0,
350
- stepName: this.stepName,
351
- stepType: this.stepType,
352
- concurrent,
353
- targetStep
354
- };
328
+ static combine(asyncResultList) {
329
+ return combineResultAsyncList(asyncResultList);
355
330
  }
356
- async getResultStep(concurrent, stepId) {
357
- return await Promise.resolve({
358
- stepId,
359
- stepName: this.stepName,
360
- stepType: this.stepType,
361
- concurrent,
362
- callUrl: this.url,
363
- callMethod: this.method,
364
- callBody: this.body,
365
- callHeaders: this.headers
366
- });
331
+ static combineWithAllErrors(asyncResultList) {
332
+ return combineResultAsyncListWithAllErrors(asyncResultList);
367
333
  }
368
- safeParseOut(out) {
369
- const { header, status, body } = JSON.parse(out);
370
- const responseHeaders = new Headers(header);
371
- if (_LazyCallStep.isText(responseHeaders.get("content-type"))) {
372
- const bytes = new Uint8Array(out.length);
373
- for (let i = 0; i < out.length; i++) {
374
- bytes[i] = out.charCodeAt(i);
334
+ map(f) {
335
+ return new _ResultAsync(this._promise.then((res) => __awaiter(this, void 0, void 0, function* () {
336
+ if (res.isErr()) {
337
+ return new Err(res.error);
375
338
  }
376
- const processedResult = new TextDecoder().decode(bytes);
377
- const newBody = JSON.parse(processedResult).body;
378
- return {
379
- status,
380
- header,
381
- body: BaseLazyStep.tryParsing(newBody)
382
- };
383
- } else {
384
- return { header, status, body };
385
- }
386
- }
387
- static applicationHeaders = /* @__PURE__ */ new Set([
388
- "application/json",
389
- "application/xml",
390
- "application/javascript",
391
- "application/x-www-form-urlencoded",
392
- "application/xhtml+xml",
393
- "application/ld+json",
394
- "application/rss+xml",
395
- "application/atom+xml"
396
- ]);
397
- static isText = (contentTypeHeader) => {
398
- if (!contentTypeHeader) {
399
- return false;
400
- }
401
- if (_LazyCallStep.applicationHeaders.has(contentTypeHeader)) {
402
- return true;
403
- }
404
- if (contentTypeHeader.startsWith("text/")) {
405
- return true;
406
- }
407
- return false;
408
- };
409
- };
410
- var LazyWaitForEventStep = class extends BaseLazyStep {
411
- eventId;
412
- timeout;
413
- stepType = "Wait";
414
- allowUndefinedOut = false;
415
- constructor(stepName, eventId, timeout) {
416
- super(stepName);
417
- this.eventId = eventId;
418
- this.timeout = timeout;
339
+ return new Ok(yield f(res.value));
340
+ })));
419
341
  }
420
- getPlanStep(concurrent, targetStep) {
421
- return {
422
- stepId: 0,
423
- stepName: this.stepName,
424
- stepType: this.stepType,
425
- waitEventId: this.eventId,
426
- timeout: this.timeout,
427
- concurrent,
428
- targetStep
429
- };
342
+ andThrough(f) {
343
+ return new _ResultAsync(this._promise.then((res) => __awaiter(this, void 0, void 0, function* () {
344
+ if (res.isErr()) {
345
+ return new Err(res.error);
346
+ }
347
+ const newRes = yield f(res.value);
348
+ if (newRes.isErr()) {
349
+ return new Err(newRes.error);
350
+ }
351
+ return new Ok(res.value);
352
+ })));
430
353
  }
431
- async getResultStep(concurrent, stepId) {
432
- return await Promise.resolve({
433
- stepId,
434
- stepName: this.stepName,
435
- stepType: this.stepType,
436
- waitEventId: this.eventId,
437
- timeout: this.timeout,
438
- concurrent
439
- });
354
+ andTee(f) {
355
+ return new _ResultAsync(this._promise.then((res) => __awaiter(this, void 0, void 0, function* () {
356
+ if (res.isErr()) {
357
+ return new Err(res.error);
358
+ }
359
+ try {
360
+ yield f(res.value);
361
+ } catch (e) {
362
+ }
363
+ return new Ok(res.value);
364
+ })));
440
365
  }
441
- safeParseOut(out) {
442
- const result = JSON.parse(out);
443
- return {
444
- ...result,
445
- eventData: BaseLazyStep.tryParsing(result.eventData)
446
- };
366
+ mapErr(f) {
367
+ return new _ResultAsync(this._promise.then((res) => __awaiter(this, void 0, void 0, function* () {
368
+ if (res.isOk()) {
369
+ return new Ok(res.value);
370
+ }
371
+ return new Err(yield f(res.error));
372
+ })));
447
373
  }
448
- };
449
- var LazyNotifyStep = class extends LazyFunctionStep {
450
- stepType = "Notify";
451
- constructor(stepName, eventId, eventData, requester) {
452
- super(stepName, async () => {
453
- const notifyResponse = await makeNotifyRequest(requester, eventId, eventData);
454
- return {
455
- eventId,
456
- eventData,
457
- notifyResponse
458
- };
459
- });
374
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
375
+ andThen(f) {
376
+ return new _ResultAsync(this._promise.then((res) => {
377
+ if (res.isErr()) {
378
+ return new Err(res.error);
379
+ }
380
+ const newValue = f(res.value);
381
+ return newValue instanceof _ResultAsync ? newValue._promise : newValue;
382
+ }));
460
383
  }
461
- safeParseOut(out) {
462
- const result = JSON.parse(out);
463
- return {
464
- ...result,
465
- eventData: BaseLazyStep.tryParsing(result.eventData)
466
- };
384
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
385
+ orElse(f) {
386
+ return new _ResultAsync(this._promise.then((res) => __awaiter(this, void 0, void 0, function* () {
387
+ if (res.isErr()) {
388
+ return f(res.error);
389
+ }
390
+ return new Ok(res.value);
391
+ })));
467
392
  }
468
- };
469
- var LazyInvokeStep = class extends BaseLazyStep {
470
- stepType = "Invoke";
471
- params;
472
- allowUndefinedOut = false;
473
- constructor(stepName, {
474
- workflow,
475
- body,
476
- headers = {},
477
- workflowRunId,
478
- retries,
479
- flowControl
480
- }) {
481
- super(stepName);
482
- this.params = {
483
- workflow,
484
- body,
485
- headers,
486
- workflowRunId: getWorkflowRunId(workflowRunId),
487
- retries,
488
- flowControl
489
- };
393
+ match(ok2, _err) {
394
+ return this._promise.then((res) => res.match(ok2, _err));
490
395
  }
491
- getPlanStep(concurrent, targetStep) {
492
- return {
493
- stepId: 0,
494
- stepName: this.stepName,
495
- stepType: this.stepType,
496
- concurrent,
497
- targetStep
498
- };
396
+ unwrapOr(t) {
397
+ return this._promise.then((res) => res.unwrapOr(t));
499
398
  }
500
399
  /**
501
- * won't be used as it's the server who will add the result step
502
- * in Invoke step.
400
+ * Emulates Rust's `?` operator in `safeTry`'s body. See also `safeTry`.
503
401
  */
504
- getResultStep(concurrent, stepId) {
505
- return Promise.resolve({
506
- stepId,
507
- stepName: this.stepName,
508
- stepType: this.stepType,
509
- concurrent
402
+ safeUnwrap() {
403
+ return __asyncGenerator(this, arguments, function* safeUnwrap_1() {
404
+ return yield __await(yield __await(yield* __asyncDelegator(__asyncValues(yield __await(this._promise.then((res) => res.safeUnwrap()))))));
510
405
  });
511
406
  }
512
- safeParseOut(out) {
513
- const result = JSON.parse(out);
514
- return {
515
- ...result,
516
- body: BaseLazyStep.tryParsing(result.body)
517
- };
518
- }
519
- };
520
-
521
- // node_modules/neverthrow/dist/index.es.js
522
- var defaultErrorConfig = {
523
- withStackTrace: false
524
- };
525
- var createNeverThrowError = (message, result, config = defaultErrorConfig) => {
526
- const data = result.isOk() ? { type: "Ok", value: result.value } : { type: "Err", value: result.error };
527
- const maybeStack = config.withStackTrace ? new Error().stack : void 0;
528
- return {
529
- data,
530
- message,
531
- stack: maybeStack
532
- };
533
- };
534
- function __awaiter(thisArg, _arguments, P, generator) {
535
- function adopt(value) {
536
- return value instanceof P ? value : new P(function(resolve) {
537
- resolve(value);
538
- });
539
- }
540
- return new (P || (P = Promise))(function(resolve, reject) {
541
- function fulfilled(value) {
542
- try {
543
- step(generator.next(value));
544
- } catch (e) {
545
- reject(e);
546
- }
547
- }
548
- function rejected(value) {
549
- try {
550
- step(generator["throw"](value));
551
- } catch (e) {
552
- reject(e);
553
- }
554
- }
555
- function step(result) {
556
- result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
557
- }
558
- step((generator = generator.apply(thisArg, [])).next());
559
- });
560
- }
561
- function __values(o) {
562
- var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
563
- if (m) return m.call(o);
564
- if (o && typeof o.length === "number") return {
565
- next: function() {
566
- if (o && i >= o.length) o = void 0;
567
- return { value: o && o[i++], done: !o };
568
- }
569
- };
570
- throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
571
- }
572
- function __await(v) {
573
- return this instanceof __await ? (this.v = v, this) : new __await(v);
574
- }
575
- function __asyncGenerator(thisArg, _arguments, generator) {
576
- if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
577
- var g = generator.apply(thisArg, _arguments || []), i, q = [];
578
- return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function() {
579
- return this;
580
- }, i;
581
- function verb(n) {
582
- if (g[n]) i[n] = function(v) {
583
- return new Promise(function(a, b) {
584
- q.push([n, v, a, b]) > 1 || resume(n, v);
585
- });
586
- };
587
- }
588
- function resume(n, v) {
589
- try {
590
- step(g[n](v));
591
- } catch (e) {
592
- settle(q[0][3], e);
593
- }
594
- }
595
- function step(r) {
596
- r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r);
597
- }
598
- function fulfill(value) {
599
- resume("next", value);
600
- }
601
- function reject(value) {
602
- resume("throw", value);
603
- }
604
- function settle(f, v) {
605
- if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]);
606
- }
607
- }
608
- function __asyncDelegator(o) {
609
- var i, p;
610
- return i = {}, verb("next"), verb("throw", function(e) {
611
- throw e;
612
- }), verb("return"), i[Symbol.iterator] = function() {
613
- return this;
614
- }, i;
615
- function verb(n, f) {
616
- i[n] = o[n] ? function(v) {
617
- return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v;
618
- } : f;
619
- }
620
- }
621
- function __asyncValues(o) {
622
- if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
623
- var m = o[Symbol.asyncIterator], i;
624
- return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function() {
625
- return this;
626
- }, i);
627
- function verb(n) {
628
- i[n] = o[n] && function(v) {
629
- return new Promise(function(resolve, reject) {
630
- v = o[n](v), settle(resolve, reject, v.done, v.value);
631
- });
632
- };
633
- }
634
- function settle(resolve, reject, d, v) {
635
- Promise.resolve(v).then(function(v2) {
636
- resolve({ value: v2, done: d });
637
- }, reject);
638
- }
639
- }
640
- var ResultAsync = class _ResultAsync {
641
- constructor(res) {
642
- this._promise = res;
643
- }
644
- static fromSafePromise(promise) {
645
- const newPromise = promise.then((value) => new Ok(value));
646
- return new _ResultAsync(newPromise);
647
- }
648
- static fromPromise(promise, errorFn) {
649
- const newPromise = promise.then((value) => new Ok(value)).catch((e) => new Err(errorFn(e)));
650
- return new _ResultAsync(newPromise);
651
- }
652
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
653
- static fromThrowable(fn, errorFn) {
654
- return (...args) => {
655
- return new _ResultAsync((() => __awaiter(this, void 0, void 0, function* () {
656
- try {
657
- return new Ok(yield fn(...args));
658
- } catch (error) {
659
- return new Err(errorFn ? errorFn(error) : error);
660
- }
661
- }))());
662
- };
663
- }
664
- static combine(asyncResultList) {
665
- return combineResultAsyncList(asyncResultList);
666
- }
667
- static combineWithAllErrors(asyncResultList) {
668
- return combineResultAsyncListWithAllErrors(asyncResultList);
669
- }
670
- map(f) {
671
- return new _ResultAsync(this._promise.then((res) => __awaiter(this, void 0, void 0, function* () {
672
- if (res.isErr()) {
673
- return new Err(res.error);
674
- }
675
- return new Ok(yield f(res.value));
676
- })));
677
- }
678
- andThrough(f) {
679
- return new _ResultAsync(this._promise.then((res) => __awaiter(this, void 0, void 0, function* () {
680
- if (res.isErr()) {
681
- return new Err(res.error);
682
- }
683
- const newRes = yield f(res.value);
684
- if (newRes.isErr()) {
685
- return new Err(newRes.error);
686
- }
687
- return new Ok(res.value);
688
- })));
689
- }
690
- andTee(f) {
691
- return new _ResultAsync(this._promise.then((res) => __awaiter(this, void 0, void 0, function* () {
692
- if (res.isErr()) {
693
- return new Err(res.error);
694
- }
695
- try {
696
- yield f(res.value);
697
- } catch (e) {
698
- }
699
- return new Ok(res.value);
700
- })));
701
- }
702
- mapErr(f) {
703
- return new _ResultAsync(this._promise.then((res) => __awaiter(this, void 0, void 0, function* () {
704
- if (res.isOk()) {
705
- return new Ok(res.value);
706
- }
707
- return new Err(yield f(res.error));
708
- })));
709
- }
710
- // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
711
- andThen(f) {
712
- return new _ResultAsync(this._promise.then((res) => {
713
- if (res.isErr()) {
714
- return new Err(res.error);
715
- }
716
- const newValue = f(res.value);
717
- return newValue instanceof _ResultAsync ? newValue._promise : newValue;
718
- }));
719
- }
720
- // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
721
- orElse(f) {
722
- return new _ResultAsync(this._promise.then((res) => __awaiter(this, void 0, void 0, function* () {
723
- if (res.isErr()) {
724
- return f(res.error);
725
- }
726
- return new Ok(res.value);
727
- })));
728
- }
729
- match(ok2, _err) {
730
- return this._promise.then((res) => res.match(ok2, _err));
731
- }
732
- unwrapOr(t) {
733
- return this._promise.then((res) => res.unwrapOr(t));
734
- }
735
- /**
736
- * Emulates Rust's `?` operator in `safeTry`'s body. See also `safeTry`.
737
- */
738
- safeUnwrap() {
739
- return __asyncGenerator(this, arguments, function* safeUnwrap_1() {
740
- return yield __await(yield __await(yield* __asyncDelegator(__asyncValues(yield __await(this._promise.then((res) => res.safeUnwrap()))))));
741
- });
742
- }
743
- // Makes ResultAsync implement PromiseLike<Result>
744
- then(successCallback, failureCallback) {
745
- return this._promise.then(successCallback, failureCallback);
407
+ // Makes ResultAsync implement PromiseLike<Result>
408
+ then(successCallback, failureCallback) {
409
+ return this._promise.then(successCallback, failureCallback);
746
410
  }
747
411
  };
748
412
  var errAsync = (err2) => new ResultAsync(Promise.resolve(new Err(err2)));
@@ -952,18 +616,22 @@ var triggerFirstInvocation = async ({
952
616
  useJSONContent,
953
617
  telemetry,
954
618
  debug,
955
- invokeCount
619
+ invokeCount,
620
+ delay
956
621
  }) => {
957
622
  const { headers } = getHeaders({
958
623
  initHeaderValue: "true",
959
- workflowRunId: workflowContext.workflowRunId,
960
- workflowUrl: workflowContext.url,
961
- userHeaders: workflowContext.headers,
962
- failureUrl: workflowContext.failureUrl,
963
- retries: workflowContext.retries,
964
- telemetry,
965
- invokeCount,
966
- flowControl: workflowContext.flowControl
624
+ workflowConfig: {
625
+ workflowRunId: workflowContext.workflowRunId,
626
+ workflowUrl: workflowContext.url,
627
+ failureUrl: workflowContext.failureUrl,
628
+ retries: workflowContext.retries,
629
+ telemetry,
630
+ flowControl: workflowContext.flowControl,
631
+ useJSONContent: useJSONContent ?? false
632
+ },
633
+ invokeCount: invokeCount ?? 0,
634
+ userHeaders: workflowContext.headers
967
635
  });
968
636
  if (workflowContext.headers.get("content-type")) {
969
637
  headers["content-type"] = workflowContext.headers.get("content-type");
@@ -977,7 +645,8 @@ var triggerFirstInvocation = async ({
977
645
  headers,
978
646
  method: "POST",
979
647
  body,
980
- url: workflowContext.url
648
+ url: workflowContext.url,
649
+ delay
981
650
  });
982
651
  if (result.deduplicated) {
983
652
  await debug?.log("WARN", "SUBMIT_FIRST_INVOCATION", {
@@ -1133,14 +802,16 @@ ${atob(callbackMessage.body ?? "")}`
1133
802
  const userHeaders = recreateUserHeaders(request.headers);
1134
803
  const { headers: requestHeaders } = getHeaders({
1135
804
  initHeaderValue: "false",
1136
- workflowRunId,
1137
- workflowUrl,
805
+ workflowConfig: {
806
+ workflowRunId,
807
+ workflowUrl,
808
+ failureUrl,
809
+ retries,
810
+ telemetry,
811
+ flowControl
812
+ },
1138
813
  userHeaders,
1139
- failureUrl,
1140
- retries,
1141
- telemetry,
1142
- invokeCount: Number(invokeCount),
1143
- flowControl
814
+ invokeCount: Number(invokeCount)
1144
815
  });
1145
816
  const callResponse = {
1146
817
  status: callbackMessage.status,
@@ -1186,268 +857,899 @@ var getTelemetryHeaders = (telemetry) => {
1186
857
  [TELEMETRY_HEADER_RUNTIME]: telemetry.runtime ?? "unknown"
1187
858
  };
1188
859
  };
1189
- var getHeaders = ({
1190
- initHeaderValue,
1191
- workflowRunId,
1192
- workflowUrl,
1193
- userHeaders,
1194
- failureUrl,
1195
- retries,
1196
- step,
1197
- callRetries,
1198
- callTimeout,
1199
- telemetry,
1200
- invokeCount,
1201
- flowControl,
1202
- callFlowControl
1203
- }) => {
1204
- const callHeaders = new Headers(step?.callHeaders);
1205
- const contentType = (callHeaders.get("content-type") ? callHeaders.get("content-type") : userHeaders?.get("Content-Type") ? userHeaders.get("Content-Type") : void 0) ?? DEFAULT_CONTENT_TYPE;
1206
- const baseHeaders = {
1207
- [WORKFLOW_INIT_HEADER]: initHeaderValue,
1208
- [WORKFLOW_ID_HEADER]: workflowRunId,
1209
- [WORKFLOW_URL_HEADER]: workflowUrl,
1210
- [WORKFLOW_FEATURE_HEADER]: "LazyFetch,InitialBody",
1211
- [WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION,
1212
- "content-type": contentType,
1213
- ...telemetry ? getTelemetryHeaders(telemetry) : {}
1214
- };
1215
- if (invokeCount !== void 0 && !step?.callUrl) {
1216
- baseHeaders[`Upstash-Forward-${WORKFLOW_INVOKE_COUNT_HEADER}`] = invokeCount.toString();
1217
- }
1218
- if (!step?.callUrl) {
1219
- baseHeaders[`Upstash-Forward-${WORKFLOW_PROTOCOL_VERSION_HEADER}`] = WORKFLOW_PROTOCOL_VERSION;
1220
- }
1221
- if (callTimeout) {
1222
- baseHeaders[`Upstash-Timeout`] = callTimeout.toString();
1223
- }
1224
- if (failureUrl) {
1225
- baseHeaders[`Upstash-Failure-Callback-Forward-${WORKFLOW_FAILURE_HEADER}`] = "true";
1226
- baseHeaders[`Upstash-Failure-Callback-Forward-Upstash-Workflow-Failure-Callback`] = "true";
1227
- baseHeaders["Upstash-Failure-Callback-Workflow-Runid"] = workflowRunId;
1228
- baseHeaders["Upstash-Failure-Callback-Workflow-Init"] = "false";
1229
- baseHeaders["Upstash-Failure-Callback-Workflow-Url"] = workflowUrl;
1230
- baseHeaders["Upstash-Failure-Callback-Workflow-Calltype"] = "failureCall";
1231
- if (retries !== void 0) {
1232
- baseHeaders["Upstash-Failure-Callback-Retries"] = retries.toString();
1233
- }
1234
- if (flowControl) {
1235
- const { flowControlKey, flowControlValue } = prepareFlowControl(flowControl);
1236
- baseHeaders["Upstash-Failure-Callback-Flow-Control-Key"] = flowControlKey;
1237
- baseHeaders["Upstash-Failure-Callback-Flow-Control-Value"] = flowControlValue;
1238
- }
1239
- if (!step?.callUrl) {
1240
- baseHeaders["Upstash-Failure-Callback"] = failureUrl;
1241
- }
1242
- }
1243
- if (step?.callUrl) {
1244
- baseHeaders["Upstash-Retries"] = callRetries?.toString() ?? "0";
1245
- baseHeaders[WORKFLOW_FEATURE_HEADER] = "WF_NoDelete,InitialBody";
1246
- if (retries !== void 0) {
1247
- baseHeaders["Upstash-Callback-Retries"] = retries.toString();
1248
- baseHeaders["Upstash-Failure-Callback-Retries"] = retries.toString();
1249
- }
1250
- if (callFlowControl) {
1251
- const { flowControlKey, flowControlValue } = prepareFlowControl(callFlowControl);
1252
- baseHeaders["Upstash-Flow-Control-Key"] = flowControlKey;
1253
- baseHeaders["Upstash-Flow-Control-Value"] = flowControlValue;
1254
- }
1255
- if (flowControl) {
1256
- const { flowControlKey, flowControlValue } = prepareFlowControl(flowControl);
1257
- baseHeaders["Upstash-Callback-Flow-Control-Key"] = flowControlKey;
1258
- baseHeaders["Upstash-Callback-Flow-Control-Value"] = flowControlValue;
860
+ var verifyRequest = async (body, signature, verifier) => {
861
+ if (!verifier) {
862
+ return;
863
+ }
864
+ try {
865
+ if (!signature) {
866
+ throw new Error("`Upstash-Signature` header is not passed.");
867
+ }
868
+ const isValid = await verifier.verify({
869
+ body,
870
+ signature
871
+ });
872
+ if (!isValid) {
873
+ throw new Error("Signature in `Upstash-Signature` header is not valid");
874
+ }
875
+ } catch (error) {
876
+ throw new WorkflowError(
877
+ `Failed to verify that the Workflow request comes from QStash: ${error}
878
+
879
+ If signature is missing, trigger the workflow endpoint by publishing your request to QStash instead of calling it directly.
880
+
881
+ If you want to disable QStash Verification, you should clear env variables QSTASH_CURRENT_SIGNING_KEY and QSTASH_NEXT_SIGNING_KEY`
882
+ );
883
+ }
884
+ };
885
+
886
+ // src/context/steps.ts
887
+ var BaseLazyStep = class _BaseLazyStep {
888
+ stepName;
889
+ constructor(stepName) {
890
+ if (!stepName) {
891
+ throw new WorkflowError(
892
+ "A workflow step name cannot be undefined or an empty string. Please provide a name for your workflow step."
893
+ );
894
+ }
895
+ if (typeof stepName !== "string") {
896
+ console.warn(
897
+ "Workflow Warning: A workflow step name must be a string. In a future release, this will throw an error."
898
+ );
899
+ }
900
+ this.stepName = stepName;
901
+ }
902
+ /**
903
+ * parse the out field of a step result.
904
+ *
905
+ * will be called when returning the steps to the context from auto executor
906
+ *
907
+ * @param out field of the step
908
+ * @returns parsed out field
909
+ */
910
+ parseOut(out) {
911
+ if (out === void 0) {
912
+ if (this.allowUndefinedOut) {
913
+ return void 0;
914
+ } else {
915
+ throw new WorkflowError(
916
+ `Error while parsing output of ${this.stepType} step. Expected a string, but got: undefined`
917
+ );
918
+ }
919
+ }
920
+ if (typeof out === "object") {
921
+ if (this.stepType !== "Wait") {
922
+ console.warn(
923
+ `Error while parsing ${this.stepType} step output. Expected a string, but got object. Please reach out to Upstash Support.`
924
+ );
925
+ return out;
926
+ }
927
+ return {
928
+ ...out,
929
+ eventData: _BaseLazyStep.tryParsing(out.eventData)
930
+ };
931
+ }
932
+ if (typeof out !== "string") {
933
+ throw new WorkflowError(
934
+ `Error while parsing output of ${this.stepType} step. Expected a string or undefined, but got: ${typeof out}`
935
+ );
936
+ }
937
+ return this.safeParseOut(out);
938
+ }
939
+ safeParseOut(out) {
940
+ return _BaseLazyStep.tryParsing(out);
941
+ }
942
+ static tryParsing(stepOut) {
943
+ try {
944
+ return JSON.parse(stepOut);
945
+ } catch {
946
+ return stepOut;
947
+ }
948
+ }
949
+ getBody({ step }) {
950
+ step.out = JSON.stringify(step.out);
951
+ return JSON.stringify(step);
952
+ }
953
+ getHeaders({ context, telemetry, invokeCount, step }) {
954
+ return getHeaders({
955
+ initHeaderValue: "false",
956
+ workflowConfig: {
957
+ workflowRunId: context.workflowRunId,
958
+ workflowUrl: context.url,
959
+ failureUrl: context.failureUrl,
960
+ retries: context.retries,
961
+ useJSONContent: false,
962
+ telemetry,
963
+ flowControl: context.flowControl
964
+ },
965
+ userHeaders: context.headers,
966
+ invokeCount,
967
+ stepInfo: {
968
+ step,
969
+ lazyStep: this
970
+ }
971
+ });
972
+ }
973
+ async submitStep({ context, body, headers }) {
974
+ return await context.qstashClient.batch([
975
+ {
976
+ body,
977
+ headers,
978
+ method: "POST",
979
+ url: context.url
980
+ }
981
+ ]);
982
+ }
983
+ };
984
+ var LazyFunctionStep = class extends BaseLazyStep {
985
+ stepFunction;
986
+ stepType = "Run";
987
+ allowUndefinedOut = true;
988
+ constructor(stepName, stepFunction) {
989
+ super(stepName);
990
+ this.stepFunction = stepFunction;
991
+ }
992
+ getPlanStep(concurrent, targetStep) {
993
+ return {
994
+ stepId: 0,
995
+ stepName: this.stepName,
996
+ stepType: this.stepType,
997
+ concurrent,
998
+ targetStep
999
+ };
1000
+ }
1001
+ async getResultStep(concurrent, stepId) {
1002
+ let result = this.stepFunction();
1003
+ if (result instanceof Promise) {
1004
+ result = await result;
1005
+ }
1006
+ return {
1007
+ stepId,
1008
+ stepName: this.stepName,
1009
+ stepType: this.stepType,
1010
+ out: result,
1011
+ concurrent
1012
+ };
1013
+ }
1014
+ };
1015
+ var LazySleepStep = class extends BaseLazyStep {
1016
+ sleep;
1017
+ stepType = "SleepFor";
1018
+ allowUndefinedOut = true;
1019
+ constructor(stepName, sleep) {
1020
+ super(stepName);
1021
+ this.sleep = sleep;
1022
+ }
1023
+ getPlanStep(concurrent, targetStep) {
1024
+ return {
1025
+ stepId: 0,
1026
+ stepName: this.stepName,
1027
+ stepType: this.stepType,
1028
+ sleepFor: this.sleep,
1029
+ concurrent,
1030
+ targetStep
1031
+ };
1032
+ }
1033
+ async getResultStep(concurrent, stepId) {
1034
+ return await Promise.resolve({
1035
+ stepId,
1036
+ stepName: this.stepName,
1037
+ stepType: this.stepType,
1038
+ sleepFor: this.sleep,
1039
+ concurrent
1040
+ });
1041
+ }
1042
+ async submitStep({ context, body, headers, isParallel }) {
1043
+ return await context.qstashClient.batch([
1044
+ {
1045
+ body,
1046
+ headers,
1047
+ method: "POST",
1048
+ url: context.url,
1049
+ delay: isParallel ? void 0 : this.sleep
1050
+ }
1051
+ ]);
1052
+ }
1053
+ };
1054
+ var LazySleepUntilStep = class extends BaseLazyStep {
1055
+ sleepUntil;
1056
+ stepType = "SleepUntil";
1057
+ allowUndefinedOut = true;
1058
+ constructor(stepName, sleepUntil) {
1059
+ super(stepName);
1060
+ this.sleepUntil = sleepUntil;
1061
+ }
1062
+ getPlanStep(concurrent, targetStep) {
1063
+ return {
1064
+ stepId: 0,
1065
+ stepName: this.stepName,
1066
+ stepType: this.stepType,
1067
+ sleepUntil: this.sleepUntil,
1068
+ concurrent,
1069
+ targetStep
1070
+ };
1071
+ }
1072
+ async getResultStep(concurrent, stepId) {
1073
+ return await Promise.resolve({
1074
+ stepId,
1075
+ stepName: this.stepName,
1076
+ stepType: this.stepType,
1077
+ sleepUntil: this.sleepUntil,
1078
+ concurrent
1079
+ });
1080
+ }
1081
+ safeParseOut() {
1082
+ return void 0;
1083
+ }
1084
+ async submitStep({ context, body, headers, isParallel }) {
1085
+ return await context.qstashClient.batch([
1086
+ {
1087
+ body,
1088
+ headers,
1089
+ method: "POST",
1090
+ url: context.url,
1091
+ notBefore: isParallel ? void 0 : this.sleepUntil
1092
+ }
1093
+ ]);
1094
+ }
1095
+ };
1096
+ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
1097
+ url;
1098
+ method;
1099
+ body;
1100
+ headers;
1101
+ retries;
1102
+ timeout;
1103
+ flowControl;
1104
+ stepType = "Call";
1105
+ allowUndefinedOut = false;
1106
+ constructor(stepName, url, method, body, headers, retries, timeout, flowControl) {
1107
+ super(stepName);
1108
+ this.url = url;
1109
+ this.method = method;
1110
+ this.body = body;
1111
+ this.headers = headers;
1112
+ this.retries = retries;
1113
+ this.timeout = timeout;
1114
+ this.flowControl = flowControl;
1115
+ }
1116
+ getPlanStep(concurrent, targetStep) {
1117
+ return {
1118
+ stepId: 0,
1119
+ stepName: this.stepName,
1120
+ stepType: this.stepType,
1121
+ concurrent,
1122
+ targetStep
1123
+ };
1124
+ }
1125
+ async getResultStep(concurrent, stepId) {
1126
+ return await Promise.resolve({
1127
+ stepId,
1128
+ stepName: this.stepName,
1129
+ stepType: this.stepType,
1130
+ concurrent,
1131
+ callUrl: this.url,
1132
+ callMethod: this.method,
1133
+ callBody: this.body,
1134
+ callHeaders: this.headers
1135
+ });
1136
+ }
1137
+ safeParseOut(out) {
1138
+ const { header, status, body } = JSON.parse(out);
1139
+ const responseHeaders = new Headers(header);
1140
+ if (_LazyCallStep.isText(responseHeaders.get("content-type"))) {
1141
+ const bytes = new Uint8Array(out.length);
1142
+ for (let i = 0; i < out.length; i++) {
1143
+ bytes[i] = out.charCodeAt(i);
1144
+ }
1145
+ const processedResult = new TextDecoder().decode(bytes);
1146
+ const newBody = JSON.parse(processedResult).body;
1147
+ return {
1148
+ status,
1149
+ header,
1150
+ body: BaseLazyStep.tryParsing(newBody)
1151
+ };
1152
+ } else {
1153
+ return { header, status, body };
1154
+ }
1155
+ }
1156
+ static applicationHeaders = /* @__PURE__ */ new Set([
1157
+ "application/json",
1158
+ "application/xml",
1159
+ "application/javascript",
1160
+ "application/x-www-form-urlencoded",
1161
+ "application/xhtml+xml",
1162
+ "application/ld+json",
1163
+ "application/rss+xml",
1164
+ "application/atom+xml"
1165
+ ]);
1166
+ static isText = (contentTypeHeader) => {
1167
+ if (!contentTypeHeader) {
1168
+ return false;
1169
+ }
1170
+ if (_LazyCallStep.applicationHeaders.has(contentTypeHeader)) {
1171
+ return true;
1172
+ }
1173
+ if (contentTypeHeader.startsWith("text/")) {
1174
+ return true;
1175
+ }
1176
+ return false;
1177
+ };
1178
+ getBody({ step }) {
1179
+ if (!step.callUrl) {
1180
+ throw new WorkflowError("Incompatible step received in LazyCallStep.getBody");
1181
+ }
1182
+ return JSON.stringify(step.callBody);
1183
+ }
1184
+ getHeaders({ context, telemetry, invokeCount, step }) {
1185
+ const { headers, contentType } = super.getHeaders({ context, telemetry, invokeCount, step });
1186
+ headers["Upstash-Retries"] = this.retries.toString();
1187
+ headers[WORKFLOW_FEATURE_HEADER] = "WF_NoDelete,InitialBody";
1188
+ if (this.flowControl) {
1189
+ const { flowControlKey, flowControlValue } = prepareFlowControl(this.flowControl);
1190
+ headers["Upstash-Flow-Control-Key"] = flowControlKey;
1191
+ headers["Upstash-Flow-Control-Value"] = flowControlValue;
1192
+ }
1193
+ if (this.timeout) {
1194
+ headers["Upstash-Timeout"] = this.timeout.toString();
1195
+ }
1196
+ const forwardedHeaders = Object.fromEntries(
1197
+ Object.entries(this.headers).map(([header, value]) => [`Upstash-Forward-${header}`, value])
1198
+ );
1199
+ return {
1200
+ headers: {
1201
+ ...headers,
1202
+ ...forwardedHeaders,
1203
+ "Upstash-Callback": context.url,
1204
+ "Upstash-Callback-Workflow-RunId": context.workflowRunId,
1205
+ "Upstash-Callback-Workflow-CallType": "fromCallback",
1206
+ "Upstash-Callback-Workflow-Init": "false",
1207
+ "Upstash-Callback-Workflow-Url": context.url,
1208
+ "Upstash-Callback-Feature-Set": "LazyFetch,InitialBody",
1209
+ "Upstash-Callback-Forward-Upstash-Workflow-Callback": "true",
1210
+ "Upstash-Callback-Forward-Upstash-Workflow-StepId": step.stepId.toString(),
1211
+ "Upstash-Callback-Forward-Upstash-Workflow-StepName": this.stepName,
1212
+ "Upstash-Callback-Forward-Upstash-Workflow-StepType": this.stepType,
1213
+ "Upstash-Callback-Forward-Upstash-Workflow-Concurrent": step.concurrent.toString(),
1214
+ "Upstash-Callback-Forward-Upstash-Workflow-ContentType": contentType,
1215
+ "Upstash-Workflow-CallType": "toCallback"
1216
+ },
1217
+ contentType
1218
+ };
1219
+ }
1220
+ async submitStep({ context, headers }) {
1221
+ return await context.qstashClient.batch([
1222
+ {
1223
+ headers,
1224
+ body: JSON.stringify(this.body),
1225
+ method: this.method,
1226
+ url: this.url
1227
+ }
1228
+ ]);
1229
+ }
1230
+ };
1231
+ var LazyWaitForEventStep = class extends BaseLazyStep {
1232
+ eventId;
1233
+ timeout;
1234
+ stepType = "Wait";
1235
+ allowUndefinedOut = false;
1236
+ constructor(stepName, eventId, timeout) {
1237
+ super(stepName);
1238
+ this.eventId = eventId;
1239
+ this.timeout = timeout;
1240
+ }
1241
+ getPlanStep(concurrent, targetStep) {
1242
+ return {
1243
+ stepId: 0,
1244
+ stepName: this.stepName,
1245
+ stepType: this.stepType,
1246
+ waitEventId: this.eventId,
1247
+ timeout: this.timeout,
1248
+ concurrent,
1249
+ targetStep
1250
+ };
1251
+ }
1252
+ async getResultStep(concurrent, stepId) {
1253
+ return await Promise.resolve({
1254
+ stepId,
1255
+ stepName: this.stepName,
1256
+ stepType: this.stepType,
1257
+ waitEventId: this.eventId,
1258
+ timeout: this.timeout,
1259
+ concurrent
1260
+ });
1261
+ }
1262
+ safeParseOut(out) {
1263
+ const result = JSON.parse(out);
1264
+ return {
1265
+ ...result,
1266
+ eventData: BaseLazyStep.tryParsing(result.eventData)
1267
+ };
1268
+ }
1269
+ getHeaders({ context, telemetry, invokeCount, step }) {
1270
+ const headers = super.getHeaders({ context, telemetry, invokeCount, step });
1271
+ headers.headers["Upstash-Workflow-CallType"] = "step";
1272
+ return headers;
1273
+ }
1274
+ getBody({ context, step, headers, telemetry }) {
1275
+ if (!step.waitEventId) {
1276
+ throw new WorkflowError("Incompatible step received in LazyWaitForEventStep.getBody");
1277
+ }
1278
+ const timeoutHeaders = {
1279
+ // to include user headers:
1280
+ ...Object.fromEntries(Object.entries(headers).map(([header, value]) => [header, [value]])),
1281
+ // to include telemetry headers:
1282
+ ...telemetry ? Object.fromEntries(
1283
+ Object.entries(getTelemetryHeaders(telemetry)).map(([header, value]) => [
1284
+ header,
1285
+ [value]
1286
+ ])
1287
+ ) : {},
1288
+ // note: using WORKFLOW_ID_HEADER doesn't work, because Runid -> RunId:
1289
+ "Upstash-Workflow-Runid": [context.workflowRunId],
1290
+ [WORKFLOW_INIT_HEADER]: ["false"],
1291
+ [WORKFLOW_URL_HEADER]: [context.url],
1292
+ "Upstash-Workflow-CallType": ["step"]
1293
+ };
1294
+ const waitBody = {
1295
+ url: context.url,
1296
+ timeout: step.timeout,
1297
+ timeoutBody: void 0,
1298
+ timeoutUrl: context.url,
1299
+ timeoutHeaders,
1300
+ step: {
1301
+ stepId: step.stepId,
1302
+ stepType: "Wait",
1303
+ stepName: step.stepName,
1304
+ concurrent: step.concurrent,
1305
+ targetStep: step.targetStep
1306
+ }
1307
+ };
1308
+ return JSON.stringify(waitBody);
1309
+ }
1310
+ async submitStep({ context, body, headers }) {
1311
+ const result = await context.qstashClient.http.request({
1312
+ path: ["v2", "wait", this.eventId],
1313
+ body,
1314
+ headers,
1315
+ method: "POST",
1316
+ parseResponseAsJson: false
1317
+ });
1318
+ return [result];
1319
+ }
1320
+ };
1321
+ var LazyNotifyStep = class extends LazyFunctionStep {
1322
+ stepType = "Notify";
1323
+ constructor(stepName, eventId, eventData, requester) {
1324
+ super(stepName, async () => {
1325
+ const notifyResponse = await makeNotifyRequest(requester, eventId, eventData);
1326
+ return {
1327
+ eventId,
1328
+ eventData,
1329
+ notifyResponse
1330
+ };
1331
+ });
1332
+ }
1333
+ safeParseOut(out) {
1334
+ const result = JSON.parse(out);
1335
+ return {
1336
+ ...result,
1337
+ eventData: BaseLazyStep.tryParsing(result.eventData)
1338
+ };
1339
+ }
1340
+ };
1341
+ var LazyInvokeStep = class extends BaseLazyStep {
1342
+ stepType = "Invoke";
1343
+ params;
1344
+ allowUndefinedOut = false;
1345
+ /**
1346
+ * workflow id of the invoked workflow
1347
+ */
1348
+ workflowId;
1349
+ constructor(stepName, {
1350
+ workflow,
1351
+ body,
1352
+ headers = {},
1353
+ workflowRunId,
1354
+ retries,
1355
+ flowControl
1356
+ }) {
1357
+ super(stepName);
1358
+ this.params = {
1359
+ workflow,
1360
+ body,
1361
+ headers,
1362
+ workflowRunId: getWorkflowRunId(workflowRunId),
1363
+ retries,
1364
+ flowControl
1365
+ };
1366
+ const { workflowId } = workflow;
1367
+ if (!workflowId) {
1368
+ throw new WorkflowError("You can only invoke workflow which has a workflowId");
1369
+ }
1370
+ this.workflowId = workflowId;
1371
+ }
1372
+ getPlanStep(concurrent, targetStep) {
1373
+ return {
1374
+ stepId: 0,
1375
+ stepName: this.stepName,
1376
+ stepType: this.stepType,
1377
+ concurrent,
1378
+ targetStep
1379
+ };
1380
+ }
1381
+ /**
1382
+ * won't be used as it's the server who will add the result step
1383
+ * in Invoke step.
1384
+ */
1385
+ getResultStep(concurrent, stepId) {
1386
+ return Promise.resolve({
1387
+ stepId,
1388
+ stepName: this.stepName,
1389
+ stepType: this.stepType,
1390
+ concurrent
1391
+ });
1392
+ }
1393
+ safeParseOut(out) {
1394
+ const result = JSON.parse(out);
1395
+ return {
1396
+ ...result,
1397
+ body: BaseLazyStep.tryParsing(result.body)
1398
+ };
1399
+ }
1400
+ getBody({ context, step, telemetry, invokeCount }) {
1401
+ const { headers: invokerHeaders } = getHeaders({
1402
+ initHeaderValue: "false",
1403
+ workflowConfig: {
1404
+ workflowRunId: context.workflowRunId,
1405
+ workflowUrl: context.url,
1406
+ failureUrl: context.failureUrl,
1407
+ retries: context.retries,
1408
+ telemetry,
1409
+ flowControl: context.flowControl,
1410
+ useJSONContent: false
1411
+ },
1412
+ userHeaders: context.headers,
1413
+ invokeCount
1414
+ });
1415
+ invokerHeaders["Upstash-Workflow-Runid"] = context.workflowRunId;
1416
+ const request = {
1417
+ body: JSON.stringify(this.params.body),
1418
+ headers: Object.fromEntries(
1419
+ Object.entries(invokerHeaders).map((pairs) => [pairs[0], [pairs[1]]])
1420
+ ),
1421
+ workflowRunId: context.workflowRunId,
1422
+ workflowUrl: context.url,
1423
+ step
1424
+ };
1425
+ return JSON.stringify(request);
1426
+ }
1427
+ getHeaders({ context, telemetry, invokeCount }) {
1428
+ const {
1429
+ workflow,
1430
+ headers = {},
1431
+ workflowRunId = getWorkflowRunId(),
1432
+ retries,
1433
+ flowControl
1434
+ } = this.params;
1435
+ const newUrl = context.url.replace(/[^/]+$/, this.workflowId);
1436
+ const {
1437
+ retries: workflowRetries,
1438
+ failureFunction,
1439
+ failureUrl,
1440
+ useJSONContent,
1441
+ flowControl: workflowFlowControl
1442
+ } = workflow.options;
1443
+ const { headers: triggerHeaders, contentType } = getHeaders({
1444
+ initHeaderValue: "true",
1445
+ workflowConfig: {
1446
+ workflowRunId,
1447
+ workflowUrl: newUrl,
1448
+ retries: retries ?? workflowRetries,
1449
+ telemetry,
1450
+ failureUrl: failureFunction ? newUrl : failureUrl,
1451
+ flowControl: flowControl ?? workflowFlowControl,
1452
+ useJSONContent: useJSONContent ?? false
1453
+ },
1454
+ invokeCount: invokeCount + 1,
1455
+ userHeaders: new Headers(headers)
1456
+ });
1457
+ triggerHeaders["Upstash-Workflow-Invoke"] = "true";
1458
+ return { headers: triggerHeaders, contentType };
1459
+ }
1460
+ async submitStep({ context, body, headers }) {
1461
+ const newUrl = context.url.replace(/[^/]+$/, this.workflowId);
1462
+ const result = await context.qstashClient.publish({
1463
+ headers,
1464
+ method: "POST",
1465
+ body,
1466
+ url: newUrl
1467
+ });
1468
+ return [result];
1469
+ }
1470
+ };
1471
+
1472
+ // src/agents/constants.ts
1473
+ var AGENT_NAME_HEADER = "upstash-agent-name";
1474
+ var MANAGER_AGENT_PROMPT = `You are an agent orchestrating other AI Agents.
1475
+
1476
+ These other agents have tools available to them.
1477
+
1478
+ Given a prompt, utilize these agents to address requests.
1479
+
1480
+ Don't always call all the agents provided to you at the same time. You can call one and use it's response to call another.
1481
+
1482
+ Avoid calling the same agent twice in one turn. Instead, prefer to call it once but provide everything
1483
+ you need from that agent.
1484
+ `;
1485
+
1486
+ // src/qstash/headers.ts
1487
+ var WorkflowHeaders = class {
1488
+ userHeaders;
1489
+ workflowConfig;
1490
+ invokeCount;
1491
+ initHeaderValue;
1492
+ stepInfo;
1493
+ headers;
1494
+ constructor({
1495
+ userHeaders,
1496
+ workflowConfig,
1497
+ invokeCount,
1498
+ initHeaderValue,
1499
+ stepInfo
1500
+ }) {
1501
+ this.userHeaders = userHeaders;
1502
+ this.workflowConfig = workflowConfig;
1503
+ this.invokeCount = invokeCount;
1504
+ this.initHeaderValue = initHeaderValue;
1505
+ this.stepInfo = stepInfo;
1506
+ this.headers = {
1507
+ rawHeaders: {},
1508
+ workflowHeaders: {},
1509
+ failureHeaders: {}
1510
+ };
1511
+ }
1512
+ getHeaders() {
1513
+ this.addBaseHeaders();
1514
+ this.addRetries();
1515
+ this.addFlowControl();
1516
+ this.addUserHeaders();
1517
+ this.addInvokeCount();
1518
+ this.addFailureUrl();
1519
+ const contentType = this.addContentType();
1520
+ return this.prefixHeaders(contentType);
1521
+ }
1522
+ addBaseHeaders() {
1523
+ this.headers.rawHeaders = {
1524
+ ...this.headers.rawHeaders,
1525
+ [WORKFLOW_INIT_HEADER]: this.initHeaderValue,
1526
+ [WORKFLOW_ID_HEADER]: this.workflowConfig.workflowRunId,
1527
+ [WORKFLOW_URL_HEADER]: this.workflowConfig.workflowUrl,
1528
+ [WORKFLOW_FEATURE_HEADER]: "LazyFetch,InitialBody",
1529
+ [WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION,
1530
+ ...this.workflowConfig.telemetry ? getTelemetryHeaders(this.workflowConfig.telemetry) : {},
1531
+ ...this.workflowConfig.telemetry && this.stepInfo?.lazyStep instanceof LazyCallStep && this.stepInfo.lazyStep.headers[AGENT_NAME_HEADER] ? { [TELEMETRY_HEADER_AGENT]: "true" } : {}
1532
+ };
1533
+ if (this.stepInfo?.lazyStep.stepType !== "Call") {
1534
+ this.headers.rawHeaders[`Upstash-Forward-${WORKFLOW_PROTOCOL_VERSION_HEADER}`] = WORKFLOW_PROTOCOL_VERSION;
1259
1535
  }
1260
- } else {
1261
- if (flowControl) {
1262
- const { flowControlKey, flowControlValue } = prepareFlowControl(flowControl);
1263
- baseHeaders["Upstash-Flow-Control-Key"] = flowControlKey;
1264
- baseHeaders["Upstash-Flow-Control-Value"] = flowControlValue;
1536
+ }
1537
+ addInvokeCount() {
1538
+ if (this.invokeCount === void 0 || this.invokeCount === 0) {
1539
+ return;
1540
+ }
1541
+ const invokeCount = this.invokeCount.toString();
1542
+ this.headers.workflowHeaders[`Forward-${WORKFLOW_INVOKE_COUNT_HEADER}`] = invokeCount;
1543
+ if (this.workflowConfig.failureUrl) {
1544
+ this.headers.failureHeaders[`Forward-${WORKFLOW_INVOKE_COUNT_HEADER}`] = invokeCount;
1265
1545
  }
1266
- if (retries !== void 0) {
1267
- baseHeaders["Upstash-Retries"] = retries.toString();
1268
- baseHeaders["Upstash-Failure-Callback-Retries"] = retries.toString();
1546
+ if (this.stepInfo?.lazyStep instanceof LazyCallStep) {
1547
+ this.headers.rawHeaders[`Upstash-Forward-${WORKFLOW_INVOKE_COUNT_HEADER}`] = invokeCount;
1269
1548
  }
1270
1549
  }
1271
- if (userHeaders) {
1272
- for (const header of userHeaders.keys()) {
1273
- if (step?.callHeaders) {
1274
- baseHeaders[`Upstash-Callback-Forward-${header}`] = userHeaders.get(header);
1275
- } else {
1276
- baseHeaders[`Upstash-Forward-${header}`] = userHeaders.get(header);
1277
- }
1278
- baseHeaders[`Upstash-Failure-Callback-Forward-${header}`] = userHeaders.get(header);
1550
+ addRetries() {
1551
+ if (this.workflowConfig.retries === void 0 || this.workflowConfig.retries === DEFAULT_RETRIES) {
1552
+ return;
1553
+ }
1554
+ const retries = this.workflowConfig.retries.toString();
1555
+ this.headers.workflowHeaders["Retries"] = retries;
1556
+ if (this.workflowConfig.failureUrl) {
1557
+ this.headers.failureHeaders["Retries"] = retries;
1279
1558
  }
1280
1559
  }
1281
- if (step?.callHeaders) {
1282
- const forwardedHeaders = Object.fromEntries(
1283
- Object.entries(step.callHeaders).map(([header, value]) => [
1284
- `Upstash-Forward-${header}`,
1285
- value
1286
- ])
1560
+ addFlowControl() {
1561
+ if (!this.workflowConfig.flowControl) {
1562
+ return;
1563
+ }
1564
+ const { flowControlKey, flowControlValue } = prepareFlowControl(
1565
+ this.workflowConfig.flowControl
1287
1566
  );
1288
- return {
1289
- headers: {
1290
- ...baseHeaders,
1291
- ...forwardedHeaders,
1292
- "Upstash-Callback": workflowUrl,
1293
- "Upstash-Callback-Workflow-RunId": workflowRunId,
1294
- "Upstash-Callback-Workflow-CallType": "fromCallback",
1295
- "Upstash-Callback-Workflow-Init": "false",
1296
- "Upstash-Callback-Workflow-Url": workflowUrl,
1297
- "Upstash-Callback-Feature-Set": "LazyFetch,InitialBody",
1298
- "Upstash-Callback-Forward-Upstash-Workflow-Callback": "true",
1299
- "Upstash-Callback-Forward-Upstash-Workflow-StepId": step.stepId.toString(),
1300
- "Upstash-Callback-Forward-Upstash-Workflow-StepName": step.stepName,
1301
- "Upstash-Callback-Forward-Upstash-Workflow-StepType": step.stepType,
1302
- "Upstash-Callback-Forward-Upstash-Workflow-Concurrent": step.concurrent.toString(),
1303
- "Upstash-Callback-Forward-Upstash-Workflow-ContentType": contentType,
1304
- [`Upstash-Callback-Forward-${WORKFLOW_INVOKE_COUNT_HEADER}`]: (invokeCount ?? 0).toString(),
1305
- "Upstash-Workflow-CallType": "toCallback"
1567
+ this.headers.workflowHeaders["Flow-Control-Key"] = flowControlKey;
1568
+ this.headers.workflowHeaders["Flow-Control-Value"] = flowControlValue;
1569
+ if (this.workflowConfig.failureUrl) {
1570
+ this.headers.failureHeaders["Flow-Control-Key"] = flowControlKey;
1571
+ this.headers.failureHeaders["Flow-Control-Value"] = flowControlValue;
1572
+ }
1573
+ }
1574
+ addUserHeaders() {
1575
+ for (const [key, value] of this.userHeaders.entries()) {
1576
+ const forwardKey = `Forward-${key}`;
1577
+ this.headers.workflowHeaders[forwardKey] = value;
1578
+ if (this.workflowConfig.failureUrl) {
1579
+ this.headers.failureHeaders[forwardKey] = value;
1306
1580
  }
1307
- };
1581
+ }
1582
+ }
1583
+ addFailureUrl() {
1584
+ if (!this.workflowConfig.failureUrl) {
1585
+ return;
1586
+ }
1587
+ this.headers.workflowHeaders["Failure-Callback"] = this.workflowConfig.failureUrl;
1588
+ this.headers.failureHeaders[`Forward-${WORKFLOW_FAILURE_HEADER}`] = "true";
1589
+ this.headers.failureHeaders[`Forward-Upstash-Workflow-Failure-Callback`] = "true";
1590
+ this.headers.failureHeaders["Workflow-Runid"] = this.workflowConfig.workflowRunId;
1591
+ this.headers.failureHeaders["Workflow-Init"] = "false";
1592
+ this.headers.failureHeaders["Workflow-Url"] = this.workflowConfig.workflowUrl;
1593
+ this.headers.failureHeaders["Workflow-Calltype"] = "failureCall";
1594
+ this.headers.failureHeaders["Feature-Set"] = "LazyFetch,InitialBody";
1595
+ if (this.workflowConfig.retries !== void 0 && this.workflowConfig.retries !== DEFAULT_RETRIES) {
1596
+ this.headers.failureHeaders["Retries"] = this.workflowConfig.retries.toString();
1597
+ }
1598
+ }
1599
+ addContentType() {
1600
+ if (this.workflowConfig.useJSONContent) {
1601
+ this.headers.rawHeaders["content-type"] = "application/json";
1602
+ return "application/json";
1603
+ }
1604
+ const callHeaders = new Headers(
1605
+ this.stepInfo?.lazyStep instanceof LazyCallStep ? this.stepInfo.lazyStep.headers : {}
1606
+ );
1607
+ const contentType = (callHeaders.get("content-type") ? callHeaders.get("content-type") : this.userHeaders?.get("Content-Type") ? this.userHeaders.get("Content-Type") : void 0) ?? DEFAULT_CONTENT_TYPE;
1608
+ this.headers.rawHeaders["content-type"] = contentType;
1609
+ return contentType;
1308
1610
  }
1309
- if (step?.waitEventId) {
1611
+ prefixHeaders(contentType) {
1612
+ const { rawHeaders, workflowHeaders, failureHeaders } = this.headers;
1613
+ const isCall = this.stepInfo?.lazyStep.stepType === "Call";
1310
1614
  return {
1311
1615
  headers: {
1312
- ...baseHeaders,
1313
- "Upstash-Workflow-CallType": "step"
1616
+ ...rawHeaders,
1617
+ ...addPrefixToHeaders(workflowHeaders, isCall ? "Upstash-Callback-" : "Upstash-"),
1618
+ ...addPrefixToHeaders(failureHeaders, "Upstash-Failure-Callback-"),
1619
+ ...isCall ? addPrefixToHeaders(failureHeaders, "Upstash-Callback-Failure-Callback-") : {}
1314
1620
  },
1315
- timeoutHeaders: {
1316
- // to include user headers:
1317
- ...Object.fromEntries(
1318
- Object.entries(baseHeaders).map(([header, value]) => [header, [value]])
1319
- ),
1320
- // to include telemetry headers:
1321
- ...telemetry ? Object.fromEntries(
1322
- Object.entries(getTelemetryHeaders(telemetry)).map(([header, value]) => [
1323
- header,
1324
- [value]
1325
- ])
1326
- ) : {},
1327
- // note: using WORKFLOW_ID_HEADER doesn't work, because Runid -> RunId:
1328
- "Upstash-Workflow-Runid": [workflowRunId],
1329
- [WORKFLOW_INIT_HEADER]: ["false"],
1330
- [WORKFLOW_URL_HEADER]: [workflowUrl],
1331
- "Upstash-Workflow-CallType": ["step"]
1332
- }
1621
+ contentType
1333
1622
  };
1334
1623
  }
1335
- return { headers: baseHeaders };
1336
1624
  };
1337
- var verifyRequest = async (body, signature, verifier) => {
1338
- if (!verifier) {
1339
- return;
1340
- }
1341
- try {
1342
- if (!signature) {
1343
- throw new Error("`Upstash-Signature` header is not passed.");
1344
- }
1345
- const isValid = await verifier.verify({
1346
- body,
1347
- signature
1348
- });
1349
- if (!isValid) {
1350
- throw new Error("Signature in `Upstash-Signature` header is not valid");
1351
- }
1352
- } catch (error) {
1353
- throw new WorkflowError(
1354
- `Failed to verify that the Workflow request comes from QStash: ${error}
1355
-
1356
- If signature is missing, trigger the workflow endpoint by publishing your request to QStash instead of calling it directly.
1357
-
1358
- If you want to disable QStash Verification, you should clear env variables QSTASH_CURRENT_SIGNING_KEY and QSTASH_NEXT_SIGNING_KEY`
1359
- );
1625
+ function addPrefixToHeaders(headers, prefix) {
1626
+ const prefixedHeaders = {};
1627
+ for (const [key, value] of Object.entries(headers)) {
1628
+ prefixedHeaders[`${prefix}${key}`] = value;
1360
1629
  }
1361
- };
1630
+ return prefixedHeaders;
1631
+ }
1362
1632
  var prepareFlowControl = (flowControl) => {
1363
1633
  const parallelism = flowControl.parallelism?.toString();
1364
- const rate = flowControl.ratePerSecond?.toString();
1634
+ const rate = (flowControl.rate ?? flowControl.ratePerSecond)?.toString();
1635
+ const period = typeof flowControl.period === "number" ? `${flowControl.period}s` : flowControl.period;
1365
1636
  const controlValue = [
1366
1637
  parallelism ? `parallelism=${parallelism}` : void 0,
1367
- rate ? `rate=${rate}` : void 0
1638
+ rate ? `rate=${rate}` : void 0,
1639
+ period ? `period=${period}` : void 0
1368
1640
  ].filter(Boolean);
1369
1641
  if (controlValue.length === 0) {
1370
- throw new import_qstash3.QstashError("Provide at least one of parallelism or ratePerSecond for flowControl");
1642
+ throw new import_qstash4.QstashError("Provide at least one of parallelism or ratePerSecond for flowControl");
1371
1643
  }
1372
1644
  return {
1373
1645
  flowControlKey: flowControl.key,
1374
1646
  flowControlValue: controlValue.join(", ")
1375
1647
  };
1376
1648
  };
1649
+ var getHeaders = (params) => {
1650
+ const workflowHeaders = new WorkflowHeaders(params);
1651
+ return workflowHeaders.getHeaders();
1652
+ };
1377
1653
 
1378
- // src/context/auto-executor.ts
1379
- var import_qstash4 = require("@upstash/qstash");
1380
-
1381
- // src/serve/serve-many.ts
1382
- var invokeWorkflow = async ({
1383
- settings,
1384
- invokeStep,
1654
+ // src/qstash/submit-steps.ts
1655
+ var submitParallelSteps = async ({
1385
1656
  context,
1657
+ steps,
1658
+ initialStepCount,
1386
1659
  invokeCount,
1387
- telemetry
1660
+ telemetry,
1661
+ debug
1388
1662
  }) => {
1389
- const {
1390
- body,
1391
- workflow,
1392
- headers = {},
1393
- workflowRunId = getWorkflowRunId(),
1394
- retries,
1395
- flowControl
1396
- } = settings;
1397
- const { workflowId } = workflow;
1398
- const {
1399
- retries: workflowRetries,
1400
- failureFunction,
1401
- failureUrl,
1402
- useJSONContent,
1403
- flowControl: workflowFlowControl
1404
- } = workflow.options;
1405
- if (!workflowId) {
1406
- throw new WorkflowError("You can only invoke workflow which has a workflowId");
1407
- }
1408
- const { headers: invokerHeaders } = getHeaders({
1409
- initHeaderValue: "false",
1410
- workflowRunId: context.workflowRunId,
1411
- workflowUrl: context.url,
1412
- userHeaders: context.headers,
1413
- failureUrl: context.failureUrl,
1414
- retries: context.retries,
1415
- telemetry,
1663
+ const planSteps = steps.map(
1664
+ (step, index) => step.getPlanStep(steps.length, initialStepCount + index)
1665
+ );
1666
+ await debug?.log("SUBMIT", "SUBMIT_STEP", {
1667
+ length: planSteps.length,
1668
+ steps: planSteps
1669
+ });
1670
+ const result = await context.qstashClient.batch(
1671
+ planSteps.map((planStep) => {
1672
+ const { headers } = getHeaders({
1673
+ initHeaderValue: "false",
1674
+ workflowConfig: {
1675
+ workflowRunId: context.workflowRunId,
1676
+ workflowUrl: context.url,
1677
+ failureUrl: context.failureUrl,
1678
+ retries: context.retries,
1679
+ flowControl: context.flowControl,
1680
+ telemetry
1681
+ },
1682
+ userHeaders: context.headers,
1683
+ invokeCount
1684
+ });
1685
+ return {
1686
+ headers,
1687
+ method: "POST",
1688
+ url: context.url,
1689
+ body: JSON.stringify(planStep),
1690
+ notBefore: planStep.sleepUntil,
1691
+ delay: planStep.sleepFor
1692
+ };
1693
+ })
1694
+ );
1695
+ await debug?.log("INFO", "SUBMIT_STEP", {
1696
+ messageIds: result.map((message) => {
1697
+ return {
1698
+ message: message.messageId
1699
+ };
1700
+ })
1701
+ });
1702
+ throw new WorkflowAbort(planSteps[0].stepName, planSteps[0]);
1703
+ };
1704
+ var submitSingleStep = async ({
1705
+ context,
1706
+ lazyStep,
1707
+ stepId,
1708
+ invokeCount,
1709
+ concurrency,
1710
+ telemetry,
1711
+ debug
1712
+ }) => {
1713
+ const resultStep = await lazyStep.getResultStep(concurrency, stepId);
1714
+ await debug?.log("INFO", "RUN_SINGLE", {
1715
+ fromRequest: false,
1716
+ step: resultStep,
1717
+ stepCount: stepId
1718
+ });
1719
+ const { headers } = lazyStep.getHeaders({
1720
+ context,
1721
+ step: resultStep,
1416
1722
  invokeCount,
1417
- flowControl: context.flowControl
1723
+ telemetry
1418
1724
  });
1419
- invokerHeaders["Upstash-Workflow-Runid"] = context.workflowRunId;
1420
- const newUrl = context.url.replace(/[^/]+$/, workflowId);
1421
- const { headers: triggerHeaders } = getHeaders({
1422
- initHeaderValue: "true",
1423
- workflowRunId,
1424
- workflowUrl: newUrl,
1425
- userHeaders: new Headers(headers),
1426
- retries: retries ?? workflowRetries,
1427
- telemetry,
1428
- failureUrl: failureFunction ? newUrl : failureUrl,
1429
- invokeCount: invokeCount + 1,
1430
- flowControl: flowControl ?? workflowFlowControl
1725
+ const body = lazyStep.getBody({
1726
+ context,
1727
+ step: resultStep,
1728
+ headers,
1729
+ invokeCount,
1730
+ telemetry
1431
1731
  });
1432
- triggerHeaders["Upstash-Workflow-Invoke"] = "true";
1433
- if (useJSONContent) {
1434
- triggerHeaders["content-type"] = "application/json";
1435
- }
1436
- const request = {
1437
- body: JSON.stringify(body),
1438
- headers: Object.fromEntries(
1439
- Object.entries(invokerHeaders).map((pairs) => [pairs[0], [pairs[1]]])
1440
- ),
1441
- workflowRunId: context.workflowRunId,
1442
- workflowUrl: context.url,
1443
- step: invokeStep
1444
- };
1445
- await context.qstashClient.publish({
1446
- headers: triggerHeaders,
1447
- method: "POST",
1448
- body: JSON.stringify(request),
1449
- url: newUrl
1732
+ await debug?.log("SUBMIT", "SUBMIT_STEP", {
1733
+ length: 1,
1734
+ steps: [resultStep]
1735
+ });
1736
+ const submitResult = await lazyStep.submitStep({
1737
+ context,
1738
+ body,
1739
+ headers,
1740
+ isParallel: concurrency !== NO_CONCURRENCY,
1741
+ invokeCount,
1742
+ step: resultStep,
1743
+ telemetry
1744
+ });
1745
+ await debug?.log("INFO", "SUBMIT_STEP", {
1746
+ messageIds: submitResult.map((message) => {
1747
+ return {
1748
+ message: message.messageId
1749
+ };
1750
+ })
1450
1751
  });
1752
+ return resultStep;
1451
1753
  };
1452
1754
 
1453
1755
  // src/context/auto-executor.ts
@@ -1554,14 +1856,16 @@ var AutoExecutor = class _AutoExecutor {
1554
1856
  });
1555
1857
  return lazyStep.parseOut(step.out);
1556
1858
  }
1557
- const resultStep = await lazyStep.getResultStep(NO_CONCURRENCY, this.stepCount);
1558
- await this.debug?.log("INFO", "RUN_SINGLE", {
1559
- fromRequest: false,
1560
- step: resultStep,
1561
- stepCount: this.stepCount
1859
+ const resultStep = await submitSingleStep({
1860
+ context: this.context,
1861
+ lazyStep,
1862
+ stepId: this.stepCount,
1863
+ invokeCount: this.invokeCount,
1864
+ concurrency: 1,
1865
+ telemetry: this.telemetry,
1866
+ debug: this.debug
1562
1867
  });
1563
- await this.submitStepsToQStash([resultStep], [lazyStep]);
1564
- return resultStep.out;
1868
+ throw new WorkflowAbort(lazyStep.stepName, resultStep);
1565
1869
  }
1566
1870
  /**
1567
1871
  * Runs steps in parallel.
@@ -1589,10 +1893,14 @@ var AutoExecutor = class _AutoExecutor {
1589
1893
  });
1590
1894
  switch (parallelCallState) {
1591
1895
  case "first": {
1592
- const planSteps = parallelSteps.map(
1593
- (parallelStep, index) => parallelStep.getPlanStep(parallelSteps.length, initialStepCount + index)
1594
- );
1595
- await this.submitStepsToQStash(planSteps, parallelSteps);
1896
+ await submitParallelSteps({
1897
+ context: this.context,
1898
+ steps: parallelSteps,
1899
+ initialStepCount,
1900
+ invokeCount: this.invokeCount,
1901
+ telemetry: this.telemetry,
1902
+ debug: this.debug
1903
+ });
1596
1904
  break;
1597
1905
  }
1598
1906
  case "partial": {
@@ -1606,13 +1914,18 @@ var AutoExecutor = class _AutoExecutor {
1606
1914
  validateStep(parallelSteps[stepIndex], planStep);
1607
1915
  try {
1608
1916
  const parallelStep = parallelSteps[stepIndex];
1609
- const resultStep = await parallelStep.getResultStep(
1610
- parallelSteps.length,
1611
- planStep.targetStep
1612
- );
1613
- await this.submitStepsToQStash([resultStep], [parallelStep]);
1917
+ const resultStep = await submitSingleStep({
1918
+ context: this.context,
1919
+ lazyStep: parallelStep,
1920
+ stepId: planStep.targetStep,
1921
+ invokeCount: this.invokeCount,
1922
+ concurrency: parallelSteps.length,
1923
+ telemetry: this.telemetry,
1924
+ debug: this.debug
1925
+ });
1926
+ throw new WorkflowAbort(parallelStep.stepName, resultStep);
1614
1927
  } catch (error) {
1615
- if (error instanceof WorkflowAbort || error instanceof import_qstash4.QstashError && error.status === 400) {
1928
+ if (error instanceof WorkflowAbort || error instanceof import_qstash5.QstashError && error.status === 400) {
1616
1929
  throw error;
1617
1930
  }
1618
1931
  throw new WorkflowError(
@@ -1668,128 +1981,6 @@ var AutoExecutor = class _AutoExecutor {
1668
1981
  return "discard";
1669
1982
  }
1670
1983
  }
1671
- /**
1672
- * sends the steps to QStash as batch
1673
- *
1674
- * @param steps steps to send
1675
- */
1676
- async submitStepsToQStash(steps, lazySteps) {
1677
- if (steps.length === 0) {
1678
- throw new WorkflowError(
1679
- `Unable to submit steps to QStash. Provided list is empty. Current step: ${this.stepCount}`
1680
- );
1681
- }
1682
- await this.debug?.log("SUBMIT", "SUBMIT_STEP", {
1683
- length: steps.length,
1684
- steps
1685
- });
1686
- if (steps[0].waitEventId && steps.length === 1) {
1687
- const waitStep = steps[0];
1688
- const { headers, timeoutHeaders } = getHeaders({
1689
- initHeaderValue: "false",
1690
- workflowRunId: this.context.workflowRunId,
1691
- workflowUrl: this.context.url,
1692
- userHeaders: this.context.headers,
1693
- step: waitStep,
1694
- failureUrl: this.context.failureUrl,
1695
- retries: this.context.retries,
1696
- telemetry: this.telemetry,
1697
- invokeCount: this.invokeCount,
1698
- flowControl: this.context.flowControl
1699
- });
1700
- const waitBody = {
1701
- url: this.context.url,
1702
- timeout: waitStep.timeout,
1703
- timeoutBody: void 0,
1704
- timeoutUrl: this.context.url,
1705
- timeoutHeaders,
1706
- step: {
1707
- stepId: waitStep.stepId,
1708
- stepType: "Wait",
1709
- stepName: waitStep.stepName,
1710
- concurrent: waitStep.concurrent,
1711
- targetStep: waitStep.targetStep
1712
- }
1713
- };
1714
- await this.context.qstashClient.http.request({
1715
- path: ["v2", "wait", waitStep.waitEventId],
1716
- body: JSON.stringify(waitBody),
1717
- headers,
1718
- method: "POST",
1719
- parseResponseAsJson: false
1720
- });
1721
- throw new WorkflowAbort(waitStep.stepName, waitStep);
1722
- }
1723
- if (steps.length === 1 && lazySteps[0] instanceof LazyInvokeStep) {
1724
- const invokeStep = steps[0];
1725
- const lazyInvokeStep = lazySteps[0];
1726
- await invokeWorkflow({
1727
- settings: lazyInvokeStep.params,
1728
- invokeStep,
1729
- context: this.context,
1730
- invokeCount: this.invokeCount,
1731
- telemetry: this.telemetry
1732
- });
1733
- throw new WorkflowAbort(invokeStep.stepName, invokeStep);
1734
- }
1735
- const result = await this.context.qstashClient.batch(
1736
- steps.map((singleStep, index) => {
1737
- const lazyStep = lazySteps[index];
1738
- const { headers } = getHeaders({
1739
- initHeaderValue: "false",
1740
- workflowRunId: this.context.workflowRunId,
1741
- workflowUrl: this.context.url,
1742
- userHeaders: this.context.headers,
1743
- step: singleStep,
1744
- failureUrl: this.context.failureUrl,
1745
- retries: this.context.retries,
1746
- callRetries: lazyStep instanceof LazyCallStep ? lazyStep.retries : void 0,
1747
- callTimeout: lazyStep instanceof LazyCallStep ? lazyStep.timeout : void 0,
1748
- telemetry: this.telemetry,
1749
- invokeCount: this.invokeCount,
1750
- flowControl: this.context.flowControl,
1751
- callFlowControl: lazyStep instanceof LazyCallStep ? lazyStep.flowControl : void 0
1752
- });
1753
- const willWait = singleStep.concurrent === NO_CONCURRENCY || singleStep.stepId === 0;
1754
- singleStep.out = JSON.stringify(singleStep.out);
1755
- return singleStep.callUrl && lazyStep instanceof LazyCallStep ? (
1756
- // if the step is a third party call, we call the third party
1757
- // url (singleStep.callUrl) and pass information about the workflow
1758
- // in the headers (handled in getHeaders). QStash makes the request
1759
- // to callUrl and returns the result to Workflow endpoint.
1760
- // handleThirdPartyCallResult method sends the result of the third
1761
- // party call to QStash.
1762
- {
1763
- headers,
1764
- method: singleStep.callMethod,
1765
- body: JSON.stringify(singleStep.callBody),
1766
- url: singleStep.callUrl
1767
- }
1768
- ) : (
1769
- // if the step is not a third party call, we use workflow
1770
- // endpoint (context.url) as URL when calling QStash. QStash
1771
- // calls us back with the updated steps list.
1772
- {
1773
- headers,
1774
- method: "POST",
1775
- body: JSON.stringify(singleStep),
1776
- url: this.context.url,
1777
- notBefore: willWait ? singleStep.sleepUntil : void 0,
1778
- delay: willWait ? singleStep.sleepFor : void 0
1779
- }
1780
- );
1781
- })
1782
- );
1783
- const _result = result;
1784
- await this.debug?.log("INFO", "SUBMIT_STEP", {
1785
- messageIds: _result.map((message) => {
1786
- return {
1787
- message: message.messageId
1788
- };
1789
- })
1790
- });
1791
- throw new WorkflowAbort(steps[0].stepName, steps[0]);
1792
- }
1793
1984
  /**
1794
1985
  * Get the promise by executing the lazt steps list. If there is a single
1795
1986
  * step, we call `runSingle`. Otherwise `runParallel` is called.
@@ -1863,7 +2054,7 @@ var sortSteps = (steps) => {
1863
2054
  };
1864
2055
 
1865
2056
  // src/context/api/anthropic.ts
1866
- var import_qstash5 = require("@upstash/qstash");
2057
+ var import_qstash6 = require("@upstash/qstash");
1867
2058
 
1868
2059
  // src/context/provider.ts
1869
2060
  var getProviderInfo = (api) => {
@@ -1927,7 +2118,7 @@ var AnthropicAPI = class extends BaseWorkflowApi {
1927
2118
  return await this.callApi(stepName, {
1928
2119
  api: {
1929
2120
  name: "llm",
1930
- provider: (0, import_qstash5.anthropic)({ token })
2121
+ provider: (0, import_qstash6.anthropic)({ token })
1931
2122
  },
1932
2123
  ...parameters
1933
2124
  });
@@ -1935,12 +2126,12 @@ var AnthropicAPI = class extends BaseWorkflowApi {
1935
2126
  };
1936
2127
 
1937
2128
  // src/context/api/openai.ts
1938
- var import_qstash6 = require("@upstash/qstash");
2129
+ var import_qstash7 = require("@upstash/qstash");
1939
2130
  var OpenAIAPI = class extends BaseWorkflowApi {
1940
2131
  async call(stepName, settings) {
1941
2132
  const { token, organization, operation, baseURL, ...parameters } = settings;
1942
2133
  const useOpenAI = baseURL === void 0;
1943
- const provider = useOpenAI ? (0, import_qstash6.openai)({ token, organization }) : (0, import_qstash6.custom)({ baseUrl: baseURL, token });
2134
+ const provider = useOpenAI ? (0, import_qstash7.openai)({ token, organization }) : (0, import_qstash7.custom)({ baseUrl: baseURL, token });
1944
2135
  return await this.callApi(stepName, {
1945
2136
  api: {
1946
2137
  name: "llm",
@@ -1952,14 +2143,14 @@ var OpenAIAPI = class extends BaseWorkflowApi {
1952
2143
  };
1953
2144
 
1954
2145
  // src/context/api/resend.ts
1955
- var import_qstash7 = require("@upstash/qstash");
2146
+ var import_qstash8 = require("@upstash/qstash");
1956
2147
  var ResendAPI = class extends BaseWorkflowApi {
1957
2148
  async call(stepName, settings) {
1958
2149
  const { token, batch = false, ...parameters } = settings;
1959
2150
  return await this.callApi(stepName, {
1960
2151
  api: {
1961
2152
  name: "email",
1962
- provider: (0, import_qstash7.resend)({ token, batch })
2153
+ provider: (0, import_qstash8.resend)({ token, batch })
1963
2154
  },
1964
2155
  ...parameters
1965
2156
  });
@@ -1985,65 +2176,58 @@ var WorkflowApi = class extends BaseWorkflowApi {
1985
2176
  }
1986
2177
  };
1987
2178
 
1988
- // src/agents/adapters.ts
2179
+ // src/agents/index.ts
1989
2180
  var import_openai2 = require("@ai-sdk/openai");
1990
- var import_ai = require("ai");
1991
-
1992
- // src/agents/constants.ts
1993
- var AGENT_NAME_HEADER = "upstash-agent-name";
1994
- var MANAGER_AGENT_PROMPT = `You are an agent orchestrating other AI Agents.
1995
-
1996
- These other agents have tools available to them.
1997
-
1998
- Given a prompt, utilize these agents to address requests.
1999
-
2000
- Don't always call all the agents provided to you at the same time. You can call one and use it's response to call another.
2001
-
2002
- Avoid calling the same agent twice in one turn. Instead, prefer to call it once but provide everything
2003
- you need from that agent.
2004
- `;
2005
2181
 
2006
2182
  // src/agents/adapters.ts
2007
- var createWorkflowOpenAI = (context, config) => {
2008
- const { baseURL, apiKey } = config ?? {};
2009
- return (0, import_openai2.createOpenAI)({
2010
- baseURL,
2011
- apiKey,
2012
- compatibility: "strict",
2013
- fetch: async (input, init) => {
2014
- try {
2015
- const headers = init?.headers ? Object.fromEntries(new Headers(init.headers).entries()) : {};
2016
- const body = init?.body ? JSON.parse(init.body) : void 0;
2017
- const agentName = headers[AGENT_NAME_HEADER];
2018
- const stepName = agentName ? `Call Agent ${agentName}` : "Call Agent";
2019
- const responseInfo = await context.call(stepName, {
2020
- url: input.toString(),
2021
- method: init?.method,
2022
- headers,
2023
- body
2024
- });
2025
- const responseHeaders = new Headers(
2026
- Object.entries(responseInfo.header).reduce(
2027
- (acc, [key, values]) => {
2028
- acc[key] = values.join(", ");
2029
- return acc;
2030
- },
2031
- {}
2032
- )
2033
- );
2034
- return new Response(JSON.stringify(responseInfo.body), {
2035
- status: responseInfo.status,
2036
- headers: responseHeaders
2037
- });
2038
- } catch (error) {
2039
- if (error instanceof Error && error.name === "WorkflowAbort") {
2040
- throw error;
2041
- } else {
2042
- console.error("Error in fetch implementation:", error);
2043
- throw error;
2044
- }
2045
- }
2183
+ var import_ai = require("ai");
2184
+ var fetchWithContextCall = async (context, agentCallParams, ...params) => {
2185
+ const [input, init] = params;
2186
+ try {
2187
+ const headers = init?.headers ? Object.fromEntries(new Headers(init.headers).entries()) : {};
2188
+ const body = init?.body ? JSON.parse(init.body) : void 0;
2189
+ const agentName = headers[AGENT_NAME_HEADER];
2190
+ const stepName = agentName ? `Call Agent ${agentName}` : "Call Agent";
2191
+ const responseInfo = await context.call(stepName, {
2192
+ url: input.toString(),
2193
+ method: init?.method,
2194
+ headers,
2195
+ body,
2196
+ timeout: agentCallParams?.timeout,
2197
+ retries: agentCallParams?.retries,
2198
+ flowControl: agentCallParams?.flowControl
2199
+ });
2200
+ const responseHeaders = new Headers(
2201
+ Object.entries(responseInfo.header).reduce(
2202
+ (acc, [key, values]) => {
2203
+ acc[key] = values.join(", ");
2204
+ return acc;
2205
+ },
2206
+ {}
2207
+ )
2208
+ );
2209
+ return new Response(JSON.stringify(responseInfo.body), {
2210
+ status: responseInfo.status,
2211
+ headers: responseHeaders
2212
+ });
2213
+ } catch (error) {
2214
+ if (error instanceof Error && error.name === "WorkflowAbort") {
2215
+ throw error;
2216
+ } else {
2217
+ console.error("Error in fetch implementation:", error);
2218
+ throw error;
2046
2219
  }
2220
+ }
2221
+ };
2222
+ var createWorkflowModel = ({
2223
+ context,
2224
+ provider,
2225
+ providerParams,
2226
+ agentCallParams
2227
+ }) => {
2228
+ return provider({
2229
+ fetch: (...params) => fetchWithContextCall(context, agentCallParams, ...params),
2230
+ ...providerParams
2047
2231
  });
2048
2232
  };
2049
2233
  var wrapTools = ({
@@ -2313,10 +2497,24 @@ var WorkflowAgents = class {
2313
2497
  */
2314
2498
  openai(...params) {
2315
2499
  const [model, settings] = params;
2316
- const { baseURL, apiKey, ...otherSettings } = settings ?? {};
2317
- const openai2 = createWorkflowOpenAI(this.context, { baseURL, apiKey });
2318
- return openai2(model, otherSettings);
2500
+ const { baseURL, apiKey, callSettings, ...otherSettings } = settings ?? {};
2501
+ const openaiModel = this.AISDKModel({
2502
+ context: this.context,
2503
+ provider: import_openai2.createOpenAI,
2504
+ providerParams: { baseURL, apiKey, compatibility: "strict" },
2505
+ agentCallParams: callSettings
2506
+ });
2507
+ return openaiModel(model, otherSettings);
2508
+ }
2509
+ AISDKModel = createWorkflowModel;
2510
+ };
2511
+
2512
+ // src/serve/serve-many.ts
2513
+ var getNewUrlFromWorkflowId = (url, workflowId) => {
2514
+ if (!workflowId) {
2515
+ throw new WorkflowError("You can only call workflow which has a workflowId");
2319
2516
  }
2517
+ return url.replace(/[^/]+$/, workflowId);
2320
2518
  };
2321
2519
 
2322
2520
  // src/context/context.ts
@@ -2540,60 +2738,42 @@ var WorkflowContext = class {
2540
2738
  }
2541
2739
  await this.addStep(new LazySleepUntilStep(stepName, time));
2542
2740
  }
2543
- /**
2544
- * Makes a third party call through QStash in order to make a
2545
- * network call without consuming any runtime.
2546
- *
2547
- * ```ts
2548
- * const { status, body } = await context.call<string>(
2549
- * "post call step",
2550
- * {
2551
- * url: "https://www.some-endpoint.com/api",
2552
- * method: "POST",
2553
- * body: "my-payload"
2554
- * }
2555
- * );
2556
- * ```
2557
- *
2558
- * tries to parse the result of the request as JSON. If it's
2559
- * not a JSON which can be parsed, simply returns the response
2560
- * body as it is.
2561
- *
2562
- * @param stepName
2563
- * @param url url to call
2564
- * @param method call method. "GET" by default.
2565
- * @param body call body
2566
- * @param headers call headers
2567
- * @param retries number of call retries. 0 by default
2568
- * @param timeout max duration to wait for the endpoint to respond. in seconds.
2569
- * @returns call result as {
2570
- * status: number;
2571
- * body: unknown;
2572
- * header: Record<string, string[]>
2573
- * }
2574
- */
2575
2741
  async call(stepName, settings) {
2576
- const {
2577
- url,
2578
- method = "GET",
2579
- body: requestBody,
2580
- headers = {},
2581
- retries = 0,
2582
- timeout,
2583
- flowControl
2584
- } = settings;
2585
- return await this.addStep(
2586
- new LazyCallStep(
2742
+ let callStep;
2743
+ if ("workflow" in settings) {
2744
+ const url = getNewUrlFromWorkflowId(this.url, settings.workflow.workflowId);
2745
+ callStep = new LazyCallStep(
2746
+ stepName,
2747
+ url,
2748
+ "POST",
2749
+ settings.body,
2750
+ settings.headers || {},
2751
+ settings.retries || 0,
2752
+ settings.timeout,
2753
+ settings.flowControl ?? settings.workflow.options.flowControl
2754
+ );
2755
+ } else {
2756
+ const {
2757
+ url,
2758
+ method = "GET",
2759
+ body,
2760
+ headers = {},
2761
+ retries = 0,
2762
+ timeout,
2763
+ flowControl
2764
+ } = settings;
2765
+ callStep = new LazyCallStep(
2587
2766
  stepName,
2588
2767
  url,
2589
2768
  method,
2590
- requestBody,
2769
+ body,
2591
2770
  headers,
2592
2771
  retries,
2593
2772
  timeout,
2594
2773
  flowControl
2595
- )
2596
- );
2774
+ );
2775
+ }
2776
+ return await this.addStep(callStep);
2597
2777
  }
2598
2778
  /**
2599
2779
  * Pauses workflow execution until a specific event occurs or a timeout is reached.
@@ -2741,7 +2921,7 @@ var WorkflowLogger = class _WorkflowLogger {
2741
2921
  };
2742
2922
 
2743
2923
  // src/serve/authorization.ts
2744
- var import_qstash8 = require("@upstash/qstash");
2924
+ var import_qstash9 = require("@upstash/qstash");
2745
2925
  var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowContext {
2746
2926
  static disabledMessage = "disabled-qstash-worklfow-run";
2747
2927
  disabled = true;
@@ -2773,7 +2953,7 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
2773
2953
  */
2774
2954
  static async tryAuthentication(routeFunction, context) {
2775
2955
  const disabledContext = new _DisabledWorkflowContext({
2776
- qstashClient: new import_qstash8.Client({
2956
+ qstashClient: new import_qstash9.Client({
2777
2957
  baseUrl: "disabled-client",
2778
2958
  token: "disabled-client"
2779
2959
  }),
@@ -2987,15 +3167,15 @@ var handleFailure = async (request, requestPayload, qstashClient, initialPayload
2987
3167
  };
2988
3168
 
2989
3169
  // src/serve/options.ts
2990
- var import_qstash9 = require("@upstash/qstash");
2991
3170
  var import_qstash10 = require("@upstash/qstash");
3171
+ var import_qstash11 = require("@upstash/qstash");
2992
3172
  var processOptions = (options) => {
2993
3173
  const environment = options?.env ?? (typeof process === "undefined" ? {} : process.env);
2994
3174
  const receiverEnvironmentVariablesSet = Boolean(
2995
3175
  environment.QSTASH_CURRENT_SIGNING_KEY && environment.QSTASH_NEXT_SIGNING_KEY
2996
3176
  );
2997
3177
  return {
2998
- qstashClient: new import_qstash10.Client({
3178
+ qstashClient: new import_qstash11.Client({
2999
3179
  baseUrl: environment.QSTASH_URL,
3000
3180
  token: environment.QSTASH_TOKEN
3001
3181
  }),
@@ -3030,7 +3210,7 @@ var processOptions = (options) => {
3030
3210
  throw error;
3031
3211
  }
3032
3212
  },
3033
- receiver: receiverEnvironmentVariablesSet ? new import_qstash9.Receiver({
3213
+ receiver: receiverEnvironmentVariablesSet ? new import_qstash10.Receiver({
3034
3214
  currentSigningKey: environment.QSTASH_CURRENT_SIGNING_KEY,
3035
3215
  nextSigningKey: environment.QSTASH_NEXT_SIGNING_KEY
3036
3216
  }) : void 0,
@@ -3039,6 +3219,7 @@ var processOptions = (options) => {
3039
3219
  retries: DEFAULT_RETRIES,
3040
3220
  useJSONContent: false,
3041
3221
  disableTelemetry: false,
3222
+ onError: console.error,
3042
3223
  ...options
3043
3224
  };
3044
3225
  };
@@ -3088,7 +3269,8 @@ var serveBase = (routeFunction, telemetry, options) => {
3088
3269
  retries,
3089
3270
  useJSONContent,
3090
3271
  disableTelemetry,
3091
- flowControl
3272
+ flowControl,
3273
+ onError
3092
3274
  } = processOptions(options);
3093
3275
  telemetry = disableTelemetry ? void 0 : telemetry;
3094
3276
  const debug = WorkflowLogger.getLogger(verbose);
@@ -3217,8 +3399,19 @@ var serveBase = (routeFunction, telemetry, options) => {
3217
3399
  try {
3218
3400
  return await handler(request);
3219
3401
  } catch (error) {
3220
- console.error(error);
3221
- return new Response(JSON.stringify(formatWorkflowError(error)), {
3402
+ const formattedError = formatWorkflowError(error);
3403
+ try {
3404
+ onError?.(error);
3405
+ } catch (onErrorError) {
3406
+ const formattedOnErrorError = formatWorkflowError(onErrorError);
3407
+ const errorMessage = `Error while running onError callback: '${formattedOnErrorError.message}'.
3408
+ Original error: '${formattedError.message}'`;
3409
+ console.error(errorMessage);
3410
+ return new Response(errorMessage, {
3411
+ status: 500
3412
+ });
3413
+ }
3414
+ return new Response(JSON.stringify(formattedError), {
3222
3415
  status: 500
3223
3416
  });
3224
3417
  }
@@ -3237,7 +3430,7 @@ var serve = (routeFunction, options) => {
3237
3430
  };
3238
3431
 
3239
3432
  // src/client/index.ts
3240
- var import_qstash11 = require("@upstash/qstash");
3433
+ var import_qstash12 = require("@upstash/qstash");
3241
3434
  var Client4 = class {
3242
3435
  client;
3243
3436
  constructor(clientConfig) {
@@ -3246,7 +3439,7 @@ var Client4 = class {
3246
3439
  "QStash token is required for Upstash Workflow!\n\nTo fix this:\n1. Get your token from the Upstash Console (https://console.upstash.com/qstash)\n2. Initialize the workflow client with:\n\n const client = new Client({\n token: '<YOUR_QSTASH_TOKEN>'\n });"
3247
3440
  );
3248
3441
  }
3249
- this.client = new import_qstash11.Client(clientConfig);
3442
+ this.client = new import_qstash12.Client(clientConfig);
3250
3443
  }
3251
3444
  /**
3252
3445
  * Cancel an ongoing workflow
@@ -3390,6 +3583,11 @@ var Client4 = class {
3390
3583
  * with `wfr_`.
3391
3584
  * @param retries retry to use in the initial request. in the rest of
3392
3585
  * the workflow, `retries` option of the `serve` will be used.
3586
+ * @param flowControl Settings for controlling the number of active requests
3587
+ * and number of requests per second with the same key.
3588
+ * @param delay Delay for the workflow run. This is used to delay the
3589
+ * execution of the workflow run. The delay is in seconds or can be passed
3590
+ * as a string with a time unit (e.g. "1h", "30m", "15s").
3393
3591
  * @returns workflow run id
3394
3592
  */
3395
3593
  async trigger({
@@ -3398,7 +3596,8 @@ var Client4 = class {
3398
3596
  headers,
3399
3597
  workflowRunId,
3400
3598
  retries,
3401
- flowControl
3599
+ flowControl,
3600
+ delay
3402
3601
  }) {
3403
3602
  const finalWorkflowRunId = getWorkflowRunId(workflowRunId);
3404
3603
  const context = new WorkflowContext({
@@ -3416,8 +3615,9 @@ var Client4 = class {
3416
3615
  });
3417
3616
  const result = await triggerFirstInvocation({
3418
3617
  workflowContext: context,
3419
- telemetry: void 0
3618
+ telemetry: void 0,
3420
3619
  // can't know workflow telemetry here
3620
+ delay
3421
3621
  });
3422
3622
  if (result.isOk()) {
3423
3623
  return { workflowRunId: finalWorkflowRunId };