@langchain/google-common 0.2.9 → 0.2.10

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.
@@ -288,7 +288,7 @@ class ChatGoogleBase extends chat_models_1.BaseChatModel {
288
288
  return this.connection.platform;
289
289
  }
290
290
  bindTools(tools, kwargs) {
291
- return this.bind({ tools: (0, common_js_1.convertToGeminiTools)(tools), ...kwargs });
291
+ return this.withConfig({ tools: (0, common_js_1.convertToGeminiTools)(tools), ...kwargs });
292
292
  }
293
293
  // Replace
294
294
  _llmType() {
@@ -424,10 +424,7 @@ class ChatGoogleBase extends chat_models_1.BaseChatModel {
424
424
  keyName: functionName,
425
425
  });
426
426
  }
427
- const llm = this.bind({
428
- tools,
429
- tool_choice: functionName,
430
- });
427
+ const llm = this.bindTools(tools).withConfig({ tool_choice: functionName });
431
428
  if (!includeRaw) {
432
429
  return llm.pipe(outputParser).withConfig({
433
430
  runName: "ChatGoogleStructuredOutput",
@@ -284,7 +284,7 @@ export class ChatGoogleBase extends BaseChatModel {
284
284
  return this.connection.platform;
285
285
  }
286
286
  bindTools(tools, kwargs) {
287
- return this.bind({ tools: convertToGeminiTools(tools), ...kwargs });
287
+ return this.withConfig({ tools: convertToGeminiTools(tools), ...kwargs });
288
288
  }
289
289
  // Replace
290
290
  _llmType() {
@@ -420,10 +420,7 @@ export class ChatGoogleBase extends BaseChatModel {
420
420
  keyName: functionName,
421
421
  });
422
422
  }
423
- const llm = this.bind({
424
- tools,
425
- tool_choice: functionName,
426
- });
423
+ const llm = this.bindTools(tools).withConfig({ tool_choice: functionName });
427
424
  if (!includeRaw) {
428
425
  return llm.pipe(outputParser).withConfig({
429
426
  runName: "ChatGoogleStructuredOutput",
package/dist/types.cjs CHANGED
@@ -61,5 +61,6 @@ exports.GeminiSearchToolAttributes = [
61
61
  exports.GeminiToolAttributes = [
62
62
  "functionDeclaration",
63
63
  "retrieval",
64
+ "urlContext",
64
65
  ...exports.GeminiSearchToolAttributes,
65
66
  ];
package/dist/types.d.ts CHANGED
@@ -266,28 +266,39 @@ export interface GoogleResponse {
266
266
  export interface GoogleRawResponse extends GoogleResponse {
267
267
  data: Blob;
268
268
  }
269
- export interface GeminiPartText {
269
+ export interface GeminiPartBase {
270
+ thought?: boolean;
271
+ }
272
+ export interface GeminiVideoMetadata {
273
+ fps?: number;
274
+ startOffset?: string;
275
+ endOffset?: string;
276
+ }
277
+ export interface GeminiPartBaseFile extends GeminiPartBase {
278
+ videoMetadata?: GeminiVideoMetadata;
279
+ }
280
+ export interface GeminiPartText extends GeminiPartBase {
270
281
  text: string;
271
282
  }
272
- export interface GeminiPartInlineData {
283
+ export interface GeminiPartInlineData extends GeminiPartBaseFile {
273
284
  inlineData: {
274
285
  mimeType: string;
275
286
  data: string;
276
287
  };
277
288
  }
278
- export interface GeminiPartFileData {
289
+ export interface GeminiPartFileData extends GeminiPartBaseFile {
279
290
  fileData: {
280
291
  mimeType: string;
281
292
  fileUri: string;
282
293
  };
283
294
  }
284
- export interface GeminiPartFunctionCall {
295
+ export interface GeminiPartFunctionCall extends GeminiPartBase {
285
296
  functionCall: {
286
297
  name: string;
287
298
  args?: object;
288
299
  };
289
300
  }
290
- export interface GeminiPartFunctionResponse {
301
+ export interface GeminiPartFunctionResponse extends GeminiPartBase {
291
302
  functionResponse: {
292
303
  name: string;
293
304
  response: object;
@@ -356,6 +367,18 @@ export interface GeminiSegment {
356
367
  export interface GeminiRetrievalMetadata {
357
368
  googleSearchDynamicRetrievalScore: number;
358
369
  }
370
+ export type GeminiUrlRetrievalStatus = "URL_RETRIEVAL_STATUS_SUCCESS" | "URL_RETRIEVAL_STATUS_ERROR";
371
+ export interface GeminiUrlRetrievalContext {
372
+ retrievedUrl: string;
373
+ urlRetrievalStatus: GeminiUrlRetrievalStatus;
374
+ }
375
+ export interface GeminiUrlRetrievalMetadata {
376
+ urlRetrievalContexts: GeminiUrlRetrievalContext[];
377
+ }
378
+ export type GeminiUrlMetadata = GeminiUrlRetrievalContext;
379
+ export interface GeminiUrlContextMetadata {
380
+ urlMetadata: GeminiUrlMetadata[];
381
+ }
359
382
  export interface GeminiLogprobsResult {
360
383
  topCandidates: GeminiLogprobsTopCandidate[];
361
384
  chosenCandidates: GeminiLogprobsResultCandidate[];
@@ -377,6 +400,7 @@ export interface GeminiTool {
377
400
  functionDeclarations?: GeminiFunctionDeclaration[];
378
401
  googleSearchRetrieval?: GoogleSearchRetrieval;
379
402
  googleSearch?: GoogleSearch;
403
+ urlContext?: UrlContext;
380
404
  retrieval?: VertexAIRetrieval;
381
405
  }
382
406
  export type GoogleSearchToolSetting = boolean | "googleSearchRetrieval" | "googleSearch" | string;
@@ -390,6 +414,8 @@ export interface GoogleSearchRetrieval {
390
414
  }
391
415
  export interface GoogleSearch {
392
416
  }
417
+ export interface UrlContext {
418
+ }
393
419
  export interface VertexAIRetrieval {
394
420
  vertexAiSearch: {
395
421
  datastore: string;
@@ -453,6 +479,8 @@ export interface GeminiResponseCandidate {
453
479
  safetyRatings: GeminiSafetyRating[];
454
480
  citationMetadata?: GeminiCitationMetadata;
455
481
  groundingMetadata?: GeminiGroundingMetadata;
482
+ urlRetrievalMetadata?: GeminiUrlRetrievalMetadata;
483
+ urlContextMetadata?: GeminiUrlContextMetadata;
456
484
  avgLogprobs?: number;
457
485
  logprobsResult: GeminiLogprobsResult;
458
486
  finishMessage?: string;
package/dist/types.js CHANGED
@@ -44,5 +44,6 @@ export const GeminiSearchToolAttributes = [
44
44
  export const GeminiToolAttributes = [
45
45
  "functionDeclaration",
46
46
  "retrieval",
47
+ "urlContext",
47
48
  ...GeminiSearchToolAttributes,
48
49
  ];
@@ -136,7 +136,7 @@ function getGeminiAPI(config) {
136
136
  return null;
137
137
  }
138
138
  }
139
- function messageContentImageUrl(content) {
139
+ function messageContentImageUrlData(content) {
140
140
  const url = typeof content.image_url === "string"
141
141
  ? content.image_url
142
142
  : content.image_url.url;
@@ -159,6 +159,11 @@ function getGeminiAPI(config) {
159
159
  };
160
160
  }
161
161
  }
162
+ function messageContentImageUrl(content) {
163
+ const ret = messageContentImageUrlData(content);
164
+ supplementVideoMetadata(content, ret);
165
+ return ret;
166
+ }
162
167
  async function blobToFileData(blob) {
163
168
  return {
164
169
  fileData: {
@@ -170,7 +175,7 @@ function getGeminiAPI(config) {
170
175
  async function fileUriContentToBlob(uri) {
171
176
  return config?.mediaManager?.getMediaBlob(uri);
172
177
  }
173
- async function messageContentMedia(
178
+ async function messageContentMediaData(
174
179
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
175
180
  content) {
176
181
  if ("mimeType" in content && "data" in content) {
@@ -198,6 +203,34 @@ function getGeminiAPI(config) {
198
203
  }
199
204
  throw new Error(`Invalid media content: ${JSON.stringify(content, null, 1)}`);
200
205
  }
206
+ function supplementVideoMetadata(
207
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
208
+ content, ret) {
209
+ // Add videoMetadata if defined
210
+ if ("videoMetadata" in content && typeof ret === "object") {
211
+ // eslint-disable-next-line no-param-reassign
212
+ ret.videoMetadata = content.videoMetadata;
213
+ }
214
+ return ret;
215
+ }
216
+ async function messageContentMedia(
217
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
218
+ content) {
219
+ const ret = await messageContentMediaData(content);
220
+ supplementVideoMetadata(content, ret);
221
+ return ret;
222
+ }
223
+ function messageContentReasoning(content) {
224
+ if (content?.reasoning && content?.reasoning.length > 0) {
225
+ return {
226
+ text: content.reasoning,
227
+ thought: true,
228
+ };
229
+ }
230
+ else {
231
+ return null;
232
+ }
233
+ }
201
234
  const standardContentBlockConverter = {
202
235
  providerName: "Google Gemini",
203
236
  fromStandardTextBlock(block) {
@@ -316,8 +349,10 @@ function getGeminiAPI(config) {
316
349
  break;
317
350
  case "media":
318
351
  return await messageContentMedia(content);
352
+ case "reasoning":
353
+ return messageContentReasoning(content);
319
354
  default:
320
- throw new Error(`Unsupported type "${content.type}" received while converting message to message parts: ${content}`);
355
+ throw new Error(`Unsupported type "${content.type}" received while converting message to message parts: ${JSON.stringify(content)}`);
321
356
  }
322
357
  throw new Error(`Cannot coerce "${content.type}" message part into a string.`);
323
358
  }
@@ -471,6 +506,12 @@ function getGeminiAPI(config) {
471
506
  return [];
472
507
  }
473
508
  }
509
+ function thoughtPartToMessageContent(part) {
510
+ return {
511
+ type: "reasoning",
512
+ reasoning: part.text,
513
+ };
514
+ }
474
515
  function textPartToMessageContent(part) {
475
516
  return {
476
517
  type: "text",
@@ -495,6 +536,9 @@ function getGeminiAPI(config) {
495
536
  if (part === undefined || part === null) {
496
537
  return null;
497
538
  }
539
+ else if (part.thought) {
540
+ return thoughtPartToMessageContent(part);
541
+ }
498
542
  else if ("text" in part) {
499
543
  return textPartToMessageContent(part);
500
544
  }
@@ -639,6 +683,19 @@ function getGeminiAPI(config) {
639
683
  content,
640
684
  };
641
685
  }
686
+ function candidateToUrlContextMetadata(candidate) {
687
+ const retrieval = candidate?.urlRetrievalMetadata?.urlRetrievalContexts ?? [];
688
+ const context = candidate?.urlContextMetadata?.urlMetadata ?? [];
689
+ const all = [...retrieval, ...context];
690
+ if (all.length === 0) {
691
+ return undefined;
692
+ }
693
+ else {
694
+ return {
695
+ urlMetadata: all,
696
+ };
697
+ }
698
+ }
642
699
  function addModalityCounts(modalityTokenCounts, details) {
643
700
  modalityTokenCounts?.forEach((modalityTokenCount) => {
644
701
  const { modality, tokenCount } = modalityTokenCount;
@@ -704,6 +761,7 @@ function getGeminiAPI(config) {
704
761
  grounding_metadata: data.candidates[0]?.groundingMetadata,
705
762
  finish_reason,
706
763
  finish_message: data.candidates[0]?.finishMessage,
764
+ url_context_metadata: candidateToUrlContextMetadata(data.candidates[0]),
707
765
  avgLogprobs: data.candidates[0]?.avgLogprobs,
708
766
  logprobs: candidateToLogprobs(data.candidates[0]),
709
767
  };
@@ -831,6 +889,7 @@ function getGeminiAPI(config) {
831
889
  if (typeof item.message.content === "string") {
832
890
  // If this is a string, turn it into a text type
833
891
  ret.push({
892
+ type: "text",
834
893
  text: item.message.content,
835
894
  });
836
895
  }
@@ -1094,10 +1153,10 @@ function getGeminiAPI(config) {
1094
1153
  // Add thinking configuration if explicitly set
1095
1154
  // Note that you cannot have thinkingBudget set to 0 and includeThoughts true
1096
1155
  if (typeof parameters.maxReasoningTokens !== "undefined") {
1156
+ const includeThoughts = parameters.maxReasoningTokens > 0;
1097
1157
  ret.thinkingConfig = {
1098
1158
  thinkingBudget: parameters.maxReasoningTokens,
1099
- // TODO: Expose this configuration to the user once google fully supports it
1100
- includeThoughts: false,
1159
+ includeThoughts,
1101
1160
  };
1102
1161
  }
1103
1162
  // Remove any undefined properties, so we don't send them
@@ -131,7 +131,7 @@ export function getGeminiAPI(config) {
131
131
  return null;
132
132
  }
133
133
  }
134
- function messageContentImageUrl(content) {
134
+ function messageContentImageUrlData(content) {
135
135
  const url = typeof content.image_url === "string"
136
136
  ? content.image_url
137
137
  : content.image_url.url;
@@ -154,6 +154,11 @@ export function getGeminiAPI(config) {
154
154
  };
155
155
  }
156
156
  }
157
+ function messageContentImageUrl(content) {
158
+ const ret = messageContentImageUrlData(content);
159
+ supplementVideoMetadata(content, ret);
160
+ return ret;
161
+ }
157
162
  async function blobToFileData(blob) {
158
163
  return {
159
164
  fileData: {
@@ -165,7 +170,7 @@ export function getGeminiAPI(config) {
165
170
  async function fileUriContentToBlob(uri) {
166
171
  return config?.mediaManager?.getMediaBlob(uri);
167
172
  }
168
- async function messageContentMedia(
173
+ async function messageContentMediaData(
169
174
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
170
175
  content) {
171
176
  if ("mimeType" in content && "data" in content) {
@@ -193,6 +198,34 @@ export function getGeminiAPI(config) {
193
198
  }
194
199
  throw new Error(`Invalid media content: ${JSON.stringify(content, null, 1)}`);
195
200
  }
201
+ function supplementVideoMetadata(
202
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
203
+ content, ret) {
204
+ // Add videoMetadata if defined
205
+ if ("videoMetadata" in content && typeof ret === "object") {
206
+ // eslint-disable-next-line no-param-reassign
207
+ ret.videoMetadata = content.videoMetadata;
208
+ }
209
+ return ret;
210
+ }
211
+ async function messageContentMedia(
212
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
213
+ content) {
214
+ const ret = await messageContentMediaData(content);
215
+ supplementVideoMetadata(content, ret);
216
+ return ret;
217
+ }
218
+ function messageContentReasoning(content) {
219
+ if (content?.reasoning && content?.reasoning.length > 0) {
220
+ return {
221
+ text: content.reasoning,
222
+ thought: true,
223
+ };
224
+ }
225
+ else {
226
+ return null;
227
+ }
228
+ }
196
229
  const standardContentBlockConverter = {
197
230
  providerName: "Google Gemini",
198
231
  fromStandardTextBlock(block) {
@@ -311,8 +344,10 @@ export function getGeminiAPI(config) {
311
344
  break;
312
345
  case "media":
313
346
  return await messageContentMedia(content);
347
+ case "reasoning":
348
+ return messageContentReasoning(content);
314
349
  default:
315
- throw new Error(`Unsupported type "${content.type}" received while converting message to message parts: ${content}`);
350
+ throw new Error(`Unsupported type "${content.type}" received while converting message to message parts: ${JSON.stringify(content)}`);
316
351
  }
317
352
  throw new Error(`Cannot coerce "${content.type}" message part into a string.`);
318
353
  }
@@ -466,6 +501,12 @@ export function getGeminiAPI(config) {
466
501
  return [];
467
502
  }
468
503
  }
504
+ function thoughtPartToMessageContent(part) {
505
+ return {
506
+ type: "reasoning",
507
+ reasoning: part.text,
508
+ };
509
+ }
469
510
  function textPartToMessageContent(part) {
470
511
  return {
471
512
  type: "text",
@@ -490,6 +531,9 @@ export function getGeminiAPI(config) {
490
531
  if (part === undefined || part === null) {
491
532
  return null;
492
533
  }
534
+ else if (part.thought) {
535
+ return thoughtPartToMessageContent(part);
536
+ }
493
537
  else if ("text" in part) {
494
538
  return textPartToMessageContent(part);
495
539
  }
@@ -634,6 +678,19 @@ export function getGeminiAPI(config) {
634
678
  content,
635
679
  };
636
680
  }
681
+ function candidateToUrlContextMetadata(candidate) {
682
+ const retrieval = candidate?.urlRetrievalMetadata?.urlRetrievalContexts ?? [];
683
+ const context = candidate?.urlContextMetadata?.urlMetadata ?? [];
684
+ const all = [...retrieval, ...context];
685
+ if (all.length === 0) {
686
+ return undefined;
687
+ }
688
+ else {
689
+ return {
690
+ urlMetadata: all,
691
+ };
692
+ }
693
+ }
637
694
  function addModalityCounts(modalityTokenCounts, details) {
638
695
  modalityTokenCounts?.forEach((modalityTokenCount) => {
639
696
  const { modality, tokenCount } = modalityTokenCount;
@@ -699,6 +756,7 @@ export function getGeminiAPI(config) {
699
756
  grounding_metadata: data.candidates[0]?.groundingMetadata,
700
757
  finish_reason,
701
758
  finish_message: data.candidates[0]?.finishMessage,
759
+ url_context_metadata: candidateToUrlContextMetadata(data.candidates[0]),
702
760
  avgLogprobs: data.candidates[0]?.avgLogprobs,
703
761
  logprobs: candidateToLogprobs(data.candidates[0]),
704
762
  };
@@ -826,6 +884,7 @@ export function getGeminiAPI(config) {
826
884
  if (typeof item.message.content === "string") {
827
885
  // If this is a string, turn it into a text type
828
886
  ret.push({
887
+ type: "text",
829
888
  text: item.message.content,
830
889
  });
831
890
  }
@@ -1089,10 +1148,10 @@ export function getGeminiAPI(config) {
1089
1148
  // Add thinking configuration if explicitly set
1090
1149
  // Note that you cannot have thinkingBudget set to 0 and includeThoughts true
1091
1150
  if (typeof parameters.maxReasoningTokens !== "undefined") {
1151
+ const includeThoughts = parameters.maxReasoningTokens > 0;
1092
1152
  ret.thinkingConfig = {
1093
1153
  thinkingBudget: parameters.maxReasoningTokens,
1094
- // TODO: Expose this configuration to the user once google fully supports it
1095
- includeThoughts: false,
1154
+ includeThoughts,
1096
1155
  };
1097
1156
  }
1098
1157
  // Remove any undefined properties, so we don't send them
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/google-common",
3
- "version": "0.2.9",
3
+ "version": "0.2.10",
4
4
  "description": "Core types and classes for Google services.",
5
5
  "type": "module",
6
6
  "engines": {
@@ -40,7 +40,7 @@
40
40
  },
41
41
  "devDependencies": {
42
42
  "@jest/globals": "^29.5.0",
43
- "@langchain/core": "0.3.55",
43
+ "@langchain/core": "0.3.57",
44
44
  "@langchain/scripts": ">=0.1.0 <0.2.0",
45
45
  "@swc/core": "^1.3.90",
46
46
  "@swc/jest": "^0.2.29",