browser-use 0.7.1 → 0.7.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/dist/browser/session.d.ts +1 -1
- package/dist/browser/session.js +7 -3
- package/dist/browser/watchdogs/base.d.ts +6 -0
- package/dist/browser/watchdogs/base.js +10 -0
- package/dist/browser/watchdogs/cdp-session-watchdog.js +1 -1
- package/dist/browser/watchdogs/crash-watchdog.js +2 -2
- package/dist/browser/watchdogs/downloads-watchdog.js +4 -4
- package/dist/browser/watchdogs/har-recording-watchdog.js +1 -1
- package/dist/browser/watchdogs/popups-watchdog.js +2 -2
- package/dist/browser/watchdogs/recording-watchdog.js +5 -2
- package/dist/code-use/service.d.ts +1 -0
- package/dist/code-use/service.js +4 -2
- package/dist/controller/registry/service.js +24 -8
- package/dist/llm/deepseek/serializer.js +19 -2
- package/dist/llm/google/chat.js +33 -22
- package/dist/llm/groq/serializer.js +4 -1
- package/dist/llm/openai/serializer.js +17 -2
- package/dist/skill-cli/direct.js +2 -2
- package/dist/tokens/service.js +3 -3
- package/dist/utils.js +1 -1
- package/package.json +10 -4
|
@@ -499,7 +499,7 @@ export declare class BrowserSession {
|
|
|
499
499
|
private _scrollWithCdpGesture;
|
|
500
500
|
/**
|
|
501
501
|
* Scroll the current page container
|
|
502
|
-
* @param pixels - Number of pixels to scroll (positive =
|
|
502
|
+
* @param pixels - Number of pixels to scroll (positive = down, negative = up)
|
|
503
503
|
*/
|
|
504
504
|
private _scrollContainer;
|
|
505
505
|
/**
|
package/dist/browser/session.js
CHANGED
|
@@ -1404,7 +1404,11 @@ export class BrowserSession {
|
|
|
1404
1404
|
});
|
|
1405
1405
|
const reconnectTask = this._auto_reconnect();
|
|
1406
1406
|
this._reconnectTask = reconnectTask;
|
|
1407
|
-
void reconnectTask
|
|
1407
|
+
void reconnectTask
|
|
1408
|
+
.catch((error) => {
|
|
1409
|
+
this.logger.warning(`Automatic reconnect failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
1410
|
+
})
|
|
1411
|
+
.finally(() => {
|
|
1408
1412
|
if (this._reconnectTask === reconnectTask) {
|
|
1409
1413
|
this._reconnectTask = null;
|
|
1410
1414
|
}
|
|
@@ -2572,7 +2576,7 @@ export class BrowserSession {
|
|
|
2572
2576
|
}
|
|
2573
2577
|
}
|
|
2574
2578
|
if (direction === 'up' || direction === 'down') {
|
|
2575
|
-
const pixels = direction === 'down' ?
|
|
2579
|
+
const pixels = direction === 'down' ? normalizedAmount : -normalizedAmount;
|
|
2576
2580
|
await this._withAbort(this._scrollContainer(pixels), signal);
|
|
2577
2581
|
return;
|
|
2578
2582
|
}
|
|
@@ -5293,7 +5297,7 @@ export class BrowserSession {
|
|
|
5293
5297
|
}
|
|
5294
5298
|
/**
|
|
5295
5299
|
* Scroll the current page container
|
|
5296
|
-
* @param pixels - Number of pixels to scroll (positive =
|
|
5300
|
+
* @param pixels - Number of pixels to scroll (positive = down, negative = up)
|
|
5297
5301
|
*/
|
|
5298
5302
|
async _scrollContainer(pixels) {
|
|
5299
5303
|
const page = await this.getCurrentPage();
|
|
@@ -17,5 +17,11 @@ export declare abstract class BaseWatchdog {
|
|
|
17
17
|
detach_from_session(): void;
|
|
18
18
|
protected onAttached(): void;
|
|
19
19
|
protected onDetached(): void;
|
|
20
|
+
/**
|
|
21
|
+
* Run fire-and-forget background work without letting a rejection surface
|
|
22
|
+
* as an unhandled promise rejection (which terminates the process on
|
|
23
|
+
* modern Node). Failures are logged at debug level.
|
|
24
|
+
*/
|
|
25
|
+
protected runBackground(label: string, work: Promise<unknown>): void;
|
|
20
26
|
private _collectHandlerMethods;
|
|
21
27
|
}
|
|
@@ -91,6 +91,16 @@ export class BaseWatchdog {
|
|
|
91
91
|
}
|
|
92
92
|
onAttached() { }
|
|
93
93
|
onDetached() { }
|
|
94
|
+
/**
|
|
95
|
+
* Run fire-and-forget background work without letting a rejection surface
|
|
96
|
+
* as an unhandled promise rejection (which terminates the process on
|
|
97
|
+
* modern Node). Failures are logged at debug level.
|
|
98
|
+
*/
|
|
99
|
+
runBackground(label, work) {
|
|
100
|
+
void work.catch((error) => {
|
|
101
|
+
this.browser_session.logger.debug(`[${this.constructor.name}] ${label} failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
102
|
+
});
|
|
103
|
+
}
|
|
94
104
|
_collectHandlerMethods() {
|
|
95
105
|
const methodNames = new Set();
|
|
96
106
|
let prototype = Object.getPrototypeOf(this);
|
|
@@ -12,7 +12,7 @@ export class CDPSessionWatchdog extends BaseWatchdog {
|
|
|
12
12
|
await this._teardownCdpMonitoring();
|
|
13
13
|
}
|
|
14
14
|
onDetached() {
|
|
15
|
-
|
|
15
|
+
this.runBackground('teardown CDP monitoring', this._teardownCdpMonitoring());
|
|
16
16
|
}
|
|
17
17
|
async _ensureCdpMonitoring() {
|
|
18
18
|
if (this._rootCdpSession) {
|
|
@@ -69,7 +69,7 @@ export class CrashWatchdog extends BaseWatchdog {
|
|
|
69
69
|
return;
|
|
70
70
|
}
|
|
71
71
|
const crashListener = (payload) => {
|
|
72
|
-
|
|
72
|
+
this.runBackground('handle page crash', this._handlePageCrash(page, payload));
|
|
73
73
|
};
|
|
74
74
|
const requestListener = (payload) => {
|
|
75
75
|
this._trackRequestStart(payload);
|
|
@@ -215,7 +215,7 @@ export class CrashWatchdog extends BaseWatchdog {
|
|
|
215
215
|
return;
|
|
216
216
|
}
|
|
217
217
|
this._healthInterval = setInterval(() => {
|
|
218
|
-
|
|
218
|
+
this.runBackground('run health check', this._runHealthCheck());
|
|
219
219
|
}, this._healthCheckIntervalMs);
|
|
220
220
|
}
|
|
221
221
|
_stopHealthMonitor() {
|
|
@@ -77,7 +77,7 @@ export class DownloadsWatchdog extends BaseWatchdog {
|
|
|
77
77
|
this._downloadCompleteCallbacks = [];
|
|
78
78
|
this._networkDownloads.clear();
|
|
79
79
|
this._detectedDownloadUrls.clear();
|
|
80
|
-
|
|
80
|
+
this.runBackground('stop CDP download monitoring', this._stopCdpDownloadMonitoring());
|
|
81
81
|
}
|
|
82
82
|
on_TabCreatedEvent() {
|
|
83
83
|
return null;
|
|
@@ -199,7 +199,7 @@ export class DownloadsWatchdog extends BaseWatchdog {
|
|
|
199
199
|
this._downloadCompleteCallbacks = [];
|
|
200
200
|
this._networkDownloads.clear();
|
|
201
201
|
this._detectedDownloadUrls.clear();
|
|
202
|
-
|
|
202
|
+
this.runBackground('stop CDP download monitoring', this._stopCdpDownloadMonitoring());
|
|
203
203
|
}
|
|
204
204
|
_normalizeCallbackRegistration(on_start_or_options, on_progress, on_complete) {
|
|
205
205
|
if (on_start_or_options &&
|
|
@@ -229,10 +229,10 @@ export class DownloadsWatchdog extends BaseWatchdog {
|
|
|
229
229
|
await session.send?.('Network.enable');
|
|
230
230
|
this._cdpSession = session;
|
|
231
231
|
const onResponseReceived = (payload) => {
|
|
232
|
-
|
|
232
|
+
this.runBackground('handle network response', this._handleNetworkResponse(payload));
|
|
233
233
|
};
|
|
234
234
|
const onLoadingFinished = (payload) => {
|
|
235
|
-
|
|
235
|
+
this.runBackground('handle loading finished', this._handleNetworkLoadingFinished(payload));
|
|
236
236
|
};
|
|
237
237
|
session.on?.('Network.responseReceived', onResponseReceived);
|
|
238
238
|
session.on?.('Network.loadingFinished', onLoadingFinished);
|
|
@@ -125,7 +125,7 @@ export class HarRecordingWatchdog extends BaseWatchdog {
|
|
|
125
125
|
}
|
|
126
126
|
}
|
|
127
127
|
onDetached() {
|
|
128
|
-
|
|
128
|
+
this.runBackground('teardown HAR capture', this._teardownCapture());
|
|
129
129
|
}
|
|
130
130
|
_resolveConfiguredHarPath() {
|
|
131
131
|
const configuredPath = this.browser_session.browser_profile.config.record_har_path;
|
|
@@ -20,7 +20,7 @@ export class PopupsWatchdog extends BaseWatchdog {
|
|
|
20
20
|
await this._detachCdpDialogHandlers();
|
|
21
21
|
}
|
|
22
22
|
onDetached() {
|
|
23
|
-
|
|
23
|
+
this.runBackground('detach CDP dialog handlers', this._detachCdpDialogHandlers());
|
|
24
24
|
}
|
|
25
25
|
async _attachCdpDialogHandler(targetId, page) {
|
|
26
26
|
if (this._dialogListenersRegistered.has(targetId)) {
|
|
@@ -30,7 +30,7 @@ export class PopupsWatchdog extends BaseWatchdog {
|
|
|
30
30
|
const session = (await this.browser_session.get_or_create_cdp_session(page));
|
|
31
31
|
await session.send?.('Page.enable');
|
|
32
32
|
const handler = (payload) => {
|
|
33
|
-
|
|
33
|
+
this.runBackground('handle javascript dialog', this._handleJavascriptDialog(payload, session));
|
|
34
34
|
};
|
|
35
35
|
session.on?.('Page.javascriptDialogOpening', handler);
|
|
36
36
|
this._dialogListenersRegistered.add(targetId);
|
|
@@ -70,7 +70,7 @@ export class RecordingWatchdog extends BaseWatchdog {
|
|
|
70
70
|
await this._startCdpScreencastIfConfigured();
|
|
71
71
|
}
|
|
72
72
|
onDetached() {
|
|
73
|
-
|
|
73
|
+
this.runBackground('stop CDP screencast', this._stopCdpScreencastIfStarted());
|
|
74
74
|
this._detachVideoListeners();
|
|
75
75
|
}
|
|
76
76
|
_recordingDisabledByDomainPolicy() {
|
|
@@ -161,7 +161,7 @@ export class RecordingWatchdog extends BaseWatchdog {
|
|
|
161
161
|
else if (typeof page.removeListener === 'function') {
|
|
162
162
|
page.removeListener('close', listener);
|
|
163
163
|
}
|
|
164
|
-
|
|
164
|
+
this.runBackground('capture video artifact', this._captureVideoArtifact(page));
|
|
165
165
|
};
|
|
166
166
|
page.on('close', listener);
|
|
167
167
|
this._videoCloseListeners.set(page, listener);
|
|
@@ -222,6 +222,9 @@ export class RecordingWatchdog extends BaseWatchdog {
|
|
|
222
222
|
flags: 'a',
|
|
223
223
|
mode: 0o600,
|
|
224
224
|
});
|
|
225
|
+
stream.on('error', (error) => {
|
|
226
|
+
this.browser_session.logger.warning(`[RecordingWatchdog] CDP screencast stream error: ${error.message}`);
|
|
227
|
+
});
|
|
225
228
|
chmodPrivatePath(filePath, 0o600);
|
|
226
229
|
const handler = (payload) => {
|
|
227
230
|
const frameData = typeof payload?.data === 'string' ? payload.data : '';
|
|
@@ -17,6 +17,7 @@ export declare class CodeAgent {
|
|
|
17
17
|
constructor(options: CodeAgentOptions);
|
|
18
18
|
add_cell(source: string): import("./views.js").CodeCell;
|
|
19
19
|
execute_cell(source: string): Promise<import("./views.js").CodeCell>;
|
|
20
|
+
private _run_cell;
|
|
20
21
|
run(max_steps?: number): Promise<CodeAgentHistoryList>;
|
|
21
22
|
get history(): CodeAgentHistoryList;
|
|
22
23
|
close(): Promise<void>;
|
package/dist/code-use/service.js
CHANGED
|
@@ -29,7 +29,9 @@ export class CodeAgent {
|
|
|
29
29
|
return this.session.add_cell(source);
|
|
30
30
|
}
|
|
31
31
|
async execute_cell(source) {
|
|
32
|
-
|
|
32
|
+
return this._run_cell(this.add_cell(source));
|
|
33
|
+
}
|
|
34
|
+
async _run_cell(cell) {
|
|
33
35
|
const startedAt = Date.now() / 1000;
|
|
34
36
|
cell.status = 'running';
|
|
35
37
|
cell.execution_count = this.session.increment_execution_count();
|
|
@@ -92,7 +94,7 @@ export class CodeAgent {
|
|
|
92
94
|
const pending = this.session.cells.filter((cell) => cell.status === 'pending');
|
|
93
95
|
const toRun = pending.slice(0, Math.max(max_steps, 0));
|
|
94
96
|
for (const cell of toRun) {
|
|
95
|
-
await this.
|
|
97
|
+
await this._run_cell(cell);
|
|
96
98
|
}
|
|
97
99
|
return this.history;
|
|
98
100
|
}
|
|
@@ -358,7 +358,7 @@ export class Registry {
|
|
|
358
358
|
}));
|
|
359
359
|
replace_sensitive_data(params, sensitiveData, currentUrl) {
|
|
360
360
|
const secretPattern = /<secret>(.*?)<\/secret>/g;
|
|
361
|
-
const applicableSecrets =
|
|
361
|
+
const applicableSecrets = Object.create(null);
|
|
362
362
|
for (const [domainOrKey, content] of Object.entries(sensitiveData)) {
|
|
363
363
|
if (content && typeof content === 'object' && !Array.isArray(content)) {
|
|
364
364
|
if (currentUrl &&
|
|
@@ -371,6 +371,13 @@ export class Registry {
|
|
|
371
371
|
applicableSecrets[domainOrKey] = content;
|
|
372
372
|
}
|
|
373
373
|
}
|
|
374
|
+
// Filter out empty values so they are reported as missing instead of
|
|
375
|
+
// silently replacing placeholders with empty strings.
|
|
376
|
+
for (const key of Object.keys(applicableSecrets)) {
|
|
377
|
+
if (!applicableSecrets[key]) {
|
|
378
|
+
delete applicableSecrets[key];
|
|
379
|
+
}
|
|
380
|
+
}
|
|
374
381
|
const cloneValue = (value) => {
|
|
375
382
|
if (Array.isArray(value)) {
|
|
376
383
|
return value.map((item) => cloneValue(item));
|
|
@@ -383,21 +390,30 @@ export class Registry {
|
|
|
383
390
|
const processed = cloneValue(params);
|
|
384
391
|
const replaced = new Set();
|
|
385
392
|
const missing = new Set();
|
|
393
|
+
const resolveSecret = (placeholder) => {
|
|
394
|
+
replaced.add(placeholder);
|
|
395
|
+
const replacement = applicableSecrets[placeholder];
|
|
396
|
+
if (placeholder.endsWith('bu_2fa_code')) {
|
|
397
|
+
return generateTotpCode(replacement);
|
|
398
|
+
}
|
|
399
|
+
return replacement;
|
|
400
|
+
};
|
|
386
401
|
const traverse = (value) => {
|
|
387
402
|
if (typeof value === 'string') {
|
|
388
|
-
|
|
403
|
+
const withTagsReplaced = value.replace(secretPattern, (_, placeholderValue) => {
|
|
389
404
|
const placeholder = String(placeholderValue);
|
|
390
405
|
if (placeholder in applicableSecrets) {
|
|
391
|
-
|
|
392
|
-
const replacement = applicableSecrets[placeholder];
|
|
393
|
-
if (placeholder.endsWith('bu_2fa_code')) {
|
|
394
|
-
return generateTotpCode(replacement);
|
|
395
|
-
}
|
|
396
|
-
return replacement;
|
|
406
|
+
return resolveSecret(placeholder);
|
|
397
407
|
}
|
|
398
408
|
missing.add(placeholder);
|
|
399
409
|
return `<secret>${placeholder}</secret>`;
|
|
400
410
|
});
|
|
411
|
+
// Handle literal secrets ("user_name" without tags) for cases where
|
|
412
|
+
// the LLM forgets the <secret> tags but uses the exact placeholder.
|
|
413
|
+
if (withTagsReplaced in applicableSecrets) {
|
|
414
|
+
return resolveSecret(withTagsReplaced);
|
|
415
|
+
}
|
|
416
|
+
return withTagsReplaced;
|
|
401
417
|
}
|
|
402
418
|
if (Array.isArray(value)) {
|
|
403
419
|
return value.map(traverse);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AssistantMessage, ContentPartImageParam, ContentPartTextParam, SystemMessage, UserMessage, } from '../messages.js';
|
|
1
|
+
import { AssistantMessage, ContentPartImageParam, ContentPartRefusalParam, ContentPartTextParam, SystemMessage, UserMessage, } from '../messages.js';
|
|
2
2
|
export class DeepSeekMessageSerializer {
|
|
3
3
|
serialize(messages) {
|
|
4
4
|
return messages.map((message) => this.serializeMessage(message));
|
|
@@ -38,9 +38,26 @@ export class DeepSeekMessageSerializer {
|
|
|
38
38
|
};
|
|
39
39
|
}
|
|
40
40
|
if (message instanceof AssistantMessage) {
|
|
41
|
+
let content = null;
|
|
42
|
+
if (typeof message.content === 'string') {
|
|
43
|
+
content = message.content;
|
|
44
|
+
}
|
|
45
|
+
else if (Array.isArray(message.content)) {
|
|
46
|
+
content = message.content.flatMap((part) => {
|
|
47
|
+
if (part instanceof ContentPartTextParam) {
|
|
48
|
+
return [{ type: 'text', text: part.text }];
|
|
49
|
+
}
|
|
50
|
+
if (part instanceof ContentPartRefusalParam) {
|
|
51
|
+
return [
|
|
52
|
+
{ type: 'text', text: `[Refusal] ${part.refusal}` },
|
|
53
|
+
];
|
|
54
|
+
}
|
|
55
|
+
return [];
|
|
56
|
+
});
|
|
57
|
+
}
|
|
41
58
|
return {
|
|
42
59
|
role: 'assistant',
|
|
43
|
-
content
|
|
60
|
+
content,
|
|
44
61
|
// DeepSeek supports tool calls in newer models
|
|
45
62
|
tool_calls: message.tool_calls?.map((toolCall) => ({
|
|
46
63
|
id: toolCall.id,
|
package/dist/llm/google/chat.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { GoogleGenAI } from '@google/genai';
|
|
1
|
+
import { GoogleGenAI, ThinkingLevel } from '@google/genai';
|
|
2
2
|
import { ModelProviderError } from '../exceptions.js';
|
|
3
3
|
import { ChatInvokeCompletion } from '../views.js';
|
|
4
4
|
import { SchemaOptimizer, zodSchemaToJsonSchema } from '../schema.js';
|
|
@@ -19,6 +19,12 @@ const buildGoogleHttpOptions = (httpOptions) => {
|
|
|
19
19
|
resolvedHttpOptions.headers = headers;
|
|
20
20
|
return resolvedHttpOptions;
|
|
21
21
|
};
|
|
22
|
+
const googleThinkingLevelByName = {
|
|
23
|
+
minimal: ThinkingLevel.MINIMAL,
|
|
24
|
+
low: ThinkingLevel.LOW,
|
|
25
|
+
medium: ThinkingLevel.MEDIUM,
|
|
26
|
+
high: ThinkingLevel.HIGH,
|
|
27
|
+
};
|
|
22
28
|
export class ChatGoogle {
|
|
23
29
|
model;
|
|
24
30
|
provider = 'google';
|
|
@@ -212,15 +218,17 @@ export class ChatGoogle {
|
|
|
212
218
|
async ainvoke(messages, output_format, options = {}) {
|
|
213
219
|
const serializer = new GoogleMessageSerializer();
|
|
214
220
|
const { contents, systemInstruction } = serializer.serializeWithSystem(messages, this.includeSystemInUser);
|
|
215
|
-
const
|
|
221
|
+
const requestConfig = this.config
|
|
222
|
+
? { ...this.config }
|
|
223
|
+
: {};
|
|
216
224
|
if (this.temperature !== null) {
|
|
217
|
-
|
|
225
|
+
requestConfig.temperature = this.temperature;
|
|
218
226
|
}
|
|
219
227
|
if (this.topP !== null) {
|
|
220
|
-
|
|
228
|
+
requestConfig.topP = this.topP;
|
|
221
229
|
}
|
|
222
230
|
if (this.seed !== null) {
|
|
223
|
-
|
|
231
|
+
requestConfig.seed = this.seed;
|
|
224
232
|
}
|
|
225
233
|
const isGemini3Pro = this.model.includes('gemini-3-pro');
|
|
226
234
|
const isGemini3Flash = this.model.includes('gemini-3-flash');
|
|
@@ -229,18 +237,18 @@ export class ChatGoogle {
|
|
|
229
237
|
if (level === 'minimal' || level === 'medium') {
|
|
230
238
|
level = 'low';
|
|
231
239
|
}
|
|
232
|
-
|
|
233
|
-
thinkingLevel: level
|
|
240
|
+
requestConfig.thinkingConfig = {
|
|
241
|
+
thinkingLevel: googleThinkingLevelByName[level],
|
|
234
242
|
};
|
|
235
243
|
}
|
|
236
244
|
else if (isGemini3Flash) {
|
|
237
245
|
if (this.thinkingLevel !== null) {
|
|
238
|
-
|
|
239
|
-
thinkingLevel: this.thinkingLevel
|
|
246
|
+
requestConfig.thinkingConfig = {
|
|
247
|
+
thinkingLevel: googleThinkingLevelByName[this.thinkingLevel],
|
|
240
248
|
};
|
|
241
249
|
}
|
|
242
250
|
else {
|
|
243
|
-
|
|
251
|
+
requestConfig.thinkingConfig = {
|
|
244
252
|
thinkingBudget: this.thinkingBudget === null ? -1 : this.thinkingBudget,
|
|
245
253
|
};
|
|
246
254
|
}
|
|
@@ -253,11 +261,11 @@ export class ChatGoogle {
|
|
|
253
261
|
budget = -1;
|
|
254
262
|
}
|
|
255
263
|
if (budget !== null) {
|
|
256
|
-
|
|
264
|
+
requestConfig.thinkingConfig = { thinkingBudget: budget };
|
|
257
265
|
}
|
|
258
266
|
}
|
|
259
267
|
if (this.maxOutputTokens !== null) {
|
|
260
|
-
|
|
268
|
+
requestConfig.maxOutputTokens = this.maxOutputTokens;
|
|
261
269
|
}
|
|
262
270
|
// Try to get schema from output_format
|
|
263
271
|
const schemaForJson = (() => {
|
|
@@ -289,8 +297,8 @@ export class ChatGoogle {
|
|
|
289
297
|
}
|
|
290
298
|
}
|
|
291
299
|
if (cleanSchemaForJson && this.supportsStructuredOutput) {
|
|
292
|
-
|
|
293
|
-
|
|
300
|
+
requestConfig.responseMimeType = 'application/json';
|
|
301
|
+
requestConfig.responseSchema = cleanSchemaForJson;
|
|
294
302
|
}
|
|
295
303
|
const requestContents = contents.map((entry) => ({
|
|
296
304
|
...entry,
|
|
@@ -309,22 +317,25 @@ export class ChatGoogle {
|
|
|
309
317
|
}
|
|
310
318
|
}
|
|
311
319
|
}
|
|
312
|
-
const request = {
|
|
313
|
-
model: this.model,
|
|
314
|
-
contents: requestContents,
|
|
315
|
-
};
|
|
316
320
|
if (systemInstruction && !this.includeSystemInUser) {
|
|
317
|
-
|
|
321
|
+
requestConfig.systemInstruction = {
|
|
318
322
|
role: 'system',
|
|
319
323
|
parts: [{ text: systemInstruction }],
|
|
320
324
|
};
|
|
321
325
|
}
|
|
322
|
-
if (
|
|
323
|
-
|
|
326
|
+
if (options.signal) {
|
|
327
|
+
requestConfig.abortSignal = options.signal;
|
|
328
|
+
}
|
|
329
|
+
const request = {
|
|
330
|
+
model: this.model,
|
|
331
|
+
contents: requestContents,
|
|
332
|
+
};
|
|
333
|
+
if (Object.keys(requestConfig).length > 0) {
|
|
334
|
+
request.config = requestConfig;
|
|
324
335
|
}
|
|
325
336
|
for (let attempt = 0; attempt < this.maxRetries; attempt += 1) {
|
|
326
337
|
try {
|
|
327
|
-
const result = await this.client.models.generateContent(request
|
|
338
|
+
const result = await this.client.models.generateContent(request);
|
|
328
339
|
const candidate = result.candidates?.[0];
|
|
329
340
|
const textParts = candidate?.content?.parts?.filter((p) => p.text) || [];
|
|
330
341
|
const text = textParts.map((p) => p.text).join('');
|
|
@@ -45,9 +45,12 @@ export class GroqMessageSerializer {
|
|
|
45
45
|
arguments: toolCall.functionCall.arguments,
|
|
46
46
|
},
|
|
47
47
|
}));
|
|
48
|
+
// Groq expects assistant content as plain text; AssistantMessage.text
|
|
49
|
+
// already joins the text parts (refusal parts excluded).
|
|
50
|
+
const content = message.content == null ? null : message.text;
|
|
48
51
|
return {
|
|
49
52
|
role: 'assistant',
|
|
50
|
-
content
|
|
53
|
+
content,
|
|
51
54
|
tool_calls: toolCalls,
|
|
52
55
|
};
|
|
53
56
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AssistantMessage, ContentPartImageParam, ContentPartTextParam, SystemMessage, UserMessage, } from '../messages.js';
|
|
1
|
+
import { AssistantMessage, ContentPartImageParam, ContentPartRefusalParam, ContentPartTextParam, SystemMessage, UserMessage, } from '../messages.js';
|
|
2
2
|
export class OpenAIMessageSerializer {
|
|
3
3
|
serialize(messages) {
|
|
4
4
|
return messages.map((message) => this.serializeMessage(message));
|
|
@@ -45,9 +45,24 @@ export class OpenAIMessageSerializer {
|
|
|
45
45
|
arguments: toolCall.functionCall.arguments,
|
|
46
46
|
},
|
|
47
47
|
}));
|
|
48
|
+
let content = null;
|
|
49
|
+
if (typeof message.content === 'string') {
|
|
50
|
+
content = message.content;
|
|
51
|
+
}
|
|
52
|
+
else if (Array.isArray(message.content)) {
|
|
53
|
+
content = message.content.flatMap((part) => {
|
|
54
|
+
if (part instanceof ContentPartTextParam) {
|
|
55
|
+
return [{ type: 'text', text: part.text }];
|
|
56
|
+
}
|
|
57
|
+
if (part instanceof ContentPartRefusalParam) {
|
|
58
|
+
return [{ type: 'refusal', refusal: part.refusal }];
|
|
59
|
+
}
|
|
60
|
+
return [];
|
|
61
|
+
});
|
|
62
|
+
}
|
|
48
63
|
return {
|
|
49
64
|
role: 'assistant',
|
|
50
|
-
content
|
|
65
|
+
content,
|
|
51
66
|
tool_calls: toolCalls,
|
|
52
67
|
refusal: message.refusal || undefined,
|
|
53
68
|
};
|
package/dist/skill-cli/direct.js
CHANGED
|
@@ -979,7 +979,7 @@ export const run_direct_command = async (argv, options = {}) => {
|
|
|
979
979
|
writeLine(environment.stdout, 'Cleared 0 cookies');
|
|
980
980
|
}
|
|
981
981
|
else {
|
|
982
|
-
const addCookies = session.browser_context.addCookies;
|
|
982
|
+
const addCookies = session.browser_context.addCookies?.bind(session.browser_context);
|
|
983
983
|
if (blockedCookies.length > 0 && !addCookies) {
|
|
984
984
|
throw new Error('Browser context does not support preserving blocked cookies');
|
|
985
985
|
}
|
|
@@ -996,7 +996,7 @@ export const run_direct_command = async (argv, options = {}) => {
|
|
|
996
996
|
const allCookies = (await session.get_cookies?.({ include_blocked: true })) ?? [];
|
|
997
997
|
const remaining = allCookies.filter((cookie) => !cookieMatchesUrl(cookie, url));
|
|
998
998
|
const removedCount = allCookies.length - remaining.length;
|
|
999
|
-
const addCookies = session.browser_context.addCookies;
|
|
999
|
+
const addCookies = session.browser_context.addCookies?.bind(session.browser_context);
|
|
1000
1000
|
if (remaining.length > 0 && !addCookies) {
|
|
1001
1001
|
throw new Error('Browser context does not support preserving non-matching cookies');
|
|
1002
1002
|
}
|
package/dist/tokens/service.js
CHANGED
|
@@ -236,9 +236,9 @@ export class TokenCost {
|
|
|
236
236
|
return {
|
|
237
237
|
new_prompt_tokens: usage.prompt_tokens,
|
|
238
238
|
new_prompt_cost: uncachedPrompt * (pricing.input_cost_per_token ?? 0),
|
|
239
|
-
prompt_read_cached_tokens:
|
|
240
|
-
prompt_read_cached_cost: cached
|
|
241
|
-
? cached *
|
|
239
|
+
prompt_read_cached_tokens: usage.prompt_cached_tokens ?? null,
|
|
240
|
+
prompt_read_cached_cost: cached && pricing.cache_read_input_token_cost
|
|
241
|
+
? cached * pricing.cache_read_input_token_cost
|
|
242
242
|
: null,
|
|
243
243
|
prompt_cached_creation_tokens: usage.prompt_cache_creation_tokens ?? null,
|
|
244
244
|
prompt_cache_creation_cost: usage.prompt_cache_creation_tokens &&
|
package/dist/utils.js
CHANGED
|
@@ -196,7 +196,7 @@ export const is_unsafe_pattern = (pattern) => {
|
|
|
196
196
|
const [, ...rest] = pattern.split('://');
|
|
197
197
|
pattern = rest.join('://');
|
|
198
198
|
}
|
|
199
|
-
const bare_domain = pattern.
|
|
199
|
+
const bare_domain = pattern.replaceAll('.*', '').replaceAll('*.', '');
|
|
200
200
|
return bare_domain.includes('*');
|
|
201
201
|
};
|
|
202
202
|
export const merge_dicts = (a, b, path = []) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "browser-use",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.3",
|
|
4
4
|
"description": "A TypeScript-first library for programmatic browser control, designed for building AI-powered web agents.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -286,6 +286,12 @@
|
|
|
286
286
|
"test:coverage": "vitest run --coverage",
|
|
287
287
|
"test:watch": "vitest --watch",
|
|
288
288
|
"test:pack": "node scripts/smoke-pack.mjs",
|
|
289
|
+
"version:check": "node scripts/update-version.mjs --check",
|
|
290
|
+
"version:sync": "node scripts/update-version.mjs sync",
|
|
291
|
+
"version:bump": "node scripts/update-version.mjs",
|
|
292
|
+
"version:patch": "node scripts/update-version.mjs patch",
|
|
293
|
+
"version:minor": "node scripts/update-version.mjs minor",
|
|
294
|
+
"version:major": "node scripts/update-version.mjs major",
|
|
289
295
|
"check": "pnpm lint && pnpm typecheck && pnpm typecheck:test && pnpm test:unit && pnpm test:integration && pnpm test:e2e && pnpm test:pack",
|
|
290
296
|
"commit": "cz",
|
|
291
297
|
"typecheck": "tsc --noEmit",
|
|
@@ -354,7 +360,7 @@
|
|
|
354
360
|
"@types/turndown": "^5.0.6",
|
|
355
361
|
"@typescript-eslint/eslint-plugin": "^8.54.0",
|
|
356
362
|
"@typescript-eslint/parser": "^8.54.0",
|
|
357
|
-
"@vitest/coverage-v8": "^4.
|
|
363
|
+
"@vitest/coverage-v8": "^4.1.8",
|
|
358
364
|
"commitizen": "^4.3.1",
|
|
359
365
|
"cz-conventional-changelog": "^3.3.0",
|
|
360
366
|
"eslint": "^9.39.2",
|
|
@@ -366,7 +372,7 @@
|
|
|
366
372
|
"tsx": "^4.21.0",
|
|
367
373
|
"typescript": "^5.9.3",
|
|
368
374
|
"vite": "^7.3.2",
|
|
369
|
-
"vitest": "^4.
|
|
375
|
+
"vitest": "^4.1.8"
|
|
370
376
|
},
|
|
371
377
|
"pnpm": {
|
|
372
378
|
"onlyBuiltDependencies": [
|
|
@@ -384,7 +390,7 @@
|
|
|
384
390
|
"fast-xml-builder": "1.2.0",
|
|
385
391
|
"fast-xml-parser": "5.7.3",
|
|
386
392
|
"flatted": "3.4.2",
|
|
387
|
-
"hono": "4.12.
|
|
393
|
+
"hono": "4.12.23",
|
|
388
394
|
"ip-address": "10.2.0",
|
|
389
395
|
"lodash": "4.18.1",
|
|
390
396
|
"minimatch": "10.2.4",
|