@upstash/workflow 0.2.12 → 0.2.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/astro.d.mts +2 -2
- package/astro.d.ts +2 -2
- package/astro.js +1205 -1036
- package/astro.mjs +1 -1
- package/{chunk-4GTHIL7S.mjs → chunk-XVNSBBDC.mjs} +870 -699
- package/cloudflare.d.mts +2 -2
- package/cloudflare.d.ts +2 -2
- package/cloudflare.js +1205 -1036
- package/cloudflare.mjs +1 -1
- package/express.d.mts +2 -2
- package/express.d.ts +2 -2
- package/express.js +1221 -1052
- package/express.mjs +1 -1
- package/h3.d.mts +2 -2
- package/h3.d.ts +2 -2
- package/h3.js +1205 -1036
- package/h3.mjs +1 -1
- package/hono.d.mts +2 -2
- package/hono.d.ts +2 -2
- package/hono.js +1206 -1037
- package/hono.mjs +2 -2
- package/index.d.mts +10 -4
- package/index.d.ts +10 -4
- package/index.js +1184 -1008
- package/index.mjs +10 -3
- package/nextjs.d.mts +2 -2
- package/nextjs.d.ts +2 -2
- package/nextjs.js +1205 -1036
- package/nextjs.mjs +1 -1
- package/package.json +1 -1
- package/{serve-many-DLguU9iR.d.mts → serve-many-BF71QZHQ.d.mts} +1 -1
- package/{serve-many-BdMq5rFX.d.ts → serve-many-BMlN2PAB.d.ts} +1 -1
- package/solidjs.d.mts +1 -1
- package/solidjs.d.ts +1 -1
- package/solidjs.js +1173 -1004
- package/solidjs.mjs +1 -1
- package/svelte.d.mts +2 -2
- package/svelte.d.ts +2 -2
- package/svelte.js +1205 -1036
- package/svelte.mjs +1 -1
- package/{types-D1W0VOpy.d.ts → types-C1WIgVLA.d.mts} +58 -45
- package/{types-D1W0VOpy.d.mts → types-C1WIgVLA.d.ts} +58 -45
|
@@ -42,11 +42,12 @@ var WORKFLOW_PROTOCOL_VERSION_HEADER = "Upstash-Workflow-Sdk-Version";
|
|
|
42
42
|
var DEFAULT_CONTENT_TYPE = "application/json";
|
|
43
43
|
var NO_CONCURRENCY = 1;
|
|
44
44
|
var DEFAULT_RETRIES = 3;
|
|
45
|
-
var VERSION = "v0.2.
|
|
45
|
+
var VERSION = "v0.2.13";
|
|
46
46
|
var SDK_TELEMETRY = `@upstash/workflow@${VERSION}`;
|
|
47
47
|
var TELEMETRY_HEADER_SDK = "Upstash-Telemetry-Sdk";
|
|
48
48
|
var TELEMETRY_HEADER_FRAMEWORK = "Upstash-Telemetry-Framework";
|
|
49
49
|
var TELEMETRY_HEADER_RUNTIME = "Upstash-Telemetry-Runtime";
|
|
50
|
+
var TELEMETRY_HEADER_AGENT = "Upstash-Telemetry-Agent";
|
|
50
51
|
|
|
51
52
|
// src/error.ts
|
|
52
53
|
import { QstashError } from "@upstash/qstash";
|
|
@@ -101,6 +102,271 @@ var StepTypes = [
|
|
|
101
102
|
"Invoke"
|
|
102
103
|
];
|
|
103
104
|
|
|
105
|
+
// src/agents/adapters.ts
|
|
106
|
+
import { tool } from "ai";
|
|
107
|
+
|
|
108
|
+
// src/agents/constants.ts
|
|
109
|
+
var AGENT_NAME_HEADER = "upstash-agent-name";
|
|
110
|
+
var MANAGER_AGENT_PROMPT = `You are an agent orchestrating other AI Agents.
|
|
111
|
+
|
|
112
|
+
These other agents have tools available to them.
|
|
113
|
+
|
|
114
|
+
Given a prompt, utilize these agents to address requests.
|
|
115
|
+
|
|
116
|
+
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.
|
|
117
|
+
|
|
118
|
+
Avoid calling the same agent twice in one turn. Instead, prefer to call it once but provide everything
|
|
119
|
+
you need from that agent.
|
|
120
|
+
`;
|
|
121
|
+
|
|
122
|
+
// src/agents/adapters.ts
|
|
123
|
+
var fetchWithContextCall = async (context, agentCallParams, ...params) => {
|
|
124
|
+
const [input, init] = params;
|
|
125
|
+
try {
|
|
126
|
+
const headers = init?.headers ? Object.fromEntries(new Headers(init.headers).entries()) : {};
|
|
127
|
+
const body = init?.body ? JSON.parse(init.body) : void 0;
|
|
128
|
+
const agentName = headers[AGENT_NAME_HEADER];
|
|
129
|
+
const stepName = agentName ? `Call Agent ${agentName}` : "Call Agent";
|
|
130
|
+
const responseInfo = await context.call(stepName, {
|
|
131
|
+
url: input.toString(),
|
|
132
|
+
method: init?.method,
|
|
133
|
+
headers,
|
|
134
|
+
body,
|
|
135
|
+
timeout: agentCallParams?.timeout,
|
|
136
|
+
retries: agentCallParams?.retries,
|
|
137
|
+
flowControl: agentCallParams?.flowControl
|
|
138
|
+
});
|
|
139
|
+
const responseHeaders = new Headers(
|
|
140
|
+
Object.entries(responseInfo.header).reduce(
|
|
141
|
+
(acc, [key, values]) => {
|
|
142
|
+
acc[key] = values.join(", ");
|
|
143
|
+
return acc;
|
|
144
|
+
},
|
|
145
|
+
{}
|
|
146
|
+
)
|
|
147
|
+
);
|
|
148
|
+
return new Response(JSON.stringify(responseInfo.body), {
|
|
149
|
+
status: responseInfo.status,
|
|
150
|
+
headers: responseHeaders
|
|
151
|
+
});
|
|
152
|
+
} catch (error) {
|
|
153
|
+
if (error instanceof Error && error.name === "WorkflowAbort") {
|
|
154
|
+
throw error;
|
|
155
|
+
} else {
|
|
156
|
+
console.error("Error in fetch implementation:", error);
|
|
157
|
+
throw error;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
var createWorkflowModel = ({
|
|
162
|
+
context,
|
|
163
|
+
provider,
|
|
164
|
+
providerParams,
|
|
165
|
+
agentCallParams
|
|
166
|
+
}) => {
|
|
167
|
+
return provider({
|
|
168
|
+
fetch: (...params) => fetchWithContextCall(context, agentCallParams, ...params),
|
|
169
|
+
...providerParams
|
|
170
|
+
});
|
|
171
|
+
};
|
|
172
|
+
var wrapTools = ({
|
|
173
|
+
context,
|
|
174
|
+
tools
|
|
175
|
+
}) => {
|
|
176
|
+
return Object.fromEntries(
|
|
177
|
+
Object.entries(tools).map((toolInfo) => {
|
|
178
|
+
const [toolName, tool3] = toolInfo;
|
|
179
|
+
const executeAsStep = "executeAsStep" in tool3 ? tool3.executeAsStep : true;
|
|
180
|
+
const aiSDKTool = convertToAISDKTool(tool3);
|
|
181
|
+
const execute = aiSDKTool.execute;
|
|
182
|
+
if (execute && executeAsStep) {
|
|
183
|
+
const wrappedExecute = (...params) => {
|
|
184
|
+
return context.run(`Run tool ${toolName}`, () => execute(...params));
|
|
185
|
+
};
|
|
186
|
+
aiSDKTool.execute = wrappedExecute;
|
|
187
|
+
}
|
|
188
|
+
return [toolName, aiSDKTool];
|
|
189
|
+
})
|
|
190
|
+
);
|
|
191
|
+
};
|
|
192
|
+
var convertToAISDKTool = (tool3) => {
|
|
193
|
+
const isLangchainTool = "invoke" in tool3;
|
|
194
|
+
return isLangchainTool ? convertLangchainTool(tool3) : tool3;
|
|
195
|
+
};
|
|
196
|
+
var convertLangchainTool = (langchainTool) => {
|
|
197
|
+
return tool({
|
|
198
|
+
description: langchainTool.description,
|
|
199
|
+
parameters: langchainTool.schema,
|
|
200
|
+
execute: async (...param) => langchainTool.invoke(...param)
|
|
201
|
+
});
|
|
202
|
+
};
|
|
203
|
+
var WorkflowTool = class {
|
|
204
|
+
/**
|
|
205
|
+
* description of the tool
|
|
206
|
+
*/
|
|
207
|
+
description;
|
|
208
|
+
/**
|
|
209
|
+
* schema of the tool
|
|
210
|
+
*/
|
|
211
|
+
schema;
|
|
212
|
+
/**
|
|
213
|
+
* function to invoke the tool
|
|
214
|
+
*/
|
|
215
|
+
invoke;
|
|
216
|
+
/**
|
|
217
|
+
* whether the invoke method of the tool is to be wrapped with `context.run`
|
|
218
|
+
*/
|
|
219
|
+
executeAsStep;
|
|
220
|
+
/**
|
|
221
|
+
*
|
|
222
|
+
* @param description description of the tool
|
|
223
|
+
* @param schema schema of the tool
|
|
224
|
+
* @param invoke function to invoke the tool
|
|
225
|
+
* @param executeAsStep whether the invoke method of the tool is to be wrapped with `context.run`
|
|
226
|
+
*/
|
|
227
|
+
constructor(params) {
|
|
228
|
+
this.description = params.description;
|
|
229
|
+
this.schema = params.schema;
|
|
230
|
+
this.invoke = params.invoke;
|
|
231
|
+
this.executeAsStep = params.executeAsStep ?? true;
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
// src/serve/serve-many.ts
|
|
236
|
+
var getWorkflowId = (url) => {
|
|
237
|
+
const components = url.split("/");
|
|
238
|
+
const lastComponent = components[components.length - 1];
|
|
239
|
+
return lastComponent.split("?")[0];
|
|
240
|
+
};
|
|
241
|
+
var serveManyBase = ({
|
|
242
|
+
workflows,
|
|
243
|
+
getUrl,
|
|
244
|
+
serveMethod,
|
|
245
|
+
options
|
|
246
|
+
}) => {
|
|
247
|
+
const workflowIds = [];
|
|
248
|
+
const workflowMap = Object.fromEntries(
|
|
249
|
+
Object.entries(workflows).map((workflow) => {
|
|
250
|
+
const workflowId = workflow[0];
|
|
251
|
+
if (workflowIds.includes(workflowId)) {
|
|
252
|
+
throw new WorkflowError(
|
|
253
|
+
`Duplicate workflow name found: '${workflowId}'. Please set different workflow names in serveMany.`
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
if (workflowId.includes("/")) {
|
|
257
|
+
throw new WorkflowError(
|
|
258
|
+
`Invalid workflow name found: '${workflowId}'. Workflow name cannot contain '/'.`
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
workflowIds.push(workflowId);
|
|
262
|
+
workflow[1].workflowId = workflowId;
|
|
263
|
+
workflow[1].options = {
|
|
264
|
+
...options,
|
|
265
|
+
...workflow[1].options
|
|
266
|
+
};
|
|
267
|
+
const params = [workflow[1].routeFunction, workflow[1].options];
|
|
268
|
+
const handler = serveMethod(...params);
|
|
269
|
+
return [workflowId, handler];
|
|
270
|
+
})
|
|
271
|
+
);
|
|
272
|
+
return {
|
|
273
|
+
handler: async (...params) => {
|
|
274
|
+
const url = getUrl(...params);
|
|
275
|
+
const pickedWorkflowId = getWorkflowId(url);
|
|
276
|
+
if (!pickedWorkflowId) {
|
|
277
|
+
return new Response(
|
|
278
|
+
`Unexpected request in serveMany. workflowId not set. Please update the URL of your request.`,
|
|
279
|
+
{
|
|
280
|
+
status: 404
|
|
281
|
+
}
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
const workflow = workflowMap[pickedWorkflowId];
|
|
285
|
+
if (!workflow) {
|
|
286
|
+
return new Response(
|
|
287
|
+
`No workflows in serveMany found for '${pickedWorkflowId}'. Please update the URL of your request.`,
|
|
288
|
+
{
|
|
289
|
+
status: 404
|
|
290
|
+
}
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
return await workflow(...params);
|
|
294
|
+
}
|
|
295
|
+
};
|
|
296
|
+
};
|
|
297
|
+
var getNewUrlFromWorkflowId = (url, workflowId) => {
|
|
298
|
+
if (!workflowId) {
|
|
299
|
+
throw new WorkflowError("You can only call workflow which has a workflowId");
|
|
300
|
+
}
|
|
301
|
+
return url.replace(/[^/]+$/, workflowId);
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
// src/context/auto-executor.ts
|
|
305
|
+
import { QstashError as QstashError5 } from "@upstash/qstash";
|
|
306
|
+
|
|
307
|
+
// src/qstash/headers.ts
|
|
308
|
+
import { QstashError as QstashError4 } from "@upstash/qstash";
|
|
309
|
+
|
|
310
|
+
// src/client/utils.ts
|
|
311
|
+
import { QstashError as QstashError2 } from "@upstash/qstash";
|
|
312
|
+
var makeNotifyRequest = async (requester, eventId, eventData) => {
|
|
313
|
+
const result = await requester.request({
|
|
314
|
+
path: ["v2", "notify", eventId],
|
|
315
|
+
method: "POST",
|
|
316
|
+
body: typeof eventData === "string" ? eventData : JSON.stringify(eventData)
|
|
317
|
+
});
|
|
318
|
+
return result;
|
|
319
|
+
};
|
|
320
|
+
var makeGetWaitersRequest = async (requester, eventId) => {
|
|
321
|
+
const result = await requester.request({
|
|
322
|
+
path: ["v2", "waiters", eventId],
|
|
323
|
+
method: "GET"
|
|
324
|
+
});
|
|
325
|
+
return result;
|
|
326
|
+
};
|
|
327
|
+
var makeCancelRequest = async (requester, workflowRunId) => {
|
|
328
|
+
await requester.request({
|
|
329
|
+
path: ["v2", "workflows", "runs", `${workflowRunId}?cancel=true`],
|
|
330
|
+
method: "DELETE",
|
|
331
|
+
parseResponseAsJson: false
|
|
332
|
+
});
|
|
333
|
+
return true;
|
|
334
|
+
};
|
|
335
|
+
var getSteps = async (requester, workflowRunId, messageId, debug) => {
|
|
336
|
+
try {
|
|
337
|
+
const steps = await requester.request({
|
|
338
|
+
path: ["v2", "workflows", "runs", workflowRunId],
|
|
339
|
+
parseResponseAsJson: true
|
|
340
|
+
});
|
|
341
|
+
if (!messageId) {
|
|
342
|
+
await debug?.log("INFO", "ENDPOINT_START", {
|
|
343
|
+
message: `Pulled ${steps.length} steps from QStashand returned them without filtering with messageId.`
|
|
344
|
+
});
|
|
345
|
+
return { steps, workflowRunEnded: false };
|
|
346
|
+
} else {
|
|
347
|
+
const index = steps.findIndex((item) => item.messageId === messageId);
|
|
348
|
+
if (index === -1) {
|
|
349
|
+
return { steps: [], workflowRunEnded: false };
|
|
350
|
+
}
|
|
351
|
+
const filteredSteps = steps.slice(0, index + 1);
|
|
352
|
+
await debug?.log("INFO", "ENDPOINT_START", {
|
|
353
|
+
message: `Pulled ${steps.length} steps from QStash and filtered them to ${filteredSteps.length} using messageId.`
|
|
354
|
+
});
|
|
355
|
+
return { steps: filteredSteps, workflowRunEnded: false };
|
|
356
|
+
}
|
|
357
|
+
} catch (error) {
|
|
358
|
+
if (error instanceof QstashError2 && error.status === 404) {
|
|
359
|
+
await debug?.log("WARN", "ENDPOINT_START", {
|
|
360
|
+
message: "Couldn't fetch workflow run steps. This can happen if the workflow run succesfully ends before some callback is executed.",
|
|
361
|
+
error
|
|
362
|
+
});
|
|
363
|
+
return { steps: void 0, workflowRunEnded: true };
|
|
364
|
+
} else {
|
|
365
|
+
throw error;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
};
|
|
369
|
+
|
|
104
370
|
// src/utils.ts
|
|
105
371
|
var NANOID_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
|
|
106
372
|
var NANOID_LENGTH = 21;
|
|
@@ -543,85 +809,27 @@ var fromThrowable = Result.fromThrowable;
|
|
|
543
809
|
|
|
544
810
|
// src/workflow-requests.ts
|
|
545
811
|
import { QstashError as QstashError3 } from "@upstash/qstash";
|
|
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)
|
|
554
|
-
});
|
|
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
812
|
var triggerFirstInvocation = async ({
|
|
609
813
|
workflowContext,
|
|
610
814
|
useJSONContent,
|
|
611
815
|
telemetry,
|
|
612
816
|
debug,
|
|
613
|
-
invokeCount
|
|
817
|
+
invokeCount,
|
|
818
|
+
delay
|
|
614
819
|
}) => {
|
|
615
820
|
const { headers } = getHeaders({
|
|
616
821
|
initHeaderValue: "true",
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
822
|
+
workflowConfig: {
|
|
823
|
+
workflowRunId: workflowContext.workflowRunId,
|
|
824
|
+
workflowUrl: workflowContext.url,
|
|
825
|
+
failureUrl: workflowContext.failureUrl,
|
|
826
|
+
retries: workflowContext.retries,
|
|
827
|
+
telemetry,
|
|
828
|
+
flowControl: workflowContext.flowControl,
|
|
829
|
+
useJSONContent: useJSONContent ?? false
|
|
830
|
+
},
|
|
831
|
+
invokeCount: invokeCount ?? 0,
|
|
832
|
+
userHeaders: workflowContext.headers
|
|
625
833
|
});
|
|
626
834
|
if (workflowContext.headers.get("content-type")) {
|
|
627
835
|
headers["content-type"] = workflowContext.headers.get("content-type");
|
|
@@ -635,7 +843,8 @@ var triggerFirstInvocation = async ({
|
|
|
635
843
|
headers,
|
|
636
844
|
method: "POST",
|
|
637
845
|
body,
|
|
638
|
-
url: workflowContext.url
|
|
846
|
+
url: workflowContext.url,
|
|
847
|
+
delay
|
|
639
848
|
});
|
|
640
849
|
if (result.deduplicated) {
|
|
641
850
|
await debug?.log("WARN", "SUBMIT_FIRST_INVOCATION", {
|
|
@@ -791,14 +1000,16 @@ ${atob(callbackMessage.body ?? "")}`
|
|
|
791
1000
|
const userHeaders = recreateUserHeaders(request.headers);
|
|
792
1001
|
const { headers: requestHeaders } = getHeaders({
|
|
793
1002
|
initHeaderValue: "false",
|
|
794
|
-
|
|
795
|
-
|
|
1003
|
+
workflowConfig: {
|
|
1004
|
+
workflowRunId,
|
|
1005
|
+
workflowUrl,
|
|
1006
|
+
failureUrl,
|
|
1007
|
+
retries,
|
|
1008
|
+
telemetry,
|
|
1009
|
+
flowControl
|
|
1010
|
+
},
|
|
796
1011
|
userHeaders,
|
|
797
|
-
|
|
798
|
-
retries,
|
|
799
|
-
telemetry,
|
|
800
|
-
invokeCount: Number(invokeCount),
|
|
801
|
-
flowControl
|
|
1012
|
+
invokeCount: Number(invokeCount)
|
|
802
1013
|
});
|
|
803
1014
|
const callResponse = {
|
|
804
1015
|
status: callbackMessage.status,
|
|
@@ -844,154 +1055,6 @@ var getTelemetryHeaders = (telemetry) => {
|
|
|
844
1055
|
[TELEMETRY_HEADER_RUNTIME]: telemetry.runtime ?? "unknown"
|
|
845
1056
|
};
|
|
846
1057
|
};
|
|
847
|
-
var getHeaders = ({
|
|
848
|
-
initHeaderValue,
|
|
849
|
-
workflowRunId,
|
|
850
|
-
workflowUrl,
|
|
851
|
-
userHeaders,
|
|
852
|
-
failureUrl,
|
|
853
|
-
retries,
|
|
854
|
-
step,
|
|
855
|
-
callRetries,
|
|
856
|
-
callTimeout,
|
|
857
|
-
telemetry,
|
|
858
|
-
invokeCount,
|
|
859
|
-
flowControl,
|
|
860
|
-
callFlowControl
|
|
861
|
-
}) => {
|
|
862
|
-
const callHeaders = new Headers(step?.callHeaders);
|
|
863
|
-
const contentType = (callHeaders.get("content-type") ? callHeaders.get("content-type") : userHeaders?.get("Content-Type") ? userHeaders.get("Content-Type") : void 0) ?? DEFAULT_CONTENT_TYPE;
|
|
864
|
-
const baseHeaders = {
|
|
865
|
-
[WORKFLOW_INIT_HEADER]: initHeaderValue,
|
|
866
|
-
[WORKFLOW_ID_HEADER]: workflowRunId,
|
|
867
|
-
[WORKFLOW_URL_HEADER]: workflowUrl,
|
|
868
|
-
[WORKFLOW_FEATURE_HEADER]: "LazyFetch,InitialBody",
|
|
869
|
-
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION,
|
|
870
|
-
"content-type": contentType,
|
|
871
|
-
...telemetry ? getTelemetryHeaders(telemetry) : {}
|
|
872
|
-
};
|
|
873
|
-
if (invokeCount !== void 0 && !step?.callUrl) {
|
|
874
|
-
baseHeaders[`Upstash-Forward-${WORKFLOW_INVOKE_COUNT_HEADER}`] = invokeCount.toString();
|
|
875
|
-
}
|
|
876
|
-
if (!step?.callUrl) {
|
|
877
|
-
baseHeaders[`Upstash-Forward-${WORKFLOW_PROTOCOL_VERSION_HEADER}`] = WORKFLOW_PROTOCOL_VERSION;
|
|
878
|
-
}
|
|
879
|
-
if (callTimeout) {
|
|
880
|
-
baseHeaders[`Upstash-Timeout`] = callTimeout.toString();
|
|
881
|
-
}
|
|
882
|
-
if (failureUrl) {
|
|
883
|
-
baseHeaders[`Upstash-Failure-Callback-Forward-${WORKFLOW_FAILURE_HEADER}`] = "true";
|
|
884
|
-
baseHeaders[`Upstash-Failure-Callback-Forward-Upstash-Workflow-Failure-Callback`] = "true";
|
|
885
|
-
baseHeaders["Upstash-Failure-Callback-Workflow-Runid"] = workflowRunId;
|
|
886
|
-
baseHeaders["Upstash-Failure-Callback-Workflow-Init"] = "false";
|
|
887
|
-
baseHeaders["Upstash-Failure-Callback-Workflow-Url"] = workflowUrl;
|
|
888
|
-
baseHeaders["Upstash-Failure-Callback-Workflow-Calltype"] = "failureCall";
|
|
889
|
-
if (retries !== void 0) {
|
|
890
|
-
baseHeaders["Upstash-Failure-Callback-Retries"] = retries.toString();
|
|
891
|
-
}
|
|
892
|
-
if (flowControl) {
|
|
893
|
-
const { flowControlKey, flowControlValue } = prepareFlowControl(flowControl);
|
|
894
|
-
baseHeaders["Upstash-Failure-Callback-Flow-Control-Key"] = flowControlKey;
|
|
895
|
-
baseHeaders["Upstash-Failure-Callback-Flow-Control-Value"] = flowControlValue;
|
|
896
|
-
}
|
|
897
|
-
if (!step?.callUrl) {
|
|
898
|
-
baseHeaders["Upstash-Failure-Callback"] = failureUrl;
|
|
899
|
-
}
|
|
900
|
-
}
|
|
901
|
-
if (step?.callUrl) {
|
|
902
|
-
baseHeaders["Upstash-Retries"] = callRetries?.toString() ?? "0";
|
|
903
|
-
baseHeaders[WORKFLOW_FEATURE_HEADER] = "WF_NoDelete,InitialBody";
|
|
904
|
-
if (retries !== void 0) {
|
|
905
|
-
baseHeaders["Upstash-Callback-Retries"] = retries.toString();
|
|
906
|
-
baseHeaders["Upstash-Failure-Callback-Retries"] = retries.toString();
|
|
907
|
-
}
|
|
908
|
-
if (callFlowControl) {
|
|
909
|
-
const { flowControlKey, flowControlValue } = prepareFlowControl(callFlowControl);
|
|
910
|
-
baseHeaders["Upstash-Flow-Control-Key"] = flowControlKey;
|
|
911
|
-
baseHeaders["Upstash-Flow-Control-Value"] = flowControlValue;
|
|
912
|
-
}
|
|
913
|
-
if (flowControl) {
|
|
914
|
-
const { flowControlKey, flowControlValue } = prepareFlowControl(flowControl);
|
|
915
|
-
baseHeaders["Upstash-Callback-Flow-Control-Key"] = flowControlKey;
|
|
916
|
-
baseHeaders["Upstash-Callback-Flow-Control-Value"] = flowControlValue;
|
|
917
|
-
}
|
|
918
|
-
} else {
|
|
919
|
-
if (flowControl) {
|
|
920
|
-
const { flowControlKey, flowControlValue } = prepareFlowControl(flowControl);
|
|
921
|
-
baseHeaders["Upstash-Flow-Control-Key"] = flowControlKey;
|
|
922
|
-
baseHeaders["Upstash-Flow-Control-Value"] = flowControlValue;
|
|
923
|
-
}
|
|
924
|
-
if (retries !== void 0) {
|
|
925
|
-
baseHeaders["Upstash-Retries"] = retries.toString();
|
|
926
|
-
baseHeaders["Upstash-Failure-Callback-Retries"] = retries.toString();
|
|
927
|
-
}
|
|
928
|
-
}
|
|
929
|
-
if (userHeaders) {
|
|
930
|
-
for (const header of userHeaders.keys()) {
|
|
931
|
-
if (step?.callHeaders) {
|
|
932
|
-
baseHeaders[`Upstash-Callback-Forward-${header}`] = userHeaders.get(header);
|
|
933
|
-
} else {
|
|
934
|
-
baseHeaders[`Upstash-Forward-${header}`] = userHeaders.get(header);
|
|
935
|
-
}
|
|
936
|
-
baseHeaders[`Upstash-Failure-Callback-Forward-${header}`] = userHeaders.get(header);
|
|
937
|
-
}
|
|
938
|
-
}
|
|
939
|
-
if (step?.callHeaders) {
|
|
940
|
-
const forwardedHeaders = Object.fromEntries(
|
|
941
|
-
Object.entries(step.callHeaders).map(([header, value]) => [
|
|
942
|
-
`Upstash-Forward-${header}`,
|
|
943
|
-
value
|
|
944
|
-
])
|
|
945
|
-
);
|
|
946
|
-
return {
|
|
947
|
-
headers: {
|
|
948
|
-
...baseHeaders,
|
|
949
|
-
...forwardedHeaders,
|
|
950
|
-
"Upstash-Callback": workflowUrl,
|
|
951
|
-
"Upstash-Callback-Workflow-RunId": workflowRunId,
|
|
952
|
-
"Upstash-Callback-Workflow-CallType": "fromCallback",
|
|
953
|
-
"Upstash-Callback-Workflow-Init": "false",
|
|
954
|
-
"Upstash-Callback-Workflow-Url": workflowUrl,
|
|
955
|
-
"Upstash-Callback-Feature-Set": "LazyFetch,InitialBody",
|
|
956
|
-
"Upstash-Callback-Forward-Upstash-Workflow-Callback": "true",
|
|
957
|
-
"Upstash-Callback-Forward-Upstash-Workflow-StepId": step.stepId.toString(),
|
|
958
|
-
"Upstash-Callback-Forward-Upstash-Workflow-StepName": step.stepName,
|
|
959
|
-
"Upstash-Callback-Forward-Upstash-Workflow-StepType": step.stepType,
|
|
960
|
-
"Upstash-Callback-Forward-Upstash-Workflow-Concurrent": step.concurrent.toString(),
|
|
961
|
-
"Upstash-Callback-Forward-Upstash-Workflow-ContentType": contentType,
|
|
962
|
-
[`Upstash-Callback-Forward-${WORKFLOW_INVOKE_COUNT_HEADER}`]: (invokeCount ?? 0).toString(),
|
|
963
|
-
"Upstash-Workflow-CallType": "toCallback"
|
|
964
|
-
}
|
|
965
|
-
};
|
|
966
|
-
}
|
|
967
|
-
if (step?.waitEventId) {
|
|
968
|
-
return {
|
|
969
|
-
headers: {
|
|
970
|
-
...baseHeaders,
|
|
971
|
-
"Upstash-Workflow-CallType": "step"
|
|
972
|
-
},
|
|
973
|
-
timeoutHeaders: {
|
|
974
|
-
// to include user headers:
|
|
975
|
-
...Object.fromEntries(
|
|
976
|
-
Object.entries(baseHeaders).map(([header, value]) => [header, [value]])
|
|
977
|
-
),
|
|
978
|
-
// to include telemetry headers:
|
|
979
|
-
...telemetry ? Object.fromEntries(
|
|
980
|
-
Object.entries(getTelemetryHeaders(telemetry)).map(([header, value]) => [
|
|
981
|
-
header,
|
|
982
|
-
[value]
|
|
983
|
-
])
|
|
984
|
-
) : {},
|
|
985
|
-
// note: using WORKFLOW_ID_HEADER doesn't work, because Runid -> RunId:
|
|
986
|
-
"Upstash-Workflow-Runid": [workflowRunId],
|
|
987
|
-
[WORKFLOW_INIT_HEADER]: ["false"],
|
|
988
|
-
[WORKFLOW_URL_HEADER]: [workflowUrl],
|
|
989
|
-
"Upstash-Workflow-CallType": ["step"]
|
|
990
|
-
}
|
|
991
|
-
};
|
|
992
|
-
}
|
|
993
|
-
return { headers: baseHeaders };
|
|
994
|
-
};
|
|
995
1058
|
var verifyRequest = async (body, signature, verifier) => {
|
|
996
1059
|
if (!verifier) {
|
|
997
1060
|
return;
|
|
@@ -1010,286 +1073,11 @@ var verifyRequest = async (body, signature, verifier) => {
|
|
|
1010
1073
|
} catch (error) {
|
|
1011
1074
|
throw new WorkflowError(
|
|
1012
1075
|
`Failed to verify that the Workflow request comes from QStash: ${error}
|
|
1013
|
-
|
|
1014
|
-
If signature is missing, trigger the workflow endpoint by publishing your request to QStash instead of calling it directly.
|
|
1015
|
-
|
|
1016
|
-
If you want to disable QStash Verification, you should clear env variables QSTASH_CURRENT_SIGNING_KEY and QSTASH_NEXT_SIGNING_KEY`
|
|
1017
|
-
);
|
|
1018
|
-
}
|
|
1019
|
-
};
|
|
1020
|
-
var prepareFlowControl = (flowControl) => {
|
|
1021
|
-
const parallelism = flowControl.parallelism?.toString();
|
|
1022
|
-
const rate = flowControl.ratePerSecond?.toString();
|
|
1023
|
-
const controlValue = [
|
|
1024
|
-
parallelism ? `parallelism=${parallelism}` : void 0,
|
|
1025
|
-
rate ? `rate=${rate}` : void 0
|
|
1026
|
-
].filter(Boolean);
|
|
1027
|
-
if (controlValue.length === 0) {
|
|
1028
|
-
throw new QstashError3("Provide at least one of parallelism or ratePerSecond for flowControl");
|
|
1029
|
-
}
|
|
1030
|
-
return {
|
|
1031
|
-
flowControlKey: flowControl.key,
|
|
1032
|
-
flowControlValue: controlValue.join(", ")
|
|
1033
|
-
};
|
|
1034
|
-
};
|
|
1035
|
-
|
|
1036
|
-
// src/serve/serve-many.ts
|
|
1037
|
-
var getWorkflowId = (url) => {
|
|
1038
|
-
const components = url.split("/");
|
|
1039
|
-
const lastComponent = components[components.length - 1];
|
|
1040
|
-
return lastComponent.split("?")[0];
|
|
1041
|
-
};
|
|
1042
|
-
var serveManyBase = ({
|
|
1043
|
-
workflows,
|
|
1044
|
-
getUrl,
|
|
1045
|
-
serveMethod,
|
|
1046
|
-
options
|
|
1047
|
-
}) => {
|
|
1048
|
-
const workflowIds = [];
|
|
1049
|
-
const workflowMap = Object.fromEntries(
|
|
1050
|
-
Object.entries(workflows).map((workflow) => {
|
|
1051
|
-
const workflowId = workflow[0];
|
|
1052
|
-
if (workflowIds.includes(workflowId)) {
|
|
1053
|
-
throw new WorkflowError(
|
|
1054
|
-
`Duplicate workflow name found: '${workflowId}'. Please set different workflow names in serveMany.`
|
|
1055
|
-
);
|
|
1056
|
-
}
|
|
1057
|
-
if (workflowId.includes("/")) {
|
|
1058
|
-
throw new WorkflowError(
|
|
1059
|
-
`Invalid workflow name found: '${workflowId}'. Workflow name cannot contain '/'.`
|
|
1060
|
-
);
|
|
1061
|
-
}
|
|
1062
|
-
workflowIds.push(workflowId);
|
|
1063
|
-
workflow[1].workflowId = workflowId;
|
|
1064
|
-
workflow[1].options = {
|
|
1065
|
-
...options,
|
|
1066
|
-
...workflow[1].options
|
|
1067
|
-
};
|
|
1068
|
-
const params = [workflow[1].routeFunction, workflow[1].options];
|
|
1069
|
-
const handler = serveMethod(...params);
|
|
1070
|
-
return [workflowId, handler];
|
|
1071
|
-
})
|
|
1072
|
-
);
|
|
1073
|
-
return {
|
|
1074
|
-
handler: async (...params) => {
|
|
1075
|
-
const url = getUrl(...params);
|
|
1076
|
-
const pickedWorkflowId = getWorkflowId(url);
|
|
1077
|
-
if (!pickedWorkflowId) {
|
|
1078
|
-
return new Response(
|
|
1079
|
-
`Unexpected request in serveMany. workflowId not set. Please update the URL of your request.`,
|
|
1080
|
-
{
|
|
1081
|
-
status: 404
|
|
1082
|
-
}
|
|
1083
|
-
);
|
|
1084
|
-
}
|
|
1085
|
-
const workflow = workflowMap[pickedWorkflowId];
|
|
1086
|
-
if (!workflow) {
|
|
1087
|
-
return new Response(
|
|
1088
|
-
`No workflows in serveMany found for '${pickedWorkflowId}'. Please update the URL of your request.`,
|
|
1089
|
-
{
|
|
1090
|
-
status: 404
|
|
1091
|
-
}
|
|
1092
|
-
);
|
|
1093
|
-
}
|
|
1094
|
-
return await workflow(...params);
|
|
1095
|
-
}
|
|
1096
|
-
};
|
|
1097
|
-
};
|
|
1098
|
-
var invokeWorkflow = async ({
|
|
1099
|
-
settings,
|
|
1100
|
-
invokeStep,
|
|
1101
|
-
context,
|
|
1102
|
-
invokeCount,
|
|
1103
|
-
telemetry
|
|
1104
|
-
}) => {
|
|
1105
|
-
const {
|
|
1106
|
-
body,
|
|
1107
|
-
workflow,
|
|
1108
|
-
headers = {},
|
|
1109
|
-
workflowRunId = getWorkflowRunId(),
|
|
1110
|
-
retries,
|
|
1111
|
-
flowControl
|
|
1112
|
-
} = settings;
|
|
1113
|
-
const { workflowId } = workflow;
|
|
1114
|
-
const {
|
|
1115
|
-
retries: workflowRetries,
|
|
1116
|
-
failureFunction,
|
|
1117
|
-
failureUrl,
|
|
1118
|
-
useJSONContent,
|
|
1119
|
-
flowControl: workflowFlowControl
|
|
1120
|
-
} = workflow.options;
|
|
1121
|
-
if (!workflowId) {
|
|
1122
|
-
throw new WorkflowError("You can only invoke workflow which has a workflowId");
|
|
1123
|
-
}
|
|
1124
|
-
const { headers: invokerHeaders } = getHeaders({
|
|
1125
|
-
initHeaderValue: "false",
|
|
1126
|
-
workflowRunId: context.workflowRunId,
|
|
1127
|
-
workflowUrl: context.url,
|
|
1128
|
-
userHeaders: context.headers,
|
|
1129
|
-
failureUrl: context.failureUrl,
|
|
1130
|
-
retries: context.retries,
|
|
1131
|
-
telemetry,
|
|
1132
|
-
invokeCount,
|
|
1133
|
-
flowControl: context.flowControl
|
|
1134
|
-
});
|
|
1135
|
-
invokerHeaders["Upstash-Workflow-Runid"] = context.workflowRunId;
|
|
1136
|
-
const newUrl = context.url.replace(/[^/]+$/, workflowId);
|
|
1137
|
-
const { headers: triggerHeaders } = getHeaders({
|
|
1138
|
-
initHeaderValue: "true",
|
|
1139
|
-
workflowRunId,
|
|
1140
|
-
workflowUrl: newUrl,
|
|
1141
|
-
userHeaders: new Headers(headers),
|
|
1142
|
-
retries: retries ?? workflowRetries,
|
|
1143
|
-
telemetry,
|
|
1144
|
-
failureUrl: failureFunction ? newUrl : failureUrl,
|
|
1145
|
-
invokeCount: invokeCount + 1,
|
|
1146
|
-
flowControl: flowControl ?? workflowFlowControl
|
|
1147
|
-
});
|
|
1148
|
-
triggerHeaders["Upstash-Workflow-Invoke"] = "true";
|
|
1149
|
-
if (useJSONContent) {
|
|
1150
|
-
triggerHeaders["content-type"] = "application/json";
|
|
1151
|
-
}
|
|
1152
|
-
const request = {
|
|
1153
|
-
body: JSON.stringify(body),
|
|
1154
|
-
headers: Object.fromEntries(
|
|
1155
|
-
Object.entries(invokerHeaders).map((pairs) => [pairs[0], [pairs[1]]])
|
|
1156
|
-
),
|
|
1157
|
-
workflowRunId: context.workflowRunId,
|
|
1158
|
-
workflowUrl: context.url,
|
|
1159
|
-
step: invokeStep
|
|
1160
|
-
};
|
|
1161
|
-
await context.qstashClient.publish({
|
|
1162
|
-
headers: triggerHeaders,
|
|
1163
|
-
method: "POST",
|
|
1164
|
-
body: JSON.stringify(request),
|
|
1165
|
-
url: newUrl
|
|
1166
|
-
});
|
|
1167
|
-
};
|
|
1168
|
-
|
|
1169
|
-
// src/agents/adapters.ts
|
|
1170
|
-
import { createOpenAI } from "@ai-sdk/openai";
|
|
1171
|
-
import { tool } from "ai";
|
|
1172
|
-
|
|
1173
|
-
// src/agents/constants.ts
|
|
1174
|
-
var AGENT_NAME_HEADER = "upstash-agent-name";
|
|
1175
|
-
var MANAGER_AGENT_PROMPT = `You are an agent orchestrating other AI Agents.
|
|
1176
|
-
|
|
1177
|
-
These other agents have tools available to them.
|
|
1178
|
-
|
|
1179
|
-
Given a prompt, utilize these agents to address requests.
|
|
1180
|
-
|
|
1181
|
-
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.
|
|
1182
|
-
|
|
1183
|
-
Avoid calling the same agent twice in one turn. Instead, prefer to call it once but provide everything
|
|
1184
|
-
you need from that agent.
|
|
1185
|
-
`;
|
|
1186
|
-
|
|
1187
|
-
// src/agents/adapters.ts
|
|
1188
|
-
var fetchWithContextCall = async (context, ...params) => {
|
|
1189
|
-
const [input, init] = params;
|
|
1190
|
-
try {
|
|
1191
|
-
const headers = init?.headers ? Object.fromEntries(new Headers(init.headers).entries()) : {};
|
|
1192
|
-
const body = init?.body ? JSON.parse(init.body) : void 0;
|
|
1193
|
-
const agentName = headers[AGENT_NAME_HEADER];
|
|
1194
|
-
const stepName = agentName ? `Call Agent ${agentName}` : "Call Agent";
|
|
1195
|
-
const responseInfo = await context.call(stepName, {
|
|
1196
|
-
url: input.toString(),
|
|
1197
|
-
method: init?.method,
|
|
1198
|
-
headers,
|
|
1199
|
-
body
|
|
1200
|
-
});
|
|
1201
|
-
const responseHeaders = new Headers(
|
|
1202
|
-
Object.entries(responseInfo.header).reduce(
|
|
1203
|
-
(acc, [key, values]) => {
|
|
1204
|
-
acc[key] = values.join(", ");
|
|
1205
|
-
return acc;
|
|
1206
|
-
},
|
|
1207
|
-
{}
|
|
1208
|
-
)
|
|
1209
|
-
);
|
|
1210
|
-
return new Response(JSON.stringify(responseInfo.body), {
|
|
1211
|
-
status: responseInfo.status,
|
|
1212
|
-
headers: responseHeaders
|
|
1213
|
-
});
|
|
1214
|
-
} catch (error) {
|
|
1215
|
-
if (error instanceof Error && error.name === "WorkflowAbort") {
|
|
1216
|
-
throw error;
|
|
1217
|
-
} else {
|
|
1218
|
-
console.error("Error in fetch implementation:", error);
|
|
1219
|
-
throw error;
|
|
1220
|
-
}
|
|
1221
|
-
}
|
|
1222
|
-
};
|
|
1223
|
-
var createWorkflowModel = ({
|
|
1224
|
-
context,
|
|
1225
|
-
provider,
|
|
1226
|
-
providerParams
|
|
1227
|
-
}) => {
|
|
1228
|
-
return provider({
|
|
1229
|
-
fetch: (...params) => fetchWithContextCall(context, ...params),
|
|
1230
|
-
...providerParams
|
|
1231
|
-
});
|
|
1232
|
-
};
|
|
1233
|
-
var wrapTools = ({
|
|
1234
|
-
context,
|
|
1235
|
-
tools
|
|
1236
|
-
}) => {
|
|
1237
|
-
return Object.fromEntries(
|
|
1238
|
-
Object.entries(tools).map((toolInfo) => {
|
|
1239
|
-
const [toolName, tool3] = toolInfo;
|
|
1240
|
-
const executeAsStep = "executeAsStep" in tool3 ? tool3.executeAsStep : true;
|
|
1241
|
-
const aiSDKTool = convertToAISDKTool(tool3);
|
|
1242
|
-
const execute = aiSDKTool.execute;
|
|
1243
|
-
if (execute && executeAsStep) {
|
|
1244
|
-
const wrappedExecute = (...params) => {
|
|
1245
|
-
return context.run(`Run tool ${toolName}`, () => execute(...params));
|
|
1246
|
-
};
|
|
1247
|
-
aiSDKTool.execute = wrappedExecute;
|
|
1248
|
-
}
|
|
1249
|
-
return [toolName, aiSDKTool];
|
|
1250
|
-
})
|
|
1251
|
-
);
|
|
1252
|
-
};
|
|
1253
|
-
var convertToAISDKTool = (tool3) => {
|
|
1254
|
-
const isLangchainTool = "invoke" in tool3;
|
|
1255
|
-
return isLangchainTool ? convertLangchainTool(tool3) : tool3;
|
|
1256
|
-
};
|
|
1257
|
-
var convertLangchainTool = (langchainTool) => {
|
|
1258
|
-
return tool({
|
|
1259
|
-
description: langchainTool.description,
|
|
1260
|
-
parameters: langchainTool.schema,
|
|
1261
|
-
execute: async (...param) => langchainTool.invoke(...param)
|
|
1262
|
-
});
|
|
1263
|
-
};
|
|
1264
|
-
var WorkflowTool = class {
|
|
1265
|
-
/**
|
|
1266
|
-
* description of the tool
|
|
1267
|
-
*/
|
|
1268
|
-
description;
|
|
1269
|
-
/**
|
|
1270
|
-
* schema of the tool
|
|
1271
|
-
*/
|
|
1272
|
-
schema;
|
|
1273
|
-
/**
|
|
1274
|
-
* function to invoke the tool
|
|
1275
|
-
*/
|
|
1276
|
-
invoke;
|
|
1277
|
-
/**
|
|
1278
|
-
* whether the invoke method of the tool is to be wrapped with `context.run`
|
|
1279
|
-
*/
|
|
1280
|
-
executeAsStep;
|
|
1281
|
-
/**
|
|
1282
|
-
*
|
|
1283
|
-
* @param description description of the tool
|
|
1284
|
-
* @param schema schema of the tool
|
|
1285
|
-
* @param invoke function to invoke the tool
|
|
1286
|
-
* @param executeAsStep whether the invoke method of the tool is to be wrapped with `context.run`
|
|
1287
|
-
*/
|
|
1288
|
-
constructor(params) {
|
|
1289
|
-
this.description = params.description;
|
|
1290
|
-
this.schema = params.schema;
|
|
1291
|
-
this.invoke = params.invoke;
|
|
1292
|
-
this.executeAsStep = params.executeAsStep ?? true;
|
|
1076
|
+
|
|
1077
|
+
If signature is missing, trigger the workflow endpoint by publishing your request to QStash instead of calling it directly.
|
|
1078
|
+
|
|
1079
|
+
If you want to disable QStash Verification, you should clear env variables QSTASH_CURRENT_SIGNING_KEY and QSTASH_NEXT_SIGNING_KEY`
|
|
1080
|
+
);
|
|
1293
1081
|
}
|
|
1294
1082
|
};
|
|
1295
1083
|
|
|
@@ -1302,6 +1090,11 @@ var BaseLazyStep = class _BaseLazyStep {
|
|
|
1302
1090
|
"A workflow step name cannot be undefined or an empty string. Please provide a name for your workflow step."
|
|
1303
1091
|
);
|
|
1304
1092
|
}
|
|
1093
|
+
if (typeof stepName !== "string") {
|
|
1094
|
+
console.warn(
|
|
1095
|
+
"Workflow Warning: A workflow step name must be a string. In a future release, this will throw an error."
|
|
1096
|
+
);
|
|
1097
|
+
}
|
|
1305
1098
|
this.stepName = stepName;
|
|
1306
1099
|
}
|
|
1307
1100
|
/**
|
|
@@ -1351,6 +1144,40 @@ var BaseLazyStep = class _BaseLazyStep {
|
|
|
1351
1144
|
return stepOut;
|
|
1352
1145
|
}
|
|
1353
1146
|
}
|
|
1147
|
+
getBody({ step }) {
|
|
1148
|
+
step.out = JSON.stringify(step.out);
|
|
1149
|
+
return JSON.stringify(step);
|
|
1150
|
+
}
|
|
1151
|
+
getHeaders({ context, telemetry, invokeCount, step }) {
|
|
1152
|
+
return getHeaders({
|
|
1153
|
+
initHeaderValue: "false",
|
|
1154
|
+
workflowConfig: {
|
|
1155
|
+
workflowRunId: context.workflowRunId,
|
|
1156
|
+
workflowUrl: context.url,
|
|
1157
|
+
failureUrl: context.failureUrl,
|
|
1158
|
+
retries: context.retries,
|
|
1159
|
+
useJSONContent: false,
|
|
1160
|
+
telemetry,
|
|
1161
|
+
flowControl: context.flowControl
|
|
1162
|
+
},
|
|
1163
|
+
userHeaders: context.headers,
|
|
1164
|
+
invokeCount,
|
|
1165
|
+
stepInfo: {
|
|
1166
|
+
step,
|
|
1167
|
+
lazyStep: this
|
|
1168
|
+
}
|
|
1169
|
+
});
|
|
1170
|
+
}
|
|
1171
|
+
async submitStep({ context, body, headers }) {
|
|
1172
|
+
return await context.qstashClient.batch([
|
|
1173
|
+
{
|
|
1174
|
+
body,
|
|
1175
|
+
headers,
|
|
1176
|
+
method: "POST",
|
|
1177
|
+
url: context.url
|
|
1178
|
+
}
|
|
1179
|
+
]);
|
|
1180
|
+
}
|
|
1354
1181
|
};
|
|
1355
1182
|
var LazyFunctionStep = class extends BaseLazyStep {
|
|
1356
1183
|
stepFunction;
|
|
@@ -1410,6 +1237,17 @@ var LazySleepStep = class extends BaseLazyStep {
|
|
|
1410
1237
|
concurrent
|
|
1411
1238
|
});
|
|
1412
1239
|
}
|
|
1240
|
+
async submitStep({ context, body, headers, isParallel }) {
|
|
1241
|
+
return await context.qstashClient.batch([
|
|
1242
|
+
{
|
|
1243
|
+
body,
|
|
1244
|
+
headers,
|
|
1245
|
+
method: "POST",
|
|
1246
|
+
url: context.url,
|
|
1247
|
+
delay: isParallel ? void 0 : this.sleep
|
|
1248
|
+
}
|
|
1249
|
+
]);
|
|
1250
|
+
}
|
|
1413
1251
|
};
|
|
1414
1252
|
var LazySleepUntilStep = class extends BaseLazyStep {
|
|
1415
1253
|
sleepUntil;
|
|
@@ -1441,6 +1279,17 @@ var LazySleepUntilStep = class extends BaseLazyStep {
|
|
|
1441
1279
|
safeParseOut() {
|
|
1442
1280
|
return void 0;
|
|
1443
1281
|
}
|
|
1282
|
+
async submitStep({ context, body, headers, isParallel }) {
|
|
1283
|
+
return await context.qstashClient.batch([
|
|
1284
|
+
{
|
|
1285
|
+
body,
|
|
1286
|
+
headers,
|
|
1287
|
+
method: "POST",
|
|
1288
|
+
url: context.url,
|
|
1289
|
+
notBefore: isParallel ? void 0 : this.sleepUntil
|
|
1290
|
+
}
|
|
1291
|
+
]);
|
|
1292
|
+
}
|
|
1444
1293
|
};
|
|
1445
1294
|
var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
|
|
1446
1295
|
url;
|
|
@@ -1524,6 +1373,58 @@ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
|
|
|
1524
1373
|
}
|
|
1525
1374
|
return false;
|
|
1526
1375
|
};
|
|
1376
|
+
getBody({ step }) {
|
|
1377
|
+
if (!step.callUrl) {
|
|
1378
|
+
throw new WorkflowError("Incompatible step received in LazyCallStep.getBody");
|
|
1379
|
+
}
|
|
1380
|
+
return JSON.stringify(step.callBody);
|
|
1381
|
+
}
|
|
1382
|
+
getHeaders({ context, telemetry, invokeCount, step }) {
|
|
1383
|
+
const { headers, contentType } = super.getHeaders({ context, telemetry, invokeCount, step });
|
|
1384
|
+
headers["Upstash-Retries"] = this.retries.toString();
|
|
1385
|
+
headers[WORKFLOW_FEATURE_HEADER] = "WF_NoDelete,InitialBody";
|
|
1386
|
+
if (this.flowControl) {
|
|
1387
|
+
const { flowControlKey, flowControlValue } = prepareFlowControl(this.flowControl);
|
|
1388
|
+
headers["Upstash-Flow-Control-Key"] = flowControlKey;
|
|
1389
|
+
headers["Upstash-Flow-Control-Value"] = flowControlValue;
|
|
1390
|
+
}
|
|
1391
|
+
if (this.timeout) {
|
|
1392
|
+
headers["Upstash-Timeout"] = this.timeout.toString();
|
|
1393
|
+
}
|
|
1394
|
+
const forwardedHeaders = Object.fromEntries(
|
|
1395
|
+
Object.entries(this.headers).map(([header, value]) => [`Upstash-Forward-${header}`, value])
|
|
1396
|
+
);
|
|
1397
|
+
return {
|
|
1398
|
+
headers: {
|
|
1399
|
+
...headers,
|
|
1400
|
+
...forwardedHeaders,
|
|
1401
|
+
"Upstash-Callback": context.url,
|
|
1402
|
+
"Upstash-Callback-Workflow-RunId": context.workflowRunId,
|
|
1403
|
+
"Upstash-Callback-Workflow-CallType": "fromCallback",
|
|
1404
|
+
"Upstash-Callback-Workflow-Init": "false",
|
|
1405
|
+
"Upstash-Callback-Workflow-Url": context.url,
|
|
1406
|
+
"Upstash-Callback-Feature-Set": "LazyFetch,InitialBody",
|
|
1407
|
+
"Upstash-Callback-Forward-Upstash-Workflow-Callback": "true",
|
|
1408
|
+
"Upstash-Callback-Forward-Upstash-Workflow-StepId": step.stepId.toString(),
|
|
1409
|
+
"Upstash-Callback-Forward-Upstash-Workflow-StepName": this.stepName,
|
|
1410
|
+
"Upstash-Callback-Forward-Upstash-Workflow-StepType": this.stepType,
|
|
1411
|
+
"Upstash-Callback-Forward-Upstash-Workflow-Concurrent": step.concurrent.toString(),
|
|
1412
|
+
"Upstash-Callback-Forward-Upstash-Workflow-ContentType": contentType,
|
|
1413
|
+
"Upstash-Workflow-CallType": "toCallback"
|
|
1414
|
+
},
|
|
1415
|
+
contentType
|
|
1416
|
+
};
|
|
1417
|
+
}
|
|
1418
|
+
async submitStep({ context, headers }) {
|
|
1419
|
+
return await context.qstashClient.batch([
|
|
1420
|
+
{
|
|
1421
|
+
headers,
|
|
1422
|
+
body: JSON.stringify(this.body),
|
|
1423
|
+
method: this.method,
|
|
1424
|
+
url: this.url
|
|
1425
|
+
}
|
|
1426
|
+
]);
|
|
1427
|
+
}
|
|
1527
1428
|
};
|
|
1528
1429
|
var LazyWaitForEventStep = class extends BaseLazyStep {
|
|
1529
1430
|
eventId;
|
|
@@ -1563,6 +1464,57 @@ var LazyWaitForEventStep = class extends BaseLazyStep {
|
|
|
1563
1464
|
eventData: BaseLazyStep.tryParsing(result.eventData)
|
|
1564
1465
|
};
|
|
1565
1466
|
}
|
|
1467
|
+
getHeaders({ context, telemetry, invokeCount, step }) {
|
|
1468
|
+
const headers = super.getHeaders({ context, telemetry, invokeCount, step });
|
|
1469
|
+
headers.headers["Upstash-Workflow-CallType"] = "step";
|
|
1470
|
+
return headers;
|
|
1471
|
+
}
|
|
1472
|
+
getBody({ context, step, headers, telemetry }) {
|
|
1473
|
+
if (!step.waitEventId) {
|
|
1474
|
+
throw new WorkflowError("Incompatible step received in LazyWaitForEventStep.getBody");
|
|
1475
|
+
}
|
|
1476
|
+
const timeoutHeaders = {
|
|
1477
|
+
// to include user headers:
|
|
1478
|
+
...Object.fromEntries(Object.entries(headers).map(([header, value]) => [header, [value]])),
|
|
1479
|
+
// to include telemetry headers:
|
|
1480
|
+
...telemetry ? Object.fromEntries(
|
|
1481
|
+
Object.entries(getTelemetryHeaders(telemetry)).map(([header, value]) => [
|
|
1482
|
+
header,
|
|
1483
|
+
[value]
|
|
1484
|
+
])
|
|
1485
|
+
) : {},
|
|
1486
|
+
// note: using WORKFLOW_ID_HEADER doesn't work, because Runid -> RunId:
|
|
1487
|
+
"Upstash-Workflow-Runid": [context.workflowRunId],
|
|
1488
|
+
[WORKFLOW_INIT_HEADER]: ["false"],
|
|
1489
|
+
[WORKFLOW_URL_HEADER]: [context.url],
|
|
1490
|
+
"Upstash-Workflow-CallType": ["step"]
|
|
1491
|
+
};
|
|
1492
|
+
const waitBody = {
|
|
1493
|
+
url: context.url,
|
|
1494
|
+
timeout: step.timeout,
|
|
1495
|
+
timeoutBody: void 0,
|
|
1496
|
+
timeoutUrl: context.url,
|
|
1497
|
+
timeoutHeaders,
|
|
1498
|
+
step: {
|
|
1499
|
+
stepId: step.stepId,
|
|
1500
|
+
stepType: "Wait",
|
|
1501
|
+
stepName: step.stepName,
|
|
1502
|
+
concurrent: step.concurrent,
|
|
1503
|
+
targetStep: step.targetStep
|
|
1504
|
+
}
|
|
1505
|
+
};
|
|
1506
|
+
return JSON.stringify(waitBody);
|
|
1507
|
+
}
|
|
1508
|
+
async submitStep({ context, body, headers }) {
|
|
1509
|
+
const result = await context.qstashClient.http.request({
|
|
1510
|
+
path: ["v2", "wait", this.eventId],
|
|
1511
|
+
body,
|
|
1512
|
+
headers,
|
|
1513
|
+
method: "POST",
|
|
1514
|
+
parseResponseAsJson: false
|
|
1515
|
+
});
|
|
1516
|
+
return [result];
|
|
1517
|
+
}
|
|
1566
1518
|
};
|
|
1567
1519
|
var LazyNotifyStep = class extends LazyFunctionStep {
|
|
1568
1520
|
stepType = "Notify";
|
|
@@ -1588,6 +1540,10 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1588
1540
|
stepType = "Invoke";
|
|
1589
1541
|
params;
|
|
1590
1542
|
allowUndefinedOut = false;
|
|
1543
|
+
/**
|
|
1544
|
+
* workflow id of the invoked workflow
|
|
1545
|
+
*/
|
|
1546
|
+
workflowId;
|
|
1591
1547
|
constructor(stepName, {
|
|
1592
1548
|
workflow,
|
|
1593
1549
|
body,
|
|
@@ -1605,6 +1561,11 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1605
1561
|
retries,
|
|
1606
1562
|
flowControl
|
|
1607
1563
|
};
|
|
1564
|
+
const { workflowId } = workflow;
|
|
1565
|
+
if (!workflowId) {
|
|
1566
|
+
throw new WorkflowError("You can only invoke workflow which has a workflowId");
|
|
1567
|
+
}
|
|
1568
|
+
this.workflowId = workflowId;
|
|
1608
1569
|
}
|
|
1609
1570
|
getPlanStep(concurrent, targetStep) {
|
|
1610
1571
|
return {
|
|
@@ -1634,10 +1595,348 @@ var LazyInvokeStep = class extends BaseLazyStep {
|
|
|
1634
1595
|
body: BaseLazyStep.tryParsing(result.body)
|
|
1635
1596
|
};
|
|
1636
1597
|
}
|
|
1598
|
+
getBody({ context, step, telemetry, invokeCount }) {
|
|
1599
|
+
const { headers: invokerHeaders } = getHeaders({
|
|
1600
|
+
initHeaderValue: "false",
|
|
1601
|
+
workflowConfig: {
|
|
1602
|
+
workflowRunId: context.workflowRunId,
|
|
1603
|
+
workflowUrl: context.url,
|
|
1604
|
+
failureUrl: context.failureUrl,
|
|
1605
|
+
retries: context.retries,
|
|
1606
|
+
telemetry,
|
|
1607
|
+
flowControl: context.flowControl,
|
|
1608
|
+
useJSONContent: false
|
|
1609
|
+
},
|
|
1610
|
+
userHeaders: context.headers,
|
|
1611
|
+
invokeCount
|
|
1612
|
+
});
|
|
1613
|
+
invokerHeaders["Upstash-Workflow-Runid"] = context.workflowRunId;
|
|
1614
|
+
const request = {
|
|
1615
|
+
body: JSON.stringify(this.params.body),
|
|
1616
|
+
headers: Object.fromEntries(
|
|
1617
|
+
Object.entries(invokerHeaders).map((pairs) => [pairs[0], [pairs[1]]])
|
|
1618
|
+
),
|
|
1619
|
+
workflowRunId: context.workflowRunId,
|
|
1620
|
+
workflowUrl: context.url,
|
|
1621
|
+
step
|
|
1622
|
+
};
|
|
1623
|
+
return JSON.stringify(request);
|
|
1624
|
+
}
|
|
1625
|
+
getHeaders({ context, telemetry, invokeCount }) {
|
|
1626
|
+
const {
|
|
1627
|
+
workflow,
|
|
1628
|
+
headers = {},
|
|
1629
|
+
workflowRunId = getWorkflowRunId(),
|
|
1630
|
+
retries,
|
|
1631
|
+
flowControl
|
|
1632
|
+
} = this.params;
|
|
1633
|
+
const newUrl = context.url.replace(/[^/]+$/, this.workflowId);
|
|
1634
|
+
const {
|
|
1635
|
+
retries: workflowRetries,
|
|
1636
|
+
failureFunction,
|
|
1637
|
+
failureUrl,
|
|
1638
|
+
useJSONContent,
|
|
1639
|
+
flowControl: workflowFlowControl
|
|
1640
|
+
} = workflow.options;
|
|
1641
|
+
const { headers: triggerHeaders, contentType } = getHeaders({
|
|
1642
|
+
initHeaderValue: "true",
|
|
1643
|
+
workflowConfig: {
|
|
1644
|
+
workflowRunId,
|
|
1645
|
+
workflowUrl: newUrl,
|
|
1646
|
+
retries: retries ?? workflowRetries,
|
|
1647
|
+
telemetry,
|
|
1648
|
+
failureUrl: failureFunction ? newUrl : failureUrl,
|
|
1649
|
+
flowControl: flowControl ?? workflowFlowControl,
|
|
1650
|
+
useJSONContent: useJSONContent ?? false
|
|
1651
|
+
},
|
|
1652
|
+
invokeCount: invokeCount + 1,
|
|
1653
|
+
userHeaders: new Headers(headers)
|
|
1654
|
+
});
|
|
1655
|
+
triggerHeaders["Upstash-Workflow-Invoke"] = "true";
|
|
1656
|
+
return { headers: triggerHeaders, contentType };
|
|
1657
|
+
}
|
|
1658
|
+
async submitStep({ context, body, headers }) {
|
|
1659
|
+
const newUrl = context.url.replace(/[^/]+$/, this.workflowId);
|
|
1660
|
+
const result = await context.qstashClient.publish({
|
|
1661
|
+
headers,
|
|
1662
|
+
method: "POST",
|
|
1663
|
+
body,
|
|
1664
|
+
url: newUrl
|
|
1665
|
+
});
|
|
1666
|
+
return [result];
|
|
1667
|
+
}
|
|
1668
|
+
};
|
|
1669
|
+
|
|
1670
|
+
// src/qstash/headers.ts
|
|
1671
|
+
var WorkflowHeaders = class {
|
|
1672
|
+
userHeaders;
|
|
1673
|
+
workflowConfig;
|
|
1674
|
+
invokeCount;
|
|
1675
|
+
initHeaderValue;
|
|
1676
|
+
stepInfo;
|
|
1677
|
+
headers;
|
|
1678
|
+
constructor({
|
|
1679
|
+
userHeaders,
|
|
1680
|
+
workflowConfig,
|
|
1681
|
+
invokeCount,
|
|
1682
|
+
initHeaderValue,
|
|
1683
|
+
stepInfo
|
|
1684
|
+
}) {
|
|
1685
|
+
this.userHeaders = userHeaders;
|
|
1686
|
+
this.workflowConfig = workflowConfig;
|
|
1687
|
+
this.invokeCount = invokeCount;
|
|
1688
|
+
this.initHeaderValue = initHeaderValue;
|
|
1689
|
+
this.stepInfo = stepInfo;
|
|
1690
|
+
this.headers = {
|
|
1691
|
+
rawHeaders: {},
|
|
1692
|
+
workflowHeaders: {},
|
|
1693
|
+
failureHeaders: {}
|
|
1694
|
+
};
|
|
1695
|
+
}
|
|
1696
|
+
getHeaders() {
|
|
1697
|
+
this.addBaseHeaders();
|
|
1698
|
+
this.addRetries();
|
|
1699
|
+
this.addFlowControl();
|
|
1700
|
+
this.addUserHeaders();
|
|
1701
|
+
this.addInvokeCount();
|
|
1702
|
+
this.addFailureUrl();
|
|
1703
|
+
const contentType = this.addContentType();
|
|
1704
|
+
return this.prefixHeaders(contentType);
|
|
1705
|
+
}
|
|
1706
|
+
addBaseHeaders() {
|
|
1707
|
+
this.headers.rawHeaders = {
|
|
1708
|
+
...this.headers.rawHeaders,
|
|
1709
|
+
[WORKFLOW_INIT_HEADER]: this.initHeaderValue,
|
|
1710
|
+
[WORKFLOW_ID_HEADER]: this.workflowConfig.workflowRunId,
|
|
1711
|
+
[WORKFLOW_URL_HEADER]: this.workflowConfig.workflowUrl,
|
|
1712
|
+
[WORKFLOW_FEATURE_HEADER]: "LazyFetch,InitialBody",
|
|
1713
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION,
|
|
1714
|
+
...this.workflowConfig.telemetry ? getTelemetryHeaders(this.workflowConfig.telemetry) : {},
|
|
1715
|
+
...this.workflowConfig.telemetry && this.stepInfo?.lazyStep instanceof LazyCallStep && this.stepInfo.lazyStep.headers[AGENT_NAME_HEADER] ? { [TELEMETRY_HEADER_AGENT]: "true" } : {}
|
|
1716
|
+
};
|
|
1717
|
+
if (this.stepInfo?.lazyStep.stepType !== "Call") {
|
|
1718
|
+
this.headers.rawHeaders[`Upstash-Forward-${WORKFLOW_PROTOCOL_VERSION_HEADER}`] = WORKFLOW_PROTOCOL_VERSION;
|
|
1719
|
+
}
|
|
1720
|
+
}
|
|
1721
|
+
addInvokeCount() {
|
|
1722
|
+
if (this.invokeCount === void 0 || this.invokeCount === 0) {
|
|
1723
|
+
return;
|
|
1724
|
+
}
|
|
1725
|
+
const invokeCount = this.invokeCount.toString();
|
|
1726
|
+
this.headers.workflowHeaders[`Forward-${WORKFLOW_INVOKE_COUNT_HEADER}`] = invokeCount;
|
|
1727
|
+
if (this.workflowConfig.failureUrl) {
|
|
1728
|
+
this.headers.failureHeaders[`Forward-${WORKFLOW_INVOKE_COUNT_HEADER}`] = invokeCount;
|
|
1729
|
+
}
|
|
1730
|
+
if (this.stepInfo?.lazyStep instanceof LazyCallStep) {
|
|
1731
|
+
this.headers.rawHeaders[`Upstash-Forward-${WORKFLOW_INVOKE_COUNT_HEADER}`] = invokeCount;
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1734
|
+
addRetries() {
|
|
1735
|
+
if (this.workflowConfig.retries === void 0 || this.workflowConfig.retries === DEFAULT_RETRIES) {
|
|
1736
|
+
return;
|
|
1737
|
+
}
|
|
1738
|
+
const retries = this.workflowConfig.retries.toString();
|
|
1739
|
+
this.headers.workflowHeaders["Retries"] = retries;
|
|
1740
|
+
if (this.workflowConfig.failureUrl) {
|
|
1741
|
+
this.headers.failureHeaders["Retries"] = retries;
|
|
1742
|
+
}
|
|
1743
|
+
}
|
|
1744
|
+
addFlowControl() {
|
|
1745
|
+
if (!this.workflowConfig.flowControl) {
|
|
1746
|
+
return;
|
|
1747
|
+
}
|
|
1748
|
+
const { flowControlKey, flowControlValue } = prepareFlowControl(
|
|
1749
|
+
this.workflowConfig.flowControl
|
|
1750
|
+
);
|
|
1751
|
+
this.headers.workflowHeaders["Flow-Control-Key"] = flowControlKey;
|
|
1752
|
+
this.headers.workflowHeaders["Flow-Control-Value"] = flowControlValue;
|
|
1753
|
+
if (this.workflowConfig.failureUrl) {
|
|
1754
|
+
this.headers.failureHeaders["Flow-Control-Key"] = flowControlKey;
|
|
1755
|
+
this.headers.failureHeaders["Flow-Control-Value"] = flowControlValue;
|
|
1756
|
+
}
|
|
1757
|
+
}
|
|
1758
|
+
addUserHeaders() {
|
|
1759
|
+
for (const [key, value] of this.userHeaders.entries()) {
|
|
1760
|
+
const forwardKey = `Forward-${key}`;
|
|
1761
|
+
this.headers.workflowHeaders[forwardKey] = value;
|
|
1762
|
+
if (this.workflowConfig.failureUrl) {
|
|
1763
|
+
this.headers.failureHeaders[forwardKey] = value;
|
|
1764
|
+
}
|
|
1765
|
+
}
|
|
1766
|
+
}
|
|
1767
|
+
addFailureUrl() {
|
|
1768
|
+
if (!this.workflowConfig.failureUrl) {
|
|
1769
|
+
return;
|
|
1770
|
+
}
|
|
1771
|
+
this.headers.workflowHeaders["Failure-Callback"] = this.workflowConfig.failureUrl;
|
|
1772
|
+
this.headers.failureHeaders[`Forward-${WORKFLOW_FAILURE_HEADER}`] = "true";
|
|
1773
|
+
this.headers.failureHeaders[`Forward-Upstash-Workflow-Failure-Callback`] = "true";
|
|
1774
|
+
this.headers.failureHeaders["Workflow-Runid"] = this.workflowConfig.workflowRunId;
|
|
1775
|
+
this.headers.failureHeaders["Workflow-Init"] = "false";
|
|
1776
|
+
this.headers.failureHeaders["Workflow-Url"] = this.workflowConfig.workflowUrl;
|
|
1777
|
+
this.headers.failureHeaders["Workflow-Calltype"] = "failureCall";
|
|
1778
|
+
this.headers.failureHeaders["Feature-Set"] = "LazyFetch,InitialBody";
|
|
1779
|
+
if (this.workflowConfig.retries !== void 0 && this.workflowConfig.retries !== DEFAULT_RETRIES) {
|
|
1780
|
+
this.headers.failureHeaders["Retries"] = this.workflowConfig.retries.toString();
|
|
1781
|
+
}
|
|
1782
|
+
}
|
|
1783
|
+
addContentType() {
|
|
1784
|
+
if (this.workflowConfig.useJSONContent) {
|
|
1785
|
+
this.headers.rawHeaders["content-type"] = "application/json";
|
|
1786
|
+
return "application/json";
|
|
1787
|
+
}
|
|
1788
|
+
const callHeaders = new Headers(
|
|
1789
|
+
this.stepInfo?.lazyStep instanceof LazyCallStep ? this.stepInfo.lazyStep.headers : {}
|
|
1790
|
+
);
|
|
1791
|
+
const contentType = (callHeaders.get("content-type") ? callHeaders.get("content-type") : this.userHeaders?.get("Content-Type") ? this.userHeaders.get("Content-Type") : void 0) ?? DEFAULT_CONTENT_TYPE;
|
|
1792
|
+
this.headers.rawHeaders["content-type"] = contentType;
|
|
1793
|
+
return contentType;
|
|
1794
|
+
}
|
|
1795
|
+
prefixHeaders(contentType) {
|
|
1796
|
+
const { rawHeaders, workflowHeaders, failureHeaders } = this.headers;
|
|
1797
|
+
const isCall = this.stepInfo?.lazyStep.stepType === "Call";
|
|
1798
|
+
return {
|
|
1799
|
+
headers: {
|
|
1800
|
+
...rawHeaders,
|
|
1801
|
+
...addPrefixToHeaders(workflowHeaders, isCall ? "Upstash-Callback-" : "Upstash-"),
|
|
1802
|
+
...addPrefixToHeaders(failureHeaders, "Upstash-Failure-Callback-"),
|
|
1803
|
+
...isCall ? addPrefixToHeaders(failureHeaders, "Upstash-Callback-Failure-Callback-") : {}
|
|
1804
|
+
},
|
|
1805
|
+
contentType
|
|
1806
|
+
};
|
|
1807
|
+
}
|
|
1808
|
+
};
|
|
1809
|
+
function addPrefixToHeaders(headers, prefix) {
|
|
1810
|
+
const prefixedHeaders = {};
|
|
1811
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
1812
|
+
prefixedHeaders[`${prefix}${key}`] = value;
|
|
1813
|
+
}
|
|
1814
|
+
return prefixedHeaders;
|
|
1815
|
+
}
|
|
1816
|
+
var prepareFlowControl = (flowControl) => {
|
|
1817
|
+
const parallelism = flowControl.parallelism?.toString();
|
|
1818
|
+
const rate = (flowControl.rate ?? flowControl.ratePerSecond)?.toString();
|
|
1819
|
+
const period = typeof flowControl.period === "number" ? `${flowControl.period}s` : flowControl.period;
|
|
1820
|
+
const controlValue = [
|
|
1821
|
+
parallelism ? `parallelism=${parallelism}` : void 0,
|
|
1822
|
+
rate ? `rate=${rate}` : void 0,
|
|
1823
|
+
period ? `period=${period}` : void 0
|
|
1824
|
+
].filter(Boolean);
|
|
1825
|
+
if (controlValue.length === 0) {
|
|
1826
|
+
throw new QstashError4("Provide at least one of parallelism or ratePerSecond for flowControl");
|
|
1827
|
+
}
|
|
1828
|
+
return {
|
|
1829
|
+
flowControlKey: flowControl.key,
|
|
1830
|
+
flowControlValue: controlValue.join(", ")
|
|
1831
|
+
};
|
|
1832
|
+
};
|
|
1833
|
+
var getHeaders = (params) => {
|
|
1834
|
+
const workflowHeaders = new WorkflowHeaders(params);
|
|
1835
|
+
return workflowHeaders.getHeaders();
|
|
1836
|
+
};
|
|
1837
|
+
|
|
1838
|
+
// src/qstash/submit-steps.ts
|
|
1839
|
+
var submitParallelSteps = async ({
|
|
1840
|
+
context,
|
|
1841
|
+
steps,
|
|
1842
|
+
initialStepCount,
|
|
1843
|
+
invokeCount,
|
|
1844
|
+
telemetry,
|
|
1845
|
+
debug
|
|
1846
|
+
}) => {
|
|
1847
|
+
const planSteps = steps.map(
|
|
1848
|
+
(step, index) => step.getPlanStep(steps.length, initialStepCount + index)
|
|
1849
|
+
);
|
|
1850
|
+
await debug?.log("SUBMIT", "SUBMIT_STEP", {
|
|
1851
|
+
length: planSteps.length,
|
|
1852
|
+
steps: planSteps
|
|
1853
|
+
});
|
|
1854
|
+
const result = await context.qstashClient.batch(
|
|
1855
|
+
planSteps.map((planStep) => {
|
|
1856
|
+
const { headers } = getHeaders({
|
|
1857
|
+
initHeaderValue: "false",
|
|
1858
|
+
workflowConfig: {
|
|
1859
|
+
workflowRunId: context.workflowRunId,
|
|
1860
|
+
workflowUrl: context.url,
|
|
1861
|
+
failureUrl: context.failureUrl,
|
|
1862
|
+
retries: context.retries,
|
|
1863
|
+
flowControl: context.flowControl,
|
|
1864
|
+
telemetry
|
|
1865
|
+
},
|
|
1866
|
+
userHeaders: context.headers,
|
|
1867
|
+
invokeCount
|
|
1868
|
+
});
|
|
1869
|
+
return {
|
|
1870
|
+
headers,
|
|
1871
|
+
method: "POST",
|
|
1872
|
+
url: context.url,
|
|
1873
|
+
body: JSON.stringify(planStep),
|
|
1874
|
+
notBefore: planStep.sleepUntil,
|
|
1875
|
+
delay: planStep.sleepFor
|
|
1876
|
+
};
|
|
1877
|
+
})
|
|
1878
|
+
);
|
|
1879
|
+
await debug?.log("INFO", "SUBMIT_STEP", {
|
|
1880
|
+
messageIds: result.map((message) => {
|
|
1881
|
+
return {
|
|
1882
|
+
message: message.messageId
|
|
1883
|
+
};
|
|
1884
|
+
})
|
|
1885
|
+
});
|
|
1886
|
+
throw new WorkflowAbort(planSteps[0].stepName, planSteps[0]);
|
|
1887
|
+
};
|
|
1888
|
+
var submitSingleStep = async ({
|
|
1889
|
+
context,
|
|
1890
|
+
lazyStep,
|
|
1891
|
+
stepId,
|
|
1892
|
+
invokeCount,
|
|
1893
|
+
concurrency,
|
|
1894
|
+
telemetry,
|
|
1895
|
+
debug
|
|
1896
|
+
}) => {
|
|
1897
|
+
const resultStep = await lazyStep.getResultStep(concurrency, stepId);
|
|
1898
|
+
await debug?.log("INFO", "RUN_SINGLE", {
|
|
1899
|
+
fromRequest: false,
|
|
1900
|
+
step: resultStep,
|
|
1901
|
+
stepCount: stepId
|
|
1902
|
+
});
|
|
1903
|
+
const { headers } = lazyStep.getHeaders({
|
|
1904
|
+
context,
|
|
1905
|
+
step: resultStep,
|
|
1906
|
+
invokeCount,
|
|
1907
|
+
telemetry
|
|
1908
|
+
});
|
|
1909
|
+
const body = lazyStep.getBody({
|
|
1910
|
+
context,
|
|
1911
|
+
step: resultStep,
|
|
1912
|
+
headers,
|
|
1913
|
+
invokeCount,
|
|
1914
|
+
telemetry
|
|
1915
|
+
});
|
|
1916
|
+
await debug?.log("SUBMIT", "SUBMIT_STEP", {
|
|
1917
|
+
length: 1,
|
|
1918
|
+
steps: [resultStep]
|
|
1919
|
+
});
|
|
1920
|
+
const submitResult = await lazyStep.submitStep({
|
|
1921
|
+
context,
|
|
1922
|
+
body,
|
|
1923
|
+
headers,
|
|
1924
|
+
isParallel: concurrency !== NO_CONCURRENCY,
|
|
1925
|
+
invokeCount,
|
|
1926
|
+
step: resultStep,
|
|
1927
|
+
telemetry
|
|
1928
|
+
});
|
|
1929
|
+
await debug?.log("INFO", "SUBMIT_STEP", {
|
|
1930
|
+
messageIds: submitResult.map((message) => {
|
|
1931
|
+
return {
|
|
1932
|
+
message: message.messageId
|
|
1933
|
+
};
|
|
1934
|
+
})
|
|
1935
|
+
});
|
|
1936
|
+
return resultStep;
|
|
1637
1937
|
};
|
|
1638
1938
|
|
|
1639
1939
|
// src/context/auto-executor.ts
|
|
1640
|
-
import { QstashError as QstashError4 } from "@upstash/qstash";
|
|
1641
1940
|
var AutoExecutor = class _AutoExecutor {
|
|
1642
1941
|
context;
|
|
1643
1942
|
promises = /* @__PURE__ */ new WeakMap();
|
|
@@ -1741,14 +2040,16 @@ var AutoExecutor = class _AutoExecutor {
|
|
|
1741
2040
|
});
|
|
1742
2041
|
return lazyStep.parseOut(step.out);
|
|
1743
2042
|
}
|
|
1744
|
-
const resultStep = await
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
2043
|
+
const resultStep = await submitSingleStep({
|
|
2044
|
+
context: this.context,
|
|
2045
|
+
lazyStep,
|
|
2046
|
+
stepId: this.stepCount,
|
|
2047
|
+
invokeCount: this.invokeCount,
|
|
2048
|
+
concurrency: 1,
|
|
2049
|
+
telemetry: this.telemetry,
|
|
2050
|
+
debug: this.debug
|
|
1749
2051
|
});
|
|
1750
|
-
|
|
1751
|
-
return resultStep.out;
|
|
2052
|
+
throw new WorkflowAbort(lazyStep.stepName, resultStep);
|
|
1752
2053
|
}
|
|
1753
2054
|
/**
|
|
1754
2055
|
* Runs steps in parallel.
|
|
@@ -1776,10 +2077,14 @@ var AutoExecutor = class _AutoExecutor {
|
|
|
1776
2077
|
});
|
|
1777
2078
|
switch (parallelCallState) {
|
|
1778
2079
|
case "first": {
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
2080
|
+
await submitParallelSteps({
|
|
2081
|
+
context: this.context,
|
|
2082
|
+
steps: parallelSteps,
|
|
2083
|
+
initialStepCount,
|
|
2084
|
+
invokeCount: this.invokeCount,
|
|
2085
|
+
telemetry: this.telemetry,
|
|
2086
|
+
debug: this.debug
|
|
2087
|
+
});
|
|
1783
2088
|
break;
|
|
1784
2089
|
}
|
|
1785
2090
|
case "partial": {
|
|
@@ -1793,13 +2098,18 @@ var AutoExecutor = class _AutoExecutor {
|
|
|
1793
2098
|
validateStep(parallelSteps[stepIndex], planStep);
|
|
1794
2099
|
try {
|
|
1795
2100
|
const parallelStep = parallelSteps[stepIndex];
|
|
1796
|
-
const resultStep = await
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
2101
|
+
const resultStep = await submitSingleStep({
|
|
2102
|
+
context: this.context,
|
|
2103
|
+
lazyStep: parallelStep,
|
|
2104
|
+
stepId: planStep.targetStep,
|
|
2105
|
+
invokeCount: this.invokeCount,
|
|
2106
|
+
concurrency: parallelSteps.length,
|
|
2107
|
+
telemetry: this.telemetry,
|
|
2108
|
+
debug: this.debug
|
|
2109
|
+
});
|
|
2110
|
+
throw new WorkflowAbort(parallelStep.stepName, resultStep);
|
|
1801
2111
|
} catch (error) {
|
|
1802
|
-
if (error instanceof WorkflowAbort || error instanceof
|
|
2112
|
+
if (error instanceof WorkflowAbort || error instanceof QstashError5 && error.status === 400) {
|
|
1803
2113
|
throw error;
|
|
1804
2114
|
}
|
|
1805
2115
|
throw new WorkflowError(
|
|
@@ -1855,128 +2165,6 @@ var AutoExecutor = class _AutoExecutor {
|
|
|
1855
2165
|
return "discard";
|
|
1856
2166
|
}
|
|
1857
2167
|
}
|
|
1858
|
-
/**
|
|
1859
|
-
* sends the steps to QStash as batch
|
|
1860
|
-
*
|
|
1861
|
-
* @param steps steps to send
|
|
1862
|
-
*/
|
|
1863
|
-
async submitStepsToQStash(steps, lazySteps) {
|
|
1864
|
-
if (steps.length === 0) {
|
|
1865
|
-
throw new WorkflowError(
|
|
1866
|
-
`Unable to submit steps to QStash. Provided list is empty. Current step: ${this.stepCount}`
|
|
1867
|
-
);
|
|
1868
|
-
}
|
|
1869
|
-
await this.debug?.log("SUBMIT", "SUBMIT_STEP", {
|
|
1870
|
-
length: steps.length,
|
|
1871
|
-
steps
|
|
1872
|
-
});
|
|
1873
|
-
if (steps[0].waitEventId && steps.length === 1) {
|
|
1874
|
-
const waitStep = steps[0];
|
|
1875
|
-
const { headers, timeoutHeaders } = getHeaders({
|
|
1876
|
-
initHeaderValue: "false",
|
|
1877
|
-
workflowRunId: this.context.workflowRunId,
|
|
1878
|
-
workflowUrl: this.context.url,
|
|
1879
|
-
userHeaders: this.context.headers,
|
|
1880
|
-
step: waitStep,
|
|
1881
|
-
failureUrl: this.context.failureUrl,
|
|
1882
|
-
retries: this.context.retries,
|
|
1883
|
-
telemetry: this.telemetry,
|
|
1884
|
-
invokeCount: this.invokeCount,
|
|
1885
|
-
flowControl: this.context.flowControl
|
|
1886
|
-
});
|
|
1887
|
-
const waitBody = {
|
|
1888
|
-
url: this.context.url,
|
|
1889
|
-
timeout: waitStep.timeout,
|
|
1890
|
-
timeoutBody: void 0,
|
|
1891
|
-
timeoutUrl: this.context.url,
|
|
1892
|
-
timeoutHeaders,
|
|
1893
|
-
step: {
|
|
1894
|
-
stepId: waitStep.stepId,
|
|
1895
|
-
stepType: "Wait",
|
|
1896
|
-
stepName: waitStep.stepName,
|
|
1897
|
-
concurrent: waitStep.concurrent,
|
|
1898
|
-
targetStep: waitStep.targetStep
|
|
1899
|
-
}
|
|
1900
|
-
};
|
|
1901
|
-
await this.context.qstashClient.http.request({
|
|
1902
|
-
path: ["v2", "wait", waitStep.waitEventId],
|
|
1903
|
-
body: JSON.stringify(waitBody),
|
|
1904
|
-
headers,
|
|
1905
|
-
method: "POST",
|
|
1906
|
-
parseResponseAsJson: false
|
|
1907
|
-
});
|
|
1908
|
-
throw new WorkflowAbort(waitStep.stepName, waitStep);
|
|
1909
|
-
}
|
|
1910
|
-
if (steps.length === 1 && lazySteps[0] instanceof LazyInvokeStep) {
|
|
1911
|
-
const invokeStep = steps[0];
|
|
1912
|
-
const lazyInvokeStep = lazySteps[0];
|
|
1913
|
-
await invokeWorkflow({
|
|
1914
|
-
settings: lazyInvokeStep.params,
|
|
1915
|
-
invokeStep,
|
|
1916
|
-
context: this.context,
|
|
1917
|
-
invokeCount: this.invokeCount,
|
|
1918
|
-
telemetry: this.telemetry
|
|
1919
|
-
});
|
|
1920
|
-
throw new WorkflowAbort(invokeStep.stepName, invokeStep);
|
|
1921
|
-
}
|
|
1922
|
-
const result = await this.context.qstashClient.batch(
|
|
1923
|
-
steps.map((singleStep, index) => {
|
|
1924
|
-
const lazyStep = lazySteps[index];
|
|
1925
|
-
const { headers } = getHeaders({
|
|
1926
|
-
initHeaderValue: "false",
|
|
1927
|
-
workflowRunId: this.context.workflowRunId,
|
|
1928
|
-
workflowUrl: this.context.url,
|
|
1929
|
-
userHeaders: this.context.headers,
|
|
1930
|
-
step: singleStep,
|
|
1931
|
-
failureUrl: this.context.failureUrl,
|
|
1932
|
-
retries: this.context.retries,
|
|
1933
|
-
callRetries: lazyStep instanceof LazyCallStep ? lazyStep.retries : void 0,
|
|
1934
|
-
callTimeout: lazyStep instanceof LazyCallStep ? lazyStep.timeout : void 0,
|
|
1935
|
-
telemetry: this.telemetry,
|
|
1936
|
-
invokeCount: this.invokeCount,
|
|
1937
|
-
flowControl: this.context.flowControl,
|
|
1938
|
-
callFlowControl: lazyStep instanceof LazyCallStep ? lazyStep.flowControl : void 0
|
|
1939
|
-
});
|
|
1940
|
-
const willWait = singleStep.concurrent === NO_CONCURRENCY || singleStep.stepId === 0;
|
|
1941
|
-
singleStep.out = JSON.stringify(singleStep.out);
|
|
1942
|
-
return singleStep.callUrl && lazyStep instanceof LazyCallStep ? (
|
|
1943
|
-
// if the step is a third party call, we call the third party
|
|
1944
|
-
// url (singleStep.callUrl) and pass information about the workflow
|
|
1945
|
-
// in the headers (handled in getHeaders). QStash makes the request
|
|
1946
|
-
// to callUrl and returns the result to Workflow endpoint.
|
|
1947
|
-
// handleThirdPartyCallResult method sends the result of the third
|
|
1948
|
-
// party call to QStash.
|
|
1949
|
-
{
|
|
1950
|
-
headers,
|
|
1951
|
-
method: singleStep.callMethod,
|
|
1952
|
-
body: JSON.stringify(singleStep.callBody),
|
|
1953
|
-
url: singleStep.callUrl
|
|
1954
|
-
}
|
|
1955
|
-
) : (
|
|
1956
|
-
// if the step is not a third party call, we use workflow
|
|
1957
|
-
// endpoint (context.url) as URL when calling QStash. QStash
|
|
1958
|
-
// calls us back with the updated steps list.
|
|
1959
|
-
{
|
|
1960
|
-
headers,
|
|
1961
|
-
method: "POST",
|
|
1962
|
-
body: JSON.stringify(singleStep),
|
|
1963
|
-
url: this.context.url,
|
|
1964
|
-
notBefore: willWait ? singleStep.sleepUntil : void 0,
|
|
1965
|
-
delay: willWait ? singleStep.sleepFor : void 0
|
|
1966
|
-
}
|
|
1967
|
-
);
|
|
1968
|
-
})
|
|
1969
|
-
);
|
|
1970
|
-
const _result = result;
|
|
1971
|
-
await this.debug?.log("INFO", "SUBMIT_STEP", {
|
|
1972
|
-
messageIds: _result.map((message) => {
|
|
1973
|
-
return {
|
|
1974
|
-
message: message.messageId
|
|
1975
|
-
};
|
|
1976
|
-
})
|
|
1977
|
-
});
|
|
1978
|
-
throw new WorkflowAbort(steps[0].stepName, steps[0]);
|
|
1979
|
-
}
|
|
1980
2168
|
/**
|
|
1981
2169
|
* Get the promise by executing the lazt steps list. If there is a single
|
|
1982
2170
|
* step, we call `runSingle`. Otherwise `runParallel` is called.
|
|
@@ -2173,7 +2361,7 @@ var WorkflowApi = class extends BaseWorkflowApi {
|
|
|
2173
2361
|
};
|
|
2174
2362
|
|
|
2175
2363
|
// src/agents/index.ts
|
|
2176
|
-
import { createOpenAI
|
|
2364
|
+
import { createOpenAI } from "@ai-sdk/openai";
|
|
2177
2365
|
|
|
2178
2366
|
// src/agents/agent.ts
|
|
2179
2367
|
import { z } from "zod";
|
|
@@ -2379,11 +2567,12 @@ var WorkflowAgents = class {
|
|
|
2379
2567
|
*/
|
|
2380
2568
|
openai(...params) {
|
|
2381
2569
|
const [model, settings] = params;
|
|
2382
|
-
const { baseURL, apiKey, ...otherSettings } = settings ?? {};
|
|
2570
|
+
const { baseURL, apiKey, callSettings, ...otherSettings } = settings ?? {};
|
|
2383
2571
|
const openaiModel = this.AISDKModel({
|
|
2384
2572
|
context: this.context,
|
|
2385
|
-
provider:
|
|
2386
|
-
providerParams: { baseURL, apiKey, compatibility: "strict" }
|
|
2573
|
+
provider: createOpenAI,
|
|
2574
|
+
providerParams: { baseURL, apiKey, compatibility: "strict" },
|
|
2575
|
+
agentCallParams: callSettings
|
|
2387
2576
|
});
|
|
2388
2577
|
return openaiModel(model, otherSettings);
|
|
2389
2578
|
}
|
|
@@ -2611,60 +2800,42 @@ var WorkflowContext = class {
|
|
|
2611
2800
|
}
|
|
2612
2801
|
await this.addStep(new LazySleepUntilStep(stepName, time));
|
|
2613
2802
|
}
|
|
2614
|
-
/**
|
|
2615
|
-
* Makes a third party call through QStash in order to make a
|
|
2616
|
-
* network call without consuming any runtime.
|
|
2617
|
-
*
|
|
2618
|
-
* ```ts
|
|
2619
|
-
* const { status, body } = await context.call<string>(
|
|
2620
|
-
* "post call step",
|
|
2621
|
-
* {
|
|
2622
|
-
* url: "https://www.some-endpoint.com/api",
|
|
2623
|
-
* method: "POST",
|
|
2624
|
-
* body: "my-payload"
|
|
2625
|
-
* }
|
|
2626
|
-
* );
|
|
2627
|
-
* ```
|
|
2628
|
-
*
|
|
2629
|
-
* tries to parse the result of the request as JSON. If it's
|
|
2630
|
-
* not a JSON which can be parsed, simply returns the response
|
|
2631
|
-
* body as it is.
|
|
2632
|
-
*
|
|
2633
|
-
* @param stepName
|
|
2634
|
-
* @param url url to call
|
|
2635
|
-
* @param method call method. "GET" by default.
|
|
2636
|
-
* @param body call body
|
|
2637
|
-
* @param headers call headers
|
|
2638
|
-
* @param retries number of call retries. 0 by default
|
|
2639
|
-
* @param timeout max duration to wait for the endpoint to respond. in seconds.
|
|
2640
|
-
* @returns call result as {
|
|
2641
|
-
* status: number;
|
|
2642
|
-
* body: unknown;
|
|
2643
|
-
* header: Record<string, string[]>
|
|
2644
|
-
* }
|
|
2645
|
-
*/
|
|
2646
2803
|
async call(stepName, settings) {
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2804
|
+
let callStep;
|
|
2805
|
+
if ("workflow" in settings) {
|
|
2806
|
+
const url = getNewUrlFromWorkflowId(this.url, settings.workflow.workflowId);
|
|
2807
|
+
callStep = new LazyCallStep(
|
|
2808
|
+
stepName,
|
|
2809
|
+
url,
|
|
2810
|
+
"POST",
|
|
2811
|
+
settings.body,
|
|
2812
|
+
settings.headers || {},
|
|
2813
|
+
settings.retries || 0,
|
|
2814
|
+
settings.timeout,
|
|
2815
|
+
settings.flowControl ?? settings.workflow.options.flowControl
|
|
2816
|
+
);
|
|
2817
|
+
} else {
|
|
2818
|
+
const {
|
|
2819
|
+
url,
|
|
2820
|
+
method = "GET",
|
|
2821
|
+
body,
|
|
2822
|
+
headers = {},
|
|
2823
|
+
retries = 0,
|
|
2824
|
+
timeout,
|
|
2825
|
+
flowControl
|
|
2826
|
+
} = settings;
|
|
2827
|
+
callStep = new LazyCallStep(
|
|
2658
2828
|
stepName,
|
|
2659
2829
|
url,
|
|
2660
2830
|
method,
|
|
2661
|
-
|
|
2831
|
+
body,
|
|
2662
2832
|
headers,
|
|
2663
2833
|
retries,
|
|
2664
2834
|
timeout,
|
|
2665
2835
|
flowControl
|
|
2666
|
-
)
|
|
2667
|
-
|
|
2836
|
+
);
|
|
2837
|
+
}
|
|
2838
|
+
return await this.addStep(callStep);
|
|
2668
2839
|
}
|
|
2669
2840
|
/**
|
|
2670
2841
|
* Pauses workflow execution until a specific event occurs or a timeout is reached.
|
|
@@ -3332,8 +3503,8 @@ export {
|
|
|
3332
3503
|
getWorkflowRunId,
|
|
3333
3504
|
StepTypes,
|
|
3334
3505
|
triggerFirstInvocation,
|
|
3335
|
-
serveManyBase,
|
|
3336
3506
|
WorkflowTool,
|
|
3507
|
+
serveManyBase,
|
|
3337
3508
|
WorkflowContext,
|
|
3338
3509
|
WorkflowLogger,
|
|
3339
3510
|
serveBase,
|