@upstash/workflow 0.2.12 → 0.2.14

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.14";
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");
@@ -150,6 +151,12 @@ var formatWorkflowError = (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)));
@@ -947,54 +611,72 @@ var StepTypes = [
947
611
 
948
612
  // src/workflow-requests.ts
949
613
  var import_qstash3 = require("@upstash/qstash");
950
- var triggerFirstInvocation = async ({
951
- workflowContext,
952
- useJSONContent,
953
- telemetry,
954
- debug,
955
- invokeCount
956
- }) => {
957
- const { headers } = getHeaders({
958
- 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
967
- });
968
- if (workflowContext.headers.get("content-type")) {
969
- headers["content-type"] = workflowContext.headers.get("content-type");
970
- }
971
- if (useJSONContent) {
972
- headers["content-type"] = "application/json";
973
- }
974
- try {
975
- const body = typeof workflowContext.requestPayload === "string" ? workflowContext.requestPayload : JSON.stringify(workflowContext.requestPayload);
976
- const result = await workflowContext.qstashClient.publish({
977
- headers,
978
- method: "POST",
979
- body,
980
- url: workflowContext.url
981
- });
982
- if (result.deduplicated) {
983
- await debug?.log("WARN", "SUBMIT_FIRST_INVOCATION", {
984
- message: `Workflow run ${workflowContext.workflowRunId} already exists. A new one isn't created.`,
614
+ var triggerFirstInvocation = async (params) => {
615
+ const firstInvocationParams = Array.isArray(params) ? params : [params];
616
+ const workflowContextClient = firstInvocationParams[0].workflowContext.qstashClient;
617
+ const invocationBatch = firstInvocationParams.map(
618
+ ({ workflowContext, useJSONContent, telemetry, invokeCount, delay }) => {
619
+ const { headers } = getHeaders({
620
+ initHeaderValue: "true",
621
+ workflowConfig: {
622
+ workflowRunId: workflowContext.workflowRunId,
623
+ workflowUrl: workflowContext.url,
624
+ failureUrl: workflowContext.failureUrl,
625
+ retries: workflowContext.retries,
626
+ telemetry,
627
+ flowControl: workflowContext.flowControl,
628
+ useJSONContent: useJSONContent ?? false
629
+ },
630
+ invokeCount: invokeCount ?? 0,
631
+ userHeaders: workflowContext.headers
632
+ });
633
+ if (workflowContext.headers.get("content-type")) {
634
+ headers["content-type"] = workflowContext.headers.get("content-type");
635
+ }
636
+ if (useJSONContent) {
637
+ headers["content-type"] = "application/json";
638
+ }
639
+ const body = typeof workflowContext.requestPayload === "string" ? workflowContext.requestPayload : JSON.stringify(workflowContext.requestPayload);
640
+ return {
985
641
  headers,
986
- requestPayload: workflowContext.requestPayload,
642
+ method: "POST",
643
+ body,
987
644
  url: workflowContext.url,
988
- messageId: result.messageId
989
- });
645
+ delay
646
+ };
647
+ }
648
+ );
649
+ try {
650
+ const results = await workflowContextClient.batch(invocationBatch);
651
+ const invocationStatuses = [];
652
+ for (let i = 0; i < results.length; i++) {
653
+ const result = results[i];
654
+ const invocationParams = firstInvocationParams[i];
655
+ if (result.deduplicated) {
656
+ await invocationParams.debug?.log("WARN", "SUBMIT_FIRST_INVOCATION", {
657
+ message: `Workflow run ${invocationParams.workflowContext.workflowRunId} already exists. A new one isn't created.`,
658
+ headers: invocationBatch[i].headers,
659
+ requestPayload: invocationParams.workflowContext.requestPayload,
660
+ url: invocationParams.workflowContext.url,
661
+ messageId: result.messageId
662
+ });
663
+ invocationStatuses.push("workflow-run-already-exists");
664
+ } else {
665
+ await invocationParams.debug?.log("SUBMIT", "SUBMIT_FIRST_INVOCATION", {
666
+ headers: invocationBatch[i].headers,
667
+ requestPayload: invocationParams.workflowContext.requestPayload,
668
+ url: invocationParams.workflowContext.url,
669
+ messageId: result.messageId
670
+ });
671
+ invocationStatuses.push("success");
672
+ }
673
+ }
674
+ const hasAnyDeduplicated = invocationStatuses.some(
675
+ (status) => status === "workflow-run-already-exists"
676
+ );
677
+ if (hasAnyDeduplicated) {
990
678
  return ok("workflow-run-already-exists");
991
679
  } else {
992
- await debug?.log("SUBMIT", "SUBMIT_FIRST_INVOCATION", {
993
- headers,
994
- requestPayload: workflowContext.requestPayload,
995
- url: workflowContext.url,
996
- messageId: result.messageId
997
- });
998
680
  return ok("success");
999
681
  }
1000
682
  } catch (error) {
@@ -1133,14 +815,16 @@ ${atob(callbackMessage.body ?? "")}`
1133
815
  const userHeaders = recreateUserHeaders(request.headers);
1134
816
  const { headers: requestHeaders } = getHeaders({
1135
817
  initHeaderValue: "false",
1136
- workflowRunId,
1137
- workflowUrl,
818
+ workflowConfig: {
819
+ workflowRunId,
820
+ workflowUrl,
821
+ failureUrl,
822
+ retries,
823
+ telemetry,
824
+ flowControl
825
+ },
1138
826
  userHeaders,
1139
- failureUrl,
1140
- retries,
1141
- telemetry,
1142
- invokeCount: Number(invokeCount),
1143
- flowControl
827
+ invokeCount: Number(invokeCount)
1144
828
  });
1145
829
  const callResponse = {
1146
830
  status: callbackMessage.status,
@@ -1172,282 +856,913 @@ ${atob(callbackMessage.body ?? "")}`
1172
856
  } else {
1173
857
  return ok("continue-workflow");
1174
858
  }
1175
- } catch (error) {
1176
- const isCallReturn = request.headers.get("Upstash-Workflow-Callback");
1177
- return err(
1178
- new WorkflowError(`Error when handling call return (isCallReturn=${isCallReturn}): ${error}`)
1179
- );
859
+ } catch (error) {
860
+ const isCallReturn = request.headers.get("Upstash-Workflow-Callback");
861
+ return err(
862
+ new WorkflowError(`Error when handling call return (isCallReturn=${isCallReturn}): ${error}`)
863
+ );
864
+ }
865
+ };
866
+ var getTelemetryHeaders = (telemetry) => {
867
+ return {
868
+ [TELEMETRY_HEADER_SDK]: telemetry.sdk,
869
+ [TELEMETRY_HEADER_FRAMEWORK]: telemetry.framework,
870
+ [TELEMETRY_HEADER_RUNTIME]: telemetry.runtime ?? "unknown"
871
+ };
872
+ };
873
+ var verifyRequest = async (body, signature, verifier) => {
874
+ if (!verifier) {
875
+ return;
876
+ }
877
+ try {
878
+ if (!signature) {
879
+ throw new Error("`Upstash-Signature` header is not passed.");
880
+ }
881
+ const isValid = await verifier.verify({
882
+ body,
883
+ signature
884
+ });
885
+ if (!isValid) {
886
+ throw new Error("Signature in `Upstash-Signature` header is not valid");
887
+ }
888
+ } catch (error) {
889
+ throw new WorkflowError(
890
+ `Failed to verify that the Workflow request comes from QStash: ${error}
891
+
892
+ If signature is missing, trigger the workflow endpoint by publishing your request to QStash instead of calling it directly.
893
+
894
+ If you want to disable QStash Verification, you should clear env variables QSTASH_CURRENT_SIGNING_KEY and QSTASH_NEXT_SIGNING_KEY`
895
+ );
896
+ }
897
+ };
898
+
899
+ // src/context/steps.ts
900
+ var BaseLazyStep = class _BaseLazyStep {
901
+ stepName;
902
+ constructor(stepName) {
903
+ if (!stepName) {
904
+ throw new WorkflowError(
905
+ "A workflow step name cannot be undefined or an empty string. Please provide a name for your workflow step."
906
+ );
907
+ }
908
+ if (typeof stepName !== "string") {
909
+ console.warn(
910
+ "Workflow Warning: A workflow step name must be a string. In a future release, this will throw an error."
911
+ );
912
+ }
913
+ this.stepName = stepName;
914
+ }
915
+ /**
916
+ * parse the out field of a step result.
917
+ *
918
+ * will be called when returning the steps to the context from auto executor
919
+ *
920
+ * @param out field of the step
921
+ * @returns parsed out field
922
+ */
923
+ parseOut(out) {
924
+ if (out === void 0) {
925
+ if (this.allowUndefinedOut) {
926
+ return void 0;
927
+ } else {
928
+ throw new WorkflowError(
929
+ `Error while parsing output of ${this.stepType} step. Expected a string, but got: undefined`
930
+ );
931
+ }
932
+ }
933
+ if (typeof out === "object") {
934
+ if (this.stepType !== "Wait") {
935
+ console.warn(
936
+ `Error while parsing ${this.stepType} step output. Expected a string, but got object. Please reach out to Upstash Support.`
937
+ );
938
+ return out;
939
+ }
940
+ return {
941
+ ...out,
942
+ eventData: _BaseLazyStep.tryParsing(out.eventData)
943
+ };
944
+ }
945
+ if (typeof out !== "string") {
946
+ throw new WorkflowError(
947
+ `Error while parsing output of ${this.stepType} step. Expected a string or undefined, but got: ${typeof out}`
948
+ );
949
+ }
950
+ return this.safeParseOut(out);
951
+ }
952
+ safeParseOut(out) {
953
+ return _BaseLazyStep.tryParsing(out);
954
+ }
955
+ static tryParsing(stepOut) {
956
+ try {
957
+ return JSON.parse(stepOut);
958
+ } catch {
959
+ return stepOut;
960
+ }
961
+ }
962
+ getBody({ step }) {
963
+ step.out = JSON.stringify(step.out);
964
+ return JSON.stringify(step);
965
+ }
966
+ getHeaders({ context, telemetry, invokeCount, step }) {
967
+ return getHeaders({
968
+ initHeaderValue: "false",
969
+ workflowConfig: {
970
+ workflowRunId: context.workflowRunId,
971
+ workflowUrl: context.url,
972
+ failureUrl: context.failureUrl,
973
+ retries: context.retries,
974
+ useJSONContent: false,
975
+ telemetry,
976
+ flowControl: context.flowControl
977
+ },
978
+ userHeaders: context.headers,
979
+ invokeCount,
980
+ stepInfo: {
981
+ step,
982
+ lazyStep: this
983
+ }
984
+ });
985
+ }
986
+ async submitStep({ context, body, headers }) {
987
+ return await context.qstashClient.batch([
988
+ {
989
+ body,
990
+ headers,
991
+ method: "POST",
992
+ url: context.url
993
+ }
994
+ ]);
995
+ }
996
+ };
997
+ var LazyFunctionStep = class extends BaseLazyStep {
998
+ stepFunction;
999
+ stepType = "Run";
1000
+ allowUndefinedOut = true;
1001
+ constructor(stepName, stepFunction) {
1002
+ super(stepName);
1003
+ this.stepFunction = stepFunction;
1004
+ }
1005
+ getPlanStep(concurrent, targetStep) {
1006
+ return {
1007
+ stepId: 0,
1008
+ stepName: this.stepName,
1009
+ stepType: this.stepType,
1010
+ concurrent,
1011
+ targetStep
1012
+ };
1013
+ }
1014
+ async getResultStep(concurrent, stepId) {
1015
+ let result = this.stepFunction();
1016
+ if (result instanceof Promise) {
1017
+ result = await result;
1018
+ }
1019
+ return {
1020
+ stepId,
1021
+ stepName: this.stepName,
1022
+ stepType: this.stepType,
1023
+ out: result,
1024
+ concurrent
1025
+ };
1026
+ }
1027
+ };
1028
+ var LazySleepStep = class extends BaseLazyStep {
1029
+ sleep;
1030
+ stepType = "SleepFor";
1031
+ allowUndefinedOut = true;
1032
+ constructor(stepName, sleep) {
1033
+ super(stepName);
1034
+ this.sleep = sleep;
1035
+ }
1036
+ getPlanStep(concurrent, targetStep) {
1037
+ return {
1038
+ stepId: 0,
1039
+ stepName: this.stepName,
1040
+ stepType: this.stepType,
1041
+ sleepFor: this.sleep,
1042
+ concurrent,
1043
+ targetStep
1044
+ };
1045
+ }
1046
+ async getResultStep(concurrent, stepId) {
1047
+ return await Promise.resolve({
1048
+ stepId,
1049
+ stepName: this.stepName,
1050
+ stepType: this.stepType,
1051
+ sleepFor: this.sleep,
1052
+ concurrent
1053
+ });
1054
+ }
1055
+ async submitStep({ context, body, headers, isParallel }) {
1056
+ return await context.qstashClient.batch([
1057
+ {
1058
+ body,
1059
+ headers,
1060
+ method: "POST",
1061
+ url: context.url,
1062
+ delay: isParallel ? void 0 : this.sleep
1063
+ }
1064
+ ]);
1065
+ }
1066
+ };
1067
+ var LazySleepUntilStep = class extends BaseLazyStep {
1068
+ sleepUntil;
1069
+ stepType = "SleepUntil";
1070
+ allowUndefinedOut = true;
1071
+ constructor(stepName, sleepUntil) {
1072
+ super(stepName);
1073
+ this.sleepUntil = sleepUntil;
1074
+ }
1075
+ getPlanStep(concurrent, targetStep) {
1076
+ return {
1077
+ stepId: 0,
1078
+ stepName: this.stepName,
1079
+ stepType: this.stepType,
1080
+ sleepUntil: this.sleepUntil,
1081
+ concurrent,
1082
+ targetStep
1083
+ };
1084
+ }
1085
+ async getResultStep(concurrent, stepId) {
1086
+ return await Promise.resolve({
1087
+ stepId,
1088
+ stepName: this.stepName,
1089
+ stepType: this.stepType,
1090
+ sleepUntil: this.sleepUntil,
1091
+ concurrent
1092
+ });
1093
+ }
1094
+ safeParseOut() {
1095
+ return void 0;
1096
+ }
1097
+ async submitStep({ context, body, headers, isParallel }) {
1098
+ return await context.qstashClient.batch([
1099
+ {
1100
+ body,
1101
+ headers,
1102
+ method: "POST",
1103
+ url: context.url,
1104
+ notBefore: isParallel ? void 0 : this.sleepUntil
1105
+ }
1106
+ ]);
1107
+ }
1108
+ };
1109
+ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
1110
+ url;
1111
+ method;
1112
+ body;
1113
+ headers;
1114
+ retries;
1115
+ timeout;
1116
+ flowControl;
1117
+ stepType = "Call";
1118
+ allowUndefinedOut = false;
1119
+ constructor(stepName, url, method, body, headers, retries, timeout, flowControl) {
1120
+ super(stepName);
1121
+ this.url = url;
1122
+ this.method = method;
1123
+ this.body = body;
1124
+ this.headers = headers;
1125
+ this.retries = retries;
1126
+ this.timeout = timeout;
1127
+ this.flowControl = flowControl;
1128
+ }
1129
+ getPlanStep(concurrent, targetStep) {
1130
+ return {
1131
+ stepId: 0,
1132
+ stepName: this.stepName,
1133
+ stepType: this.stepType,
1134
+ concurrent,
1135
+ targetStep
1136
+ };
1137
+ }
1138
+ async getResultStep(concurrent, stepId) {
1139
+ return await Promise.resolve({
1140
+ stepId,
1141
+ stepName: this.stepName,
1142
+ stepType: this.stepType,
1143
+ concurrent,
1144
+ callUrl: this.url,
1145
+ callMethod: this.method,
1146
+ callBody: this.body,
1147
+ callHeaders: this.headers
1148
+ });
1149
+ }
1150
+ safeParseOut(out) {
1151
+ const { header, status, body } = JSON.parse(out);
1152
+ const responseHeaders = new Headers(header);
1153
+ if (_LazyCallStep.isText(responseHeaders.get("content-type"))) {
1154
+ const bytes = new Uint8Array(out.length);
1155
+ for (let i = 0; i < out.length; i++) {
1156
+ bytes[i] = out.charCodeAt(i);
1157
+ }
1158
+ const processedResult = new TextDecoder().decode(bytes);
1159
+ const newBody = JSON.parse(processedResult).body;
1160
+ return {
1161
+ status,
1162
+ header,
1163
+ body: BaseLazyStep.tryParsing(newBody)
1164
+ };
1165
+ } else {
1166
+ return { header, status, body };
1167
+ }
1168
+ }
1169
+ static applicationContentTypes = [
1170
+ "application/json",
1171
+ "application/xml",
1172
+ "application/javascript",
1173
+ "application/x-www-form-urlencoded",
1174
+ "application/xhtml+xml",
1175
+ "application/ld+json",
1176
+ "application/rss+xml",
1177
+ "application/atom+xml"
1178
+ ];
1179
+ static isText = (contentTypeHeader) => {
1180
+ if (!contentTypeHeader) {
1181
+ return false;
1182
+ }
1183
+ if (_LazyCallStep.applicationContentTypes.some((type) => contentTypeHeader.includes(type))) {
1184
+ return true;
1185
+ }
1186
+ if (contentTypeHeader.startsWith("text/")) {
1187
+ return true;
1188
+ }
1189
+ return false;
1190
+ };
1191
+ getBody({ step }) {
1192
+ if (!step.callUrl) {
1193
+ throw new WorkflowError("Incompatible step received in LazyCallStep.getBody");
1194
+ }
1195
+ return JSON.stringify(step.callBody);
1196
+ }
1197
+ getHeaders({ context, telemetry, invokeCount, step }) {
1198
+ const { headers, contentType } = super.getHeaders({ context, telemetry, invokeCount, step });
1199
+ headers["Upstash-Retries"] = this.retries.toString();
1200
+ headers[WORKFLOW_FEATURE_HEADER] = "WF_NoDelete,InitialBody";
1201
+ if (this.flowControl) {
1202
+ const { flowControlKey, flowControlValue } = prepareFlowControl(this.flowControl);
1203
+ headers["Upstash-Flow-Control-Key"] = flowControlKey;
1204
+ headers["Upstash-Flow-Control-Value"] = flowControlValue;
1205
+ }
1206
+ if (this.timeout) {
1207
+ headers["Upstash-Timeout"] = this.timeout.toString();
1208
+ }
1209
+ const forwardedHeaders = Object.fromEntries(
1210
+ Object.entries(this.headers).map(([header, value]) => [`Upstash-Forward-${header}`, value])
1211
+ );
1212
+ return {
1213
+ headers: {
1214
+ ...headers,
1215
+ ...forwardedHeaders,
1216
+ "Upstash-Callback": context.url,
1217
+ "Upstash-Callback-Workflow-RunId": context.workflowRunId,
1218
+ "Upstash-Callback-Workflow-CallType": "fromCallback",
1219
+ "Upstash-Callback-Workflow-Init": "false",
1220
+ "Upstash-Callback-Workflow-Url": context.url,
1221
+ "Upstash-Callback-Feature-Set": "LazyFetch,InitialBody",
1222
+ "Upstash-Callback-Forward-Upstash-Workflow-Callback": "true",
1223
+ "Upstash-Callback-Forward-Upstash-Workflow-StepId": step.stepId.toString(),
1224
+ "Upstash-Callback-Forward-Upstash-Workflow-StepName": this.stepName,
1225
+ "Upstash-Callback-Forward-Upstash-Workflow-StepType": this.stepType,
1226
+ "Upstash-Callback-Forward-Upstash-Workflow-Concurrent": step.concurrent.toString(),
1227
+ "Upstash-Callback-Forward-Upstash-Workflow-ContentType": contentType,
1228
+ "Upstash-Workflow-CallType": "toCallback"
1229
+ },
1230
+ contentType
1231
+ };
1232
+ }
1233
+ async submitStep({ context, headers }) {
1234
+ return await context.qstashClient.batch([
1235
+ {
1236
+ headers,
1237
+ body: JSON.stringify(this.body),
1238
+ method: this.method,
1239
+ url: this.url
1240
+ }
1241
+ ]);
1242
+ }
1243
+ };
1244
+ var LazyWaitForEventStep = class extends BaseLazyStep {
1245
+ eventId;
1246
+ timeout;
1247
+ stepType = "Wait";
1248
+ allowUndefinedOut = false;
1249
+ constructor(stepName, eventId, timeout) {
1250
+ super(stepName);
1251
+ this.eventId = eventId;
1252
+ this.timeout = timeout;
1253
+ }
1254
+ getPlanStep(concurrent, targetStep) {
1255
+ return {
1256
+ stepId: 0,
1257
+ stepName: this.stepName,
1258
+ stepType: this.stepType,
1259
+ waitEventId: this.eventId,
1260
+ timeout: this.timeout,
1261
+ concurrent,
1262
+ targetStep
1263
+ };
1264
+ }
1265
+ async getResultStep(concurrent, stepId) {
1266
+ return await Promise.resolve({
1267
+ stepId,
1268
+ stepName: this.stepName,
1269
+ stepType: this.stepType,
1270
+ waitEventId: this.eventId,
1271
+ timeout: this.timeout,
1272
+ concurrent
1273
+ });
1274
+ }
1275
+ safeParseOut(out) {
1276
+ const result = JSON.parse(out);
1277
+ return {
1278
+ ...result,
1279
+ eventData: BaseLazyStep.tryParsing(result.eventData)
1280
+ };
1281
+ }
1282
+ getHeaders({ context, telemetry, invokeCount, step }) {
1283
+ const headers = super.getHeaders({ context, telemetry, invokeCount, step });
1284
+ headers.headers["Upstash-Workflow-CallType"] = "step";
1285
+ return headers;
1286
+ }
1287
+ getBody({ context, step, headers, telemetry }) {
1288
+ if (!step.waitEventId) {
1289
+ throw new WorkflowError("Incompatible step received in LazyWaitForEventStep.getBody");
1290
+ }
1291
+ const timeoutHeaders = {
1292
+ // to include user headers:
1293
+ ...Object.fromEntries(Object.entries(headers).map(([header, value]) => [header, [value]])),
1294
+ // to include telemetry headers:
1295
+ ...telemetry ? Object.fromEntries(
1296
+ Object.entries(getTelemetryHeaders(telemetry)).map(([header, value]) => [
1297
+ header,
1298
+ [value]
1299
+ ])
1300
+ ) : {},
1301
+ // note: using WORKFLOW_ID_HEADER doesn't work, because Runid -> RunId:
1302
+ "Upstash-Workflow-Runid": [context.workflowRunId],
1303
+ [WORKFLOW_INIT_HEADER]: ["false"],
1304
+ [WORKFLOW_URL_HEADER]: [context.url],
1305
+ "Upstash-Workflow-CallType": ["step"]
1306
+ };
1307
+ const waitBody = {
1308
+ url: context.url,
1309
+ timeout: step.timeout,
1310
+ timeoutBody: void 0,
1311
+ timeoutUrl: context.url,
1312
+ timeoutHeaders,
1313
+ step: {
1314
+ stepId: step.stepId,
1315
+ stepType: "Wait",
1316
+ stepName: step.stepName,
1317
+ concurrent: step.concurrent,
1318
+ targetStep: step.targetStep
1319
+ }
1320
+ };
1321
+ return JSON.stringify(waitBody);
1322
+ }
1323
+ async submitStep({ context, body, headers }) {
1324
+ const result = await context.qstashClient.http.request({
1325
+ path: ["v2", "wait", this.eventId],
1326
+ body,
1327
+ headers,
1328
+ method: "POST",
1329
+ parseResponseAsJson: false
1330
+ });
1331
+ return [result];
1332
+ }
1333
+ };
1334
+ var LazyNotifyStep = class extends LazyFunctionStep {
1335
+ stepType = "Notify";
1336
+ constructor(stepName, eventId, eventData, requester) {
1337
+ super(stepName, async () => {
1338
+ const notifyResponse = await makeNotifyRequest(requester, eventId, eventData);
1339
+ return {
1340
+ eventId,
1341
+ eventData,
1342
+ notifyResponse
1343
+ };
1344
+ });
1345
+ }
1346
+ safeParseOut(out) {
1347
+ const result = JSON.parse(out);
1348
+ return {
1349
+ ...result,
1350
+ eventData: BaseLazyStep.tryParsing(result.eventData)
1351
+ };
1352
+ }
1353
+ };
1354
+ var LazyInvokeStep = class extends BaseLazyStep {
1355
+ stepType = "Invoke";
1356
+ params;
1357
+ allowUndefinedOut = false;
1358
+ /**
1359
+ * workflow id of the invoked workflow
1360
+ */
1361
+ workflowId;
1362
+ constructor(stepName, {
1363
+ workflow,
1364
+ body,
1365
+ headers = {},
1366
+ workflowRunId,
1367
+ retries,
1368
+ flowControl
1369
+ }) {
1370
+ super(stepName);
1371
+ this.params = {
1372
+ workflow,
1373
+ body,
1374
+ headers,
1375
+ workflowRunId: getWorkflowRunId(workflowRunId),
1376
+ retries,
1377
+ flowControl
1378
+ };
1379
+ const { workflowId } = workflow;
1380
+ if (!workflowId) {
1381
+ throw new WorkflowError("You can only invoke workflow which has a workflowId");
1382
+ }
1383
+ this.workflowId = workflowId;
1384
+ }
1385
+ getPlanStep(concurrent, targetStep) {
1386
+ return {
1387
+ stepId: 0,
1388
+ stepName: this.stepName,
1389
+ stepType: this.stepType,
1390
+ concurrent,
1391
+ targetStep
1392
+ };
1393
+ }
1394
+ /**
1395
+ * won't be used as it's the server who will add the result step
1396
+ * in Invoke step.
1397
+ */
1398
+ getResultStep(concurrent, stepId) {
1399
+ return Promise.resolve({
1400
+ stepId,
1401
+ stepName: this.stepName,
1402
+ stepType: this.stepType,
1403
+ concurrent
1404
+ });
1405
+ }
1406
+ safeParseOut(out) {
1407
+ const result = JSON.parse(out);
1408
+ return {
1409
+ ...result,
1410
+ body: BaseLazyStep.tryParsing(result.body)
1411
+ };
1412
+ }
1413
+ getBody({ context, step, telemetry, invokeCount }) {
1414
+ const { headers: invokerHeaders } = getHeaders({
1415
+ initHeaderValue: "false",
1416
+ workflowConfig: {
1417
+ workflowRunId: context.workflowRunId,
1418
+ workflowUrl: context.url,
1419
+ failureUrl: context.failureUrl,
1420
+ retries: context.retries,
1421
+ telemetry,
1422
+ flowControl: context.flowControl,
1423
+ useJSONContent: false
1424
+ },
1425
+ userHeaders: context.headers,
1426
+ invokeCount
1427
+ });
1428
+ invokerHeaders["Upstash-Workflow-Runid"] = context.workflowRunId;
1429
+ const request = {
1430
+ body: JSON.stringify(this.params.body),
1431
+ headers: Object.fromEntries(
1432
+ Object.entries(invokerHeaders).map((pairs) => [pairs[0], [pairs[1]]])
1433
+ ),
1434
+ workflowRunId: context.workflowRunId,
1435
+ workflowUrl: context.url,
1436
+ step
1437
+ };
1438
+ return JSON.stringify(request);
1439
+ }
1440
+ getHeaders({ context, telemetry, invokeCount }) {
1441
+ const {
1442
+ workflow,
1443
+ headers = {},
1444
+ workflowRunId = getWorkflowRunId(),
1445
+ retries,
1446
+ flowControl
1447
+ } = this.params;
1448
+ const newUrl = context.url.replace(/[^/]+$/, this.workflowId);
1449
+ const {
1450
+ retries: workflowRetries,
1451
+ failureFunction,
1452
+ failureUrl,
1453
+ useJSONContent,
1454
+ flowControl: workflowFlowControl
1455
+ } = workflow.options;
1456
+ const { headers: triggerHeaders, contentType } = getHeaders({
1457
+ initHeaderValue: "true",
1458
+ workflowConfig: {
1459
+ workflowRunId,
1460
+ workflowUrl: newUrl,
1461
+ retries: retries ?? workflowRetries,
1462
+ telemetry,
1463
+ failureUrl: failureFunction ? newUrl : failureUrl,
1464
+ flowControl: flowControl ?? workflowFlowControl,
1465
+ useJSONContent: useJSONContent ?? false
1466
+ },
1467
+ invokeCount: invokeCount + 1,
1468
+ userHeaders: new Headers(headers)
1469
+ });
1470
+ triggerHeaders["Upstash-Workflow-Invoke"] = "true";
1471
+ return { headers: triggerHeaders, contentType };
1472
+ }
1473
+ async submitStep({ context, body, headers }) {
1474
+ const newUrl = context.url.replace(/[^/]+$/, this.workflowId);
1475
+ const result = await context.qstashClient.publish({
1476
+ headers,
1477
+ method: "POST",
1478
+ body,
1479
+ url: newUrl
1480
+ });
1481
+ return [result];
1482
+ }
1483
+ };
1484
+
1485
+ // src/agents/constants.ts
1486
+ var AGENT_NAME_HEADER = "upstash-agent-name";
1487
+ var MANAGER_AGENT_PROMPT = `You are an agent orchestrating other AI Agents.
1488
+
1489
+ These other agents have tools available to them.
1490
+
1491
+ Given a prompt, utilize these agents to address requests.
1492
+
1493
+ 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.
1494
+
1495
+ Avoid calling the same agent twice in one turn. Instead, prefer to call it once but provide everything
1496
+ you need from that agent.
1497
+ `;
1498
+
1499
+ // src/qstash/headers.ts
1500
+ var WorkflowHeaders = class {
1501
+ userHeaders;
1502
+ workflowConfig;
1503
+ invokeCount;
1504
+ initHeaderValue;
1505
+ stepInfo;
1506
+ headers;
1507
+ constructor({
1508
+ userHeaders,
1509
+ workflowConfig,
1510
+ invokeCount,
1511
+ initHeaderValue,
1512
+ stepInfo
1513
+ }) {
1514
+ this.userHeaders = userHeaders;
1515
+ this.workflowConfig = workflowConfig;
1516
+ this.invokeCount = invokeCount;
1517
+ this.initHeaderValue = initHeaderValue;
1518
+ this.stepInfo = stepInfo;
1519
+ this.headers = {
1520
+ rawHeaders: {},
1521
+ workflowHeaders: {},
1522
+ failureHeaders: {}
1523
+ };
1524
+ }
1525
+ getHeaders() {
1526
+ this.addBaseHeaders();
1527
+ this.addRetries();
1528
+ this.addFlowControl();
1529
+ this.addUserHeaders();
1530
+ this.addInvokeCount();
1531
+ this.addFailureUrl();
1532
+ const contentType = this.addContentType();
1533
+ return this.prefixHeaders(contentType);
1534
+ }
1535
+ addBaseHeaders() {
1536
+ this.headers.rawHeaders = {
1537
+ ...this.headers.rawHeaders,
1538
+ [WORKFLOW_INIT_HEADER]: this.initHeaderValue,
1539
+ [WORKFLOW_ID_HEADER]: this.workflowConfig.workflowRunId,
1540
+ [WORKFLOW_URL_HEADER]: this.workflowConfig.workflowUrl,
1541
+ [WORKFLOW_FEATURE_HEADER]: "LazyFetch,InitialBody",
1542
+ [WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION,
1543
+ ...this.workflowConfig.telemetry ? getTelemetryHeaders(this.workflowConfig.telemetry) : {},
1544
+ ...this.workflowConfig.telemetry && this.stepInfo?.lazyStep instanceof LazyCallStep && this.stepInfo.lazyStep.headers[AGENT_NAME_HEADER] ? { [TELEMETRY_HEADER_AGENT]: "true" } : {}
1545
+ };
1546
+ if (this.stepInfo?.lazyStep.stepType !== "Call") {
1547
+ this.headers.rawHeaders[`Upstash-Forward-${WORKFLOW_PROTOCOL_VERSION_HEADER}`] = WORKFLOW_PROTOCOL_VERSION;
1548
+ }
1180
1549
  }
1181
- };
1182
- var getTelemetryHeaders = (telemetry) => {
1183
- return {
1184
- [TELEMETRY_HEADER_SDK]: telemetry.sdk,
1185
- [TELEMETRY_HEADER_FRAMEWORK]: telemetry.framework,
1186
- [TELEMETRY_HEADER_RUNTIME]: telemetry.runtime ?? "unknown"
1187
- };
1188
- };
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;
1550
+ addInvokeCount() {
1551
+ if (this.invokeCount === void 0 || this.invokeCount === 0) {
1552
+ return;
1259
1553
  }
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;
1554
+ const invokeCount = this.invokeCount.toString();
1555
+ this.headers.workflowHeaders[`Forward-${WORKFLOW_INVOKE_COUNT_HEADER}`] = invokeCount;
1556
+ if (this.workflowConfig.failureUrl) {
1557
+ this.headers.failureHeaders[`Forward-${WORKFLOW_INVOKE_COUNT_HEADER}`] = invokeCount;
1265
1558
  }
1266
- if (retries !== void 0) {
1267
- baseHeaders["Upstash-Retries"] = retries.toString();
1268
- baseHeaders["Upstash-Failure-Callback-Retries"] = retries.toString();
1559
+ if (this.stepInfo?.lazyStep instanceof LazyCallStep) {
1560
+ this.headers.rawHeaders[`Upstash-Forward-${WORKFLOW_INVOKE_COUNT_HEADER}`] = invokeCount;
1269
1561
  }
1270
1562
  }
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);
1563
+ addRetries() {
1564
+ if (this.workflowConfig.retries === void 0 || this.workflowConfig.retries === DEFAULT_RETRIES) {
1565
+ return;
1566
+ }
1567
+ const retries = this.workflowConfig.retries.toString();
1568
+ this.headers.workflowHeaders["Retries"] = retries;
1569
+ if (this.workflowConfig.failureUrl) {
1570
+ this.headers.failureHeaders["Retries"] = retries;
1279
1571
  }
1280
1572
  }
1281
- if (step?.callHeaders) {
1282
- const forwardedHeaders = Object.fromEntries(
1283
- Object.entries(step.callHeaders).map(([header, value]) => [
1284
- `Upstash-Forward-${header}`,
1285
- value
1286
- ])
1573
+ addFlowControl() {
1574
+ if (!this.workflowConfig.flowControl) {
1575
+ return;
1576
+ }
1577
+ const { flowControlKey, flowControlValue } = prepareFlowControl(
1578
+ this.workflowConfig.flowControl
1287
1579
  );
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"
1580
+ this.headers.workflowHeaders["Flow-Control-Key"] = flowControlKey;
1581
+ this.headers.workflowHeaders["Flow-Control-Value"] = flowControlValue;
1582
+ if (this.workflowConfig.failureUrl) {
1583
+ this.headers.failureHeaders["Flow-Control-Key"] = flowControlKey;
1584
+ this.headers.failureHeaders["Flow-Control-Value"] = flowControlValue;
1585
+ }
1586
+ }
1587
+ addUserHeaders() {
1588
+ for (const [key, value] of this.userHeaders.entries()) {
1589
+ const forwardKey = `Forward-${key}`;
1590
+ this.headers.workflowHeaders[forwardKey] = value;
1591
+ if (this.workflowConfig.failureUrl) {
1592
+ this.headers.failureHeaders[forwardKey] = value;
1306
1593
  }
1307
- };
1594
+ }
1595
+ }
1596
+ addFailureUrl() {
1597
+ if (!this.workflowConfig.failureUrl) {
1598
+ return;
1599
+ }
1600
+ this.headers.workflowHeaders["Failure-Callback"] = this.workflowConfig.failureUrl;
1601
+ this.headers.failureHeaders[`Forward-${WORKFLOW_FAILURE_HEADER}`] = "true";
1602
+ this.headers.failureHeaders[`Forward-Upstash-Workflow-Failure-Callback`] = "true";
1603
+ this.headers.failureHeaders["Workflow-Runid"] = this.workflowConfig.workflowRunId;
1604
+ this.headers.failureHeaders["Workflow-Init"] = "false";
1605
+ this.headers.failureHeaders["Workflow-Url"] = this.workflowConfig.workflowUrl;
1606
+ this.headers.failureHeaders["Workflow-Calltype"] = "failureCall";
1607
+ this.headers.failureHeaders["Feature-Set"] = "LazyFetch,InitialBody";
1608
+ if (this.workflowConfig.retries !== void 0 && this.workflowConfig.retries !== DEFAULT_RETRIES) {
1609
+ this.headers.failureHeaders["Retries"] = this.workflowConfig.retries.toString();
1610
+ }
1611
+ }
1612
+ addContentType() {
1613
+ if (this.workflowConfig.useJSONContent) {
1614
+ this.headers.rawHeaders["content-type"] = "application/json";
1615
+ return "application/json";
1616
+ }
1617
+ const callHeaders = new Headers(
1618
+ this.stepInfo?.lazyStep instanceof LazyCallStep ? this.stepInfo.lazyStep.headers : {}
1619
+ );
1620
+ 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;
1621
+ this.headers.rawHeaders["content-type"] = contentType;
1622
+ return contentType;
1308
1623
  }
1309
- if (step?.waitEventId) {
1624
+ prefixHeaders(contentType) {
1625
+ const { rawHeaders, workflowHeaders, failureHeaders } = this.headers;
1626
+ const isCall = this.stepInfo?.lazyStep.stepType === "Call";
1310
1627
  return {
1311
1628
  headers: {
1312
- ...baseHeaders,
1313
- "Upstash-Workflow-CallType": "step"
1629
+ ...rawHeaders,
1630
+ ...addPrefixToHeaders(workflowHeaders, isCall ? "Upstash-Callback-" : "Upstash-"),
1631
+ ...addPrefixToHeaders(failureHeaders, "Upstash-Failure-Callback-"),
1632
+ ...isCall ? addPrefixToHeaders(failureHeaders, "Upstash-Callback-Failure-Callback-") : {}
1314
1633
  },
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
- }
1634
+ contentType
1333
1635
  };
1334
1636
  }
1335
- return { headers: baseHeaders };
1336
1637
  };
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
- );
1638
+ function addPrefixToHeaders(headers, prefix) {
1639
+ const prefixedHeaders = {};
1640
+ for (const [key, value] of Object.entries(headers)) {
1641
+ prefixedHeaders[`${prefix}${key}`] = value;
1360
1642
  }
1361
- };
1643
+ return prefixedHeaders;
1644
+ }
1362
1645
  var prepareFlowControl = (flowControl) => {
1363
1646
  const parallelism = flowControl.parallelism?.toString();
1364
- const rate = flowControl.ratePerSecond?.toString();
1647
+ const rate = (flowControl.rate ?? flowControl.ratePerSecond)?.toString();
1648
+ const period = typeof flowControl.period === "number" ? `${flowControl.period}s` : flowControl.period;
1365
1649
  const controlValue = [
1366
1650
  parallelism ? `parallelism=${parallelism}` : void 0,
1367
- rate ? `rate=${rate}` : void 0
1651
+ rate ? `rate=${rate}` : void 0,
1652
+ period ? `period=${period}` : void 0
1368
1653
  ].filter(Boolean);
1369
1654
  if (controlValue.length === 0) {
1370
- throw new import_qstash3.QstashError("Provide at least one of parallelism or ratePerSecond for flowControl");
1655
+ throw new import_qstash4.QstashError("Provide at least one of parallelism or ratePerSecond for flowControl");
1371
1656
  }
1372
1657
  return {
1373
1658
  flowControlKey: flowControl.key,
1374
1659
  flowControlValue: controlValue.join(", ")
1375
1660
  };
1376
1661
  };
1662
+ var getHeaders = (params) => {
1663
+ const workflowHeaders = new WorkflowHeaders(params);
1664
+ return workflowHeaders.getHeaders();
1665
+ };
1377
1666
 
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,
1667
+ // src/qstash/submit-steps.ts
1668
+ var submitParallelSteps = async ({
1385
1669
  context,
1670
+ steps,
1671
+ initialStepCount,
1386
1672
  invokeCount,
1387
- telemetry
1673
+ telemetry,
1674
+ debug
1388
1675
  }) => {
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,
1676
+ const planSteps = steps.map(
1677
+ (step, index) => step.getPlanStep(steps.length, initialStepCount + index)
1678
+ );
1679
+ await debug?.log("SUBMIT", "SUBMIT_STEP", {
1680
+ length: planSteps.length,
1681
+ steps: planSteps
1682
+ });
1683
+ const result = await context.qstashClient.batch(
1684
+ planSteps.map((planStep) => {
1685
+ const { headers } = getHeaders({
1686
+ initHeaderValue: "false",
1687
+ workflowConfig: {
1688
+ workflowRunId: context.workflowRunId,
1689
+ workflowUrl: context.url,
1690
+ failureUrl: context.failureUrl,
1691
+ retries: context.retries,
1692
+ flowControl: context.flowControl,
1693
+ telemetry
1694
+ },
1695
+ userHeaders: context.headers,
1696
+ invokeCount
1697
+ });
1698
+ return {
1699
+ headers,
1700
+ method: "POST",
1701
+ url: context.url,
1702
+ body: JSON.stringify(planStep),
1703
+ notBefore: planStep.sleepUntil,
1704
+ delay: planStep.sleepFor
1705
+ };
1706
+ })
1707
+ );
1708
+ await debug?.log("INFO", "SUBMIT_STEP", {
1709
+ messageIds: result.map((message) => {
1710
+ return {
1711
+ message: message.messageId
1712
+ };
1713
+ })
1714
+ });
1715
+ throw new WorkflowAbort(planSteps[0].stepName, planSteps[0]);
1716
+ };
1717
+ var submitSingleStep = async ({
1718
+ context,
1719
+ lazyStep,
1720
+ stepId,
1721
+ invokeCount,
1722
+ concurrency,
1723
+ telemetry,
1724
+ debug
1725
+ }) => {
1726
+ const resultStep = await lazyStep.getResultStep(concurrency, stepId);
1727
+ await debug?.log("INFO", "RUN_SINGLE", {
1728
+ fromRequest: false,
1729
+ step: resultStep,
1730
+ stepCount: stepId
1731
+ });
1732
+ const { headers } = lazyStep.getHeaders({
1733
+ context,
1734
+ step: resultStep,
1416
1735
  invokeCount,
1417
- flowControl: context.flowControl
1736
+ telemetry
1418
1737
  });
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
1738
+ const body = lazyStep.getBody({
1739
+ context,
1740
+ step: resultStep,
1741
+ headers,
1742
+ invokeCount,
1743
+ telemetry
1431
1744
  });
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
1745
+ await debug?.log("SUBMIT", "SUBMIT_STEP", {
1746
+ length: 1,
1747
+ steps: [resultStep]
1748
+ });
1749
+ const submitResult = await lazyStep.submitStep({
1750
+ context,
1751
+ body,
1752
+ headers,
1753
+ isParallel: concurrency !== NO_CONCURRENCY,
1754
+ invokeCount,
1755
+ step: resultStep,
1756
+ telemetry
1757
+ });
1758
+ await debug?.log("INFO", "SUBMIT_STEP", {
1759
+ messageIds: submitResult.map((message) => {
1760
+ return {
1761
+ message: message.messageId
1762
+ };
1763
+ })
1450
1764
  });
1765
+ return resultStep;
1451
1766
  };
1452
1767
 
1453
1768
  // src/context/auto-executor.ts
@@ -1554,14 +1869,16 @@ var AutoExecutor = class _AutoExecutor {
1554
1869
  });
