@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,827 +1,418 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
`)}}}catch{}return Je}var Fe={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"},pe=Ln(),Tt=pe,tc=Un(),rc=Math.max(1,Number.parseInt(process.env.GREEDY_FETCH_CONCURRENCY||"5",10)||5);process.env.CDP_PROFILE_DIR=k;var Gn=["fbclid","gclid","ref","ref_src","ref_url","source","utm_campaign","utm_content","utm_medium","utm_source","utm_term"],Fn=["dev.to","hashnode.com","medium.com","reddit.com","stackoverflow.com","stackexchange.com","substack.com"],Hn=["arstechnica.com","techcrunch.com","theverge.com","venturebeat.com","wired.com","zdnet.com"],Mt=["facebook.com","instagram.com","linkedin.com","pinterest.com","tiktok.com","twitter.com","x.com"];function te(e="",t=240){let r=String(e).replaceAll(/\s+/g," ").trim();if(r.length<=t)return r;let n=r.slice(0,t),i=n.lastIndexOf(" ");return i>0?`${n.slice(0,i)}...`:`${n}...`}function Ye(e=""){let t=te(e,180);if(!t)return"";if(/^https?:\/\//i.test(t))return"";let r=t.split(/\s+/).filter(Boolean).length,n=/[A-Z]/.test(t),i=/\d/.test(t);return t===t.toLowerCase()&&r<=4&&!n&&!i?"":t}function We(e="",t=""){let r=Ye(e),n=Ye(t);if(!n)return r;if(!r)return n;let i=/^https?:\/\//i.test(r),a=/^https?:\/\//i.test(n);if(i&&!a)return n;if(!i&&a)return r;return n.length>r.length?n:r}function ge(e){if(!e)return null;try{let t=new URL(e);if(!["http:","https:"].includes(t.protocol))return null;if(t.hash="",t.hostname=t.hostname.toLowerCase(),t.protocol==="https:"&&t.port==="443"||t.protocol==="http:"&&t.port==="80")t.port="";for(let i of[...t.searchParams.keys()]){let a=i.toLowerCase();if(Gn.includes(a)||a.startsWith("utm_"))t.searchParams.delete(i)}t.searchParams.sort();let r=t.pathname.replace(/\/{1,10}$/,"")||"/";t.pathname=r;let n=t.toString();return r==="/"?n.replace(/\/$/,""):n}catch{return null}}function qn(e){try{return new URL(e).hostname.toLowerCase().replace(/^www\./,"")}catch{return""}}function oe(e,t){return t.some((r)=>e===r||e.endsWith(`.${r}`))}function Jn(e,t="",r=""){let n=t.toLowerCase(),i=r.toLowerCase();if(e==="github.com"||e==="gitlab.com")return"repo";if(e==="arxiv.org"||e==="doi.org"||e==="semanticscholar.org"||e.endsWith(".semanticscholar.org")||i.includes("/paper/")||i.includes("/pdf/"))return"academic";if(oe(e,Mt))return"social";if(oe(e,Fn))return"community";if(oe(e,Hn))return"news";if(e.startsWith("docs.")||e.startsWith("developer.")||e.startsWith("developers.")||e.startsWith("api.")||n.includes("documentation")||n.includes("docs")||n.includes("reference")||i.includes("/docs/")||i.includes("/reference/")||i.includes("/api/"))return"official-docs";if(e.startsWith("blog.")||i.includes("/blog/"))return"maintainer-blog";return"website"}function Yn(e){switch(e){case"official-docs":return 5;case"repo":return 4;case"academic":return 4;case"maintainer-blog":return 3;case"website":return 2;case"community":return 1;case"news":return 0;case"social":return-6;default:return 0}}function Wn(e){let t=Object.values(e.perEngine||{}).map((r)=>r?.rank||99);return t.length?Math.min(...t):99}var Bn=["reddit.com","news.ycombinator.com","lobste.rs"];function he(e){return e.smartScore*3+e.engineCount*5+Yn(e.sourceType)*2+Math.max(0,7-Wn(e))}function Qn(e){let t=e.toLowerCase(),r=[];if(t.includes("openai")||t.includes("gpt")||t.includes("chatgpt"))r.push("openai.com","platform.openai.com","help.openai.com");if(t.includes("anthropic")||t.includes("claude"))r.push("anthropic.com","docs.anthropic.com");if(t.includes("bun"))r.push("bun.sh","bun.com");if(t.includes("next.js")||t.includes("nextjs"))r.push("nextjs.org","vercel.com");if(t.includes("playwright"))r.push("playwright.dev");if(t.includes("supabase"))r.push("supabase.com","supabase.io");if(t.includes("prisma"))r.push("prisma.io");if(t.includes("tailwind"))r.push("tailwindcss.com");if(t.includes("vite"))r.push("vitejs.dev","vite.dev");if(t.includes("astro"))r.push("astro.build");if(t.includes("svelte"))r.push("svelte.dev");if(t.includes("solid"))r.push("solidjs.com");if(t.includes("vue")||t.includes("nuxt"))r.push("vuejs.org","nuxt.com");if(t.includes("react")||t.includes("react native"))r.push("react.dev","reactnative.dev");if(t.includes("angular"))r.push("angular.io","angular.dev");if(t.includes("node.js")||t.includes("nodejs"))r.push("nodejs.org","nodejs.dev","npmjs.com");if(/\bgo\b/.test(t)||t.includes("golang"))r.push("go.dev","golang.org","pkg.go.dev");if(t.includes("deno"))r.push("deno.land","deno.com");if(t.includes("fresh"))r.push("fresh.deno.dev");if(t.includes("typescript")||t.includes("ts"))r.push("typescriptlang.org");if(t.includes("python"))r.push("python.org","docs.python.org");if(t.includes("rust"))r.push("rust-lang.org","docs.rs","crates.io");if(t.includes("zig"))r.push("ziglang.org");if(t.includes("docker"))r.push("docker.com","docs.docker.com","hub.docker.com");if(t.includes("kubernetes")||t.includes("k8s"))r.push("kubernetes.io","k8s.io");if(t.includes("postgres")||t.includes("postgresql"))r.push("postgresql.org","neon.tech","supabase.com");if(t.includes("redis"))r.push("redis.io");if(t.includes("sqlite"))r.push("sqlite.org");if(t.includes("cloudflare"))r.push("developers.cloudflare.com","cloudflare.com");if(t.includes("vercel"))r.push("vercel.com","nextjs.org");if(t.includes("netlify"))r.push("netlify.com","docs.netlify.com");if(t.includes("stripe"))r.push("stripe.com","docs.stripe.com");if(t.includes("github"))r.push("github.com","docs.github.com");if(t.includes("gitlab"))r.push("gitlab.com","docs.gitlab.com");if(t.includes("aws"))r.push("aws.amazon.com","docs.aws.amazon.com");if(t.includes("azure"))r.push("azure.microsoft.com","learn.microsoft.com");if(t.includes("gcp")||t.includes("google cloud"))r.push("cloud.google.com","developers.google.com");if(t.includes("gemini")||t.includes("google ai"))r.push("ai.google.dev","developers.google.com");for(let n of Mt){let i=n.replace(/\.com$/,"");if(t.includes(i))r.push(n)}return[...new Set(r)]}function Lt(e,t){return e===t||e.endsWith(`.${t}`)}function Be(e,t=""){let r=new Map,n=Object.keys(e||{}).filter((c)=>!c.startsWith("_")),i=Qn(t);for(let c of n){let u=e[c];if(!u?.sources)continue;for(let d=0;d<u.sources.length;d++){let p=u.sources[d],f=ge(p.url);if(!f||f.length<10)continue;let m=Ye(p.title||""),h=qn(f),g=Jn(h,m,f),y=0;if(i.some((E)=>Lt(h,E)))y+=10;if(g==="official-docs")y+=3;let v=f.toLowerCase();if(/\/docs\/|\/documentation\/|\.dev\/|\/api\/|\/reference\//.test(v))y+=2;let b=i.some((E)=>Lt(h,E));if(g==="social"&&!b)y-=20;if(i.length>0){if(oe(h,Bn))y-=3;else if(g==="community"&&!oe(h,["stackoverflow.com","stackexchange.com"]))y-=1}let w=r.get(f)||{id:"",canonicalUrl:f,displayUrl:p.url||f,domain:h,title:"",engines:[],engineCount:0,perEngine:{},sourceType:g,isOfficial:g==="official-docs",smartScore:0};if(w.title=We(w.title,m),w.displayUrl=w.displayUrl||p.url||f,w.sourceType=w.sourceType||g,w.isOfficial=w.isOfficial||g==="official-docs",w.smartScore=Math.max(w.smartScore,y),!w.engines.includes(c))w.engines.push(c);w.perEngine[c]={rank:d+1,title:We(w.perEngine[c]?.title||"",m)},r.set(f,w)}}let a=Array.from(r.values()).map((c)=>({...c,engineCount:c.engines.length})),o=a.filter((c)=>c.sourceType!=="social"),s=a.filter((c)=>c.sourceType==="social");return o.sort((c,u)=>{let d=he(u)-he(c);if(d!==0)return d;return c.domain.localeCompare(u.domain)}),s.sort((c,u)=>{let d=he(u)-he(c);if(d!==0)return d;return c.domain.localeCompare(u.domain)}),[...o,...s].slice(0,12).map((c,u)=>({...c,id:`S${u+1}`,title:c.title||c.domain||c.canonicalUrl}))}function Ut(e,t){let r=new Map(t.map((n)=>[n.id,n]));return e.map((n)=>{let i=r.get(n.id);if(!i)return n;let a=We(n.title,i.title||"");return{...n,title:a||n.title,fetch:{attempted:!0,ok:!i.error&&i.contentChars>100,status:i.status||null,finalUrl:i.finalUrl||i.url||n.canonicalUrl,contentType:i.contentType||"",lastModified:i.lastModified||"",publishedTime:i.publishedTime||"",byline:i.byline||"",siteName:i.siteName||"",lang:i.lang||"",title:i.title||"",snippet:i.snippet||"",contentChars:i.contentChars||0,source:i.source||"unknown",duration:i.duration||0,error:i.error||""}}})}import{createRequire as Kn}from"node:module";import{mkdirSync as Xn,writeFileSync as ei}from"node:fs";import{join as nr}from"node:path";import{createRequire as ni}from"node:module";import{createRequire as ii}from"node:module";import{spawn as ai}from"node:child_process";import{basename as oi}from"node:path";import{dirname as si,join as li}from"node:path";import{fileURLToPath as ci}from"node:url";import{fileURLToPath as ui}from"node:url";import{existsSync as $e,mkdirSync as di,readFileSync as or,writeFileSync as fi}from"node:fs";import{homedir as pi}from"node:os";import{join as Gt}from"node:path";import{tmpdir as hi}from"node:os";import{existsSync as _e,mkdirSync as gi,readFileSync as sr,writeFileSync as mi}from"node:fs";import{homedir as yi}from"node:os";import{join as Ft}from"node:path";import{tmpdir as wi}from"node:os";import{existsSync as Ee,mkdirSync as bi,readFileSync as lr,writeFileSync as vi}from"node:fs";import{homedir as $i}from"node:os";import{join as Ht}from"node:path";import{tmpdir as _i}from"node:os";import{basename as ro}from"node:path";import{mkdirSync as Qe,writeFileSync as C}from"node:fs";import{join as _}from"node:path";import{fileURLToPath as io}from"node:url";import{existsSync as Oe,mkdirSync as oo,readFileSync as Or,writeFileSync as so}from"node:fs";import{homedir as lo}from"node:os";import{join as Nr}from"node:path";import{tmpdir as co}from"node:os";import{spawn as wo}from"node:child_process";import{existsSync as xr}from"node:fs";import{dirname as bo,join as ye}from"node:path";import{fileURLToPath as vo}from"node:url";import{join as ko}from"node:path";import{fileURLToPath as Oo}from"node:url";var Vn=Object.defineProperty,zn=(e)=>e;function Zn(e,t){this[e]=zn.bind(null,t)}var ut=(e,t)=>{for(var r in t)Vn(e,r,{get:t[r],enumerable:!0,configurable:!0,set:Zn.bind(t,r)})},dt=(e,t)=>()=>(e&&(t=e(e=0)),t),oc=Kn(import.meta.url),rr={};ut(rr,{writeSourcesToFiles:()=>ti});function ti(e,t=ir){return Xn(t,{recursive:!0}),e.map((r)=>{if(!r.content||r.content.length<10)return r;let n=String(r.id||"unknown").replace(/[^a-zA-Z0-9_-]/g,""),i=(r.canonicalUrl||r.url||"").replace(/^https?:\/\//,"").replace(/[^a-zA-Z0-9]/g,"-").slice(0,40),a=`${n}-${i}.md`,o=nr(t,a),s=`---
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
## Comments
|
|
43
|
-
|
|
44
|
-
`;let i=t.data.children.filter((a)=>a.kind==="t1").slice(0,10);for(let a of i)n+=fr(a.data,0),n+=`
|
|
45
|
-
`}if(n.length>r)n=n.slice(0,r).trim()+`
|
|
46
|
-
|
|
47
|
-
... (truncated)`;return n}function fr(e,t){if(!e||e.body==="[deleted]"||e.body==="[removed]")return"";let r="> ".repeat(t),n="";if(n+=`${r}**u/${e.author}** (${e.score} pts)
|
|
48
|
-
`,n+=`${r}${e.body.replaceAll(`
|
|
49
|
-
`,`
|
|
50
|
-
`+r)}
|
|
51
|
-
`,t<3&&e.replies?.data?.children){let i=e.replies.data.children.filter((a)=>a.kind==="t1");for(let a of i.slice(0,5))n+=`
|
|
52
|
-
`+fr(a.data,t+1)}return n}function re(e,t=8000){if(!e||e.length<=t)return e;let r=`
|
|
53
|
-
|
|
54
|
-
[...content trimmed...]
|
|
55
|
-
|
|
56
|
-
`,n=t-r.length,i=Math.floor(n*0.75),a=n-i,o=i;while(o>i-100&&e[o]!==`
|
|
57
|
-
`)o--;if(o<=i-100)o=i;let s=e.length-a;while(s<e.length-a+100&&e[s]!==`
|
|
58
|
-
`)s++;if(s>=e.length-a+100)s=e.length-a;let l=e.slice(0,o).trimEnd(),c=e.slice(s).trimStart();return`${l}${r}${c}`}function Li(e=process.env,t=process.execPath){let r=e.GREEDY_SEARCH_NODE||e.NODE_BINARY||e.NODE;if(r?.trim())return r.trim();let n=oi(t||"").toLowerCase();if(n==="node"||n==="node.exe")return t;return"node"}function Mi(e){if(!Array.isArray(e)||e.length===0)throw Error("cdp: args must be a non-empty array");if(e[0]==="test")return e.map((t,r)=>Bt(t,r));if(!Cr.has(e[0]))throw Error(`cdp: unknown subcommand '${e[0]}'`);return e.map((t,r)=>Bt(t,r))}function Bt(e,t){if(typeof e!=="string")throw Error(`cdp: argv[${t}] must be a string (got ${typeof e})`);if(e.includes("\x00"))throw Error(`cdp: argv[${t}] contains a null byte`);return e}function pr(e,t=30000){return Ui(e,null,t)}function Ui(e,t=null,r=30000){let n=Mi(e);return new Promise((i,a)=>{let o=ai(Li(),[Ar,...n],{stdio:[t==null?"ignore":"pipe","pipe","pipe"]});if(t!=null)o.stdin.write(t),o.stdin.end();let s="",l="";o.stdout.on("data",(u)=>s+=u),o.stderr.on("data",(u)=>l+=u);let c=setTimeout(()=>{o.kill(),a(Error(`cdp timeout: ${e[0]}`))},r);o.on("close",(u)=>{if(clearTimeout(c),u===0)i(s.trim());else a(Error(l.trim()||`cdp exit ${u}`))})})}async function Qt(e){await pr(["evalraw",e,"Page.addScriptToEvaluateOnNewDocument",JSON.stringify({source:`
|
|
59
|
-
(function() {
|
|
60
|
-
// ── Runtime.enable / CDP detection masking ──────────────
|
|
61
|
-
try { delete window.__REBROWSER_RUNTIME_ENABLE; } catch(_) {}
|
|
62
|
-
try { delete window.__REBROWSER_DEVTOOLS; } catch(_) {}
|
|
63
|
-
try { delete window.__nightmare; } catch(_) {}
|
|
64
|
-
try { delete window.__phantom; } catch(_) {}
|
|
65
|
-
try { delete window.callPhantom; } catch(_) {}
|
|
66
|
-
try { delete window._phantom; } catch(_) {}
|
|
67
|
-
try { delete window.Buffer; } catch(_) {}
|
|
68
|
-
|
|
69
|
-
// Real Chrome without automation should not expose navigator.webdriver at all.
|
|
70
|
-
// A literal false or an own-property getter returning undefined is itself a
|
|
71
|
-
// common stealth tell; remove both instance and prototype properties when the
|
|
72
|
-
// descriptor is configurable (as it is with --disable-blink-features).
|
|
73
|
-
try { delete navigator.webdriver; } catch(_) {}
|
|
74
|
-
try { delete Navigator.prototype.webdriver; } catch(_) {}
|
|
75
|
-
Object.defineProperty(navigator, 'vendor', { get: () => 'Google Inc.', configurable: true });
|
|
76
|
-
Object.defineProperty(navigator, 'platform', { get: () => 'Win32', configurable: true });
|
|
77
|
-
Object.defineProperty(navigator, 'maxTouchPoints', { get: () => 0, configurable: true });
|
|
78
|
-
Object.defineProperty(navigator, 'pdfViewerEnabled', { get: () => true, configurable: true });
|
|
79
|
-
Object.defineProperty(navigator, 'productSub', { get: () => '20030107', configurable: true });
|
|
80
|
-
Object.defineProperty(navigator, 'product', { get: () => 'Gecko', configurable: true });
|
|
81
|
-
var __greedyMimeTypes = null;
|
|
82
|
-
function __makeMimeTypes() {
|
|
83
|
-
var pdf = { type: 'application/pdf', suffixes: 'pdf', description: 'Portable Document Format', enabledPlugin: null };
|
|
84
|
-
var textPdf = { type: 'text/pdf', suffixes: 'pdf', description: 'Portable Document Format', enabledPlugin: null };
|
|
85
|
-
try { Object.setPrototypeOf(pdf, MimeType.prototype); } catch(_) {}
|
|
86
|
-
try { Object.setPrototypeOf(textPdf, MimeType.prototype); } catch(_) {}
|
|
87
|
-
var m = [pdf, textPdf];
|
|
88
|
-
try { Object.setPrototypeOf(m, MimeTypeArray.prototype); } catch(_) {}
|
|
89
|
-
m.item = function item(i) { return this[i] || null; };
|
|
90
|
-
m.namedItem = function namedItem(name) { return Array.prototype.find.call(this, function(x) { return x && x.type === name; }) || null; };
|
|
91
|
-
return m;
|
|
1
|
+
import { ALL_ENGINES, RESEARCH_ENGINES } from "./constants.mjs";
|
|
2
|
+
import {
|
|
3
|
+
buildSourceRegistry,
|
|
4
|
+
mergeFetchDataIntoSources,
|
|
5
|
+
normalizeUrl,
|
|
6
|
+
trimText
|
|
7
|
+
} from "./sources.mjs";
|
|
8
|
+
import {
|
|
9
|
+
auditCitations,
|
|
10
|
+
buildFinalReportPrompt,
|
|
11
|
+
buildSynthesisFromEvidencePrompt,
|
|
12
|
+
computeResearchFloor,
|
|
13
|
+
createQuestionLedger,
|
|
14
|
+
extractEvidenceFromSources,
|
|
15
|
+
reconcileQuestionsFromSynthesis,
|
|
16
|
+
runCitationUrlCheck,
|
|
17
|
+
writeResearchBundle
|
|
18
|
+
} from "./research.mjs";
|
|
19
|
+
import { parseStructuredJson } from "./synthesis.mjs";
|
|
20
|
+
import { writeSourcesToFiles } from "./file-sources.mjs";
|
|
21
|
+
import { fetchMultipleSources } from "./fetch-source.mjs";
|
|
22
|
+
import { runGeminiPrompt } from "./synthesis-runner.mjs";
|
|
23
|
+
import { createProgressTracker } from "./progress.mjs";
|
|
24
|
+
import { spawn } from "node:child_process";
|
|
25
|
+
import { nodeRuntimeCommand } from "../utils/node-runtime.mjs";
|
|
26
|
+
import { join } from "node:path";
|
|
27
|
+
import { fileURLToPath } from "node:url";
|
|
28
|
+
const __dir = fileURLToPath(new URL(".", import.meta.url)).replace(/^\/([A-Z]:)/, "$1");
|
|
29
|
+
const SEARCH_BIN = join(__dir, "..", "..", "bin", "search.mjs");
|
|
30
|
+
function uniqueStrings(items, limit = 1 / 0) {
|
|
31
|
+
const seen = new Set;
|
|
32
|
+
const out = [];
|
|
33
|
+
for (const item of items || []) {
|
|
34
|
+
const clean = trimText(String(item || ""), 1000);
|
|
35
|
+
if (!clean || seen.has(clean))
|
|
36
|
+
continue;
|
|
37
|
+
seen.add(clean);
|
|
38
|
+
out.push(clean);
|
|
39
|
+
if (out.length >= limit)
|
|
40
|
+
break;
|
|
92
41
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
return p;
|
|
112
|
-
},
|
|
113
|
-
configurable: true,
|
|
114
|
-
});
|
|
115
|
-
Object.defineProperty(navigator, 'mimeTypes', {
|
|
116
|
-
get: () => {
|
|
117
|
-
__greedyMimeTypes = __greedyMimeTypes || __makeMimeTypes();
|
|
118
|
-
return __greedyMimeTypes;
|
|
119
|
-
},
|
|
120
|
-
configurable: true,
|
|
121
|
-
});
|
|
122
|
-
Object.defineProperty(navigator, 'languages', { get: () => ['en-US', 'en'], configurable: true });
|
|
123
|
-
try {
|
|
124
|
-
Object.defineProperty(navigator, 'connection', { get: () => ({ effectiveType: '4g', rtt: 50, downlink: 10, downlinkMax: Infinity, saveData: false }), configurable: true });
|
|
125
|
-
} catch(_) {}
|
|
126
|
-
if (!navigator.mediaDevices) {
|
|
127
|
-
Object.defineProperty(navigator, 'mediaDevices', {
|
|
128
|
-
get: () => ({
|
|
129
|
-
enumerateDevices: () => Promise.resolve([
|
|
130
|
-
{ deviceId: 'default', kind: 'audioinput', label: '', groupId: 'default' },
|
|
131
|
-
{ deviceId: 'default', kind: 'audiooutput', label: '', groupId: 'default' },
|
|
132
|
-
{ deviceId: '', kind: 'videoinput', label: '', groupId: '' },
|
|
133
|
-
]),
|
|
134
|
-
getUserMedia: () => Promise.reject(new DOMException('NotAllowedError')),
|
|
135
|
-
getDisplayMedia: () => Promise.reject(new DOMException('NotAllowedError')),
|
|
136
|
-
}),
|
|
137
|
-
configurable: true,
|
|
138
|
-
});
|
|
42
|
+
return out;
|
|
43
|
+
}
|
|
44
|
+
export function buildSearchAngles(query) {
|
|
45
|
+
const trimmed = String(query || "").trim();
|
|
46
|
+
if (!trimmed)
|
|
47
|
+
return [];
|
|
48
|
+
return [
|
|
49
|
+
`${trimmed} — definition and overview`,
|
|
50
|
+
`${trimmed} — how it works, mechanism, or key details`,
|
|
51
|
+
`${trimmed} — current usage, comparison, or best practices`
|
|
52
|
+
];
|
|
53
|
+
}
|
|
54
|
+
export function mergeSourcesByUrl(existing, incoming) {
|
|
55
|
+
const urlMap = new Map;
|
|
56
|
+
for (const s of existing || []) {
|
|
57
|
+
const key = s?.canonicalUrl || s?.finalUrl || s?.url;
|
|
58
|
+
if (key)
|
|
59
|
+
urlMap.set(key, s);
|
|
139
60
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
if (!
|
|
143
|
-
|
|
61
|
+
for (const s of incoming || []) {
|
|
62
|
+
const key = s?.canonicalUrl || s?.finalUrl || s?.url;
|
|
63
|
+
if (!key)
|
|
64
|
+
continue;
|
|
65
|
+
if (urlMap.has(key)) {
|
|
66
|
+
const merged = {
|
|
67
|
+
...urlMap.get(key),
|
|
68
|
+
angles: [
|
|
69
|
+
...urlMap.get(key).angles || [urlMap.get(key).query || ""],
|
|
70
|
+
s.query || ""
|
|
71
|
+
]
|
|
72
|
+
};
|
|
73
|
+
urlMap.set(key, merged);
|
|
74
|
+
} else {
|
|
75
|
+
urlMap.set(key, s);
|
|
144
76
|
}
|
|
145
|
-
} catch(_) {}
|
|
146
|
-
try {
|
|
147
|
-
if (!navigator.contentIndex) {
|
|
148
|
-
Object.defineProperty(navigator, 'contentIndex', { get: () => ({ add: function() {}, delete: function() {}, getAll: function() { return Promise.resolve([]); } }), configurable: true });
|
|
149
|
-
}
|
|
150
|
-
} catch(_) {}
|
|
151
|
-
|
|
152
|
-
if (!window.chrome) {
|
|
153
|
-
window.chrome = {
|
|
154
|
-
app: { isInstalled: false, InstallState: {}, RunningState: {} },
|
|
155
|
-
runtime: {
|
|
156
|
-
OnInstalledReason: {}, OnRestartRequiredReason: {}, PlatformArch: {}, PlatformNaclArch: {}, PlatformOs: {}, RequestUpdateCheckStatus: {},
|
|
157
|
-
connect: () => ({}), sendMessage: () => {}, onMessage: { addListener: () => {} }
|
|
158
|
-
},
|
|
159
|
-
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' }; },
|
|
160
|
-
csi: function() { var t = Date.now(); return { onloadT: t - 2000, startE: t - 5000, pageT: 'back', tran: 2 }; },
|
|
161
|
-
};
|
|
162
77
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
78
|
+
return Array.from(urlMap.values());
|
|
79
|
+
}
|
|
80
|
+
const _enginePattern = ALL_ENGINES.join("|");
|
|
81
|
+
const _engineRegex = new RegExp(`^\\[(${_enginePattern})\\]`);
|
|
82
|
+
function shouldForwardChildStderr(line) {
|
|
83
|
+
return /^PROGRESS:/.test(line) || /^\[greedysearch\]/.test(line) || _engineRegex.test(line) || /^GreedySearch Chrome/.test(line) || /^Launching GreedySearch Chrome/.test(line) || /^Headless mode/.test(line) || /^Ready\.?$/.test(line);
|
|
84
|
+
}
|
|
85
|
+
async function runFastAllSearch(query, { locale = null, short = true } = {}) {
|
|
86
|
+
const args = [SEARCH_BIN, "all", "--inline", "--stdin", "--fast"];
|
|
87
|
+
if (!short)
|
|
88
|
+
args.push("--full");
|
|
89
|
+
if (locale)
|
|
90
|
+
args.push("--locale", locale);
|
|
91
|
+
return new Promise((resolve, reject) => {
|
|
92
|
+
const proc = spawn(nodeRuntimeCommand(), args, {
|
|
93
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
94
|
+
env: { ...process.env, GREEDY_SEARCH_RESEARCH_CHILD: "1" }
|
|
171
95
|
});
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
if (pixels && pixels.length > 0) {
|
|
189
|
-
pixels[0] ^= 1;
|
|
190
|
-
}
|
|
191
|
-
return result;
|
|
192
|
-
});
|
|
193
|
-
} catch(_) {}
|
|
194
|
-
Object.defineProperty(navigator, 'hardwareConcurrency', { get: () => 8, configurable: true });
|
|
195
|
-
Object.defineProperty(navigator, 'deviceMemory', { get: () => 8, configurable: true });
|
|
196
|
-
|
|
197
|
-
// ── Canvas fingerprint noise ─────────────────────────
|
|
198
|
-
// Headless rendering engines produce slightly different canvas output
|
|
199
|
-
// than headed Chrome. Subtle noise breaks hash-based fingerprinting.
|
|
200
|
-
try {
|
|
201
|
-
var __canvasNoise = ((Date.now() & 0xFF) | 1);
|
|
202
|
-
var origFill = CanvasRenderingContext2D.prototype.fillText;
|
|
203
|
-
CanvasRenderingContext2D.prototype.fillText = __markNative(function fillText() {
|
|
204
|
-
this.globalAlpha = 0.9995;
|
|
205
|
-
return origFill.apply(this, arguments);
|
|
206
|
-
});
|
|
207
|
-
} catch(_) {}
|
|
208
|
-
try {
|
|
209
|
-
var origStroke = CanvasRenderingContext2D.prototype.strokeText;
|
|
210
|
-
CanvasRenderingContext2D.prototype.strokeText = __markNative(function strokeText() {
|
|
211
|
-
this.globalAlpha = 0.9995;
|
|
212
|
-
return origStroke.apply(this, arguments);
|
|
213
|
-
});
|
|
214
|
-
} catch(_) {}
|
|
215
|
-
try {
|
|
216
|
-
var origToDataURL = HTMLCanvasElement.prototype.toDataURL;
|
|
217
|
-
HTMLCanvasElement.prototype.toDataURL = __markNative(function toDataURL() {
|
|
218
|
-
var ctx = this.getContext('2d');
|
|
219
|
-
if (ctx) {
|
|
220
|
-
// Spread noise across canvas to break hash-based fingerprinting.
|
|
221
|
-
// Uses a deterministic pattern so it's consistent per page load
|
|
222
|
-
// but varies between sessions.
|
|
223
|
-
var w = this.width, h = this.height;
|
|
224
|
-
if (w > 0 && h > 0) {
|
|
225
|
-
var imgData = ctx.getImageData(0, 0, Math.min(w, 4), Math.min(h, 4));
|
|
226
|
-
if (imgData && imgData.data) {
|
|
227
|
-
for (var __i = 0; __i < imgData.data.length; __i += 4) {
|
|
228
|
-
imgData.data[__i] ^= (__canvasNoise + __i) & 0xFF;
|
|
229
|
-
}
|
|
230
|
-
ctx.putImageData(imgData, 0, 0);
|
|
231
|
-
}
|
|
96
|
+
proc.stdin.write(query);
|
|
97
|
+
proc.stdin.end();
|
|
98
|
+
let out = "";
|
|
99
|
+
let err = "";
|
|
100
|
+
let stderrBuffer = "";
|
|
101
|
+
proc.stdout.on("data", (d) => out += d);
|
|
102
|
+
proc.stderr.on("data", (d) => {
|
|
103
|
+
err += d;
|
|
104
|
+
stderrBuffer += d.toString();
|
|
105
|
+
const lines = stderrBuffer.split(`
|
|
106
|
+
`);
|
|
107
|
+
stderrBuffer = lines.pop() || "";
|
|
108
|
+
for (const line of lines) {
|
|
109
|
+
if (shouldForwardChildStderr(line)) {
|
|
110
|
+
process.stderr.write(`${line}
|
|
111
|
+
`);
|
|
232
112
|
}
|
|
233
113
|
}
|
|
234
|
-
return origToDataURL.apply(this, arguments);
|
|
235
114
|
});
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
var data = origGetChannelData.call(this, channel);
|
|
246
|
-
for (var __i = 0; __i < data.length; __i += 64) {
|
|
247
|
-
data[__i] *= 0.99999;
|
|
115
|
+
const t = setTimeout(() => {
|
|
116
|
+
proc.kill();
|
|
117
|
+
reject(new Error(`research child search timed out for: ${query}`));
|
|
118
|
+
}, 140000);
|
|
119
|
+
proc.on("close", (code) => {
|
|
120
|
+
clearTimeout(t);
|
|
121
|
+
if (code !== 0) {
|
|
122
|
+
reject(new Error(err.trim() || `search child exited with code ${code}`));
|
|
123
|
+
return;
|
|
248
124
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
// ── window outer dimensions ──────────────────────────
|
|
254
|
-
// outerWidth/Height = 0 in headless — a well-known bot signal.
|
|
255
|
-
// Mirror innerWidth/Height (set by --window-size flag) so the ratio is sane.
|
|
256
|
-
try {
|
|
257
|
-
if (!window.outerWidth) Object.defineProperty(window, 'outerWidth', { get: () => window.innerWidth || 1920, configurable: true });
|
|
258
|
-
if (!window.outerHeight) Object.defineProperty(window, 'outerHeight', { get: () => window.innerHeight || 1080, configurable: true });
|
|
259
|
-
} catch(_) {}
|
|
260
|
-
|
|
261
|
-
// ── screen properties ─────────────────────────────────
|
|
262
|
-
// Headless Chrome often reports an 800x600 screen even when the viewport is
|
|
263
|
-
// 1920x1080. Keep screen metrics internally consistent with our launch flags.
|
|
264
|
-
try {
|
|
265
|
-
Object.defineProperty(screen, 'width', { get: () => 1920, configurable: true });
|
|
266
|
-
Object.defineProperty(screen, 'height', { get: () => 1080, configurable: true });
|
|
267
|
-
Object.defineProperty(screen, 'availWidth', { get: () => 1920, configurable: true });
|
|
268
|
-
Object.defineProperty(screen, 'availHeight', { get: () => 1040, configurable: true });
|
|
269
|
-
Object.defineProperty(screen, 'colorDepth', { get: () => 24, configurable: true });
|
|
270
|
-
Object.defineProperty(screen, 'pixelDepth', { get: () => 24, configurable: true });
|
|
271
|
-
} catch(_) {}
|
|
272
|
-
|
|
273
|
-
// ── navigator.userAgentData (UA Client Hints) ─────────
|
|
274
|
-
// Derive version from the UA string already set by --user-agent flag so the
|
|
275
|
-
// two APIs are always consistent. Removes any "HeadlessChrome" brand entry.
|
|
276
|
-
try {
|
|
277
|
-
var _uaMajor = (navigator.userAgent.match(new RegExp('Chrome/([0-9]+)')) || [])[1] || '136';
|
|
278
|
-
var _uaFull = (navigator.userAgent.match(new RegExp('Chrome/([0-9.]+)')) || [])[1] || (_uaMajor + '.0.0.0');
|
|
279
|
-
var _brands = [
|
|
280
|
-
{ brand: 'Not)A;Brand', version: '99' },
|
|
281
|
-
{ brand: 'Google Chrome', version: _uaMajor },
|
|
282
|
-
{ brand: 'Chromium', version: _uaMajor },
|
|
283
|
-
];
|
|
284
|
-
Object.defineProperty(navigator, 'userAgentData', {
|
|
285
|
-
get: function() {
|
|
286
|
-
return {
|
|
287
|
-
brands: _brands, mobile: false, platform: 'Windows',
|
|
288
|
-
getHighEntropyValues: function() {
|
|
289
|
-
return Promise.resolve({
|
|
290
|
-
architecture: 'x86', bitness: '64',
|
|
291
|
-
brands: _brands,
|
|
292
|
-
fullVersionList: [
|
|
293
|
-
{ brand: 'Not)A;Brand', version: '99.0.0.0' },
|
|
294
|
-
{ brand: 'Google Chrome', version: _uaFull },
|
|
295
|
-
{ brand: 'Chromium', version: _uaFull },
|
|
296
|
-
],
|
|
297
|
-
mobile: false, model: '', platform: 'Windows',
|
|
298
|
-
platformVersion: '15.0.0', uaFullVersion: _uaFull, wow64: false,
|
|
299
|
-
});
|
|
300
|
-
},
|
|
301
|
-
toJSON: function() { return { brands: _brands, mobile: false, platform: 'Windows' }; },
|
|
302
|
-
};
|
|
303
|
-
},
|
|
304
|
-
configurable: true,
|
|
305
|
-
});
|
|
306
|
-
} catch(_) {}
|
|
307
|
-
|
|
308
|
-
// ── CDP Runtime serialization guard ──────────────────
|
|
309
|
-
// Sites detect CDP by putting a getter on Error.prototype.stack
|
|
310
|
-
// and checking if console.log triggers it (only happens when
|
|
311
|
-
// Runtime domain is enabled). We monkey-patch console methods to
|
|
312
|
-
// strip custom getters from arguments before they reach CDP.
|
|
313
|
-
try {
|
|
314
|
-
var _origLog = console.log, _origError = console.error,
|
|
315
|
-
_origWarn = console.warn, _origDebug = console.debug,
|
|
316
|
-
_origInfo = console.info;
|
|
317
|
-
var _safeArg = function(a) {
|
|
318
|
-
if (a instanceof Error) {
|
|
319
|
-
try { return new Error(a.message); } catch(_) { return a; }
|
|
320
|
-
}
|
|
321
|
-
return a;
|
|
322
|
-
};
|
|
323
|
-
console.log = __markNative(function log() { return _origLog.apply(console, Array.prototype.map.call(arguments, _safeArg)); });
|
|
324
|
-
console.error = __markNative(function error() { return _origError.apply(console, Array.prototype.map.call(arguments, _safeArg)); });
|
|
325
|
-
console.warn = __markNative(function warn() { return _origWarn.apply(console, Array.prototype.map.call(arguments, _safeArg)); });
|
|
326
|
-
console.debug = __markNative(function debug() { return _origDebug.apply(console, Array.prototype.map.call(arguments, _safeArg)); });
|
|
327
|
-
console.info = __markNative(function info() { return _origInfo.apply(console, Array.prototype.map.call(arguments, _safeArg)); });
|
|
328
|
-
} catch(_) {}
|
|
329
|
-
|
|
330
|
-
// ── Native function masking ──────────────────────────
|
|
331
|
-
// Patched APIs should not stringify as user-defined stealth code.
|
|
332
|
-
try {
|
|
333
|
-
var __nativeToString = Function.prototype.toString;
|
|
334
|
-
Function.prototype.toString = function toString() {
|
|
335
|
-
if (__greedyNativeFns.indexOf(this) !== -1) {
|
|
336
|
-
var name = this.name || '';
|
|
337
|
-
return 'function ' + name + '() { [native code] }';
|
|
125
|
+
try {
|
|
126
|
+
resolve(JSON.parse(out.trim()));
|
|
127
|
+
} catch {
|
|
128
|
+
reject(new Error(`Invalid JSON from research child: ${out.slice(0, 200)}`));
|
|
338
129
|
}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
[greedysearch] Available synthesizers: ${et.join(", ")}
|
|
349
|
-
[greedysearch] Falling back to default: ${Xe}
|
|
350
|
-
`)}}}catch{}return Xe}function Yi(e,t=9222){let r=Number.parseInt(String(e??""),10);return Number.isInteger(r)&&r>1024&&r<65535?r:t}function Wi(){try{if(_e(M)){let e=sr(M,"utf8"),t=JSON.parse(e);if(Array.isArray(t.engines)&&t.engines.length>0&&t.engines.every((r)=>typeof r==="string")){let r=t.engines.filter((i)=>be[i]),n=t.engines.filter((i)=>!be[i]);if(n.length>0)process.stderr.write(`[greedysearch] Warning: ignoring unknown engine(s) in ${M}: ${n.join(", ")}
|
|
351
|
-
[greedysearch] Available engines: ${Object.keys(be).join(", ")}
|
|
352
|
-
`);if(r.length>0)return r;process.stderr.write(`[greedysearch] Warning: no valid engines in ${M}, falling back to defaults: ${Ae.join(", ")}
|
|
353
|
-
`)}}}catch{}return Ae}function Bi(){try{if(!_e(De))gi(De,{recursive:!0});if(!_e(M))mi(M,JSON.stringify({engines:Ae,synthesizer:tt},null,2)+`
|
|
354
|
-
`,"utf8")}catch{}}function Qi(){try{if(_e(M)){let e=sr(M,"utf8"),t=JSON.parse(e);if(typeof t.synthesizer==="string"){let r=t.synthesizer.toLowerCase();if(rt.includes(r))return r;process.stderr.write(`[greedysearch] Warning: unknown synthesizer "${t.synthesizer}" in ${M}
|
|
355
|
-
[greedysearch] Available synthesizers: ${rt.join(", ")}
|
|
356
|
-
[greedysearch] Falling back to default: ${tt}
|
|
357
|
-
`)}}}catch{}return tt}async function hr(){let e=(await R(["list"])).split(`
|
|
358
|
-
`)[0];if(!e)throw Error("No Chrome tabs found");return e.slice(0,8)}async function ft(e="about:blank"){let t=await hr(),r=new URL(e).hostname;if(r==="copilot.microsoft.com"||r==="www.perplexity.ai"||r==="perplexity.ai"||r.endsWith(".perplexity.ai")){let a=await R(["evalraw",t,"Target.createTarget",JSON.stringify({url:"about:blank"})]),{targetId:o}=JSON.parse(a),s=o.slice(0,8);if(await R(["list"]).catch(()=>null),r==="copilot.microsoft.com")await Qt(s);else Qt(s).catch(()=>{});return await R(["list"]).catch(()=>null),o}let n=await R(["evalraw",t,"Target.createTarget",JSON.stringify({url:e})]),{targetId:i}=JSON.parse(n);return await R(["list"]).catch(()=>null),i}async function pt(e){try{let t=await hr();await R(["evalraw",t,"Target.closeTarget",JSON.stringify({targetId:e})])}catch{}}function Ki(e,t=9222){let r=Number.parseInt(String(e??""),10);return Number.isInteger(r)&&r>1024&&r<65535?r:t}function Vi(){try{if(Ee(U)){let e=lr(U,"utf8"),t=JSON.parse(e);if(Array.isArray(t.engines)&&t.engines.length>0&&t.engines.every((r)=>typeof r==="string")){let r=t.engines.filter((i)=>ve[i]),n=t.engines.filter((i)=>!ve[i]);if(n.length>0)process.stderr.write(`[greedysearch] Warning: ignoring unknown engine(s) in ${U}: ${n.join(", ")}
|
|
359
|
-
[greedysearch] Available engines: ${Object.keys(ve).join(", ")}
|
|
360
|
-
`);if(r.length>0)return r;process.stderr.write(`[greedysearch] Warning: no valid engines in ${U}, falling back to defaults: ${ke.join(", ")}
|
|
361
|
-
`)}}}catch{}return ke}function zi(){try{if(!Ee(Ce))bi(Ce,{recursive:!0});if(!Ee(U))vi(U,JSON.stringify({engines:ke,synthesizer:nt},null,2)+`
|
|
362
|
-
`,"utf8")}catch{}}function Zi(){try{if(Ee(U)){let e=lr(U,"utf8"),t=JSON.parse(e);if(typeof t.synthesizer==="string"){let r=t.synthesizer.toLowerCase();if(it.includes(r))return r;process.stderr.write(`[greedysearch] Warning: unknown synthesizer "${t.synthesizer}" in ${U}
|
|
363
|
-
[greedysearch] Available synthesizers: ${it.join(", ")}
|
|
364
|
-
[greedysearch] Falling back to default: ${nt}
|
|
365
|
-
`)}}}catch{}return nt}function Xi(){if(typeof globalThis.DOMMatrix>"u")globalThis.DOMMatrix=class{constructor(e=void 0){}multiplySelf(){return this}preMultiplySelf(){return this}translateSelf(){return this}scaleSelf(){return this}rotateSelf(){return this}};if(typeof globalThis.ImageData>"u")globalThis.ImageData=class{constructor(e=void 0,t=0,r=0){this.data=e,this.width=t,this.height=r}};if(typeof globalThis.Path2D>"u")globalThis.Path2D=class{constructor(e=void 0){}}}async function ea(){Xi();let e=await import("pdf-parse"),t=e.PDFParse??e.default;if(!t)throw Error("pdf-parse did not export PDFParse");return t}async function ta(e,t){try{let r=new(await ea())({data:new Uint8Array(e)});await r.load();let n=await r.getText(),i=n.text?.trim();if(!i)return null;return{title:new URL(t).pathname.split("/").pop()||"Document.pdf",content:`## PDF Content (${n.total} pages)
|
|
366
|
-
|
|
367
|
-
${i}`,pages:n.total}}catch(r){return{error:r.message||String(r)}}}function gr(e="",t=240){let r=String(e).replaceAll(/\s+/g," ").trim();if(r.length<=t)return r;let n=r.slice(0,t),i=n.lastIndexOf(" ");return i>0?`${n.slice(0,i)}...`:`${n}...`}async function ra(e,t,r=8000){let n=Date.now();try{let i=(await R(["evalraw",e,"Page.getFrameTree","{}"]).then((p)=>JSON.parse(p)).catch(()=>null))?.frameTree?.frame?.id||void 0,a=await R(["evalraw",e,"Network.loadNetworkResource",JSON.stringify({frameId:i,url:t,options:{disableCache:!0,includeCredentials:!1}})],20000),o=JSON.parse(a).resource;if(!o?.success||!o.httpStatusCode)return{url:t,error:o?.netErrorName||o?.netError||"loadNetworkResource failed",source:"chrome",duration:Date.now()-n,needsFallback:!0};let s="";if(o.stream)try{let p=await R(["evalraw",e,"IO.read",JSON.stringify({handle:o.stream})],1e4);s=JSON.parse(p).data||"",await R(["evalraw",e,"IO.close",JSON.stringify({handle:o.stream})]).catch(()=>{})}catch{}if(!s||s.length<100)return{url:t,error:"Empty response body from Network.loadNetworkResource",source:"chrome",duration:Date.now()-n,needsFallback:!0};let l=cr(o.httpStatusCode,s,t,t);if(l.blocked)return{url:t,status:o.httpStatusCode,error:`Blocked: ${l.reason}`,source:"chrome",duration:Date.now()-n,needsBrowser:!0};let c=await ur(s,t),u=dr(c);if(!u.ok)return{url:t,status:o.httpStatusCode,error:`Low quality: ${u.reason}`,source:"chrome",duration:Date.now()-n,needsBrowser:!0};let d=re(c.markdown,r);return{url:t,finalUrl:t,status:o.httpStatusCode,contentType:"text/markdown",lastModified:"",publishedTime:c.publishedTime||"",byline:c.byline||"",siteName:c.siteName||"",lang:c.lang||"",title:c.title||t,snippet:c.excerpt,content:d,contentChars:d.length,source:"chrome",duration:Date.now()-n}}catch(i){return{url:t,error:i.message,source:"chrome",duration:Date.now()-n,needsFallback:!0}}}function mr(e){try{return new URL(e).pathname.toLowerCase().endsWith(".pdf")}catch{return!1}}async function na(e,t=8000){let r=ze(e);if(r.blocked)return{url:e,finalUrl:e,status:403,error:`Blocked: ${r.reason}`,source:"pdf-http"};let n=new AbortController,i=setTimeout(()=>n.abort(),20000),a=Date.now();try{let o=await fetch(e,{method:"GET",redirect:"follow",signal:n.signal,headers:Di({accept:"application/pdf,application/octet-stream;q=0.9,*/*;q=0.5"})});clearTimeout(i);let s=o.headers.get("content-type")||"",l=o.url||e,c=Number.parseInt(o.headers.get("content-length")||"0",10);if(o.status>=400)return{url:e,finalUrl:l,status:o.status,error:`HTTP ${o.status}`,source:"pdf-http",duration:Date.now()-a};if(!s.toLowerCase().includes("application/pdf")&&!mr(l))return null;if(c>31457280)return{url:e,finalUrl:l,status:o.status,error:`PDF too large: ${c} bytes`,source:"pdf-http",duration:Date.now()-a};let u=Buffer.from(await o.arrayBuffer()),d=await ta(u,l);if(!d||d.error)return{url:e,finalUrl:l,status:o.status,error:d?.error||"PDF text extraction failed",source:"pdf-http",duration:Date.now()-a};let p=re(d.content,t);return{url:e,finalUrl:l,status:o.status,contentType:"application/pdf",lastModified:o.headers.get("last-modified")||"",title:d.title,snippet:gr(p,320),content:p,contentChars:p.length,pages:d.pages,source:"pdf-http",duration:Date.now()-a}}catch(o){return clearTimeout(i),{url:e,finalUrl:e,error:o.message||String(o),source:"pdf-http",duration:Date.now()-a}}}async function yr(e,t=8000){let r=Date.now();if(mr(e)){let i=await na(e,t);if(i?.content||i?.status===403)return i}if(Ze(e)){let i=Ze(e);if(i&&(i.type==="root"||i.type==="tree"||i.type==="blob"&&!i.path?.includes("."))){let a=await xi(e);if(a.ok){let o=re(a.content,t);return{url:e,finalUrl:e,status:200,contentType:"text/markdown",lastModified:"",title:a.title,snippet:o.slice(0,320),content:o,contentChars:o.length,source:"github-api",...a.tree&&{tree:a.tree},duration:Date.now()-r}}process.stderr.write(`[greedysearch] GitHub API fetch failed, trying HTTP: ${a.error}
|
|
368
|
-
`)}}if(Ii(e)?.type==="post"){process.stderr.write(`[greedysearch] Using Reddit JSON API for: ${e.slice(0,60)}...
|
|
369
|
-
`);let i=await ji(e,t);if(i.ok){let a=re(i.markdown,t);return{url:e,finalUrl:i.finalUrl,status:i.status,contentType:"text/markdown",lastModified:i.lastModified||"",publishedTime:i.publishedTime||"",byline:i.byline||"",siteName:i.siteName||"",lang:i.lang||"",title:i.title,snippet:i.excerpt,content:a,contentChars:a.length,source:"reddit-api",duration:Date.now()-r}}process.stderr.write(`[greedysearch] Reddit API fetch failed, falling back to HTTP: ${i.error}
|
|
370
|
-
`)}let n=await Ci(e,{timeoutMs:1e4});if(n.ok){let i=re(n.markdown,t);return{url:e,finalUrl:n.finalUrl,status:n.status,contentType:"text/markdown",lastModified:n.lastModified||"",publishedTime:n.publishedTime||"",byline:n.byline||"",siteName:n.siteName||"",lang:n.lang||"",title:n.title,snippet:n.excerpt,content:i,contentChars:i.length,source:"http",duration:Date.now()-r}}if(n.needsBrowser)try{let i=await ft();try{let a=await ra(i,e,t);if(a.content&&a.content.length>100)return a}finally{await pt(i)}}catch{}return process.stderr.write(`[greedysearch] HTTP failed for ${e.slice(0,60)}, trying browser...
|
|
371
|
-
`),await ia(e,t)}async function wr(e,t=4000,r=200){let n=Date.now()+t;while(Date.now()<n){try{if((await R(["eval",e,'document.readyState === "complete" && !!document.body && document.body.innerText.length > 500'])).trim()==="true")return}catch{}await new Promise((i)=>setTimeout(i,r))}}async function ia(e,t=8000){let r=Date.now(),n;try{n=await ft()}catch(i){return{url:e,title:"",content:null,snippet:"",contentChars:0,error:`openNewTab failed: ${i.message}`,source:"browser",duration:Date.now()-r}}try{await R(["nav",n,e],30000),await wr(n);let i=await R(["eval",n,String.raw`
|
|
372
|
-
(function(){
|
|
373
|
-
var el = document.querySelector('article, [role="main"], main, .post-content, .article-body, #content, .content');
|
|
374
|
-
var text = (el || document.body).innerText;
|
|
375
|
-
return JSON.stringify({
|
|
376
|
-
title: document.title,
|
|
377
|
-
content: text.replace(/\s+/g, ' ').trim(),
|
|
378
|
-
url: location.href
|
|
379
|
-
});
|
|
380
|
-
})()
|
|
381
|
-
`]),a=JSON.parse(i),o=re(a.content,t);return{url:e,finalUrl:a.url||e,status:200,contentType:"text/plain",lastModified:"",title:a.title,snippet:gr(o,320),content:o,contentChars:o.length,source:"browser",duration:Date.now()-r}}catch(i){return{url:e,title:"",content:null,snippet:"",contentChars:0,error:i.message,source:"browser",duration:Date.now()-r}}finally{await pt(n)}}async function aa(e,t=5,r=8000,n=at){let i=e.slice(0,t);if(i.length===0)return[];let a=Math.min(i.length,Math.max(1,Number.parseInt(String(n),10)||at));process.stderr.write(`[greedysearch] Fetching content from ${i.length} sources via HTTP (concurrency ${a})...
|
|
382
|
-
`);let o=Array(i.length),s=0,l=0;async function c(){while(!0){let f=s++;if(f>=i.length)return;let m=i[f],h=m.canonicalUrl||m.url;process.stderr.write(`[greedysearch] [${f+1}/${i.length}] Fetching: ${h.slice(0,60)}...
|
|
383
|
-
`);let g=await yr(h,r).catch((y)=>({url:h,title:"",content:null,snippet:"",contentChars:0,error:y.message,source:"error",duration:0}));if(o[f]={id:m.id,...g},g.content&&g.content.length>100)process.stderr.write(`[greedysearch] ✓ ${g.source}: ${g.content.length} chars
|
|
384
|
-
`);else if(g.error)process.stderr.write(`[greedysearch] ✗ ${g.error.slice(0,80)}
|
|
385
|
-
`);l+=1,process.stderr.write(`PROGRESS:fetch:${l}/${i.length}
|
|
386
|
-
`)}}await Promise.all(Array.from({length:a},()=>c()));let u=o.filter((f)=>f.content&&f.content.length>100),d=o.filter((f)=>f.source==="http").length,p=o.filter((f)=>f.source==="browser").length;return process.stderr.write(`[greedysearch] Fetched ${u.length}/${o.length} sources (HTTP: ${d}, Browser: ${p})
|
|
387
|
-
`),o}async function oa(e){let t=await ft();try{await R(["nav",t,e],30000),await wr(t);let r=await R(["eval",t,String.raw`
|
|
388
|
-
(function(){
|
|
389
|
-
var el = document.querySelector('article, [role="main"], main, .post-content, .article-body, #content, .content');
|
|
390
|
-
var text = (el || document.body).innerText;
|
|
391
|
-
return text.replace(/\s+/g, ' ').trim();
|
|
392
|
-
})()
|
|
393
|
-
`]);return{url:e,content:r}}catch(r){return{url:e,content:null,error:r.message}}finally{await pt(t)}}var sa,la,me=null,br="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36",ht,gt,vr,$r,_r,Er,Sr,Rr,mt,Dr,Kt,Ar,Cr,Vt,ca,O,ua,da,fa,pa,ha,ga,ma,ya,wa,Se,L,Re,Xe="gemini",et,we,ba,va,$a,zt,_a,N,Ea,Sa,Ra,Da,Aa,Ca,ka,Oa,Na,De,M,Ae,tt="gemini",rt,be,Pa,xa,Ia,ja,Ta,La,Ma,R,Zt,Ua,P,Ga,Fa,Ha,qa,Ja,Ya,Wa,Ba,Qa,Ce,U,ke,nt="gemini",it,ve,Ka,Va,at,za=dt(()=>{sa=ni(import.meta.url),la=ii(import.meta.url),ht={"user-agent":br,accept:"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8","accept-language":"en-US,en;q=0.9","accept-encoding":"gzip, deflate, br","cache-control":"no-cache",pragma:"no-cache","sec-ch-ua":'"Chromium";v="122", "Not(A:Brand";v="24", "Google Chrome";v="122"',"sec-ch-ua-mobile":"?0","sec-ch-ua-platform":'"Windows"',"sec-fetch-dest":"document","sec-fetch-mode":"navigate","sec-fetch-site":"none","sec-fetch-user":"?1","upgrade-insecure-requests":"1"},gt=[/^localhost$/i,/^127\.\d+\.\d+\.\d+$/,/^0\.0\.0\.0$/,/^\[::1\]$/,/^10\./,/^172\.(1[6-9]|2\d|3[01])\./,/^192\.168\./,/^169\.254\./,/^fc00:/i,/^fe80:/i,/\.local$/i,/\.internal$/i,/\.localhost$/i],vr=/^::ffff:(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/i,$r=/^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/i,_r=/^(?:0x[0-9a-f]+|0[0-7]*|[1-9][0-9]*)$/i,Er=["accounts.google.com","login.microsoftonline.com","login.live.com","auth0.com","okta.com","auth.mozilla.auth0.com","id.atlassian.com"],Sr=["login.","signin.","auth.","sso.","accounts.","idp."],Rr=["sign in to continue","log in to continue","authentication required","create an account to continue","subscribe to continue reading","members only"],mt={"user-agent":"GreedySearch/1.0",accept:"application/vnd.github+json","x-github-api-version":"2022-11-28"},Dr={"user-agent":"GreedySearch/1.0 (Research Bot)",accept:"application/json"},Kt=si(ci(import.meta.url)),Ar=li(Kt,"..","bin","cdp.mjs"),Cr=new Set(["list","snap","eval","shot","html","nav","net","click","clickxy","type","loadall","evalraw","browse","stop","--tab"]),Vt=hi().replaceAll("\\","/"),ca=Fi(process.env.GREEDY_SEARCH_PORT),O=(process.env.GREEDY_SEARCH_PROFILE_DIR||process.env.CDP_PROFILE_DIR||`${Vt}/greedysearch-chrome-profile`).replaceAll("\\","/"),ua=`${O}/DevToolsActivePort`,da=process.env.GREEDY_SEARCH_PID_FILE||`${O}/browser.pid`,fa=process.env.CDP_PAGES_CACHE||`${O}/cdp-pages.json`,pa=process.env.GREEDY_SEARCH_MODE_FILE||`${O}/browser-mode`,ha=process.env.GREEDY_SEARCH_METADATA_FILE||`${O}/browser-metadata.json`,ga=process.env.GREEDY_SEARCH_LAUNCH_LOCK_FILE||`${O}/browser-launch.lock`,ma=process.env.GREEDY_SEARCH_ACTIVITY_FILE||`${O}/browser-last-activity`,ya=(process.env.CDP_SOCKET_DIR||`${O}/cdp-sockets`).replaceAll("\\","/"),wa=`${O}/visible-recovery.jsonl`,Se=Gt(pi(),".dm"),L=Gt(Se,"greedyconfig"),Re=["perplexity","google","chatgpt","gemini"],qi(),et=["gemini","chatgpt"],we={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"},ba=Hi(),va=Ji(),$a=Math.max(1,Number.parseInt(process.env.GREEDY_FETCH_CONCURRENCY||"5",10)||5),process.env.CDP_PROFILE_DIR=O,zt=wi().replaceAll("\\","/"),_a=Yi(process.env.GREEDY_SEARCH_PORT),N=(process.env.GREEDY_SEARCH_PROFILE_DIR||process.env.CDP_PROFILE_DIR||`${zt}/greedysearch-chrome-profile`).replaceAll("\\","/"),Ea=`${N}/DevToolsActivePort`,Sa=process.env.GREEDY_SEARCH_PID_FILE||`${N}/browser.pid`,Ra=process.env.CDP_PAGES_CACHE||`${N}/cdp-pages.json`,Da=process.env.GREEDY_SEARCH_MODE_FILE||`${N}/browser-mode`,Aa=process.env.GREEDY_SEARCH_METADATA_FILE||`${N}/browser-metadata.json`,Ca=process.env.GREEDY_SEARCH_LAUNCH_LOCK_FILE||`${N}/browser-launch.lock`,ka=process.env.GREEDY_SEARCH_ACTIVITY_FILE||`${N}/browser-last-activity`,Oa=(process.env.CDP_SOCKET_DIR||`${N}/cdp-sockets`).replaceAll("\\","/"),Na=`${N}/visible-recovery.jsonl`,De=Ft(yi(),".dm"),M=Ft(De,"greedyconfig"),Ae=["perplexity","google","chatgpt","gemini"],Bi(),rt=["gemini","chatgpt"],be={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"},Pa=Wi(),xa=Qi(),Ia=Math.max(1,Number.parseInt(process.env.GREEDY_FETCH_CONCURRENCY||"5",10)||5),process.env.CDP_PROFILE_DIR=N,ja=Number.parseInt(process.env.GREEDY_SEARCH_IDLE_TIMEOUT_MINUTES||"5",10)||5,Ta=Gi(import.meta.url),La=Number.parseInt(process.env.GREEDY_SEARCH_IDLE_TIMEOUT_MINUTES||"5",10)||5,Ma=Number.parseInt(process.env.GREEDY_SEARCH_VISIBLE_IDLE_TIMEOUT_MINUTES||"60",10)||60,R=pr,Zt=_i().replaceAll("\\","/"),Ua=Ki(process.env.GREEDY_SEARCH_PORT),P=(process.env.GREEDY_SEARCH_PROFILE_DIR||process.env.CDP_PROFILE_DIR||`${Zt}/greedysearch-chrome-profile`).replaceAll("\\","/"),Ga=`${P}/DevToolsActivePort`,Fa=process.env.GREEDY_SEARCH_PID_FILE||`${P}/browser.pid`,Ha=process.env.CDP_PAGES_CACHE||`${P}/cdp-pages.json`,qa=process.env.GREEDY_SEARCH_MODE_FILE||`${P}/browser-mode`,Ja=process.env.GREEDY_SEARCH_METADATA_FILE||`${P}/browser-metadata.json`,Ya=process.env.GREEDY_SEARCH_LAUNCH_LOCK_FILE||`${P}/browser-launch.lock`,Wa=process.env.GREEDY_SEARCH_ACTIVITY_FILE||`${P}/browser-last-activity`,Ba=(process.env.CDP_SOCKET_DIR||`${P}/cdp-sockets`).replaceAll("\\","/"),Qa=`${P}/visible-recovery.jsonl`,Ce=Ht($i(),".dm"),U=Ht(Ce,"greedyconfig"),ke=["perplexity","google","chatgpt","gemini"],zi(),it=["gemini","chatgpt"],ve={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"},Ka=Vi(),Va=Zi(),at=Math.max(1,Number.parseInt(process.env.GREEDY_FETCH_CONCURRENCY||"5",10)||5),process.env.CDP_PROFILE_DIR=P}),Za={};ut(Za,{parseGitHubUrl:()=>kr,fetchGitHubContent:()=>to});function kr(e){try{let t=new URL(e);if(!(t.hostname==="github.com"||t.hostname.endsWith(".github.com")))return null;let r=t.pathname.split("/").filter(Boolean);if(r.length<2)return null;let[n,i]=r;if(r.length===2)return{owner:n,repo:i,type:"root"};if(r.length>=4&&(r[2]==="blob"||r[2]==="tree")){let a=r[2],o=r[3],s=r.slice(4).join("/");return{owner:n,repo:i,type:a,ref:o,path:s}}return null}catch{return null}}async function I(e,t=1e4){let r=new AbortController,n=setTimeout(()=>r.abort(),t);try{let i=await fetch(`https://api.github.com${e}`,{headers:yt,signal:r.signal});if(clearTimeout(n),!i.ok)throw Error(`GitHub API ${i.status}: ${e}`);return await i.json()}catch(i){throw clearTimeout(n),i}}async function Xa(e,t){try{let r=await I(`/repos/${e}/${t}/readme`);if(r.content&&r.encoding==="base64")return Buffer.from(r.content,"base64").toString("utf8");return""}catch{return""}}async function Xt(e,t,r="HEAD",n="",i){try{let a;if(r==="HEAD")if(i)a=await I(`/repos/${e}/${t}/git/ref/heads/${i}`).catch(()=>null);else a=await Promise.any([I(`/repos/${e}/${t}/git/ref/heads/main`),I(`/repos/${e}/${t}/git/ref/heads/master`)]).catch(()=>null);else a=await I(`/repos/${e}/${t}/git/ref/heads/${r}`).catch(()=>I(`/repos/${e}/${t}/git/ref/heads/master`).catch(()=>null));if(!a?.object?.sha)return[];let o=(await I(`/repos/${e}/${t}/git/commits/${a.object.sha}`)).tree.sha,s=(await I(`/repos/${e}/${t}/git/trees/${o}`)).tree||[];if(n)s=s.filter((l)=>l.path.startsWith(n));return s.slice(0,50).map((l)=>({path:l.path,type:l.type==="tree"?"dir":"file",size:l.size}))}catch{return[]}}async function eo(e,t,r,n,i=1e4,a){let o=async(l)=>{let c=new AbortController,u=setTimeout(()=>c.abort(),i);try{let d=await fetch(l,{headers:{"user-agent":yt["user-agent"]},signal:c.signal});if(clearTimeout(u),d.ok)return await d.text();throw Error("not ok")}catch{throw clearTimeout(u),Error("failed")}};if(!r||r==="HEAD"){if(a)try{return await o(`https://raw.githubusercontent.com/${e}/${t}/${a}/${n}`)}catch{return null}try{return await Promise.any([o(`https://raw.githubusercontent.com/${e}/${t}/main/${n}`),o(`https://raw.githubusercontent.com/${e}/${t}/master/${n}`)])}catch{return null}}let s=[`https://raw.githubusercontent.com/${e}/${t}/${r}/${n}`,`https://raw.githubusercontent.com/${e}/${t}/master/${n}`];for(let l of s)try{return await o(l)}catch{}return null}async function to(e){let t=kr(e);if(!t)return{ok:!1,error:"Not a valid GitHub URL"};let{owner:r,repo:n,type:i,ref:a,path:o}=t;try{if(i==="root"||i==="tree"&&!o){let s=await I(`/repos/${r}/${n}`),[l,c]=await Promise.allSettled([Xa(r,n),Xt(r,n,a||"HEAD","",s.default_branch)]),u=l.status==="fulfilled"?l.value:"",d=c.status==="fulfilled"?c.value:[],p=s?.description?`
|
|
394
|
-
|
|
395
|
-
> ${s.description}`:"",f=s?.stargazers_count==null?"":` ⭐ ${s.stargazers_count}`,m=s?.language?` · ${s.language}`:"",h=`# ${r}/${n}${f}${m}${p}
|
|
396
|
-
|
|
397
|
-
`;if(u)h+=u.slice(0,6000);else h+=`[No README found]
|
|
398
|
-
|
|
399
|
-
Files:
|
|
400
|
-
${d.map((g)=>` ${g.type==="dir"?"\uD83D\uDCC1":"\uD83D\uDCC4"} ${g.path}`).join(`
|
|
401
|
-
`)}`;return{ok:!0,title:`${r}/${n}`,content:h,tree:d.slice(0,30)}}if(i==="blob"&&o){let s;if(!a||a==="HEAD")try{s=(await I(`/repos/${r}/${n}`)).default_branch}catch{s=void 0}let l=await eo(r,n,a,o,1e4,s);if(l===null)return{ok:!1,error:`File not found: ${o}`};return{ok:!0,title:`${r}/${n}: ${o}`,content:l}}if(i==="tree"&&o){let s;if(!a||a==="HEAD")try{s=(await I(`/repos/${r}/${n}`)).default_branch}catch{s=void 0}let l=await Xt(r,n,a||"HEAD",o,s),c=l.map((u)=>` ${u.type==="dir"?"\uD83D\uDCC1":"\uD83D\uDCC4"} ${u.path}`).join(`
|
|
402
|
-
`);return{ok:!0,title:`${r}/${n}/${o}`,content:`[Directory: ${o}]
|
|
403
|
-
|
|
404
|
-
Files:
|
|
405
|
-
${c}`,tree:l}}return{ok:!1,error:"Unsupported GitHub URL type"}}catch(s){return{ok:!1,error:s.message}}}var yt,Cc=dt(()=>{yt={"user-agent":"GreedySearch/1.0",accept:"application/vnd.github+json","x-github-api-version":"2022-11-28"}});function no(e=process.env,t=process.execPath){let r=e.GREEDY_SEARCH_NODE||e.NODE_BINARY||e.NODE;if(r?.trim())return r.trim();let n=ro(t||"").toLowerCase();if(n==="node"||n==="node.exe")return t;return"node"}var ao=["fbclid","gclid","ref","ref_src","ref_url","source","utm_campaign","utm_content","utm_medium","utm_source","utm_term"];function z(e="",t=240){let r=String(e).replaceAll(/\s+/g," ").trim();if(r.length<=t)return r;let n=r.slice(0,t),i=n.lastIndexOf(" ");return i>0?`${n.slice(0,i)}...`:`${n}...`}function ot(e){if(!e)return null;try{let t=new URL(e);if(!["http:","https:"].includes(t.protocol))return null;if(t.hash="",t.hostname=t.hostname.toLowerCase(),t.protocol==="https:"&&t.port==="443"||t.protocol==="http:"&&t.port==="80")t.port="";for(let i of[...t.searchParams.keys()]){let a=i.toLowerCase();if(ao.includes(a)||a.startsWith("utm_"))t.searchParams.delete(i)}t.searchParams.sort();let r=t.pathname.replace(/\/{1,10}$/,"")||"/";t.pathname=r;let n=t.toString();return r==="/"?n.replace(/\/$/,""):n}catch{return null}}function uo(e,t=9222){let r=Number.parseInt(String(e??""),10);return Number.isInteger(r)&&r>1024&&r<65535?r:t}var fo=co().replaceAll("\\","/"),Lc=uo(process.env.GREEDY_SEARCH_PORT),j=(process.env.GREEDY_SEARCH_PROFILE_DIR||process.env.CDP_PROFILE_DIR||`${fo}/greedysearch-chrome-profile`).replaceAll("\\","/"),Mc=`${j}/DevToolsActivePort`,Uc=process.env.GREEDY_SEARCH_PID_FILE||`${j}/browser.pid`,Gc=process.env.CDP_PAGES_CACHE||`${j}/cdp-pages.json`,Fc=process.env.GREEDY_SEARCH_MODE_FILE||`${j}/browser-mode`,Hc=process.env.GREEDY_SEARCH_METADATA_FILE||`${j}/browser-metadata.json`,qc=process.env.GREEDY_SEARCH_LAUNCH_LOCK_FILE||`${j}/browser-launch.lock`,Jc=process.env.GREEDY_SEARCH_ACTIVITY_FILE||`${j}/browser-last-activity`,Yc=(process.env.CDP_SOCKET_DIR||`${j}/cdp-sockets`).replaceAll("\\","/"),Wc=`${j}/visible-recovery.jsonl`,st=Nr(lo(),".dm"),J=Nr(st,"greedyconfig"),lt=["perplexity","google","chatgpt","gemini"],ct="gemini";function po(){try{if(Oe(J)){let e=Or(J,"utf8"),t=JSON.parse(e);if(Array.isArray(t.engines)&&t.engines.length>0&&t.engines.every((r)=>typeof r==="string")){let r=t.engines.filter((i)=>Ke[i]),n=t.engines.filter((i)=>!Ke[i]);if(n.length>0)process.stderr.write(`[greedysearch] Warning: ignoring unknown engine(s) in ${J}: ${n.join(", ")}
|
|
406
|
-
[greedysearch] Available engines: ${Object.keys(Ke).join(", ")}
|
|
407
|
-
`);if(r.length>0)return r;process.stderr.write(`[greedysearch] Warning: no valid engines in ${J}, falling back to defaults: ${lt.join(", ")}
|
|
408
|
-
`)}}}catch{}return lt}function ho(){try{if(!Oe(st))oo(st,{recursive:!0});if(!Oe(J))so(J,JSON.stringify({engines:lt,synthesizer:ct},null,2)+`
|
|
409
|
-
`,"utf8")}catch{}}ho();var Ne=["gemini","chatgpt"];function go(){try{if(Oe(J)){let e=Or(J,"utf8"),t=JSON.parse(e);if(typeof t.synthesizer==="string"){let r=t.synthesizer.toLowerCase();if(Ne.includes(r))return r;process.stderr.write(`[greedysearch] Warning: unknown synthesizer "${t.synthesizer}" in ${J}
|
|
410
|
-
[greedysearch] Available synthesizers: ${Ne.join(", ")}
|
|
411
|
-
[greedysearch] Falling back to default: ${ct}
|
|
412
|
-
`)}}}catch{}return ct}var Ke={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"},Pr=po();var Bc=go(),Qc=Math.max(1,Number.parseInt(process.env.GREEDY_FETCH_CONCURRENCY||"5",10)||5);process.env.CDP_PROFILE_DIR=j;function mo(e){let t="",r=!1,n=!1;for(let i of String(e)){if(n){t+=i,n=!1;continue}if(i==="\\"){t+=i,n=!0;continue}if(i==='"'){r=!r,t+=i;continue}if(r&&i===`
|
|
413
|
-
`)t+="\\n";else if(r&&i==="\r")t+="\\r";else if(r&&i==="\t")t+="\\t";else t+=i}return t}function yo(e){if(!e)return null;let t=String(e).trim(),r=t.indexOf("BEGIN_JSON"),n=t.indexOf("END_JSON");if(r!==-1&&n!==-1&&r<n)t=t.slice(r+10,n).trim();else{let s=t.indexOf("{");if(s>0)t=t.slice(s)}let i=[t,t.replace(/^```json\s*/i,"").replace(/^```\s*/i,"").replace(/```$/i,"").trim()],a=t.indexOf("{"),o=t.lastIndexOf("}");if(a!==-1&&o!==-1&&a<o)i.push(t.slice(a,o+1));for(let s of[...i]){let l=mo(s);if(l!==s)i.push(l)}for(let s of i)try{return JSON.parse(s)}catch{}return null}function $o(e){return vo(new URL(".",e)).replace(/^\/([A-Z]:)/,"$1")}function _o(e,t=xr){let r=new Set;for(let n of e.filter(Boolean)){if(r.has(n))continue;if(r.add(n),t(n))return n}return e.filter(Boolean).at(-1)}function Eo(e,{moduleDir:t,entrypoint:r=process.argv[1],env:n=process.env,exists:i=xr}={}){let a=r?bo(r):null,o=n.GREEDY_SEARCH_EXTENSION_DIR?.trim()||null;return _o([t?ye(t,"..","..","extractors",e):null,t?ye(t,"..","extractors",e):null,o?ye(o,"extractors",e):null,a?ye(a,"..","extractors",e):null],i)}var So=$o(import.meta.url),Ro={gemini:"gemini.mjs",chatgpt:"chatgpt.mjs"};function Do(e="gemini"){let t=String(e||"gemini").toLowerCase();if(t==="gem")return"gemini";if(t==="gpt")return"chatgpt";return t}async function Ao(e,t,{tabPrefix:r=null,timeoutMs:n=180000,visible:i=null}={}){let a=Do(e),o=Ro[a];if(!o||!Ne.includes(a))throw Error(`Unsupported synthesizer "${e}". Supported: ${Ne.join(", ")}`);return new Promise((s,l)=>{let c=Eo(o,{moduleDir:So}),u=r?["--tab",String(r)]:[],d={...process.env,CDP_PROFILE_DIR:j};if(i!==!0)delete d.GREEDY_SEARCH_VISIBLE,delete d.GREEDY_SEARCH_ALWAYS_VISIBLE;else d.GREEDY_SEARCH_VISIBLE="1",d.GREEDY_SEARCH_ALWAYS_VISIBLE="1";let p=wo(no(),[c,"--stdin",...u],{stdio:["pipe","pipe","pipe"],env:d});p.stdin.write(t),p.stdin.end();let f="",m="";p.stdout.on("data",(g)=>f+=g),p.stderr.on("data",(g)=>m+=g);let h=setTimeout(()=>{p.kill(),l(Error(`${a} prompt timed out after ${n/1000}s`))},n);p.on("close",(g)=>{if(clearTimeout(h),g!==0){l(Error(m.trim()||`${a} extractor failed`));return}try{s(JSON.parse(f.trim()))}catch{l(Error(`bad JSON from ${a}: ${f.slice(0,100)}`))}})})}async function Co(e,t={}){return Ao("gemini",e,t)}ar();za();var No=Oo(new URL(".",import.meta.url)).replace(/^\/([A-Z]:)/,"$1"),tu=ko(No,"..","..","bin","search.mjs");var Po=Pr.join("|"),ru=new RegExp(`^\\[(${Po})\\]`);var xo=io(new URL(".",import.meta.url)).replace(/^\/([A-Z]:)/,"$1"),nu=_(xo,"..","..","bin","search.mjs"),Io=_(process.cwd(),".pi","greedysearch-research");function jo(e){return String(e||"research").toLowerCase().replaceAll(/[^a-z0-9]+/g,"-").replaceAll(/^-|-$/g,"").slice(0,60)||"research"}function se(e,t=1/0){let r=new Set,n=[];for(let i of e||[]){let a=z(String(i||""),1000);if(!a||r.has(a))continue;if(r.add(a),n.push(a),n.length>=t)break}return n}async function To(...e){let{writeSourcesToFiles:t}=await Promise.resolve().then(()=>(ar(),rr));return t(...e)}function Ir(e){return Mo(Lo(String(e)))}function Lo(e){let t="",r=0;while(r<e.length){let n=e.indexOf("[",r);if(n===-1){t+=e.slice(r);break}let i=e.indexOf("]",n+1);if(i===-1||e[i+1]!=="("||i===n+1){t+=e.slice(r,n+1),r=n+1;continue}let a=e.indexOf(")",i+2);if(a===-1){t+=e.slice(r,n+1),r=n+1;continue}let o=e.slice(i+2,a).trimStart();if(!o.startsWith("http://")&&!o.startsWith("https://")){t+=e.slice(r,n+1),r=n+1;continue}t+=e.slice(r,n),t+=e.slice(n+1,i),r=a+1}return t}function Mo(e){let t="",r=!1;for(let n of e)if(n===" "||n==="\t"||n===`
|
|
414
|
-
`||n==="\r"){if(!r)t+=" ";r=!0}else t+=n,r=!1;return t.trim()}function er(e){return new Set(String(e).toLowerCase().normalize("NFD").replaceAll(/[\u0300-\u036f]/g,"").split(/[^\w]+/).filter((t)=>t.length>1))}function jr(e,t){let r=er(e),n=er(t),i=new Set([...r,...n]).size;if(i===0)return 1;let a=0;for(let o of r)if(n.has(o))a++;return a/i}function Pe(e){return ot(e?.finalUrl||e?.canonicalUrl||e?.url||"")||e?.id||""}function Uo(e,t){let r=Array.isArray(e?.extractions)?e.extractions:[],n=new Map,i=new Map;for(let a of t||[]){if(a?.id)i.set(String(a.id),a);let o=Pe(a);if(o)n.set(o,a)}return r.map((a)=>{let o=i.get(String(a?.sourceId||""))||n.get(ot(a?.url||"")||""),s=String(a?.sourceId||o?.id||""),l=ot(a?.url||o?.finalUrl||o?.url||""),c=Array.isArray(a?.answers)?a.answers.map((u)=>({id:String(u?.id||""),evidence:z(u?.evidence||"",500),sourceIds:[s].filter(Boolean)})).filter((u)=>u.id):[];return{sourceId:s,url:l,title:o?.title||a?.title||"",rational:z(a?.rational||"",700),evidence:z(a?.evidence||"",1600),summary:z(a?.summary||"",700),answers:c,newQuestions:se(a?.newQuestions||[],6)}}).filter((a)=>a.sourceId||a.url||a.summary||a.evidence)}function Go(e,t,r,n=new Set){let i=(t||[]).filter((o)=>o.status!=="closed").slice(0,12).map((o)=>({id:o.id,question:o.question})),a=(r||[]).filter((o)=>o?.content||o?.snippet).filter((o)=>!n.has(Pe(o))).slice(0,6).map((o,s)=>({id:o.id||`F${s+1}`,title:o.title||"",url:o.finalUrl||o.url||o.canonicalUrl||"",content:z(o.content||o.snippet||"",5000)}));return["You are doing goal-based evidence extraction for an iterative research run.","For each source, extract only information that helps answer the open questions.","Use original wording/details where useful. Do not invent answers; leave questions open if evidence is insufficient.","If a source answers one or more tracked questions, identify those question IDs explicitly.","Also propose genuinely new sub-questions discovered from the evidence.","",`Original research question: ${e}`,`Open question ledger: ${JSON.stringify(i,null,2)}`,`Fetched sources: ${JSON.stringify(a,null,2)}`,"","Respond ONLY with JSON wrapped in BEGIN_JSON / END_JSON markers:","BEGIN_JSON",JSON.stringify({extractions:[{sourceId:"S1",url:"https://example.com/source",rational:"why this source matters for the goal",evidence:"specific quoted/paraphrased evidence with numbers, dates, caveats",summary:"concise contribution to the research question",answers:[{id:"Q1",evidence:"brief evidence that closes the question"}],newQuestions:["new sub-question raised by this source"]}]},null,2),"END_JSON"].join(`
|
|
415
|
-
`)}async function Tr({query:e,questions:t,fetchedSources:r,extractedSourceKeys:n}){let i=(r||[]).filter((a)=>(a?.content||a?.snippet)&&!n.has(Pe(a)));if(i.length===0)return{evidence:[],error:""};try{let a=await Co(Go(e,t,i,n),{timeoutMs:120000}),o=Ho(a,{extractions:[]}),s=Uo(o,i);for(let l of i){let c=Pe(l);if(c)n.add(c)}return{evidence:s,error:""}}catch(a){return{evidence:[],error:a.message||String(a)}}}function Lr(e,t,r,n=[],i=[]){let a=t.flatMap((l)=>l.learnings||[]),o=t.flatMap((l)=>l.gaps||[]),s=r.slice(0,12).map((l)=>({id:l.id,title:l.title,domain:l.domain,url:l.canonicalUrl,type:l.sourceType,engines:l.engines,fetch:l.fetch?.attempted?{ok:l.fetch.ok,snippet:z(l.fetch.snippet||"",1200),publishedTime:l.fetch.publishedTime||""}:void 0}));return["You are writing the final research report for an iterative deep-research run.","Produce a thorough markdown report organized into clear sections.","","Use the learnings and source registry below. Every substantive claim MUST be backed by an [S1] citation.",'Where engines disagree, surface the conflicting claims explicitly in the "differences" array.','Include a "Key Claims" structure that maps each distinct claim to its supporting source IDs.',"","Report structure:","1. ## Summary — A 2-4 sentence executive summary of findings","2. ## Key Findings — The main findings, organized by theme or question, each with inline citations","3. ## Areas of Disagreement — Where engines or sources conflict (if any)","4. ## Limitations & Caveats — Important qualifiers, gaps, or uncertainties","",`Original research question: ${e}`,`Learnings: ${JSON.stringify(a,null,2)}`,`Known gaps/caveats: ${JSON.stringify(o,null,2)}`,`Question ledger: ${JSON.stringify(n,null,2)}`,`Goal-based extracted evidence: ${JSON.stringify(i.slice(-20),null,2)}`,`Source registry: ${JSON.stringify(s,null,2)}`,"","Respond ONLY with JSON wrapped in BEGIN_JSON / END_JSON markers:","BEGIN_JSON",JSON.stringify({answer:"markdown report with sections and inline [S1] citations",agreement:{level:"high|medium|low|mixed|conflicting",summary:"one-sentence confidence summary"},differences:["notable disagreement or conflict between sources"],caveats:["important caveat or qualification"],claims:[{claim:"specific factual statement from the research",support:"strong|moderate|weak|conflicting",sourceIds:["S1","S2"]}],recommendedSources:["S1","S2"]},null,2),"END_JSON"].join(`
|
|
416
|
-
`)}function Mr(e,t=[],r=[],n=[]){let i=t.slice(0,12).map((l)=>({id:l.id,title:l.title,domain:l.domain,url:l.canonicalUrl,type:l.sourceType,engines:l.engines})),a=n.slice(-20),o=new Set;for(let l of a)for(let c of l.answers||[])if(c?.id)o.add(c.id);let s=(r||[]).filter((l)=>l.status!=="closed").map((l)=>({id:l.id,question:l.question}));return["You are writing the final research report from goal-based extracted evidence.","Per-round learnings were not produced, but the per-source evidence extraction step succeeded.","Synthesize a thorough markdown report using ONLY the evidence below. Every substantive claim MUST be backed by an [S1] citation.","","Report structure:","1. ## Summary — A 2-4 sentence executive summary of findings","2. ## Key Findings — The main findings, organized by theme or question, each with inline citations","3. ## Limitations & Caveats — Important qualifiers, gaps, or uncertainties","",`Original research question: ${e}`,`Per-source extracted evidence: ${JSON.stringify(a,null,2)}`,`Source registry: ${JSON.stringify(i,null,2)}`,`Questions already answered by the evidence: ${JSON.stringify(Array.from(o))}`,`Questions still open after this evidence: ${JSON.stringify(s)}`,"","Respond ONLY with JSON wrapped in BEGIN_JSON / END_JSON markers:","BEGIN_JSON",JSON.stringify({answer:"markdown report with sections and inline [S1] citations",agreement:{level:"high|medium|low|mixed|conflicting",summary:"one-sentence confidence summary"},differences:["notable disagreement or conflict between sources"],caveats:["important caveat or qualification"],claims:[{claim:"specific factual statement supported by the evidence",support:"strong|moderate|weak|conflicting",sourceIds:["S1","S2"]}],recommendedSources:["S1","S2"]},null,2),"END_JSON"].join(`
|
|
417
|
-
`)}var Fo=Pr.join("|"),iu=new RegExp(`^\\[(${Fo})\\]`);function Ho(e,t={}){return yo(e?.answer||"")||t}function Ur(e,t){if(!e||!Array.isArray(t))return{cited:[],missing:[],unfetched:[],ok:!0};let r=/\b[SF](\d+)\b/g,n=new Set,i;while((i=r.exec(e))!==null)n.add(`S${i[1]}`),n.add(`F${i[1]}`);let a=new Map;for(let c of t){let u=c?.id;if(u)a.set(u,c)}let o=Array.from(n),s=[],l=[];for(let c of o){let u=a.get(c);if(!u){let d=c.match(/^(S|F)(\d+)$/);if(d){let p=parseInt(d[2],10)-1;if(p>=0&&p<t.length){let f=t[p];if(f){if(!(f.fetch?.ok||f.content&&f.content.length>100||f.contentChars&&f.contentChars>100))l.push(c);continue}}}s.push(c)}else if(!(u.fetch?.ok||u.content&&u.content.length>100||u.contentChars&&u.contentChars>100))l.push(c)}return{cited:o,missing:s,unfetched:l,ok:s.length===0}}async function qo(e,{timeoutMs:t=6000,concurrency:r=4}={}){let n=Math.max(1,Math.floor(r||1)),i=(e||[]).filter((p)=>p?.id&&(p?.canonicalUrl||p?.finalUrl||p?.url));if(i.length===0)return{reachable:[],dead:[],skipped:[],ok:!0};let a=[],o=[],s=[],l=Array(i.length),c=0;async function u(){while(!0){let p=c++;if(p>=i.length)return;let f=i[p];try{let m=f.fetch?.finalUrl||f.canonicalUrl||f.finalUrl||f.url;if(!m){l[p]={id:f.id,url:"",status:"skipped"};continue}try{let h=new URL(m);if(h.protocol!=="http:"&&h.protocol!=="https:"){l[p]={id:f.id,url:m,status:"skipped"};continue}}catch{l[p]={id:f.id,url:m,status:"skipped"};continue}try{let h=new AbortController,g=setTimeout(()=>h.abort(),t);try{let y=await fetch(m,{method:"HEAD",redirect:"follow",signal:h.signal,headers:{"User-Agent":"Mozilla/5.0 (compatible; GreedySearch/2.0; +https://github.com/apmantza/greedysearch-dm)"}});clearTimeout(g);let v=y.status>=200&&y.status<400,b=[401,403,405,429].includes(y.status),w="dead";if(v)w="reachable";else if(b)w="skipped";l[p]={id:f.id,url:m,status:w,httpStatus:y.status,reason:b?"bot-protected-or-head-disallowed":void 0}}catch(y){clearTimeout(g),l[p]={id:f.id,url:m,status:"dead",error:y.name==="AbortError"?"timeout":y.message}}}catch(h){l[p]={id:f.id,url:m,status:"dead",error:h.message}}}catch(m){l[p]={id:"?",url:"",status:"dead",error:m?.message||"unknown"}}}}let d=Math.min(i.length,n);await Promise.all(Array.from({length:d},()=>u()));for(let p of l)if(p.status==="reachable")a.push(p);else if(p.status==="dead")o.push(p);else s.push(p);return{reachable:a,dead:o,skipped:s,ok:o.length===0}}async function Gr(e,t=null){process.stderr.write(`PROGRESS:research:check-urls
|
|
418
|
-
`);try{let r=new Set(t?.cited||[]),n=r.size?(e||[]).filter((a)=>r.has(a?.id)):e,i=await qo(n,{timeoutMs:6000,concurrency:4});if(!i.ok)process.stderr.write(`[greedysearch] ${i.dead.length} dead citation URL(s) detected
|
|
419
|
-
`);return i}catch(r){return process.stderr.write(`[greedysearch] URL reachability check failed: ${r.message}
|
|
420
|
-
`),null}}function Fr({sources:e=[],fetchedSources:t=[],synthesis:r={},citationAudit:n=null,gaps:i=[],questions:a=[],rounds:o=[],qualityScore:s=0,qualityThreshold:l=8.5,maxSources:c=8,requireCitations:u=!0,requireQuestions:d=!0}={}){let p=t.filter((S)=>S?.fetch?.ok||(S?.contentChars||0)>100||String(S?.content||"").length>100),f=e.filter((S)=>["official-docs","repo","maintainer-blog","academic"].includes(String(S?.sourceType||""))),m=Array.isArray(r?.claims)?r.claims:[],h=n?n.cited?.length||0:0,g=tr(a),y=(a||[]).filter((S)=>!S.createdRound||S.reason==="Original research question"),v=tr(y),b=(o||[]).length,w=Math.min(4,Math.max(2,Number(c)||8)),E=b<=1?Math.min(2,w):w,A={roundsRun:o.length>=1,fetchedSources:p.length>=E,primarySources:f.length>=1,qualityScore:s>=Math.min(l,8)||u&&m.length>0&&h>0,claimsExtracted:!u||m.length>0,citationsPresent:!u||h>0,citationsValid:!u||n?.ok===!0,unfetchedCitations:!u||(n?.unfetched||[]).length===0,requiredQuestionsClosed:!d||v.open===0};return{floorMet:Object.values(A).every(Boolean),checks:A,metrics:{fetchedOk:p.length,primarySources:f.length,claims:m.length,cited:h,gaps:i.length,openQuestions:g.open,closedQuestions:g.closed,totalQuestions:g.total,openRequiredQuestions:v.open,closedRequiredQuestions:v.closed,totalRequiredQuestions:v.total,qualityScore:s,minFetched:E}}}function Hr(e){return[{id:"Q1",question:z(Ir(e),320),status:"open",reason:"Original research question",evidence:[],sourceIds:[]}]}function Jo(e,t){let r=Ir(t).toLowerCase();return(e||[]).find((n)=>n.question?.toLowerCase()===r||jr(n.question||"",r)>=0.82)}function Yo(e,t,{evidence:r="",sourceIds:n=[],round:i=null}={}){let a=e.find((o)=>o.id===t)||Jo(e,t);if(!a)return null;if(a.status="closed",a.closedRound=a.closedRound||i,r)a.evidence=se([...a.evidence||[],r],4);if(Array.isArray(n))a.sourceIds=se([...a.sourceIds||[],...n],8);return a}function tr(e){let t=e.length,r=e.filter((n)=>n.status==="closed").length;return{total:t,closed:r,open:Math.max(0,t-r)}}function qr(e,t,r){if(!t?.answer||r?.ok!==!0)return e;let n=Array.isArray(t.claims)?t.claims:[],i=Array.isArray(r.cited)?r.cited:[];if(n.length===0||i.length===0)return e;for(let a of e){if(a.status==="closed")continue;let o=null,s=0;for(let l of n){let c=jr(a.question||"",l.claim||"");if(c>s)s=c,o=l}if(a.id==="Q1"||s>=0.18)Yo(e,a.id,{evidence:o?.claim||"Answered in final cited synthesis",sourceIds:Array.isArray(o?.sourceIds)?o.sourceIds:i.slice(0,4)})}return e}function Wo(e){if(!e.length)return"No tracked questions.";return e.map((t)=>{let r=t.sourceIds?.length?` (${t.sourceIds.join(", ")})`:"";return`- [${t.status==="closed"?"x":" "}] ${t.id}: ${t.question}${r}`}).join(`
|
|
421
|
-
`)}function Ve(e,t="None recorded."){let r=se(e);return r.length?r.map((n)=>`- ${n}`).join(`
|
|
422
|
-
`):t}function Bo(e,{query:t,rounds:r,sources:n,fetchedSources:i,citationAudit:a,citationUrls:o,floor:s,manifest:l}){let c=(i||[]).filter((h)=>h?.contentChars>100||h?.fetch?.ok),u=(n||[]).filter((h)=>["official-docs","repo","maintainer-blog","academic"].includes(String(h?.sourceType||""))),d=new Set(a?.cited||[]),p=(n||[]).filter((h)=>d.has(h?.id)),f=[`# Provenance: ${t}`,"",`- **Date:** ${l?.startedAt||new Date().toISOString()}`,`- **Duration:** ${l?.durationMs?`${(l.durationMs/1000).toFixed(1)}s`:"unknown"}`,`- **Mode:** ${l?.terminationReason==="simple_single_pass"?"simple (single-pass)":"iterative"}`,`- **Rounds:** ${l?.rounds||r?.length||1}`,"","## Sources","",`- **Consulted:** ${n?.length||0}`,`- **Fetched successfully:** ${c.length}`,`- **Primary sources:** ${u.length}`,`- **Cited in report:** ${p.length}`,""];if(p.length>0){f.push("### Cited sources","");for(let h of p){let g=h.canonicalUrl||h.finalUrl||h.url||"",y=h.fetch?.ok?"✓":"✗";f.push(`- **${h.id}:** [${h.title||g}](${g}) (${h.sourceType||"unknown"}, fetched: ${y})`)}f.push("")}if(o&&(o.reachable.length>0||o.dead.length>0)){if(f.push("## URL reachability",""),o.dead.length>0){f.push(""),f.push("**Dead links:**");for(let h of o.dead)f.push(`- ${h.id}: ${h.url} (${h.httpStatus||h.error||"unknown"})`)}if(o.reachable.length>0)f.push(""),f.push(`**Reachable:** ${o.reachable.length}/${o.reachable.length+o.dead.length}`);f.push("")}let m=!a?"NOT CHECKED":a.ok&&(o?.ok??!0)?"PASS":a.ok===!1?"FAIL (missing citations)":"FAIL (dead links)";if(f.push("## Verification","",`- **Citations:** ${a?.ok?"PASS":`FAIL — missing: ${(a?.missing||[]).join(", ")}`}`,`- **URL reachability:** ${o?o.ok?"PASS":`FAIL — ${o.dead.length} dead`:"SKIPPED"}`,`- **Floor:** ${s?.floorMet?"PASS":"PARTIAL"}`,`- **Overall:** ${m}`,""),s?.checks){f.push("## Floor checks","");for(let[h,g]of Object.entries(s.checks))f.push(`- [${g?"x":" "}] ${h}`);f.push("")}C(_(e,"provenance.md"),f.join(`
|
|
423
|
-
`),"utf8")}async function Jr({query:e,rounds:t,sources:r,fetchedSources:n,evidenceItems:i=[],synthesis:a,citationAudit:o,floor:s,manifest:l,allGaps:c=[],questions:u=[],citationUrls:d=null,outDir:p=null}){let f=new Date().toISOString().replaceAll(/[:.]/g,"-").slice(0,19),m=p||_(Io,`${f}_${jo(e)}`),h=_(m,"reports"),g=_(m,"sources"),y=_(m,"data");Qe(h,{recursive:!0}),Qe(g,{recursive:!0}),Qe(y,{recursive:!0});let v=await To(n,g),b=se([...c,...t.flatMap((w)=>w.gaps||[])]);C(_(m,"STATUS.md"),[s.floorMet?"STATUS: DONE":"STATUS: PARTIAL","",`Query: ${e}`,`Stop reason: ${l.terminationReason||"max_rounds"}`,"","## Deterministic floor checks",...Object.entries(s.checks).map(([w,E])=>`- [${E?"x":" "}] ${w}`),"","## Questions",Wo(u),"","## Open gaps",Ve(b),""].join(`
|
|
424
|
-
`),"utf8"),C(_(m,"OUTLINE.md"),["# Research bundle outline","","- `reports/SUMMARY.md` — final cited report","- `reports/CLAIMS.md` — extracted claims with support/source IDs","- `reports/EVIDENCE.md` — goal-based source evidence","- `reports/GAPS.md` — remaining caveats and uncertainties","- `provenance.md` — human-readable run metadata and verification","- `sources/` — fetched source markdown files","- `data/manifest.json` — machine-readable run metadata","- `data/rounds.json` — per-round actions/learnings/gaps","- `data/sources.json` — ranked source registry","- `data/questions.json` — open/closed question ledger",""].join(`
|
|
425
|
-
`),"utf8"),C(_(h,"SUMMARY.md"),String(a.answer||""),"utf8"),C(_(h,"CLAIMS.md"),["# Key claims","",...Array.isArray(a.claims)&&a.claims.length?a.claims.map((w)=>{let E=Array.isArray(w.sourceIds)?w.sourceIds.join(", "):"";return`- ${w.claim||""} (${w.support||"support unknown"}${E?`; ${E}`:""})`}):["No structured claims were extracted."],""].join(`
|
|
426
|
-
`),"utf8"),C(_(h,"EVIDENCE.md"),["# Extracted evidence","",...i.length?i.map((w)=>[`## ${w.sourceId||w.url||"Source"}`,w.url?`<${w.url}>`:"",w.rational?`**Rational:** ${w.rational}`:"",w.evidence?`**Evidence:** ${w.evidence}`:"",w.summary?`**Summary:** ${w.summary}`:"",""].filter(Boolean).join(`
|
|
427
|
-
`)):["No goal-based evidence was extracted."],""].join(`
|
|
428
|
-
`),"utf8"),C(_(h,"GAPS.md"),["# Gaps and caveats","","## Caveats",Ve(a.caveats||[]),"","## Research gaps",Ve(b),""].join(`
|
|
429
|
-
`),"utf8"),C(_(y,"manifest.json"),JSON.stringify({...l,floor:s,citationAudit:o},null,2),"utf8"),C(_(y,"rounds.json"),JSON.stringify(t,null,2),"utf8"),C(_(y,"sources.json"),JSON.stringify(r,null,2),"utf8"),C(_(y,"questions.json"),JSON.stringify(u,null,2),"utf8"),C(_(y,"evidence.json"),JSON.stringify(i,null,2),"utf8"),C(_(g,"index.md"),["# Source index","",...v.map((w)=>{let E=w.title||w.url,A=w.finalUrl||w.url,S=w.contentPath?` — ${w.contentPath}`:"";return`- ${w.id||"?"}: [${E}](${A})${S}`}),""].join(`
|
|
430
|
-
`),"utf8");try{Bo(m,{query:e,rounds:t,sources:r,fetchedSources:n,citationAudit:o,citationUrls:d,floor:s,manifest:l})}catch(w){process.stderr.write(`[greedysearch] Provenance sidecar write failed (non-critical): ${w.message}
|
|
431
|
-
`)}return{dir:m,statusPath:_(m,"STATUS.md"),summaryPath:_(h,"SUMMARY.md"),manifestPath:_(y,"manifest.json"),provenancePath:_(m,"provenance.md"),sourceCount:v.length,sourceFiles:v}}function Qo(e){let t="",r=!1,n=!1;for(let i of String(e)){if(n){t+=i,n=!1;continue}if(i==="\\"){t+=i,n=!0;continue}if(i==='"'){r=!r,t+=i;continue}if(r&&i===`
|
|
432
|
-
`)t+="\\n";else if(r&&i==="\r")t+="\\r";else if(r&&i==="\t")t+="\\t";else t+=i}return t}function xe(e){if(!e)return null;let t=String(e).trim(),r=t.indexOf("BEGIN_JSON"),n=t.indexOf("END_JSON");if(r!==-1&&n!==-1&&r<n)t=t.slice(r+10,n).trim();else{let s=t.indexOf("{");if(s>0)t=t.slice(s)}let i=[t,t.replace(/^```json\s*/i,"").replace(/^```\s*/i,"").replace(/```$/i,"").trim()],a=t.indexOf("{"),o=t.lastIndexOf("}");if(a!==-1&&o!==-1&&a<o)i.push(t.slice(a,o+1));for(let s of[...i]){let l=Qo(s);if(l!==s)i.push(l)}for(let s of i)try{return JSON.parse(s)}catch{}return null}import{mkdirSync as Ko,writeFileSync as Vo}from"node:fs";import{join as Yr}from"node:path";var zo=Yr(process.cwd(),".dm","greedysearch-sources");function wt(e,t=zo){return Ko(t,{recursive:!0}),e.map((r)=>{if(!r.content||r.content.length<10)return r;let n=String(r.id||"unknown").replace(/[^a-zA-Z0-9_-]/g,""),i=(r.canonicalUrl||r.url||"").replace(/^https?:\/\//,"").replace(/[^a-zA-Z0-9]/g,"-").slice(0,40),a=`${n}-${i}.md`,o=Yr(t,a),s=`---
|
|
433
|
-
url: ${r.finalUrl||r.url}
|
|
434
|
-
title: ${r.title||""}
|
|
435
|
-
source: ${r.source||"unknown"}
|
|
436
|
-
status: ${r.status||""}
|
|
437
|
-
chars: ${r.contentChars||r.content.length}
|
|
438
|
-
---
|
|
439
|
-
|
|
440
|
-
`;Vo(o,s+r.content,"utf8");let{content:l,...c}=r;return{...c,contentPath:o,contentChars:r.contentChars||l.length}})}import{createRequire as Zo}from"node:module";import{createRequire as Xo}from"node:module";import{spawn as $s}from"node:child_process";import{basename as _s}from"node:path";import{dirname as Es,join as Ss}from"node:path";import{fileURLToPath as Rs}from"node:url";import{fileURLToPath as Ds}from"node:url";import{existsSync as je,mkdirSync as As,readFileSync as dn,writeFileSync as Cs}from"node:fs";import{homedir as ks}from"node:os";import{join as fn}from"node:path";import{tmpdir as Os}from"node:os";import{existsSync as Te,mkdirSync as Ns,readFileSync as pn,writeFileSync as Ps}from"node:fs";import{homedir as xs}from"node:os";import{join as hn}from"node:path";import{tmpdir as Is}from"node:os";import{existsSync as Le,mkdirSync as Zs,readFileSync as bn,writeFileSync as Xs}from"node:fs";import{homedir as el}from"node:os";import{join as vn}from"node:path";import{tmpdir as tl}from"node:os";var mu=Zo(import.meta.url),wu=Xo(import.meta.url),Ie=null;async function es(){if(Ie)return Ie;let[{Readability:e},{JSDOM:t},{default:r}]=await Promise.all([import("@mozilla/readability"),import("jsdom"),import("turndown")]),n=new r({headingStyle:"atx",bulletListMarker:"-",codeBlockStyle:"fenced"});return n.addRule("removeDataUrls",{filter:(i)=>i.tagName==="IMG"&&i.getAttribute("src")?.startsWith("data:"),replacement:()=>""}),Ie={Readability:e,JSDOM:t,turndown:n},Ie}var rn="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36",nn={"user-agent":rn,accept:"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8","accept-language":"en-US,en;q=0.9","accept-encoding":"gzip, deflate, br","cache-control":"no-cache",pragma:"no-cache","sec-ch-ua":'"Chromium";v="122", "Not(A:Brand";v="24", "Google Chrome";v="122"',"sec-ch-ua-mobile":"?0","sec-ch-ua-platform":'"Windows"',"sec-fetch-dest":"document","sec-fetch-mode":"navigate","sec-fetch-site":"none","sec-fetch-user":"?1","upgrade-insecure-requests":"1"},an=[/^localhost$/i,/^127\.\d+\.\d+\.\d+$/,/^0\.0\.0\.0$/,/^\[::1\]$/,/^10\./,/^172\.(1[6-9]|2\d|3[01])\./,/^192\.168\./,/^169\.254\./,/^fc00:/i,/^fe80:/i,/\.local$/i,/\.internal$/i,/\.localhost$/i],ts=/^::ffff:(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/i,rs=/^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/i,ns=/^(?:0x[0-9a-f]+|0[0-7]*|[1-9][0-9]*)$/i;function is(e){if(!e||e.includes(":"))return null;let t=e.split(".");if(t.length<1||t.length>4)return null;if(!t.every((i)=>ns.test(i)))return null;let r=t.map((i)=>{if(/^0x/i.test(i))return parseInt(i,16);if(/^0[0-7]+$/.test(i))return parseInt(i,8);return parseInt(i,10)});if(r.some((i)=>!Number.isFinite(i)||i<0))return null;let n;if(r.length===1){if(r[0]>4294967295)return null;n=[r[0]>>>24&255,r[0]>>>16&255,r[0]>>>8&255,r[0]&255]}else if(r.length===2){if(r[0]>255||r[1]>16777215)return null;n=[r[0],r[1]>>>16&255,r[1]>>>8&255,r[1]&255]}else if(r.length===3){if(r[0]>255||r[1]>255||r[2]>65535)return null;n=[r[0],r[1],r[2]>>>8&255,r[2]&255]}else{if(r.some((i)=>i>255))return null;n=r}return n.join(".")}function as(e){let t=e.match(ts);if(t)return`${t[1]}.${t[2]}.${t[3]}.${t[4]}`;let r=e.match(rs);if(r){let n=parseInt(r[1],16),i=parseInt(r[2],16);if(n>65535||i>65535)return null;return[n>>>8&255,n&255,i>>>8&255,i&255].join(".")}return null}function Wr(e){return an.some((t)=>t.test(e))}function os(e={}){return{...nn,...e}}function _t(e){try{if(typeof e!=="string"||!e.trim())return{blocked:!0,reason:"URL must be a non-empty string"};let t=new URL(e);if(t.protocol!=="http:"&&t.protocol!=="https:")return{blocked:!0,reason:`Protocol not allowed: ${t.protocol}`};let r=t.hostname.toLowerCase();for(let i of an)if(i.test(r))return{blocked:!0,reason:`Private/internal address: ${r}`};if(r.startsWith("[")&&r.endsWith("]")){let i=r.slice(1,-1),a=as(i);if(a&&Wr(a))return{blocked:!0,reason:`Private/internal address: ${r} (maps to ${a})`}}let n=is(r);if(n&&Wr(n))return{blocked:!0,reason:`Private/internal address: ${r} (normalizes to ${n})`};return{blocked:!1}}catch(t){return{blocked:!0,reason:`Invalid URL: ${t.message}`}}}function ss(e){try{let t=new URL(e);if(!(t.hostname==="github.com"||t.hostname.endsWith(".github.com")))return e;let r=t.pathname.split("/").filter(Boolean);if(r.length<5)return e;let[n,i,a,o,...s]=r;if(a!=="blob")return e;let l=s.join("/");return`https://raw.githubusercontent.com/${n}/${i}/${o}/${l}`}catch{return e}}async function ls(e,t={}){let r=_t(e);if(r.blocked)return{ok:!1,url:e,finalUrl:e,status:403,error:`Blocked: ${r.reason}`,needsBrowser:!1};let n=e;if(e=ss(e),e!==n)console.error(`[fetcher] Rewrote GitHub URL: ${n.slice(0,60)}... → raw.githubusercontent.com`);let{timeoutMs:i=15000,userAgent:a,signal:o}=t,s=new AbortController,l=setTimeout(()=>s.abort(),i);if(o)o.addEventListener("abort",()=>s.abort(),{once:!0});try{let c=await fetch(e,{method:"GET",headers:{...nn,"user-agent":a||rn},redirect:"follow",signal:s.signal});clearTimeout(l);let u=c.headers.get("content-type")||"",d=c.url,p=c.headers.get("last-modified")||"",f=_t(d);if(f.blocked)return{ok:!1,url:e,finalUrl:d,status:c.status,error:`Blocked: ${f.reason}`,needsBrowser:!1};let m=!1;try{m=new URL(d).hostname.toLowerCase()==="raw.githubusercontent.com"}catch{}if(u.includes("text/plain")&&m){let b=await c.text();return{ok:!0,url:n,finalUrl:d,status:c.status,title:d.split("/").pop()||"GitHub File",byline:"",siteName:"GitHub",lang:"",publishedTime:p,lastModified:p,markdown:b,contentLength:b.length,excerpt:b.slice(0,300).replaceAll(/\n/g," "),needsBrowser:!1}}if(!u.includes("text/html")&&!u.includes("application/xhtml"))return{ok:!1,url:e,finalUrl:d,status:c.status,error:`Unsupported content type: ${u}`,needsBrowser:!1};let h=await c.text(),g=on(c.status,h,d,e);if(g.blocked)return{ok:!1,url:e,finalUrl:d,status:c.status,error:`Blocked: ${g.reason}`,needsBrowser:!0};let y=await sn(h,d),v=ln(y);if(!v.ok)return{ok:!1,url:e,finalUrl:d,status:c.status,error:`Low quality content: ${v.reason}`,needsBrowser:!0};return{ok:!0,url:e,finalUrl:d,status:c.status,title:y.title,byline:y.byline,siteName:y.siteName,lang:y.lang,publishedTime:y.publishedTime||p,lastModified:p,markdown:y.markdown,excerpt:y.excerpt,contentLength:y.markdown.length,needsBrowser:!1}}catch(c){clearTimeout(l);let u=ps(c);return{ok:!1,url:e,finalUrl:e,status:0,error:c.message,needsBrowser:u}}}function on(e,t,r,n){let i=t.match(/<title[^>]*>([^<]*)<\/title>/i)?.[1]?.toLowerCase()||"",a=t.slice(0,30000).toLowerCase(),o=`${i} ${a}`;if(e===403||e===429||e===503)return{blocked:!0,reason:`HTTP ${e}`};let s=[{pattern:/class=["'][^"']*captcha["']|<div[^>]*id=["']captcha/i,reason:"captcha"},{pattern:/g-recaptcha|data-sitekey|i['"]m not a robot/i,reason:"captcha"},{pattern:/checking your browser.{0,100}please wait|cf-browser-verification/i,reason:"cloudflare challenge"},{pattern:/just a moment.{0,50}security check|ddos protection by cloudflare/i,reason:"cloudflare challenge"},{pattern:/unusual traffic.{0,50}from your computer network/i,reason:"unusual traffic"},{pattern:/bot detected|automated.{0,20}request/i,reason:"bot detection"},{pattern:/enable\s+javascript\s+to\s+view|javascript\s+is\s+required.{0,50}enabled/i,reason:"requires javascript"},{pattern:/access denied|accessdenied/i,reason:"access denied"},{pattern:/protected by anubis|anubis uses a proof-of-work/i,reason:"anubis challenge"}];for(let c of s)if(c.pattern.test(o))return{blocked:!0,reason:c.reason};let l=fs(n,r,t);if(l)return{blocked:!0,reason:l};return{blocked:!1}}var cs=["accounts.google.com","login.microsoftonline.com","login.live.com","auth0.com","okta.com","auth.mozilla.auth0.com","id.atlassian.com"],us=["login.","signin.","auth.","sso.","accounts.","idp."],ds=["sign in to continue","log in to continue","authentication required","create an account to continue","subscribe to continue reading","members only"];function fs(e,t,r){try{let n=new URL(e),i=new URL(t);if(n.hostname.toLowerCase()===i.hostname.toLowerCase())return;let a=i.hostname.toLowerCase();if(cs.some((s)=>a===s||a.endsWith(`.${s}`)))return`redirected to login (${i.hostname})`;if(us.some((s)=>a.startsWith(s)))return`redirected to login (${i.hostname})`;let o=r.slice(0,20000).toLowerCase();if(ds.some((s)=>o.includes(s)))return`redirected to login page (${i.hostname})`}catch{}return}function ps(e){let t=e.message.toLowerCase();return t.includes("fetch failed")||t.includes("unable to verify")||t.includes("certificate")||t.includes("timeout")}function Br(e){let t=['meta[property="article:published_time"]','meta[name="article:published_time"]','meta[property="og:published_time"]','meta[name="publication_date"]','meta[name="date"]','meta[itemprop="datePublished"]','time[itemprop="datePublished"]','meta[name="DC.date"]'];for(let r of t){let n=e.querySelector(r),i=n?.getAttribute("content")||n?.getAttribute("datetime")||"";if(i)return i}return""}async function sn(e,t){let{Readability:r,JSDOM:n,turndown:i}=await es(),a=new n(e,{url:t});try{let o=a.window.document,s=new r(o).parse();if(s&&s.content){let c=i.turndown(s.content).replaceAll(/\n{3,}/g,`
|
|
441
|
-
|
|
442
|
-
`).trim(),u=s.publishedTime||Br(o)||"";return{title:s.title||o.title||t,byline:s.byline||"",siteName:s.siteName||"",lang:s.lang||"",publishedTime:u,markdown:c,excerpt:c.slice(0,300).replaceAll(/\n/g," ")}}let l=o.body;if(l){let c=l.cloneNode(!0);c.querySelectorAll("script, style, nav, footer, header, aside").forEach((d)=>d.remove());let u=(c.textContent||"").replaceAll(/\s+/g," ").trim();return{title:o.title||t,byline:"",siteName:"",lang:"",publishedTime:Br(o),markdown:u,excerpt:u.slice(0,300)}}return{title:t,byline:"",siteName:"",lang:"",publishedTime:"",markdown:"",excerpt:""}}finally{a.window.close()}}function ln(e){let t=e.markdown.trim().toLowerCase(),r=(e.title||"").toLowerCase();if(e.markdown.trim().length<100)return{ok:!1,reason:"content too short (< 100 chars)"};let n=t.toLowerCase(),i=[{check:()=>n.includes("loading")&&n.includes("please wait"),desc:"loading page"},{check:()=>n.includes("please ensure javascript is enabled"),desc:"requires javascript"},{check:()=>n.includes("enable javascript to view"),desc:"requires javascript"},{check:()=>n.includes("just a moment"),desc:"cloudflare challenge detected in content"},{check:()=>n.includes("verify you are human"),desc:"human verification"},{check:()=>n.includes("captcha required"),desc:"captcha in extracted content"},{check:()=>n.includes("access denied"),desc:"access denied in content"},{check:()=>/^\s{0,10}sign\s{1,5}in\s{0,10}$|^\s{0,10}log\s{1,5}in\s{0,10}$/im.test(t),desc:"login form only"}];for(let{check:a,desc:o}of i)if(a())return{ok:!1,reason:o};if(r.includes("just a moment")||r.includes("checking your browser"))return{ok:!1,reason:"cloudflare challenge page detected in title"};return{ok:!0}}var cn={"user-agent":"GreedySearch/1.0",accept:"application/vnd.github+json","x-github-api-version":"2022-11-28"};function Et(e){try{let t=new URL(e);if(!(t.hostname==="github.com"||t.hostname.endsWith(".github.com")))return null;let r=t.pathname.split("/").filter(Boolean);if(r.length<2)return null;let[n,i]=r;if(r.length===2)return{owner:n,repo:i,type:"root"};if(r.length>=4&&(r[2]==="blob"||r[2]==="tree")){let a=r[2],o=r[3],s=r.slice(4).join("/");return{owner:n,repo:i,type:a,ref:o,path:s}}return null}catch{return null}}async function T(e,t=1e4){let r=new AbortController,n=setTimeout(()=>r.abort(),t);try{let i=await fetch(`https://api.github.com${e}`,{headers:cn,signal:r.signal});if(clearTimeout(n),!i.ok)throw Error(`GitHub API ${i.status}: ${e}`);return await i.json()}catch(i){throw clearTimeout(n),i}}async function hs(e,t){try{let r=await T(`/repos/${e}/${t}/readme`);if(r.content&&r.encoding==="base64")return Buffer.from(r.content,"base64").toString("utf8");return""}catch{return""}}async function Qr(e,t,r="HEAD",n="",i){try{let a;if(r==="HEAD")if(i)a=await T(`/repos/${e}/${t}/git/ref/heads/${i}`).catch(()=>null);else a=await Promise.any([T(`/repos/${e}/${t}/git/ref/heads/main`),T(`/repos/${e}/${t}/git/ref/heads/master`)]).catch(()=>null);else a=await T(`/repos/${e}/${t}/git/ref/heads/${r}`).catch(()=>T(`/repos/${e}/${t}/git/ref/heads/master`).catch(()=>null));if(!a?.object?.sha)return[];let o=(await T(`/repos/${e}/${t}/git/commits/${a.object.sha}`)).tree.sha,s=(await T(`/repos/${e}/${t}/git/trees/${o}`)).tree||[];if(n)s=s.filter((l)=>l.path.startsWith(n));return s.slice(0,50).map((l)=>({path:l.path,type:l.type==="tree"?"dir":"file",size:l.size}))}catch{return[]}}async function gs(e,t,r,n,i=1e4,a){let o=async(l)=>{let c=new AbortController,u=setTimeout(()=>c.abort(),i);try{let d=await fetch(l,{headers:{"user-agent":cn["user-agent"]},signal:c.signal});if(clearTimeout(u),d.ok)return await d.text();throw Error("not ok")}catch{throw clearTimeout(u),Error("failed")}};if(!r||r==="HEAD"){if(a)try{return await o(`https://raw.githubusercontent.com/${e}/${t}/${a}/${n}`)}catch{return null}try{return await Promise.any([o(`https://raw.githubusercontent.com/${e}/${t}/main/${n}`),o(`https://raw.githubusercontent.com/${e}/${t}/master/${n}`)])}catch{return null}}let s=[`https://raw.githubusercontent.com/${e}/${t}/${r}/${n}`,`https://raw.githubusercontent.com/${e}/${t}/master/${n}`];for(let l of s)try{return await o(l)}catch{}return null}async function ms(e){let t=Et(e);if(!t)return{ok:!1,error:"Not a valid GitHub URL"};let{owner:r,repo:n,type:i,ref:a,path:o}=t;try{if(i==="root"||i==="tree"&&!o){let s=await T(`/repos/${r}/${n}`),[l,c]=await Promise.allSettled([hs(r,n),Qr(r,n,a||"HEAD","",s.default_branch)]),u=l.status==="fulfilled"?l.value:"",d=c.status==="fulfilled"?c.value:[],p=s?.description?`
|
|
443
|
-
|
|
444
|
-
> ${s.description}`:"",f=s?.stargazers_count==null?"":` ⭐ ${s.stargazers_count}`,m=s?.language?` · ${s.language}`:"",h=`# ${r}/${n}${f}${m}${p}
|
|
445
|
-
|
|
446
|
-
`;if(u)h+=u.slice(0,6000);else h+=`[No README found]
|
|
447
|
-
|
|
448
|
-
Files:
|
|
449
|
-
${d.map((g)=>` ${g.type==="dir"?"\uD83D\uDCC1":"\uD83D\uDCC4"} ${g.path}`).join(`
|
|
450
|
-
`)}`;return{ok:!0,title:`${r}/${n}`,content:h,tree:d.slice(0,30)}}if(i==="blob"&&o){let s;if(!a||a==="HEAD")try{s=(await T(`/repos/${r}/${n}`)).default_branch}catch{s=void 0}let l=await gs(r,n,a,o,1e4,s);if(l===null)return{ok:!1,error:`File not found: ${o}`};return{ok:!0,title:`${r}/${n}: ${o}`,content:l}}if(i==="tree"&&o){let s;if(!a||a==="HEAD")try{s=(await T(`/repos/${r}/${n}`)).default_branch}catch{s=void 0}let l=await Qr(r,n,a||"HEAD",o,s),c=l.map((u)=>` ${u.type==="dir"?"\uD83D\uDCC1":"\uD83D\uDCC4"} ${u.path}`).join(`
|
|
451
|
-
`);return{ok:!0,title:`${r}/${n}/${o}`,content:`[Directory: ${o}]
|
|
452
|
-
|
|
453
|
-
Files:
|
|
454
|
-
${c}`,tree:l}}return{ok:!1,error:"Unsupported GitHub URL type"}}catch(s){return{ok:!1,error:s.message}}}var ys={"user-agent":"GreedySearch/1.0 (Research Bot)",accept:"application/json"};function ws(e){try{let t=new URL(e),r=t.hostname.toLowerCase();if(!(r==="reddit.com"||r.endsWith(".reddit.com")))return null;let n=t.pathname;if(n.match(/^\/(u|user)\/[^/]+\/?$/i))return{type:"user",cleanUrl:Kr(e)};if(n.match(/^\/r\/[^/]+\/comments\/[^/]+/i))return{type:"post",cleanUrl:Kr(e)};return null}catch{return null}}function Kr(e){try{let t=new URL(e);return`${t.protocol}//${t.hostname}${t.pathname}`}catch{return e}}async function bs(e,t=8000){let r=Date.now();try{let n=e.replace(/\/+$/,"")+".json",i=new AbortController,a=setTimeout(()=>i.abort(),15000),o=await fetch(n,{headers:ys,signal:i.signal});if(clearTimeout(a),!o.ok)throw Error(`Reddit API ${o.status}`);let s=await o.json();if(!Array.isArray(s)||s.length<1)throw Error("Invalid Reddit API response structure");let l=s[0],c=s[1],u=l?.data?.children?.[0]?.data;if(!u)throw Error("No post data in Reddit response");let d=vs(u,c,t);return{ok:!0,url:e,finalUrl:e,status:200,contentType:"text/markdown",lastModified:"",title:u.title||"Reddit Post",byline:`u/${u.author}`,siteName:`r/${u.subreddit}`,lang:"en",publishedTime:new Date(u.created_utc*1000).toISOString(),excerpt:u.selftext?.slice(0,300).replace(/\n/g," ")||"",markdown:d,contentLength:d.length,needsBrowser:!1,duration:Date.now()-r}}catch(n){return{ok:!1,url:e,finalUrl:e,status:0,error:`Reddit fetch failed: ${n.message}`,needsBrowser:!1,duration:Date.now()-r}}}function vs(e,t,r){let n="";if(n+=`# ${e.title}
|
|
455
|
-
|
|
456
|
-
`,n+=`**Subreddit:** r/${e.subreddit} | **Author:** u/${e.author} | **Score:** ${e.score}
|
|
457
|
-
|
|
458
|
-
`,e.selftext)n+=e.selftext,n+=`
|
|
459
|
-
|
|
460
|
-
`;else if(e.url)try{let i=new URL(e.url).hostname.toLowerCase();if(i!=="reddit.com"&&!i.endsWith(".reddit.com"))n+=`**Link:** ${e.url}
|
|
461
|
-
|
|
462
|
-
`}catch{n+=`**Link:** ${e.url}
|
|
463
|
-
|
|
464
|
-
`}if(t?.data?.children?.length>0){n+=`---
|
|
465
|
-
|
|
466
|
-
## Comments
|
|
467
|
-
|
|
468
|
-
`;let i=t.data.children.filter((a)=>a.kind==="t1").slice(0,10);for(let a of i)n+=un(a.data,0),n+=`
|
|
469
|
-
`}if(n.length>r)n=n.slice(0,r).trim()+`
|
|
470
|
-
|
|
471
|
-
... (truncated)`;return n}function un(e,t){if(!e||e.body==="[deleted]"||e.body==="[removed]")return"";let r="> ".repeat(t),n="";if(n+=`${r}**u/${e.author}** (${e.score} pts)
|
|
472
|
-
`,n+=`${r}${e.body.replaceAll(`
|
|
473
|
-
`,`
|
|
474
|
-
`+r)}
|
|
475
|
-
`,t<3&&e.replies?.data?.children){let i=e.replies.data.children.filter((a)=>a.kind==="t1");for(let a of i.slice(0,5))n+=`
|
|
476
|
-
`+un(a.data,t+1)}return n}function ne(e,t=8000){if(!e||e.length<=t)return e;let r=`
|
|
477
|
-
|
|
478
|
-
[...content trimmed...]
|
|
479
|
-
|
|
480
|
-
`,n=t-r.length,i=Math.floor(n*0.75),a=n-i,o=i;while(o>i-100&&e[o]!==`
|
|
481
|
-
`)o--;if(o<=i-100)o=i;let s=e.length-a;while(s<e.length-a+100&&e[s]!==`
|
|
482
|
-
`)s++;if(s>=e.length-a+100)s=e.length-a;let l=e.slice(0,o).trimEnd(),c=e.slice(s).trimStart();return`${l}${r}${c}`}function js(e=process.env,t=process.execPath){let r=e.GREEDY_SEARCH_NODE||e.NODE_BINARY||e.NODE;if(r?.trim())return r.trim();let n=_s(t||"").toLowerCase();if(n==="node"||n==="node.exe")return t;return"node"}var Ts=Es(Rs(import.meta.url)),Ls=Ss(Ts,"..","bin","cdp.mjs"),Ms=new Set(["list","snap","eval","shot","html","nav","net","click","clickxy","type","loadall","evalraw","browse","stop","--tab"]);function Us(e){if(!Array.isArray(e)||e.length===0)throw Error("cdp: args must be a non-empty array");if(e[0]==="test")return e.map((t,r)=>Vr(t,r));if(!Ms.has(e[0]))throw Error(`cdp: unknown subcommand '${e[0]}'`);return e.map((t,r)=>Vr(t,r))}function Vr(e,t){if(typeof e!=="string")throw Error(`cdp: argv[${t}] must be a string (got ${typeof e})`);if(e.includes("\x00"))throw Error(`cdp: argv[${t}] contains a null byte`);return e}function gn(e,t=30000){return Gs(e,null,t)}function Gs(e,t=null,r=30000){let n=Us(e);return new Promise((i,a)=>{let o=$s(js(),[Ls,...n],{stdio:[t==null?"ignore":"pipe","pipe","pipe"]});if(t!=null)o.stdin.write(t),o.stdin.end();let s="",l="";o.stdout.on("data",(u)=>s+=u),o.stderr.on("data",(u)=>l+=u);let c=setTimeout(()=>{o.kill(),a(Error(`cdp timeout: ${e[0]}`))},r);o.on("close",(u)=>{if(clearTimeout(c),u===0)i(s.trim());else a(Error(l.trim()||`cdp exit ${u}`))})})}async function zr(e){await gn(["evalraw",e,"Page.addScriptToEvaluateOnNewDocument",JSON.stringify({source:`
|
|
483
|
-
(function() {
|
|
484
|
-
// ── Runtime.enable / CDP detection masking ──────────────
|
|
485
|
-
try { delete window.__REBROWSER_RUNTIME_ENABLE; } catch(_) {}
|
|
486
|
-
try { delete window.__REBROWSER_DEVTOOLS; } catch(_) {}
|
|
487
|
-
try { delete window.__nightmare; } catch(_) {}
|
|
488
|
-
try { delete window.__phantom; } catch(_) {}
|
|
489
|
-
try { delete window.callPhantom; } catch(_) {}
|
|
490
|
-
try { delete window._phantom; } catch(_) {}
|
|
491
|
-
try { delete window.Buffer; } catch(_) {}
|
|
492
|
-
|
|
493
|
-
// Real Chrome without automation should not expose navigator.webdriver at all.
|
|
494
|
-
// A literal false or an own-property getter returning undefined is itself a
|
|
495
|
-
// common stealth tell; remove both instance and prototype properties when the
|
|
496
|
-
// descriptor is configurable (as it is with --disable-blink-features).
|
|
497
|
-
try { delete navigator.webdriver; } catch(_) {}
|
|
498
|
-
try { delete Navigator.prototype.webdriver; } catch(_) {}
|
|
499
|
-
Object.defineProperty(navigator, 'vendor', { get: () => 'Google Inc.', configurable: true });
|
|
500
|
-
Object.defineProperty(navigator, 'platform', { get: () => 'Win32', configurable: true });
|
|
501
|
-
Object.defineProperty(navigator, 'maxTouchPoints', { get: () => 0, configurable: true });
|
|
502
|
-
Object.defineProperty(navigator, 'pdfViewerEnabled', { get: () => true, configurable: true });
|
|
503
|
-
Object.defineProperty(navigator, 'productSub', { get: () => '20030107', configurable: true });
|
|
504
|
-
Object.defineProperty(navigator, 'product', { get: () => 'Gecko', configurable: true });
|
|
505
|
-
var __greedyMimeTypes = null;
|
|
506
|
-
function __makeMimeTypes() {
|
|
507
|
-
var pdf = { type: 'application/pdf', suffixes: 'pdf', description: 'Portable Document Format', enabledPlugin: null };
|
|
508
|
-
var textPdf = { type: 'text/pdf', suffixes: 'pdf', description: 'Portable Document Format', enabledPlugin: null };
|
|
509
|
-
try { Object.setPrototypeOf(pdf, MimeType.prototype); } catch(_) {}
|
|
510
|
-
try { Object.setPrototypeOf(textPdf, MimeType.prototype); } catch(_) {}
|
|
511
|
-
var m = [pdf, textPdf];
|
|
512
|
-
try { Object.setPrototypeOf(m, MimeTypeArray.prototype); } catch(_) {}
|
|
513
|
-
m.item = function item(i) { return this[i] || null; };
|
|
514
|
-
m.namedItem = function namedItem(name) { return Array.prototype.find.call(this, function(x) { return x && x.type === name; }) || null; };
|
|
515
|
-
return m;
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
function annotateFetchedSourcesWithIds(fetchedSources, sources) {
|
|
134
|
+
const byUrl = new Map;
|
|
135
|
+
for (const source of sources || []) {
|
|
136
|
+
const key = normalizeUrl(source?.canonicalUrl || source?.finalUrl || source?.url);
|
|
137
|
+
if (key && source?.id)
|
|
138
|
+
byUrl.set(key, source.id);
|
|
516
139
|
}
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
try { Object.setPrototypeOf(plugin0, Plugin.prototype); } catch(_) {}
|
|
524
|
-
try { Object.setPrototypeOf(plugin1, Plugin.prototype); } catch(_) {}
|
|
525
|
-
try { Object.setPrototypeOf(plugin2, Plugin.prototype); } catch(_) {}
|
|
526
|
-
var p = [plugin0, plugin1, plugin2];
|
|
527
|
-
p.item = function item(i) { return this[i] || null; };
|
|
528
|
-
p.namedItem = function namedItem(name) { return Array.prototype.find.call(this, function(x) { return x && x.name === name; }) || null; };
|
|
529
|
-
p.refresh = function refresh() {};
|
|
530
|
-
try { Object.setPrototypeOf(p, PluginArray.prototype); } catch(_) {}
|
|
531
|
-
try {
|
|
532
|
-
__greedyMimeTypes[0].enabledPlugin = p[0];
|
|
533
|
-
__greedyMimeTypes[1].enabledPlugin = p[0];
|
|
534
|
-
} catch(_) {}
|
|
535
|
-
return p;
|
|
536
|
-
},
|
|
537
|
-
configurable: true,
|
|
140
|
+
return (fetchedSources || []).map((source, index) => {
|
|
141
|
+
const key = normalizeUrl(source?.finalUrl || source?.canonicalUrl || source?.url);
|
|
142
|
+
return {
|
|
143
|
+
...source,
|
|
144
|
+
id: source?.id || byUrl.get(key) || `F${index + 1}`
|
|
145
|
+
};
|
|
538
146
|
});
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
147
|
+
}
|
|
148
|
+
function questionProgress(questions) {
|
|
149
|
+
const total = questions.length;
|
|
150
|
+
const closed = questions.filter((q) => q.status === "closed").length;
|
|
151
|
+
return { total, closed, open: Math.max(0, total - closed) };
|
|
152
|
+
}
|
|
153
|
+
export async function runSimpleResearchMode({
|
|
154
|
+
query,
|
|
155
|
+
locale = null,
|
|
156
|
+
maxSources = 5,
|
|
157
|
+
qualityThreshold = 8.5,
|
|
158
|
+
writeBundle = process.env.GREEDY_RESEARCH_BUNDLE !== "0",
|
|
159
|
+
researchOutDir = null
|
|
160
|
+
} = {}) {
|
|
161
|
+
const startedAt = new Date().toISOString();
|
|
162
|
+
const startMs = Date.now();
|
|
163
|
+
const questions = createQuestionLedger(query);
|
|
164
|
+
const extractedSourceKeys = new Set;
|
|
165
|
+
process.stderr.write(`[greedysearch] Simple research mode: single-pass for "${trimText(query, 80)}"
|
|
166
|
+
`);
|
|
167
|
+
const searchAnglesCount = 3;
|
|
168
|
+
const totalSteps = searchAnglesCount + 1 + 2;
|
|
169
|
+
const progressTracker = createProgressTracker({
|
|
170
|
+
totalActions: totalSteps,
|
|
171
|
+
totalRounds: 1,
|
|
172
|
+
totalFetches: 1,
|
|
173
|
+
silent: process.env.GREEDY_RESEARCH_QUIET === "1"
|
|
545
174
|
});
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
try {
|
|
566
|
-
if (!navigator.share) {
|
|
567
|
-
navigator.share = function() { return Promise.reject(new Error('NotAllowedError')); };
|
|
568
|
-
}
|
|
569
|
-
} catch(_) {}
|
|
570
|
-
try {
|
|
571
|
-
if (!navigator.contentIndex) {
|
|
572
|
-
Object.defineProperty(navigator, 'contentIndex', { get: () => ({ add: function() {}, delete: function() {}, getAll: function() { return Promise.resolve([]); } }), configurable: true });
|
|
175
|
+
progressTracker.startRound(1);
|
|
176
|
+
let combinedSources = [];
|
|
177
|
+
let fetchedSources = [];
|
|
178
|
+
const searchAngles = buildSearchAngles(query);
|
|
179
|
+
const searchResults = [];
|
|
180
|
+
progressTracker.startAction("search", `${searchAngles.length} angles in parallel`);
|
|
181
|
+
const angleOutcomes = await Promise.allSettled(searchAngles.map((angle) => runFastAllSearch(angle, { locale, short: true })));
|
|
182
|
+
for (let i = 0;i < searchAngles.length; i++) {
|
|
183
|
+
const angle = searchAngles[i];
|
|
184
|
+
const outcome = angleOutcomes[i];
|
|
185
|
+
progressTracker.endAction();
|
|
186
|
+
if (outcome.status === "fulfilled") {
|
|
187
|
+
const result = outcome.value;
|
|
188
|
+
searchResults.push({ angle, result });
|
|
189
|
+
const sources = buildSourceRegistry(result, angle);
|
|
190
|
+
combinedSources = mergeSourcesByUrl(combinedSources, sources);
|
|
191
|
+
} else {
|
|
192
|
+
process.stderr.write(`[greedysearch] Simple search angle "${angle}" failed: ${outcome.reason.message}
|
|
193
|
+
`);
|
|
573
194
|
}
|
|
574
|
-
} catch(_) {}
|
|
575
|
-
|
|
576
|
-
if (!window.chrome) {
|
|
577
|
-
window.chrome = {
|
|
578
|
-
app: { isInstalled: false, InstallState: {}, RunningState: {} },
|
|
579
|
-
runtime: {
|
|
580
|
-
OnInstalledReason: {}, OnRestartRequiredReason: {}, PlatformArch: {}, PlatformNaclArch: {}, PlatformOs: {}, RequestUpdateCheckStatus: {},
|
|
581
|
-
connect: () => ({}), sendMessage: () => {}, onMessage: { addListener: () => {} }
|
|
582
|
-
},
|
|
583
|
-
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' }; },
|
|
584
|
-
csi: function() { var t = Date.now(); return { onloadT: t - 2000, startE: t - 5000, pageT: 'back', tran: 2 }; },
|
|
585
|
-
};
|
|
586
195
|
}
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
})
|
|
196
|
+
process.stderr.write(`PROGRESS:research:simple:fetching
|
|
197
|
+
`);
|
|
198
|
+
if (combinedSources.length > 0) {
|
|
199
|
+
try {
|
|
200
|
+
progressTracker.startFetch(`top ${Math.min(maxSources, combinedSources.length)} sources`);
|
|
201
|
+
fetchedSources = await fetchMultipleSources(combinedSources, Math.min(maxSources, combinedSources.length), 8000, Math.min(3, maxSources));
|
|
202
|
+
progressTracker.endFetch(true);
|
|
203
|
+
combinedSources = mergeFetchDataIntoSources(combinedSources, fetchedSources);
|
|
204
|
+
} catch (error) {
|
|
205
|
+
progressTracker.endFetch(false);
|
|
206
|
+
process.stderr.write(`[greedysearch] Source fetching failed: ${error.message}
|
|
207
|
+
`);
|
|
208
|
+
}
|
|
596
209
|
}
|
|
210
|
+
fetchedSources = annotateFetchedSourcesWithIds(fetchedSources, combinedSources);
|
|
211
|
+
process.stderr.write(`PROGRESS:research:simple:evidence
|
|
212
|
+
`);
|
|
213
|
+
let evidenceItems = [];
|
|
597
214
|
try {
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
215
|
+
const evidenceRun = await extractEvidenceFromSources({
|
|
216
|
+
query,
|
|
217
|
+
questions,
|
|
218
|
+
fetchedSources,
|
|
219
|
+
extractedSourceKeys
|
|
603
220
|
});
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
});
|
|
617
|
-
} catch(_) {}
|
|
618
|
-
Object.defineProperty(navigator, 'hardwareConcurrency', { get: () => 8, configurable: true });
|
|
619
|
-
Object.defineProperty(navigator, 'deviceMemory', { get: () => 8, configurable: true });
|
|
620
|
-
|
|
621
|
-
// ── Canvas fingerprint noise ─────────────────────────
|
|
622
|
-
// Headless rendering engines produce slightly different canvas output
|
|
623
|
-
// than headed Chrome. Subtle noise breaks hash-based fingerprinting.
|
|
624
|
-
try {
|
|
625
|
-
var __canvasNoise = ((Date.now() & 0xFF) | 1);
|
|
626
|
-
var origFill = CanvasRenderingContext2D.prototype.fillText;
|
|
627
|
-
CanvasRenderingContext2D.prototype.fillText = __markNative(function fillText() {
|
|
628
|
-
this.globalAlpha = 0.9995;
|
|
629
|
-
return origFill.apply(this, arguments);
|
|
630
|
-
});
|
|
631
|
-
} catch(_) {}
|
|
632
|
-
try {
|
|
633
|
-
var origStroke = CanvasRenderingContext2D.prototype.strokeText;
|
|
634
|
-
CanvasRenderingContext2D.prototype.strokeText = __markNative(function strokeText() {
|
|
635
|
-
this.globalAlpha = 0.9995;
|
|
636
|
-
return origStroke.apply(this, arguments);
|
|
637
|
-
});
|
|
638
|
-
} catch(_) {}
|
|
639
|
-
try {
|
|
640
|
-
var origToDataURL = HTMLCanvasElement.prototype.toDataURL;
|
|
641
|
-
HTMLCanvasElement.prototype.toDataURL = __markNative(function toDataURL() {
|
|
642
|
-
var ctx = this.getContext('2d');
|
|
643
|
-
if (ctx) {
|
|
644
|
-
// Spread noise across canvas to break hash-based fingerprinting.
|
|
645
|
-
// Uses a deterministic pattern so it's consistent per page load
|
|
646
|
-
// but varies between sessions.
|
|
647
|
-
var w = this.width, h = this.height;
|
|
648
|
-
if (w > 0 && h > 0) {
|
|
649
|
-
var imgData = ctx.getImageData(0, 0, Math.min(w, 4), Math.min(h, 4));
|
|
650
|
-
if (imgData && imgData.data) {
|
|
651
|
-
for (var __i = 0; __i < imgData.data.length; __i += 4) {
|
|
652
|
-
imgData.data[__i] ^= (__canvasNoise + __i) & 0xFF;
|
|
653
|
-
}
|
|
654
|
-
ctx.putImageData(imgData, 0, 0);
|
|
221
|
+
evidenceItems = evidenceRun.evidence || [];
|
|
222
|
+
for (const evidence of evidenceRun.evidence) {
|
|
223
|
+
const answered = Array.isArray(evidence.answers) ? evidence.answers : [];
|
|
224
|
+
for (const ans of answered) {
|
|
225
|
+
const id = ans?.id || ans?.question;
|
|
226
|
+
if (id) {
|
|
227
|
+
const target = questions.find((q) => q.id === id);
|
|
228
|
+
if (target) {
|
|
229
|
+
target.status = "closed";
|
|
230
|
+
target.closedRound = 1;
|
|
231
|
+
if (ans.evidence)
|
|
232
|
+
target.evidence = uniqueStrings([...target.evidence || [], ans.evidence], 4);
|
|
655
233
|
}
|
|
656
234
|
}
|
|
657
235
|
}
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
}
|
|
673
|
-
return data;
|
|
674
|
-
});
|
|
675
|
-
} catch(_) {}
|
|
676
|
-
|
|
677
|
-
// ── window outer dimensions ──────────────────────────
|
|
678
|
-
// outerWidth/Height = 0 in headless — a well-known bot signal.
|
|
679
|
-
// Mirror innerWidth/Height (set by --window-size flag) so the ratio is sane.
|
|
680
|
-
try {
|
|
681
|
-
if (!window.outerWidth) Object.defineProperty(window, 'outerWidth', { get: () => window.innerWidth || 1920, configurable: true });
|
|
682
|
-
if (!window.outerHeight) Object.defineProperty(window, 'outerHeight', { get: () => window.innerHeight || 1080, configurable: true });
|
|
683
|
-
} catch(_) {}
|
|
684
|
-
|
|
685
|
-
// ── screen properties ─────────────────────────────────
|
|
686
|
-
// Headless Chrome often reports an 800x600 screen even when the viewport is
|
|
687
|
-
// 1920x1080. Keep screen metrics internally consistent with our launch flags.
|
|
688
|
-
try {
|
|
689
|
-
Object.defineProperty(screen, 'width', { get: () => 1920, configurable: true });
|
|
690
|
-
Object.defineProperty(screen, 'height', { get: () => 1080, configurable: true });
|
|
691
|
-
Object.defineProperty(screen, 'availWidth', { get: () => 1920, configurable: true });
|
|
692
|
-
Object.defineProperty(screen, 'availHeight', { get: () => 1040, configurable: true });
|
|
693
|
-
Object.defineProperty(screen, 'colorDepth', { get: () => 24, configurable: true });
|
|
694
|
-
Object.defineProperty(screen, 'pixelDepth', { get: () => 24, configurable: true });
|
|
695
|
-
} catch(_) {}
|
|
696
|
-
|
|
697
|
-
// ── navigator.userAgentData (UA Client Hints) ─────────
|
|
698
|
-
// Derive version from the UA string already set by --user-agent flag so the
|
|
699
|
-
// two APIs are always consistent. Removes any "HeadlessChrome" brand entry.
|
|
700
|
-
try {
|
|
701
|
-
var _uaMajor = (navigator.userAgent.match(new RegExp('Chrome/([0-9]+)')) || [])[1] || '136';
|
|
702
|
-
var _uaFull = (navigator.userAgent.match(new RegExp('Chrome/([0-9.]+)')) || [])[1] || (_uaMajor + '.0.0.0');
|
|
703
|
-
var _brands = [
|
|
704
|
-
{ brand: 'Not)A;Brand', version: '99' },
|
|
705
|
-
{ brand: 'Google Chrome', version: _uaMajor },
|
|
706
|
-
{ brand: 'Chromium', version: _uaMajor },
|
|
707
|
-
];
|
|
708
|
-
Object.defineProperty(navigator, 'userAgentData', {
|
|
709
|
-
get: function() {
|
|
710
|
-
return {
|
|
711
|
-
brands: _brands, mobile: false, platform: 'Windows',
|
|
712
|
-
getHighEntropyValues: function() {
|
|
713
|
-
return Promise.resolve({
|
|
714
|
-
architecture: 'x86', bitness: '64',
|
|
715
|
-
brands: _brands,
|
|
716
|
-
fullVersionList: [
|
|
717
|
-
{ brand: 'Not)A;Brand', version: '99.0.0.0' },
|
|
718
|
-
{ brand: 'Google Chrome', version: _uaFull },
|
|
719
|
-
{ brand: 'Chromium', version: _uaFull },
|
|
720
|
-
],
|
|
721
|
-
mobile: false, model: '', platform: 'Windows',
|
|
722
|
-
platformVersion: '15.0.0', uaFullVersion: _uaFull, wow64: false,
|
|
723
|
-
});
|
|
724
|
-
},
|
|
725
|
-
toJSON: function() { return { brands: _brands, mobile: false, platform: 'Windows' }; },
|
|
726
|
-
};
|
|
727
|
-
},
|
|
728
|
-
configurable: true,
|
|
729
|
-
});
|
|
730
|
-
} catch(_) {}
|
|
731
|
-
|
|
732
|
-
// ── CDP Runtime serialization guard ──────────────────
|
|
733
|
-
// Sites detect CDP by putting a getter on Error.prototype.stack
|
|
734
|
-
// and checking if console.log triggers it (only happens when
|
|
735
|
-
// Runtime domain is enabled). We monkey-patch console methods to
|
|
736
|
-
// strip custom getters from arguments before they reach CDP.
|
|
737
|
-
try {
|
|
738
|
-
var _origLog = console.log, _origError = console.error,
|
|
739
|
-
_origWarn = console.warn, _origDebug = console.debug,
|
|
740
|
-
_origInfo = console.info;
|
|
741
|
-
var _safeArg = function(a) {
|
|
742
|
-
if (a instanceof Error) {
|
|
743
|
-
try { return new Error(a.message); } catch(_) { return a; }
|
|
744
|
-
}
|
|
745
|
-
return a;
|
|
746
|
-
};
|
|
747
|
-
console.log = __markNative(function log() { return _origLog.apply(console, Array.prototype.map.call(arguments, _safeArg)); });
|
|
748
|
-
console.error = __markNative(function error() { return _origError.apply(console, Array.prototype.map.call(arguments, _safeArg)); });
|
|
749
|
-
console.warn = __markNative(function warn() { return _origWarn.apply(console, Array.prototype.map.call(arguments, _safeArg)); });
|
|
750
|
-
console.debug = __markNative(function debug() { return _origDebug.apply(console, Array.prototype.map.call(arguments, _safeArg)); });
|
|
751
|
-
console.info = __markNative(function info() { return _origInfo.apply(console, Array.prototype.map.call(arguments, _safeArg)); });
|
|
752
|
-
} catch(_) {}
|
|
753
|
-
|
|
754
|
-
// ── Native function masking ──────────────────────────
|
|
755
|
-
// Patched APIs should not stringify as user-defined stealth code.
|
|
756
|
-
try {
|
|
757
|
-
var __nativeToString = Function.prototype.toString;
|
|
758
|
-
Function.prototype.toString = function toString() {
|
|
759
|
-
if (__greedyNativeFns.indexOf(this) !== -1) {
|
|
760
|
-
var name = this.name || '';
|
|
761
|
-
return 'function ' + name + '() { [native code] }';
|
|
236
|
+
const newQs = Array.isArray(evidence.newQuestions) ? evidence.newQuestions : [];
|
|
237
|
+
for (const q of newQs) {
|
|
238
|
+
const clean = trimText(String(q), 320);
|
|
239
|
+
if (clean && !questions.some((x) => x.question === clean)) {
|
|
240
|
+
questions.push({
|
|
241
|
+
id: `Q${questions.length + 1}`,
|
|
242
|
+
question: clean,
|
|
243
|
+
status: "open",
|
|
244
|
+
reason: "Discovered gap/follow-up",
|
|
245
|
+
createdRound: 1,
|
|
246
|
+
evidence: [],
|
|
247
|
+
sourceIds: []
|
|
248
|
+
});
|
|
249
|
+
}
|
|
762
250
|
}
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
`);
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
[
|
|
774
|
-
|
|
775
|
-
[
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
`);
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
`)
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
251
|
+
}
|
|
252
|
+
} catch (error) {
|
|
253
|
+
process.stderr.write(`[greedysearch] Evidence extraction failed: ${error.message}
|
|
254
|
+
`);
|
|
255
|
+
}
|
|
256
|
+
process.stderr.write(`PROGRESS:research:simple:synthesizing
|
|
257
|
+
`);
|
|
258
|
+
let synthesis = {
|
|
259
|
+
answer: "",
|
|
260
|
+
agreement: { level: "mixed", summary: "Single-pass synthesis." },
|
|
261
|
+
differences: [],
|
|
262
|
+
caveats: [],
|
|
263
|
+
claims: [],
|
|
264
|
+
recommendedSources: combinedSources.slice(0, 4).map((s) => s.id),
|
|
265
|
+
synthesized: false
|
|
266
|
+
};
|
|
267
|
+
if (evidenceItems.length > 0) {
|
|
268
|
+
try {
|
|
269
|
+
progressTracker.startAction("synth-evidence", "from evidence");
|
|
270
|
+
const rawReport = await runGeminiPrompt(buildSynthesisFromEvidencePrompt(query, combinedSources, questions, evidenceItems), { timeoutMs: 120000 });
|
|
271
|
+
progressTracker.endAction();
|
|
272
|
+
synthesis = {
|
|
273
|
+
...synthesis,
|
|
274
|
+
...parseStructuredJson(rawReport?.answer || "") || {}
|
|
275
|
+
};
|
|
276
|
+
synthesis.synthesized = Array.isArray(synthesis.claims) && synthesis.claims.length > 0;
|
|
277
|
+
} catch (error) {
|
|
278
|
+
process.stderr.write(`[greedysearch] Evidence synthesis failed: ${error.message}
|
|
279
|
+
`);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
if (!synthesis.synthesized && combinedSources.length > 0) {
|
|
283
|
+
try {
|
|
284
|
+
progressTracker.startAction("synth-final", "fallback report");
|
|
285
|
+
const rawReport = await runGeminiPrompt(buildFinalReportPrompt(query, [{ round: 1, learnings: [], gaps: [], actions: [] }], combinedSources, questions, evidenceItems), { timeoutMs: 120000 });
|
|
286
|
+
progressTracker.endAction();
|
|
287
|
+
synthesis = {
|
|
288
|
+
...synthesis,
|
|
289
|
+
...parseStructuredJson(rawReport?.answer || "") || {}
|
|
290
|
+
};
|
|
291
|
+
synthesis.synthesized = Array.isArray(synthesis.claims) && synthesis.claims.length > 0;
|
|
292
|
+
} catch (error) {
|
|
293
|
+
process.stderr.write(`[greedysearch] Final synthesis failed: ${error.message}
|
|
294
|
+
`);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
process.stderr.write(`PROGRESS:research:simple:audit
|
|
298
|
+
`);
|
|
299
|
+
const citationAudit = auditCitations(synthesis.answer || "", combinedSources);
|
|
300
|
+
const citationUrls = await runCitationUrlCheck(combinedSources, citationAudit);
|
|
301
|
+
reconcileQuestionsFromSynthesis(questions, synthesis, citationAudit);
|
|
302
|
+
const allGaps = uniqueStrings(synthesis.caveats || []);
|
|
303
|
+
const floor = computeResearchFloor({
|
|
304
|
+
sources: combinedSources,
|
|
305
|
+
fetchedSources,
|
|
306
|
+
synthesis,
|
|
307
|
+
citationAudit,
|
|
308
|
+
gaps: allGaps,
|
|
309
|
+
questions,
|
|
310
|
+
rounds: [{ round: 1, actions: [], learnings: [], gaps: allGaps }],
|
|
311
|
+
qualityScore: synthesis.synthesized ? 8 : 5,
|
|
312
|
+
qualityThreshold,
|
|
313
|
+
maxSources
|
|
314
|
+
});
|
|
315
|
+
const finishedAt = new Date().toISOString();
|
|
316
|
+
const durationMs = Date.now() - startMs;
|
|
317
|
+
const baseManifest = {
|
|
318
|
+
startedAt,
|
|
319
|
+
finishedAt,
|
|
320
|
+
durationMs,
|
|
321
|
+
rounds: 1,
|
|
322
|
+
terminationReason: "simple_single_pass"
|
|
323
|
+
};
|
|
324
|
+
let bundle = null;
|
|
325
|
+
let fetchedFiles;
|
|
326
|
+
if (writeBundle) {
|
|
327
|
+
process.stderr.write(`PROGRESS:research:simple:bundle
|
|
328
|
+
`);
|
|
329
|
+
try {
|
|
330
|
+
bundle = await writeResearchBundle({
|
|
331
|
+
query,
|
|
332
|
+
rounds: [
|
|
333
|
+
{
|
|
334
|
+
round: 1,
|
|
335
|
+
actions: [],
|
|
336
|
+
learnings: [],
|
|
337
|
+
gaps: allGaps,
|
|
338
|
+
evidence: evidenceItems
|
|
339
|
+
}
|
|
340
|
+
],
|
|
341
|
+
sources: combinedSources,
|
|
342
|
+
fetchedSources,
|
|
343
|
+
evidenceItems,
|
|
344
|
+
synthesis,
|
|
345
|
+
citationAudit,
|
|
346
|
+
citationUrls,
|
|
347
|
+
floor,
|
|
348
|
+
manifest: {
|
|
349
|
+
...baseManifest,
|
|
350
|
+
engines: RESEARCH_ENGINES,
|
|
351
|
+
synthesizer: "gemini",
|
|
352
|
+
actionsRun: 1,
|
|
353
|
+
searches: 1,
|
|
354
|
+
fetches: fetchedSources.length,
|
|
355
|
+
sourcesFetched: fetchedSources.filter((s) => s?.contentChars > 100).length,
|
|
356
|
+
engineFailures: [],
|
|
357
|
+
floorMet: floor.floorMet
|
|
358
|
+
},
|
|
359
|
+
allGaps,
|
|
360
|
+
questions,
|
|
361
|
+
outDir: researchOutDir
|
|
362
|
+
});
|
|
363
|
+
fetchedFiles = bundle.sourceFiles;
|
|
364
|
+
delete bundle.sourceFiles;
|
|
365
|
+
} catch (error) {
|
|
366
|
+
process.stderr.write(`[greedysearch] Research bundle write failed: ${error.message}
|
|
367
|
+
`);
|
|
368
|
+
bundle = { error: error.message || String(error) };
|
|
369
|
+
fetchedFiles = await writeSourcesToFiles(fetchedSources);
|
|
370
|
+
}
|
|
371
|
+
} else {
|
|
372
|
+
fetchedFiles = await writeSourcesToFiles(fetchedSources);
|
|
373
|
+
}
|
|
374
|
+
process.stderr.write(`PROGRESS:research:done
|
|
375
|
+
`);
|
|
376
|
+
progressTracker.endRound();
|
|
377
|
+
progressTracker.finish();
|
|
378
|
+
return {
|
|
379
|
+
query,
|
|
380
|
+
_research: {
|
|
381
|
+
mode: "simple",
|
|
382
|
+
breadth: 1,
|
|
383
|
+
iterations: 1,
|
|
384
|
+
maxSources,
|
|
385
|
+
rounds: [
|
|
386
|
+
{
|
|
387
|
+
round: 1,
|
|
388
|
+
actions: [],
|
|
389
|
+
learnings: [],
|
|
390
|
+
gaps: allGaps,
|
|
391
|
+
evidence: evidenceItems
|
|
392
|
+
}
|
|
393
|
+
],
|
|
394
|
+
learnings: [],
|
|
395
|
+
gaps: allGaps,
|
|
396
|
+
evidence: evidenceItems,
|
|
397
|
+
questions,
|
|
398
|
+
questionProgress: questionProgress(questions),
|
|
399
|
+
qualityHistory: [synthesis.synthesized ? 8 : 5],
|
|
400
|
+
terminationReason: "simple_single_pass",
|
|
401
|
+
qualityThreshold,
|
|
402
|
+
floor,
|
|
403
|
+
bundle,
|
|
404
|
+
manifest: baseManifest
|
|
405
|
+
},
|
|
406
|
+
_citationAudit: citationAudit,
|
|
407
|
+
_citationUrls: citationUrls,
|
|
408
|
+
_sources: combinedSources,
|
|
409
|
+
_fetchedSources: fetchedFiles,
|
|
410
|
+
_synthesis: synthesis,
|
|
411
|
+
_confidence: {
|
|
412
|
+
sourcesCount: combinedSources.length,
|
|
413
|
+
fetchedSourceSuccessRate: fetchedSources.length > 0 ? fetchedSources.filter((source) => source.contentChars > 100).length / fetchedSources.length : 0,
|
|
414
|
+
agreementLevel: synthesis.agreement?.level || "mixed",
|
|
415
|
+
floorMet: floor.floorMet
|
|
416
|
+
}
|
|
417
|
+
};
|
|
418
|
+
}
|