gemini-webapi 1.9.1__tar.gz → 1.10.1__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.
Files changed (37) hide show
  1. {gemini_webapi-1.9.1 → gemini_webapi-1.10.1}/.github/workflows/pypi-publish.yml +2 -2
  2. {gemini_webapi-1.9.1 → gemini_webapi-1.10.1}/PKG-INFO +31 -37
  3. {gemini_webapi-1.9.1 → gemini_webapi-1.10.1}/README.md +30 -36
  4. gemini_webapi-1.10.1/assets/sample.pdf +0 -0
  5. {gemini_webapi-1.9.1 → gemini_webapi-1.10.1}/src/gemini_webapi/client.py +12 -11
  6. {gemini_webapi-1.9.1 → gemini_webapi-1.10.1}/src/gemini_webapi/constants.py +9 -4
  7. {gemini_webapi-1.9.1 → gemini_webapi-1.10.1}/src/gemini_webapi/utils/__init__.py +1 -1
  8. {gemini_webapi-1.9.1 → gemini_webapi-1.10.1}/src/gemini_webapi/utils/upload_file.py +27 -6
  9. {gemini_webapi-1.9.1 → gemini_webapi-1.10.1}/src/gemini_webapi.egg-info/PKG-INFO +31 -37
  10. {gemini_webapi-1.9.1 → gemini_webapi-1.10.1}/src/gemini_webapi.egg-info/SOURCES.txt +1 -0
  11. {gemini_webapi-1.9.1 → gemini_webapi-1.10.1}/tests/test_client_features.py +9 -22
  12. {gemini_webapi-1.9.1 → gemini_webapi-1.10.1}/.github/dependabot.yml +0 -0
  13. {gemini_webapi-1.9.1 → gemini_webapi-1.10.1}/.github/workflows/github-release.yml +0 -0
  14. {gemini_webapi-1.9.1 → gemini_webapi-1.10.1}/.gitignore +0 -0
  15. {gemini_webapi-1.9.1 → gemini_webapi-1.10.1}/.vscode/launch.json +0 -0
  16. {gemini_webapi-1.9.1 → gemini_webapi-1.10.1}/.vscode/settings.json +0 -0
  17. {gemini_webapi-1.9.1 → gemini_webapi-1.10.1}/LICENSE +0 -0
  18. {gemini_webapi-1.9.1 → gemini_webapi-1.10.1}/assets/banner.png +0 -0
  19. {gemini_webapi-1.9.1 → gemini_webapi-1.10.1}/assets/favicon.png +0 -0
  20. {gemini_webapi-1.9.1 → gemini_webapi-1.10.1}/assets/logo.svg +0 -0
  21. {gemini_webapi-1.9.1 → gemini_webapi-1.10.1}/pyproject.toml +0 -0
  22. {gemini_webapi-1.9.1 → gemini_webapi-1.10.1}/setup.cfg +0 -0
  23. {gemini_webapi-1.9.1 → gemini_webapi-1.10.1}/src/gemini_webapi/__init__.py +0 -0
  24. {gemini_webapi-1.9.1 → gemini_webapi-1.10.1}/src/gemini_webapi/exceptions.py +0 -0
  25. {gemini_webapi-1.9.1 → gemini_webapi-1.10.1}/src/gemini_webapi/types/__init__.py +0 -0
  26. {gemini_webapi-1.9.1 → gemini_webapi-1.10.1}/src/gemini_webapi/types/candidate.py +0 -0
  27. {gemini_webapi-1.9.1 → gemini_webapi-1.10.1}/src/gemini_webapi/types/image.py +0 -0
  28. {gemini_webapi-1.9.1 → gemini_webapi-1.10.1}/src/gemini_webapi/types/modeloutput.py +0 -0
  29. {gemini_webapi-1.9.1 → gemini_webapi-1.10.1}/src/gemini_webapi/utils/get_access_token.py +0 -0
  30. {gemini_webapi-1.9.1 → gemini_webapi-1.10.1}/src/gemini_webapi/utils/load_browser_cookies.py +0 -0
  31. {gemini_webapi-1.9.1 → gemini_webapi-1.10.1}/src/gemini_webapi/utils/logger.py +0 -0
  32. {gemini_webapi-1.9.1 → gemini_webapi-1.10.1}/src/gemini_webapi/utils/rotate_1psidts.py +0 -0
  33. {gemini_webapi-1.9.1 → gemini_webapi-1.10.1}/src/gemini_webapi.egg-info/dependency_links.txt +0 -0
  34. {gemini_webapi-1.9.1 → gemini_webapi-1.10.1}/src/gemini_webapi.egg-info/requires.txt +0 -0
  35. {gemini_webapi-1.9.1 → gemini_webapi-1.10.1}/src/gemini_webapi.egg-info/top_level.txt +0 -0
  36. {gemini_webapi-1.9.1 → gemini_webapi-1.10.1}/tests/test_rotate_cookies.py +0 -0
  37. {gemini_webapi-1.9.1 → gemini_webapi-1.10.1}/tests/test_save_image.py +0 -0
