Blackbox.py 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652
  1. from __future__ import annotations
  2. from aiohttp import ClientSession
  3. import os
  4. import re
  5. import json
  6. import random
  7. import string
  8. import base64
  9. from pathlib import Path
  10. from typing import Optional
  11. from datetime import datetime, timedelta
  12. from ..typing import AsyncResult, Messages, MediaListType
  13. from ..requests.raise_for_status import raise_for_status
  14. from .base_provider import AsyncGeneratorProvider, ProviderModelMixin
  15. from ..image import to_data_uri
  16. from ..cookies import get_cookies_dir
  17. from .helper import format_prompt, format_image_prompt
  18. from ..providers.response import JsonConversation, ImageResponse
  19. from ..errors import ModelNotSupportedError
  20. from .. import debug
  21. class Conversation(JsonConversation):
  22. validated_value: str = None
  23. chat_id: str = None
  24. message_history: Messages = []
  25. def __init__(self, model: str):
  26. self.model = model
  27. class Blackbox(AsyncGeneratorProvider, ProviderModelMixin):
  28. label = "Blackbox AI"
  29. url = "https://www.blackbox.ai"
  30. api_endpoint = "https://www.blackbox.ai/api/chat"
  31. working = True
  32. supports_stream = True
  33. supports_system_message = True
  34. supports_message_history = True
  35. default_model = "blackboxai"
  36. default_vision_model = default_model
  37. default_image_model = 'flux'
  38. # Completely free models
  39. fallback_models = [
  40. "blackboxai",
  41. "blackboxai-pro",
  42. "gpt-4o-mini",
  43. "GPT-4o",
  44. "o1",
  45. "o3-mini",
  46. "Claude-sonnet-3.7",
  47. "DeepSeek-V3",
  48. "DeepSeek-R1",
  49. "DeepSeek-LLM-Chat-(67B)",
  50. # Image models
  51. "flux",
  52. # Trending agent modes
  53. 'Python Agent',
  54. 'HTML Agent',
  55. 'Builder Agent',
  56. 'Java Agent',
  57. 'JavaScript Agent',
  58. 'React Agent',
  59. 'Android Agent',
  60. 'Flutter Agent',
  61. 'Next.js Agent',
  62. 'AngularJS Agent',
  63. 'Swift Agent',
  64. 'MongoDB Agent',
  65. 'PyTorch Agent',
  66. 'Xcode Agent',
  67. 'Azure Agent',
  68. 'Bitbucket Agent',
  69. 'DigitalOcean Agent',
  70. 'Docker Agent',
  71. 'Electron Agent',
  72. 'Erlang Agent',
  73. 'FastAPI Agent',
  74. 'Firebase Agent',
  75. 'Flask Agent',
  76. 'Git Agent',
  77. 'Gitlab Agent',
  78. 'Go Agent',
  79. 'Godot Agent',
  80. 'Google Cloud Agent',
  81. 'Heroku Agent'
  82. ]
  83. image_models = [default_image_model]
  84. vision_models = [default_vision_model, 'GPT-4o', 'o1', 'o3-mini', 'Gemini-PRO', 'Gemini Agent', 'llama-3.1-8b Agent', 'llama-3.1-70b Agent', 'llama-3.1-405 Agent', 'Gemini-Flash-2.0', 'DeepSeek-V3']
  85. userSelectedModel = ['GPT-4o', 'o1', 'o3-mini', 'Gemini-PRO', 'Claude-sonnet-3.7', 'DeepSeek-V3', 'DeepSeek-R1', 'Meta-Llama-3.3-70B-Instruct-Turbo', 'Mistral-Small-24B-Instruct-2501', 'DeepSeek-LLM-Chat-(67B)', 'DBRX-Instruct', 'Qwen-QwQ-32B-Preview', 'Nous-Hermes-2-Mixtral-8x7B-DPO', 'Gemini-Flash-2.0']
  86. # Agent mode configurations
  87. agentMode = {
  88. 'GPT-4o': {'mode': True, 'id': "GPT-4o", 'name': "GPT-4o"},
  89. 'Gemini-PRO': {'mode': True, 'id': "Gemini-PRO", 'name': "Gemini-PRO"},
  90. 'Claude-sonnet-3.7': {'mode': True, 'id': "Claude-sonnet-3.7", 'name': "Claude-sonnet-3.7"},
  91. 'DeepSeek-V3': {'mode': True, 'id': "deepseek-chat", 'name': "DeepSeek-V3"},
  92. 'DeepSeek-R1': {'mode': True, 'id': "deepseek-reasoner", 'name': "DeepSeek-R1"},
  93. 'Meta-Llama-3.3-70B-Instruct-Turbo': {'mode': True, 'id': "meta-llama/Llama-3.3-70B-Instruct-Turbo", 'name': "Meta-Llama-3.3-70B-Instruct-Turbo"},
  94. 'Gemini-Flash-2.0': {'mode': True, 'id': "Gemini/Gemini-Flash-2.0", 'name': "Gemini-Flash-2.0"},
  95. 'Mistral-Small-24B-Instruct-2501': {'mode': True, 'id': "mistralai/Mistral-Small-24B-Instruct-2501", 'name': "Mistral-Small-24B-Instruct-2501"},
  96. 'DeepSeek-LLM-Chat-(67B)': {'mode': True, 'id': "deepseek-ai/deepseek-llm-67b-chat", 'name': "DeepSeek-LLM-Chat-(67B)"},
  97. 'DBRX-Instruct': {'mode': True, 'id': "databricks/dbrx-instruct", 'name': "DBRX-Instruct"},
  98. 'Qwen-QwQ-32B-Preview': {'mode': True, 'id': "Qwen/QwQ-32B-Preview", 'name': "Qwen-QwQ-32B-Preview"},
  99. 'Nous-Hermes-2-Mixtral-8x7B-DPO': {'mode': True, 'id': "NousResearch/Nous-Hermes-2-Mixtral-8x7B-DPO", 'name': "Nous-Hermes-2-Mixtral-8x7B-DPO"},
  100. }
  101. # Trending agent modes
  102. trendingAgentMode = {
  103. 'blackboxai-pro': {'mode': True, 'id': "BLACKBOXAI-PRO"},
  104. "Gemini Agent": {'mode': True, 'id': 'gemini'},
  105. "llama-3.1-405 Agent": {'mode': True, 'id': "llama-3.1-405"},
  106. 'llama-3.1-70b Agent': {'mode': True, 'id': "llama-3.1-70b"},
  107. 'llama-3.1-8b Agent': {'mode': True, 'id': "llama-3.1-8b"},
  108. 'Python Agent': {'mode': True, 'id': "python"},
  109. 'HTML Agent': {'mode': True, 'id': "html"},
  110. 'Builder Agent': {'mode': True, 'id': "builder"},
  111. 'Java Agent': {'mode': True, 'id': "java"},
  112. 'JavaScript Agent': {'mode': True, 'id': "javascript"},
  113. 'React Agent': {'mode': True, 'id': "react"},
  114. 'Android Agent': {'mode': True, 'id': "android"},
  115. 'Flutter Agent': {'mode': True, 'id': "flutter"},
  116. 'Next.js Agent': {'mode': True, 'id': "next.js"},
  117. 'AngularJS Agent': {'mode': True, 'id': "angularjs"},
  118. 'Swift Agent': {'mode': True, 'id': "swift"},
  119. 'MongoDB Agent': {'mode': True, 'id': "mongodb"},
  120. 'PyTorch Agent': {'mode': True, 'id': "pytorch"},
  121. 'Xcode Agent': {'mode': True, 'id': "xcode"},
  122. 'Azure Agent': {'mode': True, 'id': "azure"},
  123. 'Bitbucket Agent': {'mode': True, 'id': "bitbucket"},
  124. 'DigitalOcean Agent': {'mode': True, 'id': "digitalocean"},
  125. 'Docker Agent': {'mode': True, 'id': "docker"},
  126. 'Electron Agent': {'mode': True, 'id': "electron"},
  127. 'Erlang Agent': {'mode': True, 'id': "erlang"},
  128. 'FastAPI Agent': {'mode': True, 'id': "fastapi"},
  129. 'Firebase Agent': {'mode': True, 'id': "firebase"},
  130. 'Flask Agent': {'mode': True, 'id': "flask"},
  131. 'Git Agent': {'mode': True, 'id': "git"},
  132. 'Gitlab Agent': {'mode': True, 'id': "gitlab"},
  133. 'Go Agent': {'mode': True, 'id': "go"},
  134. 'Godot Agent': {'mode': True, 'id': "godot"},
  135. 'Google Cloud Agent': {'mode': True, 'id': "googlecloud"},
  136. 'Heroku Agent': {'mode': True, 'id': "heroku"},
  137. }
  138. # Complete list of all models (for authorized users)
  139. _all_models = list(dict.fromkeys([
  140. default_model,
  141. *userSelectedModel,
  142. *image_models,
  143. *list(agentMode.keys()),
  144. *list(trendingAgentMode.keys())
  145. ]))
  146. @classmethod
  147. def generate_session(cls, id_length: int = 21, days_ahead: int = 365) -> dict:
  148. """
  149. Generate a dynamic session with proper ID and expiry format.
  150. Args:
  151. id_length: Length of the numeric ID (default: 21)
  152. days_ahead: Number of days ahead for expiry (default: 365)
  153. Returns:
  154. dict: A session dictionary with user information and expiry
  155. """
  156. # Generate numeric ID
  157. numeric_id = ''.join(random.choice('0123456789') for _ in range(id_length))
  158. # Generate future expiry date
  159. future_date = datetime.now() + timedelta(days=days_ahead)
  160. expiry = future_date.strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'
  161. # Decode the encoded email
  162. encoded_email = "Z2lzZWxlQGJsYWNrYm94LmFp" # Base64 encoded email
  163. email = base64.b64decode(encoded_email).decode('utf-8')
  164. # Generate random image ID for the new URL format
  165. chars = string.ascii_letters + string.digits + "-"
  166. random_img_id = ''.join(random.choice(chars) for _ in range(48))
  167. image_url = f"https://lh3.googleusercontent.com/a/ACg8oc{random_img_id}=s96-c"
  168. return {
  169. "user": {
  170. "name": "BLACKBOX AI",
  171. "email": email,
  172. "image": image_url,
  173. "id": numeric_id
  174. },
  175. "expires": expiry
  176. }
  177. @classmethod
  178. async def fetch_validated(cls, url: str = "https://www.blackbox.ai", force_refresh: bool = False) -> Optional[str]:
  179. cache_file = Path(get_cookies_dir()) / 'blackbox.json'
  180. if not force_refresh and cache_file.exists():
  181. try:
  182. with open(cache_file, 'r') as f:
  183. data = json.load(f)
  184. if data.get('validated_value'):
  185. return data['validated_value']
  186. except Exception as e:
  187. debug.log(f"Blackbox: Error reading cache: {e}")
  188. js_file_pattern = r'static/chunks/\d{4}-[a-fA-F0-9]+\.js'
  189. uuid_pattern = r'["\']([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})["\']'
  190. def is_valid_context(text: str) -> bool:
  191. return any(char + '=' in text for char in 'abcdefghijklmnopqrstuvwxyz')
  192. async with ClientSession() as session:
  193. try:
  194. async with session.get(url) as response:
  195. if response.status != 200:
  196. return None
  197. page_content = await response.text()
  198. js_files = re.findall(js_file_pattern, page_content)
  199. for js_file in js_files:
  200. js_url = f"{url}/_next/{js_file}"
  201. async with session.get(js_url) as js_response:
  202. if js_response.status == 200:
  203. js_content = await js_response.text()
  204. for match in re.finditer(uuid_pattern, js_content):
  205. start = max(0, match.start() - 10)
  206. end = min(len(js_content), match.end() + 10)
  207. context = js_content[start:end]
  208. if is_valid_context(context):
  209. validated_value = match.group(1)
  210. cache_file.parent.mkdir(exist_ok=True)
  211. try:
  212. with open(cache_file, 'w') as f:
  213. json.dump({'validated_value': validated_value}, f)
  214. except Exception as e:
  215. debug.log(f"Blackbox: Error writing cache: {e}")
  216. return validated_value
  217. except Exception as e:
  218. debug.log(f"Blackbox: Error retrieving validated_value: {e}")
  219. return None
  220. @classmethod
  221. def generate_id(cls, length: int = 7) -> str:
  222. chars = string.ascii_letters + string.digits
  223. return ''.join(random.choice(chars) for _ in range(length))
  224. @classmethod
  225. def get_models(cls) -> list:
  226. """
  227. Returns a list of available models based on authorization status.
  228. Authorized users get the full list of models.
  229. Unauthorized users only get fallback_models.
  230. """
  231. # Check if there are valid session data in HAR files
  232. has_premium_access = cls._check_premium_access()
  233. if has_premium_access:
  234. # For authorized users - all models
  235. debug.log(f"Blackbox: Returning full model list with {len(cls._all_models)} models")
  236. return cls._all_models
  237. else:
  238. # For demo accounts - only free models
  239. debug.log(f"Blackbox: Returning free model list with {len(cls.fallback_models)} models")
  240. return cls.fallback_models
  241. @classmethod
  242. def _check_premium_access(cls) -> bool:
  243. """
  244. Checks for an authorized session in HAR files.
  245. Returns True if a valid session is found that differs from the demo.
  246. """
  247. try:
  248. har_dir = get_cookies_dir()
  249. if not os.access(har_dir, os.R_OK):
  250. return False
  251. for root, _, files in os.walk(har_dir):
  252. for file in files:
  253. if file.endswith(".har"):
  254. try:
  255. with open(os.path.join(root, file), 'rb') as f:
  256. har_data = json.load(f)
  257. for entry in har_data['log']['entries']:
  258. # Only check requests to blackbox API
  259. if 'blackbox.ai/api' in entry['request']['url']:
  260. if 'response' in entry and 'content' in entry['response']:
  261. content = entry['response']['content']
  262. if ('text' in content and
  263. isinstance(content['text'], str) and
  264. '"user"' in content['text'] and
  265. '"email"' in content['text']):
  266. try:
  267. # Process request text
  268. text = content['text'].strip()
  269. if text.startswith('{') and text.endswith('}'):
  270. text = text.replace('\\"', '"')
  271. session_data = json.loads(text)
  272. # Check if this is a valid session
  273. if (isinstance(session_data, dict) and
  274. 'user' in session_data and
  275. 'email' in session_data['user']):
  276. # Check if this is not a demo session
  277. demo_session = cls.generate_session()
  278. if (session_data['user'].get('email') !=
  279. demo_session['user'].get('email')):
  280. # This is not a demo session, so user has premium access
  281. return True
  282. except:
  283. pass
  284. except:
  285. pass
  286. return False
  287. except Exception as e:
  288. debug.log(f"Blackbox: Error checking premium access: {e}")
  289. return False
  290. # Initialize models with fallback_models
  291. models = fallback_models
  292. model_aliases = {
  293. "gpt-4o": "GPT-4o",
  294. "claude-3.7-sonnet": "Claude-sonnet-3.7",
  295. "deepseek-v3": "DeepSeek-V3",
  296. "deepseek-r1": "DeepSeek-R1",
  297. "deepseek-chat": "DeepSeek-LLM-Chat-(67B)",
  298. }
  299. @classmethod
  300. def generate_session(cls, id_length: int = 21, days_ahead: int = 365) -> dict:
  301. """
  302. Generate a dynamic session with proper ID and expiry format.
  303. Args:
  304. id_length: Length of the numeric ID (default: 21)
  305. days_ahead: Number of days ahead for expiry (default: 365)
  306. Returns:
  307. dict: A session dictionary with user information and expiry
  308. """
  309. # Generate numeric ID
  310. numeric_id = ''.join(random.choice('0123456789') for _ in range(id_length))
  311. # Generate future expiry date
  312. future_date = datetime.now() + timedelta(days=days_ahead)
  313. expiry = future_date.strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'
  314. # Decode the encoded email
  315. encoded_email = "Z2lzZWxlQGJsYWNrYm94LmFp" # Base64 encoded email
  316. email = base64.b64decode(encoded_email).decode('utf-8')
  317. # Generate random image ID for the new URL format
  318. chars = string.ascii_letters + string.digits + "-"
  319. random_img_id = ''.join(random.choice(chars) for _ in range(48))
  320. image_url = f"https://lh3.googleusercontent.com/a/ACg8oc{random_img_id}=s96-c"
  321. return {
  322. "user": {
  323. "name": "BLACKBOX AI",
  324. "email": email,
  325. "image": image_url,
  326. "id": numeric_id
  327. },
  328. "expires": expiry
  329. }
  330. @classmethod
  331. async def fetch_validated(cls, url: str = "https://www.blackbox.ai", force_refresh: bool = False) -> Optional[str]:
  332. cache_file = Path(get_cookies_dir()) / 'blackbox.json'
  333. if not force_refresh and cache_file.exists():
  334. try:
  335. with open(cache_file, 'r') as f:
  336. data = json.load(f)
  337. if data.get('validated_value'):
  338. return data['validated_value']
  339. except Exception as e:
  340. debug.log(f"Blackbox: Error reading cache: {e}")
  341. js_file_pattern = r'static/chunks/\d{4}-[a-fA-F0-9]+\.js'
  342. uuid_pattern = r'["\']([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})["\']'
  343. def is_valid_context(text: str) -> bool:
  344. return any(char + '=' in text for char in 'abcdefghijklmnopqrstuvwxyz')
  345. async with ClientSession() as session:
  346. try:
  347. async with session.get(url) as response:
  348. if response.status != 200:
  349. return None
  350. page_content = await response.text()
  351. js_files = re.findall(js_file_pattern, page_content)
  352. for js_file in js_files:
  353. js_url = f"{url}/_next/{js_file}"
  354. async with session.get(js_url) as js_response:
  355. if js_response.status == 200:
  356. js_content = await js_response.text()
  357. for match in re.finditer(uuid_pattern, js_content):
  358. start = max(0, match.start() - 10)
  359. end = min(len(js_content), match.end() + 10)
  360. context = js_content[start:end]
  361. if is_valid_context(context):
  362. validated_value = match.group(1)
  363. cache_file.parent.mkdir(exist_ok=True)
  364. try:
  365. with open(cache_file, 'w') as f:
  366. json.dump({'validated_value': validated_value}, f)
  367. except Exception as e:
  368. debug.log(f"Blackbox: Error writing cache: {e}")
  369. return validated_value
  370. except Exception as e:
  371. debug.log(f"Blackbox: Error retrieving validated_value: {e}")
  372. return None
  373. @classmethod
  374. def generate_id(cls, length: int = 7) -> str:
  375. chars = string.ascii_letters + string.digits
  376. return ''.join(random.choice(chars) for _ in range(length))
  377. @classmethod
  378. async def create_async_generator(
  379. cls,
  380. model: str,
  381. messages: Messages,
  382. prompt: str = None,
  383. proxy: str = None,
  384. media: MediaListType = None,
  385. top_p: float = None,
  386. temperature: float = None,
  387. max_tokens: int = None,
  388. conversation: Conversation = None,
  389. return_conversation: bool = False,
  390. **kwargs
  391. ) -> AsyncResult:
  392. model = cls.get_model(model)
  393. headers = {
  394. 'accept': '*/*',
  395. 'accept-language': 'en-US,en;q=0.9',
  396. 'content-type': 'application/json',
  397. 'origin': 'https://www.blackbox.ai',
  398. 'referer': 'https://www.blackbox.ai/',
  399. 'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36'
  400. }
  401. async with ClientSession(headers=headers) as session:
  402. if conversation is None or not hasattr(conversation, "chat_id"):
  403. conversation = Conversation(model)
  404. conversation.validated_value = await cls.fetch_validated()
  405. conversation.chat_id = cls.generate_id()
  406. conversation.message_history = []
  407. current_messages = []
  408. for i, msg in enumerate(messages):
  409. msg_id = conversation.chat_id if i == 0 and msg["role"] == "user" else cls.generate_id()
  410. current_msg = {
  411. "id": msg_id,
  412. "content": msg["content"],
  413. "role": msg["role"]
  414. }
  415. current_messages.append(current_msg)
  416. if media is not None:
  417. current_messages[-1]['data'] = {
  418. "imagesData": [
  419. {
  420. "filePath": f"/{image_name}",
  421. "contents": to_data_uri(image)
  422. }
  423. for image, image_name in media
  424. ],
  425. "fileText": "",
  426. "title": ""
  427. }
  428. # Try to get session data from HAR files
  429. session_data = cls.generate_session() # Default fallback
  430. session_found = False
  431. # Look for HAR session data
  432. har_dir = get_cookies_dir()
  433. if os.access(har_dir, os.R_OK):
  434. for root, _, files in os.walk(har_dir):
  435. for file in files:
  436. if file.endswith(".har"):
  437. try:
  438. with open(os.path.join(root, file), 'rb') as f:
  439. har_data = json.load(f)
  440. for entry in har_data['log']['entries']:
  441. # Only look at blackbox API responses
  442. if 'blackbox.ai/api' in entry['request']['url']:
  443. # Look for a response that has the right structure
  444. if 'response' in entry and 'content' in entry['response']:
  445. content = entry['response']['content']
  446. # Look for both regular and Google auth session formats
  447. if ('text' in content and
  448. isinstance(content['text'], str) and
  449. '"user"' in content['text'] and
  450. '"email"' in content['text'] and
  451. '"expires"' in content['text']):
  452. try:
  453. # Remove any HTML or other non-JSON content
  454. text = content['text'].strip()
  455. if text.startswith('{') and text.endswith('}'):
  456. # Replace escaped quotes
  457. text = text.replace('\\"', '"')
  458. har_session = json.loads(text)
  459. # Check if this is a valid session object (supports both regular and Google auth)
  460. if (isinstance(har_session, dict) and
  461. 'user' in har_session and
  462. 'email' in har_session['user'] and
  463. 'expires' in har_session):
  464. file_path = os.path.join(root, file)
  465. debug.log(f"Blackbox: Found session in HAR file")
  466. session_data = har_session
  467. session_found = True
  468. break
  469. except json.JSONDecodeError as e:
  470. # Only print error for entries that truly look like session data
  471. if ('"user"' in content['text'] and
  472. '"email"' in content['text']):
  473. debug.log(f"Blackbox: Error parsing likely session data: {e}")
  474. if session_found:
  475. break
  476. except Exception as e:
  477. debug.log(f"Blackbox: Error reading HAR file: {e}")
  478. if session_found:
  479. break
  480. if session_found:
  481. break
  482. data = {
  483. "messages": current_messages,
  484. "agentMode": cls.agentMode.get(model, {}) if model in cls.agentMode else {},
  485. "id": conversation.chat_id,
  486. "previewToken": None,
  487. "userId": None,
  488. "codeModelMode": True,
  489. "trendingAgentMode": cls.trendingAgentMode.get(model, {}) if model in cls.trendingAgentMode else {},
  490. "isMicMode": False,
  491. "userSystemPrompt": None,
  492. "maxTokens": max_tokens,
  493. "playgroundTopP": top_p,
  494. "playgroundTemperature": temperature,
  495. "isChromeExt": False,
  496. "githubToken": "",
  497. "clickedAnswer2": False,
  498. "clickedAnswer3": False,
  499. "clickedForceWebSearch": False,
  500. "visitFromDelta": False,
  501. "isMemoryEnabled": False,
  502. "mobileClient": False,
  503. "userSelectedModel": model if model in cls.userSelectedModel else None,
  504. "validated": conversation.validated_value,
  505. "imageGenerationMode": model == cls.default_image_model,
  506. "webSearchModePrompt": False,
  507. "deepSearchMode": False,
  508. "domains": None,
  509. "vscodeClient": False,
  510. "codeInterpreterMode": False,
  511. "customProfile": {
  512. "name": "",
  513. "occupation": "",
  514. "traits": [],
  515. "additionalInfo": "",
  516. "enableNewChats": False
  517. },
  518. "session": session_data if session_data else cls.generate_session(),
  519. "isPremium": True,
  520. "subscriptionCache": None,
  521. "beastMode": False,
  522. "webSearchMode": False
  523. }
  524. # Add debugging before making the API call
  525. if isinstance(session_data, dict) and 'user' in session_data:
  526. # Генеруємо демо-сесію для порівняння
  527. demo_session = cls.generate_session()
  528. is_demo = False
  529. if demo_session and isinstance(demo_session, dict) and 'user' in demo_session:
  530. if session_data['user'].get('email') == demo_session['user'].get('email'):
  531. is_demo = True
  532. if is_demo:
  533. debug.log(f"Blackbox: Making API request with built-in Developer Premium Account")
  534. else:
  535. user_email = session_data['user'].get('email', 'unknown')
  536. debug.log(f"Blackbox: Making API request with HAR session email: {user_email}")
  537. # Continue with the API request and async generator behavior
  538. async with session.post(cls.api_endpoint, json=data, proxy=proxy) as response:
  539. await raise_for_status(response)
  540. # Collect the full response
  541. full_response = []
  542. async for chunk in response.content.iter_any():
  543. if chunk:
  544. chunk_text = chunk.decode()
  545. full_response.append(chunk_text)
  546. # Only yield chunks for non-image models
  547. if model != cls.default_image_model:
  548. yield chunk_text
  549. full_response_text = ''.join(full_response)
  550. # For image models, check for image markdown
  551. if model == cls.default_image_model:
  552. image_url_match = re.search(r'!\[.*?\]\((.*?)\)', full_response_text)
  553. if image_url_match:
  554. image_url = image_url_match.group(1)
  555. yield ImageResponse(images=[image_url], alt=format_image_prompt(messages, prompt))
  556. return
  557. # Handle conversation history once, in one place
  558. if return_conversation:
  559. conversation.message_history.append({"role": "assistant", "content": full_response_text})
  560. yield conversation
  561. # For image models that didn't produce an image, fall back to text response
  562. elif model == cls.default_image_model:
  563. yield full_response_text