- Dockerfile: install acpx@latest alongside @anthropic-ai/claude-code
- compose.yml: bind /mnt/user/appdata/clawdforge/acpx-sessions:/root/.acpx/sessions
- DB: additive sessions + session_events tables in store.py SCHEMA
- clawdforge/acpx_runner.py: AcpxManager + AcpxSession, bounded async pool,
per-invocation subprocess model (acpx CLI itself owns the queue-owner
lifecycle, so each turn = one fresh `acpx prompt -s <uuid>` call)
- server.py: POST/GET/DELETE /sessions + POST /sessions/{id}/turn + GET /sessions
- Per-app isolation: 404 (not 403) on cross-token session access — no
existence leak across tokens
- Lifespan-managed TTL sweeper: every 60s soft-closes idle sessions past
CLAWDFORGE_SESSION_TTL_SECS (1h default), hard-deletes ledger rows past
CLAWDFORGE_SESSION_HARD_TTL_SECS (24h default)
- session_events audit table parallel to existing runs table
(events: create, turn, close, sweep_close, hard_delete)
- /healthz now reports acpx_present + acpx_version + open_sessions count
- tests/test_sessions.py: 16 tests covering create/turn/close/list/isolation/
sweep/pool-full/regression. /run regression test asserts byte-identical
v0.1 response shape.
ACPX research notes (v0.6.1, openclaw/acpx):
- npm package is `acpx`, not `@openclaw/acpx`
- Sessions are scoped by (agentCommand, cwd, name?). We mint our own UUID
as `--name` and give every session a unique cwd subdir, so the scope key
is collision-free across apps.
- session_id source: ours. We pass --name <uuid>, ACPX records it under
~/.acpx/sessions/<encoded-id>.json. We never need to parse ACPX's
acpxRecordId — our UUID is canonical.
- Subprocess lifetime: per-invocation, NOT per-session. The acpx CLI itself
spawns/maintains a per-session "queue owner" process via local IPC; each
`acpx prompt` call we make either elects itself owner or enqueues. The
AcpxSession class is therefore a thin (uuid, cwd, asyncio.Lock) handle,
not a long-lived stdio pipe. The spec's "owns one stdio pipe pair" model
was rewritten to match reality — flagged here.
- Close semantics: soft-close via `acpx sessions close <name>`. The
on-disk record stays (ACPX's `sessions prune` is the hard-delete path,
not invoked from clawdforge). DELETE /sessions/<id> is documented as
idempotent (200 with already_closed=true on second call) so SDKs can
call close() in finally/Drop blocks safely.
- File uploads: ACPX has no file-attach ACP method exposed via the CLI.
We prepend a [Attached files] header listing absolute paths; the agent
uses its Read tool to open them. Same behavior as /run --files in v0.1.
- Permissions: --approve-all on the turn invocation since the container is
unattended and callers are bearer-token-trusted. Future v0.3 may expose
a per-session permission policy.
/run endpoint unchanged — backwards compat verified by
test_run_endpoint_unchanged + test_run_endpoint_unchanged_error_shape.
Spec: memory/spec-clawdforge-v0.2.md
ACPX CLI ref: https://github.com/openclaw/acpx/blob/main/docs/CLI.md
41 lines
1.4 KiB
Docker
41 lines
1.4 KiB
Docker
FROM node:22-bookworm-slim
|
|
|
|
# System deps + Python (claude code is npm; our wrapper is Python)
|
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
python3 python3-pip python3-venv \
|
|
ca-certificates curl git \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
# Claude Code CLI
|
|
RUN npm install -g @anthropic-ai/claude-code
|
|
|
|
# ACPX — headless Agent Client Protocol CLI (https://github.com/openclaw/acpx).
|
|
# Drives multi-turn /sessions endpoints. Shares Claude Code auth from /root/.claude.
|
|
RUN npm install -g acpx@latest
|
|
|
|
# Python deps in a venv
|
|
ENV VIRTUAL_ENV=/opt/venv
|
|
RUN python3 -m venv $VIRTUAL_ENV
|
|
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
|
|
|
|
WORKDIR /app
|
|
COPY requirements.txt /app/requirements.txt
|
|
RUN pip install --no-cache-dir -r requirements.txt
|
|
|
|
COPY clawdforge /app/clawdforge
|
|
|
|
# Persistent volume mount points:
|
|
# /data -> sqlite + runs staging
|
|
# /root/.claude -> claude code auth (cobb runs `claude /login` once per container)
|
|
# /root/.config/claude -> alt config path some claude versions use
|
|
# /root/.acpx/sessions -> acpx session metadata (per-session JSON files)
|
|
RUN mkdir -p /data /root/.claude /root/.config/claude /root/.acpx/sessions \
|
|
&& chmod 700 /root/.acpx
|
|
|
|
EXPOSE 8800
|
|
|
|
CMD ["uvicorn", "clawdforge.server:app", \
|
|
"--host", "0.0.0.0", "--port", "8800", \
|
|
"--workers", "1", \
|
|
"--proxy-headers", \
|
|
"--access-log"]
|