agentic-browser 2.2.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 +5 -2
- package/dist/cli/index.d.mts +2 -0
- package/dist/cli/index.mjs +2 -2
- 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 +67 -3
- package/dist/{runtime-CRkUsvhV.mjs → runtime-PnWvjdzU.mjs} +502 -19
- package/package.json +34 -8
|
@@ -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");
|
|
@@ -2114,7 +2294,7 @@ var SessionManager = class {
|
|
|
2114
2294
|
constructor(ctx, browser) {
|
|
2115
2295
|
this.ctx = ctx;
|
|
2116
2296
|
this.browser = browser;
|
|
2117
|
-
this.store = new SessionStore(this.ctx.config.
|
|
2297
|
+
this.store = new SessionStore(this.ctx.config.dataDir);
|
|
2118
2298
|
}
|
|
2119
2299
|
async createSession(input) {
|
|
2120
2300
|
if (input.browser !== "chrome") throw new Error("Only chrome is supported");
|
|
@@ -2235,15 +2415,38 @@ var SessionManager = class {
|
|
|
2235
2415
|
}
|
|
2236
2416
|
async getContent(sessionId, options) {
|
|
2237
2417
|
const record = await this.ensureSession(sessionId);
|
|
2238
|
-
|
|
2418
|
+
const result = await this.browser.getContent(record.targetWsUrl, options);
|
|
2419
|
+
if (options.mode === "summary" && result.structuredContent) {
|
|
2420
|
+
const sc = result.structuredContent;
|
|
2421
|
+
const url = typeof sc.url === "string" ? sc.url : record.lastUrl;
|
|
2422
|
+
const parsed = this.parseUrl(url);
|
|
2423
|
+
const headingTexts = (sc.headings ?? []).map((h) => typeof h === "string" ? h : h.text ?? "");
|
|
2424
|
+
const landmarkTexts = (sc.landmarks ?? []).map((l) => typeof l === "string" ? l : l.role ?? "");
|
|
2425
|
+
this.ctx.memoryService.updateProfileFromContent(parsed.domain, parsed.pathPattern, {
|
|
2426
|
+
headings: headingTexts,
|
|
2427
|
+
landmarks: landmarkTexts
|
|
2428
|
+
});
|
|
2429
|
+
}
|
|
2430
|
+
return result;
|
|
2239
2431
|
}
|
|
2240
2432
|
async getInteractiveElements(sessionId, options) {
|
|
2241
2433
|
const record = await this.ensureSession(sessionId);
|
|
2242
2434
|
return await this.browser.getInteractiveElements(record.targetWsUrl, options);
|
|
2243
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
|
+
}
|
|
2244
2444
|
async dismissCookieBanner(sessionId) {
|
|
2245
2445
|
const record = await this.ensureSession(sessionId);
|
|
2246
|
-
|
|
2446
|
+
const result = await this.browser.dismissCookieBanner(record.targetWsUrl);
|
|
2447
|
+
const parsed = this.parseUrl(record.lastUrl);
|
|
2448
|
+
this.ctx.memoryService.updateProfileCookieBanner(parsed.domain, result);
|
|
2449
|
+
return result;
|
|
2247
2450
|
}
|
|
2248
2451
|
setStatus(status, reason) {
|
|
2249
2452
|
const active = this.store.getActive();
|
|
@@ -2361,7 +2564,7 @@ var SessionManager = class {
|
|
|
2361
2564
|
removedSessionIds.push(record.session.sessionId);
|
|
2362
2565
|
}
|
|
2363
2566
|
const keepIds = new Set(keep.map((record) => record.session.sessionId));
|
|
2364
|
-
const profilesDir = path.join(this.ctx.config.
|
|
2567
|
+
const profilesDir = path.join(this.ctx.config.dataDir, "profiles");
|
|
2365
2568
|
const removedProfileDirs = [];
|
|
2366
2569
|
if (fs.existsSync(profilesDir)) for (const entry of fs.readdirSync(profilesDir)) {
|
|
2367
2570
|
const fullPath = path.join(profilesDir, entry);
|
|
@@ -2513,6 +2716,12 @@ var ControlApi = class {
|
|
|
2513
2716
|
async dismissCookieBanner(sessionId) {
|
|
2514
2717
|
return await this.sessions.dismissCookieBanner(sessionId);
|
|
2515
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
|
+
}
|
|
2516
2725
|
listEvents(sessionId, limit = 100) {
|
|
2517
2726
|
return { events: this.eventStore.list(sessionId, limit) };
|
|
2518
2727
|
}
|
|
@@ -2549,7 +2758,7 @@ function loadConfig(env = process.env) {
|
|
|
2549
2758
|
host: env.AGENTIC_BROWSER_HOST ?? "127.0.0.1",
|
|
2550
2759
|
wsPort,
|
|
2551
2760
|
commandTimeoutMs,
|
|
2552
|
-
|
|
2761
|
+
dataDir: env.AGENTIC_BROWSER_DIR ?? path.join(os.homedir(), ".agentic-browser"),
|
|
2553
2762
|
browserExecutablePath: env.AGENTIC_BROWSER_CHROME_EXECUTABLE_PATH ?? env.AGENTIC_BROWSER_CHROME_PATH,
|
|
2554
2763
|
cdpUrl: env.AGENTIC_BROWSER_CDP_URL,
|
|
2555
2764
|
userProfileDir,
|
|
@@ -2751,7 +2960,7 @@ function selectorSignal(insight) {
|
|
|
2751
2960
|
const evidenceStrength = Math.min(selectorEvidence / 5, 1);
|
|
2752
2961
|
return .7 * recipeCoverage + .3 * evidenceStrength;
|
|
2753
2962
|
}
|
|
2754
|
-
function scoreInsight(insight, normalizedIntent, normalizedDomain) {
|
|
2963
|
+
function scoreInsight(insight, normalizedIntent, normalizedDomain, profileLookup) {
|
|
2755
2964
|
const insightIntent = normalize(insight.taskIntent);
|
|
2756
2965
|
const intentMatch = insightIntent === normalizedIntent ? 1 : 0;
|
|
2757
2966
|
const intentPartial = intentMatch === 1 || insightIntent.includes(normalizedIntent) || normalizedIntent.includes(insightIntent) ? .65 : 0;
|
|
@@ -2759,7 +2968,7 @@ function scoreInsight(insight, normalizedIntent, normalizedDomain) {
|
|
|
2759
2968
|
const reliability = .6 * confidenceFromCounts(insight.successCount, insight.failureCount) + .4 * freshnessWeight(insight.freshness);
|
|
2760
2969
|
const selectorQuality = selectorSignal(insight);
|
|
2761
2970
|
const score = .5 * Math.max(intentMatch, intentPartial) + .2 * domainMatch + .15 * reliability + .15 * selectorQuality;
|
|
2762
|
-
|
|
2971
|
+
const result = {
|
|
2763
2972
|
insightId: insight.insightId,
|
|
2764
2973
|
taskIntent: insight.taskIntent,
|
|
2765
2974
|
siteDomain: insight.siteDomain,
|
|
@@ -2770,6 +2979,14 @@ function scoreInsight(insight, normalizedIntent, normalizedDomain) {
|
|
|
2770
2979
|
selectorAliases: buildSelectorAliases(insight),
|
|
2771
2980
|
score
|
|
2772
2981
|
};
|
|
2982
|
+
const profile = profileLookup?.(insight.siteDomain);
|
|
2983
|
+
if (profile) result.siteProfile = {
|
|
2984
|
+
selectorPatterns: profile.selectorPatterns.slice(0, 5),
|
|
2985
|
+
layoutFingerprints: profile.layoutFingerprints.slice(0, 3),
|
|
2986
|
+
cookieBanner: profile.cookieBanner,
|
|
2987
|
+
visitCount: profile.visitCount
|
|
2988
|
+
};
|
|
2989
|
+
return result;
|
|
2773
2990
|
}
|
|
2774
2991
|
var MemoryIndex = class {
|
|
2775
2992
|
/** Domain → insights index, rebuilt lazily when insight list changes. */
|
|
@@ -2790,7 +3007,7 @@ var MemoryIndex = class {
|
|
|
2790
3007
|
}
|
|
2791
3008
|
this.indexedRefs = insights.slice();
|
|
2792
3009
|
}
|
|
2793
|
-
search(insights, input) {
|
|
3010
|
+
search(insights, input, profileLookup) {
|
|
2794
3011
|
const normalizedIntent = normalize(input.taskIntent);
|
|
2795
3012
|
const normalizedDomain = input.siteDomain ? normalize(input.siteDomain) : void 0;
|
|
2796
3013
|
const limit = input.limit ?? 10;
|
|
@@ -2799,7 +3016,7 @@ var MemoryIndex = class {
|
|
|
2799
3016
|
if (limit === 1 && normalizedDomain) {
|
|
2800
3017
|
let best;
|
|
2801
3018
|
for (const insight of candidates) {
|
|
2802
|
-
const result = scoreInsight(insight, normalizedIntent, normalizedDomain);
|
|
3019
|
+
const result = scoreInsight(insight, normalizedIntent, normalizedDomain, profileLookup);
|
|
2803
3020
|
if (result.score > 0 && (!best || result.score > best.score)) {
|
|
2804
3021
|
best = result;
|
|
2805
3022
|
if (best.score >= .95) break;
|
|
@@ -2807,7 +3024,7 @@ var MemoryIndex = class {
|
|
|
2807
3024
|
}
|
|
2808
3025
|
return best ? [best] : [];
|
|
2809
3026
|
}
|
|
2810
|
-
return candidates.map((insight) => scoreInsight(insight, normalizedIntent, normalizedDomain)).filter((result) => result.score > 0).sort((a, b) => b.score - a.score).slice(0, limit);
|
|
3027
|
+
return candidates.map((insight) => scoreInsight(insight, normalizedIntent, normalizedDomain, profileLookup)).filter((result) => result.score > 0).sort((a, b) => b.score - a.score).slice(0, limit);
|
|
2811
3028
|
}
|
|
2812
3029
|
};
|
|
2813
3030
|
//#endregion
|
|
@@ -2838,6 +3055,20 @@ function applyFailure(insight, signal) {
|
|
|
2838
3055
|
updatedAt: now
|
|
2839
3056
|
};
|
|
2840
3057
|
}
|
|
3058
|
+
function applyAgeStaleness(insight) {
|
|
3059
|
+
const ageDays = (Date.now() - Date.parse(insight.lastVerifiedAt)) / (1440 * 60 * 1e3);
|
|
3060
|
+
if (insight.freshness === "fresh" && ageDays > 30) return {
|
|
3061
|
+
...insight,
|
|
3062
|
+
freshness: "suspect",
|
|
3063
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3064
|
+
};
|
|
3065
|
+
if (insight.freshness === "suspect" && ageDays > 44) return {
|
|
3066
|
+
...insight,
|
|
3067
|
+
freshness: "stale",
|
|
3068
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3069
|
+
};
|
|
3070
|
+
return insight;
|
|
3071
|
+
}
|
|
2841
3072
|
function applySuccess(insight) {
|
|
2842
3073
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2843
3074
|
const successCount = insight.successCount + 1;
|
|
@@ -2904,6 +3135,147 @@ const TaskInsightSchema = z.object({
|
|
|
2904
3135
|
selectorAliases: z.array(SelectorAliasSchema).default([])
|
|
2905
3136
|
});
|
|
2906
3137
|
const MemoryStateSchema = z.object({ insights: z.array(TaskInsightSchema) });
|
|
3138
|
+
const SelectorPatternSchema = z.object({
|
|
3139
|
+
pattern: z.string().min(1),
|
|
3140
|
+
frequency: z.number().int().nonnegative(),
|
|
3141
|
+
lastSeenAt: z.string().datetime()
|
|
3142
|
+
});
|
|
3143
|
+
const PageLayoutFingerprintSchema = z.object({
|
|
3144
|
+
pathPattern: z.string().min(1),
|
|
3145
|
+
headings: z.array(z.string()).default([]),
|
|
3146
|
+
landmarks: z.array(z.string()).default([]),
|
|
3147
|
+
lastSeenAt: z.string().datetime()
|
|
3148
|
+
});
|
|
3149
|
+
const SiteProfileSchema = z.object({
|
|
3150
|
+
domain: z.string().min(1),
|
|
3151
|
+
selectorPatterns: z.array(SelectorPatternSchema).default([]),
|
|
3152
|
+
layoutFingerprints: z.array(PageLayoutFingerprintSchema).default([]),
|
|
3153
|
+
navigationPaths: z.array(z.string()).default([]),
|
|
3154
|
+
cookieBanner: z.object({
|
|
3155
|
+
detected: z.boolean(),
|
|
3156
|
+
autoDismissed: z.boolean().optional(),
|
|
3157
|
+
method: z.string().optional()
|
|
3158
|
+
}).optional(),
|
|
3159
|
+
visitCount: z.number().int().nonnegative().default(0),
|
|
3160
|
+
lastVisitAt: z.string().datetime(),
|
|
3161
|
+
createdAt: z.string().datetime()
|
|
3162
|
+
});
|
|
3163
|
+
const SiteProfileStateSchema = z.object({ profiles: z.array(SiteProfileSchema) });
|
|
3164
|
+
//#endregion
|
|
3165
|
+
//#region src/memory/site-profile-store.ts
|
|
3166
|
+
const EMPTY_STATE$1 = { profiles: [] };
|
|
3167
|
+
const FLUSH_DELAY_MS$1 = 500;
|
|
3168
|
+
const REGISTERED_EXIT_HANDLERS$1 = Symbol.for("agentic-browser.site-profile-store.exit-handlers");
|
|
3169
|
+
const REGISTERED_STORES$1 = Symbol.for("agentic-browser.site-profile-store.instances");
|
|
3170
|
+
var SiteProfileStore = class {
|
|
3171
|
+
filePath;
|
|
3172
|
+
cached = null;
|
|
3173
|
+
dirty = false;
|
|
3174
|
+
flushTimer = null;
|
|
3175
|
+
constructor(baseDir) {
|
|
3176
|
+
const memoryDir = path.join(baseDir, "memory");
|
|
3177
|
+
fs.mkdirSync(memoryDir, { recursive: true });
|
|
3178
|
+
this.filePath = path.join(memoryDir, "site-profiles.json");
|
|
3179
|
+
const tmpPath = `${this.filePath}.tmp`;
|
|
3180
|
+
try {
|
|
3181
|
+
if (fs.existsSync(tmpPath)) fs.unlinkSync(tmpPath);
|
|
3182
|
+
} catch {}
|
|
3183
|
+
if (!fs.existsSync(this.filePath)) this.writeDisk(EMPTY_STATE$1);
|
|
3184
|
+
this.registerProcessHandlers();
|
|
3185
|
+
}
|
|
3186
|
+
list() {
|
|
3187
|
+
return this.getCache();
|
|
3188
|
+
}
|
|
3189
|
+
get(domain) {
|
|
3190
|
+
const normalized = domain.toLowerCase();
|
|
3191
|
+
return this.getCache().find((p) => p.domain === normalized);
|
|
3192
|
+
}
|
|
3193
|
+
upsert(profile) {
|
|
3194
|
+
SiteProfileSchema.parse(profile);
|
|
3195
|
+
const profiles = this.getCache();
|
|
3196
|
+
const index = profiles.findIndex((p) => p.domain === profile.domain);
|
|
3197
|
+
if (index >= 0) profiles[index] = profile;
|
|
3198
|
+
else profiles.push(profile);
|
|
3199
|
+
this.markDirty();
|
|
3200
|
+
}
|
|
3201
|
+
flushSync() {
|
|
3202
|
+
if (this.flushTimer) {
|
|
3203
|
+
clearTimeout(this.flushTimer);
|
|
3204
|
+
this.flushTimer = null;
|
|
3205
|
+
}
|
|
3206
|
+
if (this.dirty && this.cached) {
|
|
3207
|
+
this.writeDisk({ profiles: this.cached });
|
|
3208
|
+
this.dirty = false;
|
|
3209
|
+
}
|
|
3210
|
+
}
|
|
3211
|
+
getCache() {
|
|
3212
|
+
if (this.cached) return this.cached;
|
|
3213
|
+
this.cached = this.readDisk().profiles;
|
|
3214
|
+
return this.cached;
|
|
3215
|
+
}
|
|
3216
|
+
markDirty() {
|
|
3217
|
+
this.dirty = true;
|
|
3218
|
+
if (!this.flushTimer) this.flushTimer = setTimeout(() => {
|
|
3219
|
+
this.flushTimer = null;
|
|
3220
|
+
this.flushSync();
|
|
3221
|
+
}, FLUSH_DELAY_MS$1);
|
|
3222
|
+
}
|
|
3223
|
+
readDisk() {
|
|
3224
|
+
let raw;
|
|
3225
|
+
try {
|
|
3226
|
+
raw = JSON.parse(fs.readFileSync(this.filePath, "utf8"));
|
|
3227
|
+
} catch {
|
|
3228
|
+
this.backupAndReset();
|
|
3229
|
+
return EMPTY_STATE$1;
|
|
3230
|
+
}
|
|
3231
|
+
try {
|
|
3232
|
+
return SiteProfileStateSchema.parse(raw);
|
|
3233
|
+
} catch {
|
|
3234
|
+
const obj = raw;
|
|
3235
|
+
if (Array.isArray(obj?.profiles)) {
|
|
3236
|
+
const salvaged = obj.profiles.filter((item) => SiteProfileSchema.safeParse(item).success);
|
|
3237
|
+
if (salvaged.length > 0) {
|
|
3238
|
+
const state = { profiles: salvaged };
|
|
3239
|
+
this.backupAndReset();
|
|
3240
|
+
this.writeDisk(state);
|
|
3241
|
+
return state;
|
|
3242
|
+
}
|
|
3243
|
+
}
|
|
3244
|
+
this.backupAndReset();
|
|
3245
|
+
return EMPTY_STATE$1;
|
|
3246
|
+
}
|
|
3247
|
+
}
|
|
3248
|
+
backupAndReset() {
|
|
3249
|
+
const corruptPath = `${this.filePath}.corrupt-${Date.now()}`;
|
|
3250
|
+
try {
|
|
3251
|
+
fs.copyFileSync(this.filePath, corruptPath);
|
|
3252
|
+
} catch {}
|
|
3253
|
+
}
|
|
3254
|
+
writeDisk(state) {
|
|
3255
|
+
const tempPath = `${this.filePath}.tmp`;
|
|
3256
|
+
fs.writeFileSync(tempPath, JSON.stringify(state, null, 2), "utf8");
|
|
3257
|
+
fs.renameSync(tempPath, this.filePath);
|
|
3258
|
+
}
|
|
3259
|
+
registerProcessHandlers() {
|
|
3260
|
+
const proc = process;
|
|
3261
|
+
const stores = proc[REGISTERED_STORES$1] ??= /* @__PURE__ */ new Set();
|
|
3262
|
+
stores.add(this);
|
|
3263
|
+
if (proc[REGISTERED_EXIT_HANDLERS$1]) return;
|
|
3264
|
+
proc[REGISTERED_EXIT_HANDLERS$1] = true;
|
|
3265
|
+
const flushAll = () => {
|
|
3266
|
+
for (const store of stores) store.flushSync();
|
|
3267
|
+
};
|
|
3268
|
+
process.on("exit", flushAll);
|
|
3269
|
+
process.on("SIGINT", () => {
|
|
3270
|
+
flushAll();
|
|
3271
|
+
process.exit(0);
|
|
3272
|
+
});
|
|
3273
|
+
process.on("SIGTERM", () => {
|
|
3274
|
+
flushAll();
|
|
3275
|
+
process.exit(0);
|
|
3276
|
+
});
|
|
3277
|
+
}
|
|
3278
|
+
};
|
|
2907
3279
|
//#endregion
|
|
2908
3280
|
//#region src/memory/task-insight-store.ts
|
|
2909
3281
|
const EMPTY_STATE = { insights: [] };
|
|
@@ -3030,25 +3402,42 @@ var TaskInsightStore = class {
|
|
|
3030
3402
|
//#endregion
|
|
3031
3403
|
//#region src/memory/memory-service.ts
|
|
3032
3404
|
const SEARCH_CACHE_TTL_MS = 2e3;
|
|
3405
|
+
const MAX_NAVIGATION_PATHS = 20;
|
|
3406
|
+
const MAX_LAYOUT_FINGERPRINTS = 10;
|
|
3407
|
+
const MAX_SELECTOR_PATTERNS = 15;
|
|
3033
3408
|
var MemoryService = class {
|
|
3034
3409
|
store;
|
|
3410
|
+
profileStore;
|
|
3035
3411
|
index;
|
|
3036
3412
|
/** Simple TTL cache for search results keyed by intent+domain+limit. */
|
|
3037
3413
|
searchCache = /* @__PURE__ */ new Map();
|
|
3038
3414
|
constructor(baseDir) {
|
|
3039
3415
|
this.store = new TaskInsightStore(baseDir);
|
|
3416
|
+
this.profileStore = new SiteProfileStore(baseDir);
|
|
3040
3417
|
this.index = new MemoryIndex();
|
|
3041
3418
|
}
|
|
3042
3419
|
/** Force an immediate synchronous flush of pending writes. */
|
|
3043
3420
|
flushSync() {
|
|
3044
3421
|
this.store.flushSync();
|
|
3422
|
+
this.profileStore.flushSync();
|
|
3045
3423
|
}
|
|
3046
3424
|
search(input) {
|
|
3047
3425
|
const cacheKey = `${input.taskIntent}\0${input.siteDomain ?? ""}\0${input.limit ?? 10}`;
|
|
3048
3426
|
const now = Date.now();
|
|
3049
3427
|
const cached = this.searchCache.get(cacheKey);
|
|
3050
3428
|
if (cached && now - cached.ts < SEARCH_CACHE_TTL_MS) return cached.results;
|
|
3051
|
-
const
|
|
3429
|
+
const insights = this.store.list();
|
|
3430
|
+
let mutated = false;
|
|
3431
|
+
for (let i = 0; i < insights.length; i++) {
|
|
3432
|
+
const decayed = applyAgeStaleness(insights[i]);
|
|
3433
|
+
if (decayed.freshness !== insights[i].freshness) {
|
|
3434
|
+
insights[i] = decayed;
|
|
3435
|
+
this.store.upsert(decayed);
|
|
3436
|
+
mutated = true;
|
|
3437
|
+
}
|
|
3438
|
+
}
|
|
3439
|
+
if (mutated) this.searchCache.clear();
|
|
3440
|
+
const results = this.index.search(insights, input, (domain) => this.profileStore.get(domain));
|
|
3052
3441
|
this.searchCache.set(cacheKey, {
|
|
3053
3442
|
results,
|
|
3054
3443
|
ts: now
|
|
@@ -3092,6 +3481,7 @@ var MemoryService = class {
|
|
|
3092
3481
|
return verified;
|
|
3093
3482
|
}
|
|
3094
3483
|
recordSuccess(input) {
|
|
3484
|
+
this.updateSiteProfile(input.siteDomain, input.selector, input.url, input.sitePathPattern);
|
|
3095
3485
|
const insights = this.store.list();
|
|
3096
3486
|
const matched = this.findBestExactMatch(insights, input);
|
|
3097
3487
|
const evidence = this.createEvidence(input, "success");
|
|
@@ -3149,6 +3539,7 @@ var MemoryService = class {
|
|
|
3149
3539
|
return withAliases;
|
|
3150
3540
|
}
|
|
3151
3541
|
recordFailure(input, errorMessage) {
|
|
3542
|
+
this.updateSiteProfile(input.siteDomain, input.selector, input.url, input.sitePathPattern);
|
|
3152
3543
|
const insights = this.store.list();
|
|
3153
3544
|
const matched = this.findBestExactMatch(insights, input);
|
|
3154
3545
|
if (!matched) return;
|
|
@@ -3163,6 +3554,91 @@ var MemoryService = class {
|
|
|
3163
3554
|
this.invalidateSearchCache();
|
|
3164
3555
|
return failed;
|
|
3165
3556
|
}
|
|
3557
|
+
/** Update site profile from page content (call after getContent with mode="summary"). */
|
|
3558
|
+
updateProfileFromContent(domain, pathPattern, structuredContent) {
|
|
3559
|
+
if (!domain || domain === "unknown") return;
|
|
3560
|
+
const normalized = domain.toLowerCase();
|
|
3561
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3562
|
+
const profile = this.profileStore.get(normalized) ?? this.createEmptyProfile(normalized, now);
|
|
3563
|
+
const fingerprint = {
|
|
3564
|
+
pathPattern,
|
|
3565
|
+
headings: (structuredContent.headings ?? []).slice(0, 8),
|
|
3566
|
+
landmarks: (structuredContent.landmarks ?? []).slice(0, 8),
|
|
3567
|
+
lastSeenAt: now
|
|
3568
|
+
};
|
|
3569
|
+
const fpIndex = profile.layoutFingerprints.findIndex((fp) => fp.pathPattern === pathPattern);
|
|
3570
|
+
if (fpIndex >= 0) profile.layoutFingerprints[fpIndex] = fingerprint;
|
|
3571
|
+
else {
|
|
3572
|
+
profile.layoutFingerprints.push(fingerprint);
|
|
3573
|
+
if (profile.layoutFingerprints.length > MAX_LAYOUT_FINGERPRINTS) profile.layoutFingerprints = profile.layoutFingerprints.sort((a, b) => b.lastSeenAt.localeCompare(a.lastSeenAt)).slice(0, MAX_LAYOUT_FINGERPRINTS);
|
|
3574
|
+
}
|
|
3575
|
+
profile.lastVisitAt = now;
|
|
3576
|
+
this.profileStore.upsert(profile);
|
|
3577
|
+
}
|
|
3578
|
+
/** Update site profile with cookie banner behavior. */
|
|
3579
|
+
updateProfileCookieBanner(domain, result) {
|
|
3580
|
+
if (!domain || domain === "unknown") return;
|
|
3581
|
+
const normalized = domain.toLowerCase();
|
|
3582
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3583
|
+
const profile = this.profileStore.get(normalized) ?? this.createEmptyProfile(normalized, now);
|
|
3584
|
+
profile.cookieBanner = {
|
|
3585
|
+
detected: true,
|
|
3586
|
+
autoDismissed: result.dismissed,
|
|
3587
|
+
method: result.method
|
|
3588
|
+
};
|
|
3589
|
+
profile.lastVisitAt = now;
|
|
3590
|
+
this.profileStore.upsert(profile);
|
|
3591
|
+
}
|
|
3592
|
+
/** Look up a site profile by domain. */
|
|
3593
|
+
getSiteProfile(domain) {
|
|
3594
|
+
return this.profileStore.get(domain);
|
|
3595
|
+
}
|
|
3596
|
+
updateSiteProfile(domain, selector, url, pathPattern) {
|
|
3597
|
+
if (!domain || domain === "unknown") return;
|
|
3598
|
+
const normalized = domain.toLowerCase();
|
|
3599
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3600
|
+
const profile = this.profileStore.get(normalized) ?? this.createEmptyProfile(normalized, now);
|
|
3601
|
+
profile.visitCount += 1;
|
|
3602
|
+
profile.lastVisitAt = now;
|
|
3603
|
+
if (selector) {
|
|
3604
|
+
const pattern = this.classifySelectorPattern(selector);
|
|
3605
|
+
if (pattern) {
|
|
3606
|
+
const existing = profile.selectorPatterns.find((p) => p.pattern === pattern);
|
|
3607
|
+
if (existing) {
|
|
3608
|
+
existing.frequency += 1;
|
|
3609
|
+
existing.lastSeenAt = now;
|
|
3610
|
+
} else if (profile.selectorPatterns.length < MAX_SELECTOR_PATTERNS) profile.selectorPatterns.push({
|
|
3611
|
+
pattern,
|
|
3612
|
+
frequency: 1,
|
|
3613
|
+
lastSeenAt: now
|
|
3614
|
+
});
|
|
3615
|
+
}
|
|
3616
|
+
}
|
|
3617
|
+
if (pathPattern && pathPattern !== "/") {
|
|
3618
|
+
if (!profile.navigationPaths.includes(pathPattern) && profile.navigationPaths.length < MAX_NAVIGATION_PATHS) profile.navigationPaths.push(pathPattern);
|
|
3619
|
+
}
|
|
3620
|
+
this.profileStore.upsert(profile);
|
|
3621
|
+
}
|
|
3622
|
+
createEmptyProfile(domain, now) {
|
|
3623
|
+
return {
|
|
3624
|
+
domain,
|
|
3625
|
+
selectorPatterns: [],
|
|
3626
|
+
layoutFingerprints: [],
|
|
3627
|
+
navigationPaths: [],
|
|
3628
|
+
visitCount: 0,
|
|
3629
|
+
lastVisitAt: now,
|
|
3630
|
+
createdAt: now
|
|
3631
|
+
};
|
|
3632
|
+
}
|
|
3633
|
+
classifySelectorPattern(selector) {
|
|
3634
|
+
if (selector.includes("[data-testid=")) return "data-testid";
|
|
3635
|
+
if (selector.includes("[data-cy=")) return "data-cy";
|
|
3636
|
+
if (selector.includes("[data-test=")) return "data-test";
|
|
3637
|
+
if (selector.includes("[aria-label=")) return "aria-label";
|
|
3638
|
+
if (selector.includes("[name=")) return "name-attribute";
|
|
3639
|
+
if (/^#[\w-]+$/.test(selector)) return "id-selector";
|
|
3640
|
+
if (selector.includes("[role=")) return "role-attribute";
|
|
3641
|
+
}
|
|
3166
3642
|
findBestExactMatch(insights, input) {
|
|
3167
3643
|
const intentLower = input.taskIntent.toLowerCase();
|
|
3168
3644
|
const domainLower = input.siteDomain.toLowerCase();
|
|
@@ -3251,7 +3727,7 @@ var MemoryService = class {
|
|
|
3251
3727
|
function createAppContext(env = process.env) {
|
|
3252
3728
|
const config = loadConfig(env);
|
|
3253
3729
|
const logger = new Logger("app");
|
|
3254
|
-
const eventStore = new EventStore(config.
|
|
3730
|
+
const eventStore = new EventStore(config.dataDir);
|
|
3255
3731
|
const tokenService = new SessionTokenService();
|
|
3256
3732
|
return {
|
|
3257
3733
|
config,
|
|
@@ -3263,7 +3739,7 @@ function createAppContext(env = process.env) {
|
|
|
3263
3739
|
port: config.wsPort,
|
|
3264
3740
|
tokenService
|
|
3265
3741
|
}),
|
|
3266
|
-
memoryService: new MemoryService(config.
|
|
3742
|
+
memoryService: new MemoryService(config.dataDir)
|
|
3267
3743
|
};
|
|
3268
3744
|
}
|
|
3269
3745
|
//#endregion
|
|
@@ -3284,8 +3760,9 @@ var AgenticBrowserCore = class {
|
|
|
3284
3760
|
return this.api.getSession(sessionId);
|
|
3285
3761
|
}
|
|
3286
3762
|
async runCommand(input) {
|
|
3763
|
+
const commandId = input.commandId ?? `${input.type}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
3287
3764
|
return await this.api.executeCommand(input.sessionId, {
|
|
3288
|
-
commandId
|
|
3765
|
+
commandId,
|
|
3289
3766
|
type: input.type,
|
|
3290
3767
|
payload: input.payload
|
|
3291
3768
|
});
|
|
@@ -3308,6 +3785,12 @@ var AgenticBrowserCore = class {
|
|
|
3308
3785
|
async dismissCookieBanner(sessionId) {
|
|
3309
3786
|
return await this.api.dismissCookieBanner(sessionId);
|
|
3310
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
|
+
}
|
|
3311
3794
|
async restartSession(sessionId) {
|
|
3312
3795
|
return await this.api.restartSession(sessionId);
|
|
3313
3796
|
}
|
|
@@ -3332,7 +3815,7 @@ var AgenticBrowserCore = class {
|
|
|
3332
3815
|
};
|
|
3333
3816
|
function createAgenticBrowserCore(options = {}) {
|
|
3334
3817
|
const context = createAppContext(options.env);
|
|
3335
|
-
return new AgenticBrowserCore(context, options.browserController ?? new ChromeCdpBrowserController(context.config.
|
|
3818
|
+
return new AgenticBrowserCore(context, options.browserController ?? new ChromeCdpBrowserController(context.config.dataDir));
|
|
3336
3819
|
}
|
|
3337
3820
|
function createMockAgenticBrowserCore(env) {
|
|
3338
3821
|
return new AgenticBrowserCore(createAppContext(env), new MockBrowserController());
|