@upstash/workflow 0.2.8-rc-invoke → 0.2.9

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.
@@ -36,6 +36,7 @@ var WORKFLOW_INIT_HEADER = "Upstash-Workflow-Init";
36
36
  var WORKFLOW_URL_HEADER = "Upstash-Workflow-Url";
37
37
  var WORKFLOW_FAILURE_HEADER = "Upstash-Workflow-Is-Failure";
38
38
  var WORKFLOW_FEATURE_HEADER = "Upstash-Feature-Set";
39
+ var WORKFLOW_INVOKE_COUNT_HEADER = "Upstash-Workflow-Invoke-Count";
39
40
  var WORKFLOW_PROTOCOL_VERSION = "1";
40
41
  var WORKFLOW_PROTOCOL_VERSION_HEADER = "Upstash-Workflow-Sdk-Version";
41
42
  var DEFAULT_CONTENT_TYPE = "application/json";
@@ -100,66 +101,6 @@ var StepTypes = [
100
101
  "Invoke"
101
102
  ];
102
103
 
103
- // src/client/utils.ts
104
- import { QstashError as QstashError2 } from "@upstash/qstash";
105
- var makeNotifyRequest = async (requester, eventId, eventData) => {
106
- const result = await requester.request({
107
- path: ["v2", "notify", eventId],
108
- method: "POST",
109
- body: typeof eventData === "string" ? eventData : JSON.stringify(eventData)
110
- });
111
- return result;
112
- };
113
- var makeGetWaitersRequest = async (requester, eventId) => {
114
- const result = await requester.request({
115
- path: ["v2", "waiters", eventId],
116
- method: "GET"
117
- });
118
- return result;
119
- };
120
- var makeCancelRequest = async (requester, workflowRunId) => {
121
- await requester.request({
122
- path: ["v2", "workflows", "runs", `${workflowRunId}?cancel=true`],
123
- method: "DELETE",
124
- parseResponseAsJson: false
125
- });
126
- return true;
127
- };
128
- var getSteps = async (requester, workflowRunId, messageId, debug) => {
129
- try {
130
- const steps = await requester.request({
131
- path: ["v2", "workflows", "runs", workflowRunId],
132
- parseResponseAsJson: true
133
- });
134
- if (!messageId) {
135
- await debug?.log("INFO", "ENDPOINT_START", {
136
- message: `Pulled ${steps.length} steps from QStashand returned them without filtering with messageId.`
137
- });
138
- return { steps, workflowRunEnded: false };
139
- } else {
140
- const index = steps.findIndex((item) => item.messageId === messageId);
141
- if (index === -1) {
142
- return { steps: [], workflowRunEnded: false };
143
- }
144
- const filteredSteps = steps.slice(0, index + 1);
145
- await debug?.log("INFO", "ENDPOINT_START", {
146
- message: `Pulled ${steps.length} steps from QStash and filtered them to ${filteredSteps.length} using messageId.`
147
- });
148
- return { steps: filteredSteps, workflowRunEnded: false };
149
- }
150
- } catch (error) {
151
- if (error instanceof QstashError2 && error.status === 404) {
152
- await debug?.log("WARN", "ENDPOINT_START", {
153
- message: "Couldn't fetch workflow run steps. This can happen if the workflow run succesfully ends before some callback is executed.",
154
- error
155
- });
156
- return { steps: void 0, workflowRunEnded: true };
157
- } else {
158
- throw error;
159
- }
160
- }
161
- };
162
-
163
104
  // src/utils.ts
164
105
  var NANOID_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
165
106
  var NANOID_LENGTH = 21;
@@ -185,339 +126,123 @@ function decodeBase64(base64) {
185
126
  }
186
127
  }
187
128
 
