@mastra/core
Version:
350 lines (349 loc) • 15.9 kB
JavaScript
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const require_agent = require("../agent-DCD4MApC.cjs");
const require_cron = require("../cron-CrmzJKFJ.cjs");
const require_workflow_event_processor = require("../workflow-event-processor-CkjVcesJ.cjs");
const require_scheduler = require("../scheduler-D9Mqp8B5.cjs");
const require_validate = require("../validate-C0iI8guc.cjs");
let _mastra_schema_compat_schema = require("@mastra/schema-compat/schema");
//#region src/workflows/stored/serialize.ts
/**
* Live → Storable half of the workflow round-trip: walk a live `stepFlow`
* (runtime references, closures) and emit the JSON-safe storable form
* (ids + serialized mapping configs, no closures).
*
* The static subset that round-trips:
* - agent / tool by id
* - mapping with `value`, `step`, `initData`, `requestContextPath`, `template`,
* `state` sources (no `fn` source — closures don't round-trip)
* - sleep / sleepUntil with literal duration/date
* - parallel (inner entries must themselves be static)
* - foreach with literal concurrency
* - conditional / loop with declarative predicates (closure predicates throw)
* - generic `.then(step)` falls back to a minimal step descriptor — usable
* only when the step's id resolves on the live Mastra at load time
*
* Anything outside the subset throws at `toStorableGraph` time: silent loss
* would ship broken workflows unnoticed.
*/
/**
* Walk a live `stepFlow` and emit a JSON-safe `SerializedStepFlowEntry[]` with
* full (un-truncated) mapping configs and all step/agent/tool references stored
* as ids. Throws on entries that can't round-trip (closures, closure predicates).
*/
function toStorableGraph(stepFlow) {
return stepFlow.map((entry) => serializeEntry(entry));
}
function serializeEntry(entry) {
switch (entry.type) {
case "step":
case "agent":
case "tool":
case "mapping": return serializeSingleEntry(entry);
case "sleep":
if (typeof entry.duration !== "number") throw new Error(`Sleep step "${entry.id}" cannot be stored: dynamic duration (function) is not supported.`);
return {
type: "sleep",
id: entry.id,
duration: entry.duration
};
case "sleepUntil":
if (!(entry.date instanceof Date)) throw new Error(`SleepUntil step "${entry.id}" cannot be stored: dynamic date (function) is not supported.`);
return {
type: "sleepUntil",
id: entry.id,
date: entry.date
};
case "parallel": return {
type: "parallel",
steps: entry.steps.map((s) => serializeSingleEntry(s))
};
case "foreach":
if (entry.step.type === "mapping") throw new Error(`Foreach step cannot iterate a mapping: mappings project data, they don't execute per item. Use an agent, tool, or plain step as the foreach body.`);
return {
type: "foreach",
step: serializeSingleEntry(entry.step),
opts: typeof entry.opts.concurrency === "function" ? { fn: entry.opts.concurrency.toString() } : { concurrency: entry.opts.concurrency }
};
case "conditional": {
const predicates = entry.predicates;
if (!predicates || predicates.some((p) => !p || typeof p !== "object")) throw new Error(`Conditional (branch) step cannot be stored: closure predicates do not round-trip. Use the declarative form ({ predicate: {...} }) for each branch.`);
return {
type: "conditional",
steps: entry.steps.map((s) => serializeSingleEntry(s)),
serializedConditions: entry.serializedConditions,
predicates
};
}
case "loop": {
const predicate = entry.predicate;
if (!predicate || typeof predicate !== "object") throw new Error(`Loop step "${require_workflow_event_processor.getSingleStepEntryId(entry.step)}" cannot be stored: closure predicates do not round-trip. Use the declarative form ({ predicate: {...} }).`);
return {
type: "loop",
step: serializeSingleEntry(entry.step),
serializedCondition: entry.serializedCondition,
loopType: entry.loopType,
predicate
};
}
default: throw new Error(`Unknown step entry type: ${JSON.stringify(entry)}`);
}
}
function serializeSingleEntry(entry) {
if (entry.type === "agent") {
const options = pickSerializableStepOptions(entry.options, entry.id, "agent");
const outputSchema = extractStructuredOutputJsonSchema(entry.options, entry.id);
return {
type: "agent",
id: entry.id,
agentId: entry.agentId,
description: entry.agent?.description,
...outputSchema ? { outputSchema } : {},
...options ? { options } : {}
};
}
if (entry.type === "tool") {
const options = pickSerializableStepOptions(entry.options, entry.id, "tool");
return {
type: "tool",
id: entry.id,
toolId: entry.toolId,
description: entry.tool?.description,
...options ? { options } : {}
};
}
if (entry.type === "mapping") {
if (typeof entry.mapConfig === "function") throw new Error(`Mapping step "${entry.id}" cannot be stored: the function form does not round-trip. Use the declarative form (template / step / initData / value).`);
const serialized = {};
for (const [key, mapping] of Object.entries(entry.mapConfig)) {
const m = mapping;
if (m.fn !== void 0) throw new Error(`Mapping step "${entry.id}" key "${key}" cannot be stored: source is a function.`);
if (m.value !== void 0) serialized[key] = { value: m.value };
else if (m.requestContextPath) serialized[key] = { requestContextPath: m.requestContextPath };
else if (typeof m.template === "string") serialized[key] = { template: m.template };
else if (m.initData) serialized[key] = {
initData: m.initData?.id,
path: m.path
};
else if (m.step) serialized[key] = {
step: Array.isArray(m.step) ? m.step.map((s) => s?.id) : m.step?.id,
path: m.path
};
else serialized[key] = m;
}
return {
type: "mapping",
id: entry.id,
mapConfig: JSON.stringify(serialized)
};
}
if (entry.step?.component === "WORKFLOW") {
const nestedFlow = entry.step.serializedStepGraph ?? entry.step.serializedStepFlow;
return {
type: "workflow",
id: entry.step.id,
workflowId: entry.step.id,
...entry.step.description ? { description: entry.step.description } : {},
...nestedFlow ? { serializedStepFlow: nestedFlow } : {}
};
}
return {
type: "step",
step: stepDescriptor(entry.step)
};
}
function stepDescriptor(step) {
return {
id: step.id,
description: step.description,
metadata: step.metadata,
component: step.component,
canSuspend: Boolean(step.suspendSchema || step.resumeSchema)
};
}
/**
* Pull the JSON-safe fields (`retries`, `metadata`) out of the options bag
* carried on a live agent/tool `SingleStepEntry`. Closure-valued fields must
* hard-crash here rather than silently vanish through storage.
*/
function pickSerializableStepOptions(options, entryId, kind) {
if (!options || typeof options !== "object") return void 0;
for (const { key, hint } of [
{
key: "onFinish",
hint: "callback closure"
},
{
key: "onChunk",
hint: "callback closure"
},
{
key: "onError",
hint: "callback closure"
},
{
key: "onStepFinish",
hint: "callback closure"
},
{
key: "onAbort",
hint: "callback closure"
},
{
key: "toolChoice",
hint: "may be a function"
}
]) if (typeof options[key] === "function") throw new Error(`${kind === "agent" ? "Agent" : "Tool"} step "${entryId}" cannot be stored: option "${key}" is a ${hint} that does not round-trip. Remove it or move that logic outside the persisted workflow.`);
if (typeof options.scorers === "function") throw new Error(`${kind === "agent" ? "Agent" : "Tool"} step "${entryId}" cannot be stored: "scorers" is a function; only the static array form round-trips.`);
const out = {};
if (typeof options.retries === "number") out.retries = options.retries;
if (options.metadata && typeof options.metadata === "object") out.metadata = options.metadata;
return Object.keys(out).length > 0 ? out : void 0;
}
/**
* If the agent-step options carry `structuredOutput.schema`, that schema IS
* the step's output shape (see `createStepFromAgent`). Emit it as JSON Schema
* so rehydration can wire the same structured output back in.
*/
function extractStructuredOutputJsonSchema(options, entryId) {
const raw = options?.structuredOutput?.schema;
if (raw === void 0 || raw === null) return void 0;
try {
return (0, _mastra_schema_compat_schema.standardSchemaToJSONSchema)((0, _mastra_schema_compat_schema.toStandardSchema)(raw));
} catch (e) {
throw new Error(`Agent step "${entryId}" cannot be stored: structuredOutput.schema is not convertible to JSON Schema (${e.message}).`);
}
}
//#endregion
//#region src/workflows/state-reader.ts
const getStep = (state, stepId) => state.steps?.[stepId];
const getFirstStepResult = (step) => {
return Array.isArray(step) ? step.find((result) => result?.status === "suspended") ?? step[0] : step;
};
const getNestedSuspendPath = (step) => {
const path = getFirstStepResult(step)?.suspendPayload?.__workflow_meta?.path;
return Array.isArray(path) ? path.filter((part) => typeof part === "string") : [];
};
function getWorkflowStepOutput(state, stepId) {
const step = getStep(state, stepId);
return Array.isArray(step) ? step.map((result) => result?.output) : step?.output;
}
function getWorkflowStepPayload(state, stepId) {
const step = getStep(state, stepId);
return Array.isArray(step) ? step.map((result) => result?.payload) : step?.payload;
}
function getWorkflowResumeLabel(state, label) {
const resumeLabel = state.resumeLabels?.[label];
return resumeLabel ? { ...resumeLabel } : void 0;
}
function getWorkflowResumeLabels(state) {
return Object.entries(state.resumeLabels ?? {}).reduce((labels, [label, value]) => {
labels[label] = { ...value };
return labels;
}, {});
}
function getWorkflowSuspendedSteps(state) {
return Object.entries(state.suspendedPaths ?? {}).map(([stepId, executionPath]) => {
const step = getStep(state, stepId);
const firstStepResult = getFirstStepResult(step);
const nestedPath = getNestedSuspendPath(step);
const path = nestedPath.length > 0 ? nestedPath[0] === stepId ? nestedPath : [stepId, ...nestedPath] : [stepId];
const resumeLabels = Object.entries(state.resumeLabels ?? {}).reduce((labels, [label, value]) => {
if (value.stepId === stepId) labels[label] = { ...value };
return labels;
}, {});
return {
stepId,
path,
executionPath,
step,
payload: Array.isArray(step) ? step.map((result) => result?.payload) : step?.payload,
suspendPayload: firstStepResult?.suspendPayload,
suspendOutput: firstStepResult?.suspendOutput,
resumeLabels
};
});
}
function getWorkflowSuspendedStep(state) {
return getWorkflowSuspendedSteps(state)[0];
}
function createWorkflowStateReader(state) {
return {
getStatus: () => state.status,
getResult: () => state.result,
getError: () => state.error,
getStepOutput: (stepId) => getWorkflowStepOutput(state, stepId),
getStepPayload: (stepId) => getWorkflowStepPayload(state, stepId),
getSuspendedStep: () => getWorkflowSuspendedStep(state),
getSuspendedSteps: () => getWorkflowSuspendedSteps(state),
getResumeLabel: (label) => getWorkflowResumeLabel(state, label),
getResumeLabels: () => getWorkflowResumeLabels(state)
};
}
//#endregion
exports.DefaultExecutionEngine = require_agent.DefaultExecutionEngine;
exports.ExecutionEngine = require_agent.ExecutionEngine;
exports.Run = require_agent.Run;
exports.Scheduler = require_scheduler.Scheduler;
exports.Workflow = require_agent.Workflow;
exports.WorkflowScheduler = require_scheduler.WorkflowScheduler;
exports.analyzeMapConfig = require_validate.analyzeMapConfig;
exports.assertValidStoredWorkflow = require_validate.assertValidStoredWorkflow;
exports.cleanStepResult = require_workflow_event_processor.cleanStepResult;
exports.cloneStep = require_agent.cloneStep$1;
exports.cloneWorkflow = require_agent.cloneWorkflow;
exports.collectNestedWorkflowIds = require_validate.collectNestedWorkflowIds;
exports.computeNextFireAt = require_cron.computeNextFireAt;
exports.createDeprecationProxy = require_workflow_event_processor.createDeprecationProxy;
exports.createEventedWorkflow = require_agent.createEventedWorkflow;
exports.createMappingStep = require_agent.createMappingStep;
exports.createRestartExecutionParams = require_workflow_event_processor.createRestartExecutionParams;
exports.createStep = require_agent.createStep$1;
exports.createStepFromAgent = require_agent.createStepFromAgent;
exports.createStepFromTool = require_agent.createStepFromTool;
exports.createTimeTravelExecutionParams = require_workflow_event_processor.createTimeTravelExecutionParams;
exports.createWorkflow = require_agent.createWorkflow;
exports.createWorkflowStateReader = createWorkflowStateReader;
exports.derivePredicateLabel = require_agent.derivePredicateLabel;
exports.evaluatePredicate = require_agent.evaluatePredicate;
exports.forEachSingleStepEntry = require_validate.forEachSingleStepEntry;
exports.forEachSingleStepEntryWithPath = require_validate.forEachSingleStepEntryWithPath;
exports.getEntryId = require_workflow_event_processor.getEntryId;
exports.getEntryWorkflow = require_workflow_event_processor.getEntryWorkflow;
exports.getResumeLabelsByStepId = require_workflow_event_processor.getResumeLabelsByStepId;
exports.getSingleStepEntryId = require_workflow_event_processor.getSingleStepEntryId;
exports.getStepIds = require_workflow_event_processor.getStepIds;
exports.getStepResult = require_workflow_event_processor.getStepResult;
exports.getWorkflowResumeLabel = getWorkflowResumeLabel;
exports.getWorkflowResumeLabels = getWorkflowResumeLabels;
exports.getWorkflowStepOutput = getWorkflowStepOutput;
exports.getWorkflowStepPayload = getWorkflowStepPayload;
exports.getWorkflowSuspendedStep = getWorkflowSuspendedStep;
exports.getWorkflowSuspendedSteps = getWorkflowSuspendedSteps;
exports.hydrateSerializedStepErrors = require_workflow_event_processor.hydrateSerializedStepErrors;
exports.inferGraphSchemas = require_validate.inferGraphSchemas;
exports.isProcessor = require_agent.isProcessor;
exports.isSingleStepEntry = require_workflow_event_processor.isSingleStepEntry;
exports.jsonSchemaToZod = require_validate.jsonSchemaToZod;
exports.mapVariable = require_agent.mapVariable;
exports.parseMapConfig = require_validate.parseMapConfig;
exports.predicateSchema = require_agent.predicateSchema;
exports.predicateToCondition = require_agent.predicateToCondition;
exports.rehydrateWorkflow = require_validate.rehydrateWorkflow;
exports.resolveForeachConcurrency = require_workflow_event_processor.resolveForeachConcurrency;
exports.runCountDeprecationMessage = require_workflow_event_processor.runCountDeprecationMessage;
exports.schemaCompatibility = require_validate.schemaCompatibility;
exports.toJsonSchemaOrUndefined = require_validate.toJsonSchemaOrUndefined;
exports.toStorableGraph = toStorableGraph;
exports.validateCron = require_cron.validateCron;
exports.validateStepInput = require_workflow_event_processor.validateStepInput;
exports.validateStepRequestContext = require_workflow_event_processor.validateStepRequestContext;
exports.validateStepResumeData = require_workflow_event_processor.validateStepResumeData;
exports.validateStepStateData = require_workflow_event_processor.validateStepStateData;
exports.validateStepSuspendData = require_workflow_event_processor.validateStepSuspendData;
exports.validateStorableJsonSchema = require_validate.validateStorableJsonSchema;
exports.validateStoredWorkflow = require_validate.validateStoredWorkflow;
exports.validateWorkflowRefs = require_validate.validateWorkflowRefs;
exports.validateWorkflowSchemas = require_validate.validateWorkflowSchemas;
exports.validateWorkflowStructure = require_validate.validateWorkflowStructure;
exports.waitForSuspendedSnapshot = require_workflow_event_processor.waitForSuspendedSnapshot;
//# sourceMappingURL=index.cjs.map