@gullabs/google 0.10.1 → 0.11.0

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/index.d.cts CHANGED
@@ -97,6 +97,10 @@ interface GeminiPartShape {
97
97
  * Real field name in @google/genai Candidate.content.parts: `thought`.
98
98
  */
99
99
  thought?: boolean;
100
+ functionCall?: {
101
+ name?: string;
102
+ args?: unknown;
103
+ };
100
104
  }
101
105
  /** A candidate returned by Gemini generateContent. */
102
106
  interface GeminiCandidateShape {
@@ -199,7 +203,19 @@ interface GeminiFileDataContentPart {
199
203
  * Each member (including the optional per-part `mediaResolution`) is a
200
204
  * structural subset of the real `@google/genai` `Part` type for the fields we use.
201
205
  */
202
- type GeminiContentPart = GeminiTextContentPart | GeminiInlineDataContentPart | GeminiFileDataContentPart;
206
+ interface GeminiFunctionCallPart {
207
+ functionCall: {
208
+ name: string;
209
+ args?: unknown;
210
+ };
211
+ }
212
+ interface GeminiFunctionResponsePart {
213
+ functionResponse: {
214
+ name: string;
215
+ response: unknown;
216
+ };
217
+ }
218
+ type GeminiContentPart = GeminiTextContentPart | GeminiInlineDataContentPart | GeminiFileDataContentPart | GeminiFunctionCallPart | GeminiFunctionResponsePart;
203
219
  /** A content object (message) we construct. */
204
220
  interface GeminiContent {
205
221
  role: string;
@@ -271,6 +287,20 @@ interface GeminiGenerateConfig {
271
287
  timeout?: number;
272
288
  headers?: Record<string, string>;
273
289
  };
290
+ tools?: Array<{
291
+ functionDeclarations?: Array<{
292
+ name: string;
293
+ description: string;
294
+ parameters?: unknown;
295
+ }>;
296
+ googleSearch?: Record<string, never>;
297
+ }>;
298
+ toolConfig?: {
299
+ functionCallingConfig?: {
300
+ mode?: 'AUTO' | 'ANY' | 'NONE';
301
+ allowedFunctionNames?: string[];
302
+ };
303
+ };
274
304
  }
275
305
  /**
276
306
  * Parameters for models.generateContent.
@@ -298,6 +328,7 @@ interface GeminiCountTokensParams {
298
328
  * is forwarded here directly, unlike `run()`'s combined timer signal.
299
329
  */
300
330
  abortSignal?: AbortSignal;
331
+ tools?: GeminiGenerateConfig['tools'];
301
332
  };
302
333
  }
303
334
  /**
@@ -859,30 +890,6 @@ declare class GoogleCacheStore {
859
890
  delete(handle: GoogleCacheHandle): Promise<void>;
860
891
  }
861
892
 
862
- /**
863
- * normalizeGroundingCitations — shape Gemini's raw groundingMetadata.groundingChunks
864
- * into a clean, deduplicated citation list.
865
- *
866
- * This is a caller-owned, optional post-processing convenience helper — NOT
867
- * request validation. It NEVER throws: any missing/malformed input yields `[]`.
868
- *
869
- * @module
870
- */
871
- interface Citation {
872
- url: string;
873
- sourceName: string;
874
- }
875
- /**
876
- * Shape Gemini's raw `groundingMetadata.groundingChunks` into a clean,
877
- * deduplicated citation list (deduplicated by URL, first-seen order).
878
- *
879
- * Accepts `unknown` since `groundingMetadata` arrives as raw JSON on
880
- * `providerMetadata` (see `docs/grounded-structured.md`). Never throws —
881
- * any missing/malformed top-level shape returns `[]`; a malformed individual
882
- * chunk is skipped rather than failing the whole array.
883
- */
884
- declare function normalizeGroundingCitations(groundingMetadata: unknown): Citation[];
885
-
886
893
  /**
887
894
  * geminiContentToMessages — migration utility: `@google/genai` `Content[]` →
888
895
  * any-llm's normalized `Message[]`.
@@ -964,4 +971,4 @@ interface GeminiContentToMessagesResult {
964
971
  */
965
972
  declare function geminiContentToMessages(input: GeminiContentToMessagesInput): GeminiContentToMessagesResult;
966
973
 
