@duckmind/dm-darwin-arm64 0.52.6 → 0.53.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.
Files changed (58) hide show
  1. package/dm +0 -0
  2. package/extensions/.dm-extensions.json +14 -10
  3. package/extensions/dm-cua/bin/browser-cua.mjs +6 -6
  4. package/extensions/dm-cua/index.js +5 -5
  5. package/extensions/dm-cua/src/browser-cua-lib.mjs +2 -2
  6. package/extensions/greedysearch-dm/bin/cdp-greedy.mjs +8 -1
  7. package/extensions/greedysearch-dm/bin/cdp-headless.mjs +1 -1
  8. package/extensions/greedysearch-dm/bin/cdp-visible.mjs +1 -1
  9. package/extensions/greedysearch-dm/bin/cdp.mjs +29 -20
  10. package/extensions/greedysearch-dm/bin/gschrome.mjs +1 -8
  11. package/extensions/greedysearch-dm/bin/kill-visible.mjs +1 -1
  12. package/extensions/greedysearch-dm/bin/launch-visible.mjs +1 -2
  13. package/extensions/greedysearch-dm/bin/launch.mjs +9 -11
  14. package/extensions/greedysearch-dm/bin/mcp.mjs +375 -0
  15. package/extensions/greedysearch-dm/bin/search.mjs +309 -157
  16. package/extensions/greedysearch-dm/bin/visible.mjs +1 -1
  17. package/extensions/greedysearch-dm/extractors/bing-copilot.mjs +205 -68
  18. package/extensions/greedysearch-dm/extractors/chatgpt.mjs +229 -140
  19. package/extensions/greedysearch-dm/extractors/common.mjs +160 -50
  20. package/extensions/greedysearch-dm/extractors/consensus.mjs +226 -93
  21. package/extensions/greedysearch-dm/extractors/consent.mjs +44 -17
  22. package/extensions/greedysearch-dm/extractors/gemini.mjs +277 -138
  23. package/extensions/greedysearch-dm/extractors/google-ai.mjs +172 -64
  24. package/extensions/greedysearch-dm/extractors/logically.mjs +183 -69
  25. package/extensions/greedysearch-dm/extractors/perplexity.mjs +331 -65
  26. package/extensions/greedysearch-dm/extractors/semantic-scholar.mjs +118 -41
  27. package/extensions/greedysearch-dm/index.js +23 -20
  28. package/extensions/greedysearch-dm/package.json +8 -3
  29. package/extensions/greedysearch-dm/skills/greedy-search/skill.md +8 -8
  30. package/extensions/greedysearch-dm/src/fetcher.mjs +2 -2
  31. package/extensions/greedysearch-dm/src/formatters/results.js +8 -6
  32. package/extensions/greedysearch-dm/src/github.mjs +7 -7
  33. package/extensions/greedysearch-dm/src/reddit.mjs +1 -1
  34. package/extensions/greedysearch-dm/src/search/browser-lifecycle.mjs +10 -8
  35. package/extensions/greedysearch-dm/src/search/challenge-detect.mjs +48 -0
  36. package/extensions/greedysearch-dm/src/search/chrome.mjs +130 -54
  37. package/extensions/greedysearch-dm/src/search/constants.mjs +6 -6
  38. package/extensions/greedysearch-dm/src/search/engines.mjs +9 -9
  39. package/extensions/greedysearch-dm/src/search/fetch-source.mjs +160 -83
  40. package/extensions/greedysearch-dm/src/search/minimize.mjs +1 -0
  41. package/extensions/greedysearch-dm/src/search/paths.mjs +1 -1
  42. package/extensions/greedysearch-dm/src/search/pdf.mjs +1 -1
  43. package/extensions/greedysearch-dm/src/search/port-pid.mjs +1 -1
  44. package/extensions/greedysearch-dm/src/search/progress.mjs +2 -0
  45. package/extensions/greedysearch-dm/src/search/recovery.mjs +1 -1
  46. package/extensions/greedysearch-dm/src/search/research.mjs +262 -167
  47. package/extensions/greedysearch-dm/src/search/scale-aware.mjs +11 -0
  48. package/extensions/greedysearch-dm/src/search/simple-research.mjs +827 -0
  49. package/extensions/greedysearch-dm/src/search/synthesis-runner.mjs +9 -9
  50. package/extensions/greedysearch-dm/src/search/synthesis.mjs +10 -10
  51. package/extensions/greedysearch-dm/src/tools/greedy-search-handler.js +23 -20
  52. package/extensions/greedysearch-dm/src/tools/shared.js +10 -9
  53. package/extensions/greedysearch-dm/src/utils/node-runtime.mjs +1 -1
  54. package/package.json +1 -1
  55. package/extensions/greedysearch-dm/src/search/cdp-endpoint.mjs +0 -3
  56. package/extensions/greedysearch-dm/src/search/launcher-paths.mjs +0 -3
  57. package/extensions/greedysearch-dm/src/search/partial-output.mjs +0 -1
  58. package/extensions/greedysearch-dm/src/utils/browser-executable.mjs +0 -1
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
- import{randomInt as oe}from"node:crypto";import{spawn as le}from"node:child_process";import{dirname as fe,join as ae}from"node:path";import{fileURLToPath as ce}from"node:url";import{basename as ge}from"node:path";function se(t=process.env,e=process.execPath){let n=t.GREEDY_SEARCH_NODE||t.NODE_BINARY||t.NODE;if(n?.trim())return n.trim();let r=ge(e||"").toLowerCase();if(r==="node"||r==="node.exe")return e;return"node"}var be=fe(ce(import.meta.url)),he=ae(be,"..","bin","cdp.mjs");function g(t,e=30000){return d(t,null,e)}function d(t,e=null,n=30000){return new Promise((r,i)=>{let u=le(se(),[he,...t],{stdio:[e==null?"ignore":"pipe","pipe","pipe"]});if(e!=null)u.stdin.write(e),u.stdin.end();let o="",f="";u.stdout.on("data",(a)=>o+=a),u.stderr.on("data",(a)=>f+=a);let l=setTimeout(()=>{u.kill(),i(Error(`cdp timeout: ${t[0]}`))},n);u.on("close",(a)=>{if(clearTimeout(l),a===0)r(o.trim());else i(Error(f.trim()||`cdp exit ${a}`))})})}async function st(t){if(t)return t;let e=(await g(["list"])).split(`
3
- `)[0]?.slice(0,8);if(!e)throw Error("No Chrome tabs found. Is Chrome running with --remote-debugging-port=9222?");let n=await g(["evalraw",e,"Target.createTarget",'{"url":"about:blank"}']),{targetId:r}=JSON.parse(n);await g(["list"]);let i=r.slice(0,8);try{await ht(i)}catch(u){process.stderr.write(`[getOrOpenTab] stealth injection failed: ${u.message}
4
- `)}return i}async function bt(t,e){let n=`
2
+ import{randomInt as at}from"node:crypto";import{spawn as lt}from"node:child_process";import{basename as ut}from"node:path";import{dirname as ct,join as ft}from"node:path";import{fileURLToPath as gt}from"node:url";function st(e=process.env,t=process.execPath){let n=e.GREEDY_SEARCH_NODE||e.NODE_BINARY||e.NODE;if(n?.trim())return n.trim();let i=ut(t||"").toLowerCase();if(i==="node"||i==="node.exe")return t;return"node"}var ht=ct(gt(import.meta.url)),pt=ft(ht,"..","bin","cdp.mjs"),mt=new Set(["list","snap","eval","shot","html","nav","net","click","clickxy","type","loadall","evalraw","browse","stop","--tab"]);function yt(e){if(!Array.isArray(e)||e.length===0)throw Error("cdp: args must be a non-empty array");if(e[0]==="test")return e.map((t,n)=>pe(t,n));if(!mt.has(e[0]))throw Error(`cdp: unknown subcommand '${e[0]}'`);return e.map((t,n)=>pe(t,n))}function pe(e,t){if(typeof e!=="string")throw Error(`cdp: argv[${t}] must be a string (got ${typeof e})`);if(e.includes("\x00"))throw Error(`cdp: argv[${t}] contains a null byte`);return e}function h(e,t=30000){return ee(e,null,t)}function ee(e,t=null,n=30000){let i=yt(e);return new Promise((r,o)=>{let a=lt(st(),[pt,...i],{stdio:[t==null?"ignore":"pipe","pipe","pipe"]});if(t!=null)a.stdin.write(t),a.stdin.end();let l="",u="";a.stdout.on("data",(s)=>l+=s),a.stderr.on("data",(s)=>u+=s);let f=setTimeout(()=>{a.kill(),o(Error(`cdp timeout: ${e[0]}`))},n);a.on("close",(s)=>{if(clearTimeout(f),s===0)r(l.trim());else o(Error(u.trim()||`cdp exit ${s}`))})})}function me(e,t){let n=(a)=>String(a??"").replace(/\s+/g," ").trim(),i=n(e),r=n(t);if(!r)return!1;if(i.length<Math.ceil(r.length*0.8))return!1;let o=Math.min(40,r.length);return i.includes(r.slice(0,o))&&i.includes(r.slice(-o))}async function ye(e){if(e)return e;let t=(await h(["list"])).split(`
3
+ `)[0]?.slice(0,8);if(!t)throw Error("No Chrome tabs found. Is Chrome running with --remote-debugging-port=9222?");let n=await h(["evalraw",t,"Target.createTarget",'{"url":"about:blank"}']),i;try{i=JSON.parse(n)}catch(a){throw Error(`Target.createTarget returned invalid JSON: ${a.message}`)}let{targetId:r}=i;if(!r)throw Error("Target.createTarget did not return a targetId");await h(["list"]);let o=r.slice(0,8);try{await be(o)}catch(a){process.stderr.write(`[getOrOpenTab] stealth injection failed: ${a.message}
4
+ `)}return o}async function de(e,t){let n=`
5
5
  (() => {
6
- window.${e} = null;
6
+ window.${t} = null;
7
7
  const _clipboard = navigator.clipboard;
8
8
  if (!_clipboard) return;
9
9
  const _origWriteText = typeof _clipboard.writeText === 'function'
@@ -14,7 +14,7 @@ import{randomInt as oe}from"node:crypto";import{spawn as le}from"node:child_proc
14
14
  : null;
15
15
 
16
16
  _clipboard.writeText = function(text) {
17
- window.${e} = String(text ?? '');
17
+ window.${t} = String(text ?? '');
18
18
  if (!_origWriteText) return Promise.resolve();
19
19
  // The OS/browser clipboard write may be denied in automated Chrome or
20
20
  // when the tab is not focused. We only need the captured text; returning
@@ -28,7 +28,7 @@ import{randomInt as oe}from"node:crypto";import{spawn as le}from"node:child_proc
28
28
  for (const item of items || []) {
29
29
  if (item.types && item.types.includes('text/plain')) {
30
30
  const blob = await item.getType('text/plain');
31
- window.${e} = await blob.text();
31
+ window.${t} = await blob.text();
32
32
  break;
33
33
  }
34
34
  }
@@ -38,7 +38,26 @@ import{randomInt as oe}from"node:crypto";import{spawn as le}from"node:child_proc
38
38
  catch (_) { return undefined; }
39
39
  };
40
40
  })();
41
- `;await g(["eval",t,n])}async function ht(t){await g(["evalraw",t,"Page.addScriptToEvaluateOnNewDocument",JSON.stringify({source:`
41
+ `;await h(["eval",e,n])}async function te(e,t,n,i={}){let{timeoutMs:r=2600}=i,o=i.retryClick!=null?i.retryClick:Math.floor(r*0.4),a=String.raw`
42
+ new Promise((resolve) => {
43
+ const _deadline = Date.now() + ${r};
44
+ const _retryAt = Date.now() + ${o};
45
+ let _retried = false;
46
+ function _click() { try { ${t}; } catch(_) {} }
47
+ function _poll() {
48
+ const val = window.${n};
49
+ if (val) { resolve(val); return; }
50
+ if (!_retried && Date.now() >= _retryAt) {
51
+ _retried = true;
52
+ _click();
53
+ }
54
+ if (Date.now() < _deadline) { setTimeout(_poll, 100); }
55
+ else { resolve(window.${n} || ''); }
56
+ }
57
+ _click();
58
+ _poll();
59
+ })
60
+ `;return await h(["eval",e,a],r+5000).catch(()=>"")}async function be(e){await h(["evalraw",e,"Page.addScriptToEvaluateOnNewDocument",JSON.stringify({source:`
42
61
  (function() {
43
62
  // ── Runtime.enable / CDP detection masking ──────────────
44
63
  try { delete window.__REBROWSER_RUNTIME_ENABLE; } catch(_) {}
@@ -49,40 +68,62 @@ import{randomInt as oe}from"node:crypto";import{spawn as le}from"node:child_proc
49
68
  try { delete window._phantom; } catch(_) {}
50
69
  try { delete window.Buffer; } catch(_) {}
51
70
 
52
- // Real Chrome without automation does not expose a useful webdriver value.
53
- // A literal false value is itself a common stealth tell; prefer undefined and
54
- // make the descriptor configurable like native browser properties.
55
- Object.defineProperty(navigator, 'webdriver', { get: () => undefined, configurable: true });
71
+ // Real Chrome without automation should not expose navigator.webdriver at all.
72
+ // A literal false or an own-property getter returning undefined is itself a
73
+ // common stealth tell; remove both instance and prototype properties when the
74
+ // descriptor is configurable (as it is with --disable-blink-features).
75
+ try { delete navigator.webdriver; } catch(_) {}
76
+ try { delete Navigator.prototype.webdriver; } catch(_) {}
56
77
  Object.defineProperty(navigator, 'vendor', { get: () => 'Google Inc.', configurable: true });
57
78
  Object.defineProperty(navigator, 'platform', { get: () => 'Win32', configurable: true });
58
79
  Object.defineProperty(navigator, 'maxTouchPoints', { get: () => 0, configurable: true });
59
80
  Object.defineProperty(navigator, 'pdfViewerEnabled', { get: () => true, configurable: true });
81
+ Object.defineProperty(navigator, 'productSub', { get: () => '20030107', configurable: true });
82
+ Object.defineProperty(navigator, 'product', { get: () => 'Gecko', configurable: true });
83
+ var __greedyMimeTypes = null;
84
+ function __makeMimeTypes() {
85
+ var pdf = { type: 'application/pdf', suffixes: 'pdf', description: 'Portable Document Format', enabledPlugin: null };
86
+ var textPdf = { type: 'text/pdf', suffixes: 'pdf', description: 'Portable Document Format', enabledPlugin: null };
87
+ try { Object.setPrototypeOf(pdf, MimeType.prototype); } catch(_) {}
88
+ try { Object.setPrototypeOf(textPdf, MimeType.prototype); } catch(_) {}
89
+ var m = [pdf, textPdf];
90
+ try { Object.setPrototypeOf(m, MimeTypeArray.prototype); } catch(_) {}
91
+ m.item = function item(i) { return this[i] || null; };
92
+ m.namedItem = function namedItem(name) { return Array.prototype.find.call(this, function(x) { return x && x.type === name; }) || null; };
93
+ return m;
94
+ }
60
95
  Object.defineProperty(navigator, 'plugins', {
61
96
  get: () => {
62
- var p = [
63
- { name: 'Chrome PDF Plugin', filename: 'internal-pdf-viewer', description: 'Portable Document Format' },
64
- { name: 'Chrome PDF Viewer', filename: 'mhjfbmdgcfjbbpaeojofohoefgiehjai', description: '' },
65
- { name: 'Native Client', filename: 'internal-nacl-plugin', description: '' },
66
- ];
67
- p.length = 3;
97
+ __greedyMimeTypes = __greedyMimeTypes || __makeMimeTypes();
98
+ var plugin0 = { name: 'Chrome PDF Plugin', filename: 'internal-pdf-viewer', description: 'Portable Document Format' };
99
+ var plugin1 = { name: 'Chrome PDF Viewer', filename: 'mhjfbmdgcfjbbpaeojofohoefgiehjai', description: '' };
100
+ var plugin2 = { name: 'Native Client', filename: 'internal-nacl-plugin', description: '' };
101
+ try { Object.setPrototypeOf(plugin0, Plugin.prototype); } catch(_) {}
102
+ try { Object.setPrototypeOf(plugin1, Plugin.prototype); } catch(_) {}
103
+ try { Object.setPrototypeOf(plugin2, Plugin.prototype); } catch(_) {}
104
+ var p = [plugin0, plugin1, plugin2];
105
+ p.item = function item(i) { return this[i] || null; };
106
+ p.namedItem = function namedItem(name) { return Array.prototype.find.call(this, function(x) { return x && x.name === name; }) || null; };
107
+ p.refresh = function refresh() {};
108
+ try { Object.setPrototypeOf(p, PluginArray.prototype); } catch(_) {}
109
+ try {
110
+ __greedyMimeTypes[0].enabledPlugin = p[0];
111
+ __greedyMimeTypes[1].enabledPlugin = p[0];
112
+ } catch(_) {}
68
113
  return p;
69
114
  },
115
+ configurable: true,
70
116
  });
71
117
  Object.defineProperty(navigator, 'mimeTypes', {
72
118
  get: () => {
73
- var m = [
74
- { type: 'application/pdf', suffixes: 'pdf', description: 'Portable Document Format', enabledPlugin: null },
75
- { type: 'text/pdf', suffixes: 'pdf', description: 'Portable Document Format', enabledPlugin: null },
76
- ];
77
- m.item = function(i) { return m[i] || null; };
78
- m.namedItem = function(name) { return m.find(function(x) { return x.type === name; }) || null; };
79
- return m;
119
+ __greedyMimeTypes = __greedyMimeTypes || __makeMimeTypes();
120
+ return __greedyMimeTypes;
80
121
  },
81
122
  configurable: true,
82
123
  });
83
124
  Object.defineProperty(navigator, 'languages', { get: () => ['en-US', 'en'], configurable: true });
84
125
  try {
85
- Object.defineProperty(navigator, 'connection', { get: () => ({ effectiveType: '4g', rtt: 50, downlink: 10, saveData: false }), configurable: true });
126
+ Object.defineProperty(navigator, 'connection', { get: () => ({ effectiveType: '4g', rtt: 50, downlink: 10, downlinkMax: Infinity, saveData: false }), configurable: true });
86
127
  } catch(_) {}
87
128
  if (!navigator.mediaDevices) {
88
129
  Object.defineProperty(navigator, 'mediaDevices', {
@@ -98,6 +139,18 @@ import{randomInt as oe}from"node:crypto";import{spawn as le}from"node:child_proc
98
139
  configurable: true,
99
140
  });
100
141
  }
142
+ // ── Missing platform APIs (headless often lacks these) ─
143
+ try {
144
+ if (!navigator.share) {
145
+ navigator.share = function() { return Promise.reject(new Error('NotAllowedError')); };
146
+ }
147
+ } catch(_) {}
148
+ try {
149
+ if (!navigator.contentIndex) {
150
+ Object.defineProperty(navigator, 'contentIndex', { get: () => ({ add: function() {}, delete: function() {}, getAll: function() { return Promise.resolve([]); } }), configurable: true });
151
+ }
152
+ } catch(_) {}
153
+
101
154
  if (!window.chrome) {
102
155
  window.chrome = {
103
156
  app: { isInstalled: false, InstallState: {}, RunningState: {} },
@@ -105,8 +158,8 @@ import{randomInt as oe}from"node:crypto";import{spawn as le}from"node:child_proc
105
158
  OnInstalledReason: {}, OnRestartRequiredReason: {}, PlatformArch: {}, PlatformNaclArch: {}, PlatformOs: {}, RequestUpdateCheckStatus: {},
106
159
  connect: () => ({}), sendMessage: () => {}, onMessage: { addListener: () => {} }
107
160
  },
108
- loadTimes: () => ({}),
109
- csi: () => ({}),
161
+ loadTimes: function() { return { requestTime: 0, startLoadTime: Date.now() - 5000, commitLoadTime: Date.now() - 3000, finishDocumentLoadTime: Date.now() - 2000, finishLoadTime: Date.now() - 1000, firstPaintTime: Date.now() - 800, navigationType: 'Other', wasFetchedViaSpdy: true, wasNpnNegotiated: true, npnNegotiatedProtocol: 'h2', wasAlternateProtocolAvailable: false, connectionInfo: 'http/2' }; },
162
+ csi: function() { var t = Date.now(); return { onloadT: t - 2000, startE: t - 5000, pageT: 'back', tran: 2 }; },
110
163
  };
111
164
  }
112
165
  var __greedyNativeFns = [];
@@ -127,6 +180,19 @@ import{randomInt as oe}from"node:crypto";import{spawn as le}from"node:child_proc
127
180
  return getParam.call(this, p);
128
181
  });
