bahi-bh commited on
Commit
2b2b8ca
·
verified ·
1 Parent(s): 2550709

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +29 -19
app.py CHANGED
@@ -7,7 +7,7 @@ import threading
7
  from typing import Any, Dict, List, Optional
8
  from collections import OrderedDict
9
  from fastapi import FastAPI, HTTPException, Request
10
- from fastapi.responses import StreamingResponse, JSONResponse
11
  from pydantic import BaseModel
12
  import g4f
13
 
@@ -308,6 +308,22 @@ def verify_api_key(request: Request):
308
 
309
  raise HTTPException(status_code=401, detail="Invalid API key. Use 'Authorization: Bearer KEY' or 'X-API-Key: KEY'")
310
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
311
  # =====================================================
312
  # CLAUDE-DESKTOP / CLAUDE-CODE COMPATIBLE ENDPOINTS
313
  # =====================================================
@@ -315,7 +331,6 @@ def verify_api_key(request: Request):
315
  @app.get("/v1/models")
316
  async def v1_models(request: Request):
317
  """Anthropic API compatible models endpoint - NO AUTH REQUIRED"""
318
- # Claude Desktop يطلب هذا أولاً بدون مفتاح
319
 
320
  models = []
321
  for pname, pobj in REAL_PROVIDERS.items():
@@ -328,7 +343,6 @@ async def v1_models(request: Request):
328
  "display_name": f"{pname} - {model}"
329
  })
330
 
331
- # نماذج افتراضية في حال لم يتم العثور على شيء
332
  if not models:
333
  models = [
334
  {"id": "sonar", "type": "model", "display_name": "Perplexity - Sonar"},
@@ -407,17 +421,13 @@ async def v1_messages_stream(request: Request):
407
  async def generate_stream():
408
  message_id = f"msg_{int(time.time())}_{os.urandom(4).hex()}"
409
 
410
- # Message start
411
  yield f"event: message_start\ndata: {{\"message\": {{\"id\": \"{message_id}\", \"type\": \"message\", \"role\": \"assistant\", \"content\": [], \"model\": \"{model}\", \"stop_reason\": null, \"stop_sequence\": null, \"usage\": {{\"input_tokens\": 0, \"output_tokens\": 0}}}}}}\n\n"
412
 
413
- # Content block start
414
  yield f"event: content_block_start\ndata: {{\"type\": \"content_block_start\", \"index\": 0, \"content_block\": {{\"type\": \"text\", \"text\": \"\"}}}}\n\n"
415
 
416
- # Stream deltas
417
  for chunk in ask(full_message, [], "Perplexity", model):
418
  yield f"event: content_block_delta\ndata: {{\"type\": \"content_block_delta\", \"index\": 0, \"delta\": {{\"type\": \"text_delta\", \"text\": {json.dumps(chunk, ensure_ascii=False)}}}}}\n\n"
419
 
420
- # Message end
421
  yield f"event: message_delta\ndata: {{\"type\": \"message_delta\", \"delta\": {{\"stop_reason\": \"end_turn\", \"stop_sequence\": null}}, \"usage\": {{\"output_tokens\": 100}}}}\n\n"
422
  yield f"event: message_stop\ndata: {{}}\n\n"
423
 
@@ -426,13 +436,12 @@ async def v1_messages_stream(request: Request):
426
  media_type="text/event-stream",
427
  headers={
428
  "Cache-Control": "no-cache",
429
- "Connection": "keep-alive",
430
- "Content-Type": "text/event-stream"
431
  }
432
  )
433
 
434
  # =====================================================
435
- # ORIGINAL ENDPOINTS (للواجهة القديمة)
436
  # =====================================================
437
 
438
  @app.get("/")
