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