UNPKG

@mastra/core

Version:
790 lines (789 loc) • 23.1 kB
import { t as MastraBase } from "./base-BeUQ6mLP.js"; import { i as MastraError, n as ErrorDomain, t as ErrorCategory } from "./error-MjDSls8S.js"; import { a as resolveObservabilityContext } from "./observability-Cz-X7NF_.js"; import { n as executeWithContextSync, t as executeWithContext } from "./utils-DxsDNzD2.js"; import "./tracing-Bm0k4FBA.js"; import { isStandardSchemaWithJSON, standardSchemaToJSONSchema, toStandardSchema } from "./schema/index.js"; import { i as isZodArray, t as getZodDef } from "./zod-utils-DTkc-hhd.js"; import { i as delay, u as isZodType$1 } from "./utils-CCbB2dG1.js"; import { a as output_exports, c as streamText, i as generateText, r as generateObject, s as streamObject } from "./dist-_kmO6lmF.js"; import { AnthropicSchemaCompatLayer, DeepSeekSchemaCompatLayer, GoogleSchemaCompatLayer, MetaSchemaCompatLayer, OpenAIReasoningSchemaCompatLayer, OpenAISchemaCompatLayer, applyCompatLayer, jsonSchema } from "@mastra/schema-compat"; //#region src/stream/aisdk/v4/usage.ts /** * Converts AI SDK v4 LanguageModelUsage to our UsageStats format. * * @param usage - The LanguageModelUsage from AI SDK v4 * @returns Normalized UsageStats */ function convertV4Usage(usage) { if (!usage) return {}; return { inputTokens: usage.promptTokens, outputTokens: usage.completionTokens }; } //#endregion //#region src/llm/model/model.ts var MastraLLMV1 = class extends MastraBase { #model; #mastra; #options; constructor({ model, mastra, options }) { super({ name: "aisdk" }); this.#model = model; this.#options = options; if (mastra) { this.#mastra = mastra; if (mastra.getLogger()) this.__setLogger(this.#mastra.getLogger()); } } __registerPrimitives(p) { if (p.logger) this.__setLogger(p.logger); } __registerMastra(p) { this.#mastra = p; } getProvider() { return this.#model.provider; } getModelId() { return this.#model.modelId; } getModel() { return this.#model; } _applySchemaCompat(schema) { const model = this.#model; const schemaCompatLayers = []; if (model) { const modelInfo = { modelId: model.modelId, supportsStructuredOutputs: model.supportsStructuredOutputs ?? false, provider: model.provider }; schemaCompatLayers.push(new OpenAIReasoningSchemaCompatLayer(modelInfo), new OpenAISchemaCompatLayer(modelInfo), new GoogleSchemaCompatLayer(modelInfo), new AnthropicSchemaCompatLayer(modelInfo), new DeepSeekSchemaCompatLayer(modelInfo), new MetaSchemaCompatLayer(modelInfo)); } return applyCompatLayer({ schema, compatLayers: schemaCompatLayers, mode: "aiSdkSchema" }); } async __text({ runId, messages, maxSteps = 5, tools = {}, temperature, toolChoice = "auto", onStepFinish, experimental_output, threadId, resourceId, requestContext, ...rest }) { const model = this.#model; const observabilityContext = resolveObservabilityContext(rest); this.logger.debug("Generating text", { runId, messages, maxSteps, threadId, resourceId, tools: Object.keys(tools) }); let schema = void 0; if (experimental_output) { this.logger.debug("Using experimental output", { runId }); if (isZodType$1(experimental_output)) { schema = experimental_output; if (isZodArray(schema)) schema = getZodDef(schema).type; schema = jsonSchema(standardSchemaToJSONSchema(toStandardSchema(schema))); } else schema = jsonSchema(experimental_output); } if (tools && Object.keys(tools).length > 0) { for (const tool of Object.values(tools)) if (tool.parameters) if ("validate" in tool.parameters) tool.parameters = tool.parameters; else if (isStandardSchemaWithJSON(tool.parameters)) tool.parameters = jsonSchema(standardSchemaToJSONSchema(tool.parameters)); else tool.parameters = jsonSchema(tool.parameters); } const llmSpan = observabilityContext.tracingContext.currentSpan?.createChildSpan({ name: `llm: '${model.modelId}'`, type: "model_generation", input: { messages, schema }, attributes: { model: model.modelId, provider: model.provider, parameters: { temperature, maxOutputTokens: rest.maxTokens, topP: rest.topP, frequencyPenalty: rest.frequencyPenalty, presencePenalty: rest.presencePenalty }, streaming: false }, metadata: { runId, threadId, resourceId }, tracingPolicy: this.#options?.tracingPolicy, requestContext }); const argsForExecute = { ...rest, messages, model, temperature, tools: { ...tools }, toolChoice, maxSteps, onStepFinish: async (props) => { try { await onStepFinish?.({ ...props, runId }); } catch (e) { throw new MastraError({ id: "LLM_TEXT_ON_STEP_FINISH_CALLBACK_EXECUTION_FAILED", domain: ErrorDomain.LLM, category: ErrorCategory.USER, details: { modelId: model.modelId, modelProvider: model.provider, runId: runId ?? "unknown", threadId: threadId ?? "unknown", resourceId: resourceId ?? "unknown", finishReason: props?.finishReason, toolCalls: props?.toolCalls ? JSON.stringify(props.toolCalls) : "", toolResults: props?.toolResults ? JSON.stringify(props.toolResults) : "", usage: props?.usage ? JSON.stringify(props.usage) : "" } }, e); } this.logger.debug("Text step change", { text: props?.text, toolCalls: props?.toolCalls, toolResults: props?.toolResults, finishReason: props?.finishReason, usage: props?.usage, runId }); const remainingTokens = parseInt(props?.response?.headers?.["x-ratelimit-remaining-tokens"] ?? "", 10); if (!isNaN(remainingTokens) && remainingTokens > 0 && remainingTokens < 2e3) { this.logger.warn("Rate limit approaching, waiting 10 seconds", { runId, remainingTokens }); const rateLimitSpan = llmSpan?.createChildSpan({ name: "rate-limit-sleep", type: "generic", metadata: { remainingTokens, delayMs: 1e4 } }); await delay(10 * 1e3); rateLimitSpan?.end(); } }, experimental_output: schema ? output_exports.object({ schema }) : void 0 }; try { const result = await executeWithContext({ span: llmSpan, fn: () => generateText(argsForExecute) }); if (schema && result.finishReason === "stop") result.object = result.experimental_output; llmSpan?.end({ output: { text: result.text, object: result.object, reasoning: result.reasoningDetails, reasoningText: result.reasoning, files: result.files, sources: result.sources, toolCalls: result.toolCalls, warnings: result.warnings }, attributes: { finishReason: result.finishReason, responseId: result.response?.id, responseModel: result.response?.modelId, usage: convertV4Usage(result.usage) } }); return result; } catch (e) { const mastraError = new MastraError({ id: "LLM_GENERATE_TEXT_AI_SDK_EXECUTION_FAILED", domain: ErrorDomain.LLM, category: ErrorCategory.THIRD_PARTY, details: { modelId: model.modelId, modelProvider: model.provider, runId: runId ?? "unknown", threadId: threadId ?? "unknown", resourceId: resourceId ?? "unknown" } }, e); this.logger.error("Generate text failed", { error: mastraError, runId, threadId, resourceId, modelId: model.modelId, modelProvider: model.provider }); llmSpan?.error({ error: mastraError }); throw mastraError; } } async __textObject({ messages, structuredOutput, runId, threadId, resourceId, requestContext, ...rest }) { const model = this.#model; const observabilityContext = resolveObservabilityContext(rest); this.logger.debug("Generating text object", { runId }); const llmSpan = observabilityContext.tracingContext.currentSpan?.createChildSpan({ name: `llm: '${model.modelId}'`, type: "model_generation", input: { messages }, attributes: { model: model.modelId, provider: model.provider, parameters: { temperature: rest.temperature, maxOutputTokens: rest.maxTokens, topP: rest.topP, frequencyPenalty: rest.frequencyPenalty, presencePenalty: rest.presencePenalty }, streaming: false }, metadata: { runId, threadId, resourceId }, tracingPolicy: this.#options?.tracingPolicy, requestContext }); try { let output = "object"; if (isZodArray(structuredOutput)) { output = "array"; const zodDef = getZodDef(structuredOutput); if ("element" in zodDef) structuredOutput = zodDef.element; else structuredOutput = zodDef.type; } const processedSchema = this._applySchemaCompat(structuredOutput); llmSpan?.update({ input: { messages, schema: processedSchema } }); const argsForExecute = { ...rest, messages, model, output, schema: processedSchema }; try { const result = await generateObject(argsForExecute); llmSpan?.end({ output: { object: result.object, warnings: result.warnings }, attributes: { finishReason: result.finishReason, responseId: result.response?.id, responseModel: result.response?.modelId, usage: convertV4Usage(result.usage) } }); return result; } catch (e) { const mastraError = new MastraError({ id: "LLM_GENERATE_OBJECT_AI_SDK_EXECUTION_FAILED", domain: ErrorDomain.LLM, category: ErrorCategory.THIRD_PARTY, details: { modelId: model.modelId, modelProvider: model.provider, runId: runId ?? "unknown", threadId: threadId ?? "unknown", resourceId: resourceId ?? "unknown" } }, e); this.logger.error("Generate object failed", { error: mastraError, runId, threadId, resourceId, modelId: model.modelId, modelProvider: model.provider }); llmSpan?.error({ error: mastraError }); throw mastraError; } } catch (e) { if (e instanceof MastraError) throw e; const mastraError = new MastraError({ id: "LLM_GENERATE_OBJECT_AI_SDK_SCHEMA_CONVERSION_FAILED", domain: ErrorDomain.LLM, category: ErrorCategory.USER, details: { modelId: model.modelId, modelProvider: model.provider, runId: runId ?? "unknown", threadId: threadId ?? "unknown", resourceId: resourceId ?? "unknown" } }, e); this.logger.error("Generate object schema conversion failed", { error: mastraError, runId, threadId, resourceId, modelId: model.modelId, modelProvider: model.provider }); llmSpan?.error({ error: mastraError }); throw mastraError; } } __stream({ messages, onStepFinish, onFinish, maxSteps = 5, tools = {}, runId, temperature, toolChoice = "auto", experimental_output, threadId, resourceId, requestContext, ...rest }) { const model = this.#model; const observabilityContext = resolveObservabilityContext(rest); let schema; if (experimental_output) if (typeof experimental_output.parse === "function") { schema = experimental_output; if (isZodArray(schema)) schema = getZodDef(schema).type; } else schema = jsonSchema(experimental_output); const llmSpan = observabilityContext.tracingContext.currentSpan?.createChildSpan({ name: `llm: '${model.modelId}'`, type: "model_generation", input: { messages }, attributes: { model: model.modelId, provider: model.provider, parameters: { temperature, maxOutputTokens: rest.maxTokens, topP: rest.topP, frequencyPenalty: rest.frequencyPenalty, presencePenalty: rest.presencePenalty }, streaming: true }, metadata: { runId, threadId, resourceId }, tracingPolicy: this.#options?.tracingPolicy, requestContext }); if (llmSpan) executeWithContextSync({ span: llmSpan, fn: () => this.logger.debug("Streaming text", { runId, threadId, resourceId, messages, maxSteps, tools: Object.keys(tools || {}) }) }); if (tools && Object.keys(tools).length > 0) { for (const tool of Object.values(tools)) if (tool.parameters) if ("validate" in tool.parameters) tool.parameters = tool.parameters; else if (isStandardSchemaWithJSON(tool.parameters)) tool.parameters = jsonSchema(standardSchemaToJSONSchema(tool.parameters)); else tool.parameters = jsonSchema(tool.parameters); } const argsForExecute = { model, temperature, tools: { ...tools }, maxSteps, toolChoice, onStepFinish: async (props) => { try { await onStepFinish?.({ ...props, runId }); } catch (e) { const mastraError = new MastraError({ id: "LLM_STREAM_ON_STEP_FINISH_CALLBACK_EXECUTION_FAILED", domain: ErrorDomain.LLM, category: ErrorCategory.USER, details: { modelId: model.modelId, modelProvider: model.provider, runId: runId ?? "unknown", threadId: threadId ?? "unknown", resourceId: resourceId ?? "unknown", finishReason: props?.finishReason, toolCalls: props?.toolCalls ? JSON.stringify(props.toolCalls) : "", toolResults: props?.toolResults ? JSON.stringify(props.toolResults) : "", usage: props?.usage ? JSON.stringify(props.usage) : "" } }, e); this.logger.trackException(mastraError); llmSpan?.error({ error: mastraError }); throw mastraError; } this.logger.debug("Stream step change", { text: props?.text, toolCalls: props?.toolCalls, toolResults: props?.toolResults, finishReason: props?.finishReason, usage: props?.usage, runId }); const remainingTokens = parseInt(props?.response?.headers?.["x-ratelimit-remaining-tokens"] ?? "", 10); if (!isNaN(remainingTokens) && remainingTokens > 0 && remainingTokens < 2e3) { this.logger.warn("Rate limit approaching, waiting 10 seconds", { runId, remainingTokens }); const rateLimitSpan = llmSpan?.createChildSpan({ name: "rate-limit-sleep", type: "generic", metadata: { remainingTokens, delayMs: 1e4 } }); await delay(10 * 1e3); rateLimitSpan?.end(); } }, onFinish: async (props) => { llmSpan?.end({ output: { text: props?.text, reasoning: props?.reasoningDetails, reasoningText: props?.reasoning, files: props?.files, sources: props?.sources, toolCalls: props?.toolCalls, warnings: props?.warnings }, attributes: { finishReason: props?.finishReason, usage: convertV4Usage(props?.usage) } }); try { await onFinish?.({ ...props, runId }); } catch (e) { const mastraError = new MastraError({ id: "LLM_STREAM_ON_FINISH_CALLBACK_EXECUTION_FAILED", domain: ErrorDomain.LLM, category: ErrorCategory.USER, details: { modelId: model.modelId, modelProvider: model.provider, runId: runId ?? "unknown", threadId: threadId ?? "unknown", resourceId: resourceId ?? "unknown", finishReason: props?.finishReason, toolCalls: props?.toolCalls ? JSON.stringify(props.toolCalls) : "", toolResults: props?.toolResults ? JSON.stringify(props.toolResults) : "", usage: props?.usage ? JSON.stringify(props.usage) : "" } }, e); llmSpan?.error({ error: mastraError }); this.logger.trackException(mastraError); throw mastraError; } this.logger.debug("Stream finished", { text: props?.text, toolCalls: props?.toolCalls, toolResults: props?.toolResults, finishReason: props?.finishReason, usage: props?.usage, runId, threadId, resourceId }); }, onError: ({ error }) => { const mastraError = new MastraError({ id: "LLM_STREAM_TEXT_AI_SDK_STREAMING_ERROR", domain: ErrorDomain.LLM, category: ErrorCategory.THIRD_PARTY, details: { modelId: model.modelId, modelProvider: model.provider, runId: runId ?? "unknown", threadId: threadId ?? "unknown", resourceId: resourceId ?? "unknown" } }, error); this.logger.error("Stream text error", { error: mastraError, runId, threadId, resourceId, modelId: model.modelId, modelProvider: model.provider }); llmSpan?.error({ error: mastraError }); }, ...rest, messages, experimental_output: schema ? output_exports.object({ schema }) : void 0 }; try { return executeWithContextSync({ span: llmSpan, fn: () => streamText(argsForExecute) }); } catch (e) { const mastraError = new MastraError({ id: "LLM_STREAM_TEXT_AI_SDK_EXECUTION_FAILED", domain: ErrorDomain.LLM, category: ErrorCategory.THIRD_PARTY, details: { modelId: model.modelId, modelProvider: model.provider, runId: runId ?? "unknown", threadId: threadId ?? "unknown", resourceId: resourceId ?? "unknown" } }, e); this.logger.error("Stream text failed", { error: mastraError, runId, threadId, resourceId, modelId: model.modelId, modelProvider: model.provider }); llmSpan?.error({ error: mastraError }); throw mastraError; } } __streamObject({ messages, runId, requestContext, threadId, resourceId, onFinish, structuredOutput, ...rest }) { const model = this.#model; const observabilityContext = resolveObservabilityContext(rest); this.logger.debug("Streaming structured output", { runId, messages }); const llmSpan = observabilityContext.tracingContext.currentSpan?.createChildSpan({ name: `llm: '${model.modelId}'`, type: "model_generation", input: { messages }, attributes: { model: model.modelId, provider: model.provider, parameters: { temperature: rest.temperature, maxOutputTokens: rest.maxTokens, topP: rest.topP, frequencyPenalty: rest.frequencyPenalty, presencePenalty: rest.presencePenalty }, streaming: true }, metadata: { runId, threadId, resourceId }, tracingPolicy: this.#options?.tracingPolicy, requestContext }); try { let output = "object"; if (isZodArray(structuredOutput)) { output = "array"; structuredOutput = getZodDef(structuredOutput).type; } const processedSchema = this._applySchemaCompat(structuredOutput); llmSpan?.update({ input: { messages, schema: processedSchema } }); const argsForExecute = { ...rest, model, onFinish: async (props) => { llmSpan?.end({ output: { text: props?.text, object: props?.object, reasoning: props?.reasoningDetails, reasoningText: props?.reasoning, files: props?.files, sources: props?.sources, warnings: props?.warnings }, attributes: { finishReason: props?.finishReason, usage: props?.usage } }); try { await onFinish?.({ ...props, runId }); } catch (e) { const mastraError = new MastraError({ id: "LLM_STREAM_OBJECT_ON_FINISH_CALLBACK_EXECUTION_FAILED", domain: ErrorDomain.LLM, category: ErrorCategory.USER, details: { modelId: model.modelId, modelProvider: model.provider, runId: runId ?? "unknown", threadId: threadId ?? "unknown", resourceId: resourceId ?? "unknown", toolCalls: "", toolResults: "", finishReason: "", usage: props?.usage ? JSON.stringify(props.usage) : "" } }, e); this.logger.trackException(mastraError); llmSpan?.error({ error: mastraError }); throw mastraError; } this.logger.debug("Object stream finished", { usage: props?.usage, runId, threadId, resourceId }); }, onError: ({ error }) => { const mastraError = new MastraError({ id: "LLM_STREAM_OBJECT_AI_SDK_STREAMING_ERROR", domain: ErrorDomain.LLM, category: ErrorCategory.THIRD_PARTY, details: { modelId: model.modelId, modelProvider: model.provider, runId: runId ?? "unknown", threadId: threadId ?? "unknown", resourceId: resourceId ?? "unknown" } }, error); this.logger.error("Stream object error", { error: mastraError, runId, threadId, resourceId, modelId: model.modelId, modelProvider: model.provider }); llmSpan?.error({ error: mastraError }); }, messages, output, schema: processedSchema }; try { return streamObject(argsForExecute); } catch (e) { const mastraError = new MastraError({ id: "LLM_STREAM_OBJECT_AI_SDK_EXECUTION_FAILED", domain: ErrorDomain.LLM, category: ErrorCategory.THIRD_PARTY, details: { modelId: model.modelId, modelProvider: model.provider, runId: runId ?? "unknown", threadId: threadId ?? "unknown", resourceId: resourceId ?? "unknown" } }, e); this.logger.error("Stream object failed", { error: mastraError, runId, threadId, resourceId, modelId: model.modelId, modelProvider: model.provider }); llmSpan?.error({ error: mastraError }); throw mastraError; } } catch (e) { if (e instanceof MastraError) { llmSpan?.error({ error: e }); throw e; } const mastraError = new MastraError({ id: "LLM_STREAM_OBJECT_AI_SDK_SCHEMA_CONVERSION_FAILED", domain: ErrorDomain.LLM, category: ErrorCategory.USER, details: { modelId: model.modelId, modelProvider: model.provider, runId: runId ?? "unknown", threadId: threadId ?? "unknown", resourceId: resourceId ?? "unknown" } }, e); this.logger.error("Stream object schema conversion failed", { error: mastraError, runId, threadId, resourceId, modelId: model.modelId, modelProvider: model.provider }); llmSpan?.error({ error: mastraError }); throw mastraError; } } convertToMessages(messages) { if (Array.isArray(messages)) return messages.map((m) => { if (typeof m === "string") return { role: "user", content: m }; return m; }); return [{ role: "user", content: messages }]; } async generate(messages, args) { const msgs = this.convertToMessages(messages); const { output, ...rest } = args ?? {}; if (!output) return await this.__text({ messages: msgs, ...rest }); return await this.__textObject({ messages: msgs, structuredOutput: output, ...rest }); } stream(messages, args) { const msgs = this.convertToMessages(messages); const { output, ...rest } = args ?? {}; if (!output) { const { maxSteps = 5, onFinish, ...streamRest } = rest; return this.__stream({ messages: msgs, maxSteps, onFinish, ...streamRest }); } const { onFinish, ...objectRest } = rest; return this.__streamObject({ messages: msgs, structuredOutput: output, onFinish, ...objectRest }); } }; //#endregion export { MastraLLMV1 as t }; //# sourceMappingURL=model-Bj_6H9X0.js.map