Spaces:
Sleeping
Sleeping
File size: 2,733 Bytes
910dadd | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | """contimp-app: FastAPI service exposing the task registry + static frontend."""
from fastapi import FastAPI, HTTPException, Request
from fastapi.responses import FileResponse
from fastapi.staticfiles import StaticFiles
from pydantic import BaseModel
from app import config, engine
from app.tasks import REGISTRY
app = FastAPI(title="contimp-app", version=config.APP_VERSION)
@app.middleware("http")
async def passcode_gate(request: Request, call_next):
needs_gate = (
config.APP_PASSCODE
and request.url.path.startswith("/api/")
and request.url.path != "/api/health"
)
if needs_gate and request.headers.get("x-contimp-passcode") != config.APP_PASSCODE:
from fastapi.responses import JSONResponse
return JSONResponse({"detail": "bad or missing passcode"}, status_code=401)
return await call_next(request)
def get_task(task_id: str):
task = REGISTRY.get(task_id)
if task is None:
raise HTTPException(404, f"unknown task {task_id!r}")
return task
@app.get("/api/health")
def health() -> dict:
return {"ok": True, "version": config.APP_VERSION, "model": config.LLM_MODEL}
@app.get("/api/tasks")
def list_tasks() -> list[dict]:
return [task.meta() for task in REGISTRY.values()]
@app.post("/api/tasks/{task_id}/sample")
def sample(task_id: str) -> dict:
s = get_task(task_id).sample()
return {"input_id": s.input_id, "text": s.text}
class RunRequest(BaseModel):
text: str
input_id: str | None = None
user: str = "anonymous"
session_id: str = "unknown"
source: str = "human"
@app.post("/api/tasks/{task_id}/run")
def run(task_id: str, body: RunRequest) -> dict:
task = get_task(task_id)
if not body.text.strip():
raise HTTPException(422, "empty input")
return engine.run_task(
task,
text=body.text,
input_id=body.input_id,
user_id=body.user,
session_id=body.session_id,
source="synthetic" if body.source == "synthetic" else "human",
)
class FeedbackRequest(BaseModel):
trace_id: str
value: int | None = None # 1 = up, 0 = down; None = note-only
comment: str | None = None
@app.post("/api/feedback")
def feedback(body: FeedbackRequest) -> dict:
if body.value is None and not (body.comment or "").strip():
raise HTTPException(422, "feedback needs a value or a comment")
value = None if body.value is None else (1 if body.value else 0)
engine.record_feedback(body.trace_id, value, body.comment)
return {"ok": True}
@app.get("/")
def index() -> FileResponse:
return FileResponse(config.STATIC_DIR / "index.html")
app.mount("/static", StaticFiles(directory=config.STATIC_DIR), name="static")
|