@duckmind/dm-windows-x64 0.60.6 → 0.60.8
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.exe +0 -0
- package/extensions/.dm-extensions.json +70 -123
- package/extensions/dm-9router-ext/src/index.js +410 -5
- package/extensions/dm-caveman/extensions/caveman.js +283 -12
- package/extensions/dm-cliproxy/index.js +182 -2
- package/extensions/dm-cliproxy/scripts/check-config-migration.js +66 -8
- package/extensions/dm-cliproxy/src/apply.js +228 -1
- package/extensions/dm-cliproxy/src/cache.js +42 -1
- package/extensions/dm-cliproxy/src/commands.js +50 -2
- package/extensions/dm-cliproxy/src/compat.js +81 -1
- package/extensions/dm-cliproxy/src/config.js +192 -2
- package/extensions/dm-cliproxy/src/conflicts.js +46 -1
- package/extensions/dm-cliproxy/src/fetch-models.js +190 -1
- package/extensions/dm-cliproxy/src/fetch-usage.js +41 -1
- package/extensions/dm-cliproxy/src/log.js +23 -1
- package/extensions/dm-cliproxy/src/status-quota.js +77 -1
- package/extensions/dm-cliproxy/src/ui-frame.js +50 -1
- package/extensions/dm-cliproxy/src/ui-hub/hub.js +199 -2
- package/extensions/dm-cliproxy/src/ui-hub/index.js +26 -2
- package/extensions/dm-cliproxy/src/ui-hub/shell.js +46 -1
- package/extensions/dm-cliproxy/src/ui-hub/view-diagnostics.js +69 -1
- package/extensions/dm-cliproxy/src/ui-hub/view-models.js +379 -1
- package/extensions/dm-cliproxy/src/ui-hub/view-usage.js +106 -1
- package/extensions/dm-cliproxy/src/ui-picker/catalog.js +41 -1
- package/extensions/dm-cliproxy/src/ui-picker/mutate.js +115 -1
- package/extensions/dm-cliproxy/src/ui-picker/prompt-confirm.js +35 -1
- package/extensions/dm-cliproxy/src/ui-picker/prompt-name.js +62 -1
- package/extensions/dm-cliproxy/src/ui-picker/providers.js +45 -1
- package/extensions/dm-cliproxy/src/ui-picker/render-text.js +34 -1
- package/extensions/dm-cliproxy/src/ui-picker/rows.js +57 -1
- package/extensions/dm-cliproxy/src/ui-setup.js +260 -2
- package/extensions/dm-cliproxy/src/ui-usage.js +151 -1
- package/extensions/dm-cliproxy/src/usage-shared-cache.js +97 -1
- package/extensions/dm-context/src/context.js +144 -1
- package/extensions/dm-context/src/index.js +339 -7
- package/extensions/dm-context/src/utils.js +9 -1
- package/extensions/dm-cua/bin/browser-cua.mjs +73 -8
- package/extensions/dm-cua/index.js +75 -6
- package/extensions/dm-cua/src/browser-cua-lib.mjs +490 -6
- package/extensions/dm-cua/src/browser-install.mjs +331 -2
- package/extensions/dm-fff/src/index.js +688 -12
- package/extensions/dm-fff/src/query.js +60 -1
- package/extensions/dm-goal/src/goal.js +894 -23
- package/extensions/dm-image2/index.js +103 -9
- package/extensions/dm-image2/src/image-lib.mjs +1275 -8
- package/extensions/dm-subagents/install.mjs +62 -8
- package/extensions/dm-subagents/src/agents/agent-management.js +1190 -36
- package/extensions/dm-subagents/src/agents/agent-memory.js +216 -6
- package/extensions/dm-subagents/src/agents/agent-scope.js +5 -1
- package/extensions/dm-subagents/src/agents/agent-selection.js +20 -1
- package/extensions/dm-subagents/src/agents/agent-serializer.js +120 -5
- package/extensions/dm-subagents/src/agents/agents.js +1139 -11
- package/extensions/dm-subagents/src/agents/chain-serializer.js +299 -11
- package/extensions/dm-subagents/src/agents/frontmatter.js +65 -6
- package/extensions/dm-subagents/src/agents/identity.js +29 -1
- package/extensions/dm-subagents/src/agents/proactive-skills.js +141 -1
- package/extensions/dm-subagents/src/agents/skills.js +614 -6
- package/extensions/dm-subagents/src/extension/config.js +35 -2
- package/extensions/dm-subagents/src/extension/control-notices.js +69 -4
- package/extensions/dm-subagents/src/extension/doctor.js +172 -15
- package/extensions/dm-subagents/src/extension/fanout-child.js +158 -231
- package/extensions/dm-subagents/src/extension/index.js +521 -359
- package/extensions/dm-subagents/src/extension/rpc.js +266 -7
- package/extensions/dm-subagents/src/extension/schemas.js +275 -1
- package/extensions/dm-subagents/src/extension/tool-description.js +111 -6
- package/extensions/dm-subagents/src/intercom/intercom-bridge.js +126 -4
- package/extensions/dm-subagents/src/intercom/native-supervisor-channel.js +452 -5
- package/extensions/dm-subagents/src/intercom/result-intercom.js +319 -3
- package/extensions/dm-subagents/src/profiles/profiles.js +458 -3
- package/extensions/dm-subagents/src/runs/background/async-execution.js +834 -40
- package/extensions/dm-subagents/src/runs/background/async-job-tracker.js +435 -14
- package/extensions/dm-subagents/src/runs/background/async-resume.js +334 -8
- package/extensions/dm-subagents/src/runs/background/async-status.js +313 -12
- package/extensions/dm-subagents/src/runs/background/chain-append.js +245 -2
- package/extensions/dm-subagents/src/runs/background/chain-root-attachment.js +136 -1
- package/extensions/dm-subagents/src/runs/background/completion-batcher.js +94 -1
- package/extensions/dm-subagents/src/runs/background/completion-dedupe.js +54 -1
- package/extensions/dm-subagents/src/runs/background/control-channel.js +190 -1
- package/extensions/dm-subagents/src/runs/background/fleet-view.js +483 -17
- package/extensions/dm-subagents/src/runs/background/notify.js +129 -3
- package/extensions/dm-subagents/src/runs/background/parallel-groups.js +34 -1
- package/extensions/dm-subagents/src/runs/background/result-watcher.js +236 -6
- package/extensions/dm-subagents/src/runs/background/run-id-resolver.js +76 -4
- package/extensions/dm-subagents/src/runs/background/run-status.js +427 -23
- package/extensions/dm-subagents/src/runs/background/scheduled-runs.js +487 -4
- package/extensions/dm-subagents/src/runs/background/stale-run-reconciler.js +306 -9
- package/extensions/dm-subagents/src/runs/background/subagent-runner.js +2849 -73
- package/extensions/dm-subagents/src/runs/background/top-level-async.js +5 -1
- package/extensions/dm-subagents/src/runs/background/wait.js +206 -11
- package/extensions/dm-subagents/src/runs/foreground/chain-clarify.js +1013 -12
- package/extensions/dm-subagents/src/runs/foreground/chain-execution.js +980 -101
- package/extensions/dm-subagents/src/runs/foreground/execution.js +1165 -45
- package/extensions/dm-subagents/src/runs/foreground/subagent-executor.js +3157 -222
- package/extensions/dm-subagents/src/runs/shared/acceptance.js +835 -3
- package/extensions/dm-subagents/src/runs/shared/chain-outputs.js +104 -1
- package/extensions/dm-subagents/src/runs/shared/completion-guard.js +116 -3
- package/extensions/dm-subagents/src/runs/shared/dm-args.js +208 -1
- package/extensions/dm-subagents/src/runs/shared/dm-spawn.js +90 -1
- package/extensions/dm-subagents/src/runs/shared/dynamic-fanout.js +282 -1
- package/extensions/dm-subagents/src/runs/shared/long-running-guard.js +148 -1
- package/extensions/dm-subagents/src/runs/shared/mcp-direct-tool-allowlist.js +305 -1
- package/extensions/dm-subagents/src/runs/shared/model-fallback.js +194 -1
- package/extensions/dm-subagents/src/runs/shared/model-scope.js +65 -1
- package/extensions/dm-subagents/src/runs/shared/nested-events.js +851 -8
- package/extensions/dm-subagents/src/runs/shared/nested-path.js +41 -1
- package/extensions/dm-subagents/src/runs/shared/nested-render.js +105 -1
- package/extensions/dm-subagents/src/runs/shared/parallel-utils.js +81 -4
- package/extensions/dm-subagents/src/runs/shared/run-history.js +51 -4
- package/extensions/dm-subagents/src/runs/shared/single-output.js +149 -8
- package/extensions/dm-subagents/src/runs/shared/structured-output.js +58 -1
- package/extensions/dm-subagents/src/runs/shared/subagent-control.js +166 -5
- package/extensions/dm-subagents/src/runs/shared/subagent-prompt-runtime.js +329 -13
- package/extensions/dm-subagents/src/runs/shared/tool-budget.js +73 -1
- package/extensions/dm-subagents/src/runs/shared/turn-budget.js +47 -4
- package/extensions/dm-subagents/src/runs/shared/workflow-graph.js +196 -1
- package/extensions/dm-subagents/src/runs/shared/worktree.js +435 -3
- package/extensions/dm-subagents/src/shared/artifacts.js +92 -2
- package/extensions/dm-subagents/src/shared/atomic-json.js +55 -1
- package/extensions/dm-subagents/src/shared/child-transcript.js +167 -5
- package/extensions/dm-subagents/src/shared/file-coalescer.js +25 -1
- package/extensions/dm-subagents/src/shared/fork-context.js +147 -4
- package/extensions/dm-subagents/src/shared/formatters.js +98 -7
- package/extensions/dm-subagents/src/shared/jsonl-writer.js +56 -2
- package/extensions/dm-subagents/src/shared/model-info.js +62 -1
- package/extensions/dm-subagents/src/shared/post-exit-stdio-guard.js +68 -1
- package/extensions/dm-subagents/src/shared/session-identity.js +6 -1
- package/extensions/dm-subagents/src/shared/session-tokens.js +39 -2
- package/extensions/dm-subagents/src/shared/settings.js +198 -11
- package/extensions/dm-subagents/src/shared/status-format.js +53 -1
- package/extensions/dm-subagents/src/shared/types.js +184 -6
- package/extensions/dm-subagents/src/shared/utils.js +462 -2
- package/extensions/dm-subagents/src/slash/prompt-template-bridge.js +288 -1
- package/extensions/dm-subagents/src/slash/prompt-workflows.js +297 -7
- package/extensions/dm-subagents/src/slash/slash-bridge.js +118 -1
- package/extensions/dm-subagents/src/slash/slash-commands.js +1287 -31
- package/extensions/dm-subagents/src/slash/slash-live-state.js +240 -4
- package/extensions/dm-subagents/src/tui/render-helpers.js +64 -1
- package/extensions/dm-subagents/src/tui/render.js +1542 -4
- package/extensions/dm-usage/index.js +1294 -9
- package/extensions/greedysearch-dm/bin/cdp-greedy.mjs +40 -9
- package/extensions/greedysearch-dm/bin/cdp-headless.mjs +5 -2
- package/extensions/greedysearch-dm/bin/cdp-visible.mjs +5 -2
- package/extensions/greedysearch-dm/bin/cdp.mjs +896 -30
- package/extensions/greedysearch-dm/bin/gschrome.mjs +30 -2
- package/extensions/greedysearch-dm/bin/kill-visible.mjs +7 -2
- package/extensions/greedysearch-dm/bin/launch-visible.mjs +13 -2
- package/extensions/greedysearch-dm/bin/launch.mjs +282 -10
- package/extensions/greedysearch-dm/bin/mcp.mjs +386 -361
- package/extensions/greedysearch-dm/bin/search.mjs +620 -540
- package/extensions/greedysearch-dm/bin/visible.mjs +22 -2
- package/extensions/greedysearch-dm/extractors/bing-copilot.mjs +329 -579
- package/extensions/greedysearch-dm/extractors/chatgpt.mjs +301 -583
- package/extensions/greedysearch-dm/extractors/common.mjs +408 -32
- package/extensions/greedysearch-dm/extractors/consensus.mjs +376 -365
- package/extensions/greedysearch-dm/extractors/consent.mjs +303 -14
- package/extensions/greedysearch-dm/extractors/gemini.mjs +228 -592
- package/extensions/greedysearch-dm/extractors/google-ai.mjs +78 -499
- package/extensions/greedysearch-dm/extractors/logically.mjs +270 -347
- package/extensions/greedysearch-dm/extractors/perplexity.mjs +243 -581
- package/extensions/greedysearch-dm/extractors/selectors.mjs +32 -1
- package/extensions/greedysearch-dm/extractors/semantic-scholar.mjs +130 -317
- package/extensions/greedysearch-dm/index.js +123 -23
- package/extensions/greedysearch-dm/src/fetcher.mjs +576 -2
- package/extensions/greedysearch-dm/src/formatters/results.js +95 -10
- package/extensions/greedysearch-dm/src/formatters/sources.js +57 -1
- package/extensions/greedysearch-dm/src/formatters/synthesis.js +49 -1
- package/extensions/greedysearch-dm/src/github.mjs +222 -7
- package/extensions/greedysearch-dm/src/reddit.mjs +145 -14
- package/extensions/greedysearch-dm/src/search/browser-lifecycle.mjs +340 -9
- package/extensions/greedysearch-dm/src/search/challenge-detect.mjs +112 -4
- package/extensions/greedysearch-dm/src/search/chrome.mjs +486 -285
- package/extensions/greedysearch-dm/src/search/constants.mjs +109 -8
- package/extensions/greedysearch-dm/src/search/defaults.mjs +10 -1
- package/extensions/greedysearch-dm/src/search/engines.mjs +79 -9
- package/extensions/greedysearch-dm/src/search/fetch-source.mjs +441 -349
- package/extensions/greedysearch-dm/src/search/file-sources.mjs +29 -7
- package/extensions/greedysearch-dm/src/search/minimize.mjs +86 -1
- package/extensions/greedysearch-dm/src/search/output.mjs +51 -5
- package/extensions/greedysearch-dm/src/search/paths.mjs +48 -1
- package/extensions/greedysearch-dm/src/search/pdf.mjs +63 -2
- package/extensions/greedysearch-dm/src/search/port-pid.mjs +69 -1
- package/extensions/greedysearch-dm/src/search/progress.mjs +109 -2
- package/extensions/greedysearch-dm/src/search/query.mjs +21 -1
- package/extensions/greedysearch-dm/src/search/recovery.mjs +49 -1
- package/extensions/greedysearch-dm/src/search/research.mjs +2227 -458
- package/extensions/greedysearch-dm/src/search/scale-aware.mjs +61 -11
- package/extensions/greedysearch-dm/src/search/simple-research.mjs +396 -805
- package/extensions/greedysearch-dm/src/search/sources.mjs +412 -1
- package/extensions/greedysearch-dm/src/search/synthesis-runner.mjs +127 -12
- package/extensions/greedysearch-dm/src/search/synthesis.mjs +202 -12
- package/extensions/greedysearch-dm/src/tools/greedy-search-handler.js +209 -23
- package/extensions/greedysearch-dm/src/tools/shared.js +226 -10
- package/extensions/greedysearch-dm/src/utils/content.mjs +35 -4
- package/extensions/greedysearch-dm/src/utils/helpers.js +22 -1
- package/extensions/greedysearch-dm/src/utils/node-runtime.mjs +10 -1
- package/extensions/greedysearch-dm/src/utils/system-cmds.mjs +61 -1
- package/package.json +1 -1
|
@@ -1,507 +1,86 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
Object.defineProperty(navigator, 'pdfViewerEnabled', { get: () => true, configurable: true });
|
|
25
|
-
Object.defineProperty(navigator, 'productSub', { get: () => '20030107', configurable: true });
|
|
26
|
-
Object.defineProperty(navigator, 'product', { get: () => 'Gecko', configurable: true });
|
|
27
|
-
var __greedyMimeTypes = null;
|
|
28
|
-
function __makeMimeTypes() {
|
|
29
|
-
var pdf = { type: 'application/pdf', suffixes: 'pdf', description: 'Portable Document Format', enabledPlugin: null };
|
|
30
|
-
var textPdf = { type: 'text/pdf', suffixes: 'pdf', description: 'Portable Document Format', enabledPlugin: null };
|
|
31
|
-
try { Object.setPrototypeOf(pdf, MimeType.prototype); } catch(_) {}
|
|
32
|
-
try { Object.setPrototypeOf(textPdf, MimeType.prototype); } catch(_) {}
|
|
33
|
-
var m = [pdf, textPdf];
|
|
34
|
-
try { Object.setPrototypeOf(m, MimeTypeArray.prototype); } catch(_) {}
|
|
35
|
-
m.item = function item(i) { return this[i] || null; };
|
|
36
|
-
m.namedItem = function namedItem(name) { return Array.prototype.find.call(this, function(x) { return x && x.type === name; }) || null; };
|
|
37
|
-
return m;
|
|
38
|
-
}
|
|
39
|
-
Object.defineProperty(navigator, 'plugins', {
|
|
40
|
-
get: () => {
|
|
41
|
-
__greedyMimeTypes = __greedyMimeTypes || __makeMimeTypes();
|
|
42
|
-
var plugin0 = { name: 'Chrome PDF Plugin', filename: 'internal-pdf-viewer', description: 'Portable Document Format' };
|
|
43
|
-
var plugin1 = { name: 'Chrome PDF Viewer', filename: 'mhjfbmdgcfjbbpaeojofohoefgiehjai', description: '' };
|
|
44
|
-
var plugin2 = { name: 'Native Client', filename: 'internal-nacl-plugin', description: '' };
|
|
45
|
-
try { Object.setPrototypeOf(plugin0, Plugin.prototype); } catch(_) {}
|
|
46
|
-
try { Object.setPrototypeOf(plugin1, Plugin.prototype); } catch(_) {}
|
|
47
|
-
try { Object.setPrototypeOf(plugin2, Plugin.prototype); } catch(_) {}
|
|
48
|
-
var p = [plugin0, plugin1, plugin2];
|
|
49
|
-
p.item = function item(i) { return this[i] || null; };
|
|
50
|
-
p.namedItem = function namedItem(name) { return Array.prototype.find.call(this, function(x) { return x && x.name === name; }) || null; };
|
|
51
|
-
p.refresh = function refresh() {};
|
|
52
|
-
try { Object.setPrototypeOf(p, PluginArray.prototype); } catch(_) {}
|
|
53
|
-
try {
|
|
54
|
-
__greedyMimeTypes[0].enabledPlugin = p[0];
|
|
55
|
-
__greedyMimeTypes[1].enabledPlugin = p[0];
|
|
56
|
-
} catch(_) {}
|
|
57
|
-
return p;
|
|
58
|
-
},
|
|
59
|
-
configurable: true,
|
|
60
|
-
});
|
|
61
|
-
Object.defineProperty(navigator, 'mimeTypes', {
|
|
62
|
-
get: () => {
|
|
63
|
-
__greedyMimeTypes = __greedyMimeTypes || __makeMimeTypes();
|
|
64
|
-
return __greedyMimeTypes;
|
|
65
|
-
},
|
|
66
|
-
configurable: true,
|
|
67
|
-
});
|
|
68
|
-
Object.defineProperty(navigator, 'languages', { get: () => ['en-US', 'en'], configurable: true });
|
|
69
|
-
try {
|
|
70
|
-
Object.defineProperty(navigator, 'connection', { get: () => ({ effectiveType: '4g', rtt: 50, downlink: 10, downlinkMax: Infinity, saveData: false }), configurable: true });
|
|
71
|
-
} catch(_) {}
|
|
72
|
-
if (!navigator.mediaDevices) {
|
|
73
|
-
Object.defineProperty(navigator, 'mediaDevices', {
|
|
74
|
-
get: () => ({
|
|
75
|
-
enumerateDevices: () => Promise.resolve([
|
|
76
|
-
{ deviceId: 'default', kind: 'audioinput', label: '', groupId: 'default' },
|
|
77
|
-
{ deviceId: 'default', kind: 'audiooutput', label: '', groupId: 'default' },
|
|
78
|
-
{ deviceId: '', kind: 'videoinput', label: '', groupId: '' },
|
|
79
|
-
]),
|
|
80
|
-
getUserMedia: () => Promise.reject(new DOMException('NotAllowedError')),
|
|
81
|
-
getDisplayMedia: () => Promise.reject(new DOMException('NotAllowedError')),
|
|
82
|
-
}),
|
|
83
|
-
configurable: true,
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
// ── Missing platform APIs (headless often lacks these) ─
|
|
87
|
-
try {
|
|
88
|
-
if (!navigator.share) {
|
|
89
|
-
navigator.share = function() { return Promise.reject(new Error('NotAllowedError')); };
|
|
90
|
-
}
|
|
91
|
-
} catch(_) {}
|
|
92
|
-
try {
|
|
93
|
-
if (!navigator.contentIndex) {
|
|
94
|
-
Object.defineProperty(navigator, 'contentIndex', { get: () => ({ add: function() {}, delete: function() {}, getAll: function() { return Promise.resolve([]); } }), configurable: true });
|
|
95
|
-
}
|
|
96
|
-
} catch(_) {}
|
|
97
|
-
|
|
98
|
-
if (!window.chrome) {
|
|
99
|
-
window.chrome = {
|
|
100
|
-
app: { isInstalled: false, InstallState: {}, RunningState: {} },
|
|
101
|
-
runtime: {
|
|
102
|
-
OnInstalledReason: {}, OnRestartRequiredReason: {}, PlatformArch: {}, PlatformNaclArch: {}, PlatformOs: {}, RequestUpdateCheckStatus: {},
|
|
103
|
-
connect: () => ({}), sendMessage: () => {}, onMessage: { addListener: () => {} }
|
|
104
|
-
},
|
|
105
|
-
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' }; },
|
|
106
|
-
csi: function() { var t = Date.now(); return { onloadT: t - 2000, startE: t - 5000, pageT: 'back', tran: 2 }; },
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
var __greedyNativeFns = [];
|
|
110
|
-
function __markNative(fn) { try { __greedyNativeFns.push(fn); } catch(_) {} return fn; }
|
|
111
|
-
|
|
112
|
-
var origQuery = navigator.permissions?.query;
|
|
113
|
-
if (origQuery) {
|
|
114
|
-
navigator.permissions.query = __markNative(function query(params) {
|
|
115
|
-
if (params && params.name === 'notifications') return Promise.resolve({ state: Notification.permission || 'default', onchange: null });
|
|
116
|
-
return origQuery.apply(this, arguments);
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
try {
|
|
120
|
-
var getParam = WebGLRenderingContext.prototype.getParameter;
|
|
121
|
-
WebGLRenderingContext.prototype.getParameter = __markNative(function getParameter(p) {
|
|
122
|
-
if (p === 37445) return 'Intel Inc.';
|
|
123
|
-
if (p === 37446) return 'Intel Iris OpenGL Engine';
|
|
124
|
-
return getParam.call(this, p);
|
|
125
|
-
});
|
|
126
|
-
} catch(_) {}
|
|
127
|
-
// ── WebGL readPixels noise ──────────────────────────
|
|
128
|
-
// CreepJS and other fingerprinters draw content with WebGL and read back the
|
|
129
|
-
// rendered pixels. Adding subtle noise breaks rendering-based fingerprinting.
|
|
130
|
-
try {
|
|
131
|
-
var origReadPixels = WebGLRenderingContext.prototype.readPixels;
|
|
132
|
-
WebGLRenderingContext.prototype.readPixels = __markNative(function readPixels(x, y, width, height, format, type, pixels) {
|
|
133
|
-
var result = origReadPixels.call(this, x, y, width, height, format, type, pixels);
|
|
134
|
-
if (pixels && pixels.length > 0) {
|
|
135
|
-
pixels[0] ^= 1;
|
|
136
|
-
}
|
|
137
|
-
return result;
|
|
138
|
-
});
|
|
139
|
-
} catch(_) {}
|
|
140
|
-
Object.defineProperty(navigator, 'hardwareConcurrency', { get: () => 8, configurable: true });
|
|
141
|
-
Object.defineProperty(navigator, 'deviceMemory', { get: () => 8, configurable: true });
|
|
142
|
-
|
|
143
|
-
// ── Canvas fingerprint noise ─────────────────────────
|
|
144
|
-
// Headless rendering engines produce slightly different canvas output
|
|
145
|
-
// than headed Chrome. Subtle noise breaks hash-based fingerprinting.
|
|
146
|
-
try {
|
|
147
|
-
var __canvasNoise = ((Date.now() & 0xFF) | 1);
|
|
148
|
-
var origFill = CanvasRenderingContext2D.prototype.fillText;
|
|
149
|
-
CanvasRenderingContext2D.prototype.fillText = __markNative(function fillText() {
|
|
150
|
-
this.globalAlpha = 0.9995;
|
|
151
|
-
return origFill.apply(this, arguments);
|
|
152
|
-
});
|
|
153
|
-
} catch(_) {}
|
|
154
|
-
try {
|
|
155
|
-
var origStroke = CanvasRenderingContext2D.prototype.strokeText;
|
|
156
|
-
CanvasRenderingContext2D.prototype.strokeText = __markNative(function strokeText() {
|
|
157
|
-
this.globalAlpha = 0.9995;
|
|
158
|
-
return origStroke.apply(this, arguments);
|
|
159
|
-
});
|
|
160
|
-
} catch(_) {}
|
|
161
|
-
try {
|
|
162
|
-
var origToDataURL = HTMLCanvasElement.prototype.toDataURL;
|
|
163
|
-
HTMLCanvasElement.prototype.toDataURL = __markNative(function toDataURL() {
|
|
164
|
-
var ctx = this.getContext('2d');
|
|
165
|
-
if (ctx) {
|
|
166
|
-
// Spread noise across canvas to break hash-based fingerprinting.
|
|
167
|
-
// Uses a deterministic pattern so it's consistent per page load
|
|
168
|
-
// but varies between sessions.
|
|
169
|
-
var w = this.width, h = this.height;
|
|
170
|
-
if (w > 0 && h > 0) {
|
|
171
|
-
var imgData = ctx.getImageData(0, 0, Math.min(w, 4), Math.min(h, 4));
|
|
172
|
-
if (imgData && imgData.data) {
|
|
173
|
-
for (var __i = 0; __i < imgData.data.length; __i += 4) {
|
|
174
|
-
imgData.data[__i] ^= (__canvasNoise + __i) & 0xFF;
|
|
175
|
-
}
|
|
176
|
-
ctx.putImageData(imgData, 0, 0);
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
return origToDataURL.apply(this, arguments);
|
|
181
|
-
});
|
|
182
|
-
} catch(_) {}
|
|
183
|
-
|
|
184
|
-
// ── AudioContext fingerprint noise ────────────────────
|
|
185
|
-
// Headless Chrome's AudioContext produces slightly different output.
|
|
186
|
-
// Subtle noise breaks audio-based fingerprinting.
|
|
187
|
-
try {
|
|
188
|
-
var __audioSeed = ((Date.now() & 0x1F) | 1);
|
|
189
|
-
var origGetChannelData = AudioBuffer.prototype.getChannelData;
|
|
190
|
-
AudioBuffer.prototype.getChannelData = __markNative(function getChannelData(channel) {
|
|
191
|
-
var data = origGetChannelData.call(this, channel);
|
|
192
|
-
for (var __i = 0; __i < data.length; __i += 64) {
|
|
193
|
-
data[__i] *= 0.99999;
|
|
194
|
-
}
|
|
195
|
-
return data;
|
|
196
|
-
});
|
|
197
|
-
} catch(_) {}
|
|
198
|
-
|
|
199
|
-
// ── window outer dimensions ──────────────────────────
|
|
200
|
-
// outerWidth/Height = 0 in headless — a well-known bot signal.
|
|
201
|
-
// Mirror innerWidth/Height (set by --window-size flag) so the ratio is sane.
|
|
202
|
-
try {
|
|
203
|
-
if (!window.outerWidth) Object.defineProperty(window, 'outerWidth', { get: () => window.innerWidth || 1920, configurable: true });
|
|
204
|
-
if (!window.outerHeight) Object.defineProperty(window, 'outerHeight', { get: () => window.innerHeight || 1080, configurable: true });
|
|
205
|
-
} catch(_) {}
|
|
206
|
-
|
|
207
|
-
// ── screen properties ─────────────────────────────────
|
|
208
|
-
// Headless Chrome often reports an 800x600 screen even when the viewport is
|
|
209
|
-
// 1920x1080. Keep screen metrics internally consistent with our launch flags.
|
|
210
|
-
try {
|
|
211
|
-
Object.defineProperty(screen, 'width', { get: () => 1920, configurable: true });
|
|
212
|
-
Object.defineProperty(screen, 'height', { get: () => 1080, configurable: true });
|
|
213
|
-
Object.defineProperty(screen, 'availWidth', { get: () => 1920, configurable: true });
|
|
214
|
-
Object.defineProperty(screen, 'availHeight', { get: () => 1040, configurable: true });
|
|
215
|
-
Object.defineProperty(screen, 'colorDepth', { get: () => 24, configurable: true });
|
|
216
|
-
Object.defineProperty(screen, 'pixelDepth', { get: () => 24, configurable: true });
|
|
217
|
-
} catch(_) {}
|
|
218
|
-
|
|
219
|
-
// ── navigator.userAgentData (UA Client Hints) ─────────
|
|
220
|
-
// Derive version from the UA string already set by --user-agent flag so the
|
|
221
|
-
// two APIs are always consistent. Removes any "HeadlessChrome" brand entry.
|
|
222
|
-
try {
|
|
223
|
-
var _uaMajor = (navigator.userAgent.match(new RegExp('Chrome/([0-9]+)')) || [])[1] || '136';
|
|
224
|
-
var _uaFull = (navigator.userAgent.match(new RegExp('Chrome/([0-9.]+)')) || [])[1] || (_uaMajor + '.0.0.0');
|
|
225
|
-
var _brands = [
|
|
226
|
-
{ brand: 'Not)A;Brand', version: '99' },
|
|
227
|
-
{ brand: 'Google Chrome', version: _uaMajor },
|
|
228
|
-
{ brand: 'Chromium', version: _uaMajor },
|
|
229
|
-
];
|
|
230
|
-
Object.defineProperty(navigator, 'userAgentData', {
|
|
231
|
-
get: function() {
|
|
232
|
-
return {
|
|
233
|
-
brands: _brands, mobile: false, platform: 'Windows',
|
|
234
|
-
getHighEntropyValues: function() {
|
|
235
|
-
return Promise.resolve({
|
|
236
|
-
architecture: 'x86', bitness: '64',
|
|
237
|
-
brands: _brands,
|
|
238
|
-
fullVersionList: [
|
|
239
|
-
{ brand: 'Not)A;Brand', version: '99.0.0.0' },
|
|
240
|
-
{ brand: 'Google Chrome', version: _uaFull },
|
|
241
|
-
{ brand: 'Chromium', version: _uaFull },
|
|
242
|
-
],
|
|
243
|
-
mobile: false, model: '', platform: 'Windows',
|
|
244
|
-
platformVersion: '15.0.0', uaFullVersion: _uaFull, wow64: false,
|
|
245
|
-
});
|
|
246
|
-
},
|
|
247
|
-
toJSON: function() { return { brands: _brands, mobile: false, platform: 'Windows' }; },
|
|
248
|
-
};
|
|
249
|
-
},
|
|
250
|
-
configurable: true,
|
|
251
|
-
});
|
|
252
|
-
} catch(_) {}
|
|
253
|
-
|
|
254
|
-
// ── CDP Runtime serialization guard ──────────────────
|
|
255
|
-
// Sites detect CDP by putting a getter on Error.prototype.stack
|
|
256
|
-
// and checking if console.log triggers it (only happens when
|
|
257
|
-
// Runtime domain is enabled). We monkey-patch console methods to
|
|
258
|
-
// strip custom getters from arguments before they reach CDP.
|
|
259
|
-
try {
|
|
260
|
-
var _origLog = console.log, _origError = console.error,
|
|
261
|
-
_origWarn = console.warn, _origDebug = console.debug,
|
|
262
|
-
_origInfo = console.info;
|
|
263
|
-
var _safeArg = function(a) {
|
|
264
|
-
if (a instanceof Error) {
|
|
265
|
-
try { return new Error(a.message); } catch(_) { return a; }
|
|
266
|
-
}
|
|
267
|
-
return a;
|
|
268
|
-
};
|
|
269
|
-
console.log = __markNative(function log() { return _origLog.apply(console, Array.prototype.map.call(arguments, _safeArg)); });
|
|
270
|
-
console.error = __markNative(function error() { return _origError.apply(console, Array.prototype.map.call(arguments, _safeArg)); });
|
|
271
|
-
console.warn = __markNative(function warn() { return _origWarn.apply(console, Array.prototype.map.call(arguments, _safeArg)); });
|
|
272
|
-
console.debug = __markNative(function debug() { return _origDebug.apply(console, Array.prototype.map.call(arguments, _safeArg)); });
|
|
273
|
-
console.info = __markNative(function info() { return _origInfo.apply(console, Array.prototype.map.call(arguments, _safeArg)); });
|
|
274
|
-
} catch(_) {}
|
|
275
|
-
|
|
276
|
-
// ── Native function masking ──────────────────────────
|
|
277
|
-
// Patched APIs should not stringify as user-defined stealth code.
|
|
278
|
-
try {
|
|
279
|
-
var __nativeToString = Function.prototype.toString;
|
|
280
|
-
Function.prototype.toString = function toString() {
|
|
281
|
-
if (__greedyNativeFns.indexOf(this) !== -1) {
|
|
282
|
-
var name = this.name || '';
|
|
283
|
-
return 'function ' + name + '() { [native code] }';
|
|
284
|
-
}
|
|
285
|
-
return __nativeToString.call(this);
|
|
286
|
-
};
|
|
287
|
-
} catch(_) {}
|
|
288
|
-
})();
|
|
289
|
-
`})])}var v={postNav:800,postNavSlow:1200,postClick:300,postType:300,inputPoll:400,copyPoll:600,afterVerify:1500};function _(e){let t=e*0.2,r=J(-Math.floor(t),Math.floor(t)+1);return Math.max(50,Math.round(e+r))}async function S(e,t={}){let{timeout:r=20000,interval:n=600,stableRounds:i=3,selector:o="document.body",minLength:a=0,isStreamingExpr:s="false"}=t,c=String.raw`
|
|
290
|
-
new Promise((resolve, reject) => {
|
|
291
|
-
const _deadline = Date.now() + ${r};
|
|
292
|
-
const _baseInterval = ${n};
|
|
293
|
-
const _stableRounds = ${i};
|
|
294
|
-
const _minLength = ${a};
|
|
295
|
-
let _lastLen = -1;
|
|
296
|
-
let _stableCount = 0;
|
|
297
|
-
|
|
298
|
-
function _jitter(ms) {
|
|
299
|
-
return Math.max(50, ms + (Math.random() * ms * 0.4 - ms * 0.2));
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
function _poll() {
|
|
303
|
-
try {
|
|
304
|
-
// Re-query DOM each tick — element may not exist at eval start
|
|
305
|
-
const el = ${o};
|
|
306
|
-
const cur = el?.textContent?.length ?? 0;
|
|
307
|
-
const streaming = ${s};
|
|
308
|
-
if (streaming) {
|
|
309
|
-
if (cur !== _lastLen) _lastLen = cur;
|
|
310
|
-
_stableCount = 0;
|
|
311
|
-
} else if (cur >= _minLength) {
|
|
312
|
-
if (cur === _lastLen) {
|
|
313
|
-
_stableCount++;
|
|
314
|
-
if (_stableCount >= _stableRounds) { resolve(cur); return; }
|
|
315
|
-
} else {
|
|
316
|
-
_lastLen = cur;
|
|
317
|
-
_stableCount = 0;
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
if (Date.now() < _deadline) {
|
|
321
|
-
setTimeout(_poll, _jitter(_baseInterval));
|
|
322
|
-
} else {
|
|
323
|
-
if (_lastLen >= _minLength && !streaming) { resolve(_lastLen); }
|
|
324
|
-
else { reject(new Error('Generation did not stabilise within ${r}ms')); }
|
|
325
|
-
}
|
|
326
|
-
} catch(e) { reject(e); }
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
_poll();
|
|
330
|
-
})
|
|
331
|
-
`,u=await m(["eval",e,c],r+1e4),l=parseInt(u,10)||0;if(l>=a)return l;throw Error(`Generation did not stabilise within ${r}ms`)}async function C(e){let t=e.indexOf("--stdin");if(t===-1)return e;let r=await new Promise((i)=>{let o="";process.stdin.setEncoding("utf8"),process.stdin.on("data",(a)=>o+=a),process.stdin.on("end",()=>i(o.trim()))}),n=[...e];return n[t]=r,n}function D(e){let t=e.includes("--short"),r=e.filter((s)=>s!=="--short"),n=r.indexOf("--tab"),i=n===-1?null:r[n+1];if(n!==-1)r=r.filter((s,c)=>c!==n&&c!==n+1);let o=r.indexOf("--locale"),a=o===-1?null:r[o+1];if(o!==-1)r=r.filter((s,c)=>c!==o&&c!==o+1);return{query:r.join(" "),tabPrefix:i,short:t,locale:a}}function N(e,t){if(!e.length||e[0]==="--help")process.stderr.write(t),process.exit(1)}function $(e,t,r=300){if(!t||e.length<=r)return e;let n=e.slice(0,r),i=n.lastIndexOf(" ");return i>0?`${n.slice(0,i)}…`:`${n}…`}function A(e){process.stdout.write(`${JSON.stringify(e,null,2)}
|
|
332
|
-
`)}function M(e,t=null){if(t){let r=JSON.stringify({_envelope:t,error:e.message});process.stdout.write(`${r}
|
|
333
|
-
`)}process.stderr.write(`Error: ${e.message}
|
|
334
|
-
`),process.exit(1)}import{randomInt as K}from"node:crypto";import{existsSync as ee,readFileSync as te}from"node:fs";import re from"node:http";var ne=`
|
|
335
|
-
(function() {
|
|
336
|
-
// Google consent page (consent.google.com)
|
|
337
|
-
var g = document.querySelector('#L2AGLb, button[jsname="b3VHJd"], .tHlp8d');
|
|
338
|
-
if (g) { g.click(); return 'google'; }
|
|
339
|
-
|
|
340
|
-
// OneTrust (used by many sites including Stack Overflow)
|
|
341
|
-
var ot = document.querySelector('#onetrust-accept-btn-handler, .onetrust-accept-btn-handler');
|
|
342
|
-
if (ot) { ot.click(); return 'onetrust'; }
|
|
343
|
-
|
|
344
|
-
// Generic "accept all" / "agree" buttons
|
|
345
|
-
var btns = Array.from(document.querySelectorAll('button, a[role=button]'));
|
|
346
|
-
var accept = btns.find(b => /^(accept all|accept cookies|agree|i agree|got it|allow all|allow cookies)$/i.test(b.innerText?.trim()));
|
|
347
|
-
if (accept) { accept.click(); return 'generic:' + accept.innerText.trim(); }
|
|
348
|
-
|
|
349
|
-
return null;
|
|
350
|
-
})()
|
|
351
|
-
`,ie=`
|
|
352
|
-
(function() {
|
|
353
|
-
var url = document.location.href;
|
|
354
|
-
|
|
355
|
-
// --- Google "sorry" page (hard CAPTCHA, can't auto-solve) ---
|
|
356
|
-
if (url.includes('/sorry/') || url.includes('sorry.google')) return 'sorry-page';
|
|
357
|
-
|
|
358
|
-
// --- Microsoft account verification page ---
|
|
359
|
-
if (url.includes('login.microsoftonline.com') || url.includes('login.live.com') || url.includes('account.microsoft.com')) {
|
|
360
|
-
var msBtns = Array.from(document.querySelectorAll('button, input[type=submit], a'));
|
|
361
|
-
var msVerify = msBtns.find(b => /verify|continue|next/i.test(b.innerText?.trim() || b.value || ''));
|
|
362
|
-
if (msVerify) { msVerify.setAttribute('data-gs-verify','1'); return JSON.stringify({t:'sel',s:'[data-gs-verify="1"]',txt:msVerify.innerText?.trim()||msVerify.value}); }
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
// --- Copilot / modal verification ---
|
|
366
|
-
var modal = document.querySelector('[role="dialog"], .b_modal, [class*="verify"], [class*="challenge"]');
|
|
367
|
-
if (modal) {
|
|
368
|
-
var modalBtns = Array.from(modal.querySelectorAll('button, a[role="button"], input[type="submit"]'));
|
|
369
|
-
var actionBtn = modalBtns.find(b => /^(continue|verify|submit|next|i agree|accept|got it)$/i.test(b.innerText?.trim() || b.value || ''));
|
|
370
|
-
if (actionBtn) { actionBtn.setAttribute('data-gs-verify','1'); return JSON.stringify({t:'sel',s:'[data-gs-verify="1"]',txt:actionBtn.innerText?.trim()}); }
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
// --- Turnstile / Cloudflare challenge iframe (return coordinates for humanClickXY) ---
|
|
374
|
-
var turnstileIframe = document.querySelector('iframe[src*="challenges.cloudflare.com"], iframe[src*="turnstile"], iframe[title*="challenge"]');
|
|
375
|
-
if (turnstileIframe) {
|
|
376
|
-
var r = turnstileIframe.getBoundingClientRect();
|
|
377
|
-
return JSON.stringify({t:'xy',x:r.left+30,y:r.top+r.height/2});
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
// --- Cloudflare Turnstile widget inside closed shadow DOM (Copilot, etc.) ---
|
|
381
|
-
// The iframe is not queryable from main document, but the host container
|
|
382
|
-
// (#cf-turnstile) and the hidden response input are. When only the
|
|
383
|
-
// hidden response input matches (no #cf-turnstile host and no visible
|
|
384
|
-
// iframe), the actual challenge widget is rendered inside a closed
|
|
385
|
-
// shadow DOM and cannot be auto-clicked. Return a sentinel so callers
|
|
386
|
-
// know to surface this as needs-human verification instead of wasting
|
|
387
|
-
// time on a doomed waitForSelector.
|
|
388
|
-
var cfTurnstileHost = document.querySelector('#cf-turnstile');
|
|
389
|
-
if (cfTurnstileHost) {
|
|
390
|
-
var r2 = cfTurnstileHost.getBoundingClientRect();
|
|
391
|
-
return JSON.stringify({t:'xy',x:r2.left+r2.width/2,y:r2.top+r2.height/2});
|
|
392
|
-
}
|
|
393
|
-
// Hidden cf-chl-widget-*_response input present but no visible host:
|
|
394
|
-
// the widget is in closed shadow DOM. Signal this so handleVerification
|
|
395
|
-
// can return 'needs-human' rather than 'clear'.
|
|
396
|
-
var cfResponseInput = document.querySelector('input[name="cf-turnstile-response"], [id^="cf-chl-widget-"][id$="_response"]');
|
|
397
|
-
if (cfResponseInput && cfResponseInput.value === '') {
|
|
398
|
-
return 'cf-closed-shadow-dom';
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
// --- Cloudflare challenge page ---
|
|
402
|
-
var cfCheckbox = document.querySelector('#cf-stage input[type="checkbox"], .ctp-checkbox-container input');
|
|
403
|
-
if (cfCheckbox) { cfCheckbox.setAttribute('data-gs-verify','1'); return JSON.stringify({t:'sel',s:'[data-gs-verify="1"]',txt:'cloudflare-checkbox'}); }
|
|
404
|
-
var cfBtn = document.querySelector('#challenge-form button, .cf-challenge button');
|
|
405
|
-
if (cfBtn) { cfBtn.setAttribute('data-gs-verify','1'); return JSON.stringify({t:'sel',s:'[data-gs-verify="1"]',txt:cfBtn.innerText?.trim()}); }
|
|
406
|
-
|
|
407
|
-
// --- Microsoft "I am human" button ---
|
|
408
|
-
var msHumanBtn = document.querySelector('button[id*="i0"], button[id*="id__"]');
|
|
409
|
-
if (msHumanBtn && /verify|human|robot|continue/i.test(msHumanBtn.innerText?.trim())) {
|
|
410
|
-
msHumanBtn.setAttribute('data-gs-verify','1'); return JSON.stringify({t:'sel',s:'[data-gs-verify="1"]',txt:msHumanBtn.innerText.trim()});
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
// --- Generic verify/continue/proceed buttons (catch-all) ---
|
|
414
|
-
// IMPORTANT: exclude sign-in / OAuth buttons (e.g. "Continue with Google",
|
|
415
|
-
// "Continue with email", "Login or sign up for free"). These appear on
|
|
416
|
-
// many sites (Perplexity, ChatGPT, etc.) when the user isn't logged in,
|
|
417
|
-
// and clicking them triggers a sign-in flow that takes us to a login
|
|
418
|
-
// wall — a much worse outcome than the original search failure we were
|
|
419
|
-
// trying to recover from. The exclusion list must cover both OAuth
|
|
420
|
-
// providers AND generic "sign in / log in / with email" patterns.
|
|
421
|
-
var btns = Array.from(document.querySelectorAll('button, input[type=submit], a[role=button]'));
|
|
422
|
-
var verify = btns.find(b => {
|
|
423
|
-
var t = (b.innerText?.trim() || b.value || '').toLowerCase();
|
|
424
|
-
var isVerifyLike = (t === 'continue' || t === 'proceed' || t === 'next' ||
|
|
425
|
-
t.startsWith('verify ') || t.startsWith('human ') || t === 'i am human' || t.includes('robot check')) &&
|
|
426
|
-
!t.includes('verified') && !document.querySelector('iframe[src*="recaptcha"]');
|
|
427
|
-
if (!isVerifyLike) return false;
|
|
428
|
-
// Exclude OAuth / sign-in buttons to prevent accidental login flows
|
|
429
|
-
// — covers "Continue with Google", "Continue with Apple", "Continue
|
|
430
|
-
// with email", "Login or sign up", "Log in", "Sign in", "Sign up",
|
|
431
|
-
// "Single sign-on", and the visible panel "Login or sign up for free"
|
|
432
|
-
// text. The previous list missed "email" and "sso" which let the
|
|
433
|
-
// auto-click land on the email/SSO sign-in buttons on Perplexity's
|
|
434
|
-
// anonymous-mode homepage, navigating us into a login flow.
|
|
435
|
-
var isSignIn = new RegExp("sign.?in|log.?in|sign.?up|with\\s+(google|apple|email|github|facebook|microsoft|sso)|sso|auth", "i").test(t);
|
|
436
|
-
return !isSignIn;
|
|
437
|
-
});
|
|
438
|
-
if (verify) { verify.setAttribute('data-gs-verify','1'); return JSON.stringify({t:'sel',s:'[data-gs-verify="1"]',txt:verify.innerText?.trim()||verify.value}); }
|
|
439
|
-
|
|
440
|
-
// --- Google reCAPTCHA checkbox ---
|
|
441
|
-
var recaptchaCheckbox = document.querySelector('.recaptcha-checkbox-unchecked, input[type=checkbox][id*="recaptcha"]');
|
|
442
|
-
if (recaptchaCheckbox) { recaptchaCheckbox.setAttribute('data-gs-verify','1'); return JSON.stringify({t:'sel',s:'[data-gs-verify="1"]',txt:'recaptcha'}); }
|
|
443
|
-
|
|
444
|
-
return null;
|
|
445
|
-
})()
|
|
446
|
-
`,ae=`
|
|
447
|
-
(function() {
|
|
448
|
-
var url = document.location.href;
|
|
449
|
-
var isVerifyPage = url.includes('/sorry/') ||
|
|
450
|
-
url.includes('challenges.cloudflare.com') ||
|
|
451
|
-
url.includes('login.microsoftonline.com') ||
|
|
452
|
-
document.querySelector('#challenge-running, #challenge-stage, .cf-turnstile, [role="dialog"]');
|
|
453
|
-
if (!isVerifyPage) return 'cleared';
|
|
454
|
-
|
|
455
|
-
var btns = Array.from(document.querySelectorAll('button, input[type=submit], a[role=button]'));
|
|
456
|
-
var btn = btns.find(b => {
|
|
457
|
-
var t = (b.innerText?.trim() || b.value || '').toLowerCase();
|
|
458
|
-
var isVerifyLike = t.includes('verify') || t.includes('human') || t.includes('robot') || t.includes('continue') || t.includes('next') || t.includes('submit');
|
|
459
|
-
if (!isVerifyLike) return false;
|
|
460
|
-
var isSignIn = /sign.in|log.in|google|microsoft|apple|facebook|github|auth/i.test(t);
|
|
461
|
-
return !isSignIn;
|
|
462
|
-
});
|
|
463
|
-
if (btn) { btn.setAttribute('data-gs-verify','1'); return JSON.stringify({t:'sel',s:'[data-gs-verify="1"]',txt:btn.innerText?.trim()||btn.value}); }
|
|
464
|
-
|
|
465
|
-
var cf = document.querySelector('#cf-stage input[type="checkbox"], .cf-turnstile input');
|
|
466
|
-
if (cf) { cf.setAttribute('data-gs-verify','1'); return JSON.stringify({t:'sel',s:'[data-gs-verify="1"]',txt:'turnstile'}); }
|
|
467
|
-
|
|
468
|
-
// Cloudflare Turnstile widget inside closed shadow DOM (detected via host container)
|
|
469
|
-
var cfTurnstileHost = document.querySelector('#cf-turnstile, [id^="cf-chl-widget-"]');
|
|
470
|
-
if (cfTurnstileHost) { return 'still-verifying'; }
|
|
471
|
-
|
|
472
|
-
var modal = document.querySelector('[role="dialog"], .b_modal, [class*="verify"]');
|
|
473
|
-
if (modal) {
|
|
474
|
-
var modalBtn = modal.querySelector('button, a[role="button"]');
|
|
475
|
-
if (modalBtn) { modalBtn.setAttribute('data-gs-verify','1'); return JSON.stringify({t:'sel',s:'[data-gs-verify="1"]',txt:modalBtn.innerText?.trim()}); }
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
return 'still-verifying';
|
|
479
|
-
})()
|
|
480
|
-
`;async function I(e,t){let r=await t(["eval",e,ne]).catch(()=>null);if(r&&r!=="null")await new Promise((n)=>setTimeout(n,1500))}function p(e,t){return K(e*1000,t*1000)/1000}async function oe(e,t){if(!globalThis.WebSocket)return;let r=process.env.CDP_PROFILE_DIR;if(!r)return;let n=`${r.replaceAll("\\","/")}/DevToolsActivePort`;if(!ee(n))return;let i=te(n,"utf8").trim().split(`
|
|
481
|
-
`)[0],o=await new Promise((c,u)=>{let l=re.get(`http://localhost:${i}/json/version`,(f)=>{let g="";f.on("data",(d)=>g+=d),f.on("end",()=>{try{c(JSON.parse(g))}catch{u(Error("bad JSON"))}})});l.on("error",u),l.setTimeout(1000,()=>{l.destroy(),u(Error("timeout"))})}),a=new globalThis.WebSocket(o.webSocketDebuggerUrl),s=0;await new Promise((c)=>{a.onopen=async()=>{let u=(g,d)=>new Promise((x)=>{let b=++s,h=(y)=>{if(JSON.parse(y.data).id===b)a.removeEventListener("message",h),x()};a.addEventListener("message",h),a.send(JSON.stringify({id:b,method:g,params:d}))}),l=e+p(-2,2),f=t+p(-2,2);await u("Input.dispatchMouseEvent",{type:"mouseMoved",x:l,y:f,button:"none"}),await new Promise((g)=>setTimeout(g,p(80,160))),await u("Input.dispatchMouseEvent",{type:"mousePressed",x:l,y:f,button:"left",clickCount:1}),await new Promise((g)=>setTimeout(g,p(30,80))),await u("Input.dispatchMouseEvent",{type:"mouseReleased",x:l+p(-1,1),y:f+p(-1,1),button:"left",clickCount:1}),setTimeout(()=>{a.close(),c()},200)},a.onerror=()=>c(),setTimeout(c,3000)})}async function R(e,t,r,n){let i=Number.parseFloat(r),o=Number.parseFloat(n);if(Number.isNaN(i)||Number.isNaN(o))throw Error(`humanClickXY: invalid coordinates (${r}, ${n})`);let a={button:"left",clickCount:1,modifiers:0},s=i+p(-3,3),c=o+p(-3,3);await t(["evalraw",e,"Input.dispatchMouseEvent",JSON.stringify({...a,type:"mouseMoved",x:s,y:c})]),await new Promise((d)=>setTimeout(d,p(80,180)));let u=i+p(-2,2),l=o+p(-2,2);await t(["evalraw",e,"Input.dispatchMouseEvent",JSON.stringify({...a,type:"mousePressed",x:u,y:l})]),await new Promise((d)=>setTimeout(d,p(30,90)));let f=u+p(-1,1),g=l+p(-1,1);return await t(["evalraw",e,"Input.dispatchMouseEvent",JSON.stringify({...a,type:"mouseReleased",x:f,y:g})]),await oe(i,o).catch(()=>{}),await new Promise((d)=>setTimeout(d,p(100,300))),`human-clicked at (${i.toFixed(0)}, ${o.toFixed(0)})`}async function le(e,t,r){let n=await t(["eval",e,`(function() {
|
|
482
|
-
var el = document.querySelector('${r.replace(/\\/g,"\\\\").replace(/'/g,"\\'")}');
|
|
483
|
-
if (!el) return 'null';
|
|
484
|
-
var r = el.getBoundingClientRect();
|
|
485
|
-
return JSON.stringify({x: r.left + r.width / 2, y: r.top + r.height / 2, w: r.width, h: r.height});
|
|
486
|
-
})()`]).catch(()=>"null");if(!n||n==="null")return null;let i=JSON.parse(n);if(i.w===0||i.h===0||i.x===0&&i.y===0)return null;let{x:o,y:a}=i;return R(e,t,o,a)}function E(e,t,r){if(!r||r==="null"||r==="cleared"||r==="still-verifying"||r==="cf-closed-shadow-dom")return Promise.resolve("no-challenge");try{let n=JSON.parse(r);if(n.t==="sel"&&n.s)return process.stderr.write(`[greedysearch] Human-clicking "${n.txt}" via CDP...
|
|
487
|
-
`),le(e,t,n.s).then((i)=>i!==null?"clicked":"cant-click");if(n.t==="xy"){if(!n.x&&!n.y)return Promise.resolve("cant-click");return process.stderr.write(`[greedysearch] Human-clicking at (${n.x.toFixed(0)}, ${n.y.toFixed(0)})...
|
|
488
|
-
`),R(e,t,n.x,n.y).then(()=>"clicked")}}catch{}return Promise.resolve("no-challenge")}async function se(e,t){let r=await t(["eval",e,ie]).catch(()=>null);if(r==="cf-closed-shadow-dom"){let n=await ce(e,t).catch(()=>null);if(n)return n;return r}if(r&&r!=="null")return r;return null}async function ce(e,t){if(typeof t!=="function")return null;await t(["evalraw",e,"DOM.enable","{}"]).catch(()=>{});let r=await t(["evalraw",e,"DOM.getDocument",JSON.stringify({depth:-1,pierce:!0})]).catch(()=>null);if(!r)return null;let n;try{n=JSON.parse(r)}catch{return null}if(n.error||!n.root)return null;let i=n.root;return await j(i,e,t)}async function j(e,t,r){if(!e)return null;let n=[];if(e.shadowRoots&&e.shadowRoots.length>0)for(let i of e.shadowRoots)n.push(i);if(e.children)for(let i of e.children)n.push(i);for(let i of n){if(i.nodeName==="IFRAME"){let a=i.attributes||[],s=a.indexOf("src"),c=s>=0?a[s+1]:"";if(c&&/challenges\.cloudflare\.com|turnstile/i.test(c)&&i.backendNodeId){let u=await r(["evalraw",t,"DOM.getBoxModel",JSON.stringify({backendNodeId:i.backendNodeId})]).catch(()=>null);if(!u)continue;let l;try{l=JSON.parse(u)}catch{continue}let f=l?.model?.content||l?.result?.model?.content;if(!f||f.length<8)continue;let g=f[0],d=f[1],x=f[4],b=f[5],h=x-g,y=b-d;if(h<50||y<20)continue;let k=g+h*0.25,P=d+y*0.5;return process.stderr.write(`[greedysearch] Found CF iframe via CDP pierce at (${g.toFixed(0)}, ${d.toFixed(0)}) ${h.toFixed(0)}x${y.toFixed(0)}, clicking checkbox at (${k.toFixed(0)}, ${P.toFixed(0)})
|
|
489
|
-
`),JSON.stringify({t:"xy",x:k,y:P})}}let o=await j(i,t,r);if(o)return o}return null}async function L(e,t,r=30000){let n=await se(e,t);if(!n)return"clear";if(n==="sorry-page"){process.stderr.write(`[greedysearch] Google CAPTCHA detected — please solve it in the browser window (waiting up to ${Math.floor(r/1000)}s)...
|
|
490
|
-
`);let o=Date.now()+r;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 E(e,t,n);if(i==="clicked"){await new Promise((a)=>setTimeout(a,2000));let o=Date.now()+r;while(Date.now()<o){let a=await t(["eval",e,ae]).catch(()=>null);if(a==="cleared"||!a||a==="null")return process.stderr.write(`[greedysearch] Verification cleared.
|
|
491
|
-
`),"clicked";if(a!=="still-verifying")await E(e,t,a),await new Promise((s)=>setTimeout(s,2000));else await new Promise((s)=>setTimeout(s,1500))}return process.stderr.write(`[greedysearch] Verification may require manual intervention.
|
|
492
|
-
`),"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.
|
|
493
|
-
`),"needs-human";return"clear"}var F={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 w=F.google,ue=50;async function de(e){let t=w.sourceExclude.map((n)=>`!a.href.includes('${n}')`).join(" && "),r=await m(["eval",e,String.raw`
|
|
1
|
+
import {
|
|
2
|
+
cdp,
|
|
3
|
+
formatAnswer,
|
|
4
|
+
getOrOpenTab,
|
|
5
|
+
handleError,
|
|
6
|
+
jitter,
|
|
7
|
+
outputJson,
|
|
8
|
+
parseArgs,
|
|
9
|
+
prepareArgs,
|
|
10
|
+
TIMING,
|
|
11
|
+
validateQuery,
|
|
12
|
+
waitForStreamComplete
|
|
13
|
+
} from "./common.mjs";
|
|
14
|
+
import { dismissConsent, handleVerification } from "./consent.mjs";
|
|
15
|
+
import { SELECTORS } from "./selectors.mjs";
|
|
16
|
+
const S = SELECTORS.google;
|
|
17
|
+
const MIN_ANSWER_LENGTH = 50;
|
|
18
|
+
async function extractAnswer(tab) {
|
|
19
|
+
const excludeFilter = S.sourceExclude.map((e) => `!a.href.includes('${e}')`).join(" && ");
|
|
20
|
+
const raw = await cdp([
|
|
21
|
+
"eval",
|
|
22
|
+
tab,
|
|
23
|
+
String.raw`
|
|
494
24
|
(function() {
|
|
495
|
-
var el = document.querySelector('${
|
|
25
|
+
var el = document.querySelector('${S.answerContainer}');
|
|
496
26
|
if (!el) return JSON.stringify({ answer: '', sources: [] });
|
|
497
27
|
var answer = el.innerText.trim();
|
|
498
|
-
var sources = Array.from(document.querySelectorAll('${
|
|
499
|
-
.filter(a => ${
|
|
500
|
-
.map(a => ({ url: a.href.split('#')[0], title: (a.closest('${
|
|
28
|
+
var sources = Array.from(document.querySelectorAll('${S.sourceLink}'))
|
|
29
|
+
.filter(a => ${excludeFilter})
|
|
30
|
+
.map(a => ({ url: a.href.split('#')[0], title: (a.closest('${S.sourceHeadingParent}')?.querySelector('h3, [role=heading]')?.innerText || a.innerText?.trim().split('\n')[0] || '').slice(0, 100) }))
|
|
501
31
|
.filter(s => s.url && s.url.length > 10)
|
|
502
32
|
.filter((v, i, arr) => arr.findIndex(x => x.url === v.url) === i)
|
|
503
33
|
.slice(0, 10);
|
|
504
34
|
return JSON.stringify({ answer, sources });
|
|
505
35
|
})()
|
|
506
|
-
`
|
|
507
|
-
|
|
36
|
+
`
|
|
37
|
+
]);
|
|
38
|
+
return JSON.parse(raw);
|
|
39
|
+
}
|
|
40
|
+
const USAGE = `Usage: node extractors/google-ai.mjs "<query>" [--tab <prefix>]
|
|
41
|
+
`;
|
|
42
|
+
async function main() {
|
|
43
|
+
const args = await prepareArgs(process.argv.slice(2));
|
|
44
|
+
validateQuery(args, USAGE);
|
|
45
|
+
const { query, tabPrefix, short, locale } = parseArgs(args);
|
|
46
|
+
try {
|
|
47
|
+
if (!tabPrefix)
|
|
48
|
+
await cdp(["list"]);
|
|
49
|
+
const tab = await getOrOpenTab(tabPrefix);
|
|
50
|
+
const langParam = locale ? `&hl=${encodeURIComponent(locale)}` : "&hl=en";
|
|
51
|
+
const url = `https://www.google.com/search?q=${encodeURIComponent(query)}&udm=50${langParam}`;
|
|
52
|
+
await new Promise((r) => setTimeout(r, jitter(TIMING.postNav)));
|
|
53
|
+
await dismissConsent(tab, cdp);
|
|
54
|
+
const currentUrl = await cdp(["eval", tab, "document.location.href"]).catch(() => "");
|
|
55
|
+
if (!currentUrl.includes("google.com/search")) {
|
|
56
|
+
await cdp(["nav", tab, url], 20000);
|
|
57
|
+
await new Promise((r) => setTimeout(r, jitter(TIMING.postNav)));
|
|
58
|
+
}
|
|
59
|
+
const verifyResult = await handleVerification(tab, cdp, 1e4);
|
|
60
|
+
if (verifyResult === "needs-human")
|
|
61
|
+
throw new Error("Google verification required — could not be completed automatically");
|
|
62
|
+
if (verifyResult === "clicked" || verifyResult === "cleared-by-user") {
|
|
63
|
+
await cdp(["nav", tab, url], 20000);
|
|
64
|
+
await new Promise((r) => setTimeout(r, jitter(TIMING.postNav)));
|
|
65
|
+
}
|
|
66
|
+
await waitForStreamComplete(tab, {
|
|
67
|
+
timeout: 30000,
|
|
68
|
+
stableRounds: 5,
|
|
69
|
+
selector: `document.querySelector('${S.answerContainer}')`,
|
|
70
|
+
minLength: MIN_ANSWER_LENGTH
|
|
71
|
+
});
|
|
72
|
+
const { answer, sources } = await extractAnswer(tab);
|
|
73
|
+
if (!answer)
|
|
74
|
+
throw new Error("No answer extracted — Google AI Mode may not have responded");
|
|
75
|
+
const finalUrl = await cdp(["eval", tab, "document.location.href"]).catch(() => url);
|
|
76
|
+
outputJson({
|
|
77
|
+
query,
|
|
78
|
+
url: finalUrl,
|
|
79
|
+
answer: formatAnswer(answer, short),
|
|
80
|
+
sources
|
|
81
|
+
});
|
|
82
|
+
} catch (e) {
|
|
83
|
+
handleError(e);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
main();
|