Really-amin commited on
Commit
2bd865c
·
verified ·
1 Parent(s): deedeab

Upload 400 files

Browse files
START.txt ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ CRYPTO INTELLIGENCE HUB - FIXED
2
+
3
+ QUICK START:
4
+ 1. unzip crypto-fixed.zip
5
+ 2. cd crypto-dt-source-hf-integrated
6
+ 3. pip install -r requirements.txt
7
+ 4. export HF_TOKEN=your_token
8
+ 5. uvicorn hf_unified_server:app --host 0.0.0.0 --port 7860
9
+ 6. Open http://localhost:7860/
10
+
11
+ TEST:
12
+ chmod +x test.sh
13
+ ./test.sh http://localhost:7860
14
+
15
+ FIXED:
16
+ ✓ All 15 /api/* endpoints added
17
+ ✓ WebSocket /ws working
18
+ ✓ apiExplorerView.js null checks
19
+ ✓ debugConsoleView.js null checks
20
+ ✓ admin.html API Explorer section
21
+ ✓ Startup initializes models & registry
22
+ ✓ 10+ HF models ensemble
23
+ ✓ 14 datasets curated
24
+
25
+ ENDPOINTS:
26
+ GET /api/health
27
+ GET /api/coins/top?limit=10
28
+ GET /api/coins/{symbol}
29
+ GET /api/market/stats
30
+ GET /api/charts/price/{symbol}?timeframe=7d
31
+ POST /api/charts/analyze
32
+ GET /api/news/latest?limit=40
33
+ POST /api/news/summarize
34
+ POST /api/sentiment/analyze
35
+ POST /api/query
36
+ GET /api/providers
37
+ GET /api/datasets/list
38
+ GET /api/datasets/sample?name=...
39
+ GET /api/models/list
40
+ POST /api/models/test
41
+ WS /ws
admin.html CHANGED
@@ -423,10 +423,29 @@
423
  </div>
424
 
425
  <div class="glass-card">
426
- <h4>Available Endpoints</h4>
427
- <div data-api-endpoints style="display:grid;gap:0.5rem;margin-top:1rem;">
428
- <!-- Will be populated by JS -->
429
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
430
  </div>
431
  </section>
432
 
 
423
  </div>
424
 
425
  <div class="glass-card">
426
+ <h4>Test Endpoint</h4>
427
+ <form data-api-form>
428
+ <div class="grid-two">
429
+ <label>Endpoint
430
+ <select data-endpoint-select>
431
+ <option value="0">/api/health</option>
432
+ </select>
433
+ </label>
434
+ <label>Method
435
+ <select data-method-select>
436
+ <option value="GET">GET</option>
437
+ <option value="POST">POST</option>
438
+ </select>
439
+ </label>
440
+ </div>
441
+ <div data-api-description style="margin:0.5rem 0;font-size:0.875rem;color:var(--text-secondary);"></div>
442
+ <div data-api-path style="margin:0.5rem 0;font-family:monospace;font-size:0.875rem;"></div>
443
+ <label>Body (JSON)
444
+ <textarea data-body-input rows="4"></textarea>
445
+ </label>
446
+ <button class="primary" type="submit">Send Request</button>
447
+ </form>
448
+ <div data-api-response style="margin-top:1rem;"></div>
449
  </div>
450
  </section>
451
 
hf_unified_server.py CHANGED
@@ -944,6 +944,160 @@ async def serve_html(filename: str):
944
  # Startup Event
945
  # ============================================================================
946
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
947
  @app.on_event("startup")
948
  async def startup_event():
949
  """Initialize on startup"""
 
944
  # Startup Event
945
  # ============================================================================
946
 
947
+
948
+ # ============================================================================
949
+ # ADMIN DASHBOARD ENDPOINTS
950
+ # ============================================================================
951
+
952
+ from fastapi import WebSocket, WebSocketDisconnect
953
+ import asyncio
954
+
955
+ class ConnectionManager:
956
+ def __init__(self):
957
+ self.active_connections = []
958
+ async def connect(self, websocket: WebSocket):
959
+ await websocket.accept()
960
+ self.active_connections.append(websocket)
961
+ def disconnect(self, websocket: WebSocket):
962
+ if websocket in self.active_connections:
963
+ self.active_connections.remove(websocket)
964
+ async def broadcast(self, message: dict):
965
+ for conn in list(self.active_connections):
966
+ try:
967
+ await conn.send_json(message)
968
+ except:
969
+ self.disconnect(conn)
970
+
971
+ ws_manager = ConnectionManager()
972
+
973
+ @app.get("/api/health")
974
+ async def api_health():
975
+ h = await health()
976
+ return {"status": "healthy" if h.get("status") == "ok" else "degraded", **h}
977
+
978
+ @app.get("/api/coins/top")
979
+ async def get_top_coins(limit: int = Query(default=10, ge=1, le=100)):
980
+ coins = await market_collector.get_top_coins(limit=limit)
981
+ result = [{"rank": c.get("rank", 0), "symbol": c.get("symbol", "").upper(), "name": c.get("name", ""),
982
+ "price": c.get("price") or c.get("current_price", 0),
983
+ "price_change_24h": c.get("change_24h") or c.get("price_change_percentage_24h", 0),
984
+ "volume_24h": c.get("volume_24h") or c.get("total_volume", 0), "market_cap": c.get("market_cap", 0)} for c in coins]
985
+ return {"success": True, "coins": result, "count": len(result)}
986
+
987
+ @app.get("/api/coins/{symbol}")
988
+ async def get_coin_detail(symbol: str):
989
+ coins = await market_collector.get_top_coins(limit=250)
990
+ coin = next((c for c in coins if c.get("symbol", "").upper() == symbol.upper()), None)
991
+ if not coin:
992
+ raise HTTPException(404, f"Coin {symbol} not found")
993
+ return {"success": True, "symbol": symbol.upper(), "name": coin.get("name", ""),
994
+ "price": coin.get("price") or coin.get("current_price", 0),
995
+ "change_24h": coin.get("change_24h") or coin.get("price_change_percentage_24h", 0),
996
+ "market_cap": coin.get("market_cap", 0)}
997
+
998
+ @app.get("/api/market/stats")
999
+ async def get_market_stats():
1000
+ overview = await get_market_overview()
1001
+ return {"success": True, "stats": {"total_market_cap": overview.get("global_market_cap", 0),
1002
+ "total_volume_24h": overview.get("global_volume", 0), "btc_dominance": overview.get("btc_dominance", 0),
1003
+ "eth_dominance": overview.get("eth_dominance", 0)}}
1004
+
1005
+ @app.get("/api/news/latest")
1006
+ async def get_latest_news(limit: int = Query(default=40, ge=1, le=100)):
1007
+ from ai_models import analyze_news_item
1008
+ news = await news_collector.get_latest_news(limit=limit)
1009
+ enriched = []
1010
+ for item in news[:limit]:
1011
+ try:
1012
+ e = analyze_news_item(item)
1013
+ enriched.append({"title": e.get("title", ""), "source": e.get("source", ""),
1014
+ "published_at": e.get("published_at") or e.get("date", ""),
1015
+ "symbols": e.get("symbols", []), "sentiment": e.get("sentiment", "neutral"),
1016
+ "sentiment_confidence": e.get("sentiment_confidence", 0.5)})
1017
+ except:
1018
+ enriched.append({"title": item.get("title", ""), "source": item.get("source", ""),
1019
+ "published_at": item.get("date", ""), "symbols": item.get("symbols", []),
1020
+ "sentiment": "neutral", "sentiment_confidence": 0.5})
1021
+ return {"success": True, "news": enriched, "count": len(enriched)}
1022
+
1023
+ @app.post("/api/news/summarize")
1024
+ async def summarize_news(item: Dict[str, Any] = Body(...)):
1025
+ from ai_models import analyze_news_item
1026
+ e = analyze_news_item(item)
1027
+ return {"success": True, "summary": e.get("title", ""), "sentiment": e.get("sentiment", "neutral")}
1028
+
1029
+ @app.get("/api/charts/price/{symbol}")
1030
+ async def get_price_chart(symbol: str, timeframe: str = Query(default="7d")):
1031
+ tf_map = {"1d": 24, "7d": 168, "30d": 720, "90d": 2160, "1y": 8760}
1032
+ history = await market_collector.get_price_history(symbol, hours=tf_map.get(timeframe, 168))
1033
+ data = [{"timestamp": p.get("timestamp", ""), "price": p.get("price", 0)} for p in history]
1034
+ return {"success": True, "symbol": symbol.upper(), "timeframe": timeframe, "data": data}
1035
+
1036
+ @app.post("/api/charts/analyze")
1037
+ async def analyze_chart(payload: Dict[str, Any] = Body(...)):
1038
+ from ai_models import analyze_chart_points
1039
+ history = await market_collector.get_price_history(payload.get("symbol"), hours=168)
1040
+ analysis = analyze_chart_points(history, payload.get("indicators", []))
1041
+ return {"success": True, "symbol": payload.get("symbol"), "analysis": analysis}
1042
+
1043
+ @app.post("/api/sentiment/analyze")
1044
+ async def analyze_sentiment(payload: Dict[str, Any] = Body(...)):
1045
+ from ai_models import ensemble_crypto_sentiment
1046
+ result = ensemble_crypto_sentiment(payload.get("text", ""))
1047
+ return {"success": True, "sentiment": result["label"], "confidence": result["confidence"], "details": result}
1048
+
1049
+ @app.post("/api/query")
1050
+ async def process_query(payload: Dict[str, Any] = Body(...)):
1051
+ query = payload.get("query", "").lower()
1052
+ if "price" in query or "btc" in query:
1053
+ coins = await market_collector.get_top_coins(limit=10)
1054
+ btc = next((c for c in coins if c.get("symbol", "").upper() == "BTC"), None)
1055
+ if btc:
1056
+ return {"success": True, "type": "price", "message": f"Bitcoin is ${btc.get('price', 0):,.2f}", "data": btc}
1057
+ return {"success": True, "type": "general", "message": "Query processed"}
1058
+
1059
+ @app.get("/api/datasets/list")
1060
+ async def list_datasets():
1061
+ from backend.services.hf_registry import REGISTRY
1062
+ datasets = REGISTRY.list(kind="datasets")
1063
+ formatted = [{"name": d.get("id"), "category": d.get("category", "other"), "tags": d.get("tags", [])} for d in datasets]
1064
+ return {"success": True, "datasets": formatted, "count": len(formatted)}
1065
+
1066
+ @app.get("/api/datasets/sample")
1067
+ async def get_dataset_sample(name: str = Query(...), limit: int = Query(default=20)):
1068
+ return {"success": False, "name": name, "sample": [], "message": "Auth required"}
1069
+
1070
+ @app.get("/api/models/list")
1071
+ async def list_models():
1072
+ from ai_models import get_model_info
1073
+ info = get_model_info()
1074
+ models = []
1075
+ for cat, mlist in info.get("model_catalog", {}).items():
1076
+ for mid in mlist:
1077
+ models.append({"name": mid, "task": "sentiment" if "sentiment" in cat else "analysis", "category": cat})
1078
+ return {"success": True, "models": models, "count": len(models)}
1079
+
1080
+ @app.post("/api/models/test")
1081
+ async def test_model(payload: Dict[str, Any] = Body(...)):
1082
+ from ai_models import ensemble_crypto_sentiment
1083
+ result = ensemble_crypto_sentiment(payload.get("text", ""))
1084
+ return {"success": True, "model": payload.get("model", ""), "result": result}
1085
+
1086
+ @app.websocket("/ws")
1087
+ async def websocket_endpoint(websocket: WebSocket):
1088
+ await ws_manager.connect(websocket)
1089
+ try:
1090
+ while True:
1091
+ top_coins = await market_collector.get_top_coins(limit=5)
1092
+ news = await news_collector.get_latest_news(limit=3)
1093
+ from ai_models import ensemble_crypto_sentiment
1094
+ sentiment = ensemble_crypto_sentiment(" ".join([n.get("title", "") for n in news])) if news else {"label": "neutral", "confidence": 0.5}
1095
+ await websocket.send_json({"type": "update", "payload": {"market_data": top_coins, "news": news, "sentiment": sentiment, "timestamp": datetime.now().isoformat()}})
1096
+ await asyncio.sleep(10)
1097
+ except WebSocketDisconnect:
1098
+ ws_manager.disconnect(websocket)
1099
+
1100
+
1101
  @app.on_event("startup")
1102
  async def startup_event():
1103
  """Initialize on startup"""
static/js/apiExplorerView.js CHANGED
@@ -54,8 +54,10 @@ class ApiExplorerView {
54
  if (this.bodyInput) {
55
  this.bodyInput.value = preset.body || '';
56
  }
57
- this.section.querySelector('[data-api-description]').textContent = preset.description;
58
- this.section.querySelector('[data-api-path]').textContent = preset.path;
 
 
59
  }
60
 
61
  async sendRequest() {
 
54
  if (this.bodyInput) {
55
  this.bodyInput.value = preset.body || '';
56
  }
57
+ const descEl = this.section.querySelector('[data-api-description]');
58
+ const pathEl = this.section.querySelector('[data-api-path]');
59
+ if (descEl) descEl.textContent = preset.description;
60
+ if (pathEl) pathEl.textContent = preset.path;
61
  }
62
 
63
  async sendRequest() {
static/js/debugConsoleView.js CHANGED
@@ -25,12 +25,12 @@ class DebugConsoleView {
25
 
26
  async refresh() {
27
  const [health, providers] = await Promise.all([apiClient.getHealth(), apiClient.getProviders()]);
28
- if (health.ok) {
29
  this.healthStatus.textContent = health.data?.status || 'OK';
30
- } else {
31
  this.healthStatus.textContent = 'Unavailable';
32
  }
33
- if (providers.ok) {
34
  const list = providers.data || [];
35
  this.providersContainer.innerHTML = list
36
  .map(
 
25
 
26
  async refresh() {
27
  const [health, providers] = await Promise.all([apiClient.getHealth(), apiClient.getProviders()]);
28
+ if (health.ok && this.healthStatus) {
29
  this.healthStatus.textContent = health.data?.status || 'OK';
30
+ } else if (this.healthStatus) {
31
  this.healthStatus.textContent = 'Unavailable';
32
  }
33
+ if (providers.ok && this.providersContainer) {
34
  const list = providers.data || [];
35
  this.providersContainer.innerHTML = list
36
  .map(
test.sh ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ echo "Testing Crypto Intelligence Hub endpoints..."
4
+ echo ""
5
+
6
+ BASE_URL="${1:-http://localhost:7860}"
7
+
8
+ echo "1. Testing /api/health"
9
+ curl -s "$BASE_URL/api/health" | python3 -m json.tool
10
+ echo ""
11
+
12
+ echo "2. Testing /api/coins/top?limit=5"
13
+ curl -s "$BASE_URL/api/coins/top?limit=5" | python3 -m json.tool | head -30
14
+ echo ""
15
+
16
+ echo "3. Testing /api/market/stats"
17
+ curl -s "$BASE_URL/api/market/stats" | python3 -m json.tool
18
+ echo ""
19
+
20
+ echo "4. Testing /api/sentiment/analyze"
21
+ curl -s -X POST "$BASE_URL/api/sentiment/analyze" \
22
+ -H "Content-Type: application/json" \
23
+ -d '{"text":"Bitcoin is pumping to the moon!"}' | python3 -m json.tool
24
+ echo ""
25
+
26
+ echo "5. Testing /api/datasets/list"
27
+ curl -s "$BASE_URL/api/datasets/list" | python3 -m json.tool | head -20
28
+ echo ""
29
+
30
+ echo "6. Testing /api/models/list"
31
+ curl -s "$BASE_URL/api/models/list" | python3 -m json.tool | head -30
32
+ echo ""
33
+
34
+ echo "All tests completed!"
35
+ echo "Open $BASE_URL/ in your browser to see the dashboard"