@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,335 +1,41 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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 tt={postNav:800,postNavSlow:1200,postClick:300,postType:300,inputPoll:400,copyPoll:600,afterVerify:1500};function U(t){let e=t*0.2,n=Gt(-Math.floor(e),Math.floor(e)+1);return Math.max(50,Math.round(t+n))}async function bt(t,e,n=15000,i=500){let r=String.raw`
|
|
290
|
-
new Promise((resolve) => {
|
|
291
|
-
const _deadline = Date.now() + ${n};
|
|
292
|
-
const _baseInterval = ${i};
|
|
293
|
-
|
|
294
|
-
function _jitter(ms) {
|
|
295
|
-
return Math.max(50, ms + (Math.random() * ms * 0.4 - ms * 0.2));
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
function _poll() {
|
|
299
|
-
try {
|
|
300
|
-
if (document.querySelector('${e}')) { resolve(true); return; }
|
|
301
|
-
if (Date.now() < _deadline) { setTimeout(_poll, _jitter(_baseInterval)); }
|
|
302
|
-
else { resolve(false); }
|
|
303
|
-
} catch(_) { resolve(false); }
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
_poll();
|
|
307
|
-
})
|
|
308
|
-
`;return await s(["eval",t,r],n+5000)==="true"}async function yt(t){let e=t.indexOf("--stdin");if(e===-1)return t;let n=await new Promise((r)=>{let o="";process.stdin.setEncoding("utf8"),process.stdin.on("data",(l)=>o+=l),process.stdin.on("end",()=>r(o.trim()))}),i=[...t];return i[e]=n,i}function wt(t){let e=t.includes("--short"),n=t.filter((u)=>u!=="--short"),i=n.indexOf("--tab"),r=i===-1?null:n[i+1];if(i!==-1)n=n.filter((u,a)=>a!==i&&a!==i+1);let o=n.indexOf("--locale"),l=o===-1?null:n[o+1];if(o!==-1)n=n.filter((u,a)=>a!==o&&a!==o+1);return{query:n.join(" "),tabPrefix:r,short:e,locale:l}}function mt(t,e){if(!t.length||t[0]==="--help")process.stderr.write(e),process.exit(1)}function vt(t,e,n=300){if(!e||t.length<=n)return t;let i=t.slice(0,n),r=i.lastIndexOf(" ");return r>0?`${i.slice(0,r)}…`:`${i}…`}function xt(t){process.stdout.write(`${JSON.stringify(t,null,2)}
|
|
309
|
-
`)}function b(t,e,n=null){if(!t||typeof t!=="object")return;let i=n?` (+${Date.now()-n}ms)`:"";if(t.lastStage=e,!Array.isArray(t.stages))t.stages=[];t.stages.push({stage:e,at:Date.now()});let r=t.engine||"extractor";console.error(`[${r}] stage: ${e}${i}`)}function et({engine:t,mode:e="headless",clipboardEmpty:n=null,fallbackUsed:i=null,blockedBy:r=null,verificationResult:o=null,inputReady:l=null,durationMs:u=null,lastStage:a=null,stages:f=null}={}){return{engine:t,mode:e,clipboardEmpty:n,fallbackUsed:i,blockedBy:r,verificationResult:o,inputReady:l,durationMs:u,lastStage:a,stages:f}}function _t(t,e=null){if(e){let n=JSON.stringify({_envelope:e,error:t.message});process.stdout.write(`${n}
|
|
310
|
-
`)}process.stderr.write(`Error: ${t.message}
|
|
311
|
-
`),process.exit(1)}import{readFileSync as Ye}from"node:fs";import{tmpdir as Ke}from"node:os";import{spawn as de,execFileSync as at,execSync as Yn}from"node:child_process";import{basename as le}from"node:path";function $t(t=process.env,e=process.execPath){let n=t.GREEDY_SEARCH_NODE||t.NODE_BINARY||t.NODE;if(n?.trim())return n.trim();let i=le(e||"").toLowerCase();if(i==="node"||i==="node.exe")return e;return"node"}import{existsSync as Dt,readFileSync as st,renameSync as He,unlinkSync as v,writeFileSync as G}from"node:fs";import ft from"node:http";import{platform as Tt}from"node:os";import{existsSync as Wt}from"node:fs";import{platform as ue}from"node:os";import{join as W}from"node:path";function w(t){let e=ue()==="win32",n=process.env.SystemRoot||"C:\\Windows",i={win32:{powershell:W(n,"System32","WindowsPowerShell","v1.0","powershell.exe"),powershell_ise:W(n,"System32","WindowsPowerShell","v1.0","powershell_ise.exe"),netstat:W(n,"System32","netstat.exe"),taskkill:W(n,"System32","taskkill.exe"),tasklist:W(n,"System32","tasklist.exe"),cmd:W(n,"System32","cmd.exe")},unix:{ps:"/usr/bin/ps",lsof:"/usr/bin/lsof",ss:"/usr/sbin/ss",grep:"/usr/bin/grep",kill:"/usr/bin/kill"}},r=e?i.win32:i.unix,o=t.toLowerCase();if(r[o]&&Wt(r[o]))return r[o];if(e&&o==="netstat"){let l=W(n,"Sysnative","netstat.exe");if(Wt(l))return l}return t}import{execFileSync as ae}from"node:child_process";import{platform as se}from"node:os";function fe(t,e){return ae(w(t),e,{encoding:"utf8",stdio:["ignore","pipe","ignore"],timeout:5000})}function ce(t){let e=String(t||"").match(/\b(\d+)\b/);return e?Number.parseInt(e[1],10):null}function ge(t){return ce(t)}function pe(t,e){for(let n of String(t||"").split(/\r?\n/)){if(!/\bLISTEN\b/i.test(n))continue;if(!n.trim().split(/\s+/).slice(0,6).some((o)=>o.endsWith(`:${e}`)))continue;let r=n.match(/\bpid=(\d+)\b/);if(r)return Number.parseInt(r[1],10)}return null}function he(t,e){for(let n of String(t||"").split(/\r?\n/)){let i=n.trim().split(/\s+/);if(i.length<5||i[0].toUpperCase()!=="TCP")continue;if(!i.at(-2)?.toUpperCase().startsWith("LISTEN"))continue;if(!i[1].endsWith(`:${e}`))continue;let r=Number.parseInt(i.at(-1),10);if(Number.isInteger(r)&&r>0)return r}return null}function nt(t,e,n){try{return t(e,n)}catch{return null}}function M(t,{platformName:e=se(),run:n=fe}={}){if(e==="win32")return he(nt(n,"netstat",["-ano","-p","TCP"]),t);let i=nt(n,"lsof",["-nP",`-iTCP:${t}`,"-sTCP:LISTEN","-t"]),r=ge(i);if(r)return r;if(e!=="linux")return null;return pe(nt(n,"ss",["-ltnp"]),t)}import{existsSync as jt}from"node:fs";import{dirname as be,join as Z}from"node:path";import{fileURLToPath as ye}from"node:url";function kt(t){return ye(new URL(".",t)).replace(/^\/([A-Z]:)/,"$1")}function we(t,e=jt){let n=new Set;for(let i of t.filter(Boolean)){if(n.has(i))continue;if(n.add(i),e(i))return i}return t.filter(Boolean).at(-1)}function Jt({moduleDir:t,entrypoint:e=process.argv[1],env:n=process.env,exists:i=jt}={}){let r=e?be(e):null,o=n.GREEDY_SEARCH_EXTENSION_DIR?.trim()||null;return we([t?Z(t,"..","..","bin","launch.mjs"):null,t?Z(t,"launch.mjs"):null,o?Z(o,"bin","launch.mjs"):null,r?Z(r,"launch.mjs"):null,r?Z(r,"..","bin","launch.mjs"):null],i)}import{existsSync as z,mkdirSync as me,readFileSync as Xt,writeFileSync as ve}from"node:fs";import{homedir as xe}from"node:os";import{join as Zt}from"node:path";import{tmpdir as _e}from"node:os";function $e(t,e=9222){let n=Number.parseInt(String(t??""),10);return Number.isInteger(n)&&n>1024&&n<65535?n:e}var We=_e().replaceAll("\\","/"),g=$e(process.env.GREEDY_SEARCH_PORT),p=(process.env.GREEDY_SEARCH_PROFILE_DIR||process.env.CDP_PROFILE_DIR||`${We}/greedysearch-chrome-profile`).replaceAll("\\","/"),q=`${p}/DevToolsActivePort`,A=process.env.GREEDY_SEARCH_PID_FILE||`${p}/browser.pid`,je=process.env.CDP_PAGES_CACHE||`${p}/cdp-pages.json`,$=process.env.GREEDY_SEARCH_MODE_FILE||`${p}/browser-mode`,qt=process.env.GREEDY_SEARCH_METADATA_FILE||`${p}/browser-metadata.json`,Bt=process.env.GREEDY_SEARCH_LAUNCH_LOCK_FILE||`${p}/browser-launch.lock`,O=process.env.GREEDY_SEARCH_ACTIVITY_FILE||`${p}/browser-last-activity`,Zn=(process.env.CDP_SOCKET_DIR||`${p}/cdp-sockets`).replaceAll("\\","/"),qn=`${p}/visible-recovery.jsonl`,it=Zt(xe(),".dm"),m=Zt(it,"greedyconfig"),ot=["perplexity","google","chatgpt","gemini"],lt="gemini";function ke(){try{if(z(m)){let t=Xt(m,"utf8"),e=JSON.parse(t);if(Array.isArray(e.engines)&&e.engines.length>0&&e.engines.every((n)=>typeof n==="string")){let n=e.engines.filter((r)=>rt[r]),i=e.engines.filter((r)=>!rt[r]);if(i.length>0)process.stderr.write(`[greedysearch] Warning: ignoring unknown engine(s) in ${m}: ${i.join(", ")}
|
|
312
|
-
[greedysearch] Available engines: ${Object.keys(rt).join(", ")}
|
|
313
|
-
`);if(n.length>0)return n;process.stderr.write(`[greedysearch] Warning: no valid engines in ${m}, falling back to defaults: ${ot.join(", ")}
|
|
314
|
-
`)}}}catch{}return ot}function Je(){try{if(!z(it))me(it,{recursive:!0});if(!z(m))ve(m,JSON.stringify({engines:ot,synthesizer:lt},null,2)+`
|
|
315
|
-
`,"utf8")}catch{}}Je();var Nt=["gemini","chatgpt"];function Ne(){try{if(z(m)){let t=Xt(m,"utf8"),e=JSON.parse(t);if(typeof e.synthesizer==="string"){let n=e.synthesizer.toLowerCase();if(Nt.includes(n))return n;process.stderr.write(`[greedysearch] Warning: unknown synthesizer "${e.synthesizer}" in ${m}
|
|
316
|
-
[greedysearch] Available synthesizers: ${Nt.join(", ")}
|
|
317
|
-
[greedysearch] Falling back to default: ${lt}
|
|
318
|
-
`)}}}catch{}return lt}var rt={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"},Bn=ke();var Qn=Ne(),Vn=Math.max(1,Number.parseInt(process.env.GREEDY_FETCH_CONCURRENCY||"5",10)||5);process.env.CDP_PROFILE_DIR=p;import{execFileSync as Qt,execSync as Un}from"node:child_process";import{existsSync as D,mkdirSync as Xe,readFileSync as N,unlinkSync as k,writeFileSync as J}from"node:fs";import{platform as Ze}from"node:os";var T=qt,j=Bt,qe=15000,P=A,C=$,B=O;function Q(t){if(!Number.isInteger(t)||t<=0)return!1;try{return process.kill(t,0),!0}catch{return!1}}function Be(t){if(!Q(t))return null;try{if(Ze()==="win32")return Qt(w("powershell"),["-NoProfile","-NonInteractive","-Command",`(Get-CimInstance Win32_Process -Filter "ProcessId = ${t}").CommandLine`],{encoding:"utf8",windowsHide:!0,timeout:5000}).trim()||null;return Qt(w("ps"),["-p",String(t),"-o","command="],{encoding:"utf8",timeout:5000}).trim()||null}catch{return null}}function Qe(t,e,n=g){if(!t)return!1;let i=(l)=>String(l||"").replaceAll("\\","/").toLowerCase(),r=i(t),o=i(e);return r.includes(o)&&r.includes(`--remote-debugging-port=${n}`)&&!r.includes("--type=")}function Vt(t,e,n=g){return Qe(Be(t),e,n)}function Ve(t=g){return M(t)}function V(){try{if(D(T)){let t=N(T,"utf8"),e=JSON.parse(t);if(e&&typeof e.tempDir==="string"&&typeof e.debugPort==="number")return{browserPid:Number.isInteger(e.browserPid)?e.browserPid:void 0,debugPort:e.debugPort,tempDir:e.tempDir,clientPids:Array.isArray(e.clientPids)?e.clientPids.filter((n)=>Number.isInteger(n)&&n>0):[],sessionMode:e.sessionMode==="visible"?"visible":"headless",lastActivity:Number.isFinite(e.lastActivity)?e.lastActivity:0,launchedAt:Number.isFinite(e.launchedAt)?e.launchedAt:0}}}catch{}try{let t=D(P)?Number.parseInt(N(P,"utf8").trim(),10)||void 0:void 0,e=D(C)?N(C,"utf8").trim()==="visible"?"visible":"headless":"headless",n=D(B)?Number.parseInt(N(B,"utf8").trim(),10)||0:0;return{browserPid:t,debugPort:g,tempDir:p,clientPids:t?[t]:[],sessionMode:e,lastActivity:n,launchedAt:0}}catch{return null}}function Y(t){try{J(T,JSON.stringify({browserPid:t.browserPid,debugPort:t.debugPort,tempDir:t.tempDir,clientPids:[...new Set(t.clientPids.filter((e)=>e>0))],sessionMode:t.sessionMode,lastActivity:t.lastActivity,launchedAt:t.launchedAt},null,2),"utf8")}catch{}try{if(t.browserPid)J(P,String(t.browserPid),"utf8")}catch{}try{J(C,t.sessionMode,"utf8")}catch{}try{J(B,String(t.lastActivity),"utf8")}catch{}}function dt(){try{k(T)}catch{}try{k(P)}catch{}try{k(C)}catch{}try{k(B)}catch{}}function ut(t){if(!t)return t;let e={...t,clientPids:[...new Set([...t.clientPids,process.pid].filter((n)=>Q(n)||n===process.pid))]};return Y(e),e}function K(t){let e=Date.now();try{if(t)Y({...t,lastActivity:e});else J(B,String(e),"utf8")}catch{}}var Tn=Number.parseInt(process.env.GREEDY_SEARCH_IDLE_TIMEOUT_MINUTES||"5",10)||5;var Ht=!1;function Ut(){if(process.env.GREEDY_SEARCH_RESEARCH_CHILD)return;if(Ht)return;Ht=!0;let t=V();if(!t)return;if(t.browserPid){if(!Q(t.browserPid)){dt();return}if(!Vt(t.browserPid,t.tempDir,t.debugPort))dt();else Y({...t,clientPids:t.clientPids.filter((r)=>Q(r))})}let e=Ve();if(e&&e!==t.browserPid)if(Vt(e,p,g))Y({browserPid:e,debugPort:g,tempDir:p,clientPids:[e],sessionMode:t.sessionMode,lastActivity:Date.now(),launchedAt:Date.now()});else process.stderr.write(`[greedysearch] Refusing to kill unverified listener ${e} on port ${g}.
|
|
319
|
-
`)}function Mt(){Xe(p,{recursive:!0});try{let t=JSON.stringify({pid:process.pid,ts:Date.now()});return J(j,t,{encoding:"utf8",flag:"wx"}),{acquired:!0,release:()=>{try{let e=N(j,"utf8");if(JSON.parse(e).pid===process.pid)k(j)}catch{}}}}catch(t){if(t?.code!=="EEXIST")return{acquired:!1,release:()=>{}}}try{let t=N(j,"utf8"),e=JSON.parse(t),n=Date.now()-(e.ts||0);if(!Q(e.pid)||n>qe){try{k(j)}catch{}try{let r=JSON.stringify({pid:process.pid,ts:Date.now()});return J(j,r,{encoding:"utf8",flag:"wx"}),{acquired:!0,release:()=>{try{k(j)}catch{}}}}catch{return{acquired:!1,release:()=>{}}}}}catch{}return{acquired:!1,release:()=>{}}}var Ue=kt(import.meta.url),zt=A,d=O,Me=Number.parseInt(process.env.GREEDY_SEARCH_IDLE_TIMEOUT_MINUTES||"5",10)||5,ze=Number.parseInt(process.env.GREEDY_SEARCH_VISIBLE_IDLE_TIMEOUT_MINUTES||"60",10)||60;function Ae(t,e=g){let n=String(t||"").toLowerCase();if(!n.includes(`--remote-debugging-port=${e}`)||n.includes("--type="))return null;return n.includes("--headless")}function Pt(){try{let t=F(),e=t?Ct(t):null,n=Ae(e);if(n!==null){try{G($,n?"headless":"visible","utf8")}catch{}return n}}catch{}try{if(!Dt($))return!0;return st($,"utf8").trim()==="headless"}catch{return!0}}function Oe(){try{G(d,String(Date.now()),"utf8")}catch{}try{let t=V();if(t)K(t)}catch{}}function Ct(t){try{if(Tt()==="win32")return at(w("powershell"),["-NoProfile","-NonInteractive","-Command",`(Get-CimInstance Win32_Process -Filter "ProcessId = ${t}").CommandLine`],{encoding:"utf8",windowsHide:!0,timeout:5000}).trim()||null;return at(w("ps"),["-p",String(t),"-o","command="],{encoding:"utf8",timeout:5000}).trim()||null}catch{return null}}function De(t){let e=String(t||"").replaceAll("\\","/"),n=p.replaceAll("\\","/");return e.includes(`--remote-debugging-port=${g}`)&&e.includes(`--user-data-dir=${n}`)&&!e.includes("--type=")}function F(){return M(g)}function R(){let t=F();return t&&De(Ct(t))?t:null}async function Te(t=1500){let e=R();if(!e)return process.stderr.write(`[greedysearch] Refusing to close an unverified listener.
|
|
320
|
-
`),!1;try{let i=await new Promise((o,l)=>{let u=ft.get(`http://localhost:${g}/json/version`,(a)=>{let f="";a.on("data",(c)=>f+=c),a.on("end",()=>{try{o(JSON.parse(f))}catch{l(Error("bad JSON"))}})});u.on("error",l),u.setTimeout(1000,()=>{u.destroy(),l(Error("timeout"))})}),r=new globalThis.WebSocket(i.webSocketDebuggerUrl);await new Promise((o)=>{r.onopen=()=>{if(R()!==e){r.close(),o();return}r.send(JSON.stringify({id:1,method:"Browser.close"})),setTimeout(()=>{r.close(),o()},200)},r.onerror=()=>o(),setTimeout(o,1000)})}catch{}let n=Date.now()+t;while(Date.now()<n){let i=F();if(!i)return!0;if(i!==e)return!1;await new Promise((r)=>setTimeout(r,150))}return Pe(e)}function Pe(t=null){try{let e=R();if(!e||t&&e!==t)return!1;if(Tt()==="win32")at(w("taskkill"),["/F","/PID",String(e)],{stdio:"ignore",windowsHide:!0});else process.kill(e,"SIGKILL");return!0}catch{return!1}}async function Yt(){if(!R()){if(F())process.stderr.write(`[greedysearch] Refusing to kill an unverified listener.
|
|
321
|
-
`);return!1}if(!await x(500)){try{v(zt)}catch{}try{v(d)}catch{}try{v($)}catch{}return!1}let e=await Te(1500);try{v(zt)}catch{}try{v(d)}catch{}try{v($)}catch{}if(e)process.stderr.write(`[greedysearch] Killed Chrome on port ${g}.
|
|
322
|
-
`);return e}var At=Yt;async function Ce(){let e=Pt()?Me:ze;if(e<=0)return!1;if(!Dt(d))return Oe(),!1;try{let n=Number.parseInt(st(d,"utf8").trim(),10);if(!n)return!1;if((Date.now()-n)/60000>=e)return Yt()}catch{}return!1}function x(t=3000){return new Promise((e)=>{let n=ft.get(`http://localhost:${g}/json/version`,(i)=>{i.resume(),e(i.statusCode===200)});n.on("error",()=>e(!1)),n.setTimeout(t,()=>{n.destroy(),e(!1)})})}async function Ot(t=3000,e=200){let n=Date.now()+t;while(Date.now()<n){if(!await x(300))return!0;await new Promise((i)=>setTimeout(i,e))}return!await x(300)}async function S(){let t=`${q}.lock`,e=`${q}.tmp`,n=5000,i=1000,r=await new Promise((o)=>{let l=Date.now(),u=()=>{try{let a=JSON.stringify({pid:process.pid,ts:Date.now()});G(t,a,{encoding:"utf8",flag:"wx"}),o(!0)}catch(a){if(a?.code!=="EEXIST"){if(Date.now()-l<1000)setTimeout(u,50);else o(!1);return}try{let f=st(t,"utf8").trim(),c=f.startsWith("{")?JSON.parse(f):{ts:Number(f)},_=Number(c?.ts)||0;if(_>0&&Date.now()-_>5000)try{v(t)}catch{}if(Date.now()-l<1000)setTimeout(u,50);else o(!1)}catch{if(Date.now()-l<1000)setTimeout(u,50);else o(!1)}}};u()});try{let o=await new Promise((a,f)=>{let c=ft.get(`http://localhost:${g}/json/version`,(_)=>{let X="";_.on("data",(L)=>X+=L),_.on("end",()=>a(X))});c.on("error",f),c.setTimeout(3000,()=>{c.destroy(),f(Error("timeout"))})}),{webSocketDebuggerUrl:l}=JSON.parse(o),u=new URL(l).pathname;if(r){G(e,`${g}
|
|
323
|
-
${u}`,"utf8");try{v(q)}catch{}He(e,q)}}catch{}finally{if(r)try{v(t)}catch{}}}async function Kt(){if(process.env.GREEDY_SEARCH_RESEARCH_CHILD&&await x()){await S();try{let o=V();if(o)K(o),ut(o)}catch{}return}Ut();let t=await Ce(),e=t?!1:await x();if(!e&&!t)await new Promise((o)=>setTimeout(o,500)),e=await x();let n=!1;if(e){let o=Pt(),l=process.env.GREEDY_SEARCH_VISIBLE==="1";if(!l&&!o)process.stderr.write(`[greedysearch] Visible Chrome detected — switching to headless mode...
|
|
324
|
-
`),await At(),await Ot(),n=!0;else if(l&&o)process.stderr.write(`[greedysearch] Headless Chrome detected — switching to visible mode...
|
|
325
|
-
`),await At(),await Ot(),n=!0}if(n?!1:await x()){await S();try{let o=V();if(o)K(o),ut(o)}catch{}return}let r=Mt();if(!r.acquired){let o=Date.now()+12000,l=!1;while(Date.now()<o){if(l=await x(500),l)break;await new Promise((u)=>setTimeout(u,250))}if(l){await S();return}}try{if(await x(1000)){await S();return}process.stderr.write(`GreedySearch Chrome not running on port ${g} — auto-launching...
|
|
326
|
-
`);let u=[Jt({moduleDir:Ue,entrypoint:process.argv[1],env:process.env})];if(process.env.GREEDY_SEARCH_VISIBLE!=="1")u.push("--headless");await new Promise((a,f)=>{de($t(),u,{stdio:["ignore",process.stderr,process.stderr]}).on("close",(_)=>_===0?a():f(Error("launch.mjs failed")))})}finally{r.release()}}var Se="https://logically.app/research-assistant/",y={input:'div.ProseMirror[contenteditable="true"]',submitButton:'.chat-control button[class*="MuiButton-black"], button[type="submit"]',answerContainer:'#last-message .chat-content, [class*="chat-content"]',citationSpan:'#last-message .chat-content span[title], [class*="chat-content"] span[title]'};async function Ge(t){return s(["eval",t,`(() => {
|
|
1
|
+
import {
|
|
2
|
+
buildEnvelope,
|
|
3
|
+
cdp,
|
|
4
|
+
formatAnswer,
|
|
5
|
+
getOrOpenTab,
|
|
6
|
+
handleError,
|
|
7
|
+
jitter,
|
|
8
|
+
logStage,
|
|
9
|
+
outputJson,
|
|
10
|
+
parseArgs,
|
|
11
|
+
prepareArgs,
|
|
12
|
+
TIMING,
|
|
13
|
+
validateQuery,
|
|
14
|
+
verifyInputText,
|
|
15
|
+
waitForSelector
|
|
16
|
+
} from "./common.mjs";
|
|
17
|
+
import { readFileSync } from "node:fs";
|
|
18
|
+
import { tmpdir } from "node:os";
|
|
19
|
+
import { ensureChrome } from "../src/search/chrome.mjs";
|
|
20
|
+
const START_URL = "https://logically.app/research-assistant/";
|
|
21
|
+
const SELECTORS = {
|
|
22
|
+
input: 'div.ProseMirror[contenteditable="true"]',
|
|
23
|
+
submitButton: '.chat-control button[class*="MuiButton-black"], button[type="submit"]',
|
|
24
|
+
answerContainer: '#last-message .chat-content, [class*="chat-content"]',
|
|
25
|
+
citationSpan: '#last-message .chat-content span[title], [class*="chat-content"] span[title]'
|
|
26
|
+
};
|
|
27
|
+
async function startNewChat(tab) {
|
|
28
|
+
const code = `(() => {
|
|
327
29
|
const buttons = Array.from(document.querySelectorAll('button'));
|
|
328
30
|
const create = buttons.find((b) => (b.innerText || '').trim() === 'Create');
|
|
329
31
|
if (!create) return 'missing';
|
|
330
32
|
create.click();
|
|
331
33
|
return 'clicked';
|
|
332
|
-
})()
|
|
34
|
+
})()`;
|
|
35
|
+
return cdp(["eval", tab, code], 5000).catch(() => "error");
|
|
36
|
+
}
|
|
37
|
+
async function detectLoginWall(tab) {
|
|
38
|
+
const code = `(() => {
|
|
333
39
|
const url = document.location.href || '';
|
|
334
40
|
if (url.includes('/login') || url.includes('/signup') || url.includes('/sign-up')) return true;
|
|
335
41
|
const modalText = Array.from(document.querySelectorAll('[role="dialog"], .MuiModal-root'))
|
|
@@ -337,8 +43,33 @@ ${u}`,"utf8");try{v(q)}catch{}He(e,q)}}catch{}finally{if(r)try{v(t)}catch{}}}asy
|
|
|
337
43
|
.join('
|
|
338
44
|
');
|
|
339
45
|
return /create a free account|continue with google|have an account[?] log in|log in|sign up/i.test(modalText);
|
|
340
|
-
})()
|
|
341
|
-
|
|
46
|
+
})()`;
|
|
47
|
+
return await cdp(["eval", tab, code], 5000).catch(() => "false") === "true";
|
|
48
|
+
}
|
|
49
|
+
async function activateTab(tab) {
|
|
50
|
+
try {
|
|
51
|
+
await cdp(["list"]);
|
|
52
|
+
const cachePath = `${tmpdir().replaceAll("\\\\", "/")}/cdp-pages.json`;
|
|
53
|
+
const pages = JSON.parse(readFileSync(cachePath, "utf8"));
|
|
54
|
+
const fullTargetId = pages.find((p) => p.targetId?.startsWith(tab))?.targetId;
|
|
55
|
+
if (fullTargetId) {
|
|
56
|
+
await cdp([
|
|
57
|
+
"browse",
|
|
58
|
+
tab,
|
|
59
|
+
"Target.activateTarget",
|
|
60
|
+
JSON.stringify({ targetId: fullTargetId })
|
|
61
|
+
]).catch(() => null);
|
|
62
|
+
await new Promise((r) => setTimeout(r, 250));
|
|
63
|
+
}
|
|
64
|
+
} catch {}
|
|
65
|
+
}
|
|
66
|
+
async function typeIntoLogically(tab, text) {
|
|
67
|
+
await activateTab(tab);
|
|
68
|
+
const pointRaw = await cdp([
|
|
69
|
+
"eval",
|
|
70
|
+
tab,
|
|
71
|
+
`(() => {
|
|
72
|
+
const inputs = Array.from(document.querySelectorAll('${SELECTORS.input}'));
|
|
342
73
|
const input = inputs.find((el) => {
|
|
343
74
|
const r = el.getBoundingClientRect();
|
|
344
75
|
return r.width > 20 && r.height > 5;
|
|
@@ -347,19 +78,64 @@ ${u}`,"utf8");try{v(q)}catch{}He(e,q)}}catch{}finally{if(r)try{v(t)}catch{}}}asy
|
|
|
347
78
|
input.scrollIntoView({ block: 'center', inline: 'center' });
|
|
348
79
|
const r = input.getBoundingClientRect();
|
|
349
80
|
return JSON.stringify({ x: Math.round(r.left + Math.min(80, r.width / 2)), y: Math.round(r.top + r.height / 2) });
|
|
350
|
-
})()`
|
|
351
|
-
|
|
81
|
+
})()`
|
|
82
|
+
]);
|
|
83
|
+
if (!pointRaw)
|
|
84
|
+
throw new Error("Logically visible input not found");
|
|
85
|
+
let point;
|
|
86
|
+
try {
|
|
87
|
+
point = JSON.parse(pointRaw);
|
|
88
|
+
} catch {
|
|
89
|
+
throw new Error("Logically input coordinates were invalid");
|
|
90
|
+
}
|
|
91
|
+
await cdp(["click", tab, SELECTORS.input]).catch(() => null);
|
|
92
|
+
await new Promise((r) => setTimeout(r, jitter(120)));
|
|
93
|
+
await cdp(["clickxy", tab, String(point.x), String(point.y)]);
|
|
94
|
+
await new Promise((r) => setTimeout(r, jitter(TIMING.postClick)));
|
|
95
|
+
const type = async () => {
|
|
96
|
+
const typeResult = await cdp([
|
|
97
|
+
"eval",
|
|
98
|
+
tab,
|
|
99
|
+
`(() => {
|
|
100
|
+
const ed = document.querySelector('${SELECTORS.input}');
|
|
352
101
|
if (!ed) return 'no-input';
|
|
353
102
|
ed.focus();
|
|
354
103
|
if (!ed.editor || !ed.editor.commands) {
|
|
355
104
|
// Fallback to execCommand for non-tiptap editors
|
|
356
|
-
const ok = document.execCommand('insertText', false, ${JSON.stringify(
|
|
105
|
+
const ok = document.execCommand('insertText', false, ${JSON.stringify(text)});
|
|
357
106
|
return ok ? 'ok' : 'exec-failed';
|
|
358
107
|
}
|
|
359
|
-
const ok = ed.editor.commands.insertContent(${JSON.stringify(
|
|
108
|
+
const ok = ed.editor.commands.insertContent(${JSON.stringify(text)});
|
|
360
109
|
return ok ? 'ok' : 'tiptap-failed';
|
|
361
|
-
})()`
|
|
362
|
-
|
|
110
|
+
})()`
|
|
111
|
+
], 5000);
|
|
112
|
+
if (typeResult !== "ok") {
|
|
113
|
+
throw new Error(`Logically type failed: ${typeResult}`);
|
|
114
|
+
}
|
|
115
|
+
await new Promise((r) => setTimeout(r, jitter(TIMING.postType)));
|
|
116
|
+
};
|
|
117
|
+
const readInput = async () => {
|
|
118
|
+
const raw = await cdp([
|
|
119
|
+
"eval",
|
|
120
|
+
tab,
|
|
121
|
+
`JSON.stringify(Array.from(document.querySelectorAll('${SELECTORS.input}')).map((el) => el.innerText || el.textContent || ''))`
|
|
122
|
+
]);
|
|
123
|
+
try {
|
|
124
|
+
return JSON.parse(raw);
|
|
125
|
+
} catch {
|
|
126
|
+
return [];
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
const verify = async () => {
|
|
130
|
+
const contents = await readInput();
|
|
131
|
+
return contents.some((content) => verifyInputText(content, text));
|
|
132
|
+
};
|
|
133
|
+
const clear = async () => {
|
|
134
|
+
await cdp([
|
|
135
|
+
"eval",
|
|
136
|
+
tab,
|
|
137
|
+
`(() => {
|
|
138
|
+
const ed = document.querySelector('${SELECTORS.input}');
|
|
363
139
|
if (!ed) return false;
|
|
364
140
|
ed.focus();
|
|
365
141
|
if (ed.editor?.commands?.clearContent) {
|
|
@@ -373,14 +149,27 @@ ${u}`,"utf8");try{v(q)}catch{}He(e,q)}}catch{}finally{if(r)try{v(t)}catch{}}}asy
|
|
|
373
149
|
selection.addRange(range);
|
|
374
150
|
document.execCommand('delete');
|
|
375
151
|
return true;
|
|
376
|
-
})()`
|
|
152
|
+
})()`
|
|
153
|
+
]);
|
|
154
|
+
};
|
|
155
|
+
await type();
|
|
156
|
+
if (await verify())
|
|
157
|
+
return;
|
|
158
|
+
await clear();
|
|
159
|
+
await type();
|
|
160
|
+
if (!await verify()) {
|
|
161
|
+
throw new Error("Logically input did not accept text — input verification failed");
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
async function waitForLogicallyAnswer(tab, timeoutMs = 90000) {
|
|
165
|
+
const code = String.raw`
|
|
377
166
|
new Promise((resolve, reject) => {
|
|
378
|
-
const deadline = Date.now() + ${
|
|
167
|
+
const deadline = Date.now() + ${timeoutMs};
|
|
379
168
|
let last = '';
|
|
380
169
|
let stable = 0;
|
|
381
170
|
function poll() {
|
|
382
171
|
try {
|
|
383
|
-
const answer = document.querySelector('${
|
|
172
|
+
const answer = document.querySelector('${SELECTORS.answerContainer}');
|
|
384
173
|
const text = (answer?.innerText || '').trim();
|
|
385
174
|
const body = document.body.innerText || '';
|
|
386
175
|
const stillGenerating = /Generating answer|Thinking\.\.\.|Searching the internet|Discovered \d+/.test(body) && text.length < 200;
|
|
@@ -390,12 +179,16 @@ ${u}`,"utf8");try{v(q)}catch{}He(e,q)}}catch{}finally{if(r)try{v(t)}catch{}}}asy
|
|
|
390
179
|
if (stable >= 3) { resolve(text.length); return; }
|
|
391
180
|
}
|
|
392
181
|
if (Date.now() < deadline) setTimeout(poll, 700 + Math.random() * 250);
|
|
393
|
-
else reject(new Error('Logically answer did not stabilise within ${
|
|
182
|
+
else reject(new Error('Logically answer did not stabilise within ${timeoutMs}ms'));
|
|
394
183
|
} catch (e) { reject(e); }
|
|
395
184
|
}
|
|
396
185
|
poll();
|
|
397
|
-
})`;
|
|
398
|
-
|
|
186
|
+
})`;
|
|
187
|
+
return cdp(["eval", tab, code], timeoutMs + 1e4);
|
|
188
|
+
}
|
|
189
|
+
async function extractAnswer(tab) {
|
|
190
|
+
const code = `(() => {
|
|
191
|
+
const el = document.querySelector('${SELECTORS.answerContainer}');
|
|
399
192
|
if (!el) return JSON.stringify({ answer: '', answerHtml: '' });
|
|
400
193
|
const clone = el.cloneNode(true);
|
|
401
194
|
clone.querySelectorAll('svg').forEach((n) => n.remove());
|
|
@@ -406,7 +199,15 @@ ${u}`,"utf8");try{v(q)}catch{}He(e,q)}}catch{}finally{if(r)try{v(t)}catch{}}}asy
|
|
|
406
199
|
answer: (el.innerText || '').trim(),
|
|
407
200
|
answerHtml: clone.innerHTML,
|
|
408
201
|
});
|
|
409
|
-
})()`;
|
|
202
|
+
})()`;
|
|
203
|
+
try {
|
|
204
|
+
return JSON.parse(await cdp(["eval", tab, code], 1e4));
|
|
205
|
+
} catch {
|
|
206
|
+
return { answer: "", answerHtml: "" };
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
async function extractFullCitationSources(tab) {
|
|
210
|
+
const code = String.raw`
|
|
410
211
|
(async () => {
|
|
411
212
|
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
412
213
|
|
|
@@ -546,10 +347,19 @@ ${u}`,"utf8");try{v(q)}catch{}He(e,q)}}catch{}finally{if(r)try{v(t)}catch{}}}asy
|
|
|
546
347
|
webCaptured: webSources.length,
|
|
547
348
|
},
|
|
548
349
|
});
|
|
549
|
-
})()
|
|
350
|
+
})()`;
|
|
351
|
+
const raw = await cdp(["eval", tab, code], 20000);
|
|
352
|
+
try {
|
|
353
|
+
return JSON.parse(raw);
|
|
354
|
+
} catch {
|
|
355
|
+
return { sources: [], summary: { expectedTotal: 0, reason: "invalid-json" } };
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
async function extractCitationSources(tab) {
|
|
359
|
+
const code = String.raw`
|
|
550
360
|
(async () => {
|
|
551
361
|
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
552
|
-
const answer = document.querySelector('${
|
|
362
|
+
const answer = document.querySelector('${SELECTORS.answerContainer}');
|
|
553
363
|
if (!answer) return JSON.stringify([]);
|
|
554
364
|
|
|
555
365
|
function parseUrlFromId(id) {
|
|
@@ -650,8 +460,64 @@ ${u}`,"utf8");try{v(q)}catch{}He(e,q)}}catch{}finally{if(r)try{v(t)}catch{}}}asy
|
|
|
650
460
|
}
|
|
651
461
|
}
|
|
652
462
|
return JSON.stringify(sources);
|
|
653
|
-
})()
|
|
654
|
-
|
|
463
|
+
})()`;
|
|
464
|
+
const raw = await cdp(["eval", tab, code], 45000);
|
|
465
|
+
try {
|
|
466
|
+
return JSON.parse(raw);
|
|
467
|
+
} catch {
|
|
468
|
+
return [];
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
const USAGE = `Usage: node extractors/logically.mjs "<query>" [--tab <prefix>]
|
|
472
|
+
`;
|
|
473
|
+
async function main() {
|
|
474
|
+
const args = await prepareArgs(process.argv.slice(2));
|
|
475
|
+
validateQuery(args, USAGE);
|
|
476
|
+
const { query, tabPrefix, short } = parseArgs(args);
|
|
477
|
+
const startTime = Date.now();
|
|
478
|
+
const mode = process.env.GREEDY_SEARCH_VISIBLE === "1" ? "visible" : "headless";
|
|
479
|
+
const env = {
|
|
480
|
+
engine: "logically",
|
|
481
|
+
mode,
|
|
482
|
+
clipboardEmpty: null,
|
|
483
|
+
fallbackUsed: null,
|
|
484
|
+
blockedBy: null,
|
|
485
|
+
verificationResult: null,
|
|
486
|
+
inputReady: null
|
|
487
|
+
};
|
|
488
|
+
try {
|
|
489
|
+
if (process.env.GREEDY_SEARCH_VISIBLE !== "1" && process.env.GREEDY_SEARCH_ALWAYS_VISIBLE !== "1") {
|
|
490
|
+
process.env.GREEDY_SEARCH_HEADLESS = "1";
|
|
491
|
+
}
|
|
492
|
+
await ensureChrome();
|
|
493
|
+
if (!tabPrefix)
|
|
494
|
+
await cdp(["list"]);
|
|
495
|
+
const tab = await getOrOpenTab(tabPrefix);
|
|
496
|
+
const currentUrl = await cdp(["eval", tab, "document.location.href"]).catch(() => "");
|
|
497
|
+
let onLogically = false;
|
|
498
|
+
try {
|
|
499
|
+
const host = new URL(currentUrl).hostname.toLowerCase();
|
|
500
|
+
onLogically = host === "logically.app" || host.endsWith(".logically.app");
|
|
501
|
+
} catch {}
|
|
502
|
+
if (!onLogically) {
|
|
503
|
+
logStage(env, "nav", startTime);
|
|
504
|
+
await cdp(["nav", tab, START_URL], 25000);
|
|
505
|
+
await new Promise((r) => setTimeout(r, 900));
|
|
506
|
+
}
|
|
507
|
+
logStage(env, "new-chat", startTime);
|
|
508
|
+
await startNewChat(tab);
|
|
509
|
+
await new Promise((r) => setTimeout(r, 700));
|
|
510
|
+
logStage(env, "input-wait", startTime);
|
|
511
|
+
const inputReady = await waitForSelector(tab, SELECTORS.input, 20000, 400);
|
|
512
|
+
env.inputReady = inputReady;
|
|
513
|
+
if (!inputReady) {
|
|
514
|
+
throw new Error("Logically input not found — page may not have loaded or is in unexpected state");
|
|
515
|
+
}
|
|
516
|
+
if (process.env.GREEDY_SEARCH_HEADLESS === "1") {
|
|
517
|
+
const quotaResult = await cdp([
|
|
518
|
+
"eval",
|
|
519
|
+
tab,
|
|
520
|
+
`(() => {
|
|
655
521
|
const text = document.body?.innerText || '';
|
|
656
522
|
const m = text.match(/Chat messages\\s*\\n?\\s*(\\d+)\\s*\\/\\s*(\\d+)/i);
|
|
657
523
|
if (m && parseInt(m[1], 10) >= parseInt(m[2], 10)) {
|
|
@@ -663,4 +529,61 @@ ${u}`,"utf8");try{v(q)}catch{}He(e,q)}}catch{}finally{if(r)try{v(t)}catch{}}}asy
|
|
|
663
529
|
);
|
|
664
530
|
if (createBtn && createBtn.disabled) return 'create-disabled';
|
|
665
531
|
return 'ok';
|
|
666
|
-
})()`
|
|
532
|
+
})()`
|
|
533
|
+
], 5000).catch(() => "ok");
|
|
534
|
+
if (quotaResult === "quota-exceeded" || quotaResult === "create-disabled") {
|
|
535
|
+
console.error("[logically] Rate Limited — skipping (visible retry won't help)");
|
|
536
|
+
env.blockedBy = "rate-limit";
|
|
537
|
+
throw new Error("Rate Limited — Logically free message quota exhausted. Wait until reset.");
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
logStage(env, "type-and-submit", startTime);
|
|
541
|
+
await typeIntoLogically(tab, query);
|
|
542
|
+
const submitted = await cdp([
|
|
543
|
+
"eval",
|
|
544
|
+
tab,
|
|
545
|
+
`(() => { const btn = document.querySelector('${SELECTORS.submitButton}'); if (!btn) return 'missing'; btn.click(); return 'clicked'; })()`
|
|
546
|
+
]);
|
|
547
|
+
if (submitted !== "clicked")
|
|
548
|
+
throw new Error("Logically submit button not found");
|
|
549
|
+
await new Promise((r) => setTimeout(r, 1500));
|
|
550
|
+
if (await detectLoginWall(tab)) {
|
|
551
|
+
env.blockedBy = "signin";
|
|
552
|
+
env.verificationResult = "needs-human";
|
|
553
|
+
throw new Error("Logically login required — please log in or create a free account in the visible browser window. Once signed in, cookies persist for future runs.");
|
|
554
|
+
}
|
|
555
|
+
logStage(env, "answer-wait", startTime);
|
|
556
|
+
await waitForLogicallyAnswer(tab, 90000);
|
|
557
|
+
logStage(env, "extract-answer-html", startTime);
|
|
558
|
+
const { answer, answerHtml } = await extractAnswer(tab);
|
|
559
|
+
if (!answer)
|
|
560
|
+
throw new Error("No answer extracted — Logically may not have responded");
|
|
561
|
+
logStage(env, "extract-full-citations", startTime);
|
|
562
|
+
const fullCitations = await extractFullCitationSources(tab);
|
|
563
|
+
let inlineSources = [];
|
|
564
|
+
let sources = fullCitations.sources?.length ? fullCitations.sources : null;
|
|
565
|
+
if (!sources) {
|
|
566
|
+
logStage(env, "extract-inline-citations", startTime);
|
|
567
|
+
inlineSources = await extractCitationSources(tab);
|
|
568
|
+
sources = inlineSources;
|
|
569
|
+
}
|
|
570
|
+
const finalUrl = await cdp(["eval", tab, "document.location.href"]).catch(() => "");
|
|
571
|
+
env.durationMs = Date.now() - startTime;
|
|
572
|
+
env.sourcePath = fullCitations.sources?.length ? "citations-popover" : "inline-citation-popovers";
|
|
573
|
+
logStage(env, "done", startTime);
|
|
574
|
+
outputJson({
|
|
575
|
+
query,
|
|
576
|
+
url: finalUrl,
|
|
577
|
+
answer: formatAnswer(answer, short),
|
|
578
|
+
answerHtml,
|
|
579
|
+
sources,
|
|
580
|
+
inlineSources,
|
|
581
|
+
citationSummary: fullCitations.summary,
|
|
582
|
+
_envelope: buildEnvelope(env)
|
|
583
|
+
});
|
|
584
|
+
} catch (e) {
|
|
585
|
+
env.durationMs = Date.now() - startTime;
|
|
586
|
+
handleError(e, buildEnvelope(env));
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
main();
|