129
182
  } catch(_) {}
183
+ // ── WebGL readPixels noise ──────────────────────────
184
+ // CreepJS and other fingerprinters draw content with WebGL and read back the
185
+ // rendered pixels. Adding subtle noise breaks rendering-based fingerprinting.
186
+ try {
187
+ var origReadPixels = WebGLRenderingContext.prototype.readPixels;
188
+ WebGLRenderingContext.prototype.readPixels = __markNative(function readPixels(x, y, width, height, format, type, pixels) {
189
+ var result = origReadPixels.call(this, x, y, width, height, format, type, pixels);
190
+ if (pixels && pixels.length > 0) {
191
+ pixels[0] ^= 1;
192
+ }
193
+ return result;
194
+ });
195
+ } catch(_) {}
130
196
  Object.defineProperty(navigator, 'hardwareConcurrency', { get: () => 8, configurable: true });
131
197
  Object.defineProperty(navigator, 'deviceMemory', { get: () => 8, configurable: true });
132
198
 
@@ -134,7 +200,7 @@ import{randomInt as oe}from"node:crypto";import{spawn as le}from"node:child_proc
134
200
  // Headless rendering engines produce slightly different canvas output
135
201
  // than headed Chrome. Subtle noise breaks hash-based fingerprinting.
136
202
  try {
137
- var __canvasNoise = ((Date.now() % 997) + Math.floor(Math.random() * 997)) & 1;
203
+ var __canvasNoise = ((Date.now() & 0xFF) | 1);
138
204
  var origFill = CanvasRenderingContext2D.prototype.fillText;
139
205
  CanvasRenderingContext2D.prototype.fillText = __markNative(function fillText() {
140
206
  this.globalAlpha = 0.9995;
@@ -153,15 +219,39 @@ import{randomInt as oe}from"node:crypto";import{spawn as le}from"node:child_proc
153
219
  HTMLCanvasElement.prototype.toDataURL = __markNative(function toDataURL() {
154
220
  var ctx = this.getContext('2d');
155
221
  if (ctx) {
156
- // Add 1px noise pixel in corner (invisible but changes hash)
157
- var imgData = ctx.getImageData(0, 0, 1, 1);
158
- if (imgData) imgData.data[0] ^= __canvasNoise;
159
- ctx.putImageData(imgData, 0, 0);
222
+ // Spread noise across canvas to break hash-based fingerprinting.
223
+ // Uses a deterministic pattern so it's consistent per page load
224
+ // but varies between sessions.
225
+ var w = this.width, h = this.height;
226
+ if (w > 0 && h > 0) {
227
+ var imgData = ctx.getImageData(0, 0, Math.min(w, 4), Math.min(h, 4));
228
+ if (imgData && imgData.data) {
229
+ for (var __i = 0; __i < imgData.data.length; __i += 4) {
230
+ imgData.data[__i] ^= (__canvasNoise + __i) & 0xFF;
231
+ }
232
+ ctx.putImageData(imgData, 0, 0);
233
+ }
234
+ }
160
235
  }
161
236
  return origToDataURL.apply(this, arguments);
162
237
  });
163
238
  } catch(_) {}
164
239
 
240
+ // ── AudioContext fingerprint noise ────────────────────
241
+ // Headless Chrome's AudioContext produces slightly different output.
242
+ // Subtle noise breaks audio-based fingerprinting.
243
+ try {
244
+ var __audioSeed = ((Date.now() & 0x1F) | 1);
245
+ var origGetChannelData = AudioBuffer.prototype.getChannelData;
246
+ AudioBuffer.prototype.getChannelData = __markNative(function getChannelData(channel) {
247
+ var data = origGetChannelData.call(this, channel);
248
+ for (var __i = 0; __i < data.length; __i += 64) {
249
+ data[__i] *= 0.99999;
250
+ }
251
+ return data;
252
+ });
253
+ } catch(_) {}
254
+
165
255
  // ── window outer dimensions ──────────────────────────
166
256
  // outerWidth/Height = 0 in headless — a well-known bot signal.
167
257
  // Mirror innerWidth/Height (set by --window-size flag) so the ratio is sane.
@@ -171,9 +261,15 @@ import{randomInt as oe}from"node:crypto";import{spawn as le}from"node:child_proc
171
261
  } catch(_) {}
172
262
 
173
263
  // ── screen properties ─────────────────────────────────
264
+ // Headless Chrome often reports an 800x600 screen even when the viewport is
265
+ // 1920x1080. Keep screen metrics internally consistent with our launch flags.
174
266
  try {
175
- if (!screen.colorDepth) Object.defineProperty(screen, 'colorDepth', { get: () => 24, configurable: true });
176
- if (!screen.pixelDepth) Object.defineProperty(screen, 'pixelDepth', { get: () => 24, configurable: true });
267
+ Object.defineProperty(screen, 'width', { get: () => 1920, configurable: true });
268
+ Object.defineProperty(screen, 'height', { get: () => 1080, configurable: true });
269
+ Object.defineProperty(screen, 'availWidth', { get: () => 1920, configurable: true });
270
+ Object.defineProperty(screen, 'availHeight', { get: () => 1040, configurable: true });
271
+ Object.defineProperty(screen, 'colorDepth', { get: () => 24, configurable: true });
272
+ Object.defineProperty(screen, 'pixelDepth', { get: () => 24, configurable: true });
177
273
  } catch(_) {}
178
274
 
179
275
  // ── navigator.userAgentData (UA Client Hints) ─────────
@@ -246,12 +342,12 @@ import{randomInt as oe}from"node:crypto";import{spawn as le}from"node:child_proc
246
342
  };
247
343
  } catch(_) {}
248
344
  })();
