browser-use 0.0.1 → 0.1.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.
Files changed (200) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +761 -0
  3. package/dist/agent/cloud-events.d.ts +264 -0
  4. package/dist/agent/cloud-events.js +318 -0
  5. package/dist/agent/gif.d.ts +15 -0
  6. package/dist/agent/gif.js +215 -0
  7. package/dist/agent/index.d.ts +8 -0
  8. package/dist/agent/index.js +8 -0
  9. package/dist/agent/message-manager/service.d.ts +30 -0
  10. package/dist/agent/message-manager/service.js +208 -0
  11. package/dist/agent/message-manager/utils.d.ts +2 -0
  12. package/dist/agent/message-manager/utils.js +41 -0
  13. package/dist/agent/message-manager/views.d.ts +26 -0
  14. package/dist/agent/message-manager/views.js +73 -0
  15. package/dist/agent/prompts.d.ts +52 -0
  16. package/dist/agent/prompts.js +259 -0
  17. package/dist/agent/service.d.ts +290 -0
  18. package/dist/agent/service.js +2200 -0
  19. package/dist/agent/views.d.ts +741 -0
  20. package/dist/agent/views.js +537 -0
  21. package/dist/browser/browser.d.ts +7 -0
  22. package/dist/browser/browser.js +5 -0
  23. package/dist/browser/context.d.ts +8 -0
  24. package/dist/browser/context.js +4 -0
  25. package/dist/browser/dvd-screensaver.d.ts +101 -0
  26. package/dist/browser/dvd-screensaver.js +270 -0
  27. package/dist/browser/extensions.d.ts +63 -0
  28. package/dist/browser/extensions.js +359 -0
  29. package/dist/browser/index.d.ts +10 -0
  30. package/dist/browser/index.js +9 -0
  31. package/dist/browser/playwright-manager.d.ts +47 -0
  32. package/dist/browser/playwright-manager.js +146 -0
  33. package/dist/browser/profile.d.ts +196 -0
  34. package/dist/browser/profile.js +815 -0
  35. package/dist/browser/session.d.ts +505 -0
  36. package/dist/browser/session.js +3409 -0
  37. package/dist/browser/types.d.ts +1184 -0
  38. package/dist/browser/types.js +1 -0
  39. package/dist/browser/utils.d.ts +1 -0
  40. package/dist/browser/utils.js +19 -0
  41. package/dist/browser/views.d.ts +78 -0
  42. package/dist/browser/views.js +72 -0
  43. package/dist/cli.d.ts +2 -0
  44. package/dist/cli.js +44 -0
  45. package/dist/config.d.ts +108 -0
  46. package/dist/config.js +430 -0
  47. package/dist/controller/index.d.ts +3 -0
  48. package/dist/controller/index.js +3 -0
  49. package/dist/controller/registry/index.d.ts +2 -0
  50. package/dist/controller/registry/index.js +2 -0
  51. package/dist/controller/registry/service.d.ts +45 -0
  52. package/dist/controller/registry/service.js +184 -0
  53. package/dist/controller/registry/views.d.ts +55 -0
  54. package/dist/controller/registry/views.js +174 -0
  55. package/dist/controller/service.d.ts +49 -0
  56. package/dist/controller/service.js +1176 -0
  57. package/dist/controller/views.d.ts +241 -0
  58. package/dist/controller/views.js +88 -0
  59. package/dist/dom/clickable-element-processor/service.d.ts +11 -0
  60. package/dist/dom/clickable-element-processor/service.js +60 -0
  61. package/dist/dom/dom_tree/index.js +1400 -0
  62. package/dist/dom/history-tree-processor/service.d.ts +14 -0
  63. package/dist/dom/history-tree-processor/service.js +75 -0
  64. package/dist/dom/history-tree-processor/view.d.ts +54 -0
  65. package/dist/dom/history-tree-processor/view.js +56 -0
  66. package/dist/dom/playground/extraction.d.ts +19 -0
  67. package/dist/dom/playground/extraction.js +187 -0
  68. package/dist/dom/playground/process-dom.d.ts +1 -0
  69. package/dist/dom/playground/process-dom.js +5 -0
  70. package/dist/dom/playground/test-accessibility.d.ts +44 -0
  71. package/dist/dom/playground/test-accessibility.js +111 -0
  72. package/dist/dom/service.d.ts +19 -0
  73. package/dist/dom/service.js +227 -0
  74. package/dist/dom/utils.d.ts +1 -0
  75. package/dist/dom/utils.js +6 -0
  76. package/dist/dom/views.d.ts +61 -0
  77. package/dist/dom/views.js +247 -0
  78. package/dist/event-bus.d.ts +11 -0
  79. package/dist/event-bus.js +19 -0
  80. package/dist/exceptions.d.ts +10 -0
  81. package/dist/exceptions.js +22 -0
  82. package/dist/filesystem/file-system.d.ts +68 -0
  83. package/dist/filesystem/file-system.js +412 -0
  84. package/dist/filesystem/index.d.ts +1 -0
  85. package/dist/filesystem/index.js +1 -0
  86. package/dist/index.d.ts +31 -0
  87. package/dist/index.js +33 -0
  88. package/dist/integrations/gmail/actions.d.ts +12 -0
  89. package/dist/integrations/gmail/actions.js +113 -0
  90. package/dist/integrations/gmail/index.d.ts +2 -0
  91. package/dist/integrations/gmail/index.js +2 -0
  92. package/dist/integrations/gmail/service.d.ts +61 -0
  93. package/dist/integrations/gmail/service.js +260 -0
  94. package/dist/llm/anthropic/chat.d.ts +28 -0
  95. package/dist/llm/anthropic/chat.js +126 -0
  96. package/dist/llm/anthropic/index.d.ts +2 -0
  97. package/dist/llm/anthropic/index.js +2 -0
  98. package/dist/llm/anthropic/serializer.d.ts +68 -0
  99. package/dist/llm/anthropic/serializer.js +285 -0
  100. package/dist/llm/aws/chat-anthropic.d.ts +61 -0
  101. package/dist/llm/aws/chat-anthropic.js +176 -0
  102. package/dist/llm/aws/chat-bedrock.d.ts +15 -0
  103. package/dist/llm/aws/chat-bedrock.js +80 -0
  104. package/dist/llm/aws/index.d.ts +3 -0
  105. package/dist/llm/aws/index.js +3 -0
  106. package/dist/llm/aws/serializer.d.ts +5 -0
  107. package/dist/llm/aws/serializer.js +68 -0
  108. package/dist/llm/azure/chat.d.ts +15 -0
  109. package/dist/llm/azure/chat.js +83 -0
  110. package/dist/llm/azure/index.d.ts +1 -0
  111. package/dist/llm/azure/index.js +1 -0
  112. package/dist/llm/base.d.ts +16 -0
  113. package/dist/llm/base.js +1 -0
  114. package/dist/llm/deepseek/chat.d.ts +15 -0
  115. package/dist/llm/deepseek/chat.js +51 -0
  116. package/dist/llm/deepseek/index.d.ts +2 -0
  117. package/dist/llm/deepseek/index.js +2 -0
  118. package/dist/llm/deepseek/serializer.d.ts +6 -0
  119. package/dist/llm/deepseek/serializer.js +57 -0
  120. package/dist/llm/exceptions.d.ts +10 -0
  121. package/dist/llm/exceptions.js +18 -0
  122. package/dist/llm/google/chat.d.ts +20 -0
  123. package/dist/llm/google/chat.js +144 -0
  124. package/dist/llm/google/index.d.ts +2 -0
  125. package/dist/llm/google/index.js +2 -0
  126. package/dist/llm/google/serializer.d.ts +6 -0
  127. package/dist/llm/google/serializer.js +64 -0
  128. package/dist/llm/groq/chat.d.ts +15 -0
  129. package/dist/llm/groq/chat.js +52 -0
  130. package/dist/llm/groq/index.d.ts +3 -0
  131. package/dist/llm/groq/index.js +3 -0
  132. package/dist/llm/groq/parser.d.ts +32 -0
  133. package/dist/llm/groq/parser.js +189 -0
  134. package/dist/llm/groq/serializer.d.ts +6 -0
  135. package/dist/llm/groq/serializer.js +56 -0
  136. package/dist/llm/messages.d.ts +77 -0
  137. package/dist/llm/messages.js +157 -0
  138. package/dist/llm/ollama/chat.d.ts +15 -0
  139. package/dist/llm/ollama/chat.js +77 -0
  140. package/dist/llm/ollama/index.d.ts +2 -0
  141. package/dist/llm/ollama/index.js +2 -0
  142. package/dist/llm/ollama/serializer.d.ts +6 -0
  143. package/dist/llm/ollama/serializer.js +53 -0
  144. package/dist/llm/openai/chat.d.ts +38 -0
  145. package/dist/llm/openai/chat.js +174 -0
  146. package/dist/llm/openai/index.d.ts +3 -0
  147. package/dist/llm/openai/index.js +3 -0
  148. package/dist/llm/openai/like.d.ts +17 -0
  149. package/dist/llm/openai/like.js +19 -0
  150. package/dist/llm/openai/serializer.d.ts +6 -0
  151. package/dist/llm/openai/serializer.js +57 -0
  152. package/dist/llm/openrouter/chat.d.ts +15 -0
  153. package/dist/llm/openrouter/chat.js +74 -0
  154. package/dist/llm/openrouter/index.d.ts +2 -0
  155. package/dist/llm/openrouter/index.js +2 -0
  156. package/dist/llm/openrouter/serializer.d.ts +3 -0
  157. package/dist/llm/openrouter/serializer.js +3 -0
  158. package/dist/llm/schema.d.ts +6 -0
  159. package/dist/llm/schema.js +77 -0
  160. package/dist/llm/views.d.ts +15 -0
  161. package/dist/llm/views.js +12 -0
  162. package/dist/logging-config.d.ts +25 -0
  163. package/dist/logging-config.js +89 -0
  164. package/dist/mcp/client.d.ts +142 -0
  165. package/dist/mcp/client.js +638 -0
  166. package/dist/mcp/controller.d.ts +6 -0
  167. package/dist/mcp/controller.js +38 -0
  168. package/dist/mcp/index.d.ts +3 -0
  169. package/dist/mcp/index.js +3 -0
  170. package/dist/mcp/server.d.ts +134 -0
  171. package/dist/mcp/server.js +759 -0
  172. package/dist/observability-decorators.d.ts +158 -0
  173. package/dist/observability-decorators.js +286 -0
  174. package/dist/observability.d.ts +23 -0
  175. package/dist/observability.js +58 -0
  176. package/dist/screenshots/index.d.ts +1 -0
  177. package/dist/screenshots/index.js +1 -0
  178. package/dist/screenshots/service.d.ts +6 -0
  179. package/dist/screenshots/service.js +28 -0
  180. package/dist/sync/auth.d.ts +27 -0
  181. package/dist/sync/auth.js +205 -0
  182. package/dist/sync/index.d.ts +2 -0
  183. package/dist/sync/index.js +2 -0
  184. package/dist/sync/service.d.ts +21 -0
  185. package/dist/sync/service.js +146 -0
  186. package/dist/telemetry/index.d.ts +2 -0
  187. package/dist/telemetry/index.js +2 -0
  188. package/dist/telemetry/service.d.ts +12 -0
  189. package/dist/telemetry/service.js +85 -0
  190. package/dist/telemetry/views.d.ts +112 -0
  191. package/dist/telemetry/views.js +112 -0
  192. package/dist/tokens/index.d.ts +2 -0
  193. package/dist/tokens/index.js +2 -0
  194. package/dist/tokens/service.d.ts +35 -0
  195. package/dist/tokens/service.js +423 -0
  196. package/dist/tokens/views.d.ts +58 -0
  197. package/dist/tokens/views.js +1 -0
  198. package/dist/utils.d.ts +128 -0
  199. package/dist/utils.js +529 -0
  200. package/package.json +94 -5
