google-genai 1.42.0__py3-none-any.whl → 1.44.0__py3-none-any.whl

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.
@@ -547,6 +547,7 @@ class BaseApiClient:
547
547
  http_options: Optional[HttpOptionsOrDict] = None,
548
548
  ):
549
549
  self.vertexai = vertexai
550
+ self.custom_base_url = None
550
551
  if self.vertexai is None:
551
552
  if os.environ.get('GOOGLE_GENAI_USE_VERTEXAI', '0').lower() in [
552
553
  'true',
@@ -628,11 +629,17 @@ class BaseApiClient:
628
629
  )
629
630
  self.api_key = None
630
631
 
632
+ self.custom_base_url = (
633
+ validated_http_options.base_url
634
+ if validated_http_options.base_url
635
+ else None
636
+ )
637
+
631
638
  # Skip fetching project from ADC if base url is provided in http options.
632
639
  if (
633
640
  not self.project
634
641
  and not self.api_key
635
- and not validated_http_options.base_url
642
+ and not self.custom_base_url
636
643
  ):
637
644
  credentials, self.project = load_auth(project=None)
638
645
  if not self._credentials:
@@ -640,7 +647,7 @@ class BaseApiClient:
640
647
 
641
648
  has_sufficient_auth = (self.project and self.location) or self.api_key
642
649
 
643
- if not has_sufficient_auth and not validated_http_options.base_url:
650
+ if not has_sufficient_auth and not self.custom_base_url:
644
651
  # Skip sufficient auth check if base url is provided in http options.
645
652
  raise ValueError(
646
653
  'Project and location or API key must be set when using the Vertex '
@@ -648,9 +655,11 @@ class BaseApiClient:
648
655
  )
649
656
  if self.api_key or self.location == 'global':
650
657
  self._http_options.base_url = f'https://aiplatform.googleapis.com/'
651
- elif validated_http_options.base_url and not has_sufficient_auth:
658
+ elif self.custom_base_url and not has_sufficient_auth:
652
659
  # Avoid setting default base url and api version if base_url provided.
653
- self._http_options.base_url = validated_http_options.base_url
660
+ # API gateway proxy can use the auth in custom headers, not url.
661
+ # Enable custom url if auth is not sufficient.
662
+ self._http_options.base_url = self.custom_base_url
654
663
  else:
655
664
  self._http_options.base_url = (
656
665
  f'https://{self.location}-aiplatform.googleapis.com/'
@@ -897,6 +906,11 @@ class BaseApiClient:
897
906
  )
898
907
 
899
908
  def _websocket_base_url(self) -> str:
909
+ has_sufficient_auth = (self.project and self.location) or self.api_key
910
+ if self.custom_base_url and not has_sufficient_auth:
911
+ # API gateway proxy can use the auth in custom headers, not url.
912
+ # Enable custom url if auth is not sufficient.
913
+ return self.custom_base_url
900
914
  url_parts = urlparse(self._http_options.base_url)
901
915
  return url_parts._replace(scheme='wss').geturl() # type: ignore[arg-type, return-value]
902
916
 
