gemini-webapi 1.9.1__py3-none-any.whl → 1.10.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.
gemini_webapi/client.py CHANGED
@@ -13,6 +13,7 @@ from .exceptions import AuthError, APIError, TimeoutError, GeminiError
13
13
  from .types import WebImage, GeneratedImage, Candidate, ModelOutput
14
14
  from .utils import (
15
15
  upload_file,
16
+ parse_file_name,
16
17
  rotate_1psidts,
17
18
  get_access_token,
18
19
  load_browser_cookies,
@@ -263,7 +264,7 @@ class GeminiClient:
263
264
  async def generate_content(
264
265
  self,
265
266
  prompt: str,
266
- images: list[bytes | str | Path] | None = None,
267
+ files: list[str | Path] | None = None,
267
268
  model: Model | str = Model.UNSPECIFIED,
268
269
  chat: Optional["ChatSession"] = None,
269
270
  **kwargs,
@@ -275,8 +276,8 @@ class GeminiClient:
275
276
  ----------
276
277
  prompt: `str`
277
278
  Prompt provided by user.
278
- images: `list[bytes | str | Path]`, optional
279
- List of image file paths or file data in bytes.
279
+ files: `list[str | Path]`, optional
280
+ List of file paths to be attached.
280
281
  model: `Model` | `str`, optional
281
282
  Specify the model to use for generation.
282
283
  Pass either a `gemini_webapi.constants.Model` enum or a model name string.
@@ -324,17 +325,17 @@ class GeminiClient:
324
325
  None,
325
326
  json.dumps(
326
327
  [
327
- images
328
+ files
328
329
  and [
329
330
  prompt,
330
331
  0,
331
332
  None,
332
333
  [
333
334
  [
334
- [await upload_file(image, self.proxy)],
335
- "filename.jpg",
335
+ [await upload_file(file, self.proxy)],
336
+ parse_file_name(file),
336
337
  ]
337
- for image in images
338
+ for file in files
338
339
  ],
339
340
  ]
340
341
  or [prompt],
@@ -550,7 +551,7 @@ class ChatSession:
550
551
  async def send_message(
551
552
  self,
552
553
  prompt: str,
553
- images: list[bytes | str | Path] | None = None,
554
+ files: list[str | Path] | None = None,
554
555
  **kwargs,
555
556
  ) -> ModelOutput:
556
557
  """
@@ -561,8 +562,8 @@ class ChatSession:
561
562
  ----------
562
563
  prompt: `str`
563
564
  Prompt provided by user.
564
- images: `list[bytes | str | Path]`, optional
565
- List of image file paths or file data in bytes.
565
+ files: `list[str | Path]`, optional
566
+ List of file paths to be attached.
566
567
  kwargs: `dict`, optional
567
568
  Additional arguments which will be passed to the post request.
568
569
  Refer to `httpx.AsyncClient.request` for more information.
@@ -587,7 +588,7 @@ class ChatSession:
587
588
  """
588
589
 
589
590
  return await self.geminiclient.generate_content(
590
- prompt=prompt, images=images, model=self.model, chat=self, **kwargs
591
+ prompt=prompt, files=files, model=self.model, chat=self, **kwargs
591
592
  )
592
593
 
593
594
  def choose_candidate(self, index: int) -> ModelOutput:
@@ -44,7 +44,7 @@ class Model(Enum):
44
44
  "gemini-2.0-flash-thinking-with-apps",
45
45
  {"x-goog-ext-525001261-jspb": '[null,null,null,null,"f8f8f5ea629f5d37"]'},
46
46
  False,
47
- )
47
+ ) # Deprecated, should be removed in the future
48
48
  G_2_0_EXP_ADVANCED = (
49
49
  "gemini-2.0-exp-advanced",
50
50
  {"x-goog-ext-525001261-jspb": '[null,null,null,null,"b1e46a6037e6aa9f"]'},
@@ -54,17 +54,17 @@ class Model(Enum):
54
54
  "gemini-1.5-flash",
55
55
  {"x-goog-ext-525001261-jspb": '[null,null,null,null,"418ab5ea040b5c43"]'},
56
56
  False,
57
- )
57
+ ) # Deprecated, should be removed in the future
58
58
  G_1_5_PRO = (
59
59
  "gemini-1.5-pro",
60
60
  {"x-goog-ext-525001261-jspb": '[null,null,null,null,"9d60dfae93c9ff1f"]'},
61
61
  True,
62
- )
62
+ ) # Deprecated, should be removed in the future
63
63
  G_1_5_PRO_RESEARCH = (
64
64
  "gemini-1.5-pro-research",
65
65
  {"x-goog-ext-525001261-jspb": '[null,null,null,null,"e5a44cb1dae2b489"]'},
66
66
  True,
67
- )
67
+ ) # Deprecated, should be removed in the future
68
68
 
