agentic-browser 2.0.1 → 2.2.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 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 text
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
@@ -132,7 +132,7 @@ agentic-browser agent elements --roles button,link,input --visible-only --limit
132
132
  agentic-browser agent elements --selector "#main-content"
133
133
  ```
134
134
 
135
- Returns a JSON array of elements with CSS selectors and fallback selectors usable in the typed agent commands like `agent click`, `agent type`, and `agent select`:
135
+ Returns a JSON array of elements with selectors and fallback selectors usable in the typed agent commands like `agent click`, `agent type`, and `agent select`:
136
136
 
137
137
  ```json
138
138
  {
@@ -154,6 +154,10 @@ Returns a JSON array of elements with CSS selectors and fallback selectors usabl
154
154
 
155
155
  MCP responses are compact — `visible`, `actions`, and `tagName` are omitted to reduce token usage, and `enabled` is omitted when it is `true`. Responses also include a `summary` block with `countsByRole` and `primaryActions` so an LLM can identify the main controls faster. The full element shape is available via the programmatic API.
156
156
 
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
+
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
+
157
161
  ````
158
162
 
159
163
  ## MCP Server
@@ -223,8 +227,8 @@ More `interact` actions:
223
227
  ### 4. Read Page Content
224
228
 
225
229
  ```bash
230
+ agentic-browser page:content <sessionId> --mode summary
226
231
  agentic-browser page:content <sessionId> --mode title
227
- agentic-browser page:content <sessionId> --mode text
228
232
  agentic-browser page:content <sessionId> --mode html --selector main
229
233
  ```
230
234
 
@@ -1,10 +1,9 @@
1
1
  #!/usr/bin/env node
2
- import { r as createCliRuntime } from "../runtime-DUSoQl5x.mjs";
2
+ import { r as createCliRuntime } from "../runtime-CRkUsvhV.mjs";
3
3
  import fs from "node:fs";
4
4
  import path from "node:path";
5
5
  import crypto from "node:crypto";
6
6
  import { Command } from "commander";
7
-
8
7
  //#region src/cli/commands/agent.ts
9
8
  const STATE_FILE_NAME = "agent-state.json";
10
9
  function stateFilePath(runtime) {
@@ -152,7 +151,8 @@ async function agentContent(runtime, input) {
152
151
  action: "content",
153
152
  ...await runtime.api.getContent(sessionId, {
154
153
  mode: input.mode,
155
- selector: input.selector
154
+ selector: input.selector,
155
+ maxChars: input.maxChars
156
156
  })
157
157
  };
158
158
  }
@@ -184,7 +184,6 @@ async function agentCleanup(runtime, input) {
184
184
  ...runtime.api.cleanupSessions(input)
185
185
  };
186
186
  }
187
-
188
187
  //#endregion
189
188
  //#region src/cli/output/result-formatter.ts
190
189
  function formatResult(resultStatus, message) {
@@ -193,7 +192,6 @@ function formatResult(resultStatus, message) {
193
192
  message
194
193
  };
195
194
  }
196
-
197
195
  //#endregion
198
196
  //#region src/cli/commands/session-start.ts
199
197
  async function runSessionStart(runtime, input) {
@@ -203,32 +201,27 @@ async function runSessionStart(runtime, input) {
203
201
  sessionId: session.sessionId
204
202
  };
205
203
  }
206
-
207
204
  //#endregion
208
205
  //#region src/cli/commands/session-status.ts
209
206
  async function runSessionStatus(runtime, input) {
210
207
  return runtime.api.getSession(input.sessionId);
211
208
  }
212
-
213
209
  //#endregion
214
210
  //#region src/cli/commands/session-stop.ts
215
211
  async function runSessionStop(runtime, input) {
216
212
  await runtime.api.terminateSession(input.sessionId);
217
213
  return { terminated: true };
218
214
  }
219
-
220
215
  //#endregion
221
216
  //#region src/cli/commands/session-cleanup.ts
222
217
  async function runSessionCleanup(runtime, input) {
223
218
  return runtime.api.cleanupSessions(input);
224
219
  }
225
-
226
220
  //#endregion
227
221
  //#region src/cli/commands/session-restart.ts
228
222
  async function runSessionRestart(runtime, input) {
229
223
  return await runtime.api.restartSession(input.sessionId);
230
224
  }
231
-
232
225
  //#endregion
233
226
  //#region src/cli/commands/session-auth.ts
234
227
  async function runSessionAuth(runtime, input) {
@@ -238,7 +231,6 @@ async function runSessionAuth(runtime, input) {
238
231
  valid: runtime.context.tokenService.validate(input.sessionId, token)
239
232
  };
240
233
  }
241
-
242
234
  //#endregion
243
235
  //#region src/cli/commands/command-run.ts
244
236
  async function runCommand(runtime, input) {
@@ -253,43 +245,38 @@ async function runCommand(runtime, input) {
253
245
  throw new Error(`Command rejected: ${error.message}`);
254
246
  }
255
247
  }
