@upstash/workflow 0.2.11 → 0.2.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/svelte.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.13";
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");
@@ -134,10 +135,16 @@ var formatWorkflowError = (error) => {
134
135
  message: error.message
135
136
  } : {
136
137
  error: "Error",
137
- message: "An error occured while executing workflow."
138
+ message: `An error occured while executing workflow: '${typeof error === "string" ? error : JSON.stringify(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)));
@@ -940,18 +604,22 @@ var triggerFirstInvocation = async ({
940
604
  useJSONContent,
941
605
  telemetry: telemetry2,
942
606
  debug,
943
- invokeCount
607
+ invokeCount,
608
+ delay
944
609
  }) => {
945
610
  const { headers } = getHeaders({
946
611
  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
612
+ workflowConfig: {
613
+ workflowRunId: workflowContext.workflowRunId,
614
+ workflowUrl: workflowContext.url,
615
+ failureUrl: workflowContext.failureUrl,
616
+ retries: workflowContext.retries,
617
+ telemetry: telemetry2,
618
+ flowControl: workflowContext.flowControl,
619
+ useJSONContent: useJSONContent ?? false
620
+ },
621
+ invokeCount: invokeCount ?? 0,
622
+ userHeaders: workflowContext.headers
955
623
  });
956
624
  if (workflowContext.headers.get("content-type")) {
957
625
  headers["content-type"] = workflowContext.headers.get("content-type");
@@ -965,7 +633,8 @@ var triggerFirstInvocation = async ({
965
633
  headers,
966
634
  method: "POST",
967
635
  body,
968
- url: workflowContext.url
636
+ url: workflowContext.url,
637
+ delay
969
638
  });
970
639
  if (result.deduplicated) {
971
640
  await debug?.log("WARN", "SUBMIT_FIRST_INVOCATION", {
@@ -1121,14 +790,16 @@ ${atob(callbackMessage.body ?? "")}`
1121
790
  const userHeaders = recreateUserHeaders(request.headers);
1122
791
  const { headers: requestHeaders } = getHeaders({
1123
792
  initHeaderValue: "false",
1124
- workflowRunId,
1125
- workflowUrl,
793
+ workflowConfig: {
794
+ workflowRunId,
795
+ workflowUrl,
796
+ failureUrl,
797
+ retries,
798
+ telemetry: telemetry2,
799
+ flowControl
800
+ },
1126
801
  userHeaders,
1127
- failureUrl,
1128
- retries,
1129
- telemetry: telemetry2,
1130
- invokeCount: Number(invokeCount),
1131
- flowControl
802
+ invokeCount: Number(invokeCount)
1132
803
  });
1133
804
  const callResponse = {
1134
805
  status: callbackMessage.status,
@@ -1174,329 +845,899 @@ var getTelemetryHeaders = (telemetry2) => {
1174
845
  [TELEMETRY_HEADER_RUNTIME]: telemetry2.runtime ?? "unknown"
1175
846
  };
1176
847
  };
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;
848
+ var verifyRequest = async (body, signature, verifier) => {
849
+ if (!verifier) {
850
+ return;
851
+ }
852
+ try {
853
+ if (!signature) {
854
+ throw new Error("`Upstash-Signature` header is not passed.");
1247
855
  }
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;
856
+ const isValid = await verifier.verify({
857
+ body,
858
+ signature
859
+ });
860
+ if (!isValid) {
861
+ throw new Error("Signature in `Upstash-Signature` header is not valid");
862
+ }
863
+ } catch (error) {
864
+ throw new WorkflowError(
865
+ `Failed to verify that the Workflow request comes from QStash: ${error}
866
+
867
+ If signature is missing, trigger the workflow endpoint by publishing your request to QStash instead of calling it directly.
868
+
869
+ If you want to disable QStash Verification, you should clear env variables QSTASH_CURRENT_SIGNING_KEY and QSTASH_NEXT_SIGNING_KEY`
870
+ );
871
+ }
872
+ };
873
+
874
+ // src/context/steps.ts
875
+ var BaseLazyStep = class _BaseLazyStep {
876
+ stepName;
877
+ constructor(stepName) {
878
+ if (!stepName) {
879
+ throw new WorkflowError(
880
+ "A workflow step name cannot be undefined or an empty string. Please provide a name for your workflow step."
881
+ );
882
+ }
883
+ if (typeof stepName !== "string") {
884
+ console.warn(
885
+ "Workflow Warning: A workflow step name must be a string. In a future release, this will throw an error."
886
+ );
887
+ }
888
+ this.stepName = stepName;
889
+ }
890
+ /**
891
+ * parse the out field of a step result.
892
+ *
893
+ * will be called when returning the steps to the context from auto executor
894
+ *
895
+ * @param out field of the step
896
+ * @returns parsed out field
897
+ */
898
+ parseOut(out) {
899
+ if (out === void 0) {
900
+ if (this.allowUndefinedOut) {
901
+ return void 0;
902
+ } else {
903
+ throw new WorkflowError(
904
+ `Error while parsing output of ${this.stepType} step. Expected a string, but got: undefined`
905
+ );
906
+ }
907
+ }
908
+ if (typeof out === "object") {
909
+ if (this.stepType !== "Wait") {
910
+ console.warn(
911
+ `Error while parsing ${this.stepType} step output. Expected a string, but got object. Please reach out to Upstash Support.`
912
+ );
913
+ return out;
914
+ }
915
+ return {
916
+ ...out,
917
+ eventData: _BaseLazyStep.tryParsing(out.eventData)
918
+ };
919
+ }
920
+ if (typeof out !== "string") {
921
+ throw new WorkflowError(
922
+ `Error while parsing output of ${this.stepType} step. Expected a string or undefined, but got: ${typeof out}`
923
+ );
924
+ }
925
+ return this.safeParseOut(out);
926
+ }
927
+ safeParseOut(out) {
928
+ return _BaseLazyStep.tryParsing(out);
929
+ }
930
+ static tryParsing(stepOut) {
931
+ try {
932
+ return JSON.parse(stepOut);
933
+ } catch {
934
+ return stepOut;
935
+ }
936
+ }
937
+ getBody({ step }) {
938
+ step.out = JSON.stringify(step.out);
939
+ return JSON.stringify(step);
940
+ }
941
+ getHeaders({ context, telemetry: telemetry2, invokeCount, step }) {
942
+ return getHeaders({
943
+ initHeaderValue: "false",
944
+ workflowConfig: {
945
+ workflowRunId: context.workflowRunId,
946
+ workflowUrl: context.url,
947
+ failureUrl: context.failureUrl,
948
+ retries: context.retries,
949
+ useJSONContent: false,
950
+ telemetry: telemetry2,
951
+ flowControl: context.flowControl
952
+ },
953
+ userHeaders: context.headers,
954
+ invokeCount,
955
+ stepInfo: {
956
+ step,
957
+ lazyStep: this
958
+ }
959
+ });
960
+ }
961
+ async submitStep({ context, body, headers }) {
962
+ return await context.qstashClient.batch([
963
+ {
964
+ body,
965
+ headers,
966
+ method: "POST",
967
+ url: context.url
968
+ }
969
+ ]);
970
+ }
971
+ };
972
+ var LazyFunctionStep = class extends BaseLazyStep {
973
+ stepFunction;
974
+ stepType = "Run";
975
+ allowUndefinedOut = true;
976
+ constructor(stepName, stepFunction) {
977
+ super(stepName);
978
+ this.stepFunction = stepFunction;
979
+ }
980
+ getPlanStep(concurrent, targetStep) {
981
+ return {
982
+ stepId: 0,
983
+ stepName: this.stepName,
984
+ stepType: this.stepType,
985
+ concurrent,
986
+ targetStep
987
+ };
988
+ }
989
+ async getResultStep(concurrent, stepId) {
990
+ let result = this.stepFunction();
991
+ if (result instanceof Promise) {
992
+ result = await result;
993
+ }
994
+ return {
995
+ stepId,
996
+ stepName: this.stepName,
997
+ stepType: this.stepType,
998
+ out: result,
999
+ concurrent
1000
+ };
1001
+ }
1002
+ };
1003
+ var LazySleepStep = class extends BaseLazyStep {
1004
+ sleep;
1005
+ stepType = "SleepFor";
1006
+ allowUndefinedOut = true;
1007
+ constructor(stepName, sleep) {
1008
+ super(stepName);
1009
+ this.sleep = sleep;
1010
+ }
1011
+ getPlanStep(concurrent, targetStep) {
1012
+ return {
1013
+ stepId: 0,
1014
+ stepName: this.stepName,
1015
+ stepType: this.stepType,
1016
+ sleepFor: this.sleep,
1017
+ concurrent,
1018
+ targetStep
1019
+ };
1020
+ }
1021
+ async getResultStep(concurrent, stepId) {
1022
+ return await Promise.resolve({
1023
+ stepId,
1024
+ stepName: this.stepName,
1025
+ stepType: this.stepType,
1026
+ sleepFor: this.sleep,
1027
+ concurrent
1028
+ });
1029
+ }
1030
+ async submitStep({ context, body, headers, isParallel }) {
1031
+ return await context.qstashClient.batch([
1032
+ {
1033
+ body,
1034
+ headers,
1035
+ method: "POST",
1036
+ url: context.url,
1037
+ delay: isParallel ? void 0 : this.sleep
1038
+ }
1039
+ ]);
1040
+ }
1041
+ };
1042
+ var LazySleepUntilStep = class extends BaseLazyStep {
1043
+ sleepUntil;
1044
+ stepType = "SleepUntil";
1045
+ allowUndefinedOut = true;
1046
+ constructor(stepName, sleepUntil) {
1047
+ super(stepName);
1048
+ this.sleepUntil = sleepUntil;
1049
+ }
1050
+ getPlanStep(concurrent, targetStep) {
1051
+ return {
1052
+ stepId: 0,
1053
+ stepName: this.stepName,
1054
+ stepType: this.stepType,
1055
+ sleepUntil: this.sleepUntil,
1056
+ concurrent,
1057
+ targetStep
1058
+ };
1059
+ }
1060
+ async getResultStep(concurrent, stepId) {
1061
+ return await Promise.resolve({
1062
+ stepId,
1063
+ stepName: this.stepName,
1064
+ stepType: this.stepType,
1065
+ sleepUntil: this.sleepUntil,
1066
+ concurrent
1067
+ });
1068
+ }
1069
+ safeParseOut() {
1070
+ return void 0;
1071
+ }
1072
+ async submitStep({ context, body, headers, isParallel }) {
1073
+ return await context.qstashClient.batch([
1074
+ {
1075
+ body,
1076
+ headers,
1077
+ method: "POST",
1078
+ url: context.url,
1079
+ notBefore: isParallel ? void 0 : this.sleepUntil
1080
+ }
1081
+ ]);
1082
+ }
1083
+ };
1084
+ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
1085
+ url;
1086
+ method;
1087
+ body;
1088
+ headers;
1089
+ retries;
1090
+ timeout;
1091
+ flowControl;
1092
+ stepType = "Call";
1093
+ allowUndefinedOut = false;
1094
+ constructor(stepName, url, method, body, headers, retries, timeout, flowControl) {
1095
+ super(stepName);
1096
+ this.url = url;
1097
+ this.method = method;
1098
+ this.body = body;
1099
+ this.headers = headers;
1100
+ this.retries = retries;
1101
+ this.timeout = timeout;
1102
+ this.flowControl = flowControl;
1103
+ }
1104
+ getPlanStep(concurrent, targetStep) {
1105
+ return {
1106
+ stepId: 0,
1107
+ stepName: this.stepName,
1108
+ stepType: this.stepType,
1109
+ concurrent,
1110
+ targetStep
1111
+ };
1112
+ }
1113
+ async getResultStep(concurrent, stepId) {
1114
+ return await Promise.resolve({
1115
+ stepId,
1116
+ stepName: this.stepName,
1117
+ stepType: this.stepType,
1118
+ concurrent,
1119
+ callUrl: this.url,
1120
+ callMethod: this.method,
1121
+ callBody: this.body,
1122
+ callHeaders: this.headers
1123
+ });
1124
+ }
1125
+ safeParseOut(out) {
1126
+ const { header, status, body } = JSON.parse(out);
1127
+ const responseHeaders = new Headers(header);
1128
+ if (_LazyCallStep.isText(responseHeaders.get("content-type"))) {
1129
+ const bytes = new Uint8Array(out.length);
1130
+ for (let i = 0; i < out.length; i++) {
1131
+ bytes[i] = out.charCodeAt(i);
1132
+ }
1133
+ const processedResult = new TextDecoder().decode(bytes);
1134
+ const newBody = JSON.parse(processedResult).body;
1135
+ return {
1136
+ status,
1137
+ header,
1138
+ body: BaseLazyStep.tryParsing(newBody)
1139
+ };
1140
+ } else {
1141
+ return { header, status, body };
1142
+ }
1143
+ }
1144
+ static applicationHeaders = /* @__PURE__ */ new Set([
1145
+ "application/json",
1146
+ "application/xml",
1147
+ "application/javascript",
1148
+ "application/x-www-form-urlencoded",
1149
+ "application/xhtml+xml",
1150
+ "application/ld+json",
1151
+ "application/rss+xml",
1152
+ "application/atom+xml"
1153
+ ]);
1154
+ static isText = (contentTypeHeader) => {
1155
+ if (!contentTypeHeader) {
1156
+ return false;
1157
+ }
1158
+ if (_LazyCallStep.applicationHeaders.has(contentTypeHeader)) {
1159
+ return true;
1160
+ }
1161
+ if (contentTypeHeader.startsWith("text/")) {
1162
+ return true;
1253
1163
  }
1254
- if (retries !== void 0) {
1255
- baseHeaders["Upstash-Retries"] = retries.toString();
1256
- baseHeaders["Upstash-Failure-Callback-Retries"] = retries.toString();
1164
+ return false;
1165
+ };
1166
+ getBody({ step }) {
1167
+ if (!step.callUrl) {
1168
+ throw new WorkflowError("Incompatible step received in LazyCallStep.getBody");
1257
1169
  }
1170
+ return JSON.stringify(step.callBody);
1258
1171
  }
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);
1172
+ getHeaders({ context, telemetry: telemetry2, invokeCount, step }) {
1173
+ const { headers, contentType } = super.getHeaders({ context, telemetry: telemetry2, invokeCount, step });
1174
+ headers["Upstash-Retries"] = this.retries.toString();
1175
+ headers[WORKFLOW_FEATURE_HEADER] = "WF_NoDelete,InitialBody";
1176
+ if (this.flowControl) {
1177
+ const { flowControlKey, flowControlValue } = prepareFlowControl(this.flowControl);
1178
+ headers["Upstash-Flow-Control-Key"] = flowControlKey;
1179
+ headers["Upstash-Flow-Control-Value"] = flowControlValue;
1180
+ }
1181
+ if (this.timeout) {
1182
+ headers["Upstash-Timeout"] = this.timeout.toString();
1267
1183
  }
1268
- }
1269
- if (step?.callHeaders) {
1270
1184
  const forwardedHeaders = Object.fromEntries(
1271
- Object.entries(step.callHeaders).map(([header, value]) => [
1272
- `Upstash-Forward-${header}`,
1273
- value
1274
- ])
1185
+ Object.entries(this.headers).map(([header, value]) => [`Upstash-Forward-${header}`, value])
1275
1186
  );
1276
1187
  return {
1277
1188
  headers: {
1278
- ...baseHeaders,
1189
+ ...headers,
1279
1190
  ...forwardedHeaders,
1280
- "Upstash-Callback": workflowUrl,
1281
- "Upstash-Callback-Workflow-RunId": workflowRunId,
1191
+ "Upstash-Callback": context.url,
1192
+ "Upstash-Callback-Workflow-RunId": context.workflowRunId,
1282
1193
  "Upstash-Callback-Workflow-CallType": "fromCallback",
1283
1194
  "Upstash-Callback-Workflow-Init": "false",
1284
- "Upstash-Callback-Workflow-Url": workflowUrl,
1195
+ "Upstash-Callback-Workflow-Url": context.url,
1285
1196
  "Upstash-Callback-Feature-Set": "LazyFetch,InitialBody",
1286
1197
  "Upstash-Callback-Forward-Upstash-Workflow-Callback": "true",
1287
1198
  "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,
1199
+ "Upstash-Callback-Forward-Upstash-Workflow-StepName": this.stepName,
1200
+ "Upstash-Callback-Forward-Upstash-Workflow-StepType": this.stepType,
1290
1201
  "Upstash-Callback-Forward-Upstash-Workflow-Concurrent": step.concurrent.toString(),
1291
1202
  "Upstash-Callback-Forward-Upstash-Workflow-ContentType": contentType,
1292
- [`Upstash-Callback-Forward-${WORKFLOW_INVOKE_COUNT_HEADER}`]: (invokeCount ?? 0).toString(),
1293
1203
  "Upstash-Workflow-CallType": "toCallback"
1204
+ },
1205
+ contentType
1206
+ };
1207
+ }
1208
+ async submitStep({ context, headers }) {
1209
+ return await context.qstashClient.batch([
1210
+ {
1211
+ headers,
1212
+ body: JSON.stringify(this.body),
1213
+ method: this.method,
1214
+ url: this.url
1294
1215
  }
1216
+ ]);
1217
+ }
1218
+ };
1219
+ var LazyWaitForEventStep = class extends BaseLazyStep {
1220
+ eventId;
1221
+ timeout;
1222
+ stepType = "Wait";
1223
+ allowUndefinedOut = false;
1224
+ constructor(stepName, eventId, timeout) {
1225
+ super(stepName);
1226
+ this.eventId = eventId;
1227
+ this.timeout = timeout;
1228
+ }
1229
+ getPlanStep(concurrent, targetStep) {
1230
+ return {
1231
+ stepId: 0,
1232
+ stepName: this.stepName,
1233
+ stepType: this.stepType,
1234
+ waitEventId: this.eventId,
1235
+ timeout: this.timeout,
1236
+ concurrent,
1237
+ targetStep
1295
1238
  };
1296
1239
  }
1297
- if (step?.waitEventId) {
1240
+ async getResultStep(concurrent, stepId) {
1241
+ return await Promise.resolve({
1242
+ stepId,
1243
+ stepName: this.stepName,
1244
+ stepType: this.stepType,
1245
+ waitEventId: this.eventId,
1246
+ timeout: this.timeout,
1247
+ concurrent
1248
+ });
1249
+ }
1250
+ safeParseOut(out) {
1251
+ const result = JSON.parse(out);
1298
1252
  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"]
1253
+ ...result,
1254
+ eventData: BaseLazyStep.tryParsing(result.eventData)
1255
+ };
1256
+ }
1257
+ getHeaders({ context, telemetry: telemetry2, invokeCount, step }) {
1258
+ const headers = super.getHeaders({ context, telemetry: telemetry2, invokeCount, step });
1259
+ headers.headers["Upstash-Workflow-CallType"] = "step";
1260
+ return headers;
1261
+ }
1262
+ getBody({ context, step, headers, telemetry: telemetry2 }) {
1263
+ if (!step.waitEventId) {
1264
+ throw new WorkflowError("Incompatible step received in LazyWaitForEventStep.getBody");
1265
+ }
1266
+ const timeoutHeaders = {
1267
+ // to include user headers:
1268
+ ...Object.fromEntries(Object.entries(headers).map(([header, value]) => [header, [value]])),
1269
+ // to include telemetry headers:
1270
+ ...telemetry2 ? Object.fromEntries(
1271
+ Object.entries(getTelemetryHeaders(telemetry2)).map(([header, value]) => [
1272
+ header,
1273
+ [value]
1274
+ ])
1275
+ ) : {},
1276
+ // note: using WORKFLOW_ID_HEADER doesn't work, because Runid -> RunId:
1277
+ "Upstash-Workflow-Runid": [context.workflowRunId],
1278
+ [WORKFLOW_INIT_HEADER]: ["false"],
1279
+ [WORKFLOW_URL_HEADER]: [context.url],
1280
+ "Upstash-Workflow-CallType": ["step"]
1281
+ };
1282
+ const waitBody = {
1283
+ url: context.url,
1284
+ timeout: step.timeout,
1285
+ timeoutBody: void 0,
1286
+ timeoutUrl: context.url,
1287
+ timeoutHeaders,
1288
+ step: {
1289
+ stepId: step.stepId,
1290
+ stepType: "Wait",
1291
+ stepName: step.stepName,
1292
+ concurrent: step.concurrent,
1293
+ targetStep: step.targetStep
1320
1294
  }
1321
1295
  };
1296
+ return JSON.stringify(waitBody);
1297
+ }
1298
+ async submitStep({ context, body, headers }) {
1299
+ const result = await context.qstashClient.http.request({
1300
+ path: ["v2", "wait", this.eventId],
1301
+ body,
1302
+ headers,
1303
+ method: "POST",
1304
+ parseResponseAsJson: false
1305
+ });
1306
+ return [result];
1322
1307
  }
1323
- return { headers: baseHeaders };
1324
1308
  };
