chore: pre-release cleanup
- Fix daemon per-command timeout: 30s → 120s (was shorter than CLI-layer timeouts) - Remove debug command: grok/debug.ts - Sync extension version to 1.0.0 - Rename PlaywrightMCP → BrowserBridge (keep backward-compat alias) - Add accept/reply-dm to README command tables - Clean up consoleMessages() JSDoc in page.ts - Update runtime.ts comment
This commit is contained in:
1 parent
13e2345089
commit
2e962b2e7c
9 files changed
+398
-363
No files matched your search
+7
-11
@@ -1,8 +1,5 @@
|
||||
/**
|
||||
* Browser session manager — auto-spawns daemon and provides IPage.
|
||||
*
|
||||
* Replaces the old PlaywrightMCP class. Still exports as PlaywrightMCP
|
||||
* for backward compatibility with main.ts and other consumers.
|
||||
*/
|
||||
|
||||
import { spawn, type ChildProcess } from 'node:child_process';
|
||||
@@ -15,21 +12,17 @@ import { isDaemonRunning, isExtensionConnected } from './daemon-client.js';
|
||||
|
||||
const DAEMON_SPAWN_TIMEOUT = 10000; // 10s to wait for daemon + extension
|
||||
|
||||
export type PlaywrightMCPState = 'idle' | 'connecting' | 'connected' | 'closing' | 'closed';
|
||||
|
||||
|
||||
export type BrowserBridgeState = 'idle' | 'connecting' | 'connected' | 'closing' | 'closed';
|
||||
|
||||
/**
|
||||
* Browser factory: manages daemon lifecycle and provides IPage instances.
|
||||
*
|
||||
* Kept as `PlaywrightMCP` class name for backward compatibility.
|
||||
*/
|
||||
export class PlaywrightMCP {
|
||||
private _state: PlaywrightMCPState = 'idle';
|
||||
export class BrowserBridge {
|
||||
private _state: BrowserBridgeState = 'idle';
|
||||
private _page: Page | null = null;
|
||||
private _daemonProc: ChildProcess | null = null;
|
||||
|
||||
get state(): PlaywrightMCPState {
|
||||
get state(): BrowserBridgeState {
|
||||
return this._state;
|
||||
}
|
||||
|
||||
@@ -113,3 +106,6 @@ export class PlaywrightMCP {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/** @deprecated Use BrowserBridge instead */
|
||||
export const PlaywrightMCP = BrowserBridge;
|
||||
+6
-6
@@ -183,12 +183,12 @@ export class Page implements IPage {
|
||||
return sendCommand('exec', { code, ...this._tabOpt() });
|
||||
}
|
||||
|
||||
async consoleMessages(level: string = 'info'): Promise<any> {
|
||||
// Console messages can't be retrospectively read via CDP Runtime.evaluate.
|
||||
// Would need Runtime.consoleAPICalled event listener, which is not yet implemented.
|
||||
if (process.env.OPENCLI_VERBOSE) {
|
||||
console.error('[page] consoleMessages() not supported in lightweight mode — returning empty');
|
||||
}
|
||||
/**
|
||||
* Console messages are not available in lightweight daemon mode.
|
||||
* Would require CDP Runtime.consoleAPICalled event listener.
|
||||
* @returns Always returns empty array.
|
||||
*/
|
||||
async consoleMessages(_level: string = 'info'): Promise<any> {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
import { cli, Strategy } from '../../registry.js';
|
||||
import type { IPage } from '../../types.js';
|
||||
|
||||
export const debugCommand = cli({
|
||||
site: 'grok',
|
||||
name: 'debug',
|
||||
description: 'Debug grok page structure',
|
||||
domain: 'grok.com',
|
||||
strategy: Strategy.COOKIE,
|
||||
browser: true,
|
||||
columns: ['data'],
|
||||
func: async (page: IPage, _kwargs: Record<string, any>) => {
|
||||
await page.goto('https://grok.com');
|
||||
await page.wait(3);
|
||||
|
||||
// Get all button-like elements near textarea
|
||||
const debug = await page.evaluate(`(() => {
|
||||
const ta = document.querySelector('textarea');
|
||||
if (!ta) return { error: 'no textarea' };
|
||||
|
||||
// Get parent containers
|
||||
let parent = ta.parentElement;
|
||||
const parents = [];
|
||||
for (let i = 0; i < 5 && parent; i++) {
|
||||
parents.push({
|
||||
tag: parent.tagName,
|
||||
class: parent.className?.substring(0, 80),
|
||||
childCount: parent.children.length,
|
||||
});
|
||||
parent = parent.parentElement;
|
||||
}
|
||||
|
||||
// Find buttons in the form/container near textarea
|
||||
const form = ta.closest('form') || ta.closest('[class*="composer"]') || ta.closest('[class*="input"]') || ta.parentElement?.parentElement;
|
||||
const buttons = form ? [...form.querySelectorAll('button')].map(b => ({
|
||||
testid: b.getAttribute('data-testid'),
|
||||
type: b.type,
|
||||
disabled: b.disabled,
|
||||
text: (b.textContent || '').substring(0, 30),
|
||||
html: b.outerHTML.substring(0, 200),
|
||||
rect: b.getBoundingClientRect().toJSON(),
|
||||
})) : [];
|
||||
|
||||
return { parents, buttons, formTag: form?.tagName, formClass: form?.className?.substring(0, 80) };
|
||||
})()`);
|
||||
|
||||
return [{ data: JSON.stringify(debug, null, 2) }];
|
||||
},
|
||||
});
|
||||
+2
-2
@@ -114,8 +114,8 @@ async function handleRequest(req: IncomingMessage, res: ServerResponse): Promise
|
||||
const result = await new Promise<unknown>((resolve, reject) => {
|
||||
const timer = setTimeout(() => {
|
||||
pending.delete(body.id);
|
||||
reject(new Error('Command timeout (30s)'));
|
||||
}, 30000);
|
||||
reject(new Error('Command timeout (120s)'));
|
||||
}, 120000);
|
||||
pending.set(body.id, { resolve, reject, timer });
|
||||
extensionWs!.send(JSON.stringify(body));
|
||||
});
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ export function withTimeoutMs<T>(promise: Promise<T>, timeoutMs: number, message
|
||||
});
|
||||
}
|
||||
|
||||
/** Interface for browser factory (PlaywrightMCP or test mocks) */
|
||||
/** Interface for browser factory (BrowserBridge or test mocks) */
|
||||
export interface IBrowserFactory {
|
||||
connect(opts?: { timeout?: number }): Promise<IPage>;
|
||||
close(): Promise<void>;
|
||||
|
||||
Reference in new issue
Block a user