browser-use 0.6.1 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -18
- package/dist/actor/element.js +24 -3
- package/dist/actor/mouse.js +21 -3
- package/dist/actor/page.js +33 -11
- package/dist/agent/gif.js +28 -3
- package/dist/agent/message-manager/service.js +2 -22
- package/dist/agent/message-manager/utils.js +15 -2
- package/dist/agent/message-manager/views.d.ts +7 -7
- package/dist/agent/message-manager/views.js +1 -0
- package/dist/agent/prompts.d.ts +3 -0
- package/dist/agent/prompts.js +22 -12
- package/dist/agent/service.d.ts +9 -1
- package/dist/agent/service.js +204 -79
- package/dist/agent/system_prompt.md +12 -11
- package/dist/agent/system_prompt_anthropic_flash.md +6 -5
- package/dist/agent/system_prompt_no_thinking.md +12 -11
- package/dist/agent/views.d.ts +2 -0
- package/dist/agent/views.js +48 -36
- package/dist/browser/extensions.js +20 -10
- package/dist/browser/profile.d.ts +4 -0
- package/dist/browser/profile.js +107 -4
- package/dist/browser/session.d.ts +28 -1
- package/dist/browser/session.js +1436 -528
- package/dist/browser/watchdogs/default-action-watchdog.js +32 -3
- package/dist/browser/watchdogs/downloads-watchdog.d.ts +4 -0
- package/dist/browser/watchdogs/downloads-watchdog.js +105 -9
- package/dist/browser/watchdogs/har-recording-watchdog.d.ts +1 -0
- package/dist/browser/watchdogs/har-recording-watchdog.js +54 -2
- package/dist/browser/watchdogs/permissions-watchdog.d.ts +5 -0
- package/dist/browser/watchdogs/permissions-watchdog.js +106 -3
- package/dist/browser/watchdogs/recording-watchdog.d.ts +2 -0
- package/dist/browser/watchdogs/recording-watchdog.js +54 -2
- package/dist/browser/watchdogs/security-watchdog.d.ts +1 -0
- package/dist/browser/watchdogs/security-watchdog.js +47 -7
- package/dist/browser/watchdogs/storage-state-watchdog.d.ts +6 -0
- package/dist/browser/watchdogs/storage-state-watchdog.js +206 -14
- package/dist/cli.d.ts +13 -2
- package/dist/cli.js +190 -9
- package/dist/code-use/namespace.js +52 -7
- package/dist/code-use/notebook-export.js +18 -2
- package/dist/code-use/service.js +1 -0
- package/dist/config.js +26 -4
- package/dist/controller/action-timeout.d.ts +9 -0
- package/dist/controller/action-timeout.js +95 -0
- package/dist/controller/registry/service.d.ts +1 -0
- package/dist/controller/registry/service.js +28 -1
- package/dist/controller/service.d.ts +2 -1
- package/dist/controller/service.js +494 -329
- package/dist/entrypoint.d.ts +1 -0
- package/dist/entrypoint.js +27 -0
- package/dist/filesystem/file-system.js +38 -8
- package/dist/integrations/gmail/service.js +30 -6
- package/dist/llm/browser-use/chat.js +2 -2
- package/dist/llm/codex/auth.d.ts +118 -0
- package/dist/llm/codex/auth.js +599 -0
- package/dist/llm/codex/chat.d.ts +70 -0
- package/dist/llm/codex/chat.js +392 -0
- package/dist/llm/codex/index.d.ts +2 -0
- package/dist/llm/codex/index.js +2 -0
- package/dist/llm/google/chat.js +18 -1
- package/dist/logging-config.js +22 -11
- package/dist/mcp/client.d.ts +1 -0
- package/dist/mcp/client.js +12 -10
- package/dist/mcp/redaction.d.ts +3 -0
- package/dist/mcp/redaction.js +132 -0
- package/dist/mcp/server.d.ts +2 -0
- package/dist/mcp/server.js +64 -22
- package/dist/screenshots/service.js +25 -2
- package/dist/skill-cli/direct.d.ts +4 -1
- package/dist/skill-cli/direct.js +263 -66
- package/dist/skill-cli/server.d.ts +1 -0
- package/dist/skill-cli/server.js +115 -25
- package/dist/skill-cli/tunnel.d.ts +1 -0
- package/dist/skill-cli/tunnel.js +16 -4
- package/dist/sync/auth.js +22 -9
- package/dist/telemetry/service.js +21 -2
- package/dist/telemetry/views.js +31 -8
- package/dist/tokens/custom-pricing.js +2 -2
- package/dist/tokens/openrouter-pricing.d.ts +11 -0
- package/dist/tokens/openrouter-pricing.js +102 -0
- package/dist/tokens/service.js +20 -16
- package/dist/utils.d.ts +3 -1
- package/dist/utils.js +3 -1
- package/package.json +68 -27
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
import { BrowserErrorEvent, CloseTabEvent, NavigateToUrlEvent, NavigationCompleteEvent, TabCreatedEvent, } from '../events.js';
|
|
2
2
|
import { BaseWatchdog } from './base.js';
|
|
3
|
+
const redactUrlForError = (url) => {
|
|
4
|
+
try {
|
|
5
|
+
const parsed = new URL(url);
|
|
6
|
+
if (parsed.protocol === 'data:') {
|
|
7
|
+
return 'data:<redacted>';
|
|
8
|
+
}
|
|
9
|
+
if (parsed.protocol === 'blob:') {
|
|
10
|
+
return parsed.origin && parsed.origin !== 'null'
|
|
11
|
+
? `blob:${parsed.origin}/<redacted>`
|
|
12
|
+
: 'blob:<redacted>';
|
|
13
|
+
}
|
|
14
|
+
return `${parsed.origin}${parsed.pathname}${parsed.search ? '?<redacted>' : ''}${parsed.hash ? '#<redacted>' : ''}`;
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
const queryIndex = url.indexOf('?');
|
|
18
|
+
const hashIndex = url.indexOf('#');
|
|
19
|
+
const cutoffCandidates = [queryIndex, hashIndex].filter((index) => index >= 0);
|
|
20
|
+
const cutoff = cutoffCandidates.length > 0 ? Math.min(...cutoffCandidates) : url.length;
|
|
21
|
+
return `${url.slice(0, cutoff)}${queryIndex >= 0 ? '?<redacted>' : ''}${hashIndex >= 0 ? '#<redacted>' : ''}`;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
3
24
|
export class SecurityWatchdog extends BaseWatchdog {
|
|
4
25
|
static LISTENS_TO = [
|
|
5
26
|
NavigateToUrlEvent,
|
|
@@ -12,30 +33,38 @@ export class SecurityWatchdog extends BaseWatchdog {
|
|
|
12
33
|
if (!denialReason) {
|
|
13
34
|
return;
|
|
14
35
|
}
|
|
36
|
+
const safeUrl = redactUrlForError(event.url);
|
|
15
37
|
await this.event_bus.dispatch(new BrowserErrorEvent({
|
|
16
38
|
error_type: 'NavigationBlocked',
|
|
17
|
-
message: `Navigation blocked to disallowed URL: ${
|
|
39
|
+
message: `Navigation blocked to disallowed URL: ${safeUrl}`,
|
|
18
40
|
details: {
|
|
19
|
-
url:
|
|
41
|
+
url: safeUrl,
|
|
20
42
|
reason: denialReason,
|
|
21
43
|
},
|
|
22
44
|
}));
|
|
23
|
-
throw new Error(`Navigation to ${
|
|
45
|
+
throw new Error(`Navigation to ${safeUrl} blocked by security policy`);
|
|
24
46
|
}
|
|
25
47
|
async on_NavigationCompleteEvent(event) {
|
|
26
48
|
const denialReason = this._getUrlDenialReason(event.url);
|
|
27
49
|
if (!denialReason) {
|
|
28
50
|
return;
|
|
29
51
|
}
|
|
52
|
+
const safeUrl = redactUrlForError(event.url);
|
|
30
53
|
await this.event_bus.dispatch(new BrowserErrorEvent({
|
|
31
54
|
error_type: 'NavigationBlocked',
|
|
32
|
-
message: `Navigation blocked to non-allowed URL: ${
|
|
55
|
+
message: `Navigation blocked to non-allowed URL: ${safeUrl}`,
|
|
33
56
|
details: {
|
|
34
|
-
url:
|
|
57
|
+
url: safeUrl,
|
|
35
58
|
target_id: event.target_id,
|
|
36
59
|
reason: denialReason,
|
|
37
60
|
},
|
|
38
61
|
}));
|
|
62
|
+
if (!this._isActiveTarget(event.target_id)) {
|
|
63
|
+
await this.event_bus.dispatch(new CloseTabEvent({
|
|
64
|
+
target_id: event.target_id,
|
|
65
|
+
}));
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
39
68
|
try {
|
|
40
69
|
await this.browser_session.navigate_to('about:blank');
|
|
41
70
|
}
|
|
@@ -48,11 +77,12 @@ export class SecurityWatchdog extends BaseWatchdog {
|
|
|
48
77
|
if (!denialReason) {
|
|
49
78
|
return;
|
|
50
79
|
}
|
|
80
|
+
const safeUrl = redactUrlForError(event.url);
|
|
51
81
|
await this.event_bus.dispatch(new BrowserErrorEvent({
|
|
52
82
|
error_type: 'TabCreationBlocked',
|
|
53
|
-
message: `Tab created with non-allowed URL: ${
|
|
83
|
+
message: `Tab created with non-allowed URL: ${safeUrl}`,
|
|
54
84
|
details: {
|
|
55
|
-
url:
|
|
85
|
+
url: safeUrl,
|
|
56
86
|
target_id: event.target_id,
|
|
57
87
|
reason: denialReason,
|
|
58
88
|
},
|
|
@@ -81,4 +111,14 @@ export class SecurityWatchdog extends BaseWatchdog {
|
|
|
81
111
|
}
|
|
82
112
|
return null;
|
|
83
113
|
}
|
|
114
|
+
_isActiveTarget(targetId) {
|
|
115
|
+
if (!targetId) {
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
const activeTab = this.browser_session.active_tab;
|
|
119
|
+
if (!activeTab) {
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
return activeTab.target_id === targetId || activeTab.tab_id === targetId;
|
|
123
|
+
}
|
|
84
124
|
}
|
|
@@ -19,6 +19,12 @@ export declare class StorageStateWatchdog extends BaseWatchdog {
|
|
|
19
19
|
private _snapshotStorageState;
|
|
20
20
|
private _readStoredState;
|
|
21
21
|
private _mergeStorageStates;
|
|
22
|
+
private _filterStorageStateForSave;
|
|
23
|
+
private _hasUrlAccessRestrictions;
|
|
22
24
|
private _applyOriginsStorage;
|
|
25
|
+
private _getOriginDenialReason;
|
|
26
|
+
private _filterCookies;
|
|
27
|
+
private _filterOrigins;
|
|
28
|
+
private _getCookieDenialReason;
|
|
23
29
|
private _normalizeStorageEntries;
|
|
24
30
|
}
|
|
@@ -2,6 +2,59 @@ import fs from 'node:fs';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { BrowserConnectedEvent, BrowserStopEvent, LoadStorageStateEvent, SaveStorageStateEvent, StorageStateLoadedEvent, StorageStateSavedEvent, } from '../events.js';
|
|
4
4
|
import { BaseWatchdog } from './base.js';
|
|
5
|
+
const chmodPrivateFile = (filePath) => {
|
|
6
|
+
if (process.platform === 'win32') {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
fs.chmodSync(filePath, 0o600);
|
|
10
|
+
};
|
|
11
|
+
const ensurePrivateDirectoryIfCreated = (dirPath) => {
|
|
12
|
+
const existed = fs.existsSync(dirPath);
|
|
13
|
+
fs.mkdirSync(dirPath, { recursive: true, mode: 0o700 });
|
|
14
|
+
if (!existed && process.platform !== 'win32') {
|
|
15
|
+
fs.chmodSync(dirPath, 0o700);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
const redactUrlForLogging = (url) => {
|
|
19
|
+
const raw = String(url ?? '');
|
|
20
|
+
if (!raw) {
|
|
21
|
+
return raw;
|
|
22
|
+
}
|
|
23
|
+
if (/^data:/i.test(raw)) {
|
|
24
|
+
return 'data:<redacted>';
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
const parsed = new URL(raw);
|
|
28
|
+
parsed.username = '';
|
|
29
|
+
parsed.password = '';
|
|
30
|
+
const [withoutHash] = parsed.href.split('#', 1);
|
|
31
|
+
const [withoutQuery] = withoutHash.split('?', 1);
|
|
32
|
+
return `${withoutQuery}${parsed.search ? '?<redacted>' : ''}${parsed.hash ? '#<redacted>' : ''}`;
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
const queryIndex = raw.indexOf('?');
|
|
36
|
+
const hashIndex = raw.indexOf('#');
|
|
37
|
+
const firstSensitiveIndex = [queryIndex, hashIndex]
|
|
38
|
+
.filter((index) => index >= 0)
|
|
39
|
+
.sort((a, b) => a - b)[0];
|
|
40
|
+
if (firstSensitiveIndex === undefined) {
|
|
41
|
+
return raw;
|
|
42
|
+
}
|
|
43
|
+
return `${raw.slice(0, firstSensitiveIndex)}${queryIndex >= 0 ? '?<redacted>' : ''}${hashIndex >= 0 ? '#<redacted>' : ''}`;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
const sameOrigin = (left, right) => {
|
|
47
|
+
try {
|
|
48
|
+
return new URL(left).origin === new URL(right).origin;
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
const writePrivateFile = (filePath, contents) => {
|
|
55
|
+
fs.writeFileSync(filePath, contents, { encoding: 'utf-8', mode: 0o600 });
|
|
56
|
+
chmodPrivateFile(filePath);
|
|
57
|
+
};
|
|
5
58
|
export class StorageStateWatchdog extends BaseWatchdog {
|
|
6
59
|
static LISTENS_TO = [
|
|
7
60
|
BrowserConnectedEvent,
|
|
@@ -34,25 +87,27 @@ export class StorageStateWatchdog extends BaseWatchdog {
|
|
|
34
87
|
}
|
|
35
88
|
const storageState = (await browserContext.storageState());
|
|
36
89
|
const normalized = storageState ?? {};
|
|
37
|
-
const merged = this._mergeStorageStates(this._readStoredState(targetPath), {
|
|
90
|
+
const merged = this._filterStorageStateForSave(this._mergeStorageStates(this._readStoredState(targetPath), {
|
|
38
91
|
cookies: Array.isArray(normalized.cookies) ? normalized.cookies : [],
|
|
39
92
|
origins: Array.isArray(normalized.origins) ? normalized.origins : [],
|
|
40
|
-
});
|
|
93
|
+
}));
|
|
41
94
|
this._lastSavedSnapshot = this._snapshotStorageState(merged);
|
|
42
95
|
const dirPath = path.dirname(targetPath);
|
|
43
|
-
|
|
96
|
+
ensurePrivateDirectoryIfCreated(dirPath);
|
|
44
97
|
const tempPath = `${targetPath}.tmp`;
|
|
45
|
-
|
|
98
|
+
writePrivateFile(tempPath, JSON.stringify(merged, null, 2));
|
|
46
99
|
if (fs.existsSync(targetPath)) {
|
|
47
100
|
const backupPath = `${targetPath}.bak`;
|
|
48
101
|
try {
|
|
49
102
|
fs.renameSync(targetPath, backupPath);
|
|
103
|
+
chmodPrivateFile(backupPath);
|
|
50
104
|
}
|
|
51
105
|
catch {
|
|
52
106
|
// Ignore backup failures and continue with atomic swap.
|
|
53
107
|
}
|
|
54
108
|
}
|
|
55
109
|
fs.renameSync(tempPath, targetPath);
|
|
110
|
+
chmodPrivateFile(targetPath);
|
|
56
111
|
await this.event_bus.dispatch(new StorageStateSavedEvent({
|
|
57
112
|
path: targetPath,
|
|
58
113
|
cookies_count: Array.isArray(merged.cookies)
|
|
@@ -81,16 +136,18 @@ export class StorageStateWatchdog extends BaseWatchdog {
|
|
|
81
136
|
cookies,
|
|
82
137
|
origins,
|
|
83
138
|
});
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
await this._applyOriginsStorage(origins);
|
|
139
|
+
const allowedCookies = this._filterCookies(cookies);
|
|
140
|
+
if (allowedCookies.length > 0 &&
|
|
141
|
+
typeof browserContext.addCookies === 'function') {
|
|
142
|
+
await browserContext.addCookies(allowedCookies);
|
|
89
143
|
}
|
|
144
|
+
const originsLoaded = origins.length > 0
|
|
145
|
+
? await this._applyOriginsStorage(origins)
|
|
146
|
+
: 0;
|
|
90
147
|
await this.event_bus.dispatch(new StorageStateLoadedEvent({
|
|
91
148
|
path: targetPath,
|
|
92
|
-
cookies_count:
|
|
93
|
-
origins_count:
|
|
149
|
+
cookies_count: allowedCookies.length,
|
|
150
|
+
origins_count: originsLoaded,
|
|
94
151
|
}));
|
|
95
152
|
}
|
|
96
153
|
onDetached() {
|
|
@@ -142,7 +199,10 @@ export class StorageStateWatchdog extends BaseWatchdog {
|
|
|
142
199
|
try {
|
|
143
200
|
const storageState = (await browserContext.storageState());
|
|
144
201
|
const normalized = storageState ?? {};
|
|
145
|
-
const snapshot = this._snapshotStorageState(
|
|
202
|
+
const snapshot = this._snapshotStorageState(this._filterStorageStateForSave({
|
|
203
|
+
cookies: Array.isArray(normalized.cookies) ? normalized.cookies : [],
|
|
204
|
+
origins: Array.isArray(normalized.origins) ? normalized.origins : [],
|
|
205
|
+
}));
|
|
146
206
|
if (snapshot === this._lastSavedSnapshot) {
|
|
147
207
|
return;
|
|
148
208
|
}
|
|
@@ -213,11 +273,32 @@ export class StorageStateWatchdog extends BaseWatchdog {
|
|
|
213
273
|
origins: [...mergedOrigins.values()],
|
|
214
274
|
};
|
|
215
275
|
}
|
|
276
|
+
_filterStorageStateForSave(state) {
|
|
277
|
+
const cookies = Array.isArray(state.cookies) ? state.cookies : [];
|
|
278
|
+
const origins = Array.isArray(state.origins) ? state.origins : [];
|
|
279
|
+
if (!this._hasUrlAccessRestrictions()) {
|
|
280
|
+
return { cookies, origins };
|
|
281
|
+
}
|
|
282
|
+
return {
|
|
283
|
+
cookies: this._filterCookies(cookies),
|
|
284
|
+
origins: this._filterOrigins(origins),
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
_hasUrlAccessRestrictions() {
|
|
288
|
+
const profile = this.browser_session.browser_profile;
|
|
289
|
+
const hasEntries = (value) => Array.isArray(value)
|
|
290
|
+
? value.length > 0
|
|
291
|
+
: value instanceof Set && value.size > 0;
|
|
292
|
+
return (hasEntries(profile.allowed_domains) ||
|
|
293
|
+
hasEntries(profile.prohibited_domains) ||
|
|
294
|
+
Boolean(profile.block_ip_addresses));
|
|
295
|
+
}
|
|
216
296
|
async _applyOriginsStorage(origins) {
|
|
217
297
|
const browserContext = this.browser_session.browser_context;
|
|
218
298
|
if (!browserContext?.newPage) {
|
|
219
|
-
return;
|
|
299
|
+
return 0;
|
|
220
300
|
}
|
|
301
|
+
let loadedCount = 0;
|
|
221
302
|
for (const originState of origins) {
|
|
222
303
|
const origin = typeof originState?.origin === 'string'
|
|
223
304
|
? originState.origin.trim()
|
|
@@ -225,6 +306,11 @@ export class StorageStateWatchdog extends BaseWatchdog {
|
|
|
225
306
|
if (!origin || !/^https?:\/\//i.test(origin)) {
|
|
226
307
|
continue;
|
|
227
308
|
}
|
|
309
|
+
const denialReason = this._getOriginDenialReason(origin);
|
|
310
|
+
if (denialReason) {
|
|
311
|
+
this.browser_session.logger.warning(`[StorageStateWatchdog] Skipping storage origin ${redactUrlForLogging(origin)}: ${denialReason}`);
|
|
312
|
+
continue;
|
|
313
|
+
}
|
|
228
314
|
const localStorageEntries = this._normalizeStorageEntries(originState?.localStorage);
|
|
229
315
|
const sessionStorageEntries = this._normalizeStorageEntries(originState?.sessionStorage);
|
|
230
316
|
if (localStorageEntries.length === 0 &&
|
|
@@ -238,6 +324,34 @@ export class StorageStateWatchdog extends BaseWatchdog {
|
|
|
238
324
|
waitUntil: 'domcontentloaded',
|
|
239
325
|
timeout: 5_000,
|
|
240
326
|
});
|
|
327
|
+
const finalUrl = typeof page.url === 'function' ? page.url() : origin;
|
|
328
|
+
const finalDenialReason = this._getOriginDenialReason(finalUrl);
|
|
329
|
+
if (finalDenialReason) {
|
|
330
|
+
this.browser_session.logger.warning(`[StorageStateWatchdog] Skipping storage origin ${redactUrlForLogging(origin)} after redirect to blocked URL: ${finalDenialReason}`);
|
|
331
|
+
try {
|
|
332
|
+
await page.goto?.('about:blank', {
|
|
333
|
+
waitUntil: 'load',
|
|
334
|
+
timeout: 5_000,
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
catch {
|
|
338
|
+
// The temporary page is closed below; resetting first is best effort.
|
|
339
|
+
}
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
342
|
+
if (!sameOrigin(origin, finalUrl)) {
|
|
343
|
+
this.browser_session.logger.warning(`[StorageStateWatchdog] Skipping storage origin ${redactUrlForLogging(origin)} after redirect to a different origin`);
|
|
344
|
+
try {
|
|
345
|
+
await page.goto?.('about:blank', {
|
|
346
|
+
waitUntil: 'load',
|
|
347
|
+
timeout: 5_000,
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
catch {
|
|
351
|
+
// The temporary page is closed below; resetting first is best effort.
|
|
352
|
+
}
|
|
353
|
+
continue;
|
|
354
|
+
}
|
|
241
355
|
await page.evaluate?.((payload) => {
|
|
242
356
|
for (const entry of payload.localStorageEntries) {
|
|
243
357
|
window.localStorage.setItem(entry.name, entry.value);
|
|
@@ -249,9 +363,10 @@ export class StorageStateWatchdog extends BaseWatchdog {
|
|
|
249
363
|
localStorageEntries,
|
|
250
364
|
sessionStorageEntries,
|
|
251
365
|
});
|
|
366
|
+
loadedCount += 1;
|
|
252
367
|
}
|
|
253
368
|
catch (error) {
|
|
254
|
-
this.browser_session.logger.debug(`[StorageStateWatchdog] Failed to apply origin storage for ${origin}: ${error.message}`);
|
|
369
|
+
this.browser_session.logger.debug(`[StorageStateWatchdog] Failed to apply origin storage for ${redactUrlForLogging(origin)}: ${error.message}`);
|
|
255
370
|
}
|
|
256
371
|
finally {
|
|
257
372
|
try {
|
|
@@ -262,6 +377,83 @@ export class StorageStateWatchdog extends BaseWatchdog {
|
|
|
262
377
|
}
|
|
263
378
|
}
|
|
264
379
|
}
|
|
380
|
+
return loadedCount;
|
|
381
|
+
}
|
|
382
|
+
_getOriginDenialReason(origin) {
|
|
383
|
+
const session = this.browser_session;
|
|
384
|
+
if (typeof session._get_url_access_denial_reason === 'function') {
|
|
385
|
+
try {
|
|
386
|
+
return session._get_url_access_denial_reason(origin);
|
|
387
|
+
}
|
|
388
|
+
catch {
|
|
389
|
+
return 'blocked';
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
if (typeof session._is_url_allowed === 'function') {
|
|
393
|
+
try {
|
|
394
|
+
return session._is_url_allowed(origin) ? null : 'blocked';
|
|
395
|
+
}
|
|
396
|
+
catch {
|
|
397
|
+
return 'blocked';
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
return null;
|
|
401
|
+
}
|
|
402
|
+
_filterCookies(cookies) {
|
|
403
|
+
return cookies.filter((cookie) => {
|
|
404
|
+
const denialReason = this._getCookieDenialReason(cookie);
|
|
405
|
+
if (!denialReason) {
|
|
406
|
+
return true;
|
|
407
|
+
}
|
|
408
|
+
const cookieName = cookie && typeof cookie === 'object' && 'name' in cookie
|
|
409
|
+
? String(cookie.name ?? '')
|
|
410
|
+
: '';
|
|
411
|
+
this.browser_session.logger.warning(`[StorageStateWatchdog] Skipping storage cookie ${cookieName || '<unnamed>'}: ${denialReason}`);
|
|
412
|
+
return false;
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
_filterOrigins(origins) {
|
|
416
|
+
return origins.filter((originState) => {
|
|
417
|
+
const origin = originState &&
|
|
418
|
+
typeof originState === 'object' &&
|
|
419
|
+
'origin' in originState &&
|
|
420
|
+
typeof originState.origin === 'string'
|
|
421
|
+
? originState.origin.trim()
|
|
422
|
+
: '';
|
|
423
|
+
const denialReason = origin
|
|
424
|
+
? this._getOriginDenialReason(origin)
|
|
425
|
+
: 'invalid_url';
|
|
426
|
+
if (!denialReason) {
|
|
427
|
+
return true;
|
|
428
|
+
}
|
|
429
|
+
this.browser_session.logger.warning(`[StorageStateWatchdog] Skipping saved storage origin ${origin ? redactUrlForLogging(origin) : '<invalid>'}: ${denialReason}`);
|
|
430
|
+
return false;
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
_getCookieDenialReason(cookie) {
|
|
434
|
+
const session = this.browser_session;
|
|
435
|
+
if (typeof session._get_cookie_access_denial_reason === 'function') {
|
|
436
|
+
try {
|
|
437
|
+
return session._get_cookie_access_denial_reason(cookie);
|
|
438
|
+
}
|
|
439
|
+
catch {
|
|
440
|
+
return 'blocked';
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
if (!cookie || typeof cookie !== 'object') {
|
|
444
|
+
return null;
|
|
445
|
+
}
|
|
446
|
+
const cookieLike = cookie;
|
|
447
|
+
const explicitUrl = typeof cookieLike.url === 'string' ? cookieLike.url.trim() : '';
|
|
448
|
+
if (explicitUrl) {
|
|
449
|
+
return this._getOriginDenialReason(explicitUrl);
|
|
450
|
+
}
|
|
451
|
+
const rawDomain = typeof cookieLike.domain === 'string' ? cookieLike.domain.trim() : '';
|
|
452
|
+
const host = rawDomain.replace(/^\./, '');
|
|
453
|
+
if (!host) {
|
|
454
|
+
return null;
|
|
455
|
+
}
|
|
456
|
+
return this._getOriginDenialReason(`https://${host}`);
|
|
265
457
|
}
|
|
266
458
|
_normalizeStorageEntries(entries) {
|
|
267
459
|
if (!Array.isArray(entries)) {
|
package/dist/cli.d.ts
CHANGED
|
@@ -3,9 +3,10 @@ import { spawnSync } from 'node:child_process';
|
|
|
3
3
|
import { BrowserProfile } from './browser/profile.js';
|
|
4
4
|
import { CloudBrowserClient } from './browser/cloud/cloud.js';
|
|
5
5
|
import { CloudManagementClient } from './browser/cloud/management.js';
|
|
6
|
+
import { loginAndSaveCodexDeviceCode, saveImportedCodexCliTokens } from './llm/codex/auth.js';
|
|
6
7
|
import type { BaseChatModel } from './llm/base.js';
|
|
7
8
|
import { get_tunnel_manager } from './skill-cli/tunnel.js';
|
|
8
|
-
type CliModelProvider = 'openai' | 'anthropic' | 'google' | 'deepseek' | 'groq' | 'openrouter' | 'azure' | 'mistral' | 'cerebras' | 'vercel' | 'oci' | 'aws-anthropic' | 'aws' | 'ollama' | 'browser-use';
|
|
9
|
+
type CliModelProvider = 'openai' | 'anthropic' | 'google' | 'deepseek' | 'groq' | 'openrouter' | 'azure' | 'codex' | 'mistral' | 'cerebras' | 'vercel' | 'oci' | 'aws-anthropic' | 'aws' | 'ollama' | 'browser-use';
|
|
9
10
|
export interface ParsedCliArgs {
|
|
10
11
|
help: boolean;
|
|
11
12
|
version: boolean;
|
|
@@ -122,6 +123,16 @@ type BrowserCookieInit = {
|
|
|
122
123
|
partitionKey?: string;
|
|
123
124
|
};
|
|
124
125
|
export declare const runInstallCommand: (options?: RunInstallCommandOptions) => void;
|
|
126
|
+
export interface RunAuthCommandOptions {
|
|
127
|
+
stdout?: WritableLike;
|
|
128
|
+
stderr?: WritableLike;
|
|
129
|
+
json_output?: boolean;
|
|
130
|
+
configDir?: string | null;
|
|
131
|
+
authStorePath?: string | null;
|
|
132
|
+
login_device_code?: typeof loginAndSaveCodexDeviceCode;
|
|
133
|
+
import_codex_cli?: typeof saveImportedCodexCliTokens;
|
|
134
|
+
}
|
|
135
|
+
export declare const runAuthCommand: (argv: string[], options?: RunAuthCommandOptions) => Promise<0 | 1>;
|
|
125
136
|
export declare const runTunnelCommand: (argv: string[], options?: RunTunnelCommandOptions) => Promise<0 | 1>;
|
|
126
137
|
export declare const runSetupCommand: (params: {
|
|
127
138
|
mode?: string | null;
|
|
@@ -133,7 +144,7 @@ export declare const runSessionCommand: (argv: string[], options?: RunSessionCom
|
|
|
133
144
|
export declare const runProfileCommand: (argv: string[], options?: RunProfileCommandOptions) => Promise<0 | 1>;
|
|
134
145
|
export declare const hasCloudRunFlags: (argv: string[]) => boolean;
|
|
135
146
|
type PrefixedSubcommand = {
|
|
136
|
-
command: 'run' | 'task' | 'session' | 'profile';
|
|
147
|
+
command: 'run' | 'task' | 'session' | 'profile' | 'auth';
|
|
137
148
|
argv: string[];
|
|
138
149
|
debug: boolean;
|
|
139
150
|
forwardedArgs: string[];
|