@omercnet/paseo-shared-browser 4.1.6-next.428.1 → 4.1.6-next.432.1
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.
- package/README.md +9 -2
- package/npm-shrinkwrap.json +4 -4
- package/package.json +5 -4
- package/scripts/chromium-release.mjs +29 -0
- package/scripts/prepare-runtime.mjs +37 -48
- package/scripts/replace-runtime.mjs +17 -0
- package/server/agent-browser-runtime.ts +1 -1
- package/server/runtime-launch-environment.test.ts +1 -1
- package/server/runtime-video-opt-in.test.ts +1 -1
package/README.md
CHANGED
|
@@ -40,7 +40,7 @@ organization names.
|
|
|
40
40
|
controller when a takeover is needed, and continues the selected action after control is granted.
|
|
41
41
|
Closing a tab or browser still requires its own confirmation. Actions that need a fresh frame wait
|
|
42
42
|
for one before sending input.
|
|
43
|
-
- The plugin owns `agent-browser` version `0.41.
|
|
43
|
+
- The plugin owns `agent-browser` version `0.41.2`, its IPC directory, and the Chromium executable.
|
|
44
44
|
It strips inherited `AGENT_BROWSER_*` variables and sets `AGENT_BROWSER_SOCKET_DIR`,
|
|
45
45
|
`AGENT_BROWSER_IDLE_TIMEOUT_MS=0`, `AGENT_BROWSER_STREAM_PORT=0`, and
|
|
46
46
|
`AGENT_BROWSER_NO_AUTO_DIALOG=1` itself.
|
|
@@ -105,7 +105,14 @@ from `/usr/bin/chromium`. Install a non-Snap Chromium build with the system pack
|
|
|
105
105
|
adding the plugin. Set `PASEO_SHARED_BROWSER_CHROMIUM_EXECUTABLE` to an absolute path when Chromium
|
|
106
106
|
is installed elsewhere. The plugin does not emulate x64 Chromium on Linux.
|
|
107
107
|
|
|
108
|
-
|
|
108
|
+
Runtime preparation keeps no Chrome download cache. When it uses the upstream installer (every
|
|
109
|
+
platform except Linux ARM64, unless `PASEO_SHARED_BROWSER_CHROMIUM_EXECUTABLE` is set), the
|
|
110
|
+
installer runs with a private home inside the staging directory, so each preparation downloads the
|
|
111
|
+
current Chrome for Testing archive (about 200 MiB) and deletes the installer's copy after staging
|
|
112
|
+
it. On a slow network that download can exceed the 180-second install timeout; set
|
|
113
|
+
`PASEO_SHARED_BROWSER_CHROMIUM_EXECUTABLE` to an existing Chromium to skip it. On Windows the
|
|
114
|
+
override is not staged into the runtime, so keep it set in the daemon environment as well.
|
|
115
|
+
|
|
109
116
|
Before upgrading the plugin on Windows, close active Shared Browser sessions and stop the Paseo
|
|
110
117
|
daemon; Windows does not allow the installer to replace runtime executables that are still running.
|
|
111
118
|
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@getpaseo/plugin": "0.15.0",
|
|
12
12
|
"@modelcontextprotocol/sdk": "1.32.2",
|
|
13
|
-
"agent-browser": "0.41.
|
|
13
|
+
"agent-browser": "0.41.2",
|
|
14
14
|
"esbuild": "0.28.2",
|
|
15
15
|
"zod": "4.6.7"
|
|
16
16
|
}
|
|
@@ -606,9 +606,9 @@
|
|
|
606
606
|
}
|
|
607
607
|
},
|
|
608
608
|
"node_modules/agent-browser": {
|
|
609
|
-
"version": "0.41.
|
|
610
|
-
"resolved": "https://registry.npmjs.org/agent-browser/-/agent-browser-0.41.
|
|
611
|
-
"integrity": "sha512
|
|
609
|
+
"version": "0.41.2",
|
|
610
|
+
"resolved": "https://registry.npmjs.org/agent-browser/-/agent-browser-0.41.2.tgz",
|
|
611
|
+
"integrity": "sha512-/agCKB5rw1EEK8SKWo4zid7a5kOwlclqALC0P3c69buJvKdhrl/dJkKdfLqGGaiNIbWzRdqqT0PxZVkwVEf2fg==",
|
|
612
612
|
"hasInstallScript": true,
|
|
613
613
|
"license": "Apache-2.0",
|
|
614
614
|
"bin": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@omercnet/paseo-shared-browser",
|
|
3
|
-
"version": "4.1.6-next.
|
|
3
|
+
"version": "4.1.6-next.432.1",
|
|
4
4
|
"description": "One real Chromium session per Paseo workspace, shared live across every connected client.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"browser",
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
"index.client.tsx",
|
|
30
30
|
"index.server.ts",
|
|
31
31
|
"client",
|
|
32
|
+
"scripts/chromium-release.mjs",
|
|
32
33
|
"scripts/prepare-dependencies.mjs",
|
|
33
34
|
"scripts/prepare-runtime.mjs",
|
|
34
35
|
"scripts/replace-runtime.mjs",
|
|
@@ -48,8 +49,8 @@
|
|
|
48
49
|
"check:write": "biome check --write .",
|
|
49
50
|
"typecheck": "tsc --noEmit",
|
|
50
51
|
"prepare:runtime": "node scripts/prepare-runtime.mjs",
|
|
51
|
-
"test": "vitest run tests/contracts.test.ts tests/lease.test.ts tests/runtime-lifecycle.test.ts tests/agent-access.test.ts tests/agent-input-safety.test.ts tests/tabs.test.ts tests/tabs-runtime-loss.test.ts tests/composer-pills.test.ts tests/sidebar.test.ts tests/pointer-mapping.test.ts tests/frame-lifecycle.test.ts tests/viewport-resync.test.ts client server shared",
|
|
52
|
-
"test:unit": "vitest run tests/contracts.test.ts tests/lease.test.ts tests/runtime-lifecycle.test.ts tests/agent-access.test.ts tests/agent-input-safety.test.ts tests/tabs.test.ts tests/tabs-runtime-loss.test.ts tests/composer-pills.test.ts tests/sidebar.test.ts tests/pointer-mapping.test.ts tests/frame-lifecycle.test.ts tests/viewport-resync.test.ts client server shared",
|
|
52
|
+
"test": "vitest run tests/contracts.test.ts tests/lease.test.ts tests/runtime-lifecycle.test.ts tests/chromium-release.test.ts tests/prepare-runtime.test.ts tests/agent-access.test.ts tests/agent-input-safety.test.ts tests/tabs.test.ts tests/tabs-runtime-loss.test.ts tests/composer-pills.test.ts tests/sidebar.test.ts tests/pointer-mapping.test.ts tests/frame-lifecycle.test.ts tests/viewport-resync.test.ts client server shared",
|
|
53
|
+
"test:unit": "vitest run tests/contracts.test.ts tests/lease.test.ts tests/runtime-lifecycle.test.ts tests/chromium-release.test.ts tests/prepare-runtime.test.ts tests/agent-access.test.ts tests/agent-input-safety.test.ts tests/tabs.test.ts tests/tabs-runtime-loss.test.ts tests/composer-pills.test.ts tests/sidebar.test.ts tests/pointer-mapping.test.ts tests/frame-lifecycle.test.ts tests/viewport-resync.test.ts client server shared",
|
|
53
54
|
"test:smoke": "vitest run tests/browser.smoke.test.ts tests/browser.drag-cancel.smoke.test.ts tests/xvfb.smoke.test.ts tests/browser.failed-open.smoke.test.ts tests/browser.background-tab.smoke.test.ts --testTimeout=30000",
|
|
54
55
|
"test:tabs": "vitest run tests/browser-tabs.smoke.test.ts --testTimeout=30000",
|
|
55
56
|
"test:video": "vitest run tests/video.smoke.test.ts --testTimeout=30000"
|
|
@@ -57,7 +58,7 @@
|
|
|
57
58
|
"dependencies": {
|
|
58
59
|
"@getpaseo/plugin": "0.15.0",
|
|
59
60
|
"@modelcontextprotocol/sdk": "1.32.2",
|
|
60
|
-
"agent-browser": "0.41.
|
|
61
|
+
"agent-browser": "0.41.2",
|
|
61
62
|
"esbuild": "0.28.2",
|
|
62
63
|
"zod": "4.6.7"
|
|
63
64
|
},
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { mkdir, readdir } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { promisify } from "node:util";
|
|
5
|
+
|
|
6
|
+
const execFileAsync = promisify(execFile);
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Runs `agent-browser install` against a private home and returns the
|
|
10
|
+
* Chromium release directory it produced. agent-browser resolves its browser
|
|
11
|
+
* cache with Rust's std::env::home_dir(): HOME on Unix and USERPROFILE on
|
|
12
|
+
* Windows, so both point at installHome.
|
|
13
|
+
*/
|
|
14
|
+
export async function installChromiumRelease(agentBrowser, args, installHome) {
|
|
15
|
+
await mkdir(installHome, { recursive: true, mode: 0o700 });
|
|
16
|
+
await execFileAsync(agentBrowser, args, {
|
|
17
|
+
env: { ...process.env, HOME: installHome, USERPROFILE: installHome },
|
|
18
|
+
timeout: 180_000,
|
|
19
|
+
windowsHide: true,
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const browsersRoot = join(installHome, ".agent-browser", "browsers");
|
|
23
|
+
const releases = (await readdir(browsersRoot, { withFileTypes: true }))
|
|
24
|
+
.filter((entry) => entry.isDirectory() && entry.name.startsWith("chrome-"))
|
|
25
|
+
.map((entry) => entry.name)
|
|
26
|
+
.sort((left, right) => right.localeCompare(left, undefined, { numeric: true }));
|
|
27
|
+
if (!releases[0]) throw new Error("agent-browser install did not produce a Chromium release");
|
|
28
|
+
return join(browsersRoot, releases[0]);
|
|
29
|
+
}
|
|
@@ -3,12 +3,13 @@ import { randomUUID } from "node:crypto";
|
|
|
3
3
|
import { constants } from "node:fs";
|
|
4
4
|
import { access, chmod, cp, lstat, mkdir, readdir, rm, symlink, writeFile } from "node:fs/promises";
|
|
5
5
|
import { createRequire } from "node:module";
|
|
6
|
-
import { arch, homedir, platform
|
|
6
|
+
import { arch, homedir, platform } from "node:os";
|
|
7
7
|
import { dirname, join, resolve } from "node:path";
|
|
8
8
|
import { fileURLToPath } from "node:url";
|
|
9
9
|
import { promisify } from "node:util";
|
|
10
10
|
import { build } from "esbuild";
|
|
11
|
-
import {
|
|
11
|
+
import { installChromiumRelease } from "./chromium-release.mjs";
|
|
12
|
+
import { discardRuntime, replaceRuntime } from "./replace-runtime.mjs";
|
|
12
13
|
|
|
13
14
|
const require = createRequire(import.meta.url);
|
|
14
15
|
|
|
@@ -18,7 +19,7 @@ function resolveDependencyRoot(packageName) {
|
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
const execFileAsync = promisify(execFile);
|
|
21
|
-
const expectedVersion = "0.41.
|
|
22
|
+
const expectedVersion = "0.41.2";
|
|
22
23
|
const hostPlatform = platform();
|
|
23
24
|
const hostArch = arch();
|
|
24
25
|
const projectRoot = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
@@ -163,26 +164,8 @@ async function installChromium() {
|
|
|
163
164
|
return executable;
|
|
164
165
|
}
|
|
165
166
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
const installHome =
|
|
169
|
-
hostPlatform === "win32" ? userInfo().homedir : join(stagingRoot, "install-home");
|
|
170
|
-
if (hostPlatform !== "win32") {
|
|
171
|
-
await mkdir(installHome, { recursive: true, mode: 0o700 });
|
|
172
|
-
}
|
|
173
|
-
await execFileAsync(runtimeEntry, ["install"], {
|
|
174
|
-
env: hostPlatform === "win32" ? process.env : { ...process.env, HOME: installHome },
|
|
175
|
-
timeout: 180_000,
|
|
176
|
-
windowsHide: true,
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
const browsersRoot = join(installHome, ".agent-browser", "browsers");
|
|
180
|
-
const releases = (await readdir(browsersRoot, { withFileTypes: true }))
|
|
181
|
-
.filter((entry) => entry.isDirectory() && entry.name.startsWith("chrome-"))
|
|
182
|
-
.map((entry) => entry.name)
|
|
183
|
-
.sort((left, right) => right.localeCompare(left, undefined, { numeric: true }));
|
|
184
|
-
const releaseDir = releases[0] && join(browsersRoot, releases[0]);
|
|
185
|
-
if (!releaseDir) throw new Error("agent-browser install did not produce a Chromium release");
|
|
167
|
+
const installHome = join(stagingRoot, "install-home");
|
|
168
|
+
const releaseDir = await installChromiumRelease(runtimeEntry, ["install"], installHome);
|
|
186
169
|
const chrome = installedChromiumExecutable(releaseDir);
|
|
187
170
|
await requireExecutable(chrome, "Installed Chromium executable");
|
|
188
171
|
await cp(releaseDir, join(stagingRoot, "chromium"), {
|
|
@@ -200,7 +183,7 @@ async function installChromium() {
|
|
|
200
183
|
);
|
|
201
184
|
await chmod(runtimeChromiumEntry, 0o700);
|
|
202
185
|
}
|
|
203
|
-
|
|
186
|
+
await rm(installHome, { recursive: true, force: true });
|
|
204
187
|
return runtimeChromiumEntry;
|
|
205
188
|
}
|
|
206
189
|
|
|
@@ -222,32 +205,38 @@ async function stageAgentBrowserEntry() {
|
|
|
222
205
|
}
|
|
223
206
|
|
|
224
207
|
await rm(stagingRoot, { recursive: true, force: true });
|
|
225
|
-
|
|
226
|
-
await
|
|
227
|
-
await
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
await
|
|
208
|
+
try {
|
|
209
|
+
await mkdir(join(runtimeModules, ".bin"), { recursive: true, mode: 0o700 });
|
|
210
|
+
await chmod(pluginDataRoot, 0o700);
|
|
211
|
+
await cp(packagedAgentBrowser, join(runtimeModules, "agent-browser"), {
|
|
212
|
+
recursive: true,
|
|
213
|
+
force: true,
|
|
214
|
+
});
|
|
215
|
+
await stageAgentBrowserEntry();
|
|
216
|
+
|
|
217
|
+
const binaryOverride = process.env.PASEO_SHARED_BROWSER_AGENT_BROWSER_BINARY;
|
|
218
|
+
if (binaryOverride)
|
|
219
|
+
await validateAgentBrowser(
|
|
220
|
+
await requireExecutable(binaryOverride, "PASEO_SHARED_BROWSER_AGENT_BROWSER_BINARY"),
|
|
221
|
+
);
|
|
222
|
+
await validateAgentBrowser(await requireExecutable(runtimeEntry, "Packaged agent-browser entry"));
|
|
223
|
+
const chromiumEntry = await installChromium();
|
|
224
|
+
await bundleRuntimeEntries();
|
|
225
|
+
|
|
226
|
+
await writeFile(
|
|
227
|
+
join(stagingRoot, "package.json"),
|
|
228
|
+
`${JSON.stringify({ private: true, type: "commonjs" }, null, 2)}\n`,
|
|
229
|
+
{ mode: 0o600 },
|
|
237
230
|
);
|
|
238
|
-
await
|
|
239
|
-
|
|
240
|
-
await
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
{ mode: 0o600 },
|
|
246
|
-
);
|
|
247
|
-
await applyPrivatePermissions(stagingRoot);
|
|
248
|
-
if (hostPlatform !== "win32") {
|
|
249
|
-
await validateChromium(await requireExecutable(chromiumEntry, "Staged Chromium executable"));
|
|
231
|
+
await applyPrivatePermissions(stagingRoot);
|
|
232
|
+
if (hostPlatform !== "win32") {
|
|
233
|
+
await validateChromium(await requireExecutable(chromiumEntry, "Staged Chromium executable"));
|
|
234
|
+
}
|
|
235
|
+
} catch (error) {
|
|
236
|
+
// A failed preparation must not leave a partial runtime, which can hold a Chromium download.
|
|
237
|
+
await discardRuntime(stagingRoot, error);
|
|
250
238
|
}
|
|
239
|
+
// Outside the cleanup: replaceRuntime can reject after publishing, when the stage is the live runtime.
|
|
251
240
|
await replaceRuntime(stagingRoot, runtimeRoot);
|
|
252
241
|
|
|
253
242
|
console.log(`Prepared immutable Shared Browser runtime assets in ${stagingRoot}`);
|
|
@@ -13,3 +13,20 @@ export async function replaceRuntime(stagingRoot, runtimeRoot) {
|
|
|
13
13
|
await rm(pendingPointer, { force: true });
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Removes a staging runtime after a failed preparation and rethrows the
|
|
19
|
+
* preparation error. Windows file locks can outlast the retries; a cleanup
|
|
20
|
+
* failure is reported but never replaces the original diagnostic.
|
|
21
|
+
*/
|
|
22
|
+
export async function discardRuntime(stagingRoot, preparationError, remove = rm) {
|
|
23
|
+
try {
|
|
24
|
+
await remove(stagingRoot, { recursive: true, force: true, maxRetries: 5, retryDelay: 200 });
|
|
25
|
+
} catch (cleanupError) {
|
|
26
|
+
console.warn(
|
|
27
|
+
`Could not remove the failed Shared Browser runtime at ${stagingRoot}:`,
|
|
28
|
+
cleanupError,
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
throw preparationError;
|
|
32
|
+
}
|
|
@@ -57,7 +57,7 @@ import { createScreencastSourceTime } from "./screencast-source-time";
|
|
|
57
57
|
import { createVideoSourceRecovery } from "./video-source-recovery";
|
|
58
58
|
|
|
59
59
|
const execFileAsync = promisify(execFile);
|
|
60
|
-
export const AGENT_BROWSER_VERSION = "0.41.
|
|
60
|
+
export const AGENT_BROWSER_VERSION = "0.41.2";
|
|
61
61
|
const PRIVATE_DIRECTORY_MODE = 0o700;
|
|
62
62
|
const PRIVATE_FILE_MODE = 0o600;
|
|
63
63
|
const DEFAULT_TIMEOUT_MS = 15_000;
|
|
@@ -23,7 +23,7 @@ vi.mock("node:child_process", () => ({
|
|
|
23
23
|
callback: (error: null, result: { stdout: string }) => void,
|
|
24
24
|
) => {
|
|
25
25
|
exec.calls.push({ file, args, env: options.env });
|
|
26
|
-
callback(null, { stdout: args.includes("--version") ? "0.41.
|
|
26
|
+
callback(null, { stdout: args.includes("--version") ? "0.41.2\n" : "{}\n" });
|
|
27
27
|
},
|
|
28
28
|
}));
|
|
29
29
|
|
|
@@ -15,7 +15,7 @@ vi.mock("node:child_process", async (importOriginal) => ({
|
|
|
15
15
|
_args: string[],
|
|
16
16
|
_options: unknown,
|
|
17
17
|
callback: (error: null, result: { stdout: string }) => void,
|
|
18
|
-
) => callback(null, { stdout: "0.41.
|
|
18
|
+
) => callback(null, { stdout: "0.41.2\n" }),
|
|
19
19
|
}));
|
|
20
20
|
|
|
21
21
|
const temporary: string[] = [];
|