@upstash/workflow 0.2.3 → 0.2.5-agents

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
@@ -90,6 +90,23 @@ var getSteps = async (requester, workflowRunId, messageId, debug) => {
90
90
  }
91
91
  };
92
92
 
93
+ // src/constants.ts
94
+ var WORKFLOW_ID_HEADER = "Upstash-Workflow-RunId";
95
+ var WORKFLOW_INIT_HEADER = "Upstash-Workflow-Init";
96
+ var WORKFLOW_URL_HEADER = "Upstash-Workflow-Url";
97
+ var WORKFLOW_FAILURE_HEADER = "Upstash-Workflow-Is-Failure";
98
+ var WORKFLOW_FEATURE_HEADER = "Upstash-Feature-Set";
99
+ var WORKFLOW_PROTOCOL_VERSION = "1";
100
+ var WORKFLOW_PROTOCOL_VERSION_HEADER = "Upstash-Workflow-Sdk-Version";
101
+ var DEFAULT_CONTENT_TYPE = "application/json";
102
+ var NO_CONCURRENCY = 1;
103
+ var DEFAULT_RETRIES = 3;
104
+ var VERSION = "v0.2.3";
105
+ var SDK_TELEMETRY = `@upstash/workflow@${VERSION}`;
106
+ var TELEMETRY_HEADER_SDK = "Upstash-Telemetry-Sdk";
107
+ var TELEMETRY_HEADER_FRAMEWORK = "Upstash-Telemetry-Framework";
108
+ var TELEMETRY_HEADER_RUNTIME = "Upstash-Telemetry-Runtime";
109
+
93
110
  // src/error.ts
94
111
  var import_qstash2 = require("@upstash/qstash");