249
- `})])}function yt(t){if(!t)return[];let e=[],n=0;while(n<t.length&&e.length<10){let r=t.indexOf("[",n);if(r===-1)break;let i=t.indexOf("](",r);if(i===-1)break;let u=i+2,o=-1;for(let f=u;f<t.length;f++){let l=t[f];if(l===")"){o=f;break}if(/\s/.test(l))break}if(o!==-1){let f=t.slice(r+1,i),l=t.slice(u,o);if(/^https?:\/\//i.test(l)&&f){if(!e.some((a)=>a.url===l))e.push({title:f,url:l})}n=o+1}else n=r+1}return e}var C={postNav:800,postNavSlow:1200,postClick:300,postType:300,inputPoll:400,copyPoll:600,afterVerify:1500};function j(t){let e=t*0.4,n=oe(-Math.floor(e),Math.floor(e)+1);return Math.max(50,Math.round(t+n))}async function wt(t,e={}){let{timeout:n=20000,interval:r=600,stableRounds:i=3,selector:u="document.body",minLength:o=0}=e,f=String.raw`
345
+ `})])}function ve(e){if(!e)return[];let t=[],n=0;while(n<e.length&&t.length<10){let i=e.indexOf("[",n);if(i===-1)break;let r=e.indexOf("](",i);if(r===-1)break;let o=r+2,a=-1;for(let l=o;l<e.length;l++){let u=e[l];if(u===")"){a=l;break}if(/\s/.test(u))break}if(a!==-1){let l=e.slice(i+1,r),u=e.slice(o,a);if(/^https?:\/\//i.test(u)&&l){if(!t.some((f)=>f.url===u))t.push({title:l,url:u})}n=a+1}else n=i+1}return t}var Q={postNav:800,postNavSlow:1200,postClick:300,postType:300,inputPoll:400,copyPoll:600,afterVerify:1500};function B(e){let t=e*0.2,n=at(-Math.floor(t),Math.floor(t)+1);return Math.max(50,Math.round(e+n))}async function we(e,t={}){let{timeout:n=20000,interval:i=600,stableRounds:r=3,selector:o="document.body",minLength:a=0,isStreamingExpr:l="false"}=t,u=String.raw`
250
346
  new Promise((resolve, reject) => {
251
347
  const _deadline = Date.now() + ${n};
252
- const _baseInterval = ${r};
253
- const _stableRounds = ${i};
254
- const _minLength = ${o};
348
+ const _baseInterval = ${i};
349
+ const _stableRounds = ${r};
350
+ const _minLength = ${a};
255
351
  let _lastLen = -1;
256
352
  let _stableCount = 0;
257
353
 
@@ -262,9 +358,13 @@ import{randomInt as oe}from"node:crypto";import{spawn as le}from"node:child_proc
262
358
  function _poll() {
263
359
  try {
264
360
  // Re-query DOM each tick — element may not exist at eval start
265
- const el = ${u};
266
- const cur = el?.innerText?.length ?? 0;
267
- if (cur >= _minLength) {
361
+ const el = ${o};
362
+ const cur = el?.textContent?.length ?? 0;
363
+ const streaming = ${l};
364
+ if (streaming) {
365
+ if (cur !== _lastLen) _lastLen = cur;
366
+ _stableCount = 0;
367
+ } else if (cur >= _minLength) {
268
368
  if (cur === _lastLen) {
269
369
  _stableCount++;
270
370
  if (_stableCount >= _stableRounds) { resolve(cur); return; }
@@ -276,7 +376,7 @@ import{randomInt as oe}from"node:crypto";import{spawn as le}from"node:child_proc
276
376
  if (Date.now() < _deadline) {
277
377
  setTimeout(_poll, _jitter(_baseInterval));
278
378
  } else {
279
- if (_lastLen >= _minLength) { resolve(_lastLen); }
379
+ if (_lastLen >= _minLength && !streaming) { resolve(_lastLen); }
280
380
  else { reject(new Error('Generation did not stabilise within ${n}ms')); }
281
381
  }
282
382
  } catch(e) { reject(e); }
@@ -284,10 +384,10 @@ import{randomInt as oe}from"node:crypto";import{spawn as le}from"node:child_proc
284
384
 
285
385
  _poll();
286
386
  })
287
- `,l=await g(["eval",t,f],n+1e4),a=parseInt(l,10)||0;if(a>=o)return a;throw Error(`Generation did not stabilise within ${n}ms`)}async function vt(t,e,n=15000,r=500){let i=String.raw`
387
+ `,f=await h(["eval",e,u],n+1e4),s=parseInt(f,10)||0;if(s>=a)return s;throw Error(`Generation did not stabilise within ${n}ms`)}async function xe(e,t,n=15000,i=500){let r=String.raw`
288
388
  new Promise((resolve) => {
289
389
  const _deadline = Date.now() + ${n};
290
- const _baseInterval = ${r};
390
+ const _baseInterval = ${i};
291
391
 
292
392
  function _jitter(ms) {
293
393
  return Math.max(50, ms + (Math.random() * ms * 0.4 - ms * 0.2));
@@ -295,7 +395,7 @@ import{randomInt as oe}from"node:crypto";import{spawn as le}from"node:child_proc
295
395
 
296
396
  function _poll() {
297
397
  try {
298
- if (document.querySelector('${e}')) { resolve(true); return; }
398
+ if (document.querySelector('${t}')) { resolve(true); return; }
299
399
  if (Date.now() < _deadline) { setTimeout(_poll, _jitter(_baseInterval)); }
300
400
  else { resolve(false); }
301
401
  } catch(_) { resolve(false); }
@@ -303,27 +403,26 @@ import{randomInt as oe}from"node:crypto";import{spawn as le}from"node:child_proc
303
403
 
304
404
  _poll();
305
405
  })
306
- `;return await g(["eval",t,i],n+5000)==="true"}async function mt(t){let e=t.indexOf("--stdin");if(e===-1)return t;let n=await new Promise((i)=>{let u="";process.stdin.setEncoding("utf8"),process.stdin.on("data",(o)=>u+=o),process.stdin.on("end",()=>i(u.trim()))}),r=[...t];return r[e]=n,r}function xt(t){let e=t.includes("--short"),n=t.filter((f)=>f!=="--short"),r=n.indexOf("--tab"),i=r===-1?null:n[r+1];if(r!==-1)n=n.filter((f,l)=>l!==r&&l!==r+1);let u=n.indexOf("--locale"),o=u===-1?null:n[u+1];if(u!==-1)n=n.filter((f,l)=>l!==u&&l!==u+1);return{query:n.join(" "),tabPrefix:i,short:e,locale:o}}function $t(t,e){if(!t.length||t[0]==="--help")process.stderr.write(e),process.exit(1)}function Jt(t,e,n=300){if(!e||t.length<=n)return t;let r=t.slice(0,n),i=r.lastIndexOf(" ");return i>0?`${r.slice(0,i)}…`:`${r}…`}function pt(t){process.stdout.write(`${JSON.stringify(t,null,2)}
307
- `)}function Wt(t,e=null){if(e){let n=JSON.stringify({_envelope:e,error:t.message});process.stdout.write(`${n}
308
- `)}process.stderr.write(`Error: ${t.message}
309
- `),process.exit(1)}import{spawn as rn,execFileSync as Dt,execSync as un}from"node:child_process";import{existsSync as G,readFileSync as L,renameSync as on,unlinkSync as x,writeFileSync as P}from"node:fs";import lt from"node:http";import{platform as Pt,tmpdir as ln}from"node:os";import{basename as ye}from"node:path";function kt(t=process.env,e=process.execPath){let n=t.GREEDY_SEARCH_NODE||t.NODE_BINARY||t.NODE;if(n?.trim())return n.trim();let r=ye(e||"").toLowerCase();if(r==="node"||r==="node.exe")return e;return"node"}import{existsSync as Xt}from"node:fs";import{platform as we}from"node:os";import{join as J}from"node:path";function v(t){let e=we()==="win32",n=process.env.SystemRoot||"C:\\Windows",r={win32:{powershell:J(n,"System32","WindowsPowerShell","v1.0","powershell.exe"),powershell_ise:J(n,"System32","WindowsPowerShell","v1.0","powershell_ise.exe"),netstat:J(n,"System32","netstat.exe"),taskkill:J(n,"System32","taskkill.exe"),tasklist:J(n,"System32","tasklist.exe"),cmd:J(n,"System32","cmd.exe")},unix:{ps:"/usr/bin/ps",lsof:"/usr/bin/lsof",ss:"/usr/sbin/ss",grep:"/usr/bin/grep",kill:"/usr/bin/kill"}},i=e?r.win32:r.unix,u=t.toLowerCase();if(i[u]&&Xt(i[u]))return i[u];if(e&&u==="netstat"){let o=J(n,"Sysnative","netstat.exe");if(Xt(o))return o}return t}import{existsSync as z,mkdirSync as ve,readFileSync as Nt,writeFileSync as me}from"node:fs";import{homedir as xe}from"node:os";import{join as Qt}from"node:path";import{tmpdir as S}from"node:os";function $e(t,e=9222){let n=Number.parseInt(String(t??""),10);return Number.isInteger(n)&&n>1024&&n<65535?n:e}var h=$e(process.env.GREEDY_SEARCH_PORT,9222),$=(process.env.GREEDY_SEARCH_PROFILE_DIR||process.env.CDP_PROFILE_DIR||`${S().replaceAll("\\","/")}/greedysearch-chrome-profile`).replaceAll("\\","/"),N=`${$}/DevToolsActivePort`,Je=`${S().replaceAll("\\","/")}/cdp-pages.json`,p=process.env.GREEDY_SEARCH_MODE_FILE||`${S().replaceAll("\\","/")}/greedysearch-chrome-mode`,Gn=`${S().replaceAll("\\","/")}/greedysearch-visible-recovery.jsonl`,E=Qt(xe(),".dm"),m=Qt(E,"greedyconfig"),tt=["perplexity","google","chatgpt"],et="gemini";function pe(){try{if(z(m)){let t=Nt(m,"utf8"),e=JSON.parse(t);if(Array.isArray(e.engines)&&e.engines.length>0&&e.engines.every((n)=>typeof n==="string")){let n=e.engines.filter((i)=>F[i]),r=e.engines.filter((i)=>!F[i]);if(r.length>0)process.stderr.write(`[greedysearch] Warning: ignoring unknown engine(s) in ${m}: ${r.join(", ")}
310
- [greedysearch] Available engines: ${Object.keys(F).join(", ")}
311
- `);if(n.length>0)return n;process.stderr.write(`[greedysearch] Warning: no valid engines in ${m}, falling back to defaults: ${tt.join(", ")}
312
- `)}}}catch{}return tt}function We(){try{if(!z(E))ve(E,{recursive:!0});if(!z(m))me(m,JSON.stringify({engines:tt,synthesizer:et},null,2)+`
313
- `,"utf8")}catch{}}We();var qt=["gemini","chatgpt"];function ke(){try{if(z(m)){let t=Nt(m,"utf8"),e=JSON.parse(t);if(typeof e.synthesizer==="string"){let n=e.synthesizer.toLowerCase();if(qt.includes(n))return n;process.stderr.write(`[greedysearch] Warning: unknown synthesizer "${e.synthesizer}" in ${m}
314
- [greedysearch] Available synthesizers: ${qt.join(", ")}
315
- [greedysearch] Falling back to default: ${et}
316
- `)}}}catch{}return et}var F={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"},Ln=pe();var In=ke(),dn=Math.max(1,Number.parseInt(process.env.GREEDY_FETCH_CONCURRENCY||"5",10)||5);process.env.CDP_PROFILE_DIR=$;import{existsSync as tr,mkdirSync as Xe,readFileSync as Bt,renameSync as qe,unlinkSync as Ne,writeFileSync as Zt}from"node:fs";import Qe from"node:http";import{platform as Vt}from"node:os";import{dirname as He}from"node:path";var jt=[9222,9223],Be=/^(0|false|no|off)$/i;function Ze(t){return[...new Set(t.filter(Boolean))]}function Ht(t,e="explicit"){let n=new URL(t),r=n.protocol==="wss:"?"wss:":"ws:",i=n.port?Number.parseInt(n.port,10):r==="wss:"?443:80;return{source:e,wsUrl:`${r}//${n.host}${n.pathname}${n.search}`,host:n.hostname,port:i,path:`${n.pathname}${n.search}`,httpUrl:`http://${n.hostname}:${i}`}}function Ot(t=process.env){return![t.GREEDY_SEARCH_REUSE_EXISTING_BROWSER,t.DM_CUA_REUSE_EXISTING_BROWSER].some((e)=>e!==void 0&&Be.test(String(e)))}function nt(t){let e=Number.parseInt(String(t??""),10);return Number.isInteger(e)&&e>0&&e<65536?e:null}function Ve(t){if(!t)return null;let e=String(t).trim();if(!e)return null;let n=new URL(e.includes("://")?e:`http://${e}`),r=nt(n.port)||(n.protocol==="https:"?443:80);return{host:n.hostname,port:r,source:`env:${e}`}}function je(t){if(!t)return[];return String(t).split(/[,\s]+/).map(nt).filter(Boolean)}function Oe({env:t=process.env,platformName:e=Vt(),procVersionText:n=null}={}){if(e!=="linux")return!1;if(t.WSL_DISTRO_NAME||t.WSL_INTEROP)return!0;let r=n??(()=>{try{return Bt("/proc/version","utf8")}catch{return""}})();return/microsoft|wsl/i.test(r)}function _e({env:t=process.env,platformName:e=Vt(),procVersionText:n=null,resolvConfText:r=null}={}){let i=["localhost","127.0.0.1"];if(Oe({env:t,platformName:e,procVersionText:n})){let o=(r??(()=>{try{return Bt("/etc/resolv.conf","utf8")}catch{return""}})()).match(/^\s*nameserver\s+([^\s#]+)/m);if(o)i.push(o[1]);i.push("host.docker.internal")}return Ze(i)}function Ae({env:t=process.env,hosts:e=_e({env:t}),autoPorts:n=jt,excludePorts:r=[]}={}){let i=[];for(let l of["GREEDY_SEARCH_CDP_WS_URL","DM_CUA_CDP_WS_URL","CDP_WS_URL"])if(t[l])i.push({wsUrl:t[l],source:`env:${l}`});for(let l of["GREEDY_SEARCH_CDP_URL","DM_CUA_CDP_URL","CDP_URL"])try{let a=Ve(t[l]);if(a)i.push(a)}catch{}for(let l of["GREEDY_SEARCH_EXISTING_CDP_PORT","DM_CUA_EXISTING_CDP_PORT","GREEDY_SEARCH_CDP_PORT","DM_CUA_CDP_PORT"]){let a=nt(t[l]);if(!a)continue;for(let c of e)i.push({host:c,port:a,source:`env:${l}`})}let u=je(t.GREEDY_SEARCH_EXISTING_CDP_PORTS);for(let l of u)for(let a of e)i.push({host:a,port:l,source:"env:GREEDY_SEARCH_EXISTING_CDP_PORTS"});let o=new Set(r.filter(Boolean));if(Ot(t))for(let l of n){if(o.has(l))continue;for(let a of e)i.push({host:a,port:l,source:"auto"})}let f=new Set;return i.filter((l)=>{let a=l.wsUrl||`${l.host}:${l.port}`;if(f.has(a))return!1;return f.add(a),!0})}async function Te(t,{timeoutMs:e=700}={}){if(t.wsUrl)return Ht(t.wsUrl,t.source);let n=t.host||"localhost",r=t.port;if(!r)return null;let i=await new Promise((u)=>{let o=Qe.get({host:n,port:r,path:"/json/version",timeout:e},(f)=>{let l="";f.setEncoding("utf8"),f.on("data",(a)=>l+=a),f.on("end",()=>u(f.statusCode===200?l:null))});o.on("error",()=>u(null)),o.setTimeout(e,()=>{o.destroy(),u(null)})});if(!i)return null;try{let u=JSON.parse(i);if(!u.webSocketDebuggerUrl)return null;let o=Ht(u.webSocketDebuggerUrl,t.source),f=o.path||new URL(u.webSocketDebuggerUrl).pathname;return{...o,host:n,port:r,httpUrl:`http://${n}:${r}`,wsUrl:`ws://${n}:${r}${f}`,path:f}}catch{return null}}async function Ke(t={}){for(let e of Ae(t)){let n=await Te(e,t);if(n)return n}return null}function Ue(t){if(!t)throw Error("missing CDP endpoint");let e=new URL(t.wsUrl);return`${e.host}
317
- ${e.pathname}${e.search}
318
- `}function Me(t,e){Xe(He(t),{recursive:!0});let n=`${t}.tmp-${process.pid}`;Zt(n,Ue(e),"utf8");try{Ne(t)}catch{}qe(n,t)}async function _t({activePortFile:t,modeFile:e,env:n=process.env,excludePorts:r=[],autoPorts:i=jt}={}){if(!Ot(n))return null;let u=await Ke({env:n,excludePorts:r,autoPorts:i});if(!u)return null;if(Me(t,u),e)Zt(e,"existing","utf8");return u}import{existsSync as Ce}from"node:fs";import{dirname as ze,join as Q}from"node:path";function Se(t){let e=new Set;return t.filter((n)=>{if(!n||e.has(n))return!1;return e.add(n),!0})}function Ye({moduleDir:t,entrypoint:e=process.argv[1],env:n=process.env}={}){let r=e?ze(e):null,i=n.GREEDY_SEARCH_EXTENSION_DIR?.trim()||null;return Se([i?Q(i,"bin","launch.mjs"):null,t?Q(t,"launch.mjs"):null,t?Q(t,"..","bin","launch.mjs"):null,t?Q(t,"..","..","bin","launch.mjs"):null,r?Q(r,"launch.mjs"):null,r?Q(r,"..","bin","launch.mjs"):null])}function At({moduleDir:t,entrypoint:e=process.argv[1],env:n=process.env,exists:r=Ce}={}){let i=Ye({moduleDir:t,entrypoint:e,env:n}),u=i.find((o)=>r(o));if(u)return u;throw Error(`GreedySearch launcher not found. Checked candidates:
319
- ${i.map((o)=>`- ${o}`).join(`
320
- `)}`)}import{execFileSync as De}from"node:child_process";import{platform as Re}from"node:os";function Pe(t,e){return De(v(t),e,{encoding:"utf8",stdio:["ignore","pipe","ignore"],timeout:5000})}function Ge(t){let e=String(t||"").match(/\b(\d+)\b/);return e?Number.parseInt(e[1],10):null}function Le(t){return Ge(t)}function Ie(t,e){for(let n of String(t||"").split(/\r?\n/)){if(!/\bLISTEN\b/i.test(n))continue;if(!n.trim().split(/\s+/).slice(0,6).some((u)=>u.endsWith(`:${e}`)))continue;let i=n.match(/\bpid=(\d+)\b/);if(i)return Number.parseInt(i[1],10)}return null}function de(t,e){for(let n of String(t||"").split(/\r?\n/)){let r=n.trim().split(/\s+/);if(r.length<5||r[0].toUpperCase()!=="TCP")continue;if(!r.at(-2)?.toUpperCase().startsWith("LISTEN"))continue;if(!r[1].endsWith(`:${e}`))continue;let u=Number.parseInt(r.at(-1),10);if(Number.isInteger(u)&&u>0)return u}return null}function rt(t,e,n){try{return t(e,n)}catch{return null}}function Y(t,{platformName:e=Re(),run:n=Pe}={}){if(e==="win32")return de(rt(n,"netstat",["-ano","-p","TCP"]),t);let r=rt(n,"lsof",["-nP",`-iTCP:${t}`,"-sTCP:LISTEN","-t"]),i=Le(r);if(i)return i;if(e!=="linux")return null;return Ie(rt(n,"ss",["-ltnp"]),t)}import{execFileSync as Tt,execSync as br}from"node:child_process";import{existsSync as W,mkdirSync as Fe,readFileSync as H,unlinkSync as X,writeFileSync as q}from"node:fs";import{platform as Ee,tmpdir as Ct}from"node:os";var T=Ct().replaceAll("\\","/"),D=`${T}/greedysearch-chrome-metadata.json`,k=`${T}/greedysearch-chrome-launch.lock`,tn=15000,O=`${T}/greedysearch-chrome.pid`,_=`${T}/greedysearch-chrome-mode`,B=`${T}/greedysearch-chrome-last-activity`;function A(t){if(!Number.isInteger(t)||t<=0)return!1;try{return process.kill(t,0),!0}catch{return!1}}function en(t){if(!A(t))return null;try{if(Ee()==="win32")return Tt(v("powershell"),["-NoProfile","-NonInteractive","-Command",`(Get-CimInstance Win32_Process -Filter "ProcessId = ${t}").CommandLine`],{encoding:"utf8",windowsHide:!0,timeout:5000}).trim()||null;return Tt(v("ps"),["-p",String(t),"-o","command="],{encoding:"utf8",timeout:5000}).trim()||null}catch{return null}}function it(t,e,n=h){if(!t)return!1;let r=(o)=>String(o||"").replaceAll("\\","/").toLowerCase(),i=r(t),u=r(e);return i.includes(u)&&i.includes(`--remote-debugging-port=${n}`)&&!i.includes("--type=")}function Kt(t,e,n=h){return it(en(t),e,n)}function nn(t=h){return Y(t)}function K(){try{if(W(D)){let t=H(D,"utf8"),e=JSON.parse(t);if(e&&typeof e.tempDir==="string"&&typeof e.debugPort==="number")return{browserPid:Number.isInteger(e.browserPid)?e.browserPid:void 0,debugPort:e.debugPort,tempDir:e.tempDir,clientPids:Array.isArray(e.clientPids)?e.clientPids.filter((n)=>Number.isInteger(n)&&n>0):[],sessionMode:e.sessionMode==="visible"?"visible":"headless",lastActivity:Number.isFinite(e.lastActivity)?e.lastActivity:0,launchedAt:Number.isFinite(e.launchedAt)?e.launchedAt:0}}}catch{}try{if(!(W(O)||W(_)||W(B)))return null;let e=W(O)?Number.parseInt(H(O,"utf8").trim(),10)||void 0:void 0,n=W(_)?H(_,"utf8").trim()==="visible"?"visible":"headless":"headless",r=W(B)?Number.parseInt(H(B,"utf8").trim(),10)||0:0;return{browserPid:e,debugPort:h,tempDir:$,clientPids:e?[e]:[],sessionMode:n,lastActivity:r,launchedAt:0}}catch{return null}}function R(t){try{q(D,JSON.stringify({browserPid:t.browserPid,debugPort:t.debugPort,tempDir:t.tempDir,clientPids:[...new Set(t.clientPids.filter((e)=>e>0))],sessionMode:t.sessionMode,lastActivity:t.lastActivity,launchedAt:t.launchedAt},null,2),"utf8")}catch{}try{if(t.browserPid)q(O,String(t.browserPid),"utf8")}catch{}try{q(_,t.sessionMode,"utf8")}catch{}try{q(B,String(t.lastActivity),"utf8")}catch{}}function Ut(){try{X(D)}catch{}try{X(O)}catch{}try{X(_)}catch{}try{X(B)}catch{}}function zt(t){if(!t)return t;let e={...t,clientPids:[...new Set([...t.clientPids,process.pid].filter((n)=>A(n)||n===process.pid))]};return R(e),e}function ut(t){let e=Date.now();try{if(t)R({...t,lastActivity:e});else q(B,String(e),"utf8")}catch{}}var xr=Number.parseInt(process.env.GREEDY_SEARCH_IDLE_TIMEOUT_MINUTES||"5",10)||5;var Mt=!1;function St(){if(Mt)return;Mt=!0;let t=K();if(!t)return;if(t.browserPid){if(!A(t.browserPid)){Ut();return}if(!Kt(t.browserPid,t.tempDir,t.debugPort))Ut();else R({...t,clientPids:t.clientPids.filter((i)=>A(i))})}let e=nn();if(e&&e!==t.browserPid)if(Kt(e,$,h))R({browserPid:e,debugPort:h,tempDir:$,clientPids:[e],sessionMode:t.sessionMode,lastActivity:Date.now(),launchedAt:Date.now()});else return}function Yt(){Fe(Ct(),{recursive:!0});try{let t=JSON.stringify({pid:process.pid,ts:Date.now()});return q(k,t,{encoding:"utf8",flag:"wx"}),{acquired:!0,release:()=>{try{let e=H(k,"utf8");if(JSON.parse(e).pid===process.pid)X(k)}catch{}}}}catch(t){if(t?.code!=="EEXIST")return{acquired:!1,release:()=>{}}}try{let t=H(k,"utf8"),e=JSON.parse(t),n=Date.now()-(e.ts||0);if(!A(e.pid)||n>tn){try{X(k)}catch{}try{let i=JSON.stringify({pid:process.pid,ts:Date.now()});return q(k,i,{encoding:"utf8",flag:"wx"}),{acquired:!0,release:()=>{try{X(k)}catch{}}}}catch{return{acquired:!1,release:()=>{}}}}}catch{}return{acquired:!1,release:()=>{}}}var fn=import.meta.dirname||new URL(".",import.meta.url).pathname.replace(/^\/([A-Z]:)/,"$1"),Gt=ln().replaceAll("\\","/"),U=`${Gt}/greedysearch-chrome.pid`,M=`${Gt}/greedysearch-chrome-last-activity`,an=Number.parseInt(process.env.GREEDY_SEARCH_IDLE_TIMEOUT_MINUTES||"5",10)||5,cn=Number.parseInt(process.env.GREEDY_SEARCH_VISIBLE_IDLE_TIMEOUT_MINUTES||"60",10)||60;function gn(t,e=h){let n=String(t||"").toLowerCase();if(!n.includes(`--remote-debugging-port=${e}`)||n.includes("--type="))return null;return n.includes("--headless")}function Lt(){try{let t=ft(),e=t?It(t):null,n=gn(e);if(n!==null){try{P(p,n?"headless":"visible","utf8")}catch{}return n}}catch{}try{if(!G(p))return!0;return L(p,"utf8").trim()==="headless"}catch{return!0}}function sn(){try{P(M,String(Date.now()),"utf8")}catch{}try{let t=K();if(t)ut(t)}catch{}}function It(t){try{if(Pt()==="win32")return Dt(v("powershell"),["-NoProfile","-NonInteractive","-Command",`(Get-CimInstance Win32_Process -Filter "ProcessId = ${t}").CommandLine`],{encoding:"utf8",windowsHide:!0,timeout:5000}).trim()||null;return Dt(v("ps"),["-p",String(t),"-o","command="],{encoding:"utf8",timeout:5000}).trim()||null}catch{return null}}function ft(){return Y(h)}function dt(){let t=[ft()];if(G(U))t.push(Number.parseInt(L(U,"utf8").trim(),10)||null);for(let e of t){if(!e)continue;if(it(It(e),$,h))return e}return null}async function bn(t=1500){let e=dt();if(!e)return!1;try{let r=await new Promise((u,o)=>{let f=lt.get(`http://localhost:${h}/json/version`,(l)=>{let a="";l.on("data",(c)=>a+=c),l.on("end",()=>{try{u(JSON.parse(a))}catch{o(Error("bad JSON"))}})});f.on("error",o),f.setTimeout(1000,()=>{f.destroy(),o(Error("timeout"))})}),i=new globalThis.WebSocket(r.webSocketDebuggerUrl);await new Promise((u)=>{i.onopen=()=>{i.send(JSON.stringify({id:1,method:"Browser.close"})),setTimeout(()=>{i.close(),u()},200)},i.onerror=()=>u(),setTimeout(u,1000)})}catch{}let n=Date.now()+t;while(Date.now()<n){let r=ft();if(!r)return!0;if(r!==e)return!0;await new Promise((i)=>setTimeout(i,150))}return hn()}function hn(){try{let t=dt();if(!t)return!1;if(Pt()==="win32")un(`${v("taskkill")} /F /PID ${t}`,{stdio:"ignore"});else process.kill(t,"SIGKILL");return!0}catch{return!1}}async function Ft(){if(!await Z(500)){try{x(U)}catch{}try{x(M)}catch{}try{x(p)}catch{}return!1}let e=await bn(1500);try{x(U)}catch{}try{x(M)}catch{}try{x(p)}catch{}if(e)process.stderr.write(`[greedysearch] Killed Chrome on port ${h}.
321
- `);return e}var Rt=Ft;async function yn(){let e=Lt()?an:cn;if(e<=0)return!1;if(!G(M))return sn(),!1;try{let n=Number.parseInt(L(M,"utf8").trim(),10);if(!n)return!1;if((Date.now()-n)/60000>=e)return Ft()}catch{}return!1}function Z(t=3000){return new Promise((e)=>{let n=lt.get(`http://localhost:${h}/json/version`,(r)=>{r.resume(),e(r.statusCode===200)});n.on("error",()=>e(!1)),n.setTimeout(t,()=>{n.destroy(),e(!1)})})}async function ot(){let t=`${N}.lock`,e=`${N}.tmp`,n=5000,r=1000,i=await new Promise((u)=>{let o=Date.now(),f=()=>{try{let l=JSON.stringify({pid:process.pid,ts:Date.now()});P(t,l,{encoding:"utf8",flag:"wx"}),u(!0)}catch(l){if(l?.code!=="EEXIST"){if(Date.now()-o<1000)setTimeout(f,50);else u(!1);return}try{let a=L(t,"utf8").trim(),c=a.startsWith("{")?JSON.parse(a):{ts:Number(a)},b=Number(c?.ts)||0;if(b>0&&Date.now()-b>5000)try{x(t)}catch{}if(Date.now()-o<1000)setTimeout(f,50);else u(!1)}catch{if(Date.now()-o<1000)setTimeout(f,50);else u(!1)}}};f()});try{let u=await new Promise((a,c)=>{let b=lt.get(`http://localhost:${h}/json/version`,(s)=>{let w="";s.on("data",(I)=>w+=I),s.on("end",()=>a(w))});b.on("error",c),b.setTimeout(3000,()=>{b.destroy(),c(Error("timeout"))})}),{webSocketDebuggerUrl:o}=JSON.parse(u),f=new URL(o),l=`${f.pathname}${f.search}`;if(i){P(e,`localhost:${h}
322
- ${l}`,"utf8");try{x(N)}catch{}on(e,N)}}catch{}finally{if(i)try{x(t)}catch{}}}async function Et(){let t=G(U)||!!K(),e=await _t({activePortFile:N,modeFile:p,excludePorts:t?[h]:[]});if(e){process.stderr.write(`[greedysearch] Reusing existing browser CDP endpoint ${e.httpUrl} (${e.source}).
323
- `);return}St();let n=await yn(),r=n?!1:await Z();if(!r&&!n)await new Promise((f)=>setTimeout(f,500)),r=await Z();let i=!1;if(r){let f=Lt(),l=process.env.GREEDY_SEARCH_VISIBLE==="1";if(!l&&!f)process.stderr.write(`[greedysearch] Visible Chrome detected — switching to headless mode...
324
- `),await Rt(),await new Promise((a)=>setTimeout(a,1000)),i=!0;else if(l&&f)process.stderr.write(`[greedysearch] Headless Chrome detected switching to visible mode...
325
- `),await Rt(),await new Promise((a)=>setTimeout(a,1000)),i=!0}if(i?!1:await Z()){await ot();try{let f=K();if(f)ut(f),zt(f)}catch{}return}let o=Yt();if(!o.acquired){let f=Date.now()+15000;while(Date.now()<f)if(await new Promise((l)=>setTimeout(l,250)),await Z(1000)){await ot();return}throw Error(`Timed out waiting for another GreedySearch launcher on port ${h}`)}try{if(await Z(1000)){await ot();return}process.stderr.write(`GreedySearch Chrome not running on port ${h} — auto-launching...
326
- `);let l=[At({moduleDir:fn,entrypoint:process.argv[1]})];if(process.env.GREEDY_SEARCH_VISIBLE!=="1")l.push("--headless");await new Promise((a,c)=>{rn(kt(),l,{stdio:["ignore",process.stderr,process.stderr]}).on("close",(s)=>s===0?a():c(Error("launch.mjs failed")))})}finally{o.release()}}import{randomInt as wn}from"node:crypto";import{existsSync as vn,readFileSync as mn}from"node:fs";import xn from"node:http";var $n=`
406
+ `;return await h(["eval",e,r],n+5000)==="true"}async function $e(e){let t=e.indexOf("--stdin");if(t===-1)return e;let n=await new Promise((r)=>{let o="";process.stdin.setEncoding("utf8"),process.stdin.on("data",(a)=>o+=a),process.stdin.on("end",()=>r(o.trim()))}),i=[...e];return i[t]=n,i}function ke(e){let t=e.includes("--short"),n=e.filter((l)=>l!=="--short"),i=n.indexOf("--tab"),r=i===-1?null:n[i+1];if(i!==-1)n=n.filter((l,u)=>u!==i&&u!==i+1);let o=n.indexOf("--locale"),a=o===-1?null:n[o+1];if(o!==-1)n=n.filter((l,u)=>u!==o&&u!==o+1);return{query:n.join(" "),tabPrefix:r,short:t,locale:a}}function _e(e,t){if(!e.length||e[0]==="--help")process.stderr.write(t),process.exit(1)}function Je(e,t,n=300){if(!t||e.length<=n)return e;let i=e.slice(0,n),r=i.lastIndexOf(" ");return r>0?`${i.slice(0,r)}…`:`${i}…`}function Ne(e){process.stdout.write(`${JSON.stringify(e,null,2)}
407
+ `)}function We(e,t=null){if(t){let n=JSON.stringify({_envelope:t,error:e.message});process.stdout.write(`${n}
408
+ `)}process.stderr.write(`Error: ${e.message}
409
+ `),process.exit(1)}import{spawn as Ut,execFileSync as ue,execSync as Ln}from"node:child_process";import{basename as dt}from"node:path";function Te(e=process.env,t=process.execPath){let n=e.GREEDY_SEARCH_NODE||e.NODE_BINARY||e.NODE;if(n?.trim())return n.trim();let i=dt(t||"").toLowerCase();if(i==="node"||i==="node.exe")return t;return"node"}import{existsSync as Ye,readFileSync as se,renameSync as Pt,unlinkSync as w,writeFileSync as F}from"node:fs";import ce from"node:http";import{platform as Re}from"node:os";import{join as zt}from"node:path";import{existsSync as je}from"node:fs";import{platform as bt}from"node:os";import{join as k}from"node:path";function b(e){let t=bt()==="win32",n=process.env.SystemRoot||"C:\\Windows",i={win32:{powershell:k(n,"System32","WindowsPowerShell","v1.0","powershell.exe"),powershell_ise:k(n,"System32","WindowsPowerShell","v1.0","powershell_ise.exe"),netstat:k(n,"System32","netstat.exe"),taskkill:k(n,"System32","taskkill.exe"),tasklist:k(n,"System32","tasklist.exe"),cmd:k(n,"System32","cmd.exe")},unix:{ps:"/usr/bin/ps",lsof:"/usr/bin/lsof",ss:"/usr/sbin/ss",grep:"/usr/bin/grep",kill:"/usr/bin/kill"}},r=t?i.win32:i.unix,o=e.toLowerCase();if(r[o]&&je(r[o]))return r[o];if(t&&o==="netstat"){let a=k(n,"Sysnative","netstat.exe");if(je(a))return a}return e}import{execFileSync as vt}from"node:child_process";import{platform as wt}from"node:os";function xt(e,t){return vt(b(e),t,{encoding:"utf8",stdio:["ignore","pipe","ignore"],timeout:5000})}function $t(e){let t=String(e||"").match(/\b(\d+)\b/);return t?Number.parseInt(t[1],10):null}function kt(e){return $t(e)}function _t(e,t){for(let n of String(e||"").split(/\r?\n/)){if(!/\bLISTEN\b/i.test(n))continue;if(!n.trim().split(/\s+/).slice(0,6).some((o)=>o.endsWith(`:${t}`)))continue;let r=n.match(/\bpid=(\d+)\b/);if(r)return Number.parseInt(r[1],10)}return null}function Jt(e,t){for(let n of String(e||"").split(/\r?\n/)){let i=n.trim().split(/\s+/);if(i.length<5||i[0].toUpperCase()!=="TCP")continue;if(!i.at(-2)?.toUpperCase().startsWith("LISTEN"))continue;if(!i[1].endsWith(`:${t}`))continue;let r=Number.parseInt(i.at(-1),10);if(Number.isInteger(r)&&r>0)return r}return null}function ne(e,t,n){try{return e(t,n)}catch{return null}}function qe(e,{platformName:t=wt(),run:n=xt}={}){if(t==="win32")return Jt(ne(n,"netstat",["-ano","-p","TCP"]),e);let i=ne(n,"lsof",["-nP",`-iTCP:${e}`,"-sTCP:LISTEN","-t"]),r=kt(i);if(r)return r;if(t!=="linux")return null;return _t(ne(n,"ss",["-ltnp"]),e)}import{existsSync as C,mkdirSync as Nt,readFileSync as Be,writeFileSync as Wt}from"node:fs";import{homedir as Tt}from"node:os";import{join as He}from"node:path";import{tmpdir as jt}from"node:os";function qt(e,t=9222){let n=Number.parseInt(String(e??""),10);return Number.isInteger(n)&&n>1024&&n<65535?n:t}var Ot=jt().replaceAll("\\","/"),m=qt(process.env.GREEDY_SEARCH_PORT),y=(process.env.GREEDY_SEARCH_PROFILE_DIR||process.env.CDP_PROFILE_DIR||`${Ot}/greedysearch-chrome-profile`).replaceAll("\\","/"),H=`${y}/DevToolsActivePort`,U=process.env.GREEDY_SEARCH_PID_FILE||`${y}/browser.pid`,Bt=process.env.CDP_PAGES_CACHE||`${y}/cdp-pages.json`,$=process.env.GREEDY_SEARCH_MODE_FILE||`${y}/browser-mode`,Ve=process.env.GREEDY_SEARCH_METADATA_FILE||`${y}/browser-metadata.json`,Me=process.env.GREEDY_SEARCH_LAUNCH_LOCK_FILE||`${y}/browser-launch.lock`,P=process.env.GREEDY_SEARCH_ACTIVITY_FILE||`${y}/browser-last-activity`,Sn=(process.env.CDP_SOCKET_DIR||`${y}/cdp-sockets`).replaceAll("\\","/"),Zn=`${y}/visible-recovery.jsonl`,ie=He(Tt(),".dm"),v=He(ie,"greedyconfig"),oe=["perplexity","google","chatgpt","gemini"],ae="gemini";function Ht(){try{if(C(v)){let e=Be(v,"utf8"),t=JSON.parse(e);if(Array.isArray(t.engines)&&t.engines.length>0&&t.engines.every((n)=>typeof n==="string")){let n=t.engines.filter((r)=>re[r]),i=t.engines.filter((r)=>!re[r]);if(i.length>0)process.stderr.write(`[greedysearch] Warning: ignoring unknown engine(s) in ${v}: ${i.join(", ")}
410
+ [greedysearch] Available engines: ${Object.keys(re).join(", ")}
411
+ `);if(n.length>0)return n;process.stderr.write(`[greedysearch] Warning: no valid engines in ${v}, falling back to defaults: ${oe.join(", ")}
412
+ `)}}}catch{}return oe}function Vt(){try{if(!C(ie))Nt(ie,{recursive:!0});if(!C(v))Wt(v,JSON.stringify({engines:oe,synthesizer:ae},null,2)+`
413
+ `,"utf8")}catch{}}Vt();var Oe=["gemini","chatgpt"];function Mt(){try{if(C(v)){let e=Be(v,"utf8"),t=JSON.parse(e);if(typeof t.synthesizer==="string"){let n=t.synthesizer.toLowerCase();if(Oe.includes(n))return n;process.stderr.write(`[greedysearch] Warning: unknown synthesizer "${t.synthesizer}" in ${v}
414
+ [greedysearch] Available synthesizers: ${Oe.join(", ")}
415
+ [greedysearch] Falling back to default: ${ae}
416
+ `)}}}catch{}return ae}var re={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"},Qn=Ht();var Cn=Mt(),Un=Math.max(1,Number.parseInt(process.env.GREEDY_FETCH_CONCURRENCY||"5",10)||5);process.env.CDP_PROFILE_DIR=y;import{execFileSync as Xe,execSync as Se}from"node:child_process";import{existsSync as z,mkdirSync as Xt,readFileSync as j,unlinkSync as J,writeFileSync as N}from"node:fs";import{platform as Ue}from"node:os";var A=Ve,_=Me,St=15000,D=U,K=$,V=P;function M(e){if(!Number.isInteger(e)||e<=0)return!1;try{return process.kill(e,0),!0}catch{return!1}}function Zt(e){if(!M(e))return null;try{if(Ue()==="win32")return Xe(b("powershell"),["-NoProfile","-NonInteractive","-Command",`(Get-CimInstance Win32_Process -Filter "ProcessId = ${e}").CommandLine`],{encoding:"utf8",windowsHide:!0,timeout:5000}).trim()||null;return Xe(b("ps"),["-p",String(e),"-o","command="],{encoding:"utf8",timeout:5000}).trim()||null}catch{return null}}function Qt(e,t,n=m){if(!e)return!1;let i=(a)=>String(a||"").replaceAll("\\","/").toLowerCase(),r=i(e),o=i(t);return r.includes(o)&&r.includes(`--remote-debugging-port=${n}`)&&!r.includes("--type=")}function Ze(e,t,n=m){return Qt(Zt(e),t,n)}function Ct(e=m){try{if(Ue()==="win32"){let n=Se(`${b("netstat")} -ano -p TCP 2>nul`,{encoding:"utf8"}),i=new RegExp(String.raw`TCP\s+\S+:${e}\s+\S+:0\s+LISTENING\s+(\d+)`,"i"),r=n.match(i);return r?Number.parseInt(r[1],10):null}let t=Se(`${b("lsof")} -i :${e} -t 2>/dev/null || ${b("ss")} -tlnp 2>/dev/null | ${b("grep")} :${e} | ${b("grep")} -oP 'pid=\\K\\d+'`,{encoding:"utf8"}).trim();return t?Number.parseInt(t.split(`
417
+ `)[0],10):null}catch{return null}}function X(){try{if(z(A)){let e=j(A,"utf8"),t=JSON.parse(e);if(t&&typeof t.tempDir==="string"&&typeof t.debugPort==="number")return{browserPid:Number.isInteger(t.browserPid)?t.browserPid:void 0,debugPort:t.debugPort,tempDir:t.tempDir,clientPids:Array.isArray(t.clientPids)?t.clientPids.filter((n)=>Number.isInteger(n)&&n>0):[],sessionMode:t.sessionMode==="visible"?"visible":"headless",lastActivity:Number.isFinite(t.lastActivity)?t.lastActivity:0,launchedAt:Number.isFinite(t.launchedAt)?t.launchedAt:0}}}catch{}try{let e=z(D)?Number.parseInt(j(D,"utf8").trim(),10)||void 0:void 0,t=z(K)?j(K,"utf8").trim()==="visible"?"visible":"headless":"headless",n=z(V)?Number.parseInt(j(V,"utf8").trim(),10)||0:0;return{browserPid:e,debugPort:m,tempDir:y,clientPids:e?[e]:[],sessionMode:t,lastActivity:n,launchedAt:0}}catch{return null}}function Y(e){try{N(A,JSON.stringify({browserPid:e.browserPid,debugPort:e.debugPort,tempDir:e.tempDir,clientPids:[...new Set(e.clientPids.filter((t)=>t>0))],sessionMode:e.sessionMode,lastActivity:e.lastActivity,launchedAt:e.launchedAt},null,2),"utf8")}catch{}try{if(e.browserPid)N(D,String(e.browserPid),"utf8")}catch{}try{N(K,e.sessionMode,"utf8")}catch{}try{N(V,String(e.lastActivity),"utf8")}catch{}}function Qe(){try{J(A)}catch{}try{J(D)}catch{}try{J(K)}catch{}try{J(V)}catch{}}function le(e){if(!e)return e;let t={...e,clientPids:[...new Set([...e.clientPids,process.pid].filter((n)=>M(n)||n===process.pid))]};return Y(t),t}function R(e){let t=Date.now();try{if(e)Y({...e,lastActivity:t});else N(V,String(t),"utf8")}catch{}}var Rn=Number.parseInt(process.env.GREEDY_SEARCH_IDLE_TIMEOUT_MINUTES||"5",10)||5;var Ce=!1;function Pe(){if(process.env.GREEDY_SEARCH_RESEARCH_CHILD)return;if(Ce)return;Ce=!0;let e=X();if(!e)return;if(e.browserPid){if(!M(e.browserPid)){Qe();return}if(!Ze(e.browserPid,e.tempDir,e.debugPort))Qe();else Y({...e,clientPids:e.clientPids.filter((r)=>M(r))})}let t=Ct();if(t&&t!==e.browserPid)if(Ze(t,y,m))Y({browserPid:t,debugPort:m,tempDir:y,clientPids:[t],sessionMode:e.sessionMode,lastActivity:Date.now(),launchedAt:Date.now()});else process.stderr.write(`[greedysearch] Refusing to kill unverified listener ${t} on port ${m}.
418
+ `)}function ze(){Xt(y,{recursive:!0});try{let e=JSON.stringify({pid:process.pid,ts:Date.now()});return N(_,e,{encoding:"utf8",flag:"wx"}),{acquired:!0,release:()=>{try{let t=j(_,"utf8");if(JSON.parse(t).pid===process.pid)J(_)}catch{}}}}catch(e){if(e?.code!=="EEXIST")return{acquired:!1,release:()=>{}}}try{let e=j(_,"utf8"),t=JSON.parse(e),n=Date.now()-(t.ts||0);if(!M(t.pid)||n>St){try{J(_)}catch{}try{let r=JSON.stringify({pid:process.pid,ts:Date.now()});return N(_,r,{encoding:"utf8",flag:"wx"}),{acquired:!0,release:()=>{try{J(_)}catch{}}}}catch{return{acquired:!1,release:()=>{}}}}}catch{}return{acquired:!1,release:()=>{}}}var At=import.meta.dirname||new URL(".",import.meta.url).pathname.replace(/^\/([A-Z]:)/,"$1"),Ae=U,S=P,Dt=Number.parseInt(process.env.GREEDY_SEARCH_IDLE_TIMEOUT_MINUTES||"5",10)||5,Kt=Number.parseInt(process.env.GREEDY_SEARCH_VISIBLE_IDLE_TIMEOUT_MINUTES||"60",10)||60;function Yt(e,t=m){let n=String(e||"").toLowerCase();if(!n.includes(`--remote-debugging-port=${t}`)||n.includes("--type="))return null;return n.includes("--headless")}function Ge(){try{let e=I(),t=e?Fe(e):null,n=Yt(t);if(n!==null){try{F($,n?"headless":"visible","utf8")}catch{}return n}}catch{}try{if(!Ye($))return!0;return se($,"utf8").trim()==="headless"}catch{return!0}}function Rt(){try{F(S,String(Date.now()),"utf8")}catch{}try{let e=X();if(e)R(e)}catch{}}function Fe(e){try{if(Re()==="win32")return ue(b("powershell"),["-NoProfile","-NonInteractive","-Command",`(Get-CimInstance Win32_Process -Filter "ProcessId = ${e}").CommandLine`],{encoding:"utf8",windowsHide:!0,timeout:5000}).trim()||null;return ue(b("ps"),["-p",String(e),"-o","command="],{encoding:"utf8",timeout:5000}).trim()||null}catch{return null}}function Gt(e){let t=String(e||"").replaceAll("\\","/"),n=y.replaceAll("\\","/");return t.includes(`--remote-debugging-port=${m}`)&&t.includes(`--user-data-dir=${n}`)&&!t.includes("--type=")}function I(){return qe(m)}function L(){let e=I();return e&&Gt(Fe(e))?e:null}async function Ft(e=1500){let t=L();if(!t)return process.stderr.write(`[greedysearch] Refusing to close an unverified listener.
419
+ `),!1;try{let i=await new Promise((o,a)=>{let l=ce.get(`http://localhost:${m}/json/version`,(u)=>{let f="";u.on("data",(s)=>f+=s),u.on("end",()=>{try{o(JSON.parse(f))}catch{a(Error("bad JSON"))}})});l.on("error",a),l.setTimeout(1000,()=>{l.destroy(),a(Error("timeout"))})}),r=new globalThis.WebSocket(i.webSocketDebuggerUrl);await new Promise((o)=>{r.onopen=()=>{if(L()!==t){r.close(),o();return}r.send(JSON.stringify({id:1,method:"Browser.close"})),setTimeout(()=>{r.close(),o()},200)},r.onerror=()=>o(),setTimeout(o,1000)})}catch{}let n=Date.now()+e;while(Date.now()<n){let i=I();if(!i)return!0;if(i!==t)return!1;await new Promise((r)=>setTimeout(r,150))}return Lt(t)}function Lt(e=null){try{let t=L();if(!t||e&&t!==e)return!1;if(Re()==="win32")ue(b("taskkill"),["/F","/PID",String(t)],{stdio:"ignore",windowsHide:!0});else process.kill(t,"SIGKILL");return!0}catch{return!1}}async function Le(){if(!L()){if(I())process.stderr.write(`[greedysearch] Refusing to kill an unverified listener.
420
+ `);return!1}if(!await x(500)){try{w(Ae)}catch{}try{w(S)}catch{}try{w($)}catch{}return!1}let t=await Ft(1500);try{w(Ae)}catch{}try{w(S)}catch{}try{w($)}catch{}if(t)process.stderr.write(`[greedysearch] Killed Chrome on port ${m}.
421
+ `);return t}var De=Le;async function It(){let t=Ge()?Dt:Kt;if(t<=0)return!1;if(!Ye(S))return Rt(),!1;try{let n=Number.parseInt(se(S,"utf8").trim(),10);if(!n)return!1;if((Date.now()-n)/60000>=t)return Le()}catch{}return!1}function x(e=3000){return new Promise((t)=>{let n=ce.get(`http://localhost:${m}/json/version`,(i)=>{i.resume(),t(i.statusCode===200)});n.on("error",()=>t(!1)),n.setTimeout(e,()=>{n.destroy(),t(!1)})})}async function Ke(e=3000,t=200){let n=Date.now()+e;while(Date.now()<n){if(!await x(300))return!0;await new Promise((i)=>setTimeout(i,t))}return!await x(300)}async function G(){let e=`${H}.lock`,t=`${H}.tmp`,n=5000,i=1000,r=await new Promise((o)=>{let a=Date.now(),l=()=>{try{let u=JSON.stringify({pid:process.pid,ts:Date.now()});F(e,u,{encoding:"utf8",flag:"wx"}),o(!0)}catch(u){if(u?.code!=="EEXIST"){if(Date.now()-a<1000)setTimeout(l,50);else o(!1);return}try{let f=se(e,"utf8").trim(),s=f.startsWith("{")?JSON.parse(f):{ts:Number(f)},g=Number(s?.ts)||0;if(g>0&&Date.now()-g>5000)try{w(e)}catch{}if(Date.now()-a<1000)setTimeout(l,50);else o(!1)}catch{if(Date.now()-a<1000)setTimeout(l,50);else o(!1)}}};l()});try{let o=await new Promise((u,f)=>{let s=ce.get(`http://localhost:${m}/json/version`,(g)=>{let p="";g.on("data",(c)=>p+=c),g.on("end",()=>u(p))});s.on("error",f),s.setTimeout(3000,()=>{s.destroy(),f(Error("timeout"))})}),{webSocketDebuggerUrl:a}=JSON.parse(o),l=new URL(a).pathname;if(r){F(t,`${m}
422
+ ${l}`,"utf8");try{w(H)}catch{}Pt(t,H)}}catch{}finally{if(r)try{w(e)}catch{}}}async function Ie(){if(process.env.GREEDY_SEARCH_RESEARCH_CHILD&&await x()){await G();try{let o=X();if(o)R(o),le(o)}catch{}return}Pe();let e=await It(),t=e?!1:await x();if(!t&&!e)await new Promise((o)=>setTimeout(o,500)),t=await x();let n=!1;if(t){let o=Ge(),a=process.env.GREEDY_SEARCH_VISIBLE==="1";if(!a&&!o)process.stderr.write(`[greedysearch] Visible Chrome detected switching to headless mode...
423
+ `),await De(),await Ke(),n=!0;else if(a&&o)process.stderr.write(`[greedysearch] Headless Chrome detected — switching to visible mode...
424
+ `),await De(),await Ke(),n=!0}if(n?!1:await x()){await G();try{let o=X();if(o)R(o),le(o)}catch{}return}let r=ze();if(!r.acquired){let o=Date.now()+12000,a=!1;while(Date.now()<o){if(a=await x(500),a)break;await new Promise((l)=>setTimeout(l,250))}if(a){await G();return}}try{if(await x(1000)){await G();return}process.stderr.write(`GreedySearch Chrome not running on port ${m} — auto-launching...
425
+ `);let a=[zt(At,"..","..","bin","launch.mjs")];if(process.env.GREEDY_SEARCH_VISIBLE!=="1")a.push("--headless");await new Promise((l,u)=>{Ut(Te(),a,{stdio:["ignore",process.stderr,process.stderr]}).on("close",(s)=>s===0?l():u(Error("launch.mjs failed")))})}finally{r.release()}}import{randomInt as Et}from"node:crypto";import{existsSync as en,readFileSync as tn}from"node:fs";import nn from"node:http";var rn=`
327
426
  (function() {
328
427
  // Google consent page (consent.google.com)
329
428
  var g = document.querySelector('#L2AGLb, button[jsname="b3VHJd"], .tHlp8d');
@@ -340,7 +439,7 @@ ${l}`,"utf8");try{x(N)}catch{}on(e,N)}}catch{}finally{if(i)try{x(t)}catch{}}}asy
340
439
 
341
440
  return null;
342
441
  })()
343
- `,Jn=`
442
+ `,on=`
344
443
  (function() {
345
444
  var url = document.location.href;
346
445
 
@@ -371,12 +470,24 @@ ${l}`,"utf8");try{x(N)}catch{}on(e,N)}}catch{}finally{if(i)try{x(t)}catch{}}}asy
371
470
 
372
471
  // --- Cloudflare Turnstile widget inside closed shadow DOM (Copilot, etc.) ---
373
472
  // The iframe is not queryable from main document, but the host container
374
- // (#cf-turnstile) and the hidden response input are.
375
- var cfTurnstileHost = document.querySelector('#cf-turnstile, [id^="cf-chl-widget-"]');
473
+ // (#cf-turnstile) and the hidden response input are. When only the
474
+ // hidden response input matches (no #cf-turnstile host and no visible
475
+ // iframe), the actual challenge widget is rendered inside a closed
476
+ // shadow DOM and cannot be auto-clicked. Return a sentinel so callers
477
+ // know to surface this as needs-human verification instead of wasting
478
+ // time on a doomed waitForSelector.
479
+ var cfTurnstileHost = document.querySelector('#cf-turnstile');
376
480
  if (cfTurnstileHost) {
377
481
  var r2 = cfTurnstileHost.getBoundingClientRect();
378
482
  return JSON.stringify({t:'xy',x:r2.left+r2.width/2,y:r2.top+r2.height/2});
379
483
  }
484
+ // Hidden cf-chl-widget-*_response input present but no visible host:
485
+ // the widget is in closed shadow DOM. Signal this so handleVerification
486
+ // can return 'needs-human' rather than 'clear'.
487
+ var cfResponseInput = document.querySelector('input[name="cf-turnstile-response"], [id^="cf-chl-widget-"][id$="_response"]');
488
+ if (cfResponseInput && cfResponseInput.value === '') {
489
+ return 'cf-closed-shadow-dom';
490
+ }
380
491
 
381
492
  // --- Cloudflare challenge page ---
382
493
  var cfCheckbox = document.querySelector('#cf-stage input[type="checkbox"], .ctp-checkbox-container input');
@@ -391,15 +502,28 @@ ${l}`,"utf8");try{x(N)}catch{}on(e,N)}}catch{}finally{if(i)try{x(t)}catch{}}}asy
391
502
  }
392
503
 
393
504
  // --- Generic verify/continue/proceed buttons (catch-all) ---
394
- // IMPORTANT: exclude sign-in / OAuth buttons (e.g. "Continue with Google")
505
+ // IMPORTANT: exclude sign-in / OAuth buttons (e.g. "Continue with Google",
506
+ // "Continue with email", "Login or sign up for free"). These appear on
507
+ // many sites (Perplexity, ChatGPT, etc.) when the user isn't logged in,
508
+ // and clicking them triggers a sign-in flow that takes us to a login
509
+ // wall — a much worse outcome than the original search failure we were
510
+ // trying to recover from. The exclusion list must cover both OAuth
511
+ // providers AND generic "sign in / log in / with email" patterns.
395
512
  var btns = Array.from(document.querySelectorAll('button, input[type=submit], a[role=button]'));
396
513
  var verify = btns.find(b => {
397
514
  var t = (b.innerText?.trim() || b.value || '').toLowerCase();
398
- var isVerifyLike = (t.includes('verify') || t.includes('human') || t.includes('robot') || t.includes('continue') || t.includes('proceed')) &&
515
+ var isVerifyLike = (t === 'continue' || t === 'proceed' || t === 'next' ||
516
+ t.startsWith('verify ') || t.startsWith('human ') || t === 'i am human' || t.includes('robot check')) &&
399
517
  !t.includes('verified') && !document.querySelector('iframe[src*="recaptcha"]');
400
518
  if (!isVerifyLike) return false;
401
519
  // Exclude OAuth / sign-in buttons to prevent accidental login flows
402
- var isSignIn = /sign.in|log.in|google|microsoft|apple|facebook|github|auth/i.test(t);
520
+ // covers "Continue with Google", "Continue with Apple", "Continue
521
+ // with email", "Login or sign up", "Log in", "Sign in", "Sign up",
522
+ // "Single sign-on", and the visible panel "Login or sign up for free"
523
+ // text. The previous list missed "email" and "sso" which let the
524
+ // auto-click land on the email/SSO sign-in buttons on Perplexity's
525
+ // anonymous-mode homepage, navigating us into a login flow.
526
+ var isSignIn = new RegExp("sign.?in|log.?in|sign.?up|with\\s+(google|apple|email|github|facebook|microsoft|sso)|sso|auth", "i").test(t);
403
527
  return !isSignIn;
404
528
  });
405
529
  if (verify) { verify.setAttribute('data-gs-verify','1'); return JSON.stringify({t:'sel',s:'[data-gs-verify="1"]',txt:verify.innerText?.trim()||verify.value}); }
@@ -410,7 +534,7 @@ ${l}`,"utf8");try{x(N)}catch{}on(e,N)}}catch{}finally{if(i)try{x(t)}catch{}}}asy
410
534
 