@@ -36,7 +36,7 @@ jobs:
36
36
  - name: Build package
37
37
  run: python -m build
38
38
  - name: Archive production artifacts
39
- uses: actions/upload-artifact@v4.6.0
39
+ uses: actions/upload-artifact@v4.6.2
40
40
  with:
41
41
  name: dist
42
42
  path: dist
@@ -52,7 +52,7 @@ jobs:
52
52
  id-token: write # IMPORTANT: this permission is mandatory for trusted publishing
53
53
  steps:
54
54
  - name: Retrieve built artifacts
55
- uses: actions/download-artifact@v4.1.8
55
+ uses: actions/download-artifact@v4.2.1
56
56
  with:
57
57
  name: dist
58
58
  path: dist
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gemini-webapi
3
- Version: 1.9.1
3
+ Version: 1.10.1
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)
@@ -831,6 +830,7 @@ Currently available models (as of Feb 5, 2025):
831
830
 
832
831
  Models pending update (may not work as expected):
833
832
 
833
+ - `gemini-2.5-exp-advanced` - Gemini 2.5 Experimental Advanced **(requires Gemini Advanced account)**
834
834
  - `gemini-2.0-exp-advanced` - Gemini 2.0 Experimental Advanced **(requires Gemini Advanced account)**
835
835
  - `gemini-1.5-pro` - Gemini 1.5 Pro **(requires Gemini Advanced account)**
836
836
  - `gemini-1.5-pro-research` - Gemini 1.5 Pro with Deep Research **(requires Gemini Advanced account)**
@@ -868,15 +868,15 @@ asyncio.run(main())
868
868
  >
869
869
  > Simply use `print(response)` to get the same output if you just want to see the response text
870
870
 
871
- ### Generate contents from image
871
+ ### Generate contents with files
872
872
 
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.
873
+ 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
874
 
875
875
  ```python
876
876
  async def main():
877
877
  response = await client.generate_content(
878
- "Describe each of these images",
879
- images=["assets/banner.png", "assets/favicon.png"],
878
+ "Introduce the contents of these two files. Is there any connection between them?",
879
+ files=["assets/sample.pdf", Path("assets/banner.png")],
880
880
  )
881
881
  print(response.text)
882
882
 
@@ -890,9 +890,15 @@ If you want to keep conversation continuous, please use `GeminiClient.start_chat
890
890
  ```python
891
891
  async def main():
892
892
  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")
893
+ response1 = await chat.send_message(
894
+ "Introduce the contents of these two files. Is there any connection between them?",
895
+ files=["assets/sample.pdf", Path("assets/banner.png")],
896
+ )
897
+ print(response1.text)
898
+ response2 = await chat.send_message(
899
+ "Use image generation tool to modify the banner with another font and design."
900
+ )
901
+ print(response2.text, response2.images, sep="\n\n----------------------------------\n\n")
896
902
 
897
903
  asyncio.run(main())
898
904
  ```
@@ -950,24 +956,27 @@ async def main():
950
956
  asyncio.run(main())
951
957
  ```
952
958
 
953
- ### Generate images with ImageFx
959
+ ### Generate images with Imagen3
954
960
 
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.
961
+ You can ask Gemini to generate and modify images with Imagen3, Google's latest AI image generator, simply by natural language.
956
962
 
957
963
  > [!IMPORTANT]
958
964
  >
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):
965
+ > 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
966
  >
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
967
  > > This feature’s availability in any specific Gemini app is also limited to the supported languages and countries of that app.
964
968
  > >
965
969
  > > For now, this feature isn’t available to users under 18.
970
+ > >
971
+ > > To use this feature, you must be signed in to Gemini Apps.
972
+
973
+ 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
974
 
967
975
  ```python
