@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,277 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildBrowserWorkspaceElementSelector,
|
|
3
|
+
findClosestBrowserWorkspaceForm
|
|
4
|
+
} from "./browser-workspace-elements.js";
|
|
5
|
+
import {
|
|
6
|
+
assertBrowserWorkspaceUrl,
|
|
7
|
+
inferBrowserWorkspaceTitle,
|
|
8
|
+
normalizeBrowserWorkspaceText
|
|
9
|
+
} from "./browser-workspace-helpers.js";
|
|
10
|
+
import {
|
|
11
|
+
createEmptyWebBrowserWorkspaceDom,
|
|
12
|
+
ensureBrowserWorkspaceDom,
|
|
13
|
+
getJSDOMClass,
|
|
14
|
+
installBrowserWorkspaceWebRuntime
|
|
15
|
+
} from "./browser-workspace-jsdom.js";
|
|
16
|
+
import { fetchBrowserWorkspaceTrackedResponse } from "./browser-workspace-network.js";
|
|
17
|
+
import {
|
|
18
|
+
getBrowserWorkspaceRuntimeState,
|
|
19
|
+
getBrowserWorkspaceTimestamp,
|
|
20
|
+
resetBrowserWorkspaceRuntimeNavigationState
|
|
21
|
+
} from "./browser-workspace-state.js";
|
|
22
|
+
function ensureBrowserWorkspaceFormControlElement(element, subaction) {
|
|
23
|
+
if (element.tagName === "INPUT" || element.tagName === "TEXTAREA" || element.tagName === "SELECT") {
|
|
24
|
+
return element;
|
|
25
|
+
}
|
|
26
|
+
throw new Error(
|
|
27
|
+
`Eliza browser workspace ${subaction} requires an input, textarea, or select target.`
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
function ensureBrowserWorkspaceCheckboxElement(element, subaction) {
|
|
31
|
+
if (element.tagName === "INPUT") {
|
|
32
|
+
const input = element;
|
|
33
|
+
const type = input.type.trim().toLowerCase();
|
|
34
|
+
if (type === "checkbox" || type === "radio") {
|
|
35
|
+
return input;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
throw new Error(
|
|
39
|
+
`Eliza browser workspace ${subaction} requires a checkbox or radio input target.`
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
function setBrowserWorkspaceControlValue(control, nextValue) {
|
|
43
|
+
control.value = nextValue;
|
|
44
|
+
if (control.tagName === "TEXTAREA") {
|
|
45
|
+
control.textContent = nextValue;
|
|
46
|
+
}
|
|
47
|
+
control.setAttribute("value", nextValue);
|
|
48
|
+
}
|
|
49
|
+
async function activateWebBrowserWorkspaceElement(tab, element, subaction) {
|
|
50
|
+
const tag = element.tagName.toLowerCase();
|
|
51
|
+
if (tag === "a") {
|
|
52
|
+
const href = element.getAttribute("href")?.trim();
|
|
53
|
+
if (!href) {
|
|
54
|
+
throw new Error("Target link does not have an href.");
|
|
55
|
+
}
|
|
56
|
+
const nextUrl = new URL(href, tab.url).toString();
|
|
57
|
+
clearWebBrowserWorkspaceTabElementRefs(tab.id);
|
|
58
|
+
tab.url = assertBrowserWorkspaceUrl(nextUrl);
|
|
59
|
+
tab.title = inferBrowserWorkspaceTitle(tab.url);
|
|
60
|
+
tab.dom = null;
|
|
61
|
+
tab.loadedUrl = null;
|
|
62
|
+
pushWebBrowserWorkspaceHistory(tab, tab.url);
|
|
63
|
+
await loadWebBrowserWorkspaceTabDocument(tab);
|
|
64
|
+
return {
|
|
65
|
+
mode: "web",
|
|
66
|
+
subaction,
|
|
67
|
+
tab: cloneWebBrowserWorkspaceTabState(tab),
|
|
68
|
+
value: {
|
|
69
|
+
clickCount: subaction === "dblclick" ? 2 : 1,
|
|
70
|
+
selector: buildBrowserWorkspaceElementSelector(element),
|
|
71
|
+
url: tab.url
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
const inputElement = tag === "input" ? element : null;
|
|
76
|
+
const inputType = inputElement?.type?.toLowerCase() ?? "";
|
|
77
|
+
if (inputElement && (inputType === "checkbox" || inputType === "radio")) {
|
|
78
|
+
inputElement.checked = inputType === "radio" ? true : !inputElement.checked;
|
|
79
|
+
return {
|
|
80
|
+
mode: "web",
|
|
81
|
+
subaction,
|
|
82
|
+
value: {
|
|
83
|
+
checked: inputElement.checked,
|
|
84
|
+
clickCount: subaction === "dblclick" ? 2 : 1,
|
|
85
|
+
selector: buildBrowserWorkspaceElementSelector(element)
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
const submitForm = findClosestBrowserWorkspaceForm(element);
|
|
90
|
+
if (submitForm && (tag === "form" || tag === "button" || tag === "input" && ["button", "image", "submit"].includes(inputType || "submit"))) {
|
|
91
|
+
await submitWebBrowserWorkspaceForm(tab, submitForm);
|
|
92
|
+
return {
|
|
93
|
+
mode: "web",
|
|
94
|
+
subaction,
|
|
95
|
+
tab: cloneWebBrowserWorkspaceTabState(tab),
|
|
96
|
+
value: {
|
|
97
|
+
clickCount: subaction === "dblclick" ? 2 : 1,
|
|
98
|
+
selector: buildBrowserWorkspaceElementSelector(element),
|
|
99
|
+
url: tab.url
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
return {
|
|
104
|
+
mode: "web",
|
|
105
|
+
subaction,
|
|
106
|
+
value: {
|
|
107
|
+
clickCount: subaction === "dblclick" ? 2 : 1,
|
|
108
|
+
selector: buildBrowserWorkspaceElementSelector(element),
|
|
109
|
+
text: normalizeBrowserWorkspaceText(element.textContent)
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function scrollWebBrowserWorkspaceTarget(dom, element, direction, pixels) {
|
|
114
|
+
const resolvedPixels = Number.isFinite(pixels) ? Math.max(1, Math.abs(pixels)) : 240;
|
|
115
|
+
const axis = direction === "left" || direction === "right" ? "x" : "y";
|
|
116
|
+
const delta = direction === "up" || direction === "left" ? -resolvedPixels : resolvedPixels;
|
|
117
|
+
if (element && element instanceof dom.window.HTMLElement) {
|
|
118
|
+
if (axis === "y") {
|
|
119
|
+
element.scrollTop = (element.scrollTop || 0) + delta;
|
|
120
|
+
return {
|
|
121
|
+
axis,
|
|
122
|
+
selector: buildBrowserWorkspaceElementSelector(element),
|
|
123
|
+
value: element.scrollTop
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
element.scrollLeft = (element.scrollLeft || 0) + delta;
|
|
127
|
+
return {
|
|
128
|
+
axis,
|
|
129
|
+
selector: buildBrowserWorkspaceElementSelector(element),
|
|
130
|
+
value: element.scrollLeft
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
const key = axis === "y" ? "__elizaScrollY" : "__elizaScrollX";
|
|
134
|
+
const current = Number(Reflect.get(dom.window, key) ?? 0);
|
|
135
|
+
const next = current + delta;
|
|
136
|
+
Reflect.set(dom.window, key, next);
|
|
137
|
+
return {
|
|
138
|
+
axis,
|
|
139
|
+
selector: null,
|
|
140
|
+
value: next
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
async function submitWebBrowserWorkspaceForm(tab, form) {
|
|
144
|
+
const state = getBrowserWorkspaceRuntimeState("web", tab.id);
|
|
145
|
+
const dom = ensureBrowserWorkspaceDom(tab);
|
|
146
|
+
const action = form.getAttribute("action")?.trim() || tab.url;
|
|
147
|
+
const method = (form.getAttribute("method")?.trim() || "get").toLowerCase();
|
|
148
|
+
const submitUrl = new URL(action, tab.url).toString();
|
|
149
|
+
const formData = new dom.window.FormData(form);
|
|
150
|
+
const searchParams = new URLSearchParams();
|
|
151
|
+
for (const [key, value] of formData.entries()) {
|
|
152
|
+
searchParams.append(key, String(value));
|
|
153
|
+
}
|
|
154
|
+
if (method === "get") {
|
|
155
|
+
const nextUrl = new URL(submitUrl);
|
|
156
|
+
nextUrl.search = searchParams.toString();
|
|
157
|
+
clearWebBrowserWorkspaceTabElementRefs(tab.id);
|
|
158
|
+
tab.url = nextUrl.toString();
|
|
159
|
+
tab.title = inferBrowserWorkspaceTitle(tab.url);
|
|
160
|
+
tab.dom = null;
|
|
161
|
+
tab.loadedUrl = null;
|
|
162
|
+
pushWebBrowserWorkspaceHistory(tab, tab.url);
|
|
163
|
+
await loadWebBrowserWorkspaceTabDocument(tab);
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
const response = await fetchBrowserWorkspaceTrackedResponse(
|
|
167
|
+
state,
|
|
168
|
+
submitUrl,
|
|
169
|
+
{
|
|
170
|
+
body: searchParams.toString(),
|
|
171
|
+
headers: {
|
|
172
|
+
"Content-Type": "application/x-www-form-urlencoded; charset=utf-8"
|
|
173
|
+
},
|
|
174
|
+
method: method.toUpperCase()
|
|
175
|
+
},
|
|
176
|
+
"document"
|
|
177
|
+
);
|
|
178
|
+
if (!response.ok) {
|
|
179
|
+
throw new Error(
|
|
180
|
+
`Browser workspace form submit failed (${response.status}): ${submitUrl}`
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
const html = await response.text();
|
|
184
|
+
const finalUrl = assertBrowserWorkspaceUrl(response.url?.trim() || submitUrl);
|
|
185
|
+
const nextDom = new (getJSDOMClass())(html, {
|
|
186
|
+
pretendToBeVisual: true,
|
|
187
|
+
url: finalUrl
|
|
188
|
+
});
|
|
189
|
+
installBrowserWorkspaceWebRuntime(tab, nextDom);
|
|
190
|
+
resetBrowserWorkspaceRuntimeNavigationState(state);
|
|
191
|
+
clearWebBrowserWorkspaceTabElementRefs(tab.id);
|
|
192
|
+
tab.url = finalUrl;
|
|
193
|
+
tab.dom = nextDom;
|
|
194
|
+
tab.loadedUrl = finalUrl;
|
|
195
|
+
tab.title = normalizeBrowserWorkspaceText(nextDom.window.document.title) || inferBrowserWorkspaceTitle(finalUrl);
|
|
196
|
+
tab.updatedAt = getBrowserWorkspaceTimestamp();
|
|
197
|
+
pushWebBrowserWorkspaceHistory(tab, finalUrl);
|
|
198
|
+
}
|
|
199
|
+
import { clearBrowserWorkspaceElementRefs } from "./browser-workspace-state.js";
|
|
200
|
+
function clearWebBrowserWorkspaceTabElementRefs(tabId) {
|
|
201
|
+
clearBrowserWorkspaceElementRefs("web", tabId);
|
|
202
|
+
}
|
|
203
|
+
function cloneWebBrowserWorkspaceTabState(tab) {
|
|
204
|
+
return {
|
|
205
|
+
id: tab.id,
|
|
206
|
+
title: tab.title,
|
|
207
|
+
url: tab.url,
|
|
208
|
+
partition: tab.partition,
|
|
209
|
+
kind: tab.kind,
|
|
210
|
+
visible: tab.visible,
|
|
211
|
+
createdAt: tab.createdAt,
|
|
212
|
+
updatedAt: tab.updatedAt,
|
|
213
|
+
lastFocusedAt: tab.lastFocusedAt
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
function pushWebBrowserWorkspaceHistory(tab, nextUrl) {
|
|
217
|
+
const nextHistory = tab.history.slice(0, tab.historyIndex + 1);
|
|
218
|
+
nextHistory.push(nextUrl);
|
|
219
|
+
tab.history = nextHistory;
|
|
220
|
+
tab.historyIndex = nextHistory.length - 1;
|
|
221
|
+
}
|
|
222
|
+
async function loadWebBrowserWorkspaceTabDocument(tab) {
|
|
223
|
+
const state = getBrowserWorkspaceRuntimeState("web", tab.id);
|
|
224
|
+
if (tab.url === "about:blank") {
|
|
225
|
+
tab.dom = createEmptyWebBrowserWorkspaceDom(tab.url);
|
|
226
|
+
installBrowserWorkspaceWebRuntime(tab, tab.dom);
|
|
227
|
+
tab.loadedUrl = tab.url;
|
|
228
|
+
tab.title = "New Tab";
|
|
229
|
+
tab.updatedAt = getBrowserWorkspaceTimestamp();
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
const response = await fetchBrowserWorkspaceTrackedResponse(
|
|
233
|
+
state,
|
|
234
|
+
tab.url,
|
|
235
|
+
{},
|
|
236
|
+
"document"
|
|
237
|
+
);
|
|
238
|
+
if (!response.ok) {
|
|
239
|
+
throw new Error(
|
|
240
|
+
`Browser workspace web load failed (${response.status}): ${tab.url}`
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
const html = await response.text();
|
|
244
|
+
const finalUrl = assertBrowserWorkspaceUrl(response.url?.trim() || tab.url);
|
|
245
|
+
const dom = new (getJSDOMClass())(html, {
|
|
246
|
+
pretendToBeVisual: true,
|
|
247
|
+
url: finalUrl
|
|
248
|
+
});
|
|
249
|
+
installBrowserWorkspaceWebRuntime(tab, dom);
|
|
250
|
+
resetBrowserWorkspaceRuntimeNavigationState(state);
|
|
251
|
+
tab.dom = dom;
|
|
252
|
+
tab.loadedUrl = finalUrl;
|
|
253
|
+
tab.url = finalUrl;
|
|
254
|
+
tab.title = normalizeBrowserWorkspaceText(dom.window.document.title) || inferBrowserWorkspaceTitle(finalUrl);
|
|
255
|
+
tab.updatedAt = getBrowserWorkspaceTimestamp();
|
|
256
|
+
tab.history[tab.historyIndex] = finalUrl;
|
|
257
|
+
}
|
|
258
|
+
async function ensureLoadedWebBrowserWorkspaceTabDocument(tab) {
|
|
259
|
+
if (!tab.dom || tab.loadedUrl !== tab.url) {
|
|
260
|
+
await loadWebBrowserWorkspaceTabDocument(tab);
|
|
261
|
+
}
|
|
262
|
+
return ensureBrowserWorkspaceDom(tab);
|
|
263
|
+
}
|
|
264
|
+
export {
|
|
265
|
+
activateWebBrowserWorkspaceElement,
|
|
266
|
+
clearWebBrowserWorkspaceTabElementRefs,
|
|
267
|
+
cloneWebBrowserWorkspaceTabState,
|
|
268
|
+
ensureBrowserWorkspaceCheckboxElement,
|
|
269
|
+
ensureBrowserWorkspaceFormControlElement,
|
|
270
|
+
ensureLoadedWebBrowserWorkspaceTabDocument,
|
|
271
|
+
loadWebBrowserWorkspaceTabDocument,
|
|
272
|
+
pushWebBrowserWorkspaceHistory,
|
|
273
|
+
scrollWebBrowserWorkspaceTarget,
|
|
274
|
+
setBrowserWorkspaceControlValue,
|
|
275
|
+
submitWebBrowserWorkspaceForm
|
|
276
|
+
};
|
|
277
|
+
//# sourceMappingURL=browser-workspace-forms.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/workspace/browser-workspace-forms.ts"],"sourcesContent":["import type { JSDOM } from \"jsdom\";\nimport {\n buildBrowserWorkspaceElementSelector,\n findClosestBrowserWorkspaceForm,\n} from \"./browser-workspace-elements.js\";\nimport {\n assertBrowserWorkspaceUrl,\n inferBrowserWorkspaceTitle,\n normalizeBrowserWorkspaceText,\n} from \"./browser-workspace-helpers.js\";\nimport {\n createEmptyWebBrowserWorkspaceDom,\n ensureBrowserWorkspaceDom,\n getJSDOMClass,\n installBrowserWorkspaceWebRuntime,\n} from \"./browser-workspace-jsdom.js\";\nimport { fetchBrowserWorkspaceTrackedResponse } from \"./browser-workspace-network.js\";\nimport {\n getBrowserWorkspaceRuntimeState,\n getBrowserWorkspaceTimestamp,\n resetBrowserWorkspaceRuntimeNavigationState,\n} from \"./browser-workspace-state.js\";\nimport type {\n BrowserWorkspaceCommandResult,\n BrowserWorkspaceScrollDirection,\n WebBrowserWorkspaceTabState,\n} from \"./browser-workspace-types.js\";\n\nexport function ensureBrowserWorkspaceFormControlElement(\n element: Element,\n subaction:\n | \"clipboard\"\n | \"fill\"\n | \"keyboardinserttext\"\n | \"keyboardtype\"\n | \"select\"\n | \"type\",\n): HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement {\n if (\n element.tagName === \"INPUT\" ||\n element.tagName === \"TEXTAREA\" ||\n element.tagName === \"SELECT\"\n ) {\n return element as\n | HTMLInputElement\n | HTMLTextAreaElement\n | HTMLSelectElement;\n }\n\n throw new Error(\n `Eliza browser workspace ${subaction} requires an input, textarea, or select target.`,\n );\n}\n\nexport function ensureBrowserWorkspaceCheckboxElement(\n element: Element,\n subaction: \"check\" | \"uncheck\",\n): HTMLInputElement {\n if (element.tagName === \"INPUT\") {\n const input = element as HTMLInputElement;\n const type = input.type.trim().toLowerCase();\n if (type === \"checkbox\" || type === \"radio\") {\n return input;\n }\n }\n\n throw new Error(\n `Eliza browser workspace ${subaction} requires a checkbox or radio input target.`,\n );\n}\n\nexport function setBrowserWorkspaceControlValue(\n control: HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement,\n nextValue: string,\n): void {\n control.value = nextValue;\n if (control.tagName === \"TEXTAREA\") {\n control.textContent = nextValue;\n }\n control.setAttribute(\"value\", nextValue);\n}\n\nexport async function activateWebBrowserWorkspaceElement(\n tab: WebBrowserWorkspaceTabState,\n element: Element,\n subaction: \"click\" | \"dblclick\",\n): Promise<BrowserWorkspaceCommandResult> {\n const tag = element.tagName.toLowerCase();\n if (tag === \"a\") {\n const href = element.getAttribute(\"href\")?.trim();\n if (!href) {\n throw new Error(\"Target link does not have an href.\");\n }\n const nextUrl = new URL(href, tab.url).toString();\n clearWebBrowserWorkspaceTabElementRefs(tab.id);\n tab.url = assertBrowserWorkspaceUrl(nextUrl);\n tab.title = inferBrowserWorkspaceTitle(tab.url);\n tab.dom = null;\n tab.loadedUrl = null;\n pushWebBrowserWorkspaceHistory(tab, tab.url);\n await loadWebBrowserWorkspaceTabDocument(tab);\n return {\n mode: \"web\",\n subaction,\n tab: cloneWebBrowserWorkspaceTabState(tab),\n value: {\n clickCount: subaction === \"dblclick\" ? 2 : 1,\n selector: buildBrowserWorkspaceElementSelector(element),\n url: tab.url,\n },\n };\n }\n\n const inputElement = tag === \"input\" ? (element as HTMLInputElement) : null;\n const inputType = inputElement?.type?.toLowerCase() ?? \"\";\n if (inputElement && (inputType === \"checkbox\" || inputType === \"radio\")) {\n inputElement.checked = inputType === \"radio\" ? true : !inputElement.checked;\n return {\n mode: \"web\",\n subaction,\n value: {\n checked: inputElement.checked,\n clickCount: subaction === \"dblclick\" ? 2 : 1,\n selector: buildBrowserWorkspaceElementSelector(element),\n },\n };\n }\n\n const submitForm = findClosestBrowserWorkspaceForm(element);\n if (\n submitForm &&\n (tag === \"form\" ||\n tag === \"button\" ||\n (tag === \"input\" &&\n [\"button\", \"image\", \"submit\"].includes(inputType || \"submit\")))\n ) {\n await submitWebBrowserWorkspaceForm(tab, submitForm);\n return {\n mode: \"web\",\n subaction,\n tab: cloneWebBrowserWorkspaceTabState(tab),\n value: {\n clickCount: subaction === \"dblclick\" ? 2 : 1,\n selector: buildBrowserWorkspaceElementSelector(element),\n url: tab.url,\n },\n };\n }\n\n return {\n mode: \"web\",\n subaction,\n value: {\n clickCount: subaction === \"dblclick\" ? 2 : 1,\n selector: buildBrowserWorkspaceElementSelector(element),\n text: normalizeBrowserWorkspaceText(element.textContent),\n },\n };\n}\n\nexport function scrollWebBrowserWorkspaceTarget(\n dom: JSDOM,\n element: Element | null,\n direction: BrowserWorkspaceScrollDirection,\n pixels: number,\n): {\n axis: \"x\" | \"y\";\n selector: string | null;\n value: number;\n} {\n const resolvedPixels = Number.isFinite(pixels)\n ? Math.max(1, Math.abs(pixels))\n : 240;\n const axis = direction === \"left\" || direction === \"right\" ? \"x\" : \"y\";\n const delta =\n direction === \"up\" || direction === \"left\"\n ? -resolvedPixels\n : resolvedPixels;\n\n if (element && element instanceof dom.window.HTMLElement) {\n if (axis === \"y\") {\n element.scrollTop = (element.scrollTop || 0) + delta;\n return {\n axis,\n selector: buildBrowserWorkspaceElementSelector(element),\n value: element.scrollTop,\n };\n }\n element.scrollLeft = (element.scrollLeft || 0) + delta;\n return {\n axis,\n selector: buildBrowserWorkspaceElementSelector(element),\n value: element.scrollLeft,\n };\n }\n\n const key = axis === \"y\" ? \"__elizaScrollY\" : \"__elizaScrollX\";\n const current = Number(Reflect.get(dom.window, key) ?? 0);\n const next = current + delta;\n Reflect.set(dom.window, key, next);\n return {\n axis,\n selector: null,\n value: next,\n };\n}\n\nexport async function submitWebBrowserWorkspaceForm(\n tab: WebBrowserWorkspaceTabState,\n form: HTMLFormElement,\n): Promise<void> {\n const state = getBrowserWorkspaceRuntimeState(\"web\", tab.id);\n const dom = ensureBrowserWorkspaceDom(tab);\n const action = form.getAttribute(\"action\")?.trim() || tab.url;\n const method = (form.getAttribute(\"method\")?.trim() || \"get\").toLowerCase();\n const submitUrl = new URL(action, tab.url).toString();\n const formData = new dom.window.FormData(form);\n const searchParams = new URLSearchParams();\n\n for (const [key, value] of formData.entries()) {\n searchParams.append(key, String(value));\n }\n\n if (method === \"get\") {\n const nextUrl = new URL(submitUrl);\n nextUrl.search = searchParams.toString();\n clearWebBrowserWorkspaceTabElementRefs(tab.id);\n tab.url = nextUrl.toString();\n tab.title = inferBrowserWorkspaceTitle(tab.url);\n tab.dom = null;\n tab.loadedUrl = null;\n pushWebBrowserWorkspaceHistory(tab, tab.url);\n await loadWebBrowserWorkspaceTabDocument(tab);\n return;\n }\n\n const response = await fetchBrowserWorkspaceTrackedResponse(\n state,\n submitUrl,\n {\n body: searchParams.toString(),\n headers: {\n \"Content-Type\": \"application/x-www-form-urlencoded; charset=utf-8\",\n },\n method: method.toUpperCase(),\n },\n \"document\",\n );\n\n if (!response.ok) {\n throw new Error(\n `Browser workspace form submit failed (${response.status}): ${submitUrl}`,\n );\n }\n\n const html = await response.text();\n const finalUrl = assertBrowserWorkspaceUrl(response.url?.trim() || submitUrl);\n const nextDom = new (getJSDOMClass())(html, {\n pretendToBeVisual: true,\n url: finalUrl,\n });\n installBrowserWorkspaceWebRuntime(tab, nextDom);\n resetBrowserWorkspaceRuntimeNavigationState(state);\n clearWebBrowserWorkspaceTabElementRefs(tab.id);\n tab.url = finalUrl;\n tab.dom = nextDom;\n tab.loadedUrl = finalUrl;\n tab.title =\n normalizeBrowserWorkspaceText(nextDom.window.document.title) ||\n inferBrowserWorkspaceTitle(finalUrl);\n tab.updatedAt = getBrowserWorkspaceTimestamp();\n pushWebBrowserWorkspaceHistory(tab, finalUrl);\n}\n\n// --- Web tab helpers that forms/activation need ---\n\nimport { clearBrowserWorkspaceElementRefs } from \"./browser-workspace-state.js\";\nimport type { BrowserWorkspaceTab } from \"./browser-workspace-types.js\";\n\nexport function clearWebBrowserWorkspaceTabElementRefs(tabId: string): void {\n clearBrowserWorkspaceElementRefs(\"web\", tabId);\n}\n\nexport function cloneWebBrowserWorkspaceTabState(\n tab: WebBrowserWorkspaceTabState,\n): BrowserWorkspaceTab {\n return {\n id: tab.id,\n title: tab.title,\n url: tab.url,\n partition: tab.partition,\n kind: tab.kind,\n visible: tab.visible,\n createdAt: tab.createdAt,\n updatedAt: tab.updatedAt,\n lastFocusedAt: tab.lastFocusedAt,\n };\n}\n\nexport function pushWebBrowserWorkspaceHistory(\n tab: WebBrowserWorkspaceTabState,\n nextUrl: string,\n): void {\n const nextHistory = tab.history.slice(0, tab.historyIndex + 1);\n nextHistory.push(nextUrl);\n tab.history = nextHistory;\n tab.historyIndex = nextHistory.length - 1;\n}\n\nexport async function loadWebBrowserWorkspaceTabDocument(\n tab: WebBrowserWorkspaceTabState,\n): Promise<void> {\n const state = getBrowserWorkspaceRuntimeState(\"web\", tab.id);\n if (tab.url === \"about:blank\") {\n tab.dom = createEmptyWebBrowserWorkspaceDom(tab.url);\n installBrowserWorkspaceWebRuntime(tab, tab.dom);\n tab.loadedUrl = tab.url;\n tab.title = \"New Tab\";\n tab.updatedAt = getBrowserWorkspaceTimestamp();\n return;\n }\n\n const response = await fetchBrowserWorkspaceTrackedResponse(\n state,\n tab.url,\n {},\n \"document\",\n );\n if (!response.ok) {\n throw new Error(\n `Browser workspace web load failed (${response.status}): ${tab.url}`,\n );\n }\n\n const html = await response.text();\n const finalUrl = assertBrowserWorkspaceUrl(response.url?.trim() || tab.url);\n const dom = new (getJSDOMClass())(html, {\n pretendToBeVisual: true,\n url: finalUrl,\n });\n installBrowserWorkspaceWebRuntime(tab, dom);\n resetBrowserWorkspaceRuntimeNavigationState(state);\n\n tab.dom = dom;\n tab.loadedUrl = finalUrl;\n tab.url = finalUrl;\n tab.title =\n normalizeBrowserWorkspaceText(dom.window.document.title) ||\n inferBrowserWorkspaceTitle(finalUrl);\n tab.updatedAt = getBrowserWorkspaceTimestamp();\n tab.history[tab.historyIndex] = finalUrl;\n}\n\nexport async function ensureLoadedWebBrowserWorkspaceTabDocument(\n tab: WebBrowserWorkspaceTabState,\n): Promise<JSDOM> {\n if (!tab.dom || tab.loadedUrl !== tab.url) {\n await loadWebBrowserWorkspaceTabDocument(tab);\n }\n return ensureBrowserWorkspaceDom(tab);\n}\n"],"mappings":"AACA;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,4CAA4C;AACrD;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAOA,SAAS,yCACd,SACA,WAO4D;AAC5D,MACE,QAAQ,YAAY,WACpB,QAAQ,YAAY,cACpB,QAAQ,YAAY,UACpB;AACA,WAAO;AAAA,EAIT;AAEA,QAAM,IAAI;AAAA,IACR,2BAA2B,SAAS;AAAA,EACtC;AACF;AAEO,SAAS,sCACd,SACA,WACkB;AAClB,MAAI,QAAQ,YAAY,SAAS;AAC/B,UAAM,QAAQ;AACd,UAAM,OAAO,MAAM,KAAK,KAAK,EAAE,YAAY;AAC3C,QAAI,SAAS,cAAc,SAAS,SAAS;AAC3C,aAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,IAAI;AAAA,IACR,2BAA2B,SAAS;AAAA,EACtC;AACF;AAEO,SAAS,gCACd,SACA,WACM;AACN,UAAQ,QAAQ;AAChB,MAAI,QAAQ,YAAY,YAAY;AAClC,YAAQ,cAAc;AAAA,EACxB;AACA,UAAQ,aAAa,SAAS,SAAS;AACzC;AAEA,eAAsB,mCACpB,KACA,SACA,WACwC;AACxC,QAAM,MAAM,QAAQ,QAAQ,YAAY;AACxC,MAAI,QAAQ,KAAK;AACf,UAAM,OAAO,QAAQ,aAAa,MAAM,GAAG,KAAK;AAChD,QAAI,CAAC,MAAM;AACT,YAAM,IAAI,MAAM,oCAAoC;AAAA,IACtD;AACA,UAAM,UAAU,IAAI,IAAI,MAAM,IAAI,GAAG,EAAE,SAAS;AAChD,2CAAuC,IAAI,EAAE;AAC7C,QAAI,MAAM,0BAA0B,OAAO;AAC3C,QAAI,QAAQ,2BAA2B,IAAI,GAAG;AAC9C,QAAI,MAAM;AACV,QAAI,YAAY;AAChB,mCAA+B,KAAK,IAAI,GAAG;AAC3C,UAAM,mCAAmC,GAAG;AAC5C,WAAO;AAAA,MACL,MAAM;AAAA,MACN;AAAA,MACA,KAAK,iCAAiC,GAAG;AAAA,MACzC,OAAO;AAAA,QACL,YAAY,cAAc,aAAa,IAAI;AAAA,QAC3C,UAAU,qCAAqC,OAAO;AAAA,QACtD,KAAK,IAAI;AAAA,MACX;AAAA,IACF;AAAA,EACF;AAEA,QAAM,eAAe,QAAQ,UAAW,UAA+B;AACvE,QAAM,YAAY,cAAc,MAAM,YAAY,KAAK;AACvD,MAAI,iBAAiB,cAAc,cAAc,cAAc,UAAU;AACvE,iBAAa,UAAU,cAAc,UAAU,OAAO,CAAC,aAAa;AACpE,WAAO;AAAA,MACL,MAAM;AAAA,MACN;AAAA,MACA,OAAO;AAAA,QACL,SAAS,aAAa;AAAA,QACtB,YAAY,cAAc,aAAa,IAAI;AAAA,QAC3C,UAAU,qCAAqC,OAAO;AAAA,MACxD;AAAA,IACF;AAAA,EACF;AAEA,QAAM,aAAa,gCAAgC,OAAO;AAC1D,MACE,eACC,QAAQ,UACP,QAAQ,YACP,QAAQ,WACP,CAAC,UAAU,SAAS,QAAQ,EAAE,SAAS,aAAa,QAAQ,IAChE;AACA,UAAM,8BAA8B,KAAK,UAAU;AACnD,WAAO;AAAA,MACL,MAAM;AAAA,MACN;AAAA,MACA,KAAK,iCAAiC,GAAG;AAAA,MACzC,OAAO;AAAA,QACL,YAAY,cAAc,aAAa,IAAI;AAAA,QAC3C,UAAU,qCAAqC,OAAO;AAAA,QACtD,KAAK,IAAI;AAAA,MACX;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA,OAAO;AAAA,MACL,YAAY,cAAc,aAAa,IAAI;AAAA,MAC3C,UAAU,qCAAqC,OAAO;AAAA,MACtD,MAAM,8BAA8B,QAAQ,WAAW;AAAA,IACzD;AAAA,EACF;AACF;AAEO,SAAS,gCACd,KACA,SACA,WACA,QAKA;AACA,QAAM,iBAAiB,OAAO,SAAS,MAAM,IACzC,KAAK,IAAI,GAAG,KAAK,IAAI,MAAM,CAAC,IAC5B;AACJ,QAAM,OAAO,cAAc,UAAU,cAAc,UAAU,MAAM;AACnE,QAAM,QACJ,cAAc,QAAQ,cAAc,SAChC,CAAC,iBACD;AAEN,MAAI,WAAW,mBAAmB,IAAI,OAAO,aAAa;AACxD,QAAI,SAAS,KAAK;AAChB,cAAQ,aAAa,QAAQ,aAAa,KAAK;AAC/C,aAAO;AAAA,QACL;AAAA,QACA,UAAU,qCAAqC,OAAO;AAAA,QACtD,OAAO,QAAQ;AAAA,MACjB;AAAA,IACF;AACA,YAAQ,cAAc,QAAQ,cAAc,KAAK;AACjD,WAAO;AAAA,MACL;AAAA,MACA,UAAU,qCAAqC,OAAO;AAAA,MACtD,OAAO,QAAQ;AAAA,IACjB;AAAA,EACF;AAEA,QAAM,MAAM,SAAS,MAAM,mBAAmB;AAC9C,QAAM,UAAU,OAAO,QAAQ,IAAI,IAAI,QAAQ,GAAG,KAAK,CAAC;AACxD,QAAM,OAAO,UAAU;AACvB,UAAQ,IAAI,IAAI,QAAQ,KAAK,IAAI;AACjC,SAAO;AAAA,IACL;AAAA,IACA,UAAU;AAAA,IACV,OAAO;AAAA,EACT;AACF;AAEA,eAAsB,8BACpB,KACA,MACe;AACf,QAAM,QAAQ,gCAAgC,OAAO,IAAI,EAAE;AAC3D,QAAM,MAAM,0BAA0B,GAAG;AACzC,QAAM,SAAS,KAAK,aAAa,QAAQ,GAAG,KAAK,KAAK,IAAI;AAC1D,QAAM,UAAU,KAAK,aAAa,QAAQ,GAAG,KAAK,KAAK,OAAO,YAAY;AAC1E,QAAM,YAAY,IAAI,IAAI,QAAQ,IAAI,GAAG,EAAE,SAAS;AACpD,QAAM,WAAW,IAAI,IAAI,OAAO,SAAS,IAAI;AAC7C,QAAM,eAAe,IAAI,gBAAgB;AAEzC,aAAW,CAAC,KAAK,KAAK,KAAK,SAAS,QAAQ,GAAG;AAC7C,iBAAa,OAAO,KAAK,OAAO,KAAK,CAAC;AAAA,EACxC;AAEA,MAAI,WAAW,OAAO;AACpB,UAAM,UAAU,IAAI,IAAI,SAAS;AACjC,YAAQ,SAAS,aAAa,SAAS;AACvC,2CAAuC,IAAI,EAAE;AAC7C,QAAI,MAAM,QAAQ,SAAS;AAC3B,QAAI,QAAQ,2BAA2B,IAAI,GAAG;AAC9C,QAAI,MAAM;AACV,QAAI,YAAY;AAChB,mCAA+B,KAAK,IAAI,GAAG;AAC3C,UAAM,mCAAmC,GAAG;AAC5C;AAAA,EACF;AAEA,QAAM,WAAW,MAAM;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,MACE,MAAM,aAAa,SAAS;AAAA,MAC5B,SAAS;AAAA,QACP,gBAAgB;AAAA,MAClB;AAAA,MACA,QAAQ,OAAO,YAAY;AAAA,IAC7B;AAAA,IACA;AAAA,EACF;AAEA,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,IAAI;AAAA,MACR,yCAAyC,SAAS,MAAM,MAAM,SAAS;AAAA,IACzE;AAAA,EACF;AAEA,QAAM,OAAO,MAAM,SAAS,KAAK;AACjC,QAAM,WAAW,0BAA0B,SAAS,KAAK,KAAK,KAAK,SAAS;AAC5E,QAAM,UAAU,KAAK,cAAc,GAAG,MAAM;AAAA,IAC1C,mBAAmB;AAAA,IACnB,KAAK;AAAA,EACP,CAAC;AACD,oCAAkC,KAAK,OAAO;AAC9C,8CAA4C,KAAK;AACjD,yCAAuC,IAAI,EAAE;AAC7C,MAAI,MAAM;AACV,MAAI,MAAM;AACV,MAAI,YAAY;AAChB,MAAI,QACF,8BAA8B,QAAQ,OAAO,SAAS,KAAK,KAC3D,2BAA2B,QAAQ;AACrC,MAAI,YAAY,6BAA6B;AAC7C,iCAA+B,KAAK,QAAQ;AAC9C;AAIA,SAAS,wCAAwC;AAG1C,SAAS,uCAAuC,OAAqB;AAC1E,mCAAiC,OAAO,KAAK;AAC/C;AAEO,SAAS,iCACd,KACqB;AACrB,SAAO;AAAA,IACL,IAAI,IAAI;AAAA,IACR,OAAO,IAAI;AAAA,IACX,KAAK,IAAI;AAAA,IACT,WAAW,IAAI;AAAA,IACf,MAAM,IAAI;AAAA,IACV,SAAS,IAAI;AAAA,IACb,WAAW,IAAI;AAAA,IACf,WAAW,IAAI;AAAA,IACf,eAAe,IAAI;AAAA,EACrB;AACF;AAEO,SAAS,+BACd,KACA,SACM;AACN,QAAM,cAAc,IAAI,QAAQ,MAAM,GAAG,IAAI,eAAe,CAAC;AAC7D,cAAY,KAAK,OAAO;AACxB,MAAI,UAAU;AACd,MAAI,eAAe,YAAY,SAAS;AAC1C;AAEA,eAAsB,mCACpB,KACe;AACf,QAAM,QAAQ,gCAAgC,OAAO,IAAI,EAAE;AAC3D,MAAI,IAAI,QAAQ,eAAe;AAC7B,QAAI,MAAM,kCAAkC,IAAI,GAAG;AACnD,sCAAkC,KAAK,IAAI,GAAG;AAC9C,QAAI,YAAY,IAAI;AACpB,QAAI,QAAQ;AACZ,QAAI,YAAY,6BAA6B;AAC7C;AAAA,EACF;AAEA,QAAM,WAAW,MAAM;AAAA,IACrB;AAAA,IACA,IAAI;AAAA,IACJ,CAAC;AAAA,IACD;AAAA,EACF;AACA,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,IAAI;AAAA,MACR,sCAAsC,SAAS,MAAM,MAAM,IAAI,GAAG;AAAA,IACpE;AAAA,EACF;AAEA,QAAM,OAAO,MAAM,SAAS,KAAK;AACjC,QAAM,WAAW,0BAA0B,SAAS,KAAK,KAAK,KAAK,IAAI,GAAG;AAC1E,QAAM,MAAM,KAAK,cAAc,GAAG,MAAM;AAAA,IACtC,mBAAmB;AAAA,IACnB,KAAK;AAAA,EACP,CAAC;AACD,oCAAkC,KAAK,GAAG;AAC1C,8CAA4C,KAAK;AAEjD,MAAI,MAAM;AACV,MAAI,YAAY;AAChB,MAAI,MAAM;AACV,MAAI,QACF,8BAA8B,IAAI,OAAO,SAAS,KAAK,KACvD,2BAA2B,QAAQ;AACrC,MAAI,YAAY,6BAA6B;AAC7C,MAAI,QAAQ,IAAI,YAAY,IAAI;AAClC;AAEA,eAAsB,2CACpB,KACgB;AAChB,MAAI,CAAC,IAAI,OAAO,IAAI,cAAc,IAAI,KAAK;AACzC,UAAM,mCAAmC,GAAG;AAAA,EAC9C;AACA,SAAO,0BAA0B,GAAG;AACtC;","names":[]}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { BrowserWorkspaceCommand, BrowserWorkspaceMode, BrowserWorkspaceSubaction } from "./browser-workspace-types.js";
|
|
2
|
+
export declare const DEFAULT_TIMEOUT_MS = 12000;
|
|
3
|
+
export declare const DEFAULT_WAIT_INTERVAL_MS = 120;
|
|
4
|
+
export declare const DEFAULT_WEB_PARTITION = "persist:eliza-browser";
|
|
5
|
+
export declare const CONNECTOR_BROWSER_WORKSPACE_PARTITION_PREFIX = "persist:connector-";
|
|
6
|
+
export declare const DESKTOP_BRIDGE_UNAVAILABLE_MESSAGE = "Eliza browser workspace desktop bridge is unavailable.";
|
|
7
|
+
export declare const browserWorkspacePageFetch: any;
|
|
8
|
+
export declare function normalizeEnvValue(value: string | undefined): string | null;
|
|
9
|
+
export declare function normalizeBrowserWorkspaceText(value: unknown): string;
|
|
10
|
+
export declare function parseBrowserWorkspaceNumberLike(value: unknown): number | undefined;
|
|
11
|
+
export declare function assertBrowserWorkspaceUrl(rawUrl: string): string;
|
|
12
|
+
export declare function inferBrowserWorkspaceTitle(url: string): string;
|
|
13
|
+
export declare function resolveConnectorBrowserWorkspacePartition(provider: string, accountId: string): string;
|
|
14
|
+
export declare function isConnectorBrowserWorkspacePartition(partition: string | null | undefined): boolean;
|
|
15
|
+
export declare function resolveBrowserWorkspaceCommandPartition(command: Pick<BrowserWorkspaceCommand, "connectorAccountId" | "connectorProvider" | "partition">, fallbackPartition: string): string;
|
|
16
|
+
export declare function assertBrowserWorkspaceConnectorSecretsNotExported(partition: string | null | undefined, operation: string): void;
|
|
17
|
+
export declare function createBrowserWorkspaceDesktopOnlyMessage(subaction: BrowserWorkspaceSubaction): string;
|
|
18
|
+
export declare function createBrowserWorkspaceNotFoundError(tabId: string): Error;
|
|
19
|
+
export declare function createBrowserWorkspaceCommandTargetError(subaction: BrowserWorkspaceSubaction): Error;
|
|
20
|
+
export declare function sleep(ms: number): Promise<void>;
|
|
21
|
+
export declare function writeBrowserWorkspaceFile(filePath: string, contents: string | Uint8Array): Promise<string>;
|
|
22
|
+
export declare function normalizeBrowserWorkspaceCommand(command: BrowserWorkspaceCommand): BrowserWorkspaceCommand;
|
|
23
|
+
export declare function resolveBrowserWorkspaceCommandElementRefs(command: BrowserWorkspaceCommand, mode: BrowserWorkspaceMode, tabId: string): BrowserWorkspaceCommand;
|
|
24
|
+
export declare function buildBrowserWorkspaceCssStringLiteral(value: string): string;
|
|
25
|
+
/** GHSA-mhhr-9ph9-64j7 / elizaOS/eliza#6767 — arbitrary script must not run in Node (JSDOM). */
|
|
26
|
+
export declare const BROWSER_WORKSPACE_JSDOM_SCRIPT_FORBIDDEN = "Browser workspace arbitrary script execution is disabled in the JSDOM (web) backend because it runs in the Node.js agent process via unsafe eval patterns (GHSA-mhhr-9ph9-64j7). Use structured subactions (click, fill, get, wait on selector/url/text) or desktop browser workspace mode instead.";
|
|
27
|
+
export declare const BROWSER_WORKSPACE_USER_SCRIPT_FORBIDDEN = "Browser workspace arbitrary user script is disabled (GHSA-mhhr-9ph9-64j7). Use structured browser workspace subactions instead.";
|
|
28
|
+
export declare function isBrowserWorkspaceUserScriptAllowed(env?: NodeJS.ProcessEnv): boolean;
|
|
29
|
+
export declare function assertBrowserWorkspaceUserScriptAllowed(script: string | undefined, context: "eval" | "wait", mode: BrowserWorkspaceMode, env?: NodeJS.ProcessEnv): void;
|
|
30
|
+
export declare function createBrowserWorkspaceJsdomScriptExecutionError(context: "eval" | "wait"): Error;
|
|
31
|
+
export declare function assertBrowserWorkspaceJsdomScriptNotRequested(script: string | undefined, context: "eval" | "wait"): void;
|
|
32
|
+
//# sourceMappingURL=browser-workspace-helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-workspace-helpers.d.ts","sourceRoot":"","sources":["../../src/workspace/browser-workspace-helpers.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,uBAAuB,EACvB,oBAAoB,EACpB,yBAAyB,EAC1B,MAAM,8BAA8B,CAAC;AAEtC,eAAO,MAAM,kBAAkB,QAAS,CAAC;AACzC,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAC5C,eAAO,MAAM,qBAAqB,0BAA0B,CAAC;AAC7D,eAAO,MAAM,4CAA4C,uBACnC,CAAC;AACvB,eAAO,MAAM,kCAAkC,2DACW,CAAC;AAC3D,eAAO,MAAM,yBAAyB,KAAoC,CAAC;AAE3E,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAM1E;AAED,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAIpE;AAED,wBAAgB,+BAA+B,CAC7C,KAAK,EAAE,OAAO,GACb,MAAM,GAAG,SAAS,CASpB;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAoBhE;AAED,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAU9D;AAgCD,wBAAgB,yCAAyC,CACvD,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAChB,MAAM,CAWR;AAED,wBAAgB,oCAAoC,CAClD,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACnC,OAAO,CAKT;AAED,wBAAgB,uCAAuC,CACrD,OAAO,EAAE,IAAI,CACX,uBAAuB,EACvB,oBAAoB,GAAG,mBAAmB,GAAG,WAAW,CACzD,EACD,iBAAiB,EAAE,MAAM,GACxB,MAAM,CAWR;AAED,wBAAgB,iDAAiD,CAC/D,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACpC,SAAS,EAAE,MAAM,GAChB,IAAI,CAON;AAED,wBAAgB,wCAAwC,CACtD,SAAS,EAAE,yBAAyB,GACnC,MAAM,CAER;AAED,wBAAgB,mCAAmC,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,CAIxE;AAED,wBAAgB,wCAAwC,CACtD,SAAS,EAAE,yBAAyB,GACnC,KAAK,CAIP;AAED,wBAAsB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAErD;AAED,wBAAsB,yBAAyB,CAC7C,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GAAG,UAAU,GAC5B,OAAO,CAAC,MAAM,CAAC,CAKjB;AAED,wBAAgB,gCAAgC,CAC9C,OAAO,EAAE,uBAAuB,GAC/B,uBAAuB,CA2BzB;AAED,wBAAgB,yCAAyC,CACvD,OAAO,EAAE,uBAAuB,EAChC,IAAI,EAAE,oBAAoB,EAC1B,KAAK,EAAE,MAAM,GACZ,uBAAuB,CA0BzB;AAED,wBAAgB,qCAAqC,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE3E;AAED,gGAAgG;AAChG,eAAO,MAAM,wCAAwC,wSACkP,CAAC;AAExS,eAAO,MAAM,uCAAuC,oIAC+E,CAAC;AAEpI,wBAAgB,mCAAmC,CACjD,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAKT;AAED,wBAAgB,uCAAuC,CACrD,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,OAAO,EAAE,MAAM,GAAG,MAAM,EACxB,IAAI,EAAE,oBAAoB,EAC1B,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,IAAI,CAgBN;AAED,wBAAgB,+CAA+C,CAC7D,OAAO,EAAE,MAAM,GAAG,MAAM,GACvB,KAAK,CAMP;AAED,wBAAgB,6CAA6C,CAC3D,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,OAAO,EAAE,MAAM,GAAG,MAAM,GACvB,IAAI,CAIN"}
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import * as fsp from "node:fs/promises";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { resolveBrowserWorkspaceElementRef } from "./browser-workspace-state.js";
|
|
4
|
+
const DEFAULT_TIMEOUT_MS = 12e3;
|
|
5
|
+
const DEFAULT_WAIT_INTERVAL_MS = 120;
|
|
6
|
+
const DEFAULT_WEB_PARTITION = "persist:eliza-browser";
|
|
7
|
+
const CONNECTOR_BROWSER_WORKSPACE_PARTITION_PREFIX = "persist:connector-";
|
|
8
|
+
const DESKTOP_BRIDGE_UNAVAILABLE_MESSAGE = "Eliza browser workspace desktop bridge is unavailable.";
|
|
9
|
+
const browserWorkspacePageFetch = globalThis.fetch.bind(globalThis);
|
|
10
|
+
function normalizeEnvValue(value) {
|
|
11
|
+
if (typeof value !== "string") {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
const trimmed = value.trim();
|
|
15
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
16
|
+
}
|
|
17
|
+
function normalizeBrowserWorkspaceText(value) {
|
|
18
|
+
return String(value ?? "").replace(/\s+/g, " ").trim();
|
|
19
|
+
}
|
|
20
|
+
function parseBrowserWorkspaceNumberLike(value) {
|
|
21
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
22
|
+
return value;
|
|
23
|
+
}
|
|
24
|
+
if (typeof value !== "string") {
|
|
25
|
+
return void 0;
|
|
26
|
+
}
|
|
27
|
+
const parsed = Number.parseFloat(value.trim());
|
|
28
|
+
return Number.isFinite(parsed) ? parsed : void 0;
|
|
29
|
+
}
|
|
30
|
+
function assertBrowserWorkspaceUrl(rawUrl) {
|
|
31
|
+
const trimmed = rawUrl.trim();
|
|
32
|
+
if (trimmed === "about:blank") {
|
|
33
|
+
return trimmed;
|
|
34
|
+
}
|
|
35
|
+
let parsed;
|
|
36
|
+
try {
|
|
37
|
+
parsed = new URL(trimmed);
|
|
38
|
+
} catch {
|
|
39
|
+
throw new Error(`browser workspace rejected invalid URL: ${rawUrl}`);
|
|
40
|
+
}
|
|
41
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
42
|
+
throw new Error(
|
|
43
|
+
`browser workspace only supports http/https URLs, got ${parsed.protocol}`
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
return parsed.toString();
|
|
47
|
+
}
|
|
48
|
+
function inferBrowserWorkspaceTitle(url) {
|
|
49
|
+
if (url === "about:blank") {
|
|
50
|
+
return "New Tab";
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
return new URL(url).hostname.replace(/^www\./, "") || "Eliza Browser";
|
|
54
|
+
} catch {
|
|
55
|
+
return "Eliza Browser";
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function normalizeConnectorBrowserWorkspaceSegment(value, fieldName) {
|
|
59
|
+
const normalized = value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").replace(/-{2,}/g, "-").slice(0, 64);
|
|
60
|
+
if (!normalized) {
|
|
61
|
+
throw new Error(`Eliza browser connector session requires ${fieldName}.`);
|
|
62
|
+
}
|
|
63
|
+
return normalized;
|
|
64
|
+
}
|
|
65
|
+
function hashConnectorBrowserWorkspacePartitionKey(provider, accountId) {
|
|
66
|
+
const input = `${provider.trim().toLowerCase()}\0${accountId.trim().toLowerCase()}`;
|
|
67
|
+
let hash = 2166136261;
|
|
68
|
+
for (let i = 0; i < input.length; i++) {
|
|
69
|
+
hash ^= input.charCodeAt(i);
|
|
70
|
+
hash = Math.imul(hash, 16777619) >>> 0;
|
|
71
|
+
}
|
|
72
|
+
return hash.toString(36).padStart(7, "0");
|
|
73
|
+
}
|
|
74
|
+
function resolveConnectorBrowserWorkspacePartition(provider, accountId) {
|
|
75
|
+
const providerSegment = normalizeConnectorBrowserWorkspaceSegment(
|
|
76
|
+
provider,
|
|
77
|
+
"provider"
|
|
78
|
+
);
|
|
79
|
+
const accountSegment = normalizeConnectorBrowserWorkspaceSegment(
|
|
80
|
+
accountId,
|
|
81
|
+
"accountId"
|
|
82
|
+
);
|
|
83
|
+
const suffix = hashConnectorBrowserWorkspacePartitionKey(provider, accountId);
|
|
84
|
+
return `${CONNECTOR_BROWSER_WORKSPACE_PARTITION_PREFIX}${providerSegment}-${accountSegment}-${suffix}`;
|
|
85
|
+
}
|
|
86
|
+
function isConnectorBrowserWorkspacePartition(partition) {
|
|
87
|
+
return (partition ?? "").trim().toLowerCase().startsWith(CONNECTOR_BROWSER_WORKSPACE_PARTITION_PREFIX);
|
|
88
|
+
}
|
|
89
|
+
function resolveBrowserWorkspaceCommandPartition(command, fallbackPartition) {
|
|
90
|
+
const explicitPartition = command.partition?.trim();
|
|
91
|
+
if (explicitPartition) {
|
|
92
|
+
return explicitPartition;
|
|
93
|
+
}
|
|
94
|
+
const provider = command.connectorProvider?.trim();
|
|
95
|
+
const accountId = command.connectorAccountId?.trim();
|
|
96
|
+
if (provider && accountId) {
|
|
97
|
+
return resolveConnectorBrowserWorkspacePartition(provider, accountId);
|
|
98
|
+
}
|
|
99
|
+
return fallbackPartition;
|
|
100
|
+
}
|
|
101
|
+
function assertBrowserWorkspaceConnectorSecretsNotExported(partition, operation) {
|
|
102
|
+
if (!isConnectorBrowserWorkspacePartition(partition)) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
throw new Error(
|
|
106
|
+
`Connector browser sessions do not allow raw cookie, token, storage, or state export (${operation}). Use the returned partition/profile/session handle instead.`
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
function createBrowserWorkspaceDesktopOnlyMessage(subaction) {
|
|
110
|
+
return `Eliza browser workspace ${subaction} is only available in the desktop app.`;
|
|
111
|
+
}
|
|
112
|
+
function createBrowserWorkspaceNotFoundError(tabId) {
|
|
113
|
+
return new Error(
|
|
114
|
+
`Browser workspace request failed (404): Tab ${tabId} was not found.`
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
function createBrowserWorkspaceCommandTargetError(subaction) {
|
|
118
|
+
return new Error(
|
|
119
|
+
`Eliza browser workspace ${subaction} requires a current tab. Open or show a tab first, or pass an explicit id.`
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
async function sleep(ms) {
|
|
123
|
+
await new Promise((resolve) => setTimeout(resolve, ms));
|
|
124
|
+
}
|
|
125
|
+
async function writeBrowserWorkspaceFile(filePath, contents) {
|
|
126
|
+
const resolved = path.resolve(filePath);
|
|
127
|
+
await fsp.mkdir(path.dirname(resolved), { recursive: true });
|
|
128
|
+
await fsp.writeFile(resolved, contents);
|
|
129
|
+
return resolved;
|
|
130
|
+
}
|
|
131
|
+
function normalizeBrowserWorkspaceCommand(command) {
|
|
132
|
+
const raw = command;
|
|
133
|
+
const normalizedSubaction = typeof raw.subaction === "string" ? raw.subaction.trim().toLowerCase() : typeof raw.operation === "string" ? raw.operation.trim().toLowerCase() : "";
|
|
134
|
+
const subaction = normalizedSubaction === "goto" ? "navigate" : normalizedSubaction === "read" ? "get" : command.subaction;
|
|
135
|
+
const timeoutMs = parseBrowserWorkspaceNumberLike(command.timeoutMs) ?? parseBrowserWorkspaceNumberLike(raw.ms) ?? parseBrowserWorkspaceNumberLike(raw.milliseconds);
|
|
136
|
+
return {
|
|
137
|
+
...command,
|
|
138
|
+
subaction,
|
|
139
|
+
timeoutMs,
|
|
140
|
+
steps: Array.isArray(command.steps) ? command.steps.map((step) => normalizeBrowserWorkspaceCommand(step)) : command.steps
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
function resolveBrowserWorkspaceCommandElementRefs(command, mode, tabId) {
|
|
144
|
+
const selector = command.selector?.trim();
|
|
145
|
+
if (!selector) {
|
|
146
|
+
return command;
|
|
147
|
+
}
|
|
148
|
+
const match = selector.match(/^(@e\d+)([\s\S]*)$/i);
|
|
149
|
+
if (!match?.[1]) {
|
|
150
|
+
return command;
|
|
151
|
+
}
|
|
152
|
+
const resolvedSelector = resolveBrowserWorkspaceElementRef(
|
|
153
|
+
mode,
|
|
154
|
+
tabId,
|
|
155
|
+
match[1]
|
|
156
|
+
);
|
|
157
|
+
if (!resolvedSelector) {
|
|
158
|
+
throw new Error(
|
|
159
|
+
`Unknown browser snapshot element ref ${match[1]}. Run snapshot or inspect again before reusing element refs.`
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
return {
|
|
163
|
+
...command,
|
|
164
|
+
selector: `${resolvedSelector}${match[2] ?? ""}`
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
function buildBrowserWorkspaceCssStringLiteral(value) {
|
|
168
|
+
return JSON.stringify(value);
|
|
169
|
+
}
|
|
170
|
+
const BROWSER_WORKSPACE_JSDOM_SCRIPT_FORBIDDEN = "Browser workspace arbitrary script execution is disabled in the JSDOM (web) backend because it runs in the Node.js agent process via unsafe eval patterns (GHSA-mhhr-9ph9-64j7). Use structured subactions (click, fill, get, wait on selector/url/text) or desktop browser workspace mode instead.";
|
|
171
|
+
const BROWSER_WORKSPACE_USER_SCRIPT_FORBIDDEN = "Browser workspace arbitrary user script is disabled (GHSA-mhhr-9ph9-64j7). Use structured browser workspace subactions instead.";
|
|
172
|
+
function isBrowserWorkspaceUserScriptAllowed(env = process.env) {
|
|
173
|
+
const flag = normalizeEnvValue(
|
|
174
|
+
env.ELIZA_BROWSER_WORKSPACE_ALLOW_USER_SCRIPT
|
|
175
|
+
)?.toLowerCase();
|
|
176
|
+
return flag === "1" || flag === "true" || flag === "yes";
|
|
177
|
+
}
|
|
178
|
+
function assertBrowserWorkspaceUserScriptAllowed(script, context, mode, env = process.env) {
|
|
179
|
+
if (!script?.trim()) {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
if (mode === "web") {
|
|
183
|
+
throw createBrowserWorkspaceJsdomScriptExecutionError(context);
|
|
184
|
+
}
|
|
185
|
+
if (!isBrowserWorkspaceUserScriptAllowed(env)) {
|
|
186
|
+
const suffix = context === "eval" ? "Eval subactions with a user `script` are disabled by default." : "Wait conditions with a user `script` are disabled by default.";
|
|
187
|
+
throw new Error(
|
|
188
|
+
`${BROWSER_WORKSPACE_USER_SCRIPT_FORBIDDEN} ${suffix} Set ELIZA_BROWSER_WORKSPACE_ALLOW_USER_SCRIPT=1 only on trusted single-user hosts.`
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
function createBrowserWorkspaceJsdomScriptExecutionError(context) {
|
|
193
|
+
const suffix = context === "eval" ? "Eval subactions are not supported on the web backend." : "Wait conditions with `script` are not supported on the web backend.";
|
|
194
|
+
return new Error(`${BROWSER_WORKSPACE_JSDOM_SCRIPT_FORBIDDEN} ${suffix}`);
|
|
195
|
+
}
|
|
196
|
+
function assertBrowserWorkspaceJsdomScriptNotRequested(script, context) {
|
|
197
|
+
if (script?.trim()) {
|
|
198
|
+
throw createBrowserWorkspaceJsdomScriptExecutionError(context);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
export {
|
|
202
|
+
BROWSER_WORKSPACE_JSDOM_SCRIPT_FORBIDDEN,
|
|
203
|
+
BROWSER_WORKSPACE_USER_SCRIPT_FORBIDDEN,
|
|
204
|
+
CONNECTOR_BROWSER_WORKSPACE_PARTITION_PREFIX,
|
|
205
|
+
DEFAULT_TIMEOUT_MS,
|
|
206
|
+
DEFAULT_WAIT_INTERVAL_MS,
|
|
207
|
+
DEFAULT_WEB_PARTITION,
|
|
208
|
+
DESKTOP_BRIDGE_UNAVAILABLE_MESSAGE,
|
|
209
|
+
assertBrowserWorkspaceConnectorSecretsNotExported,
|
|
210
|
+
assertBrowserWorkspaceJsdomScriptNotRequested,
|
|
211
|
+
assertBrowserWorkspaceUrl,
|
|
212
|
+
assertBrowserWorkspaceUserScriptAllowed,
|
|
213
|
+
browserWorkspacePageFetch,
|
|
214
|
+
buildBrowserWorkspaceCssStringLiteral,
|
|
215
|
+
createBrowserWorkspaceCommandTargetError,
|
|
216
|
+
createBrowserWorkspaceDesktopOnlyMessage,
|
|
217
|
+
createBrowserWorkspaceJsdomScriptExecutionError,
|
|
218
|
+
createBrowserWorkspaceNotFoundError,
|
|
219
|
+
inferBrowserWorkspaceTitle,
|
|
220
|
+
isBrowserWorkspaceUserScriptAllowed,
|
|
221
|
+
isConnectorBrowserWorkspacePartition,
|
|
222
|
+
normalizeBrowserWorkspaceCommand,
|
|
223
|
+
normalizeBrowserWorkspaceText,
|
|
224
|
+
normalizeEnvValue,
|
|
225
|
+
parseBrowserWorkspaceNumberLike,
|
|
226
|
+
resolveBrowserWorkspaceCommandElementRefs,
|
|
227
|
+
resolveBrowserWorkspaceCommandPartition,
|
|
228
|
+
resolveConnectorBrowserWorkspacePartition,
|
|
229
|
+
sleep,
|
|
230
|
+
writeBrowserWorkspaceFile
|
|
231
|
+
};
|
|
232
|
+
//# sourceMappingURL=browser-workspace-helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/workspace/browser-workspace-helpers.ts"],"sourcesContent":["import * as fsp from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { resolveBrowserWorkspaceElementRef } from \"./browser-workspace-state.js\";\nimport type {\n BrowserWorkspaceCommand,\n BrowserWorkspaceMode,\n BrowserWorkspaceSubaction,\n} from \"./browser-workspace-types.js\";\n\nexport const DEFAULT_TIMEOUT_MS = 12_000;\nexport const DEFAULT_WAIT_INTERVAL_MS = 120;\nexport const DEFAULT_WEB_PARTITION = \"persist:eliza-browser\";\nexport const CONNECTOR_BROWSER_WORKSPACE_PARTITION_PREFIX =\n \"persist:connector-\";\nexport const DESKTOP_BRIDGE_UNAVAILABLE_MESSAGE =\n \"Eliza browser workspace desktop bridge is unavailable.\";\nexport const browserWorkspacePageFetch = globalThis.fetch.bind(globalThis);\n\nexport function normalizeEnvValue(value: string | undefined): string | null {\n if (typeof value !== \"string\") {\n return null;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : null;\n}\n\nexport function normalizeBrowserWorkspaceText(value: unknown): string {\n return String(value ?? \"\")\n .replace(/\\s+/g, \" \")\n .trim();\n}\n\nexport function parseBrowserWorkspaceNumberLike(\n value: unknown,\n): number | undefined {\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return value;\n }\n if (typeof value !== \"string\") {\n return undefined;\n }\n const parsed = Number.parseFloat(value.trim());\n return Number.isFinite(parsed) ? parsed : undefined;\n}\n\nexport function assertBrowserWorkspaceUrl(rawUrl: string): string {\n const trimmed = rawUrl.trim();\n if (trimmed === \"about:blank\") {\n return trimmed;\n }\n\n let parsed: URL;\n try {\n parsed = new URL(trimmed);\n } catch {\n throw new Error(`browser workspace rejected invalid URL: ${rawUrl}`);\n }\n\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n throw new Error(\n `browser workspace only supports http/https URLs, got ${parsed.protocol}`,\n );\n }\n\n return parsed.toString();\n}\n\nexport function inferBrowserWorkspaceTitle(url: string): string {\n if (url === \"about:blank\") {\n return \"New Tab\";\n }\n\n try {\n return new URL(url).hostname.replace(/^www\\./, \"\") || \"Eliza Browser\";\n } catch {\n return \"Eliza Browser\";\n }\n}\n\nfunction normalizeConnectorBrowserWorkspaceSegment(\n value: string,\n fieldName: string,\n): string {\n const normalized = value\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .replace(/-{2,}/g, \"-\")\n .slice(0, 64);\n if (!normalized) {\n throw new Error(`Eliza browser connector session requires ${fieldName}.`);\n }\n return normalized;\n}\n\nfunction hashConnectorBrowserWorkspacePartitionKey(\n provider: string,\n accountId: string,\n): string {\n const input = `${provider.trim().toLowerCase()}\\0${accountId.trim().toLowerCase()}`;\n let hash = 0x811c9dc5;\n for (let i = 0; i < input.length; i++) {\n hash ^= input.charCodeAt(i);\n hash = Math.imul(hash, 0x01000193) >>> 0;\n }\n return hash.toString(36).padStart(7, \"0\");\n}\n\nexport function resolveConnectorBrowserWorkspacePartition(\n provider: string,\n accountId: string,\n): string {\n const providerSegment = normalizeConnectorBrowserWorkspaceSegment(\n provider,\n \"provider\",\n );\n const accountSegment = normalizeConnectorBrowserWorkspaceSegment(\n accountId,\n \"accountId\",\n );\n const suffix = hashConnectorBrowserWorkspacePartitionKey(provider, accountId);\n return `${CONNECTOR_BROWSER_WORKSPACE_PARTITION_PREFIX}${providerSegment}-${accountSegment}-${suffix}`;\n}\n\nexport function isConnectorBrowserWorkspacePartition(\n partition: string | null | undefined,\n): boolean {\n return (partition ?? \"\")\n .trim()\n .toLowerCase()\n .startsWith(CONNECTOR_BROWSER_WORKSPACE_PARTITION_PREFIX);\n}\n\nexport function resolveBrowserWorkspaceCommandPartition(\n command: Pick<\n BrowserWorkspaceCommand,\n \"connectorAccountId\" | \"connectorProvider\" | \"partition\"\n >,\n fallbackPartition: string,\n): string {\n const explicitPartition = command.partition?.trim();\n if (explicitPartition) {\n return explicitPartition;\n }\n const provider = command.connectorProvider?.trim();\n const accountId = command.connectorAccountId?.trim();\n if (provider && accountId) {\n return resolveConnectorBrowserWorkspacePartition(provider, accountId);\n }\n return fallbackPartition;\n}\n\nexport function assertBrowserWorkspaceConnectorSecretsNotExported(\n partition: string | null | undefined,\n operation: string,\n): void {\n if (!isConnectorBrowserWorkspacePartition(partition)) {\n return;\n }\n throw new Error(\n `Connector browser sessions do not allow raw cookie, token, storage, or state export (${operation}). Use the returned partition/profile/session handle instead.`,\n );\n}\n\nexport function createBrowserWorkspaceDesktopOnlyMessage(\n subaction: BrowserWorkspaceSubaction,\n): string {\n return `Eliza browser workspace ${subaction} is only available in the desktop app.`;\n}\n\nexport function createBrowserWorkspaceNotFoundError(tabId: string): Error {\n return new Error(\n `Browser workspace request failed (404): Tab ${tabId} was not found.`,\n );\n}\n\nexport function createBrowserWorkspaceCommandTargetError(\n subaction: BrowserWorkspaceSubaction,\n): Error {\n return new Error(\n `Eliza browser workspace ${subaction} requires a current tab. Open or show a tab first, or pass an explicit id.`,\n );\n}\n\nexport async function sleep(ms: number): Promise<void> {\n await new Promise<void>((resolve) => setTimeout(resolve, ms));\n}\n\nexport async function writeBrowserWorkspaceFile(\n filePath: string,\n contents: string | Uint8Array,\n): Promise<string> {\n const resolved = path.resolve(filePath);\n await fsp.mkdir(path.dirname(resolved), { recursive: true });\n await fsp.writeFile(resolved, contents);\n return resolved;\n}\n\nexport function normalizeBrowserWorkspaceCommand(\n command: BrowserWorkspaceCommand,\n): BrowserWorkspaceCommand {\n const raw = command as BrowserWorkspaceCommand & Record<string, unknown>;\n const normalizedSubaction =\n typeof raw.subaction === \"string\"\n ? raw.subaction.trim().toLowerCase()\n : typeof raw.operation === \"string\"\n ? raw.operation.trim().toLowerCase()\n : \"\";\n const subaction =\n normalizedSubaction === \"goto\"\n ? \"navigate\"\n : normalizedSubaction === \"read\"\n ? \"get\"\n : command.subaction;\n const timeoutMs =\n parseBrowserWorkspaceNumberLike(command.timeoutMs) ??\n parseBrowserWorkspaceNumberLike(raw.ms) ??\n parseBrowserWorkspaceNumberLike(raw.milliseconds);\n\n return {\n ...command,\n subaction,\n timeoutMs,\n steps: Array.isArray(command.steps)\n ? command.steps.map((step) => normalizeBrowserWorkspaceCommand(step))\n : command.steps,\n };\n}\n\nexport function resolveBrowserWorkspaceCommandElementRefs(\n command: BrowserWorkspaceCommand,\n mode: BrowserWorkspaceMode,\n tabId: string,\n): BrowserWorkspaceCommand {\n const selector = command.selector?.trim();\n if (!selector) {\n return command;\n }\n\n const match = selector.match(/^(@e\\d+)([\\s\\S]*)$/i);\n if (!match?.[1]) {\n return command;\n }\n\n const resolvedSelector = resolveBrowserWorkspaceElementRef(\n mode,\n tabId,\n match[1],\n );\n if (!resolvedSelector) {\n throw new Error(\n `Unknown browser snapshot element ref ${match[1]}. Run snapshot or inspect again before reusing element refs.`,\n );\n }\n\n return {\n ...command,\n selector: `${resolvedSelector}${match[2] ?? \"\"}`,\n };\n}\n\nexport function buildBrowserWorkspaceCssStringLiteral(value: string): string {\n return JSON.stringify(value);\n}\n\n/** GHSA-mhhr-9ph9-64j7 / elizaOS/eliza#6767 — arbitrary script must not run in Node (JSDOM). */\nexport const BROWSER_WORKSPACE_JSDOM_SCRIPT_FORBIDDEN =\n \"Browser workspace arbitrary script execution is disabled in the JSDOM (web) backend because it runs in the Node.js agent process via unsafe eval patterns (GHSA-mhhr-9ph9-64j7). Use structured subactions (click, fill, get, wait on selector/url/text) or desktop browser workspace mode instead.\";\n\nexport const BROWSER_WORKSPACE_USER_SCRIPT_FORBIDDEN =\n \"Browser workspace arbitrary user script is disabled (GHSA-mhhr-9ph9-64j7). Use structured browser workspace subactions instead.\";\n\nexport function isBrowserWorkspaceUserScriptAllowed(\n env: NodeJS.ProcessEnv = process.env,\n): boolean {\n const flag = normalizeEnvValue(\n env.ELIZA_BROWSER_WORKSPACE_ALLOW_USER_SCRIPT,\n )?.toLowerCase();\n return flag === \"1\" || flag === \"true\" || flag === \"yes\";\n}\n\nexport function assertBrowserWorkspaceUserScriptAllowed(\n script: string | undefined,\n context: \"eval\" | \"wait\",\n mode: BrowserWorkspaceMode,\n env: NodeJS.ProcessEnv = process.env,\n): void {\n if (!script?.trim()) {\n return;\n }\n if (mode === \"web\") {\n throw createBrowserWorkspaceJsdomScriptExecutionError(context);\n }\n if (!isBrowserWorkspaceUserScriptAllowed(env)) {\n const suffix =\n context === \"eval\"\n ? \"Eval subactions with a user `script` are disabled by default.\"\n : \"Wait conditions with a user `script` are disabled by default.\";\n throw new Error(\n `${BROWSER_WORKSPACE_USER_SCRIPT_FORBIDDEN} ${suffix} Set ELIZA_BROWSER_WORKSPACE_ALLOW_USER_SCRIPT=1 only on trusted single-user hosts.`,\n );\n }\n}\n\nexport function createBrowserWorkspaceJsdomScriptExecutionError(\n context: \"eval\" | \"wait\",\n): Error {\n const suffix =\n context === \"eval\"\n ? \"Eval subactions are not supported on the web backend.\"\n : \"Wait conditions with `script` are not supported on the web backend.\";\n return new Error(`${BROWSER_WORKSPACE_JSDOM_SCRIPT_FORBIDDEN} ${suffix}`);\n}\n\nexport function assertBrowserWorkspaceJsdomScriptNotRequested(\n script: string | undefined,\n context: \"eval\" | \"wait\",\n): void {\n if (script?.trim()) {\n throw createBrowserWorkspaceJsdomScriptExecutionError(context);\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { JSDOM } from "jsdom";
|
|
2
|
+
import type { BrowserWorkspaceRuntimeState, WebBrowserWorkspaceTabState } from "./browser-workspace-types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Locate jsdom's package.json on disk, then resolve its declared entry file from there.
|
|
5
|
+
* Vitest workers run on Node; Node cannot resolve `jsdom` from workspace roots when
|
|
6
|
+
* Bun hoists deps under node_modules/.bun, but requiring jsdom from its own package
|
|
7
|
+
* directory still works.
|
|
8
|
+
*/
|
|
9
|
+
export declare function findJsdomPackageJsonPath(): string;
|
|
10
|
+
/** Lazy-load jsdom so importing this module does not require jsdom at parse time (Vitest / server tests). */
|
|
11
|
+
export declare function getJSDOMClass(): typeof import("jsdom").JSDOM;
|
|
12
|
+
export declare function createEmptyWebBrowserWorkspaceDom(url: string): JSDOM;
|
|
13
|
+
export declare function applyBrowserWorkspaceDomSettings(dom: JSDOM, state: BrowserWorkspaceRuntimeState): void;
|
|
14
|
+
export declare function installBrowserWorkspaceWebRuntime(tab: WebBrowserWorkspaceTabState, dom: JSDOM): void;
|
|
15
|
+
export declare function ensureBrowserWorkspaceDom(tab: WebBrowserWorkspaceTabState): JSDOM;
|
|
16
|
+
//# sourceMappingURL=browser-workspace-jsdom.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-workspace-jsdom.d.ts","sourceRoot":"","sources":["../../src/workspace/browser-workspace-jsdom.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AASnC,OAAO,KAAK,EACV,4BAA4B,EAC5B,2BAA2B,EAC5B,MAAM,8BAA8B,CAAC;AAItC;;;;;GAKG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CA2CjD;AAED,6GAA6G;AAC7G,wBAAgB,aAAa,IAAI,cAAc,OAAO,EAAE,KAAK,CAc5D;AAED,wBAAgB,iCAAiC,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAQpE;AAED,wBAAgB,gCAAgC,CAC9C,GAAG,EAAE,KAAK,EACV,KAAK,EAAE,4BAA4B,GAClC,IAAI,CA8EN;AAED,wBAAgB,iCAAiC,CAC/C,GAAG,EAAE,2BAA2B,EAChC,GAAG,EAAE,KAAK,GACT,IAAI,CAqFN;AAED,wBAAgB,yBAAyB,CACvC,GAAG,EAAE,2BAA2B,GAC/B,KAAK,CAQP"}
|