def create_digest_router(*, db_path: str = "") -> APIRouter:
"""Create a digest API router with the given store path."""
router = APIRouter(prefix="/api/digest", tags=["digest"])
store = DigestStore(db_path=db_path) if db_path else DigestStore()
@router.get("")
async def get_digest():
"""Return the latest digest artifact."""
artifact = store.get_today()
if artifact is None:
raise HTTPException(status_code=404, detail="No digest for today")
return {
"text": artifact.text,
"sections": artifact.sections,
"sources_used": artifact.sources_used,
"generated_at": artifact.generated_at.isoformat(),
"model_used": artifact.model_used,
"voice_used": artifact.voice_used,
"audio_available": (
artifact.audio_path.exists() if artifact.audio_path.name else False
),
}
@router.get("/audio")
async def get_digest_audio():
"""Stream the digest audio file."""
artifact = store.get_today()
if artifact is None:
raise HTTPException(status_code=404, detail="No digest for today")
if not artifact.audio_path.exists():
raise HTTPException(status_code=404, detail="Audio not available")
return FileResponse(
str(artifact.audio_path),
media_type="audio/mpeg",
filename="digest.mp3",
)
@router.post("/generate")
async def generate_digest():
"""Force re-generation of the digest."""
try:
from openjarvis.sdk import Jarvis
with Jarvis() as j:
result = j.ask("Generate my morning digest", agent="morning_digest")
return {"status": "ok", "text": result}
except Exception as exc:
raise HTTPException(status_code=500, detail=str(exc))
@router.get("/history")
async def get_digest_history():
"""Return past digests."""
history = store.history(limit=10)
return [
{
"text": a.text[:200],
"generated_at": a.generated_at.isoformat(),
"model_used": a.model_used,
"voice_used": a.voice_used,
}
for a in history
]
@router.get("/schedule")
async def get_schedule():
"""Return the current digest schedule configuration."""
cfg = load_config()
return {
"enabled": cfg.digest.enabled,
"cron": cfg.digest.schedule,
}
@router.post("/schedule")
async def update_schedule(body: ScheduleUpdate):
"""Update the digest schedule configuration."""
cfg = load_config()
cron = body.cron if body.cron is not None else cfg.digest.schedule
try:
_save_digest_schedule(enabled=body.enabled, cron=cron)
except Exception as exc:
raise HTTPException(
status_code=500,
detail=f"Failed to save config: {exc}",
)
# Sync with the TaskScheduler
if body.enabled:
_create_scheduler_task(cron)
else:
_cancel_scheduler_tasks()
return {
"enabled": body.enabled,
"cron": cron,
}
return router