agentic-browser 2.3.0 → 2.4.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 +4 -1
- package/dist/cli/index.d.mts +2 -0
- package/dist/cli/index.mjs +1 -1
- package/dist/index.d.mts +928 -0
- package/dist/index.mjs +1 -1
- package/dist/mcp/index.d.mts +5 -0
- package/dist/mcp/index.mjs +59 -3
- package/dist/{runtime-BCGndjhR.mjs → runtime-PnWvjdzU.mjs} +206 -5
- package/package.json +30 -4
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-PnWvjdzU.mjs";
|
|
3
3
|
export { AgenticBrowserCore, createAgenticBrowserCore, createMockAgenticBrowserCore };
|
package/dist/mcp/index.mjs
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { n as createAgenticBrowserCore } from "../runtime-
|
|
2
|
+
import { n as createAgenticBrowserCore } from "../runtime-PnWvjdzU.mjs";
|
|
3
|
+
import { readFileSync } from "node:fs";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
3
6
|
import { z } from "zod";
|
|
4
7
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
5
8
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
@@ -199,6 +202,29 @@ function compactMemoryResults(results) {
|
|
|
199
202
|
}
|
|
200
203
|
//#endregion
|
|
201
204
|
//#region src/mcp/index.ts
|
|
205
|
+
function readPackageVersion() {
|
|
206
|
+
try {
|
|
207
|
+
const dir = dirname(fileURLToPath(import.meta.url));
|
|
208
|
+
for (const rel of ["../../package.json", "../package.json"]) try {
|
|
209
|
+
const pkg = JSON.parse(readFileSync(join(dir, rel), "utf8"));
|
|
210
|
+
if (pkg.version) return pkg.version;
|
|
211
|
+
} catch {}
|
|
212
|
+
} catch {}
|
|
213
|
+
return "0.0.0";
|
|
214
|
+
}
|
|
215
|
+
function classifyError(message) {
|
|
216
|
+
const lower = message.toLowerCase();
|
|
217
|
+
if (lower.includes("not found") || lower.includes("no element")) return "SELECTOR_NOT_FOUND";
|
|
218
|
+
if (lower.includes("covered") || lower.includes("overlay")) return "ELEMENT_COVERED";
|
|
219
|
+
if (lower.includes("not editable") || lower.includes("readonly")) return "ELEMENT_NOT_EDITABLE";
|
|
220
|
+
if (lower.includes("navigation failed")) return "NAVIGATION_FAILED";
|
|
221
|
+
if (lower.includes("navigation") && lower.includes("timeout")) return "NAVIGATION_TIMEOUT";
|
|
222
|
+
if (lower.includes("cdp connection") || lower.includes("websocket")) return "CDP_DISCONNECTED";
|
|
223
|
+
if (lower.includes("session") && (lower.includes("dead") || lower.includes("terminated"))) return "SESSION_DEAD";
|
|
224
|
+
if (lower.includes("dialog")) return "DIALOG_BLOCKING";
|
|
225
|
+
if (lower.includes("timeout")) return "TIMEOUT";
|
|
226
|
+
return "UNKNOWN";
|
|
227
|
+
}
|
|
202
228
|
let core;
|
|
203
229
|
let activeSessionId;
|
|
204
230
|
const DEFAULT_MCP_MAX_CHARS = {
|
|
@@ -227,7 +253,7 @@ async function resolveSession(sessionId) {
|
|
|
227
253
|
}
|
|
228
254
|
const server = new McpServer({
|
|
229
255
|
name: "agentic-browser",
|
|
230
|
-
version:
|
|
256
|
+
version: readPackageVersion()
|
|
231
257
|
});
|
|
232
258
|
server.tool("browser_start_session", "Start a new Chrome browser session (or return the existing one if healthy). Sessions auto-start when you call any other browser tool, so you rarely need to call this explicitly. Use this to force a fresh session after stopping the previous one.", {}, async () => {
|
|
233
259
|
const session = await getCore().startSession();
|
|
@@ -254,11 +280,17 @@ server.tool("browser_navigate", "Navigate the browser to a URL. A session is aut
|
|
|
254
280
|
const dismissed = await getCore().dismissCookieBanner(sid);
|
|
255
281
|
if (dismissed.dismissed) cookieBanner = dismissed;
|
|
256
282
|
} catch {}
|
|
283
|
+
let currentUrl;
|
|
284
|
+
try {
|
|
285
|
+
currentUrl = await getCore().getCurrentUrl(sid);
|
|
286
|
+
} catch {}
|
|
257
287
|
const compact = {
|
|
258
288
|
resultStatus: result.resultStatus,
|
|
259
289
|
resultMessage: result.resultMessage,
|
|
290
|
+
currentUrl,
|
|
260
291
|
cookieBanner
|
|
261
292
|
};
|
|
293
|
+
if (result.resultStatus === "failed") compact.errorCode = classifyError(result.resultMessage ?? "");
|
|
262
294
|
return { content: [{
|
|
263
295
|
type: "text",
|
|
264
296
|
text: JSON.stringify(compact)
|
|
@@ -305,10 +337,16 @@ server.tool("browser_interact", "Interact with a page element or perform browser
|
|
|
305
337
|
type: "interact",
|
|
306
338
|
payload
|
|
307
339
|
});
|
|
340
|
+
let currentUrl;
|
|
341
|
+
try {
|
|
342
|
+
currentUrl = await getCore().getCurrentUrl(sid);
|
|
343
|
+
} catch {}
|
|
308
344
|
const compact = {
|
|
309
345
|
resultStatus: result.resultStatus,
|
|
310
|
-
resultMessage: result.resultMessage
|
|
346
|
+
resultMessage: result.resultMessage,
|
|
347
|
+
currentUrl
|
|
311
348
|
};
|
|
349
|
+
if (result.resultStatus === "failed") compact.errorCode = classifyError(result.resultMessage ?? "");
|
|
312
350
|
return { content: [{
|
|
313
351
|
type: "text",
|
|
314
352
|
text: JSON.stringify(compact)
|
|
@@ -392,6 +430,24 @@ server.tool("browser_dismiss_cookies", "Dismiss cookie consent banners on the cu
|
|
|
392
430
|
text: JSON.stringify(result)
|
|
393
431
|
}] };
|
|
394
432
|
});
|
|
433
|
+
server.tool("browser_screenshot", "Capture a screenshot of the current page. Returns a base64-encoded image. Useful for visual verification, debugging element discovery failures, or when you need to see what the page looks like. A session is auto-started if needed.", {
|
|
434
|
+
format: z.enum(["jpeg", "png"]).default("jpeg").describe("Image format (jpeg is smaller, png is lossless)"),
|
|
435
|
+
quality: z.number().optional().describe("JPEG quality 0-100 (default 60, ignored for png)"),
|
|
436
|
+
fullPage: z.boolean().default(false).describe("Capture the full scrollable page instead of just the viewport"),
|
|
437
|
+
sessionId: z.string().optional().describe("Session ID (auto-resolved if omitted)")
|
|
438
|
+
}, async ({ format, quality, fullPage, sessionId }) => {
|
|
439
|
+
const sid = await resolveSession(sessionId);
|
|
440
|
+
const result = await getCore().screenshot(sid, {
|
|
441
|
+
format,
|
|
442
|
+
quality,
|
|
443
|
+
fullPage
|
|
444
|
+
});
|
|
445
|
+
return { content: [{
|
|
446
|
+
type: "image",
|
|
447
|
+
data: result.data,
|
|
448
|
+
mimeType: result.mimeType
|
|
449
|
+
}] };
|
|
450
|
+
});
|
|
395
451
|
server.tool("browser_stop_session", "Stop the browser session and terminate Chrome. The next browser tool call will auto-start a fresh session.", { sessionId: z.string().optional().describe("Session ID (uses active session if omitted)") }, async ({ sessionId }) => {
|
|
396
452
|
const sid = sessionId ?? activeSessionId;
|
|
397
453
|
if (!sid) return { content: [{
|
|
@@ -224,19 +224,78 @@ async function createTarget(cdpUrl, url = "about:blank") {
|
|
|
224
224
|
} catch {}
|
|
225
225
|
return await ensurePageWebSocketUrl(cdpUrl);
|
|
226
226
|
}
|
|
227
|
-
/**
|
|
227
|
+
/**
|
|
228
|
+
* Apply stealth patches that remove common automation fingerprints.
|
|
229
|
+
* These run before any page loads so sites cannot detect the bot.
|
|
230
|
+
*/
|
|
231
|
+
const STEALTH_SCRIPT = `
|
|
232
|
+
// Remove navigator.webdriver flag
|
|
233
|
+
Object.defineProperty(navigator, 'webdriver', { get: () => undefined });
|
|
234
|
+
|
|
235
|
+
// Provide realistic plugins array (empty = headless fingerprint)
|
|
236
|
+
Object.defineProperty(navigator, 'plugins', {
|
|
237
|
+
get: () => {
|
|
238
|
+
const plugins = [
|
|
239
|
+
{ name: 'Chrome PDF Plugin', filename: 'internal-pdf-viewer', description: 'Portable Document Format' },
|
|
240
|
+
{ name: 'Chrome PDF Viewer', filename: 'mhjfbmdgcfjbbpaeojofohoefgiehjai', description: '' },
|
|
241
|
+
{ name: 'Native Client', filename: 'internal-nacl-plugin', description: '' },
|
|
242
|
+
];
|
|
243
|
+
plugins.length = 3;
|
|
244
|
+
Object.setPrototypeOf(plugins, PluginArray.prototype);
|
|
245
|
+
return plugins;
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
// Provide realistic languages
|
|
250
|
+
Object.defineProperty(navigator, 'languages', { get: () => ['en-US', 'en'] });
|
|
251
|
+
|
|
252
|
+
// Patch chrome.runtime to look like a real Chrome
|
|
253
|
+
if (!window.chrome) window.chrome = {};
|
|
254
|
+
if (!window.chrome.runtime) window.chrome.runtime = { id: undefined };
|
|
255
|
+
|
|
256
|
+
// Remove the CDP-injected sourceURL comment from Runtime.evaluate calls
|
|
257
|
+
const origToString = Function.prototype.toString;
|
|
258
|
+
Function.prototype.toString = function() {
|
|
259
|
+
if (this === Function.prototype.toString) return 'function toString() { [native code] }';
|
|
260
|
+
return origToString.call(this);
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
// Patch permissions query to report "prompt" instead of "denied" for notifications
|
|
264
|
+
const origQuery = window.Permissions?.prototype?.query;
|
|
265
|
+
if (origQuery) {
|
|
266
|
+
window.Permissions.prototype.query = function(params) {
|
|
267
|
+
if (params?.name === 'notifications') {
|
|
268
|
+
return Promise.resolve({ state: 'prompt', onchange: null });
|
|
269
|
+
}
|
|
270
|
+
return origQuery.call(this, params);
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
`;
|
|
274
|
+
/** Verify the page is ready, apply stealth, and optionally set a custom user-agent. */
|
|
228
275
|
async function initTarget(targetWsUrl, userAgent) {
|
|
229
276
|
const conn = await CdpConnection.connect(targetWsUrl);
|
|
230
277
|
try {
|
|
231
278
|
const enables = [conn.send("Page.enable"), conn.send("Runtime.enable")];
|
|
232
|
-
|
|
279
|
+
enables.push(conn.send("Network.enable"));
|
|
233
280
|
await Promise.all(enables);
|
|
281
|
+
await conn.send("Page.addScriptToEvaluateOnNewDocument", { source: STEALTH_SCRIPT });
|
|
282
|
+
await conn.send("Runtime.evaluate", {
|
|
283
|
+
expression: STEALTH_SCRIPT,
|
|
284
|
+
returnByValue: true
|
|
285
|
+
});
|
|
234
286
|
await conn.send("Runtime.evaluate", {
|
|
235
287
|
expression: "window.location.href",
|
|
236
288
|
returnByValue: true,
|
|
237
289
|
awaitPromise: true
|
|
238
290
|
});
|
|
239
291
|
if (userAgent) await conn.send("Network.setUserAgentOverride", { userAgent });
|
|
292
|
+
else try {
|
|
293
|
+
const { userAgent: currentUA } = await conn.send("Browser.getVersion");
|
|
294
|
+
if (currentUA?.includes("HeadlessChrome")) {
|
|
295
|
+
const cleanUA = currentUA.replace(/HeadlessChrome/g, "Chrome");
|
|
296
|
+
await conn.send("Network.setUserAgentOverride", { userAgent: cleanUA });
|
|
297
|
+
}
|
|
298
|
+
} catch {}
|
|
240
299
|
} finally {
|
|
241
300
|
conn.close();
|
|
242
301
|
}
|
|
@@ -732,7 +791,10 @@ var ChromeCdpBrowserController = class {
|
|
|
732
791
|
`--remote-debugging-port=${port}`,
|
|
733
792
|
`--user-data-dir=${profileDir}`,
|
|
734
793
|
"--no-first-run",
|
|
735
|
-
"--no-default-browser-check"
|
|
794
|
+
"--no-default-browser-check",
|
|
795
|
+
"--disable-blink-features=AutomationControlled",
|
|
796
|
+
"--disable-infobars",
|
|
797
|
+
"--excludeSwitches=enable-automation"
|
|
736
798
|
];
|
|
737
799
|
if (attempt.headless) args.push("--headless=new");
|
|
738
800
|
args.push("about:blank");
|
|
@@ -1076,6 +1138,38 @@ var ChromeCdpBrowserController = class {
|
|
|
1076
1138
|
})).result.value ?? "";
|
|
1077
1139
|
});
|
|
1078
1140
|
}
|
|
1141
|
+
async screenshot(targetWsUrl, options) {
|
|
1142
|
+
return await this.withRetry(targetWsUrl, async (conn) => {
|
|
1143
|
+
await this.ensureEnabled(targetWsUrl);
|
|
1144
|
+
const format = options?.format ?? "jpeg";
|
|
1145
|
+
const params = {
|
|
1146
|
+
format,
|
|
1147
|
+
quality: format === "jpeg" ? options?.quality ?? 60 : void 0
|
|
1148
|
+
};
|
|
1149
|
+
if (options?.fullPage) {
|
|
1150
|
+
const metrics = await conn.send("Page.getLayoutMetrics");
|
|
1151
|
+
params.clip = {
|
|
1152
|
+
x: 0,
|
|
1153
|
+
y: 0,
|
|
1154
|
+
width: metrics.contentSize.width,
|
|
1155
|
+
height: metrics.contentSize.height,
|
|
1156
|
+
scale: 1
|
|
1157
|
+
};
|
|
1158
|
+
}
|
|
1159
|
+
return {
|
|
1160
|
+
data: (await conn.send("Page.captureScreenshot", params)).data,
|
|
1161
|
+
mimeType: format === "png" ? "image/png" : "image/jpeg"
|
|
1162
|
+
};
|
|
1163
|
+
});
|
|
1164
|
+
}
|
|
1165
|
+
async getCurrentUrl(targetWsUrl) {
|
|
1166
|
+
return await this.withRetry(targetWsUrl, async (conn) => {
|
|
1167
|
+
return (await conn.send("Runtime.evaluate", {
|
|
1168
|
+
expression: "window.location.href",
|
|
1169
|
+
returnByValue: true
|
|
1170
|
+
})).result.value ?? "";
|
|
1171
|
+
});
|
|
1172
|
+
}
|
|
1079
1173
|
async getContent(targetWsUrl, options) {
|
|
1080
1174
|
if (options.mode === "summary") return await this.getSummaryContent(targetWsUrl, options);
|
|
1081
1175
|
if (options.mode === "a11y") {
|
|
@@ -1149,7 +1243,8 @@ var ChromeCdpBrowserController = class {
|
|
|
1149
1243
|
fallbackSelectors: element.fallbackSelectors,
|
|
1150
1244
|
inputType: element.inputType,
|
|
1151
1245
|
placeholder: element.placeholder,
|
|
1152
|
-
ariaLabel: element.ariaLabel
|
|
1246
|
+
ariaLabel: element.ariaLabel,
|
|
1247
|
+
currentValue: element.currentValue
|
|
1153
1248
|
});
|
|
1154
1249
|
if (primaryActions.length >= 8 && inputs.length >= 8) break;
|
|
1155
1250
|
}
|
|
@@ -1261,11 +1356,84 @@ var ChromeCdpBrowserController = class {
|
|
|
1261
1356
|
};
|
|
1262
1357
|
});
|
|
1263
1358
|
|
|
1359
|
+
// Extract a readable content excerpt so the LLM understands what the page is about
|
|
1360
|
+
function extractContentExcerpt(root, maxChars) {
|
|
1361
|
+
const skipTags = new Set(['SCRIPT','STYLE','NOSCRIPT','SVG','PATH','META','LINK','BR','HR','IMG']);
|
|
1362
|
+
const blocks = [];
|
|
1363
|
+
let totalChars = 0;
|
|
1364
|
+
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {
|
|
1365
|
+
acceptNode: function(node) {
|
|
1366
|
+
const parent = node.parentElement;
|
|
1367
|
+
if (!parent) return NodeFilter.FILTER_REJECT;
|
|
1368
|
+
if (skipTags.has(parent.tagName)) return NodeFilter.FILTER_REJECT;
|
|
1369
|
+
const view = (parent.ownerDocument && parent.ownerDocument.defaultView) ? parent.ownerDocument.defaultView : window;
|
|
1370
|
+
const style = view.getComputedStyle(parent);
|
|
1371
|
+
if (style.display === 'none' || style.visibility === 'hidden') return NodeFilter.FILTER_REJECT;
|
|
1372
|
+
return NodeFilter.FILTER_ACCEPT;
|
|
1373
|
+
}
|
|
1374
|
+
});
|
|
1375
|
+
let node;
|
|
1376
|
+
while ((node = walker.nextNode())) {
|
|
1377
|
+
const text = node.textContent.replace(/\\s+/g, ' ').trim();
|
|
1378
|
+
if (!text || text.length < 2) continue;
|
|
1379
|
+
if (totalChars + text.length > maxChars) {
|
|
1380
|
+
const remaining = maxChars - totalChars;
|
|
1381
|
+
if (remaining > 20) blocks.push(text.slice(0, remaining));
|
|
1382
|
+
break;
|
|
1383
|
+
}
|
|
1384
|
+
blocks.push(text);
|
|
1385
|
+
totalChars += text.length;
|
|
1386
|
+
}
|
|
1387
|
+
return blocks.join(' ').replace(/\\s+/g, ' ').trim();
|
|
1388
|
+
}
|
|
1389
|
+
|
|
1390
|
+
// Group inputs by their parent form for contextual understanding
|
|
1391
|
+
function discoverForms(root) {
|
|
1392
|
+
const forms = [];
|
|
1393
|
+
for (const form of Array.from(root.querySelectorAll('form')).slice(0, 6)) {
|
|
1394
|
+
const formInputs = Array.from(form.querySelectorAll('input:not([type="hidden"]), select, textarea'));
|
|
1395
|
+
if (!formInputs.length) continue;
|
|
1396
|
+
const submitBtn = form.querySelector('button[type="submit"], input[type="submit"], button:not([type])');
|
|
1397
|
+
forms.push({
|
|
1398
|
+
action: form.getAttribute('action') || undefined,
|
|
1399
|
+
method: (form.getAttribute('method') || 'get').toUpperCase(),
|
|
1400
|
+
fields: formInputs.slice(0, 10).map(function(el) {
|
|
1401
|
+
const tag = el.tagName.toLowerCase();
|
|
1402
|
+
return {
|
|
1403
|
+
name: el.getAttribute('name') || undefined,
|
|
1404
|
+
type: tag === 'select' ? 'select' : tag === 'textarea' ? 'textarea' : (el.type || 'text'),
|
|
1405
|
+
label: (function() {
|
|
1406
|
+
const id = el.id;
|
|
1407
|
+
if (id) {
|
|
1408
|
+
const label = root.querySelector('label[for="' + CSS.escape(id) + '"]');
|
|
1409
|
+
if (label) return textOf(label).slice(0, 60);
|
|
1410
|
+
}
|
|
1411
|
+
const closest = el.closest('label');
|
|
1412
|
+
if (closest) return textOf(closest).slice(0, 60);
|
|
1413
|
+
const ariaLabel = el.getAttribute('aria-label');
|
|
1414
|
+
if (ariaLabel) return ariaLabel.slice(0, 60);
|
|
1415
|
+
return el.getAttribute('placeholder') || undefined;
|
|
1416
|
+
})(),
|
|
1417
|
+
required: el.required || el.getAttribute('aria-required') === 'true' || false,
|
|
1418
|
+
currentValue: ('value' in el && typeof el.value === 'string' && el.value) ? el.value.slice(0, 100) : undefined,
|
|
1419
|
+
};
|
|
1420
|
+
}),
|
|
1421
|
+
submitText: submitBtn ? textOf(submitBtn).slice(0, 40) : undefined,
|
|
1422
|
+
});
|
|
1423
|
+
}
|
|
1424
|
+
return forms;
|
|
1425
|
+
}
|
|
1426
|
+
|
|
1427
|
+
const contentExcerpt = extractContentExcerpt(scopeRoot, 1500);
|
|
1428
|
+
const forms = discoverForms(scopeRoot);
|
|
1429
|
+
|
|
1264
1430
|
return {
|
|
1265
1431
|
url: window.location.href,
|
|
1266
1432
|
title: document.title ?? '',
|
|
1433
|
+
contentExcerpt,
|
|
1267
1434
|
headings,
|
|
1268
1435
|
landmarks,
|
|
1436
|
+
forms: forms.length ? forms : undefined,
|
|
1269
1437
|
alerts,
|
|
1270
1438
|
frames,
|
|
1271
1439
|
crossOriginFrameCount: allFrames.filter((frame) => {
|
|
@@ -1697,6 +1865,9 @@ var ChromeCdpBrowserController = class {
|
|
|
1697
1865
|
if (ariaLabel) entry.ariaLabel = ariaLabel;
|
|
1698
1866
|
const placeholder = el.getAttribute('placeholder');
|
|
1699
1867
|
if (placeholder) entry.placeholder = placeholder;
|
|
1868
|
+
if ('value' in el && typeof el.value === 'string' && el.value) {
|
|
1869
|
+
entry.currentValue = el.value.slice(0, 200);
|
|
1870
|
+
}
|
|
1700
1871
|
|
|
1701
1872
|
results.push(entry);
|
|
1702
1873
|
}
|
|
@@ -1978,6 +2149,15 @@ var MockBrowserController = class {
|
|
|
1978
2149
|
if (payload.action === "dialog") return payload.text === "dismiss" ? "dismissed confirm: mock dialog" : "accepted confirm: mock dialog";
|
|
1979
2150
|
return `interacted:${payload.action}`;
|
|
1980
2151
|
}
|
|
2152
|
+
async screenshot(_targetWsUrl, options) {
|
|
2153
|
+
return {
|
|
2154
|
+
data: "bW9jaw==",
|
|
2155
|
+
mimeType: (options?.format ?? "jpeg") === "png" ? "image/png" : "image/jpeg"
|
|
2156
|
+
};
|
|
2157
|
+
}
|
|
2158
|
+
async getCurrentUrl(cdpUrl) {
|
|
2159
|
+
return this.pages.get(cdpUrl)?.url ?? "about:blank";
|
|
2160
|
+
}
|
|
1981
2161
|
async getContent(cdpUrl, options) {
|
|
1982
2162
|
const page = this.pages.get(cdpUrl);
|
|
1983
2163
|
if (!page) throw new Error("mock page missing");
|
|
@@ -2253,6 +2433,14 @@ var SessionManager = class {
|
|
|
2253
2433
|
const record = await this.ensureSession(sessionId);
|
|
2254
2434
|
return await this.browser.getInteractiveElements(record.targetWsUrl, options);
|
|
2255
2435
|
}
|
|
2436
|
+
async screenshot(sessionId, options) {
|
|
2437
|
+
const record = await this.ensureSession(sessionId);
|
|
2438
|
+
return await this.browser.screenshot(record.targetWsUrl, options);
|
|
2439
|
+
}
|
|
2440
|
+
async getCurrentUrl(sessionId) {
|
|
2441
|
+
const record = await this.ensureSession(sessionId);
|
|
2442
|
+
return await this.browser.getCurrentUrl(record.targetWsUrl);
|
|
2443
|
+
}
|
|
2256
2444
|
async dismissCookieBanner(sessionId) {
|
|
2257
2445
|
const record = await this.ensureSession(sessionId);
|
|
2258
2446
|
const result = await this.browser.dismissCookieBanner(record.targetWsUrl);
|
|
@@ -2528,6 +2716,12 @@ var ControlApi = class {
|
|
|
2528
2716
|
async dismissCookieBanner(sessionId) {
|
|
2529
2717
|
return await this.sessions.dismissCookieBanner(sessionId);
|
|
2530
2718
|
}
|
|
2719
|
+
async screenshot(sessionId, options) {
|
|
2720
|
+
return await this.sessions.screenshot(sessionId, options);
|
|
2721
|
+
}
|
|
2722
|
+
async getCurrentUrl(sessionId) {
|
|
2723
|
+
return await this.sessions.getCurrentUrl(sessionId);
|
|
2724
|
+
}
|
|
2531
2725
|
listEvents(sessionId, limit = 100) {
|
|
2532
2726
|
return { events: this.eventStore.list(sessionId, limit) };
|
|
2533
2727
|
}
|
|
@@ -3566,8 +3760,9 @@ var AgenticBrowserCore = class {
|
|
|
3566
3760
|
return this.api.getSession(sessionId);
|
|
3567
3761
|
}
|
|
3568
3762
|
async runCommand(input) {
|
|
3763
|
+
const commandId = input.commandId ?? `${input.type}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
3569
3764
|
return await this.api.executeCommand(input.sessionId, {
|
|
3570
|
-
commandId
|
|
3765
|
+
commandId,
|
|
3571
3766
|
type: input.type,
|
|
3572
3767
|
payload: input.payload
|
|
3573
3768
|
});
|
|
@@ -3590,6 +3785,12 @@ var AgenticBrowserCore = class {
|
|
|
3590
3785
|
async dismissCookieBanner(sessionId) {
|
|
3591
3786
|
return await this.api.dismissCookieBanner(sessionId);
|
|
3592
3787
|
}
|
|
3788
|
+
async screenshot(sessionId, options) {
|
|
3789
|
+
return await this.api.screenshot(sessionId, options);
|
|
3790
|
+
}
|
|
3791
|
+
async getCurrentUrl(sessionId) {
|
|
3792
|
+
return await this.api.getCurrentUrl(sessionId);
|
|
3793
|
+
}
|
|
3593
3794
|
async restartSession(sessionId) {
|
|
3594
3795
|
return await this.api.restartSession(sessionId);
|
|
3595
3796
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentic-browser",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
|
+
"description": "CLI and MCP server for AI agents to control Chrome via CDP",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"agent",
|
|
7
|
+
"ai",
|
|
8
|
+
"automation",
|
|
9
|
+
"browser",
|
|
10
|
+
"cdp",
|
|
11
|
+
"chrome",
|
|
12
|
+
"devtools-protocol",
|
|
13
|
+
"llm",
|
|
14
|
+
"mcp"
|
|
15
|
+
],
|
|
16
|
+
"homepage": "https://ph1p.github.io/agentic-browser",
|
|
4
17
|
"license": "MIT",
|
|
5
18
|
"repository": {
|
|
6
19
|
"type": "git",
|
|
@@ -17,10 +30,20 @@
|
|
|
17
30
|
],
|
|
18
31
|
"type": "module",
|
|
19
32
|
"main": "dist/index.mjs",
|
|
33
|
+
"types": "dist/index.d.mts",
|
|
20
34
|
"exports": {
|
|
21
|
-
".":
|
|
22
|
-
|
|
23
|
-
|
|
35
|
+
".": {
|
|
36
|
+
"types": "./dist/index.d.mts",
|
|
37
|
+
"default": "./dist/index.mjs"
|
|
38
|
+
},
|
|
39
|
+
"./cli": {
|
|
40
|
+
"types": "./dist/cli/index.d.mts",
|
|
41
|
+
"default": "./dist/cli/index.mjs"
|
|
42
|
+
},
|
|
43
|
+
"./mcp": {
|
|
44
|
+
"types": "./dist/mcp/index.d.mts",
|
|
45
|
+
"default": "./dist/mcp/index.mjs"
|
|
46
|
+
}
|
|
24
47
|
},
|
|
25
48
|
"publishConfig": {
|
|
26
49
|
"access": "public",
|
|
@@ -65,5 +88,8 @@
|
|
|
65
88
|
"vitest": "^4.0.18",
|
|
66
89
|
"vocs": "1.4.1"
|
|
67
90
|
},
|
|
91
|
+
"engines": {
|
|
92
|
+
"node": ">=20"
|
|
93
|
+
},
|
|
68
94
|
"packageManager": "pnpm@10.32.0"
|
|
69
95
|
}
|