UNPKG

@mastra/core

Version:

The core foundation of the Mastra framework, providing essential components and interfaces for building AI-powered applications.

4,272 lines • 127 kB
'use strict';

var chunkKXWR3FNX_cjs = require('./chunk-KXWR3FNX.cjs');
var chunkZMMZXEOL_cjs = require('./chunk-ZMMZXEOL.cjs');
var chunkUVRGQEMD_cjs = require('./chunk-UVRGQEMD.cjs');
var chunkFXAV2WYX_cjs = require('./chunk-FXAV2WYX.cjs');
var chunkRO52JMKQ_cjs = require('./chunk-RO52JMKQ.cjs');
var chunkO7IW545H_cjs = require('./chunk-O7IW545H.cjs');
var chunkLABUWBKX_cjs = require('./chunk-LABUWBKX.cjs');
var chunkST5RMVLG_cjs = require('./chunk-ST5RMVLG.cjs');
var chunkRWTSGWWL_cjs = require('./chunk-RWTSGWWL.cjs');
var api = require('@opentelemetry/api');
var zod = require('zod');
var radash = require('radash');
var crypto$1 = require('crypto');
var EventEmitter = require('events');
var sift = require('sift');
var xstate = require('xstate');

function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }

var EventEmitter__default = /*#__PURE__*/_interopDefault(EventEmitter);
var sift__default = /*#__PURE__*/_interopDefault(sift);

// src/workflows/step.ts
var Step = class {
  id;
  description;
  inputSchema;
  outputSchema;
  payload;
  execute;
  retryConfig;
  mastra;
  constructor({
    id,
    description,
    execute,
    payload,
    outputSchema,
    inputSchema,
    retryConfig
  }) {
    this.id = id;
    this.description = description ?? "";
    this.inputSchema = inputSchema;
    this.payload = payload;
    this.outputSchema = outputSchema;
    this.execute = execute;
    this.retryConfig = retryConfig;
  }
};

