@duckmind/dm-windows-x64 0.62.3 → 0.62.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/dm.exe +0 -0
  2. package/extensions/.dm-extensions.json +43 -183
  3. package/extensions/dm-context/src/context.js +1 -2
  4. package/extensions/dm-context/src/index.js +1 -2
  5. package/extensions/{greedysearch-dm/bin/cdp.mjs → dm-cua/bin/browser-cdp.mjs} +3 -3
  6. package/extensions/dm-cua/bin/browser-cua.mjs +1 -1
  7. package/extensions/{greedysearch-dm/bin/launch.mjs → dm-cua/bin/browser-launch.mjs} +12 -11
  8. package/extensions/dm-cua/index.js +1 -1
  9. package/extensions/dm-cua/src/browser-cua-lib.mjs +17 -12
  10. package/extensions/{greedysearch-dm/src/search → dm-cua/src/browser-helpers}/constants.mjs +11 -11
  11. package/extensions/{greedysearch-dm/src/utils → dm-cua/src/browser-helpers}/node-runtime.mjs +1 -1
  12. package/extensions/{greedysearch-dm/src/search → dm-cua/src/browser-helpers}/port-pid.mjs +1 -1
  13. package/extensions/dm-ponytail/extensions/ponytail.mjs +186 -0
  14. package/extensions/dm-ponytail/hooks/claude-codex-hooks.json +41 -0
  15. package/extensions/dm-ponytail/hooks/copilot-hooks.json +21 -0
  16. package/extensions/dm-ponytail/hooks/ponytail-activate.js +59 -0
  17. package/extensions/dm-ponytail/hooks/ponytail-config.js +116 -0
  18. package/extensions/dm-ponytail/hooks/ponytail-instructions.js +81 -0
  19. package/extensions/dm-ponytail/hooks/ponytail-mode-tracker.js +96 -0
  20. package/extensions/dm-ponytail/hooks/ponytail-runtime.js +79 -0
  21. package/extensions/dm-ponytail/hooks/ponytail-statusline.ps1 +24 -0
  22. package/extensions/dm-ponytail/hooks/ponytail-statusline.sh +18 -0
  23. package/extensions/dm-ponytail/hooks/ponytail-subagent.js +50 -0
  24. package/extensions/dm-ponytail/hooks/qoder-hooks.json +26 -0
  25. package/extensions/dm-ponytail/package.json +19 -0
  26. package/extensions/dm-ponytail/pi-extension/index.js +186 -0
  27. package/extensions/dm-ponytail/pi-extension/package.json +8 -0
  28. package/extensions/dm-ponytail/skills/ponytail/SKILL.md +120 -0
  29. package/extensions/dm-ponytail/skills/ponytail-audit/SKILL.md +41 -0
  30. package/extensions/dm-ponytail/skills/ponytail-debt/SKILL.md +44 -0
  31. package/extensions/dm-ponytail/skills/ponytail-gain/SKILL.md +50 -0
  32. package/extensions/dm-ponytail/skills/ponytail-help/SKILL.md +71 -0
  33. package/extensions/dm-ponytail/skills/ponytail-review/SKILL.md +57 -0
  34. package/package.json +2 -6
  35. package/extensions/dm-caveman/extensions/caveman.js +0 -300
  36. package/extensions/dm-caveman/package.json +0 -20
  37. package/extensions/dm-goal/package.json +0 -23
  38. package/extensions/dm-goal/src/goal.js +0 -914
  39. package/extensions/greedysearch-dm/bin/cdp-greedy.mjs +0 -40
  40. package/extensions/greedysearch-dm/bin/cdp-headless.mjs +0 -5
  41. package/extensions/greedysearch-dm/bin/cdp-visible.mjs +0 -5
  42. package/extensions/greedysearch-dm/bin/gschrome.mjs +0 -30
  43. package/extensions/greedysearch-dm/bin/kill-visible.mjs +0 -7
  44. package/extensions/greedysearch-dm/bin/launch-visible.mjs +0 -13
  45. package/extensions/greedysearch-dm/bin/mcp.mjs +0 -400
  46. package/extensions/greedysearch-dm/bin/search.mjs +0 -635
  47. package/extensions/greedysearch-dm/bin/visible.mjs +0 -22
  48. package/extensions/greedysearch-dm/extractors/bing-copilot.mjs +0 -344
  49. package/extensions/greedysearch-dm/extractors/chatgpt.mjs +0 -354
  50. package/extensions/greedysearch-dm/extractors/common.mjs +0 -794
  51. package/extensions/greedysearch-dm/extractors/consensus.mjs +0 -527
  52. package/extensions/greedysearch-dm/extractors/consent.mjs +0 -449
  53. package/extensions/greedysearch-dm/extractors/gemini.mjs +0 -291
  54. package/extensions/greedysearch-dm/extractors/google-ai.mjs +0 -86
  55. package/extensions/greedysearch-dm/extractors/logically.mjs +0 -589
  56. package/extensions/greedysearch-dm/extractors/perplexity.mjs +0 -370
  57. package/extensions/greedysearch-dm/extractors/selectors.mjs +0 -32
  58. package/extensions/greedysearch-dm/extractors/semantic-scholar.mjs +0 -199
  59. package/extensions/greedysearch-dm/index.js +0 -123
  60. package/extensions/greedysearch-dm/package.json +0 -27
  61. package/extensions/greedysearch-dm/skills/greedy-search/skill.md +0 -18
  62. package/extensions/greedysearch-dm/src/fetcher.mjs +0 -577
  63. package/extensions/greedysearch-dm/src/formatters/results.js +0 -95
  64. package/extensions/greedysearch-dm/src/formatters/sources.js +0 -57
  65. package/extensions/greedysearch-dm/src/formatters/synthesis.js +0 -49
  66. package/extensions/greedysearch-dm/src/github.mjs +0 -228
  67. package/extensions/greedysearch-dm/src/reddit.mjs +0 -154
  68. package/extensions/greedysearch-dm/src/search/browser-lifecycle.mjs +0 -340
  69. package/extensions/greedysearch-dm/src/search/challenge-detect.mjs +0 -156
  70. package/extensions/greedysearch-dm/src/search/chrome.mjs +0 -510
  71. package/extensions/greedysearch-dm/src/search/defaults.mjs +0 -10
  72. package/extensions/greedysearch-dm/src/search/engines.mjs +0 -79
  73. package/extensions/greedysearch-dm/src/search/fetch-source.mjs +0 -470
  74. package/extensions/greedysearch-dm/src/search/file-sources.mjs +0 -31
  75. package/extensions/greedysearch-dm/src/search/output.mjs +0 -51
  76. package/extensions/greedysearch-dm/src/search/paths.mjs +0 -48
  77. package/extensions/greedysearch-dm/src/search/pdf.mjs +0 -64
  78. package/extensions/greedysearch-dm/src/search/progress.mjs +0 -109
  79. package/extensions/greedysearch-dm/src/search/query.mjs +0 -21
  80. package/extensions/greedysearch-dm/src/search/recovery.mjs +0 -49
  81. package/extensions/greedysearch-dm/src/search/research.mjs +0 -2255
  82. package/extensions/greedysearch-dm/src/search/scale-aware.mjs +0 -61
  83. package/extensions/greedysearch-dm/src/search/simple-research.mjs +0 -418
  84. package/extensions/greedysearch-dm/src/search/sources.mjs +0 -412
  85. package/extensions/greedysearch-dm/src/search/synthesis-runner.mjs +0 -127
  86. package/extensions/greedysearch-dm/src/search/synthesis.mjs +0 -202
  87. package/extensions/greedysearch-dm/src/tools/greedy-search-handler.js +0 -209
  88. package/extensions/greedysearch-dm/src/tools/shared.js +0 -226
  89. package/extensions/greedysearch-dm/src/types.js +0 -0
  90. package/extensions/greedysearch-dm/src/utils/content.mjs +0 -38
  91. package/extensions/greedysearch-dm/src/utils/helpers.js +0 -22
  92. /package/extensions/{greedysearch-dm/src/search → dm-cua/src/browser-helpers}/minimize.mjs +0 -0
  93. /package/extensions/{greedysearch-dm/src/utils → dm-cua/src/browser-helpers}/system-cmds.mjs +0 -0