@@ -440,14 +449,14 @@ async def root():
440
  return {
441
  "message": "G4F Smart Router is running (Claude-compatible)",
442
  "endpoints": {
443
- "GET /": "هذه الصفحة",
444
- "GET /health": "التحقق من صحة الخادم",
445
- "GET /v1/models": "قائمة النماذج (Claude-compatible - NO AUTH)",
446
- "POST /v1/messages": "إرسال رسالة (Claude-compatible - REQUIRES AUTH)",
447
- "POST /v1/messages/stream": "إرسال رسالة متدفق (Claude-compatible - REQUIRES AUTH)",
448
- "GET /providers": "قائمة المزودين (يتطلب مفتاح)",
449
- "POST /chat": "إرسال رسالة (legacy)",
450
- "POST /chat/stream": "إرسال رسالة متدفق (legacy)"
451
  },
452
  "authentication": "Bearer YOUR_API_KEY or X-API-Key: YOUR_API_KEY",
453
  "cookies": COOKIE_STATUS,
@@ -496,9 +505,10 @@ async def get_providers(request: Request):
496
  # =====================================================
497
  if __name__ == "__main__":
498
  import uvicorn
 
499
  uvicorn.run(
500
  "app:app",
501
  host="0.0.0.0",
502
- port=int(os.getenv("PORT", 7860)),
503
  reload=False
504
  )
 
7
  from typing import Any, Dict, List, Optional
8
  from collections import OrderedDict
9
  from fastapi import FastAPI, HTTPException, Request
10
+ from fastapi.responses import StreamingResponse, JSONResponse, Response
11
  from pydantic import BaseModel
12
  import g4f
13
 
 
308
 
309
  raise HTTPException(status_code=401, detail="Invalid API key. Use 'Authorization: Bearer KEY' or 'X-API-Key: KEY'")
310
 
311
+ # =====================================================
312
+ # SUPPORT HEAD METHOD (لإصلاح خطأ 405)
313
+ # =====================================================
314
+
315
+ @app.head("/")
316
+ async def head_root():
317
+ return Response(status_code=200, headers={"Content-Type": "application/json"})
318
+
319
+ @app.head("/health")
320
+ async def head_health():
321
+ return Response(status_code=200, headers={"Content-Type": "application/json"})
322
+
323
+ @app.head("/v1/models")
324
+ async def head_models():
325
+ return Response(status_code=200, headers={"Content-Type": "application/json"})
326
+
327
  # =====================================================
328
  # CLAUDE-DESKTOP / CLAUDE-CODE COMPATIBLE ENDPOINTS
329
  # =====================================================
 
331
  @app.get("/v1/models")
332
  async def v1_models(request: Request):
333
  """Anthropic API compatible models endpoint - NO AUTH REQUIRED"""
 
334
 
335
  models = []
336
  for pname, pobj in REAL_PROVIDERS.items():
 
343
  "display_name": f"{pname} - {model}"
344
  })
345
 
 
346
  if not models:
347
  models = [
348
  {"id": "sonar", "type": "model", "display_name": "Perplexity - Sonar"},
 
421
  async def generate_stream():
422
  message_id = f"msg_{int(time.time())}_{os.urandom(4).hex()}"
423
 
 
424
  yield f"event: message_start\ndata: {{\"message\": {{\"id\": \"{message_id}\", \"type\": \"message\", \"role\": \"assistant\", \"content\": [], \"model\": \"{model}\", \"stop_reason\": null, \"stop_sequence\": null, \"usage\": {{\"input_tokens\": 0, \"output_tokens\": 0}}}}}}\n\n"
425
 
 
426
  yield f"event: content_block_start\ndata: {{\"type\": \"content_block_start\", \"index\": 0, \"content_block\": {{\"type\": \"text\", \"text\": \"\"}}}}\n\n"
427
 
 
428
  for chunk in ask(full_message, [], "Perplexity", model):
429
  yield f"event: content_block_delta\ndata: {{\"type\": \"content_block_delta\", \"index\": 0, \"delta\": {{\"type\": \"text_delta\", \"text\": {json.dumps(chunk, ensure_ascii=False)}}}}}\n\n"
430
 
 
431
  yield f"event: message_delta\ndata: {{\"type\": \"message_delta\", \"delta\": {{\"stop_reason\": \"end_turn\", \"stop_sequence\": null}}, \"usage\": {{\"output_tokens\": 100}}}}\n\n"
432
  yield f"event: message_stop\ndata: {{}}\n\n"
433
 
 
436
  media_type="text/event-stream",
437
  headers={
438
  "Cache-Control": "no-cache",
439
+ "Connection": "keep-alive"
 
440
  }
441
  )
442
 
443
  # =====================================================
444
+ # ORIGINAL ENDPOINTS
445
  # =====================================================
446
 
447
  @app.get("/")
 
449
  return {
450
  "message": "G4F Smart Router is running (Claude-compatible)",
451
  "endpoints": {
452
+ "GET /": "Home page",
453
+ "GET /health": "Health check",
454
+ "GET /v1/models": "List models (NO AUTH)",
455
+ "POST /v1/messages": "Send message (REQUIRES AUTH)",
456
+ "POST /v1/messages/stream": "Stream message (REQUIRES AUTH)",
457
+ "GET /providers": "List providers (REQUIRES AUTH)",
458
+ "POST /chat": "Legacy chat (REQUIRES AUTH)",
459
+ "POST /chat/stream": "Legacy stream (REQUIRES AUTH)"
460
  },
461
  "authentication": "Bearer YOUR_API_KEY or X-API-Key: YOUR_API_KEY",
462
  "cookies": COOKIE_STATUS,
 
505
  # =====================================================
506
  if __name__ == "__main__":
507
  import uvicorn
508
+ port = int(os.getenv("PORT", 7860))
509
  uvicorn.run(
510
  "app:app",
511
  host="0.0.0.0",
512
+ port=port,
513
  reload=False
514
  )