@duckmind/dm-windows-x64 0.52.3 → 0.53.1

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.
Files changed (57) hide show
  1. package/README.md +17 -0
  2. package/dm.exe +0 -0
  3. package/extensions/.dm-extensions.json +15 -8
  4. package/extensions/dm-cua/bin/browser-cua.mjs +6 -6
  5. package/extensions/dm-cua/index.js +5 -5
  6. package/extensions/dm-cua/src/browser-cua-lib.mjs +2 -2
  7. package/extensions/greedysearch-dm/bin/cdp-greedy.mjs +8 -1
  8. package/extensions/greedysearch-dm/bin/cdp-headless.mjs +1 -1
  9. package/extensions/greedysearch-dm/bin/cdp-visible.mjs +1 -1
  10. package/extensions/greedysearch-dm/bin/cdp.mjs +29 -20
  11. package/extensions/greedysearch-dm/bin/gschrome.mjs +1 -10
  12. package/extensions/greedysearch-dm/bin/kill-visible.mjs +1 -1
  13. package/extensions/greedysearch-dm/bin/launch-visible.mjs +1 -4
  14. package/extensions/greedysearch-dm/bin/launch.mjs +9 -5
  15. package/extensions/greedysearch-dm/bin/mcp.mjs +375 -0
  16. package/extensions/greedysearch-dm/bin/search.mjs +310 -156
  17. package/extensions/greedysearch-dm/bin/visible.mjs +1 -1
  18. package/extensions/greedysearch-dm/extractors/bing-copilot.mjs +205 -68
  19. package/extensions/greedysearch-dm/extractors/chatgpt.mjs +229 -140
  20. package/extensions/greedysearch-dm/extractors/common.mjs +160 -50
  21. package/extensions/greedysearch-dm/extractors/consensus.mjs +225 -92
  22. package/extensions/greedysearch-dm/extractors/consent.mjs +44 -17
  23. package/extensions/greedysearch-dm/extractors/gemini.mjs +275 -136
  24. package/extensions/greedysearch-dm/extractors/google-ai.mjs +172 -64
  25. package/extensions/greedysearch-dm/extractors/logically.mjs +183 -69
  26. package/extensions/greedysearch-dm/extractors/perplexity.mjs +331 -65
  27. package/extensions/greedysearch-dm/extractors/semantic-scholar.mjs +118 -41
  28. package/extensions/greedysearch-dm/index.js +20 -17
  29. package/extensions/greedysearch-dm/package.json +8 -3
  30. package/extensions/greedysearch-dm/skills/greedy-search/skill.md +8 -8
  31. package/extensions/greedysearch-dm/src/fetcher.mjs +2 -2
  32. package/extensions/greedysearch-dm/src/formatters/results.js +8 -6
  33. package/extensions/greedysearch-dm/src/github.mjs +7 -7
  34. package/extensions/greedysearch-dm/src/reddit.mjs +1 -1
  35. package/extensions/greedysearch-dm/src/search/browser-lifecycle.mjs +10 -9
  36. package/extensions/greedysearch-dm/src/search/challenge-detect.mjs +48 -0
  37. package/extensions/greedysearch-dm/src/search/chrome.mjs +129 -53
  38. package/extensions/greedysearch-dm/src/search/constants.mjs +8 -8
  39. package/extensions/greedysearch-dm/src/search/engines.mjs +9 -9
  40. package/extensions/greedysearch-dm/src/search/fetch-source.mjs +154 -77
  41. package/extensions/greedysearch-dm/src/search/minimize.mjs +1 -0
  42. package/extensions/greedysearch-dm/src/search/paths.mjs +1 -1
  43. package/extensions/greedysearch-dm/src/search/pdf.mjs +1 -1
  44. package/extensions/greedysearch-dm/src/search/port-pid.mjs +1 -0
  45. package/extensions/greedysearch-dm/src/search/progress.mjs +2 -0
  46. package/extensions/greedysearch-dm/src/search/recovery.mjs +1 -1
  47. package/extensions/greedysearch-dm/src/search/research.mjs +262 -167
  48. package/extensions/greedysearch-dm/src/search/scale-aware.mjs +11 -0
  49. package/extensions/greedysearch-dm/src/search/simple-research.mjs +827 -0
  50. package/extensions/greedysearch-dm/src/search/synthesis-runner.mjs +11 -11
  51. package/extensions/greedysearch-dm/src/search/synthesis.mjs +11 -11
  52. package/extensions/greedysearch-dm/src/tools/greedy-search-handler.js +23 -20
  53. package/extensions/greedysearch-dm/src/tools/shared.js +10 -9
  54. package/extensions/greedysearch-dm/src/utils/node-runtime.mjs +1 -1
  55. package/package.json +1 -1
  56. package/extensions/greedysearch-dm/src/search/cdp-endpoint.mjs +0 -3
  57. package/extensions/greedysearch-dm/src/utils/browser-executable.mjs +0 -1
@@ -1,35 +1,44 @@
1
1
  #!/usr/bin/env node