@@ -1,510 +0,0 @@
1
- import { spawn, execFileSync, execSync } from "node:child_process";
2
- import { nodeRuntimeCommand } from "../utils/node-runtime.mjs";
3
- import {
4
- existsSync,
5
- readFileSync,
6
- renameSync,
7
- unlinkSync,
8
- writeFileSync
9
- } from "node:fs";
10
- import http from "node:http";
11
- import { platform } from "node:os";
12
- import { join } from "node:path";
13
- import {
14
- cdp as _cdp,
15
- injectHeadlessStealth
16
- } from "../../extractors/common.mjs";
17
- import { resolveSystemCmd } from "../utils/system-cmds.mjs";
18
- import { findListeningProcessPid } from "./port-pid.mjs";
19
- import {
20
- moduleDirectory,
21
- resolveGreedySearchLaunchScript
22
- } from "./paths.mjs";
23
- import {
24
- ACTIVE_PORT_FILE,
25
- CHROME_MODE_FILE,
26
- GREEDY_ACTIVITY_FILE,
27
- GREEDY_PID_FILE,
28
- GREEDY_PORT,
29
- GREEDY_PROFILE_DIR,
30
- PAGES_CACHE
31
- } from "./constants.mjs";
32
- import {
33
- readMetadata,
34
- touchActivity as touchActivityBL,
35
- acquireLaunchLock,
36
- cleanupStaleSessions,
37
- registerClient
38
- } from "./browser-lifecycle.mjs";
39
- const __dir = moduleDirectory(import.meta.url);
40
- const PID_FILE = GREEDY_PID_FILE;
41
- const ACTIVITY_FILE = GREEDY_ACTIVITY_FILE;
42
- const HEADLESS_IDLE_TIMEOUT_MINUTES = Number.parseInt(process.env.GREEDY_SEARCH_IDLE_TIMEOUT_MINUTES || "5", 10) || 5;
43
- const VISIBLE_IDLE_TIMEOUT_MINUTES = Number.parseInt(process.env.GREEDY_SEARCH_VISIBLE_IDLE_TIMEOUT_MINUTES || "60", 10) || 60;
44
- export function detectHeadlessFromChromeCommandLine(cmdLine, debugPort = GREEDY_PORT) {
45
- const normalized = String(cmdLine || "").toLowerCase();
46
- if (!normalized.includes(`--remote-debugging-port=${debugPort}`) || normalized.includes("--type=")) {
47
- return null;
48
- }
49
- return normalized.includes("--headless");
50
- }
51
- export function isChromeHeadless() {
52
- try {
53
- const portPid = getPortPid();
54
- const cmdLine = portPid ? getProcessCommandLine(portPid) : null;
55
- const headless = detectHeadlessFromChromeCommandLine(cmdLine);
56
- if (headless !== null) {
57
- try {
58
- writeFileSync(CHROME_MODE_FILE, headless ? "headless" : "visible", "utf8");
59
- } catch {}
60
- return headless;
61
- }
62
- } catch {}
63
- try {
64
- if (!existsSync(CHROME_MODE_FILE))
65
- return true;
66
- return readFileSync(CHROME_MODE_FILE, "utf8").trim() === "headless";
67
- } catch {
68
- return true;
69
- }
70
- }
71
- export function touchActivity() {
72
- try {
73
- writeFileSync(ACTIVITY_FILE, String(Date.now()), "utf8");
74
- } catch {}
75
- try {
76
- const md = readMetadata();
77
- if (md)
78
- touchActivityBL(md);
79
- } catch {}
80
- }
81
- function getProcessCommandLine(pid) {
82
- try {
83
- if (platform() === "win32") {
84
- const output = execFileSync(resolveSystemCmd("powershell"), [
85
- "-NoProfile",
86
- "-NonInteractive",
87
- "-Command",
88
- `(Get-CimInstance Win32_Process -Filter "ProcessId = ${pid}").CommandLine`
89
- ], { encoding: "utf8", windowsHide: true, timeout: 5000 });
90
- return output.trim() || null;
91
- }
92
- const output = execFileSync(resolveSystemCmd("ps"), ["-p", String(pid), "-o", "command="], { encoding: "utf8", timeout: 5000 });
93
- return output.trim() || null;
94
- } catch {
95
- return null;
96
- }
97
- }
98
- function commandLineMatchesGreedyBrowser(commandLine) {
99
- const normalized = String(commandLine || "").replaceAll("\\", "/");
100
- const profile = GREEDY_PROFILE_DIR.replaceAll("\\", "/");
101
- return normalized.includes(`--remote-debugging-port=${GREEDY_PORT}`) && normalized.includes(`--user-data-dir=${profile}`) && !normalized.includes("--type=");
102
- }
103
- function getPortPid() {
104
- return findListeningProcessPid(GREEDY_PORT);
105
- }
106
- function getOwnedBrowserPid() {
107
- const pid = getPortPid();
108
- return pid && commandLineMatchesGreedyBrowser(getProcessCommandLine(pid)) ? pid : null;
109
- }
110
- async function gracefulCloseChrome(graceMs = 1500) {
111
- const ownedPid = getOwnedBrowserPid();
112
- if (!ownedPid) {
113
- process.stderr.write(`[greedysearch] Refusing to close an unverified listener.
114
- `);
115
- return false;
116
- }
117
- try {
118
- const version = await new Promise((resolve, reject) => {
119
- const req = http.get(`http://localhost:${GREEDY_PORT}/json/version`, (res) => {
120
- let body = "";
121
- res.on("data", (d) => body += d);
122
- res.on("end", () => {
123
- try {
124
- resolve(JSON.parse(body));
125
- } catch {
126
- reject(new Error("bad JSON"));
127
- }
128
- });
129
- });
130
- req.on("error", reject);
131
- req.setTimeout(1000, () => {
132
- req.destroy();
133
- reject(new Error("timeout"));
134
- });
135
- });
136
- const ws = new globalThis.WebSocket(version.webSocketDebuggerUrl);
137
- await new Promise((resolve) => {
138
- ws.onopen = () => {
139
- if (getOwnedBrowserPid() !== ownedPid) {
140
- ws.close();
141
- resolve();
142
- return;
143
- }
144
- ws.send(JSON.stringify({ id: 1, method: "Browser.close" }));
145
- setTimeout(() => {
146
- ws.close();
147
- resolve();
148
- }, 200);
149
- };
150
- ws.onerror = () => resolve();
151
- setTimeout(resolve, 1000);
152
- });
153
- } catch {}
154
- const deadline = Date.now() + graceMs;
155
- while (Date.now() < deadline) {
156
- const pid = getPortPid();
157
- if (!pid)
158
- return true;
159
- if (pid !== ownedPid)
160
- return false;
161
- await new Promise((r) => setTimeout(r, 150));
162
- }
163
- return killProcessOnPort(ownedPid);
164
- }
165
- function killProcessOnPort(expectedPid = null) {
166
- try {
167
- const pid = getOwnedBrowserPid();
168
- if (!pid || expectedPid && pid !== expectedPid)
169
- return false;
170
- if (platform() === "win32") {
171
- execFileSync(resolveSystemCmd("taskkill"), ["/F", "/PID", String(pid)], {
172
- stdio: "ignore",
173
- windowsHide: true
174
- });
175
- } else {
176
- process.kill(pid, "SIGKILL");
177
- }
178
- return true;
179
- } catch {
180
- return false;
181
- }
182
- }
183
- export async function killChrome() {
184
- if (!getOwnedBrowserPid()) {
185
- if (getPortPid()) {
186
- process.stderr.write(`[greedysearch] Refusing to kill an unverified listener.
187
- `);
188
- }
189
- return false;
190
- }
191
- const ready = await probeGreedyChrome(500);
192
- if (!ready) {
193
- try {
194
- unlinkSync(PID_FILE);
195
- } catch {}
196
- try {
197
- unlinkSync(ACTIVITY_FILE);
198
- } catch {}
199
- try {
200
- unlinkSync(CHROME_MODE_FILE);
201
- } catch {}
202
- return false;
203
- }
204
- const killed = await gracefulCloseChrome(1500);
205
- try {
206
- unlinkSync(PID_FILE);
207
- } catch {}
208
- try {
209
- unlinkSync(ACTIVITY_FILE);
210
- } catch {}
211
- try {
212
- unlinkSync(CHROME_MODE_FILE);
213
- } catch {}
214
- if (killed) {
215
- process.stderr.write(`[greedysearch] Killed Chrome on port ${GREEDY_PORT}.
216
- `);
217
- }
218
- return killed;
219
- }
220
- export const killHeadlessChrome = killChrome;
221
- export async function checkAndKillIdle() {
222
- const headless = isChromeHeadless();
223
- const timeoutMinutes = headless ? HEADLESS_IDLE_TIMEOUT_MINUTES : VISIBLE_IDLE_TIMEOUT_MINUTES;
224
- if (timeoutMinutes <= 0)
225
- return false;
226
- if (!existsSync(ACTIVITY_FILE)) {
227
- touchActivity();
228
- return false;
229
- }
230
- try {
231
- const lastActivity = Number.parseInt(readFileSync(ACTIVITY_FILE, "utf8").trim(), 10);
232
- if (!lastActivity)
233
- return false;
234
- const idleMs = Date.now() - lastActivity;
235
- const idleMinutes = idleMs / 60000;
236
- if (idleMinutes >= timeoutMinutes) {
237
- return killChrome();
238
- }
239
- } catch {}
240
- return false;
241
- }
242
- export const cdp = _cdp;
243
- export async function getAnyTab() {
244
- const list = await cdp(["list"]);
245
- const first = list.split(`
246
- `)[0];
247
- if (!first)
248
- throw new Error("No Chrome tabs found");
249
- return first.slice(0, 8);
250
- }
251
- export async function openNewTab(url = "about:blank") {
252
- const anchor = await getAnyTab();
253
- const hostname = new URL(url).hostname;
254
- const needsStealth = hostname === "copilot.microsoft.com" || hostname === "www.perplexity.ai" || hostname === "perplexity.ai" || hostname.endsWith(".perplexity.ai");
255
- if (needsStealth) {
256
- const raw = await cdp([
257
- "evalraw",
258
- anchor,
259
- "Target.createTarget",
260
- JSON.stringify({ url: "about:blank" })
261
- ]);
262
- const { targetId } = JSON.parse(raw);
263
- const tid = targetId.slice(0, 8);
264
- await cdp(["list"]).catch(() => null);
265
- if (hostname === "copilot.microsoft.com") {
266
- await injectHeadlessStealth(tid);
267
- } else {
268
- injectHeadlessStealth(tid).catch(() => {});
269
- }
270
- await cdp(["list"]).catch(() => null);
271
- return targetId;
272
- }
273
- const raw = await cdp([
274
- "evalraw",
275
- anchor,
276
- "Target.createTarget",
277
- JSON.stringify({ url })
278
- ]);
279
- const { targetId } = JSON.parse(raw);
280
- await cdp(["list"]).catch(() => null);
281
- return targetId;
282
- }
283
- export async function activateTab(targetId) {
284
- try {
285
- const anchor = await getAnyTab();
286
- await cdp([
287
- "evalraw",
288
- anchor,
289
- "Target.activateTarget",
290
- JSON.stringify({ targetId })
291
- ]);
292
- } catch {}
293
- }
294
- export async function closeTab(targetId) {
295
- try {
296
- const anchor = await getAnyTab();
297
- await cdp([
298
- "evalraw",
299
- anchor,
300
- "Target.closeTarget",
301
- JSON.stringify({ targetId })
302
- ]);
303
- } catch {}
304
- }
305
- export async function closeTabs(targetIds = []) {
306
- await Promise.all(targetIds.filter(Boolean).map((tid) => closeTab(tid).catch(() => {})));
307
- if (targetIds.length > 0) {
308
- await cdp(["list"]).catch(() => null);
309
- }
310
- }
311
- export function getFullTabFromCache(engine, engineDomains) {
312
- try {
313
- if (!existsSync(PAGES_CACHE))
314
- return null;
315
- const pages = JSON.parse(readFileSync(PAGES_CACHE, "utf8"));
316
- const found = pages.find((p) => p.url.includes(engineDomains[engine]));
317
- return found ? found.targetId : null;
318
- } catch {
319
- return null;
320
- }
321
- }
322
- export function probeGreedyChrome(timeoutMs = 3000) {
323
- return new Promise((resolve) => {
324
- const req = http.get(`http://localhost:${GREEDY_PORT}/json/version`, (res) => {
325
- res.resume();
326
- resolve(res.statusCode === 200);
327
- });
328
- req.on("error", () => resolve(false));
329
- req.setTimeout(timeoutMs, () => {
330
- req.destroy();
331
- resolve(false);
332
- });
333
- });
334
- }
335
- async function waitForPortDown(timeoutMs = 3000, intervalMs = 200) {
336
- const deadline = Date.now() + timeoutMs;
337
- while (Date.now() < deadline) {
338
- if (!await probeGreedyChrome(300))
339
- return true;
340
- await new Promise((r) => setTimeout(r, intervalMs));
341
- }
342
- return !await probeGreedyChrome(300);
343
- }
344
- export async function refreshPortFile() {
345
- const LOCK_FILE = `${ACTIVE_PORT_FILE}.lock`;
346
- const TEMP_FILE = `${ACTIVE_PORT_FILE}.tmp`;
347
- const LOCK_STALE_MS = 5000;
348
- const LOCK_WAIT_MS = 1000;
349
- const lockAcquired = await new Promise((resolve) => {
350
- const start = Date.now();
351
- const tryLock = () => {
352
- try {
353
- const payload = JSON.stringify({ pid: process.pid, ts: Date.now() });
354
- writeFileSync(LOCK_FILE, payload, { encoding: "utf8", flag: "wx" });
355
- resolve(true);
356
- } catch (e) {
357
- if (e?.code !== "EEXIST") {
358
- if (Date.now() - start < LOCK_WAIT_MS) {
359
- setTimeout(tryLock, 50);
360
- } else {
361
- resolve(false);
362
- }
363
- return;
364
- }
365
- try {
366
- const lockRaw = readFileSync(LOCK_FILE, "utf8").trim();
367
- const parsed = lockRaw.startsWith("{") ? JSON.parse(lockRaw) : { ts: Number(lockRaw) };
368
- const lockTime = Number(parsed?.ts) || 0;
369
- if (lockTime > 0 && Date.now() - lockTime > LOCK_STALE_MS) {
370
- try {
371
- unlinkSync(LOCK_FILE);
372
- } catch {}
373
- }
374
- if (Date.now() - start < LOCK_WAIT_MS) {
375
- setTimeout(tryLock, 50);
376
- } else {
377
- resolve(false);
378
- }
379
- } catch {
380
- if (Date.now() - start < LOCK_WAIT_MS) {
381
- setTimeout(tryLock, 50);
382
- } else {
383
- resolve(false);
384
- }
385
- }
386
- }
387
- };
388
- tryLock();
389
- });
390
- try {
391
- const body = await new Promise((res, rej) => {
392
- const req = http.get(`http://localhost:${GREEDY_PORT}/json/version`, (r) => {
393
- let b = "";
394
- r.on("data", (d) => b += d);
395
- r.on("end", () => res(b));
396
- });
397
- req.on("error", rej);
398
- req.setTimeout(3000, () => {
399
- req.destroy();
400
- rej(new Error("timeout"));
401
- });
402
- });
403
- const { webSocketDebuggerUrl } = JSON.parse(body);
404
- const wsPath = new URL(webSocketDebuggerUrl).pathname;
405
- if (lockAcquired) {
406
- writeFileSync(TEMP_FILE, `${GREEDY_PORT}
407
- ${wsPath}`, "utf8");
408
- try {
409
- unlinkSync(ACTIVE_PORT_FILE);
410
- } catch {}
411
- renameSync(TEMP_FILE, ACTIVE_PORT_FILE);
412
- }
413
- } catch {} finally {
414
- if (lockAcquired) {
415
- try {
416
- unlinkSync(LOCK_FILE);
417
- } catch {}
418
- }
419
- }
420
- }
421
- export async function ensureChrome() {
422
- if (process.env.GREEDY_SEARCH_RESEARCH_CHILD && await probeGreedyChrome()) {
423
- await refreshPortFile();
424
- try {
425
- const md = readMetadata();
426
- if (md) {
427
- touchActivityBL(md);
428
- registerClient(md);
429
- }
430
- } catch {}
431
- return;
432
- }
433
- cleanupStaleSessions();
434
- const wasKilled = await checkAndKillIdle();
435
- let ready = wasKilled ? false : await probeGreedyChrome();
436
- if (!ready && !wasKilled) {
437
- await new Promise((r) => setTimeout(r, 500));
438
- ready = await probeGreedyChrome();
439
- }
440
- let forceRelaunch = false;
441
- if (ready) {
442
- const headless = isChromeHeadless();
443
- const wantsVisible = process.env.GREEDY_SEARCH_VISIBLE === "1";
444
- if (!wantsVisible && !headless) {
445
- process.stderr.write(`[greedysearch] Visible Chrome detected — switching to headless mode...
446
- `);
447
- await killHeadlessChrome();
448
- await waitForPortDown();
449
- forceRelaunch = true;
450
- } else if (wantsVisible && headless) {
451
- process.stderr.write(`[greedysearch] Headless Chrome detected — switching to visible mode...
452
- `);
453
- await killHeadlessChrome();
454
- await waitForPortDown();
455
- forceRelaunch = true;
456
- }
457
- }
458
- const readyAfterModeCheck = forceRelaunch ? false : await probeGreedyChrome();
459
- if (readyAfterModeCheck) {
460
- await refreshPortFile();
461
- try {
462
- const md = readMetadata();
463
- if (md) {
464
- touchActivityBL(md);
465
- registerClient(md);
466
- }
467
- } catch {}
468
- return;
469
- }
470
- const lock = acquireLaunchLock();
471
- if (!lock.acquired) {
472
- const deadline = Date.now() + 12000;
473
- let reReady = false;
474
- while (Date.now() < deadline) {
475
- reReady = await probeGreedyChrome(500);
476
- if (reReady)
477
- break;
478
- await new Promise((r) => setTimeout(r, 250));
479
- }
480
- if (reReady) {
481
- await refreshPortFile();
482
- return;
483
- }
484
- }
485
- try {
486
- const reCheck = await probeGreedyChrome(1000);
487
- if (reCheck) {
488
- await refreshPortFile();
489
- return;
490
- }
491
- process.stderr.write(`GreedySearch Chrome not running on port ${GREEDY_PORT} — auto-launching...
492
- `);
493
- const launchScript = resolveGreedySearchLaunchScript({
494
- moduleDir: __dir,
495
- entrypoint: process.argv[1],
496
- env: process.env
497
- });
498
- const launchArgs = [launchScript];
499
- if (process.env.GREEDY_SEARCH_VISIBLE !== "1")
500
- launchArgs.push("--headless");
501
- await new Promise((resolve, reject) => {
502
- const proc = spawn(nodeRuntimeCommand(), launchArgs, {
503
- stdio: ["ignore", process.stderr, process.stderr]
504
- });
505
- proc.on("close", (code) => code === 0 ? resolve() : reject(new Error("launch.mjs failed")));
506
- });
507
- } finally {
508
- lock.release();
509
- }
510
- }
@@ -1,10 +0,0 @@
1
- export const DEFAULTS = {
2
- CDP_TIMEOUT: 30000,
3
- CDP_TIMEOUT_SHORT: 15000,
4
- NAV_TIMEOUT: 35000,
5
- STREAM_TIMEOUT: 30000,
6
- COPY_TIMEOUT: 60000,
7
- CODING_TASK_TIMEOUT: 180000,
8
- MAX_SOURCE_FETCH: 10,
9
- DESCRIPTION_MAX_LENGTH: 300
10
- };
@@ -1,79 +0,0 @@
1
- import { spawn } from "node:child_process";
2
- import { nodeRuntimeCommand } from "../utils/node-runtime.mjs";
3
- import { ENGINES, GREEDY_PROFILE_DIR } from "./constants.mjs";
4
- import {
5
- moduleDirectory,
6
- resolveGreedySearchExtractorScript
7
- } from "./paths.mjs";
8
-
9
- export { ENGINES };
10
- const __dir = moduleDirectory(import.meta.url);
11
- export function runExtractor(script, query, tabPrefix = null, short = false, timeoutMs = null, locale = null) {
12
- if (timeoutMs === null) {
13
- timeoutMs = script.includes("logically") ? 120000 : script.includes("chatgpt") ? 80000 : script.includes("gemini") ? 70000 : 60000;
14
- }
15
- const extraArgs = [
16
- ...tabPrefix ? ["--tab", tabPrefix] : [],
17
- ...short ? ["--short"] : [],
18
- ...locale ? ["--locale", locale] : []
19
- ];
20
- return new Promise((resolve, reject) => {
21
- const extractorScript = resolveGreedySearchExtractorScript(script, {
22
- moduleDir: __dir
23
- });
24
- const proc = spawn(nodeRuntimeCommand(), [extractorScript, "--stdin", ...extraArgs], {
25
- stdio: ["pipe", "pipe", "pipe"],
26
- env: { ...process.env, CDP_PROFILE_DIR: GREEDY_PROFILE_DIR }
27
- });
28
- proc.stdin.write(query);
29
- proc.stdin.end();
30
- let out = "";
31
- let err = "";
32
- proc.stdout.on("data", (d) => out += d);
33
- proc.stderr.on("data", (d) => {
34
- err += d;
35
- if (process.env.GREEDY_SEARCH_CHILD_STDERR !== "0") {
36
- process.stderr.write(d);
37
- }
38
- });
39
- const t = setTimeout(() => {
40
- proc.kill();
41
- const tailLines = (s, n = 20) => String(s ?? "").split(/\r?\n/).filter(Boolean).slice(-n).join(`
42
- `);
43
- let envelope = null;
44
- try {
45
- const parsed = JSON.parse(out.trim());
46
- if (parsed._envelope)
47
- envelope = parsed._envelope;
48
- } catch {}
49
- const errObj = new Error(`${script} timed out after ${timeoutMs / 1000}s` + (envelope?.lastStage ? ` (last stage: ${envelope.lastStage})` : ""));
50
- errObj.engineScript = script;
51
- errObj.lastStage = envelope?.lastStage || null;
52
- errObj.partialErr = tailLines(err);
53
- errObj.partialOut = tailLines(out);
54
- reject(errObj);
55
- }, timeoutMs);
56
- proc.on("close", (code) => {
57
- clearTimeout(t);
58
- if (code === 0) {
59
- try {
60
- resolve(JSON.parse(out.trim()));
61
- } catch {
62
- reject(new Error(`bad JSON from ${script}: ${out.slice(0, 100)}`));
63
- }
64
- } else {
65
- let envelope = null;
66
- try {
67
- const parsed = JSON.parse(out.trim());
68
- if (parsed._envelope)
69
- envelope = parsed._envelope;
70
- } catch {}
71
- const msg = err.trim() || `extractor exit ${code}`;
72
- const errObj = new Error(msg);
73
- if (envelope)
74
- errObj.envelope = envelope;
75
- reject(errObj);
76
- }
77
- });
78
- });
79
- }