@elizaos/plugin-browser 2.0.0-beta.1 → 2.0.3-beta.3
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 +106 -64
- package/dist/actions/browser-autofill-login.d.ts.map +1 -1
- package/dist/actions/browser-autofill-login.js.map +1 -1
- package/dist/actions/browser.d.ts +5 -6
- package/dist/actions/browser.d.ts.map +1 -1
- package/dist/actions/browser.js +312 -60
- package/dist/actions/browser.js.map +1 -1
- package/dist/actions/manage-browser-bridge.d.ts.map +1 -1
- package/dist/actions/manage-browser-bridge.js +10 -14
- package/dist/actions/manage-browser-bridge.js.map +1 -1
- package/dist/actions/wait-for-url-predicate.d.ts +34 -0
- package/dist/actions/wait-for-url-predicate.d.ts.map +1 -0
- package/dist/actions/wait-for-url-predicate.js +33 -0
- package/dist/actions/wait-for-url-predicate.js.map +1 -0
- package/dist/actions/wait-for-url.d.ts +64 -0
- package/dist/actions/wait-for-url.d.ts.map +1 -0
- package/dist/actions/wait-for-url.js +89 -0
- package/dist/actions/wait-for-url.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 +22 -4
- package/dist/browser-service.d.ts.map +1 -1
- package/dist/browser-service.js +63 -15
- package/dist/browser-service.js.map +1 -1
- 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/index.d.ts +12 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +66 -12
- package/dist/index.js.map +1 -1
- 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.map +1 -1
- package/dist/packaging.js +2 -0
- package/dist/packaging.js.map +1 -1
- package/dist/parity/browser-matrix.d.ts +45 -0
- package/dist/parity/browser-matrix.d.ts.map +1 -0
- package/dist/parity/browser-matrix.js +361 -0
- package/dist/parity/browser-matrix.js.map +1 -0
- package/dist/parity/index.d.ts +5 -0
- package/dist/parity/index.d.ts.map +1 -0
- package/dist/parity/index.js +13 -0
- package/dist/parity/index.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.map +1 -1
- package/dist/plugin.js +8 -4
- package/dist/plugin.js.map +1 -1
- package/dist/providers/workspace.d.ts +1 -1
- package/dist/providers/workspace.js.map +1 -1
- package/dist/routes/bridge.d.ts.map +1 -1
- package/dist/routes/bridge.js +63 -14
- package/dist/routes/bridge.js.map +1 -1
- package/dist/routes/workspace-setup.d.ts.map +1 -1
- package/dist/routes/workspace-setup.js +1 -1
- package/dist/routes/workspace-setup.js.map +1 -1
- package/dist/routes/workspace.d.ts +1 -2
- package/dist/routes/workspace.d.ts.map +1 -1
- package/dist/routes/workspace.js +104 -4
- package/dist/routes/workspace.js.map +1 -1
- package/dist/schema.d.ts +2 -2
- package/dist/schema.js.map +1 -1
- package/dist/service.d.ts +1 -1
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js.map +1 -1
- package/dist/targets/bridge-target.d.ts +1 -1
- package/dist/targets/bridge-target.d.ts.map +1 -1
- package/dist/targets/bridge-target.js.map +1 -1
- 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 +1 -1
- package/dist/workspace/browser-capture.d.ts.map +1 -1
- package/dist/workspace/browser-capture.js +33 -1
- package/dist/workspace/browser-capture.js.map +1 -1
- package/dist/workspace/browser-workspace-desktop.d.ts +1 -1
- package/dist/workspace/browser-workspace-desktop.d.ts.map +1 -1
- package/dist/workspace/browser-workspace-desktop.js +66 -30
- package/dist/workspace/browser-workspace-desktop.js.map +1 -1
- package/dist/workspace/browser-workspace-errors.d.ts +62 -0
- package/dist/workspace/browser-workspace-errors.d.ts.map +1 -0
- package/dist/workspace/browser-workspace-errors.js +69 -0
- package/dist/workspace/browser-workspace-errors.js.map +1 -0
- package/dist/workspace/browser-workspace-forms.d.ts.map +1 -1
- package/dist/workspace/browser-workspace-forms.js +1 -1
- package/dist/workspace/browser-workspace-forms.js.map +1 -1
- package/dist/workspace/browser-workspace-helpers.d.ts +7 -0
- package/dist/workspace/browser-workspace-helpers.d.ts.map +1 -1
- package/dist/workspace/browser-workspace-helpers.js +64 -6
- package/dist/workspace/browser-workspace-helpers.js.map +1 -1
- package/dist/workspace/browser-workspace-network.d.ts +1 -1
- package/dist/workspace/browser-workspace-network.d.ts.map +1 -1
- package/dist/workspace/browser-workspace-types.d.ts +15 -0
- package/dist/workspace/browser-workspace-types.d.ts.map +1 -1
- package/dist/workspace/browser-workspace-types.js.map +1 -1
- package/dist/workspace/browser-workspace-web.d.ts.map +1 -1
- package/dist/workspace/browser-workspace-web.js +34 -93
- package/dist/workspace/browser-workspace-web.js.map +1 -1
- package/dist/workspace/browser-workspace.d.ts +1 -1
- package/dist/workspace/browser-workspace.d.ts.map +1 -1
- package/dist/workspace/browser-workspace.js +9 -4
- package/dist/workspace/browser-workspace.js.map +1 -1
- package/dist/workspace/index.d.ts +1 -0
- package/dist/workspace/index.d.ts.map +1 -1
- package/dist/workspace/index.js +1 -0
- package/dist/workspace/index.js.map +1 -1
- package/package.json +29 -7
- package/registry-entry.json +75 -0
- package/dist/actions/browser-autofill-login.d.js +0 -1
- package/dist/actions/browser-autofill-login.d.js.map +0 -1
- package/dist/actions/browser.d.js +0 -1
- package/dist/actions/browser.d.js.map +0 -1
- package/dist/actions/manage-browser-bridge.d.js +0 -1
- package/dist/actions/manage-browser-bridge.d.js.map +0 -1
- package/dist/ambient-jsdom.d.js +0 -1
- package/dist/ambient-jsdom.d.js.map +0 -1
- package/dist/browser-service.d.js +0 -1
- package/dist/browser-service.d.js.map +0 -1
- package/dist/contracts.d.js +0 -1
- package/dist/contracts.d.js.map +0 -1
- package/dist/index.d.js +0 -21
- package/dist/index.d.js.map +0 -1
- package/dist/lifeops-session-contracts.d.js +0 -1
- package/dist/lifeops-session-contracts.d.js.map +0 -1
- package/dist/packaging.d.js +0 -1
- package/dist/packaging.d.js.map +0 -1
- package/dist/plugin.d.js +0 -1
- package/dist/plugin.d.js.map +0 -1
- package/dist/providers/workspace.d.js +0 -1
- package/dist/providers/workspace.d.js.map +0 -1
- package/dist/routes/bridge.d.js +0 -1
- package/dist/routes/bridge.d.js.map +0 -1
- package/dist/routes/workspace-account-gate.d.js +0 -1
- package/dist/routes/workspace-account-gate.d.js.map +0 -1
- package/dist/routes/workspace-setup.d.js +0 -1
- package/dist/routes/workspace-setup.d.js.map +0 -1
- package/dist/routes/workspace.d.js +0 -1
- package/dist/routes/workspace.d.js.map +0 -1
- package/dist/schema.d.js +0 -1
- package/dist/schema.d.js.map +0 -1
- package/dist/service.d.js +0 -1
- package/dist/service.d.js.map +0 -1
- package/dist/targets/bridge-target.d.js +0 -1
- package/dist/targets/bridge-target.d.js.map +0 -1
- package/dist/workspace/browser-capture.d.js +0 -1
- package/dist/workspace/browser-capture.d.js.map +0 -1
- package/dist/workspace/browser-workspace-desktop.d.js +0 -1
- package/dist/workspace/browser-workspace-desktop.d.js.map +0 -1
- package/dist/workspace/browser-workspace-elements.d.js +0 -1
- package/dist/workspace/browser-workspace-elements.d.js.map +0 -1
- package/dist/workspace/browser-workspace-forms.d.js +0 -1
- package/dist/workspace/browser-workspace-forms.d.js.map +0 -1
- package/dist/workspace/browser-workspace-helpers.d.js +0 -1
- package/dist/workspace/browser-workspace-helpers.d.js.map +0 -1
- package/dist/workspace/browser-workspace-jsdom.d.js +0 -1
- package/dist/workspace/browser-workspace-jsdom.d.js.map +0 -1
- package/dist/workspace/browser-workspace-network.d.js +0 -1
- package/dist/workspace/browser-workspace-network.d.js.map +0 -1
- package/dist/workspace/browser-workspace-snapshots.d.js +0 -1
- package/dist/workspace/browser-workspace-snapshots.d.js.map +0 -1
- package/dist/workspace/browser-workspace-state.d.js +0 -1
- package/dist/workspace/browser-workspace-state.d.js.map +0 -1
- package/dist/workspace/browser-workspace-types.d.js +0 -1
- package/dist/workspace/browser-workspace-types.d.js.map +0 -1
- package/dist/workspace/browser-workspace-web.d.js +0 -1
- package/dist/workspace/browser-workspace-web.d.js.map +0 -1
- package/dist/workspace/browser-workspace.d.js +0 -11
- package/dist/workspace/browser-workspace.d.js.map +0 -1
- package/dist/workspace/index.d.js +0 -3
- package/dist/workspace/index.d.js.map +0 -1
package/dist/actions/browser.js
CHANGED
|
@@ -2,11 +2,15 @@ import { logger } from "@elizaos/core";
|
|
|
2
2
|
import {
|
|
3
3
|
BROWSER_SERVICE_TYPE
|
|
4
4
|
} from "../browser-service.js";
|
|
5
|
-
import { executeBrowserAutofillLogin } from "./browser-autofill-login.js";
|
|
6
5
|
import {
|
|
7
6
|
executeBrowserWorkspaceCommand,
|
|
8
7
|
getBrowserWorkspaceMode
|
|
9
8
|
} from "../workspace/browser-workspace.js";
|
|
9
|
+
import {
|
|
10
|
+
WAIT_FOR_URL_DEFAULT_POLL_INTERVAL_MS,
|
|
11
|
+
WAIT_FOR_URL_DEFAULT_TIMEOUT_MS,
|
|
12
|
+
waitForUrl
|
|
13
|
+
} from "./wait-for-url.js";
|
|
10
14
|
function getMessageText(message) {
|
|
11
15
|
const content = message?.content;
|
|
12
16
|
if (typeof content === "string") {
|
|
@@ -19,10 +23,14 @@ function extractFirstUrl(value) {
|
|
|
19
23
|
return match?.[0] ?? null;
|
|
20
24
|
}
|
|
21
25
|
function inferBrowserSubaction(params, messageText) {
|
|
22
|
-
|
|
26
|
+
const normalizedAction = normalizeBrowserAction(params?.action);
|
|
27
|
+
if (normalizedAction === "autofill-login" || params?.subaction === "autofill-login") {
|
|
23
28
|
return "autofill-login";
|
|
24
29
|
}
|
|
25
|
-
|
|
30
|
+
if (normalizedAction === "wait-for-url" || params?.subaction === "wait-for-url") {
|
|
31
|
+
return "wait-for-url";
|
|
32
|
+
}
|
|
33
|
+
const legacySubaction = normalizeLegacyBrowserAction(normalizedAction);
|
|
26
34
|
if (legacySubaction) {
|
|
27
35
|
return legacySubaction;
|
|
28
36
|
}
|
|
@@ -44,8 +52,32 @@ function inferBrowserSubaction(params, messageText) {
|
|
|
44
52
|
}
|
|
45
53
|
return "state";
|
|
46
54
|
}
|
|
47
|
-
function
|
|
55
|
+
function normalizeBrowserAction(action) {
|
|
48
56
|
switch (action) {
|
|
57
|
+
case "realistic_click":
|
|
58
|
+
return "realistic-click";
|
|
59
|
+
case "realistic_fill":
|
|
60
|
+
return "realistic-fill";
|
|
61
|
+
case "realistic_type":
|
|
62
|
+
return "realistic-type";
|
|
63
|
+
case "realistic_press":
|
|
64
|
+
return "realistic-press";
|
|
65
|
+
case "cursor_move":
|
|
66
|
+
return "cursor-move";
|
|
67
|
+
case "cursor_hide":
|
|
68
|
+
return "cursor-hide";
|
|
69
|
+
case "autofill_login":
|
|
70
|
+
return "autofill-login";
|
|
71
|
+
case "wait_for_url":
|
|
72
|
+
case "wait-for-url":
|
|
73
|
+
return "wait-for-url";
|
|
74
|
+
default:
|
|
75
|
+
return action;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function normalizeLegacyBrowserAction(action) {
|
|
79
|
+
const normalizedAction = normalizeBrowserAction(action);
|
|
80
|
+
switch (normalizedAction) {
|
|
49
81
|
case "info":
|
|
50
82
|
case "context":
|
|
51
83
|
case "get_context":
|
|
@@ -56,15 +88,19 @@ function normalizeLegacyBrowserAction(action) {
|
|
|
56
88
|
case "switch_tab":
|
|
57
89
|
return "tab";
|
|
58
90
|
case "autofill-login":
|
|
91
|
+
case "wait-for-url":
|
|
59
92
|
return void 0;
|
|
60
93
|
case void 0:
|
|
61
94
|
return void 0;
|
|
62
95
|
default:
|
|
63
|
-
return
|
|
96
|
+
return isWorkspaceSubaction(normalizedAction) ? normalizedAction : void 0;
|
|
64
97
|
}
|
|
65
98
|
}
|
|
99
|
+
function isWorkspaceSubaction(action) {
|
|
100
|
+
return action === "back" || action === "click" || action === "close" || action === "forward" || action === "get" || action === "hide" || action === "navigate" || action === "open" || action === "press" || action === "reload" || action === "screenshot" || action === "show" || action === "snapshot" || action === "state" || action === "tab" || action === "type" || action === "wait" || action === "realistic-click" || action === "realistic-fill" || action === "realistic-type" || action === "realistic-press" || action === "cursor-move" || action === "cursor-hide";
|
|
101
|
+
}
|
|
66
102
|
function normalizeLegacyTabAction(action) {
|
|
67
|
-
switch (action) {
|
|
103
|
+
switch (normalizeBrowserAction(action)) {
|
|
68
104
|
case "list_tabs":
|
|
69
105
|
return "list";
|
|
70
106
|
case "open_tab":
|
|
@@ -105,6 +141,193 @@ ${serialized}`;
|
|
|
105
141
|
}
|
|
106
142
|
return `Browser ${command.subaction} completed in ${result.mode} mode.`;
|
|
107
143
|
}
|
|
144
|
+
function browserProgressRationale(command, params, messageText) {
|
|
145
|
+
const explicit = params?.rationale?.trim();
|
|
146
|
+
if (explicit) return explicit;
|
|
147
|
+
switch (command.subaction) {
|
|
148
|
+
case "open":
|
|
149
|
+
case "navigate":
|
|
150
|
+
return command.url ? `open ${command.url}` : "open requested page";
|
|
151
|
+
case "click":
|
|
152
|
+
case "realistic-click":
|
|
153
|
+
return command.selector ? `click ${command.selector}` : "click requested target";
|
|
154
|
+
case "type":
|
|
155
|
+
case "realistic-fill":
|
|
156
|
+
case "realistic-type":
|
|
157
|
+
return command.selector ? `fill ${command.selector}` : "type requested text";
|
|
158
|
+
case "press":
|
|
159
|
+
case "realistic-press":
|
|
160
|
+
return command.key ? `press ${command.key}` : "press requested key";
|
|
161
|
+
case "tab":
|
|
162
|
+
return command.tabAction ? `${command.tabAction} browser tab` : "manage browser tabs";
|
|
163
|
+
case "wait":
|
|
164
|
+
return command.selector ? `wait for ${command.selector}` : "wait for browser state";
|
|
165
|
+
case "state":
|
|
166
|
+
return messageText.trim() || "read browser state";
|
|
167
|
+
default:
|
|
168
|
+
return `run browser ${command.subaction}`;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
function buildBrowserStepProgressContent(command, params, messageText, success, error) {
|
|
172
|
+
const rationale = error ? `failed: ${error}` : browserProgressRationale(command, params, messageText);
|
|
173
|
+
return {
|
|
174
|
+
text: `Step 1: ${command.subaction} \u2014 ${rationale}`,
|
|
175
|
+
source: "action_progress",
|
|
176
|
+
merge: "replace",
|
|
177
|
+
metadata: {
|
|
178
|
+
transient: true,
|
|
179
|
+
compactProgress: true,
|
|
180
|
+
progress: {
|
|
181
|
+
source: "browser",
|
|
182
|
+
actionName: "BROWSER",
|
|
183
|
+
step: 1,
|
|
184
|
+
kind: command.subaction,
|
|
185
|
+
rationale,
|
|
186
|
+
success,
|
|
187
|
+
error
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
async function emitBrowserStepProgress(callback, command, params, messageText, success, error) {
|
|
193
|
+
if (params?.streamProgress !== true || !callback) return;
|
|
194
|
+
try {
|
|
195
|
+
await callback(
|
|
196
|
+
buildBrowserStepProgressContent(
|
|
197
|
+
command,
|
|
198
|
+
params,
|
|
199
|
+
messageText,
|
|
200
|
+
success,
|
|
201
|
+
error
|
|
202
|
+
),
|
|
203
|
+
"BROWSER"
|
|
204
|
+
);
|
|
205
|
+
} catch (callbackError) {
|
|
206
|
+
logger.warn(
|
|
207
|
+
{
|
|
208
|
+
src: "plugin:browser",
|
|
209
|
+
action: command.subaction,
|
|
210
|
+
error: callbackError instanceof Error ? callbackError.message : String(callbackError)
|
|
211
|
+
},
|
|
212
|
+
"Failed to emit browser progress callback"
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
function currentUrlFromResult(result) {
|
|
217
|
+
if (result.tab?.url) {
|
|
218
|
+
return result.tab.url;
|
|
219
|
+
}
|
|
220
|
+
if (typeof result.value === "string" && result.value.trim()) {
|
|
221
|
+
return result.value.trim();
|
|
222
|
+
}
|
|
223
|
+
if (Array.isArray(result.tabs)) {
|
|
224
|
+
const visible = result.tabs.find((tab) => tab.visible) ?? result.tabs[0];
|
|
225
|
+
if (visible?.url) {
|
|
226
|
+
return visible.url;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
async function readCurrentBrowserUrl(browserService, target, tabId) {
|
|
232
|
+
const run = async (command) => browserService ? browserService.execute(command, target) : executeBrowserWorkspaceCommand(command);
|
|
233
|
+
try {
|
|
234
|
+
const got = await run({
|
|
235
|
+
subaction: "get",
|
|
236
|
+
getMode: "url",
|
|
237
|
+
id: tabId
|
|
238
|
+
});
|
|
239
|
+
const url = currentUrlFromResult(got);
|
|
240
|
+
if (url) {
|
|
241
|
+
return url;
|
|
242
|
+
}
|
|
243
|
+
} catch (error) {
|
|
244
|
+
logger.debug(
|
|
245
|
+
`[BROWSER] wait_for_url get-url poll failed, falling back to state: ${error instanceof Error ? error.message : String(error)}`
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
try {
|
|
249
|
+
const state = await run({ subaction: "state", id: tabId });
|
|
250
|
+
return currentUrlFromResult(state);
|
|
251
|
+
} catch (error) {
|
|
252
|
+
logger.debug(
|
|
253
|
+
`[BROWSER] wait_for_url state poll could not read URL: ${error instanceof Error ? error.message : String(error)}`
|
|
254
|
+
);
|
|
255
|
+
return null;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
async function executeBrowserWaitForUrl(runtime, params, messageText, callback) {
|
|
259
|
+
const pattern = (params?.pattern ?? "").trim();
|
|
260
|
+
if (!pattern) {
|
|
261
|
+
const text = "wait_for_url needs a `pattern` (substring or regex) to watch for.";
|
|
262
|
+
logger.warn(`[BROWSER] ${text}`);
|
|
263
|
+
return {
|
|
264
|
+
text,
|
|
265
|
+
success: false,
|
|
266
|
+
values: { success: false, error: "BROWSER_WAIT_FOR_URL_NO_PATTERN" },
|
|
267
|
+
data: { actionName: "BROWSER", subaction: "wait_for_url" }
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
const browserService = runtime.getService(BROWSER_SERVICE_TYPE) ?? null;
|
|
271
|
+
const target = params?.target;
|
|
272
|
+
const startUrl = params?.url?.trim() || extractFirstUrl(messageText) || void 0;
|
|
273
|
+
const timeoutMs = params?.timeoutMs ?? WAIT_FOR_URL_DEFAULT_TIMEOUT_MS;
|
|
274
|
+
const pollIntervalMs = params?.pollIntervalMs ?? WAIT_FOR_URL_DEFAULT_POLL_INTERVAL_MS;
|
|
275
|
+
let tabId = params?.id?.trim() || void 0;
|
|
276
|
+
if (startUrl) {
|
|
277
|
+
const openCommand = {
|
|
278
|
+
subaction: tabId ? "navigate" : "open",
|
|
279
|
+
url: startUrl,
|
|
280
|
+
id: tabId
|
|
281
|
+
};
|
|
282
|
+
try {
|
|
283
|
+
const opened = browserService ? await browserService.execute(openCommand, target) : await executeBrowserWorkspaceCommand(openCommand);
|
|
284
|
+
tabId = opened.tab?.id ?? tabId;
|
|
285
|
+
} catch (error) {
|
|
286
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
287
|
+
logger.warn(
|
|
288
|
+
`[BROWSER] wait_for_url could not open ${startUrl}: ${reason}`
|
|
289
|
+
);
|
|
290
|
+
return {
|
|
291
|
+
text: `Couldn't open ${startUrl} to watch for "${pattern}": ${reason}`,
|
|
292
|
+
success: false,
|
|
293
|
+
values: { success: false, error: "BROWSER_WAIT_FOR_URL_OPEN_FAILED" },
|
|
294
|
+
data: { actionName: "BROWSER", subaction: "wait_for_url" }
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
await callback?.({
|
|
299
|
+
text: startUrl ? `I opened ${startUrl} \u2014 watching for "${pattern}" and I'll resume when it's reached.` : `Watching the current tab for "${pattern}" \u2014 I'll resume when it's reached.`
|
|
300
|
+
});
|
|
301
|
+
logger.info(
|
|
302
|
+
`[BROWSER] wait_for_url pattern="${pattern}" timeoutMs=${timeoutMs} pollIntervalMs=${pollIntervalMs} target=${target ?? "auto"}`
|
|
303
|
+
);
|
|
304
|
+
const outcome = await waitForUrl(
|
|
305
|
+
{ pattern, timeoutMs, pollIntervalMs },
|
|
306
|
+
{
|
|
307
|
+
getCurrentUrl: () => readCurrentBrowserUrl(browserService, target, tabId),
|
|
308
|
+
emitStatus: async (text) => {
|
|
309
|
+
await callback?.({ text });
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
);
|
|
313
|
+
return {
|
|
314
|
+
text: outcome.message,
|
|
315
|
+
success: outcome.matched,
|
|
316
|
+
userFacingText: outcome.message,
|
|
317
|
+
values: {
|
|
318
|
+
success: outcome.matched,
|
|
319
|
+
subaction: "wait_for_url",
|
|
320
|
+
status: outcome.status,
|
|
321
|
+
matched: outcome.matched,
|
|
322
|
+
polls: outcome.polls
|
|
323
|
+
},
|
|
324
|
+
data: {
|
|
325
|
+
actionName: "BROWSER",
|
|
326
|
+
subaction: "wait_for_url",
|
|
327
|
+
outcome
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
}
|
|
108
331
|
const browserAction = {
|
|
109
332
|
name: "BROWSER",
|
|
110
333
|
contexts: ["browser", "web", "automation", "secrets"],
|
|
@@ -115,7 +338,6 @@ const browserAction = {
|
|
|
115
338
|
"CONTROL_BROWSER",
|
|
116
339
|
"CONTROL_BROWSER_SESSION",
|
|
117
340
|
"MANAGE_ELIZA_BROWSER_WORKSPACE",
|
|
118
|
-
"MANAGE_LIFEOPS_BROWSER",
|
|
119
341
|
"NAVIGATE_SITE",
|
|
120
342
|
"OPEN_SITE",
|
|
121
343
|
"USE_BROWSER",
|
|
@@ -128,16 +350,20 @@ const browserAction = {
|
|
|
128
350
|
"LOG_INTO_SITE",
|
|
129
351
|
"SIGN_IN_TO_SITE"
|
|
130
352
|
],
|
|
131
|
-
description: "
|
|
132
|
-
descriptionCompressed: "Browser
|
|
353
|
+
description: "BROWSER action. Control registered browser target: app workspace, bridge Chrome/Safari companion, computeruse Chromium, or Stagehand fallback. BrowserService picks target if omitted. action=autofill_login + domain vault-gated autofills open workspace tab. action=wait_for_url + pattern opens an optional url then watches the tab and resumes when its URL matches (OAuth callback, deploy/CI done), streaming progress.",
|
|
354
|
+
descriptionCompressed: "Browser open|navigate|click|type|screenshot|state|autofill_login|wait_for_url; bridge status elsewhere",
|
|
133
355
|
validate: async () => true,
|
|
134
|
-
handler: async (runtime, message, _state, options) => {
|
|
356
|
+
handler: async (runtime, message, _state, options, callback) => {
|
|
135
357
|
const params = options?.parameters;
|
|
136
358
|
const messageText = getMessageText(message);
|
|
137
359
|
const subaction = inferBrowserSubaction(params, messageText);
|
|
138
360
|
if (subaction === "autofill-login") {
|
|
361
|
+
const { executeBrowserAutofillLogin } = await import("./browser-autofill-login.js");
|
|
139
362
|
return executeBrowserAutofillLogin(runtime, message, options);
|
|
140
363
|
}
|
|
364
|
+
if (subaction === "wait-for-url") {
|
|
365
|
+
return executeBrowserWaitForUrl(runtime, params, messageText, callback);
|
|
366
|
+
}
|
|
141
367
|
const url = params?.url?.trim() || extractFirstUrl(messageText) || void 0;
|
|
142
368
|
const command = {
|
|
143
369
|
id: params?.id?.trim(),
|
|
@@ -148,6 +374,7 @@ const browserAction = {
|
|
|
148
374
|
subaction,
|
|
149
375
|
tabAction: params?.tabAction ?? normalizeLegacyTabAction(params?.action),
|
|
150
376
|
text: params?.text,
|
|
377
|
+
value: params?.text,
|
|
151
378
|
timeoutMs: params?.timeoutMs,
|
|
152
379
|
url,
|
|
153
380
|
cursorDurationMs: params?.cursorDurationMs,
|
|
@@ -156,14 +383,19 @@ const browserAction = {
|
|
|
156
383
|
x: params?.x,
|
|
157
384
|
y: params?.y
|
|
158
385
|
};
|
|
159
|
-
const browserService = runtime.getService(
|
|
160
|
-
BROWSER_SERVICE_TYPE
|
|
161
|
-
);
|
|
386
|
+
const browserService = runtime.getService(BROWSER_SERVICE_TYPE);
|
|
162
387
|
try {
|
|
163
388
|
logger.info(
|
|
164
389
|
`[BROWSER] ${command.subaction} via target=${params?.target ?? "auto"} (workspace mode=${getBrowserWorkspaceMode(process.env)})`
|
|
165
390
|
);
|
|
166
391
|
const result = browserService ? await browserService.execute(command, params?.target) : await executeBrowserWorkspaceCommand(command);
|
|
392
|
+
await emitBrowserStepProgress(
|
|
393
|
+
callback,
|
|
394
|
+
command,
|
|
395
|
+
params,
|
|
396
|
+
messageText,
|
|
397
|
+
true
|
|
398
|
+
);
|
|
167
399
|
return {
|
|
168
400
|
text: formatBrowserSessionResult(command, result),
|
|
169
401
|
success: true,
|
|
@@ -179,10 +411,18 @@ const browserAction = {
|
|
|
179
411
|
}
|
|
180
412
|
};
|
|
181
413
|
} catch (error) {
|
|
182
|
-
const
|
|
183
|
-
logger.warn(`[BROWSER] Failed: ${
|
|
414
|
+
const errorText = error instanceof Error ? error.message : "Browser action failed";
|
|
415
|
+
logger.warn(`[BROWSER] Failed: ${errorText}`);
|
|
416
|
+
await emitBrowserStepProgress(
|
|
417
|
+
callback,
|
|
418
|
+
command,
|
|
419
|
+
params,
|
|
420
|
+
messageText,
|
|
421
|
+
false,
|
|
422
|
+
errorText
|
|
423
|
+
);
|
|
184
424
|
return {
|
|
185
|
-
text: `Browser action failed: ${
|
|
425
|
+
text: `Browser action failed: ${errorText}`,
|
|
186
426
|
success: false,
|
|
187
427
|
values: { success: false, error: "BROWSER_FAILED" },
|
|
188
428
|
data: {
|
|
@@ -193,9 +433,27 @@ const browserAction = {
|
|
|
193
433
|
}
|
|
194
434
|
},
|
|
195
435
|
parameters: [
|
|
436
|
+
{
|
|
437
|
+
name: "target",
|
|
438
|
+
description: "Optional browser target id. Common values: workspace, bridge, computeruse, stagehand.",
|
|
439
|
+
required: false,
|
|
440
|
+
schema: { type: "string" }
|
|
441
|
+
},
|
|
442
|
+
{
|
|
443
|
+
name: "streamProgress",
|
|
444
|
+
description: "When true, emit a compact Step 1 progress callback after the browser command dispatches.",
|
|
445
|
+
required: false,
|
|
446
|
+
schema: { type: "boolean", default: false }
|
|
447
|
+
},
|
|
448
|
+
{
|
|
449
|
+
name: "rationale",
|
|
450
|
+
description: "Optional rationale shown in streamProgress callback text.",
|
|
451
|
+
required: false,
|
|
452
|
+
schema: { type: "string" }
|
|
453
|
+
},
|
|
196
454
|
{
|
|
197
455
|
name: "action",
|
|
198
|
-
description: "Browser action
|
|
456
|
+
description: "Browser action. Snake_case canonical; legacy kebab-case and subaction accepted.",
|
|
199
457
|
required: false,
|
|
200
458
|
schema: {
|
|
201
459
|
type: "string",
|
|
@@ -224,49 +482,28 @@ const browserAction = {
|
|
|
224
482
|
"wait",
|
|
225
483
|
"close_tab",
|
|
226
484
|
"switch_tab",
|
|
227
|
-
"
|
|
228
|
-
"
|
|
229
|
-
"
|
|
230
|
-
"
|
|
231
|
-
"
|
|
232
|
-
"
|
|
233
|
-
"
|
|
485
|
+
"realistic_click",
|
|
486
|
+
"realistic_fill",
|
|
487
|
+
"realistic_type",
|
|
488
|
+
"realistic_press",
|
|
489
|
+
"cursor_move",
|
|
490
|
+
"cursor_hide",
|
|
491
|
+
"autofill_login",
|
|
492
|
+
"wait_for_url"
|
|
234
493
|
]
|
|
235
494
|
}
|
|
236
495
|
},
|
|
237
496
|
{
|
|
238
|
-
name: "
|
|
239
|
-
description: "
|
|
497
|
+
name: "pattern",
|
|
498
|
+
description: "For action=wait_for_url: substring or /regex/ to match the tab URL (e.g. callback?code=, or /\\/done$/).",
|
|
240
499
|
required: false,
|
|
241
|
-
schema: {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
"get",
|
|
249
|
-
"hide",
|
|
250
|
-
"navigate",
|
|
251
|
-
"open",
|
|
252
|
-
"press",
|
|
253
|
-
"reload",
|
|
254
|
-
"screenshot",
|
|
255
|
-
"show",
|
|
256
|
-
"snapshot",
|
|
257
|
-
"state",
|
|
258
|
-
"tab",
|
|
259
|
-
"type",
|
|
260
|
-
"wait",
|
|
261
|
-
"realistic-click",
|
|
262
|
-
"realistic-fill",
|
|
263
|
-
"realistic-type",
|
|
264
|
-
"realistic-press",
|
|
265
|
-
"cursor-move",
|
|
266
|
-
"cursor-hide",
|
|
267
|
-
"autofill-login"
|
|
268
|
-
]
|
|
269
|
-
}
|
|
500
|
+
schema: { type: "string" }
|
|
501
|
+
},
|
|
502
|
+
{
|
|
503
|
+
name: "pollIntervalMs",
|
|
504
|
+
description: "For action=wait_for_url: poll cadence in ms. Default 2000.",
|
|
505
|
+
required: false,
|
|
506
|
+
schema: { type: "number" }
|
|
270
507
|
},
|
|
271
508
|
{
|
|
272
509
|
name: "tabAction",
|
|
@@ -279,19 +516,19 @@ const browserAction = {
|
|
|
279
516
|
},
|
|
280
517
|
{
|
|
281
518
|
name: "domain",
|
|
282
|
-
description: "Required
|
|
519
|
+
description: "Required for action=autofill_login: registrable hostname, e.g. github.com.",
|
|
283
520
|
required: false,
|
|
284
521
|
schema: { type: "string" }
|
|
285
522
|
},
|
|
286
523
|
{
|
|
287
524
|
name: "username",
|
|
288
|
-
description: "
|
|
525
|
+
description: "For autofill-login: saved login username; omit for latest.",
|
|
289
526
|
required: false,
|
|
290
527
|
schema: { type: "string" }
|
|
291
528
|
},
|
|
292
529
|
{
|
|
293
530
|
name: "submit",
|
|
294
|
-
description: "
|
|
531
|
+
description: "For autofill-login: submit after filling. Default false.",
|
|
295
532
|
required: false,
|
|
296
533
|
schema: { type: "boolean" }
|
|
297
534
|
},
|
|
@@ -345,7 +582,7 @@ const browserAction = {
|
|
|
345
582
|
},
|
|
346
583
|
{
|
|
347
584
|
name: "watchMode",
|
|
348
|
-
description: "
|
|
585
|
+
description: "User watching hint; prefer realistic-* click/fill, visible cursor, pointer events.",
|
|
349
586
|
required: false,
|
|
350
587
|
schema: { type: "boolean" }
|
|
351
588
|
},
|
|
@@ -363,7 +600,7 @@ const browserAction = {
|
|
|
363
600
|
},
|
|
364
601
|
{
|
|
365
602
|
name: "replace",
|
|
366
|
-
description: "
|
|
603
|
+
description: "For realistic-fill: replace existing input, not append.",
|
|
367
604
|
required: false,
|
|
368
605
|
schema: { type: "boolean" }
|
|
369
606
|
},
|
|
@@ -408,6 +645,21 @@ const browserAction = {
|
|
|
408
645
|
text: "click completed in desktop mode."
|
|
409
646
|
}
|
|
410
647
|
}
|
|
648
|
+
],
|
|
649
|
+
[
|
|
650
|
+
{
|
|
651
|
+
name: "{{name1}}",
|
|
652
|
+
content: {
|
|
653
|
+
text: "Open the GitHub OAuth page and let me know when it redirects back to our callback."
|
|
654
|
+
}
|
|
655
|
+
},
|
|
656
|
+
{
|
|
657
|
+
name: "{{agentName}}",
|
|
658
|
+
content: {
|
|
659
|
+
text: `I opened https://github.com/login/oauth/authorize \u2014 watching for "callback?code=" and I'll resume when it's reached.`,
|
|
660
|
+
actions: ["BROWSER"]
|
|
661
|
+
}
|
|
662
|
+
}
|
|
411
663
|
]
|
|
412
664
|
]
|
|
413
665
|
};
|