@apmantza/greedysearch-pi 2.1.2 → 2.1.4
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/CHANGELOG.md +35 -1
- package/README.md +32 -180
- package/bin/search.mjs +2 -0
- package/docs/banner.svg +86 -0
- package/docs/development.md +63 -0
- package/docs/releases.md +88 -0
- package/docs/research.md +82 -0
- package/docs/runtime.md +65 -0
- package/docs/source-fetching.md +33 -0
- package/docs/usage.md +69 -0
- package/extractors/chatgpt.mjs +127 -23
- package/extractors/gemini.mjs +63 -38
- package/package.json +10 -9
- package/scripts/backfill-github-releases.mjs +139 -0
- package/scripts/changelog-extract.mjs +48 -0
- package/scripts/changelog-release.mjs +65 -0
- package/scripts/check-lockfile.mjs +45 -0
- package/scripts/lib/changelog.mjs +168 -0
- package/scripts/lint.mjs +62 -0
- package/scripts/run-tests.ps1 +179 -0
- package/src/fetcher.mjs +9 -5
- package/src/search/constants.mjs +1 -1
- package/src/search/research.mjs +57 -11
- package/src/search/simple-research.mjs +4 -1
- package/test.mjs +16 -3
- package/skills/greedy-search/skill.md +0 -20
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,40 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## [Unreleased]
|
|
3
|
+
## [Unreleased]
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
## [2.1.4] — 2026-07-04
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- **Changelog-driven release notes** (`scripts/changelog-extract.mjs`, `scripts/changelog-release.mjs`, `scripts/backfill-github-releases.mjs`, `.github/workflows/release.yml`) — GitHub releases now use curated CHANGELOG sections as the release body, with helper scripts for promoting `Unreleased`, extracting summary notes, and backfilling historical releases. The parser supports both current `## [x.y.z] — date` headings and legacy `## vx.y.z (date)` headings.
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- **README simplified like pi-lens and package skill removed** (`README.md`, `docs/*.md`, `package.json`) — The root README is now a concise project overview with installation, quick usage, and links to focused docs for usage, research mode, runtime/Chrome, source fetching, development, and releases. The duplicated Pi skill file was removed so docs live in one place.
|
|
20
|
+
- **Normal all-engine config excludes Semantic Scholar** (`src/search/constants.mjs`, `~/.pi/greedyconfig`) — Default and local all-engine fan-out now use Perplexity, Google, ChatGPT, and Gemini while academic/research engines remain opt-in.
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
|
|
24
|
+
- **Headless ChatGPT and Gemini extraction in all-mode** (`extractors/chatgpt.mjs`, `extractors/gemini.mjs`, `bin/search.mjs`) — ChatGPT now keeps its tab foregrounded during headless streaming, waits for streaming indicators to clear, and rejects repeated-domain citation stubs. Gemini now targets the latest `model-response`, avoids nested code-block copy buttons, and prefers a complete DOM fallback when clipboard copy captures only a snippet.
|
|
25
|
+
- **Research-mode floor and citation handling** (`src/search/research.mjs`, `src/search/simple-research.mjs`) — Explicit `breadth` / `iterations` values now bypass scale-aware overrides, duplicate fetch targets are skipped, cited-source URL checks only evaluate cited sources, and bot-protected HEAD responses are skipped instead of treated as dead links.
|
|
26
|
+
- **Fetcher return style consistency** (`src/fetcher.mjs`) — Multi-line formatting for the protocol-not-allowed return object in `isPrivateUrl` to match the project's code style conventions.
|
|
27
|
+
|
|
28
|
+
## [2.1.3] — 2026-06-21
|
|
29
|
+
|
|
30
|
+
### Fixed
|
|
31
|
+
|
|
32
|
+
- **Stale dependency resolution** — `jsdom` was installed at `24.1.3` despite `package.json` declaring `^29.1.1` (lockfile freeze). Fresh lockfile resolves all deps to latest within semver ranges. Updated `@sinclair/typebox` `^0.34.48` → `^0.34.49`.
|
|
33
|
+
- **Peer dep pin** — `@earendil-works/pi-coding-agent` peer dep changed from wildcard `*` to `^0.79.0` to pin compatible range against Pi `0.79.9`.
|
|
34
|
+
|
|
35
|
+
### Changed
|
|
36
|
+
|
|
37
|
+
- **CI security audit** — Added `npm audit --omit=dev --audit-level=high` to GitHub Actions CI (matching pi-lens) to block pushes/PRs that introduce high/critical vulnerabilities in production dependencies.
|
|
4
38
|
|
|
5
39
|
## [2.1.2] — 2026-06-18
|
|
6
40
|
|
package/README.md
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="docs/banner.svg" alt="GreedySearch for Pi" width="1100">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
1
5
|
# GreedySearch for Pi
|
|
2
6
|
|
|
3
|
-
|
|
7
|
+
GreedySearch registers the `greedy_search` tool for Pi: headless-first,
|
|
8
|
+
no-API-key AI/web search through a dedicated Chrome profile.
|
|
4
9
|
|
|
5
|
-
|
|
10
|
+
## What It Does
|
|
6
11
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
- Chrome
|
|
12
|
+
- Multi-engine search across Perplexity, Google AI, ChatGPT, and Gemini
|
|
13
|
+
- Source-grounded `engine: "all"` results with fetched source content
|
|
14
|
+
- Optional synthesis over engine answers and fetched sources
|
|
15
|
+
- Iterative `depth: "research"` runs with citation audit and research bundles
|
|
16
|
+
- Visible Chrome fallback for login/captcha/cookie setup when needed
|
|
12
17
|
|
|
13
18
|
## Install
|
|
14
19
|
|
|
@@ -22,16 +27,12 @@ Or from git:
|
|
|
22
27
|
pi install git:github.com/apmantza/GreedySearch-pi
|
|
23
28
|
```
|
|
24
29
|
|
|
25
|
-
##
|
|
26
|
-
|
|
27
|
-
- `greedy_search` — multi-engine AI web search, source-grounded synthesis, and deep research
|
|
28
|
-
|
|
29
|
-
## Quick usage
|
|
30
|
+
## Quick Usage
|
|
30
31
|
|
|
31
32
|
```js
|
|
32
|
-
greedy_search({ query: "React 19 changes" });
|
|
33
|
-
greedy_search({ query: "React 19 changes", synthesize: true });
|
|
34
|
-
greedy_search({ query: "Prisma vs Drizzle", engine: "perplexity" });
|
|
33
|
+
greedy_search({ query: "React 19 changes" });
|
|
34
|
+
greedy_search({ query: "React 19 changes", synthesize: true });
|
|
35
|
+
greedy_search({ query: "Prisma vs Drizzle", engine: "perplexity" });
|
|
35
36
|
greedy_search({
|
|
36
37
|
query: "Evaluate browser automation options for AI agents",
|
|
37
38
|
depth: "research",
|
|
@@ -39,181 +40,32 @@ greedy_search({
|
|
|
39
40
|
iterations: 2,
|
|
40
41
|
maxSources: 8,
|
|
41
42
|
});
|
|
42
|
-
// Research mode writes a dataroom-style bundle under .pi/greedysearch-research/ by default.
|
|
43
|
-
// Headless is the default — no window. To force visible Chrome:
|
|
44
|
-
greedy_search({ query: "Visible browser setup", engine: "perplexity", visible: true });
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
## Parameters (`greedy_search`)
|
|
48
|
-
|
|
49
|
-
### Common
|
|
50
|
-
|
|
51
|
-
- `query` (required)
|
|
52
|
-
- `fullAnswer`: return full single-engine output instead of preview
|
|
53
|
-
- `headless`: set to `false` to show Chrome window (default: `true`)
|
|
54
|
-
- `visible` / `alwaysVisible`: set to `true` to always use visible Chrome for this search
|
|
55
|
-
|
|
56
|
-
### Normal search
|
|
57
|
-
|
|
58
|
-
- `engine`: `all` (default web/search fan-out), `perplexity`, `google`, `chatgpt`, `gemini`; opt-in research engines: `semantic-scholar`, `logically`; `bing` still works for signed-in users
|
|
59
|
-
- `synthesize`: for `engine: "all"`, synthesize fetched sources with the configured synthesizer (default false)
|
|
60
|
-
- `synthesizer`: override the configured synthesis engine for this call (`gemini` default, `chatgpt` supported)
|
|
61
|
-
- `depth`: legacy `fast`/`standard`/`deep` aliases are still accepted for compatibility; prefer `synthesize` for normal search
|
|
62
|
-
|
|
63
|
-
### Deep research
|
|
64
|
-
|
|
65
|
-
- `depth`: set to `"research"` to run the iterative research workflow
|
|
66
|
-
- `breadth`: number of research actions per round, 1-5 (default 3)
|
|
67
|
-
- `iterations`: research rounds, 1-3 (default 2)
|
|
68
|
-
- `maxSources`: fetched source cap for the final report, 3-12
|
|
69
|
-
- `researchOutDir`: optional directory for the research bundle
|
|
70
|
-
- `writeResearchBundle`: write the research bundle to disk (default true for research mode)
|
|
71
|
-
|
|
72
|
-
Deep research uses the configured `~/.pi/greedyconfig.engines` list for child searches and Gemini for planning/final synthesis.
|
|
73
|
-
|
|
74
|
-
## Environment variables
|
|
75
|
-
|
|
76
|
-
| Variable | Default | Description |
|
|
77
|
-
| ------------------------------------ | ------------- | ------------------------------------------------------------- |
|
|
78
|
-
| `GREEDY_SEARCH_VISIBLE` | (unset) | Set to `1` to show Chrome window instead of headless |
|
|
79
|
-
| `GREEDY_SEARCH_ALWAYS_VISIBLE` | (unset) | Set to `1` to force visible Chrome for all GreedySearch runs |
|
|
80
|
-
| `GREEDY_SEARCH_IDLE_TIMEOUT_MINUTES` | `5` | Minutes of inactivity before auto-killing GreedySearch Chrome |
|
|
81
|
-
| `GREEDY_SEARCH_LOCALE` | `en` | Default result language (en, de, fr, es, ja, etc.) |
|
|
82
|
-
| `CHROME_PATH` | auto-detected | Path to Chrome/Chromium executable |
|
|
83
|
-
|
|
84
|
-
## Search modes
|
|
85
|
-
|
|
86
|
-
- **Individual engine search/research** — `engine: "perplexity" | "google" | "chatgpt" | "gemini" | "semantic-scholar" | "logically" | "bing"`; returns that engine's answer and sources.
|
|
87
|
-
- **Grounded multi-engine search** — default `engine: "all"`; fans out to configured engines, ranks sources, fetches top source content, and reports confidence metadata.
|
|
88
|
-
- **All + synthesis** — add `synthesize: true` (or CLI `--synthesize`) to ask the configured synthesizer to combine engine answers and fetched source evidence.
|
|
89
|
-
- **Deep research** — `depth: "research"`; iterative action planning, direct URL fetches, fast multi-engine searches, source fetching, learning extraction, deterministic floor checks, citation audit, a final cited report, and a structured on-disk bundle.
|
|
90
|
-
|
|
91
|
-
Legacy `depth: "fast" | "standard" | "deep"` values remain accepted for compatibility: `fast` skips source fetching; `standard`/`deep` request synthesis.
|
|
92
|
-
|
|
93
|
-
Configure all-engine fan-out and synthesis in `~/.pi/greedyconfig`:
|
|
94
|
-
|
|
95
|
-
```json
|
|
96
|
-
{
|
|
97
|
-
"engines": ["perplexity", "google", "chatgpt", "gemini"],
|
|
98
|
-
"synthesizer": "gemini"
|
|
99
|
-
}
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
Gemini is a normal search engine and can participate in `engine: "all"`. `semantic-scholar` and `logically` are opt-in academic/research engines; include them in `~/.pi/greedyconfig` only when you want the all-engine fan-out to include academic paper discovery or research-assistant workflows. Default `engine: "all"` excludes them because their results are noisy for casual web search — they shine in `depth: "research"` mode instead. Deep research child searches reuse the same configured `engines` list and keep query text on stdin; Gemini remains the research planner/final-report synthesizer. If `synthesize: true` and `"synthesizer": "gemini"`, Gemini runs once as a search engine and again as the synthesizer; set `"synthesizer": "chatgpt"` to separate those roles for normal all-search synthesis.
|
|
103
|
-
|
|
104
|
-
Research bundles are written by default to `.pi/greedysearch-research/<timestamp>_<query>/` and include:
|
|
105
|
-
|
|
106
|
-
```text
|
|
107
|
-
STATUS.md # floor status, open/closed question ledger, and gaps
|
|
108
|
-
OUTLINE.md # bundle table of contents
|
|
109
|
-
reports/SUMMARY.md # final cited report
|
|
110
|
-
reports/CLAIMS.md # extracted claims mapped to source IDs
|
|
111
|
-
reports/EVIDENCE.md # goal-based evidence extracted from fetched sources
|
|
112
|
-
reports/GAPS.md # caveats and remaining uncertainties
|
|
113
|
-
sources/ # fetched source markdown files
|
|
114
|
-
data/manifest.json # run metadata, stop reason, floor checks, citation audit
|
|
115
|
-
data/rounds.json # per-round actions/learnings/gaps
|
|
116
|
-
data/sources.json # ranked source registry
|
|
117
|
-
data/questions.json # STATUS-style question ledger with evidence/source IDs
|
|
118
|
-
data/evidence.json # structured rational/evidence/summary per useful source
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
CLI controls:
|
|
122
|
-
|
|
123
|
-
```bash
|
|
124
|
-
node bin/search.mjs all --inline --stdin --depth research --breadth 3 --iterations 2 --max-sources 8 <<'EOF'
|
|
125
|
-
Evaluate browser automation options for AI agents
|
|
126
|
-
EOF
|
|
127
|
-
node bin/search.mjs all "topic" --depth research --research-out-dir ./research-topic
|
|
128
|
-
node bin/search.mjs all "topic" --depth research --no-research-bundle
|
|
129
43
|
```
|
|
130
44
|
|
|
131
|
-
|
|
45
|
+
Headless is the default. Use `visible: true` only when you need to establish a
|
|
46
|
+
session, solve a challenge, or inspect the browser:
|
|
132
47
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
```text
|
|
136
|
-
/greedy-visible # launch visible Chrome for captcha/login/cookie setup
|
|
137
|
-
/greedy-status # show GreedySearch Chrome status
|
|
138
|
-
/greedy-kill # stop GreedySearch Chrome
|
|
139
|
-
/set-greedy-locale # set default result language (de, fr, es, ja, etc.)
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
Git install path:
|
|
143
|
-
|
|
144
|
-
```bash
|
|
145
|
-
GS=~/.pi/agent/git/github.com/apmantza/GreedySearch-pi
|
|
146
|
-
node "$GS/bin/launch.mjs" --status
|
|
147
|
-
node "$GS/bin/visible.mjs" # visible mode
|
|
148
|
-
node "$GS/bin/visible.mjs" --kill # strong visible/port cleanup
|
|
149
|
-
node "$GS/bin/kill-visible.mjs" # same as visible.mjs --kill
|
|
150
|
-
node "$GS/bin/cdp-visible.mjs" list # safe CDP: GreedySearch visible Chrome only
|
|
151
|
-
node "$GS/bin/cdp-headless.mjs" list # safe CDP: GreedySearch headless Chrome only
|
|
152
|
-
node "$GS/bin/cdp-greedy.mjs" list # safe CDP: any GreedySearch Chrome mode
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
npm global install path:
|
|
156
|
-
|
|
157
|
-
```bash
|
|
158
|
-
GS="$(npm root -g)/@apmantza/greedysearch-pi"
|
|
159
|
-
node "$GS/bin/launch.mjs" --status
|
|
160
|
-
node "$GS/bin/visible.mjs"
|
|
161
|
-
node "$GS/bin/visible.mjs" --kill
|
|
162
|
-
node "$GS/bin/kill-visible.mjs"
|
|
163
|
-
node "$GS/bin/cdp-visible.mjs" list
|
|
164
|
-
node "$GS/bin/cdp-headless.mjs" list
|
|
165
|
-
node "$GS/bin/cdp-greedy.mjs" list
|
|
48
|
+
```js
|
|
49
|
+
greedy_search({ query: "Visible setup", engine: "perplexity", visible: true });
|
|
166
50
|
```
|
|
167
51
|
|
|
168
|
-
|
|
52
|
+
## Documentation
|
|
169
53
|
|
|
170
|
-
|
|
54
|
+
- [Usage guide](docs/usage.md) — tool parameters, search modes, and config
|
|
55
|
+
- [Research mode](docs/research.md) — iterative workflow and bundle layout
|
|
56
|
+
- [Runtime and Chrome](docs/runtime.md) — slash commands, env vars, CDP safety
|
|
57
|
+
- [Source fetching](docs/source-fetching.md) — supported source types and metadata
|
|
58
|
+
- [Development](docs/development.md) — project layout, tests, and smoke checks
|
|
59
|
+
- [Release workflow](docs/releases.md) — changelog scripts and GitHub releases
|
|
171
60
|
|
|
172
61
|
## Requirements
|
|
173
62
|
|
|
174
|
-
- Chrome
|
|
63
|
+
- Chrome or Chromium
|
|
175
64
|
- Node.js 20.11.0+
|
|
176
65
|
|
|
177
|
-
##
|
|
178
|
-
|
|
179
|
-
When using `engine: "all"`, top source content is fetched by default. Add `synthesize: true` to synthesize with the configured synthesizer:
|
|
180
|
-
|
|
181
|
-
- **PDFs** — Direct PDF links are parsed to markdown text for source-grounded synthesis
|
|
182
|
-
- **Semantic Scholar** — Discovers academic papers and prefers direct PDF/external paper links when available
|
|
183
|
-
- **Reddit** — Uses Reddit's public `.json` API for posts and comments
|
|
184
|
-
- **GitHub** — Uses GitHub REST API for repos, READMEs, and file trees
|
|
185
|
-
- **General web** — Mozilla Readability extraction with browser fallback when needed
|
|
186
|
-
- **Metadata** — title, author/byline, site name, publish date, language, excerpt
|
|
187
|
-
|
|
188
|
-
## Project layout
|
|
189
|
-
|
|
190
|
-
- `bin/` — runtime CLIs (`search.mjs`, `launch.mjs`, `launch-visible.mjs`, `visible.mjs`, `kill-visible.mjs`, safe CDP wrappers, `cdp.mjs`)
|
|
191
|
-
- `extractors/` — engine-specific automation + stealth/consent handling
|
|
192
|
-
- `src/` — search pipeline, chrome management, source fetching, formatting
|
|
193
|
-
- `skills/` — Pi skill metadata
|
|
194
|
-
|
|
195
|
-
## Testing
|
|
196
|
-
|
|
197
|
-
Cross-platform test runner (Windows + Unix):
|
|
198
|
-
|
|
199
|
-
```bash
|
|
200
|
-
npm test # run all tests
|
|
201
|
-
npm run test:quick # skip slow tests
|
|
202
|
-
npm run test:smoke # basic health check
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
Full bash test suite (Unix only):
|
|
206
|
-
|
|
207
|
-
```bash
|
|
208
|
-
npm run test:bash # comprehensive tests
|
|
209
|
-
./test.sh parallel # race condition tests
|
|
210
|
-
./test.sh flags # flag/option tests
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
## Changelog
|
|
214
|
-
|
|
215
|
-
See `CHANGELOG.md`.
|
|
66
|
+
## Contributing
|
|
216
67
|
|
|
217
|
-
|
|
68
|
+
See [`CONTRIBUTING.md`](CONTRIBUTING.md) and [`AGENTS.md`](AGENTS.md) for the
|
|
69
|
+
extractor, recovery, and release checklists.
|
|
218
70
|
|
|
219
|
-
MIT
|
|
71
|
+
GreedySearch is released under the [MIT License](LICENSE).
|
package/bin/search.mjs
CHANGED
|
@@ -314,6 +314,8 @@ async function main() {
|
|
|
314
314
|
const ENGINE_START_URLS = {
|
|
315
315
|
perplexity: "https://www.perplexity.ai/",
|
|
316
316
|
google: "https://www.google.com/",
|
|
317
|
+
chatgpt: "https://chatgpt.com/",
|
|
318
|
+
gemini: "https://gemini.google.com/app",
|
|
317
319
|
"semantic-scholar": "https://www.semanticscholar.org/",
|
|
318
320
|
semanticscholar: "https://www.semanticscholar.org/",
|
|
319
321
|
s2: "https://www.semanticscholar.org/",
|
package/docs/banner.svg
ADDED
|
@@ -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.
|
package/docs/releases.md
ADDED
|
@@ -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.
|
package/docs/research.md
ADDED
|
@@ -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.
|