rkihacker commited on
Commit
f4d92a9
·
verified ·
1 Parent(s): 0d1e277

Update api/utils.py

Browse files
Files changed (1) hide show
  1. api/utils.py +272 -133
api/utils.py CHANGED
@@ -5,7 +5,7 @@ import re
5
  import string
6
  import time
7
  import uuid
8
- from datetime import datetime, timezone, timedelta
9
  from typing import Any, Dict, List, Optional
10
 
11
  import boto3
@@ -52,15 +52,15 @@ BLOCKED_MESSAGE = (
52
  )
53
 
54
  # ---------------------------------------------
55
- # RANDOM USER-DATA & SESSION GENERATION
56
  # ---------------------------------------------
57
  def get_random_name_email_customer():
58
  first_names = ["Aliace", "B21ob", "Car232ol", "Daavid", "Evewwlyn", "Fraank", "Grssace", "Hefctor", "Ivgy", "Jackdie"]
59
- last_names = ["Smilth", "Johnkson", "Dajvis", "Mihller", "Thomgpson", "Garwcia", "Broawn", "Wilfson", "Maartin", "Clarak"]
60
 
61
  random_name = f"{random.choice(first_names)} {random.choice(last_names)}"
62
  email_username = ''.join(random.choices(string.ascii_lowercase + string.digits, k=8))
63
- random_email = f"niansuhtech@gmail.com"
64
  suffix_length = len("Rldf7IKdNhdhiw")
65
  suffix_chars = string.ascii_letters + string.digits
66
  random_suffix = ''.join(random.choice(suffix_chars) for _ in range(suffix_length))
@@ -68,38 +68,9 @@ def get_random_name_email_customer():
68
 
69
  return random_name, random_email, random_customer_id
70
 
71
- def generate_session(email: str, id_length: int = 21, days_ahead: int = 365) -> dict:
72
- numeric_id = ''.join(random.choice('0123456789') for _ in range(id_length))
73
- future_date = datetime.now(timezone.utc) + timedelta(days=days_ahead)
74
- expiry = future_date.isoformat(timespec='milliseconds').replace('+00:00', 'Z')
75
-
76
- chars = string.ascii_letters + string.digits + "-"
77
- random_img_id = ''.join(random.choice(chars) for _ in range(48))
78
- image_url = f"https://lh3.googleusercontent.com/a/ACg8oc{random_img_id}=s96-c"
79
-
80
- return {
81
- "user": {
82
- "name": "SNAPZION",
83
- "email": email,
84
- "image": image_url,
85
- "id": numeric_id
86
- },
87
- "expires": expiry,
88
- "isNewUser": False
89
- }
90
-
91
- def generate_session_data() -> dict:
92
- _, email, _ = get_random_name_email_customer()
93
- session_data = generate_session(email)
94
- logger.info(f"Using generated session with email {email}")
95
- return session_data
96
-
97
- # ---------------------------------------------
98
- # HELPER FUNCTIONS
99
- # ---------------------------------------------
100
  def generate_system_fingerprint() -> str:
101
- raw = f"{platform.node()}-{time.time()}-{uuid.uuid4()}"
102
- short_hash = hashlib.md5(raw.encode()).hexdigest()[:12]
103
  return f"fp_{short_hash}"
104
 
105
  def get_last_user_prompt(messages: List[Any]) -> str:
@@ -115,36 +86,43 @@ def get_last_user_prompt(messages: List[Any]) -> str:
115
 
116
  def upload_replaced_urls_to_r2(urls: List[str], alt_text: str = "") -> None:
117
  if not urls:
118
- logger.info("No replaced or final URLs to store.")
119
  return
120
- existing = ""
 
121
  try:
122
- resp = s3.get_object(Bucket=R2_BUCKET_NAME, Key=R2_REPLACED_URLS_KEY)
123
- existing = resp["Body"].read().decode()
 
124
  except s3.exceptions.NoSuchKey:
125
- pass
126
  except Exception as e:
127
- logger.error(f"Error reading {R2_REPLACED_URLS_KEY}: {e}")
128
 
129
- markdown = "\n".join(f"![{alt_text}]({u})" for u in urls)
130
- content = f"{existing}\n{markdown}" if existing.strip() else markdown
 
 
 
131
 
132
  try:
133
  s3.put_object(
134
  Bucket=R2_BUCKET_NAME,
135
  Key=R2_REPLACED_URLS_KEY,
136
- Body=content.encode(),
137
  ContentType="text/plain",
138
  )