// src/workflows/types.ts
var WhenConditionReturnValue = /* @__PURE__ */(WhenConditionReturnValue2 => {
  WhenConditionReturnValue2["CONTINUE"] = "continue";
  WhenConditionReturnValue2["CONTINUE_FAILED"] = "continue_failed";
  WhenConditionReturnValue2["ABORT"] = "abort";
  WhenConditionReturnValue2["LIMBO"] = "limbo";
  return WhenConditionReturnValue2;
})(WhenConditionReturnValue || {});
function resoolveMaybePromise(value, cb) {
  if (value instanceof Promise) {
    return value.then(cb);
  }
  return cb(value);
}
var _Agent_decorators, _init, _a;
_Agent_decorators = [chunkUVRGQEMD_cjs.InstrumentClass({
  prefix: "agent",
  excludeMethods: ["hasOwnMemory", "getMemory", "__primitive", "__registerMastra", "__registerPrimitives", "__setTools", "__setLogger", "__setTelemetry", "log", "getModel", "getInstructions", "getTools", "getLLM"]
})];
exports.Agent = class Agent extends (_a = chunkRO52JMKQ_cjs.MastraBase) {
  id;
  name;
  #instructions;
  model;
  #mastra;
  #memory;
  #defaultGenerateOptions;
  #defaultStreamOptions;
  #tools;
  /** @deprecated This property is deprecated. Use evals instead. */
  metrics;
  evals;
  #voice;
  constructor(config) {
    super({
      component: chunkO7IW545H_cjs.RegisteredLogger.AGENT
    });
    this.name = config.name;
    this.id = config.name;
    this.#instructions = config.instructions;
    if (!config.model) {
      throw new Error(`LanguageModel is required to create an Agent. Please provide the 'model'.`);
    }
    this.model = config.model;
    this.#defaultGenerateOptions = config.defaultGenerateOptions || {};
    this.#defaultStreamOptions = config.defaultStreamOptions || {};
    this.#tools = config.tools || {};
    this.metrics = {};
    this.evals = {};
    if (config.mastra) {
      this.__registerMastra(config.mastra);
      this.__registerPrimitives({
        telemetry: config.mastra.getTelemetry(),
        logger: config.mastra.getLogger()
      });
    }
    if (config.metrics) {
      this.logger.warn("The metrics property is deprecated. Please use evals instead to add evaluation metrics.");
      this.metrics = config.metrics;
      this.evals = config.metrics;
    }
    if (config.evals) {
      this.evals = config.evals;
    }
    if (config.memory) {
      this.#memory = config.memory;
    }
    if (config.voice) {
      this.#voice = config.voice;
      if (typeof config.tools !== "function") {
        this.#voice?.addTools(this.tools);
      }
      if (typeof config.instructions === "string") {
        this.#voice?.addInstructions(config.instructions);
      }
    } else {
      this.#voice = new chunkKXWR3FNX_cjs.DefaultVoice();
    }
  }
  hasOwnMemory() {
    return Boolean(this.#memory);
  }
  getMemory() {
    return this.#memory ?? this.#mastra?.memory;
  }
  get voice() {
    if (typeof this.#instructions === "function") {
      throw new Error("Voice is not compatible when instructions are a function. Please use getVoice() instead.");
    }
    return this.#voice;
  }
  async getVoice({
    runtimeContext
  } = {}) {
    if (this.#voice) {
      const voice = this.#voice;
      voice?.addTools(await this.getTools({
        runtimeContext
      }));
      voice?.addInstructions(await this.getInstructions({
        runtimeContext
      }));
      return voice;
    } else {
      return new chunkKXWR3FNX_cjs.DefaultVoice();
    }
  }
  get instructions() {
    this.logger.warn("The instructions property is deprecated. Please use getInstructions() instead.");
    if (typeof this.#instructions === "function") {
      throw new Error("Instructions are not compatible when instructions are a function. Please use getInstructions() instead.");
    }
    return this.#instructions;
  }
  getInstructions({
    runtimeContext = new chunkLABUWBKX_cjs.RuntimeContext()
  } = {}) {
    if (typeof this.#instructions === "string") {
      return this.#instructions;
    }
    const result = this.#instructions({
      runtimeContext
    });
    return resoolveMaybePromise(result, instructions => {
      if (!instructions) {
        this.logger.error(`[Agent:${this.name}] - Function-based instructions returned empty value`);
        throw new Error("Instructions are required to use an Agent. The function-based instructions returned an empty value.");
      }
      return instructions;
    });
  }
  get tools() {
    this.logger.warn("The tools property is deprecated. Please use getTools() instead.");
    if (typeof this.#tools === "function") {
      throw new Error("Tools are not compatible when tools are a function. Please use getTools() instead.");
    }
    return chunkFXAV2WYX_cjs.ensureToolProperties(this.#tools);
  }
  getTools({
    runtimeContext = new chunkLABUWBKX_cjs.RuntimeContext()
  } = {}) {
    if (typeof this.#tools !== "function") {
      return chunkFXAV2WYX_cjs.ensureToolProperties(this.#tools);
    }
    const result = this.#tools({
      runtimeContext
    });
    return resoolveMaybePromise(result, tools => {
      if (!tools) {
        this.logger.error(`[Agent:${this.name}] - Function-based tools returned empty value`);
        throw new Error("Tools are required when using a function to provide them. The function returned an empty value.");
      }
      return chunkFXAV2WYX_cjs.ensureToolProperties(tools);
    });
  }
  get llm() {
    this.logger.warn("The llm property is deprecated. Please use getLLM() instead.");
    if (typeof this.model === "function") {
      throw new Error("LLM is not compatible when model is a function. Please use getLLM() instead.");
    }
    return this.getLLM();
  }
  /**
   * Gets or creates an LLM instance based on the current model
   * @param options Options for getting the LLM
   * @returns A promise that resolves to the LLM instance
   */
  getLLM({
    runtimeContext = new chunkLABUWBKX_cjs.RuntimeContext()
  } = {}) {
    const model = this.getModel({
      runtimeContext
    });
    return resoolveMaybePromise(model, model2 => {
      const llm = new chunkZMMZXEOL_cjs.MastraLLM({
        model: model2,
        mastra: this.#mastra
      });
      if (this.#primitives) {
        llm.__registerPrimitives(this.#primitives);
      }
      if (this.#mastra) {
        llm.__registerMastra(this.#mastra);
      }
      return llm;
    });
  }
  /**
   * Gets the model, resolving it if it's a function
   * @param options Options for getting the model
   * @returns A promise that resolves to the model
   */
  getModel({
    runtimeContext = new chunkLABUWBKX_cjs.RuntimeContext()
  } = {}) {
    if (typeof this.model !== "function") {
      if (!this.model) {
        this.logger.error(`[Agent:${this.name}] - No model provided`);
        throw new Error("Model is required to use an Agent.");
      }
      return this.model;
    }
    const result = this.model({
      runtimeContext
    });
    return resoolveMaybePromise(result, model => {
      if (!model) {
        this.logger.error(`[Agent:${this.name}] - Function-based model returned empty value`);
        throw new Error("Model is required to use an Agent. The function-based model returned an empty value.");
      }
      return model;
    });
  }
  __updateInstructions(newInstructions) {
    this.#instructions = newInstructions;
    this.logger.debug(`[Agents:${this.name}] Instructions updated.`, {
      model: this.model,
      name: this.name
    });
  }
  #primitives;
  __registerPrimitives(p) {
    if (p.telemetry) {
      this.__setTelemetry(p.telemetry);
    }
    if (p.logger) {
      this.__setLogger(p.logger);
    }
    this.#primitives = p;
    this.logger.debug(`[Agents:${this.name}] initialized.`, {
      model: this.model,
      name: this.name
    });
  }
  __registerMastra(mastra) {
    this.#mastra = mastra;
  }
  /**
   * Set the concrete tools for the agent
   * @param tools
   */
  __setTools(tools) {
    this.#tools = tools;
    this.logger.debug(`[Agents:${this.name}] Tools set for agent ${this.name}`, {
      model: this.model,
      name: this.name
    });
  }
  async generateTitleFromUserMessage({
    message,
    runtimeContext = new chunkLABUWBKX_cjs.RuntimeContext()
  }) {
    const llm = await this.getLLM({
      runtimeContext
    });
    const {
      text
    } = await llm.__text({
      runtimeContext,
      messages: [{
        role: "system",
        content: `

    - you will generate a short title based on the first message a user begins a conversation with
    - ensure it is not more than 80 characters long
    - the title should be a summary of the user's message
    - do not use quotes or colons
    - the entire text you return will be used as the title`
      }, {
        role: "user",
        content: JSON.stringify(message)
      }]
    });
    const cleanedText = text.replace(/<think>[\s\S]*?<\/think>/g, "").trim();
    return cleanedText;
  }
  getMostRecentUserMessage(messages) {
    const userMessages = messages.filter(message => message.role === "user");
    return userMessages.at(-1);
  }
  async genTitle(userMessage) {
    let title = `New Thread ${(/* @__PURE__ */new Date()).toISOString()}`;
    try {
      if (userMessage) {
        title = await this.generateTitleFromUserMessage({
          message: userMessage
        });
      }
    } catch (e) {
      console.error("Error generating title:", e);
    }
    return title;
  }
  async fetchMemory({
    threadId,
    thread: passedThread,
    memoryConfig,
    resourceId,
    userMessages,
    systemMessage,
    runId
  }) {
    const memory = this.getMemory();
    if (memory) {
      const thread = passedThread ?? (await memory.getThreadById({
        threadId
      }));
      if (!thread) {
        return {
          threadId: threadId || "",
          messages: userMessages
        };
      }
      const newMessages = chunkFXAV2WYX_cjs.ensureAllMessagesAreCoreMessages(userMessages);
      const now = Date.now();
      const messages = newMessages.map((u, index) => {
        return {
          id: this.getMemory()?.generateId(),
          createdAt: new Date(now + index),
          threadId,
          ...u,
          content: u.content,
          role: u.role,
          type: "text"
        };
      });
      const [memoryMessages, memorySystemMessage] = threadId && memory ? await Promise.all([memory.rememberMessages({
        threadId,
        resourceId,
        config: memoryConfig,
        systemMessage,
        vectorMessageSearch: messages.slice(-1).map(m => {
          if (typeof m === `string`) {
            return m;
          }
          return m?.content || ``;
        }).join(`
`)
      }).then(r => r.messages), memory.getSystemMessage({
        threadId,
        memoryConfig
      })]) : [[], null];
      this.logger.debug("Saved messages to memory", {
        threadId,
        runId
      });
      const processedMessages = memory.processMessages({
        messages: this.sanitizeResponseMessages(memoryMessages),
        newMessages,
        systemMessage: typeof systemMessage?.content === `string` ? systemMessage.content : void 0,
        memorySystemMessage: memorySystemMessage ?? ``
      });
      return {
        threadId: thread.id,
        messages: [memorySystemMessage ? {
          role: "system",
          content: memorySystemMessage
        } : null, ...processedMessages, ...newMessages].filter(message => Boolean(message))
      };
    }
    return {
      threadId: threadId || "",
      messages: userMessages
    };
  }
  getResponseMessages({
    messages,
    threadId,
    resourceId,
    now
  }) {
    if (!messages) return [];
    const messagesArray = Array.isArray(messages) ? messages : [messages];
    return this.sanitizeResponseMessages(messagesArray).map((message, index) => {
      const messageId = crypto$1.randomUUID();
      let toolCallIds;
      let toolCallArgs;
      let toolNames;
      let type = "text";
      if (message.role === "tool") {
        toolCallIds = message.content.map(content => content.toolCallId);
        type = "tool-result";
      }
      if (message.role === "assistant") {
        const assistantContent = message.content;
        const assistantToolCalls = assistantContent.map(content => {
          if (content.type === "tool-call") {
            return {
              toolCallId: content.toolCallId,
              toolArgs: content.args,
              toolName: content.toolName
            };
          }
          return void 0;
        })?.filter(Boolean);
        toolCallIds = assistantToolCalls?.map(toolCall => toolCall.toolCallId);
        toolCallArgs = assistantToolCalls?.map(toolCall => toolCall.toolArgs);
        toolNames = assistantToolCalls?.map(toolCall => toolCall.toolName);
        type = assistantContent?.[0]?.type;
      }
      return {
        id: messageId,
        threadId,
        resourceId,
        role: message.role,
        content: message.content,
        createdAt: new Date(now + index),
        // use Date.now() + index to make sure every message is atleast one millisecond apart
        toolCallIds: toolCallIds?.length ? toolCallIds : void 0,
        toolCallArgs: toolCallArgs?.length ? toolCallArgs : void 0,
        toolNames: toolNames?.length ? toolNames : void 0,
        type
      };
    });
  }
  sanitizeResponseMessages(messages) {
    let toolResultIds = [];
    let toolCallIds = [];
    for (const message of messages) {
      if (!Array.isArray(message.content)) continue;
      if (message.role === "tool") {
        for (const content of message.content) {
          if (content.type === "tool-result") {
            toolResultIds.push(content.toolCallId);
          }
        }
      } else if (message.role === "assistant" || message.role === "user") {
        for (const content of message.content) {
          if (typeof content !== `string`) {
            if (content.type === `tool-call`) {
              toolCallIds.push(content.toolCallId);
            }
          }
        }
      }
    }
    const messagesBySanitizedContent = messages.map(message => {
      if (message.role !== "assistant" && message.role !== `tool` && message.role !== `user`) return message;
      if (!Array.isArray(message.content)) {
        return message;
      }
      const sanitizedContent = message.content.filter(content => {
        if (content.type === `tool-call`) {
          return toolResultIds.includes(content.toolCallId);
        }
        if (content.type === `text`) {
          return content.text.trim() !== ``;
        }
        if (content.type === `tool-result`) {
          return toolCallIds.includes(content.toolCallId);
        }
        return true;
      });
      return {
        ...message,
        content: sanitizedContent
      };
    });
    return messagesBySanitizedContent.filter(message => {
      if (typeof message.content === `string`) {
        if (message.role === "assistant") {
          return true;
        }
        return message.content !== "";
      }
      if (Array.isArray(message.content)) {
        return message.content.length && message.content.every(c => {
          if (c.type === `text`) {
            return c.text && c.text !== "";
          }
          return true;
        });
      }
      return true;
    });
  }
  async convertTools({
    toolsets,
    clientTools,
    threadId,
    resourceId,
    runId,
    runtimeContext
  }) {
    this.logger.debug(`[Agents:${this.name}] - Assigning tools`, {
      runId,
      threadId,
      resourceId
    });
    const memory = this.getMemory();
    const memoryTools = memory?.getTools?.();
    let mastraProxy = void 0;
    const logger = this.logger;
    if (this.#mastra) {
      mastraProxy = chunkFXAV2WYX_cjs.createMastraProxy({
        mastra: this.#mastra,
        logger
      });
    }
    const tools = await this.getTools({
      runtimeContext
    });
    const convertedEntries = await Promise.all(Object.entries(tools || {}).map(async ([k, tool]) => {
      if (tool) {
        const options = {
          name: k,
          runId,
          threadId,
          resourceId,
          logger: this.logger,
          mastra: mastraProxy,
          memory,
          agentName: this.name,
          runtimeContext,
          model: typeof this.model === "function" ? await this.getModel({
            runtimeContext
          }) : this.model
        };
        return [k, chunkFXAV2WYX_cjs.makeCoreTool(tool, options)];
      }
      return void 0;
    }));
    const converted = Object.fromEntries(convertedEntries.filter(entry => Boolean(entry)));
    let convertedMemoryTools = {};
    if (memoryTools) {
      const memoryToolEntries = await Promise.all(Object.entries(memoryTools).map(async ([k, tool]) => {
        return [k, {
          description: tool.description,
          parameters: tool.parameters,
          execute: typeof tool?.execute === "function" ? async (args, options) => {
            try {
              this.logger.debug(`[Agent:${this.name}] - Executing memory tool ${k}`, {
                name: k,
                description: tool.description,
                args,
                runId,
                threadId,
                resourceId
              });
              return tool?.execute?.({
                context: args,
                mastra: mastraProxy,
                memory,
                runId,
                threadId,
                resourceId,
                logger: this.logger,
                agentName: this.name,
                runtimeContext
              }, options) ?? void 0;
            } catch (err) {
              this.logger.error(`[Agent:${this.name}] - Failed memory tool execution`, {
                error: err,
                runId,
                threadId,
                resourceId
              });
              throw err;
            }
          } : void 0
        }];
      }));
      convertedMemoryTools = Object.fromEntries(memoryToolEntries.filter(entry => Boolean(entry)));
    }
    const toolsFromToolsetsConverted = {
      ...converted,
      ...convertedMemoryTools
    };
    const toolsFromToolsets = Object.values(toolsets || {});
    if (toolsFromToolsets.length > 0) {
      this.logger.debug(`[Agent:${this.name}] - Adding tools from toolsets ${Object.keys(toolsets || {}).join(", ")}`, {
        runId
      });
      for (const toolset of toolsFromToolsets) {
        for (const [toolName, tool] of Object.entries(toolset)) {
          const toolObj = tool;
          const options = {
            name: toolName,
            runId,
            threadId,
            resourceId,
            logger: this.logger,
            mastra: mastraProxy,
            memory,
            agentName: this.name,
            runtimeContext,
            model: typeof this.model === "function" ? await this.getModel({
              runtimeContext
            }) : this.model
          };
          const convertedToCoreTool = chunkFXAV2WYX_cjs.makeCoreTool(toolObj, options, "toolset");
          toolsFromToolsetsConverted[toolName] = convertedToCoreTool;
        }
      }
    }
    const clientToolsForInput = Object.entries(clientTools || {});
    if (clientToolsForInput.length > 0) {
      this.logger.debug(`[Agent:${this.name}] - Adding client tools ${Object.keys(clientTools || {}).join(", ")}`, {
        runId
      });
      for (const [toolName, tool] of clientToolsForInput) {
        const {
          execute,
          ...rest
        } = tool;
        const options = {
          name: toolName,
          runId,
          threadId,
          resourceId,
          logger: this.logger,
          mastra: mastraProxy,
          memory,
          agentName: this.name,
          runtimeContext,
          model: typeof this.model === "function" ? await this.getModel({
            runtimeContext
          }) : this.model
        };
        const convertedToCoreTool = chunkFXAV2WYX_cjs.makeCoreTool(rest, options, "client-tool");
        toolsFromToolsetsConverted[toolName] = convertedToCoreTool;
      }
    }
    return toolsFromToolsetsConverted;
  }
  async preExecute({
    resourceId,
    runId,
    threadId,
    thread,
    memoryConfig,
    messages,
    systemMessage
  }) {
    let coreMessages = [];
    let threadIdToUse = threadId;
    this.logger.debug(`Saving user messages in memory for agent ${this.name}`, {
      runId
    });
    const saveMessageResponse = await this.fetchMemory({
      threadId,
      thread,
      resourceId,
      userMessages: messages,
      memoryConfig,
      systemMessage
    });
    coreMessages = saveMessageResponse.messages;
    threadIdToUse = saveMessageResponse.threadId;
    return {
      coreMessages,
      threadIdToUse
    };
  }
  __primitive({
    instructions,
    messages,
    context,
    threadId,
    memoryConfig,
    resourceId,
    runId,
    toolsets,
    clientTools,
    runtimeContext
  }) {
    return {
      before: async () => {
        if (process.env.NODE_ENV !== "test") {
          this.logger.debug(`[Agents:${this.name}] - Starting generation`, {
            runId
          });
        }
        const systemMessage = {
          role: "system",
          content: instructions || `${this.instructions}.`
        };
        let coreMessages = messages;
        let threadIdToUse = threadId;
        let thread;
        const memory = this.getMemory();
        if (threadId && memory && !resourceId) {
          throw new Error(`A resourceId must be provided when passing a threadId and using Memory. Saw threadId ${threadId} but resourceId is ${resourceId}`);
        }
        if (memory && resourceId) {
          this.logger.debug(`[Agent:${this.name}] - Memory persistence enabled: store=${this.getMemory()?.constructor.name}, resourceId=${resourceId}`, {
            runId,
            resourceId,
            threadId: threadIdToUse,
            memoryStore: this.getMemory()?.constructor.name
          });
          thread = threadIdToUse ? await memory.getThreadById({
            threadId: threadIdToUse
          }) : void 0;
          if (!thread) {
            thread = await memory.createThread({
              threadId: threadIdToUse,
              resourceId,
              memoryConfig
            });
          }
          threadIdToUse = thread.id;
          const preExecuteResult = await this.preExecute({
            resourceId,
            runId,
            threadId: threadIdToUse,
            thread,
            memoryConfig,
            messages,
            systemMessage
          });
          coreMessages = preExecuteResult.coreMessages;
          threadIdToUse = preExecuteResult.threadIdToUse;
        }
        let convertedTools;
        const reasons = [];
        if (toolsets && Object.keys(toolsets || {}).length > 0) {
          reasons.push(`toolsets present (${Object.keys(toolsets || {}).length} tools)`);
        }
        if (this.getMemory() && resourceId) {
          reasons.push("memory and resourceId available");
        }
        this.logger.debug(`[Agent:${this.name}] - Enhancing tools: ${reasons.join(", ")}`, {
          runId,
          toolsets: toolsets ? Object.keys(toolsets) : void 0,
          clientTools: clientTools ? Object.keys(clientTools) : void 0,
          hasMemory: !!this.getMemory(),
          hasResourceId: !!resourceId
        });
        convertedTools = await this.convertTools({
          toolsets,
          clientTools,
          threadId: threadIdToUse,
          resourceId,
          runId,
          runtimeContext
        });
        const messageObjects = [systemMessage, ...(context || []), ...coreMessages];
        return {
          messageObjects,
          convertedTools,
          threadId: threadIdToUse,
          thread
        };
      },
      after: async ({
        result,
        thread: threadAfter,
        threadId: threadId2,
        memoryConfig: memoryConfig2,
        outputText,
        runId: runId2
      }) => {
        const resToLog = {
          text: result?.text,
          object: result?.object,
          toolResults: result?.toolResults,
          toolCalls: result?.toolCalls,
          usage: result?.usage,
          steps: result?.steps?.map(s => {
            return {
              stepType: s?.stepType,
              text: result?.text,
              object: result?.object,
              toolResults: result?.toolResults,
              toolCalls: result?.toolCalls,
              usage: result?.usage
            };
          })
        };
        this.logger.debug(`[Agent:${this.name}] - Post processing LLM response`, {
          runId: runId2,
          result: resToLog,
          threadId: threadId2
        });
        const memory = this.getMemory();
        const thread = threadAfter || (threadId2 ? await memory?.getThreadById({
          threadId: threadId2
        }) : void 0);
        if (memory && resourceId && thread) {
          try {
            const userMessage = this.getMostRecentUserMessage(messages);
            const now = Date.now();
            const threadMessages = this.sanitizeResponseMessages(chunkFXAV2WYX_cjs.ensureAllMessagesAreCoreMessages(messages)).map((u, index) => {
              return {
                id: this.getMemory()?.generateId(),
                createdAt: new Date(now + index),
                threadId: thread.id,
                resourceId,
                ...u,
                content: u.content,
                role: u.role,
                type: "text"
              };
            });
            const dateResponseMessagesFrom = (threadMessages.at(-1)?.createdAt?.getTime?.() || Date.now()) + 1;
            void (async () => {
              if (!thread.title?.startsWith("New Thread")) {
                return;
              }
              const config = memory.getMergedThreadConfig(memoryConfig2);
              const title = config?.threads?.generateTitle ? await this.genTitle(userMessage) : void 0;
              if (!title) {
                return;
              }
              return memory.createThread({
                threadId: thread.id,
                resourceId,
                memoryConfig: memoryConfig2,
                title
              });
            })();
            let responseMessages = result.response.messages;
            if (!responseMessages && result.object) {
              responseMessages = [{
                role: "assistant",
                content: [{
                  type: "text",
                  text: outputText
                }]
              }];
            }
            await memory.saveMessages({
              messages: [...threadMessages, ...this.getResponseMessages({
                threadId: threadId2,
                resourceId,
                messages: responseMessages,
                now: dateResponseMessagesFrom
              })],
              memoryConfig: memoryConfig2
            });
          } catch (e) {
            const message = e instanceof Error ? e.message : JSON.stringify(e);
            this.logger.error("Error saving response", {
              error: message,
              runId: runId2,
              result: resToLog,
              threadId: threadId2
            });
          }
        }
        if (Object.keys(this.evals || {}).length > 0) {
          const input = messages.map(message => message.content).join("\n");
          const runIdToUse = runId2 || crypto.randomUUID();
          for (const metric of Object.values(this.evals || {})) {
            chunkST5RMVLG_cjs.executeHook("onGeneration" /* ON_GENERATION */, {
              input,
              output: outputText,
              runId: runIdToUse,
              metric,
              agentName: this.name,
              instructions: instructions || this.instructions
            });
          }
        }
      }
    };
  }
  async generate(messages, generateOptions = {}) {
    const {
      instructions,
      context,
      threadId: threadIdInFn,
      memoryOptions,
      resourceId,
      maxSteps,
      onStepFinish,
      runId,
      output,
      toolsets,
      clientTools,
      temperature,
      toolChoice = "auto",
      experimental_output,
      telemetry,
      runtimeContext = new chunkLABUWBKX_cjs.RuntimeContext(),
      ...rest
    } = Object.assign({}, this.#defaultGenerateOptions, generateOptions);
    let messagesToUse = [];
    if (typeof messages === `string`) {
      messagesToUse = [{
        role: "user",
        content: messages
      }];
    } else if (Array.isArray(messages)) {
      messagesToUse = messages.map(message => {
        if (typeof message === `string`) {
          return {
            role: "user",
            content: message
          };
        }
        return message;
      });
    } else {
      messagesToUse = [messages];
    }
    const runIdToUse = runId || crypto$1.randomUUID();
    const instructionsToUse = instructions || (await this.getInstructions({
      runtimeContext
    }));
    const llm = await this.getLLM({
      runtimeContext
    });
    const {
      before,
      after
    } = this.__primitive({
      instructions: instructionsToUse,
      messages: messagesToUse,
      context,
      threadId: threadIdInFn,
      memoryConfig: memoryOptions,
      resourceId,
      runId: runIdToUse,
      toolsets,
      clientTools,
      runtimeContext
    });
    const {
      threadId,
      thread,
      messageObjects,
      convertedTools
    } = await before();
    if (!output && experimental_output) {
      const result2 = await llm.__text({
        messages: messageObjects,
        tools: convertedTools,
        onStepFinish: result3 => {
          void onStepFinish?.(result3);
        },
        maxSteps,
        runId: runIdToUse,
        temperature,
        toolChoice: toolChoice || "auto",
        experimental_output,
        threadId,
        resourceId,
        memory: this.getMemory(),
        runtimeContext,
        ...rest
      });
      const outputText2 = result2.text;
      await after({
        result: result2,
        threadId,
        thread,
        memoryConfig: memoryOptions,
        outputText: outputText2,
        runId: runIdToUse
      });
      const newResult = result2;
      newResult.object = result2.experimental_output;
      return newResult;
    }
    if (!output) {
      const result2 = await llm.__text({
        messages: messageObjects,
        tools: convertedTools,
        onStepFinish: result3 => {
          void onStepFinish?.(result3);
        },
        maxSteps,
        runId: runIdToUse,
        temperature,
        toolChoice,
        telemetry,
        threadId,
        resourceId,
        memory: this.getMemory(),
        runtimeContext,
        ...rest
      });
      const outputText2 = result2.text;
      await after({
        result: result2,
        thread,
        threadId,
        memoryConfig: memoryOptions,
        outputText: outputText2,
        runId: runIdToUse
      });
      return result2;
    }
    const result = await llm.__textObject({
      messages: messageObjects,
      tools: convertedTools,
      structuredOutput: output,
      onStepFinish: result2 => {
        void onStepFinish?.(result2);
      },
      maxSteps,
      runId: runIdToUse,
      temperature,
      toolChoice,
      telemetry,
      memory: this.getMemory(),
      runtimeContext,
      ...rest
    });
    const outputText = JSON.stringify(result.object);
    await after({
      result,
      thread,
      threadId,
      memoryConfig: memoryOptions,
      outputText,
      runId: runIdToUse
    });
    return result;
  }
  async stream(messages, streamOptions = {}) {
    const {
      instructions,
      context,
      threadId: threadIdInFn,
      memoryOptions,
      resourceId,
      maxSteps,
      onFinish,
      onStepFinish,
      runId,
      toolsets,
      clientTools,
      output,
      temperature,
      toolChoice = "auto",
      experimental_output,
      telemetry,
      runtimeContext = new chunkLABUWBKX_cjs.RuntimeContext(),
      ...rest
    } = Object.assign({}, this.#defaultStreamOptions, streamOptions);
    const runIdToUse = runId || crypto$1.randomUUID();
    const instructionsToUse = instructions || (await this.getInstructions({
      runtimeContext
    }));
    const llm = await this.getLLM({
      runtimeContext
    });
    let messagesToUse = [];
    if (typeof messages === `string`) {
      messagesToUse = [{
        role: "user",
        content: messages
      }];
    } else {
      messagesToUse = messages.map(message => {
        if (typeof message === `string`) {
          return {
            role: "user",
            content: message
          };
        }
        return message;
      });
    }
    const {
      before,
      after
    } = this.__primitive({
      instructions: instructionsToUse,
      messages: messagesToUse,
      context,
      threadId: threadIdInFn,
      memoryConfig: memoryOptions,
      resourceId,
      runId: runIdToUse,
      toolsets,
      clientTools,
      runtimeContext
    });
    const {
      threadId,
      thread,
      messageObjects,
      convertedTools
    } = await before();
    if (!output && experimental_output) {
      this.logger.debug(`Starting agent ${this.name} llm stream call`, {
        runId
      });
      const streamResult = await llm.__stream({
        messages: messageObjects,
        temperature,
        tools: convertedTools,
        onStepFinish: result => {
          void onStepFinish?.(result);
        },
        onFinish: async result => {
          try {
            const outputText = result.text;
            await after({
              result,
              thread,
              threadId,
              memoryConfig: memoryOptions,
              outputText,
              runId: runIdToUse
            });
          } catch (e) {
            this.logger.error("Error saving memory on finish", {
              error: e,
              runId
            });
          }
          void onFinish?.(result);
        },
        maxSteps,
        runId: runIdToUse,
        toolChoice,
        experimental_output,
        memory: this.getMemory(),
        runtimeContext,
        ...rest
      });
      const newStreamResult = streamResult;
      newStreamResult.partialObjectStream = streamResult.experimental_partialOutputStream;
      return newStreamResult;
    } else if (!output) {
      this.logger.debug(`Starting agent ${this.name} llm stream call`, {
        runId
      });
      return llm.__stream({
        messages: messageObjects,
        temperature,
        tools: convertedTools,
        onStepFinish: result => {
          void onStepFinish?.(result);
        },
        onFinish: async result => {
          try {
            const outputText = result.text;
            await after({
              result,
              thread,
              threadId,
              memoryConfig: memoryOptions,
              outputText,
              runId: runIdToUse
            });
          } catch (e) {
            this.logger.error("Error saving memory on finish", {
              error: e,
              runId
            });
          }
          void onFinish?.(result);
        },
        maxSteps,
        runId: runIdToUse,
        toolChoice,
        telemetry,
        memory: this.getMemory(),
        runtimeContext,
        ...rest
      });
    }
    this.logger.debug(`Starting agent ${this.name} llm streamObject call`, {
      runId
    });
    return llm.__streamObject({
      messages: messageObjects,
      tools: convertedTools,
      temperature,
      structuredOutput: output,
      onStepFinish: result => {
        void onStepFinish?.(result);
      },
      onFinish: async result => {
        try {
          const outputText = JSON.stringify(result.object);
          await after({
            result,
            thread,
            threadId,
            memoryConfig: memoryOptions,
            outputText,
            runId: runIdToUse
          });
        } catch (e) {
          this.logger.error("Error saving memory on finish", {
            error: e,
            runId
          });
        }
        void onFinish?.(result);
      },
      runId: runIdToUse,
      toolChoice,
      telemetry,
      memory: this.getMemory(),
      runtimeContext,
      ...rest
    });
  }
  /**
   * Convert text to speech using the configured voice provider
   * @param input Text or text stream to convert to speech
   * @param options Speech options including speaker and provider-specific options
   * @returns Audio stream
   * @deprecated Use agent.voice.speak() instead
   */
  async speak(input, options) {
    if (!this.voice) {
      throw new Error("No voice provider configured");
    }
    this.logger.warn("Warning: agent.speak() is deprecated. Please use agent.voice.speak() instead.");
    try {
      return this.voice.speak(input, options);
    } catch (e) {
      this.logger.error("Error during agent speak", {
        error: e
      });
      throw e;
    }
  }
  /**
   * Convert speech to text using the configured voice provider
   * @param audioStream Audio stream to transcribe
   * @param options Provider-specific transcription options
   * @returns Text or text stream
   * @deprecated Use agent.voice.listen() instead
   */
  async listen(audioStream, options) {
    if (!this.voice) {
      throw new Error("No voice provider configured");
    }
    this.logger.warn("Warning: agent.listen() is deprecated. Please use agent.voice.listen() instead");
    try {
      return this.voice.listen(audioStream, options);
    } catch (e) {
      this.logger.error("Error during agent listen", {
        error: e
      });
      throw e;
    }
  }
  /**
   * Get a list of available speakers from the configured voice provider
   * @throws {Error} If no voice provider is configured
   * @returns {Promise<Array<{voiceId: string}>>} List of available speakers
   * @deprecated Use agent.voice.getSpeakers() instead
   */
  async getSpeakers() {
    if (!this.voice) {
      throw new Error("No voice provider configured");
    }
    this.logger.warn("Warning: agent.getSpeakers() is deprecated. Please use agent.voice.getSpeakers() instead.");
    try {
      return await this.voice.getSpeakers();
    } catch (e) {
      this.logger.error("Error during agent getSpeakers", {
        error: e
      });
      throw e;
    }
  }
  toStep() {
    const x = agentToStep(this);
    return new Step(x);
  }
};
exports.Agent = /*@__PURE__*/(_ => {
  _init = chunkRWTSGWWL_cjs.__decoratorStart(_a);
  exports.Agent = chunkRWTSGWWL_cjs.__decorateElement(_init, 0, "Agent", _Agent_decorators, exports.Agent);
  chunkRWTSGWWL_cjs.__runInitializers(_init, 1, exports.Agent);

  // src/workflows/utils.ts
  return exports.Agent;
})();
// src/workflows/utils.ts
function isErrorEvent(stateEvent) {
  return stateEvent.type.startsWith("xstate.error.actor.");
}
function isTransitionEvent(stateEvent) {
  return stateEvent.type.startsWith("xstate.done.actor.");
}
function isVariableReference(value) {
  return typeof value === "object" && "step" in value && "path" in value;
}
function getStepResult(result) {
  if (result?.status === "success") return result.output;
  return void 0;
}
function getSuspendedPaths({
  value,
  path,
  suspendedPaths
}) {
  if (typeof value === "string") {
    if (value === "suspended") {
      suspendedPaths.add(path);
    }
  } else {
    Object.keys(value).forEach(key => getSuspendedPaths({
      value: value[key],
      path: path ? `${path}.${key}` : key,
      suspendedPaths
    }));
  }
}
function isFinalState(status) {
  return ["completed", "failed"].includes(status);
}
function isLimboState(status) {
  return status === "limbo";
}
function recursivelyCheckForFinalState({
  value,
  suspendedPaths,
  path
}) {
  if (typeof value === "string") {
    return isFinalState(value) || isLimboState(value) || suspendedPaths.has(path);
  }
  return Object.keys(value).every(key => recursivelyCheckForFinalState({
    value: value[key],
    suspendedPaths,
    path: path ? `${path}.${key}` : key
  }));
}
function getActivePathsAndStatus(value) {
  const paths = [];
  const traverse = (current, path = []) => {
    for (const [key, value2] of Object.entries(current)) {
      const currentPath = [...path, key];
      if (typeof value2 === "string") {
        paths.push({
          stepPath: currentPath,
          stepId: key,
          status: value2
        });
      } else if (typeof value2 === "object" && value2 !== null) {
        traverse(value2, currentPath);
      }
    }
  };
  traverse(value);
  return paths;
}
function mergeChildValue(startStepId, parent, child) {
  const traverse = current => {
    const obj = {};
    for (const [key, value] of Object.entries(current)) {
      if (key === startStepId) {
        obj[key] = {
          ...child
        };
      } else if (typeof value === "string") {
        obj[key] = value;
      } else if (typeof value === "object" && value !== null) {
        obj[key] = traverse(value);
      }
    }
    return obj;
  };
  return traverse(parent);
}
var updateStepInHierarchy = (value, targetStepId) => {
  const result = {};
  for (const key of Object.keys(value)) {
    const currentValue = value[key];
    if (key === targetStepId) {
      result[key] = "pending";
    } else if (typeof currentValue === "object" && currentValue !== null) {
      result[key] = updateStepInHierarchy(currentValue, targetStepId);
    } else {
      result[key] = currentValue;
    }
  }
  return result;
};
function getResultActivePaths(state) {
  const activePaths = getActivePathsAndStatus(state.value);
  const activePathsAndStatus = activePaths.reduce((acc, curr) => {
    const entry = {
      status: curr.status,
      stepPath: curr.stepPath
    };
    if (curr.status === "suspended") {
      entry.suspendPayload = state.context.steps[curr.stepId].suspendPayload;
      entry.stepPath = curr.stepPath;
    }
    acc.set(curr.stepId, entry);
    return acc;
  }, /* @__PURE__ */new Map());
  return activePathsAndStatus;
}
function isWorkflow(step) {
  return step instanceof Workflow;
}
function isAgent(step) {
  return step instanceof exports.Agent;
}
function resolveVariables({
  runId,
  logger,
  variables,
  context
}) {
  const resolvedData = {};
  for (const [key, variable] of Object.entries(variables)) {
    const sourceData = variable.step === "trigger" ? context.triggerData : getStepResult(context.steps[variable.step.id ?? variable.step.name]);
    logger.debug(`Got source data for ${key} variable from ${variable.step === "trigger" ? "trigger" : variable.step.id ?? variable.step.name}`, {
      sourceData,
      path: variable.path,
      runId
    });
    if (!sourceData && variable.step !== "trigger") {
      resolvedData[key] = void 0;
      continue;
    }
    const value = variable.path === "" || variable.path === "." ? sourceData : radash.get(sourceData, variable.path);
    logger.debug(`Resolved variable ${key}`, {
      value,
      runId
    });
    resolvedData[key] = value;
  }
  return resolvedData;
}
function agentToStep(agent, {
  mastra
} = {}) {
  return {
    id: agent.name,
    inputSchema: zod.z.object({
      prompt: zod.z.string(),
      resourceId: zod.z.string().optional(),
      threadId: zod.z.string().optional()
    }),
    outputSchema: zod.z.object({
      text: zod.z.string()
    }),
    execute: async ({
      context,
      runId,
      mastra: mastraFromExecute
    }) => {
      const realMastra = mastraFromExecute ?? mastra;
      if (!realMastra) {
        throw new Error("Mastra instance not found");
      }
      agent.__registerMastra(realMastra);
      agent.__registerPrimitives({
        logger: realMastra.getLogger(),
        telemetry: realMastra.getTelemetry()
      });
      const result = await agent.generate(context.inputData.prompt, {
        runId,
        resourceId: context.inputData.resourceId,
        threadId: context.inputData.threadId
      });
      return {
        text: result.text
      };
    }
  };
}
function workflowToStep(workflow, {
  mastra
}) {
  workflow.setNested(true);
  return {
    id: workflow.name,
    workflow,
    workflowId: toCamelCaseWithRandomSuffix(workflow.name),
    execute: async ({
      context,
      suspend,
      emit,
      mastra: mastraFromExecute,
      runtimeContext
    }) => {
      const realMastra = mastraFromExecute ?? mastra;
      if (realMastra) {
        workflow.__registerMastra(realMastra);
        workflow.__registerPrimitives({
          logger: realMastra.getLogger(),
          telemetry: realMastra.getTelemetry()
        });
      }
      const run = context.isResume ? workflow.createRun({
        runId: context.isResume.runId
      }) : workflow.createRun();
      const unwatch = run.watch(state => {
        emit("state-update", workflow.name, state.results, {
          ...context,
          ...{
            [workflow.name]: state.results
          }
        });
      });
      const awaitedResult = context.isResume && context.isResume.stepId.includes(".") ? await run.resume({
        stepId: context.isResume.stepId.split(".").slice(1).join("."),
        context: context.inputData,
        runtimeContext
      }) : await run.start({
        triggerData: context.inputData,
        runtimeContext
      });
      unwatch();
      if (!awaitedResult) {
        throw new Error("Workflow run failed");
      }
      if (awaitedResult.activePaths?.size > 0) {
        const suspendedStep = [...awaitedResult.activePaths.entries()].find(([, {
          status
        }]) => {
          return status === "suspended";
        });
        if (suspendedStep) {
          await suspend(suspendedStep[1].suspendPayload, {
            ...awaitedResult,
            runId: run.runId
          });
        }
      }
      return {
        ...awaitedResult,
        runId: run.runId
      };
    }
  };
}
function toCamelCaseWithRandomSuffix(str) {
  if (!str) return "";
  const normalizedStr = str.replace(/[-_]/g, " ");
  const words = normalizedStr.split(" ").filter(word => word.length > 0);
  const camelCase = words.map((word, index) => {
    word = word.replace(/[^a-zA-Z0-9]/g, "");
    if (index === 0) {
      return word.toLowerCase();
    }
    return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
  }).join("");
  const randomString = generateRandomLetters(3);
  return camelCase + randomString;
}
function generateRandomLetters(length) {
  const characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
  let result = "";
  for (let i = 0; i < length; i++) {
    const randomIndex = Math.floor(Math.random() * characters.length);
    result += characters.charAt(randomIndex);
  }
  return result;
}
function isConditionalKey(key) {
  return key.startsWith("__") && (key.includes("_if") || key.includes("_else"));
}
var Machine = class extends EventEmitter__default.default {
  logger;
  #mastra;
  #runtimeContext;
  #workflowInstance;
  #executionSpan;
  #stepGraph;
  #machine;
  #runId;
  #startStepId;
  name;
  #actor = null;
  #steps = {};
  #retryConfig;
  constructor({
    logger,
    mastra,
    runtimeContext,
    workflowInstance,
    executionSpan,
    name,
    runId,
    steps,
    stepGraph,
    retryConfig,
    startStepId
  }) {
    super();
    this.#mastra = mastra;
    this.#workflowInstance = workflowInstance;
    this.#runtimeContext = runtimeContext;
    this.#executionSpan = executionSpan;
    this.logger = logger;
    this.#runId = runId;
    this.#startStepId = startStepId;
    this.name = name;
    this.#stepGraph = stepGraph;
    this.#steps = steps;
    this.#retryConfig = retryConfig;
    this.initializeMachine();
  }
  get startStepId() {
    return this.#startStepId;
  }
  async execute({
    stepId,
    input,
    snapshot,
    resumeData
  } = {}) {
    if (snapshot) {
      this.logger.debug(`Workflow snapshot received`, {
        runId: this.#runId,
        snapshot
      });
    }
    const origSteps = input.steps;
    const isResumedInitialStep = this.#stepGraph?.initial[0]?.step?.id === stepId;
    if (isResumedInitialStep) {
      snapshot = void 0;
      input.steps = {};
    }
    this.logger.debug(`Machine input prepared`, {
      runId: this.#runId,
      input
    });
    const actorSnapshot = snapshot ? {
      ...snapshot,
      context: {
        ...input,
        inputData: {
          ...(snapshot?.context?.inputData || {}),
          ...resumeData
        },
        // ts-ignore is needed here because our snapshot types don't really match xstate snapshot types right now. We should fix this in general.
        // @ts-ignore
        isResume: {
          runId: snapshot?.context?.steps[stepId.split(".")?.[0]]?.output?.runId || this.#runId,
          stepId
        }
      }
    } : void 0;
    this.logger.debug(`Creating actor with configuration`, {
      input,
      actorSnapshot,
      runId: this.#runId,
      machineStates: this.#machine.config.states
    });
    this.#actor = xstate.createActor(this.#machine, {
      inspect: inspectionEvent => {
        this.logger.debug("XState inspection event", {
          type: inspectionEvent.type,
          event: inspectionEvent.event,
          runId: this.#runId
        });
      },
      input: {
        ...input,
        inputData: {
          ...(snapshot?.context?.inputData || {}),
          ...resumeData
        }
      },
      snapshot: actorSnapshot
    });
    this.#actor.start();
    if (stepId) {
      this.#actor.send({
        type: "RESET_TO_PENDING",
        stepId
      });
    }
    this.logger.debug("Actor started", {
      runId: this.#runId
    });
    return new Promise((resolve, reject) => {
      if (!this.#actor) {
        this.logger.error("Actor not initialized", {
          runId: this.#runId
        });
        const e = new Error("Actor not initialized");
        this.#executionSpan?.recordException(e);
        this.#executionSpan?.end();
        reject(e);
        return;
      }
      const suspendedPaths = /* @__PURE__ */new Set();
      this.#actor.subscribe(async state => {
        this.emit("state-update", this.#startStepId, state);
        getSuspendedPaths({
          value: state.value,
          path: "",
          suspendedPaths
        });
        const allStatesValue = state.value;
        const allStatesComplete = recursivelyCheckForFinalState({
          value: allStatesValue,
          suspendedPaths,
          path: ""
        });
        this.logger.debug("State completion check", {
          allStatesComplete,
          suspendedPaths: Array.from(suspendedPaths),
          runId: this.#runId
        });
        if (!allStatesComplete) {
          this.logger.debug("Not all states complete", {
            allStatesComplete,
            suspendedPaths: Array.from(suspendedPaths),
            runId: this.#runId
          });
          return;
        }
        try {
          this.logger.debug("All states complete", {
            runId: this.#runId
          });
          await this.#workflowInstance.persistWorkflowSnapshot();
          this.#cleanup();
          this.#executionSpan?.end();
          resolve({
            runId: this.#runId,
            results: isResumedInitialStep ? {
              ...origSteps,
              ...state.context.steps
            } : state.context.steps,
            activePaths: getResultActivePaths(state),
            timestamp: Date.now()
          });
        } catch (error) {
          this.logger.debug("Failed to persist final snapshot", {
            error
          });
          this.#cleanup();
          this.#executionSpan?.end();
          resolve({
            runId: this.#runId,
            results: isResumedInitialStep ? {
              ...origSteps,
              ...state.context.steps
            } : state.context.steps,
            activePaths: getResultActivePaths(state),
            timestamp: Date.now()
          });
        }
      });
    });
  }
  #cleanup() {
    if (this.#actor) {
      this.#actor.stop();
      this.#actor = null;
    }
    this.removeAllListeners();
  }
  #makeDelayMap() {
    const delayMap = {};
    Object.keys(this.#steps).forEach(stepId => {
      delayMap[stepId] = this.#steps[stepId]?.step?.retryConfig?.delay || this.#retryConfig?.delay || 1e3;
    });
    return delayMap;
  }
  #getDefaultActions() {
    return {
      updateStepResult: xstate.assign({
        steps: ({
          context,
          event
        }) => {
          if (!isTransitionEvent(event)) return context.steps;
          const {
            stepId,
            result
          } = event.output;
          return {
            ...context.steps,
            [stepId]: {
              status: "success",
              output: result
            }
          };
        }
      }),
      setStepError: xstate.assign({
        steps: ({
          context,
          event
        }, params) => {
          if (!isErrorEvent(event)) return context.steps;
          const {
            stepId
          } = params;
          if (!stepId) return context.steps;
          return {
            ...context.steps,
            [stepId]: {
              status: "failed",
              error: event.error.message
            }
          };
        }
      }),
      notifyStepCompletion: async (_, params) => {
        const {
          stepId
        } = params;
        this.logger.debug(`Step ${stepId} completed`);
      },
      snapshotStep: xstate.assign({
        _snapshot: ({}, params) => {
          const {
            stepId
          } = params;
          return {
            stepId
          };
        }
      }),
      persistSnapshot: async ({
        context
      }) => {
        if (context._snapshot) {
          await this.#workflowInstance.persistWorkflowSnapshot();
        }
        return;
      },
      decrementAttemptCount: xstate.assign({
        attempts: ({
          context,
          event
        }, params) => {
          if (!isTransitionEvent(event)) return context.attempts;
          const {
            stepId
          } = params;
          const attemptCount = context.attempts[stepId];
          if (attemptCount === void 0) return context.attempts;
          return {
            ...context.attempts,
            [stepId]: attemptCount - 1
          };
        }
      })
    };
  }
  #getDefaultActors() {
    return {
      resolverFunction: xstate.fromPromise(async ({
        input
      }) => {
        const {
          stepNode,
          context
        } = input;
        const attemptCount = context.attempts[stepNode.id];
        const resolvedData = this.#resolveVariables({
          stepConfig: stepNode.config,
          context,
          stepId: stepNode.id
        });
        this.logger.debug(`Resolved variables for ${stepNode.id}`, {
          resolvedData,
          runId: this.#runId
        });
        const logger = this.logger;
        let mastraProxy = void 0;
        if (this.#mastra) {
          mastraProxy = chunkFXAV2WYX_cjs.createMastraProxy({
            mastra: this.#mastra,
            logger
          });
        }
        let result = void 0;
        try {
          result = await stepNode.config.handler({
            context: {
              ...context,
              inputData: {
                ...(context?.inputData || {}),
                ...resolvedData
              },
              getStepResult: stepId => {
                const resolvedStepId = typeof stepId === "string" ? stepId : stepId.id;
                if (resolvedStepId === "trigger") {
                  return context.triggerData;
                }
                const result2 = context.steps[resolvedStepId];
                if (result2 && result2.status === "success") {
                  return result2.output;
                }
                return void 0;
              }
            },
            emit: (event, ...args) => {
              this.emit(event, ...args);
            },
            suspend: async (payload, softSuspend) => {
              await this.#workflowInstance.suspend(stepNode.id, this);
              if (this.#actor) {
                context.steps[stepNode.id] = {
                  status: "suspended",
                  suspendPayload: payload,
                  output: softSuspend
                };
                this.logger.debug(`Sending SUSPENDED event for step ${stepNode.id}`);
                this.#actor?.send({
                  type: "SUSPENDED",
                  suspendPayload: payload,
                  stepId: stepNode.id,
                  softSuspend
                });
              } else {
                this.logger.debug(`Actor not available for step ${stepNode.id}`);
              }
            },
            runId: this.#runId,
            mastra: mastraProxy,
            runtimeContext: this.#runtimeContext
          });
        } catch (error) {
          this.logger.debug(`Step ${stepNode.id} failed`, {
            stepId: stepNode.id,
            error,
            runId: this.#runId
          });
          this.logger.debug(`Attempt count for step ${stepNode.id}`, {
            attemptCount,
            attempts: context.attempts,
            runId: this.#runId,
            stepId: stepNode.id
          });
          if (!attemptCount || attemptCount < 0) {
            return {
              type: "STEP_FAILED",
              error: error instanceof Error ? error.message : `Step:${stepNode.id} failed with error: ${error}`,
              stepId: stepNode.id
            };
          }
          return {
            type: "STEP_WAITING",
            stepId: stepNode.id
          };
        }
        this.logger.debug(`Step ${stepNode.id} result`, {
          stepId: stepNode.id,
          result,
          runId: this.#runId
        });
        return {
          type: "STEP_SUCCESS",
          result,
          stepId: stepNode.id
        };
      }),
      conditionCheck: xstate.fromPromise(async ({
        input
      }) => {
        const {
          context,
          stepNode
        } = input;
        const stepConfig = stepNode.config;
        this.logger.debug(`Checking conditions for step ${stepNode.id}`, {
          stepId: stepNode.id,
          runId: this.#runId
        });
        if (!stepConfig?.when) {
          return {
            type: "CONDITIONS_MET"
          };
        }
        this.logger.debug(`Checking conditions for step ${stepNode.id}`, {
          stepId: stepNode.id,
          runId: this.#runId
        });
        if (typeof stepConfig?.when === "function") {
          let conditionMet = await stepConfig.when({
            context: {
              ...context,
              getStepResult: stepId => {
                const resolvedStepId = typeof stepId === "string" ? stepId : stepId.id;
                if (resolvedStepId === "trigger") {
                  return context.triggerData;
                }
                const result = context.steps[resolvedStepId];
                if (result && result.status === "success") {
                  return result.output;
                }
                return void 0;
              }
            },
            mastra: this.#mastra
          });
          if (conditionMet === "abort" /* ABORT */) {
            conditionMet = false;
          } else if (conditionMet === "continue_failed" /* CONTINUE_FAILED */) {
            return {
              type: "CONDITIONS_SKIP_TO_COMPLETED"
            };
          } else if (conditionMet === "limbo" /* LIMBO */) {
            return {
              type: "CONDITIONS_LIMBO"
            };
          } else if (conditionMet) {
            this.logger.debug(`Condition met for step ${stepNode.id}`, {
              stepId: stepNode.id,
              runId: this.#runId
            });
            return {
              type: "CONDITIONS_MET"
            };
          }
          if (isConditionalKey(stepNode.id)) {
            return {
              type: "CONDITIONS_LIMBO"
            };
          }
          return this.#workflowInstance.hasSubscribers(stepNode.id) ? {
            type: "CONDITIONS_SKIPPED"
          } : {
            type: "CONDITIONS_LIMBO"
          };
        } else {
          const conditionMet = this.#evaluateCondition(stepConfig.when, context);
          if (!conditionMet) {
            return {
              type: "CONDITION_FAILED",
              error: `Step:${stepNode.id} condition check failed`
            };
          }
        }
        return {
          type: "CONDITIONS_MET"
        };
      }),
      spawnSubscriberFunction: xstate.fromPromise(async ({
        input
      }) => {
        const {
          parentStepId,
          context
        } = input;
        const result = await this.#workflowInstance.runMachine(parentStepId, context, this.#runtimeContext);
        return Promise.resolve({
          steps: result.reduce((acc, r) => {
            return {
              ...acc,
              ...r?.results
            };
          }, {})
        });
      })
    };
  }
  #resolveVariables({
    stepConfig,
    context,
    stepId
  }) {
    this.logger.debug(`Resolving variables for step ${stepId}`, {
      stepId,
      runId: this.#runId
    });
    const resolvedData = {};
    for (const [key, variable] of Object.entries(stepConfig.data)) {
      const sourceData = variable.step === "trigger" ? context.triggerData : getStepResult(context.steps[variable.step.id]);
      this.logger.debug(`Got source data for ${key} variable from ${variable.step === "trigger" ? "trigger" : variable.step.id}`, {
        sourceData,
        path: variable.path,
        runId: this.#runId
      });
      if (!sourceData && variable.step !== "trigger") {
        resolvedData[key] = void 0;
        continue;
      }
      const value = variable.path === "" || variable.path === "." ? sourceData : radash.get(sourceData, variable.path);
      this.logger.debug(`Resolved variable ${key}`, {
        value,
        runId: this.#runId
      });
      resolvedData[key] = value;
    }
    return resolvedData;
  }
  initializeMachine() {
    const machine = xstate.setup({
      types: {},
      delays: this.#makeDelayMap(),
      actions: this.#getDefaultActions(),
      actors: this.#getDefaultActors()
    }).createMachine({
      id: this.name,
      type: "parallel",
      context: ({
        input
      }) => ({
        ...input
      }),
      states: this.#buildStateHierarchy(this.#stepGraph)
    });
    this.#machine = machine;
    return machine;
  }
  #buildStateHierarchy(stepGraph) {
    const states = {};
    stepGraph.initial.forEach(stepNode => {
      const nextSteps = [...(stepGraph[stepNode.id] || [])];
      states[stepNode.id] = {
        ...this.#buildBaseState(stepNode, nextSteps)
      };
    });
    return states;
  }
  #buildBaseState(stepNode, nextSteps = []) {
    const nextStep = nextSteps.shift();
    return {
      initial: "pending",
      on: {
        RESET_TO_PENDING: {
          target: ".pending"
          // Note the dot to target child state
        }
      },
      states: {
        pending: {
          entry: () => {
            this.logger.debug(`Step ${stepNode.id} pending`, {
              stepId: stepNode.id,
              runId: this.#runId
            });
          },
          exit: () => {
            this.logger.debug(`Step ${stepNode.id} finished pending`, {
              stepId: stepNode.id,
              runId: this.#runId
            });
          },
          invoke: {
            src: "conditionCheck",
            input: ({
              context
            }) => {
              return {
                context,
                stepNode
              };
            },
            onDone: [{
              guard: ({
                event
              }) => {
                return event.output.type === "SUSPENDED";
              },
              target: "suspended",
              actions: [xstate.assign({
                steps: ({
                  context,
                  event
                }) => {
                  if (event.output.type !== "SUSPENDED") return context.steps;
                  if (event.output.softSuspend) {
                    return {
                      ...context.steps,
                      [stepNode.id]: {
                        status: "suspended",
                        ...(context.steps?.[stepNode.id] || {}),
                        output: event.output.softSuspend
                      }
                    };
                  }
                  return {
                    ...context.steps,
                    [stepNode.id]: {
                      status: "suspended",
                      ...(context.steps?.[stepNode.id] || {})
                    }
                  };
                },
                attempts: ({
                  context,
                  event
                }) => {
                  if (event.output.type !== "SUSPENDED") return context.attempts;
                  return {
                    ...context.attempts,
                    [stepNode.id]: stepNode.step.retryConfig?.attempts || 0
                  };
                }
              })]
            }, {
              guard: ({
                event
              }) => {
                return event.output.type === "WAITING";
              },
              target: "waiting",
              actions: [{
                type: "decrementAttemptCount",
                params: {
                  stepId: stepNode.id
                }
              }, xstate.assign({
                steps: ({
                  context,
                  event
                }) => {
                  if (event.output.type !== "WAITING") return context.steps;
                  return {
                    ...context.steps,
                    [stepNode.id]: {
                      status: "waiting"
                    }
                  };
                }
              })]
            }, {
              guard: ({
                event
              }) => {
                return event.output.type === "CONDITIONS_MET";
              },
              target: "executing"
            }, {
              guard: ({
                event
              }) => {
                return event.output.type === "CONDITIONS_SKIP_TO_COMPLETED";
              },
              target: "completed"
            }, {
              guard: ({
                event
              }) => {
                return event.output.type === "CONDITIONS_SKIPPED";
              },
              actions: xstate.assign({
                steps: ({
                  context
                }) => {
                  const newStep = {
                    ...context.steps,
                    [stepNode.id]: {
                      status: "skipped"
                    }
                  };
                  this.logger.debug(`Step ${stepNode.id} skipped`, {
                    stepId: stepNode.id,
                    runId: this.#runId
                  });
                  return newStep;
                }
              }),
              target: "runningSubscribers"
            }, {
              guard: ({
                event
              }) => {
                return event.output.type === "CONDITIONS_LIMBO";
              },
              target: "limbo",
              actions: xstate.assign({
                steps: ({
                  context
                }) => {
                  const newStep = {
                    ...context.steps,
                    [stepNode.id]: {
                      status: "skipped"
                    }
                  };
                  this.logger.debug(`Step ${stepNode.id} skipped`, {
                    stepId: stepNode.id,
                    runId: this.#runId
                  });
                  return newStep;
                }
              })
            }, {
              guard: ({
                event
              }) => {
                return event.output.type === "CONDITION_FAILED";
              },
              target: "failed",
              actions: xstate.assign({
                steps: ({
                  context,
                  event
                }) => {
                  if (event.output.type !== "CONDITION_FAILED") return context.steps;
                  this.logger.debug(`Workflow condition check failed`, {
                    error: event.output.error,
                    stepId: stepNode.id
                  });
                  return {
                    ...context.steps,
                    [stepNode.id]: {
                      status: "failed",
                      error: event.output.error
                    }
                  };
                }
              })
            }]
          }
        },
        waiting: {
          entry: () => {
            this.logger.debug(`Step ${stepNode.id} waiting`, {
              stepId: stepNode.id,
              timestamp: (/* @__PURE__ */new Date()).toISOString(),
              runId: this.#runId
            });
          },
          exit: () => {
            this.logger.debug(`Step ${stepNode.id} finished waiting`, {
              stepId: stepNode.id,
              timestamp: (/* @__PURE__ */new Date()).toISOString(),
              runId: this.#runId
            });
          },
          after: {
            [stepNode.id]: {
              target: "pending"
            }
          }
        },
        limbo: {
          // no target, will stay in limbo indefinitely
          entry: () => {
            this.logger.debug(`Step ${stepNode.id} limbo`, {
              stepId: stepNode.id,
              timestamp: (/* @__PURE__ */new Date()).toISOString(),
              runId: this.#runId
            });
          },
          exit: () => {
            this.logger.debug(`Step ${stepNode.id} finished limbo`, {
              stepId: stepNode.id,
              timestamp: (/* @__PURE__ */new Date()).toISOString(),
              runId: this.#runId
            });
          }
        },
        suspended: {
          type: "final",
          entry: [() => {
            this.logger.debug(`Step ${stepNode.id} suspended`, {
              stepId: stepNode.id,
              runId: this.#runId
            });
          }, xstate.assign({
            steps: ({
              context,
              event
            }) => {
              return {
                ...context.steps,
                [stepNode.id]: {
                  ...(context?.steps?.[stepNode.id] || {}),
                  status: "suspended",
                  suspendPayload: event.type === "SUSPENDED" ? event.suspendPayload : void 0,
                  output: event.type === "SUSPENDED" ? event.softSuspend : void 0
                }
              };
            }
          })]
        },
        executing: {
          entry: () => {
            this.logger.debug(`Step ${stepNode.id} executing`, {
              stepId: stepNode.id,
              runId: this.#runId
            });
          },
          on: {
            SUSPENDED: {
              target: "suspended",
              actions: [xstate.assign({
                steps: ({
                  context,
                  event
                }) => {
                  return {
                    ...context.steps,
                    [stepNode.id]: {
                      status: "suspended",
                      suspendPayload: event.type === "SUSPENDED" ? event.suspendPayload : void 0,
                      output: event.type === "SUSPENDED" ? event.softSuspend : void 0
                    }
                  };
                }
              })]
            }
          },
          invoke: {
            src: "resolverFunction",
            input: ({
              context
            }) => ({
              context,
              stepNode
            }),
            onDone: [{
              guard: ({
                event
              }) => {
                return event.output.type === "STEP_FAILED";
              },
              target: "failed",
              actions: xstate.assign({
                steps: ({
                  context,
                  event
                }) => {
                  if (event.output.type !== "STEP_FAILED") return context.steps;
                  const newStep = {
                    ...context.steps,
                    [stepNode.id]: {
                      status: "failed",
                      error: event.output.error
                    }
                  };
                  this.logger.debug(`Step ${stepNode.id} failed`, {
                    error: event.output.error,
                    stepId: stepNode.id
                  });
                  return newStep;
                }
              })
            }, {
              guard: ({
                event
              }) => {
                return event.output.type === "STEP_SUCCESS";
              },
              actions: [({
                event
              }) => {
                this.logger.debug(`Step ${stepNode.id} finished executing`, {
                  stepId: stepNode.id,
                  output: event.output,
                  runId: this.#runId
                });
              }, {
                type: "updateStepResult",
                params: {
                  stepId: stepNode.id
                }
              }, {
                type: "spawnSubscribers",
                params: {
                  stepId: stepNode.id
                }
              }],
              target: "runningSubscribers"
            }, {
              guard: ({
                event
              }) => {
                return event.output.type === "STEP_WAITING";
              },
              target: "waiting",
              actions: [{
                type: "decrementAttemptCount",
                params: {
                  stepId: stepNode.id
                }
              }, xstate.assign({
                steps: ({
                  context,
                  event
                }) => {
                  if (event.output.type !== "STEP_WAITING") return context.steps;
                  return {
                    ...context.steps,
                    [stepNode.id]: {
                      status: "waiting"
                    }
                  };
                }
              })]
            }],
            onError: {
              target: "failed",
              actions: [{
                type: "setStepError",
                params: {
                  stepId: stepNode.id
                }
              }]
            }
          }
        },
        runningSubscribers: {
          entry: () => {
            this.logger.debug(`Step ${stepNode.id} running subscribers`, {
              stepId: stepNode.id,
              runId: this.#runId
            });
          },
          exit: () => {
            this.logger.debug(`Step ${stepNode.id} finished running subscribers`, {
              stepId: stepNode.id,
              runId: this.#runId
            });
          },
          invoke: {
            src: "spawnSubscriberFunction",
            input: ({
              context
            }) => ({
              parentStepId: stepNode.id,
              context
            }),
            onDone: {
              target: nextStep ? nextStep.id : "completed",
              actions: [xstate.assign({
                steps: ({
                  context,
                  event
                }) => ({
                  ...context.steps,
                  ...event.output.steps
                })
              }), () => this.logger.debug(`Subscriber execution completed`, {
                stepId: stepNode.id
              })]
            },
            onError: {
              target: nextStep ? nextStep.id : "completed",
              actions: ({
                event
              }) => {
                this.logger.debug(`Subscriber execution failed`, {
                  error: event.error,
                  stepId: stepNode.id
                });
              }
            }
          }
        },
        completed: {
          type: "final",
          entry: [{
            type: "notifyStepCompletion",
            params: {
              stepId: stepNode.id
            }
          }, {
            type: "snapshotStep",
            params: {
              stepId: stepNode.id
            }
          }, {
            type: "persistSnapshot"
          }]
        },
        failed: {
          type: "final",
          entry: [{
            type: "notifyStepCompletion",
            params: {
              stepId: stepNode.id
            }
          }, {
            type: "snapshotStep",
            params: {
              stepId: stepNode.id
            }
          }, {
            type: "persistSnapshot"
          }]
        },
        // build chain of next steps recursively
        ...(nextStep ? {
          [nextStep.id]: {
            ...this.#buildBaseState(nextStep, nextSteps)
          }
        } : {})
      }
    };
  }
  #evaluateCondition(condition, context) {
    let andBranchResult = true;
    let baseResult = true;
    let orBranchResult = true;
    const simpleCondition = Object.entries(condition).find(([key]) => key.includes("."));
    if (simpleCondition) {
      const [key, queryValue] = simpleCondition;
      const [stepId, ...pathParts] = key.split(".");
      const path = pathParts.join(".");
      const sourceData = stepId === "trigger" ? context.triggerData : getStepResult(context.steps[stepId]);
      this.logger.debug(`Got condition data from step ${stepId}`, {
        stepId,
        sourceData,
        runId: this.#runId
      });
      if (!sourceData) {
        return false;
      }
      let value = radash.get(sourceData, path);
      if (stepId !== "trigger" && path === "status" && !value) {
        value = "success";
      }
      if (typeof queryValue === "object" && queryValue !== null) {
        baseResult = sift__default.default(queryValue)(value);
      } else {
        baseResult = value === queryValue;
      }
    }
    if ("ref" in condition) {
      const {
        ref,
        query
      } = condition;
      const sourceData = ref.step === "trigger" ? context.triggerData : getStepResult(context.steps[ref.step.id]);
      this.logger.debug(`Got condition data from ${ref.step === "trigger" ? "trigger" : ref.step.id}`, {
        sourceData,
        runId: this.#runId
      });
      if (!sourceData) {
        return false;
      }
      let value = radash.get(sourceData, ref.path);
      if (ref.step !== "trigger" && ref.path === "status" && !value) {
        value = "success";
      }
      baseResult = sift__default.default(query)(value);
    }
    if ("and" in condition) {
      andBranchResult = condition.and.every(cond => this.#evaluateCondition(cond, context));
      this.logger.debug(`Evaluated AND condition`, {
        andBranchResult,
        runId: this.#runId
      });
    }
    if ("or" in condition) {
      orBranchResult = condition.or.some(cond => this.#evaluateCondition(cond, context));
      this.logger.debug(`Evaluated OR condition`, {
        orBranchResult,
        runId: this.#runId
      });
    }
    if ("not" in condition) {
      baseResult = !this.#evaluateCondition(condition.not, context);
      this.logger.debug(`Evaluated NOT condition`, {
        baseResult,
        runId: this.#runId
      });
    }
    const finalResult = baseResult && andBranchResult && orBranchResult;
    this.logger.debug(`Evaluated condition`, {
      finalResult,
      runId: this.#runId
    });
    return finalResult;
  }
  getSnapshot() {
    const snapshot = this.#actor?.getSnapshot();
    return snapshot;
  }
};

