Blackbox.py 30 KB

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