google-genai 1.55.0__py3-none-any.whl → 1.57.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.
Files changed (88) hide show
  1. google/genai/_api_client.py +37 -18
  2. google/genai/_interactions/_base_client.py +8 -2
  3. google/genai/_interactions/resources/interactions.py +6 -6
  4. google/genai/_interactions/types/__init__.py +4 -0
  5. google/genai/_interactions/types/audio_content.py +0 -1
  6. google/genai/_interactions/types/audio_content_param.py +0 -1
  7. google/genai/_interactions/types/code_execution_call_content.py +0 -1
  8. google/genai/_interactions/types/code_execution_call_content_param.py +0 -1
  9. google/genai/_interactions/types/code_execution_result_content.py +0 -1
  10. google/genai/_interactions/types/code_execution_result_content_param.py +0 -1
  11. google/genai/_interactions/types/content.py +63 -0
  12. google/genai/_interactions/types/content_delta.py +7 -23
  13. google/genai/_interactions/types/content_param.py +61 -0
  14. google/genai/_interactions/types/content_start.py +4 -44
  15. google/genai/_interactions/types/deep_research_agent_config.py +0 -1
  16. google/genai/_interactions/types/deep_research_agent_config_param.py +0 -1
  17. google/genai/_interactions/types/document_content.py +3 -2
  18. google/genai/_interactions/types/document_content_param.py +3 -2
  19. google/genai/_interactions/types/document_mime_type.py +23 -0
  20. google/genai/_interactions/types/document_mime_type_param.py +25 -0
  21. google/genai/_interactions/types/dynamic_agent_config.py +0 -1
  22. google/genai/_interactions/types/dynamic_agent_config_param.py +0 -1
  23. google/genai/_interactions/types/file_search_result_content.py +0 -1
  24. google/genai/_interactions/types/file_search_result_content_param.py +0 -1
  25. google/genai/_interactions/types/function_call_content.py +0 -1
  26. google/genai/_interactions/types/function_call_content_param.py +0 -1
  27. google/genai/_interactions/types/function_result_content.py +1 -2
  28. google/genai/_interactions/types/function_result_content_param.py +1 -2
  29. google/genai/_interactions/types/google_search_call_content.py +0 -1
  30. google/genai/_interactions/types/google_search_call_content_param.py +0 -1
  31. google/genai/_interactions/types/google_search_result_content.py +0 -1
  32. google/genai/_interactions/types/google_search_result_content_param.py +0 -1
  33. google/genai/_interactions/types/image_content.py +1 -2
  34. google/genai/_interactions/types/image_content_param.py +1 -2
  35. google/genai/_interactions/types/interaction.py +4 -52
  36. google/genai/_interactions/types/interaction_create_params.py +2 -22
  37. google/genai/_interactions/types/mcp_server_tool_call_content.py +0 -1
  38. google/genai/_interactions/types/mcp_server_tool_call_content_param.py +0 -1
  39. google/genai/_interactions/types/mcp_server_tool_result_content.py +1 -2
  40. google/genai/_interactions/types/mcp_server_tool_result_content_param.py +1 -2
  41. google/genai/_interactions/types/model.py +1 -0
  42. google/genai/_interactions/types/model_param.py +1 -0
  43. google/genai/_interactions/types/text_content.py +0 -1
  44. google/genai/_interactions/types/text_content_param.py +0 -1
  45. google/genai/_interactions/types/thinking_level.py +1 -1
  46. google/genai/_interactions/types/thought_content.py +0 -1
  47. google/genai/_interactions/types/thought_content_param.py +0 -1
  48. google/genai/_interactions/types/turn.py +3 -44
  49. google/genai/_interactions/types/turn_param.py +4 -40
  50. google/genai/_interactions/types/url_context_call_content.py +0 -1
  51. google/genai/_interactions/types/url_context_call_content_param.py +0 -1
  52. google/genai/_interactions/types/url_context_result_content.py +0 -1
  53. google/genai/_interactions/types/url_context_result_content_param.py +0 -1
  54. google/genai/_interactions/types/usage.py +1 -1
  55. google/genai/_interactions/types/usage_param.py +1 -1
  56. google/genai/_interactions/types/video_content.py +1 -2
  57. google/genai/_interactions/types/video_content_param.py +1 -2
  58. google/genai/_live_converters.py +36 -64
  59. google/genai/_local_tokenizer_loader.py +1 -0
  60. google/genai/_tokens_converters.py +14 -14
  61. google/genai/batches.py +27 -22
  62. google/genai/caches.py +42 -42
  63. google/genai/chats.py +0 -2
  64. google/genai/client.py +3 -1
  65. google/genai/files.py +224 -0
  66. google/genai/models.py +57 -72
  67. google/genai/tests/chats/test_get_history.py +9 -8
  68. google/genai/tests/chats/test_validate_response.py +1 -1
  69. google/genai/tests/client/test_client_requests.py +1 -135
  70. google/genai/tests/files/test_register.py +272 -0
  71. google/genai/tests/files/test_register_table.py +70 -0
  72. google/genai/tests/interactions/test_auth.py +479 -0
  73. google/genai/tests/interactions/test_integration.py +2 -0
  74. google/genai/tests/interactions/test_paths.py +105 -0
  75. google/genai/tests/live/test_live.py +2 -36
  76. google/genai/tests/local_tokenizer/test_local_tokenizer.py +1 -1
  77. google/genai/tests/models/test_function_call_streaming.py +90 -90
  78. google/genai/tests/models/test_generate_content.py +1 -2
  79. google/genai/tests/models/test_recontext_image.py +1 -1
  80. google/genai/tests/pytest_helper.py +17 -0
  81. google/genai/tunings.py +1 -27
  82. google/genai/types.py +603 -518
  83. google/genai/version.py +1 -1
  84. {google_genai-1.55.0.dist-info → google_genai-1.57.0.dist-info}/METADATA +224 -22
  85. {google_genai-1.55.0.dist-info → google_genai-1.57.0.dist-info}/RECORD +88 -80
  86. {google_genai-1.55.0.dist-info → google_genai-1.57.0.dist-info}/WHEEL +0 -0
  87. {google_genai-1.55.0.dist-info → google_genai-1.57.0.dist-info}/licenses/LICENSE +0 -0
  88. {google_genai-1.55.0.dist-info → google_genai-1.57.0.dist-info}/top_level.txt +0 -0
