UNPKG

@mastra/core

Version:

Mastra is a framework for building AI-powered applications and agents with a modern TypeScript stack.

1,646 lines (1,636 loc) 175 kB
'use strict'; var chunkACQ5CVFF_cjs = require('./chunk-ACQ5CVFF.cjs'); var chunkZCBG4ZQT_cjs = require('./chunk-ZCBG4ZQT.cjs'); var chunkQJB2YTBM_cjs = require('./chunk-QJB2YTBM.cjs'); var chunkKJBMTK5B_cjs = require('./chunk-KJBMTK5B.cjs'); var chunkDEZHPHA5_cjs = require('./chunk-DEZHPHA5.cjs'); var chunkXB4FLS7A_cjs = require('./chunk-XB4FLS7A.cjs'); var chunk2E7FPUYL_cjs = require('./chunk-2E7FPUYL.cjs'); var chunkD3BJ5NBH_cjs = require('./chunk-D3BJ5NBH.cjs'); var chunkG3JYQ2UI_cjs = require('./chunk-G3JYQ2UI.cjs'); var chunkFCQNDFEW_cjs = require('./chunk-FCQNDFEW.cjs'); var chunk7GW2TQXP_cjs = require('./chunk-7GW2TQXP.cjs'); var chunkRQ4MB5TM_cjs = require('./chunk-RQ4MB5TM.cjs'); var chunk4U7ZLI36_cjs = require('./chunk-4U7ZLI36.cjs'); var chunkCAVARKYS_cjs = require('./chunk-CAVARKYS.cjs'); var croner = require('croner'); var crypto = require('crypto'); var web = require('stream/web'); var v4 = require('zod/v4'); var EventEmitter = require('events'); function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; } var EventEmitter__default = /*#__PURE__*/_interopDefault(EventEmitter); function validateCron(cron, timezone) { const job = new croner.Cron(cron, { timezone }); job.nextRun(); } function computeNextFireAt(cron, options) { const job = new croner.Cron(cron, { timezone: options?.timezone }); const reference = options?.after !== void 0 ? new Date(options.after) : /* @__PURE__ */ new Date(); const next = job.nextRun(reference); if (!next) { throw new Error(`Cron expression "${cron}" has no future occurrence after ${reference.toISOString()}`); } return next.getTime(); } // src/workflows/evented/helpers.ts function isTripwireChunk(chunk) { return chunk !== null && typeof chunk === "object" && "type" in chunk && chunk.type === "tripwire" && "payload" in chunk; } function createTripWireFromChunk(chunk) { const { payload } = chunk; return new chunkACQ5CVFF_cjs.TripWire( payload.reason || "Agent tripwire triggered", { retry: payload.retry, metadata: payload.metadata }, payload.processorId ); } function getTextDeltaFromChunk(chunk, isV2Model) { if (chunk.type !== "text-delta") { return void 0; } return isV2Model ? chunk.payload?.text : chunk.textDelta; } function resolveCurrentState(params) { const { stepResult, stepResults, state } = params; return stepResult?.__state ?? stepResults?.__state ?? state ?? {}; } // src/events/processor.ts var EventProcessor = class { mastra; __registerMastra(mastra) { this.mastra = mastra; } constructor({ mastra }) { this.mastra = mastra; } }; var StepExecutor = class extends chunkFCQNDFEW_cjs.MastraBase { mastra; constructor({ mastra }) { super({ name: "StepExecutor", component: chunk7GW2TQXP_cjs.RegisteredLogger.WORKFLOW }); this.mastra = mastra; } __registerMastra(mastra) { this.mastra = mastra; const logger = mastra?.getLogger(); if (logger) { this.__setLogger(logger); } } /** * Creates an output writer function that publishes chunks to the workflow event stream. * @param runId - The workflow run ID * @returns An async function that writes chunks to the pubsub */ createOutputWriter(runId) { return async (chunk) => { try { if (this.mastra?.pubsub) { await this.mastra.pubsub.publish(`workflow.events.v2.${runId}`, { type: "watch", runId, data: chunk }); } } catch (err) { this.logger.debug("Failed to publish workflow watch event", { runId, error: err }); } }; } async execute(params) { const { step, stepResults, runId, requestContext, retryCount = 0, perStep } = params; const abortController = params.abortController ?? new AbortController(); let suspended; let bailed; const startedAt = Date.now(); const { inputData, validationError } = await chunkACQ5CVFF_cjs.validateStepInput({ prevOutput: typeof params.foreachIdx === "number" ? params.input?.[params.foreachIdx] : params.input, step, validateInputs: params.validateInputs ?? true }); let stepInfo = { ...stepResults[step.id], startedAt, payload: (typeof params.foreachIdx === "number" ? params.input : inputData) ?? {} }; if (params.resumeData) { stepInfo.resumePayload = params.resumeData; stepInfo.resumedAt = Date.now(); if (stepInfo.suspendPayload && "__workflow_meta" in stepInfo.suspendPayload) { const { __workflow_meta, ...userSuspendPayload } = stepInfo.suspendPayload; stepInfo.suspendPayload = userSuspendPayload; } } let suspendDataToUse = params.stepResults[step.id]?.status === "suspended" ? params.stepResults[step.id]?.suspendPayload : void 0; if (suspendDataToUse && "__workflow_meta" in suspendDataToUse) { const { __workflow_meta, ...userSuspendData } = suspendDataToUse; suspendDataToUse = userSuspendData; } let stateUpdate; try { if (validationError) { throw validationError; } const callId = crypto.randomUUID(); const outputWriter = this.createOutputWriter(runId); const stepOutput = await chunkD3BJ5NBH_cjs.executeWithContext({ span: params.tracingContext?.currentSpan, fn: () => step.execute( chunkACQ5CVFF_cjs.createDeprecationProxy( { workflowId: params.workflowId, runId, mastra: this.mastra, requestContext, inputData, state: params.state, setState: async (newState) => { stateUpdate = { ...stateUpdate ?? params.state, ...newState }; }, retryCount, resumeData: params.resumeData, suspendData: suspendDataToUse, getInitData: () => stepResults?.input, getStepResult: chunkACQ5CVFF_cjs.getStepResult.bind(this, stepResults), suspend: async (suspendPayload, suspendOptions) => { const { suspendData, validationError: validationError2 } = await chunkACQ5CVFF_cjs.validateStepSuspendData({ suspendData: suspendPayload, step, validateInputs: params.validateInputs ?? true }); if (validationError2) { throw validationError2; } const resumeLabels = {}; if (suspendOptions?.resumeLabel) { const labels = Array.isArray(suspendOptions.resumeLabel) ? suspendOptions.resumeLabel : [suspendOptions.resumeLabel]; for (const label of labels) { resumeLabels[label] = { stepId: step.id, foreachIndex: params.foreachIdx }; } } suspended = { payload: { ...suspendData, __workflow_meta: { runId, path: [step.id], foreachIndex: params.foreachIdx, resumeLabels: Object.keys(resumeLabels).length > 0 ? resumeLabels : void 0 } } }; }, bail: (result) => { bailed = { payload: result }; }, writer: new chunkKJBMTK5B_cjs.ToolStream( { prefix: "workflow-step", callId, name: step.id, runId }, outputWriter ), abort: () => { abortController?.abort(); }, [chunkZCBG4ZQT_cjs.PUBSUB_SYMBOL]: this.mastra.pubsub, [chunkZCBG4ZQT_cjs.STREAM_FORMAT_SYMBOL]: params.format, engine: {}, abortSignal: abortController?.signal, ...chunk2E7FPUYL_cjs.createObservabilityContext(params.tracingContext) }, { paramName: "runCount", deprecationMessage: chunkACQ5CVFF_cjs.runCountDeprecationMessage, logger: this.logger } ) ) }); const isNestedWorkflowStep = step.component === "WORKFLOW"; const nestedWflowStepPaused = isNestedWorkflowStep && perStep; const endedAt = Date.now(); const finalState = stateUpdate ?? params.state; let finalResult; if (suspended) { finalResult = { ...stepInfo, status: "suspended", suspendedAt: endedAt, ...stepOutput ? { suspendOutput: stepOutput } : {}, __state: finalState }; if (suspended.payload) { finalResult.suspendPayload = suspended.payload; } } else if (bailed) { finalResult = { ...stepInfo, // @ts-expect-error - bailed status not in type status: "bailed", endedAt, output: bailed.payload, __state: finalState }; } else if (nestedWflowStepPaused) { finalResult = { ...stepInfo, status: "paused", __state: finalState }; } else { finalResult = { ...stepInfo, status: "success", endedAt, output: stepOutput, __state: finalState }; } return finalResult; } catch (error) { const endedAt = Date.now(); const errorInstance = chunk4U7ZLI36_cjs.getErrorFromUnknown(error, { serializeStack: false, fallbackMessage: "Unknown step execution error" }); const stepId = params.step.id; const mastraError = new chunk4U7ZLI36_cjs.MastraError( { id: "WORKFLOW_STEP_INVOKE_FAILED", domain: "MASTRA_WORKFLOW" /* MASTRA_WORKFLOW */, category: "USER" /* USER */, details: { workflowId: params.workflowId, runId: params.runId, stepId } }, errorInstance ); this.logger?.trackException(mastraError); this.logger?.error(`Error executing step ${stepId}: ` + errorInstance?.stack); return { ...stepInfo, status: "failed", endedAt, error: errorInstance, // Preserve TripWire data as plain object for proper serialization // Important: Check `error` not `errorInstance` because getErrorFromUnknown // converts the error and loses the prototype chain tripwire: error instanceof chunkACQ5CVFF_cjs.TripWire ? { reason: error.message, retry: error.options?.retry, metadata: error.options?.metadata, processorId: error.processorId } : void 0 }; } } async evaluateConditions(params) { const { step, stepResults, runId, requestContext, retryCount = 0 } = params; const abortController = params.abortController ?? new AbortController(); const results = await Promise.all( step.conditions.map((condition) => { try { return this.evaluateCondition({ workflowId: params.workflowId, condition, runId, requestContext, inputData: params.input, state: params.state, retryCount, resumeData: params.resumeData, abortController, stepResults, iterationCount: 0 }); } catch (e) { this.mastra?.getLogger()?.error("error evaluating condition", e); return false; } }) ); const idxs = results.reduce((acc, result, idx) => { if (result) { acc.push(idx); } return acc; }, []); return idxs; } async evaluateCondition({ workflowId, condition, runId, inputData, resumeData, stepResults, state, requestContext, abortController, retryCount = 0, iterationCount }) { const callId = crypto.randomUUID(); const outputWriter = this.createOutputWriter(runId); return condition( chunkACQ5CVFF_cjs.createDeprecationProxy( { workflowId, runId, mastra: this.mastra, requestContext, inputData, state, retryCount, resumeData, getInitData: () => stepResults?.input, getStepResult: chunkACQ5CVFF_cjs.getStepResult.bind(this, stepResults), bail: (_result) => { throw new Error("Not implemented"); }, writer: new chunkKJBMTK5B_cjs.ToolStream( { prefix: "workflow-step", callId, name: "condition", runId }, outputWriter ), abort: () => { abortController?.abort(); }, [chunkZCBG4ZQT_cjs.PUBSUB_SYMBOL]: this.mastra.pubsub, [chunkZCBG4ZQT_cjs.STREAM_FORMAT_SYMBOL]: void 0, // TODO engine: {}, abortSignal: abortController?.signal, // TODO ...chunk2E7FPUYL_cjs.createObservabilityContext(), iterationCount }, { paramName: "runCount", deprecationMessage: chunkACQ5CVFF_cjs.runCountDeprecationMessage, logger: this.logger } ) ); } async resolveSleep(params) { const { step, stepResults, runId, requestContext, retryCount = 0 } = params; const currentState = params.state ?? stepResults?.__state ?? {}; const abortController = params.abortController ?? new AbortController(); if (step.duration) { return step.duration; } if (!step.fn) { return 0; } try { const callId = crypto.randomUUID(); const outputWriter = this.createOutputWriter(runId); return await step.fn( chunkACQ5CVFF_cjs.createDeprecationProxy( { workflowId: params.workflowId, runId, mastra: this.mastra, requestContext, inputData: params.input, state: currentState, setState: async (newState) => { Object.assign(currentState, newState); }, retryCount, resumeData: params.resumeData, getInitData: () => stepResults?.input, getStepResult: chunkACQ5CVFF_cjs.getStepResult.bind(this, stepResults), suspend: async (_suspendPayload) => { throw new Error("Not implemented"); }, bail: (_result) => { throw new Error("Not implemented"); }, abort: () => { abortController?.abort(); }, writer: new chunkKJBMTK5B_cjs.ToolStream( { prefix: "workflow-step", callId, name: step.id, runId }, outputWriter ), [chunkZCBG4ZQT_cjs.PUBSUB_SYMBOL]: this.mastra.pubsub, [chunkZCBG4ZQT_cjs.STREAM_FORMAT_SYMBOL]: void 0, // TODO engine: {}, abortSignal: abortController?.signal, // TODO ...chunk2E7FPUYL_cjs.createObservabilityContext() }, { paramName: "runCount", deprecationMessage: chunkACQ5CVFF_cjs.runCountDeprecationMessage, logger: this.logger } ) ); } catch (e) { this.mastra?.getLogger()?.error("error evaluating condition", e); return 0; } } async resolveSleepUntil(params) { const { step, stepResults, runId, requestContext, retryCount = 0 } = params; const currentState = params.state ?? stepResults?.__state ?? {}; const abortController = params.abortController ?? new AbortController(); if (step.date) { return step.date.getTime() - Date.now(); } if (!step.fn) { return 0; } try { const callId = crypto.randomUUID(); const outputWriter = this.createOutputWriter(runId); const result = await step.fn( chunkACQ5CVFF_cjs.createDeprecationProxy( { workflowId: params.workflowId, runId, mastra: this.mastra, requestContext, inputData: params.input, state: currentState, setState: async (newState) => { Object.assign(currentState, newState); }, retryCount, resumeData: params.resumeData, getInitData: () => stepResults?.input, getStepResult: chunkACQ5CVFF_cjs.getStepResult.bind(this, stepResults), suspend: async (_suspendPayload) => { throw new Error("Not implemented"); }, bail: (_result) => { throw new Error("Not implemented"); }, abort: () => { abortController?.abort(); }, writer: new chunkKJBMTK5B_cjs.ToolStream( { prefix: "workflow-step", callId, name: step.id, runId }, outputWriter ), [chunkZCBG4ZQT_cjs.PUBSUB_SYMBOL]: this.mastra.pubsub, [chunkZCBG4ZQT_cjs.STREAM_FORMAT_SYMBOL]: void 0, // TODO engine: {}, abortSignal: abortController?.signal, // TODO ...chunk2E7FPUYL_cjs.createObservabilityContext() }, { paramName: "runCount", deprecationMessage: chunkACQ5CVFF_cjs.runCountDeprecationMessage, logger: this.logger } ) ); return result.getTime() - Date.now(); } catch (e) { this.mastra?.getLogger()?.error("error evaluating condition", e); return 0; } } }; // src/workflows/evented/workflow-event-processor/loop.ts async function processWorkflowLoop({ workflowId, prevResult, runId, executionPath, stepResults, activeStepsPath, resumeSteps, resumeData, parentWorkflow, requestContext, retryCount = 0, perStep, state, outputOptions }, { pubsub, stepExecutor, step, stepResult }) { const currentState = resolveCurrentState({ stepResult, stepResults, state }); const reqContext = new chunkCAVARKYS_cjs.RequestContext(Object.entries(requestContext ?? {})); const prevIterationCount = stepResults[step.step?.id]?.metadata?.iterationCount ?? 0; const iterationCount = prevIterationCount + 1; const loopCondition = await stepExecutor.evaluateCondition({ workflowId, condition: step.condition, runId, stepResults, state: currentState, requestContext: reqContext, inputData: prevResult?.status === "success" ? prevResult.output : void 0, resumeData, abortController: new AbortController(), retryCount, iterationCount }); const loopAgainData = { parentWorkflow, workflowId, runId, executionPath, resumeSteps: [], stepResults, prevResult: stepResult, resumeData: void 0, activeStepsPath, requestContext, retryCount, perStep, state: currentState, outputOptions }; const loopEndData = { parentWorkflow, workflowId, runId, executionPath, resumeSteps, stepResults, prevResult: stepResult, resumeData, activeStepsPath, requestContext, perStep, state: currentState, outputOptions }; if (step.loopType === "dountil") { if (loopCondition) { await pubsub.publish("workflows", { type: "workflow.step.end", runId, data: loopEndData }); } else { await pubsub.publish("workflows", { type: "workflow.step.run", runId, data: loopAgainData }); } } else { if (loopCondition) { await pubsub.publish("workflows", { type: "workflow.step.run", runId, data: loopAgainData }); } else { await pubsub.publish("workflows", { type: "workflow.step.end", runId, data: loopEndData }); } } } async function processWorkflowForEach({ workflowId, prevResult, runId, executionPath, stepResults, activeStepsPath, resumeSteps, timeTravel, restart, resumeData, parentWorkflow, requestContext, perStep, state, outputOptions, forEachIndex }, { pubsub, mastra, step }) { const currentState = resolveCurrentState({ stepResults, state }); const currentResult = stepResults[step.step.id]; const idx = currentResult?.output?.length ?? 0; const targetLen = prevResult?.output?.length ?? 0; if (forEachIndex !== void 0 && resumeSteps?.length > 0 && idx > 0) { const outputArray = currentResult?.output; const outputLength = Array.isArray(outputArray) ? outputArray.length : 0; if (!Array.isArray(outputArray) || forEachIndex < 0 || forEachIndex >= outputLength) { const error = new Error( `Invalid forEachIndex ${forEachIndex} for forEach resume: expected index in range [0, ${outputLength - 1}] but output array has length ${outputLength}` ); await pubsub.publish("workflows", { type: "workflow.fail", runId, data: { parentWorkflow, workflowId, runId, executionPath, resumeSteps, stepResults, prevResult: { status: "failed", error }, activeStepsPath, requestContext, state: currentState, outputOptions } }); return; } const iterationResult = currentResult?.output?.[forEachIndex]; if (iterationResult?.status === "suspended" || iterationResult === null) { const isNestedWorkflow2 = step.step.component === "WORKFLOW"; const targetArray2 = prevResult?.output; const iterationPrevResult2 = isNestedWorkflow2 && prevResult.status === "success" && Array.isArray(targetArray2) ? { status: "success", output: targetArray2[forEachIndex] } : prevResult; await pubsub.publish("workflows", { type: "workflow.step.run", runId, data: { parentWorkflow, workflowId, runId, executionPath: [executionPath[0], forEachIndex], resumeSteps, timeTravel, restart, stepResults, prevResult: iterationPrevResult2, resumeData, activeStepsPath, requestContext, perStep, state: currentState, outputOptions } }); return; } const pendingIterations = currentResult.output.filter((r) => r === null || r?.status === "suspended"); if (pendingIterations.length > 0) { const collectedResumeLabels = {}; for (let i = 0; i < currentResult.output.length; i++) { const iterResult = currentResult.output[i]; if (iterResult?.status === "suspended" && iterResult.suspendPayload?.__workflow_meta?.resumeLabels) { Object.assign(collectedResumeLabels, iterResult.suspendPayload.__workflow_meta.resumeLabels); } } const suspendMeta = { foreachIndex: forEachIndex }; if (Object.keys(collectedResumeLabels).length > 0) { suspendMeta.resumeLabels = collectedResumeLabels; } await pubsub.publish("workflows", { type: "workflow.step.end", runId, data: { parentWorkflow, workflowId, runId, executionPath, resumeSteps, stepResults: { ...stepResults, [step.step.id]: { ...currentResult, status: "suspended", suspendedAt: Date.now(), suspendPayload: { __workflow_meta: suspendMeta } } }, prevResult: { status: "suspended", output: currentResult.output, suspendPayload: { __workflow_meta: suspendMeta }, payload: currentResult.payload, startedAt: currentResult.startedAt, suspendedAt: Date.now() }, activeStepsPath, requestContext, state: currentState, outputOptions } }); return; } return; } if (resumeData !== void 0 && forEachIndex === void 0 && currentResult?.output?.length > 0) { const suspendedIndices = []; for (let i = 0; i < currentResult.output.length; i++) { const iterResult = currentResult.output[i]; if (iterResult && typeof iterResult === "object" && iterResult.status === "suspended") { suspendedIndices.push(i); } } if (suspendedIndices.length > 0) { const concurrency = step.opts.concurrency ?? 1; const indicesToResume = suspendedIndices.slice(0, concurrency); const workflowsStore2 = await mastra.getStorage()?.getStore("workflows"); const updatedOutput = [...currentResult.output]; for (const suspIdx of indicesToResume) { updatedOutput[suspIdx] = chunkQJB2YTBM_cjs.createPendingMarker(); } await workflowsStore2?.updateWorkflowResults({ workflowName: workflowId, runId, stepId: step.step.id, result: { ...currentResult, output: updatedOutput }, requestContext }); const isNestedWorkflow2 = step.step.component === "WORKFLOW"; for (const suspIdx of indicesToResume) { const targetArray2 = prevResult?.output; const iterationPrevResult2 = isNestedWorkflow2 && prevResult.status === "success" && Array.isArray(targetArray2) ? { status: "success", output: targetArray2[suspIdx] } : prevResult; try { await pubsub.publish("workflows", { type: "workflow.step.run", runId, data: { parentWorkflow, workflowId, runId, executionPath: [executionPath[0], suspIdx], resumeSteps, timeTravel, restart, stepResults, prevResult: iterationPrevResult2, resumeData, activeStepsPath, requestContext, perStep, state: currentState, outputOptions } }); } catch { } } return; } } const workflowsStore = await mastra.getStorage()?.getStore("workflows"); if (idx >= targetLen && currentResult?.output?.filter((r) => r !== null)?.length >= targetLen || prevResult?.output?.length === 0) { let result = currentResult; if (prevResult?.output?.length === 0) { result = { status: "success", output: [], startedAt: Date.now(), endedAt: Date.now(), payload: prevResult?.output }; await workflowsStore?.updateWorkflowResults({ workflowName: workflowId, runId, stepId: step.step.id, result, requestContext }); stepResults[step.step.id] = result; } await pubsub.publish("workflows", { type: "workflow.step.run", runId, data: { parentWorkflow, workflowId, runId, executionPath: executionPath.slice(0, -1).concat([executionPath[executionPath.length - 1] + 1]), resumeSteps, stepResults, timeTravel, restart, prevResult: result, resumeData: void 0, // No resumeData when advancing past foreach activeStepsPath, requestContext, perStep, state: currentState, outputOptions } }); return; } else if (idx >= targetLen) { return; } if (executionPath.length === 1 && idx === 0) { const concurrency = Math.min(step.opts.concurrency ?? 1, targetLen); const dummyResult = Array.from({ length: concurrency }, () => null); await workflowsStore?.updateWorkflowResults({ workflowName: workflowId, runId, stepId: step.step.id, result: { status: "success", output: dummyResult, startedAt: Date.now(), payload: prevResult?.output }, requestContext }); const isNestedWorkflow2 = step.step.component === "WORKFLOW"; for (let i = 0; i < concurrency; i++) { const targetArray2 = prevResult?.output; const iterationPrevResult2 = isNestedWorkflow2 && prevResult.status === "success" && Array.isArray(targetArray2) ? { status: "success", output: targetArray2[i] } : prevResult; await pubsub.publish("workflows", { type: "workflow.step.run", runId, data: { parentWorkflow, workflowId, runId, executionPath: [executionPath[0], i], resumeSteps, stepResults, timeTravel, restart, prevResult: iterationPrevResult2, resumeData, activeStepsPath, requestContext, perStep, state: currentState, outputOptions } }); } return; } currentResult.output.push(null); await workflowsStore?.updateWorkflowResults({ workflowName: workflowId, runId, stepId: step.step.id, result: { status: "success", output: currentResult.output, startedAt: Date.now(), payload: prevResult?.output }, requestContext }); const isNestedWorkflow = step.step.component === "WORKFLOW"; const targetArray = prevResult?.output; const iterationPrevResult = isNestedWorkflow && prevResult.status === "success" && Array.isArray(targetArray) ? { status: "success", output: targetArray[idx] } : prevResult; await pubsub.publish("workflows", { type: "workflow.step.run", runId, data: { parentWorkflow, workflowId, runId, executionPath: [executionPath[0], idx], resumeSteps, timeTravel, restart, stepResults, prevResult: iterationPrevResult, resumeData, activeStepsPath, requestContext, perStep, state: currentState, outputOptions } }); } // src/workflows/evented/workflow-event-processor/parallel.ts async function processWorkflowParallel({ workflowId, runId, executionPath, stepResults, activeStepsPath, resumeSteps, timeTravel, restart, prevResult, resumeData, parentWorkflow, requestContext, perStep, state, outputOptions }, { pubsub, step }) { const pathsToRun = {}; const currentState = resolveCurrentState({ stepResults, state }); for (let i = 0; i < step.steps.length; i++) { const nestedStep = step.steps[i]; if (nestedStep?.type === "step") { if (restart) { pathsToRun[nestedStep.step.id] = !!restart.activeStepsPath[nestedStep.step.id]; } else { pathsToRun[nestedStep.step.id] = true; } if (perStep) { break; } } } await Promise.all( step.steps?.filter((step2) => pathsToRun[step2.step.id]).map(async (_step, idx) => { return pubsub.publish("workflows", { type: "workflow.step.run", runId, data: { workflowId, runId, executionPath: restart ? executionPath.slice(0, -1).concat([idx]) : executionPath.concat([idx]), resumeSteps, stepResults, prevResult, resumeData, timeTravel, restart: restart ? { ...restart, isParallelOrConditionalRestarted: true } : void 0, parentWorkflow, activeStepsPath, requestContext, perStep, state: currentState, outputOptions } }); }) ); } async function processWorkflowConditional({ workflowId, runId, executionPath, stepResults, activeStepsPath, resumeSteps, timeTravel, restart, prevResult, resumeData, parentWorkflow, requestContext, perStep, state, outputOptions }, { pubsub, stepExecutor, step }) { const currentState = resolveCurrentState({ stepResults, state }); const reqContext = new chunkCAVARKYS_cjs.RequestContext(Object.entries(requestContext ?? {})); const idxs = await stepExecutor.evaluateConditions({ workflowId, step, runId, stepResults, state: currentState, requestContext: reqContext, input: prevResult?.status === "success" ? prevResult.output : void 0, resumeData }); const truthyIdxs = {}; for (let i = 0; i < idxs.length; i++) { truthyIdxs[idxs[i]] = true; } let onlyStepToRun; if (perStep) { const stepsToRun = step.steps.filter((_, idx) => truthyIdxs[idx]); onlyStepToRun = stepsToRun[0]; } if (onlyStepToRun) { const stepIndex = step.steps.findIndex((step2) => step2.step.id === onlyStepToRun.step.id); activeStepsPath[onlyStepToRun.step.id] = executionPath.concat([stepIndex]); await pubsub.publish("workflows", { type: "workflow.step.run", runId, data: { workflowId, runId, executionPath: executionPath.concat([stepIndex]), resumeSteps, stepResults, timeTravel, restart, prevResult, resumeData, parentWorkflow, activeStepsPath, requestContext, perStep, state: currentState, outputOptions } }); } else { await Promise.all( step.steps.map(async (step2, idx) => { if (truthyIdxs[idx]) { if (step2?.type === "step") { activeStepsPath[step2.step.id] = executionPath.concat([idx]); } return pubsub.publish("workflows", { type: "workflow.step.run", runId, data: { workflowId, runId, executionPath: executionPath.concat([idx]), resumeSteps, stepResults, timeTravel, restart: restart ? { ...restart, isParallelOrConditionalRestarted: true } : void 0, prevResult, resumeData, parentWorkflow, activeStepsPath, requestContext, perStep, state: currentState, outputOptions } }); } else { return pubsub.publish("workflows", { type: "workflow.step.end", runId, data: { workflowId, runId, executionPath: executionPath.concat([idx]), resumeSteps, stepResults, prevResult: { status: "skipped" }, resumeData, parentWorkflow, activeStepsPath, requestContext, perStep, state: currentState, outputOptions } }); } }) ); } } // src/workflows/evented/workflow-event-processor/sleep.ts async function processWorkflowWaitForEvent(workflowData, { pubsub, eventName, currentState }) { const executionPath = currentState?.waitingPaths[eventName]; if (!executionPath) { return; } const currentStep = getStep(workflowData.workflow, executionPath); const prevResult = { status: "success", output: currentState?.context[currentStep?.id ?? "input"]?.payload }; await pubsub.publish("workflows", { type: "workflow.step.run", runId: workflowData.runId, data: { workflowId: workflowData.workflowId, runId: workflowData.runId, executionPath, resumeSteps: [], resumeData: workflowData.resumeData, parentWorkflow: workflowData.parentWorkflow, stepResults: currentState?.context, prevResult, activeStepsPath: {}, requestContext: currentState?.requestContext, perStep: workflowData.perStep } }); } async function processWorkflowSleep({ workflowId, runId, executionPath, stepResults, activeStepsPath, resumeSteps, timeTravel, restart, prevResult, resumeData, parentWorkflow, requestContext, perStep }, { pubsub, stepExecutor, step }) { const startedAt = Date.now(); await pubsub.publish(`workflow.events.v2.${runId}`, { type: "watch", runId, data: { type: "workflow-step-waiting", payload: { id: step.id, status: "waiting", payload: prevResult.status === "success" ? prevResult.output : void 0, startedAt } } }); const reqContext = new chunkCAVARKYS_cjs.RequestContext(Object.entries(requestContext ?? {})); const duration = await stepExecutor.resolveSleep({ workflowId, step, runId, stepResults, requestContext: reqContext, input: prevResult?.status === "success" ? prevResult.output : void 0, resumeData }); setTimeout( async () => { await pubsub.publish(`workflow.events.v2.${runId}`, { type: "watch", runId, data: { type: "workflow-step-result", payload: { id: step.id, status: "success", payload: prevResult.status === "success" ? prevResult.output : void 0, output: prevResult.status === "success" ? prevResult.output : void 0, startedAt, endedAt: Date.now() } } }); await pubsub.publish(`workflow.events.v2.${runId}`, { type: "watch", runId, data: { type: "workflow-step-finish", payload: { id: step.id, metadata: {} } } }); await pubsub.publish("workflows", { type: "workflow.step.run", runId, data: { workflowId, runId, executionPath: executionPath.slice(0, -1).concat([executionPath[executionPath.length - 1] + 1]), resumeSteps, timeTravel, restart, stepResults, prevResult, resumeData, parentWorkflow, activeStepsPath, requestContext, perStep } }); }, duration < 0 ? 0 : duration ); } async function processWorkflowSleepUntil({ workflowId, runId, executionPath, stepResults, activeStepsPath, resumeSteps, timeTravel, restart, prevResult, resumeData, parentWorkflow, requestContext, perStep }, { pubsub, stepExecutor, step }) { const startedAt = Date.now(); const reqContext = new chunkCAVARKYS_cjs.RequestContext(Object.entries(requestContext ?? {})); const duration = await stepExecutor.resolveSleepUntil({ workflowId, step, runId, stepResults, requestContext: reqContext, input: prevResult?.status === "success" ? prevResult.output : void 0, resumeData }); await pubsub.publish(`workflow.events.v2.${runId}`, { type: "watch", runId, data: { type: "workflow-step-waiting", payload: { id: step.id, status: "waiting", payload: prevResult.status === "success" ? prevResult.output : void 0, startedAt } } }); setTimeout( async () => { await pubsub.publish(`workflow.events.v2.${runId}`, { type: "watch", runId, data: { type: "workflow-step-result", payload: { id: step.id, status: "success", payload: prevResult.status === "success" ? prevResult.output : void 0, output: prevResult.status === "success" ? prevResult.output : void 0, startedAt, endedAt: Date.now() } } }); await pubsub.publish(`workflow.events.v2.${runId}`, { type: "watch", runId, data: { type: "workflow-step-finish", payload: { id: step.id, metadata: {} } } }); await pubsub.publish("workflows", { type: "workflow.step.run", runId, data: { workflowId, runId, executionPath: executionPath.slice(0, -1).concat([executionPath[executionPath.length - 1] + 1]), resumeSteps, timeTravel, restart, stepResults, prevResult, resumeData, parentWorkflow, activeStepsPath, requestContext, perStep } }); }, duration < 0 ? 0 : duration ); } // src/workflows/evented/workflow-event-processor/index.ts var WorkflowEventProcessor = class extends EventProcessor { stepExecutor; stepExecutionStrategy; // Map of runId -> AbortController for active workflow runs abortControllers = /* @__PURE__ */ new Map(); // Map of child runId -> parent runId for tracking nested workflows parentChildRelationships = /* @__PURE__ */ new Map(); runFormats = /* @__PURE__ */ new Map(); constructor({ mastra, stepExecutionStrategy }) { super({ mastra }); this.stepExecutor = new StepExecutor({ mastra }); this.stepExecutionStrategy = stepExecutionStrategy; } /** * Get or create an AbortController for a workflow run */ getOrCreateAbortController(runId) { let controller = this.abortControllers.get(runId); if (!controller) { controller = new AbortController(); this.abortControllers.set(runId, controller); } return controller; } /** * Cancel a workflow run and all its nested child workflows */ cancelRunAndChildren(runId) { const controller = this.abortControllers.get(runId); if (controller) { controller.abort(); } for (const [childRunId, parentRunId] of this.parentChildRelationships.entries()) { if (parentRunId === runId) { this.cancelRunAndChildren(childRunId); } } } /** * Clean up abort controller and relationships when a workflow completes. * Also cleans up any orphaned child entries that reference this run as parent. */ cleanupRun(runId) { this.abortControllers.delete(runId); this.parentChildRelationships.delete(runId); this.runFormats.delete(runId); for (const [childRunId, parentRunId] of this.parentChildRelationships.entries()) { if (parentRunId === runId) { this.parentChildRelationships.delete(childRunId); } } } __registerMastra(mastra) { super.__registerMastra(mastra); this.stepExecutor.__registerMastra(mastra); } /** * Resolves a workflow by id without throwing. Searches first by the * workflow's `.id` (the value that ends up on event payloads) and then * falls back to the registration key in `Mastra.workflows`. Returns * `undefined` if neither lookup succeeds — callers decide how to handle * the missing case (e.g. terminal failure vs. cleanup pass-through) so * we don't throw inside `#dispatch` and trigger infinite event retries. */ #tryResolveWorkflow(workflowId) { try { return this.mastra.getWorkflowById(workflowId); } catch { return void 0; } } async errorWorkflow({ parentWorkflow, workflowId, runId, resumeSteps, stepResults, resumeData, requestContext }, e) { await this.mastra.pubsub.publish("workflows", { type: "workflow.fail", runId, data: { workflowId, runId, executionPath: [], resumeSteps, stepResults, prevResult: { status: "failed", error: chunk4U7ZLI36_cjs.getErrorFromUnknown(e).toJSON() }, requestContext, resumeData, activeStepsPath: {}, parentWorkflow } }); } async processWorkflowCancel({ workflowId, runId, prevResult, ...args }) { this.cancelRunAndChildren(runId); const workflowsStore = await this.mastra.getStorage()?.getStore("workflows"); const currentState = await workflowsStore?.loadWorkflowSnapshot({ workflowName: workflowId, runId }); if (!currentState) { this.mastra.getLogger()?.warn("Canceling workflow without loaded state", { workflowId, runId }); } await this.endWorkflow( { workflowId, runId, prevResult, ...args }, "canceled" ); } async processWorkflowStart({ workflow, parentWorkflow, workflowId, runId, resumeSteps, prevResult, resumeData, timeTravel, restart, executionPath, stepResults, requestContext, perStep, format, state, outputOptions, forEachIndex }) { const initialState = arguments[0].initialState ?? state ?? {}; const resolvedFormat = format ?? this.runFormats.get(runId); this.runFormats.set(runId, resolvedFormat); this.getOrCreateAbortController(runId); if (parentWorkflow?.runId) { this.parentChildRelationships.set(runId, parentWorkflow.runId); } const workflowsStore = await this.mastra.getStorage()?.getStore("workflows"); const existingRun = await workflowsStore?.getWorkflowRunById({ runId, workflowName: workflow.id }); const resourceId = existingRun?.resourceId; const shouldPersist = workflow?.options?.shouldPersistSnapshot?.({ stepResults: stepResults ?? {}, workflowStatus: "running" }) ?? true; if (shouldPersist) { await workflowsStore?.persistWorkflowSnapshot({ workflowName: workflow.id, runId, resourceId, snapshot: { activePaths: [], suspendedPaths: {}, resumeLabels: {}, waitingPaths: {}, activeStepsPath: {}, serializedStepGraph: workflow.serializedStepGraph, timestamp: Date.now(), runId, context: { ...stepResults ?? { input: prevResult?.status === "success" ? prevResult.output : void 0 }, __state: initialState }, status: "running", value: initialState } }); if (parentWorkflow) { const parentSnap = await workflowsStore?.loadWorkflowSnapshot({ workflowName: parentWorkflow.workflowId, runId: parentWorkflow.runId }); const existing = parentSnap?.context?.[workflowId]; await workflowsStore?.updateWorkflowResults({ workflowName: parentWorkflow.workflowId, runId: parentWorkflow.runId, stepId: workflowId, result: { startedAt: existing?.startedAt ?? Date.now(), status: "running", payload: existing?.payload ?? parentWorkflow.input?.output ?? {}, ...existing ?? {}, // preserve anything else (suspendPayload, etc.) metadata: { ...existing?.metadata ?? {}, nestedRunId: runId } }, requestContext }); } } await this.mastra.pubsub.publish("workflows", { type: "workflow.step.run", runId, data: { parentWorkflow, workflowId, runId, executionPath: executionPath ?? [0], resumeSteps, stepResults: { ...stepResults ?? { input: prevResult?.status === "success" ? prevResult.output : void 0 }, __state: initialState }, prevResult, timeTravel, restart, requestContext, resumeData, activeStepsPath: {}, perStep, state: initialState, outputOptions, forEachIndex } }); } async endWorkflow(args, status = "success") { const { workflowId, runId, prevResult, perStep, workflow, stepResults, activeStepsPath, executionPath } = args; const workflowsStore = await this.mastra.getStorage()?.getStore("workflows"); const finalStatus = perStep && status === "success" ? "paused" : status; const shouldPersist = workflow?.options?.shouldPersistSnapshot?.({ stepResults: stepResults ?? {}, workflowStatus: finalStatus }) ?? true; if (shouldPersist) { await workflowsStore?.updateWorkflowState({ workflowName: workflowId, runId, opts: { status: finalStatus, result: prevResult, activePaths: executionPath, activeStepsPath } }); } if (perStep) { await this.mastra.pubsub.publish(`workflow.events.v2.${runId}`, { type: "watch", runId, data: { type: "workflow-paused", payload: {} } }); } await this.mastra.pubsub.publish(`workflow.events.v2.${runId}`, { type: "watch", runId, data: { type: "workflow-finish", payload: { runId } } }); await this.mastra.pubsub.publish("workflows", { type: "workflow.end", runId, data: { ...args, workflow: void 0 } }); } async processWorkflowEnd(args) { const { resumeSteps, prevResult, resumeData, parentWorkflow, activeStepsPath, requestContext, runId, timeTravel, perStep, stepResults, state} = args; const finalState = resolveCurrentState({ stepResults, state }); this.cleanupRun(runId); if (parentWorkflow) { const step = parentWorkflow.stepGraph[parentWorkflow.executionPath[0]]; if (step?.type === "loop") { await processWorkflowLoop( { workflowId: parentWorkflow.workflowId, prevResult, runId: parentWorkflow.runId, executionPath: parentWorkflow.executionPath, stepResults: parentWorkflow.stepResults, activeStepsPath: parentWorkflow.activeStepsPath, resumeSteps: parentWorkflow.resumeSteps, resumeData: parentWorkflow.resumeData, parentWorkflow: parentWorkflow.parentWorkflow, requestContext, retryCount: 0 }, { pubsub: this.mastra.pubsub, stepExecutor: this.stepExecutor, step, stepResult: prevResult } ); } el