968
976
  async def main():
969
977
  response = await client.generate_content("Generate some pictures of cats")
970
- for image in response.images:
978
+ for i, image in enumerate(response.images):
979
+ await image.save(path="temp/", filename=f"cat_{i}.png", verbose=True)
971
980
  print(image, "\n\n----------------------------------\n")
972
981
 
973
982
  asyncio.run(main())
@@ -977,32 +986,17 @@ asyncio.run(main())
977
986
  >
978
987
  > 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
988
 
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
989
  ### Generate contents with Gemini extensions
994
990
 
995
991
  > [!IMPORTANT]
996
992
  >
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):
993
+ > 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
994
  >
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.
995
+ > > To connect apps to Gemini, you must have​​​​ Gemini Apps Activity on.
1002
996
  > >
1003
- > > Have Gemini Apps Activity on. Extensions are only available when Gemini Apps Activity is turned on.
997
+ > > To use this feature, you must be signed in to Gemini Apps.
1004
998
  > >
1005
- > > Important: For now, extensions are available in **English, Japanese, and Korean** only.
999
+ > > Important: If you’re under 18, Google Workspace and Maps apps currently only work with English prompts in Gemini.
1006
1000
 
1007
1001
  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
1002
 
@@ -29,7 +29,7 @@ A reverse-engineered asynchronous python wrapper for [Google Gemini](https://gem
29
29
  ## Features
30
30
 
31
31
  - **Persistent Cookies** - Automatically refreshes cookies in background. Optimized for always-on services.
32
- - **ImageFx Support** - Supports retrieving images generated by ImageFx, Google's latest AI image generator.
32
+ - **Image Generation** - Natively supports generating and modifying images with natural language.
33
33
  - **Extension Support** - Supports generating contents with [Gemini extensions](https://gemini.google.com/extensions) on, like YouTube and Gmail.
34
34
  - **Classified Outputs** - Automatically categorizes texts, web images and AI generated images in the response.
35
35
  - **Official Flavor** - Provides a simple and elegant interface inspired by [Google Generative AI](https://ai.google.dev/tutorials/python_quickstart)'s official API.
@@ -45,13 +45,12 @@ A reverse-engineered asynchronous python wrapper for [Google Gemini](https://gem
45
45
  - [Initialization](#initialization)
46
46
  - [Select language model](#select-language-model)
47
47
  - [Generate contents from text](#generate-contents-from-text)
48
- - [Generate contents from image](#generate-contents-from-image)
48
+ - [Generate contents with files](#generate-contents-with-files)
49
49
  - [Conversations across multiple turns](#conversations-across-multiple-turns)
50
50
  - [Continue previous conversations](#continue-previous-conversations)
51
51
  - [Retrieve model's thought process](#retrieve-models-thought-process)
52
52
  - [Retrieve images in response](#retrieve-images-in-response)
53
- - [Generate images with ImageFx](#generate-images-with-imagefx)
54
- - [Save images to local files](#save-images-to-local-files)
53
+ - [Generate images with Imagen3](#generate-images-with-imagen3)
55
54
  - [Generate contents with Gemini extensions](#generate-contents-with-gemini-extensions)
56
55
  - [Check and switch to other reply candidates](#check-and-switch-to-other-reply-candidates)
57
56
  - [Control log level](#control-log-level)
@@ -148,6 +147,7 @@ Currently available models (as of Feb 5, 2025):
148
147
 
149
148
  Models pending update (may not work as expected):
150
149
 
150
+ - `gemini-2.5-exp-advanced` - Gemini 2.5 Experimental Advanced **(requires Gemini Advanced account)**
151
151
  - `gemini-2.0-exp-advanced` - Gemini 2.0 Experimental Advanced **(requires Gemini Advanced account)**
152
152
  - `gemini-1.5-pro` - Gemini 1.5 Pro **(requires Gemini Advanced account)**
153
153
  - `gemini-1.5-pro-research` - Gemini 1.5 Pro with Deep Research **(requires Gemini Advanced account)**
@@ -185,15 +185,15 @@ asyncio.run(main())
185
185
  >
186
186
  > Simply use `print(response)` to get the same output if you just want to see the response text
187
187
 
188
- ### Generate contents from image
188
+ ### Generate contents with files
189
189
 
190
- 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.
190
+ 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.
191
191
 
192
192
  ```python
193
193
  async def main():
194
194
  response = await client.generate_content(
195
- "Describe each of these images",
196
- images=["assets/banner.png", "assets/favicon.png"],
195
+ "Introduce the contents of these two files. Is there any connection between them?",
196
+ files=["assets/sample.pdf", Path("assets/banner.png")],
197
197
  )
198
198
  print(response.text)
199
199
 
@@ -207,9 +207,15 @@ If you want to keep conversation continuous, please use `GeminiClient.start_chat
207
207
  ```python
208
208
  async def main():
209
209
  chat = client.start_chat()
210
- response1 = await chat.send_message("Briefly introduce Europe")
211
- response2 = await chat.send_message("What's the population there?")
212
- print(response1.text, response2.text, sep="\n\n----------------------------------\n\n")
210
+ response1 = await chat.send_message(
211
+ "Introduce the contents of these two files. Is there any connection between them?",
212
+ files=["assets/sample.pdf", Path("assets/banner.png")],
213
+ )
214
+ print(response1.text)
215
+ response2 = await chat.send_message(
216
+ "Use image generation tool to modify the banner with another font and design."
217
+ )
218
+ print(response2.text, response2.images, sep="\n\n----------------------------------\n\n")
213
219
 
214
220
  asyncio.run(main())
215
221
  ```
@@ -267,24 +273,27 @@ async def main():
267
273
  asyncio.run(main())
268
274
  ```
269
275
 
270
- ### Generate images with ImageFx
276
+ ### Generate images with Imagen3
271
277
 
272
- 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.
278
+ You can ask Gemini to generate and modify images with Imagen3, Google's latest AI image generator, simply by natural language.
273
279
 
274
280
  > [!IMPORTANT]
275
281
  >
276
- > 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):
282
+ > 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):
277
283
  >
278
- > > 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**.
279
- > >
280
284
  > > This feature’s availability in any specific Gemini app is also limited to the supported languages and countries of that app.
281
285
  > >
282
286
  > > For now, this feature isn’t available to users under 18.
287
+ > >
288
+ > > To use this feature, you must be signed in to Gemini Apps.
289
+
290
+ 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`.
283
291
 
284
292
  ```python
285
293
  async def main():
286
294
  response = await client.generate_content("Generate some pictures of cats")
287
- for image in response.images:
295
+ for i, image in enumerate(response.images):
296
+ await image.save(path="temp/", filename=f"cat_{i}.png", verbose=True)
288
297
  print(image, "\n\n----------------------------------\n")
289
298
 
290
299
  asyncio.run(main())
@@ -294,32 +303,17 @@ asyncio.run(main())
294
303
  >
295
304
  > 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.
296
305
 
297
- ### Save images to local files
298
-
299
- 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`.
300
-
301
- ```python
302
- async def main():
303
- response = await client.generate_content("Generate some pictures of cats")
304
- for i, image in enumerate(response.images):
305
- await image.save(path="temp/", filename=f"cat_{i}.png", verbose=True)
306
-
307
- asyncio.run(main())
308
- ```
309
-
310
306
  ### Generate contents with Gemini extensions
311
307
 
312
308
  > [!IMPORTANT]
313
309
  >
314
- > 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):
310
+ > 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):
315
311
  >
316
- > > To use extensions in Gemini Apps:
317
- > >
318
- > > 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.
312
+ > > To connect apps to Gemini, you must have​​​​ Gemini Apps Activity on.
319
313
  > >
320
- > > Have Gemini Apps Activity on. Extensions are only available when Gemini Apps Activity is turned on.
314
+ > > To use this feature, you must be signed in to Gemini Apps.
321
315
  > >
322
- > > Important: For now, extensions are available in **English, Japanese, and Korean** only.
316
+ > > Important: If you’re under 18, Google Workspace and Maps apps currently only work with English prompts in Gemini.
323
317
 
324
318
  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.
325
319
 
Binary file
@@ -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,27 +44,32 @@ 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"]'},
51
51
  True,
52
52
  )
53
+ G_2_5_EXP_ADVANCED = (
54
+ "gemini-2.5-exp-advanced",
55
+ {"x-goog-ext-525001261-jspb": '[null,null,null,null,"203e6bb81620bcfe"]'},
56
+ True,
57
+ )
53
58
  G_1_5_FLASH = (
54
59
  "gemini-1.5-flash",
55
60
  {"x-goog-ext-525001261-jspb": '[null,null,null,null,"418ab5ea040b5c43"]'},
56
61
  False,
57
- )
62
+ ) # Deprecated, should be removed in the future
58
63
  G_1_5_PRO = (
59
64
  "gemini-1.5-pro",
60
65
  {"x-goog-ext-525001261-jspb": '[null,null,null,null,"9d60dfae93c9ff1f"]'},
61
66
  True,
62
- )
67
+ ) # Deprecated, should be removed in the future
63
68
  G_1_5_PRO_RESEARCH = (
64
69
  "gemini-1.5-pro-research",
65
70
  {"x-goog-ext-525001261-jspb": '[null,null,null,null,"e5a44cb1dae2b489"]'},
66
71
  True,
67
- )
72
+ ) # Deprecated, should be removed in the future
68
73
 
69
74
  def __init__(self, name, header, advanced_only):
70
75
  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.1
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)
@@ -831,6 +830,7 @@ Currently available models (as of Feb 5, 2025):
831
830
 
832
831
  Models pending update (may not work as expected):
833
832
 
833
+ - `gemini-2.5-exp-advanced` - Gemini 2.5 Experimental Advanced **(requires Gemini Advanced account)**
834
834
  - `gemini-2.0-exp-advanced` - Gemini 2.0 Experimental Advanced **(requires Gemini Advanced account)**
835
835
  - `gemini-1.5-pro` - Gemini 1.5 Pro **(requires Gemini Advanced account)**
836
836
  - `gemini-1.5-pro-research` - Gemini 1.5 Pro with Deep Research **(requires Gemini Advanced account)**
@@ -868,15 +868,15 @@ asyncio.run(main())
868
868
  >
869
869
  > Simply use `print(response)` to get the same output if you just want to see the response text
870
870
 
871
- ### Generate contents from image
871
+ ### Generate contents with files
872
872
 
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.
873
+ 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
874
 
875
875
  ```python
876
876
  async def main():
877
877
  response = await client.generate_content(
878
- "Describe each of these images",
879
- images=["assets/banner.png", "assets/favicon.png"],
878
+ "Introduce the contents of these two files. Is there any connection between them?",
879
+ files=["assets/sample.pdf", Path("assets/banner.png")],
880
880
  )
881
881
  print(response.text)
882
882
 
@@ -890,9 +890,15 @@ If you want to keep conversation continuous, please use `GeminiClient.start_chat
890
890
  ```python
891
891
  async def main():
892
892
  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")
893
+ response1 = await chat.send_message(
894
+ "Introduce the contents of these two files. Is there any connection between them?",
895
+ files=["assets/sample.pdf", Path("assets/banner.png")],
896
+ )
897
+ print(response1.text)
898
+ response2 = await chat.send_message(
899
+ "Use image generation tool to modify the banner with another font and design."
900
+ )
901
+ print(response2.text, response2.images, sep="\n\n----------------------------------\n\n")
896
902
 
897
903
  asyncio.run(main())
898
904
  ```
@@ -950,24 +956,27 @@ async def main():
950
956
  asyncio.run(main())
951
957
  ```
952
958
 
953
- ### Generate images with ImageFx
959
+ ### Generate images with Imagen3
954
960
 
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.
961
+ You can ask Gemini to generate and modify images with Imagen3, Google's latest AI image generator, simply by natural language.
956
962
 
957
963
  > [!IMPORTANT]
958
964
  >
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):
965
+ > 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
966
  >
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
967
  > > This feature’s availability in any specific Gemini app is also limited to the supported languages and countries of that app.
964
968
  > >
965
969
  > > For now, this feature isn’t available to users under 18.
970
+ > >
971
+ > > To use this feature, you must be signed in to Gemini Apps.
972
+
973
+ 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
974
 
967
975
  ```python
968
976
  async def main():
969
977
  response = await client.generate_content("Generate some pictures of cats")
970
- for image in response.images:
978
+ for i, image in enumerate(response.images):
979
+ await image.save(path="temp/", filename=f"cat_{i}.png", verbose=True)
971
980
  print(image, "\n\n----------------------------------\n")
972
981
 
973
982
  asyncio.run(main())
@@ -977,32 +986,17 @@ asyncio.run(main())
977
986
  >
978
987
  > 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
988
 
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
989
  ### Generate contents with Gemini extensions
994
990
 
995
991
  > [!IMPORTANT]
996
992
  >
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):
993
+ > 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
994
  >
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.
995
+ > > To connect apps to Gemini, you must have​​​​ Gemini Apps Activity on.
1002
996
  > >
1003
- > > Have Gemini Apps Activity on. Extensions are only available when Gemini Apps Activity is turned on.
997
+ > > To use this feature, you must be signed in to Gemini Apps.
1004
998
  > >
1005
- > > Important: For now, extensions are available in **English, Japanese, and Korean** only.
999
+ > > Important: If you’re under 18, Google Workspace and Maps apps currently only work with English prompts in Gemini.
1006
1000
 
1007
1001
  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
1002
 
@@ -10,6 +10,7 @@ pyproject.toml
10
10
  assets/banner.png
11
11
  assets/favicon.png
12
12
  assets/logo.svg
13
+ assets/sample.pdf
13
14
  src/gemini_webapi/__init__.py
14
15
  src/gemini_webapi/client.py
15
16
  src/gemini_webapi/constants.py
@@ -32,17 +32,9 @@ class TestGeminiClient(unittest.IsolatedAsyncioTestCase):
32
32
 
33
33
  @logger.catch(reraise=True)
34
34
  async def test_thinking_model(self):
35
- response = await self.geminiclient.generate_content(
36
- "What's 1+1?", model=Model.G_2_0_FLASH_THINKING
37
- )
38
- logger.debug(response.thoughts)
39
- logger.debug(response.text)
40
-
41
- @logger.catch(reraise=True)
42
- async def test_thinking_with_apps(self):
43
35
  response = await self.geminiclient.generate_content(
44
36
  "Tell me a fact about today in history and illustrate it with a youtube video",
45
- model=Model.G_2_0_FLASH_THINKING_WITH_APPS,
37
+ model=Model.G_2_0_FLASH_THINKING,
46
38
  )
47
39
  logger.debug(response.thoughts)
48
40
  logger.debug(response.text)
@@ -61,10 +53,10 @@ class TestGeminiClient(unittest.IsolatedAsyncioTestCase):
61
53
  logger.debug(f"Model version ({model.model_name}): {response.text}")
62
54
 
63
55
  @logger.catch(reraise=True)
64
- async def test_upload_image(self):
56
+ async def test_upload_files(self):
65
57
  response = await self.geminiclient.generate_content(
66
- "Describe these images",
67
- images=[Path("assets/banner.png"), "assets/favicon.png"],
58
+ "Introduce the contents of these two files. Is there any connection between them?",
59
+ files=["assets/sample.pdf", Path("assets/banner.png")],
68
60
  )
69
61
  logger.debug(response.text)
70
62
 
@@ -92,11 +84,14 @@ class TestGeminiClient(unittest.IsolatedAsyncioTestCase):
92
84
  chat = self.geminiclient.start_chat()
93
85
  response1 = await chat.send_message(
94
86
  "What's the difference between these two images?",
95
- images=["assets/banner.png", "assets/favicon.png"],
87
+ files=["assets/banner.png", "assets/favicon.png"],
96
88
  )
97
89
  logger.debug(response1.text)
98
- response2 = await chat.send_message("Tell me more.")
90
+ response2 = await chat.send_message(
91
+ "Use image generation tool to modify the banner with another font and design."
92
+ )
99
93
  logger.debug(response2.text)
94
+ logger.debug(response2.images)
100
95
 
101
96
  @logger.catch(reraise=True)
102
97
  async def test_send_web_image(self):
@@ -120,14 +115,6 @@ class TestGeminiClient(unittest.IsolatedAsyncioTestCase):
120
115
  self.assertTrue(image.url)
121
116
  logger.debug(image)
122
117
 
123
- @logger.catch(reraise=True)
124
- async def test_image_generation_failure(self):
125
- response = await self.geminiclient.generate_content(
126
- "Generate some pictures of people"
127
- )
128
- self.assertFalse(response.images)
129
- logger.debug(response.text)
130
-
131
118
  @logger.catch(reraise=True)
132
119
  async def test_card_content(self):
133
120
  response = await self.geminiclient.generate_content("How is today's weather?")
File without changes
File without changes
File without changes