@mastra/core
Version:
790 lines (789 loc) • 23.1 kB
JavaScript
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