agentic-browser 2.1.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +1 -1
- package/README.md +5 -3
- package/dist/cli/index.mjs +15 -8
- package/dist/index.mjs +1 -1
- package/dist/mcp/index.mjs +63 -11
- package/dist/{runtime-CEvs2yzE.mjs → runtime-BCGndjhR.mjs} +779 -79
- package/package.json +5 -5
package/AGENTS.md
CHANGED
|
@@ -108,7 +108,7 @@ AgenticBrowserCore → ControlApi → SessionManager → BrowserController (CDP)
|
|
|
108
108
|
|
|
109
109
|
## Environment Variables
|
|
110
110
|
|
|
111
|
-
- `
|
|
111
|
+
- `AGENTIC_BROWSER_DIR` — base dir for sessions/memory/events (default: `.agentic-browser`)
|
|
112
112
|
- `AGENTIC_BROWSER_CHROME_EXECUTABLE_PATH` — explicit Chrome path (auto-discovered if not set)
|
|
113
113
|
- `AGENTIC_BROWSER_CDP_URL` — connect to an already-running Chrome via CDP (e.g. `http://127.0.0.1:9222`)
|
|
114
114
|
- `AGENTIC_BROWSER_USER_PROFILE` — use real Chrome profile (`default`, `true`, or absolute path)
|
package/README.md
CHANGED
|
@@ -113,7 +113,7 @@ agentic-browser agent start --user-agent "MyBot/1.0"
|
|
|
113
113
|
agentic-browser agent status
|
|
114
114
|
agentic-browser agent navigate https://example.com
|
|
115
115
|
agentic-browser agent click "#login"
|
|
116
|
-
agentic-browser agent content --mode
|
|
116
|
+
agentic-browser agent content --mode summary
|
|
117
117
|
agentic-browser agent content --mode html --selector main
|
|
118
118
|
agentic-browser agent elements
|
|
119
119
|
agentic-browser agent elements --roles button,link --limit 20
|
|
@@ -156,6 +156,8 @@ MCP responses are compact — `visible`, `actions`, and `tagName` are omitted to
|
|
|
156
156
|
|
|
157
157
|
When an element lives inside an open shadow root or a same-origin iframe, discovery returns a composed locator using `>>>` to cross boundaries, for example `iframe[name="checkout"] >>> button[aria-label="Pay"]`. The same locator string works with `agent click`, `agent type`, MCP `browser_interact`, and fallback selectors.
|
|
158
158
|
|
|
159
|
+
`agent content` and MCP `browser_get_content` now default to `summary`, which returns a low-token overview with `title`, `headings`, `landmarks`, `primaryActions`, `inputs`, `alerts`, and iframe metadata. Use `a11y` when you need the deeper accessibility structure, and `text` or `html` only when you need raw content.
|
|
160
|
+
|
|
159
161
|
````
|
|
160
162
|
|
|
161
163
|
## MCP Server
|
|
@@ -225,8 +227,8 @@ More `interact` actions:
|
|
|
225
227
|
### 4. Read Page Content
|
|
226
228
|
|
|
227
229
|
```bash
|
|
230
|
+
agentic-browser page:content <sessionId> --mode summary
|
|
228
231
|
agentic-browser page:content <sessionId> --mode title
|
|
229
|
-
agentic-browser page:content <sessionId> --mode text
|
|
230
232
|
agentic-browser page:content <sessionId> --mode html --selector main
|
|
231
233
|
```
|
|
232
234
|
|
|
@@ -265,7 +267,7 @@ agentic-browser memory:stats
|
|
|
265
267
|
## Important Notes for LLMs
|
|
266
268
|
|
|
267
269
|
- Exactly **one** managed session is supported at a time.
|
|
268
|
-
- Session state is persisted in
|
|
270
|
+
- Session state is persisted in `~/.agentic-browser/` (override with `AGENTIC_BROWSER_DIR`).
|
|
269
271
|
- All commands print exactly one JSON line to `stdout`.
|
|
270
272
|
- The typed `agent` commands are the preferred interface for LLMs. Use low-level `command:run` only when you need raw JSON payload control.
|
|
271
273
|
- Parse only `stdout` as result object and use exit code for success/failure.
|
package/dist/cli/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { r as createCliRuntime } from "../runtime-
|
|
2
|
+
import { r as createCliRuntime } from "../runtime-BCGndjhR.mjs";
|
|
3
3
|
import fs from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import crypto from "node:crypto";
|
|
@@ -7,7 +7,7 @@ import { Command } from "commander";
|
|
|
7
7
|
//#region src/cli/commands/agent.ts
|
|
8
8
|
const STATE_FILE_NAME = "agent-state.json";
|
|
9
9
|
function stateFilePath(runtime) {
|
|
10
|
-
return path.join(runtime.context.config.
|
|
10
|
+
return path.join(runtime.context.config.dataDir, STATE_FILE_NAME);
|
|
11
11
|
}
|
|
12
12
|
function loadState(runtime) {
|
|
13
13
|
const filePath = stateFilePath(runtime);
|
|
@@ -151,7 +151,8 @@ async function agentContent(runtime, input) {
|
|
|
151
151
|
action: "content",
|
|
152
152
|
...await runtime.api.getContent(sessionId, {
|
|
153
153
|
mode: input.mode,
|
|
154
|
-
selector: input.selector
|
|
154
|
+
selector: input.selector,
|
|
155
|
+
maxChars: input.maxChars
|
|
155
156
|
})
|
|
156
157
|
};
|
|
157
158
|
}
|
|
@@ -249,7 +250,8 @@ async function runCommand(runtime, input) {
|
|
|
249
250
|
async function runPageContent(runtime, input) {
|
|
250
251
|
return await runtime.api.getContent(input.sessionId, {
|
|
251
252
|
mode: input.mode,
|
|
252
|
-
selector: input.selector
|
|
253
|
+
selector: input.selector,
|
|
254
|
+
maxChars: input.maxChars
|
|
253
255
|
});
|
|
254
256
|
}
|
|
255
257
|
//#endregion
|
|
@@ -322,11 +324,12 @@ async function main() {
|
|
|
322
324
|
});
|
|
323
325
|
console.log(JSON.stringify(result));
|
|
324
326
|
});
|
|
325
|
-
program.command("page:content").argument("<sessionId>").option("--mode <mode>", "title|text|html|a11y", "
|
|
327
|
+
program.command("page:content").argument("<sessionId>").option("--mode <mode>", "title|text|html|a11y|summary", "summary").option("--selector <selector>", "optional CSS selector").option("--max-chars <n>", "max characters for text/html/a11y modes").action(async (sessionId, options) => {
|
|
326
328
|
const result = await runPageContent(runtime, {
|
|
327
329
|
sessionId,
|
|
328
330
|
mode: options.mode,
|
|
329
|
-
selector: options.selector
|
|
331
|
+
selector: options.selector,
|
|
332
|
+
maxChars: options.maxChars ? Number.parseInt(options.maxChars, 10) : void 0
|
|
330
333
|
});
|
|
331
334
|
console.log(JSON.stringify(result));
|
|
332
335
|
});
|
|
@@ -470,8 +473,12 @@ async function main() {
|
|
|
470
473
|
const result = await agentTerminate(runtime);
|
|
471
474
|
console.log(JSON.stringify(result));
|
|
472
475
|
});
|
|
473
|
-
agent.command("content").option("--mode <mode>", "title|text|html|a11y", "
|
|
474
|
-
const result = await agentContent(runtime,
|
|
476
|
+
agent.command("content").option("--mode <mode>", "title|text|html|a11y|summary", "summary").option("--selector <selector>", "optional CSS selector").option("--max-chars <n>", "max characters for text/html/a11y modes").action(async (options) => {
|
|
477
|
+
const result = await agentContent(runtime, {
|
|
478
|
+
mode: options.mode,
|
|
479
|
+
selector: options.selector,
|
|
480
|
+
maxChars: options.maxChars ? Number.parseInt(options.maxChars, 10) : void 0
|
|
481
|
+
});
|
|
475
482
|
console.log(JSON.stringify(result));
|
|
476
483
|
});
|
|
477
484
|
agent.command("elements").description("List interactive elements on the current page").option("--roles <roles>", "comma-separated roles filter", (v) => v.split(",")).option("--visible-only", "only visible elements", true).option("--no-visible-only", "include hidden elements").option("--limit <n>", "max elements", "50").option("--selector <selector>", "scope to CSS selector subtree").action(async (options) => {
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { i as createMockAgenticBrowserCore, n as createAgenticBrowserCore, t as AgenticBrowserCore } from "./runtime-
|
|
2
|
+
import { i as createMockAgenticBrowserCore, n as createAgenticBrowserCore, t as AgenticBrowserCore } from "./runtime-BCGndjhR.mjs";
|
|
3
3
|
export { AgenticBrowserCore, createAgenticBrowserCore, createMockAgenticBrowserCore };
|
package/dist/mcp/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { n as createAgenticBrowserCore } from "../runtime-
|
|
2
|
+
import { n as createAgenticBrowserCore } from "../runtime-BCGndjhR.mjs";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
5
5
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
@@ -22,10 +22,27 @@ function truncateContent(content, limit) {
|
|
|
22
22
|
};
|
|
23
23
|
const originalLength = content.length;
|
|
24
24
|
return {
|
|
25
|
-
content: content.slice(0, limit) + `\n\n[Truncated
|
|
25
|
+
content: content.slice(0, limit) + `\n\n[Truncated - showing first ${limit} of ${originalLength} characters. Use a CSS selector to scope the content, or use mode="summary" for a lower-token overview.]`,
|
|
26
26
|
truncated: true
|
|
27
27
|
};
|
|
28
28
|
}
|
|
29
|
+
function resolveCompactedContent(result, limit) {
|
|
30
|
+
if (result.truncated) return {
|
|
31
|
+
content: result.content,
|
|
32
|
+
truncated: true
|
|
33
|
+
};
|
|
34
|
+
return truncateContent(result.content, limit);
|
|
35
|
+
}
|
|
36
|
+
function parseStructuredSummary(result) {
|
|
37
|
+
if (result.structuredContent) return result.structuredContent;
|
|
38
|
+
if (!result.content) return;
|
|
39
|
+
try {
|
|
40
|
+
const parsed = JSON.parse(result.content);
|
|
41
|
+
return parsed && typeof parsed === "object" ? parsed : void 0;
|
|
42
|
+
} catch {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
29
46
|
function summarizeTextContent(content) {
|
|
30
47
|
const lines = uniqueLines(content);
|
|
31
48
|
return {
|
|
@@ -68,9 +85,23 @@ function compactPageContent(result, maxChars) {
|
|
|
68
85
|
text: 8e3,
|
|
69
86
|
a11y: 1e4,
|
|
70
87
|
html: 4e3,
|
|
71
|
-
title: void 0
|
|
88
|
+
title: void 0,
|
|
89
|
+
summary: void 0
|
|
72
90
|
}[result.mode];
|
|
73
|
-
|
|
91
|
+
if (result.mode === "summary") {
|
|
92
|
+
const structured = parseStructuredSummary(result);
|
|
93
|
+
if (structured) return {
|
|
94
|
+
mode: "summary",
|
|
95
|
+
...structured,
|
|
96
|
+
truncated: false
|
|
97
|
+
};
|
|
98
|
+
return {
|
|
99
|
+
mode: "summary",
|
|
100
|
+
content: result.content,
|
|
101
|
+
truncated: false
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
const truncated = resolveCompactedContent(result, limit);
|
|
74
105
|
if (result.mode === "title") return {
|
|
75
106
|
...result,
|
|
76
107
|
truncated: false
|
|
@@ -81,6 +112,7 @@ function compactPageContent(result, maxChars) {
|
|
|
81
112
|
mode: result.mode,
|
|
82
113
|
content: truncated.content,
|
|
83
114
|
truncated: truncated.truncated,
|
|
115
|
+
originalLength: result.originalLength,
|
|
84
116
|
summaryLines: summary.summaryLines,
|
|
85
117
|
previewLines: summary.previewLines
|
|
86
118
|
};
|
|
@@ -91,6 +123,7 @@ function compactPageContent(result, maxChars) {
|
|
|
91
123
|
mode: result.mode,
|
|
92
124
|
content: truncated.content,
|
|
93
125
|
truncated: truncated.truncated,
|
|
126
|
+
originalLength: result.originalLength,
|
|
94
127
|
headings: summary.headings,
|
|
95
128
|
landmarks: summary.landmarks,
|
|
96
129
|
actions: summary.actions,
|
|
@@ -101,7 +134,8 @@ function compactPageContent(result, maxChars) {
|
|
|
101
134
|
return {
|
|
102
135
|
mode: result.mode,
|
|
103
136
|
content: truncated.content,
|
|
104
|
-
truncated: truncated.truncated
|
|
137
|
+
truncated: truncated.truncated,
|
|
138
|
+
originalLength: result.originalLength
|
|
105
139
|
};
|
|
106
140
|
}
|
|
107
141
|
function summarizeElements(elements) {
|
|
@@ -152,6 +186,14 @@ function compactMemoryResults(results) {
|
|
|
152
186
|
if (Array.isArray(compactAlias.fallbackSelectors) && compactAlias.fallbackSelectors.length === 0) delete compactAlias.fallbackSelectors;
|
|
153
187
|
return compactAlias;
|
|
154
188
|
});
|
|
189
|
+
if (compact.siteProfile) {
|
|
190
|
+
const profile = compact.siteProfile;
|
|
191
|
+
compact.siteProfile = {
|
|
192
|
+
selectorPatterns: (profile.selectorPatterns ?? []).map((p) => `${p.pattern} (x${p.frequency})`),
|
|
193
|
+
cookieBanner: profile.cookieBanner,
|
|
194
|
+
visitCount: profile.visitCount
|
|
195
|
+
};
|
|
196
|
+
}
|
|
155
197
|
return compact;
|
|
156
198
|
}) };
|
|
157
199
|
}
|
|
@@ -159,6 +201,13 @@ function compactMemoryResults(results) {
|
|
|
159
201
|
//#region src/mcp/index.ts
|
|
160
202
|
let core;
|
|
161
203
|
let activeSessionId;
|
|
204
|
+
const DEFAULT_MCP_MAX_CHARS = {
|
|
205
|
+
summary: void 0,
|
|
206
|
+
title: void 0,
|
|
207
|
+
text: 8e3,
|
|
208
|
+
a11y: 1e4,
|
|
209
|
+
html: 4e3
|
|
210
|
+
};
|
|
162
211
|
function getCore() {
|
|
163
212
|
if (!core) core = createAgenticBrowserCore();
|
|
164
213
|
return core;
|
|
@@ -265,26 +314,29 @@ server.tool("browser_interact", "Interact with a page element or perform browser
|
|
|
265
314
|
text: JSON.stringify(compact)
|
|
266
315
|
}] };
|
|
267
316
|
});
|
|
268
|
-
server.tool("browser_get_content", "Get the current page content. Modes: \"text\" (readable text), \"a11y\" (accessibility tree
|
|
317
|
+
server.tool("browser_get_content", "Get the current page content. Modes: \"summary\" (recommended low-token overview with headings, actions, inputs, alerts, and iframe awareness), \"text\" (readable text), \"a11y\" (accessibility tree for deeper structure), \"title\" (page title only), \"html\" (raw HTML). A session is auto-started if needed.", {
|
|
269
318
|
mode: z.enum([
|
|
270
319
|
"title",
|
|
271
320
|
"text",
|
|
272
321
|
"html",
|
|
273
|
-
"a11y"
|
|
274
|
-
|
|
322
|
+
"a11y",
|
|
323
|
+
"summary"
|
|
324
|
+
]).default("summary").describe("Content extraction mode"),
|
|
275
325
|
selector: z.string().optional().describe("CSS selector to scope content (e.g. \"main\", \"#content\")"),
|
|
276
|
-
maxChars: z.number().optional().describe("Maximum characters to return (default:
|
|
326
|
+
maxChars: z.number().optional().describe("Maximum characters to return (default: 8000 for text, 10000 for a11y, 4000 for html, ignored for summary/title). Use a CSS selector to scope content instead of raising this limit."),
|
|
277
327
|
sessionId: z.string().optional().describe("Session ID (auto-resolved if omitted)")
|
|
278
328
|
}, async ({ mode, selector, maxChars, sessionId }) => {
|
|
279
329
|
const sid = await resolveSession(sessionId);
|
|
330
|
+
const effectiveMaxChars = maxChars ?? DEFAULT_MCP_MAX_CHARS[mode];
|
|
280
331
|
const result = await getCore().getPageContent({
|
|
281
332
|
sessionId: sid,
|
|
282
333
|
mode,
|
|
283
|
-
selector
|
|
334
|
+
selector,
|
|
335
|
+
maxChars: effectiveMaxChars
|
|
284
336
|
});
|
|
285
337
|
return { content: [{
|
|
286
338
|
type: "text",
|
|
287
|
-
text: JSON.stringify(compactPageContent(result
|
|
339
|
+
text: JSON.stringify(compactPageContent(result))
|
|
288
340
|
}] };
|
|
289
341
|
});
|
|
290
342
|
server.tool("browser_get_elements", "Discover all interactive elements on the current page (buttons, links, inputs, etc.). Returns CSS selectors and fallbackSelectors you can use with browser_interact. Pass fallbackSelectors to browser_interact for automatic retry when the primary selector breaks. Actions are derived from role: link/button/custom→click, input/textarea/contenteditable→click+type+press, select→click+select, checkbox/radio→toggle. A session is auto-started if needed.", {
|