@upstash/workflow 0.2.12 → 0.2.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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.7";
45
+ var VERSION = "v0.2.14";
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,116 +809,72 @@ 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.`
812
+ var triggerFirstInvocation = async (params) => {
813
+ const firstInvocationParams = Array.isArray(params) ? params : [params];
814
+ const workflowContextClient = firstInvocationParams[0].workflowContext.qstashClient;
815
+ const invocationBatch = firstInvocationParams.map(
816
+ ({ workflowContext, useJSONContent, telemetry, invokeCount, delay }) => {
817
+ const { headers } = getHeaders({
818
+ initHeaderValue: "true",
819
+ workflowConfig: {
820
+ workflowRunId: workflowContext.workflowRunId,
821
+ workflowUrl: workflowContext.url,
822
+ failureUrl: workflowContext.failureUrl,
823
+ retries: workflowContext.retries,
824
+ telemetry,
825
+ flowControl: workflowContext.flowControl,
826
+ useJSONContent: useJSONContent ?? false
827
+ },
828
+ invokeCount: invokeCount ?? 0,
829
+ userHeaders: workflowContext.headers
581
830
  });
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 };
831
+ if (workflowContext.headers.get("content-type")) {
832
+ headers["content-type"] = workflowContext.headers.get("content-type");
587
833
  }
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);
634
- const result = await workflowContext.qstashClient.publish({
635
- headers,
636
- method: "POST",
637
- body,
638
- url: workflowContext.url
639
- });
640
- if (result.deduplicated) {
641
- await debug?.log("WARN", "SUBMIT_FIRST_INVOCATION", {
642
- message: `Workflow run ${workflowContext.workflowRunId} already exists. A new one isn't created.`,
834
+ if (useJSONContent) {
835
+ headers["content-type"] = "application/json";
836
+ }
837
+ const body = typeof workflowContext.requestPayload === "string" ? workflowContext.requestPayload : JSON.stringify(workflowContext.requestPayload);
838
+ return {
643
839
  headers,
644
- requestPayload: workflowContext.requestPayload,
840
+ method: "POST",
841
+ body,
645
842
  url: workflowContext.url,
646
- messageId: result.messageId
647
- });
843
+ delay
844
+ };
845
+ }
846
+ );
847
+ try {
848
+ const results = await workflowContextClient.batch(invocationBatch);
849
+ const invocationStatuses = [];
850
+ for (let i = 0; i < results.length; i++) {
851
+ const result = results[i];
852
+ const invocationParams = firstInvocationParams[i];
853
+ if (result.deduplicated) {
854
+ await invocationParams.debug?.log("WARN", "SUBMIT_FIRST_INVOCATION", {
855
+ message: `Workflow run ${invocationParams.workflowContext.workflowRunId} already exists. A new one isn't created.`,
856
+ headers: invocationBatch[i].headers,
857
+ requestPayload: invocationParams.workflowContext.requestPayload,
858
+ url: invocationParams.workflowContext.url,
859
+ messageId: result.messageId
860
+ });
861
+ invocationStatuses.push("workflow-run-already-exists");
862
+ } else {
863
+ await invocationParams.debug?.log("SUBMIT", "SUBMIT_FIRST_INVOCATION", {
864
+ headers: invocationBatch[i].headers,
865
+ requestPayload: invocationParams.workflowContext.requestPayload,
866
+ url: invocationParams.workflowContext.url,
867
+ messageId: result.messageId
868
+ });
869
+ invocationStatuses.push("success");
870
+ }
871
+ }
872
+ const hasAnyDeduplicated = invocationStatuses.some(
873
+ (status) => status === "workflow-run-already-exists"
874
+ );
875
+ if (hasAnyDeduplicated) {
648
876
  return ok("workflow-run-already-exists");
649
877
  } else {
650
- await debug?.log("SUBMIT", "SUBMIT_FIRST_INVOCATION", {
651
- headers,
652
- requestPayload: workflowContext.requestPayload,
653
- url: workflowContext.url,
654
- messageId: result.messageId
655
- });
656
878
  return ok("success");
657
879
  }
658
880
  } catch (error) {
@@ -791,14 +1013,16 @@ ${atob(callbackMessage.body ?? "")}`
791
1013
  const userHeaders = recreateUserHeaders(request.headers);
792
1014
  const { headers: requestHeaders } = getHeaders({
793
1015
  initHeaderValue: "false",
794
- workflowRunId,
795
- workflowUrl,
1016
+ workflowConfig: {
1017
+ workflowRunId,
1018
+ workflowUrl,
1019
+ failureUrl,
1020
+ retries,
1021
+ telemetry,
1022
+ flowControl
1023
+ },
796
1024
  userHeaders,
797
- failureUrl,
798
- retries,
799
- telemetry,
800
- invokeCount: Number(invokeCount),
801
- flowControl
1025
+ invokeCount: Number(invokeCount)
802
1026
  });
803
1027
  const callResponse = {
804
1028
  status: callbackMessage.status,
@@ -844,154 +1068,6 @@ var getTelemetryHeaders = (telemetry) => {
844
1068
  [TELEMETRY_HEADER_RUNTIME]: telemetry.runtime ?? "unknown"
845
1069
  };
846
1070
  };
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
1071
  var verifyRequest = async (body, signature, verifier) => {
996
1072
  if (!verifier) {
997
1073
  return;
@@ -1010,286 +1086,11 @@ var verifyRequest = async (body, signature, verifier) => {
1010
1086
  } catch (error) {
1011
1087
  throw new WorkflowError(
1012
1088
  `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;
1089
+
1090
+ If signature is missing, trigger the workflow endpoint by publishing your request to QStash instead of calling it directly.
1091
+
1092
+ If you want to disable QStash Verification, you should clear env variables QSTASH_CURRENT_SIGNING_KEY and QSTASH_NEXT_SIGNING_KEY`
1093
+ );
1293
1094
  }
1294
1095
  };
1295
1096
 
@@ -1302,6 +1103,11 @@ var BaseLazyStep = class _BaseLazyStep {
1302
1103
  "A workflow step name cannot be undefined or an empty string. Please provide a name for your workflow step."
1303
1104
  );
1304
1105
  }
1106
+ if (typeof stepName !== "string") {
1107
+ console.warn(
1108
+ "Workflow Warning: A workflow step name must be a string. In a future release, this will throw an error."
1109
+ );
1110
+ }
1305
1111
  this.stepName = stepName;
1306
1112
  }
1307
1113
  /**
@@ -1351,6 +1157,40 @@ var BaseLazyStep = class _BaseLazyStep {
1351
1157
  return stepOut;
1352
1158
  }
1353
1159
  }
1160
+ getBody({ step }) {
1161
+ step.out = JSON.stringify(step.out);
1162
+ return JSON.stringify(step);
1163
+ }
1164
+ getHeaders({ context, telemetry, invokeCount, step }) {
1165
+ return getHeaders({
1166
+ initHeaderValue: "false",
1167
+ workflowConfig: {
1168
+ workflowRunId: context.workflowRunId,
1169
+ workflowUrl: context.url,
1170
+ failureUrl: context.failureUrl,
1171
+ retries: context.retries,
1172
+ useJSONContent: false,
1173
+ telemetry,
1174
+ flowControl: context.flowControl
1175
+ },
1176
+ userHeaders: context.headers,
1177
+ invokeCount,
1178
+ stepInfo: {
1179
+ step,
1180
+ lazyStep: this
1181
+ }
1182
+ });
1183
+ }
1184
+ async submitStep({ context, body, headers }) {
1185
+ return await context.qstashClient.batch([
1186
+ {
1187
+ body,
1188
+ headers,
1189
+ method: "POST",
1190
+ url: context.url
1191
+ }
1192
+ ]);
1193
+ }
1354
1194
  };
1355
1195
  var LazyFunctionStep = class extends BaseLazyStep {
1356
1196
  stepFunction;
@@ -1410,6 +1250,17 @@ var LazySleepStep = class extends BaseLazyStep {
1410
1250
  concurrent
1411
1251
  });
1412
1252
  }
1253
+ async submitStep({ context, body, headers, isParallel }) {
1254
+ return await context.qstashClient.batch([
1255
+ {
1256
+ body,
1257
+ headers,
1258
+ method: "POST",
1259
+ url: context.url,
1260
+ delay: isParallel ? void 0 : this.sleep
1261
+ }
1262
+ ]);
1263
+ }
1413
1264
  };
1414
1265
  var LazySleepUntilStep = class extends BaseLazyStep {
1415
1266
  sleepUntil;
@@ -1441,6 +1292,17 @@ var LazySleepUntilStep = class extends BaseLazyStep {
1441
1292
  safeParseOut() {
1442
1293
  return void 0;
1443
1294
  }
1295
+ async submitStep({ context, body, headers, isParallel }) {
1296
+ return await context.qstashClient.batch([
1297
+ {
1298
+ body,
1299
+ headers,
1300
+ method: "POST",
1301
+ url: context.url,
1302
+ notBefore: isParallel ? void 0 : this.sleepUntil
1303
+ }
1304
+ ]);
1305
+ }
1444
1306
  };
1445
1307
  var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
1446
1308
  url;
@@ -1502,7 +1364,7 @@ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
1502
1364
  return { header, status, body };
1503
1365
  }
1504
1366
  }
1505
- static applicationHeaders = /* @__PURE__ */ new Set([
1367
+ static applicationContentTypes = [
1506
1368
  "application/json",
1507
1369
  "application/xml",
1508
1370
  "application/javascript",
@@ -1511,12 +1373,12 @@ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
1511
1373
  "application/ld+json",
1512
1374
  "application/rss+xml",
1513
1375
  "application/atom+xml"
1514
- ]);
1376
+ ];
1515
1377
  static isText = (contentTypeHeader) => {
1516
1378
  if (!contentTypeHeader) {
1517
1379
  return false;
1518
1380
  }
1519
- if (_LazyCallStep.applicationHeaders.has(contentTypeHeader)) {
1381
+ if (_LazyCallStep.applicationContentTypes.some((type) => contentTypeHeader.includes(type))) {
1520
1382
  return true;
1521
1383
  }
1522
1384
  if (contentTypeHeader.startsWith("text/")) {
@@ -1524,6 +1386,58 @@ var LazyCallStep = class _LazyCallStep extends BaseLazyStep {
1524
1386
  }
1525
1387
  return false;
1526
1388
  };
1389
+ getBody({ step }) {
1390
+ if (!step.callUrl) {
1391
+ throw new WorkflowError("Incompatible step received in LazyCallStep.getBody");
1392
+ }
1393
+ return JSON.stringify(step.callBody);
1394
+ }
1395
+ getHeaders({ context, telemetry, invokeCount, step }) {
1396
+ const { headers, contentType } = super.getHeaders({ context, telemetry, invokeCount, step });
1397
+ headers["Upstash-Retries"] = this.retries.toString();
1398
+ headers[WORKFLOW_FEATURE_HEADER] = "WF_NoDelete,InitialBody";
1399
+ if (this.flowControl) {
1400
+ const { flowControlKey, flowControlValue } = prepareFlowControl(this.flowControl);
1401
+ headers["Upstash-Flow-Control-Key"] = flowControlKey;
1402
+ headers["Upstash-Flow-Control-Value"] = flowControlValue;
1403
+ }
1404
+ if (this.timeout) {
1405
+ headers["Upstash-Timeout"] = this.timeout.toString();
1406
+ }
1407
+ const forwardedHeaders = Object.fromEntries(
1408
+ Object.entries(this.headers).map(([header, value]) => [`Upstash-Forward-${header}`, value])
1409
+ );
1410
+ return {
1411
+ headers: {
1412
+ ...headers,
1413
+ ...forwardedHeaders,
1414
+ "Upstash-Callback": context.url,
1415
+ "Upstash-Callback-Workflow-RunId": context.workflowRunId,
1416
+ "Upstash-Callback-Workflow-CallType": "fromCallback",
1417
+ "Upstash-Callback-Workflow-Init": "false",
1418
+ "Upstash-Callback-Workflow-Url": context.url,
1419
+ "Upstash-Callback-Feature-Set": "LazyFetch,InitialBody",
1420
+ "Upstash-Callback-Forward-Upstash-Workflow-Callback": "true",
1421
+ "Upstash-Callback-Forward-Upstash-Workflow-StepId": step.stepId.toString(),
1422
+ "Upstash-Callback-Forward-Upstash-Workflow-StepName": this.stepName,
1423
+ "Upstash-Callback-Forward-Upstash-Workflow-StepType": this.stepType,
1424
+ "Upstash-Callback-Forward-Upstash-Workflow-Concurrent": step.concurrent.toString(),
1425
+ "Upstash-Callback-Forward-Upstash-Workflow-ContentType": contentType,
1426
+ "Upstash-Workflow-CallType": "toCallback"
1427
+ },
1428
+ contentType
1429
+ };
1430
+ }
1431
+ async submitStep({ context, headers }) {
1432
+ return await context.qstashClient.batch([
1433
+ {
1434
+ headers,
1435
+ body: JSON.stringify(this.body),
1436
+ method: this.method,
1437
+ url: this.url
1438
+ }
1439
+ ]);
1440
+ }
1527
1441
  };
1528
1442
  var LazyWaitForEventStep = class extends BaseLazyStep {
1529
1443
  eventId;
@@ -1563,6 +1477,57 @@ var LazyWaitForEventStep = class extends BaseLazyStep {
1563
1477
  eventData: BaseLazyStep.tryParsing(result.eventData)
1564
1478
  };
1565
1479
  }
1480
+ getHeaders({ context, telemetry, invokeCount, step }) {
1481
+ const headers = super.getHeaders({ context, telemetry, invokeCount, step });
1482
+ headers.headers["Upstash-Workflow-CallType"] = "step";
1483
+ return headers;
1484
+ }
1485
+ getBody({ context, step, headers, telemetry }) {
1486
+ if (!step.waitEventId) {
1487
+ throw new WorkflowError("Incompatible step received in LazyWaitForEventStep.getBody");
1488
+ }
1489
+ const timeoutHeaders = {
1490
+ // to include user headers:
1491
+ ...Object.fromEntries(Object.entries(headers).map(([header, value]) => [header, [value]])),
1492
+ // to include telemetry headers:
1493
+ ...telemetry ? Object.fromEntries(
1494
+ Object.entries(getTelemetryHeaders(telemetry)).map(([header, value]) => [
1495
+ header,
1496
+ [value]
1497
+ ])
1498
+ ) : {},
1499
+ // note: using WORKFLOW_ID_HEADER doesn't work, because Runid -> RunId:
1500
+ "Upstash-Workflow-Runid": [context.workflowRunId],
1501
+ [WORKFLOW_INIT_HEADER]: ["false"],
1502
+ [WORKFLOW_URL_HEADER]: [context.url],
1503
+ "Upstash-Workflow-CallType": ["step"]
1504
+ };
1505
+ const waitBody = {
1506
+ url: context.url,
1507
+ timeout: step.timeout,
1508
+ timeoutBody: void 0,
1509
+ timeoutUrl: context.url,
1510
+ timeoutHeaders,
1511
+ step: {
1512
+ stepId: step.stepId,
1513
+ stepType: "Wait",
1514
+ stepName: step.stepName,
1515
+ concurrent: step.concurrent,
1516
+ targetStep: step.targetStep
1517
+ }
1518
+ };
1519
+ return JSON.stringify(waitBody);
1520
+ }
1521
+ async submitStep({ context, body, headers }) {
1522
+ const result = await context.qstashClient.http.request({
1523
+ path: ["v2", "wait", this.eventId],
1524
+ body,
1525
+ headers,
1526
+ method: "POST",
1527
+ parseResponseAsJson: false
1528
+ });
1529
+ return [result];
1530
+ }
1566
1531
  };
1567
1532
  var LazyNotifyStep = class extends LazyFunctionStep {
1568
1533
  stepType = "Notify";
@@ -1588,6 +1553,10 @@ var LazyInvokeStep = class extends BaseLazyStep {
1588
1553
  stepType = "Invoke";
1589
1554
  params;
1590
1555
  allowUndefinedOut = false;
1556
+ /**
1557
+ * workflow id of the invoked workflow
1558
+ */
1559
+ workflowId;
1591
1560
  constructor(stepName, {
1592
1561
  workflow,
1593
1562
  body,
@@ -1605,6 +1574,11 @@ var LazyInvokeStep = class extends BaseLazyStep {
1605
1574
  retries,
1606
1575
  flowControl
1607
1576
  };
1577
+ const { workflowId } = workflow;
1578
+ if (!workflowId) {
1579
+ throw new WorkflowError("You can only invoke workflow which has a workflowId");
1580
+ }
1581
+ this.workflowId = workflowId;
1608
1582
  }
1609
1583
  getPlanStep(concurrent, targetStep) {
1610
1584
  return {
@@ -1634,10 +1608,348 @@ var LazyInvokeStep = class extends BaseLazyStep {
1634
1608
  body: BaseLazyStep.tryParsing(result.body)
1635
1609
  };
1636
1610
  }
1611
+ getBody({ context, step, telemetry, invokeCount }) {
1612
+ const { headers: invokerHeaders } = getHeaders({
1613
+ initHeaderValue: "false",
1614
+ workflowConfig: {
1615
+ workflowRunId: context.workflowRunId,
1616
+ workflowUrl: context.url,
1617
+ failureUrl: context.failureUrl,
1618
+ retries: context.retries,
1619
+ telemetry,
1620
+ flowControl: context.flowControl,
1621
+ useJSONContent: false
1622
+ },
1623
+ userHeaders: context.headers,
1624
+ invokeCount
1625
+ });
1626
+ invokerHeaders["Upstash-Workflow-Runid"] = context.workflowRunId;
1627
+ const request = {
1628
+ body: JSON.stringify(this.params.body),
1629
+ headers: Object.fromEntries(
1630
+ Object.entries(invokerHeaders).map((pairs) => [pairs[0], [pairs[1]]])
1631
+ ),
1632
+ workflowRunId: context.workflowRunId,
1633
+ workflowUrl: context.url,
1634
+ step
1635
+ };
1636
+ return JSON.stringify(request);
1637
+ }
1638
+ getHeaders({ context, telemetry, invokeCount }) {
1639
+ const {
1640
+ workflow,
1641
+ headers = {},
1642
+ workflowRunId = getWorkflowRunId(),
1643
+ retries,
1644
+ flowControl
1645
+ } = this.params;
1646
+ const newUrl = context.url.replace(/[^/]+$/, this.workflowId);
1647
+ const {
1648
+ retries: workflowRetries,
1649
+ failureFunction,
1650
+ failureUrl,
1651
+ useJSONContent,
1652
+ flowControl: workflowFlowControl
1653
+ } = workflow.options;
1654
+ const { headers: triggerHeaders, contentType } = getHeaders({
1655
+ initHeaderValue: "true",
1656
+ workflowConfig: {
1657
+ workflowRunId,
1658
+ workflowUrl: newUrl,
1659
+ retries: retries ?? workflowRetries,
1660
+ telemetry,
1661
+ failureUrl: failureFunction ? newUrl : failureUrl,
1662
+ flowControl: flowControl ?? workflowFlowControl,
1663
+ useJSONContent: useJSONContent ?? false
1664
+ },
1665
+ invokeCount: invokeCount + 1,
1666
+ userHeaders: new Headers(headers)
1667
+ });
1668
+ triggerHeaders["Upstash-Workflow-Invoke"] = "true";
1669
+ return { headers: triggerHeaders, contentType };
1670
+ }
1671
+ async submitStep({ context, body, headers }) {
1672
+ const newUrl = context.url.replace(/[^/]+$/, this.workflowId);
1673
+ const result = await context.qstashClient.publish({
1674
+ headers,
1675
+ method: "POST",
1676
+ body,
1677
+ url: newUrl
1678
+ });
1679
+ return [result];
1680
+ }
1681
+ };
1682
+
1683
+ // src/qstash/headers.ts
1684
+ var WorkflowHeaders = class {
1685
+ userHeaders;
1686
+ workflowConfig;
1687
+ invokeCount;
1688
+ initHeaderValue;
1689
+ stepInfo;
1690
+ headers;
1691
+ constructor({
1692
+ userHeaders,
1693
+ workflowConfig,
1694
+ invokeCount,
1695
+ initHeaderValue,
1696
+ stepInfo
1697
+ }) {
1698
+ this.userHeaders = userHeaders;
1699
+ this.workflowConfig = workflowConfig;
1700
+ this.invokeCount = invokeCount;
1701
+ this.initHeaderValue = initHeaderValue;
1702
+ this.stepInfo = stepInfo;
1703
+ this.headers = {
1704
+ rawHeaders: {},
1705
+ workflowHeaders: {},
1706
+ failureHeaders: {}
1707
+ };
1708
+ }
1709
+ getHeaders() {
1710
+ this.addBaseHeaders();
1711
+ this.addRetries();
1712
+ this.addFlowControl();
1713
+ this.addUserHeaders();
1714
+ this.addInvokeCount();
1715
+ this.addFailureUrl();
1716
+ const contentType = this.addContentType();
1717
+ return this.prefixHeaders(contentType);
1718
+ }
1719
+ addBaseHeaders() {
1720
+ this.headers.rawHeaders = {
1721
+ ...this.headers.rawHeaders,
1722
+ [WORKFLOW_INIT_HEADER]: this.initHeaderValue,
1723
+ [WORKFLOW_ID_HEADER]: this.workflowConfig.workflowRunId,
1724
+ [WORKFLOW_URL_HEADER]: this.workflowConfig.workflowUrl,
1725
+ [WORKFLOW_FEATURE_HEADER]: "LazyFetch,InitialBody",
1726
+ [WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION,
1727
+ ...this.workflowConfig.telemetry ? getTelemetryHeaders(this.workflowConfig.telemetry) : {},
1728
+ ...this.workflowConfig.telemetry && this.stepInfo?.lazyStep instanceof LazyCallStep && this.stepInfo.lazyStep.headers[AGENT_NAME_HEADER] ? { [TELEMETRY_HEADER_AGENT]: "true" } : {}
1729
+ };
1730
+ if (this.stepInfo?.lazyStep.stepType !== "Call") {
1731
+ this.headers.rawHeaders[`Upstash-Forward-${WORKFLOW_PROTOCOL_VERSION_HEADER}`] = WORKFLOW_PROTOCOL_VERSION;
1732
+ }
1733
+ }
1734
+ addInvokeCount() {
1735
+ if (this.invokeCount === void 0 || this.invokeCount === 0) {
1736
+ return;
1737
+ }
1738
+ const invokeCount = this.invokeCount.toString();
1739
+ this.headers.workflowHeaders[`Forward-${WORKFLOW_INVOKE_COUNT_HEADER}`] = invokeCount;
1740
+ if (this.workflowConfig.failureUrl) {
1741
+ this.headers.failureHeaders[`Forward-${WORKFLOW_INVOKE_COUNT_HEADER}`] = invokeCount;
1742
+ }
1743
+ if (this.stepInfo?.lazyStep instanceof LazyCallStep) {
1744
+ this.headers.rawHeaders[`Upstash-Forward-${WORKFLOW_INVOKE_COUNT_HEADER}`] = invokeCount;
1745
+ }
1746
+ }
1747
+ addRetries() {
1748
+ if (this.workflowConfig.retries === void 0 || this.workflowConfig.retries === DEFAULT_RETRIES) {
1749
+ return;
1750
+ }
1751
+ const retries = this.workflowConfig.retries.toString();
1752
+ this.headers.workflowHeaders["Retries"] = retries;
1753
+ if (this.workflowConfig.failureUrl) {
1754
+ this.headers.failureHeaders["Retries"] = retries;
1755
+ }
1756
+ }
1757
+ addFlowControl() {
1758
+ if (!this.workflowConfig.flowControl) {
1759
+ return;
1760
+ }
1761
+ const { flowControlKey, flowControlValue } = prepareFlowControl(
1762
+ this.workflowConfig.flowControl
1763
+ );
1764
+ this.headers.workflowHeaders["Flow-Control-Key"] = flowControlKey;
1765
+ this.headers.workflowHeaders["Flow-Control-Value"] = flowControlValue;
1766
+ if (this.workflowConfig.failureUrl) {
1767
+ this.headers.failureHeaders["Flow-Control-Key"] = flowControlKey;
1768
+ this.headers.failureHeaders["Flow-Control-Value"] = flowControlValue;
1769
+ }
1770
+ }
1771
+ addUserHeaders() {
1772
+ for (const [key, value] of this.userHeaders.entries()) {
1773
+ const forwardKey = `Forward-${key}`;
1774
+ this.headers.workflowHeaders[forwardKey] = value;
1775
+ if (this.workflowConfig.failureUrl) {
1776
+ this.headers.failureHeaders[forwardKey] = value;
1777
+ }
1778
+ }
1779
+ }
1780
+ addFailureUrl() {
1781
+ if (!this.workflowConfig.failureUrl) {
1782
+ return;
1783
+ }
1784
+ this.headers.workflowHeaders["Failure-Callback"] = this.workflowConfig.failureUrl;
1785
+ this.headers.failureHeaders[`Forward-${WORKFLOW_FAILURE_HEADER}`] = "true";
1786
+ this.headers.failureHeaders[`Forward-Upstash-Workflow-Failure-Callback`] = "true";
1787
+ this.headers.failureHeaders["Workflow-Runid"] = this.workflowConfig.workflowRunId;
1788
+ this.headers.failureHeaders["Workflow-Init"] = "false";
1789
+ this.headers.failureHeaders["Workflow-Url"] = this.workflowConfig.workflowUrl;
1790
+ this.headers.failureHeaders["Workflow-Calltype"] = "failureCall";
1791
+ this.headers.failureHeaders["Feature-Set"] = "LazyFetch,InitialBody";
1792
+ if (this.workflowConfig.retries !== void 0 && this.workflowConfig.retries !== DEFAULT_RETRIES) {
1793
+ this.headers.failureHeaders["Retries"] = this.workflowConfig.retries.toString();
1794
+ }
1795
+ }
1796
+ addContentType() {
1797
+ if (this.workflowConfig.useJSONContent) {
1798
+ this.headers.rawHeaders["content-type"] = "application/json";
1799
+ return "application/json";
1800
+ }
1801
+ const callHeaders = new Headers(
1802
+ this.stepInfo?.lazyStep instanceof LazyCallStep ? this.stepInfo.lazyStep.headers : {}
1803
+ );
1804
+ 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;
1805
+ this.headers.rawHeaders["content-type"] = contentType;
1806
+ return contentType;
1807
+ }
1808
+ prefixHeaders(contentType) {
1809
+ const { rawHeaders, workflowHeaders, failureHeaders } = this.headers;
1810
+ const isCall = this.stepInfo?.lazyStep.stepType === "Call";
1811
+ return {
1812
+ headers: {
1813
+ ...rawHeaders,
1814
+ ...addPrefixToHeaders(workflowHeaders, isCall ? "Upstash-Callback-" : "Upstash-"),
1815
+ ...addPrefixToHeaders(failureHeaders, "Upstash-Failure-Callback-"),
1816
+ ...isCall ? addPrefixToHeaders(failureHeaders, "Upstash-Callback-Failure-Callback-") : {}
1817
+ },
1818
+ contentType
1819
+ };
1820
+ }
1821
+ };
1822
+ function addPrefixToHeaders(headers, prefix) {
1823
+ const prefixedHeaders = {};
1824
+ for (const [key, value] of Object.entries(headers)) {
1825
+ prefixedHeaders[`${prefix}${key}`] = value;
1826
+ }
1827
+ return prefixedHeaders;
1828
+ }
1829
+ var prepareFlowControl = (flowControl) => {
1830
+ const parallelism = flowControl.parallelism?.toString();
1831
+ const rate = (flowControl.rate ?? flowControl.ratePerSecond)?.toString();
1832
+ const period = typeof flowControl.period === "number" ? `${flowControl.period}s` : flowControl.period;
1833
+ const controlValue = [
1834
+ parallelism ? `parallelism=${parallelism}` : void 0,
1835
+ rate ? `rate=${rate}` : void 0,
1836
+ period ? `period=${period}` : void 0
1837
+ ].filter(Boolean);
1838
+ if (controlValue.length === 0) {
1839
+ throw new QstashError4("Provide at least one of parallelism or ratePerSecond for flowControl");
1840
+ }
1841
+ return {
1842
+ flowControlKey: flowControl.key,
1843
+ flowControlValue: controlValue.join(", ")
1844
+ };
1845
+ };
1846
+ var getHeaders = (params) => {
1847
+ const workflowHeaders = new WorkflowHeaders(params);
1848
+ return workflowHeaders.getHeaders();
1849
+ };
1850
+
1851
+ // src/qstash/submit-steps.ts
1852
+ var submitParallelSteps = async ({
1853
+ context,
1854
+ steps,
1855
+ initialStepCount,
1856
+ invokeCount,
1857
+ telemetry,
1858
+ debug
1859
+ }) => {
1860
+ const planSteps = steps.map(
1861
+ (step, index) => step.getPlanStep(steps.length, initialStepCount + index)
1862
+ );
1863
+ await debug?.log("SUBMIT", "SUBMIT_STEP", {
1864
+ length: planSteps.length,
1865
+ steps: planSteps
1866
+ });
1867
+ const result = await context.qstashClient.batch(
1868
+ planSteps.map((planStep) => {
1869
+ const { headers } = getHeaders({
1870
+ initHeaderValue: "false",
1871
+ workflowConfig: {
1872
+ workflowRunId: context.workflowRunId,
1873
+ workflowUrl: context.url,
1874
+ failureUrl: context.failureUrl,
1875
+ retries: context.retries,
1876
+ flowControl: context.flowControl,
1877
+ telemetry
1878
+ },
1879
+ userHeaders: context.headers,
1880
+ invokeCount
1881
+ });
1882
+ return {
1883
+ headers,
1884
+ method: "POST",
1885
+ url: context.url,
1886
+ body: JSON.stringify(planStep),
1887
+ notBefore: planStep.sleepUntil,
1888
+ delay: planStep.sleepFor
1889
+ };
1890
+ })
1891
+ );
1892
+ await debug?.log("INFO", "SUBMIT_STEP", {
1893
+ messageIds: result.map((message) => {
1894
+ return {
1895
+ message: message.messageId
1896
+ };
1897
+ })
1898
+ });
1899
+ throw new WorkflowAbort(planSteps[0].stepName, planSteps[0]);
1900
+ };
1901
+ var submitSingleStep = async ({
1902
+ context,
1903
+ lazyStep,
1904
+ stepId,
1905
+ invokeCount,
1906
+ concurrency,
1907
+ telemetry,
1908
+ debug
1909
+ }) => {
1910
+ const resultStep = await lazyStep.getResultStep(concurrency, stepId);
1911
+ await debug?.log("INFO", "RUN_SINGLE", {
1912
+ fromRequest: false,
1913
+ step: resultStep,
1914
+ stepCount: stepId
1915
+ });
1916
+ const { headers } = lazyStep.getHeaders({
1917
+ context,
1918
+ step: resultStep,
1919
+ invokeCount,
1920
+ telemetry
1921
+ });
1922
+ const body = lazyStep.getBody({
1923
+ context,
1924
+ step: resultStep,
1925
+ headers,
1926
+ invokeCount,
1927
+ telemetry
1928
+ });
1929
+ await debug?.log("SUBMIT", "SUBMIT_STEP", {
1930
+ length: 1,
1931
+ steps: [resultStep]
1932
+ });
1933
+ const submitResult = await lazyStep.submitStep({
1934
+ context,
1935
+ body,
1936
+ headers,
1937
+ isParallel: concurrency !== NO_CONCURRENCY,
1938
+ invokeCount,
1939
+ step: resultStep,
1940
+ telemetry
1941
+ });
1942
+ await debug?.log("INFO", "SUBMIT_STEP", {
1943
+ messageIds: submitResult.map((message) => {
1944
+ return {
1945
+ message: message.messageId
1946
+ };
1947
+ })
1948
+ });
1949
+ return resultStep;
1637
1950
  };
1638
1951
 
1639
1952
  // src/context/auto-executor.ts
1640
- import { QstashError as QstashError4 } from "@upstash/qstash";
1641
1953
  var AutoExecutor = class _AutoExecutor {
1642
1954
  context;
1643
1955
  promises = /* @__PURE__ */ new WeakMap();
@@ -1741,14 +2053,16 @@ var AutoExecutor = class _AutoExecutor {
1741
2053
  });
1742
2054
  return lazyStep.parseOut(step.out);
1743
2055
  }
1744
- const resultStep = await lazyStep.getResultStep(NO_CONCURRENCY, this.stepCount);
1745
- await this.debug?.log("INFO", "RUN_SINGLE", {
1746
- fromRequest: false,
1747
- step: resultStep,
1748
- stepCount: this.stepCount
2056
+ const resultStep = await submitSingleStep({
2057
+ context: this.context,
2058
+ lazyStep,
2059
+ stepId: this.stepCount,
2060
+ invokeCount: this.invokeCount,
2061
+ concurrency: 1,
2062
+ telemetry: this.telemetry,
2063
+ debug: this.debug
1749
2064
  });
1750
- await this.submitStepsToQStash([resultStep], [lazyStep]);
1751
- return resultStep.out;
2065
+ throw new WorkflowAbort(lazyStep.stepName, resultStep);
1752
2066
  }
1753
2067
  /**
1754
2068
  * Runs steps in parallel.
@@ -1776,10 +2090,14 @@ var AutoExecutor = class _AutoExecutor {
1776
2090
  });
1777
2091
  switch (parallelCallState) {
1778
2092
  case "first": {
1779
- const planSteps = parallelSteps.map(
1780
- (parallelStep, index) => parallelStep.getPlanStep(parallelSteps.length, initialStepCount + index)
1781
- );
1782
- await this.submitStepsToQStash(planSteps, parallelSteps);
2093
+ await submitParallelSteps({
2094
+ context: this.context,
2095
+ steps: parallelSteps,
2096
+ initialStepCount,
2097
+ invokeCount: this.invokeCount,
2098
+ telemetry: this.telemetry,
2099
+ debug: this.debug
2100
+ });
1783
2101
  break;
1784
2102
  }
1785
2103
  case "partial": {
@@ -1793,13 +2111,18 @@ var AutoExecutor = class _AutoExecutor {
1793
2111
  validateStep(parallelSteps[stepIndex], planStep);
1794
2112
  try {
1795
2113
  const parallelStep = parallelSteps[stepIndex];
1796
- const resultStep = await parallelStep.getResultStep(
1797
- parallelSteps.length,
1798
- planStep.targetStep
1799
- );
1800
- await this.submitStepsToQStash([resultStep], [parallelStep]);
2114
+ const resultStep = await submitSingleStep({
2115
+ context: this.context,
2116
+ lazyStep: parallelStep,
2117
+ stepId: planStep.targetStep,
2118
+ invokeCount: this.invokeCount,
2119
+ concurrency: parallelSteps.length,
2120
+ telemetry: this.telemetry,
2121
+ debug: this.debug
2122
+ });
2123
+ throw new WorkflowAbort(parallelStep.stepName, resultStep);
1801
2124
  } catch (error) {
1802
- if (error instanceof WorkflowAbort || error instanceof QstashError4 && error.status === 400) {
2125
+ if (error instanceof WorkflowAbort || error instanceof QstashError5 && error.status === 400) {
1803
2126
  throw error;
1804
2127
  }
1805
2128
  throw new WorkflowError(
@@ -1855,128 +2178,6 @@ var AutoExecutor = class _AutoExecutor {
1855
2178
  return "discard";
1856
2179
  }
1857
2180
  }
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
2181
  /**
1981
2182
  * Get the promise by executing the lazt steps list. If there is a single
1982
2183
  * step, we call `runSingle`. Otherwise `runParallel` is called.
@@ -2173,7 +2374,7 @@ var WorkflowApi = class extends BaseWorkflowApi {
2173
2374
  };
2174
2375
 
2175
2376
  // src/agents/index.ts
2176
- import { createOpenAI as createOpenAI2 } from "@ai-sdk/openai";
2377
+ import { createOpenAI } from "@ai-sdk/openai";
2177
2378
 
2178
2379
  // src/agents/agent.ts
2179
2380
  import { z } from "zod";
@@ -2379,11 +2580,12 @@ var WorkflowAgents = class {
2379
2580
  */
2380
2581
  openai(...params) {
2381
2582
  const [model, settings] = params;
2382
- const { baseURL, apiKey, ...otherSettings } = settings ?? {};
2583
+ const { baseURL, apiKey, callSettings, ...otherSettings } = settings ?? {};
2383
2584
  const openaiModel = this.AISDKModel({
2384
2585
  context: this.context,
2385
- provider: createOpenAI2,
2386
- providerParams: { baseURL, apiKey, compatibility: "strict" }
2586
+ provider: createOpenAI,
2587
+ providerParams: { baseURL, apiKey, compatibility: "strict" },
2588
+ agentCallParams: callSettings
2387
2589
  });
2388
2590
  return openaiModel(model, otherSettings);
2389
2591
  }
@@ -2611,60 +2813,42 @@ var WorkflowContext = class {
2611
2813
  }
2612
2814
  await this.addStep(new LazySleepUntilStep(stepName, time));
2613
2815
  }
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
2816
  async call(stepName, settings) {
2647
- const {
2648
- url,
2649
- method = "GET",
2650
- body: requestBody,
2651
- headers = {},
2652
- retries = 0,
2653
- timeout,
2654
- flowControl
2655
- } = settings;
2656
- return await this.addStep(
2657
- new LazyCallStep(
2817
+ let callStep;
2818
+ if ("workflow" in settings) {
2819
+ const url = getNewUrlFromWorkflowId(this.url, settings.workflow.workflowId);
2820
+ callStep = new LazyCallStep(
2821
+ stepName,
2822
+ url,
2823
+ "POST",
2824
+ settings.body,
2825
+ settings.headers || {},
2826
+ settings.retries || 0,
2827
+ settings.timeout,
2828
+ settings.flowControl ?? settings.workflow.options.flowControl
2829
+ );
2830
+ } else {
2831
+ const {
2832
+ url,
2833
+ method = "GET",
2834
+ body,
2835
+ headers = {},
2836
+ retries = 0,
2837
+ timeout,
2838
+ flowControl
2839
+ } = settings;
2840
+ callStep = new LazyCallStep(
2658
2841
  stepName,
2659
2842
  url,
2660
2843
  method,
2661
- requestBody,
2844
+ body,
2662
2845
  headers,
2663
2846
  retries,
2664
2847
  timeout,
2665
2848
  flowControl
2666
- )
2667
- );
2849
+ );
2850
+ }
2851
+ return await this.addStep(callStep);
2668
2852
  }
2669
2853
  /**
2670
2854
  * Pauses workflow execution until a specific event occurs or a timeout is reached.
@@ -3332,8 +3516,8 @@ export {
3332
3516
  getWorkflowRunId,
3333
3517
  StepTypes,
3334
3518
  triggerFirstInvocation,
3335
- serveManyBase,
3336
3519
  WorkflowTool,
3520
+ serveManyBase,
3337
3521
  WorkflowContext,
3338
3522
  WorkflowLogger,
3339
3523
  serveBase,