diff --git a/src/agents/clawdis-tools.ts b/src/agents/clawdis-tools.ts index ffcfa4d44..15b333270 100644 --- a/src/agents/clawdis-tools.ts +++ b/src/agents/clawdis-tools.ts @@ -575,7 +575,9 @@ const BrowserToolSchema = Type.Union([ }), ]); -function createBrowserTool(opts?: { defaultControlUrl?: string }): AnyAgentTool { +function createBrowserTool(opts?: { + defaultControlUrl?: string; +}): AnyAgentTool { return { label: "Browser", name: "browser", diff --git a/src/agents/pi-embedded-runner.test.ts b/src/agents/pi-embedded-runner.test.ts index 1e34e0eb0..462434378 100644 --- a/src/agents/pi-embedded-runner.test.ts +++ b/src/agents/pi-embedded-runner.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it } from "vitest"; -import type { SandboxContext } from "./sandbox.js"; import { buildEmbeddedSandboxInfo } from "./pi-embedded-runner.js"; +import type { SandboxContext } from "./sandbox.js"; describe("buildEmbeddedSandboxInfo", () => { it("returns undefined when sandbox is missing", () => { diff --git a/src/agents/sandbox.ts b/src/agents/sandbox.ts index d65f1da2e..338a66191 100644 --- a/src/agents/sandbox.ts +++ b/src/agents/sandbox.ts @@ -4,15 +4,15 @@ import fs from "node:fs/promises"; import os from "node:os"; import path from "node:path"; -import type { ClawdisConfig } from "../config/config.js"; -import { STATE_DIR_CLAWDIS } from "../config/config.js"; -import { DEFAULT_CLAWD_BROWSER_COLOR } from "../browser/constants.js"; -import type { ResolvedBrowserConfig } from "../browser/config.js"; import { type BrowserBridge, startBrowserBridgeServer, stopBrowserBridgeServer, } from "../browser/bridge-server.js"; +import type { ResolvedBrowserConfig } from "../browser/config.js"; +import { DEFAULT_CLAWD_BROWSER_COLOR } from "../browser/constants.js"; +import type { ClawdisConfig } from "../config/config.js"; +import { STATE_DIR_CLAWDIS } from "../config/config.js"; import { defaultRuntime } from "../runtime.js"; import { resolveUserPath } from "../utils.js"; import { @@ -357,10 +357,9 @@ function execDocker(args: string[], opts?: { allowFailure?: boolean }) { } async function readDockerPort(containerName: string, port: number) { - const result = await execDocker( - ["port", containerName, `${port}/tcp`], - { allowFailure: true }, - ); + const result = await execDocker(["port", containerName, `${port}/tcp`], { + allowFailure: true, + }); if (result.code !== 0) return null; const line = result.stdout.trim().split(/\r?\n/)[0] ?? ""; const match = line.match(/:(\d+)\s*$/); @@ -552,22 +551,17 @@ async function ensureSandboxBrowser(params: { for (const entry of params.cfg.docker.tmpfs) { args.push("--tmpfs", entry); } - if (params.cfg.docker.network) args.push("--network", params.cfg.docker.network); + if (params.cfg.docker.network) + args.push("--network", params.cfg.docker.network); if (params.cfg.docker.user) args.push("--user", params.cfg.docker.user); for (const cap of params.cfg.docker.capDrop) { args.push("--cap-drop", cap); } args.push("--security-opt", "no-new-privileges"); args.push("-v", `${params.workspaceDir}:${params.cfg.docker.workdir}`); - args.push( - "-p", - `127.0.0.1::${params.cfg.browser.cdpPort}`, - ); + args.push("-p", `127.0.0.1::${params.cfg.browser.cdpPort}`); if (params.cfg.browser.enableNoVnc && !params.cfg.browser.headless) { - args.push( - "-p", - `127.0.0.1::${params.cfg.browser.noVncPort}`, - ); + args.push("-p", `127.0.0.1::${params.cfg.browser.noVncPort}`); } args.push( "-e", @@ -579,14 +573,8 @@ async function ensureSandboxBrowser(params: { params.cfg.browser.enableNoVnc ? "1" : "0" }`, ); - args.push( - "-e", - `CLAWDIS_BROWSER_CDP_PORT=${params.cfg.browser.cdpPort}`, - ); - args.push( - "-e", - `CLAWDIS_BROWSER_VNC_PORT=${params.cfg.browser.vncPort}`, - ); + args.push("-e", `CLAWDIS_BROWSER_CDP_PORT=${params.cfg.browser.cdpPort}`); + args.push("-e", `CLAWDIS_BROWSER_VNC_PORT=${params.cfg.browser.vncPort}`); args.push( "-e", `CLAWDIS_BROWSER_NOVNC_PORT=${params.cfg.browser.noVncPort}`, @@ -603,14 +591,13 @@ async function ensureSandboxBrowser(params: { params.cfg.browser.cdpPort, ); if (!mappedCdp) { - throw new Error( - `Failed to resolve CDP port mapping for ${containerName}.`, - ); + throw new Error(`Failed to resolve CDP port mapping for ${containerName}.`); } - const mappedNoVnc = params.cfg.browser.enableNoVnc && !params.cfg.browser.headless - ? await readDockerPort(containerName, params.cfg.browser.noVncPort) - : null; + const mappedNoVnc = + params.cfg.browser.enableNoVnc && !params.cfg.browser.headless + ? await readDockerPort(containerName, params.cfg.browser.noVncPort) + : null; const existing = BROWSER_BRIDGES.get(params.sessionKey); const shouldReuse = @@ -618,18 +605,23 @@ async function ensureSandboxBrowser(params: { existing.containerName === containerName && existing.bridge.state.resolved.cdpPort === mappedCdp; if (existing && !shouldReuse) { - await stopBrowserBridgeServer(existing.bridge.server).catch(() => undefined); + await stopBrowserBridgeServer(existing.bridge.server).catch( + () => undefined, + ); BROWSER_BRIDGES.delete(params.sessionKey); } - const bridge = shouldReuse - ? existing!.bridge - : await startBrowserBridgeServer({ - resolved: buildSandboxBrowserResolvedConfig({ - controlPort: 0, - cdpPort: mappedCdp, - headless: params.cfg.browser.headless, - }), - }); + let bridge: BrowserBridge; + if (shouldReuse && existing) { + bridge = existing.bridge; + } else { + bridge = await startBrowserBridgeServer({ + resolved: buildSandboxBrowserResolvedConfig({ + controlPort: 0, + cdpPort: mappedCdp, + headless: params.cfg.browser.headless, + }), + }); + } if (!shouldReuse) { BROWSER_BRIDGES.set(params.sessionKey, { bridge, containerName }); } @@ -646,7 +638,9 @@ async function ensureSandboxBrowser(params: { }); const noVncUrl = - mappedNoVnc && params.cfg.browser.enableNoVnc && !params.cfg.browser.headless + mappedNoVnc && + params.cfg.browser.enableNoVnc && + !params.cfg.browser.headless ? `http://127.0.0.1:${mappedNoVnc}/vnc.html?autoconnect=1&resize=remote` : undefined; diff --git a/src/browser/bridge-server.ts b/src/browser/bridge-server.ts index 8391d2c16..c20db834b 100644 --- a/src/browser/bridge-server.ts +++ b/src/browser/bridge-server.ts @@ -1,5 +1,5 @@ -import type { AddressInfo } from "node:net"; import type { Server } from "node:http"; +import type { AddressInfo } from "node:net"; import express from "express"; import type { ResolvedBrowserConfig } from "./config.js";