Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
7ecffa2
Add persistent browser REPL API specification
rgarcia Aug 2, 2026
3d201ca
Add persistent browser REPL Node runtime
rgarcia Aug 2, 2026
a8386b3
Add POST /browser/execute with API-owned REPL child lifecycle
rgarcia Aug 2, 2026
37ef26e
Bundle browser REPL in both images; add e2e tests and docs
rgarcia Aug 2, 2026
1e4b8b6
Make REPL timeouts destructive; close spec test-plan gaps
rgarcia Aug 2, 2026
eea5216
Address QA findings for the persistent browser REPL
rgarcia Aug 2, 2026
27953ed
Fix REPL helper ergonomics; close remaining QA review gaps
rgarcia Aug 2, 2026
7f09606
Harden browser REPL against frozen renderers; close QA findings
rgarcia Aug 2, 2026
c4ba4f2
Handle process-level REPL failures deterministically; close QA cycle-…
rgarcia Aug 2, 2026
55c3ecc
Close fresh QA cycle-5 findings: const/let semantics, scroll swallow,…
rgarcia Aug 3, 2026
d084c69
Close fresh QA findings: scroll settle window, orphan kill on child-d…
rgarcia Aug 3, 2026
05481b4
Retry first command on a never-answered CDP connection; correct scrol…
rgarcia Aug 3, 2026
7253af5
Replace vendored Acorn with pinned dependency
rgarcia Aug 3, 2026
d2eb55e
Implement SourceTextModule browser REPL cells
rgarcia Aug 10, 2026
a51eb77
Document JavaScript module-cell REPL semantics
rgarcia Aug 10, 2026
89a422b
Fix browser REPL binding identity and var persistence
rgarcia Aug 10, 2026
eb64aec
Fix browser REPL cell invariants and generated docs
rgarcia Aug 10, 2026
f8ddab4
Fix persistent browser REPL cell rewrites
rgarcia Aug 10, 2026
beebea0
Fix browser REPL rewrite and output invariants
rgarcia Aug 10, 2026
18056d3
Fix browser REPL object rest destructuring
rgarcia Aug 10, 2026
e25e4ac
Fix browser REPL request and stray output limits
rgarcia Aug 10, 2026
4ebf79e
Fix stray image output item limit
rgarcia Aug 10, 2026
c1b0db6
Regenerate OpenAPI server with SSE flushing
rgarcia Aug 10, 2026
3a3b907
Reduce browser REPL review surface
rgarcia Aug 10, 2026
1f32d64
Add persistent browser REPL API
rgarcia Sep 2, 2026
d4aeac8
Merge remote-tracking branch 'origin/main' into rgarcia/browser-repl
rgarcia Sep 4, 2026
9249def
Integrate WebMCP with browser REPL
rgarcia Sep 4, 2026
f079941
Support Playwright Core in browser REPL
rgarcia Sep 4, 2026
77e9275
Add Patchright and CDP event waiting
rgarcia Sep 9, 2026
e8b70e1
Add accessibility snapshots and harden browser REPL
rgarcia Sep 9, 2026
973c293
Merge remote-tracking branch 'origin/main' into rgarcia/browser-repl
rgarcia Sep 9, 2026
0f71c0e
Remove redundant Browser REPL key helper
rgarcia Sep 9, 2026
2cd52e0
Simplify Browser REPL image packaging
rgarcia Sep 9, 2026
4fcd797
Simplify browser REPL process cleanup
rgarcia Sep 9, 2026
e4e48db
Encapsulate browser REPL lifecycle
rgarcia Sep 10, 2026
e5fb0c8
Consolidate browser REPL documentation
rgarcia Sep 10, 2026
e5a6cb9
Remove accessibility snapshot license copy
rgarcia Sep 10, 2026
7017a98
Clarify browser REPL CDP ownership
rgarcia Sep 12, 2026
95c0bc0
Name browser REPL CDP client explicitly
rgarcia Sep 12, 2026
037152e
Remove leading browser helpers newline
rgarcia Sep 12, 2026
7a9c182
Add live browser REPL method help
rgarcia Sep 12, 2026
eda0aa2
Trim duplicate browser REPL README documentation
rgarcia Sep 12, 2026
b82c93c
Merge remote-tracking branch 'origin/main' into rgarcia/browser-repl
rgarcia Sep 12, 2026
33ab8f5
Fix Browser REPL navigation and shadow actions
rgarcia Sep 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ Deployed successfully!

## Connect to the browser via Chrome DevTools Protocol

Port `9222` is exposed via `ncat`, allowing you to connect Chrome DevTools Protocol-based browser frameworks like Playwright and Puppeteer (and CDP-based SDKs like Browser Use). You can use these frameworks to drive the browser in the cloud. You can also disconnect from the browser and reconnect to it.
Port `9222` is exposed via `ncat`, allowing you to connect Chrome DevTools Protocol-based browser frameworks like Playwright and Puppeteer. You can use these frameworks to drive the browser in the cloud. You can also disconnect from the browser and reconnect to it.

First, fetch the browser's CDP websocket endpoint:

Expand Down
15 changes: 15 additions & 0 deletions images/chromium-headful/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,21 @@ RUN esbuild /tmp/playwright-daemon.ts \
--external:esbuild \
&& rm /tmp/playwright-daemon.ts /tmp/page-target-id-cache.ts /tmp/webmcp.ts

