@apmantza/greedysearch-pi 2.1.3 → 2.1.5

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.
@@ -0,0 +1,86 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 480" width="1200" height="480">
2
+ <defs>
3
+ <linearGradient id="bg" x1="0%" y1="0%" x2="100%" y2="100%">
4
+ <stop offset="0%" style="stop-color:#0d1117"/>
5
+ <stop offset="50%" style="stop-color:#161b22"/>
6
+ <stop offset="100%" style="stop-color:#0d1117"/>
7
+ </linearGradient>
8
+
9
+ <linearGradient id="title" x1="0%" y1="0%" x2="100%" y2="0%">
10
+ <stop offset="0%" style="stop-color:#58a6ff"/>
11
+ <stop offset="50%" style="stop-color:#bc8cff"/>
12
+ <stop offset="100%" style="stop-color:#3fb950"/>
13
+ </linearGradient>
14
+
15
+ <linearGradient id="piGrad" x1="0%" y1="0%" x2="100%" y2="100%">
16
+ <stop offset="0%" style="stop-color:#8b5cf6"/>
17
+ <stop offset="100%" style="stop-color:#a78bfa"/>
18
+ </linearGradient>
19
+
20
+ <filter id="glow" x="-20%" y="-20%" width="140%" height="140%">
21
+ <feGaussianBlur stdDeviation="6" result="blur"/>
22
+ <feComposite in="SourceGraphic" in2="blur" operator="over"/>
23
+ </filter>
24
+
25
+ <pattern id="dots" width="20" height="20" patternUnits="userSpaceOnUse">
26
+ <circle cx="2" cy="2" r="0.8" fill="#30363d" opacity="0.4"/>
27
+ </pattern>
28
+ </defs>
29
+
30
+ <!-- Background -->
31
+ <rect width="1200" height="480" fill="url(#bg)"/>
32
+ <rect width="1200" height="480" fill="url(#dots)"/>
33
+
34
+ <circle cx="1050" cy="100" r="300" fill="#bc8cff" opacity="0.03"/>
35
+ <circle cx="1150" cy="400" r="200" fill="#3fb950" opacity="0.03"/>
36
+
37
+ <!-- ===== PI LOGO (left) ===== -->
38
+ <g transform="translate(60, 140)">
39
+ <circle cx="60" cy="60" r="72" fill="none" stroke="#8b5cf6" stroke-width="2" opacity="0.3"/>
40
+ <circle cx="60" cy="60" r="62" fill="none" stroke="#8b5cf6" stroke-width="1" opacity="0.1"/>
41
+ <g transform="translate(18, 18) scale(2.6)">
42
+ <path fill="#8b5cf6" fill-rule="evenodd" d="M0 0H15V10H10V15H5V20H0ZM5 5V10H10V5Z"/>
43
+ <rect x="15" y="10" width="5" height="10" fill="#8b5cf6"/>
44
+ </g>
45
+ </g>
46
+
47
+ <!-- ===== TITLE ===== -->
48
+ <text x="240" y="195" font-family="'Segoe UI', -apple-system, system-ui, sans-serif" font-size="72" font-weight="700" letter-spacing="-1.5" fill="url(#title)" filter="url(#glow)">
49
+ GreedySearch
50
+ </text>
51
+
52
+ <!-- ===== "No API keys" badge ===== -->
53
+ <g transform="translate(240, 218)">
54
+ <rect x="0" y="0" width="155" height="28" rx="14" fill="#1f6feb" opacity="0.15"/>
55
+ <rect x="0" y="0" width="155" height="28" rx="14" fill="none" stroke="#1f6feb" stroke-width="1" opacity="0.3"/>
56
+ <text x="77" y="19" font-family="'Segoe UI', -apple-system, system-ui, sans-serif" font-size="13" font-weight="600" fill="#58a6ff" text-anchor="middle">🔑 No API keys</text>
57
+ </g>
58
+
59
+ <!-- ===== TAGLINE ===== -->
60
+ <text x="240" y="280" font-family="'Segoe UI', -apple-system, system-ui, sans-serif" font-size="20" font-weight="400" fill="#8b949e" letter-spacing="0.3">
61
+ Multi-engine AI search via browser automation.
62
+ </text>
63
+
64
+ <!-- ===== ENGINE PILLS ===== -->
65
+ <g transform="translate(240, 310)">
66
+ <!-- Perplexity -->
67
+ <rect x="0" y="0" width="115" height="30" rx="15" fill="#00c8b4" opacity="0.12"/>
68
+ <rect x="0" y="0" width="115" height="30" rx="15" fill="none" stroke="#00c8b4" stroke-width="1" opacity="0.3"/>
69
+ <text x="57" y="20" font-family="'Segoe UI', -apple-system, system-ui, sans-serif" font-size="13" font-weight="600" fill="#00c8b4" text-anchor="middle">Perplexity</text>
70
+
71
+ <!-- Bing -->
72
+ <rect x="130" y="0" width="115" height="30" rx="15" fill="#00a4ef" opacity="0.12"/>
73
+ <rect x="130" y="0" width="115" height="30" rx="15" fill="none" stroke="#00a4ef" stroke-width="1" opacity="0.3"/>
74
+ <text x="187" y="20" font-family="'Segoe UI', -apple-system, system-ui, sans-serif" font-size="13" font-weight="600" fill="#00a4ef" text-anchor="middle">Bing Copilot</text>
75
+
76
+ <!-- Google AI -->
77
+ <rect x="260" y="0" width="115" height="30" rx="15" fill="#fbbc04" opacity="0.12"/>
78
+ <rect x="260" y="0" width="115" height="30" rx="15" fill="none" stroke="#fbbc04" stroke-width="1" opacity="0.3"/>
79
+ <text x="317" y="20" font-family="'Segoe UI', -apple-system, system-ui, sans-serif" font-size="13" font-weight="600" fill="#fbbc04" text-anchor="middle">Google AI</text>
80
+
81
+ <!-- Gemini -->
82
+ <rect x="390" y="0" width="100" height="30" rx="15" fill="#8b5cf6" opacity="0.12"/>
83
+ <rect x="390" y="0" width="100" height="30" rx="15" fill="none" stroke="#8b5cf6" stroke-width="1" opacity="0.3"/>
84
+ <text x="440" y="20" font-family="'Segoe UI', -apple-system, system-ui, sans-serif" font-size="13" font-weight="600" fill="#a78bfa" text-anchor="middle">Gemini</text>
85
+ </g>
86
+ </svg>
@@ -0,0 +1,63 @@
1
+ # Development
2
+
3
+ ## Project Layout
4
+
5
+ - `index.ts` — Pi extension entrypoint.
6
+ - `src/tools/greedy-search-handler.ts` — Pi tool registration/handler.
7
+ - `bin/search.mjs` — CLI orchestration.
8
+ - `extractors/` — engine-specific browser automation.
9
+ - `src/search/` — search pipeline, Chrome lifecycle, recovery, synthesis,
10
+ source ranking, and research orchestration.
11
+ - `test.mjs`, `test-suite/`, `test/` — unit and smoke tests.
12
+
13
+ Pi loads this extension through `jiti`; TypeScript does not need to be
14
+ precompiled for Pi runtime.
15
+
16
+ ## Checks
17
+
18
+ ```bash
19
+ npm run check:lockfile
20
+ npm run lint
21
+ node test.mjs unit
22
+ npm pack --dry-run --json
23
+ ```
24
+
25
+ Jiti load check:
26
+
27
+ ```bash
28
+ node - <<'NODE'
29
+ import { createJiti } from 'file:///C:/Users/R3LiC/AppData/Roaming/npm/node_modules/@earendil-works/pi-coding-agent/node_modules/jiti/lib/jiti.mjs';
30
+ const jiti = createJiti(import.meta.url, { interopDefault: true });
31
+ const mod = await jiti.import('./index.ts');
32
+ console.log('jiti ok', typeof mod.default);
33
+ NODE
34
+ ```
35
+
36
+ ## Useful Headless Smoke Checks
37
+
38
+ ```bash
39
+ node bin/launch.mjs --kill || node bin/kill-visible.mjs
40
+ node bin/search.mjs all --inline --stdin --full <<'EOF'
41
+ TypeScript 5.8 5.9 Node.js ESM module-resolution changes
42
+ EOF
43
+
44
+ node bin/search.mjs all --inline --stdin --depth research \
45
+ --breadth 1 --iterations 1 --max-sources 3 <<'EOF'
46
+ Node.js native TypeScript type stripping for CLI authors
47
+ EOF
48
+ ```
49
+
50
+ ## Extractor Notes
51
+
52
+ When adding or changing an extractor:
53
+
54
+ 1. Reuse `extractors/common.mjs` utilities.
55
+ 2. Prefer single in-browser polling evals over Node-side CDP polling loops.
56
+ 3. Use language-agnostic selectors and data attributes where possible.
57
+ 4. Avoid matching English UI strings except as a last resort.
58
+ 5. Register new engines in both `src/search/constants.mjs` and `bin/search.mjs`
59
+ when they need all-mode pre-seeding.
60
+ 6. Update `README.md`, `docs/`, `src/tools/greedy-search-handler.ts`, and
61
+ `CHANGELOG.md`.
62
+
63
+ See [`AGENTS.md`](../AGENTS.md) for the full extractor and recovery guide.
@@ -0,0 +1,190 @@
1
+ # Inspiration: Browser Automation Patterns from the Ecosystem
2
+
3
+ This document captures patterns and ideas from two open-source browser automation
4
+ projects that could inform future improvements to GreedySearch-pi. Kameleo is
5
+ omitted — its anti-detection engine is commercial and C++-level, not applicable
6
+ to our JS-level CDP approach.
7
+
8
+ ---
9
+
10
+ ## 1. [chrome-devtools-axi](https://github.com/kunchenguid/chrome-devtools-axi)
11
+
12
+ A wrapper around `chrome-devtools-mcp` (Google's official MCP server) with TOON
13
+ encoding, accessibility tree snapshots, contextual suggestions, and a persistent
14
+ bridge architecture. Designed as an Agent Skill (AXI-compliant).
15
+
16
+ ### Notable patterns
17
+
18
+ #### Generation-based stale ref detection
19
+
20
+ Every accessibility tree snapshot carries a `g<N>:` generation prefix that bumps
21
+ on each capture. When an agent passes a stale ref back (e.g. `@g1:5` after the
22
+ page re-rendered), the action fails loudly with `STALE_REF` instead of silently
23
+ no-op'ing. The agent then re-snapshots and retries.
24
+
25
+ **Applicability to GreedySearch-pi:** We don't use accessibility refs, but the
26
+ generation-counter concept could help with the ChatGPT copy-button race
27
+ condition. Currently, `document.querySelectorAll('[data-testid="copy-turn-action-button"]')`
28
+ can pick the wrong button when the assistant response hasn't rendered its own
29
+ copy button yet. A generation counter on the assistant message element would let
30
+ us verify we're clicking the right generation's button.
31
+
32
+ #### Named session isolation (`CHROME_DEVTOOLS_AXI_SESSION`)
33
+
34
+ Each session name gets its own bridge process, port (auto-derived from the name),
35
+ and on-disk state. In isolated mode each bridge also launches its own Chrome,
36
+ so concurrent sessions share neither browser state nor stale-ref tracking.
37
+
38
+ **Applicability to GreedySearch-pi:** Could support concurrent GreedySearch
39
+ users on a shared machine without port conflicts. Currently we use a single
40
+ Chrome profile at `<tmp>/greedysearch-chrome-profile` on port 9222. Named
41
+ sessions would let multiple Pi agents run searches simultaneously.
42
+
43
+ #### Persistent bridge server (one per user session)
44
+
45
+ A detached process keeps the MCP session alive across commands, so Chrome
46
+ doesn't restart every invocation. Writes a PID file to `~/.chrome-devtools-axi/bridge.pid`,
47
+ recycles stale CDP targets after a deep health check, and reaps child processes
48
+ on stop.
49
+
50
+ **Applicability to GreedySearch-pi:** We already have per-tab daemons in
51
+ `bin/cdp.mjs` that hold CDP sessions open. The difference is per-tab vs
52
+ per-user-session. A per-user bridge could reduce Chrome launch overhead when
53
+ switching between engines, but our current model (one Chrome instance, multiple
54
+ tabs) already achieves this.
55
+
56
+ #### Multi-step script execution (`run` command)
57
+
58
+ Accepts multi-step scripts from stdin, executing them sequentially against the
59
+ same browser session. Each step is a CLI command (open, click, fill, eval, etc.).
60
+
61
+ **Applicability to GreedySearch-pi:** Our research mode already orchestrates
62
+ multi-step workflows (plan → search → fetch → synthesize). The `run` pattern
63
+ is cleaner for ad-hoc multi-step tasks but our orchestration is purpose-built
64
+ for research.
65
+
66
+ #### `CHROME_DEVTOOLS_AXI_BROWSER_URL` for external Chrome
67
+
68
+ Connects to an existing Chrome instance instead of launching one. Accepts both
69
+ `http://` URLs (fetches `/json/version` to discover WebSocket URL) and `ws://`
70
+ endpoints directly. Supports authenticated WebSocket endpoints via
71
+ `CHROME_DEVTOOLS_AXI_WS_HEADERS`.
72
+
73
+ **Applicability to GreedySearch-pi:** We already support `CDP_PROFILE_DIR` for
74
+ targeting our own Chrome profile. The WebSocket auth header support could be
75
+ useful for connecting to remote browser instances (BrowserBase, Browserless,
76
+ etc.) in a future cloud mode.
77
+
78
+ #### `CHROME_DEVTOOLS_AXI_CHANNEL` for release channel selection
79
+
80
+ Picks which installed Chrome release channel to target — `stable` (default),
81
+ `beta`, `canary`, or `dev`. Used by `--autoConnect` and launch modes.
82
+
83
+ **Applicability to GreedySearch-pi:** Could let users test against Chrome Beta
84
+ or Canary to catch anti-bot changes before they hit stable.
85
+
86
+ ### What's not applicable
87
+
88
+ - **TOON encoding** — compact structured output format. We use JSON for
89
+ structured data and plain text for answers. Not needed.
90
+ - **Lighthouse / performance / heap snapshots** — performance auditing is
91
+ outside GreedySearch's scope.
92
+ - **chrome-devtools-mcp dependency** — wrapping MCP would mean losing control
93
+ over our extraction pipelines, stealth patches, and multi-engine
94
+ parallelization. Not worth it.
95
+
96
+ ---
97
+
98
+ ## 2. [faster-chrome-devtools-skill](https://github.com/zeke/faster-chrome-devtools-skill)
99
+
100
+ A Pi-compatible Agent Skill wrapping CDP in a zero-dependency Node.js script.
101
+ Shares the same ancestor (`chrome-cdp-skill` by pasky) as our `bin/cdp.mjs`.
102
+ WebSocket client from scratch (RFC 6455), background daemon, accessibility
103
+ snapshots, Cloudflare Browser Run support.
104
+
105
+ ### Notable patterns
106
+
107
+ #### Daemon-level Runtime.enable workaround (`captureMainContext`)
108
+
109
+ **Already implemented in GreedySearch-pi.** Our `bin/cdp.mjs` has the exact
110
+ pattern: briefly enable `Runtime` at daemon start (50-100ms), capture the main
111
+ execution context ID, immediately disable, then pass `contextId` explicitly on
112
+ every `Runtime.evaluate` call. This avoids the persistent `Runtime.enable`
113
+ detection vector that Cloudflare/DataDome watch for (the browser auto-serializes
114
+ console objects when Runtime is active, triggering proxy traps in anti-bot
115
+ scripts).
116
+
117
+ Our implementation is in `bin/cdp.mjs` — `captureMainContext()` function with
118
+ detailed comments citing rebrowser.net and the detection mechanism.
119
+
120
+ #### `loadall` command (repeated click-until-gone)
121
+
122
+ Repeatedly clicks a CSS selector (e.g. "Load more") at a configurable interval
123
+ until the element disappears from the DOM. Has a 5-minute hard deadline and
124
+ interval clamping (100ms–30s).
125
+
126
+ **Applicability to GreedySearch-pi:** Could be useful for infinite-scroll result
127
+ pages in research mode. Some search engines (Bing, Google) paginate results
128
+ behind "Show more" buttons. A `loadall`-style helper in `extractors/common.mjs`
129
+ would let extractors scroll through all results before extracting.
130
+
131
+ #### Compact accessibility tree mode
132
+
133
+ `shouldShowAxNode()` filters out `InlineTextBox` nodes and empty/trivial nodes
134
+ from snapshot output, producing a much more compact tree.
135
+
136
+ **Applicability to GreedySearch-pi:** Minor UX improvement for our `snap`
137
+ command output. Not a priority.
138
+
139
+ #### `browserraw` / `browse` level commands
140
+
141
+ Sends browser-level CDP commands (no sessionId) for things like
142
+ `Browser.setDownloadBehavior`, `Browser.grantPermissions`, etc.
143
+
144
+ **Applicability to GreedySearch-pi:** Could be useful for PDF download in
145
+ research mode when fetching academic papers. Currently we fetch via HTTP; a
146
+ browser-level download handler would let us capture PDFs that require
147
+ JavaScript rendering.
148
+
149
+ #### Cloudflare Browser Run support
150
+
151
+ Connects to Cloudflare's remote browser service via `wss://` endpoints with
152
+ authentication headers. Uses `lab=true` by default for Chrome beta features.
153
+
154
+ **Applicability to GreedySearch-pi:** Future direction — running GreedySearch
155
+ in the cloud without a local Chrome instance. The WebSocket auth header pattern
156
+ (`CHROME_DEVTOOLS_AXI_WS_HEADERS`) from chrome-devtools-axi complements this.
157
+
158
+ #### `--ws-endpoint` / `--http-endpoint` env vars
159
+
160
+ Cleaner than our `CDP_PROFILE_DIR` approach for specifying which Chrome to
161
+ connect to. `CDP_WS_ENDPOINT` and `CDP_HTTP_ENDPOINT` env vars with explicit
162
+ `--ws-endpoint` / `--http-endpoint` CLI flags.
163
+
164
+ **Applicability to GreedySearch-pi:** Could simplify our connection logic.
165
+ Currently we derive the WebSocket URL from `DevToolsActivePort` in the profile
166
+ directory. Accepting an explicit endpoint would be more flexible.
167
+
168
+ ### What's not applicable
169
+
170
+ - **Hand-rolled RFC 6455 WebSocket client** — unnecessary since Node.js 22+
171
+ has built-in `WebSocket`. We use the native one.
172
+ - **General-purpose browser skill** — it's designed for ad-hoc browsing, not
173
+ multi-engine search. No clipboard interception, no stream detection, no
174
+ source extraction.
175
+ - **Per-tab daemon model** — same as ours. No improvement to adopt.
176
+
177
+ ---
178
+
179
+ ## Summary of actionable ideas
180
+
181
+ | Idea | Source | Priority | Effort |
182
+ |------|--------|----------|--------|
183
+ | Generation counters for stale-ref detection | chrome-devtools-axi | Medium | Small |
184
+ | Named session isolation | chrome-devtools-axi | Low | Medium |
185
+ | `loadall` helper for infinite-scroll pages | faster-chrome-devtools-skill | Medium | Small |
186
+ | Browser-level CDP for PDF download | faster-chrome-devtools-skill | Low | Small |
187
+ | Explicit WS endpoint env vars | faster-chrome-devtools-skill | Low | Small |
188
+ | Remote browser auth headers | both | Low | Medium |
189
+ | Release channel selection | chrome-devtools-axi | Low | Small |
190
+ | Runtime.enable workaround | faster-chrome-devtools-skill | ✅ Already done | — |
@@ -0,0 +1,88 @@
1
+ # Release Workflow
2
+
3
+ Releases are automated from `package.json` versions and `CHANGELOG.md` sections.
4
+ The curated changelog entry is the source of truth for GitHub release notes.
5
+
6
+ ## Cut a Release
7
+
8
+ 1. Bump `package.json`.
9
+ 2. Add entries under `## [Unreleased]`.
10
+ 3. Promote the changelog section:
11
+
12
+ ```bash
13
+ npm run changelog:release
14
+ ```
15
+
16
+ Or with explicit values:
17
+
18
+ ```bash
19
+ node scripts/changelog-release.mjs 2.2.0 --date 2026-07-03
20
+ ```
21
+
22
+ 4. Run checks:
23
+
24
+ ```bash
25
+ npm run check:lockfile
26
+ npm run lint
27
+ node test.mjs unit
28
+ ```
29
+
30
+ 5. Commit and push to `master`.
31
+
32
+ ## Changelog Scripts
33
+
34
+ - `npm run changelog:check` — verifies `## [Unreleased]` has releaseable
35
+ entries.
36
+ - `npm run changelog:release` — moves `Unreleased` into the current
37
+ `package.json` version and opens a fresh empty `Unreleased` section.
38
+ - `npm run changelog:extract -- <version>` — prints release notes for a
39
+ version.
40
+ - `npm run release:backfill-notes` — dry-run GitHub release-body backfill.
41
+
42
+ The parser supports both current headings like:
43
+
44
+ ```markdown
45
+ ## [2.1.3] — 2026-06-21
46
+ ```
47
+
48
+ and older headings like:
49
+
50
+ ```markdown
51
+ ## v1.8.5 (2026-04-29)
52
+ ```
53
+
54
+ so historical releases can be backfilled from the same changelog.
55
+
56
+ ## GitHub Release Notes
57
+
58
+ `.github/workflows/release.yml` extracts release notes with:
59
+
60
+ ```bash
61
+ node scripts/changelog-extract.mjs "$VERSION" --summary -o RELEASE_NOTES.md
62
+ ```
63
+
64
+ and passes `RELEASE_NOTES.md` to `softprops/action-gh-release`. GitHub release
65
+ bodies therefore match the curated changelog summary instead of generated PR
66
+ or commit-title notes.
67
+
68
+ ## Backfill Existing Releases
69
+
70
+ Preview the update plan:
71
+
72
+ ```bash
73
+ npm run release:backfill-notes
74
+ ```
75
+
76
+ Apply it with the GitHub CLI authenticated:
77
+
78
+ ```bash
79
+ node scripts/backfill-github-releases.mjs --apply
80
+ ```
81
+
82
+ Limit to specific tags:
83
+
84
+ ```bash
85
+ node scripts/backfill-github-releases.mjs --apply --only v2.1.3,v2.1.2
86
+ ```
87
+
88
+ Use `--full` to write the full changelog prose instead of the summarized body.
@@ -0,0 +1,82 @@
1
+ # Research Mode
2
+
3
+ Set `depth: "research"` to run GreedySearch's iterative research workflow.
4
+
5
+ ```js
6
+ greedy_search({
7
+ query: "Evaluate browser automation options for AI agents",
8
+ depth: "research",
9
+ breadth: 3,
10
+ iterations: 2,
11
+ maxSources: 8,
12
+ });
13
+ ```
14
+
15
+ ## Workflow
16
+
17
+ Research mode performs:
18
+
19
+ 1. Query complexity classification when breadth/iterations are not explicit.
20
+ 2. Action planning with Gemini.
21
+ 3. Fast all-engine child searches using the configured engine list.
22
+ 4. Direct URL fetches when useful.
23
+ 5. Source ranking, dedupe, and source-content fetching.
24
+ 6. Evidence and learning extraction.
25
+ 7. Final cited synthesis.
26
+ 8. Citation audit, URL reachability checks, and deterministic floor checks.
27
+
28
+ Simple questions may take a single-pass path. Explicit `breadth` or
29
+ `iterations` values always override classifier suggestions.
30
+
31
+ ## Bundle Layout
32
+
33
+ Research bundles are written by default under
34
+ `.pi/greedysearch-research/<timestamp>_<query>/`.
35
+
36
+ ```text
37
+ STATUS.md # floor status, question ledger, and gaps
38
+ OUTLINE.md # bundle table of contents
39
+ provenance.md # run metadata and verification summary
40
+ reports/SUMMARY.md # final cited report
41
+ reports/CLAIMS.md # claims mapped to source IDs
42
+ reports/EVIDENCE.md # extracted source evidence
43
+ reports/GAPS.md # caveats and remaining uncertainties
44
+ sources/ # fetched source markdown files
45
+ data/manifest.json # metadata, stop reason, floor checks, citation audit
46
+ data/rounds.json # per-round actions/learnings/gaps
47
+ data/sources.json # ranked source registry
48
+ data/questions.json # open/closed question ledger
49
+ data/evidence.json # structured evidence per useful source
50
+ ```
51
+
52
+ ## CLI
53
+
54
+ ```bash
55
+ node bin/search.mjs all --inline --stdin --depth research \
56
+ --breadth 3 --iterations 2 --max-sources 8 <<'EOF'
57
+ Evaluate browser automation options for AI agents
58
+ EOF
59
+
60
+ node bin/search.mjs all --inline --stdin --depth research \
61
+ --research-out-dir ./research-topic <<'EOF'
62
+ Topic
63
+ EOF
64
+
65
+ node bin/search.mjs all --inline --stdin --depth research \
66
+ --no-research-bundle <<'EOF'
67
+ Topic
68
+ EOF
69
+ ```
70
+
71
+ ## Verification
72
+
73
+ The provenance sidecar records:
74
+
75
+ - sources consulted, fetched, and cited;
76
+ - primary/official source counts;
77
+ - citation audit status;
78
+ - citation URL reachability;
79
+ - floor checks and overall status.
80
+
81
+ Bot-protected or HEAD-disallowing hosts are skipped in URL reachability rather
82
+ than marked dead when they return common anti-bot statuses such as 403.
@@ -0,0 +1,65 @@
1
+ # Runtime and Chrome
2
+
3
+ GreedySearch uses a dedicated Chrome profile and debug port. It must not attach
4
+ to your normal Chrome profile.
5
+
6
+ - Profile: OS temp directory `greedysearch-chrome-profile`
7
+ - Port: `9222`
8
+ - Default mode: headless
9
+
10
+ ## Pi Commands
11
+
12
+ ```text
13
+ /greedy-visible # launch visible Chrome for captcha/login/cookie setup
14
+ /greedy-status # show GreedySearch Chrome status
15
+ /greedy-kill # stop GreedySearch Chrome
16
+ /set-greedy-locale # set default result language
17
+ ```
18
+
19
+ ## Environment Variables
20
+
21
+ - `GREEDY_SEARCH_VISIBLE` — set `1` to show Chrome instead of headless.
22
+ - `GREEDY_SEARCH_ALWAYS_VISIBLE` — set `1` to force visible mode for all runs.
23
+ - `GREEDY_SEARCH_IDLE_TIMEOUT_MINUTES` — headless idle cleanup timeout;
24
+ default `5`.
25
+ - `GREEDY_SEARCH_LOCALE` — default result language; default `en`.
26
+ - `CHROME_PATH` — Chrome/Chromium executable path; auto-detected by default.
27
+
28
+ ## Runtime Helpers
29
+
30
+ Git install path:
31
+
32
+ ```bash
33
+ GS=~/.pi/agent/git/github.com/apmantza/GreedySearch-pi
34
+ node "$GS/bin/launch.mjs" --status
35
+ node "$GS/bin/visible.mjs"
36
+ node "$GS/bin/visible.mjs" --kill
37
+ node "$GS/bin/kill-visible.mjs"
38
+ node "$GS/bin/cdp-visible.mjs" list
39
+ node "$GS/bin/cdp-headless.mjs" list
40
+ node "$GS/bin/cdp-greedy.mjs" list
41
+ ```
42
+
43
+ npm global install path:
44
+
45
+ ```bash
46
+ GS="$(npm root -g)/@apmantza/greedysearch-pi"
47
+ node "$GS/bin/launch.mjs" --status
48
+ node "$GS/bin/visible.mjs"
49
+ node "$GS/bin/visible.mjs" --kill
50
+ node "$GS/bin/kill-visible.mjs"
51
+ node "$GS/bin/cdp-visible.mjs" list
52
+ node "$GS/bin/cdp-headless.mjs" list
53
+ node "$GS/bin/cdp-greedy.mjs" list
54
+ ```
55
+
56
+ ## CDP Safety
57
+
58
+ Use only the safe wrappers for manual debugging:
59
+
60
+ - `bin/cdp-visible.mjs` — refuses unless GreedySearch Chrome is visible.
61
+ - `bin/cdp-headless.mjs` — refuses unless GreedySearch Chrome is headless.
62
+ - `bin/cdp-greedy.mjs` — attaches only to the GreedySearch Chrome profile.
63
+
64
+ Avoid raw `bin/cdp.mjs` unless `CDP_PROFILE_DIR` explicitly points at the
65
+ GreedySearch profile.
@@ -0,0 +1,33 @@
1
+ # Source Fetching
2
+
3
+ For `engine: "all"`, GreedySearch ranks discovered sources and fetches top source
4
+ content by default. `synthesize: true` then asks the configured synthesizer to
5
+ combine engine answers with fetched evidence.
6
+
7
+ ## Supported Sources
8
+
9
+ - **PDFs** — direct PDF links are parsed into markdown text.
10
+ - **Semantic Scholar** — academic paper URLs and direct PDFs are preferred when
11
+ the engine is used directly or opted into the fan-out.
12
+ - **Reddit** — public `.json` API for posts and comments.
13
+ - **GitHub** — REST API for repos, READMEs, file trees, and raw file content.
14
+ - **General web** — Readability extraction with browser fallback.
15
+
16
+ ## Metadata
17
+
18
+ Fetched sources include the best available:
19
+
20
+ - title;
21
+ - final URL;
22
+ - status/content type;
23
+ - byline and site name;
24
+ - publish or modified date;
25
+ - language;
26
+ - excerpt/snippet;
27
+ - trimmed markdown/plain text content.
28
+
29
+ ## Security
30
+
31
+ Fetchers reject private/internal URLs and re-check the final redirected URL to
32
+ avoid SSRF bypasses. GitHub and Reddit URLs use dedicated fetchers where
33
+ possible to avoid fragile page scraping.