@ai-sdk/google
Advanced tools
@@ -140,7 +140,8 @@ import * as _ai_sdk_provider_utils from '@ai-sdk/provider-utils'; | ||
| tools: ({ | ||
| functionDeclarations: Array<{ | ||
| functionDeclarations: { | ||
| name: string; | ||
| description: string; | ||
| parameters: unknown; | ||
| }>; | ||
| parameters?: unknown; | ||
| parametersJsonSchema?: unknown; | ||
| }[]; | ||
| } | Record<string, any>)[] | undefined; | ||
@@ -147,0 +148,0 @@ toolConfig: { |
+2
-2
| { | ||
| "name": "@ai-sdk/google", | ||
| "version": "4.0.51", | ||
| "version": "4.0.53", | ||
| "type": "module", | ||
@@ -39,3 +39,3 @@ "license": "Apache-2.0", | ||
| "@ai-sdk/provider": "4.0.8", | ||
| "@ai-sdk/provider-utils": "5.0.30" | ||
| "@ai-sdk/provider-utils": "5.0.32" | ||
| }, | ||
@@ -42,0 +42,0 @@ "devDependencies": { |
@@ -17,2 +17,14 @@ import { | ||
| const recursiveReferenceFunctionalityPrefix = | ||
| 'recursive JSON Schema reference:'; | ||
| export function isRecursiveJSONSchemaReferenceError( | ||
| error: unknown, | ||
| ): error is UnsupportedFunctionalityError { | ||
| return ( | ||
| UnsupportedFunctionalityError.isInstance(error) && | ||
| error.functionality.startsWith(recursiveReferenceFunctionalityPrefix) | ||
| ); | ||
| } | ||
| /** | ||
@@ -209,3 +221,3 @@ * Converts JSON Schema 7 to OpenAPI Schema 3.0 | ||
| throw new UnsupportedFunctionalityError({ | ||
| functionality: `recursive JSON Schema reference: ${reference}`, | ||
| functionality: `${recursiveReferenceFunctionalityPrefix} ${reference}`, | ||
| message: | ||
@@ -212,0 +224,0 @@ 'Google schema conversion does not support recursive JSON Schema references.', |
+9
-78
| import { | ||
| EmptyResponseBodyError, | ||
| InvalidArgumentError, | ||
@@ -17,2 +16,3 @@ InvalidResponseDataError, | ||
| convertAsyncIteratorToReadableStream, | ||
| createJsonLinesResponseHandler, | ||
| createJsonResponseHandler, | ||
@@ -22,3 +22,3 @@ generateId, | ||
| lazySchema, | ||
| parseJSON, | ||
| normalizeBatchRequestCounts, | ||
| postJsonToApi, | ||
@@ -404,7 +404,9 @@ postToApi, | ||
| const { value: stream } = await getFromApi({ | ||
| const { value: lines } = await getFromApi({ | ||
| url: `${this.getBaseOrigin()}/download/v1beta/${encodedResponsesFile}:download?alt=media`, | ||
| headers: await this.getHeaders(options.headers), | ||
| failedResponseHandler: googleFailedResponseHandler, | ||
| successfulResponseHandler: rawStreamResponseHandler, | ||
| successfulResponseHandler: createJsonLinesResponseHandler( | ||
| googleBatchResultLineSchema, | ||
| ), | ||
| abortSignal: options.abortSignal, | ||
@@ -416,3 +418,3 @@ fetch: this.batchConfig.fetch, | ||
| return convertAsyncIteratorToReadableStream( | ||
| this.iterateBatchResults(parseJsonLines(stream)), | ||
| this.iterateBatchResults(lines), | ||
| ); | ||
@@ -633,13 +635,3 @@ } | ||
| if ( | ||
| total == null || | ||
| completed == null || | ||
| failed == null || | ||
| pending == null || | ||
| completed + failed + pending !== total | ||
| ) { | ||
| return undefined; | ||
| } | ||
| return { | ||
| return normalizeBatchRequestCounts({ | ||
| total, | ||
@@ -649,3 +641,3 @@ pending, | ||
| failed, | ||
| }; | ||
| }); | ||
| } | ||
@@ -685,62 +677,1 @@ | ||
| }; | ||
| const rawStreamResponseHandler: ResponseHandler< | ||
| ReadableStream<Uint8Array> | ||
| > = async ({ response }) => { | ||
| if (response.body == null) { | ||
| throw new EmptyResponseBodyError(); | ||
| } | ||
| return { value: response.body }; | ||
| }; | ||
| async function* parseJsonLines( | ||
| stream: ReadableStream<Uint8Array>, | ||
| ): AsyncGenerator<GoogleBatchResultLine> { | ||
| const reader = stream.getReader(); | ||
| const decoder = new TextDecoder(); | ||
| let buffer = ''; | ||
| let finished = false; | ||
| try { | ||
| while (true) { | ||
| const { done, value } = await reader.read(); | ||
| if (done) { | ||
| finished = true; | ||
| buffer += decoder.decode(); | ||
| break; | ||
| } | ||
| buffer += decoder.decode(value, { stream: true }); | ||
| let lineEnd = buffer.indexOf('\n'); | ||
| while (lineEnd !== -1) { | ||
| const line = buffer.slice(0, lineEnd).replace(/\r$/, ''); | ||
| buffer = buffer.slice(lineEnd + 1); | ||
| if (line.trim().length > 0) { | ||
| yield await parseJSON({ | ||
| text: line, | ||
| schema: googleBatchResultLineSchema, | ||
| }); | ||
| } | ||
| lineEnd = buffer.indexOf('\n'); | ||
| } | ||
| } | ||
| const finalLine = buffer.replace(/\r$/, ''); | ||
| if (finalLine.trim().length > 0) { | ||
| yield await parseJSON({ | ||
| text: finalLine, | ||
| schema: googleBatchResultLineSchema, | ||
| }); | ||
| } | ||
| } finally { | ||
| if (!finished) { | ||
| await reader.cancel().catch(() => {}); | ||
| } | ||
| reader.releaseLock(); | ||
| } | ||
| } |
+27
-2
@@ -37,2 +37,13 @@ import { | ||
| function encodePathSegment(value: string): string { | ||
| const encodedValue = encodeURIComponent(value); | ||
| // URL parsing normalizes both literal and percent-encoded dot segments. | ||
| return encodedValue === '.' | ||
| ? '%252E' | ||
| : encodedValue === '..' | ||
| ? '%252E%252E' | ||
| : encodedValue; | ||
| } | ||
| export class GoogleFiles implements FilesV4 { | ||
@@ -110,3 +121,3 @@ readonly specificationVersion = 'v4'; | ||
| }, | ||
| body: fileBytes, | ||
| body: ensureArrayBufferBacked(fileBytes), | ||
| }); | ||
@@ -142,4 +153,10 @@ | ||
| const fileNameMatch = /^files\/([^/]+)$/.exec(file.name); | ||
| const filePath = | ||
| fileNameMatch != null | ||
| ? `files/${encodePathSegment(fileNameMatch[1])}` | ||
| : encodePathSegment(file.name); | ||
| const { value: fileStatus } = await getFromApi({ | ||
| url: `${this.config.baseURL}/${file.name}`, | ||
| url: `${this.config.baseURL}/${filePath}`, | ||
| validateUrl: false, | ||
@@ -188,2 +205,10 @@ headers: combineHeaders(resolvedHeaders), | ||
| function ensureArrayBufferBacked(data: Uint8Array): Uint8Array<ArrayBuffer> { | ||
| if (data.buffer instanceof ArrayBuffer) { | ||
| return data as Uint8Array<ArrayBuffer>; | ||
| } | ||
| return new Uint8Array(data); | ||
| } | ||
| type GoogleFileResource = { | ||
@@ -190,0 +215,0 @@ name: string; |
@@ -6,6 +6,21 @@ import { | ||
| } from '@ai-sdk/provider'; | ||
| import { convertJSONSchemaToOpenAPISchema } from './convert-json-schema-to-openapi-schema'; | ||
| import { | ||
| convertJSONSchemaToOpenAPISchema, | ||
| isRecursiveJSONSchemaReferenceError, | ||
| } from './convert-json-schema-to-openapi-schema'; | ||
| import type { GoogleModelId } from './google-language-model-options'; | ||
| import { getGoogleModelCapabilities } from './google-model-capabilities'; | ||
| type FunctionTool = Extract< | ||
| NonNullable<LanguageModelV4CallOptions['tools']>[number], | ||
| { type: 'function' } | ||
| >; | ||
| type GoogleFunctionDeclaration = { | ||
| name: string; | ||
| description: string; | ||
| parameters?: unknown; | ||
| parametersJsonSchema?: unknown; | ||
| }; | ||
| export function prepareTools({ | ||
@@ -25,7 +40,3 @@ tools, | ||
| | { | ||
| functionDeclarations: Array<{ | ||
| name: string; | ||
| description: string; | ||
| parameters: unknown; | ||
| }>; | ||
| functionDeclarations: GoogleFunctionDeclaration[]; | ||
| } | ||
@@ -177,14 +188,6 @@ | Record<string, any> | ||
| if (hasFunctionTools && usesGemini3Features && googleTools.length > 0) { | ||
| const functionDeclarations: Array<{ | ||
| name: string; | ||
| description: string; | ||
| parameters: unknown; | ||
| }> = []; | ||
| const functionDeclarations: GoogleFunctionDeclaration[] = []; | ||
| for (const tool of tools) { | ||
| if (tool.type === 'function') { | ||
| functionDeclarations.push({ | ||
| name: tool.name, | ||
| description: tool.description ?? '', | ||
| parameters: convertJSONSchemaToOpenAPISchema(tool.inputSchema), | ||
| }); | ||
| functionDeclarations.push(prepareFunctionDeclaration(tool)); | ||
| } | ||
@@ -244,7 +247,3 @@ } | ||
| case 'function': | ||
| functionDeclarations.push({ | ||
| name: tool.name, | ||
| description: tool.description ?? '', | ||
| parameters: convertJSONSchemaToOpenAPISchema(tool.inputSchema), | ||
| }); | ||
| functionDeclarations.push(prepareFunctionDeclaration(tool)); | ||
| if (tool.strict === true) { | ||
@@ -321,1 +320,26 @@ hasStrictTools = true; | ||
| } | ||
| function prepareFunctionDeclaration( | ||
| tool: FunctionTool, | ||
| ): GoogleFunctionDeclaration { | ||
| const declaration = { | ||
| name: tool.name, | ||
| description: tool.description ?? '', | ||
| }; | ||
| try { | ||
| return { | ||
| ...declaration, | ||
| parameters: convertJSONSchemaToOpenAPISchema(tool.inputSchema), | ||
| }; | ||
| } catch (error) { | ||
| if (!isRecursiveJSONSchemaReferenceError(error)) { | ||
| throw error; | ||
| } | ||
| return { | ||
| ...declaration, | ||
| parametersJsonSchema: tool.inputSchema, | ||
| }; | ||
| } | ||
| } |
@@ -9,3 +9,6 @@ import type { | ||
| } from '@ai-sdk/provider'; | ||
| import type { ParseResult } from '@ai-sdk/provider-utils'; | ||
| import { | ||
| createProviderStreamError, | ||
| type ParseResult, | ||
| } from '@ai-sdk/provider-utils'; | ||
| import type { | ||
@@ -825,6 +828,11 @@ GoogleInteractionsEvent, | ||
| finishStatus = 'failed'; | ||
| const errorPayload = event.error ?? { | ||
| message: 'Unknown interaction error', | ||
| }; | ||
| controller.enqueue({ type: 'error', error: errorPayload }); | ||
| controller.enqueue({ | ||
| type: 'error', | ||
| error: createProviderStreamError({ | ||
| message: event.error?.message ?? 'Unknown interaction error', | ||
| type: event.event_type, | ||
| code: event.error?.code ?? undefined, | ||
| data: event, | ||
| }), | ||
| }); | ||
| break; | ||
@@ -831,0 +839,0 @@ } |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
2220970
0.15%28480
0.05%+ Added
- Removed