@omercnet/paseo-shared-browser 4.1.1-next.332.1 → 4.1.1-next.348.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 +1 -1
- package/npm-shrinkwrap.json +10 -10
- package/package.json +2 -2
- package/scripts/prepare-runtime.mjs +1 -1
- package/server/agent-browser-runtime.ts +1 -1
- package/server/native-video-backpressure.test.ts +44 -4
- package/server/native-video-extension-source.ts +6 -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.39.
|
|
43
|
+
- The plugin owns `agent-browser` version `0.39.4`, 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.
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@getpaseo/plugin": "0.14.0",
|
|
12
12
|
"@modelcontextprotocol/sdk": "1.30.0",
|
|
13
|
-
"agent-browser": "0.39.
|
|
13
|
+
"agent-browser": "0.39.4",
|
|
14
14
|
"esbuild": "0.28.2",
|
|
15
15
|
"zod": "4.4.3"
|
|
16
16
|
}
|
|
@@ -606,9 +606,9 @@
|
|
|
606
606
|
}
|
|
607
607
|
},
|
|
608
608
|
"node_modules/agent-browser": {
|
|
609
|
-
"version": "0.39.
|
|
610
|
-
"resolved": "https://registry.npmjs.org/agent-browser/-/agent-browser-0.39.
|
|
611
|
-
"integrity": "sha512-
|
|
609
|
+
"version": "0.39.4",
|
|
610
|
+
"resolved": "https://registry.npmjs.org/agent-browser/-/agent-browser-0.39.4.tgz",
|
|
611
|
+
"integrity": "sha512-R0ue5CWlpkGtbcXeq3ZKM96zLrCXkNKEGyttgWhi0eSNKoNSvxglvv1/D9NhKxe+MI+djiCFepPd4PYOM0H2Rg==",
|
|
612
612
|
"hasInstallScript": true,
|
|
613
613
|
"license": "Apache-2.0",
|
|
614
614
|
"bin": {
|
|
@@ -1029,9 +1029,9 @@
|
|
|
1029
1029
|
}
|
|
1030
1030
|
},
|
|
1031
1031
|
"node_modules/express-rate-limit": {
|
|
1032
|
-
"version": "8.7.
|
|
1033
|
-
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.7.
|
|
1034
|
-
"integrity": "sha512-
|
|
1032
|
+
"version": "8.7.2",
|
|
1033
|
+
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.7.2.tgz",
|
|
1034
|
+
"integrity": "sha512-U1ScocxDD9WI09LaBVypvNkOtNR5yWAmZLkuKJdAzIchA4YKFYF6GT5IKER7epG58oXtjvGlV0/6ii0F83EyZg==",
|
|
1035
1035
|
"license": "MIT",
|
|
1036
1036
|
"dependencies": {
|
|
1037
1037
|
"debug": "^4.4.3",
|
|
@@ -1233,9 +1233,9 @@
|
|
|
1233
1233
|
}
|
|
1234
1234
|
},
|
|
1235
1235
|
"node_modules/i18next": {
|
|
1236
|
-
"version": "26.5.
|
|
1237
|
-
"resolved": "https://registry.npmjs.org/i18next/-/i18next-26.5.
|
|
1238
|
-
"integrity": "sha512-
|
|
1236
|
+
"version": "26.5.12",
|
|
1237
|
+
"resolved": "https://registry.npmjs.org/i18next/-/i18next-26.5.12.tgz",
|
|
1238
|
+
"integrity": "sha512-vTt8tc3y5axoU7wwTYg8vjpILLyP33a5GyGJAVI7FDRx1XueYxZVIkcVeStoftrVnAM/o28hKvK0sslucDI9aQ==",
|
|
1239
1239
|
"funding": [
|
|
1240
1240
|
{
|
|
1241
1241
|
"type": "individual",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@omercnet/paseo-shared-browser",
|
|
3
|
-
"version": "4.1.1-next.
|
|
3
|
+
"version": "4.1.1-next.348.1",
|
|
4
4
|
"description": "One real Chromium session per Paseo workspace, shared live across every connected client.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"browser",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"dependencies": {
|
|
58
58
|
"@getpaseo/plugin": "0.14.0",
|
|
59
59
|
"@modelcontextprotocol/sdk": "1.30.0",
|
|
60
|
-
"agent-browser": "0.39.
|
|
60
|
+
"agent-browser": "0.39.4",
|
|
61
61
|
"esbuild": "0.28.2",
|
|
62
62
|
"zod": "4.4.3"
|
|
63
63
|
},
|
|
@@ -18,7 +18,7 @@ function resolveDependencyRoot(packageName) {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
const execFileAsync = promisify(execFile);
|
|
21
|
-
const expectedVersion = "0.39.
|
|
21
|
+
const expectedVersion = "0.39.4";
|
|
22
22
|
const hostPlatform = platform();
|
|
23
23
|
const hostArch = arch();
|
|
24
24
|
const projectRoot = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
@@ -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.39.
|
|
60
|
+
export const AGENT_BROWSER_VERSION = "0.39.4";
|
|
61
61
|
const PRIVATE_DIRECTORY_MODE = 0o700;
|
|
62
62
|
const PRIVATE_FILE_MODE = 0o600;
|
|
63
63
|
const DEFAULT_TIMEOUT_MS = 15_000;
|
|
@@ -17,7 +17,7 @@ async function fixture(failFirstEncoder = false) {
|
|
|
17
17
|
}),
|
|
18
18
|
cancel: async () => deliver({ done: true }),
|
|
19
19
|
};
|
|
20
|
-
const pending: { timestamp: number; type: string }[] = [];
|
|
20
|
+
const pending: { timestamp: number; type: string; queued: boolean }[] = [];
|
|
21
21
|
const encoded: { timestamp: number; keyFrame: boolean }[] = [];
|
|
22
22
|
let encoder: Encoder;
|
|
23
23
|
const instances: Encoder[] = [];
|
|
@@ -37,14 +37,31 @@ async function fixture(failFirstEncoder = false) {
|
|
|
37
37
|
if (failFirstEncoder && this === instances[0]) throw new Error("Codec stopped");
|
|
38
38
|
this.encodeQueueSize++;
|
|
39
39
|
encoded.push({ timestamp: frame.timestamp, keyFrame: options.keyFrame });
|
|
40
|
-
pending.push({
|
|
40
|
+
pending.push({
|
|
41
|
+
timestamp: frame.timestamp,
|
|
42
|
+
type: options.keyFrame ? "key" : "delta",
|
|
43
|
+
queued: true,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
/** WebCodecs lowers encodeQueueSize once the codec starts a frame, before its output. */
|
|
47
|
+
dequeue() {
|
|
48
|
+
const value = pending.find((entry) => entry.queued);
|
|
49
|
+
if (!value) throw new Error("No queued fixture frame");
|
|
50
|
+
value.queued = false;
|
|
51
|
+
this.encodeQueueSize--;
|
|
41
52
|
}
|
|
53
|
+
/** Emits in submission order, as an in-order realtime codec does. */
|
|
42
54
|
output() {
|
|
43
55
|
const value = pending.shift();
|
|
44
56
|
if (!value) throw new Error("No queued fixture frame");
|
|
45
|
-
this.encodeQueueSize--;
|
|
57
|
+
if (value.queued) this.encodeQueueSize--;
|
|
46
58
|
this.callbacks.output(
|
|
47
|
-
{
|
|
59
|
+
{
|
|
60
|
+
timestamp: value.timestamp,
|
|
61
|
+
type: value.type,
|
|
62
|
+
byteLength: 10,
|
|
63
|
+
copyTo: (bytes: Uint8Array) => bytes.fill(1),
|
|
64
|
+
},
|
|
48
65
|
{},
|
|
49
66
|
);
|
|
50
67
|
}
|
|
@@ -94,6 +111,7 @@ async function fixture(failFirstEncoder = false) {
|
|
|
94
111
|
await turn();
|
|
95
112
|
},
|
|
96
113
|
output: () => encoder!.output(),
|
|
114
|
+
dequeue: () => encoder!.dequeue(),
|
|
97
115
|
ack: () =>
|
|
98
116
|
runInContext(
|
|
99
117
|
'for(const p of fixturePackets) acknowledge("stream",p.sequence)',
|
|
@@ -189,6 +207,28 @@ it("still suppresses dependencies after an actual encoded output is dropped", as
|
|
|
189
207
|
}
|
|
190
208
|
});
|
|
191
209
|
|
|
210
|
+
it("emits outputs from a codec that lags further behind than its dequeued queue size", async () => {
|
|
211
|
+
const f = await fixture();
|
|
212
|
+
try {
|
|
213
|
+
const timestamps = [0, 33334, 66668, 100002, 133336, 166670];
|
|
214
|
+
for (const timestamp of timestamps) {
|
|
215
|
+
await f.frame(timestamp);
|
|
216
|
+
f.dequeue();
|
|
217
|
+
}
|
|
218
|
+
expect(f.encoded).toHaveLength(timestamps.length);
|
|
219
|
+
for (const _ of timestamps) {
|
|
220
|
+
f.output();
|
|
221
|
+
f.ack();
|
|
222
|
+
}
|
|
223
|
+
expect(f.packets.map((p) => [p.timestampUs, p.type])).toEqual(
|
|
224
|
+
timestamps.map((timestamp, index) => [timestamp, index ? "delta" : "key"]),
|
|
225
|
+
);
|
|
226
|
+
expect(f.encoded.filter((e) => e.keyFrame)).toHaveLength(1);
|
|
227
|
+
} finally {
|
|
228
|
+
await f.stop();
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
|
|
192
232
|
it("shipped packet conversion is exact with native and legacy byte APIs", () => {
|
|
193
233
|
for (const native of [true, false]) {
|
|
194
234
|
const context = createContext({
|
|
@@ -132,7 +132,12 @@ async function startCapture(targetId, width, height, generation) {
|
|
|
132
132
|
continue;
|
|
133
133
|
state.lastEncodedTimestampUs = frame.timestamp;
|
|
134
134
|
state.frameGenerations.set(frame.timestamp, current.generation);
|
|
135
|
-
|
|
135
|
+
// encodeQueueSize drops when the codec dequeues a frame, not when it
|
|
136
|
+
// outputs, so a slow encode keeps more frames in flight than the gate
|
|
137
|
+
// above admits. Bound by one second at the 60fps ceiling, the host's
|
|
138
|
+
// packet age limit, so an in-flight output keeps its generation
|
|
139
|
+
// for as long as the host would still accept it.
|
|
140
|
+
while (state.frameGenerations.size > 60)
|
|
136
141
|
state.frameGenerations.delete(state.frameGenerations.keys().next().value);
|
|
137
142
|
const keyFrame =
|
|
138
143
|
state.forceKey || frame.timestamp - state.lastKeyTimestamp >= 1000000;
|
|
@@ -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.39.
|
|
26
|
+
callback(null, { stdout: args.includes("--version") ? "0.39.4\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.39.
|
|
18
|
+
) => callback(null, { stdout: "0.39.4\n" }),
|
|
19
19
|
}));
|
|
20
20
|
|
|
21
21
|
const temporary: string[] = [];
|