@duckmind/dm-windows-x64 0.60.6 → 0.60.9

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 (197) hide show
  1. package/dm.exe +0 -0
  2. package/extensions/.dm-extensions.json +70 -123
  3. package/extensions/dm-9router-ext/src/index.js +410 -5
  4. package/extensions/dm-caveman/extensions/caveman.js +283 -12
  5. package/extensions/dm-cliproxy/index.js +182 -2
  6. package/extensions/dm-cliproxy/scripts/check-config-migration.js +66 -8
  7. package/extensions/dm-cliproxy/src/apply.js +228 -1
  8. package/extensions/dm-cliproxy/src/cache.js +42 -1
  9. package/extensions/dm-cliproxy/src/commands.js +50 -2
  10. package/extensions/dm-cliproxy/src/compat.js +81 -1
  11. package/extensions/dm-cliproxy/src/config.js +192 -2
  12. package/extensions/dm-cliproxy/src/conflicts.js +46 -1
  13. package/extensions/dm-cliproxy/src/fetch-models.js +190 -1
  14. package/extensions/dm-cliproxy/src/fetch-usage.js +41 -1
  15. package/extensions/dm-cliproxy/src/log.js +23 -1
  16. package/extensions/dm-cliproxy/src/status-quota.js +77 -1
  17. package/extensions/dm-cliproxy/src/ui-frame.js +50 -1
  18. package/extensions/dm-cliproxy/src/ui-hub/hub.js +199 -2
  19. package/extensions/dm-cliproxy/src/ui-hub/index.js +26 -2
  20. package/extensions/dm-cliproxy/src/ui-hub/shell.js +46 -1
  21. package/extensions/dm-cliproxy/src/ui-hub/view-diagnostics.js +69 -1
  22. package/extensions/dm-cliproxy/src/ui-hub/view-models.js +379 -1
  23. package/extensions/dm-cliproxy/src/ui-hub/view-usage.js +106 -1
  24. package/extensions/dm-cliproxy/src/ui-picker/catalog.js +41 -1
  25. package/extensions/dm-cliproxy/src/ui-picker/mutate.js +115 -1
  26. package/extensions/dm-cliproxy/src/ui-picker/prompt-confirm.js +35 -1
  27. package/extensions/dm-cliproxy/src/ui-picker/prompt-name.js +62 -1
  28. package/extensions/dm-cliproxy/src/ui-picker/providers.js +45 -1
  29. package/extensions/dm-cliproxy/src/ui-picker/render-text.js +34 -1
  30. package/extensions/dm-cliproxy/src/ui-picker/rows.js +57 -1
  31. package/extensions/dm-cliproxy/src/ui-setup.js +260 -2
  32. package/extensions/dm-cliproxy/src/ui-usage.js +151 -1
  33. package/extensions/dm-cliproxy/src/usage-shared-cache.js +97 -1
  34. package/extensions/dm-context/src/context.js +144 -1
  35. package/extensions/dm-context/src/index.js +339 -7
  36. package/extensions/dm-context/src/utils.js +9 -1
  37. package/extensions/dm-cua/bin/browser-cua.mjs +73 -8
  38. package/extensions/dm-cua/index.js +75 -6
  39. package/extensions/dm-cua/src/browser-cua-lib.mjs +490 -6
  40. package/extensions/dm-cua/src/browser-install.mjs +331 -2
  41. package/extensions/dm-fff/src/index.js +688 -12
  42. package/extensions/dm-fff/src/query.js +60 -1
  43. package/extensions/dm-goal/src/goal.js +894 -23
  44. package/extensions/dm-image2/index.js +103 -9
  45. package/extensions/dm-image2/src/image-lib.mjs +1275 -8
  46. package/extensions/dm-subagents/install.mjs +62 -8
  47. package/extensions/dm-subagents/src/agents/agent-management.js +1190 -36
  48. package/extensions/dm-subagents/src/agents/agent-memory.js +216 -6
  49. package/extensions/dm-subagents/src/agents/agent-scope.js +5 -1
  50. package/extensions/dm-subagents/src/agents/agent-selection.js +20 -1
  51. package/extensions/dm-subagents/src/agents/agent-serializer.js +120 -5
  52. package/extensions/dm-subagents/src/agents/agents.js +1139 -11
  53. package/extensions/dm-subagents/src/agents/chain-serializer.js +299 -11
  54. package/extensions/dm-subagents/src/agents/frontmatter.js +65 -6
  55. package/extensions/dm-subagents/src/agents/identity.js +29 -1
  56. package/extensions/dm-subagents/src/agents/proactive-skills.js +141 -1
  57. package/extensions/dm-subagents/src/agents/skills.js +614 -6
  58. package/extensions/dm-subagents/src/extension/config.js +35 -2
  59. package/extensions/dm-subagents/src/extension/control-notices.js +69 -4
  60. package/extensions/dm-subagents/src/extension/doctor.js +172 -15
  61. package/extensions/dm-subagents/src/extension/fanout-child.js +158 -231
  62. package/extensions/dm-subagents/src/extension/index.js +521 -359
  63. package/extensions/dm-subagents/src/extension/rpc.js +266 -7
  64. package/extensions/dm-subagents/src/extension/schemas.js +275 -1
  65. package/extensions/dm-subagents/src/extension/tool-description.js +111 -6
  66. package/extensions/dm-subagents/src/intercom/intercom-bridge.js +126 -4
  67. package/extensions/dm-subagents/src/intercom/native-supervisor-channel.js +452 -5
  68. package/extensions/dm-subagents/src/intercom/result-intercom.js +319 -3
  69. package/extensions/dm-subagents/src/profiles/profiles.js +458 -3
  70. package/extensions/dm-subagents/src/runs/background/async-execution.js +834 -40
  71. package/extensions/dm-subagents/src/runs/background/async-job-tracker.js +435 -14
  72. package/extensions/dm-subagents/src/runs/background/async-resume.js +334 -8
  73. package/extensions/dm-subagents/src/runs/background/async-status.js +313 -12
  74. package/extensions/dm-subagents/src/runs/background/chain-append.js +245 -2
  75. package/extensions/dm-subagents/src/runs/background/chain-root-attachment.js +136 -1
  76. package/extensions/dm-subagents/src/runs/background/completion-batcher.js +94 -1
  77. package/extensions/dm-subagents/src/runs/background/completion-dedupe.js +54 -1
  78. package/extensions/dm-subagents/src/runs/background/control-channel.js +190 -1
  79. package/extensions/dm-subagents/src/runs/background/fleet-view.js +483 -17
  80. package/extensions/dm-subagents/src/runs/background/notify.js +129 -3
  81. package/extensions/dm-subagents/src/runs/background/parallel-groups.js +34 -1
  82. package/extensions/dm-subagents/src/runs/background/result-watcher.js +236 -6
  83. package/extensions/dm-subagents/src/runs/background/run-id-resolver.js +76 -4
  84. package/extensions/dm-subagents/src/runs/background/run-status.js +427 -23
  85. package/extensions/dm-subagents/src/runs/background/scheduled-runs.js +487 -4
  86. package/extensions/dm-subagents/src/runs/background/stale-run-reconciler.js +306 -9
  87. package/extensions/dm-subagents/src/runs/background/subagent-runner.js +2849 -73
  88. package/extensions/dm-subagents/src/runs/background/top-level-async.js +5 -1
  89. package/extensions/dm-subagents/src/runs/background/wait.js +206 -11
  90. package/extensions/dm-subagents/src/runs/foreground/chain-clarify.js +1013 -12
  91. package/extensions/dm-subagents/src/runs/foreground/chain-execution.js +980 -101
  92. package/extensions/dm-subagents/src/runs/foreground/execution.js +1165 -45
  93. package/extensions/dm-subagents/src/runs/foreground/subagent-executor.js +3157 -222
  94. package/extensions/dm-subagents/src/runs/shared/acceptance.js +835 -3
  95. package/extensions/dm-subagents/src/runs/shared/chain-outputs.js +104 -1
  96. package/extensions/dm-subagents/src/runs/shared/completion-guard.js +116 -3
  97. package/extensions/dm-subagents/src/runs/shared/dm-args.js +208 -1
  98. package/extensions/dm-subagents/src/runs/shared/dm-spawn.js +90 -1
  99. package/extensions/dm-subagents/src/runs/shared/dynamic-fanout.js +282 -1
  100. package/extensions/dm-subagents/src/runs/shared/long-running-guard.js +148 -1
  101. package/extensions/dm-subagents/src/runs/shared/mcp-direct-tool-allowlist.js +305 -1
  102. package/extensions/dm-subagents/src/runs/shared/model-fallback.js +194 -1
  103. package/extensions/dm-subagents/src/runs/shared/model-scope.js +65 -1
  104. package/extensions/dm-subagents/src/runs/shared/nested-events.js +851 -8
  105. package/extensions/dm-subagents/src/runs/shared/nested-path.js +41 -1
  106. package/extensions/dm-subagents/src/runs/shared/nested-render.js +105 -1
  107. package/extensions/dm-subagents/src/runs/shared/parallel-utils.js +81 -4
  108. package/extensions/dm-subagents/src/runs/shared/run-history.js +51 -4
  109. package/extensions/dm-subagents/src/runs/shared/single-output.js +149 -8
  110. package/extensions/dm-subagents/src/runs/shared/structured-output.js +58 -1
  111. package/extensions/dm-subagents/src/runs/shared/subagent-control.js +166 -5
  112. package/extensions/dm-subagents/src/runs/shared/subagent-prompt-runtime.js +329 -13
  113. package/extensions/dm-subagents/src/runs/shared/tool-budget.js +73 -1
  114. package/extensions/dm-subagents/src/runs/shared/turn-budget.js +47 -4
  115. package/extensions/dm-subagents/src/runs/shared/workflow-graph.js +196 -1
  116. package/extensions/dm-subagents/src/runs/shared/worktree.js +435 -3
  117. package/extensions/dm-subagents/src/shared/artifacts.js +92 -2
  118. package/extensions/dm-subagents/src/shared/atomic-json.js +55 -1
  119. package/extensions/dm-subagents/src/shared/child-transcript.js +167 -5
  120. package/extensions/dm-subagents/src/shared/file-coalescer.js +25 -1
  121. package/extensions/dm-subagents/src/shared/fork-context.js +147 -4
  122. package/extensions/dm-subagents/src/shared/formatters.js +98 -7
  123. package/extensions/dm-subagents/src/shared/jsonl-writer.js +56 -2
  124. package/extensions/dm-subagents/src/shared/model-info.js +62 -1
  125. package/extensions/dm-subagents/src/shared/post-exit-stdio-guard.js +68 -1
  126. package/extensions/dm-subagents/src/shared/session-identity.js +6 -1
  127. package/extensions/dm-subagents/src/shared/session-tokens.js +39 -2
  128. package/extensions/dm-subagents/src/shared/settings.js +198 -11
  129. package/extensions/dm-subagents/src/shared/status-format.js +53 -1
  130. package/extensions/dm-subagents/src/shared/types.js +184 -6
  131. package/extensions/dm-subagents/src/shared/utils.js +462 -2
  132. package/extensions/dm-subagents/src/slash/prompt-template-bridge.js +288 -1
  133. package/extensions/dm-subagents/src/slash/prompt-workflows.js +297 -7
  134. package/extensions/dm-subagents/src/slash/slash-bridge.js +118 -1
  135. package/extensions/dm-subagents/src/slash/slash-commands.js +1287 -31
  136. package/extensions/dm-subagents/src/slash/slash-live-state.js +240 -4
  137. package/extensions/dm-subagents/src/tui/render-helpers.js +64 -1
  138. package/extensions/dm-subagents/src/tui/render.js +1542 -4
  139. package/extensions/dm-usage/index.js +1294 -9
  140. package/extensions/greedysearch-dm/bin/cdp-greedy.mjs +40 -9
  141. package/extensions/greedysearch-dm/bin/cdp-headless.mjs +5 -2
  142. package/extensions/greedysearch-dm/bin/cdp-visible.mjs +5 -2
  143. package/extensions/greedysearch-dm/bin/cdp.mjs +896 -30
  144. package/extensions/greedysearch-dm/bin/gschrome.mjs +30 -2
  145. package/extensions/greedysearch-dm/bin/kill-visible.mjs +7 -2
  146. package/extensions/greedysearch-dm/bin/launch-visible.mjs +13 -2
  147. package/extensions/greedysearch-dm/bin/launch.mjs +282 -10
  148. package/extensions/greedysearch-dm/bin/mcp.mjs +386 -361
  149. package/extensions/greedysearch-dm/bin/search.mjs +620 -540
  150. package/extensions/greedysearch-dm/bin/visible.mjs +22 -2
  151. package/extensions/greedysearch-dm/extractors/bing-copilot.mjs +329 -579
  152. package/extensions/greedysearch-dm/extractors/chatgpt.mjs +301 -583
  153. package/extensions/greedysearch-dm/extractors/common.mjs +408 -32
  154. package/extensions/greedysearch-dm/extractors/consensus.mjs +376 -365
  155. package/extensions/greedysearch-dm/extractors/consent.mjs +303 -14
  156. package/extensions/greedysearch-dm/extractors/gemini.mjs +228 -592
  157. package/extensions/greedysearch-dm/extractors/google-ai.mjs +78 -499
  158. package/extensions/greedysearch-dm/extractors/logically.mjs +270 -347
  159. package/extensions/greedysearch-dm/extractors/perplexity.mjs +243 -581
  160. package/extensions/greedysearch-dm/extractors/selectors.mjs +32 -1
  161. package/extensions/greedysearch-dm/extractors/semantic-scholar.mjs +130 -317
  162. package/extensions/greedysearch-dm/index.js +123 -23
  163. package/extensions/greedysearch-dm/src/fetcher.mjs +576 -2
  164. package/extensions/greedysearch-dm/src/formatters/results.js +95 -10
  165. package/extensions/greedysearch-dm/src/formatters/sources.js +57 -1
  166. package/extensions/greedysearch-dm/src/formatters/synthesis.js +49 -1
  167. package/extensions/greedysearch-dm/src/github.mjs +222 -7
  168. package/extensions/greedysearch-dm/src/reddit.mjs +145 -14
  169. package/extensions/greedysearch-dm/src/search/browser-lifecycle.mjs +340 -9
  170. package/extensions/greedysearch-dm/src/search/challenge-detect.mjs +112 -4
  171. package/extensions/greedysearch-dm/src/search/chrome.mjs +486 -285
  172. package/extensions/greedysearch-dm/src/search/constants.mjs +109 -8
  173. package/extensions/greedysearch-dm/src/search/defaults.mjs +10 -1
  174. package/extensions/greedysearch-dm/src/search/engines.mjs +79 -9
  175. package/extensions/greedysearch-dm/src/search/fetch-source.mjs +441 -349
  176. package/extensions/greedysearch-dm/src/search/file-sources.mjs +29 -7
  177. package/extensions/greedysearch-dm/src/search/minimize.mjs +86 -1
  178. package/extensions/greedysearch-dm/src/search/output.mjs +51 -5
  179. package/extensions/greedysearch-dm/src/search/paths.mjs +48 -1
  180. package/extensions/greedysearch-dm/src/search/pdf.mjs +63 -2
  181. package/extensions/greedysearch-dm/src/search/port-pid.mjs +69 -1
  182. package/extensions/greedysearch-dm/src/search/progress.mjs +109 -2
  183. package/extensions/greedysearch-dm/src/search/query.mjs +21 -1
  184. package/extensions/greedysearch-dm/src/search/recovery.mjs +49 -1
  185. package/extensions/greedysearch-dm/src/search/research.mjs +2227 -458
  186. package/extensions/greedysearch-dm/src/search/scale-aware.mjs +61 -11
  187. package/extensions/greedysearch-dm/src/search/simple-research.mjs +396 -805
  188. package/extensions/greedysearch-dm/src/search/sources.mjs +412 -1
  189. package/extensions/greedysearch-dm/src/search/synthesis-runner.mjs +127 -12
  190. package/extensions/greedysearch-dm/src/search/synthesis.mjs +202 -12
  191. package/extensions/greedysearch-dm/src/tools/greedy-search-handler.js +209 -23
  192. package/extensions/greedysearch-dm/src/tools/shared.js +226 -10
  193. package/extensions/greedysearch-dm/src/utils/content.mjs +35 -4
  194. package/extensions/greedysearch-dm/src/utils/helpers.js +22 -1
  195. package/extensions/greedysearch-dm/src/utils/node-runtime.mjs +10 -1
  196. package/extensions/greedysearch-dm/src/utils/system-cmds.mjs +61 -1
  197. package/package.json +1 -1