139
- logger.info(f"Appended {len(urls)} URLs to {R2_REPLACED_URLS_KEY}.")
140
  except Exception as e:
141
- logger.error(f"Error writing {R2_REPLACED_URLS_KEY}: {e}")
142
 
143
  def calculate_tokens(text: str, model: str) -> int:
144
  try:
145
- enc = tiktoken.encoding_for_model(model)
146
- return len(enc.encode(text))
147
- except Exception:
 
 
148
  return len(text.split())
149
 
150
  def create_chat_completion_data(
@@ -166,20 +144,22 @@ def create_chat_completion_data(
166
  }
167
  return {
168
  "id": request_id,
169
- "object": "chat.completion.chunk",
170
  "created": timestamp,
171
  "model": model,
172
  "system_fingerprint": system_fingerprint,
173
- "choices": [{"index": 0, "delta": {"content": content, "role": "assistant"}, "finish_reason": finish_reason}],
 
 
 
 
 
 
 
174
  "usage": usage,
175
  }
176
 
177
  def message_to_dict(message, model_prefix: Optional[str] = None):
178
- """
179
- Convert a ChatRequest message to a dict for the request payload.
180
- Supports up to three images with type-based structure and sends multiple formats.
181
- Prepends model_prefix to text content if specified.
182
- """
183
  content = ""
184
  images_data = []
185
  image_urls = []
@@ -189,11 +169,11 @@ def message_to_dict(message, model_prefix: Optional[str] = None):
189
  if item.get("type") == "text":
190
  content = item.get("text", "").strip()
191
  elif item.get("type") == "image_url" and len(images_data) < 3:
192
- url = item["image_url"].get("url", "")
193
- if url:
194
- path = f"MultipleFiles/{uuid.uuid4().hex}.jpg"
195
- images_data.append({"filePath": path, "contents": url})
196
- image_urls.append({"image_url": {"url": url}})
197
  elif isinstance(message.content, str):
198
  content = message.content.strip()
199
 
@@ -208,14 +188,14 @@ def message_to_dict(message, model_prefix: Optional[str] = None):
208
  "title": "snapshot",
209
  "imagesData": images_data
210
  }
211
- # embed any extra URLs in content list
212
- for extra in image_urls[1:]:
213
- base.setdefault("content", []).append(extra)
214
 
215
  return base
216
 
217
  def strip_model_prefix(content: str, model_prefix: Optional[str] = None) -> str:
218
  if model_prefix and content.startswith(model_prefix):
 
219
  return content[len(model_prefix):].strip()
220
  return content
221
 
@@ -223,23 +203,29 @@ def strip_model_prefix(content: str, model_prefix: Optional[str] = None) -> str:
223
  # STREAMING RESPONSE HANDLER
224
  # ---------------------------------------------
225
  async def process_streaming_response(request: ChatRequest):
226
- system_fp = generate_system_fingerprint()
 
 
 
 
 
227
  request_id = f"chatcmpl-{uuid.uuid4()}"
228
- logger.info(f"Processing (stream) {request_id} - Model: {request.model}")
229
 
230
  agent_mode = AGENT_MODE.get(request.model, {})
231
- trending_mode = TRENDING_AGENT_MODE.get(request.model, {})
232
- prefix = MODEL_PREFIXES.get(request.model, "")
233
 
234
- headers_api = get_headers_api_chat(BASE_URL)
235
  if request.model == "o1-preview":
236
  await asyncio.sleep(random.randint(1, 60))
237
 
238
- h = await getHid()
239
- if not h:
 
240
  raise HTTPException(status_code=500, detail="Missing h-value.")
241
 
242
- msgs = [message_to_dict(m, prefix) for m in request.messages]
243
 
244
  json_data = {
245
  "agentMode": agent_mode,
@@ -259,41 +245,75 @@ async def process_streaming_response(request: ChatRequest):
259
  "isPremium": True,
260
  "isMemoryEnabled": False,
261
  "maxTokens": request.max_tokens,
262
- "messages": msgs,
263
  "mobileClient": False,
264
  "playgroundTemperature": request.temperature,
265
  "playgroundTopP": request.top_p,
266
  "previewToken": None,
267
- "trendingAgentMode": trending_mode,
268
  "userId": None,
269
  "userSelectedModel": MODEL_MAPPING.get(request.model, request.model),
270
  "userSystemPrompt": None,
271
- "validated": h,
272
  "visitFromDelta": False,
273
  "webSearchModePrompt": False,
274
  "vscodeClient": False,
275
  "designerMode": False,
276
  "workspaceId": "",
277
  "beastMode": False,
278
- "customProfile": {"name": "", "occupation": "", "traits": [], "additionalInfo": "", "enableNewChats": False},
279
- "webSearchModeOption": {"autoMode": False, "webMode": False, "offlineMode": True},
280
- "session": generate_session_data(),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
281
  }
