@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/nextjs.js CHANGED
@@ -94,11 +94,12 @@ var WORKFLOW_PROTOCOL_VERSION_HEADER = "Upstash-Workflow-Sdk-Version";
94
94
  var DEFAULT_CONTENT_TYPE = "application/json";
95
95
  var NO_CONCURRENCY = 1;
96
96
  var DEFAULT_RETRIES = 3;
97
- var VERSION = "v0.2.7";
97
+ var VERSION = "v0.2.14";
98
98
  var SDK_TELEMETRY = `@upstash/workflow@${VERSION}`;
99
99
  var TELEMETRY_HEADER_SDK = "Upstash-Telemetry-Sdk";
100
100
  var TELEMETRY_HEADER_FRAMEWORK = "Upstash-Telemetry-Framework";
101
101
  var TELEMETRY_HEADER_RUNTIME = "Upstash-Telemetry-Runtime";
102
+ var TELEMETRY_HEADER_AGENT = "Upstash-Telemetry-Agent";
102
103
 
103
104
  // src/error.ts
104
105
  var import_qstash2 = require("@upstash/qstash");
@@ -141,6 +142,12 @@ var formatWorkflowError = (error) => {
141
142
  };
142
143
  };
143
144
 
145
+ // src/context/auto-executor.ts
146
+ var import_qstash5 = require("@upstash/qstash");
147
+
148
+ // src/qstash/headers.ts
149
+ var import_qstash4 = require("@upstash/qstash");
150
+
144
151
  // src/utils.ts
145
152
  var NANOID_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
146
153
  var NANOID_LENGTH = 21;
@@ -166,574 +173,231 @@ function decodeBase64(base64) {
166
173
  }
167
174
  }
168
175
 