95
112
  var WorkflowError = class extends import_qstash2.QstashError {
@@ -727,18 +744,6 @@ var Err = class {
727
744
  };
728
745
  var fromThrowable = Result.fromThrowable;
729
746
 
730
- // src/constants.ts
731
- var WORKFLOW_ID_HEADER = "Upstash-Workflow-RunId";
732
- var WORKFLOW_INIT_HEADER = "Upstash-Workflow-Init";
733
- var WORKFLOW_URL_HEADER = "Upstash-Workflow-Url";
734
- var WORKFLOW_FAILURE_HEADER = "Upstash-Workflow-Is-Failure";
735
- var WORKFLOW_FEATURE_HEADER = "Upstash-Feature-Set";
736
- var WORKFLOW_PROTOCOL_VERSION = "1";
737
- var WORKFLOW_PROTOCOL_VERSION_HEADER = "Upstash-Workflow-Sdk-Version";
738
- var DEFAULT_CONTENT_TYPE = "application/json";
739
- var NO_CONCURRENCY = 1;
740
- var DEFAULT_RETRIES = 3;
741
-
742
747
  // src/types.ts
743
748
  var StepTypes = [
744
749
  "Initial",
@@ -752,16 +757,21 @@ var StepTypes = [
752
757
 
753
758
  // src/workflow-requests.ts
754
759
  var import_qstash3 = require("@upstash/qstash");
755
- var triggerFirstInvocation = async (workflowContext, retries, useJSONContent, debug) => {
756
- const { headers } = getHeaders(
757
- "true",
758
- workflowContext.workflowRunId,
759
- workflowContext.url,
760
- workflowContext.headers,
761
- void 0,
762
- workflowContext.failureUrl,
763
- retries
764
- );
760
+ var triggerFirstInvocation = async ({
761
+ workflowContext,
762
+ useJSONContent,
763
+ telemetry,
764
+ debug
765
+ }) => {
766
+ const { headers } = getHeaders({
767
+ initHeaderValue: "true",
768
+ workflowRunId: workflowContext.workflowRunId,
769
+ workflowUrl: workflowContext.url,
770
+ userHeaders: workflowContext.headers,
771
+ failureUrl: workflowContext.failureUrl,
772
+ retries: workflowContext.retries,
773
+ telemetry
774
+ });
765
775
  if (useJSONContent) {
766
776
  headers["content-type"] = "application/json";
767
777
  }
@@ -867,7 +877,16 @@ var recreateUserHeaders = (headers) => {
867
877
  }
868
878
  return filteredHeaders;
869
879
  };
870
- var handleThirdPartyCallResult = async (request, requestPayload, client, workflowUrl, failureUrl, retries, debug) => {
880
+ var handleThirdPartyCallResult = async ({
881
+ request,
882
+ requestPayload,
883
+ client,
884
+ workflowUrl,
885
+ failureUrl,
886
+ retries,
887
+ telemetry,
888
+ debug
889
+ }) => {
871
890
  try {
872
891
  if (request.headers.get("Upstash-Workflow-Callback")) {
873
892
  let callbackPayload;
@@ -926,15 +945,15 @@ ${atob(callbackMessage.body ?? "")}`
926
945
  );
927
946
  }
928
947
  const userHeaders = recreateUserHeaders(request.headers);
929
- const { headers: requestHeaders } = getHeaders(
930
- "false",
948
+ const { headers: requestHeaders } = getHeaders({
949
+ initHeaderValue: "false",
931
950
  workflowRunId,
932
951
  workflowUrl,
933
952
  userHeaders,
934
- void 0,
935
953
  failureUrl,
936
- retries
937
- );
954
+ retries,
955
+ telemetry
956
+ });
938
957
  const callResponse = {
939
958
  status: callbackMessage.status,
940
959
  body: atob(callbackMessage.body ?? ""),
@@ -972,12 +991,31 @@ ${atob(callbackMessage.body ?? "")}`
972
991
  );
973
992
  }
974
993
  };
975
- var getHeaders = (initHeaderValue, workflowRunId, workflowUrl, userHeaders, step, failureUrl, retries, callRetries, callTimeout) => {
994
+ var getTelemetryHeaders = (telemetry) => {
995
+ return {
996
+ [TELEMETRY_HEADER_SDK]: telemetry.sdk,
997
+ [TELEMETRY_HEADER_FRAMEWORK]: telemetry.framework,
998
+ [TELEMETRY_HEADER_RUNTIME]: telemetry.runtime ?? "unknown"
999
+ };
1000
+ };
1001
+ var getHeaders = ({
1002
+ initHeaderValue,
1003
+ workflowRunId,
1004
+ workflowUrl,
1005
+ userHeaders,
1006
+ failureUrl,
1007
+ retries,
1008
+ step,
1009
+ callRetries,
1010
+ callTimeout,
1011
+ telemetry
1012
+ }) => {
976
1013
  const baseHeaders = {
977
1014
  [WORKFLOW_INIT_HEADER]: initHeaderValue,
978
1015
  [WORKFLOW_ID_HEADER]: workflowRunId,
979
1016
  [WORKFLOW_URL_HEADER]: workflowUrl,
980
- [WORKFLOW_FEATURE_HEADER]: "LazyFetch,InitialBody"
1017
+ [WORKFLOW_FEATURE_HEADER]: "LazyFetch,InitialBody",
1018
+ ...telemetry ? getTelemetryHeaders(telemetry) : {}
981
1019
  };
982
1020
  if (!step?.callUrl) {
983
1021
  baseHeaders[`Upstash-Forward-${WORKFLOW_PROTOCOL_VERSION_HEADER}`] = WORKFLOW_PROTOCOL_VERSION;
@@ -1051,6 +1089,13 @@ var getHeaders = (initHeaderValue, workflowRunId, workflowUrl, userHeaders, step
1051
1089
  ...Object.fromEntries(
1052
1090
  Object.entries(baseHeaders).map(([header, value]) => [header, [value]])
1053
1091
  ),
1092
+ // to include telemetry headers:
1093
+ ...telemetry ? Object.fromEntries(
1094
+ Object.entries(getTelemetryHeaders(telemetry)).map(([header, value]) => [
1095
+ header,
1096
+ [value]
1097
+ ])
1098
+ ) : {},
1054
1099
  // note: using WORKFLOW_ID_HEADER doesn't work, because Runid -> RunId:
1055
1100
  "Upstash-Workflow-Runid": [workflowRunId],
1056
1101
  [WORKFLOW_INIT_HEADER]: ["false"],
@@ -1089,6 +1134,7 @@ If you want to disable QStash Verification, you should clear env variables QSTAS
1089
1134
  };
1090
1135
 
1091
1136
  // src/context/auto-executor.ts
1137
+ var import_qstash4 = require("@upstash/qstash");
1092
1138
  var AutoExecutor = class _AutoExecutor {
1093
1139
  context;
1094
1140
  promises = /* @__PURE__ */ new WeakMap();
@@ -1097,13 +1143,15 @@ var AutoExecutor = class _AutoExecutor {
1097
1143
  nonPlanStepCount;
1098
1144
  steps;
1099
1145
  indexInCurrentList = 0;
1146
+ telemetry;
1100
1147
  stepCount = 0;
1101
1148
  planStepCount = 0;
1102
1149
  executingStep = false;
1103
- constructor(context, steps, debug) {
1150
+ constructor(context, steps, telemetry, debug) {
1104
1151
  this.context = context;
1105
- this.debug = debug;
1106
1152
  this.steps = steps;
1153
+ this.telemetry = telemetry;
1154
+ this.debug = debug;
1107
1155
  this.nonPlanStepCount = this.steps.filter((step) => !step.targetStep).length;
1108
1156
  }
1109
1157
  /**
@@ -1246,7 +1294,7 @@ var AutoExecutor = class _AutoExecutor {
1246
1294
  );
1247
1295
  await this.submitStepsToQStash([resultStep], [parallelStep]);
1248
1296
  } catch (error) {
1249
- if (error instanceof WorkflowAbort) {
1297
+ if (error instanceof WorkflowAbort || error instanceof import_qstash4.QstashError && error.status === 400) {
1250
1298
  throw error;
1251
1299
  }
1252
1300
  throw new WorkflowError(
@@ -1317,15 +1365,16 @@ var AutoExecutor = class _AutoExecutor {
1317
1365
  });
1318
1366
  if (steps[0].waitEventId && steps.length === 1) {
1319
1367
  const waitStep = steps[0];
1320
- const { headers, timeoutHeaders } = getHeaders(
1321
- "false",
1322
- this.context.workflowRunId,
1323
- this.context.url,
1324
- this.context.headers,
1325
- waitStep,
1326
- this.context.failureUrl,
1327
- this.context.retries
1328
- );
1368
+ const { headers, timeoutHeaders } = getHeaders({
1369
+ initHeaderValue: "false",
1370
+ workflowRunId: this.context.workflowRunId,
1371
+ workflowUrl: this.context.url,
1372
+ userHeaders: this.context.headers,
1373
+ step: waitStep,
1374
+ failureUrl: this.context.failureUrl,
1375
+ retries: this.context.retries,
1376
+ telemetry: this.telemetry
1377
+ });
1329
1378
  const waitBody = {
1330
1379
  url: this.context.url,
1331
1380
  timeout: waitStep.timeout,
@@ -1352,17 +1401,18 @@ var AutoExecutor = class _AutoExecutor {
1352
1401
  const result = await this.context.qstashClient.batchJSON(
1353
1402
  steps.map((singleStep, index) => {
1354
1403
  const lazyStep = lazySteps[index];
1355
- const { headers } = getHeaders(
1356
- "false",
1357
- this.context.workflowRunId,
1358
- this.context.url,
1359
- this.context.headers,
1360
- singleStep,
1361
- this.context.failureUrl,
1362
- this.context.retries,
1363
- lazyStep instanceof LazyCallStep ? lazyStep.retries : void 0,
1364
- lazyStep instanceof LazyCallStep ? lazyStep.timeout : void 0
1365
- );
1404
+ const { headers } = getHeaders({
1405
+ initHeaderValue: "false",
1406
+ workflowRunId: this.context.workflowRunId,
1407
+ workflowUrl: this.context.url,
1408
+ userHeaders: this.context.headers,
1409
+ step: singleStep,
1410
+ failureUrl: this.context.failureUrl,
1411
+ retries: this.context.retries,
1412
+ callRetries: lazyStep instanceof LazyCallStep ? lazyStep.retries : void 0,
1413
+ callTimeout: lazyStep instanceof LazyCallStep ? lazyStep.timeout : void 0,
1414
+ telemetry: this.telemetry
1415
+ });
1366
1416
  const willWait = singleStep.concurrent === NO_CONCURRENCY || singleStep.stepId === 0;
1367
1417
  singleStep.out = JSON.stringify(singleStep.out);
1368
1418
  return singleStep.callUrl ? (
@@ -1475,7 +1525,7 @@ var sortSteps = (steps) => {
1475
1525
  };
1476
1526
 
1477
1527
  // src/context/api/anthropic.ts
1478
- var import_qstash4 = require("@upstash/qstash");
1528
+ var import_qstash5 = require("@upstash/qstash");
1479
1529
 
1480
1530
  // src/context/provider.ts
1481
1531
  var getProviderInfo = (api) => {
@@ -1539,7 +1589,7 @@ var AnthropicAPI = class extends BaseWorkflowApi {
1539
1589
  return await this.callApi(stepName, {
1540
1590
  api: {
1541
1591
  name: "llm",
1542
- provider: (0, import_qstash4.anthropic)({ token })
1592
+ provider: (0, import_qstash5.anthropic)({ token })
1543
1593
  },
1544
1594
  ...parameters
1545
1595
  });
@@ -1547,14 +1597,14 @@ var AnthropicAPI = class extends BaseWorkflowApi {
1547
1597
  };
1548
1598
 
1549
1599
  // src/context/api/openai.ts
1550
- var import_qstash5 = require("@upstash/qstash");
1600
+ var import_qstash6 = require("@upstash/qstash");
1551
1601
  var OpenAIAPI = class extends BaseWorkflowApi {
1552
1602
  async call(stepName, settings) {
1553
1603
  const { token, organization, operation, ...parameters } = settings;
1554
1604
  return await this.callApi(stepName, {
1555
1605
  api: {
1556
1606
  name: "llm",
1557
- provider: (0, import_qstash5.openai)({ token, organization })
1607
+ provider: (0, import_qstash6.openai)({ token, organization })
1558
1608
  },
1559
1609
  ...parameters
1560
1610
  });
@@ -1562,14 +1612,14 @@ var OpenAIAPI = class extends BaseWorkflowApi {
1562
1612
  };
1563
1613
 
1564
1614
  // src/context/api/resend.ts
1565
- var import_qstash6 = require("@upstash/qstash");
1615
+ var import_qstash7 = require("@upstash/qstash");
1566
1616
  var ResendAPI = class extends BaseWorkflowApi {
1567
1617
  async call(stepName, settings) {
1568
1618
  const { token, batch = false, ...parameters } = settings;
1569
1619
  return await this.callApi(stepName, {
1570
1620
  api: {
1571
1621
  name: "email",
1572
- provider: (0, import_qstash6.resend)({ token, batch })
1622
+ provider: (0, import_qstash7.resend)({ token, batch })
1573
1623
  },
1574
1624
  ...parameters
1575
1625
  });
@@ -1595,6 +1645,216 @@ var WorkflowApi = class extends BaseWorkflowApi {
1595
1645
  }
1596
1646
  };
1597
1647
 
1648
+ // src/agents/adapters.ts
1649
+ var import_openai2 = require("@ai-sdk/openai");
1650
+ var import_ai = require("ai");
1651
+ var AGENT_NAME_HEADER = "upstash-agent-name";
1652
+ var createWorkflowOpenAI = (context) => {
1653
+ return (0, import_openai2.createOpenAI)({
1654
+ compatibility: "strict",
1655
+ fetch: async (input, init) => {
1656
+ try {
1657
+ const headers = init?.headers ? Object.fromEntries(new Headers(init.headers).entries()) : {};
1658
+ const body = init?.body ? JSON.parse(init.body) : void 0;
1659
+ const agentName = headers[AGENT_NAME_HEADER];
1660
+ const stepName = agentName ? `Call Agent ${agentName}` : "Call Agent";
1661
+ const responseInfo = await context.call(stepName, {
1662
+ url: input.toString(),
1663
+ method: init?.method,
1664
+ headers,
1665
+ body
1666
+ });
1667
+ const responseHeaders = new Headers(
1668
+ Object.entries(responseInfo.header).reduce(
1669
+ (acc, [key, values]) => {
1670
+ acc[key] = values.join(", ");
1671
+ return acc;
1672
+ },
1673
+ {}
1674
+ )
1675
+ );
1676
+ return new Response(JSON.stringify(responseInfo.body), {
1677
+ status: responseInfo.status,
1678
+ headers: responseHeaders
1679
+ });
1680
+ } catch (error) {
1681
+ if (error instanceof Error && error.name === "WorkflowAbort") {
1682
+ throw error;
1683
+ } else {
1684
+ console.error("Error in fetch implementation:", error);
1685
+ throw error;
1686
+ }
1687
+ }
1688
+ }
1689
+ });
1690
+ };
1691
+ var wrapTools = ({
1692
+ context,
1693
+ tools
1694
+ }) => {
1695
+ return Object.fromEntries(
1696
+ Object.entries(tools).map((toolInfo) => {
1697
+ const [toolName, tool3] = toolInfo;
1698
+ const aiSDKTool = convertToAISDKTool(tool3);
1699
+ const execute = aiSDKTool.execute;
1700
+ if (execute) {
1701
+ const wrappedExecute = (...params) => {
1702
+ return context.run(`Run tool ${toolName}`, () => execute(...params));
1703
+ };
1704
+ aiSDKTool.execute = wrappedExecute;
1705
+ }
1706
+ return [toolName, aiSDKTool];
1707
+ })
1708
+ );
1709
+ };
1710
+ var convertToAISDKTool = (tool3) => {
1711
+ const isLangchainTool = "invoke" in tool3;
1712
+ return isLangchainTool ? convertLangchainTool(tool3) : tool3;
1713
+ };
1714
+ var convertLangchainTool = (langchainTool) => {
1715
+ return (0, import_ai.tool)({
1716
+ description: langchainTool.description,
1717
+ parameters: langchainTool.schema,
1718
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1719
+ execute: async (param) => langchainTool.invoke(param)
1720
+ });
1721
+ };
1722
+
1723
+ // src/agents/agent.ts
1724
+ var import_zod = require("zod");
1725
+ var import_ai2 = require("ai");
1726
+ var Agent = class {
1727
+ name;
1728
+ tools;
1729
+ maxSteps;
1730
+ background;
1731
+ model;
1732
+ constructor({ tools, maxSteps, background, name, model }) {
1733
+ this.name = name;
1734
+ this.tools = tools ?? {};
1735
+ this.maxSteps = maxSteps;
1736
+ this.background = background;
1737
+ this.model = model;
1738
+ }
1739
+ async call({ prompt }) {
1740
+ try {
1741
+ return await (0, import_ai2.generateText)({
1742
+ model: this.model,
1743
+ tools: this.tools,
1744
+ maxSteps: this.maxSteps,
1745
+ system: this.background,
1746
+ prompt,
1747
+ headers: {
1748
+ [AGENT_NAME_HEADER]: this.name
1749
+ }
1750
+ });
1751
+ } catch (error) {
1752
+ if (error instanceof import_ai2.ToolExecutionError) {
1753
+ if (error.cause instanceof Error && error.cause.name === "WorkflowAbort") {
1754
+ throw error.cause;
1755
+ } else if (error.cause instanceof import_ai2.ToolExecutionError && error.cause.cause instanceof Error && error.cause.cause.name === "WorkflowAbort") {
1756
+ throw error.cause.cause;
1757
+ } else {
1758
+ throw error;
1759
+ }
1760
+ } else {
1761
+ throw error;
1762
+ }
1763
+ }
1764
+ }
1765
+ asTool() {
1766
+ const toolDescriptions = Object.values(this.tools).map((tool3) => tool3.description).join("\n");
1767
+ return (0, import_ai2.tool)({
1768
+ parameters: import_zod.z.object({ prompt: import_zod.z.string() }),
1769
+ execute: async ({ prompt }) => {
1770
+ return await this.call({ prompt });
1771
+ },
1772
+ description: `An AI Agent with the following background: ${this.background}Has access to the following tools: ${toolDescriptions}`
1773
+ });
1774
+ }
1775
+ };
1776
+ var MANAGER_AGENT_PROMPT = `You are an AI agent who orchestrates other AI Agents.
1777
+ These other agents have tools available to them.
1778
+ Given a prompt, utilize these agents to address requests.
1779
+ 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.
1780
+ `;
1781
+ var ManagerAgent = class extends Agent {
1782
+ agents;
1783
+ constructor({
1784
+ maxSteps,
1785
+ background = MANAGER_AGENT_PROMPT,
1786
+ agents,
1787
+ model,
1788
+ name = "manager llm"
1789
+ }) {
1790
+ super({
1791
+ background,
1792
+ maxSteps,
1793
+ tools: Object.fromEntries(agents.map((agent) => [agent.name, agent.asTool()])),
1794
+ name,
1795
+ model
1796
+ });
1797
+ this.agents = agents;
1798
+ }
1799
+ };
1800
+
1801
+ // src/agents/task.ts
1802
+ var Task = class {
1803
+ context;
1804
+ taskParameters;
1805
+ constructor({
1806
+ context,
1807
+ taskParameters
1808
+ }) {
1809
+ this.context = context;
1810
+ this.taskParameters = taskParameters;
1811
+ }
1812
+ async run() {
1813
+ const { prompt, ...otherParams } = this.taskParameters;
1814
+ const safePrompt = await this.context.run("Get Prompt", () => prompt);
1815
+ if ("agent" in otherParams) {
1816
+ const agent = otherParams.agent;
1817
+ const result = await agent.call({
1818
+ prompt: safePrompt
1819
+ });
1820
+ return { text: result.text };
1821
+ } else {
1822
+ const { agents, maxSteps, model, background } = otherParams;
1823
+ const managerAgent = new ManagerAgent({
1824
+ model,
1825
+ maxSteps,
1826
+ agents,
1827
+ name: "Manager LLM",
1828
+ background
1829
+ });
1830
+ const result = await managerAgent.call({ prompt: safePrompt });
1831
+ return { text: result.text };
1832
+ }
1833
+ }
1834
+ };
1835
+
1836
+ // src/agents/index.ts
1837
+ var WorkflowAgents = class {
1838
+ context;
1839
+ constructor({ context }) {
1840
+ this.context = context;
1841
+ }
1842
+ agent(params) {
1843
+ const wrappedTools = wrapTools({ context: this.context, tools: params.tools });
1844
+ return new Agent({
1845
+ ...params,
1846
+ tools: wrappedTools
1847
+ });
1848
+ }
1849
+ task(taskParameters) {
1850
+ return new Task({ context: this.context, taskParameters });
1851
+ }
1852
+ openai(...params) {
1853
+ const openai2 = createWorkflowOpenAI(this.context);
1854
+ return openai2(...params);
1855
+ }
1856
+ };
1857
+
1598
1858
  // src/context/context.ts
1599
1859
  var WorkflowContext = class {
1600
1860
  executor;
@@ -1727,7 +1987,8 @@ var WorkflowContext = class {
1727
1987
  debug,
1728
1988
  initialPayload,
1729
1989
  env,
1730
- retries
1990
+ retries,
1991
+ telemetry
1731
1992
  }) {
1732
1993
  this.qstashClient = qstashClient;
1733
1994
  this.workflowRunId = workflowRunId;
@@ -1738,7 +1999,7 @@ var WorkflowContext = class {
1738
1999
  this.requestPayload = initialPayload;
1739
2000
  this.env = env ?? {};
1740
2001
  this.retries = retries ?? DEFAULT_RETRIES;
1741
- this.executor = new AutoExecutor(this, this.steps, debug);
2002
+ this.executor = new AutoExecutor(this, this.steps, telemetry, debug);
1742
2003
  }
1743
2004
  /**
1744
2005
  * Executes a workflow step
@@ -1979,6 +2240,11 @@ var WorkflowContext = class {
1979
2240
  context: this
1980
2241
  });
1981
2242
  }
2243
+ get agents() {
2244
+ return new WorkflowAgents({
2245
+ context: this
2246
+ });
2247
+ }
1982
2248
  };
1983
2249
 
1984
2250
  // src/logger.ts
@@ -2056,7 +2322,7 @@ function decodeBase64(base64) {
2056
2322
  }
2057
2323
 
2058
2324
  // src/serve/authorization.ts
2059
- var import_qstash7 = require("@upstash/qstash");
2325
+ var import_qstash8 = require("@upstash/qstash");
2060
2326
  var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowContext {
2061
2327
  static disabledMessage = "disabled-qstash-worklfow-run";
2062
2328
  /**
@@ -2087,7 +2353,7 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
2087
2353
  */
2088
2354
  static async tryAuthentication(routeFunction, context) {
2089
2355
  const disabledContext = new _DisabledWorkflowContext({
2090
- qstashClient: new import_qstash7.Client({
2356
+ qstashClient: new import_qstash8.Client({
2091
2357
  baseUrl: "disabled-client",
2092
2358
  token: "disabled-client"
2093
2359
  }),
@@ -2183,6 +2449,7 @@ var checkIfLastOneIsDuplicate = async (steps, debug) => {
2183
2449
  if (step.stepId === lastStepId && step.targetStep === lastTargetStepId) {
2184
2450
  const message = `Upstash Workflow: The step '${step.stepName}' with id '${step.stepId}' has run twice during workflow execution. Rest of the workflow will continue running as usual.`;
2185
2451
  await debug?.log("WARN", "RESPONSE_DEFAULT", message);
2452
+ console.log(steps);
2186
2453
  console.warn(message);
2187
2454
  return true;
2188
2455
  }
@@ -2251,7 +2518,7 @@ var parseRequest = async (requestPayload, isFirstInvocation, workflowRunId, requ
2251
2518
  };
2252
2519
  }
2253
2520
  };
2254
- var handleFailure = async (request, requestPayload, qstashClient, initialPayloadParser, routeFunction, failureFunction, debug) => {
2521
+ var handleFailure = async (request, requestPayload, qstashClient, initialPayloadParser, routeFunction, failureFunction, env, retries, debug) => {
2255
2522
  if (request.headers.get(WORKFLOW_FAILURE_HEADER) !== "true") {
2256
2523
  return ok("not-failure-callback");
2257
2524
  }
@@ -2276,7 +2543,11 @@ var handleFailure = async (request, requestPayload, qstashClient, initialPayload
2276
2543
  steps: [],
2277
2544
  url,
2278
2545
  failureUrl: url,
2279
- debug
2546
+ debug,
2547
+ env,
2548
+ retries,
2549
+ telemetry: void 0
2550
+ // not going to make requests in authentication check
2280
2551
  });
2281
2552
  const authCheck = await DisabledWorkflowContext.tryAuthentication(
2282
2553
  routeFunction,
@@ -2301,15 +2572,15 @@ var handleFailure = async (request, requestPayload, qstashClient, initialPayload
2301
2572
  };
2302
2573
 
2303
2574
  // src/serve/options.ts
2304
- var import_qstash8 = require("@upstash/qstash");
2305
2575
  var import_qstash9 = require("@upstash/qstash");
2576
+ var import_qstash10 = require("@upstash/qstash");
2306
2577
  var processOptions = (options) => {
2307
2578
  const environment = options?.env ?? (typeof process === "undefined" ? {} : process.env);
2308
2579
  const receiverEnvironmentVariablesSet = Boolean(
2309
2580
  environment.QSTASH_CURRENT_SIGNING_KEY && environment.QSTASH_NEXT_SIGNING_KEY
2310
2581
  );
2311
2582
  return {
2312
- qstashClient: new import_qstash9.Client({
2583
+ qstashClient: new import_qstash10.Client({
2313
2584
  baseUrl: environment.QSTASH_URL,
2314
2585
  token: environment.QSTASH_TOKEN
2315
2586
  }),
@@ -2343,7 +2614,7 @@ var processOptions = (options) => {
2343
2614
  throw error;
2344
2615
  }
2345
2616
  },
2346
- receiver: receiverEnvironmentVariablesSet ? new import_qstash8.Receiver({
2617
+ receiver: receiverEnvironmentVariablesSet ? new import_qstash9.Receiver({
2347
2618
  currentSigningKey: environment.QSTASH_CURRENT_SIGNING_KEY,
2348
2619
  nextSigningKey: environment.QSTASH_NEXT_SIGNING_KEY
2349
2620
  }) : void 0,
@@ -2351,6 +2622,7 @@ var processOptions = (options) => {
2351
2622
  env: environment,
2352
2623
  retries: DEFAULT_RETRIES,
2353
2624
  useJSONContent: false,
2625
+ disableTelemetry: false,
2354
2626
  ...options
2355
2627
  };
2356
2628
  };
@@ -2385,7 +2657,7 @@ var determineUrls = async (request, url, baseUrl, failureFunction, failureUrl, d
2385
2657
  var AUTH_FAIL_MESSAGE = `Failed to authenticate Workflow request. If this is unexpected, see the caveat https://upstash.com/docs/workflow/basics/caveats#avoid-non-deterministic-code-outside-context-run`;
2386
2658
 
2387
2659
  // src/serve/index.ts
2388
- var serveBase = (routeFunction, options) => {
2660
+ var serveBase = (routeFunction, telemetry, options) => {
2389
2661
  const {
2390
2662
  qstashClient,
2391
2663
  onStepFinish,
@@ -2398,8 +2670,10 @@ var serveBase = (routeFunction, options) => {
2398
2670
  baseUrl,
2399
2671
  env,
2400
2672
  retries,
2401
- useJSONContent
2673
+ useJSONContent,
2674
+ disableTelemetry
2402
2675
  } = processOptions(options);
2676
+ telemetry = disableTelemetry ? void 0 : telemetry;
2403
2677
  const debug = WorkflowLogger.getLogger(verbose);
2404
2678
  const handler = async (request) => {
2405
2679
  await debug?.log("INFO", "ENDPOINT_START");
@@ -2435,7 +2709,10 @@ var serveBase = (routeFunction, options) => {
2435
2709
  qstashClient,
2436
2710
  initialPayloadParser,
2437
2711
  routeFunction,
2438
- failureFunction
2712
+ failureFunction,
2713
+ env,
2714
+ retries,
2715
+ debug
2439
2716
  );
2440
2717
  if (failureCheck.isErr()) {
2441
2718
  throw failureCheck.error;
@@ -2453,7 +2730,8 @@ var serveBase = (routeFunction, options) => {
2453
2730
  failureUrl: workflowFailureUrl,
2454
2731
  debug,
2455
2732
  env,
2456
- retries
2733
+ retries,
2734
+ telemetry
2457
2735
  });
2458
2736
  const authCheck = await DisabledWorkflowContext.tryAuthentication(
2459
2737
  routeFunction,
@@ -2469,22 +2747,23 @@ var serveBase = (routeFunction, options) => {
2469
2747
  "auth-fail"
2470
2748
  );
2471
2749
  }
2472
- const callReturnCheck = await handleThirdPartyCallResult(
2750
+ const callReturnCheck = await handleThirdPartyCallResult({
2473
2751
  request,
2474
- rawInitialPayload,
2475
- qstashClient,
2752
+ requestPayload: rawInitialPayload,
2753
+ client: qstashClient,
2476
2754
  workflowUrl,
2477
- workflowFailureUrl,
2755
+ failureUrl: workflowFailureUrl,
2478
2756
  retries,
2757
+ telemetry,
2479
2758
  debug
2480
- );
2759
+ });
2481
2760
  if (callReturnCheck.isErr()) {
2482
2761
  await debug?.log("ERROR", "SUBMIT_THIRD_PARTY_RESULT", {
2483
2762
  error: callReturnCheck.error.message
2484
2763
  });
2485
2764
  throw callReturnCheck.error;
2486
2765
  } else if (callReturnCheck.value === "continue-workflow") {
2487
- const result = isFirstInvocation ? await triggerFirstInvocation(workflowContext, retries, useJSONContent, debug) : await triggerRouteFunction({
2766
+ const result = isFirstInvocation ? await triggerFirstInvocation({ workflowContext, useJSONContent, telemetry, debug }) : await triggerRouteFunction({
2488
2767
  onStep: async () => routeFunction(workflowContext),
2489
2768
  onCleanup: async () => {
2490
2769
  await triggerWorkflowDelete(workflowContext, debug);
@@ -2519,11 +2798,18 @@ var serveBase = (routeFunction, options) => {
2519
2798
  return { handler: safeHandler };
2520
2799
  };
2521
2800
  var serve = (routeFunction, options) => {
2522
- return serveBase(routeFunction, options);
2801
+ return serveBase(
2802
+ routeFunction,
2803
+ {
2804
+ sdk: SDK_TELEMETRY,
2805
+ framework: "unknown"
2806
+ },
2807
+ options
2808
+ );
2523
2809
  };
2524
2810
 
2525
2811
  // src/client/index.ts
2526
- var import_qstash10 = require("@upstash/qstash");
2812
+ var import_qstash11 = require("@upstash/qstash");
2527
2813
  var Client4 = class {
2528
2814
  client;
2529
2815
  constructor(clientConfig) {
@@ -2532,7 +2818,7 @@ var Client4 = class {
2532
2818
  "QStash token is required for Upstash Workflow!\n\nTo fix this:\n1. Get your token from the Upstash Console (https://console.upstash.com/qstash)\n2. Initialize the workflow client with:\n\n const client = new Client({\n token: '<YOUR_QSTASH_TOKEN>'\n });"
2533
2819
  );
2534
2820
  }
2535
- this.client = new import_qstash10.Client(clientConfig);
2821
+ this.client = new import_qstash11.Client(clientConfig);
2536
2822
  }
2537
2823
  /**
2538
2824
  * Cancel an ongoing workflow
@@ -2693,9 +2979,16 @@ var Client4 = class {
2693
2979
  initialPayload: body,
2694
2980
  steps: [],
2695
2981
  url,
2696
- workflowRunId: finalWorkflowRunId
2982
+ workflowRunId: finalWorkflowRunId,
2983
+ retries,
2984
+ telemetry: void 0
2985
+ // can't know workflow telemetry here
2986
+ });
2987
+ const result = await triggerFirstInvocation({
2988
+ workflowContext: context,
2989
+ telemetry: void 0
2990
+ // can't know workflow telemetry here
2697
2991
  });
2698
- const result = await triggerFirstInvocation(context, retries ?? DEFAULT_RETRIES);
2699
2992
  if (result.isOk()) {
2700
2993
  return { workflowRunId: finalWorkflowRunId };
2701
2994
  } else {