282
 
283
  prompt_tokens = sum(
284
- calculate_tokens(m.get("content", ""), request.model) +
285
- sum(calculate_tokens(img["contents"], request.model) for img in m.get("data", {}).get("imagesData", []))
286
- for m in msgs
287
  )
288
-
289
  completion_tokens = 0
290
- final_links: List[str] = []
291
 
292
  async with httpx.AsyncClient() as client:
293
  try:
294
- async with client.stream("POST", f"{BASE_URL}/api/chat", headers=headers_api, json=json_data, timeout=100) as resp:
295
- resp.raise_for_status()
296
- async for chunk in resp.aiter_text():
 
 
 
 
 
 
297
  if not chunk:
298
  continue
299
  if chunk.startswith("$@$v=undefined-rv1$@$"):
@@ -302,48 +322,92 @@ async def process_streaming_response(request: ChatRequest):
302
  chunk = chunk.replace(BLOCKED_MESSAGE, "").strip()
303
  if not chunk:
304
  continue
305
- chunk = chunk.replace("https://storage.googleapis.com", "https://cdn.snapzion.com")
306
- links = re.findall(r"(https://cdn\.snapzion\.com[^\s\)]+)", chunk)
307
- final_links.extend(links)
308
- clean = strip_model_prefix(chunk, prefix)
309
- completion_tokens += calculate_tokens(clean, request.model)
310
- ts = int(datetime.now().timestamp())
311
  yield "data: " + json.dumps(
312
- create_chat_completion_data(clean, request.model, ts, request_id, system_fp, prompt_tokens, completion_tokens)
 
 
313
  ) + "\n\n"
314
 
315
- ts = int(datetime.now().timestamp())
316
  yield "data: " + json.dumps(
317
- create_chat_completion_data("", request.model, ts, request_id, system_fp, prompt_tokens, completion_tokens, "stop")
 
 
 
 
318
  ) + "\n\n"
319
  yield "data: [DONE]\n\n"
320
 