2
- import{spawn as s}from"node:child_process";import{existsSync as m,mkdirSync as t,readdirSync as e,readFileSync as w,unlinkSync as U,writeFileSync as p}from"node:fs";import l from"node:net";import{homedir as _,platform as F,tmpdir as c}from"node:os";import{join as H}from"node:path";import{basename as d}from"node:path";function I(z=process.env,$=process.execPath){let Q=z.GREEDY_SEARCH_NODE||z.NODE_BINARY||z.NODE;if(Q?.trim())return Q.trim();let Z=d($||"").toLowerCase();if(Z==="node"||Z==="node.exe")return $;return"node"}function D(z,$="localhost"){let Q=String(z||"").trim().split(/\r?\n/).map((K)=>K.trim()).filter(Boolean);if(Q.length===0)throw Error("empty DevToolsActivePort");let[Z,Y=""]=Q;if(/^wss?:\/\//i.test(Z))return Z;if(Z.includes(":"))return`ws://${Z}${Y}`;return`ws://${$}:${Z}${Y}`}var x=90000,i=30000,h=1200000,zz=20,Qz=300,v=8,a=c().replaceAll("\\","/"),C=process.env.CDP_PAGES_CACHE||`${a}/cdp-pages.json`,A=process.env.CDP_SOCKET_DIR||a;function o(z){if(F()==="win32")return`\\\\.\\pipe\\cdp-${z}`;return t(A,{recursive:!0}),`${A.replaceAll("\\","/")}/cdp-${z}.sock`}function Zz(){let z=F();if(z==="win32")return H(_(),"AppData","Local","Google","Chrome","User Data","DevToolsActivePort");if(z==="darwin")return H(_(),"Library","Application Support","Google","Chrome","DevToolsActivePort");return H(_(),".config","google-chrome","DevToolsActivePort")}function r(){for(let Q of["GREEDY_SEARCH_CDP_WS_URL","DM_CUA_CDP_WS_URL","CDP_WS_URL"])if(process.env[Q])return process.env[Q];let z=process.env.CDP_PROFILE_DIR;if(z){let Q=`${z.replaceAll("\\","/")}/DevToolsActivePort`;if(m(Q))return D(w(Q,"utf8"));throw Error(`GreedySearch DevToolsActivePort not found at ${Q}. Refusing to fall back to the main Chrome session.`)}let $=Zz();return D(w($,"utf8"))}var R=(z)=>new Promise(($)=>setTimeout($,z));function E(){if(F()==="win32")return[];let z=A;try{return e(z).filter(($)=>$.startsWith("cdp-")&&$.endsWith(".sock")).map(($)=>({targetId:$.slice(4,-5),socketPath:H(z,$)}))}catch{return[]}}function k(z,$,Q="target",Z=""){let Y=z.toUpperCase(),K=$.filter((X)=>X.toUpperCase().startsWith(Y));if(K.length===0){let X=Z?` ${Z}`:"";throw Error(`No ${Q} matching prefix "${z}".${X}`)}if(K.length>1)throw Error(`Ambiguous prefix "${z}" — matches ${K.length} ${Q}s. Use more characters.`);return K[0]}function $z(z){if(z.length===0)return v;let $=Math.max(...z.map((Q)=>Q.length));for(let Q=v;Q<=$;Q++)if(new Set(z.map((Y)=>Y.slice(0,Q).toUpperCase())).size===z.length)return Q;return $}class y{#z;#Y=0;#Q=new Map;#Z=new Map;#$=[];async connect(z){return new Promise(($,Q)=>{this.#z=new WebSocket(z),this.#z.onopen=()=>$(),this.#z.onerror=(Z)=>Q(Error(`WebSocket error: ${Z.message||Z.type}`)),this.#z.onclose=()=>this.#$.forEach((Z)=>Z()),this.#z.onmessage=(Z)=>{let Y=JSON.parse(Z.data);if(Y.id&&this.#Q.has(Y.id)){let{resolve:K,reject:X}=this.#Q.get(Y.id);if(this.#Q.delete(Y.id),Y.error)X(Error(Y.error.message));else K(Y.result)}else if(Y.method&&this.#Z.has(Y.method))for(let K of[...this.#Z.get(Y.method)])K(Y.params||{},Y)}})}send(z,$={},Q){let Z=++this.#Y;return new Promise((Y,K)=>{this.#Q.set(Z,{resolve:Y,reject:K});let X={id:Z,method:z,params:$};if(Q)X.sessionId=Q;this.#z.send(JSON.stringify(X)),setTimeout(()=>{if(this.#Q.has(Z))this.#Q.delete(Z),K(Error(`Timeout: ${z}`))},x)})}onEvent(z,$){if(!this.#Z.has(z))this.#Z.set(z,new Set);let Q=this.#Z.get(z);return Q.add($),()=>{if(Q.delete($),Q.size===0)this.#Z.delete(z)}}waitForEvent(z,$=x){let Q=!1,Z,Y;return{promise:new Promise((X,W)=>{Z=this.onEvent(z,(B)=>{if(Q)return;Q=!0,clearTimeout(Y),Z(),X(B)}),Y=setTimeout(()=>{if(Q)return;Q=!0,Z(),W(Error(`Timeout waiting for event: ${z}`))},$)}),cancel(){if(Q)return;Q=!0,clearTimeout(Y),Z?.()}}}onClose(z){this.#$.push(z)}close(){this.#z.close()}}async function T(z){let{targetInfos:$}=await z.send("Target.getTargets");return $.filter((Q)=>Q.type==="page"&&(!Q.url.startsWith("chrome://")||Q.url==="chrome://newtab/"))}function n(z){let $=$z(z.map((Q)=>Q.targetId));return z.map((Q)=>{let Z=Q.targetId.slice(0,$).padEnd($),Y=Q.title.substring(0,54).padEnd(54);return`${Z} ${Y} ${Q.url}`}).join(`
3
- `)}function Yz(z,$=!1){let Q=z.role?.value||"",Z=z.name?.value??"",Y=z.value?.value;if($&&Q==="InlineTextBox")return!1;return Q!=="none"&&Q!=="generic"&&!(Z===""&&(Y===""||Y==null))}function Kz(z,$){let Q=z.role?.value||"",Z=z.name?.value??"",Y=z.value?.value,X=`${" ".repeat(Math.min($,10))}[${Q}]`;if(Z!=="")X+=` ${Z}`;if(!(Y===""||Y==null))X+=` = ${JSON.stringify(Y)}`;return X}function Xz(z,$,Q){let Z=[],Y=new Set;for(let K of z.childIds||[]){let X=$.get(K);if(X&&!Y.has(X.nodeId))Y.add(X.nodeId),Z.push(X)}for(let K of Q.get(z.nodeId)||[])if(!Y.has(K.nodeId))Y.add(K.nodeId),Z.push(K);return Z}async function Vz(z,$,Q=!1){let{nodes:Z}=await z.send("Accessibility.getFullAXTree",{},$),Y=new Map(Z.map((V)=>[V.nodeId,V])),K=new Map;for(let V of Z){if(!V.parentId)continue;if(!K.has(V.parentId))K.set(V.parentId,[]);K.get(V.parentId).push(V)}let X=[],W=new Set;function B(V,q){if(!V||W.has(V.nodeId))return;if(W.add(V.nodeId),Yz(V,Q))X.push(Kz(V,q));for(let G of Xz(V,Y,K))B(G,q+1)}let J=Z.filter((V)=>!V.parentId||!Y.has(V.parentId));for(let V of J)B(V,0);for(let V of Z)B(V,0);return X.join(`
4
- `)}var N=new Map;async function g(z,$){let Q=[],Z=z.onEvent("Runtime.executionContextCreated",(W)=>{if(W?.context)Q.push(W.context)});await z.send("Runtime.enable",{},$),await R(100),Z(),await z.send("Runtime.disable",{},$).catch(()=>{});let Y=null;try{Y=(await z.send("Page.getFrameTree",{},$))?.frameTree?.frame?.id??null}catch{}let K=Q.filter((W)=>W.auxData?.isDefault&&W.auxData?.type==="default");return(Y&&K.find((W)=>W.auxData?.frameId===Y)||K[0]||null)?.id??null}async function L(z,$,Q){let Z=N.get($);if(Z==null){if(Z=await g(z,$),Z==null)throw Error("Failed to capture main execution context — is the page loaded?");N.set($,Z)}async function Y(K){let X=await z.send("Runtime.evaluate",{expression:Q,contextId:K,returnByValue:!0,awaitPromise:!0},$);if(X.exceptionDetails)throw Error(X.exceptionDetails.text||X.exceptionDetails.exception?.description);let W=X.result.value;return typeof W==="object"?JSON.stringify(W,null,2):String(W??"")}try{return await Y(Z)}catch(K){if(N.delete($),Z=await g(z,$),Z==null)throw Error("Failed to re-capture execution context after navigation");return N.set($,Z),Y(Z)}}async function Wz(z,$,Q){let Z=1;try{let W=await z.send("Page.getLayoutMetrics",{},$);Z=W.visualViewport?.clientWidth?W.cssVisualViewport?.clientWidth?Math.round(W.visualViewport.clientWidth/W.cssVisualViewport.clientWidth*100)/100:1:1;let{deviceScaleFactor:B}=await z.send("Emulation.getDeviceMetricsOverride",{},$).catch(()=>({}));if(B)Z=B}catch{}if(Z===1)try{let W=await L(z,$,"window.devicePixelRatio"),B=Number.parseFloat(W);if(B>0)Z=B}catch{}await z.send("Page.enable",{},$).catch(()=>{}),await z.send("Page.bringToFront",{},$).catch(()=>{});let{data:Y}=await z.send("Page.captureScreenshot",{format:"png"},$),K=Q||H(c(),"screenshot.png");p(K,Buffer.from(Y,"base64"));let X=[K];if(X.push(`Screenshot saved. Device pixel ratio (DPR): ${Z}`),X.push("Coordinate mapping:"),X.push(` Screenshot pixels → CSS pixels (for CDP Input events): divide by ${Z}`),X.push(` e.g. screenshot point (${Math.round(100*Z)}, ${Math.round(200*Z)}) → CSS (100, 200) → use clickxy <target> 100 200`),Z!==1)X.push(` On this ${Z}x display: CSS px = screenshot px / ${Z} ≈ screenshot px × ${Math.round(100/Z)/100}`);return X.join(`
5
- `)}async function qz(z,$,Q){let Z=Q?`document.querySelector(${JSON.stringify(Q)})?.outerHTML || 'Element not found'`:"document.documentElement.outerHTML";return L(z,$,Z)}async function Gz(z,$,Q=i){let Z=Date.now()+Q,Y="",K;while(Date.now()<Z){try{let X=await L(z,$,"document.readyState");if(Y=X,X==="complete")return}catch(X){K=X}await R(200)}if(Y)throw Error(`Timed out waiting for navigation to finish (last readyState: ${Y})`);if(K)throw Error(`Timed out waiting for navigation to finish (${K.message})`);throw Error("Timed out waiting for navigation to finish")}async function Jz(z,$,Q){await z.send("Page.enable",{},$);let Z=z.waitForEvent("Page.loadEventFired",i),Y=await z.send("Page.navigate",{url:Q},$);if(Y.errorText)throw Z.cancel(),Error(Y.errorText);if(Y.loaderId)await Z.promise;else Z.cancel();return await Gz(z,$,5000),`Navigated to ${Q}`}async function Bz(z,$){let Q=await L(z,$,`JSON.stringify(performance.getEntriesByType('resource').map(e => ({
2
+ import{spawn as MQ}from"node:child_process";import{createHash as YQ}from"node:crypto";import{basename as XQ}from"node:path";function m(Q=process.env,z=process.execPath){let $=Q.GREEDY_SEARCH_NODE||Q.NODE_BINARY||Q.NODE;if($?.trim())return $.trim();let V=XQ(z||"").toLowerCase();if(V==="node"||V==="node.exe")return z;return"node"}import{existsSync as d,mkdirSync as wQ,readdirSync as jQ,readFileSync as v,unlinkSync as O,writeFileSync as s}from"node:fs";import e from"node:net";import{homedir as f,platform as u,tmpdir as kQ}from"node:os";import{join as k}from"node:path";import{existsSync as y,mkdirSync as WQ,readFileSync as l,writeFileSync as ZQ}from"node:fs";import{homedir as KQ}from"node:os";import{join as i}from"node:path";import{tmpdir as qQ}from"node:os";function BQ(Q,z=9222){let $=Number.parseInt(String(Q??""),10);return Number.isInteger($)&&$>1024&&$<65535?$:z}var JQ=qQ().replaceAll("\\","/"),tQ=BQ(process.env.GREEDY_SEARCH_PORT),U=(process.env.GREEDY_SEARCH_PROFILE_DIR||process.env.CDP_PROFILE_DIR||`${JQ}/greedysearch-chrome-profile`).replaceAll("\\","/"),dQ=`${U}/DevToolsActivePort`,sQ=process.env.GREEDY_SEARCH_PID_FILE||`${U}/browser.pid`,N=process.env.CDP_PAGES_CACHE||`${U}/cdp-pages.json`,eQ=process.env.GREEDY_SEARCH_MODE_FILE||`${U}/browser-mode`,Q0=process.env.GREEDY_SEARCH_METADATA_FILE||`${U}/browser-metadata.json`,$0=process.env.GREEDY_SEARCH_LAUNCH_LOCK_FILE||`${U}/browser-launch.lock`,V0=process.env.GREEDY_SEARCH_ACTIVITY_FILE||`${U}/browser-last-activity`,j=(process.env.CDP_SOCKET_DIR||`${U}/cdp-sockets`).replaceAll("\\","/"),z0=`${U}/visible-recovery.jsonl`,R=i(KQ(),".dm"),M=i(R,"greedyconfig"),P=["perplexity","google","chatgpt","gemini"],D="gemini";function bQ(){try{if(y(M)){let Q=l(M,"utf8"),z=JSON.parse(Q);if(Array.isArray(z.engines)&&z.engines.length>0&&z.engines.every(($)=>typeof $==="string")){let $=z.engines.filter((X)=>C[X]),V=z.engines.filter((X)=>!C[X]);if(V.length>0)process.stderr.write(`[greedysearch] Warning: ignoring unknown engine(s) in ${M}: ${V.join(", ")}
3
+ [greedysearch] Available engines: ${Object.keys(C).join(", ")}
4
+ `);if($.length>0)return $;process.stderr.write(`[greedysearch] Warning: no valid engines in ${M}, falling back to defaults: ${P.join(", ")}
5
+ `)}}}catch{}return P}function HQ(){try{if(!y(R))WQ(R,{recursive:!0});if(!y(M))ZQ(M,JSON.stringify({engines:P,synthesizer:D},null,2)+`
6
+ `,"utf8")}catch{}}HQ();var p=["gemini","chatgpt"];function UQ(){try{if(y(M)){let Q=l(M,"utf8"),z=JSON.parse(Q);if(typeof z.synthesizer==="string"){let $=z.synthesizer.toLowerCase();if(p.includes($))return $;process.stderr.write(`[greedysearch] Warning: unknown synthesizer "${z.synthesizer}" in ${M}
7
+ [greedysearch] Available synthesizers: ${p.join(", ")}
8
+ [greedysearch] Falling back to default: ${D}
9
+ `)}}}catch{}return D}var C={perplexity:"perplexity.mjs",p:"perplexity.mjs",bing:"bing-copilot.mjs",b:"bing-copilot.mjs",google:"google-ai.mjs",g:"google-ai.mjs",gemini:"gemini.mjs",gem:"gemini.mjs",chatgpt:"chatgpt.mjs",gpt:"chatgpt.mjs","semantic-scholar":"semantic-scholar.mjs",semanticscholar:"semantic-scholar.mjs",s2:"semantic-scholar.mjs",logically:"logically.mjs",log:"logically.mjs"},X0=bQ();var W0=UQ(),Z0=Math.max(1,Number.parseInt(process.env.GREEDY_FETCH_CONCURRENCY||"5",10)||5);process.env.CDP_PROFILE_DIR=U;var c=90000,QQ=30000,a=1200000,LQ=20,o=300,r=8,OQ=YQ("sha256").update(j).digest("hex").slice(0,12);function $Q(Q){if(u()==="win32")return`\\\\.\\pipe\\dm-cdp-${OQ}-${Q}`;return wQ(j,{recursive:!0}),k(j,`${Q}.sock`)}function GQ(){let Q=u();if(Q==="win32")return k(f(),"AppData","Local","Google","Chrome","User Data","DevToolsActivePort");if(Q==="darwin")return k(f(),"Library","Application Support","Google","Chrome","DevToolsActivePort");return k(f(),".config","google-chrome","DevToolsActivePort")}function VQ(){let Q=process.env.CDP_PROFILE_DIR;if(Q){let V=`${Q.replaceAll("\\","/")}/DevToolsActivePort`;if(d(V)){let X=v(V,"utf8").trim().split(`
10
+ `);return`ws://localhost:${X[0]}${X[1]}`}throw Error(`GreedySearch DevToolsActivePort not found at ${V}. Refusing to fall back to the main Chrome session.`)}let z=GQ(),$=v(z,"utf8").trim().split(`
11
+ `);return`ws://localhost:${$[0]}${$[1]}`}var A=(Q)=>new Promise((z)=>setTimeout(z,Q));function S(){if(u()==="win32")return[];try{return jQ(j).filter((Q)=>Q.endsWith(".sock")).map((Q)=>({targetId:Q.slice(0,-5),socketPath:k(j,Q)}))}catch{return[]}}function _(Q,z,$="target",V=""){let X=Q.toUpperCase(),W=z.filter((Z)=>Z.toUpperCase().startsWith(X));if(W.length===0){let Z=V?` ${V}`:"";throw Error(`No ${$} matching prefix "${Q}".${Z}`)}if(W.length>1)throw Error(`Ambiguous prefix "${Q}" — matches ${W.length} ${$}s. Use more characters.`);return W[0]}function AQ(Q){if(Q.length===0)return r;let z=Math.max(...Q.map(($)=>$.length));for(let $=r;$<=z;$++)if(new Set(Q.map((X)=>X.slice(0,$).toUpperCase())).size===Q.length)return $;return z}class h{#Q;#X=0;#$=new Map;#V=new Map;#z=[];async connect(Q){return new Promise((z,$)=>{this.#Q=new WebSocket(Q),this.#Q.onopen=()=>z(),this.#Q.onerror=(V)=>$(Error(`WebSocket error: ${V.message||V.type}`)),this.#Q.onclose=()=>this.#z.forEach((V)=>V()),this.#Q.onmessage=(V)=>{let X=JSON.parse(V.data);if(X.id&&this.#$.has(X.id)){let{resolve:W,reject:Z}=this.#$.get(X.id);if(this.#$.delete(X.id),X.error)Z(Error(X.error.message));else W(X.result)}else if(X.method&&this.#V.has(X.method))for(let W of[...this.#V.get(X.method)])W(X.params||{},X)}})}send(Q,z={},$){let V=++this.#X;return new Promise((X,W)=>{this.#$.set(V,{resolve:X,reject:W});let Z={id:V,method:Q,params:z};if($)Z.sessionId=$;this.#Q.send(JSON.stringify(Z)),setTimeout(()=>{if(this.#$.has(V))this.#$.delete(V),W(Error(`Timeout: ${Q}`))},c)})}onEvent(Q,z){if(!this.#V.has(Q))this.#V.set(Q,new Set);let $=this.#V.get(Q);return $.add(z),()=>{if($.delete(z),$.size===0)this.#V.delete(Q)}}waitForEvent(Q,z=c){let $=!1,V,X;return{promise:new Promise((Z,q)=>{V=this.onEvent(Q,(H)=>{if($)return;$=!0,clearTimeout(X),V(),Z(H)}),X=setTimeout(()=>{if($)return;$=!0,V(),q(Error(`Timeout waiting for event: ${Q}`))},z)}),cancel(){if($)return;$=!0,clearTimeout(X),V?.()}}}onClose(Q){this.#z.push(Q)}close(){this.#Q.close()}}async function x(Q){let{targetInfos:z}=await Q.send("Target.getTargets");return z.filter(($)=>$.type==="page"&&(!$.url.startsWith("chrome://")||$.url==="chrome://newtab/"))}function zQ(Q){let z=AQ(Q.map(($)=>$.targetId));return Q.map(($)=>{let V=$.targetId.slice(0,z).padEnd(z),X=$.title.substring(0,54).padEnd(54);return`${V} ${X} ${$.url}`}).join(`
12
+ `)}function yQ(Q,z=!1){let $=Q.role?.value||"",V=Q.name?.value??"",X=Q.value?.value;if(z&&$==="InlineTextBox")return!1;return $!=="none"&&$!=="generic"&&!(V===""&&(X===""||X==null))}function NQ(Q,z){let $=Q.role?.value||"",V=Q.name?.value??"",X=Q.value?.value,Z=`${" ".repeat(Math.min(z,10))}[${$}]`;if(V!=="")Z+=` ${V}`;if(!(X===""||X==null))Z+=` = ${JSON.stringify(X)}`;return Z}function FQ(Q,z,$){let V=[],X=new Set;for(let W of Q.childIds||[]){let Z=z.get(W);if(Z&&!X.has(Z.nodeId))X.add(Z.nodeId),V.push(Z)}for(let W of $.get(Q.nodeId)||[])if(!X.has(W.nodeId))X.add(W.nodeId),V.push(W);return V}async function TQ(Q,z,$=!1){let{nodes:V}=await Q.send("Accessibility.getFullAXTree",{},z),X=new Map(V.map((K)=>[K.nodeId,K])),W=new Map;for(let K of V){if(!K.parentId)continue;if(!W.has(K.parentId))W.set(K.parentId,[]);W.get(K.parentId).push(K)}let Z=[],q=new Set;function H(K,B){if(!K||q.has(K.nodeId))return;if(q.add(K.nodeId),yQ(K,$))Z.push(NQ(K,B));for(let J of FQ(K,X,W))H(J,B+1)}let b=V.filter((K)=>!K.parentId||!X.has(K.parentId));for(let K of b)H(K,0);for(let K of V)H(K,0);return Z.join(`
13
+ `)}var L=new Map;async function n(Q,z){let $=[],V=Q.onEvent("Runtime.executionContextCreated",(q)=>{if(q?.context)$.push(q.context)});await Q.send("Runtime.enable",{},z),await A(100),V(),await Q.send("Runtime.disable",{},z).catch(()=>{});let X=null;try{X=(await Q.send("Page.getFrameTree",{},z))?.frameTree?.frame?.id??null}catch{}let W=$.filter((q)=>q.auxData?.isDefault&&q.auxData?.type==="default");return(X&&W.find((q)=>q.auxData?.frameId===X)||W[0]||null)?.id??null}async function w(Q,z,$){let V=L.get(z);if(V==null){if(V=await n(Q,z),V==null)throw Error("Failed to capture main execution context — is the page loaded?");L.set(z,V)}async function X(W){let Z=await Q.send("Runtime.evaluate",{expression:$,contextId:W,returnByValue:!0,awaitPromise:!0},z);if(Z.exceptionDetails)throw Error(Z.exceptionDetails.text||Z.exceptionDetails.exception?.description);let q=Z.result.value;return typeof q==="object"?JSON.stringify(q,null,2):String(q??"")}try{return await X(V)}catch(W){if(L.delete(z),V=await n(Q,z),V==null)throw Error("Failed to re-capture execution context after navigation");return L.set(z,V),X(V)}}async function CQ(Q,z,$){let V=1;try{let q=await Q.send("Page.getLayoutMetrics",{},z);V=q.visualViewport?.clientWidth?q.cssVisualViewport?.clientWidth?Math.round(q.visualViewport.clientWidth/q.cssVisualViewport.clientWidth*100)/100:1:1;let{deviceScaleFactor:H}=await Q.send("Emulation.getDeviceMetricsOverride",{},z).catch(()=>({}));if(H)V=H}catch{}if(V===1)try{let q=await w(Q,z,"window.devicePixelRatio"),H=Number.parseFloat(q);if(H>0)V=H}catch{}let{data:X}=await Q.send("Page.captureScreenshot",{format:"png"},z),W=$||k(kQ(),"screenshot.png");s(W,Buffer.from(X,"base64"));let Z=[W];if(Z.push(`Screenshot saved. Device pixel ratio (DPR): ${V}`),Z.push("Coordinate mapping:"),Z.push(` Screenshot pixels → CSS pixels (for CDP Input events): divide by ${V}`),Z.push(` e.g. screenshot point (${Math.round(100*V)}, ${Math.round(200*V)}) → CSS (100, 200) → use clickxy <target> 100 200`),V!==1)Z.push(` On this ${V}x display: CSS px = screenshot px / ${V} ≈ screenshot px × ${Math.round(100/V)/100}`);return Z.join(`
14
+ `)}async function RQ(Q,z,$){let V=$?`document.querySelector(${JSON.stringify($)})?.outerHTML || 'Element not found'`:"document.documentElement.outerHTML";return w(Q,z,V)}async function PQ(Q,z,$=QQ){let V=Date.now()+$,X="",W;while(Date.now()<V){try{let Z=await w(Q,z,"document.readyState");if(X=Z,Z==="complete")return}catch(Z){W=Z}await A(200)}if(X)throw Error(`Timed out waiting for navigation to finish (last readyState: ${X})`);if(W)throw Error(`Timed out waiting for navigation to finish (${W.message})`);throw Error("Timed out waiting for navigation to finish")}async function DQ(Q,z,$){await Q.send("Page.enable",{},z);let V=Q.waitForEvent("Page.loadEventFired",QQ),X=await Q.send("Page.navigate",{url:$},z);if(X.errorText)throw V.cancel(),Error(X.errorText);L.delete(z);let W=!1;if(X.loaderId)try{await V.promise,W=!0}catch{}else V.cancel();if(!W)await PQ(Q,z,5000);return`Navigated to ${$}`}async function fQ(Q,z){let $=await w(Q,z,`JSON.stringify(performance.getEntriesByType('resource').map(e => ({
6
15
  name: e.name.substring(0, 120), type: e.initiatorType,
7
16
  duration: Math.round(e.duration), size: e.transferSize
8
- })))`);return JSON.parse(Q).map((Z)=>`${String(Z.duration).padStart(5)}ms ${String(Z.size||"?").padStart(8)}B ${Z.type.padEnd(8)} ${Z.name}`).join(`
9
- `)}async function Lz(z,$,Q){if(!Q)throw Error("CSS selector required");let Z=`
17
+ })))`);return JSON.parse($).map((V)=>`${String(V.duration).padStart(5)}ms ${String(V.size||"?").padStart(8)}B ${V.type.padEnd(8)} ${V.name}`).join(`
18
+ `)}async function vQ(Q,z,$){if(!$)throw Error("CSS selector required");let V=`
10
19
  (function() {
11
- const el = document.querySelector(${JSON.stringify(Q)});
12
- if (!el) return { ok: false, error: 'Element not found: ' + ${JSON.stringify(Q)} };
20
+ const el = document.querySelector(${JSON.stringify($)});
21
+ if (!el) return { ok: false, error: 'Element not found: ' + ${JSON.stringify($)} };
13
22
  el.scrollIntoView({ block: 'center' });
14
23
  el.click();
15
24
  return { ok: true, tag: el.tagName, text: el.textContent.trim().substring(0, 80) };
16
25
  })()
17
- `,Y=await L(z,$,Z),K=JSON.parse(Y);if(!K.ok)throw Error(K.error);return`Clicked <${K.tag}> "${K.text}"`}async function Oz(z,$,Q,Z){let Y=Number.parseFloat(Q),K=Number.parseFloat(Z);if(Number.isNaN(Y)||Number.isNaN(K))throw Error("x and y must be numbers (CSS pixels)");let X={x:Y,y:K,button:"left",clickCount:1,modifiers:0};return await z.send("Input.dispatchMouseEvent",{...X,type:"mouseMoved"},$),await z.send("Input.dispatchMouseEvent",{...X,type:"mousePressed"},$),await R(50),await z.send("Input.dispatchMouseEvent",{...X,type:"mouseReleased"},$),`Clicked at CSS (${Y}, ${K})`}async function Hz(z,$,Q){if(Q==null||Q==="")throw Error("text required");return await z.send("Input.insertText",{text:Q},$),`Typed ${Q.length} characters`}async function Uz(z,$,Q,Z=1500){if(!Q)throw Error("CSS selector required");Z=Math.min(Math.max(Number.parseInt(Z,10)||1500,100),30000);let Y=0,K=Date.now()+300000;while(Date.now()<K){if(await L(z,$,`!!document.querySelector(${JSON.stringify(Q)})`)!=="true")break;let W=`
26
+ `,X=await w(Q,z,V),W=JSON.parse(X);if(!W.ok)throw Error(W.error);return`Clicked <${W.tag}> "${W.text}"`}async function _Q(Q,z,$,V){let X=Number.parseFloat($),W=Number.parseFloat(V);if(Number.isNaN(X)||Number.isNaN(W))throw Error("x and y must be numbers (CSS pixels)");let Z={x:X,y:W,button:"left",clickCount:1,modifiers:0};return await Q.send("Input.dispatchMouseEvent",{...Z,type:"mouseMoved"},z),await Q.send("Input.dispatchMouseEvent",{...Z,type:"mousePressed"},z),await A(50),await Q.send("Input.dispatchMouseEvent",{...Z,type:"mouseReleased"},z),`Clicked at CSS (${X}, ${W})`}async function xQ(Q,z,$){if($==null||$==="")throw Error("text required");return await Q.send("Input.insertText",{text:$},z),`Typed ${$.length} characters`}async function uQ(Q,z,$,V=1500){if(!$)throw Error("CSS selector required");V=Math.min(Math.max(Number.parseInt(V,10)||1500,100),30000);let X=0,W=Date.now()+300000;while(Date.now()<W){if(await w(Q,z,`!!document.querySelector(${JSON.stringify($)})`)!=="true")break;let q=`
18
27
  (function() {
19
- const el = document.querySelector(${JSON.stringify(Q)});
28
+ const el = document.querySelector(${JSON.stringify($)});
20
29
  if (!el) return false;
21
30
  el.scrollIntoView({ block: 'center' });
22
31
  el.click();
23
32
  return true;
24
33
  })()
25
- `;if(await L(z,$,W)!=="true")break;Y++,await R(Z)}return`Clicked "${Q}" ${Y} time(s) until it disappeared`}async function bz(z,$,Q,Z){if(!Q)throw Error('CDP method required (e.g. "DOM.getDocument")');let Y={};if(Z)try{Y=JSON.parse(Z)}catch{throw Error(`Invalid JSON params: ${Z}`)}let K=await z.send(Q,Y,$);return JSON.stringify(K,null,2)}async function Rz(z,$,Q){if(!$)throw Error("Browser CDP method required");let Z={};if(Q)try{Z=JSON.parse(Q)}catch{throw Error(`Invalid JSON params: ${Q}`)}let Y=await z.send($,Z);return JSON.stringify(Y,null,2)}async function Nz(z){let $=o(z),Q=new y;try{await Q.connect(r())}catch(V){process.stderr.write(`Daemon: cannot connect to Chrome: ${V.message}
26
- `),process.exit(1)}let Z;try{Z=(await Q.send("Target.attachToTarget",{targetId:z,flatten:!0})).sessionId}catch(V){process.stderr.write(`Daemon: attach failed: ${V.message}
27
- `),Q.close(),process.exit(1)}let Y=!0;function K(){if(!Y)return;Y=!1,J.close();try{U($)}catch{}Q.close(),process.exit(0)}Q.onEvent("Target.targetDestroyed",(V)=>{if(V.targetId===z)K()}),Q.onEvent("Target.detachedFromTarget",(V)=>{if(V.sessionId===Z)K()}),Q.onClose(()=>K()),process.on("SIGTERM",K),process.on("SIGINT",K);let X=setTimeout(K,h);function W(){clearTimeout(X),X=setTimeout(K,h)}async function B({cmd:V,args:q}){W();try{let G;switch(V){case"list":{let O=await T(Q);G=n(O);break}case"list_raw":{let O=await T(Q);G=JSON.stringify(O);break}case"snap":case"snapshot":G=await Vz(Q,Z,!0);break;case"eval":G=await L(Q,Z,q[0]);break;case"shot":case"screenshot":G=await Wz(Q,Z,q[0]);break;case"html":G=await qz(Q,Z,q[0]);break;case"nav":case"navigate":G=await Jz(Q,Z,q[0]);break;case"net":case"network":G=await Bz(Q,Z);break;case"click":G=await Lz(Q,Z,q[0]);break;case"clickxy":G=await Oz(Q,Z,q[0],q[1]);break;case"type":G=await Hz(Q,Z,q[0]);break;case"loadall":G=await Uz(Q,Z,q[0],q[1]?Number.parseInt(q[1],10):1500);break;case"evalraw":G=await bz(Q,Z,q[0],q[1]);break;case"browse":case"browserraw":G=await Rz(Q,q[0],q[1]);break;case"stop":return{ok:!0,result:"",stopAfter:!0};default:return{ok:!1,error:`Unknown command: ${V}`}}return{ok:!0,result:G??""}}catch(G){return{ok:!1,error:G.message}}}let J=l.createServer((V)=>{let q="";V.on("data",(G)=>{q+=G.toString();let O=q.split(`
28
- `);q=O.pop();for(let S of O){if(!S.trim())continue;let M;try{M=JSON.parse(S)}catch{V.write(`${JSON.stringify({ok:!1,error:"Invalid JSON request",id:null})}
29
- `);continue}B(M).then((P)=>{let f=`${JSON.stringify({...P,id:M.id})}
30
- `;if(P.stopAfter)V.end(f,K);else V.write(f)})}})});try{U($)}catch{}J.listen($)}function b(z){return new Promise(($,Q)=>{let Z=l.connect(z);Z.on("connect",()=>$(Z)),Z.on("error",Q)})}async function jz(z){let $=o(z);try{return await b($)}catch{}try{U($)}catch{}s(I(),[process.argv[1],"_daemon",z],{detached:!0,stdio:"ignore"}).unref();for(let Z=0;Z<zz;Z++){await R(Qz);try{return await b($)}catch{}}throw Error("Daemon failed to start — did you click Allow in Chrome?")}function j(z,$){return new Promise((Q,Z)=>{let Y="",K=!1,X=()=>{z.off("data",W),z.off("error",B),z.off("end",J),z.off("close",V)},W=(q)=>{Y+=q.toString();let G=Y.indexOf(`
31
- `);if(G===-1)return;K=!0,X(),Q(JSON.parse(Y.slice(0,G))),z.end()},B=(q)=>{if(K)return;K=!0,X(),Z(q)},J=()=>{if(K)return;K=!0,X(),Z(Error("Connection closed before response"))},V=()=>{if(K)return;K=!0,X(),Z(Error("Connection closed before response"))};z.on("data",W),z.on("error",B),z.on("end",J),z.on("close",V),$.id=1,z.write(`${JSON.stringify($)}
32
- `)})}function Mz(){return E()[0]?.socketPath||null}async function Dz(z){let $=E();if(z){let Q=k(z,$.map((Y)=>Y.targetId),"daemon"),Z=$.find((Y)=>Y.targetId===Q);try{let Y=await b(Z.socketPath);await j(Y,{cmd:"stop"})}catch{try{U(Z.socketPath)}catch{}}return}for(let Q of $)try{let Z=await b(Q.socketPath);await j(Z,{cmd:"stop"})}catch{try{U(Q.socketPath)}catch{}}}var u=`cdp - lightweight Chrome DevTools Protocol CLI (no Puppeteer)
34
+ `;if(await w(Q,z,q)!=="true")break;X++,await A(V)}return`Clicked "${$}" ${X} time(s) until it disappeared`}async function SQ(Q,z,$,V){if(!$)throw Error('CDP method required (e.g. "DOM.getDocument")');let X={};if(V)try{X=JSON.parse(V)}catch{throw Error(`Invalid JSON params: ${V}`)}let W=await Q.send($,X,z);return JSON.stringify(W,null,2)}async function hQ(Q,z,$){if(!z)throw Error("Browser CDP method required");let V={};if($)try{V=JSON.parse($)}catch{throw Error(`Invalid JSON params: ${$}`)}let X=await Q.send(z,V);return JSON.stringify(X,null,2)}async function EQ(Q){let z=$Q(Q),$=new h;try{await $.connect(VQ())}catch(K){process.stderr.write(`Daemon: cannot connect to Chrome: ${K.message}
35
+ `),process.exit(1)}let V;try{V=(await $.send("Target.attachToTarget",{targetId:Q,flatten:!0})).sessionId}catch(K){process.stderr.write(`Daemon: attach failed: ${K.message}
36
+ `),$.close(),process.exit(1)}let X=!0;function W(){if(!X)return;X=!1,b.close();try{O(z)}catch{}$.close(),process.exit(0)}$.onEvent("Target.targetDestroyed",(K)=>{if(K.targetId===Q)W()}),$.onEvent("Target.detachedFromTarget",(K)=>{if(K.sessionId===V)W()}),$.onClose(()=>W()),process.on("SIGTERM",W),process.on("SIGINT",W);let Z=setTimeout(W,a);function q(){clearTimeout(Z),Z=setTimeout(W,a)}async function H({cmd:K,args:B}){q();try{let J;switch(K){case"list":{let Y=await x($);J=zQ(Y);break}case"list_raw":{let Y=await x($);J=JSON.stringify(Y);break}case"snap":case"snapshot":J=await TQ($,V,!0);break;case"eval":J=await w($,V,B[0]);break;case"shot":case"screenshot":J=await CQ($,V,B[0]);break;case"html":J=await RQ($,V,B[0]);break;case"nav":case"navigate":J=await DQ($,V,B[0]);break;case"net":case"network":J=await fQ($,V);break;case"click":J=await vQ($,V,B[0]);break;case"clickxy":J=await _Q($,V,B[0],B[1]);break;case"type":J=await xQ($,V,B[0]);break;case"loadall":J=await uQ($,V,B[0],B[1]?Number.parseInt(B[1],10):1500);break;case"evalraw":J=await SQ($,V,B[0],B[1]);break;case"browse":case"browserraw":J=await hQ($,B[0],B[1]);break;case"stop":return{ok:!0,result:"",stopAfter:!0};default:return{ok:!1,error:`Unknown command: ${K}`}}return{ok:!0,result:J??""}}catch(J){return{ok:!1,error:J.message}}}let b=e.createServer((K)=>{let B="";K.on("data",(J)=>{B+=J.toString();let Y=B.split(`
37
+ `);B=Y.pop();for(let E of Y){if(!E.trim())continue;let T;try{T=JSON.parse(E)}catch{K.write(`${JSON.stringify({ok:!1,error:"Invalid JSON request",id:null})}
38
+ `);continue}H(T).then((I)=>{let g=`${JSON.stringify({...I,id:T.id})}
39
+ `;if(I.stopAfter)K.end(g,W);else K.write(g)})}})});try{O(z)}catch{}b.listen(z)}function G(Q){return new Promise((z,$)=>{let V=e.connect(Q);V.on("connect",()=>z(V)),V.on("error",$)})}async function IQ(Q){let z=$Q(Q);try{return await G(z)}catch{}try{O(z)}catch{}MQ(m(),[process.argv[1],"_daemon",Q],{detached:!0,stdio:"ignore"}).unref();let V=[50,100,200],X=Date.now()+LQ*o,W=0;while(Date.now()<X){try{return await G(z)}catch{}let Z=V[W]??o;W++,await A(Z)}throw Error("Daemon failed to start — did you click Allow in Chrome?")}function F(Q,z){return new Promise(($,V)=>{let X="",W=!1,Z=()=>{Q.off("data",q),Q.off("error",H),Q.off("end",b),Q.off("close",K)},q=(B)=>{X+=B.toString();let J=X.indexOf(`
40
+ `);if(J===-1)return;W=!0,Z();try{$(JSON.parse(X.slice(0,J)))}catch(Y){V(Error(`Invalid JSON response from daemon: ${Y.message}`))}Q.end()},H=(B)=>{if(W)return;W=!0,Z(),V(B)},b=()=>{if(W)return;W=!0,Z(),V(Error("Connection closed before response"))},K=()=>{if(W)return;W=!0,Z(),V(Error("Connection closed before response"))};Q.on("data",q),Q.on("error",H),Q.on("end",b),Q.on("close",K),z.id=1,Q.write(`${JSON.stringify(z)}
41
+ `)})}function gQ(){return S()[0]?.socketPath||null}async function mQ(Q){let z=S();if(Q){let $=_(Q,z.map((X)=>X.targetId),"daemon"),V=z.find((X)=>X.targetId===$);try{let X=await G(V.socketPath);await F(X,{cmd:"stop"})}catch{try{O(V.socketPath)}catch{}}return}for(let $ of z)try{let V=await G($.socketPath);await F(V,{cmd:"stop"})}catch{try{O($.socketPath)}catch{}}}var t=`cdp - lightweight Chrome DevTools Protocol CLI (no Puppeteer)
33
42
 
34
43
  Usage: cdp <command> [args]
35
44
 
@@ -47,5 +56,5 @@ Usage: cdp <command> [args]
47
56
  evalraw <target> <method> [json] Send a raw CDP command; returns JSON result
48
57
  browse <target> <method> [json] Send a browser-level CDP command (no session)
49
58
  stop [target] Stop daemon(s)
50
- `,_z=new Set(["snap","snapshot","eval","shot","screenshot","html","nav","navigate","net","network","click","clickxy","type","loadall","evalraw","browse","browserraw"]);async function Cz(){let[z,...$]=process.argv.slice(2);if(z==="_daemon"){await Nz($[0]);return}if(!z||z==="help"||z==="--help"||z==="-h")console.log(u),process.exit(0);if(z==="list"||z==="ls"){let J,V=Mz();if(V)try{let q=await b(V),G=await j(q,{cmd:"list_raw"});if(G.ok)J=JSON.parse(G.result)}catch{}if(!J){let q=new y;await q.connect(r()),J=await T(q),q.close()}p(C,JSON.stringify(J)),console.log(n(J)),setTimeout(()=>process.exit(0),100);return}if(z==="stop"){await Dz($[0]);return}if(!_z.has(z))console.error(`Unknown command: ${z}
51
- `),console.log(u),process.exit(1);let Q=$[0];if(!Q)console.error('Error: target ID required. Run "cdp list" first.'),process.exit(1);let Z,Y=E().map((J)=>J.targetId);if(Y.filter((J)=>J.toUpperCase().startsWith(Q.toUpperCase())).length>0)Z=k(Q,Y,"daemon");else{if(!m(C))console.error('No page list cached. Run "cdp list" first.'),process.exit(1);let J=JSON.parse(w(C,"utf8"));Z=k(Q,J.map((V)=>V.targetId),"target",'Run "cdp list".')}let X=await jz(Z),W=$.slice(1);if(z==="eval"){let J=W.join(" ");if(!J)console.error("Error: expression required"),process.exit(1);W[0]=J}else if(z==="type"){let J=W.join(" ");if(W[0]==="--stdin")J=await new Promise((V)=>{let q="";if(process.stdin.setEncoding("utf8"),process.stdin.on("data",(G)=>q+=G),process.stdin.on("end",()=>V(q)),process.stdin.isTTY)V("")});if(!J)console.error("Error: text required"),process.exit(1);W[0]=J}else if(z==="evalraw"){if(!W[0])console.error("Error: CDP method required"),process.exit(1);if(W.length>2)W[1]=W.slice(1).join(" ")}else if(z==="browse"||z==="browserraw"){if(!W[0])console.error("Error: browser CDP method required"),process.exit(1);if(W.length>2)W[1]=W.slice(1).join(" ")}if((z==="nav"||z==="navigate")&&!W[0])console.error("Error: URL required"),process.exit(1);let B=await j(X,{cmd:z,args:W});if(B.ok){if(B.result)console.log(B.result)}else console.error("Error:",B.error),process.exitCode=1}Cz().catch((z)=>{console.error(z.message),process.exit(1)});
59
+ `,pQ=new Set(["snap","snapshot","eval","shot","screenshot","html","nav","navigate","net","network","click","clickxy","type","loadall","evalraw","browse","browserraw"]);async function lQ(){let[Q,...z]=process.argv.slice(2);if(Q==="_daemon"){await EQ(z[0]);return}if(!Q||Q==="help"||Q==="--help"||Q==="-h")console.log(t),process.exit(0);if(Q==="list"||Q==="ls"){let b,K=gQ();if(K)try{let B=await G(K),J=await F(B,{cmd:"list_raw"});if(J.ok)b=JSON.parse(J.result)}catch{}if(!b){let B=new h;await B.connect(VQ()),b=await x(B),B.close()}s(N,JSON.stringify(b)),console.log(zQ(b)),process.exit(0)}if(Q==="stop"){await mQ(z[0]);return}if(!pQ.has(Q))console.error(`Unknown command: ${Q}
60
+ `),console.log(t),process.exit(1);let $=z[0];if(!$)console.error('Error: target ID required. Run "cdp list" first.'),process.exit(1);let V,X=S().map((b)=>b.targetId);if(X.filter((b)=>b.toUpperCase().startsWith($.toUpperCase())).length>0)V=_($,X,"daemon");else{if(!d(N))console.error('No page list cached. Run "cdp list" first.'),process.exit(1);let b=JSON.parse(v(N,"utf8"));V=_($,b.map((K)=>K.targetId),"target",'Run "cdp list".')}let Z=await IQ(V),q=z.slice(1);if(Q==="eval"){let b=q.join(" ");if(!b)console.error("Error: expression required"),process.exit(1);q[0]=b}else if(Q==="type"){let b=q.join(" ");if(q[0]==="--stdin")b=await new Promise((K)=>{let B="";if(process.stdin.setEncoding("utf8"),process.stdin.on("data",(J)=>B+=J),process.stdin.on("end",()=>K(B)),process.stdin.isTTY)K("")});if(!b)console.error("Error: text required"),process.exit(1);q[0]=b}else if(Q==="evalraw"){if(!q[0])console.error("Error: CDP method required"),process.exit(1);if(q.length>2)q[1]=q.slice(1).join(" ")}else if(Q==="browse"||Q==="browserraw"){if(!q[0])console.error("Error: browser CDP method required"),process.exit(1);if(q.length>2)q[1]=q.slice(1).join(" ")}if((Q==="nav"||Q==="navigate")&&!q[0])console.error("Error: URL required"),process.exit(1);let H=await F(Z,{cmd:Q,args:q});if(H.ok){if(H.result)console.log(H.result)}else console.error("Error:",H.error),process.exitCode=1}lQ().catch((Q)=>{console.error(Q.message),process.exit(1)});
@@ -1,11 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import{execSync as c,spawn as g}from"node:child_process";import{existsSync as u,mkdirSync as x,readFileSync as k,unlinkSync as Y,writeFileSync as B}from"node:fs";import{platform as _,tmpdir as w}from"node:os";import{join as O}from"node:path";var b=w().replaceAll("\\","/"),e=9222,p=O(w(),"greedysearch-chrome-profile"),h=`${b}/greedysearch-chrome.pid`,l=`${b}/greedysearch-chrome-mode`;function m(o){try{if(_()==="win32"){let C=c("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=c(`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 f(){let o=m(e);if(!o)return!1;try{if(_()==="win32")c(`taskkill /F /PID ${o}`,{stdio:"ignore"});else process.kill(o,"SIGKILL");return!0}catch{return!1}}function H(){for(let o of[h,l])try{Y(o)}catch{}}async function U(){let{ok:o,body:r}=await probe();if(!o){console.log("Not running.");return}let C=u(l)?k(l,"utf8").trim():"unknown",a=u(h)?k(h,"utf8").trim():"none",n=m(e)||"unknown",{Browser:s}=JSON.parse(r);console.log(`Running: ${s}`),console.log(` Mode: ${C}`),console.log(` Port: ${e}`),console.log(` PID file: ${a}`),console.log(` PID actual:${n}`)}async function K(){let{ok:o}=await probe();if(!o){console.log("Not running — nothing to kill."),H();return}console.log("Killing browser on port 9222..."),f(),H(),await new Promise((C)=>setTimeout(C,1500));let{ok:r}=await probe();console.log(r?"FAILED — still running.":"Killed.")}async function R(o){let{ok:r}=await probe();if(r){let A=u(l)?k(l,"utf8").trim():"unknown";if(A===o){console.log(`Already running in ${o} mode.`);return}console.log(`${A} browser running — killing to switch to ${o}...`),f(),H(),await new Promise((i)=>setTimeout(i,1500))}if(!(process.env.CHROME_PATH||findChrome()))console.error("Chrome not found."),process.exit(1);let a=o==="headless",n=[`--remote-debugging-port=${e}`,"--disable-features=DevToolsPrivacyUI","--no-first-run","--no-default-browser-check","--disable-default-apps","--disable-blink-features=AutomationControlled","--window-size=1920,1080",`--user-data-dir=${p}`,"--profile-directory=Default"];if(a){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"),_()==="win32")n.push("--disable-software-rasterizer")}n.push("about:blank"),x(p,{recursive:!0}),console.log(`Launching ${o} ${browser.label} on port ${e}...`);let s=g(browser.path,n,{detached:!0,stdio:"ignore"});s.unref(),B(h,String(s.pid)),B(l,o);for(let A=0;A<30;A++){await new Promise((t)=>setTimeout(t,500));let{ok:i}=await probe();if(i){try{let{body:t}=await probe(),{webSocketDebuggerUrl:W}=JSON.parse(t),G=new URL(W).pathname;B(`${p}/DevToolsActivePort`,`${e}
4
- ${G}`)}catch{}console.log("Ready.");return}}console.error("Timeout — Chrome did not become ready."),process.exit(1)}var T=process.argv[2];switch(T){case"launch-headless":await R("headless");break;case"launch-visible":await R("visible");break;case"kill":await K();break;case"status":await U();break;default:console.log(`Usage: node bin/gschrome.mjs <command>
5
-
6
- Commands:
7
- launch-headless Start headless Chrome on port 9222
8
- launch-visible Start visible Chrome on port 9222
9
- kill Kill Chrome on port 9222 (headless or visible)
10
- status Show running status
11
- `),process.exit(1)}
2
+ import{spawn as a}from"node:child_process";import{fileURLToPath as e}from"node:url";import{basename as c}from"node:path";function u(s=process.env,i=process.execPath){let o=s.GREEDY_SEARCH_NODE||s.NODE_BINARY||s.NODE;if(o?.trim())return o.trim();let r=c(i||"").toLowerCase();if(r==="node"||r==="node.exe")return i;return"node"}var m=process.argv[2]||"status",n=e(new URL("./launch.mjs",import.meta.url)),p={"launch-headless":{args:[],visible:!1},"launch-visible":{args:[],visible:!0},kill:{args:["--kill"],visible:null},status:{args:["--status"],visible:null}},l=p[m];if(!l)console.error("Usage: gschrome.mjs launch-headless|launch-visible|kill|status"),process.exit(2);var t={...process.env};if(l.visible===!0)t.GREEDY_SEARCH_VISIBLE="1";if(l.visible===!1)delete t.GREEDY_SEARCH_VISIBLE;var E=a(u(),[n,...l.args],{stdio:"inherit",env:t});E.on("exit",(s,i)=>{if(i)process.kill(process.pid,i);process.exit(s??1)});
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import{spawn as K}from"node:child_process";import{basename as H}from"node:path";function F(q=process.env,z=process.execPath){let A=q.GREEDY_SEARCH_NODE||q.NODE_BINARY||q.NODE;if(A?.trim())return A.trim();let E=H(z||"").toLowerCase();if(E==="node"||E==="node.exe")return z;return"node"}var O=new URL("./launch-visible.mjs",import.meta.url).pathname.replace(/^\/([A-Z]:)/,"$1"),Q=K(F(),[O,"--kill"],{stdio:"inherit"});Q.on("close",(q)=>process.exit(q??0));
2
+ import{spawn as J}from"node:child_process";import{basename as H}from"node:path";function F(k=process.env,q=process.execPath){let z=k.GREEDY_SEARCH_NODE||k.NODE_BINARY||k.NODE;if(z?.trim())return z.trim();let E=H(q||"").toLowerCase();if(E==="node"||E==="node.exe")return q;return"node"}var K=new URL("./launch-visible.mjs",import.meta.url).pathname.replace(/^\/([A-Z]:)/,"$1"),L=J(F(),[K,"--kill"],{stdio:"inherit"});L.on("close",(k)=>process.exit(k??0));
@@ -1,5 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import{execSync as c,spawn as YC}from"node:child_process";import{existsSync as EC,mkdirSync as GC,readFileSync as u,unlinkSync as D,writeFileSync as $}from"node:fs";import MC from"node:http";import{platform as p,tmpdir as g}from"node:os";import{join as I}from"node:path";import{existsSync as N}from"node:fs";import{platform as V}from"node:os";function l(C=V()){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 L(C,A=N){return C.find((_)=>_&&A(_))||null}function a(C,A){for(let _ of A){let R=C[_]?.trim();if(R)return{key:_,path:R}}return null}function v(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 S({env:C=process.env,platformName:A=V(),exists:_=N}={}){let R=(C.GREEDY_SEARCH_BROWSER||C.DM_CUA_BROWSER||"auto").toLowerCase(),O=a(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:v(R,O.key)};let W=l(A);if(R==="cloak")return{path:L(W.cloak,_),label:"CloakBrowser"};if(R==="chrome")return{path:L(W.chrome,_),label:"Chrome"};let K=L(W.cloak,_);return{path:K||L(W.chrome,_),label:K?"CloakBrowser":"Chrome"}}import{existsSync as h,mkdirSync as o,readFileSync as J,renameSync as r,unlinkSync as n,writeFileSync as U}from"node:fs";import i from"node:http";import{platform as m}from"node:os";import{dirname as s}from"node:path";var x=[9222,9223],d=/^(0|false|no|off)$/i;function t(C){return[...new Set(C.filter(Boolean))]}function w(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 q(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 y(C=process.env){return![C.GREEDY_SEARCH_REUSE_EXISTING_BROWSER,C.DM_CUA_REUSE_EXISTING_BROWSER].some((A)=>A!==void 0&&d.test(String(A)))}function Q(C){let A=Number.parseInt(String(C??""),10);return Number.isInteger(A)&&A>0&&A<65536?A:null}function e(C){if(!C)return null;let A=String(C).trim();if(!A)return null;let _=new URL(A.includes("://")?A:`http://${A}`),R=Q(_.port)||(_.protocol==="https:"?443:80);return{host:_.hostname,port:R,source:`env:${A}`}}function CC(C){if(!C)return[];return String(C).split(/[,\s]+/).map(Q).filter(Boolean)}function AC({env:C=process.env,platformName:A=m(),procVersionText:_=null}={}){if(A!=="linux")return!1;if(C.WSL_DISTRO_NAME||C.WSL_INTEROP)return!0;let R=_??(()=>{try{return J("/proc/version","utf8")}catch{return""}})();return/microsoft|wsl/i.test(R)}function _C({env:C=process.env,platformName:A=m(),procVersionText:_=null,resolvConfText:R=null}={}){let B=["localhost","127.0.0.1"];if(AC({env:C,platformName:A,procVersionText:_})){let W=(R??(()=>{try{return J("/etc/resolv.conf","utf8")}catch{return""}})()).match(/^\s*nameserver\s+([^\s#]+)/m);if(W)B.push(W[1]);B.push("host.docker.internal")}return t(B)}function RC({env:C=process.env,hosts:A=_C({env:C}),autoPorts:_=x,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=e(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=Q(C[H]);if(!Y)continue;for(let M of A)B.push({host:M,port:Y,source:`env:${H}`})}let O=CC(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(y(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 BC(C,{timeoutMs:A=700}={}){if(C.wsUrl)return q(C.wsUrl,C.source);let _=C.host||"localhost",R=C.port;if(!R)return null;let B=await new Promise((O)=>{let W=i.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=q(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 OC(C={}){for(let A of RC(C)){let _=await BC(A,C);if(_)return _}return null}function HC(C){if(!C)throw Error("missing CDP endpoint");let A=new URL(C.wsUrl);return`${A.host}
3
- ${A.pathname}${A.search}
4
- `}function KC(C,A){o(s(C),{recursive:!0});let _=`${C}.tmp-${process.pid}`;U(_,HC(A),"utf8");try{n(C)}catch{}r(_,C)}async function P({activePortFile:C,modeFile:A,env:_=process.env,excludePorts:R=[],autoPorts:B=x}={}){if(!y(_))return null;let O=await OC({env:_,excludePorts:R,autoPorts:B});if(!O)return null;if(KC(C,O),A)U(A,"existing","utf8");return O}function WC(C){return String(C||"").trim()==="existing"}function X(C,A){if(!A||!h(A))return!1;if(!WC(J(A,"utf8")))return!1;return!!C&&h(C)}var E=9222,f=I(g(),"greedysearch-chrome-profile"),G=I(f,"DevToolsActivePort"),z=I(g(),"greedysearch-chrome.pid"),b=I(g(),"greedysearch-chrome-mode");function j(){if(!EC(z))return!1;let C=Number.parseInt(u(z,"utf8").trim(),10);if(!C)return!1;try{return process.kill(C,0),C}catch{return!1}}function k(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 Z(C){try{if(p()==="win32")c(`taskkill /F /PID ${C} /T`,{stdio:"ignore"});else process.kill(C,"SIGKILL");return!0}catch{return!1}}function T(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 bC(C){try{let A=await T(`http://localhost:${C}/json/version`).then((H)=>JSON.parse(H.body)),R=(await T(`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 DC(C=15000){let A=Date.now()+C;while(Date.now()<A){let{ok:_,body:R}=await T(`http://localhost:${E}/json/version`,1500);if(_)try{let{webSocketDebuggerUrl:B}=JSON.parse(R),O=new URL(B).pathname;return $(G,`${E}
5
- ${O}`,"utf8"),!0}catch{}await new Promise((B)=>setTimeout(B,400))}return!1}function F(){let C=j();if(C)Z(C);let A=k(E);if(A&&A!==C)Z(A);try{D(z)}catch{}try{D(G)}catch{}try{D(b)}catch{}return new Promise((_)=>{let R=Date.now(),B=()=>{let O=k(E);if(!O)return _(!0);if(Date.now()-R>5000)return _(!1);Z(O),setTimeout(B,500)};B()})}async function LC(){let C=process.argv[2];if(C==="--kill"){if(X(G,b)){try{D(G)}catch{}try{D(b)}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(X(G,b)){try{let H=w(u(G,"utf8"));console.log(`Reusing existing browser — ${H}`)}catch{console.log("Reusing existing browser.")}return}let K=j()||k(E);if(K)console.log(`Running — pid ${K}, port ${E}`);else console.log("Not running.");return}let A=await P({activePortFile:G,modeFile:b,excludePorts:j()?[E]:[],autoPorts:j()?[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 _=S();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(f,{recursive:!0});let R=[`--remote-debugging-port=${E}`,"--disable-features=DevToolsPrivacyUI","--no-first-run","--no-default-browser-check","--disable-default-apps",`--user-data-dir=${f}`,"--profile-directory=Default","--new-window","about:blank"];console.log("Launching visible Chrome...");let B=YC(_.path,R,{detached:!0,stdio:"ignore"});B.unref();let O=B.pid;if($(z,String(O)),$(b,"visible","utf8"),console.log(`Chrome PID: ${O}`),!await DC())console.error("Chrome did not become ready within 15s."),process.exit(1);await bC(E),console.log("Visible Chrome ready on port 9222."),console.log("Keep this terminal open to keep Chrome alive.")}LC();
2
+ import{spawn as m}from"node:child_process";import{fileURLToPath as E}from"node:url";import{basename as t}from"node:path";function s(o=process.env,i=process.execPath){let p=o.GREEDY_SEARCH_NODE||o.NODE_BINARY||o.NODE;if(p?.trim())return p.trim();let r=t(i||"").toLowerCase();if(r==="node"||r==="node.exe")return i;return"node"}var R=E(new URL("./launch.mjs",import.meta.url)),L=m(s(),[R,...process.argv.slice(2)],{stdio:"inherit",env:{...process.env,GREEDY_SEARCH_VISIBLE:"1"}});L.on("exit",(o,i)=>{if(i)process.kill(process.pid,i);process.exit(o??1)});
@@ -1,6 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import{execSync as R,spawn as jz}from"node:child_process";import{existsSync as E,mkdirSync as Az,readdirSync as Lz,readFileSync as b,unlinkSync as A,writeFileSync as C}from"node:fs";import c from"node:http";import{platform as I,tmpdir as S}from"node:os";import{join as D}from"node:path";import{existsSync as g,mkdirSync as s,readFileSync as H,renameSync as n,unlinkSync as r,writeFileSync as k}from"node:fs";import i from"node:http";import{platform as F}from"node:os";import{dirname as o}from"node:path";var w=[9222,9223],t=/^(0|false|no|off)$/i;function e(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&&t.test(String(J)))}function M(z){let J=Number.parseInt(String(z??""),10);return Number.isInteger(J)&&J>0&&J<65536?J:null}function zz(z){if(!z)return null;let J=String(z).trim();if(!J)return null;let K=new URL(J.includes("://")?J:`http://${J}`),Q=M(K.port)||(K.protocol==="https:"?443:80);return{host:K.hostname,port:Q,source:`env:${J}`}}function Jz(z){if(!z)return[];return String(z).split(/[,\s]+/).map(M).filter(Boolean)}function Kz({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 H("/proc/version","utf8")}catch{return""}})();return/microsoft|wsl/i.test(Q)}function Qz({env:z=process.env,platformName:J=F(),procVersionText:K=null,resolvConfText:Q=null}={}){let X=["localhost","127.0.0.1"];if(Kz({env:z,platformName:J,procVersionText:K})){let O=(Q??(()=>{try{return H("/etc/resolv.conf","utf8")}catch{return""}})()).match(/^\s*nameserver\s+([^\s#]+)/m);if(O)X.push(O[1]);X.push("host.docker.internal")}return e(X)}function Xz({env:z=process.env,hosts:J=Qz({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 G=zz(z[$]);if(G)X.push(G)}catch{}for(let $ of["GREEDY_SEARCH_EXISTING_CDP_PORT","DM_CUA_EXISTING_CDP_PORT","GREEDY_SEARCH_CDP_PORT","DM_CUA_CDP_PORT"]){let G=M(z[$]);if(!G)continue;for(let W of J)X.push({host:W,port:G,source:`env:${$}`})}let Y=Jz(z.GREEDY_SEARCH_EXISTING_CDP_PORTS);for(let $ of Y)for(let G of J)X.push({host:G,port:$,source:"env:GREEDY_SEARCH_EXISTING_CDP_PORTS"});let O=new Set(Q.filter(Boolean));if(P(z))for(let $ of K){if(O.has($))continue;for(let G of J)X.push({host:G,port:$,source:"auto"})}let Z=new Set;return X.filter(($)=>{let G=$.wsUrl||`${$.host}:${$.port}`;if(Z.has(G))return!1;return Z.add(G),!0})}async function Yz(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 O=i.get({host:K,port:Q,path:"/json/version",timeout:J},(Z)=>{let $="";Z.setEncoding("utf8"),Z.on("data",(G)=>$+=G),Z.on("end",()=>Y(Z.statusCode===200?$:null))});O.on("error",()=>Y(null)),O.setTimeout(J,()=>{O.destroy(),Y(null)})});if(!X)return null;try{let Y=JSON.parse(X);if(!Y.webSocketDebuggerUrl)return null;let O=y(Y.webSocketDebuggerUrl,z.source),Z=O.path||new URL(Y.webSocketDebuggerUrl).pathname;return{...O,host:K,port:Q,httpUrl:`http://${K}:${Q}`,wsUrl:`ws://${K}:${Q}${Z}`,path:Z}}catch{return null}}async function Zz(z={}){for(let J of Xz(z)){let K=await Yz(J,z);if(K)return K}return null}function $z(z){if(!z)throw Error("missing CDP endpoint");let J=new URL(z.wsUrl);return`${J.host}
3
- ${J.pathname}${J.search}
4
- `}function Gz(z,J){s(o(z),{recursive:!0});let K=`${z}.tmp-${process.pid}`;k(K,$z(J),"utf8");try{r(z)}catch{}n(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 Zz({env:K,excludePorts:Q,autoPorts:X});if(!Y)return null;if(Gz(z,Y),J)k(J,"existing","utf8");return Y}function Oz(z){return String(z||"").trim()==="existing"}function q(z,J){if(!J||!g(J))return!1;if(!Oz(H(J,"utf8")))return!1;return!!z&&g(z)}function Nz(z,J){let K=Number.parseInt(String(z??""),10);return Number.isInteger(K)&&K>1024&&K<65535?K:J}var j=Nz(process.env.GREEDY_SEARCH_PORT,9222),f=process.env.GREEDY_SEARCH_PROFILE_DIR||process.env.CDP_PROFILE_DIR||D(S(),"greedysearch-chrome-profile"),N=D(f,"DevToolsActivePort"),V=process.env.GREEDY_SEARCH_PID_FILE||D(S(),"greedysearch-chrome.pid"),L=process.env.GREEDY_SEARCH_MODE_FILE||D(S(),"greedysearch-chrome-mode"),Vz=/^(1|true|yes|on)$/i.test(process.env.GREEDY_SEARCH_ALLOW_PORT_CLEANUP??"1");function l(z){return z.find((J)=>J&&E(J))||null}function v(){let z=I();return l(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 l(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 Wz(){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",_z=[`--remote-debugging-port=${j}`,"--disable-features=DevToolsPrivacyUI","--no-first-run","--no-default-browser-check","--disable-default-apps","--disable-blink-features=AutomationControlled",`--user-data-dir=${f}`,"--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 Bz(z){try{let J=D(z,".."),Q=Lz(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 Dz(z){let J=[..._z];if(B()){J.push("--headless=new");let K=Bz(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 Rz=()=>process.env.GREEDY_SEARCH_VISIBLE==="1";function Iz(){try{if(!E(L))return!0;return b(L,"utf8").trim()==="headless"}catch{return!0}}async function Uz(){if(B())return;try{let z=await new Promise((O,Z)=>{c.get(`http://localhost:${j}/json/version`,($)=>{let G="";$.on("data",(W)=>G+=W),$.on("end",()=>O(JSON.parse(G)))}).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 O=++X;Y.set(O,{resolve:(Z)=>{let G=(Z.targetInfos||[]).find((U)=>U.type==="page");if(!G){Q.close();return}let W=++X;Y.set(W,{resolve:(U)=>{let a=U.windowId,x=++X;Y.set(x,{resolve:()=>{},reject:()=>{}}),Q.send(JSON.stringify({id:x,method:"Browser.setWindowBounds",params:{windowId:a,bounds:{windowState:"minimized"}}})),setTimeout(()=>Q.close(),500)},reject:()=>Q.close()}),Q.send(JSON.stringify({id:W,method:"Browser.getWindowForTarget",params:{targetId:G.targetId}}))},reject:()=>Q.close()}),Q.send(JSON.stringify({id:O,method:"Target.getTargets",params:{}}))},Q.onmessage=(O)=>{let Z=JSON.parse(O.data);if(Z.id&&Y.has(Z.id)){let{resolve:$,reject:G}=Y.get(Z.id);if(Y.delete(Z.id),Z.error)G?.(Z.error);else $?.(Z.result)}},setTimeout(()=>Q.close(),5000)}catch{}}function _(){if(!E(V))return!1;let z=Number.parseInt(b(V,"utf8").trim(),10);if(!z)return!1;try{return process.kill(z,0),z}catch{return!1}}function d(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 T(z){try{if(I()==="win32")R(`taskkill /F /T /PID ${z}`,{stdio:"ignore"});else process.kill(z,"SIGTERM");return!0}catch{return!1}}function Hz(){let z=d(j);if(!z)return;let J=_();if(J&&z===J)return;if(!Vz)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...`),T(z);try{A(V)}catch{}try{A(N)}catch{}try{A(L)}catch{}}function Mz(z,J=1000){return new Promise((K)=>{let Q=c.get(z,(X)=>{let Y="";X.on("data",(O)=>Y+=O),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 p(z=15000){let J=Date.now()+z;while(Date.now()<J){let{ok:K,body:Q}=await Mz(`http://localhost:${j}/json/version`,1500);if(K)try{let{webSocketDebuggerUrl:X}=JSON.parse(Q),Y=new URL(X).pathname;return C(N,`${j}
6
- ${Y}`,"utf8"),!0}catch{}await new Promise((X)=>setTimeout(X,400))}return!1}async function qz(){let z=process.argv[2];if(Hz(),z==="--kill"){if(q(N,L)){try{A(N)}catch{}try{A(L)}catch{}console.log("Detached from existing browser CDP endpoint; no browser process was killed.");return}let Z=_()||d(j);if(Z){let $=T(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(q(N,L)){try{let $=h(b(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}let Q=_();if(Q)if(process.env.GREEDY_SEARCH_VISIBLE==="1"&&!process.argv.includes("--headless")&&Iz()){console.log(`Headless browser running (pid ${Q}) but visible requested — killing...`),T(Q);try{A(V)}catch{}try{A(L)}catch{}}else{if(await p(5000)){console.log(`GreedySearch browser already running (pid ${Q}).`);return}console.log(`Stale PID ${Q} — launching fresh.`);try{A(V)}catch{}}let X=Wz();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(Az(f,{recursive:!0}),console.log(`Launching GreedySearch ${X.label} on port ${j}...`),B())console.log("Headless mode — no window will be shown");else if(!Rz())console.log("Window will be minimized");let Y=jz(X.path,Dz(X.path),{detached:!0,stdio:"ignore"});if(Y.unref(),C(V,String(Y.pid)),C(L,B()?"headless":"visible","utf8"),!await p())console.error(`${X.label} did not become ready within 15s.`),process.exit(1);if(B())console.log("Ready (headless).");else await Uz(),console.log("Ready.")}qz();
2
+ import{execFileSync as T,execSync as zt,spawn as gt}from"node:child_process";import{existsSync as o,mkdirSync as xt,readdirSync as jt,readFileSync as _,unlinkSync as U,writeFileSync as A}from"node:fs";import{platform as c,tmpdir as Wu}from"node:os";import{join as kt}from"node:path";import E from"node:http";function x(t,u=1000){return new Promise((f)=>{let $=E.get(t,(b)=>{let J="";b.on("data",(q)=>J+=q),b.on("end",()=>f({ok:b.statusCode===200,body:J}))});$.on("error",()=>f({ok:!1})),$.setTimeout(u,()=>{$.destroy(),f({ok:!1})})})}async function p(t){try{let u=await x(`http://localhost:${t}/json/version`);if(!u.ok)return;let f=JSON.parse(u.body),$=await x(`http://localhost:${t}/json/list`);if(!$.ok)return;let J=JSON.parse($.body).find((h)=>h.type==="page")?.id;if(!J)return;let q=f.webSocketDebuggerUrl;if(typeof q!=="string")return;let g=new URL(q);if(g.hostname!=="localhost"&&g.hostname!=="127.0.0.1")return;if(!/^ws:\/\/localhost:\d+/.test(`ws://${g.host}`))return;let n=new WebSocket(`ws://localhost:${t}${g.pathname}`);await new Promise((h)=>{let a=!1,I=setTimeout(()=>V(),5000),V=()=>{if(a)return;a=!0,clearTimeout(I);try{n.close()}catch{}h()};n.onopen=()=>{try{n.send(JSON.stringify({id:1,method:"Browser.getWindowForTarget",params:{targetId:J}}))}catch{V()}},n.onmessage=(i)=>{try{let w=JSON.parse(i.data);if(w.id===1&&w.result?.windowId)n.send(JSON.stringify({id:2,method:"Browser.setWindowBounds",params:{windowId:w.result.windowId,bounds:{windowState:"minimized"}}}));else if(w.id===2)V();else if(w.id===1)V()}catch{V()}},n.onerror=V})}catch{}}import{existsSync as j,mkdirSync as tt,readFileSync as y,writeFileSync as ut}from"node:fs";import{homedir as ft}from"node:os";import{join as m}from"node:path";import{tmpdir as $t}from"node:os";function bt(t,u=9222){let f=Number.parseInt(String(t??""),10);return Number.isInteger(f)&&f>1024&&f<65535?f:u}var Jt=$t().replaceAll("\\","/"),G=bt(process.env.GREEDY_SEARCH_PORT),W=(process.env.GREEDY_SEARCH_PROFILE_DIR||process.env.CDP_PROFILE_DIR||`${Jt}/greedysearch-chrome-profile`).replaceAll("\\","/"),S=`${W}/DevToolsActivePort`,L=process.env.GREEDY_SEARCH_PID_FILE||`${W}/browser.pid`,mt=process.env.CDP_PAGES_CACHE||`${W}/cdp-pages.json`,O=process.env.GREEDY_SEARCH_MODE_FILE||`${W}/browser-mode`,Gt=process.env.GREEDY_SEARCH_METADATA_FILE||`${W}/browser-metadata.json`,St=process.env.GREEDY_SEARCH_LAUNCH_LOCK_FILE||`${W}/browser-launch.lock`,Lt=process.env.GREEDY_SEARCH_ACTIVITY_FILE||`${W}/browser-last-activity`,Ot=(process.env.CDP_SOCKET_DIR||`${W}/cdp-sockets`).replaceAll("\\","/"),Dt=`${W}/visible-recovery.jsonl`,r=m(ft(),".dm"),K=m(r,"greedyconfig"),Y=["perplexity","google","chatgpt","gemini"],N="gemini";function Wt(){try{if(j(K)){let t=y(K,"utf8"),u=JSON.parse(t);if(Array.isArray(u.engines)&&u.engines.length>0&&u.engines.every((f)=>typeof f==="string")){let f=u.engines.filter((b)=>M[b]),$=u.engines.filter((b)=>!M[b]);if($.length>0)process.stderr.write(`[greedysearch] Warning: ignoring unknown engine(s) in ${K}: ${$.join(", ")}
3
+ [greedysearch] Available engines: ${Object.keys(M).join(", ")}
4
+ `);if(f.length>0)return f;process.stderr.write(`[greedysearch] Warning: no valid engines in ${K}, falling back to defaults: ${Y.join(", ")}
5
+ `)}}}catch{}return Y}function qt(){try{if(!j(r))tt(r,{recursive:!0});if(!j(K))ut(K,JSON.stringify({engines:Y,synthesizer:N},null,2)+`
6
+ `,"utf8")}catch{}}qt();var l=["gemini","chatgpt"];function Qt(){try{if(j(K)){let t=y(K,"utf8"),u=JSON.parse(t);if(typeof u.synthesizer==="string"){let f=u.synthesizer.toLowerCase();if(l.includes(f))return f;process.stderr.write(`[greedysearch] Warning: unknown synthesizer "${u.synthesizer}" in ${K}
7
+ [greedysearch] Available synthesizers: ${l.join(", ")}
8
+ [greedysearch] Falling back to default: ${N}
9
+ `)}}}catch{}return N}var M={perplexity:"perplexity.mjs",p:"perplexity.mjs",bing:"bing-copilot.mjs",b:"bing-copilot.mjs",google:"google-ai.mjs",g:"google-ai.mjs",gemini:"gemini.mjs",gem:"gemini.mjs",chatgpt:"chatgpt.mjs",gpt:"chatgpt.mjs","semantic-scholar":"semantic-scholar.mjs",semanticscholar:"semantic-scholar.mjs",s2:"semantic-scholar.mjs",logically:"logically.mjs",log:"logically.mjs"},et=Wt();var Pt=Qt(),Ft=Math.max(1,Number.parseInt(process.env.GREEDY_FETCH_CONCURRENCY||"5",10)||5);process.env.CDP_PROFILE_DIR=W;import{execFileSync as Bt}from"node:child_process";import{platform as Xt}from"node:os";import{existsSync as D}from"node:fs";import{platform as Kt}from"node:os";import{join as B}from"node:path";function Z(t){let u=Kt()==="win32",f=process.env.SystemRoot||"C:\\Windows",$={win32:{powershell:B(f,"System32","WindowsPowerShell","v1.0","powershell.exe"),powershell_ise:B(f,"System32","WindowsPowerShell","v1.0","powershell_ise.exe"),netstat:B(f,"System32","netstat.exe"),taskkill:B(f,"System32","taskkill.exe"),tasklist:B(f,"System32","tasklist.exe"),cmd:B(f,"System32","cmd.exe")},unix:{ps:"/usr/bin/ps",lsof:"/usr/bin/lsof",ss:"/usr/sbin/ss",grep:"/usr/bin/grep",kill:"/usr/bin/kill"}},b=u?$.win32:$.unix,J=t.toLowerCase();if(b[J]&&D(b[J]))return b[J];if(u&&J==="netstat"){let q=B(f,"Sysnative","netstat.exe");if(D(q))return q}return t}function nt(t,u){return Bt(Z(t),u,{encoding:"utf8",stdio:["ignore","pipe","ignore"],timeout:5000})}function Vt(t){let u=String(t||"").match(/\b(\d+)\b/);return u?Number.parseInt(u[1],10):null}function Zt(t){return Vt(t)}function Ut(t,u){for(let f of String(t||"").split(/\r?\n/)){if(!/\bLISTEN\b/i.test(f))continue;if(!f.trim().split(/\s+/).slice(0,6).some((J)=>J.endsWith(`:${u}`)))continue;let b=f.match(/\bpid=(\d+)\b/);if(b)return Number.parseInt(b[1],10)}return null}function wt(t,u){for(let f of String(t||"").split(/\r?\n/)){let $=f.trim().split(/\s+/);if($.length<5||$[0].toUpperCase()!=="TCP")continue;if(!$.at(-2)?.toUpperCase().startsWith("LISTEN"))continue;if(!$[1].endsWith(`:${u}`))continue;let b=Number.parseInt($.at(-1),10);if(Number.isInteger(b)&&b>0)return b}return null}function C(t,u,f){try{return t(u,f)}catch{return null}}function e(t,{platformName:u=Xt(),run:f=nt}={}){if(u==="win32")return wt(C(f,"netstat",["-ano","-p","TCP"]),t);let $=C(f,"lsof",["-nP",`-iTCP:${t}`,"-sTCP:LISTEN","-t"]),b=Zt($);if(b)return b;if(u!=="linux")return null;return Ut(C(f,"ss",["-ltnp"]),t)}var Q=G,s=W,d=S,X=L,z=O;function vt(){let t=c();return(t==="win32"?["C:/Program Files/Google/Chrome/Application/chrome.exe","C:/Program Files (x86)/Google/Chrome/Application/chrome.exe"]:t==="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"]).find(o)||null}var k=()=>process.env.GREEDY_SEARCH_VISIBLE!=="1",At=[`--remote-debugging-port=${Q}`,"--disable-features=DevToolsPrivacyUI","--no-first-run","--no-default-browser-check","--disable-default-apps","--disable-blink-features=AutomationControlled",`--user-data-dir=${s}`,"--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 Ht(t){try{let u=kt(t,".."),$=jt(u).find((b)=>/^\d{1,10}\.\d{1,10}\.\d{1,10}\.\d{1,10}$/.test(b));if($)return $.split(".")[0]}catch{}try{let f=zt(`"${t}" --version`,{encoding:"utf8",timeout:5000}).trim().match(/(\d{1,10})\.\d{1,10}\.\d{1,10}/);if(f)return f[1]}catch{}return null}function ht(t){let u=[...At];if(k()){u.push("--headless=new");let f=Ht(t)||"136";u.push(`--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${f}.0.0.0 Safari/537.36`)}return u.push("about:blank"),u}var Mt=()=>process.env.GREEDY_SEARCH_VISIBLE==="1";function rt(){try{if(!o(z))return!0;return _(z,"utf8").trim()==="headless"}catch{return!0}}function Yt(t){try{if(c()==="win32")return T(Z("powershell"),["-NoProfile","-NonInteractive","-Command",`(Get-CimInstance Win32_Process -Filter "ProcessId = ${t}").CommandLine`],{encoding:"utf8",windowsHide:!0,timeout:5000}).trim()||null;return T(Z("ps"),["-p",String(t),"-o","command="],{encoding:"utf8",timeout:5000}).trim()||null}catch{return null}}function Nt(t,u=s,f=Q){let $=String(t||"").replaceAll("\\","/"),b=String(u||"").replaceAll("\\","/");return $.includes(`--remote-debugging-port=${f}`)&&$.includes(`--user-data-dir=${b}`)&&!$.includes("--type=")}function H(t){if(!Number.isInteger(t)||t<=0)return!1;try{process.kill(t,0)}catch{return!1}return Nt(Yt(t))}function v(){if(!o(X))return!1;let t=Number.parseInt(_(X,"utf8").trim(),10);return H(t)?t:!1}function R(t){return e(t)}function Ct(){let t=R(Q);return H(t)?t:null}function P(t){if(!H(t))return!1;try{if(c()==="win32")T(Z("taskkill"),["/F","/T","/PID",String(t)],{stdio:"ignore",windowsHide:!0});else process.kill(t,"SIGTERM");return!0}catch{return!1}}function Tt(){let t=R(Q);if(!t)return!0;let u=v();if(u&&t===u)return!0;if(H(t))return A(X,String(t),"utf8"),!0;return console.error(`Browser/CDP port ${Q} is owned by unverified pid ${t}; refusing to kill it. Set GREEDY_SEARCH_PORT to a free port.`),!1}async function F(t=15000){let u=Date.now()+t;while(Date.now()<u){let{ok:f,body:$}=await x(`http://localhost:${Q}/json/version`,1500);if(f)try{let{webSocketDebuggerUrl:b}=JSON.parse($),J=new URL(b).pathname;return A(d,`${Q}
10
+ ${J}`,"utf8"),!0}catch{}await new Promise((b)=>setTimeout(b,400))}return!1}async function ot(){let t=process.argv[2];if(!Tt()){process.exitCode=1;return}if(t==="--kill"){let J=v()||Ct();if(J){let q=P(J);console.log(q?`Stopped Chrome (pid ${J}).`:`Failed to stop pid ${J}.`)}else console.log("GreedySearch Chrome is not running.");try{U(X)}catch{}try{U(d)}catch{}try{U(z)}catch{}return}if(t==="--status"){let J=v();if(J)console.log(`Running — pid ${J}, port ${Q}`);else console.log("Not running.");return}let u=v();if(u)if(process.env.GREEDY_SEARCH_VISIBLE==="1"&&!process.argv.includes("--headless")&&rt()){console.log(`Headless Chrome running (pid ${u}) but visible requested — killing...`),P(u);try{U(X)}catch{}try{U(z)}catch{}}else{if(await F(5000)){console.log(`GreedySearch Chrome already running (pid ${u}).`);return}console.log(`Stale PID ${u} — launching fresh.`);try{U(X)}catch{}}let f=process.env.CHROME_PATH||vt();if(!f)console.error("Chrome not found. Set CHROME_PATH env var."),process.exit(1);if(xt(s,{recursive:!0}),console.log(`Launching GreedySearch Chrome on port ${Q}...`),k())console.log("Headless mode — no window will be shown");else if(!Mt())console.log("Window will be minimized");let $=gt(f,ht(f),{detached:!0,stdio:"ignore"});if($.unref(),A(X,String($.pid)),A(z,k()?"headless":"visible","utf8"),!await F())console.error("Chrome did not become ready within 15s."),process.exit(1);if(k())console.log("Ready (headless).");else await p(Q),console.log("Ready.")}ot();export{Nt as commandLineMatchesGreedyBrowser};