188
- // src/context/steps.ts
189
- var BaseLazyStep = class {
190
- stepName;
191
- // will be set in the subclasses
192
- constructor(stepName) {
193
- if (!stepName) {
194
- throw new WorkflowError(
195
- "A workflow step name cannot be undefined or an empty string. Please provide a name for your workflow step."
196
- );
197
- }
198
- this.stepName = stepName;
199
- }
129
+ // node_modules/neverthrow/dist/index.es.js
130
+ var defaultErrorConfig = {
131
+ withStackTrace: false
200
132
  };
201
- var LazyFunctionStep = class extends BaseLazyStep {
202
- stepFunction;
203
- stepType = "Run";
204
- constructor(stepName, stepFunction) {
205
- super(stepName);
206
- this.stepFunction = stepFunction;
133
+ var createNeverThrowError = (message, result, config = defaultErrorConfig) => {
134
+ const data = result.isOk() ? { type: "Ok", value: result.value } : { type: "Err", value: result.error };
135
+ const maybeStack = config.withStackTrace ? new Error().stack : void 0;
136
+ return {
137
+ data,
138
+ message,
139
+ stack: maybeStack
140
+ };
141
+ };
142
+ function __awaiter(thisArg, _arguments, P, generator) {
143
+ function adopt(value) {
144
+ return value instanceof P ? value : new P(function(resolve) {
145
+ resolve(value);
146
+ });
207
147
  }
208
- getPlanStep(concurrent, targetStep) {
209
- return {
210
- stepId: 0,
211
- stepName: this.stepName,
212
- stepType: this.stepType,
213
- concurrent,
214
- targetStep
148
+ return new (P || (P = Promise))(function(resolve, reject) {
149
+ function fulfilled(value) {
150
+ try {
151
+ step(generator.next(value));
152
+ } catch (e) {
153
+ reject(e);
154
+ }
155
+ }
156
+ function rejected(value) {
157
+ try {
158
+ step(generator["throw"](value));
159
+ } catch (e) {
160
+ reject(e);
161
+ }
162
+ }
163
+ function step(result) {
164
+ result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
165
+ }
166
+ step((generator = generator.apply(thisArg, [])).next());
167
+ });
168
+ }
169
+ function __values(o) {
170
+ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
171
+ if (m) return m.call(o);
172
+ if (o && typeof o.length === "number") return {
173
+ next: function() {
174
+ if (o && i >= o.length) o = void 0;
175
+ return { value: o && o[i++], done: !o };
176
+ }
177
+ };
178
+ throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
179
+ }
180
+ function __await(v) {
181
+ return this instanceof __await ? (this.v = v, this) : new __await(v);
182
+ }
183
+ function __asyncGenerator(thisArg, _arguments, generator) {
184
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
185
+ var g = generator.apply(thisArg, _arguments || []), i, q = [];
186
+ return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function() {
187
+ return this;
188
+ }, i;
189
+ function verb(n) {
190
+ if (g[n]) i[n] = function(v) {
191
+ return new Promise(function(a, b) {
192
+ q.push([n, v, a, b]) > 1 || resume(n, v);
193
+ });
215
194
  };
216
195
  }
217
- async getResultStep(concurrent, stepId) {
218
- let result = this.stepFunction();
219
- if (result instanceof Promise) {
220
- result = await result;
196
+ function resume(n, v) {
197
+ try {
198
+ step(g[n](v));
199
+ } catch (e) {
200
+ settle(q[0][3], e);
221
201
  }
222
- return {
223
- stepId,
224
- stepName: this.stepName,
225
- stepType: this.stepType,
226
- out: result,
227
- concurrent
228
- };
229
202
  }
230
- };
231
- var LazySleepStep = class extends BaseLazyStep {
232
- sleep;
233
- stepType = "SleepFor";
234
- constructor(stepName, sleep) {
235
- super(stepName);
236
- this.sleep = sleep;
203
+ function step(r) {
204
+ r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r);
237
205
  }
238
- getPlanStep(concurrent, targetStep) {
239
- return {
240
- stepId: 0,
241
- stepName: this.stepName,
242
- stepType: this.stepType,
243
- sleepFor: this.sleep,
244
- concurrent,
245
- targetStep
246
- };
206
+ function fulfill(value) {
207
+ resume("next", value);
247
208
  }
248
- async getResultStep(concurrent, stepId) {
249
- return await Promise.resolve({
250
- stepId,
251
- stepName: this.stepName,
252
- stepType: this.stepType,
253
- sleepFor: this.sleep,
254
- concurrent
255
- });
209
+ function reject(value) {
210
+ resume("throw", value);
256
211
  }
257
- };
258
- var LazySleepUntilStep = class extends BaseLazyStep {
259
- sleepUntil;
260
- stepType = "SleepUntil";
261
- constructor(stepName, sleepUntil) {
262
- super(stepName);
263
- this.sleepUntil = sleepUntil;
212
+ function settle(f, v) {
213
+ if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]);
264
214
  }
265
- getPlanStep(concurrent, targetStep) {
266
- return {
267
- stepId: 0,
268
- stepName: this.stepName,
269
- stepType: this.stepType,
270
- sleepUntil: this.sleepUntil,
271
- concurrent,
272
- targetStep
215
+ }
216
+ function __asyncDelegator(o) {
217
+ var i, p;
218
+ return i = {}, verb("next"), verb("throw", function(e) {
219
+ throw e;
220
+ }), verb("return"), i[Symbol.iterator] = function() {
221
+ return this;
222
+ }, i;
223
+ function verb(n, f) {
224
+ i[n] = o[n] ? function(v) {
225
+ return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v;
226
+ } : f;
227
+ }
228
+ }
229
+ function __asyncValues(o) {
230
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
231
+ var m = o[Symbol.asyncIterator], i;
232
+ 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() {
233
+ return this;
234
+ }, i);
235
+ function verb(n) {
236
+ i[n] = o[n] && function(v) {
237
+ return new Promise(function(resolve, reject) {
238
+ v = o[n](v), settle(resolve, reject, v.done, v.value);
239
+ });
273
240
  };
274
241
  }
275
- async getResultStep(concurrent, stepId) {
276
- return await Promise.resolve({
277
- stepId,
278
- stepName: this.stepName,
279
- stepType: this.stepType,
280
- sleepUntil: this.sleepUntil,
281
- concurrent
282
- });
283
- }
284
- };
285
- var LazyCallStep = class extends BaseLazyStep {
286
- url;
287
- method;
288
- body;
289
- headers;
290
- retries;
291
- timeout;
292
- stepType = "Call";
293
- constructor(stepName, url, method, body, headers, retries, timeout) {
294
- super(stepName);
295
- this.url = url;
296
- this.method = method;
297
- this.body = body;
298
- this.headers = headers;
299
- this.retries = retries;
300
- this.timeout = timeout;
301
- }
302
- getPlanStep(concurrent, targetStep) {
303
- return {
304
- stepId: 0,
305
- stepName: this.stepName,
306
- stepType: this.stepType,
307
- concurrent,
308
- targetStep
309
- };
310
- }
311
- async getResultStep(concurrent, stepId) {
312
- return await Promise.resolve({
313
- stepId,
314
- stepName: this.stepName,
315
- stepType: this.stepType,
316
- concurrent,
317
- callUrl: this.url,
318
- callMethod: this.method,
319
- callBody: this.body,
320
- callHeaders: this.headers
321
- });
322
- }
323
- };
324
- var LazyWaitForEventStep = class extends BaseLazyStep {
325
- eventId;
326
- timeout;
327
- stepType = "Wait";
328
- constructor(stepName, eventId, timeout) {
329
- super(stepName);
330
- this.eventId = eventId;
331
- this.timeout = timeout;
332
- }
333
- getPlanStep(concurrent, targetStep) {
334
- return {
335
- stepId: 0,
336
- stepName: this.stepName,
337
- stepType: this.stepType,
338
- waitEventId: this.eventId,
339
- timeout: this.timeout,
340
- concurrent,
341
- targetStep
342
- };
343
- }
344
- async getResultStep(concurrent, stepId) {
345
- return await Promise.resolve({
346
- stepId,
347
- stepName: this.stepName,
348
- stepType: this.stepType,
349
- waitEventId: this.eventId,
350
- timeout: this.timeout,
351
- concurrent
352
- });
353
- }
354
- };
355
- var LazyNotifyStep = class extends LazyFunctionStep {
356
- stepType = "Notify";
357
- constructor(stepName, eventId, eventData, requester) {
358
- super(stepName, async () => {
359
- const notifyResponse = await makeNotifyRequest(requester, eventId, eventData);
360
- return {
361
- eventId,
362
- eventData,
363
- notifyResponse
364
- };
365
- });
366
- }
367
- };
368
- var LazyInvokeStep = class extends BaseLazyStep {
369
- stepType = "Invoke";
370
- params;
371
- constructor(stepName, { workflow, body, headers = {}, workflowRunId, retries }) {
372
- super(stepName);
373
- this.params = {
374
- workflow,
375
- body,
376
- headers,
377
- workflowRunId: getWorkflowRunId(workflowRunId),
378
- retries
379
- };
380
- }
381
- getPlanStep(concurrent, targetStep) {
382
- return {
383
- stepId: 0,
384
- stepName: this.stepName,
385
- stepType: this.stepType,
386
- concurrent,
387
- targetStep
388
- };
389
- }
390
- /**
391
- * won't be used as it's the server who will add the result step
392
- * in Invoke step.
393
- */
394
- getResultStep(concurrent, stepId) {
395
- return Promise.resolve({
396
- stepId,
397
- stepName: this.stepName,
398
- stepType: this.stepType,
399
- concurrent
400
- });
401
- }
402
- };
403
-
404
- // node_modules/neverthrow/dist/index.es.js
405
- var defaultErrorConfig = {
406
- withStackTrace: false
407
- };
408
- var createNeverThrowError = (message, result, config = defaultErrorConfig) => {
409
- const data = result.isOk() ? { type: "Ok", value: result.value } : { type: "Err", value: result.error };
410
- const maybeStack = config.withStackTrace ? new Error().stack : void 0;
411
- return {
412
- data,
413
- message,
414
- stack: maybeStack
415
- };
416
- };
417
- function __awaiter(thisArg, _arguments, P, generator) {
418
- function adopt(value) {
419
- return value instanceof P ? value : new P(function(resolve) {
420
- resolve(value);
421
- });
422
- }
423
- return new (P || (P = Promise))(function(resolve, reject) {
424
- function fulfilled(value) {
425
- try {
426
- step(generator.next(value));
427
- } catch (e) {
428
- reject(e);
429
- }
430
- }
431
- function rejected(value) {
432
- try {
433
- step(generator["throw"](value));
434
- } catch (e) {
435
- reject(e);
436
- }
437
- }
438
- function step(result) {
439
- result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
440
- }
441
- step((generator = generator.apply(thisArg, [])).next());
442
- });
443
- }
444
- function __values(o) {
445
- var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
446
- if (m) return m.call(o);
447
- if (o && typeof o.length === "number") return {
448
- next: function() {
449
- if (o && i >= o.length) o = void 0;
450
- return { value: o && o[i++], done: !o };
451
- }
452
- };
453
- throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
454
- }
455
- function __await(v) {
456
- return this instanceof __await ? (this.v = v, this) : new __await(v);
457
- }
458
- function __asyncGenerator(thisArg, _arguments, generator) {
459
- if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
460
- var g = generator.apply(thisArg, _arguments || []), i, q = [];
461
- return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function() {
462
- return this;
463
- }, i;
464
- function verb(n) {
465
- if (g[n]) i[n] = function(v) {
466
- return new Promise(function(a, b) {
467
- q.push([n, v, a, b]) > 1 || resume(n, v);
468
- });
469
- };
470
- }
471
- function resume(n, v) {
472
- try {
473
- step(g[n](v));
474
- } catch (e) {
475
- settle(q[0][3], e);
476
- }
477
- }
478
- function step(r) {
479
- r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r);
480
- }
481
- function fulfill(value) {
482
- resume("next", value);
483
- }
484
- function reject(value) {
485
- resume("throw", value);
486
- }
487
- function settle(f, v) {
488
- if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]);
489
- }
490
- }
491
- function __asyncDelegator(o) {
492
- var i, p;
493
- return i = {}, verb("next"), verb("throw", function(e) {
494
- throw e;
495
- }), verb("return"), i[Symbol.iterator] = function() {
496
- return this;
497
- }, i;
498
- function verb(n, f) {
499
- i[n] = o[n] ? function(v) {
500
- return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v;
501
- } : f;
502
- }
503
- }
504
- function __asyncValues(o) {
505
- if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
506
- var m = o[Symbol.asyncIterator], i;
507
- 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() {
508
- return this;
509
- }, i);
510
- function verb(n) {
511
- i[n] = o[n] && function(v) {
512
- return new Promise(function(resolve, reject) {
513
- v = o[n](v), settle(resolve, reject, v.done, v.value);
514
- });
515
- };
516
- }
517
- function settle(resolve, reject, d, v) {
518
- Promise.resolve(v).then(function(v2) {
519
- resolve({ value: v2, done: d });
520
- }, reject);
242
+ function settle(resolve, reject, d, v) {
243
+ Promise.resolve(v).then(function(v2) {
244
+ resolve({ value: v2, done: d });
245
+ }, reject);
521
246
  }
522
247
  }
523
248
  var ResultAsync = class _ResultAsync {
@@ -818,29 +543,94 @@ var fromThrowable = Result.fromThrowable;
818
543
 
819
544
  // src/workflow-requests.ts
820
545
  import { QstashError as QstashError3 } from "@upstash/qstash";
821
- var triggerFirstInvocation = async ({
822
- workflowContext,
823
- useJSONContent,
824
- telemetry,
825
- debug
826
- }) => {
827
- const { headers } = getHeaders({
828
- initHeaderValue: "true",
829
- workflowRunId: workflowContext.workflowRunId,
830
- workflowUrl: workflowContext.url,
831
- userHeaders: workflowContext.headers,
832
- failureUrl: workflowContext.failureUrl,
833
- retries: workflowContext.retries,
834
- telemetry
546
+
547
+ // src/client/utils.ts
548
+ import { QstashError as QstashError2 } from "@upstash/qstash";
549
+ var makeNotifyRequest = async (requester, eventId, eventData) => {
550
+ const result = await requester.request({
551
+ path: ["v2", "notify", eventId],
552
+ method: "POST",
553
+ body: typeof eventData === "string" ? eventData : JSON.stringify(eventData)
835
554
  });
836
- if (workflowContext.headers.get("content-type")) {
837
- headers["content-type"] = workflowContext.headers.get("content-type");
838
- }
839
- if (useJSONContent) {
840
- headers["content-type"] = "application/json";
841
- }
842
- try {
843
- const body = typeof workflowContext.requestPayload === "string" ? workflowContext.requestPayload : JSON.stringify(workflowContext.requestPayload);
555
+ return result;
556
+ };
557
+ var makeGetWaitersRequest = async (requester, eventId) => {
558
+ const result = await requester.request({
559
+ path: ["v2", "waiters", eventId],
560
+ method: "GET"
561
+ });
562
+ return result;
563
+ };
564
+ var makeCancelRequest = async (requester, workflowRunId) => {
565
+ await requester.request({
566
+ path: ["v2", "workflows", "runs", `${workflowRunId}?cancel=true`],
567
+ method: "DELETE",
568
+ parseResponseAsJson: false
569
+ });
570
+ return true;
571
+ };
572
+ var getSteps = async (requester, workflowRunId, messageId, debug) => {
573
+ try {
574
+ const steps = await requester.request({
575
+ path: ["v2", "workflows", "runs", workflowRunId],
576
+ parseResponseAsJson: true
577
+ });
578
+ if (!messageId) {
579
+ await debug?.log("INFO", "ENDPOINT_START", {
580
+ message: `Pulled ${steps.length} steps from QStashand returned them without filtering with messageId.`
581
+ });
582
+ return { steps, workflowRunEnded: false };
583
+ } else {
584
+ const index = steps.findIndex((item) => item.messageId === messageId);
585
+ if (index === -1) {
586
+ return { steps: [], workflowRunEnded: false };
587
+ }
588
+ const filteredSteps = steps.slice(0, index + 1);
589
+ await debug?.log("INFO", "ENDPOINT_START", {
590
+ message: `Pulled ${steps.length} steps from QStash and filtered them to ${filteredSteps.length} using messageId.`
591
+ });
592
+ return { steps: filteredSteps, workflowRunEnded: false };
593
+ }
594
+ } catch (error) {
595
+ if (error instanceof QstashError2 && error.status === 404) {
596
+ await debug?.log("WARN", "ENDPOINT_START", {
597
+ message: "Couldn't fetch workflow run steps. This can happen if the workflow run succesfully ends before some callback is executed.",
598
+ error
599
+ });
600
+ return { steps: void 0, workflowRunEnded: true };
601
+ } else {
602
+ throw error;
603
+ }
604
+ }
605
+ };
606
+
607
+ // src/workflow-requests.ts
608
+ var triggerFirstInvocation = async ({
609
+ workflowContext,
610
+ useJSONContent,
611
+ telemetry,
612
+ debug,
613
+ invokeCount
614
+ }) => {
615
+ const { headers } = getHeaders({
616
+ initHeaderValue: "true",
617
+ workflowRunId: workflowContext.workflowRunId,
618
+ workflowUrl: workflowContext.url,
619
+ userHeaders: workflowContext.headers,
620
+ failureUrl: workflowContext.failureUrl,
621
+ retries: workflowContext.retries,
622
+ telemetry,
623
+ invokeCount,
624
+ flowControl: workflowContext.flowControl
625
+ });
626
+ if (workflowContext.headers.get("content-type")) {
627
+ headers["content-type"] = workflowContext.headers.get("content-type");
628
+ }
629
+ if (useJSONContent) {
630
+ headers["content-type"] = "application/json";
631
+ }
632
+ try {
633
+ const body = typeof workflowContext.requestPayload === "string" ? workflowContext.requestPayload : JSON.stringify(workflowContext.requestPayload);
844
634
  const result = await workflowContext.qstashClient.publish({
845
635
  headers,
846
636
  method: "POST",
@@ -937,6 +727,7 @@ var handleThirdPartyCallResult = async ({
937
727
  failureUrl,
938
728
  retries,
939
729
  telemetry,
730
+ flowControl,
940
731
  debug
941
732
  }) => {
942
733
  try {
@@ -984,6 +775,7 @@ ${atob(callbackMessage.body ?? "")}`
984
775
  const stepType = request.headers.get("Upstash-Workflow-StepType");
985
776
  const concurrentString = request.headers.get("Upstash-Workflow-Concurrent");
986
777
  const contentType = request.headers.get("Upstash-Workflow-ContentType");
778
+ const invokeCount = request.headers.get(WORKFLOW_INVOKE_COUNT_HEADER);
987
779
  if (!(workflowRunId && stepIdString && stepName && StepTypes.includes(stepType) && concurrentString && contentType)) {
988
780
  throw new Error(
989
781
  `Missing info in callback message source header: ${JSON.stringify({
@@ -1004,7 +796,9 @@ ${atob(callbackMessage.body ?? "")}`
1004
796
  userHeaders,
1005
797
  failureUrl,
1006
798
  retries,
1007
- telemetry
799
+ telemetry,
800
+ invokeCount: Number(invokeCount),
801
+ flowControl
1008
802
  });
1009
803
  const callResponse = {
1010
804
  status: callbackMessage.status,
@@ -1060,7 +854,10 @@ var getHeaders = ({
1060
854
  step,
1061
855
  callRetries,
1062
856
  callTimeout,
1063
- telemetry
857
+ telemetry,
858
+ invokeCount,
859
+ flowControl,
860
+ callFlowControl
1064
861
  }) => {
1065
862
  const contentType = (userHeaders ? userHeaders.get("Content-Type") : void 0) ?? DEFAULT_CONTENT_TYPE;
1066
863
  const baseHeaders = {
@@ -1072,6 +869,9 @@ var getHeaders = ({
1072
869
  "content-type": contentType,
1073
870
  ...telemetry ? getTelemetryHeaders(telemetry) : {}
1074
871
  };
872
+ if (invokeCount !== void 0 && !step?.callUrl) {
873
+ baseHeaders[`Upstash-Forward-${WORKFLOW_INVOKE_COUNT_HEADER}`] = invokeCount.toString();
874
+ }
1075
875
  if (!step?.callUrl) {
1076
876
  baseHeaders[`Upstash-Forward-${WORKFLOW_PROTOCOL_VERSION_HEADER}`] = WORKFLOW_PROTOCOL_VERSION;
1077
877
  }
@@ -1080,13 +880,23 @@ var getHeaders = ({
1080
880
  }
1081
881
  if (failureUrl) {
1082
882
  baseHeaders[`Upstash-Failure-Callback-Forward-${WORKFLOW_FAILURE_HEADER}`] = "true";
883
+ baseHeaders[`Upstash-Failure-Callback-Forward-Upstash-Workflow-Failure-Callback`] = "true";
884
+ baseHeaders["Upstash-Failure-Callback-Workflow-Runid"] = workflowRunId;
885
+ baseHeaders["Upstash-Failure-Callback-Workflow-Init"] = "false";
886
+ baseHeaders["Upstash-Failure-Callback-Workflow-Url"] = workflowUrl;
887
+ baseHeaders["Upstash-Failure-Callback-Workflow-Calltype"] = "failureCall";
888
+ if (retries !== void 0) {
889
+ baseHeaders["Upstash-Failure-Callback-Retries"] = retries.toString();
890
+ }
891
+ if (flowControl) {
892
+ const { flowControlKey, flowControlValue } = prepareFlowControl(flowControl);
893
+ baseHeaders["Upstash-Failure-Callback-Flow-Control-Key"] = flowControlKey;
894
+ baseHeaders["Upstash-Failure-Callback-Flow-Control-Value"] = flowControlValue;
895
+ }
1083
896
  if (!step?.callUrl) {
1084
897
  baseHeaders["Upstash-Failure-Callback"] = failureUrl;
1085
898
  }
1086
899
  }
1087
- if (step?.stepType === "Invoke") {
1088
- baseHeaders["upstash-workflow-invoke"] = "true";
1089
- }
1090
900
  if (step?.callUrl) {
1091
901
  baseHeaders["Upstash-Retries"] = callRetries?.toString() ?? "0";
1092
902
  baseHeaders[WORKFLOW_FEATURE_HEADER] = "WF_NoDelete,InitialBody";
@@ -1094,9 +904,26 @@ var getHeaders = ({
1094
904
  baseHeaders["Upstash-Callback-Retries"] = retries.toString();
1095
905
  baseHeaders["Upstash-Failure-Callback-Retries"] = retries.toString();
1096
906
  }
1097
- } else if (retries !== void 0) {
1098
- baseHeaders["Upstash-Retries"] = retries.toString();
1099
- baseHeaders["Upstash-Failure-Callback-Retries"] = retries.toString();
907
+ if (callFlowControl) {
908
+ const { flowControlKey, flowControlValue } = prepareFlowControl(callFlowControl);
909
+ baseHeaders["Upstash-Flow-Control-Key"] = flowControlKey;
910
+ baseHeaders["Upstash-Flow-Control-Value"] = flowControlValue;
911
+ }
912
+ if (flowControl) {
913
+ const { flowControlKey, flowControlValue } = prepareFlowControl(flowControl);
914
+ baseHeaders["Upstash-Callback-Flow-Control-Key"] = flowControlKey;
915
+ baseHeaders["Upstash-Callback-Flow-Control-Value"] = flowControlValue;
916
+ }
917
+ } else {
918
+ if (flowControl) {
919
+ const { flowControlKey, flowControlValue } = prepareFlowControl(flowControl);
920
+ baseHeaders["Upstash-Flow-Control-Key"] = flowControlKey;
921
+ baseHeaders["Upstash-Flow-Control-Value"] = flowControlValue;
922
+ }
923
+ if (retries !== void 0) {
924
+ baseHeaders["Upstash-Retries"] = retries.toString();
925
+ baseHeaders["Upstash-Failure-Callback-Retries"] = retries.toString();
926
+ }
1100
927
  }
1101
928
  if (userHeaders) {
1102
929
  for (const header of userHeaders.keys()) {
@@ -1116,76 +943,575 @@ var getHeaders = ({
1116
943
  ])
1117
944
  );
1118
945
  return {
1119
- headers: {
1120
- ...baseHeaders,
1121
- ...forwardedHeaders,
1122
- "Upstash-Callback": workflowUrl,
1123
- "Upstash-Callback-Workflow-RunId": workflowRunId,
1124
- "Upstash-Callback-Workflow-CallType": "fromCallback",
1125
- "Upstash-Callback-Workflow-Init": "false",
1126
- "Upstash-Callback-Workflow-Url": workflowUrl,
1127
- "Upstash-Callback-Feature-Set": "LazyFetch,InitialBody",
1128
- "Upstash-Callback-Forward-Upstash-Workflow-Callback": "true",
1129
- "Upstash-Callback-Forward-Upstash-Workflow-StepId": step.stepId.toString(),
1130
- "Upstash-Callback-Forward-Upstash-Workflow-StepName": step.stepName,
1131
- "Upstash-Callback-Forward-Upstash-Workflow-StepType": step.stepType,
1132
- "Upstash-Callback-Forward-Upstash-Workflow-Concurrent": step.concurrent.toString(),
1133
- "Upstash-Callback-Forward-Upstash-Workflow-ContentType": contentType,
1134
- "Upstash-Workflow-CallType": "toCallback"
1135
- }
946
+ headers: {
947
+ ...baseHeaders,
948
+ ...forwardedHeaders,
949
+ "Upstash-Callback": workflowUrl,
950
+ "Upstash-Callback-Workflow-RunId": workflowRunId,
951
+ "Upstash-Callback-Workflow-CallType": "fromCallback",
952
+ "Upstash-Callback-Workflow-Init": "false",
953
+ "Upstash-Callback-Workflow-Url": workflowUrl,
954
+ "Upstash-Callback-Feature-Set": "LazyFetch,InitialBody",
955
+ "Upstash-Callback-Forward-Upstash-Workflow-Callback": "true",
956
+ "Upstash-Callback-Forward-Upstash-Workflow-StepId": step.stepId.toString(),
957
+ "Upstash-Callback-Forward-Upstash-Workflow-StepName": step.stepName,
958
+ "Upstash-Callback-Forward-Upstash-Workflow-StepType": step.stepType,
959
+ "Upstash-Callback-Forward-Upstash-Workflow-Concurrent": step.concurrent.toString(),
960
+ "Upstash-Callback-Forward-Upstash-Workflow-ContentType": contentType,
961
+ [`Upstash-Callback-Forward-${WORKFLOW_INVOKE_COUNT_HEADER}`]: (invokeCount ?? 0).toString(),
962
+ "Upstash-Workflow-CallType": "toCallback"
963
+ }
964
+ };
965
+ }
966
+ if (step?.waitEventId) {
967
+ return {
968
+ headers: {
969
+ ...baseHeaders,
970
+ "Upstash-Workflow-CallType": "step"
971
+ },
972
+ timeoutHeaders: {
973
+ // to include user headers:
974
+ ...Object.fromEntries(
975
+ Object.entries(baseHeaders).map(([header, value]) => [header, [value]])
976
+ ),
977
+ // to include telemetry headers:
978
+ ...telemetry ? Object.fromEntries(
979
+ Object.entries(getTelemetryHeaders(telemetry)).map(([header, value]) => [
980
+ header,
981
+ [value]
982
+ ])
983
+ ) : {},
984
+ // note: using WORKFLOW_ID_HEADER doesn't work, because Runid -> RunId:
985
+ "Upstash-Workflow-Runid": [workflowRunId],
986
+ [WORKFLOW_INIT_HEADER]: ["false"],
987
+ [WORKFLOW_URL_HEADER]: [workflowUrl],
988
+ "Upstash-Workflow-CallType": ["step"]
989
+ }
990
+ };
991
+ }
992
+ return { headers: baseHeaders };
993
+ };
994
+ var verifyRequest = async (body, signature, verifier) => {
995
+ if (!verifier) {
996
+ return;
997
+ }
998
+ try {
999
+ if (!signature) {
1000
+ throw new Error("`Upstash-Signature` header is not passed.");
1001
+ }
1002
+ const isValid = await verifier.verify({
1003
+ body,
1004
+ signature
1005
+ });
1006
+ if (!isValid) {
1007
+ throw new Error("Signature in `Upstash-Signature` header is not valid");
1008
+ }
1009
+ } catch (error) {
1010
+ throw new WorkflowError(
1011
+ `Failed to verify that the Workflow request comes from QStash: ${error}
1012
+
1013
+ If signature is missing, trigger the workflow endpoint by publishing your request to QStash instead of calling it directly.
1014
+
1015
+ If you want to disable QStash Verification, you should clear env variables QSTASH_CURRENT_SIGNING_KEY and QSTASH_NEXT_SIGNING_KEY`
1016
+ );
1017
+ }
1018
+ };
1019
+ var prepareFlowControl = (flowControl) => {
1020
+ const parallelism = flowControl.parallelism?.toString();
1021
+ const rate = flowControl.ratePerSecond?.toString();
1022
+ const controlValue = [
1023
+ parallelism ? `parallelism=${parallelism}` : void 0,
1024
+ rate ? `rate=${rate}` : void 0
1025
+ ].filter(Boolean);
1026
+ if (controlValue.length === 0) {
1027
+ throw new QstashError3("Provide at least one of parallelism or ratePerSecond for flowControl");
1028
+ }
1029
+ return {
1030
+ flowControlKey: flowControl.key,
1031
+ flowControlValue: controlValue.join(", ")
1032
+ };
1033
+ };
1034
+
1035
+ // src/serve/serve-many.ts
1036
+ var getWorkflowId = (url) => {
1037
+ const components = url.split("/");
1038
+ const lastComponent = components[components.length - 1];
1039
+ return lastComponent.split("?")[0];
1040
+ };
1041
+ var serveManyBase = ({
1042
+ workflows,
1043
+ getUrl,
1044
+ serveMethod,
1045
+ options
1046
+ }) => {
1047
+ const workflowIds = [];
1048
+ const workflowMap = Object.fromEntries(
1049
+ Object.entries(workflows).map((workflow) => {
1050
+ const workflowId = workflow[0];
1051
+ if (workflowIds.includes(workflowId)) {
1052
+ throw new WorkflowError(
1053
+ `Duplicate workflow name found: '${workflowId}'. Please set different workflow names in serveMany.`
1054
+ );
1055
+ }
1056
+ if (workflowId.includes("/")) {
1057
+ throw new WorkflowError(
1058
+ `Invalid workflow name found: '${workflowId}'. Workflow name cannot contain '/'.`
1059
+ );
1060
+ }
1061
+ workflowIds.push(workflowId);
1062
+ workflow[1].workflowId = workflowId;
1063
+ workflow[1].options = {
1064
+ ...options,
1065
+ ...workflow[1].options
1066
+ };
1067
+ const params = [workflow[1].routeFunction, workflow[1].options];
1068
+ const handler = serveMethod(...params);
1069
+ return [workflowId, handler];
1070
+ })
1071
+ );
1072
+ return {
1073
+ handler: async (...params) => {
1074
+ const url = getUrl(...params);
1075
+ const pickedWorkflowId = getWorkflowId(url);
1076
+ if (!pickedWorkflowId) {
1077
+ return new Response(
1078
+ `Unexpected request in serveMany. workflowId not set. Please update the URL of your request.`,
1079
+ {
1080
+ status: 404
1081
+ }
1082
+ );
1083
+ }
1084
+ const workflow = workflowMap[pickedWorkflowId];
1085
+ if (!workflow) {
1086
+ return new Response(
1087
+ `No workflows in serveMany found for '${pickedWorkflowId}'. Please update the URL of your request.`,
1088
+ {
1089
+ status: 404
1090
+ }
1091
+ );
1092
+ }
1093
+ return await workflow(...params);
1094
+ }
1095
+ };
1096
+ };
1097
+ var invokeWorkflow = async ({
1098
+ settings,
1099
+ invokeStep,
1100
+ context,
1101
+ invokeCount,
1102
+ telemetry
1103
+ }) => {
1104
+ const {
1105
+ body,
1106
+ workflow,
1107
+ headers = {},
1108
+ workflowRunId = getWorkflowRunId(),
1109
+ retries,
1110
+ flowControl
1111
+ } = settings;
1112
+ const { workflowId } = workflow;
1113
+ const {
1114
+ retries: workflowRetries,
1115
+ failureFunction,
1116
+ failureUrl,
1117
+ useJSONContent,
1118
+ flowControl: workflowFlowControl
1119
+ } = workflow.options;
1120
+ if (!workflowId) {
1121
+ throw new WorkflowError("You can only invoke workflow which has a workflowId");
1122
+ }
1123
+ const { headers: invokerHeaders } = getHeaders({
1124
+ initHeaderValue: "false",
1125
+ workflowRunId: context.workflowRunId,
1126
+ workflowUrl: context.url,
1127
+ userHeaders: context.headers,
1128
+ failureUrl: context.failureUrl,
1129
+ retries: context.retries,
1130
+ telemetry,
1131
+ invokeCount,
1132
+ flowControl: context.flowControl
1133
+ });
1134
+ invokerHeaders["Upstash-Workflow-Runid"] = context.workflowRunId;
1135
+ const newUrl = context.url.replace(/[^/]+$/, workflowId);
1136
+ const { headers: triggerHeaders } = getHeaders({
1137
+ initHeaderValue: "true",
1138
+ workflowRunId,
1139
+ workflowUrl: newUrl,
1140
+ userHeaders: new Headers(headers),
1141
+ retries: retries ?? workflowRetries,
1142
+ telemetry,
1143
+ failureUrl: failureFunction ? newUrl : failureUrl,
1144
+ invokeCount: invokeCount + 1,
1145
+ flowControl: flowControl ?? workflowFlowControl
1146
+ });
1147
+ triggerHeaders["Upstash-Workflow-Invoke"] = "true";
1148
+ if (useJSONContent) {
1149
+ triggerHeaders["content-type"] = "application/json";
1150
+ }
1151
+ const request = {
1152
+ body: JSON.stringify(body),
1153
+ headers: Object.fromEntries(
1154
+ Object.entries(invokerHeaders).map((pairs) => [pairs[0], [pairs[1]]])
1155
+ ),
1156
+ workflowRunId,
1157
+ workflowUrl: context.url,
1158
+ step: invokeStep
1159
+ };
1160
+ await context.qstashClient.publish({
1161
+ headers: triggerHeaders,
1162
+ method: "POST",
1163
+ body: JSON.stringify(request),
1164
+ url: newUrl
1165
+ });
1166
+ };
1167
+
1168
+ // src/agents/adapters.ts
1169
+ import { createOpenAI } from "@ai-sdk/openai";
1170
+ import { tool } from "ai";
1171
+
1172
+ // src/agents/constants.ts
1173
+ var AGENT_NAME_HEADER = "upstash-agent-name";
1174
+ var MANAGER_AGENT_PROMPT = `You are an agent orchestrating other AI Agents.
1175
+
1176
+ These other agents have tools available to them.
1177
+
1178
+ Given a prompt, utilize these agents to address requests.
1179
+
1180
+ 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.
1181
+
1182
+ Avoid calling the same agent twice in one turn. Instead, prefer to call it once but provide everything
1183
+ you need from that agent.
1184
+ `;
1185
+
1186
+ // src/agents/adapters.ts
1187
+ var createWorkflowOpenAI = (context, config) => {
1188
+ const { baseURL, apiKey } = config ?? {};
1189
+ return createOpenAI({
1190
+ baseURL,
1191
+ apiKey,
1192
+ compatibility: "strict",
1193
+ fetch: async (input, init) => {
1194
+ try {
1195
+ const headers = init?.headers ? Object.fromEntries(new Headers(init.headers).entries()) : {};
1196
+ const body = init?.body ? JSON.parse(init.body) : void 0;
1197
+ const agentName = headers[AGENT_NAME_HEADER];
1198
+ const stepName = agentName ? `Call Agent ${agentName}` : "Call Agent";
1199
+ const responseInfo = await context.call(stepName, {
1200
+ url: input.toString(),
1201
+ method: init?.method,
1202
+ headers,
1203
+ body
1204
+ });
1205
+ const responseHeaders = new Headers(
1206
+ Object.entries(responseInfo.header).reduce(
1207
+ (acc, [key, values]) => {
1208
+ acc[key] = values.join(", ");
1209
+ return acc;
1210
+ },
1211
+ {}
1212
+ )
1213
+ );
1214
+ return new Response(JSON.stringify(responseInfo.body), {
1215
+ status: responseInfo.status,
1216
+ headers: responseHeaders
1217
+ });
1218
+ } catch (error) {
1219
+ if (error instanceof Error && error.name === "WorkflowAbort") {
1220
+ throw error;
1221
+ } else {
1222
+ console.error("Error in fetch implementation:", error);
1223
+ throw error;
1224
+ }
1225
+ }
1226
+ }
1227
+ });
1228
+ };
1229
+ var wrapTools = ({
1230
+ context,
1231
+ tools
1232
+ }) => {
1233
+ return Object.fromEntries(
1234
+ Object.entries(tools).map((toolInfo) => {
1235
+ const [toolName, tool3] = toolInfo;
1236
+ const executeAsStep = "executeAsStep" in tool3 ? tool3.executeAsStep : true;
1237
+ const aiSDKTool = convertToAISDKTool(tool3);
1238
+ const execute = aiSDKTool.execute;
1239
+ if (execute && executeAsStep) {
1240
+ const wrappedExecute = (...params) => {
1241
+ return context.run(`Run tool ${toolName}`, () => execute(...params));
1242
+ };
1243
+ aiSDKTool.execute = wrappedExecute;
1244
+ }
1245
+ return [toolName, aiSDKTool];
1246
+ })
1247
+ );
1248
+ };
1249
+ var convertToAISDKTool = (tool3) => {
1250
+ const isLangchainTool = "invoke" in tool3;
1251
+ return isLangchainTool ? convertLangchainTool(tool3) : tool3;
1252
+ };
1253
+ var convertLangchainTool = (langchainTool) => {
1254
+ return tool({
1255
+ description: langchainTool.description,
1256
+ parameters: langchainTool.schema,
1257
+ execute: async (...param) => langchainTool.invoke(...param)
1258
+ });
1259
+ };
1260
+ var WorkflowTool = class {
1261
+ /**
1262
+ * description of the tool
1263
+ */
1264
+ description;
1265
+ /**
1266
+ * schema of the tool
1267
+ */
1268
+ schema;
1269
+ /**
1270
+ * function to invoke the tool
1271
+ */
1272
+ invoke;
1273
+ /**
1274
+ * whether the invoke method of the tool is to be wrapped with `context.run`
1275
+ */
1276
+ executeAsStep;
1277
+ /**
1278
+ *
1279
+ * @param description description of the tool
1280
+ * @param schema schema of the tool
1281
+ * @param invoke function to invoke the tool
1282
+ * @param executeAsStep whether the invoke method of the tool is to be wrapped with `context.run`
1283
+ */
1284
+ constructor(params) {
1285
+ this.description = params.description;
1286
+ this.schema = params.schema;
1287
+ this.invoke = params.invoke;
1288
+ this.executeAsStep = params.executeAsStep ?? true;
1289
+ }
1290
+ };
1291
+
1292
+ // src/context/steps.ts
1293
+ var BaseLazyStep = class {
1294
+ stepName;
1295
+ // will be set in the subclasses
1296
+ constructor(stepName) {
1297
+ if (!stepName) {
1298
+ throw new WorkflowError(
1299
+ "A workflow step name cannot be undefined or an empty string. Please provide a name for your workflow step."
1300
+ );
1301
+ }
1302
+ this.stepName = stepName;
1303
+ }
1304
+ };
1305
+ var LazyFunctionStep = class extends BaseLazyStep {
1306
+ stepFunction;
1307
+ stepType = "Run";
1308
+ constructor(stepName, stepFunction) {
1309
+ super(stepName);
1310
+ this.stepFunction = stepFunction;
1311
+ }
1312
+ getPlanStep(concurrent, targetStep) {
1313
+ return {
1314
+ stepId: 0,
1315
+ stepName: this.stepName,
1316
+ stepType: this.stepType,
1317
+ concurrent,
1318
+ targetStep
1319
+ };
1320
+ }
1321
+ async getResultStep(concurrent, stepId) {
1322
+ let result = this.stepFunction();
1323
+ if (result instanceof Promise) {
1324
+ result = await result;
1325
+ }
1326
+ return {
1327
+ stepId,
1328
+ stepName: this.stepName,
1329
+ stepType: this.stepType,
1330
+ out: result,
1331
+ concurrent
1332
+ };
1333
+ }
1334
+ };
1335
+ var LazySleepStep = class extends BaseLazyStep {
1336
+ sleep;
1337
+ stepType = "SleepFor";
1338
+ constructor(stepName, sleep) {
1339
+ super(stepName);
1340
+ this.sleep = sleep;
1341
+ }
1342
+ getPlanStep(concurrent, targetStep) {
1343
+ return {
1344
+ stepId: 0,
1345
+ stepName: this.stepName,
1346
+ stepType: this.stepType,
1347
+ sleepFor: this.sleep,
1348
+ concurrent,
1349
+ targetStep
1350
+ };
1351
+ }
1352
+ async getResultStep(concurrent, stepId) {
1353
+ return await Promise.resolve({
1354
+ stepId,
1355
+ stepName: this.stepName,
1356
+ stepType: this.stepType,
1357
+ sleepFor: this.sleep,
1358
+ concurrent
1359
+ });
1360
+ }
1361
+ };
1362
+ var LazySleepUntilStep = class extends BaseLazyStep {
1363
+ sleepUntil;
1364
+ stepType = "SleepUntil";
1365
+ constructor(stepName, sleepUntil) {
1366
+ super(stepName);
1367
+ this.sleepUntil = sleepUntil;
1368
+ }
1369
+ getPlanStep(concurrent, targetStep) {
1370
+ return {
1371
+ stepId: 0,
1372
+ stepName: this.stepName,
1373
+ stepType: this.stepType,
1374
+ sleepUntil: this.sleepUntil,
1375
+ concurrent,
1376
+ targetStep
1377
+ };
1378
+ }
1379
+ async getResultStep(concurrent, stepId) {
1380
+ return await Promise.resolve({
1381
+ stepId,
1382
+ stepName: this.stepName,
1383
+ stepType: this.stepType,
1384
+ sleepUntil: this.sleepUntil,
1385
+ concurrent
1386
+ });
1387
+ }
1388
+ };
1389
+ var LazyCallStep = class extends BaseLazyStep {
1390
+ url;
1391
+ method;
1392
+ body;
1393
+ headers;
1394
+ retries;
1395
+ timeout;
1396
+ flowControl;
1397
+ stepType = "Call";
1398
+ constructor(stepName, url, method, body, headers, retries, timeout, flowControl) {
1399
+ super(stepName);
1400
+ this.url = url;
1401
+ this.method = method;
1402
+ this.body = body;
1403
+ this.headers = headers;
1404
+ this.retries = retries;
1405
+ this.timeout = timeout;
1406
+ this.flowControl = flowControl;
1407
+ }
1408
+ getPlanStep(concurrent, targetStep) {
1409
+ return {
1410
+ stepId: 0,
1411
+ stepName: this.stepName,
1412
+ stepType: this.stepType,
1413
+ concurrent,
1414
+ targetStep
1136
1415
  };
1137
1416
  }
1138
- if (step?.waitEventId) {
1417
+ async getResultStep(concurrent, stepId) {
1418
+ return await Promise.resolve({
1419
+ stepId,
1420
+ stepName: this.stepName,
1421
+ stepType: this.stepType,
1422
+ concurrent,
1423
+ callUrl: this.url,
1424
+ callMethod: this.method,
1425
+ callBody: this.body,
1426
+ callHeaders: this.headers
1427
+ });
1428
+ }
1429
+ };
1430
+ var LazyWaitForEventStep = class extends BaseLazyStep {
1431
+ eventId;
1432
+ timeout;
1433
+ stepType = "Wait";
1434
+ constructor(stepName, eventId, timeout) {
1435
+ super(stepName);
1436
+ this.eventId = eventId;
1437
+ this.timeout = timeout;
1438
+ }
1439
+ getPlanStep(concurrent, targetStep) {
1139
1440
  return {
1140
- headers: {
1141
- ...baseHeaders,
1142
- "Upstash-Workflow-CallType": "step"
1143
- },
1144
- timeoutHeaders: {
1145
- // to include user headers:
1146
- ...Object.fromEntries(
1147
- Object.entries(baseHeaders).map(([header, value]) => [header, [value]])
1148
- ),
1149
- // to include telemetry headers:
1150
- ...telemetry ? Object.fromEntries(
1151
- Object.entries(getTelemetryHeaders(telemetry)).map(([header, value]) => [
1152
- header,
1153
- [value]
1154
- ])
1155
- ) : {},
1156
- // note: using WORKFLOW_ID_HEADER doesn't work, because Runid -> RunId:
1157
- "Upstash-Workflow-Runid": [workflowRunId],
1158
- [WORKFLOW_INIT_HEADER]: ["false"],
1159
- [WORKFLOW_URL_HEADER]: [workflowUrl],
1160
- "Upstash-Workflow-CallType": ["step"]
1161
- }
1441
+ stepId: 0,
1442
+ stepName: this.stepName,
1443
+ stepType: this.stepType,
1444
+ waitEventId: this.eventId,
1445
+ timeout: this.timeout,
1446
+ concurrent,
1447
+ targetStep
1162
1448
  };
1163
1449
  }
1164
- return { headers: baseHeaders };
1450
+ async getResultStep(concurrent, stepId) {
1451
+ return await Promise.resolve({
1452
+ stepId,
1453
+ stepName: this.stepName,
1454
+ stepType: this.stepType,
1455
+ waitEventId: this.eventId,
1456
+ timeout: this.timeout,
1457
+ concurrent
1458
+ });
1459
+ }
1165
1460
  };
1166
- var verifyRequest = async (body, signature, verifier) => {
1167
- if (!verifier) {
1168
- return;
1461
+ var LazyNotifyStep = class extends LazyFunctionStep {
1462
+ stepType = "Notify";
1463
+ constructor(stepName, eventId, eventData, requester) {
1464
+ super(stepName, async () => {
1465
+ const notifyResponse = await makeNotifyRequest(requester, eventId, eventData);
1466
+ return {
1467
+ eventId,
1468
+ eventData,
1469
+ notifyResponse
1470
+ };
1471
+ });
1169
1472
  }
1170
- try {
1171
- if (!signature) {
1172
- throw new Error("`Upstash-Signature` header is not passed.");
1173
- }
1174
- const isValid = await verifier.verify({
1473
+ };
1474
+ var LazyInvokeStep = class extends BaseLazyStep {
1475
+ stepType = "Invoke";
1476
+ params;
1477
+ constructor(stepName, {
1478
+ workflow,
1479
+ body,
1480
+ headers = {},
1481
+ workflowRunId,
1482
+ retries,
1483
+ flowControl
1484
+ }) {
1485
+ super(stepName);
1486
+ this.params = {
1487
+ workflow,
1175
1488
  body,
1176
- signature
1489
+ headers,
1490
+ workflowRunId: getWorkflowRunId(workflowRunId),
1491
+ retries,
1492
+ flowControl
1493
+ };
1494
+ }
1495
+ getPlanStep(concurrent, targetStep) {
1496
+ return {
1497
+ stepId: 0,
1498
+ stepName: this.stepName,
1499
+ stepType: this.stepType,
1500
+ concurrent,
1501
+ targetStep
1502
+ };
1503
+ }
1504
+ /**
1505
+ * won't be used as it's the server who will add the result step
1506
+ * in Invoke step.
1507
+ */
1508
+ getResultStep(concurrent, stepId) {
1509
+ return Promise.resolve({
1510
+ stepId,
1511
+ stepName: this.stepName,
1512
+ stepType: this.stepType,
1513
+ concurrent
1177
1514
  });
1178
- if (!isValid) {
1179
- throw new Error("Signature in `Upstash-Signature` header is not valid");
1180
- }
1181
- } catch (error) {
1182
- throw new WorkflowError(
1183
- `Failed to verify that the Workflow request comes from QStash: ${error}
1184
-
1185
- If signature is missing, trigger the workflow endpoint by publishing your request to QStash instead of calling it directly.
1186
-
1187
- If you want to disable QStash Verification, you should clear env variables QSTASH_CURRENT_SIGNING_KEY and QSTASH_NEXT_SIGNING_KEY`
1188
- );
1189
1515
  }
1190
1516
  };
1191
1517
 
@@ -1199,14 +1525,16 @@ var AutoExecutor = class _AutoExecutor {
1199
1525
  nonPlanStepCount;
1200
1526
  steps;
1201
1527
  indexInCurrentList = 0;
1528
+ invokeCount;
1202
1529
  telemetry;
1203
1530
  stepCount = 0;
1204
1531
  planStepCount = 0;
1205
1532
  executingStep = false;
1206
- constructor(context, steps, telemetry, debug) {
1533
+ constructor(context, steps, telemetry, invokeCount, debug) {
1207
1534
  this.context = context;
1208
1535
  this.steps = steps;
1209
1536
  this.telemetry = telemetry;
1537
+ this.invokeCount = invokeCount ?? 0;
1210
1538
  this.debug = debug;
1211
1539
  this.nonPlanStepCount = this.steps.filter((step) => !step.targetStep).length;
1212
1540
  }
@@ -1429,7 +1757,9 @@ var AutoExecutor = class _AutoExecutor {
1429
1757
  step: waitStep,
1430
1758
  failureUrl: this.context.failureUrl,
1431
1759
  retries: this.context.retries,
1432
- telemetry: this.telemetry
1760
+ telemetry: this.telemetry,
1761
+ invokeCount: this.invokeCount,
1762
+ flowControl: this.context.flowControl
1433
1763
  });
1434
1764
  const waitBody = {
1435
1765
  url: this.context.url,
@@ -1457,17 +1787,13 @@ var AutoExecutor = class _AutoExecutor {
1457
1787
  if (steps.length === 1 && lazySteps[0] instanceof LazyInvokeStep) {
1458
1788
  const invokeStep = steps[0];
1459
1789
  const lazyInvokeStep = lazySteps[0];
1460
- await lazyInvokeStep.params.workflow.callback(
1461
- {
1462
- body: lazyInvokeStep.params.body,
1463
- headers: lazyInvokeStep.params.headers,
1464
- workflowRunId: lazyInvokeStep.params.workflowRunId,
1465
- workflow: lazyInvokeStep.params.workflow,
1466
- retries: lazyInvokeStep.params.retries
1467
- },
1790
+ await invokeWorkflow({
1791
+ settings: lazyInvokeStep.params,
1468
1792
  invokeStep,
1469
- this.context
1470
- );
1793
+ context: this.context,
1794
+ invokeCount: this.invokeCount,
1795
+ telemetry: this.telemetry
1796
+ });
1471
1797
  throw new WorkflowAbort(invokeStep.stepName, invokeStep);
1472
1798
  }
1473
1799
  const result = await this.context.qstashClient.batchJSON(
@@ -1483,11 +1809,14 @@ var AutoExecutor = class _AutoExecutor {
1483
1809
  retries: this.context.retries,
1484
1810
  callRetries: lazyStep instanceof LazyCallStep ? lazyStep.retries : void 0,
1485
1811
  callTimeout: lazyStep instanceof LazyCallStep ? lazyStep.timeout : void 0,
1486
- telemetry: this.telemetry
1812
+ telemetry: this.telemetry,
1813
+ invokeCount: this.invokeCount,
1814
+ flowControl: this.context.flowControl,
1815
+ callFlowControl: lazyStep instanceof LazyCallStep ? lazyStep.flowControl : void 0
1487
1816
  });
1488
1817
  const willWait = singleStep.concurrent === NO_CONCURRENCY || singleStep.stepId === 0;
1489
1818
  singleStep.out = JSON.stringify(singleStep.out);
1490
- return singleStep.callUrl ? (
1819
+ return singleStep.callUrl && lazyStep instanceof LazyCallStep ? (
1491
1820
  // if the step is a third party call, we call the third party
1492
1821
  // url (singleStep.callUrl) and pass information about the workflow
1493
1822
  // in the headers (handled in getHeaders). QStash makes the request
@@ -1719,98 +2048,6 @@ var WorkflowApi = class extends BaseWorkflowApi {
1719
2048
  }
1720
2049
  };
1721
2050
 
1722
- // src/agents/adapters.ts
1723
- import { createOpenAI } from "@ai-sdk/openai";
1724
- import { tool } from "ai";
1725
-
1726
- // src/agents/constants.ts
1727
- var AGENT_NAME_HEADER = "upstash-agent-name";
1728
- var MANAGER_AGENT_PROMPT = `You are an agent orchestrating other AI Agents.
1729
-
1730
- These other agents have tools available to them.
1731
-
1732
- Given a prompt, utilize these agents to address requests.
1733
-
1734
- 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.
1735
-
1736
- Avoid calling the same agent twice in one turn. Instead, prefer to call it once but provide everything
1737
- you need from that agent.
1738
- `;
1739
-
1740
- // src/agents/adapters.ts
1741
- var createWorkflowOpenAI = (context, config) => {
1742
- const { baseURL, apiKey } = config ?? {};
1743
- return createOpenAI({
1744
- baseURL,
1745
- apiKey,
1746
- compatibility: "strict",
1747
- fetch: async (input, init) => {
1748
- try {
1749
- const headers = init?.headers ? Object.fromEntries(new Headers(init.headers).entries()) : {};
1750
- const body = init?.body ? JSON.parse(init.body) : void 0;
1751
- const agentName = headers[AGENT_NAME_HEADER];
1752
- const stepName = agentName ? `Call Agent ${agentName}` : "Call Agent";
1753
- const responseInfo = await context.call(stepName, {
1754
- url: input.toString(),
1755
- method: init?.method,
1756
- headers,
1757
- body
1758
- });
1759
- const responseHeaders = new Headers(
1760
- Object.entries(responseInfo.header).reduce(
1761
- (acc, [key, values]) => {
1762
- acc[key] = values.join(", ");
1763
- return acc;
1764
- },
1765
- {}
1766
- )
1767
- );
1768
- return new Response(JSON.stringify(responseInfo.body), {
1769
- status: responseInfo.status,
1770
- headers: responseHeaders
1771
- });
1772
- } catch (error) {
1773
- if (error instanceof Error && error.name === "WorkflowAbort") {
1774
- throw error;
1775
- } else {
1776
- console.error("Error in fetch implementation:", error);
1777
- throw error;
1778
- }
1779
- }
1780
- }
1781
- });
1782
- };
1783
- var wrapTools = ({
1784
- context,
1785
- tools
1786
- }) => {
1787
- return Object.fromEntries(
1788
- Object.entries(tools).map((toolInfo) => {
1789
- const [toolName, tool3] = toolInfo;
1790
- const aiSDKTool = convertToAISDKTool(tool3);
1791
- const execute = aiSDKTool.execute;
1792
- if (execute) {
1793
- const wrappedExecute = (...params) => {
1794
- return context.run(`Run tool ${toolName}`, () => execute(...params));
1795
- };
1796
- aiSDKTool.execute = wrappedExecute;
1797
- }
1798
- return [toolName, aiSDKTool];
1799
- })
1800
- );
1801
- };
1802
- var convertToAISDKTool = (tool3) => {
1803
- const isLangchainTool = "invoke" in tool3;
1804
- return isLangchainTool ? convertLangchainTool(tool3) : tool3;
1805
- };
1806
- var convertLangchainTool = (langchainTool) => {
1807
- return tool({
1808
- description: langchainTool.description,
1809
- parameters: langchainTool.schema,
1810
- execute: async (...param) => langchainTool.invoke(...param)
1811
- });
1812
- };
1813
-
1814
2051
  // src/agents/agent.ts
1815
2052
  import { z } from "zod";
1816
2053
  import { generateText, tool as tool2, ToolExecutionError } from "ai";
@@ -2143,6 +2380,11 @@ var WorkflowContext = class {
2143
2380
  * Number of retries
2144
2381
  */
2145
2382
  retries;
2383
+ /**
2384
+ * Settings for controlling the number of active requests
2385
+ * and number of requests per second with the same key.
2386
+ */
2387
+ flowControl;
2146
2388
  constructor({
2147
2389
  qstashClient,
2148
2390
  workflowRunId,
@@ -2154,7 +2396,9 @@ var WorkflowContext = class {
2154
2396
  initialPayload,
2155
2397
  env,
2156
2398
  retries,
2157
- telemetry
2399
+ telemetry,
2400
+ invokeCount,
2401
+ flowControl
2158
2402
  }) {
2159
2403
  this.qstashClient = qstashClient;
2160
2404
  this.workflowRunId = workflowRunId;
@@ -2165,7 +2409,8 @@ var WorkflowContext = class {
2165
2409
  this.requestPayload = initialPayload;
2166
2410
  this.env = env ?? {};
2167
2411
  this.retries = retries ?? DEFAULT_RETRIES;
2168
- this.executor = new AutoExecutor(this, this.steps, telemetry, debug);
2412
+ this.flowControl = flowControl;
2413
+ this.executor = new AutoExecutor(this, this.steps, telemetry, invokeCount, debug);
2169
2414
  }
2170
2415
  /**
2171
2416
  * Executes a workflow step
@@ -2267,7 +2512,7 @@ var WorkflowContext = class {
2267
2512
  * }
2268
2513
  */
2269
2514
  async call(stepName, settings) {
2270
- const { url, method = "GET", body, headers = {}, retries = 0, timeout } = settings;
2515
+ const { url, method = "GET", body, headers = {}, retries = 0, timeout, flowControl } = settings;
2271
2516
  const result = await this.addStep(
2272
2517
  new LazyCallStep(
2273
2518
  stepName,
@@ -2276,7 +2521,8 @@ var WorkflowContext = class {
2276
2521
  body,
2277
2522
  headers,
2278
2523
  retries,
2279
- timeout
2524
+ timeout,
2525
+ flowControl
2280
2526
  )
2281
2527
  );
2282
2528
  if (typeof result === "string") {
@@ -2513,7 +2759,8 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
2513
2759
  failureUrl: context.failureUrl,
2514
2760
  initialPayload: context.requestPayload,
2515
2761
  env: context.env,
2516
- retries: context.retries
2762
+ retries: context.retries,
2763
+ flowControl: context.flowControl
2517
2764
  });
2518
2765
  try {
2519
2766
  await routeFunction(disabledContext);
@@ -2666,7 +2913,7 @@ var parseRequest = async (requestPayload, isFirstInvocation, workflowRunId, requ
2666
2913
  };
2667
2914
  }
2668
2915
  };
2669
- var handleFailure = async (request, requestPayload, qstashClient, initialPayloadParser, routeFunction, failureFunction, env, retries, debug) => {
2916
+ var handleFailure = async (request, requestPayload, qstashClient, initialPayloadParser, routeFunction, failureFunction, env, retries, flowControl, debug) => {
2670
2917
  if (request.headers.get(WORKFLOW_FAILURE_HEADER) !== "true") {
2671
2918
  return ok("not-failure-callback");
2672
2919
  }
@@ -2678,22 +2925,21 @@ var handleFailure = async (request, requestPayload, qstashClient, initialPayload
2678
2925
  );
2679
2926
  }
2680
2927
  try {
2681
- const { status, header, body, url, sourceHeader, sourceBody, workflowRunId } = JSON.parse(
2682
- requestPayload
2683
- );
2928
+ const { status, header, body, url, sourceBody, workflowRunId } = JSON.parse(requestPayload);
2684
2929
  const decodedBody = body ? decodeBase64(body) : "{}";
2685
2930
  const errorPayload = JSON.parse(decodedBody);
2686
2931
  const workflowContext = new WorkflowContext({
2687
2932
  qstashClient,
2688
2933
  workflowRunId,
2689
2934
  initialPayload: sourceBody ? initialPayloadParser(decodeBase64(sourceBody)) : void 0,
2690
- headers: recreateUserHeaders(new Headers(sourceHeader)),
2935
+ headers: recreateUserHeaders(request.headers),
2691
2936
  steps: [],
2692
2937
  url,
2693
2938
  failureUrl: url,
2694
2939
  debug,
2695
2940
  env,
2696
2941
  retries,
2942
+ flowControl,
2697
2943
  telemetry: void 0
2698
2944
  // not going to make requests in authentication check
2699
2945
  });
@@ -2820,7 +3066,8 @@ var serveBase = (routeFunction, telemetry, options) => {
2820
3066
  env,
2821
3067
  retries,
2822
3068
  useJSONContent,
2823
- disableTelemetry
3069
+ disableTelemetry,
3070
+ flowControl
2824
3071
  } = processOptions(options);
2825
3072
  telemetry = disableTelemetry ? void 0 : telemetry;
2826
3073
  const debug = WorkflowLogger.getLogger(verbose);
@@ -2861,6 +3108,7 @@ var serveBase = (routeFunction, telemetry, options) => {
2861
3108
  failureFunction,
2862
3109
  env,
2863
3110
  retries,
3111
+ flowControl,
2864
3112
  debug
2865
3113
  );
2866
3114
  if (failureCheck.isErr()) {
@@ -2869,6 +3117,7 @@ var serveBase = (routeFunction, telemetry, options) => {
2869
3117
  await debug?.log("WARN", "RESPONSE_DEFAULT", "failureFunction executed");
2870
3118
  return onStepFinish(workflowRunId, "failure-callback");
2871
3119
  }
3120
+ const invokeCount = Number(request.headers.get(WORKFLOW_INVOKE_COUNT_HEADER) ?? "0");
2872
3121
  const workflowContext = new WorkflowContext({
2873
3122
  qstashClient,
2874
3123
  workflowRunId,
@@ -2880,7 +3129,9 @@ var serveBase = (routeFunction, telemetry, options) => {
2880
3129
  debug,
2881
3130
  env,
2882
3131
  retries,
2883
- telemetry
3132
+ telemetry,
3133
+ invokeCount,
3134
+ flowControl
2884
3135
  });
2885
3136
  const authCheck = await DisabledWorkflowContext.tryAuthentication(
2886
3137
  routeFunction,
@@ -2903,6 +3154,7 @@ var serveBase = (routeFunction, telemetry, options) => {
2903
3154
  workflowUrl,
2904
3155
  failureUrl: workflowFailureUrl,
2905
3156
  retries,
3157
+ flowControl,
2906
3158
  telemetry,
2907
3159
  debug
2908
3160
  });
@@ -2912,7 +3164,13 @@ var serveBase = (routeFunction, telemetry, options) => {
2912
3164
  });
2913
3165
  throw callReturnCheck.error;
2914
3166
  } else if (callReturnCheck.value === "continue-workflow") {
2915
- const result = isFirstInvocation ? await triggerFirstInvocation({ workflowContext, useJSONContent, telemetry, debug }) : await triggerRouteFunction({
3167
+ const result = isFirstInvocation ? await triggerFirstInvocation({
3168
+ workflowContext,
3169
+ useJSONContent,
3170
+ telemetry,
3171
+ debug,
3172
+ invokeCount
3173
+ }) : await triggerRouteFunction({
2916
3174
  onStep: async () => routeFunction(workflowContext),
2917
3175
  onCleanup: async (result2) => {
2918
3176
  await triggerWorkflowDelete(workflowContext, result2, debug);
@@ -2969,7 +3227,8 @@ export {
2969
3227
  getWorkflowRunId,
2970
3228
  StepTypes,
2971
3229
  triggerFirstInvocation,
2972
- getHeaders,
3230
+ serveManyBase,
3231
+ WorkflowTool,
2973
3232
  WorkflowContext,
2974
3233
  WorkflowLogger,
2975
3234
  serveBase,