321
- except Exception as e:
322
- logger.error(f"Stream error {request_id}: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
323
 
324
- upload_replaced_urls_to_r2(final_links, alt_text=get_last_user_prompt(request.messages))
325
 
326
  # ---------------------------------------------
327
  # NON-STREAMING RESPONSE HANDLER
328
  # ---------------------------------------------
329
  async def process_non_streaming_response(request: ChatRequest):
330
- system_fp = generate_system_fingerprint()
 
 
 
 
 
331
  request_id = f"chatcmpl-{uuid.uuid4()}"
332
- logger.info(f"Processing (non-stream) {request_id} - Model: {request.model}")
333
 
334
  agent_mode = AGENT_MODE.get(request.model, {})
335
- trending_mode = TRENDING_AGENT_MODE.get(request.model, {})
336
- prefix = MODEL_PREFIXES.get(request.model, "")
337
-
338
- headers_api = get_headers_api_chat(BASE_URL)
 
 
 
 
 
339
  if request.model == "o1-preview":
340
  await asyncio.sleep(random.randint(20, 60))
341
 
342
- h = await getHid()
343
- if not h:
 
 
344
  raise HTTPException(status_code=500, detail="Missing h-value.")
345
 
346
- msgs = [message_to_dict(m, prefix) for m in request.messages]
347
 
348
  json_data = {
349
  "agentMode": agent_mode,
@@ -363,66 +427,141 @@ async def process_non_streaming_response(request: ChatRequest):
363
  "isPremium": True,
364
  "isMemoryEnabled": False,
365
  "maxTokens": request.max_tokens,
366
- "messages": msgs,
367
  "mobileClient": False,
368
  "playgroundTemperature": request.temperature,
369
  "playgroundTopP": request.top_p,
370
  "previewToken": None,
371
- "trendingAgentMode": trending_mode,
372
  "userId": None,
373
  "userSelectedModel": MODEL_MAPPING.get(request.model, request.model),
374
  "userSystemPrompt": None,
375
- "validated": h,
376
  "visitFromDelta": False,
377
  "webSearchModePrompt": False,
378
  "vscodeClient": False,
379
  "designerMode": False,
380
  "workspaceId": "",
381
  "beastMode": False,
382
- "customProfile": {"name": "", "occupation": "", "traits": [], "additionalInfo": "", "enableNewChats": False},
383
- "webSearchModeOption": {"autoMode": False, "webMode": False, "offlineMode": True},
384
- "session": generate_session_data(),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
385
  }
386
 
387
  prompt_tokens = sum(
388
- calculate_tokens(m.get("content", ""), request.model) +
389
- sum(calculate_tokens(img["contents"], request.model) for img in m.get("data", {}).get("imagesData", []))
390
- for m in msgs
391
  )
392
 
393
- full_resp = ""
394
- final_links: List[str] = []
395
 
396
  async with httpx.AsyncClient() as client:
397
  try:
398
- resp = await client.post(f"{BASE_URL}/api/chat", headers=headers_api, json=json_data)
399
- resp.raise_for_status()
400
- full_resp = resp.text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
401
  except Exception as e:
 
 
402
  return {
403
  "id": request_id,
404
  "object": "chat.completion",
405
  "created": int(datetime.now().timestamp()),
406
  "model": request.model,
407
- "system_fingerprint": system_fp,
408
- "choices": [{"index": 0, "message": {"role": "assistant", "content": str(e)}, "finish_reason": "error"}],
409
- "usage": {"prompt_tokens": prompt_tokens, "completion_tokens": 0, "total_tokens": prompt_tokens},
 
 
 
 
410
  }
411
 
412
- full_resp = full_resp.replace(BLOCKED_MESSAGE, "").strip()
413
- full_resp = full_resp.replace("https://storage.googleapis.com", "https://cdn.snapzion.com")
414
- final_links.extend(re.findall(r"(https://cdn\.snapzion\.com[^\s\)]+)", full_resp))
415
- clean = strip_model_prefix(full_resp, prefix)
416
- completion_tokens = calculate_tokens(clean, request.model)
 
 
 
 
 
 
 
 
 
417
 
418
- upload_replaced_urls_to_r2(final_links, alt_text=get_last_user_prompt(request.messages))
 
419
 
420
  return {
421
  "id": request_id,
422
  "object": "chat.completion",
423
  "created": int(datetime.now().timestamp()),
424
  "model": request.model,
425
- "system_fingerprint": system_fp,
426
- "choices": [{"index": 0, "message": {"role": "assistant", "content": clean}, "finish_reason": "stop"}],
427
- "usage": {"prompt_tokens": prompt_tokens, "completion_tokens": completion_tokens, "total_tokens": prompt_tokens + completion_tokens},
 
 
 
 
428
  }
 
5
  import string
6
  import time
7
  import uuid
8
+ from datetime import datetime, timezone
9
  from typing import Any, Dict, List, Optional
10
 
11
  import boto3
 
52
  )
53
 
54
  # ---------------------------------------------
55
+ # RANDOM USER-DATA GENERATION
56
  # ---------------------------------------------
57
  def get_random_name_email_customer():
58
  first_names = ["Aliace", "B21ob", "Car232ol", "Daavid", "Evewwlyn", "Fraank", "Grssace", "Hefctor", "Ivgy", "Jackdie"]
59
+ last_names = ["Smilth", "Johnkson", "Dajvis", "Mihller", "Thomgpson", "Garwcia", "Broawn", "Wilfson", "Maartin", "Clarak"]
60
 
61
  random_name = f"{random.choice(first_names)} {random.choice(last_names)}"
62
  email_username = ''.join(random.choices(string.ascii_lowercase + string.digits, k=8))
63
+ random_email = f"{email_username}@gmail.com"
64
  suffix_length = len("Rldf7IKdNhdhiw")
65
  suffix_chars = string.ascii_letters + string.digits
66
  random_suffix = ''.join(random.choice(suffix_chars) for _ in range(suffix_length))
 
68
 
69
  return random_name, random_email, random_customer_id
70
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  def generate_system_fingerprint() -> str:
72
+ raw_data = f"{platform.node()}-{time.time()}-{uuid.uuid4()}"
73
+ short_hash = hashlib.md5(raw_data.encode()).hexdigest()[:12]
74
  return f"fp_{short_hash}"
75
 
76
  def get_last_user_prompt(messages: List[Any]) -> str:
 
86
 
87
  def upload_replaced_urls_to_r2(urls: List[str], alt_text: str = "") -> None:
88
  if not urls:
89
+ logger.info("No replaced or final Snapzion URLs to store. Skipping snapzion.txt update.")
90
  return
91
+
92
+ existing_data = ""
93
  try:
