feat: Playwright worker image (@playwright/cli) + capability-driven variants + image/video artifacts (#2) #36
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/playwright"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #2.
Adds an opt-in Playwright worker image so agents can navigate/screenshot apps they build, plus the generalized worker-capability rails the design called for and inline image/video artifacts. History is curated into 4 logical commits.
What's included
1.
refactor(worker)— renamenexus-worker→agent-nexus-worker, node 22 baseBrand-consistent two-repo scheme (
agent-nexus+agent-nexus-worker); base bumped tonode:22-slimwith theorg.nexus.workerlabel. UpdatesWORKER_IMAGE/worker_image-setting defaults, compose, and docs.2.
feat(workers)— label-driven capability registry + per-workspace image selectionWorker images self-describe via OCI labels; a pure capability registry (
nexus/src/lib/server/workers/capabilities.ts) resolves per-image HostConfig deltas (Init+ShmSize) and claude launch-flag deltas — the registry, not the path-only socket proxy, is the security boundary. Adds theworkers.worker_imagecolumn (migration 0010), a label-filteredGET /api/worker-images, spawn-time validation, an image picker in the create-workspace form, and theimageLaunchArgsplumbing.3.
feat(artifacts)— inline image/video artifactsWidens
artifacts.kindtoimage|video(migration 0011 rebuilds the table — SQLite can'tALTERaCHECK), classifies by extension (inferKind+ MIME helper), adds a raw media streaming endpoint (honorsmax_file_bytes, 413 on oversize), and renders<img>/<video>inline in the Artifacts panel.4.
feat(worker)— Playwright image via@playwright/cli+ per-image plugin skillHeadless Chromium baked via
@playwright/cli's bundled core. No MCP server, port, orclaude mcp add-jsonregistration — the agent drives the browser per-command (playwright-cli open|goto|snapshot|click|screenshot|…).@playwright/cli's SKILL is baked as a claude plugin at/opt/nexus/plugins/playwrightand loaded per-session viaclaude --plugin-dir(contributed by the capability registry'slaunchArgs). It lives outside~/.claude, so it reaches only this image's sessions and never the fleet-shared config volume. CI builds the variant (tag suffix-playwright0.1.13).Note:
@playwright/clivs@playwright/mcpThis PR originally used
@playwright/mcp(an always-on HTTP MCP server). It now uses Microsoft's@playwright/cli— their recommended browser-automation surface for coding agents: cleaner (no server/port/registration), more token-efficient, ships a maintained skill, and sidesteps the HTTP-transport MCP stability risk. Both bundle the same alphaplaywright-core, so the browser-version story is unchanged: one baked alpha Chromium for the agent; a project's stablenpx playwright testdoes a one-timenpx playwright install chromium.Verification
Remaining manual smoke (Docker host / CI)
imagesmatrix exercises the buildx base-pre-build for the PlaywrightFROM).playwright-cli --helpworks, theplaywright-cliskill is discoverable (loaded via--plugin-dir, not in~/.claude), a screenshot round-trips throughnotify-artifact, and/dev/shmsizing (1 GiB) holds on a non-trivial page.fdc74d4f3d2c9d2ebec2feat: Playwright worker image + capability-driven variants + image/video artifacts (#2)to feat: Playwright worker image (@playwright/cli) + capability-driven variants + image/video artifacts (#2)2c9d2ebec205dc4d3cd305dc4d3cd33dcfc983753dcfc98375cd50ddb08ecd50ddb08e9f2085961a9f2085961af97dc34d03Two issues surfaced by Playwright smoke-testing: 1. notify-artifact rejected normal screenshots — the 256 KiB max_file_bytes text cap was wrongly applied to binary media. Add a dedicated, operator- configurable media cap: `media_max_file_bytes` instance setting (env MEDIA_MAX_FILE_BYTES, default 10 MiB, range 1 KiB–100 MiB). The pure maxBytesForKind() picks the cap by kind; applied at artifact registration, the artifact raw-serve endpoint, and the worker file-explorer read. 2. The file explorer couldn't view image/video. Render them inline, reusing the Artifacts pane's renderer: - NEW $lib/media.ts — one client-safe ext->{kind,mime} classifier; the server mime.ts (mimeFromPath) and service.ts (inferKind) import it too, so the image/video lists can't drift between client and server. - NEW MediaView.svelte — shared <img>/<video> renderer used by BOTH ArtifactViewer (src = raw endpoint) and FileExplorerPanel (src = data: URL built from the file bytes, read with allowBinary). Settings UI gets a friendly label + help for the new cap. config-explorer reads are uncapped (only writes limit size) so its preview works unchanged. typecheck 0, lint clean, 532 tests, build OK; adversarial review clean (only cosmetic nits, addressed; pre-existing SVG-in-<img> note left as-is).