@elizaos/plugin-browser 2.0.0-alpha.9 → 2.0.11-beta.7
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/LICENSE +21 -0
- package/README.md +98 -83
- package/auto-enable.ts +24 -0
- package/dist/actions/browser-autofill-login.d.ts +43 -0
- package/dist/actions/browser-autofill-login.d.ts.map +1 -0
- package/dist/actions/browser-autofill-login.js +278 -0
- package/dist/actions/browser-autofill-login.js.map +1 -0
- package/dist/actions/browser.d.ts +11 -0
- package/dist/actions/browser.d.ts.map +1 -0
- package/dist/actions/browser.js +412 -0
- package/dist/actions/browser.js.map +1 -0
- package/dist/actions/manage-browser-bridge.d.ts +34 -0
- package/dist/actions/manage-browser-bridge.d.ts.map +1 -0
- package/dist/actions/manage-browser-bridge.js +572 -0
- package/dist/actions/manage-browser-bridge.js.map +1 -0
- package/dist/bridge-policy.d.ts +10 -0
- package/dist/bridge-policy.d.ts.map +1 -0
- package/dist/bridge-policy.js +37 -0
- package/dist/bridge-policy.js.map +1 -0
- package/dist/bridge-readiness.d.ts +16 -0
- package/dist/bridge-readiness.d.ts.map +1 -0
- package/dist/bridge-readiness.js +82 -0
- package/dist/bridge-readiness.js.map +1 -0
- package/dist/bridge-records.d.ts +9 -0
- package/dist/bridge-records.d.ts.map +1 -0
- package/dist/bridge-records.js +37 -0
- package/dist/bridge-records.js.map +1 -0
- package/dist/browser-capture-hooks.d.ts +9 -0
- package/dist/browser-capture-hooks.d.ts.map +1 -0
- package/dist/browser-capture-hooks.js +15 -0
- package/dist/browser-capture-hooks.js.map +1 -0
- package/dist/browser-service.d.ts +103 -0
- package/dist/browser-service.d.ts.map +1 -0
- package/dist/browser-service.js +186 -0
- package/dist/browser-service.js.map +1 -0
- package/dist/browser-workspace-hooks.d.ts +14 -0
- package/dist/browser-workspace-hooks.d.ts.map +1 -0
- package/dist/browser-workspace-hooks.js +15 -0
- package/dist/browser-workspace-hooks.js.map +1 -0
- package/dist/companion-auth.d.ts +34 -0
- package/dist/companion-auth.d.ts.map +1 -0
- package/dist/companion-auth.js +98 -0
- package/dist/companion-auth.js.map +1 -0
- package/dist/contracts.d.ts +284 -0
- package/dist/contracts.d.ts.map +1 -0
- package/dist/contracts.js +56 -0
- package/dist/contracts.js.map +1 -0
- package/dist/index.d.ts +30 -16
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +76 -90
- package/dist/index.js.map +1 -1
- package/dist/lifeops-session-contracts.d.ts +46 -0
- package/dist/lifeops-session-contracts.d.ts.map +1 -0
- package/dist/lifeops-session-contracts.js +1 -0
- package/dist/lifeops-session-contracts.js.map +1 -0
- package/dist/message-adapter.d.ts +9 -0
- package/dist/message-adapter.d.ts.map +1 -0
- package/dist/message-adapter.js +104 -0
- package/dist/message-adapter.js.map +1 -0
- package/dist/packaging.d.ts +27 -0
- package/dist/packaging.d.ts.map +1 -0
- package/dist/packaging.js +571 -0
- package/dist/packaging.js.map +1 -0
- package/dist/password-manager-bridge.d.ts +50 -0
- package/dist/password-manager-bridge.d.ts.map +1 -0
- package/dist/password-manager-bridge.js +437 -0
- package/dist/password-manager-bridge.js.map +1 -0
- package/dist/plugin.d.ts +10 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +168 -0
- package/dist/plugin.js.map +1 -0
- package/dist/providers/workspace.d.ts +13 -0
- package/dist/providers/workspace.d.ts.map +1 -0
- package/dist/providers/workspace.js +64 -0
- package/dist/providers/workspace.js.map +1 -0
- package/dist/routes/bridge.d.ts +37 -0
- package/dist/routes/bridge.d.ts.map +1 -0
- package/dist/routes/bridge.js +844 -0
- package/dist/routes/bridge.js.map +1 -0
- package/dist/routes/workspace-account-gate.d.ts +29 -0
- package/dist/routes/workspace-account-gate.d.ts.map +1 -0
- package/dist/routes/workspace-account-gate.js +147 -0
- package/dist/routes/workspace-account-gate.js.map +1 -0
- package/dist/routes/workspace-setup.d.ts +10 -0
- package/dist/routes/workspace-setup.d.ts.map +1 -0
- package/dist/routes/workspace-setup.js +65 -0
- package/dist/routes/workspace-setup.js.map +1 -0
- package/dist/routes/workspace.d.ts +20 -0
- package/dist/routes/workspace.d.ts.map +1 -0
- package/dist/routes/workspace.js +276 -0
- package/dist/routes/workspace.js.map +1 -0
- package/dist/schema.d.ts +2326 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +133 -0
- package/dist/schema.js.map +1 -0
- package/dist/service.d.ts +30 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/service.js +5 -0
- package/dist/service.js.map +1 -0
- package/dist/targets/bridge-target.d.ts +31 -0
- package/dist/targets/bridge-target.d.ts.map +1 -0
- package/dist/targets/bridge-target.js +98 -0
- package/dist/targets/bridge-target.js.map +1 -0
- package/dist/targets/stagehand-target.d.ts +3 -0
- package/dist/targets/stagehand-target.d.ts.map +1 -0
- package/dist/targets/stagehand-target.js +187 -0
- package/dist/targets/stagehand-target.js.map +1 -0
- package/dist/workspace/browser-capture.d.ts +41 -0
- package/dist/workspace/browser-capture.d.ts.map +1 -0
- package/dist/workspace/browser-capture.js +159 -0
- package/dist/workspace/browser-capture.js.map +1 -0
- package/dist/workspace/browser-workspace-desktop.d.ts +19 -0
- package/dist/workspace/browser-workspace-desktop.d.ts.map +1 -0
- package/dist/workspace/browser-workspace-desktop.js +1578 -0
- package/dist/workspace/browser-workspace-desktop.js.map +1 -0
- package/dist/workspace/browser-workspace-elements.d.ts +42 -0
- package/dist/workspace/browser-workspace-elements.d.ts.map +1 -0
- package/dist/workspace/browser-workspace-elements.js +547 -0
- package/dist/workspace/browser-workspace-elements.js.map +1 -0
- package/dist/workspace/browser-workspace-forms.d.ts +19 -0
- package/dist/workspace/browser-workspace-forms.d.ts.map +1 -0
- package/dist/workspace/browser-workspace-forms.js +277 -0
- package/dist/workspace/browser-workspace-forms.js.map +1 -0
- package/dist/workspace/browser-workspace-helpers.d.ts +32 -0
- package/dist/workspace/browser-workspace-helpers.d.ts.map +1 -0
- package/dist/workspace/browser-workspace-helpers.js +232 -0
- package/dist/workspace/browser-workspace-helpers.js.map +1 -0
- package/dist/workspace/browser-workspace-jsdom.d.ts +16 -0
- package/dist/workspace/browser-workspace-jsdom.d.ts.map +1 -0
- package/dist/workspace/browser-workspace-jsdom.js +233 -0
- package/dist/workspace/browser-workspace-jsdom.js.map +1 -0
- package/dist/workspace/browser-workspace-network.d.ts +7 -0
- package/dist/workspace/browser-workspace-network.d.ts.map +1 -0
- package/dist/workspace/browser-workspace-network.js +145 -0
- package/dist/workspace/browser-workspace-network.js.map +1 -0
- package/dist/workspace/browser-workspace-snapshots.d.ts +14 -0
- package/dist/workspace/browser-workspace-snapshots.d.ts.map +1 -0
- package/dist/workspace/browser-workspace-snapshots.js +144 -0
- package/dist/workspace/browser-workspace-snapshots.js.map +1 -0
- package/dist/workspace/browser-workspace-state.d.ts +24 -0
- package/dist/workspace/browser-workspace-state.d.ts.map +1 -0
- package/dist/workspace/browser-workspace-state.js +155 -0
- package/dist/workspace/browser-workspace-state.js.map +1 -0
- package/dist/workspace/browser-workspace-types.d.ts +345 -0
- package/dist/workspace/browser-workspace-types.d.ts.map +1 -0
- package/dist/workspace/browser-workspace-types.js +11 -0
- package/dist/workspace/browser-workspace-types.js.map +1 -0
- package/dist/workspace/browser-workspace-web.d.ts +8 -0
- package/dist/workspace/browser-workspace-web.d.ts.map +1 -0
- package/dist/workspace/browser-workspace-web.js +1342 -0
- package/dist/workspace/browser-workspace-web.js.map +1 -0
- package/dist/workspace/browser-workspace.d.ts +39 -0
- package/dist/workspace/browser-workspace.d.ts.map +1 -0
- package/dist/workspace/browser-workspace.js +958 -0
- package/dist/workspace/browser-workspace.js.map +1 -0
- package/dist/workspace/index.d.ts +26 -0
- package/dist/workspace/index.d.ts.map +1 -0
- package/dist/workspace/index.js +3 -0
- package/dist/workspace/index.js.map +1 -0
- package/dist/workspace.d.ts +2 -0
- package/dist/workspace.d.ts.map +1 -0
- package/dist/workspace.js +2 -0
- package/dist/workspace.js.map +1 -0
- package/package.json +71 -110
- package/dist/actions/click.d.ts +0 -3
- package/dist/actions/click.d.ts.map +0 -1
- package/dist/actions/click.js +0 -158
- package/dist/actions/click.js.map +0 -1
- package/dist/actions/extract.d.ts +0 -3
- package/dist/actions/extract.d.ts.map +0 -1
- package/dist/actions/extract.js +0 -168
- package/dist/actions/extract.js.map +0 -1
- package/dist/actions/index.d.ts +0 -7
- package/dist/actions/index.d.ts.map +0 -1
- package/dist/actions/index.js +0 -7
- package/dist/actions/index.js.map +0 -1
- package/dist/actions/navigate.d.ts +0 -3
- package/dist/actions/navigate.d.ts.map +0 -1
- package/dist/actions/navigate.js +0 -187
- package/dist/actions/navigate.js.map +0 -1
- package/dist/actions/screenshot.d.ts +0 -3
- package/dist/actions/screenshot.d.ts.map +0 -1
- package/dist/actions/screenshot.js +0 -167
- package/dist/actions/screenshot.js.map +0 -1
- package/dist/actions/select.d.ts +0 -3
- package/dist/actions/select.d.ts.map +0 -1
- package/dist/actions/select.js +0 -167
- package/dist/actions/select.js.map +0 -1
- package/dist/actions/type.d.ts +0 -3
- package/dist/actions/type.d.ts.map +0 -1
- package/dist/actions/type.js +0 -167
- package/dist/actions/type.js.map +0 -1
- package/dist/cli/index.d.ts +0 -8
- package/dist/cli/index.d.ts.map +0 -1
- package/dist/cli/index.js +0 -13
- package/dist/cli/index.js.map +0 -1
- package/dist/cli/register.d.ts +0 -20
- package/dist/cli/register.d.ts.map +0 -1
- package/dist/cli/register.js +0 -403
- package/dist/cli/register.js.map +0 -1
- package/dist/providerRelevance.d.ts +0 -4
- package/dist/providerRelevance.d.ts.map +0 -1
- package/dist/providerRelevance.js +0 -33
- package/dist/providerRelevance.js.map +0 -1
- package/dist/providers/browser-state.d.ts +0 -3
- package/dist/providers/browser-state.d.ts.map +0 -1
- package/dist/providers/browser-state.js +0 -72
- package/dist/providers/browser-state.js.map +0 -1
- package/dist/providers/index.d.ts +0 -2
- package/dist/providers/index.d.ts.map +0 -1
- package/dist/providers/index.js +0 -2
- package/dist/providers/index.js.map +0 -1
- package/dist/services/browser-service.d.ts +0 -32
- package/dist/services/browser-service.d.ts.map +0 -1
- package/dist/services/browser-service.js +0 -213
- package/dist/services/browser-service.js.map +0 -1
- package/dist/services/index.d.ts +0 -4
- package/dist/services/index.d.ts.map +0 -1
- package/dist/services/index.js +0 -4
- package/dist/services/index.js.map +0 -1
- package/dist/services/process-manager.d.ts +0 -24
- package/dist/services/process-manager.d.ts.map +0 -1
- package/dist/services/process-manager.js +0 -270
- package/dist/services/process-manager.js.map +0 -1
- package/dist/services/websocket-client.d.ts +0 -35
- package/dist/services/websocket-client.d.ts.map +0 -1
- package/dist/services/websocket-client.js +0 -221
- package/dist/services/websocket-client.js.map +0 -1
- package/dist/types.d.ts +0 -101
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
- package/dist/utils/captcha.d.ts +0 -33
- package/dist/utils/captcha.d.ts.map +0 -1
- package/dist/utils/captcha.js +0 -219
- package/dist/utils/captcha.js.map +0 -1
- package/dist/utils/errors.d.ts +0 -37
- package/dist/utils/errors.d.ts.map +0 -1
- package/dist/utils/errors.js +0 -81
- package/dist/utils/errors.js.map +0 -1
- package/dist/utils/index.d.ts +0 -5
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js +0 -5
- package/dist/utils/index.js.map +0 -1
- package/dist/utils/retry.d.ts +0 -26
- package/dist/utils/retry.d.ts.map +0 -1
- package/dist/utils/retry.js +0 -55
- package/dist/utils/retry.js.map +0 -1
- package/dist/utils/security.d.ts +0 -27
- package/dist/utils/security.d.ts.map +0 -1
- package/dist/utils/security.js +0 -139
- package/dist/utils/security.js.map +0 -1
- package/dist/utils/url.d.ts +0 -12
- package/dist/utils/url.d.ts.map +0 -1
- package/dist/utils/url.js +0 -39
- package/dist/utils/url.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-capture.d.ts","sourceRoot":"","sources":["../../src/workspace/browser-capture.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAoBH,oDAAoD;AACpD,eAAO,MAAM,UAAU,QAA2C,CAAC;AAEnE,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+EAA+E;IAC/E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8BAA8B;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,+BAA+B,IAAI,MAAM,CAExD;AAED,wBAAgB,yBAAyB,IAAI,OAAO,CAEnD;AA2BD,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,oBAAoB,iBAoHrE;AAED,wBAAsB,kBAAkB,kBAevC;AAED,wBAAgB,uBAAuB,IAAI,OAAO,CAEjD;AAED,wBAAgB,YAAY,IAAI,OAAO,CAEtC"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { setTimeout as sleep } from "node:timers/promises";
|
|
5
|
+
import { logger } from "@elizaos/core";
|
|
6
|
+
const CHROME_PATH = process.platform === "darwin" ? "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" : process.platform === "win32" ? "C:\\Program Files\\Google Chrome\\Application\\chrome.exe" : "/usr/bin/google-chrome-stable";
|
|
7
|
+
let activeBrowser = null;
|
|
8
|
+
let activeCaptureLoop = null;
|
|
9
|
+
let stopSignal = false;
|
|
10
|
+
const FRAME_FILE = join(tmpdir(), "eliza-stream-frame.jpg");
|
|
11
|
+
function getBrowserCaptureExecutablePath() {
|
|
12
|
+
return CHROME_PATH;
|
|
13
|
+
}
|
|
14
|
+
function isBrowserCaptureSupported() {
|
|
15
|
+
return existsSync(CHROME_PATH);
|
|
16
|
+
}
|
|
17
|
+
function ensurePopoutUrl(raw) {
|
|
18
|
+
try {
|
|
19
|
+
const u = new URL(raw);
|
|
20
|
+
if (u.hash?.includes("?")) {
|
|
21
|
+
if (!u.hash.includes("popout")) {
|
|
22
|
+
u.hash = `${u.hash}&popout`;
|
|
23
|
+
}
|
|
24
|
+
} else if (u.hash) {
|
|
25
|
+
u.hash = `${u.hash}?popout`;
|
|
26
|
+
} else if (!u.searchParams.has("popout")) {
|
|
27
|
+
u.searchParams.set("popout", "");
|
|
28
|
+
}
|
|
29
|
+
return u.toString();
|
|
30
|
+
} catch {
|
|
31
|
+
const sep = raw.includes("?") ? "&" : "?";
|
|
32
|
+
return `${raw}${sep}popout`;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
async function startBrowserCapture(config) {
|
|
36
|
+
if (activeBrowser) {
|
|
37
|
+
logger.info("[browser-capture] Already running");
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (!isBrowserCaptureSupported()) {
|
|
41
|
+
throw new Error(
|
|
42
|
+
`Google Chrome not found at ${CHROME_PATH}. Install Chrome or update browser-capture before enabling screen capture.`
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
const { url, width = 1280, height = 720, fps = 4, quality = 70 } = config;
|
|
46
|
+
const captureUrl = ensurePopoutUrl(url);
|
|
47
|
+
stopSignal = false;
|
|
48
|
+
logger.info(`[browser-capture] Launching headless Chrome to ${captureUrl}`);
|
|
49
|
+
const { default: puppeteer } = await import("puppeteer-core");
|
|
50
|
+
const browser = await puppeteer.launch({
|
|
51
|
+
executablePath: CHROME_PATH,
|
|
52
|
+
headless: true,
|
|
53
|
+
args: [
|
|
54
|
+
`--window-size=${width},${height}`,
|
|
55
|
+
"--no-sandbox",
|
|
56
|
+
"--disable-dev-shm-usage",
|
|
57
|
+
"--disable-extensions",
|
|
58
|
+
"--mute-audio",
|
|
59
|
+
// WebGL / SwiftShader — required for VRM avatar rendering parity
|
|
60
|
+
"--use-gl=swiftshader",
|
|
61
|
+
"--enable-webgl",
|
|
62
|
+
"--ignore-gpu-blocklist"
|
|
63
|
+
]
|
|
64
|
+
});
|
|
65
|
+
activeBrowser = browser;
|
|
66
|
+
const page = await browser.newPage();
|
|
67
|
+
await page.setViewport({ width, height, deviceScaleFactor: 1 });
|
|
68
|
+
await page.evaluateOnNewDocument(
|
|
69
|
+
(overlayLayout, theme, avatarIndex, destinationId) => {
|
|
70
|
+
if (overlayLayout) {
|
|
71
|
+
localStorage.setItem("eliza.stream.overlay-layout.v1", overlayLayout);
|
|
72
|
+
if (destinationId) {
|
|
73
|
+
localStorage.setItem(
|
|
74
|
+
`eliza.stream.overlay-layout.v1.${destinationId}`,
|
|
75
|
+
overlayLayout
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (theme) {
|
|
80
|
+
localStorage.setItem("eliza:theme", theme);
|
|
81
|
+
}
|
|
82
|
+
if (avatarIndex != null) {
|
|
83
|
+
localStorage.setItem("eliza_avatar_index", String(avatarIndex));
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
config.overlayLayout,
|
|
87
|
+
config.theme,
|
|
88
|
+
config.avatarIndex,
|
|
89
|
+
config.destinationId
|
|
90
|
+
);
|
|
91
|
+
await page.goto(captureUrl, {
|
|
92
|
+
waitUntil: "networkidle0",
|
|
93
|
+
timeout: 6e4
|
|
94
|
+
});
|
|
95
|
+
logger.info(`[browser-capture] Page loaded, writing frames to ${FRAME_FILE}`);
|
|
96
|
+
let frameCount = 0;
|
|
97
|
+
const frameIntervalMs = Math.max(100, Math.round(1e3 / Math.max(1, fps)));
|
|
98
|
+
activeCaptureLoop = (async () => {
|
|
99
|
+
while (!stopSignal) {
|
|
100
|
+
try {
|
|
101
|
+
await page.screenshot({
|
|
102
|
+
path: FRAME_FILE,
|
|
103
|
+
quality,
|
|
104
|
+
type: "jpeg"
|
|
105
|
+
});
|
|
106
|
+
frameCount += 1;
|
|
107
|
+
if (frameCount % 20 === 0) {
|
|
108
|
+
logger.debug(`[browser-capture] ${frameCount} frames written`);
|
|
109
|
+
}
|
|
110
|
+
} catch (error) {
|
|
111
|
+
if (!stopSignal) {
|
|
112
|
+
logger.warn(
|
|
113
|
+
`[browser-capture] frame capture failed: ${error instanceof Error ? error.message : String(error)}`
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (!stopSignal) {
|
|
118
|
+
await sleep(frameIntervalMs);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
})();
|
|
122
|
+
logger.info(
|
|
123
|
+
`[browser-capture] Screenshot loop active (${fps} fps), saving to ${FRAME_FILE}`
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
async function stopBrowserCapture() {
|
|
127
|
+
stopSignal = true;
|
|
128
|
+
if (activeCaptureLoop) {
|
|
129
|
+
try {
|
|
130
|
+
await activeCaptureLoop;
|
|
131
|
+
} catch {
|
|
132
|
+
}
|
|
133
|
+
activeCaptureLoop = null;
|
|
134
|
+
}
|
|
135
|
+
if (activeBrowser) {
|
|
136
|
+
try {
|
|
137
|
+
await activeBrowser.close();
|
|
138
|
+
} catch {
|
|
139
|
+
}
|
|
140
|
+
activeBrowser = null;
|
|
141
|
+
}
|
|
142
|
+
logger.info("[browser-capture] Stopped");
|
|
143
|
+
}
|
|
144
|
+
function isBrowserCaptureRunning() {
|
|
145
|
+
return activeBrowser !== null;
|
|
146
|
+
}
|
|
147
|
+
function hasFrameFile() {
|
|
148
|
+
return existsSync(FRAME_FILE);
|
|
149
|
+
}
|
|
150
|
+
export {
|
|
151
|
+
FRAME_FILE,
|
|
152
|
+
getBrowserCaptureExecutablePath,
|
|
153
|
+
hasFrameFile,
|
|
154
|
+
isBrowserCaptureRunning,
|
|
155
|
+
isBrowserCaptureSupported,
|
|
156
|
+
startBrowserCapture,
|
|
157
|
+
stopBrowserCapture
|
|
158
|
+
};
|
|
159
|
+
//# sourceMappingURL=browser-capture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/workspace/browser-capture.ts"],"sourcesContent":["/**\n * Headless browser capture — opens the StreamView in headless Chrome and\n * saves screenshots to a temp file. FFmpeg reads the temp file using\n * -loop 1 to continuously re-read the latest frame.\n *\n * This approach avoids the pipe bottleneck — FFmpeg reads at its own\n * pace while the browser updates the file independently.\n *\n * Visual parity with the desktop shell:\n * - Appends `?popout` to the URL so the app renders StreamView directly\n * (without onboarding, auth gates, or navigation chrome).\n * - Enables SwiftShader for WebGL so VRM avatar renders identically.\n * - Seeds localStorage with overlay layout, theme, and avatar index so\n * the first rendered frame matches the configured appearance.\n * - Uses `waitUntil: \"networkidle0\"` to ensure all assets load before capture.\n * - Keeps CSS animations/transitions enabled for visual parity.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { setTimeout as sleep } from \"node:timers/promises\";\nimport { logger } from \"@elizaos/core\";\nimport type { Browser } from \"puppeteer-core\";\n\nconst CHROME_PATH =\n process.platform === \"darwin\"\n ? \"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome\"\n : process.platform === \"win32\"\n ? \"C:\\\\Program Files\\\\Google Chrome\\\\Application\\\\chrome.exe\"\n : \"/usr/bin/google-chrome-stable\";\n\nlet activeBrowser: Browser | null = null;\nlet activeCaptureLoop: Promise<void> | null = null;\nlet stopSignal = false;\n\n/** Path to the temp frame file that FFmpeg reads */\nexport const FRAME_FILE = join(tmpdir(), \"eliza-stream-frame.jpg\");\n\nexport interface BrowserCaptureConfig {\n url: string;\n width?: number;\n height?: number;\n fps?: number;\n quality?: number;\n /** Optional overlay layout JSON to seed into localStorage before page load. */\n overlayLayout?: string;\n /** Theme name to apply (e.g. \"eliza\", \"haxor\", \"psycho\"). */\n theme?: string;\n /** Avatar VRM index (1–8). */\n avatarIndex?: number;\n /** Destination ID — seeds the destination-specific localStorage key. */\n destinationId?: string;\n}\n\nexport function getBrowserCaptureExecutablePath(): string {\n return CHROME_PATH;\n}\n\nexport function isBrowserCaptureSupported(): boolean {\n return existsSync(CHROME_PATH);\n}\n\n/**\n * Ensure the URL includes the `?popout` parameter so the app renders only\n * StreamView without startup gates or navigation chrome.\n */\nfunction ensurePopoutUrl(raw: string): string {\n try {\n const u = new URL(raw);\n // Handle both query and hash-based routing\n if (u.hash?.includes(\"?\")) {\n if (!u.hash.includes(\"popout\")) {\n u.hash = `${u.hash}&popout`;\n }\n } else if (u.hash) {\n u.hash = `${u.hash}?popout`;\n } else if (!u.searchParams.has(\"popout\")) {\n u.searchParams.set(\"popout\", \"\");\n }\n return u.toString();\n } catch {\n // Fallback: just append\n const sep = raw.includes(\"?\") ? \"&\" : \"?\";\n return `${raw}${sep}popout`;\n }\n}\n\nexport async function startBrowserCapture(config: BrowserCaptureConfig) {\n if (activeBrowser) {\n logger.info(\"[browser-capture] Already running\");\n return;\n }\n\n if (!isBrowserCaptureSupported()) {\n throw new Error(\n `Google Chrome not found at ${CHROME_PATH}. Install Chrome or update browser-capture before enabling screen capture.`,\n );\n }\n\n const { url, width = 1280, height = 720, fps = 4, quality = 70 } = config;\n const captureUrl = ensurePopoutUrl(url);\n\n stopSignal = false;\n logger.info(`[browser-capture] Launching headless Chrome to ${captureUrl}`);\n\n const { default: puppeteer } = await import(\"puppeteer-core\");\n const browser = await puppeteer.launch({\n executablePath: CHROME_PATH,\n headless: true,\n args: [\n `--window-size=${width},${height}`,\n \"--no-sandbox\",\n \"--disable-dev-shm-usage\",\n \"--disable-extensions\",\n \"--mute-audio\",\n // WebGL / SwiftShader — required for VRM avatar rendering parity\n \"--use-gl=swiftshader\",\n \"--enable-webgl\",\n \"--ignore-gpu-blocklist\",\n ],\n });\n\n activeBrowser = browser;\n\n const page = await browser.newPage();\n await page.setViewport({ width, height, deviceScaleFactor: 1 });\n\n // Seed localStorage before navigation so the first render matches the desktop shell.\n // Keys must match exactly what the React app reads:\n // - \"eliza:theme\" → ThemeName\n // - \"eliza_avatar_index\" → VRM index (1–8)\n // - \"eliza.stream.overlay-layout.v1[.destId]\" → OverlayLayout JSON\n await page.evaluateOnNewDocument(\n (\n overlayLayout: string | undefined,\n theme: string | undefined,\n avatarIndex: number | undefined,\n destinationId: string | undefined,\n ) => {\n if (overlayLayout) {\n // Seed both global and destination-specific keys so the hook\n // resolves correctly regardless of when activeDestination loads.\n localStorage.setItem(\"eliza.stream.overlay-layout.v1\", overlayLayout);\n if (destinationId) {\n localStorage.setItem(\n `eliza.stream.overlay-layout.v1.${destinationId}`,\n overlayLayout,\n );\n }\n }\n if (theme) {\n localStorage.setItem(\"eliza:theme\", theme);\n }\n if (avatarIndex != null) {\n localStorage.setItem(\"eliza_avatar_index\", String(avatarIndex));\n }\n },\n config.overlayLayout,\n config.theme,\n config.avatarIndex,\n config.destinationId,\n );\n\n // Use networkidle0 so fonts, VRM models, and preview images finish loading\n await page.goto(captureUrl, {\n waitUntil: \"networkidle0\",\n timeout: 60_000,\n });\n\n logger.info(`[browser-capture] Page loaded, writing frames to ${FRAME_FILE}`);\n\n let frameCount = 0;\n const frameIntervalMs = Math.max(100, Math.round(1000 / Math.max(1, fps)));\n activeCaptureLoop = (async () => {\n while (!stopSignal) {\n try {\n await page.screenshot({\n path: FRAME_FILE,\n quality,\n type: \"jpeg\",\n });\n frameCount += 1;\n if (frameCount % 20 === 0) {\n logger.debug(`[browser-capture] ${frameCount} frames written`);\n }\n } catch (error) {\n if (!stopSignal) {\n logger.warn(\n `[browser-capture] frame capture failed: ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n }\n if (!stopSignal) {\n await sleep(frameIntervalMs);\n }\n }\n })();\n\n logger.info(\n `[browser-capture] Screenshot loop active (${fps} fps), saving to ${FRAME_FILE}`,\n );\n}\n\nexport async function stopBrowserCapture() {\n stopSignal = true;\n if (activeCaptureLoop) {\n try {\n await activeCaptureLoop;\n } catch {}\n activeCaptureLoop = null;\n }\n if (activeBrowser) {\n try {\n await activeBrowser.close();\n } catch {}\n activeBrowser = null;\n }\n logger.info(\"[browser-capture] Stopped\");\n}\n\nexport function isBrowserCaptureRunning(): boolean {\n return activeBrowser !== null;\n}\n\nexport function hasFrameFile(): boolean {\n return existsSync(FRAME_FILE);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { BrowserWorkspaceBridgeConfig, BrowserWorkspaceCommand, BrowserWorkspaceCommandResult, BrowserWorkspaceSnapshotRecord, BrowserWorkspaceTab, EvaluateBrowserWorkspaceTabRequest } from "./browser-workspace-types.js";
|
|
2
|
+
export declare function resolveBrowserWorkspaceBridgeConfig(env?: NodeJS.ProcessEnv): BrowserWorkspaceBridgeConfig | null;
|
|
3
|
+
export declare function isBrowserWorkspaceBridgeConfigured(env?: NodeJS.ProcessEnv): boolean;
|
|
4
|
+
export declare function getBrowserWorkspaceUnavailableMessage(): string;
|
|
5
|
+
export declare function requestBrowserWorkspace<T>(path: string, init?: RequestInit, env?: NodeJS.ProcessEnv): Promise<T>;
|
|
6
|
+
export declare function evaluateBrowserWorkspaceTab(request: EvaluateBrowserWorkspaceTabRequest, env?: NodeJS.ProcessEnv): Promise<unknown>;
|
|
7
|
+
export declare function snapshotBrowserWorkspaceTab(id: string, env?: NodeJS.ProcessEnv): Promise<{
|
|
8
|
+
data: string;
|
|
9
|
+
}>;
|
|
10
|
+
export declare function createDesktopBrowserWorkspaceCommandScript(command: BrowserWorkspaceCommand, env?: NodeJS.ProcessEnv): string;
|
|
11
|
+
export declare function createDesktopBrowserWorkspaceUtilityScript(command: BrowserWorkspaceCommand): string;
|
|
12
|
+
export declare function executeDesktopBrowserWorkspaceUtilityCommand(command: BrowserWorkspaceCommand, env: NodeJS.ProcessEnv): Promise<BrowserWorkspaceCommandResult>;
|
|
13
|
+
export declare function getDesktopBrowserWorkspaceSnapshotRecord(command: BrowserWorkspaceCommand, env: NodeJS.ProcessEnv): Promise<BrowserWorkspaceSnapshotRecord>;
|
|
14
|
+
export declare function getDesktopBrowserWorkspaceSessionState(command: BrowserWorkspaceCommand, env: NodeJS.ProcessEnv): Promise<Record<string, unknown>>;
|
|
15
|
+
export declare function loadDesktopBrowserWorkspaceSessionState(command: BrowserWorkspaceCommand, payload: Record<string, unknown>, env: NodeJS.ProcessEnv): Promise<void>;
|
|
16
|
+
export declare function executeDesktopBrowserWorkspaceDomCommand(command: BrowserWorkspaceCommand, env: NodeJS.ProcessEnv): Promise<BrowserWorkspaceCommandResult>;
|
|
17
|
+
export declare function resolveBrowserWorkspaceCurrentTab(tabs: BrowserWorkspaceTab[]): BrowserWorkspaceTab | null;
|
|
18
|
+
export declare function resolveDesktopBrowserWorkspaceTargetTabId(command: BrowserWorkspaceCommand, env: NodeJS.ProcessEnv): Promise<string>;
|
|
19
|
+
//# sourceMappingURL=browser-workspace-desktop.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-workspace-desktop.d.ts","sourceRoot":"","sources":["../../src/workspace/browser-workspace-desktop.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EACV,4BAA4B,EAC5B,uBAAuB,EACvB,6BAA6B,EAE7B,8BAA8B,EAC9B,mBAAmB,EACnB,kCAAkC,EACnC,MAAM,8BAA8B,CAAC;AAsBtC,wBAAgB,mCAAmC,CACjD,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,4BAA4B,GAAG,IAAI,CAUrC;AAED,wBAAgB,kCAAkC,CAChD,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAET;AAED,wBAAgB,qCAAqC,IAAI,MAAM,CAE9D;AAED,wBAAsB,uBAAuB,CAAC,CAAC,EAC7C,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,WAAW,EAClB,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAAC,CAAC,CAAC,CA6BZ;AAED,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,kCAAkC,EAC3C,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAAC,OAAO,CAAC,CAuBlB;AAED,wBAAsB,2BAA2B,CAC/C,EAAE,EAAE,MAAM,EACV,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAY3B;AAsBD,wBAAgB,0CAA0C,CACxD,OAAO,EAAE,uBAAuB,EAChC,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,CA0wBR;AAED,wBAAgB,0CAA0C,CACxD,OAAO,EAAE,uBAAuB,GAC/B,MAAM,CAibR;AAED,wBAAsB,4CAA4C,CAChE,OAAO,EAAE,uBAAuB,EAChC,GAAG,EAAE,MAAM,CAAC,UAAU,GACrB,OAAO,CAAC,6BAA6B,CAAC,CAwCxC;AAED,wBAAsB,wCAAwC,CAC5D,OAAO,EAAE,uBAAuB,EAChC,GAAG,EAAE,MAAM,CAAC,UAAU,GACrB,OAAO,CAAC,8BAA8B,CAAC,CA0CzC;AAED,wBAAsB,sCAAsC,CAC1D,OAAO,EAAE,uBAAuB,EAChC,GAAG,EAAE,MAAM,CAAC,UAAU,GACrB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAwClC;AAED,wBAAsB,uCAAuC,CAC3D,OAAO,EAAE,uBAAuB,EAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,GAAG,EAAE,MAAM,CAAC,UAAU,GACrB,OAAO,CAAC,IAAI,CAAC,CA+Bf;AAED,wBAAsB,wCAAwC,CAC5D,OAAO,EAAE,uBAAuB,EAChC,GAAG,EAAE,MAAM,CAAC,UAAU,GACrB,OAAO,CAAC,6BAA6B,CAAC,CA+DxC;AAID,wBAAgB,iCAAiC,CAC/C,IAAI,EAAE,mBAAmB,EAAE,GAC1B,mBAAmB,GAAG,IAAI,CAgB5B;AAED,wBAAsB,yCAAyC,CAC7D,OAAO,EAAE,uBAAuB,EAChC,GAAG,EAAE,MAAM,CAAC,UAAU,GACrB,OAAO,CAAC,MAAM,CAAC,CAoBjB"}
|