94
+ response = s3.get_object(Bucket=R2_BUCKET_NAME, Key=R2_REPLACED_URLS_KEY)
95
+ existing_data = response['Body'].read().decode('utf-8')
96
+ logger.info("Successfully read existing snapzion.txt from R2.")
97
  except s3.exceptions.NoSuchKey:
98
+ logger.info("snapzion.txt does not exist yet. Will create a new one.")
99
  except Exception as e:
100
+ logger.error(f"Error reading snapzion.txt from R2: {e}")
101
 
102
+ alt_text = alt_text.strip()
103
+ markdown_lines = [f"![{alt_text}]({url})" for url in urls]
104
+ to_append = "\n".join(markdown_lines)
105
+
106
+ updated_content = (existing_data + "\n" + to_append) if existing_data.strip() else to_append
107
 
108
  try:
109
  s3.put_object(
110
  Bucket=R2_BUCKET_NAME,
111
  Key=R2_REPLACED_URLS_KEY,
112
+ Body=updated_content.encode("utf-8"),
113
  ContentType="text/plain",
114
  )
115
+ logger.info(f"Appended {len(urls)} new URLs to snapzion.txt in R2 (in Markdown format).")
116
  except Exception as e:
117
+ logger.error(f"Failed to upload replaced URLs to R2: {e}")
118
 
119
  def calculate_tokens(text: str, model: str) -> int:
120
  try:
121
+ encoding = tiktoken.encoding_for_model(model)
122
+ tokens = encoding.encode(text)
123
+ return len(tokens)
124
+ except KeyError:
125
+ logger.warning(f"Model '{model}' not supported by tiktoken for token counting. Using a generic method.")
126
  return len(text.split())
127
 
128
  def create_chat_completion_data(
 
144
  }
145
  return {
146
  "id": request_id,
147
+ "object": "chat.completion.chunk" if finish_reason is None else "chat.completion",
148
  "created": timestamp,
149
  "model": model,
150
  "system_fingerprint": system_fingerprint,
151
+ "choices": [{
152
+ "index": 0,
153
+ "delta" if finish_reason is None else "message": {
154
+ "content": content,
155
+ "role": "assistant"
156
+ },
157
+ "finish_reason": finish_reason
158
+ }],
159
  "usage": usage,
160
  }
161
 
162
  def message_to_dict(message, model_prefix: Optional[str] = None):
 
 
 
 
 
163
  content = ""
164
  images_data = []
165
  image_urls = []
 
169
  if item.get("type") == "text":
170
  content = item.get("text", "").strip()
171
  elif item.get("type") == "image_url" and len(images_data) < 3:
172
+ image_url = item["image_url"].get("url", "")
173
+ if image_url:
174
+ file_path = f"MultipleFiles/{uuid.uuid4().hex}.jpg"
175
+ images_data.append({"filePath": file_path, "contents": image_url})
176
+ image_urls.append({"image_url": {"url": image_url}})
177
  elif isinstance(message.content, str):
178
  content = message.content.strip()
179
 
 
188
  "title": "snapshot",
189
  "imagesData": images_data
190
  }
191
+ for img in image_urls[1:]:
192
+ base["content"] = [base["content"], img]
 
193
 
194
  return base
195
 
196
  def strip_model_prefix(content: str, model_prefix: Optional[str] = None) -> str:
197
  if model_prefix and content.startswith(model_prefix):
198
+ logger.debug(f"Stripping prefix '{model_prefix}' from content.")
199
  return content[len(model_prefix):].strip()
200
  return content
201
 
 
203
  # STREAMING RESPONSE HANDLER
204
  # ---------------------------------------------
205
  async def process_streaming_response(request: ChatRequest):
206
+ # Generate a fixed-length session ID on each request
207
+ session_id = str(uuid.uuid4()) # 36-character UUID
208
+ is_new_user = False # set your own logic here
209
+
210
+ system_fingerprint = generate_system_fingerprint()
211
+ random_name, random_email, random_customer_id = get_random_name_email_customer()
212
  request_id = f"chatcmpl-{uuid.uuid4()}"
213
+ logger.info(f"Processing request (stream) {request_id} - Model: {request.model}")
214
 
215
  agent_mode = AGENT_MODE.get(request.model, {})
216
+ trending_agent_mode = TRENDING_AGENT_MODE.get(request.model, {})
217
+ model_prefix = MODEL_PREFIXES.get(request.model, "")
218
 
219
+ headers_api_chat = get_headers_api_chat(BASE_URL)
220
  if request.model == "o1-preview":
221
  await asyncio.sleep(random.randint(1, 60))
