browser-use 0.1.0 → 0.3.0
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 +301 -636
- package/dist/actor/element.d.ts +19 -0
- package/dist/actor/element.js +46 -0
- package/dist/actor/index.d.ts +4 -0
- package/dist/actor/index.js +4 -0
- package/dist/actor/mouse.d.ts +19 -0
- package/dist/actor/mouse.js +39 -0
- package/dist/actor/page.d.ts +29 -0
- package/dist/actor/page.js +88 -0
- package/dist/actor/utils.d.ts +4 -0
- package/dist/actor/utils.js +35 -0
- package/dist/agent/cloud-events.d.ts +18 -0
- package/dist/agent/cloud-events.js +65 -2
- package/dist/agent/gif.d.ts +1 -0
- package/dist/agent/gif.js +24 -2
- package/dist/agent/judge.d.ts +17 -0
- package/dist/agent/judge.js +197 -0
- package/dist/agent/message-manager/service.d.ts +12 -4
- package/dist/agent/message-manager/service.js +205 -39
- package/dist/agent/message-manager/utils.js +0 -1
- package/dist/agent/message-manager/views.d.ts +4 -0
- package/dist/agent/message-manager/views.js +11 -7
- package/dist/agent/prompts.d.ts +24 -3
- package/dist/agent/prompts.js +274 -59
- package/dist/agent/service.d.ts +99 -40
- package/dist/agent/service.js +2282 -474
- package/dist/agent/variable-detector.d.ts +12 -0
- package/dist/agent/variable-detector.js +211 -0
- package/dist/agent/views.d.ts +237 -17
- package/dist/agent/views.js +446 -32
- package/dist/browser/cloud/cloud.d.ts +20 -0
- package/dist/browser/cloud/cloud.js +129 -0
- package/dist/browser/cloud/index.d.ts +2 -0
- package/dist/browser/cloud/index.js +2 -0
- package/dist/browser/cloud/views.d.ts +41 -0
- package/dist/browser/cloud/views.js +35 -0
- package/dist/browser/events.d.ts +345 -0
- package/dist/browser/events.js +566 -0
- package/dist/browser/extensions.js +17 -17
- package/dist/browser/index.d.ts +4 -0
- package/dist/browser/index.js +4 -0
- package/dist/browser/profile.d.ts +8 -2
- package/dist/browser/profile.js +79 -12
- package/dist/browser/session-manager.d.ts +85 -0
- package/dist/browser/session-manager.js +208 -0
- package/dist/browser/session.d.ts +100 -8
- package/dist/browser/session.js +1102 -63
- package/dist/browser/types.d.ts +0 -2
- package/dist/browser/views.d.ts +39 -0
- package/dist/browser/views.js +32 -0
- package/dist/browser/watchdogs/aboutblank-watchdog.d.ts +12 -0
- package/dist/browser/watchdogs/aboutblank-watchdog.js +131 -0
- package/dist/browser/watchdogs/base.d.ts +21 -0
- package/dist/browser/watchdogs/base.js +81 -0
- package/dist/browser/watchdogs/cdp-session-watchdog.d.ts +14 -0
- package/dist/browser/watchdogs/cdp-session-watchdog.js +177 -0
- package/dist/browser/watchdogs/crash-watchdog.d.ts +38 -0
- package/dist/browser/watchdogs/crash-watchdog.js +296 -0
- package/dist/browser/watchdogs/default-action-watchdog.d.ts +49 -0
- package/dist/browser/watchdogs/default-action-watchdog.js +212 -0
- package/dist/browser/watchdogs/dom-watchdog.d.ts +8 -0
- package/dist/browser/watchdogs/dom-watchdog.js +31 -0
- package/dist/browser/watchdogs/downloads-watchdog.d.ts +77 -0
- package/dist/browser/watchdogs/downloads-watchdog.js +409 -0
- package/dist/browser/watchdogs/har-recording-watchdog.d.ts +19 -0
- package/dist/browser/watchdogs/har-recording-watchdog.js +317 -0
- package/dist/browser/watchdogs/index.d.ts +15 -0
- package/dist/browser/watchdogs/index.js +15 -0
- package/dist/browser/watchdogs/local-browser-watchdog.d.ts +10 -0
- package/dist/browser/watchdogs/local-browser-watchdog.js +32 -0
- package/dist/browser/watchdogs/permissions-watchdog.d.ts +8 -0
- package/dist/browser/watchdogs/permissions-watchdog.js +73 -0
- package/dist/browser/watchdogs/popups-watchdog.d.ts +13 -0
- package/dist/browser/watchdogs/popups-watchdog.js +77 -0
- package/dist/browser/watchdogs/recording-watchdog.d.ts +27 -0
- package/dist/browser/watchdogs/recording-watchdog.js +249 -0
- package/dist/browser/watchdogs/screenshot-watchdog.d.ts +6 -0
- package/dist/browser/watchdogs/screenshot-watchdog.js +13 -0
- package/dist/browser/watchdogs/security-watchdog.d.ts +10 -0
- package/dist/browser/watchdogs/security-watchdog.js +84 -0
- package/dist/browser/watchdogs/storage-state-watchdog.d.ts +24 -0
- package/dist/browser/watchdogs/storage-state-watchdog.js +288 -0
- package/dist/cli.d.ts +41 -0
- package/dist/cli.js +820 -10
- package/dist/code-use/formatting.d.ts +3 -0
- package/dist/code-use/formatting.js +18 -0
- package/dist/code-use/index.d.ts +6 -0
- package/dist/code-use/index.js +6 -0
- package/dist/code-use/namespace.d.ts +5 -0
- package/dist/code-use/namespace.js +81 -0
- package/dist/code-use/notebook-export.d.ts +3 -0
- package/dist/code-use/notebook-export.js +56 -0
- package/dist/code-use/service.d.ts +24 -0
- package/dist/code-use/service.js +104 -0
- package/dist/code-use/utils.d.ts +4 -0
- package/dist/code-use/utils.js +98 -0
- package/dist/code-use/views.d.ts +108 -0
- package/dist/code-use/views.js +165 -0
- package/dist/config.d.ts +13 -0
- package/dist/config.js +69 -3
- package/dist/controller/registry/service.d.ts +10 -1
- package/dist/controller/registry/service.js +266 -10
- package/dist/controller/registry/views.d.ts +4 -1
- package/dist/controller/registry/views.js +25 -2
- package/dist/controller/service.d.ts +10 -1
- package/dist/controller/service.js +1849 -288
- package/dist/controller/views.d.ts +78 -155
- package/dist/controller/views.js +61 -12
- package/dist/dom/history-tree-processor/service.d.ts +5 -0
- package/dist/dom/history-tree-processor/service.js +169 -14
- package/dist/dom/history-tree-processor/view.d.ts +7 -1
- package/dist/dom/history-tree-processor/view.js +10 -1
- package/dist/dom/markdown-extractor.d.ts +37 -0
- package/dist/dom/markdown-extractor.js +345 -0
- package/dist/dom/service.d.ts +3 -1
- package/dist/dom/service.js +76 -0
- package/dist/dom/views.d.ts +1 -0
- package/dist/dom/views.js +45 -0
- package/dist/event-bus.d.ts +107 -7
- package/dist/event-bus.js +313 -10
- package/dist/filesystem/file-system.d.ts +18 -0
- package/dist/filesystem/file-system.js +530 -42
- package/dist/index.d.ts +7 -0
- package/dist/index.js +6 -0
- package/dist/integrations/gmail/actions.d.ts +3 -3
- package/dist/integrations/gmail/actions.js +5 -5
- package/dist/llm/anthropic/chat.d.ts +18 -1
- package/dist/llm/anthropic/chat.js +123 -55
- package/dist/llm/anthropic/serializer.d.ts +2 -0
- package/dist/llm/anthropic/serializer.js +81 -9
- package/dist/llm/aws/chat-anthropic.d.ts +17 -0
- package/dist/llm/aws/chat-anthropic.js +129 -40
- package/dist/llm/aws/chat-bedrock.d.ts +28 -1
- package/dist/llm/aws/chat-bedrock.js +161 -34
- package/dist/llm/aws/serializer.d.ts +13 -1
- package/dist/llm/aws/serializer.js +56 -17
- package/dist/llm/azure/chat.d.ts +53 -2
- package/dist/llm/azure/chat.js +366 -53
- package/dist/llm/base.d.ts +2 -0
- package/dist/llm/browser-use/chat.d.ts +40 -0
- package/dist/llm/browser-use/chat.js +305 -0
- package/dist/llm/browser-use/index.d.ts +1 -0
- package/dist/llm/browser-use/index.js +1 -0
- package/dist/llm/cerebras/chat.d.ts +39 -0
- package/dist/llm/cerebras/chat.js +178 -0
- package/dist/llm/cerebras/index.d.ts +2 -0
- package/dist/llm/cerebras/index.js +2 -0
- package/dist/llm/cerebras/serializer.d.ts +7 -0
- package/dist/llm/cerebras/serializer.js +82 -0
- package/dist/llm/deepseek/chat.d.ts +19 -2
- package/dist/llm/deepseek/chat.js +138 -25
- package/dist/llm/google/chat.d.ts +46 -2
- package/dist/llm/google/chat.js +268 -63
- package/dist/llm/google/serializer.d.ts +9 -1
- package/dist/llm/google/serializer.js +141 -34
- package/dist/llm/groq/chat.d.ts +21 -2
- package/dist/llm/groq/chat.js +125 -26
- package/dist/llm/groq/parser.js +3 -1
- package/dist/llm/messages.d.ts +4 -4
- package/dist/llm/mistral/chat.d.ts +43 -0
- package/dist/llm/mistral/chat.js +154 -0
- package/dist/llm/mistral/index.d.ts +2 -0
- package/dist/llm/mistral/index.js +2 -0
- package/dist/llm/mistral/schema.d.ts +8 -0
- package/dist/llm/mistral/schema.js +27 -0
- package/dist/llm/models.d.ts +2 -0
- package/dist/llm/models.js +317 -0
- package/dist/llm/ollama/chat.d.ts +13 -1
- package/dist/llm/ollama/chat.js +110 -19
- package/dist/llm/ollama/serializer.d.ts +1 -0
- package/dist/llm/ollama/serializer.js +34 -12
- package/dist/llm/openai/chat.d.ts +16 -0
- package/dist/llm/openai/chat.js +94 -44
- package/dist/llm/openai/like.d.ts +5 -3
- package/dist/llm/openai/like.js +7 -3
- package/dist/llm/openai/responses-serializer.d.ts +18 -0
- package/dist/llm/openai/responses-serializer.js +72 -0
- package/dist/llm/openrouter/chat.d.ts +28 -2
- package/dist/llm/openrouter/chat.js +115 -29
- package/dist/llm/schema.d.ts +11 -1
- package/dist/llm/schema.js +81 -1
- package/dist/llm/vercel/chat.d.ts +50 -0
- package/dist/llm/vercel/chat.js +276 -0
- package/dist/llm/vercel/index.d.ts +1 -0
- package/dist/llm/vercel/index.js +1 -0
- package/dist/llm/vercel/serializer.d.ts +5 -0
- package/dist/llm/vercel/serializer.js +7 -0
- package/dist/llm/views.d.ts +2 -1
- package/dist/llm/views.js +3 -1
- package/dist/logging-config.d.ts +2 -0
- package/dist/logging-config.js +82 -29
- package/dist/mcp/client.d.ts +10 -5
- package/dist/mcp/client.js +21 -15
- package/dist/mcp/controller.d.ts +42 -3
- package/dist/mcp/controller.js +56 -31
- package/dist/mcp/server.d.ts +14 -0
- package/dist/mcp/server.js +257 -51
- package/dist/observability.js +10 -4
- package/dist/sandbox/index.d.ts +2 -0
- package/dist/sandbox/index.js +2 -0
- package/dist/sandbox/sandbox.d.ts +19 -0
- package/dist/sandbox/sandbox.js +140 -0
- package/dist/sandbox/views.d.ts +67 -0
- package/dist/sandbox/views.js +121 -0
- package/dist/skill-cli/index.d.ts +3 -0
- package/dist/skill-cli/index.js +3 -0
- package/dist/skill-cli/protocol.d.ts +30 -0
- package/dist/skill-cli/protocol.js +48 -0
- package/dist/skill-cli/server.d.ts +11 -0
- package/dist/skill-cli/server.js +85 -0
- package/dist/skill-cli/sessions.d.ts +24 -0
- package/dist/skill-cli/sessions.js +47 -0
- package/dist/skills/index.d.ts +3 -0
- package/dist/skills/index.js +3 -0
- package/dist/skills/service.d.ts +27 -0
- package/dist/skills/service.js +266 -0
- package/dist/skills/utils.d.ts +6 -0
- package/dist/skills/utils.js +53 -0
- package/dist/skills/views.d.ts +40 -0
- package/dist/skills/views.js +10 -0
- package/dist/sync/auth.js +8 -3
- package/dist/sync/service.d.ts +6 -6
- package/dist/sync/service.js +54 -89
- package/dist/telemetry/views.d.ts +20 -6
- package/dist/telemetry/views.js +23 -5
- package/dist/tokens/custom-pricing.d.ts +2 -0
- package/dist/tokens/custom-pricing.js +22 -0
- package/dist/tokens/index.d.ts +2 -0
- package/dist/tokens/index.js +2 -0
- package/dist/tokens/mappings.d.ts +1 -0
- package/dist/tokens/mappings.js +3 -0
- package/dist/tokens/service.js +30 -12
- package/dist/tools/extraction/index.d.ts +2 -0
- package/dist/tools/extraction/index.js +2 -0
- package/dist/tools/extraction/schema-utils.d.ts +6 -0
- package/dist/tools/extraction/schema-utils.js +237 -0
- package/dist/tools/extraction/views.d.ts +7 -0
- package/dist/tools/index.d.ts +5 -0
- package/dist/tools/index.js +5 -0
- package/dist/tools/registry/index.d.ts +2 -0
- package/dist/tools/registry/index.js +2 -0
- package/dist/tools/registry/service.d.ts +1 -0
- package/dist/tools/registry/service.js +1 -0
- package/dist/tools/registry/views.d.ts +1 -0
- package/dist/tools/registry/views.js +1 -0
- package/dist/tools/service.d.ts +2 -0
- package/dist/tools/service.js +1 -0
- package/dist/tools/utils.d.ts +2 -0
- package/dist/tools/utils.js +57 -0
- package/dist/tools/views.d.ts +1 -0
- package/dist/tools/views.js +1 -0
- package/dist/utils.d.ts +10 -1
- package/dist/utils.js +70 -3
- package/package.json +265 -28
- package/dist/dom/playground/process-dom.js +0 -5
- package/dist/dom/playground/test-accessibility.d.ts +0 -44
- package/dist/dom/playground/test-accessibility.js +0 -111
- /package/dist/{dom/playground/process-dom.d.ts → tools/extraction/views.js} +0 -0
|
@@ -7,46 +7,60 @@ export interface AgentTelemetryPayload {
|
|
|
7
7
|
task: string;
|
|
8
8
|
model: string;
|
|
9
9
|
model_provider: string;
|
|
10
|
-
planner_llm: string | null;
|
|
11
10
|
max_steps: number;
|
|
12
11
|
max_actions_per_step: number;
|
|
13
|
-
use_vision: boolean;
|
|
14
|
-
use_validation: boolean;
|
|
12
|
+
use_vision: boolean | 'auto';
|
|
15
13
|
version: string;
|
|
16
14
|
source: string;
|
|
17
15
|
cdp_url: string | null;
|
|
16
|
+
agent_type: string | null;
|
|
18
17
|
action_errors: BaseSequence;
|
|
19
18
|
action_history: Array<Array<Record<string, unknown>> | null> | undefined;
|
|
20
19
|
urls_visited: BaseSequence;
|
|
21
20
|
steps: number;
|
|
22
21
|
total_input_tokens: number;
|
|
22
|
+
total_output_tokens: number;
|
|
23
|
+
prompt_cached_tokens: number;
|
|
24
|
+
total_tokens: number;
|
|
23
25
|
total_duration_seconds: number;
|
|
24
26
|
success: boolean | null;
|
|
25
27
|
final_result_response: string | null;
|
|
26
28
|
error_message: string | null;
|
|
29
|
+
judge_verdict?: boolean | null;
|
|
30
|
+
judge_reasoning?: string | null;
|
|
31
|
+
judge_failure_reason?: string | null;
|
|
32
|
+
judge_reached_captcha?: boolean | null;
|
|
33
|
+
judge_impossible_task?: boolean | null;
|
|
27
34
|
}
|
|
28
35
|
export declare class AgentTelemetryEvent extends BaseTelemetryEvent implements AgentTelemetryPayload {
|
|
29
36
|
name: string;
|
|
30
37
|
task: string;
|
|
31
38
|
model: string;
|
|
32
39
|
model_provider: string;
|
|
33
|
-
planner_llm: string | null;
|
|
34
40
|
max_steps: number;
|
|
35
41
|
max_actions_per_step: number;
|
|
36
|
-
use_vision: boolean;
|
|
37
|
-
use_validation: boolean;
|
|
42
|
+
use_vision: boolean | 'auto';
|
|
38
43
|
version: string;
|
|
39
44
|
source: string;
|
|
40
45
|
cdp_url: string | null;
|
|
46
|
+
agent_type: string | null;
|
|
41
47
|
action_errors: BaseSequence;
|
|
42
48
|
action_history: Array<Array<Record<string, unknown>> | null> | undefined;
|
|
43
49
|
urls_visited: BaseSequence;
|
|
44
50
|
steps: number;
|
|
45
51
|
total_input_tokens: number;
|
|
52
|
+
total_output_tokens: number;
|
|
53
|
+
prompt_cached_tokens: number;
|
|
54
|
+
total_tokens: number;
|
|
46
55
|
total_duration_seconds: number;
|
|
47
56
|
success: boolean | null;
|
|
48
57
|
final_result_response: string | null;
|
|
49
58
|
error_message: string | null;
|
|
59
|
+
judge_verdict: boolean | null;
|
|
60
|
+
judge_reasoning: string | null;
|
|
61
|
+
judge_failure_reason: string | null;
|
|
62
|
+
judge_reached_captcha: boolean | null;
|
|
63
|
+
judge_impossible_task: boolean | null;
|
|
50
64
|
constructor(payload: AgentTelemetryPayload);
|
|
51
65
|
}
|
|
52
66
|
export interface MCPClientTelemetryPayload {
|
package/dist/telemetry/views.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
import { is_running_in_docker } from '../config.js';
|
|
1
2
|
export class BaseTelemetryEvent {
|
|
2
3
|
properties() {
|
|
3
4
|
const entries = Object.entries(this).filter(([key]) => key !== 'name');
|
|
4
|
-
return
|
|
5
|
+
return {
|
|
6
|
+
...Object.fromEntries(entries),
|
|
7
|
+
is_docker: is_running_in_docker(),
|
|
8
|
+
};
|
|
5
9
|
}
|
|
6
10
|
}
|
|
7
11
|
export class AgentTelemetryEvent extends BaseTelemetryEvent {
|
|
@@ -9,45 +13,59 @@ export class AgentTelemetryEvent extends BaseTelemetryEvent {
|
|
|
9
13
|
task;
|
|
10
14
|
model;
|
|
11
15
|
model_provider;
|
|
12
|
-
planner_llm;
|
|
13
16
|
max_steps;
|
|
14
17
|
max_actions_per_step;
|
|
15
18
|
use_vision;
|
|
16
|
-
use_validation;
|
|
17
19
|
version;
|
|
18
20
|
source;
|
|
19
21
|
cdp_url;
|
|
22
|
+
agent_type;
|
|
20
23
|
action_errors;
|
|
21
24
|
action_history;
|
|
22
25
|
urls_visited;
|
|
23
26
|
steps;
|
|
24
27
|
total_input_tokens;
|
|
28
|
+
total_output_tokens;
|
|
29
|
+
prompt_cached_tokens;
|
|
30
|
+
total_tokens;
|
|
25
31
|
total_duration_seconds;
|
|
26
32
|
success;
|
|
27
33
|
final_result_response;
|
|
28
34
|
error_message;
|
|
35
|
+
judge_verdict;
|
|
36
|
+
judge_reasoning;
|
|
37
|
+
judge_failure_reason;
|
|
38
|
+
judge_reached_captcha;
|
|
39
|
+
judge_impossible_task;
|
|
29
40
|
constructor(payload) {
|
|
30
41
|
super();
|
|
31
42
|
this.task = payload.task;
|
|
32
43
|
this.model = payload.model;
|
|
33
44
|
this.model_provider = payload.model_provider;
|
|
34
|
-
this.planner_llm = payload.planner_llm;
|
|
35
45
|
this.max_steps = payload.max_steps;
|
|
36
46
|
this.max_actions_per_step = payload.max_actions_per_step;
|
|
37
47
|
this.use_vision = payload.use_vision;
|
|
38
|
-
this.use_validation = payload.use_validation;
|
|
39
48
|
this.version = payload.version;
|
|
40
49
|
this.source = payload.source;
|
|
41
50
|
this.cdp_url = payload.cdp_url;
|
|
51
|
+
this.agent_type = payload.agent_type;
|
|
42
52
|
this.action_errors = payload.action_errors;
|
|
43
53
|
this.action_history = payload.action_history;
|
|
44
54
|
this.urls_visited = payload.urls_visited;
|
|
45
55
|
this.steps = payload.steps;
|
|
46
56
|
this.total_input_tokens = payload.total_input_tokens;
|
|
57
|
+
this.total_output_tokens = payload.total_output_tokens;
|
|
58
|
+
this.prompt_cached_tokens = payload.prompt_cached_tokens;
|
|
59
|
+
this.total_tokens = payload.total_tokens;
|
|
47
60
|
this.total_duration_seconds = payload.total_duration_seconds;
|
|
48
61
|
this.success = payload.success;
|
|
49
62
|
this.final_result_response = payload.final_result_response;
|
|
50
63
|
this.error_message = payload.error_message;
|
|
64
|
+
this.judge_verdict = payload.judge_verdict ?? null;
|
|
65
|
+
this.judge_reasoning = payload.judge_reasoning ?? null;
|
|
66
|
+
this.judge_failure_reason = payload.judge_failure_reason ?? null;
|
|
67
|
+
this.judge_reached_captcha = payload.judge_reached_captcha ?? null;
|
|
68
|
+
this.judge_impossible_task = payload.judge_impossible_task ?? null;
|
|
51
69
|
}
|
|
52
70
|
}
|
|
53
71
|
export class MCPClientTelemetryEvent extends BaseTelemetryEvent {
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export const CUSTOM_MODEL_PRICING = {
|
|
2
|
+
'bu-1-0': {
|
|
3
|
+
input_cost_per_token: 0.2 / 1_000_000,
|
|
4
|
+
output_cost_per_token: 2.0 / 1_000_000,
|
|
5
|
+
cache_read_input_token_cost: 0.02 / 1_000_000,
|
|
6
|
+
cache_creation_input_token_cost: null,
|
|
7
|
+
max_tokens: null,
|
|
8
|
+
max_input_tokens: null,
|
|
9
|
+
max_output_tokens: null,
|
|
10
|
+
},
|
|
11
|
+
'bu-2-0': {
|
|
12
|
+
input_cost_per_token: 0.6 / 1_000_000,
|
|
13
|
+
output_cost_per_token: 3.5 / 1_000_000,
|
|
14
|
+
cache_read_input_token_cost: 0.06 / 1_000_000,
|
|
15
|
+
cache_creation_input_token_cost: null,
|
|
16
|
+
max_tokens: null,
|
|
17
|
+
max_input_tokens: null,
|
|
18
|
+
max_output_tokens: null,
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
CUSTOM_MODEL_PRICING['bu-latest'] = CUSTOM_MODEL_PRICING['bu-1-0'];
|
|
22
|
+
CUSTOM_MODEL_PRICING.smart = CUSTOM_MODEL_PRICING['bu-1-0'];
|
package/dist/tokens/index.d.ts
CHANGED
package/dist/tokens/index.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const MODEL_TO_LITELLM: Record<string, string>;
|
package/dist/tokens/service.js
CHANGED
|
@@ -4,6 +4,9 @@ import { encode } from 'gpt-tokenizer';
|
|
|
4
4
|
import axios from 'axios';
|
|
5
5
|
import { CONFIG } from '../config.js';
|
|
6
6
|
import { createLogger } from '../logging-config.js';
|
|
7
|
+
import { create_task_with_error_handling } from '../utils.js';
|
|
8
|
+
import { CUSTOM_MODEL_PRICING } from './custom-pricing.js';
|
|
9
|
+
import { MODEL_TO_LITELLM } from './mappings.js';
|
|
7
10
|
const logger = createLogger('browser_use.tokens');
|
|
8
11
|
const costLogger = createLogger('browser_use.tokens.cost');
|
|
9
12
|
const PRICING_URL = 'https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json';
|
|
@@ -66,7 +69,7 @@ export class TokenCost {
|
|
|
66
69
|
}
|
|
67
70
|
}
|
|
68
71
|
catch (error) {
|
|
69
|
-
logger.
|
|
72
|
+
logger.debug(`Failed to load token pricing cache: ${error.message}`);
|
|
70
73
|
}
|
|
71
74
|
await this.fetchAndCachePricing();
|
|
72
75
|
}
|
|
@@ -125,7 +128,7 @@ export class TokenCost {
|
|
|
125
128
|
await fs.promises.writeFile(path.join(this.cacheDir, fileName), JSON.stringify(cached, null, 2));
|
|
126
129
|
}
|
|
127
130
|
catch (error) {
|
|
128
|
-
logger.
|
|
131
|
+
logger.debug(`Failed to fetch LiteLLM pricing: ${error.message}`);
|
|
129
132
|
this.pricingData = this.pricingData ?? {};
|
|
130
133
|
}
|
|
131
134
|
}
|
|
@@ -145,16 +148,18 @@ export class TokenCost {
|
|
|
145
148
|
this.registeredLlms.add(llm);
|
|
146
149
|
const original = llm.ainvoke.bind(llm);
|
|
147
150
|
this.originalAinvoke.set(llm, original);
|
|
148
|
-
|
|
149
|
-
llm.ainvoke = async function (...args) {
|
|
151
|
+
llm.ainvoke = (async (...args) => {
|
|
150
152
|
// @ts-ignore - Spread operator type compatibility
|
|
151
153
|
const result = await original(...args);
|
|
152
154
|
if (result?.usage) {
|
|
153
|
-
const usageEntry =
|
|
154
|
-
|
|
155
|
+
const usageEntry = this.addUsage(llm.model, result.usage);
|
|
156
|
+
create_task_with_error_handling(this.logUsage(llm.model, usageEntry), {
|
|
157
|
+
name: 'log_token_usage',
|
|
158
|
+
suppress_exceptions: true,
|
|
159
|
+
});
|
|
155
160
|
}
|
|
156
161
|
return result;
|
|
157
|
-
};
|
|
162
|
+
});
|
|
158
163
|
return llm;
|
|
159
164
|
}
|
|
160
165
|
async logUsage(model, entry) {
|
|
@@ -168,7 +173,7 @@ export class TokenCost {
|
|
|
168
173
|
const completionSection = this.includeCost && cost && cost.completion_cost > 0
|
|
169
174
|
? `📤 ${ansi.green}${completionTokensFmt} ($${cost.completion_cost.toFixed(4)})${ansi.reset}`
|
|
170
175
|
: `📤 ${ansi.green}${completionTokensFmt}${ansi.reset}`;
|
|
171
|
-
costLogger.
|
|
176
|
+
costLogger.debug(`🧠 ${ansi.cyan}${model}${ansi.reset} | ${inputPart} | ${completionSection}`);
|
|
172
177
|
}
|
|
173
178
|
buildInputDisplay(usage, cost) {
|
|
174
179
|
const parts = [];
|
|
@@ -245,11 +250,25 @@ export class TokenCost {
|
|
|
245
250
|
};
|
|
246
251
|
}
|
|
247
252
|
async getModelPricing(modelName) {
|
|
253
|
+
const customPricing = CUSTOM_MODEL_PRICING[modelName];
|
|
254
|
+
if (customPricing) {
|
|
255
|
+
return {
|
|
256
|
+
model: modelName,
|
|
257
|
+
input_cost_per_token: customPricing.input_cost_per_token ?? null,
|
|
258
|
+
output_cost_per_token: customPricing.output_cost_per_token ?? null,
|
|
259
|
+
cache_read_input_token_cost: customPricing.cache_read_input_token_cost ?? null,
|
|
260
|
+
cache_creation_input_token_cost: customPricing.cache_creation_input_token_cost ?? null,
|
|
261
|
+
max_tokens: customPricing.max_tokens ?? null,
|
|
262
|
+
max_input_tokens: customPricing.max_input_tokens ?? null,
|
|
263
|
+
max_output_tokens: customPricing.max_output_tokens ?? null,
|
|
264
|
+
};
|
|
265
|
+
}
|
|
248
266
|
await this.ensurePricingLoaded();
|
|
249
267
|
if (!this.pricingData) {
|
|
250
268
|
return null;
|
|
251
269
|
}
|
|
252
|
-
const
|
|
270
|
+
const litellmModelName = MODEL_TO_LITELLM[modelName] ?? modelName;
|
|
271
|
+
const pricing = this.pricingData[litellmModelName];
|
|
253
272
|
if (!pricing) {
|
|
254
273
|
return null;
|
|
255
274
|
}
|
|
@@ -368,9 +387,8 @@ export class TokenCost {
|
|
|
368
387
|
const completionCostPart = this.includeCost && summary.total_completion_cost > 0
|
|
369
388
|
? ` ($${summary.total_completion_cost.toFixed(4)})`
|
|
370
389
|
: '';
|
|
371
|
-
costLogger.
|
|
390
|
+
costLogger.debug(`💲 ${ansi.bold}Total Usage Summary${ansi.reset}: ${ansi.blue}${totalTokens} tokens${ansi.reset}${totalCostPart} | ` +
|
|
372
391
|
`⬅️ ${ansi.yellow}${promptTokens}${promptCostPart}${ansi.reset} | ➡️ ${ansi.green}${completionTokens}${completionCostPart}${ansi.reset}`);
|
|
373
|
-
costLogger.info(`📊 ${ansi.bold}Per-Model Usage Breakdown${ansi.reset}:`);
|
|
374
392
|
for (const [model, stats] of Object.entries(summary.by_model)) {
|
|
375
393
|
const totalFmt = this.formatTokens(stats.total_tokens);
|
|
376
394
|
const promptFmt = this.formatTokens(stats.prompt_tokens);
|
|
@@ -379,7 +397,7 @@ export class TokenCost {
|
|
|
379
397
|
const costPart = this.includeCost && stats.cost > 0
|
|
380
398
|
? ` ($${stats.cost.toFixed(4)})`
|
|
381
399
|
: '';
|
|
382
|
-
costLogger.
|
|
400
|
+
costLogger.debug(` 🤖 ${ansi.cyan}${model}${ansi.reset}: ${ansi.blue}${totalFmt} tokens${ansi.reset}${costPart} | ` +
|
|
383
401
|
`⬅️ ${ansi.yellow}${promptFmt}${ansi.reset} | ➡️ ${ansi.green}${completionFmt}${ansi.reset} | ` +
|
|
384
402
|
`📞 ${stats.invocations} calls | 📈 ${avgFmt}/call`);
|
|
385
403
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const findUnsupportedJsonSchemaKeyword: (schema: unknown) => string | null;
|
|
3
|
+
export declare const schemaDictToZodSchema: (schema: unknown) => z.ZodTypeAny;
|
|
4
|
+
export declare const resolveDefaultForSchema: (schema: unknown) => unknown;
|
|
5
|
+
export declare const normalizeStructuredDataBySchema: (value: unknown, schema: unknown) => unknown;
|
|
6
|
+
export declare const schema_dict_to_zod_schema: (schema: unknown) => z.ZodTypeAny;
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
const UNSUPPORTED_KEYWORDS = new Set([
|
|
3
|
+
'$ref',
|
|
4
|
+
'allOf',
|
|
5
|
+
'anyOf',
|
|
6
|
+
'oneOf',
|
|
7
|
+
'not',
|
|
8
|
+
'$defs',
|
|
9
|
+
'definitions',
|
|
10
|
+
'if',
|
|
11
|
+
'then',
|
|
12
|
+
'else',
|
|
13
|
+
'dependentSchemas',
|
|
14
|
+
'dependentRequired',
|
|
15
|
+
]);
|
|
16
|
+
const PRIMITIVE_DEFAULTS = {
|
|
17
|
+
string: '',
|
|
18
|
+
number: 0.0,
|
|
19
|
+
integer: 0,
|
|
20
|
+
boolean: false,
|
|
21
|
+
};
|
|
22
|
+
const isRecord = (value) => !!value && typeof value === 'object' && !Array.isArray(value);
|
|
23
|
+
const getTypeList = (schema) => {
|
|
24
|
+
const schemaType = schema.type;
|
|
25
|
+
if (Array.isArray(schemaType)) {
|
|
26
|
+
return schemaType.map((item) => String(item).toLowerCase());
|
|
27
|
+
}
|
|
28
|
+
if (typeof schemaType === 'string' && schemaType.trim().length > 0) {
|
|
29
|
+
return [schemaType.toLowerCase()];
|
|
30
|
+
}
|
|
31
|
+
return ['string'];
|
|
32
|
+
};
|
|
33
|
+
export const findUnsupportedJsonSchemaKeyword = (schema) => {
|
|
34
|
+
if (Array.isArray(schema)) {
|
|
35
|
+
for (const item of schema) {
|
|
36
|
+
const found = findUnsupportedJsonSchemaKeyword(item);
|
|
37
|
+
if (found) {
|
|
38
|
+
return found;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
if (!isRecord(schema)) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
for (const [key, value] of Object.entries(schema)) {
|
|
47
|
+
if (UNSUPPORTED_KEYWORDS.has(key)) {
|
|
48
|
+
return key;
|
|
49
|
+
}
|
|
50
|
+
const found = findUnsupportedJsonSchemaKeyword(value);
|
|
51
|
+
if (found) {
|
|
52
|
+
return found;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return null;
|
|
56
|
+
};
|
|
57
|
+
const checkUnsupported = (schema) => {
|
|
58
|
+
const unsupported = findUnsupportedJsonSchemaKeyword(schema);
|
|
59
|
+
if (unsupported) {
|
|
60
|
+
throw new Error(`Unsupported JSON Schema keyword: ${unsupported}`);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
const resolveType = (schema, name) => {
|
|
64
|
+
checkUnsupported(schema);
|
|
65
|
+
const typeList = getTypeList(schema);
|
|
66
|
+
if (Array.isArray(schema.enum)) {
|
|
67
|
+
return z.string();
|
|
68
|
+
}
|
|
69
|
+
if (typeList.includes('object')) {
|
|
70
|
+
const properties = isRecord(schema.properties)
|
|
71
|
+
? schema.properties
|
|
72
|
+
: null;
|
|
73
|
+
const base = properties
|
|
74
|
+
? buildObjectSchema(schema, name)
|
|
75
|
+
: z.record(z.string(), z.any());
|
|
76
|
+
return typeList.includes('null') || schema.nullable === true
|
|
77
|
+
? base.nullable()
|
|
78
|
+
: base;
|
|
79
|
+
}
|
|
80
|
+
if (typeList.includes('array')) {
|
|
81
|
+
const items = isRecord(schema.items)
|
|
82
|
+
? resolveType(schema.items, `${name}_item`)
|
|
83
|
+
: z.any();
|
|
84
|
+
const arraySchema = z.array(items);
|
|
85
|
+
return typeList.includes('null') || schema.nullable === true
|
|
86
|
+
? arraySchema.nullable()
|
|
87
|
+
: arraySchema;
|
|
88
|
+
}
|
|
89
|
+
let primitive = z.string();
|
|
90
|
+
if (typeList.includes('integer')) {
|
|
91
|
+
primitive = z.number().int();
|
|
92
|
+
}
|
|
93
|
+
else if (typeList.includes('number')) {
|
|
94
|
+
primitive = z.number();
|
|
95
|
+
}
|
|
96
|
+
else if (typeList.includes('boolean')) {
|
|
97
|
+
primitive = z.boolean();
|
|
98
|
+
}
|
|
99
|
+
else if (typeList.includes('null')) {
|
|
100
|
+
primitive = z.null();
|
|
101
|
+
}
|
|
102
|
+
else if (typeList.includes('string')) {
|
|
103
|
+
primitive = z.string();
|
|
104
|
+
}
|
|
105
|
+
if (schema.nullable === true && !typeList.includes('null')) {
|
|
106
|
+
return primitive.nullable();
|
|
107
|
+
}
|
|
108
|
+
return primitive;
|
|
109
|
+
};
|
|
110
|
+
const applyOptionalDefaults = (propertySchema, propertyType) => {
|
|
111
|
+
if (Object.prototype.hasOwnProperty.call(propertySchema, 'default')) {
|
|
112
|
+
return propertyType.default(propertySchema.default);
|
|
113
|
+
}
|
|
114
|
+
const typeList = getTypeList(propertySchema);
|
|
115
|
+
const allowsNull = propertySchema.nullable === true || typeList.includes('null');
|
|
116
|
+
if (allowsNull) {
|
|
117
|
+
return propertyType.nullable().default(null);
|
|
118
|
+
}
|
|
119
|
+
if (Array.isArray(propertySchema.enum)) {
|
|
120
|
+
return propertyType.nullable().default(null);
|
|
121
|
+
}
|
|
122
|
+
if (typeList.includes('array')) {
|
|
123
|
+
return propertyType.default([]);
|
|
124
|
+
}
|
|
125
|
+
const primitiveType = typeList.find((item) => item in PRIMITIVE_DEFAULTS);
|
|
126
|
+
if (primitiveType) {
|
|
127
|
+
return propertyType.default(PRIMITIVE_DEFAULTS[primitiveType]);
|
|
128
|
+
}
|
|
129
|
+
return propertyType.nullable().default(null);
|
|
130
|
+
};
|
|
131
|
+
const buildObjectSchema = (schema, name) => {
|
|
132
|
+
checkUnsupported(schema);
|
|
133
|
+
const properties = isRecord(schema.properties)
|
|
134
|
+
? schema.properties
|
|
135
|
+
: {};
|
|
136
|
+
const required = new Set(Array.isArray(schema.required)
|
|
137
|
+
? schema.required
|
|
138
|
+
.map((item) => String(item))
|
|
139
|
+
.filter((item) => item.length > 0)
|
|
140
|
+
: []);
|
|
141
|
+
const shape = {};
|
|
142
|
+
for (const [propertyName, propertySchema] of Object.entries(properties)) {
|
|
143
|
+
if (!isRecord(propertySchema)) {
|
|
144
|
+
shape[propertyName] = z.any();
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
const propertyType = resolveType(propertySchema, `${name}_${propertyName}`);
|
|
148
|
+
if (required.has(propertyName)) {
|
|
149
|
+
shape[propertyName] = propertyType;
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
shape[propertyName] = applyOptionalDefaults(propertySchema, propertyType);
|
|
153
|
+
}
|
|
154
|
+
return z.object(shape).strict();
|
|
155
|
+
};
|
|
156
|
+
export const schemaDictToZodSchema = (schema) => {
|
|
157
|
+
if (!isRecord(schema)) {
|
|
158
|
+
throw new Error('Top-level schema must be an object');
|
|
159
|
+
}
|
|
160
|
+
checkUnsupported(schema);
|
|
161
|
+
const typeList = getTypeList(schema);
|
|
162
|
+
if (!typeList.includes('object')) {
|
|
163
|
+
throw new Error('Top-level schema must have type "object"');
|
|
164
|
+
}
|
|
165
|
+
if (!isRecord(schema.properties) || !Object.keys(schema.properties).length) {
|
|
166
|
+
throw new Error('Top-level schema must have at least one property');
|
|
167
|
+
}
|
|
168
|
+
const modelName = typeof schema.title === 'string' && schema.title.trim().length > 0
|
|
169
|
+
? schema.title
|
|
170
|
+
: 'DynamicExtractionModel';
|
|
171
|
+
return buildObjectSchema(schema, modelName);
|
|
172
|
+
};
|
|
173
|
+
export const resolveDefaultForSchema = (schema) => {
|
|
174
|
+
if (!isRecord(schema)) {
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
if (Object.prototype.hasOwnProperty.call(schema, 'default')) {
|
|
178
|
+
return schema.default;
|
|
179
|
+
}
|
|
180
|
+
const typeList = getTypeList(schema);
|
|
181
|
+
const allowsNull = schema.nullable === true || typeList.includes('null');
|
|
182
|
+
if (allowsNull) {
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
if (Array.isArray(schema.enum)) {
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
if (typeList.includes('array')) {
|
|
189
|
+
return [];
|
|
190
|
+
}
|
|
191
|
+
const primitiveType = typeList.find((item) => item in PRIMITIVE_DEFAULTS);
|
|
192
|
+
if (primitiveType) {
|
|
193
|
+
return PRIMITIVE_DEFAULTS[primitiveType];
|
|
194
|
+
}
|
|
195
|
+
return null;
|
|
196
|
+
};
|
|
197
|
+
export const normalizeStructuredDataBySchema = (value, schema) => {
|
|
198
|
+
if (!isRecord(schema)) {
|
|
199
|
+
return value;
|
|
200
|
+
}
|
|
201
|
+
const typeList = getTypeList(schema);
|
|
202
|
+
if (typeList.includes('object')) {
|
|
203
|
+
const properties = isRecord(schema.properties)
|
|
204
|
+
? schema.properties
|
|
205
|
+
: {};
|
|
206
|
+
const required = new Set(Array.isArray(schema.required)
|
|
207
|
+
? schema.required
|
|
208
|
+
.map((item) => String(item))
|
|
209
|
+
.filter((item) => item.length > 0)
|
|
210
|
+
: []);
|
|
211
|
+
const source = isRecord(value) ? value : {};
|
|
212
|
+
const normalized = {};
|
|
213
|
+
for (const [propertyName, propertySchema] of Object.entries(properties)) {
|
|
214
|
+
if (Object.prototype.hasOwnProperty.call(source, propertyName)) {
|
|
215
|
+
normalized[propertyName] = normalizeStructuredDataBySchema(source[propertyName], propertySchema);
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
if (required.has(propertyName)) {
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
normalized[propertyName] = resolveDefaultForSchema(propertySchema);
|
|
222
|
+
}
|
|
223
|
+
for (const [propertyName, propertyValue] of Object.entries(source)) {
|
|
224
|
+
if (!Object.prototype.hasOwnProperty.call(normalized, propertyName)) {
|
|
225
|
+
normalized[propertyName] = propertyValue;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return normalized;
|
|
229
|
+
}
|
|
230
|
+
if (typeList.includes('array') &&
|
|
231
|
+
Array.isArray(value) &&
|
|
232
|
+
isRecord(schema.items)) {
|
|
233
|
+
return value.map((item) => normalizeStructuredDataBySchema(item, schema.items));
|
|
234
|
+
}
|
|
235
|
+
return value;
|
|
236
|
+
};
|
|
237
|
+
export const schema_dict_to_zod_schema = schemaDictToZodSchema;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../../controller/registry/service.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../../controller/registry/service.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../../controller/registry/views.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../../controller/registry/views.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Controller as Tools } from '../controller/service.js';
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { DOMElementNode } from '../dom/views.js';
|
|
2
|
+
const normalizeBoolLike = (value) => {
|
|
3
|
+
const normalized = String(value ?? '')
|
|
4
|
+
.trim()
|
|
5
|
+
.toLowerCase();
|
|
6
|
+
return normalized === 'true' || normalized === 'checked' || normalized === '';
|
|
7
|
+
};
|
|
8
|
+
const summarizeText = (text, maxLength = 30) => {
|
|
9
|
+
const compact = text.replace(/\s+/g, ' ').trim();
|
|
10
|
+
if (!compact) {
|
|
11
|
+
return '';
|
|
12
|
+
}
|
|
13
|
+
return compact.length > maxLength
|
|
14
|
+
? `${compact.slice(0, maxLength)}...`
|
|
15
|
+
: compact;
|
|
16
|
+
};
|
|
17
|
+
export const getClickDescription = (node) => {
|
|
18
|
+
const parts = [node.tag_name];
|
|
19
|
+
const inputType = node.attributes.type;
|
|
20
|
+
if (node.tag_name === 'input' && inputType) {
|
|
21
|
+
parts.push(`type=${inputType}`);
|
|
22
|
+
if (inputType === 'checkbox') {
|
|
23
|
+
const isChecked = normalizeBoolLike(node.attributes.checked);
|
|
24
|
+
parts.push(`checkbox-state=${isChecked ? 'checked' : 'unchecked'}`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const role = node.attributes.role;
|
|
28
|
+
if (role) {
|
|
29
|
+
parts.push(`role=${role}`);
|
|
30
|
+
if (role === 'checkbox') {
|
|
31
|
+
const isChecked = normalizeBoolLike(node.attributes['aria-checked']);
|
|
32
|
+
parts.push(`checkbox-state=${isChecked ? 'checked' : 'unchecked'}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (['label', 'span', 'div'].includes(node.tag_name) &&
|
|
36
|
+
!parts.some((part) => part.startsWith('type='))) {
|
|
37
|
+
const hiddenCheckboxChild = node.children.find((child) => child instanceof DOMElementNode &&
|
|
38
|
+
child.tag_name === 'input' &&
|
|
39
|
+
child.attributes.type === 'checkbox' &&
|
|
40
|
+
!child.is_visible);
|
|
41
|
+
if (hiddenCheckboxChild) {
|
|
42
|
+
const isChecked = normalizeBoolLike(hiddenCheckboxChild.attributes.checked);
|
|
43
|
+
parts.push(`checkbox-state=${isChecked ? 'checked' : 'unchecked'}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
const text = summarizeText(node.get_all_text_till_next_clickable_element());
|
|
47
|
+
if (text) {
|
|
48
|
+
parts.push(`"${text}"`);
|
|
49
|
+
}
|
|
50
|
+
for (const attribute of ['id', 'name', 'aria-label']) {
|
|
51
|
+
const value = node.attributes[attribute];
|
|
52
|
+
if (value && value.trim().length > 0) {
|
|
53
|
+
parts.push(`${attribute}=${value.slice(0, 20)}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return parts.join(' ');
|
|
57
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../controller/views.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../controller/views.js';
|