Skip to content

Commit abbfc7a

Browse files
GiniGini
authored andcommitted
build: add remote E2B workspace image promotion
1 parent e89e28b commit abbfc7a

3 files changed

Lines changed: 90 additions & 1 deletion

File tree

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
name: Build ONEComputer workspace image
2+
3+
on:
4+
workflow_dispatch:
5+
push:
6+
branches:
7+
- codex/onevibe-computer
8+
9+
permissions:
10+
contents: read
11+
packages: write
12+
13+
jobs:
14+
build:
15+
runs-on: ubuntu-24.04
16+
timeout-minutes: 360
17+
steps:
18+
- name: Check out source
19+
uses: actions/checkout@v4
20+
21+
- name: Set up Buildx
22+
uses: docker/setup-buildx-action@v3
23+
24+
- name: Log in to GHCR
25+
uses: docker/login-action@v3
26+
with:
27+
registry: ghcr.io
28+
username: ${{ github.actor }}
29+
password: ${{ secrets.GITHUB_TOKEN }}
30+
31+
- name: Build and publish immutable workspace image
32+
id: image
33+
uses: docker/build-push-action@v6
34+
with:
35+
context: .
36+
file: docker/Dockerfile.workspace
37+
platforms: linux/amd64
38+
push: true
39+
tags: ghcr.io/one-computer/onecomputer-workspace:${{ github.sha }}
40+
labels: |
41+
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
42+
org.opencontainers.image.revision=${{ github.sha }}
43+
provenance: true
44+
sbom: true
45+
cache-from: type=gha,scope=onecomputer-workspace
46+
cache-to: type=gha,mode=max,scope=onecomputer-workspace
47+
48+
- name: Publish digest for E2B template promotion
49+
run: |
50+
echo "Image: ghcr.io/one-computer/onecomputer-workspace@${{ steps.image.outputs.digest }}" >> "$GITHUB_STEP_SUMMARY"
51+
echo "Digest: ${{ steps.image.outputs.digest }}" >> "$GITHUB_STEP_SUMMARY"

docs/ONEVIBE_REAL_E2B_ACP_DEPLOYMENT.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,36 @@ redacted durable activity, replay, approvals, and cleanup proof. No E2B
251251
pause/resume or snapshot behavior is allowed to silently extend a Cowork task
252252
or fabricate a missing ACP transcript.
253253

254+
## ACP and template R&D verification — 2026-08-01
255+
256+
The current ACP sources and the older ONEVibe experiments were reviewed before
257+
the live foundation work. The official ACP repository states that protocol
258+
wire compatibility is determined by the negotiated `initialize` protocol
259+
version, not by the npm package version; optional features must be gated by
260+
the capabilities exchanged during initialization. The official Codex adapter
261+
is a stdio ACP server and supports client-provided custom OpenAI-compatible
262+
gateways. The legacy ONEVibe bridge used a similar stdio lifecycle, but its
263+
default auto-approval path and host-oriented workdir assumptions are not
264+
acceptable for governed E2B execution. The current bridge therefore keeps
265+
permission cancellation as the default, uses task-confined paths, and
266+
configures the gateway in memory before `session/new`.
267+
268+
The ACP streamable-HTTP RFC was also checked. It defines a different transport
269+
shape (connection-scoped and session-scoped SSE streams, `Acp-Connection-Id`,
270+
and `Acp-Session-Id`) for remote ACP servers. ONEComputer does not expose that
271+
transport from the E2B guest: the guest runtime remains stdio, while Control's
272+
canonical SSE is the product-facing replay stream. This avoids treating ACP
273+
transport identifiers as user authentication or as the evidence sequence.
274+
275+
E2B's current template SDK supports private registry credentials on
276+
`Template().fromImage(...)`, while `fromDockerfile(...)` does not support
277+
multi-stage Dockerfiles. The build path therefore publishes the exact
278+
multi-stage workspace image to an OCI registry and passes short-lived registry
279+
credentials only to the E2B template build; credentials are never baked into
280+
the image or committed. The repository's `scripts/build-e2b-template.mts`
281+
now accepts the paired `E2B_REGISTRY_USERNAME` and `E2B_REGISTRY_PASSWORD`
282+
variables for this purpose.
283+
254284
## Current known prerequisite
255285

256286
The repository now contains the provider-hosted ACP bridge and routing logic,

scripts/build-e2b-template.mts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { Template, defaultBuildLogger } from "e2b";
22

33
const image = process.env.ONECOMPUTER_WORKSPACE_IMAGE_REF?.trim();
44
const name = process.env.E2B_TEMPLATE_NAME?.trim() || "onecomputer-workspace:dev";
5+
const registryUsername = process.env.E2B_REGISTRY_USERNAME?.trim();
6+
const registryPassword = process.env.E2B_REGISTRY_PASSWORD?.trim();
57

68
if (!image || !image.includes("@sha256:")) {
79
throw new Error("ONECOMPUTER_WORKSPACE_IMAGE_REF must be a linux/amd64 image pinned by digest");
@@ -12,9 +14,15 @@ if (!process.env.E2B_API_KEY?.trim()) {
1214
if (!/^[A-Za-z0-9][A-Za-z0-9._/-]{0,127}:[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/.test(name)) {
1315
throw new Error("E2B_TEMPLATE_NAME must include an immutable tag, for example onecomputer-workspace:qualification");
1416
}
17+
if (Boolean(registryUsername) !== Boolean(registryPassword)) {
18+
throw new Error("E2B_REGISTRY_USERNAME and E2B_REGISTRY_PASSWORD must be provided together");
19+
}
1520

1621
const template = Template()
17-
.fromImage(image)
22+
.fromImage(image, registryUsername && registryPassword ? {
23+
username: registryUsername,
24+
password: registryPassword,
25+
} : undefined)
1826
.setUser("root");
1927

2028
const build = await Template.build(template, name, {

0 commit comments

Comments
 (0)