222
 
223
+ h_value = await getHid()
224
+ if not h_value:
225
+ logger.error("No h-value for validation.")
226
  raise HTTPException(status_code=500, detail="Missing h-value.")
227
 
228
+ messages = [message_to_dict(msg, model_prefix=model_prefix) for msg in request.messages]
229
 
230
  json_data = {
231
  "agentMode": agent_mode,
 
245
  "isPremium": True,
246
  "isMemoryEnabled": False,
247
  "maxTokens": request.max_tokens,
248
+ "messages": messages,
249
  "mobileClient": False,
250
  "playgroundTemperature": request.temperature,
251
  "playgroundTopP": request.top_p,
252
  "previewToken": None,
253
+ "trendingAgentMode": trending_agent_mode,
254
  "userId": None,
255
  "userSelectedModel": MODEL_MAPPING.get(request.model, request.model),
256
  "userSystemPrompt": None,
257
+ "validated": h_value,
258
  "visitFromDelta": False,
259
  "webSearchModePrompt": False,
260
  "vscodeClient": False,
261
  "designerMode": False,
262
  "workspaceId": "",
263
  "beastMode": False,
264
+ "customProfile": {
265
+ "name": "",
266
+ "occupation": "",
267
+ "traits": [],
268
+ "additionalInfo": "",
269
+ "enableNewChats": False
270
+ },
271
+ "webSearchModeOption": {
272
+ "autoMode": False,
273
+ "webMode": False,
274
+ "offlineMode": True
275
+ },
276
+ # Insert the session with new id and isNewUser flag
277
+ "session": {
278
+ "user": {
279
+ "name": random_name,
280
+ "email": random_email,
281
+ "image": "https://lh3.googleusercontent.com/a/...=s96-c",
282
+ "subscriptionStatus": "PREMIUM"
283
+ },
284
+ "expires": datetime.now(timezone.utc)
285
+ .isoformat(timespec='milliseconds')
286
+ .replace('+00:00', 'Z'),
287
+ "subscriptionCache": {
288
+ "customerId": random_customer_id,
289
+ "status": "PREMIUM",
290
+ "isTrialSubscription": "False",
291
+ "expiryTimestamp": 1744652408,
292
+ "lastChecked": int(time.time() * 1000)
293
+ },
294
+ "id": session_id,
295
+ "isNewUser": is_new_user
296
+ }
297
  }
298
 
299
  prompt_tokens = sum(
300
+ calculate_tokens(msg["content"], request.model)
301
+ for msg in messages if "content" in msg
 
302
  )
 
303
  completion_tokens = 0
304
+ final_snapzion_links: List[str] = []
305
 
306
  async with httpx.AsyncClient() as client:
307
  try:
308
+ async with client.stream(
309
+ "POST", f"{BASE_URL}/api/chat",
310
+ headers=headers_api_chat,
311
+ json=json_data,
312
+ timeout=100
313
+ ) as response:
314
+ response.raise_for_status()
315
+ async for chunk in response.aiter_text():
316
+ timestamp = int(datetime.now().timestamp())
317
  if not chunk:
318
  continue
319
  if chunk.startswith("$@$v=undefined-rv1$@$"):
 
322
  chunk = chunk.replace(BLOCKED_MESSAGE, "").strip()
323
  if not chunk:
324
  continue
325
+ if "https://storage.googleapis.com" in chunk:
326
+ chunk = chunk.replace("https://storage.googleapis.com", "https://cdn.snapzion.com")
327
+ snapzion_urls = re.findall(r"(https://cdn\.snapzion\.com[^\s\)]+)", chunk)
328
+ final_snapzion_links.extend(snapzion_urls)
329
+ cleaned = strip_model_prefix(chunk, model_prefix)
330
+ completion_tokens += calculate_tokens(cleaned, request.model)
331
  yield "data: " + json.dumps(
332
+ create_chat_completion_data(cleaned, request.model, timestamp,
333
+ request_id, system_fingerprint,
334
+ prompt_tokens, completion_tokens)
335
  ) + "\n\n"
336
 
337
+ # send final stop event
338
  yield "data: " + json.dumps(
339
+ create_chat_completion_data(
340
+ "", request.model, int(datetime.now().timestamp()),
341
+ request_id, system_fingerprint,
342
+ prompt_tokens, completion_tokens, "stop"
343
+ )
344
  ) + "\n\n"
345
  yield "data: [DONE]\n\n"
346
 