@@ -229,6 +229,20 @@ def _GenerationConfig_to_vertex(
229
229
  return to_object
230
230
 
231
231
 
232
+ def _GoogleMaps_to_mldev(
233
+ from_object: Union[dict[str, Any], object],
234
+ parent_object: Optional[dict[str, Any]] = None,
235
+ ) -> dict[str, Any]:
236
+ to_object: dict[str, Any] = {}
237
+ if getv(from_object, ['auth_config']) is not None:
238
+ raise ValueError('auth_config parameter is not supported in Gemini API.')
239
+
240
+ if getv(from_object, ['enable_widget']) is not None:
241
+ setv(to_object, ['enableWidget'], getv(from_object, ['enable_widget']))
242
+
243
+ return to_object
244
+
245
+
232
246
  def _GoogleSearch_to_mldev(
233
247
  from_object: Union[dict[str, Any], object],
234
248
  parent_object: Optional[dict[str, Any]] = None,
@@ -1258,7 +1272,11 @@ def _Tool_to_mldev(
1258
1272
  )
1259
1273
 
1260
1274
  if getv(from_object, ['google_maps']) is not None:
1261
- raise ValueError('google_maps parameter is not supported in Gemini API.')
1275
+ setv(
1276
+ to_object,
1277
+ ['googleMaps'],
1278
+ _GoogleMaps_to_mldev(getv(from_object, ['google_maps']), to_object),
1279
+ )
1262
1280
 
1263
1281
  if getv(from_object, ['url_context']) is not None:
1264
1282
  setv(to_object, ['urlContext'], getv(from_object, ['url_context']))
@@ -201,11 +201,11 @@ def _GeneratedVideo_from_mldev(
201
201
  parent_object: Optional[dict[str, Any]] = None,
202
202
  ) -> dict[str, Any]:
203
203
  to_object: dict[str, Any] = {}
204
- if getv(from_object, ['_self']) is not None:
204
+ if getv(from_object, ['video']) is not None:
205
205
  setv(
206
206
  to_object,
207
207
  ['video'],
208
- _Video_from_mldev(getv(from_object, ['_self']), to_object),
208
+ _Video_from_mldev(getv(from_object, ['video']), to_object),
209
209
  )
210
210
 
211
211
  return to_object
@@ -261,14 +261,14 @@ def _Video_from_mldev(
261
261
  parent_object: Optional[dict[str, Any]] = None,
262
262
  ) -> dict[str, Any]:
263
263
  to_object: dict[str, Any] = {}
264
- if getv(from_object, ['video', 'uri']) is not None:
265
- setv(to_object, ['uri'], getv(from_object, ['video', 'uri']))
264
+ if getv(from_object, ['uri']) is not None:
265
+ setv(to_object, ['uri'], getv(from_object, ['uri']))
266
266
 
267
- if getv(from_object, ['video', 'encodedVideo']) is not None:
267
+ if getv(from_object, ['encodedVideo']) is not None:
268
268
  setv(
269
269
  to_object,
270
270
  ['video_bytes'],
271
- base_t.t_bytes(getv(from_object, ['video', 'encodedVideo'])),
271
+ base_t.t_bytes(getv(from_object, ['encodedVideo'])),
272
272
  )
273
273
 
274
274
  if getv(from_object, ['encoding']) is not None:
@@ -138,7 +138,7 @@ def _redact_request_url(url: str) -> str:
138
138
  result,
139
139
  )
140
140
  result = re.sub(
141
- r'https://generativelanguage.googleapis.com/[^/]+',
141
+ r'.*generativelanguage.*.googleapis.com/[^/]+',
142
142
  '{MLDEV_URL_PREFIX}',
143
143
  result,
144
144
  )
@@ -148,6 +148,20 @@ def _FileData_to_mldev(
148
148
  return to_object
149
149
 
150
150
 
151
+ def _GoogleMaps_to_mldev(
152
+ from_object: Union[dict[str, Any], object],
153
+ parent_object: Optional[dict[str, Any]] = None,
154
+ ) -> dict[str, Any]:
155
+ to_object: dict[str, Any] = {}
156
+ if getv(from_object, ['auth_config']) is not None:
157
+ raise ValueError('auth_config parameter is not supported in Gemini API.')
158
+
159
+ if getv(from_object, ['enable_widget']) is not None:
160
+ setv(to_object, ['enableWidget'], getv(from_object, ['enable_widget']))
161
+
162
+ return to_object
163
+
164
+
151
165
  def _GoogleSearch_to_mldev(
152
166
  from_object: Union[dict[str, Any], object],
153
167
  parent_object: Optional[dict[str, Any]] = None,
@@ -448,7 +462,11 @@ def _Tool_to_mldev(
448
462
  )
449
463
 
450
464
  if getv(from_object, ['google_maps']) is not None:
451
- raise ValueError('google_maps parameter is not supported in Gemini API.')
465
+ setv(
466
+ to_object,
467
+ ['googleMaps'],
468
+ _GoogleMaps_to_mldev(getv(from_object, ['google_maps']), to_object),
469
+ )
452
470
 
453
471
  if getv(from_object, ['url_context']) is not None:
454
472
  setv(to_object, ['urlContext'], getv(from_object, ['url_context']))
@@ -41,28 +41,6 @@ from . import types
41
41
 
42
42
  logger = logging.getLogger('google_genai._transformers')
43
43
 
44
-
45
- def _is_duck_type_of(obj: Any, cls: type[pydantic.BaseModel]) -> bool:
46
- """Checks if an object has all of the fields of a Pydantic model.
47
-
48
- This is a duck-typing alternative to `isinstance` to solve dual-import
49
- problems. It returns False for dictionaries, which should be handled by
50
- `isinstance(obj, dict)`.
51
-
52
- Args:
53
- obj: The object to check.
54
- cls: The Pydantic model class to duck-type against.
55
-
56
- Returns:
57
- True if the object has all the fields defined in the Pydantic model, False
58
- otherwise.
59
- """
60
- if isinstance(obj, dict) or not hasattr(cls, 'model_fields'):
61
- return False
62
-
63
- # Check if the object has all of the Pydantic model's defined fields.
64
- return all(hasattr(obj, field) for field in cls.model_fields)
65
-
66
44
  if sys.version_info >= (3, 10):
67
45
  VersionedUnionType = builtin_types.UnionType
68
46
  _UNION_TYPES = (typing.Union, builtin_types.UnionType)
@@ -94,6 +72,28 @@ metric_name_sdk_api_map = {
94
72
  metric_name_api_sdk_map = {v: k for k, v in metric_name_sdk_api_map.items()}
95
73
 
96
74
 
75
+ def _is_duck_type_of(obj: Any, cls: type[pydantic.BaseModel]) -> bool:
76
+ """Checks if an object has all of the fields of a Pydantic model.
77
+
78
+ This is a duck-typing alternative to `isinstance` to solve dual-import
79
+ problems. It returns False for dictionaries, which should be handled by
80
+ `isinstance(obj, dict)`.
81
+
82
+ Args:
83
+ obj: The object to check.
84
+ cls: The Pydantic model class to duck-type against.
85
+
86
+ Returns:
87
+ True if the object has all the fields defined in the Pydantic model, False
88
+ otherwise.
89
+ """
90
+ if isinstance(obj, dict) or not hasattr(cls, 'model_fields'):
91
+ return False
92
+
93
+ # Check if the object has all of the Pydantic model's defined fields.
94
+ return all(hasattr(obj, field) for field in cls.model_fields)
95
+
96
+
97
97
  def _resource_name(
98
98
  client: _api_client.BaseApiClient,
99
99
  resource_name: str,
@@ -306,7 +306,7 @@ def t_function_response(
306
306
  raise ValueError('function_response is required.')
307
307
  if isinstance(function_response, dict):
308
308
  return types.FunctionResponse.model_validate(function_response)
309
- elif isinstance(function_response, types.FunctionResponse):
309
+ elif _is_duck_type_of(function_response, types.FunctionResponse):
310
310
  return function_response
311
311
  else:
312
312
  raise TypeError(
@@ -342,8 +342,8 @@ def t_blob(blob: types.BlobImageUnionDict) -> types.Blob:
342
342
  if not blob:
343
343
  raise ValueError('blob is required.')
344
344
 
345
- if isinstance(blob, types.Blob):
346
- return blob
345
+ if _is_duck_type_of(blob, types.Blob):
346
+ return blob # type: ignore[return-value]
347
347
 
348
348
  if isinstance(blob, dict):
349
349
  return types.Blob.model_validate(blob)
@@ -383,10 +383,10 @@ def t_part(part: Optional[types.PartUnionDict]) -> types.Part:
383
383
  raise ValueError('content part is required.')
384
384
  if isinstance(part, str):
385
385
  return types.Part(text=part)
386
- if isinstance(part, types.File):
387
- if not part.uri or not part.mime_type:
386
+ if _is_duck_type_of(part, types.File):
387
+ if not part.uri or not part.mime_type: # type: ignore[union-attr]
388
388
  raise ValueError('file uri and mime_type are required.')
389
- return types.Part.from_uri(file_uri=part.uri, mime_type=part.mime_type)
389
+ return types.Part.from_uri(file_uri=part.uri, mime_type=part.mime_type) # type: ignore[union-attr]
390
390
  if isinstance(part, dict):
391
391
  try:
392
392
  return types.Part.model_validate(part)
@@ -449,8 +449,8 @@ def t_content(
449
449
  ) -> types.Content:
450
450
  if content is None:
451
451
  raise ValueError('content is required.')
452
- if isinstance(content, types.Content):
453
- return content
452
+ if _is_duck_type_of(content, types.Content):
453
+ return content # type: ignore[return-value]
454
454
  if isinstance(content, dict):
455
455
  try:
456
456
  return types.Content.model_validate(content)
@@ -461,15 +461,15 @@ def t_content(
461
461
  if possible_part.function_call
462
462
  else types.UserContent(parts=[possible_part])
463
463
  )
464
- if isinstance(content, types.File):
465
- return types.UserContent(parts=[t_part(content)])
466
- if isinstance(content, types.Part):
464
+ if _is_duck_type_of(content, types.File):
465
+ return types.UserContent(parts=[t_part(content)]) # type: ignore[arg-type]
466
+ if _is_duck_type_of(content, types.Part):
467
467
  return (
468
- types.ModelContent(parts=[content])
469
- if content.function_call
470
- else types.UserContent(parts=[content])
468
+ types.ModelContent(parts=[content]) # type: ignore[arg-type]
469
+ if content.function_call # type: ignore[union-attr]
470
+ else types.UserContent(parts=[content]) # type: ignore[arg-type]
471
471
  )
472
- return types.UserContent(parts=content)
472
+ return types.UserContent(parts=content) # type: ignore[arg-type]
473
473
 
474
474
 
475
475
  def t_contents_for_embed(
@@ -516,8 +516,8 @@ def t_contents(
516
516
  ) -> TypeGuard[types.PartUnionDict]:
517
517
  if (
518
518
  isinstance(part, str)
519
- or isinstance(part, types.File)
520
- or isinstance(part, types.Part)
519
+ or _is_duck_type_of(part, types.File)
520
+ or _is_duck_type_of(part, types.Part)
521
521
  ):
522
522
  return True
523
523
 
@@ -884,12 +884,12 @@ def t_schema(
884
884
  return types.Schema.model_validate(origin)
885
885
  if isinstance(origin, EnumMeta):
886
886
  return _process_enum(origin, client)
887
- if isinstance(origin, types.Schema):
888
- if dict(origin) == dict(types.Schema()):
887
+ if _is_duck_type_of(origin, types.Schema):
888
+ if dict(origin) == dict(types.Schema()): # type: ignore [arg-type]
889
889
  # response_schema value was coerced to an empty Schema instance because
890
890
  # it did not adhere to the Schema field annotation
891
891
  _raise_for_unsupported_schema_type(origin)
892
- schema = origin.model_dump(exclude_unset=True)
892
+ schema = origin.model_dump(exclude_unset=True) # type: ignore[union-attr]
893
893
  process_schema(schema, client)
894
894
  return types.Schema.model_validate(schema)
895
895
 
@@ -926,8 +926,8 @@ def t_speech_config(
926
926
  ) -> Optional[types.SpeechConfig]:
927
927
  if not origin:
928
928
  return None
929
- if isinstance(origin, types.SpeechConfig):
930
- return origin
929
+ if _is_duck_type_of(origin, types.SpeechConfig):
930
+ return origin # type: ignore[return-value]
931
931
  if isinstance(origin, str):
932
932
  return types.SpeechConfig(
933
933
  voice_config=types.VoiceConfig(
@@ -943,17 +943,17 @@ def t_speech_config(
943
943
  def t_live_speech_config(
944
944
  origin: types.SpeechConfigOrDict,
945
945
  ) -> Optional[types.SpeechConfig]:
946
- if isinstance(origin, types.SpeechConfig):
946
+ if _is_duck_type_of(origin, types.SpeechConfig):
947
947
  speech_config = origin
948
948
  if isinstance(origin, dict):
949
949
  speech_config = types.SpeechConfig.model_validate(origin)
950
950
 
951
- if speech_config.multi_speaker_voice_config is not None:
951
+ if speech_config.multi_speaker_voice_config is not None: # type: ignore[union-attr]
952
952
  raise ValueError(
953
953
  'multi_speaker_voice_config is not supported in the live API.'
954
954
  )
955
955
 
956
- return speech_config
956
+ return speech_config # type: ignore[return-value]
957
957
 
958
958
 
959
959
  def t_tool(
@@ -969,7 +969,7 @@ def t_tool(
969
969
  )
970
970
  ]
971
971
  )
972
- elif McpTool is not None and isinstance(origin, McpTool):
972
+ elif McpTool is not None and _is_duck_type_of(origin, McpTool):
973
973
  return mcp_to_gemini_tool(origin)
974
974
  elif isinstance(origin, dict):
975
975
  return types.Tool.model_validate(origin)
@@ -1012,13 +1012,13 @@ def t_batch_job_source(
1012
1012
  ) -> types.BatchJobSource:
1013
1013
  if isinstance(src, dict):
1014
1014
  src = types.BatchJobSource(**src)
1015
- if isinstance(src, types.BatchJobSource):
1015
+ if _is_duck_type_of(src, types.BatchJobSource):
1016
1016
  vertex_sources = sum(
1017
- [src.gcs_uri is not None, src.bigquery_uri is not None]
1017
+ [src.gcs_uri is not None, src.bigquery_uri is not None] # type: ignore[union-attr]
1018
1018
  )
1019
1019
  mldev_sources = sum([
1020
- src.inlined_requests is not None,
1021
- src.file_name is not None,
1020
+ src.inlined_requests is not None, # type: ignore[union-attr]
1021
+ src.file_name is not None, # type: ignore[union-attr]
1022
1022
  ])
1023
1023
  if client.vertexai:
1024
1024
  if mldev_sources or vertex_sources != 1:
@@ -1033,7 +1033,7 @@ def t_batch_job_source(
1033
1033
  '`inlined_embed_content_requests`, or `embed_content_file_name` '
1034
1034
  'must be set, other sources are not supported in Gemini API.'
1035
1035
  )
1036
- return src
1036
+ return src # type: ignore[return-value]
1037
1037
 
1038
1038
  elif isinstance(src, list):
1039
1039
  return types.BatchJobSource(inlined_requests=src)
@@ -1063,7 +1063,7 @@ def t_embedding_batch_job_source(
1063
1063
  if isinstance(src, dict):
1064
1064
  src = types.EmbeddingsBatchJobSource(**src)
1065
1065
 
1066
- if isinstance(src, types.EmbeddingsBatchJobSource):
1066
+ if _is_duck_type_of(src, types.EmbeddingsBatchJobSource):
1067
1067
  mldev_sources = sum([
1068
1068
  src.inlined_requests is not None,
1069
1069
  src.file_name is not None,
@@ -1098,7 +1098,7 @@ def t_batch_job_destination(
1098
1098
  )
1099
1099
  else:
1100
1100
  raise ValueError(f'Unsupported destination: {dest}')
1101
- elif isinstance(dest, types.BatchJobDestination):
1101
+ elif _is_duck_type_of(dest, types.BatchJobDestination):
1102
1102
  return dest
1103
1103
  else:
1104
1104
  raise ValueError(f'Unsupported destination: {dest}')
@@ -1198,13 +1198,13 @@ def t_file_name(
1198
1198
  name: Optional[Union[str, types.File, types.Video, types.GeneratedVideo]],
1199
1199
  ) -> str:
1200
1200
  # Remove the files/ prefix since it's added to the url path.
1201
- if isinstance(name, types.File):
1202
- name = name.name
1203
- elif isinstance(name, types.Video):
1204
- name = name.uri
1205
- elif isinstance(name, types.GeneratedVideo):
1206
- if name.video is not None:
1207
- name = name.video.uri
1201
+ if _is_duck_type_of(name, types.File):
1202
+ name = name.name # type: ignore[union-attr]
1203
+ elif _is_duck_type_of(name, types.Video):
1204
+ name = name.uri # type: ignore[union-attr]
1205
+ elif _is_duck_type_of(name, types.GeneratedVideo):
1206
+ if name.video is not None: # type: ignore[union-attr]
1207
+ name = name.video.uri # type: ignore[union-attr]
1208
1208
  else:
1209
1209
  name = None
1210
1210
 
@@ -1247,7 +1247,7 @@ def t_tuning_job_status(status: str) -> Union[types.JobState, str]:
1247
1247
  def t_content_strict(content: types.ContentOrDict) -> types.Content:
1248
1248
  if isinstance(content, dict):
1249
1249
  return types.Content.model_validate(content)
1250
- elif isinstance(content, types.Content):
1250
+ elif _is_duck_type_of(content, types.Content):
1251
1251
  return content
1252
1252
  else:
1253
1253
  raise ValueError(
google/genai/batches.py CHANGED
@@ -1016,6 +1016,20 @@ def _GetBatchJobParameters_to_vertex(
1016
1016
  return to_object
1017
1017
 
1018
1018
 
1019
+ def _GoogleMaps_to_mldev(
1020
+ from_object: Union[dict[str, Any], object],
1021
+ parent_object: Optional[dict[str, Any]] = None,
1022
+ ) -> dict[str, Any]:
1023
+ to_object: dict[str, Any] = {}
1024
+ if getv(from_object, ['auth_config']) is not None:
1025
+ raise ValueError('auth_config parameter is not supported in Gemini API.')
1026
+
1027
+ if getv(from_object, ['enable_widget']) is not None:
1028
+ setv(to_object, ['enableWidget'], getv(from_object, ['enable_widget']))
1029
+
1030
+ return to_object
1031
+
1032
+
1019
1033
  def _GoogleSearch_to_mldev(
1020
1034
  from_object: Union[dict[str, Any], object],
1021
1035
  parent_object: Optional[dict[str, Any]] = None,
@@ -1057,6 +1071,9 @@ def _InlinedRequest_to_mldev(
1057
1071
  ],
1058
1072
  )
1059
1073
 
1074
+ if getv(from_object, ['metadata']) is not None:
1075
+ setv(to_object, ['metadata'], getv(from_object, ['metadata']))
1076
+
1060
1077
  if getv(from_object, ['config']) is not None:
1061
1078
  setv(
1062
1079
  to_object,
@@ -1323,7 +1340,11 @@ def _Tool_to_mldev(
1323
1340
  )
1324
1341
 
1325
1342
  if getv(from_object, ['google_maps']) is not None:
1326
- raise ValueError('google_maps parameter is not supported in Gemini API.')
1343
+ setv(
1344
+ to_object,
1345
+ ['googleMaps'],
1346
+ _GoogleMaps_to_mldev(getv(from_object, ['google_maps']), to_object),
1347
+ )
1327
1348
 
1328
1349
  if getv(from_object, ['url_context']) is not None:
1329
1350
  setv(to_object, ['urlContext'], getv(from_object, ['url_context']))
google/genai/caches.py CHANGED
@@ -362,6 +362,20 @@ def _GetCachedContentParameters_to_vertex(
362
362
  return to_object
363
363
 
364
364
 
365
+ def _GoogleMaps_to_mldev(
366
+ from_object: Union[dict[str, Any], object],
367
+ parent_object: Optional[dict[str, Any]] = None,
368
+ ) -> dict[str, Any]:
369
+ to_object: dict[str, Any] = {}
370
+ if getv(from_object, ['auth_config']) is not None:
371
+ raise ValueError('auth_config parameter is not supported in Gemini API.')
372
+
373
+ if getv(from_object, ['enable_widget']) is not None:
374
+ setv(to_object, ['enableWidget'], getv(from_object, ['enable_widget']))
375
+
376
+ return to_object
377
+
378
+
365
379
  def _GoogleSearch_to_mldev(
366
380
  from_object: Union[dict[str, Any], object],
367
381
  parent_object: Optional[dict[str, Any]] = None,
@@ -585,7 +599,11 @@ def _Tool_to_mldev(
585
599
  )
586
600
 
587
601
  if getv(from_object, ['google_maps']) is not None:
588
- raise ValueError('google_maps parameter is not supported in Gemini API.')
602
+ setv(
603
+ to_object,
604
+ ['googleMaps'],
605
+ _GoogleMaps_to_mldev(getv(from_object, ['google_maps']), to_object),
606
+ )
589
607
 
590
608
  if getv(from_object, ['url_context']) is not None:
591
609
  setv(to_object, ['urlContext'], getv(from_object, ['url_context']))
google/genai/live.py CHANGED
@@ -980,7 +980,8 @@ class AsyncLive(_api_module.BaseModule):
980
980
  api_key = self._api_client.api_key
981
981
  version = self._api_client._http_options.api_version
982
982
  uri = f'{base_url}/ws/google.cloud.aiplatform.{version}.LlmBidiService/BidiGenerateContent'
983
- headers = self._api_client._http_options.headers or {}
983
+ original_headers = self._api_client._http_options.headers
984
+ headers = original_headers.copy() if original_headers is not None else {}
984
985
 
985
986
  request_dict = _common.convert_to_dict(
986
987
  live_converters._LiveConnectParameters_to_vertex(
@@ -1012,12 +1013,24 @@ class AsyncLive(_api_module.BaseModule):
1012
1013
  bearer_token = creds.token
1013
1014
  original_headers = self._api_client._http_options.headers
1014
1015
  headers = original_headers.copy() if original_headers is not None else {}
1015
- headers['Authorization'] = f'Bearer {bearer_token}'
1016
+ if not headers.get('Authorization'):
1017
+ headers['Authorization'] = f'Bearer {bearer_token}'
1016
1018
  version = self._api_client._http_options.api_version
1017
- uri = f'{base_url}/ws/google.cloud.aiplatform.{version}.LlmBidiService/BidiGenerateContent'
1019
+
1020
+ has_sufficient_auth = (
1021
+ self._api_client.project and self._api_client.location
1022
+ )
1023
+ if self._api_client.custom_base_url and not has_sufficient_auth:
1024
+ # API gateway proxy can use the auth in custom headers, not url.
1025
+ # Enable custom url if auth is not sufficient.
1026
+ uri = self._api_client.custom_base_url
1027
+ # Keep the model as is.
1028
+ transformed_model = model
1029
+ else:
1030
+ uri = f'{base_url}/ws/google.cloud.aiplatform.{version}.LlmBidiService/BidiGenerateContent'
1018
1031
  location = self._api_client.location
1019
1032
  project = self._api_client.project
1020
- if transformed_model.startswith('publishers/'):
1033
+ if transformed_model.startswith('publishers/') and project and location:
1021
1034
  transformed_model = (
1022
1035
  f'projects/{project}/locations/{location}/' + transformed_model
1023
1036
  )
google/genai/models.py CHANGED
@@ -2262,11 +2262,11 @@ def _GeneratedVideo_from_mldev(
2262
2262
  parent_object: Optional[dict[str, Any]] = None,
2263
2263
  ) -> dict[str, Any]:
2264
2264
  to_object: dict[str, Any] = {}
2265
- if getv(from_object, ['_self']) is not None:
2265
+ if getv(from_object, ['video']) is not None:
2266
2266
  setv(
2267
2267
  to_object,
2268
2268
  ['video'],
2269
- _Video_from_mldev(getv(from_object, ['_self']), to_object),
2269
+ _Video_from_mldev(getv(from_object, ['video']), to_object),
2270
2270
  )
2271
2271
 
2272
2272
  return to_object
@@ -2433,6 +2433,20 @@ def _GetModelParameters_to_vertex(
2433
2433
  return to_object
2434
2434
 
2435
2435
 
2436
+ def _GoogleMaps_to_mldev(
2437
+ from_object: Union[dict[str, Any], object],
2438
+ parent_object: Optional[dict[str, Any]] = None,
2439
+ ) -> dict[str, Any]:
2440
+ to_object: dict[str, Any] = {}
2441
+ if getv(from_object, ['auth_config']) is not None:
2442
+ raise ValueError('auth_config parameter is not supported in Gemini API.')
2443
+
2444
+ if getv(from_object, ['enable_widget']) is not None:
2445
+ setv(to_object, ['enableWidget'], getv(from_object, ['enable_widget']))
2446
+
2447
+ return to_object
2448
+
2449
+
2436
2450
  def _GoogleSearch_to_mldev(
2437
2451
  from_object: Union[dict[str, Any], object],
2438
2452
  parent_object: Optional[dict[str, Any]] = None,
@@ -3310,7 +3324,11 @@ def _Tool_to_mldev(
3310
3324
  )
3311
3325
 
3312
3326
  if getv(from_object, ['google_maps']) is not None:
3313
- raise ValueError('google_maps parameter is not supported in Gemini API.')
3327
+ setv(
3328
+ to_object,
3329
+ ['googleMaps'],
3330
+ _GoogleMaps_to_mldev(getv(from_object, ['google_maps']), to_object),
3331
+ )
3314
3332
 
3315
3333
  if getv(from_object, ['url_context']) is not None:
3316
3334
  setv(to_object, ['urlContext'], getv(from_object, ['url_context']))
@@ -3662,14 +3680,14 @@ def _Video_from_mldev(
3662
3680
  parent_object: Optional[dict[str, Any]] = None,
3663
3681
  ) -> dict[str, Any]:
3664
3682
  to_object: dict[str, Any] = {}
3665
- if getv(from_object, ['video', 'uri']) is not None:
3666
- setv(to_object, ['uri'], getv(from_object, ['video', 'uri']))
3683
+ if getv(from_object, ['uri']) is not None:
3684
+ setv(to_object, ['uri'], getv(from_object, ['uri']))
3667
3685
 
3668
- if getv(from_object, ['video', 'encodedVideo']) is not None:
3686
+ if getv(from_object, ['encodedVideo']) is not None:
3669
3687
  setv(
3670
3688
  to_object,
3671
3689
  ['video_bytes'],
3672
- base_t.t_bytes(getv(from_object, ['video', 'encodedVideo'])),
3690
+ base_t.t_bytes(getv(from_object, ['encodedVideo'])),
3673
3691
  )
3674
3692
 
3675
3693
  if getv(from_object, ['encoding']) is not None:
@@ -3705,12 +3723,12 @@ def _Video_to_mldev(
3705
3723
  ) -> dict[str, Any]:
3706
3724
  to_object: dict[str, Any] = {}
3707
3725
  if getv(from_object, ['uri']) is not None:
3708
- setv(to_object, ['video', 'uri'], getv(from_object, ['uri']))
3726
+ setv(to_object, ['uri'], getv(from_object, ['uri']))
3709
3727
 
3710
3728
  if getv(from_object, ['video_bytes']) is not None:
3711
3729
  setv(
3712
3730
  to_object,
3713
- ['video', 'encodedVideo'],
3731
+ ['encodedVideo'],
3714
3732
  base_t.t_bytes(getv(from_object, ['video_bytes'])),
3715
3733
  )
3716
3734
 
@@ -5430,6 +5448,36 @@ class Models(_api_module.BaseModule):
5430
5448
  'Source and prompt/image/video are mutually exclusive.'
5431
5449
  + ' Please only use source.'
5432
5450
  )
5451
+ # Gemini Developer API does not support video bytes.
5452
+ video_dct: dict[str, Any] = {}
5453
+ if not self._api_client.vertexai and video:
5454
+ if isinstance(video, types.Video):
5455
+ video_dct = video.model_dump()
5456
+ else:
5457
+ video_dct = dict(video)
5458
+
5459
+ if video_dct.get('uri') and video_dct.get('video_bytes'):
5460
+ video = types.Video(
5461
+ uri=video_dct.get('uri'), mime_type=video_dct.get('mime_type')
5462
+ )
5463
+ elif not self._api_client.vertexai and source:
5464
+ if isinstance(source, types.GenerateVideosSource):
5465
+ source_dct = source.model_dump()
5466
+ video_dct = source_dct.get('video', {})
5467
+ else:
5468
+ source_dct = dict(source)
5469
+ if isinstance(source_dct.get('video'), types.Video):
5470
+ video_obj: types.Video = source_dct.get('video', types.Video())
5471
+ video_dct = video_obj.model_dump()
5472
+ if video_dct and video_dct.get('uri') and video_dct.get('video_bytes'):
5473
+ source = types.GenerateVideosSource(
5474
+ prompt=source_dct.get('prompt'),
5475
+ image=source_dct.get('image'),
5476
+ video=types.Video(
5477
+ uri=video_dct.get('uri'),
5478
+ mime_type=video_dct.get('mime_type'),
5479
+ ),
5480
+ )
5433
5481
  return self._generate_videos(
5434
5482
  model=model,
5435
5483
  prompt=prompt,
google/genai/types.py CHANGED
@@ -2823,6 +2823,10 @@ class GoogleMaps(_common.BaseModel):
2823
2823
  default=None,
2824
2824
  description="""Optional. Auth config for the Google Maps tool.""",
2825
2825
  )
2826
+ enable_widget: Optional[bool] = Field(
2827
+ default=None,
2828
+ description="""Optional. If true, include the widget context token in the response.""",
2829
+ )
2826
2830
 
2827
2831
 
2828
2832
  class GoogleMapsDict(TypedDict, total=False):
@@ -2831,6 +2835,9 @@ class GoogleMapsDict(TypedDict, total=False):
2831
2835
  auth_config: Optional[AuthConfigDict]
2832
2836
  """Optional. Auth config for the Google Maps tool."""
2833
2837
 
2838
+ enable_widget: Optional[bool]
2839
+ """Optional. If true, include the widget context token in the response."""
2840
+
2834
2841
 
2835
2842
  GoogleMapsOrDict = Union[GoogleMaps, GoogleMapsDict]
2836
2843
 
@@ -4850,6 +4857,12 @@ class GroundingChunkMapsPlaceAnswerSourcesReviewSnippet(_common.BaseModel):
4850
4857
  default=None,
4851
4858
  description="""A reference representing this place review which may be used to look up this place review again.""",
4852
4859
  )
4860
+ review_id: Optional[str] = Field(
4861
+ default=None, description="""Id of the review referencing the place."""
4862
+ )
4863
+ title: Optional[str] = Field(
4864
+ default=None, description="""Title of the review."""
4865
+ )
4853
4866
 
4854
4867
 
4855
4868
  class GroundingChunkMapsPlaceAnswerSourcesReviewSnippetDict(
@@ -4874,6 +4887,12 @@ class GroundingChunkMapsPlaceAnswerSourcesReviewSnippetDict(
4874
4887
  review: Optional[str]
4875
4888
  """A reference representing this place review which may be used to look up this place review again."""
4876
4889
 
4890
+ review_id: Optional[str]
4891
+ """Id of the review referencing the place."""
4892
+
4893
+ title: Optional[str]
4894
+ """Title of the review."""
4895
+
4877
4896
 
4878
4897
  GroundingChunkMapsPlaceAnswerSourcesReviewSnippetOrDict = Union[
4879
4898
  GroundingChunkMapsPlaceAnswerSourcesReviewSnippet,
@@ -5234,6 +5253,39 @@ class SearchEntryPointDict(TypedDict, total=False):
5234
5253
  SearchEntryPointOrDict = Union[SearchEntryPoint, SearchEntryPointDict]
5235
5254
 
5236
5255
 
5256
+ class GroundingMetadataSourceFlaggingUri(_common.BaseModel):
5257
+ """Source content flagging uri for a place or review.
5258
+
5259
+ This is currently populated only for Google Maps grounding.
5260
+ """
5261
+
5262
+ flag_content_uri: Optional[str] = Field(
5263
+ default=None,
5264
+ description="""A link where users can flag a problem with the source (place or review).""",
5265
+ )
5266
+ source_id: Optional[str] = Field(
5267
+ default=None, description="""Id of the place or review."""
5268
+ )
5269
+
5270
+
5271
+ class GroundingMetadataSourceFlaggingUriDict(TypedDict, total=False):
5272
+ """Source content flagging uri for a place or review.
5273
+
5274
+ This is currently populated only for Google Maps grounding.
5275
+ """
5276
+
5277
+ flag_content_uri: Optional[str]
5278
+ """A link where users can flag a problem with the source (place or review)."""
5279
+
5280
+ source_id: Optional[str]
5281
+ """Id of the place or review."""
5282
+
5283
+
5284
+ GroundingMetadataSourceFlaggingUriOrDict = Union[
5285
+ GroundingMetadataSourceFlaggingUri, GroundingMetadataSourceFlaggingUriDict
5286
+ ]
5287
+
5288
+
5237
5289
  class GroundingMetadata(_common.BaseModel):
5238
5290
  """Metadata returned to client when grounding is enabled."""
5239
5291
 
@@ -5259,6 +5311,12 @@ class GroundingMetadata(_common.BaseModel):
5259
5311
  default=None,
5260
5312
  description="""Optional. Google search entry for the following-up web searches.""",
5261
5313
  )
5314
+ source_flagging_uris: Optional[list[GroundingMetadataSourceFlaggingUri]] = (
5315
+ Field(
5316
+ default=None,
5317
+ description="""Optional. Output only. List of source flagging uris. This is currently populated only for Google Maps grounding.""",
5318
+ )
5319
+ )
5262
5320
  web_search_queries: Optional[list[str]] = Field(
5263
5321
  default=None,
5264
5322
  description="""Optional. Web search queries for the following-up web search.""",
@@ -5286,6 +5344,9 @@ class GroundingMetadataDict(TypedDict, total=False):
5286
5344
  search_entry_point: Optional[SearchEntryPointDict]
5287
5345
  """Optional. Google search entry for the following-up web searches."""
5288
5346
 
5347
+ source_flagging_uris: Optional[list[GroundingMetadataSourceFlaggingUriDict]]
5348
+ """Optional. Output only. List of source flagging uris. This is currently populated only for Google Maps grounding."""
5349
+
5289
5350
  web_search_queries: Optional[list[str]]
5290
5351
  """Optional. Web search queries for the following-up web search."""
5291
5352
 
@@ -11705,6 +11766,10 @@ class InlinedRequest(_common.BaseModel):
11705
11766
  description="""Content of the request.
11706
11767
  """,
11707
11768
  )
11769
+ metadata: Optional[dict[str, str]] = Field(
11770
+ default=None,
11771
+ description="""The metadata to be associated with the request.""",
11772
+ )
11708
11773
  config: Optional[GenerateContentConfig] = Field(
11709
11774
  default=None,
11710
11775
  description="""Configuration that contains optional model parameters.
@@ -11723,6 +11788,9 @@ class InlinedRequestDict(TypedDict, total=False):
11723
11788
  """Content of the request.
11724
11789
  """
11725
11790
 
11791
+ metadata: Optional[dict[str, str]]
11792
+ """The metadata to be associated with the request."""
11793
+
11726
11794
  config: Optional[GenerateContentConfigDict]
11727
11795
  """Configuration that contains optional model parameters.
11728
11796
  """
google/genai/version.py CHANGED
@@ -13,4 +13,4 @@
13
13
  # limitations under the License.
14
14
  #
15
15
 
16
- __version__ = '1.42.0' # x-release-please-version
16
+ __version__ = '1.44.0' # x-release-please-version
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: google-genai
3
- Version: 1.42.0
3
+ Version: 1.44.0
4
4
  Summary: GenAI Python SDK
5
5
  Author-email: Google LLC <googleapis-packages@google.com>
6
6
  License: Apache-2.0
@@ -1,39 +1,39 @@
1
1
  google/genai/__init__.py,sha256=SKz_9WQKA3R4OpJIDJlgssVfizLNDG2tuWtOD9pxrPE,729
2
2
  google/genai/_adapters.py,sha256=Kok38miNYJff2n--l0zEK_hbq0y2rWOH7k75J7SMYbQ,1744
3
- google/genai/_api_client.py,sha256=uLgUFk9HC2xIJglFoxPXLUazN6uVmwqDHIJA_PbVIr0,62127
3
+ google/genai/_api_client.py,sha256=oTXkMUpmG0pfiE17wIGxhEBMOHT0-EOXE9k1mFF9XSs,62680
4
4
  google/genai/_api_module.py,sha256=lj8eUWx8_LBGBz-49qz6_ywWm3GYp3d8Bg5JoOHbtbI,902
5
5
  google/genai/_automatic_function_calling_util.py,sha256=xXNkJR-pzSMkeSXMz3Jw-kMHFbTJEiRJ3wocuwtWW4I,11627
6
6
  google/genai/_base_transformers.py,sha256=wljA6m4tLl4XLGlBC2DNOls5N9-X9tffBq0M7i8jgpw,1034
7
7
  google/genai/_base_url.py,sha256=E5H4dew14Y16qfnB3XRnjSCi19cJVlkaMNoM_8ip-PM,1597
8
8
  google/genai/_common.py,sha256=SWlfo_Yg6KK-gnSYUMU4EgWFvGmAbi99xPrp-ZR7atA,24150
9
9
  google/genai/_extra_utils.py,sha256=YLw64xzAKD_fQJp327-GGZM3kQ0sVdhNXMeDaaNkVFE,23011
10
- google/genai/_live_converters.py,sha256=J2-mFI182xTlKzHd6rFSHp743Ju8Fg05QUTbgEMkM8g,41592
10
+ google/genai/_live_converters.py,sha256=jhGi2U7G8XC27qE-9LY6B-jc5mAHK1vS_Nx9_-jBNF0,42115
11
11
  google/genai/_local_tokenizer_loader.py,sha256=cGN1F0f7hNjRIGCGTLeox7IGAZf_YcvZjSp2rCyhUak,7465
12
12
  google/genai/_mcp_utils.py,sha256=HuWJ8FUjquv40Mf_QjcL5r5yXWrS-JjINsjlOSbbyAc,3870
13
- google/genai/_operations_converters.py,sha256=hPmrlU_yJWT4di2arA0VKaoQIB1MbCPglmAZ4D8M-Ds,8744
14
- google/genai/_replay_api_client.py,sha256=E_tbw61TfOgxXhlKfoycN9X_5XaX5yBQHMnPj34w6nk,22731
13
+ google/genai/_operations_converters.py,sha256=8w4WSeA_KSyc56JcL1MTknZHIds0gF3E8YdriluUJfY,8708
14
+ google/genai/_replay_api_client.py,sha256=p8FyEtJ2kkAEPo62Q03zP6WsyH8-bhYR8se5T80tTN8,22727
15
15
  google/genai/_test_api_client.py,sha256=4ruFIy5_1qcbKqqIBu3HSQbpSOBrxiecBtDZaTGFR1s,4797
16
- google/genai/_tokens_converters.py,sha256=0a7GH3-tnM_JT3v7eSWYf7lGfRZ7m_WAZ_26OoL7Qa8,13614
17
- google/genai/_transformers.py,sha256=lW5gri3gEWR7n-wtujyvd4LTsS6-ff6hdVqOBX22VUg,42051
18
- google/genai/batches.py,sha256=YVq7BsIlW7mQgrPkZ_qSCVB2Kt_1G2l9jX38NFn7Eak,74345
19
- google/genai/caches.py,sha256=lG9SxUoWjGB-J0pwtmU2RakIvGDyOZnaSqe-eueV4eQ,44265
16
+ google/genai/_tokens_converters.py,sha256=xQY6yWtt7iJtfygfmd29d9mjjGKOpy0xG3yTdlr7APk,14137
17
+ google/genai/_transformers.py,sha256=tx6FecRkfQbEmmgXZrb8ndIRacAfluKIFlyQilslWG0,42782
18
+ google/genai/batches.py,sha256=wWkpsY7-a_jxkpkAu6PlbJ2VKRS7j8vy_a-BRPI-BZY,74986
19
+ google/genai/caches.py,sha256=uQLFO0JuzBGm1Gv92v2Dqp_QQ4qoPTX1vqI1grHyfKU,44788
20
20
  google/genai/chats.py,sha256=pIBw8d13llupLn4a7vP6vnpbzDcvCCrZZ-Q2r8Cvo7g,16652
21
21
  google/genai/client.py,sha256=bwKV5gHKpxzmfFTtoudQ_hEz5QfUzKYMJHYT-AnQfNU,13066
22
22
  google/genai/errors.py,sha256=dLH0Bo8-Y0K7zKASU5O0y_0FSKpSFJn8JPcnwIUvtIM,6089
23
23
  google/genai/files.py,sha256=2TkcZo7iviHA48OEjc9YnyirZ-umBUN7Z4Gdr4nHyJI,31551
24
- google/genai/live.py,sha256=e3oKgUV3hda-FP9Prx8cG0d8nPDKNRRJn5gn9oMlrXk,40413
24
+ google/genai/live.py,sha256=1YfDR2VTqeHp2YJkgX2j1KHDaLcGCLN4Y6O9T4cM-4U,40996
25
25
  google/genai/live_music.py,sha256=Y7I7jh5SAKgyjBIMLboH0oTnZJ18uOT2SpRDKURvp94,6783
26
26
  google/genai/local_tokenizer.py,sha256=EKZ72cV2Zfutlo_efMOPnLRNZN4WQe57rD3G80cF340,14109
27
- google/genai/models.py,sha256=sxiZyGuhci-dTpqb9a-zKCYdJBIQm6RiMk34xNq4RX0,224324
27
+ google/genai/models.py,sha256=TDLTUqTaUPxsm7NBACd_T9M9fo7vkjvpsskO0zNkMzQ,226022
28
28
  google/genai/operations.py,sha256=KgM5vsagUnAMGk9wKxuQYBUh_6bwrPQ9BzZvydiumQA,16208
29
29
  google/genai/pagers.py,sha256=m0SfWWn1EJs2k1On3DZx371qb8g2BRm_188ExsicIRc,7098
30
30
  google/genai/py.typed,sha256=RsMFoLwBkAvY05t6izop4UHZtqOPLiKp3GkIEizzmQY,40
31
31
  google/genai/tokens.py,sha256=4BPW0gGWFeFVk3INkuY2tfREnsrvzQDhouvRI6_F9Q8,12235
32
32
  google/genai/tunings.py,sha256=VmCBW_RR16QbzVpimi7pTEv6XTVeyDGpwqmJqetUj0o,58175
33
- google/genai/types.py,sha256=n9PvKsdTgydZug-6JbjIjnEk6WvXb5nut_zF6tHjWLk,558477
34
- google/genai/version.py,sha256=IywLlohBT1FvKiX8GIR6rqqIZVkzZF3HmTK_9TuJN5o,627
35
- google_genai-1.42.0.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
36
- google_genai-1.42.0.dist-info/METADATA,sha256=eDIdLeToHF_DET2M-_wgH2xjjyb_3-zJPgp3Ya6Z5Vc,45280
37
- google_genai-1.42.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
38
- google_genai-1.42.0.dist-info/top_level.txt,sha256=_1QvSJIhFAGfxb79D6DhB7SUw2X6T4rwnz_LLrbcD3c,7
39
- google_genai-1.42.0.dist-info/RECORD,,
33
+ google/genai/types.py,sha256=oqO4Jz5fi_QG-Qn-NhDc8frOS4ezU30A-iHSuVLLyXU,560764
34
+ google/genai/version.py,sha256=0a7FbSHg9E9Hna1gzIXHqRPylS_ExnriVNkKmCT0SxQ,627
35
+ google_genai-1.44.0.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
36
+ google_genai-1.44.0.dist-info/METADATA,sha256=V2p7mXdE4WchoCapPeQZ-EUDtRhHKy2dD3zDk6StyQU,45280
37
+ google_genai-1.44.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
38
+ google_genai-1.44.0.dist-info/top_level.txt,sha256=_1QvSJIhFAGfxb79D6DhB7SUw2X6T4rwnz_LLrbcD3c,7
39
+ google_genai-1.44.0.dist-info/RECORD,,