UNPKG

@ai-sdk/google

Version:
151 lines (133 loc) • 3.29 kB
import type { LanguageModelV4Prompt, LanguageModelV4ToolResultOutput, } from '@ai-sdk/provider'; import { type FetchFunction, detectMediaType, downloadBlob, isFullMediaType, isUrlSupported, } from '@ai-sdk/provider-utils'; /** * Download tool result file URLs that Vertex cannot reference directly before * converting the prompt to the Google request format. */ export async function downloadToolResultFiles( prompt: LanguageModelV4Prompt, { abortSignal, fetch, maxBytes, supportedUrls = {}, }: { abortSignal: AbortSignal | undefined; fetch?: FetchFunction; maxBytes: number; supportedUrls?: Record<string, RegExp[]>; }, ): Promise<LanguageModelV4Prompt> { const result: LanguageModelV4Prompt = []; for (const message of prompt) { if (message.role === 'assistant') { const content: typeof message.content = []; for (const part of message.content) { content.push( part.type === 'tool-result' ? { ...part, output: await downloadToolResultOutput(part.output, { abortSignal, fetch, maxBytes, supportedUrls, }), } : part, ); } result.push({ ...message, content }); continue; } if (message.role === 'tool') { const content: typeof message.content = []; for (const part of message.content) { if (part.type !== 'tool-result') { content.push(part); continue; } content.push({ ...part, output: await downloadToolResultOutput(part.output, { abortSignal, fetch, maxBytes, supportedUrls, }), }); } result.push({ ...message, content }); continue; } result.push(message); } return result; } async function downloadToolResultOutput( output: LanguageModelV4ToolResultOutput, { abortSignal, fetch, maxBytes, supportedUrls, }: { abortSignal: AbortSignal | undefined; fetch?: FetchFunction; maxBytes: number; supportedUrls: Record<string, RegExp[]>; }, ): Promise<LanguageModelV4ToolResultOutput> { if (output.type !== 'content') { return output; } const value: typeof output.value = []; for (const part of output.value) { if (part.type !== 'file' || part.data.type !== 'url') { value.push(part); continue; } if ( isUrlSupported({ url: part.data.url.toString(), mediaType: part.mediaType, supportedUrls, }) ) { value.push(part); continue; } const blob = await downloadBlob(part.data.url.toString(), { abortSignal, fetch, maxBytes, }); const data = new Uint8Array(await blob.arrayBuffer()); const detectedMediaType = detectMediaType({ data, topLevelType: 'image', }); value.push({ ...part, data: { type: 'data' as const, data }, mediaType: detectedMediaType ?? (blob.type && !isFullMediaType(part.mediaType) ? blob.type : part.mediaType), }); } return { ...output, value, }; }