347
+ except httpx.HTTPStatusError as e:
348
+ logger.error(f"HTTP error (stream) {request_id}: {e}")
349
+ error_message = f"HTTP error occurred: {e}"
350
+ try:
351
+ details = e.response.json()
352
+ error_message += f" Details: {details}"
353
+ except ValueError:
354
+ error_message += f" Response body: {e.response.text}"
355
+ yield "data: " + json.dumps(
356
+ create_chat_completion_data(error_message, request.model,
357
+ int(datetime.now().timestamp()),
358
+ request_id, system_fingerprint,
359
+ prompt_tokens, completion_tokens, "error")
360
+ ) + "\n\n"
361
+ yield "data: [DONE]\n\n"
362
+
363
+ except (httpx.RequestError, Exception) as e:
364
+ logger.error(f"Request error (stream) {request_id}: {e}")
365
+ error_message = f"Request error occurred: {e}"
366
+ yield "data: " + json.dumps(
367
+ create_chat_completion_data(error_message, request.model,
368
+ int(datetime.now().timestamp()),
369
+ request_id, system_fingerprint,
370
+ prompt_tokens, completion_tokens, "error")
371
+ ) + "\n\n"
372
+ yield "data: [DONE]\n\n"
373
+
374
+ last_user_prompt = get_last_user_prompt(request.messages)
375
+ upload_replaced_urls_to_r2(final_snapzion_links, alt_text=last_user_prompt)
376
 
 
377
 
378
  # ---------------------------------------------
379
  # NON-STREAMING RESPONSE HANDLER
380
  # ---------------------------------------------
381
  async def process_non_streaming_response(request: ChatRequest):
382
+ # Generate a fixed-length session ID on each request
383
+ session_id = str(uuid.uuid4())
384
+ is_new_user = False
385
+
386
+ system_fingerprint = generate_system_fingerprint()
387
+ random_name, random_email, random_customer_id = get_random_name_email_customer()
388
  request_id = f"chatcmpl-{uuid.uuid4()}"
389
+ logger.info(f"Processing request (non-stream) {request_id} - Model: {request.model}")
390
 
391
  agent_mode = AGENT_MODE.get(request.model, {})
392
+ trending_agent_mode = TRENDING_AGENT_MODE.get(request.model, {})
393
+ model_prefix = MODEL_PREFIXES.get(request.model, "")
394
+
395
+ headers_api_chat = get_headers_api_chat(BASE_URL)
396
+ headers_chat = get_headers_chat(
397
+ BASE_URL,
398
+ next_action=str(uuid.uuid4()),
399
+ next_router_state_tree=json.dumps([""])
400
+ )
401
  if request.model == "o1-preview":
402
  await asyncio.sleep(random.randint(20, 60))
403
 
404
+ # You could also use: h_value = await getHid()
405
+ h_value = "00f37b34-a166-4efb-bce5-1312d87f2f94"
406
+ if not h_value:
407
+ logger.error("Failed to retrieve h-value.")
408
  raise HTTPException(status_code=500, detail="Missing h-value.")
409
 
410
+ messages = [message_to_dict(msg, model_prefix=model_prefix) for msg in request.messages]
411
 
412
  json_data = {
413
  "agentMode": agent_mode,
 
427
  "isPremium": True,
428
  "isMemoryEnabled": False,
429
  "maxTokens": request.max_tokens,
430
+ "messages": messages,
431
  "mobileClient": False,
432
  "playgroundTemperature": request.temperature,
433
  "playgroundTopP": request.top_p,
434
  "previewToken": None,
435
+ "trendingAgentMode": trending_agent_mode,
436
  "userId": None,
437
  "userSelectedModel": MODEL_MAPPING.get(request.model, request.model),
438
  "userSystemPrompt": None,
439
+ "validated": h_value,
440
  "visitFromDelta": False,
441
  "webSearchModePrompt": False,
442
  "vscodeClient": False,
443
  "designerMode": False,
444
  "workspaceId": "",
445
  "beastMode": False,
446
+ "customProfile": {
447
+ "name": "",
448
+ "occupation": "",
449
+ "traits": [],
450
+ "additionalInfo": "",
451
+ "enableNewChats": False
452
+ },
453
+ "webSearchModeOption": {
454
+ "autoMode": False,
455
+ "webMode": False,
456
+ "offlineMode": True
457
+ },
458
+ # Insert the session with new id and isNewUser flag
459
+ "session": {
460
+ "user": {
461
+ "name": random_name,
462
+ "email": random_email,
463
+ "image": "https://lh3.googleusercontent.com/a/...=s96-c",
464
+ "subscriptionStatus": "PREMIUM"
465
+ },
466
+ "expires": datetime.now(timezone.utc)
467
+ .isoformat(timespec='milliseconds')
468
+ .replace('+00:00', 'Z'),
469
+ "subscriptionCache": {
470
+ "customerId": random_customer_id,
471
+ "status": "PREMIUM",
472
+ "isTrialSubscription": "False",
473
+ "expiryTimestamp": 1744652408,
474
+ "lastChecked": int(time.time() * 1000)
475
+ },
476
+ "id": session_id,
477
+ "isNewUser": is_new_user
478
+ }
479
  }
