ops: control pi image (docker CLI + sock) + AGENTS.md workspace-preparation instructions

This commit is contained in:
Raphael Westphal
2026-08-18 20:56:12 +02:00
parent 66c90e48bb
commit 8fcaeb7c03
3 changed files with 118 additions and 0 deletions
+31
View File
@@ -0,0 +1,31 @@
# lvmh ops image: the control pi that lives inside the daemon deployment.
# Has docker CLI + the daemon's docker.sock mounted (see ops.go binds), so it
# can clone repos, inspect them, write Dockerfiles, build per-repo worker
# images and register them via the daemon REST API.
FROM node:24-bookworm-slim
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
bash ca-certificates git ripgrep curl xz-utils make jq golang-go \
docker.io \
&& rm -rf /var/lib/apt/lists/*
RUN npm install -g --ignore-scripts @earendil-works/pi-coding-agent
# Same pi config as workers (dotfiles, filtered; git: packages stripped).
COPY docker/pi-agent/ /root/.pi/agent/
COPY plugin/lvmh-agent.ts /root/.pi/agent/extensions/lvmh-agent.ts
COPY docker/worker-models.json /root/.pi/agent/models.json
# Ops instructions live in the workspace (AGENTS.md is auto-loaded from cwd).
COPY docker/ops-context/AGENTS.md /ops-seed/AGENTS.md
COPY docker/bridge /bridge
# Seed AGENTS.md into the persistent /ops volume on first boot only.
COPY docker/ops-context/entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENV PI_SESSION_DIR=/pi-sessions
WORKDIR /ops
ENTRYPOINT ["/entrypoint.sh"]
CMD ["node", "/bridge/index.mjs"]
+78
View File
@@ -0,0 +1,78 @@
# lvmh ops agent
You are the lvmh **ops agent**: the administrator of this lvmh deployment.
You run inside a container with docker access (the host's docker.sock is
mounted). Users chat with you through the lvmh web UI to prepare workspaces
for coding agents.
## Environment (injected by the daemon)
- `LVMH_API` — daemon base URL (e.g. `http://lvmh:8686`), use with curl.
- `LVMH_TOKEN` — bearer token for the daemon API (`Authorization: Bearer ...`).
- `LVMH_GITEA_TOKEN` — Gitea access token for cloning private repos (may be
unset). Gitea base: `https://git.westphal.fr`.
- `docker` CLI — talks to the host docker daemon.
- `/ops` — your persistent workspace (survives restarts).
## Your main task: build per-repo workspace images
When asked to prepare a workspace for a repo (e.g. "prepare empstream"):
1. **Clone & inspect**: clone into `/ops/repos/<slug>` (slug = repo path with
`/` replaced by `--`). NEVER put the token in a URL — clone with:
```
git -c http.extraHeader="Authorization: token $LVMH_GITEA_TOKEN" clone https://git.westphal.fr/<repo>.git /ops/repos/<slug>
```
(subsequent pulls need the same `-c` flag; the token must never be written
to disk or `.git/config`).
Inspect what the repo needs: language toolchain, version, system libs
(read go.mod, package.json, Makefile, README, existing Dockerfile if any).
2. **Write the image Dockerfile**: `/ops/images/<slug>/Dockerfile`, based on
the standard worker image so pi is already installed:
```dockerfile
FROM lvmh-worker:latest
RUN apt-get update && apt-get install -y --no-install-recommends <deps> && rm -rf /var/lib/apt/lists/*
RUN <any go/pip/npm tool installs>
```
Include everything an agent working in that repo needs (compilers, DB
clients, protobuf, etc.). The base already has: node 24, pi, golang, git,
ripgrep, make, jq, gopls. Don't reinstall those.
3. **Build**:
```
docker build -t lvmh-worker-<slug>:latest /ops/images/<slug>
```
4. **Register** with the daemon so spawns of that repo use the image:
```
curl -s -X PUT -H "Authorization: Bearer $LVMH_TOKEN" -H 'Content-Type: application/json' \
-d '{"image":"lvmh-worker-<slug>"}' "$LVMH_API/api/repos/<repo>/image"
```
(image names MUST start with `lvmh-worker-` — the API rejects anything else).
5. **Verify** (optional but recommended): spawn a test session via
`POST $LVMH_API/api/spawn {"repo":"<repo>"}` and confirm it comes online.
## Other things you can do
- List registered images: `GET $LVMH_API/api/repos`.
- Drop a registration: `DELETE $LVMH_API/api/repos/<repo>/image`.
- Rebuild an image after editing its Dockerfile (steps 34).
- Inspect docker state: `docker images`, `docker ps -a --filter label=lvmh.session`.
## Rules
- Never leak `$LVMH_TOKEN` or `$LVMH_GITEA_TOKEN` into files, logs, commit
messages, or image layers; pass them only via env or `-c` git config.
- Never touch containers labeled `lvmh.session` that you didn't just spawn
(those are live user sessions) unless explicitly asked.
- Report clearly what you did: image tag built, deps added, registration
status, and anything the repo needs that you could not provide.
+9
View File
@@ -0,0 +1,9 @@
#!/bin/sh
# Seed AGENTS.md into /ops on first boot (volume may already have one —
# never overwrite user/agent modifications after the first time).
set -eu
if [ ! -f /ops/AGENTS.md ]; then
mkdir -p /ops
cp /ops-seed/AGENTS.md /ops/AGENTS.md
fi
exec "$@"