@upstash/workflow 0.2.8-rc-invoke → 0.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/nextjs.mjs CHANGED
@@ -1,11 +1,8 @@
1
- import {
2
- createInvokeCallback,
3
- serveManyBase
4
- } from "./chunk-LCZMBGEM.mjs";
5
1
  import {
6
2
  SDK_TELEMETRY,
7
- serveBase
8
- } from "./chunk-IWAW7GIG.mjs";
3
+ serveBase,
4
+ serveManyBase
5
+ } from "./chunk-IPXJZU3K.mjs";
9
6
 
10
7
  // platforms/nextjs.ts
11
8
  var appTelemetry = {
@@ -31,21 +28,22 @@ var serve = (routeFunction, options) => {
31
28
  };
32
29
  };
33
30
  var createWorkflow = (...params) => {
34
- const { POST } = serve(...params);
31
+ const [routeFunction, options = {}] = params;
35
32
  return {
36
- callback: createInvokeCallback(appTelemetry),
37
- handler: POST,
33
+ routeFunction,
34
+ options,
38
35
  workflowId: void 0
39
36
  };
40
37
  };
41
- var serveMany = (workflows) => {
38
+ var serveMany = (workflows, options) => {
42
39
  return {
43
40
  POST: serveManyBase({
44
41
  workflows,
45
- getWorkflowId(params) {
46
- const components = params.url.split("/");
47
- return components[components.length - 1];
48
- }
42
+ getUrl(params) {
43
+ return params.url;
44
+ },
45
+ serveMethod: (...params) => serve(...params).POST,
46
+ options
49
47
  }).handler
50
48
  };
51
49
  };
@@ -74,24 +72,24 @@ var servePagesRouter = (routeFunction, options) => {
74
72
  };
75
73
  };
76
74
  var createWorkflowPagesRouter = (...params) => {
77
- const { handler } = servePagesRouter(...params);
75
+ const [routeFunction, options = {}] = params;
78
76
  return {
79
- callback: createInvokeCallback(pagesTelemetry),
80
- handler,
77
+ routeFunction,
78
+ options,
81
79
  workflowId: void 0
82
80
  };
83
81
  };