967
- export { type CacheKey, type Citation, FLEX_DEFAULT_TIMEOUT_MS, type FileDeleteOptions, GEMINI_PRICING, type GeminiAdapterOptions, type GeminiCachesClientLike, type GeminiClientLike, type GeminiContentToMessagesInput, type GeminiContentToMessagesResult, type GeminiCountTokensParams, type GeminiCountTokensResponseShape, type GeminiFilesClientLike, type GoogleCacheHandle, GoogleCacheStore, type GoogleCacheStoreOptions, type GoogleFileHandle, GoogleFileStore, type GoogleFileStoreOptions, type GoogleProviderOptions, type GoogleSafetySetting, type GoogleSearchTool, STANDARD_DEFAULT_TIMEOUT_MS, TIER_FACTOR, TRANSPORT_TIMEOUT_BUFFER_MS, buildGoogleClient, defaultGeminiRegistry, geminiAdapter, geminiContentToMessages, geminiModelDescriptors, geminiPricingSource, gemmaModelDescriptors, googleProvider, isGeminiCapacityError, normalizeGroundingCitations, pricingVersion, requireApiKey };
974
+ export { type CacheKey, FLEX_DEFAULT_TIMEOUT_MS, type FileDeleteOptions, GEMINI_PRICING, type GeminiAdapterOptions, type GeminiCachesClientLike, type GeminiClientLike, type GeminiContentToMessagesInput, type GeminiContentToMessagesResult, type GeminiCountTokensParams, type GeminiCountTokensResponseShape, type GeminiFilesClientLike, type GoogleCacheHandle, GoogleCacheStore, type GoogleCacheStoreOptions, type GoogleFileHandle, GoogleFileStore, type GoogleFileStoreOptions, type GoogleProviderOptions, type GoogleSafetySetting, type GoogleSearchTool, STANDARD_DEFAULT_TIMEOUT_MS, TIER_FACTOR, TRANSPORT_TIMEOUT_BUFFER_MS, buildGoogleClient, defaultGeminiRegistry, geminiAdapter, geminiContentToMessages, geminiModelDescriptors, geminiPricingSource, gemmaModelDescriptors, googleProvider, isGeminiCapacityError, pricingVersion, requireApiKey };
package/dist/index.d.ts CHANGED
@@ -97,6 +97,10 @@ interface GeminiPartShape {
97
97
  * Real field name in @google/genai Candidate.content.parts: `thought`.
98
98
  */
99
99
  thought?: boolean;
100
+ functionCall?: {
101
+ name?: string;
102
+ args?: unknown;
103
+ };
100
104
  }
101
105
  /** A candidate returned by Gemini generateContent. */
102
106
  interface GeminiCandidateShape {
@@ -199,7 +203,19 @@ interface GeminiFileDataContentPart {
199
203
  * Each member (including the optional per-part `mediaResolution`) is a
200
204
  * structural subset of the real `@google/genai` `Part` type for the fields we use.
201
205
  */
202
- type GeminiContentPart = GeminiTextContentPart | GeminiInlineDataContentPart | GeminiFileDataContentPart;
206
+ interface GeminiFunctionCallPart {
207
+ functionCall: {
208
+ name: string;
209
+ args?: unknown;
210
+ };
211
+ }
212
+ interface GeminiFunctionResponsePart {
213
+ functionResponse: {
214
+ name: string;
215
+ response: unknown;
216
+ };
217
+ }
218
+ type GeminiContentPart = GeminiTextContentPart | GeminiInlineDataContentPart | GeminiFileDataContentPart | GeminiFunctionCallPart | GeminiFunctionResponsePart;
203
219
  /** A content object (message) we construct. */
204
220
  interface GeminiContent {
205
221
  role: string;
@@ -271,6 +287,20 @@ interface GeminiGenerateConfig {
271
287
  timeout?: number;
272
288
  headers?: Record<string, string>;
273
289
  };
290
+ tools?: Array<{
291
+ functionDeclarations?: Array<{
292
+ name: string;
293
+ description: string;
294
+ parameters?: unknown;
295
+ }>;
296
+ googleSearch?: Record<string, never>;
297
+ }>;
298
+ toolConfig?: {
299
+ functionCallingConfig?: {
300
+ mode?: 'AUTO' | 'ANY' | 'NONE';
301
+ allowedFunctionNames?: string[];
302
+ };
303
+ };
274
304
  }
275
305
  /**
276
306
  * Parameters for models.generateContent.
@@ -298,6 +328,7 @@ interface GeminiCountTokensParams {
298
328
  * is forwarded here directly, unlike `run()`'s combined timer signal.
299
329
  */
300
330
  abortSignal?: AbortSignal;
331
+ tools?: GeminiGenerateConfig['tools'];
301
332
  };
302
333
  }