480
 
481
  prompt_tokens = sum(
482
+ calculate_tokens(msg["content"], request.model)
483
+ for msg in messages if "content" in msg
 
484
  )
485
 
486
+ full_response = ""
487
+ final_snapzion_links: List[str] = []
488
 
489
  async with httpx.AsyncClient() as client:
490
  try:
491
+ async with client.stream(
492
+ "POST", f"{BASE_URL}/api/chat",
493
+ headers=headers_api_chat,
494
+ json=json_data
495
+ ) as response:
496
+ response.raise_for_status()
497
+ async for chunk in response.aiter_text():
498
+ full_response += chunk
499
+ except httpx.HTTPStatusError as e:
500
+ logger.error(f"HTTP error (non-stream) {request_id}: {e}")
501
+ error_message = f"HTTP error occurred: {e}"
502
+ try:
503
+ error_details = e.response.json()
504
+ error_message += f" Details: {error_details}"
505
+ except ValueError:
506
+ error_message += f" Response body: {e.response.text}"
507
+ return {
508
+ "id": request_id,
509
+ "object": "chat.completion",
510
+ "created": int(datetime.now().timestamp()),
511
+ "model": request.model,
512
+ "system_fingerprint": system_fingerprint,
513
+ "choices": [{
514
+ "index": 0,
515
+ "message": {"role": "assistant", "content": error_message},
516
+ "finish_reason": "error"
517
+ }],
518
+ "usage": {"prompt_tokens": prompt_tokens, "completion_tokens": 0, "total_tokens": prompt_tokens}
519
+ }
520
  except Exception as e:
521
+ logger.error(f"Unexpected error (non-stream) {request_id}: {e}")
522
+ error_message = f"An unexpected error occurred: {e}"
523
  return {
524
  "id": request_id,
525
  "object": "chat.completion",
526
  "created": int(datetime.now().timestamp()),
527
  "model": request.model,
528
+ "system_fingerprint": system_fingerprint,
529
+ "choices": [{
530
+ "index": 0,
531
+ "message": {"role": "assistant", "content": error_message},
532
+ "finish_reason": "error"
533
+ }],
534
+ "usage": {"prompt_tokens": prompt_tokens, "completion_tokens": 0, "total_tokens": prompt_tokens}
535
  }
536
 
537
+ # Post-process response
538
+ if full_response.startswith("$@$v=undefined-rv1$@$"):
539
+ full_response = full_response[21:]
540
+ if BLOCKED_MESSAGE in full_response:
541
+ full_response = full_response.replace(BLOCKED_MESSAGE, "").strip()
542
+ if not full_response:
543
+ raise HTTPException(status_code=500, detail="Blocked message in response.")
544
+ if "https://storage.googleapis.com" in full_response:
545
+ full_response = full_response.replace("https://storage.googleapis.com", "https://cdn.snapzion.com")
546
+ snapzion_urls = re.findall(r"(https://cdn\.snapzion\.com[^\s\)]+)", full_response)
547
+ final_snapzion_links.extend(snapzion_urls)
548
+
549
+ cleaned = strip_model_prefix(full_response, model_prefix)
550
+ completion_tokens = calculate_tokens(cleaned, request.model)
551
 
552
+ last_user_prompt = get_last_user_prompt(request.messages)
553
+ upload_replaced_urls_to_r2(final_snapzion_links, alt_text=last_user_prompt)
554
 
555
  return {
556
  "id": request_id,
557
  "object": "chat.completion",
558
  "created": int(datetime.now().timestamp()),
559
  "model": request.model,
560
+ "system_fingerprint": system_fingerprint,
561
+ "choices": [{
562
+ "index": 0,
563
+ "message": {"role": "assistant", "content": cleaned},
564
+ "finish_reason": "stop"
565
+ }],
566
+ "usage": {"prompt_tokens": prompt_tokens, "completion_tokens": completion_tokens, "total_tokens": prompt_tokens + completion_tokens}
567
  }