1555
1870
  return lazyStep.parseOut(step.out);
1556
1871
  }
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
1872
+ const resultStep = await submitSingleStep({
1873
+ context: this.context,
1874
+ lazyStep,
1875
+ stepId: this.stepCount,
1876
+ invokeCount: this.invokeCount,
1877
+ concurrency: 1,
1878
+ telemetry: this.telemetry,
1879
+ debug: this.debug
1562
1880
  });
1563
- await this.submitStepsToQStash([resultStep], [lazyStep]);
1564
- return resultStep.out;
1881
+ throw new WorkflowAbort(lazyStep.stepName, resultStep);
1565
1882
  }
1566
1883
  /**
1567
1884
  * Runs steps in parallel.
@@ -1589,10 +1906,14 @@ var AutoExecutor = class _AutoExecutor {
1589
1906
  });
1590
1907
  switch (parallelCallState) {
1591
1908
  case "first": {
1592
- const planSteps = parallelSteps.map(
1593
- (parallelStep, index) => parallelStep.getPlanStep(parallelSteps.length, initialStepCount + index)
1594
- );
1595
- await this.submitStepsToQStash(planSteps, parallelSteps);
1909
+ await submitParallelSteps({
1910
+ context: this.context,
1911
+ steps: parallelSteps,
1912
+ initialStepCount,
1913
+ invokeCount: this.invokeCount,
1914
+ telemetry: this.telemetry,
1915
+ debug: this.debug
1916
+ });
1596
1917
  break;
1597
1918
  }
1598
1919
  case "partial": {
@@ -1606,13 +1927,18 @@ var AutoExecutor = class _AutoExecutor {
1606
1927
  validateStep(parallelSteps[stepIndex], planStep);
1607
1928
  try {
1608
1929
  const parallelStep = parallelSteps[stepIndex];
1609
- const resultStep = await parallelStep.getResultStep(
1610
- parallelSteps.length,
1611
- planStep.targetStep
1612
- );
1613
- await this.submitStepsToQStash([resultStep], [parallelStep]);
1930
+ const resultStep = await submitSingleStep({
1931
+ context: this.context,
1932
+ lazyStep: parallelStep,
1933
+ stepId: planStep.targetStep,
1934
+ invokeCount: this.invokeCount,
1935
+ concurrency: parallelSteps.length,
1936
+ telemetry: this.telemetry,
1937
+ debug: this.debug
1938
+ });
1939
+ throw new WorkflowAbort(parallelStep.stepName, resultStep);
1614
1940
  } catch (error) {
1615
- if (error instanceof WorkflowAbort || error instanceof import_qstash4.QstashError && error.status === 400) {
1941
+ if (error instanceof WorkflowAbort || error instanceof import_qstash5.QstashError && error.status === 400) {
1616
1942
  throw error;
1617
1943
  }
1618
1944
  throw new WorkflowError(
@@ -1668,128 +1994,6 @@ var AutoExecutor = class _AutoExecutor {
1668
1994
  return "discard";
1669
1995
  }
1670
1996
  }
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
1997
  /**
1794
1998
  * Get the promise by executing the lazt steps list. If there is a single
1795
1999
  * step, we call `runSingle`. Otherwise `runParallel` is called.
@@ -1863,7 +2067,7 @@ var sortSteps = (steps) => {
1863
2067
  };
1864
2068
 
1865
2069
  // src/context/api/anthropic.ts
1866
- var import_qstash5 = require("@upstash/qstash");
2070
+ var import_qstash6 = require("@upstash/qstash");
1867
2071
 
1868
2072
  // src/context/provider.ts
1869
2073
  var getProviderInfo = (api) => {
@@ -1927,7 +2131,7 @@ var AnthropicAPI = class extends BaseWorkflowApi {
1927
2131
  return await this.callApi(stepName, {
1928
2132
  api: {
1929
2133
  name: "llm",
1930
- provider: (0, import_qstash5.anthropic)({ token })
2134
+ provider: (0, import_qstash6.anthropic)({ token })
1931
2135
  },
1932
2136
  ...parameters
1933
2137
  });
@@ -1935,12 +2139,12 @@ var AnthropicAPI = class extends BaseWorkflowApi {
1935
2139
  };
1936
2140
 
1937
2141
  // src/context/api/openai.ts
1938
- var import_qstash6 = require("@upstash/qstash");
2142
+ var import_qstash7 = require("@upstash/qstash");
1939
2143
  var OpenAIAPI = class extends BaseWorkflowApi {
1940
2144
  async call(stepName, settings) {
1941
2145
  const { token, organization, operation, baseURL, ...parameters } = settings;
1942
2146
  const useOpenAI = baseURL === void 0;
1943
- const provider = useOpenAI ? (0, import_qstash6.openai)({ token, organization }) : (0, import_qstash6.custom)({ baseUrl: baseURL, token });
2147
+ const provider = useOpenAI ? (0, import_qstash7.openai)({ token, organization }) : (0, import_qstash7.custom)({ baseUrl: baseURL, token });
1944
2148
  return await this.callApi(stepName, {
1945
2149
  api: {
1946
2150
  name: "llm",
@@ -1952,14 +2156,14 @@ var OpenAIAPI = class extends BaseWorkflowApi {
1952
2156
  };
1953
2157
 
1954
2158
  // src/context/api/resend.ts
1955
- var import_qstash7 = require("@upstash/qstash");
2159
+ var import_qstash8 = require("@upstash/qstash");
1956
2160
  var ResendAPI = class extends BaseWorkflowApi {
1957
2161
  async call(stepName, settings) {
1958
2162
  const { token, batch = false, ...parameters } = settings;
1959
2163
  return await this.callApi(stepName, {
1960
2164
  api: {
1961
2165
  name: "email",
1962
- provider: (0, import_qstash7.resend)({ token, batch })
2166
+ provider: (0, import_qstash8.resend)({ token, batch })
1963
2167
  },
1964
2168
  ...parameters
1965
2169
  });
@@ -1986,28 +2190,11 @@ var WorkflowApi = class extends BaseWorkflowApi {
1986
2190
  };
1987
2191
 
1988
2192
  // src/agents/index.ts
1989
- var import_openai3 = require("@ai-sdk/openai");
1990
-
1991
- // src/agents/adapters.ts
1992
2193
  var import_openai2 = require("@ai-sdk/openai");
1993
- var import_ai = require("ai");
1994
-
1995
- // src/agents/constants.ts
1996
- var AGENT_NAME_HEADER = "upstash-agent-name";
1997
- var MANAGER_AGENT_PROMPT = `You are an agent orchestrating other AI Agents.
1998
-
1999
- These other agents have tools available to them.
2000
-
2001
- Given a prompt, utilize these agents to address requests.
2002
-
2003
- 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.
2004
-
2005
- Avoid calling the same agent twice in one turn. Instead, prefer to call it once but provide everything
2006
- you need from that agent.
2007
- `;
2008
2194
 
2009
2195
  // src/agents/adapters.ts
2010
- var fetchWithContextCall = async (context, ...params) => {
2196
+ var import_ai = require("ai");
2197
+ var fetchWithContextCall = async (context, agentCallParams, ...params) => {
2011
2198
  const [input, init] = params;
2012
2199
  try {
2013
2200
  const headers = init?.headers ? Object.fromEntries(new Headers(init.headers).entries()) : {};
@@ -2018,7 +2205,10 @@ var fetchWithContextCall = async (context, ...params) => {
2018
2205
  url: input.toString(),
2019
2206
  method: init?.method,
2020
2207
  headers,
2021
- body
2208
+ body,
2209
+ timeout: agentCallParams?.timeout,
2210
+ retries: agentCallParams?.retries,
2211
+ flowControl: agentCallParams?.flowControl
2022
2212
  });
2023
2213
  const responseHeaders = new Headers(
2024
2214
  Object.entries(responseInfo.header).reduce(
@@ -2045,10 +2235,11 @@ var fetchWithContextCall = async (context, ...params) => {
2045
2235
  var createWorkflowModel = ({
2046
2236
  context,
2047
2237
  provider,
2048
- providerParams
2238
+ providerParams,
2239
+ agentCallParams
2049
2240
  }) => {
2050
2241
  return provider({
2051
- fetch: (...params) => fetchWithContextCall(context, ...params),
2242
+ fetch: (...params) => fetchWithContextCall(context, agentCallParams, ...params),
2052
2243
  ...providerParams
2053
2244
  });
2054
2245
  };
@@ -2319,17 +2510,26 @@ var WorkflowAgents = class {
2319
2510
  */
