Cortex: FastAPI backend serving Inara via Claude/Gemini CLI backends. Includes SSE streaming chat, session persistence, Google Chat webhook handler, and Docker support. Inara: Identity files (persona, soul, protocols, memory, context tiers) mounted read-only into the container at runtime. Features in initial cut: - /chat endpoint with SSE keepalive + LLM fallback - Session store with rolling history window - Markdown rendering, copy-to-clipboard, links open in new tab - Stacked right-column input controls (height selector, enter toggle, note mode with public/private) — semi-hidden until textarea grows - /note endpoint for injecting public context into session history - Docker Compose config (local dev runs natively; Docker for server) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
51 lines
1.4 KiB
Python
51 lines
1.4 KiB
Python
import json
|
|
from pathlib import Path
|
|
from datetime import datetime
|
|
from config import settings
|
|
|
|
|
|
def _path(session_id: str) -> Path:
|
|
d = settings.sessions_path()
|
|
d.mkdir(parents=True, exist_ok=True)
|
|
return d / f"{session_id}.json"
|
|
|
|
|
|
def load(session_id: str) -> list[dict]:
|
|
path = _path(session_id)
|
|
if not path.exists():
|
|
return []
|
|
return json.loads(path.read_text()).get("messages", [])
|
|
|
|
|
|
def save(session_id: str, messages: list[dict]) -> None:
|
|
path = _path(session_id)
|
|
existing = json.loads(path.read_text()) if path.exists() else {}
|
|
|
|
# Enforce rolling window
|
|
windowed = messages[-settings.max_history_messages:]
|
|
|
|
path.write_text(json.dumps({
|
|
"session_id": session_id,
|
|
"created": existing.get("created", datetime.now().isoformat()),
|
|
"updated": datetime.now().isoformat(),
|
|
"messages": windowed,
|
|
}, indent=2))
|
|
|
|
|
|
def list_all() -> list[dict]:
|
|
d = settings.sessions_path()
|
|
if not d.exists():
|
|
return []
|
|
results = []
|
|
for f in sorted(d.glob("*.json"), key=lambda p: p.stat().st_mtime, reverse=True):
|
|
try:
|
|
data = json.loads(f.read_text())
|
|
results.append({
|
|
"session_id": data["session_id"],
|
|
"updated": data.get("updated"),
|
|
"message_count": len(data.get("messages", [])),
|
|
})
|
|
except Exception:
|
|
pass
|
|
return results
|