clementine-agent 1.6.0 → 1.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/dist/cli/browser.d.ts +12 -0
- package/dist/cli/browser.js +267 -18
- package/dist/cli/index.js +9 -1
- package/package.json +1 -1
package/dist/cli/browser.d.ts
CHANGED
|
@@ -20,5 +20,17 @@
|
|
|
20
20
|
export declare function cmdBrowserStatus(): Promise<void>;
|
|
21
21
|
export declare function cmdBrowserInstall(): Promise<void>;
|
|
22
22
|
export declare function cmdBrowserEnable(): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Auto-prompt during `clementine update`. Stays silent unless there's
|
|
25
|
+
* something actionable — mirrors the keychain wizard's behavior.
|
|
26
|
+
*
|
|
27
|
+
* Skips prompting when:
|
|
28
|
+
* - Not in an interactive TTY
|
|
29
|
+
* - The MCP wrapper isn't shipped with this version
|
|
30
|
+
* - Browser harness is already installed AND enabled
|
|
31
|
+
* - User previously dismissed the prompt
|
|
32
|
+
*/
|
|
33
|
+
export declare function maybePromptBrowserHarness(): Promise<void>;
|
|
23
34
|
export declare function cmdBrowserDisable(): Promise<void>;
|
|
35
|
+
export declare function cmdBrowserConnect(): Promise<void>;
|
|
24
36
|
//# sourceMappingURL=browser.d.ts.map
|
package/dist/cli/browser.js
CHANGED
|
@@ -19,9 +19,11 @@
|
|
|
19
19
|
*/
|
|
20
20
|
import { execSync, spawnSync } from 'node:child_process';
|
|
21
21
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
22
|
+
import http from 'node:http';
|
|
22
23
|
import os from 'node:os';
|
|
23
24
|
import path from 'node:path';
|
|
24
25
|
import { fileURLToPath } from 'node:url';
|
|
26
|
+
import { confirm } from '@inquirer/prompts';
|
|
25
27
|
const BOLD = '\x1b[1m';
|
|
26
28
|
const DIM = '\x1b[0;90m';
|
|
27
29
|
const GREEN = '\x1b[0;32m';
|
|
@@ -40,10 +42,36 @@ const VENV_PYTHON = path.join(VENV_DIR, 'bin', 'python3');
|
|
|
40
42
|
const MCP_SERVERS_FILE = path.join(BASE_DIR, 'mcp-servers.json');
|
|
41
43
|
const HARNESS_REPO = 'https://github.com/browser-use/browser-harness.git';
|
|
42
44
|
const SERVER_NAME = 'browser-harness';
|
|
45
|
+
const DISMISSED_MARKER = path.join(BASE_DIR, '.browser-harness-dismissed');
|
|
43
46
|
function commandExists(cmd) {
|
|
44
47
|
const result = spawnSync('which', [cmd], { stdio: 'pipe' });
|
|
45
48
|
return result.status === 0;
|
|
46
49
|
}
|
|
50
|
+
/** Probe the CDP socket — returns true if Chrome is listening on :9222. */
|
|
51
|
+
function probeCdp() {
|
|
52
|
+
return new Promise(resolve => {
|
|
53
|
+
const req = http.get('http://localhost:9222/json/version', { timeout: 1500 }, res => {
|
|
54
|
+
resolve(res.statusCode === 200);
|
|
55
|
+
res.resume();
|
|
56
|
+
});
|
|
57
|
+
req.on('error', () => resolve(false));
|
|
58
|
+
req.on('timeout', () => { req.destroy(); resolve(false); });
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
/** True if a Google Chrome process is currently running. */
|
|
62
|
+
function isChromeRunning() {
|
|
63
|
+
if (process.platform === 'darwin') {
|
|
64
|
+
const r = spawnSync('pgrep', ['-x', 'Google Chrome'], { stdio: 'pipe' });
|
|
65
|
+
return r.status === 0;
|
|
66
|
+
}
|
|
67
|
+
// Linux: chrome / chromium / google-chrome
|
|
68
|
+
for (const name of ['google-chrome', 'chromium', 'chrome']) {
|
|
69
|
+
const r = spawnSync('pgrep', ['-x', name], { stdio: 'pipe' });
|
|
70
|
+
if (r.status === 0)
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
47
75
|
function pythonVersion() {
|
|
48
76
|
try {
|
|
49
77
|
const out = execSync('python3 --version', { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
|
|
@@ -75,6 +103,7 @@ export async function cmdBrowserStatus() {
|
|
|
75
103
|
const harnessOk = existsSync(path.join(HARNESS_HOME, 'src'));
|
|
76
104
|
const servers = loadMcpServers();
|
|
77
105
|
const enabled = Object.prototype.hasOwnProperty.call(servers, SERVER_NAME);
|
|
106
|
+
const cdpOk = await probeCdp();
|
|
78
107
|
console.log();
|
|
79
108
|
console.log(` ${BOLD}Browser Harness${RESET} ${DIM}(beta)${RESET}`);
|
|
80
109
|
console.log();
|
|
@@ -83,6 +112,7 @@ export async function cmdBrowserStatus() {
|
|
|
83
112
|
console.log(` ${venvOk ? GREEN + '✓' : YELLOW + '○'}${RESET} venv installed ${DIM}${VENV_DIR}${RESET}`);
|
|
84
113
|
console.log(` ${harnessOk ? GREEN + '✓' : YELLOW + '○'}${RESET} harness cloned ${DIM}${HARNESS_HOME}${RESET}`);
|
|
85
114
|
console.log(` ${enabled ? GREEN + '✓' : DIM + '○'}${RESET} MCP entry ${DIM}${enabled ? 'enabled' : 'disabled'} in mcp-servers.json${RESET}`);
|
|
115
|
+
console.log(` ${cdpOk ? GREEN + '✓' : YELLOW + '○'}${RESET} Chrome CDP ${DIM}${cdpOk ? 'connected on :9222' : 'not connected — run: clementine browser connect'}${RESET}`);
|
|
86
116
|
console.log();
|
|
87
117
|
if (!py) {
|
|
88
118
|
console.log(` ${YELLOW}Install Python 3.10+ first:${RESET}`);
|
|
@@ -97,12 +127,20 @@ export async function cmdBrowserStatus() {
|
|
|
97
127
|
console.log(` Next: ${BOLD}clementine browser enable${RESET}`);
|
|
98
128
|
console.log();
|
|
99
129
|
}
|
|
130
|
+
else if (!cdpOk) {
|
|
131
|
+
console.log(` Next: ${BOLD}clementine browser connect${RESET}`);
|
|
132
|
+
console.log();
|
|
133
|
+
}
|
|
100
134
|
else {
|
|
101
|
-
console.log(` ${GREEN}Ready.${RESET} ${DIM}
|
|
135
|
+
console.log(` ${GREEN}Ready.${RESET} ${DIM}Browser harness is fully connected.${RESET}`);
|
|
102
136
|
console.log();
|
|
103
137
|
}
|
|
104
138
|
}
|
|
105
|
-
|
|
139
|
+
/**
|
|
140
|
+
* Core install logic. Returns true on success, false on any failure.
|
|
141
|
+
* Prints progress + errors to stdout/stderr but never calls process.exit.
|
|
142
|
+
*/
|
|
143
|
+
async function runInstall() {
|
|
106
144
|
console.log();
|
|
107
145
|
console.log(` ${BOLD}Installing browser-harness${RESET} ${DIM}(beta)${RESET}`);
|
|
108
146
|
console.log();
|
|
@@ -110,13 +148,13 @@ export async function cmdBrowserInstall() {
|
|
|
110
148
|
console.error(` ${RED}python3 not found.${RESET} Install Python 3.10+ first:`);
|
|
111
149
|
console.error(` ${CYAN}brew install python@3.12${RESET}`);
|
|
112
150
|
console.error();
|
|
113
|
-
|
|
151
|
+
return false;
|
|
114
152
|
}
|
|
115
153
|
if (!existsSync(MCP_SCRIPT)) {
|
|
116
154
|
console.error(` ${RED}MCP wrapper not found at:${RESET} ${MCP_SCRIPT}`);
|
|
117
155
|
console.error(` ${DIM}This means the package was installed without vendor/ files. Reinstall:${RESET}`);
|
|
118
156
|
console.error(` ${CYAN}npm install -g clementine-agent@latest${RESET}`);
|
|
119
|
-
|
|
157
|
+
return false;
|
|
120
158
|
}
|
|
121
159
|
if (!existsSync(BASE_DIR))
|
|
122
160
|
mkdirSync(BASE_DIR, { recursive: true });
|
|
@@ -124,7 +162,7 @@ export async function cmdBrowserInstall() {
|
|
|
124
162
|
if (!existsSync(HARNESS_HOME)) {
|
|
125
163
|
if (!commandExists('git')) {
|
|
126
164
|
console.error(` ${RED}git not found.${RESET} Install git, then re-run.`);
|
|
127
|
-
|
|
165
|
+
return false;
|
|
128
166
|
}
|
|
129
167
|
console.log(` ${DIM}→ cloning ${HARNESS_REPO}${RESET}`);
|
|
130
168
|
try {
|
|
@@ -132,7 +170,7 @@ export async function cmdBrowserInstall() {
|
|
|
132
170
|
}
|
|
133
171
|
catch {
|
|
134
172
|
console.error(` ${RED}Clone failed.${RESET} Check network / git access and try again.`);
|
|
135
|
-
|
|
173
|
+
return false;
|
|
136
174
|
}
|
|
137
175
|
}
|
|
138
176
|
else {
|
|
@@ -146,7 +184,7 @@ export async function cmdBrowserInstall() {
|
|
|
146
184
|
}
|
|
147
185
|
catch {
|
|
148
186
|
console.error(` ${RED}venv creation failed.${RESET}`);
|
|
149
|
-
|
|
187
|
+
return false;
|
|
150
188
|
}
|
|
151
189
|
}
|
|
152
190
|
else {
|
|
@@ -165,25 +203,21 @@ export async function cmdBrowserInstall() {
|
|
|
165
203
|
}
|
|
166
204
|
catch {
|
|
167
205
|
console.error(` ${RED}pip install failed.${RESET} Inspect output above and re-run when fixed.`);
|
|
168
|
-
|
|
206
|
+
return false;
|
|
169
207
|
}
|
|
170
208
|
console.log();
|
|
171
209
|
console.log(` ${GREEN}✓${RESET} Install complete.`);
|
|
172
|
-
|
|
173
|
-
console.log(` ${BOLD}Next steps:${RESET}`);
|
|
174
|
-
console.log(` 1. Enable Chrome remote debugging — open Chrome with:`);
|
|
175
|
-
console.log(` ${CYAN}/Applications/Google\\ Chrome.app/Contents/MacOS/Google\\ Chrome \\${RESET}`);
|
|
176
|
-
console.log(` ${CYAN}--remote-debugging-port=9222${RESET}`);
|
|
177
|
-
console.log(` 2. Enable the MCP server: ${BOLD}clementine browser enable${RESET}`);
|
|
178
|
-
console.log(` 3. Restart the daemon: ${BOLD}clementine restart${RESET}`);
|
|
179
|
-
console.log();
|
|
210
|
+
return true;
|
|
180
211
|
}
|
|
181
|
-
|
|
212
|
+
/**
|
|
213
|
+
* Core enable logic. Returns true on success, false on any failure.
|
|
214
|
+
*/
|
|
215
|
+
function runEnable() {
|
|
182
216
|
if (!existsSync(VENV_PYTHON) || !existsSync(MCP_SCRIPT)) {
|
|
183
217
|
console.error();
|
|
184
218
|
console.error(` ${RED}Not installed yet.${RESET} Run ${BOLD}clementine browser install${RESET} first.`);
|
|
185
219
|
console.error();
|
|
186
|
-
|
|
220
|
+
return false;
|
|
187
221
|
}
|
|
188
222
|
const servers = loadMcpServers();
|
|
189
223
|
servers[SERVER_NAME] = {
|
|
@@ -201,9 +235,107 @@ export async function cmdBrowserEnable() {
|
|
|
201
235
|
saveMcpServers(servers);
|
|
202
236
|
console.log();
|
|
203
237
|
console.log(` ${GREEN}✓${RESET} Registered ${BOLD}${SERVER_NAME}${RESET} in mcp-servers.json`);
|
|
238
|
+
return true;
|
|
239
|
+
}
|
|
240
|
+
export async function cmdBrowserInstall() {
|
|
241
|
+
const ok = await runInstall();
|
|
242
|
+
if (!ok)
|
|
243
|
+
process.exit(1);
|
|
244
|
+
console.log();
|
|
245
|
+
console.log(` ${BOLD}Next:${RESET} ${BOLD}clementine browser enable${RESET} — register the MCP server`);
|
|
246
|
+
console.log(` ${DIM}Then connect Chrome with: clementine browser connect${RESET}`);
|
|
247
|
+
console.log();
|
|
248
|
+
}
|
|
249
|
+
export async function cmdBrowserEnable() {
|
|
250
|
+
const ok = runEnable();
|
|
251
|
+
if (!ok)
|
|
252
|
+
process.exit(1);
|
|
204
253
|
console.log(` ${DIM}Restart the daemon to pick up the change: clementine restart${RESET}`);
|
|
205
254
|
console.log();
|
|
206
255
|
}
|
|
256
|
+
/**
|
|
257
|
+
* Auto-prompt during `clementine update`. Stays silent unless there's
|
|
258
|
+
* something actionable — mirrors the keychain wizard's behavior.
|
|
259
|
+
*
|
|
260
|
+
* Skips prompting when:
|
|
261
|
+
* - Not in an interactive TTY
|
|
262
|
+
* - The MCP wrapper isn't shipped with this version
|
|
263
|
+
* - Browser harness is already installed AND enabled
|
|
264
|
+
* - User previously dismissed the prompt
|
|
265
|
+
*/
|
|
266
|
+
export async function maybePromptBrowserHarness() {
|
|
267
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY)
|
|
268
|
+
return;
|
|
269
|
+
if (!existsSync(MCP_SCRIPT))
|
|
270
|
+
return;
|
|
271
|
+
const servers = loadMcpServers();
|
|
272
|
+
const enabled = Object.prototype.hasOwnProperty.call(servers, SERVER_NAME);
|
|
273
|
+
const installed = existsSync(VENV_PYTHON);
|
|
274
|
+
if (enabled && installed)
|
|
275
|
+
return;
|
|
276
|
+
if (existsSync(DISMISSED_MARKER))
|
|
277
|
+
return;
|
|
278
|
+
console.log();
|
|
279
|
+
console.log(` ${BOLD}Browser Harness available${RESET} ${DIM}(beta, opt-in)${RESET}`);
|
|
280
|
+
console.log(` ${DIM}Lets Clementine drive your real Chrome — fill forms, post on LinkedIn,${RESET}`);
|
|
281
|
+
console.log(` ${DIM}book appointments — using your live browser session.${RESET}`);
|
|
282
|
+
console.log();
|
|
283
|
+
let answer;
|
|
284
|
+
try {
|
|
285
|
+
answer = await confirm({
|
|
286
|
+
message: 'Install Browser Harness now?',
|
|
287
|
+
default: false,
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
catch {
|
|
291
|
+
// User Ctrl+C'd or terminal closed — treat as decline, don't dismiss permanently
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
if (!answer) {
|
|
295
|
+
try {
|
|
296
|
+
writeFileSync(DISMISSED_MARKER, new Date().toISOString() + '\n');
|
|
297
|
+
}
|
|
298
|
+
catch { /* non-fatal */ }
|
|
299
|
+
console.log(` ${DIM}Skipped. To install later: clementine browser install${RESET}`);
|
|
300
|
+
console.log();
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
// User said yes — run install + enable inline
|
|
304
|
+
const installOk = await runInstall();
|
|
305
|
+
if (!installOk) {
|
|
306
|
+
console.error(` ${YELLOW}Install failed.${RESET} ${DIM}You can retry with: clementine browser install${RESET}`);
|
|
307
|
+
console.log();
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
const enableOk = runEnable();
|
|
311
|
+
if (!enableOk) {
|
|
312
|
+
console.error(` ${YELLOW}Enable failed.${RESET} ${DIM}Retry with: clementine browser enable${RESET}`);
|
|
313
|
+
console.log();
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
console.log();
|
|
317
|
+
console.log(` ${GREEN}✓${RESET} Browser Harness installed and enabled.`);
|
|
318
|
+
console.log();
|
|
319
|
+
// Offer to connect Chrome right now
|
|
320
|
+
let connectNow = false;
|
|
321
|
+
try {
|
|
322
|
+
connectNow = await confirm({
|
|
323
|
+
message: 'Connect Chrome now? (relaunches Chrome with debugging — will close current windows)',
|
|
324
|
+
default: false,
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
catch {
|
|
328
|
+
// Ctrl+C — bail without dismissing
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
if (connectNow) {
|
|
332
|
+
await runConnect({ confirmQuit: false });
|
|
333
|
+
}
|
|
334
|
+
else {
|
|
335
|
+
console.log(` ${DIM}Connect later with: ${BOLD}clementine browser connect${RESET}`);
|
|
336
|
+
console.log();
|
|
337
|
+
}
|
|
338
|
+
}
|
|
207
339
|
export async function cmdBrowserDisable() {
|
|
208
340
|
const servers = loadMcpServers();
|
|
209
341
|
if (!Object.prototype.hasOwnProperty.call(servers, SERVER_NAME)) {
|
|
@@ -221,4 +353,121 @@ export async function cmdBrowserDisable() {
|
|
|
221
353
|
console.log(` ${DIM}Restart the daemon: clementine restart${RESET}`);
|
|
222
354
|
console.log();
|
|
223
355
|
}
|
|
356
|
+
/**
|
|
357
|
+
* Core connect logic — quits any running Chrome and relaunches with
|
|
358
|
+
* --remote-debugging-port=9222 so browser-harness can connect.
|
|
359
|
+
*
|
|
360
|
+
* Returns true when CDP is reachable on :9222 at the end, false otherwise.
|
|
361
|
+
* Never calls process.exit so it's safe to call from the auto-prompt flow.
|
|
362
|
+
*/
|
|
363
|
+
async function runConnect(opts = {}) {
|
|
364
|
+
// 1. Already connected? Done.
|
|
365
|
+
if (await probeCdp()) {
|
|
366
|
+
console.log();
|
|
367
|
+
console.log(` ${GREEN}✓${RESET} Already connected — Chrome is running with remote debugging on :9222`);
|
|
368
|
+
console.log();
|
|
369
|
+
return true;
|
|
370
|
+
}
|
|
371
|
+
// 2. Platform check — auto-launch is currently macOS only
|
|
372
|
+
if (process.platform !== 'darwin' && process.platform !== 'linux') {
|
|
373
|
+
console.error();
|
|
374
|
+
console.error(` ${YELLOW}Auto-connect is only supported on macOS and Linux.${RESET}`);
|
|
375
|
+
console.error(` Launch Chrome manually with the flag: ${BOLD}--remote-debugging-port=9222${RESET}`);
|
|
376
|
+
console.error();
|
|
377
|
+
return false;
|
|
378
|
+
}
|
|
379
|
+
// 3. Chrome already running without the flag? Need to quit first.
|
|
380
|
+
if (isChromeRunning()) {
|
|
381
|
+
console.log();
|
|
382
|
+
console.log(` ${YELLOW}Chrome is running, but without remote debugging.${RESET}`);
|
|
383
|
+
console.log(` ${DIM}To connect, Chrome needs to be quit and relaunched with the flag.${RESET}`);
|
|
384
|
+
console.log(` ${DIM}This will close your current Chrome windows.${RESET}`);
|
|
385
|
+
console.log();
|
|
386
|
+
let confirmed = !opts.confirmQuit; // skip prompt when caller already confirmed
|
|
387
|
+
if (opts.confirmQuit) {
|
|
388
|
+
try {
|
|
389
|
+
confirmed = await confirm({
|
|
390
|
+
message: 'Quit Chrome and relaunch with debugging?',
|
|
391
|
+
default: false,
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
catch {
|
|
395
|
+
return false;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
if (!confirmed) {
|
|
399
|
+
console.log(` ${DIM}Skipped. To do it yourself: quit Chrome (Cmd+Q), then run:${RESET}`);
|
|
400
|
+
console.log(` ${BOLD}clementine browser connect${RESET}`);
|
|
401
|
+
console.log();
|
|
402
|
+
return false;
|
|
403
|
+
}
|
|
404
|
+
console.log(` ${DIM}→ quitting Chrome...${RESET}`);
|
|
405
|
+
try {
|
|
406
|
+
if (process.platform === 'darwin') {
|
|
407
|
+
execSync('osascript -e \'tell application "Google Chrome" to quit\'', { stdio: 'pipe' });
|
|
408
|
+
}
|
|
409
|
+
else {
|
|
410
|
+
// Linux: graceful TERM, then KILL if needed
|
|
411
|
+
try {
|
|
412
|
+
execSync('pkill -TERM -x "google-chrome|chromium|chrome"', { stdio: 'pipe' });
|
|
413
|
+
}
|
|
414
|
+
catch { /* ok */ }
|
|
415
|
+
}
|
|
416
|
+
// Wait briefly for Chrome to actually exit
|
|
417
|
+
for (let i = 0; i < 15; i++) {
|
|
418
|
+
if (!isChromeRunning())
|
|
419
|
+
break;
|
|
420
|
+
await new Promise(r => setTimeout(r, 300));
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
catch {
|
|
424
|
+
console.error(` ${RED}Failed to quit Chrome.${RESET} Please quit it manually and re-run.`);
|
|
425
|
+
return false;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
// 4. Launch Chrome with the debugging flag
|
|
429
|
+
console.log(` ${DIM}→ launching Chrome with --remote-debugging-port=9222${RESET}`);
|
|
430
|
+
try {
|
|
431
|
+
if (process.platform === 'darwin') {
|
|
432
|
+
execSync('open -na "Google Chrome" --args --remote-debugging-port=9222', { stdio: 'pipe' });
|
|
433
|
+
}
|
|
434
|
+
else {
|
|
435
|
+
// Linux — find a chrome binary in PATH
|
|
436
|
+
const candidates = ['google-chrome', 'chromium', 'chrome'];
|
|
437
|
+
const bin = candidates.find(commandExists);
|
|
438
|
+
if (!bin) {
|
|
439
|
+
console.error(` ${RED}No Chrome / Chromium binary found in PATH.${RESET}`);
|
|
440
|
+
return false;
|
|
441
|
+
}
|
|
442
|
+
// Launch detached so this command returns immediately
|
|
443
|
+
execSync(`nohup ${bin} --remote-debugging-port=9222 >/dev/null 2>&1 &`, { stdio: 'pipe' });
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
catch (e) {
|
|
447
|
+
console.error(` ${RED}Failed to launch Chrome:${RESET} ${String(e).slice(0, 200)}`);
|
|
448
|
+
return false;
|
|
449
|
+
}
|
|
450
|
+
// 5. Poll for CDP availability (up to ~6s)
|
|
451
|
+
for (let i = 0; i < 24; i++) {
|
|
452
|
+
await new Promise(r => setTimeout(r, 250));
|
|
453
|
+
if (await probeCdp()) {
|
|
454
|
+
console.log();
|
|
455
|
+
console.log(` ${GREEN}✓${RESET} Connected — Chrome is running with remote debugging on :9222`);
|
|
456
|
+
console.log(` ${DIM}Browser harness can now control your live session.${RESET}`);
|
|
457
|
+
console.log();
|
|
458
|
+
return true;
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
console.error();
|
|
462
|
+
console.error(` ${YELLOW}Chrome launched, but CDP socket isn't responding yet.${RESET}`);
|
|
463
|
+
console.error(` ${DIM}Check that Chrome started, then verify with:${RESET}`);
|
|
464
|
+
console.error(` ${CYAN}curl http://localhost:9222/json/version${RESET}`);
|
|
465
|
+
console.error();
|
|
466
|
+
return false;
|
|
467
|
+
}
|
|
468
|
+
export async function cmdBrowserConnect() {
|
|
469
|
+
const ok = await runConnect({ confirmQuit: true });
|
|
470
|
+
if (!ok)
|
|
471
|
+
process.exit(1);
|
|
472
|
+
}
|
|
224
473
|
//# sourceMappingURL=browser.js.map
|
package/dist/cli/index.js
CHANGED
|
@@ -24,7 +24,7 @@ import { cmdCronList, cmdCronRun, cmdCronRunDue, cmdCronRuns, cmdCronAdd, cmdCro
|
|
|
24
24
|
import { cmdDashboard } from './dashboard.js';
|
|
25
25
|
import { cmdChat } from './chat.js';
|
|
26
26
|
import { cmdIngestSeed, cmdIngestRun, cmdIngestList, cmdIngestStatus } from './ingest.js';
|
|
27
|
-
import { cmdBrowserStatus, cmdBrowserInstall, cmdBrowserEnable, cmdBrowserDisable } from './browser.js';
|
|
27
|
+
import { cmdBrowserStatus, cmdBrowserInstall, cmdBrowserEnable, cmdBrowserDisable, cmdBrowserConnect, maybePromptBrowserHarness } from './browser.js';
|
|
28
28
|
import { isSensitiveEnvKey } from '../secrets/sensitivity.js';
|
|
29
29
|
const __filename = fileURLToPath(import.meta.url);
|
|
30
30
|
const __dirname = path.dirname(__filename);
|
|
@@ -3171,6 +3171,8 @@ async function cmdUpdate(options) {
|
|
|
3171
3171
|
console.log(` ${DIM}Restart your daemon to pick up the new code:${RESET}`);
|
|
3172
3172
|
console.log(` clementine restart`);
|
|
3173
3173
|
}
|
|
3174
|
+
// Surface new opt-in integrations (silent unless action needed)
|
|
3175
|
+
await maybePromptBrowserHarness();
|
|
3174
3176
|
return;
|
|
3175
3177
|
}
|
|
3176
3178
|
let step = 0;
|
|
@@ -3830,6 +3832,8 @@ async function cmdUpdate(options) {
|
|
|
3830
3832
|
}
|
|
3831
3833
|
console.log(` ${DIM}Config backup: ${backupDir}${RESET}`);
|
|
3832
3834
|
console.log();
|
|
3835
|
+
// Surface new opt-in integrations (silent unless action needed)
|
|
3836
|
+
await maybePromptBrowserHarness();
|
|
3833
3837
|
}
|
|
3834
3838
|
// ── Cron commands ───────────────────────────────────────────────────
|
|
3835
3839
|
const cronCmd = program
|
|
@@ -4566,6 +4570,10 @@ browserCmd
|
|
|
4566
4570
|
.command('enable')
|
|
4567
4571
|
.description('Register the browser harness MCP server in mcp-servers.json')
|
|
4568
4572
|
.action(cmdBrowserEnable);
|
|
4573
|
+
browserCmd
|
|
4574
|
+
.command('connect')
|
|
4575
|
+
.description('Quit Chrome and relaunch it with --remote-debugging-port=9222 (one-shot)')
|
|
4576
|
+
.action(cmdBrowserConnect);
|
|
4569
4577
|
browserCmd
|
|
4570
4578
|
.command('disable')
|
|
4571
4579
|
.description('Remove the browser harness MCP entry (keeps installed files)')
|