69
69
  def __init__(self, name, header, advanced_only):
70
70
  self.model_name = name
@@ -1,6 +1,6 @@
1
1
  from asyncio import Task
2
2
 
3
- from .upload_file import upload_file # noqa: F401
3
+ from .upload_file import upload_file, parse_file_name # noqa: F401
4
4
  from .rotate_1psidts import rotate_1psidts # noqa: F401
5
5
  from .get_access_token import get_access_token # noqa: F401
6
6
  from .load_browser_cookies import load_browser_cookies # noqa: F401
@@ -7,14 +7,14 @@ from ..constants import Endpoint, Headers
7
7
 
8
8
 
9
9
  @validate_call
10
- async def upload_file(file: bytes | str | Path, proxy: str | None = None) -> str:
10
+ async def upload_file(file: str | Path, proxy: str | None = None) -> str:
11
11
  """
12
12
  Upload a file to Google's server and return its identifier.
13
13
 
14
14
  Parameters
15
15
  ----------
16
- file : `bytes` | `str` | `Path`
17
- File data in bytes, or path to the file to be uploaded.
16
+ file : `str` | `Path`
17
+ Path to the file to be uploaded.
18
18
  proxy: `str`, optional
19
19
  Proxy URL.
20
20
 
@@ -30,9 +30,8 @@ async def upload_file(file: bytes | str | Path, proxy: str | None = None) -> str
30
30
  If the upload request failed.
31
31
  """
32
32
 
33
- if not isinstance(file, bytes):
34
- with open(file, "rb") as f:
35
- file = f.read()
33
+ with open(file, "rb") as f:
34
+ file = f.read()
36
35
 
37
36
  async with AsyncClient(http2=True, proxy=proxy) as client:
38
37
  response = await client.post(
@@ -43,3 +42,25 @@ async def upload_file(file: bytes | str | Path, proxy: str | None = None) -> str
43
42
  )
44
43
  response.raise_for_status()
45
44
  return response.text
