agentic-browser 2.5.0 → 2.5.1
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/dist/cli/index.mjs +3 -3
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +1 -1
- package/dist/mcp/index.mjs +2 -2
- package/dist/{runtime-C3Y-UgC1.mjs → runtime-BeD8ZcjH.mjs} +161 -30
- package/package.json +13 -13
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-BeD8ZcjH.mjs";
|
|
3
3
|
import fs from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import crypto from "node:crypto";
|
|
@@ -242,7 +242,7 @@ async function runCommand(runtime, input) {
|
|
|
242
242
|
payload: input.payload
|
|
243
243
|
});
|
|
244
244
|
} catch (error) {
|
|
245
|
-
throw new Error(`Command rejected: ${error.message}
|
|
245
|
+
throw new Error(`Command rejected: ${error.message}`, { cause: error });
|
|
246
246
|
}
|
|
247
247
|
}
|
|
248
248
|
//#endregion
|
|
@@ -279,11 +279,11 @@ async function runMemoryStats(runtime) {
|
|
|
279
279
|
}
|
|
280
280
|
//#endregion
|
|
281
281
|
//#region src/cli/index.ts
|
|
282
|
+
const collect = (value, previous = []) => [...previous, value];
|
|
282
283
|
async function main() {
|
|
283
284
|
const runtime = createCliRuntime();
|
|
284
285
|
const program = new Command();
|
|
285
286
|
program.name("agentic-browser").description("Agentic browser CLI");
|
|
286
|
-
const collect = (value, previous = []) => [...previous, value];
|
|
287
287
|
program.command("session:start").option("--cdp-url <url>", "connect to existing Chrome via CDP endpoint URL").option("--user-profile <path>", "use 'default' for system Chrome profile or an absolute path").option("--headless", "run Chrome in headless mode (no visible window)").option("--user-agent <string>", "override the browser user-agent string").action(async (options) => {
|
|
288
288
|
if (options.cdpUrl) runtime.context.config.cdpUrl = options.cdpUrl;
|
|
289
289
|
if (options.userProfile) runtime.context.config.userProfileDir = options.userProfile === "true" || options.userProfile === "default" ? "default" : options.userProfile;
|
package/dist/index.d.mts
CHANGED
|
@@ -99,6 +99,7 @@ interface BrowserController {
|
|
|
99
99
|
getCurrentUrl(targetWsUrl: string): Promise<string>;
|
|
100
100
|
terminate(pid: number): void;
|
|
101
101
|
closeConnection?(targetWsUrl: string): void;
|
|
102
|
+
dispose?(): void;
|
|
102
103
|
}
|
|
103
104
|
//#endregion
|
|
104
105
|
//#region src/memory/memory-schemas.d.ts
|
|
@@ -600,8 +601,7 @@ declare class SessionManager {
|
|
|
600
601
|
//#region src/transport/control-api.d.ts
|
|
601
602
|
declare class ControlApi {
|
|
602
603
|
private readonly sessions;
|
|
603
|
-
|
|
604
|
-
constructor(sessions: SessionManager, eventStore: EventStore);
|
|
604
|
+
constructor(sessions: SessionManager);
|
|
605
605
|
createSession(input: {
|
|
606
606
|
browser: "chrome";
|
|
607
607
|
}): Promise<{
|
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-BeD8ZcjH.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-BeD8ZcjH.mjs";
|
|
3
3
|
import { readFileSync } from "node:fs";
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
@@ -155,7 +155,7 @@ function summarizeElements(elements) {
|
|
|
155
155
|
});
|
|
156
156
|
}
|
|
157
157
|
return {
|
|
158
|
-
countsByRole: Object.fromEntries([...byRole.entries()].
|
|
158
|
+
countsByRole: Object.fromEntries([...byRole.entries()].toSorted((a, b) => b[1] - a[1])),
|
|
159
159
|
primaryActions
|
|
160
160
|
};
|
|
161
161
|
}
|
|
@@ -175,6 +175,10 @@ async function getJson(url, timeoutMs = 5e3) {
|
|
|
175
175
|
if (!response.ok) throw new Error(`HTTP ${response.status}: ${url}`);
|
|
176
176
|
return await response.json();
|
|
177
177
|
}
|
|
178
|
+
/** Debugger connection timing */
|
|
179
|
+
const DEBUGGER_READY_TIMEOUT_MS = 15e3;
|
|
180
|
+
const DEBUGGER_INITIAL_RETRY_DELAY_MS = 50;
|
|
181
|
+
const DEBUGGER_MAX_RETRY_DELAY_MS = 250;
|
|
178
182
|
/** Check if the debug port is accepting TCP connections (faster than an HTTP fetch). */
|
|
179
183
|
function probePort(port) {
|
|
180
184
|
return new Promise((resolve) => {
|
|
@@ -193,16 +197,15 @@ function probePort(port) {
|
|
|
193
197
|
});
|
|
194
198
|
}
|
|
195
199
|
async function waitForDebugger(port) {
|
|
196
|
-
const maxMs = 15e3;
|
|
197
200
|
const start = Date.now();
|
|
198
|
-
let delay =
|
|
199
|
-
while (Date.now() - start <
|
|
201
|
+
let delay = DEBUGGER_INITIAL_RETRY_DELAY_MS;
|
|
202
|
+
while (Date.now() - start < DEBUGGER_READY_TIMEOUT_MS) {
|
|
200
203
|
if (await probePort(port)) try {
|
|
201
204
|
await getJson(`http://127.0.0.1:${port}/json/version`);
|
|
202
205
|
return;
|
|
203
206
|
} catch {}
|
|
204
207
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
205
|
-
delay = Math.min(delay * 2,
|
|
208
|
+
delay = Math.min(delay * 2, DEBUGGER_MAX_RETRY_DELAY_MS);
|
|
206
209
|
}
|
|
207
210
|
throw new Error("Chrome debug endpoint did not become ready in time");
|
|
208
211
|
}
|
|
@@ -694,6 +697,9 @@ function buildKeyDispatchPayload(inputKey) {
|
|
|
694
697
|
nativeVirtualKeyCode: 0
|
|
695
698
|
};
|
|
696
699
|
}
|
|
700
|
+
/** Connection pool configuration */
|
|
701
|
+
const CONNECTION_IDLE_TIMEOUT_MS = 300 * 1e3;
|
|
702
|
+
const CONNECTION_CLEANUP_INTERVAL_MS = 6e4;
|
|
697
703
|
var ChromeCdpBrowserController = class {
|
|
698
704
|
connections = /* @__PURE__ */ new Map();
|
|
699
705
|
cleanupInterval;
|
|
@@ -701,11 +707,16 @@ var ChromeCdpBrowserController = class {
|
|
|
701
707
|
this.baseDir = baseDir;
|
|
702
708
|
this.connectionFactory = connectionFactory;
|
|
703
709
|
this.cleanupInterval = setInterval(() => {
|
|
704
|
-
const cutoff = Date.now() -
|
|
710
|
+
const cutoff = Date.now() - CONNECTION_IDLE_TIMEOUT_MS;
|
|
705
711
|
for (const [url, entry] of this.connections) if (entry.lastUsedAt < cutoff) this.dropConnection(url);
|
|
706
|
-
},
|
|
712
|
+
}, CONNECTION_CLEANUP_INTERVAL_MS);
|
|
707
713
|
this.cleanupInterval.unref();
|
|
708
714
|
}
|
|
715
|
+
/** Stop the cleanup interval and close all connections. Call when disposing the controller. */
|
|
716
|
+
dispose() {
|
|
717
|
+
clearInterval(this.cleanupInterval);
|
|
718
|
+
for (const url of this.connections.keys()) this.dropConnection(url);
|
|
719
|
+
}
|
|
709
720
|
async getConnection(targetWsUrl) {
|
|
710
721
|
const cached = this.connections.get(targetWsUrl);
|
|
711
722
|
if (cached) {
|
|
@@ -849,12 +860,18 @@ var ChromeCdpBrowserController = class {
|
|
|
849
860
|
});
|
|
850
861
|
}
|
|
851
862
|
async handleDialogAction(targetWsUrl, payload) {
|
|
863
|
+
const DIALOG_WAIT_TIMEOUT_MS = 500;
|
|
864
|
+
const DIALOG_POLL_INTERVAL_MS = 10;
|
|
865
|
+
const MAX_POLL_ATTEMPTS = 10;
|
|
852
866
|
return await this.withRetry(targetWsUrl, async (conn) => {
|
|
853
867
|
await this.ensureEnabled(targetWsUrl);
|
|
854
868
|
const cached = this.connections.get(targetWsUrl);
|
|
855
869
|
if (!cached?.pendingDialog) try {
|
|
856
|
-
await conn.waitForEvent("Page.javascriptDialogOpening",
|
|
857
|
-
|
|
870
|
+
await conn.waitForEvent("Page.javascriptDialogOpening", DIALOG_WAIT_TIMEOUT_MS);
|
|
871
|
+
for (let attempt = 0; attempt < MAX_POLL_ATTEMPTS; attempt++) {
|
|
872
|
+
if (cached?.pendingDialog) break;
|
|
873
|
+
await new Promise((r) => setTimeout(r, DIALOG_POLL_INTERVAL_MS));
|
|
874
|
+
}
|
|
858
875
|
} catch {
|
|
859
876
|
return "no dialog present";
|
|
860
877
|
}
|
|
@@ -2467,6 +2484,113 @@ var MockBrowserController = class {
|
|
|
2467
2484
|
closeConnection(_targetWsUrl) {}
|
|
2468
2485
|
};
|
|
2469
2486
|
//#endregion
|
|
2487
|
+
//#region src/lib/domain-schemas.ts
|
|
2488
|
+
const InteractActionSchema = z.enum([
|
|
2489
|
+
"click",
|
|
2490
|
+
"type",
|
|
2491
|
+
"press",
|
|
2492
|
+
"waitFor",
|
|
2493
|
+
"evaluate",
|
|
2494
|
+
"scroll",
|
|
2495
|
+
"hover",
|
|
2496
|
+
"select",
|
|
2497
|
+
"toggle",
|
|
2498
|
+
"goBack",
|
|
2499
|
+
"goForward",
|
|
2500
|
+
"refresh",
|
|
2501
|
+
"dialog"
|
|
2502
|
+
]);
|
|
2503
|
+
const InteractPayloadSchema = z.object({
|
|
2504
|
+
action: InteractActionSchema,
|
|
2505
|
+
selector: z.string().optional(),
|
|
2506
|
+
fallbackSelectors: z.array(z.string()).optional(),
|
|
2507
|
+
text: z.string().optional(),
|
|
2508
|
+
key: z.string().optional(),
|
|
2509
|
+
value: z.string().optional(),
|
|
2510
|
+
scrollX: z.number().optional(),
|
|
2511
|
+
scrollY: z.number().optional(),
|
|
2512
|
+
timeoutMs: z.number().optional()
|
|
2513
|
+
});
|
|
2514
|
+
const SessionStatusSchema = z.enum([
|
|
2515
|
+
"starting",
|
|
2516
|
+
"ready",
|
|
2517
|
+
"disconnected",
|
|
2518
|
+
"failed",
|
|
2519
|
+
"terminated"
|
|
2520
|
+
]);
|
|
2521
|
+
const CommandTypeSchema = z.enum([
|
|
2522
|
+
"navigate",
|
|
2523
|
+
"interact",
|
|
2524
|
+
"restart",
|
|
2525
|
+
"terminate"
|
|
2526
|
+
]);
|
|
2527
|
+
const ResultStatusSchema = z.enum([
|
|
2528
|
+
"success",
|
|
2529
|
+
"failed",
|
|
2530
|
+
"timed_out"
|
|
2531
|
+
]);
|
|
2532
|
+
const ConnectionStateSchema = z.enum([
|
|
2533
|
+
"connecting",
|
|
2534
|
+
"ready",
|
|
2535
|
+
"disconnected",
|
|
2536
|
+
"failed"
|
|
2537
|
+
]);
|
|
2538
|
+
const EventCategorySchema = z.enum([
|
|
2539
|
+
"lifecycle",
|
|
2540
|
+
"security",
|
|
2541
|
+
"command"
|
|
2542
|
+
]);
|
|
2543
|
+
const EventSeveritySchema = z.enum([
|
|
2544
|
+
"info",
|
|
2545
|
+
"warning",
|
|
2546
|
+
"error"
|
|
2547
|
+
]);
|
|
2548
|
+
z.object({
|
|
2549
|
+
sessionId: z.string().min(1),
|
|
2550
|
+
status: SessionStatusSchema,
|
|
2551
|
+
browserType: z.literal("chrome"),
|
|
2552
|
+
startedAt: z.string().datetime(),
|
|
2553
|
+
endedAt: z.string().datetime().optional(),
|
|
2554
|
+
authTokenRef: z.string().min(1)
|
|
2555
|
+
}).refine((session) => session.status === "terminated" ? Boolean(session.endedAt) : true, {
|
|
2556
|
+
message: "endedAt is required for terminated sessions",
|
|
2557
|
+
path: ["endedAt"]
|
|
2558
|
+
});
|
|
2559
|
+
z.object({
|
|
2560
|
+
commandId: z.string().min(1),
|
|
2561
|
+
sessionId: z.string().min(1),
|
|
2562
|
+
type: CommandTypeSchema,
|
|
2563
|
+
payload: z.record(z.string(), z.unknown()),
|
|
2564
|
+
submittedAt: z.string().datetime(),
|
|
2565
|
+
completedAt: z.string().datetime().optional(),
|
|
2566
|
+
resultStatus: ResultStatusSchema.optional(),
|
|
2567
|
+
resultMessage: z.string().optional()
|
|
2568
|
+
}).refine((command) => command.completedAt ? Boolean(command.resultStatus) : true, {
|
|
2569
|
+
message: "resultStatus is required when completedAt is set",
|
|
2570
|
+
path: ["resultStatus"]
|
|
2571
|
+
});
|
|
2572
|
+
z.object({
|
|
2573
|
+
sessionId: z.string().min(1),
|
|
2574
|
+
state: ConnectionStateSchema,
|
|
2575
|
+
lastHeartbeatAt: z.string().datetime().optional(),
|
|
2576
|
+
disconnectReason: z.string().optional()
|
|
2577
|
+
});
|
|
2578
|
+
z.object({
|
|
2579
|
+
sessionId: z.string().min(1),
|
|
2580
|
+
tokenId: z.string().min(1),
|
|
2581
|
+
issuedAt: z.string().datetime(),
|
|
2582
|
+
expiresAt: z.string().datetime().optional(),
|
|
2583
|
+
revokedAt: z.string().datetime().optional()
|
|
2584
|
+
});
|
|
2585
|
+
z.object({
|
|
2586
|
+
eventId: z.string().min(1),
|
|
2587
|
+
sessionId: z.string().min(1),
|
|
2588
|
+
category: EventCategorySchema,
|
|
2589
|
+
message: z.string().min(1),
|
|
2590
|
+
createdAt: z.string().datetime(),
|
|
2591
|
+
severity: EventSeveritySchema
|
|
2592
|
+
});
|
|
2593
|
+
//#endregion
|
|
2470
2594
|
//#region src/session/session-store.ts
|
|
2471
2595
|
var SessionStore = class {
|
|
2472
2596
|
filePath;
|
|
@@ -2610,7 +2734,7 @@ var SessionManager = class {
|
|
|
2610
2734
|
return this.mustGetRecord(recovered.sessionId);
|
|
2611
2735
|
} catch (restartError) {
|
|
2612
2736
|
this.recordEvent(sessionId, "lifecycle", "error", `Recovery failed: ${restartError.message}`);
|
|
2613
|
-
throw new Error(`Session is not ready and recovery failed: ${restartError.message}
|
|
2737
|
+
throw new Error(`Session is not ready and recovery failed: ${restartError.message}`, { cause: restartError });
|
|
2614
2738
|
}
|
|
2615
2739
|
throw new Error("Session is terminated. Start a new session.");
|
|
2616
2740
|
}
|
|
@@ -2639,8 +2763,11 @@ var SessionManager = class {
|
|
|
2639
2763
|
const finalUrl = await this.browser.navigate(record.targetWsUrl, url);
|
|
2640
2764
|
this.store.setLastUrl(sessionId, finalUrl);
|
|
2641
2765
|
resultMessage = `Navigated to ${finalUrl}`;
|
|
2642
|
-
} else if (input.type === "interact")
|
|
2643
|
-
|
|
2766
|
+
} else if (input.type === "interact") {
|
|
2767
|
+
const parsedPayload = InteractPayloadSchema.safeParse(input.payload);
|
|
2768
|
+
if (!parsedPayload.success) throw new Error(`Invalid interact payload: ${parsedPayload.error.message}`);
|
|
2769
|
+
resultMessage = `Interaction result: ${await this.browser.interact(record.targetWsUrl, parsedPayload.data)}`;
|
|
2770
|
+
} else if (input.type === "restart") {
|
|
2644
2771
|
await this.restartSession(sessionId);
|
|
2645
2772
|
resultMessage = "Session restarted";
|
|
2646
2773
|
} else if (input.type === "terminate") {
|
|
@@ -2952,9 +3079,8 @@ var SessionManager = class {
|
|
|
2952
3079
|
//#endregion
|
|
2953
3080
|
//#region src/transport/control-api.ts
|
|
2954
3081
|
var ControlApi = class {
|
|
2955
|
-
constructor(sessions
|
|
3082
|
+
constructor(sessions) {
|
|
2956
3083
|
this.sessions = sessions;
|
|
2957
|
-
this.eventStore = eventStore;
|
|
2958
3084
|
}
|
|
2959
3085
|
async createSession(input) {
|
|
2960
3086
|
return await this.sessions.createSession(input);
|
|
@@ -2990,7 +3116,7 @@ var ControlApi = class {
|
|
|
2990
3116
|
return await this.sessions.getCurrentUrl(sessionId);
|
|
2991
3117
|
}
|
|
2992
3118
|
listEvents(sessionId, limit = 100) {
|
|
2993
|
-
return { events: this.
|
|
3119
|
+
return { events: this.sessions.listEvents(sessionId, limit) };
|
|
2994
3120
|
}
|
|
2995
3121
|
searchMemory(input) {
|
|
2996
3122
|
return { results: this.sessions.searchMemory(input) };
|
|
@@ -3215,7 +3341,7 @@ function buildSelectorHints(insight) {
|
|
|
3215
3341
|
if (!evidence.selector || evidence.result !== "success") continue;
|
|
3216
3342
|
weightedSelectors.set(evidence.selector, (weightedSelectors.get(evidence.selector) ?? 0) + 3);
|
|
3217
3343
|
}
|
|
3218
|
-
return [...weightedSelectors.entries()].
|
|
3344
|
+
return [...weightedSelectors.entries()].toSorted((a, b) => b[1] - a[1]).slice(0, 5).map(([selector]) => selector);
|
|
3219
3345
|
}
|
|
3220
3346
|
function buildSelectorAliases(insight) {
|
|
3221
3347
|
return insight.selectorAliases ?? [];
|
|
@@ -3291,7 +3417,7 @@ var MemoryIndex = class {
|
|
|
3291
3417
|
}
|
|
3292
3418
|
return best ? [best] : [];
|
|
3293
3419
|
}
|
|
3294
|
-
return candidates.map((insight) => scoreInsight(insight, normalizedIntent, normalizedDomain, profileLookup)).filter((result) => result.score > 0).
|
|
3420
|
+
return candidates.map((insight) => scoreInsight(insight, normalizedIntent, normalizedDomain, profileLookup)).filter((result) => result.score > 0).toSorted((a, b) => b.score - a.score).slice(0, limit);
|
|
3295
3421
|
}
|
|
3296
3422
|
};
|
|
3297
3423
|
//#endregion
|
|
@@ -3668,10 +3794,19 @@ var TaskInsightStore = class {
|
|
|
3668
3794
|
};
|
|
3669
3795
|
//#endregion
|
|
3670
3796
|
//#region src/memory/memory-service.ts
|
|
3797
|
+
/** Memory service configuration */
|
|
3671
3798
|
const SEARCH_CACHE_TTL_MS = 2e3;
|
|
3799
|
+
const MAX_EVIDENCE_RECORDS = 50;
|
|
3800
|
+
const MAX_RECIPE_STEPS = 8;
|
|
3801
|
+
const MAX_SELECTOR_ALIASES = 10;
|
|
3802
|
+
/** Site profile limits */
|
|
3672
3803
|
const MAX_NAVIGATION_PATHS = 20;
|
|
3673
3804
|
const MAX_LAYOUT_FINGERPRINTS = 10;
|
|
3674
3805
|
const MAX_SELECTOR_PATTERNS = 15;
|
|
3806
|
+
function normalizePathSegment(value) {
|
|
3807
|
+
const [firstSegment = ""] = value.replace(/\/\*$/, "").split("/").filter(Boolean);
|
|
3808
|
+
return firstSegment.toLowerCase();
|
|
3809
|
+
}
|
|
3675
3810
|
var MemoryService = class {
|
|
3676
3811
|
store;
|
|
3677
3812
|
profileStore;
|
|
@@ -3729,7 +3864,7 @@ var MemoryService = class {
|
|
|
3729
3864
|
fresh: insights.filter((x) => x.freshness === "fresh").length,
|
|
3730
3865
|
suspect: insights.filter((x) => x.freshness === "suspect").length,
|
|
3731
3866
|
stale: insights.filter((x) => x.freshness === "stale").length,
|
|
3732
|
-
topDomains: [...byDomain.entries()].
|
|
3867
|
+
topDomains: [...byDomain.entries()].toSorted((a, b) => b[1] - a[1]).slice(0, 10).map(([domain, count]) => ({
|
|
3733
3868
|
domain,
|
|
3734
3869
|
count
|
|
3735
3870
|
}))
|
|
@@ -3781,7 +3916,7 @@ var MemoryService = class {
|
|
|
3781
3916
|
const refreshed = applySuccess({
|
|
3782
3917
|
...matched,
|
|
3783
3918
|
useCount: matched.useCount + 1,
|
|
3784
|
-
evidence: [...matched.evidence.slice(-
|
|
3919
|
+
evidence: [...matched.evidence.slice(-(MAX_EVIDENCE_RECORDS - 1)), evidence],
|
|
3785
3920
|
actionRecipe: this.mergeRecipe(matched.actionRecipe, input.step),
|
|
3786
3921
|
expectedOutcome: input.expectedOutcome
|
|
3787
3922
|
});
|
|
@@ -3815,7 +3950,7 @@ var MemoryService = class {
|
|
|
3815
3950
|
const failed = applyFailure({
|
|
3816
3951
|
...matched,
|
|
3817
3952
|
useCount: matched.useCount + 1,
|
|
3818
|
-
evidence: [...matched.evidence.slice(-
|
|
3953
|
+
evidence: [...matched.evidence.slice(-(MAX_EVIDENCE_RECORDS - 1)), evidence]
|
|
3819
3954
|
}, signal);
|
|
3820
3955
|
this.store.upsert(failed);
|
|
3821
3956
|
this.invalidateSearchCache();
|
|
@@ -3837,7 +3972,7 @@ var MemoryService = class {
|
|
|
3837
3972
|
if (fpIndex >= 0) profile.layoutFingerprints[fpIndex] = fingerprint;
|
|
3838
3973
|
else {
|
|
3839
3974
|
profile.layoutFingerprints.push(fingerprint);
|
|
3840
|
-
if (profile.layoutFingerprints.length > MAX_LAYOUT_FINGERPRINTS) profile.layoutFingerprints = profile.layoutFingerprints.
|
|
3975
|
+
if (profile.layoutFingerprints.length > MAX_LAYOUT_FINGERPRINTS) profile.layoutFingerprints = profile.layoutFingerprints.toSorted((a, b) => b.lastSeenAt.localeCompare(a.lastSeenAt)).slice(0, MAX_LAYOUT_FINGERPRINTS);
|
|
3841
3976
|
}
|
|
3842
3977
|
profile.lastVisitAt = now;
|
|
3843
3978
|
this.profileStore.upsert(profile);
|
|
@@ -3929,12 +4064,8 @@ var MemoryService = class {
|
|
|
3929
4064
|
return score;
|
|
3930
4065
|
}
|
|
3931
4066
|
sameFirstPathSegment(left, right) {
|
|
3932
|
-
const
|
|
3933
|
-
|
|
3934
|
-
return firstSegment.toLowerCase();
|
|
3935
|
-
};
|
|
3936
|
-
const leftSegment = normalize(left);
|
|
3937
|
-
const rightSegment = normalize(right);
|
|
4067
|
+
const leftSegment = normalizePathSegment(left);
|
|
4068
|
+
const rightSegment = normalizePathSegment(right);
|
|
3938
4069
|
return Boolean(leftSegment) && leftSegment === rightSegment;
|
|
3939
4070
|
}
|
|
3940
4071
|
createEvidence(input, result, reason) {
|
|
@@ -3963,11 +4094,11 @@ var MemoryService = class {
|
|
|
3963
4094
|
selector,
|
|
3964
4095
|
fallbackSelectors: []
|
|
3965
4096
|
});
|
|
3966
|
-
if (aliasMap.size >=
|
|
4097
|
+
if (aliasMap.size >= MAX_SELECTOR_ALIASES) break;
|
|
3967
4098
|
}
|
|
3968
4099
|
return {
|
|
3969
4100
|
...insight,
|
|
3970
|
-
selectorAliases: [...aliasMap.values()].slice(0,
|
|
4101
|
+
selectorAliases: [...aliasMap.values()].slice(0, MAX_SELECTOR_ALIASES)
|
|
3971
4102
|
};
|
|
3972
4103
|
}
|
|
3973
4104
|
deriveAliasName(selector) {
|
|
@@ -3986,7 +4117,7 @@ var MemoryService = class {
|
|
|
3986
4117
|
}
|
|
3987
4118
|
mergeRecipe(recipe, step) {
|
|
3988
4119
|
if (recipe.find((existing) => existing.summary === step.summary && existing.selector === step.selector)) return recipe;
|
|
3989
|
-
return [...recipe, step].slice(-
|
|
4120
|
+
return [...recipe, step].slice(-MAX_RECIPE_STEPS);
|
|
3990
4121
|
}
|
|
3991
4122
|
};
|
|
3992
4123
|
//#endregion
|
|
@@ -4018,7 +4149,7 @@ var AgenticBrowserCore = class {
|
|
|
4018
4149
|
constructor(context, browserController) {
|
|
4019
4150
|
this.context = context;
|
|
4020
4151
|
this.sessions = new SessionManager(context, browserController);
|
|
4021
|
-
this.api = new ControlApi(this.sessions
|
|
4152
|
+
this.api = new ControlApi(this.sessions);
|
|
4022
4153
|
}
|
|
4023
4154
|
async startSession(input = { browser: "chrome" }) {
|
|
4024
4155
|
return await this.api.createSession(input);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentic-browser",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.1",
|
|
4
4
|
"description": "CLI and MCP server for AI agents to control Chrome via CDP",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|
|
@@ -66,9 +66,9 @@
|
|
|
66
66
|
"typecheck": "tsc"
|
|
67
67
|
},
|
|
68
68
|
"dependencies": {
|
|
69
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
69
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
70
70
|
"commander": "^14.0.3",
|
|
71
|
-
"ws": "^8.
|
|
71
|
+
"ws": "^8.20.0",
|
|
72
72
|
"zod": "^4.3.6"
|
|
73
73
|
},
|
|
74
74
|
"devDependencies": {
|
|
@@ -76,20 +76,20 @@
|
|
|
76
76
|
"@semantic-release/github": "^12.0.6",
|
|
77
77
|
"@semantic-release/npm": "^13.1.5",
|
|
78
78
|
"@semantic-release/release-notes-generator": "^14.1.0",
|
|
79
|
-
"@types/node": "^25.
|
|
79
|
+
"@types/node": "^25.6.0",
|
|
80
80
|
"@types/ws": "^8.18.1",
|
|
81
|
-
"oxfmt": "^0.
|
|
82
|
-
"oxlint": "^1.
|
|
83
|
-
"react": "^19.2.
|
|
84
|
-
"react-dom": "^19.2.
|
|
81
|
+
"oxfmt": "^0.44.0",
|
|
82
|
+
"oxlint": "^1.59.0",
|
|
83
|
+
"react": "^19.2.5",
|
|
84
|
+
"react-dom": "^19.2.5",
|
|
85
85
|
"semantic-release": "^25.0.3",
|
|
86
|
-
"tsdown": "^0.21.
|
|
87
|
-
"typescript": "^
|
|
88
|
-
"vitest": "^4.
|
|
86
|
+
"tsdown": "^0.21.7",
|
|
87
|
+
"typescript": "^6.0.2",
|
|
88
|
+
"vitest": "^4.1.4",
|
|
89
89
|
"vocs": "1.4.1"
|
|
90
90
|
},
|
|
91
91
|
"engines": {
|
|
92
|
-
"node": ">=
|
|
92
|
+
"node": ">=22"
|
|
93
93
|
},
|
|
94
|
-
"packageManager": "pnpm@10.
|
|
94
|
+
"packageManager": "pnpm@10.33.0"
|
|
95
95
|
}
|