# Copy and install the browser REPL's pinned runtime dependencies before bundling.
COPY server/runtime/ /tmp/browser-repl/
RUN npm ci --ignore-scripts --no-audit --no-fund --omit=dev --prefix /tmp/browser-repl \
&& mkdir -p /usr/local/lib/browser-repl \
&& cp -a /tmp/browser-repl/node_modules /usr/local/lib/browser-repl/node_modules \
&& esbuild /tmp/browser-repl/browser-repl.ts \
--bundle \
--platform=node \
--target=node22 \
--format=cjs \
--supported:dynamic-import=true \
--external:sharp \
--outfile=/usr/local/lib/browser-repl/browser-repl.js \
&& rm -rf /tmp/browser-repl

RUN useradd -m -s /bin/bash kernel

# Bake the envoy forward-proxy CA cert into the image (system trust store +
Expand Down
15 changes: 15 additions & 0 deletions images/chromium-headless/image/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -301,4 +301,19 @@ RUN esbuild /tmp/playwright-daemon.ts \
--external:esbuild \
&& rm /tmp/playwright-daemon.ts /tmp/page-target-id-cache.ts /tmp/webmcp.ts

# Copy and install the browser REPL's pinned runtime dependencies before bundling.
COPY server/runtime/ /tmp/browser-repl/
RUN npm ci --ignore-scripts --no-audit --no-fund --omit=dev --prefix /tmp/browser-repl \
&& mkdir -p /usr/local/lib/browser-repl \
&& cp -a /tmp/browser-repl/node_modules /usr/local/lib/browser-repl/node_modules \
&& esbuild /tmp/browser-repl/browser-repl.ts \
--bundle \
--platform=node \
--target=node22 \
--format=cjs \
--supported:dynamic-import=true \
--external:sharp \
--outfile=/usr/local/lib/browser-repl/browser-repl.js \
&& rm -rf /tmp/browser-repl

ENTRYPOINT [ "/wrapper" ]
16 changes: 13 additions & 3 deletions server/Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
SHELL := /bin/bash
.PHONY: oapi-generate build dev test test-unit test-runtime test-e2e clean
.PHONY: oapi-generate repl-help-generate repl-help-check runtime-typecheck build dev test test-unit test-runtime test-e2e clean

BIN_DIR ?= $(CURDIR)/bin
RECORDING_DIR ?= $(CURDIR)/recordings
Expand All @@ -14,7 +14,17 @@ $(RECORDING_DIR):
# 1. Convert 3.1 → 3.0 since oapi-codegen doesn't support 3.1 yet (https://github.com/oapi-codegen/oapi-codegen/issues/373)
# 2. Run oapi-codegen with our config (version pinned via go.mod tool directive)
# 3. go mod tidy to pull deps
oapi-generate:
runtime-typecheck:
npm ci --ignore-scripts --no-audit --no-fund --prefix ./runtime
npm run typecheck --prefix ./runtime

repl-help-generate:
node --no-warnings ./scripts/replhelp/main.mjs

repl-help-check:
node --no-warnings ./scripts/replhelp/main.mjs --check

oapi-generate: repl-help-generate
pnpm i -g @apiture/openapi-down-convert
openapi-down-convert --input openapi.yaml --output openapi-3.0.yaml --allOf
go tool oapi-codegen -config ./oapi-codegen.yaml ./openapi-3.0.yaml
Expand All @@ -39,7 +49,7 @@ test-unit:
go vet ./...
go test -v -race $$(go list ./... | grep -v /e2e$$)

test-runtime:
test-runtime: runtime-typecheck repl-help-check
node --test runtime/*.test.ts

test-e2e:
Expand Down
1 change: 1 addition & 0 deletions server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export OUTPUT_DIR=/tmp/recordings

- **YAML Spec**: `GET /spec.yaml`
- **JSON Spec**: `GET /spec.json`
- **Browser REPL guide**: [`docs/repl.md`](docs/repl.md)

## 🔧 Development

Expand Down
7 changes: 6 additions & 1 deletion server/cmd/api/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ type ApiService struct {
// playwrightDaemonCmd holds the daemon process for cleanup
playwrightDaemonCmd *exec.Cmd

browserRepl *browserReplManager

webmcp webMCPClient

// policy management
Expand Down Expand Up @@ -169,6 +171,7 @@ func New(
cdpMonitor: mon,
otlpExport: otlpExport,
webmcp: webmcpclient.NewManager(upstreamMgr),
browserRepl: newBrowserReplManager(),
lifecycleCtx: ctx,
lifecycleCancel: cancel,
}, nil
Expand Down Expand Up @@ -431,6 +434,8 @@ func (s *ApiService) ListRecorders(ctx context.Context, _ oapi.ListRecordersRequ
}

func (s *ApiService) Shutdown(ctx context.Context) error {
replErr := s.browserRepl.Shutdown(ctx)

_ = s.webmcp.Close()
s.monitorMu.Lock()
s.lifecycleCancel()
Expand All @@ -439,5 +444,5 @@ func (s *ApiService) Shutdown(ctx context.Context) error {
s.monitorMu.Unlock()
// The OTLP export sink is stopped by main after the servers drain, so any
// events they emit on the way down are still exported (mirrors s2Writer).
return s.recordManager.StopAll(ctx)
return errors.Join(replErr, s.recordManager.StopAll(ctx))
}
Loading
Loading