169
- // src/context/steps.ts
170
- var BaseLazyStep = class _BaseLazyStep {
171
- stepName;
172
- constructor(stepName) {
173
- if (!stepName) {
174
- throw new WorkflowError(
175
- "A workflow step name cannot be undefined or an empty string. Please provide a name for your workflow step."
176
- );
177
- }
178
- this.stepName = stepName;
176
+ // node_modules/neverthrow/dist/index.es.js
177
+ var defaultErrorConfig = {
178
+ withStackTrace: false
179
+ };
180
+ var createNeverThrowError = (message, result, config = defaultErrorConfig) => {
181
+ const data = result.isOk() ? { type: "Ok", value: result.value } : { type: "Err", value: result.error };
182
+ const maybeStack = config.withStackTrace ? new Error().stack : void 0;
183
+ return {
184
+ data,
185
+ message,
186
+ stack: maybeStack
187
+ };
188
+ };
189
+ function __awaiter(thisArg, _arguments, P, generator) {
190
+ function adopt(value) {
191
+ return value instanceof P ? value : new P(function(resolve) {
192
+ resolve(value);
193
+ });
179
194
  }
180
- /**
181
- * parse the out field of a step result.
182
- *
183
- * will be called when returning the steps to the context from auto executor
184
- *
185
- * @param out field of the step
186
- * @returns parsed out field
187
- */
188
- parseOut(out) {
189
- if (out === void 0) {
190
- if (this.allowUndefinedOut) {
191
- return void 0;
192
- } else {
193
- throw new WorkflowError(
194
- `Error while parsing output of ${this.stepType} step. Expected a string, but got: undefined`
195
- );
195
+ return new (P || (P = Promise))(function(resolve, reject) {
196
+ function fulfilled(value) {
197
+ try {
198
+ step(generator.next(value));
199
+ } catch (e) {
200
+ reject(e);
196
201
  }
197
202
  }
198
- if (typeof out === "object") {
199
- if (this.stepType !== "Wait") {
200
- console.warn(
201
- `Error while parsing ${this.stepType} step output. Expected a string, but got object. Please reach out to Upstash Support.`
202
- );
203
- return out;
203
+ function rejected(value) {
204
+ try {
205
+ step(generator["throw"](value));
206
+ } catch (e) {
207
+ reject(e);
204
208
  }
205
- return {
206
- ...out,
207
- eventData: _BaseLazyStep.tryParsing(out.eventData)
208
- };
209
209
  }
210
- if (typeof out !== "string") {
211
- throw new WorkflowError(
212
- `Error while parsing output of ${this.stepType} step. Expected a string or undefined, but got: ${typeof out}`
213
- );
210
+ function step(result) {
211
+ result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
214
212
  }
215
- return this.safeParseOut(out);
216
- }
217
- safeParseOut(out) {
218
- return _BaseLazyStep.tryParsing(out);
213
+ step((generator = generator.apply(thisArg, [])).next());
214
+ });
215
+ }
216
+ function __values(o) {
217
+ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
218
+ if (m) return m.call(o);
219
+ if (o && typeof o.length === "number") return {
220
+ next: function() {
221
+ if (o && i >= o.length) o = void 0;
222
+ return { value: o && o[i++], done: !o };
223
+ }
224
+ };
225
+ throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
226
+ }
227
+ function __await(v) {
228
+ return this instanceof __await ? (this.v = v, this) : new __await(v);
229
+ }
230
+ function __asyncGenerator(thisArg, _arguments, generator) {
231
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
232
+ var g = generator.apply(thisArg, _arguments || []), i, q = [];
233
+ return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function() {
234
+ return this;
235
+ }, i;
236
+ function verb(n) {
237
+ if (g[n]) i[n] = function(v) {
238
+ return new Promise(function(a, b) {
239
+ q.push([n, v, a, b]) > 1 || resume(n, v);
240
+ });
241
+ };
219
242
  }
220
- static tryParsing(stepOut) {
243
+ function resume(n, v) {
221
244
  try {
222
- return JSON.parse(stepOut);
223
- } catch {
224
- return stepOut;
245
+ step(g[n](v));
246
+ } catch (e) {
247
+ settle(q[0][3], e);
225
248
  }
226
249
  }
227
- };
228
- var LazyFunctionStep = class extends BaseLazyStep {
229
- stepFunction;
230
- stepType = "Run";
231
- allowUndefinedOut = true;
232
- constructor(stepName, stepFunction) {
233
- super(stepName);
234
- this.stepFunction = stepFunction;
250
+ function step(r) {
251
+ r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r);
235
252
  }
236
- getPlanStep(concurrent, targetStep) {
237
- return {
238
- stepId: 0,
239
- stepName: this.stepName,
240
- stepType: this.stepType,
241
- concurrent,
242
- targetStep
243
- };
253
+ function fulfill(value) {
254
+ resume("next", value);
244
255
  }
245
- async getResultStep(concurrent, stepId) {
246
- let result = this.stepFunction();
247
- if (result instanceof Promise) {
248
- result = await result;
249
- }
250
- return {
251
- stepId,
252
- stepName: this.stepName,
253
- stepType: this.stepType,
254
- out: result,
255
- concurrent
256
- };
256
+ function reject(value) {
257
+ resume("throw", value);
257
258
  }
258
- };
259
- var LazySleepStep = class extends BaseLazyStep {
260
- sleep;
261
- stepType = "SleepFor";
262
- allowUndefinedOut = true;
263
- constructor(stepName, sleep) {
264
- super(stepName);
265
- this.sleep = sleep;
259
+ function settle(f, v) {
260
+ if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]);
266
261
  }
267
- getPlanStep(concurrent, targetStep) {
268
- return {
269
- stepId: 0,
270
- stepName: this.stepName,
271
- stepType: this.stepType,
272
- sleepFor: this.sleep,
273
- concurrent,
274
- targetStep
262
+ }
263
+ function __asyncDelegator(o) {
264
+ var i, p;
265
+ return i = {}, verb("next"), verb("throw", function(e) {
266
+ throw e;
267
+ }), verb("return"), i[Symbol.iterator] = function() {
268
+ return this;
269
+ }, i;
270
+ function verb(n, f) {
271
+ i[n] = o[n] ? function(v) {
272
+ return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v;
273
+ } : f;
274
+ }
275
+ }
276
+ function __asyncValues(o) {
277
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
278
+ var m = o[Symbol.asyncIterator], i;
279
+ 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() {
280
+ return this;
281
+ }, i);
282
+ function verb(n) {
283
+ i[n] = o[n] && function(v) {
284
+ return new Promise(function(resolve, reject) {
285
+ v = o[n](v), settle(resolve, reject, v.done, v.value);
286
+ });
275
287
  };
276
288
  }
277
- async getResultStep(concurrent, stepId) {
278
- return await Promise.resolve({
279
- stepId,
280
- stepName: this.stepName,
281
- stepType: this.stepType,
282
- sleepFor: this.sleep,
283
- concurrent
284
- });
289
+ function settle(resolve, reject, d, v) {
290
+ Promise.resolve(v).then(function(v2) {
291
+ resolve({ value: v2, done: d });
292
+ }, reject);
285
293
  }
286
- };
287
- var LazySleepUntilStep = class extends BaseLazyStep {
288
- sleepUntil;
289
- stepType = "SleepUntil";
290
- allowUndefinedOut = true;
291
- constructor(stepName, sleepUntil) {
292
- super(stepName);
293
- this.sleepUntil = sleepUntil;
294
+ }
295
+ var ResultAsync = class _ResultAsync {
296
+ constructor(res) {
297
+ this._promise = res;
294
298
  }
295
- getPlanStep(concurrent, targetStep) {
296
- return {
297
- stepId: 0,
298
- stepName: this.stepName,
299
- stepType: this.stepType,
300
- sleepUntil: this.sleepUntil,
301
- concurrent,
302
- targetStep
303
- };
299
+ static fromSafePromise(promise) {
300
+ const newPromise = promise.then((value) => new Ok(value));
301
+ return new _ResultAsync(newPromise);
304
302
  }
305
- async getResultStep(concurrent, stepId) {
306
- return await Promise.resolve({
307
- stepId,
308
- stepName: this.stepName,
309
- stepType: this.stepType,
310
- sleepUntil: this.sleepUntil,
311
- concurrent
312
- });
303
+ static fromPromise(promise, errorFn) {
304
+ const newPromise = promise.then((value) => new Ok(value)).catch((e) => new Err(errorFn(e)));
305
+ return new _ResultAsync(newPromise);
313
306
  }
314
- safeParseOut() {
315
- return void 0;
307
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
308
+ static fromThrowable(fn, errorFn) {
309
+ return (...args) => {
310
+ return new _ResultAsync((() => __awaiter(this, void 0, void 0, function* () {
311
+ try {
312
+ return new Ok(yield fn(...args));
313
+ } catch (error) {
314
+ return new Err(errorFn ? errorFn(error) : error);
315
+ }
316
+ }))());
317
+ };
316
318
  }
317
- };
318
- var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
319
- url;
320
- method;
321
- body;
322
- headers;
323
- retries;
324
- timeout;
325
- flowControl;
326
- stepType = "Call";
327
- allowUndefinedOut = false;
328
- constructor(stepName, url, method, body, headers, retries, timeout, flowControl) {
329
- super(stepName);
330
- this.url = url;
331
- this.method = method;
332
- this.body = body;
333
- this.headers = headers;
334
- this.retries = retries;
335
- this.timeout = timeout;
336
- this.flowControl = flowControl;
337
- }
338
- getPlanStep(concurrent, targetStep) {
339
- return {
340
- stepId: 0,
341
- stepName: this.stepName,
342
- stepType: this.stepType,
343
- concurrent,
344
- targetStep
345
- };
319
+ static combine(asyncResultList) {
320
+ return combineResultAsyncList(asyncResultList);
346
321
  }
347
- async getResultStep(concurrent, stepId) {
348
- return await Promise.resolve({
349
- stepId,
350
- stepName: this.stepName,
351
- stepType: this.stepType,
352
- concurrent,
353
- callUrl: this.url,
354
- callMethod: this.method,
355
- callBody: this.body,
356
- callHeaders: this.headers
357
- });
322
+ static combineWithAllErrors(asyncResultList) {
323
+ return combineResultAsyncListWithAllErrors(asyncResultList);
358
324
  }
359
- safeParseOut(out) {
360
- const { header, status, body } = JSON.parse(out);
361
- const responseHeaders = new Headers(header);
362
- if (_LazyCallStep.isText(responseHeaders.get("content-type"))) {
363
- const bytes = new Uint8Array(out.length);
364
- for (let i = 0; i < out.length; i++) {
365
- bytes[i] = out.charCodeAt(i);
325
+ map(f) {
326
+ return new _ResultAsync(this._promise.then((res) => __awaiter(this, void 0, void 0, function* () {
327
+ if (res.isErr()) {
328
+ return new Err(res.error);
366
329
  }
367
- const processedResult = new TextDecoder().decode(bytes);
368
- const newBody = JSON.parse(processedResult).body;
369
- return {
370
- status,
371
- header,
372
- body: BaseLazyStep.tryParsing(newBody)
373
- };
374
- } else {
375
- return { header, status, body };
376
- }
377
- }
378
- static applicationHeaders = /* @__PURE__ */ new Set([
379
- "application/json",
380
- "application/xml",
381
- "application/javascript",
382
- "application/x-www-form-urlencoded",
383
- "application/xhtml+xml",
384
- "application/ld+json",
385
- "application/rss+xml",
386
- "application/atom+xml"
387
- ]);
388
- static isText = (contentTypeHeader) => {
389
- if (!contentTypeHeader) {
390
- return false;
391
- }
392
- if (_LazyCallStep.applicationHeaders.has(contentTypeHeader)) {
393
- return true;
394
- }
395
- if (contentTypeHeader.startsWith("text/")) {
396
- return true;
397
- }
398
- return false;
399
- };
400
- };
401
- var LazyWaitForEventStep = class extends BaseLazyStep {
402
- eventId;
403
- timeout;
404
- stepType = "Wait";
405
- allowUndefinedOut = false;
406
- constructor(stepName, eventId, timeout) {
407
- super(stepName);
408
- this.eventId = eventId;
409
- this.timeout = timeout;
330
+ return new Ok(yield f(res.value));
331
+ })));
410
332
  }
411
- getPlanStep(concurrent, targetStep) {
412
- return {
413
- stepId: 0,
414
- stepName: this.stepName,
415
- stepType: this.stepType,
416
- waitEventId: this.eventId,
417
- timeout: this.timeout,
418
- concurrent,
419
- targetStep
420
- };
333
+ andThrough(f) {
334
+ return new _ResultAsync(this._promise.then((res) => __awaiter(this, void 0, void 0, function* () {
335
+ if (res.isErr()) {
336
+ return new Err(res.error);
337
+ }
338
+ const newRes = yield f(res.value);
339
+ if (newRes.isErr()) {
340
+ return new Err(newRes.error);
341
+ }
342
+ return new Ok(res.value);
343
+ })));
421
344
  }
422
- async getResultStep(concurrent, stepId) {
423
- return await Promise.resolve({
424
- stepId,
425
- stepName: this.stepName,
426
- stepType: this.stepType,
427
- waitEventId: this.eventId,
428
- timeout: this.timeout,
429
- concurrent
430
- });
345
+ andTee(f) {
346
+ return new _ResultAsync(this._promise.then((res) => __awaiter(this, void 0, void 0, function* () {
347
+ if (res.isErr()) {
348
+ return new Err(res.error);
349
+ }
350
+ try {
351
+ yield f(res.value);
352
+ } catch (e) {
353
+ }
354
+ return new Ok(res.value);
355
+ })));
431
356
  }
432
- safeParseOut(out) {
433
- const result = JSON.parse(out);
434
- return {
435
- ...result,
436
- eventData: BaseLazyStep.tryParsing(result.eventData)
437
- };
357
+ mapErr(f) {
358
+ return new _ResultAsync(this._promise.then((res) => __awaiter(this, void 0, void 0, function* () {
359
+ if (res.isOk()) {
360
+ return new Ok(res.value);
361
+ }
362
+ return new Err(yield f(res.error));
363
+ })));
438
364
  }
439
- };
440
- var LazyNotifyStep = class extends LazyFunctionStep {
441
- stepType = "Notify";
442
- constructor(stepName, eventId, eventData, requester) {
443
- super(stepName, async () => {
444
- const notifyResponse = await makeNotifyRequest(requester, eventId, eventData);
445
- return {
446
- eventId,
447
- eventData,
448
- notifyResponse
449
- };
450
- });
365
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
366
+ andThen(f) {
367
+ return new _ResultAsync(this._promise.then((res) => {
368
+ if (res.isErr()) {
369
+ return new Err(res.error);
370
+ }
371
+ const newValue = f(res.value);
372
+ return newValue instanceof _ResultAsync ? newValue._promise : newValue;
373
+ }));
451
374
  }
452
- safeParseOut(out) {
453
- const result = JSON.parse(out);
454
- return {
455
- ...result,
456
- eventData: BaseLazyStep.tryParsing(result.eventData)
457
- };
375
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
376
+ orElse(f) {
377
+ return new _ResultAsync(this._promise.then((res) => __awaiter(this, void 0, void 0, function* () {
378
+ if (res.isErr()) {
379
+ return f(res.error);
380
+ }
381
+ return new Ok(res.value);
382
+ })));
458
383
  }
459
- };
460
- var LazyInvokeStep = class extends BaseLazyStep {
461
- stepType = "Invoke";
462
- params;
463
- allowUndefinedOut = false;
464
- constructor(stepName, {
465
- workflow,
466
- body,
467
- headers = {},
468
- workflowRunId,
469
- retries,
470
- flowControl
471
- }) {
472
- super(stepName);
473
- this.params = {
474
- workflow,
475
- body,
476
- headers,
477
- workflowRunId: getWorkflowRunId(workflowRunId),
478
- retries,
479
- flowControl
480
- };
384
+ match(ok2, _err) {
385
+ return this._promise.then((res) => res.match(ok2, _err));
481
386
  }
482
- getPlanStep(concurrent, targetStep) {
483
- return {
484
- stepId: 0,
485
- stepName: this.stepName,
486
- stepType: this.stepType,
487
- concurrent,
488
- targetStep
489
- };
387
+ unwrapOr(t) {
388
+ return this._promise.then((res) => res.unwrapOr(t));
490
389
  }
491
390
  /**
492
- * won't be used as it's the server who will add the result step
493
- * in Invoke step.
391
+ * Emulates Rust's `?` operator in `safeTry`'s body. See also `safeTry`.
494
392
  */
495
- getResultStep(concurrent, stepId) {
496
- return Promise.resolve({
497
- stepId,
498
- stepName: this.stepName,
499
- stepType: this.stepType,
500
- concurrent
393
+ safeUnwrap() {
394
+ return __asyncGenerator(this, arguments, function* safeUnwrap_1() {
395
+ return yield __await(yield __await(yield* __asyncDelegator(__asyncValues(yield __await(this._promise.then((res) => res.safeUnwrap()))))));
501
396
  });
502
397
  }
503
- safeParseOut(out) {
504
- const result = JSON.parse(out);
505
- return {
506
- ...result,
507
- body: BaseLazyStep.tryParsing(result.body)
508
- };
509
- }
510
- };
511
-
512
- // node_modules/neverthrow/dist/index.es.js
513
- var defaultErrorConfig = {
514
- withStackTrace: false
515
- };
516
- var createNeverThrowError = (message, result, config = defaultErrorConfig) => {
517
- const data = result.isOk() ? { type: "Ok", value: result.value } : { type: "Err", value: result.error };
518
- const maybeStack = config.withStackTrace ? new Error().stack : void 0;
519
- return {
520
- data,
521
- message,
522
- stack: maybeStack
523
- };
524
- };
525
- function __awaiter(thisArg, _arguments, P, generator) {
526
- function adopt(value) {
527
- return value instanceof P ? value : new P(function(resolve) {
528
- resolve(value);
529
- });
530
- }
531
- return new (P || (P = Promise))(function(resolve, reject) {
532
- function fulfilled(value) {
533
- try {
534
- step(generator.next(value));
535
- } catch (e) {
536
- reject(e);
537
- }
538
- }
539
- function rejected(value) {
540
- try {
541
- step(generator["throw"](value));
542
- } catch (e) {
543
- reject(e);
544
- }
545
- }
546
- function step(result) {
547
- result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
548
- }
549
- step((generator = generator.apply(thisArg, [])).next());
550
- });
551
- }
552
- function __values(o) {
553
- var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
554
- if (m) return m.call(o);
555
- if (o && typeof o.length === "number") return {
556
- next: function() {
557
- if (o && i >= o.length) o = void 0;
558
- return { value: o && o[i++], done: !o };
559
- }
560
- };
561
- throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
562
- }
563
- function __await(v) {
564
- return this instanceof __await ? (this.v = v, this) : new __await(v);
565
- }
566
- function __asyncGenerator(thisArg, _arguments, generator) {
567
- if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
568
- var g = generator.apply(thisArg, _arguments || []), i, q = [];
569
- return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function() {
570
- return this;
571
- }, i;
572
- function verb(n) {
573
- if (g[n]) i[n] = function(v) {
574
- return new Promise(function(a, b) {
575
- q.push([n, v, a, b]) > 1 || resume(n, v);
576
- });
577
- };
578
- }
579
- function resume(n, v) {
580
- try {
581
- step(g[n](v));
582
- } catch (e) {
583
- settle(q[0][3], e);
584
- }
585
- }
586
- function step(r) {
587
- r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r);
588
- }
589
- function fulfill(value) {
590
- resume("next", value);
591
- }
592
- function reject(value) {
593
- resume("throw", value);
594
- }
595
- function settle(f, v) {
596
- if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]);
597
- }
598
- }
599
- function __asyncDelegator(o) {
600
- var i, p;
601
- return i = {}, verb("next"), verb("throw", function(e) {
602
- throw e;
603
- }), verb("return"), i[Symbol.iterator] = function() {
604
- return this;
605
- }, i;
606
- function verb(n, f) {
607
- i[n] = o[n] ? function(v) {
608
- return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v;
609
- } : f;
610
- }
611
- }
612
- function __asyncValues(o) {
613
- if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
614
- var m = o[Symbol.asyncIterator], i;
615
- 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() {
616
- return this;
617
- }, i);
618
- function verb(n) {
619
- i[n] = o[n] && function(v) {
620
- return new Promise(function(resolve, reject) {
621
- v = o[n](v), settle(resolve, reject, v.done, v.value);
622
- });
623
- };
624
- }
625
- function settle(resolve, reject, d, v) {
626
- Promise.resolve(v).then(function(v2) {
627
- resolve({ value: v2, done: d });
628
- }, reject);
629
- }
630
- }
631
- var ResultAsync = class _ResultAsync {
632
- constructor(res) {
633
- this._promise = res;
634
- }
635
- static fromSafePromise(promise) {
636
- const newPromise = promise.then((value) => new Ok(value));
637
- return new _ResultAsync(newPromise);
638
- }
639
- static fromPromise(promise, errorFn) {
640
- const newPromise = promise.then((value) => new Ok(value)).catch((e) => new Err(errorFn(e)));
641
- return new _ResultAsync(newPromise);
642
- }
643
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
644
- static fromThrowable(fn, errorFn) {
645
- return (...args) => {
646
- return new _ResultAsync((() => __awaiter(this, void 0, void 0, function* () {
647
- try {
648
- return new Ok(yield fn(...args));
649
- } catch (error) {
650
- return new Err(errorFn ? errorFn(error) : error);
651
- }
652
- }))());
653
- };
654
- }
655
- static combine(asyncResultList) {
656
- return combineResultAsyncList(asyncResultList);
657
- }
658
- static combineWithAllErrors(asyncResultList) {
659
- return combineResultAsyncListWithAllErrors(asyncResultList);
660
- }
661
- map(f) {
662
- return new _ResultAsync(this._promise.then((res) => __awaiter(this, void 0, void 0, function* () {
663
- if (res.isErr()) {
664
- return new Err(res.error);
665
- }
666
- return new Ok(yield f(res.value));
667
- })));
668
- }
669
- andThrough(f) {
670
- return new _ResultAsync(this._promise.then((res) => __awaiter(this, void 0, void 0, function* () {
671
- if (res.isErr()) {
672
- return new Err(res.error);
673
- }
674
- const newRes = yield f(res.value);
675
- if (newRes.isErr()) {
676
- return new Err(newRes.error);
677
- }
678
- return new Ok(res.value);
679
- })));
680
- }
681
- andTee(f) {
682
- return new _ResultAsync(this._promise.then((res) => __awaiter(this, void 0, void 0, function* () {
683
- if (res.isErr()) {
684
- return new Err(res.error);
685
- }
686
- try {
687
- yield f(res.value);
688
- } catch (e) {
689
- }
690
- return new Ok(res.value);
691
- })));
692
- }
693
- mapErr(f) {
694
- return new _ResultAsync(this._promise.then((res) => __awaiter(this, void 0, void 0, function* () {
695
- if (res.isOk()) {
696
- return new Ok(res.value);
697
- }
698
- return new Err(yield f(res.error));
699
- })));
700
- }
701
- // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
702
- andThen(f) {
703
- return new _ResultAsync(this._promise.then((res) => {
704
- if (res.isErr()) {
705
- return new Err(res.error);
706
- }
707
- const newValue = f(res.value);
708
- return newValue instanceof _ResultAsync ? newValue._promise : newValue;
709
- }));
710
- }
711
- // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
712
- orElse(f) {
713
- return new _ResultAsync(this._promise.then((res) => __awaiter(this, void 0, void 0, function* () {
714
- if (res.isErr()) {
715
- return f(res.error);
716
- }
717
- return new Ok(res.value);
718
- })));
719
- }
720
- match(ok2, _err) {
721
- return this._promise.then((res) => res.match(ok2, _err));
722
- }
723
- unwrapOr(t) {
724
- return this._promise.then((res) => res.unwrapOr(t));
725
- }
726
- /**
727
- * Emulates Rust's `?` operator in `safeTry`'s body. See also `safeTry`.
728
- */
729
- safeUnwrap() {
730
- return __asyncGenerator(this, arguments, function* safeUnwrap_1() {
731
- return yield __await(yield __await(yield* __asyncDelegator(__asyncValues(yield __await(this._promise.then((res) => res.safeUnwrap()))))));
732
- });
733
- }
734
- // Makes ResultAsync implement PromiseLike<Result>
735
- then(successCallback, failureCallback) {
736
- return this._promise.then(successCallback, failureCallback);
398
+ // Makes ResultAsync implement PromiseLike<Result>
399
+ then(successCallback, failureCallback) {
400
+ return this._promise.then(successCallback, failureCallback);
737
401
  }
738
402
  };
739
403
  var errAsync = (err2) => new ResultAsync(Promise.resolve(new Err(err2)));
@@ -938,54 +602,72 @@ var StepTypes = [
938
602
 
939
603
  // src/workflow-requests.ts
940
604
  var import_qstash3 = require("@upstash/qstash");
941
- var triggerFirstInvocation = async ({
942
- workflowContext,
943
- useJSONContent,
944
- telemetry,
945
- debug,
946
- invokeCount
947
- }) => {
948
- const { headers } = getHeaders({
949
- initHeaderValue: "true",
950
- workflowRunId: workflowContext.workflowRunId,
951
- workflowUrl: workflowContext.url,
952
- userHeaders: workflowContext.headers,
953
- failureUrl: workflowContext.failureUrl,
954
- retries: workflowContext.retries,
955
- telemetry,
956
- invokeCount,
957
- flowControl: workflowContext.flowControl
958
- });
959
- if (workflowContext.headers.get("content-type")) {
960
- headers["content-type"] = workflowContext.headers.get("content-type");
961
- }
962
- if (useJSONContent) {
963
- headers["content-type"] = "application/json";
964
- }
965
- try {
966
- const body = typeof workflowContext.requestPayload === "string" ? workflowContext.requestPayload : JSON.stringify(workflowContext.requestPayload);
967
- const result = await workflowContext.qstashClient.publish({
968
- headers,
969
- method: "POST",
970
- body,
971
- url: workflowContext.url
972
- });
973
- if (result.deduplicated) {
974
- await debug?.log("WARN", "SUBMIT_FIRST_INVOCATION", {
975
- message: `Workflow run ${workflowContext.workflowRunId} already exists. A new one isn't created.`,
605
+ var triggerFirstInvocation = async (params) => {
606
+ const firstInvocationParams = Array.isArray(params) ? params : [params];
607
+ const workflowContextClient = firstInvocationParams[0].workflowContext.qstashClient;
608
+ const invocationBatch = firstInvocationParams.map(
609
+ ({ workflowContext, useJSONContent, telemetry, invokeCount, delay }) => {
610
+ const { headers } = getHeaders({
611
+ initHeaderValue: "true",
612
+ workflowConfig: {
613
+ workflowRunId: workflowContext.workflowRunId,
614
+ workflowUrl: workflowContext.url,
615
+ failureUrl: workflowContext.failureUrl,
616
+ retries: workflowContext.retries,
617
+ telemetry,
618
+ flowControl: workflowContext.flowControl,
619
+ useJSONContent: useJSONContent ?? false
620
+ },
621
+ invokeCount: invokeCount ?? 0,
622
+ userHeaders: workflowContext.headers
623
+ });
624
+ if (workflowContext.headers.get("content-type")) {
625
+ headers["content-type"] = workflowContext.headers.get("content-type");
626
+ }
627
+ if (useJSONContent) {
628
+ headers["content-type"] = "application/json";
629
+ }
630
+ const body = typeof workflowContext.requestPayload === "string" ? workflowContext.requestPayload : JSON.stringify(workflowContext.requestPayload);
631
+ return {
976
632
  headers,
977
- requestPayload: workflowContext.requestPayload,
633
+ method: "POST",
634
+ body,
978
635
  url: workflowContext.url,
979
- messageId: result.messageId
980
- });
636
+ delay
637
+ };
638
+ }
639
+ );
640
+ try {
641
+ const results = await workflowContextClient.batch(invocationBatch);
642
+ const invocationStatuses = [];
643
+ for (let i = 0; i < results.length; i++) {
644
+ const result = results[i];
645
+ const invocationParams = firstInvocationParams[i];
646
+ if (result.deduplicated) {
647
+ await invocationParams.debug?.log("WARN", "SUBMIT_FIRST_INVOCATION", {
648
+ message: `Workflow run ${invocationParams.workflowContext.workflowRunId} already exists. A new one isn't created.`,
649
+ headers: invocationBatch[i].headers,
650
+ requestPayload: invocationParams.workflowContext.requestPayload,
651
+ url: invocationParams.workflowContext.url,
652
+ messageId: result.messageId
653
+ });
654
+ invocationStatuses.push("workflow-run-already-exists");
655
+ } else {
656
+ await invocationParams.debug?.log("SUBMIT", "SUBMIT_FIRST_INVOCATION", {
657
+ headers: invocationBatch[i].headers,
658
+ requestPayload: invocationParams.workflowContext.requestPayload,
659
+ url: invocationParams.workflowContext.url,
660
+ messageId: result.messageId
661
+ });
662
+ invocationStatuses.push("success");
663
+ }
664
+ }
665
+ const hasAnyDeduplicated = invocationStatuses.some(
666
+ (status) => status === "workflow-run-already-exists"
667
+ );
668
+ if (hasAnyDeduplicated) {
981
669
  return ok("workflow-run-already-exists");
982
670
  } else {
983
- await debug?.log("SUBMIT", "SUBMIT_FIRST_INVOCATION", {
984
- headers,
985
- requestPayload: workflowContext.requestPayload,
986
- url: workflowContext.url,
987
- messageId: result.messageId
988
- });
989
671
  return ok("success");
990
672
  }
991
673
  } catch (error) {
@@ -1124,14 +806,16 @@ ${atob(callbackMessage.body ?? "")}`
1124
806
  const userHeaders = recreateUserHeaders(request.headers);
1125
807
  const { headers: requestHeaders } = getHeaders({
1126
808
  initHeaderValue: "false",
1127
- workflowRunId,
1128
- workflowUrl,
809
+ workflowConfig: {
810
+ workflowRunId,
811
+ workflowUrl,
812
+ failureUrl,
813
+ retries,
814
+ telemetry,
815
+ flowControl
816
+ },
1129
817
  userHeaders,
1130
- failureUrl,
1131
- retries,
1132
- telemetry,
1133
- invokeCount: Number(invokeCount),
1134
- flowControl
818
+ invokeCount: Number(invokeCount)
1135
819
  });
1136
820
  const callResponse = {
1137
821
  status: callbackMessage.status,
@@ -1177,329 +861,899 @@ var getTelemetryHeaders = (telemetry) => {
1177
861
  [TELEMETRY_HEADER_RUNTIME]: telemetry.runtime ?? "unknown"
1178
862
  };
1179
863
  };
1180
- var getHeaders = ({
1181
- initHeaderValue,
1182
- workflowRunId,
1183
- workflowUrl,
1184
- userHeaders,
1185
- failureUrl,
1186
- retries,
1187
- step,
1188
- callRetries,
1189
- callTimeout,
1190
- telemetry,
1191
- invokeCount,
1192
- flowControl,
1193
- callFlowControl
1194
- }) => {
1195
- const callHeaders = new Headers(step?.callHeaders);
1196
- const contentType = (callHeaders.get("content-type") ? callHeaders.get("content-type") : userHeaders?.get("Content-Type") ? userHeaders.get("Content-Type") : void 0) ?? DEFAULT_CONTENT_TYPE;
1197
- const baseHeaders = {
1198
- [WORKFLOW_INIT_HEADER]: initHeaderValue,
1199
- [WORKFLOW_ID_HEADER]: workflowRunId,
1200
- [WORKFLOW_URL_HEADER]: workflowUrl,
1201
- [WORKFLOW_FEATURE_HEADER]: "LazyFetch,InitialBody",
1202
- [WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION,
1203
- "content-type": contentType,
1204
- ...telemetry ? getTelemetryHeaders(telemetry) : {}
1205
- };
1206
- if (invokeCount !== void 0 && !step?.callUrl) {
1207
- baseHeaders[`Upstash-Forward-${WORKFLOW_INVOKE_COUNT_HEADER}`] = invokeCount.toString();
1208
- }
1209
- if (!step?.callUrl) {
1210
- baseHeaders[`Upstash-Forward-${WORKFLOW_PROTOCOL_VERSION_HEADER}`] = WORKFLOW_PROTOCOL_VERSION;
1211
- }
1212
- if (callTimeout) {
1213
- baseHeaders[`Upstash-Timeout`] = callTimeout.toString();
1214
- }
1215
- if (failureUrl) {
1216
- baseHeaders[`Upstash-Failure-Callback-Forward-${WORKFLOW_FAILURE_HEADER}`] = "true";
1217
- baseHeaders[`Upstash-Failure-Callback-Forward-Upstash-Workflow-Failure-Callback`] = "true";
1218
- baseHeaders["Upstash-Failure-Callback-Workflow-Runid"] = workflowRunId;
1219
- baseHeaders["Upstash-Failure-Callback-Workflow-Init"] = "false";
1220
- baseHeaders["Upstash-Failure-Callback-Workflow-Url"] = workflowUrl;
1221
- baseHeaders["Upstash-Failure-Callback-Workflow-Calltype"] = "failureCall";
1222
- if (retries !== void 0) {
1223
- baseHeaders["Upstash-Failure-Callback-Retries"] = retries.toString();
1224
- }
1225
- if (flowControl) {
1226
- const { flowControlKey, flowControlValue } = prepareFlowControl(flowControl);
1227
- baseHeaders["Upstash-Failure-Callback-Flow-Control-Key"] = flowControlKey;
1228
- baseHeaders["Upstash-Failure-Callback-Flow-Control-Value"] = flowControlValue;
1229
- }
1230
- if (!step?.callUrl) {
1231
- baseHeaders["Upstash-Failure-Callback"] = failureUrl;
1232
- }
1233
- }
1234
- if (step?.callUrl) {
1235
- baseHeaders["Upstash-Retries"] = callRetries?.toString() ?? "0";
1236
- baseHeaders[WORKFLOW_FEATURE_HEADER] = "WF_NoDelete,InitialBody";
1237
- if (retries !== void 0) {
1238
- baseHeaders["Upstash-Callback-Retries"] = retries.toString();
1239
- baseHeaders["Upstash-Failure-Callback-Retries"] = retries.toString();
1240
- }
1241
- if (callFlowControl) {
1242
- const { flowControlKey, flowControlValue } = prepareFlowControl(callFlowControl);
1243
- baseHeaders["Upstash-Flow-Control-Key"] = flowControlKey;
1244
- baseHeaders["Upstash-Flow-Control-Value"] = flowControlValue;
1245
- }
1246
- if (flowControl) {
1247
- const { flowControlKey, flowControlValue } = prepareFlowControl(flowControl);
1248
- baseHeaders["Upstash-Callback-Flow-Control-Key"] = flowControlKey;
1249
- baseHeaders["Upstash-Callback-Flow-Control-Value"] = flowControlValue;
864
+ var verifyRequest = async (body, signature, verifier) => {
865
+ if (!verifier) {
866
+ return;
867
+ }
868
+ try {
869
+ if (!signature) {
870
+ throw new Error("`Upstash-Signature` header is not passed.");
871
+ }
872
+ const isValid = await verifier.verify({
873
+ body,
874
+ signature
875
+ });
876
+ if (!isValid) {
877
+ throw new Error("Signature in `Upstash-Signature` header is not valid");
878
+ }
879
+ } catch (error) {
880
+ throw new WorkflowError(
881
+ `Failed to verify that the Workflow request comes from QStash: ${error}
882
+
883
+ If signature is missing, trigger the workflow endpoint by publishing your request to QStash instead of calling it directly.
884
+
885
+ If you want to disable QStash Verification, you should clear env variables QSTASH_CURRENT_SIGNING_KEY and QSTASH_NEXT_SIGNING_KEY`
886
+ );
887
+ }
888
+ };
889
+
890
+ // src/context/steps.ts
891
+ var BaseLazyStep = class _BaseLazyStep {
892
+ stepName;
893
+ constructor(stepName) {
894
+ if (!stepName) {
895
+ throw new WorkflowError(
896
+ "A workflow step name cannot be undefined or an empty string. Please provide a name for your workflow step."
897
+ );
898
+ }
899
+ if (typeof stepName !== "string") {
900
+ console.warn(
901
+ "Workflow Warning: A workflow step name must be a string. In a future release, this will throw an error."
902
+ );
903
+ }
904
+ this.stepName = stepName;
905
+ }
906
+ /**
907
+ * parse the out field of a step result.
908
+ *
909
+ * will be called when returning the steps to the context from auto executor
910
+ *
911
+ * @param out field of the step
912
+ * @returns parsed out field
913
+ */
914
+ parseOut(out) {
915
+ if (out === void 0) {
916
+ if (this.allowUndefinedOut) {
917
+ return void 0;
918
+ } else {
919
+ throw new WorkflowError(
920
+ `Error while parsing output of ${this.stepType} step. Expected a string, but got: undefined`
921
+ );
922
+ }
923
+ }
924
+ if (typeof out === "object") {
925
+ if (this.stepType !== "Wait") {
926
+ console.warn(
927
+ `Error while parsing ${this.stepType} step output. Expected a string, but got object. Please reach out to Upstash Support.`
928
+ );
929
+ return out;
930
+ }
931
+ return {
932
+ ...out,
933
+ eventData: _BaseLazyStep.tryParsing(out.eventData)
934
+ };
935
+ }
936
+ if (typeof out !== "string") {
937
+ throw new WorkflowError(
938
+ `Error while parsing output of ${this.stepType} step. Expected a string or undefined, but got: ${typeof out}`
939
+ );
940
+ }
941
+ return this.safeParseOut(out);
942
+ }
943
+ safeParseOut(out) {
944
+ return _BaseLazyStep.tryParsing(out);
945
+ }
946
+ static tryParsing(stepOut) {
947
+ try {
948
+ return JSON.parse(stepOut);
949
+ } catch {
950
+ return stepOut;
951
+ }
952
+ }
953
+ getBody({ step }) {
954
+ step.out = JSON.stringify(step.out);
955
+ return JSON.stringify(step);
956
+ }
957
+ getHeaders({ context, telemetry, invokeCount, step }) {
958
+ return getHeaders({
959
+ initHeaderValue: "false",
960
+ workflowConfig: {
961
+ workflowRunId: context.workflowRunId,
962
+ workflowUrl: context.url,
963
+ failureUrl: context.failureUrl,
964
+ retries: context.retries,
965
+ useJSONContent: false,
966
+ telemetry,
967
+ flowControl: context.flowControl
968
+ },
969
+ userHeaders: context.headers,
970
+ invokeCount,
971
+ stepInfo: {
972
+ step,
973
+ lazyStep: this
974
+ }
975
+ });
976
+ }
977
+ async submitStep({ context, body, headers }) {
978
+ return await context.qstashClient.batch([
979
+ {
980
+ body,
981
+ headers,
982
+ method: "POST",
983
+ url: context.url
984
+ }
985
+ ]);
986
+ }
987
+ };
988
+ var LazyFunctionStep = class extends BaseLazyStep {
989
+ stepFunction;
990
+ stepType = "Run";
991
+ allowUndefinedOut = true;
992
+ constructor(stepName, stepFunction) {
993
+ super(stepName);
994
+ this.stepFunction = stepFunction;
995
+ }
996
+ getPlanStep(concurrent, targetStep) {
997
+ return {
998
+ stepId: 0,
999
+ stepName: this.stepName,
1000
+ stepType: this.stepType,
1001
+ concurrent,
1002
+ targetStep
1003
+ };
1004
+ }
1005
+ async getResultStep(concurrent, stepId) {
1006
+ let result = this.stepFunction();
1007
+ if (result instanceof Promise) {
1008
+ result = await result;
1009
+ }
1010
+ return {
1011
+ stepId,
1012
+ stepName: this.stepName,
1013
+ stepType: this.stepType,
1014
+ out: result,
1015
+ concurrent
1016
+ };
1017
+ }
1018
+ };
1019
+ var LazySleepStep = class extends BaseLazyStep {
1020
+ sleep;
1021
+ stepType = "SleepFor";
1022
+ allowUndefinedOut = true;
1023
+ constructor(stepName, sleep) {
1024
+ super(stepName);
1025
+ this.sleep = sleep;
1026
+ }
1027
+ getPlanStep(concurrent, targetStep) {
1028
+ return {
1029
+ stepId: 0,
1030
+ stepName: this.stepName,
1031
+ stepType: this.stepType,
1032
+ sleepFor: this.sleep,
1033
+ concurrent,
1034
+ targetStep
1035
+ };
1036
+ }
1037
+ async getResultStep(concurrent, stepId) {
1038
+ return await Promise.resolve({
1039
+ stepId,
1040
+ stepName: this.stepName,
1041
+ stepType: this.stepType,
1042
+ sleepFor: this.sleep,
1043
+ concurrent
1044
+ });
1045
+ }
1046
+ async submitStep({ context, body, headers, isParallel }) {
1047
+ return await context.qstashClient.batch([
1048
+ {
1049
+ body,
1050
+ headers,
1051
+ method: "POST",
1052
+ url: context.url,
1053
+ delay: isParallel ? void 0 : this.sleep
1054
+ }
1055
+ ]);
1056
+ }
1057
+ };
1058
+ var LazySleepUntilStep = class extends BaseLazyStep {
1059
+ sleepUntil;
1060
+ stepType = "SleepUntil";
1061
+ allowUndefinedOut = true;
1062
+ constructor(stepName, sleepUntil) {
1063
+ super(stepName);
1064
+ this.sleepUntil = sleepUntil;
1065
+ }
1066
+ getPlanStep(concurrent, targetStep) {
1067
+ return {
1068
+ stepId: 0,
1069
+ stepName: this.stepName,
1070
+ stepType: this.stepType,
1071
+ sleepUntil: this.sleepUntil,
1072
+ concurrent,
1073
+ targetStep
1074
+ };
1075
+ }
1076
+ async getResultStep(concurrent, stepId) {
1077
+ return await Promise.resolve({
1078
+ stepId,
1079
+ stepName: this.stepName,
1080
+ stepType: this.stepType,
1081
+ sleepUntil: this.sleepUntil,
1082
+ concurrent
1083
+ });
1084
+ }
1085
+ safeParseOut() {
1086
+ return void 0;
1087
+ }
1088
+ async submitStep({ context, body, headers, isParallel }) {
1089
+ return await context.qstashClient.batch([
1090
+ {
1091
+ body,
1092
+ headers,
1093
+ method: "POST",
1094
+ url: context.url,
1095
+ notBefore: isParallel ? void 0 : this.sleepUntil
1096
+ }
1097
+ ]);
1098
+ }
1099
+ };
1100
+ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
1101
+ url;
1102
+ method;
1103
+ body;
1104
+ headers;
1105
+ retries;
1106
+ timeout;
1107
+ flowControl;
1108
+ stepType = "Call";
1109
+ allowUndefinedOut = false;
1110
+ constructor(stepName, url, method, body, headers, retries, timeout, flowControl) {
1111
+ super(stepName);
1112
+ this.url = url;
1113
+ this.method = method;
1114
+ this.body = body;
1115
+ this.headers = headers;
1116
+ this.retries = retries;
1117
+ this.timeout = timeout;
1118
+ this.flowControl = flowControl;
1119
+ }
1120
+ getPlanStep(concurrent, targetStep) {
1121
+ return {
1122
+ stepId: 0,
1123
+ stepName: this.stepName,
1124
+ stepType: this.stepType,
1125
+ concurrent,
1126
+ targetStep
1127
+ };
1128
+ }
1129
+ async getResultStep(concurrent, stepId) {
1130
+ return await Promise.resolve({
1131
+ stepId,
1132
+ stepName: this.stepName,
1133
+ stepType: this.stepType,
1134
+ concurrent,
1135
+ callUrl: this.url,
1136
+ callMethod: this.method,
1137
+ callBody: this.body,
1138
+ callHeaders: this.headers
1139
+ });
1140
+ }
1141
+ safeParseOut(out) {
1142
+ const { header, status, body } = JSON.parse(out);
1143
+ const responseHeaders = new Headers(header);
1144
+ if (_LazyCallStep.isText(responseHeaders.get("content-type"))) {
1145
+ const bytes = new Uint8Array(out.length);
1146
+ for (let i = 0; i < out.length; i++) {
1147
+ bytes[i] = out.charCodeAt(i);
1148
+ }
1149
+ const processedResult = new TextDecoder().decode(bytes);
1150
+ const newBody = JSON.parse(processedResult).body;
1151
+ return {
1152
+ status,
1153
+ header,
1154
+ body: BaseLazyStep.tryParsing(newBody)
1155
+ };
1156
+ } else {
1157
+ return { header, status, body };
1250
1158
  }
1251
- } else {
1252
- if (flowControl) {
1253
- const { flowControlKey, flowControlValue } = prepareFlowControl(flowControl);
1254
- baseHeaders["Upstash-Flow-Control-Key"] = flowControlKey;
1255
- baseHeaders["Upstash-Flow-Control-Value"] = flowControlValue;
1159
+ }
1160
+ static applicationContentTypes = [
1161
+ "application/json",
1162
+ "application/xml",
1163
+ "application/javascript",
1164
+ "application/x-www-form-urlencoded",
1165
+ "application/xhtml+xml",
1166
+ "application/ld+json",
1167
+ "application/rss+xml",
1168
+ "application/atom+xml"
1169
+ ];
1170
+ static isText = (contentTypeHeader) => {
1171
+ if (!contentTypeHeader) {
1172
+ return false;
1256
1173
  }
1257
- if (retries !== void 0) {
1258
- baseHeaders["Upstash-Retries"] = retries.toString();
1259
- baseHeaders["Upstash-Failure-Callback-Retries"] = retries.toString();
1174
+ if (_LazyCallStep.applicationContentTypes.some((type) => contentTypeHeader.includes(type))) {
1175
+ return true;
1260
1176
  }
1261
- }
1262
- if (userHeaders) {
1263
- for (const header of userHeaders.keys()) {
1264
- if (step?.callHeaders) {
1265
- baseHeaders[`Upstash-Callback-Forward-${header}`] = userHeaders.get(header);
1266
- } else {
1267
- baseHeaders[`Upstash-Forward-${header}`] = userHeaders.get(header);
1268
- }
1269
- baseHeaders[`Upstash-Failure-Callback-Forward-${header}`] = userHeaders.get(header);
1177
+ if (contentTypeHeader.startsWith("text/")) {
1178
+ return true;
1179
+ }
1180
+ return false;
1181
+ };
1182
+ getBody({ step }) {
1183
+ if (!step.callUrl) {
1184
+ throw new WorkflowError("Incompatible step received in LazyCallStep.getBody");
1270
1185
  }
1186
+ return JSON.stringify(step.callBody);
1271
1187
  }
1272
- if (step?.callHeaders) {
1188
+ getHeaders({ context, telemetry, invokeCount, step }) {
1189
+ const { headers, contentType } = super.getHeaders({ context, telemetry, invokeCount, step });
1190
+ headers["Upstash-Retries"] = this.retries.toString();
1191
+ headers[WORKFLOW_FEATURE_HEADER] = "WF_NoDelete,InitialBody";
1192
+ if (this.flowControl) {
1193
+ const { flowControlKey, flowControlValue } = prepareFlowControl(this.flowControl);
1194
+ headers["Upstash-Flow-Control-Key"] = flowControlKey;
1195
+ headers["Upstash-Flow-Control-Value"] = flowControlValue;
1196
+ }
1197
+ if (this.timeout) {
1198
+ headers["Upstash-Timeout"] = this.timeout.toString();
1199
+ }
1273
1200
  const forwardedHeaders = Object.fromEntries(
1274
- Object.entries(step.callHeaders).map(([header, value]) => [
1275
- `Upstash-Forward-${header}`,
1276
- value
1277
- ])
1201
+ Object.entries(this.headers).map(([header, value]) => [`Upstash-Forward-${header}`, value])
1278
1202
  );
1279
1203
  return {
1280
1204
  headers: {
1281
- ...baseHeaders,
1205
+ ...headers,
1282
1206
  ...forwardedHeaders,
1283
- "Upstash-Callback": workflowUrl,
1284
- "Upstash-Callback-Workflow-RunId": workflowRunId,
1207
+ "Upstash-Callback": context.url,
1208
+ "Upstash-Callback-Workflow-RunId": context.workflowRunId,
1285
1209
  "Upstash-Callback-Workflow-CallType": "fromCallback",
1286
1210
  "Upstash-Callback-Workflow-Init": "false",
1287
- "Upstash-Callback-Workflow-Url": workflowUrl,
1211
+ "Upstash-Callback-Workflow-Url": context.url,
1288
1212
  "Upstash-Callback-Feature-Set": "LazyFetch,InitialBody",
1289
1213
  "Upstash-Callback-Forward-Upstash-Workflow-Callback": "true",
1290
1214
  "Upstash-Callback-Forward-Upstash-Workflow-StepId": step.stepId.toString(),
1291
- "Upstash-Callback-Forward-Upstash-Workflow-StepName": step.stepName,
1292
- "Upstash-Callback-Forward-Upstash-Workflow-StepType": step.stepType,
1215
+ "Upstash-Callback-Forward-Upstash-Workflow-StepName": this.stepName,
1216
+ "Upstash-Callback-Forward-Upstash-Workflow-StepType": this.stepType,
1293
1217
  "Upstash-Callback-Forward-Upstash-Workflow-Concurrent": step.concurrent.toString(),
1294
1218
  "Upstash-Callback-Forward-Upstash-Workflow-ContentType": contentType,
1295
- [`Upstash-Callback-Forward-${WORKFLOW_INVOKE_COUNT_HEADER}`]: (invokeCount ?? 0).toString(),
1296
1219
  "Upstash-Workflow-CallType": "toCallback"
1220
+ },
1221
+ contentType
1222
+ };
1223
+ }
1224
+ async submitStep({ context, headers }) {
1225
+ return await context.qstashClient.batch([
1226
+ {
1227
+ headers,
1228
+ body: JSON.stringify(this.body),
1229
+ method: this.method,
1230
+ url: this.url
1297
1231
  }
1232
+ ]);
1233
+ }
1234
+ };
1235
+ var LazyWaitForEventStep = class extends BaseLazyStep {
1236
+ eventId;
1237
+ timeout;
1238
+ stepType = "Wait";
1239
+ allowUndefinedOut = false;
1240
+ constructor(stepName, eventId, timeout) {
1241
+ super(stepName);
1242
+ this.eventId = eventId;
1243
+ this.timeout = timeout;
1244
+ }
1245
+ getPlanStep(concurrent, targetStep) {
1246
+ return {
1247
+ stepId: 0,
1248
+ stepName: this.stepName,
1249
+ stepType: this.stepType,
1250
+ waitEventId: this.eventId,
1251
+ timeout: this.timeout,
1252
+ concurrent,
1253
+ targetStep
1298
1254
  };
1299
1255
  }
1300
- if (step?.waitEventId) {
1256
+ async getResultStep(concurrent, stepId) {
1257
+ return await Promise.resolve({
1258
+ stepId,
1259
+ stepName: this.stepName,
1260
+ stepType: this.stepType,
1261
+ waitEventId: this.eventId,
1262
+ timeout: this.timeout,
1263
+ concurrent
1264
+ });
1265
+ }
1266
+ safeParseOut(out) {
1267
+ const result = JSON.parse(out);
1301
1268
  return {
1302
- headers: {
1303
- ...baseHeaders,
1304
- "Upstash-Workflow-CallType": "step"
1305
- },
1306
- timeoutHeaders: {
1307
- // to include user headers:
1308
- ...Object.fromEntries(
1309
- Object.entries(baseHeaders).map(([header, value]) => [header, [value]])
1310
- ),
1311
- // to include telemetry headers:
1312
- ...telemetry ? Object.fromEntries(
1313
- Object.entries(getTelemetryHeaders(telemetry)).map(([header, value]) => [
1314
- header,
1315
- [value]
1316
- ])
1317
- ) : {},
1318
- // note: using WORKFLOW_ID_HEADER doesn't work, because Runid -> RunId:
1319
- "Upstash-Workflow-Runid": [workflowRunId],
1320
- [WORKFLOW_INIT_HEADER]: ["false"],
1321
- [WORKFLOW_URL_HEADER]: [workflowUrl],
1322
- "Upstash-Workflow-CallType": ["step"]
1269
+ ...result,
1270
+ eventData: BaseLazyStep.tryParsing(result.eventData)
1271
+ };
1272
+ }
1273
+ getHeaders({ context, telemetry, invokeCount, step }) {
1274
+ const headers = super.getHeaders({ context, telemetry, invokeCount, step });
1275
+ headers.headers["Upstash-Workflow-CallType"] = "step";
1276
+ return headers;
1277
+ }
1278
+ getBody({ context, step, headers, telemetry }) {
1279
+ if (!step.waitEventId) {
1280
+ throw new WorkflowError("Incompatible step received in LazyWaitForEventStep.getBody");
1281
+ }
1282
+ const timeoutHeaders = {
1283
+ // to include user headers:
1284
+ ...Object.fromEntries(Object.entries(headers).map(([header, value]) => [header, [value]])),
1285
+ // to include telemetry headers:
1286
+ ...telemetry ? Object.fromEntries(
1287
+ Object.entries(getTelemetryHeaders(telemetry)).map(([header, value]) => [
1288
+ header,
1289
+ [value]
1290
+ ])
1291
+ ) : {},
1292
+ // note: using WORKFLOW_ID_HEADER doesn't work, because Runid -> RunId:
1293
+ "Upstash-Workflow-Runid": [context.workflowRunId],
1294
+ [WORKFLOW_INIT_HEADER]: ["false"],
1295
+ [WORKFLOW_URL_HEADER]: [context.url],
1296
+ "Upstash-Workflow-CallType": ["step"]
1297
+ };
1298
+ const waitBody = {
1299
+ url: context.url,
1300
+ timeout: step.timeout,
1301
+ timeoutBody: void 0,
1302
+ timeoutUrl: context.url,
1303
+ timeoutHeaders,
1304
+ step: {
1305
+ stepId: step.stepId,
1306
+ stepType: "Wait",
1307
+ stepName: step.stepName,
1308
+ concurrent: step.concurrent,
1309
+ targetStep: step.targetStep
1323
1310
  }
1324
1311
  };
1312
+ return JSON.stringify(waitBody);
1313
+ }
1314
+ async submitStep({ context, body, headers }) {
1315
+ const result = await context.qstashClient.http.request({
1316
+ path: ["v2", "wait", this.eventId],
1317
+ body,
1318
+ headers,
1319
+ method: "POST",
1320
+ parseResponseAsJson: false
1321
+ });
1322
+ return [result];
1325
1323
  }
1326
- return { headers: baseHeaders };
1327
1324
  };
1328
- var verifyRequest = async (body, signature, verifier) => {
1329
- if (!verifier) {
1330
- return;
1325
+ var LazyNotifyStep = class extends LazyFunctionStep {
1326
+ stepType = "Notify";
1327
+ constructor(stepName, eventId, eventData, requester) {
1328
+ super(stepName, async () => {
1329
+ const notifyResponse = await makeNotifyRequest(requester, eventId, eventData);
1330
+ return {
1331
+ eventId,
1332
+ eventData,
1333
+ notifyResponse
1334
+ };
1335
+ });
1331
1336
  }
1332
- try {
1333
- if (!signature) {
1334
- throw new Error("`Upstash-Signature` header is not passed.");
1337
+ safeParseOut(out) {
1338
+ const result = JSON.parse(out);
1339
+ return {
1340
+ ...result,
1341
+ eventData: BaseLazyStep.tryParsing(result.eventData)
1342
+ };
1343
+ }
1344
+ };
1345
+ var LazyInvokeStep = class extends BaseLazyStep {
1346
+ stepType = "Invoke";
1347
+ params;
1348
+ allowUndefinedOut = false;
1349
+ /**
1350
+ * workflow id of the invoked workflow
1351
+ */
1352
+ workflowId;
1353
+ constructor(stepName, {
1354
+ workflow,
1355
+ body,
1356
+ headers = {},
1357
+ workflowRunId,
1358
+ retries,
1359
+ flowControl
1360
+ }) {
1361
+ super(stepName);
1362
+ this.params = {
1363
+ workflow,
1364
+ body,
1365
+ headers,
1366
+ workflowRunId: getWorkflowRunId(workflowRunId),
1367
+ retries,
1368
+ flowControl
1369
+ };
1370
+ const { workflowId } = workflow;
1371
+ if (!workflowId) {
1372
+ throw new WorkflowError("You can only invoke workflow which has a workflowId");
1335
1373
  }
1336
- const isValid = await verifier.verify({
1374
+ this.workflowId = workflowId;
1375
+ }
1376
+ getPlanStep(concurrent, targetStep) {
1377
+ return {
1378
+ stepId: 0,
1379
+ stepName: this.stepName,
1380
+ stepType: this.stepType,
1381
+ concurrent,
1382
+ targetStep
1383
+ };
1384
+ }
1385
+ /**
1386
+ * won't be used as it's the server who will add the result step
1387
+ * in Invoke step.
1388
+ */
1389
+ getResultStep(concurrent, stepId) {
1390
+ return Promise.resolve({
1391
+ stepId,
1392
+ stepName: this.stepName,
1393
+ stepType: this.stepType,
1394
+ concurrent
1395
+ });
1396
+ }
1397
+ safeParseOut(out) {
1398
+ const result = JSON.parse(out);
1399
+ return {
1400
+ ...result,
1401
+ body: BaseLazyStep.tryParsing(result.body)
1402
+ };
1403
+ }
1404
+ getBody({ context, step, telemetry, invokeCount }) {
1405
+ const { headers: invokerHeaders } = getHeaders({
1406
+ initHeaderValue: "false",
1407
+ workflowConfig: {
1408
+ workflowRunId: context.workflowRunId,
1409
+ workflowUrl: context.url,
1410
+ failureUrl: context.failureUrl,
1411
+ retries: context.retries,
1412
+ telemetry,
1413
+ flowControl: context.flowControl,
1414
+ useJSONContent: false
1415
+ },
1416
+ userHeaders: context.headers,
1417
+ invokeCount
1418
+ });
1419
+ invokerHeaders["Upstash-Workflow-Runid"] = context.workflowRunId;
1420
+ const request = {
1421
+ body: JSON.stringify(this.params.body),
1422
+ headers: Object.fromEntries(
1423
+ Object.entries(invokerHeaders).map((pairs) => [pairs[0], [pairs[1]]])
1424
+ ),
1425
+ workflowRunId: context.workflowRunId,
1426
+ workflowUrl: context.url,
1427
+ step
1428
+ };
1429
+ return JSON.stringify(request);
1430
+ }
1431
+ getHeaders({ context, telemetry, invokeCount }) {
1432
+ const {
1433
+ workflow,
1434
+ headers = {},
1435
+ workflowRunId = getWorkflowRunId(),
1436
+ retries,
1437
+ flowControl
1438
+ } = this.params;
1439
+ const newUrl = context.url.replace(/[^/]+$/, this.workflowId);
1440
+ const {
1441
+ retries: workflowRetries,
1442
+ failureFunction,
1443
+ failureUrl,
1444
+ useJSONContent,
1445
+ flowControl: workflowFlowControl
1446
+ } = workflow.options;
1447
+ const { headers: triggerHeaders, contentType } = getHeaders({
1448
+ initHeaderValue: "true",
1449
+ workflowConfig: {
1450
+ workflowRunId,
1451
+ workflowUrl: newUrl,
1452
+ retries: retries ?? workflowRetries,
1453
+ telemetry,
1454
+ failureUrl: failureFunction ? newUrl : failureUrl,
1455
+ flowControl: flowControl ?? workflowFlowControl,
1456
+ useJSONContent: useJSONContent ?? false
1457
+ },
1458
+ invokeCount: invokeCount + 1,
1459
+ userHeaders: new Headers(headers)
1460
+ });
1461
+ triggerHeaders["Upstash-Workflow-Invoke"] = "true";
1462
+ return { headers: triggerHeaders, contentType };
1463
+ }
1464
+ async submitStep({ context, body, headers }) {
1465
+ const newUrl = context.url.replace(/[^/]+$/, this.workflowId);
1466
+ const result = await context.qstashClient.publish({
1467
+ headers,
1468
+ method: "POST",
1337
1469
  body,
1338
- signature
1470
+ url: newUrl
1339
1471
  });
1340
- if (!isValid) {
1341
- throw new Error("Signature in `Upstash-Signature` header is not valid");
1342
- }
1343
- } catch (error) {
1344
- throw new WorkflowError(
1345
- `Failed to verify that the Workflow request comes from QStash: ${error}
1472
+ return [result];
1473
+ }
1474
+ };
1346
1475
 
1347
- If signature is missing, trigger the workflow endpoint by publishing your request to QStash instead of calling it directly.
1476
+ // src/agents/constants.ts
1477
+ var AGENT_NAME_HEADER = "upstash-agent-name";
1478
+ var MANAGER_AGENT_PROMPT = `You are an agent orchestrating other AI Agents.
1348
1479
 
1349
- If you want to disable QStash Verification, you should clear env variables QSTASH_CURRENT_SIGNING_KEY and QSTASH_NEXT_SIGNING_KEY`
1480
+ These other agents have tools available to them.
1481
+
1482
+ Given a prompt, utilize these agents to address requests.
1483
+
1484
+ 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.
1485
+
1486
+ Avoid calling the same agent twice in one turn. Instead, prefer to call it once but provide everything
1487
+ you need from that agent.
1488
+ `;
1489
+
1490
+ // src/qstash/headers.ts
1491
+ var WorkflowHeaders = class {
1492
+ userHeaders;
1493
+ workflowConfig;
1494
+ invokeCount;
1495
+ initHeaderValue;
1496
+ stepInfo;
1497
+ headers;
1498
+ constructor({
1499
+ userHeaders,
1500
+ workflowConfig,
1501
+ invokeCount,
1502
+ initHeaderValue,
1503
+ stepInfo
1504
+ }) {
1505
+ this.userHeaders = userHeaders;
1506
+ this.workflowConfig = workflowConfig;
1507
+ this.invokeCount = invokeCount;
1508
+ this.initHeaderValue = initHeaderValue;
1509
+ this.stepInfo = stepInfo;
1510
+ this.headers = {
1511
+ rawHeaders: {},
1512
+ workflowHeaders: {},
1513
+ failureHeaders: {}
1514
+ };
1515
+ }
1516
+ getHeaders() {
1517
+ this.addBaseHeaders();
1518
+ this.addRetries();
1519
+ this.addFlowControl();
1520
+ this.addUserHeaders();
1521
+ this.addInvokeCount();
1522
+ this.addFailureUrl();
1523
+ const contentType = this.addContentType();
1524
+ return this.prefixHeaders(contentType);
1525
+ }
1526
+ addBaseHeaders() {
1527
+ this.headers.rawHeaders = {
1528
+ ...this.headers.rawHeaders,
1529
+ [WORKFLOW_INIT_HEADER]: this.initHeaderValue,
1530
+ [WORKFLOW_ID_HEADER]: this.workflowConfig.workflowRunId,
1531
+ [WORKFLOW_URL_HEADER]: this.workflowConfig.workflowUrl,
1532
+ [WORKFLOW_FEATURE_HEADER]: "LazyFetch,InitialBody",
1533
+ [WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION,
1534
+ ...this.workflowConfig.telemetry ? getTelemetryHeaders(this.workflowConfig.telemetry) : {},
1535
+ ...this.workflowConfig.telemetry && this.stepInfo?.lazyStep instanceof LazyCallStep && this.stepInfo.lazyStep.headers[AGENT_NAME_HEADER] ? { [TELEMETRY_HEADER_AGENT]: "true" } : {}
1536
+ };
1537
+ if (this.stepInfo?.lazyStep.stepType !== "Call") {
1538
+ this.headers.rawHeaders[`Upstash-Forward-${WORKFLOW_PROTOCOL_VERSION_HEADER}`] = WORKFLOW_PROTOCOL_VERSION;
1539
+ }
1540
+ }
1541
+ addInvokeCount() {
1542
+ if (this.invokeCount === void 0 || this.invokeCount === 0) {
1543
+ return;
1544
+ }
1545
+ const invokeCount = this.invokeCount.toString();
1546
+ this.headers.workflowHeaders[`Forward-${WORKFLOW_INVOKE_COUNT_HEADER}`] = invokeCount;
1547
+ if (this.workflowConfig.failureUrl) {
1548
+ this.headers.failureHeaders[`Forward-${WORKFLOW_INVOKE_COUNT_HEADER}`] = invokeCount;
1549
+ }
1550
+ if (this.stepInfo?.lazyStep instanceof LazyCallStep) {
1551
+ this.headers.rawHeaders[`Upstash-Forward-${WORKFLOW_INVOKE_COUNT_HEADER}`] = invokeCount;
1552
+ }
1553
+ }
1554
+ addRetries() {
1555
+ if (this.workflowConfig.retries === void 0 || this.workflowConfig.retries === DEFAULT_RETRIES) {
1556
+ return;
1557
+ }
1558
+ const retries = this.workflowConfig.retries.toString();
1559
+ this.headers.workflowHeaders["Retries"] = retries;
1560
+ if (this.workflowConfig.failureUrl) {
1561
+ this.headers.failureHeaders["Retries"] = retries;
1562
+ }
1563
+ }
1564
+ addFlowControl() {
1565
+ if (!this.workflowConfig.flowControl) {
1566
+ return;
1567
+ }
1568
+ const { flowControlKey, flowControlValue } = prepareFlowControl(
1569
+ this.workflowConfig.flowControl
1570
+ );
1571
+ this.headers.workflowHeaders["Flow-Control-Key"] = flowControlKey;
1572
+ this.headers.workflowHeaders["Flow-Control-Value"] = flowControlValue;
1573
+ if (this.workflowConfig.failureUrl) {
1574
+ this.headers.failureHeaders["Flow-Control-Key"] = flowControlKey;
1575
+ this.headers.failureHeaders["Flow-Control-Value"] = flowControlValue;
1576
+ }
1577
+ }
1578
+ addUserHeaders() {
1579
+ for (const [key, value] of this.userHeaders.entries()) {
1580
+ const forwardKey = `Forward-${key}`;
1581
+ this.headers.workflowHeaders[forwardKey] = value;
1582
+ if (this.workflowConfig.failureUrl) {
1583
+ this.headers.failureHeaders[forwardKey] = value;
1584
+ }
1585
+ }
1586
+ }
1587
+ addFailureUrl() {
1588
+ if (!this.workflowConfig.failureUrl) {
1589
+ return;
1590
+ }
1591
+ this.headers.workflowHeaders["Failure-Callback"] = this.workflowConfig.failureUrl;
1592
+ this.headers.failureHeaders[`Forward-${WORKFLOW_FAILURE_HEADER}`] = "true";
1593
+ this.headers.failureHeaders[`Forward-Upstash-Workflow-Failure-Callback`] = "true";
1594
+ this.headers.failureHeaders["Workflow-Runid"] = this.workflowConfig.workflowRunId;
1595
+ this.headers.failureHeaders["Workflow-Init"] = "false";
1596
+ this.headers.failureHeaders["Workflow-Url"] = this.workflowConfig.workflowUrl;
1597
+ this.headers.failureHeaders["Workflow-Calltype"] = "failureCall";
1598
+ this.headers.failureHeaders["Feature-Set"] = "LazyFetch,InitialBody";
1599
+ if (this.workflowConfig.retries !== void 0 && this.workflowConfig.retries !== DEFAULT_RETRIES) {
1600
+ this.headers.failureHeaders["Retries"] = this.workflowConfig.retries.toString();
1601
+ }
1602
+ }
1603
+ addContentType() {
1604
+ if (this.workflowConfig.useJSONContent) {
1605
+ this.headers.rawHeaders["content-type"] = "application/json";
1606
+ return "application/json";
1607
+ }
1608
+ const callHeaders = new Headers(
1609
+ this.stepInfo?.lazyStep instanceof LazyCallStep ? this.stepInfo.lazyStep.headers : {}
1350
1610
  );
1611
+ 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;
1612
+ this.headers.rawHeaders["content-type"] = contentType;
1613
+ return contentType;
1614
+ }
1615
+ prefixHeaders(contentType) {
1616
+ const { rawHeaders, workflowHeaders, failureHeaders } = this.headers;
1617
+ const isCall = this.stepInfo?.lazyStep.stepType === "Call";
1618
+ return {
1619
+ headers: {
1620
+ ...rawHeaders,
1621
+ ...addPrefixToHeaders(workflowHeaders, isCall ? "Upstash-Callback-" : "Upstash-"),
1622
+ ...addPrefixToHeaders(failureHeaders, "Upstash-Failure-Callback-"),
1623
+ ...isCall ? addPrefixToHeaders(failureHeaders, "Upstash-Callback-Failure-Callback-") : {}
1624
+ },
1625
+ contentType
1626
+ };
1351
1627
  }
1352
1628
  };
1629
+ function addPrefixToHeaders(headers, prefix) {
1630
+ const prefixedHeaders = {};
1631
+ for (const [key, value] of Object.entries(headers)) {
1632
+ prefixedHeaders[`${prefix}${key}`] = value;
1633
+ }
1634
+ return prefixedHeaders;
1635
+ }
1353
1636
  var prepareFlowControl = (flowControl) => {
1354
1637
  const parallelism = flowControl.parallelism?.toString();
1355
- const rate = flowControl.ratePerSecond?.toString();
1638
+ const rate = (flowControl.rate ?? flowControl.ratePerSecond)?.toString();
1639
+ const period = typeof flowControl.period === "number" ? `${flowControl.period}s` : flowControl.period;
1356
1640
  const controlValue = [
1357
1641
  parallelism ? `parallelism=${parallelism}` : void 0,
1358
- rate ? `rate=${rate}` : void 0
1642
+ rate ? `rate=${rate}` : void 0,
1643
+ period ? `period=${period}` : void 0
1359
1644
  ].filter(Boolean);
1360
1645
  if (controlValue.length === 0) {
1361
- throw new import_qstash3.QstashError("Provide at least one of parallelism or ratePerSecond for flowControl");
1646
+ throw new import_qstash4.QstashError("Provide at least one of parallelism or ratePerSecond for flowControl");
1362
1647
  }
1363
1648
  return {
1364
1649
  flowControlKey: flowControl.key,
1365
- flowControlValue: controlValue.join(", ")
1366
- };
1367
- };
1368
-
1369
- // src/context/auto-executor.ts
1370
- var import_qstash4 = require("@upstash/qstash");
1371
-
1372
- // src/serve/serve-many.ts
1373
- var getWorkflowId = (url) => {
1374
- const components = url.split("/");
1375
- const lastComponent = components[components.length - 1];
1376
- return lastComponent.split("?")[0];
1377
- };
1378
- var serveManyBase = ({
1379
- workflows,
1380
- getUrl,
1381
- serveMethod,
1382
- options
1650
+ flowControlValue: controlValue.join(", ")
1651
+ };
1652
+ };
1653
+ var getHeaders = (params) => {
1654
+ const workflowHeaders = new WorkflowHeaders(params);
1655
+ return workflowHeaders.getHeaders();
1656
+ };
1657
+
1658
+ // src/qstash/submit-steps.ts
1659
+ var submitParallelSteps = async ({
1660
+ context,
1661
+ steps,
1662
+ initialStepCount,
1663
+ invokeCount,
1664
+ telemetry,
1665
+ debug
1383
1666
  }) => {
1384
- const workflowIds = [];
1385
- const workflowMap = Object.fromEntries(
1386
- Object.entries(workflows).map((workflow) => {
1387
- const workflowId = workflow[0];
1388
- if (workflowIds.includes(workflowId)) {
1389
- throw new WorkflowError(
1390
- `Duplicate workflow name found: '${workflowId}'. Please set different workflow names in serveMany.`
1391
- );
1392
- }
1393
- if (workflowId.includes("/")) {
1394
- throw new WorkflowError(
1395
- `Invalid workflow name found: '${workflowId}'. Workflow name cannot contain '/'.`
1396
- );
1397
- }
1398
- workflowIds.push(workflowId);
1399
- workflow[1].workflowId = workflowId;
1400
- workflow[1].options = {
1401
- ...options,
1402
- ...workflow[1].options
1667
+ const planSteps = steps.map(
1668
+ (step, index) => step.getPlanStep(steps.length, initialStepCount + index)
1669
+ );
1670
+ await debug?.log("SUBMIT", "SUBMIT_STEP", {
1671
+ length: planSteps.length,
1672
+ steps: planSteps
1673
+ });
1674
+ const result = await context.qstashClient.batch(
1675
+ planSteps.map((planStep) => {
1676
+ const { headers } = getHeaders({
1677
+ initHeaderValue: "false",
1678
+ workflowConfig: {
1679
+ workflowRunId: context.workflowRunId,
1680
+ workflowUrl: context.url,
1681
+ failureUrl: context.failureUrl,
1682
+ retries: context.retries,
1683
+ flowControl: context.flowControl,
1684
+ telemetry
1685
+ },
1686
+ userHeaders: context.headers,
1687
+ invokeCount
1688
+ });
1689
+ return {
1690
+ headers,
1691
+ method: "POST",
1692
+ url: context.url,
1693
+ body: JSON.stringify(planStep),
1694
+ notBefore: planStep.sleepUntil,
1695
+ delay: planStep.sleepFor
1403
1696
  };
1404
- const params = [workflow[1].routeFunction, workflow[1].options];
1405
- const handler = serveMethod(...params);
1406
- return [workflowId, handler];
1407
1697
  })
1408
1698
  );
1409
- return {
1410
- handler: async (...params) => {
1411
- const url = getUrl(...params);
1412
- const pickedWorkflowId = getWorkflowId(url);
1413
- if (!pickedWorkflowId) {
1414
- return new Response(
1415
- `Unexpected request in serveMany. workflowId not set. Please update the URL of your request.`,
1416
- {
1417
- status: 404
1418
- }
1419
- );
1420
- }
1421
- const workflow = workflowMap[pickedWorkflowId];
1422
- if (!workflow) {
1423
- return new Response(
1424
- `No workflows in serveMany found for '${pickedWorkflowId}'. Please update the URL of your request.`,
1425
- {
1426
- status: 404
1427
- }
1428
- );
1429
- }
1430
- return await workflow(...params);
1431
- }
1432
- };
1699
+ await debug?.log("INFO", "SUBMIT_STEP", {
1700
+ messageIds: result.map((message) => {
1701
+ return {
1702
+ message: message.messageId
1703
+ };
1704
+ })
1705
+ });
1706
+ throw new WorkflowAbort(planSteps[0].stepName, planSteps[0]);
1433
1707
  };
1434
- var invokeWorkflow = async ({
1435
- settings,
1436
- invokeStep,
1708
+ var submitSingleStep = async ({
1437
1709
  context,
1710
+ lazyStep,
1711
+ stepId,
1438
1712
  invokeCount,
1439
- telemetry
1713
+ concurrency,
1714
+ telemetry,
1715
+ debug
1440
1716
  }) => {
1441
- const {
1442
- body,
1443
- workflow,
1444
- headers = {},
1445
- workflowRunId = getWorkflowRunId(),
1446
- retries,
1447
- flowControl
1448
- } = settings;
1449
- const { workflowId } = workflow;
1450
- const {
1451
- retries: workflowRetries,
1452
- failureFunction,
1453
- failureUrl,
1454
- useJSONContent,
1455
- flowControl: workflowFlowControl
1456
- } = workflow.options;
1457
- if (!workflowId) {
1458
- throw new WorkflowError("You can only invoke workflow which has a workflowId");
1459
- }
1460
- const { headers: invokerHeaders } = getHeaders({
1461
- initHeaderValue: "false",
1462
- workflowRunId: context.workflowRunId,
1463
- workflowUrl: context.url,
1464
- userHeaders: context.headers,
1465
- failureUrl: context.failureUrl,
1466
- retries: context.retries,
1467
- telemetry,
1717
+ const resultStep = await lazyStep.getResultStep(concurrency, stepId);
1718
+ await debug?.log("INFO", "RUN_SINGLE", {
1719
+ fromRequest: false,
1720
+ step: resultStep,
1721
+ stepCount: stepId
1722
+ });
1723
+ const { headers } = lazyStep.getHeaders({
1724
+ context,
1725
+ step: resultStep,
1468
1726
  invokeCount,
1469
- flowControl: context.flowControl
1727
+ telemetry
1470
1728
  });
1471
- invokerHeaders["Upstash-Workflow-Runid"] = context.workflowRunId;
1472
- const newUrl = context.url.replace(/[^/]+$/, workflowId);
1473
- const { headers: triggerHeaders } = getHeaders({
1474
- initHeaderValue: "true",
1475
- workflowRunId,
1476
- workflowUrl: newUrl,
1477
- userHeaders: new Headers(headers),
1478
- retries: retries ?? workflowRetries,
1479
- telemetry,
1480
- failureUrl: failureFunction ? newUrl : failureUrl,
1481
- invokeCount: invokeCount + 1,
1482
- flowControl: flowControl ?? workflowFlowControl
1729
+ const body = lazyStep.getBody({
1730
+ context,
1731
+ step: resultStep,
1732
+ headers,
1733
+ invokeCount,
1734
+ telemetry
1483
1735
  });
1484
- triggerHeaders["Upstash-Workflow-Invoke"] = "true";
1485
- if (useJSONContent) {
1486
- triggerHeaders["content-type"] = "application/json";
1487
- }
1488
- const request = {
1489
- body: JSON.stringify(body),
1490
- headers: Object.fromEntries(
1491
- Object.entries(invokerHeaders).map((pairs) => [pairs[0], [pairs[1]]])
1492
- ),
1493
- workflowRunId: context.workflowRunId,
1494
- workflowUrl: context.url,
1495
- step: invokeStep
1496
- };
1497
- await context.qstashClient.publish({
1498
- headers: triggerHeaders,
1499
- method: "POST",
1500
- body: JSON.stringify(request),
1501
- url: newUrl
1736
+ await debug?.log("SUBMIT", "SUBMIT_STEP", {
1737
+ length: 1,
1738
+ steps: [resultStep]
1739
+ });
1740
+ const submitResult = await lazyStep.submitStep({
1741
+ context,
1742
+ body,
1743
+ headers,
1744
+ isParallel: concurrency !== NO_CONCURRENCY,
1745
+ invokeCount,
1746
+ step: resultStep,
1747
+ telemetry
1502
1748
  });
1749
+ await debug?.log("INFO", "SUBMIT_STEP", {
1750
+ messageIds: submitResult.map((message) => {
1751
+ return {
1752
+ message: message.messageId
1753
+ };
1754
+ })
1755
+ });
1756
+ return resultStep;
1503
1757
  };
1504
1758
 
1505
1759
  // src/context/auto-executor.ts
@@ -1606,14 +1860,16 @@ var AutoExecutor = class _AutoExecutor {
1606
1860
  });
1607
1861
  return lazyStep.parseOut(step.out);
1608
1862
  }
1609
- const resultStep = await lazyStep.getResultStep(NO_CONCURRENCY, this.stepCount);
1610
- await this.debug?.log("INFO", "RUN_SINGLE", {
1611
- fromRequest: false,
1612
- step: resultStep,
1613
- stepCount: this.stepCount
1863
+ const resultStep = await submitSingleStep({
1864
+ context: this.context,
1865
+ lazyStep,
1866
+ stepId: this.stepCount,
1867
+ invokeCount: this.invokeCount,
1868
+ concurrency: 1,
1869
+ telemetry: this.telemetry,
1870
+ debug: this.debug
1614
1871
  });
1615
- await this.submitStepsToQStash([resultStep], [lazyStep]);
1616
- return resultStep.out;
1872
+ throw new WorkflowAbort(lazyStep.stepName, resultStep);
1617
1873
  }
1618
1874
  /**
1619
1875
  * Runs steps in parallel.
@@ -1641,10 +1897,14 @@ var AutoExecutor = class _AutoExecutor {
1641
1897
  });
1642
1898
  switch (parallelCallState) {
1643
1899
  case "first": {
1644
- const planSteps = parallelSteps.map(
1645
- (parallelStep, index) => parallelStep.getPlanStep(parallelSteps.length, initialStepCount + index)
1646
- );
1647
- await this.submitStepsToQStash(planSteps, parallelSteps);
1900
+ await submitParallelSteps({
1901
+ context: this.context,
1902
+ steps: parallelSteps,
1903
+ initialStepCount,
1904
+ invokeCount: this.invokeCount,
1905
+ telemetry: this.telemetry,
1906
+ debug: this.debug
1907
+ });
1648
1908
  break;
1649
1909
  }
1650
1910
  case "partial": {
@@ -1658,13 +1918,18 @@ var AutoExecutor = class _AutoExecutor {
1658
1918
  validateStep(parallelSteps[stepIndex], planStep);
1659
1919
  try {
1660
1920
  const parallelStep = parallelSteps[stepIndex];
1661
- const resultStep = await parallelStep.getResultStep(
1662
- parallelSteps.length,
1663
- planStep.targetStep
1664
- );
1665
- await this.submitStepsToQStash([resultStep], [parallelStep]);
1921
+ const resultStep = await submitSingleStep({
1922
+ context: this.context,
1923
+ lazyStep: parallelStep,
1924
+ stepId: planStep.targetStep,
1925
+ invokeCount: this.invokeCount,
1926
+ concurrency: parallelSteps.length,
1927
+ telemetry: this.telemetry,
1928
+ debug: this.debug
1929
+ });
1930
+ throw new WorkflowAbort(parallelStep.stepName, resultStep);
1666
1931
  } catch (error) {
1667
- if (error instanceof WorkflowAbort || error instanceof import_qstash4.QstashError && error.status === 400) {
1932
+ if (error instanceof WorkflowAbort || error instanceof import_qstash5.QstashError && error.status === 400) {
1668
1933
  throw error;
1669
1934
  }
1670
1935
  throw new WorkflowError(
@@ -1720,128 +1985,6 @@ var AutoExecutor = class _AutoExecutor {
1720
1985
  return "discard";
1721
1986
  }
1722
1987
  }
1723
- /**
1724
- * sends the steps to QStash as batch
1725
- *
1726
- * @param steps steps to send
1727
- */
1728
- async submitStepsToQStash(steps, lazySteps) {
1729
- if (steps.length === 0) {
1730
- throw new WorkflowError(
1731
- `Unable to submit steps to QStash. Provided list is empty. Current step: ${this.stepCount}`
1732
- );
1733
- }
1734
- await this.debug?.log("SUBMIT", "SUBMIT_STEP", {
1735
- length: steps.length,
1736
- steps
1737
- });
1738
- if (steps[0].waitEventId && steps.length === 1) {
1739
- const waitStep = steps[0];
1740
- const { headers, timeoutHeaders } = getHeaders({
1741
- initHeaderValue: "false",
1742
- workflowRunId: this.context.workflowRunId,
1743
- workflowUrl: this.context.url,
1744
- userHeaders: this.context.headers,
1745
- step: waitStep,
1746
- failureUrl: this.context.failureUrl,
1747
- retries: this.context.retries,
1748
- telemetry: this.telemetry,
1749
- invokeCount: this.invokeCount,
1750
- flowControl: this.context.flowControl
1751
- });
1752
- const waitBody = {
1753
- url: this.context.url,
1754
- timeout: waitStep.timeout,
1755
- timeoutBody: void 0,
1756
- timeoutUrl: this.context.url,
1757
- timeoutHeaders,
1758
- step: {
1759
- stepId: waitStep.stepId,
1760
- stepType: "Wait",
1761
- stepName: waitStep.stepName,
1762
- concurrent: waitStep.concurrent,
1763
- targetStep: waitStep.targetStep
1764
- }
1765
- };
1766
- await this.context.qstashClient.http.request({
1767
- path: ["v2", "wait", waitStep.waitEventId],
1768
- body: JSON.stringify(waitBody),
1769
- headers,
1770
- method: "POST",
1771
- parseResponseAsJson: false
1772
- });
1773
- throw new WorkflowAbort(waitStep.stepName, waitStep);
1774
- }
1775
- if (steps.length === 1 && lazySteps[0] instanceof LazyInvokeStep) {
1776
- const invokeStep = steps[0];
1777
- const lazyInvokeStep = lazySteps[0];
1778
- await invokeWorkflow({
1779
- settings: lazyInvokeStep.params,
1780
- invokeStep,
1781
- context: this.context,
1782
- invokeCount: this.invokeCount,
1783
- telemetry: this.telemetry
1784
- });
1785
- throw new WorkflowAbort(invokeStep.stepName, invokeStep);
1786
- }
1787
- const result = await this.context.qstashClient.batch(
1788
- steps.map((singleStep, index) => {
1789
- const lazyStep = lazySteps[index];
1790
- const { headers } = getHeaders({
1791
- initHeaderValue: "false",
1792
- workflowRunId: this.context.workflowRunId,
1793
- workflowUrl: this.context.url,
1794
- userHeaders: this.context.headers,
1795
- step: singleStep,
1796
- failureUrl: this.context.failureUrl,
1797
- retries: this.context.retries,
1798
- callRetries: lazyStep instanceof LazyCallStep ? lazyStep.retries : void 0,
1799
- callTimeout: lazyStep instanceof LazyCallStep ? lazyStep.timeout : void 0,
1800
- telemetry: this.telemetry,
1801
- invokeCount: this.invokeCount,
1802
- flowControl: this.context.flowControl,
1803
- callFlowControl: lazyStep instanceof LazyCallStep ? lazyStep.flowControl : void 0
1804
- });
1805
- const willWait = singleStep.concurrent === NO_CONCURRENCY || singleStep.stepId === 0;
1806
- singleStep.out = JSON.stringify(singleStep.out);
1807
- return singleStep.callUrl && lazyStep instanceof LazyCallStep ? (
1808
- // if the step is a third party call, we call the third party
1809
- // url (singleStep.callUrl) and pass information about the workflow
1810
- // in the headers (handled in getHeaders). QStash makes the request
1811
- // to callUrl and returns the result to Workflow endpoint.
1812
- // handleThirdPartyCallResult method sends the result of the third
1813
- // party call to QStash.
1814
- {
1815
- headers,
1816
- method: singleStep.callMethod,
1817
- body: JSON.stringify(singleStep.callBody),
1818
- url: singleStep.callUrl
1819
- }
1820
- ) : (
1821
- // if the step is not a third party call, we use workflow
1822
- // endpoint (context.url) as URL when calling QStash. QStash
1823
- // calls us back with the updated steps list.
1824
- {
1825
- headers,
1826
- method: "POST",
1827
- body: JSON.stringify(singleStep),
1828
- url: this.context.url,
1829
- notBefore: willWait ? singleStep.sleepUntil : void 0,
1830
- delay: willWait ? singleStep.sleepFor : void 0
1831
- }
1832
- );
1833
- })
1834
- );
1835
- const _result = result;
1836
- await this.debug?.log("INFO", "SUBMIT_STEP", {
1837
- messageIds: _result.map((message) => {
1838
- return {
1839
- message: message.messageId
1840
- };
1841
- })
1842
- });
1843
- throw new WorkflowAbort(steps[0].stepName, steps[0]);
1844
- }
1845
1988
  /**
1846
1989
  * Get the promise by executing the lazt steps list. If there is a single
1847
1990
  * step, we call `runSingle`. Otherwise `runParallel` is called.
@@ -1915,7 +2058,7 @@ var sortSteps = (steps) => {
1915
2058
  };
1916
2059
 
1917
2060
  // src/context/api/anthropic.ts
1918
- var import_qstash5 = require("@upstash/qstash");
2061
+ var import_qstash6 = require("@upstash/qstash");
1919
2062
 
1920
2063
  // src/context/provider.ts
1921
2064
  var getProviderInfo = (api) => {
@@ -1979,7 +2122,7 @@ var AnthropicAPI = class extends BaseWorkflowApi {
1979
2122
  return await this.callApi(stepName, {
1980
2123
  api: {
1981
2124
  name: "llm",
1982
- provider: (0, import_qstash5.anthropic)({ token })
2125
+ provider: (0, import_qstash6.anthropic)({ token })
1983
2126
  },
1984
2127
  ...parameters
1985
2128
  });
@@ -1987,12 +2130,12 @@ var AnthropicAPI = class extends BaseWorkflowApi {
1987
2130
  };
1988
2131
 
1989
2132
  // src/context/api/openai.ts
1990
- var import_qstash6 = require("@upstash/qstash");
2133
+ var import_qstash7 = require("@upstash/qstash");
1991
2134
  var OpenAIAPI = class extends BaseWorkflowApi {
1992
2135
  async call(stepName, settings) {
1993
2136
  const { token, organization, operation, baseURL, ...parameters } = settings;
1994
2137
  const useOpenAI = baseURL === void 0;
1995
- const provider = useOpenAI ? (0, import_qstash6.openai)({ token, organization }) : (0, import_qstash6.custom)({ baseUrl: baseURL, token });
2138
+ const provider = useOpenAI ? (0, import_qstash7.openai)({ token, organization }) : (0, import_qstash7.custom)({ baseUrl: baseURL, token });
1996
2139
  return await this.callApi(stepName, {
1997
2140
  api: {
1998
2141
  name: "llm",
@@ -2004,14 +2147,14 @@ var OpenAIAPI = class extends BaseWorkflowApi {
2004
2147
  };
2005
2148
 
2006
2149
  // src/context/api/resend.ts
2007
- var import_qstash7 = require("@upstash/qstash");
2150
+ var import_qstash8 = require("@upstash/qstash");
2008
2151
  var ResendAPI = class extends BaseWorkflowApi {
2009
2152
  async call(stepName, settings) {
2010
2153
  const { token, batch = false, ...parameters } = settings;
2011
2154
  return await this.callApi(stepName, {
2012
2155
  api: {
2013
2156
  name: "email",
2014
- provider: (0, import_qstash7.resend)({ token, batch })
2157
+ provider: (0, import_qstash8.resend)({ token, batch })
2015
2158
  },
2016
2159
  ...parameters
2017
2160
  });
@@ -2038,28 +2181,11 @@ var WorkflowApi = class extends BaseWorkflowApi {
2038
2181
  };
2039
2182
 
2040
2183
  // src/agents/index.ts
2041
- var import_openai3 = require("@ai-sdk/openai");
2042
-
2043
- // src/agents/adapters.ts
2044
2184
  var import_openai2 = require("@ai-sdk/openai");
2045
- var import_ai = require("ai");
2046
-
2047
- // src/agents/constants.ts
2048
- var AGENT_NAME_HEADER = "upstash-agent-name";
2049
- var MANAGER_AGENT_PROMPT = `You are an agent orchestrating other AI Agents.
2050
-
2051
- These other agents have tools available to them.
2052
-
2053
- Given a prompt, utilize these agents to address requests.
2054
-
2055
- 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.
2056
-
2057
- Avoid calling the same agent twice in one turn. Instead, prefer to call it once but provide everything
2058
- you need from that agent.
2059
- `;
2060
2185
 
2061
2186
  // src/agents/adapters.ts
2062
- var fetchWithContextCall = async (context, ...params) => {
2187
+ var import_ai = require("ai");
2188
+ var fetchWithContextCall = async (context, agentCallParams, ...params) => {
2063
2189
  const [input, init] = params;
2064
2190
  try {
2065
2191
  const headers = init?.headers ? Object.fromEntries(new Headers(init.headers).entries()) : {};
@@ -2070,7 +2196,10 @@ var fetchWithContextCall = async (context, ...params) => {
2070
2196
  url: input.toString(),
2071
2197
  method: init?.method,
2072
2198
  headers,
2073
- body
2199
+ body,
2200
+ timeout: agentCallParams?.timeout,
2201
+ retries: agentCallParams?.retries,
2202
+ flowControl: agentCallParams?.flowControl
2074
2203
  });
2075
2204
  const responseHeaders = new Headers(
2076
2205
  Object.entries(responseInfo.header).reduce(
@@ -2097,10 +2226,11 @@ var fetchWithContextCall = async (context, ...params) => {
2097
2226
  var createWorkflowModel = ({
2098
2227
  context,
2099
2228
  provider,
2100
- providerParams
2229
+ providerParams,
2230
+ agentCallParams
2101
2231
  }) => {
2102
2232
  return provider({
2103
- fetch: (...params) => fetchWithContextCall(context, ...params),
2233
+ fetch: (...params) => fetchWithContextCall(context, agentCallParams, ...params),
2104
2234
  ...providerParams
2105
2235
  });
2106
2236
  };
@@ -2340,17 +2470,87 @@ var WorkflowAgents = class {
2340
2470
  */
2341
2471
  openai(...params) {
2342
2472
  const [model, settings] = params;
2343
- const { baseURL, apiKey, ...otherSettings } = settings ?? {};
2473
+ const { baseURL, apiKey, callSettings, ...otherSettings } = settings ?? {};
2344
2474
  const openaiModel = this.AISDKModel({
2345
2475
  context: this.context,
2346
- provider: import_openai3.createOpenAI,
2347
- providerParams: { baseURL, apiKey, compatibility: "strict" }
2476
+ provider: import_openai2.createOpenAI,
2477
+ providerParams: { baseURL, apiKey, compatibility: "strict" },
2478
+ agentCallParams: callSettings
2348
2479
  });
2349
2480
  return openaiModel(model, otherSettings);
2350
2481
  }
2351
2482
  AISDKModel = createWorkflowModel;
2352
2483
  };
2353
2484
 
2485
+ // src/serve/serve-many.ts
2486
+ var getWorkflowId = (url) => {
2487
+ const components = url.split("/");
2488
+ const lastComponent = components[components.length - 1];
2489
+ return lastComponent.split("?")[0];
2490
+ };
2491
+ var serveManyBase = ({
2492
+ workflows,
2493
+ getUrl,
2494
+ serveMethod,
2495
+ options
2496
+ }) => {
2497
+ const workflowIds = [];
2498
+ const workflowMap = Object.fromEntries(
2499
+ Object.entries(workflows).map((workflow) => {
2500
+ const workflowId = workflow[0];
2501
+ if (workflowIds.includes(workflowId)) {
2502
+ throw new WorkflowError(
2503
+ `Duplicate workflow name found: '${workflowId}'. Please set different workflow names in serveMany.`
2504
+ );
2505
+ }
2506
+ if (workflowId.includes("/")) {
2507
+ throw new WorkflowError(
2508
+ `Invalid workflow name found: '${workflowId}'. Workflow name cannot contain '/'.`
2509
+ );
2510
+ }
2511
+ workflowIds.push(workflowId);
2512
+ workflow[1].workflowId = workflowId;
2513
+ workflow[1].options = {
2514
+ ...options,
2515
+ ...workflow[1].options
2516
+ };
2517
+ const params = [workflow[1].routeFunction, workflow[1].options];
2518
+ const handler = serveMethod(...params);
2519
+ return [workflowId, handler];
2520
+ })
2521
+ );
2522
+ return {
2523
+ handler: async (...params) => {
2524
+ const url = getUrl(...params);
2525
+ const pickedWorkflowId = getWorkflowId(url);
2526
+ if (!pickedWorkflowId) {
2527
+ return new Response(
2528
+ `Unexpected request in serveMany. workflowId not set. Please update the URL of your request.`,
2529
+ {
2530
+ status: 404
2531
+ }
2532
+ );
2533
+ }
2534
+ const workflow = workflowMap[pickedWorkflowId];
2535
+ if (!workflow) {
2536
+ return new Response(
2537
+ `No workflows in serveMany found for '${pickedWorkflowId}'. Please update the URL of your request.`,
2538
+ {
2539
+ status: 404
2540
+ }
2541
+ );
2542
+ }
2543
+ return await workflow(...params);
2544
+ }
2545
+ };
2546
+ };
2547
+ var getNewUrlFromWorkflowId = (url, workflowId) => {
2548
+ if (!workflowId) {
2549
+ throw new WorkflowError("You can only call workflow which has a workflowId");
2550
+ }
2551
+ return url.replace(/[^/]+$/, workflowId);
2552
+ };
2553
+
2354
2554
  // src/context/context.ts
2355
2555
  var WorkflowContext = class {
2356
2556
  executor;
@@ -2572,60 +2772,42 @@ var WorkflowContext = class {
2572
2772
  }
2573
2773
  await this.addStep(new LazySleepUntilStep(stepName, time));
2574
2774
  }
2575
- /**
2576
- * Makes a third party call through QStash in order to make a
2577
- * network call without consuming any runtime.
2578
- *
2579
- * ```ts
2580
- * const { status, body } = await context.call<string>(
2581
- * "post call step",
2582
- * {
2583
- * url: "https://www.some-endpoint.com/api",
2584
- * method: "POST",
2585
- * body: "my-payload"
2586
- * }
2587
- * );
2588
- * ```
2589
- *
2590
- * tries to parse the result of the request as JSON. If it's
2591
- * not a JSON which can be parsed, simply returns the response
2592
- * body as it is.
2593
- *
2594
- * @param stepName
2595
- * @param url url to call
2596
- * @param method call method. "GET" by default.
2597
- * @param body call body
2598
- * @param headers call headers
2599
- * @param retries number of call retries. 0 by default
2600
- * @param timeout max duration to wait for the endpoint to respond. in seconds.
2601
- * @returns call result as {
2602
- * status: number;
2603
- * body: unknown;
2604
- * header: Record<string, string[]>
2605
- * }
2606
- */
2607
2775
  async call(stepName, settings) {
2608
- const {
2609
- url,
2610
- method = "GET",
2611
- body: requestBody,
2612
- headers = {},
2613
- retries = 0,
2614
- timeout,
2615
- flowControl
2616
- } = settings;
2617
- return await this.addStep(
2618
- new LazyCallStep(
2776
+ let callStep;
2777
+ if ("workflow" in settings) {
2778
+ const url = getNewUrlFromWorkflowId(this.url, settings.workflow.workflowId);
2779
+ callStep = new LazyCallStep(
2780
+ stepName,
2781
+ url,
2782
+ "POST",
2783
+ settings.body,
2784
+ settings.headers || {},
2785
+ settings.retries || 0,
2786
+ settings.timeout,
2787
+ settings.flowControl ?? settings.workflow.options.flowControl
2788
+ );
2789
+ } else {
2790
+ const {
2791
+ url,
2792
+ method = "GET",
2793
+ body,
2794
+ headers = {},
2795
+ retries = 0,
2796
+ timeout,
2797
+ flowControl
2798
+ } = settings;
2799
+ callStep = new LazyCallStep(
2619
2800
  stepName,
2620
2801
  url,
2621
2802
  method,
2622
- requestBody,
2803
+ body,
2623
2804
  headers,
2624
2805
  retries,
2625
2806
  timeout,
2626
2807
  flowControl
2627
- )
2628
- );
2808
+ );
2809
+ }
2810
+ return await this.addStep(callStep);
2629
2811
  }
2630
2812
  /**
2631
2813
  * Pauses workflow execution until a specific event occurs or a timeout is reached.
@@ -2773,7 +2955,7 @@ var WorkflowLogger = class _WorkflowLogger {
2773
2955
  };
2774
2956
 
2775
2957
  // src/serve/authorization.ts
2776
- var import_qstash8 = require("@upstash/qstash");
2958
+ var import_qstash9 = require("@upstash/qstash");
2777
2959
  var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowContext {
2778
2960
  static disabledMessage = "disabled-qstash-worklfow-run";
2779
2961
  disabled = true;
@@ -2805,7 +2987,7 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
2805
2987
  */
2806
2988
  static async tryAuthentication(routeFunction, context) {
2807
2989
  const disabledContext = new _DisabledWorkflowContext({
2808
- qstashClient: new import_qstash8.Client({
2990
+ qstashClient: new import_qstash9.Client({
2809
2991
  baseUrl: "disabled-client",
2810
2992
  token: "disabled-client"
2811
2993
  }),
@@ -3019,15 +3201,15 @@ var handleFailure = async (request, requestPayload, qstashClient, initialPayload
3019
3201
  };
3020
3202
 
3021
3203
  // src/serve/options.ts
3022
- var import_qstash9 = require("@upstash/qstash");
3023
3204
  var import_qstash10 = require("@upstash/qstash");
3205
+ var import_qstash11 = require("@upstash/qstash");
3024
3206
  var processOptions = (options) => {
3025
3207
  const environment = options?.env ?? (typeof process === "undefined" ? {} : process.env);
3026
3208
  const receiverEnvironmentVariablesSet = Boolean(
3027
3209
  environment.QSTASH_CURRENT_SIGNING_KEY && environment.QSTASH_NEXT_SIGNING_KEY
3028
3210
  );
3029
3211
  return {
3030
- qstashClient: new import_qstash10.Client({
3212
+ qstashClient: new import_qstash11.Client({
3031
3213
  baseUrl: environment.QSTASH_URL,
3032
3214
  token: environment.QSTASH_TOKEN
3033
3215
  }),
@@ -3062,7 +3244,7 @@ var processOptions = (options) => {
3062
3244
  throw error;
3063
3245
  }
3064
3246
  },
3065
- receiver: receiverEnvironmentVariablesSet ? new import_qstash9.Receiver({
3247
+ receiver: receiverEnvironmentVariablesSet ? new import_qstash10.Receiver({
3066
3248
  currentSigningKey: environment.QSTASH_CURRENT_SIGNING_KEY,
3067
3249
  nextSigningKey: environment.QSTASH_NEXT_SIGNING_KEY
3068
3250
  }) : void 0,