@@ -1,589 +1,55 @@
1
- #!/usr/bin/env node
2
- import{randomInt as ut}from"node:crypto";import{spawn as st}from"node:child_process";import{basename as ct}from"node:path";import{dirname as gt,join as ht}from"node:path";import{fileURLToPath as pt}from"node:url";function ft(e=process.env,t=process.execPath){let n=e.GREEDY_SEARCH_NODE||e.NODE_BINARY||e.NODE;if(n?.trim())return n.trim();let r=ct(t||"").toLowerCase();if(r==="node"||r==="node.exe")return t;return"node"}var mt=gt(pt(import.meta.url)),yt=ht(mt,"..","bin","cdp.mjs"),vt=new Set(["list","snap","eval","shot","html","nav","net","click","clickxy","type","loadall","evalraw","browse","stop","--tab"]);function dt(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)=>ye(t,n));if(!vt.has(e[0]))throw Error(`cdp: unknown subcommand '${e[0]}'`);return e.map((t,n)=>ye(t,n))}function ye(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 ne(e,null,t)}function ne(e,t=null,n=30000){let r=dt(e);return new Promise((i,o)=>{let a=st(ft(),[yt,...r],{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)i(l.trim());else o(Error(u.trim()||`cdp exit ${s}`))})})}function ve(e,t){let n=(a)=>String(a??"").replace(/\s+/g," ").trim(),r=n(e),i=n(t);if(!i)return!1;if(r.length<Math.ceil(i.length*0.8))return!1;let o=Math.min(40,i.length);return r.includes(i.slice(0,o))&&r.includes(i.slice(-o))}async function de(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"}']),r;try{r=JSON.parse(n)}catch(a){throw Error(`Target.createTarget returned invalid JSON: ${a.message}`)}let{targetId:i}=r;if(!i)throw Error("Target.createTarget did not return a targetId");await h(["list"]);let o=i.slice(0,8);try{await we(o)}catch(a){process.stderr.write(`[getOrOpenTab] stealth injection failed: ${a.message}
4
- `)}return o}async function be(e,t){let n=`
5
- (() => {
6
- window.${t} = null;
7
- const _clipboard = navigator.clipboard;
8
- if (!_clipboard) return;
9
- const _origWriteText = typeof _clipboard.writeText === 'function'
10
- ? _clipboard.writeText.bind(_clipboard)
11
- : null;
12
- const _origWrite = typeof _clipboard.write === 'function'
13
- ? _clipboard.write.bind(_clipboard)
14
- : null;
15
-
16
- _clipboard.writeText = function(text) {
17
- window.${t} = String(text ?? '');
18
- if (!_origWriteText) return Promise.resolve();
19
- // The OS/browser clipboard write may be denied in automated Chrome or
20
- // when the tab is not focused. We only need the captured text; returning
21
- // a resolved promise prevents the page from surfacing a misleading
22
- // "failed to copy" toast after our interceptor already succeeded.
23
- return Promise.resolve(_origWriteText(text)).catch(() => undefined);
24
- };
25
-
26
- _clipboard.write = async function(items) {
27
- try {
28
- for (const item of items || []) {
29
- if (item.types && item.types.includes('text/plain')) {
30
- const blob = await item.getType('text/plain');
31
- window.${t} = await blob.text();
32
- break;
33
- }
34
- }
35
- } catch(e) {}
36
- if (!_origWrite) return undefined;
37
- try { return await _origWrite(items); }
38
- catch (_) { return undefined; }
39
- };
40
- })();
41
- `;await h(["eval",e,n])}async function re(e,t,n,r={}){let{timeoutMs:i=2600}=r,o=r.retryClick!=null?r.retryClick:Math.floor(i*0.4),a=String.raw`
42
- new Promise((resolve) => {
43
- const _deadline = Date.now() + ${i};
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],i+5000).catch(()=>"")}async function we(e){await h(["evalraw",e,"Page.addScriptToEvaluateOnNewDocument",JSON.stringify({source:`
61
- (function() {
62
- // ── Runtime.enable / CDP detection masking ──────────────
63
- try { delete window.__REBROWSER_RUNTIME_ENABLE; } catch(_) {}
64
- try { delete window.__REBROWSER_DEVTOOLS; } catch(_) {}
65
- try { delete window.__nightmare; } catch(_) {}
66
- try { delete window.__phantom; } catch(_) {}
67
- try { delete window.callPhantom; } catch(_) {}
68
- try { delete window._phantom; } catch(_) {}
69
- try { delete window.Buffer; } catch(_) {}
70
-
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(_) {}
77
- Object.defineProperty(navigator, 'vendor', { get: () => 'Google Inc.', configurable: true });
78
- Object.defineProperty(navigator, 'platform', { get: () => 'Win32', configurable: true });
79
- Object.defineProperty(navigator, 'maxTouchPoints', { get: () => 0, configurable: true });
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
- }
95
- Object.defineProperty(navigator, 'plugins', {
96
- get: () => {
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(_) {}
113
- return p;
114
- },
115
- configurable: true,
116
- });
117
- Object.defineProperty(navigator, 'mimeTypes', {
118
- get: () => {
119
- __greedyMimeTypes = __greedyMimeTypes || __makeMimeTypes();
120
- return __greedyMimeTypes;
121
- },
122
- configurable: true,
123
- });
124
- Object.defineProperty(navigator, 'languages', { get: () => ['en-US', 'en'], configurable: true });
125
- try {
126
- Object.defineProperty(navigator, 'connection', { get: () => ({ effectiveType: '4g', rtt: 50, downlink: 10, downlinkMax: Infinity, saveData: false }), configurable: true });
127
- } catch(_) {}
128
- if (!navigator.mediaDevices) {
129
- Object.defineProperty(navigator, 'mediaDevices', {
130
- get: () => ({
131
- enumerateDevices: () => Promise.resolve([
132
- { deviceId: 'default', kind: 'audioinput', label: '', groupId: 'default' },
133
- { deviceId: 'default', kind: 'audiooutput', label: '', groupId: 'default' },
134
- { deviceId: '', kind: 'videoinput', label: '', groupId: '' },
135
- ]),
136
- getUserMedia: () => Promise.reject(new DOMException('NotAllowedError')),
137
- getDisplayMedia: () => Promise.reject(new DOMException('NotAllowedError')),
138
- }),
139
- configurable: true,
140
- });
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
-
154
- if (!window.chrome) {
155
- window.chrome = {
156
- app: { isInstalled: false, InstallState: {}, RunningState: {} },
157
- runtime: {
158
- OnInstalledReason: {}, OnRestartRequiredReason: {}, PlatformArch: {}, PlatformNaclArch: {}, PlatformOs: {}, RequestUpdateCheckStatus: {},
159
- connect: () => ({}), sendMessage: () => {}, onMessage: { addListener: () => {} }
160
- },
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 }; },
163
- };
164
- }
165
- var __greedyNativeFns = [];
166
- function __markNative(fn) { try { __greedyNativeFns.push(fn); } catch(_) {} return fn; }
167
-
168
- var origQuery = navigator.permissions?.query;
169
- if (origQuery) {
170
- navigator.permissions.query = __markNative(function query(params) {
171
- if (params && params.name === 'notifications') return Promise.resolve({ state: Notification.permission || 'default', onchange: null });
172
- return origQuery.apply(this, arguments);
173
- });
174
- }
175
- try {
176
- var getParam = WebGLRenderingContext.prototype.getParameter;
177
- WebGLRenderingContext.prototype.getParameter = __markNative(function getParameter(p) {
178
- if (p === 37445) return 'Intel Inc.';
179
- if (p === 37446) return 'Intel Iris OpenGL Engine';
180
- return getParam.call(this, p);
181
- });
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(_) {}
196
- Object.defineProperty(navigator, 'hardwareConcurrency', { get: () => 8, configurable: true });
197
- Object.defineProperty(navigator, 'deviceMemory', { get: () => 8, configurable: true });
198
-
199
- // ── Canvas fingerprint noise ─────────────────────────
200
- // Headless rendering engines produce slightly different canvas output
201
- // than headed Chrome. Subtle noise breaks hash-based fingerprinting.
202
- try {
203
- var __canvasNoise = ((Date.now() & 0xFF) | 1);
204
- var origFill = CanvasRenderingContext2D.prototype.fillText;
205
- CanvasRenderingContext2D.prototype.fillText = __markNative(function fillText() {
206
- this.globalAlpha = 0.9995;
207
- return origFill.apply(this, arguments);
208
- });
209
- } catch(_) {}
210
- try {
211
- var origStroke = CanvasRenderingContext2D.prototype.strokeText;
212
- CanvasRenderingContext2D.prototype.strokeText = __markNative(function strokeText() {
213
- this.globalAlpha = 0.9995;
214
- return origStroke.apply(this, arguments);
215
- });
216
- } catch(_) {}
217
- try {
218
- var origToDataURL = HTMLCanvasElement.prototype.toDataURL;
219
- HTMLCanvasElement.prototype.toDataURL = __markNative(function toDataURL() {
220
- var ctx = this.getContext('2d');
221
- if (ctx) {
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
- }
235
- }
236
- return origToDataURL.apply(this, arguments);
237
- });
238
- } catch(_) {}
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
-
255
- // ── window outer dimensions ──────────────────────────
256
- // outerWidth/Height = 0 in headless — a well-known bot signal.
257
- // Mirror innerWidth/Height (set by --window-size flag) so the ratio is sane.
258
- try {
259
- if (!window.outerWidth) Object.defineProperty(window, 'outerWidth', { get: () => window.innerWidth || 1920, configurable: true });
260
- if (!window.outerHeight) Object.defineProperty(window, 'outerHeight', { get: () => window.innerHeight || 1080, configurable: true });
261
- } catch(_) {}
262
-
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.
266
- try {
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 });
273
- } catch(_) {}
274
-
275
- // ── navigator.userAgentData (UA Client Hints) ─────────
276
- // Derive version from the UA string already set by --user-agent flag so the
277
- // two APIs are always consistent. Removes any "HeadlessChrome" brand entry.
278
- try {
279
- var _uaMajor = (navigator.userAgent.match(new RegExp('Chrome/([0-9]+)')) || [])[1] || '136';
280
- var _uaFull = (navigator.userAgent.match(new RegExp('Chrome/([0-9.]+)')) || [])[1] || (_uaMajor + '.0.0.0');
281
- var _brands = [
282
- { brand: 'Not)A;Brand', version: '99' },
283
- { brand: 'Google Chrome', version: _uaMajor },
284
- { brand: 'Chromium', version: _uaMajor },
285
- ];
286
- Object.defineProperty(navigator, 'userAgentData', {
287
- get: function() {
288
- return {
289
- brands: _brands, mobile: false, platform: 'Windows',
290
- getHighEntropyValues: function() {
291
- return Promise.resolve({
292
- architecture: 'x86', bitness: '64',
293
- brands: _brands,
294
- fullVersionList: [
295
- { brand: 'Not)A;Brand', version: '99.0.0.0' },
296
- { brand: 'Google Chrome', version: _uaFull },
297
- { brand: 'Chromium', version: _uaFull },
298
- ],
299
- mobile: false, model: '', platform: 'Windows',
300
- platformVersion: '15.0.0', uaFullVersion: _uaFull, wow64: false,
301
- });
302
- },
303
- toJSON: function() { return { brands: _brands, mobile: false, platform: 'Windows' }; },
304
- };
305
- },
306
- configurable: true,
307
- });
308
- } catch(_) {}
309
-
310
- // ── CDP Runtime serialization guard ──────────────────
311
- // Sites detect CDP by putting a getter on Error.prototype.stack
312
- // and checking if console.log triggers it (only happens when
313
- // Runtime domain is enabled). We monkey-patch console methods to
314
- // strip custom getters from arguments before they reach CDP.
315
- try {
316
- var _origLog = console.log, _origError = console.error,
317
- _origWarn = console.warn, _origDebug = console.debug,
318
- _origInfo = console.info;
319
- var _safeArg = function(a) {
320
- if (a instanceof Error) {
321
- try { return new Error(a.message); } catch(_) { return a; }
322
- }
323
- return a;
324
- };
325
- console.log = __markNative(function log() { return _origLog.apply(console, Array.prototype.map.call(arguments, _safeArg)); });
326
- console.error = __markNative(function error() { return _origError.apply(console, Array.prototype.map.call(arguments, _safeArg)); });
327
- console.warn = __markNative(function warn() { return _origWarn.apply(console, Array.prototype.map.call(arguments, _safeArg)); });
328
- console.debug = __markNative(function debug() { return _origDebug.apply(console, Array.prototype.map.call(arguments, _safeArg)); });
329
- console.info = __markNative(function info() { return _origInfo.apply(console, Array.prototype.map.call(arguments, _safeArg)); });
330
- } catch(_) {}
331
-
332
- // ── Native function masking ──────────────────────────
333
- // Patched APIs should not stringify as user-defined stealth code.
334
- try {
335
- var __nativeToString = Function.prototype.toString;
336
- Function.prototype.toString = function toString() {
337
- if (__greedyNativeFns.indexOf(this) !== -1) {
338
- var name = this.name || '';
339
- return 'function ' + name + '() { [native code] }';
340
- }
341
- return __nativeToString.call(this);
342
- };
343
- } catch(_) {}
344
- })();
345
- `})])}function xe(e){if(!e)return[];let t=[],n=0;while(n<e.length&&t.length<10){let r=e.indexOf("[",n);if(r===-1)break;let i=e.indexOf("](",r);if(i===-1)break;let o=i+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(r+1,i),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=r+1}return t}var Q={postNav:800,postNavSlow:1200,postClick:300,postType:300,inputPoll:400,copyPoll:600,afterVerify:1500};function O(e){let t=e*0.2,n=ut(-Math.floor(t),Math.floor(t)+1);return Math.max(50,Math.round(e+n))}async function $e(e,t={}){let{timeout:n=20000,interval:r=600,stableRounds:i=3,selector:o="document.body",minLength:a=0,isStreamingExpr:l="false"}=t,u=String.raw`
346
- new Promise((resolve, reject) => {
347
- const _deadline = Date.now() + ${n};
348
- const _baseInterval = ${r};
349
- const _stableRounds = ${i};
350
- const _minLength = ${a};
351
- let _lastLen = -1;
352
- let _stableCount = 0;
353
-
354
- function _jitter(ms) {
355
- return Math.max(50, ms + (Math.random() * ms * 0.4 - ms * 0.2));
356
- }
357
-
358
- function _poll() {
359
- try {
360
- // Re-query DOM each tick — element may not exist at eval start
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) {
368
- if (cur === _lastLen) {
369
- _stableCount++;
370
- if (_stableCount >= _stableRounds) { resolve(cur); return; }
371
- } else {
372
- _lastLen = cur;
373
- _stableCount = 0;
374
- }
375
- }
376
- if (Date.now() < _deadline) {
377
- setTimeout(_poll, _jitter(_baseInterval));
378
- } else {
379
- if (_lastLen >= _minLength && !streaming) { resolve(_lastLen); }
380
- else { reject(new Error('Generation did not stabilise within ${n}ms')); }
381
- }
382
- } catch(e) { reject(e); }
383
- }
384
-
385
- _poll();
386
- })
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 _e(e,t,n=15000,r=500){let i=String.raw`
388
- new Promise((resolve) => {
389
- const _deadline = Date.now() + ${n};
390
- const _baseInterval = ${r};
391
-
392
- function _jitter(ms) {
393
- return Math.max(50, ms + (Math.random() * ms * 0.4 - ms * 0.2));
394
- }
395
-
396
- function _poll() {
397
- try {
398
- if (document.querySelector('${t}')) { resolve(true); return; }
399
- if (Date.now() < _deadline) { setTimeout(_poll, _jitter(_baseInterval)); }
400
- else { resolve(false); }
401
- } catch(_) { resolve(false); }
402
- }
403
-
404
- _poll();
405
- })
406
- `;return await h(["eval",e,i],n+5000)==="true"}async function ke(e){let t=e.indexOf("--stdin");if(t===-1)return e;let n=await new Promise((i)=>{let o="";process.stdin.setEncoding("utf8"),process.stdin.on("data",(a)=>o+=a),process.stdin.on("end",()=>i(o.trim()))}),r=[...e];return r[t]=n,r}function Ne(e){let t=e.includes("--short"),n=e.filter((l)=>l!=="--short"),r=n.indexOf("--tab"),i=r===-1?null:n[r+1];if(r!==-1)n=n.filter((l,u)=>u!==r&&u!==r+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:i,short:t,locale:a}}function Je(e,t){if(!e.length||e[0]==="--help")process.stderr.write(t),process.exit(1)}function We(e,t,n=300){if(!t||e.length<=n)return e;let r=e.slice(0,n),i=r.lastIndexOf(" ");return i>0?`${r.slice(0,i)}…`:`${r}…`}function je(e){process.stdout.write(`${JSON.stringify(e,null,2)}
407
- `)}function Te(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 Yt,execFileSync as ce,execSync as ur}from"node:child_process";import{basename as bt}from"node:path";function Se(e=process.env,t=process.execPath){let n=e.GREEDY_SEARCH_NODE||e.NODE_BINARY||e.NODE;if(n?.trim())return n.trim();let r=bt(t||"").toLowerCase();if(r==="node"||r==="node.exe")return t;return"node"}import{existsSync as Ge,readFileSync as fe,renameSync as Rt,unlinkSync as w,writeFileSync as I}from"node:fs";import ge from"node:http";import{platform as Fe}from"node:os";import{existsSync as qe}from"node:fs";import{platform as wt}from"node:os";import{join as _}from"node:path";function d(e){let t=wt()==="win32",n=process.env.SystemRoot||"C:\\Windows",r={win32:{powershell:_(n,"System32","WindowsPowerShell","v1.0","powershell.exe"),powershell_ise:_(n,"System32","WindowsPowerShell","v1.0","powershell_ise.exe"),netstat:_(n,"System32","netstat.exe"),taskkill:_(n,"System32","taskkill.exe"),tasklist:_(n,"System32","tasklist.exe"),cmd:_(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=t?r.win32:r.unix,o=e.toLowerCase();if(i[o]&&qe(i[o]))return i[o];if(t&&o==="netstat"){let a=_(n,"Sysnative","netstat.exe");if(qe(a))return a}return e}import{execFileSync as xt}from"node:child_process";import{platform as $t}from"node:os";function _t(e,t){return xt(d(e),t,{encoding:"utf8",stdio:["ignore","pipe","ignore"],timeout:5000})}function kt(e){let t=String(e||"").match(/\b(\d+)\b/);return t?Number.parseInt(t[1],10):null}function Nt(e){return kt(e)}function Jt(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 i=n.match(/\bpid=(\d+)\b/);if(i)return Number.parseInt(i[1],10)}return null}function Wt(e,t){for(let n of String(e||"").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(`:${t}`))continue;let i=Number.parseInt(r.at(-1),10);if(Number.isInteger(i)&&i>0)return i}return null}function ie(e,t,n){try{return e(t,n)}catch{return null}}function U(e,{platformName:t=$t(),run:n=_t}={}){if(t==="win32")return Wt(ie(n,"netstat",["-ano","-p","TCP"]),e);let r=ie(n,"lsof",["-nP",`-iTCP:${e}`,"-sTCP:LISTEN","-t"]),i=Nt(r);if(i)return i;if(t!=="linux")return null;return Jt(ie(n,"ss",["-ltnp"]),e)}import{existsSync as Oe}from"node:fs";import{dirname as jt,join as B}from"node:path";import{fileURLToPath as Tt}from"node:url";function Be(e){return Tt(new URL(".",e)).replace(/^\/([A-Z]:)/,"$1")}function St(e,t=Oe){let n=new Set;for(let r of e.filter(Boolean)){if(n.has(r))continue;if(n.add(r),t(r))return r}return e.filter(Boolean).at(-1)}function He({moduleDir:e,entrypoint:t=process.argv[1],env:n=process.env,exists:r=Oe}={}){let i=t?jt(t):null,o=n.GREEDY_SEARCH_EXTENSION_DIR?.trim()||null;return St([e?B(e,"..","..","bin","launch.mjs"):null,e?B(e,"launch.mjs"):null,o?B(o,"bin","launch.mjs"):null,i?B(i,"launch.mjs"):null,i?B(i,"..","bin","launch.mjs"):null],r)}import{existsSync as z,mkdirSync as qt,readFileSync as Ve,writeFileSync as Ot}from"node:fs";import{homedir as Bt}from"node:os";import{join as Me}from"node:path";import{tmpdir as Ht}from"node:os";function Xt(e,t=9222){let n=Number.parseInt(String(e??""),10);return Number.isInteger(n)&&n>1024&&n<65535?n:t}var Vt=Ht().replaceAll("\\","/"),m=Xt(process.env.GREEDY_SEARCH_PORT),y=(process.env.GREEDY_SEARCH_PROFILE_DIR||process.env.CDP_PROFILE_DIR||`${Vt}/greedysearch-chrome-profile`).replaceAll("\\","/"),H=`${y}/DevToolsActivePort`,P=process.env.GREEDY_SEARCH_PID_FILE||`${y}/browser.pid`,Mt=process.env.CDP_PAGES_CACHE||`${y}/cdp-pages.json`,$=process.env.GREEDY_SEARCH_MODE_FILE||`${y}/browser-mode`,Ze=process.env.GREEDY_SEARCH_METADATA_FILE||`${y}/browser-metadata.json`,Ce=process.env.GREEDY_SEARCH_LAUNCH_LOCK_FILE||`${y}/browser-launch.lock`,A=process.env.GREEDY_SEARCH_ACTIVITY_FILE||`${y}/browser-last-activity`,Kn=(process.env.CDP_SOCKET_DIR||`${y}/cdp-sockets`).replaceAll("\\","/"),Yn=`${y}/visible-recovery.jsonl`,ae=Me(Bt(),".dm"),b=Me(ae,"greedyconfig"),le=["perplexity","google","chatgpt","gemini"],ue="gemini";function Zt(){try{if(z(b)){let e=Ve(b,"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((i)=>oe[i]),r=t.engines.filter((i)=>!oe[i]);if(r.length>0)process.stderr.write(`[greedysearch] Warning: ignoring unknown engine(s) in ${b}: ${r.join(", ")}
410
- [greedysearch] Available engines: ${Object.keys(oe).join(", ")}
411
- `);if(n.length>0)return n;process.stderr.write(`[greedysearch] Warning: no valid engines in ${b}, falling back to defaults: ${le.join(", ")}
412
- `)}}}catch{}return le}function Ct(){try{if(!z(ae))qt(ae,{recursive:!0});if(!z(b))Ot(b,JSON.stringify({engines:le,synthesizer:ue},null,2)+`
413
- `,"utf8")}catch{}}Ct();var Xe=["gemini","chatgpt"];function Qt(){try{if(z(b)){let e=Ve(b,"utf8"),t=JSON.parse(e);if(typeof t.synthesizer==="string"){let n=t.synthesizer.toLowerCase();if(Xe.includes(n))return n;process.stderr.write(`[greedysearch] Warning: unknown synthesizer "${t.synthesizer}" in ${b}
414
- [greedysearch] Available synthesizers: ${Xe.join(", ")}
415
- [greedysearch] Falling back to default: ${ue}
416
- `)}}}catch{}return ue}var oe={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"},Rn=Zt();var Gn=Qt(),Fn=Math.max(1,Number.parseInt(process.env.GREEDY_FETCH_CONCURRENCY||"5",10)||5);process.env.CDP_PROFILE_DIR=y;import{execFileSync as Qe,execSync as En}from"node:child_process";import{existsSync as D,mkdirSync as Ut,readFileSync as T,unlinkSync as N,writeFileSync as J}from"node:fs";import{platform as zt}from"node:os";var K=Ze,k=Ce,Pt=15000,Y=P,R=$,X=A;function V(e){if(!Number.isInteger(e)||e<=0)return!1;try{return process.kill(e,0),!0}catch{return!1}}function At(e){if(!V(e))return null;try{if(zt()==="win32")return Qe(d("powershell"),["-NoProfile","-NonInteractive","-Command",`(Get-CimInstance Win32_Process -Filter "ProcessId = ${e}").CommandLine`],{encoding:"utf8",windowsHide:!0,timeout:5000}).trim()||null;return Qe(d("ps"),["-p",String(e),"-o","command="],{encoding:"utf8",timeout:5000}).trim()||null}catch{return null}}function Dt(e,t,n=m){if(!e)return!1;let r=(a)=>String(a||"").replaceAll("\\","/").toLowerCase(),i=r(e),o=r(t);return i.includes(o)&&i.includes(`--remote-debugging-port=${n}`)&&!i.includes("--type=")}function Ue(e,t,n=m){return Dt(At(e),t,n)}function Kt(e=m){return U(e)}function M(){try{if(D(K)){let e=T(K,"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=D(Y)?Number.parseInt(T(Y,"utf8").trim(),10)||void 0:void 0,t=D(R)?T(R,"utf8").trim()==="visible"?"visible":"headless":"headless",n=D(X)?Number.parseInt(T(X,"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 G(e){try{J(K,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)J(Y,String(e.browserPid),"utf8")}catch{}try{J(R,e.sessionMode,"utf8")}catch{}try{J(X,String(e.lastActivity),"utf8")}catch{}}function ze(){try{N(K)}catch{}try{N(Y)}catch{}try{N(R)}catch{}try{N(X)}catch{}}function se(e){if(!e)return e;let t={...e,clientPids:[...new Set([...e.clientPids,process.pid].filter((n)=>V(n)||n===process.pid))]};return G(t),t}function F(e){let t=Date.now();try{if(e)G({...e,lastActivity:t});else J(X,String(t),"utf8")}catch{}}var or=Number.parseInt(process.env.GREEDY_SEARCH_IDLE_TIMEOUT_MINUTES||"5",10)||5;var Pe=!1;function Ae(){if(process.env.GREEDY_SEARCH_RESEARCH_CHILD)return;if(Pe)return;Pe=!0;let e=M();if(!e)return;if(e.browserPid){if(!V(e.browserPid)){ze();return}if(!Ue(e.browserPid,e.tempDir,e.debugPort))ze();else G({...e,clientPids:e.clientPids.filter((i)=>V(i))})}let t=Kt();if(t&&t!==e.browserPid)if(Ue(t,y,m))G({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}.
417
- `)}function De(){Ut(y,{recursive:!0});try{let e=JSON.stringify({pid:process.pid,ts:Date.now()});return J(k,e,{encoding:"utf8",flag:"wx"}),{acquired:!0,release:()=>{try{let t=T(k,"utf8");if(JSON.parse(t).pid===process.pid)N(k)}catch{}}}}catch(e){if(e?.code!=="EEXIST")return{acquired:!1,release:()=>{}}}try{let e=T(k,"utf8"),t=JSON.parse(e),n=Date.now()-(t.ts||0);if(!V(t.pid)||n>Pt){try{N(k)}catch{}try{let i=JSON.stringify({pid:process.pid,ts:Date.now()});return J(k,i,{encoding:"utf8",flag:"wx"}),{acquired:!0,release:()=>{try{N(k)}catch{}}}}catch{return{acquired:!1,release:()=>{}}}}}catch{}return{acquired:!1,release:()=>{}}}var Gt=Be(import.meta.url),Ke=P,Z=A,Ft=Number.parseInt(process.env.GREEDY_SEARCH_IDLE_TIMEOUT_MINUTES||"5",10)||5,Lt=Number.parseInt(process.env.GREEDY_SEARCH_VISIBLE_IDLE_TIMEOUT_MINUTES||"60",10)||60;function It(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 Le(){try{let e=ee(),t=e?Ie(e):null,n=It(t);if(n!==null){try{I($,n?"headless":"visible","utf8")}catch{}return n}}catch{}try{if(!Ge($))return!0;return fe($,"utf8").trim()==="headless"}catch{return!0}}function Et(){try{I(Z,String(Date.now()),"utf8")}catch{}try{let e=M();if(e)F(e)}catch{}}function Ie(e){try{if(Fe()==="win32")return ce(d("powershell"),["-NoProfile","-NonInteractive","-Command",`(Get-CimInstance Win32_Process -Filter "ProcessId = ${e}").CommandLine`],{encoding:"utf8",windowsHide:!0,timeout:5000}).trim()||null;return ce(d("ps"),["-p",String(e),"-o","command="],{encoding:"utf8",timeout:5000}).trim()||null}catch{return null}}function en(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 ee(){return U(m)}function E(){let e=ee();return e&&en(Ie(e))?e:null}async function tn(e=1500){let t=E();if(!t)return process.stderr.write(`[greedysearch] Refusing to close an unverified listener.
418
- `),!1;try{let r=await new Promise((o,a)=>{let l=ge.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"))})}),i=new globalThis.WebSocket(r.webSocketDebuggerUrl);await new Promise((o)=>{i.onopen=()=>{if(E()!==t){i.close(),o();return}i.send(JSON.stringify({id:1,method:"Browser.close"})),setTimeout(()=>{i.close(),o()},200)},i.onerror=()=>o(),setTimeout(o,1000)})}catch{}let n=Date.now()+e;while(Date.now()<n){let r=ee();if(!r)return!0;if(r!==t)return!1;await new Promise((i)=>setTimeout(i,150))}return nn(t)}function nn(e=null){try{let t=E();if(!t||e&&t!==e)return!1;if(Fe()==="win32")ce(d("taskkill"),["/F","/PID",String(t)],{stdio:"ignore",windowsHide:!0});else process.kill(t,"SIGKILL");return!0}catch{return!1}}async function Ee(){if(!E()){if(ee())process.stderr.write(`[greedysearch] Refusing to kill an unverified listener.
419
- `);return!1}if(!await x(500)){try{w(Ke)}catch{}try{w(Z)}catch{}try{w($)}catch{}return!1}let t=await tn(1500);try{w(Ke)}catch{}try{w(Z)}catch{}try{w($)}catch{}if(t)process.stderr.write(`[greedysearch] Killed Chrome on port ${m}.
420
- `);return t}var Ye=Ee;async function rn(){let t=Le()?Ft:Lt;if(t<=0)return!1;if(!Ge(Z))return Et(),!1;try{let n=Number.parseInt(fe(Z,"utf8").trim(),10);if(!n)return!1;if((Date.now()-n)/60000>=t)return Ee()}catch{}return!1}function x(e=3000){return new Promise((t)=>{let n=ge.get(`http://localhost:${m}/json/version`,(r)=>{r.resume(),t(r.statusCode===200)});n.on("error",()=>t(!1)),n.setTimeout(e,()=>{n.destroy(),t(!1)})})}async function Re(e=3000,t=200){let n=Date.now()+e;while(Date.now()<n){if(!await x(300))return!0;await new Promise((r)=>setTimeout(r,t))}return!await x(300)}async function L(){let e=`${H}.lock`,t=`${H}.tmp`,n=5000,r=1000,i=await new Promise((o)=>{let a=Date.now(),l=()=>{try{let u=JSON.stringify({pid:process.pid,ts:Date.now()});I(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=fe(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=ge.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(i){I(t,`${m}
421
- ${l}`,"utf8");try{w(H)}catch{}Rt(t,H)}}catch{}finally{if(i)try{w(e)}catch{}}}async function et(){if(process.env.GREEDY_SEARCH_RESEARCH_CHILD&&await x()){await L();try{let o=M();if(o)F(o),se(o)}catch{}return}Ae();let e=await rn(),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=Le(),a=process.env.GREEDY_SEARCH_VISIBLE==="1";if(!a&&!o)process.stderr.write(`[greedysearch] Visible Chrome detected — switching to headless mode...
422
- `),await Ye(),await Re(),n=!0;else if(a&&o)process.stderr.write(`[greedysearch] Headless Chrome detected — switching to visible mode...
423
- `),await Ye(),await Re(),n=!0}if(n?!1:await x()){await L();try{let o=M();if(o)F(o),se(o)}catch{}return}let i=De();if(!i.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 L();return}}try{if(await x(1000)){await L();return}process.stderr.write(`GreedySearch Chrome not running on port ${m} — auto-launching...
424
- `);let l=[He({moduleDir:Gt,entrypoint:process.argv[1],env:process.env})];if(process.env.GREEDY_SEARCH_VISIBLE!=="1")l.push("--headless");await new Promise((u,f)=>{Yt(Se(),l,{stdio:["ignore",process.stderr,process.stderr]}).on("close",(g)=>g===0?u():f(Error("launch.mjs failed")))})}finally{i.release()}}import{randomInt as on}from"node:crypto";import{existsSync as an,readFileSync as ln}from"node:fs";import un from"node:http";var sn=`
425
- (function() {
426
- // Google consent page (consent.google.com)
427
- var g = document.querySelector('#L2AGLb, button[jsname="b3VHJd"], .tHlp8d');
428
- if (g) { g.click(); return 'google'; }
429
-
430
- // OneTrust (used by many sites including Stack Overflow)
431
- var ot = document.querySelector('#onetrust-accept-btn-handler, .onetrust-accept-btn-handler');
432
- if (ot) { ot.click(); return 'onetrust'; }
433
-
434
- // Generic "accept all" / "agree" buttons
435
- var btns = Array.from(document.querySelectorAll('button, a[role=button]'));
436
- var accept = btns.find(b => /^(accept all|accept cookies|agree|i agree|got it|allow all|allow cookies)$/i.test(b.innerText?.trim()));
437
- if (accept) { accept.click(); return 'generic:' + accept.innerText.trim(); }
438
-
439
- return null;
440
- })()
441
- `,cn=`
442
- (function() {
443
- var url = document.location.href;
444
-
445
- // --- Google "sorry" page (hard CAPTCHA, can't auto-solve) ---
446
- if (url.includes('/sorry/') || url.includes('sorry.google')) return 'sorry-page';
447
-
448
- // --- Microsoft account verification page ---
449
- if (url.includes('login.microsoftonline.com') || url.includes('login.live.com') || url.includes('account.microsoft.com')) {
450
- var msBtns = Array.from(document.querySelectorAll('button, input[type=submit], a'));
451
- var msVerify = msBtns.find(b => /verify|continue|next/i.test(b.innerText?.trim() || b.value || ''));
452
- if (msVerify) { msVerify.setAttribute('data-gs-verify','1'); return JSON.stringify({t:'sel',s:'[data-gs-verify="1"]',txt:msVerify.innerText?.trim()||msVerify.value}); }
453
- }
454
-
455
- // --- Copilot / modal verification ---
456
- var modal = document.querySelector('[role="dialog"], .b_modal, [class*="verify"], [class*="challenge"]');
457
- if (modal) {
458
- var modalBtns = Array.from(modal.querySelectorAll('button, a[role="button"], input[type="submit"]'));
459
- var actionBtn = modalBtns.find(b => /^(continue|verify|submit|next|i agree|accept|got it)$/i.test(b.innerText?.trim() || b.value || ''));
460
- if (actionBtn) { actionBtn.setAttribute('data-gs-verify','1'); return JSON.stringify({t:'sel',s:'[data-gs-verify="1"]',txt:actionBtn.innerText?.trim()}); }
461
- }
462
-
463
- // --- Turnstile / Cloudflare challenge iframe (return coordinates for humanClickXY) ---
464
- var turnstileIframe = document.querySelector('iframe[src*="challenges.cloudflare.com"], iframe[src*="turnstile"], iframe[title*="challenge"]');
465
- if (turnstileIframe) {
466
- var r = turnstileIframe.getBoundingClientRect();
467
- return JSON.stringify({t:'xy',x:r.left+30,y:r.top+r.height/2});
468
- }
469
-
470
- // --- Cloudflare Turnstile widget inside closed shadow DOM (Copilot, etc.) ---
471
- // The iframe is not queryable from main document, but the host container
472
- // (#cf-turnstile) and the hidden response input are. When only the
473
- // hidden response input matches (no #cf-turnstile host and no visible
474
- // iframe), the actual challenge widget is rendered inside a closed
475
- // shadow DOM and cannot be auto-clicked. Return a sentinel so callers
476
- // know to surface this as needs-human verification instead of wasting
477
- // time on a doomed waitForSelector.
478
- var cfTurnstileHost = document.querySelector('#cf-turnstile');
479
- if (cfTurnstileHost) {
480
- var r2 = cfTurnstileHost.getBoundingClientRect();
481
- return JSON.stringify({t:'xy',x:r2.left+r2.width/2,y:r2.top+r2.height/2});
482
- }
483
- // Hidden cf-chl-widget-*_response input present but no visible host:
484
- // the widget is in closed shadow DOM. Signal this so handleVerification
485
- // can return 'needs-human' rather than 'clear'.
486
- var cfResponseInput = document.querySelector('input[name="cf-turnstile-response"], [id^="cf-chl-widget-"][id$="_response"]');
487
- if (cfResponseInput && cfResponseInput.value === '') {
488
- return 'cf-closed-shadow-dom';
489
- }
490
-
491
- // --- Cloudflare challenge page ---
492
- var cfCheckbox = document.querySelector('#cf-stage input[type="checkbox"], .ctp-checkbox-container input');
493
- if (cfCheckbox) { cfCheckbox.setAttribute('data-gs-verify','1'); return JSON.stringify({t:'sel',s:'[data-gs-verify="1"]',txt:'cloudflare-checkbox'}); }
494
- var cfBtn = document.querySelector('#challenge-form button, .cf-challenge button');
495
- if (cfBtn) { cfBtn.setAttribute('data-gs-verify','1'); return JSON.stringify({t:'sel',s:'[data-gs-verify="1"]',txt:cfBtn.innerText?.trim()}); }
496
-
497
- // --- Microsoft "I am human" button ---
498
- var msHumanBtn = document.querySelector('button[id*="i0"], button[id*="id__"]');
499
- if (msHumanBtn && /verify|human|robot|continue/i.test(msHumanBtn.innerText?.trim())) {
500
- msHumanBtn.setAttribute('data-gs-verify','1'); return JSON.stringify({t:'sel',s:'[data-gs-verify="1"]',txt:msHumanBtn.innerText.trim()});
501
- }
502
-
503
- // --- Generic verify/continue/proceed buttons (catch-all) ---
504
- // IMPORTANT: exclude sign-in / OAuth buttons (e.g. "Continue with Google",
505
- // "Continue with email", "Login or sign up for free"). These appear on
506
- // many sites (Perplexity, ChatGPT, etc.) when the user isn't logged in,
507
- // and clicking them triggers a sign-in flow that takes us to a login
508
- // wall — a much worse outcome than the original search failure we were
509
- // trying to recover from. The exclusion list must cover both OAuth
510
- // providers AND generic "sign in / log in / with email" patterns.
511
- var btns = Array.from(document.querySelectorAll('button, input[type=submit], a[role=button]'));
512
- var verify = btns.find(b => {
513
- var t = (b.innerText?.trim() || b.value || '').toLowerCase();
514
- var isVerifyLike = (t === 'continue' || t === 'proceed' || t === 'next' ||
515
- t.startsWith('verify ') || t.startsWith('human ') || t === 'i am human' || t.includes('robot check')) &&
516
- !t.includes('verified') && !document.querySelector('iframe[src*="recaptcha"]');
517
- if (!isVerifyLike) return false;
518
- // Exclude OAuth / sign-in buttons to prevent accidental login flows
519
- // — covers "Continue with Google", "Continue with Apple", "Continue
520
- // with email", "Login or sign up", "Log in", "Sign in", "Sign up",
521
- // "Single sign-on", and the visible panel "Login or sign up for free"
522
- // text. The previous list missed "email" and "sso" which let the
523
- // auto-click land on the email/SSO sign-in buttons on Perplexity's
524
- // anonymous-mode homepage, navigating us into a login flow.
525
- var isSignIn = new RegExp("sign.?in|log.?in|sign.?up|with\\s+(google|apple|email|github|facebook|microsoft|sso)|sso|auth", "i").test(t);
526
- return !isSignIn;
527
- });
528
- if (verify) { verify.setAttribute('data-gs-verify','1'); return JSON.stringify({t:'sel',s:'[data-gs-verify="1"]',txt:verify.innerText?.trim()||verify.value}); }
529
-
530
- // --- Google reCAPTCHA checkbox ---
531
- var recaptchaCheckbox = document.querySelector('.recaptcha-checkbox-unchecked, input[type=checkbox][id*="recaptcha"]');
532
- if (recaptchaCheckbox) { recaptchaCheckbox.setAttribute('data-gs-verify','1'); return JSON.stringify({t:'sel',s:'[data-gs-verify="1"]',txt:'recaptcha'}); }
533
-
534
- return null;
535
- })()
536
- `,fn=`
537
- (function() {
538
- var url = document.location.href;
539
- var isVerifyPage = url.includes('/sorry/') ||
540
- url.includes('challenges.cloudflare.com') ||
541
- url.includes('login.microsoftonline.com') ||
542
- document.querySelector('#challenge-running, #challenge-stage, .cf-turnstile, [role="dialog"]');
543
- if (!isVerifyPage) return 'cleared';
544
-
545
- var btns = Array.from(document.querySelectorAll('button, input[type=submit], a[role=button]'));
546
- var btn = btns.find(b => {
547
- var t = (b.innerText?.trim() || b.value || '').toLowerCase();
548
- var isVerifyLike = t.includes('verify') || t.includes('human') || t.includes('robot') || t.includes('continue') || t.includes('next') || t.includes('submit');
549
- if (!isVerifyLike) return false;
550
- var isSignIn = /sign.in|log.in|google|microsoft|apple|facebook|github|auth/i.test(t);
551
- return !isSignIn;
552
- });
553
- if (btn) { btn.setAttribute('data-gs-verify','1'); return JSON.stringify({t:'sel',s:'[data-gs-verify="1"]',txt:btn.innerText?.trim()||btn.value}); }
554
-
555
- var cf = document.querySelector('#cf-stage input[type="checkbox"], .cf-turnstile input');
556
- if (cf) { cf.setAttribute('data-gs-verify','1'); return JSON.stringify({t:'sel',s:'[data-gs-verify="1"]',txt:'turnstile'}); }
557
-
558
- // Cloudflare Turnstile widget inside closed shadow DOM (detected via host container)
559
- var cfTurnstileHost = document.querySelector('#cf-turnstile, [id^="cf-chl-widget-"]');
560
- if (cfTurnstileHost) { return 'still-verifying'; }
561
-
562
- var modal = document.querySelector('[role="dialog"], .b_modal, [class*="verify"]');
563
- if (modal) {
564
- var modalBtn = modal.querySelector('button, a[role="button"]');
565
- if (modalBtn) { modalBtn.setAttribute('data-gs-verify','1'); return JSON.stringify({t:'sel',s:'[data-gs-verify="1"]',txt:modalBtn.innerText?.trim()}); }
566
- }
567
-
568
- return 'still-verifying';
569
- })()
570
- `;async function nt(e,t){let n=await t(["eval",e,sn]).catch(()=>null);if(n&&n!=="null")await new Promise((r)=>setTimeout(r,1500))}function v(e,t){return on(e*1000,t*1000)/1000}async function gn(e,t){if(!globalThis.WebSocket)return;let n=process.env.CDP_PROFILE_DIR;if(!n)return;let r=`${n.replaceAll("\\","/")}/DevToolsActivePort`;if(!an(r))return;let i=ln(r,"utf8").trim().split(`
571
- `)[0],o=await new Promise((u,f)=>{let s=un.get(`http://localhost:${i}/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((C)=>{let W=++l,j=(q)=>{if(JSON.parse(q.data).id===W)a.removeEventListener("message",j),C()};a.addEventListener("message",j),a.send(JSON.stringify({id:W,method:p,params:c}))}),s=e+v(-2,2),g=t+v(-2,2);await f("Input.dispatchMouseEvent",{type:"mouseMoved",x:s,y:g,button:"none"}),await new Promise((p)=>setTimeout(p,v(80,160))),await f("Input.dispatchMouseEvent",{type:"mousePressed",x:s,y:g,button:"left",clickCount:1}),await new Promise((p)=>setTimeout(p,v(30,80))),await f("Input.dispatchMouseEvent",{type:"mouseReleased",x:s+v(-1,1),y:g+v(-1,1),button:"left",clickCount:1}),setTimeout(()=>{a.close(),u()},200)},a.onerror=()=>u(),setTimeout(u,3000)})}async function rt(e,t,n,r){let i=Number.parseFloat(n),o=Number.parseFloat(r);if(Number.isNaN(i)||Number.isNaN(o))throw Error(`humanClickXY: invalid coordinates (${n}, ${r})`);let a={button:"left",clickCount:1,modifiers:0},l=i+v(-3,3),u=o+v(-3,3);await t(["evalraw",e,"Input.dispatchMouseEvent",JSON.stringify({...a,type:"mouseMoved",x:l,y:u})]),await new Promise((c)=>setTimeout(c,v(80,180)));let f=i+v(-2,2),s=o+v(-2,2);await t(["evalraw",e,"Input.dispatchMouseEvent",JSON.stringify({...a,type:"mousePressed",x:f,y:s})]),await new Promise((c)=>setTimeout(c,v(30,90)));let g=f+v(-1,1),p=s+v(-1,1);return await t(["evalraw",e,"Input.dispatchMouseEvent",JSON.stringify({...a,type:"mouseReleased",x:g,y:p})]),await gn(i,o).catch(()=>{}),await new Promise((c)=>setTimeout(c,v(100,300))),`human-clicked at (${i.toFixed(0)}, ${o.toFixed(0)})`}async function hn(e,t,n){let r=await t(["eval",e,`(function() {
572
- var el = document.querySelector('${n.replace(/\\/g,"\\\\").replace(/'/g,"\\'")}');
573
- if (!el) return 'null';
574
- var r = el.getBoundingClientRect();
575
- return JSON.stringify({x: r.left + r.width / 2, y: r.top + r.height / 2, w: r.width, h: r.height});
576
- })()`]).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:o,y:a}=i;return rt(e,t,o,a)}function tt(e,t,n){if(!n||n==="null"||n==="cleared"||n==="still-verifying"||n==="cf-closed-shadow-dom")return Promise.resolve("no-challenge");try{let r=JSON.parse(n);if(r.t==="sel"&&r.s)return process.stderr.write(`[greedysearch] Human-clicking "${r.txt}" via CDP...
577
- `),hn(e,t,r.s).then((i)=>i!==null?"clicked":"cant-click");if(r.t==="xy"){if(!r.x&&!r.y)return Promise.resolve("cant-click");return process.stderr.write(`[greedysearch] Human-clicking at (${r.x.toFixed(0)}, ${r.y.toFixed(0)})...
578
- `),rt(e,t,r.x,r.y).then(()=>"clicked")}}catch{}return Promise.resolve("no-challenge")}async function pn(e,t){let n=await t(["eval",e,cn]).catch(()=>null);if(n==="cf-closed-shadow-dom"){let r=await mn(e,t).catch(()=>null);if(r)return r;return n}if(n&&n!=="null")return n;return null}async function mn(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 r;try{r=JSON.parse(n)}catch{return null}if(r.error||!r.root)return null;let i=r.root;return await it(i,e,t)}async function it(e,t,n){if(!e)return null;let r=[];if(e.shadowRoots&&e.shadowRoots.length>0)for(let i of e.shadowRoots)r.push(i);if(e.children)for(let i of e.children)r.push(i);for(let i of r){if(i.nodeName==="IFRAME"){let a=i.attributes||[],l=a.indexOf("src"),u=l>=0?a[l+1]:"";if(u&&/challenges\.cloudflare\.com|turnstile/i.test(u)&&i.backendNodeId){let f=await n(["evalraw",t,"DOM.getBoxModel",JSON.stringify({backendNodeId:i.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],C=g[4],W=g[5],j=C-p,q=W-c;if(j<50||q<20)continue;let pe=p+j*0.25,me=c+q*0.5;return process.stderr.write(`[greedysearch] Found CF iframe via CDP pierce at (${p.toFixed(0)}, ${c.toFixed(0)}) ${j.toFixed(0)}x${q.toFixed(0)}, clicking checkbox at (${pe.toFixed(0)}, ${me.toFixed(0)})
579
- `),JSON.stringify({t:"xy",x:pe,y:me})}}let o=await it(i,t,n);if(o)return o}return null}async function ot(e,t,n=30000){let r=await pn(e,t);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)...
580
- `);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 i=await tt(e,t,r);if(i==="clicked"){await new Promise((a)=>setTimeout(a,2000));let o=Date.now()+n;while(Date.now()<o){let a=await t(["eval",e,fn]).catch(()=>null);if(a==="cleared"||!a||a==="null")return process.stderr.write(`[greedysearch] Verification cleared.
581
- `),"clicked";if(a!=="still-verifying")await tt(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.
582
- `),"needs-human"}if(i==="cant-click")return process.stderr.write(`[greedysearch] Verification challenge detected but cannot be auto-clicked — please solve it manually in the visible browser window.
583
- `),"needs-human";return"clear"}var at={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 S=at.gemini,te="__geminiClipboard";async function yn(e,t){await h(["click",e,S.input]),await new Promise((a)=>setTimeout(a,O(200)));let n=async()=>{await ne(["type",e,"--stdin"],t),await new Promise((a)=>setTimeout(a,O(300)))},r=async()=>{let a=await h(["eval",e,`(() => {
1
+ import {
2
+ cdp,
3
+ cdpWithInput,
4
+ clickCopyAndAwaitClipboard,
5
+ formatAnswer,
6
+ getOrOpenTab,
7
+ handleError,
8
+ injectClipboardInterceptor,
9
+ jitter,
10
+ outputJson,
11
+ parseArgs,
12
+ parseSourcesFromMarkdown,
13
+ prepareArgs,
14
+ TIMING,
15
+ validateQuery,
16
+ verifyInputText,
17
+ waitForSelector,
18
+ waitForStreamComplete
19
+ } from "./common.mjs";
20
+ import { ensureChrome } from "../src/search/chrome.mjs";
21
+ import { dismissConsent, handleVerification } from "./consent.mjs";
22
+ import { SELECTORS } from "./selectors.mjs";
23
+ const S = SELECTORS.gemini;
24
+ const GLOBAL_VAR = "__geminiClipboard";
25
+ async function typeIntoGemini(tab, text) {
26
+ await cdp(["click", tab, S.input]);
27
+ await new Promise((r) => setTimeout(r, jitter(200)));
28
+ const type = async () => {
29
+ await cdpWithInput(["type", tab, "--stdin"], text);
30
+ await new Promise((r) => setTimeout(r, jitter(300)));
31
+ };
32
+ const readInput = async () => {
33
+ const raw = await cdp([
34
+ "eval",
35
+ tab,
36
+ `(() => {
584
37
  const el = document.querySelector('${S.input}');
585
38
  return JSON.stringify(el ? el.innerText || el.textContent || '' : '');
586
- })()`]);try{return JSON.parse(a)}catch{return a}},i=async()=>ve(await r(),t),o=async()=>{await h(["eval",e,`(() => {
39
+ })()`
40
+ ]);
41
+ try {
42
+ return JSON.parse(raw);
43
+ } catch {
44
+ return raw;
45
+ }
46
+ };
47
+ const verify = async () => verifyInputText(await readInput(), text);
48
+ const clear = async () => {
49
+ await cdp([
50
+ "eval",
51
+ tab,
52
+ `(() => {
587
53
  const el = document.querySelector('${S.input}');
588
54
  if (!el) return false;
589
55
  el.focus();
@@ -594,10 +60,44 @@ ${l}`,"utf8");try{w(H)}catch{}Rt(t,H)}}catch{}finally{if(i)try{w(e)}catch{}}}asy
594
60
  selection.addRange(range);
595
61
  document.execCommand('delete');
596
62
  return true;
597
- })()`])};if(await n(),await i())return;if(await o(),await n(),!await i())throw Error("Gemini input field did not accept text — input verification failed")}async function he(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 vn(e){await h(["eval",e,`(function() {
63
+ })()`
64
+ ]);
65
+ };
66
+ await type();
67
+ if (await verify())
68
+ return;
69
+ await clear();
70
+ await type();
71
+ if (!await verify()) {
72
+ throw new Error("Gemini input field did not accept text — input verification failed");
73
+ }
74
+ }
75
+ async function bringToFront(tab, { required = false } = {}) {
76
+ try {
77
+ await cdp(["evalraw", tab, "Page.bringToFront", "{}"], 5000);
78
+ return true;
79
+ } catch (error) {
80
+ console.error(`[gemini] bringToFront failed: ${error.message}`);
81
+ if (required)
82
+ throw error;
83
+ return false;
84
+ }
85
+ }
86
+ async function scrollToBottom(tab) {
87
+ await cdp([
88
+ "eval",
89
+ tab,
90
+ `(function() {
598
91
  const chat = document.querySelector('chat-window, [role="main"], main') || document.body;
599
92
  chat.scrollTo ? chat.scrollTo({ top: chat.scrollHeight, behavior: 'smooth' }) : window.scrollTo(0, document.body.scrollHeight);
600
- })()`])}async function dn(e){let t=await h(["eval",e,String.raw`
93
+ })()`
94
+ ]);
95
+ }
96
+ async function extractAnswerFromDom(tab) {
97
+ const raw = await cdp([
98
+ "eval",
99
+ tab,
100
+ String.raw`
601
101
  new Promise((resolve) => {
602
102
  const _deadline = Date.now() + 6000;
603
103
  function _tryExtract() {
@@ -629,8 +129,17 @@ ${l}`,"utf8");try{w(H)}catch{}Rt(t,H)}}catch{}finally{if(i)try{w(e)}catch{}}}asy
629
129
  }
630
130
  _tryExtract();
631
131
  })
632
- `],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 lt=`(() => {
633
- window.${te} = '';
132
+ `
133
+ ], 8000);
134
+ try {
135
+ return JSON.parse(raw);
136
+ } catch (error) {
137
+ console.error(`[gemini] DOM fallback JSON parse failed (${raw.length} chars): ${error.message}`);
138
+ return { answer: "", sources: [] };
139
+ }
140
+ }
141
+ const GEMINI_COPY_CLICK_EXPR = `(() => {
142
+ window.${GLOBAL_VAR} = '';
634
143
  const responses = Array.from(document.querySelectorAll('model-response'));
635
144
  const resp = responses[responses.length - 1];
636
145
  if (!resp) return;
@@ -638,11 +147,28 @@ ${l}`,"utf8");try{w(H)}catch{}Rt(t,H)}}catch{}finally{if(i)try{w(e)}catch{}}}asy
638
147
  const nonCodeButtons = buttons.filter((btn) => !btn.closest('pre, code, code-block, .code-block, .code-container'));
