@upstash/workflow 0.2.22-rc → 0.3.0-rc

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/index.js CHANGED
@@ -27,13 +27,101 @@ __export(src_exports, {
27
27
  WorkflowError: () => WorkflowError,
28
28
  WorkflowLogger: () => WorkflowLogger,
29
29
  WorkflowNonRetryableError: () => WorkflowNonRetryableError,
30
- WorkflowTool: () => WorkflowTool,
30
+ WorkflowRetryAfterError: () => WorkflowRetryAfterError,
31
31
  serve: () => serve
32
32
  });
33
33
  module.exports = __toCommonJS(src_exports);
34
34
 
35
35
  // src/client/utils.ts
36
+ var import_qstash2 = require("@upstash/qstash");
37
+
38
+ // src/error.ts
36
39
  var import_qstash = require("@upstash/qstash");
40
+ var WorkflowError = class extends import_qstash.QstashError {
41
+ constructor(message) {
42
+ super(message);
43
+ this.name = "WorkflowError";
44
+ }
45
+ };
46
+ var WorkflowAbort = class extends Error {
47
+ stepInfo;
48
+ stepName;
49
+ /**
50
+ * whether workflow is to be canceled on abort
51
+ */
52
+ cancelWorkflow;
53
+ /**
54
+ *
55
+ * @param stepName name of the aborting step
56
+ * @param stepInfo step information
57
+ * @param cancelWorkflow
58
+ */
59
+ constructor(stepName, stepInfo, cancelWorkflow = false) {
60
+ super(
61
+ `This is an Upstash Workflow error thrown after a step executes. It is expected to be raised. Make sure that you await for each step. Also, if you are using try/catch blocks, you should not wrap context.run/sleep/sleepUntil/call methods with try/catch. Aborting workflow after executing step '${stepName}'.`
62
+ );
63
+ this.name = "WorkflowAbort";
64
+ this.stepName = stepName;
65
+ this.stepInfo = stepInfo;
66
+ this.cancelWorkflow = cancelWorkflow;
67
+ }
68
+ };
69
+ var WorkflowNonRetryableError = class extends WorkflowAbort {
70
+ /**
71
+ * @param message error message to be displayed
72
+ */
73
+ constructor(message) {
74
+ super("fail", void 0, false);
75
+ this.name = "WorkflowNonRetryableError";
76
+ if (message) this.message = message;
77
+ }
78
+ };
79
+ var WorkflowRetryAfterError = class extends WorkflowAbort {
80
+ retryAfter;
81
+ /**
82
+ * @param retryAfter time in seconds after which the workflow should be retried
83
+ * @param message error message to be displayed
84
+ */
85
+ constructor(message, retryAfter) {
86
+ super("retry", void 0, false);
87
+ this.name = "WorkflowRetryAfterError";
88
+ this.retryAfter = retryAfter;
89
+ if (message) this.message = message;
90
+ }
91
+ };
92
+ var formatWorkflowError = (error) => {
93
+ return error instanceof Error ? {
94
+ error: error.name,
95
+ message: error.message,
96
+ stack: error.stack
97
+ } : {
98
+ error: "Error",
99
+ message: `An error occured while executing workflow: '${typeof error === "string" ? error : JSON.stringify(error)}'`
100
+ };
101
+ };
102
+ function getConstructorName(obj) {
103
+ if (obj === null || obj === void 0) {
104
+ return null;
105
+ }
106
+ const ctor = obj.constructor;
107
+ if (!ctor || ctor.name === "Object") {
108
+ return null;
109
+ }
110
+ return ctor.name;
111
+ }
112
+ function getConstructorNames(obj) {
113
+ const proto = Object.getPrototypeOf(obj);
114
+ const name = getConstructorName(proto);
115
+ if (name === null) {
116
+ return [];
117
+ }
118
+ return [name, ...getConstructorNames(proto)];
119
+ }
120
+ function isInstanceOf(v, ctor) {
121
+ return getConstructorNames(v).includes(ctor.name);
122
+ }
123
+
124
+ // src/client/utils.ts
37
125
  var makeNotifyRequest = async (requester, eventId, eventData) => {
38
126
  const result = await requester.request({
39
127
  path: ["v2", "notify", eventId],
@@ -80,7 +168,7 @@ var getSteps = async (requester, workflowRunId, messageId, debug) => {
80
168
  return { steps: filteredSteps, workflowRunEnded: false };
81
169
  }
82
170
  } catch (error) {
83
- if (error instanceof import_qstash.QstashError && error.status === 404) {
171
+ if (isInstanceOf(error, import_qstash2.QstashError) && error.status === 404) {
84
172
  await debug?.log("WARN", "ENDPOINT_START", {
85
173
  message: "Couldn't fetch workflow run steps. This can happen if the workflow run succesfully ends before some callback is executed.",
86
174
  error
@@ -105,64 +193,11 @@ var WORKFLOW_PROTOCOL_VERSION_HEADER = "Upstash-Workflow-Sdk-Version";
105
193
  var DEFAULT_CONTENT_TYPE = "application/json";
106
194
  var NO_CONCURRENCY = 1;
107
195
  var DEFAULT_RETRIES = 3;
108
- var VERSION = "v0.2.21";
196
+ var VERSION = "v0.3.0-rc";
109
197
  var SDK_TELEMETRY = `@upstash/workflow@${VERSION}`;
110
198
  var TELEMETRY_HEADER_SDK = "Upstash-Telemetry-Sdk";
111
199
  var TELEMETRY_HEADER_FRAMEWORK = "Upstash-Telemetry-Framework";
112
200
  var TELEMETRY_HEADER_RUNTIME = "Upstash-Telemetry-Runtime";
113
- var TELEMETRY_HEADER_AGENT = "Upstash-Telemetry-Agent";
114
-
115
- // src/error.ts
116
- var import_qstash2 = require("@upstash/qstash");
117
- var WorkflowError = class extends import_qstash2.QstashError {
118
- constructor(message) {
119
- super(message);
120
- this.name = "WorkflowError";
121
- }
122
- };
123
- var WorkflowAbort = class extends Error {
124
- stepInfo;
125
- stepName;
126
- /**
127
- * whether workflow is to be canceled on abort
128
- */
129
- cancelWorkflow;
130
- /**
131
- *
132
- * @param stepName name of the aborting step
133
- * @param stepInfo step information
134
- * @param cancelWorkflow
135
- */
136
- constructor(stepName, stepInfo, cancelWorkflow = false) {
137
- super(
138
- `This is an Upstash Workflow error thrown after a step executes. It is expected to be raised. Make sure that you await for each step. Also, if you are using try/catch blocks, you should not wrap context.run/sleep/sleepUntil/call methods with try/catch. Aborting workflow after executing step '${stepName}'.`
139
- );
140
- this.name = "WorkflowAbort";
141
- this.stepName = stepName;
142
- this.stepInfo = stepInfo;
143
- this.cancelWorkflow = cancelWorkflow;
144
- }
145
- };
146
- var WorkflowNonRetryableError = class extends WorkflowAbort {
147
- /**
148
- * @param message error message to be displayed
149
- */
150
- constructor(message) {
151
- super("fail", void 0, false);
152
- this.name = "WorkflowNonRetryableError";
153
- if (message) this.message = message;
154
- }
155
- };
156
- var formatWorkflowError = (error) => {
157
- return error instanceof Error ? {
158
- error: error.name,
159
- message: error.message,
160
- stack: error.stack
161
- } : {
162
- error: "Error",
163
- message: `An error occured while executing workflow: '${typeof error === "string" ? error : JSON.stringify(error)}'`
164
- };
165
- };
166
201
 
167
202
  // src/context/auto-executor.ts
168
203
  var import_qstash5 = require("@upstash/qstash");
@@ -535,9 +570,9 @@ var Ok = class {
535
570
  }
536
571
  safeUnwrap() {
537
572
  const value = this.value;
538
- return function* () {
573
+ return (function* () {
539
574
  return value;
540
- }();
575
+ })();
541
576
  }
542
577
  _unsafeUnwrap(_) {
543
578
  return this.value;
@@ -596,10 +631,10 @@ var Err = class {
596
631
  }
597
632
  safeUnwrap() {
598
633
  const error = this.error;
599
- return function* () {
634
+ return (function* () {
600
635
  yield err(error);
601
636
  throw new Error("Do not use this generator out of `safeTry`");
602
- }();
637
+ })();
603
638
  }
604
639
  _unsafeUnwrap(config) {
605
640
  throw createNeverThrowError("Called `_unsafeUnwrap` on an Err", this, config);
@@ -723,17 +758,17 @@ var triggerRouteFunction = async ({
723
758
  return ok("workflow-finished");
724
759
  } catch (error) {
725
760
  const error_ = error;
726
- if (error instanceof import_qstash3.QstashError && error.status === 400) {
761
+ if (isInstanceOf(error, import_qstash3.QstashError) && error.status === 400) {
727
762
  await debug?.log("WARN", "RESPONSE_WORKFLOW", {
728
763
  message: `tried to append to a cancelled workflow. exiting without publishing.`,
729
764
  name: error.name,
730
765
  errorMessage: error.message
731
766
  });
732
767
  return ok("workflow-was-finished");
733
- } else if (!(error_ instanceof WorkflowAbort)) {
734
- return err(error_);
735
- } else if (error_ instanceof WorkflowNonRetryableError) {
768
+ } else if (isInstanceOf(error_, WorkflowNonRetryableError) || isInstanceOf(error_, WorkflowRetryAfterError)) {
736
769
  return ok(error_);
770
+ } else if (!isInstanceOf(error_, WorkflowAbort)) {
771
+ return err(error_);
737
772
  } else if (error_.cancelWorkflow) {
738
773
  await onCancel();
739
774
  return ok("workflow-finished");
@@ -1566,20 +1601,6 @@ var LazyInvokeStep = class extends BaseLazyStep {
1566
1601
  }
1567
1602
  };
1568
1603
 
1569
- // src/agents/constants.ts
1570
- var AGENT_NAME_HEADER = "upstash-agent-name";
1571
- var MANAGER_AGENT_PROMPT = `You are an agent orchestrating other AI Agents.
1572
-
1573
- These other agents have tools available to them.
1574
-
1575
- Given a prompt, utilize these agents to address requests.
1576
-
1577
- 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.
1578
-
1579
- Avoid calling the same agent twice in one turn. Instead, prefer to call it once but provide everything
1580
- you need from that agent.
1581
- `;
1582
-
1583
1604
  // src/qstash/headers.ts
1584
1605
  var WorkflowHeaders = class {
1585
1606
  userHeaders;
@@ -1628,8 +1649,7 @@ var WorkflowHeaders = class {
1628
1649
  [WORKFLOW_URL_HEADER]: this.workflowConfig.workflowUrl,
1629
1650
  [WORKFLOW_FEATURE_HEADER]: "LazyFetch,InitialBody,WF_DetectTrigger" + (this.keepTriggerConfig ? ",WF_TriggerOnConfig" : ""),
1630
1651
  [WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION,
1631
- ...this.workflowConfig.telemetry ? getTelemetryHeaders(this.workflowConfig.telemetry) : {},
1632
- ...this.workflowConfig.telemetry && this.stepInfo?.lazyStep instanceof LazyCallStep && this.stepInfo.lazyStep.headers[AGENT_NAME_HEADER] ? { [TELEMETRY_HEADER_AGENT]: "true" } : {}
1652
+ ...this.workflowConfig.telemetry ? getTelemetryHeaders(this.workflowConfig.telemetry) : {}
1633
1653
  };
1634
1654
  if (this.stepInfo?.lazyStep.stepType !== "Call") {
1635
1655
  this.headers.rawHeaders[`Upstash-Forward-${WORKFLOW_PROTOCOL_VERSION_HEADER}`] = WORKFLOW_PROTOCOL_VERSION;
@@ -2040,7 +2060,7 @@ var AutoExecutor = class _AutoExecutor {
2040
2060
  });
2041
2061
  throw new WorkflowAbort(parallelStep.stepName, resultStep);
2042
2062
  } catch (error) {
2043
- if (error instanceof WorkflowAbort || error instanceof import_qstash5.QstashError && error.status === 400) {
2063
+ if (isInstanceOf(error, WorkflowAbort) || isInstanceOf(error, import_qstash5.QstashError) && error.status === 400) {
2044
2064
  throw error;
2045
2065
  }
2046
2066
  throw new WorkflowError(
@@ -2147,7 +2167,7 @@ var validateParallelSteps = (lazySteps, stepsFromRequest) => {
2147
2167
  validateStep(lazySteps[index], stepFromRequest);
2148
2168
  }
2149
2169
  } catch (error) {
2150
- if (error instanceof WorkflowError) {
2170
+ if (isInstanceOf(error, WorkflowError)) {
2151
2171
  const lazyStepNames = lazySteps.map((lazyStep) => lazyStep.stepName);
2152
2172
  const lazyStepTypes = lazySteps.map((lazyStep) => lazyStep.stepType);
2153
2173
  const requestStepNames = stepsFromRequest.map((step) => step.stepName);
@@ -2292,340 +2312,6 @@ var WorkflowApi = class extends BaseWorkflowApi {
2292
2312
  }
2293
2313
  };
2294
2314
 
2295
- // src/agents/index.ts
2296
- var import_openai2 = require("@ai-sdk/openai");
2297
-
2298
- // src/agents/adapters.ts
2299
- var import_ai = require("ai");
2300
- var fetchWithContextCall = async (context, agentCallParams, ...params) => {
2301
- const [input, init] = params;
2302
- try {
2303
- const headers = init?.headers ? Object.fromEntries(new Headers(init.headers).entries()) : {};
2304
- const body = init?.body ? JSON.parse(init.body) : void 0;
2305
- const agentName = headers[AGENT_NAME_HEADER];
2306
- const stepName = agentName ? `Call Agent ${agentName}` : "Call Agent";
2307
- const responseInfo = await context.call(stepName, {
2308
- url: input.toString(),
2309
- method: init?.method,
2310
- headers,
2311
- body,
2312
- timeout: agentCallParams?.timeout,
2313
- retries: agentCallParams?.retries,
2314
- retryDelay: agentCallParams?.retryDelay,
2315
- flowControl: agentCallParams?.flowControl
2316
- });
2317
- const responseHeaders = new Headers(
2318
- Object.entries(responseInfo.header).reduce(
2319
- (acc, [key, values]) => {
2320
- acc[key] = values.join(", ");
2321
- return acc;
2322
- },
2323
- {}
2324
- )
2325
- );
2326
- return new Response(JSON.stringify(responseInfo.body), {
2327
- status: responseInfo.status,
2328
- headers: responseHeaders
2329
- });
2330
- } catch (error) {
2331
- if (error instanceof Error && error.name === "WorkflowAbort") {
2332
- throw error;
2333
- } else {
2334
- console.error("Error in fetch implementation:", error);
2335
- throw error;
2336
- }
2337
- }
2338
- };
2339
- var createWorkflowModel = ({
2340
- context,
2341
- provider,
2342
- providerParams,
2343
- agentCallParams
2344
- }) => {
2345
- return provider({
2346
- fetch: (...params) => fetchWithContextCall(context, agentCallParams, ...params),
2347
- ...providerParams
2348
- });
2349
- };
2350
- var wrapTools = ({
2351
- context,
2352
- tools
2353
- }) => {
2354
- return Object.fromEntries(
2355
- Object.entries(tools).map((toolInfo) => {
2356
- const [toolName, tool3] = toolInfo;
2357
- const executeAsStep = "executeAsStep" in tool3 ? tool3.executeAsStep : true;
2358
- const aiSDKTool = convertToAISDKTool(tool3);
2359
- const execute = aiSDKTool.execute;
2360
- if (execute && executeAsStep) {
2361
- const wrappedExecute = (...params) => {
2362
- return context.run(`Run tool ${toolName}`, () => execute(...params));
2363
- };
2364
- aiSDKTool.execute = wrappedExecute;
2365
- }
2366
- return [toolName, aiSDKTool];
2367
- })
2368
- );
2369
- };
2370
- var convertToAISDKTool = (tool3) => {
2371
- const isLangchainTool = "invoke" in tool3;
2372
- return isLangchainTool ? convertLangchainTool(tool3) : tool3;
2373
- };
2374
- var convertLangchainTool = (langchainTool) => {
2375
- return (0, import_ai.tool)({
2376
- description: langchainTool.description,
2377
- parameters: langchainTool.schema,
2378
- execute: async (...param) => langchainTool.invoke(...param)
2379
- });
2380
- };
2381
- var WorkflowTool = class {
2382
- /**
2383
- * description of the tool
2384
- */
2385
- description;
2386
- /**
2387
- * schema of the tool
2388
- */
2389
- schema;
2390
- /**
2391
- * function to invoke the tool
2392
- */
2393
- invoke;
2394
- /**
2395
- * whether the invoke method of the tool is to be wrapped with `context.run`
2396
- */
2397
- executeAsStep;
2398
- /**
2399
- *
2400
- * @param description description of the tool
2401
- * @param schema schema of the tool
2402
- * @param invoke function to invoke the tool
2403
- * @param executeAsStep whether the invoke method of the tool is to be wrapped with `context.run`
2404
- */
2405
- constructor(params) {
2406
- this.description = params.description;
2407
- this.schema = params.schema;
2408
- this.invoke = params.invoke;
2409
- this.executeAsStep = params.executeAsStep ?? true;
2410
- }
2411
- };
2412
-
2413
- // src/agents/agent.ts
2414
- var import_zod = require("zod");
2415
- var import_ai2 = require("ai");
2416
-
2417
- // src/serve/utils.ts
2418
- var isDisabledWorkflowContext = (context) => {
2419
- return "disabled" in context;
2420
- };
2421
-
2422
- // src/agents/agent.ts
2423
- var Agent = class {
2424
- name;
2425
- tools;
2426
- maxSteps;
2427
- background;
2428
- model;
2429
- temparature;
2430
- context;
2431
- constructor({ tools, maxSteps, background, name, model, temparature = 0.1 }, context) {
2432
- this.name = name;
2433
- this.tools = tools ?? {};
2434
- this.maxSteps = maxSteps;
2435
- this.background = background;
2436
- this.model = model;
2437
- this.temparature = temparature;
2438
- this.context = context;
2439
- }
2440
- /**
2441
- * Trigger the agent by passing a prompt
2442
- *
2443
- * @param prompt task to assign to the agent
2444
- * @returns Response as `{ text: string }`
2445
- */
2446
- async call({ prompt }) {
2447
- try {
2448
- if (isDisabledWorkflowContext(this.context)) {
2449
- await this.context.sleep("abort", 0);
2450
- }
2451
- const result = await (0, import_ai2.generateText)({
2452
- model: this.model,
2453
- tools: this.tools,
2454
- maxSteps: this.maxSteps,
2455
- system: this.background,
2456
- prompt,
2457
- headers: {
2458
- [AGENT_NAME_HEADER]: this.name
2459
- },
2460
- temperature: this.temparature
2461
- });
2462
- return { text: result.text };
2463
- } catch (error) {
2464
- if (error instanceof import_ai2.ToolExecutionError) {
2465
- if (error.cause instanceof Error && error.cause.name === "WorkflowAbort") {
2466
- throw error.cause;
2467
- } else if (error.cause instanceof import_ai2.ToolExecutionError && error.cause.cause instanceof Error && error.cause.cause.name === "WorkflowAbort") {
2468
- throw error.cause.cause;
2469
- } else {
2470
- throw error;
2471
- }
2472
- } else {
2473
- throw error;
2474
- }
2475
- }
2476
- }
2477
- /**
2478
- * Convert the agent to a tool which can be used by other agents.
2479
- *
2480
- * @returns the agent as a tool
2481
- */
2482
- asTool() {
2483
- const toolDescriptions = Object.values(this.tools).map((tool3) => tool3.description).join("\n");
2484
- return (0, import_ai2.tool)({
2485
- parameters: import_zod.z.object({ prompt: import_zod.z.string() }),
2486
- execute: async ({ prompt }) => {
2487
- return await this.call({ prompt });
2488
- },
2489
- description: `An AI Agent with the following background: ${this.background}Has access to the following tools: ${toolDescriptions}`
2490
- });
2491
- }
2492
- };
2493
- var ManagerAgent = class extends Agent {
2494
- agents;
2495
- /**
2496
- * A manager agent which coordinates agents available to it to achieve a
2497
- * given task
2498
- *
2499
- * @param name Name of the agent
2500
- * @param background Background of the agent. If not passed, default will be used.
2501
- * @param model LLM model to use
2502
- * @param agents: List of agents available to the agent
2503
- * @param maxSteps number of times the manager agent can call the LLM at most.
2504
- * If the agent abruptly stops execution after calling other agents, you may
2505
- * need to increase maxSteps
2506
- */
2507
- constructor({
2508
- agents,
2509
- background = MANAGER_AGENT_PROMPT,
2510
- model,
2511
- maxSteps,
2512
- name = "manager llm"
2513
- }, context) {
2514
- super(
2515
- {
2516
- background,
2517
- maxSteps,
2518
- tools: Object.fromEntries(agents.map((agent) => [agent.name, agent.asTool()])),
2519
- name,
2520
- model
2521
- },
2522
- context
2523
- );
2524
- this.agents = agents;
2525
- }
2526
- };
2527
-
2528
- // src/agents/task.ts
2529
- var Task = class {
2530
- context;
2531
- taskParameters;
2532
- constructor({
2533
- context,
2534
- taskParameters
2535
- }) {
2536
- this.context = context;
2537
- this.taskParameters = taskParameters;
2538
- }
2539
- /**
2540
- * Run the agents to complete the task
2541
- *
2542
- * @returns Result of the task as { text: string }
2543
- */
2544
- async run() {
2545
- const { prompt, ...otherParams } = this.taskParameters;
2546
- if ("agent" in otherParams) {
2547
- const agent = otherParams.agent;
2548
- const result = await agent.call({
2549
- prompt
2550
- });
2551
- return { text: result.text };
2552
- } else {
2553
- const { agents, maxSteps, model, background } = otherParams;
2554
- const managerAgent = new ManagerAgent(
2555
- {
2556
- model,
2557
- maxSteps,
2558
- agents,
2559
- name: "Manager LLM",
2560
- background
2561
- },
2562
- this.context
2563
- );
2564
- const result = await managerAgent.call({ prompt });
2565
- return { text: result.text };
2566
- }
2567
- }
2568
- };
2569
-
2570
- // src/agents/index.ts
2571
- var WorkflowAgents = class {
2572
- context;
2573
- constructor({ context }) {
2574
- this.context = context;
2575
- }
2576
- /**
2577
- * Defines an agent
2578
- *
2579
- * ```ts
2580
- * const researcherAgent = context.agents.agent({
2581
- * model,
2582
- * name: 'academic',
2583
- * maxSteps: 2,
2584
- * tools: {
2585
- * wikiTool: new WikipediaQueryRun({
2586
- * topKResults: 1,
2587
- * maxDocContentLength: 500,
2588
- * })
2589
- * },
2590
- * background:
2591
- * 'You are researcher agent with access to Wikipedia. ' +
2592
- * 'Utilize Wikipedia as much as possible for correct information',
2593
- * });
2594
- * ```
2595
- *
2596
- * @param params agent parameters
2597
- * @returns
2598
- */
2599
- agent(params) {
2600
- const wrappedTools = wrapTools({ context: this.context, tools: params.tools });
2601
- return new Agent(
2602
- {
2603
- ...params,
2604
- tools: wrappedTools
2605
- },
2606
- this.context
2607
- );
2608
- }
2609
- task(taskParameters) {
2610
- return new Task({ context: this.context, taskParameters });
2611
- }
2612
- /**
2613
- * creates an openai model for agents
2614
- */
2615
- openai(...params) {
2616
- const [model, settings] = params;
2617
- const { baseURL, apiKey, callSettings, ...otherSettings } = settings ?? {};
2618
- const openaiModel = this.AISDKModel({
2619
- context: this.context,
2620
- provider: import_openai2.createOpenAI,
2621
- providerParams: { baseURL, apiKey, compatibility: "strict" },
2622
- agentCallParams: callSettings
2623
- });
2624
- return openaiModel(model, otherSettings);
2625
- }
2626
- AISDKModel = createWorkflowModel;
2627
- };
2628
-
2629
2315
  // src/serve/serve-many.ts
2630
2316
  var getNewUrlFromWorkflowId = (url, workflowId) => {
2631
2317
  if (!workflowId) {
@@ -2867,7 +2553,7 @@ var WorkflowContext = class {
2867
2553
  * @returns result of the step function
2868
2554
  */
2869
2555
  async run(stepName, stepFunction) {
2870
- const wrappedStepFunction = () => this.executor.wrapStep(stepName, stepFunction);
2556
+ const wrappedStepFunction = (() => this.executor.wrapStep(stepName, stepFunction));
2871
2557
  return await this.addStep(new LazyFunctionStep(stepName, wrappedStepFunction));
2872
2558
  }
2873
2559
  /**
@@ -3038,11 +2724,6 @@ var WorkflowContext = class {
3038
2724
  context: this
3039
2725
  });
3040
2726
  }
3041
- get agents() {
3042
- return new WorkflowAgents({
3043
- context: this
3044
- });
3045
- }
3046
2727
  };
3047
2728
 
3048
2729
  // src/logger.ts
@@ -3146,7 +2827,7 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
3146
2827
  try {
3147
2828
  await routeFunction(disabledContext);
3148
2829
  } catch (error) {
3149
- if (error instanceof WorkflowAbort && error.stepName === this.disabledMessage || error instanceof WorkflowNonRetryableError) {
2830
+ if (isInstanceOf(error, WorkflowAbort) && error.stepName === this.disabledMessage || isInstanceOf(error, WorkflowNonRetryableError) || isInstanceOf(error, WorkflowRetryAfterError)) {
3150
2831
  return ok("step-found");
3151
2832
  }
3152
2833
  console.warn(
@@ -3399,13 +3080,24 @@ var processOptions = (options) => {
3399
3080
  },
3400
3081
  status: 489
3401
3082
  });
3402
- } else if (detailedFinishCondition?.condition === "failure-callback") {
3403
- return new Response(detailedFinishCondition.result ?? void 0, {
3404
- status: 200,
3083
+ } else if (detailedFinishCondition?.condition === "retry-after-error") {
3084
+ return new Response(JSON.stringify(formatWorkflowError(detailedFinishCondition.result)), {
3405
3085
  headers: {
3086
+ "Retry-After": detailedFinishCondition.result.retryAfter.toString(),
3406
3087
  [WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
3407
- }
3088
+ },
3089
+ status: 429
3408
3090
  });
3091
+ } else if (detailedFinishCondition?.condition === "failure-callback") {
3092
+ return new Response(
3093
+ JSON.stringify({ result: detailedFinishCondition.result ?? void 0 }),
3094
+ {
3095
+ status: 200,
3096
+ headers: {
3097
+ [WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
3098
+ }
3099
+ }
3100
+ );
3409
3101
  }
3410
3102
  return new Response(JSON.stringify({ workflowRunId }), {
3411
3103
  status: 200,
@@ -3615,12 +3307,18 @@ var serveBase = (routeFunction, telemetry, options) => {
3615
3307
  },
3616
3308
  debug
3617
3309
  });
3618
- if (result.isOk() && result.value instanceof WorkflowNonRetryableError) {
3310
+ if (result.isOk() && isInstanceOf(result.value, WorkflowNonRetryableError)) {
3619
3311
  return onStepFinish(workflowRunId, result.value, {
3620
3312
  condition: "non-retryable-error",
3621
3313
  result: result.value
3622
3314
  });
3623
3315
  }
3316
+ if (result.isOk() && isInstanceOf(result.value, WorkflowRetryAfterError)) {
3317
+ return onStepFinish(workflowRunId, result.value, {
3318
+ condition: "retry-after-error",
3319
+ result: result.value
3320
+ });
3321
+ }
3624
3322
  if (result.isErr()) {
3625
3323
  await debug?.log("ERROR", "ERROR", { error: result.error.message });
3626
3324
  throw result.error;
@@ -3651,7 +3349,7 @@ var serveBase = (routeFunction, telemetry, options) => {
3651
3349
  const errorMessage = `Error while running onError callback: '${formattedOnErrorError.message}'.
3652
3350
  Original error: '${formattedError.message}'`;
3653
3351
  console.error(errorMessage);
3654
- return new Response(errorMessage, {
3352
+ return new Response(JSON.stringify({ error: errorMessage }), {
3655
3353
  status: 500,
3656
3354
  headers: {
3657
3355
  [WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
@@ -3909,7 +3607,6 @@ var Client4 = class {
3909
3607
  const finalWorkflowRunId = getWorkflowRunId(option.workflowRunId);
3910
3608
  const context = new WorkflowContext({
3911
3609
  qstashClient: this.client,
3912
- // @ts-expect-error header type mismatch because of bun
3913
3610
  headers: new Headers({
3914
3611
  ...option.headers ?? {},
3915
3612
  ...option.label ? { [WORKFLOW_LABEL_HEADER]: option.label } : {}
@@ -3920,14 +3617,14 @@ var Client4 = class {
3920
3617
  workflowRunId: finalWorkflowRunId,
3921
3618
  retries: option.retries,
3922
3619
  retryDelay: option.retryDelay,
3923
- telemetry: { sdk: SDK_TELEMETRY },
3620
+ telemetry: option.disableTelemetry ? void 0 : { sdk: SDK_TELEMETRY },
3924
3621
  flowControl: option.flowControl,
3925
3622
  failureUrl,
3926
3623
  label: option.label
3927
3624
  });
3928
3625
  return {
3929
3626
  workflowContext: context,
3930
- telemetry: { sdk: SDK_TELEMETRY },
3627
+ telemetry: option.disableTelemetry ? void 0 : { sdk: SDK_TELEMETRY },
3931
3628
  delay: option.delay,
3932
3629
  notBefore: option.notBefore,
3933
3630
  keepTriggerConfig: option.keepTriggerConfig
@@ -4012,6 +3709,6 @@ var Client4 = class {
4012
3709
  WorkflowError,
4013
3710
  WorkflowLogger,
4014
3711
  WorkflowNonRetryableError,
4015
- WorkflowTool,
3712
+ WorkflowRetryAfterError,
4016
3713
  serve
4017
3714
  });