@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.
- package/astro.d.mts +4 -4
- package/astro.d.ts +4 -4
- package/astro.js +282 -135
- package/astro.mjs +17 -15
- package/{chunk-IWAW7GIG.mjs → chunk-IPXJZU3K.mjs} +851 -592
- package/cloudflare.d.mts +4 -4
- package/cloudflare.d.ts +4 -4
- package/cloudflare.js +278 -135
- package/cloudflare.mjs +13 -15
- package/express.d.mts +4 -4
- package/express.d.ts +4 -4
- package/express.js +281 -144
- package/express.mjs +16 -22
- package/h3.d.mts +4 -4
- package/h3.d.ts +4 -4
- package/h3.js +275 -135
- package/h3.mjs +10 -15
- package/hono.d.mts +4 -4
- package/hono.d.ts +4 -4
- package/hono.js +277 -134
- package/hono.mjs +12 -14
- package/index.d.mts +268 -5
- package/index.d.ts +268 -5
- package/index.js +297 -43
- package/index.mjs +60 -3
- package/nextjs.d.mts +6 -6
- package/nextjs.d.ts +6 -6
- package/nextjs.js +286 -143
- package/nextjs.mjs +21 -23
- package/package.json +1 -1
- package/serve-many-BVDpPsF-.d.mts +13 -0
- package/serve-many-e4zufyXN.d.ts +13 -0
- package/solidjs.d.mts +1 -1
- package/solidjs.d.ts +1 -1
- package/solidjs.js +207 -41
- package/solidjs.mjs +1 -1
- package/svelte.d.mts +8 -9
- package/svelte.d.ts +8 -9
- package/svelte.js +278 -135
- package/svelte.mjs +13 -15
- package/{types-C7Y7WUQd.d.mts → types-CYhDXnf8.d.mts} +110 -18
- package/{types-C7Y7WUQd.d.ts → types-CYhDXnf8.d.ts} +110 -18
- package/chunk-LCZMBGEM.mjs +0 -95
- package/serve-many-BlBvXfBS.d.mts +0 -10
- package/serve-many-Dw-UUnH6.d.ts +0 -10
|
@@ -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
|
-
//
|
|
189
|
-
var
|
|
190
|
-
|
|
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
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
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
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
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
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
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
|
-
|
|
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
|
-
|
|
239
|
-
|
|
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
|
-
|
|
249
|
-
|
|
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
|
-
|
|
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
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
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
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
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
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
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
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
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
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
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
|
-
|
|
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
|
|
1167
|
-
|
|
1168
|
-
|
|
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
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
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
|
-
|
|
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
|
|
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.
|
|
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,
|
|
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(
|
|
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({
|
|
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
|
-
|
|
3230
|
+
serveManyBase,
|
|
3231
|
+
WorkflowTool,
|
|
2973
3232
|
WorkflowContext,
|
|
2974
3233
|
WorkflowLogger,
|
|
2975
3234
|
serveBase,
|