@duckmind/dm-darwin-x64 0.43.0 → 0.43.4

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/dm CHANGED
Binary file
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "status": "ok",
3
- "prepared_at": "2026-07-05T18:04:46Z",
3
+ "prepared_at": "2026-07-07T16:00:55.489219+00:00",
4
4
  "managed_entries": [
5
5
  {
6
6
  "id": "dm-context",
@@ -398,6 +398,7 @@
398
398
  "src/search/fetch-source.mjs",
399
399
  "src/search/file-sources.mjs",
400
400
  "src/search/output.mjs",
401
+ "src/search/paths.mjs",
401
402
  "src/search/pdf.mjs",
402
403
  "src/search/query.mjs",
403
404
  "src/search/recovery.mjs",
@@ -405,13 +406,14 @@
405
406
  "src/search/sources.mjs",
406
407
  "src/search/synthesis-runner.mjs",
407
408
  "src/search/synthesis.mjs",
409
+ "src/utils/browser-executable.mjs",
408
410
  "src/utils/content.mjs",
409
411
  "src/utils/node-runtime.mjs",
410
412
  "src/utils/system-cmds.mjs"
411
413
  ],
412
- "file_count": 43,
413
- "before_bytes": 473122,
414
- "after_bytes": 753909,
414
+ "file_count": 45,
415
+ "before_bytes": 477153,
416
+ "after_bytes": 761716,
415
417
  "externals": [
416
418
  "@duckmind/dm-agent-core",
417
419
  "@duckmind/dm-ai",
@@ -8,7 +8,7 @@ Multi-engine AI web search for DM via browser automation.
8
8
  - Real browser results from configurable engines: Perplexity, Google AI, ChatGPT, Gemini, plus opt-in Semantic Scholar and Logically research engines
9
9
  - Research mode as the centerpiece: iterative planning, source fetching, citation audit, and structured bundles
10
10
  - Optional configurable synthesis with source grounding (Gemini by default)
11
- - Chrome runs headless by default — no window, purely background
11
+ - CloakBrowser/Chrome runs headless by default — no window, purely background
12
12
 
13
13
  ## Install
14
14
 
@@ -40,7 +40,7 @@ greedy_search({
40
40
  maxSources: 8,
41
41
  });
42
42
  // Research mode writes a dataroom-style bundle under .dm/greedysearch-research/ by default.
43
- // Headless is the default — no window. To force visible Chrome:
43
+ // Headless is the default — no window. To force visible browser:
44
44
  greedy_search({ query: "Visible browser setup", engine: "perplexity", visible: true });
45
45
  ```
46
46
 
@@ -50,8 +50,8 @@ greedy_search({ query: "Visible browser setup", engine: "perplexity", visible: t
50
50
 
51
51
  - `query` (required)
52
52
  - `fullAnswer`: return full single-engine output instead of preview
53
- - `headless`: set to `false` to show Chrome window (default: `true`)
54
- - `visible` / `alwaysVisible`: set to `true` to always use visible Chrome for this search
53
+ - `headless`: set to `false` to show a browser window (default: `true`)
54
+ - `visible` / `alwaysVisible`: set to `true` to always use a visible browser for this search
55
55
 
56
56
  ### Normal search
57
57
 
@@ -75,11 +75,14 @@ Deep research uses the configured `~/.dm/greedyconfig.engines` list for child se
75
75
 
76
76
  | Variable | Default | Description |
77
77
  | ------------------------------------ | ------------- | ------------------------------------------------------------- |
78
- | `GREEDY_SEARCH_VISIBLE` | (unset) | Set to `1` to show Chrome window instead of headless |
79
- | `GREEDY_SEARCH_ALWAYS_VISIBLE` | (unset) | Set to `1` to force visible Chrome for all GreedySearch runs |
80
- | `GREEDY_SEARCH_IDLE_TIMEOUT_MINUTES` | `5` | Minutes of inactivity before auto-killing GreedySearch Chrome |
78
+ | `GREEDY_SEARCH_VISIBLE` | (unset) | Set to `1` to show a browser window instead of headless |
79
+ | `GREEDY_SEARCH_ALWAYS_VISIBLE` | (unset) | Set to `1` to force visible browser for all GreedySearch runs |
80
+ | `GREEDY_SEARCH_IDLE_TIMEOUT_MINUTES` | `5` | Minutes of inactivity before auto-killing GreedySearch browser |
81
81
  | `GREEDY_SEARCH_LOCALE` | `en` | Default result language (en, de, fr, es, ja, etc.) |
82
- | `CHROME_PATH` | auto-detected | Path to Chrome/Chromium executable |
82
+ | `GREEDY_SEARCH_BROWSER` / `DM_CUA_BROWSER` | `auto` | `auto`, `cloak`, or `chrome`; auto prefers CloakBrowser when installed |
83
+ | `GREEDY_SEARCH_BROWSER_PATH` / `DM_CUA_BROWSER_PATH` | (unset) | Explicit browser executable override |
84
+ | `DM_CUA_CLOAK_PATH` / `CLOAKBROWSER_BINARY_PATH` | (unset) | Explicit CloakBrowser executable; DM does not bundle the binary |
85
+ | `CHROME_PATH` | auto-detected | Path to Chrome/Chromium executable fallback |
83
86
 
84
87
  ## Search modes
85
88
 
@@ -133,9 +136,9 @@ node bin/search.mjs all "topic" --depth research --no-research-bundle
133
136
  Inside DM, prefer the extension commands (no package path needed):
134
137
 
135
138
  ```text
136
- /greedy-visible # launch visible Chrome for captcha/login/cookie setup
137
- /greedy-status # show GreedySearch Chrome status
138
- /greedy-kill # stop GreedySearch Chrome
139
+ /greedy-visible # launch visible browser for captcha/login/cookie setup
140
+ /greedy-status # show GreedySearch browser status
141
+ /greedy-kill # stop GreedySearch browser
139
142
  /set-greedy-locale # set default result language (de, fr, es, ja, etc.)
140
143
  ```
141
144
 
@@ -147,9 +150,9 @@ node "$GS/bin/launch.mjs" --status
147
150
  node "$GS/bin/visible.mjs" # visible mode
148
151
  node "$GS/bin/visible.mjs" --kill # strong visible/port cleanup
149
152
  node "$GS/bin/kill-visible.mjs" # same as visible.mjs --kill
150
- node "$GS/bin/cdp-visible.mjs" list # safe CDP: GreedySearch visible Chrome only
151
- node "$GS/bin/cdp-headless.mjs" list # safe CDP: GreedySearch headless Chrome only
152
- node "$GS/bin/cdp-greedy.mjs" list # safe CDP: any GreedySearch Chrome mode
153
+ node "$GS/bin/cdp-visible.mjs" list # safe CDP: GreedySearch visible browser only
154
+ node "$GS/bin/cdp-headless.mjs" list # safe CDP: GreedySearch headless browser only
155
+ node "$GS/bin/cdp-greedy.mjs" list # safe CDP: any GreedySearch browser mode
153
156
  ```
154
157
 
155
158
  npm global install path:
@@ -165,13 +168,13 @@ node "$GS/bin/cdp-headless.mjs" list
165
168
  node "$GS/bin/cdp-greedy.mjs" list
166
169
  ```
167
170
 
168
- Chrome is auto-cleaned after 5 min idle. Override with `GREEDY_SEARCH_IDLE_TIMEOUT_MINUTES=10` or disable with `0`.
171
+ GreedySearch browser is auto-cleaned after 5 min idle. Override with `GREEDY_SEARCH_IDLE_TIMEOUT_MINUTES=10` or disable with `0`.
169
172
 
170
- **CDP safety:** use `cdp-visible.mjs`, `cdp-headless.mjs`, or `cdp-greedy.mjs` for debugging. They always set `CDP_PROFILE_DIR` to the dedicated GreedySearch Chrome profile and never fall back to your main Chrome session. Avoid calling raw `bin/cdp.mjs` manually unless you explicitly set `CDP_PROFILE_DIR`.
173
+ **CDP safety:** use `cdp-visible.mjs`, `cdp-headless.mjs`, or `cdp-greedy.mjs` for debugging. They always set `CDP_PROFILE_DIR` to the dedicated GreedySearch browser profile and never fall back to your main browser session. Avoid calling raw `bin/cdp.mjs` manually unless you explicitly set `CDP_PROFILE_DIR`.
171
174
 
172
175
  ## Requirements
173
176
 
174
- - Chrome
177
+ - CloakBrowser or Chrome/Chromium
175
178
  - Node.js 20.11.0+
176
179
 
177
180
  ## Source fetching
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import{execSync as q,spawn as b}from"node:child_process";import{existsSync as Z,mkdirSync as f,readFileSync as K,unlinkSync as R,writeFileSync as U}from"node:fs";import D from"node:http";import{platform as j,tmpdir as w}from"node:os";import{join as _}from"node:path";var g=w().replaceAll("\\","/"),Q=9222,C=_(w(),"greedysearch-chrome-profile"),$=`${g}/greedysearch-chrome.pid`,V=`${g}/greedysearch-chrome-mode`;function u(){let z=j();return(z==="win32"?["C:/Program Files/Google/Chrome/Application/chrome.exe","C:/Program Files (x86)/Google/Chrome/Application/chrome.exe"]:z==="darwin"?["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"]:["/usr/bin/google-chrome","/usr/bin/google-chrome-stable","/usr/bin/chromium-browser","/usr/bin/chromium"]).find(Z)||null}function W(){return new Promise((z)=>{let A=D.get(`http://localhost:${Q}/json/version`,(G)=>{let J="";G.on("data",(N)=>J+=N),G.on("end",()=>z({ok:!0,body:J}))});A.on("error",()=>z({ok:!1})),A.setTimeout(2000,()=>{A.destroy(),z({ok:!1})})})}function x(z){try{if(j()==="win32"){let G=q("netstat -ano -p TCP 2>nul",{encoding:"utf8"}),J=new RegExp(String.raw`TCP\s+\S+:${z}\s+\S+:0\s+LISTENING\s+(\d+)`,"i");return(G.match(J)||[])[1]?parseInt(G.match(J)[1]):null}let A=q(`lsof -i :${z} -t 2>/dev/null || ss -tlnp 2>/dev/null | grep :${z} | grep -oP 'pid=\\K\\d+'`,{encoding:"utf8"}).trim();return A?parseInt(A.split(`
3
- `)[0]):null}catch{return null}}function T(){let z=x(Q);if(!z)return!1;try{if(j()==="win32")q(`taskkill /F /PID ${z}`,{stdio:"ignore"});else process.kill(z,"SIGKILL");return!0}catch{return!1}}function v(){for(let z of[$,V])try{R(z)}catch{}}async function L(){let{ok:z,body:A}=await W();if(!z){console.log("Not running.");return}let G=Z(V)?K(V,"utf8").trim():"unknown",J=Z($)?K($,"utf8").trim():"none",N=x(Q)||"unknown",{Browser:Y}=JSON.parse(A);console.log(`Running: ${Y}`),console.log(` Mode: ${G}`),console.log(` Port: ${Q}`),console.log(` PID file: ${J}`),console.log(` PID actual:${N}`)}async function O(){let{ok:z}=await W();if(!z){console.log("Not running — nothing to kill."),v();return}console.log("Killing Chrome on port 9222..."),T(),v(),await new Promise((G)=>setTimeout(G,1500));let{ok:A}=await W();console.log(A?"FAILED — still running.":"Killed.")}async function k(z){let{ok:A}=await W();if(A){let X=Z(V)?K(V,"utf8").trim():"unknown";if(X===z){console.log(`Already running in ${z} mode.`);return}console.log(`${X} Chrome running — killing to switch to ${z}...`),T(),v(),await new Promise((B)=>setTimeout(B,1500))}let G=process.env.CHROME_PATH||u();if(!G)console.error("Chrome not found."),process.exit(1);let J=z==="headless",N=[`--remote-debugging-port=${Q}`,"--disable-features=DevToolsPrivacyUI","--no-first-run","--no-default-browser-check","--disable-default-apps","--disable-blink-features=AutomationControlled","--window-size=1920,1080",`--user-data-dir=${C}`,"--profile-directory=Default"];if(J){if(N.push("--headless=new","--disable-gpu","--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"),j()==="win32")N.push("--disable-software-rasterizer")}N.push("about:blank"),f(C,{recursive:!0}),console.log(`Launching ${z} Chrome on port ${Q}...`);let Y=b(G,N,{detached:!0,stdio:"ignore"});Y.unref(),U($,String(Y.pid)),U(V,z);for(let X=0;X<30;X++){await new Promise((H)=>setTimeout(H,500));let{ok:B}=await W();if(B){try{let{body:H}=await W(),{webSocketDebuggerUrl:h}=JSON.parse(H),M=new URL(h).pathname;U(`${C}/DevToolsActivePort`,`${Q}
4
- ${M}`)}catch{}console.log("Ready.");return}}console.error("Timeout — Chrome did not become ready."),process.exit(1)}var S=process.argv[2];switch(S){case"launch-headless":await k("headless");break;case"launch-visible":await k("visible");break;case"kill":await O();break;case"status":await L();break;default:console.log(`Usage: node bin/gschrome.mjs <command>
2
+ import{execSync as s,spawn as e}from"node:child_process";import{existsSync as R,mkdirSync as N,readFileSync as m,unlinkSync as z,writeFileSync as H}from"node:fs";import J from"node:http";import{platform as f,tmpdir as x}from"node:os";import{join as Q}from"node:path";import{existsSync as w}from"node:fs";import{platform as W}from"node:os";function M(o=W()){if(o==="win32")return{cloak:["C:/Program Files/CloakBrowser/CloakBrowser.exe","C:/Program Files (x86)/CloakBrowser/CloakBrowser.exe"],chrome:["C:/Program Files/Google/Chrome/Application/chrome.exe","C:/Program Files (x86)/Google/Chrome/Application/chrome.exe"]};if(o==="darwin")return{cloak:["/Applications/CloakBrowser.app/Contents/MacOS/CloakBrowser","/Applications/Cloak Browser.app/Contents/MacOS/CloakBrowser"],chrome:["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome","/Applications/Chromium.app/Contents/MacOS/Chromium"]};return{cloak:["/usr/bin/cloakbrowser","/usr/local/bin/cloakbrowser","/opt/CloakBrowser/CloakBrowser"],chrome:["/usr/bin/google-chrome","/usr/bin/google-chrome-stable","/usr/bin/chromium-browser","/usr/bin/chromium","/snap/bin/chromium"]}}function c(o,r=w){return o.find((C)=>C&&r(C))||null}function T(o,r){for(let C of r){let a=o[C]?.trim();if(a)return{key:C,path:a}}return null}function b(o,r){if(o==="chrome"||r==="CHROME_PATH")return"Chrome";if(o==="cloak"||r==="DM_CUA_CLOAK_PATH"||r==="CLOAKBROWSER_BINARY_PATH")return"CloakBrowser";return"browser"}function G({env:o=process.env,platformName:r=W(),exists:C=w}={}){let a=(o.GREEDY_SEARCH_BROWSER||o.DM_CUA_BROWSER||"auto").toLowerCase(),h=T(o,a==="chrome"?["GREEDY_SEARCH_BROWSER_PATH","DM_CUA_BROWSER_PATH","CHROME_PATH"]:["GREEDY_SEARCH_BROWSER_PATH","DM_CUA_BROWSER_PATH","DM_CUA_CLOAK_PATH","CLOAKBROWSER_BINARY_PATH","CHROME_PATH"]);if(h)return{path:h.path,label:b(a,h.key)};let n=M(r);if(a==="cloak")return{path:c(n.cloak,C),label:"CloakBrowser"};if(a==="chrome")return{path:c(n.chrome,C),label:"Chrome"};let l=c(n.cloak,C);return{path:l||c(n.chrome,C),label:l?"CloakBrowser":"Chrome"}}var Y=x().replaceAll("\\","/"),i=9222,_=Q(x(),"greedysearch-chrome-profile"),u=`${Y}/greedysearch-chrome.pid`,t=`${Y}/greedysearch-chrome-mode`;function B(){return new Promise((o)=>{let r=J.get(`http://localhost:${i}/json/version`,(C)=>{let a="";C.on("data",(A)=>a+=A),C.on("end",()=>o({ok:!0,body:a}))});r.on("error",()=>o({ok:!1})),r.setTimeout(2000,()=>{r.destroy(),o({ok:!1})})})}function U(o){try{if(f()==="win32"){let C=s("netstat -ano -p TCP 2>nul",{encoding:"utf8"}),a=new RegExp(String.raw`TCP\s+\S+:${o}\s+\S+:0\s+LISTENING\s+(\d+)`,"i");return(C.match(a)||[])[1]?parseInt(C.match(a)[1]):null}let r=s(`lsof -i :${o} -t 2>/dev/null || ss -tlnp 2>/dev/null | grep :${o} | grep -oP 'pid=\\K\\d+'`,{encoding:"utf8"}).trim();return r?parseInt(r.split(`
3
+ `)[0]):null}catch{return null}}function K(){let o=U(i);if(!o)return!1;try{if(f()==="win32")s(`taskkill /F /PID ${o}`,{stdio:"ignore"});else process.kill(o,"SIGKILL");return!0}catch{return!1}}function p(){for(let o of[u,t])try{z(o)}catch{}}async function S(){let{ok:o,body:r}=await B();if(!o){console.log("Not running.");return}let C=R(t)?m(t,"utf8").trim():"unknown",a=R(u)?m(u,"utf8").trim():"none",A=U(i)||"unknown",{Browser:h}=JSON.parse(r);console.log(`Running: ${h}`),console.log(` Mode: ${C}`),console.log(` Port: ${i}`),console.log(` PID file: ${a}`),console.log(` PID actual:${A}`)}async function V(){let{ok:o}=await B();if(!o){console.log("Not running — nothing to kill."),p();return}console.log("Killing browser on port 9222..."),K(),p(),await new Promise((C)=>setTimeout(C,1500));let{ok:r}=await B();console.log(r?"FAILED — still running.":"Killed.")}async function g(o){let{ok:r}=await B();if(r){let n=R(t)?m(t,"utf8").trim():"unknown";if(n===o){console.log(`Already running in ${o} mode.`);return}console.log(`${n} browser running — killing to switch to ${o}...`),K(),p(),await new Promise((l)=>setTimeout(l,1500))}let C=G();if(!C.path)console.error("CloakBrowser/Chrome not found. Set GREEDY_SEARCH_BROWSER_PATH, DM_CUA_BROWSER_PATH, DM_CUA_CLOAK_PATH, CLOAKBROWSER_BINARY_PATH, or CHROME_PATH."),process.exit(1);let a=o==="headless",A=[`--remote-debugging-port=${i}`,"--disable-features=DevToolsPrivacyUI","--no-first-run","--no-default-browser-check","--disable-default-apps","--disable-blink-features=AutomationControlled","--window-size=1920,1080",`--user-data-dir=${_}`,"--profile-directory=Default"];if(a){if(A.push("--headless=new","--disable-gpu","--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"),f()==="win32")A.push("--disable-software-rasterizer")}A.push("about:blank"),N(_,{recursive:!0}),console.log(`Launching ${o} ${C.label} on port ${i}...`);let h=e(C.path,A,{detached:!0,stdio:"ignore"});h.unref(),H(u,String(h.pid)),H(t,o);for(let n=0;n<30;n++){await new Promise((k)=>setTimeout(k,500));let{ok:l}=await B();if(l){try{let{body:k}=await B(),{webSocketDebuggerUrl:O}=JSON.parse(k),E=new URL(O).pathname;H(`${_}/DevToolsActivePort`,`${i}
4
+ ${E}`)}catch{}console.log("Ready.");return}}console.error("Timeout — Chrome did not become ready."),process.exit(1)}var X=process.argv[2];switch(X){case"launch-headless":await g("headless");break;case"launch-visible":await g("visible");break;case"kill":await V();break;case"status":await S();break;default:console.log(`Usage: node bin/gschrome.mjs <command>
5
5
 
6
6
  Commands:
7
7
  launch-headless Start headless Chrome on port 9222
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{execSync as h,spawn as Kj}from"node:child_process";import{existsSync as P,mkdirSync as Qj,readFileSync as m,unlinkSync as N,writeFileSync as _}from"node:fs";import Yj from"node:http";import{platform as b,tmpdir as U}from"node:os";import{join as B}from"node:path";import{existsSync as g,mkdirSync as u,readFileSync as D,renameSync as v,unlinkSync as c,writeFileSync as f}from"node:fs";import p from"node:http";import{platform as E}from"node:os";import{dirname as l}from"node:path";var k=[9222,9223],a=/^(0|false|no|off)$/i;function d(j){return[...new Set(j.filter(Boolean))]}function x(j,z="localhost"){let J=String(j||"").trim().split(/\r?\n/).map((Y)=>Y.trim()).filter(Boolean);if(J.length===0)throw Error("empty DevToolsActivePort");let[Q,K=""]=J;if(/^wss?:\/\//i.test(Q))return Q;if(Q.includes(":"))return`ws://${Q}${K}`;return`ws://${z}:${Q}${K}`}function S(j,z="explicit"){let J=new URL(j),Q=J.protocol==="wss:"?"wss:":"ws:",K=J.port?Number.parseInt(J.port,10):Q==="wss:"?443:80;return{source:z,wsUrl:`${Q}//${J.host}${J.pathname}${J.search}`,host:J.hostname,port:K,path:`${J.pathname}${J.search}`,httpUrl:`http://${J.hostname}:${K}`}}function y(j=process.env){return![j.GREEDY_SEARCH_REUSE_EXISTING_BROWSER,j.DM_CUA_REUSE_EXISTING_BROWSER].some((z)=>z!==void 0&&a.test(String(z)))}function H(j){let z=Number.parseInt(String(j??""),10);return Number.isInteger(z)&&z>0&&z<65536?z:null}function n(j){if(!j)return null;let z=String(j).trim();if(!z)return null;let J=new URL(z.includes("://")?z:`http://${z}`),Q=H(J.port)||(J.protocol==="https:"?443:80);return{host:J.hostname,port:Q,source:`env:${z}`}}function i(j){if(!j)return[];return String(j).split(/[,\s]+/).map(H).filter(Boolean)}function s({env:j=process.env,platformName:z=E(),procVersionText:J=null}={}){if(z!=="linux")return!1;if(j.WSL_DISTRO_NAME||j.WSL_INTEROP)return!0;let Q=J??(()=>{try{return D("/proc/version","utf8")}catch{return""}})();return/microsoft|wsl/i.test(Q)}function r({env:j=process.env,platformName:z=E(),procVersionText:J=null,resolvConfText:Q=null}={}){let K=["localhost","127.0.0.1"];if(s({env:j,platformName:z,procVersionText:J})){let I=(Q??(()=>{try{return D("/etc/resolv.conf","utf8")}catch{return""}})()).match(/^\s*nameserver\s+([^\s#]+)/m);if(I)K.push(I[1]);K.push("host.docker.internal")}return d(K)}function o({env:j=process.env,hosts:z=r({env:j}),autoPorts:J=k,excludePorts:Q=[]}={}){let K=[];for(let Z of["GREEDY_SEARCH_CDP_WS_URL","DM_CUA_CDP_WS_URL","CDP_WS_URL"])if(j[Z])K.push({wsUrl:j[Z],source:`env:${Z}`});for(let Z of["GREEDY_SEARCH_CDP_URL","DM_CUA_CDP_URL","CDP_URL"])try{let X=n(j[Z]);if(X)K.push(X)}catch{}for(let Z of["GREEDY_SEARCH_EXISTING_CDP_PORT","DM_CUA_EXISTING_CDP_PORT","GREEDY_SEARCH_CDP_PORT","DM_CUA_CDP_PORT"]){let X=H(j[Z]);if(!X)continue;for(let A of z)K.push({host:A,port:X,source:`env:${Z}`})}let Y=i(j.GREEDY_SEARCH_EXISTING_CDP_PORTS);for(let Z of Y)for(let X of z)K.push({host:X,port:Z,source:"env:GREEDY_SEARCH_EXISTING_CDP_PORTS"});let I=new Set(Q.filter(Boolean));if(y(j))for(let Z of J){if(I.has(Z))continue;for(let X of z)K.push({host:X,port:Z,source:"auto"})}let $=new Set;return K.filter((Z)=>{let X=Z.wsUrl||`${Z.host}:${Z.port}`;if($.has(X))return!1;return $.add(X),!0})}async function t(j,{timeoutMs:z=700}={}){if(j.wsUrl)return S(j.wsUrl,j.source);let J=j.host||"localhost",Q=j.port;if(!Q)return null;let K=await new Promise((Y)=>{let I=p.get({host:J,port:Q,path:"/json/version",timeout:z},($)=>{let Z="";$.setEncoding("utf8"),$.on("data",(X)=>Z+=X),$.on("end",()=>Y($.statusCode===200?Z:null))});I.on("error",()=>Y(null)),I.setTimeout(z,()=>{I.destroy(),Y(null)})});if(!K)return null;try{let Y=JSON.parse(K);if(!Y.webSocketDebuggerUrl)return null;let I=S(Y.webSocketDebuggerUrl,j.source),$=I.path||new URL(Y.webSocketDebuggerUrl).pathname;return{...I,host:J,port:Q,httpUrl:`http://${J}:${Q}`,wsUrl:`ws://${J}:${Q}${$}`,path:$}}catch{return null}}async function e(j={}){for(let z of o(j)){let J=await t(z,j);if(J)return J}return null}function jj(j){if(!j)throw Error("missing CDP endpoint");let z=new URL(j.wsUrl);return`${z.host}
3
- ${z.pathname}${z.search}
4
- `}function zj(j,z){u(l(j),{recursive:!0});let J=`${j}.tmp-${process.pid}`;f(J,jj(z),"utf8");try{c(j)}catch{}v(J,j)}async function w({activePortFile:j,modeFile:z,env:J=process.env,excludePorts:Q=[],autoPorts:K=k}={}){if(!y(J))return null;let Y=await e({env:J,excludePorts:Q,autoPorts:K});if(!Y)return null;if(zj(j,Y),z)f(z,"existing","utf8");return Y}function Jj(j){return String(j||"").trim()==="existing"}function q(j,z){if(!z||!g(z))return!1;if(!Jj(D(z,"utf8")))return!1;return!!j&&g(j)}var G=9222,C=B(U(),"greedysearch-chrome-profile"),W=B(C,"DevToolsActivePort"),V=B(U(),"greedysearch-chrome.pid"),L=B(U(),"greedysearch-chrome-mode");function Zj(){let j=b();return(j==="win32"?["C:/Program Files/Google/Chrome/Application/chrome.exe","C:/Program Files (x86)/Google/Chrome/Application/chrome.exe"]:j==="darwin"?["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome","/Applications/Chromium.app/Contents/MacOS/Chromium"]:["/usr/bin/google-chrome","/usr/bin/google-chrome-stable","/usr/bin/chromium-browser","/usr/bin/chromium"]).find(P)||null}function O(){if(!P(V))return!1;let j=Number.parseInt(m(V,"utf8").trim(),10);if(!j)return!1;try{return process.kill(j,0),j}catch{return!1}}function M(j){try{if(b()==="win32"){let J=h("netstat -ano -p TCP 2>nul",{encoding:"utf8"}),Q=new RegExp(String.raw`TCP\s+[^\s]*:${j}\s+[^\s]*:0\s+LISTENING\s+(\d+)`,"i"),K=J.match(Q);return K?Number.parseInt(K[1],10):null}}catch{return null}}function R(j){try{if(b()==="win32")h(`taskkill /F /PID ${j} /T`,{stdio:"ignore"});else process.kill(j,"SIGKILL");return!0}catch{return!1}}function T(j,z=1000){return new Promise((J)=>{let Q=Yj.get(j,(K)=>{let Y="";K.on("data",(I)=>Y+=I),K.on("end",()=>J({ok:K.statusCode===200,body:Y}))});Q.on("error",()=>J({ok:!1})),Q.setTimeout(z,()=>{Q.destroy(),J({ok:!1})})})}async function $j(j){try{let z=await T(`http://localhost:${j}/json/version`).then((Z)=>JSON.parse(Z.body)),Q=(await T(`http://localhost:${j}/json/list`).then((Z)=>JSON.parse(Z.body))).find((Z)=>Z.type==="page")?.id;if(!Q)return;let K=z.webSocketDebuggerUrl;if(typeof K!=="string")return;let Y=new URL(K);if(Y.hostname!=="localhost"&&Y.hostname!=="127.0.0.1")return;if(!/^ws:\/\/localhost:\d+/.test(`ws://${Y.host}`))return;let I=Y.pathname,$=new WebSocket(`ws://localhost:${j}${I}`);await new Promise((Z)=>{$.onopen=()=>$.send(JSON.stringify({id:1,method:"Browser.getWindowForTarget",params:{targetId:Q}})),$.onmessage=(X)=>{let A=JSON.parse(X.data);if(A.id===1&&A.result?.windowId)$.send(JSON.stringify({id:2,method:"Browser.setWindowBounds",params:{windowId:A.result.windowId,bounds:{windowState:"minimized"}}}));else if(A.id===2)$.close(),Z()},$.onerror=()=>{$.close(),Z()},setTimeout(()=>{try{$.close()}catch{}Z()},5000)})}catch{}}async function Ij(j=15000){let z=Date.now()+j;while(Date.now()<z){let{ok:J,body:Q}=await T(`http://localhost:${G}/json/version`,1500);if(J)try{let{webSocketDebuggerUrl:K}=JSON.parse(Q),Y=new URL(K),I=`${Y.pathname}${Y.search}`;return _(W,`localhost:${G}
5
- ${I}`,"utf8"),!0}catch{}await new Promise((K)=>setTimeout(K,400))}return!1}function F(){let j=O();if(j)R(j);let z=M(G);if(z&&z!==j)R(z);try{N(V)}catch{}try{N(W)}catch{}try{N(L)}catch{}return new Promise((J)=>{let Q=Date.now(),K=()=>{let Y=M(G);if(!Y)return J(!0);if(Date.now()-Q>5000)return J(!1);R(Y),setTimeout(K,500)};K()})}async function Xj(){let j=process.argv[2];if(j==="--kill"){if(q(W,L)){try{N(W)}catch{}try{N(L)}catch{}console.log("Detached from existing browser CDP endpoint; no browser process was killed.");return}await F(),console.log("Chrome stopped.");return}if(j==="--status"){if(q(W,L)){try{let Z=x(m(W,"utf8"));console.log(`Reusing existing browser — ${Z}`)}catch{console.log("Reusing existing browser.")}return}let $=O()||M(G);if($)console.log(`Running — pid ${$}, port ${G}`);else console.log("Not running.");return}let z=await w({activePortFile:W,modeFile:L,excludePorts:O()?[G]:[],autoPorts:O()?[9223]:[G,9223]});if(z){console.log(`Reusing existing browser CDP endpoint ${z.httpUrl} (${z.source}).`);return}console.log("Stopping any existing Chrome on port 9222..."),await F();let J=process.env.CHROME_PATH||Zj();if(!J)console.error("Chrome not found. Set CHROME_PATH env var."),process.exit(1);Qj(C,{recursive:!0});let Q=[`--remote-debugging-port=${G}`,"--disable-features=DevToolsPrivacyUI","--no-first-run","--no-default-browser-check","--disable-default-apps",`--user-data-dir=${C}`,"--profile-directory=Default","--new-window","about:blank"];console.log("Launching visible Chrome...");let K=Kj(J,Q,{detached:!0,stdio:"ignore"});K.unref();let Y=K.pid;if(_(V,String(Y)),_(L,"visible","utf8"),console.log(`Chrome PID: ${Y}`),!await Ij())console.error("Chrome did not become ready within 15s."),process.exit(1);await $j(G),console.log("Visible Chrome ready on port 9222."),console.log("Keep this terminal open to keep Chrome alive.")}Xj();
2
+ import{execSync as c,spawn as YC}from"node:child_process";import{existsSync as EC,mkdirSync as GC,readFileSync as u,unlinkSync as L,writeFileSync as f}from"node:fs";import MC from"node:http";import{platform as p,tmpdir as N}from"node:os";import{join as J}from"node:path";import{existsSync as V,mkdirSync as l,readFileSync as Q,renameSync as a,unlinkSync as v,writeFileSync as h}from"node:fs";import o from"node:http";import{platform as S}from"node:os";import{dirname as n}from"node:path";var q=[9222,9223],r=/^(0|false|no|off)$/i;function i(C){return[...new Set(C.filter(Boolean))]}function m(C,A="localhost"){let _=String(C||"").trim().split(/\r?\n/).map((O)=>O.trim()).filter(Boolean);if(_.length===0)throw Error("empty DevToolsActivePort");let[R,B=""]=_;if(/^wss?:\/\//i.test(R))return R;if(R.includes(":"))return`ws://${R}${B}`;return`ws://${A}:${R}${B}`}function b(C,A="explicit"){let _=new URL(C),R=_.protocol==="wss:"?"wss:":"ws:",B=_.port?Number.parseInt(_.port,10):R==="wss:"?443:80;return{source:A,wsUrl:`${R}//${_.host}${_.pathname}${_.search}`,host:_.hostname,port:B,path:`${_.pathname}${_.search}`,httpUrl:`http://${_.hostname}:${B}`}}function U(C=process.env){return![C.GREEDY_SEARCH_REUSE_EXISTING_BROWSER,C.DM_CUA_REUSE_EXISTING_BROWSER].some((A)=>A!==void 0&&r.test(String(A)))}function X(C){let A=Number.parseInt(String(C??""),10);return Number.isInteger(A)&&A>0&&A<65536?A:null}function s(C){if(!C)return null;let A=String(C).trim();if(!A)return null;let _=new URL(A.includes("://")?A:`http://${A}`),R=X(_.port)||(_.protocol==="https:"?443:80);return{host:_.hostname,port:R,source:`env:${A}`}}function d(C){if(!C)return[];return String(C).split(/[,\s]+/).map(X).filter(Boolean)}function t({env:C=process.env,platformName:A=S(),procVersionText:_=null}={}){if(A!=="linux")return!1;if(C.WSL_DISTRO_NAME||C.WSL_INTEROP)return!0;let R=_??(()=>{try{return Q("/proc/version","utf8")}catch{return""}})();return/microsoft|wsl/i.test(R)}function e({env:C=process.env,platformName:A=S(),procVersionText:_=null,resolvConfText:R=null}={}){let B=["localhost","127.0.0.1"];if(t({env:C,platformName:A,procVersionText:_})){let W=(R??(()=>{try{return Q("/etc/resolv.conf","utf8")}catch{return""}})()).match(/^\s*nameserver\s+([^\s#]+)/m);if(W)B.push(W[1]);B.push("host.docker.internal")}return i(B)}function CC({env:C=process.env,hosts:A=e({env:C}),autoPorts:_=q,excludePorts:R=[]}={}){let B=[];for(let H of["GREEDY_SEARCH_CDP_WS_URL","DM_CUA_CDP_WS_URL","CDP_WS_URL"])if(C[H])B.push({wsUrl:C[H],source:`env:${H}`});for(let H of["GREEDY_SEARCH_CDP_URL","DM_CUA_CDP_URL","CDP_URL"])try{let Y=s(C[H]);if(Y)B.push(Y)}catch{}for(let H of["GREEDY_SEARCH_EXISTING_CDP_PORT","DM_CUA_EXISTING_CDP_PORT","GREEDY_SEARCH_CDP_PORT","DM_CUA_CDP_PORT"]){let Y=X(C[H]);if(!Y)continue;for(let M of A)B.push({host:M,port:Y,source:`env:${H}`})}let O=d(C.GREEDY_SEARCH_EXISTING_CDP_PORTS);for(let H of O)for(let Y of A)B.push({host:Y,port:H,source:"env:GREEDY_SEARCH_EXISTING_CDP_PORTS"});let W=new Set(R.filter(Boolean));if(U(C))for(let H of _){if(W.has(H))continue;for(let Y of A)B.push({host:Y,port:H,source:"auto"})}let K=new Set;return B.filter((H)=>{let Y=H.wsUrl||`${H.host}:${H.port}`;if(K.has(Y))return!1;return K.add(Y),!0})}async function AC(C,{timeoutMs:A=700}={}){if(C.wsUrl)return b(C.wsUrl,C.source);let _=C.host||"localhost",R=C.port;if(!R)return null;let B=await new Promise((O)=>{let W=o.get({host:_,port:R,path:"/json/version",timeout:A},(K)=>{let H="";K.setEncoding("utf8"),K.on("data",(Y)=>H+=Y),K.on("end",()=>O(K.statusCode===200?H:null))});W.on("error",()=>O(null)),W.setTimeout(A,()=>{W.destroy(),O(null)})});if(!B)return null;try{let O=JSON.parse(B);if(!O.webSocketDebuggerUrl)return null;let W=b(O.webSocketDebuggerUrl,C.source),K=W.path||new URL(O.webSocketDebuggerUrl).pathname;return{...W,host:_,port:R,httpUrl:`http://${_}:${R}`,wsUrl:`ws://${_}:${R}${K}`,path:K}}catch{return null}}async function _C(C={}){for(let A of CC(C)){let _=await AC(A,C);if(_)return _}return null}function RC(C){if(!C)throw Error("missing CDP endpoint");let A=new URL(C.wsUrl);return`${A.host}
3
+ ${A.pathname}${A.search}
4
+ `}function BC(C,A){l(n(C),{recursive:!0});let _=`${C}.tmp-${process.pid}`;h(_,RC(A),"utf8");try{v(C)}catch{}a(_,C)}async function x({activePortFile:C,modeFile:A,env:_=process.env,excludePorts:R=[],autoPorts:B=q}={}){if(!U(_))return null;let O=await _C({env:_,excludePorts:R,autoPorts:B});if(!O)return null;if(BC(C,O),A)h(A,"existing","utf8");return O}function OC(C){return String(C||"").trim()==="existing"}function Z(C,A){if(!A||!V(A))return!1;if(!OC(Q(A,"utf8")))return!1;return!!C&&V(C)}import{existsSync as w}from"node:fs";import{platform as y}from"node:os";function HC(C=y()){if(C==="win32")return{cloak:["C:/Program Files/CloakBrowser/CloakBrowser.exe","C:/Program Files (x86)/CloakBrowser/CloakBrowser.exe"],chrome:["C:/Program Files/Google/Chrome/Application/chrome.exe","C:/Program Files (x86)/Google/Chrome/Application/chrome.exe"]};if(C==="darwin")return{cloak:["/Applications/CloakBrowser.app/Contents/MacOS/CloakBrowser","/Applications/Cloak Browser.app/Contents/MacOS/CloakBrowser"],chrome:["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome","/Applications/Chromium.app/Contents/MacOS/Chromium"]};return{cloak:["/usr/bin/cloakbrowser","/usr/local/bin/cloakbrowser","/opt/CloakBrowser/CloakBrowser"],chrome:["/usr/bin/google-chrome","/usr/bin/google-chrome-stable","/usr/bin/chromium-browser","/usr/bin/chromium","/snap/bin/chromium"]}}function j(C,A=w){return C.find((_)=>_&&A(_))||null}function KC(C,A){for(let _ of A){let R=C[_]?.trim();if(R)return{key:_,path:R}}return null}function WC(C,A){if(C==="chrome"||A==="CHROME_PATH")return"Chrome";if(C==="cloak"||A==="DM_CUA_CLOAK_PATH"||A==="CLOAKBROWSER_BINARY_PATH")return"CloakBrowser";return"browser"}function P({env:C=process.env,platformName:A=y(),exists:_=w}={}){let R=(C.GREEDY_SEARCH_BROWSER||C.DM_CUA_BROWSER||"auto").toLowerCase(),O=KC(C,R==="chrome"?["GREEDY_SEARCH_BROWSER_PATH","DM_CUA_BROWSER_PATH","CHROME_PATH"]:["GREEDY_SEARCH_BROWSER_PATH","DM_CUA_BROWSER_PATH","DM_CUA_CLOAK_PATH","CLOAKBROWSER_BINARY_PATH","CHROME_PATH"]);if(O)return{path:O.path,label:WC(R,O.key)};let W=HC(A);if(R==="cloak")return{path:j(W.cloak,_),label:"CloakBrowser"};if(R==="chrome")return{path:j(W.chrome,_),label:"Chrome"};let K=j(W.cloak,_);return{path:K||j(W.chrome,_),label:K?"CloakBrowser":"Chrome"}}var E=9222,k=J(N(),"greedysearch-chrome-profile"),G=J(k,"DevToolsActivePort"),I=J(N(),"greedysearch-chrome.pid"),D=J(N(),"greedysearch-chrome-mode");function z(){if(!EC(I))return!1;let C=Number.parseInt(u(I,"utf8").trim(),10);if(!C)return!1;try{return process.kill(C,0),C}catch{return!1}}function T(C){try{if(p()==="win32"){let _=c("netstat -ano -p TCP 2>nul",{encoding:"utf8"}),R=new RegExp(String.raw`TCP\s+[^\s]*:${C}\s+[^\s]*:0\s+LISTENING\s+(\d+)`,"i"),B=_.match(R);return B?Number.parseInt(B[1],10):null}}catch{return null}}function $(C){try{if(p()==="win32")c(`taskkill /F /PID ${C} /T`,{stdio:"ignore"});else process.kill(C,"SIGKILL");return!0}catch{return!1}}function g(C,A=1000){return new Promise((_)=>{let R=MC.get(C,(B)=>{let O="";B.on("data",(W)=>O+=W),B.on("end",()=>_({ok:B.statusCode===200,body:O}))});R.on("error",()=>_({ok:!1})),R.setTimeout(A,()=>{R.destroy(),_({ok:!1})})})}async function DC(C){try{let A=await g(`http://localhost:${C}/json/version`).then((H)=>JSON.parse(H.body)),R=(await g(`http://localhost:${C}/json/list`).then((H)=>JSON.parse(H.body))).find((H)=>H.type==="page")?.id;if(!R)return;let B=A.webSocketDebuggerUrl;if(typeof B!=="string")return;let O=new URL(B);if(O.hostname!=="localhost"&&O.hostname!=="127.0.0.1")return;if(!/^ws:\/\/localhost:\d+/.test(`ws://${O.host}`))return;let W=O.pathname,K=new WebSocket(`ws://localhost:${C}${W}`);await new Promise((H)=>{K.onopen=()=>K.send(JSON.stringify({id:1,method:"Browser.getWindowForTarget",params:{targetId:R}})),K.onmessage=(Y)=>{let M=JSON.parse(Y.data);if(M.id===1&&M.result?.windowId)K.send(JSON.stringify({id:2,method:"Browser.setWindowBounds",params:{windowId:M.result.windowId,bounds:{windowState:"minimized"}}}));else if(M.id===2)K.close(),H()},K.onerror=()=>{K.close(),H()},setTimeout(()=>{try{K.close()}catch{}H()},5000)})}catch{}}async function LC(C=15000){let A=Date.now()+C;while(Date.now()<A){let{ok:_,body:R}=await g(`http://localhost:${E}/json/version`,1500);if(_)try{let{webSocketDebuggerUrl:B}=JSON.parse(R),O=new URL(B),W=`${O.pathname}${O.search}`;return f(G,`localhost:${E}
5
+ ${W}`,"utf8"),!0}catch{}await new Promise((B)=>setTimeout(B,400))}return!1}function F(){let C=z();if(C)$(C);let A=T(E);if(A&&A!==C)$(A);try{L(I)}catch{}try{L(G)}catch{}try{L(D)}catch{}return new Promise((_)=>{let R=Date.now(),B=()=>{let O=T(E);if(!O)return _(!0);if(Date.now()-R>5000)return _(!1);$(O),setTimeout(B,500)};B()})}async function jC(){let C=process.argv[2];if(C==="--kill"){if(Z(G,D)){try{L(G)}catch{}try{L(D)}catch{}console.log("Detached from existing browser CDP endpoint; no browser process was killed.");return}await F(),console.log("Browser stopped.");return}if(C==="--status"){if(Z(G,D)){try{let H=m(u(G,"utf8"));console.log(`Reusing existing browser — ${H}`)}catch{console.log("Reusing existing browser.")}return}let K=z()||T(E);if(K)console.log(`Running — pid ${K}, port ${E}`);else console.log("Not running.");return}let A=await x({activePortFile:G,modeFile:D,excludePorts:z()?[E]:[],autoPorts:z()?[9223]:[E,9223]});if(A){console.log(`Reusing existing browser CDP endpoint ${A.httpUrl} (${A.source}).`);return}console.log("Stopping any existing browser on port 9222..."),await F();let _=P();if(!_.path)console.error("CloakBrowser/Chrome not found. Set GREEDY_SEARCH_BROWSER_PATH, DM_CUA_BROWSER_PATH, DM_CUA_CLOAK_PATH, CLOAKBROWSER_BINARY_PATH, or CHROME_PATH."),process.exit(1);GC(k,{recursive:!0});let R=[`--remote-debugging-port=${E}`,"--disable-features=DevToolsPrivacyUI","--no-first-run","--no-default-browser-check","--disable-default-apps",`--user-data-dir=${k}`,"--profile-directory=Default","--new-window","about:blank"];console.log(`Launching visible ${_.label}...`);let B=YC(_.path,R,{detached:!0,stdio:"ignore"});B.unref();let O=B.pid;if(f(I,String(O)),f(D,"visible","utf8"),console.log(`${_.label} PID: ${O}`),!await LC())console.error(`${_.label} did not become ready within 15s.`),process.exit(1);await DC(E),console.log(`Visible ${_.label} ready on port 9222.`),console.log(`Keep this terminal open to keep ${_.label} alive.`)}jC();
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import{execSync as R,spawn as Lz}from"node:child_process";import{existsSync as b,mkdirSync as l,readdirSync as Nz,readFileSync as S,unlinkSync as A,writeFileSync as T}from"node:fs";import a from"node:http";import{platform as I,tmpdir as f}from"node:os";import{join as D}from"node:path";import{existsSync as g,mkdirSync as i,readFileSync as q,renameSync as r,unlinkSync as o,writeFileSync as k}from"node:fs";import t from"node:http";import{platform as F}from"node:os";import{dirname as e}from"node:path";var w=[9222,9223],zz=/^(0|false|no|off)$/i;function Jz(z){return[...new Set(z.filter(Boolean))]}function h(z,J="localhost"){let K=String(z||"").trim().split(/\r?\n/).map((Y)=>Y.trim()).filter(Boolean);if(K.length===0)throw Error("empty DevToolsActivePort");let[Q,X=""]=K;if(/^wss?:\/\//i.test(Q))return Q;if(Q.includes(":"))return`ws://${Q}${X}`;return`ws://${J}:${Q}${X}`}function y(z,J="explicit"){let K=new URL(z),Q=K.protocol==="wss:"?"wss:":"ws:",X=K.port?Number.parseInt(K.port,10):Q==="wss:"?443:80;return{source:J,wsUrl:`${Q}//${K.host}${K.pathname}${K.search}`,host:K.hostname,port:X,path:`${K.pathname}${K.search}`,httpUrl:`http://${K.hostname}:${X}`}}function P(z=process.env){return![z.GREEDY_SEARCH_REUSE_EXISTING_BROWSER,z.DM_CUA_REUSE_EXISTING_BROWSER].some((J)=>J!==void 0&&zz.test(String(J)))}function U(z){let J=Number.parseInt(String(z??""),10);return Number.isInteger(J)&&J>0&&J<65536?J:null}function Kz(z){if(!z)return null;let J=String(z).trim();if(!J)return null;let K=new URL(J.includes("://")?J:`http://${J}`),Q=U(K.port)||(K.protocol==="https:"?443:80);return{host:K.hostname,port:Q,source:`env:${J}`}}function Qz(z){if(!z)return[];return String(z).split(/[,\s]+/).map(U).filter(Boolean)}function Xz({env:z=process.env,platformName:J=F(),procVersionText:K=null}={}){if(J!=="linux")return!1;if(z.WSL_DISTRO_NAME||z.WSL_INTEROP)return!0;let Q=K??(()=>{try{return q("/proc/version","utf8")}catch{return""}})();return/microsoft|wsl/i.test(Q)}function Yz({env:z=process.env,platformName:J=F(),procVersionText:K=null,resolvConfText:Q=null}={}){let X=["localhost","127.0.0.1"];if(Xz({env:z,platformName:J,procVersionText:K})){let G=(Q??(()=>{try{return q("/etc/resolv.conf","utf8")}catch{return""}})()).match(/^\s*nameserver\s+([^\s#]+)/m);if(G)X.push(G[1]);X.push("host.docker.internal")}return Jz(X)}function Zz({env:z=process.env,hosts:J=Yz({env:z}),autoPorts:K=w,excludePorts:Q=[]}={}){let X=[];for(let $ of["GREEDY_SEARCH_CDP_WS_URL","DM_CUA_CDP_WS_URL","CDP_WS_URL"])if(z[$])X.push({wsUrl:z[$],source:`env:${$}`});for(let $ of["GREEDY_SEARCH_CDP_URL","DM_CUA_CDP_URL","CDP_URL"])try{let O=Kz(z[$]);if(O)X.push(O)}catch{}for(let $ of["GREEDY_SEARCH_EXISTING_CDP_PORT","DM_CUA_EXISTING_CDP_PORT","GREEDY_SEARCH_CDP_PORT","DM_CUA_CDP_PORT"]){let O=U(z[$]);if(!O)continue;for(let W of J)X.push({host:W,port:O,source:`env:${$}`})}let Y=Qz(z.GREEDY_SEARCH_EXISTING_CDP_PORTS);for(let $ of Y)for(let O of J)X.push({host:O,port:$,source:"env:GREEDY_SEARCH_EXISTING_CDP_PORTS"});let G=new Set(Q.filter(Boolean));if(P(z))for(let $ of K){if(G.has($))continue;for(let O of J)X.push({host:O,port:$,source:"auto"})}let Z=new Set;return X.filter(($)=>{let O=$.wsUrl||`${$.host}:${$.port}`;if(Z.has(O))return!1;return Z.add(O),!0})}async function $z(z,{timeoutMs:J=700}={}){if(z.wsUrl)return y(z.wsUrl,z.source);let K=z.host||"localhost",Q=z.port;if(!Q)return null;let X=await new Promise((Y)=>{let G=t.get({host:K,port:Q,path:"/json/version",timeout:J},(Z)=>{let $="";Z.setEncoding("utf8"),Z.on("data",(O)=>$+=O),Z.on("end",()=>Y(Z.statusCode===200?$:null))});G.on("error",()=>Y(null)),G.setTimeout(J,()=>{G.destroy(),Y(null)})});if(!X)return null;try{let Y=JSON.parse(X);if(!Y.webSocketDebuggerUrl)return null;let G=y(Y.webSocketDebuggerUrl,z.source),Z=G.path||new URL(Y.webSocketDebuggerUrl).pathname;return{...G,host:K,port:Q,httpUrl:`http://${K}:${Q}`,wsUrl:`ws://${K}:${Q}${Z}`,path:Z}}catch{return null}}async function Gz(z={}){for(let J of Zz(z)){let K=await $z(J,z);if(K)return K}return null}function Oz(z){if(!z)throw Error("missing CDP endpoint");let J=new URL(z.wsUrl);return`${J.host}
2
+ import{execSync as R,spawn as Lz}from"node:child_process";import{existsSync as b,mkdirSync as l,readdirSync as Nz,readFileSync as S,unlinkSync as A,writeFileSync as T}from"node:fs";import d from"node:http";import{platform as I,tmpdir as f}from"node:os";import{join as D}from"node:path";import{existsSync as g,mkdirSync as r,readFileSync as q,renameSync as i,unlinkSync as o,writeFileSync as k}from"node:fs";import t from"node:http";import{platform as F}from"node:os";import{dirname as e}from"node:path";var w=[9222,9223],zz=/^(0|false|no|off)$/i;function Jz(z){return[...new Set(z.filter(Boolean))]}function h(z,J="localhost"){let K=String(z||"").trim().split(/\r?\n/).map((Y)=>Y.trim()).filter(Boolean);if(K.length===0)throw Error("empty DevToolsActivePort");let[Q,X=""]=K;if(/^wss?:\/\//i.test(Q))return Q;if(Q.includes(":"))return`ws://${Q}${X}`;return`ws://${J}:${Q}${X}`}function y(z,J="explicit"){let K=new URL(z),Q=K.protocol==="wss:"?"wss:":"ws:",X=K.port?Number.parseInt(K.port,10):Q==="wss:"?443:80;return{source:J,wsUrl:`${Q}//${K.host}${K.pathname}${K.search}`,host:K.hostname,port:X,path:`${K.pathname}${K.search}`,httpUrl:`http://${K.hostname}:${X}`}}function P(z=process.env){return![z.GREEDY_SEARCH_REUSE_EXISTING_BROWSER,z.DM_CUA_REUSE_EXISTING_BROWSER].some((J)=>J!==void 0&&zz.test(String(J)))}function U(z){let J=Number.parseInt(String(z??""),10);return Number.isInteger(J)&&J>0&&J<65536?J:null}function Kz(z){if(!z)return null;let J=String(z).trim();if(!J)return null;let K=new URL(J.includes("://")?J:`http://${J}`),Q=U(K.port)||(K.protocol==="https:"?443:80);return{host:K.hostname,port:Q,source:`env:${J}`}}function Qz(z){if(!z)return[];return String(z).split(/[,\s]+/).map(U).filter(Boolean)}function Xz({env:z=process.env,platformName:J=F(),procVersionText:K=null}={}){if(J!=="linux")return!1;if(z.WSL_DISTRO_NAME||z.WSL_INTEROP)return!0;let Q=K??(()=>{try{return q("/proc/version","utf8")}catch{return""}})();return/microsoft|wsl/i.test(Q)}function Yz({env:z=process.env,platformName:J=F(),procVersionText:K=null,resolvConfText:Q=null}={}){let X=["localhost","127.0.0.1"];if(Xz({env:z,platformName:J,procVersionText:K})){let G=(Q??(()=>{try{return q("/etc/resolv.conf","utf8")}catch{return""}})()).match(/^\s*nameserver\s+([^\s#]+)/m);if(G)X.push(G[1]);X.push("host.docker.internal")}return Jz(X)}function Zz({env:z=process.env,hosts:J=Yz({env:z}),autoPorts:K=w,excludePorts:Q=[]}={}){let X=[];for(let $ of["GREEDY_SEARCH_CDP_WS_URL","DM_CUA_CDP_WS_URL","CDP_WS_URL"])if(z[$])X.push({wsUrl:z[$],source:`env:${$}`});for(let $ of["GREEDY_SEARCH_CDP_URL","DM_CUA_CDP_URL","CDP_URL"])try{let O=Kz(z[$]);if(O)X.push(O)}catch{}for(let $ of["GREEDY_SEARCH_EXISTING_CDP_PORT","DM_CUA_EXISTING_CDP_PORT","GREEDY_SEARCH_CDP_PORT","DM_CUA_CDP_PORT"]){let O=U(z[$]);if(!O)continue;for(let W of J)X.push({host:W,port:O,source:`env:${$}`})}let Y=Qz(z.GREEDY_SEARCH_EXISTING_CDP_PORTS);for(let $ of Y)for(let O of J)X.push({host:O,port:$,source:"env:GREEDY_SEARCH_EXISTING_CDP_PORTS"});let G=new Set(Q.filter(Boolean));if(P(z))for(let $ of K){if(G.has($))continue;for(let O of J)X.push({host:O,port:$,source:"auto"})}let Z=new Set;return X.filter(($)=>{let O=$.wsUrl||`${$.host}:${$.port}`;if(Z.has(O))return!1;return Z.add(O),!0})}async function $z(z,{timeoutMs:J=700}={}){if(z.wsUrl)return y(z.wsUrl,z.source);let K=z.host||"localhost",Q=z.port;if(!Q)return null;let X=await new Promise((Y)=>{let G=t.get({host:K,port:Q,path:"/json/version",timeout:J},(Z)=>{let $="";Z.setEncoding("utf8"),Z.on("data",(O)=>$+=O),Z.on("end",()=>Y(Z.statusCode===200?$:null))});G.on("error",()=>Y(null)),G.setTimeout(J,()=>{G.destroy(),Y(null)})});if(!X)return null;try{let Y=JSON.parse(X);if(!Y.webSocketDebuggerUrl)return null;let G=y(Y.webSocketDebuggerUrl,z.source),Z=G.path||new URL(Y.webSocketDebuggerUrl).pathname;return{...G,host:K,port:Q,httpUrl:`http://${K}:${Q}`,wsUrl:`ws://${K}:${Q}${Z}`,path:Z}}catch{return null}}async function Gz(z={}){for(let J of Zz(z)){let K=await $z(J,z);if(K)return K}return null}function Oz(z){if(!z)throw Error("missing CDP endpoint");let J=new URL(z.wsUrl);return`${J.host}
3
3
  ${J.pathname}${J.search}
4
- `}function jz(z,J){i(e(z),{recursive:!0});let K=`${z}.tmp-${process.pid}`;k(K,Oz(J),"utf8");try{o(z)}catch{}r(K,z)}async function m({activePortFile:z,modeFile:J,env:K=process.env,excludePorts:Q=[],autoPorts:X=w}={}){if(!P(K))return null;let Y=await Gz({env:K,excludePorts:Q,autoPorts:X});if(!Y)return null;if(jz(z,Y),J)k(J,"existing","utf8");return Y}function Az(z){return String(z||"").trim()==="existing"}function C(z,J){if(!J||!g(J))return!1;if(!Az(q(J,"utf8")))return!1;return!!z&&g(z)}function Vz(z,J){let K=Number.parseInt(String(z??""),10);return Number.isInteger(K)&&K>1024&&K<65535?K:J}var j=Vz(process.env.GREEDY_SEARCH_PORT,9222),H=process.env.GREEDY_SEARCH_PROFILE_DIR||process.env.CDP_PROFILE_DIR||D(f(),"greedysearch-chrome-profile"),N=D(H,"DevToolsActivePort"),V=process.env.GREEDY_SEARCH_PID_FILE||D(f(),"greedysearch-chrome.pid"),L=process.env.GREEDY_SEARCH_MODE_FILE||D(f(),"greedysearch-chrome-mode"),Wz=/^(1|true|yes|on)$/i.test(process.env.GREEDY_SEARCH_ALLOW_PORT_CLEANUP??"1");function d(z){return z.find((J)=>J&&b(J))||null}function v(){let z=I();return d(z==="win32"?["C:/Program Files/CloakBrowser/CloakBrowser.exe","C:/Program Files (x86)/CloakBrowser/CloakBrowser.exe"]:z==="darwin"?["/Applications/CloakBrowser.app/Contents/MacOS/CloakBrowser","/Applications/Cloak Browser.app/Contents/MacOS/CloakBrowser"]:["/usr/bin/cloakbrowser","/usr/local/bin/cloakbrowser","/opt/CloakBrowser/CloakBrowser"])}function u(){let z=I();return d(z==="win32"?["C:/Program Files/Google/Chrome/Application/chrome.exe","C:/Program Files (x86)/Google/Chrome/Application/chrome.exe"]:z==="darwin"?["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome","/Applications/Chromium.app/Contents/MacOS/Chromium"]:["/usr/bin/google-chrome","/usr/bin/google-chrome-stable","/usr/bin/chromium-browser","/usr/bin/chromium","/snap/bin/chromium"])}function _z(){let z=(process.env.GREEDY_SEARCH_BROWSER||process.env.DM_CUA_BROWSER||"auto").toLowerCase(),J=process.env.GREEDY_SEARCH_BROWSER_PATH||process.env.DM_CUA_BROWSER_PATH||process.env.DM_CUA_CLOAK_PATH||process.env.CLOAKBROWSER_BINARY_PATH||process.env.CHROME_PATH;if(J)return{path:J,label:z==="chrome"?"Chrome":z==="cloak"?"CloakBrowser":"browser"};if(z==="cloak")return{path:v(),label:"CloakBrowser"};if(z==="chrome")return{path:u(),label:"Chrome"};let K=v();return{path:K||u(),label:K?"CloakBrowser":"Chrome"}}var B=()=>process.env.GREEDY_SEARCH_VISIBLE!=="1",Bz=[`--remote-debugging-port=${j}`,"--disable-features=DevToolsPrivacyUI","--no-first-run","--no-default-browser-check","--disable-default-apps","--disable-blink-features=AutomationControlled",`--user-data-dir=${H}`,"--profile-directory=Default","--window-size=1920,1080","--lang=en-US","--force-color-profile=srgb","--disable-background-timer-throttling","--disable-renderer-backgrounding","--disable-backgrounding-occluded-windows"];function Dz(z){try{let J=D(z,".."),Q=Nz(J).find((X)=>/^\d{1,10}\.\d{1,10}\.\d{1,10}\.\d{1,10}$/.test(X));if(Q)return Q.split(".")[0]}catch{}try{let K=R(`"${z}" --version`,{encoding:"utf8",timeout:5000}).trim().match(/(\d{1,10})\.\d{1,10}\.\d{1,10}/);if(K)return K[1]}catch{}return null}function Rz(z){let J=[...Bz];if(B()){J.push("--headless=new");let K=Dz(z)||"136";J.push(`--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${K}.0.0.0 Safari/537.36`)}return J.push("about:blank"),J}var Iz=()=>process.env.GREEDY_SEARCH_VISIBLE==="1";function Hz(){try{if(!b(L))return!0;return S(L,"utf8").trim()==="headless"}catch{return!0}}async function Mz(){if(B())return;try{let z=await new Promise((G,Z)=>{a.get(`http://localhost:${j}/json/version`,($)=>{let O="";$.on("data",(W)=>O+=W),$.on("end",()=>G(JSON.parse(O)))}).on("error",Z)}),J=new URL(z.webSocketDebuggerUrl).pathname,K=globalThis.WebSocket;if(!K)return;let Q=new K(`ws://localhost:${j}${J}`),X=0,Y=new Map;Q.onopen=()=>{let G=++X;Y.set(G,{resolve:(Z)=>{let O=(Z.targetInfos||[]).find((M)=>M.type==="page");if(!O){Q.close();return}let W=++X;Y.set(W,{resolve:(M)=>{let n=M.windowId,x=++X;Y.set(x,{resolve:()=>{},reject:()=>{}}),Q.send(JSON.stringify({id:x,method:"Browser.setWindowBounds",params:{windowId:n,bounds:{windowState:"minimized"}}})),setTimeout(()=>Q.close(),500)},reject:()=>Q.close()}),Q.send(JSON.stringify({id:W,method:"Browser.getWindowForTarget",params:{targetId:O.targetId}}))},reject:()=>Q.close()}),Q.send(JSON.stringify({id:G,method:"Target.getTargets",params:{}}))},Q.onmessage=(G)=>{let Z=JSON.parse(G.data);if(Z.id&&Y.has(Z.id)){let{resolve:$,reject:O}=Y.get(Z.id);if(Y.delete(Z.id),Z.error)O?.(Z.error);else $?.(Z.result)}},setTimeout(()=>Q.close(),5000)}catch{}}function _(){if(!b(V))return!1;let z=Number.parseInt(S(V,"utf8").trim(),10);if(!z)return!1;try{return process.kill(z,0),z}catch{return!1}}function s(z){try{if(I()==="win32"){let Q=R("netstat -ano -p TCP 2>nul",{encoding:"utf8"}),X=new RegExp(String.raw`TCP\s+[^\s]*:${z}\s+[^\s]*:0\s+LISTENING\s+(\d+)`,"i"),Y=Q.match(X);return Y?Number.parseInt(Y[1],10):null}let K=R(String.raw`lsof -i :${z} -t 2>/dev/null || ss -tlnp 2>/dev/null | grep :${z} | grep -oP 'pid=\K\d+'`,{encoding:"utf8"}).trim();return K?Number.parseInt(K.split(`
5
- `)[0],10):null}catch{return null}}function E(z){try{if(I()==="win32")R(`taskkill /F /T /PID ${z}`,{stdio:"ignore"});else process.kill(z,"SIGTERM");return!0}catch{return!1}}function p(){let z=s(j);if(!z)return;let J=_();if(J&&z===J)return;if(!Wz)console.error(`Browser/CDP port ${j} is already owned by untracked pid ${z}; refusing to kill it. Set GREEDY_SEARCH_PORT or DM_CUA_PORT to a free port.`),process.exit(1);console.log(`Ghost browser on port ${j} (pid ${z}) — cleaning up...`),E(z);try{A(V)}catch{}try{A(N)}catch{}try{A(L)}catch{}}function qz(z,J=1000){return new Promise((K)=>{let Q=a.get(z,(X)=>{let Y="";X.on("data",(G)=>Y+=G),X.on("end",()=>K({ok:X.statusCode===200,body:Y}))});Q.on("error",()=>K({ok:!1})),Q.setTimeout(J,()=>{Q.destroy(),K({ok:!1})})})}async function c(z=15000){let J=Date.now()+z;while(Date.now()<J){let{ok:K,body:Q}=await qz(`http://localhost:${j}/json/version`,1500);if(K)try{let{webSocketDebuggerUrl:X}=JSON.parse(Q),Y=new URL(X),G=`${Y.pathname}${Y.search}`;return l(H,{recursive:!0}),T(N,`localhost:${j}
6
- ${G}`,"utf8"),!0}catch{}await new Promise((X)=>setTimeout(X,400))}return!1}async function Uz(){let z=process.argv[2];if(z==="--kill"){if(C(N,L)){try{A(N)}catch{}try{A(L)}catch{}console.log("Detached from existing browser CDP endpoint; no browser process was killed.");return}p();let Z=_()||s(j);if(Z){let $=E(Z);console.log($?`Stopped browser (pid ${Z}).`:`Failed to stop pid ${Z}.`)}else console.log("GreedySearch browser is not running.");try{A(V)}catch{}try{A(N)}catch{}try{A(L)}catch{}return}if(z==="--status"){if(C(N,L)){try{let $=h(S(N,"utf8"));console.log(`Reusing existing browser — ${$}`)}catch{console.log("Reusing existing browser.")}return}let Z=_();if(Z)console.log(`Running — pid ${Z}, port ${j}`);else console.log("Not running.");return}let J=_(),K=await m({activePortFile:N,modeFile:L,excludePorts:J?[j]:[],autoPorts:J?[9223]:[j,9223]});if(K){console.log(`Reusing existing browser CDP endpoint ${K.httpUrl} (${K.source}).`);return}p();let Q=_();if(Q)if(process.env.GREEDY_SEARCH_VISIBLE==="1"&&!process.argv.includes("--headless")&&Hz()){console.log(`Headless browser running (pid ${Q}) but visible requested — killing...`),E(Q);try{A(V)}catch{}try{A(L)}catch{}}else{if(await c(5000)){console.log(`GreedySearch browser already running (pid ${Q}).`);return}console.log(`Stale PID ${Q} — launching fresh.`);try{A(V)}catch{}}let X=_z();if(!X.path)console.error("CloakBrowser/Chrome not found. Set GREEDY_SEARCH_BROWSER_PATH, DM_CUA_BROWSER_PATH, DM_CUA_CLOAK_PATH, CLOAKBROWSER_BINARY_PATH, or CHROME_PATH."),process.exit(1);if(l(H,{recursive:!0}),console.log(`Launching GreedySearch ${X.label} on port ${j}...`),B())console.log("Headless mode — no window will be shown");else if(!Iz())console.log("Window will be minimized");let Y=Lz(X.path,Rz(X.path),{detached:!0,stdio:"ignore"});if(Y.unref(),T(V,String(Y.pid)),T(L,B()?"headless":"visible","utf8"),!await c())console.error(`${X.label} did not become ready within 15s.`),process.exit(1);if(B())console.log("Ready (headless).");else await Mz(),console.log("Ready.")}Uz();
4
+ `}function jz(z,J){r(e(z),{recursive:!0});let K=`${z}.tmp-${process.pid}`;k(K,Oz(J),"utf8");try{o(z)}catch{}i(K,z)}async function m({activePortFile:z,modeFile:J,env:K=process.env,excludePorts:Q=[],autoPorts:X=w}={}){if(!P(K))return null;let Y=await Gz({env:K,excludePorts:Q,autoPorts:X});if(!Y)return null;if(jz(z,Y),J)k(J,"existing","utf8");return Y}function Az(z){return String(z||"").trim()==="existing"}function C(z,J){if(!J||!g(J))return!1;if(!Az(q(J,"utf8")))return!1;return!!z&&g(z)}function Vz(z,J){let K=Number.parseInt(String(z??""),10);return Number.isInteger(K)&&K>1024&&K<65535?K:J}var j=Vz(process.env.GREEDY_SEARCH_PORT,9222),H=process.env.GREEDY_SEARCH_PROFILE_DIR||process.env.CDP_PROFILE_DIR||D(f(),"greedysearch-chrome-profile"),N=D(H,"DevToolsActivePort"),V=process.env.GREEDY_SEARCH_PID_FILE||D(f(),"greedysearch-chrome.pid"),L=process.env.GREEDY_SEARCH_MODE_FILE||D(f(),"greedysearch-chrome-mode"),Wz=/^(1|true|yes|on)$/i.test(process.env.GREEDY_SEARCH_ALLOW_PORT_CLEANUP??"1");function a(z){return z.find((J)=>J&&b(J))||null}function v(){let z=I();return a(z==="win32"?["C:/Program Files/CloakBrowser/CloakBrowser.exe","C:/Program Files (x86)/CloakBrowser/CloakBrowser.exe"]:z==="darwin"?["/Applications/CloakBrowser.app/Contents/MacOS/CloakBrowser","/Applications/Cloak Browser.app/Contents/MacOS/CloakBrowser"]:["/usr/bin/cloakbrowser","/usr/local/bin/cloakbrowser","/opt/CloakBrowser/CloakBrowser"])}function u(){let z=I();return a(z==="win32"?["C:/Program Files/Google/Chrome/Application/chrome.exe","C:/Program Files (x86)/Google/Chrome/Application/chrome.exe"]:z==="darwin"?["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome","/Applications/Chromium.app/Contents/MacOS/Chromium"]:["/usr/bin/google-chrome","/usr/bin/google-chrome-stable","/usr/bin/chromium-browser","/usr/bin/chromium","/snap/bin/chromium"])}function _z(){let z=(process.env.GREEDY_SEARCH_BROWSER||process.env.DM_CUA_BROWSER||"auto").toLowerCase(),J=process.env.GREEDY_SEARCH_BROWSER_PATH||process.env.DM_CUA_BROWSER_PATH||process.env.DM_CUA_CLOAK_PATH||process.env.CLOAKBROWSER_BINARY_PATH||process.env.CHROME_PATH;if(J){let Q=J===process.env.DM_CUA_CLOAK_PATH||J===process.env.CLOAKBROWSER_BINARY_PATH,X=J===process.env.CHROME_PATH;return{path:J,label:z==="chrome"||X?"Chrome":z==="cloak"||Q?"CloakBrowser":"browser"}}if(z==="cloak")return{path:v(),label:"CloakBrowser"};if(z==="chrome")return{path:u(),label:"Chrome"};let K=v();return{path:K||u(),label:K?"CloakBrowser":"Chrome"}}var B=()=>process.env.GREEDY_SEARCH_VISIBLE!=="1",Bz=[`--remote-debugging-port=${j}`,"--disable-features=DevToolsPrivacyUI","--no-first-run","--no-default-browser-check","--disable-default-apps","--disable-blink-features=AutomationControlled",`--user-data-dir=${H}`,"--profile-directory=Default","--window-size=1920,1080","--lang=en-US","--force-color-profile=srgb","--disable-background-timer-throttling","--disable-renderer-backgrounding","--disable-backgrounding-occluded-windows"];function Dz(z){try{let J=D(z,".."),Q=Nz(J).find((X)=>/^\d{1,10}\.\d{1,10}\.\d{1,10}\.\d{1,10}$/.test(X));if(Q)return Q.split(".")[0]}catch{}try{let K=R(`"${z}" --version`,{encoding:"utf8",timeout:5000}).trim().match(/(\d{1,10})\.\d{1,10}\.\d{1,10}/);if(K)return K[1]}catch{}return null}function Rz(z){let J=[...Bz];if(B()){J.push("--headless=new");let K=Dz(z)||"136";J.push(`--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${K}.0.0.0 Safari/537.36`)}return J.push("about:blank"),J}var Iz=()=>process.env.GREEDY_SEARCH_VISIBLE==="1";function Hz(){try{if(!b(L))return!0;return S(L,"utf8").trim()==="headless"}catch{return!0}}async function Mz(){if(B())return;try{let z=await new Promise((G,Z)=>{d.get(`http://localhost:${j}/json/version`,($)=>{let O="";$.on("data",(W)=>O+=W),$.on("end",()=>G(JSON.parse(O)))}).on("error",Z)}),J=new URL(z.webSocketDebuggerUrl).pathname,K=globalThis.WebSocket;if(!K)return;let Q=new K(`ws://localhost:${j}${J}`),X=0,Y=new Map;Q.onopen=()=>{let G=++X;Y.set(G,{resolve:(Z)=>{let O=(Z.targetInfos||[]).find((M)=>M.type==="page");if(!O){Q.close();return}let W=++X;Y.set(W,{resolve:(M)=>{let s=M.windowId,x=++X;Y.set(x,{resolve:()=>{},reject:()=>{}}),Q.send(JSON.stringify({id:x,method:"Browser.setWindowBounds",params:{windowId:s,bounds:{windowState:"minimized"}}})),setTimeout(()=>Q.close(),500)},reject:()=>Q.close()}),Q.send(JSON.stringify({id:W,method:"Browser.getWindowForTarget",params:{targetId:O.targetId}}))},reject:()=>Q.close()}),Q.send(JSON.stringify({id:G,method:"Target.getTargets",params:{}}))},Q.onmessage=(G)=>{let Z=JSON.parse(G.data);if(Z.id&&Y.has(Z.id)){let{resolve:$,reject:O}=Y.get(Z.id);if(Y.delete(Z.id),Z.error)O?.(Z.error);else $?.(Z.result)}},setTimeout(()=>Q.close(),5000)}catch{}}function _(){if(!b(V))return!1;let z=Number.parseInt(S(V,"utf8").trim(),10);if(!z)return!1;try{return process.kill(z,0),z}catch{return!1}}function n(z){try{if(I()==="win32"){let Q=R("netstat -ano -p TCP 2>nul",{encoding:"utf8"}),X=new RegExp(String.raw`TCP\s+[^\s]*:${z}\s+[^\s]*:0\s+LISTENING\s+(\d+)`,"i"),Y=Q.match(X);return Y?Number.parseInt(Y[1],10):null}let K=R(String.raw`lsof -i :${z} -t 2>/dev/null || ss -tlnp 2>/dev/null | grep :${z} | grep -oP 'pid=\K\d+'`,{encoding:"utf8"}).trim();return K?Number.parseInt(K.split(`
5
+ `)[0],10):null}catch{return null}}function E(z){try{if(I()==="win32")R(`taskkill /F /T /PID ${z}`,{stdio:"ignore"});else process.kill(z,"SIGTERM");return!0}catch{return!1}}function p(){let z=n(j);if(!z)return;let J=_();if(J&&z===J)return;if(!Wz)console.error(`Browser/CDP port ${j} is already owned by untracked pid ${z}; refusing to kill it. Set GREEDY_SEARCH_PORT or DM_CUA_PORT to a free port.`),process.exit(1);console.log(`Ghost browser on port ${j} (pid ${z}) — cleaning up...`),E(z);try{A(V)}catch{}try{A(N)}catch{}try{A(L)}catch{}}function qz(z,J=1000){return new Promise((K)=>{let Q=d.get(z,(X)=>{let Y="";X.on("data",(G)=>Y+=G),X.on("end",()=>K({ok:X.statusCode===200,body:Y}))});Q.on("error",()=>K({ok:!1})),Q.setTimeout(J,()=>{Q.destroy(),K({ok:!1})})})}async function c(z=15000){let J=Date.now()+z;while(Date.now()<J){let{ok:K,body:Q}=await qz(`http://localhost:${j}/json/version`,1500);if(K)try{let{webSocketDebuggerUrl:X}=JSON.parse(Q),Y=new URL(X),G=`${Y.pathname}${Y.search}`;return l(H,{recursive:!0}),T(N,`localhost:${j}
6
+ ${G}`,"utf8"),!0}catch{}await new Promise((X)=>setTimeout(X,400))}return!1}async function Uz(){let z=process.argv[2];if(z==="--kill"){if(C(N,L)){try{A(N)}catch{}try{A(L)}catch{}console.log("Detached from existing browser CDP endpoint; no browser process was killed.");return}p();let Z=_()||n(j);if(Z){let $=E(Z);console.log($?`Stopped browser (pid ${Z}).`:`Failed to stop pid ${Z}.`)}else console.log("GreedySearch browser is not running.");try{A(V)}catch{}try{A(N)}catch{}try{A(L)}catch{}return}if(z==="--status"){if(C(N,L)){try{let $=h(S(N,"utf8"));console.log(`Reusing existing browser — ${$}`)}catch{console.log("Reusing existing browser.")}return}let Z=_();if(Z)console.log(`Running — pid ${Z}, port ${j}`);else console.log("Not running.");return}let J=_(),K=await m({activePortFile:N,modeFile:L,excludePorts:J?[j]:[],autoPorts:J?[9223]:[j,9223]});if(K){console.log(`Reusing existing browser CDP endpoint ${K.httpUrl} (${K.source}).`);return}p();let Q=_();if(Q)if(process.env.GREEDY_SEARCH_VISIBLE==="1"&&!process.argv.includes("--headless")&&Hz()){console.log(`Headless browser running (pid ${Q}) but visible requested — killing...`),E(Q);try{A(V)}catch{}try{A(L)}catch{}}else{if(await c(5000)){console.log(`GreedySearch browser already running (pid ${Q}).`);return}console.log(`Stale PID ${Q} — launching fresh.`);try{A(V)}catch{}}let X=_z();if(!X.path)console.error("CloakBrowser/Chrome not found. Set GREEDY_SEARCH_BROWSER_PATH, DM_CUA_BROWSER_PATH, DM_CUA_CLOAK_PATH, CLOAKBROWSER_BINARY_PATH, or CHROME_PATH."),process.exit(1);if(l(H,{recursive:!0}),console.log(`Launching GreedySearch ${X.label} on port ${j}...`),B())console.log("Headless mode — no window will be shown");else if(!Iz())console.log("Window will be minimized");let Y=Lz(X.path,Rz(X.path),{detached:!0,stdio:"ignore"});if(Y.unref(),T(V,String(Y.pid)),T(L,B()?"headless":"visible","utf8"),!await c())console.error(`${X.label} did not become ready within 15s.`),process.exit(1);if(B())console.log("Ready (headless).");else await Mz(),console.log("Ready.")}Uz();