@opengeni/runtime 4.0.1 → 4.0.3-canary.36199476632001
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/dist/{agent-RJQLKFIW.js → agent-ME6HT4DH.js} +2 -2
- package/dist/assets/codemode-client.json +1 -1
- package/dist/browser-action-json-schema.d.ts +4 -0
- package/dist/{chunk-J5AR5XAJ.js → chunk-FAFZCSN7.js} +695 -210
- package/dist/chunk-FAFZCSN7.js.map +1 -0
- package/dist/{chunk-ZG2YH25H.js → chunk-JAYHA6BF.js} +2 -2
- package/dist/{chunk-UNICCRW5.js → chunk-LZIXCZUV.js} +6 -3
- package/dist/{chunk-UNICCRW5.js.map → chunk-LZIXCZUV.js.map} +1 -1
- package/dist/{chunk-J6J3VYFW.js → chunk-P4V7JGQ2.js} +1037 -105
- package/dist/chunk-P4V7JGQ2.js.map +1 -0
- package/dist/{chunk-SPT3PLMX.js → chunk-PRHMSM6C.js} +2 -2
- package/dist/codex-tool-search.d.ts +12 -0
- package/dist/context-compaction.d.ts +4 -2
- package/dist/index.d.ts +27 -8
- package/dist/index.js +23 -7
- package/dist/interaction-tools.d.ts +1 -1
- package/dist/{lazy-manifest-OEYEHNVY.js → lazy-manifest-GCGUFIWP.js} +3 -3
- package/dist/{localSources-TWHTEKGO.js → localSources-FDH65AFI.js} +4 -4
- package/dist/metrics.d.ts +17 -0
- package/dist/model-provider-routing.d.ts +14 -0
- package/dist/operational-instructions.d.ts +1 -1
- package/dist/provider-quota.d.ts +76 -0
- package/dist/sandbox/browser-control-client.d.ts +28 -1
- package/dist/sandbox/channel-a.d.ts +43 -0
- package/dist/sandbox/index.d.ts +3 -3
- package/dist/sandbox/index.js +10 -6
- package/dist/sandbox/providers/modal-command-router-wire.d.ts +8 -0
- package/dist/sandbox/providers/modal.d.ts +5 -6
- package/dist/workspace-tool-gateway.js +5 -5
- package/package.json +11 -11
- package/src/browser-action-json-schema.ts +10 -0
- package/src/bundled_artifact_skills/opengeni-documents/SKILL.md +4 -1
- package/src/bundled_artifact_skills/opengeni-documents/references/api.md +20 -0
- package/src/bundled_default_skills/opengeni-client/SKILL.md +4 -1
- package/src/bundled_default_skills/opengeni-client/references/discovery-and-autonomy.md +31 -0
- package/src/bundled_default_skills/opengeni-client/references/runtime-profile-and-verification.md +32 -0
- package/src/codex-tool-search.ts +54 -6
- package/src/context-compaction.ts +19 -3
- package/src/index.ts +285 -56
- package/src/interaction-tools.ts +656 -48
- package/src/lazy-tool-transport.ts +4 -0
- package/src/metrics.ts +26 -0
- package/src/model-context-inspector.ts +1 -0
- package/src/model-provider-client.ts +37 -16
- package/src/model-provider-routing.ts +32 -6
- package/src/operational-instructions.ts +1 -1
- package/src/provider-quota.ts +412 -0
- package/src/sandbox/browser-control-client.ts +241 -26
- package/src/sandbox/channel-a.ts +370 -0
- package/src/sandbox/index.ts +6 -1
- package/src/sandbox/providers/modal-command-control.ts +7 -1
- package/src/sandbox/providers/modal-command-router-wire.ts +47 -6
- package/src/sandbox/providers/modal.ts +16 -24
- package/src/sandbox/routing/routing-session.ts +29 -6
- package/dist/chunk-J5AR5XAJ.js.map +0 -1
- package/dist/chunk-J6J3VYFW.js.map +0 -1
- /package/dist/{agent-RJQLKFIW.js.map → agent-ME6HT4DH.js.map} +0 -0
- /package/dist/{chunk-ZG2YH25H.js.map → chunk-JAYHA6BF.js.map} +0 -0
- /package/dist/{chunk-SPT3PLMX.js.map → chunk-PRHMSM6C.js.map} +0 -0
- /package/dist/{lazy-manifest-OEYEHNVY.js.map → lazy-manifest-GCGUFIWP.js.map} +0 -0
- /package/dist/{localSources-TWHTEKGO.js.map → localSources-FDH65AFI.js.map} +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createHash, randomUUID } from "node:crypto";
|
|
2
2
|
import { posix as posixPath } from "node:path";
|
|
3
|
+
import { parseBrowserFrameMetadata, type BrowserFrameMetadata } from "@opengeni/sdk";
|
|
3
4
|
import {
|
|
4
5
|
BROWSER_CONTROL_MAX_JSON_BYTES,
|
|
5
6
|
BROWSER_CONTROL_PORT,
|
|
@@ -14,6 +15,8 @@ import {
|
|
|
14
15
|
BrowserDownloadExportReceipt,
|
|
15
16
|
BrowserDownloadExportRequest,
|
|
16
17
|
BrowserDownloadListResponse,
|
|
18
|
+
BrowserDomReadRequest,
|
|
19
|
+
BrowserDomReadResponse,
|
|
17
20
|
BrowserExternalAuthCommand,
|
|
18
21
|
BrowserExternalAuthResult,
|
|
19
22
|
BrowserObservation,
|
|
@@ -21,6 +24,7 @@ import {
|
|
|
21
24
|
BrowserProtectedAuthFillReceipt,
|
|
22
25
|
BrowserRevisionMaterialization,
|
|
23
26
|
BrowserTarget,
|
|
27
|
+
BrowserTargetState,
|
|
24
28
|
BrowserWorkspaceFileStageRequest,
|
|
25
29
|
BrowserWorkspaceFileStageResponse,
|
|
26
30
|
ComputerActionCommand,
|
|
@@ -40,6 +44,8 @@ import {
|
|
|
40
44
|
type BrowserDownloadExportReceipt as BrowserDownloadExportReceiptValue,
|
|
41
45
|
type BrowserDownloadExportRequest as BrowserDownloadExportRequestValue,
|
|
42
46
|
type BrowserDownloadListResponse as BrowserDownloadListResponseValue,
|
|
47
|
+
type BrowserDomReadRequest as BrowserDomReadRequestValue,
|
|
48
|
+
type BrowserDomReadResponse as BrowserDomReadResponseValue,
|
|
43
49
|
type BrowserExternalAuthCommand as BrowserExternalAuthCommandValue,
|
|
44
50
|
type BrowserExternalAuthResult as BrowserExternalAuthResultValue,
|
|
45
51
|
type BrowserDiagnosticKind,
|
|
@@ -48,6 +54,7 @@ import {
|
|
|
48
54
|
type BrowserProtectedAuthFillReceipt as BrowserProtectedAuthFillReceiptValue,
|
|
49
55
|
type BrowserRevisionMaterialization as BrowserRevisionMaterializationValue,
|
|
50
56
|
type BrowserTarget as BrowserTargetValue,
|
|
57
|
+
type BrowserTargetState as BrowserTargetStateValue,
|
|
51
58
|
type BrowserWorkspaceFileStageRequest as BrowserWorkspaceFileStageRequestValue,
|
|
52
59
|
type BrowserWorkspaceFileStageResponse as BrowserWorkspaceFileStageResponseValue,
|
|
53
60
|
type ComputerActionCommand as ComputerActionCommandValue,
|
|
@@ -165,6 +172,35 @@ export type ComputerControlFrame = {
|
|
|
165
172
|
metadata: ComputerControlFrameMetadata;
|
|
166
173
|
};
|
|
167
174
|
|
|
175
|
+
export type BrowserControlFrame = {
|
|
176
|
+
data: Uint8Array;
|
|
177
|
+
mediaType: "image/jpeg" | "image/png";
|
|
178
|
+
metadataHeader: string;
|
|
179
|
+
metadata: BrowserFrameMetadata;
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
export type BrowserControlScreenshotOptions = {
|
|
183
|
+
fullPage?: boolean;
|
|
184
|
+
format?: "jpeg" | "png";
|
|
185
|
+
quality?: number;
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
type ExpectedBrowserFrameEvidence = {
|
|
189
|
+
browserSessionId: string;
|
|
190
|
+
controllerGeneration: string;
|
|
191
|
+
targetId: string;
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
type FrameRequest = {
|
|
195
|
+
method: "GET";
|
|
196
|
+
path: string;
|
|
197
|
+
token: string;
|
|
198
|
+
timeoutMs?: number;
|
|
199
|
+
} & (
|
|
200
|
+
| { surface: "browser"; expectedFrameEvidence: ExpectedBrowserFrameEvidence }
|
|
201
|
+
| { surface: "computer"; expectedFrameEvidence: ExpectedComputerFrameEvidence }
|
|
202
|
+
);
|
|
203
|
+
|
|
168
204
|
export type ComputerControlFrameMetadata = {
|
|
169
205
|
frameId: string;
|
|
170
206
|
computerSessionId: string;
|
|
@@ -947,7 +983,17 @@ export class BrowserControlClient {
|
|
|
947
983
|
expectedFrameEvidence: ExpectedComputerFrameEvidence;
|
|
948
984
|
timeoutMs?: number;
|
|
949
985
|
}): Promise<ComputerControlFrame> {
|
|
950
|
-
return await this.requestBytes(input);
|
|
986
|
+
return (await this.requestBytes({ ...input, surface: "computer" })) as ComputerControlFrame;
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
async requestBrowserBytesForSession(input: {
|
|
990
|
+
method: "GET";
|
|
991
|
+
path: string;
|
|
992
|
+
token: string;
|
|
993
|
+
expectedFrameEvidence: ExpectedBrowserFrameEvidence;
|
|
994
|
+
timeoutMs?: number;
|
|
995
|
+
}): Promise<BrowserControlFrame> {
|
|
996
|
+
return (await this.requestBytes({ ...input, surface: "browser" })) as BrowserControlFrame;
|
|
951
997
|
}
|
|
952
998
|
|
|
953
999
|
private async requestJson(
|
|
@@ -1124,15 +1170,9 @@ export class BrowserControlClient {
|
|
|
1124
1170
|
}
|
|
1125
1171
|
|
|
1126
1172
|
private async requestBytes(
|
|
1127
|
-
input:
|
|
1128
|
-
method: "GET";
|
|
1129
|
-
path: string;
|
|
1130
|
-
token: string;
|
|
1131
|
-
expectedFrameEvidence: ExpectedComputerFrameEvidence;
|
|
1132
|
-
timeoutMs?: number;
|
|
1133
|
-
},
|
|
1173
|
+
input: FrameRequest,
|
|
1134
1174
|
retryNativeEndpoint = true,
|
|
1135
|
-
): Promise<ComputerControlFrame> {
|
|
1175
|
+
): Promise<ComputerControlFrame | BrowserControlFrame> {
|
|
1136
1176
|
const requireHostFetch = this.session.requireHostFetchController === true;
|
|
1137
1177
|
if (this.session.resolveExposedPort && !this.session.ensureBrowserControl) {
|
|
1138
1178
|
try {
|
|
@@ -1247,10 +1287,10 @@ export class BrowserControlClient {
|
|
|
1247
1287
|
const data = await readBytes(
|
|
1248
1288
|
this.session,
|
|
1249
1289
|
responsePath,
|
|
1250
|
-
COMPUTER_SCREENSHOT_MAX_BYTES,
|
|
1290
|
+
input.surface === "browser" ? 24 * 1024 * 1024 : COMPUTER_SCREENSHOT_MAX_BYTES,
|
|
1251
1291
|
timeoutMs,
|
|
1252
1292
|
);
|
|
1253
|
-
return
|
|
1293
|
+
return controllerImageFrame(data, headers, input);
|
|
1254
1294
|
} catch (error) {
|
|
1255
1295
|
if (
|
|
1256
1296
|
error instanceof BrowserControlRequestError ||
|
|
@@ -1432,6 +1472,104 @@ export class BrowserControlSessionClient {
|
|
|
1432
1472
|
);
|
|
1433
1473
|
}
|
|
1434
1474
|
|
|
1475
|
+
async targetState(targetId: string): Promise<BrowserTargetStateValue> {
|
|
1476
|
+
let state: BrowserTargetStateValue;
|
|
1477
|
+
try {
|
|
1478
|
+
state = BrowserTargetState.parse(
|
|
1479
|
+
await this.parent.requestForSession({
|
|
1480
|
+
method: "GET",
|
|
1481
|
+
path: this.targetPath(targetId, "state"),
|
|
1482
|
+
token: this.viewToken,
|
|
1483
|
+
}),
|
|
1484
|
+
);
|
|
1485
|
+
} catch (error) {
|
|
1486
|
+
// Active Connected Machines can run an older browserd during an API rollout.
|
|
1487
|
+
// Only its exact unknown-route response permits the existing observation path.
|
|
1488
|
+
// A missing session or target must keep its original error.
|
|
1489
|
+
if (
|
|
1490
|
+
!(error instanceof BrowserControlRequestError) ||
|
|
1491
|
+
error.status !== 404 ||
|
|
1492
|
+
error.error.code !== "resource_not_found" ||
|
|
1493
|
+
error.error.message !== "route not found"
|
|
1494
|
+
) {
|
|
1495
|
+
throw error;
|
|
1496
|
+
}
|
|
1497
|
+
const observation = await this.observe(targetId);
|
|
1498
|
+
state = BrowserTargetState.parse({
|
|
1499
|
+
browserSessionId: observation.browserSessionId,
|
|
1500
|
+
controllerGeneration: observation.target.controllerGeneration,
|
|
1501
|
+
targetId: observation.target.id,
|
|
1502
|
+
targetGeneration: observation.target.targetGeneration,
|
|
1503
|
+
documentGeneration: observation.target.documentGeneration,
|
|
1504
|
+
frameId: observation.frameId,
|
|
1505
|
+
});
|
|
1506
|
+
}
|
|
1507
|
+
if (
|
|
1508
|
+
state.browserSessionId !== this.reference.browserSessionId ||
|
|
1509
|
+
state.controllerGeneration !== this.reference.controllerGeneration ||
|
|
1510
|
+
state.targetId !== targetId
|
|
1511
|
+
) {
|
|
1512
|
+
throw new BrowserControlProtocolError("browser target state belongs to another binding");
|
|
1513
|
+
}
|
|
1514
|
+
return state;
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1517
|
+
async readDom(
|
|
1518
|
+
targetId: string,
|
|
1519
|
+
requestInput: BrowserDomReadRequestValue,
|
|
1520
|
+
): Promise<BrowserDomReadResponseValue> {
|
|
1521
|
+
const request = BrowserDomReadRequest.parse(requestInput);
|
|
1522
|
+
const result = BrowserDomReadResponse.parse(
|
|
1523
|
+
await this.parent.requestForSession({
|
|
1524
|
+
method: "POST",
|
|
1525
|
+
path: this.targetPath(targetId, "dom-read"),
|
|
1526
|
+
token: this.viewToken,
|
|
1527
|
+
body: request,
|
|
1528
|
+
}),
|
|
1529
|
+
);
|
|
1530
|
+
if (
|
|
1531
|
+
result.browserSessionId !== this.reference.browserSessionId ||
|
|
1532
|
+
result.controllerGeneration !== this.reference.controllerGeneration ||
|
|
1533
|
+
result.targetId !== targetId ||
|
|
1534
|
+
result.targetGeneration !== request.expectedTargetGeneration ||
|
|
1535
|
+
result.documentGeneration !== request.expectedDocumentGeneration ||
|
|
1536
|
+
result.frameId !== request.expectedFrameId ||
|
|
1537
|
+
result.kind !== request.kind
|
|
1538
|
+
) {
|
|
1539
|
+
throw new BrowserControlProtocolError("browser DOM read belongs to another binding");
|
|
1540
|
+
}
|
|
1541
|
+
return result;
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1544
|
+
async capture(
|
|
1545
|
+
targetId: string,
|
|
1546
|
+
options: BrowserControlScreenshotOptions = {},
|
|
1547
|
+
): Promise<BrowserControlFrame> {
|
|
1548
|
+
const query = new URLSearchParams({
|
|
1549
|
+
format: options.format ?? "jpeg",
|
|
1550
|
+
quality: String(boundedInteger(options.quality ?? 55, 1, 100, "browser screenshot quality")),
|
|
1551
|
+
});
|
|
1552
|
+
if (options.format !== undefined && options.format !== "jpeg" && options.format !== "png") {
|
|
1553
|
+
throw new RangeError("browser screenshot format is invalid");
|
|
1554
|
+
}
|
|
1555
|
+
if (options.fullPage !== undefined) {
|
|
1556
|
+
if (typeof options.fullPage !== "boolean") {
|
|
1557
|
+
throw new RangeError("browser screenshot fullPage is invalid");
|
|
1558
|
+
}
|
|
1559
|
+
query.set("fullPage", String(options.fullPage));
|
|
1560
|
+
}
|
|
1561
|
+
return await this.parent.requestBrowserBytesForSession({
|
|
1562
|
+
method: "GET",
|
|
1563
|
+
path: this.targetPath(targetId, `screenshot?${query}`),
|
|
1564
|
+
token: this.viewToken,
|
|
1565
|
+
expectedFrameEvidence: {
|
|
1566
|
+
browserSessionId: this.reference.browserSessionId,
|
|
1567
|
+
controllerGeneration: this.reference.controllerGeneration,
|
|
1568
|
+
targetId: requireOpaqueId(targetId, "browser target id"),
|
|
1569
|
+
},
|
|
1570
|
+
});
|
|
1571
|
+
}
|
|
1572
|
+
|
|
1435
1573
|
async readClipboard(): Promise<BrowserClipboardValue> {
|
|
1436
1574
|
return BrowserClipboard.parse(
|
|
1437
1575
|
await this.parent.requestForSession({
|
|
@@ -1840,15 +1978,9 @@ async function requestExposedController(
|
|
|
1840
1978
|
|
|
1841
1979
|
async function requestExposedControllerBytes(
|
|
1842
1980
|
endpoint: ExposedPortEndpoint,
|
|
1843
|
-
input:
|
|
1844
|
-
method: "GET";
|
|
1845
|
-
path: string;
|
|
1846
|
-
token: string;
|
|
1847
|
-
expectedFrameEvidence: ExpectedComputerFrameEvidence;
|
|
1848
|
-
timeoutMs?: number;
|
|
1849
|
-
},
|
|
1981
|
+
input: FrameRequest,
|
|
1850
1982
|
defaultTimeoutMs: number,
|
|
1851
|
-
): Promise<ComputerControlFrame> {
|
|
1983
|
+
): Promise<ComputerControlFrame | BrowserControlFrame> {
|
|
1852
1984
|
const token = requireToken(input.token, "browser controller token");
|
|
1853
1985
|
const timeoutMs = boundedTimeout(input.timeoutMs ?? defaultTimeoutMs);
|
|
1854
1986
|
const streamUrl = exposedControllerUrl(endpoint, input.path);
|
|
@@ -1872,12 +2004,91 @@ async function requestExposedControllerBytes(
|
|
|
1872
2004
|
throw new BrowserControlProtocolError("browser controller image response is invalid");
|
|
1873
2005
|
}
|
|
1874
2006
|
const declaredLength = Number(response.headers.get("content-length"));
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
2007
|
+
const maxBytes = input.surface === "browser" ? 24 * 1024 * 1024 : COMPUTER_SCREENSHOT_MAX_BYTES;
|
|
2008
|
+
if (Number.isFinite(declaredLength) && declaredLength > maxBytes) {
|
|
2009
|
+
await response.body?.cancel("frame exceeds its byte bound").catch(() => undefined);
|
|
2010
|
+
throw new RangeError("frame exceeds its byte bound");
|
|
2011
|
+
}
|
|
2012
|
+
const data = await readBoundedFrameResponse(response, maxBytes);
|
|
2013
|
+
return controllerImageFrame(data, response.headers, input);
|
|
2014
|
+
}
|
|
2015
|
+
|
|
2016
|
+
async function readBoundedFrameResponse(response: Response, maxBytes: number): Promise<Uint8Array> {
|
|
2017
|
+
if (!response.body) throw new BrowserControlProtocolError("browser controller image is empty");
|
|
2018
|
+
const reader = response.body.getReader();
|
|
2019
|
+
const chunks: Uint8Array[] = [];
|
|
2020
|
+
let size = 0;
|
|
2021
|
+
try {
|
|
2022
|
+
for (;;) {
|
|
2023
|
+
const { done, value } = await reader.read();
|
|
2024
|
+
if (done) break;
|
|
2025
|
+
size += value.byteLength;
|
|
2026
|
+
if (size > maxBytes) {
|
|
2027
|
+
await reader.cancel("frame exceeds its byte bound").catch(() => undefined);
|
|
2028
|
+
throw new RangeError("frame exceeds its byte bound");
|
|
2029
|
+
}
|
|
2030
|
+
chunks.push(value);
|
|
2031
|
+
}
|
|
2032
|
+
} finally {
|
|
2033
|
+
reader.releaseLock();
|
|
1878
2034
|
}
|
|
1879
|
-
const data = new Uint8Array(
|
|
1880
|
-
|
|
2035
|
+
const data = new Uint8Array(size);
|
|
2036
|
+
let offset = 0;
|
|
2037
|
+
for (const chunk of chunks) {
|
|
2038
|
+
data.set(chunk, offset);
|
|
2039
|
+
offset += chunk.byteLength;
|
|
2040
|
+
}
|
|
2041
|
+
return data;
|
|
2042
|
+
}
|
|
2043
|
+
|
|
2044
|
+
function controllerImageFrame(
|
|
2045
|
+
data: Uint8Array,
|
|
2046
|
+
headers: { get(name: string): string | null | undefined },
|
|
2047
|
+
input: FrameRequest,
|
|
2048
|
+
): ComputerControlFrame | BrowserControlFrame {
|
|
2049
|
+
return input.surface === "browser"
|
|
2050
|
+
? browserControlFrame(data, headers, input.expectedFrameEvidence)
|
|
2051
|
+
: computerControlFrame(data, headers, input.expectedFrameEvidence);
|
|
2052
|
+
}
|
|
2053
|
+
|
|
2054
|
+
function browserControlFrame(
|
|
2055
|
+
data: Uint8Array,
|
|
2056
|
+
headers: { get(name: string): string | null | undefined },
|
|
2057
|
+
expected: ExpectedBrowserFrameEvidence,
|
|
2058
|
+
): BrowserControlFrame {
|
|
2059
|
+
if (data.byteLength < 1 || data.byteLength > 24 * 1024 * 1024) {
|
|
2060
|
+
throw new RangeError("browser frame exceeds its byte bound");
|
|
2061
|
+
}
|
|
2062
|
+
const get = (name: string): string | null => headers.get(name.toLowerCase()) ?? null;
|
|
2063
|
+
const mediaType = get("content-type")?.split(";", 1)[0]?.trim().toLowerCase();
|
|
2064
|
+
if (mediaType !== "image/jpeg" && mediaType !== "image/png") {
|
|
2065
|
+
throw new BrowserControlProtocolError("browser frame media type is invalid");
|
|
2066
|
+
}
|
|
2067
|
+
const metadataHeader = get("x-opengeni-browser-frame");
|
|
2068
|
+
if (
|
|
2069
|
+
!metadataHeader ||
|
|
2070
|
+
metadataHeader.length > 64 * 1024 ||
|
|
2071
|
+
!/^[A-Za-z0-9_-]+$/u.test(metadataHeader)
|
|
2072
|
+
) {
|
|
2073
|
+
throw new BrowserControlProtocolError("browser frame metadata is invalid");
|
|
2074
|
+
}
|
|
2075
|
+
let metadata: BrowserFrameMetadata;
|
|
2076
|
+
try {
|
|
2077
|
+
metadata = parseBrowserFrameMetadata(
|
|
2078
|
+
JSON.parse(Buffer.from(metadataHeader, "base64url").toString("utf8")),
|
|
2079
|
+
);
|
|
2080
|
+
} catch {
|
|
2081
|
+
throw new BrowserControlProtocolError("browser frame metadata is invalid");
|
|
2082
|
+
}
|
|
2083
|
+
if (
|
|
2084
|
+
metadata.browserSessionId !== expected.browserSessionId ||
|
|
2085
|
+
metadata.controllerGeneration !== expected.controllerGeneration ||
|
|
2086
|
+
metadata.targetId !== expected.targetId ||
|
|
2087
|
+
metadata.mediaType !== mediaType
|
|
2088
|
+
) {
|
|
2089
|
+
throw new BrowserControlProtocolError("browser frame evidence does not match its request");
|
|
2090
|
+
}
|
|
2091
|
+
return { data, mediaType, metadataHeader, metadata };
|
|
1881
2092
|
}
|
|
1882
2093
|
|
|
1883
2094
|
function computerControlFrame(
|
|
@@ -2764,7 +2975,11 @@ async function readBytes(
|
|
|
2764
2975
|
timeoutMs: number,
|
|
2765
2976
|
): Promise<Uint8Array> {
|
|
2766
2977
|
const privatePath = absolutePrivatePath(path, "browser private binary response path");
|
|
2767
|
-
if (
|
|
2978
|
+
if (
|
|
2979
|
+
!Number.isSafeInteger(maxBytes) ||
|
|
2980
|
+
maxBytes < 1 ||
|
|
2981
|
+
maxBytes > Math.max(24 * 1024 * 1024, COMPUTER_SCREENSHOT_MAX_BYTES)
|
|
2982
|
+
) {
|
|
2768
2983
|
throw new RangeError("browser private binary response limit is invalid");
|
|
2769
2984
|
}
|
|
2770
2985
|
const sizeMarker = `OPENGENI_BROWSER_PRIVATE_SIZE_${randomUUID()}`;
|
|
@@ -2783,7 +2998,7 @@ async function readBytes(
|
|
|
2783
2998
|
"browser private binary response size",
|
|
2784
2999
|
);
|
|
2785
3000
|
if (size < 1 || size > maxBytes) {
|
|
2786
|
-
throw new RangeError("
|
|
3001
|
+
throw new RangeError("frame exceeds its byte bound");
|
|
2787
3002
|
}
|
|
2788
3003
|
const chunks: Buffer[] = [];
|
|
2789
3004
|
for (let offset = 0; offset < size; offset += PRIVATE_READ_CHUNK_BYTES) {
|