// src/workflows/workflow-instance.ts
var WorkflowInstance = class {
  name;
  #mastra;
  #machines = {};
  logger;
  #steps = {};
  #stepGraph;
  #stepSubscriberGraph = {};
  #retryConfig;
  events;
  #runId;
  #state = null;
  #executionSpan;
  #onStepTransition = /* @__PURE__ */new Set();
  #onFinish;
  #resultMapping;
  // indexed by stepId
  #suspendedMachines = {};
  // {step1&&step2: {step1: true, step2: true}}
  #compoundDependencies = {};
  constructor({
    name,
    logger,
    steps,
    runId,
    retryConfig,
    mastra,
    stepGraph,
    stepSubscriberGraph,
    onFinish,
    onStepTransition,
    resultMapping,
    events
  }) {
    this.name = name;
    this.logger = logger;
    this.#steps = steps;
    this.#stepGraph = stepGraph;
    this.#stepSubscriberGraph = stepSubscriberGraph;
    this.#retryConfig = retryConfig;
    this.#mastra = mastra;
    this.#runId = runId ?? crypto.randomUUID();
    this.#onFinish = onFinish;
    this.#resultMapping = resultMapping;
    this.events = events;
    onStepTransition?.forEach(handler => this.#onStepTransition.add(handler));
    this.#initializeCompoundDependencies();
  }
  setState(state) {
    this.#state = state;
  }
  get runId() {
    return this.#runId;
  }
  get executionSpan() {
    return this.#executionSpan;
  }
  watch(onTransition) {
    this.#onStepTransition.add(onTransition);
    return () => {
      this.#onStepTransition.delete(onTransition);
    };
  }
  async start({
    triggerData,
    runtimeContext
  } = {}) {
    const results = await this.execute({
      triggerData,
      runtimeContext: runtimeContext ?? new chunkLABUWBKX_cjs.RuntimeContext()
    });
    if (this.#onFinish) {
      this.#onFinish();
    }
    return {
      ...results,
      runId: this.runId
    };
  }
  isCompoundDependencyMet(stepKey) {
    if (!this.#isCompoundKey(stepKey)) return true;
    const dependencies = this.#compoundDependencies[stepKey];
    return dependencies ? Object.values(dependencies).every(status => status === true) : true;
  }
  async execute({
    triggerData,
    snapshot,
    stepId,
    resumeData,
    runtimeContext
  } = {
    runtimeContext: new chunkLABUWBKX_cjs.RuntimeContext()
  }) {
    this.#executionSpan = this.#mastra?.getTelemetry()?.tracer.startSpan(`workflow.${this.name}.execute`, {
      attributes: {
        componentName: this.name,
        runId: this.runId
      }
    });
    let machineInput = {
      // Maintain the original step results and their output
      steps: {},
      triggerData: triggerData || {},
      attempts: Object.keys(this.#steps).reduce((acc, stepKey) => {
        acc[stepKey] = this.#steps[stepKey]?.step?.retryConfig?.attempts || this.#retryConfig?.attempts || 0;
        return acc;
      }, {})
    };
    let stepGraph = this.#stepGraph;
    let startStepId = "trigger";
    if (snapshot) {
      const runState = snapshot;
      if (stepId && runState?.suspendedSteps?.[stepId]) {
        startStepId = runState.suspendedSteps[stepId];
        stepGraph = this.#stepSubscriberGraph[startStepId] ?? this.#stepGraph;
        machineInput = runState.context;
      }
    }
    const defaultMachine = new Machine({
      logger: this.logger,
      mastra: this.#mastra,
      runtimeContext,
      workflowInstance: this,
      name: this.name,
      runId: this.runId,
      steps: this.#steps,
      stepGraph,
      executionSpan: this.#executionSpan,
      startStepId,
      retryConfig: this.#retryConfig
    });
    this.#machines[startStepId] = defaultMachine;
    const stateUpdateHandler = (startStepId2, state, ctx) => {
      let fullState = {
        value: {},
        context: {}
      };
      if (ctx) {
        fullState["value"] = state;
        fullState["context"] = ctx;
      } else {
        fullState = state;
      }
      if (startStepId2 === "trigger") {
        this.#state = fullState.value;
      } else {
        this.#state = mergeChildValue(startStepId2, this.#state, fullState.value);
      }
      const now = Date.now();
      if (this.#onStepTransition) {
        this.#onStepTransition.forEach(onTransition => {
          void onTransition({
            runId: this.#runId,
            results: fullState.context.steps,
            activePaths: getResultActivePaths(fullState),
            timestamp: now
          });
        });
      }
    };
    defaultMachine.on("state-update", stateUpdateHandler);
    const {
      results,
      activePaths
    } = await defaultMachine.execute({
      snapshot,
      stepId,
      input: machineInput,
      resumeData
    });
    await this.persistWorkflowSnapshot();
    const result = {
      results,
      activePaths,
      timestamp: Date.now()
    };
    if (this.#resultMapping) {
      result.result = resolveVariables({
        runId: this.#runId,
        logger: this.logger,
        variables: this.#resultMapping,
        context: {
          steps: results,
          triggerData}
      });
    }
    return result;
  }
  hasSubscribers(stepId) {
    return Object.keys(this.#stepSubscriberGraph).some(key => key.split("&&").includes(stepId));
  }
  async runMachine(parentStepId, input, runtimeContext = new chunkLABUWBKX_cjs.RuntimeContext()) {
    const stepStatus = input.steps[parentStepId]?.status;
    const subscriberKeys = Object.keys(this.#stepSubscriberGraph).filter(key => key.split("&&").includes(parentStepId));
    subscriberKeys.forEach(key => {
      if (["success", "failure", "skipped"].includes(stepStatus) && this.#isCompoundKey(key)) {
        this.#compoundDependencies[key][parentStepId] = true;
      }
    });
    const stateUpdateHandler = (startStepId, state, ctx) => {
      let fullState = {
        value: {},
        context: {}
      };
      if (ctx) {
        fullState["value"] = state;
        fullState["context"] = ctx;
      } else {
        fullState = state;
      }
      if (startStepId === "trigger") {
        this.#state = fullState.value;
      } else {
        this.#state = mergeChildValue(startStepId, this.#state, fullState.value);
      }
      const now = Date.now();
      if (this.#onStepTransition) {
        this.#onStepTransition.forEach(onTransition => {
          void onTransition({
            runId: this.#runId,
            results: fullState.context.steps,
            activePaths: getResultActivePaths(fullState),
            timestamp: now
          });
        });
      }
    };
    const results = await Promise.all(subscriberKeys.map(async key => {
      if (!this.#stepSubscriberGraph[key] || !this.isCompoundDependencyMet(key)) {
        return;
      }
      this.#resetCompoundDependency(key);
      const machine = new Machine({
        logger: this.logger,
        mastra: this.#mastra,
        runtimeContext,
        workflowInstance: this,
        name: parentStepId === "trigger" ? this.name : `${this.name}-${parentStepId}`,
        runId: this.runId,
        steps: this.#steps,
        stepGraph: this.#stepSubscriberGraph[key],
        executionSpan: this.#executionSpan,
        startStepId: parentStepId
      });
      machine.on("state-update", stateUpdateHandler);
      this.#machines[parentStepId] = machine;
      return machine.execute({
        input
      });
    }));
    return results;
  }
  async suspend(stepId, machine) {
    this.#suspendedMachines[stepId] = machine;
  }
  /**
   * Persists the workflow state to the database
   */
  async persistWorkflowSnapshot() {
    const storage = this.#mastra?.getStorage();
    if (!storage) {
      this.logger.debug("Snapshot cannot be persisted. Mastra engine is not initialized", {
        runId: this.#runId
      });
      return;
    }
    const existingSnapshot = await storage.loadWorkflowSnapshot({
      workflowName: this.name,
      runId: this.#runId
    });
    const machineSnapshots = {};
    for (const [stepId, machine] of Object.entries(this.#machines)) {
      const machineSnapshot = machine?.getSnapshot();
      if (machineSnapshot) {
        machineSnapshots[stepId] = {
          ...machineSnapshot
        };
      }
    }
    let snapshot = machineSnapshots["trigger"];
    delete machineSnapshots["trigger"];
    const suspendedSteps = Object.entries(this.#suspendedMachines).reduce((acc, [stepId, machine]) => {
      acc[stepId] = machine.startStepId;
      return acc;
    }, {});
    if (!snapshot && existingSnapshot) {
      existingSnapshot.childStates = {
        ...existingSnapshot.childStates,
        ...machineSnapshots
      };
      existingSnapshot.suspendedSteps = {
        ...existingSnapshot.suspendedSteps,
        ...suspendedSteps
      };
      await storage.persistWorkflowSnapshot({
        workflowName: this.name,
        runId: this.#runId,
        snapshot: existingSnapshot
      });
      return;
    } else if (snapshot && !existingSnapshot) {
      snapshot.suspendedSteps = suspendedSteps;
      snapshot.childStates = {
        ...machineSnapshots
      };
      await storage.persistWorkflowSnapshot({
        workflowName: this.name,
        runId: this.#runId,
        snapshot
      });
      return;
    } else if (!snapshot) {
      this.logger.debug("Snapshot cannot be persisted. No snapshot received.", {
        runId: this.#runId
      });
      return;
    }
    snapshot.suspendedSteps = {
      ...existingSnapshot.suspendedSteps,
      ...suspendedSteps
    };
    if (!existingSnapshot || snapshot === existingSnapshot) {
      await storage.persistWorkflowSnapshot({
        workflowName: this.name,
        runId: this.#runId,
        snapshot
      });
      return;
    }
    if (existingSnapshot?.childStates) {
      snapshot.childStates = {
        ...existingSnapshot.childStates,
        ...machineSnapshots
      };
    } else {
      snapshot.childStates = machineSnapshots;
    }
    await storage.persistWorkflowSnapshot({
      workflowName: this.name,
      runId: this.#runId,
      snapshot
    });
  }
  async getState() {
    const storedSnapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
      workflowName: this.name,
      runId: this.runId
    });
    const prevSnapshot = storedSnapshot ? {
      trigger: storedSnapshot,
      ...Object.entries(storedSnapshot?.childStates ?? {}).reduce((acc, [stepId, snapshot2]) => ({
        ...acc,
        [stepId]: snapshot2
      }), {})
    } : {};
    const currentSnapshot = Object.entries(this.#machines).reduce((acc, [stepId, machine]) => {
      const snapshot2 = machine.getSnapshot();
      if (!snapshot2) {
        return acc;
      }
      return {
        ...acc,
        [stepId]: snapshot2
      };
    }, {});
    Object.assign(prevSnapshot, currentSnapshot);
    const trigger = prevSnapshot.trigger;
    delete prevSnapshot.trigger;
    const snapshot = {
      ...trigger};
    const m = getActivePathsAndStatus(prevSnapshot.value);
    return {
      runId: this.runId,
      value: snapshot.value,
      context: snapshot.context,
      activePaths: m,
      timestamp: Date.now()
    };
  }
  async resumeWithEvent(eventName, data, runtimeContext = new chunkLABUWBKX_cjs.RuntimeContext()) {
    const event = this.events?.[eventName];
    if (!event) {
      throw new Error(`Event ${eventName} not found`);
    }
    const results = await this.resume({
      stepId: `__${eventName}_event`,
      context: {
        resumedEvent: data
      },
      runtimeContext
    });
    return results;
  }
  async resume({
    stepId,
    context: resumeContext,
    runtimeContext = new chunkLABUWBKX_cjs.RuntimeContext()
  }) {
    await new Promise(resolve => setTimeout(resolve, 0));
    return this._resume({
      stepId,
      context: resumeContext,
      runtimeContext
    });
  }
  async #loadWorkflowSnapshot(runId) {
    const storage = this.#mastra?.getStorage();
    if (!storage) {
      this.logger.debug("Snapshot cannot be loaded. Mastra engine is not initialized", {
        runId
      });
      return;
    }
    await this.persistWorkflowSnapshot();
    return storage.loadWorkflowSnapshot({
      runId,
      workflowName: this.name
    });
  }
  async _resume({
    stepId,
    context: resumeContext,
    runtimeContext
  }) {
    const snapshot = await this.#loadWorkflowSnapshot(this.runId);
    if (!snapshot) {
      throw new Error(`No snapshot found for workflow run ${this.runId}`);
    }
    const stepParts = stepId.split(".");
    const stepPath = stepParts.join(".");
    if (stepParts.length > 1) {
      stepId = stepParts[0] ?? stepId;
    }
    let parsedSnapshot;
    try {
      parsedSnapshot = typeof snapshot === "string" ? JSON.parse(snapshot) : snapshot;
    } catch (error) {
      this.logger.debug("Failed to parse workflow snapshot for resume", {
        error,
        runId: this.runId
      });
      throw new Error("Failed to parse workflow snapshot");
    }
    const startStepId = parsedSnapshot.suspendedSteps?.[stepId];
    if (!startStepId) {
      return;
    }
    parsedSnapshot = startStepId === "trigger" ? parsedSnapshot : {
      ...parsedSnapshot?.childStates?.[startStepId],
      ...{
        suspendedSteps: parsedSnapshot.suspendedSteps
      }
    };
    if (!parsedSnapshot) {
      throw new Error(`No snapshot found for step: ${stepId} starting at ${startStepId}`);
    }
    if (resumeContext) {
      parsedSnapshot.context.steps[stepId] = {
        status: "success",
        output: {
          ...(parsedSnapshot?.context?.steps?.[stepId]?.output || {}),
          ...resumeContext
        }
      };
    }
    if (parsedSnapshot.children) {
      Object.entries(parsedSnapshot.children).forEach(([, child]) => {
        if (child.snapshot?.input?.stepNode) {
          const stepDef = this.#makeStepDef(child.snapshot.input.stepNode.step.id);
          child.snapshot.input.stepNode.config = {
            ...child.snapshot.input.stepNode.config,
            ...stepDef
          };
          child.snapshot.input.context = parsedSnapshot.context;
        }
      });
    }
    parsedSnapshot.value = updateStepInHierarchy(parsedSnapshot.value, stepId);
    if (parsedSnapshot.context?.attempts) {
      parsedSnapshot.context.attempts[stepId] = this.#steps[stepId]?.step?.retryConfig?.attempts || this.#retryConfig?.attempts || 0;
    }
    this.logger.debug("Resuming workflow with updated snapshot", {
      updatedSnapshot: parsedSnapshot,
      runId: this.runId,
      stepId
    });
    return this.execute({
      snapshot: parsedSnapshot,
      stepId: stepPath,
      resumeData: resumeContext,
      runtimeContext
    });
  }
  #initializeCompoundDependencies() {
    Object.keys(this.#stepSubscriberGraph).forEach(stepKey => {
      if (this.#isCompoundKey(stepKey)) {
        const requiredSteps = stepKey.split("&&");
        this.#compoundDependencies[stepKey] = requiredSteps.reduce((acc, step) => {
          acc[step] = false;
          return acc;
        }, {});
      }
    });
  }
  #resetCompoundDependency(key) {
    if (this.#isCompoundKey(key)) {
      const requiredSteps = key.split("&&");
      this.#compoundDependencies[key] = requiredSteps.reduce((acc, step) => {
        acc[step] = false;
        return acc;
      }, {});
    }
  }
  #makeStepDef(stepId) {
    const executeStep = (handler2, spanName, attributes) => {
      return async data => {
        return await api.context.with(api.trace.setSpan(api.context.active(), this.#executionSpan), async () => {
          if (this.#mastra?.getTelemetry()) {
            return this.#mastra.getTelemetry()?.traceMethod(handler2, {
              spanName,
              attributes
            })(data);
          } else {
            return handler2(data);
          }
        });
      };
    };
    const handler = async ({
      context,
      ...rest
    }) => {
      const targetStep = this.#steps[stepId];
      if (!targetStep) throw new Error(`Step not found`);
      const {
        payload = {},
        execute = async () => {}
      } = targetStep.step;
      const mergedData = {
        ...payload,
        ...context
      };
      const finalAction = this.#mastra?.getTelemetry() ? executeStep(execute, `workflow.${this.name}.action.${stepId}`, {
        componentName: this.name,
        runId: rest.runId
      }) : execute;
      return finalAction ? await finalAction({
        context: mergedData,
        ...rest
      }) : {};
    };
    const finalHandler = ({
      context,
      ...rest
    }) => {
      if (this.#executionSpan) {
        return executeStep(handler, `workflow.${this.name}.step.${stepId}`, {
          componentName: this.name,
          runId: rest?.runId
        })({
          context,
          ...rest
        });
      }
      return handler({
        context,
        ...rest
      });
    };
    return {
      handler: finalHandler,
      data: {}
    };
  }
  #isCompoundKey(key) {
    return key.includes("&&");
  }
};

