@bacnh85/pi-web 0.3.0 → 0.4.3
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/README.md +171 -77
- package/extensions/.mocharc.yml +5 -0
- package/extensions/index.ts +474 -0
- package/extensions/lib/brave.ts +45 -0
- package/{lib → extensions/lib}/config.ts +8 -10
- package/{lib → extensions/lib}/crawl4ai.ts +11 -45
- package/extensions/lib/extract.ts +185 -0
- package/{lib → extensions/lib}/firecrawl.ts +7 -19
- package/{lib → extensions/lib}/format.ts +2 -71
- package/extensions/lib/retry.ts +29 -0
- package/extensions/lib/search.ts +240 -0
- package/extensions/lib/searxng.ts +69 -0
- package/extensions/package.json +3 -0
- package/extensions/test/unit/config.test.ts +309 -0
- package/extensions/test/unit/crawl4ai.test.ts +69 -0
- package/extensions/test/unit/extract.test.ts +134 -0
- package/extensions/test/unit/format.test.ts +194 -0
- package/extensions/test/unit/search.test.ts +147 -0
- package/package.json +11 -10
- package/skills/pi-web/SKILL.md +108 -0
- package/index.ts +0 -638
- package/lib/brave.ts +0 -40
- package/lib/retry.ts +0 -142
- package/lib/searxng.ts +0 -63
- /package/{lib → extensions/lib}/content.ts +0 -0
- /package/{types.d.ts → extensions/types.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -1,31 +1,23 @@
|
|
|
1
|
-
# pi-web
|
|
1
|
+
# pi-web v0.4
|
|
2
2
|
|
|
3
|
-
Pi extension for web search,
|
|
3
|
+
Pi extension for **unified web search, content extraction, site crawling, and page capture**.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Auto-selects the best backend from SearXNG (self-hosted), Brave Search, Firecrawl, and Crawl4AI — so agents don't have to know which backend to use. Search selection is adaptive: broad discovery prefers self-hosted SearXNG, while precision-sensitive searches and inline content prefer Brave.
|
|
6
6
|
|
|
7
|
-
Install
|
|
7
|
+
## Install
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
10
|
pi install npm:@bacnh85/pi-web
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
From this repository
|
|
13
|
+
From this repository:
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
cd extensions/pi-web
|
|
17
|
-
npm install
|
|
18
|
-
cd ../..
|
|
19
|
-
|
|
20
16
|
pi install ./extensions/pi-web
|
|
21
17
|
# or test directly
|
|
22
18
|
pi -e ./extensions/pi-web
|
|
23
19
|
```
|
|
24
20
|
|
|
25
|
-
The package manifest points Pi directly at `./index.ts`, so published npm installs and local installs load the same extension entrypoint.
|
|
26
|
-
|
|
27
|
-
If you manually copy this directory instead of using `pi install`, run `npm install --omit=dev` in the copied `pi-web` directory so readable-content dependencies such as `@mozilla/readability` are present.
|
|
28
|
-
|
|
29
21
|
## Configuration
|
|
30
22
|
|
|
31
23
|
Environment lookup order:
|
|
@@ -33,79 +25,198 @@ Environment lookup order:
|
|
|
33
25
|
1. Process environment
|
|
34
26
|
2. Current working directory `.env.local`
|
|
35
27
|
3. Current working directory `.env`
|
|
36
|
-
4. Pi global config
|
|
37
|
-
5. Pi global config
|
|
28
|
+
4. Pi global config `~/.pi/agent/.env.local`
|
|
29
|
+
5. Pi global config `~/.pi/agent/.env`
|
|
38
30
|
|
|
39
31
|
Variables:
|
|
40
32
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
33
|
+
| Variable | Required | Default | Notes |
|
|
34
|
+
|---|---|---|---|
|
|
35
|
+
| `BRAVE_API_KEY` | No (1) | — | Brave Search API key |
|
|
36
|
+
| `SEARXNG_BASE_URL` | No | `http://172.30.55.22:8888` | Self-hosted SearXNG |
|
|
37
|
+
| `FIRECRAWL_API_URL` | No | `https://api.firecrawl.dev/v2` | Self-hosted or hosted |
|
|
38
|
+
| `FIRECRAWL_API_KEY` | No (2) | — | Required for hosted Firecrawl |
|
|
39
|
+
| `CRAWL4AI_API_URL` | No | `http://172.30.55.22:11235` | Self-hosted Crawl4AI |
|
|
40
|
+
| `CRAWL4AI_API_TOKEN` | No (3) | — | Required if Crawl4AI auth enabled |
|
|
41
|
+
|
|
42
|
+
> (1) At least one search backend (SearXNG, Brave, or Firecrawl) must be configured for `web_search`.
|
|
43
|
+
> (2) Required for hosted Firecrawl; optional for self-hosted instances without auth.
|
|
44
|
+
> (3) Required for Crawl4AI v0.9+ default config.
|
|
49
45
|
|
|
50
|
-
Secrets are never printed;
|
|
46
|
+
Secrets are never printed; `web_status` reports only presence/source.
|
|
51
47
|
|
|
52
48
|
## Tools
|
|
53
49
|
|
|
54
|
-
|
|
50
|
+
### `web_search` — Unified search
|
|
55
51
|
|
|
56
|
-
-
|
|
52
|
+
Searches the web. Auto-selects backends adaptively: SearXNG for broad self-hosted discovery, Brave for precision-sensitive queries and `include_content`, Firecrawl as last resort.
|
|
57
53
|
|
|
58
|
-
|
|
54
|
+
```
|
|
55
|
+
web_search query="ansible podman quadlet" count=5
|
|
56
|
+
web_search query="ansible documentation" backend=brave count=10
|
|
57
|
+
web_search query="latest python release" engines="google,github"
|
|
58
|
+
web_search query="riven media" include_content=true
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Parameters:
|
|
62
|
+
|
|
63
|
+
| Parameter | Type | Default | Description |
|
|
64
|
+
|---|---|---|---|
|
|
65
|
+
| `query` | string | — | Search query |
|
|
66
|
+
| `count` | number | 5 | Number of results (max 20) |
|
|
67
|
+
| `freshness` | string | — | Time filter: `pw`, `pm`, `py`, or `YYYY-MM-DDtoYYYY-MM-DD` |
|
|
68
|
+
| `country` | string | `US` | Two-letter country code |
|
|
69
|
+
| `backend` | string | `auto` | Force backend: `auto`, `searxng`, `brave`, `firecrawl` |
|
|
70
|
+
| `engines` | string | — | SearXNG engine override, e.g. `google,github` |
|
|
71
|
+
| `include_content` | boolean | false | Fetch page content alongside results |
|
|
72
|
+
| `content_chars` | number | 5000 | Max content chars per result |
|
|
59
73
|
|
|
60
|
-
-
|
|
74
|
+
**Auto-selection behavior:**
|
|
61
75
|
|
|
62
|
-
SearXNG
|
|
76
|
+
1. **SearXNG** — first for broad/general discovery, especially when `engines` is supplied.
|
|
77
|
+
2. **Brave** — first for precision-sensitive queries (`site:`, quoted phrases, docs/API/source lookups, short proper-name queries) and whenever `include_content` is true. Requires `BRAVE_API_KEY`.
|
|
78
|
+
3. **Firecrawl Search** — last resort. ⚠️ Poor semantic accuracy on domain-specific/ambiguous queries (e.g., "Riven" returns League of Legends results). Prefer SearXNG or Brave for precision.
|
|
63
79
|
|
|
64
|
-
|
|
80
|
+
Tool output includes search diagnostics showing attempted backends and the selected backend.
|
|
65
81
|
|
|
66
|
-
|
|
82
|
+
Use `backend` parameter to force a specific backend when needed.
|
|
67
83
|
|
|
68
|
-
|
|
69
|
-
- `firecrawl_scrape` — scrape a URL as markdown/html/links/summary/json.
|
|
70
|
-
- `firecrawl_map` — discover URLs for a site.
|
|
71
|
-
- `firecrawl_crawl` — start a conservative crawl, optionally polling for results.
|
|
84
|
+
### `web_extract` — Unified content extraction
|
|
72
85
|
|
|
73
|
-
|
|
86
|
+
Extracts readable content from a URL. Auto-selects backend: static (JSDOM) → dynamic (Firecrawl) → full (Crawl4AI), with extraction diagnostics showing fallback attempts.
|
|
74
87
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
- `crawl4ai_status` — check Crawl4AI server health, version, and auth status.
|
|
88
|
+
```
|
|
89
|
+
web_extract url="https://docs.ansible.com/..."
|
|
90
|
+
web_extract url="https://riven.tv/" mode=static
|
|
91
|
+
web_extract url="https://example.com" mode=dynamic prompt="Extract pricing plans"
|
|
92
|
+
```
|
|
81
93
|
|
|
82
|
-
|
|
94
|
+
Parameters:
|
|
83
95
|
|
|
84
|
-
|
|
85
|
-
|
|
96
|
+
| Parameter | Type | Default | Description |
|
|
97
|
+
|---|---|---|---|
|
|
98
|
+
| `url` | string | — | URL to extract |
|
|
99
|
+
| `mode` | string | `auto` | `auto`, `static`, `dynamic`, or `full` |
|
|
100
|
+
| `prompt` | string | — | Prompt for JSON extraction (dynamic mode) |
|
|
101
|
+
| `schema` | any | — | JSON schema for structured extraction (dynamic mode) |
|
|
102
|
+
| `content_chars` | number | 20000 | Max content chars |
|
|
103
|
+
| `wait_for` | number | — | Milliseconds to wait for Firecrawl dynamic rendering. Crawl4AI `/md` full mode may ignore this. |
|
|
104
|
+
| `mobile` | boolean | false | Emulate mobile viewport (dynamic mode) |
|
|
86
105
|
|
|
87
|
-
|
|
106
|
+
**Mode behavior:**
|
|
88
107
|
|
|
89
|
-
|
|
108
|
+
| Mode | Backend | Best for | API key needed |
|
|
109
|
+
|---|---|---|---|
|
|
110
|
+
| `static` | JSDOM+Readability | Simple static pages, blog posts, docs | No |
|
|
111
|
+
| `dynamic` | Firecrawl Scrape | JS-rendered pages, dynamic content | Maybe |
|
|
112
|
+
| `full` | Crawl4AI | JS-heavy SPA, complex rendering | Maybe |
|
|
113
|
+
| `auto` (default) | static → dynamic → full | Unknown page type | Maybe |
|
|
114
|
+
|
|
115
|
+
In `auto` mode, fallbacks are noted in the output (e.g., `[Extraction fell back to Firecrawl Scrape (dynamic mode)]`). If `static` extraction fails, the tool gracefully escalates to heavier backends.
|
|
116
|
+
|
|
117
|
+
> ⚠️ **Note on Firecrawl Scrape**: Fails on bot-protected sites (Ansible docs, many CDN-backed doc sites). Falls back to `full` mode (Crawl4AI) in `auto` mode.
|
|
118
|
+
|
|
119
|
+
### `web_map` — Site URL discovery
|
|
120
|
+
|
|
121
|
+
Discovers URLs from a site using Firecrawl Map. Best on base domains; may return fewer results on sub-paths.
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
web_map url="https://riven.tv"
|
|
125
|
+
web_map url="https://docs.example.com" sitemap=only
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Parameters: `url`, `limit` (default 100), `include_subdomains`, `search`, `sitemap`, `use_index`, `ignore_cache`.
|
|
129
|
+
|
|
130
|
+
### `web_crawl` — Site crawl
|
|
131
|
+
|
|
132
|
+
Crawls pages from a site. Two modes:
|
|
133
|
+
|
|
134
|
+
- **`light`** (default): Firecrawl Crawl — conservative, docs-focused, single URL.
|
|
135
|
+
- **`full`**: Crawl4AI Crawl — headless browser, rendered data, media, links, up to 100 URLs.
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
web_crawl url="https://docs.example.com" limit=10 # Firecrawl light mode
|
|
139
|
+
web_crawl urls=["https://a.com","https://b.com"] mode=full # Crawl4AI full mode
|
|
140
|
+
web_crawl url="https://example.com" mode=light poll=true # Poll for completion
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### `web_screenshot` — Page screenshot
|
|
144
|
+
|
|
145
|
+
Captures a full-page PNG screenshot using Crawl4AI. Returns base64-encoded PNG.
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
web_screenshot url="https://example.com"
|
|
149
|
+
web_screenshot url="https://example.com" wait_for=5 wait_for_images=true
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### `web_pdf` — Page PDF
|
|
153
|
+
|
|
154
|
+
Generates a PDF document using Crawl4AI. Returns base64-encoded PDF.
|
|
155
|
+
|
|
156
|
+
```
|
|
157
|
+
web_pdf url="https://example.com/article"
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### `web_status` — Provider status
|
|
161
|
+
|
|
162
|
+
Shows all provider configuration status and Crawl4AI server health.
|
|
163
|
+
|
|
164
|
+
```
|
|
165
|
+
web_status
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Typical output:
|
|
169
|
+
|
|
170
|
+
```json
|
|
171
|
+
{
|
|
172
|
+
"brave": { "apiKeyFound": true, "apiKeySource": "process.env" },
|
|
173
|
+
"searxng": { "baseUrl": "http://172.30.55.22:8888", ... },
|
|
174
|
+
"firecrawl": { "baseUrl": "http://172.30.55.22:3002/v2", ... },
|
|
175
|
+
"crawl4ai": {
|
|
176
|
+
"baseUrl": "http://172.30.55.22:11235",
|
|
177
|
+
...
|
|
178
|
+
"health": { "status": "healthy", "version": "0.5.0", ... }
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Library structure
|
|
90
184
|
|
|
91
185
|
| Module | Contents |
|
|
92
186
|
|--------|----------|
|
|
93
187
|
| `lib/config.ts` | Environment loading, config helpers for all providers |
|
|
94
|
-
| `lib/format.ts` | Text sanitization, truncation,
|
|
188
|
+
| `lib/format.ts` | Text sanitization, truncation, crawl/scrape result formatting |
|
|
95
189
|
| `lib/content.ts` | Readable content extraction (JSDOM + Readability + Turndown) |
|
|
96
190
|
| `lib/retry.ts` | Retry with exponential backoff for transient HTTP failures |
|
|
97
|
-
| `lib/brave.ts` | Brave Search API fetch client |
|
|
98
|
-
| `lib/searxng.ts` | SearXNG metasearch fetch client |
|
|
99
|
-
| `lib/firecrawl.ts` | Firecrawl API fetch client with v2→v1 fallback |
|
|
100
|
-
| `lib/crawl4ai.ts` | Crawl4AI Docker API fetch client (
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
191
|
+
| `lib/brave.ts` | Brave Search API fetch client (internal) |
|
|
192
|
+
| `lib/searxng.ts` | SearXNG metasearch fetch client (internal) |
|
|
193
|
+
| `lib/firecrawl.ts` | Firecrawl API fetch client with v2→v1 fallback (internal) |
|
|
194
|
+
| `lib/crawl4ai.ts` | Crawl4AI Docker API fetch client (internal) |
|
|
195
|
+
| `lib/search.ts` | Unified search orchestrator — probes backends, fallback chain |
|
|
196
|
+
| `lib/extract.ts` | Unified extraction orchestrator — mode-based backend selection |
|
|
197
|
+
|
|
198
|
+
## Migration from 0.3.x
|
|
199
|
+
|
|
200
|
+
v0.4 replaces the 14 individual backend-specific tools with 7 unified tools:
|
|
201
|
+
|
|
202
|
+
| v0.3 tool | v0.4 replacement |
|
|
203
|
+
|---|---|
|
|
204
|
+
| `brave_search` | `web_search` with `backend: "brave"` |
|
|
205
|
+
| `searxng_search` | `web_search` with `backend: "searxng"` |
|
|
206
|
+
| `firecrawl_search` | `web_search` with `backend: "firecrawl"` |
|
|
207
|
+
| `web_content` | `web_extract` with `mode: "static"` |
|
|
208
|
+
| `firecrawl_scrape` | `web_extract` with `mode: "dynamic"` |
|
|
209
|
+
| `crawl4ai_scrape` | `web_extract` with `mode: "full"` |
|
|
210
|
+
| `firecrawl_map` | `web_map` (same behavior) |
|
|
211
|
+
| `firecrawl_crawl` | `web_crawl` with `mode: "light"` |
|
|
212
|
+
| `crawl4ai_crawl` | `web_crawl` with `mode: "full"` |
|
|
213
|
+
| `crawl4ai_stream` | (removed — use `web_crawl` with `mode: "full"`) |
|
|
214
|
+
| `crawl4ai_screenshot` | `web_screenshot` (same behavior) |
|
|
215
|
+
| `crawl4ai_pdf` | `web_pdf` (same behavior) |
|
|
216
|
+
| `crawl4ai_status` | Merged into `web_status` |
|
|
217
|
+
| `web_status` | `web_status` (enhanced with Crawl4AI health) |
|
|
218
|
+
|
|
219
|
+
All v0.3 tool names were removed in v0.4. Update any agent instructions or skills that reference the old names.
|
|
109
220
|
|
|
110
221
|
## Development
|
|
111
222
|
|
|
@@ -116,20 +227,3 @@ npm test
|
|
|
116
227
|
# Run only unit tests
|
|
117
228
|
npm run test:unit
|
|
118
229
|
```
|
|
119
|
-
|
|
120
|
-
## Practical Guidance
|
|
121
|
-
|
|
122
|
-
- Use `searxng_search` first for general web search, docs lookup, current facts, and source discovery; it is fast, self-hosted, and avoids hosted API costs/rate limits.
|
|
123
|
-
- Use `brave_search` as a fast hosted fallback when SearXNG results are weak/unavailable, or when an independent search index is useful. Use `include_content` sparingly.
|
|
124
|
-
- Use `web_content` for fast known-URL article/docs extraction when simple readable markdown is enough.
|
|
125
|
-
- Use `firecrawl_search` when SearXNG/Brave are unavailable, when Firecrawl search is preferred, or when search results should include scraped markdown.
|
|
126
|
-
- Use `firecrawl_scrape` for known URLs when extraction quality matters, pages are dynamic, links are needed, or structured JSON extraction is requested.
|
|
127
|
-
- Use `firecrawl_map` before crawling to discover candidate URLs and keep crawls targeted.
|
|
128
|
-
- Use `firecrawl_crawl` only when multiple pages are required; keep limits conservative and use include/exclude paths.
|
|
129
|
-
- Use `crawl4ai_scrape` for JavaScript-rendered pages and when you need high-quality LLM-ready markdown.
|
|
130
|
-
- Use `crawl4ai_crawl` when you need full crawl data (HTML, links, media) from multiple URLs.
|
|
131
|
-
- Use `crawl4ai_screenshot` or `crawl4ai_pdf` for visual/printable snapshots of rendered pages.
|
|
132
|
-
- Prefer `web_content` or `firecrawl_scrape` over Crawl4AI for simple static pages — Crawl4AI launches a full headless browser and is more resource-intensive.
|
|
133
|
-
- When answering from web content, cite source URLs from result links or metadata.
|
|
134
|
-
- Use `web_status` when provider configuration is uncertain or a web tool fails due to credentials/config.
|
|
135
|
-
- Use `crawl4ai_status` when Crawl4AI-specific connection issues occur.
|