google-genai 1.22.0__py3-none-any.whl → 1.23.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.
- google/genai/_api_client.py +85 -8
- google/genai/live.py +4 -1
- google/genai/tunings.py +24 -0
- google/genai/types.py +16 -2
- google/genai/version.py +1 -1
- {google_genai-1.22.0.dist-info → google_genai-1.23.0.dist-info}/METADATA +51 -2
- {google_genai-1.22.0.dist-info → google_genai-1.23.0.dist-info}/RECORD +10 -10
- {google_genai-1.22.0.dist-info → google_genai-1.23.0.dist-info}/WHEEL +0 -0
- {google_genai-1.22.0.dist-info → google_genai-1.23.0.dist-info}/licenses/LICENSE +0 -0
- {google_genai-1.22.0.dist-info → google_genai-1.23.0.dist-info}/top_level.txt +0 -0
google/genai/_api_client.py
CHANGED
@@ -60,6 +60,11 @@ from .types import HttpOptionsOrDict
|
|
60
60
|
from .types import HttpResponse as SdkHttpResponse
|
61
61
|
from .types import HttpRetryOptions
|
62
62
|
|
63
|
+
try:
|
64
|
+
from websockets.asyncio.client import connect as ws_connect
|
65
|
+
except ModuleNotFoundError:
|
66
|
+
# This try/except is for TAP, mypy complains about it which is why we have the type: ignore
|
67
|
+
from websockets.client import connect as ws_connect # type: ignore
|
63
68
|
|
64
69
|
has_aiohttp = False
|
65
70
|
try:
|
@@ -227,11 +232,13 @@ class HttpResponse:
|
|
227
232
|
headers: Union[dict[str, str], httpx.Headers, 'CIMultiDictProxy[str]'],
|
228
233
|
response_stream: Union[Any, str] = None,
|
229
234
|
byte_stream: Union[Any, bytes] = None,
|
235
|
+
session: Optional['aiohttp.ClientSession'] = None,
|
230
236
|
):
|
231
237
|
self.status_code: int = 200
|
232
238
|
self.headers = headers
|
233
239
|
self.response_stream = response_stream
|
234
240
|
self.byte_stream = byte_stream
|
241
|
+
self._session = session
|
235
242
|
|
236
243
|
# Async iterator for async streaming.
|
237
244
|
def __aiter__(self) -> 'HttpResponse':
|
@@ -291,16 +298,23 @@ class HttpResponse:
|
|
291
298
|
chunk = chunk[len('data: ') :]
|
292
299
|
yield json.loads(chunk)
|
293
300
|
elif hasattr(self.response_stream, 'content'):
|
294
|
-
|
295
|
-
|
296
|
-
|
301
|
+
# This is aiohttp.ClientResponse.
|
302
|
+
try:
|
303
|
+
while True:
|
304
|
+
chunk = await self.response_stream.content.readline()
|
305
|
+
if not chunk:
|
306
|
+
break
|
297
307
|
# In async streaming mode, the chunk of JSON is prefixed with
|
298
308
|
# "data:" which we must strip before parsing.
|
299
|
-
|
300
|
-
chunk = chunk.decode('utf-8')
|
309
|
+
chunk = chunk.decode('utf-8')
|
301
310
|
if chunk.startswith('data: '):
|
302
311
|
chunk = chunk[len('data: ') :]
|
303
|
-
|
312
|
+
chunk = chunk.strip()
|
313
|
+
if chunk:
|
314
|
+
yield json.loads(chunk)
|
315
|
+
finally:
|
316
|
+
if hasattr(self, '_session') and self._session:
|
317
|
+
await self._session.close()
|
304
318
|
else:
|
305
319
|
raise ValueError('Error parsing streaming response.')
|
306
320
|
|
@@ -538,6 +552,7 @@ class BaseApiClient:
|
|
538
552
|
# Default options for both clients.
|
539
553
|
self._http_options.headers = {'Content-Type': 'application/json'}
|
540
554
|
if self.api_key:
|
555
|
+
self.api_key = self.api_key.strip()
|
541
556
|
if self._http_options.headers is not None:
|
542
557
|
self._http_options.headers['x-goog-api-key'] = self.api_key
|
543
558
|
# Update the http options with the user provided http options.
|
@@ -558,7 +573,10 @@ class BaseApiClient:
|
|
558
573
|
# Do it once at the genai.Client level. Share among all requests.
|
559
574
|
self._async_client_session_request_args = self._ensure_aiohttp_ssl_ctx(
|
560
575
|
self._http_options
|
561
|
-
)
|
576
|
+
)
|
577
|
+
self._websocket_ssl_ctx = self._ensure_websocket_ssl_ctx(
|
578
|
+
self._http_options
|
579
|
+
)
|
562
580
|
|
563
581
|
retry_kwargs = _retry_args(self._http_options.retry_options)
|
564
582
|
self._retry = tenacity.Retrying(**retry_kwargs, reraise=True)
|
@@ -688,6 +706,63 @@ class BaseApiClient:
|
|
688
706
|
|
689
707
|
return _maybe_set(async_args, ctx)
|
690
708
|
|
709
|
+
|
710
|
+
@staticmethod
|
711
|
+
def _ensure_websocket_ssl_ctx(options: HttpOptions) -> dict[str, Any]:
|
712
|
+
"""Ensures the SSL context is present in the async client args.
|
713
|
+
|
714
|
+
Creates a default SSL context if one is not provided.
|
715
|
+
|
716
|
+
Args:
|
717
|
+
options: The http options to check for SSL context.
|
718
|
+
|
719
|
+
Returns:
|
720
|
+
An async aiohttp ClientSession._request args.
|
721
|
+
"""
|
722
|
+
|
723
|
+
verify = 'ssl' # keep it consistent with httpx.
|
724
|
+
async_args = options.async_client_args
|
725
|
+
ctx = async_args.get(verify) if async_args else None
|
726
|
+
|
727
|
+
if not ctx:
|
728
|
+
# Initialize the SSL context for the httpx client.
|
729
|
+
# Unlike requests, the aiohttp package does not automatically pull in the
|
730
|
+
# environment variables SSL_CERT_FILE or SSL_CERT_DIR. They need to be
|
731
|
+
# enabled explicitly. Instead of 'verify' at client level in httpx,
|
732
|
+
# aiohttp uses 'ssl' at request level.
|
733
|
+
ctx = ssl.create_default_context(
|
734
|
+
cafile=os.environ.get('SSL_CERT_FILE', certifi.where()),
|
735
|
+
capath=os.environ.get('SSL_CERT_DIR'),
|
736
|
+
)
|
737
|
+
|
738
|
+
def _maybe_set(
|
739
|
+
args: Optional[dict[str, Any]],
|
740
|
+
ctx: ssl.SSLContext,
|
741
|
+
) -> dict[str, Any]:
|
742
|
+
"""Sets the SSL context in the client args if not set.
|
743
|
+
|
744
|
+
Does not override the SSL context if it is already set.
|
745
|
+
|
746
|
+
Args:
|
747
|
+
args: The client args to to check for SSL context.
|
748
|
+
ctx: The SSL context to set.
|
749
|
+
|
750
|
+
Returns:
|
751
|
+
The client args with the SSL context included.
|
752
|
+
"""
|
753
|
+
if not args or not args.get(verify):
|
754
|
+
args = (args or {}).copy()
|
755
|
+
args[verify] = ctx
|
756
|
+
# Drop the args that isn't in the aiohttp RequestOptions.
|
757
|
+
copied_args = args.copy()
|
758
|
+
for key in copied_args.copy():
|
759
|
+
if key not in inspect.signature(ws_connect).parameters and key != 'ssl':
|
760
|
+
del copied_args[key]
|
761
|
+
return copied_args
|
762
|
+
|
763
|
+
return _maybe_set(async_args, ctx)
|
764
|
+
|
765
|
+
|
691
766
|
def _websocket_base_url(self) -> str:
|
692
767
|
url_parts = urlparse(self._http_options.base_url)
|
693
768
|
return url_parts._replace(scheme='wss').geturl() # type: ignore[arg-type, return-value]
|
@@ -882,6 +957,7 @@ class BaseApiClient:
|
|
882
957
|
self, http_request: HttpRequest, stream: bool = False
|
883
958
|
) -> HttpResponse:
|
884
959
|
data: Optional[Union[str, bytes]] = None
|
960
|
+
|
885
961
|
if self.vertexai and not self.api_key:
|
886
962
|
http_request.headers['Authorization'] = (
|
887
963
|
f'Bearer {await self._async_access_token()}'
|
@@ -912,8 +988,9 @@ class BaseApiClient:
|
|
912
988
|
timeout=aiohttp.ClientTimeout(connect=http_request.timeout),
|
913
989
|
**self._async_client_session_request_args,
|
914
990
|
)
|
991
|
+
|
915
992
|
await errors.APIError.raise_for_async_response(response)
|
916
|
-
return HttpResponse(response.headers, response)
|
993
|
+
return HttpResponse(response.headers, response, session=session)
|
917
994
|
else:
|
918
995
|
# aiohttp is not available. Fall back to httpx.
|
919
996
|
httpx_request = self._async_httpx_client.build_request(
|
google/genai/live.py
CHANGED
@@ -1037,7 +1037,10 @@ class AsyncLive(_api_module.BaseModule):
|
|
1037
1037
|
if headers is None:
|
1038
1038
|
headers = {}
|
1039
1039
|
_mcp_utils.set_mcp_usage_header(headers)
|
1040
|
-
|
1040
|
+
|
1041
|
+
async with ws_connect(
|
1042
|
+
uri, additional_headers=headers, **self._api_client._websocket_ssl_ctx
|
1043
|
+
) as ws:
|
1041
1044
|
await ws.send(request)
|
1042
1045
|
try:
|
1043
1046
|
# websockets 14.0+
|
google/genai/tunings.py
CHANGED
@@ -108,6 +108,11 @@ def _TuningDataset_to_mldev(
|
|
108
108
|
if getv(from_object, ['gcs_uri']) is not None:
|
109
109
|
raise ValueError('gcs_uri parameter is not supported in Gemini API.')
|
110
110
|
|
111
|
+
if getv(from_object, ['vertex_dataset_resource']) is not None:
|
112
|
+
raise ValueError(
|
113
|
+
'vertex_dataset_resource parameter is not supported in Gemini API.'
|
114
|
+
)
|
115
|
+
|
111
116
|
if getv(from_object, ['examples']) is not None:
|
112
117
|
setv(
|
113
118
|
to_object,
|
@@ -129,6 +134,11 @@ def _TuningValidationDataset_to_mldev(
|
|
129
134
|
if getv(from_object, ['gcs_uri']) is not None:
|
130
135
|
raise ValueError('gcs_uri parameter is not supported in Gemini API.')
|
131
136
|
|
137
|
+
if getv(from_object, ['vertex_dataset_resource']) is not None:
|
138
|
+
raise ValueError(
|
139
|
+
'vertex_dataset_resource parameter is not supported in Gemini API.'
|
140
|
+
)
|
141
|
+
|
132
142
|
return to_object
|
133
143
|
|
134
144
|
|
@@ -302,6 +312,13 @@ def _TuningDataset_to_vertex(
|
|
302
312
|
getv(from_object, ['gcs_uri']),
|
303
313
|
)
|
304
314
|
|
315
|
+
if getv(from_object, ['vertex_dataset_resource']) is not None:
|
316
|
+
setv(
|
317
|
+
parent_object,
|
318
|
+
['supervisedTuningSpec', 'trainingDatasetUri'],
|
319
|
+
getv(from_object, ['vertex_dataset_resource']),
|
320
|
+
)
|
321
|
+
|
305
322
|
if getv(from_object, ['examples']) is not None:
|
306
323
|
raise ValueError('examples parameter is not supported in Vertex AI.')
|
307
324
|
|
@@ -316,6 +333,13 @@ def _TuningValidationDataset_to_vertex(
|
|
316
333
|
if getv(from_object, ['gcs_uri']) is not None:
|
317
334
|
setv(to_object, ['validationDatasetUri'], getv(from_object, ['gcs_uri']))
|
318
335
|
|
336
|
+
if getv(from_object, ['vertex_dataset_resource']) is not None:
|
337
|
+
setv(
|
338
|
+
parent_object,
|
339
|
+
['supervisedTuningSpec', 'trainingDatasetUri'],
|
340
|
+
getv(from_object, ['vertex_dataset_resource']),
|
341
|
+
)
|
342
|
+
|
319
343
|
return to_object
|
320
344
|
|
321
345
|
|
google/genai/types.py
CHANGED
@@ -8699,6 +8699,10 @@ class TuningDataset(_common.BaseModel):
|
|
8699
8699
|
default=None,
|
8700
8700
|
description="""GCS URI of the file containing training dataset in JSONL format.""",
|
8701
8701
|
)
|
8702
|
+
vertex_dataset_resource: Optional[str] = Field(
|
8703
|
+
default=None,
|
8704
|
+
description="""The resource name of the Vertex Multimodal Dataset that is used as training dataset. Example: 'projects/my-project-id-or-number/locations/my-location/datasets/my-dataset-id'.""",
|
8705
|
+
)
|
8702
8706
|
examples: Optional[list[TuningExample]] = Field(
|
8703
8707
|
default=None,
|
8704
8708
|
description="""Inline examples with simple input/output text.""",
|
@@ -8711,6 +8715,9 @@ class TuningDatasetDict(TypedDict, total=False):
|
|
8711
8715
|
gcs_uri: Optional[str]
|
8712
8716
|
"""GCS URI of the file containing training dataset in JSONL format."""
|
8713
8717
|
|
8718
|
+
vertex_dataset_resource: Optional[str]
|
8719
|
+
"""The resource name of the Vertex Multimodal Dataset that is used as training dataset. Example: 'projects/my-project-id-or-number/locations/my-location/datasets/my-dataset-id'."""
|
8720
|
+
|
8714
8721
|
examples: Optional[list[TuningExampleDict]]
|
8715
8722
|
"""Inline examples with simple input/output text."""
|
8716
8723
|
|
@@ -8724,6 +8731,10 @@ class TuningValidationDataset(_common.BaseModel):
|
|
8724
8731
|
default=None,
|
8725
8732
|
description="""GCS URI of the file containing validation dataset in JSONL format.""",
|
8726
8733
|
)
|
8734
|
+
vertex_dataset_resource: Optional[str] = Field(
|
8735
|
+
default=None,
|
8736
|
+
description="""The resource name of the Vertex Multimodal Dataset that is used as training dataset. Example: 'projects/my-project-id-or-number/locations/my-location/datasets/my-dataset-id'.""",
|
8737
|
+
)
|
8727
8738
|
|
8728
8739
|
|
8729
8740
|
class TuningValidationDatasetDict(TypedDict, total=False):
|
@@ -8731,6 +8742,9 @@ class TuningValidationDatasetDict(TypedDict, total=False):
|
|
8731
8742
|
gcs_uri: Optional[str]
|
8732
8743
|
"""GCS URI of the file containing validation dataset in JSONL format."""
|
8733
8744
|
|
8745
|
+
vertex_dataset_resource: Optional[str]
|
8746
|
+
"""The resource name of the Vertex Multimodal Dataset that is used as training dataset. Example: 'projects/my-project-id-or-number/locations/my-location/datasets/my-dataset-id'."""
|
8747
|
+
|
8734
8748
|
|
8735
8749
|
TuningValidationDatasetOrDict = Union[
|
8736
8750
|
TuningValidationDataset, TuningValidationDatasetDict
|
@@ -12801,7 +12815,7 @@ class AudioChunk(_common.BaseModel):
|
|
12801
12815
|
"""Representation of an audio chunk."""
|
12802
12816
|
|
12803
12817
|
data: Optional[bytes] = Field(
|
12804
|
-
default=None, description="""Raw
|
12818
|
+
default=None, description="""Raw bytes of audio data."""
|
12805
12819
|
)
|
12806
12820
|
mime_type: Optional[str] = Field(
|
12807
12821
|
default=None, description="""MIME type of the audio chunk."""
|
@@ -12816,7 +12830,7 @@ class AudioChunkDict(TypedDict, total=False):
|
|
12816
12830
|
"""Representation of an audio chunk."""
|
12817
12831
|
|
12818
12832
|
data: Optional[bytes]
|
12819
|
-
"""Raw
|
12833
|
+
"""Raw bytes of audio data."""
|
12820
12834
|
|
12821
12835
|
mime_type: Optional[str]
|
12822
12836
|
"""MIME type of the audio chunk."""
|
google/genai/version.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: google-genai
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.23.0
|
4
4
|
Summary: GenAI Python SDK
|
5
5
|
Author-email: Google LLC <googleapis-packages@google.com>
|
6
6
|
License: Apache-2.0
|
@@ -743,6 +743,53 @@ response = client.models.generate_content(
|
|
743
743
|
),
|
744
744
|
)
|
745
745
|
```
|
746
|
+
|
747
|
+
#### Model Context Protocol (MCP) support (experimental)
|
748
|
+
|
749
|
+
Built-in [MCP](https://modelcontextprotocol.io/introduction) support is an
|
750
|
+
experimental feature. You can pass a local MCP server as a tool directly.
|
751
|
+
|
752
|
+
```python
|
753
|
+
import os
|
754
|
+
import asyncio
|
755
|
+
from datetime import datetime
|
756
|
+
from mcp import ClientSession, StdioServerParameters
|
757
|
+
from mcp.client.stdio import stdio_client
|
758
|
+
from google import genai
|
759
|
+
|
760
|
+
client = genai.Client()
|
761
|
+
|
762
|
+
# Create server parameters for stdio connection
|
763
|
+
server_params = StdioServerParameters(
|
764
|
+
command="npx", # Executable
|
765
|
+
args=["-y", "@philschmid/weather-mcp"], # MCP Server
|
766
|
+
env=None, # Optional environment variables
|
767
|
+
)
|
768
|
+
|
769
|
+
async def run():
|
770
|
+
async with stdio_client(server_params) as (read, write):
|
771
|
+
async with ClientSession(read, write) as session:
|
772
|
+
# Prompt to get the weather for the current day in London.
|
773
|
+
prompt = f"What is the weather in London in {datetime.now().strftime('%Y-%m-%d')}?"
|
774
|
+
|
775
|
+
# Initialize the connection between client and server
|
776
|
+
await session.initialize()
|
777
|
+
|
778
|
+
# Send request to the model with MCP function declarations
|
779
|
+
response = await client.aio.models.generate_content(
|
780
|
+
model="gemini-2.5-flash",
|
781
|
+
contents=prompt,
|
782
|
+
config=genai.types.GenerateContentConfig(
|
783
|
+
temperature=0,
|
784
|
+
tools=[session], # uses the session, will automatically call the tool using automatic function calling
|
785
|
+
),
|
786
|
+
)
|
787
|
+
print(response.text)
|
788
|
+
|
789
|
+
# Start the asyncio event loop and run the main function
|
790
|
+
asyncio.run(run())
|
791
|
+
```
|
792
|
+
|
746
793
|
### JSON Response Schema
|
747
794
|
|
748
795
|
However you define your schema, don't duplicate it in your input prompt,
|
@@ -1260,7 +1307,7 @@ client.
|
|
1260
1307
|
|
1261
1308
|
### Tune
|
1262
1309
|
|
1263
|
-
- Vertex AI supports tuning from GCS source
|
1310
|
+
- Vertex AI supports tuning from GCS source or from a Vertex Multimodal Dataset
|
1264
1311
|
- Gemini Developer API supports tuning from inline examples
|
1265
1312
|
|
1266
1313
|
```python
|
@@ -1269,10 +1316,12 @@ from google.genai import types
|
|
1269
1316
|
if client.vertexai:
|
1270
1317
|
model = 'gemini-2.0-flash-001'
|
1271
1318
|
training_dataset = types.TuningDataset(
|
1319
|
+
# or gcs_uri=my_vertex_multimodal_dataset
|
1272
1320
|
gcs_uri='gs://cloud-samples-data/ai-platform/generative_ai/gemini-1_5/text/sft_train_data.jsonl',
|
1273
1321
|
)
|
1274
1322
|
else:
|
1275
1323
|
model = 'models/gemini-2.0-flash-001'
|
1324
|
+
# or gcs_uri=my_vertex_multimodal_dataset.resource_name
|
1276
1325
|
training_dataset = types.TuningDataset(
|
1277
1326
|
examples=[
|
1278
1327
|
types.TuningExample(
|
@@ -1,6 +1,6 @@
|
|
1
1
|
google/genai/__init__.py,sha256=SYTxz3Ho06pP2TBlvDU0FkUJz8ytbR3MgEpS9HvVYq4,709
|
2
2
|
google/genai/_adapters.py,sha256=Kok38miNYJff2n--l0zEK_hbq0y2rWOH7k75J7SMYbQ,1744
|
3
|
-
google/genai/_api_client.py,sha256=
|
3
|
+
google/genai/_api_client.py,sha256=bbuu6LUCEf6MH-DzhEg-w7iv84SqRy5vIluXDKOn1UU,52447
|
4
4
|
google/genai/_api_module.py,sha256=lj8eUWx8_LBGBz-49qz6_ywWm3GYp3d8Bg5JoOHbtbI,902
|
5
5
|
google/genai/_automatic_function_calling_util.py,sha256=IJkPq2fT9pYxYm5Pbu5-e0nBoZKoZla7yT4_txWRKLs,10324
|
6
6
|
google/genai/_base_url.py,sha256=E5H4dew14Y16qfnB3XRnjSCi19cJVlkaMNoM_8ip-PM,1597
|
@@ -18,18 +18,18 @@ google/genai/chats.py,sha256=0QdOUeWEYDQgAWBy1f7a3z3yY9S8tXSowUzNrzazzj4,16651
|
|
18
18
|
google/genai/client.py,sha256=wXnfZBSv9p-yKtX_gabUrfBXoYHuqHhzK_VgwRttMgY,10777
|
19
19
|
google/genai/errors.py,sha256=UebysH1cDeIdtp1O06CW7lQjnNrWtuqZTeVgEJylX48,5589
|
20
20
|
google/genai/files.py,sha256=MCcHRXiMFKjbnt78yVPejszEgGz_MHRXfJyDi5-07Gs,39655
|
21
|
-
google/genai/live.py,sha256=
|
21
|
+
google/genai/live.py,sha256=8Vts1bX8ZWOa0PiS3zmYhG1QMhLtBPC_ATLTSAIrazs,38945
|
22
22
|
google/genai/live_music.py,sha256=3GG9nsto8Vhkohcs-4CPMS4DFp1ZtMuLYzHfvEPYAeg,6971
|
23
23
|
google/genai/models.py,sha256=7gBXwg6_RdW_HRD_iRFIAdqu0bkUkW0fAp_PMEPVwoU,239309
|
24
24
|
google/genai/operations.py,sha256=99zs__fTWsyQu7rMGmBI1_4tuAJxLR0g3yp7ymsUsBA,19609
|
25
25
|
google/genai/pagers.py,sha256=nyVYxp92rS-UaewO_oBgP593knofeLU6yOn6RolNoGQ,6797
|
26
26
|
google/genai/py.typed,sha256=RsMFoLwBkAvY05t6izop4UHZtqOPLiKp3GkIEizzmQY,40
|
27
27
|
google/genai/tokens.py,sha256=oew9I0fGuGLlXMdCn2Ot9Lv_herHMnvZOYjjdOz2CAM,12324
|
28
|
-
google/genai/tunings.py,sha256=
|
29
|
-
google/genai/types.py,sha256=
|
30
|
-
google/genai/version.py,sha256=
|
31
|
-
google_genai-1.
|
32
|
-
google_genai-1.
|
33
|
-
google_genai-1.
|
34
|
-
google_genai-1.
|
35
|
-
google_genai-1.
|
28
|
+
google/genai/tunings.py,sha256=u6Hcfkc-nUYB_spSfY98h7EIiSz0dH3wVH0b2feMh1M,49072
|
29
|
+
google/genai/types.py,sha256=LGLNmXkmnCLU-narShhG_1rtglfARNm6pvvZOiO5_lA,460023
|
30
|
+
google/genai/version.py,sha256=Snuhu088Fxuibck04VaPaZ69LvJ5pKNdicb9oZYwcrY,627
|
31
|
+
google_genai-1.23.0.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
32
|
+
google_genai-1.23.0.dist-info/METADATA,sha256=Yylx0cTXrq87K2-VIbM9e1RT80LHMcvUC5ZB8Y0YTqc,38902
|
33
|
+
google_genai-1.23.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
34
|
+
google_genai-1.23.0.dist-info/top_level.txt,sha256=_1QvSJIhFAGfxb79D6DhB7SUw2X6T4rwnz_LLrbcD3c,7
|
35
|
+
google_genai-1.23.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|