agentic-browser 2.6.0 → 2.6.2
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 +25 -19
- package/README.md +1 -1
- package/dist/cli/index.mjs +38 -39
- package/dist/index.d.mts +20 -33
- package/dist/index.mjs +1 -2
- package/dist/mcp/index.d.mts +1 -4
- package/dist/mcp/index.mjs +47 -18
- package/dist/{runtime-BzdbtFF4.mjs → runtime-Bo7FmRYk.mjs} +359 -116
- package/dist/{setup-DUAjdbQ3.mjs → setup-DwFaZOPf.mjs} +13 -6
- package/package.json +20 -18
package/AGENTS.md
CHANGED
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
## Quick Reference
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
6
|
+
pnpm build # tsdown (~20ms)
|
|
7
|
+
pnpm typecheck # tsc --noEmit
|
|
8
|
+
pnpm lint # oxlint
|
|
9
|
+
pnpm lint:fix # oxlint --fix
|
|
10
|
+
pnpm format # oxfmt --write
|
|
11
|
+
pnpm test # vitest run
|
|
12
|
+
pnpm test:watch # vitest
|
|
13
|
+
pnpm docs:dev # vocs dev server
|
|
14
14
|
```
|
|
15
15
|
|
|
16
16
|
## Architecture
|
|
@@ -29,7 +29,7 @@ src/
|
|
|
29
29
|
commands/agent.ts — Stateful agent commands (auto-restart, retry, session persistence)
|
|
30
30
|
commands/*.ts — Low-level CLI command handlers
|
|
31
31
|
mcp/
|
|
32
|
-
index.ts — MCP server (stdio transport,
|
|
32
|
+
index.ts — MCP server (stdio transport, tools wrapping AgenticBrowserCore)
|
|
33
33
|
session/
|
|
34
34
|
browser-controller.ts — BrowserController interface + ChromeCdpBrowserController (CDP WebSocket)
|
|
35
35
|
session-manager.ts — Orchestrates sessions, commands, memory recording
|
|
@@ -68,7 +68,7 @@ AgenticBrowserCore → ControlApi → SessionManager → BrowserController (CDP)
|
|
|
68
68
|
|
|
69
69
|
- **ESM-only**: `"type": "module"`, use `.js` extensions in all TypeScript imports
|
|
70
70
|
- **Zod v4**: `import { z } from "zod"` — `z.record()` requires key+value args
|
|
71
|
-
- **Commander.js
|
|
71
|
+
- **Commander.js v15**: colon-namespaced commands (`session:start`, `memory:search`)
|
|
72
72
|
- **CLI output**: exactly one JSON line to `stdout`, errors to `stderr`
|
|
73
73
|
- **Types**: interfaces for public contracts, type aliases for unions/inferred
|
|
74
74
|
- **No console.log in MCP server**: use `process.stderr.write()` for debug output
|
|
@@ -111,21 +111,27 @@ AgenticBrowserCore → ControlApi → SessionManager → BrowserController (CDP)
|
|
|
111
111
|
- `AGENTIC_BROWSER_DIR` — base dir for sessions/memory/events (default: `~/.agentic-browser`)
|
|
112
112
|
- `AGENTIC_BROWSER_CHROME_EXECUTABLE_PATH` — explicit Chrome path (auto-discovered if not set)
|
|
113
113
|
- `AGENTIC_BROWSER_CDP_URL` — connect to an already-running Chrome via CDP (e.g. `http://127.0.0.1:9222`)
|
|
114
|
+
- `AGENTIC_BROWSER_ALLOW_FILE_URLS` — allow `file:` URLs in navigate (`true` or `1`); default is http(s) and about:blank only
|
|
114
115
|
- `AGENTIC_BROWSER_USER_PROFILE` — use real Chrome profile (`default`, `true`, or absolute path)
|
|
116
|
+
- `AGENTIC_BROWSER_CHROME_PATH` — alias of `AGENTIC_BROWSER_CHROME_EXECUTABLE_PATH`
|
|
117
|
+
- `AGENTIC_BROWSER_HEADLESS` — `true` or `1` to launch Chrome headless
|
|
118
|
+
- `AGENTIC_BROWSER_USER_AGENT` — override the browser user agent
|
|
115
119
|
|
|
116
120
|
## MCP Server
|
|
117
121
|
|
|
118
122
|
Subcommand: `agentic-browser mcp` (stdio transport). Setup: `agentic-browser setup`. Tools:
|
|
119
123
|
|
|
120
|
-
| Tool
|
|
121
|
-
|
|
|
122
|
-
| `browser_start_session`
|
|
123
|
-
| `browser_navigate`
|
|
124
|
-
| `browser_interact`
|
|
125
|
-
| `browser_get_content`
|
|
126
|
-
| `browser_get_elements`
|
|
127
|
-
| `browser_search_memory`
|
|
128
|
-
| `browser_stop_session`
|
|
124
|
+
| Tool | Purpose |
|
|
125
|
+
| ------------------------- | --------------------------------------------------------------------------------------------------------- |
|
|
126
|
+
| `browser_start_session` | Start Chrome, return sessionId |
|
|
127
|
+
| `browser_navigate` | Navigate to URL |
|
|
128
|
+
| `browser_interact` | click / type / press / waitFor / scroll / hover / select / toggle / goBack / goForward / refresh / dialog |
|
|
129
|
+
| `browser_get_content` | Get page title / text / html |
|
|
130
|
+
| `browser_get_elements` | Discover interactive elements |
|
|
131
|
+
| `browser_search_memory` | Search task memory |
|
|
132
|
+
| `browser_stop_session` | Stop Chrome session |
|
|
133
|
+
| `browser_dismiss_cookies` | Dismiss cookie or consent banner |
|
|
134
|
+
| `browser_screenshot` | Screenshot as base64 (jpeg or png, optional full page) |
|
|
129
135
|
|
|
130
136
|
## For Browser Automation Tasks
|
|
131
137
|
|
package/README.md
CHANGED
package/dist/cli/index.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { r as createCliRuntime } from "../runtime-
|
|
2
|
+
import { a as isConnectionError, o as ensurePrivateDir, r as createCliRuntime, s as writePrivateFileSync } from "../runtime-Bo7FmRYk.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
|
-
|
|
7
|
+
// src/cli/commands/agent.ts
|
|
8
8
|
const STATE_FILE_NAME = "agent-state.json";
|
|
9
9
|
function stateFilePath(runtime) {
|
|
10
10
|
return path.join(runtime.context.config.dataDir, STATE_FILE_NAME);
|
|
@@ -20,8 +20,8 @@ function loadState(runtime) {
|
|
|
20
20
|
}
|
|
21
21
|
function saveState(runtime, state) {
|
|
22
22
|
const dir = path.dirname(stateFilePath(runtime));
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
ensurePrivateDir(dir);
|
|
24
|
+
writePrivateFileSync(stateFilePath(runtime), JSON.stringify(state, null, 2));
|
|
25
25
|
}
|
|
26
26
|
function requireSessionId(runtime) {
|
|
27
27
|
const state = loadState(runtime);
|
|
@@ -63,6 +63,12 @@ async function agentStop(runtime) {
|
|
|
63
63
|
sessionId
|
|
64
64
|
};
|
|
65
65
|
}
|
|
66
|
+
/** Only connection-level failures justify a restart + re-run. */
|
|
67
|
+
function isRetryableFailure(message) {
|
|
68
|
+
if (isConnectionError(message)) return true;
|
|
69
|
+
const lower = message.toLowerCase();
|
|
70
|
+
return lower.includes("session") && (lower.includes("dead") || lower.includes("terminated"));
|
|
71
|
+
}
|
|
66
72
|
async function executeAgentCommand(runtime, input) {
|
|
67
73
|
const sessionId = requireSessionId(runtime);
|
|
68
74
|
await ensureReady(runtime, sessionId);
|
|
@@ -71,16 +77,24 @@ async function executeAgentCommand(runtime, input) {
|
|
|
71
77
|
type: input.type,
|
|
72
78
|
payload: input.payload
|
|
73
79
|
});
|
|
74
|
-
|
|
75
|
-
const first = await attempt();
|
|
76
|
-
if (first.resultStatus === "failed") throw new Error(first.resultMessage ?? "Command failed");
|
|
77
|
-
return first;
|
|
78
|
-
} catch {
|
|
80
|
+
const retryAfterRestart = async () => {
|
|
79
81
|
await runtime.api.restartSession(sessionId);
|
|
80
82
|
const second = await attempt();
|
|
81
83
|
if (second.resultStatus === "failed") throw new Error(second.resultMessage ?? "Command failed after retry");
|
|
82
84
|
return second;
|
|
85
|
+
};
|
|
86
|
+
const noRetry = input.type === "restart" || input.type === "terminate";
|
|
87
|
+
let first;
|
|
88
|
+
try {
|
|
89
|
+
first = await attempt();
|
|
90
|
+
} catch (error) {
|
|
91
|
+
if (noRetry || !isRetryableFailure(error.message)) throw error;
|
|
92
|
+
return await retryAfterRestart();
|
|
83
93
|
}
|
|
94
|
+
if (first.resultStatus !== "failed") return first;
|
|
95
|
+
const message = first.resultMessage ?? "Command failed";
|
|
96
|
+
if (noRetry || !isRetryableFailure(message)) throw new Error(message);
|
|
97
|
+
return await retryAfterRestart();
|
|
84
98
|
}
|
|
85
99
|
async function agentNavigate(runtime, input) {
|
|
86
100
|
const result = await executeAgentCommand(runtime, {
|
|
@@ -184,16 +198,14 @@ async function agentCleanup(runtime, input) {
|
|
|
184
198
|
...runtime.api.cleanupSessions(input)
|
|
185
199
|
};
|
|
186
200
|
}
|
|
187
|
-
|
|
188
|
-
//#region src/cli/output/result-formatter.ts
|
|
201
|
+
// src/cli/output/result-formatter.ts
|
|
189
202
|
function formatResult(resultStatus, message) {
|
|
190
203
|
return {
|
|
191
204
|
resultStatus,
|
|
192
205
|
message
|
|
193
206
|
};
|
|
194
207
|
}
|
|
195
|
-
|
|
196
|
-
//#region src/cli/commands/session-start.ts
|
|
208
|
+
// src/cli/commands/session-start.ts
|
|
197
209
|
async function runSessionStart(runtime, input) {
|
|
198
210
|
const session = await runtime.api.createSession(input);
|
|
199
211
|
return {
|
|
@@ -201,29 +213,24 @@ async function runSessionStart(runtime, input) {
|
|
|
201
213
|
sessionId: session.sessionId
|
|
202
214
|
};
|
|
203
215
|
}
|
|
204
|
-
|
|
205
|
-
//#region src/cli/commands/session-status.ts
|
|
216
|
+
// src/cli/commands/session-status.ts
|
|
206
217
|
async function runSessionStatus(runtime, input) {
|
|
207
218
|
return runtime.api.getSession(input.sessionId);
|
|
208
219
|
}
|
|
209
|
-
|
|
210
|
-
//#region src/cli/commands/session-stop.ts
|
|
220
|
+
// src/cli/commands/session-stop.ts
|
|
211
221
|
async function runSessionStop(runtime, input) {
|
|
212
222
|
await runtime.api.terminateSession(input.sessionId);
|
|
213
223
|
return { terminated: true };
|
|
214
224
|
}
|
|
215
|
-
|
|
216
|
-
//#region src/cli/commands/session-cleanup.ts
|
|
225
|
+
// src/cli/commands/session-cleanup.ts
|
|
217
226
|
async function runSessionCleanup(runtime, input) {
|
|
218
227
|
return runtime.api.cleanupSessions(input);
|
|
219
228
|
}
|
|
220
|
-
|
|
221
|
-
//#region src/cli/commands/session-restart.ts
|
|
229
|
+
// src/cli/commands/session-restart.ts
|
|
222
230
|
async function runSessionRestart(runtime, input) {
|
|
223
231
|
return await runtime.api.restartSession(input.sessionId);
|
|
224
232
|
}
|
|
225
|
-
|
|
226
|
-
//#region src/cli/commands/session-auth.ts
|
|
233
|
+
// src/cli/commands/session-auth.ts
|
|
227
234
|
async function runSessionAuth(runtime, input) {
|
|
228
235
|
const token = runtime.api.rotateSessionToken(input.sessionId);
|
|
229
236
|
return {
|
|
@@ -231,8 +238,7 @@ async function runSessionAuth(runtime, input) {
|
|
|
231
238
|
valid: runtime.context.tokenService.validate(input.sessionId, token)
|
|
232
239
|
};
|
|
233
240
|
}
|
|
234
|
-
|
|
235
|
-
//#region src/cli/commands/command-run.ts
|
|
241
|
+
// src/cli/commands/command-run.ts
|
|
236
242
|
async function runCommand(runtime, input) {
|
|
237
243
|
if (!input.sessionId) throw new Error("No active session. Start or restart a session first.");
|
|
238
244
|
try {
|
|
@@ -245,8 +251,7 @@ async function runCommand(runtime, input) {
|
|
|
245
251
|
throw new Error(`Command rejected: ${error.message}`, { cause: error });
|
|
246
252
|
}
|
|
247
253
|
}
|
|
248
|
-
|
|
249
|
-
//#region src/cli/commands/page-content.ts
|
|
254
|
+
// src/cli/commands/page-content.ts
|
|
250
255
|
async function runPageContent(runtime, input) {
|
|
251
256
|
return await runtime.api.getContent(input.sessionId, {
|
|
252
257
|
mode: input.mode,
|
|
@@ -254,31 +259,26 @@ async function runPageContent(runtime, input) {
|
|
|
254
259
|
maxChars: input.maxChars
|
|
255
260
|
});
|
|
256
261
|
}
|
|
257
|
-
|
|
258
|
-
//#region src/cli/commands/memory-search.ts
|
|
262
|
+
// src/cli/commands/memory-search.ts
|
|
259
263
|
async function runMemorySearch(runtime, input) {
|
|
260
264
|
if (!input.taskIntent || !input.taskIntent.trim()) throw new Error("taskIntent is required");
|
|
261
265
|
return runtime.api.searchMemory(input);
|
|
262
266
|
}
|
|
263
|
-
|
|
264
|
-
//#region src/cli/commands/memory-inspect.ts
|
|
267
|
+
// src/cli/commands/memory-inspect.ts
|
|
265
268
|
async function runMemoryInspect(runtime, input) {
|
|
266
269
|
if (!input.insightId || !input.insightId.trim()) throw new Error("insightId is required");
|
|
267
270
|
return runtime.api.inspectMemory(input.insightId);
|
|
268
271
|
}
|
|
269
|
-
|
|
270
|
-
//#region src/cli/commands/memory-verify.ts
|
|
272
|
+
// src/cli/commands/memory-verify.ts
|
|
271
273
|
async function runMemoryVerify(runtime, input) {
|
|
272
274
|
if (!input.insightId || !input.insightId.trim()) throw new Error("insightId is required");
|
|
273
275
|
return runtime.api.verifyMemory(input.insightId);
|
|
274
276
|
}
|
|
275
|
-
|
|
276
|
-
//#region src/cli/commands/memory-stats.ts
|
|
277
|
+
// src/cli/commands/memory-stats.ts
|
|
277
278
|
async function runMemoryStats(runtime) {
|
|
278
279
|
return runtime.api.memoryStats();
|
|
279
280
|
}
|
|
280
|
-
|
|
281
|
-
//#region src/cli/index.ts
|
|
281
|
+
// src/cli/index.ts
|
|
282
282
|
const collect = (value, previous = []) => [...previous, value];
|
|
283
283
|
async function main() {
|
|
284
284
|
const runtime = createCliRuntime();
|
|
@@ -513,7 +513,7 @@ async function main() {
|
|
|
513
513
|
await startMcpServer();
|
|
514
514
|
});
|
|
515
515
|
program.command("setup").description("Configure agentic-browser as MCP server for your AI tool").action(async () => {
|
|
516
|
-
const { runSetup } = await import("../setup-
|
|
516
|
+
const { runSetup } = await import("../setup-DwFaZOPf.mjs");
|
|
517
517
|
await runSetup();
|
|
518
518
|
});
|
|
519
519
|
await program.parseAsync(process.argv);
|
|
@@ -526,5 +526,4 @@ main().then((keepAlive) => {
|
|
|
526
526
|
console.error(JSON.stringify({ error: message }));
|
|
527
527
|
process.exit(1);
|
|
528
528
|
});
|
|
529
|
-
//#endregion
|
|
530
529
|
export {};
|
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
|
|
2
|
-
import
|
|
2
|
+
import "ws";
|
|
3
3
|
import { z } from "zod";
|
|
4
|
-
//#region src/session/browser-controller.d.ts
|
|
5
4
|
type InteractAction = "click" | "type" | "press" | "waitFor" | "evaluate" | "scroll" | "hover" | "select" | "toggle" | "goBack" | "goForward" | "refresh" | "dialog";
|
|
6
5
|
interface InteractPayload {
|
|
7
6
|
action: InteractAction;
|
|
@@ -100,8 +99,6 @@ interface BrowserController {
|
|
|
100
99
|
closeConnection?(targetWsUrl: string): void;
|
|
101
100
|
dispose?(): void;
|
|
102
101
|
}
|
|
103
|
-
//#endregion
|
|
104
|
-
//#region src/memory/memory-schemas.d.ts
|
|
105
102
|
declare const InsightFreshnessSchema: z.ZodEnum<{
|
|
106
103
|
fresh: "fresh";
|
|
107
104
|
stale: "stale";
|
|
@@ -233,8 +230,6 @@ interface MemorySearchResult {
|
|
|
233
230
|
score: number;
|
|
234
231
|
siteProfile?: SiteProfileSummary;
|
|
235
232
|
}
|
|
236
|
-
//#endregion
|
|
237
|
-
//#region src/lib/domain-schemas.d.ts
|
|
238
233
|
declare const SessionStatusSchema: z.ZodEnum<{
|
|
239
234
|
disconnected: "disconnected";
|
|
240
235
|
failed: "failed";
|
|
@@ -302,8 +297,6 @@ type CommandType = z.infer<typeof CommandTypeSchema>;
|
|
|
302
297
|
type Session = z.infer<typeof SessionSchema>;
|
|
303
298
|
type Command = z.infer<typeof CommandSchema>;
|
|
304
299
|
type SessionEvent = z.infer<typeof SessionEventSchema>;
|
|
305
|
-
//#endregion
|
|
306
|
-
//#region src/lib/config.d.ts
|
|
307
300
|
interface AppConfig {
|
|
308
301
|
dataDir: string;
|
|
309
302
|
browserExecutablePath?: string;
|
|
@@ -311,10 +304,9 @@ interface AppConfig {
|
|
|
311
304
|
userProfileDir?: string;
|
|
312
305
|
headless?: boolean;
|
|
313
306
|
userAgent?: string;
|
|
307
|
+
allowFileUrls: boolean;
|
|
314
308
|
}
|
|
315
309
|
declare function loadConfig(env?: NodeJS.ProcessEnv): AppConfig;
|
|
316
|
-
//#endregion
|
|
317
|
-
//#region src/observability/logger.d.ts
|
|
318
310
|
interface LogContext {
|
|
319
311
|
[key: string]: unknown;
|
|
320
312
|
}
|
|
@@ -326,8 +318,6 @@ declare class Logger {
|
|
|
326
318
|
warning(message: string, context?: LogContext): void;
|
|
327
319
|
error(message: string, context?: LogContext): void;
|
|
328
320
|
}
|
|
329
|
-
//#endregion
|
|
330
|
-
//#region src/observability/event-store.d.ts
|
|
331
321
|
declare class EventStore {
|
|
332
322
|
private readonly events;
|
|
333
323
|
private readonly filePath;
|
|
@@ -349,8 +339,6 @@ declare class EventStore {
|
|
|
349
339
|
private flushAsync;
|
|
350
340
|
private readonly flushSync;
|
|
351
341
|
}
|
|
352
|
-
//#endregion
|
|
353
|
-
//#region src/auth/session-token.d.ts
|
|
354
342
|
declare class SessionTokenService {
|
|
355
343
|
private readonly tokens;
|
|
356
344
|
issue(sessionId: string): string;
|
|
@@ -359,8 +347,6 @@ declare class SessionTokenService {
|
|
|
359
347
|
get(sessionId: string): string | undefined;
|
|
360
348
|
seed(sessionId: string, token: string): void;
|
|
361
349
|
}
|
|
362
|
-
//#endregion
|
|
363
|
-
//#region src/memory/memory-service.d.ts
|
|
364
350
|
interface MemorySearchInput {
|
|
365
351
|
taskIntent: string;
|
|
366
352
|
siteDomain?: string;
|
|
@@ -385,6 +371,8 @@ declare class MemoryService {
|
|
|
385
371
|
constructor(baseDir: string);
|
|
386
372
|
/** Force an immediate synchronous flush of pending writes. */
|
|
387
373
|
flushSync(): void;
|
|
374
|
+
/** Flush pending writes and release the stores' process exit hooks. */
|
|
375
|
+
dispose(): void;
|
|
388
376
|
search(input: MemorySearchInput): MemorySearchResult[];
|
|
389
377
|
/** Invalidate search cache when data changes. */
|
|
390
378
|
private invalidateSearchCache;
|
|
@@ -400,8 +388,8 @@ declare class MemoryService {
|
|
|
400
388
|
}>;
|
|
401
389
|
};
|
|
402
390
|
verify(insightId: string): TaskInsight;
|
|
403
|
-
recordSuccess(
|
|
404
|
-
recordFailure(
|
|
391
|
+
recordSuccess(rawInput: RecordExecutionInput): TaskInsight;
|
|
392
|
+
recordFailure(rawInput: RecordExecutionInput, errorMessage: string): TaskInsight | undefined;
|
|
405
393
|
/** Update site profile from page content (call after getContent with mode="summary"). */
|
|
406
394
|
updateProfileFromContent(domain: string, pathPattern: string, structuredContent: {
|
|
407
395
|
headings?: string[];
|
|
@@ -421,13 +409,13 @@ declare class MemoryService {
|
|
|
421
409
|
private findBestExactMatch;
|
|
422
410
|
private scoreExactMatch;
|
|
423
411
|
private sameFirstPathSegment;
|
|
412
|
+
/** Strip query strings and fragments from every URL-bearing field before it is persisted. */
|
|
413
|
+
private sanitizeInput;
|
|
424
414
|
private createEvidence;
|
|
425
415
|
private maybeGenerateAliases;
|
|
426
416
|
private deriveAliasName;
|
|
427
417
|
private mergeRecipe;
|
|
428
418
|
}
|
|
429
|
-
//#endregion
|
|
430
|
-
//#region src/cli/app.d.ts
|
|
431
419
|
interface AppContext {
|
|
432
420
|
config: ReturnType<typeof loadConfig>;
|
|
433
421
|
logger: Logger;
|
|
@@ -435,8 +423,6 @@ interface AppContext {
|
|
|
435
423
|
tokenService: SessionTokenService;
|
|
436
424
|
memoryService: MemoryService;
|
|
437
425
|
}
|
|
438
|
-
//#endregion
|
|
439
|
-
//#region src/session/session-store.d.ts
|
|
440
426
|
interface StoredSessionRecord {
|
|
441
427
|
session: Session;
|
|
442
428
|
cdpUrl: string;
|
|
@@ -444,8 +430,6 @@ interface StoredSessionRecord {
|
|
|
444
430
|
pid: number;
|
|
445
431
|
lastUrl?: string;
|
|
446
432
|
}
|
|
447
|
-
//#endregion
|
|
448
|
-
//#region src/session/session-manager.d.ts
|
|
449
433
|
interface CreateSessionInput {
|
|
450
434
|
browser: "chrome";
|
|
451
435
|
}
|
|
@@ -584,8 +568,6 @@ declare class SessionManager {
|
|
|
584
568
|
private buildMemoryContext;
|
|
585
569
|
private parseUrl;
|
|
586
570
|
}
|
|
587
|
-
//#endregion
|
|
588
|
-
//#region src/transport/control-api.d.ts
|
|
589
571
|
declare class ControlApi {
|
|
590
572
|
private readonly sessions;
|
|
591
573
|
constructor(sessions: SessionManager);
|
|
@@ -746,8 +728,6 @@ declare class ControlApi {
|
|
|
746
728
|
dryRun?: boolean;
|
|
747
729
|
}): CleanupResult;
|
|
748
730
|
}
|
|
749
|
-
//#endregion
|
|
750
|
-
//#region src/cli/runtime.d.ts
|
|
751
731
|
interface AgenticBrowserCoreOptions {
|
|
752
732
|
env?: NodeJS.ProcessEnv;
|
|
753
733
|
browserController?: BrowserController;
|
|
@@ -758,11 +738,19 @@ interface ExecuteCommandInput {
|
|
|
758
738
|
type: CommandType;
|
|
759
739
|
payload: Record<string, unknown>;
|
|
760
740
|
}
|
|
761
|
-
declare class AgenticBrowserCore {
|
|
741
|
+
export declare class AgenticBrowserCore {
|
|
762
742
|
readonly context: AppContext;
|
|
763
743
|
readonly sessions: SessionManager;
|
|
764
744
|
readonly api: ControlApi;
|
|
745
|
+
private readonly browserController;
|
|
746
|
+
private disposed;
|
|
765
747
|
constructor(context: AppContext, browserController: BrowserController);
|
|
748
|
+
/**
|
|
749
|
+
* Release process-level resources (event store and memory store exit handlers,
|
|
750
|
+
* controller timers). Flushes pending memory writes.
|
|
751
|
+
* Does not terminate browser sessions. Idempotent.
|
|
752
|
+
*/
|
|
753
|
+
dispose(): Promise<void>;
|
|
766
754
|
startSession(input?: {
|
|
767
755
|
browser: "chrome";
|
|
768
756
|
}): Promise<{
|
|
@@ -909,7 +897,6 @@ declare class AgenticBrowserCore {
|
|
|
909
897
|
}>;
|
|
910
898
|
};
|
|
911
899
|
}
|
|
912
|
-
declare function createAgenticBrowserCore(options?: AgenticBrowserCoreOptions): AgenticBrowserCore;
|
|
913
|
-
declare function createMockAgenticBrowserCore(env: NodeJS.ProcessEnv): AgenticBrowserCore;
|
|
914
|
-
|
|
915
|
-
export { AgenticBrowserCore, type AgenticBrowserCoreOptions, type DismissCookieBannerResult, type ElementAction, type ErrorCode, type ExecuteCommandInput, type InteractiveElement, type InteractiveElementRole, type InteractiveElementsOptions, type InteractiveElementsResult, type LaunchOptions, type ScreenshotOptions, type ScreenshotResult, createAgenticBrowserCore, createMockAgenticBrowserCore };
|
|
900
|
+
export declare function createAgenticBrowserCore(options?: AgenticBrowserCoreOptions): AgenticBrowserCore;
|
|
901
|
+
export declare function createMockAgenticBrowserCore(env: NodeJS.ProcessEnv): AgenticBrowserCore;
|
|
902
|
+
export type { AgenticBrowserCoreOptions, DismissCookieBannerResult, ElementAction, ErrorCode, ExecuteCommandInput, InteractiveElement, InteractiveElementRole, InteractiveElementsOptions, InteractiveElementsResult, LaunchOptions, ScreenshotOptions, ScreenshotResult };
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
export { AgenticBrowserCore, createAgenticBrowserCore, createMockAgenticBrowserCore };
|
|
2
|
+
export { t as AgenticBrowserCore, n as createAgenticBrowserCore, i as createMockAgenticBrowserCore } from "./runtime-Bo7FmRYk.mjs";
|
package/dist/mcp/index.d.mts
CHANGED
package/dist/mcp/index.mjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { n as createAgenticBrowserCore } from "../runtime-
|
|
2
|
+
import { n as createAgenticBrowserCore } from "../runtime-Bo7FmRYk.mjs";
|
|
3
3
|
import { readFileSync } from "node:fs";
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
8
8
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
9
|
-
|
|
9
|
+
// src/mcp/response-helpers.ts
|
|
10
10
|
function uniqueLines(content, maxLineLength = 160) {
|
|
11
11
|
const seen = /* @__PURE__ */ new Set();
|
|
12
12
|
const lines = [];
|
|
@@ -204,8 +204,7 @@ function compactMemoryResults(results) {
|
|
|
204
204
|
return compact;
|
|
205
205
|
}) };
|
|
206
206
|
}
|
|
207
|
-
|
|
208
|
-
//#region src/mcp/element-refs.ts
|
|
207
|
+
// src/mcp/element-refs.ts
|
|
209
208
|
var ElementRefRegistry = class {
|
|
210
209
|
bySession = /* @__PURE__ */ new Map();
|
|
211
210
|
/**
|
|
@@ -245,8 +244,41 @@ var ElementRefRegistry = class {
|
|
|
245
244
|
this.bySession.delete(sessionId);
|
|
246
245
|
}
|
|
247
246
|
};
|
|
248
|
-
|
|
249
|
-
|
|
247
|
+
// src/mcp/session-resolver.ts
|
|
248
|
+
/**
|
|
249
|
+
* Tracks the active session and auto-starts one on demand. Concurrent callers
|
|
250
|
+
* share a single in-flight start so only one session is launched.
|
|
251
|
+
*/
|
|
252
|
+
function createSessionResolver(start) {
|
|
253
|
+
let activeSessionId;
|
|
254
|
+
let pendingSession;
|
|
255
|
+
return {
|
|
256
|
+
async resolve(sessionId) {
|
|
257
|
+
if (sessionId) return sessionId;
|
|
258
|
+
if (activeSessionId) return activeSessionId;
|
|
259
|
+
if (pendingSession) return pendingSession;
|
|
260
|
+
const p = (async () => {
|
|
261
|
+
const session = await start();
|
|
262
|
+
activeSessionId = session.sessionId;
|
|
263
|
+
return session.sessionId;
|
|
264
|
+
})();
|
|
265
|
+
pendingSession = p;
|
|
266
|
+
try {
|
|
267
|
+
return await p;
|
|
268
|
+
} finally {
|
|
269
|
+
pendingSession = void 0;
|
|
270
|
+
}
|
|
271
|
+
},
|
|
272
|
+
current: () => activeSessionId,
|
|
273
|
+
set(sessionId) {
|
|
274
|
+
activeSessionId = sessionId;
|
|
275
|
+
},
|
|
276
|
+
clear() {
|
|
277
|
+
activeSessionId = void 0;
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
// src/mcp/index.ts
|
|
250
282
|
function readPackageVersion() {
|
|
251
283
|
try {
|
|
252
284
|
const dir = dirname(fileURLToPath(import.meta.url));
|
|
@@ -271,7 +303,7 @@ function classifyError(message) {
|
|
|
271
303
|
return "UNKNOWN";
|
|
272
304
|
}
|
|
273
305
|
let core;
|
|
274
|
-
|
|
306
|
+
const sessionResolver = createSessionResolver(() => getCore().startSession());
|
|
275
307
|
const DEFAULT_MCP_MAX_CHARS = {
|
|
276
308
|
summary: void 0,
|
|
277
309
|
title: void 0,
|
|
@@ -313,10 +345,7 @@ async function snapshotElements(sessionId, opts = {}) {
|
|
|
313
345
|
* This means the LLM never has to call browser_start_session explicitly.
|
|
314
346
|
*/
|
|
315
347
|
async function resolveSession(sessionId) {
|
|
316
|
-
|
|
317
|
-
if (activeSessionId) return activeSessionId;
|
|
318
|
-
activeSessionId = (await getCore().startSession()).sessionId;
|
|
319
|
-
return activeSessionId;
|
|
348
|
+
return sessionResolver.resolve(sessionId);
|
|
320
349
|
}
|
|
321
350
|
const server = new McpServer({
|
|
322
351
|
name: "agentic-browser",
|
|
@@ -324,7 +353,7 @@ const server = new McpServer({
|
|
|
324
353
|
});
|
|
325
354
|
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 () => {
|
|
326
355
|
const session = await getCore().startSession();
|
|
327
|
-
|
|
356
|
+
sessionResolver.set(session.sessionId);
|
|
328
357
|
const { authTokenRef: _, ...compactSession } = session;
|
|
329
358
|
return { content: [{
|
|
330
359
|
type: "text",
|
|
@@ -536,7 +565,7 @@ server.tool("browser_screenshot", "Capture a screenshot of the current page. Ret
|
|
|
536
565
|
}] };
|
|
537
566
|
});
|
|
538
567
|
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 }) => {
|
|
539
|
-
const sid = sessionId ??
|
|
568
|
+
const sid = sessionId ?? sessionResolver.current();
|
|
540
569
|
if (!sid) return { content: [{
|
|
541
570
|
type: "text",
|
|
542
571
|
text: JSON.stringify({
|
|
@@ -546,7 +575,7 @@ server.tool("browser_stop_session", "Stop the browser session and terminate Chro
|
|
|
546
575
|
}] };
|
|
547
576
|
await getCore().stopSession(sid);
|
|
548
577
|
refs.clear(sid);
|
|
549
|
-
if (
|
|
578
|
+
if (sessionResolver.current() === sid) sessionResolver.clear();
|
|
550
579
|
return { content: [{
|
|
551
580
|
type: "text",
|
|
552
581
|
text: JSON.stringify({
|
|
@@ -558,11 +587,12 @@ server.tool("browser_stop_session", "Stop the browser session and terminate Chro
|
|
|
558
587
|
async function main() {
|
|
559
588
|
const transport = new StdioServerTransport();
|
|
560
589
|
transport.onclose = async () => {
|
|
561
|
-
|
|
590
|
+
const activeId = sessionResolver.current();
|
|
591
|
+
if (activeId) {
|
|
562
592
|
try {
|
|
563
|
-
await getCore().stopSession(
|
|
593
|
+
await getCore().stopSession(activeId);
|
|
564
594
|
} catch {}
|
|
565
|
-
|
|
595
|
+
sessionResolver.clear();
|
|
566
596
|
}
|
|
567
597
|
try {
|
|
568
598
|
getCore().context.memoryService.flushSync();
|
|
@@ -573,5 +603,4 @@ async function main() {
|
|
|
573
603
|
};
|
|
574
604
|
await server.connect(transport);
|
|
575
605
|
}
|
|
576
|
-
//#endregion
|
|
577
606
|
export { main };
|