docpull 4.0.1__tar.gz → 4.2.0__tar.gz
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.
- {docpull-4.0.1/src/docpull.egg-info → docpull-4.2.0}/PKG-INFO +266 -21
- docpull-4.2.0/README.md +575 -0
- {docpull-4.0.1 → docpull-4.2.0}/pyproject.toml +10 -2
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/__init__.py +1 -1
- docpull-4.2.0/src/docpull/benchmark.py +2922 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/cli.py +20 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/conversion/chunking.py +56 -23
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/conversion/extractor.py +129 -1
- docpull-4.2.0/src/docpull/conversion/markdown.py +516 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/conversion/special_cases.py +108 -3
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/core/fetcher.py +6 -4
- docpull-4.2.0/src/docpull/fixtures/__init__.py +1 -0
- docpull-4.2.0/src/docpull/fixtures/parallel-search-extract.json +103 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/http/client.py +80 -11
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/mcp/server.py +299 -1
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/mcp/sources.py +1 -0
- docpull-4.2.0/src/docpull/pack_tools.py +517 -0
- docpull-4.2.0/src/docpull/parallel_workflows.py +5740 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/pipeline/steps/convert.py +7 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/pipeline/steps/fetch.py +8 -24
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/pipeline/steps/save_ndjson.py +56 -0
- docpull-4.2.0/src/docpull/provider_cli.py +426 -0
- docpull-4.2.0/src/docpull/provider_keys.py +217 -0
- docpull-4.2.0/src/docpull/security/__init__.py +13 -0
- docpull-4.2.0/src/docpull/security/download_policy.py +339 -0
- docpull-4.2.0/src/docpull/source_scoring.py +98 -0
- {docpull-4.0.1 → docpull-4.2.0/src/docpull.egg-info}/PKG-INFO +266 -21
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull.egg-info/SOURCES.txt +13 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull.egg-info/requires.txt +8 -0
- docpull-4.2.0/tests/test_benchmark.py +645 -0
- {docpull-4.0.1 → docpull-4.2.0}/tests/test_chunking.py +24 -0
- {docpull-4.0.1 → docpull-4.2.0}/tests/test_cli.py +30 -0
- {docpull-4.0.1 → docpull-4.2.0}/tests/test_conversion.py +88 -0
- {docpull-4.0.1 → docpull-4.2.0}/tests/test_convert_step_new.py +25 -0
- {docpull-4.0.1 → docpull-4.2.0}/tests/test_mcp_server.py +13 -0
- {docpull-4.0.1 → docpull-4.2.0}/tests/test_mcp_tools.py +1 -0
- docpull-4.2.0/tests/test_pack_tools.py +283 -0
- docpull-4.2.0/tests/test_parallel_workflows.py +2246 -0
- docpull-4.2.0/tests/test_provider_cli.py +85 -0
- {docpull-4.0.1 → docpull-4.2.0}/tests/test_save_ndjson.py +8 -0
- {docpull-4.0.1 → docpull-4.2.0}/tests/test_security_hardening.py +237 -0
- {docpull-4.0.1 → docpull-4.2.0}/tests/test_special_cases.py +99 -1
- docpull-4.0.1/README.md +0 -336
- docpull-4.0.1/src/docpull/conversion/markdown.py +0 -280
- docpull-4.0.1/src/docpull/security/__init__.py +0 -6
- {docpull-4.0.1 → docpull-4.2.0}/LICENSE +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/setup.cfg +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/__main__.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/cache/__init__.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/cache/frontier.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/cache/manager.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/cache/streaming_dedup.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/conversion/__init__.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/conversion/protocols.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/conversion/trafilatura_extractor.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/core/__init__.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/discovery/__init__.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/discovery/_fetch.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/discovery/composite.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/discovery/crawler.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/discovery/filters.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/discovery/link_extractors/__init__.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/discovery/link_extractors/enhanced.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/discovery/link_extractors/protocols.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/discovery/link_extractors/static.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/discovery/protocols.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/discovery/sitemap.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/doctor.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/http/__init__.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/http/protocols.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/http/rate_limiter.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/mcp/__init__.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/mcp/tools.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/metadata_extractor.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/models/__init__.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/models/config.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/models/document.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/models/events.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/models/profiles.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/models/run.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/pipeline/__init__.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/pipeline/base.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/pipeline/manifest.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/pipeline/steps/__init__.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/pipeline/steps/chunk.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/pipeline/steps/dedup.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/pipeline/steps/metadata.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/pipeline/steps/save.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/pipeline/steps/save_json.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/pipeline/steps/save_sqlite.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/pipeline/steps/validate.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/py.typed +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/security/robots.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/security/url_validator.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull/time_utils.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull.egg-info/dependency_links.txt +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull.egg-info/entry_points.txt +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/src/docpull.egg-info/top_level.txt +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/tests/test_cache_conditional_get.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/tests/test_ci_policy.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/tests/test_discovery.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/tests/test_frontier_resume.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/tests/test_integration.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/tests/test_link_extractors.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/tests/test_naming.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/tests/test_outputs_e2e.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/tests/test_pipeline.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/tests/test_real_site_regressions.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/tests/test_save_sqlite.py +0 -0
- {docpull-4.0.1 → docpull-4.2.0}/tests/test_time_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: docpull
|
|
3
|
-
Version: 4.0
|
|
3
|
+
Version: 4.2.0
|
|
4
4
|
Summary: Pull documentation from the web and convert to clean markdown
|
|
5
5
|
Author-email: Zachary Roth <support@raintree.technology>
|
|
6
6
|
Maintainer-email: Raintree Technology <support@raintree.technology>
|
|
@@ -62,6 +62,10 @@ Requires-Dist: mcp>=1.0.0; extra == "mcp"
|
|
|
62
62
|
Requires-Dist: pyjwt>=2.13.0; extra == "mcp"
|
|
63
63
|
Requires-Dist: python-multipart>=0.0.27; extra == "mcp"
|
|
64
64
|
Requires-Dist: starlette>=1.0.1; extra == "mcp"
|
|
65
|
+
Provides-Extra: parallel
|
|
66
|
+
Requires-Dist: parallel-web>=1.0.1; extra == "parallel"
|
|
67
|
+
Provides-Extra: observability
|
|
68
|
+
Requires-Dist: raindrop-ai>=0.0.50; extra == "observability"
|
|
65
69
|
Provides-Extra: llm
|
|
66
70
|
Requires-Dist: tiktoken>=0.7.0; extra == "llm"
|
|
67
71
|
Provides-Extra: all
|
|
@@ -73,6 +77,8 @@ Requires-Dist: mcp>=1.0.0; extra == "all"
|
|
|
73
77
|
Requires-Dist: pyjwt>=2.13.0; extra == "all"
|
|
74
78
|
Requires-Dist: python-multipart>=0.0.27; extra == "all"
|
|
75
79
|
Requires-Dist: starlette>=1.0.1; extra == "all"
|
|
80
|
+
Requires-Dist: parallel-web>=1.0.1; extra == "all"
|
|
81
|
+
Requires-Dist: raindrop-ai>=0.0.50; extra == "all"
|
|
76
82
|
Provides-Extra: dev
|
|
77
83
|
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
78
84
|
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
@@ -90,7 +96,7 @@ Dynamic: license-file
|
|
|
90
96
|
|
|
91
97
|
# docpull
|
|
92
98
|
|
|
93
|
-
**Security-hardened, browser-free crawler that turns
|
|
99
|
+
**Security-hardened, browser-free web scraper and crawler that turns server-rendered pages into clean, AI-ready Markdown — fast.**
|
|
94
100
|
|
|
95
101
|
[](https://www.python.org/downloads/)
|
|
96
102
|
[](https://badge.fury.io/py/docpull)
|
|
@@ -103,15 +109,16 @@ Dynamic: license-file
|
|
|
103
109
|
</a>
|
|
104
110
|
</p>
|
|
105
111
|
|
|
106
|
-
docpull
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
112
|
+
docpull is a web scraper for static and server-rendered sites, with
|
|
113
|
+
documentation crawling as its sharpest default workflow. It uses async HTTP (not
|
|
114
|
+
Playwright) to fetch pages, discover links, extract main content, and write clean
|
|
115
|
+
Markdown with source-URL frontmatter — in seconds, with a small install
|
|
116
|
+
footprint. It won't render JavaScript, but for the large class of sites that
|
|
117
|
+
don't need it (API references, vendor docs, Python/Go stdlib, blogs, OpenAPI
|
|
118
|
+
specs, Next.js and Docusaurus builds), it is a fast, auditable,
|
|
119
|
+
sandbox-friendly way to pipe web content into an LLM context, a RAG index, or an
|
|
120
|
+
offline archive. SSRF, XXE, DNS-rebinding, and CRLF-injection protections are on
|
|
121
|
+
by default — a necessity when an AI agent is choosing the URLs.
|
|
115
122
|
|
|
116
123
|
## Install
|
|
117
124
|
|
|
@@ -122,22 +129,24 @@ pip install docpull
|
|
|
122
129
|
pip install 'docpull[llm]' # tiktoken for token-accurate chunking
|
|
123
130
|
pip install 'docpull[trafilatura]' # alternative extractor for noisy pages
|
|
124
131
|
pip install 'docpull[mcp]' # run as an MCP server for AI agents
|
|
132
|
+
pip install 'docpull[parallel]' # Parallel API context packs
|
|
133
|
+
pip install 'docpull[observability]' # Raindrop benchmark tracing
|
|
125
134
|
pip install 'docpull[all]' # everything above
|
|
126
135
|
```
|
|
127
136
|
|
|
128
137
|
## Quick start
|
|
129
138
|
|
|
130
139
|
```bash
|
|
131
|
-
#
|
|
140
|
+
# Scrape a page graph and save Markdown
|
|
132
141
|
docpull https://docs.example.com
|
|
133
142
|
|
|
134
|
-
#
|
|
143
|
+
# Scrape one page, no crawl — the fast path for agents
|
|
135
144
|
docpull https://docs.example.com/guide --single
|
|
136
145
|
|
|
137
146
|
# LLM-ready NDJSON with 4k-token chunks streamed to stdout
|
|
138
147
|
docpull https://docs.example.com --profile llm --stream | jq .
|
|
139
148
|
|
|
140
|
-
# Mirror
|
|
149
|
+
# Mirror scraped content for offline use
|
|
141
150
|
docpull https://docs.example.com --profile mirror --cache
|
|
142
151
|
```
|
|
143
152
|
|
|
@@ -220,6 +229,166 @@ docpull https://site.com --profile mirror # Full archive, polite, cached, hier
|
|
|
220
229
|
docpull https://site.com --profile quick # Sampling: 50 pages, depth 2.
|
|
221
230
|
```
|
|
222
231
|
|
|
232
|
+
## Parallel context packs
|
|
233
|
+
|
|
234
|
+
`docpull[parallel]` adds an optional source-discovery and research layer on top
|
|
235
|
+
of Parallel web intelligence APIs. Use the core crawler when you already know
|
|
236
|
+
the docs URL. Use Parallel packs when an agent needs current web sources found,
|
|
237
|
+
extracted, researched, organized, and loaded as durable local context.
|
|
238
|
+
|
|
239
|
+
Parallel handles live Search, Extract, Task, Entity Search, FindAll, TaskGroup,
|
|
240
|
+
and Monitor calls. docpull turns those results into local, inspectable packs
|
|
241
|
+
with Markdown, NDJSON, manifests, hashes, source indexes, workflow metadata, and
|
|
242
|
+
an `AGENT_CONTEXT.md` load plan so agents do not need to reverse-engineer raw API
|
|
243
|
+
responses before using the pack.
|
|
244
|
+
|
|
245
|
+
Live calls use your own Parallel API key. docpull never proxies requests through
|
|
246
|
+
a shared account or writes the key into pack artifacts. For normal PyPI installs,
|
|
247
|
+
`docpull parallel init` stores the key in a local secrets file with restricted
|
|
248
|
+
permissions so it works across shells and agent sessions. Pack artifacts can
|
|
249
|
+
still contain source content, workflow inputs/outputs, selected URLs, and
|
|
250
|
+
metadata, so treat them as research data.
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
pip install 'docpull[parallel]'
|
|
254
|
+
|
|
255
|
+
# Recommended local setup. Prompts securely and writes ~/.config/docpull/secrets.env.
|
|
256
|
+
docpull parallel init
|
|
257
|
+
docpull parallel auth --json
|
|
258
|
+
|
|
259
|
+
# Optional project-local setup for agent worktrees. Writes .env.local and
|
|
260
|
+
# adds it to .gitignore.
|
|
261
|
+
docpull parallel init --project
|
|
262
|
+
|
|
263
|
+
# CI can still use a normal environment secret instead.
|
|
264
|
+
export PARALLEL_API_KEY="<your-parallel-api-key>"
|
|
265
|
+
|
|
266
|
+
docpull parallel context-pack "Compare AI web-search APIs for agents" \
|
|
267
|
+
--query "AI web search API" \
|
|
268
|
+
--query "agent web extraction API" \
|
|
269
|
+
--include-domain parallel.ai \
|
|
270
|
+
--exclude-domain onparallel.com \
|
|
271
|
+
--output-dir ./packs/ai-web-search \
|
|
272
|
+
--mode advanced \
|
|
273
|
+
--extract-limit 8 \
|
|
274
|
+
--max-estimated-cost 0.05 \
|
|
275
|
+
--task-brief
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
`docpull parallel auth` checks local SDK/key presence without printing the key
|
|
279
|
+
value and reports the key source (`env`, `project_env`, `user_config`, or
|
|
280
|
+
`missing`). It does not make a live Parallel call or prove the key is valid. Use
|
|
281
|
+
`--json` when an agent or CI job needs machine-readable configuration status.
|
|
282
|
+
|
|
283
|
+
## Optional live providers
|
|
284
|
+
|
|
285
|
+
Parallel, Tavily, and Exa are equal optional live providers for benchmark and
|
|
286
|
+
provider context-pack workflows. You can configure zero, one, two, or all three
|
|
287
|
+
API keys. docpull looks for keys in this order: environment variables, project
|
|
288
|
+
`.env.local`, then `~/.config/docpull/secrets.env`. Missing providers are skipped
|
|
289
|
+
instead of failing provider-neutral runs.
|
|
290
|
+
|
|
291
|
+
```bash
|
|
292
|
+
docpull providers auth --json
|
|
293
|
+
docpull providers init parallel
|
|
294
|
+
docpull providers init tavily
|
|
295
|
+
docpull providers init exa
|
|
296
|
+
|
|
297
|
+
docpull providers context-pack "Compare AI web-search APIs for agents" \
|
|
298
|
+
--provider auto \
|
|
299
|
+
--query "AI web search API" \
|
|
300
|
+
--include-domain docs.parallel.ai \
|
|
301
|
+
--output-dir ./packs/provider-comparison
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
Use `--provider all` to request all three and record skipped-provider metadata
|
|
305
|
+
for keys or optional SDKs that are not configured. Use repeated `--provider`
|
|
306
|
+
values to run a specific subset.
|
|
307
|
+
|
|
308
|
+
A Parallel pack contains:
|
|
309
|
+
|
|
310
|
+
- `AGENT_CONTEXT.md` — agent load plan with source order, pack signals, warnings, errors, and artifact map.
|
|
311
|
+
- `documents.ndjson` — chunked records for agents and RAG pipelines.
|
|
312
|
+
- `corpus.manifest.json` — stable docpull record manifest.
|
|
313
|
+
- `parallel.pack.json` — Parallel workflow metadata, selected URLs, errors, IDs, and usage.
|
|
314
|
+
- `sources.md` and `sources/*.md` — human-readable sources and extracted Markdown.
|
|
315
|
+
- `brief.md` when `--task-brief` is enabled.
|
|
316
|
+
|
|
317
|
+
That makes the Parallel layer more than a pass-through wrapper: Parallel finds
|
|
318
|
+
and enriches live web sources, while docpull normalizes them into a repeatable
|
|
319
|
+
context pack that can be scored, diffed, audited, and loaded offline.
|
|
320
|
+
|
|
321
|
+
For planning without spending credits, use `--dry-run`. For repeatable packs,
|
|
322
|
+
use `--include-domain`, `--exclude-domain`, `--after-date`, and `--max-search-results`
|
|
323
|
+
to pin the source policy that appears later in `parallel.pack.json`.
|
|
324
|
+
Use `--fetch-max-age-seconds`, `--fetch-timeout-seconds`,
|
|
325
|
+
`--disable-cache-fallback`, `--excerpt-chars-per-result`, and `--location`
|
|
326
|
+
when you need Parallel's freshness, excerpt-size, and geo controls.
|
|
327
|
+
|
|
328
|
+
Offline fixtures are supported for demos and tests without a Parallel account:
|
|
329
|
+
|
|
330
|
+
```bash
|
|
331
|
+
docpull parallel demo --output-dir ./packs/demo
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
When working from the source checkout, the same fixture can also be imported
|
|
335
|
+
directly with `docpull parallel import ./docs/examples/parallel-search-extract.json`.
|
|
336
|
+
|
|
337
|
+
The core workflow is Search + Extract + optional Task. Broader pack workflows
|
|
338
|
+
cover Search-only snapshots, docs discovery plans, Extract-known-URL packs,
|
|
339
|
+
core-fetch-with-Parallel-fallback packs, diff briefs, Task lifecycle snapshots,
|
|
340
|
+
Entity Search, FindAll lifecycle actions, TaskGroup batches, Monitor
|
|
341
|
+
metadata/events, API specs, and local source scoring.
|
|
342
|
+
See [docs/parallel.md](docs/parallel.md) for the Parallel product cross-reference
|
|
343
|
+
and the boundary between docpull, Parallel MCP, and planned workflows.
|
|
344
|
+
|
|
345
|
+
Additional Parallel-backed artifact commands:
|
|
346
|
+
|
|
347
|
+
```bash
|
|
348
|
+
# Readiness and API-key setup checks.
|
|
349
|
+
docpull parallel auth
|
|
350
|
+
docpull parallel init
|
|
351
|
+
docpull parallel init --project
|
|
352
|
+
|
|
353
|
+
# Search + Extract + optional Task brief.
|
|
354
|
+
docpull parallel context-pack "Compare AI web-search APIs for agents" \
|
|
355
|
+
--query "AI web search API" \
|
|
356
|
+
--include-domain parallel.ai \
|
|
357
|
+
--dry-run
|
|
358
|
+
|
|
359
|
+
# Search-only, docs-discovery, known-URL extract, fallback, and structured Task packs.
|
|
360
|
+
docpull parallel search-pack "Parallel Search API docs" --query "Parallel Search API" --dry-run
|
|
361
|
+
docpull parallel discover-docs "Find Parallel API docs" \
|
|
362
|
+
--query "Parallel Search API docs" \
|
|
363
|
+
--include-domain docs.parallel.ai \
|
|
364
|
+
--dry-run
|
|
365
|
+
docpull parallel extract-pack https://docs.parallel.ai/api-reference/search/search --dry-run
|
|
366
|
+
docpull parallel fallback-pack https://docs.parallel.ai/api-reference/search/search --dry-run
|
|
367
|
+
docpull parallel task-pack "Research Parallel Search API" \
|
|
368
|
+
--source-include-domain docs.parallel.ai \
|
|
369
|
+
--output-schema-json '{"type":"object","properties":{"summary":{"type":"string"}},"required":["summary"]}' \
|
|
370
|
+
--dry-run
|
|
371
|
+
|
|
372
|
+
# Entity dossiers, FindAll lifecycle, batch enrichment, monitors, and API specs.
|
|
373
|
+
docpull parallel entity-pack "AI developer infrastructure companies" --entity-type companies
|
|
374
|
+
docpull parallel findall-pack "AI developer infrastructure companies" --generator preview --dry-run
|
|
375
|
+
docpull parallel findall-ingest-pack "Find companies with public API docs"
|
|
376
|
+
docpull parallel findall-result-pack findall_123 --output-dir ./packs/findall-result
|
|
377
|
+
docpull parallel taskgroup-pack ./companies.json --prompt-template "Research {company}" --dry-run
|
|
378
|
+
docpull parallel taskgroup-pack ./companies.json --prompt-template "Research {company}" --wait
|
|
379
|
+
docpull parallel monitor-pack create "New vendor pricing changes" --dry-run
|
|
380
|
+
docpull parallel monitor-pack create --type snapshot --task-run-id run_123 --dry-run
|
|
381
|
+
docpull parallel monitor-pack list --status active --output-dir ./packs/monitors
|
|
382
|
+
docpull parallel monitor-pack events monitor_123 --cursor next_cursor --output-dir ./packs/events
|
|
383
|
+
docpull parallel api-pack https://docs.parallel.ai/public-openapi.json --output-dir ./packs/parallel-openapi
|
|
384
|
+
docpull parallel run ./docs/examples/parallel-llms-api-pack.yaml --dry-run
|
|
385
|
+
docpull parallel run ./docs/examples/parallel-openapi-api-pack.yaml --dry-run
|
|
386
|
+
docpull pack score ./packs/parallel-openapi
|
|
387
|
+
docpull pack sources ./packs/parallel-openapi --require-domain docs.parallel.ai
|
|
388
|
+
docpull pack diff ./packs/old ./packs/new --markdown ./packs/changes.md
|
|
389
|
+
docpull parallel diff-brief ./packs/old ./packs/new --dry-run
|
|
390
|
+
```
|
|
391
|
+
|
|
223
392
|
## MCP server
|
|
224
393
|
|
|
225
394
|
docpull ships an MCP (Model Context Protocol) server so AI agents can call it
|
|
@@ -271,17 +440,21 @@ pip install 'docpull[mcp]'
|
|
|
271
440
|
|
|
272
441
|
See [plugin/README.md](plugin/README.md) for details.
|
|
273
442
|
|
|
274
|
-
Tools exposed (
|
|
443
|
+
Tools exposed (12 total — read tools advertise `readOnlyHint` so hosts that auto-approve safe tools won't prompt):
|
|
275
444
|
|
|
276
445
|
Read:
|
|
277
446
|
- `fetch_url(url, max_tokens?)` — one-shot fetch, no crawl. HTTPS-only, SSRF-validated.
|
|
278
|
-
- `list_sources(category?)` — show available aliases (react, nextjs, fastapi, …)
|
|
447
|
+
- `list_sources(category?)` — show available aliases (react, nextjs, parallel, fastapi, …)
|
|
279
448
|
- `list_indexed()` — what has been fetched locally, with last-fetched age
|
|
280
449
|
- `grep_docs(pattern, library?, limit?, context?)` — regex search across fetched Markdown (length-capped + wall-clock budgeted to mitigate ReDoS)
|
|
281
450
|
- `read_doc(library, path, line_start?, line_end?)` — read a specific cached file, optionally line-sliced
|
|
451
|
+
- `pack_score(pack_dir, required_domains?)` — score a local context pack for agent readiness.
|
|
452
|
+
- `pack_diff(old_pack_dir, new_pack_dir)` — compare pack URL sets and content hashes.
|
|
282
453
|
|
|
283
454
|
Write:
|
|
284
455
|
- `ensure_docs(source, force?, profile?)` — fetch a named library (cached 7 days). Forwards progress to clients that supply a `progressToken`.
|
|
456
|
+
- `parallel_context_pack(...)` — build or dry-run a Parallel Search + Extract pack without shelling out.
|
|
457
|
+
- `parallel_api_pack(source, kind?, output_dir?)` — build a pack from `llms.txt` or OpenAPI.
|
|
285
458
|
- `add_source(name, url, description?, category?, max_pages?, force?)` — register a user alias (HTTPS-only, atomic write to `sources.yaml`).
|
|
286
459
|
- `remove_source(name, delete_cache?)` — drop a user alias and (optionally) its cached docs.
|
|
287
460
|
|
|
@@ -388,15 +561,16 @@ End-to-end numbers from `tests/benchmarks/test_10k_pages.py` against a
|
|
|
388
561
|
synthetic 10,000-page localhost site (RAG profile, `max_concurrent=50`,
|
|
389
562
|
`per_host_concurrent=50`, HTTP keep-alive, 5% injected duplicate content).
|
|
390
563
|
The benchmark emits progress every 1,000 pages plus a final JSON report for
|
|
391
|
-
trend tooling.
|
|
564
|
+
trend tooling. Wall time varies by machine; the value below is the latest
|
|
565
|
+
local audit run.
|
|
392
566
|
|
|
393
567
|
| Metric | Value |
|
|
394
568
|
|---|---|
|
|
395
|
-
| Total wall time | ~
|
|
569
|
+
| Total wall time | ~309 s |
|
|
396
570
|
| Pages fetched / skipped / failed | 9,501 / 499 / 0 |
|
|
397
|
-
| Time to first saved page | ~
|
|
398
|
-
| Per-page latency p50 / p95 / p99 | ~0 /
|
|
399
|
-
| Peak RSS delta from baseline | ~
|
|
571
|
+
| Time to first saved page | ~119 ms |
|
|
572
|
+
| Per-page latency p50 / p95 / p99 | ~0 / 168 / 271 ms |
|
|
573
|
+
| Peak RSS delta from baseline | ~93 MB |
|
|
400
574
|
| Cache manifest size on disk | ~8.9 MB |
|
|
401
575
|
| Duplicates detected (5% injected) | 499 / 500 |
|
|
402
576
|
|
|
@@ -404,6 +578,77 @@ Reproduce with `make benchmark` (requires `aiohttp`; runs the gated
|
|
|
404
578
|
benchmark in `tests/benchmarks/` and prints progress plus a JSON line you can
|
|
405
579
|
pipe into trend tooling).
|
|
406
580
|
|
|
581
|
+
For real-site and live-provider context-pack benchmarks, use the first-class
|
|
582
|
+
benchmark harness:
|
|
583
|
+
|
|
584
|
+
```bash
|
|
585
|
+
docpull benchmark quick
|
|
586
|
+
docpull benchmark quick --provider auto --max-estimated-cost 0.05
|
|
587
|
+
docpull benchmark quick --provider all --max-estimated-cost 0.10
|
|
588
|
+
docpull benchmark quick --target-set provider-matrix --provider all \
|
|
589
|
+
--max-pages 8 --max-depth 1 --max-search-results 5 --extract-limit 2 \
|
|
590
|
+
--max-estimated-cost 0.10
|
|
591
|
+
docpull benchmark article .bench/runs/<run>/benchmark.report.json
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
`docpull benchmark quick` writes `benchmark.report.json` and
|
|
595
|
+
`benchmark.summary.md` under `.bench/runs/<timestamp>/` by default. The core
|
|
596
|
+
cases measure an LLM-profile crawl plus a cached rerun. Passing `--provider auto`
|
|
597
|
+
runs every locally ready provider. Passing `--provider all` requests Parallel,
|
|
598
|
+
Tavily, and Exa, then records missing keys or optional SDKs in
|
|
599
|
+
`skipped_providers` without failing the benchmark. Live Parallel calls still use
|
|
600
|
+
the local `--max-estimated-cost` guard before any work starts.
|
|
601
|
+
|
|
602
|
+
Use `--target-set tool-docs` to run a cross-pull matrix across the Parallel,
|
|
603
|
+
Exa, Tavily, Raindrop, and DocPull documentation sites. Use `--target-set provider-matrix`
|
|
604
|
+
to add three low-cap adversarial public targets for JS-heavy docs, noisy
|
|
605
|
+
archived navigation, and freshness-sensitive pricing. Matrix runs skip the
|
|
606
|
+
cached core pass by default so the headline grid stays provider x target; pass
|
|
607
|
+
`--cached-pass` to force cache measurement across the matrix.
|
|
608
|
+
|
|
609
|
+
The compatibility flags `--parallel`, `--tavily`, and `--exa` still work as
|
|
610
|
+
provider aliases. Tavily Search + Extract and Exa Search-with-contents are
|
|
611
|
+
normalized into the same local
|
|
612
|
+
`documents.ndjson`, `corpus.manifest.json`, `sources.md`, provider `*.pack.json`,
|
|
613
|
+
`pack.score.json`, and `source.scores.json` artifacts as the core and Parallel
|
|
614
|
+
cases. The report keeps the legacy pack score and adds weighted benchmark
|
|
615
|
+
sub-scores for coverage, cleanliness, source fidelity, freshness, and density.
|
|
616
|
+
Keys can be exported as `PARALLEL_API_KEY`, `TAVILY_API_KEY`, and `EXA_API_KEY`
|
|
617
|
+
or stored together in `~/.config/docpull/secrets.env`; docpull does not write
|
|
618
|
+
keys into benchmark artifacts.
|
|
619
|
+
|
|
620
|
+
Tavily usage is credit-based, so set `TAVILY_CREDIT_USD` or pass
|
|
621
|
+
`--tavily-credit-usd` to convert credits into estimated dollars for cost
|
|
622
|
+
comparisons. Without that value, Tavily credits are still recorded in
|
|
623
|
+
`cost_units` but excluded from normalized USD totals.
|
|
624
|
+
|
|
625
|
+
To trace the benchmark in Raindrop for a publishable observability/eval loop,
|
|
626
|
+
install the optional SDK and pass `--trace raindrop`:
|
|
627
|
+
|
|
628
|
+
```bash
|
|
629
|
+
pip install 'docpull[parallel,observability]'
|
|
630
|
+
export PARALLEL_API_KEY="<your-parallel-api-key>"
|
|
631
|
+
export TAVILY_API_KEY="<your-tavily-api-key>"
|
|
632
|
+
export TAVILY_CREDIT_USD="<account-credit-value>"
|
|
633
|
+
export EXA_API_KEY="<your-exa-api-key>"
|
|
634
|
+
export RAINDROP_WRITE_KEY="<your-raindrop-write-key>"
|
|
635
|
+
docpull benchmark quick --target-set provider-matrix --provider all --trace raindrop \
|
|
636
|
+
--max-pages 8 --max-depth 1 --max-search-results 5 --extract-limit 2 \
|
|
637
|
+
--max-estimated-cost 0.10
|
|
638
|
+
docpull benchmark article .bench/runs/<run>/benchmark.report.json
|
|
639
|
+
```
|
|
640
|
+
|
|
641
|
+
Raindrop traces are metadata-only by default: docpull records timings, counts,
|
|
642
|
+
scores, costs, selected URLs, provider, workflow, target, prompt, settings, and
|
|
643
|
+
artifact paths, but does not send scraped page content unless a future caller
|
|
644
|
+
explicitly adds that behavior. `RAINDROP_WRITE_KEY` can be exported or stored in
|
|
645
|
+
the same `~/.config/docpull/secrets.env` file as the provider keys.
|
|
646
|
+
|
|
647
|
+
When Raindrop tracing is enabled, DocPull also emits Raindrop signals for
|
|
648
|
+
attention-worthy benchmark cells: failed cases, low scores, slow cases,
|
|
649
|
+
high-cost cells, and score-dimension warnings. The benchmark report stores the
|
|
650
|
+
Raindrop event id and signal counts so traced runs can be audited later.
|
|
651
|
+
|
|
407
652
|
## Troubleshooting
|
|
408
653
|
|
|
409
654
|
```bash
|