Benny-Tang commited on
Commit
4cbbddf
·
verified ·
1 Parent(s): 16c8b7f

Create api/server.py

Browse files
Files changed (1) hide show
  1. api/server.py +146 -0
api/server.py ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ python3 << 'PYEOF'
2
+ code = '''
3
+ import asyncio, json, os, sys, time
4
+ from datetime import datetime
5
+ from typing import AsyncGenerator
6
+ from fastapi import FastAPI, HTTPException, Request
7
+ from fastapi.middleware.cors import CORSMiddleware
8
+ from fastapi.responses import HTMLResponse, StreamingResponse
9
+ from pydantic import BaseModel, Field
10
+
11
+ sys.path.insert(0, "/opt/aegis")
12
+ from agents.swarm import (signal_agent, intelligence_agent, forecast_agent,
13
+ simulation_agent, decision_agent, alert_agent, execution_agent,
14
+ run_aegis_pipeline, scrape_marine_traffic)
15
+ from models.forecaster import get_forecaster
16
+
17
+ app = FastAPI(title="Aegis", version="2.0.0")
18
+ app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"])
19
+
20
+ @app.middleware("http")
21
+ async def timing(request: Request, call_next):
22
+ start = time.time()
23
+ response = await call_next(request)
24
+ response.headers["X-Response-Time"] = f"{round((time.time()-start)*1000,1)}ms"
25
+ response.headers["X-Powered-By"] = "AMD Instinct MI300X"
26
+ return response
27
+
28
+ class CrisisEvent(BaseModel):
29
+ oil_price_change_pct: float = Field(default=18.0)
30
+ shipping_disruption: str = Field(default="Strait of Hormuz disruption")
31
+ news_headline: str = Field(default="Regional conflict near Persian Gulf")
32
+ severity: str = Field(default="HIGH")
33
+ disruption_factor: float = Field(default=0.7, ge=0, le=1)
34
+ horizon_days: int = Field(default=14, ge=1, le=90)
35
+
36
+ class ForecastRequest(BaseModel):
37
+ oil_shock_pct: float = Field(default=0.0)
38
+ disruption_factor: float = Field(default=0.0, ge=0, le=1)
39
+ horizon_days: int = Field(default=14, ge=1, le=90)
40
+
41
+ @app.on_event("startup")
42
+ async def startup():
43
+ print("Aegis starting on AMD Developer Cloud...")
44
+ try:
45
+ get_forecaster()
46
+ print("Forecaster ready")
47
+ except Exception as e:
48
+ print(f"Forecaster warning: {e}")
49
+
50
+ @app.get("/health")
51
+ async def health():
52
+ return {
53
+ "status": "online", "system": "Aegis", "version": "2.0.0",
54
+ "timestamp": datetime.utcnow().isoformat(),
55
+ "agents": 7, "platform": "AMD Developer Cloud",
56
+ "model": "llama-3.3-70b-versatile",
57
+ "forecast": "ARIMA(2,1,2) + XGBoost hybrid",
58
+ }
59
+
60
+ @app.get("/api/marine")
61
+ async def marine_feed():
62
+ """Live MarineTraffic shipping news feed."""
63
+ try:
64
+ data = scrape_marine_traffic()
65
+ return {"success": True, "data": data}
66
+ except Exception as e:
67
+ raise HTTPException(status_code=500, detail=str(e))
68
+
69
+ @app.post("/api/forecast")
70
+ async def forecast_only(req: ForecastRequest):
71
+ try:
72
+ fc = get_forecaster()
73
+ result = fc.forecast(req.horizon_days, req.oil_shock_pct, req.disruption_factor)
74
+ return {"success": True, "data": result}
75
+ except Exception as e:
76
+ raise HTTPException(status_code=500, detail=str(e))
77
+
78
+ @app.post("/api/crisis")
79
+ async def run_crisis(event: CrisisEvent):
80
+ try:
81
+ fc = get_forecaster()
82
+ forecast_data = fc.forecast(event.horizon_days, event.oil_price_change_pct, event.disruption_factor)
83
+ results = await run_aegis_pipeline(event.model_dump(), forecast_data)
84
+ return {"success": True, "timestamp": datetime.utcnow().isoformat(), "data": results}
85
+ except Exception as e:
86
+ import traceback
87
+ raise HTTPException(status_code=500, detail=f"{e}\\n{traceback.format_exc()}")
88
+
89
+ @app.get("/api/stream")
90
+ async def stream_crisis(oil_change: float=18.0, disruption: float=0.7, severity: str="HIGH"):
91
+ async def gen() -> AsyncGenerator[str, None]:
92
+ def sse(d): return f"data: {json.dumps(d)}\\n\\n"
93
+ yield sse({"type":"start","message":"Aegis pipeline initiated"})
94
+ try:
95
+ fc = get_forecaster()
96
+ fd = fc.forecast(14, oil_change, disruption)
97
+ yield sse({"type":"forecast_ready","data":fd["summary"]})
98
+ ev = {"oil_price_change_pct":oil_change,"shipping_disruption":"Strait of Hormuz",
99
+ "news_headline":"Geopolitical escalation","severity":severity,"disruption_factor":disruption}
100
+ yield sse({"type":"agent_start","agent":"signal","index":1})
101
+ sig = await signal_agent(ev)
102
+ yield sse({"type":"agent_done","agent":"signal","data":sig})
103
+ yield sse({"type":"agent_start","agent":"intelligence","index":2})
104
+ intel = await intelligence_agent(sig, ev)
105
+ yield sse({"type":"agent_done","agent":"intelligence","data":intel})
106
+ yield sse({"type":"agent_start","agent":"forecast","index":3})
107
+ fore = await forecast_agent(intel, fd)
108
+ yield sse({"type":"agent_done","agent":"forecast","data":fore})
109
+ yield sse({"type":"agent_start","agent":"simulation","index":4})
110
+ sim = await simulation_agent(fore, ev)
111
+ yield sse({"type":"agent_done","agent":"simulation","data":sim})
112
+ yield sse({"type":"agent_start","agent":"decision","index":5})
113
+ dec = await decision_agent(sim, fore, intel)
114
+ yield sse({"type":"agent_done","agent":"decision","data":dec})
115
+ yield sse({"type":"agent_start","agent":"alert","index":6})
116
+ alert = await alert_agent(dec, fore)
117
+ yield sse({"type":"agent_done","agent":"alert","data":alert})
118
+ yield sse({"type":"agent_start","agent":"execution","index":7})
119
+ exe = await execution_agent(dec)
120
+ yield sse({"type":"agent_done","agent":"execution","data":exe})
121
+ yield sse({"type":"complete","message":"All 7 agents finished",
122
+ "summary":dec.get("executive_summary",""),"threat":dec.get("threat_level","")})
123
+ except Exception as e:
124
+ yield sse({"type":"error","message":str(e)})
125
+ return StreamingResponse(gen(), media_type="text/event-stream",
126
+ headers={"Cache-Control":"no-cache","X-Accel-Buffering":"no"})
127
+
128
+ @app.get("/api/status")
129
+ async def status():
130
+ import random
131
+ return {"agents_online":7,"platform":"AMD Developer Cloud",
132
+ "oil_price":round(82+random.uniform(-2,2),2),
133
+ "risk_level":"LOW","groq_model":"llama-3.3-70b-versatile",
134
+ "forecast_model":"ARIMA(2,1,2)+XGBoost"}
135
+
136
+ @app.get("/", response_class=HTMLResponse)
137
+ async def index():
138
+ with open("/opt/aegis/frontend.html") as f:
139
+ return f.read()
140
+ '''
141
+ with open("/opt/aegis/api/server.py","w") as f:
142
+ f.write(code)
143
+ print("server.py written OK")
144
+ PYEOF
145
+
146
+ ✅ Should print: server.py written OK