'use strict'; var chunkUC46OXET_cjs = require('./chunk-UC46OXET.cjs'); var chunkAWVVTLZF_cjs = require('./chunk-AWVVTLZF.cjs'); var chunkFHPG32XN_cjs = require('./chunk-FHPG32XN.cjs'); var chunkXB4FLS7A_cjs = require('./chunk-XB4FLS7A.cjs'); var chunkLP4WZA6D_cjs = require('./chunk-LP4WZA6D.cjs'); var chunkWSD4JNMB_cjs = require('./chunk-WSD4JNMB.cjs'); var chunk2TATDSHU_cjs = require('./chunk-2TATDSHU.cjs'); var chunkPWQW5NYR_cjs = require('./chunk-PWQW5NYR.cjs'); var chunkXSOONORA_cjs = require('./chunk-XSOONORA.cjs'); var crypto = require('crypto'); var web = require('stream/web'); var events = require('events'); var schemaCompat = require('@mastra/schema-compat'); // src/stream/aisdk/v5/compat/delayed-promise.ts var DelayedPromise = class { status = { type: "pending" }; _promise; _resolve = void 0; _reject = void 0; get promise() { if (this._promise) { return this._promise; } this._promise = new Promise((resolve, reject) => { if (this.status.type === "resolved") { resolve(this.status.value); } else if (this.status.type === "rejected") { reject(this.status.error); } this._resolve = resolve; this._reject = reject; }); return this._promise; } resolve(value) { this.status = { type: "resolved", value }; if (this._promise) { this._resolve?.(value); } } reject(error) { this.status = { type: "rejected", error }; if (this._promise) { this._reject?.(error); } } }; // src/stream/aisdk/v5/compat/consume-stream.ts async function consumeStream({ stream, onError, logger }) { const reader = stream.getReader(); try { while (true) { const { done } = await reader.read(); if (done) break; } } catch (error) { logger?.error("consumeStream error", error); onError?.(error); } finally { reader.releaseLock(); } } // src/stream/base/input.ts function safeEnqueue(controller, chunk) { try { controller.enqueue(chunk); return true; } catch { return false; } } function safeClose(controller) { try { controller.close(); return true; } catch { return false; } } function safeError(controller, error) { try { controller.error(error); return true; } catch { return false; } } var MastraModelInput = class extends chunkWSD4JNMB_cjs.MastraBase { initialize({ runId, createStream, onResult }) { const self = this; let outputStream; outputStream = new ReadableStream({ async start(controller) { try { const stream = await createStream(); chunkAWVVTLZF_cjs.attachModelStreamTransport(outputStream, chunkAWVVTLZF_cjs.readModelStreamTransport(stream)); const initialChunks = onResult({ warnings: stream.warnings, request: stream.request, rawResponse: stream.rawResponse || stream.response || {} }); if (initialChunks) { for (const chunk of Array.isArray(initialChunks) ? initialChunks : [initialChunks]) { controller.enqueue(chunk); } } await self.transform({ runId, stream: stream.stream, controller }); safeClose(controller); } catch (error) { safeError(controller, error); } } }); return outputStream; } }; function asJsonSchema(schema) { if (!schema) { return void 0; } if (chunkXB4FLS7A_cjs.isStandardSchemaWithJSON(schema)) { const jsonSchema = chunkXB4FLS7A_cjs.standardSchemaToJSONSchema(schema, { io: "input", target: "draft-07" }); return jsonSchema; } return schema; } function getTransformedSchema(schema, options) { if (!schema) { return void 0; } const jsonSchema = options?.model ? schemaCompat.applyCompatLayer({ schema, compatLayers: [new schemaCompat.AnthropicSchemaCompatLayer(options.model)], mode: "jsonSchema" }) : asJsonSchema(schema); if (!jsonSchema) { return void 0; } const { $schema, ...itemSchema } = jsonSchema; if (itemSchema.type === "array") { const innerElement = itemSchema.items; const arrayOutputSchema = { $schema, type: "object", properties: { elements: { type: "array", items: innerElement } }, required: ["elements"], additionalProperties: false }; return { jsonSchema: arrayOutputSchema, outputFormat: "array" }; } if (itemSchema.enum && Array.isArray(itemSchema.enum)) { const enumOutputSchema = { $schema, type: "object", properties: { result: { type: itemSchema.type || "string", enum: itemSchema.enum } }, required: ["result"], additionalProperties: false }; return { jsonSchema: enumOutputSchema, outputFormat: "enum" }; } return { jsonSchema, outputFormat: jsonSchema.type // 'object' }; } function getResponseFormat(schema, options) { if (schema) { const transformedSchema = getTransformedSchema(schema, options); return { type: "json", schema: transformedSchema?.jsonSchema }; } return { type: "text" }; } // src/stream/base/output-format-handlers.ts function escapeUnescapedControlCharsInJsonStrings(text) { let result = ""; let inString = false; let i = 0; while (i < text.length) { const char = text[i]; if (char === "\\" && i + 1 < text.length) { result += char + text[i + 1]; i += 2; continue; } if (char === '"') { inString = !inString; result += char; i++; continue; } if (inString) { if (char === "\n") { result += "\\n"; i++; continue; } if (char === "\r") { result += "\\r"; i++; continue; } if (char === " ") { result += "\\t"; i++; continue; } } result += char; i++; } return result; } var BaseFormatHandler = class { /** * The original user-provided schema (Zod, JSON Schema, or AI SDK Schema). */ schema; /** * Validate partial chunks as they are streamed. @planned */ validatePartialChunks = false; partialSchema; constructor(schema, options = {}) { this.schema = schema; if (options.validatePartialChunks && this.isZodSchema(schema) && "partial" in schema && typeof schema.partial === "function") { this.partialSchema = schema.partial(); this.validatePartialChunks = true; } } /** * Checks if the original schema is a Zod schema with safeParse method. */ isZodSchema(schema) { return schemaCompat.isZodType(schema); } /** * Validates a value against the schema using StandardSchemaWithJSON's validate method. */ async validateValue(value) { if (!this.schema) { return { success: true, value }; } if (this.isZodSchema(this.schema)) { try { const ssResult = await this.schema["~standard"].validate(value); if (!ssResult.issues) { return { success: true, value: ssResult.value }; } const errorMessages = ssResult.issues.map((e) => `- ${e.path?.join(".") || "root"}: ${e.message}`).join("\n"); const zodResult = this.schema.safeParse(value); const zodError = !zodResult.success ? zodResult.error : void 0; return { success: false, error: new chunkXSOONORA_cjs.MastraError( { domain: chunkXSOONORA_cjs.ErrorDomain.AGENT, category: chunkXSOONORA_cjs.ErrorCategory.SYSTEM, id: "STRUCTURED_OUTPUT_SCHEMA_VALIDATION_FAILED", text: `Structured output validation failed: ${errorMessages}`, details: { value: typeof value === "object" ? JSON.stringify(value) : String(value) } }, zodError ) }; } catch (error) { return { success: false, error: error instanceof Error ? error : new Error("Zod validation failed", { cause: error }) }; } } try { const ssResult = await this.schema["~standard"].validate(value); if (!ssResult.issues) { return { success: true, value: ssResult.value }; } const errorMessages = ssResult.issues.map((e) => `- ${e.path?.join(".") || "root"}: ${e.message}`).join("\n"); return { success: false, error: new chunkXSOONORA_cjs.MastraError({ domain: chunkXSOONORA_cjs.ErrorDomain.AGENT, category: chunkXSOONORA_cjs.ErrorCategory.SYSTEM, id: "STRUCTURED_OUTPUT_SCHEMA_VALIDATION_FAILED", text: `Structured output validation failed: ${errorMessages}`, details: { value: typeof value === "object" ? JSON.stringify(value) : String(value) } }) }; } catch (error) { return { success: false, error: error instanceof Error ? error : new Error("Validation failed", { cause: error }) }; } } /** * Preprocesses accumulated text to handle LLMs that wrap JSON in code blocks * and fix common JSON formatting issues like unescaped newlines in strings. * Extracts content from the first complete valid ```json...``` code block or removes opening ```json prefix if no complete code block is found (streaming chunks). * @param accumulatedText - Raw accumulated text from streaming * @returns Processed text ready for JSON parsing */ preprocessText(accumulatedText) { let processedText = accumulatedText; if (processedText.includes("<|message|>")) { const match = processedText.match(/<\|message\|>([\s\S]+)$/); if (match && match[1]) { processedText = match[1]; } } const trimmedStart = processedText.trimStart(); if (/^```json\b/.test(trimmedStart)) { const match = trimmedStart.match(/^```json\s*\n?([\s\S]*?)\n?\s*```\s*$/); if (match && match[1]) { processedText = match[1].trim(); } else { processedText = trimmedStart.replace(/^```json\s*\n?/, ""); } } processedText = escapeUnescapedControlCharsInJsonStrings(processedText); return processedText; } }; var ObjectFormatHandler = class extends BaseFormatHandler { type = "object"; async processPartialChunk({ accumulatedText, previousObject }) { const processedAccumulatedText = this.preprocessText(accumulatedText); const { value: currentObjectJson, state } = await chunkPWQW5NYR_cjs.parsePartialJson(processedAccumulatedText); if (this.validatePartialChunks && this.partialSchema) { const result = this.partialSchema?.safeParse(currentObjectJson); if (result.success && result.data && result.data !== void 0 && !chunkPWQW5NYR_cjs.isDeepEqualData(previousObject, result.data)) { return { shouldEmit: true, emitValue: result.data, newPreviousResult: result.data }; } return { shouldEmit: false }; } if (currentObjectJson !== void 0 && currentObjectJson !== null && typeof currentObjectJson === "object" && !chunkPWQW5NYR_cjs.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 chunkPWQW5NYR_cjs.parsePartialJson(rawValue); return this.validateValue(value); } }; 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 chunkPWQW5NYR_cjs.parsePartialJson(processedAccumulatedText); if (currentObjectJson !== void 0 && !chunkPWQW5NYR_cjs.isDeepEqualData(previousObject, currentObjectJson)) { const rawElements = currentObjectJson && typeof currentObjectJson === "object" && "elements" in currentObjectJson && Array.isArray(currentObjectJson.elements) ? 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 (!chunkPWQW5NYR_cjs.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.") }; } return this.validateValue(resultValue); } }; var EnumFormatHandler = class extends BaseFormatHandler { type = "enum"; /** Previously emitted enum result to avoid duplicate emissions */ textPreviousEnumResult; /** * Finds the best matching enum value for a partial result string. * If multiple values match, returns the partial string. If only one matches, returns that value. * @param partialResult - Partial enum string from streaming * @returns Best matching enum value or undefined if no matches */ findBestEnumMatch(partialResult) { if (!this.schema) { return void 0; } const outputJsonSchema = chunkXB4FLS7A_cjs.standardSchemaToJSONSchema(this.schema); const enumValues = outputJsonSchema?.enum; if (!enumValues) { return void 0; } 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 chunkPWQW5NYR_cjs.parsePartialJson(processedAccumulatedText); if (currentObjectJson !== void 0 && currentObjectJson !== null && typeof currentObjectJson === "object" && !Array.isArray(currentObjectJson) && "result" in currentObjectJson && typeof currentObjectJson.result === "string" && !chunkPWQW5NYR_cjs.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 chunkPWQW5NYR_cjs.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") }; } return this.validateValue(finalValue.result); } }; function createOutputHandler({ schema }) { const normalizedSchema = schema ? chunkXB4FLS7A_cjs.toStandardSchema(schema) : void 0; const transformedSchema = getTransformedSchema(normalizedSchema); switch (transformedSchema?.outputFormat) { case "array": return new ArrayFormatHandler(normalizedSchema); case "enum": return new EnumFormatHandler(normalizedSchema); case "object": default: return new ObjectFormatHandler(normalizedSchema); } } function createObjectStreamTransformer({ structuredOutput, logger }) { const handler = createOutputHandler({ schema: structuredOutput?.schema }); let accumulatedText = ""; let previousObject = void 0; let currentRunId; let finalResult; return new web.TransformStream({ async transform(chunk, controller) { if (chunk.runId) { currentRunId = chunk.runId; } 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; const chunkData = { from: chunk.from, runId: chunk.runId, type: "object", object: result.emitValue // TODO: handle partial runtime type validation of json chunks }; controller.enqueue(chunkData); } } if (chunk.type === "text-end") { controller.enqueue(chunk); if (accumulatedText?.trim() && !finalResult) { finalResult = await handler.validateAndTransformFinal(accumulatedText); if (finalResult.success) { controller.enqueue({ from: "AGENT" /* AGENT */, runId: currentRunId ?? "", type: "object-result", object: finalResult.value }); } } return; } controller.enqueue(chunk); }, async flush(controller) { if (finalResult && !finalResult.success) { handleValidationError(finalResult.error, controller); } if (accumulatedText?.trim() && !finalResult) { finalResult = await handler.validateAndTransformFinal(accumulatedText); if (finalResult.success) { controller.enqueue({ from: "AGENT" /* AGENT */, runId: currentRunId ?? "", type: "object-result", object: finalResult.value }); } else { handleValidationError(finalResult.error, controller); } } } }); function handleValidationError(error, controller) { if (structuredOutput?.errorStrategy === "warn") { logger?.warn(error.message); } else if (structuredOutput?.errorStrategy === "fallback") { controller.enqueue({ from: "AGENT" /* AGENT */, runId: currentRunId ?? "", type: "object-result", object: structuredOutput.fallbackValue }); } else { controller.enqueue({ from: "AGENT" /* AGENT */, runId: currentRunId ?? "", type: "error", payload: { error } }); } } } function createJsonTextStreamTransformer(schema) { let previousArrayLength = 0; let hasStartedArray = false; let chunkCount = 0; const outputSchema = getTransformedSchema(schema); return new web.TransformStream({ transform(chunk, controller) { if (chunk.type !== "object" || !chunk.object) { return; } if (outputSchema?.outputFormat === "array" && Array.isArray(chunk.object)) { 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 var STRUCTURED_OUTPUT_PROCESSOR_NAME = "structured-output"; function createDestructurableOutput(output) { return new Proxy(output, { get(target, prop, _receiver) { const originalValue = Reflect.get(target, prop, target); if (typeof originalValue === "function") { return originalValue.bind(target); } return originalValue; } }); } var MastraModelOutput = class extends chunkWSD4JNMB_cjs.MastraBase { #status = "running"; #error; #baseStream; #bufferedChunks = []; #streamFinished = false; #finishCallbackSent = false; #emitter = new events.EventEmitter(); #bufferedSteps = []; #bufferedReasoningDetails = {}; #bufferedByStep = { text: "", reasoning: [], sources: [], files: [], toolCalls: [], toolResults: [], dynamicToolCalls: [], dynamicToolResults: [], staticToolCalls: [], staticToolResults: [], content: [], usage: { inputTokens: void 0, outputTokens: void 0, totalTokens: void 0 }, warnings: [], request: {}, response: { id: "", timestamp: /* @__PURE__ */ new Date(), modelId: "", messages: [], uiMessages: [] }, reasoningText: "", providerMetadata: void 0, finishReason: void 0 }; #bufferedText = []; #bufferedObject; #bufferedTextChunks = {}; #bufferedSources = []; #bufferedReasoning = []; #bufferedFiles = []; #toolCallArgsDeltas = {}; #toolCallDeltaIdNameMap = {}; #toolCallStreamingMeta = {}; #toolCalls = []; #toolResults = []; #warnings = []; #finishReason = void 0; #request = {}; #usageCount = { inputTokens: void 0, outputTokens: void 0, totalTokens: void 0 }; #tripwire = void 0; #transportRef; #transportClosed = false; #delayedPromises = { suspendPayload: new DelayedPromise(), resumeSchema: new DelayedPromise(), object: new DelayedPromise(), finishReason: new DelayedPromise(), usage: new DelayedPromise(), warnings: new DelayedPromise(), providerMetadata: new DelayedPromise(), response: new DelayedPromise(), request: new DelayedPromise(), text: new DelayedPromise(), reasoning: new DelayedPromise(), reasoningText: new DelayedPromise(), sources: new DelayedPromise(), files: new DelayedPromise(), toolCalls: new DelayedPromise(), toolResults: new DelayedPromise(), steps: new DelayedPromise(), totalUsage: new DelayedPromise(), content: new DelayedPromise() }; #consumptionStarted = false; #returnScorerData = false; #structuredOutputMode = void 0; #model; /** * Unique identifier for this execution run. */ runId; #options; /** * The processor runner for this stream. */ processorRunner; /** * The message list for this stream. */ messageList; /** * Trace ID for this execution. */ traceId; /** * Root span ID for this execution, identifying the top-level span in the trace. */ spanId; messageId; constructor({ model: _model, stream, messageList, options, messageId, initialState }) { super({ component: "LLM", name: "MastraModelOutput" }); this.#options = options; this.#transportRef = options.transportRef; this.#returnScorerData = !!options.returnScorerData; this.runId = options.runId; const resultSpan = chunkLP4WZA6D_cjs.getRootExportSpan(options.tracingContext?.currentSpan); this.traceId = resultSpan?.externalTraceId; this.spanId = resultSpan?.id; this.#model = _model; this.messageId = messageId; if (options.structuredOutput?.schema) { this.#structuredOutputMode = options.structuredOutput.model ? "processor" : "direct"; } if (options.outputProcessors?.length) { this.processorRunner = new ProcessorRunner({ inputProcessors: [], outputProcessors: options.outputProcessors, logger: this.logger, agentName: "MastraModelOutput", processorStates: options.processorStates }); } this.messageList = messageList; const self = this; let processedStream = stream; const processorRunner = this.processorRunner; if (processorRunner && options.isLLMExecutionStep) { const processorStates = options.processorStates || /* @__PURE__ */ new Map(); processedStream = stream.pipeThrough( new web.TransformStream({ async transform(chunk, controller) { if (chunk.type === "finish" && chunk.payload?.stepResult?.reason === "tool-calls") { controller.enqueue(chunk); return; } else { if (!processorStates.has(STRUCTURED_OUTPUT_PROCESSOR_NAME)) { const processorIndex = processorRunner.outputProcessors.findIndex( (p) => p.id === STRUCTURED_OUTPUT_PROCESSOR_NAME ); if (processorIndex !== -1) { const structuredOutputProcessor = processorRunner.outputProcessors[processorIndex]; const structuredOutputProcessorState = new ProcessorState({ processorName: structuredOutputProcessor?.name ?? STRUCTURED_OUTPUT_PROCESSOR_NAME, tracingContext: options.tracingContext, processorIndex, createSpan: true }); structuredOutputProcessorState.customState = { controller }; processorStates.set(STRUCTURED_OUTPUT_PROCESSOR_NAME, structuredOutputProcessorState); } } else { const structuredOutputProcessorState = processorStates.get(STRUCTURED_OUTPUT_PROCESSOR_NAME); if (structuredOutputProcessorState) { structuredOutputProcessorState.customState.controller = controller; } } const streamWriter = { custom: async (data) => controller.enqueue(data) }; const { part: processed, blocked, reason, tripwireOptions, processorId } = await processorRunner.processPart( chunk, processorStates, chunkFHPG32XN_cjs.resolveObservabilityContext(options), options.requestContext, self.messageList, 0, streamWriter ); const enqueueTripwire = (r, opts, pid) => { controller.enqueue({ type: "tripwire", payload: { reason: r || "Output processor blocked content", retry: opts?.retry, metadata: opts?.metadata, processorId: pid } }); }; if (blocked) { enqueueTripwire(reason, tripwireOptions, processorId); return; } if (processed) { controller.enqueue(processed); } const reprocessed = await processorRunner.drainReprocessParts( processorStates, chunkFHPG32XN_cjs.resolveObservabilityContext(options), options.requestContext, self.messageList, 0, streamWriter ); for (const r of reprocessed) { if (r.blocked) { enqueueTripwire(r.reason, r.tripwireOptions, r.processorId); return; } if (r.part != null) { controller.enqueue(r.part); } } } } }) ); } if (self.#structuredOutputMode === "direct" && self.#options.isLLMExecutionStep) { processedStream = processedStream.pipeThrough( createObjectStreamTransformer({ structuredOutput: self.#options.structuredOutput, logger: self.logger }) ); } this.#baseStream = processedStream.pipeThrough( new web.TransformStream({ transform: async (chunk, controller) => { switch (chunk.type) { case "tool-call-suspended": case "tool-call-approval": self.#status = "suspended"; self.#delayedPromises.suspendPayload.resolve(chunk.payload); self.#delayedPromises.resumeSchema.resolve(chunk.payload.resumeSchema); if (!self.#finishCallbackSent) { self.#finishCallbackSent = true; await options?.onFinish?.(self.#createSuspendedOnFinishPayload(chunk)); } break; case "abort": self.#status = "canceled"; if (!self.#finishCallbackSent) { self.#finishCallbackSent = true; await options?.onFinish?.(self.#createAbortedOnFinishPayload()); } self.#closeTransportIfNeeded(); break; case "raw": if (!self.#options.includeRawChunks) { return; } break; case "object-result": self.#bufferedObject = chunk.object; if (self.#delayedPromises.object.status.type === "pending") { self.#delayedPromises.object.resolve(chunk.object); } break; 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; self.#toolCallStreamingMeta[chunk.payload.toolCallId] = { toolName: chunk.payload.toolName, providerExecuted: chunk.payload.providerExecuted, providerMetadata: chunk.payload.providerMetadata, dynamic: chunk.payload.dynamic, ...chunk.payload.observability ? { observability: chunk.payload.observability } : {} }; break; case "tool-call-input-streaming-end": { const toolCallId = chunk.payload.toolCallId; const meta = self.#toolCallStreamingMeta[toolCallId]; const deltaParts = self.#toolCallArgsDeltas[toolCallId]; let args = {}; if (deltaParts?.length) { try { const merged = deltaParts.join(""); args = typeof merged === "string" && merged.length > 0 ? JSON.parse(merged) : {}; } catch { args = {}; } } delete self.#toolCallStreamingMeta[toolCallId]; delete self.#toolCallArgsDeltas[toolCallId]; delete self.#toolCallDeltaIdNameMap[toolCallId]; if (meta) { const synthetic = { type: "tool-call", runId: chunk.runId, from: chunk.from, payload: { toolCallId, toolName: meta.toolName, args, providerExecuted: meta.providerExecuted, providerMetadata: meta.providerMetadata, dynamic: meta.dynamic, ...meta.observability ? { observability: meta.observability } : {} } }; self.#toolCalls.push(synthetic); self.#bufferedByStep.toolCalls.push(synthetic); self.#emitChunk(chunk); controller.enqueue(chunk); self.#emitChunk(synthetic); controller.enqueue(synthetic); return; } 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", runId: chunk.runId, from: chunk.from, payload: { id: chunk.payload.id, providerMetadata: chunk.payload.providerMetadata, text: "" } }; break; case "reasoning-delta": { self.#bufferedReasoning.push({ type: "reasoning", runId: chunk.runId, from: chunk.from, payload: chunk.payload }); self.#bufferedByStep.reasoning.push({ type: "reasoning", runId: chunk.runId, from: chunk.from, payload: chunk.payload }); const bufferedReasoning = self.#bufferedReasoningDetails[chunk.payload.id]; if (bufferedReasoning) { bufferedReasoning.payload.text += chunk.payload.text; if (chunk.payload.providerMetadata) { bufferedReasoning.payload.providerMetadata = chunk.payload.providerMetadata; } } break; } case "reasoning-end": { const bufferedReasoning = self.#bufferedReasoningDetails[chunk.payload.id]; if (chunk.payload.providerMetadata && bufferedReasoning) { bufferedReasoning.payload.providerMetadata = chunk.payload.providerMetadata; } break; } case "tool-call": { const existingSynthetic = self.#toolCalls.find((tc) => tc.payload.toolCallId === chunk.payload.toolCallId); if (existingSynthetic) { if (chunk.payload.args && Object.keys(existingSynthetic.payload.args || {}).length === 0) { existingSynthetic.payload.args = chunk.payload.args; } if (chunk.payload.providerMetadata && !existingSynthetic.payload.providerMetadata) { existingSynthetic.payload.providerMetadata = chunk.payload.providerMetadata; } if (chunk.payload.dynamic != null && existingSynthetic.payload.dynamic == null) { existingSynthetic.payload.dynamic = chunk.payload.dynamic; } if (chunk.payload.observability && !existingSynthetic.payload.observability) { existingSynthetic.payload.observability = chunk.payload.observability; } return; } self.#toolCalls.push(chunk); self.#bufferedByStep.toolCalls.push(chunk); const toolCallPayload = chunk.payload; if (toolCallPayload?.output?.from === "AGENT" && toolCallPayload?.output?.type === "finish") { const finishPayload = toolCallPayload.output.payload; if (finishPayload?.usage) { 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 { providerMetadata, request, ...otherMetadata } = chunk.payload.metadata; const payloadSteps = chunk.payload.output?.steps || []; const currentPayloadStep = payloadSteps[payloadSteps.length - 1]; const stepTripwire = currentPayloadStep?.tripwire; const stepText = stepTripwire ? "" : self.#bufferedByStep.text; const stepResult = { stepType: self.#bufferedSteps.length === 0 ? "initial" : "tool-result", sources: self.#bufferedByStep.sources, files: self.#bufferedByStep.files, toolCalls: self.#bufferedByStep.toolCalls, toolResults: self.#bufferedByStep.toolResults, content: messageList.get.response.aiV5.modelContent(-1), text: stepText, // Include tripwire data if present tripwire: stepTripwire, reasoningText: self.#bufferedReasoning.map((reasoningPart) => reasoningPart.payload.text).join(""), reasoning: Object.values(self.#bufferedReasoningDetails), get staticToolCalls() { return self.#bufferedByStep.toolCalls.filter( (part) => part.type === "tool-call" && part.payload?.dynamic === false ); }, get dynamicToolCalls() { return self.#bufferedByStep.toolCalls.filter( (part) => part.type === "tool-call" && part.payload?.dynamic === true ); }, get staticToolResults() { return self.#bufferedByStep.toolResults.filter( (part) => part.type === "tool-result" && part.payload?.dynamic === false ); }, get dynamicToolResults() { return self.#bufferedByStep.toolResults.filter( (part) => part.type === "tool-result" && part.payload?.dynamic === true ); }, finishReason: chunk.payload.stepResult.reason, usage: chunk.payload.output.usage, warnings: self.#warnings, request: request || {}, response: { id: chunk.payload.id || "", timestamp: chunk.payload.metadata?.timestamp || /* @__PURE__ */ new Date(), ...otherMetadata, modelId: chunk.payload.metadata?.modelId || chunk.payload.metadata?.model || "", messages: chunk.payload.messages?.nonUser || [], dbMessages: self.messageList.get.response.db(), // We have to cast this until messageList can take generics also and type metadata, it was too // complicated to do this in this PR, it will require a much bigger change. uiMessages: messageList.get.response.aiV5.ui() }, providerMetadata: providerMetadata ?? chunk.payload.providerMetadata }; 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: [], dynamicToolCalls: [], dynamicToolResults: [], staticToolCalls: [], staticToolResults: [], content: [], usage: { inputTokens: void 0, outputTokens: void 0, totalTokens: void 0 }, warnings: [], request: {}, response: { id: "", timestamp: /* @__PURE__ */ new Date(), modelId: "", messages: [], uiMessages: [] }, reasoningText: "", providerMetadata: void 0, finishReason: void 0 }; break; } case "tripwire": self.#tripwire = { reason: chunk.payload?.reason || "Content blocked", retry: chunk.payload?.retry, metadata: chunk.payload?.metadata, processorId: chunk.payload?.processorId }; self.#finishReason = "other"; self.#streamFinished = true; self.resolvePromises({ text: self.#bufferedText.join(""), finishReason: "other", object: void 0, usage: self.#usageCount, warnings: self.#warnings, providerMetadata: void 0, response: { dbMessages: self.messageList.get.response.db() }, request: {}, reasoning: [], reasoningText: void 0, sources: [], files: [], toolCalls: [], toolResults: [], steps: self.#bufferedSteps, totalUsage: self.#usageCount, content: [], suspendPayload: void 0, // Tripwire doesn't suspend, so resolve to undefined resumeSchema: void 0 }); self.#closeTransportIfNeeded(); self.#emitChunk(chunk); controller.enqueue(chunk); self.#emitter.emit("finish"); controller.terminate(); return; case "finish": self.#status = "success"; if (chunk.payload.stepResult.reason) { self.#finishReason = chunk.payload.stepResult.reason; } const finalProviderMetadata = chunk.payload.metadata?.providerMetadata ?? chunk.payload.providerMetadata; if (chunk.payload.stepResult.reason === "tripwire") { const outputSteps = chunk.payload.output?.steps; const lastStep = outputSteps?.[outputSteps?.length - 1]; const stepTripwire = lastStep?.tripwire; self.#tripwire = { reason: stepTripwire?.reason || "Processor tripwire triggered", retry: stepTripwire?.retry, metadata: stepTripwire?.metadata, processorId: stepTripwire?.processorId }; } if (self.#bufferedObject !== void 0) { const responseMessages = messageList.get.response.db(); const lastAssistantMessage = [...responseMessages].reverse().find((m) => m.role === "assistant"); if (lastAssistantMessage) { if (!lastAssistantMessage.content.metadata) { lastAssistantMessage.content.metadata = {}; } lastAssistantMessage.content.metadata.structuredOutput = self.#bufferedObject; } } 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 = { inputTokens: self.#usageCount.inputTokens ?? 0, outputTokens: self.#usageCount.outputTokens ?? 0, totalTokens: self.#usageCount.totalTokens ?? 0, ...self.#usageCount.reasoningTokens !== void 0 && { reasoningTokens: self.#usageCount.reasoningTokens }, ...self.#usageCount.cachedInputTokens !== void 0 && { cachedInputTokens: self.#usageCount.cachedInputTokens }, ...self.#usageCount.cacheCreationInputTokens !== void 0 && { cacheCreationInputTokens: self.#usageCount.cacheCreationInputTokens }, ...self.#usageCount.raw !== void 0 && { raw: self.#usageCount.raw } }; try { if (self.processorRunner && !self.#options.isLLMExecutionStep) { const lastStep = self.#bufferedSteps[self.#bufferedSteps.length - 1]; const originalText = lastStep?.text || ""; const outputResultWriter = { custom: async (data) => { self.#emitChunk(data); controller.enqueue(data); } }; const outputResult = { text: self.#bufferedText.join(""), usage: chunk.payload.output.usage, finishReason: self.#finishReason || "unknown", steps: [...self.#bufferedSteps] }; self.messageList = await self.processorRunner.runOutputProcessors( self.messageList, chunkFHPG32XN_cjs.resolveObservabilityContext(options), self.#options.requestContext, 0, outputResultWriter, outputResult ); const responseMessages = self.messageList.get.response.aiV4.core(); const lastResponseMessage = responseMessages[responseMessages.length - 1]; const outputText = lastResponseMessage ? chunk2TATDSHU_cjs.coreContentToString(lastResponseMessage.content) : ""; if (lastStep && outputText && outputText !== originalText) { lastStep.text = outputText; } this.resolvePromises({ text: outputText || originalText, finishReason: 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() }; } chunk.payload.response = response; } else if (!self.#options.isLLMExecutionStep) { this.resolvePromises({ text: self.#bufferedText.join(""), finishReason: self.#finishReason }); } } catch (error2) { if (error2 instanceof TripWire) { self.#tripwire = { reason: error2.message, retry: error2.options?.retry, metadata: error2.options?.metadata, processorId: error2.processorId }; self.resolvePromises({ finishReason: "other", text: "" }); } else { self.#error = chunkXSOONORA_cjs.getErrorFromUnknown(error2, { fallbackMessage: "Unknown error in stream" }); self.resolvePromises({ finishReason: "error", text: "" }); } if (self.#delayedPromises.object.status.type !== "resolved") { self.#delayedPromises.object.resolve(void 0); } } const reasoningText = self.#bufferedReasoning.length > 0 ? self.#bufferedReasoning.map((reasoningPart) => reasoningPart.payload.text).join("") : void 0; const baseFinishStep = self.#bufferedSteps[self.#bufferedSteps.length - 1]; if (baseFinishStep && baseFinishStep.providerMetadata === void 0 && finalProviderMetadata !== void 0) { baseFinishStep.providerMetadata = finalProviderMetadata; } this.resolvePromises({ usage: self.#usageCount, warnings: self.#warnings, providerMetadata: finalProviderMetadata, response: { ...response, dbMessages: self.messageList.get.response.db() }, request: self.#request || {}, reasoningText, reasoning: Object.values(self.#bufferedReasoningDetails || {}), sources: self.#bufferedSources, files: self.#bufferedFiles, toolCalls: self.#toolCalls, toolResults: self.#toolResults, steps: self.#bufferedSteps, totalUsage: self.#getTotalUsage(), content: messageList.get.response.aiV5.stepContent(), suspendPayload: void 0, resumeSchema: void 0 }); if (baseFinishStep) { const onFinishPayload = { // StepResult properties from baseFinishStep providerMetadata: baseFinishStep.providerMetadata ?? finalProviderMetadata, text: self.#bufferedText.join(""), warnings: baseFinishStep.warnings ?? [], finishReason: chunk.payload.stepResult.reason, content: messageList.get.response.aiV5.stepContent(), request: await self.request, error: self.error, reasoning: await self.reasoning, reasoningText: await self.reasoningText, sources: await self.sources, files: await self.files, steps: self.#bufferedSteps, response: { ...await self.response, ...baseFinishStep.response, messages: messageList.get.response.aiV5.model(), dbMessages: self.messageList.get.response.db() }, usage: chunk.payload.output.usage, totalUsage: self.#getTotalUsage(), toolCalls: await self.toolCalls, toolResults: await self.toolResults, staticToolCalls: (await self.toolCalls).filter((toolCall) => toolCall?.payload?.dynamic === false), staticToolResults: (await self.toolResults).filter( (toolResult) => toolResult?.payload?.dynamic === false ), dynamicToolCalls: (await self.toolCalls).filter((toolCall) => toolCall?.payload?.dynamic === true), dynamicToolResults: (await self.toolResults).filter( (toolResult) => toolResult?.payload?.dynamic === true ), // Custom properties (not part of standard callback) ...self.#model.modelId && self.#model.provider && self.#model.version ? { model: self.#model } : {}, object: self.#delayedPromises.object.status.type === "rejected" ? void 0 : self.#delayedPromises.object.status.type === "resolved" ? self.#delayedPromises.object.status.value : self.#structuredOutputMode === "direct" && baseFinishStep.text ? (() => { try { return JSON.parse(baseFinishStep.text); } catch { return void 0; } })() : void 0 }; if (!self.#finishCallbackSent) { self.#finishCallbackSent = true; await options?.onFinish?.(onFinishPayload); } } self.#closeTransportIfNeeded(); break; case "error": const error = chunkXSOONORA_cjs.getErrorFromUnknown(chunk.payload.error, { fallbackMessage: "Unknown error chunk in stream" }); self.#error = error; self.#status = "failed"; self.#streamFinished = true; Object.values(self.#delayedPromises).forEach((promise) => { if (promise.status.type === "pending") { promise.reject(self.#error); } }); self.#closeTransportIfNeeded(); break; } self.#emitChunk(chunk); controller.enqueue(chunk); }, flush: () => { if (self.#delayedPromises.object.status.type === "pending") { self.#delayedPromises.object.resolve(void 0); } if (self.#status === "suspended") { const reasoningText = self.#bufferedReasoning.length > 0 ? self.#bufferedReasoning.map((reasoningPart) => reasoningPart.payload.text).join("") : void 0; self.resolvePromises({ toolResults: self.#toolResults, toolCalls: self.#toolCalls, text: self.#bufferedText.join(""), reasoning: Object.values(self.#bufferedReasoningDetails || {}), reasoningText, sources: self.#bufferedSources, files: self.#bufferedFiles, steps: self.#bufferedSteps, usage: self.#usageCount, totalUsage: self.#getTotalUsage(), warnings: self.#warnings, finishReason: "suspended", content: self.messageList.get.response.aiV5.stepContent(), object: void 0, request: self.#request, response: { dbMessages: self.messageList.get.response.db() }, providerMetadata: void 0 }); } Object.entries(self.#delayedPromises).forEach(([key, promise]) => { if (promise.status.type === "pending") { promise.reject(new Error(`promise '${key}' was not resolved or rejected when stream finished`)); } }); self.#closeTransportIfNeeded(); self.#streamFinished = true; self.#emitter.emit("finish"); } }) ); if (initialState) { this.deserializeState(initialState); } } resolvePromise(key, value) { if (!(key in this.#delayedPromises)) { throw new chunkXSOONORA_cjs.MastraError({ id: "MASTRA_MODEL_OUTPUT_INVALID_PROMISE_KEY", domain: chunkXSOONORA_cjs.ErrorDomain.LLM, category: chunkXSOONORA_cjs.ErrorCategory.SYSTEM, text: `Attempted to resolve invalid promise key '${key}' with value '${typeof value === "object" ? JSON.stringify(value, null, 2) : value}'` }); } this.#delayedPromises[key].resolve(value); } resolvePromises(data) { for (const keyString in data) { const key = keyString; this.resolvePromise(key, data[key]); } } #closeTransportIfNeeded() { const transport = this.#transportRef?.current; if (!transport || !transport.closeOnFinish || this.#transportClosed) { return; } this.#transportClosed = true; try { transport.close(); } catch { } } #getDelayedPromise(promise) { if (!this.#consumptionStarted) { void this.consumeStream(); } return promise.promise; } /** * Resolves to the complete text response after streaming completes. */ get text() { return this.#getDelayedPromise(this.#delayedPromises.text); } /** * Resolves to reasoning parts array for models that support reasoning. */ get reasoning() { return this.#getDelayedPromise(this.#delayedPromises.reasoning); } /** * Resolves to complete reasoning text for models that support reasoning. */ get reasoningText() { return this.#getDelayedPromise(this.#delayedPromises.reasoningText); } get sources() { return this.#getDelayedPromise(this.#delayedPromises.sources); } get files() { return this.#getDelayedPromise(this.#delayedPromises.files); } get steps() { return this.#getDelayedPromise(this.#delayedPromises.steps); } get suspendPayload() { return this.#getDelayedPromise(this.#delayedPromises.suspendPayload); } get resumeSchema() { return this.#getDelayedPromise(this.#delayedPromises.resumeSchema); } /** * Stream of all chunks. Provides complete control over stream processing. */ get fullStream() { return this.#createEventedStream(); } /** * Resolves to the reason generation finished. */ get finishReason() { return this.#getDelayedPromise(this.#delayedPromises.finishReason); } /** * Resolves to array of all tool calls made during execution. */ get toolCalls() { return this.#getDelayedPromise(this.#delayedPromises.toolCalls); } /** * Resolves to array of all tool execution results. */ get toolResults() { return this.#getDelayedPromise(this.#delayedPromises.toolResults); } /** * Resolves to token usage statistics including inputTokens, outputTokens, and totalTokens. */ get usage() { return this.#getDelayedPromise(this.#delayedPromises.usage); } /** * Resolves to array of all warnings generated during execution. */ get warnings() { return this.#getDelayedPromise(this.#delayedPromises.warnings); } /** * Resolves to provider metadata generated during execution. */ get providerMetadata() { return this.#getDelayedPromise(this.#delayedPromises.providerMetadata); } /** * Resolves to the complete response from the model. */ get response() { return this.#getDelayedPromise(this.#delayedPromises.response); } /** * Resolves to the complete request sent to the model. */ get request() { return this.#getDelayedPromise(this.#delayedPromises.request); } /** * Transport handle for the current stream (when available). */ get transport() { return this.#transportRef?.current; } /** * Resolves to an error if an error occurred during streaming. */ get error() { return this.#error; } updateUsageCount(usage) { if (!usage) { return; } if (usage.inputTokens !== void 0) { this.#usageCount.inputTokens = (this.#usageCount.inputTokens ?? 0) + usage.inputTokens; } if (usage.outputTokens !== void 0) { this.#usageCount.outputTokens = (this.#usageCount.outputTokens ?? 0) + usage.outputTokens; } if (usage.totalTokens !== void 0) { this.#usageCount.totalTokens = (this.#usageCount.totalTokens ?? 0) + usage.totalTokens; } if (usage.reasoningTokens !== void 0) { this.#usageCount.reasoningTokens = (this.#usageCount.reasoningTokens ?? 0) + usage.reasoningTokens; } if (usage.cachedInputTokens !== void 0) { this.#usageCount.cachedInputTokens = (this.#usageCount.cachedInputTokens ?? 0) + usage.cachedInputTokens; } if (usage.cacheCreationInputTokens !== void 0) { this.#usageCount.cacheCreationInputTokens = (this.#usageCount.cacheCreationInputTokens ?? 0) + usage.cacheCreationInputTokens; } if (usage.raw !== void 0) { this.#usageCount.raw = usage.raw; } } populateUsageCount(usage) { if (!usage) { return; } if (usage.inputTokens !== void 0 && this.#usageCount.inputTokens === void 0) { this.#usageCount.inputTokens = usage.inputTokens; } if (usage.outputTokens !== void 0 && this.#usageCount.outputTokens === void 0) { this.#usageCount.outputTokens = usage.outputTokens; } if (usage.totalTokens !== void 0 && this.#usageCount.totalTokens === void 0) { this.#usageCount.totalTokens = usage.totalTokens; } if (usage.reasoningTokens !== void 0 && this.#usageCount.reasoningTokens === void 0) { this.#usageCount.reasoningTokens = usage.reasoningTokens; } if (usage.cachedInputTokens !== void 0 && this.#usageCount.cachedInputTokens === void 0) { this.#usageCount.cachedInputTokens = usage.cachedInputTokens; } if (usage.cacheCreationInputTokens !== void 0 && this.#usageCount.cacheCreationInputTokens === void 0) { this.#usageCount.cacheCreationInputTokens = usage.cacheCreationInputTokens; } if (usage.raw !== void 0 && this.#usageCount.raw === void 0) { this.#usageCount.raw = usage.raw; } } async consumeStream(options) { if (this.#consumptionStarted) { return; } this.#consumptionStarted = true; try { await consumeStream({ stream: this.#baseStream, onError: options?.onError, logger: this.logger }); } catch (error) { options?.onError?.(error); } } /** * Returns complete output including text, usage, tool calls, and all metadata. */ async getFullOutput() { await this.consumeStream({ onError: (error) => { this.logger.error("Error consuming stream", error); throw error; } }); let scoringData; if (this.#returnScorerData) { scoringData = { input: { inputMessages: this.messageList.getPersisted.input.db(), rememberedMessages: this.messageList.getPersisted.remembered.db(), systemMessages: this.messageList.getSystemMessages(), taggedSystemMessages: this.messageList.getPersisted.taggedSystemMessages }, output: this.messageList.getPersisted.response.db() }; } const steps = await this.steps; const textFromSteps = steps.map((step) => step.text || "").join(""); const fullOutput = { text: textFromSteps, usage: await this.usage, steps, finishReason: await this.finishReason, warnings: await this.warnings, providerMetadata: await this.providerMetadata, request: await this.request, reasoning: await this.reasoning, reasoningText: await this.reasoningText, toolCalls: await this.toolCalls, toolResults: await this.toolResults, sources: await this.sources, files: await this.files, response: await this.response, totalUsage: await this.totalUsage, object: await this.object, error: this.error, tripwire: this.#tripwire, ...scoringData ? { scoringData } : {}, traceId: this.traceId, spanId: this.spanId, runId: this.runId, suspendPayload: await this.suspendPayload, resumeSchema: await this.resumeSchema, // All messages from this execution (input + memory history + response) messages: this.messageList.get.all.db(), // Only messages loaded from memory (conversation history) rememberedMessages: this.messageList.get.remembered.db() }; return fullOutput; } /** * Tripwire data if the stream was aborted due to an output processor blocking the content. * Returns undefined if no tripwire was triggered. */ get tripwire() { return this.#tripwire; } /** * The total usage of the stream. */ get totalUsage() { return this.#getDelayedPromise(this.#delayedPromises.totalUsage); } get content() { return this.#getDelayedPromise(this.#delayedPromises.content); } /** * Stream of valid JSON chunks. The final JSON result is validated against the output schema when the stream ends. * * @example * ```typescript * const stream = await agent.stream("Extract data", { * structuredOutput: { * schema: z.object({ name: z.string(), age: z.number() }), * model: 'gpt-4o-mini' // optional to use a model for structuring json output * } * }); * // partial json chunks * for await (const data of stream.objectStream) { * console.log(data); // { name: 'John' }, { name: 'John', age: 30 } * } * ``` */ get objectStream() { return this.#createEventedStream().pipeThrough( new web.TransformStream({ transform(chunk, controller) { if (chunk.type === "object") { controller.enqueue(chunk.object); } } }) ); } /** * Stream of individual array elements when output schema is an array type. */ get elementStream() { let publishedElements = 0; return this.#createEventedStream().pipeThrough( new web.TransformStream({ transform(chunk, controller) { if (chunk.type === "object") { if (Array.isArray(chunk.object)) { for (; publishedElements < chunk.object.length; publishedElements++) { controller.enqueue(chunk.object[publishedElements]); } } } } }) ); } /** * Stream of only text content, filtering out metadata and other chunk types. */ get textStream() { if (this.#structuredOutputMode === "direct") { const outputSchema = getTransformedSchema(this.#options.structuredOutput?.schema); if (outputSchema?.outputFormat === "array") { return this.#createEventedStream().pipeThrough( createJsonTextStreamTransformer(this.#options.structuredOutput?.schema) ); } } return this.#createEventedStream().pipeThrough( new web.TransformStream({ transform(chunk, controller) { if (chunk.type === "text-delta") { controller.enqueue(chunk.payload.text); } } }) ); } /** * Resolves to the complete object response from the model. Validated against the 'output' schema when the stream ends. * * @example * ```typescript * const stream = await agent.stream("Extract data", { * structuredOutput: { * schema: z.object({ name: z.string(), age: z.number() }), * model: 'gpt-4o-mini' // optionally use a model for structuring json output * } * }); * // final validated json * const data = await stream.object // { name: 'John', age: 30 } * ``` */ get object() { if (!this.processorRunner && !this.#options.structuredOutput?.schema && this.#delayedPromises.object.status.type === "pending") { this.#delayedPromises.object.resolve(void 0); } return this.#getDelayedPromise(this.#delayedPromises.object); } // Internal methods for immediate values - used internally by Mastra (llm-execution.ts bailing on errors/abort signals with current state) // These are not part of the public API /** @internal */ _getImmediateToolCalls() { return this.#toolCalls; } /** @internal */ _getImmediateToolResults() { return this.#toolResults; } /** @internal */ _getImmediateText() { return this.#bufferedText.join(""); } /** @internal */ _getImmediateObject() { return this.#bufferedObject; } /** @internal */ _getImmediateUsage() { return this.#usageCount; } /** @internal */ _getImmediateWarnings() { return this.#warnings; } /** @internal */ _getImmediateFinishReason() { return this.#finishReason; } /** @internal */ _getBaseStream() { return this.#baseStream; } /** @internal */ _waitUntilFinished() { if (this.#streamFinished) { return Promise.resolve(); } return new Promise((resolve) => { this.#emitter.once("finish", resolve); }); } #getTotalUsage() { let total = this.#usageCount.totalTokens; if (total === void 0) { const input = this.#usageCount.inputTokens ?? 0; const output = this.#usageCount.outputTokens ?? 0; const reasoning = this.#usageCount.reasoningTokens ?? 0; total = input + output + reasoning; } return { inputTokens: this.#usageCount.inputTokens, outputTokens: this.#usageCount.outputTokens, totalTokens: total, reasoningTokens: this.#usageCount.reasoningTokens, cachedInputTokens: this.#usageCount.cachedInputTokens, cacheCreationInputTokens: this.#usageCount.cacheCreationInputTokens, ...this.#usageCount.raw !== void 0 && { raw: this.#usageCount.raw } }; } #createAbortedOnFinishPayload() { return { finishReason: "aborted", text: "", reasoning: [], reasoningText: void 0, sources: [], files: [], toolCalls: [], toolResults: [], staticToolCalls: [], staticToolResults: [], dynamicToolCalls: [], dynamicToolResults: [], content: [], usage: { inputTokens: void 0, outputTokens: void 0, totalTokens: void 0 }, warnings: [], providerMetadata: void 0, request: {}, response: {}, steps: [], totalUsage: { inputTokens: void 0, outputTokens: void 0, totalTokens: void 0 }, object: void 0 }; } #createSuspendedOnFinishPayload(chunk) { return { finishReason: "suspended", suspendReason: chunk.type, toolName: chunk.payload.toolName, toolCallId: chunk.payload.toolCallId, // Empty defaults for the LLMStepResult/MastraOnFinishCallback shape. text: "", reasoning: [], reasoningText: void 0, sources: [], files: [], toolCalls: [], toolResults: [], staticToolCalls: [], staticToolResults: [], dynamicToolCalls: [], dynamicToolResults: [], content: [], usage: { inputTokens: void 0, outputTokens: void 0, totalTokens: void 0 }, warnings: [], providerMetadata: void 0, request: {}, response: {}, steps: [], totalUsage: { inputTokens: void 0, outputTokens: void 0, totalTokens: void 0 }, object: void 0 }; } #emitChunk(chunk) { this.#bufferedChunks.push(chunk); this.#emitter.emit("chunk", chunk); } #createEventedStream() { const self = this; return new web.ReadableStream({ start(controller) { self.#bufferedChunks.forEach((chunk) => { controller.enqueue(chunk); }); if (self.#streamFinished) { controller.close(); return; } const chunkHandler = (chunk) => { safeEnqueue(controller, chunk); }; const finishHandler = () => { self.#emitter.off("chunk", chunkHandler); self.#emitter.off("finish", finishHandler); safeClose(controller); }; self.#emitter.on("chunk", chunkHandler); self.#emitter.on("finish", finishHandler); }, pull(_controller) { if (!self.#consumptionStarted) { void self.consumeStream(); } }, cancel() { self.#emitter.removeAllListeners(); } }); } get status() { return this.#status; } serializeState() { return { status: this.#status, bufferedSteps: this.#bufferedSteps, bufferedReasoningDetails: this.#bufferedReasoningDetails, bufferedByStep: this.#bufferedByStep, bufferedText: this.#bufferedText, bufferedTextChunks: this.#bufferedTextChunks, bufferedSources: this.#bufferedSources, bufferedReasoning: this.#bufferedReasoning, bufferedFiles: this.#bufferedFiles, toolCallArgsDeltas: this.#toolCallArgsDeltas, toolCallDeltaIdNameMap: this.#toolCallDeltaIdNameMap, toolCallStreamingMeta: this.#toolCallStreamingMeta, toolCalls: this.#toolCalls, toolResults: this.#toolResults, warnings: this.#warnings, finishReason: this.#finishReason, request: this.#request, usageCount: this.#usageCount, tripwire: this.#tripwire, messageList: this.messageList.serialize() }; } deserializeState(state) { this.#status = state.status; this.#bufferedSteps = state.bufferedSteps; this.#bufferedReasoningDetails = state.bufferedReasoningDetails; this.#bufferedByStep = state.bufferedByStep; this.#bufferedText = state.bufferedText; this.#bufferedTextChunks = state.bufferedTextChunks; this.#bufferedSources = state.bufferedSources; this.#bufferedReasoning = state.bufferedReasoning; this.#bufferedFiles = state.bufferedFiles; this.#toolCallArgsDeltas = state.toolCallArgsDeltas; this.#toolCallDeltaIdNameMap = state.toolCallDeltaIdNameMap; this.#toolCallStreamingMeta = state.toolCallStreamingMeta ?? {}; this.#toolCalls = state.toolCalls; this.#toolResults = state.toolResults; this.#warnings = state.warnings; this.#finishReason = state.finishReason; this.#request = state.request; this.#usageCount = state.usageCount; this.#tripwire = state.tripwire; this.messageList = this.messageList.deserialize(state.messageList); } }; // src/agent/trip-wire.ts var TripWire = class extends Error { options; processorId; constructor(reason, options = {}, processorId) { super(reason); this.options = options; this.processorId = processorId; Object.setPrototypeOf(this, new.target.prototype); } }; var getModelOutputForTripwire = async ({ tripwire, runId, options, model, messageList, ...rest }) => { const observabilityContext = chunkFHPG32XN_cjs.resolveObservabilityContext(rest); const tripwireStream = new web.ReadableStream({ start(controller) { controller.enqueue({ type: "tripwire", runId, from: "AGENT" /* AGENT */, payload: { reason: tripwire.reason || "", retry: tripwire.retry, metadata: tripwire.metadata, processorId: tripwire.processorId } }); controller.close(); } }); const modelOutput = new MastraModelOutput({ model: { modelId: model.modelId, provider: model.provider, version: model.specificationVersion }, stream: tripwireStream, messageList, options: { runId, structuredOutput: options.structuredOutput, ...observabilityContext, onFinish: options.onFinish, // Fix these types after the types PR is merged onStepFinish: options.onStepFinish, returnScorerData: options.returnScorerData, requestContext: options.requestContext }, messageId: crypto.randomUUID() }); return modelOutput; }; // src/agent/utils.ts var supportedLanguageModelSpecifications = ["v2", "v3"]; var isSupportedLanguageModel = (model) => { return supportedLanguageModelSpecifications.includes(model.specificationVersion); }; async function tryGenerateWithJsonFallback(agent, prompt, options) { if (!options.structuredOutput?.schema) { throw new chunkXSOONORA_cjs.MastraError({ id: "STRUCTURED_OUTPUT_OPTIONS_REQUIRED", domain: chunkXSOONORA_cjs.ErrorDomain.AGENT, category: chunkXSOONORA_cjs.ErrorCategory.USER, text: "structuredOutput is required to use tryGenerateWithJsonFallback" }); } try { const result = await agent.generate(prompt, options); if (result.object === void 0) { throw new chunkXSOONORA_cjs.MastraError({ id: "STRUCTURED_OUTPUT_OBJECT_UNDEFINED", domain: chunkXSOONORA_cjs.ErrorDomain.AGENT, category: chunkXSOONORA_cjs.ErrorCategory.USER, text: "structuredOutput object is undefined" }); } return result; } catch (error) { console.warn("Error in tryGenerateWithJsonFallback. Attempting fallback.", error); return await agent.generate(prompt, { ...options, structuredOutput: { ...options.structuredOutput, jsonPromptInjection: true } }); } } async function tryStreamWithJsonFallback(agent, prompt, options) { if (!options.structuredOutput?.schema) { throw new chunkXSOONORA_cjs.MastraError({ id: "STRUCTURED_OUTPUT_OPTIONS_REQUIRED", domain: chunkXSOONORA_cjs.ErrorDomain.AGENT, category: chunkXSOONORA_cjs.ErrorCategory.USER, text: "structuredOutput is required to use tryStreamWithJsonFallback" }); } const { onStream, ...streamOptions } = options; try { const result = await agent.stream(prompt, streamOptions); void onStream?.(result); const object = await result.object; if (!object) { throw new chunkXSOONORA_cjs.MastraError({ id: "STRUCTURED_OUTPUT_OBJECT_UNDEFINED", domain: chunkXSOONORA_cjs.ErrorDomain.AGENT, category: chunkXSOONORA_cjs.ErrorCategory.USER, text: "structuredOutput object is undefined" }); } return result; } catch (error) { console.warn("Error in tryStreamWithJsonFallback. Attempting fallback.", error); const result = await agent.stream(prompt, { ...streamOptions, structuredOutput: { ...streamOptions.structuredOutput, jsonPromptInjection: true } }); void onStream?.(result); return result; } } function resolveThreadIdFromArgs(args) { let resolved; if (args?.memory?.thread) { if (typeof args.memory.thread === "string") { resolved = { id: args.memory.thread }; } else if (typeof args.memory.thread === "object" && args.memory.thread.id) { resolved = args.memory.thread; } } if (!resolved && args?.threadId) { resolved = { id: args.threadId }; } if (args.overrideId) { return { ...resolved || {}, id: args.overrideId }; } return resolved; } // src/processors/is-processor-workflow.ts function isProcessorWorkflow(obj) { return obj !== null && typeof obj === "object" && "id" in obj && typeof obj.id === "string" && "inputSchema" in obj && "outputSchema" in obj && "execute" in obj && typeof obj.execute === "function" && !("processInput" in obj) && !("processInputStep" in obj) && !("processOutputStream" in obj) && !("processOutputResult" in obj) && !("processOutputStep" in obj) && !("processLLMRequest" in obj) && !("processAPIError" in obj); } // src/processors/send-signal.ts function createProcessorSendSignal(args) { return async (signalInput) => { const signal = chunk2TATDSHU_cjs.createSignal(signalInput); args.messageList.markResponseMessageBoundary(); args.rotateResponseMessageId?.(); const signalForTranscript = args.messageList.addSignal(signal); await args.writer?.custom(signalForTranscript.toDataPart()); return signalForTranscript; }; } // src/processors/span-payload.ts function isPlainObject(value) { if (value === null || typeof value !== "object" || Array.isArray(value)) { return false; } const prototype = Object.getPrototypeOf(value); return prototype === Object.prototype || prototype === null; } function readString(value) { return typeof value === "string" ? value : void 0; } function summarizeProcessorToolEntry(key, value) { if (!isPlainObject(value)) { return { id: key, name: key }; } const id = readString(value.id) ?? key; const name = readString(value.name) ?? id; const description = readString(value.description); return { id, name, ...description !== void 0 ? { description } : {} }; } function summarizeProcessorModelForSpan(value) { if (!isPlainObject(value)) { return void 0; } const modelId = readString(value.modelId) ?? readString(value.id); const provider = readString(value.provider); const specificationVersion = readString(value.specificationVersion); if (modelId === void 0 && provider === void 0 && specificationVersion === void 0) { return void 0; } return { ...modelId !== void 0 ? { modelId } : {}, ...provider !== void 0 ? { provider } : {}, ...specificationVersion !== void 0 ? { specificationVersion } : {} }; } function summarizeProcessorToolsForSpan(tools) { if (!isPlainObject(tools)) { return void 0; } return Object.entries(tools).map(([key, value]) => summarizeProcessorToolEntry(key, value)); } function summarizeProcessorToolRegistry(tools) { if (!isPlainObject(tools)) { return void 0; } const summaries = summarizeProcessorToolsForSpan(tools); if (!summaries) { return void 0; } return Object.keys(tools).map((registryKey, index) => ({ registryKey, summary: summaries[index] })); } function resolveToolInRegistry(toolRegistry, toolKey) { return toolRegistry.find( (candidate) => candidate.summary.id === toolKey || candidate.summary.name === toolKey || candidate.registryKey === toolKey ); } function summarizeActiveToolsForSpan(activeTools, tools) { if (!Array.isArray(activeTools)) { return void 0; } const toolRegistry = summarizeProcessorToolRegistry(tools) ?? []; const summaries = activeTools.map((tool) => { const toolKey = readString(tool); if (toolKey === void 0) { return void 0; } const match = resolveToolInRegistry(toolRegistry, toolKey); return { id: match?.summary.id ?? toolKey, name: match?.summary.name ?? toolKey }; }).filter((tool) => tool !== void 0); return summaries; } function summarizeToolChoiceForSpan(toolChoice, tools) { if (typeof toolChoice === "string") { return { type: toolChoice }; } if (!isPlainObject(toolChoice)) { return void 0; } const type = readString(toolChoice.type); if (type === void 0) { return void 0; } if (type !== "tool") { return { type }; } const toolKey = readString(toolChoice.toolName) ?? readString(toolChoice.toolId); if (toolKey === void 0) { return { type }; } const toolRegistry = summarizeProcessorToolRegistry(tools) ?? []; const match = resolveToolInRegistry(toolRegistry, toolKey); const fallbackToolId = readString(toolChoice.toolId) ?? toolKey; const fallbackToolName = readString(toolChoice.toolName) ?? toolKey; return { type, tool: match ? { id: match.summary.id, name: match.summary.name } : { id: fallbackToolId, name: fallbackToolName } }; } function summarizeProcessorResultForSpan(value) { if (!isPlainObject(value)) { return void 0; } const projected = {}; for (const key of [ "text", "object", "finishReason", "toolCalls", "toolResults", "warnings", "files", "sources", "reasoning", "reasoningText", "tripwire" ]) { if (value[key] !== void 0) { projected[key] = value[key]; } } if (Array.isArray(value.steps)) { projected.stepCount = value.steps.length; } return Object.keys(projected).length > 0 ? projected : void 0; } // src/processors/stream-reprocess.ts var REPROCESS_PART_KEY = "__mastraReprocessPart"; var CLAUDE_46_PATTERN = /[^0-9]4[.-]6/; function isMaybeClaude46(model) { if (typeof model === "function") return true; if (Array.isArray(model)) { return model.some((m) => isMaybeClaude46(m.model ?? m)); } if (typeof model === "string") { return model.startsWith("anthropic") && CLAUDE_46_PATTERN.test(model); } if (model && typeof model === "object" && "provider" in model && "modelId" in model) { const { provider, modelId } = model; return provider.startsWith("anthropic") && CLAUDE_46_PATTERN.test(modelId); } return true; } var TrailingAssistantGuard = class { id = "trailing-assistant-guard"; name = "Trailing Assistant Guard"; processInputStep({ messages, structuredOutput }) { const willUseResponseFormat = structuredOutput?.schema && !structuredOutput?.model && !structuredOutput?.jsonPromptInjection; if (!willUseResponseFormat) return; const lastMessage = messages[messages.length - 1]; if (!lastMessage || lastMessage.role !== "assistant") return; return { messages: [ ...messages, { id: crypto.randomUUID(), role: "user", content: { format: 2, parts: [{ type: "text", text: "Generate the structured response." }] }, createdAt: /* @__PURE__ */ new Date() } ] }; } }; // src/processors/runner.ts async function invokeOnViolation(processor, error) { if (!processor.onViolation) return; try { const violation = { processorId: error.processorId ?? processor.id, message: error.message, detail: error.options?.metadata }; await processor.onViolation(violation); } catch { } } var ProcessorState = class { inputAccumulatedText = ""; outputAccumulatedText = ""; outputChunkCount = 0; customState = {}; streamParts = []; span; constructor(options) { if (!options?.createSpan || !options.processorName) { return; } const currentSpan = options.tracingContext?.currentSpan; const parentSpan = currentSpan?.findParent("agent_run" /* AGENT_RUN */) || currentSpan?.parent || currentSpan; this.span = parentSpan?.createChildSpan({ type: "processor_run" /* PROCESSOR_RUN */, name: `output stream processor: ${options.processorName}`, entityType: chunkLP4WZA6D_cjs.EntityType.OUTPUT_PROCESSOR, entityName: options.processorName, attributes: { processorExecutor: "legacy", processorIndex: options.processorIndex ?? 0 }, input: { totalChunks: 0 } }); } /** Track incoming chunk (before processor transformation) */ addInputPart(part) { if (part.type === "text-delta") { this.inputAccumulatedText += part.payload.text; } this.streamParts.push(part); if (this.span) { this.span.input = { totalChunks: this.streamParts.length, accumulatedText: this.inputAccumulatedText }; } } /** Track outgoing chunk (after processor transformation) */ addOutputPart(part) { if (!part) return; this.outputChunkCount++; if (part.type === "text-delta") { this.outputAccumulatedText += part.payload.text; } } /** Get final output for span */ getFinalOutput() { return { totalChunks: this.outputChunkCount, accumulatedText: this.outputAccumulatedText }; } }; function areProcessorMessageArraysEqual(before, after) { if (before === after) { return true; } if (!before || !after) { return before === after; } return before.length === after.length && before.every((message, index) => chunk2TATDSHU_cjs.messagesAreEqual(message, after[index])); } function buildProcessInputStepSpanInput(args) { const summarizedModel = summarizeProcessorModelForSpan(args.model); const summarizedTools = summarizeProcessorToolsForSpan(args.tools); const summarizedToolChoice = summarizeToolChoiceForSpan(args.toolChoice, args.tools); const summarizedActiveTools = summarizeActiveToolsForSpan(args.activeTools, args.tools); return { messages: args.messages, systemMessages: args.systemMessages, stepNumber: args.stepNumber, ...args.messageId ? { messageId: args.messageId } : {}, retryCount: args.retryCount, ...summarizedModel ? { model: summarizedModel } : {}, ...summarizedTools ? { tools: summarizedTools } : {}, ...summarizedToolChoice ? { toolChoice: summarizedToolChoice } : {}, ...summarizedActiveTools ? { activeTools: summarizedActiveTools } : {} }; } function buildProcessInputStepSpanOutput(args) { const output = {}; if (!areProcessorMessageArraysEqual(args.beforeMessages, args.messages)) { output.messages = args.messages; } if (!areProcessorMessageArraysEqual(args.beforeSystemMessages, args.systemMessages)) { output.systemMessages = args.systemMessages; } if (args.afterStepInput.messageId !== args.beforeStepInput.messageId) { output.messageId = args.afterStepInput.messageId; } if (args.result.model !== void 0 || args.afterStepInput.model !== args.beforeStepInput.model) { const model = summarizeProcessorModelForSpan(args.afterStepInput.model); if (model) { output.model = model; } } if (args.result.tools !== void 0 || args.afterStepInput.tools !== args.beforeStepInput.tools) { const tools = summarizeProcessorToolsForSpan(args.afterStepInput.tools); if (tools) { output.tools = tools; } } if (args.result.toolChoice !== void 0 || args.afterStepInput.toolChoice !== args.beforeStepInput.toolChoice || args.afterStepInput.tools !== args.beforeStepInput.tools) { const toolChoice = summarizeToolChoiceForSpan(args.afterStepInput.toolChoice, args.afterStepInput.tools); if (toolChoice) { output.toolChoice = toolChoice; } } if (args.result.activeTools !== void 0 || args.afterStepInput.activeTools !== args.beforeStepInput.activeTools || args.afterStepInput.tools !== args.beforeStepInput.tools) { const activeTools = summarizeActiveToolsForSpan(args.afterStepInput.activeTools, args.afterStepInput.tools); if (activeTools) { output.activeTools = activeTools; } } if (args.result.retryCount !== void 0) { output.retryCount = args.result.retryCount; } return output; } var ProcessorRunner = class _ProcessorRunner { inputProcessors; outputProcessors; errorProcessors; logger; agentName; /** * Shared processor state that persists across loop iterations. * Used by all processor methods (input and output) to share state. * Keyed by processor ID. */ processorStates; constructor({ inputProcessors, outputProcessors, errorProcessors, logger, agentName, processorStates }) { this.inputProcessors = inputProcessors ?? []; this.outputProcessors = outputProcessors ?? []; this.errorProcessors = errorProcessors ?? []; this.logger = logger; this.agentName = agentName; this.processorStates = processorStates ?? /* @__PURE__ */ new Map(); } /** * Get or create ProcessorState for the given processor ID. * This state persists across loop iterations and is shared between * all processor methods (input and output). */ getProcessorState(processorId) { let state = this.processorStates.get(processorId); if (!state) { state = new ProcessorState(); this.processorStates.set(processorId, state); } return state; } async runComputeStateSignal({ processor, messageList, stepNumber, steps, requestContext, writer, abort, processorState, memory, resourceId, threadId, abortSignal, retryCount, rotateResponseMessageId }) { const computeStateSignal = processor.computeStateSignal?.bind(processor); if (!computeStateSignal) return; const memoryContext = chunkUC46OXET_cjs.parseMemoryRequestContext(requestContext); const resolvedMemory = memory; const resolvedThreadId = threadId ?? memoryContext?.thread?.id; const resolvedResourceId = resourceId ?? memoryContext?.resourceId; if (!resolvedMemory || !resolvedThreadId || !resolvedResourceId) { throw new Error( `[Processor:${processor.id}] computeStateSignal requires Mastra memory with an active resourceId and threadId` ); } const loadedThread = await resolvedMemory.getThreadById({ threadId: resolvedThreadId }) ?? memoryContext?.thread; if (!loadedThread) { throw new Error(`[Processor:${processor.id}] computeStateSignal could not load thread ${resolvedThreadId}`); } let thread = { ...loadedThread, id: resolvedThreadId, resourceId: loadedThread.resourceId ?? resolvedResourceId, createdAt: loadedThread.createdAt ?? /* @__PURE__ */ new Date(), updatedAt: loadedThread.updatedAt ?? /* @__PURE__ */ new Date(), metadata: loadedThread.metadata }; const stateId = processor.stateId ?? processor.id; const beforeAddStateSignal = rotateResponseMessageId ? () => { messageList.markResponseMessageBoundary(); rotateResponseMessageId(); } : void 0; const trackingById = chunkUC46OXET_cjs.getStateSignalsMetadata(thread.metadata); const tracking = trackingById[stateId]; const { activeStateSignals, contextWindow, lastSnapshot, deltasSinceSnapshot } = await chunkUC46OXET_cjs.resolveStateSignalHistory({ messageList, memory: resolvedMemory, threadId: resolvedThreadId, stateId, tracking }); const result = await computeStateSignal({ messages: messageList.get.all.db(), messageList, stepNumber, steps, state: processorState.customState, requestContext, writer, abortSignal, abort, retryCount, resourceId: resolvedResourceId, threadId: resolvedThreadId, activeStateSignals, contextWindow, lastSnapshot, deltasSinceSnapshot, tracking, sendStateSignal: async (stateSignal) => { const sendResult = await chunkUC46OXET_cjs.applyStateSignal({ input: stateSignal, memory: resolvedMemory, thread, resourceId: resolvedResourceId, threadId: resolvedThreadId, memoryConfig: memoryContext?.memoryConfig, messageList, defaultId: stateId, beforeAddSignal: beforeAddStateSignal, writeSignal: (signal) => writer?.custom(signal.toDataPart()) }); if (!sendResult.skipped) { const updated = await resolvedMemory.getThreadById({ threadId: resolvedThreadId }); if (updated) thread = { ...thread, metadata: updated.metadata }; } return sendResult.skipped ? sendResult : sendResult.signal; } }); if (!result) return; await chunkUC46OXET_cjs.applyStateSignal({ input: result, memory: resolvedMemory, thread, resourceId: resolvedResourceId, threadId: resolvedThreadId, memoryConfig: memoryContext?.memoryConfig, messageList, defaultId: stateId, beforeAddSignal: beforeAddStateSignal, writeSignal: (signal) => writer?.custom(signal.toDataPart()) }); } async runWorkflowComputeStateSignals({ workflow, messageList, stepNumber, steps, requestContext, writer, memory, resourceId, threadId, abortSignal, retryCount, rotateResponseMessageId }) { for (const processor of workflow.__stateSignalProcessors ?? []) { const abort = (reason, options) => { throw new TripWire(reason || `Tripwire triggered by ${processor.id}`, options, processor.id); }; await this.runComputeStateSignal({ processor, messageList, stepNumber, steps, requestContext, writer, abort, processorState: this.getProcessorState(processor.id), memory, resourceId, threadId, abortSignal, retryCount, rotateResponseMessageId }); } } /** * Execute a workflow as a processor and handle the result. * Returns the processed messages and any tripwire information. */ async executeWorkflowAsProcessor(workflow, input, observabilityContext, requestContext, writer, abortSignal) { const run = await workflow.createRun(); const result = await run.start({ // Cast to allow processorStates/abortSignal - passed through to workflow processor steps // but not part of the official ProcessorStepOutput schema inputData: { ...input, // Pass the processorStates map so workflow processor steps can access their state processorStates: this.processorStates, // Pass abortSignal so processors can cancel in-flight work abortSignal }, ...observabilityContext, requestContext, outputWriter: writer ? (chunk) => writer.custom(chunk) : void 0 }); if (result.status === "tripwire") { const tripwireData = result.tripwire; throw new TripWire( tripwireData?.reason || `Tripwire triggered in workflow ${workflow.id}`, { retry: tripwireData?.retry, metadata: tripwireData?.metadata }, tripwireData?.processorId || workflow.id ); } if (result.status !== "success") { const details = []; if (result.status === "failed") { if (result.error) { details.push(result.error.message || JSON.stringify(result.error)); } for (const [stepId, step] of Object.entries(result.steps)) { if (step.status === "failed" && step.error?.message) { details.push(`step ${stepId}: ${step.error.message}`); } } } const detailStr = details.length > 0 ? ` \u2014 ${details.join("; ")}` : ""; throw new chunkXSOONORA_cjs.MastraError({ category: "USER", domain: "AGENT", id: "PROCESSOR_WORKFLOW_FAILED", text: `Processor workflow ${workflow.id} failed with status: ${result.status}${detailStr}` }); } const output = result.result; if (!output || typeof output !== "object") { return input; } if (!("phase" in output) || !("messages" in output || "part" in output || "messageList" in output)) { throw new chunkXSOONORA_cjs.MastraError({ category: "USER", domain: "AGENT", id: "PROCESSOR_WORKFLOW_INVALID_OUTPUT", text: `Processor workflow ${workflow.id} returned invalid output format. Expected ProcessorStepOutput.` }); } return output; } async runOutputProcessors(messageList, observabilityContext, requestContext, retryCount = 0, writer, result) { for (const [index, processorOrWorkflow] of this.outputProcessors.entries()) { const allNewMessages = messageList.get.response.db(); let processableMessages = [...allNewMessages]; const idsBeforeProcessing = processableMessages.map((m) => m.id); const check = messageList.makeMessageSourceChecker(); if (isProcessorWorkflow(processorOrWorkflow)) { await this.executeWorkflowAsProcessor( processorOrWorkflow, { phase: "outputResult", messages: processableMessages, messageList, retryCount, result }, observabilityContext, requestContext, writer ); continue; } const processor = processorOrWorkflow; const abort = (reason, options) => { throw new TripWire(reason || `Tripwire triggered by ${processor.id}`, options, processor.id); }; const processMethod = processor.processOutputResult?.bind(processor); if (!processMethod) { continue; } const outputMessagesBefore = processableMessages; const outputSystemMessagesBefore = messageList.getAllSystemMessages(); const defaultResult = { text: "", usage: { inputTokens: 0, outputTokens: 0, totalTokens: 0 }, finishReason: "unknown", steps: [] }; const summarizedResult = result ? summarizeProcessorResultForSpan(result) : void 0; const currentSpan = observabilityContext?.tracingContext?.currentSpan; const parentSpan = currentSpan?.findParent("agent_run" /* AGENT_RUN */) || currentSpan?.parent || currentSpan; const processorSpan = parentSpan?.createChildSpan({ type: "processor_run" /* PROCESSOR_RUN */, name: `output processor: ${processor.id}`, entityType: chunkLP4WZA6D_cjs.EntityType.OUTPUT_PROCESSOR, entityId: processor.id, entityName: processor.name, attributes: { processorExecutor: "legacy", processorIndex: index }, input: { messages: processableMessages, ...summarizedResult ? { result: summarizedResult } : {}, retryCount } }); messageList.startRecording(); try { const processorState = this.getProcessorState(processor.id); const processResult = await processMethod({ messages: processableMessages, messageList, state: processorState.customState, result: result ?? defaultResult, abort, ...chunkFHPG32XN_cjs.createObservabilityContext({ currentSpan: processorSpan }), requestContext, retryCount, writer, sendSignal: createProcessorSendSignal({ messageList, writer }) }); const mutations = messageList.stopRecording(); if (processResult instanceof chunk2TATDSHU_cjs.MessageList) { if (processResult !== messageList) { throw new chunkXSOONORA_cjs.MastraError({ category: "USER", domain: "AGENT", id: "PROCESSOR_RETURNED_EXTERNAL_MESSAGE_LIST", text: `Processor ${processor.id} returned a MessageList instance other than the one that was passed in as an argument. New external message list instances are not supported. Use the messageList argument instead.` }); } if (mutations.length > 0) { processableMessages = processResult.get.response.db(); } } else { if (processResult) { const deletedIds = idsBeforeProcessing.filter( (i) => !processResult.some((m) => m.id === i) ); if (deletedIds.length) { messageList.removeByIds(deletedIds); } processableMessages = processResult || []; for (const message of processResult) { messageList.removeByIds([message.id]); messageList.add(message, check.getSource(message) || "response"); } } } processorSpan?.end({ output: { ...!areProcessorMessageArraysEqual(outputMessagesBefore, processableMessages) ? { messages: processableMessages } : {}, ...!areProcessorMessageArraysEqual(outputSystemMessagesBefore, messageList.getAllSystemMessages()) ? { systemMessages: messageList.getAllSystemMessages() } : {} }, attributes: mutations.length > 0 ? { messageListMutations: mutations } : void 0 }); } catch (error) { messageList.stopRecording(); if (error instanceof TripWire) { processorSpan?.error({ error, endSpan: true, attributes: { tripwireAbort: { reason: error.message, retry: error.options?.retry, metadata: error.options?.metadata } } }); await invokeOnViolation(processor, error); throw error; } processorSpan?.error({ error, endSpan: true }); throw error; } } return messageList; } /** * Process a stream part through all output processors with state management */ async processPart(part, processorStates, observabilityContext, requestContext, messageList, retryCount = 0, writer) { if (!this.outputProcessors.length) { return { part, blocked: false }; } try { let processedPart = part; const isFinishChunk = part.type === "finish"; for (const [index, processorOrWorkflow] of this.outputProcessors.entries()) { if (isProcessorWorkflow(processorOrWorkflow)) { if (!processedPart) continue; const workflowId = processorOrWorkflow.id; let state = processorStates.get(workflowId); if (!state) { state = new ProcessorState(); processorStates.set(workflowId, state); } state.addInputPart(processedPart); try { const result = await this.executeWorkflowAsProcessor( processorOrWorkflow, { phase: "outputStream", part: processedPart, streamParts: state.streamParts, state: state.customState, messageList, retryCount }, observabilityContext, requestContext, writer ); if ("part" in result) { processedPart = result.part; } state.addOutputPart(processedPart); } catch (error) { if (error instanceof TripWire) { return { part: null, blocked: true, reason: error.message, tripwireOptions: error.options, processorId: error.processorId || workflowId }; } this.logger.error("Output processor workflow failed", { agent: this.agentName, workflowId, error }); } continue; } const processor = processorOrWorkflow; try { if (processor.processOutputStream && processedPart) { let state = processorStates.get(processor.id); if (!state) { state = new ProcessorState({ processorName: processor.name ?? processor.id, ...observabilityContext, processorIndex: index, createSpan: true }); processorStates.set(processor.id, state); } state.addInputPart(processedPart); const result = await processor.processOutputStream({ part: processedPart, streamParts: state.streamParts, state: state.customState, abort: (reason, options) => { throw new TripWire(reason || `Stream part blocked by ${processor.id}`, options, processor.id); }, ...chunkFHPG32XN_cjs.createObservabilityContext({ currentSpan: state.span }), requestContext, messageList, retryCount, writer }); processedPart = result; state.addOutputPart(processedPart); } } catch (error) { if (error instanceof TripWire) { const state2 = processorStates.get(processor.id); state2?.span?.error({ error, endSpan: true, attributes: { tripwireAbort: { reason: error.message, retry: error.options?.retry, metadata: error.options?.metadata } } }); await invokeOnViolation(processor, error); return { part: null, blocked: true, reason: error.message, tripwireOptions: error.options, processorId: processor.id }; } const state = processorStates.get(processor.id); state?.span?.error({ error, endSpan: true }); this.logger.error("Output processor failed", { agent: this.agentName, processorId: processor.id, error }); } } if (isFinishChunk) { for (const state of processorStates.values()) { if (state.span) { state.span.end({ output: state.getFinalOutput() }); } } } return { part: processedPart, blocked: false }; } catch (error) { this.logger.error("Stream part processing failed", { agent: this.agentName, error }); for (const state of processorStates.values()) { state.span?.error({ error, endSpan: true }); } return { part, blocked: false }; } } /** * Re-drive any parts that stream processors stashed for reprocessing through * the full output processor chain. * * A stream processor can only return one part from `processOutputStream`, but * some processors (e.g. `BatchPartsProcessor`) need to emit a second part for * one input — it returns the first part and stashes the second under * `REPROCESS_PART_KEY` on its state. After the primary part has been emitted, * callers invoke this to push each stashed part back through the whole chain * (so it receives downstream processing) and emit the results in order. * * Returns the processed results in emission order. Reprocessing can itself * stash more parts, so this drains until none remain. */ async drainReprocessParts(processorStates, observabilityContext, requestContext, messageList, retryCount = 0, writer) { const results = []; const takeNext = () => { for (const state of processorStates.values()) { const custom = state.customState; const stashed = custom[REPROCESS_PART_KEY]; if (stashed) { delete custom[REPROCESS_PART_KEY]; return stashed; } } return void 0; }; let guard = 0; let next = takeNext(); while (next && guard++ < 1e3) { const result = await this.processPart( next, processorStates, observabilityContext, requestContext, messageList, retryCount, writer ); results.push(result); if (result.blocked) { break; } next = takeNext(); } return results; } async runOutputProcessorsForStream(streamResult, observabilityContext, writer) { return new ReadableStream({ start: async (controller) => { const reader = streamResult.fullStream.getReader(); const processorStates = /* @__PURE__ */ new Map(); const streamWriter = writer ?? { custom: async (data) => controller.enqueue(data) }; try { while (true) { const { done, value } = await reader.read(); if (done) { controller.close(); break; } const { part: processedPart, blocked, reason, tripwireOptions, processorId } = await this.processPart( value, processorStates, observabilityContext, void 0, void 0, 0, streamWriter ); const enqueueTripwire = (r, opts, pid) => { void this.logger.debug("Stream part blocked by output processor", { agent: this.agentName, reason: r, originalPart: value }); controller.enqueue({ type: "tripwire", payload: { reason: r || "Output processor blocked content", retry: opts?.retry, metadata: opts?.metadata, processorId: pid } }); }; if (blocked) { enqueueTripwire(reason, tripwireOptions, processorId); controller.close(); break; } else if (processedPart != null) { controller.enqueue(processedPart); } const reprocessed = await this.drainReprocessParts( processorStates, observabilityContext, void 0, void 0, 0, streamWriter ); let aborted = false; for (const r of reprocessed) { if (r.blocked) { enqueueTripwire(r.reason, r.tripwireOptions, r.processorId); controller.close(); aborted = true; break; } if (r.part != null) { controller.enqueue(r.part); } } if (aborted) { break; } } } catch (error) { controller.error(error); } } }); } async runInputProcessors(messageList, observabilityContext, requestContext, retryCount = 0) { for (const [index, processorOrWorkflow] of this.inputProcessors.entries()) { let processableMessages = messageList.get.input.db(); const inputIds = processableMessages.map((m) => m.id); const check = messageList.makeMessageSourceChecker(); if (isProcessorWorkflow(processorOrWorkflow)) { const currentSystemMessages2 = messageList.getSystemMessages(); await this.executeWorkflowAsProcessor( processorOrWorkflow, { phase: "input", messages: processableMessages, messageList, systemMessages: currentSystemMessages2, retryCount }, observabilityContext, requestContext ); continue; } const processor = processorOrWorkflow; const abort = (reason, options) => { throw new TripWire(reason || `Tripwire triggered by ${processor.id}`, options, processor.id); }; const processMethod = processor.processInput?.bind(processor); if (!processMethod) { continue; } const currentSystemMessages = messageList.getSystemMessages(); const inputMessagesBefore = processableMessages; const inputSystemMessagesBefore = currentSystemMessages; const currentSpan = observabilityContext?.tracingContext?.currentSpan; const parentSpan = currentSpan?.findParent("agent_run" /* AGENT_RUN */) || currentSpan?.parent || currentSpan; const processorSpan = parentSpan?.createChildSpan({ type: "processor_run" /* PROCESSOR_RUN */, name: `input processor: ${processor.id}`, entityType: chunkLP4WZA6D_cjs.EntityType.INPUT_PROCESSOR, entityId: processor.id, entityName: processor.name, attributes: { processorExecutor: "legacy", processorIndex: index }, input: { messages: processableMessages, systemMessages: currentSystemMessages } }); messageList.startRecording(); try { const processorState = this.getProcessorState(processor.id); const result = await processMethod({ messages: processableMessages, systemMessages: currentSystemMessages, state: processorState.customState, abort, ...chunkFHPG32XN_cjs.createObservabilityContext({ currentSpan: processorSpan }), messageList, requestContext, retryCount, sendSignal: createProcessorSendSignal({ messageList }) }); let mutations; if (result instanceof chunk2TATDSHU_cjs.MessageList) { if (result !== messageList) { throw new chunkXSOONORA_cjs.MastraError({ category: "USER", domain: "AGENT", id: "PROCESSOR_RETURNED_EXTERNAL_MESSAGE_LIST", text: `Processor ${processor.id} returned a MessageList instance other than the one that was passed in as an argument. New external message list instances are not supported. Use the messageList argument instead.` }); } mutations = messageList.stopRecording(); if (mutations.length > 0) { processableMessages = messageList.get.input.db(); } } else if (this.isProcessInputResultWithSystemMessages(result)) { mutations = messageList.stopRecording(); messageList.replaceAllSystemMessages(result.systemMessages); const regularMessages = result.messages; if (regularMessages) { const deletedIds = inputIds.filter((i) => !regularMessages.some((m) => m.id === i)); if (deletedIds.length) { messageList.removeByIds(deletedIds); } const newSystemMessages = regularMessages.filter((m) => m.role === "system"); const nonSystemMessages = regularMessages.filter((m) => m.role !== "system"); for (const sysMsg of newSystemMessages) { const systemText = sysMsg.content.content ?? sysMsg.content.parts?.map((p) => p.type === "text" ? p.text : "").join("\n") ?? ""; messageList.addSystem(systemText); } if (nonSystemMessages.length > 0) { for (const message of nonSystemMessages) { messageList.removeByIds([message.id]); messageList.add(message, check.getSource(message) || "input"); } } } processableMessages = messageList.get.input.db(); } else { mutations = messageList.stopRecording(); if (result) { const deletedIds = inputIds.filter((i) => !result.some((m) => m.id === i)); if (deletedIds.length) { messageList.removeByIds(deletedIds); } const systemMessages = result.filter((m) => m.role === "system"); const nonSystemMessages = result.filter((m) => m.role !== "system"); for (const sysMsg of systemMessages) { const systemText = sysMsg.content.content ?? sysMsg.content.parts?.map((p) => p.type === "text" ? p.text : "").join("\n") ?? ""; messageList.addSystem(systemText); } if (nonSystemMessages.length > 0) { for (const message of nonSystemMessages) { messageList.removeByIds([message.id]); messageList.add(message, check.getSource(message) || "input"); } } processableMessages = messageList.get.input.db(); } } processorSpan?.end({ output: { ...!areProcessorMessageArraysEqual(inputMessagesBefore, processableMessages) ? { messages: processableMessages } : {}, ...!areProcessorMessageArraysEqual(inputSystemMessagesBefore, messageList.getSystemMessages()) ? { systemMessages: messageList.getSystemMessages() } : {} }, attributes: mutations.length > 0 ? { messageListMutations: mutations } : void 0 }); } catch (error) { messageList.stopRecording(); if (error instanceof TripWire) { processorSpan?.error({ error, endSpan: true, attributes: { tripwireAbort: { reason: error.message, retry: error.options?.retry, metadata: error.options?.metadata } } }); await invokeOnViolation(processor, error); throw error; } processorSpan?.error({ error, endSpan: true }); throw error; } } return messageList; } /** * Run processInputStep for all processors that implement it. * Called at each step of the agentic loop, before the LLM is invoked. * * Unlike processInput which runs once at the start, this runs at every step * (including tool call continuations). This is useful for: * - Transforming message types between steps (e.g., AI SDK 'reasoning' -> Anthropic 'thinking') * - Modifying messages based on step context * - Implementing per-step message transformations * * @param args.messages - The current messages to be sent to the LLM (MastraDBMessage format) * @param args.messageList - MessageList instance for managing message sources * @param args.stepNumber - The current step number (0-indexed) * @param args.tracingContext - Optional tracing context for observability * @param args.requestContext - Optional runtime context with execution metadata * * @returns The processed MessageList */ async runProcessInputStep(args) { const { messageList, stepNumber, steps, requestContext, writer } = args; const observabilityContext = chunkFHPG32XN_cjs.resolveObservabilityContext(args); const stepInput = { messageId: args.messageId, tools: args.tools, toolChoice: args.toolChoice, model: args.model, activeTools: args.activeTools, providerOptions: args.providerOptions, modelSettings: args.modelSettings, structuredOutput: args.structuredOutput, retryCount: args.retryCount ?? 0 }; const processors = stepInput.model && isMaybeClaude46(stepInput.model) ? [...this.inputProcessors, new TrailingAssistantGuard()] : this.inputProcessors; for (const [index, processorOrWorkflow] of processors.entries()) { const processableMessages = messageList.get.all.db(); const idsBeforeProcessing = processableMessages.map((m) => m.id); const check = messageList.makeMessageSourceChecker(); if (isProcessorWorkflow(processorOrWorkflow)) { const currentSystemMessages2 = messageList.getSystemMessages(); const result = await this.executeWorkflowAsProcessor( processorOrWorkflow, { phase: "inputStep", messages: processableMessages, messageList, stepNumber, steps, systemMessages: currentSystemMessages2, rotateResponseMessageId: args.rotateResponseMessageId ? () => { const nextMessageId = args.rotateResponseMessageId(); stepInput.messageId = nextMessageId; return nextMessageId; } : void 0, ...stepInput }, observabilityContext, requestContext, writer, args.abortSignal ); Object.assign(stepInput, result); await this.runWorkflowComputeStateSignals({ workflow: processorOrWorkflow, messageList, stepNumber, steps, requestContext, writer, memory: args.memory, resourceId: args.resourceId, threadId: args.threadId, abortSignal: args.abortSignal, retryCount: args.retryCount ?? 0, rotateResponseMessageId: args.rotateResponseMessageId ? () => { const nextMessageId = args.rotateResponseMessageId(); stepInput.messageId = nextMessageId; return nextMessageId; } : void 0 }); continue; } const processor = processorOrWorkflow; const processMethod = processor.processInputStep?.bind(processor); const computeStateSignal = processor.computeStateSignal?.bind(processor); if (!processMethod && !computeStateSignal) { continue; } const abort = (reason, options) => { throw new TripWire(reason || `Tripwire triggered by ${processor.id}`, options, processor.id); }; const currentSystemMessages = messageList.getSystemMessages(); const inputData = { messages: processableMessages, stepNumber, steps, messageId: stepInput.messageId, systemMessages: currentSystemMessages, tools: stepInput.tools, toolChoice: stepInput.toolChoice, model: stepInput.model, activeTools: stepInput.activeTools, providerOptions: stepInput.providerOptions, modelSettings: stepInput.modelSettings, structuredOutput: stepInput.structuredOutput, requestContext }; const currentSpan = observabilityContext.tracingContext?.currentSpan; const processorSpan = currentSpan?.createChildSpan({ type: "processor_run" /* PROCESSOR_RUN */, name: `input step processor: ${processor.id}`, entityType: chunkLP4WZA6D_cjs.EntityType.INPUT_STEP_PROCESSOR, entityId: processor.id, entityName: processor.name, attributes: { processorExecutor: "legacy", processorIndex: index }, input: buildProcessInputStepSpanInput({ messages: inputData.messages, systemMessages: inputData.systemMessages, stepNumber: inputData.stepNumber, messageId: inputData.messageId, retryCount: args.retryCount ?? 0, model: inputData.model, tools: inputData.tools, toolChoice: inputData.toolChoice, activeTools: inputData.activeTools }) }); messageList.startRecording(); try { const processorState = this.getProcessorState(processor.id); const beforeStepInput = { messageId: inputData.messageId, model: inputData.model, tools: inputData.tools, toolChoice: inputData.toolChoice, activeTools: inputData.activeTools }; const rotateResponseMessageId = args.rotateResponseMessageId ? () => { const nextMessageId = args.rotateResponseMessageId(); stepInput.messageId = nextMessageId; return nextMessageId; } : void 0; const processMethodArgs = { messageList, ...inputData, state: processorState.customState, abort, ...rotateResponseMessageId ? { rotateResponseMessageId } : {}, ...chunkFHPG32XN_cjs.createObservabilityContext({ currentSpan: processorSpan }), retryCount: args.retryCount ?? 0, writer, abortSignal: args.abortSignal, sendSignal: createProcessorSendSignal({ messageList, writer, rotateResponseMessageId }), sendStateSignal: async (stateSignal) => { const memoryContext = chunkUC46OXET_cjs.parseMemoryRequestContext(requestContext); const resolvedMemory = args.memory; const resolvedThreadId = args.threadId ?? memoryContext?.thread?.id; const resolvedResourceId = args.resourceId ?? memoryContext?.resourceId; if (!resolvedMemory || !resolvedThreadId || !resolvedResourceId) { throw new Error( `[Processor:${processor.id}] sendStateSignal requires Mastra memory with an active resourceId and threadId` ); } const loadedThread = await resolvedMemory.getThreadById({ threadId: resolvedThreadId }) ?? memoryContext?.thread; if (!loadedThread) { throw new Error(`[Processor:${processor.id}] sendStateSignal could not load thread ${resolvedThreadId}`); } const thread = { ...loadedThread, id: resolvedThreadId, resourceId: loadedThread.resourceId ?? resolvedResourceId, createdAt: loadedThread.createdAt ?? /* @__PURE__ */ new Date(), updatedAt: loadedThread.updatedAt ?? /* @__PURE__ */ new Date(), metadata: loadedThread.metadata }; const result2 = await chunkUC46OXET_cjs.applyStateSignal({ input: stateSignal, memory: resolvedMemory, thread, resourceId: resolvedResourceId, threadId: resolvedThreadId, memoryConfig: memoryContext?.memoryConfig, messageList, defaultId: processor.stateId ?? processor.id, beforeAddSignal: rotateResponseMessageId ? () => { messageList.markResponseMessageBoundary(); rotateResponseMessageId(); } : void 0, writeSignal: (signal) => writer?.custom(signal.toDataPart()) }); return result2.skipped ? result2 : result2.signal; } }; const result = processMethod ? await _ProcessorRunner.validateAndFormatProcessInputStepResult(await processMethod(processMethodArgs), { messageList, processor, stepNumber }) : {}; const { messages, systemMessages, ...rest } = result; if (messages) { _ProcessorRunner.applyMessagesToMessageList(messages, messageList, idsBeforeProcessing, check); } if (systemMessages) { messageList.replaceAllSystemMessages(systemMessages); } Object.assign(stepInput, rest); await this.runComputeStateSignal({ processor, messageList, stepNumber, steps, requestContext, writer, abort, processorState, memory: args.memory, resourceId: args.resourceId, threadId: args.threadId, abortSignal: args.abortSignal, retryCount: args.retryCount ?? 0, rotateResponseMessageId }); const mutations = messageList.stopRecording(); processorSpan?.end({ output: buildProcessInputStepSpanOutput({ result, beforeStepInput, afterStepInput: stepInput, beforeMessages: inputData.messages, beforeSystemMessages: inputData.systemMessages, messages: messageList.get.all.db(), systemMessages: messageList.getSystemMessages() }), attributes: mutations.length > 0 ? { messageListMutations: mutations } : void 0 }); } catch (error) { messageList.stopRecording(); if (error instanceof TripWire) { processorSpan?.error({ error, endSpan: true, attributes: { tripwireAbort: { reason: error.message, retry: error.options?.retry, metadata: error.options?.metadata } } }); await invokeOnViolation(processor, error); throw error; } processorSpan?.error({ error, endSpan: true }); throw error; } } return stepInput; } /** * Run processLLMRequest for all processors that implement it. * * Called *after* `MessageList` has been converted to `LanguageModelV2Prompt` * and immediately *before* the prompt is forwarded to the provider. * Mutations are scoped to this single call — they do not affect the * persisted message list, memory, UI, or future model swaps. */ async runProcessLLMRequest(args) { chunkFHPG32XN_cjs.resolveObservabilityContext({ tracingContext: args.tracingContext }); let currentPrompt = args.prompt; let cachedResponse; for (const processorOrWorkflow of this.inputProcessors) { if (isProcessorWorkflow(processorOrWorkflow)) continue; const processor = processorOrWorkflow; const processMethod = processor.processLLMRequest?.bind(processor); if (!processMethod) continue; const abort = (reason, options) => { throw new TripWire(reason || `Tripwire triggered by ${processor.id}`, options, processor.id); }; try { const processorState = this.getProcessorState(processor.id); const result = await processMethod({ prompt: currentPrompt, // The Processor interface types `model` as `MastraLanguageModel`, but // the runner accepts the looser `unknown` to match other call paths // (e.g. unresolved string ids or function-typed dynamic models). model: args.model, stepNumber: args.stepNumber, steps: args.steps, state: processorState.customState, retryCount: args.retryCount ?? 0, requestContext: args.requestContext, abort, abortSignal: args.abortSignal, writer: args.writer, ...chunkFHPG32XN_cjs.createObservabilityContext(args.tracingContext) }); if (result && typeof result === "object") { if (Object.prototype.hasOwnProperty.call(result, "prompt")) { currentPrompt = result.prompt; } if (result.response && !cachedResponse) { cachedResponse = result.response; } } } catch (error) { if (error instanceof TripWire) { await invokeOnViolation(processor, error); } throw error; } } return { prompt: currentPrompt, response: cachedResponse }; } /** * Run processLLMResponse for all processors that implement it. * * Called *after* the LLM step completes (or after a cached response is * replayed) and *after* output processors have collected the response * chunks. The shared `state` object is the same instance passed to * `processLLMRequest` for the same step, allowing processors to correlate * pre- and post-call work (e.g. cache key stash, then cache write). */ async runProcessLLMResponse(args) { chunkFHPG32XN_cjs.resolveObservabilityContext({ tracingContext: args.tracingContext }); for (const processorOrWorkflow of this.inputProcessors) { if (isProcessorWorkflow(processorOrWorkflow)) continue; const processor = processorOrWorkflow; const processMethod = processor.processLLMResponse?.bind(processor); if (!processMethod) continue; const abort = (reason, options) => { throw new TripWire(reason || `Tripwire triggered by ${processor.id}`, options, processor.id); }; try { const processorState = this.getProcessorState(processor.id); await processMethod({ chunks: args.chunks, model: args.model, stepNumber: args.stepNumber, steps: args.steps, state: processorState.customState, warnings: args.warnings, request: args.request, rawResponse: args.rawResponse, fromCache: args.fromCache, retryCount: args.retryCount ?? 0, requestContext: args.requestContext, abort, abortSignal: args.abortSignal, writer: args.writer, ...chunkFHPG32XN_cjs.createObservabilityContext(args.tracingContext) }); } catch (error) { if (error instanceof TripWire) { await invokeOnViolation(processor, error); } throw error; } } } /** * Type guard to check if result is { messages, systemMessages } */ isProcessInputResultWithSystemMessages(result) { return result !== null && typeof result === "object" && "messages" in result && "systemMessages" in result && Array.isArray(result.messages) && Array.isArray(result.systemMessages); } /** * Run processOutputStep for all processors that implement it. * Called after each LLM response in the agentic loop, before tool execution. * * Unlike processOutputResult which runs once at the end, this runs at every step. * This is the ideal place to implement guardrails that can trigger retries. * * @param args.messages - The current messages including the LLM response * @param args.messageList - MessageList instance for managing message sources * @param args.stepNumber - The current step number (0-indexed) * @param args.finishReason - The finish reason from the LLM * @param args.toolCalls - Tool calls made in this step (if any) * @param args.text - Generated text from this step * @param args.tracingContext - Optional tracing context for observability * @param args.requestContext - Optional runtime context with execution metadata * @param args.retryCount - Number of times processors have triggered retry * * @returns The processed MessageList */ async runProcessOutputStep(args) { const { steps, messageList, stepNumber, finishReason, toolCalls, text, usage, requestContext, retryCount = 0, writer } = args; const observabilityContext = chunkFHPG32XN_cjs.resolveObservabilityContext(args); for (const [index, processorOrWorkflow] of this.outputProcessors.entries()) { const processableMessages = messageList.get.all.db(); const idsBeforeProcessing = processableMessages.map((m) => m.id); const check = messageList.makeMessageSourceChecker(); if (isProcessorWorkflow(processorOrWorkflow)) { const currentSystemMessages2 = messageList.getSystemMessages(); await this.executeWorkflowAsProcessor( processorOrWorkflow, { phase: "outputStep", messages: processableMessages, messageList, stepNumber, finishReason, toolCalls, text, usage, systemMessages: currentSystemMessages2, steps, retryCount }, observabilityContext, requestContext, writer ); continue; } const processor = processorOrWorkflow; const processMethod = processor.processOutputStep?.bind(processor); if (!processMethod) { continue; } const abort = (reason, options) => { throw new TripWire(reason || `Tripwire triggered by ${processor.id}`, options, processor.id); }; const currentSystemMessages = messageList.getSystemMessages(); const defaultUsage = { inputTokens: void 0, outputTokens: void 0, totalTokens: void 0 }; const currentSpan = observabilityContext.tracingContext?.currentSpan; const parentSpan = currentSpan?.findParent("agent_run" /* AGENT_RUN */) || currentSpan?.parent || currentSpan; const processorSpan = parentSpan?.createChildSpan({ type: "processor_run" /* PROCESSOR_RUN */, name: `output step processor: ${processor.id}`, entityType: chunkLP4WZA6D_cjs.EntityType.OUTPUT_STEP_PROCESSOR, entityId: processor.id, entityName: processor.name, attributes: { processorExecutor: "legacy", processorIndex: index }, input: { messages: processableMessages, systemMessages: currentSystemMessages, stepNumber, ...finishReason !== void 0 ? { finishReason } : {}, ...toolCalls !== void 0 ? { toolCalls } : {}, ...text !== void 0 ? { text } : {} } }); messageList.startRecording(); const processorState = this.getProcessorState(processor.id); try { const result = await processMethod({ messages: processableMessages, messageList, stepNumber, finishReason, toolCalls, text, usage: usage ?? defaultUsage, systemMessages: currentSystemMessages, steps, state: processorState.customState, abort, ...chunkFHPG32XN_cjs.createObservabilityContext({ currentSpan: processorSpan }), requestContext, retryCount, writer, sendSignal: createProcessorSendSignal({ messageList, writer }) }); const mutations = messageList.stopRecording(); if (result instanceof chunk2TATDSHU_cjs.MessageList) { if (result !== messageList) { throw new chunkXSOONORA_cjs.MastraError({ category: "USER", domain: "AGENT", id: "PROCESSOR_RETURNED_EXTERNAL_MESSAGE_LIST", text: `Processor ${processor.id} returned a MessageList instance other than the one that was passed in as an argument. New external message list instances are not supported. Use the messageList argument instead.` }); } } else if (result) { const deletedIds = idsBeforeProcessing.filter( (i) => !result.some((m) => m.id === i) ); if (deletedIds.length) { messageList.removeByIds(deletedIds); } for (const message of result) { messageList.removeByIds([message.id]); if (message.role === "system") { const systemText = message.content.content ?? message.content.parts?.map((p) => p.type === "text" ? p.text : "").join("\n") ?? ""; messageList.addSystem(systemText); } else { messageList.add(message, check.getSource(message) || "response"); } } } processorSpan?.end({ output: { ...!areProcessorMessageArraysEqual(processableMessages, messageList.get.all.db()) ? { messages: messageList.get.all.db() } : {}, ...!areProcessorMessageArraysEqual(currentSystemMessages, messageList.getSystemMessages()) ? { systemMessages: messageList.getSystemMessages() } : {} }, attributes: mutations.length > 0 ? { messageListMutations: mutations } : void 0 }); } catch (error) { messageList.stopRecording(); if (error instanceof TripWire) { processorSpan?.error({ error, endSpan: true, attributes: { tripwireAbort: { reason: error.message, retry: error.options?.retry, metadata: error.options?.metadata } } }); await invokeOnViolation(processor, error); throw error; } processorSpan?.error({ error, endSpan: true }); throw error; } } return messageList; } /** * Run processAPIError on all processors that implement it. * Called when an LLM API call fails with a non-retryable error. * Iterates through both input and output processors. * * @returns { retry: boolean } indicating whether to retry the LLM call */ async runProcessAPIError(args) { const { error, messageList, stepNumber, steps, requestContext, retryCount = 0, writer, abortSignal } = args; const observabilityContext = chunkFHPG32XN_cjs.resolveObservabilityContext(args); const allProcessors = [ ...this.inputProcessors, ...this.outputProcessors, ...this.errorProcessors ]; for (const [index, processorOrWorkflow] of allProcessors.entries()) { if (isProcessorWorkflow(processorOrWorkflow)) { continue; } const processor = processorOrWorkflow; const processMethod = processor.processAPIError?.bind(processor); if (!processMethod) { continue; } const abort = (reason, options) => { throw new TripWire(reason || `Tripwire triggered by ${processor.id}`, options, processor.id); }; const processableMessages = messageList.get.all.db(); const systemMessagesBefore = messageList.getAllSystemMessages(); const messageIdBefore = args.messageId; let messageIdAfter = args.messageId; const currentSpan = observabilityContext.tracingContext?.currentSpan; const parentSpan = currentSpan?.findParent("agent_run" /* AGENT_RUN */) || currentSpan?.parent || currentSpan; const processorSpan = parentSpan?.createChildSpan({ type: "processor_run" /* PROCESSOR_RUN */, name: `request error processor: ${processor.id}`, entityType: chunkLP4WZA6D_cjs.EntityType.OUTPUT_STEP_PROCESSOR, entityId: processor.id, entityName: processor.name, attributes: { processorExecutor: "legacy", processorIndex: index }, input: { messages: processableMessages, error: error instanceof Error ? error.message : String(error), stepNumber, ...args.messageId ? { messageId: args.messageId } : {}, retryCount } }); messageList.startRecording(); const processorState = this.getProcessorState(processor.id); try { const rotateResponseMessageId = args.rotateResponseMessageId ? () => { const nextMessageId = args.rotateResponseMessageId(); messageIdAfter = nextMessageId; return nextMessageId; } : void 0; const result = await processMethod({ messages: processableMessages, messageList, stepNumber, steps, state: processorState.customState, error, abort, ...chunkFHPG32XN_cjs.createObservabilityContext({ currentSpan: processorSpan }), requestContext, retryCount, writer, abortSignal, messageId: args.messageId, ...rotateResponseMessageId ? { rotateResponseMessageId } : {}, sendSignal: createProcessorSendSignal({ messageList, writer, rotateResponseMessageId }) }); const mutations = messageList.stopRecording(); const messagesAfter = messageList.get.all.db(); const systemMessagesAfter = messageList.getAllSystemMessages(); const output = { retry: result?.retry ?? false }; if (!areProcessorMessageArraysEqual(processableMessages, messagesAfter)) { output.messages = messagesAfter; } if (!areProcessorMessageArraysEqual(systemMessagesBefore, systemMessagesAfter)) { output.systemMessages = systemMessagesAfter; } if (messageIdAfter !== messageIdBefore) { output.messageId = messageIdAfter; } processorSpan?.end({ output, attributes: mutations.length > 0 ? { messageListMutations: mutations } : void 0 }); if (result?.retry) { return { retry: true }; } } catch (processorError) { messageList.stopRecording(); if (processorError instanceof TripWire) { processorSpan?.error({ error: processorError, endSpan: true, attributes: { tripwireAbort: { reason: processorError.message, retry: processorError.options?.retry, metadata: processorError.options?.metadata } } }); await invokeOnViolation(processor, processorError); throw processorError; } processorSpan?.error({ error: processorError, endSpan: true }); this.logger.error( `[Agent:${this.agentName}] - Request error processor ${processor.id} failed:`, processorError ); } } return { retry: false }; } static applyMessagesToMessageList(messages, messageList, idsBeforeProcessing, check, defaultSource = "input") { const deletedIds = idsBeforeProcessing.filter((i) => !messages.some((m) => m.id === i)); if (deletedIds.length) { messageList.removeByIds(deletedIds); } for (const message of messages) { messageList.removeByIds([message.id]); if (message.role === "system") { const systemText = message.content.content ?? message.content.parts?.map((p) => p.type === "text" ? p.text : "").join("\n") ?? ""; messageList.addSystem(systemText); } else { messageList.add(message, check.getSource(message) || defaultSource); } } } static async validateAndFormatProcessInputStepResult(result, { messageList, processor, stepNumber }) { if (result instanceof chunk2TATDSHU_cjs.MessageList) { if (result !== messageList) { throw new chunkXSOONORA_cjs.MastraError({ category: "USER", domain: "AGENT", id: "PROCESSOR_RETURNED_EXTERNAL_MESSAGE_LIST", text: `Processor ${processor.id} returned a MessageList instance other than the one that was passed in as an argument. New external message list instances are not supported. Use the messageList argument instead.` }); } return { messageList: result }; } else if (Array.isArray(result)) { return { messages: result }; } else if (result) { if (result.messageList && result.messageList !== messageList) { throw new chunkXSOONORA_cjs.MastraError({ category: "USER", domain: "AGENT", id: "PROCESSOR_RETURNED_EXTERNAL_MESSAGE_LIST", text: `Processor ${processor.id} returned a MessageList instance other than the one that was passed in as an argument. New external message list instances are not supported. Use the messageList argument instead.` }); } if (result.messages && result.messageList) { throw new chunkXSOONORA_cjs.MastraError({ category: "USER", domain: "AGENT", id: "PROCESSOR_RETURNED_MESSAGES_AND_MESSAGE_LIST", text: `Processor ${processor.id} returned both messages and messageList. Only one of these is allowed.` }); } const { model: _model, ...rest } = result; if (result.model) { const resolvedModel = await chunkAWVVTLZF_cjs.resolveModelConfig(result.model); const isSupported = isSupportedLanguageModel(resolvedModel); if (!isSupported) { throw new chunkXSOONORA_cjs.MastraError({ category: "USER", domain: "AGENT", id: "PROCESSOR_RETURNED_UNSUPPORTED_MODEL", text: `Processor ${processor.id} returned an unsupported model version ${resolvedModel.specificationVersion} in step ${stepNumber}. Only ${supportedLanguageModelSpecifications.join(", ")} models are supported in processInputStep.` }); } return { model: resolvedModel, ...rest }; } return rest; } return {}; } }; exports.DelayedPromise = DelayedPromise; exports.MastraModelInput = MastraModelInput; exports.MastraModelOutput = MastraModelOutput; exports.ProcessorRunner = ProcessorRunner; exports.ProcessorState = ProcessorState; exports.REPROCESS_PART_KEY = REPROCESS_PART_KEY; exports.TripWire = TripWire; exports.createDestructurableOutput = createDestructurableOutput; exports.createProcessorSendSignal = createProcessorSendSignal; exports.escapeUnescapedControlCharsInJsonStrings = escapeUnescapedControlCharsInJsonStrings; exports.getModelOutputForTripwire = getModelOutputForTripwire; exports.getResponseFormat = getResponseFormat; exports.isProcessorWorkflow = isProcessorWorkflow; exports.isSupportedLanguageModel = isSupportedLanguageModel; exports.resolveThreadIdFromArgs = resolveThreadIdFromArgs; exports.safeClose = safeClose; exports.safeEnqueue = safeEnqueue; exports.summarizeActiveToolsForSpan = summarizeActiveToolsForSpan; exports.summarizeProcessorModelForSpan = summarizeProcessorModelForSpan; exports.summarizeProcessorResultForSpan = summarizeProcessorResultForSpan; exports.summarizeProcessorToolsForSpan = summarizeProcessorToolsForSpan; exports.summarizeToolChoiceForSpan = summarizeToolChoiceForSpan; exports.supportedLanguageModelSpecifications = supportedLanguageModelSpecifications; exports.tryGenerateWithJsonFallback = tryGenerateWithJsonFallback; exports.tryStreamWithJsonFallback = tryStreamWithJsonFallback; //# sourceMappingURL=chunk-NYGUBLK3.cjs.map //# sourceMappingURL=chunk-NYGUBLK3.cjs.map