@@ -207,23 +207,12 @@ export class SessionManager {
207207 ] ;
208208
209209 if ( config . antiDetection ?. useCloakBrowser ) {
210- // CloakBrowser: stealth Chromium with 33 C++-level patches for DataDome.
211- // Uses its own Chromium binary — cannot share profiles with real Chrome.
212- // Profile dir is sibling to the standard profile: <site>-cloak
213- // Lazy import — only loaded when useCloakBrowser is configured, so adapters
214- // that don't need it never trigger the ~140MB binary download on install.
215- const { launchPersistentContext : cloakLaunch } = await import ( "cloakbrowser" ) ;
216- const cloakProfileDir = this . getProfileDir ( `${ config . site } -cloak` ) ;
217- fs . mkdirSync ( cloakProfileDir , { recursive : true , mode : 0o700 } ) ;
218- log . info ( { site : config . site , cloakProfileDir } , "launching CloakBrowser for DataDome bypass" ) ;
219- context = await cloakLaunch ( {
220- userDataDir : cloakProfileDir ,
221- headless : ! headed ,
222- humanize : true ,
223- args : antiAutomationArgs ,
224- } ) as unknown as BrowserContext ;
225- } else {
226- context = await chromium . launchPersistentContext ( profileDir , {
210+ // CloakBrowser was removed — fall through to standard patchright launch.
211+ // (useCloakBrowser is now a no-op; the option is retained in types for
212+ // backward compatibility but does nothing.)
213+ log . warn ( { site : config . site } , "antiDetection.useCloakBrowser is deprecated — ignored" ) ;
214+ }
215+ context = await chromium . launchPersistentContext ( profileDir , {
227216 headless : ! headed ,
228217 slowMo,
229218 // viewport: null tells Chrome to use its natural window size rather than
@@ -235,7 +224,6 @@ export class SessionManager {
235224 ...( config . channel ? { channel : config . channel } : { } ) ,
236225 ...devicePreset ,
237226 } ) ;
238- }
239227 }
240228
241229 const page = await context . newPage ( ) ;
@@ -382,3 +370,106 @@ export function getDefaultDataDir(): string {
382370function isProcessRunning ( pid : number ) : boolean {
383371 try { process . kill ( pid , 0 ) ; return true ; } catch { return false ; }
384372}
373+
374+ // ── CDP auto-discovery ────────────────────────────────────────────────────────
375+ // Ported from dev-browser's BrowserManager.autoConnect() / probePort() logic.
376+ // Discovers a running Chrome/Chromium instance with remote debugging enabled.
377+
378+ const DISCOVERY_PORTS = [ 9222 , 9223 , 9224 , 9225 , 9226 , 9227 , 9228 , 9229 ] ;
379+ const PROBE_TIMEOUT_MS = 750 ;
380+
381+ /** Candidate paths for Chrome's DevToolsActivePort file on macOS and Linux. */
382+ function getDevToolsActivePortCandidates ( ) : string [ ] {
383+ const home = os . homedir ( ) ;
384+ switch ( process . platform ) {
385+ case "darwin" :
386+ return [
387+ path . join ( home , "Library" , "Application Support" , "Google" , "Chrome" , "DevToolsActivePort" ) ,
388+ path . join ( home , "Library" , "Application Support" , "Google" , "Chrome Canary" , "DevToolsActivePort" ) ,
389+ path . join ( home , "Library" , "Application Support" , "Chromium" , "DevToolsActivePort" ) ,
390+ path . join ( home , "Library" , "Application Support" , "BraveSoftware" , "Brave-Browser" , "DevToolsActivePort" ) ,
391+ ] ;
392+ case "linux" :
393+ return [
394+ path . join ( home , ".config" , "google-chrome" , "DevToolsActivePort" ) ,
395+ path . join ( home , ".config" , "chromium" , "DevToolsActivePort" ) ,
396+ path . join ( home , ".config" , "google-chrome-beta" , "DevToolsActivePort" ) ,
397+ path . join ( home , ".config" , "google-chrome-unstable" , "DevToolsActivePort" ) ,
398+ path . join ( home , ".config" , "BraveSoftware" , "Brave-Browser" , "DevToolsActivePort" ) ,
399+ ] ;
400+ default :
401+ return [ ] ;
402+ }
403+ }
404+
405+ /** Parse a DevToolsActivePort file. Returns a `ws://` URL or null if invalid. */
406+ function parseDevToolsActivePort ( contents : string , expectedPort ?: number ) : string | null {
407+ const lines = contents . split ( / \r ? \n / ) . map ( ( l ) => l . trim ( ) ) . filter ( ( l ) => l . length > 0 ) ;
408+ const port = Number . parseInt ( lines [ 0 ] ?? "" , 10 ) ;
409+ const wsPath = lines [ 1 ] ?? "" ;
410+ if ( ! Number . isInteger ( port ) || port < 1 || port > 65_535 ) return null ;
411+ if ( expectedPort !== undefined && port !== expectedPort ) return null ;
412+ if ( ! wsPath . startsWith ( "/devtools/browser/" ) ) return null ;
413+ return `ws://127.0.0.1:${ port } ${ wsPath } ` ;
414+ }
415+
416+ /** Try to fetch /json/version on a CDP endpoint and return the WS debugger URL. */
417+ async function fetchCdpWebSocketUrl (
418+ httpEndpoint : string ,
419+ timeoutMs : number
420+ ) : Promise < string | null > {
421+ try {
422+ const url = new URL ( "/json/version" , httpEndpoint ) . href ;
423+ const res = await fetch ( url , {
424+ headers : { accept : "application/json" } ,
425+ signal : AbortSignal . timeout ( timeoutMs ) ,
426+ } ) ;
427+ if ( ! res . ok ) return null ;
428+ const data = ( await res . json ( ) ) as { webSocketDebuggerUrl ?: string } ;
429+ return typeof data . webSocketDebuggerUrl === "string" && data . webSocketDebuggerUrl . length > 0
430+ ? data . webSocketDebuggerUrl
431+ : null ;
432+ } catch {
433+ return null ;
434+ }
435+ }
436+
437+ /**
438+ * Auto-discover a running Chrome/Chromium instance with remote debugging enabled.
439+ *
440+ * Strategy (in order):
441+ * 1. Read DevToolsActivePort from known Chrome/Canary/Brave/Chromium profile dirs
442+ * 2. Probe ports 9222–9229 via GET /json/version
443+ *
444+ * Returns the CDP WebSocket URL (`ws://...`) or throws with a helpful message.
445+ */
446+ export async function autoDiscoverCdpEndpoint ( ) : Promise < string > {
447+ // 1. Try DevToolsActivePort files first — fastest, no network needed
448+ for ( const candidate of getDevToolsActivePortCandidates ( ) ) {
449+ try {
450+ const contents = fs . readFileSync ( candidate , "utf8" ) ;
451+ const wsUrl = parseDevToolsActivePort ( contents ) ;
452+ if ( wsUrl ) return wsUrl ;
453+ } catch {
454+ // File missing or unreadable — try next
455+ }
456+ }
457+
458+ // 2. Fall back to port probing
459+ for ( const port of DISCOVERY_PORTS ) {
460+ const httpEndpoint = `http://127.0.0.1:${ port } ` ;
461+ const wsUrl = await fetchCdpWebSocketUrl ( httpEndpoint , PROBE_TIMEOUT_MS ) ;
462+ if ( wsUrl ) return wsUrl ;
463+ }
464+
465+ const launchCmd =
466+ process . platform === "darwin"
467+ ? '"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --remote-debugging-port=9222'
468+ : "google-chrome --remote-debugging-port=9222" ;
469+
470+ throw new Error (
471+ "Could not auto-discover a running Chrome instance with remote debugging enabled.\n" +
472+ "Enable it at chrome://inspect/#remote-debugging\n" +
473+ `or launch Chrome with: ${ launchCmd } `
474+ ) ;
475+ }
0 commit comments