303
334
  /**
@@ -859,30 +890,6 @@ declare class GoogleCacheStore {
859
890
  delete(handle: GoogleCacheHandle): Promise<void>;
860
891
  }
861
892
 
862
- /**
863
- * normalizeGroundingCitations — shape Gemini's raw groundingMetadata.groundingChunks
864
- * into a clean, deduplicated citation list.
865
- *
866
- * This is a caller-owned, optional post-processing convenience helper — NOT
867
- * request validation. It NEVER throws: any missing/malformed input yields `[]`.
868
- *
869
- * @module
870
- */
871
- interface Citation {
872
- url: string;
873
- sourceName: string;
874
- }
875
- /**
876
- * Shape Gemini's raw `groundingMetadata.groundingChunks` into a clean,
877
- * deduplicated citation list (deduplicated by URL, first-seen order).
878
- *
879
- * Accepts `unknown` since `groundingMetadata` arrives as raw JSON on
880
- * `providerMetadata` (see `docs/grounded-structured.md`). Never throws —
881
- * any missing/malformed top-level shape returns `[]`; a malformed individual
882
- * chunk is skipped rather than failing the whole array.
883
- */
884
- declare function normalizeGroundingCitations(groundingMetadata: unknown): Citation[];
885
-
886
893
  /**
887
894
  * geminiContentToMessages — migration utility: `@google/genai` `Content[]` →
888
895
  * any-llm's normalized `Message[]`.
@@ -964,4 +971,4 @@ interface GeminiContentToMessagesResult {
964
971
  */
965
972
  declare function geminiContentToMessages(input: GeminiContentToMessagesInput): GeminiContentToMessagesResult;
966
973
 
967
- export { type CacheKey, type Citation, FLEX_DEFAULT_TIMEOUT_MS, type FileDeleteOptions, GEMINI_PRICING, type GeminiAdapterOptions, type GeminiCachesClientLike, type GeminiClientLike, type GeminiContentToMessagesInput, type GeminiContentToMessagesResult, type GeminiCountTokensParams, type GeminiCountTokensResponseShape, type GeminiFilesClientLike, type GoogleCacheHandle, GoogleCacheStore, type GoogleCacheStoreOptions, type GoogleFileHandle, GoogleFileStore, type GoogleFileStoreOptions, type GoogleProviderOptions, type GoogleSafetySetting, type GoogleSearchTool, STANDARD_DEFAULT_TIMEOUT_MS, TIER_FACTOR, TRANSPORT_TIMEOUT_BUFFER_MS, buildGoogleClient, defaultGeminiRegistry, geminiAdapter, geminiContentToMessages, geminiModelDescriptors, geminiPricingSource, gemmaModelDescriptors, googleProvider, isGeminiCapacityError, normalizeGroundingCitations, pricingVersion, requireApiKey };
974
+ export { type CacheKey, FLEX_DEFAULT_TIMEOUT_MS, type FileDeleteOptions, GEMINI_PRICING, type GeminiAdapterOptions, type GeminiCachesClientLike, type GeminiClientLike, type GeminiContentToMessagesInput, type GeminiContentToMessagesResult, type GeminiCountTokensParams, type GeminiCountTokensResponseShape, type GeminiFilesClientLike, type GoogleCacheHandle, GoogleCacheStore, type GoogleCacheStoreOptions, type GoogleFileHandle, GoogleFileStore, type GoogleFileStoreOptions, type GoogleProviderOptions, type GoogleSafetySetting, type GoogleSearchTool, STANDARD_DEFAULT_TIMEOUT_MS, TIER_FACTOR, TRANSPORT_TIMEOUT_BUFFER_MS, buildGoogleClient, defaultGeminiRegistry, geminiAdapter, geminiContentToMessages, geminiModelDescriptors, geminiPricingSource, gemmaModelDescriptors, googleProvider, isGeminiCapacityError, pricingVersion, requireApiKey };
package/dist/index.js CHANGED
@@ -40,6 +40,49 @@ var GOOGLE_REASONING_EFFORT_BUDGET = {
40
40
  high: 24576
41
41
  };