2320
2511
  openai(...params) {
2321
2512
  const [model, settings] = params;
2322
- const { baseURL, apiKey, ...otherSettings } = settings ?? {};
2513
+ const { baseURL, apiKey, callSettings, ...otherSettings } = settings ?? {};
2323
2514
  const openaiModel = this.AISDKModel({
2324
2515
  context: this.context,
2325
- provider: import_openai3.createOpenAI,
2326
- providerParams: { baseURL, apiKey, compatibility: "strict" }
2516
+ provider: import_openai2.createOpenAI,
2517
+ providerParams: { baseURL, apiKey, compatibility: "strict" },
2518
+ agentCallParams: callSettings
2327
2519
  });
2328
2520
  return openaiModel(model, otherSettings);
2329
2521
  }
2330
2522
  AISDKModel = createWorkflowModel;
2331
2523
  };
2332
2524
 
2525
+ // src/serve/serve-many.ts
2526
+ var getNewUrlFromWorkflowId = (url, workflowId) => {
2527
+ if (!workflowId) {
2528
+ throw new WorkflowError("You can only call workflow which has a workflowId");
2529
+ }
2530
+ return url.replace(/[^/]+$/, workflowId);
2531
+ };
2532
+
2333
2533
  // src/context/context.ts
2334
2534
  var WorkflowContext = class {
2335
2535
  executor;
@@ -2551,60 +2751,42 @@ var WorkflowContext = class {
2551
2751
  }
2552
2752
  await this.addStep(new LazySleepUntilStep(stepName, time));
2553
2753
  }
