webscout 8.3.6__py3-none-any.whl → 2025.10.11__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.
Potentially problematic release.
This version of webscout might be problematic. Click here for more details.
- webscout/AIauto.py +250 -250
- webscout/AIbase.py +379 -379
- webscout/AIutel.py +60 -58
- webscout/Bard.py +1012 -1012
- webscout/Bing_search.py +417 -417
- webscout/DWEBS.py +529 -529
- webscout/Extra/Act.md +309 -309
- webscout/Extra/GitToolkit/__init__.py +10 -10
- webscout/Extra/GitToolkit/gitapi/README.md +110 -110
- webscout/Extra/GitToolkit/gitapi/__init__.py +11 -11
- webscout/Extra/GitToolkit/gitapi/repository.py +195 -195
- webscout/Extra/GitToolkit/gitapi/user.py +96 -96
- webscout/Extra/GitToolkit/gitapi/utils.py +61 -61
- webscout/Extra/YTToolkit/README.md +375 -375
- webscout/Extra/YTToolkit/YTdownloader.py +956 -956
- webscout/Extra/YTToolkit/__init__.py +2 -2
- webscout/Extra/YTToolkit/transcriber.py +475 -475
- webscout/Extra/YTToolkit/ytapi/README.md +44 -44
- webscout/Extra/YTToolkit/ytapi/__init__.py +6 -6
- webscout/Extra/YTToolkit/ytapi/channel.py +307 -307
- webscout/Extra/YTToolkit/ytapi/errors.py +13 -13
- webscout/Extra/YTToolkit/ytapi/extras.py +118 -118
- webscout/Extra/YTToolkit/ytapi/https.py +88 -88
- webscout/Extra/YTToolkit/ytapi/patterns.py +61 -61
- webscout/Extra/YTToolkit/ytapi/playlist.py +58 -58
- webscout/Extra/YTToolkit/ytapi/pool.py +7 -7
- webscout/Extra/YTToolkit/ytapi/query.py +39 -39
- webscout/Extra/YTToolkit/ytapi/stream.py +62 -62
- webscout/Extra/YTToolkit/ytapi/utils.py +62 -62
- webscout/Extra/YTToolkit/ytapi/video.py +232 -232
- webscout/Extra/autocoder/__init__.py +9 -9
- webscout/Extra/autocoder/autocoder.py +1105 -1105
- webscout/Extra/autocoder/autocoder_utiles.py +332 -332
- webscout/Extra/gguf.md +429 -429
- webscout/Extra/gguf.py +1213 -1213
- webscout/Extra/tempmail/README.md +487 -487
- webscout/Extra/tempmail/__init__.py +27 -27
- webscout/Extra/tempmail/async_utils.py +140 -140
- webscout/Extra/tempmail/base.py +160 -160
- webscout/Extra/tempmail/cli.py +186 -186
- webscout/Extra/tempmail/emailnator.py +84 -84
- webscout/Extra/tempmail/mail_tm.py +360 -360
- webscout/Extra/tempmail/temp_mail_io.py +291 -291
- webscout/Extra/weather.md +281 -281
- webscout/Extra/weather.py +193 -193
- webscout/Litlogger/README.md +10 -10
- webscout/Litlogger/__init__.py +15 -15
- webscout/Litlogger/formats.py +13 -13
- webscout/Litlogger/handlers.py +121 -121
- webscout/Litlogger/levels.py +13 -13
- webscout/Litlogger/logger.py +134 -134
- webscout/Provider/AISEARCH/Perplexity.py +332 -332
- webscout/Provider/AISEARCH/README.md +279 -279
- webscout/Provider/AISEARCH/__init__.py +33 -11
- webscout/Provider/AISEARCH/felo_search.py +206 -206
- webscout/Provider/AISEARCH/genspark_search.py +323 -323
- webscout/Provider/AISEARCH/hika_search.py +185 -185
- webscout/Provider/AISEARCH/iask_search.py +410 -410
- webscout/Provider/AISEARCH/monica_search.py +219 -219
- webscout/Provider/AISEARCH/scira_search.py +316 -314
- webscout/Provider/AISEARCH/stellar_search.py +177 -177
- webscout/Provider/AISEARCH/webpilotai_search.py +255 -255
- webscout/Provider/Aitopia.py +314 -315
- webscout/Provider/Andi.py +3 -3
- webscout/Provider/Apriel.py +306 -0
- webscout/Provider/ChatGPTClone.py +236 -236
- webscout/Provider/ChatSandbox.py +343 -342
- webscout/Provider/Cloudflare.py +324 -324
- webscout/Provider/Cohere.py +208 -207
- webscout/Provider/Deepinfra.py +370 -369
- webscout/Provider/ExaAI.py +260 -260
- webscout/Provider/ExaChat.py +308 -387
- webscout/Provider/Flowith.py +221 -221
- webscout/Provider/GMI.py +293 -0
- webscout/Provider/Gemini.py +164 -162
- webscout/Provider/GeminiProxy.py +167 -166
- webscout/Provider/GithubChat.py +371 -370
- webscout/Provider/Groq.py +800 -800
- webscout/Provider/HeckAI.py +383 -379
- webscout/Provider/Jadve.py +282 -297
- webscout/Provider/K2Think.py +308 -0
- webscout/Provider/Koboldai.py +206 -384
- webscout/Provider/LambdaChat.py +423 -425
- webscout/Provider/Nemotron.py +244 -245
- webscout/Provider/Netwrck.py +248 -247
- webscout/Provider/OLLAMA.py +395 -394
- webscout/Provider/OPENAI/Cloudflare.py +394 -395
- webscout/Provider/OPENAI/FalconH1.py +452 -457
- webscout/Provider/OPENAI/FreeGemini.py +297 -299
- webscout/Provider/OPENAI/{monochat.py → K2Think.py} +432 -329
- webscout/Provider/OPENAI/NEMOTRON.py +241 -244
- webscout/Provider/OPENAI/PI.py +428 -427
- webscout/Provider/OPENAI/README.md +959 -959
- webscout/Provider/OPENAI/TogetherAI.py +345 -345
- webscout/Provider/OPENAI/TwoAI.py +466 -467
- webscout/Provider/OPENAI/__init__.py +33 -59
- webscout/Provider/OPENAI/ai4chat.py +313 -303
- webscout/Provider/OPENAI/base.py +249 -269
- webscout/Provider/OPENAI/chatglm.py +528 -0
- webscout/Provider/OPENAI/chatgpt.py +593 -588
- webscout/Provider/OPENAI/chatgptclone.py +521 -524
- webscout/Provider/OPENAI/chatsandbox.py +202 -177
- webscout/Provider/OPENAI/deepinfra.py +319 -315
- webscout/Provider/OPENAI/e2b.py +1665 -1665
- webscout/Provider/OPENAI/exaai.py +420 -420
- webscout/Provider/OPENAI/exachat.py +452 -452
- webscout/Provider/OPENAI/friendli.py +232 -232
- webscout/Provider/OPENAI/{refact.py → gmi.py} +324 -274
- webscout/Provider/OPENAI/groq.py +364 -364
- webscout/Provider/OPENAI/heckai.py +314 -311
- webscout/Provider/OPENAI/llmchatco.py +337 -337
- webscout/Provider/OPENAI/netwrck.py +355 -354
- webscout/Provider/OPENAI/oivscode.py +290 -290
- webscout/Provider/OPENAI/opkfc.py +518 -518
- webscout/Provider/OPENAI/pydantic_imports.py +1 -1
- webscout/Provider/OPENAI/scirachat.py +535 -529
- webscout/Provider/OPENAI/sonus.py +308 -308
- webscout/Provider/OPENAI/standardinput.py +442 -442
- webscout/Provider/OPENAI/textpollinations.py +340 -348
- webscout/Provider/OPENAI/toolbaz.py +419 -413
- webscout/Provider/OPENAI/typefully.py +362 -362
- webscout/Provider/OPENAI/utils.py +295 -295
- webscout/Provider/OPENAI/venice.py +436 -436
- webscout/Provider/OPENAI/wisecat.py +387 -387
- webscout/Provider/OPENAI/writecream.py +166 -166
- webscout/Provider/OPENAI/x0gpt.py +378 -378
- webscout/Provider/OPENAI/yep.py +389 -389
- webscout/Provider/OpenGPT.py +230 -230
- webscout/Provider/Openai.py +244 -496
- webscout/Provider/PI.py +405 -404
- webscout/Provider/Perplexitylabs.py +430 -431
- webscout/Provider/QwenLM.py +272 -254
- webscout/Provider/STT/__init__.py +32 -2
- webscout/Provider/{Llama3.py → Sambanova.py} +257 -258
- webscout/Provider/StandardInput.py +309 -309
- webscout/Provider/TTI/README.md +82 -82
- webscout/Provider/TTI/__init__.py +33 -12
- webscout/Provider/TTI/aiarta.py +413 -413
- webscout/Provider/TTI/base.py +136 -136
- webscout/Provider/TTI/bing.py +243 -243
- webscout/Provider/TTI/gpt1image.py +149 -149
- webscout/Provider/TTI/imagen.py +196 -196
- webscout/Provider/TTI/infip.py +211 -211
- webscout/Provider/TTI/magicstudio.py +232 -232
- webscout/Provider/TTI/monochat.py +219 -219
- webscout/Provider/TTI/piclumen.py +214 -214
- webscout/Provider/TTI/pixelmuse.py +232 -232
- webscout/Provider/TTI/pollinations.py +232 -232
- webscout/Provider/TTI/together.py +288 -288
- webscout/Provider/TTI/utils.py +12 -12
- webscout/Provider/TTI/venice.py +367 -367
- webscout/Provider/TTS/README.md +192 -192
- webscout/Provider/TTS/__init__.py +33 -10
- webscout/Provider/TTS/parler.py +110 -110
- webscout/Provider/TTS/streamElements.py +333 -333
- webscout/Provider/TTS/utils.py +280 -280
- webscout/Provider/TeachAnything.py +237 -236
- webscout/Provider/TextPollinationsAI.py +311 -318
- webscout/Provider/TogetherAI.py +356 -357
- webscout/Provider/TwoAI.py +313 -569
- webscout/Provider/TypliAI.py +312 -311
- webscout/Provider/UNFINISHED/ChatHub.py +208 -208
- webscout/Provider/UNFINISHED/ChutesAI.py +313 -313
- webscout/Provider/{GizAI.py → UNFINISHED/GizAI.py} +294 -294
- webscout/Provider/{Marcus.py → UNFINISHED/Marcus.py} +198 -198
- webscout/Provider/{Qodo.py → UNFINISHED/Qodo.py} +477 -477
- webscout/Provider/UNFINISHED/VercelAIGateway.py +338 -338
- webscout/Provider/{XenAI.py → UNFINISHED/XenAI.py} +324 -324
- webscout/Provider/UNFINISHED/Youchat.py +330 -330
- webscout/Provider/UNFINISHED/liner.py +334 -0
- webscout/Provider/UNFINISHED/liner_api_request.py +262 -262
- webscout/Provider/UNFINISHED/puterjs.py +634 -634
- webscout/Provider/UNFINISHED/samurai.py +223 -223
- webscout/Provider/UNFINISHED/test_lmarena.py +119 -119
- webscout/Provider/Venice.py +251 -250
- webscout/Provider/VercelAI.py +256 -255
- webscout/Provider/WiseCat.py +232 -231
- webscout/Provider/WrDoChat.py +367 -366
- webscout/Provider/__init__.py +33 -86
- webscout/Provider/ai4chat.py +174 -174
- webscout/Provider/akashgpt.py +331 -334
- webscout/Provider/cerebras.py +446 -340
- webscout/Provider/chatglm.py +394 -214
- webscout/Provider/cleeai.py +211 -212
- webscout/Provider/deepseek_assistant.py +1 -1
- webscout/Provider/elmo.py +282 -282
- webscout/Provider/geminiapi.py +208 -208
- webscout/Provider/granite.py +261 -261
- webscout/Provider/hermes.py +263 -265
- webscout/Provider/julius.py +223 -222
- webscout/Provider/learnfastai.py +309 -309
- webscout/Provider/llama3mitril.py +214 -214
- webscout/Provider/llmchat.py +243 -243
- webscout/Provider/llmchatco.py +290 -290
- webscout/Provider/meta.py +801 -801
- webscout/Provider/oivscode.py +309 -309
- webscout/Provider/scira_chat.py +384 -457
- webscout/Provider/searchchat.py +292 -291
- webscout/Provider/sonus.py +258 -258
- webscout/Provider/toolbaz.py +370 -364
- webscout/Provider/turboseek.py +274 -265
- webscout/Provider/typefully.py +208 -207
- webscout/Provider/x0gpt.py +1 -0
- webscout/Provider/yep.py +372 -371
- webscout/__init__.py +30 -31
- webscout/__main__.py +5 -5
- webscout/auth/api_key_manager.py +189 -189
- webscout/auth/config.py +175 -175
- webscout/auth/models.py +185 -185
- webscout/auth/routes.py +664 -664
- webscout/auth/simple_logger.py +236 -236
- webscout/cli.py +523 -523
- webscout/conversation.py +438 -438
- webscout/exceptions.py +361 -361
- webscout/litagent/Readme.md +298 -298
- webscout/litagent/__init__.py +28 -28
- webscout/litagent/agent.py +581 -581
- webscout/litagent/constants.py +59 -59
- webscout/litprinter/__init__.py +58 -58
- webscout/models.py +181 -181
- webscout/optimizers.py +419 -419
- webscout/prompt_manager.py +288 -288
- webscout/sanitize.py +1078 -1078
- webscout/scout/README.md +401 -401
- webscout/scout/__init__.py +8 -8
- webscout/scout/core/__init__.py +6 -6
- webscout/scout/core/crawler.py +297 -297
- webscout/scout/core/scout.py +706 -706
- webscout/scout/core/search_result.py +95 -95
- webscout/scout/core/text_analyzer.py +62 -62
- webscout/scout/core/text_utils.py +277 -277
- webscout/scout/core/web_analyzer.py +51 -51
- webscout/scout/element.py +599 -599
- webscout/scout/parsers/__init__.py +69 -69
- webscout/scout/parsers/html5lib_parser.py +172 -172
- webscout/scout/parsers/html_parser.py +236 -236
- webscout/scout/parsers/lxml_parser.py +178 -178
- webscout/scout/utils.py +37 -37
- webscout/swiftcli/Readme.md +323 -323
- webscout/swiftcli/__init__.py +95 -95
- webscout/swiftcli/core/__init__.py +7 -7
- webscout/swiftcli/core/cli.py +308 -308
- webscout/swiftcli/core/context.py +104 -104
- webscout/swiftcli/core/group.py +241 -241
- webscout/swiftcli/decorators/__init__.py +28 -28
- webscout/swiftcli/decorators/command.py +221 -221
- webscout/swiftcli/decorators/options.py +220 -220
- webscout/swiftcli/decorators/output.py +302 -302
- webscout/swiftcli/exceptions.py +21 -21
- webscout/swiftcli/plugins/__init__.py +9 -9
- webscout/swiftcli/plugins/base.py +135 -135
- webscout/swiftcli/plugins/manager.py +269 -269
- webscout/swiftcli/utils/__init__.py +59 -59
- webscout/swiftcli/utils/formatting.py +252 -252
- webscout/swiftcli/utils/parsing.py +267 -267
- webscout/update_checker.py +117 -117
- webscout/version.py +1 -1
- webscout/webscout_search.py +1183 -1183
- webscout/webscout_search_async.py +649 -649
- webscout/yep_search.py +346 -346
- webscout/zeroart/README.md +89 -89
- webscout/zeroart/__init__.py +134 -134
- webscout/zeroart/base.py +66 -66
- webscout/zeroart/effects.py +100 -100
- webscout/zeroart/fonts.py +1238 -1238
- {webscout-8.3.6.dist-info → webscout-2025.10.11.dist-info}/METADATA +937 -936
- webscout-2025.10.11.dist-info/RECORD +300 -0
- webscout/Provider/AISEARCH/DeepFind.py +0 -254
- webscout/Provider/AllenAI.py +0 -440
- webscout/Provider/Blackboxai.py +0 -793
- webscout/Provider/FreeGemini.py +0 -250
- webscout/Provider/GptOss.py +0 -207
- webscout/Provider/Hunyuan.py +0 -283
- webscout/Provider/Kimi.py +0 -445
- webscout/Provider/MCPCore.py +0 -322
- webscout/Provider/MiniMax.py +0 -207
- webscout/Provider/OPENAI/BLACKBOXAI.py +0 -1045
- webscout/Provider/OPENAI/MiniMax.py +0 -298
- webscout/Provider/OPENAI/Qwen3.py +0 -304
- webscout/Provider/OPENAI/autoproxy.py +0 -1067
- webscout/Provider/OPENAI/copilot.py +0 -321
- webscout/Provider/OPENAI/gptoss.py +0 -288
- webscout/Provider/OPENAI/kimi.py +0 -469
- webscout/Provider/OPENAI/mcpcore.py +0 -431
- webscout/Provider/OPENAI/multichat.py +0 -378
- webscout/Provider/OPENAI/qodo.py +0 -630
- webscout/Provider/OPENAI/xenai.py +0 -514
- webscout/Provider/Reka.py +0 -214
- webscout/Provider/UNFINISHED/fetch_together_models.py +0 -90
- webscout/Provider/asksteve.py +0 -220
- webscout/Provider/copilot.py +0 -441
- webscout/Provider/freeaichat.py +0 -294
- webscout/Provider/koala.py +0 -182
- webscout/Provider/lmarena.py +0 -198
- webscout/Provider/monochat.py +0 -275
- webscout/Provider/multichat.py +0 -375
- webscout/Provider/scnet.py +0 -244
- webscout/Provider/talkai.py +0 -194
- webscout/tempid.py +0 -128
- webscout-8.3.6.dist-info/RECORD +0 -327
- {webscout-8.3.6.dist-info → webscout-2025.10.11.dist-info}/WHEEL +0 -0
- {webscout-8.3.6.dist-info → webscout-2025.10.11.dist-info}/entry_points.txt +0 -0
- {webscout-8.3.6.dist-info → webscout-2025.10.11.dist-info}/licenses/LICENSE.md +0 -0
- {webscout-8.3.6.dist-info → webscout-2025.10.11.dist-info}/top_level.txt +0 -0
|
@@ -1,289 +1,289 @@
|
|
|
1
|
-
import requests
|
|
2
|
-
import random
|
|
3
|
-
import string
|
|
4
|
-
import json
|
|
5
|
-
import time
|
|
6
|
-
from typing import Optional, List, Dict, Any
|
|
7
|
-
from webscout.Provider.TTI.utils import (
|
|
8
|
-
ImageData,
|
|
9
|
-
ImageResponse
|
|
10
|
-
)
|
|
11
|
-
from webscout.Provider.TTI.base import TTICompatibleProvider, BaseImages
|
|
12
|
-
from io import BytesIO
|
|
13
|
-
import os
|
|
14
|
-
import tempfile
|
|
15
|
-
from webscout.litagent import LitAgent
|
|
16
|
-
from requests.adapters import HTTPAdapter
|
|
17
|
-
from urllib3.util.retry import Retry
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
class Images(BaseImages):
|
|
21
|
-
def __init__(self, client):
|
|
22
|
-
self._client = client
|
|
23
|
-
self.base_url = "https://api.together.xyz/v1"
|
|
24
|
-
# Create a session - it will automatically get proxies from the global monkey patch!
|
|
25
|
-
self.session = requests.Session()
|
|
26
|
-
self._setup_session_with_retries()
|
|
27
|
-
|
|
28
|
-
def _setup_session_with_retries(self):
|
|
29
|
-
"""Setup session with retry strategy and timeout configurations"""
|
|
30
|
-
# Configure retry strategy
|
|
31
|
-
retry_strategy = Retry(
|
|
32
|
-
total=3,
|
|
33
|
-
status_forcelist=[429, 500, 502, 503, 504],
|
|
34
|
-
backoff_factor=1,
|
|
35
|
-
allowed_methods=["HEAD", "GET", "OPTIONS", "POST"],
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
adapter = HTTPAdapter(max_retries=retry_strategy)
|
|
39
|
-
self.session.mount("http://", adapter)
|
|
40
|
-
self.session.mount("https://", adapter)
|
|
41
|
-
|
|
42
|
-
def get_api_key(self) -> str:
|
|
43
|
-
"""Get API key from activation endpoint or cache"""
|
|
44
|
-
if hasattr(self._client, '_api_key_cache') and self._client._api_key_cache:
|
|
45
|
-
return self._client._api_key_cache
|
|
46
|
-
|
|
47
|
-
try:
|
|
48
|
-
activation_endpoint = "https://www.codegeneration.ai/activate-v2"
|
|
49
|
-
response = requests.get(
|
|
50
|
-
activation_endpoint,
|
|
51
|
-
headers={"Accept": "application/json"},
|
|
52
|
-
timeout=30
|
|
53
|
-
)
|
|
54
|
-
response.raise_for_status()
|
|
55
|
-
activation_data = response.json()
|
|
56
|
-
api_key = activation_data["openAIParams"]["apiKey"]
|
|
57
|
-
self._client._api_key_cache = api_key
|
|
58
|
-
return api_key
|
|
59
|
-
except Exception as e:
|
|
60
|
-
raise Exception(f"Failed to get activation key: {e}")
|
|
61
|
-
|
|
62
|
-
def build_headers(self, extra: Optional[Dict[str, str]] = None) -> Dict[str, str]:
|
|
63
|
-
"""Build headers with API authorization"""
|
|
64
|
-
api_key = self.get_api_key()
|
|
65
|
-
|
|
66
|
-
agent = LitAgent()
|
|
67
|
-
fp = agent.generate_fingerprint("chrome")
|
|
68
|
-
headers = {
|
|
69
|
-
"Authorization": f"Bearer {api_key}",
|
|
70
|
-
"Content-Type": "application/json",
|
|
71
|
-
"accept": "application/json",
|
|
72
|
-
"accept-language": fp["accept_language"],
|
|
73
|
-
"user-agent": fp["user_agent"],
|
|
74
|
-
"sec-ch-ua": fp["sec_ch_ua"],
|
|
75
|
-
"sec-ch-ua-mobile": "?0",
|
|
76
|
-
"sec-ch-ua-platform": '"Windows"',
|
|
77
|
-
"sec-fetch-dest": "empty",
|
|
78
|
-
"sec-fetch-mode": "cors",
|
|
79
|
-
"sec-fetch-site": "cross-site",
|
|
80
|
-
}
|
|
81
|
-
if extra:
|
|
82
|
-
headers.update(extra)
|
|
83
|
-
return headers
|
|
84
|
-
|
|
85
|
-
def create(
|
|
86
|
-
self,
|
|
87
|
-
model: str = None,
|
|
88
|
-
prompt: str = None,
|
|
89
|
-
n: int = 1,
|
|
90
|
-
size: str = "1024x1024",
|
|
91
|
-
response_format: str = "url",
|
|
92
|
-
user: Optional[str] = None,
|
|
93
|
-
style: str = None,
|
|
94
|
-
aspect_ratio: str = None,
|
|
95
|
-
timeout: int = 120,
|
|
96
|
-
image_format: str = "png",
|
|
97
|
-
enhance: bool = True,
|
|
98
|
-
steps: int = 20,
|
|
99
|
-
seed: Optional[int] = None,
|
|
100
|
-
**kwargs,
|
|
101
|
-
) -> ImageResponse:
|
|
102
|
-
"""
|
|
103
|
-
Create images using Together.xyz image models
|
|
104
|
-
|
|
105
|
-
Args:
|
|
106
|
-
model: Image model to use (defaults to first available)
|
|
107
|
-
prompt: Text description of the image to generate
|
|
108
|
-
n: Number of images to generate (1-4)
|
|
109
|
-
size: Image size in format "WIDTHxHEIGHT"
|
|
110
|
-
response_format: "url" or "b64_json"
|
|
111
|
-
timeout: Request timeout in seconds
|
|
112
|
-
steps: Number of inference steps (1-50)
|
|
113
|
-
seed: Random seed for reproducible results
|
|
114
|
-
**kwargs: Additional model-specific parameters
|
|
115
|
-
"""
|
|
116
|
-
if not prompt:
|
|
117
|
-
raise ValueError(
|
|
118
|
-
"Describe the image you want to create (use the 'prompt' property)."
|
|
119
|
-
)
|
|
120
|
-
|
|
121
|
-
# Use provided model or default to first available
|
|
122
|
-
if not model:
|
|
123
|
-
model = self._client.AVAILABLE_MODELS[0]
|
|
124
|
-
elif model not in self._client.AVAILABLE_MODELS:
|
|
125
|
-
raise ValueError(f"Model '{model}' not available. Choose from: {self._client.AVAILABLE_MODELS}")
|
|
126
|
-
|
|
127
|
-
# Parse size
|
|
128
|
-
if 'x' in size:
|
|
129
|
-
width, height = map(int, size.split('x'))
|
|
130
|
-
else:
|
|
131
|
-
width = height = int(size)
|
|
132
|
-
|
|
133
|
-
# Build request body
|
|
134
|
-
body = {
|
|
135
|
-
"model": model,
|
|
136
|
-
"prompt": prompt,
|
|
137
|
-
"width": width,
|
|
138
|
-
"height": height,
|
|
139
|
-
# Clamp steps to 1-4 as required by Together.xyz API
|
|
140
|
-
"steps": min(max(steps, 1), 4),
|
|
141
|
-
"n": min(max(n, 1), 4), # Clamp between 1-4
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
# Add optional parameters
|
|
145
|
-
if seed is not None:
|
|
146
|
-
body["seed"] = seed
|
|
147
|
-
|
|
148
|
-
# Add any additional kwargs
|
|
149
|
-
body.update(kwargs)
|
|
150
|
-
|
|
151
|
-
try:
|
|
152
|
-
resp = self.session.request(
|
|
153
|
-
"post",
|
|
154
|
-
f"{self.base_url}/images/generations",
|
|
155
|
-
json=body,
|
|
156
|
-
headers=self.build_headers(),
|
|
157
|
-
timeout=timeout,
|
|
158
|
-
)
|
|
159
|
-
|
|
160
|
-
data = resp.json()
|
|
161
|
-
|
|
162
|
-
# Check for errors
|
|
163
|
-
if "error" in data:
|
|
164
|
-
error_msg = data["error"].get("message", str(data["error"]))
|
|
165
|
-
raise RuntimeError(f"Together.xyz API error: {error_msg}")
|
|
166
|
-
|
|
167
|
-
if not data.get("data") or len(data["data"]) == 0:
|
|
168
|
-
raise RuntimeError("Failed to process image. No data found.")
|
|
169
|
-
|
|
170
|
-
result = data["data"]
|
|
171
|
-
result_data = []
|
|
172
|
-
|
|
173
|
-
for i, item in enumerate(result):
|
|
174
|
-
if response_format == "url":
|
|
175
|
-
if "url" in item:
|
|
176
|
-
result_data.append(ImageData(url=item["url"]))
|
|
177
|
-
else: # b64_json
|
|
178
|
-
if "b64_json" in item:
|
|
179
|
-
result_data.append(ImageData(b64_json=item["b64_json"]))
|
|
180
|
-
|
|
181
|
-
if not result_data:
|
|
182
|
-
raise RuntimeError("No valid image data found in response")
|
|
183
|
-
|
|
184
|
-
return ImageResponse(data=result_data)
|
|
185
|
-
|
|
186
|
-
except requests.exceptions.Timeout:
|
|
187
|
-
raise RuntimeError(f"Request timed out after {timeout} seconds. Try reducing image size or steps.")
|
|
188
|
-
except requests.exceptions.RequestException as e:
|
|
189
|
-
# Print the response content for debugging if available
|
|
190
|
-
if hasattr(e, 'response') and e.response is not None:
|
|
191
|
-
try:
|
|
192
|
-
print("[Together.xyz API error details]", e.response.text)
|
|
193
|
-
except Exception:
|
|
194
|
-
pass
|
|
195
|
-
raise RuntimeError(f"Network error: {str(e)}")
|
|
196
|
-
except json.JSONDecodeError:
|
|
197
|
-
raise RuntimeError("Invalid JSON response from Together.xyz API")
|
|
198
|
-
except Exception as e:
|
|
199
|
-
raise RuntimeError(f"An error occurred: {str(e)}")
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
class TogetherImage(TTICompatibleProvider):
|
|
203
|
-
"""
|
|
204
|
-
Together.xyz Text-to-Image provider
|
|
205
|
-
Updated: 2025-08-01 10:42:41 UTC by OEvortex
|
|
206
|
-
Supports FLUX and other image generation models
|
|
207
|
-
"""
|
|
208
|
-
|
|
209
|
-
# Image models from Together.xyz API (filtered for image type only)
|
|
210
|
-
AVAILABLE_MODELS = [
|
|
211
|
-
"black-forest-labs/FLUX.1-canny",
|
|
212
|
-
"black-forest-labs/FLUX.1-depth",
|
|
213
|
-
"black-forest-labs/FLUX.1-dev",
|
|
214
|
-
"black-forest-labs/FLUX.1-dev-lora",
|
|
215
|
-
"black-forest-labs/FLUX.1-kontext-dev",
|
|
216
|
-
"black-forest-labs/FLUX.1-kontext-max",
|
|
217
|
-
"black-forest-labs/FLUX.1-kontext-pro",
|
|
218
|
-
"black-forest-labs/FLUX.1-krea-dev",
|
|
219
|
-
"black-forest-labs/FLUX.1-pro",
|
|
220
|
-
"black-forest-labs/FLUX.1-redux",
|
|
221
|
-
"black-forest-labs/FLUX.1-schnell",
|
|
222
|
-
"black-forest-labs/FLUX.1-schnell-Free",
|
|
223
|
-
"black-forest-labs/FLUX.1.1-pro"
|
|
224
|
-
]
|
|
225
|
-
|
|
226
|
-
def __init__(self):
|
|
227
|
-
self.images = Images(self)
|
|
228
|
-
self._api_key_cache = None
|
|
229
|
-
|
|
230
|
-
@property
|
|
231
|
-
def models(self):
|
|
232
|
-
class _ModelList:
|
|
233
|
-
def list(inner_self):
|
|
234
|
-
return TogetherImage.AVAILABLE_MODELS
|
|
235
|
-
|
|
236
|
-
return _ModelList()
|
|
237
|
-
|
|
238
|
-
def convert_model_name(self, model: str) -> str:
|
|
239
|
-
"""Convert model alias to full model name"""
|
|
240
|
-
if model in self.AVAILABLE_MODELS:
|
|
241
|
-
return model
|
|
242
|
-
|
|
243
|
-
# Default to first available model
|
|
244
|
-
return self.AVAILABLE_MODELS[0]
|
|
245
|
-
|
|
246
|
-
# def fetch_available_models(self) -> List[str]:
|
|
247
|
-
# """Fetch current image models from Together.xyz API"""
|
|
248
|
-
# try:
|
|
249
|
-
# api_key = self.images.get_api_key()
|
|
250
|
-
# headers = {
|
|
251
|
-
# "Authorization": f"Bearer {api_key}",
|
|
252
|
-
# "Accept": "application/json"
|
|
253
|
-
# }
|
|
254
|
-
|
|
255
|
-
# response = requests.get(
|
|
256
|
-
# "https://api.together.xyz/v1/models",
|
|
257
|
-
# headers=headers,
|
|
258
|
-
# timeout=30
|
|
259
|
-
# )
|
|
260
|
-
# response.raise_for_status()
|
|
261
|
-
# models_data = response.json()
|
|
262
|
-
|
|
263
|
-
# # Filter image models
|
|
264
|
-
# image_models = []
|
|
265
|
-
# for model in models_data:
|
|
266
|
-
# if isinstance(model, dict) and model.get("type", "").lower() == "image":
|
|
267
|
-
# image_models.append(model["id"])
|
|
268
|
-
|
|
269
|
-
# return sorted(image_models)
|
|
270
|
-
|
|
271
|
-
# except Exception as e:
|
|
272
|
-
# return self.AVAILABLE_MODELS
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
if __name__ == "__main__":
|
|
276
|
-
from rich import print
|
|
277
|
-
client = TogetherImage()
|
|
278
|
-
|
|
279
|
-
# Test with a sample prompt
|
|
280
|
-
response = client.images.create(
|
|
281
|
-
model="black-forest-labs/FLUX.1-schnell-Free", # Free FLUX model
|
|
282
|
-
prompt="A majestic dragon flying over a mystical forest, fantasy art, highly detailed",
|
|
283
|
-
size="1024x1024",
|
|
284
|
-
n=1,
|
|
285
|
-
steps=25,
|
|
286
|
-
response_format="url",
|
|
287
|
-
timeout=120,
|
|
288
|
-
)
|
|
1
|
+
import requests
|
|
2
|
+
import random
|
|
3
|
+
import string
|
|
4
|
+
import json
|
|
5
|
+
import time
|
|
6
|
+
from typing import Optional, List, Dict, Any
|
|
7
|
+
from webscout.Provider.TTI.utils import (
|
|
8
|
+
ImageData,
|
|
9
|
+
ImageResponse
|
|
10
|
+
)
|
|
11
|
+
from webscout.Provider.TTI.base import TTICompatibleProvider, BaseImages
|
|
12
|
+
from io import BytesIO
|
|
13
|
+
import os
|
|
14
|
+
import tempfile
|
|
15
|
+
from webscout.litagent import LitAgent
|
|
16
|
+
from requests.adapters import HTTPAdapter
|
|
17
|
+
from urllib3.util.retry import Retry
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class Images(BaseImages):
|
|
21
|
+
def __init__(self, client):
|
|
22
|
+
self._client = client
|
|
23
|
+
self.base_url = "https://api.together.xyz/v1"
|
|
24
|
+
# Create a session - it will automatically get proxies from the global monkey patch!
|
|
25
|
+
self.session = requests.Session()
|
|
26
|
+
self._setup_session_with_retries()
|
|
27
|
+
|
|
28
|
+
def _setup_session_with_retries(self):
|
|
29
|
+
"""Setup session with retry strategy and timeout configurations"""
|
|
30
|
+
# Configure retry strategy
|
|
31
|
+
retry_strategy = Retry(
|
|
32
|
+
total=3,
|
|
33
|
+
status_forcelist=[429, 500, 502, 503, 504],
|
|
34
|
+
backoff_factor=1,
|
|
35
|
+
allowed_methods=["HEAD", "GET", "OPTIONS", "POST"],
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
adapter = HTTPAdapter(max_retries=retry_strategy)
|
|
39
|
+
self.session.mount("http://", adapter)
|
|
40
|
+
self.session.mount("https://", adapter)
|
|
41
|
+
|
|
42
|
+
def get_api_key(self) -> str:
|
|
43
|
+
"""Get API key from activation endpoint or cache"""
|
|
44
|
+
if hasattr(self._client, '_api_key_cache') and self._client._api_key_cache:
|
|
45
|
+
return self._client._api_key_cache
|
|
46
|
+
|
|
47
|
+
try:
|
|
48
|
+
activation_endpoint = "https://www.codegeneration.ai/activate-v2"
|
|
49
|
+
response = requests.get(
|
|
50
|
+
activation_endpoint,
|
|
51
|
+
headers={"Accept": "application/json"},
|
|
52
|
+
timeout=30
|
|
53
|
+
)
|
|
54
|
+
response.raise_for_status()
|
|
55
|
+
activation_data = response.json()
|
|
56
|
+
api_key = activation_data["openAIParams"]["apiKey"]
|
|
57
|
+
self._client._api_key_cache = api_key
|
|
58
|
+
return api_key
|
|
59
|
+
except Exception as e:
|
|
60
|
+
raise Exception(f"Failed to get activation key: {e}")
|
|
61
|
+
|
|
62
|
+
def build_headers(self, extra: Optional[Dict[str, str]] = None) -> Dict[str, str]:
|
|
63
|
+
"""Build headers with API authorization"""
|
|
64
|
+
api_key = self.get_api_key()
|
|
65
|
+
|
|
66
|
+
agent = LitAgent()
|
|
67
|
+
fp = agent.generate_fingerprint("chrome")
|
|
68
|
+
headers = {
|
|
69
|
+
"Authorization": f"Bearer {api_key}",
|
|
70
|
+
"Content-Type": "application/json",
|
|
71
|
+
"accept": "application/json",
|
|
72
|
+
"accept-language": fp["accept_language"],
|
|
73
|
+
"user-agent": fp["user_agent"],
|
|
74
|
+
"sec-ch-ua": fp["sec_ch_ua"],
|
|
75
|
+
"sec-ch-ua-mobile": "?0",
|
|
76
|
+
"sec-ch-ua-platform": '"Windows"',
|
|
77
|
+
"sec-fetch-dest": "empty",
|
|
78
|
+
"sec-fetch-mode": "cors",
|
|
79
|
+
"sec-fetch-site": "cross-site",
|
|
80
|
+
}
|
|
81
|
+
if extra:
|
|
82
|
+
headers.update(extra)
|
|
83
|
+
return headers
|
|
84
|
+
|
|
85
|
+
def create(
|
|
86
|
+
self,
|
|
87
|
+
model: str = None,
|
|
88
|
+
prompt: str = None,
|
|
89
|
+
n: int = 1,
|
|
90
|
+
size: str = "1024x1024",
|
|
91
|
+
response_format: str = "url",
|
|
92
|
+
user: Optional[str] = None,
|
|
93
|
+
style: str = None,
|
|
94
|
+
aspect_ratio: str = None,
|
|
95
|
+
timeout: int = 120,
|
|
96
|
+
image_format: str = "png",
|
|
97
|
+
enhance: bool = True,
|
|
98
|
+
steps: int = 20,
|
|
99
|
+
seed: Optional[int] = None,
|
|
100
|
+
**kwargs,
|
|
101
|
+
) -> ImageResponse:
|
|
102
|
+
"""
|
|
103
|
+
Create images using Together.xyz image models
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
model: Image model to use (defaults to first available)
|
|
107
|
+
prompt: Text description of the image to generate
|
|
108
|
+
n: Number of images to generate (1-4)
|
|
109
|
+
size: Image size in format "WIDTHxHEIGHT"
|
|
110
|
+
response_format: "url" or "b64_json"
|
|
111
|
+
timeout: Request timeout in seconds
|
|
112
|
+
steps: Number of inference steps (1-50)
|
|
113
|
+
seed: Random seed for reproducible results
|
|
114
|
+
**kwargs: Additional model-specific parameters
|
|
115
|
+
"""
|
|
116
|
+
if not prompt:
|
|
117
|
+
raise ValueError(
|
|
118
|
+
"Describe the image you want to create (use the 'prompt' property)."
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
# Use provided model or default to first available
|
|
122
|
+
if not model:
|
|
123
|
+
model = self._client.AVAILABLE_MODELS[0]
|
|
124
|
+
elif model not in self._client.AVAILABLE_MODELS:
|
|
125
|
+
raise ValueError(f"Model '{model}' not available. Choose from: {self._client.AVAILABLE_MODELS}")
|
|
126
|
+
|
|
127
|
+
# Parse size
|
|
128
|
+
if 'x' in size:
|
|
129
|
+
width, height = map(int, size.split('x'))
|
|
130
|
+
else:
|
|
131
|
+
width = height = int(size)
|
|
132
|
+
|
|
133
|
+
# Build request body
|
|
134
|
+
body = {
|
|
135
|
+
"model": model,
|
|
136
|
+
"prompt": prompt,
|
|
137
|
+
"width": width,
|
|
138
|
+
"height": height,
|
|
139
|
+
# Clamp steps to 1-4 as required by Together.xyz API
|
|
140
|
+
"steps": min(max(steps, 1), 4),
|
|
141
|
+
"n": min(max(n, 1), 4), # Clamp between 1-4
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
# Add optional parameters
|
|
145
|
+
if seed is not None:
|
|
146
|
+
body["seed"] = seed
|
|
147
|
+
|
|
148
|
+
# Add any additional kwargs
|
|
149
|
+
body.update(kwargs)
|
|
150
|
+
|
|
151
|
+
try:
|
|
152
|
+
resp = self.session.request(
|
|
153
|
+
"post",
|
|
154
|
+
f"{self.base_url}/images/generations",
|
|
155
|
+
json=body,
|
|
156
|
+
headers=self.build_headers(),
|
|
157
|
+
timeout=timeout,
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
data = resp.json()
|
|
161
|
+
|
|
162
|
+
# Check for errors
|
|
163
|
+
if "error" in data:
|
|
164
|
+
error_msg = data["error"].get("message", str(data["error"]))
|
|
165
|
+
raise RuntimeError(f"Together.xyz API error: {error_msg}")
|
|
166
|
+
|
|
167
|
+
if not data.get("data") or len(data["data"]) == 0:
|
|
168
|
+
raise RuntimeError("Failed to process image. No data found.")
|
|
169
|
+
|
|
170
|
+
result = data["data"]
|
|
171
|
+
result_data = []
|
|
172
|
+
|
|
173
|
+
for i, item in enumerate(result):
|
|
174
|
+
if response_format == "url":
|
|
175
|
+
if "url" in item:
|
|
176
|
+
result_data.append(ImageData(url=item["url"]))
|
|
177
|
+
else: # b64_json
|
|
178
|
+
if "b64_json" in item:
|
|
179
|
+
result_data.append(ImageData(b64_json=item["b64_json"]))
|
|
180
|
+
|
|
181
|
+
if not result_data:
|
|
182
|
+
raise RuntimeError("No valid image data found in response")
|
|
183
|
+
|
|
184
|
+
return ImageResponse(data=result_data)
|
|
185
|
+
|
|
186
|
+
except requests.exceptions.Timeout:
|
|
187
|
+
raise RuntimeError(f"Request timed out after {timeout} seconds. Try reducing image size or steps.")
|
|
188
|
+
except requests.exceptions.RequestException as e:
|
|
189
|
+
# Print the response content for debugging if available
|
|
190
|
+
if hasattr(e, 'response') and e.response is not None:
|
|
191
|
+
try:
|
|
192
|
+
print("[Together.xyz API error details]", e.response.text)
|
|
193
|
+
except Exception:
|
|
194
|
+
pass
|
|
195
|
+
raise RuntimeError(f"Network error: {str(e)}")
|
|
196
|
+
except json.JSONDecodeError:
|
|
197
|
+
raise RuntimeError("Invalid JSON response from Together.xyz API")
|
|
198
|
+
except Exception as e:
|
|
199
|
+
raise RuntimeError(f"An error occurred: {str(e)}")
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
class TogetherImage(TTICompatibleProvider):
|
|
203
|
+
"""
|
|
204
|
+
Together.xyz Text-to-Image provider
|
|
205
|
+
Updated: 2025-08-01 10:42:41 UTC by OEvortex
|
|
206
|
+
Supports FLUX and other image generation models
|
|
207
|
+
"""
|
|
208
|
+
|
|
209
|
+
# Image models from Together.xyz API (filtered for image type only)
|
|
210
|
+
AVAILABLE_MODELS = [
|
|
211
|
+
"black-forest-labs/FLUX.1-canny",
|
|
212
|
+
"black-forest-labs/FLUX.1-depth",
|
|
213
|
+
"black-forest-labs/FLUX.1-dev",
|
|
214
|
+
"black-forest-labs/FLUX.1-dev-lora",
|
|
215
|
+
"black-forest-labs/FLUX.1-kontext-dev",
|
|
216
|
+
"black-forest-labs/FLUX.1-kontext-max",
|
|
217
|
+
"black-forest-labs/FLUX.1-kontext-pro",
|
|
218
|
+
"black-forest-labs/FLUX.1-krea-dev",
|
|
219
|
+
"black-forest-labs/FLUX.1-pro",
|
|
220
|
+
"black-forest-labs/FLUX.1-redux",
|
|
221
|
+
"black-forest-labs/FLUX.1-schnell",
|
|
222
|
+
"black-forest-labs/FLUX.1-schnell-Free",
|
|
223
|
+
"black-forest-labs/FLUX.1.1-pro"
|
|
224
|
+
]
|
|
225
|
+
|
|
226
|
+
def __init__(self):
|
|
227
|
+
self.images = Images(self)
|
|
228
|
+
self._api_key_cache = None
|
|
229
|
+
|
|
230
|
+
@property
|
|
231
|
+
def models(self):
|
|
232
|
+
class _ModelList:
|
|
233
|
+
def list(inner_self):
|
|
234
|
+
return TogetherImage.AVAILABLE_MODELS
|
|
235
|
+
|
|
236
|
+
return _ModelList()
|
|
237
|
+
|
|
238
|
+
def convert_model_name(self, model: str) -> str:
|
|
239
|
+
"""Convert model alias to full model name"""
|
|
240
|
+
if model in self.AVAILABLE_MODELS:
|
|
241
|
+
return model
|
|
242
|
+
|
|
243
|
+
# Default to first available model
|
|
244
|
+
return self.AVAILABLE_MODELS[0]
|
|
245
|
+
|
|
246
|
+
# def fetch_available_models(self) -> List[str]:
|
|
247
|
+
# """Fetch current image models from Together.xyz API"""
|
|
248
|
+
# try:
|
|
249
|
+
# api_key = self.images.get_api_key()
|
|
250
|
+
# headers = {
|
|
251
|
+
# "Authorization": f"Bearer {api_key}",
|
|
252
|
+
# "Accept": "application/json"
|
|
253
|
+
# }
|
|
254
|
+
|
|
255
|
+
# response = requests.get(
|
|
256
|
+
# "https://api.together.xyz/v1/models",
|
|
257
|
+
# headers=headers,
|
|
258
|
+
# timeout=30
|
|
259
|
+
# )
|
|
260
|
+
# response.raise_for_status()
|
|
261
|
+
# models_data = response.json()
|
|
262
|
+
|
|
263
|
+
# # Filter image models
|
|
264
|
+
# image_models = []
|
|
265
|
+
# for model in models_data:
|
|
266
|
+
# if isinstance(model, dict) and model.get("type", "").lower() == "image":
|
|
267
|
+
# image_models.append(model["id"])
|
|
268
|
+
|
|
269
|
+
# return sorted(image_models)
|
|
270
|
+
|
|
271
|
+
# except Exception as e:
|
|
272
|
+
# return self.AVAILABLE_MODELS
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
if __name__ == "__main__":
|
|
276
|
+
from rich import print
|
|
277
|
+
client = TogetherImage()
|
|
278
|
+
|
|
279
|
+
# Test with a sample prompt
|
|
280
|
+
response = client.images.create(
|
|
281
|
+
model="black-forest-labs/FLUX.1-schnell-Free", # Free FLUX model
|
|
282
|
+
prompt="A majestic dragon flying over a mystical forest, fantasy art, highly detailed",
|
|
283
|
+
size="1024x1024",
|
|
284
|
+
n=1,
|
|
285
|
+
steps=25,
|
|
286
|
+
response_format="url",
|
|
287
|
+
timeout=120,
|
|
288
|
+
)
|
|
289
289
|
print(response)
|
webscout/Provider/TTI/utils.py
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import time
|
|
2
|
-
from typing import List, Optional
|
|
3
|
-
from pydantic import BaseModel, Field
|
|
4
|
-
|
|
5
|
-
class ImageData(BaseModel):
|
|
6
|
-
url: Optional[str] = None
|
|
7
|
-
b64_json: Optional[str] = None
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class ImageResponse(BaseModel):
|
|
11
|
-
created: int = Field(default_factory=lambda: int(time.time()))
|
|
12
|
-
data: List[ImageData]
|
|
1
|
+
import time
|
|
2
|
+
from typing import List, Optional
|
|
3
|
+
from pydantic import BaseModel, Field
|
|
4
|
+
|
|
5
|
+
class ImageData(BaseModel):
|
|
6
|
+
url: Optional[str] = None
|
|
7
|
+
b64_json: Optional[str] = None
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ImageResponse(BaseModel):
|
|
11
|
+
created: int = Field(default_factory=lambda: int(time.time()))
|
|
12
|
+
data: List[ImageData]
|