@tanstack/ai-gemini 0.10.7 → 0.10.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/adapters/audio.d.ts +1 -1
- package/dist/esm/adapters/audio.js +3 -2
- package/dist/esm/adapters/audio.js.map +1 -1
- package/dist/esm/adapters/image.d.ts +1 -1
- package/dist/esm/adapters/image.js +13 -8
- package/dist/esm/adapters/image.js.map +1 -1
- package/dist/esm/adapters/text.d.ts +1 -1
- package/dist/esm/adapters/text.js +45 -25
- package/dist/esm/adapters/text.js.map +1 -1
- package/dist/esm/adapters/tts.d.ts +1 -1
- package/dist/esm/adapters/tts.js +6 -5
- package/dist/esm/adapters/tts.js.map +1 -1
- package/dist/esm/image/image-provider-options.js +3 -2
- package/dist/esm/image/image-provider-options.js.map +1 -1
- package/dist/esm/model-meta.d.ts +23 -1
- package/dist/esm/model-meta.js +5 -1
- package/dist/esm/model-meta.js.map +1 -1
- package/dist/esm/tools/code-execution-tool.js +3 -2
- package/dist/esm/tools/code-execution-tool.js.map +1 -1
- package/dist/esm/tools/computer-use-tool.d.ts +2 -2
- package/dist/esm/tools/computer-use-tool.js +15 -6
- package/dist/esm/tools/computer-use-tool.js.map +1 -1
- package/dist/esm/tools/file-search-tool.js +3 -2
- package/dist/esm/tools/file-search-tool.js.map +1 -1
- package/dist/esm/tools/function-declaration-tool.js +1 -2
- package/dist/esm/tools/function-declaration-tool.js.map +1 -1
- package/dist/esm/tools/google-maps-tool.js +3 -2
- package/dist/esm/tools/google-maps-tool.js.map +1 -1
- package/dist/esm/tools/google-search-retriveal-tool.js +3 -2
- package/dist/esm/tools/google-search-retriveal-tool.js.map +1 -1
- package/dist/esm/tools/google-search-tool.js +3 -2
- package/dist/esm/tools/google-search-tool.js.map +1 -1
- package/dist/esm/tools/url-context-tool.js +3 -2
- package/dist/esm/tools/url-context-tool.js.map +1 -1
- package/package.json +3 -3
- package/src/adapters/audio.ts +2 -2
- package/src/adapters/image.ts +13 -6
- package/src/adapters/text.ts +69 -37
- package/src/adapters/tts.ts +7 -6
- package/src/image/image-provider-options.ts +3 -2
- package/src/model-meta.ts +43 -0
- package/src/tools/code-execution-tool.ts +3 -3
- package/src/tools/computer-use-tool.ts +18 -7
- package/src/tools/file-search-tool.ts +3 -3
- package/src/tools/function-declaration-tool.ts +1 -2
- package/src/tools/google-maps-tool.ts +3 -3
- package/src/tools/google-search-retriveal-tool.ts +3 -3
- package/src/tools/google-search-tool.ts +3 -3
- package/src/tools/url-context-tool.ts +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"google-search-retriveal-tool.js","sources":["../../../src/tools/google-search-retriveal-tool.ts"],"sourcesContent":["import type { GoogleSearchRetrieval } from '@google/genai'\nimport type { ProviderTool, Tool } from '@tanstack/ai'\n\nexport type GoogleSearchRetrievalToolConfig = GoogleSearchRetrieval\n\n/** @deprecated Renamed to `GoogleSearchRetrievalToolConfig`. Will be removed in a future release. */\nexport type GoogleSearchRetrievalTool = GoogleSearchRetrievalToolConfig\n\nexport type GeminiGoogleSearchRetrievalTool = ProviderTool<\n 'gemini',\n 'google_search_retrieval'\n>\n\nexport function convertGoogleSearchRetrievalToolToAdapterFormat(tool: Tool) {\n const metadata = tool.metadata as GoogleSearchRetrievalToolConfig\n return {\n googleSearchRetrieval: metadata,\n }\n}\n\nexport function googleSearchRetrievalTool(\n config?: GoogleSearchRetrievalToolConfig,\n): GeminiGoogleSearchRetrievalTool {\n
|
|
1
|
+
{"version":3,"file":"google-search-retriveal-tool.js","sources":["../../../src/tools/google-search-retriveal-tool.ts"],"sourcesContent":["import { brandProviderTool } from '@tanstack/ai'\nimport type { GoogleSearchRetrieval } from '@google/genai'\nimport type { ProviderTool, Tool } from '@tanstack/ai'\n\nexport type GoogleSearchRetrievalToolConfig = GoogleSearchRetrieval\n\n/** @deprecated Renamed to `GoogleSearchRetrievalToolConfig`. Will be removed in a future release. */\nexport type GoogleSearchRetrievalTool = GoogleSearchRetrievalToolConfig\n\nexport type GeminiGoogleSearchRetrievalTool = ProviderTool<\n 'gemini',\n 'google_search_retrieval'\n>\n\nexport function convertGoogleSearchRetrievalToolToAdapterFormat(tool: Tool) {\n const metadata = tool.metadata as GoogleSearchRetrievalToolConfig\n return {\n googleSearchRetrieval: metadata,\n }\n}\n\nexport function googleSearchRetrievalTool(\n config?: GoogleSearchRetrievalToolConfig,\n): GeminiGoogleSearchRetrievalTool {\n return brandProviderTool<GeminiGoogleSearchRetrievalTool>({\n name: 'google_search_retrieval',\n description: '',\n metadata: config,\n })\n}\n"],"names":[],"mappings":";AAcO,SAAS,gDAAgD,MAAY;AAC1E,QAAM,WAAW,KAAK;AACtB,SAAO;AAAA,IACL,uBAAuB;AAAA,EAAA;AAE3B;AAEO,SAAS,0BACd,QACiC;AACjC,SAAO,kBAAmD;AAAA,IACxD,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,EAAA,CACX;AACH;"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { brandProviderTool } from "@tanstack/ai";
|
|
1
2
|
function convertGoogleSearchToolToAdapterFormat(tool) {
|
|
2
3
|
const metadata = tool.metadata;
|
|
3
4
|
return {
|
|
@@ -5,11 +6,11 @@ function convertGoogleSearchToolToAdapterFormat(tool) {
|
|
|
5
6
|
};
|
|
6
7
|
}
|
|
7
8
|
function googleSearchTool(config) {
|
|
8
|
-
return {
|
|
9
|
+
return brandProviderTool({
|
|
9
10
|
name: "google_search",
|
|
10
11
|
description: "",
|
|
11
12
|
metadata: config
|
|
12
|
-
};
|
|
13
|
+
});
|
|
13
14
|
}
|
|
14
15
|
export {
|
|
15
16
|
convertGoogleSearchToolToAdapterFormat,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"google-search-tool.js","sources":["../../../src/tools/google-search-tool.ts"],"sourcesContent":["import type { GoogleSearch } from '@google/genai'\nimport type { ProviderTool, Tool } from '@tanstack/ai'\n\nexport type GoogleSearchToolConfig = GoogleSearch\n\n/** @deprecated Renamed to `GoogleSearchToolConfig`. Will be removed in a future release. */\nexport type GoogleSearchTool = GoogleSearchToolConfig\n\nexport type GeminiGoogleSearchTool = ProviderTool<'gemini', 'google_search'>\n\nexport function convertGoogleSearchToolToAdapterFormat(tool: Tool) {\n const metadata = tool.metadata as GoogleSearchToolConfig\n return {\n googleSearch: metadata,\n }\n}\n\nexport function googleSearchTool(\n config?: GoogleSearchToolConfig,\n): GeminiGoogleSearchTool {\n
|
|
1
|
+
{"version":3,"file":"google-search-tool.js","sources":["../../../src/tools/google-search-tool.ts"],"sourcesContent":["import { brandProviderTool } from '@tanstack/ai'\nimport type { GoogleSearch } from '@google/genai'\nimport type { ProviderTool, Tool } from '@tanstack/ai'\n\nexport type GoogleSearchToolConfig = GoogleSearch\n\n/** @deprecated Renamed to `GoogleSearchToolConfig`. Will be removed in a future release. */\nexport type GoogleSearchTool = GoogleSearchToolConfig\n\nexport type GeminiGoogleSearchTool = ProviderTool<'gemini', 'google_search'>\n\nexport function convertGoogleSearchToolToAdapterFormat(tool: Tool) {\n const metadata = tool.metadata as GoogleSearchToolConfig\n return {\n googleSearch: metadata,\n }\n}\n\nexport function googleSearchTool(\n config?: GoogleSearchToolConfig,\n): GeminiGoogleSearchTool {\n return brandProviderTool<GeminiGoogleSearchTool>({\n name: 'google_search',\n description: '',\n metadata: config,\n })\n}\n"],"names":[],"mappings":";AAWO,SAAS,uCAAuC,MAAY;AACjE,QAAM,WAAW,KAAK;AACtB,SAAO;AAAA,IACL,cAAc;AAAA,EAAA;AAElB;AAEO,SAAS,iBACd,QACwB;AACxB,SAAO,kBAA0C;AAAA,IAC/C,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,EAAA,CACX;AACH;"}
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
+
import { brandProviderTool } from "@tanstack/ai";
|
|
1
2
|
function convertUrlContextToolToAdapterFormat(_tool) {
|
|
2
3
|
return {
|
|
3
4
|
urlContext: {}
|
|
4
5
|
};
|
|
5
6
|
}
|
|
6
7
|
function urlContextTool() {
|
|
7
|
-
return {
|
|
8
|
+
return brandProviderTool({
|
|
8
9
|
name: "url_context",
|
|
9
10
|
description: "",
|
|
10
11
|
metadata: {}
|
|
11
|
-
};
|
|
12
|
+
});
|
|
12
13
|
}
|
|
13
14
|
export {
|
|
14
15
|
convertUrlContextToolToAdapterFormat,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"url-context-tool.js","sources":["../../../src/tools/url-context-tool.ts"],"sourcesContent":["import type { ProviderTool, Tool } from '@tanstack/ai'\n\nexport interface UrlContextToolConfig {}\n\n/** @deprecated Renamed to `UrlContextToolConfig`. Will be removed in a future release. */\nexport type UrlContextTool = UrlContextToolConfig\n\nexport type GeminiUrlContextTool = ProviderTool<'gemini', 'url_context'>\n\nexport function convertUrlContextToolToAdapterFormat(_tool: Tool) {\n return {\n urlContext: {},\n }\n}\n\nexport function urlContextTool(): GeminiUrlContextTool {\n
|
|
1
|
+
{"version":3,"file":"url-context-tool.js","sources":["../../../src/tools/url-context-tool.ts"],"sourcesContent":["import { brandProviderTool } from '@tanstack/ai'\nimport type { ProviderTool, Tool } from '@tanstack/ai'\n\nexport interface UrlContextToolConfig {}\n\n/** @deprecated Renamed to `UrlContextToolConfig`. Will be removed in a future release. */\nexport type UrlContextTool = UrlContextToolConfig\n\nexport type GeminiUrlContextTool = ProviderTool<'gemini', 'url_context'>\n\nexport function convertUrlContextToolToAdapterFormat(_tool: Tool) {\n return {\n urlContext: {},\n }\n}\n\nexport function urlContextTool(): GeminiUrlContextTool {\n return brandProviderTool<GeminiUrlContextTool>({\n name: 'url_context',\n description: '',\n metadata: {},\n })\n}\n"],"names":[],"mappings":";AAUO,SAAS,qCAAqC,OAAa;AAChE,SAAO;AAAA,IACL,YAAY,CAAA;AAAA,EAAC;AAEjB;AAEO,SAAS,iBAAuC;AACrD,SAAO,kBAAwC;AAAA,IAC7C,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU,CAAA;AAAA,EAAC,CACZ;AACH;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/ai-gemini",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.9",
|
|
4
4
|
"description": "Google Gemini adapter for TanStack AI",
|
|
5
5
|
"author": "",
|
|
6
6
|
"license": "MIT",
|
|
@@ -38,13 +38,13 @@
|
|
|
38
38
|
"@tanstack/ai-utils": "0.2.0"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
|
-
"@tanstack/ai": "^0.
|
|
41
|
+
"@tanstack/ai": "^0.21.0"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@vitest/coverage-v8": "4.0.14",
|
|
45
45
|
"vite": "^7.3.3",
|
|
46
46
|
"zod": "^4.2.0",
|
|
47
|
-
"@tanstack/ai": "0.
|
|
47
|
+
"@tanstack/ai": "0.21.0"
|
|
48
48
|
},
|
|
49
49
|
"scripts": {
|
|
50
50
|
"build": "vite build",
|
package/src/adapters/audio.ts
CHANGED
|
@@ -66,7 +66,7 @@ export class GeminiAudioAdapter<
|
|
|
66
66
|
> extends BaseAudioAdapter<TModel, GeminiAudioProviderOptions> {
|
|
67
67
|
readonly name = 'gemini' as const
|
|
68
68
|
|
|
69
|
-
private client: GoogleGenAI
|
|
69
|
+
private readonly client: GoogleGenAI
|
|
70
70
|
|
|
71
71
|
constructor(config: GeminiAudioConfig, model: TModel) {
|
|
72
72
|
super(model, config)
|
|
@@ -120,7 +120,7 @@ export class GeminiAudioAdapter<
|
|
|
120
120
|
model,
|
|
121
121
|
audio: {
|
|
122
122
|
b64Json: audioPart.inlineData.data,
|
|
123
|
-
contentType,
|
|
123
|
+
...(contentType !== undefined && { contentType }),
|
|
124
124
|
},
|
|
125
125
|
}
|
|
126
126
|
} catch (error) {
|
package/src/adapters/image.ts
CHANGED
|
@@ -61,7 +61,7 @@ export class GeminiImageAdapter<
|
|
|
61
61
|
GeminiImageModelProviderOptionsByName,
|
|
62
62
|
GeminiImageModelSizeByName
|
|
63
63
|
> {
|
|
64
|
-
readonly kind = 'image' as const
|
|
64
|
+
override readonly kind = 'image' as const
|
|
65
65
|
readonly name = 'gemini' as const
|
|
66
66
|
|
|
67
67
|
// Type-only property - never assigned at runtime
|
|
@@ -71,7 +71,7 @@ export class GeminiImageAdapter<
|
|
|
71
71
|
modelSizeByName: GeminiImageModelSizeByName
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
private client: GoogleGenAI
|
|
74
|
+
private readonly client: GoogleGenAI
|
|
75
75
|
|
|
76
76
|
constructor(config: GeminiImageConfig, model: TModel) {
|
|
77
77
|
super(model, config)
|
|
@@ -214,7 +214,6 @@ export class GeminiImageAdapter<
|
|
|
214
214
|
id: generateId(this.name),
|
|
215
215
|
model,
|
|
216
216
|
images,
|
|
217
|
-
usage: undefined,
|
|
218
217
|
}
|
|
219
218
|
}
|
|
220
219
|
|
|
@@ -223,10 +222,14 @@ export class GeminiImageAdapter<
|
|
|
223
222
|
): GenerateImagesConfig {
|
|
224
223
|
const { size, numberOfImages, modelOptions } = options
|
|
225
224
|
|
|
225
|
+
// Build with conditional spreads — under exactOptionalPropertyTypes the
|
|
226
|
+
// vendor `GenerateImagesConfig` fields are `field?: T` (no `| undefined`),
|
|
227
|
+
// so we can only assign the property when we actually have a value.
|
|
228
|
+
const sizeAspectRatio = size ? sizeToAspectRatio(size) : undefined
|
|
226
229
|
return {
|
|
227
230
|
numberOfImages: numberOfImages ?? 1,
|
|
228
231
|
// Map size to aspect ratio if provided (modelOptions.aspectRatio will override)
|
|
229
|
-
|
|
232
|
+
...(sizeAspectRatio !== undefined && { aspectRatio: sizeAspectRatio }),
|
|
230
233
|
...modelOptions,
|
|
231
234
|
}
|
|
232
235
|
}
|
|
@@ -242,7 +245,12 @@ export class GeminiImageAdapter<
|
|
|
242
245
|
for (const item of entries) {
|
|
243
246
|
const b64Json = item.image?.imageBytes
|
|
244
247
|
if (b64Json) {
|
|
245
|
-
images.push({
|
|
248
|
+
images.push({
|
|
249
|
+
b64Json,
|
|
250
|
+
...(item.enhancedPrompt !== undefined && {
|
|
251
|
+
revisedPrompt: item.enhancedPrompt,
|
|
252
|
+
}),
|
|
253
|
+
})
|
|
246
254
|
continue
|
|
247
255
|
}
|
|
248
256
|
// Imagen can drop individual entries with a raiFilteredReason when
|
|
@@ -277,7 +285,6 @@ export class GeminiImageAdapter<
|
|
|
277
285
|
id: generateId(this.name),
|
|
278
286
|
model,
|
|
279
287
|
images,
|
|
280
|
-
usage: undefined,
|
|
281
288
|
}
|
|
282
289
|
}
|
|
283
290
|
}
|
package/src/adapters/text.ts
CHANGED
|
@@ -106,10 +106,10 @@ export class GeminiTextAdapter<
|
|
|
106
106
|
TToolCapabilities,
|
|
107
107
|
GeminiToolCallMetadata
|
|
108
108
|
> {
|
|
109
|
-
readonly kind = 'text' as const
|
|
109
|
+
override readonly kind = 'text' as const
|
|
110
110
|
readonly name = 'gemini' as const
|
|
111
111
|
|
|
112
|
-
private client: GoogleGenAI
|
|
112
|
+
private readonly client: GoogleGenAI
|
|
113
113
|
|
|
114
114
|
constructor(config: GeminiTextConfig, model: TModel) {
|
|
115
115
|
super({}, model)
|
|
@@ -315,10 +315,12 @@ export class GeminiTextAdapter<
|
|
|
315
315
|
|
|
316
316
|
accumulatedThinking += part.text
|
|
317
317
|
|
|
318
|
-
// Spec REASONING content event
|
|
318
|
+
// Spec REASONING content event — reasoningMessageId is set in the
|
|
319
|
+
// hasEmittedStepStarted block above (entered on the same `part.thought` path)
|
|
320
|
+
if (!reasoningMessageId) continue
|
|
319
321
|
yield {
|
|
320
322
|
type: EventType.REASONING_MESSAGE_CONTENT,
|
|
321
|
-
messageId: reasoningMessageId
|
|
323
|
+
messageId: reasoningMessageId,
|
|
322
324
|
delta: part.text,
|
|
323
325
|
model,
|
|
324
326
|
timestamp: Date.now(),
|
|
@@ -399,7 +401,11 @@ export class GeminiTextAdapter<
|
|
|
399
401
|
: JSON.stringify(functionArgs),
|
|
400
402
|
index: nextToolIndex++,
|
|
401
403
|
started: false,
|
|
402
|
-
thoughtSignature
|
|
404
|
+
// Only set thoughtSignature when present — under EOPT, the
|
|
405
|
+
// optional field cannot accept an explicit `undefined`.
|
|
406
|
+
...(partThoughtSignature !== undefined && {
|
|
407
|
+
thoughtSignature: partThoughtSignature,
|
|
408
|
+
}),
|
|
403
409
|
}
|
|
404
410
|
toolCallMap.set(toolCallId, toolCallData)
|
|
405
411
|
} else {
|
|
@@ -617,13 +623,16 @@ export class GeminiTextAdapter<
|
|
|
617
623
|
model,
|
|
618
624
|
timestamp: Date.now(),
|
|
619
625
|
finishReason: toolCallMap.size > 0 ? 'tool_calls' : 'stop',
|
|
620
|
-
usage
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
626
|
+
// RunFinishedEvent.usage is `usage?: {...}` (no `| undefined`) under
|
|
627
|
+
// exactOptionalPropertyTypes; only include it when usageMetadata is
|
|
628
|
+
// present rather than assigning an explicit `undefined`.
|
|
629
|
+
...(chunk.usageMetadata && {
|
|
630
|
+
usage: {
|
|
631
|
+
promptTokens: chunk.usageMetadata.promptTokenCount ?? 0,
|
|
632
|
+
completionTokens: chunk.usageMetadata.candidatesTokenCount ?? 0,
|
|
633
|
+
totalTokens: chunk.usageMetadata.totalTokenCount ?? 0,
|
|
634
|
+
},
|
|
635
|
+
}),
|
|
627
636
|
}
|
|
628
637
|
}
|
|
629
638
|
}
|
|
@@ -707,10 +716,7 @@ export class GeminiTextAdapter<
|
|
|
707
716
|
>)
|
|
708
717
|
: {}
|
|
709
718
|
} catch {
|
|
710
|
-
parsedArgs =
|
|
711
|
-
string,
|
|
712
|
-
unknown
|
|
713
|
-
>
|
|
719
|
+
parsedArgs = {}
|
|
714
720
|
}
|
|
715
721
|
|
|
716
722
|
const thoughtSignature = (
|
|
@@ -744,7 +750,7 @@ export class GeminiTextAdapter<
|
|
|
744
750
|
response: {
|
|
745
751
|
content: msg.content || '',
|
|
746
752
|
},
|
|
747
|
-
}
|
|
753
|
+
},
|
|
748
754
|
})
|
|
749
755
|
}
|
|
750
756
|
|
|
@@ -819,31 +825,57 @@ export class GeminiTextAdapter<
|
|
|
819
825
|
private mapCommonOptionsToGemini(
|
|
820
826
|
options: TextOptions<GeminiTextProviderOptions>,
|
|
821
827
|
) {
|
|
822
|
-
|
|
823
|
-
|
|
828
|
+
// Separate `thinkingConfig` from the other model options so the loose
|
|
829
|
+
// local `thinkingLevel?: keyof typeof ThinkingLevel` type doesn't leak
|
|
830
|
+
// into the SDK config object via the `...modelOpts` spread — we re-add a
|
|
831
|
+
// properly-typed `ThinkingConfig` below.
|
|
832
|
+
const { thinkingConfig, ...modelOpts } = options.modelOptions ?? {}
|
|
833
|
+
// Build the thinkingConfig payload only when the caller actually supplied
|
|
834
|
+
// one. Our local `thinkingLevel` is typed as `keyof typeof ThinkingLevel`
|
|
835
|
+
// (string union) so users can pass plain strings; the SDK target is the
|
|
836
|
+
// `ThinkingLevel` enum, and every field is `field?: T` under EOPT — so we
|
|
837
|
+
// re-emit fields via conditional spreads.
|
|
838
|
+
const mappedThinkingConfig = thinkingConfig
|
|
839
|
+
? {
|
|
840
|
+
...(thinkingConfig.includeThoughts !== undefined && {
|
|
841
|
+
includeThoughts: thinkingConfig.includeThoughts,
|
|
842
|
+
}),
|
|
843
|
+
...(thinkingConfig.thinkingBudget !== undefined && {
|
|
844
|
+
thinkingBudget: thinkingConfig.thinkingBudget,
|
|
845
|
+
}),
|
|
846
|
+
...(thinkingConfig.thinkingLevel
|
|
847
|
+
? {
|
|
848
|
+
thinkingLevel: thinkingConfig.thinkingLevel as ThinkingLevel,
|
|
849
|
+
}
|
|
850
|
+
: {}),
|
|
851
|
+
}
|
|
852
|
+
: undefined
|
|
853
|
+
|
|
854
|
+
const normalizedPrompts = normalizeSystemPrompts(options.systemPrompts)
|
|
855
|
+
const systemInstruction =
|
|
856
|
+
normalizedPrompts.length > 0
|
|
857
|
+
? normalizedPrompts.map((p) => p.content).join('\n')
|
|
858
|
+
: undefined
|
|
859
|
+
|
|
860
|
+
// Vendor `GenerateContentConfig` fields are `field?: T` (no `| undefined`)
|
|
861
|
+
// under EOPT, so spread each common option only when present rather than
|
|
862
|
+
// emitting `field: undefined`s into the wire payload.
|
|
824
863
|
const requestOptions: GenerateContentParameters = {
|
|
825
864
|
model: options.model,
|
|
826
865
|
contents: this.formatMessages(options.messages),
|
|
827
866
|
config: {
|
|
828
867
|
...modelOpts,
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
: undefined,
|
|
841
|
-
systemInstruction: (() => {
|
|
842
|
-
const prompts = normalizeSystemPrompts(options.systemPrompts)
|
|
843
|
-
return prompts.length > 0
|
|
844
|
-
? prompts.map((p) => p.content).join('\n')
|
|
845
|
-
: undefined
|
|
846
|
-
})(),
|
|
868
|
+
...(options.temperature !== undefined && {
|
|
869
|
+
temperature: options.temperature,
|
|
870
|
+
}),
|
|
871
|
+
...(options.topP !== undefined && { topP: options.topP }),
|
|
872
|
+
...(options.maxTokens !== undefined && {
|
|
873
|
+
maxOutputTokens: options.maxTokens,
|
|
874
|
+
}),
|
|
875
|
+
...(mappedThinkingConfig !== undefined && {
|
|
876
|
+
thinkingConfig: mappedThinkingConfig,
|
|
877
|
+
}),
|
|
878
|
+
...(systemInstruction !== undefined && { systemInstruction }),
|
|
847
879
|
tools: convertToolsToProviderFormat(options.tools),
|
|
848
880
|
},
|
|
849
881
|
}
|
package/src/adapters/tts.ts
CHANGED
|
@@ -121,7 +121,7 @@ export class GeminiTTSAdapter<
|
|
|
121
121
|
> extends BaseTTSAdapter<TModel, GeminiTTSProviderOptions> {
|
|
122
122
|
readonly name = 'gemini' as const
|
|
123
123
|
|
|
124
|
-
private client: GoogleGenAI
|
|
124
|
+
private readonly client: GoogleGenAI
|
|
125
125
|
|
|
126
126
|
constructor(config: GeminiTTSConfig, model: TModel) {
|
|
127
127
|
super(model, config)
|
|
@@ -251,8 +251,9 @@ export class GeminiTTSAdapter<
|
|
|
251
251
|
}
|
|
252
252
|
|
|
253
253
|
// Strip any mime parameters (e.g. `audio/ogg;codec=opus`) before pulling
|
|
254
|
-
// the subtype out as the file format.
|
|
255
|
-
|
|
254
|
+
// the subtype out as the file format. `String.split` always returns at
|
|
255
|
+
// least one element, so [0] is defined.
|
|
256
|
+
const format = (mimeType.split(';')[0] ?? '').split('/')[1] || 'wav'
|
|
256
257
|
|
|
257
258
|
return {
|
|
258
259
|
id: generateId(this.name),
|
|
@@ -275,7 +276,7 @@ function parsePcmMimeType(
|
|
|
275
276
|
mimeType: string,
|
|
276
277
|
): { sampleRate: number; channels: number; bitsPerSample: number } | undefined {
|
|
277
278
|
const normalized = mimeType.toLowerCase()
|
|
278
|
-
const subtype = normalized.split(';')[0]
|
|
279
|
+
const subtype = (normalized.split(';')[0] ?? '').split('/')[1] ?? ''
|
|
279
280
|
// Exclude containerized wav (e.g. `audio/wav;codec=pcm`) — those already
|
|
280
281
|
// carry a RIFF header and must not be re-wrapped.
|
|
281
282
|
if (subtype.includes('wav')) return undefined
|
|
@@ -351,8 +352,8 @@ function wrapPcmBase64AsWav(
|
|
|
351
352
|
}
|
|
352
353
|
let binary = ''
|
|
353
354
|
const bytes = new Uint8Array(buffer)
|
|
354
|
-
for (
|
|
355
|
-
binary += String.fromCharCode(
|
|
355
|
+
for (const byte of bytes) {
|
|
356
|
+
binary += String.fromCharCode(byte)
|
|
356
357
|
}
|
|
357
358
|
return btoa(binary)
|
|
358
359
|
}
|
|
@@ -304,6 +304,7 @@ export function parseNativeImageSize(
|
|
|
304
304
|
size: string,
|
|
305
305
|
): { aspectRatio: string; resolution: string } | undefined {
|
|
306
306
|
const match = size.match(/^(\d+:\d+)_(.+)$/)
|
|
307
|
-
|
|
308
|
-
|
|
307
|
+
const [, aspectRatio, resolution] = match ?? []
|
|
308
|
+
if (aspectRatio === undefined || resolution === undefined) return undefined
|
|
309
|
+
return { aspectRatio, resolution }
|
|
309
310
|
}
|
package/src/model-meta.ts
CHANGED
|
@@ -965,6 +965,40 @@ const VEO_2 = {
|
|
|
965
965
|
[VEO_2.name]: VEO_2,
|
|
966
966
|
} as const */
|
|
967
967
|
|
|
968
|
+
const GEMINI_3_5_FLASH = {
|
|
969
|
+
name: 'gemini-3.5-flash',
|
|
970
|
+
max_input_tokens: 1_048_576,
|
|
971
|
+
max_output_tokens: 65_536,
|
|
972
|
+
supports: {
|
|
973
|
+
input: ['text', 'image', 'video', 'document', 'audio'],
|
|
974
|
+
output: ['text'],
|
|
975
|
+
capabilities: [
|
|
976
|
+
'batch_api',
|
|
977
|
+
'caching',
|
|
978
|
+
'function_calling',
|
|
979
|
+
'structured_output',
|
|
980
|
+
'thinking',
|
|
981
|
+
],
|
|
982
|
+
tools: ['code_execution', 'file_search', 'google_search', 'url_context'],
|
|
983
|
+
},
|
|
984
|
+
pricing: {
|
|
985
|
+
input: {
|
|
986
|
+
normal: 1.5,
|
|
987
|
+
cached: 0.15,
|
|
988
|
+
},
|
|
989
|
+
output: {
|
|
990
|
+
normal: 9,
|
|
991
|
+
},
|
|
992
|
+
},
|
|
993
|
+
} as const satisfies ModelMeta<
|
|
994
|
+
GeminiToolConfigOptions &
|
|
995
|
+
GeminiSafetyOptions &
|
|
996
|
+
GeminiCommonConfigOptions &
|
|
997
|
+
GeminiCachedContentOptions &
|
|
998
|
+
GeminiStructuredOutputOptions &
|
|
999
|
+
GeminiThinkingOptions
|
|
1000
|
+
>
|
|
1001
|
+
|
|
968
1002
|
export const GEMINI_MODELS = [
|
|
969
1003
|
GEMINI_3_1_PRO.name,
|
|
970
1004
|
GEMINI_3_PRO.name,
|
|
@@ -977,6 +1011,8 @@ export const GEMINI_MODELS = [
|
|
|
977
1011
|
GEMINI_2_5_FLASH_LITE_PREVIEW.name,
|
|
978
1012
|
GEMINI_2_FLASH.name,
|
|
979
1013
|
GEMINI_2_FLASH_LITE.name,
|
|
1014
|
+
|
|
1015
|
+
GEMINI_3_5_FLASH.name,
|
|
980
1016
|
] as const
|
|
981
1017
|
|
|
982
1018
|
export type GeminiModels = (typeof GEMINI_MODELS)[number]
|
|
@@ -1135,6 +1171,12 @@ export type GeminiChatModelProviderOptionsByName = {
|
|
|
1135
1171
|
GeminiCommonConfigOptions &
|
|
1136
1172
|
GeminiCachedContentOptions &
|
|
1137
1173
|
GeminiStructuredOutputOptions
|
|
1174
|
+
[GEMINI_3_5_FLASH.name]: GeminiToolConfigOptions &
|
|
1175
|
+
GeminiSafetyOptions &
|
|
1176
|
+
GeminiCommonConfigOptions &
|
|
1177
|
+
GeminiCachedContentOptions &
|
|
1178
|
+
GeminiStructuredOutputOptions &
|
|
1179
|
+
GeminiThinkingOptions
|
|
1138
1180
|
}
|
|
1139
1181
|
|
|
1140
1182
|
/**
|
|
@@ -1183,4 +1225,5 @@ export type GeminiModelInputModalitiesByName = {
|
|
|
1183
1225
|
[GEMINI_2_5_FLASH_PREVIEW.name]: typeof GEMINI_2_5_FLASH_PREVIEW.supports.input
|
|
1184
1226
|
[GEMINI_2_FLASH.name]: typeof GEMINI_2_FLASH.supports.input
|
|
1185
1227
|
[GEMINI_2_FLASH_LITE.name]: typeof GEMINI_2_FLASH_LITE.supports.input
|
|
1228
|
+
[GEMINI_3_5_FLASH.name]: typeof GEMINI_3_5_FLASH.supports.input
|
|
1186
1229
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { brandProviderTool } from '@tanstack/ai'
|
|
1
2
|
import type { ProviderTool, Tool } from '@tanstack/ai'
|
|
2
3
|
|
|
3
4
|
export interface CodeExecutionToolConfig {}
|
|
@@ -14,10 +15,9 @@ export function convertCodeExecutionToolToAdapterFormat(_tool: Tool) {
|
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
export function codeExecutionTool(): GeminiCodeExecutionTool {
|
|
17
|
-
|
|
18
|
-
return {
|
|
18
|
+
return brandProviderTool<GeminiCodeExecutionTool>({
|
|
19
19
|
name: 'code_execution',
|
|
20
20
|
description: '',
|
|
21
21
|
metadata: {},
|
|
22
|
-
}
|
|
22
|
+
})
|
|
23
23
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { brandProviderTool } from '@tanstack/ai'
|
|
1
2
|
import type { ComputerUse } from '@google/genai'
|
|
2
3
|
import type { ProviderTool, Tool } from '@tanstack/ai'
|
|
3
4
|
|
|
@@ -10,10 +11,17 @@ export type GeminiComputerUseTool = ProviderTool<'gemini', 'computer_use'>
|
|
|
10
11
|
|
|
11
12
|
export function convertComputerUseToolToAdapterFormat(tool: Tool) {
|
|
12
13
|
const metadata = tool.metadata as ComputerUseToolConfig
|
|
14
|
+
// Vendor `ComputerUse` fields are `field?: T` (no `| undefined`) under EOPT,
|
|
15
|
+
// so spread each field conditionally rather than emitting explicit
|
|
16
|
+
// `undefined`s on the wire payload.
|
|
13
17
|
return {
|
|
14
18
|
computerUse: {
|
|
15
|
-
|
|
16
|
-
|
|
19
|
+
...(metadata.environment !== undefined && {
|
|
20
|
+
environment: metadata.environment,
|
|
21
|
+
}),
|
|
22
|
+
...(metadata.excludedPredefinedFunctions !== undefined && {
|
|
23
|
+
excludedPredefinedFunctions: metadata.excludedPredefinedFunctions,
|
|
24
|
+
}),
|
|
17
25
|
},
|
|
18
26
|
}
|
|
19
27
|
}
|
|
@@ -21,13 +29,16 @@ export function convertComputerUseToolToAdapterFormat(tool: Tool) {
|
|
|
21
29
|
export function computerUseTool(
|
|
22
30
|
config: ComputerUseToolConfig,
|
|
23
31
|
): GeminiComputerUseTool {
|
|
24
|
-
|
|
25
|
-
return {
|
|
32
|
+
return brandProviderTool<GeminiComputerUseTool>({
|
|
26
33
|
name: 'computer_use',
|
|
27
34
|
description: '',
|
|
28
35
|
metadata: {
|
|
29
|
-
|
|
30
|
-
|
|
36
|
+
...(config.environment !== undefined && {
|
|
37
|
+
environment: config.environment,
|
|
38
|
+
}),
|
|
39
|
+
...(config.excludedPredefinedFunctions !== undefined && {
|
|
40
|
+
excludedPredefinedFunctions: config.excludedPredefinedFunctions,
|
|
41
|
+
}),
|
|
31
42
|
},
|
|
32
|
-
}
|
|
43
|
+
})
|
|
33
44
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { brandProviderTool } from '@tanstack/ai'
|
|
1
2
|
import type { FileSearch } from '@google/genai'
|
|
2
3
|
import type { ProviderTool, Tool } from '@tanstack/ai'
|
|
3
4
|
|
|
@@ -18,10 +19,9 @@ export function convertFileSearchToolToAdapterFormat(tool: Tool) {
|
|
|
18
19
|
export function fileSearchTool(
|
|
19
20
|
config: FileSearchToolConfig,
|
|
20
21
|
): GeminiFileSearchTool {
|
|
21
|
-
|
|
22
|
-
return {
|
|
22
|
+
return brandProviderTool<GeminiFileSearchTool>({
|
|
23
23
|
name: 'file_search',
|
|
24
24
|
description: '',
|
|
25
25
|
metadata: config,
|
|
26
|
-
}
|
|
26
|
+
})
|
|
27
27
|
}
|
|
@@ -4,8 +4,7 @@ export type FunctionDeclarationTool = FunctionDeclaration
|
|
|
4
4
|
|
|
5
5
|
const validateFunctionDeclarationTool = (tool: FunctionDeclarationTool) => {
|
|
6
6
|
const nameRegex = /^[a-zA-Z0-9_:.-]{1,64}$/
|
|
7
|
-
|
|
8
|
-
if (!valid) {
|
|
7
|
+
if (tool.name === undefined || !nameRegex.test(tool.name)) {
|
|
9
8
|
throw new Error(
|
|
10
9
|
`Invalid function name: ${tool.name}. Must be 1-64 characters long and contain only a-z, A-Z, 0-9, underscores, colons, dots, and dashes.`,
|
|
11
10
|
)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { brandProviderTool } from '@tanstack/ai'
|
|
1
2
|
import type { GoogleMaps } from '@google/genai'
|
|
2
3
|
import type { ProviderTool, Tool } from '@tanstack/ai'
|
|
3
4
|
|
|
@@ -18,10 +19,9 @@ export function convertGoogleMapsToolToAdapterFormat(tool: Tool) {
|
|
|
18
19
|
export function googleMapsTool(
|
|
19
20
|
config?: GoogleMapsToolConfig,
|
|
20
21
|
): GeminiGoogleMapsTool {
|
|
21
|
-
|
|
22
|
-
return {
|
|
22
|
+
return brandProviderTool<GeminiGoogleMapsTool>({
|
|
23
23
|
name: 'google_maps',
|
|
24
24
|
description: '',
|
|
25
25
|
metadata: config,
|
|
26
|
-
}
|
|
26
|
+
})
|
|
27
27
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { brandProviderTool } from '@tanstack/ai'
|
|
1
2
|
import type { GoogleSearchRetrieval } from '@google/genai'
|
|
2
3
|
import type { ProviderTool, Tool } from '@tanstack/ai'
|
|
3
4
|
|
|
@@ -21,10 +22,9 @@ export function convertGoogleSearchRetrievalToolToAdapterFormat(tool: Tool) {
|
|
|
21
22
|
export function googleSearchRetrievalTool(
|
|
22
23
|
config?: GoogleSearchRetrievalToolConfig,
|
|
23
24
|
): GeminiGoogleSearchRetrievalTool {
|
|
24
|
-
|
|
25
|
-
return {
|
|
25
|
+
return brandProviderTool<GeminiGoogleSearchRetrievalTool>({
|
|
26
26
|
name: 'google_search_retrieval',
|
|
27
27
|
description: '',
|
|
28
28
|
metadata: config,
|
|
29
|
-
}
|
|
29
|
+
})
|
|
30
30
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { brandProviderTool } from '@tanstack/ai'
|
|
1
2
|
import type { GoogleSearch } from '@google/genai'
|
|
2
3
|
import type { ProviderTool, Tool } from '@tanstack/ai'
|
|
3
4
|
|
|
@@ -18,10 +19,9 @@ export function convertGoogleSearchToolToAdapterFormat(tool: Tool) {
|
|
|
18
19
|
export function googleSearchTool(
|
|
19
20
|
config?: GoogleSearchToolConfig,
|
|
20
21
|
): GeminiGoogleSearchTool {
|
|
21
|
-
|
|
22
|
-
return {
|
|
22
|
+
return brandProviderTool<GeminiGoogleSearchTool>({
|
|
23
23
|
name: 'google_search',
|
|
24
24
|
description: '',
|
|
25
25
|
metadata: config,
|
|
26
|
-
}
|
|
26
|
+
})
|
|
27
27
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { brandProviderTool } from '@tanstack/ai'
|
|
1
2
|
import type { ProviderTool, Tool } from '@tanstack/ai'
|
|
2
3
|
|
|
3
4
|
export interface UrlContextToolConfig {}
|
|
@@ -14,10 +15,9 @@ export function convertUrlContextToolToAdapterFormat(_tool: Tool) {
|
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
export function urlContextTool(): GeminiUrlContextTool {
|
|
17
|
-
|
|
18
|
-
return {
|
|
18
|
+
return brandProviderTool<GeminiUrlContextTool>({
|
|
19
19
|
name: 'url_context',
|
|
20
20
|
description: '',
|
|
21
21
|
metadata: {},
|
|
22
|
-
}
|
|
22
|
+
})
|
|
23
23
|
}
|