google/genai/files.py CHANGED
@@ -22,6 +22,9 @@ import os
22
22
  from typing import Any, Optional, Union
23
23
  from urllib.parse import urlencode
24
24
 
25
+ import google.auth
26
+
27
+ from . import _api_client
25
28
  from . import _api_module
26
29
  from . import _common
27
30
  from . import _extra_utils
@@ -149,6 +152,33 @@ def _ListFilesResponse_from_mldev(
149
152
  return to_object
150
153
 
151
154
 
155
+ def _RegisterFilesParameters_to_mldev(
156
+ from_object: Union[dict[str, Any], object],
157
+ parent_object: Optional[dict[str, Any]] = None,
158
+ ) -> dict[str, Any]:
159
+ to_object: dict[str, Any] = {}
160
+ if getv(from_object, ['uris']) is not None:
161
+ setv(to_object, ['uris'], getv(from_object, ['uris']))
162
+
163
+ return to_object
164
+
165
+
166
+ def _RegisterFilesResponse_from_mldev(
167
+ from_object: Union[dict[str, Any], object],
168
+ parent_object: Optional[dict[str, Any]] = None,
169
+ ) -> dict[str, Any]:
170
+ to_object: dict[str, Any] = {}
171
+ if getv(from_object, ['sdkHttpResponse']) is not None:
172
+ setv(
173
+ to_object, ['sdk_http_response'], getv(from_object, ['sdkHttpResponse'])
174
+ )
175
+
176
+ if getv(from_object, ['files']) is not None:
177
+ setv(to_object, ['files'], [item for item in getv(from_object, ['files'])])
178
+
179
+ return to_object
180
+
181
+
152
182
  class Files(_api_module.BaseModule):
153
183
 
154
184
  def _list(
@@ -402,6 +432,69 @@ class Files(_api_module.BaseModule):
402
432
  self._api_client._verify_response(return_value)
403
433
  return return_value
404
434
 
435
+ def _register_files(
436
+ self,
437
+ *,
438
+ uris: list[str],
439
+ config: Optional[types.RegisterFilesConfigOrDict] = None,
440
+ ) -> types.RegisterFilesResponse:
441
+ parameter_model = types._RegisterFilesParameters(
442
+ uris=uris,
443
+ config=config,
444
+ )
445
+
446
+ request_url_dict: Optional[dict[str, str]]
447
+ if self._api_client.vertexai:
448
+ raise ValueError(
449
+ 'This method is only supported in the Gemini Developer client.'
450
+ )
451
+ else:
452
+ request_dict = _RegisterFilesParameters_to_mldev(parameter_model)
453
+ request_url_dict = request_dict.get('_url')
454
+ if request_url_dict:
455
+ path = 'files:register'.format_map(request_url_dict)
456
+ else:
457
+ path = 'files:register'
458
+
459
+ query_params = request_dict.get('_query')
460
+ if query_params:
461
+ path = f'{path}?{urlencode(query_params)}'
462
+ # TODO: remove the hack that pops config.
463
+ request_dict.pop('config', None)
464
+
465
+ http_options: Optional[types.HttpOptions] = None
466
+ if (
467
+ parameter_model.config is not None
468
+ and parameter_model.config.http_options is not None
469
+ ):
470
+ http_options = parameter_model.config.http_options
471
+
472
+ request_dict = _common.convert_to_dict(request_dict)
473
+ request_dict = _common.encode_unserializable_types(request_dict)
474
+
475
+ response = self._api_client.request(
476
+ 'post', path, request_dict, http_options
477
+ )
478
+
479
+ if config is not None and getattr(
480
+ config, 'should_return_http_response', None
481
+ ):
482
+ return_value = types.RegisterFilesResponse(sdk_http_response=response)
483
+ self._api_client._verify_response(return_value)
484
+ return return_value
485
+
486
+ response_dict = {} if not response.body else json.loads(response.body)
487
+
488
+ if not self._api_client.vertexai:
489
+ response_dict = _RegisterFilesResponse_from_mldev(response_dict)
490
+
491
+ return_value = types.RegisterFilesResponse._from_response(
492
+ response=response_dict, kwargs=parameter_model.model_dump()
493
+ )
494
+
495
+ self._api_client._verify_response(return_value)
496
+ return return_value
497
+
405
498
  def upload(
406
499
  self,
407
500
  *,
@@ -559,6 +652,39 @@ class Files(_api_module.BaseModule):
559
652
 
560
653
  return data
561
654
 
655
+ def register_files(
656
+ self,
657
+ *,
658
+ auth: google.auth.credentials.Credentials,
659
+ uris: list[str],
660
+ config: Optional[types.RegisterFilesConfigOrDict] = None,
661
+ ) -> types.RegisterFilesResponse:
662
+ """Registers gcs files with the file service."""
663
+ if not isinstance(auth, google.auth.credentials.Credentials):
664
+ raise ValueError(
665
+ 'auth must be a google.auth.credentials.Credentials object.'
666
+ )
667
+ if config is None:
668
+ config = types.RegisterFilesConfig()
669
+ else:
670
+ config = types.RegisterFilesConfig.model_validate(config)
671
+ config = config.model_copy(deep=True)
672
+
673
+ http_options = config.http_options or types.HttpOptions()
674
+ headers = http_options.headers or {}
675
+ headers = {k.lower(): v for k, v in headers.items()}
676
+
677
+ token = _api_client.get_token_from_credentials(self._api_client, auth)
678
+ headers['authorization'] = f'Bearer {token}'
679
+
680
+ if auth.quota_project_id:
681
+ headers['x-goog-user-project'] = auth.quota_project_id
682
+
683
+ http_options.headers = headers
684
+ config.http_options = http_options
685
+
686
+ return self._register_files(uris=uris, config=config)
687
+
562
688
  def list(
563
689
  self, *, config: Optional[types.ListFilesConfigOrDict] = None
564
690
  ) -> Pager[types.File]:
@@ -845,6 +971,69 @@ class AsyncFiles(_api_module.BaseModule):
845
971
  self._api_client._verify_response(return_value)
846
972
  return return_value
847
973
 
974
+ async def _register_files(
975
+ self,
976
+ *,
977
+ uris: list[str],
978
+ config: Optional[types.RegisterFilesConfigOrDict] = None,
979
+ ) -> types.RegisterFilesResponse:
980
+ parameter_model = types._RegisterFilesParameters(
981
+ uris=uris,
982
+ config=config,
983
+ )
984
+
985
+ request_url_dict: Optional[dict[str, str]]
986
+ if self._api_client.vertexai:
987
+ raise ValueError(
988
+ 'This method is only supported in the Gemini Developer client.'
989
+ )
990
+ else:
991
+ request_dict = _RegisterFilesParameters_to_mldev(parameter_model)
992
+ request_url_dict = request_dict.get('_url')
993
+ if request_url_dict:
994
+ path = 'files:register'.format_map(request_url_dict)
995
+ else:
996
+ path = 'files:register'
997
+
998
+ query_params = request_dict.get('_query')
999
+ if query_params:
1000
+ path = f'{path}?{urlencode(query_params)}'
1001
+ # TODO: remove the hack that pops config.
1002
+ request_dict.pop('config', None)
1003
+
1004
+ http_options: Optional[types.HttpOptions] = None
1005
+ if (
1006
+ parameter_model.config is not None
1007
+ and parameter_model.config.http_options is not None
1008
+ ):
1009
+ http_options = parameter_model.config.http_options
1010
+
1011
+ request_dict = _common.convert_to_dict(request_dict)
1012
+ request_dict = _common.encode_unserializable_types(request_dict)
1013
+
1014
+ response = await self._api_client.async_request(
1015
+ 'post', path, request_dict, http_options
1016
+ )
1017
+
1018
+ if config is not None and getattr(
1019
+ config, 'should_return_http_response', None
1020
+ ):
1021
+ return_value = types.RegisterFilesResponse(sdk_http_response=response)
1022
+ self._api_client._verify_response(return_value)
1023
+ return return_value
1024
+
1025
+ response_dict = {} if not response.body else json.loads(response.body)
1026
+
1027
+ if not self._api_client.vertexai:
1028
+ response_dict = _RegisterFilesResponse_from_mldev(response_dict)
1029
+
1030
+ return_value = types.RegisterFilesResponse._from_response(
1031
+ response=response_dict, kwargs=parameter_model.model_dump()
1032
+ )
1033
+
1034
+ self._api_client._verify_response(return_value)
1035
+ return return_value
1036
+
848
1037
  async def upload(
849
1038
  self,
850
1039
  *,
@@ -992,6 +1181,41 @@ class AsyncFiles(_api_module.BaseModule):
992
1181
 
993
1182
  return data
994
1183
 
1184
+ async def register_files(
1185
+ self,
1186
+ *,
1187
+ auth: google.auth.credentials.Credentials,
1188
+ uris: list[str],
1189
+ config: Optional[types.RegisterFilesConfigOrDict] = None,
1190
+ ) -> types.RegisterFilesResponse:
1191
+ """Registers gcs files with the file service."""
1192
+ if not isinstance(auth, google.auth.credentials.Credentials):
1193
+ raise ValueError(
1194
+ 'auth must be a google.auth.credentials.Credentials object.'
1195
+ )
1196
+ if config is None:
1197
+ config = types.RegisterFilesConfig()
1198
+ else:
1199
+ config = types.RegisterFilesConfig.model_validate(config)
1200
+ config = config.model_copy(deep=True)
1201
+
1202
+ http_options = config.http_options or types.HttpOptions()
1203
+ headers = http_options.headers or {}
1204
+ headers = {k.lower(): v for k, v in headers.items()}
1205
+
1206
+ token = await _api_client.async_get_token_from_credentials(
1207
+ self._api_client, auth
1208
+ )
1209
+ headers['authorization'] = f'Bearer {token}'
1210
+
1211
+ if auth.quota_project_id:
1212
+ headers['x-goog-user-project'] = auth.quota_project_id
1213
+
1214
+ http_options.headers = headers
1215
+ config.http_options = http_options
1216
+
1217
+ return await self._register_files(uris=uris, config=config)
1218
+
995
1219
  async def list(
996
1220
  self, *, config: Optional[types.ListFilesConfigOrDict] = None
997
1221
  ) -> AsyncPager[types.File]:
google/genai/models.py CHANGED
@@ -891,9 +891,6 @@ def _FunctionCallingConfig_to_mldev(
891
891
  parent_object: Optional[dict[str, Any]] = None,
892
892
  ) -> dict[str, Any]:
893
893
  to_object: dict[str, Any] = {}
894
- if getv(from_object, ['mode']) is not None:
895
- setv(to_object, ['mode'], getv(from_object, ['mode']))
896
-
897
894
  if getv(from_object, ['allowed_function_names']) is not None:
898
895
  setv(
899
896
  to_object,
@@ -901,6 +898,9 @@ def _FunctionCallingConfig_to_mldev(
901
898
  getv(from_object, ['allowed_function_names']),
902
899
  )
903
900
 
901
+ if getv(from_object, ['mode']) is not None:
902
+ setv(to_object, ['mode'], getv(from_object, ['mode']))
903
+
904
904
  if getv(from_object, ['stream_function_call_arguments']) is not None:
905
905
  raise ValueError(
906
906
  'stream_function_call_arguments parameter is not supported in Gemini'
@@ -915,9 +915,6 @@ def _FunctionDeclaration_to_vertex(
915
915
  parent_object: Optional[dict[str, Any]] = None,
916
916
  ) -> dict[str, Any]:
917
917
  to_object: dict[str, Any] = {}
918
- if getv(from_object, ['behavior']) is not None:
919
- raise ValueError('behavior parameter is not supported in Vertex AI.')
920
-
921
918
  if getv(from_object, ['description']) is not None:
922
919
  setv(to_object, ['description'], getv(from_object, ['description']))
923
920
 
@@ -944,6 +941,9 @@ def _FunctionDeclaration_to_vertex(
944
941
  getv(from_object, ['response_json_schema']),
945
942
  )
946
943
 
944
+ if getv(from_object, ['behavior']) is not None:
945
+ raise ValueError('behavior parameter is not supported in Vertex AI.')
946
+
947
947
  return to_object
948
948
 
949
949
 
@@ -1258,9 +1258,7 @@ def _GenerateContentConfig_to_vertex(
1258
1258
  setv(
1259
1259
  to_object,
1260
1260
  ['speechConfig'],
1261
- _SpeechConfig_to_vertex(
1262
- t.t_speech_config(getv(from_object, ['speech_config'])), to_object
1263
- ),
1261
+ t.t_speech_config(getv(from_object, ['speech_config'])),
1264
1262
  )
1265
1263
 
1266
1264
  if getv(from_object, ['audio_timestamp']) is not None:
@@ -2446,13 +2444,7 @@ def _GenerationConfig_to_vertex(
2446
2444
  setv(to_object, ['seed'], getv(from_object, ['seed']))
2447
2445
 
2448
2446
  if getv(from_object, ['speech_config']) is not None:
2449
- setv(
2450
- to_object,
2451
- ['speechConfig'],
2452
- _SpeechConfig_to_vertex(
2453
- getv(from_object, ['speech_config']), to_object
2454
- ),
2455
- )
2447
+ setv(to_object, ['speechConfig'], getv(from_object, ['speech_config']))
2456
2448
 
2457
2449
  if getv(from_object, ['stop_sequences']) is not None:
2458
2450
  setv(to_object, ['stopSequences'], getv(from_object, ['stop_sequences']))
@@ -2557,6 +2549,11 @@ def _ImageConfig_to_mldev(
2557
2549
  if getv(from_object, ['image_size']) is not None:
2558
2550
  setv(to_object, ['imageSize'], getv(from_object, ['image_size']))
2559
2551
 
2552
+ if getv(from_object, ['person_generation']) is not None:
2553
+ raise ValueError(
2554
+ 'person_generation parameter is not supported in Gemini API.'
2555
+ )
2556
+
2560
2557
  if getv(from_object, ['output_mime_type']) is not None:
2561
2558
  raise ValueError(
2562
2559
  'output_mime_type parameter is not supported in Gemini API.'
@@ -2581,6 +2578,13 @@ def _ImageConfig_to_vertex(
2581
2578
  if getv(from_object, ['image_size']) is not None:
2582
2579
  setv(to_object, ['imageSize'], getv(from_object, ['image_size']))
2583
2580
 
2581
+ if getv(from_object, ['person_generation']) is not None:
2582
+ setv(
2583
+ to_object,
2584
+ ['personGeneration'],
2585
+ getv(from_object, ['person_generation']),
2586
+ )
2587
+
2584
2588
  if getv(from_object, ['output_mime_type']) is not None:
2585
2589
  setv(
2586
2590
  to_object,
@@ -3427,30 +3431,16 @@ def _SegmentImageSource_to_vertex(
3427
3431
  return to_object
3428
3432
 
3429
3433
 
3430
- def _SpeechConfig_to_vertex(
3434
+ def _ToolConfig_to_mldev(
3431
3435
  from_object: Union[dict[str, Any], object],
3432
3436
  parent_object: Optional[dict[str, Any]] = None,
3433
3437
  ) -> dict[str, Any]:
3434
3438
  to_object: dict[str, Any] = {}
3435
- if getv(from_object, ['voice_config']) is not None:
3436
- setv(to_object, ['voiceConfig'], getv(from_object, ['voice_config']))
3437
-
3438
- if getv(from_object, ['language_code']) is not None:
3439
- setv(to_object, ['languageCode'], getv(from_object, ['language_code']))
3440
-
3441
- if getv(from_object, ['multi_speaker_voice_config']) is not None:
3442
- raise ValueError(
3443
- 'multi_speaker_voice_config parameter is not supported in Vertex AI.'
3439
+ if getv(from_object, ['retrieval_config']) is not None:
3440
+ setv(
3441
+ to_object, ['retrievalConfig'], getv(from_object, ['retrieval_config'])
3444
3442
  )
3445
3443
 
3446
- return to_object
3447
-
3448
-
3449
- def _ToolConfig_to_mldev(
3450
- from_object: Union[dict[str, Any], object],
3451
- parent_object: Optional[dict[str, Any]] = None,
3452
- ) -> dict[str, Any]:
3453
- to_object: dict[str, Any] = {}
3454
3444
  if getv(from_object, ['function_calling_config']) is not None:
3455
3445
  setv(
3456
3446
  to_object,
@@ -3460,11 +3450,6 @@ def _ToolConfig_to_mldev(
3460
3450
  ),
3461
3451
  )
3462
3452
 
3463
- if getv(from_object, ['retrieval_config']) is not None:
3464
- setv(
3465
- to_object, ['retrievalConfig'], getv(from_object, ['retrieval_config'])
3466
- )
3467
-
3468
3453
  return to_object
3469
3454
 
3470
3455
 
@@ -3473,23 +3458,9 @@ def _Tool_to_mldev(
3473
3458
  parent_object: Optional[dict[str, Any]] = None,
3474
3459
  ) -> dict[str, Any]:
3475
3460
  to_object: dict[str, Any] = {}
3476
- if getv(from_object, ['function_declarations']) is not None:
3477
- setv(
3478
- to_object,
3479
- ['functionDeclarations'],
3480
- [item for item in getv(from_object, ['function_declarations'])],
3481
- )
3482
-
3483
3461
  if getv(from_object, ['retrieval']) is not None:
3484
3462
  raise ValueError('retrieval parameter is not supported in Gemini API.')
3485
3463
 
3486
- if getv(from_object, ['google_search_retrieval']) is not None:
3487
- setv(
3488
- to_object,
3489
- ['googleSearchRetrieval'],
3490
- getv(from_object, ['google_search_retrieval']),
3491
- )
3492
-
3493
3464
  if getv(from_object, ['computer_use']) is not None:
3494
3465
  setv(to_object, ['computerUse'], getv(from_object, ['computer_use']))
3495
3466
 
@@ -3504,6 +3475,13 @@ def _Tool_to_mldev(
3504
3475
  'enterprise_web_search parameter is not supported in Gemini API.'
3505
3476
  )
3506
3477
 
3478
+ if getv(from_object, ['function_declarations']) is not None:
3479
+ setv(
3480
+ to_object,
3481
+ ['functionDeclarations'],
3482
+ [item for item in getv(from_object, ['function_declarations'])],
3483
+ )
3484
+
3507
3485
  if getv(from_object, ['google_maps']) is not None:
3508
3486
  setv(
3509
3487
  to_object,
@@ -3518,6 +3496,13 @@ def _Tool_to_mldev(
3518
3496
  _GoogleSearch_to_mldev(getv(from_object, ['google_search']), to_object),
3519
3497
  )
3520
3498
 
3499
+ if getv(from_object, ['google_search_retrieval']) is not None:
3500
+ setv(
3501
+ to_object,
3502
+ ['googleSearchRetrieval'],
3503
+ getv(from_object, ['google_search_retrieval']),
3504
+ )
3505
+
3521
3506
  if getv(from_object, ['url_context']) is not None:
3522
3507
  setv(to_object, ['urlContext'], getv(from_object, ['url_context']))
3523
3508
 
@@ -3529,26 +3514,9 @@ def _Tool_to_vertex(
3529
3514
  parent_object: Optional[dict[str, Any]] = None,
3530
3515
  ) -> dict[str, Any]:
3531
3516
  to_object: dict[str, Any] = {}
3532
- if getv(from_object, ['function_declarations']) is not None:
3533
- setv(
3534
- to_object,
3535
- ['functionDeclarations'],
3536
- [
3537
- _FunctionDeclaration_to_vertex(item, to_object)
3538
- for item in getv(from_object, ['function_declarations'])
3539
- ],
3540
- )
3541
-
3542
3517
  if getv(from_object, ['retrieval']) is not None:
3543
3518
  setv(to_object, ['retrieval'], getv(from_object, ['retrieval']))
3544
3519
 
3545
- if getv(from_object, ['google_search_retrieval']) is not None:
3546
- setv(
3547
- to_object,
3548
- ['googleSearchRetrieval'],
3549
- getv(from_object, ['google_search_retrieval']),
3550
- )
3551
-
3552
3520
  if getv(from_object, ['computer_use']) is not None:
3553
3521
  setv(to_object, ['computerUse'], getv(from_object, ['computer_use']))
3554
3522
 
@@ -3565,12 +3533,29 @@ def _Tool_to_vertex(
3565
3533
  getv(from_object, ['enterprise_web_search']),
3566
3534
  )
3567
3535
 
3536
+ if getv(from_object, ['function_declarations']) is not None:
3537
+ setv(
3538
+ to_object,
3539
+ ['functionDeclarations'],
3540
+ [
3541
+ _FunctionDeclaration_to_vertex(item, to_object)
3542
+ for item in getv(from_object, ['function_declarations'])
3543
+ ],
3544
+ )
3545
+
3568
3546
  if getv(from_object, ['google_maps']) is not None:
3569
3547
  setv(to_object, ['googleMaps'], getv(from_object, ['google_maps']))
3570
3548
 
3571
3549
  if getv(from_object, ['google_search']) is not None:
3572
3550
  setv(to_object, ['googleSearch'], getv(from_object, ['google_search']))
3573
3551
 
3552
+ if getv(from_object, ['google_search_retrieval']) is not None:
3553
+ setv(
3554
+ to_object,
3555
+ ['googleSearchRetrieval'],
3556
+ getv(from_object, ['google_search_retrieval']),
3557
+ )
3558
+
3574
3559
  if getv(from_object, ['url_context']) is not None:
3575
3560
  setv(to_object, ['urlContext'], getv(from_object, ['url_context']))
3576
3561
 
@@ -4454,7 +4439,7 @@ class Models(_api_module.BaseModule):
4454
4439
  image = product_recontext_response.generated_images[0].image
4455
4440
 
4456
4441
  virtual_try_on_response = client.models.recontext_image(
4457
- model="virtual-try-on-preview-08-04",
4442
+ model="virtual-try-on-001",
4458
4443
  source=types.RecontextImageSource(
4459
4444
  person_image=types.Image.from_file(IMAGE1_FILE_PATH),
4460
4445
  product_images=[types.ProductImage.from_file(IMAGE2_FILE_PATH)],
@@ -6298,7 +6283,7 @@ class AsyncModels(_api_module.BaseModule):
6298
6283
  image = product_recontext_response.generated_images[0].image
6299
6284
 
6300
6285
  virtual_try_on_response = client.models.recontext_image(
6301
- model="virtual-try-on-preview-08-04",
6286
+ model="virtual-try-on-001",
6302
6287
  source=types.RecontextImageSource(
6303
6288
  person_image=types.Image.from_file(IMAGE1_FILE_PATH),
6304
6289
  product_images=[types.ProductImage.from_file(IMAGE2_FILE_PATH)],
@@ -55,7 +55,7 @@ def mock_api_client(vertexai=False):
55
55
 
56
56
 
57
57
  @pytest.fixture
58
- def mock_generate_content_invalid_content():
58
+ def mock_generate_content_with_empty_text_part():
59
59
  with mock.patch.object(
60
60
  models.Models, 'generate_content'
61
61
  ) as mock_generate_content:
@@ -84,7 +84,7 @@ def mock_generate_content_empty_content():
84
84
 
85
85
 
86
86
  @pytest.fixture
87
- def mock_generate_content_stream_invalid_content():
87
+ def mock_generate_content_stream_with_empty_text_part():
88
88
  with mock.patch.object(
89
89
  models.Models, 'generate_content_stream'
90
90
  ) as mock_generate_content:
@@ -95,7 +95,8 @@ def mock_generate_content_stream_invalid_content():
95
95
  content=types.Content(
96
96
  role='model',
97
97
  parts=[types.Part(text='')],
98
- )
98
+ ),
99
+ finish_reason=types.FinishReason.STOP,
99
100
  )
100
101
  ]
101
102
  )
@@ -481,7 +482,7 @@ def test_history_with_invalid_turns():
481
482
  assert chat.get_history(curated=True) == curated_history
482
483
 
483
484
 
484
- def test_chat_with_invalid_content(mock_generate_content_invalid_content):
485
+ def test_chat_with_empty_text_part(mock_generate_content_with_empty_text_part):
485
486
  models_module = models.Models(mock_api_client)
486
487
  chats_module = chats.Chats(modules=models_module)
487
488
  chat = chats_module.create(model='gemini-2.5-flash')
@@ -496,7 +497,7 @@ def test_chat_with_invalid_content(mock_generate_content_invalid_content):
496
497
  ),
497
498
  ]
498
499
  assert chat.get_history() == expected_comprehensive_history
499
- assert not chat.get_history(curated=True)
500
+ assert chat.get_history(curated=True) == expected_comprehensive_history
500
501
 
501
502
 
502
503
  def test_chat_with_empty_content(mock_generate_content_empty_content):
@@ -517,8 +518,8 @@ def test_chat_with_empty_content(mock_generate_content_empty_content):
517
518
  assert not chat.get_history(curated=True)
518
519
 
519
520
 
520
- def test_chat_stream_with_invalid_content(
521
- mock_generate_content_stream_invalid_content,
521
+ def test_chat_stream_with_empty_text_part(
522
+ mock_generate_content_stream_with_empty_text_part,
522
523
  ):
523
524
  models_module = models.Models(mock_api_client)
524
525
  chats_module = chats.Chats(modules=models_module)
@@ -536,7 +537,7 @@ def test_chat_stream_with_invalid_content(
536
537
  ),
537
538
  ]
538
539
  assert chat.get_history() == expected_comprehensive_history
539
- assert not chat.get_history(curated=True)
540
+ assert chat.get_history(curated=True) == expected_comprehensive_history
540
541
 
541
542
 
542
543
  def test_chat_stream_with_empty_content(
@@ -53,7 +53,7 @@ def test_validate_response_part_with_empty_text():
53
53
  ]
54
54
  )
55
55
 
56
- assert not _validate_response(response)
56
+ assert _validate_response(response)
57
57
 
58
58
 
59
59
  def test_validate_response_part_with_text():