639
148
  const btn = nonCodeButtons[nonCodeButtons.length - 1] || buttons[buttons.length - 1];
640
149
  if (btn) btn.click();
641
- })()`;async function bn(e,t="",n=!1){let r=t.toLowerCase().trim(),i=!1;if(n)i=await h(["eval",e,String.raw`(() => {
150
+ })()`;
151
+ async function extractAnswer(tab, query = "", streamWaitOk = false) {
152
+ const queryNorm = query.toLowerCase().trim();
153
+ let modelReady = false;
154
+ if (streamWaitOk) {
155
+ const ready = await cdp([
156
+ "eval",
157
+ tab,
158
+ String.raw`(() => {
642
159
  const responses = Array.from(document.querySelectorAll('model-response'));
643
160
  const r = responses[responses.length - 1];
644
161
  return !!r && (r.innerText || '').trim().length > 60;
645
- })()`]).catch(()=>"false")==="true";else{let c=Date.now()+12000;while(Date.now()<c){if(await h(["eval",e,String.raw`(() => {
162
+ })()`
163
+ ]).catch(() => "false");
164
+ modelReady = ready === "true";
165
+ } else {
166
+ const modelDeadline = Date.now() + 12000;
167
+ while (Date.now() < modelDeadline) {
168
+ const ready = await cdp([
169
+ "eval",
170
+ tab,
171
+ String.raw`(() => {
646
172
  const responses = Array.from(document.querySelectorAll('model-response'));
647
173
  const r = responses[responses.length - 1];
648
174
  if (!r) return false;
@@ -651,5 +177,115 @@ ${l}`,"utf8");try{w(H)}catch{}Rt(t,H)}}catch{}finally{if(i)try{w(e)}catch{}}}asy
651
177
  // ("Gemini said" / "Το Gemini είπε" / etc.) and ideally
652
178
  // a copy button rendered on the response.
653
179
  return t.length > 60;
654
- })()`])==="true"){i=!0;break}await new Promise((W)=>setTimeout(W,800))}}if(!i)console.error("[gemini] Warning: model-response did not render content");let o=await re(e,lt,te,{timeoutMs:600,retryClick:600});if(o&&r&&(o.toLowerCase().trim()===r||o.trim().length<r.length))console.error("[gemini] Clipboard echoed query, retrying in 2s..."),await new Promise((c)=>setTimeout(c,2000)),o=await re(e,lt,te,{timeoutMs:600,retryClick:600});let a=null,l=o?.trim()||"",u=r&&(l.toLowerCase()===r||l.length<r.length);if(!(l.length>500&&!u)){a=await dn(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=xe(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 wn=`Usage: node extractors/gemini.mjs "<query>" [--tab <prefix>]
655
- `;async function xn(){let e=await ke(process.argv.slice(2));Je(e,wn);let{query:t,tabPrefix:n,short:r}=Ne(e);if(process.env.GREEDY_SEARCH_VISIBLE!=="1"&&process.env.GREEDY_SEARCH_ALWAYS_VISIBLE!=="1")process.env.GREEDY_SEARCH_HEADLESS="1";await et();try{await h(["list"]);let i=await de(n),o=await h(["eval",i,"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",i,"https://gemini.google.com/app"],20000),await new Promise((c)=>setTimeout(c,600));await nt(i,h),await ot(i,h,1e4),await _e(i,S.input,8000,Q.inputPoll),await new Promise((c)=>setTimeout(c,O(Q.postClick))),await he(i,{required:!0}),await be(i,te),await yn(i,t),await new Promise((c)=>setTimeout(c,O(Q.postType))),await h(["eval",i,`document.querySelector('${S.sendButton}')?.click()`]),await he(i);let l=0,u=setInterval(()=>{if(he(i).catch(()=>null),++l%10===0)vn(i).catch(()=>null)},6000),f=!0;try{await $e(i,{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 bn(i,t,f);if(!s)throw Error("No answer captured from Gemini clipboard");let p=await h(["eval",i,"document.location.href"]).catch(()=>"https://gemini.google.com/app");je({query:t,url:p,answer:We(s,r),sources:g})}catch(i){Te(i)}}xn();
180
+ })()`
181
+ ]);
182
+ if (ready === "true") {
183
+ modelReady = true;
184
+ break;
185
+ }
186
+ await new Promise((r) => setTimeout(r, 800));
187
+ }
188
+ }
189
+ if (!modelReady) {
190
+ console.error("[gemini] Warning: model-response did not render content");
191
+ }
192
+ let answer = await clickCopyAndAwaitClipboard(tab, GEMINI_COPY_CLICK_EXPR, GLOBAL_VAR, { timeoutMs: 600, retryClick: 600 });
193
+ if (answer && queryNorm && (answer.toLowerCase().trim() === queryNorm || answer.trim().length < queryNorm.length)) {
194
+ console.error("[gemini] Clipboard echoed query, retrying in 2s...");
195
+ await new Promise((r) => setTimeout(r, 2000));
196
+ answer = await clickCopyAndAwaitClipboard(tab, GEMINI_COPY_CLICK_EXPR, GLOBAL_VAR, { timeoutMs: 600, retryClick: 600 });
197
+ }
198
+ let domFallback = null;
199
+ const answerText = answer?.trim() || "";
200
+ const clipboardLooksEchoed = queryNorm && (answerText.toLowerCase() === queryNorm || answerText.length < queryNorm.length);
201
+ const clipboardLooksComplete = answerText.length > 500 && !clipboardLooksEchoed;
202
+ if (!clipboardLooksComplete) {
203
+ domFallback = await extractAnswerFromDom(tab);
204
+ const domExtendsClipboard = answerText && domFallback.answer.includes(answerText) && domFallback.answer.length > answerText.length * 2;
205
+ if (domFallback.answer && (!answerText || clipboardLooksEchoed || domExtendsClipboard)) {
206
+ answer = domFallback.answer;
207
+ }
208
+ }
209
+ if (!answer) {
210
+ throw new Error("Gemini returned no answer — model-response never rendered content");
211
+ }
212
+ const sourcesInline = parseSourcesFromMarkdown(answer);
213
+ const sourceMap = new Map;
214
+ for (const s of [...domFallback?.sources || [], ...sourcesInline]) {
215
+ if (s?.url && !sourceMap.has(s.url))
216
+ sourceMap.set(s.url, s);
217
+ }
218
+ const sources = Array.from(sourceMap.values()).slice(0, 10);
219
+ return { answer: answer.trim(), sources };
220
+ }
221
+ const USAGE = `Usage: node extractors/gemini.mjs "<query>" [--tab <prefix>]
222
+ `;
223
+ async function main() {
224
+ const args = await prepareArgs(process.argv.slice(2));
225
+ validateQuery(args, USAGE);
226
+ const { query, tabPrefix, short } = parseArgs(args);
227
+ if (process.env.GREEDY_SEARCH_VISIBLE !== "1" && process.env.GREEDY_SEARCH_ALWAYS_VISIBLE !== "1") {
228
+ process.env.GREEDY_SEARCH_HEADLESS = "1";
229
+ }
230
+ await ensureChrome();
231
+ try {
232
+ await cdp(["list"]);
233
+ const tab = await getOrOpenTab(tabPrefix);
234
+ const currentUrl = await cdp(["eval", tab, "document.location.href"]).catch(() => "");
235
+ let onGemini = false;
236
+ try {
237
+ const host = new URL(currentUrl).hostname.toLowerCase();
238
+ onGemini = host === "gemini.google.com" || host.endsWith(".gemini.google.com");
239
+ } catch {}
240
+ if (!onGemini) {
241
+ await cdp(["nav", tab, "https://gemini.google.com/app"], 20000);
242
+ await new Promise((r) => setTimeout(r, 600));
243
+ }
244
+ await dismissConsent(tab, cdp);
245
+ await handleVerification(tab, cdp, 1e4);
246
+ await waitForSelector(tab, S.input, 8000, TIMING.inputPoll);
247
+ await new Promise((r) => setTimeout(r, jitter(TIMING.postClick)));
248
+ await bringToFront(tab, { required: true });
249
+ await injectClipboardInterceptor(tab, GLOBAL_VAR);
250
+ await typeIntoGemini(tab, query);
251
+ await new Promise((r) => setTimeout(r, jitter(TIMING.postType)));
252
+ await cdp([
253
+ "eval",
254
+ tab,
255
+ `document.querySelector('${S.sendButton}')?.click()`
256
+ ]);
257
+ await bringToFront(tab);
258
+ let pollTick = 0;
259
+ const scrollInterval = setInterval(() => {
260
+ bringToFront(tab).catch(() => null);
261
+ if (++pollTick % 10 === 0)
262
+ scrollToBottom(tab).catch(() => null);
263
+ }, 6000);
264
+ let streamWaitOk = true;
265
+ try {
266
+ await waitForStreamComplete(tab, {
267
+ timeout: 45000,
268
+ stableRounds: 5,
269
+ minLength: 60,
270
+ selector: "(() => { const responses = Array.from(document.querySelectorAll('model-response')); return responses[responses.length - 1]; })()"
271
+ });
272
+ } catch {
273
+ streamWaitOk = false;
274
+ } finally {
275
+ clearInterval(scrollInterval);
276
+ }
277
+ const { answer, sources } = await extractAnswer(tab, query, streamWaitOk);
278
+ if (!answer)
279
+ throw new Error("No answer captured from Gemini clipboard");
280
+ const finalUrl = await cdp(["eval", tab, "document.location.href"]).catch(() => "https://gemini.google.com/app");
281
+ outputJson({
282
+ query,
283
+ url: finalUrl,
284
+ answer: formatAnswer(answer, short),
285
+ sources
286
+ });
287
+ } catch (e) {
288
+ handleError(e);
289
+ }
290
+ }
291
+ main();