256
-
257
248
  //#endregion
258
249
  //#region src/cli/commands/page-content.ts
259
250
  async function runPageContent(runtime, input) {
260
251
  return await runtime.api.getContent(input.sessionId, {
261
252
  mode: input.mode,
262
- selector: input.selector
253
+ selector: input.selector,
254
+ maxChars: input.maxChars
263
255
  });
264
256
  }
265
-
266
257
  //#endregion
267
258
  //#region src/cli/commands/memory-search.ts
268
259
  async function runMemorySearch(runtime, input) {
269
260
  if (!input.taskIntent || !input.taskIntent.trim()) throw new Error("taskIntent is required");
270
261
  return runtime.api.searchMemory(input);
271
262
  }
272
-
273
263
  //#endregion
274
264
  //#region src/cli/commands/memory-inspect.ts
275
265
  async function runMemoryInspect(runtime, input) {
276
266
  if (!input.insightId || !input.insightId.trim()) throw new Error("insightId is required");
277
267
  return runtime.api.inspectMemory(input.insightId);
278
268
  }
279
-
280
269
  //#endregion
281
270
  //#region src/cli/commands/memory-verify.ts
282
271
  async function runMemoryVerify(runtime, input) {
283
272
  if (!input.insightId || !input.insightId.trim()) throw new Error("insightId is required");
284
273
  return runtime.api.verifyMemory(input.insightId);
285
274
  }
286
-
287
275
  //#endregion
288
276
  //#region src/cli/commands/memory-stats.ts
289
277
  async function runMemoryStats(runtime) {
290
278
  return runtime.api.memoryStats();
291
279
  }
292
-
293
280
  //#endregion
294
281
  //#region src/cli/index.ts
295
282
  async function main() {
@@ -337,11 +324,12 @@ async function main() {
337
324
  });
338
325
  console.log(JSON.stringify(result));
339
326
  });
340
- program.command("page:content").argument("<sessionId>").option("--mode <mode>", "title|text|html|a11y", "text").option("--selector <selector>", "optional CSS selector").action(async (sessionId, options) => {
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) => {
341
328
  const result = await runPageContent(runtime, {
342
329
  sessionId,
343
330
  mode: options.mode,
344
- selector: options.selector
331
+ selector: options.selector,
332
+ maxChars: options.maxChars ? Number.parseInt(options.maxChars, 10) : void 0
345
333
  });
346
334
  console.log(JSON.stringify(result));
347
335
  });
@@ -485,8 +473,12 @@ async function main() {
485
473
  const result = await agentTerminate(runtime);
486
474
  console.log(JSON.stringify(result));
487
475
  });
488
- agent.command("content").option("--mode <mode>", "title|text|html|a11y", "text").option("--selector <selector>", "optional CSS selector").action(async (options) => {
489
- const result = await agentContent(runtime, options);
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
+ });
490
482
  console.log(JSON.stringify(result));
491
483
  });
492
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) => {
@@ -520,7 +512,7 @@ async function main() {
520
512
  await startMcpServer();
521
513
  });
522
514
  program.command("setup").description("Configure agentic-browser as MCP server for your AI tool").action(async () => {
523
- const { runSetup } = await import("../setup-COK-KCfv.mjs");
515
+ const { runSetup } = await import("../setup-BP0YyerC.mjs");
524
516
  await runSetup();
525
517
  });
526
518
  await program.parseAsync(process.argv);
@@ -533,6 +525,5 @@ main().then((keepAlive) => {
533
525
  console.error(JSON.stringify({ error: message }));
534
526
  process.exit(1);
535
527
  });
536
-
537
528
  //#endregion
538
- export { };
529
+ export {};
package/dist/index.mjs CHANGED
@@ -1,4 +1,3 @@
1
1
  #!/usr/bin/env node
2
- import { i as createMockAgenticBrowserCore, n as createAgenticBrowserCore, t as AgenticBrowserCore } from "./runtime-DUSoQl5x.mjs";
3
-
4
- export { AgenticBrowserCore, createAgenticBrowserCore, createMockAgenticBrowserCore };
2
+ import { i as createMockAgenticBrowserCore, n as createAgenticBrowserCore, t as AgenticBrowserCore } from "./runtime-CRkUsvhV.mjs";
3
+ export { AgenticBrowserCore, createAgenticBrowserCore, createMockAgenticBrowserCore };
@@ -1,9 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { n as createAgenticBrowserCore } from "../runtime-DUSoQl5x.mjs";
2
+ import { n as createAgenticBrowserCore } from "../runtime-CRkUsvhV.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";
6
-
7
6
  //#region src/mcp/response-helpers.ts