45
+
46
+
47
+ def parse_file_name(file: str | Path) -> str:
48
+ """
49
+ Parse the file name from the given path.
50
+
51
+ Parameters
52
+ ----------
53
+ file : `str` | `Path`
54
+ Path to the file.
55
+
56
+ Returns
57
+ -------
58
+ `str`
59
+ File name with extension.
60
+ """
61
+
62
+ file = Path(file)
63
+ if not file.is_file():
64
+ raise ValueError(f"{file} is not a valid file.")
65
+
66
+ return file.name
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gemini-webapi
3
- Version: 1.9.1
3
+ Version: 1.10.0
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
@@ -712,7 +712,7 @@ A reverse-engineered asynchronous python wrapper for [Google Gemini](https://gem
712
712
  ## Features
713
713
 
714
714
  - **Persistent Cookies** - Automatically refreshes cookies in background. Optimized for always-on services.
715
- - **ImageFx Support** - Supports retrieving images generated by ImageFx, Google's latest AI image generator.
715
+ - **Image Generation** - Natively supports generating and modifying images with natural language.
716
716
  - **Extension Support** - Supports generating contents with [Gemini extensions](https://gemini.google.com/extensions) on, like YouTube and Gmail.
717
717
  - **Classified Outputs** - Automatically categorizes texts, web images and AI generated images in the response.
718
718
  - **Official Flavor** - Provides a simple and elegant interface inspired by [Google Generative AI](https://ai.google.dev/tutorials/python_quickstart)'s official API.
@@ -728,13 +728,12 @@ A reverse-engineered asynchronous python wrapper for [Google Gemini](https://gem
728
728
  - [Initialization](#initialization)
729
729
  - [Select language model](#select-language-model)
730
730
  - [Generate contents from text](#generate-contents-from-text)
731
- - [Generate contents from image](#generate-contents-from-image)
731
+ - [Generate contents with files](#generate-contents-with-files)
732
732
  - [Conversations across multiple turns](#conversations-across-multiple-turns)
733
733
  - [Continue previous conversations](#continue-previous-conversations)
734
734
  - [Retrieve model's thought process](#retrieve-models-thought-process)
735
735
  - [Retrieve images in response](#retrieve-images-in-response)
736
- - [Generate images with ImageFx](#generate-images-with-imagefx)
737
- - [Save images to local files](#save-images-to-local-files)
736
+ - [Generate images with Imagen3](#generate-images-with-imagen3)
738
737
  - [Generate contents with Gemini extensions](#generate-contents-with-gemini-extensions)
739
738
  - [Check and switch to other reply candidates](#check-and-switch-to-other-reply-candidates)
740
739
  - [Control log level](#control-log-level)
@@ -868,15 +867,15 @@ asyncio.run(main())
868
867
  >
869
868
  > Simply use `print(response)` to get the same output if you just want to see the response text
870
869
 
871
- ### Generate contents from image
870
+ ### Generate contents with files
872
871
 
873
- Gemini supports image recognition and generating contents from images. Optionally, you can pass images in a list of file data in `bytes` or their paths in `str` or `pathlib.Path` to `GeminiClient.generate_content` together with text prompt.
872
+ Gemini supports file input, including images and documents. Optionally, you can pass files as a list of paths in `str` or `pathlib.Path` to `GeminiClient.generate_content` together with text prompt.
874
873
 
875
874
  ```python
876
875
  async def main():
877
876
  response = await client.generate_content(
878
- "Describe each of these images",
879
- images=["assets/banner.png", "assets/favicon.png"],
877
+ "Introduce the contents of these two files. Is there any connection between them?",
878
+ files=["assets/sample.pdf", Path("assets/banner.png")],
880
879
  )
881
880
  print(response.text)
882
881
 
@@ -890,9 +889,15 @@ If you want to keep conversation continuous, please use `GeminiClient.start_chat
890
889
  ```python
891
890
  async def main():
892
891
  chat = client.start_chat()
893
- response1 = await chat.send_message("Briefly introduce Europe")
894
- response2 = await chat.send_message("What's the population there?")
895
- print(response1.text, response2.text, sep="\n\n----------------------------------\n\n")
892
+ response1 = await chat.send_message(
893
+ "Introduce the contents of these two files. Is there any connection between them?",
894
+ files=["assets/sample.pdf", Path("assets/banner.png")],
895
+ )
896
+ print(response1.text)
897
+ response2 = await chat.send_message(
898
+ "Use image generation tool to modify the banner with another font and design."
899
+ )
900
+ print(response2.text, response2.images, sep="\n\n----------------------------------\n\n")
896
901
 
897
902
  asyncio.run(main())
898
903
  ```
@@ -950,24 +955,27 @@ async def main():
950
955
  asyncio.run(main())
951
956
  ```
952
957
 
953
- ### Generate images with ImageFx
958
+ ### Generate images with Imagen3
954
959
 
955
- In February 2022, Google introduced a new AI image generator called ImageFx and integrated it into Gemini. You can ask Gemini to generate images with ImageFx simply by natural language.
960
+ You can ask Gemini to generate and modify images with Imagen3, Google's latest AI image generator, simply by natural language.
956
961
 
957
962
  > [!IMPORTANT]
958
963
  >
959
- > Google has some limitations on the image generation feature in Gemini, so its availability could be different per region/account. Here's a summary copied from [official documentation](https://support.google.com/gemini/answer/14286560) (as of February 15th, 2024):
964
+ > Google has some limitations on the image generation feature in Gemini, so its availability could be different per region/account. Here's a summary copied from [official documentation](https://support.google.com/gemini/answer/14286560) (as of March 19th, 2025):
960
965
  >
961
- > > Image generation in Gemini Apps is available in most countries, except in the European Economic Area (EEA), Switzerland, and the UK. It’s only available for **English prompts**.
962
- > >
963
966
  > > This feature’s availability in any specific Gemini app is also limited to the supported languages and countries of that app.
964
967
  > >
965
968
  > > For now, this feature isn’t available to users under 18.
969
+ > >
970
+ > > To use this feature, you must be signed in to Gemini Apps.
971
+
972
+ You can save images returned from Gemini to local by calling `Image.save()`. Optionally, you can specify the file path and file name by passing `path` and `filename` arguments to the function and skip images with invalid file names by passing `skip_invalid_filename=True`. Works for both `WebImage` and `GeneratedImage`.
966
973
 
967
974
  ```python
968
975
  async def main():
969
976
  response = await client.generate_content("Generate some pictures of cats")
970
- for image in response.images:
977
+ for i, image in enumerate(response.images):
978
+ await image.save(path="temp/", filename=f"cat_{i}.png", verbose=True)
971
979
  print(image, "\n\n----------------------------------\n")
972
980
 
973
981
  asyncio.run(main())
@@ -977,32 +985,17 @@ asyncio.run(main())
977
985
  >
978
986
  > by default, when asked to send images (like the previous example), Gemini will send images fetched from web instead of generating images with AI model, unless you specifically require to "generate" images in your prompt. In this package, web images and generated images are treated differently as `WebImage` and `GeneratedImage`, and will be automatically categorized in the output.
979
987
 
980
- ### Save images to local files
981
-
982
- You can save images returned from Gemini to local files under `/temp` by calling `Image.save()`. Optionally, you can specify the file path and file name by passing `path` and `filename` arguments to the function and skip images with invalid file names by passing `skip_invalid_filename=True`. Works for both `WebImage` and `GeneratedImage`.
983
-
984
- ```python
985
- async def main():
986
- response = await client.generate_content("Generate some pictures of cats")
987
- for i, image in enumerate(response.images):
988
- await image.save(path="temp/", filename=f"cat_{i}.png", verbose=True)
989
-
990
- asyncio.run(main())
991
- ```
992
-
993
988
  ### Generate contents with Gemini extensions
994
989
 
995
990
  > [!IMPORTANT]
996
991
  >
997
- > To access Gemini extensions in API, you must activate them on the [Gemini website](https://gemini.google.com/extensions) first. Same as image generation, Google also has limitations on the availability of Gemini extensions. Here's a summary copied from [official documentation](https://support.google.com/gemini/answer/13695044) (as of February 18th, 2024):
992
+ > To access Gemini extensions in API, you must activate them on the [Gemini website](https://gemini.google.com/extensions) first. Same as image generation, Google also has limitations on the availability of Gemini extensions. Here's a summary copied from [official documentation](https://support.google.com/gemini/answer/13695044) (as of March 19th, 2025):
998
993
  >
999
- > > To use extensions in Gemini Apps:
1000
- > >
1001
- > > Sign in with your personal Google Account that you manage on your own. Extensions, including the Google Workspace extension, are currently not available to Google Workspace accounts for school, business, or other organizations.
994
+ > > To connect apps to Gemini, you must have​​​​ Gemini Apps Activity on.
1002
995
  > >
1003
- > > Have Gemini Apps Activity on. Extensions are only available when Gemini Apps Activity is turned on.
996
+ > > To use this feature, you must be signed in to Gemini Apps.
1004
997
  > >
1005
- > > Important: For now, extensions are available in **English, Japanese, and Korean** only.
998
+ > > Important: If you’re under 18, Google Workspace and Maps apps currently only work with English prompts in Gemini.
1006
999
 
1007
1000
  After activating extensions for your account, you can access them in your prompts either by natural language or by starting your prompt with "@" followed by the extension keyword.
1008
1001
 
@@ -1,19 +1,19 @@
1
1
  gemini_webapi/__init__.py,sha256=28uNIywK4vCXxENaSagNWUzhqr1RyNtLzDF6WRRM4KQ,194
2
- gemini_webapi/client.py,sha256=4ptFBYy-ipcxox1x7WDOK04YMYU_cu6NwS8CSrmz3kM,23105
3
- gemini_webapi/constants.py,sha256=_8TdJH3dvzSDo0qfhKCAerWXBbH71u0B0mSGOkkJQ5w,2737
2
+ gemini_webapi/client.py,sha256=WsH07qepNSQzq4pdYIJW393Jr4gcdp8D64ti6GlDj9E,23065
3
+ gemini_webapi/constants.py,sha256=pg0JiSbUgrsMqVkWwPSPRqKfKIo2qpDAEJ7Kl-XOBc4,2925
4
4
  gemini_webapi/exceptions.py,sha256=6e-EXHGApi4iC0GDw7RKc3YqVK8UvEkHYaJyGQbReLw,548
5
5
  gemini_webapi/types/__init__.py,sha256=d2kvXnE004s2E2KDmPPLi5N-BQ59FgDSlrGrO3Wphww,163
6
6
  gemini_webapi/types/candidate.py,sha256=dMoGr53WR7FYDRrXpG9Yd_n9YTHGwGaFHZ8zPt8RMWw,1178
7
7
  gemini_webapi/types/image.py,sha256=4BC8hxAWJrYFwzA60CivF1di4RZkzPKjcaSPPFKmRdY,5237
8
8
  gemini_webapi/types/modeloutput.py,sha256=h07kQOkL5r-oPLvZ59uVtO1eP4FGy5ZpzuYQzAeQdr8,1196
9
- gemini_webapi/utils/__init__.py,sha256=mcm1kgQ5HHKyZrhHS-rd_GXbKMpIDUsq02XtmlQNN_I,357
9
+ gemini_webapi/utils/__init__.py,sha256=tO6Sx-3fcPeyITZcvUmcFKBFlR5XW87xUFbNrIh3_mE,374
10
10
  gemini_webapi/utils/get_access_token.py,sha256=uyb6tuzPr3mHttCjiM86M29ykrnHqsUClYdf5sVkyEQ,5465
11
11
  gemini_webapi/utils/load_browser_cookies.py,sha256=A5n_VsB7Rm8ck5lpy856UNJEhv30l3dvQ3j0g3ln1fE,1535
12
12
  gemini_webapi/utils/logger.py,sha256=PF4ROQq7scRRrWzeYdeYiYs2S2Jqr0bgjyrPbXVOCqE,816
13
13
  gemini_webapi/utils/rotate_1psidts.py,sha256=NyQ9OYPLBOcvpc8bodvEYDIVFrsYN0kdfc831lPEctM,1680
14
- gemini_webapi/utils/upload_file.py,sha256=A-ZQ54gy2wOVA_giEEVLQQK5zTJfrgq99Z5YYYOAFYc,1163
15
- gemini_webapi-1.9.1.dist-info/licenses/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
16
- gemini_webapi-1.9.1.dist-info/METADATA,sha256=LXrhPGqkC1MfBvX868TaWV-xKuVpQmsDbi90KSrKHzg,57797
17
- gemini_webapi-1.9.1.dist-info/WHEEL,sha256=tTnHoFhvKQHCh4jz3yCn0WPTYIy7wXx3CJtJ7SJGV7c,91
18
- gemini_webapi-1.9.1.dist-info/top_level.txt,sha256=dtWtug_ZrmnUqCYuu8NmGzTgWglHeNzhHU_hXmqZGWE,14
19
- gemini_webapi-1.9.1.dist-info/RECORD,,
14
+ gemini_webapi/utils/upload_file.py,sha256=SJOMr6kryK_ClrKmqI96fqZBNFOMPsyAvFINAGAU3rk,1468
15
+ gemini_webapi-1.10.0.dist-info/licenses/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
16
+ gemini_webapi-1.10.0.dist-info/METADATA,sha256=j5G5uhgjXjfAUYwK8UmWVP85ZCXoAxdwVLrsiu7FtKQ,57353
17
+ gemini_webapi-1.10.0.dist-info/WHEEL,sha256=tTnHoFhvKQHCh4jz3yCn0WPTYIy7wXx3CJtJ7SJGV7c,91
18
+ gemini_webapi-1.10.0.dist-info/top_level.txt,sha256=dtWtug_ZrmnUqCYuu8NmGzTgWglHeNzhHU_hXmqZGWE,14
19
+ gemini_webapi-1.10.0.dist-info/RECORD,,