2554
- /**
2555
- * Makes a third party call through QStash in order to make a
2556
- * network call without consuming any runtime.
2557
- *
2558
- * ```ts
2559
- * const { status, body } = await context.call<string>(
2560
- * "post call step",
2561
- * {
2562
- * url: "https://www.some-endpoint.com/api",
2563
- * method: "POST",
2564
- * body: "my-payload"
2565
- * }
2566
- * );
2567
- * ```
2568
- *
2569
- * tries to parse the result of the request as JSON. If it's
2570
- * not a JSON which can be parsed, simply returns the response
2571
- * body as it is.
2572
- *
2573
- * @param stepName
2574
- * @param url url to call
2575
- * @param method call method. "GET" by default.
2576
- * @param body call body
2577
- * @param headers call headers
2578
- * @param retries number of call retries. 0 by default
2579
- * @param timeout max duration to wait for the endpoint to respond. in seconds.
2580
- * @returns call result as {
2581
- * status: number;
2582
- * body: unknown;
2583
- * header: Record<string, string[]>
2584
- * }
2585
- */
2586
2754
  async call(stepName, settings) {
2587
- const {
2588
- url,
2589
- method = "GET",
2590
- body: requestBody,
2591
- headers = {},
2592
- retries = 0,
2593
- timeout,
2594
- flowControl
2595
- } = settings;
2596
- return await this.addStep(
2597
- new LazyCallStep(
2755
+ let callStep;
2756
+ if ("workflow" in settings) {
2757
+ const url = getNewUrlFromWorkflowId(this.url, settings.workflow.workflowId);
2758
+ callStep = new LazyCallStep(
2759
+ stepName,
2760
+ url,
2761
+ "POST",
2762
+ settings.body,
2763
+ settings.headers || {},
2764
+ settings.retries || 0,
2765
+ settings.timeout,
2766
+ settings.flowControl ?? settings.workflow.options.flowControl
2767
+ );
2768
+ } else {
2769
+ const {
2770
+ url,
2771
+ method = "GET",
2772
+ body,
2773
+ headers = {},
2774
+ retries = 0,
2775
+ timeout,
2776
+ flowControl
2777
+ } = settings;
2778
+ callStep = new LazyCallStep(
2598
2779
  stepName,
2599
2780
  url,
2600
2781
  method,
2601
- requestBody,
2782
+ body,
2602
2783
  headers,
2603
2784
  retries,
2604
2785
  timeout,
2605
2786
  flowControl
2606
- )
2607
- );
2787
+ );
2788
+ }
2789
+ return await this.addStep(callStep);
2608
2790
  }
