slice 6: LLM + Chromium PDF renderer worker
Watches mission_artifacts for MD entries with render_pdf_status='pending'
and turns them into styled PDFs via:
1. Read source MD from <mission_root>/<path>
2. Call configured LLM (default gemini-2.5-flash) with a document-
typesetter system prompt that constrains style to a self-contained
HTML doc with inline CSS + our color palette
3. Print to PDF via `chromium --headless=new --print-to-pdf`
4. Save alongside source MD (foo.md → foo.pdf) + update
mission_artifacts.rendered_pdf_path + render_pdf_status='done'
Graceful degradation: GEMINI_API_KEY unset OR chromium missing =
row marked failed with a descriptive error, worker keeps ticking.
The frontend's "Open PDF" affordance (Slice 2) light up automatically
when render succeeds.
Boot ordering: PDF worker spawns after task_card_worker. Poll every
30s over up to MAX_PARALLEL=2 rows at a time — respects LLM rate
limits and keeps chromium's peak RAM under control.
Env knobs:
GEMINI_API_KEY — required for LLM step
CLAWMATES_PDF_RENDERER_MODEL — model id, default gemini-2.5-flash
CHROMIUM_BIN — chromium binary, default `chromium`
CLAWMATES_MISSIONS_ROOT — artifact dir root, default /var/lib/clawmates-missions
Dockerfile now installs chromium + fonts-liberation and sets
CHROMIUM_BIN=/usr/bin/chromium so the container image has everything
the renderer needs.
Also bumps workspace tokio deps to include the `process` feature
(required for tokio::process::Command).
Follow-ups:
- Anthropic + OpenAI provider variants (only Gemini in this slice)
- SSE stream on /api/missions/{id}/artifacts for the "PDF ready"
notification instead of poll-via-mission-GET
- Per-template PDF style overrides (currently one house style
for all missions)
Co-Authored-By: Claude Opus 4.7 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
f40ec075a5
commit
3ac3d53da7
@@ -288,6 +288,12 @@ async fn run() -> Result<(), String> {
|
||||
// for INT-XX markers in event payloads and upserts mission_tasks
|
||||
// rows so the canvas renders a live status timeline.
|
||||
cm_api::task_card_worker::spawn(pool.clone());
|
||||
// PDF renderer worker (Slice 6): watches mission_artifacts for
|
||||
// MD entries with render_pdf_status='pending', calls the
|
||||
// configured LLM (default Gemini 2.5 Flash) for styled HTML,
|
||||
// prints to PDF via chromium --headless. No-op-friendly when
|
||||
// GEMINI_API_KEY / chromium binary aren't configured.
|
||||
cm_api::pdf_renderer::spawn(pool.clone());
|
||||
// Outbound-email delivery: drains the §15-gated `outbox` over SMTP. Inert
|
||||
// until CLAWMATES_SMTP_* is set, so it ships safely before credentials exist.
|
||||
cm_runtime::spawn_drainer(pool.clone(), std::time::Duration::from_secs(10));
|
||||
|
||||
Reference in New Issue
Block a user