"""Projects router — registered git repos + work contexts from Redis.""" from __future__ import annotations from typing import Optional from fastapi import APIRouter from app.redis_client import get_redis, list_projects, list_workcontexts, PROJECT_KEY_PREFIX, WORKCONTEXT_KEY_PREFIX router = APIRouter(prefix="/api/v1", tags=["projects"]) @router.get("/projects") def api_list_projects(context: Optional[str] = None, q: Optional[str] = None): r = get_redis() projects = list_projects(r, context=context) # Merge in work contexts (keyed by path) wc_keys = r.keys(f"{WORKCONTEXT_KEY_PREFIX}*") import json work_contexts: dict = {} for key in wc_keys: raw = r.get(key) if raw: try: path = key[len(WORKCONTEXT_KEY_PREFIX):] work_contexts[path] = json.loads(raw) except Exception: pass # Attach work context and apply search filter result = [] for p in projects: path = p.get("path", "") p["work_context"] = work_contexts.get(path) if q and q.lower() not in (p.get("name", "") + p.get("path", "") + " ".join(p.get("tags", []))).lower(): continue result.append(p) # Sort: projects with recent work context first result.sort( key=lambda p: ( p["work_context"]["saved_at"] if p.get("work_context") else "", ), reverse=True, ) # Context breakdown contexts = {} for p in result: c = p.get("context", "unknown") contexts[c] = contexts.get(c, 0) + 1 return {"projects": result, "total": len(result), "contexts": contexts} @router.get("/workcontexts") def api_list_workcontexts(): r = get_redis() return {"contexts": list_workcontexts(r)}