Percy3822 commited on
Commit
be0c9e2
·
verified ·
1 Parent(s): f82166c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +41 -81
app.py CHANGED
@@ -1,91 +1,51 @@
1
- import os
2
- import json
3
- import time
4
- import asyncio
5
  from pathlib import Path
6
- from typing import Dict, Any
 
7
 
8
- from fastapi import FastAPI, Body, Request
9
- from fastapi.responses import JSONResponse, StreamingResponse
10
- from fastapi.staticfiles import StaticFiles
 
 
 
 
11
 
12
- BASE_DIR = Path(os.environ.get("BASE_DIR", "/tmp/brain_app"))
13
- FILES_DIR = BASE_DIR / "files"
14
- LOGS_DIR = FILES_DIR / "logs"
15
- FILES_DIR.mkdir(parents=True, exist_ok=True)
16
- LOGS_DIR.mkdir(parents=True, exist_ok=True)
17
 
18
- EVENTS_FILE = LOGS_DIR / "events.jsonl"
19
- TELEM_FILE = LOGS_DIR / "telemetry.jsonl"
20
-
21
- app = FastAPI(title="Brain")
22
- app.mount("/files", StaticFiles(directory=str(FILES_DIR)), name="files")
23
-
24
- def append_jsonl(path: Path, obj: Dict[str, Any]):
25
- obj = {"ts": time.time(), **obj}
26
- with path.open("a", encoding="utf-8") as f:
27
- f.write(json.dumps(obj, ensure_ascii=False) + "\n")
28
 
29
  @app.get("/health")
30
- def health():
31
- return {
32
- "ok": True,
33
- "service": "brain",
34
- "time": time.time(),
35
- "base_dir": str(BASE_DIR),
36
- "files_dir": str(FILES_DIR),
37
- "logs_dir": str(LOGS_DIR),
38
- "events_file": str(EVENTS_FILE),
39
- "telemetry_file": str(TELEM_FILE),
40
- }
41
 
42
  @app.post("/process")
43
- async def process(payload: Dict[str, Any] = Body(...)):
44
- append_jsonl(EVENTS_FILE, {"type": "process", "data": payload})
45
- return {"ok": True, "received": payload}
46
-
47
- @app.post("/log_error")
48
- async def log_error(payload: Dict[str, Any] = Body(...)):
49
- append_jsonl(EVENTS_FILE, {"type": "error", "data": payload})
50
- return {"ok": True}
51
-
52
- @app.post("/telemetry")
53
- async def telemetry(payload: Dict[str, Any] = Body(...)):
54
- append_jsonl(TELEM_FILE, {"type": "telemetry", "data": payload})
55
- return {"ok": True}
56
-
57
- def sse_lines(path: Path, event_filter: str | None = None):
58
- # Tail-like SSE; yields lines as they are appended
59
- pos = 0
60
- while True:
61
- try:
62
- with path.open("r", encoding="utf-8") as f:
63
- f.seek(pos)
64
- for line in f:
65
- pos = f.tell()
66
- try:
67
- obj = json.loads(line.strip())
68
- if event_filter and obj.get("type") != event_filter:
69
- continue
70
- yield f"data: {json.dumps(obj, ensure_ascii=False)}\n\n"
71
- except Exception:
72
- continue
73
- except FileNotFoundError:
74
- pass
75
- time.sleep(0.5)
76
 
77
  @app.get("/stream/logs")
78
- def stream_logs():
79
- return StreamingResponse(sse_lines(EVENTS_FILE, None), media_type="text/event-stream")
80
-
81
- @app.get("/stream/errors")
82
- def stream_errors():
83
- return StreamingResponse(sse_lines(EVENTS_FILE, "error"), media_type="text/event-stream")
84
-
85
- @app.get("/stream/telemetry")
86
- def stream_telemetry():
87
- return StreamingResponse(sse_lines(TELEM_FILE, "telemetry"), media_type="text/event-stream")
88
-
89
- @app.get("/")
90
- def index():
91
- return {"ok": True, "service": "brain", "streams": ["/stream/logs", "/stream/telemetry"]}
 
 
 
 
 
1
+ import os, json, time
 
 
 
2
  from pathlib import Path
3
+ from fastapi import FastAPI, Request
4
+ from fastapi.responses import StreamingResponse, JSONResponse
5
 
6
+ BASE_DIR = Path(os.getenv("BASE_DIR","/tmp/brain_app"))
7
+ FILES = BASE_DIR / "files"
8
+ LOGS = FILES / "logs"
9
+ EVENTS = LOGS / "events.jsonl"
10
+ FILES.mkdir(parents=True, exist_ok=True)
11
+ LOGS.mkdir(parents=True, exist_ok=True)
12
+ EVENTS.touch(exist_ok=True)
13
 
14
+ app = FastAPI()
 
 
 
 
15
 
16
+ def log_event(kind: str, data: dict):
17
+ ev = {"ts": time.time(), "type": kind, "data": data}
18
+ with EVENTS.open("a", encoding="utf-8") as f:
19
+ f.write(json.dumps(ev, ensure_ascii=False) + "\n")
 
 
 
 
 
 
20
 
21
  @app.get("/health")
22
+ async def health():
23
+ return {"ok": True, "service": "brain", "base_dir": str(BASE_DIR), "events_file": str(EVENTS)}
 
 
 
 
 
 
 
 
 
24
 
25
  @app.post("/process")
26
+ async def process(req: Request):
27
+ body = await req.json()
28
+ log_event("process", body)
29
+ # TODO: Replace this echo with your real brain logic
30
+ reply = f"Echo: {(body.get('text') or body)}"
31
+ return {"ok": True, "reply": reply}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
 
33
  @app.get("/stream/logs")
34
+ async def stream_logs():
35
+ async def gen():
36
+ last = EVENTS.stat().st_size
37
+ with EVENTS.open("r", encoding="utf-8") as f:
38
+ f.seek(0,0)
39
+ for line in f:
40
+ yield f"data: {line}\n\n"
41
+ f.seek(last)
42
+ while True:
43
+ where = f.tell()
44
+ line = f.readline()
45
+ if not line:
46
+ await asyncio.sleep(0.5)
47
+ f.seek(where)
48
+ continue
49
+ yield f"data: {line}\n\n"
50
+ import asyncio
51
+ return StreamingResponse(gen(), media_type="text/event-stream")