Add campaign layer, GPU model caching, file browser cleanup

- Campaigns: new table, CRUD API, React context + provider
- Sessions: scoped to campaigns, paths under campaigns/{id}/
- File browser: scoped per campaign, removed copy/paste/autoPlay
- Sidebar: campaign selector dropdown at top
- Transcribe: GPU model cached/released via job counter
- Jobs: status text updates dynamically in real-time
- Auto-redirect: blocked when summarize job is active
This commit is contained in:
KansaiGaijin
2026-07-10 21:41:29 +12:00
parent db19cfd05e
commit bc7ac32de3
19 changed files with 702 additions and 182 deletions

View File

@@ -1,3 +1,5 @@
from pathlib import Path
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import FileResponse, JSONResponse
@@ -14,6 +16,7 @@ from .routers import jobs as jobs_router
from .routers import models as models_router
from .routers import diagnostics as diagnostics_router
from .routers import files as files_router
from .routers import campaigns as campaigns_router
setup_logging()
log = get_logger(__name__)
@@ -54,11 +57,15 @@ app.include_router(jobs_router.router)
app.include_router(models_router.router)
app.include_router(diagnostics_router.router)
app.include_router(files_router.router)
app.include_router(campaigns_router.router)
@app.get("/api/sessions/{session_id}/audio")
def get_audio(session_id: str):
audio_path = config.AUDIO_DIR / f"{session_id}.wav"
row = db.get_conn().execute("SELECT audio_path FROM sessions WHERE id = ?", (session_id,)).fetchone()
if not row or not row["audio_path"]:
raise HTTPException(404, "Session not found or audio not available")
audio_path = Path(row["audio_path"])
if not audio_path.exists():
raise HTTPException(404, "Audio not available for this session")
return FileResponse(audio_path, media_type="audio/wav")