@mastra/core
Version:
Mastra is a framework for building AI-powered applications and agents with a modern TypeScript stack.
1,880 lines (1,874 loc) • 71.1 kB
JavaScript
'use strict';
var chunkXDMQQZNX_cjs = require('./chunk-XDMQQZNX.cjs');
var chunkABJOUEVA_cjs = require('./chunk-ABJOUEVA.cjs');
var chunkGPWMM745_cjs = require('./chunk-GPWMM745.cjs');
var chunk5NTO7S5I_cjs = require('./chunk-5NTO7S5I.cjs');
var chunkVF676YCO_cjs = require('./chunk-VF676YCO.cjs');
var chunk6VOPKVYH_cjs = require('./chunk-6VOPKVYH.cjs');
var chunkA5KDVZDL_cjs = require('./chunk-A5KDVZDL.cjs');
var EventEmitter = require('events');
var crypto = require('crypto');
var z = require('zod');
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
var EventEmitter__default = /*#__PURE__*/_interopDefault(EventEmitter);
var z__default = /*#__PURE__*/_interopDefault(z);
var StepExecutor = class extends chunk6VOPKVYH_cjs.MastraBase {
mastra;
constructor({ mastra }) {
super({ name: "StepExecutor", component: chunkA5KDVZDL_cjs.RegisteredLogger.WORKFLOW });
this.mastra = mastra;
}
__registerMastra(mastra) {
this.mastra = mastra;
}
async execute(params) {
const { step, stepResults, runId, runtimeContext, runCount = 0 } = params;
const abortController = new AbortController();
let suspended;
let bailed;
const startedAt = Date.now();
const { inputData, validationError } = await chunkXDMQQZNX_cjs.validateStepInput({
prevOutput: typeof params.foreachIdx === "number" ? params.input?.[params.foreachIdx] : params.input,
step,
validateInputs: params.validateInputs ?? false
});
let stepInfo = {
...stepResults[step.id],
startedAt,
payload: (typeof params.foreachIdx === "number" ? params.input : inputData) ?? {}
};
if (params.resumeData) {
delete stepInfo.suspendPayload?.["__workflow_meta"];
stepInfo.resumePayload = params.resumeData;
stepInfo.resumedAt = Date.now();
}
try {
if (validationError) {
throw validationError;
}
const stepResult = await step.execute({
workflowId: params.workflowId,
runId,
mastra: this.mastra,
runtimeContext,
inputData,
state: params.state,
setState: (state) => {
params.state = state;
},
runCount,
resumeData: params.resumeData,
getInitData: () => stepResults?.input,
getStepResult: chunkXDMQQZNX_cjs.getStepResult.bind(this, stepResults),
suspend: async (suspendPayload) => {
suspended = { payload: { ...suspendPayload, __workflow_meta: { runId, path: [step.id] } } };
},
bail: (result) => {
bailed = { payload: result };
},
// TODO
writer: void 0,
abort: () => {
abortController?.abort();
},
[chunkABJOUEVA_cjs.EMITTER_SYMBOL]: params.emitter,
// TODO: refactor this to use our PubSub actually
[chunkABJOUEVA_cjs.STREAM_FORMAT_SYMBOL]: void 0,
// TODO
engine: {},
abortSignal: abortController?.signal,
// TODO
tracingContext: {}
});
const endedAt = Date.now();
let finalResult;
if (suspended) {
finalResult = {
...stepInfo,
status: "suspended",
suspendedAt: endedAt
};
if (suspended.payload) {
finalResult.suspendPayload = suspended.payload;
}
} else if (bailed) {
finalResult = {
...stepInfo,
// @ts-ignore
status: "bailed",
endedAt,
output: bailed.payload
};
} else {
finalResult = {
...stepInfo,
status: "success",
endedAt,
output: stepResult
};
}
return finalResult;
} catch (error) {
const endedAt = Date.now();
return {
...stepInfo,
status: "failed",
endedAt,
error: error instanceof Error ? error?.stack ?? error.message : error
};
}
}
async evaluateConditions(params) {
const { step, stepResults, runId, runtimeContext, runCount = 0 } = params;
const abortController = new AbortController();
const ee = new EventEmitter__default.default();
const results = await Promise.all(
step.conditions.map((condition) => {
try {
return this.evaluateCondition({
workflowId: params.workflowId,
condition,
runId,
runtimeContext,
inputData: params.input,
state: params.state,
runCount,
resumeData: params.resumeData,
abortController,
stepResults,
emitter: ee,
iterationCount: 0
});
} catch (e) {
console.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,
runtimeContext,
emitter,
abortController,
runCount = 0,
iterationCount
}) {
return condition({
workflowId,
runId,
mastra: this.mastra,
runtimeContext,
inputData,
state,
setState: (_state) => {
},
runCount,
resumeData,
getInitData: () => stepResults?.input,
getStepResult: chunkXDMQQZNX_cjs.getStepResult.bind(this, stepResults),
suspend: async (_suspendPayload) => {
throw new Error("Not implemented");
},
bail: (_result) => {
throw new Error("Not implemented");
},
// TODO
writer: void 0,
abort: () => {
abortController?.abort();
},
[chunkABJOUEVA_cjs.EMITTER_SYMBOL]: emitter,
// TODO: refactor this to use our PubSub actually
[chunkABJOUEVA_cjs.STREAM_FORMAT_SYMBOL]: void 0,
// TODO
engine: {},
abortSignal: abortController?.signal,
// TODO
tracingContext: {},
iterationCount
});
}
async resolveSleep(params) {
const { step, stepResults, runId, runtimeContext, runCount = 0 } = params;
const abortController = new AbortController();
const ee = new EventEmitter__default.default();
if (step.duration) {
return step.duration;
}
if (!step.fn) {
return 0;
}
try {
return await step.fn({
workflowId: params.workflowId,
runId,
mastra: this.mastra,
runtimeContext,
inputData: params.input,
// TODO: implement state
state: {},
setState: (_state) => {
},
runCount,
resumeData: params.resumeData,
getInitData: () => stepResults?.input,
getStepResult: chunkXDMQQZNX_cjs.getStepResult.bind(this, stepResults),
suspend: async (_suspendPayload) => {
throw new Error("Not implemented");
},
bail: (_result) => {
throw new Error("Not implemented");
},
abort: () => {
abortController?.abort();
},
// TODO
writer: void 0,
[chunkABJOUEVA_cjs.EMITTER_SYMBOL]: ee,
// TODO: refactor this to use our PubSub actually
[chunkABJOUEVA_cjs.STREAM_FORMAT_SYMBOL]: void 0,
// TODO
engine: {},
abortSignal: abortController?.signal,
// TODO
tracingContext: {}
});
} catch (e) {
console.error("error evaluating condition", e);
return 0;
}
}
async resolveSleepUntil(params) {
const { step, stepResults, runId, runtimeContext, runCount = 0 } = params;
const abortController = new AbortController();
const ee = new EventEmitter__default.default();
if (step.date) {
return step.date.getTime() - Date.now();
}
if (!step.fn) {
return 0;
}
try {
const result = await step.fn({
workflowId: params.workflowId,
runId,
mastra: this.mastra,
runtimeContext,
inputData: params.input,
// TODO: implement state
state: {},
setState: (_state) => {
},
runCount,
resumeData: params.resumeData,
getInitData: () => stepResults?.input,
getStepResult: chunkXDMQQZNX_cjs.getStepResult.bind(this, stepResults),
suspend: async (_suspendPayload) => {
throw new Error("Not implemented");
},
bail: (_result) => {
throw new Error("Not implemented");
},
abort: () => {
abortController?.abort();
},
// TODO
writer: void 0,
[chunkABJOUEVA_cjs.EMITTER_SYMBOL]: ee,
// TODO: refactor this to use our PubSub actually
[chunkABJOUEVA_cjs.STREAM_FORMAT_SYMBOL]: void 0,
// TODO
engine: {},
abortSignal: abortController?.signal,
// TODO
tracingContext: {}
});
return result.getTime() - Date.now();
} catch (e) {
console.error("error evaluating condition", e);
return 0;
}
}
};
// src/events/processor.ts
var EventProcessor = class {
mastra;
__registerMastra(mastra) {
this.mastra = mastra;
}
constructor({ mastra }) {
this.mastra = mastra;
}
};
async function processWorkflowLoop({
workflowId,
prevResult,
runId,
executionPath,
stepResults,
activeSteps,
resumeSteps,
resumeData,
parentWorkflow,
runtimeContext,
runCount = 0
}, {
pubsub,
stepExecutor,
step,
stepResult
}) {
const loopCondition = await stepExecutor.evaluateCondition({
workflowId,
condition: step.condition,
runId,
stepResults,
// TODO: implement state
state: {},
emitter: new EventEmitter__default.default(),
// TODO
runtimeContext: new chunkGPWMM745_cjs.RuntimeContext(),
// TODO
inputData: prevResult?.status === "success" ? prevResult.output : void 0,
resumeData,
abortController: new AbortController(),
runCount,
iterationCount: 0
//TODO: implement
});
if (step.loopType === "dountil") {
if (loopCondition) {
await pubsub.publish("workflows", {
type: "workflow.step.end",
runId,
data: {
parentWorkflow,
workflowId,
runId,
executionPath,
resumeSteps,
stepResults,
prevResult: stepResult,
resumeData,
activeSteps,
runtimeContext
}
});
} else {
await pubsub.publish("workflows", {
type: "workflow.step.run",
runId,
data: {
parentWorkflow,
workflowId,
runId,
executionPath,
resumeSteps,
stepResults,
prevResult: stepResult,
resumeData,
activeSteps,
runtimeContext,
runCount
}
});
}
} else {
if (loopCondition) {
await pubsub.publish("workflows", {
type: "workflow.step.run",
runId,
data: {
parentWorkflow,
workflowId,
runId,
executionPath,
resumeSteps,
stepResults,
prevResult: stepResult,
resumeData,
activeSteps,
runtimeContext,
runCount
}
});
} else {
await pubsub.publish("workflows", {
type: "workflow.step.end",
runId,
data: {
parentWorkflow,
workflowId,
runId,
executionPath,
resumeSteps,
stepResults,
prevResult: stepResult,
resumeData,
activeSteps,
runtimeContext
}
});
}
}
}
async function processWorkflowForEach({
workflowId,
prevResult,
runId,
executionPath,
stepResults,
activeSteps,
resumeSteps,
resumeData,
parentWorkflow,
runtimeContext
}, {
pubsub,
mastra,
step
}) {
const currentResult = stepResults[step.step.id];
const idx = currentResult?.output?.length ?? 0;
const targetLen = prevResult?.output?.length ?? 0;
if (idx >= targetLen && currentResult.output.filter((r) => r !== null).length >= targetLen) {
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,
prevResult: currentResult,
resumeData,
activeSteps,
runtimeContext
}
});
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 mastra.getStorage()?.updateWorkflowResults({
workflowName: workflowId,
runId,
stepId: step.step.id,
result: {
status: "succcess",
output: dummyResult,
startedAt: Date.now(),
payload: prevResult?.output
},
runtimeContext
});
for (let i = 0; i < concurrency; i++) {
await pubsub.publish("workflows", {
type: "workflow.step.run",
runId,
data: {
parentWorkflow,
workflowId,
runId,
executionPath: [executionPath[0], i],
resumeSteps,
stepResults,
prevResult,
resumeData,
activeSteps,
runtimeContext
}
});
}
return;
}
currentResult.output.push(null);
await mastra.getStorage()?.updateWorkflowResults({
workflowName: workflowId,
runId,
stepId: step.step.id,
result: {
status: "succcess",
output: currentResult.output,
startedAt: Date.now(),
payload: prevResult?.output
},
runtimeContext
});
await pubsub.publish("workflows", {
type: "workflow.step.run",
runId,
data: {
parentWorkflow,
workflowId,
runId,
executionPath: [executionPath[0], idx],
resumeSteps,
stepResults,
prevResult,
resumeData,
activeSteps,
runtimeContext
}
});
}
async function processWorkflowParallel({
workflowId,
runId,
executionPath,
stepResults,
activeSteps,
resumeSteps,
prevResult,
resumeData,
parentWorkflow,
runtimeContext
}, {
pubsub,
step
}) {
for (let i = 0; i < step.steps.length; i++) {
const nestedStep = step.steps[i];
if (nestedStep?.type === "step") {
activeSteps[nestedStep.step.id] = true;
}
}
await Promise.all(
step.steps.map(async (_step, idx) => {
return pubsub.publish("workflows", {
type: "workflow.step.run",
runId,
data: {
workflowId,
runId,
executionPath: executionPath.concat([idx]),
resumeSteps,
stepResults,
prevResult,
resumeData,
parentWorkflow,
activeSteps,
runtimeContext
}
});
})
);
}
async function processWorkflowConditional({
workflowId,
runId,
executionPath,
stepResults,
activeSteps,
resumeSteps,
prevResult,
resumeData,
parentWorkflow,
runtimeContext
}, {
pubsub,
stepExecutor,
step
}) {
const idxs = await stepExecutor.evaluateConditions({
workflowId,
step,
runId,
stepResults,
// TODO: implement state
state: {},
emitter: new EventEmitter__default.default(),
// TODO
runtimeContext: new chunkGPWMM745_cjs.RuntimeContext(),
// TODO
input: prevResult?.status === "success" ? prevResult.output : void 0,
resumeData
});
const truthyIdxs = {};
for (let i = 0; i < idxs.length; i++) {
truthyIdxs[idxs[i]] = true;
}
await Promise.all(
step.steps.map(async (step2, idx) => {
if (truthyIdxs[idx]) {
if (step2?.type === "step") {
activeSteps[step2.step.id] = true;
}
return pubsub.publish("workflows", {
type: "workflow.step.run",
runId,
data: {
workflowId,
runId,
executionPath: executionPath.concat([idx]),
resumeSteps,
stepResults,
prevResult,
resumeData,
parentWorkflow,
activeSteps,
runtimeContext
}
});
} else {
return pubsub.publish("workflows", {
type: "workflow.step.end",
runId,
data: {
workflowId,
runId,
executionPath: executionPath.concat([idx]),
resumeSteps,
stepResults,
prevResult: { status: "skipped" },
resumeData,
parentWorkflow,
activeSteps,
runtimeContext
}
});
}
})
);
}
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,
activeSteps: [],
runtimeContext: currentState?.runtimeContext
}
});
}
async function processWorkflowSleep({
workflowId,
runId,
executionPath,
stepResults,
activeSteps,
resumeSteps,
prevResult,
resumeData,
parentWorkflow,
runtimeContext
}, {
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 duration = await stepExecutor.resolveSleep({
workflowId,
step,
runId,
stepResults,
emitter: new EventEmitter__default.default(),
// TODO
runtimeContext: new chunkGPWMM745_cjs.RuntimeContext(),
// TODO
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,
stepResults,
prevResult,
resumeData,
parentWorkflow,
activeSteps,
runtimeContext
}
});
},
duration < 0 ? 0 : duration
);
}
async function processWorkflowSleepUntil({
workflowId,
runId,
executionPath,
stepResults,
activeSteps,
resumeSteps,
prevResult,
resumeData,
parentWorkflow,
runtimeContext
}, {
pubsub,
stepExecutor,
step
}) {
const startedAt = Date.now();
const duration = await stepExecutor.resolveSleepUntil({
workflowId,
step,
runId,
stepResults,
emitter: new EventEmitter__default.default(),
// TODO
runtimeContext: new chunkGPWMM745_cjs.RuntimeContext(),
// TODO
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,
stepResults,
prevResult,
resumeData,
parentWorkflow,
activeSteps,
runtimeContext
}
});
},
duration < 0 ? 0 : duration
);
}
// src/workflows/evented/workflow-event-processor/index.ts
var WorkflowEventProcessor = class extends EventProcessor {
stepExecutor;
constructor({ mastra }) {
super({ mastra });
this.stepExecutor = new StepExecutor({ mastra });
}
__registerMastra(mastra) {
super.__registerMastra(mastra);
this.stepExecutor.__registerMastra(mastra);
}
async errorWorkflow({
parentWorkflow,
workflowId,
runId,
resumeSteps,
stepResults,
resumeData,
runtimeContext
}, e) {
await this.mastra.pubsub.publish("workflows", {
type: "workflow.fail",
runId,
data: {
workflowId,
runId,
executionPath: [],
resumeSteps,
stepResults,
prevResult: { status: "failed", error: e.stack ?? e.message },
runtimeContext,
resumeData,
activeSteps: {},
parentWorkflow
}
});
}
async processWorkflowCancel({ workflowId, runId }) {
const currentState = await this.mastra.getStorage()?.updateWorkflowState({
workflowName: workflowId,
runId,
opts: {
status: "canceled"
}
});
await this.endWorkflow({
workflow: void 0,
workflowId,
runId,
stepResults: currentState?.context,
prevResult: { status: "canceled" },
runtimeContext: currentState?.runtimeContext,
executionPath: [],
activeSteps: {},
resumeSteps: [],
resumeData: void 0,
parentWorkflow: void 0
});
}
async processWorkflowStart({
workflow,
parentWorkflow,
workflowId,
runId,
resumeSteps,
prevResult,
resumeData,
executionPath,
stepResults,
runtimeContext
}) {
await this.mastra.getStorage()?.persistWorkflowSnapshot({
workflowName: workflow.id,
runId,
snapshot: {
activePaths: [],
suspendedPaths: {},
resumeLabels: {},
waitingPaths: {},
serializedStepGraph: workflow.serializedStepGraph,
timestamp: Date.now(),
runId,
status: "running",
context: stepResults ?? {
input: prevResult?.status === "success" ? prevResult.output : void 0
},
value: {}
}
});
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
},
prevResult,
runtimeContext,
resumeData,
activeSteps: {}
}
});
}
async endWorkflow(args) {
const { stepResults, workflowId, runId, prevResult } = args;
await this.mastra.getStorage()?.updateWorkflowState({
workflowName: workflowId,
runId,
opts: {
status: "success",
result: prevResult
}
});
await this.mastra.pubsub.publish(`workflow.events.${runId}`, {
type: "watch",
runId,
data: {
type: "watch",
payload: {
currentStep: void 0,
workflowState: {
status: prevResult.status,
steps: stepResults,
result: prevResult.status === "success" ? prevResult.output : null,
error: prevResult.error ?? null
}
},
eventTimestamp: Date.now()
}
});
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, activeSteps, runtimeContext, runId } = args;
if (parentWorkflow) {
await this.mastra.pubsub.publish("workflows", {
type: "workflow.step.end",
runId,
data: {
workflowId: parentWorkflow.workflowId,
runId: parentWorkflow.runId,
executionPath: parentWorkflow.executionPath,
resumeSteps,
stepResults: parentWorkflow.stepResults,
prevResult,
resumeData,
activeSteps,
parentWorkflow: parentWorkflow.parentWorkflow,
parentContext: parentWorkflow,
runtimeContext
}
});
}
await this.mastra.pubsub.publish("workflows-finish", {
type: "workflow.end",
runId,
data: { ...args, workflow: void 0 }
});
}
async processWorkflowSuspend(args) {
const { resumeSteps, prevResult, resumeData, parentWorkflow, activeSteps, runId, runtimeContext } = args;
if (parentWorkflow) {
await this.mastra.pubsub.publish("workflows", {
type: "workflow.step.end",
runId,
data: {
workflowId: parentWorkflow.workflowId,
runId: parentWorkflow.runId,
executionPath: parentWorkflow.executionPath,
resumeSteps,
stepResults: parentWorkflow.stepResults,
prevResult: {
...prevResult,
suspendPayload: {
...prevResult.suspendPayload,
__workflow_meta: {
runId,
path: parentWorkflow?.stepId ? [parentWorkflow.stepId].concat(prevResult.suspendPayload?.__workflow_meta?.path ?? []) : prevResult.suspendPayload?.__workflow_meta?.path ?? []
}
}
},
resumeData,
activeSteps,
runtimeContext,
parentWorkflow: parentWorkflow.parentWorkflow,
parentContext: parentWorkflow
}
});
}
await this.mastra.pubsub.publish("workflows-finish", {
type: "workflow.suspend",
runId,
data: { ...args, workflow: void 0 }
});
}
async processWorkflowFail(args) {
const { workflowId, runId, resumeSteps, prevResult, resumeData, parentWorkflow, activeSteps, runtimeContext } = args;
await this.mastra.getStorage()?.updateWorkflowState({
workflowName: workflowId,
runId,
opts: {
status: "failed",
error: prevResult.error
}
});
if (parentWorkflow) {
await this.mastra.pubsub.publish("workflows", {
type: "workflow.step.end",
runId,
data: {
workflowId: parentWorkflow.workflowId,
runId: parentWorkflow.runId,
executionPath: parentWorkflow.executionPath,
resumeSteps,
stepResults: parentWorkflow.stepResults,
prevResult,
resumeData,
activeSteps,
runtimeContext,
parentWorkflow: parentWorkflow.parentWorkflow,
parentContext: parentWorkflow
}
});
}
await this.mastra.pubsub.publish("workflows-finish", {
type: "workflow.fail",
runId,
data: { ...args, workflow: void 0 }
});
}
async processWorkflowStepRun({
workflow,
workflowId,
runId,
executionPath,
stepResults,
activeSteps,
resumeSteps,
prevResult,
resumeData,
parentWorkflow,
runtimeContext,
runCount = 0
}) {
let stepGraph = workflow.stepGraph;
if (!executionPath?.length) {
return this.errorWorkflow(
{
workflowId,
runId,
executionPath,
stepResults,
activeSteps,
resumeSteps,
prevResult,
resumeData,
parentWorkflow,
runtimeContext
},
new chunk5NTO7S5I_cjs.MastraError({
id: "MASTRA_WORKFLOW",
text: `Execution path is empty: ${JSON.stringify(executionPath)}`,
domain: "MASTRA_WORKFLOW" /* MASTRA_WORKFLOW */,
category: "SYSTEM" /* SYSTEM */
})
);
}
let step = stepGraph[executionPath[0]];
if (!step) {
return this.errorWorkflow(
{
workflowId,
runId,
executionPath,
stepResults,
activeSteps,
resumeSteps,
prevResult,
resumeData,
parentWorkflow,
runtimeContext
},
new chunk5NTO7S5I_cjs.MastraError({
id: "MASTRA_WORKFLOW",
text: `Step not found in step graph: ${JSON.stringify(executionPath)}`,
domain: "MASTRA_WORKFLOW" /* MASTRA_WORKFLOW */,
category: "SYSTEM" /* SYSTEM */
})
);
}
if ((step.type === "parallel" || step.type === "conditional") && executionPath.length > 1) {
step = step.steps[executionPath[1]];
} else if (step.type === "parallel") {
return processWorkflowParallel(
{
workflowId,
runId,
executionPath,
stepResults,
activeSteps,
resumeSteps,
prevResult,
resumeData,
parentWorkflow,
runtimeContext
},
{
pubsub: this.mastra.pubsub,
step
}
);
} else if (step?.type === "conditional") {
return processWorkflowConditional(
{
workflowId,
runId,
executionPath,
stepResults,
activeSteps,
resumeSteps,
prevResult,
resumeData,
parentWorkflow,
runtimeContext
},
{
pubsub: this.mastra.pubsub,
stepExecutor: this.stepExecutor,
step
}
);
} else if (step?.type === "sleep") {
return processWorkflowSleep(
{
workflowId,
runId,
executionPath,
stepResults,
activeSteps,
resumeSteps,
prevResult,
resumeData,
parentWorkflow,
runtimeContext
},
{
pubsub: this.mastra.pubsub,
stepExecutor: this.stepExecutor,
step
}
);
} else if (step?.type === "sleepUntil") {
return processWorkflowSleepUntil(
{
workflowId,
runId,
executionPath,
stepResults,
activeSteps,
resumeSteps,
prevResult,
resumeData,
parentWorkflow,
runtimeContext
},
{
pubsub: this.mastra.pubsub,
stepExecutor: this.stepExecutor,
step
}
);
} else if (step?.type === "waitForEvent" && !resumeData) {
await this.mastra.getStorage()?.updateWorkflowResults({
workflowName: workflowId,
runId,
stepId: step.step.id,
result: {
startedAt: Date.now(),
status: "waiting",
payload: prevResult.status === "success" ? prevResult.output : void 0
},
runtimeContext
});
await this.mastra.getStorage()?.updateWorkflowState({
workflowName: workflowId,
runId,
opts: {
status: "waiting",
waitingPaths: {
[step.event]: executionPath
}
}
});
await this.mastra.pubsub.publish(`workflow.events.v2.${runId}`, {
type: "watch",
runId,
data: {
type: "workflow-step-waiting",
payload: {
id: step.step.id,
status: "waiting",
payload: prevResult.status === "success" ? prevResult.output : void 0,
startedAt: Date.now()
}
}
});
return;
} else if (step?.type === "foreach" && executionPath.length === 1) {
return processWorkflowForEach(
{
workflowId,
runId,
executionPath,
stepResults,
activeSteps,
resumeSteps,
prevResult,
resumeData,
parentWorkflow,
runtimeContext
},
{
pubsub: this.mastra.pubsub,
mastra: this.mastra,
step
}
);
}
if (!isExecutableStep(step)) {
return this.errorWorkflow(
{
workflowId,
runId,
executionPath,
stepResults,
activeSteps,
resumeSteps,
prevResult,
resumeData,
parentWorkflow,
runtimeContext
},
new chunk5NTO7S5I_cjs.MastraError({
id: "MASTRA_WORKFLOW",
text: `Step is not executable: ${step?.type} -- ${JSON.stringify(executionPath)}`,
domain: "MASTRA_WORKFLOW" /* MASTRA_WORKFLOW */,
category: "SYSTEM" /* SYSTEM */
})
);
}
activeSteps[step.step.id] = true;
if (step.step instanceof EventedWorkflow) {
if (resumeSteps?.length > 1) {
const stepData = stepResults[step.step.id];
const nestedRunId = stepData?.suspendPayload?.__workflow_meta?.runId;
if (!nestedRunId) {
return this.errorWorkflow(
{
workflowId,
runId,
executionPath,
stepResults,
activeSteps,
resumeSteps,
prevResult,
resumeData,
parentWorkflow,
runtimeContext
},
new chunk5NTO7S5I_cjs.MastraError({
id: "MASTRA_WORKFLOW",
text: `Nested workflow run id not found: ${JSON.stringify(stepResults)}`,
domain: "MASTRA_WORKFLOW" /* MASTRA_WORKFLOW */,
category: "SYSTEM" /* SYSTEM */
})
);
}
const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
workflowName: step.step.id,
runId: nestedRunId
});
const nestedStepResults = snapshot?.context;
const nestedSteps = resumeSteps.slice(1);
await this.mastra.pubsub.publish("workflows", {
type: "workflow.resume",
runId,
data: {
workflowId: step.step.id,
parentWorkflow: {
stepId: step.step.id,
workflowId,
runId,
executionPath,
resumeSteps,
stepResults,
input: prevResult,
parentWorkflow
},
executionPath: snapshot?.suspendedPaths?.[nestedSteps[0]],
runId: nestedRunId,
resumeSteps: nestedSteps,
stepResults: nestedStepResults,
prevResult,
resumeData,
activeSteps,
runtimeContext
}
});
} else {
await this.mastra.pubsub.publish("workflows", {
type: "workflow.start",
runId,
data: {
workflowId: step.step.id,
parentWorkflow: {
stepId: step.step.id,
workflowId,
runId,
executionPath,
resumeSteps,
stepResults,
input: prevResult,
parentWorkflow
},
executionPath: [0],
runId: crypto.randomUUID(),
resumeSteps,
prevResult,
resumeData,
activeSteps,
runtimeContext
}
});
}
return;
}
if (step.type === "step" || step.type === "waitForEvent") {
await this.mastra.pubsub.publish(`workflow.events.${runId}`, {
type: "watch",
runId,
data: {
type: "watch",
payload: {
currentStep: { id: step.step.id, status: "running" },
workflowState: {
status: "running",
steps: stepResults,
error: null,
result: null
}
},
eventTimestamp: Date.now()
}
});
await this.mastra.pubsub.publish(`workflow.events.v2.${runId}`, {
type: "watch",
runId,
data: {
type: "workflow-step-start",
payload: {
id: step.step.id,
startedAt: Date.now(),
payload: prevResult.status === "success" ? prevResult.output : void 0,
status: "running"
}
}
});
}
const ee = new EventEmitter__default.default();
ee.on("watch-v2", async (event) => {
await this.mastra.pubsub.publish(`workflow.events.v2.${runId}`, {
type: "watch",
runId,
data: event
});
});
const rc = new chunkGPWMM745_cjs.RuntimeContext();
for (const [key, value] of Object.entries(runtimeContext)) {
rc.set(key, value);
}
const stepResult = await this.stepExecutor.execute({
workflowId,
step: step.step,
runId,
stepResults,
// TODO: implement state
state: {},
emitter: ee,
runtimeContext: rc,
input: prevResult?.output,
resumeData: step.type === "waitForEvent" || resumeSteps?.length === 1 && resumeSteps?.[0] === step.step.id ? resumeData : void 0,
runCount,
foreachIdx: step.type === "foreach" ? executionPath[1] : void 0,
validateInputs: workflow.options.validateInputs
});
runtimeContext = Object.fromEntries(rc.entries());
if (stepResult.status === "bailed") {
stepResult.status = "success";
await this.endWorkflow({
workflow,
resumeData,
parentWorkflow,
workflowId,
runId,
executionPath,
resumeSteps,
stepResults: {
...stepResults,
[step.step.id]: stepResult
},
prevResult: stepResult,
activeSteps,
runtimeContext
});
return;
}
if (stepResult.status === "failed") {
if (runCount >= (workflow.retryConfig.attempts ?? 0)) {
await this.mastra.pubsub.publish("workflows", {
type: "workflow.step.end",
runId,
data: {
parentWorkflow,
workflowId,
runId,
executionPath,
resumeSteps,
stepResults,
prevResult: stepResult,
activeSteps,
runtimeContext
}
});
} else {
return this.mastra.pubsub.publish("workflows", {
type: "workflow.step.run",
runId,
data: {
parentWorkflow,
workflowId,
runId,
executionPath,
resumeSteps,
stepResults,
prevResult,
activeSteps,
runtimeContext,
runCount: runCount + 1
}
});
}
}
if (step.type === "loop") {
await processWorkflowLoop(
{
workflowId,
prevResult: stepResult,
runId,
executionPath,
stepResults,
activeSteps,
resumeSteps,
resumeData,
parentWorkflow,
runtimeContext,
runCount: runCount + 1
},
{
pubsub: this.mastra.pubsub,
stepExecutor: this.stepExecutor,
step,
stepResult
}
);
} else {
await this.mastra.pubsub.publish("workflows", {
type: "workflow.step.end",
runId,
data: {
parentWorkflow,
workflowId,
runId,
executionPath,
resumeSteps,
stepResults,
prevResult: stepResult,
activeSteps,
runtimeContext
}
});
}
}
async processWorkflowStepEnd({
workflow,
workflowId,
runId,
executionPath,
resumeSteps,
prevResult,
parentWorkflow,
stepResults,
activeSteps,
parentContext,
runtimeContext
}) {
let step = workflow.stepGraph[executionPath[0]];
if ((step?.type === "parallel" || step?.type === "conditional") && executionPath.length > 1) {
step = step.steps[executionPath[1]];
}
if (!step) {
return this.errorWorkflow(
{
workflowId,
runId,
executionPath,
resumeSteps,
prevResult,
stepResults,
activeSteps,
runtimeContext
},
new chunk5NTO7S5I_cjs.MastraError({
id: "MASTRA_WORKFLOW",
text: `Step not found: ${JSON.stringify(executionPath)}`,
domain: "MASTRA_WORKFLOW" /* MASTRA_WORKFLOW */,
category: "SYSTEM" /* SYSTEM */
})
);
}
if (step.type === "foreach") {
const snapshot = await this.mastra.getStorage()?.loadWorkflowSnapshot({
workflowName: workflowId,
runId
});
const currentIdx = executionPath[1];
const currentResult = snapshot?.context?.[step.step.id]?.output;
let newResult = prevResult;
if (currentIdx !== void 0) {
if (currentResult) {
currentResult[currentIdx] = prevResult.output;
newResult = { ...prevResult, output: currentResult };
} else {
newResult = { ...prevResult, output: [prevResult.output] };
}
}
const newStepResults = await this.mastra.getStorage()?.updateWorkflowResults({
workflowName: workflow.id,
runId,
stepId: step.step.id,
result: newResult,
runtimeContext
});
if (!newStepResults) {
return;
}
stepResults = newStepResults;
} else if (isExecutableStep(step)) {
delete activeSteps[step.step.id];
if (parentContext) {
prevResult = stepResults[step.step.id] = {
...prevResult,
payload: parentContext.input?.output ?? {}
};
}
const newStepResults = await this.mastra.getStorage()?.updateWorkflowResults({
workflowName: workflow.id,
runId,
stepId: step.step.id,
result: prevResult,
runtimeContext
});
if (!newStepResults) {
return;
}
stepResults = newStepResults;
}
if (!prevResult?.status || prevResult.status === "failed") {
await this.mastra.pubsub.publish("workflows", {
type: "workflow.fail",
runId,
data: {
workflowId,
runId,
executionPath,
resumeSteps,
parentWorkflow,
stepResults,
prevResult,
activeSteps,
runtimeContext
}
});
return;
} else if (prevResult.status === "suspended") {
const suspendedPaths = {};
const suspendedStep = getStep(workflow, executionPath);
if (suspendedStep) {
suspendedPaths[suspendedStep.id] = executionPath;
}
await this.mastra.getStorage()?.updateWorkflowState({
workflowName: workflowId,
runId,
opts: {
status: "suspended",
result: prevResult,
suspendedPaths
}
});
await this.mastra.pubsub.publish("workflows", {
type: "workflow.suspend",
runId,
data: {
workflowId,
runId,
executionPath,
resumeSteps,
parentWorkflow,
stepResults,
prevResult,
activeSteps,
runtimeContext
}
});
await this.mastra.pubsub.publish(`workflow.events.${runId}`, {
type: "watch",
runId,
data: {
type: "watch",
payload: {
currentStep: { ...prevResult, id: step?.step?.id },
workflowState: {
status: "suspended",
steps: stepResults,
suspendPayload: prevResult.suspendPayload
}
}
}
});
await this.mastra.pubsub.publish(`workflow.events.v2.${runId}`, {
type: "watch",
runId,
data: {
type: "workflow-step-suspended",
payload: {
id: step?.step?.id,
...prevResult,
suspendedAt: Date.now(),
suspendPayload: prevResult.suspendPayload
}
}
});
return;
}
if (step?.type === "step" || step?.type === "waitForEvent") {
await this.mastra.pubsub.publish(`workflow.events.${runId}`, {
type: "watch",
runId,
data: {
type: "watch",
payload: {
currentStep: { ...prevResult, id: step.step.id },
workflowState: {
status: "running",
steps: stepResults,
error: null,
result: null
}
},
eventTimestamp: Date.now()
}
});
await this.mastra.pubsub.publish(`workflow.events.v2.${runId}`, {
type: "watch",
runId,
data: {
type: "workflow-step-result",
payload: {
id: step.step.id,
...prevResult
}
}
});
if (prevResult.status === "success") {
await this.mastra.pubsub.publish(`workflow.events.v2.${runId}`, {
type: "watch",
runId,
data: {
type: "workflow-step-finish",
payload: {
id: step.step.id,
metadata: {}
}
}
});
}
}
step = workflow.stepGraph[executionPath[0]];
if ((step?.type === "parallel" || step?.type === "conditional") && executionPath.length > 1) {
let skippedCount = 0;
const allResults = step.steps.reduce(
(acc, step2) => {
if (isExecutableStep(step2)) {
const res = stepResults?.[step2.step.id];
if (res && res.status === "success") {
acc[step2.step.id] = res?.output;
} else if (res?.status === "skipped") {
skippedCount++;
}
}
return acc;
},
{}
);
const keys = Object.keys(allResults);
if (keys.length + skippedCount < step.steps.length) {
return;
}
await this.mastra.pubsub.publish("workflows", {
type: "workflow.step.end",
runId,
data: {
parentWorkflow,
workflowId,
runId,
executionPath: executionPath.slice(0, -1),
resumeSteps,
stepResults,
prevResult: { status: "success", output: allResults },
activeSteps,
runtimeContext
}
});
} else if (step?.type === "foreach") {
await this.mastra.pubsub.publish("workflows", {
type: "workflow.step.run",
runId,
data: {
workflowId,
runId,
executionPath: executionPath.slice(0, -1),
resumeSteps,
parentWorkflow,
stepResults,
prevResult: { ...prevResult, output: prevResult?.payload },
activeSteps,
runtimeContext
}
});
} else if (executionPath[0] >= workflow.stepGraph.length - 1) {
await this.endWorkflow({
workflow,
parentWorkflow,
workflowId,
runId,
executionPath,
resumeSteps,
stepResults,
prevResult,
activeSteps,
runtimeContext
});
} else {
await this.mastra.pubsub.publish("workflows", {
type: "workflow.step.run",
runId,
data: {
workflowId,
runId,
executionPath: executionPath.slice(0, -1).concat([executionPath[executionPath.length - 1] + 1]),
resumeSteps,
parentWorkflow,
stepResults,
prevResult,
activeSteps,
runtimeContext
}
});
}
}
async loadData({
workflowId,
runId
}) {
const snapshot = await this.mastra.getStorage()?.loadWorkflowSnapshot({
workflowName: workflowId,
runId
});
return snapshot;
}
async process(event, ack) {
const { type, data } = event;
const workflowData =