411
535
  return null;
412
536
  })()
413
- `,pn=`
537
+ `,an=`
414
538
  (function() {
415
539
  var url = document.location.href;
416
540
  var isVerifyPage = url.includes('/sorry/') ||
@@ -444,74 +568,89 @@ ${l}`,"utf8");try{x(N)}catch{}on(e,N)}}catch{}finally{if(i)try{x(t)}catch{}}}asy
444
568
 
445
569
  return 'still-verifying';
446
570
  })()
447
- `;async function ee(t,e){let n=await e(["eval",t,$n]).catch(()=>null);if(n&&n!=="null")await new Promise((r)=>setTimeout(r,1500))}function y(t,e){return wn(t*1000,e*1000)/1000}async function Wn(t,e){if(!globalThis.WebSocket)return;let n=process.env.CDP_PROFILE_DIR;if(!n)return;let r=`${n.replaceAll("\\","/")}/DevToolsActivePort`;if(!vn(r))return;let i=mn(r,"utf8").trim().split(`
448
- `)[0],u=await new Promise((l,a)=>{let c=xn.get(`http://localhost:${i}/json/version`,(b)=>{let s="";b.on("data",(w)=>s+=w),b.on("end",()=>{try{l(JSON.parse(s))}catch{a(Error("bad JSON"))}})});c.on("error",a),c.setTimeout(1000,()=>{c.destroy(),a(Error("timeout"))})}),o=new globalThis.WebSocket(u.webSocketDebuggerUrl),f=0;await new Promise((l)=>{o.onopen=async()=>{let a=(s,w)=>new Promise((I)=>{let ct=++f,gt=(ue)=>{if(JSON.parse(ue.data).id===ct)o.removeEventListener("message",gt),I()};o.addEventListener("message",gt),o.send(JSON.stringify({id:ct,method:s,params:w}))}),c=t+y(-2,2),b=e+y(-2,2);await a("Input.dispatchMouseEvent",{type:"mouseMoved",x:c,y:b,button:"none"}),await new Promise((s)=>setTimeout(s,y(80,160))),await a("Input.dispatchMouseEvent",{type:"mousePressed",x:c,y:b,button:"left",clickCount:1}),await new Promise((s)=>setTimeout(s,y(30,80))),await a("Input.dispatchMouseEvent",{type:"mouseReleased",x:c+y(-1,1),y:b+y(-1,1),button:"left",clickCount:1}),setTimeout(()=>{o.close(),l()},200)},o.onerror=()=>l(),setTimeout(l,3000)})}async function ne(t,e,n,r){let i=Number.parseFloat(n),u=Number.parseFloat(r);if(Number.isNaN(i)||Number.isNaN(u))throw Error(`humanClickXY: invalid coordinates (${n}, ${r})`);let o={button:"left",clickCount:1,modifiers:0},f=i+y(-3,3),l=u+y(-3,3);await e(["evalraw",t,"Input.dispatchMouseEvent",JSON.stringify({...o,type:"mouseMoved",x:f,y:l})]),await new Promise((w)=>setTimeout(w,y(80,180)));let a=i+y(-2,2),c=u+y(-2,2);await e(["evalraw",t,"Input.dispatchMouseEvent",JSON.stringify({...o,type:"mousePressed",x:a,y:c})]),await new Promise((w)=>setTimeout(w,y(30,90)));let b=a+y(-1,1),s=c+y(-1,1);return await e(["evalraw",t,"Input.dispatchMouseEvent",JSON.stringify({...o,type:"mouseReleased",x:b,y:s})]),await Wn(i,u).catch(()=>{}),await new Promise((w)=>setTimeout(w,y(100,300))),`human-clicked at (${i.toFixed(0)}, ${u.toFixed(0)})`}async function kn(t,e,n){let r=await e(["eval",t,`(function() {
571
+ `;async function et(e,t){let n=await t(["eval",e,rn]).catch(()=>null);if(n&&n!=="null")await new Promise((i)=>setTimeout(i,1500))}function d(e,t){return Et(e*1000,t*1000)/1000}async function ln(e,t){if(!globalThis.WebSocket)return;let n=process.env.CDP_PROFILE_DIR;if(!n)return;let i=`${n.replaceAll("\\","/")}/DevToolsActivePort`;if(!en(i))return;let r=tn(i,"utf8").trim().split(`
572
+ `)[0],o=await new Promise((u,f)=>{let s=nn.get(`http://localhost:${r}/json/version`,(g)=>{let p="";g.on("data",(c)=>p+=c),g.on("end",()=>{try{u(JSON.parse(p))}catch{f(Error("bad JSON"))}})});s.on("error",f),s.setTimeout(1000,()=>{s.destroy(),f(Error("timeout"))})}),a=new globalThis.WebSocket(o.webSocketDebuggerUrl),l=0;await new Promise((u)=>{a.onopen=async()=>{let f=(p,c)=>new Promise((Z)=>{let W=++l,T=(O)=>{if(JSON.parse(O.data).id===W)a.removeEventListener("message",T),Z()};a.addEventListener("message",T),a.send(JSON.stringify({id:W,method:p,params:c}))}),s=e+d(-2,2),g=t+d(-2,2);await f("Input.dispatchMouseEvent",{type:"mouseMoved",x:s,y:g,button:"none"}),await new Promise((p)=>setTimeout(p,d(80,160))),await f("Input.dispatchMouseEvent",{type:"mousePressed",x:s,y:g,button:"left",clickCount:1}),await new Promise((p)=>setTimeout(p,d(30,80))),await f("Input.dispatchMouseEvent",{type:"mouseReleased",x:s+d(-1,1),y:g+d(-1,1),button:"left",clickCount:1}),setTimeout(()=>{a.close(),u()},200)},a.onerror=()=>u(),setTimeout(u,3000)})}async function tt(e,t,n,i){let r=Number.parseFloat(n),o=Number.parseFloat(i);if(Number.isNaN(r)||Number.isNaN(o))throw Error(`humanClickXY: invalid coordinates (${n}, ${i})`);let a={button:"left",clickCount:1,modifiers:0},l=r+d(-3,3),u=o+d(-3,3);await t(["evalraw",e,"Input.dispatchMouseEvent",JSON.stringify({...a,type:"mouseMoved",x:l,y:u})]),await new Promise((c)=>setTimeout(c,d(80,180)));let f=r+d(-2,2),s=o+d(-2,2);await t(["evalraw",e,"Input.dispatchMouseEvent",JSON.stringify({...a,type:"mousePressed",x:f,y:s})]),await new Promise((c)=>setTimeout(c,d(30,90)));let g=f+d(-1,1),p=s+d(-1,1);return await t(["evalraw",e,"Input.dispatchMouseEvent",JSON.stringify({...a,type:"mouseReleased",x:g,y:p})]),await ln(r,o).catch(()=>{}),await new Promise((c)=>setTimeout(c,d(100,300))),`human-clicked at (${r.toFixed(0)}, ${o.toFixed(0)})`}async function un(e,t,n){let i=await t(["eval",e,`(function() {
449
573
  var el = document.querySelector('${n.replace(/\\/g,"\\\\").replace(/'/g,"\\'")}');
450
574
  if (!el) return 'null';
451
575
  var r = el.getBoundingClientRect();
452
576
  return JSON.stringify({x: r.left + r.width / 2, y: r.top + r.height / 2, w: r.width, h: r.height});
453
- })()`]).catch(()=>"null");if(!r||r==="null")return null;let i=JSON.parse(r);if(i.w===0||i.h===0||i.x===0&&i.y===0)return null;let{x:u,y:o}=i;return ne(t,e,u,o)}async function te(t,e,n){if(!n||n==="null"||n==="cleared"||n==="still-verifying")return!1;try{let r=JSON.parse(n);if(r.t==="sel"&&r.s)return process.stderr.write(`[greedysearch] Human-clicking "${r.txt}" via CDP...
454
- `),await kn(t,e,r.s)!==null;if(r.t==="xy"){if(!r.x&&!r.y)return!1;return process.stderr.write(`[greedysearch] Human-clicking at (${r.x.toFixed(0)}, ${r.y.toFixed(0)})...
455
- `),await ne(t,e,r.x,r.y),!0}}catch{}return!1}async function Xn(t,e){let n=await e(["eval",t,Jn]).catch(()=>null);return n&&n!=="null"?n:null}async function re(t,e,n=30000){let r=await Xn(t,e);if(!r)return"clear";if(r==="sorry-page"){process.stderr.write(`[greedysearch] Google CAPTCHA detected please solve it in the browser window (waiting up to ${Math.floor(n/1000)}s)...
456
- `);let i=Date.now()+n;while(Date.now()<i)if(await new Promise((u)=>setTimeout(u,2000)),!(await e(["eval",t,"document.location.href"]).catch(()=>"")).includes("/sorry/"))return"cleared-by-user";return"needs-human"}if(await te(t,e,r)){await new Promise((u)=>setTimeout(u,2000));let i=Date.now()+n;while(Date.now()<i){let u=await e(["eval",t,pn]).catch(()=>null);if(u==="cleared"||!u||u==="null")return process.stderr.write(`[greedysearch] Verification cleared.
457
- `),"clicked";if(u!=="still-verifying")await te(t,e,u),await new Promise((o)=>setTimeout(o,2000));else await new Promise((o)=>setTimeout(o,1500))}return process.stderr.write(`[greedysearch] Verification may require manual intervention.
458
- `),"needs-human"}return"clear"}var ie={perplexity:{input:"#ask-input",copyButton:null,sourceItem:"[data-pplx-citation-url]",sourceLink:"a",consent:"#onetrust-accept-btn-handler"},bing:{input:"#userInput",copyButton:'button[data-testid="copy-ai-message-button"]',sourceLink:'a[href^="http"][target="_blank"]',sourceExclude:"copilot.microsoft.com",consent:"#onetrust-accept-btn-handler"},google:{answerContainer:".pWvJNd",sourceLink:'a[href^="http"]',sourceExclude:["google.","gstatic","googleapis"],sourceHeadingParent:"[data-snhf]",consent:'#L2AGLb, button[jsname="b3VHJd"], .tHlp8d'},gemini:{input:"rich-textarea .ql-editor",copyButton:'button:has(mat-icon[data-mat-icon-name="copy"])',sendButton:'button:has(mat-icon[data-mat-icon-name="arrow_upward"]), [data-test-id="send-button"], .send-button',sourcesSidebarButton:"button.legacy-sources-sidebar-button",sourcesExclude:["gemini.google","gstatic","google.com/search"],citationButtonPattern:'button[aria-label*="citation from"]',citationNameRegex:/from\s{1,20}([^.]{1,200})\.\s/}};var V=ie.gemini,at="__geminiClipboard";async function qn(t,e){if(await g(["click",t,V.input]),await new Promise((r)=>setTimeout(r,j(200))),await d(["type",t,"--stdin"],e),await new Promise((r)=>setTimeout(r,j(300))),await g(["eval",t,`(function() {
459
- var el = document.querySelector('${V.input}');
460
- if (!el) return false;
461
- var content = el.innerText || el.textContent || '';
462
- return content.trim().length >= ${Math.floor(e.length*0.8)};
463
- })()`])!=="true")throw Error("Gemini input field did not accept text — input verification failed")}async function Nn(t){await g(["eval",t,`(function() {
577
+ })()`]).catch(()=>"null");if(!i||i==="null")return null;let r=JSON.parse(i);if(r.w===0||r.h===0||r.x===0&&r.y===0)return null;let{x:o,y:a}=r;return tt(e,t,o,a)}function Ee(e,t,n){if(!n||n==="null"||n==="cleared"||n==="still-verifying"||n==="cf-closed-shadow-dom")return Promise.resolve("no-challenge");try{let i=JSON.parse(n);if(i.t==="sel"&&i.s)return process.stderr.write(`[greedysearch] Human-clicking "${i.txt}" via CDP...
578
+ `),un(e,t,i.s).then((r)=>r!==null?"clicked":"cant-click");if(i.t==="xy"){if(!i.x&&!i.y)return Promise.resolve("cant-click");return process.stderr.write(`[greedysearch] Human-clicking at (${i.x.toFixed(0)}, ${i.y.toFixed(0)})...
579
+ `),tt(e,t,i.x,i.y).then(()=>"clicked")}}catch{}return Promise.resolve("no-challenge")}async function sn(e,t){let n=await t(["eval",e,on]).catch(()=>null);if(n==="cf-closed-shadow-dom"){let i=await cn(e,t).catch(()=>null);if(i)return i;return n}if(n&&n!=="null")return n;return null}async function cn(e,t){if(typeof t!=="function")return null;await t(["evalraw",e,"DOM.enable","{}"]).catch(()=>{});let n=await t(["evalraw",e,"DOM.getDocument",JSON.stringify({depth:-1,pierce:!0})]).catch(()=>null);if(!n)return null;let i;try{i=JSON.parse(n)}catch{return null}if(i.error||!i.root)return null;let r=i.root;return await nt(r,e,t)}async function nt(e,t,n){if(!e)return null;let i=[];if(e.shadowRoots&&e.shadowRoots.length>0)for(let r of e.shadowRoots)i.push(r);if(e.children)for(let r of e.children)i.push(r);for(let r of i){if(r.nodeName==="IFRAME"){let a=r.attributes||[],l=a.indexOf("src"),u=l>=0?a[l+1]:"";if(u&&/challenges\.cloudflare\.com|turnstile/i.test(u)&&r.backendNodeId){let f=await n(["evalraw",t,"DOM.getBoxModel",JSON.stringify({backendNodeId:r.backendNodeId})]).catch(()=>null);if(!f)continue;let s;try{s=JSON.parse(f)}catch{continue}let g=s?.model?.content||s?.result?.model?.content;if(!g||g.length<8)continue;let p=g[0],c=g[1],Z=g[4],W=g[5],T=Z-p,O=W-c;if(T<50||O<20)continue;let ge=p+T*0.25,he=c+O*0.5;return process.stderr.write(`[greedysearch] Found CF iframe via CDP pierce at (${p.toFixed(0)}, ${c.toFixed(0)}) ${T.toFixed(0)}x${O.toFixed(0)}, clicking checkbox at (${ge.toFixed(0)}, ${he.toFixed(0)})
580
+ `),JSON.stringify({t:"xy",x:ge,y:he})}}let o=await nt(r,t,n);if(o)return o}return null}async function rt(e,t,n=30000){let i=await sn(e,t);if(!i)return"clear";if(i==="sorry-page"){process.stderr.write(`[greedysearch] Google CAPTCHA detected — please solve it in the browser window (waiting up to ${Math.floor(n/1000)}s)...
581
+ `);let o=Date.now()+n;while(Date.now()<o)if(await new Promise((a)=>setTimeout(a,2000)),!(await t(["eval",e,"document.location.href"]).catch(()=>"")).includes("/sorry/"))return"cleared-by-user";return"needs-human"}let r=await Ee(e,t,i);if(r==="clicked"){await new Promise((a)=>setTimeout(a,2000));let o=Date.now()+n;while(Date.now()<o){let a=await t(["eval",e,an]).catch(()=>null);if(a==="cleared"||!a||a==="null")return process.stderr.write(`[greedysearch] Verification cleared.
582
+ `),"clicked";if(a!=="still-verifying")await Ee(e,t,a),await new Promise((l)=>setTimeout(l,2000));else await new Promise((l)=>setTimeout(l,1500))}return process.stderr.write(`[greedysearch] Verification may require manual intervention.
583
+ `),"needs-human"}if(r==="cant-click")return process.stderr.write(`[greedysearch] Verification challenge detected but cannot be auto-clicked — please solve it manually in the visible browser window.
584
+ `),"needs-human";return"clear"}var it={perplexity:{input:"#ask-input",copyButton:null,sourceItem:"[data-pplx-citation-url]",sourceLink:"a",consent:"#onetrust-accept-btn-handler"},bing:{input:"#userInput",copyButton:'button[data-testid="copy-ai-message-button"]',sourceLink:'a[href^="http"][target="_blank"]',sourceExclude:"copilot.microsoft.com",consent:"#onetrust-accept-btn-handler"},google:{answerContainer:".pWvJNd",sourceLink:'a[href^="http"]',sourceExclude:["google.","gstatic","googleapis"],sourceHeadingParent:"[data-snhf]",consent:'#L2AGLb, button[jsname="b3VHJd"], .tHlp8d'},gemini:{input:"rich-textarea .ql-editor",copyButton:'button:has(mat-icon[data-mat-icon-name="copy"])',sendButton:'button:has(mat-icon[data-mat-icon-name="arrow_upward"]), [data-test-id="send-button"], .send-button',sourcesSidebarButton:"button.legacy-sources-sidebar-button",sourcesExclude:["gemini.google","gstatic","google.com/search"],citationButtonPattern:'button[aria-label*="citation from"]',citationNameRegex:/from\s{1,20}([^.]{1,200})\.\s/}};var q=it.gemini,E="__geminiClipboard";async function fn(e,t){await h(["click",e,q.input]),await new Promise((a)=>setTimeout(a,B(200)));let n=async()=>{await ee(["type",e,"--stdin"],t),await new Promise((a)=>setTimeout(a,B(300)))},i=async()=>{let a=await h(["eval",e,`(() => {
585
+ const el = document.querySelector('${q.input}');
586
+ return JSON.stringify(el ? el.innerText || el.textContent || '' : '');
587
+ })()`]);try{return JSON.parse(a)}catch{return a}},r=async()=>me(await i(),t),o=async()=>{await h(["eval",e,`(() => {
588
+ const el = document.querySelector('${q.input}');
589
+ if (!el) return false;
590
+ el.focus();
591
+ const range = document.createRange();
592
+ range.selectNodeContents(el);
593
+ const selection = window.getSelection();
594
+ selection.removeAllRanges();
595
+ selection.addRange(range);
596
+ document.execCommand('delete');
597
+ return true;
598
+ })()`])};if(await n(),await r())return;if(await o(),await n(),!await r())throw Error("Gemini input field did not accept text — input verification failed")}async function fe(e,{required:t=!1}={}){try{return await h(["evalraw",e,"Page.bringToFront","{}"],5000),!0}catch(n){if(console.error(`[gemini] bringToFront failed: ${n.message}`),t)throw n;return!1}}async function gn(e){await h(["eval",e,`(function() {
464
599
  const chat = document.querySelector('chat-window, [role="main"], main') || document.body;
465
600
  chat.scrollTo ? chat.scrollTo({ top: chat.scrollHeight, behavior: 'smooth' }) : window.scrollTo(0, document.body.scrollHeight);
466
- })()`])}async function Qn(t){let e=await g(["eval",t,String.raw`
467
- (() => {
468
- // The model-response element is a custom element <model-response>.
469
- // Its innerText starts with the "Gemini said" label in the
470
- // current locale; strip that prefix and return the rest.
471
- const resp = document.querySelector('model-response');
472
- if (!resp) return JSON.stringify({ answer: '', sources: [] });
473
- const text = (resp.innerText || resp.textContent || '').trim();
474
- // Strip the locale-specific "Gemini said" label prefix.
475
- // It varies ("Το Gemini είπε" in Greek, "Gemini said" in
476
- // English, etc.) so we just look for the first newline and
477
- // take what follows.
478
- const idx = text.indexOf('\n');
479
- const answer = idx >= 0 ? text.slice(idx + 1).trim() : text;
480
- if (!answer) return JSON.stringify({ answer: '', sources: [] });
481
- // Extract source links from the response.
482
- const seen = new Set();
483
- const sources = [];
484
- for (const link of resp.querySelectorAll('a[href]')) {
485
- const url = link.href;
486
- if (!url || seen.has(url)) continue;
487
- seen.add(url);
488
- const title = (link.innerText || link.textContent || '').replace(/\s+/g, ' ').trim();
489
- sources.push({ title, url });
490
- if (sources.length >= 10) break;
491
- }
492
- return JSON.stringify({ answer, sources });
493
- })()
494
- `]);try{return JSON.parse(e)}catch{return{answer:"",sources:[]}}}async function Hn(t,e=""){let n=e.toLowerCase().trim(),r=!1,i=Date.now()+12000;while(Date.now()<i){if(await g(["eval",t,String.raw`(() => {
495
- const r = document.querySelector('model-response');
496
- if (!r) return false;
497
- const t = (r.innerText || '').trim();
498
- // Must have content beyond the locale-specific label
499
- // ("Gemini said" / "Το Gemini είπε" / etc.) and ideally
500
- // a copy button rendered on the response.
501
- return t.length > 20;
502
- })()`])===!0){r=!0;break}await new Promise((b)=>setTimeout(b,800))}if(!r)console.error("[gemini] Warning: model-response did not render content");await g(["eval",t,`(() => {
503
- const resp = document.querySelector('model-response');
504
- if (!resp) return 'no-model-response';
505
- const btn = resp.querySelector('${V.copyButton}');
506
- if (!btn) return 'no-copy-button';
507
- btn.click();
508
- return 'clicked';
509
- })()`]),await new Promise((c)=>setTimeout(c,600));let u=await g(["eval",t,`window.${at} || ''`]);if(u&&n&&(u.toLowerCase().trim()===n||u.trim().length<n.length))console.error("[gemini] Clipboard echoed query, retrying in 2s..."),await new Promise((c)=>setTimeout(c,2000)),await g(["eval",t,`(() => {
510
- const resp = document.querySelector('model-response');
511
- if (!resp) return 'no-model-response';
512
- const btn = resp.querySelector('${V.copyButton}');
513
- if (!btn) return 'no-copy-button';
514
- btn.click();
515
- return 'clicked';
516
- })()`]),await new Promise((c)=>setTimeout(c,600)),u=await g(["eval",t,`window.${at} || ''`]);let o=null;if(!u||n&&(u.toLowerCase().trim()===n||u.trim().length<n.length)){if(o=await Qn(t),o.answer)u=o.answer}if(!u)throw Error("Gemini returned no answer — model-response never rendered content");let f=yt(u),l=new Map;for(let c of[...o?.sources||[],...f])if(c?.url&&!l.has(c.url))l.set(c.url,c);let a=Array.from(l.values()).slice(0,10);return{answer:u.trim(),sources:a}}var Bn=`Usage: node extractors/gemini.mjs "<query>" [--tab <prefix>]
517
- `;async function Zn(){let t=await mt(process.argv.slice(2));$t(t,Bn);let{query:e,tabPrefix:n,short:r}=xt(t);if(process.env.GREEDY_SEARCH_VISIBLE!=="1"&&process.env.GREEDY_SEARCH_ALWAYS_VISIBLE!=="1")process.env.GREEDY_SEARCH_HEADLESS="1";await Et();try{await g(["list"]);let i=await st(n),u=await g(["eval",i,"document.location.href"]).catch(()=>""),o=!1;try{let s=new URL(u).hostname.toLowerCase();o=s==="gemini.google.com"||s.endsWith(".gemini.google.com")}catch{}if(!o)await g(["nav",i,"https://gemini.google.com/app"],20000),await new Promise((s)=>setTimeout(s,600));await ee(i,g),await re(i,g,1e4),await vt(i,V.input,8000,C.inputPoll),await new Promise((s)=>setTimeout(s,j(C.postClick))),await bt(i,at),await qn(i,e),await new Promise((s)=>setTimeout(s,j(C.postType))),await g(["eval",i,`document.querySelector('${V.sendButton}')?.click()`]);let f=0,l=setInterval(()=>{if(++f%10===0)Nn(i).catch(()=>null)},6000);try{await wt(i,{timeout:45000,minLength:50})}finally{clearInterval(l)}let{answer:a,sources:c}=await Hn(i,e);if(!a)throw Error("No answer captured from Gemini clipboard");let b=await g(["eval",i,"document.location.href"]).catch(()=>"https://gemini.google.com/app");pt({query:e,url:b,answer:Jt(a,r),sources:c})}catch(i){Wt(i)}}Zn();
601
+ })()`])}async function hn(e){let t=await h(["eval",e,String.raw`
602
+ new Promise((resolve) => {
603
+ const _deadline = Date.now() + 6000;
604
+ function _tryExtract() {
605
+ const responses = Array.from(document.querySelectorAll('model-response'));
606
+ const resp = responses[responses.length - 1];
607
+ if (resp) {
608
+ const text = (resp.innerText || resp.textContent || '').trim();
609
+ const idx = text.indexOf('\n');
610
+ const answer = idx >= 0 ? text.slice(idx + 1).trim() : text;
611
+ if (answer) {
612
+ const seen = new Set();
613
+ const sources = [];
614
+ for (const link of resp.querySelectorAll('a[href]')) {
615
+ const url = link.href;
616
+ if (!url || seen.has(url)) continue;
617
+ seen.add(url);
618
+ const title = (link.innerText || link.textContent || '').replace(/\s+/g, ' ').trim();
619
+ sources.push({ title, url });
620
+ if (sources.length >= 10) break;
621
+ }
622
+ return resolve(JSON.stringify({ answer, sources }));
623
+ }
624
+ }
625
+ if (Date.now() < _deadline) {
626
+ setTimeout(_tryExtract, 500);
627
+ } else {
628
+ resolve(JSON.stringify({ answer: '', sources: [] }));
629
+ }
630
+ }
631
+ _tryExtract();
632
+ })
633
+ `],8000);try{return JSON.parse(t)}catch(n){return console.error(`[gemini] DOM fallback JSON parse failed (${t.length} chars): ${n.message}`),{answer:"",sources:[]}}}var ot=`(() => {
634
+ window.${E} = '';
635
+ const responses = Array.from(document.querySelectorAll('model-response'));
636
+ const resp = responses[responses.length - 1];
637
+ if (!resp) return;
638
+ const buttons = Array.from(resp.querySelectorAll('${q.copyButton}'));
639
+ const nonCodeButtons = buttons.filter((btn) => !btn.closest('pre, code, code-block, .code-block, .code-container'));
640
+ const btn = nonCodeButtons[nonCodeButtons.length - 1] || buttons[buttons.length - 1];
641
+ if (btn) btn.click();
642
+ })()`;async function pn(e,t="",n=!1){let i=t.toLowerCase().trim(),r=!1;if(n)r=await h(["eval",e,String.raw`(() => {
643
+ const responses = Array.from(document.querySelectorAll('model-response'));
644
+ const r = responses[responses.length - 1];
645
+ return !!r && (r.innerText || '').trim().length > 60;
646
+ })()`]).catch(()=>"false")==="true";else{let c=Date.now()+12000;while(Date.now()<c){if(await h(["eval",e,String.raw`(() => {
647
+ const responses = Array.from(document.querySelectorAll('model-response'));
648
+ const r = responses[responses.length - 1];
649
+ if (!r) return false;
650
+ const t = (r.innerText || '').trim();
651
+ // Must have content beyond the locale-specific label
652
+ // ("Gemini said" / "Το Gemini είπε" / etc.) and ideally
653
+ // a copy button rendered on the response.
654
+ return t.length > 60;
655
+ })()`])==="true"){r=!0;break}await new Promise((W)=>setTimeout(W,800))}}if(!r)console.error("[gemini] Warning: model-response did not render content");let o=await te(e,ot,E,{timeoutMs:600,retryClick:600});if(o&&i&&(o.toLowerCase().trim()===i||o.trim().length<i.length))console.error("[gemini] Clipboard echoed query, retrying in 2s..."),await new Promise((c)=>setTimeout(c,2000)),o=await te(e,ot,E,{timeoutMs:600,retryClick:600});let a=null,l=o?.trim()||"",u=i&&(l.toLowerCase()===i||l.length<i.length);if(!(l.length>500&&!u)){a=await hn(e);let c=l&&a.answer.includes(l)&&a.answer.length>l.length*2;if(a.answer&&(!l||u||c))o=a.answer}if(!o)throw Error("Gemini returned no answer — model-response never rendered content");let s=ve(o),g=new Map;for(let c of[...a?.sources||[],...s])if(c?.url&&!g.has(c.url))g.set(c.url,c);let p=Array.from(g.values()).slice(0,10);return{answer:o.trim(),sources:p}}var mn=`Usage: node extractors/gemini.mjs "<query>" [--tab <prefix>]
656
+ `;async function yn(){let e=await $e(process.argv.slice(2));_e(e,mn);let{query:t,tabPrefix:n,short:i}=ke(e);if(process.env.GREEDY_SEARCH_VISIBLE!=="1"&&process.env.GREEDY_SEARCH_ALWAYS_VISIBLE!=="1")process.env.GREEDY_SEARCH_HEADLESS="1";await Ie();try{await h(["list"]);let r=await ye(n),o=await h(["eval",r,"document.location.href"]).catch(()=>""),a=!1;try{let c=new URL(o).hostname.toLowerCase();a=c==="gemini.google.com"||c.endsWith(".gemini.google.com")}catch{}if(!a)await h(["nav",r,"https://gemini.google.com/app"],20000),await new Promise((c)=>setTimeout(c,600));await et(r,h),await rt(r,h,1e4),await xe(r,q.input,8000,Q.inputPoll),await new Promise((c)=>setTimeout(c,B(Q.postClick))),await fe(r,{required:!0}),await de(r,E),await fn(r,t),await new Promise((c)=>setTimeout(c,B(Q.postType))),await h(["eval",r,`document.querySelector('${q.sendButton}')?.click()`]),await fe(r);let l=0,u=setInterval(()=>{if(fe(r).catch(()=>null),++l%10===0)gn(r).catch(()=>null)},6000),f=!0;try{await we(r,{timeout:45000,stableRounds:5,minLength:60,selector:"(() => { const responses = Array.from(document.querySelectorAll('model-response')); return responses[responses.length - 1]; })()"})}catch{f=!1}finally{clearInterval(u)}let{answer:s,sources:g}=await pn(r,t,f);if(!s)throw Error("No answer captured from Gemini clipboard");let p=await h(["eval",r,"document.location.href"]).catch(()=>"https://gemini.google.com/app");Ne({query:t,url:p,answer:Je(s,i),sources:g})}catch(r){We(r)}}yn();