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.
Files changed (258) hide show
  1. package/README.md +301 -636
  2. package/dist/actor/element.d.ts +19 -0
  3. package/dist/actor/element.js +46 -0
  4. package/dist/actor/index.d.ts +4 -0
  5. package/dist/actor/index.js +4 -0
  6. package/dist/actor/mouse.d.ts +19 -0
  7. package/dist/actor/mouse.js +39 -0
  8. package/dist/actor/page.d.ts +29 -0
  9. package/dist/actor/page.js +88 -0
  10. package/dist/actor/utils.d.ts +4 -0
  11. package/dist/actor/utils.js +35 -0
  12. package/dist/agent/cloud-events.d.ts +18 -0
  13. package/dist/agent/cloud-events.js +65 -2
  14. package/dist/agent/gif.d.ts +1 -0
  15. package/dist/agent/gif.js +24 -2
  16. package/dist/agent/judge.d.ts +17 -0
  17. package/dist/agent/judge.js +197 -0
  18. package/dist/agent/message-manager/service.d.ts +12 -4
  19. package/dist/agent/message-manager/service.js +205 -39
  20. package/dist/agent/message-manager/utils.js +0 -1
  21. package/dist/agent/message-manager/views.d.ts +4 -0
  22. package/dist/agent/message-manager/views.js +11 -7
  23. package/dist/agent/prompts.d.ts +24 -3
  24. package/dist/agent/prompts.js +274 -59
  25. package/dist/agent/service.d.ts +99 -40
  26. package/dist/agent/service.js +2282 -474
  27. package/dist/agent/variable-detector.d.ts +12 -0
  28. package/dist/agent/variable-detector.js +211 -0
  29. package/dist/agent/views.d.ts +237 -17
  30. package/dist/agent/views.js +446 -32
  31. package/dist/browser/cloud/cloud.d.ts +20 -0
  32. package/dist/browser/cloud/cloud.js +129 -0
  33. package/dist/browser/cloud/index.d.ts +2 -0
  34. package/dist/browser/cloud/index.js +2 -0
  35. package/dist/browser/cloud/views.d.ts +41 -0
  36. package/dist/browser/cloud/views.js +35 -0
  37. package/dist/browser/events.d.ts +345 -0
  38. package/dist/browser/events.js +566 -0
  39. package/dist/browser/extensions.js +17 -17
  40. package/dist/browser/index.d.ts +4 -0
  41. package/dist/browser/index.js +4 -0
  42. package/dist/browser/profile.d.ts +8 -2
  43. package/dist/browser/profile.js +79 -12
  44. package/dist/browser/session-manager.d.ts +85 -0
  45. package/dist/browser/session-manager.js +208 -0
  46. package/dist/browser/session.d.ts +100 -8
  47. package/dist/browser/session.js +1102 -63
  48. package/dist/browser/types.d.ts +0 -2
  49. package/dist/browser/views.d.ts +39 -0
  50. package/dist/browser/views.js +32 -0
  51. package/dist/browser/watchdogs/aboutblank-watchdog.d.ts +12 -0
  52. package/dist/browser/watchdogs/aboutblank-watchdog.js +131 -0
  53. package/dist/browser/watchdogs/base.d.ts +21 -0
  54. package/dist/browser/watchdogs/base.js +81 -0
  55. package/dist/browser/watchdogs/cdp-session-watchdog.d.ts +14 -0
  56. package/dist/browser/watchdogs/cdp-session-watchdog.js +177 -0
  57. package/dist/browser/watchdogs/crash-watchdog.d.ts +38 -0
  58. package/dist/browser/watchdogs/crash-watchdog.js +296 -0
  59. package/dist/browser/watchdogs/default-action-watchdog.d.ts +49 -0
  60. package/dist/browser/watchdogs/default-action-watchdog.js +212 -0
  61. package/dist/browser/watchdogs/dom-watchdog.d.ts +8 -0
  62. package/dist/browser/watchdogs/dom-watchdog.js +31 -0
  63. package/dist/browser/watchdogs/downloads-watchdog.d.ts +77 -0
  64. package/dist/browser/watchdogs/downloads-watchdog.js +409 -0
  65. package/dist/browser/watchdogs/har-recording-watchdog.d.ts +19 -0
  66. package/dist/browser/watchdogs/har-recording-watchdog.js +317 -0
  67. package/dist/browser/watchdogs/index.d.ts +15 -0
  68. package/dist/browser/watchdogs/index.js +15 -0
  69. package/dist/browser/watchdogs/local-browser-watchdog.d.ts +10 -0
  70. package/dist/browser/watchdogs/local-browser-watchdog.js +32 -0
  71. package/dist/browser/watchdogs/permissions-watchdog.d.ts +8 -0
  72. package/dist/browser/watchdogs/permissions-watchdog.js +73 -0
  73. package/dist/browser/watchdogs/popups-watchdog.d.ts +13 -0
  74. package/dist/browser/watchdogs/popups-watchdog.js +77 -0
  75. package/dist/browser/watchdogs/recording-watchdog.d.ts +27 -0
  76. package/dist/browser/watchdogs/recording-watchdog.js +249 -0
  77. package/dist/browser/watchdogs/screenshot-watchdog.d.ts +6 -0
  78. package/dist/browser/watchdogs/screenshot-watchdog.js +13 -0
  79. package/dist/browser/watchdogs/security-watchdog.d.ts +10 -0
  80. package/dist/browser/watchdogs/security-watchdog.js +84 -0
  81. package/dist/browser/watchdogs/storage-state-watchdog.d.ts +24 -0
  82. package/dist/browser/watchdogs/storage-state-watchdog.js +288 -0
  83. package/dist/cli.d.ts +41 -0
  84. package/dist/cli.js +820 -10
  85. package/dist/code-use/formatting.d.ts +3 -0
  86. package/dist/code-use/formatting.js +18 -0
  87. package/dist/code-use/index.d.ts +6 -0
  88. package/dist/code-use/index.js +6 -0
  89. package/dist/code-use/namespace.d.ts +5 -0
  90. package/dist/code-use/namespace.js +81 -0
  91. package/dist/code-use/notebook-export.d.ts +3 -0
  92. package/dist/code-use/notebook-export.js +56 -0
  93. package/dist/code-use/service.d.ts +24 -0
  94. package/dist/code-use/service.js +104 -0
  95. package/dist/code-use/utils.d.ts +4 -0
  96. package/dist/code-use/utils.js +98 -0
  97. package/dist/code-use/views.d.ts +108 -0
  98. package/dist/code-use/views.js +165 -0
  99. package/dist/config.d.ts +13 -0
  100. package/dist/config.js +69 -3
  101. package/dist/controller/registry/service.d.ts +10 -1
  102. package/dist/controller/registry/service.js +266 -10
  103. package/dist/controller/registry/views.d.ts +4 -1
  104. package/dist/controller/registry/views.js +25 -2
  105. package/dist/controller/service.d.ts +10 -1
  106. package/dist/controller/service.js +1849 -288
  107. package/dist/controller/views.d.ts +78 -155
  108. package/dist/controller/views.js +61 -12
  109. package/dist/dom/history-tree-processor/service.d.ts +5 -0
  110. package/dist/dom/history-tree-processor/service.js +169 -14
  111. package/dist/dom/history-tree-processor/view.d.ts +7 -1
  112. package/dist/dom/history-tree-processor/view.js +10 -1
  113. package/dist/dom/markdown-extractor.d.ts +37 -0
  114. package/dist/dom/markdown-extractor.js +345 -0
  115. package/dist/dom/service.d.ts +3 -1
  116. package/dist/dom/service.js +76 -0
  117. package/dist/dom/views.d.ts +1 -0
  118. package/dist/dom/views.js +45 -0
  119. package/dist/event-bus.d.ts +107 -7
  120. package/dist/event-bus.js +313 -10
  121. package/dist/filesystem/file-system.d.ts +18 -0
  122. package/dist/filesystem/file-system.js +530 -42
  123. package/dist/index.d.ts +7 -0
  124. package/dist/index.js +6 -0
  125. package/dist/integrations/gmail/actions.d.ts +3 -3
  126. package/dist/integrations/gmail/actions.js +5 -5
  127. package/dist/llm/anthropic/chat.d.ts +18 -1
  128. package/dist/llm/anthropic/chat.js +123 -55
  129. package/dist/llm/anthropic/serializer.d.ts +2 -0
  130. package/dist/llm/anthropic/serializer.js +81 -9
  131. package/dist/llm/aws/chat-anthropic.d.ts +17 -0
  132. package/dist/llm/aws/chat-anthropic.js +129 -40
  133. package/dist/llm/aws/chat-bedrock.d.ts +28 -1
  134. package/dist/llm/aws/chat-bedrock.js +161 -34
  135. package/dist/llm/aws/serializer.d.ts +13 -1
  136. package/dist/llm/aws/serializer.js +56 -17
  137. package/dist/llm/azure/chat.d.ts +53 -2
  138. package/dist/llm/azure/chat.js +366 -53
  139. package/dist/llm/base.d.ts +2 -0
  140. package/dist/llm/browser-use/chat.d.ts +40 -0
  141. package/dist/llm/browser-use/chat.js +305 -0
  142. package/dist/llm/browser-use/index.d.ts +1 -0
  143. package/dist/llm/browser-use/index.js +1 -0
  144. package/dist/llm/cerebras/chat.d.ts +39 -0
  145. package/dist/llm/cerebras/chat.js +178 -0
  146. package/dist/llm/cerebras/index.d.ts +2 -0
  147. package/dist/llm/cerebras/index.js +2 -0
  148. package/dist/llm/cerebras/serializer.d.ts +7 -0
  149. package/dist/llm/cerebras/serializer.js +82 -0
  150. package/dist/llm/deepseek/chat.d.ts +19 -2
  151. package/dist/llm/deepseek/chat.js +138 -25
  152. package/dist/llm/google/chat.d.ts +46 -2
  153. package/dist/llm/google/chat.js +268 -63
  154. package/dist/llm/google/serializer.d.ts +9 -1
  155. package/dist/llm/google/serializer.js +141 -34
  156. package/dist/llm/groq/chat.d.ts +21 -2
  157. package/dist/llm/groq/chat.js +125 -26
  158. package/dist/llm/groq/parser.js +3 -1
  159. package/dist/llm/messages.d.ts +4 -4
  160. package/dist/llm/mistral/chat.d.ts +43 -0
  161. package/dist/llm/mistral/chat.js +154 -0
  162. package/dist/llm/mistral/index.d.ts +2 -0
  163. package/dist/llm/mistral/index.js +2 -0
  164. package/dist/llm/mistral/schema.d.ts +8 -0
  165. package/dist/llm/mistral/schema.js +27 -0
  166. package/dist/llm/models.d.ts +2 -0
  167. package/dist/llm/models.js +317 -0
  168. package/dist/llm/ollama/chat.d.ts +13 -1
  169. package/dist/llm/ollama/chat.js +110 -19
  170. package/dist/llm/ollama/serializer.d.ts +1 -0
  171. package/dist/llm/ollama/serializer.js +34 -12
  172. package/dist/llm/openai/chat.d.ts +16 -0
  173. package/dist/llm/openai/chat.js +94 -44
  174. package/dist/llm/openai/like.d.ts +5 -3
  175. package/dist/llm/openai/like.js +7 -3
  176. package/dist/llm/openai/responses-serializer.d.ts +18 -0
  177. package/dist/llm/openai/responses-serializer.js +72 -0
  178. package/dist/llm/openrouter/chat.d.ts +28 -2
  179. package/dist/llm/openrouter/chat.js +115 -29
  180. package/dist/llm/schema.d.ts +11 -1
  181. package/dist/llm/schema.js +81 -1
  182. package/dist/llm/vercel/chat.d.ts +50 -0
  183. package/dist/llm/vercel/chat.js +276 -0
  184. package/dist/llm/vercel/index.d.ts +1 -0
  185. package/dist/llm/vercel/index.js +1 -0
  186. package/dist/llm/vercel/serializer.d.ts +5 -0
  187. package/dist/llm/vercel/serializer.js +7 -0
  188. package/dist/llm/views.d.ts +2 -1
  189. package/dist/llm/views.js +3 -1
  190. package/dist/logging-config.d.ts +2 -0
  191. package/dist/logging-config.js +82 -29
  192. package/dist/mcp/client.d.ts +10 -5
  193. package/dist/mcp/client.js +21 -15
  194. package/dist/mcp/controller.d.ts +42 -3
  195. package/dist/mcp/controller.js +56 -31
  196. package/dist/mcp/server.d.ts +14 -0
  197. package/dist/mcp/server.js +257 -51
  198. package/dist/observability.js +10 -4
  199. package/dist/sandbox/index.d.ts +2 -0
  200. package/dist/sandbox/index.js +2 -0
  201. package/dist/sandbox/sandbox.d.ts +19 -0
  202. package/dist/sandbox/sandbox.js +140 -0
  203. package/dist/sandbox/views.d.ts +67 -0
  204. package/dist/sandbox/views.js +121 -0
  205. package/dist/skill-cli/index.d.ts +3 -0
  206. package/dist/skill-cli/index.js +3 -0
  207. package/dist/skill-cli/protocol.d.ts +30 -0
  208. package/dist/skill-cli/protocol.js +48 -0
  209. package/dist/skill-cli/server.d.ts +11 -0
  210. package/dist/skill-cli/server.js +85 -0
  211. package/dist/skill-cli/sessions.d.ts +24 -0
  212. package/dist/skill-cli/sessions.js +47 -0
  213. package/dist/skills/index.d.ts +3 -0
  214. package/dist/skills/index.js +3 -0
  215. package/dist/skills/service.d.ts +27 -0
  216. package/dist/skills/service.js +266 -0
  217. package/dist/skills/utils.d.ts +6 -0
  218. package/dist/skills/utils.js +53 -0
  219. package/dist/skills/views.d.ts +40 -0
  220. package/dist/skills/views.js +10 -0
  221. package/dist/sync/auth.js +8 -3
  222. package/dist/sync/service.d.ts +6 -6
  223. package/dist/sync/service.js +54 -89
  224. package/dist/telemetry/views.d.ts +20 -6
  225. package/dist/telemetry/views.js +23 -5
  226. package/dist/tokens/custom-pricing.d.ts +2 -0
  227. package/dist/tokens/custom-pricing.js +22 -0
  228. package/dist/tokens/index.d.ts +2 -0
  229. package/dist/tokens/index.js +2 -0
  230. package/dist/tokens/mappings.d.ts +1 -0
  231. package/dist/tokens/mappings.js +3 -0
  232. package/dist/tokens/service.js +30 -12
  233. package/dist/tools/extraction/index.d.ts +2 -0
  234. package/dist/tools/extraction/index.js +2 -0
  235. package/dist/tools/extraction/schema-utils.d.ts +6 -0
  236. package/dist/tools/extraction/schema-utils.js +237 -0
  237. package/dist/tools/extraction/views.d.ts +7 -0
  238. package/dist/tools/index.d.ts +5 -0
  239. package/dist/tools/index.js +5 -0
  240. package/dist/tools/registry/index.d.ts +2 -0
  241. package/dist/tools/registry/index.js +2 -0
  242. package/dist/tools/registry/service.d.ts +1 -0
  243. package/dist/tools/registry/service.js +1 -0
  244. package/dist/tools/registry/views.d.ts +1 -0
  245. package/dist/tools/registry/views.js +1 -0
  246. package/dist/tools/service.d.ts +2 -0
  247. package/dist/tools/service.js +1 -0
  248. package/dist/tools/utils.d.ts +2 -0
  249. package/dist/tools/utils.js +57 -0
  250. package/dist/tools/views.d.ts +1 -0
  251. package/dist/tools/views.js +1 -0
  252. package/dist/utils.d.ts +10 -1
  253. package/dist/utils.js +70 -3
  254. package/package.json +265 -28
  255. package/dist/dom/playground/process-dom.js +0 -5
  256. package/dist/dom/playground/test-accessibility.d.ts +0 -44
  257. package/dist/dom/playground/test-accessibility.js +0 -111
  258. /package/dist/{dom/playground/process-dom.d.ts → tools/extraction/views.js} +0 -0
