webscout 8.2.2__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 -143
- webscout/AIbase.py +247 -123
- webscout/AIutel.py +68 -132
- webscout/Bard.py +1072 -535
- webscout/Extra/GitToolkit/__init__.py +2 -2
- 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 -0
- 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 -0
- 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 -45
- 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 +189 -18
- webscout/Extra/__init__.py +2 -3
- webscout/Extra/gguf.py +1298 -682
- webscout/Extra/tempmail/README.md +488 -0
- 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 +237 -304
- webscout/Provider/AISEARCH/README.md +106 -0
- webscout/Provider/AISEARCH/__init__.py +16 -10
- webscout/Provider/AISEARCH/brave_search.py +298 -0
- webscout/Provider/AISEARCH/iask_search.py +130 -209
- webscout/Provider/AISEARCH/monica_search.py +200 -246
- webscout/Provider/AISEARCH/webpilotai_search.py +242 -281
- 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 -0
- webscout/Provider/ClaudeOnline.py +365 -0
- webscout/Provider/Cohere.py +232 -208
- webscout/Provider/DeepAI.py +367 -0
- webscout/Provider/Deepinfra.py +343 -173
- webscout/Provider/EssentialAI.py +217 -0
- webscout/Provider/ExaAI.py +274 -261
- webscout/Provider/Gemini.py +60 -54
- webscout/Provider/GithubChat.py +385 -367
- webscout/Provider/Gradient.py +286 -0
- webscout/Provider/Groq.py +556 -670
- webscout/Provider/HadadXYZ.py +323 -0
- webscout/Provider/HeckAI.py +392 -233
- webscout/Provider/HuggingFace.py +387 -0
- webscout/Provider/IBM.py +340 -0
- webscout/Provider/Jadve.py +317 -266
- webscout/Provider/K2Think.py +306 -0
- webscout/Provider/Koboldai.py +221 -381
- webscout/Provider/Netwrck.py +273 -228
- 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 -0
- webscout/Provider/OPENAI/TogetherAI.py +405 -0
- webscout/Provider/OPENAI/TwoAI.py +255 -0
- webscout/Provider/OPENAI/__init__.py +148 -25
- webscout/Provider/OPENAI/ai4chat.py +348 -0
- webscout/Provider/OPENAI/akashgpt.py +436 -0
- webscout/Provider/OPENAI/algion.py +303 -0
- webscout/Provider/OPENAI/ayle.py +365 -0
- webscout/Provider/OPENAI/base.py +253 -46
- webscout/Provider/OPENAI/cerebras.py +296 -0
- webscout/Provider/OPENAI/chatgpt.py +514 -193
- webscout/Provider/OPENAI/chatsandbox.py +233 -0
- webscout/Provider/OPENAI/deepinfra.py +403 -272
- webscout/Provider/OPENAI/e2b.py +2370 -1350
- webscout/Provider/OPENAI/elmo.py +278 -0
- webscout/Provider/OPENAI/exaai.py +186 -138
- webscout/Provider/OPENAI/freeassist.py +446 -0
- webscout/Provider/OPENAI/gradient.py +448 -0
- webscout/Provider/OPENAI/groq.py +380 -0
- webscout/Provider/OPENAI/hadadxyz.py +292 -0
- webscout/Provider/OPENAI/heckai.py +100 -104
- 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 -327
- webscout/Provider/OPENAI/meta.py +541 -0
- webscout/Provider/OPENAI/netwrck.py +110 -84
- webscout/Provider/OPENAI/nvidia.py +317 -0
- webscout/Provider/OPENAI/oivscode.py +348 -0
- webscout/Provider/OPENAI/openrouter.py +328 -0
- webscout/Provider/OPENAI/pydantic_imports.py +1 -0
- webscout/Provider/OPENAI/sambanova.py +397 -0
- webscout/Provider/OPENAI/sonus.py +126 -115
- webscout/Provider/OPENAI/textpollinations.py +218 -133
- webscout/Provider/OPENAI/toolbaz.py +136 -166
- webscout/Provider/OPENAI/typefully.py +419 -0
- webscout/Provider/OPENAI/typliai.py +279 -0
- webscout/Provider/OPENAI/utils.py +314 -211
- webscout/Provider/OPENAI/wisecat.py +103 -125
- webscout/Provider/OPENAI/writecream.py +185 -156
- webscout/Provider/OPENAI/x0gpt.py +227 -136
- webscout/Provider/OPENAI/zenmux.py +380 -0
- webscout/Provider/OpenRouter.py +386 -0
- webscout/Provider/Openai.py +337 -496
- webscout/Provider/PI.py +443 -344
- 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 -0
- webscout/Provider/TTI/__init__.py +37 -12
- webscout/Provider/TTI/base.py +147 -0
- webscout/Provider/TTI/claudeonline.py +393 -0
- webscout/Provider/TTI/magicstudio.py +292 -0
- webscout/Provider/TTI/miragic.py +180 -0
- webscout/Provider/TTI/pollinations.py +331 -0
- webscout/Provider/TTI/together.py +334 -0
- webscout/Provider/TTI/utils.py +14 -0
- webscout/Provider/TTS/README.md +186 -0
- webscout/Provider/TTS/__init__.py +43 -7
- webscout/Provider/TTS/base.py +523 -0
- 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 -0
- 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 -180
- webscout/Provider/TTS/streamElements.py +275 -333
- webscout/Provider/TTS/utils.py +280 -280
- webscout/Provider/TextPollinationsAI.py +221 -121
- webscout/Provider/TogetherAI.py +450 -0
- webscout/Provider/TwoAI.py +309 -199
- webscout/Provider/TypliAI.py +311 -0
- webscout/Provider/UNFINISHED/ChatHub.py +219 -0
- webscout/Provider/{OPENAI/glider.py → UNFINISHED/ChutesAI.py} +160 -145
- webscout/Provider/UNFINISHED/GizAI.py +300 -0
- webscout/Provider/UNFINISHED/Marcus.py +218 -0
- webscout/Provider/UNFINISHED/Qodo.py +481 -0
- webscout/Provider/UNFINISHED/XenAI.py +330 -0
- webscout/Provider/{Youchat.py → UNFINISHED/Youchat.py} +64 -47
- 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 -0
- webscout/Provider/UNFINISHED/samurai.py +231 -0
- webscout/Provider/WiseCat.py +256 -196
- webscout/Provider/WrDoChat.py +390 -0
- webscout/Provider/__init__.py +115 -198
- webscout/Provider/ai4chat.py +181 -202
- webscout/Provider/akashgpt.py +330 -342
- webscout/Provider/cerebras.py +397 -242
- webscout/Provider/cleeai.py +236 -213
- webscout/Provider/elmo.py +291 -234
- webscout/Provider/geminiapi.py +343 -208
- webscout/Provider/julius.py +245 -223
- webscout/Provider/learnfastai.py +333 -266
- webscout/Provider/llama3mitril.py +230 -180
- webscout/Provider/llmchat.py +308 -213
- webscout/Provider/llmchatco.py +321 -311
- webscout/Provider/meta.py +996 -794
- webscout/Provider/oivscode.py +332 -0
- webscout/Provider/searchchat.py +316 -293
- webscout/Provider/sonus.py +264 -208
- webscout/Provider/toolbaz.py +359 -320
- webscout/Provider/turboseek.py +332 -219
- webscout/Provider/typefully.py +262 -280
- webscout/Provider/x0gpt.py +332 -256
- webscout/__init__.py +31 -38
- webscout/__main__.py +5 -5
- webscout/cli.py +585 -293
- webscout/client.py +1497 -0
- webscout/conversation.py +140 -565
- webscout/exceptions.py +383 -339
- 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 +32 -378
- webscout/prompt_manager.py +376 -274
- webscout/sanitize.py +1514 -0
- webscout/scout/README.md +452 -0
- webscout/scout/__init__.py +8 -8
- webscout/scout/core/__init__.py +7 -7
- webscout/scout/core/crawler.py +330 -140
- webscout/scout/core/scout.py +800 -568
- 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 -460
- 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 -809
- webscout/swiftcli/core/__init__.py +7 -0
- webscout/swiftcli/core/cli.py +574 -0
- webscout/swiftcli/core/context.py +98 -0
- webscout/swiftcli/core/group.py +268 -0
- webscout/swiftcli/decorators/__init__.py +28 -0
- webscout/swiftcli/decorators/command.py +243 -0
- webscout/swiftcli/decorators/options.py +247 -0
- webscout/swiftcli/decorators/output.py +392 -0
- webscout/swiftcli/exceptions.py +21 -0
- webscout/swiftcli/plugins/__init__.py +9 -0
- webscout/swiftcli/plugins/base.py +134 -0
- webscout/swiftcli/plugins/manager.py +269 -0
- webscout/swiftcli/utils/__init__.py +58 -0
- webscout/swiftcli/utils/formatting.py +251 -0
- webscout/swiftcli/utils/parsing.py +368 -0
- 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 -55
- webscout/zeroart/base.py +70 -60
- webscout/zeroart/effects.py +155 -99
- webscout/zeroart/fonts.py +1799 -816
- webscout-2026.1.19.dist-info/METADATA +638 -0
- webscout-2026.1.19.dist-info/RECORD +312 -0
- {webscout-8.2.2.dist-info → webscout-2026.1.19.dist-info}/WHEEL +1 -1
- webscout-2026.1.19.dist-info/entry_points.txt +4 -0
- webscout-2026.1.19.dist-info/top_level.txt +1 -0
- inferno/__init__.py +0 -6
- inferno/__main__.py +0 -9
- inferno/cli.py +0 -6
- webscout/DWEBS.py +0 -477
- webscout/Extra/autocoder/__init__.py +0 -9
- webscout/Extra/autocoder/autocoder.py +0 -849
- webscout/Extra/autocoder/autocoder_utiles.py +0 -332
- webscout/LLM.py +0 -442
- webscout/Litlogger/__init__.py +0 -67
- webscout/Litlogger/core/__init__.py +0 -6
- webscout/Litlogger/core/level.py +0 -23
- webscout/Litlogger/core/logger.py +0 -165
- webscout/Litlogger/handlers/__init__.py +0 -12
- webscout/Litlogger/handlers/console.py +0 -33
- webscout/Litlogger/handlers/file.py +0 -143
- webscout/Litlogger/handlers/network.py +0 -173
- webscout/Litlogger/styles/__init__.py +0 -7
- webscout/Litlogger/styles/colors.py +0 -249
- webscout/Litlogger/styles/formats.py +0 -458
- webscout/Litlogger/styles/text.py +0 -87
- webscout/Litlogger/utils/__init__.py +0 -6
- webscout/Litlogger/utils/detectors.py +0 -153
- webscout/Litlogger/utils/formatters.py +0 -200
- webscout/Local/__init__.py +0 -12
- webscout/Local/__main__.py +0 -9
- webscout/Local/api.py +0 -576
- webscout/Local/cli.py +0 -516
- webscout/Local/config.py +0 -75
- webscout/Local/llm.py +0 -287
- webscout/Local/model_manager.py +0 -253
- webscout/Local/server.py +0 -721
- webscout/Local/utils.py +0 -93
- webscout/Provider/AI21.py +0 -177
- webscout/Provider/AISEARCH/DeepFind.py +0 -250
- webscout/Provider/AISEARCH/ISou.py +0 -256
- webscout/Provider/AISEARCH/felo_search.py +0 -228
- webscout/Provider/AISEARCH/genspark_search.py +0 -208
- webscout/Provider/AISEARCH/hika_search.py +0 -194
- webscout/Provider/AISEARCH/scira_search.py +0 -324
- webscout/Provider/Aitopia.py +0 -292
- webscout/Provider/AllenAI.py +0 -413
- webscout/Provider/Blackboxai.py +0 -229
- webscout/Provider/C4ai.py +0 -432
- webscout/Provider/ChatGPTClone.py +0 -226
- webscout/Provider/ChatGPTES.py +0 -237
- webscout/Provider/ChatGPTGratis.py +0 -194
- webscout/Provider/Chatify.py +0 -175
- webscout/Provider/Cloudflare.py +0 -273
- webscout/Provider/DeepSeek.py +0 -196
- webscout/Provider/ElectronHub.py +0 -709
- webscout/Provider/ExaChat.py +0 -342
- webscout/Provider/Free2GPT.py +0 -241
- webscout/Provider/GPTWeb.py +0 -193
- webscout/Provider/Glider.py +0 -211
- webscout/Provider/HF_space/__init__.py +0 -0
- webscout/Provider/HF_space/qwen_qwen2.py +0 -206
- webscout/Provider/HuggingFaceChat.py +0 -462
- webscout/Provider/Hunyuan.py +0 -272
- webscout/Provider/LambdaChat.py +0 -392
- webscout/Provider/Llama.py +0 -200
- webscout/Provider/Llama3.py +0 -204
- webscout/Provider/Marcus.py +0 -148
- webscout/Provider/OLLAMA.py +0 -396
- webscout/Provider/OPENAI/c4ai.py +0 -367
- webscout/Provider/OPENAI/chatgptclone.py +0 -460
- webscout/Provider/OPENAI/exachat.py +0 -433
- webscout/Provider/OPENAI/freeaichat.py +0 -352
- webscout/Provider/OPENAI/opkfc.py +0 -488
- webscout/Provider/OPENAI/scirachat.py +0 -463
- webscout/Provider/OPENAI/standardinput.py +0 -425
- webscout/Provider/OPENAI/typegpt.py +0 -346
- webscout/Provider/OPENAI/uncovrAI.py +0 -455
- webscout/Provider/OPENAI/venice.py +0 -413
- webscout/Provider/OPENAI/yep.py +0 -327
- webscout/Provider/OpenGPT.py +0 -199
- webscout/Provider/Perplexitylabs.py +0 -415
- webscout/Provider/Phind.py +0 -535
- webscout/Provider/PizzaGPT.py +0 -198
- webscout/Provider/Reka.py +0 -214
- webscout/Provider/StandardInput.py +0 -278
- webscout/Provider/TTI/AiForce/__init__.py +0 -22
- webscout/Provider/TTI/AiForce/async_aiforce.py +0 -224
- webscout/Provider/TTI/AiForce/sync_aiforce.py +0 -245
- webscout/Provider/TTI/FreeAIPlayground/__init__.py +0 -9
- webscout/Provider/TTI/FreeAIPlayground/async_freeaiplayground.py +0 -181
- webscout/Provider/TTI/FreeAIPlayground/sync_freeaiplayground.py +0 -180
- webscout/Provider/TTI/ImgSys/__init__.py +0 -23
- webscout/Provider/TTI/ImgSys/async_imgsys.py +0 -202
- webscout/Provider/TTI/ImgSys/sync_imgsys.py +0 -195
- webscout/Provider/TTI/MagicStudio/__init__.py +0 -2
- webscout/Provider/TTI/MagicStudio/async_magicstudio.py +0 -111
- webscout/Provider/TTI/MagicStudio/sync_magicstudio.py +0 -109
- webscout/Provider/TTI/Nexra/__init__.py +0 -22
- webscout/Provider/TTI/Nexra/async_nexra.py +0 -286
- webscout/Provider/TTI/Nexra/sync_nexra.py +0 -258
- webscout/Provider/TTI/PollinationsAI/__init__.py +0 -23
- webscout/Provider/TTI/PollinationsAI/async_pollinations.py +0 -311
- webscout/Provider/TTI/PollinationsAI/sync_pollinations.py +0 -265
- webscout/Provider/TTI/aiarta/__init__.py +0 -2
- webscout/Provider/TTI/aiarta/async_aiarta.py +0 -482
- webscout/Provider/TTI/aiarta/sync_aiarta.py +0 -440
- webscout/Provider/TTI/artbit/__init__.py +0 -22
- webscout/Provider/TTI/artbit/async_artbit.py +0 -155
- webscout/Provider/TTI/artbit/sync_artbit.py +0 -148
- webscout/Provider/TTI/fastflux/__init__.py +0 -22
- webscout/Provider/TTI/fastflux/async_fastflux.py +0 -261
- webscout/Provider/TTI/fastflux/sync_fastflux.py +0 -252
- webscout/Provider/TTI/huggingface/__init__.py +0 -22
- webscout/Provider/TTI/huggingface/async_huggingface.py +0 -199
- webscout/Provider/TTI/huggingface/sync_huggingface.py +0 -195
- webscout/Provider/TTI/piclumen/__init__.py +0 -23
- webscout/Provider/TTI/piclumen/async_piclumen.py +0 -268
- webscout/Provider/TTI/piclumen/sync_piclumen.py +0 -233
- webscout/Provider/TTI/pixelmuse/__init__.py +0 -4
- webscout/Provider/TTI/pixelmuse/async_pixelmuse.py +0 -249
- webscout/Provider/TTI/pixelmuse/sync_pixelmuse.py +0 -182
- webscout/Provider/TTI/talkai/__init__.py +0 -4
- webscout/Provider/TTI/talkai/async_talkai.py +0 -229
- webscout/Provider/TTI/talkai/sync_talkai.py +0 -207
- webscout/Provider/TTS/gesserit.py +0 -127
- webscout/Provider/TeachAnything.py +0 -187
- webscout/Provider/Venice.py +0 -219
- webscout/Provider/VercelAI.py +0 -234
- webscout/Provider/WebSim.py +0 -228
- webscout/Provider/Writecream.py +0 -211
- webscout/Provider/WritingMate.py +0 -197
- webscout/Provider/aimathgpt.py +0 -189
- webscout/Provider/askmyai.py +0 -158
- webscout/Provider/asksteve.py +0 -203
- webscout/Provider/bagoodex.py +0 -145
- webscout/Provider/chatglm.py +0 -205
- webscout/Provider/copilot.py +0 -428
- webscout/Provider/freeaichat.py +0 -271
- webscout/Provider/gaurish.py +0 -244
- webscout/Provider/geminiprorealtime.py +0 -160
- webscout/Provider/granite.py +0 -187
- webscout/Provider/hermes.py +0 -219
- webscout/Provider/koala.py +0 -268
- webscout/Provider/labyrinth.py +0 -340
- webscout/Provider/lepton.py +0 -194
- webscout/Provider/llamatutor.py +0 -192
- webscout/Provider/multichat.py +0 -325
- webscout/Provider/promptrefine.py +0 -193
- webscout/Provider/scira_chat.py +0 -277
- webscout/Provider/scnet.py +0 -187
- webscout/Provider/talkai.py +0 -194
- webscout/Provider/tutorai.py +0 -252
- webscout/Provider/typegpt.py +0 -232
- webscout/Provider/uncovr.py +0 -312
- webscout/Provider/yep.py +0 -376
- webscout/litprinter/__init__.py +0 -59
- webscout/scout/core.py +0 -881
- webscout/tempid.py +0 -128
- webscout/webscout_search.py +0 -1346
- webscout/webscout_search_async.py +0 -877
- webscout/yep_search.py +0 -297
- webscout-8.2.2.dist-info/METADATA +0 -734
- webscout-8.2.2.dist-info/RECORD +0 -309
- webscout-8.2.2.dist-info/entry_points.txt +0 -5
- webscout-8.2.2.dist-info/top_level.txt +0 -3
- webstoken/__init__.py +0 -30
- webstoken/classifier.py +0 -189
- webstoken/keywords.py +0 -216
- webstoken/language.py +0 -128
- webstoken/ner.py +0 -164
- webstoken/normalizer.py +0 -35
- webstoken/processor.py +0 -77
- webstoken/sentiment.py +0 -206
- webstoken/stemmer.py +0 -73
- webstoken/tagger.py +0 -60
- webstoken/tokenizer.py +0 -158
- {webscout-8.2.2.dist-info → webscout-2026.1.19.dist-info/licenses}/LICENSE.md +0 -0
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from typing import Any, Dict, Generator, List, Optional, Union, cast
|
|
3
|
+
|
|
4
|
+
from curl_cffi import CurlError
|
|
5
|
+
from curl_cffi.requests import Session
|
|
6
|
+
|
|
7
|
+
from webscout import exceptions
|
|
8
|
+
from webscout.AIbase import Provider, Response
|
|
9
|
+
from webscout.AIutel import AwesomePrompts, Conversation, Optimizers, sanitize_stream
|
|
10
|
+
from webscout.litagent import LitAgent as Lit
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Sambanova(Provider):
|
|
14
|
+
"""
|
|
15
|
+
A class to interact with the Sambanova API.
|
|
16
|
+
"""
|
|
17
|
+
required_auth = True
|
|
18
|
+
AVAILABLE_MODELS = [
|
|
19
|
+
"DeepSeek-R1",
|
|
20
|
+
"DeepSeek-V3",
|
|
21
|
+
"Meta-Llama-3.3-70B-Instruct",
|
|
22
|
+
"Meta-Llama-3.1-8B-Instruct",
|
|
23
|
+
"Meta-Llama-3.1-70B-Instruct",
|
|
24
|
+
"Meta-Llama-3.1-405B-Instruct",
|
|
25
|
+
"Qwen2.5-72B-Instruct",
|
|
26
|
+
"Qwen2.5-Coder-32B-Instruct"
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
def update_available_models(self):
|
|
30
|
+
"""Update the available models list from Sambanova API."""
|
|
31
|
+
if not self.api_key:
|
|
32
|
+
return
|
|
33
|
+
|
|
34
|
+
try:
|
|
35
|
+
temp_session = Session()
|
|
36
|
+
headers = {
|
|
37
|
+
"Content-Type": "application/json",
|
|
38
|
+
"Authorization": f"Bearer {self.api_key}",
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
response = temp_session.get(
|
|
42
|
+
"https://api.sambanova.ai/v1/models",
|
|
43
|
+
headers=headers,
|
|
44
|
+
impersonate="chrome120"
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
if response.status_code == 200:
|
|
48
|
+
data = response.json()
|
|
49
|
+
if "data" in data and isinstance(data["data"], list):
|
|
50
|
+
new_models = [model['id'] for model in data['data'] if 'id' in model]
|
|
51
|
+
if new_models:
|
|
52
|
+
self.AVAILABLE_MODELS = new_models
|
|
53
|
+
|
|
54
|
+
except Exception:
|
|
55
|
+
pass
|
|
56
|
+
|
|
57
|
+
def __init__(
|
|
58
|
+
self,
|
|
59
|
+
api_key: Optional[str] = None,
|
|
60
|
+
is_conversation: bool = True,
|
|
61
|
+
max_tokens: int = 4096,
|
|
62
|
+
timeout: int = 30,
|
|
63
|
+
intro: Optional[str] = None,
|
|
64
|
+
filepath: Optional[str] = None,
|
|
65
|
+
update_file: bool = True,
|
|
66
|
+
proxies: dict = {},
|
|
67
|
+
history_offset: int = 10250,
|
|
68
|
+
act: Optional[str] = None,
|
|
69
|
+
model: str = "Meta-Llama-3.1-8B-Instruct",
|
|
70
|
+
system_prompt: str = "You are a helpful AI assistant.",
|
|
71
|
+
):
|
|
72
|
+
"""
|
|
73
|
+
Initializes the Sambanova API with given parameters.
|
|
74
|
+
"""
|
|
75
|
+
self.api_key = api_key
|
|
76
|
+
self.model = model
|
|
77
|
+
self.system_prompt = system_prompt
|
|
78
|
+
self.timeout = timeout
|
|
79
|
+
|
|
80
|
+
# Update models list dynamically if API key is provided
|
|
81
|
+
if api_key:
|
|
82
|
+
self.update_available_models()
|
|
83
|
+
|
|
84
|
+
# Initialize curl_cffi Session
|
|
85
|
+
self.session = Session()
|
|
86
|
+
self.is_conversation = is_conversation
|
|
87
|
+
self.max_tokens_to_sample = max_tokens
|
|
88
|
+
self.last_response = {}
|
|
89
|
+
|
|
90
|
+
self.headers = {
|
|
91
|
+
"Authorization": f"Bearer {self.api_key}",
|
|
92
|
+
"Content-Type": "application/json",
|
|
93
|
+
"User-Agent": Lit().random(),
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
# Update curl_cffi session headers and proxies
|
|
97
|
+
self.session = Session()
|
|
98
|
+
self.session.headers.update(self.headers)
|
|
99
|
+
if proxies:
|
|
100
|
+
self.session.proxies.update(proxies)
|
|
101
|
+
self.system_prompt = system_prompt
|
|
102
|
+
|
|
103
|
+
self.__available_optimizers = (
|
|
104
|
+
method
|
|
105
|
+
for method in dir(Optimizers)
|
|
106
|
+
if callable(getattr(Optimizers, method)) and not method.startswith("__")
|
|
107
|
+
)
|
|
108
|
+
self.conversation = Conversation(
|
|
109
|
+
is_conversation, self.max_tokens_to_sample, filepath, update_file
|
|
110
|
+
)
|
|
111
|
+
self.conversation.history_offset = history_offset
|
|
112
|
+
|
|
113
|
+
if act:
|
|
114
|
+
self.conversation.intro = AwesomePrompts().get_act(cast(Union[str, int], act), default=self.conversation.intro, case_insensitive=True
|
|
115
|
+
) or self.conversation.intro
|
|
116
|
+
elif intro:
|
|
117
|
+
self.conversation.intro = intro
|
|
118
|
+
|
|
119
|
+
# Configure the API base URL
|
|
120
|
+
self.base_url = "https://api.sambanova.ai/v1/chat/completions"
|
|
121
|
+
|
|
122
|
+
def ask(
|
|
123
|
+
self,
|
|
124
|
+
prompt: str,
|
|
125
|
+
stream: bool = False,
|
|
126
|
+
raw: bool = False,
|
|
127
|
+
optimizer: Optional[str] = None,
|
|
128
|
+
conversationally: bool = False,
|
|
129
|
+
tools: Optional[List[Dict[str, Any]]] = None,
|
|
130
|
+
tool_choice: Optional[Dict[str, Any]] = None,
|
|
131
|
+
**kwargs: Any,
|
|
132
|
+
) -> Response:
|
|
133
|
+
"""Chat with AI using the Sambanova API."""
|
|
134
|
+
conversation_prompt = self.conversation.gen_complete_prompt(prompt)
|
|
135
|
+
if optimizer:
|
|
136
|
+
if optimizer in self.__available_optimizers:
|
|
137
|
+
conversation_prompt = getattr(Optimizers, optimizer)(
|
|
138
|
+
conversation_prompt if conversationally else prompt
|
|
139
|
+
)
|
|
140
|
+
else:
|
|
141
|
+
raise Exception(
|
|
142
|
+
f"Optimizer is not one of {list(self.__available_optimizers)}"
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
payload = {
|
|
146
|
+
"model": self.model,
|
|
147
|
+
"messages": [
|
|
148
|
+
{"role": "system", "content": self.system_prompt},
|
|
149
|
+
{"role": "user", "content": conversation_prompt},
|
|
150
|
+
],
|
|
151
|
+
"max_tokens": self.max_tokens_to_sample,
|
|
152
|
+
"stream": stream
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if tools:
|
|
156
|
+
payload["tools"] = tools
|
|
157
|
+
if tool_choice:
|
|
158
|
+
payload["tool_choice"] = tool_choice
|
|
159
|
+
|
|
160
|
+
def for_stream():
|
|
161
|
+
try:
|
|
162
|
+
# Use curl_cffi session post with impersonate
|
|
163
|
+
response = self.session.post(
|
|
164
|
+
self.base_url,
|
|
165
|
+
json=payload,
|
|
166
|
+
stream=True,
|
|
167
|
+
timeout=self.timeout,
|
|
168
|
+
impersonate="chrome120"
|
|
169
|
+
)
|
|
170
|
+
response.raise_for_status()
|
|
171
|
+
|
|
172
|
+
streaming_text = ""
|
|
173
|
+
processed_stream = sanitize_stream(
|
|
174
|
+
data=response.iter_lines(),
|
|
175
|
+
intro_value="data:",
|
|
176
|
+
to_json=True,
|
|
177
|
+
skip_markers=["[DONE]"],
|
|
178
|
+
content_extractor=lambda chunk: chunk.get('choices', [{}])[0].get('delta') if isinstance(chunk, dict) else None,
|
|
179
|
+
yield_raw_on_error=False,
|
|
180
|
+
raw=raw
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
for delta in processed_stream:
|
|
184
|
+
if isinstance(delta, dict):
|
|
185
|
+
if 'content' in delta and delta['content'] is not None:
|
|
186
|
+
content = delta['content']
|
|
187
|
+
if raw:
|
|
188
|
+
yield content
|
|
189
|
+
else:
|
|
190
|
+
streaming_text += content
|
|
191
|
+
yield {"text": content}
|
|
192
|
+
elif 'tool_calls' in delta:
|
|
193
|
+
tool_calls = delta['tool_calls']
|
|
194
|
+
if raw:
|
|
195
|
+
yield json.dumps(tool_calls)
|
|
196
|
+
else:
|
|
197
|
+
yield {"tool_calls": tool_calls}
|
|
198
|
+
|
|
199
|
+
self.last_response.update({"text": streaming_text})
|
|
200
|
+
if streaming_text:
|
|
201
|
+
self.conversation.update_chat_history(prompt, streaming_text)
|
|
202
|
+
|
|
203
|
+
except CurlError as e:
|
|
204
|
+
raise exceptions.ProviderConnectionError(f"Request failed (CurlError): {e}") from e
|
|
205
|
+
except Exception as e:
|
|
206
|
+
raise exceptions.ProviderConnectionError(f"Request failed ({type(e).__name__}): {e}") from e
|
|
207
|
+
|
|
208
|
+
def for_non_stream():
|
|
209
|
+
try:
|
|
210
|
+
payload["stream"] = False
|
|
211
|
+
response = self.session.post(
|
|
212
|
+
self.base_url,
|
|
213
|
+
json=payload,
|
|
214
|
+
timeout=self.timeout,
|
|
215
|
+
impersonate="chrome120"
|
|
216
|
+
)
|
|
217
|
+
response.raise_for_status()
|
|
218
|
+
resp_json = response.json()
|
|
219
|
+
|
|
220
|
+
if 'choices' in resp_json and len(resp_json['choices']) > 0:
|
|
221
|
+
choice = resp_json['choices'][0]
|
|
222
|
+
message = choice.get('message', {})
|
|
223
|
+
content = message.get('content', '')
|
|
224
|
+
tool_calls = message.get('tool_calls')
|
|
225
|
+
|
|
226
|
+
result = {}
|
|
227
|
+
if content:
|
|
228
|
+
result["text"] = content
|
|
229
|
+
if tool_calls:
|
|
230
|
+
result["tool_calls"] = tool_calls
|
|
231
|
+
|
|
232
|
+
self.last_response = result
|
|
233
|
+
self.conversation.update_chat_history(prompt, content or "")
|
|
234
|
+
|
|
235
|
+
if raw:
|
|
236
|
+
return content if content else (json.dumps(tool_calls) if tool_calls else "")
|
|
237
|
+
return result
|
|
238
|
+
else:
|
|
239
|
+
return {}
|
|
240
|
+
|
|
241
|
+
except Exception as e:
|
|
242
|
+
raise exceptions.FailedToGenerateResponseError(f"Non-stream request failed: {e}") from e
|
|
243
|
+
|
|
244
|
+
return for_stream() if stream else for_non_stream()
|
|
245
|
+
|
|
246
|
+
def chat(
|
|
247
|
+
self,
|
|
248
|
+
prompt: str,
|
|
249
|
+
stream: bool = False,
|
|
250
|
+
optimizer: Optional[str] = None,
|
|
251
|
+
conversationally: bool = False,
|
|
252
|
+
**kwargs: Any,
|
|
253
|
+
) -> Union[str, Generator[str, None, None]]:
|
|
254
|
+
"""Generate response `str`"""
|
|
255
|
+
raw = kwargs.get("raw", False)
|
|
256
|
+
tools = kwargs.get("tools")
|
|
257
|
+
tool_choice = kwargs.get("tool_choice")
|
|
258
|
+
|
|
259
|
+
def for_stream_chat():
|
|
260
|
+
# ask() yields dicts or strings when streaming
|
|
261
|
+
gen = self.ask(
|
|
262
|
+
prompt, stream=True, raw=raw,
|
|
263
|
+
optimizer=optimizer, conversationally=conversationally,
|
|
264
|
+
tools=tools, tool_choice=tool_choice
|
|
265
|
+
)
|
|
266
|
+
for response_dict in gen:
|
|
267
|
+
if raw:
|
|
268
|
+
yield cast(str, response_dict)
|
|
269
|
+
else:
|
|
270
|
+
yield self.get_message(cast(Response, response_dict))
|
|
271
|
+
|
|
272
|
+
def for_non_stream_chat():
|
|
273
|
+
# ask() returns dict or str when not streaming
|
|
274
|
+
response_data = self.ask(
|
|
275
|
+
prompt,
|
|
276
|
+
stream=False,
|
|
277
|
+
raw=raw,
|
|
278
|
+
optimizer=optimizer,
|
|
279
|
+
conversationally=conversationally,
|
|
280
|
+
tools=tools,
|
|
281
|
+
tool_choice=tool_choice
|
|
282
|
+
)
|
|
283
|
+
if raw:
|
|
284
|
+
return cast(str, response_data)
|
|
285
|
+
return self.get_message(response_data)
|
|
286
|
+
|
|
287
|
+
return for_stream_chat() if stream else for_non_stream_chat()
|
|
288
|
+
|
|
289
|
+
def get_message(self, response: Response) -> str:
|
|
290
|
+
"""
|
|
291
|
+
Retrieves a clean message from the provided response.
|
|
292
|
+
|
|
293
|
+
Args:
|
|
294
|
+
response: The raw response data.
|
|
295
|
+
|
|
296
|
+
Returns:
|
|
297
|
+
str: The extracted message.
|
|
298
|
+
"""
|
|
299
|
+
if isinstance(response, str):
|
|
300
|
+
return response
|
|
301
|
+
elif isinstance(response, dict):
|
|
302
|
+
if "text" in response:
|
|
303
|
+
return response["text"]
|
|
304
|
+
elif "tool_calls" in response:
|
|
305
|
+
return json.dumps(response["tool_calls"])
|
|
306
|
+
return str(response)
|
|
307
|
+
|
|
308
|
+
if __name__ == "__main__":
|
|
309
|
+
# Ensure curl_cffi is installed
|
|
310
|
+
from rich import print
|
|
311
|
+
ai = Sambanova(api_key='')
|
|
312
|
+
response = ai.chat(input(">>> "), stream=True)
|
|
313
|
+
if hasattr(response, "__iter__") and not isinstance(response, (str, bytes)):
|
|
314
|
+
for chunk in response:
|
|
315
|
+
print(chunk, end="", flush=True)
|
|
316
|
+
else:
|
|
317
|
+
print(response)
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# 🖼️ Webscout Text-to-Image (TTI) Providers
|
|
2
|
+
|
|
3
|
+
Webscout includes a collection of Text-to-Image providers that follow a common interface inspired by the OpenAI Python client. Each provider exposes an `images.create()` method which returns an `ImageResponse` object containing either image URLs or base64 data.
|
|
4
|
+
|
|
5
|
+
These providers allow you to easily generate AI‑created art from text prompts while handling image conversion and temporary hosting automatically.
|
|
6
|
+
|
|
7
|
+
## ✨ Features
|
|
8
|
+
|
|
9
|
+
- **Unified API** – Consistent `images.create()` method for all providers
|
|
10
|
+
- **Multiple Providers** – Generate images using different third‑party services
|
|
11
|
+
- **URL or Base64 Output** – Receive image URLs (uploaded to catbox.moe/0x0.st) or base64 encoded bytes
|
|
12
|
+
- **PNG/JPEG Conversion** – Images are converted in memory to your chosen format
|
|
13
|
+
- **Model Listing** – Query available models with `provider.models.list()`
|
|
14
|
+
|
|
15
|
+
## 📦 Supported Providers
|
|
16
|
+
|
|
17
|
+
| Provider | Available Models (examples) | Status |
|
|
18
|
+
| ---------------- | ----------------------------------------- | --------- |
|
|
19
|
+
| `PollinationsAI` | `flux`, `flux-pro`, `turbo`, `gptimage` | Working |
|
|
20
|
+
| `MagicStudioAI` | `magicstudio` | Working |
|
|
21
|
+
| `ClaudeOnlineTTI`| `claude-imagine` | Working |
|
|
22
|
+
| `TogetherImage` | `flux.1-schnell`, `flux.1-pro` | Working* |
|
|
23
|
+
|
|
24
|
+
\* Requires authentication (API keys).
|
|
25
|
+
|
|
26
|
+
> **Note**: Some providers require the `Pillow` package for image processing.
|
|
27
|
+
|
|
28
|
+
## 🚀 Quick Start
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
from webscout.Provider.TTI import PollinationsAI
|
|
32
|
+
|
|
33
|
+
# Initialize the provider
|
|
34
|
+
client = PollinationsAI()
|
|
35
|
+
|
|
36
|
+
# Generate two images and get URLs
|
|
37
|
+
response = client.images.create(
|
|
38
|
+
model="flux",
|
|
39
|
+
prompt="A futuristic city skyline at sunset",
|
|
40
|
+
n=2,
|
|
41
|
+
response_format="url"
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
print(response)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Base64 Output
|
|
48
|
+
|
|
49
|
+
If you prefer the raw image data:
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
response = client.images.create(
|
|
53
|
+
model="flux",
|
|
54
|
+
prompt="Crystal mountain landscape",
|
|
55
|
+
response_format="b64_json"
|
|
56
|
+
)
|
|
57
|
+
# `response.data` will contain base64 strings
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## 🔧 Provider Specifics
|
|
61
|
+
|
|
62
|
+
- **PollinationsAI** – Allows setting a custom seed for reproducible results.
|
|
63
|
+
- **MagicStudioAI** – Generates images through MagicStudio's public endpoint.
|
|
64
|
+
- **ClaudeOnlineTTI** – Uses Pollinations.ai backend to provide image generation capabilities.
|
|
65
|
+
- **TogetherImage** – High-quality image generation via Together.xyz API (Requires API Key).
|
|
66
|
+
|
|
67
|
+
## 🤝 Contributing
|
|
68
|
+
|
|
69
|
+
Contributions and additional providers are welcome! Feel free to submit a pull request.
|
|
@@ -1,12 +1,37 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
from .
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
from .
|
|
12
|
-
from .
|
|
1
|
+
# This file marks the directory as a Python package.
|
|
2
|
+
# Static imports for all TTI (Text-to-Image) provider modules
|
|
3
|
+
|
|
4
|
+
# Base classes
|
|
5
|
+
from webscout.Provider.TTI.base import (
|
|
6
|
+
BaseImages,
|
|
7
|
+
TTICompatibleProvider,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
# Provider implementations
|
|
11
|
+
from webscout.Provider.TTI.claudeonline import ClaudeOnlineTTI
|
|
12
|
+
from webscout.Provider.TTI.magicstudio import MagicStudioAI
|
|
13
|
+
from webscout.Provider.TTI.miragic import MiragicAI
|
|
14
|
+
from webscout.Provider.TTI.pollinations import PollinationsAI
|
|
15
|
+
from webscout.Provider.TTI.together import TogetherImage
|
|
16
|
+
|
|
17
|
+
# Utility classes
|
|
18
|
+
from webscout.Provider.TTI.utils import (
|
|
19
|
+
ImageData,
|
|
20
|
+
ImageResponse,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
# List of all exported names
|
|
24
|
+
__all__ = [
|
|
25
|
+
# Base classes
|
|
26
|
+
"TTICompatibleProvider",
|
|
27
|
+
"BaseImages",
|
|
28
|
+
# Utilities
|
|
29
|
+
"ImageData",
|
|
30
|
+
"ImageResponse",
|
|
31
|
+
# Providers
|
|
32
|
+
"ClaudeOnlineTTI",
|
|
33
|
+
"MagicStudioAI",
|
|
34
|
+
"PollinationsAI",
|
|
35
|
+
"TogetherImage",
|
|
36
|
+
"MiragicAI",
|
|
37
|
+
]
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from typing import Any, List, Optional, Union, cast
|
|
3
|
+
|
|
4
|
+
from .utils import ImageResponse
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class BaseImages(ABC):
|
|
8
|
+
@abstractmethod
|
|
9
|
+
def create(
|
|
10
|
+
self,
|
|
11
|
+
*,
|
|
12
|
+
model: str,
|
|
13
|
+
prompt: str,
|
|
14
|
+
n: int = 1,
|
|
15
|
+
size: str = "1024x1024",
|
|
16
|
+
response_format: str = "url",
|
|
17
|
+
user: Optional[str] = None,
|
|
18
|
+
style: str = "none",
|
|
19
|
+
aspect_ratio: str = "1:1",
|
|
20
|
+
timeout: Optional[int] = None,
|
|
21
|
+
image_format: str = "png",
|
|
22
|
+
seed: Optional[int] = None,
|
|
23
|
+
convert_format: bool = False,
|
|
24
|
+
**kwargs,
|
|
25
|
+
) -> ImageResponse:
|
|
26
|
+
"""
|
|
27
|
+
Abstract method to create images from a prompt.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
model: The model to use for image generation.
|
|
31
|
+
prompt: The prompt for the image.
|
|
32
|
+
n: Number of images to generate.
|
|
33
|
+
size: Image size.
|
|
34
|
+
response_format: "url" or "b64_json".
|
|
35
|
+
user: Optional user identifier.
|
|
36
|
+
style: Optional style.
|
|
37
|
+
aspect_ratio: Optional aspect ratio.
|
|
38
|
+
timeout: Request timeout in seconds.
|
|
39
|
+
image_format: "png" or "jpeg" for output format.
|
|
40
|
+
seed: Optional random seed for reproducibility.
|
|
41
|
+
**kwargs: Additional provider-specific parameters.
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
ImageResponse: The generated images.
|
|
45
|
+
"""
|
|
46
|
+
raise NotImplementedError
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
# class ProxyAutoMeta(ABCMeta):
|
|
50
|
+
# """Metaclass providing seamless proxy injection for providers."""
|
|
51
|
+
|
|
52
|
+
# def __call__(cls, *args, **kwargs):
|
|
53
|
+
# # Determine if automatic proxying should be disabled
|
|
54
|
+
# disable_auto_proxy = kwargs.get('disable_auto_proxy', False) or getattr(cls, 'DISABLE_AUTO_PROXY', False)
|
|
55
|
+
|
|
56
|
+
# # Proxies may be supplied explicitly
|
|
57
|
+
# proxies = kwargs.get('proxies', None)
|
|
58
|
+
|
|
59
|
+
# # Otherwise try to fetch one automatically
|
|
60
|
+
# if proxies is None and not disable_auto_proxy:
|
|
61
|
+
# try:
|
|
62
|
+
# proxies = {"http": get_auto_proxy(), "https": get_auto_proxy()}
|
|
63
|
+
# except Exception as e:
|
|
64
|
+
# print(f"Failed to fetch auto-proxy: {e}")
|
|
65
|
+
# proxies = {}
|
|
66
|
+
# elif proxies is None:
|
|
67
|
+
# proxies = {}
|
|
68
|
+
|
|
69
|
+
# # No global monkeypatching, just set proxies on the instance
|
|
70
|
+
# instance = super().__call__(*args, **kwargs)
|
|
71
|
+
# instance.proxies = proxies
|
|
72
|
+
|
|
73
|
+
# # If proxies are set, patch any existing session-like attributes
|
|
74
|
+
# if proxies:
|
|
75
|
+
# for attr in dir(instance):
|
|
76
|
+
# obj = getattr(instance, attr)
|
|
77
|
+
# if isinstance(obj, requests.Session):
|
|
78
|
+
# obj.proxies.update(proxies)
|
|
79
|
+
# if CurlSession and isinstance(obj, CurlSession):
|
|
80
|
+
# try:
|
|
81
|
+
# obj.proxies.update(proxies)
|
|
82
|
+
# except (ValueError, KeyError, AttributeError):
|
|
83
|
+
# print("Failed to update proxies for CurlSession due to an expected error.")
|
|
84
|
+
# if CurlAsyncSession and isinstance(obj, CurlAsyncSession):
|
|
85
|
+
# try:
|
|
86
|
+
# obj.proxies.update(proxies)
|
|
87
|
+
# except (ValueError, KeyError, AttributeError):
|
|
88
|
+
# print("Failed to update proxies for CurlAsyncSession due to an expected error.")
|
|
89
|
+
|
|
90
|
+
# # Helper for backward compatibility
|
|
91
|
+
# def get_proxied_session():
|
|
92
|
+
# s = requests.Session()
|
|
93
|
+
# s.proxies.update(proxies)
|
|
94
|
+
# return s
|
|
95
|
+
|
|
96
|
+
# instance.get_proxied_session = get_proxied_session
|
|
97
|
+
|
|
98
|
+
# def get_proxied_curl_session(impersonate="chrome120", **kw):
|
|
99
|
+
# if CurlSession:
|
|
100
|
+
# return CurlSession(proxies=proxies, impersonate=impersonate, **kw)
|
|
101
|
+
# raise ImportError("curl_cffi is not installed")
|
|
102
|
+
|
|
103
|
+
# instance.get_proxied_curl_session = get_proxied_curl_session
|
|
104
|
+
|
|
105
|
+
# def get_proxied_curl_async_session(impersonate="chrome120", **kw):
|
|
106
|
+
# if CurlAsyncSession:
|
|
107
|
+
# return CurlAsyncSession(proxies=proxies, impersonate=impersonate, **kw)
|
|
108
|
+
# raise ImportError("curl_cffi is not installed")
|
|
109
|
+
|
|
110
|
+
# instance.get_proxied_curl_async_session = get_proxied_curl_async_session
|
|
111
|
+
|
|
112
|
+
# return instance
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
class TTICompatibleProvider(ABC):
|
|
116
|
+
"""
|
|
117
|
+
Abstract Base Class for TTI providers mimicking the OpenAI Python client structure.
|
|
118
|
+
Requires a nested 'images.create' structure.
|
|
119
|
+
All subclasses automatically get proxy support via ProxyAutoMeta.
|
|
120
|
+
|
|
121
|
+
Class Attributes:
|
|
122
|
+
required_auth (bool): Whether this provider requires authentication (API key, cookie, etc.)
|
|
123
|
+
working (bool): Whether this provider is currently working/operational
|
|
124
|
+
|
|
125
|
+
Available proxy helpers:
|
|
126
|
+
- self.get_proxied_session() - returns a requests.Session with proxies
|
|
127
|
+
- self.get_proxied_curl_session() - returns a curl_cffi.Session with proxies
|
|
128
|
+
- self.get_proxied_curl_async_session() - returns a curl_cffi.AsyncSession with proxies
|
|
129
|
+
"""
|
|
130
|
+
|
|
131
|
+
images: BaseImages
|
|
132
|
+
required_auth: bool = False # Default: no auth required
|
|
133
|
+
working: bool = True # Default: provider is working
|
|
134
|
+
AVAILABLE_MODELS: List[str] = [] # List of available models
|
|
135
|
+
|
|
136
|
+
@abstractmethod
|
|
137
|
+
def __init__(self, **kwargs: Any):
|
|
138
|
+
pass
|
|
139
|
+
|
|
140
|
+
@property
|
|
141
|
+
@abstractmethod
|
|
142
|
+
def models(self) -> Any:
|
|
143
|
+
"""
|
|
144
|
+
Property that returns an object with a .list() method returning available models.
|
|
145
|
+
Subclasses must implement this property.
|
|
146
|
+
"""
|
|
147
|
+
raise NotImplementedError
|