84
- var serveManyPagesRouter = (workflows) => {
82
+ var serveManyPagesRouter = (workflows, options) => {
85
83
  return serveManyBase({
86
84
  workflows,
87
- getWorkflowId(request_) {
85
+ getUrl(request_) {
88
86
  const protocol = request_.headers["x-forwarded-proto"];
89
87
  const host = request_.headers.host;
90
88
  const baseUrl = `${protocol}://${host}`;
91
- const url = `${baseUrl}${request_.url}`;
92
- const components = url.split("/");
93
- return components[components.length - 1];
94
- }
89
+ return `${baseUrl}${request_.url}`;
90
+ },
91
+ serveMethod: (...params) => servePagesRouter(...params).handler,
92
+ options
95
93
  });
96
94
  };
97
95
  export {
package/package.json CHANGED
@@ -1 +1 @@
1
- {"name":"@upstash/workflow","version":"v0.2.8-rc-invoke","description":"Durable, Reliable and Performant Serverless Functions","main":"./index.js","module":"./index.mjs","types":"./index.d.ts","files":["./*"],"exports":{".":{"import":"./index.mjs","require":"./index.js"},"./dist/nextjs":{"import":"./nextjs.mjs","require":"./nextjs.js"},"./nextjs":{"import":"./nextjs.mjs","require":"./nextjs.js"},"./h3":{"import":"./h3.mjs","require":"./h3.js"},"./svelte":{"import":"./svelte.mjs","require":"./svelte.js"},"./solidjs":{"import":"./solidjs.mjs","require":"./solidjs.js"},"./workflow":{"import":"./workflow.mjs","require":"./workflow.js"},"./hono":{"import":"./hono.mjs","require":"./hono.js"},"./cloudflare":{"import":"./cloudflare.mjs","require":"./cloudflare.js"},"./astro":{"import":"./astro.mjs","require":"./astro.js"},"./express":{"import":"./express.mjs","require":"./express.js"}},"scripts":{"build":"tsup && cp README.md ./dist/ && cp package.json ./dist/ && cp LICENSE ./dist/","test":"bun test src","fmt":"prettier --write .","lint":"tsc && eslint \"{src,platforms}/**/*.{js,ts,tsx}\" --quiet --fix","check-exports":"bun run build && cd dist && attw -P"},"repository":{"type":"git","url":"git+https://github.com/upstash/workflow-ts.git"},"keywords":["upstash","qstash","workflow","serverless"],"author":"Cahid Arda Oz","license":"MIT","bugs":{"url":"https://github.com/upstash/workflow-ts/issues"},"homepage":"https://github.com/upstash/workflow-ts#readme","devDependencies":{"@commitlint/cli":"^19.5.0","@commitlint/config-conventional":"^19.5.0","@eslint/js":"^9.11.1","@solidjs/start":"^1.0.8","@sveltejs/kit":"^2.6.1","@types/bun":"^1.1.10","@types/express":"^5.0.0","astro":"^4.16.7","eslint":"^9.11.1","eslint-plugin-unicorn":"^55.0.0","express":"^4.21.1","globals":"^15.10.0","h3":"^1.12.0","hono":"^4.6.20","husky":"^9.1.6","next":"^14.2.14","prettier":"3.3.3","tsup":"^8.3.0","typescript":"^5.7.2","typescript-eslint":"^8.18.0"},"dependencies":{"@ai-sdk/openai":"^1.0.15","@upstash/qstash":"^2.7.20","ai":"^4.0.30","zod":"^3.24.1"},"directories":{"example":"examples"}}
1
+ {"name":"@upstash/workflow","version":"v0.2.9","description":"Durable, Reliable and Performant Serverless Functions","main":"./index.js","module":"./index.mjs","types":"./index.d.ts","files":["./*"],"exports":{".":{"import":"./index.mjs","require":"./index.js"},"./dist/nextjs":{"import":"./nextjs.mjs","require":"./nextjs.js"},"./nextjs":{"import":"./nextjs.mjs","require":"./nextjs.js"},"./h3":{"import":"./h3.mjs","require":"./h3.js"},"./svelte":{"import":"./svelte.mjs","require":"./svelte.js"},"./solidjs":{"import":"./solidjs.mjs","require":"./solidjs.js"},"./workflow":{"import":"./workflow.mjs","require":"./workflow.js"},"./hono":{"import":"./hono.mjs","require":"./hono.js"},"./cloudflare":{"import":"./cloudflare.mjs","require":"./cloudflare.js"},"./astro":{"import":"./astro.mjs","require":"./astro.js"},"./express":{"import":"./express.mjs","require":"./express.js"}},"scripts":{"build":"tsup && cp README.md ./dist/ && cp package.json ./dist/ && cp LICENSE ./dist/","test":"bun test src","fmt":"prettier --write .","lint":"tsc && eslint \"{src,platforms}/**/*.{js,ts,tsx}\" --quiet --fix","check-exports":"bun run build && cd dist && attw -P"},"repository":{"type":"git","url":"git+https://github.com/upstash/workflow-ts.git"},"keywords":["upstash","qstash","workflow","serverless"],"author":"Cahid Arda Oz","license":"MIT","bugs":{"url":"https://github.com/upstash/workflow-ts/issues"},"homepage":"https://github.com/upstash/workflow-ts#readme","devDependencies":{"@commitlint/cli":"^19.5.0","@commitlint/config-conventional":"^19.5.0","@eslint/js":"^9.11.1","@solidjs/start":"^1.0.8","@sveltejs/kit":"^2.6.1","@types/bun":"^1.1.10","@types/express":"^5.0.0","astro":"^4.16.7","eslint":"^9.11.1","eslint-plugin-unicorn":"^55.0.0","express":"^4.21.1","globals":"^15.10.0","h3":"^1.12.0","hono":"^4.6.20","husky":"^9.1.6","next":"^14.2.14","prettier":"3.3.3","tsup":"^8.3.0","typescript":"^5.7.2","typescript-eslint":"^8.18.0"},"dependencies":{"@ai-sdk/openai":"^1.0.15","@upstash/qstash":"^2.7.22","ai":"^4.0.30","zod":"^3.24.1"},"directories":{"example":"examples"}}
@@ -0,0 +1,13 @@
1
+ import { k as PublicServeOptions, R as RouteFunction, t as InvokableWorkflow } from './types-CYhDXnf8.mjs';
2
+
3
+ type OmitOptionsInServeMany<TOptions> = Omit<TOptions, "env" | "url" | "schema" | "initialPayloadParser">;
4
+ declare const serveManyBase: <THandler extends (...params: any[]) => any, TOptions extends OmitOptionsInServeMany<PublicServeOptions> = OmitOptionsInServeMany<PublicServeOptions>, TServeParams extends [routeFunction: RouteFunction<any, any>, options: TOptions] = [routeFunction: RouteFunction<any, any>, options: TOptions]>({ workflows, getUrl, serveMethod, options, }: {
5
+ workflows: Record<string, InvokableWorkflow<any, any>>;
6
+ getUrl: (...params: Parameters<THandler>) => string;
7
+ serveMethod: (...params: TServeParams) => THandler;
8
+ options?: TOptions;
9
+ }) => {
10
+ handler: (...params: Parameters<THandler>) => Promise<any>;
11
+ };
12
+
13
+ export { serveManyBase as s };
@@ -0,0 +1,13 @@
1
+ import { k as PublicServeOptions, R as RouteFunction, t as InvokableWorkflow } from './types-CYhDXnf8.js';
2
+
3
+ type OmitOptionsInServeMany<TOptions> = Omit<TOptions, "env" | "url" | "schema" | "initialPayloadParser">;
4
+ declare const serveManyBase: <THandler extends (...params: any[]) => any, TOptions extends OmitOptionsInServeMany<PublicServeOptions> = OmitOptionsInServeMany<PublicServeOptions>, TServeParams extends [routeFunction: RouteFunction<any, any>, options: TOptions] = [routeFunction: RouteFunction<any, any>, options: TOptions]>({ workflows, getUrl, serveMethod, options, }: {
5
+ workflows: Record<string, InvokableWorkflow<any, any>>;
6
+ getUrl: (...params: Parameters<THandler>) => string;
7
+ serveMethod: (...params: TServeParams) => THandler;
8
+ options?: TOptions;
9
+ }) => {
10
+ handler: (...params: Parameters<THandler>) => Promise<any>;
11
+ };
12
+
13
+ export { serveManyBase as s };
package/solidjs.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { APIEvent } from '@solidjs/start/server';
2
- import { R as RouteFunction, j as PublicServeOptions } from './types-C7Y7WUQd.mjs';
2
+ import { R as RouteFunction, k as PublicServeOptions } from './types-CYhDXnf8.mjs';
3
3
  import '@upstash/qstash';
4
4
  import 'zod';
5
5
  import 'ai';
package/solidjs.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { APIEvent } from '@solidjs/start/server';
2
- import { R as RouteFunction, j as PublicServeOptions } from './types-C7Y7WUQd.js';
2
+ import { R as RouteFunction, k as PublicServeOptions } from './types-CYhDXnf8.js';
3
3
  import '@upstash/qstash';
4
4
  import 'zod';
5
5
  import 'ai';
package/solidjs.js CHANGED
@@ -83,6 +83,7 @@ var WORKFLOW_INIT_HEADER = "Upstash-Workflow-Init";
83
83
  var WORKFLOW_URL_HEADER = "Upstash-Workflow-Url";
84
84
  var WORKFLOW_FAILURE_HEADER = "Upstash-Workflow-Is-Failure";
85
85
  var WORKFLOW_FEATURE_HEADER = "Upstash-Feature-Set";
86
+ var WORKFLOW_INVOKE_COUNT_HEADER = "Upstash-Workflow-Invoke-Count";
86
87
  var WORKFLOW_PROTOCOL_VERSION = "1";
87
88
  var WORKFLOW_PROTOCOL_VERSION_HEADER = "Upstash-Workflow-Sdk-Version";
88
89
  var DEFAULT_CONTENT_TYPE = "application/json";
@@ -264,8 +265,9 @@ var LazyCallStep = class extends BaseLazyStep {
264
265
  headers;
265
266
  retries;
266
267
  timeout;
268
+ flowControl;
267
269
  stepType = "Call";
268
- constructor(stepName, url, method, body, headers, retries, timeout) {
270
+ constructor(stepName, url, method, body, headers, retries, timeout, flowControl) {
269
271
  super(stepName);
270
272
  this.url = url;
271
273
  this.method = method;
@@ -273,6 +275,7 @@ var LazyCallStep = class extends BaseLazyStep {
273
275
  this.headers = headers;
274
276
  this.retries = retries;
275
277
  this.timeout = timeout;
278
+ this.flowControl = flowControl;
276
279
  }
277
280
  getPlanStep(concurrent, targetStep) {
278
281
  return {
@@ -343,14 +346,22 @@ var LazyNotifyStep = class extends LazyFunctionStep {
343
346
  var LazyInvokeStep = class extends BaseLazyStep {
344
347
  stepType = "Invoke";
345
348
  params;
346
- constructor(stepName, { workflow, body, headers = {}, workflowRunId, retries }) {
349
+ constructor(stepName, {
350
+ workflow,
351
+ body,
352
+ headers = {},
353
+ workflowRunId,
354
+ retries,
355
+ flowControl
356
+ }) {
347
357
  super(stepName);
348
358
  this.params = {
349
359
  workflow,
350
360
  body,
351
361
  headers,
352
362
  workflowRunId: getWorkflowRunId(workflowRunId),
353
- retries
363
+ retries,
364
+ flowControl
354
365
  };
355
366
  }
356
367
  getPlanStep(concurrent, targetStep) {
@@ -809,7 +820,8 @@ var triggerFirstInvocation = async ({
809
820
  workflowContext,
810
821
  useJSONContent,
811
822
  telemetry,
812
- debug
823
+ debug,
824
+ invokeCount
813
825
  }) => {
814
826
  const { headers } = getHeaders({
815
827
  initHeaderValue: "true",
@@ -818,7 +830,9 @@ var triggerFirstInvocation = async ({
818
830
  userHeaders: workflowContext.headers,
819
831
  failureUrl: workflowContext.failureUrl,
820
832
  retries: workflowContext.retries,
821
- telemetry
833
+ telemetry,
834
+ invokeCount,
835
+ flowControl: workflowContext.flowControl
822
836
  });
823
837
  if (workflowContext.headers.get("content-type")) {
824
838
  headers["content-type"] = workflowContext.headers.get("content-type");
@@ -924,6 +938,7 @@ var handleThirdPartyCallResult = async ({
924
938
  failureUrl,
925
939
  retries,
926
940
  telemetry,
941
+ flowControl,
927
942
  debug
928
943
  }) => {
929
944
  try {
@@ -971,6 +986,7 @@ ${atob(callbackMessage.body ?? "")}`
971
986
  const stepType = request.headers.get("Upstash-Workflow-StepType");
972
987
  const concurrentString = request.headers.get("Upstash-Workflow-Concurrent");
973
988
  const contentType = request.headers.get("Upstash-Workflow-ContentType");
989
+ const invokeCount = request.headers.get(WORKFLOW_INVOKE_COUNT_HEADER);
974
990
  if (!(workflowRunId && stepIdString && stepName && StepTypes.includes(stepType) && concurrentString && contentType)) {
975
991
  throw new Error(
976
992
  `Missing info in callback message source header: ${JSON.stringify({
@@ -991,7 +1007,9 @@ ${atob(callbackMessage.body ?? "")}`
991
1007
  userHeaders,
992
1008
  failureUrl,
993
1009
  retries,
994
- telemetry
1010
+ telemetry,
1011
+ invokeCount: Number(invokeCount),
1012
+ flowControl
995
1013
  });
996
1014
  const callResponse = {
997
1015
  status: callbackMessage.status,
@@ -1047,7 +1065,10 @@ var getHeaders = ({
1047
1065
  step,
1048
1066
  callRetries,
1049
1067
  callTimeout,
1050
- telemetry
1068
+ telemetry,
1069
+ invokeCount,
1070
+ flowControl,
1071
+ callFlowControl
1051
1072
  }) => {
1052
1073
  const contentType = (userHeaders ? userHeaders.get("Content-Type") : void 0) ?? DEFAULT_CONTENT_TYPE;
1053
1074
  const baseHeaders = {
@@ -1059,6 +1080,9 @@ var getHeaders = ({
1059
1080
  "content-type": contentType,
1060
1081
  ...telemetry ? getTelemetryHeaders(telemetry) : {}
1061
1082
  };
1083
+ if (invokeCount !== void 0 && !step?.callUrl) {
1084
+ baseHeaders[`Upstash-Forward-${WORKFLOW_INVOKE_COUNT_HEADER}`] = invokeCount.toString();
1085
+ }
1062
1086
  if (!step?.callUrl) {
1063
1087
  baseHeaders[`Upstash-Forward-${WORKFLOW_PROTOCOL_VERSION_HEADER}`] = WORKFLOW_PROTOCOL_VERSION;
1064
1088
  }
@@ -1067,13 +1091,23 @@ var getHeaders = ({
1067
1091
  }
1068
1092
  if (failureUrl) {
1069
1093
  baseHeaders[`Upstash-Failure-Callback-Forward-${WORKFLOW_FAILURE_HEADER}`] = "true";
1094
+ baseHeaders[`Upstash-Failure-Callback-Forward-Upstash-Workflow-Failure-Callback`] = "true";
1095
+ baseHeaders["Upstash-Failure-Callback-Workflow-Runid"] = workflowRunId;
1096
+ baseHeaders["Upstash-Failure-Callback-Workflow-Init"] = "false";
1097
+ baseHeaders["Upstash-Failure-Callback-Workflow-Url"] = workflowUrl;
1098
+ baseHeaders["Upstash-Failure-Callback-Workflow-Calltype"] = "failureCall";
1099
+ if (retries !== void 0) {
1100
+ baseHeaders["Upstash-Failure-Callback-Retries"] = retries.toString();
1101
+ }
1102
+ if (flowControl) {
1103
+ const { flowControlKey, flowControlValue } = prepareFlowControl(flowControl);
1104
+ baseHeaders["Upstash-Failure-Callback-Flow-Control-Key"] = flowControlKey;
1105
+ baseHeaders["Upstash-Failure-Callback-Flow-Control-Value"] = flowControlValue;
1106
+ }
1070
1107
  if (!step?.callUrl) {
1071
1108
  baseHeaders["Upstash-Failure-Callback"] = failureUrl;
1072
1109
  }
1073
1110
  }
1074
- if (step?.stepType === "Invoke") {
1075
- baseHeaders["upstash-workflow-invoke"] = "true";
1076
- }
1077
1111
  if (step?.callUrl) {
1078
1112
  baseHeaders["Upstash-Retries"] = callRetries?.toString() ?? "0";
1079
1113
  baseHeaders[WORKFLOW_FEATURE_HEADER] = "WF_NoDelete,InitialBody";
@@ -1081,9 +1115,26 @@ var getHeaders = ({
1081
1115
  baseHeaders["Upstash-Callback-Retries"] = retries.toString();
1082
1116
  baseHeaders["Upstash-Failure-Callback-Retries"] = retries.toString();
1083
1117
  }
1084
- } else if (retries !== void 0) {
1085
- baseHeaders["Upstash-Retries"] = retries.toString();
1086
- baseHeaders["Upstash-Failure-Callback-Retries"] = retries.toString();
1118
+ if (callFlowControl) {
1119
+ const { flowControlKey, flowControlValue } = prepareFlowControl(callFlowControl);
1120
+ baseHeaders["Upstash-Flow-Control-Key"] = flowControlKey;
1121
+ baseHeaders["Upstash-Flow-Control-Value"] = flowControlValue;
1122
+ }
1123
+ if (flowControl) {
1124
+ const { flowControlKey, flowControlValue } = prepareFlowControl(flowControl);
1125
+ baseHeaders["Upstash-Callback-Flow-Control-Key"] = flowControlKey;
1126
+ baseHeaders["Upstash-Callback-Flow-Control-Value"] = flowControlValue;
1127
+ }
1128
+ } else {
1129
+ if (flowControl) {
1130
+ const { flowControlKey, flowControlValue } = prepareFlowControl(flowControl);
1131
+ baseHeaders["Upstash-Flow-Control-Key"] = flowControlKey;
1132
+ baseHeaders["Upstash-Flow-Control-Value"] = flowControlValue;
1133
+ }
1134
+ if (retries !== void 0) {
1135
+ baseHeaders["Upstash-Retries"] = retries.toString();
1136
+ baseHeaders["Upstash-Failure-Callback-Retries"] = retries.toString();
1137
+ }
1087
1138
  }
1088
1139
  if (userHeaders) {
1089
1140
  for (const header of userHeaders.keys()) {
@@ -1118,6 +1169,7 @@ var getHeaders = ({
1118
1169
  "Upstash-Callback-Forward-Upstash-Workflow-StepType": step.stepType,
1119
1170
  "Upstash-Callback-Forward-Upstash-Workflow-Concurrent": step.concurrent.toString(),
1120
1171
  "Upstash-Callback-Forward-Upstash-Workflow-ContentType": contentType,
1172
+ [`Upstash-Callback-Forward-${WORKFLOW_INVOKE_COUNT_HEADER}`]: (invokeCount ?? 0).toString(),
1121
1173
  "Upstash-Workflow-CallType": "toCallback"
1122
1174
  }
1123
1175
  };
@@ -1175,9 +1227,98 @@ If you want to disable QStash Verification, you should clear env variables QSTAS
1175
1227
  );
1176
1228
  }
1177
1229
  };
1230
+ var prepareFlowControl = (flowControl) => {
1231
+ const parallelism = flowControl.parallelism?.toString();
1232
+ const rate = flowControl.ratePerSecond?.toString();
1233
+ const controlValue = [
1234
+ parallelism ? `parallelism=${parallelism}` : void 0,
1235
+ rate ? `rate=${rate}` : void 0
1236
+ ].filter(Boolean);
1237
+ if (controlValue.length === 0) {
1238
+ throw new import_qstash3.QstashError("Provide at least one of parallelism or ratePerSecond for flowControl");
1239
+ }
1240
+ return {
1241
+ flowControlKey: flowControl.key,
1242
+ flowControlValue: controlValue.join(", ")
1243
+ };
1244
+ };
1178
1245
 
1179
1246
  // src/context/auto-executor.ts
1180
1247
  var import_qstash4 = require("@upstash/qstash");
1248
+
1249
+ // src/serve/serve-many.ts
1250
+ var invokeWorkflow = async ({
1251
+ settings,
1252
+ invokeStep,
1253
+ context,
1254
+ invokeCount,
1255
+ telemetry
1256
+ }) => {
1257
+ const {
1258
+ body,
1259
+ workflow,
1260
+ headers = {},
1261
+ workflowRunId = getWorkflowRunId(),
1262
+ retries,
1263
+ flowControl
1264
+ } = settings;
1265
+ const { workflowId } = workflow;
1266
+ const {
1267
+ retries: workflowRetries,
1268
+ failureFunction,
1269
+ failureUrl,
1270
+ useJSONContent,
1271
+ flowControl: workflowFlowControl
1272
+ } = workflow.options;
1273
+ if (!workflowId) {
1274
+ throw new WorkflowError("You can only invoke workflow which has a workflowId");
1275
+ }
1276
+ const { headers: invokerHeaders } = getHeaders({
1277
+ initHeaderValue: "false",
1278
+ workflowRunId: context.workflowRunId,
1279
+ workflowUrl: context.url,
1280
+ userHeaders: context.headers,
1281
+ failureUrl: context.failureUrl,
1282
+ retries: context.retries,
1283
+ telemetry,
1284
+ invokeCount,
1285
+ flowControl: context.flowControl
1286
+ });
1287
+ invokerHeaders["Upstash-Workflow-Runid"] = context.workflowRunId;
1288
+ const newUrl = context.url.replace(/[^/]+$/, workflowId);
1289
+ const { headers: triggerHeaders } = getHeaders({
1290
+ initHeaderValue: "true",
1291
+ workflowRunId,
1292
+ workflowUrl: newUrl,
1293
+ userHeaders: new Headers(headers),
1294
+ retries: retries ?? workflowRetries,
1295
+ telemetry,
1296
+ failureUrl: failureFunction ? newUrl : failureUrl,
1297
+ invokeCount: invokeCount + 1,
1298
+ flowControl: flowControl ?? workflowFlowControl
1299
+ });
1300
+ triggerHeaders["Upstash-Workflow-Invoke"] = "true";
1301
+ if (useJSONContent) {
1302
+ triggerHeaders["content-type"] = "application/json";
1303
+ }
1304
+ const request = {
1305
+ body: JSON.stringify(body),
1306
+ headers: Object.fromEntries(
1307
+ Object.entries(invokerHeaders).map((pairs) => [pairs[0], [pairs[1]]])
1308
+ ),
1309
+ workflowRunId,
1310
+ workflowUrl: context.url,
1311
+ step: invokeStep
1312
+ };
1313
+ await context.qstashClient.publish({
1314
+ headers: triggerHeaders,
1315
+ method: "POST",
1316
+ body: JSON.stringify(request),
1317
+ url: newUrl
1318
+ });
1319
+ };
1320
+
1321
+ // src/context/auto-executor.ts
1181
1322
  var AutoExecutor = class _AutoExecutor {
1182
1323
  context;
1183
1324
  promises = /* @__PURE__ */ new WeakMap();
@@ -1186,14 +1327,16 @@ var AutoExecutor = class _AutoExecutor {
1186
1327
  nonPlanStepCount;
1187
1328
  steps;
1188
1329
  indexInCurrentList = 0;
1330
+ invokeCount;
1189
1331
  telemetry;
1190
1332
  stepCount = 0;
1191
1333
  planStepCount = 0;
1192
1334
  executingStep = false;
1193
- constructor(context, steps, telemetry, debug) {
1335
+ constructor(context, steps, telemetry, invokeCount, debug) {
1194
1336
  this.context = context;
1195
1337
  this.steps = steps;
1196
1338
  this.telemetry = telemetry;
1339
+ this.invokeCount = invokeCount ?? 0;
1197
1340
  this.debug = debug;
1198
1341
  this.nonPlanStepCount = this.steps.filter((step) => !step.targetStep).length;
1199
1342
  }
@@ -1416,7 +1559,9 @@ var AutoExecutor = class _AutoExecutor {
1416
1559
  step: waitStep,
1417
1560
  failureUrl: this.context.failureUrl,
1418
1561
  retries: this.context.retries,
1419
- telemetry: this.telemetry
1562
+ telemetry: this.telemetry,
1563
+ invokeCount: this.invokeCount,
1564
+ flowControl: this.context.flowControl
1420
1565
  });
1421
1566
  const waitBody = {
1422
1567
  url: this.context.url,
@@ -1444,17 +1589,13 @@ var AutoExecutor = class _AutoExecutor {
1444
1589
  if (steps.length === 1 && lazySteps[0] instanceof LazyInvokeStep) {
1445
1590
  const invokeStep = steps[0];
1446
1591
  const lazyInvokeStep = lazySteps[0];
1447
- await lazyInvokeStep.params.workflow.callback(
1448
- {
1449
- body: lazyInvokeStep.params.body,
1450
- headers: lazyInvokeStep.params.headers,
1451
- workflowRunId: lazyInvokeStep.params.workflowRunId,
1452
- workflow: lazyInvokeStep.params.workflow,
1453
- retries: lazyInvokeStep.params.retries
1454
- },
1592
+ await invokeWorkflow({
1593
+ settings: lazyInvokeStep.params,
1455
1594
  invokeStep,
1456
- this.context
1457
- );
1595
+ context: this.context,
1596
+ invokeCount: this.invokeCount,
1597
+ telemetry: this.telemetry
1598
+ });
1458
1599
  throw new WorkflowAbort(invokeStep.stepName, invokeStep);
1459
1600
  }
1460
1601
  const result = await this.context.qstashClient.batchJSON(
@@ -1470,11 +1611,14 @@ var AutoExecutor = class _AutoExecutor {
1470
1611
  retries: this.context.retries,
1471
1612
  callRetries: lazyStep instanceof LazyCallStep ? lazyStep.retries : void 0,
1472
1613
  callTimeout: lazyStep instanceof LazyCallStep ? lazyStep.timeout : void 0,
1473
- telemetry: this.telemetry
1614
+ telemetry: this.telemetry,
1615
+ invokeCount: this.invokeCount,
1616
+ flowControl: this.context.flowControl,
1617
+ callFlowControl: lazyStep instanceof LazyCallStep ? lazyStep.flowControl : void 0
1474
1618
  });
1475
1619
  const willWait = singleStep.concurrent === NO_CONCURRENCY || singleStep.stepId === 0;
1476
1620
  singleStep.out = JSON.stringify(singleStep.out);
1477
- return singleStep.callUrl ? (
1621
+ return singleStep.callUrl && lazyStep instanceof LazyCallStep ? (
1478
1622
  // if the step is a third party call, we call the third party
1479
1623
  // url (singleStep.callUrl) and pass information about the workflow
1480
1624
  // in the headers (handled in getHeaders). QStash makes the request
@@ -1774,9 +1918,10 @@ var wrapTools = ({
1774
1918
  return Object.fromEntries(
1775
1919
  Object.entries(tools).map((toolInfo) => {
1776
1920
  const [toolName, tool3] = toolInfo;
1921
+ const executeAsStep = "executeAsStep" in tool3 ? tool3.executeAsStep : true;
1777
1922
  const aiSDKTool = convertToAISDKTool(tool3);
1778
1923
  const execute = aiSDKTool.execute;
1779
- if (execute) {
1924
+ if (execute && executeAsStep) {
1780
1925
  const wrappedExecute = (...params) => {
1781
1926
  return context.run(`Run tool ${toolName}`, () => execute(...params));
1782
1927
  };
@@ -2130,6 +2275,11 @@ var WorkflowContext = class {
2130
2275
  * Number of retries
2131
2276
  */
2132
2277
  retries;
2278
+ /**
2279
+ * Settings for controlling the number of active requests
2280
+ * and number of requests per second with the same key.
2281
+ */
2282
+ flowControl;
2133
2283
  constructor({
2134
2284
  qstashClient,
2135
2285
  workflowRunId,
@@ -2141,7 +2291,9 @@ var WorkflowContext = class {
2141
2291
  initialPayload,
2142
2292
  env,
2143
2293
  retries,
2144
- telemetry
2294
+ telemetry,
2295
+ invokeCount,
2296
+ flowControl
2145
2297
  }) {
2146
2298
  this.qstashClient = qstashClient;
2147
2299
  this.workflowRunId = workflowRunId;
@@ -2152,7 +2304,8 @@ var WorkflowContext = class {
2152
2304
  this.requestPayload = initialPayload;
2153
2305
  this.env = env ?? {};
2154
2306
  this.retries = retries ?? DEFAULT_RETRIES;
2155
- this.executor = new AutoExecutor(this, this.steps, telemetry, debug);
2307
+ this.flowControl = flowControl;
2308
+ this.executor = new AutoExecutor(this, this.steps, telemetry, invokeCount, debug);
2156
2309
  }
2157
2310
  /**
2158
2311
  * Executes a workflow step
@@ -2254,7 +2407,7 @@ var WorkflowContext = class {
2254
2407
  * }
2255
2408
  */
2256
2409
  async call(stepName, settings) {
2257
- const { url, method = "GET", body, headers = {}, retries = 0, timeout } = settings;
2410
+ const { url, method = "GET", body, headers = {}, retries = 0, timeout, flowControl } = settings;
2258
2411
  const result = await this.addStep(
2259
2412
  new LazyCallStep(
2260
2413
  stepName,
@@ -2263,7 +2416,8 @@ var WorkflowContext = class {
2263
2416
  body,
2264
2417
  headers,
2265
2418
  retries,
2266
- timeout
2419
+ timeout,
2420
+ flowControl
2267
2421
  )
2268
2422
  );
2269
2423
  if (typeof result === "string") {
@@ -2500,7 +2654,8 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
2500
2654
  failureUrl: context.failureUrl,
2501
2655
  initialPayload: context.requestPayload,
2502
2656
  env: context.env,
2503
- retries: context.retries
2657
+ retries: context.retries,
2658
+ flowControl: context.flowControl
2504
2659
  });
2505
2660
  try {
2506
2661
  await routeFunction(disabledContext);
@@ -2653,7 +2808,7 @@ var parseRequest = async (requestPayload, isFirstInvocation, workflowRunId, requ
2653
2808
  };
2654
2809
  }
2655
2810
  };
2656
- var handleFailure = async (request, requestPayload, qstashClient, initialPayloadParser, routeFunction, failureFunction, env, retries, debug) => {
2811
+ var handleFailure = async (request, requestPayload, qstashClient, initialPayloadParser, routeFunction, failureFunction, env, retries, flowControl, debug) => {
2657
2812
  if (request.headers.get(WORKFLOW_FAILURE_HEADER) !== "true") {
2658
2813
  return ok("not-failure-callback");
2659
2814
  }
@@ -2665,22 +2820,21 @@ var handleFailure = async (request, requestPayload, qstashClient, initialPayload
2665
2820
  );
2666
2821
  }
2667
2822
  try {
2668
- const { status, header, body, url, sourceHeader, sourceBody, workflowRunId } = JSON.parse(
2669
- requestPayload
2670
- );
2823
+ const { status, header, body, url, sourceBody, workflowRunId } = JSON.parse(requestPayload);
2671
2824
  const decodedBody = body ? decodeBase64(body) : "{}";
2672
2825
  const errorPayload = JSON.parse(decodedBody);
2673
2826
  const workflowContext = new WorkflowContext({
2674
2827
  qstashClient,
2675
2828
  workflowRunId,
2676
2829
  initialPayload: sourceBody ? initialPayloadParser(decodeBase64(sourceBody)) : void 0,
2677
- headers: recreateUserHeaders(new Headers(sourceHeader)),
2830
+ headers: recreateUserHeaders(request.headers),
2678
2831
  steps: [],
2679
2832
  url,
2680
2833
  failureUrl: url,
2681
2834
  debug,
2682
2835
  env,
2683
2836
  retries,
2837
+ flowControl,
2684
2838
  telemetry: void 0
2685
2839
  // not going to make requests in authentication check
2686
2840
  });
@@ -2807,7 +2961,8 @@ var serveBase = (routeFunction, telemetry, options) => {
2807
2961
  env,
2808
2962
  retries,
2809
2963
  useJSONContent,
2810
- disableTelemetry
2964
+ disableTelemetry,
2965
+ flowControl
2811
2966
  } = processOptions(options);
2812
2967
  telemetry = disableTelemetry ? void 0 : telemetry;
2813
2968
  const debug = WorkflowLogger.getLogger(verbose);
@@ -2848,6 +3003,7 @@ var serveBase = (routeFunction, telemetry, options) => {
2848
3003
  failureFunction,
2849
3004
  env,
2850
3005
  retries,
3006
+ flowControl,
2851
3007
  debug
2852
3008
  );
2853
3009
  if (failureCheck.isErr()) {
@@ -2856,6 +3012,7 @@ var serveBase = (routeFunction, telemetry, options) => {
2856
3012
  await debug?.log("WARN", "RESPONSE_DEFAULT", "failureFunction executed");
2857
3013
  return onStepFinish(workflowRunId, "failure-callback");
2858
3014
  }
3015
+ const invokeCount = Number(request.headers.get(WORKFLOW_INVOKE_COUNT_HEADER) ?? "0");
2859
3016
  const workflowContext = new WorkflowContext({
2860
3017
  qstashClient,
2861
3018
  workflowRunId,
@@ -2867,7 +3024,9 @@ var serveBase = (routeFunction, telemetry, options) => {
2867
3024
  debug,
2868
3025
  env,
2869
3026
  retries,
2870
- telemetry
3027
+ telemetry,
3028
+ invokeCount,
3029
+ flowControl
2871
3030
  });
2872
3031
  const authCheck = await DisabledWorkflowContext.tryAuthentication(
2873
3032
  routeFunction,
@@ -2890,6 +3049,7 @@ var serveBase = (routeFunction, telemetry, options) => {
2890
3049
  workflowUrl,
2891
3050
  failureUrl: workflowFailureUrl,
2892
3051
  retries,
3052
+ flowControl,
2893
3053
  telemetry,
2894
3054
  debug
2895
3055
  });
@@ -2899,7 +3059,13 @@ var serveBase = (routeFunction, telemetry, options) => {
2899
3059
  });
2900
3060
  throw callReturnCheck.error;
2901
3061
  } else if (callReturnCheck.value === "continue-workflow") {
2902
- const result = isFirstInvocation ? await triggerFirstInvocation({ workflowContext, useJSONContent, telemetry, debug }) : await triggerRouteFunction({
3062
+ const result = isFirstInvocation ? await triggerFirstInvocation({
3063
+ workflowContext,
3064
+ useJSONContent,
3065
+ telemetry,
3066
+ debug,
3067
+ invokeCount
3068
+ }) : await triggerRouteFunction({
2903
3069
  onStep: async () => routeFunction(workflowContext),
2904
3070
  onCleanup: async (result2) => {
2905
3071
  await triggerWorkflowDelete(workflowContext, result2, debug);
package/solidjs.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  SDK_TELEMETRY,
3
3
  serveBase
4
- } from "./chunk-IWAW7GIG.mjs";
4
+ } from "./chunk-IPXJZU3K.mjs";
5
5
 
6
6
  // platforms/solidjs.ts
7
7
  var serve = (routeFunction, options) => {