daemon: agent-driven workspace images — repo→image registry (GET/PUT/DELETE /api/repos), spawn resolves custom image, self-healing lvmh-ops control container with docker.sock; 132 tests, e2e 87/87
This commit is contained in:
+26
@@ -170,6 +170,9 @@ Errors: `{"error": "message"}` with appropriate status.
|
||||
|
||||
| `POST /api/spawn` | `{repo: "group/project", branch?: "main"}` → `{sessionId, containerId}` | clone (per-repo volume) → run container |
|
||||
| `GET /api/spawn/status` | → `[{repo, state, containerId, sessionId?}]` | in-flight clone/spawn jobs |
|
||||
| `GET /api/repos` | → `[{repo, image}]` | repo→custom image registrations, sorted by repo |
|
||||
| `PUT /api/repos/{repo}/image` | `{image}` → `{ok}` | register custom image; repo must pass repo validation, image must match `lvmh-worker-*` |
|
||||
| `DELETE /api/repos/{repo}/image` | → `{ok}` | drop registration (idempotent); repo spawns fall back to `lvmh-worker:latest` |
|
||||
|
||||
`POST /api/spawn` semantics:
|
||||
|
||||
@@ -187,6 +190,26 @@ Errors: `{"error": "message"}` with appropriate status.
|
||||
4. Response returns immediately after container create; status via
|
||||
`/api/spawn/status` and session list.
|
||||
|
||||
**Repo→image resolution:** before creating the container the daemon looks up
|
||||
`repo` in the repo-images registry (`repo_images` table, managed by the
|
||||
`/api/repos` routes). A registered image replaces `lvmh-worker:latest` in
|
||||
the created container; the daemon does NOT build custom images — if the
|
||||
registered image is missing on the docker host the job errors with
|
||||
`custom image <name> not built (ask the ops agent to build it)`. Image names
|
||||
are pinned to the `lvmh-worker-*` namespace by validation. Without a
|
||||
registration (or after DELETE) spawns use the default worker image.
|
||||
|
||||
**Ops container.** The daemon keeps one long-lived control container,
|
||||
`lvmh-ops` (image `lvmh-ops:latest`, built from `docker/control.Dockerfile`
|
||||
when missing): an agent pi with the docker socket mounted, its own
|
||||
`lvmh-ops-work:/ops` workspace volume and the shared session/pi-cache
|
||||
volumes, on the daemon network with a fixed session id `lvmh-ops-control`.
|
||||
It prepares repos, builds per-repo worker images (docker CLI via the socket)
|
||||
and registers them through `/api/repos`. A loop re-checks every 30s: stopped
|
||||
→ started, missing → built+created+started; `DELETE
|
||||
/api/sessions/lvmh-ops-control/container` removes it and the loop recreates
|
||||
it on the next tick with a fresh session.
|
||||
|
||||
### GitLab
|
||||
|
||||
| `GET /api/gitlab/status` | → `{connected: bool, baseUrl, username?}` | |
|
||||
@@ -244,6 +267,7 @@ CREATE TABLE events(sessionId TEXT NOT NULL, seq INTEGER NOT NULL,
|
||||
CREATE TABLE sessions(id TEXT PRIMARY KEY, info TEXT NOT NULL, -- session JSON
|
||||
lastSeq INTEGER NOT NULL DEFAULT 0, lastEventAt INTEGER, online INTEGER DEFAULT 0);
|
||||
CREATE TABLE settings(key TEXT PRIMARY KEY, value TEXT NOT NULL); -- gitlab PAT etc
|
||||
CREATE TABLE repo_images(repo TEXT PRIMARY KEY, image TEXT NOT NULL); -- repo→custom worker image
|
||||
```
|
||||
|
||||
File `lvmh.db` on volume `lvmh-data`.
|
||||
@@ -256,3 +280,5 @@ File `lvmh.db` on volume `lvmh-data`.
|
||||
| `LVMH_TOKEN` | plugin, daemon, web UI storage | shared secret |
|
||||
| `ZAI_RENAUD_API_KEY` | daemon, containers | LLM provider key |
|
||||
| `LVMH_CONTAINER_DOCKER_SOCK` | daemon container | `/var/run/docker.sock` |
|
||||
| `LVMH_GITEA_TOKEN` | ops container | PAT passed through from the daemon store, for repo clone/push |
|
||||
| `LVMH_API` | ops container | `http://lvmh:8686` — daemon REST base for curl |
|
||||
|
||||
Reference in New Issue
Block a user