release: v2.9.0 — agent-browser, manifest reader, opencode 1.18.13
Not tagged yet; this is the v2.9.0 changeset landing on main. Added - agent-browser + a Playwright-managed headless Chromium in the base (~625 MB after deleting the redundant chromium_headless_shell build), so an agent can drive a real browser and VERIFY front-end work instead of assuming it renders. Ported from pi-devbox. AGENT_BROWSER_EXECUTABLE_PATH points at the stable symlink /usr/local/bin/agent-chrome, which the Dockerfile resolves with `find` rather than hardcoding: Playwright's browser dir is per-version AND per-arch (chrome-linux on arm64, chrome-linux64 on amd64), and the headless shell binary is named chrome-headless-shell so `-name chrome` skips it. - opencode-devbox-version: a reader for the build manifest. The image has baked ground truth to /etc/opencode-devbox/build-manifest.json for several releases, but nothing read it and nothing printed it — so "which image am I running?" meant knowing the path by heart. Three modes (--json/--quiet/human), plus a live-vs-baked drift check, because NPM_CONFIG_PREFIX points at the persistent config volume and a user `npm install -g opencode` can shadow the baked binary. entrypoint-user.sh prints it as its first output. - ENV COLORTERM=truecolor, completing a true-colour story the image already half-shipped (terminfo entries + Neovim termguicolors, but no capability advertisement, so bat/delta fell back to 256 colours). - Smoke assertions for agent-browser, that agent-chrome resolves to an executable (catches a Playwright layout change, not just a dangling symlink), COLORTERM, the manifest's release_tag, and all three version-command modes. Changed - opencode 1.17.20 -> 1.18.13. Verified by diffing upstream source, not release notes: core config.ts, config/provider.ts and schema.json are byte-identical, so generate-config.py needs no change. 1.18.13 (published mid-audit) was re-verified separately — 249 files in the compare payload, under GitHub's 300-file cap, so the list is complete rather than truncated; content is the Electron app plus localisation; the five contract-surface files hash identical at both tags. The bg-subagents removal trigger has NOT fired: runtime-flags.ts still gates the flag behind OPENCODE_EXPERIMENTAL at all three tags. - yq: dropped Debian's apt package (the unrelated Python kislyuk/yq — jq syntax, 3.x line) for mikefarah's Go yq v4 from GitHub. The cloud-init repo's provision.sh/deploy.sh need v4 syntax, and THIRD_PARTY.md already credited "yq (mikefarah)" while the image shipped the Python one, so this also closes a documented-vs-shipped mismatch. Smoke pins the contract to mikefarah v4. BEHAVIOUR CHANGE for any in-image script calling yq with jq-style syntax. - mempalace pin 3.5.0 -> 3.6.0, in lockstep with pi-devbox (5724302). Reviewed for MCP tool-schema changes before bumping — none, and nothing touches diary_write. - Default models -> claude-opus-5 (anthropic, and bedrock's global.anthropic.claude-opus-5) and openai/gpt-5.6. gpt-5.4 had gone stale: gpt-5.6 shipped four days before the v2.8.0 cut. Affects only new containers with no OPENCODE_MODEL and no existing config. - Smoke size thresholds +650 MB (base 2950->3600, omos 3650->4300), sized to keep the same ~250 MB headroom so the guardrail still catches runaway growth rather than routine apt drift. Do NOT copy pi-devbox's number: it sums `docker history`, this repo uses `docker image inspect .Size`. Documentation - New README section "Choosing a provider and model", making explicit that the baked defaults are only defaults and nobody is locked to Anthropic/Bedrock, including the three real gotchas: defaults seed only a NEW config, an existing opencode.jsonc on the persistent volume is never rewritten, and switching model needs no rebuild. - New README section "Browser automation (agent-browser)"; opencode-devbox-version documented under Build provenance; COLORTERM under Terminal compatibility. - README Build Args table drift fixed — FOUR missing args added (AGENT_BROWSER_VERSION, PLAYWRIGHT_VERSION, YQ_VERSION and GITLEAKS_VERSION, the last of which had existed as an ARG but was never listed), plus rows for the two pinned args absent entirely (MEMPALACE_VERSION, DEBIAN_VERSION), plus a refreshed stale OPENCODE_VERSION example. Third consecutive release to find drift in this table. - AGENTS.md: the stale MemPalace anyOf convention rewritten. It described a perl RUN block already DELETED at the 3.5.0 bump and asserted "PyPI latest is 3.4.0 (== our pin), no release contains the fix yet, the workaround must stay" — all three false. Replaced with a pin-review rule. Two new conventions added: the agent-browser/Chromium size coupling, and the yq identity trap. - THIRD_PARTY.md: agent-browser, Playwright, Chromium. Verified locally with the CI-pinned hadolint 2.14.0 and actionlint 1.7.7, the shell guard, DOCKER_HUB.md sync, bash -n, py_compile, and by generating the config for all three providers.
This commit is contained in:
+86
-3
@@ -50,7 +50,6 @@ RUN apt-get update && \
|
||||
openssh-client \
|
||||
gnupg \
|
||||
jq \
|
||||
yq \
|
||||
ripgrep \
|
||||
fd-find \
|
||||
tree \
|
||||
@@ -351,6 +350,29 @@ RUN ARCH=$(case "${TARGETARCH}" in amd64) echo "x86_64" ;; arm64) echo "aarch64"
|
||||
sed -i 's/^ font: (),$/ font: ("Libertinus Serif",),/' /usr/share/pandoc/data/templates/template.typst && \
|
||||
grep -q 'font: ("Libertinus Serif",),' /usr/share/pandoc/data/templates/template.typst
|
||||
|
||||
# ── yq (mikefarah) — YAML processor, jq's companion for YAML ─────────
|
||||
# Installed as the mikefarah Go binary — NOT Debian's `yq` apt package, which
|
||||
# is the unrelated Python kislyuk/yq (a jq wrapper with different syntax and a
|
||||
# different version line, 3.x). THIRD_PARTY.md already credited "yq
|
||||
# (mikefarah)" while the image actually shipped the Python one, so this closes
|
||||
# a documented-vs-shipped mismatch as well as bringing parity with pi-devbox
|
||||
# (its v1.2.3). The cloud-init repo's deploy.sh/provision.sh require mikefarah
|
||||
# v4 syntax. Follows the repo's `latest` convention (like tealdeer/uv/typst);
|
||||
# the smoke test pins the contract to major v4, so both a regression to the
|
||||
# Python package and a surprise future yq v5 fail CI loudly instead of
|
||||
# silently breaking those scripts. Pin a tag with --build-arg YQ_VERSION=vX.Y.Z.
|
||||
ARG YQ_VERSION=latest
|
||||
RUN ARCH=$(case "${TARGETARCH}" in amd64) echo "amd64" ;; arm64) echo "arm64" ;; *) echo "amd64" ;; esac) && \
|
||||
V="${YQ_VERSION}" && \
|
||||
if [ "$V" = "latest" ]; then \
|
||||
V=$(curl -sI --retry 5 --retry-delay 5 --retry-all-errors "https://github.com/mikefarah/yq/releases/latest" | awk 'tolower($1)=="location:" { sub(/\r$/,"",$2); n=split($2,a,"/"); print a[n] }'); \
|
||||
fi && \
|
||||
[ -n "$V" ] && \
|
||||
echo "Installing mikefarah yq ${V}" && \
|
||||
curl -fsSL --retry 5 --retry-delay 5 --retry-all-errors "https://github.com/mikefarah/yq/releases/download/${V}/yq_linux_${ARCH}" -o /usr/local/bin/yq && \
|
||||
chmod +x /usr/local/bin/yq && \
|
||||
yq --version
|
||||
|
||||
# ── MemPalace — local-first AI memory system ─────────────────────────
|
||||
# Provides semantic search over conversation history via 29 MCP tools.
|
||||
# Always installed in the base (variant-independent). Set
|
||||
@@ -367,7 +389,17 @@ ARG INSTALL_MEMPALACE=true
|
||||
# `"required": ["agent_name"]` with entry/content enforced at dispatch, which
|
||||
# the Anthropic tools API accepts — so the perl mcp_server.py workaround that
|
||||
# used to live below is gone. (pi-devbox dropped it in its v1.2.2.)
|
||||
ARG MEMPALACE_VERSION=3.5.0
|
||||
#
|
||||
# 3.6.0 (2026-07-17) is an additive/reliability release — secure `mempalace
|
||||
# serve` remote mode, optional Milvus backend, atomic KG supersede(),
|
||||
# conversation chronology, mining exclusions, plus recovery/locking fixes.
|
||||
# Reviewed for MCP tool-schema changes before bumping: there are NONE, and
|
||||
# nothing touches diary_write — so the 3.3.x/3.4.0 regression class does not
|
||||
# recur. Two fixes are directly relevant to how this image uses mempalace:
|
||||
# read-only mode now covers checkpoint + delete_by_source in _MUTATING_TOOLS
|
||||
# (#1930), and agent attribution is preserved in mempalace_checkpoint
|
||||
# (#2023/#2034).
|
||||
ARG MEMPALACE_VERSION=3.6.0
|
||||
ENV UV_TOOL_DIR=/opt/uv-tools
|
||||
ENV UV_TOOL_BIN_DIR=/usr/local/bin
|
||||
RUN if [ "${INSTALL_MEMPALACE}" = "true" ]; then \
|
||||
@@ -439,6 +471,12 @@ ENV LANG=en_US.UTF-8
|
||||
ENV LANGUAGE=en_US:en
|
||||
ENV LC_ALL=en_US.UTF-8
|
||||
ENV EDITOR=nvim
|
||||
# Advertise 24-bit colour so colour-aware tools (Neovim's own auto-detect, bat,
|
||||
# delta, ...) use true colour instead of a 256-colour fallback. Completes the
|
||||
# true-colour story the terminfo + sysinit.vim layers below already start.
|
||||
# Safe for the modern terminals this devbox targets; override by exporting
|
||||
# `COLORTERM=` (empty) from a terminal that lacks true-colour support.
|
||||
ENV COLORTERM=truecolor
|
||||
ENV PATH="/home/developer/.local/bin:/home/developer/.cargo/bin:${PATH}"
|
||||
# Enable opencode's native background subagents. opencode gates this behind an
|
||||
# experimental flag (packages/opencode/src/tool/task.ts errors with
|
||||
@@ -449,7 +487,9 @@ ENV PATH="/home/developer/.local/bin:/home/developer/.cargo/bin:${PATH}"
|
||||
# *enables* a capability). Overridable at runtime: -e OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=false.
|
||||
# REMOVAL TRIGGER: when opencode promotes background subagents out of experimental
|
||||
# (flag becomes default / renamed), drop this ENV. No upstream roadmap date as of
|
||||
# opencode 1.17.20 / omos 2.2.0 (2026-07).
|
||||
# opencode 1.18.13 / omos 2.2.9 (2026-08). Re-verified against upstream source
|
||||
# at all three tags (1.17.20, 1.18.12, 1.18.13): packages/opencode/src/effect/runtime-flags.ts
|
||||
# is unchanged and still gates the flag behind OPENCODE_EXPERIMENTAL — trigger has NOT fired.
|
||||
ENV OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true
|
||||
|
||||
# ── Node.js (required for opencode/pi/omos at variant build + MCP servers) ──
|
||||
@@ -458,6 +498,45 @@ RUN curl -fsSL --retry 5 --retry-delay 5 --retry-all-errors https://deb.nodesour
|
||||
apt-get install -y --no-install-recommends nodejs && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# ── agent-browser + Playwright Chromium — real-browser verification ──
|
||||
# Lets the agent drive an actual browser (open pages, click/fill/eval, snapshot
|
||||
# the DOM, screenshot) to VERIFY front-end work — live DOM, WebGL, layout,
|
||||
# popup positioning — instead of guessing. Ported from pi-devbox.
|
||||
#
|
||||
# We resolve the Chrome binary through a stable symlink (/usr/local/bin/
|
||||
# agent-chrome) exposed via AGENT_BROWSER_EXECUTABLE_PATH — the symlink
|
||||
# insulates the ENV from Playwright's per-version, per-ARCH browser directory
|
||||
# (`chrome-linux` on arm64, `chrome-linux64` on amd64 — Chrome-for-Testing), so
|
||||
# we `find` the `chrome` binary rather than hardcode the path; the headless-shell
|
||||
# binary is named `chrome-headless-shell`, so `-name chrome` skips it.
|
||||
#
|
||||
# `playwright install --with-deps chromium` also apt-installs Chromium's runtime
|
||||
# libs; verified to resolve correctly on Debian trixie (the t64 library renames
|
||||
# are handled by Playwright's dep list). The build runs as root, so the apt step
|
||||
# works. NPM_CONFIG_PREFIX=/usr keeps both CLIs on /usr so they survive the
|
||||
# ~/.config/opencode/npm-global volume mount (the same trick the variant uses
|
||||
# for opencode). After fetching, we DROP Playwright's `chromium_headless_shell-*`
|
||||
# build — agent-browser drives the full chrome, so the headless shell is dead
|
||||
# weight — and clean the apt/npm caches, trimming the layer to ~625 MB from
|
||||
# ~960 MB. This is the bulk of the base's size and the one real tradeoff of
|
||||
# shipping it to every variant; the smoke-test size thresholds were lifted in
|
||||
# lockstep (see scripts/smoke-test.sh).
|
||||
ARG AGENT_BROWSER_VERSION=latest
|
||||
ARG PLAYWRIGHT_VERSION=latest
|
||||
ENV PLAYWRIGHT_BROWSERS_PATH=/usr/local/share/ms-playwright
|
||||
RUN NPM_CONFIG_PREFIX=/usr npm install -g \
|
||||
"agent-browser@${AGENT_BROWSER_VERSION}" \
|
||||
"playwright@${PLAYWRIGHT_VERSION}" && \
|
||||
playwright install --with-deps chromium && \
|
||||
CHROME="$(find "${PLAYWRIGHT_BROWSERS_PATH}" -type f -name chrome -path '*/chromium-*/*' | head -n1)" && \
|
||||
[ -n "$CHROME" ] && ln -sf "$CHROME" /usr/local/bin/agent-chrome && \
|
||||
agent-browser --version && \
|
||||
test -x "$(readlink -f /usr/local/bin/agent-chrome)" && \
|
||||
rm -rf "${PLAYWRIGHT_BROWSERS_PATH}"/chromium_headless_shell-* && \
|
||||
npm cache clean --force && \
|
||||
rm -rf /var/lib/apt/lists/* /root/.npm /tmp/*
|
||||
ENV AGENT_BROWSER_EXECUTABLE_PATH=/usr/local/bin/agent-chrome
|
||||
|
||||
# ── AWS CLI v2 (for SSO/Bedrock authentication) ─────────────────────
|
||||
RUN ARCH=$(case "${TARGETARCH}" in \
|
||||
amd64) echo "x86_64" ;; \
|
||||
@@ -551,6 +630,9 @@ RUN tic -x -o /usr/share/terminfo /usr/local/share/terminfo-src/ghostty.terminfo
|
||||
# ── Entrypoint ────────────────────────────────────────────────────────
|
||||
COPY rootfs/usr/local/lib/opencode-devbox/ /usr/local/lib/opencode-devbox/
|
||||
COPY rootfs/usr/local/bin/dot-watch /usr/local/bin/dot-watch
|
||||
# Reader for the build manifest baked in Dockerfile.variant. Printed at
|
||||
# container start by entrypoint-user.sh; also available on demand.
|
||||
COPY rootfs/usr/local/bin/opencode-devbox-version /usr/local/bin/opencode-devbox-version
|
||||
# Image-baked skills + harness instruction. Under /usr/local so a named volume
|
||||
# over a home dir (e.g. devbox-opencode-config on ~/.config/opencode) can't
|
||||
# shadow them; entrypoint-user.sh links them into ~/.agents/skills/ and
|
||||
@@ -561,6 +643,7 @@ COPY entrypoint.sh /usr/local/bin/entrypoint.sh
|
||||
COPY entrypoint-user.sh /usr/local/bin/entrypoint-user.sh
|
||||
RUN chmod +x /usr/local/bin/entrypoint.sh /usr/local/bin/entrypoint-user.sh \
|
||||
/usr/local/bin/dot-watch \
|
||||
/usr/local/bin/opencode-devbox-version \
|
||||
/usr/local/lib/opencode-devbox/*.py
|
||||
|
||||
# Start as root — entrypoint adjusts UID/GID then drops to developer
|
||||
|
||||
Reference in New Issue
Block a user