// src/workflows/workflow.ts
var Workflow = class extends chunkRO52JMKQ_cjs.MastraBase {
  name;
  triggerSchema;
  resultSchema;
  resultMapping;
  events;
  #retryConfig;
  #mastra;
  #runs = /* @__PURE__ */new Map();
  isNested = false;
  #onStepTransition = /* @__PURE__ */new Set();
  // registers stepIds on `after` calls
  #afterStepStack = [];
  #lastStepStack = [];
  #lastBuilderType = null;
  #ifStack = [];
  #stepGraph = {
    initial: []
  };
  #serializedStepGraph = {
    initial: []
  };
  #stepSubscriberGraph = {};
  #serializedStepSubscriberGraph = {};
  #steps = {};
  #ifCount = 0;
  /**
   * Creates a new Workflow instance
   * @param name - Identifier for the workflow (not necessarily unique)
   * @param logger - Optional logger instance
   */
  constructor({
    name,
    triggerSchema,
    result,
    retryConfig,
    mastra,
    events
  }) {
    super({
      component: "WORKFLOW",
      name
    });
    this.name = name;
    this.#retryConfig = retryConfig;
    this.triggerSchema = triggerSchema;
    this.resultSchema = result?.schema;
    this.resultMapping = result?.mapping;
    this.events = events;
    if (mastra) {
      this.__registerPrimitives({
        telemetry: mastra.getTelemetry(),
        logger: mastra.getLogger()
      });
      this.#mastra = mastra;
    }
  }
  step(next, config) {
    const that = this;
    if (Array.isArray(next)) {
      const nextSteps = next.map(step2 => {
        if (isWorkflow(step2)) {
          const asStep = step2.toStep();
          return asStep;
        } else if (isAgent(step2)) {
          return agentToStep(step2);
        } else {
          return step2;
        }
      });
      nextSteps.forEach(step2 => this.step(step2, config));
      this.after(nextSteps);
      this.step(new Step({
        id: `__after_${next.map(step2 => config?.id ?? step2?.id ?? step2?.name).join("_")}`,
        execute: async () => {
          return {
            success: true
          };
        }
      }));
      return this;
    }
    const {
      variables = {}
    } = config || {};
    const requiredData = {};
    for (const [key, variable] of Object.entries(variables)) {
      if (variable && isVariableReference(variable)) {
        requiredData[key] = variable;
      }
    }
    const step = isWorkflow(next) ?
    // @ts-ignore
    workflowToStep(next, {
      mastra: this.#mastra
    }) : isAgent(next) ?
    // @ts-ignore
    agentToStep(next, {
      mastra: this.#mastra
    }) : next;
    const stepKey = this.#makeStepKey(step, config);
    const when = config?.["#internal"]?.when || config?.when;
    const graphEntry = {
      step,
      config: {
        ...this.#makeStepDef(stepKey),
        ...config,
        loopLabel: config?.["#internal"]?.loopLabel,
        loopType: config?.["#internal"]?.loopType,
        serializedWhen: typeof when === "function" ? when.toString() : when,
        data: requiredData
      },
      get id() {
        return that.#makeStepKey(this.step, this.config);
      }
    };
    this.#steps[stepKey] = graphEntry;
    const parentStepKey = this.#getParentStepKey({
      loop_check: true
    });
    const stepGraph = this.#stepSubscriberGraph[parentStepKey || ""];
    const serializedStepGraph = this.#serializedStepSubscriberGraph[parentStepKey || ""];
    if (parentStepKey && stepGraph) {
      if (!stepGraph.initial.some(step2 => step2.config.id === stepKey || step2.step.id === stepKey)) {
        stepGraph.initial.push(graphEntry);
        if (serializedStepGraph) serializedStepGraph.initial.push(graphEntry);
      }
      stepGraph[stepKey] = [];
      if (serializedStepGraph) serializedStepGraph[stepKey] = [];
    } else {
      if (!this.#stepGraph[stepKey]) this.#stepGraph[stepKey] = [];
      this.#stepGraph.initial.push(graphEntry);
      this.#serializedStepGraph.initial.push(graphEntry);
    }
    this.#lastStepStack.push(stepKey);
    this.#lastBuilderType = "step";
    return this;
  }
  #__internalStep(next, config, internalUse) {
    const that = this;
    if (Array.isArray(next)) {
      const nextSteps = next.map(step2 => {
        if (isWorkflow(step2)) {
          const asStep = step2.toStep();
          return asStep;
        } else {
          return step2;
        }
      });
      nextSteps.forEach(step2 => this.#__internalStep(step2, config, internalUse));
      this.after(nextSteps);
      this.#__internalStep(new Step({
        id: `__after_${next.map(step2 => step2?.id ?? step2?.name).join("_")}`,
        execute: async () => {
          return {
            success: true
          };
        }
      }), void 0, internalUse);
      return this;
    }
    const {
      variables = {}
    } = config || {};
    const requiredData = {};
    for (const [key, variable] of Object.entries(variables)) {
      if (variable && isVariableReference(variable)) {
        requiredData[key] = variable;
      }
    }
    const step = isWorkflow(next) ?
    // @ts-ignore
    workflowToStep(next, {
      mastra: this.#mastra
    }) : next;
    const stepKey = this.#makeStepKey(step, config);
    const when = config?.["#internal"]?.when || config?.when;
    const graphEntry = {
      step,
      config: {
        ...this.#makeStepDef(stepKey),
        ...config,
        loopLabel: config?.["#internal"]?.loopLabel,
        loopType: config?.["#internal"]?.loopType,
        serializedWhen: typeof when === "function" ? when.toString() : when,
        data: requiredData
      },
      get id() {
        return that.#makeStepKey(this.step, this.config);
      }
    };
    this.#steps[stepKey] = graphEntry;
    const parentStepKey = this.#getParentStepKey();
    const stepGraph = this.#stepSubscriberGraph[parentStepKey || ""];
    const serializedStepGraph = this.#serializedStepSubscriberGraph[parentStepKey || ""];
    if (parentStepKey && stepGraph) {
      if (!stepGraph.initial.some(step2 => step2.step.id === stepKey)) {
        stepGraph.initial.push(graphEntry);
        if (serializedStepGraph) serializedStepGraph.initial.push(graphEntry);
      }
      stepGraph[stepKey] = [];
      if (serializedStepGraph) serializedStepGraph[stepKey] = [];
    } else {
      if (!this.#stepGraph[stepKey]) this.#stepGraph[stepKey] = [];
      this.#stepGraph.initial.push(graphEntry);
      this.#serializedStepGraph.initial.push(graphEntry);
    }
    this.#lastStepStack.push(stepKey);
    this.#lastBuilderType = "step";
    return this;
  }
  #makeStepKey(step, config) {
    if (typeof step === "string") return step;
    return `${config?.id ?? step.id ?? step.name}`;
  }
  then(next, config) {
    const that = this;
    if (Array.isArray(next)) {
      const lastStep = this.#steps[this.#lastStepStack[this.#lastStepStack.length - 1] ?? ""];
      if (!lastStep) {
        throw new Error("Condition requires a step to be executed after");
      }
      this.after(lastStep.step);
      const nextSteps = next.map(step2 => {
        if (isWorkflow(step2)) {
          return workflowToStep(step2, {
            mastra: this.#mastra
          });
        }
        if (isAgent(step2)) {
          return agentToStep(step2);
        }
        return step2;
      });
      nextSteps.forEach(step2 => this.step(step2, config));
      this.step(new Step({
        // @ts-ignore
        id: `__after_${next.map(step2 => step2?.id ?? step2?.name).join("_")}`,
        execute: async () => {
          return {
            success: true
          };
        }
      }));
      return this;
    }
    const {
      variables = {}
    } = config || {};
    const requiredData = {};
    for (const [key, variable] of Object.entries(variables)) {
      if (variable && isVariableReference(variable)) {
        requiredData[key] = variable;
      }
    }
    const lastStepKey = this.#lastStepStack[this.#lastStepStack.length - 1];
    const step = isWorkflow(next) ? workflowToStep(next, {
      mastra: this.#mastra
    }) : isAgent(next) ? agentToStep(next) : next;
    const stepKey = this.#makeStepKey(step, config);
    const when = config?.["#internal"]?.when || config?.when;
    const graphEntry = {
      step,
      config: {
        ...this.#makeStepDef(stepKey),
        ...config,
        loopLabel: config?.["#internal"]?.loopLabel,
        loopType: config?.["#internal"]?.loopType,
        serializedWhen: typeof when === "function" ? when.toString() : when,
        data: requiredData
      },
      get id() {
        return that.#makeStepKey(this.step, this.config);
      }
    };
    this.#steps[stepKey] = graphEntry;
    if (!lastStepKey) return this;
    const parentStepKey = this.#getParentStepKey();
    const stepGraph = this.#stepSubscriberGraph[parentStepKey || ""];
    const serializedStepGraph = this.#serializedStepSubscriberGraph[parentStepKey || ""];
    if (parentStepKey && this.#lastBuilderType === "after") {
      return this.step(step, config);
    }
    if (parentStepKey && stepGraph && stepGraph[lastStepKey]) {
      stepGraph[lastStepKey].push(graphEntry);
      if (serializedStepGraph && serializedStepGraph[lastStepKey]) serializedStepGraph[lastStepKey].push(graphEntry);
    } else {
      if (!this.#stepGraph[lastStepKey]) this.#stepGraph[lastStepKey] = [];
      if (!this.#serializedStepGraph[lastStepKey]) this.#serializedStepGraph[lastStepKey] = [];
      this.#stepGraph[lastStepKey].push(graphEntry);
      this.#serializedStepGraph[lastStepKey].push(graphEntry);
    }
    this.#lastBuilderType = "then";
    return this;
  }
  loop(applyOperator, condition, fallbackStep, loopType, variables) {
    const lastStepKey = this.#lastStepStack[this.#lastStepStack.length - 1];
    if (!lastStepKey) return this;
    const fallbackStepKey = this.#makeStepKey(fallbackStep);
    const fallbackStepNode = {
      step: fallbackStep,
      config: {
        ...this.#makeStepDef(fallbackStepKey)
      },
      get id() {
        return fallbackStepKey;
      }
    };
    this.#steps[fallbackStepKey] = fallbackStepNode;
    const checkStepKey = `__${fallbackStepKey}_${loopType}_loop_check`;
    const checkStep = {
      id: checkStepKey,
      execute: async ({
        context
      }) => {
        if (typeof condition === "function") {
          const result = await condition({
            context
          });
          switch (loopType) {
            case "while":
              return {
                status: result ? "continue" : "complete"
              };
            case "until":
              return {
                status: result ? "complete" : "continue"
              };
            default:
              throw new Error(`Invalid loop type: ${loopType}`);
          }
        }
        if (condition && "ref" in condition) {
          const {
            ref,
            query
          } = condition;
          const stepId = typeof ref.step === "string" ? ref.step : "id" in ref.step ? ref.step.id : null;
          if (!stepId) {
            return {
              status: "continue"
            };
          }
          const stepOutput = context.steps?.[stepId]?.output;
          if (!stepOutput) {
            return {
              status: "continue"
            };
          }
          const value = ref.path.split(".").reduce((obj, key) => obj?.[key], stepOutput);
          const operator = Object.keys(query)[0];
          const target = query[operator];
          return applyOperator(operator, value, target);
        }
        return {
          status: "continue"
        };
      },
      outputSchema: zod.z.object({
        status: zod.z.enum(["continue", "complete"])
      })
    };
    const checkStepNode = {
      step: checkStep,
      config: {
        ...this.#makeStepDef(checkStepKey)
      },
      get id() {
        return checkStepKey;
      }
    };
    this.#steps[checkStepKey] = checkStepNode;
    const loopFinishedStepKey = `__${fallbackStepKey}_${loopType}_loop_finished`;
    const loopFinishedStep = {
      id: loopFinishedStepKey,
      execute: async () => {
        return {
          success: true
        };
      }
    };
    const loopFinishedStepNode = {
      step: loopFinishedStep,
      config: {
        ...this.#makeStepDef(loopFinishedStepKey)
      },
      get id() {
        return loopFinishedStepKey;
      }
    };
    this.#steps[loopFinishedStepKey] = loopFinishedStepNode;
    this.then(checkStep, {
      id: checkStepKey,
      "#internal": {
        loopLabel: `${fallbackStepKey} ${loopType} loop check`
      }
    });
    this.after(checkStep);
    this.#__internalStep(fallbackStep, {
      when: async ({
        context
      }) => {
        const checkStepResult = context.steps?.[checkStepKey];
        if (checkStepResult?.status !== "success") {
          return "abort" /* ABORT */;
        }
        const status = checkStepResult?.output?.status;
        return status === "continue" ? "continue" /* CONTINUE */ : "continue_failed" /* CONTINUE_FAILED */;
      },
      variables,
      "#internal": {
        // @ts-ignore
        when: condition,
        loopType
      }
    }).then(checkStep, {
      id: checkStepKey,
      "#internal": {
        loopLabel: `${fallbackStepKey} ${loopType} loop check`
      }
    });
    this.#__internalStep(loopFinishedStep, {
      id: loopFinishedStepKey,
      when: async ({
        context
      }) => {
        const checkStepResult = context.steps?.[checkStepKey];
        if (checkStepResult?.status !== "success") {
          return "continue_failed" /* CONTINUE_FAILED */;
        }
        const status = checkStepResult?.output?.status;
        return status === "complete" ? "continue" /* CONTINUE */ : "continue_failed" /* CONTINUE_FAILED */;
      },
      "#internal": {
        loopLabel: `${fallbackStepKey} ${loopType} loop finished`,
        //@ts-ignore
        loopType
      }
    });
    return this;
  }
  while(condition, fallbackStep, variables) {
    const applyOperator = (operator, value, target) => {
      switch (operator) {
        case "$eq":
          return {
            status: value !== target ? "complete" : "continue"
          };
        case "$ne":
          return {
            status: value === target ? "complete" : "continue"
          };
        case "$gt":
          return {
            status: value <= target ? "complete" : "continue"
          };
        case "$gte":
          return {
            status: value < target ? "complete" : "continue"
          };
        case "$lt":
          return {
            status: value >= target ? "complete" : "continue"
          };
        case "$lte":
          return {
            status: value > target ? "complete" : "continue"
          };
        default:
          return {
            status: "continue"
          };
      }
    };
    const res = this.loop(applyOperator, condition, fallbackStep, "while", variables);
    this.#lastBuilderType = "while";
    return res;
  }
  until(condition, fallbackStep, variables) {
    const applyOperator = (operator, value, target) => {
      switch (operator) {
        case "$eq":
          return {
            status: value === target ? "complete" : "continue"
          };
        case "$ne":
          return {
            status: value !== target ? "complete" : "continue"
          };
        case "$gt":
          return {
            status: value > target ? "complete" : "continue"
          };
        case "$gte":
          return {
            status: value >= target ? "complete" : "continue"
          };
        case "$lt":
          return {
            status: value < target ? "complete" : "continue"
          };
        case "$lte":
          return {
            status: value <= target ? "complete" : "continue"
          };
        default:
          return {
            status: "continue"
          };
      }
    };
    const res = this.loop(applyOperator, condition, fallbackStep, "until", variables);
    this.#lastBuilderType = "until";
    return res;
  }
  if(condition, ifStep, elseStep) {
    this.#ifCount++;
    const lastStep = this.#getLastStep({
      if_else_check: this.#lastBuilderType !== "else"
    });
    if (!lastStep) {
      throw new Error("Condition requires a step to be executed after");
    }
    this.after(lastStep.step);
    if (ifStep) {
      const _ifStep = isWorkflow(ifStep) ? workflowToStep(ifStep, {
        mastra: this.#mastra
      }) : ifStep;
      this.step(_ifStep, {
        id: _ifStep.id,
        when: condition
      });
      if (elseStep) {
        const _elseStep = isWorkflow(elseStep) ? workflowToStep(elseStep, {
          mastra: this.#mastra
        }) : elseStep;
        this.step(_elseStep, {
          id: _elseStep.id,
          when: typeof condition === "function" ? async payload => {
            const result = await condition(payload);
            return !result;
          } : {
            not: condition
          }
        });
        this.after([_ifStep, _elseStep]);
      } else {
        this.after(_ifStep);
      }
      this.step(new Step({
        id: `${lastStep.id}_if_else`,
        execute: async () => {
          return {
            executed: true
          };
        }
      }));
      return this;
    }
    const ifStepKey = `__${lastStep.id}_if_${this.#ifCount}`;
    this.step({
      id: ifStepKey,
      execute: async () => {
        return {
          executed: true
        };
      }
    }, {
      id: ifStepKey,
      when: condition
    });
    const elseStepKey = `__${lastStep.id}_else_${this.#ifCount}`;
    this.#ifStack.push({
      condition,
      elseStepKey,
      condStep: lastStep.step
    });
    this.#lastBuilderType = "if";
    return this;
  }
  else() {
    const activeCondition = this.#ifStack.pop();
    if (!activeCondition) {
      throw new Error("No active condition found");
    }
    this.after(activeCondition.condStep).step({
      id: activeCondition.elseStepKey,
      execute: async () => {
        return {
          executed: true
        };
      }
    }, {
      id: activeCondition.elseStepKey,
      when: typeof activeCondition.condition === "function" ? async payload => {
        const result = await activeCondition.condition(payload);
        return !result;
      } : {
        not: activeCondition.condition
      }
    });
    this.#lastBuilderType = "else";
    return this;
  }
  after(steps) {
    const stepsArray = Array.isArray(steps) ? steps : [steps];
    const stepKeys = stepsArray.map(step => this.#makeStepKey(step));
    const compoundKey = stepKeys.join("&&");
    this.#afterStepStack.push(compoundKey);
    if (!this.#stepSubscriberGraph[compoundKey]) {
      this.#stepSubscriberGraph[compoundKey] = {
        initial: []
      };
      this.#serializedStepSubscriberGraph[compoundKey] = {
        initial: []
      };
    }
    this.#lastBuilderType = "after";
    return this;
  }
  afterEvent(eventName) {
    const event = this.events?.[eventName];
    if (!event) {
      throw new Error(`Event ${eventName} not found`);
    }
    const lastStep = this.#steps[this.#lastStepStack[this.#lastStepStack.length - 1] ?? ""];
    if (!lastStep) {
      throw new Error("Condition requires a step to be executed after");
    }
    const eventStepKey = `__${eventName}_event`;
    const eventStep = new Step({
      id: eventStepKey,
      execute: async ({
        context,
        suspend
      }) => {
        if (context.inputData?.resumedEvent) {
          return {
            executed: true,
            resumedEvent: context.inputData?.resumedEvent
          };
        }
        await suspend();
        return {
          executed: false
        };
      }
    });
    this.after(lastStep.step).step(eventStep).after(eventStep);
    this.#lastBuilderType = "afterEvent";
    return this;
  }
  /**
   * Executes the workflow with the given trigger data
   * @param triggerData - Initial data to start the workflow with
   * @returns Promise resolving to workflow results or rejecting with error
   * @throws Error if trigger schema validation fails
   */
  createRun({
    runId,
    events
  } = {}) {
    const run = new WorkflowInstance({
      logger: this.logger,
      name: this.name,
      mastra: this.#mastra,
      retryConfig: this.#retryConfig,
      steps: this.#steps,
      runId,
      stepGraph: this.#stepGraph,
      stepSubscriberGraph: this.#stepSubscriberGraph,
      onStepTransition: this.#onStepTransition,
      resultMapping: this.resultMapping,
      onFinish: () => {
        this.#runs.delete(run.runId);
      },
      events
    });
    this.#runs.set(run.runId, run);
    return {
      start: run.start.bind(run),
      runId: run.runId,
      watch: run.watch.bind(run),
      resume: run.resume.bind(run),
      resumeWithEvent: run.resumeWithEvent.bind(run)
    };
  }
  /**
   * Gets a workflow run instance by ID
   * @param runId - ID of the run to retrieve
   * @returns The workflow run instance if found, undefined otherwise
   */
  getRun(runId) {
    return this.#runs.get(runId);
  }
  /**
   * Rebuilds the machine with the current steps configuration and validates the workflow
   *
   * This is the last step of a workflow builder method chain
   * @throws Error if validation fails
   *
   * @returns this instance for method chaining
   */
  commit() {
    return this;
  }
  // record all object paths that leads to a suspended state
  #getSuspendedPaths({
    value,
    path,
    suspendedPaths
  }) {
    if (typeof value === "string") {
      if (value === "suspended") {
        suspendedPaths.add(path);
      }
    } else {
      Object.keys(value).forEach(key => this.#getSuspendedPaths({
        value: value[key],
        path: path ? `${path}.${key}` : key,
        suspendedPaths
      }));
    }
  }
  async getWorkflowRuns(args) {
    const storage = this.#mastra?.getStorage();
    if (!storage) {
      this.logger.debug("Cannot get workflow runs. Mastra engine is not initialized");
      return {
        runs: [],
        total: 0
      };
    }
    return storage.getWorkflowRuns({
      workflowName: this.name,
      ...(args ?? {})
    });
  }
  getExecutionSpan(runId) {
    return this.#runs.get(runId)?.executionSpan;
  }
  #getParentStepKey({
    loop_check = false,
    if_else_check = false
  } = {}) {
    for (let i = this.#afterStepStack.length - 1; i >= 0; i--) {
      const stepKey = this.#afterStepStack[i];
      if (!stepKey) continue;
      const isValidStep = this.#stepSubscriberGraph[stepKey] && (!loop_check || !stepKey.includes("loop_check")) && (!if_else_check || !isConditionalKey(stepKey));
      if (isValidStep) {
        return stepKey;
      }
    }
    return void 0;
  }
  #getLastStep({
    if_else_check
  }) {
    for (let i = this.#lastStepStack.length - 1; i >= 0; i--) {
      const stepKey = this.#lastStepStack[i];
      if (!stepKey) continue;
      const step = this.#steps[stepKey];
      const isInvalidStep = !step || if_else_check && isConditionalKey(stepKey);
      if (isInvalidStep) continue;
      return step;
    }
    return void 0;
  }
  #makeStepDef(stepId) {
    const executeStep = (handler2, spanName, attributes) => {
      return async data => {
        return await api.context.with(api.trace.setSpan(api.context.active(), this.getExecutionSpan(attributes?.runId ?? data?.runId)), async () => {
          if (this?.telemetry) {
            return this.telemetry.traceMethod(handler2, {
              spanName,
              attributes
            })(data);
          } else {
            return handler2(data);
          }
        });
      };
    };
    const handler = async ({
      context,
      ...rest
    }) => {
      const targetStep = this.#steps[stepId];
      if (!targetStep) throw new Error(`Step not found`);
      const {
        payload = {},
        execute = async () => {}
      } = targetStep.step;
      const finalAction = this.telemetry ? executeStep(execute, `workflow.${this.name}.action.${stepId}`, {
        componentName: this.name,
        runId: rest.runId
      }) : execute;
      return finalAction ? await finalAction({
        context: {
          ...context,
          inputData: {
            ...(context?.inputData || {}),
            ...payload
          }
        },
        ...rest
      }) : {};
    };
    const finalHandler = ({
      context,
      ...rest
    }) => {
      if (this.getExecutionSpan(rest?.runId)) {
        return executeStep(handler, `workflow.${this.name}.step.${stepId}`, {
          componentName: this.name,
          runId: rest?.runId
        })({
          context,
          ...rest
        });
      }
      return handler({
        context,
        ...rest
      });
    };
    return {
      handler: finalHandler,
      data: {}
    };
  }
  #getActivePathsAndStatus(value) {
    const paths = [];
    const traverse = (current, path = []) => {
      for (const [key, value2] of Object.entries(current)) {
        const currentPath = [...path, key];
        if (typeof value2 === "string") {
          paths.push({
            stepPath: currentPath,
            stepId: key,
            status: value2
          });
        } else if (typeof value2 === "object" && value2 !== null) {
          traverse(value2, currentPath);
        }
      }
    };
    traverse(value);
    return paths;
  }
  async getState(runId) {
    const run = this.#runs.get(runId);
    if (run) {
      return run.getState();
    }
    const storage = this.#mastra?.getStorage();
    const storedSnapshot = await storage?.loadWorkflowSnapshot({
      runId,
      workflowName: this.name
    });
    if (storedSnapshot) {
      const parsed = storedSnapshot;
      const m = this.#getActivePathsAndStatus(parsed.value);
      return {
        runId,
        value: parsed.value,
        context: parsed.context,
        activePaths: m,
        timestamp: Date.now()
      };
    }
    return null;
  }
  async resume({
    runId,
    stepId,
    context: resumeContext,
    runtimeContext = new chunkLABUWBKX_cjs.RuntimeContext()
  }) {
    this.logger.warn(`Please use 'resume' on the 'createRun' call instead, resume is deprecated`);
    const activeRun = this.#runs.get(runId);
    if (activeRun) {
      return activeRun.resume({
        stepId,
        context: resumeContext,
        runtimeContext
      });
    }
    const run = this.createRun({
      runId
    });
    return run.resume({
      stepId,
      context: resumeContext,
      runtimeContext
    });
  }
  watch(onTransition) {
    this.logger.warn(`Please use 'watch' on the 'createRun' call instead, watch is deprecated`);
    this.#onStepTransition.add(onTransition);
    return () => {
      this.#onStepTransition.delete(onTransition);
    };
  }
  async resumeWithEvent(runId, eventName, data) {
    this.logger.warn(`Please use 'resumeWithEvent' on the 'createRun' call instead, resumeWithEvent is deprecated`);
    const event = this.events?.[eventName];
    if (!event) {
      throw new Error(`Event ${eventName} not found`);
    }
    const results = await this.resume({
      runId,
      stepId: `__${eventName}_event`,
      context: {
        resumedEvent: data
      },
      runtimeContext: new chunkLABUWBKX_cjs.RuntimeContext()
    });
    return results;
  }
  __registerMastra(mastra) {
    this.#mastra = mastra;
  }
  __registerPrimitives(p) {
    if (p.telemetry) {
      this.__setTelemetry(p.telemetry);
    }
    if (p.logger) {
      this.__setLogger(p.logger);
    }
  }
  get stepGraph() {
    return this.#stepGraph;
  }
  get stepSubscriberGraph() {
    return this.#stepSubscriberGraph;
  }
  get serializedStepGraph() {
    return this.#serializedStepGraph;
  }
  get serializedStepSubscriberGraph() {
    return this.#serializedStepSubscriberGraph;
  }
  get steps() {
    return Object.entries(this.#steps).reduce((acc, [key, step]) => {
      acc[key] = step.step;
      return acc;
    }, {});
  }
  setNested(isNested) {
    this.isNested = isNested;
  }
  toStep() {
    const x = workflowToStep(this, {
      mastra: this.#mastra
    });
    return new Step(x);
  }
};

exports.Step = Step;
exports.WhenConditionReturnValue = WhenConditionReturnValue;
exports.Workflow = Workflow;
exports.agentToStep = agentToStep;
exports.getActivePathsAndStatus = getActivePathsAndStatus;
exports.getResultActivePaths = getResultActivePaths;
exports.getStepResult = getStepResult;
exports.getSuspendedPaths = getSuspendedPaths;
exports.isAgent = isAgent;
exports.isConditionalKey = isConditionalKey;
exports.isErrorEvent = isErrorEvent;
exports.isFinalState = isFinalState;
exports.isLimboState = isLimboState;
exports.isTransitionEvent = isTransitionEvent;
exports.isVariableReference = isVariableReference;
exports.isWorkflow = isWorkflow;
exports.mergeChildValue = mergeChildValue;
exports.recursivelyCheckForFinalState = recursivelyCheckForFinalState;
exports.resolveVariables = resolveVariables;
exports.updateStepInHierarchy = updateStepInHierarchy;
exports.workflowToStep = workflowToStep;