@@ -0,0 +1,227 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import fs from 'node:fs';
8
+ import { fileURLToPath } from 'node:url';
9
+ import { createLogger } from '../logging-config.js';
10
+ import { observe_debug } from '../observability.js';
11
+ import { time_execution_async } from '../utils.js';
12
+ import { is_new_tab_page } from '../utils.js';
13
+ import { DOMElementNode, DOMState, DOMTextNode, } from './views.js';
14
+ const DOM_TREE_SCRIPT = fs.readFileSync(fileURLToPath(new URL('./dom_tree/index.js', import.meta.url)), 'utf-8');
15
+ export class DomService {
16
+ page;
17
+ logger;
18
+ jsCode;
19
+ constructor(page, logger = createLogger('browser_use.dom.service')) {
20
+ this.page = page;
21
+ this.logger = logger;
22
+ this.jsCode = DOM_TREE_SCRIPT;
23
+ }
24
+ // @ts-ignore - Decorator type mismatch with TypeScript strict mode
25
+ async get_clickable_elements(highlight_elements = true, focus_element = -1, viewport_expansion = 0) {
26
+ const [element_tree, selector_map] = await this._build_dom_tree(highlight_elements, focus_element, viewport_expansion);
27
+ return new DOMState(element_tree, selector_map);
28
+ }
29
+ // @ts-ignore - Decorator type mismatch with TypeScript strict mode
30
+ async get_cross_origin_iframes() {
31
+ const hiddenFrameUrls = await this.page
32
+ .locator('iframe')
33
+ .evaluateAll((elements) => elements
34
+ .filter((el) => {
35
+ const element = el;
36
+ const style = window.getComputedStyle(element);
37
+ const rect = element.getBoundingClientRect();
38
+ return (style.visibility === 'hidden' ||
39
+ style.display === 'none' ||
40
+ rect.width === 0 ||
41
+ rect.height === 0);
42
+ })
43
+ .map((el) => el.src));
44
+ const currentHost = this.safeHostname(this.getPageUrl());
45
+ return this.getFrames()
46
+ .map((frame) => this.getFrameUrl(frame))
47
+ .filter((url) => {
48
+ if (!url)
49
+ return false;
50
+ const host = this.safeHostname(url);
51
+ if (!host)
52
+ return false;
53
+ if (host === currentHost)
54
+ return false;
55
+ if (hiddenFrameUrls.includes(url))
56
+ return false;
57
+ return !this.isAdUrl(url);
58
+ });
59
+ }
60
+ // @ts-ignore - Decorator type mismatch with TypeScript strict mode
61
+ async _build_dom_tree(highlight_elements, focus_element, viewport_expansion) {
62
+ const canEvaluate = await this.page.evaluate(() => 1 + 1);
63
+ if (canEvaluate !== 2) {
64
+ throw new Error('The page cannot evaluate JavaScript code properly');
65
+ }
66
+ const pageUrl = this.getPageUrl();
67
+ if (is_new_tab_page(pageUrl) || pageUrl.startsWith('chrome://')) {
68
+ return [
69
+ new DOMElementNode(false, null, 'body', '', {}, []),
70
+ {},
71
+ ];
72
+ }
73
+ const args = {
74
+ doHighlightElements: highlight_elements,
75
+ focusHighlightIndex: focus_element,
76
+ viewportExpansion: viewport_expansion,
77
+ debugMode: this.isDebugEnabled(),
78
+ };
79
+ let eval_page;
80
+ try {
81
+ this.logger.debug(`🔧 Starting JavaScript DOM analysis for ${pageUrl.slice(0, 50)}...`);
82
+ eval_page = await this.page.evaluate(({ script, evaluateArgs }) => {
83
+ const fn = eval(script);
84
+ return fn(evaluateArgs);
85
+ }, { script: this.jsCode, evaluateArgs: args });
86
+ this.logger.debug('✅ JavaScript DOM analysis completed');
87
+ }
88
+ catch (error) {
89
+ this.logger.error(`Error evaluating DOMTree: ${error.message}`);
90
+ throw error;
91
+ }
92
+ if (args.debugMode && eval_page.perfMetrics) {
93
+ const perf = eval_page.perfMetrics;
94
+ const totalNodes = perf?.nodeMetrics?.totalNodes ?? 0;
95
+ let interactiveCount = 0;
96
+ if (eval_page.map) {
97
+ for (const node of Object.values(eval_page.map)) {
98
+ if (node?.isInteractive) {
99
+ interactiveCount += 1;
100
+ }
101
+ }
102
+ }
103
+ this.logger.debug(`🔎 Ran buildDOMTree.js interactive element detection on: ${pageUrl.slice(0, 50)} interactive=${interactiveCount}/${totalNodes}`);
104
+ }
105
+ this.logger.debug('🔄 Starting DOM tree construction...');
106
+ const result = await this._construct_dom_tree(eval_page);
107
+ this.logger.debug('✅ DOM tree construction completed');
108
+ return result;
109
+ }
110
+ // @ts-ignore - Decorator type mismatch with TypeScript strict mode
111
+ async _construct_dom_tree(eval_page) {
112
+ const selector_map = {};
113
+ const node_map = new Map();
114
+ const child_index = new Map();
115
+ for (const [id, node_data] of Object.entries(eval_page.map)) {
116
+ const [node, children] = this._parse_node(node_data);
117
+ if (!node)
118
+ continue;
119
+ node_map.set(id, node);
120
+ child_index.set(id, children);
121
+ if (node instanceof DOMElementNode &&
122
+ node.highlight_index !== null &&
123
+ node.highlight_index !== undefined) {
124
+ selector_map[node.highlight_index] = node;
125
+ }
126
+ }
127
+ for (const [id, childrenIds] of child_index.entries()) {
128
+ const parentNode = node_map.get(id);
129
+ if (!(parentNode instanceof DOMElementNode))
130
+ continue;
131
+ for (const childId of childrenIds || []) {
132
+ const key = String(childId);
133
+ const childNode = node_map.get(key);
134
+ if (!childNode)
135
+ continue;
136
+ childNode.parent = parentNode;
137
+ parentNode.children.push(childNode);
138
+ }
139
+ }
140
+ const rootNode = node_map.get(String(eval_page.rootId));
141
+ if (!(rootNode instanceof DOMElementNode)) {
142
+ throw new Error('Failed to construct DOM tree');
143
+ }
144
+ return [rootNode, selector_map];
145
+ }
146
+ _parse_node(node_data) {
147
+ if (!node_data) {
148
+ return [null, []];
149
+ }
150
+ if (node_data.type === 'TEXT_NODE') {
151
+ const textNode = new DOMTextNode(node_data.isVisible ?? false, null, node_data.text ?? '');
152
+ return [textNode, []];
153
+ }
154
+ const children = Array.isArray(node_data.children)
155
+ ? node_data.children
156
+ : [];
157
+ const tag = node_data.tagName ?? 'div';
158
+ const xpath = node_data.xpath ?? '';
159
+ const attributes = node_data.attributes ?? {};
160
+ const element = new DOMElementNode(node_data.isVisible ?? false, null, tag, xpath, attributes, []);
161
+ element.is_interactive = Boolean(node_data.isInteractive);
162
+ element.is_top_element = Boolean(node_data.isTopElement);
163
+ element.is_in_viewport = Boolean(node_data.isInViewport);
164
+ element.shadow_root = Boolean(node_data.shadowRoot);
165
+ element.highlight_index =
166
+ node_data.highlightIndex === undefined ||
167
+ node_data.highlightIndex === null
168
+ ? null
169
+ : Number(node_data.highlightIndex);
170
+ element.page_coordinates = node_data.pageCoordinates ?? null;
171
+ element.viewport_coordinates =
172
+ node_data.viewportCoordinates ?? null;
173
+ element.viewport_info = node_data.viewportInfo ?? null;
174
+ element.is_new = node_data.isNew ?? null;
175
+ return [element, children];
176
+ }
177
+ safeHostname(url) {
178
+ if (!url)
179
+ return '';
180
+ try {
181
+ return new URL(url).hostname;
182
+ }
183
+ catch {
184
+ return '';
185
+ }
186
+ }
187
+ getFrames() {
188
+ const frames = this.page.frames;
189
+ return typeof frames === 'function'
190
+ ? frames.call(this.page)
191
+ : (frames ?? []);
192
+ }
193
+ getFrameUrl(frame) {
194
+ return typeof frame.url === 'function' ? frame.url() : (frame.url ?? '');
195
+ }
196
+ isAdUrl(url) {
197
+ const host = this.safeHostname(url);
198
+ return ['doubleclick.net', 'adroll.com', 'googletagmanager.com'].some((domain) => host.endsWith(domain));
199
+ }
200
+ getPageUrl() {
201
+ return typeof this.page.url === 'function'
202
+ ? this.page.url()
203
+ : (this.page.url ?? '');
204
+ }
205
+ isDebugEnabled() {
206
+ return ((process.env.BROWSER_USE_LOGGING_LEVEL ?? '').toLowerCase() === 'debug');
207
+ }
208
+ }
209
+ __decorate([
210
+ observe_debug({
211
+ ignore_input: true,
212
+ ignore_output: true,
213
+ name: 'get_clickable_elements',
214
+ })
215
+ // @ts-ignore - Decorator type mismatch with TypeScript strict mode
216
+ ,
217
+ time_execution_async('--get_clickable_elements')
218
+ ], DomService.prototype, "get_clickable_elements", null);
219
+ __decorate([
220
+ time_execution_async('--get_cross_origin_iframes')
221
+ ], DomService.prototype, "get_cross_origin_iframes", null);
222
+ __decorate([
223
+ time_execution_async('--build_dom_tree')
224
+ ], DomService.prototype, "_build_dom_tree", null);
225
+ __decorate([
226
+ time_execution_async('--construct_dom_tree')
227
+ ], DomService.prototype, "_construct_dom_tree", null);
@@ -0,0 +1 @@
1
+ export declare const cap_text_length: (text: string, max_length: number) => string;
@@ -0,0 +1,6 @@
1
+ export const cap_text_length = (text, max_length) => {
2
+ if (text.length > max_length) {
3
+ return `${text.slice(0, max_length)}...`;
4
+ }
5
+ return text;
6
+ };
@@ -0,0 +1,61 @@
1
+ import { CoordinateSet, HashedDomElement, ViewportInfo } from './history-tree-processor/view.js';
2
+ export declare abstract class DOMBaseNode {
3
+ is_visible: boolean;
4
+ parent: DOMElementNode | null;
5
+ constructor(is_visible: boolean, parent?: DOMElementNode | null);
6
+ abstract toJSON(): Record<string, unknown>;
7
+ }
8
+ export declare class DOMTextNode extends DOMBaseNode {
9
+ text: string;
10
+ type: string;
11
+ constructor(is_visible: boolean, parent: DOMElementNode | null, text: string);
12
+ has_parent_with_highlight_index(): boolean;
13
+ is_parent_in_viewport(): boolean;
14
+ is_parent_top_element(): boolean;
15
+ toJSON(): {
16
+ text: string;
17
+ type: string;
18
+ };
19
+ }
20
+ export declare const DEFAULT_INCLUDE_ATTRIBUTES: string[];
21
+ export declare class DOMElementNode extends DOMBaseNode {
22
+ tag_name: string;
23
+ xpath: string;
24
+ attributes: Record<string, string>;
25
+ children: DOMBaseNode[];
26
+ is_interactive: boolean;
27
+ is_top_element: boolean;
28
+ is_in_viewport: boolean;
29
+ shadow_root: boolean;
30
+ highlight_index: number | null;
31
+ viewport_coordinates: CoordinateSet | null;
32
+ page_coordinates: CoordinateSet | null;
33
+ viewport_info: ViewportInfo | null;
34
+ is_new: boolean | null;
35
+ private cached_hash;
36
+ constructor(is_visible: boolean, parent: DOMElementNode | null, tag_name: string, xpath: string, attributes: Record<string, string>, children: DOMBaseNode[]);
37
+ toJSON(): {
38
+ tag_name: string;
39
+ xpath: string;
40
+ attributes: Record<string, string>;
41
+ is_visible: boolean;
42
+ is_interactive: boolean;
43
+ is_top_element: boolean;
44
+ is_in_viewport: boolean;
45
+ shadow_root: boolean;
46
+ highlight_index: number | null;
47
+ viewport_coordinates: CoordinateSet | null;
48
+ page_coordinates: CoordinateSet | null;
49
+ children: Record<string, unknown>[];
50
+ };
51
+ toString(): string;
52
+ get hash(): HashedDomElement;
53
+ get_all_text_till_next_clickable_element(max_depth?: number): string;
54
+ clickable_elements_to_string(include_attributes?: string[]): string;
55
+ }
56
+ export type SelectorMap = Record<number, DOMElementNode>;
57
+ export declare class DOMState {
58
+ element_tree: DOMElementNode;
59
+ selector_map: SelectorMap;
60
+ constructor(element_tree: DOMElementNode, selector_map: SelectorMap);
61
+ }
@@ -0,0 +1,247 @@
1
+ import { cap_text_length } from './utils.js';
2
+ import { time_execution_sync } from '../utils.js';
3
+ import { HistoryTreeProcessor } from './history-tree-processor/service.js';
4
+ export class DOMBaseNode {
5
+ is_visible;
6
+ parent;
7
+ constructor(is_visible, parent = null) {
8
+ this.is_visible = is_visible;
9
+ this.parent = parent;
10
+ }
11
+ }
12
+ export class DOMTextNode extends DOMBaseNode {
13
+ text;
14
+ type = 'TEXT_NODE';
15
+ constructor(is_visible, parent, text) {
16
+ super(is_visible, parent);
17
+ this.text = text;
18
+ }
19
+ has_parent_with_highlight_index() {
20
+ let current = this.parent;
21
+ while (current) {
22
+ if (current.highlight_index !== null &&
23
+ current.highlight_index !== undefined) {
24
+ return true;
25
+ }
26
+ current = current.parent;
27
+ }
28
+ return false;
29
+ }
30
+ is_parent_in_viewport() {
31
+ return Boolean(this.parent?.is_in_viewport);
32
+ }
33
+ is_parent_top_element() {
34
+ return Boolean(this.parent?.is_top_element);
35
+ }
36
+ toJSON() {
37
+ return {
38
+ text: this.text,
39
+ type: this.type,
40
+ };
41
+ }
42
+ }
43
+ export const DEFAULT_INCLUDE_ATTRIBUTES = [
44
+ 'title',
45
+ 'type',
46
+ 'checked',
47
+ 'name',
48
+ 'role',
49
+ 'value',
50
+ 'placeholder',
51
+ 'data-date-format',
52
+ 'alt',
53
+ 'aria-label',
54
+ 'aria-expanded',
55
+ 'data-state',
56
+ 'aria-checked',
57
+ ];
58
+ export class DOMElementNode extends DOMBaseNode {
59
+ tag_name;
60
+ xpath;
61
+ attributes;
62
+ children;
63
+ is_interactive = false;
64
+ is_top_element = false;
65
+ is_in_viewport = false;
66
+ shadow_root = false;
67
+ highlight_index = null;
68
+ viewport_coordinates = null;
69
+ page_coordinates = null;
70
+ viewport_info = null;
71
+ is_new = null;
72
+ cached_hash = null;
73
+ constructor(is_visible, parent, tag_name, xpath, attributes, children) {
74
+ super(is_visible, parent);
75
+ this.tag_name = tag_name;
76
+ this.xpath = xpath;
77
+ this.attributes = attributes;
78
+ this.children = children;
79
+ }
80
+ toJSON() {
81
+ return {
82
+ tag_name: this.tag_name,
83
+ xpath: this.xpath,
84
+ attributes: this.attributes,
85
+ is_visible: this.is_visible,
86
+ is_interactive: this.is_interactive,
87
+ is_top_element: this.is_top_element,
88
+ is_in_viewport: this.is_in_viewport,
89
+ shadow_root: this.shadow_root,
90
+ highlight_index: this.highlight_index,
91
+ viewport_coordinates: this.viewport_coordinates,
92
+ page_coordinates: this.page_coordinates,
93
+ children: this.children.map((child) => child.toJSON()),
94
+ };
95
+ }
96
+ toString() {
97
+ let tag_str = `<${this.tag_name}`;
98
+ for (const [key, value] of Object.entries(this.attributes)) {
99
+ tag_str += ` ${key}="${value}"`;
100
+ }
101
+ tag_str += '>';
102
+ const extras = [];
103
+ if (this.is_interactive)
104
+ extras.push('interactive');
105
+ if (this.is_top_element)
106
+ extras.push('top');
107
+ if (this.shadow_root)
108
+ extras.push('shadow-root');
109
+ if (this.highlight_index !== null && this.highlight_index !== undefined) {
110
+ extras.push(`highlight:${this.highlight_index}`);
111
+ }
112
+ if (this.is_in_viewport)
113
+ extras.push('in-viewport');
114
+ if (extras.length) {
115
+ tag_str += ` [${extras.join(', ')}]`;
116
+ }
117
+ return tag_str;
118
+ }
119
+ get hash() {
120
+ if (!this.cached_hash) {
121
+ this.cached_hash = HistoryTreeProcessor._hash_dom_element(this);
122
+ }
123
+ return this.cached_hash;
124
+ }
125
+ get_all_text_till_next_clickable_element(max_depth = -1) {
126
+ const text_parts = [];
127
+ const collect_text = (node, current_depth) => {
128
+ if (max_depth !== -1 && current_depth > max_depth) {
129
+ return;
130
+ }
131
+ if (node instanceof DOMElementNode &&
132
+ node !== this &&
133
+ node.highlight_index !== null &&
134
+ node.highlight_index !== undefined) {
135
+ return;
136
+ }
137
+ if (node instanceof DOMTextNode) {
138
+ text_parts.push(node.text);
139
+ }
140
+ else if (node instanceof DOMElementNode) {
141
+ for (const child of node.children) {
142
+ collect_text(child, current_depth + 1);
143
+ }
144
+ }
145
+ };
146
+ collect_text(this, 0);
147
+ return text_parts.join('\n').trim();
148
+ }
149
+ clickable_elements_to_string(include_attributes) {
150
+ return CLICKABLE_ELEMENTS_TO_STRING_IMPL.call(this, include_attributes);
151
+ }
152
+ }
153
+ const CLICKABLE_ELEMENTS_TO_STRING_IMPL = time_execution_sync('--clickable_elements_to_string')(function (include_attributes) {
154
+ const formatted_text = [];
155
+ const attributes_list = include_attributes ?? DEFAULT_INCLUDE_ATTRIBUTES;
156
+ const process_node = (node, depth) => {
157
+ const next_depth = depth;
158
+ const depth_str = '\t'.repeat(depth);
159
+ if (node instanceof DOMElementNode) {
160
+ let working_depth = next_depth;
161
+ if (node.highlight_index !== null && node.highlight_index !== undefined) {
162
+ working_depth += 1;
163
+ let text = node.get_all_text_till_next_clickable_element();
164
+ let attributes_html_str = null;
165
+ if (attributes_list.length) {
166
+ const attributes_to_include = Object.fromEntries(Object.entries(node.attributes)
167
+ .filter(([key, value]) => attributes_list.includes(key) && String(value).trim() !== '')
168
+ .map(([key, value]) => [key, String(value).trim()]));
169
+ const ordered_keys = attributes_list.filter((key) => key in attributes_to_include);
170
+ if (ordered_keys.length > 1) {
171
+ const keys_to_remove = new Set();
172
+ const seen_values = {};
173
+ for (const key of ordered_keys) {
174
+ const value = attributes_to_include[key];
175
+ if (value && value.length > 5) {
176
+ if (seen_values[value]) {
177
+ keys_to_remove.add(key);
178
+ }
179
+ else {
180
+ seen_values[value] = key;
181
+ }
182
+ }
183
+ }
184
+ for (const key of keys_to_remove) {
185
+ delete attributes_to_include[key];
186
+ }
187
+ }
188
+ if (node.tag_name === attributes_to_include.role) {
189
+ delete attributes_to_include.role;
190
+ }
191
+ for (const attr of ['aria-label', 'placeholder', 'title']) {
192
+ if (attributes_to_include[attr] &&
193
+ attributes_to_include[attr].trim().toLowerCase() ===
194
+ text.trim().toLowerCase()) {
195
+ delete attributes_to_include[attr];
196
+ }
197
+ }
198
+ if (Object.entries(attributes_to_include).length) {
199
+ attributes_html_str = Object.entries(attributes_to_include)
200
+ .map(([key, value]) => `${key}=${cap_text_length(value, 15)}`)
201
+ .join(' ');
202
+ }
203
+ }
204
+ const highlight_indicator = node.is_new
205
+ ? `*[${node.highlight_index}]`
206
+ : `[${node.highlight_index}]`;
207
+ let line = `${depth_str}${highlight_indicator}<${node.tag_name}`;
208
+ if (attributes_html_str) {
209
+ line += ` ${attributes_html_str}`;
210
+ }
211
+ if (text) {
212
+ text = text.trim();
213
+ if (!attributes_html_str) {
214
+ line += ' ';
215
+ }
216
+ line += `>${text}`;
217
+ }
218
+ else if (!attributes_html_str) {
219
+ line += ' ';
220
+ }
221
+ line += ' />';
222
+ formatted_text.push(line);
223
+ }
224
+ for (const child of node.children) {
225
+ process_node(child, working_depth);
226
+ }
227
+ }
228
+ else if (node instanceof DOMTextNode) {
229
+ if (node.has_parent_with_highlight_index()) {
230
+ return;
231
+ }
232
+ if (node.parent?.is_visible && node.parent.is_top_element) {
233
+ formatted_text.push(`${depth_str}${node.text}`);
234
+ }
235
+ }
236
+ };
237
+ process_node(this, 0);
238
+ return formatted_text.join('\n');
239
+ });
240
+ export class DOMState {
241
+ element_tree;
242
+ selector_map;
243
+ constructor(element_tree, selector_map) {
244
+ this.element_tree = element_tree;
245
+ this.selector_map = selector_map;
246
+ }
247
+ }
@@ -0,0 +1,11 @@
1
+ export type EventHandler<T = any> = (event: T) => void | Promise<void>;
2
+ export declare class EventBus {
3
+ readonly name: string;
4
+ private emitter;
5
+ constructor(name: string);
6
+ on<T = any>(eventType: string, handler: EventHandler<T>): void;
7
+ dispatch<T extends {
8
+ event_type?: string;
9
+ }>(event: T): void;
10
+ stop(): Promise<void>;
11
+ }
@@ -0,0 +1,19 @@
1
+ import EventEmitter from 'eventemitter3';
2
+ export class EventBus {
3
+ name;
4
+ emitter = new EventEmitter();
5
+ constructor(name) {
6
+ this.name = name;
7
+ }
8
+ on(eventType, handler) {
9
+ this.emitter.on(eventType, handler);
10
+ }
11
+ dispatch(event) {
12
+ const eventType = event?.event_type ?? event?.constructor?.name ?? 'event';
13
+ this.emitter.emit(eventType, event);
14
+ this.emitter.emit('*', event);
15
+ }
16
+ async stop() {
17
+ this.emitter.removeAllListeners();
18
+ }
19
+ }
@@ -0,0 +1,10 @@
1
+ export declare class LLMException extends Error {
2
+ readonly statusCode: number;
3
+ readonly detail: string;
4
+ constructor(statusCode: number, detail: string);
5
+ }
6
+ export declare class URLNotAllowedError extends Error {
7
+ readonly url: string;
8
+ readonly allowedDomains: string[];
9
+ constructor(url: string, allowedDomains: string[]);
10
+ }
@@ -0,0 +1,22 @@
1
+ export class LLMException extends Error {
2
+ statusCode;
3
+ detail;
4
+ constructor(statusCode, detail) {
5
+ super(`Error ${statusCode}: ${detail}`);
6
+ this.statusCode = statusCode;
7
+ this.detail = detail;
8
+ this.name = 'LLMException';
9
+ }
10
+ }
11
+ export class URLNotAllowedError extends Error {
12
+ url;
13
+ allowedDomains;
14
+ constructor(url, allowedDomains) {
15
+ super(`URL "${url}" is not allowed. ` +
16
+ `Only domains matching ${JSON.stringify(allowedDomains)} are permitted. ` +
17
+ `This is enforced because sensitive_data was provided to Agent.`);
18
+ this.url = url;
19
+ this.allowedDomains = allowedDomains;
20
+ this.name = 'URLNotAllowedError';
21
+ }
22
+ }
@@ -0,0 +1,68 @@
1
+ export declare const INVALID_FILENAME_ERROR_MESSAGE = "Error: Invalid filename format. Must be alphanumeric with supported extension.";
2
+ export declare const DEFAULT_FILE_SYSTEM_PATH = "browseruse_agent_data";
3
+ export declare class FileSystemError extends Error {
4
+ }
5
+ declare abstract class BaseFile {
6
+ name: string;
7
+ protected content: string;
8
+ constructor(name: string, content?: string);
9
+ abstract get extension(): string;
10
+ get fullName(): string;
11
+ get size(): number;
12
+ get lineCount(): number;
13
+ protected writeFileContent(content: string): void;
14
+ protected appendFileContent(content: string): void;
15
+ read(): string;
16
+ syncToDisk(dir: string): Promise<void>;
17
+ syncToDiskSync(dir: string): void;
18
+ write(content: string, dir: string): Promise<void>;
19
+ writeSync(content: string, dir: string): void;
20
+ append(content: string, dir: string): Promise<void>;
21
+ appendSync(content: string, dir: string): void;
22
+ toJSON(): {
23
+ name: string;
24
+ content: string;
25
+ };
26
+ }
27
+ export interface FileState {
28
+ type: string;
29
+ data: {
30
+ name: string;
31
+ content: string;
32
+ };
33
+ }
34
+ export interface FileSystemState {
35
+ files: Record<string, FileState>;
36
+ base_dir: string;
37
+ extracted_content_count: number;
38
+ }
39
+ export declare class FileSystem {
40
+ private files;
41
+ private readonly defaultFiles;
42
+ private readonly baseDir;
43
+ readonly dataDir: string;
44
+ extractedContentCount: number;
45
+ constructor(baseDir: string, createDefaultFiles?: boolean);
46
+ private createDefaultFiles;
47
+ private isValidFilename;
48
+ private parseFilename;
49
+ private getFileClass;
50
+ private instantiateFile;
51
+ get_allowed_extensions(): string[];
52
+ get_dir(): string;
53
+ get_file(filename: string): BaseFile | null;
54
+ list_files(): string[];
55
+ display_file(filename: string): string | null;
56
+ read_file(filename: string, externalFile?: boolean): Promise<string>;
57
+ write_file(filename: string, content: string): Promise<string>;
58
+ append_file(filename: string, content: string): Promise<string>;
59
+ replace_file_str(filename: string, oldStr: string, newStr: string): Promise<string>;
60
+ save_extracted_content(content: string): Promise<string>;
61
+ describe(): string;
62
+ get_todo_contents(): string;
63
+ get_state(): FileSystemState;
64
+ nuke(): Promise<void>;
65
+ static from_state_sync(state: FileSystemState): FileSystem;
66
+ static from_state(state: FileSystemState): Promise<FileSystem>;
67
+ }
68
+ export {};