@mastra/core 0.16.4-alpha.2 → 0.17.0-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +55 -0
- package/dist/agent/agent.d.ts +17 -2
- package/dist/agent/agent.d.ts.map +1 -1
- package/dist/agent/index.cjs +11 -11
- package/dist/agent/index.js +2 -2
- package/dist/agent/input-processor/index.cjs +6 -6
- package/dist/agent/input-processor/index.js +1 -1
- package/dist/agent/message-list/index.d.ts +1 -1
- package/dist/agent/message-list/index.d.ts.map +1 -1
- package/dist/agent/types.d.ts +15 -2
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/ai-tracing/exporters/default.d.ts +1 -0
- package/dist/ai-tracing/exporters/default.d.ts.map +1 -1
- package/dist/ai-tracing/index.cjs +35 -31
- package/dist/ai-tracing/index.js +1 -1
- package/dist/ai-tracing/span_processors/sensitive-data-filter.d.ts +7 -1
- package/dist/ai-tracing/span_processors/sensitive-data-filter.d.ts.map +1 -1
- package/dist/ai-tracing/spans/base.d.ts +2 -1
- package/dist/ai-tracing/spans/base.d.ts.map +1 -1
- package/dist/ai-tracing/types.d.ts +35 -4
- package/dist/ai-tracing/types.d.ts.map +1 -1
- package/dist/ai-tracing/utils.d.ts +3 -2
- package/dist/ai-tracing/utils.d.ts.map +1 -1
- package/dist/bundler/index.cjs +2 -2
- package/dist/bundler/index.d.ts +8 -2
- package/dist/bundler/index.d.ts.map +1 -1
- package/dist/bundler/index.js +1 -1
- package/dist/{chunk-AWILTHBM.js → chunk-2PQSZI63.js} +3 -3
- package/dist/{chunk-AWILTHBM.js.map → chunk-2PQSZI63.js.map} +1 -1
- package/dist/{chunk-4VP3M5T7.js → chunk-4OT7CXAS.js} +17 -4
- package/dist/chunk-4OT7CXAS.js.map +1 -0
- package/dist/{chunk-O5GOFG6A.js → chunk-4VHC2F5H.js} +10 -8
- package/dist/chunk-4VHC2F5H.js.map +1 -0
- package/dist/{chunk-VVH4BOE4.cjs → chunk-6MDSS7WL.cjs} +4 -4
- package/dist/{chunk-VVH4BOE4.cjs.map → chunk-6MDSS7WL.cjs.map} +1 -1
- package/dist/{chunk-YLR7PB3B.cjs → chunk-BGAJ72HJ.cjs} +104 -86
- package/dist/chunk-BGAJ72HJ.cjs.map +1 -0
- package/dist/{chunk-YYZT5JKX.js → chunk-BY37WSX5.js} +5 -5
- package/dist/{chunk-YYZT5JKX.js.map → chunk-BY37WSX5.js.map} +1 -1
- package/dist/{chunk-ERRIEUC2.cjs → chunk-CP4TZ4HO.cjs} +129 -48
- package/dist/chunk-CP4TZ4HO.cjs.map +1 -0
- package/dist/{chunk-W4GRW6AV.cjs → chunk-F3XF7MEZ.cjs} +12 -12
- package/dist/{chunk-W4GRW6AV.cjs.map → chunk-F3XF7MEZ.cjs.map} +1 -1
- package/dist/{chunk-PY4MHJTE.js → chunk-G366B5BY.js} +2 -2
- package/dist/chunk-G366B5BY.js.map +1 -0
- package/dist/{chunk-GJKL73EJ.cjs → chunk-HBQSSMAD.cjs} +13 -11
- package/dist/chunk-HBQSSMAD.cjs.map +1 -0
- package/dist/{chunk-UIFZI5XX.cjs → chunk-HZGYVRVN.cjs} +21 -8
- package/dist/chunk-HZGYVRVN.cjs.map +1 -0
- package/dist/{chunk-DUUXEPE5.cjs → chunk-MRZHPP3G.cjs} +103 -5
- package/dist/chunk-MRZHPP3G.cjs.map +1 -0
- package/dist/{chunk-ODLGLX2R.js → chunk-PL3B3FZM.js} +129 -49
- package/dist/chunk-PL3B3FZM.js.map +1 -0
- package/dist/{chunk-LVVAUDVQ.cjs → chunk-QHDT3QQC.cjs} +2 -2
- package/dist/chunk-QHDT3QQC.cjs.map +1 -0
- package/dist/chunk-QPOJZU26.cjs +14 -0
- package/dist/{chunk-ELKY3FEM.cjs.map → chunk-QPOJZU26.cjs.map} +1 -1
- package/dist/{chunk-VH3RNDZA.cjs → chunk-RNJ4GD7U.cjs} +6 -6
- package/dist/{chunk-VH3RNDZA.cjs.map → chunk-RNJ4GD7U.cjs.map} +1 -1
- package/dist/{chunk-ES5UWPHJ.js → chunk-TUXCO343.js} +17 -6
- package/dist/chunk-TUXCO343.js.map +1 -0
- package/dist/{chunk-CF3TI576.js → chunk-UWUM3F3X.js} +84 -66
- package/dist/chunk-UWUM3F3X.js.map +1 -0
- package/dist/{chunk-BVE3UPHV.js → chunk-VXJFKEON.js} +4 -4
- package/dist/{chunk-BVE3UPHV.js.map → chunk-VXJFKEON.js.map} +1 -1
- package/dist/{chunk-FTDM75SW.cjs → chunk-X3MOJJYH.cjs} +20 -9
- package/dist/chunk-X3MOJJYH.cjs.map +1 -0
- package/dist/{chunk-LVKX346H.js → chunk-XKVDOO2O.js} +3 -3
- package/dist/{chunk-LVKX346H.js.map → chunk-XKVDOO2O.js.map} +1 -1
- package/dist/{chunk-ZDMAOD35.js → chunk-XRJDA7BI.js} +102 -4
- package/dist/chunk-XRJDA7BI.js.map +1 -0
- package/dist/deployer/index.cjs +2 -2
- package/dist/deployer/index.js +1 -1
- package/dist/index.cjs +40 -40
- package/dist/index.js +8 -8
- package/dist/llm/model/model.d.ts +3 -1
- package/dist/llm/model/model.d.ts.map +1 -1
- package/dist/llm/model/model.loop.d.ts +6 -4
- package/dist/llm/model/model.loop.d.ts.map +1 -1
- package/dist/llm/model/model.loop.types.d.ts +1 -1
- package/dist/llm/model/model.loop.types.d.ts.map +1 -1
- package/dist/llm/model/shared.types.d.ts +5 -0
- package/dist/llm/model/shared.types.d.ts.map +1 -1
- package/dist/loop/index.cjs +2 -2
- package/dist/loop/index.js +1 -1
- package/dist/loop/loop.d.ts +1 -1
- package/dist/loop/loop.d.ts.map +1 -1
- package/dist/loop/test-utils/fullStream.d.ts.map +1 -1
- package/dist/loop/test-utils/generateText.d.ts.map +1 -1
- package/dist/loop/test-utils/options.d.ts.map +1 -1
- package/dist/loop/test-utils/resultObject.d.ts.map +1 -1
- package/dist/loop/test-utils/streamObject.d.ts.map +1 -1
- package/dist/loop/test-utils/textStream.d.ts.map +1 -1
- package/dist/loop/test-utils/tools.d.ts.map +1 -1
- package/dist/loop/test-utils/utils.d.ts +4 -3
- package/dist/loop/test-utils/utils.d.ts.map +1 -1
- package/dist/loop/types.d.ts +2 -2
- package/dist/loop/types.d.ts.map +1 -1
- package/dist/loop/workflows/agentic-execution/index.d.ts +836 -0
- package/dist/loop/workflows/agentic-execution/index.d.ts.map +1 -0
- package/dist/loop/workflows/agentic-execution/llm-execution-step.d.ts +559 -0
- package/dist/loop/workflows/agentic-execution/llm-execution-step.d.ts.map +1 -0
- package/dist/loop/workflows/agentic-execution/llm-mapping-step.d.ts +311 -0
- package/dist/loop/workflows/agentic-execution/llm-mapping-step.d.ts.map +1 -0
- package/dist/loop/{workflow → workflows/agentic-execution}/tool-call-step.d.ts +16 -16
- package/dist/loop/workflows/agentic-execution/tool-call-step.d.ts.map +1 -0
- package/dist/loop/workflows/agentic-loop/index.d.ts +842 -0
- package/dist/loop/workflows/agentic-loop/index.d.ts.map +1 -0
- package/dist/loop/workflows/run-state.d.ts.map +1 -0
- package/dist/loop/workflows/schema.d.ts +439 -0
- package/dist/loop/workflows/schema.d.ts.map +1 -0
- package/dist/loop/{workflow → workflows}/stream.d.ts +1 -1
- package/dist/loop/workflows/stream.d.ts.map +1 -0
- package/dist/mastra/index.cjs +2 -2
- package/dist/mastra/index.js +1 -1
- package/dist/memory/index.cjs +4 -4
- package/dist/memory/index.js +1 -1
- package/dist/network/index.cjs +2 -2
- package/dist/network/index.js +1 -1
- package/dist/network/vNext/index.cjs +34 -34
- package/dist/network/vNext/index.cjs.map +1 -1
- package/dist/network/vNext/index.js +7 -7
- package/dist/network/vNext/index.js.map +1 -1
- package/dist/processors/index.cjs +8 -8
- package/dist/processors/index.js +2 -2
- package/dist/relevance/index.cjs +4 -4
- package/dist/relevance/index.js +1 -1
- package/dist/scores/base.d.ts.map +1 -1
- package/dist/scores/index.cjs +8 -8
- package/dist/scores/index.js +1 -1
- package/dist/server/types.d.ts +7 -0
- package/dist/server/types.d.ts.map +1 -1
- package/dist/storage/index.cjs +3 -3
- package/dist/storage/index.js +1 -1
- package/dist/stream/aisdk/v5/execute.d.ts +2 -1
- package/dist/stream/aisdk/v5/execute.d.ts.map +1 -1
- package/dist/stream/aisdk/v5/output-helpers.d.ts +1 -5
- package/dist/stream/aisdk/v5/output-helpers.d.ts.map +1 -1
- package/dist/stream/aisdk/v5/output.d.ts +2 -10
- package/dist/stream/aisdk/v5/output.d.ts.map +1 -1
- package/dist/stream/base/output-format-handlers.d.ts.map +1 -1
- package/dist/stream/base/output.d.ts +1 -5
- package/dist/stream/base/output.d.ts.map +1 -1
- package/dist/stream/index.cjs +3 -3
- package/dist/stream/index.js +1 -1
- package/dist/stream/types.d.ts +8 -2
- package/dist/stream/types.d.ts.map +1 -1
- package/dist/test-utils/llm-mock.cjs +2 -2
- package/dist/test-utils/llm-mock.js +1 -1
- package/dist/utils.cjs +17 -17
- package/dist/utils.d.ts +2 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +1 -1
- package/dist/workflows/default.d.ts.map +1 -1
- package/dist/workflows/evented/index.cjs +10 -10
- package/dist/workflows/evented/index.js +1 -1
- package/dist/workflows/evented/workflow.d.ts.map +1 -1
- package/dist/workflows/execution-engine.d.ts +7 -2
- package/dist/workflows/execution-engine.d.ts.map +1 -1
- package/dist/workflows/index.cjs +10 -10
- package/dist/workflows/index.js +1 -1
- package/dist/workflows/legacy/index.cjs +22 -22
- package/dist/workflows/legacy/index.js +1 -1
- package/dist/workflows/types.d.ts +6 -1
- package/dist/workflows/types.d.ts.map +1 -1
- package/dist/workflows/workflow.d.ts +12 -10
- package/dist/workflows/workflow.d.ts.map +1 -1
- package/package.json +7 -6
- package/dist/chunk-4VP3M5T7.js.map +0 -1
- package/dist/chunk-CF3TI576.js.map +0 -1
- package/dist/chunk-DUUXEPE5.cjs.map +0 -1
- package/dist/chunk-ELKY3FEM.cjs +0 -14
- package/dist/chunk-ERRIEUC2.cjs.map +0 -1
- package/dist/chunk-ES5UWPHJ.js.map +0 -1
- package/dist/chunk-FTDM75SW.cjs.map +0 -1
- package/dist/chunk-GJKL73EJ.cjs.map +0 -1
- package/dist/chunk-LVVAUDVQ.cjs.map +0 -1
- package/dist/chunk-O5GOFG6A.js.map +0 -1
- package/dist/chunk-ODLGLX2R.js.map +0 -1
- package/dist/chunk-PY4MHJTE.js.map +0 -1
- package/dist/chunk-UIFZI5XX.cjs.map +0 -1
- package/dist/chunk-YLR7PB3B.cjs.map +0 -1
- package/dist/chunk-ZDMAOD35.js.map +0 -1
- package/dist/loop/workflow/llm-execution.d.ts +0 -81
- package/dist/loop/workflow/llm-execution.d.ts.map +0 -1
- package/dist/loop/workflow/outer-llm-step.d.ts +0 -44
- package/dist/loop/workflow/outer-llm-step.d.ts.map +0 -1
- package/dist/loop/workflow/run-state.d.ts.map +0 -1
- package/dist/loop/workflow/schema.d.ts +0 -92
- package/dist/loop/workflow/schema.d.ts.map +0 -1
- package/dist/loop/workflow/stream.d.ts.map +0 -1
- package/dist/loop/workflow/tool-call-step.d.ts.map +0 -1
- /package/dist/loop/{workflow → workflows}/run-state.d.ts +0 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { DefaultVoice } from './chunk-QQIBOVFQ.js';
|
|
2
2
|
import { STREAM_FORMAT_SYMBOL, EMITTER_SYMBOL } from './chunk-NLNKQD2T.js';
|
|
3
3
|
import { InstrumentClass, Telemetry } from './chunk-TLJPVRO5.js';
|
|
4
|
-
import { MastraLLMV1 } from './chunk-
|
|
5
|
-
import { MessageList, DefaultGeneratedFile, DefaultGeneratedFileWithType } from './chunk-
|
|
4
|
+
import { MastraLLMV1 } from './chunk-4VHC2F5H.js';
|
|
5
|
+
import { MessageList, DefaultGeneratedFile, DefaultGeneratedFileWithType } from './chunk-XRJDA7BI.js';
|
|
6
6
|
import { executeHook } from './chunk-TTELJD4F.js';
|
|
7
7
|
import { zodToJsonSchema } from './chunk-PJKCPRYF.js';
|
|
8
|
-
import { getValidTraceId, wrapMastra, selectFields, getOrCreateSpan, ensureToolProperties, makeCoreTool, createMastraProxy, delay } from './chunk-
|
|
8
|
+
import { getValidTraceId, wrapMastra, selectFields, getOrCreateSpan, ensureToolProperties, makeCoreTool, createMastraProxy, delay } from './chunk-PL3B3FZM.js';
|
|
9
9
|
import { RuntimeContext } from './chunk-HLRWYUFN.js';
|
|
10
10
|
import { MastraError } from './chunk-MCOVMKIS.js';
|
|
11
11
|
import { ToolStream } from './chunk-A3QHQYMC.js';
|
|
@@ -13,7 +13,7 @@ import { Tool, createTool } from './chunk-BJGHUKKM.js';
|
|
|
13
13
|
import { MastraBase } from './chunk-6GF5M4GX.js';
|
|
14
14
|
import { RegisteredLogger, ConsoleLogger } from './chunk-X3GXU6TZ.js';
|
|
15
15
|
import { __commonJS, __toESM, __decoratorStart, __decorateElement, __runInitializers } from './chunk-3HXBPDKN.js';
|
|
16
|
-
import
|
|
16
|
+
import z5, { z } from 'zod';
|
|
17
17
|
import { getErrorMessage, TypeValidationError } from '@ai-sdk/provider-v5';
|
|
18
18
|
import { createTextStreamResponse, createUIMessageStreamResponse, createUIMessageStream, consumeStream, generateId, asSchema, parsePartialJson, isDeepEqualData, jsonSchema, tool, stepCountIs } from 'ai-v5';
|
|
19
19
|
import * as crypto2 from 'crypto';
|
|
@@ -73,12 +73,17 @@ var BaseFormatHandler=class{/**
|
|
|
73
73
|
* Whether to validate partial chunks. @planned
|
|
74
74
|
*/validatePartialChunks=false;/**
|
|
75
75
|
* Partial schema for validating partial chunks as they are streamed. @planned
|
|
76
|
-
*/partialSchema;constructor(schema,options={}){if(!schema){this.schema=void 0;}else if(schema&&typeof schema==="object"&&!schema.safeParse&&!schema.jsonSchema){this.schema=jsonSchema(schema);}else {this.schema=asSchema(schema);}if(options.validatePartialChunks){if(schema!==void 0&&"partial"in schema&&typeof schema.partial==="function"){this.validatePartialChunks=true;this.partialSchema=schema.partial();}}}
|
|
76
|
+
*/partialSchema;constructor(schema,options={}){if(!schema){this.schema=void 0;}else if(schema&&typeof schema==="object"&&!schema.safeParse&&!schema.jsonSchema){this.schema=jsonSchema(schema);}else {this.schema=asSchema(schema);}if(options.validatePartialChunks){if(schema!==void 0&&"partial"in schema&&typeof schema.partial==="function"){this.validatePartialChunks=true;this.partialSchema=schema.partial();}}}/**
|
|
77
|
+
* Preprocesses accumulated text to handle LLMs that wrap JSON in code blocks.
|
|
78
|
+
* Extracts content from the first complete valid ```json...``` code block or removes opening ```json prefix if no complete code block is found (streaming chunks).
|
|
79
|
+
* @param accumulatedText - Raw accumulated text from streaming
|
|
80
|
+
* @returns Processed text ready for JSON parsing
|
|
81
|
+
*/preprocessText(accumulatedText){let processedText=accumulatedText;if(processedText.includes("```json")){const match=processedText.match(/```json\s*\n?([\s\S]*?)\n?\s*```/);if(match&&match[1]){processedText=match[1].trim();}else {processedText=processedText.replace(/^```json\s*\n?/,"");}}return processedText;}};var ObjectFormatHandler=class extends BaseFormatHandler{type="object";async processPartialChunk({accumulatedText,previousObject}){const processedAccumulatedText=this.preprocessText(accumulatedText);const{value:currentObjectJson,state}=await parsePartialJson(processedAccumulatedText);if(this.validatePartialChunks&&this.partialSchema){const result=this.partialSchema?.safeParse(currentObjectJson);if(result.success&&result.data&&result.data!==void 0&&!isDeepEqualData(previousObject,result.data)){return {shouldEmit:true,emitValue:result.data,newPreviousResult:result.data};}return {shouldEmit:false};}if(currentObjectJson!==void 0&¤tObjectJson!==null&&typeof currentObjectJson==="object"&&!isDeepEqualData(previousObject,currentObjectJson)){return {shouldEmit:["successful-parse","repaired-parse"].includes(state),emitValue:currentObjectJson,newPreviousResult:currentObjectJson};}return {shouldEmit:false};}async validateAndTransformFinal(finalRawValue){if(!finalRawValue){return {success:false,error:new Error("No object generated: could not parse the response.")};}const rawValue=this.preprocessText(finalRawValue);const{value}=await parsePartialJson(rawValue);if(!this.schema){return {success:true,value};}try{const result=await safeValidateTypes({value,schema:this.schema});if(result.success){return {success:true,value:result.value};}else {return {success:false,error:result.error??new Error("Validation failed",{cause:result.error})};}}catch(error){return {success:false,error:error instanceof Error?error:new Error("Validation failed",{cause:error})};}}};var ArrayFormatHandler=class extends BaseFormatHandler{type="array";/** Previously filtered array to track changes */textPreviousFilteredArray=[];/** Whether we've emitted the initial empty array */hasEmittedInitialArray=false;async processPartialChunk({accumulatedText,previousObject}){const processedAccumulatedText=this.preprocessText(accumulatedText);const{value:currentObjectJson,state:parseState}=await parsePartialJson(processedAccumulatedText);if(currentObjectJson!==void 0&&!isDeepEqualData(previousObject,currentObjectJson)){const rawElements=currentObjectJson?.elements||[];const filteredElements=[];for(let i=0;i<rawElements.length;i++){const element=rawElements[i];if(i===rawElements.length-1&&parseState!=="successful-parse"){if(element&&typeof element==="object"&&Object.keys(element).length>0){filteredElements.push(element);}}else {if(element&&typeof element==="object"&&Object.keys(element).length>0){filteredElements.push(element);}}}if(!this.hasEmittedInitialArray){this.hasEmittedInitialArray=true;if(filteredElements.length===0){this.textPreviousFilteredArray=[];return {shouldEmit:true,emitValue:[],newPreviousResult:currentObjectJson};}}if(!isDeepEqualData(this.textPreviousFilteredArray,filteredElements)){this.textPreviousFilteredArray=[...filteredElements];return {shouldEmit:true,emitValue:filteredElements,newPreviousResult:currentObjectJson};}}return {shouldEmit:false};}async validateAndTransformFinal(_finalValue){const resultValue=this.textPreviousFilteredArray;if(!resultValue){return {success:false,error:new Error("No object generated: could not parse the response.")};}if(!this.schema){return {success:true,value:resultValue};}try{const result=await safeValidateTypes({value:resultValue,schema:this.schema});if(result.success){return {success:true,value:result.value};}else {return {success:false,error:result.error??new Error("Validation failed",{cause:result.error})};}}catch(error){return {success:false,error:error instanceof Error?error:new Error("Validation failed",{cause:error})};}}};var EnumFormatHandler=class extends BaseFormatHandler{type="enum";/** Previously emitted enum result to avoid duplicate emissions */textPreviousEnumResult;/**
|
|
77
82
|
* Finds the best matching enum value for a partial result string.
|
|
78
83
|
* If multiple values match, returns the partial string. If only one matches, returns that value.
|
|
79
84
|
* @param partialResult - Partial enum string from streaming
|
|
80
85
|
* @returns Best matching enum value or undefined if no matches
|
|
81
|
-
*/findBestEnumMatch(partialResult){if(!this.schema?.jsonSchema?.enum){return void 0;}const enumValues=this.schema.jsonSchema.enum;const possibleEnumValues=enumValues.filter(value=>typeof value==="string").filter(enumValue=>enumValue.startsWith(partialResult));if(possibleEnumValues.length===0){return void 0;}const firstMatch=possibleEnumValues[0];return possibleEnumValues.length===1&&firstMatch!==void 0?firstMatch:partialResult;}async processPartialChunk({accumulatedText,previousObject}){const{value:currentObjectJson}=await parsePartialJson(
|
|
86
|
+
*/findBestEnumMatch(partialResult){if(!this.schema?.jsonSchema?.enum){return void 0;}const enumValues=this.schema.jsonSchema.enum;const possibleEnumValues=enumValues.filter(value=>typeof value==="string").filter(enumValue=>enumValue.startsWith(partialResult));if(possibleEnumValues.length===0){return void 0;}const firstMatch=possibleEnumValues[0];return possibleEnumValues.length===1&&firstMatch!==void 0?firstMatch:partialResult;}async processPartialChunk({accumulatedText,previousObject}){const processedAccumulatedText=this.preprocessText(accumulatedText);const{value:currentObjectJson}=await parsePartialJson(processedAccumulatedText);if(currentObjectJson!==void 0&¤tObjectJson!==null&&typeof currentObjectJson==="object"&&!Array.isArray(currentObjectJson)&&"result"in currentObjectJson&&typeof currentObjectJson.result==="string"&&!isDeepEqualData(previousObject,currentObjectJson)){const partialResult=currentObjectJson.result;const bestMatch=this.findBestEnumMatch(partialResult);if(partialResult.length>0&&bestMatch&&bestMatch!==this.textPreviousEnumResult){this.textPreviousEnumResult=bestMatch;return {shouldEmit:true,emitValue:bestMatch,newPreviousResult:currentObjectJson};}}return {shouldEmit:false};}async validateAndTransformFinal(rawFinalValue){const processedValue=this.preprocessText(rawFinalValue);const{value}=await parsePartialJson(processedValue);if(!(typeof value==="object"&&value!==null&&"result"in value)){return {success:false,error:new Error("Invalid enum format: expected object with result property")};}const finalValue=value;if(!finalValue||typeof finalValue!=="object"||typeof finalValue.result!=="string"){return {success:false,error:new Error("Invalid enum format: expected object with result property")};}if(!this.schema){return {success:true,value:finalValue.result};}try{const result=await safeValidateTypes({value:finalValue.result,schema:this.schema});if(result.success){return {success:true,value:result.value};}else {return {success:false,error:result.error??new Error("Enum validation failed")};}}catch(error){return {success:false,error:error instanceof Error?error:new Error("Validation failed")};}}};function createOutputHandler({schema,transformedSchema}){switch(transformedSchema?.outputFormat){case "array":return new ArrayFormatHandler(schema);case "enum":return new EnumFormatHandler(schema);case "object":default:return new ObjectFormatHandler(schema);}}function createObjectStreamTransformer({schema,onFinish}){const responseFormat=getResponseFormat(schema);const transformedSchema=getTransformedSchema(schema);const handler=createOutputHandler({transformedSchema,schema});let accumulatedText="";let previousObject=void 0;let finishReason;let currentRunId;return new TransformStream({async transform(chunk,controller){if(chunk.runId){currentRunId=chunk.runId;}if(chunk.type==="finish"){finishReason=chunk.payload.stepResult.reason;controller.enqueue(chunk);return;}if(responseFormat?.type!=="json"){controller.enqueue(chunk);return;}if(chunk.type==="text-delta"&&typeof chunk.payload?.text==="string"){accumulatedText+=chunk.payload.text;const result=await handler.processPartialChunk({accumulatedText,previousObject});if(result.shouldEmit){previousObject=result.newPreviousResult??previousObject;controller.enqueue({from:chunk.from,runId:chunk.runId,type:"object",object:result.emitValue// TODO: handle partial runtime type validation of json chunks
|
|
82
87
|
});}}controller.enqueue(chunk);},async flush(controller){if(responseFormat?.type!=="json"){return;}if(["tool-calls"].includes(finishReason??"")){onFinish(void 0);return;}const finalResult=await handler.validateAndTransformFinal(accumulatedText);if(!finalResult.success){controller.enqueue({from:"AGENT"/* AGENT */,runId:currentRunId??"",type:"error",payload:{error:finalResult.error??new Error("Validation failed")}});return;}onFinish(finalResult.value);}});}function createJsonTextStreamTransformer(schema){let previousArrayLength=0;let hasStartedArray=false;let chunkCount=0;const outputSchema=getTransformedSchema(schema);return new TransformStream({transform(chunk,controller){if(chunk.type!=="object"||!chunk.object){return;}if(outputSchema?.outputFormat==="array"){chunkCount++;if(chunkCount===1){if(chunk.object.length>0){controller.enqueue(JSON.stringify(chunk.object));previousArrayLength=chunk.object.length;hasStartedArray=true;return;}}if(!hasStartedArray){controller.enqueue("[");hasStartedArray=true;}for(let i=previousArrayLength;i<chunk.object.length;i++){const elementJson=JSON.stringify(chunk.object[i]);if(i>0){controller.enqueue(","+elementJson);}else {controller.enqueue(elementJson);}}previousArrayLength=chunk.object.length;}else {controller.enqueue(JSON.stringify(chunk.object));}},flush(controller){if(hasStartedArray&&outputSchema?.outputFormat==="array"&&chunkCount>1){controller.enqueue("]");}}});}// src/stream/base/output.ts
|
|
83
88
|
var MastraModelOutput=class extends MastraBase{#aisdkv5;#error;#baseStream;#bufferedSteps=[];#bufferedReasoningDetails={};#bufferedByStep={text:"",reasoning:"",sources:[],files:[],toolCalls:[],toolResults:[],msgCount:0};#bufferedText=[];#bufferedTextChunks={};#bufferedSources=[];#bufferedReasoning=[];#bufferedFiles=[];#toolCallArgsDeltas={};#toolCallDeltaIdNameMap={};#toolCalls=[];// TODO: add type
|
|
84
89
|
#toolResults=[];// TODO: add type
|
|
@@ -88,7 +93,7 @@ text:new DelayedPromise(),reasoning:new DelayedPromise(),reasoningText:new Delay
|
|
|
88
93
|
files:new DelayedPromise(),// TODO: add type
|
|
89
94
|
toolCalls:new DelayedPromise(),// TODO: add type
|
|
90
95
|
toolResults:new DelayedPromise(),// TODO: add type
|
|
91
|
-
steps:new DelayedPromise(),totalUsage:new DelayedPromise(),content:new DelayedPromise(),reasoningDetails:new DelayedPromise()};#streamConsumed=false;#returnScorerData=false;/**
|
|
96
|
+
steps:new DelayedPromise(),totalUsage:new DelayedPromise(),content:new DelayedPromise(),reasoningDetails:new DelayedPromise()};#streamConsumed=false;#returnScorerData=false;#model;/**
|
|
92
97
|
* Unique identifier for this execution run.
|
|
93
98
|
*/runId;#options;/**
|
|
94
99
|
* The processor runner for this stream.
|
|
@@ -96,10 +101,9 @@ steps:new DelayedPromise(),totalUsage:new DelayedPromise(),content:new DelayedPr
|
|
|
96
101
|
* The message list for this stream.
|
|
97
102
|
*/messageList;/**
|
|
98
103
|
* Trace ID used on the execution (if the execution was traced).
|
|
99
|
-
*/traceId;messageId;constructor({model:_model,stream,messageList,options,messageId}){super({component:"LLM",name:"MastraModelOutput"});this.#options=options;this.#returnScorerData=!!options.returnScorerData;this.runId=options.runId;this.traceId=getValidTraceId(options.tracingContext?.currentSpan);this.messageId=messageId;if(options.outputProcessors?.length){this.processorRunner=new ProcessorRunner({inputProcessors:[],outputProcessors:options.outputProcessors,logger:this.logger,agentName:"MastraModelOutput"});}if(options.outputProcessorRunnerMode){this.outputProcessorRunnerMode=options.outputProcessorRunnerMode;}this.messageList=messageList;const self=this;let processedStream=stream;const processorRunner=this.processorRunner;if(processorRunner&&options.outputProcessorRunnerMode===`stream`){const processorStates=/* @__PURE__ */new Map();processedStream=stream.pipeThrough(new TransformStream({async transform(chunk,controller){const{part:processed,blocked,reason}=await processorRunner.processPart(chunk,processorStates);if(blocked){controller.enqueue({type:"tripwire",payload:{tripwireReason:reason||"Output processor blocked content"}});return;}if(processed){controller.enqueue(processed);}}}));}this.#baseStream=processedStream.pipeThrough(new TransformStream({transform:async(chunk,controller)=>{switch(chunk.type){case "source":self.#bufferedSources.push(chunk);self.#bufferedByStep.sources.push(chunk);break;case "text-delta":self.#bufferedText.push(chunk.payload.text);self.#bufferedByStep.text+=chunk.payload.text;if(chunk.payload.id){const ary=self.#bufferedTextChunks[chunk.payload.id]??[];ary.push(chunk.payload.text);self.#bufferedTextChunks[chunk.payload.id]=ary;}break;case "tool-call-input-streaming-start":self.#toolCallDeltaIdNameMap[chunk.payload.toolCallId]=chunk.payload.toolName;break;case "tool-call-delta":if(!self.#toolCallArgsDeltas[chunk.payload.toolCallId]){self.#toolCallArgsDeltas[chunk.payload.toolCallId]=[];}self.#toolCallArgsDeltas?.[chunk.payload.toolCallId]?.push(chunk.payload.argsTextDelta);chunk.payload.toolName||=self.#toolCallDeltaIdNameMap[chunk.payload.toolCallId];break;case "file":self.#bufferedFiles.push(chunk);self.#bufferedByStep.files.push(chunk);break;case "reasoning-start":self.#bufferedReasoningDetails[chunk.payload.id]={type:"reasoning",text:"",providerMetadata:chunk.payload.providerMetadata||{}};break;case "reasoning-delta":{self.#bufferedReasoning.push(chunk.payload.text);self.#bufferedByStep.reasoning+=chunk.payload.text;const bufferedReasoning=self.#bufferedReasoningDetails[chunk.payload.id];if(bufferedReasoning){bufferedReasoning.text+=chunk.payload.text;if(chunk.payload.providerMetadata){bufferedReasoning.providerMetadata=chunk.payload.providerMetadata;}}break;}case "reasoning-end":{const bufferedReasoning=self.#bufferedReasoningDetails[chunk.payload.id];if(chunk.payload.providerMetadata&&bufferedReasoning){bufferedReasoning.providerMetadata=chunk.payload.providerMetadata;}break;}case "tool-call":self.#toolCalls.push(chunk);self.#bufferedByStep.toolCalls.push(chunk);if(chunk.payload?.output?.from==="AGENT"&&chunk.payload?.output?.type==="finish"){const finishPayload=chunk.payload?.output.payload;self.updateUsageCount(finishPayload.usage);}break;case "tool-result":self.#toolResults.push(chunk);self.#bufferedByStep.toolResults.push(chunk);break;case "step-finish":{self.updateUsageCount(chunk.payload.output.usage);self.#warnings=chunk.payload.stepResult.warnings||[];if(chunk.payload.metadata.request){self.#request=chunk.payload.metadata.request;}const reasoningDetails=reasoningDetailsFromMessages(chunk.payload.messages.all.slice(self.#bufferedByStep.msgCount));const{providerMetadata,request,...otherMetadata}=chunk.payload.metadata;const stepResult={stepType:self.#bufferedSteps.length===0?"initial":"tool-result",text:self.#bufferedByStep.text,reasoning:self.#bufferedByStep.reasoning||void 0,sources:self.#bufferedByStep.sources,files:self.#bufferedByStep.files,toolCalls:self.#bufferedByStep.toolCalls,toolResults:self.#bufferedByStep.toolResults,warnings:self.#warnings,reasoningDetails,providerMetadata,experimental_providerMetadata:providerMetadata,isContinued:chunk.payload.stepResult.isContinued,logprobs:chunk.payload.stepResult.logprobs,finishReason:chunk.payload.stepResult.reason,response:{...otherMetadata,messages:chunk.payload.messages.nonUser},request,usage:chunk.payload.output.usage
|
|
100
|
-
content
|
|
101
|
-
|
|
102
|
-
content:messageList.get.response.aiV5.stepContent(),request:await self.request,error:self.error,reasoning:await self.aisdk.v5.reasoning,reasoningText:await self.aisdk.v5.reasoningText,sources:await self.aisdk.v5.sources,files:await self.aisdk.v5.files,steps:transformSteps({steps:self.#bufferedSteps}),response:{...(await self.response),messages:messageList.get.response.aiV5.model()},usage:chunk.payload.output.usage,totalUsage:self.#getTotalUsage(),toolCalls:await self.aisdk.v5.toolCalls,toolResults:await self.aisdk.v5.toolResults,staticToolCalls:(await self.aisdk.v5.toolCalls).filter(toolCall=>toolCall.dynamic===false),staticToolResults:(await self.aisdk.v5.toolResults).filter(toolResult=>toolResult.dynamic===false),dynamicToolCalls:(await self.aisdk.v5.toolCalls).filter(toolCall=>toolCall.dynamic===true),dynamicToolResults:(await self.aisdk.v5.toolResults).filter(toolResult=>toolResult.dynamic===true),object:self.#delayedPromises.object.status.type==="resolved"?self.#delayedPromises.object.status.value:self.#options.output&&baseFinishStep.text?(()=>{try{return JSON.parse(baseFinishStep.text);}catch{return void 0;}})():void 0};await options?.onFinish?.(onFinishPayload);}if(options?.rootSpan){options.rootSpan.setAttributes({...(baseFinishStep?.usage?.reasoningTokens?{"stream.usage.reasoningTokens":baseFinishStep.usage.reasoningTokens}:{}),...(baseFinishStep?.usage?.totalTokens?{"stream.usage.totalTokens":baseFinishStep.usage.totalTokens}:{}),...(baseFinishStep?.usage?.inputTokens?{"stream.usage.inputTokens":baseFinishStep.usage.inputTokens}:{}),...(baseFinishStep?.usage?.outputTokens?{"stream.usage.outputTokens":baseFinishStep.usage.outputTokens}:{}),...(baseFinishStep?.usage?.cachedInputTokens?{"stream.usage.cachedInputTokens":baseFinishStep.usage.cachedInputTokens}:{}),...(baseFinishStep?.providerMetadata?{"stream.response.providerMetadata":JSON.stringify(baseFinishStep?.providerMetadata)}:{}),...(baseFinishStep?.finishReason?{"stream.response.finishReason":baseFinishStep?.finishReason}:{}),...(options?.telemetry_settings?.recordOutputs!==false?{"stream.response.text":baseFinishStep?.text}:{}),...(baseFinishStep?.toolCalls&&options?.telemetry_settings?.recordOutputs!==false?{"stream.response.toolCalls":JSON.stringify(baseFinishStep?.toolCalls?.map(chunk2=>{return {type:"tool-call",toolCallId:chunk2.payload.toolCallId,args:chunk2.payload.args,toolName:chunk2.payload.toolName};}))}:{})});options.rootSpan.end();}break;case "error":self.#error=chunk.payload.error;const error=typeof self.#error==="object"?new Error(self.#error.message):new Error(String(self.#error));Object.values(self.#delayedPromises).forEach(promise=>promise.reject(error));break;}controller.enqueue(chunk);}}));this.#aisdkv5=new AISDKV5OutputStream({modelOutput:this,messageList,options:{toolCallStreaming:options?.toolCallStreaming,output:options?.output}});}#getDelayedPromise(promise){if(!this.#streamConsumed){void this.consumeStream();}return promise.promise;}/**
|
|
104
|
+
*/traceId;messageId;constructor({model:_model,stream,messageList,options,messageId}){super({component:"LLM",name:"MastraModelOutput"});this.#options=options;this.#returnScorerData=!!options.returnScorerData;this.runId=options.runId;this.traceId=getValidTraceId(options.tracingContext?.currentSpan);this.#model=_model;this.messageId=messageId;if(options.outputProcessors?.length){this.processorRunner=new ProcessorRunner({inputProcessors:[],outputProcessors:options.outputProcessors,logger:this.logger,agentName:"MastraModelOutput"});}if(options.outputProcessorRunnerMode){this.outputProcessorRunnerMode=options.outputProcessorRunnerMode;}this.messageList=messageList;const self=this;let processedStream=stream;const processorRunner=this.processorRunner;if(processorRunner&&options.outputProcessorRunnerMode===`stream`){const processorStates=/* @__PURE__ */new Map();processedStream=stream.pipeThrough(new TransformStream({async transform(chunk,controller){const{part:processed,blocked,reason}=await processorRunner.processPart(chunk,processorStates);if(blocked){controller.enqueue({type:"tripwire",payload:{tripwireReason:reason||"Output processor blocked content"}});return;}if(processed){controller.enqueue(processed);}}}));}this.#baseStream=processedStream.pipeThrough(new TransformStream({transform:async(chunk,controller)=>{switch(chunk.type){case "source":self.#bufferedSources.push(chunk);self.#bufferedByStep.sources.push(chunk);break;case "text-delta":self.#bufferedText.push(chunk.payload.text);self.#bufferedByStep.text+=chunk.payload.text;if(chunk.payload.id){const ary=self.#bufferedTextChunks[chunk.payload.id]??[];ary.push(chunk.payload.text);self.#bufferedTextChunks[chunk.payload.id]=ary;}break;case "tool-call-input-streaming-start":self.#toolCallDeltaIdNameMap[chunk.payload.toolCallId]=chunk.payload.toolName;break;case "tool-call-delta":if(!self.#toolCallArgsDeltas[chunk.payload.toolCallId]){self.#toolCallArgsDeltas[chunk.payload.toolCallId]=[];}self.#toolCallArgsDeltas?.[chunk.payload.toolCallId]?.push(chunk.payload.argsTextDelta);chunk.payload.toolName||=self.#toolCallDeltaIdNameMap[chunk.payload.toolCallId];break;case "file":self.#bufferedFiles.push(chunk);self.#bufferedByStep.files.push(chunk);break;case "reasoning-start":self.#bufferedReasoningDetails[chunk.payload.id]={type:"reasoning",text:"",providerMetadata:chunk.payload.providerMetadata||{}};break;case "reasoning-delta":{self.#bufferedReasoning.push(chunk.payload.text);self.#bufferedByStep.reasoning+=chunk.payload.text;const bufferedReasoning=self.#bufferedReasoningDetails[chunk.payload.id];if(bufferedReasoning){bufferedReasoning.text+=chunk.payload.text;if(chunk.payload.providerMetadata){bufferedReasoning.providerMetadata=chunk.payload.providerMetadata;}}break;}case "reasoning-end":{const bufferedReasoning=self.#bufferedReasoningDetails[chunk.payload.id];if(chunk.payload.providerMetadata&&bufferedReasoning){bufferedReasoning.providerMetadata=chunk.payload.providerMetadata;}break;}case "tool-call":self.#toolCalls.push(chunk);self.#bufferedByStep.toolCalls.push(chunk);if(chunk.payload?.output?.from==="AGENT"&&chunk.payload?.output?.type==="finish"){const finishPayload=chunk.payload?.output.payload;self.updateUsageCount(finishPayload.usage);}break;case "tool-result":self.#toolResults.push(chunk);self.#bufferedByStep.toolResults.push(chunk);break;case "step-finish":{self.updateUsageCount(chunk.payload.output.usage);self.#warnings=chunk.payload.stepResult.warnings||[];if(chunk.payload.metadata.request){self.#request=chunk.payload.metadata.request;}const reasoningDetails=reasoningDetailsFromMessages(chunk.payload.messages.all.slice(self.#bufferedByStep.msgCount));const{providerMetadata,request,...otherMetadata}=chunk.payload.metadata;const stepResult={stepType:self.#bufferedSteps.length===0?"initial":"tool-result",text:self.#bufferedByStep.text,reasoning:self.#bufferedByStep.reasoning||void 0,sources:self.#bufferedByStep.sources,files:self.#bufferedByStep.files,toolCalls:self.#bufferedByStep.toolCalls,toolResults:self.#bufferedByStep.toolResults,warnings:self.#warnings,reasoningDetails,providerMetadata,experimental_providerMetadata:providerMetadata,isContinued:chunk.payload.stepResult.isContinued,logprobs:chunk.payload.stepResult.logprobs,finishReason:chunk.payload.stepResult.reason,response:{...otherMetadata,messages:chunk.payload.messages.nonUser},request,usage:chunk.payload.output.usage,content:messageList.get.response.aiV5.modelContent(-1)};await options?.onStepFinish?.({...(self.#model.modelId&&self.#model.provider&&self.#model.version?{model:self.#model}:{}),...stepResult});self.#bufferedSteps.push(stepResult);self.#bufferedByStep={text:"",reasoning:"",sources:[],files:[],toolCalls:[],toolResults:[],msgCount:chunk.payload.messages.all.length};break;}case "tripwire":self.#tripwire=true;self.#tripwireReason=chunk.payload?.tripwireReason||"Content blocked";self.#finishReason="other";self.#delayedPromises.text.resolve(self.#bufferedText.join(""));self.#delayedPromises.finishReason.resolve("other");self.#delayedPromises.object.resolve(void 0);self.#delayedPromises.usage.resolve(self.#usageCount);self.#delayedPromises.warnings.resolve(self.#warnings);self.#delayedPromises.providerMetadata.resolve(void 0);self.#delayedPromises.response.resolve({});self.#delayedPromises.request.resolve({});self.#delayedPromises.reasoning.resolve("");self.#delayedPromises.reasoningText.resolve(void 0);self.#delayedPromises.sources.resolve([]);self.#delayedPromises.files.resolve([]);self.#delayedPromises.toolCalls.resolve([]);self.#delayedPromises.toolResults.resolve([]);self.#delayedPromises.steps.resolve(self.#bufferedSteps);self.#delayedPromises.totalUsage.resolve(self.#usageCount);self.#delayedPromises.content.resolve([]);self.#delayedPromises.reasoningDetails.resolve([]);controller.enqueue(chunk);controller.terminate();return;case "finish":if(chunk.payload.stepResult.reason){self.#finishReason=chunk.payload.stepResult.reason;}let response={};if(chunk.payload.metadata){const{providerMetadata,request,...otherMetadata}=chunk.payload.metadata;response={...otherMetadata,messages:messageList.get.response.aiV5.model(),uiMessages:messageList.get.response.aiV5.ui()};}this.populateUsageCount(chunk.payload.output.usage);chunk.payload.output.usage=self.#usageCount;try{if(self.processorRunner&&self.outputProcessorRunnerMode===`result`){self.messageList=await self.processorRunner.runOutputProcessors(self.messageList);const outputText=self.messageList.get.response.aiV4.core().map(m=>MessageList.coreContentToString(m.content)).join("\n");const messages=self.messageList.get.response.v2();const messagesWithStructuredData=messages.filter(msg=>msg.content.metadata&&msg.content.metadata.structuredOutput);if(messagesWithStructuredData[0]&&messagesWithStructuredData[0].content.metadata?.structuredOutput){const structuredOutput=messagesWithStructuredData[0].content.metadata.structuredOutput;self.#delayedPromises.object.resolve(structuredOutput);}else if(!self.#options.output){self.#delayedPromises.object.resolve(void 0);}self.#delayedPromises.text.resolve(outputText);self.#delayedPromises.finishReason.resolve(self.#finishReason);if(chunk.payload.metadata){const{providerMetadata,request,...otherMetadata}=chunk.payload.metadata;response={...otherMetadata,messages:messageList.get.response.aiV5.model(),uiMessages:messageList.get.response.aiV5.ui()};}}else {const textContent=self.#bufferedText.join("");self.#delayedPromises.text.resolve(textContent);self.#delayedPromises.finishReason.resolve(self.#finishReason);const messages=self.messageList.get.response.v2();const messagesWithStructuredData=messages.filter(msg=>msg.content.metadata&&msg.content.metadata.structuredOutput);if(messagesWithStructuredData[0]&&// this is to make typescript happy
|
|
105
|
+
messagesWithStructuredData[0].content.metadata?.structuredOutput){const structuredOutput=messagesWithStructuredData[0].content.metadata.structuredOutput;self.#delayedPromises.object.resolve(structuredOutput);}else if(!self.#options.output&&self.#delayedPromises.object.status.type!=="resolved"){self.#delayedPromises.object.resolve(void 0);}}}catch(error2){if(error2 instanceof TripWire){self.#tripwire=true;self.#tripwireReason=error2.message;self.#delayedPromises.finishReason.resolve("other");self.#delayedPromises.text.resolve("");}else {self.#error=error2 instanceof Error?error2.message:String(error2);self.#delayedPromises.finishReason.resolve("error");self.#delayedPromises.text.resolve("");}self.#delayedPromises.object.resolve(void 0);}self.#delayedPromises.usage.resolve(self.#usageCount);self.#delayedPromises.warnings.resolve(self.#warnings);self.#delayedPromises.providerMetadata.resolve(chunk.payload.metadata?.providerMetadata);self.#delayedPromises.response.resolve(response);self.#delayedPromises.request.resolve(self.#request||{});self.#delayedPromises.text.resolve(self.#bufferedText.join(""));self.#delayedPromises.reasoning.resolve(self.#bufferedReasoning.join(""));const reasoningText=self.#bufferedReasoning.length>0?self.#bufferedReasoning.join(""):void 0;self.#delayedPromises.reasoningText.resolve(reasoningText);self.#delayedPromises.sources.resolve(self.#bufferedSources);self.#delayedPromises.files.resolve(self.#bufferedFiles);self.#delayedPromises.toolCalls.resolve(self.#toolCalls);self.#delayedPromises.toolResults.resolve(self.#toolResults);self.#delayedPromises.steps.resolve(self.#bufferedSteps);self.#delayedPromises.totalUsage.resolve(self.#getTotalUsage());self.#delayedPromises.content.resolve(messageList.get.response.aiV5.stepContent());self.#delayedPromises.reasoningDetails.resolve(Object.values(self.#bufferedReasoningDetails||{}));const baseFinishStep=self.#bufferedSteps[self.#bufferedSteps.length-1];if(baseFinishStep){const onFinishPayload={...(self.#model.modelId&&self.#model.provider&&self.#model.version?{model:self.#model}:{}),text:baseFinishStep.text,warnings:baseFinishStep.warnings??[],finishReason:chunk.payload.stepResult.reason,// TODO: we should add handling for step IDs in message list so you can retrieve step content by step id. And on finish should the content here be from all steps?
|
|
106
|
+
content:messageList.get.response.aiV5.stepContent(),request:await self.request,error:self.error,reasoning:await self.aisdk.v5.reasoning,reasoningText:await self.aisdk.v5.reasoningText,sources:await self.aisdk.v5.sources,files:await self.aisdk.v5.files,steps:transformSteps({steps:self.#bufferedSteps}),response:{...(await self.response),messages:messageList.get.response.aiV5.model()},usage:chunk.payload.output.usage,totalUsage:self.#getTotalUsage(),toolCalls:await self.aisdk.v5.toolCalls,toolResults:await self.aisdk.v5.toolResults,staticToolCalls:(await self.aisdk.v5.toolCalls).filter(toolCall=>toolCall.dynamic===false),staticToolResults:(await self.aisdk.v5.toolResults).filter(toolResult=>toolResult.dynamic===false),dynamicToolCalls:(await self.aisdk.v5.toolCalls).filter(toolCall=>toolCall.dynamic===true),dynamicToolResults:(await self.aisdk.v5.toolResults).filter(toolResult=>toolResult.dynamic===true),object:self.#delayedPromises.object.status.type==="resolved"?self.#delayedPromises.object.status.value:self.#options.output&&baseFinishStep.text?(()=>{try{return JSON.parse(baseFinishStep.text);}catch{return void 0;}})():void 0};await options?.onFinish?.(onFinishPayload);}if(options?.rootSpan){options.rootSpan.setAttributes({...(self.#model.modelId?{"aisdk.model.id":self.#model.modelId}:{}),...(self.#model.provider?{"aisdk.model.provider":self.#model.provider}:{}),...(baseFinishStep?.usage?.reasoningTokens?{"stream.usage.reasoningTokens":baseFinishStep.usage.reasoningTokens}:{}),...(baseFinishStep?.usage?.totalTokens?{"stream.usage.totalTokens":baseFinishStep.usage.totalTokens}:{}),...(baseFinishStep?.usage?.inputTokens?{"stream.usage.inputTokens":baseFinishStep.usage.inputTokens}:{}),...(baseFinishStep?.usage?.outputTokens?{"stream.usage.outputTokens":baseFinishStep.usage.outputTokens}:{}),...(baseFinishStep?.usage?.cachedInputTokens?{"stream.usage.cachedInputTokens":baseFinishStep.usage.cachedInputTokens}:{}),...(baseFinishStep?.providerMetadata?{"stream.response.providerMetadata":JSON.stringify(baseFinishStep?.providerMetadata)}:{}),...(baseFinishStep?.finishReason?{"stream.response.finishReason":baseFinishStep?.finishReason}:{}),...(options?.telemetry_settings?.recordOutputs!==false?{"stream.response.text":baseFinishStep?.text}:{}),...(baseFinishStep?.toolCalls&&options?.telemetry_settings?.recordOutputs!==false?{"stream.response.toolCalls":JSON.stringify(baseFinishStep?.toolCalls?.map(chunk2=>{return {type:"tool-call",toolCallId:chunk2.payload.toolCallId,args:chunk2.payload.args,toolName:chunk2.payload.toolName};}))}:{})});options.rootSpan.end();}break;case "error":self.#error=chunk.payload.error;const error=typeof self.#error==="object"?new Error(self.#error.message):new Error(String(self.#error));Object.values(self.#delayedPromises).forEach(promise=>promise.reject(error));break;}controller.enqueue(chunk);}}));this.#aisdkv5=new AISDKV5OutputStream({modelOutput:this,messageList,options:{toolCallStreaming:options?.toolCallStreaming,output:options?.output}});}#getDelayedPromise(promise){if(!this.#streamConsumed){void this.consumeStream();}return promise.promise;}/**
|
|
103
107
|
* Resolves to the complete text response after streaming completes.
|
|
104
108
|
*/get text(){return this.#getDelayedPromise(this.#delayedPromises.text);}/**
|
|
105
109
|
* Resolves to complete reasoning text for models that support reasoning.
|
|
@@ -170,10 +174,10 @@ var noopSpanContext={traceId:"",spanId:"",traceFlags:0};var noopSpan={spanContex
|
|
|
170
174
|
function getTracer({isEnabled=false,tracer}={}){if(!isEnabled){return noopTracer;}if(tracer){return tracer;}return trace.getTracer("mastra");}function assembleOperationName({operationId,telemetry}){return {"mastra.operationId":operationId,"operation.name":`${operationId}${telemetry?.functionId!=null?` ${telemetry.functionId}`:""}`,...(telemetry?.functionId?{"resource.name":telemetry?.functionId}:{})};}function getTelemetryAttributes({model,settings,telemetry,headers}){return {"aisdk.model.provider":model.provider,"aisdk.model.id":model.modelId,// settings:
|
|
171
175
|
...Object.entries(settings).reduce((attributes,[key,value])=>{attributes[`stream.settings.${key}`]=value;return attributes;},{}),// add metadata as attributes:
|
|
172
176
|
...Object.entries(telemetry?.metadata??{}).reduce((attributes,[key,value])=>{attributes[`stream.telemetry.metadata.${key}`]=value;return attributes;},{}),// request headers
|
|
173
|
-
...Object.entries(headers??{}).reduce((attributes,[key,value])=>{if(value!==void 0){attributes[`stream.request.headers.${key}`]=value;}return attributes;},{})};}function getRootSpan({operationId,model,modelSettings,telemetry_settings,headers}){const tracer=getTracer({isEnabled:telemetry_settings?.isEnabled,tracer:telemetry_settings?.tracer});const baseTelemetryAttributes=getTelemetryAttributes({model:{modelId:model.modelId,provider:model.provider},settings:modelSettings??{maxRetries:2},telemetry:telemetry_settings,headers});const rootSpan=tracer.startSpan(operationId).setAttributes({...assembleOperationName({operationId,telemetry:telemetry_settings}),...baseTelemetryAttributes});return {rootSpan};}// src/loop/
|
|
177
|
+
...Object.entries(headers??{}).reduce((attributes,[key,value])=>{if(value!==void 0){attributes[`stream.request.headers.${key}`]=value;}return attributes;},{})};}function getRootSpan({operationId,model,modelSettings,telemetry_settings,headers}){const tracer=getTracer({isEnabled:telemetry_settings?.isEnabled,tracer:telemetry_settings?.tracer});const baseTelemetryAttributes=getTelemetryAttributes({model:{modelId:model.modelId,provider:model.provider},settings:modelSettings??{maxRetries:2},telemetry:telemetry_settings,headers});const rootSpan=tracer.startSpan(operationId).setAttributes({...assembleOperationName({operationId,telemetry:telemetry_settings}),...baseTelemetryAttributes});return {rootSpan};}// src/loop/workflows/stream.ts
|
|
174
178
|
var MastraWorkflowStream=class extends ReadableStream$1{#usageCount={promptTokens:0,completionTokens:0,totalTokens:0};#streamPromise;#run;constructor({createStream,run}){const deferredPromise={promise:null,resolve:null,reject:null};deferredPromise.promise=new Promise((resolve,reject)=>{deferredPromise.resolve=resolve;deferredPromise.reject=reject;});const updateUsageCount=usage=>{this.#usageCount.promptTokens+=parseInt(usage?.promptTokens?.toString()??"0",10);this.#usageCount.completionTokens+=parseInt(usage?.completionTokens?.toString()??"0",10);this.#usageCount.totalTokens+=parseInt(usage?.totalTokens?.toString()??"0",10);};super({start:async controller=>{const writer=new WritableStream({write:chunk=>{if(chunk.type==="step-output"&&chunk.payload?.output?.from==="AGENT"&&chunk.payload?.output?.type==="finish"||chunk.type==="step-output"&&chunk.payload?.output?.from==="WORKFLOW"&&chunk.payload?.output?.type==="finish"){const finishPayload=chunk.payload?.output.payload;if(finishPayload){updateUsageCount(finishPayload.usage);}}controller.enqueue(chunk);}});controller.enqueue({type:"workflow-start",runId:run.runId,from:"WORKFLOW"/* WORKFLOW */,payload:{workflowId:run.workflowId}});const stream=await createStream(writer);let workflowStatus="success";for await(const chunk of stream){if(chunk.type==="step-finish"&&chunk.payload.usage){updateUsageCount(chunk.payload.usage);}else if(chunk.type==="workflow-canceled"){workflowStatus="canceled";}else if(chunk.type==="workflow-step-result"&&chunk.payload.status==="failed"){workflowStatus="failed";}controller.enqueue(chunk);}controller.enqueue({type:"workflow-finish",runId:run.runId,from:"WORKFLOW"/* WORKFLOW */,payload:{workflowStatus,output:{usage:this.#usageCount},metadata:{}}});controller.close();deferredPromise.resolve();}});this.#run=run;this.#streamPromise=deferredPromise;}get status(){return this.#streamPromise.promise.then(()=>this.#run._getExecutionResults()).then(res=>res.status);}get result(){return this.#streamPromise.promise.then(()=>this.#run._getExecutionResults());}get usage(){return this.#streamPromise.promise.then(()=>this.#usageCount);}};// src/workflows/default.ts
|
|
175
179
|
function runScorer({runId,scorerId,scorerObject,input,output,runtimeContext,entity,structuredOutput,source,entityType,threadId,resourceId,tracingContext}){let shouldExecute=false;if(!scorerObject?.sampling||scorerObject?.sampling?.type==="none"){shouldExecute=true;}if(scorerObject?.sampling?.type){switch(scorerObject?.sampling?.type){case "ratio":shouldExecute=Math.random()<scorerObject?.sampling?.rate;break;default:shouldExecute=true;}}if(!shouldExecute){return;}const payload={scorer:{id:scorerId,name:scorerObject.scorer.name,description:scorerObject.scorer.description},input,output,runtimeContext:Object.fromEntries(runtimeContext.entries()),runId,source,entity,structuredOutput,entityType,threadId,resourceId,tracingContext};executeHook("onScorerRun"/* ON_SCORER_RUN */,payload);}// src/workflows/execution-engine.ts
|
|
176
|
-
var ExecutionEngine=class extends MastraBase{mastra;constructor({mastra}){super({name:"ExecutionEngine",component:RegisteredLogger.WORKFLOW});this.mastra=mastra;}__registerMastra(mastra){this.mastra=mastra;}};// src/workflows/default.ts
|
|
180
|
+
var ExecutionEngine=class extends MastraBase{mastra;options;constructor({mastra,options}){super({name:"ExecutionEngine",component:RegisteredLogger.WORKFLOW});this.mastra=mastra;this.options=options;}__registerMastra(mastra){this.mastra=mastra;}};// src/workflows/default.ts
|
|
177
181
|
var DefaultExecutionEngine=class extends ExecutionEngine{/**
|
|
178
182
|
* Preprocesses an error caught during workflow execution.
|
|
179
183
|
*
|
|
@@ -194,14 +198,14 @@ var DefaultExecutionEngine=class extends ExecutionEngine{/**
|
|
|
194
198
|
* @param graph The execution graph to execute
|
|
195
199
|
* @param input The input data for the workflow
|
|
196
200
|
* @returns A promise that resolves to the workflow output
|
|
197
|
-
*/async execute(params){const{workflowId,runId,resourceId,graph,input,resume,retryConfig,workflowAISpan,disableScorers}=params;const{attempts=0,delay:delay2=0}=retryConfig??{};const steps=graph.steps;this.runCounts.clear();if(steps.length===0){const empty_graph_error=new MastraError({id:"WORKFLOW_EXECUTE_EMPTY_GRAPH",text:"Workflow must have at least one step",domain:"MASTRA_WORKFLOW"/* MASTRA_WORKFLOW */,category:"USER"/* USER */});workflowAISpan?.error({error:empty_graph_error});throw empty_graph_error;}const executionSpan=this.mastra?.getTelemetry()?.tracer.startSpan(`workflow.${workflowId}.execute`,{attributes:{componentName:workflowId,runId,resourceId}});let startIdx=0;if(resume?.resumePath){startIdx=resume.resumePath[0];resume.resumePath.shift();}const stepResults=resume?.stepResults||{input};let lastOutput;for(let i=startIdx;i<steps.length;i++){const entry=steps[i];try{lastOutput=await this.executeEntry({workflowId,runId,resourceId,entry,serializedStepGraph:params.serializedStepGraph,prevStep:steps[i-1],stepResults,resume,executionContext:{workflowId,runId,executionPath:[i],suspendedPaths:{},retryConfig:{attempts,delay:delay2},executionSpan,format:params.format},tracingContext:{currentSpan:workflowAISpan
|
|
198
|
-
suspend:async _suspendPayload=>{},bail:()=>{},abort:()=>{abortController?.abort();},[EMITTER_SYMBOL]:emitter,[STREAM_FORMAT_SYMBOL]:executionContext.format,engine:{},abortSignal:abortController?.signal,writer:new ToolStream({prefix:"workflow-step",callId:stepCallId,name:"sleep",runId},writableStream)});sleepSpan?.update({attributes:{durationMs:duration}});}try{await new Promise(resolve=>setTimeout(resolve,!duration||duration<0?0:duration));sleepSpan?.end();}catch(e){sleepSpan?.error({error:e});}}async executeSleepUntil({workflowId,runId,entry,prevOutput,stepResults,emitter,abortController,runtimeContext,executionContext,writableStream,tracingContext}){let{date,fn}=entry;const sleepUntilSpan=tracingContext.currentSpan?.createChildSpan({type:"workflow_sleep"/* WORKFLOW_SLEEP */,name:`sleepUntil: ${date?date.toISOString():"dynamic"}`,attributes:{untilDate:date,durationMs:date?Math.max(0,date.getTime()-Date.now()):void 0,sleepType:fn?"dynamic":"fixed"},
|
|
199
|
-
suspend:async _suspendPayload=>{},bail:()=>{},abort:()=>{abortController?.abort();},[EMITTER_SYMBOL]:emitter,[STREAM_FORMAT_SYMBOL]:executionContext.format,engine:{},abortSignal:abortController?.signal,writer:new ToolStream({prefix:"workflow-step",callId:stepCallId,name:"sleepUntil",runId},writableStream)});const time2=!date?0:date.getTime()-Date.now();sleepUntilSpan?.update({attributes:{durationMs:Math.max(0,time2)}});}const time=!date?0:date?.getTime()-Date.now();try{await new Promise(resolve=>setTimeout(resolve,time<0?0:time));sleepUntilSpan?.end();}catch(e){sleepUntilSpan?.error({error:e});}}async executeWaitForEvent({event,emitter,timeout,tracingContext}){const waitSpan=tracingContext?.currentSpan?.createChildSpan({type:"workflow_wait_event"/* WORKFLOW_WAIT_EVENT */,name:`wait: ${event}`,attributes:{eventName:event,timeoutMs:timeout},
|
|
201
|
+
*/async execute(params){const{workflowId,runId,resourceId,graph,input,resume,retryConfig,workflowAISpan,disableScorers}=params;const{attempts=0,delay:delay2=0}=retryConfig??{};const steps=graph.steps;this.runCounts.clear();if(steps.length===0){const empty_graph_error=new MastraError({id:"WORKFLOW_EXECUTE_EMPTY_GRAPH",text:"Workflow must have at least one step",domain:"MASTRA_WORKFLOW"/* MASTRA_WORKFLOW */,category:"USER"/* USER */});workflowAISpan?.error({error:empty_graph_error});throw empty_graph_error;}const executionSpan=this.mastra?.getTelemetry()?.tracer.startSpan(`workflow.${workflowId}.execute`,{attributes:{componentName:workflowId,runId,resourceId}});let startIdx=0;if(resume?.resumePath){startIdx=resume.resumePath[0];resume.resumePath.shift();}const stepResults=resume?.stepResults||{input};let lastOutput;for(let i=startIdx;i<steps.length;i++){const entry=steps[i];try{lastOutput=await this.executeEntry({workflowId,runId,resourceId,entry,serializedStepGraph:params.serializedStepGraph,prevStep:steps[i-1],stepResults,resume,executionContext:{workflowId,runId,executionPath:[i],suspendedPaths:{},retryConfig:{attempts,delay:delay2},executionSpan,format:params.format},tracingContext:{currentSpan:workflowAISpan},abortController:params.abortController,emitter:params.emitter,runtimeContext:params.runtimeContext,writableStream:params.writableStream,disableScorers});if(lastOutput.result.status!=="success"){if(lastOutput.result.status==="bailed"){lastOutput.result.status="success";}const result2=await this.fmtReturnValue(executionSpan,params.emitter,stepResults,lastOutput.result);await this.persistStepUpdate({workflowId,runId,resourceId,stepResults:lastOutput.stepResults,serializedStepGraph:params.serializedStepGraph,executionContext:lastOutput.executionContext,workflowStatus:result2.status,result:result2.result,error:result2.error,runtimeContext:params.runtimeContext});if(result2.error){workflowAISpan?.error({error:result2.error,attributes:{status:result2.status}});}else {workflowAISpan?.end({output:result2.result,attributes:{status:result2.status}});}return result2;}}catch(e){const error=this.preprocessExecutionError(e,{id:"WORKFLOW_ENGINE_STEP_EXECUTION_FAILED",domain:"MASTRA_WORKFLOW"/* MASTRA_WORKFLOW */,category:"USER"/* USER */,details:{workflowId,runId}},"Error executing step: ");const result2=await this.fmtReturnValue(executionSpan,params.emitter,stepResults,lastOutput.result,e);await this.persistStepUpdate({workflowId,runId,resourceId,stepResults:lastOutput.stepResults,serializedStepGraph:params.serializedStepGraph,executionContext:lastOutput.executionContext,workflowStatus:result2.status,result:result2.result,error:result2.error,runtimeContext:params.runtimeContext});workflowAISpan?.error({error,attributes:{status:result2.status}});return result2;}}const result=await this.fmtReturnValue(executionSpan,params.emitter,stepResults,lastOutput.result);await this.persistStepUpdate({workflowId,runId,resourceId,stepResults:lastOutput.stepResults,serializedStepGraph:params.serializedStepGraph,executionContext:lastOutput.executionContext,workflowStatus:result.status,result:result.result,error:result.error,runtimeContext:params.runtimeContext});workflowAISpan?.end({output:result.result,attributes:{status:result.status}});return result;}getStepOutput(stepResults,step){if(!step){return stepResults.input;}else if(step.type==="step"||step.type==="waitForEvent"){return stepResults[step.step.id]?.output;}else if(step.type==="sleep"||step.type==="sleepUntil"){return stepResults[step.id]?.output;}else if(step.type==="parallel"||step.type==="conditional"){return step.steps.reduce((acc,entry)=>{if(entry.type==="step"||entry.type==="waitForEvent"){acc[entry.step.id]=stepResults[entry.step.id]?.output;}else if(entry.type==="parallel"||entry.type==="conditional"){const parallelResult=this.getStepOutput(stepResults,entry)?.output;acc={...acc,...parallelResult};}else if(entry.type==="loop"){acc[entry.step.id]=stepResults[entry.step.id]?.output;}else if(entry.type==="foreach"){acc[entry.step.id]=stepResults[entry.step.id]?.output;}else if(entry.type==="sleep"||entry.type==="sleepUntil"){acc[entry.id]=stepResults[entry.id]?.output;}return acc;},{});}else if(step.type==="loop"){return stepResults[step.step.id]?.output;}else if(step.type==="foreach"){return stepResults[step.step.id]?.output;}}async executeSleep({workflowId,runId,entry,prevOutput,stepResults,emitter,abortController,runtimeContext,executionContext,writableStream,tracingContext}){let{duration,fn}=entry;const sleepSpan=tracingContext.currentSpan?.createChildSpan({type:"workflow_sleep"/* WORKFLOW_SLEEP */,name:`sleep: ${duration?`${duration}ms`:"dynamic"}`,attributes:{durationMs:duration,sleepType:fn?"dynamic":"fixed"},tracingPolicy:this.options?.tracingPolicy});if(fn){const stepCallId=randomUUID();duration=await fn({runId,workflowId,mastra:this.mastra,runtimeContext,inputData:prevOutput,runCount:-1,tracingContext:{currentSpan:sleepSpan},getInitData:()=>stepResults?.input,getStepResult:step=>{if(!step?.id){return null;}const result=stepResults[step.id];if(result?.status==="success"){return result.output;}return null;},// TODO: this function shouldn't have suspend probably?
|
|
202
|
+
suspend:async _suspendPayload=>{},bail:()=>{},abort:()=>{abortController?.abort();},[EMITTER_SYMBOL]:emitter,[STREAM_FORMAT_SYMBOL]:executionContext.format,engine:{},abortSignal:abortController?.signal,writer:new ToolStream({prefix:"workflow-step",callId:stepCallId,name:"sleep",runId},writableStream)});sleepSpan?.update({attributes:{durationMs:duration}});}try{await new Promise(resolve=>setTimeout(resolve,!duration||duration<0?0:duration));sleepSpan?.end();}catch(e){sleepSpan?.error({error:e});}}async executeSleepUntil({workflowId,runId,entry,prevOutput,stepResults,emitter,abortController,runtimeContext,executionContext,writableStream,tracingContext}){let{date,fn}=entry;const sleepUntilSpan=tracingContext.currentSpan?.createChildSpan({type:"workflow_sleep"/* WORKFLOW_SLEEP */,name:`sleepUntil: ${date?date.toISOString():"dynamic"}`,attributes:{untilDate:date,durationMs:date?Math.max(0,date.getTime()-Date.now()):void 0,sleepType:fn?"dynamic":"fixed"},tracingPolicy:this.options?.tracingPolicy});if(fn){const stepCallId=randomUUID();date=await fn({runId,workflowId,mastra:this.mastra,runtimeContext,inputData:prevOutput,runCount:-1,tracingContext:{currentSpan:sleepUntilSpan},getInitData:()=>stepResults?.input,getStepResult:step=>{if(!step?.id){return null;}const result=stepResults[step.id];if(result?.status==="success"){return result.output;}return null;},// TODO: this function shouldn't have suspend probably?
|
|
203
|
+
suspend:async _suspendPayload=>{},bail:()=>{},abort:()=>{abortController?.abort();},[EMITTER_SYMBOL]:emitter,[STREAM_FORMAT_SYMBOL]:executionContext.format,engine:{},abortSignal:abortController?.signal,writer:new ToolStream({prefix:"workflow-step",callId:stepCallId,name:"sleepUntil",runId},writableStream)});const time2=!date?0:date.getTime()-Date.now();sleepUntilSpan?.update({attributes:{durationMs:Math.max(0,time2)}});}const time=!date?0:date?.getTime()-Date.now();try{await new Promise(resolve=>setTimeout(resolve,time<0?0:time));sleepUntilSpan?.end();}catch(e){sleepUntilSpan?.error({error:e});}}async executeWaitForEvent({event,emitter,timeout,tracingContext}){const waitSpan=tracingContext?.currentSpan?.createChildSpan({type:"workflow_wait_event"/* WORKFLOW_WAIT_EVENT */,name:`wait: ${event}`,attributes:{eventName:event,timeoutMs:timeout},tracingPolicy:this.options?.tracingPolicy});const startTime=Date.now();return new Promise((resolve,reject)=>{const cb=eventData=>{waitSpan?.end({output:eventData,attributes:{eventReceived:true,waitDurationMs:Date.now()-startTime}});resolve(eventData);};if(timeout){setTimeout(()=>{emitter.off(`user-event-${event}`,cb);const error=new Error("Timeout waiting for event");waitSpan?.error({error,attributes:{eventReceived:false,waitDurationMs:Date.now()-startTime}});reject(error);},timeout);}emitter.once(`user-event-${event}`,cb);});}async executeStep({workflowId,runId,resourceId,step,stepResults,executionContext,resume,prevOutput,emitter,abortController,runtimeContext,skipEmits=false,writableStream,disableScorers,serializedStepGraph,tracingContext}){const startTime=resume?.steps[0]===step.id?void 0:Date.now();const resumeTime=resume?.steps[0]===step.id?Date.now():void 0;const stepCallId=randomUUID();const stepInfo={...stepResults[step.id],...(resume?.steps[0]===step.id?{resumePayload:resume?.resumePayload}:{payload:prevOutput}),...(startTime?{startedAt:startTime}:{}),...(resumeTime?{resumedAt:resumeTime}:{}),status:"running"};const stepAISpan=tracingContext.currentSpan?.createChildSpan({name:`workflow step: '${step.id}'`,type:"workflow_step"/* WORKFLOW_STEP */,input:prevOutput,attributes:{stepId:step.id},tracingPolicy:this.options?.tracingPolicy});if(!skipEmits){await emitter.emit("watch",{type:"watch",payload:{currentStep:{id:step.id,...stepInfo},workflowState:{status:"running",steps:{...stepResults,[step.id]:{...stepInfo}},result:null,error:null}},eventTimestamp:Date.now()});await emitter.emit("watch-v2",{type:"workflow-step-start",payload:{id:step.id,stepCallId,...stepInfo}});}await this.persistStepUpdate({workflowId,runId,resourceId,serializedStepGraph,stepResults:{...stepResults,[step.id]:stepInfo},executionContext,workflowStatus:"running",runtimeContext});const _runStep=(step2,spanName,attributes)=>{return async data=>{const telemetry=this.mastra?.getTelemetry();const span=executionContext.executionSpan;if(!telemetry||!span){return step2.execute(data);}return context.with(trace.setSpan(context.active(),span),async()=>{return telemetry.traceMethod(step2.execute.bind(step2),{spanName,attributes})(data);});};};const runStep=_runStep(step,`workflow.${workflowId}.step.${step.id}`,{componentName:workflowId,runId,resourceId:resourceId??""});let execResults;const retries=step.retries??executionContext.retryConfig.attempts??0;const delay2=executionContext.retryConfig.delay??0;for(let i=0;i<retries+1;i++){if(i>0&&delay2){await new Promise(resolve=>setTimeout(resolve,delay2));}try{let suspended;let bailed;const result=await runStep({runId,resourceId,workflowId,mastra:this.mastra?wrapMastra(this.mastra,{currentSpan:stepAISpan}):void 0,runtimeContext,inputData:prevOutput,runCount:this.getOrGenerateRunCount(step.id),resumeData:resume?.steps[0]===step.id?resume?.resumePayload:void 0,tracingContext:{currentSpan:stepAISpan},getInitData:()=>stepResults?.input,getStepResult:step2=>{if(!step2?.id){return null;}const result2=stepResults[step2.id];if(result2?.status==="success"){return result2.output;}return null;},suspend:async suspendPayload=>{executionContext.suspendedPaths[step.id]=executionContext.executionPath;suspended={payload:suspendPayload};},bail:result2=>{bailed={payload:result2};},abort:()=>{abortController?.abort();},// Only pass resume data if this step was actually suspended before
|
|
200
204
|
// This prevents pending nested workflows from trying to resume instead of start
|
|
201
205
|
resume:stepResults[step.id]?.status==="suspended"?{steps:resume?.steps?.slice(1)||[],resumePayload:resume?.resumePayload,// @ts-ignore
|
|
202
206
|
runId:stepResults[step.id]?.suspendPayload?.__workflow_meta?.runId}:void 0,[EMITTER_SYMBOL]:emitter,[STREAM_FORMAT_SYMBOL]:executionContext.format,engine:{},abortSignal:abortController?.signal,writer:new ToolStream({prefix:"workflow-step",callId:stepCallId,name:step.id,runId},writableStream),// Disable scorers must be explicitly set to false they are on by default
|
|
203
|
-
scorers:disableScorers===false?void 0:step.scorers});if(step.scorers){await this.runScorers({scorers:step.scorers,runId,input:prevOutput,output:result,workflowId,stepId:step.id,runtimeContext,disableScorers,tracingContext:{currentSpan:tracingContext.currentSpan
|
|
204
|
-
suspend:async _suspendPayload=>{},bail:()=>{},abort:()=>{abortController?.abort();},[EMITTER_SYMBOL]:emitter,[STREAM_FORMAT_SYMBOL]:executionContext.format,engine:{},abortSignal:abortController?.signal,writer:new ToolStream({prefix:"workflow-step",callId:randomUUID(),name:"conditional",runId},writableStream)});evalSpan?.end({output:result,attributes:{result:!!result}});return result?index:null;}catch(e){const error=this.preprocessExecutionError(e,{id:"WORKFLOW_CONDITION_EVALUATION_FAILED",domain:"MASTRA_WORKFLOW"/* MASTRA_WORKFLOW */,category:"USER"/* USER */,details:{workflowId,runId}},"Error evaluating condition: ");evalSpan?.error({error,attributes:{result:false}});return null;}}))).filter(index=>index!==null);const stepsToRun=entry.steps.filter((_,index)=>truthyIndexes.includes(index));conditionalSpan?.update({attributes:{truthyIndexes,selectedSteps:stepsToRun.map(s=>s.type==="step"?s.step.id:`control-${s.type}`)}});const stepsToExecute=stepsToRun.filter(step=>{if(resume&&step.type==="step"){const existingResult=stepResults[step.step.id];return !existingResult||existingResult.status==="suspended"||existingResult.status==="failed";}return true;});const results=await Promise.all(stepsToExecute.map((step,_index)=>this.executeEntry({workflowId,runId,resourceId,entry:step,prevStep,stepResults,serializedStepGraph,resume,executionContext:{workflowId,runId,executionPath:[...executionContext.executionPath,stepsToRun.indexOf(step)],suspendedPaths:executionContext.suspendedPaths,retryConfig:executionContext.retryConfig,executionSpan:executionContext.executionSpan},tracingContext:{currentSpan:conditionalSpan
|
|
207
|
+
scorers:disableScorers===false?void 0:step.scorers});if(step.scorers){await this.runScorers({scorers:step.scorers,runId,input:prevOutput,output:result,workflowId,stepId:step.id,runtimeContext,disableScorers,tracingContext:{currentSpan:tracingContext.currentSpan}});}if(suspended){execResults={status:"suspended",suspendPayload:suspended.payload,suspendedAt:Date.now()};}else if(bailed){execResults={status:"bailed",output:bailed.payload,endedAt:Date.now()};}else {execResults={status:"success",output:result,endedAt:Date.now()};}break;}catch(e){const error=this.preprocessExecutionError(e,{id:"WORKFLOW_STEP_INVOKE_FAILED",domain:"MASTRA_WORKFLOW"/* MASTRA_WORKFLOW */,category:"USER"/* USER */,details:{workflowId,runId,stepId:step.id}},`Error executing step ${step.id}: `);stepAISpan?.error({error,attributes:{status:"failed"}});execResults={status:"failed",error:error?.stack,endedAt:Date.now()};}}if(!skipEmits){await emitter.emit("watch",{type:"watch",payload:{currentStep:{id:step.id,...stepInfo,...execResults},workflowState:{status:"running",steps:{...stepResults,[step.id]:{...stepInfo,...execResults}},result:null,error:null}},eventTimestamp:Date.now()});if(execResults.status==="suspended"){await emitter.emit("watch-v2",{type:"workflow-step-suspended",payload:{id:step.id,stepCallId,...execResults}});}else {await emitter.emit("watch-v2",{type:"workflow-step-result",payload:{id:step.id,stepCallId,...execResults}});await emitter.emit("watch-v2",{type:"workflow-step-finish",payload:{id:step.id,stepCallId,metadata:{}}});}}if(execResults.status!="failed"){stepAISpan?.end({output:execResults.output,attributes:{status:execResults.status}});}return {...stepInfo,...execResults};}async runScorers({scorers,runId,input,output,workflowId,stepId,runtimeContext,disableScorers,tracingContext}){let scorersToUse=scorers;if(typeof scorersToUse==="function"){try{scorersToUse=await scorersToUse({runtimeContext});}catch(error){this.preprocessExecutionError(error,{id:"WORKFLOW_FAILED_TO_FETCH_SCORERS",domain:"MASTRA_WORKFLOW"/* MASTRA_WORKFLOW */,category:"USER"/* USER */,details:{runId,workflowId,stepId}},"Error fetching scorers: ");}}if(!disableScorers&&scorersToUse&&Object.keys(scorersToUse||{}).length>0){for(const[id,scorerObject]of Object.entries(scorersToUse||{})){runScorer({scorerId:id,scorerObject,runId,input:[input],output,runtimeContext,entity:{id:workflowId,stepId},structuredOutput:true,source:"LIVE",entityType:"WORKFLOW",tracingContext});}}}async executeParallel({workflowId,runId,resourceId,entry,prevStep,serializedStepGraph,stepResults,resume,executionContext,tracingContext,emitter,abortController,runtimeContext,writableStream,disableScorers}){const parallelSpan=tracingContext.currentSpan?.createChildSpan({type:"workflow_parallel"/* WORKFLOW_PARALLEL */,name:`parallel: '${entry.steps.length} branches'`,input:this.getStepOutput(stepResults,prevStep),attributes:{branchCount:entry.steps.length,parallelSteps:entry.steps.map(s=>s.type==="step"?s.step.id:`control-${s.type}`)},tracingPolicy:this.options?.tracingPolicy});let execResults;const results=await Promise.all(entry.steps.map((step,i)=>this.executeEntry({workflowId,runId,resourceId,entry:step,prevStep,stepResults,serializedStepGraph,resume,executionContext:{workflowId,runId,executionPath:[...executionContext.executionPath,i],suspendedPaths:executionContext.suspendedPaths,retryConfig:executionContext.retryConfig,executionSpan:executionContext.executionSpan},tracingContext:{currentSpan:parallelSpan},emitter,abortController,runtimeContext,writableStream,disableScorers})));const hasFailed=results.find(result=>result.result.status==="failed");const hasSuspended=results.find(result=>result.result.status==="suspended");if(hasFailed){execResults={status:"failed",error:hasFailed.result.error};}else if(hasSuspended){execResults={status:"suspended",payload:hasSuspended.result.suspendPayload};}else if(abortController?.signal?.aborted){execResults={status:"canceled"};}else {execResults={status:"success",output:results.reduce((acc,result,index)=>{if(result.result.status==="success"){acc[entry.steps[index].step.id]=result.result.output;}return acc;},{})};}if(execResults.status==="failed"){parallelSpan?.error({error:new Error(execResults.error)});}else {parallelSpan?.end({output:execResults.output||execResults});}return execResults;}async executeConditional({workflowId,runId,resourceId,entry,prevOutput,prevStep,serializedStepGraph,stepResults,resume,executionContext,tracingContext,emitter,abortController,runtimeContext,writableStream,disableScorers}){const conditionalSpan=tracingContext.currentSpan?.createChildSpan({type:"workflow_conditional"/* WORKFLOW_CONDITIONAL */,name:`conditional: '${entry.conditions.length} conditions'`,input:prevOutput,attributes:{conditionCount:entry.conditions.length},tracingPolicy:this.options?.tracingPolicy});let execResults;const truthyIndexes=(await Promise.all(entry.conditions.map(async(cond,index)=>{const evalSpan=conditionalSpan?.createChildSpan({type:"workflow_conditional_eval"/* WORKFLOW_CONDITIONAL_EVAL */,name:`condition '${index}'`,input:prevOutput,attributes:{conditionIndex:index},tracingPolicy:this.options?.tracingPolicy});try{const result=await cond({runId,workflowId,mastra:this.mastra,runtimeContext,inputData:prevOutput,runCount:-1,tracingContext:{currentSpan:evalSpan},getInitData:()=>stepResults?.input,getStepResult:step=>{if(!step?.id){return null;}const result2=stepResults[step.id];if(result2?.status==="success"){return result2.output;}return null;},// TODO: this function shouldn't have suspend probably?
|
|
208
|
+
suspend:async _suspendPayload=>{},bail:()=>{},abort:()=>{abortController?.abort();},[EMITTER_SYMBOL]:emitter,[STREAM_FORMAT_SYMBOL]:executionContext.format,engine:{},abortSignal:abortController?.signal,writer:new ToolStream({prefix:"workflow-step",callId:randomUUID(),name:"conditional",runId},writableStream)});evalSpan?.end({output:result,attributes:{result:!!result}});return result?index:null;}catch(e){const error=this.preprocessExecutionError(e,{id:"WORKFLOW_CONDITION_EVALUATION_FAILED",domain:"MASTRA_WORKFLOW"/* MASTRA_WORKFLOW */,category:"USER"/* USER */,details:{workflowId,runId}},"Error evaluating condition: ");evalSpan?.error({error,attributes:{result:false}});return null;}}))).filter(index=>index!==null);const stepsToRun=entry.steps.filter((_,index)=>truthyIndexes.includes(index));conditionalSpan?.update({attributes:{truthyIndexes,selectedSteps:stepsToRun.map(s=>s.type==="step"?s.step.id:`control-${s.type}`)}});const stepsToExecute=stepsToRun.filter(step=>{if(resume&&step.type==="step"){const existingResult=stepResults[step.step.id];return !existingResult||existingResult.status==="suspended"||existingResult.status==="failed";}return true;});const results=await Promise.all(stepsToExecute.map((step,_index)=>this.executeEntry({workflowId,runId,resourceId,entry:step,prevStep,stepResults,serializedStepGraph,resume,executionContext:{workflowId,runId,executionPath:[...executionContext.executionPath,stepsToRun.indexOf(step)],suspendedPaths:executionContext.suspendedPaths,retryConfig:executionContext.retryConfig,executionSpan:executionContext.executionSpan},tracingContext:{currentSpan:conditionalSpan},emitter,abortController,runtimeContext,writableStream,disableScorers})));const mergedStepResults={...stepResults};results.forEach(result=>{if("stepResults"in result&&result.stepResults){Object.assign(mergedStepResults,result.stepResults);}});const allResults=stepsToRun.map(step=>{if(step.type==="step"){const stepResult=mergedStepResults[step.step.id];if(stepResult){return {result:stepResult};}}return {result:{status:"success",output:{}}};}).filter(Boolean);const hasFailed=allResults.find(result=>result.result.status==="failed");const hasSuspended=allResults.find(result=>result.result.status==="suspended");if(hasFailed){execResults={status:"failed",error:hasFailed.result.error};}else if(hasSuspended){execResults={status:"suspended",payload:hasSuspended.result.suspendPayload};}else if(abortController?.signal?.aborted){execResults={status:"canceled"};}else {execResults={status:"success",output:allResults.reduce((acc,result,index)=>{if(result.result.status==="success"){acc[stepsToRun[index].step.id]=result.result.output;}return acc;},{})};}if(execResults.status==="failed"){conditionalSpan?.error({error:new Error(execResults.error)});}else {conditionalSpan?.end({output:execResults.output||execResults});}return execResults;}async executeLoop({workflowId,runId,resourceId,entry,prevOutput,stepResults,resume,executionContext,tracingContext,emitter,abortController,runtimeContext,writableStream,disableScorers,serializedStepGraph}){const{step,condition}=entry;const loopSpan=tracingContext.currentSpan?.createChildSpan({type:"workflow_loop"/* WORKFLOW_LOOP */,name:`loop: '${entry.loopType}'`,input:prevOutput,attributes:{loopType:entry.loopType},tracingPolicy:this.options?.tracingPolicy});let isTrue=true;let iteration=0;const prevPayload=stepResults[step.id]?.payload;let result={status:"success",output:prevPayload??prevOutput};let currentResume=resume;do{result=await this.executeStep({workflowId,runId,resourceId,step,stepResults,executionContext,resume:currentResume,prevOutput:result.output,tracingContext:{currentSpan:loopSpan},emitter,abortController,runtimeContext,writableStream,disableScorers,serializedStepGraph});if(currentResume&&result.status!=="suspended"){currentResume=void 0;}if(result.status!=="success"){loopSpan?.end({attributes:{totalIterations:iteration}});return result;}const evalSpan=loopSpan?.createChildSpan({type:"workflow_conditional_eval"/* WORKFLOW_CONDITIONAL_EVAL */,name:`condition: '${entry.loopType}'`,input:selectFields(result.output,["stepResult","output.text","output.object","messages"]),attributes:{conditionIndex:iteration},tracingPolicy:this.options?.tracingPolicy});isTrue=await condition({workflowId,runId,mastra:this.mastra,runtimeContext,inputData:result.output,runCount:-1,tracingContext:{currentSpan:evalSpan},getInitData:()=>stepResults?.input,getStepResult:step2=>{if(!step2?.id){return null;}const result2=stepResults[step2.id];return result2?.status==="success"?result2.output:null;},suspend:async _suspendPayload=>{},bail:()=>{},abort:()=>{abortController?.abort();},[EMITTER_SYMBOL]:emitter,[STREAM_FORMAT_SYMBOL]:executionContext.format,engine:{},abortSignal:abortController?.signal,writer:new ToolStream({prefix:"workflow-step",callId:randomUUID(),name:"loop",runId},writableStream)});evalSpan?.end({output:isTrue});iteration++;}while(entry.loopType==="dowhile"?isTrue:!isTrue);loopSpan?.end({output:result.output,attributes:{totalIterations:iteration}});return result;}async executeForeach({workflowId,runId,resourceId,entry,prevOutput,stepResults,resume,executionContext,tracingContext,emitter,abortController,runtimeContext,writableStream,disableScorers,serializedStepGraph}){const{step,opts}=entry;const results=[];const concurrency=opts.concurrency;const startTime=resume?.steps[0]===step.id?void 0:Date.now();const resumeTime=resume?.steps[0]===step.id?Date.now():void 0;const stepInfo={...stepResults[step.id],...(resume?.steps[0]===step.id?{resumePayload:resume?.resumePayload}:{payload:prevOutput}),...(startTime?{startedAt:startTime}:{}),...(resumeTime?{resumedAt:resumeTime}:{})};const loopSpan=tracingContext.currentSpan?.createChildSpan({type:"workflow_loop"/* WORKFLOW_LOOP */,name:`loop: 'foreach'`,input:prevOutput,attributes:{loopType:"foreach",concurrency},tracingPolicy:this.options?.tracingPolicy});await emitter.emit("watch",{type:"watch",payload:{currentStep:{id:step.id,status:"running",...stepInfo},workflowState:{status:"running",steps:{...stepResults,[step.id]:{status:"running",...stepInfo}},result:null,error:null}},eventTimestamp:Date.now()});await emitter.emit("watch-v2",{type:"workflow-step-start",payload:{id:step.id,...stepInfo,status:"running"}});for(let i=0;i<prevOutput.length;i+=concurrency){const items=prevOutput.slice(i,i+concurrency);const itemsResults=await Promise.all(items.map(item=>{return this.executeStep({workflowId,runId,resourceId,step,stepResults,executionContext,resume,prevOutput:item,tracingContext:{currentSpan:loopSpan},emitter,abortController,runtimeContext,skipEmits:true,writableStream,disableScorers,serializedStepGraph});}));for(const result of itemsResults){if(result.status!=="success"){const{status,error,suspendPayload,suspendedAt,endedAt,output}=result;const execResults={status,error,suspendPayload,suspendedAt,endedAt,output};await emitter.emit("watch",{type:"watch",payload:{currentStep:{id:step.id,...stepInfo,...execResults},workflowState:{status:"running",steps:{...stepResults,[step.id]:{...stepInfo,...execResults}},result:null,error:null}},eventTimestamp:Date.now()});if(execResults.status==="suspended"){await emitter.emit("watch-v2",{type:"workflow-step-suspended",payload:{id:step.id,...execResults}});}else {await emitter.emit("watch-v2",{type:"workflow-step-result",payload:{id:step.id,...execResults}});await emitter.emit("watch-v2",{type:"workflow-step-finish",payload:{id:step.id,metadata:{}}});}return result;}results.push(result?.output);}}await emitter.emit("watch",{type:"watch",payload:{currentStep:{id:step.id,...stepInfo,status:"success",output:results,endedAt:Date.now()},workflowState:{status:"running",steps:{...stepResults,[step.id]:{...stepInfo,status:"success",output:results,endedAt:Date.now()}},result:null,error:null}},eventTimestamp:Date.now()});await emitter.emit("watch-v2",{type:"workflow-step-result",payload:{id:step.id,status:"success",output:results,endedAt:Date.now()}});await emitter.emit("watch-v2",{type:"workflow-step-finish",payload:{id:step.id,metadata:{}}});loopSpan?.end({output:results});return {...stepInfo,status:"success",output:results,//@ts-ignore
|
|
205
209
|
endedAt:Date.now()};}async persistStepUpdate({workflowId,runId,resourceId,stepResults,serializedStepGraph,executionContext,workflowStatus,result,error,runtimeContext}){const runtimeContextObj={};runtimeContext.forEach((value,key)=>{runtimeContextObj[key]=value;});await this.mastra?.getStorage()?.persistWorkflowSnapshot({workflowName:workflowId,runId,resourceId,snapshot:{runId,status:workflowStatus,value:{},context:stepResults,activePaths:[],serializedStepGraph,suspendedPaths:executionContext.suspendedPaths,waitingPaths:{},result,error,runtimeContext:runtimeContextObj,// @ts-ignore
|
|
206
210
|
timestamp:Date.now()}});}async executeEntry({workflowId,runId,resourceId,entry,prevStep,serializedStepGraph,stepResults,resume,executionContext,tracingContext,emitter,abortController,runtimeContext,writableStream,disableScorers}){const prevOutput=this.getStepOutput(stepResults,prevStep);let execResults;if(entry.type==="step"){const{step}=entry;execResults=await this.executeStep({workflowId,runId,resourceId,step,stepResults,executionContext,resume,prevOutput,tracingContext,emitter,abortController,runtimeContext,writableStream,disableScorers,serializedStepGraph});}else if(resume?.resumePath?.length&&entry.type==="parallel"){const idx=resume.resumePath.shift();const resumedStepResult=await this.executeEntry({workflowId,runId,resourceId,entry:entry.steps[idx],prevStep,serializedStepGraph,stepResults,resume,executionContext:{workflowId,runId,executionPath:[...executionContext.executionPath,idx],suspendedPaths:executionContext.suspendedPaths,retryConfig:executionContext.retryConfig,executionSpan:executionContext.executionSpan},tracingContext,emitter,abortController,runtimeContext,writableStream,disableScorers});if(resumedStepResult.stepResults){Object.assign(stepResults,resumedStepResult.stepResults);}const allParallelStepsComplete=entry.steps.every(parallelStep=>{if(parallelStep.type==="step"){const stepResult=stepResults[parallelStep.step.id];return stepResult&&stepResult.status==="success";}return true;});if(allParallelStepsComplete){execResults={status:"success",output:entry.steps.reduce((acc,parallelStep)=>{if(parallelStep.type==="step"){const stepResult=stepResults[parallelStep.step.id];if(stepResult&&stepResult.status==="success"){acc[parallelStep.step.id]=stepResult.output;}}return acc;},{})};}else {const stillSuspended=entry.steps.find(parallelStep=>{if(parallelStep.type==="step"){const stepResult=stepResults[parallelStep.step.id];return stepResult&&stepResult.status==="suspended";}return false;});execResults={status:"suspended",payload:stillSuspended&&stillSuspended.type==="step"?stepResults[stillSuspended.step.id]?.suspendPayload:{}};}const updatedExecutionContext={...executionContext,...resumedStepResult.executionContext,suspendedPaths:{...executionContext.suspendedPaths,...resumedStepResult.executionContext?.suspendedPaths}};if(execResults.status==="suspended"){entry.steps.forEach((parallelStep,stepIndex)=>{if(parallelStep.type==="step"){const stepResult=stepResults[parallelStep.step.id];if(stepResult&&stepResult.status==="suspended"){updatedExecutionContext.suspendedPaths[parallelStep.step.id]=[...executionContext.executionPath,stepIndex];}}});}return {result:execResults,stepResults:resumedStepResult.stepResults,executionContext:updatedExecutionContext};}else if(entry.type==="parallel"){execResults=await this.executeParallel({workflowId,runId,entry,prevStep,stepResults,serializedStepGraph,resume,executionContext,tracingContext,emitter,abortController,runtimeContext,writableStream,disableScorers});}else if(entry.type==="conditional"){execResults=await this.executeConditional({workflowId,runId,entry,prevStep,prevOutput,stepResults,serializedStepGraph,resume,executionContext,tracingContext,emitter,abortController,runtimeContext,writableStream,disableScorers});}else if(entry.type==="loop"){execResults=await this.executeLoop({workflowId,runId,entry,prevStep,prevOutput,stepResults,resume,executionContext,tracingContext,emitter,abortController,runtimeContext,writableStream,disableScorers,serializedStepGraph});}else if(entry.type==="foreach"){execResults=await this.executeForeach({workflowId,runId,entry,prevStep,prevOutput,stepResults,resume,executionContext,tracingContext,emitter,abortController,runtimeContext,writableStream,disableScorers,serializedStepGraph});}else if(entry.type==="sleep"){const startedAt=Date.now();await emitter.emit("watch",{type:"watch",payload:{currentStep:{id:entry.id,status:"waiting",payload:prevOutput,startedAt},workflowState:{status:"waiting",steps:{...stepResults,[entry.id]:{status:"waiting",payload:prevOutput,startedAt}},result:null,error:null}},eventTimestamp:Date.now()});await emitter.emit("watch-v2",{type:"workflow-step-waiting",payload:{id:entry.id,payload:prevOutput,startedAt,status:"waiting"}});await this.persistStepUpdate({workflowId,runId,resourceId,serializedStepGraph,stepResults,executionContext,workflowStatus:"waiting",runtimeContext});await this.executeSleep({workflowId,runId,entry,prevStep,prevOutput,stepResults,serializedStepGraph,resume,executionContext,tracingContext,emitter,abortController,runtimeContext,writableStream});await this.persistStepUpdate({workflowId,runId,resourceId,serializedStepGraph,stepResults,executionContext,workflowStatus:"running",runtimeContext});const endedAt=Date.now();const stepInfo={payload:prevOutput,startedAt,endedAt};execResults={...stepInfo,status:"success",output:prevOutput};stepResults[entry.id]={...stepInfo,status:"success",output:prevOutput};await emitter.emit("watch",{type:"watch",payload:{currentStep:{id:entry.id,...execResults},workflowState:{status:"running",steps:{...stepResults,[entry.id]:{...execResults}},result:null,error:null}},eventTimestamp:Date.now()});await emitter.emit("watch-v2",{type:"workflow-step-result",payload:{id:entry.id,endedAt,status:"success",output:prevOutput}});await emitter.emit("watch-v2",{type:"workflow-step-finish",payload:{id:entry.id,metadata:{}}});}else if(entry.type==="sleepUntil"){const startedAt=Date.now();await emitter.emit("watch",{type:"watch",payload:{currentStep:{id:entry.id,status:"waiting",payload:prevOutput,startedAt},workflowState:{status:"waiting",steps:{...stepResults,[entry.id]:{status:"waiting",payload:prevOutput,startedAt}},result:null,error:null}},eventTimestamp:Date.now()});await emitter.emit("watch-v2",{type:"workflow-step-waiting",payload:{id:entry.id,payload:prevOutput,startedAt,status:"waiting"}});await this.persistStepUpdate({workflowId,runId,resourceId,serializedStepGraph,stepResults,executionContext,workflowStatus:"waiting",runtimeContext});await this.executeSleepUntil({workflowId,runId,entry,prevStep,prevOutput,stepResults,serializedStepGraph,resume,executionContext,tracingContext,emitter,abortController,runtimeContext,writableStream});await this.persistStepUpdate({workflowId,runId,resourceId,serializedStepGraph,stepResults,executionContext,workflowStatus:"running",runtimeContext});const endedAt=Date.now();const stepInfo={payload:prevOutput,startedAt,endedAt};execResults={...stepInfo,status:"success",output:prevOutput};stepResults[entry.id]={...stepInfo,status:"success",output:prevOutput};await emitter.emit("watch",{type:"watch",payload:{currentStep:{id:entry.id,...execResults},workflowState:{status:"running",steps:{...stepResults,[entry.id]:{...execResults}},result:null,error:null}},eventTimestamp:Date.now()});await emitter.emit("watch-v2",{type:"workflow-step-result",payload:{id:entry.id,endedAt,status:"success",output:prevOutput}});await emitter.emit("watch-v2",{type:"workflow-step-finish",payload:{id:entry.id,metadata:{}}});}else if(entry.type==="waitForEvent"){const startedAt=Date.now();let eventData;await emitter.emit("watch",{type:"watch",payload:{currentStep:{id:entry.step.id,status:"waiting",payload:prevOutput,startedAt},workflowState:{status:"waiting",steps:{...stepResults,[entry.step.id]:{status:"waiting",payload:prevOutput,startedAt}},result:null,error:null}},eventTimestamp:Date.now()});await emitter.emit("watch-v2",{type:"workflow-step-waiting",payload:{id:entry.step.id,payload:prevOutput,startedAt,status:"waiting"}});await this.persistStepUpdate({workflowId,runId,resourceId,serializedStepGraph,stepResults,executionContext,workflowStatus:"waiting",runtimeContext});try{eventData=await this.executeWaitForEvent({event:entry.event,emitter,timeout:entry.timeout,tracingContext});const{step}=entry;execResults=await this.executeStep({workflowId,runId,resourceId,step,stepResults,executionContext,resume:{resumePayload:eventData,steps:[entry.step.id]},prevOutput,tracingContext,emitter,abortController,runtimeContext,writableStream,disableScorers,serializedStepGraph});}catch(error){execResults={status:"failed",error};}const endedAt=Date.now();const stepInfo={payload:prevOutput,startedAt,endedAt};execResults={...execResults,...stepInfo};}if(entry.type==="step"||entry.type==="waitForEvent"||entry.type==="loop"||entry.type==="foreach"){stepResults[entry.step.id]=execResults;}if(abortController?.signal?.aborted){execResults={...execResults,status:"canceled"};}await this.persistStepUpdate({workflowId,runId,resourceId,serializedStepGraph,stepResults,executionContext,workflowStatus:execResults.status==="success"?"running":execResults.status,runtimeContext});if(execResults.status==="canceled"){await emitter.emit("watch-v2",{type:"workflow-canceled",payload:{}});}return {result:execResults,stepResults,executionContext};}};// src/workflows/workflow.ts
|
|
207
211
|
function mapVariable(config){return config;}function createStep(params){if(params instanceof Agent){return {id:params.name,// @ts-ignore
|
|
@@ -213,7 +217,7 @@ outputSchema:z.object({text:z.string()}),execute:async({inputData,[EMITTER_SYMBO
|
|
|
213
217
|
runtimeContext,onFinish:result=>{streamPromise.resolve(result.text);},abortSignal});stream=fullStream;await emitter.emit("watch-v2",{type:"tool-call-streaming-start",...(toolData??{})});for await(const chunk of stream){if(chunk.type==="text-delta"){await emitter.emit("watch-v2",{type:"tool-call-delta",...(toolData??{}),argsTextDelta:chunk.textDelta});}}await emitter.emit("watch-v2",{type:"tool-call-streaming-finish",...(toolData??{})});}else {const modelOutput=await params.streamVNext(inputData.prompt,{runtimeContext,onFinish:result=>{streamPromise.resolve(result.text);}// abortSignal,
|
|
214
218
|
});stream=modelOutput.fullStream;for await(const chunk of stream){await writer.write(chunk);}}if(abortSignal.aborted){return abort();}return {text:await streamPromise.promise};}};}if(params instanceof Tool){if(!params.inputSchema||!params.outputSchema){throw new Error("Tool must have input and output schemas defined");}return {// TODO: tool probably should have strong id type
|
|
215
219
|
// @ts-ignore
|
|
216
|
-
id:params.id,inputSchema:params.inputSchema,outputSchema:params.outputSchema,execute:async({inputData,mastra,runtimeContext,tracingContext})=>{return params.execute({context:inputData,mastra,runtimeContext,tracingContext});}};}return {id:params.id,description:params.description,inputSchema:params.inputSchema,outputSchema:params.outputSchema,resumeSchema:params.resumeSchema,suspendSchema:params.suspendSchema,scorers:params.scorers,retries:params.retries,execute:params.execute.bind(params)};}function cloneStep(step,opts){return {id:opts.id,description:step.description,inputSchema:step.inputSchema,outputSchema:step.outputSchema,execute:step.execute,retries:step.retries};}function createWorkflow(params){return new Workflow(params);}function cloneWorkflow(workflow,opts){const wf=new Workflow({id:opts.id,inputSchema:workflow.inputSchema,outputSchema:workflow.outputSchema,steps:workflow.stepDefs,mastra:workflow.mastra});wf.setStepFlow(workflow.stepGraph);wf.commit();return wf;}var Workflow=class extends MastraBase{id;description;inputSchema;outputSchema;steps;stepDefs;stepFlow;serializedStepFlow;executionEngine;executionGraph;retryConfig;#mastra;#runs=/* @__PURE__ */new Map();constructor({mastra,id,inputSchema,outputSchema,description,executionEngine,retryConfig,steps}){super({name:id,component:RegisteredLogger.WORKFLOW});this.id=id;this.description=description;this.inputSchema=inputSchema;this.outputSchema=outputSchema;this.retryConfig=retryConfig??{attempts:0,delay:0};this.executionGraph=this.buildExecutionGraph();this.stepFlow=[];this.serializedStepFlow=[];this.#mastra=mastra;this.steps={};this.stepDefs=steps;if(!executionEngine){this.executionEngine=new DefaultExecutionEngine({mastra:this.#mastra});}else {this.executionEngine=executionEngine;}this.#runs=/* @__PURE__ */new Map();}get runs(){return this.#runs;}get mastra(){return this.#mastra;}__registerMastra(mastra){this.#mastra=mastra;this.executionEngine.__registerMastra(mastra);}__registerPrimitives(p){if(p.telemetry){this.__setTelemetry(p.telemetry);}if(p.logger){this.__setLogger(p.logger);}}setStepFlow(stepFlow){this.stepFlow=stepFlow;}/**
|
|
220
|
+
id:params.id,inputSchema:params.inputSchema,outputSchema:params.outputSchema,execute:async({inputData,mastra,runtimeContext,tracingContext})=>{return params.execute({context:inputData,mastra,runtimeContext,tracingContext});}};}return {id:params.id,description:params.description,inputSchema:params.inputSchema,outputSchema:params.outputSchema,resumeSchema:params.resumeSchema,suspendSchema:params.suspendSchema,scorers:params.scorers,retries:params.retries,execute:params.execute.bind(params)};}function cloneStep(step,opts){return {id:opts.id,description:step.description,inputSchema:step.inputSchema,outputSchema:step.outputSchema,execute:step.execute,retries:step.retries};}function createWorkflow(params){return new Workflow(params);}function cloneWorkflow(workflow,opts){const wf=new Workflow({id:opts.id,inputSchema:workflow.inputSchema,outputSchema:workflow.outputSchema,steps:workflow.stepDefs,mastra:workflow.mastra});wf.setStepFlow(workflow.stepGraph);wf.commit();return wf;}var Workflow=class extends MastraBase{id;description;inputSchema;outputSchema;steps;stepDefs;stepFlow;serializedStepFlow;executionEngine;executionGraph;options;retryConfig;#mastra;#runs=/* @__PURE__ */new Map();constructor({mastra,id,inputSchema,outputSchema,description,executionEngine,retryConfig,steps,options}){super({name:id,component:RegisteredLogger.WORKFLOW});this.id=id;this.description=description;this.inputSchema=inputSchema;this.outputSchema=outputSchema;this.retryConfig=retryConfig??{attempts:0,delay:0};this.executionGraph=this.buildExecutionGraph();this.stepFlow=[];this.serializedStepFlow=[];this.#mastra=mastra;this.steps={};this.stepDefs=steps;this.options=options;if(!executionEngine){this.executionEngine=new DefaultExecutionEngine({mastra:this.#mastra,options:{tracingPolicy:options?.tracingPolicy}});}else {this.executionEngine=executionEngine;}this.#runs=/* @__PURE__ */new Map();}get runs(){return this.#runs;}get mastra(){return this.#mastra;}__registerMastra(mastra){this.#mastra=mastra;this.executionEngine.__registerMastra(mastra);}__registerPrimitives(p){if(p.telemetry){this.__setTelemetry(p.telemetry);}if(p.logger){this.__setLogger(p.logger);}}setStepFlow(stepFlow){this.stepFlow=stepFlow;}/**
|
|
217
221
|
* Adds a step to the workflow
|
|
218
222
|
* @param step The step to add to the workflow
|
|
219
223
|
* @returns The workflow instance for chaining
|
|
@@ -238,20 +242,16 @@ condition,loopType:"dountil",serializedCondition:{id:`${step.id}-condition`,fn:c
|
|
|
238
242
|
* This method should be called after all steps have been added to the workflow
|
|
239
243
|
* @returns A built workflow instance ready for execution
|
|
240
244
|
*/commit(){this.executionGraph=this.buildExecutionGraph();return this;}get stepGraph(){return this.stepFlow;}get serializedStepGraph(){return this.serializedStepFlow;}/**
|
|
241
|
-
*
|
|
242
|
-
* @
|
|
243
|
-
|
|
244
|
-
* @param options.resourceId Optional resource ID to associate with this run
|
|
245
|
-
* @param options.disableScorers Optional flag to disable scorers for this run
|
|
246
|
-
* @returns A Run instance that can be used to execute the workflow
|
|
247
|
-
*/createRun(options){if(this.stepFlow.length===0){throw new Error("Execution flow of workflow is not defined. Add steps to the workflow via .then(), .branch(), etc.");}if(!this.executionGraph.steps){throw new Error("Uncommitted step flow changes detected. Call .commit() to register the steps.");}const runIdToUse=options?.runId||this.#mastra?.generateId()||randomUUID();const run=this.#runs.get(runIdToUse)??new Run({workflowId:this.id,runId:runIdToUse,resourceId:options?.resourceId,executionEngine:this.executionEngine,executionGraph:this.executionGraph,mastra:this.#mastra,retryConfig:this.retryConfig,serializedStepGraph:this.serializedStepGraph,disableScorers:options?.disableScorers,cleanup:()=>this.#runs.delete(runIdToUse)});this.#runs.set(runIdToUse,run);this.mastra?.getLogger().warn("createRun() will be removed on September 16th, 2025. Use createRunAsync() instead.");return run;}/**
|
|
245
|
+
* @deprecated Use createRunAsync() instead.
|
|
246
|
+
* @throws {Error} Always throws an error directing users to use createRunAsync()
|
|
247
|
+
*/createRun(_options){throw new Error("createRun() has been deprecated. Please use createRunAsync() instead.\n\nMigration guide:\n Before: const run = workflow.createRun();\n After: const run = await workflow.createRunAsync();\n\nNote: createRunAsync() is an async method, so make sure your calling function is async.");}/**
|
|
248
248
|
* Creates a new workflow run instance and stores a snapshot of the workflow in the storage
|
|
249
249
|
* @param options Optional configuration for the run
|
|
250
250
|
* @param options.runId Optional custom run ID, defaults to a random UUID
|
|
251
251
|
* @param options.resourceId Optional resource ID to associate with this run
|
|
252
252
|
* @param options.disableScorers Optional flag to disable scorers for this run
|
|
253
253
|
* @returns A Run instance that can be used to execute the workflow
|
|
254
|
-
*/async createRunAsync(options){if(this.stepFlow.length===0){throw new Error("Execution flow of workflow is not defined. Add steps to the workflow via .then(), .branch(), etc.");}if(!this.executionGraph.steps){throw new Error("Uncommitted step flow changes detected. Call .commit() to register the steps.");}const runIdToUse=options?.runId||this.#mastra?.generateId()||randomUUID();const run=this.#runs.get(runIdToUse)??new Run({workflowId:this.id,runId:runIdToUse,resourceId:options?.resourceId,executionEngine:this.executionEngine,executionGraph:this.executionGraph,mastra:this.#mastra,retryConfig:this.retryConfig,serializedStepGraph:this.serializedStepGraph,disableScorers:options?.disableScorers,cleanup:()=>this.#runs.delete(runIdToUse)});this.#runs.set(runIdToUse,run);const workflowSnapshotInStorage=await this.getWorkflowRunExecutionResult(runIdToUse,false);if(!workflowSnapshotInStorage){await this.mastra?.getStorage()?.persistWorkflowSnapshot({workflowName:this.id,runId:runIdToUse,resourceId:options?.resourceId,snapshot:{runId:runIdToUse,status:"pending",value:{},context:{},activePaths:[],serializedStepGraph:this.serializedStepGraph,suspendedPaths:{},waitingPaths:{},result:void 0,error:void 0,// @ts-ignore
|
|
254
|
+
*/async createRunAsync(options){if(this.stepFlow.length===0){throw new Error("Execution flow of workflow is not defined. Add steps to the workflow via .then(), .branch(), etc.");}if(!this.executionGraph.steps){throw new Error("Uncommitted step flow changes detected. Call .commit() to register the steps.");}const runIdToUse=options?.runId||this.#mastra?.generateId()||randomUUID();const run=this.#runs.get(runIdToUse)??new Run({workflowId:this.id,runId:runIdToUse,resourceId:options?.resourceId,executionEngine:this.executionEngine,executionGraph:this.executionGraph,mastra:this.#mastra,retryConfig:this.retryConfig,serializedStepGraph:this.serializedStepGraph,disableScorers:options?.disableScorers,cleanup:()=>this.#runs.delete(runIdToUse),tracingPolicy:this.options?.tracingPolicy});this.#runs.set(runIdToUse,run);const workflowSnapshotInStorage=await this.getWorkflowRunExecutionResult(runIdToUse,false);if(!workflowSnapshotInStorage){await this.mastra?.getStorage()?.persistWorkflowSnapshot({workflowName:this.id,runId:runIdToUse,resourceId:options?.resourceId,snapshot:{runId:runIdToUse,status:"pending",value:{},context:{},activePaths:[],serializedStepGraph:this.serializedStepGraph,suspendedPaths:{},waitingPaths:{},result:void 0,error:void 0,// @ts-ignore
|
|
255
255
|
timestamp:Date.now()}});}return run;}async getScorers({runtimeContext=new RuntimeContext()}={}){const steps=this.steps;if(!steps||Object.keys(steps).length===0){return {};}const scorers={};for(const step of Object.values(steps)){if(step.scorers){let scorersToUse=step.scorers;if(typeof scorersToUse==="function"){scorersToUse=await scorersToUse({runtimeContext});}for(const[id,scorer]of Object.entries(scorersToUse)){scorers[id]=scorer;}}}return scorers;}// This method should only be called internally for nested workflow execution, as well as from mastra server handlers
|
|
256
256
|
// To run a workflow use `.createRunAsync` and then `.start` or `.resume`
|
|
257
257
|
async execute({runId,inputData,resumeData,suspend,resume,[EMITTER_SYMBOL]:emitter,mastra,runtimeContext,abort,abortSignal,runCount,tracingContext,writer}){this.__registerMastra(mastra);const isResume=!!(resume?.steps&&resume.steps.length>0);const run=isResume?await this.createRunAsync({runId:resume.runId}):await this.createRunAsync({runId});const nestedAbortCb=()=>{abort();};run.abortController.signal.addEventListener("abort",nestedAbortCb);abortSignal.addEventListener("abort",async()=>{run.abortController.signal.removeEventListener("abort",nestedAbortCb);await run.cancel();});const unwatchV2=run.watch(event=>{emitter.emit("nested-watch-v2",{event,workflowId:this.id});},"watch-v2");const unwatch=run.watch(event=>{emitter.emit("nested-watch",{event,workflowId:this.id,runId:run.runId,isResume:!!resume?.steps?.length});},"watch");if(runCount&&runCount>0&&resume?.steps?.length&&runtimeContext){runtimeContext.set("__mastraWorflowInputData",inputData);}const res=isResume?await run.resume({resumeData,step:resume.steps,runtimeContext,tracingContext}):await run.start({inputData,runtimeContext,tracingContext,writableStream:writer});unwatch();unwatchV2();const suspendedSteps=Object.entries(res.steps).filter(([_stepName,stepResult])=>{const stepRes=stepResult;return stepRes?.status==="suspended";});if(suspendedSteps?.length){for(const[stepName,stepResult]of suspendedSteps){const suspendPath=[stepName,...(stepResult?.suspendPayload?.__workflow_meta?.path??[])];await suspend({...stepResult?.suspendPayload,__workflow_meta:{runId:run.runId,path:suspendPath}});}}if(res.status==="failed"){throw res.error;}return res.status==="success"?res.result:void 0;}async getWorkflowRuns(args){const storage=this.#mastra?.getStorage();if(!storage){this.logger.debug("Cannot get workflow runs. Mastra storage is not initialized");return {runs:[],total:0};}return storage.getWorkflowRuns({workflowName:this.id,...(args??{})});}async getWorkflowRunById(runId){const storage=this.#mastra?.getStorage();if(!storage){this.logger.debug("Cannot get workflow runs from storage. Mastra storage is not initialized");return this.#runs.get(runId)?{...this.#runs.get(runId),workflowName:this.id}:null;}const run=await storage.getWorkflowRunById({runId,workflowName:this.id});return run??(this.#runs.get(runId)?{...this.#runs.get(runId),workflowName:this.id}:null);}async getWorkflowRunSteps({runId,workflowId}){const storage=this.#mastra?.getStorage();if(!storage){this.logger.debug("Cannot get workflow run steps. Mastra storage is not initialized");return {};}const run=await storage.getWorkflowRunById({runId,workflowName:workflowId});let snapshot=run?.snapshot;if(!snapshot){return {};}if(typeof snapshot==="string"){try{snapshot=JSON.parse(snapshot);}catch(e){this.logger.debug("Cannot get workflow run execution result. Snapshot is not a valid JSON string",e);return {};}}const{serializedStepGraph,context}=snapshot;const{input,...steps}=context;let finalSteps={};for(const step of Object.keys(steps)){const stepGraph=serializedStepGraph.find(stepGraph2=>stepGraph2?.step?.id===step);finalSteps[step]=steps[step];if(stepGraph&&stepGraph?.step?.component==="WORKFLOW"){const nestedSteps=await this.getWorkflowRunSteps({runId,workflowId:step});if(nestedSteps){const updatedNestedSteps=Object.entries(nestedSteps).reduce((acc,[key,value])=>{acc[`${step}.${key}`]=value;return acc;},{});finalSteps={...finalSteps,...updatedNestedSteps};}}}return finalSteps;}async getWorkflowRunExecutionResult(runId,withNestedWorkflows=true){const storage=this.#mastra?.getStorage();if(!storage){this.logger.debug("Cannot get workflow run execution result. Mastra storage is not initialized");return null;}const run=await storage.getWorkflowRunById({runId,workflowName:this.id});let snapshot=run?.snapshot;if(!snapshot){return null;}if(typeof snapshot==="string"){try{snapshot=JSON.parse(snapshot);}catch(e){this.logger.debug("Cannot get workflow run execution result. Snapshot is not a valid JSON string",e);return null;}}const fullSteps=withNestedWorkflows?await this.getWorkflowRunSteps({runId,workflowId:this.id}):snapshot.context;return {status:snapshot.status,result:snapshot.result,error:snapshot.error,payload:snapshot.context?.input,steps:fullSteps};}};var Run=class{#abortController;emitter;/**
|
|
@@ -263,6 +263,8 @@ async execute({runId,inputData,resumeData,suspend,resume,[EMITTER_SYMBOL]:emitte
|
|
|
263
263
|
*/resourceId;/**
|
|
264
264
|
* Whether to disable scorers for this run
|
|
265
265
|
*/disableScorers;/**
|
|
266
|
+
* Options around how to trace this run
|
|
267
|
+
*/tracingPolicy;/**
|
|
266
268
|
* Internal state of the workflow run
|
|
267
269
|
*/state={};/**
|
|
268
270
|
* The execution engine for this run
|
|
@@ -272,9 +274,9 @@ async execute({runId,inputData,resumeData,suspend,resume,[EMITTER_SYMBOL]:emitte
|
|
|
272
274
|
* The serialized step graph for this run
|
|
273
275
|
*/serializedStepGraph;/**
|
|
274
276
|
* The storage for this run
|
|
275
|
-
*/#mastra;get mastra(){return this.#mastra;}closeStreamAction;executionResults;cleanup;retryConfig;constructor(params){this.workflowId=params.workflowId;this.runId=params.runId;this.resourceId=params.resourceId;this.serializedStepGraph=params.serializedStepGraph;this.executionEngine=params.executionEngine;this.executionGraph=params.executionGraph;this.#mastra=params.mastra;this.emitter=new EventEmitter();this.retryConfig=params.retryConfig;this.cleanup=params.cleanup;this.disableScorers=params.disableScorers;}get abortController(){if(!this.#abortController){this.#abortController=new AbortController();}return this.#abortController;}/**
|
|
277
|
+
*/#mastra;get mastra(){return this.#mastra;}closeStreamAction;executionResults;cleanup;retryConfig;constructor(params){this.workflowId=params.workflowId;this.runId=params.runId;this.resourceId=params.resourceId;this.serializedStepGraph=params.serializedStepGraph;this.executionEngine=params.executionEngine;this.executionGraph=params.executionGraph;this.#mastra=params.mastra;this.emitter=new EventEmitter();this.retryConfig=params.retryConfig;this.cleanup=params.cleanup;this.disableScorers=params.disableScorers;this.tracingPolicy=params.tracingPolicy;}get abortController(){if(!this.#abortController){this.#abortController=new AbortController();}return this.#abortController;}/**
|
|
276
278
|
* Cancels the workflow execution
|
|
277
|
-
*/async cancel(){this.abortController?.abort();}async sendEvent(event,data){this.emitter.emit(`user-event-${event}`,data);}async _start({inputData,runtimeContext,writableStream,tracingContext,tracingOptions,format}){const workflowAISpan=getOrCreateSpan({type:"workflow_run"/* WORKFLOW_RUN */,name:`workflow run: '${this.workflowId}'`,input:inputData,attributes:{workflowId:this.workflowId},
|
|
279
|
+
*/async cancel(){this.abortController?.abort();}async sendEvent(event,data){this.emitter.emit(`user-event-${event}`,data);}async _start({inputData,runtimeContext,writableStream,tracingContext,tracingOptions,format}){const workflowAISpan=getOrCreateSpan({type:"workflow_run"/* WORKFLOW_RUN */,name:`workflow run: '${this.workflowId}'`,input:inputData,attributes:{workflowId:this.workflowId},tracingPolicy:this.tracingPolicy,tracingOptions,tracingContext,runtimeContext});const traceId=getValidTraceId(workflowAISpan);const result=await this.executionEngine.execute({workflowId:this.workflowId,runId:this.runId,resourceId:this.resourceId,disableScorers:this.disableScorers,graph:this.executionGraph,serializedStepGraph:this.serializedStepGraph,input:inputData,emitter:{emit:async(event,data)=>{this.emitter.emit(event,data);},on:(event,callback)=>{this.emitter.on(event,callback);},off:(event,callback)=>{this.emitter.off(event,callback);},once:(event,callback)=>{this.emitter.once(event,callback);}},retryConfig:this.retryConfig,runtimeContext:runtimeContext??new RuntimeContext(),abortController:this.abortController,writableStream,workflowAISpan,format});if(result.status!=="suspended"){this.cleanup?.();}result.traceId=traceId;return result;}/**
|
|
278
280
|
* Starts the workflow execution with the provided input
|
|
279
281
|
* @param input The input data for the workflow
|
|
280
282
|
* @returns A promise that resolves to the workflow output
|
|
@@ -286,20 +288,26 @@ async execute({runId,inputData,resumeData,suspend,resume,[EMITTER_SYMBOL]:emitte
|
|
|
286
288
|
* Starts the workflow execution with the provided input as a stream
|
|
287
289
|
* @param input The input data for the workflow
|
|
288
290
|
* @returns A promise that resolves to the workflow output
|
|
289
|
-
*/streamVNext({inputData,runtimeContext,tracingContext,format}={}){this.closeStreamAction=async()=>{};return new MastraWorkflowStream({run:this,createStream:()=>{const{readable,writable}=new TransformStream({transform(chunk,controller){controller.enqueue(chunk);}});let buffer=[];let isWriting=false;const tryWrite=async()=>{const chunkToWrite=buffer;buffer=[];if(chunkToWrite.length===0||isWriting){return;}isWriting=true;let watchWriter=writable.getWriter();try{for(const chunk of chunkToWrite){await watchWriter.write(chunk);}}finally{watchWriter.releaseLock();}isWriting=false;setImmediate(tryWrite);};const unwatch=this.watch(async({type,from="WORKFLOW"/* WORKFLOW */,payload})=>{buffer.push({type,runId:this.runId,from,payload:{stepName:payload.id,...payload}});await tryWrite();},"watch-v2");this.closeStreamAction=async()=>{unwatch();try{await writable.close();}catch(err){console.error("Error closing stream:",err);}};const executionResults=this._start({inputData,runtimeContext,tracingContext,writableStream:writable,format}).then(result=>{if(result.status!=="suspended"){this.closeStreamAction?.().catch(()=>{});}return result;});this.executionResults=executionResults;return readable;}});}watch(cb,type="watch"){const watchCb=event=>{this.updateState(event.payload);cb({type:event.type,payload:this.getState(),eventTimestamp:event.eventTimestamp});};const nestedWatchCb=({event,workflowId})=>{try{const{type:type2,payload,eventTimestamp}=event;const prefixedSteps=Object.fromEntries(Object.entries(payload?.workflowState?.steps??{}).map(([stepId,step])=>[`${workflowId}.${stepId}`,step]));const newPayload={currentStep:{...payload?.currentStep,id:`${workflowId}.${payload?.currentStep?.id}`},workflowState:{steps:prefixedSteps}};this.updateState(newPayload);cb({type:type2,payload:this.getState(),eventTimestamp});}catch(e){console.error(e);}};const nestedWatchV2Cb=({event,workflowId})=>{this.emitter.emit("watch-v2",{...event,...(event.payload?.id?{payload:{...event.payload,id:`${workflowId}.${event.payload.id}`}}:{})});};if(type==="watch"){this.emitter.on("watch",watchCb);this.emitter.on("nested-watch",nestedWatchCb);}else if(type==="watch-v2"){this.emitter.on("watch-v2",cb);this.emitter.on("nested-watch-v2",nestedWatchV2Cb);}return ()=>{if(type==="watch-v2"){this.emitter.off("watch-v2",cb);this.emitter.off("nested-watch-v2",nestedWatchV2Cb);}else {this.emitter.off("watch",watchCb);this.emitter.off("nested-watch",nestedWatchCb);}};}async watchAsync(cb,type="watch"){return this.watch(cb,type);}async resume(params){const snapshot=await this.#mastra?.getStorage()?.loadWorkflowSnapshot({workflowName:this.workflowId,runId:this.runId});if(!snapshot){throw new Error("No snapshot found for this workflow run");}let steps;if(params.step){steps=(Array.isArray(params.step)?params.step:[params.step]).map(step=>typeof step==="string"?step:step?.id);}else {const suspendedStepPaths=[];Object.entries(snapshot?.suspendedPaths??{}).forEach(([stepId,_executionPath])=>{const stepResult=snapshot?.context?.[stepId];if(stepResult&&typeof stepResult==="object"&&"status"in stepResult){const stepRes=stepResult;if(stepRes.status==="suspended"){const nestedPath=stepRes.suspendPayload?.__workflow_meta?.path;if(nestedPath&&Array.isArray(nestedPath)){suspendedStepPaths.push([stepId,...nestedPath]);}else {suspendedStepPaths.push([stepId]);}}}});if(suspendedStepPaths.length===0){throw new Error("No suspended steps found in this workflow run");}if(suspendedStepPaths.length===1){steps=suspendedStepPaths[0];}else {const pathStrings=suspendedStepPaths.map(path=>`[${path.join(", ")}]`);throw new Error(`Multiple suspended steps found: ${pathStrings.join(", ")}. Please specify which step to resume using the "step" parameter.`);}}if(!params.runCount){if(snapshot.status!=="suspended"){throw new Error("This workflow run was not suspended");}const suspendedStepIds=Object.keys(snapshot?.suspendedPaths??{});const isStepSuspended=suspendedStepIds.includes(steps?.[0]??"");if(!isStepSuspended){throw new Error(`This workflow step "${steps?.[0]}" was not suspended. Available suspended steps: [${suspendedStepIds.join(", ")}]`);}}let runtimeContextInput;if(params.runCount&¶ms.runCount>0&¶ms.runtimeContext){runtimeContextInput=params.runtimeContext.get("__mastraWorflowInputData");params.runtimeContext.delete("__mastraWorflowInputData");}const stepResults={...(snapshot?.context??{}),input:runtimeContextInput??snapshot?.context?.input};let runtimeContextToUse=params.runtimeContext??new RuntimeContext();Object.entries(snapshot?.runtimeContext??{}).forEach(([key,value])=>{if(!runtimeContextToUse.has(key)){runtimeContextToUse.set(key,value);}});const workflowAISpan=getOrCreateSpan({type:"workflow_run"/* WORKFLOW_RUN */,name:`workflow run: '${this.workflowId}'`,input:params.resumeData,attributes:{workflowId:this.workflowId},
|
|
291
|
+
*/streamVNext({inputData,runtimeContext,tracingContext,format}={}){this.closeStreamAction=async()=>{};return new MastraWorkflowStream({run:this,createStream:()=>{const{readable,writable}=new TransformStream({transform(chunk,controller){controller.enqueue(chunk);}});let buffer=[];let isWriting=false;const tryWrite=async()=>{const chunkToWrite=buffer;buffer=[];if(chunkToWrite.length===0||isWriting){return;}isWriting=true;let watchWriter=writable.getWriter();try{for(const chunk of chunkToWrite){await watchWriter.write(chunk);}}finally{watchWriter.releaseLock();}isWriting=false;setImmediate(tryWrite);};const unwatch=this.watch(async({type,from="WORKFLOW"/* WORKFLOW */,payload})=>{buffer.push({type,runId:this.runId,from,payload:{stepName:payload.id,...payload}});await tryWrite();},"watch-v2");this.closeStreamAction=async()=>{unwatch();try{await writable.close();}catch(err){console.error("Error closing stream:",err);}};const executionResults=this._start({inputData,runtimeContext,tracingContext,writableStream:writable,format}).then(result=>{if(result.status!=="suspended"){this.closeStreamAction?.().catch(()=>{});}return result;});this.executionResults=executionResults;return readable;}});}watch(cb,type="watch"){const watchCb=event=>{this.updateState(event.payload);cb({type:event.type,payload:this.getState(),eventTimestamp:event.eventTimestamp});};const nestedWatchCb=({event,workflowId})=>{try{const{type:type2,payload,eventTimestamp}=event;const prefixedSteps=Object.fromEntries(Object.entries(payload?.workflowState?.steps??{}).map(([stepId,step])=>[`${workflowId}.${stepId}`,step]));const newPayload={currentStep:{...payload?.currentStep,id:`${workflowId}.${payload?.currentStep?.id}`},workflowState:{steps:prefixedSteps}};this.updateState(newPayload);cb({type:type2,payload:this.getState(),eventTimestamp});}catch(e){console.error(e);}};const nestedWatchV2Cb=({event,workflowId})=>{this.emitter.emit("watch-v2",{...event,...(event.payload?.id?{payload:{...event.payload,id:`${workflowId}.${event.payload.id}`}}:{})});};if(type==="watch"){this.emitter.on("watch",watchCb);this.emitter.on("nested-watch",nestedWatchCb);}else if(type==="watch-v2"){this.emitter.on("watch-v2",cb);this.emitter.on("nested-watch-v2",nestedWatchV2Cb);}return ()=>{if(type==="watch-v2"){this.emitter.off("watch-v2",cb);this.emitter.off("nested-watch-v2",nestedWatchV2Cb);}else {this.emitter.off("watch",watchCb);this.emitter.off("nested-watch",nestedWatchCb);}};}async watchAsync(cb,type="watch"){return this.watch(cb,type);}async resume(params){const snapshot=await this.#mastra?.getStorage()?.loadWorkflowSnapshot({workflowName:this.workflowId,runId:this.runId});if(!snapshot){throw new Error("No snapshot found for this workflow run");}let steps;if(params.step){steps=(Array.isArray(params.step)?params.step:[params.step]).map(step=>typeof step==="string"?step:step?.id);}else {const suspendedStepPaths=[];Object.entries(snapshot?.suspendedPaths??{}).forEach(([stepId,_executionPath])=>{const stepResult=snapshot?.context?.[stepId];if(stepResult&&typeof stepResult==="object"&&"status"in stepResult){const stepRes=stepResult;if(stepRes.status==="suspended"){const nestedPath=stepRes.suspendPayload?.__workflow_meta?.path;if(nestedPath&&Array.isArray(nestedPath)){suspendedStepPaths.push([stepId,...nestedPath]);}else {suspendedStepPaths.push([stepId]);}}}});if(suspendedStepPaths.length===0){throw new Error("No suspended steps found in this workflow run");}if(suspendedStepPaths.length===1){steps=suspendedStepPaths[0];}else {const pathStrings=suspendedStepPaths.map(path=>`[${path.join(", ")}]`);throw new Error(`Multiple suspended steps found: ${pathStrings.join(", ")}. Please specify which step to resume using the "step" parameter.`);}}if(!params.runCount){if(snapshot.status!=="suspended"){throw new Error("This workflow run was not suspended");}const suspendedStepIds=Object.keys(snapshot?.suspendedPaths??{});const isStepSuspended=suspendedStepIds.includes(steps?.[0]??"");if(!isStepSuspended){throw new Error(`This workflow step "${steps?.[0]}" was not suspended. Available suspended steps: [${suspendedStepIds.join(", ")}]`);}}let runtimeContextInput;if(params.runCount&¶ms.runCount>0&¶ms.runtimeContext){runtimeContextInput=params.runtimeContext.get("__mastraWorflowInputData");params.runtimeContext.delete("__mastraWorflowInputData");}const stepResults={...(snapshot?.context??{}),input:runtimeContextInput??snapshot?.context?.input};let runtimeContextToUse=params.runtimeContext??new RuntimeContext();Object.entries(snapshot?.runtimeContext??{}).forEach(([key,value])=>{if(!runtimeContextToUse.has(key)){runtimeContextToUse.set(key,value);}});const workflowAISpan=getOrCreateSpan({type:"workflow_run"/* WORKFLOW_RUN */,name:`workflow run: '${this.workflowId}'`,input:params.resumeData,attributes:{workflowId:this.workflowId},tracingPolicy:this.tracingPolicy,tracingOptions:params.tracingOptions,tracingContext:params.tracingContext,runtimeContext:runtimeContextToUse});const traceId=getValidTraceId(workflowAISpan);const executionResultPromise=this.executionEngine.execute({workflowId:this.workflowId,runId:this.runId,graph:this.executionGraph,serializedStepGraph:this.serializedStepGraph,input:snapshot?.context?.input,resume:{steps,stepResults,resumePayload:params.resumeData,// @ts-ignore
|
|
290
292
|
resumePath:snapshot?.suspendedPaths?.[steps?.[0]]},emitter:{emit:(event,data)=>{this.emitter.emit(event,data);return Promise.resolve();},on:(event,callback)=>{this.emitter.on(event,callback);},off:(event,callback)=>{this.emitter.off(event,callback);},once:(event,callback)=>{this.emitter.once(event,callback);}},runtimeContext:runtimeContextToUse,abortController:this.abortController,workflowAISpan}).then(result=>{if(result.status!=="suspended"){this.closeStreamAction?.().catch(()=>{});}result.traceId=traceId;return result;});this.executionResults=executionResultPromise;return executionResultPromise;}/**
|
|
291
293
|
* Returns the current state of the workflow run
|
|
292
294
|
* @returns The current state of the workflow run
|
|
293
295
|
*/getState(){return this.state;}updateState(state){if(state.currentStep){this.state.currentStep=state.currentStep;}else if(state.workflowState?.status!=="running"){delete this.state.currentStep;}if(state.workflowState){this.state.workflowState=deepMergeWorkflowState(this.state.workflowState??{},state.workflowState??{});}}/**
|
|
294
296
|
* @access private
|
|
295
297
|
* @returns The execution results of the workflow run
|
|
296
|
-
*/_getExecutionResults(){return this.executionResults;}};function deepMergeWorkflowState(a,b){if(!a||typeof a!=="object")return b;if(!b||typeof b!=="object")return a;const result={...a};for(const key in b){if(b[key]===void 0)continue;if(b[key]!==null&&typeof b[key]==="object"){const aVal=result[key];const bVal=b[key];if(Array.isArray(bVal)){result[key]=bVal.filter(item=>item!==void 0);}else if(typeof aVal==="object"&&aVal!==null){result[key]=deepMergeWorkflowState(aVal,bVal);}else {result[key]=bVal;}}else {result[key]=b[key];}}return result;}// src/loop/
|
|
298
|
+
*/_getExecutionResults(){return this.executionResults;}};function deepMergeWorkflowState(a,b){if(!a||typeof a!=="object")return b;if(!b||typeof b!=="object")return a;const result={...a};for(const key in b){if(b[key]===void 0)continue;if(b[key]!==null&&typeof b[key]==="object"){const aVal=result[key];const bVal=b[key];if(Array.isArray(bVal)){result[key]=bVal.filter(item=>item!==void 0);}else if(typeof aVal==="object"&&aVal!==null){result[key]=deepMergeWorkflowState(aVal,bVal);}else {result[key]=bVal;}}else {result[key]=b[key];}}return result;}// src/loop/workflows/schema.ts
|
|
299
|
+
var languageModelUsageSchema=z5.object({inputTokens:z5.number(),outputTokens:z5.number(),totalTokens:z5.number(),reasoningTokens:z5.number().optional(),cachedInputTokens:z5.number().optional()});var llmIterationStepResultSchema=z5.object({reason:z5.string(),warnings:z5.array(z5.any()),isContinued:z5.boolean(),logprobs:z5.any().optional(),totalUsage:languageModelUsageSchema.optional(),headers:z5.record(z5.string()).optional(),messageId:z5.string().optional(),request:z5.record(z5.any()).optional()});var llmIterationOutputSchema=z5.object({messageId:z5.string(),messages:z5.object({all:z5.array(z5.any()),// ModelMessage[] but too complex to validate at runtime
|
|
300
|
+
user:z5.array(z5.any()),nonUser:z5.array(z5.any())}),output:z5.object({text:z5.string().optional(),reasoning:z5.array(z5.any()).optional(),reasoningText:z5.string().optional(),files:z5.array(z5.any()).optional(),// GeneratedFile[]
|
|
301
|
+
toolCalls:z5.array(z5.any()).optional(),// TypedToolCall[]
|
|
302
|
+
toolResults:z5.array(z5.any()).optional(),// TypedToolResult[]
|
|
303
|
+
sources:z5.array(z5.any()).optional(),// LanguageModelV2Source[]
|
|
304
|
+
staticToolCalls:z5.array(z5.any()).optional(),dynamicToolCalls:z5.array(z5.any()).optional(),staticToolResults:z5.array(z5.any()).optional(),dynamicToolResults:z5.array(z5.any()).optional(),usage:languageModelUsageSchema,steps:z5.array(z5.any())// StepResult[]
|
|
305
|
+
}),metadata:z5.object({id:z5.string().optional(),model:z5.string().optional(),modelId:z5.string().optional(),timestamp:z5.date().optional(),providerMetadata:z5.record(z5.any()).optional(),headers:z5.record(z5.string()).optional(),request:z5.record(z5.any()).optional()}),stepResult:llmIterationStepResultSchema});var toolCallInputSchema=z5.object({toolCallId:z5.string(),toolName:z5.string(),args:z5.record(z5.any()),providerMetadata:z5.record(z5.any()).optional(),providerExecuted:z5.boolean().optional(),output:z5.any().optional()});var toolCallOutputSchema=toolCallInputSchema.extend({result:z5.any(),error:z5.any().optional()});// src/loop/workflows/agentic-execution/llm-execution-step.ts
|
|
297
306
|
var MastraModelInput=class extends MastraBase{initialize({runId,createStream,onResult}){const self=this;const stream=new ReadableStream({async start(controller){try{const stream2=await createStream();onResult({warnings:stream2.warnings,request:stream2.request,rawResponse:stream2.rawResponse||stream2.response||{}});await self.transform({runId,stream:stream2.stream,controller});controller.close();}catch(error){controller.error(error);}}});return stream;}};// src/stream/aisdk/v5/input.ts
|
|
298
307
|
var AISDKV5InputStream=class extends MastraModelInput{constructor({component,name}){super({component,name});}async transform({runId,stream,controller}){for await(const chunk of stream){const transformedChunk=convertFullStreamChunkToMastra(chunk,{runId});if(transformedChunk){controller.enqueue(transformedChunk);}}}};// src/stream/aisdk/v5/model-supports.ts
|
|
299
308
|
function getModelSupport(modelId,provider){return modelSupports.find(m=>m.modelId===modelId&&m.provider===provider);}var modelSupports=[];// src/stream/aisdk/v5/execute.ts
|
|
300
|
-
function execute({runId,model,providerOptions,inputMessages,tools,toolChoice,options,onResult,modelStreamSpan,telemetry_settings,includeRawChunks,modelSettings,output,headers}){const v5=new AISDKV5InputStream({component:"LLM",name:model.modelId});const toolsAndToolChoice=prepareToolsAndToolChoice({tools,toolChoice,activeTools:options?.activeTools});if(modelStreamSpan&&toolsAndToolChoice?.tools?.length&&telemetry_settings?.recordOutputs!==false){modelStreamSpan.setAttributes({"stream.prompt.tools":toolsAndToolChoice?.tools?.map(tool=>JSON.stringify(tool))});}const modelSupports2=getModelSupport(model.modelId,model.provider);const modelSupportsResponseFormat=modelSupports2?.capabilities.responseFormat?.support==="full";const responseFormat=output?getResponseFormat(output):void 0;let prompt=inputMessages;if(output&&responseFormat?.type==="json"&&!modelSupportsResponseFormat){prompt=injectJsonInstructionIntoMessages({messages:inputMessages,schema:responseFormat.schema});}const stream=v5.initialize({runId,onResult,createStream:async()=>{try{const stream2=await model.doStream({...toolsAndToolChoice,prompt,providerOptions,abortSignal:options?.abortSignal,includeRawChunks,responseFormat:modelSupportsResponseFormat?responseFormat:void 0,...(modelSettings??{}),headers});return stream2;}catch(error){console.error("Error creating stream",error);if(isAbortError$1(error)&&options?.abortSignal?.aborted){console.log("Abort error",error);}return {stream:new ReadableStream({start:async controller=>{controller.enqueue({type:"error",error:{message:error instanceof Error?error.message:JSON.stringify(error),stack:error instanceof Error?error.stack:void 0}});controller.close();}}),warnings:[],request:{},rawResponse:{}};}}});return stream;}// src/loop/
|
|
301
|
-
var AgenticRunState=class{#state;constructor({_internal,model}){this.#state={responseMetadata:{id:_internal?.generateId?.(),timestamp:_internal?.currentDate?.(),modelId:model.modelId,headers:void 0},isReasoning:false,isStreaming:false,providerOptions:void 0,hasToolCallStreaming:false,hasErrored:false,reasoningDeltas:[],textDeltas:[],stepResult:void 0};}setState(state){this.#state={...this.#state,...state};}get state(){return this.#state;}};// src/loop/
|
|
302
|
-
var llmIterationOutputSchema=z6.object({messageId:z6.string(),messages:z6.object({all:z6.array(z6.any()),user:z6.array(z6.any()),nonUser:z6.array(z6.any())}),output:z6.any(),metadata:z6.any(),stepResult:z6.any().optional()});var toolCallInputSchema=z6.object({toolCallId:z6.string(),toolName:z6.string(),args:z6.any(),providerMetadata:z6.any(),providerExecuted:z6.boolean().optional(),output:z6.any().optional()});var toolCallOutputSchema=toolCallInputSchema.extend({result:z6.any(),error:z6.any().optional()});// src/loop/workflow/llm-execution.ts
|
|
309
|
+
function execute({runId,model,providerOptions,inputMessages,tools,toolChoice,options,onResult,modelStreamSpan,telemetry_settings,includeRawChunks,modelSettings,output,headers,shouldThrowError}){const v5=new AISDKV5InputStream({component:"LLM",name:model.modelId});const toolsAndToolChoice=prepareToolsAndToolChoice({tools,toolChoice,activeTools:options?.activeTools});if(modelStreamSpan&&toolsAndToolChoice?.tools?.length&&telemetry_settings?.recordOutputs!==false){modelStreamSpan.setAttributes({"stream.prompt.tools":toolsAndToolChoice?.tools?.map(tool=>JSON.stringify(tool))});}const modelSupports2=getModelSupport(model.modelId,model.provider);const modelSupportsResponseFormat=modelSupports2?.capabilities.responseFormat?.support==="full";const responseFormat=output?getResponseFormat(output):void 0;let prompt=inputMessages;if(output&&responseFormat?.type==="json"&&!modelSupportsResponseFormat){prompt=injectJsonInstructionIntoMessages({messages:inputMessages,schema:responseFormat.schema});}const stream=v5.initialize({runId,onResult,createStream:async()=>{try{const stream2=await model.doStream({...toolsAndToolChoice,prompt,providerOptions,abortSignal:options?.abortSignal,includeRawChunks,responseFormat:modelSupportsResponseFormat?responseFormat:void 0,...(modelSettings??{}),headers});return stream2;}catch(error){console.error("Error creating stream",error);if(isAbortError$1(error)&&options?.abortSignal?.aborted){console.log("Abort error",error);}if(shouldThrowError){throw error;}return {stream:new ReadableStream({start:async controller=>{controller.enqueue({type:"error",error:{message:error instanceof Error?error.message:JSON.stringify(error),stack:error instanceof Error?error.stack:void 0}});controller.close();}}),warnings:[],request:{},rawResponse:{}};}}});return stream;}// src/loop/workflows/run-state.ts
|
|
310
|
+
var AgenticRunState=class{#state;constructor({_internal,model}){this.#state={responseMetadata:{id:_internal?.generateId?.(),timestamp:_internal?.currentDate?.(),modelId:model.modelId,modelVersion:model.specificationVersion,modelProvider:model.provider,headers:void 0},isReasoning:false,isStreaming:false,providerOptions:void 0,hasToolCallStreaming:false,hasErrored:false,reasoningDeltas:[],textDeltas:[],stepResult:void 0};}setState(state){this.#state={...this.#state,...state};}get state(){return this.#state;}};// src/loop/workflows/agentic-execution/llm-execution-step.ts
|
|
303
311
|
async function processOutputStream({tools,messageId,messageList,outputStream,runState,options,controller,responseFromModel,includeRawChunks}){for await(const chunk of outputStream.fullStream){if(!chunk){continue;}if(chunk.type=="object"){continue;}if(chunk.type!=="reasoning-delta"&&chunk.type!=="reasoning-signature"&&chunk.type!=="redacted-reasoning"&&runState.state.isReasoning){if(runState.state.reasoningDeltas.length){messageList.add({id:messageId,role:"assistant",content:[{type:"reasoning",text:runState.state.reasoningDeltas.join(""),signature:chunk.payload.signature,providerOptions:chunk.payload.providerMetadata??runState.state.providerOptions}]},"response");}runState.setState({isReasoning:false,reasoningDeltas:[]});}if(chunk.type!=="text-delta"&&chunk.type!=="tool-call"&&// not 100% sure about this being the right fix.
|
|
304
312
|
// basically for some llm providers they add response-metadata after each text-delta
|
|
305
313
|
// we then flush the chunks by calling messageList.add (a few lines down)
|
|
@@ -308,17 +316,25 @@ async function processOutputStream({tools,messageId,messageList,outputStream,run
|
|
|
308
316
|
// BUT does this cause other issues?
|
|
309
317
|
// Alternative solution: in message list allow combining text deltas together when the message source is "response" and the text parts are directly next to each other
|
|
310
318
|
// simple solution for now is to not flush text deltas on response-metadata
|
|
311
|
-
chunk.type!=="response-metadata"&&runState.state.isStreaming){if(runState.state.textDeltas.length){const textStartPayload=chunk.payload;const providerMetadata=textStartPayload.providerMetadata??runState.state.providerOptions;messageList.add({id:messageId,role:"assistant",content:[providerMetadata?{type:"text",text:runState.state.textDeltas.join(""),providerOptions:providerMetadata}:{type:"text",text:runState.state.textDeltas.join("")}]},"response");}runState.setState({isStreaming:false,textDeltas:[]});}switch(chunk.type){case "response-metadata":runState.setState({responseMetadata:{id:chunk.payload.id,timestamp:chunk.payload.timestamp,modelId:chunk.payload.modelId,headers:chunk.payload.headers}});break;case "text-delta":{const textDeltasFromState=runState.state.textDeltas;textDeltasFromState.push(chunk.payload.text);runState.setState({textDeltas:textDeltasFromState,isStreaming:true});controller.enqueue(chunk);break;}case "tool-call-input-streaming-start":{const tool=tools?.[chunk.payload.toolName]||Object.values(tools||{})?.find(tool2=>`id`in tool2&&tool2.id===chunk.payload.toolName);if(tool&&"onInputStart"in tool){try{await tool?.onInputStart?.({toolCallId:chunk.payload.toolCallId,messages:messageList.get.input.aiV5.model(),abortSignal:options?.abortSignal});}catch(error){console.error("Error calling onInputStart",error);}}controller.enqueue(chunk);break;}case "tool-call-delta":{const tool=tools?.[chunk.payload.toolName||""]||Object.values(tools||{})?.find(tool2=>`id`in tool2&&tool2.id===chunk.payload.toolName);if(tool&&"onInputDelta"in tool){try{await tool?.onInputDelta?.({inputTextDelta:chunk.payload.argsTextDelta,toolCallId:chunk.payload.toolCallId,messages:messageList.get.input.aiV5.model(),abortSignal:options?.abortSignal});}catch(error){console.error("Error calling onInputDelta",error);}}controller.enqueue(chunk);break;}case "reasoning-start":{runState.setState({providerOptions:chunk.payload.providerMetadata??runState.state.providerOptions});if(Object.values(chunk.payload.providerMetadata||{}).find(v=>v?.redactedData)){messageList.add({id:messageId,role:"assistant",content:[{type:"reasoning",text:"",providerOptions:chunk.payload.providerMetadata??runState.state.providerOptions}]},"response");controller.enqueue(chunk);break;}controller.enqueue(chunk);break;}case "reasoning-delta":{const reasoningDeltasFromState=runState.state.reasoningDeltas;reasoningDeltasFromState.push(chunk.payload.text);runState.setState({isReasoning:true,reasoningDeltas:reasoningDeltasFromState,providerOptions:chunk.payload.providerMetadata??runState.state.providerOptions});controller.enqueue(chunk);break;}case "file":messageList.add({id:messageId,role:"assistant",content:[{type:"file",data:chunk.payload.data,mimeType:chunk.payload.mimeType}]},"response");controller.enqueue(chunk);break;case "source":messageList.add({id:messageId,role:"assistant",content:{format:2,parts:[{type:"source",source:{sourceType:"url",id:chunk.payload.id,url:chunk.payload.url||"",title:chunk.payload.title,providerMetadata:chunk.payload.providerMetadata}}]},createdAt:/* @__PURE__ */new Date()},"response");controller.enqueue(chunk);break;case "finish":runState.setState({providerOptions:chunk.payload.metadata.providerMetadata,stepResult:{reason:chunk.payload.reason,logprobs:chunk.payload.logprobs,warnings:responseFromModel.warnings,totalUsage:chunk.payload.totalUsage,headers:responseFromModel.rawResponse?.headers,messageId,isContinued:!["stop","error"].includes(chunk.payload.reason),request:responseFromModel.request}});break;case "error":if(isAbortError(chunk.payload.error)&&options?.abortSignal?.aborted){break;}runState.setState({hasErrored:true});runState.setState({stepResult:{isContinued:false,reason:"error"}});let e=chunk.payload.error;if(typeof e==="object"){e=new Error(e?.message||"Unknown error");Object.assign(e,chunk.payload.error);}controller.enqueue({...chunk,payload:{...chunk.payload,error:e}});await options?.onError?.({error:e});break;default:controller.enqueue(chunk);}if(["text-delta","reasoning-delta","source","tool-call","tool-call-input-streaming-start","tool-call-delta","raw"].includes(chunk.type)){const transformedChunk=convertMastraChunkToAISDKv5({chunk});if(chunk.type==="raw"&&!includeRawChunks){return;}await options?.onChunk?.({chunk:transformedChunk});}if(runState.state.hasErrored){break;}}}function createLLMExecutionStep({model,_internal,messageId,runId,modelStreamSpan,telemetry_settings,tools,toolChoice,messageList,includeRawChunks,modelSettings,providerOptions,options,toolCallStreaming,controller,output,outputProcessors,headers,downloadRetries,downloadConcurrency}){return createStep({id:"llm-execution",inputSchema:llmIterationOutputSchema,outputSchema:llmIterationOutputSchema,execute:async({inputData,bail,tracingContext})=>{const runState=new AgenticRunState({_internal,model});let modelResult;let warnings;let request;let rawResponse;switch(model.specificationVersion){case "v2":{const messageListPromptArgs={downloadRetries,downloadConcurrency,supportedUrls:model?.supportedUrls};let inputMessages=await messageList.get.all.aiV5.llmPrompt(messageListPromptArgs);let stepModel=model;let stepToolChoice=toolChoice;let stepTools=tools;if(options?.prepareStep){try{const prepareStepResult=await options.prepareStep({stepNumber:inputData.output?.steps?.length||0,steps:inputData.output?.steps||[],model,messages:messageList.get.all.aiV5.model()});if(prepareStepResult){if(prepareStepResult.model){stepModel=prepareStepResult.model;}if(prepareStepResult.toolChoice){stepToolChoice=prepareStepResult.toolChoice;}if(prepareStepResult.activeTools&&stepTools){const activeToolsSet=new Set(prepareStepResult.activeTools);stepTools=Object.fromEntries(Object.entries(stepTools).filter(([toolName])=>activeToolsSet.has(toolName)));}if(prepareStepResult.messages){const newMessages=prepareStepResult.messages;const newMessageList=new MessageList();for(const message of newMessages){if(message.role==="system"){newMessageList.addSystem(message);}else if(message.role==="user"){newMessageList.add(message,"input");}else if(message.role==="assistant"||message.role==="tool"){newMessageList.add(message,"response");}}inputMessages=await newMessageList.get.all.aiV5.llmPrompt(messageListPromptArgs);}}}catch(error){console.error("Error in prepareStep callback:",error);}}modelResult=execute({runId,model:stepModel,providerOptions,inputMessages,tools:stepTools,toolChoice:stepToolChoice,options,modelSettings,telemetry_settings,includeRawChunks,output,headers,onResult:({warnings:warningsFromStream,request:requestFromStream,rawResponse:rawResponseFromStream})=>{warnings=warningsFromStream;request=requestFromStream||{};rawResponse=rawResponseFromStream;controller.enqueue({runId,from:"AGENT"/* AGENT */,type:"step-start",payload:{request:request||{},warnings:[],messageId}});},modelStreamSpan});break;}default:{throw new Error(`Unsupported model version: ${model.specificationVersion}`);}}const outputStream=new MastraModelOutput({model:{modelId:model.modelId,provider:model.provider,version:model.specificationVersion},stream:modelResult,messageList,messageId,options:{runId,rootSpan:modelStreamSpan,toolCallStreaming,telemetry_settings,includeRawChunks,output,outputProcessors,outputProcessorRunnerMode:"stream",tracingContext}});try{await processOutputStream({outputStream,includeRawChunks,tools,messageId,messageList,runState,options,controller,responseFromModel:{warnings,request,rawResponse}});}catch(error){console.log("Error in LLM Execution Step",error);if(isAbortError(error)&&options?.abortSignal?.aborted){await options?.onAbort?.({steps:inputData?.output?.steps??[]});controller.enqueue({type:"abort",runId,from:"AGENT"/* AGENT */,payload:{}});const usage2=outputStream._getImmediateUsage();const responseMetadata2=runState.state.responseMetadata;const text2=outputStream._getImmediateText();return bail({messageId,stepResult:{reason:"abort",warnings,isContinued:false},metadata:{providerMetadata:providerOptions,...responseMetadata2,headers:rawResponse?.headers,request},output:{text:text2,toolCalls:[],usage:usage2??inputData.output?.usage,steps:[]},messages:{all:messageList.get.all.aiV5.model(),user:messageList.get.input.aiV5.model(),nonUser:messageList.get.response.aiV5.model()}});}controller.enqueue({type:"error",runId,from:"AGENT"/* AGENT */,payload:{error}});runState.setState({hasErrored:true,stepResult:{isContinued:false,reason:"error"}});}if(outputStream.tripwire){controller.enqueue({type:"tripwire",runId,from:"AGENT"/* AGENT */,payload:{tripwireReason:outputStream.tripwireReason||"Content blocked by output processor"}});runState.setState({stepResult:{isContinued:false,reason:"abort"}});}const toolCalls=outputStream._getImmediateToolCalls()?.map(chunk=>{return chunk.payload;});if(toolCalls.length>0){const assistantContent=[...toolCalls.map(toolCall=>{return {type:"tool-call",toolCallId:toolCall.toolCallId,toolName:toolCall.toolName,args:toolCall.args};})];messageList.add({id:messageId,role:"assistant",content:assistantContent},"response");}const finishReason=runState?.state?.stepResult?.reason??outputStream._getImmediateFinishReason();const hasErrored=runState.state.hasErrored;const usage=outputStream._getImmediateUsage();const responseMetadata=runState.state.responseMetadata;const text=outputStream._getImmediateText();const tripwireTriggered=outputStream.tripwire;const steps=inputData.output?.steps||[];steps.push(new DefaultStepResult({warnings:outputStream._getImmediateWarnings(),providerMetadata:providerOptions,finishReason:runState.state.stepResult?.reason,content:messageList.get.response.aiV5.modelContent(),// @ts-ignore this is how it worked internally for transformResponse which was removed TODO: how should this actually work?
|
|
312
|
-
|
|
313
|
-
function createToolCallStep({tools,messageList,options,telemetry_settings,writer}){return createStep({id:"toolCallStep",inputSchema:toolCallInputSchema,outputSchema:toolCallOutputSchema,execute:async({inputData})=>{if(inputData.providerExecuted){const tracer2=getTracer({isEnabled:telemetry_settings?.isEnabled,tracer:telemetry_settings?.tracer});const span2=tracer2.startSpan("mastra.stream.toolCall").setAttributes({...assembleOperationName({operationId:"mastra.stream.toolCall",telemetry:telemetry_settings}),"stream.toolCall.toolName":inputData.toolName,"stream.toolCall.toolCallId":inputData.toolCallId,"stream.toolCall.args":JSON.stringify(inputData.args),"stream.toolCall.providerExecuted":true});if(inputData.output){span2.setAttributes({"stream.toolCall.result":JSON.stringify(inputData.output)});}span2.end();return {...inputData,result:inputData.output};}const tool=tools?.[inputData.toolName]||Object.values(tools||{})?.find(tool2=>`id`in tool2&&tool2.id===inputData.toolName);if(!tool){throw new Error(`Tool ${inputData.toolName} not found`);}if(tool&&"onInputAvailable"in tool){try{await tool?.onInputAvailable?.({toolCallId:inputData.toolCallId,input:inputData.args,messages:messageList.get.input.aiV5.model(),abortSignal:options?.abortSignal});}catch(error){console.error("Error calling onInputAvailable",error);}}if(!tool.execute){return inputData;}const tracer=getTracer({isEnabled:telemetry_settings?.isEnabled,tracer:telemetry_settings?.tracer});const span=tracer.startSpan("mastra.stream.toolCall").setAttributes({...assembleOperationName({operationId:"mastra.stream.toolCall",telemetry:telemetry_settings}),"stream.toolCall.toolName":inputData.toolName,"stream.toolCall.toolCallId":inputData.toolCallId,"stream.toolCall.args":JSON.stringify(inputData.args)});try{const result=await tool.execute(inputData.args,{abortSignal:options?.abortSignal,toolCallId:inputData.toolCallId,messages:messageList.get.input.aiV5.model(),writableStream:writer});span.setAttributes({"stream.toolCall.result":JSON.stringify(result)});span.end();return {result,...inputData};}catch(error){span.setStatus({code:2,message:error?.message??error});span.recordException(error);return {error,...inputData};}}});}// src/loop/
|
|
314
|
-
function
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
+
chunk.type!=="response-metadata"&&runState.state.isStreaming){if(runState.state.textDeltas.length){const textStartPayload=chunk.payload;const providerMetadata=textStartPayload.providerMetadata??runState.state.providerOptions;messageList.add({id:messageId,role:"assistant",content:[providerMetadata?{type:"text",text:runState.state.textDeltas.join(""),providerOptions:providerMetadata}:{type:"text",text:runState.state.textDeltas.join("")}]},"response");}runState.setState({isStreaming:false,textDeltas:[]});}switch(chunk.type){case "response-metadata":runState.setState({responseMetadata:{id:chunk.payload.id,timestamp:chunk.payload.timestamp,modelId:chunk.payload.modelId,headers:chunk.payload.headers}});break;case "text-delta":{const textDeltasFromState=runState.state.textDeltas;textDeltasFromState.push(chunk.payload.text);runState.setState({textDeltas:textDeltasFromState,isStreaming:true});controller.enqueue(chunk);break;}case "tool-call-input-streaming-start":{const tool=tools?.[chunk.payload.toolName]||Object.values(tools||{})?.find(tool2=>`id`in tool2&&tool2.id===chunk.payload.toolName);if(tool&&"onInputStart"in tool){try{await tool?.onInputStart?.({toolCallId:chunk.payload.toolCallId,messages:messageList.get.input.aiV5.model(),abortSignal:options?.abortSignal});}catch(error){console.error("Error calling onInputStart",error);}}controller.enqueue(chunk);break;}case "tool-call-delta":{const tool=tools?.[chunk.payload.toolName||""]||Object.values(tools||{})?.find(tool2=>`id`in tool2&&tool2.id===chunk.payload.toolName);if(tool&&"onInputDelta"in tool){try{await tool?.onInputDelta?.({inputTextDelta:chunk.payload.argsTextDelta,toolCallId:chunk.payload.toolCallId,messages:messageList.get.input.aiV5.model(),abortSignal:options?.abortSignal});}catch(error){console.error("Error calling onInputDelta",error);}}controller.enqueue(chunk);break;}case "reasoning-start":{runState.setState({providerOptions:chunk.payload.providerMetadata??runState.state.providerOptions});if(Object.values(chunk.payload.providerMetadata||{}).find(v=>v?.redactedData)){messageList.add({id:messageId,role:"assistant",content:[{type:"reasoning",text:"",providerOptions:chunk.payload.providerMetadata??runState.state.providerOptions}]},"response");controller.enqueue(chunk);break;}controller.enqueue(chunk);break;}case "reasoning-delta":{const reasoningDeltasFromState=runState.state.reasoningDeltas;reasoningDeltasFromState.push(chunk.payload.text);runState.setState({isReasoning:true,reasoningDeltas:reasoningDeltasFromState,providerOptions:chunk.payload.providerMetadata??runState.state.providerOptions});controller.enqueue(chunk);break;}case "file":messageList.add({id:messageId,role:"assistant",content:[{type:"file",data:chunk.payload.data,mimeType:chunk.payload.mimeType}]},"response");controller.enqueue(chunk);break;case "source":messageList.add({id:messageId,role:"assistant",content:{format:2,parts:[{type:"source",source:{sourceType:"url",id:chunk.payload.id,url:chunk.payload.url||"",title:chunk.payload.title,providerMetadata:chunk.payload.providerMetadata}}]},createdAt:/* @__PURE__ */new Date()},"response");controller.enqueue(chunk);break;case "finish":runState.setState({providerOptions:chunk.payload.metadata.providerMetadata,stepResult:{reason:chunk.payload.reason,logprobs:chunk.payload.logprobs,warnings:responseFromModel.warnings,totalUsage:chunk.payload.totalUsage,headers:responseFromModel.rawResponse?.headers,messageId,isContinued:!["stop","error"].includes(chunk.payload.reason),request:responseFromModel.request}});break;case "error":if(isAbortError(chunk.payload.error)&&options?.abortSignal?.aborted){break;}runState.setState({hasErrored:true});runState.setState({stepResult:{isContinued:false,reason:"error"}});let e=chunk.payload.error;if(typeof e==="object"){e=new Error(e?.message||"Unknown error");Object.assign(e,chunk.payload.error);}controller.enqueue({...chunk,payload:{...chunk.payload,error:e}});await options?.onError?.({error:e});break;default:controller.enqueue(chunk);}if(["text-delta","reasoning-delta","source","tool-call","tool-call-input-streaming-start","tool-call-delta","raw"].includes(chunk.type)){const transformedChunk=convertMastraChunkToAISDKv5({chunk});if(chunk.type==="raw"&&!includeRawChunks){return;}await options?.onChunk?.({chunk:transformedChunk});}if(runState.state.hasErrored){break;}}}function executeStreamWithFallbackModels(models){return async callback=>{let index=0;let finalResult;let done=false;for(const modelConfig of models){index++;const maxRetries=modelConfig.maxRetries||0;let attempt=0;if(done){break;}while(attempt<=maxRetries){try{console.log(`====Executing model ${modelConfig.model.modelId}, attempt ${attempt}====`);const isLastModel=attempt===maxRetries&&index===models.length;const result=await callback(modelConfig.model,isLastModel);finalResult=result;done=true;break;}catch(err){attempt++;console.log(`====Error in model ${modelConfig.model.modelId}, attempt ${attempt}====`,err);if(attempt>maxRetries){break;}}}}return finalResult;};}function createLLMExecutionStep({models,_internal,messageId,runId,modelStreamSpan,telemetry_settings,tools,toolChoice,messageList,includeRawChunks,modelSettings,providerOptions,options,toolCallStreaming,controller,output,outputProcessors,headers,downloadRetries,downloadConcurrency}){return createStep({id:"llm-execution",inputSchema:llmIterationOutputSchema,outputSchema:llmIterationOutputSchema,execute:async({inputData,bail,tracingContext})=>{let modelResult;let warnings;let request;let rawResponse;const{outputStream,callBail,runState}=await executeStreamWithFallbackModels(models)(async(model,isLastModel)=>{const runState2=new AgenticRunState({_internal,model});switch(model.specificationVersion){case "v2":{const messageListPromptArgs={downloadRetries,downloadConcurrency,supportedUrls:model?.supportedUrls};let inputMessages=await messageList.get.all.aiV5.llmPrompt(messageListPromptArgs);let stepModel=model;let stepToolChoice=toolChoice;let stepTools=tools;if(options?.prepareStep){try{const prepareStepResult=await options.prepareStep({stepNumber:inputData.output?.steps?.length||0,steps:inputData.output?.steps||[],model,messages:messageList.get.all.aiV5.model()});if(prepareStepResult){if(prepareStepResult.model){stepModel=prepareStepResult.model;}if(prepareStepResult.toolChoice){stepToolChoice=prepareStepResult.toolChoice;}if(prepareStepResult.activeTools&&stepTools){const activeToolsSet=new Set(prepareStepResult.activeTools);stepTools=Object.fromEntries(Object.entries(stepTools).filter(([toolName])=>activeToolsSet.has(toolName)));}if(prepareStepResult.messages){const newMessages=prepareStepResult.messages;const newMessageList=new MessageList();for(const message of newMessages){if(message.role==="system"){newMessageList.addSystem(message);}else if(message.role==="user"){newMessageList.add(message,"input");}else if(message.role==="assistant"||message.role==="tool"){newMessageList.add(message,"response");}}inputMessages=await newMessageList.get.all.aiV5.llmPrompt(messageListPromptArgs);}}}catch(error){console.error("Error in prepareStep callback:",error);}}modelResult=execute({runId,model:stepModel,providerOptions,inputMessages,tools:stepTools,toolChoice:stepToolChoice,options,modelSettings,telemetry_settings,includeRawChunks,output,headers,onResult:({warnings:warningsFromStream,request:requestFromStream,rawResponse:rawResponseFromStream})=>{warnings=warningsFromStream;request=requestFromStream||{};rawResponse=rawResponseFromStream;controller.enqueue({runId,from:"AGENT"/* AGENT */,type:"step-start",payload:{request:request||{},warnings:[],messageId}});},modelStreamSpan,shouldThrowError:!isLastModel});break;}default:{throw new Error(`Unsupported model version: ${model.specificationVersion}`);}}const outputStream2=new MastraModelOutput({model:{modelId:model.modelId,provider:model.provider,version:model.specificationVersion},stream:modelResult,messageList,messageId,options:{runId,rootSpan:modelStreamSpan,toolCallStreaming,telemetry_settings,includeRawChunks,output,outputProcessors,outputProcessorRunnerMode:"stream",tracingContext}});try{await processOutputStream({outputStream:outputStream2,includeRawChunks,tools,messageId,messageList,runState:runState2,options,controller,responseFromModel:{warnings,request,rawResponse}});}catch(error){console.log("Error in LLM Execution Step",error);if(isAbortError(error)&&options?.abortSignal?.aborted){await options?.onAbort?.({steps:inputData?.output?.steps??[]});controller.enqueue({type:"abort",runId,from:"AGENT"/* AGENT */,payload:{}});return {callBail:true,outputStream:outputStream2,runState:runState2};}if(isLastModel){controller.enqueue({type:"error",runId,from:"AGENT"/* AGENT */,payload:{error}});runState2.setState({hasErrored:true,stepResult:{isContinued:false,reason:"error"}});}else {throw error;}}return {outputStream:outputStream2,callBail:false,runState:runState2};});if(callBail){const usage2=outputStream._getImmediateUsage();const responseMetadata2=runState.state.responseMetadata;const text2=outputStream._getImmediateText();return bail({messageId,stepResult:{reason:"abort",warnings,isContinued:false},metadata:{providerMetadata:providerOptions,...responseMetadata2,headers:rawResponse?.headers,request},output:{text:text2,toolCalls:[],usage:usage2??inputData.output?.usage,steps:[]},messages:{all:messageList.get.all.aiV5.model(),user:messageList.get.input.aiV5.model(),nonUser:messageList.get.response.aiV5.model()}});}if(outputStream.tripwire){controller.enqueue({type:"tripwire",runId,from:"AGENT"/* AGENT */,payload:{tripwireReason:outputStream.tripwireReason||"Content blocked by output processor"}});runState.setState({stepResult:{isContinued:false,reason:"abort"}});}const toolCalls=outputStream._getImmediateToolCalls()?.map(chunk=>{return chunk.payload;});if(toolCalls.length>0){const assistantContent=[...toolCalls.map(toolCall=>{return {type:"tool-call",toolCallId:toolCall.toolCallId,toolName:toolCall.toolName,args:toolCall.args};})];messageList.add({id:messageId,role:"assistant",content:assistantContent},"response");}const finishReason=runState?.state?.stepResult?.reason??outputStream._getImmediateFinishReason();const hasErrored=runState.state.hasErrored;const usage=outputStream._getImmediateUsage();const responseMetadata=runState.state.responseMetadata;const text=outputStream._getImmediateText();const tripwireTriggered=outputStream.tripwire;const steps=inputData.output?.steps||[];const existingResponseCount=inputData.messages?.nonUser?.length||0;const allResponseContent=messageList.get.response.aiV5.modelContent(steps.length);const currentIterationContent=allResponseContent.slice(existingResponseCount);steps.push(new DefaultStepResult({warnings:outputStream._getImmediateWarnings(),providerMetadata:providerOptions,finishReason:runState.state.stepResult?.reason,content:currentIterationContent,response:{...responseMetadata,...rawResponse,messages:messageList.get.response.aiV5.model()},request,usage:outputStream._getImmediateUsage()}));const messages={all:messageList.get.all.aiV5.model(),user:messageList.get.input.aiV5.model(),nonUser:messageList.get.response.aiV5.model()};return {messageId,stepResult:{reason:tripwireTriggered?"abort":hasErrored?"error":finishReason,warnings,isContinued:tripwireTriggered?false:!["stop","error"].includes(finishReason)},metadata:{providerMetadata:runState.state.providerOptions,...responseMetadata,...rawResponse,headers:rawResponse?.headers,request},output:{text,toolCalls,usage:usage??inputData.output?.usage,steps},messages};}});}// src/loop/workflows/agentic-execution/llm-mapping-step.ts
|
|
320
|
+
function createLLMMappingStep({models,telemetry_settings,_internal,modelStreamSpan,...rest},llmExecutionStep){return createStep({id:"llmExecutionMappingStep",inputSchema:z5.array(toolCallOutputSchema),outputSchema:llmIterationOutputSchema,execute:async({inputData,getStepResult:getStepResult2,bail})=>{const initialResult=getStepResult2(llmExecutionStep);if(inputData?.every(toolCall=>toolCall?.result===void 0)){const errorResults=inputData.filter(toolCall=>toolCall?.error);const toolResultMessageId=rest.experimental_generateMessageId?.()||_internal?.generateId?.();if(errorResults?.length){errorResults.forEach(toolCall=>{const chunk={type:"tool-error",runId:rest.runId,from:"AGENT"/* AGENT */,payload:{error:toolCall.error,args:toolCall.args,toolCallId:toolCall.toolCallId,toolName:toolCall.toolName,providerMetadata:toolCall.providerMetadata}};rest.controller.enqueue(chunk);});rest.messageList.add({id:toolResultMessageId,role:"tool",content:errorResults.map(toolCall=>{return {type:"tool-result",args:toolCall.args,toolCallId:toolCall.toolCallId,toolName:toolCall.toolName,result:{tool_execution_error:toolCall.error?.message??toolCall.error}};})},"response");}initialResult.stepResult.isContinued=false;return bail(initialResult);}if(inputData?.length){for(const toolCall of inputData){const chunk={type:"tool-result",runId:rest.runId,from:"AGENT"/* AGENT */,payload:{args:toolCall.args,toolCallId:toolCall.toolCallId,toolName:toolCall.toolName,result:toolCall.result,providerMetadata:toolCall.providerMetadata,providerExecuted:toolCall.providerExecuted}};rest.controller.enqueue(chunk);if(initialResult?.metadata?.modelVersion==="v2"){await rest.options?.onChunk?.({chunk:convertMastraChunkToAISDKv5({chunk})});}const toolResultMessageId=rest.experimental_generateMessageId?.()||_internal?.generateId?.();rest.messageList.add({id:toolResultMessageId,role:"tool",content:inputData.map(toolCall2=>{return {type:"tool-result",args:toolCall2.args,toolCallId:toolCall2.toolCallId,toolName:toolCall2.toolName,result:toolCall2.result};})},"response");}return {...initialResult,messages:{all:rest.messageList.get.all.aiV5.model(),user:rest.messageList.get.input.aiV5.model(),nonUser:rest.messageList.get.response.aiV5.model()}};}}});}// src/loop/workflows/agentic-execution/tool-call-step.ts
|
|
321
|
+
function createToolCallStep({tools,messageList,options,telemetry_settings,writer}){return createStep({id:"toolCallStep",inputSchema:toolCallInputSchema,outputSchema:toolCallOutputSchema,execute:async({inputData})=>{if(inputData.providerExecuted){const tracer2=getTracer({isEnabled:telemetry_settings?.isEnabled,tracer:telemetry_settings?.tracer});const span2=tracer2.startSpan("mastra.stream.toolCall").setAttributes({...assembleOperationName({operationId:"mastra.stream.toolCall",telemetry:telemetry_settings}),"stream.toolCall.toolName":inputData.toolName,"stream.toolCall.toolCallId":inputData.toolCallId,"stream.toolCall.args":JSON.stringify(inputData.args),"stream.toolCall.providerExecuted":true});if(inputData.output){span2.setAttributes({"stream.toolCall.result":JSON.stringify(inputData.output)});}span2.end();return {...inputData,result:inputData.output};}const tool=tools?.[inputData.toolName]||Object.values(tools||{})?.find(tool2=>`id`in tool2&&tool2.id===inputData.toolName);if(!tool){throw new Error(`Tool ${inputData.toolName} not found`);}if(tool&&"onInputAvailable"in tool){try{await tool?.onInputAvailable?.({toolCallId:inputData.toolCallId,input:inputData.args,messages:messageList.get.input.aiV5.model(),abortSignal:options?.abortSignal});}catch(error){console.error("Error calling onInputAvailable",error);}}if(!tool.execute){return inputData;}const tracer=getTracer({isEnabled:telemetry_settings?.isEnabled,tracer:telemetry_settings?.tracer});const span=tracer.startSpan("mastra.stream.toolCall").setAttributes({...assembleOperationName({operationId:"mastra.stream.toolCall",telemetry:telemetry_settings}),"stream.toolCall.toolName":inputData.toolName,"stream.toolCall.toolCallId":inputData.toolCallId,"stream.toolCall.args":JSON.stringify(inputData.args)});try{const result=await tool.execute(inputData.args,{abortSignal:options?.abortSignal,toolCallId:inputData.toolCallId,messages:messageList.get.input.aiV5.model(),writableStream:writer});span.setAttributes({"stream.toolCall.result":JSON.stringify(result)});span.end();return {result,...inputData};}catch(error){span.setStatus({code:2,message:error?.message??error});span.recordException(error);return {error,...inputData};}}});}// src/loop/workflows/agentic-execution/index.ts
|
|
322
|
+
function createAgenticExecutionWorkflow({models,telemetry_settings,_internal,modelStreamSpan,...rest}){const llmExecutionStep=createLLMExecutionStep({models,_internal,modelStreamSpan,telemetry_settings,...rest});const toolCallStep=createToolCallStep({telemetry_settings,...rest});const llmMappingStep=createLLMMappingStep({models,telemetry_settings,_internal,modelStreamSpan,...rest},llmExecutionStep);return createWorkflow({id:"executionWorkflow",inputSchema:llmIterationOutputSchema,outputSchema:llmIterationOutputSchema,options:{tracingPolicy:{// mark all workflow spans related to the
|
|
323
|
+
// VNext execution as internal
|
|
324
|
+
internal:1/* WORKFLOW */}}}).then(llmExecutionStep).map(async({inputData})=>{const typedInputData=inputData;if(modelStreamSpan&&telemetry_settings?.recordOutputs!==false&&typedInputData.output.toolCalls?.length){modelStreamSpan.setAttribute("stream.response.toolCalls",JSON.stringify(typedInputData.output.toolCalls?.map(toolCall=>{return {toolCallId:toolCall.toolCallId,// @ts-ignore TODO: look into the type here
|
|
325
|
+
args:toolCall.args,toolName:toolCall.toolName};})));}return typedInputData.output.toolCalls||[];}).foreach(toolCallStep,{concurrency:10}).then(llmMappingStep).commit();}// src/loop/workflows/agentic-loop/index.ts
|
|
326
|
+
function createAgenticLoopWorkflow(params){const{models,_internal,messageId,runId,modelStreamSpan,telemetry_settings,toolChoice,messageList,modelSettings,controller,writer,...rest}=params;const accumulatedSteps=[];let previousContentLength=0;const agenticExecutionWorkflow=createAgenticExecutionWorkflow({messageId,models,telemetry_settings,_internal,modelSettings,toolChoice,modelStreamSpan,controller,writer,messageList,runId,...rest});return createWorkflow({id:"agentic-loop",inputSchema:llmIterationOutputSchema,outputSchema:llmIterationOutputSchema,options:{tracingPolicy:{// mark all workflow spans related to the
|
|
327
|
+
// VNext execution as internal
|
|
328
|
+
internal:1/* WORKFLOW */}}}).dowhile(agenticExecutionWorkflow,async({inputData})=>{const typedInputData=inputData;let hasFinishedSteps=false;const allContent=typedInputData.messages.nonUser.flatMap(message=>message.content);const currentContent=allContent.slice(previousContentLength);previousContentLength=allContent.length;const currentStep={content:currentContent,usage:typedInputData.output.usage||{inputTokens:0,outputTokens:0,totalTokens:0},// we need to cast this because we add 'abort' for tripwires
|
|
329
|
+
finishReason:typedInputData.stepResult?.reason||"unknown",warnings:typedInputData.stepResult?.warnings||[],request:typedInputData.metadata?.request||{},response:{...typedInputData.metadata,modelId:typedInputData.metadata?.modelId||typedInputData.metadata?.model||"",messages:[]},text:typedInputData.output.text||"",reasoning:typedInputData.output.reasoning||[],reasoningText:typedInputData.output.reasoningText||"",files:typedInputData.output.files||[],toolCalls:typedInputData.output.toolCalls||[],toolResults:typedInputData.output.toolResults||[],sources:typedInputData.output.sources||[],staticToolCalls:typedInputData.output.staticToolCalls||[],dynamicToolCalls:typedInputData.output.dynamicToolCalls||[],staticToolResults:typedInputData.output.staticToolResults||[],dynamicToolResults:typedInputData.output.dynamicToolResults||[],providerMetadata:typedInputData.metadata?.providerMetadata};accumulatedSteps.push(currentStep);if(rest.stopWhen&&typedInputData.stepResult?.isContinued&&accumulatedSteps.length>0){const conditions=await Promise.all((Array.isArray(rest.stopWhen)?rest.stopWhen:[rest.stopWhen]).map(condition=>{return condition({steps:accumulatedSteps});}));const hasStopped=conditions.some(condition=>condition);hasFinishedSteps=hasStopped;}if(typedInputData.stepResult){typedInputData.stepResult.isContinued=hasFinishedSteps?false:typedInputData.stepResult.isContinued;}if(typedInputData.stepResult?.reason!=="abort"){controller.enqueue({type:"step-finish",runId,from:"AGENT"/* AGENT */,payload:typedInputData});}modelStreamSpan.setAttributes({"stream.response.id":typedInputData.metadata?.id,"stream.response.model":typedInputData.metadata?.modelId,...(typedInputData.metadata?.providerMetadata?{"stream.response.providerMetadata":JSON.stringify(typedInputData.metadata.providerMetadata)}:{}),"stream.response.finishReason":typedInputData.stepResult?.reason,"stream.usage.inputTokens":typedInputData.output.usage?.inputTokens,"stream.usage.outputTokens":typedInputData.output.usage?.outputTokens,"stream.usage.totalTokens":typedInputData.output.usage?.totalTokens,...(telemetry_settings?.recordOutputs!==false?{"stream.response.text":typedInputData.output.text,"stream.prompt.messages":JSON.stringify(messageList.get.input.aiV5.model())}:{})});modelStreamSpan.end();const reason=typedInputData.stepResult?.reason;if(reason===void 0){return false;}return typedInputData.stepResult?.isContinued??false;}).commit();}// src/loop/workflows/stream.ts
|
|
330
|
+
function workflowLoopStream({telemetry_settings,models,toolChoice,modelSettings,_internal,modelStreamSpan,llmAISpan,messageId,runId,messageList,startTimestamp,...rest}){return new ReadableStream$1({start:async controller=>{const writer=new WritableStream({write:chunk=>{controller.enqueue(chunk);}});modelStreamSpan.setAttributes({...(telemetry_settings?.recordInputs!==false?{"stream.prompt.toolChoice":toolChoice?JSON.stringify(toolChoice):"auto"}:{})});const agenticLoopWorkflow=createAgenticLoopWorkflow({messageId,models,telemetry_settings,_internal,modelSettings,toolChoice,modelStreamSpan,controller,writer,runId,messageList,startTimestamp,...rest});const initialData={messageId,messages:{all:messageList.get.all.aiV5.model(),user:messageList.get.input.aiV5.model(),nonUser:[]},output:{steps:[],usage:{inputTokens:0,outputTokens:0,totalTokens:0}},metadata:{},stepResult:{reason:"undefined",warnings:[],isContinued:true,totalUsage:{inputTokens:0,outputTokens:0,totalTokens:0}}};const msToFirstChunk=_internal?.now?.()-startTimestamp;modelStreamSpan.addEvent("ai.stream.firstChunk",{"ai.response.msToFirstChunk":msToFirstChunk});modelStreamSpan.setAttributes({"stream.response.timestamp":new Date(startTimestamp).toISOString(),"stream.response.msToFirstChunk":msToFirstChunk});controller.enqueue({type:"start",runId,from:"AGENT"/* AGENT */,payload:{}});const run=await agenticLoopWorkflow.createRunAsync({runId});const executionResult=await run.start({inputData:initialData,tracingContext:{currentSpan:llmAISpan}});if(executionResult.status!=="success"){controller.close();return;}if(executionResult.result.stepResult?.reason==="abort"){controller.close();return;}controller.enqueue({type:"finish",runId,from:"AGENT"/* AGENT */,payload:{...executionResult.result,stepResult:{...executionResult.result.stepResult,// @ts-ignore we add 'abort' for tripwires so the type is not compatible
|
|
331
|
+
reason:executionResult.result.stepResult.reason}}});const msToFinish=(_internal?.now?.()??Date.now())-startTimestamp;modelStreamSpan.addEvent("ai.stream.finish");modelStreamSpan.setAttributes({"stream.response.msToFinish":msToFinish,"stream.response.avgOutputTokensPerSecond":1e3*(executionResult?.result?.output?.usage?.outputTokens??0)/msToFinish});controller.close();}});}// src/loop/loop.ts
|
|
332
|
+
function loop({models,logger,runId,idGenerator,telemetry_settings,messageList,includeRawChunks,modelSettings,tools,_internal,mode="stream",outputProcessors,returnScorerData,llmAISpan,...rest}){let loggerToUse=logger||new ConsoleLogger({level:"debug"});if(models.length===0||!models[0]){const mastraError=new MastraError({id:"LOOP_MODELS_EMPTY",domain:"LLM"/* LLM */,category:"USER"/* USER */});loggerToUse.trackException(mastraError);loggerToUse.error(mastraError.toString());throw mastraError;}const firstModel=models[0];let runIdToUse=runId;if(!runIdToUse){runIdToUse=idGenerator?.()||crypto.randomUUID();}const internalToUse={now:_internal?.now||(()=>Date.now()),generateId:_internal?.generateId||(()=>generateId()),currentDate:_internal?.currentDate||(()=>/* @__PURE__ */new Date())};let startTimestamp=internalToUse.now?.();const{rootSpan}=getRootSpan({operationId:mode==="stream"?`mastra.stream`:`mastra.generate`,model:{modelId:firstModel.model.modelId,provider:firstModel.model.provider},modelSettings,headers:modelSettings?.headers??rest.headers,telemetry_settings});rootSpan.setAttributes({...(telemetry_settings?.recordOutputs!==false?{"stream.prompt.messages":JSON.stringify(messageList.get.input.aiV5.model())}:{})});const{rootSpan:modelStreamSpan}=getRootSpan({operationId:`mastra.${mode}.aisdk.doStream`,model:{modelId:firstModel.model.modelId,provider:firstModel.model.provider},modelSettings,headers:modelSettings?.headers??rest.headers,telemetry_settings});const messageId=rest.experimental_generateMessageId?.()||internalToUse.generateId?.();const workflowLoopProps={models,runId:runIdToUse,logger:loggerToUse,startTimestamp,messageList,includeRawChunks:!!includeRawChunks,_internal:internalToUse,tools,modelStreamSpan,telemetry_settings,modelSettings,outputProcessors,llmAISpan,messageId,...rest};const stream=workflowLoopStream(workflowLoopProps);return new MastraModelOutput({model:{modelId:firstModel.model.modelId,provider:firstModel.model.provider,version:firstModel.model.specificationVersion},stream,messageList,messageId,options:{runId:runIdToUse,telemetry_settings,rootSpan,toolCallStreaming:rest.toolCallStreaming,onFinish:rest.options?.onFinish,onStepFinish:rest.options?.onStepFinish,includeRawChunks:!!includeRawChunks,output:rest.output,outputProcessors,outputProcessorRunnerMode:"result",returnScorerData,tracingContext:{currentSpan:llmAISpan}}});}// src/llm/model/model.loop.ts
|
|
333
|
+
var MastraLLMVNext=class extends MastraBase{#models;#mastra;#options;#firstModel;constructor({mastra,models,options}){super({name:"aisdk"});this.#options=options;if(mastra){this.#mastra=mastra;if(mastra.getLogger()){this.__setLogger(this.#mastra.getLogger());}}if(models.length===0||!models[0]){const mastraError=new MastraError({id:"LLM_LOOP_MODELS_EMPTY",domain:"LLM"/* LLM */,category:"USER"/* USER */});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}else {this.#models=models;this.#firstModel=models[0];}}__registerPrimitives(p){if(p.telemetry){this.__setTelemetry(p.telemetry);}if(p.logger){this.__setLogger(p.logger);}}__registerMastra(p){this.#mastra=p;}getProvider(){return this.#firstModel.model.provider;}getModelId(){return this.#firstModel.model.modelId;}getModel(){return this.#firstModel.model;}_applySchemaCompat(schema){const model=this.#firstModel.model;const schemaCompatLayers=[];if(model){const modelInfo={modelId:model.modelId,supportsStructuredOutputs:true,provider:model.provider};schemaCompatLayers.push(new OpenAIReasoningSchemaCompatLayer(modelInfo),new OpenAISchemaCompatLayer(modelInfo),new GoogleSchemaCompatLayer(modelInfo),new AnthropicSchemaCompatLayer(modelInfo),new DeepSeekSchemaCompatLayer(modelInfo),new MetaSchemaCompatLayer(modelInfo));}return applyCompatLayer({schema,compatLayers:schemaCompatLayers,mode:"aiSdkSchema"});}convertToMessages(messages){if(Array.isArray(messages)){return messages.map(m=>{if(typeof m==="string"){return {role:"user",content:m};}return m;});}return [{role:"user",content:messages}];}stream({stopWhen=stepCountIs(5),maxSteps,tools={},runId,modelSettings,toolChoice="auto",telemetry_settings,threadId,resourceId,output,options,outputProcessors,returnScorerData,providerOptions,tracingContext,messageList,_internal// ...rest
|
|
334
|
+
}){let stopWhenToUse;if(maxSteps&&typeof maxSteps==="number"){stopWhenToUse=stepCountIs(maxSteps);}else {stopWhenToUse=stopWhen;}const messages=messageList.get.all.aiV5.model();const firstModel=this.#firstModel.model;this.logger.debug(`[LLM] - Streaming text`,{runId,threadId,resourceId,messages,tools:Object.keys(tools||{})});const llmAISpan=tracingContext?.currentSpan?.createChildSpan({name:`llm: '${firstModel.modelId}'`,type:"llm_generation"/* LLM_GENERATION */,input:{messages:[...messageList.getSystemMessages(),...messages]},attributes:{model:firstModel.modelId,provider:firstModel.provider,streaming:true,parameters:modelSettings},metadata:{runId,threadId,resourceId},tracingPolicy:this.#options?.tracingPolicy});try{const loopOptions={messageList,models:this.#models,tools,stopWhen:stopWhenToUse,toolChoice,modelSettings,providerOptions,telemetry_settings:{...this.experimental_telemetry,...telemetry_settings},_internal,output,outputProcessors,returnScorerData,llmAISpan,options:{...options,onStepFinish:async props=>{try{await options?.onStepFinish?.({...props,runId});}catch(e){const mastraError=new MastraError({id:"LLM_STREAM_ON_STEP_FINISH_CALLBACK_EXECUTION_FAILED",domain:"LLM"/* LLM */,category:"USER"/* USER */,details:{modelId:props.model.modelId,modelProvider:props.model.provider,runId:runId??"unknown",threadId:threadId??"unknown",resourceId:resourceId??"unknown",finishReason:props?.finishReason,toolCalls:props?.toolCalls?JSON.stringify(props.toolCalls):"",toolResults:props?.toolResults?JSON.stringify(props.toolResults):"",usage:props?.usage?JSON.stringify(props.usage):""}},e);llmAISpan?.error({error:mastraError});this.logger.trackException(mastraError);throw mastraError;}this.logger.debug("[LLM] - Stream Step Change:",{text:props?.text,toolCalls:props?.toolCalls,toolResults:props?.toolResults,finishReason:props?.finishReason,usage:props?.usage,runId});if(props?.response?.headers?.["x-ratelimit-remaining-tokens"]&&parseInt(props?.response?.headers?.["x-ratelimit-remaining-tokens"],10)<2e3){this.logger.warn("Rate limit approaching, waiting 10 seconds",{runId});await delay(10*1e3);}},onFinish:async props=>{try{await options?.onFinish?.({...props,runId});}catch(e){const mastraError=new MastraError({id:"LLM_STREAM_ON_FINISH_CALLBACK_EXECUTION_FAILED",domain:"LLM"/* LLM */,category:"USER"/* USER */,details:{modelId:props.model.modelId,modelProvider:props.model.provider,runId:runId??"unknown",threadId:threadId??"unknown",resourceId:resourceId??"unknown",finishReason:props?.finishReason,toolCalls:props?.toolCalls?JSON.stringify(props.toolCalls):"",toolResults:props?.toolResults?JSON.stringify(props.toolResults):"",usage:props?.usage?JSON.stringify(props.usage):""}},e);llmAISpan?.error({error:mastraError});this.logger.trackException(mastraError);throw mastraError;}llmAISpan?.end({output:{text:props?.text,reasoning:props?.reasoning,reasoningText:props?.reasoningText,files:props?.files,sources:props?.sources,warnings:props?.warnings},attributes:{finishReason:props?.finishReason,usage:{promptTokens:props?.totalUsage?.inputTokens,completionTokens:props?.totalUsage?.outputTokens,totalTokens:props?.totalUsage?.totalTokens}}});this.logger.debug("[LLM] - Stream Finished:",{text:props?.text,toolCalls:props?.toolCalls,toolResults:props?.toolResults,finishReason:props?.finishReason,usage:props?.usage,runId,threadId,resourceId});}}};return loop(loopOptions);}catch(e){const mastraError=new MastraError({id:"LLM_STREAM_TEXT_AI_SDK_EXECUTION_FAILED",domain:"LLM"/* LLM */,category:"THIRD_PARTY"/* THIRD_PARTY */,details:{modelId:firstModel.modelId,modelProvider:firstModel.provider,runId:runId??"unknown",threadId:threadId??"unknown",resourceId:resourceId??"unknown"}},e);llmAISpan?.error({error:mastraError});throw mastraError;}}};// src/loop/network/index.ts
|
|
319
335
|
var MastraAgentNetworkStream=class extends ReadableStream$1{#usageCount={promptTokens:0,completionTokens:0,totalTokens:0};#streamPromise;#run;constructor({createStream,run}){const deferredPromise={promise:null,resolve:null,reject:null};deferredPromise.promise=new Promise((resolve,reject)=>{deferredPromise.resolve=resolve;deferredPromise.reject=reject;});const updateUsageCount=usage=>{this.#usageCount.promptTokens+=parseInt(usage?.promptTokens?.toString()??"0",10);this.#usageCount.completionTokens+=parseInt(usage?.completionTokens?.toString()??"0",10);this.#usageCount.totalTokens+=parseInt(usage?.totalTokens?.toString()??"0",10);};super({start:async controller=>{const writer=new WritableStream({write:chunk=>{if(chunk.type==="step-output"&&chunk.payload?.output?.from==="AGENT"&&chunk.payload?.output?.type==="finish"||chunk.type==="step-output"&&chunk.payload?.output?.from==="WORKFLOW"&&chunk.payload?.output?.type==="finish"){const finishPayload=chunk.payload?.output.payload;if(finishPayload){updateUsageCount(finishPayload.usage);}}controller.enqueue(chunk);}});const stream=await createStream(writer);for await(const chunk of stream){if(chunk.type==="workflow-step-output"){const innerChunk=chunk.payload.output;const innerChunkType=innerChunk.payload.output;controller.enqueue(innerChunkType);}}controller.close();deferredPromise.resolve();}});this.#run=run;this.#streamPromise=deferredPromise;}get status(){return this.#streamPromise.promise.then(()=>this.#run._getExecutionResults()).then(res=>res.status);}get result(){return this.#streamPromise.promise.then(()=>this.#run._getExecutionResults());}get usage(){return this.#streamPromise.promise.then(()=>this.#usageCount);}};// src/loop/types.ts
|
|
320
|
-
var RESOURCE_TYPES=
|
|
321
|
-
async function getRoutingAgent({runtimeContext,agent}){const instructionsToUse=await agent.getInstructions({runtimeContext});const agentsToUse=await agent.listAgents({runtimeContext});const workflowsToUse=await agent.getWorkflows({runtimeContext});const toolsToUse=await agent.getTools({runtimeContext});const model=await agent.getModel({runtimeContext});const memoryToUse=await agent.getMemory({runtimeContext});const agentList=Object.entries(agentsToUse).map(([name,agent2])=>{return ` - **${name}**: ${agent2.getDescription()}`;}).join("\n");const workflowList=Object.entries(workflowsToUse).map(([name,workflow])=>{return ` - **${name}**: ${workflow.description}, input schema: ${JSON.stringify(zodToJsonSchema(workflow.inputSchema))}`;}).join("\n");const toolList=Object.entries(toolsToUse).map(([name,tool])=>{return ` - **${name}**: ${tool.description}, input schema: ${JSON.stringify(zodToJsonSchema(tool.inputSchema||
|
|
336
|
+
var RESOURCE_TYPES=z5.enum(["agent","workflow","none","tool"]);// src/loop/network/index.ts
|
|
337
|
+
async function getRoutingAgent({runtimeContext,agent}){const instructionsToUse=await agent.getInstructions({runtimeContext});const agentsToUse=await agent.listAgents({runtimeContext});const workflowsToUse=await agent.getWorkflows({runtimeContext});const toolsToUse=await agent.getTools({runtimeContext});const model=await agent.getModel({runtimeContext});const memoryToUse=await agent.getMemory({runtimeContext});const agentList=Object.entries(agentsToUse).map(([name,agent2])=>{return ` - **${name}**: ${agent2.getDescription()}`;}).join("\n");const workflowList=Object.entries(workflowsToUse).map(([name,workflow])=>{return ` - **${name}**: ${workflow.description}, input schema: ${JSON.stringify(zodToJsonSchema(workflow.inputSchema))}`;}).join("\n");const toolList=Object.entries(toolsToUse).map(([name,tool])=>{return ` - **${name}**: ${tool.description}, input schema: ${JSON.stringify(zodToJsonSchema(tool.inputSchema||z5.object({})))}`;}).join("\n");const instructions=`
|
|
322
338
|
You are a router in a network of specialized AI agents.
|
|
323
339
|
Your job is to decide which agent should handle each step of a task.
|
|
324
340
|
If asking for completion of a task, make sure to follow system instructions closely.
|
|
@@ -340,7 +356,7 @@ async function getRoutingAgent({runtimeContext,agent}){const instructionsToUse=a
|
|
|
340
356
|
When calling an agent, the prompt should be a text value, like you would call an LLM in a chat interface.
|
|
341
357
|
Keep in mind that the user only sees the final result of the task. When reviewing completion, you should know that the user will not see the intermediate results.
|
|
342
358
|
`;return new Agent({name:"routing-agent",instructions,model,memory:memoryToUse,// @ts-ignore
|
|
343
|
-
_agentNetworkAppend:true});}function getLastMessage(messages){let message="";if(typeof messages==="string"){message=messages;}else {const lastMessage=Array.isArray(messages)?messages[messages.length-1]:messages;if(typeof lastMessage==="string"){message=lastMessage;}else if(lastMessage&&`content`in lastMessage&&lastMessage?.content){const lastMessageContent=lastMessage.content;if(typeof lastMessageContent==="string"){message=lastMessageContent;}else if(Array.isArray(lastMessageContent)){const lastPart=lastMessageContent[lastMessageContent.length-1];if(lastPart?.type==="text"){message=lastPart.text;}}}}return message;}async function prepareMemoryStep({threadId,resourceId,messages,routingAgent,runtimeContext,generateId:generateId2}){const memory=await routingAgent.getMemory({runtimeContext});let thread=await memory?.getThreadById({threadId});if(!thread){thread=await memory?.createThread({threadId,title:"",resourceId});}if(typeof messages==="string"){await memory?.saveMessages({messages:[{id:generateId2(),type:"text",role:"user",content:{parts:[{type:"text",text:messages}],format:2},createdAt:/* @__PURE__ */new Date(),threadId:thread?.id,resourceId:thread?.resourceId}],format:"v2"});}else {const messageList=new MessageList({threadId:thread?.id,resourceId:thread?.resourceId});messageList.add(messages,"user");const messagesToSave=messageList.get.all.v2();await memory?.saveMessages({messages:messagesToSave,format:"v2"});}return {thread};}async function createNetworkLoop({networkName,runtimeContext,runId,agent,generateId:generateId2,routingAgentOptions}){const routingStep=createStep({id:"routing-agent-step",inputSchema:
|
|
359
|
+
_agentNetworkAppend:true});}function getLastMessage(messages){let message="";if(typeof messages==="string"){message=messages;}else {const lastMessage=Array.isArray(messages)?messages[messages.length-1]:messages;if(typeof lastMessage==="string"){message=lastMessage;}else if(lastMessage&&`content`in lastMessage&&lastMessage?.content){const lastMessageContent=lastMessage.content;if(typeof lastMessageContent==="string"){message=lastMessageContent;}else if(Array.isArray(lastMessageContent)){const lastPart=lastMessageContent[lastMessageContent.length-1];if(lastPart?.type==="text"){message=lastPart.text;}}}}return message;}async function prepareMemoryStep({threadId,resourceId,messages,routingAgent,runtimeContext,generateId:generateId2}){const memory=await routingAgent.getMemory({runtimeContext});let thread=await memory?.getThreadById({threadId});if(!thread){thread=await memory?.createThread({threadId,title:"",resourceId});}if(typeof messages==="string"){await memory?.saveMessages({messages:[{id:generateId2(),type:"text",role:"user",content:{parts:[{type:"text",text:messages}],format:2},createdAt:/* @__PURE__ */new Date(),threadId:thread?.id,resourceId:thread?.resourceId}],format:"v2"});}else {const messageList=new MessageList({threadId:thread?.id,resourceId:thread?.resourceId});messageList.add(messages,"user");const messagesToSave=messageList.get.all.v2();await memory?.saveMessages({messages:messagesToSave,format:"v2"});}return {thread};}async function createNetworkLoop({networkName,runtimeContext,runId,agent,generateId:generateId2,routingAgentOptions}){const routingStep=createStep({id:"routing-agent-step",inputSchema:z5.object({task:z5.string(),resourceId:z5.string(),resourceType:RESOURCE_TYPES,result:z5.string().optional(),iteration:z5.number(),threadId:z5.string().optional(),threadResourceId:z5.string().optional(),isOneOff:z5.boolean(),verboseIntrospection:z5.boolean()}),outputSchema:z5.object({task:z5.string(),resourceId:z5.string(),resourceType:RESOURCE_TYPES,prompt:z5.string(),result:z5.string(),isComplete:z5.boolean().optional(),selectionReason:z5.string(),iteration:z5.number()}),execute:async({inputData,getInitData,writer})=>{const initData=await getInitData();const completionSchema=z5.object({isComplete:z5.boolean(),finalResult:z5.string(),completionReason:z5.string()});const routingAgent=await getRoutingAgent({runtimeContext,agent});let completionResult;let iterationCount=inputData.iteration?inputData.iteration+1:0;await writer.write({type:"routing-agent-start",payload:{inputData:{...inputData,iteration:iterationCount}}});if(inputData.resourceType!=="none"&&inputData?.result){console.log("Input Data for decision making",inputData);const completionPrompt=`
|
|
344
360
|
The ${inputData.resourceType} ${inputData.resourceId} has contributed to the task.
|
|
345
361
|
This is the result from the agent: ${inputData.result}
|
|
346
362
|
|
|
@@ -377,10 +393,10 @@ ${completionResult?.object?.finalResult}`:""}
|
|
|
377
393
|
}
|
|
378
394
|
|
|
379
395
|
The 'selectionReason' property should explain why you picked the primitive${inputData.verboseIntrospection?", as well as why the other primitives were not picked.":"."}
|
|
380
|
-
`}];const options={output:
|
|
396
|
+
`}];const options={output:z5.object({resourceId:z5.string(),resourceType:RESOURCE_TYPES,prompt:z5.string(),selectionReason:z5.string()}),runtimeContext,maxSteps:1,memory:{thread:initData?.threadId??runId,resource:initData?.threadResourceId??networkName,readOnly:true},...routingAgentOptions};const result=await routingAgent.generateVNext(prompt,options);const object=result.object;const endPayload={task:inputData.task,result:"",resourceId:object.resourceId,resourceType:object.resourceType,prompt:object.prompt,isComplete:object.resourceId==="none"&&object.resourceType==="none",selectionReason:object.selectionReason,iteration:iterationCount};await writer.write({type:"routing-agent-end",payload:endPayload});return endPayload;}});const agentStep=createStep({id:"agent-execution-step",inputSchema:z5.object({task:z5.string(),resourceId:z5.string(),resourceType:RESOURCE_TYPES,prompt:z5.string(),result:z5.string(),isComplete:z5.boolean().optional(),selectionReason:z5.string(),iteration:z5.number()}),outputSchema:z5.object({task:z5.string(),resourceId:z5.string(),resourceType:RESOURCE_TYPES,result:z5.string(),isComplete:z5.boolean().optional(),iteration:z5.number()}),execute:async({inputData,writer,getInitData})=>{const agentsMap=await agent.listAgents({runtimeContext});const agentId=inputData.resourceId;const agentForStep=agentsMap[inputData.resourceId];if(!agentForStep){throw new Error(`Agent ${agentId} not found`);}const runId2=generateId2();await writer.write({type:"agent-execution-start",payload:{agentId:inputData.resourceId,args:inputData,runId:runId2}});const result=await agentForStep.streamVNext(inputData.prompt,{// resourceId: inputData.resourceId,
|
|
381
397
|
// threadId: inputData.threadId,
|
|
382
|
-
runtimeContext,runId:runId2});for await(const chunk of result.fullStream){await writer.write({type:`agent-execution-event-${chunk.type}`,payload:chunk});}const memory=await agent.getMemory({runtimeContext});const initData=await getInitData();const messages=result.messageList.get.all.v1();await memory?.saveMessages({messages:[{id:generateId2(),type:"text",role:"assistant",content:{parts:[{type:"text",text:JSON.stringify({isNetwork:true,selectionReason:inputData.selectionReason,resourceType:inputData.resourceType,resourceId:inputData.resourceId,input:inputData.prompt,finalResult:{text:await result.text,toolCalls:await result.toolCalls,messages}})}],format:2},createdAt:/* @__PURE__ */new Date(),threadId:initData.threadId||runId2,resourceId:initData.threadResourceId||networkName}],format:"v2"});const endPayload={task:inputData.task,agentId:inputData.resourceId,result:await result.text,isComplete:false,iteration:inputData.iteration};await writer.write({type:"agent-execution-end",payload:endPayload});return {task:inputData.task,resourceId:inputData.resourceId,resourceType:inputData.resourceType,result:await result.text,isComplete:false,iteration:inputData.iteration};}});const workflowStep=createStep({id:"workflow-execution-step",inputSchema:
|
|
383
|
-
tracingContext:{currentSpan:void 0},writer},{toolCallId,messages:[]});const memory=await agent.getMemory({runtimeContext});const initData=await getInitData();await memory?.saveMessages({messages:[{id:generateId2(),type:"text",role:"assistant",content:{parts:[{type:"text",text:JSON.stringify({isNetwork:true,selectionReason:inputData.selectionReason,resourceType:inputData.resourceType,resourceId:inputData.resourceId,finalResult:{result:finalResult,toolCallId},input:inputDataToUse})}],format:2},createdAt:/* @__PURE__ */new Date(),threadId:initData.threadId||runId,resourceId:initData.threadResourceId||networkName}],format:"v2"});const endPayload={task:inputData.task,resourceId:inputData.resourceId,resourceType:inputData.resourceType,result:finalResult,isComplete:false,iteration:inputData.iteration,toolCallId,toolName:inputData.resourceId};await writer?.write({type:"tool-execution-end",payload:endPayload});return endPayload;}});const finishStep=createStep({id:"finish-step",inputSchema:
|
|
398
|
+
runtimeContext,runId:runId2});for await(const chunk of result.fullStream){await writer.write({type:`agent-execution-event-${chunk.type}`,payload:chunk});}const memory=await agent.getMemory({runtimeContext});const initData=await getInitData();const messages=result.messageList.get.all.v1();await memory?.saveMessages({messages:[{id:generateId2(),type:"text",role:"assistant",content:{parts:[{type:"text",text:JSON.stringify({isNetwork:true,selectionReason:inputData.selectionReason,resourceType:inputData.resourceType,resourceId:inputData.resourceId,input:inputData.prompt,finalResult:{text:await result.text,toolCalls:await result.toolCalls,messages}})}],format:2},createdAt:/* @__PURE__ */new Date(),threadId:initData.threadId||runId2,resourceId:initData.threadResourceId||networkName}],format:"v2"});const endPayload={task:inputData.task,agentId:inputData.resourceId,result:await result.text,isComplete:false,iteration:inputData.iteration};await writer.write({type:"agent-execution-end",payload:endPayload});return {task:inputData.task,resourceId:inputData.resourceId,resourceType:inputData.resourceType,result:await result.text,isComplete:false,iteration:inputData.iteration};}});const workflowStep=createStep({id:"workflow-execution-step",inputSchema:z5.object({task:z5.string(),resourceId:z5.string(),resourceType:RESOURCE_TYPES,prompt:z5.string(),result:z5.string(),isComplete:z5.boolean().optional(),selectionReason:z5.string(),iteration:z5.number()}),outputSchema:z5.object({task:z5.string(),resourceId:z5.string(),resourceType:RESOURCE_TYPES,result:z5.string(),isComplete:z5.boolean().optional(),iteration:z5.number()}),execute:async({inputData,writer,getInitData})=>{const workflowsMap=await agent.getWorkflows({runtimeContext});const wf=workflowsMap[inputData.resourceId];if(!wf){throw new Error(`Workflow ${inputData.resourceId} not found`);}let input;try{input=JSON.parse(inputData.prompt);}catch(e){console.error(e);throw new Error(`Invalid task input: ${inputData.task}`);}const run=await wf.createRunAsync();const toolData={name:wf.name,args:inputData,runId:run.runId};await writer?.write({type:"workflow-execution-start",payload:toolData});const stream=run.streamVNext({inputData:input,runtimeContext});let chunks=[];for await(const chunk of stream){chunks.push(chunk);await writer?.write({type:`workflow-execution-event-${chunk.type}`,payload:chunk});}let runSuccess=true;const workflowState=await stream.result;if(!workflowState?.status||workflowState?.status==="failed"){runSuccess=false;}const finalResult=JSON.stringify({isNetwork:true,resourceType:inputData.resourceType,resourceId:inputData.resourceId,selectionReason:inputData.selectionReason,input,finalResult:{runId:run.runId,runResult:workflowState,chunks,runSuccess}});const memory=await agent.getMemory({runtimeContext});const initData=await getInitData();await memory?.saveMessages({messages:[{id:generateId2(),type:"text",role:"assistant",content:{parts:[{type:"text",text:finalResult}],format:2},createdAt:/* @__PURE__ */new Date(),threadId:initData.threadId||runId,resourceId:initData.threadResourceId||networkName}],format:"v2"});const endPayload={task:inputData.task,resourceId:inputData.resourceId,resourceType:inputData.resourceType,result:finalResult,isComplete:false,iteration:inputData.iteration};await writer?.write({type:"workflow-execution-end",payload:endPayload});return endPayload;}});const toolStep=createStep({id:"tool-execution-step",inputSchema:z5.object({task:z5.string(),resourceId:z5.string(),resourceType:RESOURCE_TYPES,prompt:z5.string(),result:z5.string(),isComplete:z5.boolean().optional(),selectionReason:z5.string(),iteration:z5.number()}),outputSchema:z5.object({task:z5.string(),resourceId:z5.string(),resourceType:RESOURCE_TYPES,result:z5.string(),isComplete:z5.boolean().optional(),iteration:z5.number()}),execute:async({inputData,getInitData,writer})=>{const toolsMap=await agent.getTools({runtimeContext});const tool=toolsMap[inputData.resourceId];if(!tool){throw new Error(`Tool ${inputData.resourceId} not found`);}if(!tool.execute){throw new Error(`Tool ${inputData.resourceId} does not have an execute function`);}let inputDataToUse;try{inputDataToUse=JSON.parse(inputData.prompt);}catch(e){console.error(e);throw new Error(`Invalid task input: ${inputData.task}`);}const toolCallId=generateId2();await writer?.write({type:"tool-execution-start",payload:{args:{...inputData,args:inputDataToUse,toolName:inputData.resourceId,toolCallId},runId}});const finalResult=await tool.execute({runtimeContext,mastra:agent.getMastraInstance(),resourceId:inputData.resourceId,threadId:runId,runId,context:inputDataToUse,// TODO: Pass proper tracing context when network supports tracing
|
|
399
|
+
tracingContext:{currentSpan:void 0},writer},{toolCallId,messages:[]});const memory=await agent.getMemory({runtimeContext});const initData=await getInitData();await memory?.saveMessages({messages:[{id:generateId2(),type:"text",role:"assistant",content:{parts:[{type:"text",text:JSON.stringify({isNetwork:true,selectionReason:inputData.selectionReason,resourceType:inputData.resourceType,resourceId:inputData.resourceId,finalResult:{result:finalResult,toolCallId},input:inputDataToUse})}],format:2},createdAt:/* @__PURE__ */new Date(),threadId:initData.threadId||runId,resourceId:initData.threadResourceId||networkName}],format:"v2"});const endPayload={task:inputData.task,resourceId:inputData.resourceId,resourceType:inputData.resourceType,result:finalResult,isComplete:false,iteration:inputData.iteration,toolCallId,toolName:inputData.resourceId};await writer?.write({type:"tool-execution-end",payload:endPayload});return endPayload;}});const finishStep=createStep({id:"finish-step",inputSchema:z5.object({task:z5.string(),resourceId:z5.string(),resourceType:RESOURCE_TYPES,prompt:z5.string(),result:z5.string(),isComplete:z5.boolean().optional(),selectionReason:z5.string(),iteration:z5.number()}),outputSchema:z5.object({task:z5.string(),result:z5.string(),isComplete:z5.boolean(),iteration:z5.number()}),execute:async({inputData,writer})=>{const endPayload={task:inputData.task,result:inputData.result,isComplete:!!inputData.isComplete,iteration:inputData.iteration};await writer?.write({type:"network-execution-event-step-finish",payload:endPayload});return endPayload;}});const networkWorkflow=createWorkflow({id:"Agent-Network-Outer-Workflow",inputSchema:z5.object({task:z5.string(),resourceId:z5.string(),resourceType:RESOURCE_TYPES,result:z5.string().optional(),iteration:z5.number(),threadId:z5.string().optional(),threadResourceId:z5.string().optional(),isOneOff:z5.boolean(),verboseIntrospection:z5.boolean()}),outputSchema:z5.object({task:z5.string(),resourceId:z5.string(),resourceType:RESOURCE_TYPES,prompt:z5.string(),result:z5.string(),isComplete:z5.boolean().optional(),completionReason:z5.string().optional(),iteration:z5.number(),threadId:z5.string().optional(),threadResourceId:z5.string().optional(),isOneOff:z5.boolean()})});networkWorkflow.then(routingStep).branch([[async({inputData})=>!inputData.isComplete&&inputData.resourceType==="agent",agentStep],[async({inputData})=>!inputData.isComplete&&inputData.resourceType==="workflow",workflowStep],[async({inputData})=>!inputData.isComplete&&inputData.resourceType==="tool",toolStep],[async({inputData})=>inputData.isComplete,finishStep]]).map({task:{step:[routingStep,agentStep,workflowStep,toolStep],path:"task"},isComplete:{step:[agentStep,workflowStep,toolStep,finishStep],path:"isComplete"},completionReason:{step:[routingStep,agentStep,workflowStep,toolStep,finishStep],path:"completionReason"},result:{step:[agentStep,workflowStep,toolStep,finishStep],path:"result"},resourceId:{step:[routingStep,agentStep,workflowStep,toolStep],path:"resourceId"},resourceType:{step:[routingStep,agentStep,workflowStep,toolStep],path:"resourceType"},iteration:{step:[routingStep,agentStep,workflowStep,toolStep],path:"iteration"},isOneOff:{initData:networkWorkflow,path:"isOneOff"},threadId:{initData:networkWorkflow,path:"threadId"},threadResourceId:{initData:networkWorkflow,path:"threadResourceId"}}).commit();return {networkWorkflow};}async function networkLoop({networkName,runtimeContext,runId,routingAgent,routingAgentOptions,generateId:generateId2,maxIterations,threadId,resourceId,messages}){const{networkWorkflow}=await createNetworkLoop({networkName,runtimeContext,runId,agent:routingAgent,routingAgentOptions,generateId:generateId2});const finalStep=createStep({id:"final-step",inputSchema:networkWorkflow.outputSchema,outputSchema:networkWorkflow.outputSchema,execute:async({inputData,writer})=>{if(inputData.iteration>=maxIterations){await writer?.write({type:"network-execution-event-finish",payload:{...inputData,completionReason:`Max iterations reached: ${maxIterations}`}});return {...inputData,completionReason:`Max iterations reached: ${maxIterations}`};}return inputData;}});const mainWorkflow=createWorkflow({id:"agent-loop-main-workflow",inputSchema:z5.object({iteration:z5.number(),task:z5.string(),resourceId:z5.string(),resourceType:RESOURCE_TYPES,result:z5.string().optional(),threadId:z5.string().optional(),threadResourceId:z5.string().optional(),isOneOff:z5.boolean(),verboseIntrospection:z5.boolean()}),outputSchema:z5.object({task:z5.string(),resourceId:z5.string(),resourceType:RESOURCE_TYPES,prompt:z5.string(),result:z5.string(),isComplete:z5.boolean().optional(),completionReason:z5.string().optional(),iteration:z5.number()})}).dountil(networkWorkflow,async({inputData})=>{return inputData.isComplete||inputData.iteration>=maxIterations;}).then(finalStep).commit();const run=await mainWorkflow.createRunAsync({runId});const{thread}=await prepareMemoryStep({runtimeContext,threadId:threadId||run.runId,resourceId:resourceId||networkName,messages,routingAgent,generateId:generateId2});const task=getLastMessage(messages);return new MastraAgentNetworkStream({run,createStream:()=>{return run.streamVNext({inputData:{task,resourceId:"",resourceType:"none",iteration:0,threadResourceId:thread?.resourceId,threadId:thread?.id,isOneOff:false,verboseIntrospection:true}});}});}// src/processors/processors/structured-output.ts
|
|
384
400
|
var StructuredOutputProcessor=class{name="structured-output";schema;structuringAgent;errorStrategy;fallbackValue;constructor(options,fallbackModel){this.schema=options.schema;this.errorStrategy=options.errorStrategy??"strict";this.fallbackValue=options.fallbackValue;const modelToUse=options.model||fallbackModel;if(!modelToUse){throw new Error("StructuredOutputProcessor requires a model to be provided either in options or as fallback");}this.structuringAgent=new Agent({name:"structured-output-structurer",instructions:options.instructions||this.generateInstructions(),model:modelToUse});}async processOutputResult(args){const{messages,abort}=args;const processedMessages=await Promise.all(messages.map(async message=>{if(message.role!=="assistant"){return message;}const textContent=this.extractTextContent(message);if(!textContent.trim()){return message;}try{const modelDef=await this.structuringAgent.getModel();let structuredResult;const prompt=`Extract and structure the key information from the following text according to the specified schema. Keep the original meaning and details:
|
|
385
401
|
|
|
386
402
|
${textContent}`;const schema=this.schema;if(modelDef.specificationVersion==="v2"){structuredResult=await this.structuringAgent.generateVNext(prompt,{output:schema});}else {structuredResult=await this.structuringAgent.generate(prompt,{output:schema});}if(!structuredResult.object){this.handleError("Structuring failed","Internal agent did not generate structured output",abort);if(this.errorStrategy==="fallback"&&this.fallbackValue!==void 0){return {...message,content:{...message.content,metadata:{...(message.content.metadata||{}),structuredOutput:this.fallbackValue}}};}return message;}return {...message,content:{...message.content,parts:[{type:"text",text:textContent// Keep original text unchanged
|
|
@@ -489,26 +505,26 @@ var SaveQueueManager=class _SaveQueueManager{logger;debounceMs;memory;static MAX
|
|
|
489
505
|
* @param threadId - The ID of the thread whose messages are being saved.
|
|
490
506
|
* @param memoryConfig - Optional memory configuration for saving.
|
|
491
507
|
*/async flushMessages(messageList,threadId,memoryConfig){if(!threadId)return;this.clearDebounce(threadId);return this.enqueueSave(threadId,messageList,memoryConfig);}};// src/agent/agent.ts
|
|
492
|
-
function resolveMaybePromise(value,cb){if(value instanceof Promise){return value.then(cb);}return cb(value);}function resolveThreadIdFromArgs(args){if(args?.memory?.thread){if(typeof args.memory.thread==="string")return {id:args.memory.thread};if(typeof args.memory.thread==="object"&&args.memory.thread.id)return args.memory.thread;}if(args?.threadId)return {id:args.threadId};return void 0;}var _Agent_decorators,_init,_a;_Agent_decorators=[InstrumentClass({prefix:"agent",excludeMethods:["hasOwnMemory","getMemory","__primitive","__registerMastra","__registerPrimitives","__runInputProcessors","__runOutputProcessors","_wrapToolsWithAITracing","getProcessorRunner","__setTools","__setLogger","__setTelemetry","log","listAgents","getModel","getInstructions","getTools","getLLM","getWorkflows","getDefaultGenerateOptions","getDefaultStreamOptions","getDescription","getScorers","getVoice"]})];var Agent=class extends(_a=MastraBase){id;name;#instructions;#description;model;#mastra;#memory;#workflows;#defaultGenerateOptions;#defaultStreamOptions;#defaultVNextStreamOptions;#tools;evals;#scorers;#agents;#voice;#inputProcessors;#outputProcessors;// This flag is for agent network messages. We should change the agent network formatting and remove this flag after.
|
|
493
|
-
_agentNetworkAppend=false;constructor(config){super({component:RegisteredLogger.AGENT});this.name=config.name;this.id=config.id??config.name;this.#instructions=config.instructions;this.#description=config.description;if(!config.model){const mastraError=new MastraError({id:"AGENT_CONSTRUCTOR_MODEL_REQUIRED",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:config.name},text:`LanguageModel is required to create an Agent. Please provide the 'model'.`});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}this.model=config.model;if(config.workflows){this.#workflows=config.workflows;}this.#defaultGenerateOptions=config.defaultGenerateOptions||{};this.#defaultStreamOptions=config.defaultStreamOptions||{};this.#defaultVNextStreamOptions=config.defaultVNextStreamOptions||{};this.#tools=config.tools||{};this.evals={};if(config.mastra){this.__registerMastra(config.mastra);this.__registerPrimitives({telemetry:config.mastra.getTelemetry(),logger:config.mastra.getLogger()});}this.#scorers=config.scorers||{};this.#agents=config.agents||{};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 DefaultVoice();}if(config.inputProcessors){this.#inputProcessors=config.inputProcessors;}if(config.outputProcessors){this.#outputProcessors=config.outputProcessors;}this._agentNetworkAppend=config._agentNetworkAppend||false;}getMastraInstance(){return this.#mastra;}listAgents({runtimeContext=new RuntimeContext()}={}){const agentsToUse=this.#agents?typeof this.#agents==="function"?this.#agents({runtimeContext}):this.#agents:{};return resolveMaybePromise(agentsToUse,agents=>{if(!agents){const mastraError=new MastraError({id:"AGENT_GET_AGENTS_FUNCTION_EMPTY_RETURN",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name},text:`[Agent:${this.name}] - Function-based agents returned empty value`});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}return agents;});}async getProcessorRunner({runtimeContext,inputProcessorOverrides,outputProcessorOverrides}){const inputProcessors=inputProcessorOverrides??(this.#inputProcessors?typeof this.#inputProcessors==="function"?await this.#inputProcessors({runtimeContext}):this.#inputProcessors:[]);const outputProcessors=outputProcessorOverrides??(this.#outputProcessors?typeof this.#outputProcessors==="function"?await this.#outputProcessors({runtimeContext}):this.#outputProcessors:[]);this.logger.debug("outputProcessors",outputProcessors);return new ProcessorRunner({inputProcessors,outputProcessors,logger:this.logger,agentName:this.name});}async getResolvedOutputProcessors(runtimeContext){if(!this.#outputProcessors){return [];}if(typeof this.#outputProcessors==="function"){return await this.#outputProcessors({runtimeContext:runtimeContext||new RuntimeContext()});}return this.#outputProcessors;}hasOwnMemory(){return Boolean(this.#memory);}async getMemory({runtimeContext=new RuntimeContext()}={}){if(!this.#memory){return void 0;}let resolvedMemory;if(typeof this.#memory!=="function"){resolvedMemory=this.#memory;}else {const result=this.#memory({runtimeContext,mastra:this.#mastra});resolvedMemory=await Promise.resolve(result);if(!resolvedMemory){const mastraError=new MastraError({id:"AGENT_GET_MEMORY_FUNCTION_EMPTY_RETURN",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name},text:`[Agent:${this.name}] - Function-based memory returned empty value`});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}}if(this.#mastra&&resolvedMemory){resolvedMemory.__registerMastra(this.#mastra);if(!resolvedMemory.hasOwnStorage){const storage=this.#mastra.getStorage();if(storage){resolvedMemory.setStorage(storage);}}}return resolvedMemory;}get voice(){if(typeof this.#instructions==="function"){const mastraError=new MastraError({id:"AGENT_VOICE_INCOMPATIBLE_WITH_FUNCTION_INSTRUCTIONS",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name},text:"Voice is not compatible when instructions are a function. Please use getVoice() instead."});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}return this.#voice;}async getWorkflows({runtimeContext=new RuntimeContext()}={}){let workflowRecord;if(typeof this.#workflows==="function"){workflowRecord=await Promise.resolve(this.#workflows({runtimeContext,mastra:this.#mastra}));}else {workflowRecord=this.#workflows??{};}Object.entries(workflowRecord||{}).forEach(([_workflowName,workflow])=>{if(this.#mastra){workflow.__registerMastra(this.#mastra);}});return workflowRecord;}async getScorers({runtimeContext=new RuntimeContext()}={}){if(typeof this.#scorers!=="function"){return this.#scorers;}const result=this.#scorers({runtimeContext,mastra:this.#mastra});return resolveMaybePromise(result,scorers=>{if(!scorers){const mastraError=new MastraError({id:"AGENT_GET_SCORERS_FUNCTION_EMPTY_RETURN",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name},text:`[Agent:${this.name}] - Function-based scorers returned empty value`});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}return scorers;});}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 DefaultVoice();}}get instructions(){this.logger.warn("The instructions property is deprecated. Please use getInstructions() instead.");if(typeof this.#instructions==="function"){const mastraError=new MastraError({id:"AGENT_INSTRUCTIONS_INCOMPATIBLE_WITH_FUNCTION_INSTRUCTIONS",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name},text:"Instructions are not compatible when instructions are a function. Please use getInstructions() instead."});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}return this.#instructions;}getInstructions({runtimeContext=new RuntimeContext()}={}){if(typeof this.#instructions==="string"){return this.#instructions;}const result=this.#instructions({runtimeContext,mastra:this.#mastra});return resolveMaybePromise(result,instructions=>{if(!instructions){const mastraError=new MastraError({id:"AGENT_GET_INSTRUCTIONS_FUNCTION_EMPTY_RETURN",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name},text:"Instructions are required to use an Agent. The function-based instructions returned an empty value."});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}return instructions;});}getDescription(){return this.#description??"";}getDefaultGenerateOptions({runtimeContext=new RuntimeContext()}={}){if(typeof this.#defaultGenerateOptions!=="function"){return this.#defaultGenerateOptions;}const result=this.#defaultGenerateOptions({runtimeContext,mastra:this.#mastra});return resolveMaybePromise(result,options=>{if(!options){const mastraError=new MastraError({id:"AGENT_GET_DEFAULT_GENERATE_OPTIONS_FUNCTION_EMPTY_RETURN",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name},text:`[Agent:${this.name}] - Function-based default generate options returned empty value`});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}return options;});}getDefaultStreamOptions({runtimeContext=new RuntimeContext()}={}){if(typeof this.#defaultStreamOptions!=="function"){return this.#defaultStreamOptions;}const result=this.#defaultStreamOptions({runtimeContext,mastra:this.#mastra});return resolveMaybePromise(result,options=>{if(!options){const mastraError=new MastraError({id:"AGENT_GET_DEFAULT_STREAM_OPTIONS_FUNCTION_EMPTY_RETURN",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name},text:`[Agent:${this.name}] - Function-based default stream options returned empty value`});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}return options;});}getDefaultVNextStreamOptions({runtimeContext=new RuntimeContext()}={}){if(typeof this.#defaultVNextStreamOptions!=="function"){return this.#defaultVNextStreamOptions;}const result=this.#defaultVNextStreamOptions({runtimeContext,mastra:this.#mastra});return resolveMaybePromise(result,options=>{if(!options){const mastraError=new MastraError({id:"AGENT_GET_DEFAULT_VNEXT_STREAM_OPTIONS_FUNCTION_EMPTY_RETURN",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name},text:`[Agent:${this.name}] - Function-based default vnext stream options returned empty value`});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}return options;});}get tools(){this.logger.warn("The tools property is deprecated. Please use getTools() instead.");if(typeof this.#tools==="function"){const mastraError=new MastraError({id:"AGENT_GET_TOOLS_FUNCTION_INCOMPATIBLE_WITH_TOOL_FUNCTION_TYPE",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name},text:"Tools are not compatible when tools are a function. Please use getTools() instead."});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}return ensureToolProperties(this.#tools);}getTools({runtimeContext=new RuntimeContext()}={}){if(typeof this.#tools!=="function"){return ensureToolProperties(this.#tools);}const result=this.#tools({runtimeContext,mastra:this.#mastra});return resolveMaybePromise(result,tools=>{if(!tools){const mastraError=new MastraError({id:"AGENT_GET_TOOLS_FUNCTION_EMPTY_RETURN",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name},text:`[Agent:${this.name}] - Function-based tools returned empty value`});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}return ensureToolProperties(tools);});}get llm(){this.logger.warn("The llm property is deprecated. Please use getLLM() instead.");if(typeof this.model==="function"){const mastraError=new MastraError({id:"AGENT_LLM_GETTER_INCOMPATIBLE_WITH_FUNCTION_MODEL",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name},text:"LLM is not compatible when model is a function. Please use getLLM() instead."});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}return this.getLLM();}/**
|
|
508
|
+
function resolveMaybePromise(value,cb){if(value instanceof Promise){return value.then(cb);}return cb(value);}function resolveThreadIdFromArgs(args){if(args?.memory?.thread){if(typeof args.memory.thread==="string")return {id:args.memory.thread};if(typeof args.memory.thread==="object"&&args.memory.thread.id)return args.memory.thread;}if(args?.threadId)return {id:args.threadId};return void 0;}var _Agent_decorators,_init,_a;_Agent_decorators=[InstrumentClass({prefix:"agent",excludeMethods:["hasOwnMemory","getMemory","__primitive","__registerMastra","__registerPrimitives","__runInputProcessors","__runOutputProcessors","_wrapToolsWithAITracing","getProcessorRunner","__setTools","__setLogger","__setTelemetry","log","listAgents","getModel","getInstructions","getTools","getLLM","getWorkflows","getDefaultGenerateOptions","getDefaultStreamOptions","getDescription","getScorers","getVoice"]})];var Agent=class extends(_a=MastraBase){id;name;#instructions;#description;model;maxRetries;#mastra;#memory;#workflows;#defaultGenerateOptions;#defaultStreamOptions;#defaultVNextStreamOptions;#tools;evals;#scorers;#agents;#voice;#inputProcessors;#outputProcessors;#options;// This flag is for agent network messages. We should change the agent network formatting and remove this flag after.
|
|
509
|
+
_agentNetworkAppend=false;constructor(config){super({component:RegisteredLogger.AGENT});this.name=config.name;this.id=config.id??config.name;this.#instructions=config.instructions;this.#description=config.description;this.#options=config.options;if(!config.model){const mastraError=new MastraError({id:"AGENT_CONSTRUCTOR_MODEL_REQUIRED",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:config.name},text:`LanguageModel is required to create an Agent. Please provide the 'model'.`});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}if(Array.isArray(config.model)){if(config.model.length===0){const mastraError=new MastraError({id:"AGENT_CONSTRUCTOR_MODEL_ARRAY_EMPTY",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:config.name},text:`Model array is empty. Please provide at least one model.`});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}this.model=config.model.map(mdl=>({id:randomUUID(),model:mdl.model,maxRetries:mdl.maxRetries??config?.maxRetries??0,enabled:mdl.enabled??true}));}else {this.model=config.model;}this.maxRetries=config.maxRetries??0;if(config.workflows){this.#workflows=config.workflows;}this.#defaultGenerateOptions=config.defaultGenerateOptions||{};this.#defaultStreamOptions=config.defaultStreamOptions||{};this.#defaultVNextStreamOptions=config.defaultVNextStreamOptions||{};this.#tools=config.tools||{};this.evals={};if(config.mastra){this.__registerMastra(config.mastra);this.__registerPrimitives({telemetry:config.mastra.getTelemetry(),logger:config.mastra.getLogger()});}this.#scorers=config.scorers||{};this.#agents=config.agents||{};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 DefaultVoice();}if(config.inputProcessors){this.#inputProcessors=config.inputProcessors;}if(config.outputProcessors){this.#outputProcessors=config.outputProcessors;}this._agentNetworkAppend=config._agentNetworkAppend||false;}getMastraInstance(){return this.#mastra;}listAgents({runtimeContext=new RuntimeContext()}={}){const agentsToUse=this.#agents?typeof this.#agents==="function"?this.#agents({runtimeContext}):this.#agents:{};return resolveMaybePromise(agentsToUse,agents=>{if(!agents){const mastraError=new MastraError({id:"AGENT_GET_AGENTS_FUNCTION_EMPTY_RETURN",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name},text:`[Agent:${this.name}] - Function-based agents returned empty value`});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}return agents;});}async getProcessorRunner({runtimeContext,inputProcessorOverrides,outputProcessorOverrides}){const inputProcessors=inputProcessorOverrides??(this.#inputProcessors?typeof this.#inputProcessors==="function"?await this.#inputProcessors({runtimeContext}):this.#inputProcessors:[]);const outputProcessors=outputProcessorOverrides??(this.#outputProcessors?typeof this.#outputProcessors==="function"?await this.#outputProcessors({runtimeContext}):this.#outputProcessors:[]);this.logger.debug("outputProcessors",outputProcessors);return new ProcessorRunner({inputProcessors,outputProcessors,logger:this.logger,agentName:this.name});}async getResolvedOutputProcessors(runtimeContext){if(!this.#outputProcessors){return [];}if(typeof this.#outputProcessors==="function"){return await this.#outputProcessors({runtimeContext:runtimeContext||new RuntimeContext()});}return this.#outputProcessors;}hasOwnMemory(){return Boolean(this.#memory);}async getMemory({runtimeContext=new RuntimeContext()}={}){if(!this.#memory){return void 0;}let resolvedMemory;if(typeof this.#memory!=="function"){resolvedMemory=this.#memory;}else {const result=this.#memory({runtimeContext,mastra:this.#mastra});resolvedMemory=await Promise.resolve(result);if(!resolvedMemory){const mastraError=new MastraError({id:"AGENT_GET_MEMORY_FUNCTION_EMPTY_RETURN",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name},text:`[Agent:${this.name}] - Function-based memory returned empty value`});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}}if(this.#mastra&&resolvedMemory){resolvedMemory.__registerMastra(this.#mastra);if(!resolvedMemory.hasOwnStorage){const storage=this.#mastra.getStorage();if(storage){resolvedMemory.setStorage(storage);}}}return resolvedMemory;}get voice(){if(typeof this.#instructions==="function"){const mastraError=new MastraError({id:"AGENT_VOICE_INCOMPATIBLE_WITH_FUNCTION_INSTRUCTIONS",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name},text:"Voice is not compatible when instructions are a function. Please use getVoice() instead."});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}return this.#voice;}async getWorkflows({runtimeContext=new RuntimeContext()}={}){let workflowRecord;if(typeof this.#workflows==="function"){workflowRecord=await Promise.resolve(this.#workflows({runtimeContext,mastra:this.#mastra}));}else {workflowRecord=this.#workflows??{};}Object.entries(workflowRecord||{}).forEach(([_workflowName,workflow])=>{if(this.#mastra){workflow.__registerMastra(this.#mastra);}});return workflowRecord;}async getScorers({runtimeContext=new RuntimeContext()}={}){if(typeof this.#scorers!=="function"){return this.#scorers;}const result=this.#scorers({runtimeContext,mastra:this.#mastra});return resolveMaybePromise(result,scorers=>{if(!scorers){const mastraError=new MastraError({id:"AGENT_GET_SCORERS_FUNCTION_EMPTY_RETURN",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name},text:`[Agent:${this.name}] - Function-based scorers returned empty value`});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}return scorers;});}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 DefaultVoice();}}get instructions(){this.logger.warn("The instructions property is deprecated. Please use getInstructions() instead.");if(typeof this.#instructions==="function"){const mastraError=new MastraError({id:"AGENT_INSTRUCTIONS_INCOMPATIBLE_WITH_FUNCTION_INSTRUCTIONS",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name},text:"Instructions are not compatible when instructions are a function. Please use getInstructions() instead."});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}return this.#instructions;}getInstructions({runtimeContext=new RuntimeContext()}={}){if(typeof this.#instructions==="string"){return this.#instructions;}const result=this.#instructions({runtimeContext,mastra:this.#mastra});return resolveMaybePromise(result,instructions=>{if(!instructions){const mastraError=new MastraError({id:"AGENT_GET_INSTRUCTIONS_FUNCTION_EMPTY_RETURN",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name},text:"Instructions are required to use an Agent. The function-based instructions returned an empty value."});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}return instructions;});}getDescription(){return this.#description??"";}getDefaultGenerateOptions({runtimeContext=new RuntimeContext()}={}){if(typeof this.#defaultGenerateOptions!=="function"){return this.#defaultGenerateOptions;}const result=this.#defaultGenerateOptions({runtimeContext,mastra:this.#mastra});return resolveMaybePromise(result,options=>{if(!options){const mastraError=new MastraError({id:"AGENT_GET_DEFAULT_GENERATE_OPTIONS_FUNCTION_EMPTY_RETURN",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name},text:`[Agent:${this.name}] - Function-based default generate options returned empty value`});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}return options;});}getDefaultStreamOptions({runtimeContext=new RuntimeContext()}={}){if(typeof this.#defaultStreamOptions!=="function"){return this.#defaultStreamOptions;}const result=this.#defaultStreamOptions({runtimeContext,mastra:this.#mastra});return resolveMaybePromise(result,options=>{if(!options){const mastraError=new MastraError({id:"AGENT_GET_DEFAULT_STREAM_OPTIONS_FUNCTION_EMPTY_RETURN",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name},text:`[Agent:${this.name}] - Function-based default stream options returned empty value`});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}return options;});}getDefaultVNextStreamOptions({runtimeContext=new RuntimeContext()}={}){if(typeof this.#defaultVNextStreamOptions!=="function"){return this.#defaultVNextStreamOptions;}const result=this.#defaultVNextStreamOptions({runtimeContext,mastra:this.#mastra});return resolveMaybePromise(result,options=>{if(!options){const mastraError=new MastraError({id:"AGENT_GET_DEFAULT_VNEXT_STREAM_OPTIONS_FUNCTION_EMPTY_RETURN",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name},text:`[Agent:${this.name}] - Function-based default vnext stream options returned empty value`});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}return options;});}get tools(){this.logger.warn("The tools property is deprecated. Please use getTools() instead.");if(typeof this.#tools==="function"){const mastraError=new MastraError({id:"AGENT_GET_TOOLS_FUNCTION_INCOMPATIBLE_WITH_TOOL_FUNCTION_TYPE",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name},text:"Tools are not compatible when tools are a function. Please use getTools() instead."});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}return ensureToolProperties(this.#tools);}getTools({runtimeContext=new RuntimeContext()}={}){if(typeof this.#tools!=="function"){return ensureToolProperties(this.#tools);}const result=this.#tools({runtimeContext,mastra:this.#mastra});return resolveMaybePromise(result,tools=>{if(!tools){const mastraError=new MastraError({id:"AGENT_GET_TOOLS_FUNCTION_EMPTY_RETURN",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name},text:`[Agent:${this.name}] - Function-based tools returned empty value`});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}return ensureToolProperties(tools);});}get llm(){this.logger.warn("The llm property is deprecated. Please use getLLM() instead.");if(typeof this.model==="function"){const mastraError=new MastraError({id:"AGENT_LLM_GETTER_INCOMPATIBLE_WITH_FUNCTION_MODEL",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name},text:"LLM is not compatible when model is a function. Please use getLLM() instead."});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}return this.getLLM();}/**
|
|
494
510
|
* Gets or creates an LLM instance based on the current model
|
|
495
511
|
* @param options Options for getting the LLM
|
|
496
512
|
* @returns A promise that resolves to the LLM instance
|
|
497
|
-
*/getLLM({runtimeContext=new RuntimeContext(),model}={}){const modelToUse=model?typeof model==="function"?model({runtimeContext,mastra:this.#mastra}):model:this.getModel({runtimeContext});return resolveMaybePromise(modelToUse,resolvedModel=>{let llm;if(resolvedModel.specificationVersion==="v2"){llm=new MastraLLMVNext({
|
|
513
|
+
*/getLLM({runtimeContext=new RuntimeContext(),model}={}){const modelToUse=model?typeof model==="function"?model({runtimeContext,mastra:this.#mastra}):model:this.getModel({runtimeContext});return resolveMaybePromise(modelToUse,resolvedModel=>{let llm;if(resolvedModel.specificationVersion==="v2"){llm=this.prepareModels(runtimeContext,model).then(models=>{const enabledModels=models.filter(model2=>model2.enabled);return new MastraLLMVNext({models:enabledModels,mastra:this.#mastra,options:{tracingPolicy:this.#options?.tracingPolicy}});});}else {llm=new MastraLLMV1({model:resolvedModel,mastra:this.#mastra,options:{tracingPolicy:this.#options?.tracingPolicy}});}return resolveMaybePromise(llm,resolvedLLM=>{if(this.#primitives){resolvedLLM.__registerPrimitives(this.#primitives);}if(this.#mastra){resolvedLLM.__registerMastra(this.#mastra);}return resolvedLLM;});});}/**
|
|
498
514
|
* Gets the model, resolving it if it's a function
|
|
499
515
|
* @param options Options for getting the model
|
|
500
516
|
* @returns A promise that resolves to the model
|
|
501
|
-
*/getModel({runtimeContext=new RuntimeContext()}={}){if(typeof this.model!=="function"){if(!this.model){const mastraError=new MastraError({id:"AGENT_GET_MODEL_MISSING_MODEL_INSTANCE",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name},text:`[Agent:${this.name}] - No model provided`});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}return this.model;}const result=this.model({runtimeContext,mastra:this.#mastra});return resolveMaybePromise(result,model=>{if(!model){const mastraError=new MastraError({id:"AGENT_GET_MODEL_FUNCTION_EMPTY_RETURN",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name},text:`[Agent:${this.name}] - Function-based model returned empty value`});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}return model;});}__updateInstructions(newInstructions){this.#instructions=newInstructions;this.logger.debug(`[Agents:${this.name}] Instructions updated.`,{model:this.model,name:this.name});}__updateModel({model}){this.model=model;this.logger.debug(`[Agents:${this.name}] Model 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;}/**
|
|
517
|
+
*/getModel({runtimeContext=new RuntimeContext()}={}){if(typeof this.model!=="function"){if(!this.model){const mastraError=new MastraError({id:"AGENT_GET_MODEL_MISSING_MODEL_INSTANCE",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name},text:`[Agent:${this.name}] - No model provided`});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}let modelToUse;if(Array.isArray(this.model)){if(this.model.length===0||!this.model[0]){const mastraError=new MastraError({id:"AGENT_GET_MODEL_MISSING_MODEL_INSTANCE",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name},text:`[Agent:${this.name}] - Empty model list provided`});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}modelToUse=this.model[0].model;if(typeof modelToUse!=="function"&&modelToUse.specificationVersion!=="v2"){const mastraError=new MastraError({id:"AGENT_GET_MODEL_INCOMPATIBLE_WITH_MODEL_ARRAY_V1",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name},text:`[Agent:${this.name}] - Only v2 models are allowed when an array of models is provided`});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}}else {modelToUse=this.model;}if(typeof modelToUse==="function"){const result2=modelToUse({runtimeContext,mastra:this.#mastra});return resolveMaybePromise(result2,model=>{if(!model){const mastraError=new MastraError({id:"AGENT_GET_MODEL_FUNCTION_EMPTY_RETURN",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name},text:`[Agent:${this.name}] - Function-based model returned empty value`});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}if(Array.isArray(this.model)&&model.specificationVersion!=="v2"){const mastraError=new MastraError({id:"AGENT_GET_MODEL_INCOMPATIBLE_WITH_MODEL_ARRAY_V1",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name},text:`[Agent:${this.name}] - Only v2 models are allowed when an array of models is provided`});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}return model;});}return modelToUse;}const result=this.model({runtimeContext,mastra:this.#mastra});return resolveMaybePromise(result,model=>{if(!model){const mastraError=new MastraError({id:"AGENT_GET_MODEL_FUNCTION_EMPTY_RETURN",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name},text:`[Agent:${this.name}] - Function-based model returned empty value`});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}return model;});}async getModelList(runtimeContext=new RuntimeContext()){if(!Array.isArray(this.model)){return null;}return this.prepareModels(runtimeContext);}__updateInstructions(newInstructions){this.#instructions=newInstructions;this.logger.debug(`[Agents:${this.name}] Instructions updated.`,{model:this.model,name:this.name});}__updateModel({model}){this.model=model;this.logger.debug(`[Agents:${this.name}] Model updated.`,{model:this.model,name:this.name});}reorderModels(modelIds){if(!Array.isArray(this.model)){this.logger.warn(`[Agents:${this.name}] model is not an array`);return;}this.model=this.model.sort((a,b)=>{const aIndex=modelIds.indexOf(a.id);const bIndex=modelIds.indexOf(b.id);return aIndex-bIndex;});this.logger.debug(`[Agents:${this.name}] Models reordered`);}updateModelInModelList({id,model,enabled,maxRetries}){if(!Array.isArray(this.model)){this.logger.warn(`[Agents:${this.name}] model is not an array`);return;}const modelToUpdate=this.model.find(m=>m.id===id);if(!modelToUpdate){this.logger.warn(`[Agents:${this.name}] model ${id} not found`);return;}this.model=this.model.map(mdl=>{if(mdl.id===id){return {...mdl,model:model??mdl.model,enabled:enabled??mdl.enabled,maxRetries:maxRetries??mdl.maxRetries};}return mdl;});this.logger.debug(`[Agents:${this.name}] model ${id} updated`);}#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;}/**
|
|
502
518
|
* Set the concrete tools for the agent
|
|
503
519
|
* @param tools
|
|
504
520
|
*/__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 RuntimeContext(),tracingContext,model,instructions}){const llm=await this.getLLM({runtimeContext,model});const normMessage=new MessageList().add(message,"user").get.all.ui().at(-1);if(!normMessage){throw new Error(`Could not generate title from input ${JSON.stringify(message)}`);}const partsToGen=[];for(const part of normMessage.parts){if(part.type===`text`){partsToGen.push(part);}else if(part.type===`source`){partsToGen.push({type:"text",text:`User added URL: ${part.source.url.substring(0,100)}`});}else if(part.type===`file`){partsToGen.push({type:"text",text:`User added ${part.mimeType} file: ${part.data.substring(0,100)}`});}}const systemInstructions=await this.resolveTitleInstructions(runtimeContext,instructions);let text="";if(llm.getModel().specificationVersion==="v2"){const messageList=new MessageList().add([{role:"system",content:systemInstructions}],"system").add([{role:"user",content:JSON.stringify(partsToGen)}],"input");const result=llm.stream({runtimeContext,tracingContext,messageList});text=await result.text;}else {const result=await llm.__text({runtimeContext,tracingContext,messages:[{role:"system",content:systemInstructions},{role:"user",content:JSON.stringify(partsToGen)}]});text=result.text;}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,runtimeContext,tracingContext,model,instructions){try{if(userMessage){const normMessage=new MessageList().add(userMessage,"user").get.all.ui().at(-1);if(normMessage){return await this.generateTitleFromUserMessage({message:normMessage,runtimeContext,tracingContext,model,instructions});}}return `New Thread ${(/* @__PURE__ */new Date()).toISOString()}`;}catch(e){this.logger.error("Error generating title:",e);return void 0;}}/* @deprecated use agent.getMemory() and query memory directly */async fetchMemory({threadId,thread:passedThread,memoryConfig,resourceId,runId,userMessages,systemMessage,messageList=new MessageList({threadId,resourceId}),runtimeContext=new RuntimeContext()}){const memory=await this.getMemory({runtimeContext});if(memory){const thread=passedThread??(await memory.getThreadById({threadId}));if(!thread){return {threadId:threadId||"",messages:userMessages||[]};}if(userMessages&&userMessages.length>0){messageList.add(userMessages,"memory");}if(systemMessage?.role==="system"){messageList.addSystem(systemMessage,"memory");}const[memoryMessages,memorySystemMessage]=threadId&&memory?await Promise.all([memory.rememberMessages({threadId,resourceId,config:memoryConfig,vectorMessageSearch:messageList.getLatestUserContent()||""}).then(r=>r.messagesV2),memory.getSystemMessage({threadId,memoryConfig})]):[[],null];this.logger.debug("Fetched messages from memory",{threadId,runId,fetchedCount:memoryMessages.length});if(memorySystemMessage){messageList.addSystem(memorySystemMessage,"memory");}messageList.add(memoryMessages,"memory");const systemMessages=messageList.getSystemMessages()?.map(m=>m.content)?.join(`
|
|
505
521
|
`)??void 0;const newMessages=messageList.get.input.v1();const processedMemoryMessages=await memory.processMessages({// these will be processed
|
|
506
522
|
messages:messageList.get.remembered.v1(),// these are here for inspecting but shouldn't be returned by the processor
|
|
507
523
|
// - ex TokenLimiter needs to measure all tokens even though it's only processing remembered messages
|
|
508
|
-
newMessages,systemMessage:systemMessages,memorySystemMessage:memorySystemMessage||void 0});const returnList=new MessageList().addSystem(systemMessages).add(processedMemoryMessages,"memory").add(newMessages,"user");return {threadId:thread.id,messages:returnList.get.all.prompt()};}return {threadId:threadId||"",messages:userMessages||[]};}async getMemoryTools({runId,resourceId,threadId,runtimeContext,tracingContext,mastraProxy}){let convertedMemoryTools={};const memory=await this.getMemory({runtimeContext});const memoryTools=memory?.getTools?.();if(memoryTools){this.logger.debug(`[Agent:${this.name}] - Adding tools from memory ${Object.keys(memoryTools||{}).join(", ")}`,{runId});for(const[toolName,tool]of Object.entries(memoryTools)){const toolObj=tool;const options={name:toolName,runId,threadId,resourceId,logger:this.logger,mastra:mastraProxy,memory,agentName:this.name,runtimeContext,tracingContext,model:
|
|
509
|
-
vectorMessageSearch}).then(r=>r.messagesV2);}async getAssignedTools({runId,resourceId,threadId,runtimeContext,tracingContext,mastraProxy,writableStream}){let toolsForRequest={};this.logger.debug(`[Agents:${this.name}] - Assembling assigned tools`,{runId,threadId,resourceId});const memory=await this.getMemory({runtimeContext});const assignedTools=await this.getTools({runtimeContext});const assignedToolEntries=Object.entries(assignedTools||{});const assignedCoreToolEntries=await Promise.all(assignedToolEntries.map(async([k,tool])=>{if(!tool){return;}const options={name:k,runId,threadId,resourceId,logger:this.logger,mastra:mastraProxy,memory,agentName:this.name,runtimeContext,tracingContext,model:
|
|
524
|
+
newMessages,systemMessage:systemMessages,memorySystemMessage:memorySystemMessage||void 0});const returnList=new MessageList().addSystem(systemMessages).add(processedMemoryMessages,"memory").add(newMessages,"user");return {threadId:thread.id,messages:returnList.get.all.prompt()};}return {threadId:threadId||"",messages:userMessages||[]};}async getMemoryTools({runId,resourceId,threadId,runtimeContext,tracingContext,mastraProxy}){let convertedMemoryTools={};const memory=await this.getMemory({runtimeContext});const memoryTools=memory?.getTools?.();if(memoryTools){this.logger.debug(`[Agent:${this.name}] - Adding tools from memory ${Object.keys(memoryTools||{}).join(", ")}`,{runId});for(const[toolName,tool]of Object.entries(memoryTools)){const toolObj=tool;const options={name:toolName,runId,threadId,resourceId,logger:this.logger,mastra:mastraProxy,memory,agentName:this.name,runtimeContext,tracingContext,model:await this.getModel({runtimeContext}),tracingPolicy:this.#options?.tracingPolicy};const convertedToCoreTool=makeCoreTool(toolObj,options);convertedMemoryTools[toolName]=convertedToCoreTool;}}return convertedMemoryTools;}async __runInputProcessors({runtimeContext,tracingContext,messageList,inputProcessorOverrides}){let tripwireTriggered=false;let tripwireReason="";if(inputProcessorOverrides?.length||this.#inputProcessors){const runner=await this.getProcessorRunner({runtimeContext,inputProcessorOverrides});const tracedRunInputProcessors=(messageList2,tracingContext2)=>{const telemetry=this.#mastra?.getTelemetry();if(!telemetry){return runner.runInputProcessors(messageList2,tracingContext2,void 0);}return telemetry.traceMethod(async data=>{return runner.runInputProcessors(data.messageList,tracingContext2,telemetry);},{spanName:`agent.${this.name}.inputProcessors`,attributes:{"agent.name":this.name,"inputProcessors.count":runner.inputProcessors.length.toString(),"inputProcessors.names":runner.inputProcessors.map(p=>p.name).join(",")}})({messageList:messageList2});};try{messageList=await tracedRunInputProcessors(messageList,tracingContext);}catch(error){if(error instanceof TripWire){tripwireTriggered=true;tripwireReason=error.message;}else {throw new MastraError({id:"AGENT_INPUT_PROCESSOR_ERROR",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,text:`[Agent:${this.name}] - Input processor error`},error);}}}return {messageList,tripwireTriggered,tripwireReason};}async __runOutputProcessors({runtimeContext,tracingContext,messageList,outputProcessorOverrides}){let tripwireTriggered=false;let tripwireReason="";if(outputProcessorOverrides?.length||this.#outputProcessors){const runner=await this.getProcessorRunner({runtimeContext,outputProcessorOverrides});const tracedRunOutputProcessors=(messageList2,tracingContext2)=>{const telemetry=this.#mastra?.getTelemetry();if(!telemetry){return runner.runOutputProcessors(messageList2,tracingContext2,void 0);}return telemetry.traceMethod(async data=>{return runner.runOutputProcessors(data.messageList,tracingContext2,telemetry);},{spanName:`agent.${this.name}.outputProcessors`,attributes:{"agent.name":this.name,"outputProcessors.count":runner.outputProcessors.length.toString(),"outputProcessors.names":runner.outputProcessors.map(p=>p.name).join(",")}})({messageList:messageList2});};try{messageList=await tracedRunOutputProcessors(messageList,tracingContext);}catch(e){if(e instanceof TripWire){tripwireTriggered=true;tripwireReason=e.message;this.logger.debug(`[Agent:${this.name}] - Output processor tripwire triggered: ${e.message}`);}else {throw e;}}}return {messageList,tripwireTriggered,tripwireReason};}async getMemoryMessages({resourceId,threadId,vectorMessageSearch,memoryConfig,runtimeContext}){const memory=await this.getMemory({runtimeContext});if(!memory){return [];}return memory.rememberMessages({threadId,resourceId,config:memoryConfig,// The new user messages aren't in the list yet cause we add memory messages first to try to make sure ordering is correct (memory comes before new user messages)
|
|
525
|
+
vectorMessageSearch}).then(r=>r.messagesV2);}async getAssignedTools({runId,resourceId,threadId,runtimeContext,tracingContext,mastraProxy,writableStream}){let toolsForRequest={};this.logger.debug(`[Agents:${this.name}] - Assembling assigned tools`,{runId,threadId,resourceId});const memory=await this.getMemory({runtimeContext});const assignedTools=await this.getTools({runtimeContext});const assignedToolEntries=Object.entries(assignedTools||{});const assignedCoreToolEntries=await Promise.all(assignedToolEntries.map(async([k,tool])=>{if(!tool){return;}const options={name:k,runId,threadId,resourceId,logger:this.logger,mastra:mastraProxy,memory,agentName:this.name,runtimeContext,tracingContext,model:await this.getModel({runtimeContext}),writableStream,tracingPolicy:this.#options?.tracingPolicy};return [k,makeCoreTool(tool,options)];}));const assignedToolEntriesConverted=Object.fromEntries(assignedCoreToolEntries.filter(entry=>Boolean(entry)));toolsForRequest={...assignedToolEntriesConverted};return toolsForRequest;}async getToolsets({runId,threadId,resourceId,toolsets,runtimeContext,tracingContext,mastraProxy}){let toolsForRequest={};const memory=await this.getMemory({runtimeContext});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,tracingContext,model:await this.getModel({runtimeContext}),tracingPolicy:this.#options?.tracingPolicy};const convertedToCoreTool=makeCoreTool(toolObj,options,"toolset");toolsForRequest[toolName]=convertedToCoreTool;}}}return toolsForRequest;}async getClientTools({runId,threadId,resourceId,runtimeContext,tracingContext,mastraProxy,clientTools}){let toolsForRequest={};const memory=await this.getMemory({runtimeContext});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:execute2,...rest}=tool;const options={name:toolName,runId,threadId,resourceId,logger:this.logger,mastra:mastraProxy,memory,agentName:this.name,runtimeContext,tracingContext,model:await this.getModel({runtimeContext}),tracingPolicy:this.#options?.tracingPolicy};const convertedToCoreTool=makeCoreTool(rest,options,"client-tool");toolsForRequest[toolName]=convertedToCoreTool;}}return toolsForRequest;}async getWorkflowTools({runId,threadId,resourceId,runtimeContext,tracingContext,methodType,format}){const convertedWorkflowTools={};const workflows=await this.getWorkflows({runtimeContext});if(Object.keys(workflows).length>0){for(const[workflowName,workflow]of Object.entries(workflows)){const toolObj=createTool({id:workflowName,description:workflow.description||`Workflow: ${workflowName}`,inputSchema:workflow.inputSchema,outputSchema:workflow.outputSchema,mastra:this.#mastra,// manually wrap workflow tools with ai tracing, so that we can pass the
|
|
510
526
|
// current tool span onto the workflow to maintain continuity of the trace
|
|
511
|
-
execute:async({context,writer,tracingContext:innerTracingContext})=>{try{this.logger.debug(`[Agent:${this.name}] - Executing workflow as tool ${workflowName}`,{name:workflowName,description:workflow.description,args:context,runId,threadId,resourceId});const run=await workflow.createRunAsync();let result;if(methodType==="generate"){result=await run.start({inputData:context,runtimeContext,tracingContext:innerTracingContext});}else if(methodType==="stream"){const streamResult=run.stream({inputData:context,runtimeContext,tracingContext:innerTracingContext});if(writer){await streamResult.stream.pipeTo(writer);}else {for await(const _chunk of streamResult.stream){}}result=await streamResult.getWorkflowState();}else if(methodType==="streamVNext"){const streamResult=run.streamVNext({inputData:context,runtimeContext,tracingContext:innerTracingContext,format});if(writer){await streamResult.pipeTo(writer);}result=await streamResult.result;}return {result,runId:run.runId};}catch(err){const mastraError=new MastraError({id:"AGENT_WORKFLOW_TOOL_EXECUTION_FAILED",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name,runId:runId||"",threadId:threadId||"",resourceId:resourceId||""},text:`[Agent:${this.name}] - Failed workflow tool execution`},err);this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}}});const options={name:workflowName,runId,threadId,resourceId,logger:this.logger,mastra:this.#mastra,memory:await this.getMemory({runtimeContext}),agentName:this.name,runtimeContext,model:
|
|
527
|
+
execute:async({context,writer,tracingContext:innerTracingContext})=>{try{this.logger.debug(`[Agent:${this.name}] - Executing workflow as tool ${workflowName}`,{name:workflowName,description:workflow.description,args:context,runId,threadId,resourceId});const run=await workflow.createRunAsync();let result;if(methodType==="generate"){result=await run.start({inputData:context,runtimeContext,tracingContext:innerTracingContext});}else if(methodType==="stream"){const streamResult=run.stream({inputData:context,runtimeContext,tracingContext:innerTracingContext});if(writer){await streamResult.stream.pipeTo(writer);}else {for await(const _chunk of streamResult.stream){}}result=await streamResult.getWorkflowState();}else if(methodType==="streamVNext"){const streamResult=run.streamVNext({inputData:context,runtimeContext,tracingContext:innerTracingContext,format});if(writer){await streamResult.pipeTo(writer);}result=await streamResult.result;}return {result,runId:run.runId};}catch(err){const mastraError=new MastraError({id:"AGENT_WORKFLOW_TOOL_EXECUTION_FAILED",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name,runId:runId||"",threadId:threadId||"",resourceId:resourceId||""},text:`[Agent:${this.name}] - Failed workflow tool execution`},err);this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}}});const options={name:workflowName,runId,threadId,resourceId,logger:this.logger,mastra:this.#mastra,memory:await this.getMemory({runtimeContext}),agentName:this.name,runtimeContext,model:await this.getModel({runtimeContext}),tracingContext,tracingPolicy:this.#options?.tracingPolicy};convertedWorkflowTools[workflowName]=makeCoreTool(toolObj,options);}}return convertedWorkflowTools;}async convertTools({toolsets,clientTools,threadId,resourceId,runId,runtimeContext,tracingContext,writableStream,methodType,format}){let mastraProxy=void 0;const logger=this.logger;if(this.#mastra){mastraProxy=createMastraProxy({mastra:this.#mastra,logger});}const assignedTools=await this.getAssignedTools({runId,resourceId,threadId,runtimeContext,tracingContext,mastraProxy,writableStream});const memoryTools=await this.getMemoryTools({runId,resourceId,threadId,runtimeContext,tracingContext,mastraProxy});const toolsetTools=await this.getToolsets({runId,resourceId,threadId,runtimeContext,tracingContext,mastraProxy,toolsets});const clientSideTools=await this.getClientTools({runId,resourceId,threadId,runtimeContext,tracingContext,mastraProxy,clientTools});const workflowTools=await this.getWorkflowTools({runId,resourceId,threadId,runtimeContext,methodType,format,tracingContext});return this.formatTools({...assignedTools,...memoryTools,...toolsetTools,...clientSideTools,...workflowTools});}formatTools(tools){const INVALID_CHAR_REGEX=/[^a-zA-Z0-9_\-]/g;const STARTING_CHAR_REGEX=/[a-zA-Z_]/;for(const key of Object.keys(tools)){if(tools[key]&&(key.length>63||key.match(INVALID_CHAR_REGEX)||!key[0].match(STARTING_CHAR_REGEX))){let newKey=key.replace(INVALID_CHAR_REGEX,"_");if(!newKey[0].match(STARTING_CHAR_REGEX)){newKey="_"+newKey;}newKey=newKey.slice(0,63);if(tools[newKey]){const mastraError=new MastraError({id:"AGENT_TOOL_NAME_COLLISION",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name,toolName:newKey},text:`Two or more tools resolve to the same name "${newKey}". Please rename one of the tools to avoid this collision.`});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}tools[newKey]=tools[key];delete tools[key];}}return tools;}/**
|
|
512
528
|
* Adds response messages from a step to the MessageList and schedules persistence.
|
|
513
529
|
* This is used for incremental saving: after each agent step, messages are added to a save queue
|
|
514
530
|
* and a debounced save operation is triggered to avoid redundant writes.
|
|
@@ -518,7 +534,7 @@ execute:async({context,writer,tracingContext:innerTracingContext})=>{try{this.lo
|
|
|
518
534
|
* @param threadId - The thread ID.
|
|
519
535
|
* @param memoryConfig - The memory configuration for saving.
|
|
520
536
|
* @param runId - (Optional) The run ID for logging.
|
|
521
|
-
*/async saveStepMessages({saveQueueManager,result,messageList,threadId,memoryConfig,runId}){try{messageList.add(result.response.messages,"response");await saveQueueManager.batchMessages(messageList,threadId,memoryConfig);}catch(e){await saveQueueManager.flushMessages(messageList,threadId,memoryConfig);this.logger.error("Error saving memory on step finish",{error:e,runId});throw e;}}__primitive({instructions,messages,context,thread,memoryConfig,resourceId,runId,toolsets,clientTools,runtimeContext,saveQueueManager,writableStream,methodType,tracingContext,tracingOptions}){return {before:async()=>{if(process.env.NODE_ENV!=="test"){this.logger.debug(`[Agents:${this.name}] - Starting generation`,{runId});}const agentAISpan=getOrCreateSpan({type:"agent_run"/* AGENT_RUN */,name:`agent run: '${this.id}'`,input:{messages},attributes:{agentId:this.id,instructions,availableTools:[...(toolsets?Object.keys(toolsets):[]),...(clientTools?Object.keys(clientTools):[])]},metadata:{runId,resourceId,threadId:thread?thread.id:void 0},
|
|
537
|
+
*/async saveStepMessages({saveQueueManager,result,messageList,threadId,memoryConfig,runId}){try{messageList.add(result.response.messages,"response");await saveQueueManager.batchMessages(messageList,threadId,memoryConfig);}catch(e){await saveQueueManager.flushMessages(messageList,threadId,memoryConfig);this.logger.error("Error saving memory on step finish",{error:e,runId});throw e;}}__primitive({instructions,messages,context,thread,memoryConfig,resourceId,runId,toolsets,clientTools,runtimeContext,saveQueueManager,writableStream,methodType,tracingContext,tracingOptions}){return {before:async()=>{if(process.env.NODE_ENV!=="test"){this.logger.debug(`[Agents:${this.name}] - Starting generation`,{runId});}const agentAISpan=getOrCreateSpan({type:"agent_run"/* AGENT_RUN */,name:`agent run: '${this.id}'`,input:{messages},attributes:{agentId:this.id,instructions,availableTools:[...(toolsets?Object.keys(toolsets):[]),...(clientTools?Object.keys(clientTools):[])]},metadata:{runId,resourceId,threadId:thread?thread.id:void 0},tracingPolicy:this.#options?.tracingPolicy,tracingOptions,tracingContext,runtimeContext});const innerTracingContext={currentSpan:agentAISpan};const memory=await this.getMemory({runtimeContext});const toolEnhancements=[// toolsets
|
|
522
538
|
toolsets&&Object.keys(toolsets||{}).length>0?`toolsets present (${Object.keys(toolsets||{}).length} tools)`:void 0,// memory tools
|
|
523
539
|
memory&&resourceId?"memory and resourceId available":void 0].filter(Boolean).join(", ");this.logger.debug(`[Agent:${this.name}] - Enhancing tools: ${toolEnhancements}`,{runId,toolsets:toolsets?Object.keys(toolsets):void 0,clientTools:clientTools?Object.keys(clientTools):void 0,hasMemory:!!memory,hasResourceId:!!resourceId});const threadId=thread?.id;const convertedTools=await this.convertTools({toolsets,clientTools,threadId,resourceId,runId,runtimeContext,tracingContext:innerTracingContext,writableStream,methodType});const messageList=new MessageList({threadId,resourceId,generateMessageId:this.#mastra?.generateId?.bind(this.#mastra),// @ts-ignore Flag for agent network messages
|
|
524
540
|
_agentNetworkAppend:this._agentNetworkAppend}).addSystem({role:"system",content:instructions||`${this.instructions}.`}).add(context||[],"context");if(!memory||!threadId&&!resourceId){messageList.add(messages,"user");const{tripwireTriggered:tripwireTriggered2,tripwireReason:tripwireReason2}=await this.__runInputProcessors({runtimeContext,tracingContext:innerTracingContext,messageList});return {messageObjects:messageList.get.all.prompt(),convertedTools,threadExists:false,thread:void 0,messageList,agentAISpan,...(tripwireTriggered2&&{tripwire:true,tripwireReason:tripwireReason2})};}if(!threadId||!resourceId){const mastraError=new MastraError({id:"AGENT_MEMORY_MISSING_RESOURCE_ID",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name,threadId:threadId||"",resourceId:resourceId||""},text:`A resourceId and a threadId must be provided when using Memory. Saw threadId "${threadId}" and resourceId "${resourceId}"`});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());agentAISpan?.error({error:mastraError});throw mastraError;}const store=memory.constructor.name;this.logger.debug(`[Agent:${this.name}] - Memory persistence enabled: store=${store}, resourceId=${resourceId}`,{runId,resourceId,threadId,memoryStore:store});let threadObject=void 0;const existingThread=await memory.getThreadById({threadId});if(existingThread){if(!existingThread.metadata&&thread.metadata||thread.metadata&&!(0, import_fast_deep_equal.default)(existingThread.metadata,thread.metadata)){threadObject=await memory.saveThread({thread:{...existingThread,metadata:thread.metadata},memoryConfig});}else {threadObject=existingThread;}}else {threadObject=await memory.createThread({threadId,metadata:thread.metadata,title:thread.title,memoryConfig,resourceId,saveThread:false});}const config=memory.getMergedThreadConfig(memoryConfig||{});const hasResourceScopeSemanticRecall=typeof config?.semanticRecall==="object"&&config?.semanticRecall?.scope==="resource";let[memoryMessages,memorySystemMessage]=await Promise.all([existingThread||hasResourceScopeSemanticRecall?this.getMemoryMessages({resourceId,threadId:threadObject.id,vectorMessageSearch:new MessageList().add(messages,`user`).getLatestUserContent()||"",memoryConfig,runtimeContext}):[],memory.getSystemMessage({threadId:threadObject.id,resourceId,memoryConfig})]);this.logger.debug("Fetched messages from memory",{threadId:threadObject.id,runId,fetchedCount:memoryMessages.length});const resultsFromOtherThreads=memoryMessages.filter(m=>m.threadId!==threadObject.id);if(resultsFromOtherThreads.length&&!memorySystemMessage){memorySystemMessage=``;}if(resultsFromOtherThreads.length){memorySystemMessage+=`
|
|
@@ -538,9 +554,9 @@ _agentNetworkAppend:this._agentNetworkAppend}).addSystem(instructions||`${this.i
|
|
|
538
554
|
messageObjects:processedList,agentAISpan,...(tripwireTriggered&&{tripwire:true,tripwireReason}),threadExists:!!existingThread};},after:async({result,thread:threadAfter,threadId,memoryConfig:memoryConfig2,outputText,runId:runId2,messageList,threadExists,structuredOutput=false,overrideScorers,agentAISpan})=>{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});const messageListResponses=new MessageList({threadId,resourceId,generateMessageId:this.#mastra?.generateId?.bind(this.#mastra),// @ts-ignore Flag for agent network messages
|
|
539
555
|
_agentNetworkAppend:this._agentNetworkAppend}).add(result.response.messages,"response").get.all.core();const usedWorkingMemory=messageListResponses?.some(m=>m.role==="tool"&&m?.content?.some(c=>c?.toolName==="updateWorkingMemory"));const memory=await this.getMemory({runtimeContext});const thread2=usedWorkingMemory?threadId?await memory?.getThreadById({threadId}):void 0:threadAfter;if(memory&&resourceId&&thread2){try{let responseMessages=result.response.messages;if(!responseMessages&&result.object){responseMessages=[{role:"assistant",content:[{type:"text",text:outputText// outputText contains the stringified object
|
|
540
556
|
}]}];}if(responseMessages){messageList.add(responseMessages,"response");}if(!threadExists){await memory.createThread({threadId:thread2.id,metadata:thread2.metadata,title:thread2.title,memoryConfig:memoryConfig2,resourceId:thread2.resourceId});}const promises=[saveQueueManager.flushMessages(messageList,threadId,memoryConfig2)];if(thread2.title?.startsWith("New Thread")){const config=memory.getMergedThreadConfig(memoryConfig2);const userMessage=this.getMostRecentUserMessage(messageList.get.all.ui());const{shouldGenerate,model:titleModel,instructions:titleInstructions}=this.resolveTitleGenerationConfig(config?.threads?.generateTitle);if(shouldGenerate&&userMessage){promises.push(this.genTitle(userMessage,runtimeContext,{currentSpan:agentAISpan},titleModel,titleInstructions).then(title=>{if(title){return memory.createThread({threadId:thread2.id,resourceId,memoryConfig:memoryConfig2,title,metadata:thread2.metadata});}}));}}await Promise.all(promises);}catch(e){await saveQueueManager.flushMessages(messageList,threadId,memoryConfig2);if(e instanceof MastraError){agentAISpan?.error({error:e});throw e;}const mastraError=new MastraError({id:"AGENT_MEMORY_PERSIST_RESPONSE_MESSAGES_FAILED",domain:"AGENT"/* AGENT */,category:"SYSTEM"/* SYSTEM */,details:{agentName:this.name,runId:runId2||"",threadId:threadId||"",result:JSON.stringify(resToLog)}},e);this.logger.trackException(mastraError);this.logger.error(mastraError.toString());agentAISpan?.error({error:mastraError});throw mastraError;}}else {let responseMessages=result.response.messages;if(!responseMessages&&result.object){responseMessages=[{role:"assistant",content:[{type:"text",text:outputText// outputText contains the stringified object
|
|
541
|
-
}]}];}if(responseMessages){messageList.add(responseMessages,"response");}}await this.#runScorers({messageList,runId:runId2,outputText,instructions,runtimeContext,structuredOutput,overrideScorers,threadId,resourceId,tracingContext:{currentSpan:agentAISpan
|
|
557
|
+
}]}];}if(responseMessages){messageList.add(responseMessages,"response");}}await this.#runScorers({messageList,runId:runId2,outputText,instructions,runtimeContext,structuredOutput,overrideScorers,threadId,resourceId,tracingContext:{currentSpan:agentAISpan}});const scoringData={input:{inputMessages:messageList.getPersisted.input.ui(),rememberedMessages:messageList.getPersisted.remembered.ui(),systemMessages:messageList.getSystemMessages(),taggedSystemMessages:messageList.getPersisted.taggedSystemMessages},output:messageList.getPersisted.response.ui()};agentAISpan?.end({output:{text:result?.text,object:result?.object,files:result?.files}});return {scoringData};}};}async#runScorers({messageList,runId,outputText,instructions,runtimeContext,structuredOutput,overrideScorers,threadId,resourceId,tracingContext}){const agentName=this.name;const userInputMessages=messageList.get.all.ui().filter(m=>m.role==="user");const input=userInputMessages.map(message=>typeof message.content==="string"?message.content:"").join("\n");const runIdToUse=runId||this.#mastra?.generateId()||randomUUID();if(Object.keys(this.evals||{}).length>0){for(const metric of Object.values(this.evals||{})){executeHook("onGeneration"/* ON_GENERATION */,{input,output:outputText,runId:runIdToUse,metric,agentName,instructions});}}let scorers={};try{scorers=overrideScorers?this.resolveOverrideScorerReferences(overrideScorers):await this.getScorers({runtimeContext});}catch(e){this.logger.warn(`[Agent:${this.name}] - Failed to get scorers: ${e}`);return;}const scorerInput={inputMessages:messageList.getPersisted.input.ui(),rememberedMessages:messageList.getPersisted.remembered.ui(),systemMessages:messageList.getSystemMessages(),taggedSystemMessages:messageList.getPersisted.taggedSystemMessages};const scorerOutput=messageList.getPersisted.response.ui();if(Object.keys(scorers||{}).length>0){for(const[id,scorerObject]of Object.entries(scorers)){runScorer({scorerId:overrideScorers?scorerObject.scorer.name:id,scorerObject,runId,input:scorerInput,output:scorerOutput,runtimeContext,entity:{id:this.id,name:this.name},source:"LIVE",entityType:"AGENT",structuredOutput:!!structuredOutput,threadId,resourceId,tracingContext});}}}resolveOverrideScorerReferences(overrideScorers){const result={};for(const[id,scorerObject]of Object.entries(overrideScorers)){if(typeof scorerObject.scorer==="string"){try{if(!this.#mastra){throw new MastraError({id:"AGENT_GENEREATE_SCORER_NOT_FOUND",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,text:`Mastra not found when fetching scorer. Make sure to fetch agent from mastra.getAgent()`});}const scorer=this.#mastra.getScorerByName(scorerObject.scorer);result[id]={scorer,sampling:scorerObject.sampling};}catch(error){this.logger.warn(`[Agent:${this.name}] - Failed to get scorer ${scorerObject.scorer}: ${error}`);}}else {result[id]=scorerObject;}}if(Object.keys(result).length===0){throw new MastraError({id:"AGENT_GENEREATE_SCORER_NOT_FOUND",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,text:`No scorers found in overrideScorers`});}return result;}async prepareLLMOptions(messages,options,methodType){const{context,memoryOptions:memoryConfigFromArgs,resourceId:resourceIdFromArgs,maxSteps,onStepFinish,toolsets,clientTools,temperature,toolChoice="auto",runtimeContext=new RuntimeContext(),tracingContext,tracingOptions,savePerStep,writableStream,...args}=options;const threadFromArgs=resolveThreadIdFromArgs({threadId:args.threadId,memory:args.memory});const resourceId=args.memory?.resource||resourceIdFromArgs;const memoryConfig=args.memory?.options||memoryConfigFromArgs;if(resourceId&&threadFromArgs&&!this.hasOwnMemory()){this.logger.warn(`[Agent:${this.name}] - No memory is configured but resourceId and threadId were passed in args. This will not work.`);}const runId=args.runId||this.#mastra?.generateId()||randomUUID();const instructions=args.instructions||(await this.getInstructions({runtimeContext}));const llm=await this.getLLM({runtimeContext});const activeSpan=Telemetry.getActiveSpan();const baggageEntries={};if(threadFromArgs?.id){if(activeSpan){activeSpan.setAttribute("threadId",threadFromArgs.id);}baggageEntries.threadId={value:threadFromArgs.id};}if(resourceId){if(activeSpan){activeSpan.setAttribute("resourceId",resourceId);}baggageEntries.resourceId={value:resourceId};}if(Object.keys(baggageEntries).length>0){Telemetry.setBaggage(baggageEntries);}const memory=await this.getMemory({runtimeContext});const saveQueueManager=new SaveQueueManager({logger:this.logger,memory});const{before,after}=this.__primitive({messages,instructions,context,thread:threadFromArgs,memoryConfig,resourceId,runId,toolsets,clientTools,runtimeContext,saveQueueManager,writableStream,methodType,tracingContext,tracingOptions});let messageList;let thread;let threadExists;return {llm,before:async()=>{const beforeResult=await before();const{messageObjects,convertedTools,agentAISpan}=beforeResult;threadExists=beforeResult.threadExists||false;messageList=beforeResult.messageList;thread=beforeResult.thread;const threadId=thread?.id;const result={...options,messages:messageObjects,tools:convertedTools,runId,temperature,toolChoice,threadId,resourceId,runtimeContext,onStepFinish:async props=>{if(savePerStep){if(!threadExists&&memory&&thread){await memory.createThread({threadId,title:thread.title,metadata:thread.metadata,resourceId:thread.resourceId,memoryConfig});threadExists=true;}await this.saveStepMessages({saveQueueManager,result:props,messageList,threadId,memoryConfig,runId});}return onStepFinish?.({...props,runId});},...(beforeResult.tripwire&&{tripwire:beforeResult.tripwire,tripwireReason:beforeResult.tripwireReason}),...args,agentAISpan};return result;},after:async({result,outputText,structuredOutput=false,agentAISpan,overrideScorers})=>{const afterResult=await after({result,outputText,threadId:thread?.id,thread,memoryConfig,runId,messageList,structuredOutput,threadExists,agentAISpan,overrideScorers});return afterResult;}};}async prepareModels(runtimeContext,model){if(model||!Array.isArray(this.model)){const modelToUse=model??this.model;const resolvedModel=typeof modelToUse==="function"?await modelToUse({runtimeContext,mastra:this.#mastra}):modelToUse;if(resolvedModel.specificationVersion!=="v2"){const mastraError=new MastraError({id:"AGENT_PREPARE_MODELS_INCOMPATIBLE_WITH_MODEL_ARRAY_V1",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name},text:`[Agent:${this.name}] - Only v2 models are allowed when an array of models is provided`});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}return [{id:"main",model:resolvedModel,maxRetries:this.maxRetries??0,enabled:true}];}const models=await Promise.all(this.model.map(async modelConfig=>{const model2=typeof modelConfig.model==="function"?await modelConfig.model({runtimeContext,mastra:this.#mastra}):modelConfig.model;if(model2.specificationVersion!=="v2"){const mastraError=new MastraError({id:"AGENT_PREPARE_MODELS_INCOMPATIBLE_WITH_MODEL_ARRAY_V1",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name},text:`[Agent:${this.name}] - Only v2 models are allowed when an array of models is provided`});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}return {id:modelConfig.id,model:model2,maxRetries:modelConfig.maxRetries,enabled:modelConfig.enabled};}));return models;}/**
|
|
542
558
|
* Merges telemetry wrapper with default onFinish callback when needed
|
|
543
|
-
*/#mergeOnFinishWithTelemetry(streamOptions,defaultStreamOptions){let finalOnFinish=streamOptions?.onFinish||defaultStreamOptions.onFinish;if(streamOptions?.onFinish&&streamOptions.onFinish.__hasOriginalOnFinish===false&&defaultStreamOptions.onFinish){const telemetryWrapper=streamOptions.onFinish;const defaultCallback=defaultStreamOptions.onFinish;finalOnFinish=async data=>{await telemetryWrapper(data);await defaultCallback(data);};}return finalOnFinish;}async#execute({methodType,format="mastra",...options}){const runtimeContext=options.runtimeContext||new RuntimeContext();const threadFromArgs=resolveThreadIdFromArgs({threadId:options.threadId,memory:options.memory});const resourceId=options.memory?.resource||options.resourceId;const memoryConfig=options.memory?.options;if(resourceId&&threadFromArgs&&!this.hasOwnMemory()){this.logger.warn(`[Agent:${this.name}] - No memory is configured but resourceId and threadId were passed in args. This will not work.`);}const llm=await this.getLLM({runtimeContext,model:options.model});const runId=options.runId||this.#mastra?.generateId()||randomUUID();const instructions=options.instructions||(await this.getInstructions({runtimeContext}));const agentAISpan=getOrCreateSpan({type:"agent_run"/* AGENT_RUN */,name:`agent run: '${this.id}'`,input:options.messages,attributes:{agentId:this.id,instructions},metadata:{runId,resourceId,threadId:threadFromArgs?.id},
|
|
559
|
+
*/#mergeOnFinishWithTelemetry(streamOptions,defaultStreamOptions){let finalOnFinish=streamOptions?.onFinish||defaultStreamOptions.onFinish;if(streamOptions?.onFinish&&streamOptions.onFinish.__hasOriginalOnFinish===false&&defaultStreamOptions.onFinish){const telemetryWrapper=streamOptions.onFinish;const defaultCallback=defaultStreamOptions.onFinish;finalOnFinish=async data=>{await telemetryWrapper(data);await defaultCallback(data);};}return finalOnFinish;}async#execute({methodType,format="mastra",...options}){const runtimeContext=options.runtimeContext||new RuntimeContext();const threadFromArgs=resolveThreadIdFromArgs({threadId:options.threadId,memory:options.memory});const resourceId=options.memory?.resource||options.resourceId;const memoryConfig=options.memory?.options;if(resourceId&&threadFromArgs&&!this.hasOwnMemory()){this.logger.warn(`[Agent:${this.name}] - No memory is configured but resourceId and threadId were passed in args. This will not work.`);}const llm=await this.getLLM({runtimeContext,model:options.model});const runId=options.runId||this.#mastra?.generateId()||randomUUID();const instructions=options.instructions||(await this.getInstructions({runtimeContext}));const agentAISpan=getOrCreateSpan({type:"agent_run"/* AGENT_RUN */,name:`agent run: '${this.id}'`,input:options.messages,attributes:{agentId:this.id,instructions},metadata:{runId,resourceId,threadId:threadFromArgs?.id},tracingPolicy:this.#options?.tracingPolicy,tracingOptions:options.tracingOptions,tracingContext:options.tracingContext,runtimeContext});const activeSpan=Telemetry.getActiveSpan();const baggageEntries={};if(threadFromArgs?.id){if(activeSpan){activeSpan.setAttribute("threadId",threadFromArgs.id);}baggageEntries.threadId={value:threadFromArgs.id};}if(resourceId){if(activeSpan){activeSpan.setAttribute("resourceId",resourceId);}baggageEntries.resourceId={value:resourceId};}if(Object.keys(baggageEntries).length>0){Telemetry.setBaggage(baggageEntries);}const memory=await this.getMemory({runtimeContext});const saveQueueManager=new SaveQueueManager({logger:this.logger,memory});if(process.env.NODE_ENV!=="test"){this.logger.debug(`[Agents:${this.name}] - Starting generation`,{runId});}const prepareToolsStep=createStep({id:"prepare-tools-step",inputSchema:z.any(),outputSchema:z.object({convertedTools:z.record(z.string(),z.any())}),execute:async()=>{const toolEnhancements=[// toolsets
|
|
544
560
|
options?.toolsets&&Object.keys(options?.toolsets||{}).length>0?`toolsets present (${Object.keys(options?.toolsets||{}).length} tools)`:void 0,// memory tools
|
|
545
561
|
memory&&resourceId?"memory and resourceId available":void 0].filter(Boolean).join(", ");this.logger.debug(`[Agent:${this.name}] - Enhancing tools: ${toolEnhancements}`,{runId,toolsets:options?.toolsets?Object.keys(options?.toolsets):void 0,clientTools:options?.clientTools?Object.keys(options?.clientTools):void 0,hasMemory:!!memory,hasResourceId:!!resourceId});const threadId=threadFromArgs?.id;const convertedTools=await this.convertTools({toolsets:options?.toolsets,clientTools:options?.clientTools,threadId,resourceId,runId,runtimeContext,tracingContext:{currentSpan:agentAISpan},writableStream:options.writableStream,methodType,format});return {convertedTools};}});const prepareMemory=createStep({id:"prepare-memory-step",inputSchema:z.any(),outputSchema:z.object({threadExists:z.boolean(),thread:z.any(),messageList:z.any(),tripwire:z.boolean().optional(),tripwireReason:z.string().optional()}),execute:async({tracingContext})=>{const thread=threadFromArgs;const messageList=new MessageList({threadId:thread?.id,resourceId,generateMessageId:this.#mastra?.generateId?.bind(this.#mastra),// @ts-ignore Flag for agent network messages
|
|
546
562
|
_agentNetworkAppend:this._agentNetworkAppend}).addSystem({role:"system",content:instructions||`${this.instructions}.`}).add(options.context||[],"context");if(!memory||!thread?.id&&!resourceId){messageList.add(options.messages,"user");const{tripwireTriggered:tripwireTriggered2,tripwireReason:tripwireReason2}=await this.__runInputProcessors({runtimeContext,tracingContext,messageList});return {threadExists:false,thread:void 0,messageList,...(tripwireTriggered2&&{tripwire:true,tripwireReason:tripwireReason2})};}if(!thread?.id||!resourceId){const mastraError=new MastraError({id:"AGENT_MEMORY_MISSING_RESOURCE_ID",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{agentName:this.name,threadId:thread?.id||"",resourceId:resourceId||""},text:`A resourceId and a threadId must be provided when using Memory. Saw threadId "${thread?.id}" and resourceId "${resourceId}"`});this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}const store=memory.constructor.name;this.logger.debug(`[Agent:${this.name}] - Memory persistence enabled: store=${store}, resourceId=${resourceId}`,{runId,resourceId,threadId:thread?.id,memoryStore:store});let threadObject=void 0;const existingThread=await memory.getThreadById({threadId:thread?.id});if(existingThread){if(!existingThread.metadata&&thread.metadata||thread.metadata&&!(0, import_fast_deep_equal.default)(existingThread.metadata,thread.metadata)){threadObject=await memory.saveThread({thread:{...existingThread,metadata:thread.metadata},memoryConfig});}else {threadObject=existingThread;}}else {threadObject=await memory.createThread({threadId:thread?.id,metadata:thread.metadata,title:thread.title,memoryConfig,resourceId,saveThread:false});}const config=memory.getMergedThreadConfig(memoryConfig||{});const hasResourceScopeSemanticRecall=typeof config?.semanticRecall==="object"&&config?.semanticRecall?.scope==="resource";let[memoryMessages,memorySystemMessage]=await Promise.all([existingThread||hasResourceScopeSemanticRecall?this.getMemoryMessages({resourceId,threadId:threadObject.id,vectorMessageSearch:new MessageList().add(options.messages,`user`).getLatestUserContent()||"",memoryConfig,runtimeContext}):[],memory.getSystemMessage({threadId:threadObject.id,resourceId,memoryConfig})]);this.logger.debug("Fetched messages from memory",{threadId:threadObject.id,runId,fetchedCount:memoryMessages.length});const resultsFromOtherThreads=memoryMessages.filter(m=>m.threadId!==threadObject.id);if(resultsFromOtherThreads.length&&!memorySystemMessage){memorySystemMessage=``;}if(resultsFromOtherThreads.length){memorySystemMessage+=`
|
|
@@ -556,9 +572,11 @@ messages:messageList.get.remembered.v1(),// these are here for inspecting but sh
|
|
|
556
572
|
// - ex TokenLimiter needs to measure all tokens even though it's only processing remembered messages
|
|
557
573
|
newMessages:messageList.get.input.v1(),systemMessage,memorySystemMessage:memorySystemMessage||void 0});const processedList=new MessageList({threadId:threadObject.id,resourceId,generateMessageId:this.#mastra?.generateId?.bind(this.#mastra),// @ts-ignore Flag for agent network messages
|
|
558
574
|
_agentNetworkAppend:this._agentNetworkAppend}).addSystem(instructions||`${this.instructions}.`).addSystem(memorySystemMessage).addSystem(systemMessages).add(options.context||[],"context").add(processedMemoryMessages,"memory").add(messageList.get.input.v2(),"user");return {thread:threadObject,messageList:processedList,// add old processed messages + new input messages
|
|
559
|
-
...(tripwireTriggered&&{tripwire:true,tripwireReason}),threadExists:!!existingThread};}});const streamStep=createStep({id:"stream-text-step",inputSchema:z.any(),outputSchema:z.any(),execute:async({inputData,tracingContext})=>{this.logger.debug(`Starting agent ${this.name} llm stream call`,{runId});const outputProcessors=inputData.outputProcessors||(this.#outputProcessors?typeof this.#outputProcessors==="function"?await this.#outputProcessors({runtimeContext:inputData.runtimeContext||new RuntimeContext()}):this.#outputProcessors:[]);const streamResult=llm.stream({...inputData,outputProcessors,returnScorerData:options.returnScorerData,tracingContext,_internal:{generateId:inputData.experimental_generateMessageId||this.#mastra?.generateId?.bind(this.#mastra)}});if(format==="aisdk"){return streamResult.aisdk.v5;}return streamResult;}});const executionWorkflow=createWorkflow({id:"execution-workflow",inputSchema:z.any(),outputSchema:z.any(),steps:[prepareToolsStep,prepareMemory]
|
|
575
|
+
...(tripwireTriggered&&{tripwire:true,tripwireReason}),threadExists:!!existingThread};}});const streamStep=createStep({id:"stream-text-step",inputSchema:z.any(),outputSchema:z.any(),execute:async({inputData,tracingContext})=>{this.logger.debug(`Starting agent ${this.name} llm stream call`,{runId});const outputProcessors=inputData.outputProcessors||(this.#outputProcessors?typeof this.#outputProcessors==="function"?await this.#outputProcessors({runtimeContext:inputData.runtimeContext||new RuntimeContext()}):this.#outputProcessors:[]);const streamResult=llm.stream({...inputData,outputProcessors,returnScorerData:options.returnScorerData,tracingContext,_internal:{generateId:inputData.experimental_generateMessageId||this.#mastra?.generateId?.bind(this.#mastra)}});if(format==="aisdk"){return streamResult.aisdk.v5;}return streamResult;}});const executionWorkflow=createWorkflow({id:"execution-workflow",inputSchema:z.any(),outputSchema:z.any(),steps:[prepareToolsStep,prepareMemory],options:{tracingPolicy:{// mark all workflow spans related to the
|
|
576
|
+
// VNext execution as internal
|
|
577
|
+
internal:1/* WORKFLOW */}}}).parallel([prepareToolsStep,prepareMemory]).map(async({inputData,bail})=>{const result2={...options,tools:inputData["prepare-tools-step"].convertedTools,runId,toolChoice:options.toolChoice,thread:inputData["prepare-memory-step"].thread,threadId:inputData["prepare-memory-step"].thread?.id,resourceId,runtimeContext,onStepFinish:async props=>{if(options.savePerStep){if(!inputData["prepare-memory-step"].threadExists&&memory&&inputData["prepare-memory-step"].thread){await memory.createThread({threadId:inputData["prepare-memory-step"].thread?.id,title:inputData["prepare-memory-step"].thread?.title,metadata:inputData["prepare-memory-step"].thread?.metadata,resourceId:inputData["prepare-memory-step"].thread?.resourceId,memoryConfig});inputData["prepare-memory-step"].threadExists=true;}await this.saveStepMessages({saveQueueManager,result:props,messageList:inputData["prepare-memory-step"].messageList,threadId:inputData["prepare-memory-step"].thread?.id,memoryConfig,runId});}return options.onStepFinish?.({...props,runId});},...(inputData["prepare-memory-step"].tripwire&&{tripwire:inputData["prepare-memory-step"].tripwire,tripwireReason:inputData["prepare-memory-step"].tripwireReason})};if(result2.tripwire){const emptyResult={textStream:async function*(){}(),fullStream:new globalThis.ReadableStream({start(controller){controller.enqueue({type:"tripwire",runId:result2.runId,from:"AGENT"/* AGENT */,payload:{tripwireReason:result2.tripwireReason}});controller.close();}}),objectStream:new globalThis.ReadableStream({start(controller){controller.close();}}),text:Promise.resolve(""),usage:Promise.resolve({inputTokens:0,outputTokens:0,totalTokens:0}),finishReason:Promise.resolve("other"),tripwire:true,tripwireReason:result2.tripwireReason,response:{id:randomUUID(),timestamp:/* @__PURE__ */new Date(),modelId:"tripwire",messages:[]},toolCalls:Promise.resolve([]),toolResults:Promise.resolve([]),warnings:Promise.resolve(void 0),request:{body:JSON.stringify({messages:[]})},object:void 0,experimental_output:void 0,steps:void 0,experimental_providerMetadata:void 0};return bail(emptyResult);}let effectiveOutputProcessors=options.outputProcessors||(this.#outputProcessors?typeof this.#outputProcessors==="function"?await this.#outputProcessors({runtimeContext:result2.runtimeContext}):this.#outputProcessors:[]);if(options.structuredOutput){const agentModel=await this.getModel({runtimeContext:result2.runtimeContext});const structuredProcessor=new StructuredOutputProcessor(options.structuredOutput,agentModel);effectiveOutputProcessors=effectiveOutputProcessors?[...effectiveOutputProcessors,structuredProcessor]:[structuredProcessor];}const loopOptions={runtimeContext:result2.runtimeContext,tracingContext:{currentSpan:agentAISpan},runId,toolChoice:result2.toolChoice,tools:result2.tools,resourceId:result2.resourceId,threadId:result2.threadId,structuredOutput:result2.structuredOutput,stopWhen:result2.stopWhen,maxSteps:result2.maxSteps,providerOptions:result2.providerOptions,options:{...(options.prepareStep&&{prepareStep:options.prepareStep}),onFinish:async payload=>{if(payload.finishReason==="error"){this.logger.error("Error in agent stream",{error:payload.error,runId});return;}const messageList=inputData["prepare-memory-step"].messageList;try{const outputText=messageList.get.all.core().map(m=>m.content).join("\n");await this.#executeOnFinish({result:payload,outputText,instructions,thread:result2.thread,threadId:result2.threadId,readOnlyMemory:options.memory?.readOnly,resourceId,memoryConfig,runtimeContext,agentAISpan,runId,messageList,threadExists:inputData["prepare-memory-step"].threadExists,structuredOutput:!!options.output,saveQueueManager,overrideScorers:options.scorers});}catch(e){this.logger.error("Error saving memory on finish",{error:e,runId});}await options?.onFinish?.({...payload,runId,messages:messageList.get.response.aiV5.model(),usage:payload.usage,totalUsage:payload.totalUsage});},onStepFinish:result2.onStepFinish,onChunk:options.onChunk,onError:options.onError,onAbort:options.onAbort,activeTools:options.activeTools,abortSignal:options.abortSignal},output:options.output,outputProcessors:effectiveOutputProcessors,modelSettings:{temperature:0,...(options.modelSettings||{})},messageList:inputData["prepare-memory-step"].messageList};return loopOptions;}).then(streamStep).commit();const run=await executionWorkflow.createRunAsync();const result=await run.start({tracingContext:{currentSpan:agentAISpan}});return result;}async#executeOnFinish({result,instructions,readOnlyMemory,thread:threadAfter,threadId,resourceId,memoryConfig,outputText,runtimeContext,agentAISpan,runId,messageList,threadExists,structuredOutput=false,saveQueueManager,overrideScorers}){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,result:resToLog,threadId,resourceId});const messageListResponses=messageList.get.response.aiV4.core();const usedWorkingMemory=messageListResponses?.some(m=>m.role==="tool"&&m?.content?.some(c=>c?.toolName==="updateWorkingMemory"));const memory=await this.getMemory({runtimeContext});const thread=usedWorkingMemory?threadId?await memory?.getThreadById({threadId}):void 0:threadAfter;if(memory&&resourceId&&thread&&!readOnlyMemory){try{let responseMessages=result.response.messages;if(!responseMessages&&result.object){responseMessages=[{role:"assistant",content:[{type:"text",text:outputText// outputText contains the stringified object
|
|
560
578
|
}]}];}if(responseMessages){const filteredMessages=responseMessages.filter(m=>m.role!=="user");messageList.add(filteredMessages,"response");}if(!threadExists){await memory.createThread({threadId:thread.id,metadata:thread.metadata,title:thread.title,memoryConfig,resourceId:thread.resourceId});}const promises=[saveQueueManager.flushMessages(messageList,threadId,memoryConfig)];if(thread.title?.startsWith("New Thread")){const config=memory.getMergedThreadConfig(memoryConfig);const userMessage=this.getMostRecentUserMessage(messageList.get.all.ui());const{shouldGenerate,model:titleModel,instructions:titleInstructions}=this.resolveTitleGenerationConfig(config?.threads?.generateTitle);if(shouldGenerate&&userMessage){promises.push(this.genTitle(userMessage,runtimeContext,{currentSpan:agentAISpan},titleModel,titleInstructions).then(title=>{if(title){return memory.createThread({threadId:thread.id,resourceId,memoryConfig,title,metadata:thread.metadata});}}));}}await Promise.all(promises);}catch(e){await saveQueueManager.flushMessages(messageList,threadId,memoryConfig);if(e instanceof MastraError){throw e;}const mastraError=new MastraError({id:"AGENT_MEMORY_PERSIST_RESPONSE_MESSAGES_FAILED",domain:"AGENT"/* AGENT */,category:"SYSTEM"/* SYSTEM */,details:{agentName:this.name,runId:runId||"",threadId:threadId||"",result:JSON.stringify(resToLog)}},e);this.logger.trackException(mastraError);this.logger.error(mastraError.toString());throw mastraError;}}else {let responseMessages=result.response.messages;if(!responseMessages&&result.object){responseMessages=[{role:"assistant",content:[{type:"text",text:outputText// outputText contains the stringified object
|
|
561
|
-
}]}];}if(responseMessages){messageList.add(responseMessages,"response");}}await this.#runScorers({messageList,runId,outputText,instructions,runtimeContext,structuredOutput,overrideScorers,tracingContext:{currentSpan:agentAISpan
|
|
579
|
+
}]}];}if(responseMessages){messageList.add(responseMessages,"response");}}await this.#runScorers({messageList,runId,outputText,instructions,runtimeContext,structuredOutput,overrideScorers,tracingContext:{currentSpan:agentAISpan}});agentAISpan?.end({output:{text:result?.text,object:result?.object,files:result?.files}});}async network(messages,options){const runId=options?.runId||this.#mastra?.generateId()||randomUUID();const runtimeContextToUse=options?.runtimeContext||new RuntimeContext();return await networkLoop({networkName:this.name,runtimeContext:runtimeContextToUse,runId,routingAgent:this,routingAgentOptions:{telemetry:options?.telemetry,modelSettings:options?.modelSettings},generateId:()=>this.#mastra?.generateId()||randomUUID(),maxIterations:options?.maxSteps||1,messages,threadId:typeof options?.memory?.thread==="string"?options?.memory?.thread:options?.memory?.thread?.id,resourceId:options?.memory?.resource});}async generateVNext(messages,options){const result=await this.streamVNext(messages,options);if(result.tripwire){return result;}let fullOutput=await result.getFullOutput();const error=fullOutput.error;if(fullOutput.finishReason==="error"&&error){throw error;}return fullOutput;}async streamVNext(messages,streamOptions){const defaultStreamOptions=await this.getDefaultVNextStreamOptions({runtimeContext:streamOptions?.runtimeContext});let mergedStreamOptions={...defaultStreamOptions,...streamOptions,onFinish:this.#mergeOnFinishWithTelemetry(streamOptions,defaultStreamOptions)};let modelOverride;if(mergedStreamOptions.structuredOutput&&mergedStreamOptions.maxSteps===1){if(mergedStreamOptions.structuredOutput.model){modelOverride=mergedStreamOptions.structuredOutput.model;}mergedStreamOptions={...mergedStreamOptions,output:mergedStreamOptions.structuredOutput.schema,structuredOutput:void 0// Remove structuredOutput to avoid confusion downstream
|
|
562
580
|
};}const llm=await this.getLLM({runtimeContext:mergedStreamOptions.runtimeContext,model:modelOverride});if(llm.getModel().specificationVersion!=="v2"){throw new MastraError({id:"AGENT_STREAM_VNEXT_V1_MODEL_NOT_SUPPORTED",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,text:"V1 models are not supported for streamVNext. Please use stream instead."});}const result=await this.#execute({...mergedStreamOptions,messages,methodType:"streamVNext",model:modelOverride});if(result.status!=="success"){if(result.status==="failed"){throw new MastraError({id:"AGENT_STREAM_VNEXT_FAILED",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,text:result.error.message,details:{error:result.error.message}});}throw new MastraError({id:"AGENT_STREAM_VNEXT_UNKNOWN_ERROR",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,text:"An unknown error occurred while streaming"});}return result.result;}async generate(messages,generateOptions={}){this.logger.warn("Deprecation NOTICE:\nGenerate method will switch to use generateVNext implementation September 23rd, 2025. Please use generateLegacy if you don't want to upgrade just yet.");return this.generateLegacy(messages,generateOptions);}async generateLegacy(messages,generateOptions={}){const defaultGenerateOptions=await this.getDefaultGenerateOptions({runtimeContext:generateOptions.runtimeContext});const mergedGenerateOptions={...defaultGenerateOptions,...generateOptions,experimental_generateMessageId:defaultGenerateOptions.experimental_generateMessageId||this.#mastra?.generateId?.bind(this.#mastra)};const{llm,before,after}=await this.prepareLLMOptions(messages,mergedGenerateOptions,"generate");if(llm.getModel().specificationVersion!=="v1"){this.logger.error("V2 models are not supported for the current version of generate. Please use generateVNext instead.",{modelId:llm.getModel().modelId});throw new MastraError({id:"AGENT_GENERATE_V2_MODEL_NOT_SUPPORTED",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{modelId:llm.getModel().modelId},text:"V2 models are not supported for the current version of generate. Please use generateVNext instead."});}let llmToUse=llm;const beforeResult=await before();const traceId=getValidTraceId(beforeResult.agentAISpan);if(beforeResult.tripwire){const tripwireResult={text:"",object:void 0,usage:{totalTokens:0,promptTokens:0,completionTokens:0},finishReason:"other",response:{id:randomUUID(),timestamp:/* @__PURE__ */new Date(),modelId:"tripwire",messages:[]},responseMessages:[],toolCalls:[],toolResults:[],warnings:void 0,request:{body:JSON.stringify({messages:[]})},experimental_output:void 0,steps:void 0,experimental_providerMetadata:void 0,tripwire:true,tripwireReason:beforeResult.tripwireReason,traceId};return tripwireResult;}const{experimental_output,output,agentAISpan,...llmOptions}=beforeResult;const tracingContext={currentSpan:agentAISpan};let finalOutputProcessors=mergedGenerateOptions.outputProcessors;if(mergedGenerateOptions.structuredOutput){const agentModel=await this.getModel({runtimeContext:mergedGenerateOptions.runtimeContext});const structuredProcessor=new StructuredOutputProcessor(mergedGenerateOptions.structuredOutput,agentModel);finalOutputProcessors=finalOutputProcessors?[...finalOutputProcessors,structuredProcessor]:[structuredProcessor];}if(!output||experimental_output){const result2=await llmToUse.__text({...llmOptions,tracingContext,experimental_output});const outputProcessorResult2=await this.__runOutputProcessors({runtimeContext:mergedGenerateOptions.runtimeContext||new RuntimeContext(),tracingContext,outputProcessorOverrides:finalOutputProcessors,messageList:new MessageList({threadId:llmOptions.threadId||"",resourceId:llmOptions.resourceId||""}).add({role:"assistant",content:[{type:"text",text:result2.text}]},"response")});if(outputProcessorResult2.tripwireTriggered){const tripwireResult={text:"",object:void 0,usage:{totalTokens:0,promptTokens:0,completionTokens:0},finishReason:"other",response:{id:randomUUID(),timestamp:/* @__PURE__ */new Date(),modelId:"tripwire",messages:[]},responseMessages:[],toolCalls:[],toolResults:[],warnings:void 0,request:{body:JSON.stringify({messages:[]})},experimental_output:void 0,steps:void 0,experimental_providerMetadata:void 0,tripwire:true,tripwireReason:outputProcessorResult2.tripwireReason,traceId};return tripwireResult;}const newText2=outputProcessorResult2.messageList.get.response.v2().map(msg=>msg.content.parts.map(part=>part.type==="text"?part.text:"").join("")).join("");result2.text=newText2;if(finalOutputProcessors&&finalOutputProcessors.length>0){const messages2=outputProcessorResult2.messageList.get.response.v2();this.logger.debug("Checking messages for experimentalOutput metadata:",messages2.map(m=>({role:m.role,hasContentMetadata:!!m.content.metadata,contentMetadata:m.content.metadata})));const messagesWithStructuredData=messages2.filter(msg=>msg.content.metadata&&msg.content.metadata.structuredOutput);this.logger.debug("Messages with structured data:",messagesWithStructuredData.length);if(messagesWithStructuredData[0]&&messagesWithStructuredData[0].content.metadata?.structuredOutput){result2.object=messagesWithStructuredData[0].content.metadata.structuredOutput;this.logger.debug("Using structured data from processor metadata for result.object");}else {try{const processedOutput=JSON.parse(newText2);result2.object=processedOutput;this.logger.debug("Using fallback JSON parsing for result.object");}catch(error){this.logger.warn("Failed to parse processed output as JSON, updating text only",{error});}}}const overrideScorers=mergedGenerateOptions.scorers;const afterResult2=await after({result:result2,outputText:newText2,agentAISpan,...(overrideScorers?{overrideScorers}:{})});if(generateOptions.returnScorerData){result2.scoringData=afterResult2.scoringData;}result2.traceId=traceId;return result2;}const result=await llmToUse.__textObject({...llmOptions,tracingContext,structuredOutput:output});const outputText=JSON.stringify(result.object);const outputProcessorResult=await this.__runOutputProcessors({runtimeContext:mergedGenerateOptions.runtimeContext||new RuntimeContext(),tracingContext,messageList:new MessageList({threadId:llmOptions.threadId||"",resourceId:llmOptions.resourceId||""}).add({role:"assistant",content:[{type:"text",text:outputText}]},"response")});if(outputProcessorResult.tripwireTriggered){const tripwireResult={text:"",object:void 0,usage:{totalTokens:0,promptTokens:0,completionTokens:0},finishReason:"other",response:{id:randomUUID(),timestamp:/* @__PURE__ */new Date(),modelId:"tripwire",messages:[]},responseMessages:[],toolCalls:[],toolResults:[],warnings:void 0,request:{body:JSON.stringify({messages:[]})},experimental_output:void 0,steps:void 0,experimental_providerMetadata:void 0,tripwire:true,tripwireReason:outputProcessorResult.tripwireReason,traceId};return tripwireResult;}const newText=outputProcessorResult.messageList.get.response.v2().map(msg=>msg.content.parts.map(part=>part.type==="text"?part.text:"").join("")).join("");try{const processedObject=JSON.parse(newText);result.object=processedObject;}catch(error){this.logger.warn("Failed to parse processed output as JSON, keeping original result",{error});}const afterResult=await after({result,outputText:newText,...(generateOptions.scorers?{overrideScorers:generateOptions.scorers}:{}),structuredOutput:true,agentAISpan});if(generateOptions.returnScorerData){result.scoringData=afterResult.scoringData;}result.traceId=traceId;return result;}async stream(messages,streamOptions={}){this.logger.warn("Deprecation NOTICE:\nStream method will switch to use streamVNext implementation September 23rd, 2025. Please use streamLegacy if you don't want to upgrade just yet.");return this.streamLegacy(messages,streamOptions);}async streamLegacy(messages,streamOptions={}){const defaultStreamOptions=await this.getDefaultStreamOptions({runtimeContext:streamOptions.runtimeContext});const mergedStreamOptions={...defaultStreamOptions,...streamOptions,onFinish:this.#mergeOnFinishWithTelemetry(streamOptions,defaultStreamOptions),experimental_generateMessageId:defaultStreamOptions.experimental_generateMessageId||this.#mastra?.generateId?.bind(this.#mastra)};const{llm,before,after}=await this.prepareLLMOptions(messages,mergedStreamOptions,"stream");if(llm.getModel().specificationVersion!=="v1"){this.logger.error("V2 models are not supported for stream. Please use streamVNext instead.",{modelId:llm.getModel().modelId});throw new MastraError({id:"AGENT_STREAM_V2_MODEL_NOT_SUPPORTED",domain:"AGENT"/* AGENT */,category:"USER"/* USER */,details:{modelId:llm.getModel().modelId},text:"V2 models are not supported for stream. Please use streamVNext instead."});}const beforeResult=await before();const traceId=getValidTraceId(beforeResult.agentAISpan);if(beforeResult.tripwire){const emptyResult={textStream:async function*(){}(),fullStream:Promise.resolve("").then(()=>{const emptyStream=new globalThis.ReadableStream({start(controller){controller.close();}});return emptyStream;}),text:Promise.resolve(""),usage:Promise.resolve({totalTokens:0,promptTokens:0,completionTokens:0}),finishReason:Promise.resolve("other"),tripwire:true,tripwireReason:beforeResult.tripwireReason,response:{id:randomUUID(),timestamp:/* @__PURE__ */new Date(),modelId:"tripwire",messages:[]},toolCalls:Promise.resolve([]),toolResults:Promise.resolve([]),warnings:Promise.resolve(void 0),request:{body:JSON.stringify({messages:[]})},experimental_output:void 0,steps:void 0,experimental_providerMetadata:void 0,traceId,toAIStream:()=>Promise.resolve("").then(()=>{const emptyStream=new globalThis.ReadableStream({start(controller){controller.close();}});return emptyStream;}),get experimental_partialOutputStream(){return async function*(){}();},pipeDataStreamToResponse:()=>Promise.resolve(),pipeTextStreamToResponse:()=>Promise.resolve(),toDataStreamResponse:()=>new Response("",{status:200,headers:{"Content-Type":"text/plain"}}),toTextStreamResponse:()=>new Response("",{status:200,headers:{"Content-Type":"text/plain"}})};return emptyResult;}const{onFinish,runId,output,experimental_output,agentAISpan,...llmOptions}=beforeResult;const overrideScorers=mergedStreamOptions.scorers;const tracingContext={currentSpan:agentAISpan};if(!output||experimental_output){this.logger.debug(`Starting agent ${this.name} llm stream call`,{runId});const streamResult=llm.__stream({...llmOptions,experimental_output,tracingContext,outputProcessors:await this.getResolvedOutputProcessors(mergedStreamOptions.runtimeContext),onFinish:async result=>{try{const outputText=result.text;await after({result,outputText,agentAISpan,...(overrideScorers?{overrideScorers}:{})});}catch(e){this.logger.error("Error saving memory on finish",{error:e,runId});}await onFinish?.({...result,runId});},runId});streamResult.traceId=traceId;return streamResult;}this.logger.debug(`Starting agent ${this.name} llm streamObject call`,{runId});const streamObjectResult=llm.__streamObject({...llmOptions,tracingContext,onFinish:async result=>{try{const outputText=JSON.stringify(result.object);await after({result,outputText,structuredOutput:true,agentAISpan,...(overrideScorers?{overrideScorers}:{})});}catch(e){this.logger.error("Error saving memory on finish",{error:e,runId});}await onFinish?.({...result,runId});},runId,structuredOutput:output});streamObjectResult.traceId=traceId;return streamObjectResult;}/**
|
|
563
581
|
* Convert text to speech using the configured voice provider
|
|
564
582
|
* @param input Text or text stream to convert to speech
|
|
@@ -592,7 +610,7 @@ return Agent;})();// src/processors/processors/moderation.ts
|
|
|
592
610
|
var ModerationProcessor=class _ModerationProcessor{name="moderation";moderationAgent;categories;threshold;strategy;includeScores;chunkWindow;// Default OpenAI moderation categories
|
|
593
611
|
static DEFAULT_CATEGORIES=["hate","hate/threatening","harassment","harassment/threatening","self-harm","self-harm/intent","self-harm/instructions","sexual","sexual/minors","violence","violence/graphic"];constructor(options){this.categories=options.categories||_ModerationProcessor.DEFAULT_CATEGORIES;this.threshold=options.threshold??0.5;this.strategy=options.strategy||"block";this.includeScores=options.includeScores??false;this.chunkWindow=options.chunkWindow??0;this.moderationAgent=new Agent({name:"content-moderator",instructions:options.instructions||this.createDefaultInstructions(),model:options.model});}async processInput(args){try{const{messages,abort,tracingContext}=args;if(messages.length===0){return messages;}const passedMessages=[];for(const message of messages){const textContent=this.extractTextContent(message);if(!textContent.trim()){passedMessages.push(message);continue;}const moderationResult=await this.moderateContent(textContent,false,tracingContext);if(this.isModerationFlagged(moderationResult)){this.handleFlaggedContent(moderationResult,this.strategy,abort);if(this.strategy==="filter"){continue;}}passedMessages.push(message);}return passedMessages;}catch(error){if(error instanceof TripWire){throw error;}args.abort(`Moderation failed: ${error instanceof Error?error.message:"Unknown error"}`);}}async processOutputResult(args){return this.processInput(args);}async processOutputStream(args){try{const{part,streamParts,abort,tracingContext}=args;if(part.type!=="text-delta"){return part;}const contentToModerate=this.buildContextFromChunks(streamParts);const moderationResult=await this.moderateContent(contentToModerate,true,tracingContext);if(this.isModerationFlagged(moderationResult)){this.handleFlaggedContent(moderationResult,this.strategy,abort);if(this.strategy==="filter"){return null;}}return part;}catch(error){if(error instanceof TripWire){throw error;}console.warn("[ModerationProcessor] Stream moderation failed:",error);return args.part;}}/**
|
|
594
612
|
* Moderate content using the internal agent
|
|
595
|
-
*/async moderateContent(content,isStream=false,tracingContext){const prompt=this.createModerationPrompt(content,isStream);try{const model=await this.moderationAgent.getModel();const schema=
|
|
613
|
+
*/async moderateContent(content,isStream=false,tracingContext){const prompt=this.createModerationPrompt(content,isStream);try{const model=await this.moderationAgent.getModel();const schema=z5.object({category_scores:z5.object(this.categories.reduce((props,category)=>{props[category]=z5.number().min(0).max(1).optional();return props;},{})).optional(),reason:z5.string().optional()});let response;if(model.specificationVersion==="v2"){response=await this.moderationAgent.generateVNext(prompt,{output:schema,modelSettings:{temperature:0},tracingContext});}else {response=await this.moderationAgent.generate(prompt,{output:schema,temperature:0,tracingContext});}const result=response.object;return result;}catch(error){console.warn("[ModerationProcessor] Agent moderation failed, allowing content:",error);return {};}}/**
|
|
596
614
|
* Determine if content is flagged based on category scores above threshold
|
|
597
615
|
*/isModerationFlagged(result){if(result.category_scores){const scores=Object.values(result.category_scores).filter(score=>typeof score==="number");if(scores.length===0)return false;const maxScore=Math.max(...scores);return maxScore>=this.threshold;}return false;}/**
|
|
598
616
|
* Handle flagged content based on strategy
|
|
@@ -630,7 +648,7 @@ static DEFAULT_DETECTION_TYPES=["injection",// General prompt injection attempts
|
|
|
630
648
|
"role-manipulation"// Attempts to manipulate the AI's role or persona
|
|
631
649
|
];constructor(options){this.detectionTypes=options.detectionTypes||_PromptInjectionDetector.DEFAULT_DETECTION_TYPES;this.threshold=options.threshold??0.7;this.strategy=options.strategy||"block";this.includeScores=options.includeScores??false;this.detectionAgent=new Agent({name:"prompt-injection-detector",instructions:options.instructions||this.createDefaultInstructions(),model:options.model});}async processInput(args){try{const{messages,abort,tracingContext}=args;if(messages.length===0){return messages;}const processedMessages=[];for(const message of messages){const textContent=this.extractTextContent(message);if(!textContent.trim()){processedMessages.push(message);continue;}const detectionResult=await this.detectPromptInjection(textContent,tracingContext);if(this.isInjectionFlagged(detectionResult)){const processedMessage=this.handleDetectedInjection(message,detectionResult,this.strategy,abort);if(this.strategy==="filter"){continue;}else if(this.strategy==="rewrite"){if(processedMessage){processedMessages.push(processedMessage);}continue;}}processedMessages.push(message);}return processedMessages;}catch(error){if(error instanceof TripWire){throw error;}throw new Error(`Prompt injection detection failed: ${error instanceof Error?error.stack:"Unknown error"}`);}}/**
|
|
632
650
|
* Detect prompt injection using the internal agent
|
|
633
|
-
*/async detectPromptInjection(content,tracingContext){const prompt=this.createDetectionPrompt(content);try{const model=await this.detectionAgent.getModel();let response;const schema=
|
|
651
|
+
*/async detectPromptInjection(content,tracingContext){const prompt=this.createDetectionPrompt(content);try{const model=await this.detectionAgent.getModel();let response;const schema=z5.object({categories:z5.object(this.detectionTypes.reduce((props,type)=>{props[type]=z5.number().min(0).max(1).optional();return props;},{})).optional(),reason:z5.string().optional(),rewritten_content:z5.string().optional()});if(model.specificationVersion==="v2"){response=await this.detectionAgent.generateVNext(prompt,{output:schema,modelSettings:{temperature:0},tracingContext});}else {response=await this.detectionAgent.generate(prompt,{output:schema,temperature:0,tracingContext});}const result=response.object;return result;}catch(error){console.warn("[PromptInjectionDetector] Detection agent failed, allowing content:",error);return {};}}/**
|
|
634
652
|
* Determine if prompt injection is flagged based on category scores above threshold
|
|
635
653
|
*/isInjectionFlagged(result){if(result.categories){const maxScore=Math.max(...Object.values(result.categories).filter(score=>typeof score==="number"));return maxScore>=this.threshold;}return false;}/**
|
|
636
654
|
* Handle detected prompt injection based on strategy
|
|
@@ -671,7 +689,7 @@ static DEFAULT_DETECTION_TYPES=["email",// Email addresses
|
|
|
671
689
|
"iban"// International Bank Account Numbers
|
|
672
690
|
];constructor(options){this.detectionTypes=options.detectionTypes||_PIIDetector.DEFAULT_DETECTION_TYPES;this.threshold=options.threshold??0.6;this.strategy=options.strategy||"redact";this.redactionMethod=options.redactionMethod||"mask";this.includeDetections=options.includeDetections??false;this.preserveFormat=options.preserveFormat??true;this.detectionAgent=new Agent({name:"pii-detector",instructions:options.instructions||this.createDefaultInstructions(),model:options.model});}async processInput(args){try{const{messages,abort,tracingContext}=args;if(messages.length===0){return messages;}const processedMessages=[];for(const message of messages){const textContent=this.extractTextContent(message);if(!textContent.trim()){processedMessages.push(message);continue;}const detectionResult=await this.detectPII(textContent,tracingContext);if(this.isPIIFlagged(detectionResult)){const processedMessage=this.handleDetectedPII(message,detectionResult,this.strategy,abort);if(this.strategy==="filter"){continue;}else if(this.strategy==="redact"){if(processedMessage){processedMessages.push(processedMessage);}else {processedMessages.push(message);}continue;}}processedMessages.push(message);}return processedMessages;}catch(error){if(error instanceof TripWire){throw error;}throw new Error(`PII detection failed: ${error instanceof Error?error.stack:"Unknown error"}`);}}/**
|
|
673
691
|
* Detect PII using the internal agent
|
|
674
|
-
*/async detectPII(content,tracingContext){const prompt=this.createDetectionPrompt(content);const schema=
|
|
692
|
+
*/async detectPII(content,tracingContext){const prompt=this.createDetectionPrompt(content);const schema=z5.object({categories:z5.object(this.detectionTypes.reduce((props,type)=>{props[type]=z5.number().min(0).max(1).optional();return props;},{})).optional(),detections:z5.array(z5.object({type:z5.string(),value:z5.string(),confidence:z5.number().min(0).max(1),start:z5.number(),end:z5.number(),redacted_value:z5.string().optional()})).optional(),redacted_content:z5.string().optional()});try{const model=await this.detectionAgent.getModel();let response;if(model.specificationVersion==="v2"){response=await this.detectionAgent.generateVNext(prompt,{output:schema,modelSettings:{temperature:0},tracingContext});}else {response=await this.detectionAgent.generate(prompt,{output:schema,temperature:0,tracingContext});}const result=response.object;if(!result.redacted_content&&result.detections&&result.detections.length>0){result.redacted_content=this.applyRedactionMethod(content,result.detections);result.detections=result.detections.map(detection=>({...detection,redacted_value:detection.redacted_value||this.redactValue(detection.value,detection.type)}));}return result;}catch(error){console.warn("[PIIDetector] Detection agent failed, allowing content:",error);return {};}}/**
|
|
675
693
|
* Determine if PII is flagged based on detections or category scores above threshold
|
|
676
694
|
*/isPIIFlagged(result){if(result.detections&&result.detections.length>0){return true;}if(result.categories){const maxScore=Math.max(...Object.values(result.categories).filter(score=>typeof score==="number"));return maxScore>=this.threshold;}return false;}/**
|
|
677
695
|
* Handle detected PII based on strategy
|
|
@@ -713,7 +731,7 @@ var LanguageDetector=class _LanguageDetector{name="language-detector";detectionA
|
|
|
713
731
|
static DEFAULT_TARGET_LANGUAGES=["English","en"];// Common language codes and names mapping
|
|
714
732
|
static LANGUAGE_MAP={en:"English",es:"Spanish",fr:"French",de:"German",it:"Italian",pt:"Portuguese",ru:"Russian",ja:"Japanese",ko:"Korean",zh:"Chinese","zh-cn":"Chinese (Simplified)","zh-tw":"Chinese (Traditional)",ar:"Arabic",hi:"Hindi",th:"Thai",vi:"Vietnamese",tr:"Turkish",pl:"Polish",nl:"Dutch",sv:"Swedish",da:"Danish",no:"Norwegian",fi:"Finnish",el:"Greek",he:"Hebrew",cs:"Czech",hu:"Hungarian",ro:"Romanian",bg:"Bulgarian",hr:"Croatian",sk:"Slovak",sl:"Slovenian",et:"Estonian",lv:"Latvian",lt:"Lithuanian",uk:"Ukrainian",be:"Belarusian"};constructor(options){this.targetLanguages=options.targetLanguages||_LanguageDetector.DEFAULT_TARGET_LANGUAGES;this.threshold=options.threshold??0.7;this.strategy=options.strategy||"detect";this.preserveOriginal=options.preserveOriginal??true;this.minTextLength=options.minTextLength??10;this.includeDetectionDetails=options.includeDetectionDetails??false;this.translationQuality=options.translationQuality||"quality";this.detectionAgent=new Agent({name:"language-detector",instructions:options.instructions||this.createDefaultInstructions(),model:options.model});}async processInput(args){try{const{messages,abort}=args;if(messages.length===0){return messages;}const processedMessages=[];for(const message of messages){const textContent=this.extractTextContent(message);if(textContent.length<this.minTextLength){processedMessages.push(message);continue;}const detectionResult=await this.detectLanguage(textContent);if(detectionResult.confidence&&detectionResult.confidence<this.threshold){processedMessages.push(message);continue;}if(!this.isNonTargetLanguage(detectionResult)){const targetLanguageCode=this.getLanguageCode(this.targetLanguages[0]);const targetMessage=this.addLanguageMetadata(message,{iso_code:targetLanguageCode,confidence:0.95});if(this.includeDetectionDetails){console.info(`[LanguageDetector] Content in target language: Language detected: ${this.getLanguageName(targetLanguageCode)} (${targetLanguageCode}) with confidence 0.95`);}processedMessages.push(targetMessage);continue;}const processedMessage=await this.handleDetectedLanguage(message,detectionResult,this.strategy,abort);if(processedMessage){processedMessages.push(processedMessage);}else {continue;}}return processedMessages;}catch(error){if(error instanceof TripWire){throw error;}args.abort(`Language detection failed: ${error instanceof Error?error.message:"Unknown error"}`);}}/**
|
|
715
733
|
* Detect language using the internal agent
|
|
716
|
-
*/async detectLanguage(content){const prompt=this.createDetectionPrompt(content);try{const model=await this.detectionAgent.getModel();let response;const schema=
|
|
734
|
+
*/async detectLanguage(content){const prompt=this.createDetectionPrompt(content);try{const model=await this.detectionAgent.getModel();let response;const schema=z5.object({iso_code:z5.string().optional(),confidence:z5.number().min(0).max(1).optional(),translated_text:z5.string().optional()});if(model.specificationVersion==="v2"){response=await this.detectionAgent.generateVNext(prompt,{output:schema,modelSettings:{temperature:0}});}else {response=await this.detectionAgent.generate(prompt,{output:schema,temperature:0});}if(response.object.translated_text&&!response.object.confidence){response.object.confidence=0.95;}return response.object;}catch(error){console.warn("[LanguageDetector] Detection agent failed, assuming target language:",error);return {};}}/**
|
|
717
735
|
* Determine if language detection indicates non-target language
|
|
718
736
|
*/isNonTargetLanguage(result){if(result.iso_code&&result.confidence&&result.confidence>=this.threshold){return !this.isTargetLanguage(result.iso_code);}return false;}/**
|
|
719
737
|
* Get detected language name from ISO code
|
|
@@ -741,5 +759,5 @@ Target: ${this.targetLanguages.join("/")}${translate}`;}};// src/agent/input-pro
|
|
|
741
759
|
var LanguageDetectorInputProcessor=class{name="language-detector";processor;constructor(options){this.processor=new LanguageDetector(options);}async process(args){return this.processor.processInput(args);}};
|
|
742
760
|
|
|
743
761
|
export { AISDKV5OutputStream, Agent, DefaultExecutionEngine, ExecutionEngine, LanguageDetector, LanguageDetectorInputProcessor, LegacyStep, LegacyWorkflow, MastraModelOutput, ModerationInputProcessor, ModerationProcessor, PIIDetector, PIIDetectorInputProcessor, PromptInjectionDetector, PromptInjectionDetectorInputProcessor, RESOURCE_TYPES, Run, StructuredOutputProcessor, TripWire, UnicodeNormalizer, UnicodeNormalizerInputProcessor, WhenConditionReturnValue, Workflow, agentToStep, cloneStep, cloneWorkflow, createStep, createWorkflow, getActivePathsAndStatus, getResultActivePaths, getStepResult, getSuspendedPaths, isAgent, isConditionalKey, isErrorEvent, isFinalState, isLimboState, isTransitionEvent, isVariableReference, isWorkflow, loop, mapVariable, mergeChildValue, recursivelyCheckForFinalState, resolveVariables, updateStepInHierarchy, workflowToStep };
|
|
744
|
-
//# sourceMappingURL=chunk-
|
|
745
|
-
//# sourceMappingURL=chunk-
|
|
762
|
+
//# sourceMappingURL=chunk-UWUM3F3X.js.map
|
|
763
|
+
//# sourceMappingURL=chunk-UWUM3F3X.js.map
|