agentic-browser 1.0.3 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +6 -2
- package/README.md +85 -0
- package/dist/cli/index.mjs +7 -3
- package/dist/index.mjs +1 -1
- package/dist/mcp/index.mjs +1 -1
- package/dist/{runtime-4pX1c4Cs.mjs → runtime-D6awVhGy.mjs} +50 -4
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -59,8 +59,10 @@ AgenticBrowserCore → ControlApi → SessionManager → BrowserController (CDP)
|
|
|
59
59
|
```
|
|
60
60
|
|
|
61
61
|
1. `createAgenticBrowserCore()` builds AppContext + ChromeCdpBrowserController
|
|
62
|
-
2.
|
|
63
|
-
3.
|
|
62
|
+
2. `createSession` either launches a new Chrome (`browser.launch()`) or connects to existing one (`browser.connect(cdpUrl)`) based on config
|
|
63
|
+
3. Commands execute via CDP `Runtime.evaluate` on the browser page
|
|
64
|
+
4. Results are recorded as evidence, indexed per-domain for memory search
|
|
65
|
+
5. Connected sessions (pid=0) skip `process.kill` on terminate — the user's browser stays open
|
|
64
66
|
|
|
65
67
|
## Code Conventions
|
|
66
68
|
|
|
@@ -108,6 +110,8 @@ AgenticBrowserCore → ControlApi → SessionManager → BrowserController (CDP)
|
|
|
108
110
|
|
|
109
111
|
- `AGENTIC_BROWSER_LOG_DIR` — base dir for sessions/memory/events (default: `.agentic-browser`)
|
|
110
112
|
- `AGENTIC_BROWSER_CHROME_EXECUTABLE_PATH` — explicit Chrome path (auto-discovered if not set)
|
|
113
|
+
- `AGENTIC_BROWSER_CDP_URL` — connect to an already-running Chrome via CDP (e.g. `http://127.0.0.1:9222`)
|
|
114
|
+
- `AGENTIC_BROWSER_USER_PROFILE` — use real Chrome profile (`default`, `true`, or absolute path)
|
|
111
115
|
|
|
112
116
|
## MCP Server
|
|
113
117
|
|
package/README.md
CHANGED
|
@@ -37,12 +37,74 @@ npm run lint
|
|
|
37
37
|
npm test
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
+
## Use Your Existing Chrome
|
|
41
|
+
|
|
42
|
+
By default, agentic-browser launches a fresh Chrome with a throwaway profile. If you want to use your logged-in sessions, cookies, or extensions, there are two ways:
|
|
43
|
+
|
|
44
|
+
### Option 1: Control your running Chrome (recommended)
|
|
45
|
+
|
|
46
|
+
This lets agentic-browser take over your already-open Chrome — no need to quit it, no need to log in again.
|
|
47
|
+
|
|
48
|
+
**Step 1.** Quit Chrome, then relaunch it with remote debugging enabled:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# macOS
|
|
52
|
+
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222
|
|
53
|
+
|
|
54
|
+
# Linux
|
|
55
|
+
google-chrome --remote-debugging-port=9222
|
|
56
|
+
|
|
57
|
+
# Windows
|
|
58
|
+
chrome.exe --remote-debugging-port=9222
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Chrome opens normally with all your tabs, extensions, and sessions intact.
|
|
62
|
+
|
|
63
|
+
**Step 2.** Connect agentic-browser:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
agentic-browser agent start --cdp-url http://127.0.0.1:9222
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Stopping the session will **not** close your Chrome.
|
|
70
|
+
|
|
71
|
+
### Option 2: Launch a new Chrome with your profile
|
|
72
|
+
|
|
73
|
+
**Important:** You must quit Chrome first. Chrome locks its profile directory — if Chrome is already running, this command will fail.
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# Quit Chrome, then:
|
|
77
|
+
agentic-browser agent start --user-profile default
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
This launches a new Chrome window using your default profile. You can also pass a custom profile path:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
agentic-browser agent start --user-profile /path/to/chrome/profile
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Default profile locations per platform:
|
|
87
|
+
- **macOS:** `~/Library/Application Support/Google/Chrome`
|
|
88
|
+
- **Linux:** `~/.config/google-chrome`
|
|
89
|
+
- **Windows:** `%LOCALAPPDATA%\Google\Chrome\User Data`
|
|
90
|
+
|
|
91
|
+
### Environment variables
|
|
92
|
+
|
|
93
|
+
These options can also be set via environment variables (CLI flags take precedence):
|
|
94
|
+
|
|
95
|
+
| Variable | Example | Description |
|
|
96
|
+
| ------------------------------ | ------------------------------ | ------------------------------- |
|
|
97
|
+
| `AGENTIC_BROWSER_CDP_URL` | `http://127.0.0.1:9222` | Connect to a running Chrome |
|
|
98
|
+
| `AGENTIC_BROWSER_USER_PROFILE` | `default` or an absolute path | Launch with a real profile |
|
|
99
|
+
|
|
40
100
|
## Agent Commands (Recommended for LLMs)
|
|
41
101
|
|
|
42
102
|
The `agent` subcommand manages session state, auto-restarts on disconnect, generates command IDs, and retries failed commands automatically:
|
|
43
103
|
|
|
44
104
|
```bash
|
|
45
105
|
agentic-browser agent start
|
|
106
|
+
agentic-browser agent start --cdp-url http://127.0.0.1:9222
|
|
107
|
+
agentic-browser agent start --user-profile default
|
|
46
108
|
agentic-browser agent status
|
|
47
109
|
agentic-browser agent run navigate '{"url":"https://example.com"}'
|
|
48
110
|
agentic-browser agent run interact '{"action":"click","selector":"#login"}'
|
|
@@ -120,6 +182,8 @@ For direct control without session state management:
|
|
|
120
182
|
|
|
121
183
|
```bash
|
|
122
184
|
agentic-browser session:start
|
|
185
|
+
agentic-browser session:start --cdp-url http://127.0.0.1:9222
|
|
186
|
+
agentic-browser session:start --user-profile default
|
|
123
187
|
```
|
|
124
188
|
|
|
125
189
|
### 2. Read Session Status
|
|
@@ -220,6 +284,27 @@ const memory = core.searchMemory({
|
|
|
220
284
|
await core.stopSession(session.sessionId);
|
|
221
285
|
```
|
|
222
286
|
|
|
287
|
+
### Connect to your running Chrome
|
|
288
|
+
|
|
289
|
+
```ts
|
|
290
|
+
// Chrome must be running with --remote-debugging-port=9222
|
|
291
|
+
const core = createAgenticBrowserCore({
|
|
292
|
+
env: { ...process.env, AGENTIC_BROWSER_CDP_URL: "http://127.0.0.1:9222" },
|
|
293
|
+
});
|
|
294
|
+
const session = await core.startSession();
|
|
295
|
+
// Stopping the session will NOT close your Chrome
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### Launch Chrome with your real profile
|
|
299
|
+
|
|
300
|
+
```ts
|
|
301
|
+
// Chrome must be closed first
|
|
302
|
+
const core = createAgenticBrowserCore({
|
|
303
|
+
env: { ...process.env, AGENTIC_BROWSER_USER_PROFILE: "default" },
|
|
304
|
+
});
|
|
305
|
+
const session = await core.startSession();
|
|
306
|
+
```
|
|
307
|
+
|
|
223
308
|
## Documentation
|
|
224
309
|
|
|
225
310
|
```bash
|
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-D6awVhGy.mjs";
|
|
3
3
|
import fs from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import crypto from "node:crypto";
|
|
@@ -243,7 +243,9 @@ async function main() {
|
|
|
243
243
|
const runtime = createCliRuntime();
|
|
244
244
|
const program = new Command();
|
|
245
245
|
program.name("agentic-browser").description("Agentic browser CLI");
|
|
246
|
-
program.command("session:start").action(async () => {
|
|
246
|
+
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").action(async (options) => {
|
|
247
|
+
if (options.cdpUrl) runtime.context.config.cdpUrl = options.cdpUrl;
|
|
248
|
+
if (options.userProfile) runtime.context.config.userProfileDir = options.userProfile === "true" || options.userProfile === "default" ? "default" : options.userProfile;
|
|
247
249
|
const result = await runSessionStart(runtime, { browser: "chrome" });
|
|
248
250
|
console.log(JSON.stringify(result));
|
|
249
251
|
});
|
|
@@ -308,7 +310,9 @@ async function main() {
|
|
|
308
310
|
console.log(JSON.stringify(result));
|
|
309
311
|
});
|
|
310
312
|
const agent = program.command("agent").description("Stateful agent wrapper with session persistence and auto-retry");
|
|
311
|
-
agent.command("start").action(async () => {
|
|
313
|
+
agent.command("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").action(async (options) => {
|
|
314
|
+
if (options.cdpUrl) runtime.context.config.cdpUrl = options.cdpUrl;
|
|
315
|
+
if (options.userProfile) runtime.context.config.userProfileDir = options.userProfile === "true" || options.userProfile === "default" ? "default" : options.userProfile;
|
|
312
316
|
const result = await agentStart(runtime);
|
|
313
317
|
console.log(JSON.stringify(result));
|
|
314
318
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
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-D6awVhGy.mjs";
|
|
3
3
|
|
|
4
4
|
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-D6awVhGy.mjs";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
5
5
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { spawn } from "node:child_process";
|
|
3
3
|
import fs from "node:fs";
|
|
4
4
|
import net from "node:net";
|
|
5
|
+
import os from "node:os";
|
|
5
6
|
import path from "node:path";
|
|
6
7
|
import WebSocket, { WebSocketServer } from "ws";
|
|
7
8
|
import { URL as URL$1, fileURLToPath } from "node:url";
|
|
@@ -157,6 +158,13 @@ async function getFreePort() {
|
|
|
157
158
|
});
|
|
158
159
|
});
|
|
159
160
|
}
|
|
161
|
+
function resolveDefaultProfileDir() {
|
|
162
|
+
const platform = os.platform();
|
|
163
|
+
const home = os.homedir();
|
|
164
|
+
if (platform === "darwin") return path.join(home, "Library", "Application Support", "Google", "Chrome");
|
|
165
|
+
if (platform === "win32") return path.join(process.env.LOCALAPPDATA ?? path.join(home, "AppData", "Local"), "Google", "Chrome", "User Data");
|
|
166
|
+
return path.join(home, ".config", "google-chrome");
|
|
167
|
+
}
|
|
160
168
|
var ChromeCdpBrowserController = class {
|
|
161
169
|
connections = /* @__PURE__ */ new Map();
|
|
162
170
|
constructor(baseDir, connectionFactory = CdpConnection.connect) {
|
|
@@ -191,6 +199,19 @@ var ChromeCdpBrowserController = class {
|
|
|
191
199
|
closeConnection(targetWsUrl) {
|
|
192
200
|
this.dropConnection(targetWsUrl);
|
|
193
201
|
}
|
|
202
|
+
async connect(cdpUrl) {
|
|
203
|
+
const parsed = new URL(cdpUrl);
|
|
204
|
+
const port = Number.parseInt(parsed.port, 10);
|
|
205
|
+
if (!port) throw new Error(`Invalid CDP URL: could not extract port from ${cdpUrl}`);
|
|
206
|
+
await waitForDebugger(port);
|
|
207
|
+
const targetWsUrl = await createTarget(cdpUrl);
|
|
208
|
+
await evaluateExpression(targetWsUrl, "window.location.href");
|
|
209
|
+
return {
|
|
210
|
+
pid: 0,
|
|
211
|
+
cdpUrl,
|
|
212
|
+
targetWsUrl
|
|
213
|
+
};
|
|
214
|
+
}
|
|
194
215
|
async ensureEnabled(targetWsUrl) {
|
|
195
216
|
const cached = this.connections.get(targetWsUrl);
|
|
196
217
|
if (!cached) return;
|
|
@@ -203,11 +224,16 @@ var ChromeCdpBrowserController = class {
|
|
|
203
224
|
cached.enabled.runtime = true;
|
|
204
225
|
}
|
|
205
226
|
}
|
|
206
|
-
async launch(sessionId, explicitPath) {
|
|
227
|
+
async launch(sessionId, explicitPath, userProfileDir) {
|
|
207
228
|
const executablePath = discoverChrome(explicitPath);
|
|
208
229
|
const extension = loadControlExtension();
|
|
209
|
-
|
|
230
|
+
let profileDir;
|
|
231
|
+
if (userProfileDir === "default") profileDir = resolveDefaultProfileDir();
|
|
232
|
+
else if (userProfileDir) profileDir = userProfileDir;
|
|
233
|
+
else profileDir = path.join(this.baseDir, "profiles", sessionId);
|
|
210
234
|
fs.mkdirSync(profileDir, { recursive: true });
|
|
235
|
+
const lockFile = path.join(profileDir, "SingletonLock");
|
|
236
|
+
if (fs.existsSync(lockFile)) throw new Error(`Chrome profile is already in use (lock file exists: ${lockFile}). Quit the running Chrome instance first, or use --cdp-url to connect to it instead.`);
|
|
211
237
|
const launchAttempts = [
|
|
212
238
|
{
|
|
213
239
|
withExtension: true,
|
|
@@ -640,6 +666,7 @@ var ChromeCdpBrowserController = class {
|
|
|
640
666
|
}
|
|
641
667
|
}
|
|
642
668
|
terminate(pid) {
|
|
669
|
+
if (pid === 0) return;
|
|
643
670
|
try {
|
|
644
671
|
process.kill(pid, "SIGTERM");
|
|
645
672
|
} catch {}
|
|
@@ -662,6 +689,19 @@ var MockBrowserController = class {
|
|
|
662
689
|
targetWsUrl
|
|
663
690
|
};
|
|
664
691
|
}
|
|
692
|
+
async connect(cdpUrl) {
|
|
693
|
+
this.pages.set(cdpUrl, {
|
|
694
|
+
url: "about:blank",
|
|
695
|
+
title: "about:blank",
|
|
696
|
+
text: "",
|
|
697
|
+
html: "<html><body></body></html>"
|
|
698
|
+
});
|
|
699
|
+
return {
|
|
700
|
+
pid: 0,
|
|
701
|
+
cdpUrl,
|
|
702
|
+
targetWsUrl: cdpUrl
|
|
703
|
+
};
|
|
704
|
+
}
|
|
665
705
|
async navigate(cdpUrl, url) {
|
|
666
706
|
const page = this.pages.get(cdpUrl);
|
|
667
707
|
if (!page) throw new Error("mock page missing");
|
|
@@ -785,7 +825,7 @@ var SessionManager = class {
|
|
|
785
825
|
if (active && active.session.status !== "terminated") throw new Error("A managed session is already active");
|
|
786
826
|
const sessionId = crypto.randomUUID();
|
|
787
827
|
const token = this.ctx.tokenService.issue(sessionId);
|
|
788
|
-
const launched = await this.browser.launch(sessionId, this.ctx.config.browserExecutablePath);
|
|
828
|
+
const launched = this.ctx.config.cdpUrl ? await this.browser.connect(this.ctx.config.cdpUrl) : await this.browser.launch(sessionId, this.ctx.config.browserExecutablePath, this.ctx.config.userProfileDir);
|
|
789
829
|
const session = {
|
|
790
830
|
sessionId,
|
|
791
831
|
status: "ready",
|
|
@@ -1136,12 +1176,18 @@ function loadConfig(env = process.env) {
|
|
|
1136
1176
|
const commandTimeoutMs = Number.parseInt(env.AGENTIC_BROWSER_COMMAND_TIMEOUT_MS ?? `${DEFAULT_TIMEOUT_MS}`, 10);
|
|
1137
1177
|
if (Number.isNaN(wsPort) || wsPort <= 0) throw new Error("AGENTIC_BROWSER_WS_PORT must be a positive integer");
|
|
1138
1178
|
if (Number.isNaN(commandTimeoutMs) || commandTimeoutMs <= 0) throw new Error("AGENTIC_BROWSER_COMMAND_TIMEOUT_MS must be a positive integer");
|
|
1179
|
+
const userProfile = env.AGENTIC_BROWSER_USER_PROFILE;
|
|
1180
|
+
let userProfileDir;
|
|
1181
|
+
if (userProfile === "true" || userProfile === "default") userProfileDir = "default";
|
|
1182
|
+
else if (userProfile && path.isAbsolute(userProfile)) userProfileDir = userProfile;
|
|
1139
1183
|
return {
|
|
1140
1184
|
host: env.AGENTIC_BROWSER_HOST ?? "127.0.0.1",
|
|
1141
1185
|
wsPort,
|
|
1142
1186
|
commandTimeoutMs,
|
|
1143
1187
|
logDir: env.AGENTIC_BROWSER_LOG_DIR ?? path.resolve(process.cwd(), ".agentic-browser"),
|
|
1144
|
-
browserExecutablePath: env.AGENTIC_BROWSER_CHROME_PATH
|
|
1188
|
+
browserExecutablePath: env.AGENTIC_BROWSER_CHROME_PATH,
|
|
1189
|
+
cdpUrl: env.AGENTIC_BROWSER_CDP_URL,
|
|
1190
|
+
userProfileDir
|
|
1145
1191
|
};
|
|
1146
1192
|
}
|
|
1147
1193
|
|