2609
2791
  /**
2610
2792
  * Pauses workflow execution until a specific event occurs or a timeout is reached.
@@ -2752,7 +2934,7 @@ var WorkflowLogger = class _WorkflowLogger {
2752
2934
  };
2753
2935
 
2754
2936
  // src/serve/authorization.ts
2755
- var import_qstash8 = require("@upstash/qstash");
2937
+ var import_qstash9 = require("@upstash/qstash");
2756
2938
  var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowContext {
2757
2939
  static disabledMessage = "disabled-qstash-worklfow-run";
2758
2940
  disabled = true;
@@ -2784,7 +2966,7 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
2784
2966
  */
2785
2967
  static async tryAuthentication(routeFunction, context) {
2786
2968
  const disabledContext = new _DisabledWorkflowContext({
2787
- qstashClient: new import_qstash8.Client({
2969
+ qstashClient: new import_qstash9.Client({
2788
2970
  baseUrl: "disabled-client",
2789
2971
  token: "disabled-client"
2790
2972
  }),
@@ -2998,15 +3180,15 @@ var handleFailure = async (request, requestPayload, qstashClient, initialPayload
2998
3180
  };
2999
3181
 
3000
3182
  // src/serve/options.ts
3001
- var import_qstash9 = require("@upstash/qstash");
3002
3183
  var import_qstash10 = require("@upstash/qstash");
3184
+ var import_qstash11 = require("@upstash/qstash");
3003
3185
  var processOptions = (options) => {
3004
3186
  const environment = options?.env ?? (typeof process === "undefined" ? {} : process.env);
3005
3187
  const receiverEnvironmentVariablesSet = Boolean(
3006
3188
  environment.QSTASH_CURRENT_SIGNING_KEY && environment.QSTASH_NEXT_SIGNING_KEY
3007
3189
  );
3008
3190
  return {
3009
- qstashClient: new import_qstash10.Client({
3191
+ qstashClient: new import_qstash11.Client({
3010
3192
  baseUrl: environment.QSTASH_URL,
3011
3193
  token: environment.QSTASH_TOKEN
3012
3194
  }),
@@ -3041,7 +3223,7 @@ var processOptions = (options) => {
3041
3223
  throw error;
3042
3224
  }
3043
3225
  },
3044
- receiver: receiverEnvironmentVariablesSet ? new import_qstash9.Receiver({
3226
+ receiver: receiverEnvironmentVariablesSet ? new import_qstash10.Receiver({
3045
3227
  currentSigningKey: environment.QSTASH_CURRENT_SIGNING_KEY,
3046
3228
  nextSigningKey: environment.QSTASH_NEXT_SIGNING_KEY
3047
3229
  }) : void 0,
@@ -3261,7 +3443,7 @@ var serve = (routeFunction, options) => {
3261
3443
  };
3262
3444
 
3263
3445
  // src/client/index.ts
3264
- var import_qstash11 = require("@upstash/qstash");
3446
+ var import_qstash12 = require("@upstash/qstash");
3265
3447
  var Client4 = class {
3266
3448
  client;
3267
3449
  constructor(clientConfig) {
@@ -3270,7 +3452,7 @@ var Client4 = class {
3270
3452
  "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 });"
3271
3453
  );
3272
3454
  }
3273
- this.client = new import_qstash11.Client(clientConfig);
3455
+ this.client = new import_qstash12.Client(clientConfig);
3274
3456
  }
3275
3457
  /**
3276
3458
  * Cancel an ongoing workflow
@@ -3388,63 +3570,39 @@ var Client4 = class {
3388
3570
  async getWaiters({ eventId }) {
3389
3571
  return await makeGetWaitersRequest(this.client.http, eventId);
3390
3572
  }
3391
- /**
3392
- * Trigger new workflow run and returns the workflow run id
3393
- *
3394
- * ```ts
3395
- * const { workflowRunId } = await client.trigger({
3396
- * url: "https://workflow-endpoint.com",
3397
- * body: "hello there!", // Optional body
3398
- * headers: { ... }, // Optional headers
3399
- * workflowRunId: "my-workflow", // Optional workflow run ID
3400
- * retries: 3 // Optional retries for the initial request
3401
- * });
3402
- *
3403
- * console.log(workflowRunId)
3404
- * // wfr_my-workflow
3405
- * ```
3406
- *
3407
- * @param url URL of the workflow
3408
- * @param body body to start the workflow with
3409
- * @param headers headers to use in the request
3410
- * @param workflowRunId optional workflow run id to use. mind that
3411
- * you should pass different workflow run ids for different runs.
3412
- * The final workflowRunId will be `wfr_${workflowRunId}`, in
3413
- * other words: the workflow run id you pass will be prefixed
3414
- * with `wfr_`.
3415
- * @param retries retry to use in the initial request. in the rest of
3416
- * the workflow, `retries` option of the `serve` will be used.
3417
- * @returns workflow run id
3418
- */
3419
- async trigger({
3420
- url,
3421
- body,
3422
- headers,
3423
- workflowRunId,
3424
- retries,
3425
- flowControl
3426
- }) {
3427
- const finalWorkflowRunId = getWorkflowRunId(workflowRunId);
3428
- const context = new WorkflowContext({
3429
- qstashClient: this.client,
3430
- // @ts-expect-error headers type mismatch
3431
- headers: new Headers(headers ?? {}),
3432
- initialPayload: body,
3433
- steps: [],
3434
- url,
3435
- workflowRunId: finalWorkflowRunId,
3436
- retries,
3437
- telemetry: void 0,
3438
- // can't know workflow telemetry here
3439
- flowControl
3440
- });
3441
- const result = await triggerFirstInvocation({
3442
- workflowContext: context,
3443
- telemetry: void 0
3444
- // can't know workflow telemetry here
3573
+ async trigger(params) {
3574
+ const isBatchInput = Array.isArray(params);
3575
+ const options = isBatchInput ? params : [params];
3576
+ const invocations = options.map((option) => {
3577
+ const failureUrl = option.useFailureFunction ? option.url : option.failureUrl;
3578
+ const finalWorkflowRunId = getWorkflowRunId(option.workflowRunId);
3579
+ const context = new WorkflowContext({
3580
+ qstashClient: this.client,
3581
+ // @ts-expect-error headers type mismatch
3582
+ headers: new Headers(option.headers ?? {}),
3583
+ initialPayload: option.body,
3584
+ steps: [],
3585
+ url: option.url,
3586
+ workflowRunId: finalWorkflowRunId,
3587
+ retries: option.retries,
3588
+ telemetry: void 0,
3589
+ // can't know workflow telemetry here
3590
+ flowControl: option.flowControl,
3591
+ failureUrl
3592
+ });
3593
+ return {
3594
+ workflowContext: context,
3595
+ telemetry: void 0,
3596
+ // can't know workflow telemetry here
3597
+ delay: option.delay
3598
+ };
3445
3599
  });
3600
+ const result = await triggerFirstInvocation(invocations);
3601
+ const workflowRunIds = invocations.map(
3602
+ (invocation) => invocation.workflowContext.workflowRunId
3603
+ );
3446
3604
  if (result.isOk()) {
3447
- return { workflowRunId: finalWorkflowRunId };
3605
+ return isBatchInput ? workflowRunIds.map((id) => ({ workflowRunId: id })) : { workflowRunId: workflowRunIds[0] };
3448
3606
  } else {
3449
3607
  throw result.error;
3450
3608
  }