@mastra/inngest 1.2.2 → 1.3.0-alpha.0

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/dist/index.cjs CHANGED
@@ -10,6 +10,7 @@ var workflows = require('@mastra/core/workflows');
10
10
  var _constants = require('@mastra/core/workflows/_constants');
11
11
  var zod = require('zod');
12
12
  var crypto$1 = require('crypto');
13
+ var durable = require('@mastra/core/agent/durable');
13
14
  var di = require('@mastra/core/di');
14
15
  var inngest = require('inngest');
15
16
  var realtime = require('@inngest/realtime');
@@ -230,7 +231,8 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
230
231
  const span = observability.startSpan({
231
232
  ...options,
232
233
  traceId: executionContext.tracingIds?.traceId,
233
- parentSpanId
234
+ parentSpanId,
235
+ tracingPolicy: this.options?.tracingPolicy
234
236
  });
235
237
  return span?.exportSpan();
236
238
  });
@@ -518,6 +520,17 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
518
520
  };
519
521
  }
520
522
  };
523
+ function parseTopic(topic) {
524
+ const workflowMatch = topic.match(/^workflow\.events\.v2\.(.+)$/);
525
+ if (workflowMatch && workflowMatch[1]) {
526
+ return { runId: workflowMatch[1], topicType: "workflow" };
527
+ }
528
+ const agentMatch = topic.match(/^agent\.stream\.(.+)$/);
529
+ if (agentMatch && agentMatch[1]) {
530
+ return { runId: agentMatch[1], topicType: "agent" };
531
+ }
532
+ return null;
533
+ }
521
534
  var InngestPubSub = class extends events.PubSub {
522
535
  inngest;
523
536
  workflowId;
@@ -532,60 +545,84 @@ var InngestPubSub = class extends events.PubSub {
532
545
  /**
533
546
  * Publish an event to Inngest's realtime system.
534
547
  *
535
- * Topic format: "workflow.events.v2.{runId}"
536
- * Maps to Inngest channel: "workflow:{workflowId}:{runId}"
548
+ * Supported topic formats:
549
+ * - "workflow.events.v2.{runId}" - workflow events
550
+ * -> channel: "workflow:{workflowId}:{runId}", topic: "watch"
551
+ * - "agent.stream.{runId}" - agent stream events
552
+ * -> channel: "agent:{runId}", topic: "agent-stream"
553
+ * (Note: agent stream uses runId-only channel so nested workflows can publish to same channel)
537
554
  */
538
555
  async publish(topic, event) {
539
556
  if (!this.publishFn) {
540
557
  return;
541
558
  }
542
- const match = topic.match(/^workflow\.events\.v2\.(.+)$/);
543
- if (!match) {
559
+ const parsed = parseTopic(topic);
560
+ if (!parsed) {
544
561
  return;
545
562
  }
546
- const runId = match[1];
563
+ const { runId, topicType } = parsed;
564
+ const inngestTopic = topicType === "agent" ? "agent-stream" : "watch";
565
+ const channel = topicType === "agent" ? `agent:${runId}` : `workflow:${this.workflowId}:${runId}`;
547
566
  try {
567
+ const dataToSend = topicType === "agent" ? event : event.data;
548
568
  await this.publishFn({
549
- channel: `workflow:${this.workflowId}:${runId}`,
550
- topic: "watch",
551
- data: event.data
569
+ channel,
570
+ topic: inngestTopic,
571
+ data: dataToSend
552
572
  });
553
573
  } catch (err) {
574
+ if (topicType === "agent" && (event.type === "finish" || event.type === "error")) {
575
+ throw err;
576
+ }
554
577
  console.error("InngestPubSub publish error:", err?.message ?? err);
555
578
  }
556
579
  }
557
580
  /**
558
581
  * Subscribe to events from Inngest's realtime system.
559
582
  *
560
- * Topic format: "workflow.events.v2.{runId}"
561
- * Maps to Inngest channel: "workflow:{workflowId}:{runId}"
583
+ * Supported topic formats:
584
+ * - "workflow.events.v2.{runId}" - workflow events
585
+ * -> channel: "workflow:{workflowId}:{runId}", topic: "watch"
586
+ * - "agent.stream.{runId}" - agent stream events
587
+ * -> channel: "agent:{runId}", topic: "agent-stream"
588
+ * (Note: agent stream uses runId-only channel so nested workflows can publish to same channel)
562
589
  */
563
590
  async subscribe(topic, cb) {
564
- const match = topic.match(/^workflow\.events\.v2\.(.+)$/);
565
- if (!match || !match[1]) {
591
+ const parsed = parseTopic(topic);
592
+ if (!parsed) {
566
593
  return;
567
594
  }
568
- const runId = match[1];
595
+ const { runId, topicType } = parsed;
569
596
  if (this.subscriptions.has(topic)) {
570
597
  this.subscriptions.get(topic).callbacks.add(cb);
571
598
  return;
572
599
  }
573
600
  const callbacks = /* @__PURE__ */ new Set([cb]);
574
- const channel = `workflow:${this.workflowId}:${runId}`;
575
- const streamPromise = realtime.subscribe(
601
+ const inngestTopic = topicType === "agent" ? "agent-stream" : "watch";
602
+ const channel = topicType === "agent" ? `agent:${runId}` : `workflow:${this.workflowId}:${runId}`;
603
+ const stream = await realtime.subscribe(
576
604
  {
577
605
  channel,
578
- topics: ["watch"],
606
+ topics: [inngestTopic],
579
607
  app: this.inngest
580
608
  },
581
609
  (message) => {
582
- const event = {
583
- id: crypto.randomUUID(),
584
- type: "watch",
585
- runId,
586
- data: message.data,
587
- createdAt: /* @__PURE__ */ new Date()
588
- };
610
+ let event;
611
+ if (topicType === "agent" && message.data?.type && message.data?.runId) {
612
+ event = {
613
+ id: crypto.randomUUID(),
614
+ createdAt: /* @__PURE__ */ new Date(),
615
+ ...message.data
616
+ };
617
+ } else {
618
+ event = {
619
+ id: crypto.randomUUID(),
620
+ type: inngestTopic,
621
+ runId,
622
+ data: message.data,
623
+ createdAt: /* @__PURE__ */ new Date()
624
+ };
625
+ }
589
626
  for (const callback of callbacks) {
590
627
  callback(event);
591
628
  }
@@ -593,9 +630,11 @@ var InngestPubSub = class extends events.PubSub {
593
630
  );
594
631
  this.subscriptions.set(topic, {
595
632
  unsubscribe: () => {
596
- streamPromise.then((stream) => stream.cancel()).catch((err) => {
633
+ try {
634
+ void stream.cancel();
635
+ } catch (err) {
597
636
  console.error("InngestPubSub unsubscribe error:", err);
598
- });
637
+ }
599
638
  },
600
639
  callbacks
601
640
  });
@@ -1577,13 +1616,26 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
1577
1616
  }
1578
1617
  }
1579
1618
  });
1580
- } catch (error) {
1581
- throw error;
1619
+ } catch (executionError) {
1620
+ result = {
1621
+ status: "failed",
1622
+ steps: {},
1623
+ state: initialState ?? {},
1624
+ error: executionError instanceof Error ? executionError : new Error(String(executionError))
1625
+ };
1582
1626
  }
1583
1627
  let finalizeError;
1584
1628
  let finalizeErrored = false;
1585
1629
  try {
1586
1630
  await step.run(`workflow.${this.id}.finalize`, async () => {
1631
+ if (result.status === "failed" && inputData?.__workflowKind === "durable-agent" && inputData?.runId) {
1632
+ const error = result.error instanceof Error ? result.error : new Error(String(result.error));
1633
+ try {
1634
+ await durable.emitErrorEvent(pubsub, inputData.runId, error);
1635
+ } catch (e) {
1636
+ this.logger.debug?.("Failed to emit error event:", e);
1637
+ }
1638
+ }
1587
1639
  if (result.status !== "paused") {
1588
1640
  await engine.invokeLifecycleCallbacksInternal({
1589
1641
  status: result.status,
@@ -1752,6 +1804,560 @@ var serve = createServe(hono.serve);
1752
1804
 
1753
1805
  // src/types.ts
1754
1806
  var _compatibilityCheck = true;
1807
+ var durableAgenticInputSchema = zod.z.object({
1808
+ runId: zod.z.string(),
1809
+ agentId: zod.z.string(),
1810
+ agentName: zod.z.string().optional(),
1811
+ messageListState: zod.z.any(),
1812
+ toolsMetadata: zod.z.array(zod.z.any()),
1813
+ modelConfig: durable.modelConfigSchema,
1814
+ options: zod.z.any(),
1815
+ state: zod.z.any(),
1816
+ messageId: zod.z.string(),
1817
+ // Observability fields (Inngest-specific)
1818
+ agentSpanData: zod.z.any().optional(),
1819
+ modelSpanData: zod.z.any().optional(),
1820
+ stepIndex: zod.z.number().optional()
1821
+ });
1822
+ var iterationStateSchema = durable.baseIterationStateSchema.extend({
1823
+ // Observability - exported span data for agent run
1824
+ agentSpanData: zod.z.any().optional(),
1825
+ // Observability - exported span data for model generation (ONE span for entire run)
1826
+ modelSpanData: zod.z.any().optional(),
1827
+ // Step index for continuation across iterations (maintains step: 0, 1, 2, ...)
1828
+ stepIndex: zod.z.number()
1829
+ });
1830
+ var INNGEST_ENGINE_PREFIX = "inngest";
1831
+ var InngestDurableStepIds = {
1832
+ AGENTIC_EXECUTION: `${INNGEST_ENGINE_PREFIX}:${durable.DurableStepIds.AGENTIC_EXECUTION}`,
1833
+ AGENTIC_LOOP: `${INNGEST_ENGINE_PREFIX}:${durable.DurableStepIds.AGENTIC_LOOP}`
1834
+ };
1835
+ function createInngestDurableAgenticWorkflow(options) {
1836
+ const { inngest, maxSteps = durable.DurableAgentDefaults.MAX_STEPS } = options;
1837
+ const { createWorkflow } = init(inngest);
1838
+ const llmExecutionStep = durable.createDurableLLMExecutionStep();
1839
+ const toolCallStep = durable.createDurableToolCallStep();
1840
+ const llmMappingStep = durable.createDurableLLMMappingStep();
1841
+ const backgroundTaskCheckStep = durable.createDurableBackgroundTaskCheckStep();
1842
+ const singleIterationWorkflow = createWorkflow({
1843
+ id: InngestDurableStepIds.AGENTIC_EXECUTION,
1844
+ inputSchema: iterationStateSchema,
1845
+ outputSchema: iterationStateSchema,
1846
+ options: {
1847
+ tracingPolicy: {
1848
+ // Mark all workflow spans as internal so they're hidden in traces
1849
+ // This makes the trace structure match regular agents (agent_run -> model_generation -> tool_call)
1850
+ internal: observability.InternalSpans.WORKFLOW
1851
+ },
1852
+ shouldPersistSnapshot: ({ workflowStatus }) => workflowStatus === "suspended",
1853
+ validateInputs: false
1854
+ },
1855
+ steps: []
1856
+ }).map(
1857
+ async ({ inputData }) => {
1858
+ const state = inputData;
1859
+ return {
1860
+ runId: state.runId,
1861
+ agentId: state.agentId,
1862
+ agentName: state.agentName,
1863
+ messageListState: state.messageListState,
1864
+ toolsMetadata: state.toolsMetadata,
1865
+ modelConfig: state.modelConfig,
1866
+ options: state.options,
1867
+ state: state.state,
1868
+ messageId: state.messageId,
1869
+ // Pass agent span data so model spans can use it as parent
1870
+ agentSpanData: state.agentSpanData,
1871
+ // Pass model span data (ONE span for entire agent run)
1872
+ modelSpanData: state.modelSpanData,
1873
+ // Pass step index for continuation (step: 0, 1, 2, ...)
1874
+ stepIndex: state.stepIndex
1875
+ };
1876
+ },
1877
+ { id: "map-to-llm-input" }
1878
+ ).then(llmExecutionStep).map(
1879
+ async ({ inputData }) => {
1880
+ const llmOutput = inputData;
1881
+ return llmOutput.toolCalls ?? [];
1882
+ },
1883
+ { id: "extract-tool-calls" }
1884
+ ).foreach(toolCallStep).map(
1885
+ async ({ inputData, getStepResult, getInitData, mastra }) => {
1886
+ const toolResults = inputData;
1887
+ const llmOutput = getStepResult(llmExecutionStep.id);
1888
+ const initData = getInitData();
1889
+ const observability$1 = mastra?.observability?.getSelectedInstance({});
1890
+ const modelSpanData = llmOutput?.modelSpanData;
1891
+ const stepSpanData = llmOutput?.stepSpanData;
1892
+ const modelSpan = modelSpanData ? observability$1?.rebuildSpan(modelSpanData) : void 0;
1893
+ const stepSpan = stepSpanData ? observability$1?.rebuildSpan(stepSpanData) : void 0;
1894
+ const agentSpan = initData.agentSpanData ? observability$1?.rebuildSpan(initData.agentSpanData) : void 0;
1895
+ const toolParentSpan = stepSpan ?? modelSpan ?? agentSpan;
1896
+ for (const tr of toolResults) {
1897
+ const toolSpan = toolParentSpan?.createChildSpan({
1898
+ type: observability.SpanType.TOOL_CALL,
1899
+ name: `tool: '${tr.toolName}'`,
1900
+ entityType: observability.EntityType.TOOL,
1901
+ entityId: tr.toolName,
1902
+ entityName: tr.toolName,
1903
+ input: tr.args
1904
+ });
1905
+ if (tr.error) {
1906
+ toolSpan?.error({ error: new Error(tr.error.message) });
1907
+ } else {
1908
+ toolSpan?.end({ output: tr.result });
1909
+ }
1910
+ if (!tr.error) {
1911
+ stepSpan?.createEventSpan({
1912
+ type: observability.SpanType.MODEL_CHUNK,
1913
+ name: `chunk: 'tool-result'`,
1914
+ output: {
1915
+ toolCallId: tr.toolCallId,
1916
+ toolName: tr.toolName,
1917
+ result: tr.result
1918
+ }
1919
+ });
1920
+ }
1921
+ }
1922
+ const toolCalls = llmOutput?.toolCalls ?? [];
1923
+ if (stepSpan) {
1924
+ const stepFinishPayload = llmOutput.stepFinishPayload;
1925
+ stepSpan.end({
1926
+ output: {
1927
+ toolCalls: toolCalls.map((tc) => ({
1928
+ toolCallId: tc.toolCallId,
1929
+ toolName: tc.toolName,
1930
+ args: tc.args
1931
+ })),
1932
+ toolResults: toolResults.map((tr) => ({
1933
+ toolCallId: tr.toolCallId,
1934
+ toolName: tr.toolName,
1935
+ result: tr.result,
1936
+ error: tr.error
1937
+ }))
1938
+ },
1939
+ attributes: {
1940
+ usage: stepFinishPayload?.output?.usage,
1941
+ finishReason: stepFinishPayload?.stepResult?.reason,
1942
+ isContinued: stepFinishPayload?.stepResult?.isContinued
1943
+ }
1944
+ });
1945
+ }
1946
+ return {
1947
+ llmOutput,
1948
+ toolResults,
1949
+ runId: initData.runId,
1950
+ agentId: initData.agentId,
1951
+ messageId: initData.messageId,
1952
+ state: llmOutput?.state ?? initData.state
1953
+ };
1954
+ },
1955
+ { id: "collect-tool-results" }
1956
+ ).then(llmMappingStep).then(backgroundTaskCheckStep).map(
1957
+ async ({ inputData, getInitData }) => {
1958
+ const executionOutput = inputData;
1959
+ const initData = getInitData();
1960
+ const baseUpdate = durable.createBaseIterationStateUpdate({
1961
+ currentState: initData,
1962
+ executionOutput
1963
+ });
1964
+ const newIterationState = {
1965
+ ...baseUpdate,
1966
+ // Preserve agent span data for observability
1967
+ agentSpanData: initData.agentSpanData,
1968
+ // Preserve model span data (ONE span for entire agent run)
1969
+ modelSpanData: initData.modelSpanData,
1970
+ // Increment step index for next iteration (step: 0 → 1 → 2 → ...)
1971
+ stepIndex: initData.stepIndex + 1
1972
+ };
1973
+ return newIterationState;
1974
+ },
1975
+ { id: "update-iteration-state" }
1976
+ ).commit();
1977
+ return createWorkflow({
1978
+ id: InngestDurableStepIds.AGENTIC_LOOP,
1979
+ inputSchema: durableAgenticInputSchema,
1980
+ outputSchema: durable.durableAgenticOutputSchema,
1981
+ options: {
1982
+ tracingPolicy: {
1983
+ // Mark all workflow spans as internal so they're hidden in traces
1984
+ // This makes the trace structure match regular agents (agent_run -> model_generation -> tool_call)
1985
+ internal: observability.InternalSpans.WORKFLOW
1986
+ },
1987
+ shouldPersistSnapshot: ({ workflowStatus }) => workflowStatus === "suspended",
1988
+ validateInputs: false
1989
+ },
1990
+ steps: []
1991
+ }).map(
1992
+ async ({ inputData }) => {
1993
+ const input = inputData;
1994
+ const agentSpanData = input.agentSpanData;
1995
+ const modelSpanData = input.modelSpanData;
1996
+ const iterationState = {
1997
+ ...input,
1998
+ iterationCount: 0,
1999
+ accumulatedSteps: [],
2000
+ accumulatedUsage: {
2001
+ inputTokens: 0,
2002
+ outputTokens: 0,
2003
+ totalTokens: 0
2004
+ },
2005
+ lastStepResult: void 0,
2006
+ agentSpanData,
2007
+ modelSpanData,
2008
+ stepIndex: input.stepIndex ?? 0
2009
+ };
2010
+ return iterationState;
2011
+ },
2012
+ { id: "init-iteration-state" }
2013
+ ).dowhile(singleIterationWorkflow, async ({ inputData }) => {
2014
+ const state = inputData;
2015
+ const shouldContinue = state.lastStepResult?.isContinued === true;
2016
+ const effectiveMaxSteps = state.options?.maxSteps ?? maxSteps;
2017
+ const underMaxSteps = state.iterationCount < effectiveMaxSteps;
2018
+ return shouldContinue && underMaxSteps;
2019
+ }).map(
2020
+ async (params) => {
2021
+ const { inputData, mastra } = params;
2022
+ const state = inputData;
2023
+ const pubsub = params[_constants.PUBSUB_SYMBOL];
2024
+ const lastStep = state.accumulatedSteps[state.accumulatedSteps.length - 1];
2025
+ const finalText = lastStep?.text;
2026
+ const finalOutput = {
2027
+ messageListState: state.messageListState,
2028
+ messageId: state.messageId,
2029
+ stepResult: state.lastStepResult || {
2030
+ reason: "stop",
2031
+ warnings: [],
2032
+ isContinued: false
2033
+ },
2034
+ output: {
2035
+ text: finalText,
2036
+ usage: state.accumulatedUsage,
2037
+ steps: state.accumulatedSteps
2038
+ },
2039
+ state: state.state
2040
+ };
2041
+ const observability = mastra?.observability?.getSelectedInstance({});
2042
+ if (state.modelSpanData) {
2043
+ const modelSpan = observability?.rebuildSpan(state.modelSpanData);
2044
+ modelSpan?.end({
2045
+ output: {
2046
+ text: finalText,
2047
+ usage: state.accumulatedUsage
2048
+ },
2049
+ attributes: {
2050
+ finishReason: state.lastStepResult?.reason || "stop"
2051
+ }
2052
+ });
2053
+ }
2054
+ if (state.agentSpanData) {
2055
+ const agentSpan = observability?.rebuildSpan(state.agentSpanData);
2056
+ agentSpan?.end({
2057
+ output: finalOutput.output
2058
+ });
2059
+ }
2060
+ if (pubsub) {
2061
+ await durable.emitFinishEvent(pubsub, state.runId, {
2062
+ output: finalOutput.output,
2063
+ stepResult: finalOutput.stepResult
2064
+ });
2065
+ }
2066
+ return finalOutput;
2067
+ },
2068
+ { id: "map-final-output" }
2069
+ ).commit();
2070
+ }
2071
+
2072
+ // src/durable-agent/create-inngest-agent.ts
2073
+ function createInngestAgent(options) {
2074
+ const {
2075
+ agent,
2076
+ inngest,
2077
+ id: idOverride,
2078
+ name: nameOverride,
2079
+ pubsub: customPubsub,
2080
+ cache,
2081
+ mastra: mastraOption
2082
+ } = options;
2083
+ const agentId = idOverride ?? agent.id;
2084
+ const agentName = nameOverride ?? agent.name;
2085
+ let mastra = mastraOption;
2086
+ const workflow = createInngestDurableAgenticWorkflow({ inngest });
2087
+ let _customCache = cache;
2088
+ let innerPubsub = customPubsub ?? new InngestPubSub(inngest, InngestDurableStepIds.AGENTIC_LOOP);
2089
+ let _cachingPubsub = null;
2090
+ function getPubsub() {
2091
+ if (!_cachingPubsub) {
2092
+ const resolvedCache = _customCache ?? mastra?.serverCache;
2093
+ if (resolvedCache) {
2094
+ _customCache = resolvedCache;
2095
+ _cachingPubsub = new events.CachingPubSub(innerPubsub, resolvedCache);
2096
+ } else {
2097
+ _cachingPubsub = innerPubsub;
2098
+ }
2099
+ }
2100
+ return _cachingPubsub;
2101
+ }
2102
+ function getCache() {
2103
+ getPubsub();
2104
+ return _customCache;
2105
+ }
2106
+ async function triggerWorkflow(runId, workflowInput, tracingOptions) {
2107
+ const eventName = `workflow.${InngestDurableStepIds.AGENTIC_LOOP}`;
2108
+ await inngest.send({
2109
+ name: eventName,
2110
+ data: {
2111
+ inputData: workflowInput,
2112
+ runId,
2113
+ resourceId: workflowInput.state?.resourceId,
2114
+ requestContext: {},
2115
+ tracingOptions
2116
+ }
2117
+ });
2118
+ }
2119
+ async function emitError(runId, error) {
2120
+ await durable.emitErrorEvent(getPubsub(), runId, error);
2121
+ }
2122
+ const inngestAgent = {
2123
+ get id() {
2124
+ return agentId;
2125
+ },
2126
+ get name() {
2127
+ return agentName;
2128
+ },
2129
+ get agent() {
2130
+ return agent;
2131
+ },
2132
+ get inngest() {
2133
+ return inngest;
2134
+ },
2135
+ get cache() {
2136
+ return getCache();
2137
+ },
2138
+ get pubsub() {
2139
+ return getPubsub();
2140
+ },
2141
+ async stream(messages, streamOptions) {
2142
+ const preparation = await durable.prepareForDurableExecution({
2143
+ agent,
2144
+ messages,
2145
+ options: streamOptions,
2146
+ runId: streamOptions?.runId,
2147
+ requestContext: streamOptions?.requestContext
2148
+ });
2149
+ const { runId, messageId, workflowInput, threadId, resourceId } = preparation;
2150
+ workflowInput.agentId = agentId;
2151
+ workflowInput.agentName = agentName;
2152
+ const observability$1 = mastra?.observability?.getSelectedInstance({
2153
+ requestContext: streamOptions?.requestContext
2154
+ });
2155
+ const agentSpan = observability$1?.startSpan({
2156
+ type: observability.SpanType.AGENT_RUN,
2157
+ name: `agent run: '${agentId}'`,
2158
+ entityType: observability.EntityType.AGENT,
2159
+ entityId: agentId,
2160
+ entityName: agentName,
2161
+ input: workflowInput.messageListState,
2162
+ metadata: {
2163
+ runId,
2164
+ threadId,
2165
+ resourceId
2166
+ }
2167
+ });
2168
+ const agentSpanData = agentSpan?.exportSpan();
2169
+ const modelSpan = agentSpan?.createChildSpan({
2170
+ type: observability.SpanType.MODEL_GENERATION,
2171
+ name: `llm: '${workflowInput.modelConfig.modelId}'`,
2172
+ input: { messages: workflowInput.messageListState },
2173
+ attributes: {
2174
+ model: workflowInput.modelConfig.modelId,
2175
+ provider: workflowInput.modelConfig.provider,
2176
+ streaming: true,
2177
+ parameters: {
2178
+ temperature: workflowInput.options?.temperature
2179
+ }
2180
+ }
2181
+ });
2182
+ const modelSpanData = modelSpan?.exportSpan();
2183
+ workflowInput.agentSpanData = agentSpanData;
2184
+ workflowInput.modelSpanData = modelSpanData;
2185
+ workflowInput.stepIndex = 0;
2186
+ const {
2187
+ output,
2188
+ cleanup: streamCleanup,
2189
+ ready
2190
+ } = durable.createDurableAgentStream({
2191
+ pubsub: getPubsub(),
2192
+ runId,
2193
+ messageId,
2194
+ model: {
2195
+ modelId: workflowInput.modelConfig.modelId,
2196
+ provider: workflowInput.modelConfig.provider,
2197
+ version: "v3"
2198
+ },
2199
+ threadId,
2200
+ resourceId,
2201
+ onChunk: streamOptions?.onChunk,
2202
+ onStepFinish: streamOptions?.onStepFinish,
2203
+ onFinish: streamOptions?.onFinish,
2204
+ onError: streamOptions?.onError,
2205
+ onSuspended: streamOptions?.onSuspended
2206
+ });
2207
+ const tracingOptions = agentSpanData ? { traceId: agentSpanData.traceId, parentSpanId: agentSpanData.id } : void 0;
2208
+ ready.then(() => triggerWorkflow(runId, workflowInput, tracingOptions)).catch((error) => {
2209
+ void emitError(runId, error);
2210
+ });
2211
+ const result = {
2212
+ output,
2213
+ runId,
2214
+ threadId,
2215
+ resourceId,
2216
+ cleanup: streamCleanup,
2217
+ // Also expose fullStream directly for server compatibility
2218
+ get fullStream() {
2219
+ return output.fullStream;
2220
+ }
2221
+ };
2222
+ return result;
2223
+ },
2224
+ async resume(runId, resumeData, resumeOptions) {
2225
+ const {
2226
+ output,
2227
+ cleanup: streamCleanup,
2228
+ ready
2229
+ } = durable.createDurableAgentStream({
2230
+ pubsub: getPubsub(),
2231
+ runId,
2232
+ messageId: crypto.randomUUID(),
2233
+ model: {
2234
+ modelId: void 0,
2235
+ provider: void 0,
2236
+ version: "v3"
2237
+ },
2238
+ threadId: resumeOptions?.threadId,
2239
+ resourceId: resumeOptions?.resourceId,
2240
+ onChunk: resumeOptions?.onChunk,
2241
+ onStepFinish: resumeOptions?.onStepFinish,
2242
+ onFinish: resumeOptions?.onFinish,
2243
+ onError: resumeOptions?.onError,
2244
+ onSuspended: resumeOptions?.onSuspended
2245
+ });
2246
+ const eventName = `workflow.${InngestDurableStepIds.AGENTIC_LOOP}`;
2247
+ ready.then(async () => {
2248
+ const workflowsStore = await mastra?.getStorage()?.getStore("workflows");
2249
+ const snapshot = await workflowsStore?.loadWorkflowSnapshot({
2250
+ workflowName: InngestDurableStepIds.AGENTIC_LOOP,
2251
+ runId
2252
+ });
2253
+ const suspendedStepIds = snapshot?.suspendedPaths ? Object.keys(snapshot.suspendedPaths) : [];
2254
+ const steps = suspendedStepIds.length > 0 ? suspendedStepIds : [];
2255
+ await inngest.send({
2256
+ name: eventName,
2257
+ data: {
2258
+ inputData: resumeData,
2259
+ initialState: snapshot?.value ?? {},
2260
+ runId,
2261
+ resourceId: resumeOptions?.resourceId,
2262
+ requestContext: {},
2263
+ stepResults: snapshot?.context,
2264
+ resume: {
2265
+ steps,
2266
+ stepResults: snapshot?.context,
2267
+ resumePayload: resumeData,
2268
+ resumePath: steps[0] ? snapshot?.suspendedPaths?.[steps[0]] : void 0
2269
+ }
2270
+ }
2271
+ });
2272
+ }).catch((error) => {
2273
+ void emitError(runId, error);
2274
+ });
2275
+ return {
2276
+ output,
2277
+ get fullStream() {
2278
+ return output.fullStream;
2279
+ },
2280
+ runId,
2281
+ threadId: resumeOptions?.threadId,
2282
+ resourceId: resumeOptions?.resourceId,
2283
+ cleanup: streamCleanup
2284
+ };
2285
+ },
2286
+ async prepare(messages, prepareOptions) {
2287
+ const preparation = await durable.prepareForDurableExecution({
2288
+ agent,
2289
+ messages,
2290
+ options: prepareOptions,
2291
+ requestContext: prepareOptions?.requestContext
2292
+ });
2293
+ preparation.workflowInput.agentId = agentId;
2294
+ preparation.workflowInput.agentName = agentName;
2295
+ return {
2296
+ runId: preparation.runId,
2297
+ messageId: preparation.messageId,
2298
+ workflowInput: preparation.workflowInput,
2299
+ threadId: preparation.threadId,
2300
+ resourceId: preparation.resourceId
2301
+ };
2302
+ },
2303
+ async observe(runId, observeOptions) {
2304
+ const {
2305
+ output,
2306
+ cleanup: streamCleanup,
2307
+ ready
2308
+ } = durable.createDurableAgentStream({
2309
+ pubsub: getPubsub(),
2310
+ runId,
2311
+ messageId: crypto.randomUUID(),
2312
+ model: {
2313
+ modelId: void 0,
2314
+ provider: void 0,
2315
+ version: "v3"
2316
+ },
2317
+ offset: observeOptions?.offset,
2318
+ onChunk: observeOptions?.onChunk,
2319
+ onStepFinish: observeOptions?.onStepFinish,
2320
+ onFinish: observeOptions?.onFinish,
2321
+ onError: observeOptions?.onError,
2322
+ onSuspended: observeOptions?.onSuspended
2323
+ });
2324
+ await ready;
2325
+ return {
2326
+ output,
2327
+ get fullStream() {
2328
+ return output.fullStream;
2329
+ },
2330
+ runId,
2331
+ cleanup: streamCleanup
2332
+ };
2333
+ },
2334
+ getDurableWorkflows() {
2335
+ return [workflow];
2336
+ },
2337
+ __setMastra(mastraInstance) {
2338
+ mastra = mastraInstance;
2339
+ }
2340
+ };
2341
+ return new Proxy(inngestAgent, {
2342
+ get(target, prop, receiver) {
2343
+ if (prop in target) {
2344
+ return Reflect.get(target, prop, receiver);
2345
+ }
2346
+ const agentValue = agent[prop];
2347
+ if (typeof agentValue === "function") {
2348
+ return agentValue.bind(agent);
2349
+ }
2350
+ return agentValue;
2351
+ },
2352
+ has(target, prop) {
2353
+ return prop in target || prop in agent;
2354
+ }
2355
+ });
2356
+ }
2357
+ function isInngestAgent(obj) {
2358
+ if (!obj) return false;
2359
+ return typeof obj.id === "string" && typeof obj.name === "string" && "agent" in obj && "inngest" in obj && typeof obj.stream === "function" && typeof obj.getDurableWorkflows === "function";
2360
+ }
1755
2361
 
1756
2362
  // src/index.ts
1757
2363
  function isInngestWorkflow(input) {
@@ -2473,9 +3079,12 @@ exports.InngestPubSub = InngestPubSub;
2473
3079
  exports.InngestRun = InngestRun;
2474
3080
  exports.InngestWorkflow = InngestWorkflow;
2475
3081
  exports._compatibilityCheck = _compatibilityCheck;
3082
+ exports.createInngestAgent = createInngestAgent;
3083
+ exports.createInngestDurableAgenticWorkflow = createInngestDurableAgenticWorkflow;
2476
3084
  exports.createServe = createServe;
2477
3085
  exports.createStep = createStep;
2478
3086
  exports.init = init;
3087
+ exports.isInngestAgent = isInngestAgent;
2479
3088
  exports.serve = serve;
2480
3089
  //# sourceMappingURL=index.cjs.map
2481
3090
  //# sourceMappingURL=index.cjs.map