Initial commit: AI Dungeon clone (FastAPI backend + React frontend)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KFsGHju9szibJJa2YJcdbg
This commit is contained in:
parththakkar106
2026-07-06 16:08:19 +05:30
co-authored by Claude Fable 5
commit db9f904222
57 changed files with 7804 additions and 0 deletions
+56
View File
@@ -0,0 +1,56 @@
"""In-memory ring buffer of recent provider requests/responses for the debug page.
API keys never enter the log: only the request body (which carries no
credentials) and response text are recorded, both truncated.
"""
import itertools
from collections import deque
from datetime import datetime, timezone
MAX_ENTRIES = 30
MAX_TEXT = 6000
_entries: deque[dict] = deque(maxlen=MAX_ENTRIES)
_ids = itertools.count(1)
def _clip(text: str) -> str:
if len(text) <= MAX_TEXT:
return text
return text[:MAX_TEXT] + f"\n… [{len(text) - MAX_TEXT} more chars truncated]"
def _clip_obj(obj):
if isinstance(obj, str):
return _clip(obj)
if isinstance(obj, dict):
return {k: _clip_obj(v) for k, v in obj.items()}
if isinstance(obj, list):
return [_clip_obj(v) for v in obj]
return obj
def start_entry(url: str, model: str, body: dict) -> dict:
entry = {
"id": next(_ids),
"time": datetime.now(timezone.utc).isoformat(),
"url": url,
"model": model,
"request": _clip_obj(body),
"status": "pending",
"response": "",
"error": None,
}
_entries.appendleft(entry)
return entry
def finish_entry(entry: dict, *, response: str = "", error: str | None = None) -> None:
entry["response"] = _clip(response)
entry["error"] = error
entry["status"] = "error" if error else "ok"
def recent() -> list[dict]:
return list(_entries)