42
42
 
43
+ // src/grounding.ts
44
+ function hostnameFrom(url) {
45
+ return url.hostname.startsWith("www.") ? url.hostname.slice(4) : url.hostname;
46
+ }
47
+ function toCitation(chunk) {
48
+ if (chunk === null || typeof chunk !== "object") return void 0;
49
+ const web = chunk["web"];
50
+ if (web === null || typeof web !== "object") return void 0;
51
+ const uri = web["uri"];
52
+ if (typeof uri !== "string" || uri.length === 0) return void 0;
53
+ let parsed;
54
+ try {
55
+ parsed = new URL(uri);
56
+ } catch {
57
+ return void 0;
58
+ }
59
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return void 0;
60
+ if (parsed.hostname === "") return void 0;
61
+ const title = web["title"];
62
+ const hasTitle = typeof title === "string" && title.length > 0;
63
+ const sourceName = hasTitle ? title : hostnameFrom(parsed);
64
+ return {
65
+ url: uri,
66
+ ...hasTitle ? { title } : {},
67
+ sourceName
68
+ };
69
+ }
70
+ function normalizeGroundingCitations(groundingMetadata) {
71
+ if (groundingMetadata === null || typeof groundingMetadata !== "object") return [];
72
+ const chunks = groundingMetadata["groundingChunks"];
73
+ if (!Array.isArray(chunks)) return [];
74
+ const seen = /* @__PURE__ */ new Set();
75
+ const citations = [];
76
+ for (const chunk of chunks) {
77
+ const citation = toCitation(chunk);
78
+ if (citation === void 0) continue;
79
+ if (seen.has(citation.url)) continue;
80
+ seen.add(citation.url);
81
+ citations.push(citation);
82
+ }
83
+ return citations;
84
+ }
85
+
43
86
  // src/flex-fallback.ts
44
87
  var CAPACITY_PATTERNS = [
45
88
  /capacity/i,
@@ -387,6 +430,12 @@ function mapUsage(meta) {
387
430
  };
388
431
  return usage;
389
432
  }