1325
- var verifyRequest = async (body, signature, verifier) => {
1326
- if (!verifier) {
1327
- return;
1309
+ var LazyNotifyStep = class extends LazyFunctionStep {
1310
+ stepType = "Notify";
1311
+ constructor(stepName, eventId, eventData, requester) {
1312
+ super(stepName, async () => {
1313
+ const notifyResponse = await makeNotifyRequest(requester, eventId, eventData);
1314
+ return {
1315
+ eventId,
1316
+ eventData,
1317
+ notifyResponse
1318
+ };
1319
+ });
1328
1320
  }
1329
- try {
1330
- if (!signature) {
1331
- throw new Error("`Upstash-Signature` header is not passed.");
1321
+ safeParseOut(out) {
1322
+ const result = JSON.parse(out);
1323
+ return {
1324
+ ...result,
1325
+ eventData: BaseLazyStep.tryParsing(result.eventData)
1326
+ };
1327
+ }
1328
+ };
1329
+ var LazyInvokeStep = class extends BaseLazyStep {
1330
+ stepType = "Invoke";
1331
+ params;
1332
+ allowUndefinedOut = false;
1333
+ /**
1334
+ * workflow id of the invoked workflow
1335
+ */
1336
+ workflowId;
1337
+ constructor(stepName, {
1338
+ workflow,
1339
+ body,
1340
+ headers = {},
1341
+ workflowRunId,
1342
+ retries,
1343
+ flowControl
1344
+ }) {
1345
+ super(stepName);
1346
+ this.params = {
1347
+ workflow,
1348
+ body,
1349
+ headers,
1350
+ workflowRunId: getWorkflowRunId(workflowRunId),
1351
+ retries,
1352
+ flowControl
1353
+ };
1354
+ const { workflowId } = workflow;
1355
+ if (!workflowId) {
1356
+ throw new WorkflowError("You can only invoke workflow which has a workflowId");
1332
1357
  }
1333
- const isValid = await verifier.verify({
1358
+ this.workflowId = workflowId;
1359
+ }
1360
+ getPlanStep(concurrent, targetStep) {
1361
+ return {
1362
+ stepId: 0,
1363
+ stepName: this.stepName,
1364
+ stepType: this.stepType,
1365
+ concurrent,
1366
+ targetStep
1367
+ };
1368
+ }
1369
+ /**
1370
+ * won't be used as it's the server who will add the result step
1371
+ * in Invoke step.
1372
+ */
1373
+ getResultStep(concurrent, stepId) {
1374
+ return Promise.resolve({
1375
+ stepId,
1376
+ stepName: this.stepName,
1377
+ stepType: this.stepType,
1378
+ concurrent
1379
+ });
1380
+ }
1381
+ safeParseOut(out) {
1382
+ const result = JSON.parse(out);
1383
+ return {
1384
+ ...result,
1385
+ body: BaseLazyStep.tryParsing(result.body)
1386
+ };
1387
+ }
1388
+ getBody({ context, step, telemetry: telemetry2, invokeCount }) {
1389
+ const { headers: invokerHeaders } = getHeaders({
1390
+ initHeaderValue: "false",
1391
+ workflowConfig: {
1392
+ workflowRunId: context.workflowRunId,
1393
+ workflowUrl: context.url,
1394
+ failureUrl: context.failureUrl,
1395
+ retries: context.retries,
1396
+ telemetry: telemetry2,
1397
+ flowControl: context.flowControl,
1398
+ useJSONContent: false
1399
+ },
1400
+ userHeaders: context.headers,
1401
+ invokeCount
1402
+ });
1403
+ invokerHeaders["Upstash-Workflow-Runid"] = context.workflowRunId;
1404
+ const request = {
1405
+ body: JSON.stringify(this.params.body),
1406
+ headers: Object.fromEntries(
1407
+ Object.entries(invokerHeaders).map((pairs) => [pairs[0], [pairs[1]]])
1408
+ ),
1409
+ workflowRunId: context.workflowRunId,
1410
+ workflowUrl: context.url,
1411
+ step
1412
+ };
1413
+ return JSON.stringify(request);
1414
+ }
1415
+ getHeaders({ context, telemetry: telemetry2, invokeCount }) {
1416
+ const {
1417
+ workflow,
1418
+ headers = {},
1419
+ workflowRunId = getWorkflowRunId(),
1420
+ retries,
1421
+ flowControl
1422
+ } = this.params;
1423
+ const newUrl = context.url.replace(/[^/]+$/, this.workflowId);
1424
+ const {
1425
+ retries: workflowRetries,
1426
+ failureFunction,
1427
+ failureUrl,
1428
+ useJSONContent,
1429
+ flowControl: workflowFlowControl
1430
+ } = workflow.options;
1431
+ const { headers: triggerHeaders, contentType } = getHeaders({
1432
+ initHeaderValue: "true",
1433
+ workflowConfig: {
1434
+ workflowRunId,
1435
+ workflowUrl: newUrl,
1436
+ retries: retries ?? workflowRetries,
1437
+ telemetry: telemetry2,
1438
+ failureUrl: failureFunction ? newUrl : failureUrl,
1439
+ flowControl: flowControl ?? workflowFlowControl,
1440
+ useJSONContent: useJSONContent ?? false
1441
+ },
1442
+ invokeCount: invokeCount + 1,
1443
+ userHeaders: new Headers(headers)
1444
+ });
1445
+ triggerHeaders["Upstash-Workflow-Invoke"] = "true";
1446
+ return { headers: triggerHeaders, contentType };
1447
+ }
1448
+ async submitStep({ context, body, headers }) {
1449
+ const newUrl = context.url.replace(/[^/]+$/, this.workflowId);
1450
+ const result = await context.qstashClient.publish({
1451
+ headers,
1452
+ method: "POST",
1334
1453
  body,
1335
- signature
1454
+ url: newUrl
1336
1455
  });
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}
1456
+ return [result];
1457
+ }
1458
+ };
1343
1459
 
1344
- If signature is missing, trigger the workflow endpoint by publishing your request to QStash instead of calling it directly.
1460
+ // src/agents/constants.ts
1461
+ var AGENT_NAME_HEADER = "upstash-agent-name";
1462
+ var MANAGER_AGENT_PROMPT = `You are an agent orchestrating other AI Agents.
1345
1463
 
1346
- If you want to disable QStash Verification, you should clear env variables QSTASH_CURRENT_SIGNING_KEY and QSTASH_NEXT_SIGNING_KEY`
1464
+ These other agents have tools available to them.
1465
+
1466
+ Given a prompt, utilize these agents to address requests.
1467
+
1468
+ 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.
1469
+
1470
+ Avoid calling the same agent twice in one turn. Instead, prefer to call it once but provide everything
1471
+ you need from that agent.
1472
+ `;
1473
+
1474
+ // src/qstash/headers.ts
1475
+ var WorkflowHeaders = class {
1476
+ userHeaders;
1477
+ workflowConfig;
1478
+ invokeCount;
1479
+ initHeaderValue;
1480
+ stepInfo;
1481
+ headers;
1482
+ constructor({
1483
+ userHeaders,
1484
+ workflowConfig,
1485
+ invokeCount,
1486
+ initHeaderValue,
1487
+ stepInfo
1488
+ }) {
1489
+ this.userHeaders = userHeaders;
1490
+ this.workflowConfig = workflowConfig;
1491
+ this.invokeCount = invokeCount;
1492
+ this.initHeaderValue = initHeaderValue;
1493
+ this.stepInfo = stepInfo;
1494
+ this.headers = {
1495
+ rawHeaders: {},
1496
+ workflowHeaders: {},
1497
+ failureHeaders: {}
1498
+ };
1499
+ }
1500
+ getHeaders() {
1501
+ this.addBaseHeaders();
1502
+ this.addRetries();
1503
+ this.addFlowControl();
1504
+ this.addUserHeaders();
1505
+ this.addInvokeCount();
1506
+ this.addFailureUrl();
1507
+ const contentType = this.addContentType();
1508
+ return this.prefixHeaders(contentType);
1509
+ }
1510
+ addBaseHeaders() {
1511
+ this.headers.rawHeaders = {
1512
+ ...this.headers.rawHeaders,
1513
+ [WORKFLOW_INIT_HEADER]: this.initHeaderValue,
1514
+ [WORKFLOW_ID_HEADER]: this.workflowConfig.workflowRunId,
1515
+ [WORKFLOW_URL_HEADER]: this.workflowConfig.workflowUrl,
1516
+ [WORKFLOW_FEATURE_HEADER]: "LazyFetch,InitialBody",
1517
+ [WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION,
1518
+ ...this.workflowConfig.telemetry ? getTelemetryHeaders(this.workflowConfig.telemetry) : {},
1519
+ ...this.workflowConfig.telemetry && this.stepInfo?.lazyStep instanceof LazyCallStep && this.stepInfo.lazyStep.headers[AGENT_NAME_HEADER] ? { [TELEMETRY_HEADER_AGENT]: "true" } : {}
1520
+ };
1521
+ if (this.stepInfo?.lazyStep.stepType !== "Call") {
1522
+ this.headers.rawHeaders[`Upstash-Forward-${WORKFLOW_PROTOCOL_VERSION_HEADER}`] = WORKFLOW_PROTOCOL_VERSION;
1523
+ }
1524
+ }
1525
+ addInvokeCount() {
1526
+ if (this.invokeCount === void 0 || this.invokeCount === 0) {
1527
+ return;
1528
+ }
1529
+ const invokeCount = this.invokeCount.toString();
1530
+ this.headers.workflowHeaders[`Forward-${WORKFLOW_INVOKE_COUNT_HEADER}`] = invokeCount;
1531
+ if (this.workflowConfig.failureUrl) {
1532
+ this.headers.failureHeaders[`Forward-${WORKFLOW_INVOKE_COUNT_HEADER}`] = invokeCount;
1533
+ }
1534
+ if (this.stepInfo?.lazyStep instanceof LazyCallStep) {
1535
+ this.headers.rawHeaders[`Upstash-Forward-${WORKFLOW_INVOKE_COUNT_HEADER}`] = invokeCount;
1536
+ }
1537
+ }
1538
+ addRetries() {
1539
+ if (this.workflowConfig.retries === void 0 || this.workflowConfig.retries === DEFAULT_RETRIES) {
1540
+ return;
1541
+ }
1542
+ const retries = this.workflowConfig.retries.toString();
1543
+ this.headers.workflowHeaders["Retries"] = retries;
1544
+ if (this.workflowConfig.failureUrl) {
1545
+ this.headers.failureHeaders["Retries"] = retries;
1546
+ }
1547
+ }
1548
+ addFlowControl() {
1549
+ if (!this.workflowConfig.flowControl) {
1550
+ return;
1551
+ }
1552
+ const { flowControlKey, flowControlValue } = prepareFlowControl(
1553
+ this.workflowConfig.flowControl
1554
+ );
1555
+ this.headers.workflowHeaders["Flow-Control-Key"] = flowControlKey;
1556
+ this.headers.workflowHeaders["Flow-Control-Value"] = flowControlValue;
1557
+ if (this.workflowConfig.failureUrl) {
1558
+ this.headers.failureHeaders["Flow-Control-Key"] = flowControlKey;
1559
+ this.headers.failureHeaders["Flow-Control-Value"] = flowControlValue;
1560
+ }
1561
+ }
1562
+ addUserHeaders() {
1563
+ for (const [key, value] of this.userHeaders.entries()) {
1564
+ const forwardKey = `Forward-${key}`;
1565
+ this.headers.workflowHeaders[forwardKey] = value;
1566
+ if (this.workflowConfig.failureUrl) {
1567
+ this.headers.failureHeaders[forwardKey] = value;
1568
+ }
1569
+ }
1570
+ }
1571
+ addFailureUrl() {
1572
+ if (!this.workflowConfig.failureUrl) {
1573
+ return;
1574
+ }
1575
+ this.headers.workflowHeaders["Failure-Callback"] = this.workflowConfig.failureUrl;
1576
+ this.headers.failureHeaders[`Forward-${WORKFLOW_FAILURE_HEADER}`] = "true";
1577
+ this.headers.failureHeaders[`Forward-Upstash-Workflow-Failure-Callback`] = "true";
1578
+ this.headers.failureHeaders["Workflow-Runid"] = this.workflowConfig.workflowRunId;
1579
+ this.headers.failureHeaders["Workflow-Init"] = "false";
1580
+ this.headers.failureHeaders["Workflow-Url"] = this.workflowConfig.workflowUrl;
1581
+ this.headers.failureHeaders["Workflow-Calltype"] = "failureCall";
1582
+ this.headers.failureHeaders["Feature-Set"] = "LazyFetch,InitialBody";
1583
+ if (this.workflowConfig.retries !== void 0 && this.workflowConfig.retries !== DEFAULT_RETRIES) {
1584
+ this.headers.failureHeaders["Retries"] = this.workflowConfig.retries.toString();
1585
+ }
1586
+ }
1587
+ addContentType() {
1588
+ if (this.workflowConfig.useJSONContent) {
1589
+ this.headers.rawHeaders["content-type"] = "application/json";
1590
+ return "application/json";
1591
+ }
1592
+ const callHeaders = new Headers(
1593
+ this.stepInfo?.lazyStep instanceof LazyCallStep ? this.stepInfo.lazyStep.headers : {}
1347
1594
  );
1595
+ 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;
1596
+ this.headers.rawHeaders["content-type"] = contentType;
1597
+ return contentType;
1598
+ }
1599
+ prefixHeaders(contentType) {
1600
+ const { rawHeaders, workflowHeaders, failureHeaders } = this.headers;
1601
+ const isCall = this.stepInfo?.lazyStep.stepType === "Call";
1602
+ return {
1603
+ headers: {
1604
+ ...rawHeaders,
1605
+ ...addPrefixToHeaders(workflowHeaders, isCall ? "Upstash-Callback-" : "Upstash-"),
1606
+ ...addPrefixToHeaders(failureHeaders, "Upstash-Failure-Callback-"),
1607
+ ...isCall ? addPrefixToHeaders(failureHeaders, "Upstash-Callback-Failure-Callback-") : {}
1608
+ },
1609
+ contentType
1610
+ };
1348
1611
  }
1349
1612
  };
1613
+ function addPrefixToHeaders(headers, prefix) {
1614
+ const prefixedHeaders = {};
1615
+ for (const [key, value] of Object.entries(headers)) {
1616
+ prefixedHeaders[`${prefix}${key}`] = value;
1617
+ }
1618
+ return prefixedHeaders;
1619
+ }
1350
1620
  var prepareFlowControl = (flowControl) => {
1351
1621
  const parallelism = flowControl.parallelism?.toString();
1352
- const rate = flowControl.ratePerSecond?.toString();
1622
+ const rate = (flowControl.rate ?? flowControl.ratePerSecond)?.toString();
1623
+ const period = typeof flowControl.period === "number" ? `${flowControl.period}s` : flowControl.period;
1353
1624
  const controlValue = [
1354
1625
  parallelism ? `parallelism=${parallelism}` : void 0,
1355
- rate ? `rate=${rate}` : void 0
1626
+ rate ? `rate=${rate}` : void 0,
1627
+ period ? `period=${period}` : void 0
1356
1628
  ].filter(Boolean);
1357
1629
  if (controlValue.length === 0) {
1358
- throw new import_qstash3.QstashError("Provide at least one of parallelism or ratePerSecond for flowControl");
1630
+ throw new import_qstash4.QstashError("Provide at least one of parallelism or ratePerSecond for flowControl");
1359
1631
  }
1360
1632
  return {
1361
1633
  flowControlKey: flowControl.key,
1362
1634
  flowControlValue: controlValue.join(", ")
1363
1635
  };
1364
1636
  };
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];
1637
+ var getHeaders = (params) => {
1638
+ const workflowHeaders = new WorkflowHeaders(params);
1639
+ return workflowHeaders.getHeaders();
1374
1640
  };
1375
- var serveManyBase = ({
1376
- workflows,
1377
- getUrl,
1378
- serveMethod,
1379
- options
1641
+
1642
+ // src/qstash/submit-steps.ts
1643
+ var submitParallelSteps = async ({
1644
+ context,
1645
+ steps,
1646
+ initialStepCount,
1647
+ invokeCount,
1648
+ telemetry: telemetry2,
1649
+ debug
1380
1650
  }) => {
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
1651
+ const planSteps = steps.map(
1652
+ (step, index) => step.getPlanStep(steps.length, initialStepCount + index)
1653
+ );
1654
+ await debug?.log("SUBMIT", "SUBMIT_STEP", {
1655
+ length: planSteps.length,
1656
+ steps: planSteps
1657
+ });
1658
+ const result = await context.qstashClient.batch(
1659
+ planSteps.map((planStep) => {
1660
+ const { headers } = getHeaders({
1661
+ initHeaderValue: "false",
1662
+ workflowConfig: {
1663
+ workflowRunId: context.workflowRunId,
1664
+ workflowUrl: context.url,
1665
+ failureUrl: context.failureUrl,
1666
+ retries: context.retries,
1667
+ flowControl: context.flowControl,
1668
+ telemetry: telemetry2
1669
+ },
1670
+ userHeaders: context.headers,
1671
+ invokeCount
1672
+ });
1673
+ return {
1674
+ headers,
1675
+ method: "POST",
1676
+ url: context.url,
1677
+ body: JSON.stringify(planStep),
1678
+ notBefore: planStep.sleepUntil,
1679
+ delay: planStep.sleepFor
1400
1680
  };
1401
- const params = [workflow[1].routeFunction, workflow[1].options];
1402
- const handler = serveMethod(...params);
1403
- return [workflowId, handler];
1404
1681
  })
1405
1682
  );
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
- };
1683
+ await debug?.log("INFO", "SUBMIT_STEP", {
1684
+ messageIds: result.map((message) => {
1685
+ return {
1686
+ message: message.messageId
1687
+ };
1688
+ })
1689
+ });
1690
+ throw new WorkflowAbort(planSteps[0].stepName, planSteps[0]);
1430
1691
  };
1431
- var invokeWorkflow = async ({
1432
- settings,
1433
- invokeStep,
1692
+ var submitSingleStep = async ({
1434
1693
  context,
1694
+ lazyStep,
1695
+ stepId,
1435
1696
  invokeCount,
1436
- telemetry: telemetry2
1697
+ concurrency,
1698
+ telemetry: telemetry2,
1699
+ debug
1437
1700
  }) => {
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,
1701
+ const resultStep = await lazyStep.getResultStep(concurrency, stepId);
1702
+ await debug?.log("INFO", "RUN_SINGLE", {
1703
+ fromRequest: false,
1704
+ step: resultStep,
1705
+ stepCount: stepId
1706
+ });
1707
+ const { headers } = lazyStep.getHeaders({
1708
+ context,
1709
+ step: resultStep,
1465
1710
  invokeCount,
1466
- flowControl: context.flowControl
1711
+ telemetry: telemetry2
1467
1712
  });
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
1713
+ const body = lazyStep.getBody({
1714
+ context,
1715
+ step: resultStep,
1716
+ headers,
1717
+ invokeCount,
1718
+ telemetry: telemetry2
1480
1719
  });
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
1720
+ await debug?.log("SUBMIT", "SUBMIT_STEP", {
1721
+ length: 1,
1722
+ steps: [resultStep]
1723
+ });
1724
+ const submitResult = await lazyStep.submitStep({
1725
+ context,
1726
+ body,
1727
+ headers,
1728
+ isParallel: concurrency !== NO_CONCURRENCY,
1729
+ invokeCount,
1730
+ step: resultStep,
1731
+ telemetry: telemetry2
1732
+ });
1733
+ await debug?.log("INFO", "SUBMIT_STEP", {
1734
+ messageIds: submitResult.map((message) => {
1735
+ return {
1736
+ message: message.messageId
1737
+ };
1738
+ })
1499
1739
  });
1740
+ return resultStep;
1500
1741
  };
1501
1742
 
1502
1743
  // src/context/auto-executor.ts
@@ -1603,14 +1844,16 @@ var AutoExecutor = class _AutoExecutor {
1603
1844
  });
1604
1845
  return lazyStep.parseOut(step.out);
1605
1846
  }
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
1847
+ const resultStep = await submitSingleStep({
1848
+ context: this.context,
1849
+ lazyStep,
1850
+ stepId: this.stepCount,
1851
+ invokeCount: this.invokeCount,
1852
+ concurrency: 1,
1853
+ telemetry: this.telemetry,
1854
+ debug: this.debug
1611
1855
  });
1612
- await this.submitStepsToQStash([resultStep], [lazyStep]);
1613
- return resultStep.out;
1856
+ throw new WorkflowAbort(lazyStep.stepName, resultStep);
1614
1857
  }
1615
1858
  /**
1616
1859
  * Runs steps in parallel.
@@ -1638,10 +1881,14 @@ var AutoExecutor = class _AutoExecutor {
1638
1881
  });
1639
1882
  switch (parallelCallState) {
1640
1883
  case "first": {
1641
- const planSteps = parallelSteps.map(
1642
- (parallelStep, index) => parallelStep.getPlanStep(parallelSteps.length, initialStepCount + index)
1643
- );
1644
- await this.submitStepsToQStash(planSteps, parallelSteps);
1884
+ await submitParallelSteps({
1885
+ context: this.context,
1886
+ steps: parallelSteps,
1887
+ initialStepCount,
1888
+ invokeCount: this.invokeCount,
1889
+ telemetry: this.telemetry,
1890
+ debug: this.debug
1891
+ });
1645
1892
  break;
1646
1893
  }
1647
1894
  case "partial": {
@@ -1655,13 +1902,18 @@ var AutoExecutor = class _AutoExecutor {
1655
1902
  validateStep(parallelSteps[stepIndex], planStep);
1656
1903
  try {
1657
1904
  const parallelStep = parallelSteps[stepIndex];
1658
- const resultStep = await parallelStep.getResultStep(
1659
- parallelSteps.length,
1660
- planStep.targetStep
1661
- );
1662
- await this.submitStepsToQStash([resultStep], [parallelStep]);
1905
+ const resultStep = await submitSingleStep({
1906
+ context: this.context,
1907
+ lazyStep: parallelStep,
1908
+ stepId: planStep.targetStep,
1909
+ invokeCount: this.invokeCount,
1910
+ concurrency: parallelSteps.length,
1911
+ telemetry: this.telemetry,
1912
+ debug: this.debug
1913
+ });
1914
+ throw new WorkflowAbort(parallelStep.stepName, resultStep);
1663
1915
  } catch (error) {
1664
- if (error instanceof WorkflowAbort || error instanceof import_qstash4.QstashError && error.status === 400) {
1916
+ if (error instanceof WorkflowAbort || error instanceof import_qstash5.QstashError && error.status === 400) {
1665
1917
  throw error;
1666
1918
  }
1667
1919
  throw new WorkflowError(
@@ -1717,128 +1969,6 @@ var AutoExecutor = class _AutoExecutor {
1717
1969
  return "discard";
1718
1970
  }
1719
1971
  }
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
1972
  /**
1843
1973
  * Get the promise by executing the lazt steps list. If there is a single
1844
1974
  * step, we call `runSingle`. Otherwise `runParallel` is called.
@@ -1912,7 +2042,7 @@ var sortSteps = (steps) => {
1912
2042
  };
1913
2043
 
1914
2044
  // src/context/api/anthropic.ts
1915
- var import_qstash5 = require("@upstash/qstash");
2045
+ var import_qstash6 = require("@upstash/qstash");
1916
2046
 
1917
2047
  // src/context/provider.ts
1918
2048
  var getProviderInfo = (api) => {
@@ -1976,7 +2106,7 @@ var AnthropicAPI = class extends BaseWorkflowApi {
1976
2106
  return await this.callApi(stepName, {
1977
2107
  api: {
1978
2108
  name: "llm",
1979
- provider: (0, import_qstash5.anthropic)({ token })
2109
+ provider: (0, import_qstash6.anthropic)({ token })
1980
2110
  },
1981
2111
  ...parameters
1982
2112
  });
@@ -1984,12 +2114,12 @@ var AnthropicAPI = class extends BaseWorkflowApi {
1984
2114
  };
1985
2115
 
1986
2116
  // src/context/api/openai.ts
1987
- var import_qstash6 = require("@upstash/qstash");
2117
+ var import_qstash7 = require("@upstash/qstash");
1988
2118
  var OpenAIAPI = class extends BaseWorkflowApi {
1989
2119
  async call(stepName, settings) {
1990
2120
  const { token, organization, operation, baseURL, ...parameters } = settings;
1991
2121
  const useOpenAI = baseURL === void 0;
1992
- const provider = useOpenAI ? (0, import_qstash6.openai)({ token, organization }) : (0, import_qstash6.custom)({ baseUrl: baseURL, token });
2122
+ const provider = useOpenAI ? (0, import_qstash7.openai)({ token, organization }) : (0, import_qstash7.custom)({ baseUrl: baseURL, token });
1993
2123
  return await this.callApi(stepName, {
1994
2124
  api: {
1995
2125
  name: "llm",
@@ -2001,14 +2131,14 @@ var OpenAIAPI = class extends BaseWorkflowApi {
2001
2131
  };
2002
2132
 
2003
2133
  // src/context/api/resend.ts
2004
- var import_qstash7 = require("@upstash/qstash");
2134
+ var import_qstash8 = require("@upstash/qstash");
2005
2135
  var ResendAPI = class extends BaseWorkflowApi {
2006
2136
  async call(stepName, settings) {
2007
2137
  const { token, batch = false, ...parameters } = settings;
2008
2138
  return await this.callApi(stepName, {
2009
2139
  api: {
2010
2140
  name: "email",
2011
- provider: (0, import_qstash7.resend)({ token, batch })
2141
+ provider: (0, import_qstash8.resend)({ token, batch })
2012
2142
  },
2013
2143
  ...parameters
2014
2144
  });
@@ -2034,65 +2164,58 @@ var WorkflowApi = class extends BaseWorkflowApi {
2034
2164
  }
2035
2165
  };
2036
2166
 
2037
- // src/agents/adapters.ts
2167
+ // src/agents/index.ts
2038
2168
  var import_openai2 = require("@ai-sdk/openai");
2039
- var import_ai = require("ai");
2040
-
2041
- // src/agents/constants.ts
2042
- var AGENT_NAME_HEADER = "upstash-agent-name";
2043
- var MANAGER_AGENT_PROMPT = `You are an agent orchestrating other AI Agents.
2044
-
2045
- These other agents have tools available to them.
2046
-
2047
- Given a prompt, utilize these agents to address requests.
2048
-
2049
- 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.
2050
-
2051
- Avoid calling the same agent twice in one turn. Instead, prefer to call it once but provide everything
2052
- you need from that agent.
2053
- `;
2054
2169
 
2055
2170
  // src/agents/adapters.ts
2056
- var createWorkflowOpenAI = (context, config) => {
2057
- const { baseURL, apiKey } = config ?? {};
2058
- return (0, import_openai2.createOpenAI)({
2059
- baseURL,
2060
- apiKey,
2061
- compatibility: "strict",
2062
- fetch: async (input, init) => {
2063
- try {
2064
- const headers = init?.headers ? Object.fromEntries(new Headers(init.headers).entries()) : {};
2065
- const body = init?.body ? JSON.parse(init.body) : void 0;
2066
- const agentName = headers[AGENT_NAME_HEADER];
2067
- const stepName = agentName ? `Call Agent ${agentName}` : "Call Agent";
2068
- const responseInfo = await context.call(stepName, {
2069
- url: input.toString(),
2070
- method: init?.method,
2071
- headers,
2072
- body
2073
- });
2074
- const responseHeaders = new Headers(
2075
- Object.entries(responseInfo.header).reduce(
2076
- (acc, [key, values]) => {
2077
- acc[key] = values.join(", ");
2078
- return acc;
2079
- },
2080
- {}
2081
- )
2082
- );
2083
- return new Response(JSON.stringify(responseInfo.body), {
2084
- status: responseInfo.status,
2085
- headers: responseHeaders
2086
- });
2087
- } catch (error) {
2088
- if (error instanceof Error && error.name === "WorkflowAbort") {
2089
- throw error;
2090
- } else {
2091
- console.error("Error in fetch implementation:", error);
2092
- throw error;
2093
- }
2094
- }
2171
+ var import_ai = require("ai");
2172
+ var fetchWithContextCall = async (context, agentCallParams, ...params) => {
2173
+ const [input, init] = params;
2174
+ try {
2175
+ const headers = init?.headers ? Object.fromEntries(new Headers(init.headers).entries()) : {};
2176
+ const body = init?.body ? JSON.parse(init.body) : void 0;
2177
+ const agentName = headers[AGENT_NAME_HEADER];
2178
+ const stepName = agentName ? `Call Agent ${agentName}` : "Call Agent";
2179
+ const responseInfo = await context.call(stepName, {
2180
+ url: input.toString(),
2181
+ method: init?.method,
2182
+ headers,
2183
+ body,
2184
+ timeout: agentCallParams?.timeout,
2185
+ retries: agentCallParams?.retries,
2186
+ flowControl: agentCallParams?.flowControl
2187
+ });
2188
+ const responseHeaders = new Headers(
2189
+ Object.entries(responseInfo.header).reduce(
2190
+ (acc, [key, values]) => {
2191
+ acc[key] = values.join(", ");
2192
+ return acc;
2193
+ },
2194
+ {}
2195
+ )
2196
+ );
2197
+ return new Response(JSON.stringify(responseInfo.body), {
2198
+ status: responseInfo.status,
2199
+ headers: responseHeaders
2200
+ });
2201
+ } catch (error) {
2202
+ if (error instanceof Error && error.name === "WorkflowAbort") {
2203
+ throw error;
2204
+ } else {
2205
+ console.error("Error in fetch implementation:", error);
2206
+ throw error;
2095
2207
  }
2208
+ }
2209
+ };
2210
+ var createWorkflowModel = ({
2211
+ context,
2212
+ provider,
2213
+ providerParams,
2214
+ agentCallParams
2215
+ }) => {
2216
+ return provider({
2217
+ fetch: (...params) => fetchWithContextCall(context, agentCallParams, ...params),
2218
+ ...providerParams
2096
2219
  });
2097
2220
  };
2098
2221
  var wrapTools = ({
@@ -2331,10 +2454,85 @@ var WorkflowAgents = class {
2331
2454
  */
2332
2455
  openai(...params) {
2333
2456
  const [model, settings] = params;
2334
- const { baseURL, apiKey, ...otherSettings } = settings ?? {};
2335
- const openai2 = createWorkflowOpenAI(this.context, { baseURL, apiKey });
2336
- return openai2(model, otherSettings);
2457
+ const { baseURL, apiKey, callSettings, ...otherSettings } = settings ?? {};
2458
+ const openaiModel = this.AISDKModel({
2459
+ context: this.context,
2460
+ provider: import_openai2.createOpenAI,
2461
+ providerParams: { baseURL, apiKey, compatibility: "strict" },
2462
+ agentCallParams: callSettings
2463
+ });
2464
+ return openaiModel(model, otherSettings);
2465
+ }
2466
+ AISDKModel = createWorkflowModel;
2467
+ };
2468
+
2469
+ // src/serve/serve-many.ts
2470
+ var getWorkflowId = (url) => {
2471
+ const components = url.split("/");
2472
+ const lastComponent = components[components.length - 1];
2473
+ return lastComponent.split("?")[0];
2474
+ };
2475
+ var serveManyBase = ({
2476
+ workflows,
2477
+ getUrl,
2478
+ serveMethod,
2479
+ options
2480
+ }) => {
2481
+ const workflowIds = [];
2482
+ const workflowMap = Object.fromEntries(
2483
+ Object.entries(workflows).map((workflow) => {
2484
+ const workflowId = workflow[0];
2485
+ if (workflowIds.includes(workflowId)) {
2486
+ throw new WorkflowError(
2487
+ `Duplicate workflow name found: '${workflowId}'. Please set different workflow names in serveMany.`
2488
+ );
2489
+ }
2490
+ if (workflowId.includes("/")) {
2491
+ throw new WorkflowError(
2492
+ `Invalid workflow name found: '${workflowId}'. Workflow name cannot contain '/'.`
2493
+ );
2494
+ }
2495
+ workflowIds.push(workflowId);
2496
+ workflow[1].workflowId = workflowId;
2497
+ workflow[1].options = {
2498
+ ...options,
2499
+ ...workflow[1].options
2500
+ };
2501
+ const params = [workflow[1].routeFunction, workflow[1].options];
2502
+ const handler = serveMethod(...params);
2503
+ return [workflowId, handler];
2504
+ })
2505
+ );
2506
+ return {
2507
+ handler: async (...params) => {
2508
+ const url = getUrl(...params);
2509
+ const pickedWorkflowId = getWorkflowId(url);
2510
+ if (!pickedWorkflowId) {
2511
+ return new Response(
2512
+ `Unexpected request in serveMany. workflowId not set. Please update the URL of your request.`,
2513
+ {
2514
+ status: 404
2515
+ }
2516
+ );
2517
+ }
2518
+ const workflow = workflowMap[pickedWorkflowId];
2519
+ if (!workflow) {
2520
+ return new Response(
2521
+ `No workflows in serveMany found for '${pickedWorkflowId}'. Please update the URL of your request.`,
2522
+ {
2523
+ status: 404
2524
+ }
2525
+ );
2526
+ }
2527
+ return await workflow(...params);
2528
+ }
2529
+ };
2530
+ };
2531
+ var getNewUrlFromWorkflowId = (url, workflowId) => {
2532
+ if (!workflowId) {
2533
+ throw new WorkflowError("You can only call workflow which has a workflowId");
2337
2534
  }
2535
+ return url.replace(/[^/]+$/, workflowId);
2338
2536
  };
2339
2537
 
2340
2538
  // src/context/context.ts
@@ -2558,60 +2756,42 @@ var WorkflowContext = class {
2558
2756
  }
2559
2757
  await this.addStep(new LazySleepUntilStep(stepName, time));
2560
2758
  }
2561
- /**
2562
- * Makes a third party call through QStash in order to make a
2563
- * network call without consuming any runtime.
2564
- *
2565
- * ```ts
2566
- * const { status, body } = await context.call<string>(
2567
- * "post call step",
2568
- * {
2569
- * url: "https://www.some-endpoint.com/api",
2570
- * method: "POST",
2571
- * body: "my-payload"
2572
- * }
2573
- * );
2574
- * ```
2575
- *
2576
- * tries to parse the result of the request as JSON. If it's
2577
- * not a JSON which can be parsed, simply returns the response
2578
- * body as it is.
2579
- *
2580
- * @param stepName
2581
- * @param url url to call
2582
- * @param method call method. "GET" by default.
2583
- * @param body call body
2584
- * @param headers call headers
2585
- * @param retries number of call retries. 0 by default
2586
- * @param timeout max duration to wait for the endpoint to respond. in seconds.
2587
- * @returns call result as {
2588
- * status: number;
2589
- * body: unknown;
2590
- * header: Record<string, string[]>
2591
- * }
2592
- */
2593
2759
  async call(stepName, settings) {
2594
- const {
2595
- url,
2596
- method = "GET",
2597
- body: requestBody,
2598
- headers = {},
2599
- retries = 0,
2600
- timeout,
2601
- flowControl
2602
- } = settings;
2603
- return await this.addStep(
2604
- new LazyCallStep(
2760
+ let callStep;
2761
+ if ("workflow" in settings) {
2762
+ const url = getNewUrlFromWorkflowId(this.url, settings.workflow.workflowId);
2763
+ callStep = new LazyCallStep(
2764
+ stepName,
2765
+ url,
2766
+ "POST",
2767
+ settings.body,
2768
+ settings.headers || {},
2769
+ settings.retries || 0,
2770
+ settings.timeout,
2771
+ settings.flowControl ?? settings.workflow.options.flowControl
2772
+ );
2773
+ } else {
2774
+ const {
2775
+ url,
2776
+ method = "GET",
2777
+ body,
2778
+ headers = {},
2779
+ retries = 0,
2780
+ timeout,
2781
+ flowControl
2782
+ } = settings;
2783
+ callStep = new LazyCallStep(
2605
2784
  stepName,
2606
2785
  url,
2607
2786
  method,
2608
- requestBody,
2787
+ body,
2609
2788
  headers,
2610
2789
  retries,
2611
2790
  timeout,
2612
2791
  flowControl
2613
- )
2614
- );
2792
+ );
2793
+ }
2794
+ return await this.addStep(callStep);
2615
2795
  }
2616
2796
  /**
2617
2797
  * Pauses workflow execution until a specific event occurs or a timeout is reached.
@@ -2759,7 +2939,7 @@ var WorkflowLogger = class _WorkflowLogger {
2759
2939
  };
2760
2940
 
2761
2941
  // src/serve/authorization.ts
2762
- var import_qstash8 = require("@upstash/qstash");
2942
+ var import_qstash9 = require("@upstash/qstash");
2763
2943
  var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowContext {
2764
2944
  static disabledMessage = "disabled-qstash-worklfow-run";
2765
2945
  disabled = true;
@@ -2791,7 +2971,7 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
2791
2971
  */
2792
2972
  static async tryAuthentication(routeFunction, context) {
2793
2973
  const disabledContext = new _DisabledWorkflowContext({
2794
- qstashClient: new import_qstash8.Client({
2974
+ qstashClient: new import_qstash9.Client({
2795
2975
  baseUrl: "disabled-client",
2796
2976
  token: "disabled-client"
2797
2977
  }),
@@ -3005,15 +3185,15 @@ var handleFailure = async (request, requestPayload, qstashClient, initialPayload
3005
3185
  };
3006
3186
 
3007
3187
  // src/serve/options.ts
3008
- var import_qstash9 = require("@upstash/qstash");
3009
3188
  var import_qstash10 = require("@upstash/qstash");
3189
+ var import_qstash11 = require("@upstash/qstash");
3010
3190
  var processOptions = (options) => {
3011
3191
  const environment = options?.env ?? (typeof process === "undefined" ? {} : process.env);
3012
3192
  const receiverEnvironmentVariablesSet = Boolean(
3013
3193
  environment.QSTASH_CURRENT_SIGNING_KEY && environment.QSTASH_NEXT_SIGNING_KEY
3014
3194
  );
3015
3195
  return {
3016
- qstashClient: new import_qstash10.Client({
3196
+ qstashClient: new import_qstash11.Client({
3017
3197
  baseUrl: environment.QSTASH_URL,
3018
3198
  token: environment.QSTASH_TOKEN
3019
3199
  }),
@@ -3048,7 +3228,7 @@ var processOptions = (options) => {
3048
3228
  throw error;
3049
3229
  }
3050
3230
  },
3051
- receiver: receiverEnvironmentVariablesSet ? new import_qstash9.Receiver({
3231
+ receiver: receiverEnvironmentVariablesSet ? new import_qstash10.Receiver({
3052
3232
  currentSigningKey: environment.QSTASH_CURRENT_SIGNING_KEY,
3053
3233
  nextSigningKey: environment.QSTASH_NEXT_SIGNING_KEY
3054
3234
  }) : void 0,
@@ -3057,6 +3237,7 @@ var processOptions = (options) => {
3057
3237
  retries: DEFAULT_RETRIES,
3058
3238
  useJSONContent: false,
3059
3239
  disableTelemetry: false,
3240
+ onError: console.error,
3060
3241
  ...options
3061
3242
  };
3062
3243
  };
@@ -3106,7 +3287,8 @@ var serveBase = (routeFunction, telemetry2, options) => {
3106
3287
  retries,
3107
3288
  useJSONContent,
3108
3289
  disableTelemetry,
3109
- flowControl
3290
+ flowControl,
3291
+ onError
3110
3292
  } = processOptions(options);
3111
3293
  telemetry2 = disableTelemetry ? void 0 : telemetry2;
3112
3294
  const debug = WorkflowLogger.getLogger(verbose);
@@ -3235,8 +3417,19 @@ var serveBase = (routeFunction, telemetry2, options) => {
3235
3417
  try {
3236
3418
  return await handler(request);
3237
3419
  } catch (error) {
3238
- console.error(error);
3239
- return new Response(JSON.stringify(formatWorkflowError(error)), {
3420
+ const formattedError = formatWorkflowError(error);
3421
+ try {
3422
+ onError?.(error);
3423
+ } catch (onErrorError) {
3424
+ const formattedOnErrorError = formatWorkflowError(onErrorError);
3425
+ const errorMessage = `Error while running onError callback: '${formattedOnErrorError.message}'.
3426
+ Original error: '${formattedError.message}'`;
3427
+ console.error(errorMessage);
3428
+ return new Response(errorMessage, {
3429
+ status: 500
3430
+ });
3431
+ }
3432
+ return new Response(JSON.stringify(formattedError), {
3240
3433
  status: 500
3241
3434
  });
3242
3435
  }