@@ -0,0 +1,3 @@
1
+ import type { BrowserStateSummary } from '../browser/views.js';
2
+ import type { BrowserSession } from '../browser/session.js';
3
+ export declare const format_browser_state_for_llm: (state: BrowserStateSummary, namespace: Record<string, unknown>, _browser_session: BrowserSession) => Promise<string>;
@@ -0,0 +1,18 @@
1
+ export const format_browser_state_for_llm = async (state, namespace, _browser_session) => {
2
+ const lines = [];
3
+ lines.push('## Browser State');
4
+ lines.push(`**URL:** ${state.url}`);
5
+ lines.push(`**Title:** ${state.title}`);
6
+ lines.push('');
7
+ const vars = Object.keys(namespace)
8
+ .filter((key) => !key.startsWith('_'))
9
+ .sort();
10
+ lines.push(`**Available:** ${vars.length > 0 ? vars.join(', ') : '(none)'}`);
11
+ lines.push('');
12
+ const dom = typeof state.llm_representation === 'function'
13
+ ? state.llm_representation()
14
+ : '';
15
+ lines.push('**DOM Structure:**');
16
+ lines.push(dom || 'Empty DOM tree (you might have to wait for page load)');
17
+ return lines.join('\n');
18
+ };
@@ -0,0 +1,6 @@
1
+ export * from './views.js';
2
+ export * from './utils.js';
3
+ export * from './namespace.js';
4
+ export * from './service.js';
5
+ export * from './formatting.js';
6
+ export * from './notebook-export.js';
@@ -0,0 +1,6 @@
1
+ export * from './views.js';
2
+ export * from './utils.js';
3
+ export * from './namespace.js';
4
+ export * from './service.js';
5
+ export * from './formatting.js';
6
+ export * from './notebook-export.js';
@@ -0,0 +1,5 @@
1
+ import type { BrowserSession } from '../browser/session.js';
2
+ export interface CreateNamespaceOptions {
3
+ namespace?: Record<string, unknown>;
4
+ }
5
+ export declare const create_namespace: (browser_session: BrowserSession, options?: CreateNamespaceOptions) => Record<string, unknown>;
@@ -0,0 +1,81 @@
1
+ const buildExpression = (source, args) => `(${source})(${args.map((arg) => JSON.stringify(arg)).join(',')})`;
2
+ export const create_namespace = (browser_session, options = {}) => {
3
+ const namespace = options.namespace ?? {};
4
+ namespace.browser = browser_session;
5
+ namespace.navigate = async (url, init = {}) => {
6
+ await browser_session.navigate_to(url, init);
7
+ };
8
+ namespace.go_back = async () => {
9
+ await browser_session.go_back();
10
+ };
11
+ namespace.go_forward = async () => {
12
+ await browser_session.go_forward();
13
+ };
14
+ namespace.refresh = async () => {
15
+ await browser_session.refresh();
16
+ };
17
+ namespace.wait = async (seconds) => {
18
+ await browser_session.wait(seconds);
19
+ };
20
+ namespace.click = async (index) => {
21
+ const node = await browser_session.get_dom_element_by_index(index);
22
+ if (!node) {
23
+ throw new Error(`Element index ${index} not found`);
24
+ }
25
+ return browser_session._click_element_node(node);
26
+ };
27
+ namespace.input = async (index, text, clear = true) => {
28
+ const node = await browser_session.get_dom_element_by_index(index);
29
+ if (!node) {
30
+ throw new Error(`Element index ${index} not found`);
31
+ }
32
+ return browser_session._input_text_element_node(node, text, {
33
+ clear,
34
+ });
35
+ };
36
+ namespace.select_dropdown = async (index, text) => {
37
+ const node = await browser_session.get_dom_element_by_index(index);
38
+ if (!node) {
39
+ throw new Error(`Element index ${index} not found`);
40
+ }
41
+ return browser_session.select_dropdown_option(node, text);
42
+ };
43
+ namespace.upload_file = async (index, file_path) => {
44
+ const node = await browser_session.get_dom_element_by_index(index);
45
+ if (!node) {
46
+ throw new Error(`Element index ${index} not found`);
47
+ }
48
+ return browser_session.upload_file(node, file_path);
49
+ };
50
+ namespace.screenshot = async (full_page = false) => {
51
+ return browser_session.take_screenshot(full_page);
52
+ };
53
+ namespace.send_keys = async (keys) => {
54
+ await browser_session.send_keys(keys);
55
+ };
56
+ namespace.evaluate = async (code, ...args) => {
57
+ const page = await browser_session.get_current_page();
58
+ if (!page) {
59
+ throw new Error('No active page for evaluate');
60
+ }
61
+ if (typeof code === 'function') {
62
+ return page.evaluate(code, ...args);
63
+ }
64
+ if (args.length === 0) {
65
+ return page.evaluate(code);
66
+ }
67
+ return page.evaluate(buildExpression(code, args));
68
+ };
69
+ namespace.done = (result = null, success = true) => {
70
+ namespace._task_done = true;
71
+ namespace._task_success = success;
72
+ namespace._task_result =
73
+ typeof result === 'string'
74
+ ? result
75
+ : result == null
76
+ ? null
77
+ : JSON.stringify(result);
78
+ return result;
79
+ };
80
+ return namespace;
81
+ };
@@ -0,0 +1,3 @@
1
+ import type { CodeAgent } from './service.js';
2
+ export declare const export_to_ipynb: (agent: CodeAgent, output_path: string) => string;
3
+ export declare const session_to_python_script: (agent: CodeAgent) => string;
@@ -0,0 +1,56 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ export const export_to_ipynb = (agent, output_path) => {
4
+ const notebook = {
5
+ nbformat: 4,
6
+ nbformat_minor: 5,
7
+ metadata: {
8
+ kernelspec: {
9
+ display_name: 'Node.js',
10
+ language: 'javascript',
11
+ name: 'javascript',
12
+ },
13
+ },
14
+ cells: agent.session.cells.map((cell) => {
15
+ if (cell.cell_type === 'markdown') {
16
+ return {
17
+ cell_type: 'markdown',
18
+ metadata: {},
19
+ source: cell.source.split('\n').map((entry) => `${entry}\n`),
20
+ };
21
+ }
22
+ return {
23
+ cell_type: 'code',
24
+ metadata: {},
25
+ source: cell.source.split('\n').map((entry) => `${entry}\n`),
26
+ execution_count: cell.execution_count,
27
+ outputs: cell.output
28
+ ? [
29
+ {
30
+ output_type: 'stream',
31
+ name: 'stdout',
32
+ text: `${cell.output}\n`,
33
+ },
34
+ ]
35
+ : [],
36
+ };
37
+ }),
38
+ };
39
+ const resolved = path.resolve(output_path);
40
+ fs.mkdirSync(path.dirname(resolved), { recursive: true });
41
+ fs.writeFileSync(resolved, JSON.stringify(notebook, null, 2), 'utf-8');
42
+ return resolved;
43
+ };
44
+ export const session_to_python_script = (agent) => {
45
+ const lines = [];
46
+ lines.push('# Generated from browser-use code-use session');
47
+ lines.push('');
48
+ for (const cell of agent.session.cells) {
49
+ if (cell.cell_type !== 'code') {
50
+ continue;
51
+ }
52
+ lines.push(cell.source);
53
+ lines.push('');
54
+ }
55
+ return lines.join('\n');
56
+ };
@@ -0,0 +1,24 @@
1
+ import { CodeAgentHistory, CodeAgentHistoryList, NotebookSession } from './views.js';
2
+ import type { BrowserSession } from '../browser/session.js';
3
+ type ExecutorFn = (source: string, namespace: Record<string, unknown>) => Promise<unknown>;
4
+ export interface CodeAgentOptions {
5
+ task: string;
6
+ browser_session: BrowserSession;
7
+ namespace?: Record<string, unknown>;
8
+ executor?: ExecutorFn;
9
+ }
10
+ export declare class CodeAgent {
11
+ task: string;
12
+ browser_session: BrowserSession;
13
+ session: NotebookSession;
14
+ namespace: Record<string, unknown>;
15
+ complete_history: CodeAgentHistory[];
16
+ private readonly executor;
17
+ constructor(options: CodeAgentOptions);
18
+ add_cell(source: string): import("./views.js").CodeCell;
19
+ execute_cell(source: string): Promise<import("./views.js").CodeCell>;
20
+ run(max_steps?: number): Promise<CodeAgentHistoryList>;
21
+ get history(): CodeAgentHistoryList;
22
+ close(): Promise<void>;
23
+ }
24
+ export {};
@@ -0,0 +1,104 @@
1
+ import { CodeAgentHistory, CodeAgentHistoryList, CodeAgentState, CodeAgentStepMetadata, NotebookSession, } from './views.js';
2
+ import { create_namespace } from './namespace.js';
3
+ const AsyncFunction = Object.getPrototypeOf(async function () {
4
+ return undefined;
5
+ }).constructor;
6
+ const default_executor = async (source, namespace) => {
7
+ const injectableNames = Object.keys(namespace).filter((name) => /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name));
8
+ const prelude = injectableNames
9
+ .map((name) => `const ${name} = namespace[${JSON.stringify(name)}];`)
10
+ .join('\n');
11
+ const runner = new AsyncFunction('namespace', `${prelude}\n${source}\nreturn undefined;`);
12
+ return runner(namespace);
13
+ };
14
+ export class CodeAgent {
15
+ task;
16
+ browser_session;
17
+ session;
18
+ namespace;
19
+ complete_history = [];
20
+ executor;
21
+ constructor(options) {
22
+ this.task = options.task;
23
+ this.browser_session = options.browser_session;
24
+ this.namespace = create_namespace(options.browser_session, options.namespace ? { namespace: options.namespace } : {});
25
+ this.session = new NotebookSession({ namespace: this.namespace });
26
+ this.executor = options.executor ?? default_executor;
27
+ }
28
+ add_cell(source) {
29
+ return this.session.add_cell(source);
30
+ }
31
+ async execute_cell(source) {
32
+ const cell = this.add_cell(source);
33
+ const startedAt = Date.now() / 1000;
34
+ cell.status = 'running';
35
+ cell.execution_count = this.session.increment_execution_count();
36
+ let resultItem;
37
+ try {
38
+ const output = await this.executor(cell.source, this.namespace);
39
+ cell.status = 'success';
40
+ cell.output =
41
+ output == null
42
+ ? null
43
+ : typeof output === 'string'
44
+ ? output
45
+ : JSON.stringify(output);
46
+ cell.error = null;
47
+ resultItem = {
48
+ extracted_content: cell.output,
49
+ error: null,
50
+ is_done: Boolean(this.namespace._task_done),
51
+ success: typeof this.namespace._task_success === 'boolean'
52
+ ? this.namespace._task_success
53
+ : null,
54
+ };
55
+ }
56
+ catch (error) {
57
+ cell.status = 'error';
58
+ cell.output = null;
59
+ cell.error = String(error?.message ?? error);
60
+ resultItem = {
61
+ extracted_content: null,
62
+ error: cell.error,
63
+ is_done: false,
64
+ success: false,
65
+ };
66
+ }
67
+ const page = await this.browser_session.get_current_page();
68
+ const state = new CodeAgentState({
69
+ url: typeof page?.url === 'function' ? page.url() : null,
70
+ title: typeof page?.title === 'function' ? await page.title() : null,
71
+ });
72
+ const metadata = new CodeAgentStepMetadata({
73
+ step_start_time: startedAt,
74
+ step_end_time: Date.now() / 1000,
75
+ });
76
+ const modelOutput = {
77
+ model_output: cell.source,
78
+ full_response: cell.source,
79
+ };
80
+ const historyItem = new CodeAgentHistory({
81
+ model_output: modelOutput,
82
+ result: [resultItem],
83
+ state,
84
+ metadata,
85
+ });
86
+ this.complete_history.push(historyItem);
87
+ this.session._complete_history = [...this.complete_history];
88
+ return cell;
89
+ }
90
+ async run(max_steps = 100) {
91
+ const pending = this.session.cells.filter((cell) => cell.status === 'pending');
92
+ const toRun = pending.slice(0, Math.max(max_steps, 0));
93
+ for (const cell of toRun) {
94
+ await this.execute_cell(cell.source);
95
+ }
96
+ return this.history;
97
+ }
98
+ get history() {
99
+ return new CodeAgentHistoryList(this.complete_history, null);
100
+ }
101
+ async close() {
102
+ // Keep lifecycle explicit; caller controls browser shutdown.
103
+ }
104
+ }
@@ -0,0 +1,4 @@
1
+ export declare const truncate_message_content: (content: string, max_length?: number) => string;
2
+ export declare const detect_token_limit_issue: (completion: string, completion_tokens: number | null, max_tokens: number | null, stop_reason: string | null) => [boolean, string | null];
3
+ export declare const extract_url_from_task: (task: string) => string | null;
4
+ export declare const extract_code_blocks: (text: string) => Record<string, string>;
@@ -0,0 +1,98 @@
1
+ export const truncate_message_content = (content, max_length = 10000) => {
2
+ if (content.length <= max_length) {
3
+ return content;
4
+ }
5
+ return `${content.slice(0, max_length)}\n\n[... truncated ${content.length - max_length} characters for history]`;
6
+ };
7
+ export const detect_token_limit_issue = (completion, completion_tokens, max_tokens, stop_reason) => {
8
+ if (stop_reason === 'max_tokens') {
9
+ return [true, `Response terminated due to max_tokens (${stop_reason})`];
10
+ }
11
+ if (completion_tokens != null &&
12
+ max_tokens != null &&
13
+ max_tokens > 0 &&
14
+ completion_tokens / max_tokens >= 0.9) {
15
+ return [
16
+ true,
17
+ `Response used ${(completion_tokens / max_tokens) * 100}% of max_tokens (${completion_tokens}/${max_tokens})`,
18
+ ];
19
+ }
20
+ if (completion.length >= 6) {
21
+ const last6 = completion.slice(-6);
22
+ const repeated = completion.split(last6).length - 1;
23
+ if (repeated >= 40) {
24
+ return [
25
+ true,
26
+ `Repetitive output detected: last 6 chars "${last6}" appears ${repeated} times`,
27
+ ];
28
+ }
29
+ }
30
+ return [false, null];
31
+ };
32
+ export const extract_url_from_task = (task) => {
33
+ const withoutEmails = task.replace(/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g, '');
34
+ const matches = [];
35
+ const patterns = [
36
+ /https?:\/\/[^\s<>"']+/g,
37
+ /(?:www\.)?[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*\.[a-zA-Z]{2,}(?:\/[^\s<>"']*)?/g,
38
+ ];
39
+ for (const pattern of patterns) {
40
+ const found = withoutEmails.match(pattern) ?? [];
41
+ for (const entry of found) {
42
+ const trimmed = entry.replace(/[.,;:!?()[\]]+$/g, '');
43
+ matches.push(trimmed.startsWith('http://') || trimmed.startsWith('https://')
44
+ ? trimmed
45
+ : `https://${trimmed}`);
46
+ }
47
+ }
48
+ const unique = [...new Set(matches)];
49
+ if (unique.length !== 1) {
50
+ return null;
51
+ }
52
+ return unique[0];
53
+ };
54
+ export const extract_code_blocks = (text) => {
55
+ const blocks = {};
56
+ const regex = /(`{3,})(\w+)(?:\s+(\w+))?\n([\s\S]*?)\1(?:\n|$)/g;
57
+ let match;
58
+ let pythonIndex = 0;
59
+ while ((match = regex.exec(text)) != null) {
60
+ const langRaw = match[2].toLowerCase();
61
+ const name = match[3] ?? null;
62
+ const content = match[4].replace(/\s+$/, '');
63
+ if (!content) {
64
+ continue;
65
+ }
66
+ const lang = langRaw === 'javascript' || langRaw === 'js'
67
+ ? 'js'
68
+ : langRaw === 'markdown' || langRaw === 'md'
69
+ ? 'markdown'
70
+ : langRaw === 'sh' || langRaw === 'shell'
71
+ ? 'bash'
72
+ : langRaw;
73
+ if (!['python', 'js', 'bash', 'markdown'].includes(lang)) {
74
+ continue;
75
+ }
76
+ if (name) {
77
+ blocks[name] = content;
78
+ continue;
79
+ }
80
+ if (lang === 'python') {
81
+ blocks[`python_${pythonIndex}`] = content;
82
+ pythonIndex += 1;
83
+ continue;
84
+ }
85
+ blocks[lang] = content;
86
+ }
87
+ if (pythonIndex > 0) {
88
+ blocks.python = blocks.python_0;
89
+ }
90
+ else {
91
+ const genericMatches = [...text.matchAll(/```\n([\s\S]*?)```/g)].map((entry) => entry[1].trim());
92
+ const generic = genericMatches.filter(Boolean).join('\n\n');
93
+ if (generic) {
94
+ blocks.python = generic;
95
+ }
96
+ }
97
+ return blocks;
98
+ };
@@ -0,0 +1,108 @@
1
+ import type { UsageSummary } from '../tokens/views.js';
2
+ export type CellType = 'code' | 'markdown';
3
+ export type ExecutionStatus = 'pending' | 'running' | 'success' | 'error';
4
+ export interface CodeCellInit {
5
+ id?: string;
6
+ cell_type?: CellType;
7
+ source: string;
8
+ output?: string | null;
9
+ execution_count?: number | null;
10
+ status?: ExecutionStatus;
11
+ error?: string | null;
12
+ browser_state?: string | null;
13
+ }
14
+ export declare class CodeCell {
15
+ id: string;
16
+ cell_type: CellType;
17
+ source: string;
18
+ output: string | null;
19
+ execution_count: number | null;
20
+ status: ExecutionStatus;
21
+ error: string | null;
22
+ browser_state: string | null;
23
+ constructor(init: CodeCellInit);
24
+ }
25
+ export interface CodeAgentModelOutput {
26
+ model_output: string;
27
+ full_response: string;
28
+ }
29
+ export interface CodeAgentResult {
30
+ extracted_content?: string | null;
31
+ error?: string | null;
32
+ is_done: boolean;
33
+ success?: boolean | null;
34
+ }
35
+ export declare class CodeAgentState {
36
+ url: string | null;
37
+ title: string | null;
38
+ screenshot_path: string | null;
39
+ constructor(init: {
40
+ url?: string | null;
41
+ title?: string | null;
42
+ screenshot_path?: string | null;
43
+ });
44
+ get_screenshot(): string | null;
45
+ }
46
+ export declare class CodeAgentStepMetadata {
47
+ input_tokens: number | null;
48
+ output_tokens: number | null;
49
+ step_start_time: number;
50
+ step_end_time: number;
51
+ constructor(init: {
52
+ input_tokens?: number | null;
53
+ output_tokens?: number | null;
54
+ step_start_time: number;
55
+ step_end_time: number;
56
+ });
57
+ get duration_seconds(): number;
58
+ }
59
+ export declare class CodeAgentHistory {
60
+ model_output: CodeAgentModelOutput | null;
61
+ result: CodeAgentResult[];
62
+ state: CodeAgentState;
63
+ metadata: CodeAgentStepMetadata | null;
64
+ screenshot_path: string | null;
65
+ constructor(init: {
66
+ model_output?: CodeAgentModelOutput | null;
67
+ result?: CodeAgentResult[];
68
+ state: CodeAgentState;
69
+ metadata?: CodeAgentStepMetadata | null;
70
+ screenshot_path?: string | null;
71
+ });
72
+ }
73
+ export declare class CodeAgentHistoryList {
74
+ private readonly complete_history;
75
+ private readonly usage_summary;
76
+ constructor(complete_history: CodeAgentHistory[], usage_summary?: UsageSummary | null);
77
+ get history(): CodeAgentHistory[];
78
+ get usage(): UsageSummary | null;
79
+ final_result(): string | null;
80
+ is_done(): boolean;
81
+ is_successful(): boolean | null;
82
+ errors(): (string | null)[];
83
+ has_errors(): boolean;
84
+ urls(): (string | null)[];
85
+ action_results(): CodeAgentResult[];
86
+ extracted_content(): string[];
87
+ number_of_steps(): number;
88
+ total_duration_seconds(): number;
89
+ }
90
+ export declare class NotebookSession {
91
+ id: string;
92
+ cells: CodeCell[];
93
+ current_execution_count: number;
94
+ namespace: Record<string, unknown>;
95
+ _complete_history: CodeAgentHistory[];
96
+ _usage_summary: UsageSummary | null;
97
+ constructor(init?: {
98
+ id?: string;
99
+ cells?: CodeCell[];
100
+ current_execution_count?: number;
101
+ namespace?: Record<string, unknown>;
102
+ });
103
+ add_cell(source: string): CodeCell;
104
+ get_cell(cell_id: string): CodeCell | null;
105
+ get_latest_cell(): CodeCell;
106
+ increment_execution_count(): number;
107
+ get history(): CodeAgentHistoryList;
108
+ }