UNPKG

@mastra/core

Version:
237 lines (236 loc) • 6.88 kB
let crypto = require("crypto"); //#region src/llm/model/aisdk/generate-to-stream.ts /** * Converts a doGenerate result to a ReadableStream format. * This is shared between V2 and V3 model wrappers since the content/result structure is compatible. */ function createStreamFromGenerateResult(result) { return new ReadableStream({ start(controller) { controller.enqueue({ type: "stream-start", warnings: result.warnings }); controller.enqueue({ type: "response-metadata", id: result.response?.id, modelId: result.response?.modelId, timestamp: result.response?.timestamp }); const toolCallMeta = {}; for (const message of result.content) if (message.type === "tool-call") { const toolCall = message; toolCallMeta[toolCall.toolCallId] = { providerExecuted: toolCall.providerExecuted }; controller.enqueue({ type: "tool-input-start", id: toolCall.toolCallId, toolName: toolCall.toolName, providerExecuted: toolCall.providerExecuted, dynamic: toolCall.dynamic, providerMetadata: toolCall.providerMetadata }); controller.enqueue({ type: "tool-input-delta", id: toolCall.toolCallId, delta: toolCall.input, providerMetadata: toolCall.providerMetadata }); controller.enqueue({ type: "tool-input-end", id: toolCall.toolCallId, providerMetadata: toolCall.providerMetadata }); controller.enqueue(toolCall); } else if (message.type === "tool-result") { const toolResult = message; const meta = toolCallMeta[toolResult.toolCallId]; if (meta?.providerExecuted) controller.enqueue({ ...toolResult, providerExecuted: meta.providerExecuted }); else controller.enqueue(message); } else if (message.type === "text") { const text = message; const id = `msg_${(0, crypto.randomUUID)()}`; controller.enqueue({ type: "text-start", id, providerMetadata: text.providerMetadata }); controller.enqueue({ type: "text-delta", id, delta: text.text }); controller.enqueue({ type: "text-end", id }); } else if (message.type === "reasoning") { const id = `reasoning_${(0, crypto.randomUUID)()}`; const reasoning = message; controller.enqueue({ type: "reasoning-start", id, providerMetadata: reasoning.providerMetadata }); controller.enqueue({ type: "reasoning-delta", id, delta: reasoning.text, providerMetadata: reasoning.providerMetadata }); controller.enqueue({ type: "reasoning-end", id, providerMetadata: reasoning.providerMetadata }); } else if (message.type === "file") { const file = message; controller.enqueue({ type: "file", mediaType: file.mediaType, data: file.data }); } else if (message.type === "source") { const source = message; if (source.sourceType === "url") controller.enqueue({ type: "source", id: source.id, sourceType: "url", url: source.url, title: source.title, providerMetadata: source.providerMetadata }); else controller.enqueue({ type: "source", id: source.id, sourceType: "document", mediaType: source.mediaType, filename: source.filename, title: source.title, providerMetadata: source.providerMetadata }); } controller.enqueue({ type: "finish", finishReason: result.finishReason, usage: result.usage, providerMetadata: result.providerMetadata }); controller.close(); } }); } //#endregion //#region src/llm/model/aisdk/v5/model.ts /** * Strips per-tool `strict` from function tools (V2 providers don't support it) * and, when any tool had `strict: true`, injects `strictJsonSchema: true` into * the OpenAI provider options so the V2 OpenAI provider enables strict mode * globally for all tools. */ function applyStrictForV2(options) { if (!options.tools?.length) return options; let hasStrictTool = false; const sanitizedTools = options.tools.map((tool) => { if (tool.type !== "function" || !("strict" in tool)) return tool; if (tool.strict === true) hasStrictTool = true; const { strict: _strict, ...rest } = tool; return rest; }); let result = { ...options, tools: sanitizedTools }; if (hasStrictTool) { const existingOpenai = options.providerOptions?.openai ?? {}; if (existingOpenai.strictJsonSchema == null) result = { ...result, providerOptions: { ...options.providerOptions, openai: { ...existingOpenai, strictJsonSchema: true } } }; } return result; } /** * Wrapper class for AI SDK V5 (LanguageModelV2) that converts doGenerate to return * a stream format for consistency with Mastra's streaming architecture. */ var AISDKV5LanguageModel = class { /** * The language model must specify which language model interface version it implements. */ specificationVersion = "v2"; /** * Name of the provider for logging purposes. */ provider; /** * Provider-specific model ID for logging purposes. */ modelId; gatewayId; /** * Supported URL patterns by media type for the provider. * * The keys are media type patterns or full media types (e.g. `*\/*` for everything, `audio/*`, `video/*`, or `application/pdf`). * and the values are arrays of regular expressions that match the URL paths. * The matching should be against lower-case URLs. * Matched URLs are supported natively by the model and are not downloaded. * @returns A map of supported URL patterns by media type (as a promise or a plain object). */ supportedUrls; #model; constructor(config) { this.#model = config; this.provider = this.#model.provider; this.modelId = this.#model.modelId; this.gatewayId = config.gatewayId; this.supportedUrls = this.#model.supportedUrls; } async doGenerate(options) { const result = await this.#model.doGenerate(applyStrictForV2(options)); return { ...result, request: result.request, response: result.response, stream: createStreamFromGenerateResult(result) }; } async doStream(options) { return await this.#model.doStream(applyStrictForV2(options)); } /** * Custom serialization for tracing/observability spans. * `#model` is already a true JS private field and not enumerable, so * the wrapped provider SDK client can't leak. This method makes the * safe shape explicit and avoids walking `supportedUrls` (a * PromiseLike / regex map that isn't useful in spans). */ serializeForSpan() { return { specificationVersion: this.specificationVersion, modelId: this.modelId, provider: this.provider, gatewayId: this.gatewayId }; } }; //#endregion Object.defineProperty(exports, "AISDKV5LanguageModel", { enumerable: true, get: function() { return AISDKV5LanguageModel; } }); Object.defineProperty(exports, "createStreamFromGenerateResult", { enumerable: true, get: function() { return createStreamFromGenerateResult; } }); //# sourceMappingURL=model-CxJfDXLP.cjs.map