webscout 8.2.9__py3-none-any.whl → 2026.1.19__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.
- webscout/AIauto.py +524 -251
- webscout/AIbase.py +247 -319
- webscout/AIutel.py +68 -703
- webscout/Bard.py +1072 -1026
- webscout/Extra/GitToolkit/__init__.py +10 -10
- webscout/Extra/GitToolkit/gitapi/__init__.py +20 -12
- webscout/Extra/GitToolkit/gitapi/gist.py +142 -0
- webscout/Extra/GitToolkit/gitapi/organization.py +91 -0
- webscout/Extra/GitToolkit/gitapi/repository.py +308 -195
- webscout/Extra/GitToolkit/gitapi/search.py +162 -0
- webscout/Extra/GitToolkit/gitapi/trending.py +236 -0
- webscout/Extra/GitToolkit/gitapi/user.py +128 -96
- webscout/Extra/GitToolkit/gitapi/utils.py +82 -62
- webscout/Extra/YTToolkit/README.md +443 -375
- webscout/Extra/YTToolkit/YTdownloader.py +953 -957
- webscout/Extra/YTToolkit/__init__.py +3 -3
- webscout/Extra/YTToolkit/transcriber.py +595 -476
- webscout/Extra/YTToolkit/ytapi/README.md +230 -44
- webscout/Extra/YTToolkit/ytapi/__init__.py +22 -6
- webscout/Extra/YTToolkit/ytapi/captions.py +190 -0
- webscout/Extra/YTToolkit/ytapi/channel.py +302 -307
- webscout/Extra/YTToolkit/ytapi/errors.py +13 -13
- webscout/Extra/YTToolkit/ytapi/extras.py +178 -118
- webscout/Extra/YTToolkit/ytapi/hashtag.py +120 -0
- webscout/Extra/YTToolkit/ytapi/https.py +89 -88
- webscout/Extra/YTToolkit/ytapi/patterns.py +61 -61
- webscout/Extra/YTToolkit/ytapi/playlist.py +59 -59
- webscout/Extra/YTToolkit/ytapi/pool.py +8 -8
- webscout/Extra/YTToolkit/ytapi/query.py +143 -40
- webscout/Extra/YTToolkit/ytapi/shorts.py +122 -0
- webscout/Extra/YTToolkit/ytapi/stream.py +68 -63
- webscout/Extra/YTToolkit/ytapi/suggestions.py +97 -0
- webscout/Extra/YTToolkit/ytapi/utils.py +66 -62
- webscout/Extra/YTToolkit/ytapi/video.py +403 -232
- webscout/Extra/__init__.py +2 -3
- webscout/Extra/gguf.py +1298 -684
- webscout/Extra/tempmail/README.md +487 -487
- webscout/Extra/tempmail/__init__.py +28 -28
- webscout/Extra/tempmail/async_utils.py +143 -141
- webscout/Extra/tempmail/base.py +172 -161
- webscout/Extra/tempmail/cli.py +191 -187
- webscout/Extra/tempmail/emailnator.py +88 -84
- webscout/Extra/tempmail/mail_tm.py +378 -361
- webscout/Extra/tempmail/temp_mail_io.py +304 -292
- webscout/Extra/weather.py +196 -194
- webscout/Extra/weather_ascii.py +17 -15
- webscout/Provider/AISEARCH/PERPLEXED_search.py +175 -0
- webscout/Provider/AISEARCH/Perplexity.py +292 -333
- webscout/Provider/AISEARCH/README.md +106 -279
- webscout/Provider/AISEARCH/__init__.py +16 -9
- webscout/Provider/AISEARCH/brave_search.py +298 -0
- webscout/Provider/AISEARCH/iask_search.py +357 -410
- webscout/Provider/AISEARCH/monica_search.py +200 -220
- webscout/Provider/AISEARCH/webpilotai_search.py +242 -255
- webscout/Provider/Algion.py +413 -0
- webscout/Provider/Andi.py +74 -69
- webscout/Provider/Apriel.py +313 -0
- webscout/Provider/Ayle.py +323 -0
- webscout/Provider/ChatSandbox.py +329 -342
- webscout/Provider/ClaudeOnline.py +365 -0
- webscout/Provider/Cohere.py +232 -208
- webscout/Provider/DeepAI.py +367 -0
- webscout/Provider/Deepinfra.py +467 -340
- webscout/Provider/EssentialAI.py +217 -0
- webscout/Provider/ExaAI.py +274 -261
- webscout/Provider/Gemini.py +175 -169
- webscout/Provider/GithubChat.py +385 -369
- webscout/Provider/Gradient.py +286 -0
- webscout/Provider/Groq.py +556 -801
- webscout/Provider/HadadXYZ.py +323 -0
- webscout/Provider/HeckAI.py +392 -375
- webscout/Provider/HuggingFace.py +387 -0
- webscout/Provider/IBM.py +340 -0
- webscout/Provider/Jadve.py +317 -291
- webscout/Provider/K2Think.py +306 -0
- webscout/Provider/Koboldai.py +221 -384
- webscout/Provider/Netwrck.py +273 -270
- webscout/Provider/Nvidia.py +310 -0
- webscout/Provider/OPENAI/DeepAI.py +489 -0
- webscout/Provider/OPENAI/K2Think.py +423 -0
- webscout/Provider/OPENAI/PI.py +463 -0
- webscout/Provider/OPENAI/README.md +890 -952
- webscout/Provider/OPENAI/TogetherAI.py +405 -0
- webscout/Provider/OPENAI/TwoAI.py +255 -357
- webscout/Provider/OPENAI/__init__.py +148 -40
- webscout/Provider/OPENAI/ai4chat.py +348 -293
- webscout/Provider/OPENAI/akashgpt.py +436 -0
- webscout/Provider/OPENAI/algion.py +303 -0
- webscout/Provider/OPENAI/{exachat.py → ayle.py} +365 -444
- webscout/Provider/OPENAI/base.py +253 -249
- webscout/Provider/OPENAI/cerebras.py +296 -0
- webscout/Provider/OPENAI/chatgpt.py +870 -556
- webscout/Provider/OPENAI/chatsandbox.py +233 -173
- webscout/Provider/OPENAI/deepinfra.py +403 -322
- webscout/Provider/OPENAI/e2b.py +2370 -1414
- webscout/Provider/OPENAI/elmo.py +278 -0
- webscout/Provider/OPENAI/exaai.py +452 -417
- webscout/Provider/OPENAI/freeassist.py +446 -0
- webscout/Provider/OPENAI/gradient.py +448 -0
- webscout/Provider/OPENAI/groq.py +380 -364
- webscout/Provider/OPENAI/hadadxyz.py +292 -0
- webscout/Provider/OPENAI/heckai.py +333 -308
- webscout/Provider/OPENAI/huggingface.py +321 -0
- webscout/Provider/OPENAI/ibm.py +425 -0
- webscout/Provider/OPENAI/llmchat.py +253 -0
- webscout/Provider/OPENAI/llmchatco.py +378 -335
- webscout/Provider/OPENAI/meta.py +541 -0
- webscout/Provider/OPENAI/netwrck.py +374 -357
- webscout/Provider/OPENAI/nvidia.py +317 -0
- webscout/Provider/OPENAI/oivscode.py +348 -287
- webscout/Provider/OPENAI/openrouter.py +328 -0
- webscout/Provider/OPENAI/pydantic_imports.py +1 -172
- webscout/Provider/OPENAI/sambanova.py +397 -0
- webscout/Provider/OPENAI/sonus.py +305 -304
- webscout/Provider/OPENAI/textpollinations.py +370 -339
- webscout/Provider/OPENAI/toolbaz.py +375 -413
- webscout/Provider/OPENAI/typefully.py +419 -355
- webscout/Provider/OPENAI/typliai.py +279 -0
- webscout/Provider/OPENAI/utils.py +314 -318
- webscout/Provider/OPENAI/wisecat.py +359 -387
- webscout/Provider/OPENAI/writecream.py +185 -163
- webscout/Provider/OPENAI/x0gpt.py +462 -365
- webscout/Provider/OPENAI/zenmux.py +380 -0
- webscout/Provider/OpenRouter.py +386 -0
- webscout/Provider/Openai.py +337 -496
- webscout/Provider/PI.py +443 -429
- webscout/Provider/QwenLM.py +346 -254
- webscout/Provider/STT/__init__.py +28 -0
- webscout/Provider/STT/base.py +303 -0
- webscout/Provider/STT/elevenlabs.py +264 -0
- webscout/Provider/Sambanova.py +317 -0
- webscout/Provider/TTI/README.md +69 -82
- webscout/Provider/TTI/__init__.py +37 -7
- webscout/Provider/TTI/base.py +147 -64
- webscout/Provider/TTI/claudeonline.py +393 -0
- webscout/Provider/TTI/magicstudio.py +292 -201
- webscout/Provider/TTI/miragic.py +180 -0
- webscout/Provider/TTI/pollinations.py +331 -221
- webscout/Provider/TTI/together.py +334 -0
- webscout/Provider/TTI/utils.py +14 -11
- webscout/Provider/TTS/README.md +186 -192
- webscout/Provider/TTS/__init__.py +43 -10
- webscout/Provider/TTS/base.py +523 -159
- webscout/Provider/TTS/deepgram.py +286 -156
- webscout/Provider/TTS/elevenlabs.py +189 -111
- webscout/Provider/TTS/freetts.py +218 -0
- webscout/Provider/TTS/murfai.py +288 -113
- webscout/Provider/TTS/openai_fm.py +364 -129
- webscout/Provider/TTS/parler.py +203 -111
- webscout/Provider/TTS/qwen.py +334 -0
- webscout/Provider/TTS/sherpa.py +286 -0
- webscout/Provider/TTS/speechma.py +693 -580
- webscout/Provider/TTS/streamElements.py +275 -333
- webscout/Provider/TTS/utils.py +280 -280
- webscout/Provider/TextPollinationsAI.py +331 -308
- webscout/Provider/TogetherAI.py +450 -0
- webscout/Provider/TwoAI.py +309 -475
- webscout/Provider/TypliAI.py +311 -305
- webscout/Provider/UNFINISHED/ChatHub.py +219 -209
- webscout/Provider/{OPENAI/glider.py → UNFINISHED/ChutesAI.py} +331 -326
- webscout/Provider/{GizAI.py → UNFINISHED/GizAI.py} +300 -295
- webscout/Provider/{Marcus.py → UNFINISHED/Marcus.py} +218 -198
- webscout/Provider/UNFINISHED/Qodo.py +481 -0
- webscout/Provider/{MCPCore.py → UNFINISHED/XenAI.py} +330 -315
- webscout/Provider/UNFINISHED/Youchat.py +347 -330
- webscout/Provider/UNFINISHED/aihumanizer.py +41 -0
- webscout/Provider/UNFINISHED/grammerchecker.py +37 -0
- webscout/Provider/UNFINISHED/liner.py +342 -0
- webscout/Provider/UNFINISHED/liner_api_request.py +246 -263
- webscout/Provider/{samurai.py → UNFINISHED/samurai.py} +231 -224
- webscout/Provider/WiseCat.py +256 -233
- webscout/Provider/WrDoChat.py +390 -370
- webscout/Provider/__init__.py +115 -174
- webscout/Provider/ai4chat.py +181 -174
- webscout/Provider/akashgpt.py +330 -335
- webscout/Provider/cerebras.py +397 -290
- webscout/Provider/cleeai.py +236 -213
- webscout/Provider/elmo.py +291 -283
- webscout/Provider/geminiapi.py +343 -208
- webscout/Provider/julius.py +245 -223
- webscout/Provider/learnfastai.py +333 -325
- webscout/Provider/llama3mitril.py +230 -215
- webscout/Provider/llmchat.py +308 -258
- webscout/Provider/llmchatco.py +321 -306
- webscout/Provider/meta.py +996 -801
- webscout/Provider/oivscode.py +332 -309
- webscout/Provider/searchchat.py +316 -292
- webscout/Provider/sonus.py +264 -258
- webscout/Provider/toolbaz.py +359 -353
- webscout/Provider/turboseek.py +332 -266
- webscout/Provider/typefully.py +262 -202
- webscout/Provider/x0gpt.py +332 -299
- webscout/__init__.py +31 -39
- webscout/__main__.py +5 -5
- webscout/cli.py +585 -524
- webscout/client.py +1497 -70
- webscout/conversation.py +140 -436
- webscout/exceptions.py +383 -362
- webscout/litagent/__init__.py +29 -29
- webscout/litagent/agent.py +492 -455
- webscout/litagent/constants.py +60 -60
- webscout/models.py +505 -181
- webscout/optimizers.py +74 -420
- webscout/prompt_manager.py +376 -288
- webscout/sanitize.py +1514 -0
- webscout/scout/README.md +452 -404
- webscout/scout/__init__.py +8 -8
- webscout/scout/core/__init__.py +7 -7
- webscout/scout/core/crawler.py +330 -210
- webscout/scout/core/scout.py +800 -607
- webscout/scout/core/search_result.py +51 -96
- webscout/scout/core/text_analyzer.py +64 -63
- webscout/scout/core/text_utils.py +412 -277
- webscout/scout/core/web_analyzer.py +54 -52
- webscout/scout/element.py +872 -478
- webscout/scout/parsers/__init__.py +70 -69
- webscout/scout/parsers/html5lib_parser.py +182 -172
- webscout/scout/parsers/html_parser.py +238 -236
- webscout/scout/parsers/lxml_parser.py +203 -178
- webscout/scout/utils.py +38 -37
- webscout/search/__init__.py +47 -0
- webscout/search/base.py +201 -0
- webscout/search/bing_main.py +45 -0
- webscout/search/brave_main.py +92 -0
- webscout/search/duckduckgo_main.py +57 -0
- webscout/search/engines/__init__.py +127 -0
- webscout/search/engines/bing/__init__.py +15 -0
- webscout/search/engines/bing/base.py +35 -0
- webscout/search/engines/bing/images.py +114 -0
- webscout/search/engines/bing/news.py +96 -0
- webscout/search/engines/bing/suggestions.py +36 -0
- webscout/search/engines/bing/text.py +109 -0
- webscout/search/engines/brave/__init__.py +19 -0
- webscout/search/engines/brave/base.py +47 -0
- webscout/search/engines/brave/images.py +213 -0
- webscout/search/engines/brave/news.py +353 -0
- webscout/search/engines/brave/suggestions.py +318 -0
- webscout/search/engines/brave/text.py +167 -0
- webscout/search/engines/brave/videos.py +364 -0
- webscout/search/engines/duckduckgo/__init__.py +25 -0
- webscout/search/engines/duckduckgo/answers.py +80 -0
- webscout/search/engines/duckduckgo/base.py +189 -0
- webscout/search/engines/duckduckgo/images.py +100 -0
- webscout/search/engines/duckduckgo/maps.py +183 -0
- webscout/search/engines/duckduckgo/news.py +70 -0
- webscout/search/engines/duckduckgo/suggestions.py +22 -0
- webscout/search/engines/duckduckgo/text.py +221 -0
- webscout/search/engines/duckduckgo/translate.py +48 -0
- webscout/search/engines/duckduckgo/videos.py +80 -0
- webscout/search/engines/duckduckgo/weather.py +84 -0
- webscout/search/engines/mojeek.py +61 -0
- webscout/search/engines/wikipedia.py +77 -0
- webscout/search/engines/yahoo/__init__.py +41 -0
- webscout/search/engines/yahoo/answers.py +19 -0
- webscout/search/engines/yahoo/base.py +34 -0
- webscout/search/engines/yahoo/images.py +323 -0
- webscout/search/engines/yahoo/maps.py +19 -0
- webscout/search/engines/yahoo/news.py +258 -0
- webscout/search/engines/yahoo/suggestions.py +140 -0
- webscout/search/engines/yahoo/text.py +273 -0
- webscout/search/engines/yahoo/translate.py +19 -0
- webscout/search/engines/yahoo/videos.py +302 -0
- webscout/search/engines/yahoo/weather.py +220 -0
- webscout/search/engines/yandex.py +67 -0
- webscout/search/engines/yep/__init__.py +13 -0
- webscout/search/engines/yep/base.py +34 -0
- webscout/search/engines/yep/images.py +101 -0
- webscout/search/engines/yep/suggestions.py +38 -0
- webscout/search/engines/yep/text.py +99 -0
- webscout/search/http_client.py +172 -0
- webscout/search/results.py +141 -0
- webscout/search/yahoo_main.py +57 -0
- webscout/search/yep_main.py +48 -0
- webscout/server/__init__.py +48 -0
- webscout/server/config.py +78 -0
- webscout/server/exceptions.py +69 -0
- webscout/server/providers.py +286 -0
- webscout/server/request_models.py +131 -0
- webscout/server/request_processing.py +404 -0
- webscout/server/routes.py +642 -0
- webscout/server/server.py +351 -0
- webscout/server/ui_templates.py +1171 -0
- webscout/swiftcli/__init__.py +79 -95
- webscout/swiftcli/core/__init__.py +7 -7
- webscout/swiftcli/core/cli.py +574 -297
- webscout/swiftcli/core/context.py +98 -104
- webscout/swiftcli/core/group.py +268 -241
- webscout/swiftcli/decorators/__init__.py +28 -28
- webscout/swiftcli/decorators/command.py +243 -221
- webscout/swiftcli/decorators/options.py +247 -220
- webscout/swiftcli/decorators/output.py +392 -252
- webscout/swiftcli/exceptions.py +21 -21
- webscout/swiftcli/plugins/__init__.py +9 -9
- webscout/swiftcli/plugins/base.py +134 -135
- webscout/swiftcli/plugins/manager.py +269 -269
- webscout/swiftcli/utils/__init__.py +58 -59
- webscout/swiftcli/utils/formatting.py +251 -252
- webscout/swiftcli/utils/parsing.py +368 -267
- webscout/update_checker.py +280 -136
- webscout/utils.py +28 -14
- webscout/version.py +2 -1
- webscout/version.py.bak +3 -0
- webscout/zeroart/__init__.py +218 -135
- webscout/zeroart/base.py +70 -66
- webscout/zeroart/effects.py +155 -101
- webscout/zeroart/fonts.py +1799 -1239
- webscout-2026.1.19.dist-info/METADATA +638 -0
- webscout-2026.1.19.dist-info/RECORD +312 -0
- {webscout-8.2.9.dist-info → webscout-2026.1.19.dist-info}/WHEEL +1 -1
- {webscout-8.2.9.dist-info → webscout-2026.1.19.dist-info}/entry_points.txt +1 -1
- webscout/DWEBS.py +0 -520
- webscout/Extra/Act.md +0 -309
- webscout/Extra/GitToolkit/gitapi/README.md +0 -110
- webscout/Extra/autocoder/__init__.py +0 -9
- webscout/Extra/autocoder/autocoder.py +0 -1105
- webscout/Extra/autocoder/autocoder_utiles.py +0 -332
- webscout/Extra/gguf.md +0 -430
- webscout/Extra/weather.md +0 -281
- webscout/Litlogger/README.md +0 -10
- webscout/Litlogger/__init__.py +0 -15
- webscout/Litlogger/formats.py +0 -4
- webscout/Litlogger/handlers.py +0 -103
- webscout/Litlogger/levels.py +0 -13
- webscout/Litlogger/logger.py +0 -92
- webscout/Provider/AI21.py +0 -177
- webscout/Provider/AISEARCH/DeepFind.py +0 -254
- webscout/Provider/AISEARCH/felo_search.py +0 -202
- webscout/Provider/AISEARCH/genspark_search.py +0 -324
- webscout/Provider/AISEARCH/hika_search.py +0 -186
- webscout/Provider/AISEARCH/scira_search.py +0 -298
- webscout/Provider/Aitopia.py +0 -316
- webscout/Provider/AllenAI.py +0 -440
- webscout/Provider/Blackboxai.py +0 -791
- webscout/Provider/ChatGPTClone.py +0 -237
- webscout/Provider/ChatGPTGratis.py +0 -194
- webscout/Provider/Cloudflare.py +0 -324
- webscout/Provider/ExaChat.py +0 -358
- webscout/Provider/Flowith.py +0 -217
- webscout/Provider/FreeGemini.py +0 -250
- webscout/Provider/Glider.py +0 -225
- webscout/Provider/HF_space/__init__.py +0 -0
- webscout/Provider/HF_space/qwen_qwen2.py +0 -206
- webscout/Provider/HuggingFaceChat.py +0 -469
- webscout/Provider/Hunyuan.py +0 -283
- webscout/Provider/LambdaChat.py +0 -411
- webscout/Provider/Llama3.py +0 -259
- webscout/Provider/Nemotron.py +0 -218
- webscout/Provider/OLLAMA.py +0 -396
- webscout/Provider/OPENAI/BLACKBOXAI.py +0 -766
- webscout/Provider/OPENAI/Cloudflare.py +0 -378
- webscout/Provider/OPENAI/FreeGemini.py +0 -283
- webscout/Provider/OPENAI/NEMOTRON.py +0 -232
- webscout/Provider/OPENAI/Qwen3.py +0 -283
- webscout/Provider/OPENAI/api.py +0 -969
- webscout/Provider/OPENAI/c4ai.py +0 -373
- webscout/Provider/OPENAI/chatgptclone.py +0 -494
- webscout/Provider/OPENAI/copilot.py +0 -242
- webscout/Provider/OPENAI/flowith.py +0 -162
- webscout/Provider/OPENAI/freeaichat.py +0 -359
- webscout/Provider/OPENAI/mcpcore.py +0 -389
- webscout/Provider/OPENAI/multichat.py +0 -376
- webscout/Provider/OPENAI/opkfc.py +0 -496
- webscout/Provider/OPENAI/scirachat.py +0 -477
- webscout/Provider/OPENAI/standardinput.py +0 -433
- webscout/Provider/OPENAI/typegpt.py +0 -364
- webscout/Provider/OPENAI/uncovrAI.py +0 -463
- webscout/Provider/OPENAI/venice.py +0 -431
- webscout/Provider/OPENAI/yep.py +0 -382
- webscout/Provider/OpenGPT.py +0 -209
- webscout/Provider/Perplexitylabs.py +0 -415
- webscout/Provider/Reka.py +0 -214
- webscout/Provider/StandardInput.py +0 -290
- webscout/Provider/TTI/aiarta.py +0 -365
- webscout/Provider/TTI/artbit.py +0 -0
- webscout/Provider/TTI/fastflux.py +0 -200
- webscout/Provider/TTI/piclumen.py +0 -203
- webscout/Provider/TTI/pixelmuse.py +0 -225
- webscout/Provider/TTS/gesserit.py +0 -128
- webscout/Provider/TTS/sthir.py +0 -94
- webscout/Provider/TeachAnything.py +0 -229
- webscout/Provider/UNFINISHED/puterjs.py +0 -635
- webscout/Provider/UNFINISHED/test_lmarena.py +0 -119
- webscout/Provider/Venice.py +0 -258
- webscout/Provider/VercelAI.py +0 -253
- webscout/Provider/Writecream.py +0 -246
- webscout/Provider/WritingMate.py +0 -269
- webscout/Provider/asksteve.py +0 -220
- webscout/Provider/chatglm.py +0 -215
- webscout/Provider/copilot.py +0 -425
- webscout/Provider/freeaichat.py +0 -285
- webscout/Provider/granite.py +0 -235
- webscout/Provider/hermes.py +0 -266
- webscout/Provider/koala.py +0 -170
- webscout/Provider/lmarena.py +0 -198
- webscout/Provider/multichat.py +0 -364
- webscout/Provider/scira_chat.py +0 -299
- webscout/Provider/scnet.py +0 -243
- webscout/Provider/talkai.py +0 -194
- webscout/Provider/typegpt.py +0 -289
- webscout/Provider/uncovr.py +0 -368
- webscout/Provider/yep.py +0 -389
- webscout/litagent/Readme.md +0 -276
- webscout/litprinter/__init__.py +0 -59
- webscout/swiftcli/Readme.md +0 -323
- webscout/tempid.py +0 -128
- webscout/webscout_search.py +0 -1184
- webscout/webscout_search_async.py +0 -654
- webscout/yep_search.py +0 -347
- webscout/zeroart/README.md +0 -89
- webscout-8.2.9.dist-info/METADATA +0 -1033
- webscout-8.2.9.dist-info/RECORD +0 -289
- {webscout-8.2.9.dist-info → webscout-2026.1.19.dist-info}/licenses/LICENSE.md +0 -0
- {webscout-8.2.9.dist-info → webscout-2026.1.19.dist-info}/top_level.txt +0 -0
webscout/Provider/Jadve.py
CHANGED
|
@@ -1,291 +1,317 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
from
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
from webscout
|
|
9
|
-
from webscout import
|
|
10
|
-
from webscout.
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
self.
|
|
61
|
-
self.
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
self.
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
"
|
|
73
|
-
"
|
|
74
|
-
"
|
|
75
|
-
"
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
self.
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
1
|
+
import re
|
|
2
|
+
import secrets
|
|
3
|
+
from typing import Any, Dict, Generator, Optional, Union, cast
|
|
4
|
+
|
|
5
|
+
from curl_cffi import CurlError
|
|
6
|
+
from curl_cffi.requests import Session
|
|
7
|
+
|
|
8
|
+
from webscout import exceptions
|
|
9
|
+
from webscout.AIbase import Provider, Response
|
|
10
|
+
from webscout.AIutel import ( # Import sanitize_stream
|
|
11
|
+
AwesomePrompts,
|
|
12
|
+
Conversation,
|
|
13
|
+
Optimizers,
|
|
14
|
+
sanitize_stream,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class JadveOpenAI(Provider):
|
|
19
|
+
"""
|
|
20
|
+
A class to interact with the OpenAI API through jadve.com using the streaming endpoint.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
required_auth = False
|
|
24
|
+
AVAILABLE_MODELS = ["gpt-5-mini", "claude-3-5-haiku-20241022"]
|
|
25
|
+
|
|
26
|
+
def __init__(
|
|
27
|
+
self,
|
|
28
|
+
is_conversation: bool = True,
|
|
29
|
+
max_tokens: int = 600,
|
|
30
|
+
timeout: int = 30,
|
|
31
|
+
intro: Optional[str] = None,
|
|
32
|
+
filepath: Optional[str] = None,
|
|
33
|
+
update_file: bool = True,
|
|
34
|
+
proxies: dict = {},
|
|
35
|
+
history_offset: int = 10250,
|
|
36
|
+
act: Optional[str] = None,
|
|
37
|
+
model: str = "gpt-5-mini",
|
|
38
|
+
system_prompt: str = "You are a helpful AI assistant.", # Note: system_prompt is not used by this API
|
|
39
|
+
):
|
|
40
|
+
"""
|
|
41
|
+
Initializes the JadveOpenAI client.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
is_conversation (bool, optional): Enable conversational mode. Defaults to True.
|
|
45
|
+
max_tokens (int, optional): Maximum tokens for generation. Defaults to 600.
|
|
46
|
+
timeout (int, optional): HTTP request timeout in seconds. Defaults to 30.
|
|
47
|
+
intro (str, optional): Introductory prompt text. Defaults to None.
|
|
48
|
+
filepath (str, optional): Path to conversation history file. Defaults to None.
|
|
49
|
+
update_file (bool, optional): Whether to update the conversation history file. Defaults to True.
|
|
50
|
+
proxies (dict, optional): Proxies for HTTP requests. Defaults to {}.
|
|
51
|
+
history_offset (int, optional): Limit for conversation history. Defaults to 10250.
|
|
52
|
+
act (str|int, optional): Act key for AwesomePrompts. Defaults to None.
|
|
53
|
+
model (str, optional): AI model to be used. Defaults to "gpt-4o-mini".
|
|
54
|
+
system_prompt (str, optional): System prompt text. Defaults to "You are a helpful AI assistant."
|
|
55
|
+
"""
|
|
56
|
+
if model not in self.AVAILABLE_MODELS:
|
|
57
|
+
raise ValueError(f"Invalid model: {model}. Choose from: {self.AVAILABLE_MODELS}")
|
|
58
|
+
|
|
59
|
+
# Initialize curl_cffi Session
|
|
60
|
+
self.session = Session()
|
|
61
|
+
self.is_conversation = is_conversation
|
|
62
|
+
self.max_tokens_to_sample = max_tokens
|
|
63
|
+
self.api_endpoint = "https://ai-api.jadve.com/api/chat"
|
|
64
|
+
self.stream_chunk_size = 64
|
|
65
|
+
self.timeout = timeout
|
|
66
|
+
self.last_response = {}
|
|
67
|
+
self.model = model
|
|
68
|
+
self.system_prompt = system_prompt
|
|
69
|
+
|
|
70
|
+
# Headers for API requests
|
|
71
|
+
self.headers = {
|
|
72
|
+
"accept": "*/*",
|
|
73
|
+
"accept-language": "en-US,en;q=0.9,en-IN;q=0.8",
|
|
74
|
+
"content-type": "application/json",
|
|
75
|
+
"dnt": "1",
|
|
76
|
+
"origin": "https://jadve.com",
|
|
77
|
+
"priority": "u=1, i",
|
|
78
|
+
"referer": "https://jadve.com/",
|
|
79
|
+
"sec-fetch-dest": "empty",
|
|
80
|
+
"sec-fetch-mode": "cors",
|
|
81
|
+
"sec-fetch-site": "same-site",
|
|
82
|
+
"sec-ch-ua": '"Chromium";v="140", "Not=A?Brand";v="24", "Microsoft Edge";v="140"',
|
|
83
|
+
"sec-ch-ua-mobile": "?0",
|
|
84
|
+
"sec-ch-ua-platform": '"Windows"',
|
|
85
|
+
"sec-gpc": "1",
|
|
86
|
+
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0",
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
# Update curl_cffi session headers and proxies
|
|
90
|
+
self.session = Session()
|
|
91
|
+
self.session.headers.update(self.headers)
|
|
92
|
+
if proxies:
|
|
93
|
+
self.session.proxies.update(proxies)
|
|
94
|
+
|
|
95
|
+
self.__available_optimizers = (
|
|
96
|
+
method
|
|
97
|
+
for method in dir(Optimizers)
|
|
98
|
+
if callable(getattr(Optimizers, method)) and not method.startswith("__")
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
self.conversation = Conversation(
|
|
102
|
+
is_conversation, self.max_tokens_to_sample, filepath, update_file
|
|
103
|
+
)
|
|
104
|
+
self.conversation.history_offset = history_offset
|
|
105
|
+
|
|
106
|
+
if act:
|
|
107
|
+
self.conversation.intro = (
|
|
108
|
+
AwesomePrompts().get_act(
|
|
109
|
+
cast(Union[str, int], act),
|
|
110
|
+
default=self.conversation.intro,
|
|
111
|
+
case_insensitive=True,
|
|
112
|
+
)
|
|
113
|
+
or self.conversation.intro
|
|
114
|
+
)
|
|
115
|
+
elif intro:
|
|
116
|
+
self.conversation.intro = intro
|
|
117
|
+
|
|
118
|
+
@staticmethod
|
|
119
|
+
def _jadve_extractor(chunk: Union[str, Dict[str, Any]]) -> Optional[str]:
|
|
120
|
+
"""Extracts content from the Jadve stream format '0:"..."'."""
|
|
121
|
+
if isinstance(chunk, str):
|
|
122
|
+
match = re.search(
|
|
123
|
+
r'0:"(.*?)"(?=,|$)', chunk
|
|
124
|
+
) # Look for 0:"...", possibly followed by comma or end of string
|
|
125
|
+
if match:
|
|
126
|
+
# Decode potential unicode escapes like \u00e9 and handle escaped quotes/backslashes
|
|
127
|
+
content = match.group(1).encode().decode("unicode_escape")
|
|
128
|
+
return content.replace("\\\\", "\\").replace('\\"', '"')
|
|
129
|
+
return None
|
|
130
|
+
|
|
131
|
+
def ask(
|
|
132
|
+
self,
|
|
133
|
+
prompt: str,
|
|
134
|
+
stream: bool = False,
|
|
135
|
+
raw: bool = False,
|
|
136
|
+
optimizer: Optional[str] = None,
|
|
137
|
+
conversationally: bool = False,
|
|
138
|
+
**kwargs: Any,
|
|
139
|
+
) -> Response:
|
|
140
|
+
"""
|
|
141
|
+
Chat with AI.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
prompt (str): Prompt to be sent.
|
|
145
|
+
stream (bool, optional): Flag for streaming response. Defaults to False.
|
|
146
|
+
raw (bool, optional): Return raw content chunks. Defaults to False.
|
|
147
|
+
optimizer (str, optional): Prompt optimizer name. Defaults to None.
|
|
148
|
+
conversationally (bool, optional): Flag for conversational optimization. Defaults to False.
|
|
149
|
+
Returns:
|
|
150
|
+
dict or generator: A dictionary with the generated text or a generator yielding text chunks.
|
|
151
|
+
"""
|
|
152
|
+
conversation_prompt = self.conversation.gen_complete_prompt(prompt)
|
|
153
|
+
if optimizer:
|
|
154
|
+
if optimizer in self.__available_optimizers:
|
|
155
|
+
conversation_prompt = getattr(Optimizers, optimizer)(
|
|
156
|
+
conversation_prompt if conversationally else prompt
|
|
157
|
+
)
|
|
158
|
+
else:
|
|
159
|
+
raise Exception(f"Optimizer is not one of {list(self.__available_optimizers)}")
|
|
160
|
+
|
|
161
|
+
payload = {
|
|
162
|
+
"id": secrets.token_hex(8),
|
|
163
|
+
"messages": [
|
|
164
|
+
{"role": "user", "content": [{"type": "text", "text": conversation_prompt}]}
|
|
165
|
+
],
|
|
166
|
+
"model": self.model,
|
|
167
|
+
"botId": "",
|
|
168
|
+
"chatId": "",
|
|
169
|
+
"stream": True,
|
|
170
|
+
"returnTokensUsage": True,
|
|
171
|
+
"useTools": False,
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
def for_stream():
|
|
175
|
+
full_response_text = "" # Initialize outside try block
|
|
176
|
+
try:
|
|
177
|
+
# Use curl_cffi session post with impersonate
|
|
178
|
+
response = self.session.post(
|
|
179
|
+
self.api_endpoint,
|
|
180
|
+
# headers are set on the session
|
|
181
|
+
json=payload,
|
|
182
|
+
stream=True,
|
|
183
|
+
timeout=self.timeout,
|
|
184
|
+
# proxies are set on the session
|
|
185
|
+
impersonate="chrome120", # Use a common impersonation profile
|
|
186
|
+
)
|
|
187
|
+
response.raise_for_status() # Check for HTTP errors
|
|
188
|
+
|
|
189
|
+
# Use sanitize_stream
|
|
190
|
+
processed_stream = sanitize_stream(
|
|
191
|
+
data=response.iter_content(chunk_size=None), # Pass byte iterator
|
|
192
|
+
intro_value=None, # No simple prefix
|
|
193
|
+
to_json=False, # Content is text after extraction
|
|
194
|
+
content_extractor=self._jadve_extractor, # Use the specific extractor
|
|
195
|
+
yield_raw_on_error=True,
|
|
196
|
+
raw=raw,
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
for content_chunk in processed_stream:
|
|
200
|
+
if raw:
|
|
201
|
+
if content_chunk and isinstance(content_chunk, str):
|
|
202
|
+
full_response_text += content_chunk
|
|
203
|
+
yield content_chunk
|
|
204
|
+
else:
|
|
205
|
+
if content_chunk and isinstance(content_chunk, str):
|
|
206
|
+
full_response_text += content_chunk
|
|
207
|
+
resp = {"text": content_chunk}
|
|
208
|
+
yield resp
|
|
209
|
+
|
|
210
|
+
# Update history after stream finishes
|
|
211
|
+
self.last_response = {"text": full_response_text}
|
|
212
|
+
self.conversation.update_chat_history(prompt, full_response_text)
|
|
213
|
+
|
|
214
|
+
except CurlError as e: # Catch CurlError
|
|
215
|
+
raise exceptions.FailedToGenerateResponseError(
|
|
216
|
+
f"Request failed (CurlError): {e}"
|
|
217
|
+
) from e
|
|
218
|
+
except Exception as e: # Catch other potential exceptions (like HTTPError)
|
|
219
|
+
err_text = ""
|
|
220
|
+
if hasattr(e, "response"):
|
|
221
|
+
response_obj = getattr(e, "response")
|
|
222
|
+
if hasattr(response_obj, "text"):
|
|
223
|
+
err_text = getattr(response_obj, "text")
|
|
224
|
+
raise exceptions.FailedToGenerateResponseError(
|
|
225
|
+
f"Failed to generate response ({type(e).__name__}): {e} - {err_text}"
|
|
226
|
+
) from e
|
|
227
|
+
|
|
228
|
+
def for_non_stream():
|
|
229
|
+
collected_text = ""
|
|
230
|
+
try:
|
|
231
|
+
for chunk_data in for_stream():
|
|
232
|
+
if raw:
|
|
233
|
+
if isinstance(chunk_data, str):
|
|
234
|
+
collected_text += chunk_data
|
|
235
|
+
else:
|
|
236
|
+
if isinstance(chunk_data, dict) and "text" in chunk_data:
|
|
237
|
+
collected_text += chunk_data["text"]
|
|
238
|
+
except Exception as e:
|
|
239
|
+
if not collected_text:
|
|
240
|
+
raise exceptions.FailedToGenerateResponseError(
|
|
241
|
+
f"Failed to get non-stream response: {str(e)}"
|
|
242
|
+
) from e
|
|
243
|
+
# last_response and history are updated within for_stream
|
|
244
|
+
return collected_text if raw else self.last_response
|
|
245
|
+
|
|
246
|
+
return for_stream() if stream else for_non_stream()
|
|
247
|
+
|
|
248
|
+
def chat(
|
|
249
|
+
self,
|
|
250
|
+
prompt: str,
|
|
251
|
+
stream: bool = False,
|
|
252
|
+
optimizer: Optional[str] = None,
|
|
253
|
+
conversationally: bool = False,
|
|
254
|
+
**kwargs: Any,
|
|
255
|
+
) -> Union[str, Generator[str, None, None]]:
|
|
256
|
+
"""
|
|
257
|
+
Generate a chat response (string).
|
|
258
|
+
|
|
259
|
+
Args:
|
|
260
|
+
prompt (str): Prompt to be sent.
|
|
261
|
+
stream (bool, optional): Flag for streaming response. Defaults to False.
|
|
262
|
+
optimizer (str, optional): Prompt optimizer name. Defaults to None.
|
|
263
|
+
conversationally (bool, optional): Flag for conversational optimization. Defaults to False.
|
|
264
|
+
**kwargs: Additional parameters including raw.
|
|
265
|
+
Returns:
|
|
266
|
+
str or generator: Generated response string or generator yielding response chunks.
|
|
267
|
+
"""
|
|
268
|
+
raw = kwargs.get("raw", False)
|
|
269
|
+
|
|
270
|
+
def for_stream_chat():
|
|
271
|
+
gen = self.ask(
|
|
272
|
+
prompt, stream=True, raw=raw, optimizer=optimizer, conversationally=conversationally
|
|
273
|
+
)
|
|
274
|
+
for response in gen:
|
|
275
|
+
if raw:
|
|
276
|
+
yield response
|
|
277
|
+
else:
|
|
278
|
+
yield self.get_message(response)
|
|
279
|
+
|
|
280
|
+
def for_non_stream_chat():
|
|
281
|
+
response_data = self.ask(
|
|
282
|
+
prompt,
|
|
283
|
+
stream=False,
|
|
284
|
+
raw=raw,
|
|
285
|
+
optimizer=optimizer,
|
|
286
|
+
conversationally=conversationally,
|
|
287
|
+
)
|
|
288
|
+
if raw:
|
|
289
|
+
return response_data if isinstance(response_data, str) else str(response_data)
|
|
290
|
+
return self.get_message(response_data)
|
|
291
|
+
|
|
292
|
+
return for_stream_chat() if stream else for_non_stream_chat()
|
|
293
|
+
|
|
294
|
+
def get_message(self, response: Response) -> str:
|
|
295
|
+
"""
|
|
296
|
+
Retrieves message from the response.
|
|
297
|
+
|
|
298
|
+
Args:
|
|
299
|
+
response (Response): Response from the ask() method.
|
|
300
|
+
Returns:
|
|
301
|
+
str: Extracted text.
|
|
302
|
+
"""
|
|
303
|
+
if not isinstance(response, dict):
|
|
304
|
+
return str(response)
|
|
305
|
+
# Extractor handles formatting
|
|
306
|
+
return cast(Dict[str, Any], response).get("text", "")
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
if __name__ == "__main__":
|
|
310
|
+
for model in JadveOpenAI.AVAILABLE_MODELS:
|
|
311
|
+
ai = JadveOpenAI(model=model)
|
|
312
|
+
response = ai.chat("hi")
|
|
313
|
+
print(f"Model: {model}")
|
|
314
|
+
print(response)
|
|
315
|
+
print("-" * 50)
|
|
316
|
+
# for chunk in response:
|
|
317
|
+
# print(chunk, end="", flush=True)
|