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]>
58 lines
2.8 KiB
Docker
58 lines
2.8 KiB
Docker
# clawmates-server: static musl build into distroless. The same image serves
|
|
# the air-gapped bundle and the cloud registry.
|
|
FROM rust:1.96-slim AS builder
|
|
ARG TARGETARCH
|
|
# git + cmake are needed for the clawhdf5 git dependency (fetched via the git
|
|
# CLI — libgit2 chokes on Gitea smart-HTTP) and its zlib-ng C build (cmake).
|
|
RUN apt-get update \
|
|
&& apt-get install -y --no-install-recommends musl-tools git cmake make pkg-config \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
WORKDIR /src
|
|
COPY Cargo.toml Cargo.lock rust-toolchain.toml ./
|
|
COPY crates ./crates
|
|
COPY tools ./tools
|
|
COPY images/seccomp ./images/seccomp
|
|
COPY migrations ./migrations
|
|
COPY .sqlx ./.sqlx
|
|
# Install the musl target AFTER rust-toolchain.toml is in place, so rustup adds
|
|
# it to the toolchain the workspace pins (channel 1.96.0), not the base image's
|
|
# default. Doing this before the COPY installs into a toolchain cargo won't
|
|
# actually use, and the build then fails with E0463 (no core for musl).
|
|
RUN case "$TARGETARCH" in \
|
|
arm64) echo aarch64-unknown-linux-musl > /rust-target ;; \
|
|
*) echo x86_64-unknown-linux-musl > /rust-target ;; \
|
|
esac \
|
|
&& rustup target add "$(cat /rust-target)"
|
|
ENV SQLX_OFFLINE=true
|
|
# Fetch git deps with the system git (libgit2 fails against Gitea smart-HTTP);
|
|
# build the zlib-ng C dep with the musl cross compiler for the static target.
|
|
ENV CARGO_NET_GIT_FETCH_WITH_CLI=true \
|
|
CC_x86_64_unknown_linux_musl=musl-gcc \
|
|
CC_aarch64_unknown_linux_musl=musl-gcc
|
|
RUN cargo build --release --target "$(cat /rust-target)" -p clawmates-server \
|
|
&& cp "target/$(cat /rust-target)/release/clawmates-server" /clawmates-server
|
|
|
|
FROM debian:12-slim
|
|
# git — required at runtime for research topic repo clones
|
|
# (routes/research_setup::ensure_repo_workspace shells out to `git clone`
|
|
# and `git ls-files`). The distroless variant we had here didn't include
|
|
# a git binary; every wizard-materialized research topic silently failed
|
|
# to clone until this change.
|
|
# ca-certificates — required by `git clone` over HTTPS.
|
|
# chromium — headless print-to-pdf for the mission PDF renderer
|
|
# (Slice 6). Ships fonts-liberation so text renders sanely without
|
|
# hitting the web for a font. Set CHROMIUM_BIN=/usr/bin/chromium
|
|
# if the invoking process picks a different name.
|
|
RUN apt-get update \
|
|
&& apt-get install -y --no-install-recommends git ca-certificates \
|
|
chromium fonts-liberation \
|
|
&& rm -rf /var/lib/apt/lists/* \
|
|
&& useradd -u 65532 -M -s /usr/sbin/nologin nonroot
|
|
ENV CHROMIUM_BIN=/usr/bin/chromium
|
|
COPY --from=builder /clawmates-server /usr/local/bin/clawmates-server
|
|
# Builtin templates (team + workflow). Loader upserts them on boot.
|
|
COPY templates /etc/clawmates/templates
|
|
COPY skills /etc/clawmates/skills
|
|
USER 65532
|
|
ENTRYPOINT ["/usr/local/bin/clawmates-server"]
|