8
7
  function uniqueLines(content, maxLineLength = 160) {
9
8
  const seen = /* @__PURE__ */ new Set();
@@ -23,10 +22,27 @@ function truncateContent(content, limit) {
23
22
  };
24
23
  const originalLength = content.length;
25
24
  return {
26
- content: content.slice(0, limit) + `\n\n[Truncated — showing first ${limit} of ${originalLength} characters. Use a CSS selector to scope the content.]`,
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.]`,
27
26
  truncated: true
28
27
  };
29
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
+ }
30
46
  function summarizeTextContent(content) {
31
47
  const lines = uniqueLines(content);
32
48
  return {
@@ -69,9 +85,23 @@ function compactPageContent(result, maxChars) {
69
85
  text: 8e3,
70
86
  a11y: 1e4,
71
87
  html: 4e3,
72
- title: void 0
88
+ title: void 0,
89
+ summary: void 0
73
90
  }[result.mode];
74
- const truncated = truncateContent(result.content, limit);
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);
75
105
  if (result.mode === "title") return {
76
106
  ...result,
77
107
  truncated: false
@@ -82,6 +112,7 @@ function compactPageContent(result, maxChars) {
82
112
  mode: result.mode,
83
113
  content: truncated.content,
84
114
  truncated: truncated.truncated,
115
+ originalLength: result.originalLength,
85
116
  summaryLines: summary.summaryLines,
86
117
  previewLines: summary.previewLines
87
118
  };
@@ -92,6 +123,7 @@ function compactPageContent(result, maxChars) {
92
123
  mode: result.mode,
93
124
  content: truncated.content,
94
125
  truncated: truncated.truncated,
126
+ originalLength: result.originalLength,
95
127
  headings: summary.headings,
96
128
  landmarks: summary.landmarks,
97
129
  actions: summary.actions,
@@ -102,7 +134,8 @@ function compactPageContent(result, maxChars) {
102
134
  return {
103
135
  mode: result.mode,
104
136
  content: truncated.content,
105
- truncated: truncated.truncated
137
+ truncated: truncated.truncated,
138
+ originalLength: result.originalLength
106
139
  };
107
140
  }
108
141
  function summarizeElements(elements) {
@@ -156,11 +189,17 @@ function compactMemoryResults(results) {
156
189
  return compact;
157
190
  }) };
158
191
  }
159
-
160
192
  //#endregion
161
193
  //#region src/mcp/index.ts
162
194
  let core;
163
195
  let activeSessionId;
196
+ const DEFAULT_MCP_MAX_CHARS = {
197
+ summary: void 0,
198
+ title: void 0,
199
+ text: 8e3,
200
+ a11y: 1e4,
201
+ html: 4e3
202
+ };
164
203
  function getCore() {
165
204
  if (!core) core = createAgenticBrowserCore();
166
205
  return core;
@@ -267,26 +306,29 @@ server.tool("browser_interact", "Interact with a page element or perform browser
267
306
  text: JSON.stringify(compact)
268
307
  }] };
269
308
  });
270
- server.tool("browser_get_content", "Get the current page content. Modes: \"text\" (readable text), \"a11y\" (accessibility tree — best for understanding page structure), \"title\" (page title only), \"html\" (raw HTML). Use \"a11y\" to see the full page hierarchy with roles, names, and states. A session is auto-started if needed.", {
309
+ 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.", {
271
310
  mode: z.enum([
272
311
  "title",
273
312
  "text",
274
313
  "html",
275
- "a11y"
276
- ]).default("text").describe("Content extraction mode"),
314
+ "a11y",
315
+ "summary"
316
+ ]).default("summary").describe("Content extraction mode"),
277
317
  selector: z.string().optional().describe("CSS selector to scope content (e.g. \"main\", \"#content\")"),
278
- maxChars: z.number().optional().describe("Maximum characters to return (default: 12000 for text/a11y, 6000 for html, no cap for title). Use a CSS selector to scope content instead of raising this limit."),
318
+ 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."),
279
319
  sessionId: z.string().optional().describe("Session ID (auto-resolved if omitted)")
280
320
  }, async ({ mode, selector, maxChars, sessionId }) => {
281
321
  const sid = await resolveSession(sessionId);
322
+ const effectiveMaxChars = maxChars ?? DEFAULT_MCP_MAX_CHARS[mode];
282
323
  const result = await getCore().getPageContent({
283
324
  sessionId: sid,
284
325
  mode,
285
- selector
326
+ selector,
327
+ maxChars: effectiveMaxChars
286
328
  });
287
329
  return { content: [{
288
330
  type: "text",
289
- text: JSON.stringify(compactPageContent(result, maxChars))
331
+ text: JSON.stringify(compactPageContent(result))
290
332
  }] };
291
333
  });
292
334
  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.", {
@@ -379,6 +421,5 @@ async function main() {
379
421
  };
380
422
  await server.connect(transport);
381
423
  }
382
-
383
424
  //#endregion
384
- export { main };
425
+ export { main };