browser-use 0.6.0 → 0.7.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 +29 -18
- package/dist/actor/element.js +24 -3
- package/dist/actor/mouse.js +21 -3
- package/dist/actor/page.js +33 -11
- package/dist/agent/gif.js +28 -3
- package/dist/agent/message-manager/service.js +2 -22
- package/dist/agent/message-manager/utils.js +15 -2
- package/dist/agent/message-manager/views.d.ts +7 -7
- package/dist/agent/message-manager/views.js +1 -0
- package/dist/agent/prompts.d.ts +3 -0
- package/dist/agent/prompts.js +22 -12
- package/dist/agent/service.d.ts +9 -1
- package/dist/agent/service.js +215 -81
- package/dist/agent/system_prompt.md +12 -11
- package/dist/agent/system_prompt_anthropic_flash.md +6 -5
- package/dist/agent/system_prompt_no_thinking.md +12 -11
- package/dist/agent/views.d.ts +2 -0
- package/dist/agent/views.js +48 -36
- package/dist/browser/extensions.js +20 -10
- package/dist/browser/profile.d.ts +4 -0
- package/dist/browser/profile.js +107 -4
- package/dist/browser/session.d.ts +28 -1
- package/dist/browser/session.js +1436 -528
- package/dist/browser/watchdogs/default-action-watchdog.js +32 -3
- package/dist/browser/watchdogs/downloads-watchdog.d.ts +4 -0
- package/dist/browser/watchdogs/downloads-watchdog.js +105 -9
- package/dist/browser/watchdogs/har-recording-watchdog.d.ts +1 -0
- package/dist/browser/watchdogs/har-recording-watchdog.js +54 -2
- package/dist/browser/watchdogs/permissions-watchdog.d.ts +5 -0
- package/dist/browser/watchdogs/permissions-watchdog.js +106 -3
- package/dist/browser/watchdogs/recording-watchdog.d.ts +2 -0
- package/dist/browser/watchdogs/recording-watchdog.js +54 -2
- package/dist/browser/watchdogs/security-watchdog.d.ts +1 -0
- package/dist/browser/watchdogs/security-watchdog.js +47 -7
- package/dist/browser/watchdogs/storage-state-watchdog.d.ts +6 -0
- package/dist/browser/watchdogs/storage-state-watchdog.js +206 -14
- package/dist/cli.d.ts +13 -2
- package/dist/cli.js +188 -8
- package/dist/code-use/namespace.js +52 -7
- package/dist/code-use/notebook-export.js +18 -2
- package/dist/code-use/service.js +1 -0
- package/dist/config.js +27 -5
- package/dist/controller/action-timeout.d.ts +9 -0
- package/dist/controller/action-timeout.js +95 -0
- package/dist/controller/registry/service.d.ts +1 -0
- package/dist/controller/registry/service.js +28 -1
- package/dist/controller/registry/views.d.ts +2 -0
- package/dist/controller/registry/views.js +44 -17
- package/dist/controller/service.d.ts +2 -1
- package/dist/controller/service.js +494 -329
- package/dist/filesystem/file-system.js +38 -8
- package/dist/integrations/gmail/service.js +30 -6
- package/dist/llm/browser-use/chat.js +2 -2
- package/dist/llm/codex/auth.d.ts +118 -0
- package/dist/llm/codex/auth.js +599 -0
- package/dist/llm/codex/chat.d.ts +70 -0
- package/dist/llm/codex/chat.js +392 -0
- package/dist/llm/codex/index.d.ts +2 -0
- package/dist/llm/codex/index.js +2 -0
- package/dist/llm/google/chat.js +18 -1
- package/dist/logging-config.js +22 -11
- package/dist/mcp/client.d.ts +1 -0
- package/dist/mcp/client.js +12 -10
- package/dist/mcp/redaction.d.ts +3 -0
- package/dist/mcp/redaction.js +132 -0
- package/dist/mcp/server.d.ts +2 -0
- package/dist/mcp/server.js +64 -22
- package/dist/observability.js +1 -1
- package/dist/screenshots/service.js +25 -2
- package/dist/skill-cli/direct.d.ts +4 -1
- package/dist/skill-cli/direct.js +260 -64
- package/dist/skill-cli/server.d.ts +1 -0
- package/dist/skill-cli/server.js +115 -25
- package/dist/skill-cli/tunnel.d.ts +1 -0
- package/dist/skill-cli/tunnel.js +16 -4
- package/dist/sync/auth.js +22 -9
- package/dist/telemetry/service.js +21 -2
- package/dist/telemetry/views.js +31 -8
- package/dist/tokens/custom-pricing.js +2 -2
- package/dist/tokens/openrouter-pricing.d.ts +11 -0
- package/dist/tokens/openrouter-pricing.js +102 -0
- package/dist/tokens/service.js +20 -16
- package/dist/utils.d.ts +3 -1
- package/dist/utils.js +4 -2
- package/package.json +75 -33
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
## ✨ Features
|
|
24
24
|
|
|
25
25
|
- 🤖 **Autonomous Browser Control** — AI-driven navigation, clicking, typing, form filling, scrolling, and tab management
|
|
26
|
-
- 🧠 **
|
|
26
|
+
- 🧠 **15+ LLM Providers & Adapters** — OpenAI, Anthropic, Google Gemini, Azure, AWS Bedrock, Groq, Ollama, DeepSeek, OpenRouter, Mistral, Cerebras, Browser Use, LiteLLM, OCI Raw, Vercel, and custom providers
|
|
27
27
|
- 👁️ **Vision Support** — Screenshot-based understanding for visual web interactions
|
|
28
28
|
- 🔧 **45+ Built-in Actions** — Navigation, element interaction, scrolling, forms, tabs, content extraction, file I/O, and more
|
|
29
29
|
- 🧩 **Custom Actions** — Extensible registry with Zod schema validation, domain restrictions, and page filters
|
|
@@ -112,7 +112,7 @@ npx browser-use --mcp
|
|
|
112
112
|
| **BrowserSession** | Playwright wrapper — browser lifecycle, tab management, screenshots |
|
|
113
113
|
| **DomService** | Extracts interactive elements with indexed mapping for LLM consumption |
|
|
114
114
|
| **MessageManager** | Manages LLM conversation history with token optimization |
|
|
115
|
-
| **LLM Providers** | Unified `BaseChatModel` interface across
|
|
115
|
+
| **LLM Providers** | Unified `BaseChatModel` interface across 15+ providers and adapters |
|
|
116
116
|
|
|
117
117
|
### How It Works
|
|
118
118
|
|
|
@@ -125,19 +125,24 @@ npx browser-use --mcp
|
|
|
125
125
|
|
|
126
126
|
## 🔌 LLM Providers
|
|
127
127
|
|
|
128
|
-
| Provider | Import
|
|
129
|
-
| ----------------- |
|
|
130
|
-
| **OpenAI** | `browser-use/llm/openai`
|
|
131
|
-
| **
|
|
132
|
-
| **
|
|
133
|
-
| **
|
|
134
|
-
| **
|
|
135
|
-
| **
|
|
136
|
-
| **
|
|
137
|
-
| **
|
|
138
|
-
| **
|
|
139
|
-
| **
|
|
140
|
-
| **
|
|
128
|
+
| Provider | Import | Vision | Notes |
|
|
129
|
+
| ----------------- | ----------------------------- | ------ | ----------------------------------------------- |
|
|
130
|
+
| **OpenAI** | `browser-use/llm/openai` | ✅ | Default provider, reasoning models (o1/o3/o4) |
|
|
131
|
+
| **Codex** | `browser-use/llm/codex` | ✅ | Experimental ChatGPT/Codex OAuth provider |
|
|
132
|
+
| **Anthropic** | `browser-use/llm/anthropic` | ✅ | Prompt caching support |
|
|
133
|
+
| **Google Gemini** | `browser-use/llm/google` | ✅ | Extended thinking support |
|
|
134
|
+
| **Azure OpenAI** | `browser-use/llm/azure` | ✅ | Enterprise deployment |
|
|
135
|
+
| **AWS Bedrock** | `browser-use/llm/aws` | ✅ | Claude via AWS |
|
|
136
|
+
| **Groq** | `browser-use/llm/groq` | ❌ | Fastest inference |
|
|
137
|
+
| **Ollama** | `browser-use/llm/ollama` | ❌ | Local/self-hosted models |
|
|
138
|
+
| **DeepSeek** | `browser-use/llm/deepseek` | ❌ | Cost-effective |
|
|
139
|
+
| **OpenRouter** | `browser-use/llm/openrouter` | Varies | Multi-model routing |
|
|
140
|
+
| **Mistral** | `browser-use/llm/mistral` | Varies | Mistral models |
|
|
141
|
+
| **Cerebras** | `browser-use/llm/cerebras` | ❌ | Fast inference |
|
|
142
|
+
| **Browser Use** | `browser-use/llm/browser-use` | Varies | Hosted Browser Use LLM |
|
|
143
|
+
| **LiteLLM** | `browser-use/llm/litellm` | Varies | OpenAI-compatible LiteLLM gateway |
|
|
144
|
+
| **OCI Raw** | `browser-use/llm/oci-raw` | Varies | Oracle Cloud Generative AI |
|
|
145
|
+
| **Vercel** | `browser-use/llm/vercel` | Varies | Vercel AI Gateway / routed models |
|
|
141
146
|
|
|
142
147
|
<details>
|
|
143
148
|
<summary>Provider examples</summary>
|
|
@@ -167,6 +172,11 @@ const llm = new ChatOllama('llama3', 'http://localhost:11434');
|
|
|
167
172
|
|
|
168
173
|
// OpenAI Reasoning Models
|
|
169
174
|
const llm = new ChatOpenAI({ model: 'o3-mini', reasoningEffort: 'medium' });
|
|
175
|
+
|
|
176
|
+
// Codex OAuth provider (experimental)
|
|
177
|
+
// First run: npx browser-use auth codex login
|
|
178
|
+
import { ChatCodex } from 'browser-use/llm/codex';
|
|
179
|
+
const codexLlm = new ChatCodex({ model: 'gpt-5.5' });
|
|
170
180
|
```
|
|
171
181
|
|
|
172
182
|
</details>
|
|
@@ -210,6 +220,7 @@ const agent = new Agent({
|
|
|
210
220
|
### Custom Actions
|
|
211
221
|
|
|
212
222
|
```typescript
|
|
223
|
+
import fs from 'node:fs';
|
|
213
224
|
import { Controller, ActionResult } from 'browser-use';
|
|
214
225
|
import { z } from 'zod';
|
|
215
226
|
|
|
@@ -345,7 +356,7 @@ Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_
|
|
|
345
356
|
}
|
|
346
357
|
```
|
|
347
358
|
|
|
348
|
-
|
|
359
|
+
Core MCP tools include `retry_with_browser_use_agent`, `browser_navigate`, `browser_click`, `browser_type`, `browser_get_state`, `browser_extract_content`, `browser_scroll`, `browser_go_back`, `browser_list_tabs`, `browser_switch_tab`, `browser_close_tab`, `browser_list_sessions`, `browser_close_session`, and `browser_close_all`. The server also exposes registered controller actions as additional MCP tools.
|
|
349
360
|
|
|
350
361
|
> See [MCP Server Guide](./docs/MCP_SERVER.md) for more details.
|
|
351
362
|
|
|
@@ -354,7 +365,7 @@ Available MCP tools: `browser_run_task`, `browser_navigate`, `browser_click`, `b
|
|
|
354
365
|
- **Sensitive Data Masking** — Credentials are automatically masked in logs and LLM context
|
|
355
366
|
- **Domain Restrictions** — Lock browser navigation to trusted domains
|
|
356
367
|
- **Domain-scoped Secrets** — Credentials are only injected on matching domains
|
|
357
|
-
- **
|
|
368
|
+
- **Sensitive Data Warning** — Browser-Use warns when `sensitive_data` is used without `allowed_domains`
|
|
358
369
|
- **Chromium Sandbox** — Enabled by default for production security
|
|
359
370
|
|
|
360
371
|
```typescript
|
|
@@ -423,4 +434,4 @@ pnpm exec tsx examples/simple-search.ts
|
|
|
423
434
|
|
|
424
435
|
## 📄 License
|
|
425
436
|
|
|
426
|
-
[MIT](./LICENSE)
|
|
437
|
+
[MIT](./LICENSE)
|
package/dist/actor/element.js
CHANGED
|
@@ -18,7 +18,14 @@ export class Element {
|
|
|
18
18
|
if (!locator?.hover) {
|
|
19
19
|
return;
|
|
20
20
|
}
|
|
21
|
-
await
|
|
21
|
+
const page = await this.browser_session.get_current_page();
|
|
22
|
+
await this.browser_session.validate_page_after_action(page);
|
|
23
|
+
try {
|
|
24
|
+
await locator.hover({ timeout: 5000 });
|
|
25
|
+
}
|
|
26
|
+
finally {
|
|
27
|
+
await this.browser_session.validate_page_after_action(page);
|
|
28
|
+
}
|
|
22
29
|
}
|
|
23
30
|
async get_attribute(name) {
|
|
24
31
|
return this.node.attributes?.[name] ?? null;
|
|
@@ -28,7 +35,14 @@ export class Element {
|
|
|
28
35
|
if (!locator?.boundingBox) {
|
|
29
36
|
return null;
|
|
30
37
|
}
|
|
31
|
-
|
|
38
|
+
const page = await this.browser_session.get_current_page();
|
|
39
|
+
await this.browser_session.validate_page_after_action(page);
|
|
40
|
+
try {
|
|
41
|
+
return await locator.boundingBox();
|
|
42
|
+
}
|
|
43
|
+
finally {
|
|
44
|
+
await this.browser_session.validate_page_after_action(page);
|
|
45
|
+
}
|
|
32
46
|
}
|
|
33
47
|
async select_option(values) {
|
|
34
48
|
const list = Array.isArray(values) ? values : [values];
|
|
@@ -41,6 +55,13 @@ export class Element {
|
|
|
41
55
|
if (!locator?.evaluate) {
|
|
42
56
|
throw new Error('Element evaluate is unavailable for this node');
|
|
43
57
|
}
|
|
44
|
-
|
|
58
|
+
const page = await this.browser_session.get_current_page();
|
|
59
|
+
await this.browser_session.validate_page_after_action(page);
|
|
60
|
+
try {
|
|
61
|
+
return await locator.evaluate(page_function, ...args);
|
|
62
|
+
}
|
|
63
|
+
finally {
|
|
64
|
+
await this.browser_session.validate_page_after_action(page);
|
|
65
|
+
}
|
|
45
66
|
}
|
|
46
67
|
}
|
package/dist/actor/mouse.js
CHANGED
|
@@ -20,20 +20,38 @@ export class Mouse {
|
|
|
20
20
|
if (!page?.mouse?.move) {
|
|
21
21
|
return;
|
|
22
22
|
}
|
|
23
|
-
await
|
|
23
|
+
await this.browser_session.validate_page_after_action(page);
|
|
24
|
+
try {
|
|
25
|
+
await page.mouse.move(x, y);
|
|
26
|
+
}
|
|
27
|
+
finally {
|
|
28
|
+
await this.browser_session.validate_page_after_action(page);
|
|
29
|
+
}
|
|
24
30
|
}
|
|
25
31
|
async down(options = {}) {
|
|
26
32
|
const page = await this._page();
|
|
27
33
|
if (!page?.mouse?.down) {
|
|
28
34
|
return;
|
|
29
35
|
}
|
|
30
|
-
await
|
|
36
|
+
await this.browser_session.validate_page_after_action(page);
|
|
37
|
+
try {
|
|
38
|
+
await page.mouse.down({ button: options.button ?? 'left' });
|
|
39
|
+
}
|
|
40
|
+
finally {
|
|
41
|
+
await this.browser_session.validate_page_after_action(page);
|
|
42
|
+
}
|
|
31
43
|
}
|
|
32
44
|
async up(options = {}) {
|
|
33
45
|
const page = await this._page();
|
|
34
46
|
if (!page?.mouse?.up) {
|
|
35
47
|
return;
|
|
36
48
|
}
|
|
37
|
-
await
|
|
49
|
+
await this.browser_session.validate_page_after_action(page);
|
|
50
|
+
try {
|
|
51
|
+
await page.mouse.up({ button: options.button ?? 'left' });
|
|
52
|
+
}
|
|
53
|
+
finally {
|
|
54
|
+
await this.browser_session.validate_page_after_action(page);
|
|
55
|
+
}
|
|
38
56
|
}
|
|
39
57
|
}
|
package/dist/actor/page.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Element } from './element.js';
|
|
2
2
|
import { Mouse } from './mouse.js';
|
|
3
|
+
const buildExpression = (source, args) => `(${source})(${args.map((arg) => JSON.stringify(arg)).join(',')})`;
|
|
3
4
|
export class Page {
|
|
4
5
|
browser_session;
|
|
5
6
|
_mouse = null;
|
|
@@ -21,11 +22,23 @@ export class Page {
|
|
|
21
22
|
}
|
|
22
23
|
async get_url() {
|
|
23
24
|
const page = await this._currentPage();
|
|
24
|
-
|
|
25
|
+
await this.browser_session.validate_page_after_action(page);
|
|
26
|
+
try {
|
|
27
|
+
return typeof page.url === 'function' ? page.url() : '';
|
|
28
|
+
}
|
|
29
|
+
finally {
|
|
30
|
+
await this.browser_session.validate_page_after_action(page);
|
|
31
|
+
}
|
|
25
32
|
}
|
|
26
33
|
async get_title() {
|
|
27
34
|
const page = await this._currentPage();
|
|
28
|
-
|
|
35
|
+
await this.browser_session.validate_page_after_action(page);
|
|
36
|
+
try {
|
|
37
|
+
return typeof page.title === 'function' ? page.title() : '';
|
|
38
|
+
}
|
|
39
|
+
finally {
|
|
40
|
+
await this.browser_session.validate_page_after_action(page);
|
|
41
|
+
}
|
|
29
42
|
}
|
|
30
43
|
async goto(url, options = {}) {
|
|
31
44
|
await this.browser_session.navigate_to(url, {
|
|
@@ -47,16 +60,19 @@ export class Page {
|
|
|
47
60
|
}
|
|
48
61
|
async evaluate(page_function, ...args) {
|
|
49
62
|
const page = await this._currentPage();
|
|
50
|
-
|
|
51
|
-
|
|
63
|
+
await this.browser_session.validate_page_after_action(page);
|
|
64
|
+
try {
|
|
65
|
+
if (typeof page_function === 'function') {
|
|
66
|
+
return await page.evaluate(page_function, ...args);
|
|
67
|
+
}
|
|
68
|
+
if (args.length === 0) {
|
|
69
|
+
return await page.evaluate(page_function);
|
|
70
|
+
}
|
|
71
|
+
return await page.evaluate(buildExpression(page_function, args));
|
|
52
72
|
}
|
|
53
|
-
|
|
54
|
-
|
|
73
|
+
finally {
|
|
74
|
+
await this.browser_session.validate_page_after_action(page);
|
|
55
75
|
}
|
|
56
|
-
const expression = `(${page_function})(${args
|
|
57
|
-
.map((arg) => JSON.stringify(arg))
|
|
58
|
-
.join(',')})`;
|
|
59
|
-
return page.evaluate(expression);
|
|
60
76
|
}
|
|
61
77
|
async screenshot(options = {}) {
|
|
62
78
|
return this.browser_session.take_screenshot(options.full_page ?? false);
|
|
@@ -69,7 +85,13 @@ export class Page {
|
|
|
69
85
|
if (!page.setViewportSize) {
|
|
70
86
|
return;
|
|
71
87
|
}
|
|
72
|
-
await
|
|
88
|
+
await this.browser_session.validate_page_after_action(page);
|
|
89
|
+
try {
|
|
90
|
+
await page.setViewportSize({ width, height });
|
|
91
|
+
}
|
|
92
|
+
finally {
|
|
93
|
+
await this.browser_session.validate_page_after_action(page);
|
|
94
|
+
}
|
|
73
95
|
}
|
|
74
96
|
async get_element_by_index(index) {
|
|
75
97
|
const node = await this.browser_session.get_dom_element_by_index(index);
|
package/dist/agent/gif.js
CHANGED
|
@@ -6,6 +6,29 @@ import { createLogger } from '../logging-config.js';
|
|
|
6
6
|
import { PLACEHOLDER_4PX_SCREENSHOT } from '../browser/views.js';
|
|
7
7
|
import { is_new_tab_page } from '../utils.js';
|
|
8
8
|
const logger = createLogger('browser_use.agent.gif');
|
|
9
|
+
const chmodPrivateFile = (filePath) => {
|
|
10
|
+
if (process.platform === 'win32') {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
try {
|
|
14
|
+
fs.chmodSync(filePath, 0o600);
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
/* best effort */
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
const ensurePrivateDirectoryIfCreated = async (dirPath) => {
|
|
21
|
+
const existed = fs.existsSync(dirPath);
|
|
22
|
+
await fs.promises.mkdir(dirPath, { recursive: true, mode: 0o700 });
|
|
23
|
+
if (!existed && process.platform !== 'win32') {
|
|
24
|
+
try {
|
|
25
|
+
await fs.promises.chmod(dirPath, 0o700);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
/* best effort */
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
};
|
|
9
32
|
export const decode_unicode_escapes_to_utf8 = (text) => {
|
|
10
33
|
if (!text.includes('\\u')) {
|
|
11
34
|
return text;
|
|
@@ -186,10 +209,11 @@ export const create_history_gif = async (task, history, { output_path = 'agent_h
|
|
|
186
209
|
const canvas = createCanvas(width, height);
|
|
187
210
|
const ctx = canvas.getContext('2d');
|
|
188
211
|
const encoder = new GIFEncoder(width, height);
|
|
189
|
-
|
|
190
|
-
|
|
212
|
+
const resolvedOutputPath = path.resolve(output_path);
|
|
213
|
+
await ensurePrivateDirectoryIfCreated(path.dirname(resolvedOutputPath));
|
|
214
|
+
const writeStream = fs.createWriteStream(resolvedOutputPath, {
|
|
215
|
+
mode: 0o600,
|
|
191
216
|
});
|
|
192
|
-
const writeStream = fs.createWriteStream(path.resolve(output_path));
|
|
193
217
|
encoder.createReadStream().pipe(writeStream);
|
|
194
218
|
encoder.start();
|
|
195
219
|
encoder.setRepeat(0);
|
|
@@ -233,5 +257,6 @@ export const create_history_gif = async (task, history, { output_path = 'agent_h
|
|
|
233
257
|
writeStream.on('finish', resolve);
|
|
234
258
|
writeStream.on('error', reject);
|
|
235
259
|
});
|
|
260
|
+
chmodPrivateFile(resolvedOutputPath);
|
|
236
261
|
logger.info(`Created GIF at ${output_path}`);
|
|
237
262
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ContentPartTextParam, SystemMessage, UserMessage, } from '../../llm/messages.js';
|
|
2
|
+
import { redactSensitiveDataFromString, } from '../views.js';
|
|
2
3
|
import { AgentMessagePrompt } from '../prompts.js';
|
|
3
4
|
import { MessageManagerState, HistoryItem } from './views.js';
|
|
4
5
|
import { match_url_with_domain_pattern } from '../../utils.js';
|
|
@@ -336,28 +337,7 @@ export class MessageManager {
|
|
|
336
337
|
if (!this.sensitiveData) {
|
|
337
338
|
return message;
|
|
338
339
|
}
|
|
339
|
-
const replaceSensitive = (value) =>
|
|
340
|
-
const placeholders = {};
|
|
341
|
-
for (const [keyOrDomain, content] of Object.entries(this.sensitiveData)) {
|
|
342
|
-
if (content && typeof content === 'object' && !Array.isArray(content)) {
|
|
343
|
-
for (const [k, v] of Object.entries(content)) {
|
|
344
|
-
if (v)
|
|
345
|
-
placeholders[k] = v;
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
else if (typeof content === 'string') {
|
|
349
|
-
placeholders[keyOrDomain] = content;
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
if (!Object.keys(placeholders).length) {
|
|
353
|
-
return value;
|
|
354
|
-
}
|
|
355
|
-
let updated = value;
|
|
356
|
-
for (const [key, val] of Object.entries(placeholders)) {
|
|
357
|
-
updated = updated.replaceAll(val, `<secret>${key}</secret>`);
|
|
358
|
-
}
|
|
359
|
-
return updated;
|
|
360
|
-
};
|
|
340
|
+
const replaceSensitive = (value) => redactSensitiveDataFromString(value, this.sensitiveData ?? null);
|
|
361
341
|
if (typeof message.content === 'string') {
|
|
362
342
|
message.content = replaceSensitive(message.content);
|
|
363
343
|
}
|
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
+
const chmodPrivateFile = (filePath) => {
|
|
4
|
+
if (process.platform !== 'win32') {
|
|
5
|
+
fs.chmodSync(filePath, 0o600);
|
|
6
|
+
}
|
|
7
|
+
};
|
|
8
|
+
const ensurePrivateDirectoryIfCreated = async (dirPath) => {
|
|
9
|
+
const existed = fs.existsSync(dirPath);
|
|
10
|
+
await fs.promises.mkdir(dirPath, { recursive: true, mode: 0o700 });
|
|
11
|
+
if (!existed && process.platform !== 'win32') {
|
|
12
|
+
await fs.promises.chmod(dirPath, 0o700);
|
|
13
|
+
}
|
|
14
|
+
};
|
|
3
15
|
const serializeResponse = (response) => {
|
|
4
16
|
if (!response) {
|
|
5
17
|
return '';
|
|
@@ -34,7 +46,8 @@ const formatConversation = (messages, response) => {
|
|
|
34
46
|
};
|
|
35
47
|
export const saveConversation = async (inputMessages, response, target, encoding = 'utf-8') => {
|
|
36
48
|
const targetPath = path.resolve(target);
|
|
37
|
-
await
|
|
49
|
+
await ensurePrivateDirectoryIfCreated(path.dirname(targetPath));
|
|
38
50
|
const payload = formatConversation(inputMessages, response);
|
|
39
|
-
await fs.promises.writeFile(targetPath, payload, { encoding });
|
|
51
|
+
await fs.promises.writeFile(targetPath, payload, { encoding, mode: 0o600 });
|
|
52
|
+
chmodPrivateFile(targetPath);
|
|
40
53
|
};
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { Message } from '../../llm/messages.js';
|
|
2
2
|
export declare class HistoryItem {
|
|
3
|
-
step_number: number | null;
|
|
4
|
-
evaluation_previous_goal: string | null;
|
|
5
|
-
memory: string | null;
|
|
6
|
-
next_goal: string | null;
|
|
7
|
-
action_results: string | null;
|
|
8
|
-
error: string | null;
|
|
9
|
-
system_message: string | null;
|
|
3
|
+
readonly step_number: number | null;
|
|
4
|
+
readonly evaluation_previous_goal: string | null;
|
|
5
|
+
readonly memory: string | null;
|
|
6
|
+
readonly next_goal: string | null;
|
|
7
|
+
readonly action_results: string | null;
|
|
8
|
+
readonly error: string | null;
|
|
9
|
+
readonly system_message: string | null;
|
|
10
10
|
constructor(step_number?: number | null, evaluation_previous_goal?: string | null, memory?: string | null, next_goal?: string | null, action_results?: string | null, error?: string | null, system_message?: string | null);
|
|
11
11
|
to_string(): string;
|
|
12
12
|
}
|
|
@@ -17,6 +17,7 @@ export class HistoryItem {
|
|
|
17
17
|
if (this.error && this.system_message) {
|
|
18
18
|
throw new Error('Cannot have both error and system_message at the same time');
|
|
19
19
|
}
|
|
20
|
+
Object.freeze(this);
|
|
20
21
|
}
|
|
21
22
|
to_string() {
|
|
22
23
|
const stepStr = this.step_number != null ? 'step' : 'step_unknown';
|
package/dist/agent/prompts.d.ts
CHANGED
|
@@ -62,6 +62,9 @@ export declare class AgentMessagePrompt {
|
|
|
62
62
|
constructor(init: AgentMessagePromptInit);
|
|
63
63
|
private extractPageStatistics;
|
|
64
64
|
private browserStateDescription;
|
|
65
|
+
private currentDateString;
|
|
66
|
+
private userRequestDescription;
|
|
67
|
+
private stepMetaDescription;
|
|
65
68
|
private agentStateDescription;
|
|
66
69
|
private resizeScreenshotForLlm;
|
|
67
70
|
get_user_message(use_vision?: boolean): UserMessage;
|
package/dist/agent/prompts.js
CHANGED
|
@@ -268,20 +268,30 @@ ${recentEventsText}${closedPopupsText}${pdfMessage}Interactive elements${truncat
|
|
|
268
268
|
${elementsText}
|
|
269
269
|
`;
|
|
270
270
|
}
|
|
271
|
-
|
|
272
|
-
const todoContents = this.fileSystem.get_todo_contents();
|
|
273
|
-
const todoText = todoContents || '[empty todo.md, fill it when applicable]';
|
|
271
|
+
currentDateString() {
|
|
274
272
|
const now = new Date();
|
|
275
273
|
const pad = (value) => String(value).padStart(2, '0');
|
|
276
|
-
|
|
274
|
+
return `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}`;
|
|
275
|
+
}
|
|
276
|
+
userRequestDescription() {
|
|
277
|
+
return `<user_request>
|
|
278
|
+
${this.task ?? ''}
|
|
279
|
+
</user_request>
|
|
280
|
+
|
|
281
|
+
`;
|
|
282
|
+
}
|
|
283
|
+
stepMetaDescription() {
|
|
277
284
|
let stepInfoDescription = this.stepInfo != null
|
|
278
285
|
? `Step${this.stepInfo.step_number + 1} maximum:${this.stepInfo.max_steps}\n`
|
|
279
286
|
: '';
|
|
280
|
-
stepInfoDescription += `Today:${
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
287
|
+
stepInfoDescription += `Today:${this.currentDateString()}`;
|
|
288
|
+
return `<step_info>${stepInfoDescription}</step_info>
|
|
289
|
+
`;
|
|
290
|
+
}
|
|
291
|
+
agentStateDescription() {
|
|
292
|
+
const todoContents = this.fileSystem.get_todo_contents();
|
|
293
|
+
const todoText = todoContents || '[empty todo.md, fill it when applicable]';
|
|
294
|
+
let agentState = `<file_system>
|
|
285
295
|
${this.fileSystem.describe()}
|
|
286
296
|
</file_system>
|
|
287
297
|
<todo_contents>
|
|
@@ -298,8 +308,6 @@ ${this.planDescription}
|
|
|
298
308
|
agentState += `<sensitive_data>${this.sensitiveData}</sensitive_data>
|
|
299
309
|
`;
|
|
300
310
|
}
|
|
301
|
-
agentState += `<step_info>${stepInfoDescription}</step_info>
|
|
302
|
-
`;
|
|
303
311
|
if (this.availableFilePaths?.length) {
|
|
304
312
|
agentState += `<available_file_paths>${this.availableFilePaths.join('\n')}
|
|
305
313
|
Use with absolute paths</available_file_paths>
|
|
@@ -337,7 +345,8 @@ Use with absolute paths</available_file_paths>
|
|
|
337
345
|
this.browserState.tabs.length === 1) {
|
|
338
346
|
use_vision = false;
|
|
339
347
|
}
|
|
340
|
-
let stateDescription =
|
|
348
|
+
let stateDescription = this.userRequestDescription();
|
|
349
|
+
stateDescription += `<agent_history>
|
|
341
350
|
${(this.agentHistoryDescription ?? '').trim()}
|
|
342
351
|
</agent_history>
|
|
343
352
|
|
|
@@ -366,6 +375,7 @@ ${this.pageFilteredActions}
|
|
|
366
375
|
if (this.unavailableSkillsInfo) {
|
|
367
376
|
stateDescription += `\n${this.unavailableSkillsInfo}\n`;
|
|
368
377
|
}
|
|
378
|
+
stateDescription += this.stepMetaDescription();
|
|
369
379
|
stateDescription = sanitize_surrogates(stateDescription);
|
|
370
380
|
const hasReadStateImages = this.readStateImages.length > 0;
|
|
371
381
|
if ((use_vision === true && this.screenshots.length > 0) ||
|
package/dist/agent/service.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ import type { StructuredOutputParser } from './views.js';
|
|
|
15
15
|
import { ScreenshotService } from '../screenshots/service.js';
|
|
16
16
|
import { ProductTelemetry } from '../telemetry/service.js';
|
|
17
17
|
import { type SkillService } from '../skills/index.js';
|
|
18
|
-
export declare const log_response: (response: AgentOutput, registry?: Controller<any>, logInstance?: import("../logging-config.js").Logger) => void;
|
|
18
|
+
export declare const log_response: (response: AgentOutput, registry?: Controller<any>, logInstance?: import("../logging-config.js").Logger, sensitive_data?: Record<string, string | Record<string, string>> | null) => void;
|
|
19
19
|
type ControllerContext = unknown;
|
|
20
20
|
type AgentHookFunc<Context, AgentStructuredOutput> = (agent: Agent<Context, AgentStructuredOutput>) => Promise<void> | void;
|
|
21
21
|
interface RerunHistoryOptions {
|
|
@@ -162,6 +162,7 @@ export declare class Agent<Context = ControllerContext, AgentStructuredOutput =
|
|
|
162
162
|
private _url_shortening_limit;
|
|
163
163
|
private skill_service;
|
|
164
164
|
private _skills_registered;
|
|
165
|
+
private _redactSensitiveText;
|
|
165
166
|
constructor(params: AgentConstructorParams<Context, AgentStructuredOutput>);
|
|
166
167
|
private _normalizeMessageCompactionSetting;
|
|
167
168
|
private _createSessionIdWithAgentSuffix;
|
|
@@ -243,6 +244,7 @@ export declare class Agent<Context = ControllerContext, AgentStructuredOutput =
|
|
|
243
244
|
* Initially only include actions with no filters
|
|
244
245
|
*/
|
|
245
246
|
private _setup_action_models;
|
|
247
|
+
private _filter_cookies_for_domain_policy;
|
|
246
248
|
private _register_skills_as_actions;
|
|
247
249
|
private _get_unavailable_skills_info;
|
|
248
250
|
/**
|
|
@@ -263,7 +265,13 @@ export declare class Agent<Context = ControllerContext, AgentStructuredOutput =
|
|
|
263
265
|
multi_act(actions: Array<Record<string, Record<string, unknown>>>, options?: {
|
|
264
266
|
check_for_new_elements?: boolean;
|
|
265
267
|
signal?: AbortSignal | null;
|
|
268
|
+
action_timeout?: number | null;
|
|
266
269
|
}): Promise<ActionResult[]>;
|
|
270
|
+
private _shouldPropagateActionError;
|
|
271
|
+
private _isConnectionLikeError;
|
|
272
|
+
private _formatActionExecutionError;
|
|
273
|
+
private _actionResultFromBrowserError;
|
|
274
|
+
private _actionResultFromRegistryTimeout;
|
|
267
275
|
private _generate_rerun_summary;
|
|
268
276
|
private _execute_ai_step;
|
|
269
277
|
rerun_history(history: AgentHistoryList, options?: RerunHistoryOptions): Promise<ActionResult[]>;
|