gemini-webapi 1.14.2__tar.gz → 1.14.3__tar.gz
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.
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/PKG-INFO +6 -2
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/README.md +5 -1
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/src/gemini_webapi/client.py +98 -48
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/src/gemini_webapi/constants.py +12 -0
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/src/gemini_webapi/types/__init__.py +1 -0
- gemini_webapi-1.14.3/src/gemini_webapi/types/grpc.py +34 -0
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/src/gemini_webapi.egg-info/PKG-INFO +6 -2
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/src/gemini_webapi.egg-info/SOURCES.txt +1 -0
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/tests/test_client_features.py +1 -1
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/.github/dependabot.yml +0 -0
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/.github/workflows/github-release.yml +0 -0
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/.github/workflows/pypi-publish.yml +0 -0
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/.gitignore +0 -0
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/.vscode/launch.json +0 -0
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/.vscode/settings.json +0 -0
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/LICENSE +0 -0
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/assets/banner.png +0 -0
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/assets/favicon.png +0 -0
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/assets/logo.svg +0 -0
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/assets/sample.pdf +0 -0
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/pyproject.toml +0 -0
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/setup.cfg +0 -0
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/src/gemini_webapi/__init__.py +0 -0
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/src/gemini_webapi/exceptions.py +0 -0
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/src/gemini_webapi/types/candidate.py +0 -0
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/src/gemini_webapi/types/gem.py +0 -0
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/src/gemini_webapi/types/image.py +0 -0
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/src/gemini_webapi/types/modeloutput.py +0 -0
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/src/gemini_webapi/utils/__init__.py +0 -0
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/src/gemini_webapi/utils/get_access_token.py +0 -0
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/src/gemini_webapi/utils/load_browser_cookies.py +0 -0
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/src/gemini_webapi/utils/logger.py +0 -0
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/src/gemini_webapi/utils/rotate_1psidts.py +0 -0
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/src/gemini_webapi/utils/upload_file.py +0 -0
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/src/gemini_webapi.egg-info/dependency_links.txt +0 -0
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/src/gemini_webapi.egg-info/requires.txt +0 -0
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/src/gemini_webapi.egg-info/top_level.txt +0 -0
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/tests/test_rotate_cookies.py +0 -0
- {gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/tests/test_save_image.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gemini-webapi
|
|
3
|
-
Version: 1.14.
|
|
3
|
+
Version: 1.14.3
|
|
4
4
|
Summary: ✨ An elegant async Python wrapper for Google Gemini web app
|
|
5
5
|
Author: UZQueen
|
|
6
6
|
License: GNU AFFERO GENERAL PUBLIC LICENSE
|
|
@@ -931,10 +931,14 @@ asyncio.run(main())
|
|
|
931
931
|
|
|
932
932
|
System prompt can be applied to conversations via [Gemini Gems](https://gemini.google.com/gems/view). To use a gem, you can pass `gem` argument to `GeminiClient.generate_content` or `GeminiClient.start_chat`. `gem` can be either a string of gem id or a `gemini_webapi.Gem` object. Only one gem can be applied to a single conversation.
|
|
933
933
|
|
|
934
|
+
> [!TIP]
|
|
935
|
+
>
|
|
936
|
+
> There are some system predefined gems that by default are not shown to users (and therefore may not work properly). Use `client.fetch_gems(include_hidden=True)` to include them in the fetch result.
|
|
937
|
+
|
|
934
938
|
```python
|
|
935
939
|
async def main():
|
|
936
940
|
# Fetch all gems for the current account, including both predefined and user-created ones
|
|
937
|
-
await client.fetch_gems()
|
|
941
|
+
await client.fetch_gems(include_hidden=False)
|
|
938
942
|
|
|
939
943
|
# Once fetched, gems will be cached in `GeminiClient.gems`
|
|
940
944
|
gems = client.gems
|
|
@@ -247,10 +247,14 @@ asyncio.run(main())
|
|
|
247
247
|
|
|
248
248
|
System prompt can be applied to conversations via [Gemini Gems](https://gemini.google.com/gems/view). To use a gem, you can pass `gem` argument to `GeminiClient.generate_content` or `GeminiClient.start_chat`. `gem` can be either a string of gem id or a `gemini_webapi.Gem` object. Only one gem can be applied to a single conversation.
|
|
249
249
|
|
|
250
|
+
> [!TIP]
|
|
251
|
+
>
|
|
252
|
+
> There are some system predefined gems that by default are not shown to users (and therefore may not work properly). Use `client.fetch_gems(include_hidden=True)` to include them in the fetch result.
|
|
253
|
+
|
|
250
254
|
```python
|
|
251
255
|
async def main():
|
|
252
256
|
# Fetch all gems for the current account, including both predefined and user-created ones
|
|
253
|
-
await client.fetch_gems()
|
|
257
|
+
await client.fetch_gems(include_hidden=False)
|
|
254
258
|
|
|
255
259
|
# Once fetched, gems will be cached in `GeminiClient.gems`
|
|
256
260
|
gems = client.gems
|
|
@@ -7,9 +7,9 @@ from pathlib import Path
|
|
|
7
7
|
from typing import Any, Optional
|
|
8
8
|
|
|
9
9
|
import orjson as json
|
|
10
|
-
from httpx import AsyncClient, ReadTimeout
|
|
10
|
+
from httpx import AsyncClient, ReadTimeout, Response
|
|
11
11
|
|
|
12
|
-
from .constants import Endpoint, ErrorCode, Headers, Model
|
|
12
|
+
from .constants import Endpoint, ErrorCode, Headers, Model, GRPC
|
|
13
13
|
from .exceptions import (
|
|
14
14
|
AuthError,
|
|
15
15
|
APIError,
|
|
@@ -20,7 +20,15 @@ from .exceptions import (
|
|
|
20
20
|
ModelInvalid,
|
|
21
21
|
TemporarilyBlocked,
|
|
22
22
|
)
|
|
23
|
-
from .types import
|
|
23
|
+
from .types import (
|
|
24
|
+
WebImage,
|
|
25
|
+
GeneratedImage,
|
|
26
|
+
Candidate,
|
|
27
|
+
ModelOutput,
|
|
28
|
+
Gem,
|
|
29
|
+
GemJar,
|
|
30
|
+
RPCData,
|
|
31
|
+
)
|
|
24
32
|
from .utils import (
|
|
25
33
|
upload_file,
|
|
26
34
|
parse_file_name,
|
|
@@ -301,67 +309,61 @@ class GeminiClient:
|
|
|
301
309
|
|
|
302
310
|
return self._gems
|
|
303
311
|
|
|
304
|
-
|
|
305
|
-
async def fetch_gems(self, **kwargs) -> GemJar:
|
|
312
|
+
async def fetch_gems(self, include_hidden: bool = False, **kwargs) -> GemJar:
|
|
306
313
|
"""
|
|
307
314
|
Get a list of available gems from gemini, including system predefined gems and user-created custom gems.
|
|
308
315
|
|
|
309
316
|
Note that network request will be sent every time this method is called.
|
|
310
317
|
Once the gems are fetched, they will be cached and accessible via `GeminiClient.gems` property.
|
|
311
318
|
|
|
319
|
+
Parameters
|
|
320
|
+
----------
|
|
321
|
+
include_hidden: `bool`, optional
|
|
322
|
+
There are some predefined gems that by default are not shown to users (and therefore may not work properly).
|
|
323
|
+
Set this parameter to `True` to include them in the fetched gem list.
|
|
324
|
+
|
|
312
325
|
Returns
|
|
313
326
|
-------
|
|
314
327
|
:class:`GemJar`
|
|
315
328
|
Refer to `gemini_webapi.types.GemJar`.
|
|
316
329
|
"""
|
|
317
330
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
"
|
|
323
|
-
"
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
)
|
|
334
|
-
except ReadTimeout:
|
|
335
|
-
raise TimeoutError(
|
|
336
|
-
"Fetch gems request timed out, please try again. If the problem persists, "
|
|
337
|
-
"consider setting a higher `timeout` value when initializing GeminiClient."
|
|
338
|
-
)
|
|
331
|
+
response = await self._batch_execute(
|
|
332
|
+
[
|
|
333
|
+
RPCData(
|
|
334
|
+
rpcid=GRPC.LIST_GEMS,
|
|
335
|
+
payload="[4]" if include_hidden else "[3]",
|
|
336
|
+
identifier="system",
|
|
337
|
+
),
|
|
338
|
+
RPCData(
|
|
339
|
+
rpcid=GRPC.LIST_GEMS,
|
|
340
|
+
payload="[2]",
|
|
341
|
+
identifier="custom",
|
|
342
|
+
),
|
|
343
|
+
],
|
|
344
|
+
**kwargs,
|
|
345
|
+
)
|
|
339
346
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
f"Failed to fetch gems. Request failed with status code {response.status_code}"
|
|
343
|
-
)
|
|
344
|
-
else:
|
|
345
|
-
try:
|
|
346
|
-
response_json = json.loads(response.text.split("\n")[2])
|
|
347
|
+
try:
|
|
348
|
+
response_json = json.loads(response.text.split("\n")[2])
|
|
347
349
|
|
|
348
|
-
|
|
350
|
+
predefined_gems, custom_gems = [], []
|
|
349
351
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
352
|
+
for part in response_json:
|
|
353
|
+
if part[-1] == "system":
|
|
354
|
+
predefined_gems = json.loads(part[2])[2]
|
|
355
|
+
elif part[-1] == "custom":
|
|
356
|
+
if custom_gems_container := json.loads(part[2]):
|
|
357
|
+
custom_gems = custom_gems_container[2]
|
|
356
358
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
359
|
+
if not predefined_gems and not custom_gems:
|
|
360
|
+
raise Exception
|
|
361
|
+
except Exception:
|
|
362
|
+
await self.close()
|
|
363
|
+
logger.debug(f"Invalid response: {response.text}")
|
|
364
|
+
raise APIError(
|
|
365
|
+
"Failed to fetch gems. Invalid response data received. Client will try to re-initialize on next request."
|
|
366
|
+
)
|
|
365
367
|
|
|
366
368
|
self._gems = GemJar(
|
|
367
369
|
itertools.chain(
|
|
@@ -665,6 +667,54 @@ class GeminiClient:
|
|
|
665
667
|
|
|
666
668
|
return ChatSession(geminiclient=self, **kwargs)
|
|
667
669
|
|
|
670
|
+
@running(retry=2)
|
|
671
|
+
async def _batch_execute(self, payloads: list[RPCData], **kwargs) -> Response:
|
|
672
|
+
"""
|
|
673
|
+
Execute a batch of requests to Gemini API.
|
|
674
|
+
|
|
675
|
+
Parameters
|
|
676
|
+
----------
|
|
677
|
+
payloads: `list[GRPC]`
|
|
678
|
+
List of `gemini_webapi.types.GRPC` objects to be executed.
|
|
679
|
+
kwargs: `dict`, optional
|
|
680
|
+
Additional arguments which will be passed to the post request.
|
|
681
|
+
Refer to `httpx.AsyncClient.request` for more information.
|
|
682
|
+
|
|
683
|
+
Returns
|
|
684
|
+
-------
|
|
685
|
+
:class:`httpx.Response`
|
|
686
|
+
Response object containing the result of the batch execution.
|
|
687
|
+
"""
|
|
688
|
+
|
|
689
|
+
try:
|
|
690
|
+
response = await self.client.post(
|
|
691
|
+
Endpoint.BATCH_EXEC,
|
|
692
|
+
data={
|
|
693
|
+
"at": self.access_token,
|
|
694
|
+
"f.req": json.dumps(
|
|
695
|
+
[[payload.serialize() for payload in payloads]]
|
|
696
|
+
).decode(),
|
|
697
|
+
},
|
|
698
|
+
**kwargs,
|
|
699
|
+
)
|
|
700
|
+
except ReadTimeout:
|
|
701
|
+
raise TimeoutError(
|
|
702
|
+
"Batch execute request timed out, please try again. If the problem persists, "
|
|
703
|
+
"consider setting a higher `timeout` value when initializing GeminiClient."
|
|
704
|
+
)
|
|
705
|
+
|
|
706
|
+
if response.status_code != 200:
|
|
707
|
+
logger.debug(
|
|
708
|
+
f"Batch execution failed with status code {response.status_code}. "
|
|
709
|
+
f"RPC: {', '.join({payload.rpcid.name for payload in payloads})}; "
|
|
710
|
+
f"Invalid response: {response.text}"
|
|
711
|
+
)
|
|
712
|
+
raise APIError(
|
|
713
|
+
f"Batch execution failed with status code {response.status_code}"
|
|
714
|
+
)
|
|
715
|
+
|
|
716
|
+
return response
|
|
717
|
+
|
|
668
718
|
|
|
669
719
|
class ChatSession:
|
|
670
720
|
"""
|
|
@@ -10,6 +10,18 @@ class Endpoint(StrEnum):
|
|
|
10
10
|
BATCH_EXEC = "https://gemini.google.com/_/BardChatUi/data/batchexecute"
|
|
11
11
|
|
|
12
12
|
|
|
13
|
+
class GRPC(StrEnum):
|
|
14
|
+
"""
|
|
15
|
+
Google RPC ids used in Gemini API.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
# Chat methods
|
|
19
|
+
READ_CHAT = "hNvQHb"
|
|
20
|
+
|
|
21
|
+
# Gem methods
|
|
22
|
+
LIST_GEMS = "CNgdBe"
|
|
23
|
+
|
|
24
|
+
|
|
13
25
|
class Headers(Enum):
|
|
14
26
|
GEMINI = {
|
|
15
27
|
"Content-Type": "application/x-www-form-urlencoded;charset=utf-8",
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from pydantic import BaseModel
|
|
2
|
+
|
|
3
|
+
from ..constants import GRPC
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class RPCData(BaseModel):
|
|
7
|
+
"""
|
|
8
|
+
Helper class containing necessary data for Google RPC calls.
|
|
9
|
+
|
|
10
|
+
Parameters
|
|
11
|
+
----------
|
|
12
|
+
rpcid : GRPC
|
|
13
|
+
Google RPC ID.
|
|
14
|
+
payload : str
|
|
15
|
+
Payload for the RPC call.
|
|
16
|
+
identifier : str, optional
|
|
17
|
+
Identifier/order for the RPC call, defaults to "generic".
|
|
18
|
+
Makes sense if there are multiple RPC calls in a batch, where this identifier
|
|
19
|
+
can be used to distinguish between responses.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
rpcid: GRPC
|
|
23
|
+
payload: str
|
|
24
|
+
identifier: str = "generic"
|
|
25
|
+
|
|
26
|
+
def __repr__(self):
|
|
27
|
+
return f"GRPC(rpcid='{self.rpcid}', payload='{self.payload}', identifier='{self.identifier}')"
|
|
28
|
+
|
|
29
|
+
def serialize(self) -> list:
|
|
30
|
+
"""
|
|
31
|
+
Serializes object into formatted payload ready for RPC call.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
return [self.rpcid, self.payload, None, self.identifier]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gemini-webapi
|
|
3
|
-
Version: 1.14.
|
|
3
|
+
Version: 1.14.3
|
|
4
4
|
Summary: ✨ An elegant async Python wrapper for Google Gemini web app
|
|
5
5
|
Author: UZQueen
|
|
6
6
|
License: GNU AFFERO GENERAL PUBLIC LICENSE
|
|
@@ -931,10 +931,14 @@ asyncio.run(main())
|
|
|
931
931
|
|
|
932
932
|
System prompt can be applied to conversations via [Gemini Gems](https://gemini.google.com/gems/view). To use a gem, you can pass `gem` argument to `GeminiClient.generate_content` or `GeminiClient.start_chat`. `gem` can be either a string of gem id or a `gemini_webapi.Gem` object. Only one gem can be applied to a single conversation.
|
|
933
933
|
|
|
934
|
+
> [!TIP]
|
|
935
|
+
>
|
|
936
|
+
> There are some system predefined gems that by default are not shown to users (and therefore may not work properly). Use `client.fetch_gems(include_hidden=True)` to include them in the fetch result.
|
|
937
|
+
|
|
934
938
|
```python
|
|
935
939
|
async def main():
|
|
936
940
|
# Fetch all gems for the current account, including both predefined and user-created ones
|
|
937
|
-
await client.fetch_gems()
|
|
941
|
+
await client.fetch_gems(include_hidden=False)
|
|
938
942
|
|
|
939
943
|
# Once fetched, gems will be cached in `GeminiClient.gems`
|
|
940
944
|
gems = client.gems
|
|
@@ -23,6 +23,7 @@ src/gemini_webapi.egg-info/top_level.txt
|
|
|
23
23
|
src/gemini_webapi/types/__init__.py
|
|
24
24
|
src/gemini_webapi/types/candidate.py
|
|
25
25
|
src/gemini_webapi/types/gem.py
|
|
26
|
+
src/gemini_webapi/types/grpc.py
|
|
26
27
|
src/gemini_webapi/types/image.py
|
|
27
28
|
src/gemini_webapi/types/modeloutput.py
|
|
28
29
|
src/gemini_webapi/utils/__init__.py
|
|
@@ -97,7 +97,7 @@ class TestGeminiClient(unittest.IsolatedAsyncioTestCase):
|
|
|
97
97
|
|
|
98
98
|
@logger.catch(reraise=True)
|
|
99
99
|
async def test_fetch_gems(self):
|
|
100
|
-
await self.geminiclient.fetch_gems()
|
|
100
|
+
await self.geminiclient.fetch_gems(include_hidden=True)
|
|
101
101
|
gems = self.geminiclient.gems
|
|
102
102
|
self.assertTrue(len(gems.filter(predefined=True)) > 0)
|
|
103
103
|
for gem in gems:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/src/gemini_webapi/utils/load_browser_cookies.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{gemini_webapi-1.14.2 → gemini_webapi-1.14.3}/src/gemini_webapi.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|