@ricsam/r5d-browser 0.0.137 → 0.0.139
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 +7 -33
- package/dist/cjs/package.json +1 -1
- package/dist/mjs/browser-input.mjs +56 -1
- package/dist/mjs/cli-options.mjs +1 -0
- package/dist/mjs/main.mjs +25 -396
- package/dist/mjs/package.json +1 -1
- package/dist/mjs/personal-diagnostics.mjs +24 -0
- package/dist/mjs/personal-main.mjs +159 -0
- package/dist/mjs/personal-port-forward.mjs +183 -0
- package/dist/mjs/personal-relay-client.mjs +33 -0
- package/dist/mjs/personal-relay-shutdown.mjs +46 -0
- package/dist/mjs/runtime/browser-executor.mjs +11 -0
- package/dist/mjs/runtime/chromium-factory.mjs +101 -0
- package/dist/mjs/runtime/ipc.mjs +128 -0
- package/dist/mjs/runtime/isolated-root.mjs +53 -0
- package/dist/mjs/runtime/keeper.mjs +169 -0
- package/dist/mjs/runtime/ledger.mjs +193 -0
- package/dist/mjs/runtime/main.mjs +105 -0
- package/dist/mjs/runtime/private-paths.mjs +48 -0
- package/dist/mjs/runtime/protocol.mjs +72 -0
- package/dist/types/browser-input.d.ts +4 -0
- package/dist/types/cli-options.d.ts +1 -0
- package/dist/types/personal-diagnostics.d.ts +13 -0
- package/dist/types/personal-main.d.ts +9 -0
- package/dist/types/personal-port-forward.d.ts +45 -0
- package/dist/types/personal-relay-client.d.ts +51 -0
- package/dist/types/personal-relay-shutdown.d.ts +19 -0
- package/dist/types/runtime/chromium-factory.d.ts +25 -0
- package/dist/types/runtime/fixtures/counter-main.d.ts +1 -0
- package/dist/types/runtime/fixtures/counter-runtime.d.ts +6 -2
- package/dist/types/runtime/isolated-root.d.ts +12 -0
- package/dist/types/runtime/main.d.ts +20 -13
- package/dist/types/runtime/private-paths.d.ts +4 -0
- package/package.json +6 -5
- package/dist/cjs/browser-input.cjs +0 -87
- package/dist/cjs/browser-runtime.cjs +0 -708
- package/dist/cjs/chrome-launcher.cjs +0 -701
- package/dist/cjs/cli-options.cjs +0 -95
- package/dist/cjs/main.cjs +0 -427
- package/dist/cjs/password-safe-snapshot.cjs +0 -150
- package/dist/cjs/port-forward-manager.cjs +0 -233
- package/dist/cjs/upload-store.cjs +0 -136
- package/dist/mjs/port-forward-manager.mjs +0 -199
- package/dist/types/port-forward-manager.d.ts +0 -23
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { BrowserCliOptions } from "./cli-options";
|
|
2
|
+
export declare function personalBrowserConnection(options: BrowserCliOptions): {
|
|
3
|
+
origin: string;
|
|
4
|
+
token: string;
|
|
5
|
+
};
|
|
6
|
+
/** Keep Chrome's OS environment intact while isolating r5d state per origin. */
|
|
7
|
+
export declare function personalBrowserStateDirectory(origin: string, rootPath?: string): string;
|
|
8
|
+
/** The locally retained keeper, profile and ledger outlive every web reconnect. */
|
|
9
|
+
export declare function startPersonalBrowser(options: BrowserCliOptions, version: string): Promise<void>;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { PersonalBrowserObserver } from "./personal-diagnostics";
|
|
2
|
+
export type ForwardRequest = {
|
|
3
|
+
forwardId: string;
|
|
4
|
+
streamId: string;
|
|
5
|
+
requestId: string;
|
|
6
|
+
command: {
|
|
7
|
+
method: "connect" | "write" | "read" | "close";
|
|
8
|
+
offset?: number;
|
|
9
|
+
after?: number;
|
|
10
|
+
base64?: string;
|
|
11
|
+
end?: boolean;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
export type ForwardCall = (request: ForwardRequest) => Promise<any>;
|
|
15
|
+
export declare class PersonalForwardResponseError extends Error {
|
|
16
|
+
readonly status: number;
|
|
17
|
+
readonly code?: string | undefined;
|
|
18
|
+
constructor(status: number, message: string, code?: string | undefined);
|
|
19
|
+
}
|
|
20
|
+
/** Local loopback sockets outlive every HTTP relay/web connection. Each byte
|
|
21
|
+
* operation waits for its immutable acknowledgement before advancing offsets. */
|
|
22
|
+
export declare class PersonalPortForwardManager {
|
|
23
|
+
private readonly call;
|
|
24
|
+
private readonly observer?;
|
|
25
|
+
private active;
|
|
26
|
+
private failures;
|
|
27
|
+
private queue;
|
|
28
|
+
private stopping;
|
|
29
|
+
constructor(call: ForwardCall, observer?: PersonalBrowserObserver | undefined);
|
|
30
|
+
private observe;
|
|
31
|
+
list(): {
|
|
32
|
+
forwardId: string;
|
|
33
|
+
ready: boolean;
|
|
34
|
+
activeConnections: number;
|
|
35
|
+
lastError: {
|
|
36
|
+
error: string;
|
|
37
|
+
at: string;
|
|
38
|
+
} | null;
|
|
39
|
+
}[];
|
|
40
|
+
reconcile(raw: unknown): Promise<void>;
|
|
41
|
+
private start;
|
|
42
|
+
private stop;
|
|
43
|
+
private accept;
|
|
44
|
+
close(): Promise<void>;
|
|
45
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { BrowserKeeper } from "./runtime/keeper";
|
|
2
|
+
import { type BrowserReceipt } from "./runtime/protocol";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
export declare const PersonalBrowserAction: z.ZodObject<{
|
|
5
|
+
id: z.ZodString;
|
|
6
|
+
requestHash: z.ZodString;
|
|
7
|
+
request: z.ZodObject<{
|
|
8
|
+
action: z.ZodEnum<{
|
|
9
|
+
list_tabs: "list_tabs";
|
|
10
|
+
list_downloads: "list_downloads";
|
|
11
|
+
get_download: "get_download";
|
|
12
|
+
open_tab: "open_tab";
|
|
13
|
+
close_tab: "close_tab";
|
|
14
|
+
navigate: "navigate";
|
|
15
|
+
set_viewport: "set_viewport";
|
|
16
|
+
read_page: "read_page";
|
|
17
|
+
screenshot: "screenshot";
|
|
18
|
+
move_mouse: "move_mouse";
|
|
19
|
+
mouse_click: "mouse_click";
|
|
20
|
+
scroll: "scroll";
|
|
21
|
+
wait_for: "wait_for";
|
|
22
|
+
form_input: "form_input";
|
|
23
|
+
keyboard: "keyboard";
|
|
24
|
+
keyboard_type: "keyboard_type";
|
|
25
|
+
run_js: "run_js";
|
|
26
|
+
upload_begin: "upload_begin";
|
|
27
|
+
upload_chunk: "upload_chunk";
|
|
28
|
+
upload_attach: "upload_attach";
|
|
29
|
+
upload_abort: "upload_abort";
|
|
30
|
+
}>;
|
|
31
|
+
input: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
32
|
+
}, z.core.$strict>;
|
|
33
|
+
}, z.core.$strict>;
|
|
34
|
+
/** Network replacement never disposes this keeper. Its ledger decides whether an
|
|
35
|
+
* action ran; polling the same server queue item cannot replay a browser effect. */
|
|
36
|
+
export declare class PersonalBrowserProcessor {
|
|
37
|
+
private readonly keeper;
|
|
38
|
+
readonly identity: {
|
|
39
|
+
installationId: string;
|
|
40
|
+
userId: string;
|
|
41
|
+
instanceId: string;
|
|
42
|
+
};
|
|
43
|
+
private readonly nextEpoch?;
|
|
44
|
+
private epoch;
|
|
45
|
+
constructor(keeper: BrowserKeeper, identity: {
|
|
46
|
+
installationId: string;
|
|
47
|
+
userId: string;
|
|
48
|
+
instanceId: string;
|
|
49
|
+
}, nextEpoch?: (() => number) | undefined);
|
|
50
|
+
execute(raw: unknown): Promise<BrowserReceipt>;
|
|
51
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
type RelayAction = {
|
|
2
|
+
id: string;
|
|
3
|
+
requestHash: string;
|
|
4
|
+
};
|
|
5
|
+
export type PersonalBrowserAcknowledgement = {
|
|
6
|
+
id: string;
|
|
7
|
+
requestHash: string;
|
|
8
|
+
state: "completed" | "unknown";
|
|
9
|
+
result: unknown;
|
|
10
|
+
};
|
|
11
|
+
/** Shutdown cancels queue observation, never an admitted browser effect or its receipt. */
|
|
12
|
+
export declare class PersonalBrowserRelayShutdown {
|
|
13
|
+
private readonly polls;
|
|
14
|
+
get stopping(): boolean;
|
|
15
|
+
get pollSignal(): AbortSignal;
|
|
16
|
+
stop(): void;
|
|
17
|
+
dispatch<T extends RelayAction>(actions: readonly T[], execute: (action: T) => Promise<unknown>, acknowledge: (receipt: PersonalBrowserAcknowledgement) => Promise<unknown>): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { BrowserExecutor } from "./keeper";
|
|
3
|
+
/** Declarative built-in factory approval, NOT an arbitrary JS module or Chromium argument escape hatch. */
|
|
4
|
+
export declare const ChromiumFactoryApproval: z.ZodObject<{
|
|
5
|
+
kind: z.ZodLiteral<"isolated-chromium-v1">;
|
|
6
|
+
executablePath: z.ZodString;
|
|
7
|
+
allowedOrigins: z.ZodArray<z.ZodString>;
|
|
8
|
+
}, z.core.$strict>;
|
|
9
|
+
export type ChromiumFactoryApproval = z.infer<typeof ChromiumFactoryApproval>;
|
|
10
|
+
export declare function loadApprovedChromiumFactory(filename: string, sha256: string): ChromiumFactoryApproval;
|
|
11
|
+
export type ChromiumKeeperIdentity = {
|
|
12
|
+
runId: string;
|
|
13
|
+
browserPid: number;
|
|
14
|
+
keeperPid: number;
|
|
15
|
+
profile: string;
|
|
16
|
+
downloads: string;
|
|
17
|
+
uploads: string;
|
|
18
|
+
};
|
|
19
|
+
export declare function createIsolatedChromiumRuntime(input: {
|
|
20
|
+
runs: string;
|
|
21
|
+
approval: ChromiumFactoryApproval;
|
|
22
|
+
}): Promise<{
|
|
23
|
+
executor: BrowserExecutor;
|
|
24
|
+
identity: ChromiumKeeperIdentity;
|
|
25
|
+
}>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { BrowserExecutor } from "../keeper";
|
|
2
2
|
/** Offline subprocess proof. No Chrome, network, profiles or user resources. */
|
|
3
|
-
export declare const createBrowserKeeperRuntime:
|
|
3
|
+
export declare const createBrowserKeeperRuntime: ({ directory }: {
|
|
4
|
+
directory: string;
|
|
5
|
+
}) => Promise<{
|
|
6
|
+
executor: BrowserExecutor;
|
|
7
|
+
}>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare function isolatedBrowserRoot(root: string, installationId: string, userId: string): {
|
|
2
|
+
ledger: string;
|
|
3
|
+
runs: string;
|
|
4
|
+
};
|
|
5
|
+
export declare function freshBrowserRun(runs: string): {
|
|
6
|
+
id: string;
|
|
7
|
+
directory: string;
|
|
8
|
+
profile: string;
|
|
9
|
+
downloads: string;
|
|
10
|
+
uploads: string;
|
|
11
|
+
home: string;
|
|
12
|
+
};
|
|
@@ -1,16 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { type ChromiumKeeperIdentity } from "./chromium-factory";
|
|
3
|
+
export declare const BrowserKeeperConfig: z.ZodObject<{
|
|
4
|
+
installationId: z.ZodString;
|
|
5
|
+
userId: z.ZodString;
|
|
6
|
+
instanceId: z.ZodString;
|
|
7
|
+
releaseId: z.ZodString;
|
|
8
|
+
root: z.ZodString;
|
|
9
|
+
factory: z.ZodObject<{
|
|
10
|
+
approvalPath: z.ZodString;
|
|
11
|
+
sha256: z.ZodString;
|
|
12
|
+
}, z.core.$strict>;
|
|
13
|
+
adapters: z.ZodArray<z.ZodObject<{
|
|
14
|
+
ownerId: z.ZodString;
|
|
15
|
+
token: z.ZodString;
|
|
16
|
+
}, z.core.$strict>>;
|
|
17
|
+
}, z.core.$strict>;
|
|
18
|
+
/** Only the built-in isolated REAL Chromium factory is reachable from this startup boundary. */
|
|
14
19
|
export declare function startConfiguredBrowserKeeper(configPath: string): Promise<{
|
|
20
|
+
socketPath: string;
|
|
21
|
+
identity: ChromiumKeeperIdentity;
|
|
15
22
|
close(): Promise<void>;
|
|
16
23
|
}>;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** Reject symlink ancestors, non-canonical paths and writable-by-other-user ancestors. */
|
|
2
|
+
export declare function assertPrivatePath(filename: string, kind: "directory" | "file", immutable?: boolean): void;
|
|
3
|
+
export declare function readPrivateFile(filename: string, maximumBytes: number, immutable?: boolean): Buffer;
|
|
4
|
+
export declare function makePrivateDirectory(directory: string): void;
|
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ricsam/r5d-browser",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.139",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"main": "./dist/
|
|
5
|
+
"main": "./dist/mjs/main.mjs",
|
|
6
6
|
"module": "./dist/mjs/main.mjs",
|
|
7
7
|
"types": "./dist/types/main.d.ts",
|
|
8
8
|
"exports": {
|
|
9
9
|
".": {
|
|
10
10
|
"types": "./dist/types/main.d.ts",
|
|
11
11
|
"import": "./dist/mjs/main.mjs",
|
|
12
|
-
"
|
|
12
|
+
"default": "./dist/mjs/main.mjs"
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
15
|
"repository": {
|
|
@@ -18,11 +18,12 @@
|
|
|
18
18
|
"directory": "packages/r5d-browser"
|
|
19
19
|
},
|
|
20
20
|
"bin": {
|
|
21
|
-
"r5d-browser": "dist/
|
|
21
|
+
"r5d-browser": "dist/mjs/main.mjs"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@ricsam/r5d-api": "^0.0.
|
|
24
|
+
"@ricsam/r5d-api": "^0.0.139",
|
|
25
25
|
"playwright-core": "1.62.1",
|
|
26
|
+
"zod": "^4.1.13",
|
|
26
27
|
"ws": "^8.18.3"
|
|
27
28
|
},
|
|
28
29
|
"files": [
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
var browser_input_exports = {};
|
|
20
|
-
__export(browser_input_exports, {
|
|
21
|
-
MAX_VIEWPORT_DIMENSION: () => MAX_VIEWPORT_DIMENSION,
|
|
22
|
-
normalizeBrowserInput: () => normalizeBrowserInput,
|
|
23
|
-
parseViewportInput: () => parseViewportInput
|
|
24
|
-
});
|
|
25
|
-
module.exports = __toCommonJS(browser_input_exports);
|
|
26
|
-
const browserInputFields = {
|
|
27
|
-
list_tabs: { required: [], optional: [] },
|
|
28
|
-
list_downloads: { required: [], optional: [] },
|
|
29
|
-
get_download: { required: ["downloadId"], optional: ["offset", "maxBytes"] },
|
|
30
|
-
open_tab: { required: [], optional: ["url", "disposition"] },
|
|
31
|
-
close_tab: { required: ["tabId"], optional: [] },
|
|
32
|
-
navigate: { required: ["tabId", "url"], optional: [] },
|
|
33
|
-
set_viewport: { required: ["tabId"], optional: ["width", "height", "reset"] },
|
|
34
|
-
read_page: { required: ["tabId"], optional: ["depth", "maxChars"] },
|
|
35
|
-
screenshot: { required: ["tabId"], optional: ["fullPage"] },
|
|
36
|
-
move_mouse: { required: ["tabId", "x", "y"], optional: [] },
|
|
37
|
-
mouse_click: { required: ["tabId"], optional: ["ref", "x", "y", "button", "clickCount"] },
|
|
38
|
-
scroll: { required: ["tabId"], optional: ["ref", "direction", "amount", "x", "y"] },
|
|
39
|
-
wait_for: { required: ["tabId"], optional: ["selector", "text", "url", "loadState", "state", "timeoutMs"] },
|
|
40
|
-
form_input: { required: ["tabId", "ref"], optional: ["value", "values", "checked"] },
|
|
41
|
-
keyboard: { required: ["tabId", "keys"], optional: ["modifiers"] },
|
|
42
|
-
keyboard_type: { required: ["tabId", "text"], optional: ["mode", "delayMs"] },
|
|
43
|
-
run_js: { required: ["tabId", "code"], optional: [] },
|
|
44
|
-
upload_files: { required: ["tabId", "files"], optional: ["ref", "selector"] },
|
|
45
|
-
upload_begin: { required: ["tabId", "uploadId", "files"], optional: ["ref", "selector"] },
|
|
46
|
-
upload_chunk: { required: ["tabId", "uploadId", "index", "offset", "base64"], optional: [] },
|
|
47
|
-
upload_attach: { required: ["tabId", "uploadId", "hashes"], optional: [] },
|
|
48
|
-
upload_abort: { required: ["tabId", "uploadId"], optional: [] },
|
|
49
|
-
port_forward: { required: ["workerPort"], optional: ["browserPort"] },
|
|
50
|
-
list_port_forwards: { required: [], optional: [] },
|
|
51
|
-
stop_port_forward: { required: ["forwardId"], optional: [] }
|
|
52
|
-
};
|
|
53
|
-
const MAX_VIEWPORT_DIMENSION = 4096;
|
|
54
|
-
function parseViewportInput(input) {
|
|
55
|
-
if (input.reset !== void 0 && typeof input.reset !== "boolean") throw new Error("set_viewport reset must be a boolean.");
|
|
56
|
-
if (input.reset === true) {
|
|
57
|
-
if (input.width !== void 0 || input.height !== void 0)
|
|
58
|
-
throw new Error("set_viewport accepts width/height or reset: true, not both.");
|
|
59
|
-
return null;
|
|
60
|
-
}
|
|
61
|
-
const { width, height } = input;
|
|
62
|
-
for (const [name, value] of Object.entries({ width, height })) {
|
|
63
|
-
if (typeof value !== "number" || !Number.isInteger(value) || value < 1 || value > MAX_VIEWPORT_DIMENSION) {
|
|
64
|
-
throw new Error(
|
|
65
|
-
`set_viewport requires ${name} to be an integer from 1 to ${MAX_VIEWPORT_DIMENSION} CSS pixels, or reset: true without dimensions.`
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
return { width, height };
|
|
70
|
-
}
|
|
71
|
-
function normalizeBrowserInput(action, input) {
|
|
72
|
-
const fields = browserInputFields[action];
|
|
73
|
-
for (const key of fields.required) {
|
|
74
|
-
if (input[key] === null || input[key] === void 0) throw new Error(`${action} requires ${key}.`);
|
|
75
|
-
}
|
|
76
|
-
const normalized = { ...input };
|
|
77
|
-
for (const key of fields.optional) {
|
|
78
|
-
if (normalized[key] === null) delete normalized[key];
|
|
79
|
-
}
|
|
80
|
-
return normalized;
|
|
81
|
-
}
|
|
82
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
83
|
-
0 && (module.exports = {
|
|
84
|
-
MAX_VIEWPORT_DIMENSION,
|
|
85
|
-
normalizeBrowserInput,
|
|
86
|
-
parseViewportInput
|
|
87
|
-
});
|