433
+ function mapGoogleToolChoice(choice) {
434
+ if (choice === "auto") return { mode: "AUTO" };
435
+ if (choice === "required") return { mode: "ANY" };
436
+ if (choice === "none") return { mode: "NONE" };
437
+ return { mode: "ANY", allowedFunctionNames: [choice.name] };
438
+ }
390
439
  function mapPart(p) {
391
440
  switch (p.kind) {
392
441
  case "text":
@@ -414,6 +463,20 @@ function mapPart(p) {
414
463
  "Google Gemini expects FileUriPart with a Files API uri; got file-ref (provider file id). Upload via GoogleFileStore and pass the returned uri.",
415
464
  { kind: "bad_request", retryable: false, provider: "google" }
416
465
  );
466
+ case "tool-call":
467
+ return {
468
+ functionCall: {
469
+ name: p.toolName,
470
+ args: p.args
471
+ }
472
+ };
473
+ case "tool-result":
474
+ return {
475
+ functionResponse: {
476
+ name: p.toolName,
477
+ response: p.isError === true ? { error: p.result } : p.result
478
+ }
479
+ };
417
480
  default:
418
481
  return assertNever(p);
419
482
  }
@@ -557,6 +620,34 @@ function geminiAdapter(opts) {
557
620
  if (googleProviderConfig.tools !== void 0) {
558
621
  config.tools = googleProviderConfig.tools;
559
622
  }
623
+ if (req.tools !== void 0 && req.tools.length > 0) {
624
+ if (req.modelDescriptor?.capabilities?.functionCalling !== true) {
625
+ throw new LlmError(
626
+ `tools is not supported for google model "${model}" (capabilities.functionCalling is not true).`,
627
+ { kind: "bad_request", retryable: false, provider: "google" }
628
+ );
629
+ }
630
+ if (googleProviderConfig.tools !== void 0) {
631
+ throw new LlmError(
632
+ "tools cannot be combined with providerOptions.google.tools (googleSearch) in this iteration.",
633
+ { kind: "bad_request", retryable: false, provider: "google" }
634
+ );
635
+ }
636
+ config.tools = [
637
+ {
638
+ functionDeclarations: req.tools.map((tool) => ({
639
+ name: tool.name,
640
+ description: tool.description,
641
+ parameters: tool.inputJsonSchema
642
+ }))
643
+ }
644
+ ];
645
+ if (req.toolChoice !== void 0) {
646
+ config.toolConfig = {
647
+ functionCallingConfig: mapGoogleToolChoice(req.toolChoice)
648
+ };
649
+ }
650
+ }
560
651
  assertSamplingAllowed(config, model, req.modelDescriptor?.capabilities?.sampling);
561
652
  let tierTimeoutHandle;
562
653
  const clearTierTimeout = () => {
@@ -674,7 +765,15 @@ function geminiAdapter(opts) {
674
765
  const parts = candidate.content?.parts ?? [];
675
766
  const textParts = [];
676
767
  const thoughtParts = [];
768
+ const toolCalls = [];
677
769
  for (const part of parts) {
770
+ if (part.functionCall !== void 0 && typeof part.functionCall.name === "string") {
771
+ toolCalls.push({
772
+ toolCallId: part.functionCall.name,
773
+ toolName: part.functionCall.name,
774
+ args: part.functionCall.args ?? {}
775
+ });
776
+ }
678
777
  if (part.text !== void 0) {
679
778
  if (part.thought === true) {
680
779
  thoughtParts.push(part.text);
@@ -702,7 +801,7 @@ function geminiAdapter(opts) {
702
801
  ...text.length > 0 ? { text } : {},
703
802
  ...reasoningText !== void 0 ? { reasoningText } : {},
704
803
  ...rawStructured !== void 0 ? { rawStructured } : {},
705
- ...finishReason !== void 0 ? { finishReason } : {},
804
+ ...toolCalls.length > 0 ? { toolCalls, finishReason: "tool_calls" } : finishReason !== void 0 ? { finishReason } : {},
706
805
  ...response.modelVersion !== void 0 ? { modelVersion: response.modelVersion } : {},
707
806
  ...response.responseId !== void 0 ? { responseId: response.responseId } : {},
708
807
  // Build providerMetadata — merge promptFeedback + groundingMetadata when present.
@@ -718,6 +817,12 @@ function geminiAdapter(opts) {
718
817
  meta["groundingMetadata"] = gm;
719
818
  }
720
819
  return { providerMetadata: meta };
820
+ })(),
821
+ ...(() => {
822
+ const gm = candidate.groundingMetadata;
823
+ if (gm === void 0) return {};
824
+ const citations = normalizeGroundingCitations(gm);
825
+ return citations.length > 0 ? { citations } : {};
721
826
  })()
722
827
  };
723
828
  return result;
@@ -730,13 +835,23 @@ function geminiAdapter(opts) {
730
835
  );
731
836
  }
732
837
  const contents = mapMessagesToGeminiContents(req.messages);
838
+ const countTools = req.tools !== void 0 && req.tools.length > 0 ? [
839
+ {
840
+ functionDeclarations: req.tools.map((tool) => ({
841
+ name: tool.name,
842
+ description: tool.description,
843
+ parameters: tool.inputJsonSchema
844
+ }))
845
+ }
846
+ ] : void 0;
733
847
  const params = {
734
848
  model: req.model,
735
849
  contents,
736
- ...req.system !== void 0 || ctx.signal !== void 0 ? {
850
+ ...req.system !== void 0 || ctx.signal !== void 0 || countTools !== void 0 ? {
737
851
  config: {
738
852
  ...req.system !== void 0 ? { systemInstruction: { parts: [{ text: req.system }] } } : {},
739
- ...ctx.signal !== void 0 ? { abortSignal: ctx.signal } : {}
853
+ ...ctx.signal !== void 0 ? { abortSignal: ctx.signal } : {},
854
+ ...countTools !== void 0 ? { tools: countTools } : {}
740
855
  }
741
856
  } : {}
742
857
  };
@@ -753,6 +868,7 @@ function geminiAdapter(opts) {
753
868
  const details = response.cachedContentTokenCount !== void 0 ? { cached: response.cachedContentTokenCount } : void 0;
754
869
  return {
755
870
  totalTokens: response.totalTokens,
871
+ accuracy: "exact",
756
872
  ...details !== void 0 ? { details } : {},
757
873
  raw: response
758
874
  };
@@ -2536,6 +2652,7 @@ var geminiModelDescriptors = [
2536
2652
  sampling: "tunable",
2537
2653
  caching: { explicit: true, minTokens: 2048 },
2538
2654
  grounding: true,
2655
+ functionCalling: true,
2539
2656
  serviceTiers: ["flex", "standard"]
2540
2657
  },
2541
2658
  configSchema: Gemini25ProConfigSchema,
@@ -2556,6 +2673,7 @@ var geminiModelDescriptors = [
2556
2673
  sampling: "tunable",
2557
2674
  caching: { explicit: true, minTokens: 2048 },
2558
2675
  grounding: true,
2676
+ functionCalling: true,
2559
2677
  serviceTiers: ["flex", "standard"]
2560
2678
  },
2561
2679
  configSchema: Gemini25FlashConfigSchema,
@@ -2576,6 +2694,7 @@ var geminiModelDescriptors = [
2576
2694
  sampling: "tunable",
2577
2695
  caching: { explicit: true, minTokens: 2048 },
2578
2696
  grounding: true,
2697
+ functionCalling: true,
2579
2698
  serviceTiers: ["flex", "standard"]
2580
2699
  },
2581
2700
  configSchema: Gemini25FlashLiteConfigSchema,
@@ -2596,6 +2715,7 @@ var geminiModelDescriptors = [
2596
2715
  sampling: "fixed",
2597
2716
  caching: { explicit: true, minTokens: 2048 },
2598
2717
  grounding: true,
2718
+ functionCalling: true,
2599
2719
  serviceTiers: ["flex", "standard"]
2600
2720
  },
2601
2721
  configSchema: Gemini35FlashConfigSchema,
@@ -2616,6 +2736,7 @@ var geminiModelDescriptors = [
2616
2736
  sampling: "fixed",
2617
2737
  caching: { explicit: true, minTokens: 2048 },
2618
2738
  grounding: true,
2739
+ functionCalling: true,
2619
2740
  serviceTiers: ["flex", "standard"]
2620
2741
  },
2621
2742
  configSchema: Gemini31FlashLiteConfigSchema,
@@ -2636,6 +2757,7 @@ var geminiModelDescriptors = [
2636
2757
  sampling: "fixed",
2637
2758
  caching: { explicit: true, minTokens: 2048 },
2638
2759
  grounding: true,
2760
+ functionCalling: true,
2639
2761
  serviceTiers: ["flex", "standard"]
2640
2762
  },
2641
2763
  configSchema: Gemini31ProPreviewConfigSchema,
@@ -2656,6 +2778,7 @@ var geminiModelDescriptors = [
2656
2778
  sampling: "fixed",
2657
2779
  caching: { explicit: true, minTokens: 2048 },
2658
2780
  grounding: true,
2781
+ functionCalling: true,
2659
2782
  serviceTiers: ["flex", "standard"]
2660
2783
  },
2661
2784
  configSchema: Gemini3FlashPreviewConfigSchema,
@@ -3191,44 +3314,6 @@ var GoogleCacheStore = class {
3191
3314
  }
3192
3315
  }
3193
3316
  };
3194
-
3195
- // src/grounding.ts
3196
- function hostnameFrom(url) {
3197
- return url.hostname.startsWith("www.") ? url.hostname.slice(4) : url.hostname;
3198
- }
3199
- function toCitation(chunk) {
3200
- if (chunk === null || typeof chunk !== "object") return void 0;
3201
- const web = chunk["web"];
3202
- if (web === null || typeof web !== "object") return void 0;
3203
- const uri = web["uri"];
3204
- if (typeof uri !== "string" || uri.length === 0) return void 0;
3205
- let parsed;
3206
- try {
3207
- parsed = new URL(uri);
3208
- } catch {
3209
- return void 0;
3210
- }
3211
- if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return void 0;
3212
- if (parsed.hostname === "") return void 0;
3213
- const title = web["title"];
3214
- const sourceName = typeof title === "string" && title.length > 0 ? title : hostnameFrom(parsed);
3215
- return { url: uri, sourceName };
3216
- }
3217
- function normalizeGroundingCitations(groundingMetadata) {
3218
- if (groundingMetadata === null || typeof groundingMetadata !== "object") return [];
3219
- const chunks = groundingMetadata["groundingChunks"];
3220
- if (!Array.isArray(chunks)) return [];
3221
- const seen = /* @__PURE__ */ new Set();
3222
- const citations = [];
3223
- for (const chunk of chunks) {
3224
- const citation = toCitation(chunk);
3225
- if (citation === void 0) continue;
3226
- if (seen.has(citation.url)) continue;
3227
- seen.add(citation.url);
3228
- citations.push(citation);
3229
- }
3230
- return citations;
3231
- }
3232
3317
  function badRequest(message) {
3233
3318
  return new LlmError(message, { kind: "bad_request", retryable: false });
3234
3319
  }
@@ -3271,13 +3356,37 @@ function convertPart(part, location) {
3271
3356
  (key) => key === "text" || key === "inlineData" || key === "fileData"
3272
3357
  );
3273
3358
  if (baseKeys.length === 0) {
3359
+ if (keys.includes("functionCall") && keys.every((k) => k === "functionCall")) {
3360
+ const fc = part.functionCall;
3361
+ if (fc === void 0 || typeof fc.name !== "string" || fc.name.length === 0) {
3362
+ throw badRequest(`${location}: functionCall.name is required.`);
3363
+ }
3364
+ return {
3365
+ kind: "tool-call",
3366
+ toolCallId: fc.name,
3367
+ toolName: fc.name,
3368
+ args: fc.args ?? {}
3369
+ };
3370
+ }
3371
+ if (keys.includes("functionResponse") && keys.every((k) => k === "functionResponse")) {
3372
+ const fr = part.functionResponse;
3373
+ if (fr === void 0 || typeof fr.name !== "string" || fr.name.length === 0) {
3374
+ throw badRequest(`${location}: functionResponse.name is required.`);
3375
+ }
3376
+ return {
3377
+ kind: "tool-result",
3378
+ toolCallId: fr.name,
3379
+ toolName: fr.name,
3380
+ result: fr.response ?? null
3381
+ };
3382
+ }
3274
3383
  if (keys.length === 0) {
3275
3384
  throw badRequest(
3276
3385
  `${location}: Part has no recognized fields set (expected exactly one of text, inlineData, fileData).`
3277
3386
  );
3278
3387
  }
3279
3388
  throw badRequest(
3280
- `${location}: Part keys [${keys.join(", ")}] are not supported by geminiContentToMessages \u2014 only text, inlineData, and fileData parts can be represented in any-llm.`
3389
+ `${location}: Part keys [${keys.join(", ")}] are not supported by geminiContentToMessages \u2014 only text, inlineData, fileData, functionCall, and functionResponse parts can be represented in any-llm.`
3281
3390
  );
3282
3391
  }
3283
3392
  if (baseKeys.length > 1) {
@@ -3400,6 +3509,6 @@ function geminiContentToMessages(input) {
3400
3509
  return { ...system !== void 0 ? { system } : {}, messages };
3401
3510
  }
3402
3511
 
3403
- export { FLEX_DEFAULT_TIMEOUT_MS, GEMINI_PRICING, GoogleCacheStore, GoogleFileStore, STANDARD_DEFAULT_TIMEOUT_MS, TIER_FACTOR, TRANSPORT_TIMEOUT_BUFFER_MS, buildGoogleClient, defaultGeminiRegistry, geminiAdapter, geminiContentToMessages, geminiModelDescriptors, geminiPricingSource, gemmaModelDescriptors, googleProvider, isGeminiCapacityError, normalizeGroundingCitations, pricingVersion, requireApiKey };
3512
+ export { FLEX_DEFAULT_TIMEOUT_MS, GEMINI_PRICING, GoogleCacheStore, GoogleFileStore, STANDARD_DEFAULT_TIMEOUT_MS, TIER_FACTOR, TRANSPORT_TIMEOUT_BUFFER_MS, buildGoogleClient, defaultGeminiRegistry, geminiAdapter, geminiContentToMessages, geminiModelDescriptors, geminiPricingSource, gemmaModelDescriptors, googleProvider, isGeminiCapacityError, pricingVersion, requireApiKey };
3404
3513
  //# sourceMappingURL=index.js.map
3405
3514
  //# sourceMappingURL=index.js.map