@runuai/host 0.8.43 → 0.8.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -47,7 +47,18 @@ import { dockerCli } from "./docker-exec";
47
47
  import { MCP_CONFIG_LOCK_PATH } from "./mcp-config-lock";
48
48
 
49
49
  const SERVER_DISPLAY = ":99";
50
- const XVFB_CMD = `Xvfb ${SERVER_DISPLAY} -screen 0 1440x900x24 -nolisten tcp`;
50
+ /**
51
+ * The virtual screen, and the ONLY place its size is written.
52
+ *
53
+ * Chromium's window has to be told the same numbers (see CHROMIUM_ARGS). There
54
+ * is no window manager on this display — nothing to maximise a window or
55
+ * service a resize — so the window is whatever size it was created at, forever.
56
+ * Two independent copies of "1440x900" would drift, and the failure is quiet:
57
+ * the page renders at the size you asked for while the window shows part of it.
58
+ */
59
+ const SCREEN_W = 1440;
60
+ const SCREEN_H = 900;
61
+ const XVFB_CMD = `Xvfb ${SERVER_DISPLAY} -screen 0 ${SCREEN_W}x${SCREEN_H}x24 -nolisten tcp`;
51
62
 
52
63
  /**
53
64
  * The MCP server package — PINNED, deliberately, and the single source of
@@ -127,6 +138,42 @@ const INSTALL_BROWSER =
127
138
  `PLAYWRIGHT_SKIP_BROWSER_GC=1 timeout --kill-after=10 ${INSTALL_TIMEOUT_S} ` +
128
139
  `npx -y ${MCP_PKG} install-browser ${BROWSER}`;
129
140
  const INSTALL_LOG = "/tmp/uai-pw-browser.log";
141
+
142
+ /**
143
+ * Chromium flags the MCP has no CLI passthrough for, so they ride a config file
144
+ * (`--config`, `browser.launchOptions.args`).
145
+ *
146
+ * `--window-size`/`--window-position` because there is NO WINDOW MANAGER on the
147
+ * virtual display. Chromium opens at its own default — 1050x880 inside a
148
+ * 1440x900 screen — and with nothing to service resize requests, stays there. A
149
+ * later `browser_resize` then only APPEARS to work: Playwright falls back to a
150
+ * CDP device-metrics override, so the page renders at the requested width while
151
+ * the window still shows the leftmost 1050px. Everything past that edge is
152
+ * painted where nobody can see it and nothing reports an error. Window creation
153
+ * is the only moment the size can be set.
154
+ *
155
+ * `--test-type` suppresses "You are using an unsupported command-line flag:
156
+ * --no-sandbox", which we cannot avoid triggering — no user namespaces in the
157
+ * container, so the sandbox has to go. Measured on this exact launch path
158
+ * (persistent context): the infobar costs 56px of viewport, permanently, in a
159
+ * window a human is watching.
160
+ */
161
+ const CHROMIUM_ARGS = [
162
+ "--test-type",
163
+ "--window-position=0,0",
164
+ `--window-size=${SCREEN_W},${SCREEN_H}`,
165
+ ];
166
+ const MCP_LAUNCH_CONFIG = "/tmp/uai-playwright-mcp.json";
167
+ /**
168
+ * Base64, not raw JSON. This command is embedded three ways — a JSON value in
169
+ * `.mcp.json`, a TOML LITERAL in Codex's config, and an `sh -lc` argument — and
170
+ * a literal TOML string cannot contain a single quote at all (`tomlString`
171
+ * throws rather than emit one). Base64's alphabet has no quotes, so the same
172
+ * bytes survive every layer with no escaping rules to get wrong.
173
+ */
174
+ const MCP_LAUNCH_CONFIG_B64 = Buffer.from(
175
+ JSON.stringify({ browser: { launchOptions: { args: CHROMIUM_ARGS } } }),
176
+ ).toString("base64");
130
177
  /** Host-side backstop, deliberately looser than the in-container `timeout`. */
131
178
  const INSTALL_TIMEOUT_MS = 300_000;
132
179
  const MCP_CONFIG_PATH = "/workspace/.mcp.json";
@@ -162,12 +209,16 @@ const X_LOCK = `/tmp/.X${SERVER_DISPLAY.slice(1)}-lock`;
162
209
  // slow. Ensuring the display is fine: Xvfb is local and instant.
163
210
  const SERVER_LAUNCHER =
164
211
  `cd /workspace; ` +
212
+ // Writing a local file is not a download — it stays off the handshake budget.
213
+ `echo ${MCP_LAUNCH_CONFIG_B64} | base64 -d > ${MCP_LAUNCH_CONFIG}; ` +
165
214
  `if command -v Xvfb >/dev/null 2>&1; then ` +
166
215
  `[ -e ${X_LOCK} ] || (nohup ${XVFB_CMD} >>/tmp/uai-xvfb.log 2>&1 &); ` +
167
216
  `sleep 1; export DISPLAY=${SERVER_DISPLAY}; ` +
168
- `exec npx -y ${MCP_PKG} --browser ${BROWSER} --no-sandbox; ` +
217
+ `exec npx -y ${MCP_PKG} --config ${MCP_LAUNCH_CONFIG} ` +
218
+ `--browser ${BROWSER} --no-sandbox; ` +
169
219
  `else ` +
170
- `exec npx -y ${MCP_PKG} --browser ${BROWSER} --no-sandbox --headless; ` +
220
+ `exec npx -y ${MCP_PKG} --config ${MCP_LAUNCH_CONFIG} ` +
221
+ `--browser ${BROWSER} --no-sandbox --headless; ` +
171
222
  `fi`;
172
223
 
173
224
  const SERVER_COMMAND = "sh";
@@ -250,6 +301,24 @@ const HISTORICAL_SERVER_DEFS: Array<Record<string, unknown>> = [
250
301
  `else exec npx -y @playwright/mcp@0.0.78 --browser chromium --no-sandbox --headless; fi`,
251
302
  ],
252
303
  },
304
+ {
305
+ // The pinned launcher BEFORE `--config`: no window geometry and no
306
+ // `--test-type`, so its Chromium opened at 1050x880 on a 1440x900 screen,
307
+ // clipping anything wider, under an infobar. Listed so a container still
308
+ // running it is rewritten rather than left as it is.
309
+ command: "sh",
310
+ args: [
311
+ "-lc",
312
+ `cd /workspace; ` +
313
+ `if command -v Xvfb >/dev/null 2>&1; then ` +
314
+ `[ -e ${X_LOCK} ] || (nohup ${XVFB_CMD} >>/tmp/uai-xvfb.log 2>&1 &); ` +
315
+ `sleep 1; export DISPLAY=${SERVER_DISPLAY}; ` +
316
+ `exec npx -y ${MCP_PKG} --browser ${BROWSER} --no-sandbox; ` +
317
+ `else ` +
318
+ `exec npx -y ${MCP_PKG} --browser ${BROWSER} --no-sandbox --headless; ` +
319
+ `fi`,
320
+ ],
321
+ },
253
322
  SERVER_DEF,
254
323
  ];
255
324
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runuai/host",
3
- "version": "0.8.43",
3
+ "version": "0.8.44",
4
4
  "description": "Uai host — runs ephemeral AI coding tasks in Docker on a machine you control.",
5
5
  "license": "MIT",
6
6
  "author": "Diogo Perillo <diogo.perillo@gmail.com>",