@duckmind/dm-darwin-arm64 0.52.3 → 0.53.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dm +0 -0
- package/extensions/.dm-extensions.json +15 -8
- package/extensions/dm-cua/bin/browser-cua.mjs +6 -6
- package/extensions/dm-cua/index.js +5 -5
- package/extensions/dm-cua/src/browser-cua-lib.mjs +2 -2
- package/extensions/greedysearch-dm/bin/cdp-greedy.mjs +8 -1
- package/extensions/greedysearch-dm/bin/cdp-headless.mjs +1 -1
- package/extensions/greedysearch-dm/bin/cdp-visible.mjs +1 -1
- package/extensions/greedysearch-dm/bin/cdp.mjs +29 -20
- package/extensions/greedysearch-dm/bin/gschrome.mjs +1 -10
- package/extensions/greedysearch-dm/bin/kill-visible.mjs +1 -1
- package/extensions/greedysearch-dm/bin/launch-visible.mjs +1 -4
- package/extensions/greedysearch-dm/bin/launch.mjs +9 -5
- package/extensions/greedysearch-dm/bin/mcp.mjs +375 -0
- package/extensions/greedysearch-dm/bin/search.mjs +310 -156
- package/extensions/greedysearch-dm/bin/visible.mjs +1 -1
- package/extensions/greedysearch-dm/extractors/bing-copilot.mjs +205 -68
- package/extensions/greedysearch-dm/extractors/chatgpt.mjs +229 -140
- package/extensions/greedysearch-dm/extractors/common.mjs +160 -50
- package/extensions/greedysearch-dm/extractors/consensus.mjs +225 -92
- package/extensions/greedysearch-dm/extractors/consent.mjs +44 -17
- package/extensions/greedysearch-dm/extractors/gemini.mjs +275 -136
- package/extensions/greedysearch-dm/extractors/google-ai.mjs +172 -64
- package/extensions/greedysearch-dm/extractors/logically.mjs +183 -69
- package/extensions/greedysearch-dm/extractors/perplexity.mjs +331 -65
- package/extensions/greedysearch-dm/extractors/semantic-scholar.mjs +118 -41
- package/extensions/greedysearch-dm/index.js +20 -17
- package/extensions/greedysearch-dm/package.json +8 -3
- package/extensions/greedysearch-dm/skills/greedy-search/skill.md +8 -8
- package/extensions/greedysearch-dm/src/fetcher.mjs +2 -2
- package/extensions/greedysearch-dm/src/formatters/results.js +8 -6
- package/extensions/greedysearch-dm/src/github.mjs +7 -7
- package/extensions/greedysearch-dm/src/reddit.mjs +1 -1
- package/extensions/greedysearch-dm/src/search/browser-lifecycle.mjs +10 -9
- package/extensions/greedysearch-dm/src/search/challenge-detect.mjs +48 -0
- package/extensions/greedysearch-dm/src/search/chrome.mjs +129 -53
- package/extensions/greedysearch-dm/src/search/constants.mjs +8 -8
- package/extensions/greedysearch-dm/src/search/engines.mjs +9 -9
- package/extensions/greedysearch-dm/src/search/fetch-source.mjs +154 -77
- package/extensions/greedysearch-dm/src/search/minimize.mjs +1 -0
- package/extensions/greedysearch-dm/src/search/paths.mjs +1 -1
- package/extensions/greedysearch-dm/src/search/pdf.mjs +1 -1
- package/extensions/greedysearch-dm/src/search/port-pid.mjs +1 -0
- package/extensions/greedysearch-dm/src/search/progress.mjs +2 -0
- package/extensions/greedysearch-dm/src/search/recovery.mjs +1 -1
- package/extensions/greedysearch-dm/src/search/research.mjs +262 -167
- package/extensions/greedysearch-dm/src/search/scale-aware.mjs +11 -0
- package/extensions/greedysearch-dm/src/search/simple-research.mjs +827 -0
- package/extensions/greedysearch-dm/src/search/synthesis-runner.mjs +11 -11
- package/extensions/greedysearch-dm/src/search/synthesis.mjs +11 -11
- package/extensions/greedysearch-dm/src/tools/greedy-search-handler.js +23 -20
- package/extensions/greedysearch-dm/src/tools/shared.js +10 -9
- package/extensions/greedysearch-dm/src/utils/node-runtime.mjs +1 -1
- package/package.json +1 -1
- package/extensions/greedysearch-dm/src/search/cdp-endpoint.mjs +0 -3
- package/extensions/greedysearch-dm/src/utils/browser-executable.mjs +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{randomInt as
|
|
1
|
+
import{randomInt as Y}from"node:crypto";import{existsSync as j,readFileSync as P}from"node:fs";import I from"node:http";var C=`
|
|
2
2
|
(function() {
|
|
3
3
|
// Google consent page (consent.google.com)
|
|
4
4
|
var g = document.querySelector('#L2AGLb, button[jsname="b3VHJd"], .tHlp8d');
|
|
@@ -15,7 +15,7 @@ import{randomInt as T}from"node:crypto";import{existsSync as Y,readFileSync as _
|
|
|
15
15
|
|
|
16
16
|
return null;
|
|
17
17
|
})()
|
|
18
|
-
`,
|
|
18
|
+
`,v=`
|
|
19
19
|
(function() {
|
|
20
20
|
var url = document.location.href;
|
|
21
21
|
|
|
@@ -46,12 +46,24 @@ import{randomInt as T}from"node:crypto";import{existsSync as Y,readFileSync as _
|
|
|
46
46
|
|
|
47
47
|
// --- Cloudflare Turnstile widget inside closed shadow DOM (Copilot, etc.) ---
|
|
48
48
|
// The iframe is not queryable from main document, but the host container
|
|
49
|
-
// (#cf-turnstile) and the hidden response input are.
|
|
50
|
-
|
|
49
|
+
// (#cf-turnstile) and the hidden response input are. When only the
|
|
50
|
+
// hidden response input matches (no #cf-turnstile host and no visible
|
|
51
|
+
// iframe), the actual challenge widget is rendered inside a closed
|
|
52
|
+
// shadow DOM and cannot be auto-clicked. Return a sentinel so callers
|
|
53
|
+
// know to surface this as needs-human verification instead of wasting
|
|
54
|
+
// time on a doomed waitForSelector.
|
|
55
|
+
var cfTurnstileHost = document.querySelector('#cf-turnstile');
|
|
51
56
|
if (cfTurnstileHost) {
|
|
52
57
|
var r2 = cfTurnstileHost.getBoundingClientRect();
|
|
53
58
|
return JSON.stringify({t:'xy',x:r2.left+r2.width/2,y:r2.top+r2.height/2});
|
|
54
59
|
}
|
|
60
|
+
// Hidden cf-chl-widget-*_response input present but no visible host:
|
|
61
|
+
// the widget is in closed shadow DOM. Signal this so handleVerification
|
|
62
|
+
// can return 'needs-human' rather than 'clear'.
|
|
63
|
+
var cfResponseInput = document.querySelector('input[name="cf-turnstile-response"], [id^="cf-chl-widget-"][id$="_response"]');
|
|
64
|
+
if (cfResponseInput && cfResponseInput.value === '') {
|
|
65
|
+
return 'cf-closed-shadow-dom';
|
|
66
|
+
}
|
|
55
67
|
|
|
56
68
|
// --- Cloudflare challenge page ---
|
|
57
69
|
var cfCheckbox = document.querySelector('#cf-stage input[type="checkbox"], .ctp-checkbox-container input');
|
|
@@ -66,15 +78,28 @@ import{randomInt as T}from"node:crypto";import{existsSync as Y,readFileSync as _
|
|
|
66
78
|
}
|
|
67
79
|
|
|
68
80
|
// --- Generic verify/continue/proceed buttons (catch-all) ---
|
|
69
|
-
// IMPORTANT: exclude sign-in / OAuth buttons (e.g. "Continue with Google"
|
|
81
|
+
// IMPORTANT: exclude sign-in / OAuth buttons (e.g. "Continue with Google",
|
|
82
|
+
// "Continue with email", "Login or sign up for free"). These appear on
|
|
83
|
+
// many sites (Perplexity, ChatGPT, etc.) when the user isn't logged in,
|
|
84
|
+
// and clicking them triggers a sign-in flow that takes us to a login
|
|
85
|
+
// wall — a much worse outcome than the original search failure we were
|
|
86
|
+
// trying to recover from. The exclusion list must cover both OAuth
|
|
87
|
+
// providers AND generic "sign in / log in / with email" patterns.
|
|
70
88
|
var btns = Array.from(document.querySelectorAll('button, input[type=submit], a[role=button]'));
|
|
71
89
|
var verify = btns.find(b => {
|
|
72
90
|
var t = (b.innerText?.trim() || b.value || '').toLowerCase();
|
|
73
|
-
var isVerifyLike = (t
|
|
91
|
+
var isVerifyLike = (t === 'continue' || t === 'proceed' || t === 'next' ||
|
|
92
|
+
t.startsWith('verify ') || t.startsWith('human ') || t === 'i am human' || t.includes('robot check')) &&
|
|
74
93
|
!t.includes('verified') && !document.querySelector('iframe[src*="recaptcha"]');
|
|
75
94
|
if (!isVerifyLike) return false;
|
|
76
95
|
// Exclude OAuth / sign-in buttons to prevent accidental login flows
|
|
77
|
-
|
|
96
|
+
// — covers "Continue with Google", "Continue with Apple", "Continue
|
|
97
|
+
// with email", "Login or sign up", "Log in", "Sign in", "Sign up",
|
|
98
|
+
// "Single sign-on", and the visible panel "Login or sign up for free"
|
|
99
|
+
// text. The previous list missed "email" and "sso" which let the
|
|
100
|
+
// auto-click land on the email/SSO sign-in buttons on Perplexity's
|
|
101
|
+
// anonymous-mode homepage, navigating us into a login flow.
|
|
102
|
+
var isSignIn = new RegExp("sign.?in|log.?in|sign.?up|with\\s+(google|apple|email|github|facebook|microsoft|sso)|sso|auth", "i").test(t);
|
|
78
103
|
return !isSignIn;
|
|
79
104
|
});
|
|
80
105
|
if (verify) { verify.setAttribute('data-gs-verify','1'); return JSON.stringify({t:'sel',s:'[data-gs-verify="1"]',txt:verify.innerText?.trim()||verify.value}); }
|
|
@@ -85,7 +110,7 @@ import{randomInt as T}from"node:crypto";import{existsSync as Y,readFileSync as _
|
|
|
85
110
|
|
|
86
111
|
return null;
|
|
87
112
|
})()
|
|
88
|
-
`,
|
|
113
|
+
`,k=`
|
|
89
114
|
(function() {
|
|
90
115
|
var url = document.location.href;
|
|
91
116
|
var isVerifyPage = url.includes('/sorry/') ||
|
|
@@ -119,15 +144,17 @@ import{randomInt as T}from"node:crypto";import{existsSync as Y,readFileSync as _
|
|
|
119
144
|
|
|
120
145
|
return 'still-verifying';
|
|
121
146
|
})()
|
|
122
|
-
`;async function
|
|
123
|
-
`)[0],U=await new Promise((
|
|
124
|
-
var el = document.querySelector('${
|
|
147
|
+
`;async function y(A,G){let B=await G(["eval",A,C]).catch(()=>null);if(B&&B!=="null")await new Promise((z)=>setTimeout(z,1500))}function Z(A,G){return Y(A*1000,G*1000)/1000}async function F(A,G){if(!globalThis.WebSocket)return;let B=process.env.CDP_PROFILE_DIR;if(!B)return;let z=`${B.replaceAll("\\","/")}/DevToolsActivePort`;if(!j(z))return;let K=P(z,"utf8").trim().split(`
|
|
148
|
+
`)[0],U=await new Promise((q,O)=>{let $=I.get(`http://localhost:${K}/json/version`,(W)=>{let L="";W.on("data",(H)=>L+=H),W.on("end",()=>{try{q(JSON.parse(L))}catch{O(Error("bad JSON"))}})});$.on("error",O),$.setTimeout(1000,()=>{$.destroy(),O(Error("timeout"))})}),Q=new globalThis.WebSocket(U.webSocketDebuggerUrl),N=0;await new Promise((q)=>{Q.onopen=async()=>{let O=(L,H)=>new Promise((V)=>{let T=++N,D=(J)=>{if(JSON.parse(J.data).id===T)Q.removeEventListener("message",D),V()};Q.addEventListener("message",D),Q.send(JSON.stringify({id:T,method:L,params:H}))}),$=A+Z(-2,2),W=G+Z(-2,2);await O("Input.dispatchMouseEvent",{type:"mouseMoved",x:$,y:W,button:"none"}),await new Promise((L)=>setTimeout(L,Z(80,160))),await O("Input.dispatchMouseEvent",{type:"mousePressed",x:$,y:W,button:"left",clickCount:1}),await new Promise((L)=>setTimeout(L,Z(30,80))),await O("Input.dispatchMouseEvent",{type:"mouseReleased",x:$+Z(-1,1),y:W+Z(-1,1),button:"left",clickCount:1}),setTimeout(()=>{Q.close(),q()},200)},Q.onerror=()=>q(),setTimeout(q,3000)})}async function S(A,G,B,z){let K=Number.parseFloat(B),U=Number.parseFloat(z);if(Number.isNaN(K)||Number.isNaN(U))throw Error(`humanClickXY: invalid coordinates (${B}, ${z})`);let Q={button:"left",clickCount:1,modifiers:0},N=K+Z(-3,3),q=U+Z(-3,3);await G(["evalraw",A,"Input.dispatchMouseEvent",JSON.stringify({...Q,type:"mouseMoved",x:N,y:q})]),await new Promise((H)=>setTimeout(H,Z(80,180)));let O=K+Z(-2,2),$=U+Z(-2,2);await G(["evalraw",A,"Input.dispatchMouseEvent",JSON.stringify({...Q,type:"mousePressed",x:O,y:$})]),await new Promise((H)=>setTimeout(H,Z(30,90)));let W=O+Z(-1,1),L=$+Z(-1,1);return await G(["evalraw",A,"Input.dispatchMouseEvent",JSON.stringify({...Q,type:"mouseReleased",x:W,y:L})]),await F(K,U).catch(()=>{}),await new Promise((H)=>setTimeout(H,Z(100,300))),`human-clicked at (${K.toFixed(0)}, ${U.toFixed(0)})`}async function w(A,G,B){let z=await G(["eval",A,`(function() {
|
|
149
|
+
var el = document.querySelector('${B.replace(/\\/g,"\\\\").replace(/'/g,"\\'")}');
|
|
125
150
|
if (!el) return 'null';
|
|
126
151
|
var r = el.getBoundingClientRect();
|
|
127
152
|
return JSON.stringify({x: r.left + r.width / 2, y: r.top + r.height / 2, w: r.width, h: r.height});
|
|
128
|
-
})()`]).catch(()=>"null");if(!z||z==="null")return null;let
|
|
129
|
-
`),
|
|
130
|
-
`),
|
|
131
|
-
`)
|
|
132
|
-
`),"
|
|
133
|
-
`),"
|
|
153
|
+
})()`]).catch(()=>"null");if(!z||z==="null")return null;let K=JSON.parse(z);if(K.w===0||K.h===0||K.x===0&&K.y===0)return null;let{x:U,y:Q}=K;return S(A,G,U,Q)}function M(A,G,B){if(!B||B==="null"||B==="cleared"||B==="still-verifying"||B==="cf-closed-shadow-dom")return Promise.resolve("no-challenge");try{let z=JSON.parse(B);if(z.t==="sel"&&z.s)return process.stderr.write(`[greedysearch] Human-clicking "${z.txt}" via CDP...
|
|
154
|
+
`),w(A,G,z.s).then((K)=>K!==null?"clicked":"cant-click");if(z.t==="xy"){if(!z.x&&!z.y)return Promise.resolve("cant-click");return process.stderr.write(`[greedysearch] Human-clicking at (${z.x.toFixed(0)}, ${z.y.toFixed(0)})...
|
|
155
|
+
`),S(A,G,z.x,z.y).then(()=>"clicked")}}catch{}return Promise.resolve("no-challenge")}async function g(A,G){let B=await G(["eval",A,v]).catch(()=>null);if(B==="cf-closed-shadow-dom"){let z=await m(A,G).catch(()=>null);if(z)return z;return B}if(B&&B!=="null")return B;return null}async function m(A,G){if(typeof G!=="function")return null;await G(["evalraw",A,"DOM.enable","{}"]).catch(()=>{});let B=await G(["evalraw",A,"DOM.getDocument",JSON.stringify({depth:-1,pierce:!0})]).catch(()=>null);if(!B)return null;let z;try{z=JSON.parse(B)}catch{return null}if(z.error||!z.root)return null;let K=z.root;return await E(K,A,G)}async function E(A,G,B){if(!A)return null;let z=[];if(A.shadowRoots&&A.shadowRoots.length>0)for(let K of A.shadowRoots)z.push(K);if(A.children)for(let K of A.children)z.push(K);for(let K of z){if(K.nodeName==="IFRAME"){let Q=K.attributes||[],N=Q.indexOf("src"),q=N>=0?Q[N+1]:"";if(q&&/challenges\.cloudflare\.com|turnstile/i.test(q)&&K.backendNodeId){let O=await B(["evalraw",G,"DOM.getBoxModel",JSON.stringify({backendNodeId:K.backendNodeId})]).catch(()=>null);if(!O)continue;let $;try{$=JSON.parse(O)}catch{continue}let W=$?.model?.content||$?.result?.model?.content;if(!W||W.length<8)continue;let L=W[0],H=W[1],V=W[4],T=W[5],D=V-L,J=T-H;if(D<50||J<20)continue;let X=L+D*0.25,_=H+J*0.5;return process.stderr.write(`[greedysearch] Found CF iframe via CDP pierce at (${L.toFixed(0)}, ${H.toFixed(0)}) ${D.toFixed(0)}x${J.toFixed(0)}, clicking checkbox at (${X.toFixed(0)}, ${_.toFixed(0)})
|
|
156
|
+
`),JSON.stringify({t:"xy",x:X,y:_})}}let U=await E(K,G,B);if(U)return U}return null}async function u(A,G,B=30000){let z=await g(A,G);if(!z)return"clear";if(z==="sorry-page"){process.stderr.write(`[greedysearch] Google CAPTCHA detected — please solve it in the browser window (waiting up to ${Math.floor(B/1000)}s)...
|
|
157
|
+
`);let U=Date.now()+B;while(Date.now()<U)if(await new Promise((N)=>setTimeout(N,2000)),!(await G(["eval",A,"document.location.href"]).catch(()=>"")).includes("/sorry/"))return"cleared-by-user";return"needs-human"}let K=await M(A,G,z);if(K==="clicked"){await new Promise((Q)=>setTimeout(Q,2000));let U=Date.now()+B;while(Date.now()<U){let Q=await G(["eval",A,k]).catch(()=>null);if(Q==="cleared"||!Q||Q==="null")return process.stderr.write(`[greedysearch] Verification cleared.
|
|
158
|
+
`),"clicked";if(Q!=="still-verifying")await M(A,G,Q),await new Promise((N)=>setTimeout(N,2000));else await new Promise((N)=>setTimeout(N,1500))}return process.stderr.write(`[greedysearch] Verification may require manual intervention.
|
|
159
|
+
`),"needs-human"}if(K==="cant-click")return process.stderr.write(`[greedysearch] Verification challenge detected but cannot be auto-clicked — please solve it manually in the visible browser window.
|
|
160
|
+
`),"needs-human";return"clear"}export{S as humanClickXY,w as humanClickElement,u as handleVerification,y as dismissConsent,g as detectVerificationChallenge};
|