pi-quiver 5.2.4 → 5.3.0
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 +24 -0
- package/README.md +36 -10
- package/dist/bin/pi-quiver.js +702 -259
- package/dist/lib/unpdf-worker.js +58 -0
- package/extensions/doc_to_md.ts +52 -62
- package/lib/doc-to-md-bundle.ts +139 -0
- package/lib/doc-to-md-core.ts +261 -301
- package/lib/doc-to-md-handle.ts +108 -0
- package/lib/doc-to-md-options.ts +186 -0
- package/lib/unpdf-worker.ts +54 -0
- package/package.json +6 -4
- package/scripts/doc_to_md.py +369 -0
- package/scripts/pdf_to_md.py +0 -30
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,30 @@ Published to npm as `pi-quiver` (`pi install npm:pi-quiver`). Pushing a
|
|
|
8
8
|
via OIDC trusted publishing. The release helper at
|
|
9
9
|
`.agents/skills/release/scripts/release.sh` cuts the tag; CI publishes.
|
|
10
10
|
|
|
11
|
+
## v5.3.0 - 2026-09-09
|
|
12
|
+
|
|
13
|
+
- doc_to_md: results are now a bundle on disk (`<stem>.md` + `images/`, temp dir
|
|
14
|
+
or `outputDir`) plus a bounded handle (paths, page count, outline,
|
|
15
|
+
diagnostics) - Markdown is never returned inline; `read` the `Saved-To` file.
|
|
16
|
+
The former 32KB inline/spill size gate is gone (#13).
|
|
17
|
+
- doc_to_md: `info` mode (page count, metadata, TOC or sheet inventory),
|
|
18
|
+
optional 1-based `pages` selection, canonical `--- end of page.page_number=N ---`
|
|
19
|
+
separators on every tier, images always extracted with relative links.
|
|
20
|
+
- doc_to_md: three terminable child tiers - pymupdf4llm -> PyMuPDF per-page text
|
|
21
|
+
(degraded, marked) -> unpdf worker only when no Python backend; each spawn is
|
|
22
|
+
tree-killed on its own timeout; backend discovery bounded by one absolute
|
|
23
|
+
`warmTimeoutMs`; managed venv moves to `doc-to-md-venv-v2` with openpyxl,
|
|
24
|
+
xlrd and pillow pinned alongside pymupdf4llm.
|
|
25
|
+
- doc_to_md: direct `.xlsx`/`.xls` conversion to per-worksheet matrices
|
|
26
|
+
(formulas + cached values, merged/hidden/truncation disclosed, sheet images).
|
|
27
|
+
- doc_to_md: one option descriptor table drives the tool schema, the new
|
|
28
|
+
`quiver.docToMd` settings block (per-call > settings > deprecated
|
|
29
|
+
`PI_DOC_TO_MD_*` env > default) and the CLI (`pi-quiver doc-to-md [flags]`,
|
|
30
|
+
`--help`, exit codes 0/1/2). `scripts/pdf_to_md.py` replaced by
|
|
31
|
+
`scripts/doc_to_md.py`; `unpdf` bumped to ^1.8.1.
|
|
32
|
+
- Tests: synthetic PDF/DOCX/PPTX/XLSX/XLS fixtures, uv/soffice-gated integration
|
|
33
|
+
suite; CI installs uv and LibreOffice.
|
|
34
|
+
|
|
11
35
|
## v5.2.4 - 2026-09-08
|
|
12
36
|
|
|
13
37
|
- doc_to_md: build the LibreOffice `-env:UserInstallation` value with
|
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ But the moment an agent does that, one `fetch` or PDF read can dump hundreds of
|
|
|
16
16
|
|
|
17
17
|
## Why pi-quiver exists
|
|
18
18
|
|
|
19
|
-
`fetch`
|
|
19
|
+
`fetch` brings real web pages and GitHub issues/PRs into context and is size-gated by construction: over 32 KB or 1000 lines spills to a temp file with a preview and a grep/read hint. `doc_to_md` converts local PDF/DOCX/PPTX/XLSX/XLS files into a Markdown bundle on disk and returns only a concise handle. Ingestion is what makes data-driven work possible; bounded tool results keep it safe.
|
|
20
20
|
|
|
21
21
|
`session-name`, `sword-header`, `fast-mode`, `provider-stall-watchdog`, and `slack` are opt-in ergonomics, recovery, and integration controls: session labeling, a themed startup header, Anthropic fast mode, semantic-stall recovery, and context-safe Slack search/threads/posting with repo-policy injection, `@name` mention resolution, cached emails, and per-call unfurl control.
|
|
22
22
|
|
|
@@ -29,19 +29,21 @@ Four independent extensions for the [pi coding agent](https://github.com/earendi
|
|
|
29
29
|
- [pi-condense](https://github.com/jjuraszek/pi-condense) - context economy (prune context, keep it recoverable)
|
|
30
30
|
- [pi-gauntlet](https://github.com/jjuraszek/pi-gauntlet) - process (the gated brainstorm->ship workflow)
|
|
31
31
|
|
|
32
|
-
No code dependency between them. pi-quiver is call-level:
|
|
32
|
+
No code dependency between them. pi-quiver is call-level: `fetch` gates the size of what comes *in*, while `doc_to_md` writes a bundle and returns its handle. [pi-condense](https://github.com/jjuraszek/pi-condense) is loop-level: it prunes what's already *in context* once a tool call is done. Different problem, same discipline.
|
|
33
33
|
|
|
34
34
|
## Mental model
|
|
35
35
|
|
|
36
|
-
Every ingestion extension here is context-safe by construction, not by convention:
|
|
36
|
+
Every ingestion extension here is context-safe by construction, not by convention: `fetch` size-gates every call, while `doc_to_md` always writes a bundle and returns a handle instead of inline Markdown. `fetch` and `doc_to_md` bring real sources in; `session-name`, `sword-header`, `fast-mode`, `provider-stall-watchdog`, and `slack` are opt-in.
|
|
37
37
|
|
|
38
38
|
```mermaid
|
|
39
39
|
flowchart LR
|
|
40
|
-
S[web page
|
|
40
|
+
S[web page] --> T[fetch]
|
|
41
41
|
T --> E[extract main content]
|
|
42
42
|
E --> G{"over 32KB or 1000 lines?"}
|
|
43
43
|
G -->|no| I[return inline to context]
|
|
44
44
|
G -->|yes| F[spill to temp file<br/>return preview + grep/read hint]
|
|
45
|
+
D[local PDF / Office / Excel] --> B[doc_to_md]
|
|
46
|
+
B --> H[Markdown bundle on disk<br/>return handle]
|
|
45
47
|
```
|
|
46
48
|
|
|
47
49
|
## Quick example
|
|
@@ -62,8 +64,8 @@ A 300 KB changelog page never touches your context window - you get a preview an
|
|
|
62
64
|
|
|
63
65
|
| Extension | Tool | What it does |
|
|
64
66
|
| --- | --- | --- |
|
|
65
|
-
| `extensions/fetch.ts` | `fetch` | Retrieve URLs over HTTP(S). HTML -> Markdown (Readability extraction, Turndown conversion). Binary saved untouched to a temp file. GitHub issue/PR/repo/actions-run/actions-job URLs auto-route through `gh` (falls back to HTTP); failed runs/jobs include failed-step logs (best-effort, summary-only otherwise). Same size gate as `
|
|
66
|
-
| `extensions/doc_to_md.ts` | `doc_to_md` | Convert a local PDF/DOCX/PPTX to Markdown
|
|
67
|
+
| `extensions/fetch.ts` | `fetch` | Retrieve URLs over HTTP(S). HTML -> Markdown (Readability extraction, Turndown conversion). Binary saved untouched to a temp file. GitHub issue/PR/repo/actions-run/actions-job URLs auto-route through `gh` (falls back to HTTP); failed runs/jobs include failed-step logs (best-effort, summary-only otherwise). Same size gate as `fetch`. Behavior lives in `lib/fetch-core.ts`; also exposed as the `pi-quiver fetch` CLI (see [Claude Code support](#claude-code-support)). |
|
|
68
|
+
| `extensions/doc_to_md.ts` | `doc_to_md` | Convert a local PDF/DOCX/PPTX/XLSX/XLS to a Markdown bundle on disk (`<stem>.md` + `images/`) and return a handle (paths, page count, outline, diagnostics) - never inline Markdown. `info` mode inspects first; `pages` selects 1-based pages; every page ends with `--- end of page.page_number=N ---`. Tiers: pymupdf4llm -> PyMuPDF text (degraded) -> unpdf worker (no Python only). Excel -> per-worksheet matrices with formulas/cached values/merged/hidden. Settings under `quiver.docToMd`. |
|
|
67
69
|
| `extensions/session-name.ts` | `/session-name` | Manual + opt-in automatic session naming, naming rules and deny list, long-session revisits, and Ghostty/Herdr tab rename. OFF by default. |
|
|
68
70
|
| `extensions/sword-header.ts` | `/builtin-header` | Themed ASCII startup header replacing pi's default logo. OFF by default. |
|
|
69
71
|
| `extensions/fast-mode.ts` | `/fast` | Inject Anthropic fast-mode (`speed: "fast"` + `anthropic-beta: fast-mode-2026-02-01`) into every Claude Opus 4.8 / Opus 5 request, any thinking level. `--fast` flag + `/fast [on\|off\|status]`. OFF by default. |
|
|
@@ -91,7 +93,7 @@ Full routing rules, size-gate mechanics, and config: [doc/fetch.md](doc/fetch.md
|
|
|
91
93
|
## When NOT to use
|
|
92
94
|
|
|
93
95
|
- You need a general-purpose web scraper (JS-rendered pages, pagination, auth flows) - `fetch` does plain HTTP + Readability extraction, nothing more.
|
|
94
|
-
- You need
|
|
96
|
+
- You need `.xlsm`, sheet/range selection or chart rendering - out of scope.
|
|
95
97
|
- You want automatic session naming, a custom header, fast mode, or stall recovery without opting in - all stay off until you flip the config.
|
|
96
98
|
- You need *mid-stream* stall recovery in JSON, RPC, or print runs - only the pre-first-event tier arms there; mid-stream silence falls through to pi's transport timeout.
|
|
97
99
|
|
|
@@ -131,7 +133,7 @@ The npm package's bundled JS deps install automatically on `pi install`. A few *
|
|
|
131
133
|
| Prerequisite | Needed by | If absent |
|
|
132
134
|
| --- | --- | --- |
|
|
133
135
|
| `gh` (GitHub CLI, installed + `gh auth login`) | `fetch` GitHub issue/PR/repo/actions-run/actions-job routing | Falls back to an HTTP fetch of the rendered page (private repos hit a login wall). |
|
|
134
|
-
| `uv` (+ managed Python 3.14, fetched on first use) | `doc_to_md` high-fidelity PDF conversion (preferred route) | Falls back to a system Python >= 3.12
|
|
136
|
+
| `uv` (+ managed Python 3.14, fetched on first use) | `doc_to_md` high-fidelity PDF and Excel conversion (preferred route), with `pymupdf4llm`, `openpyxl`, `xlrd`, and `pillow` | Falls back to a system Python >= 3.12 or one-time managed venv; PDF degrades to `unpdf` only when no capable Python exists. Excel requires the Python backend (no JS fallback). |
|
|
135
137
|
| LibreOffice (`soffice` on `PATH`) | `doc_to_md` DOCX/PPTX conversion | Office inputs error (no JS fallback for office->PDF); PDFs unaffected. |
|
|
136
138
|
|
|
137
139
|
None is a hard install-time dependency of the package; they are tools you provide in the environment where pi runs.
|
|
@@ -262,6 +264,30 @@ Operational notes:
|
|
|
262
264
|
|
|
263
265
|
Each setting can also be overridden per-process via `PI_QUIVER_SLACK_ENABLED`, `PI_QUIVER_SLACK_CACHE_PATH`, `PI_QUIVER_SLACK_USER_TOKEN_ENV`, `PI_QUIVER_SLACK_BOT_TOKEN_ENV`, and `PI_QUIVER_SLACK_UPLOAD_THRESHOLD_CHARS` - applied on top of the resolved `settings.json` layers, same override rung the extension's config resolver defines. Tokens themselves are resolved per call: process env first, then the repo's `.env` file (or the primary checkout's, for a worktree with none) - never a fallback across identities. Full reference incl. cache layering, the announce protocol, and the `search.messages`/`conversations.replies` throttle caveats: [doc/slack.md](doc/slack.md).
|
|
264
266
|
|
|
267
|
+
### doc_to_md settings
|
|
268
|
+
|
|
269
|
+
`doc_to_md` is always registered. Configure tunables in `quiver.docToMd`; per-call > `quiver.docToMd` > `PI_DOC_TO_MD_*` env (deprecated) > default. The result is a handle; `read` the `Saved-To` file (offset/limit) for the Markdown, images live under `Images-Dir`.
|
|
270
|
+
|
|
271
|
+
| Key | Default | Meaning |
|
|
272
|
+
|---|---|---|
|
|
273
|
+
| `primaryTimeoutMs` | `60000` | pymupdf4llm tier and unpdf tier deadline. |
|
|
274
|
+
| `fallbackTimeoutMs` | `30000` | PyMuPDF text tier and PDF info deadline. |
|
|
275
|
+
| `sofficeTimeoutMs` | `120000` | DOCX/PPTX -> PDF deadline. |
|
|
276
|
+
| `excelTimeoutMs` | `60000` | Excel child and Excel info deadline. |
|
|
277
|
+
| `warmTimeoutMs` | `120000` | Absolute first-call backend discovery/bootstrap deadline. |
|
|
278
|
+
| `pymupdfVersion` | `1.27.2.3` | pymupdf4llm pin, minimum `1.27.0`. |
|
|
279
|
+
| `imageDpi` | `150` | Render DPI for page images. |
|
|
280
|
+
| `imageFormat` | `png` | Rendered image format: `png` or `jpg`; embedded images retain their extension. |
|
|
281
|
+
| `maxCellsPerSheet` | `50000` | Rows x columns budget per worksheet. |
|
|
282
|
+
| `maxOutputBytes` | `20000000` | Child stdout cap in bytes. |
|
|
283
|
+
| `outlineMaxEntries` | `40` | Heading outline, TOC, or sheet inventory entries in the handle. |
|
|
284
|
+
|
|
285
|
+
A bundle is `<outputDir>/<stem>.md` plus `<outputDir>/images/`; without `outputDir`, the tool creates a per-call temp root. A conversion owns `<stem>.md.lock` until it atomically publishes the Markdown. An existing `<stem>.md` fails the call unless `overwrite` is set; `overwrite` replaces that Markdown and the images it owns (`<stem>-p<N>-<n>.*` / `<stem>-s<idx>-<n>.*`), nothing else. Temp bundles are caller-owned - the tool never deletes a bundle it produced.
|
|
286
|
+
|
|
287
|
+
Excel needs a Python backend with openpyxl, xlrd and pillow - otherwise the call fails with `Remedy: install uv, or pip install openpyxl xlrd pillow`.
|
|
288
|
+
|
|
289
|
+
Worst-case wall time is `warmTimeoutMs (first call) + sofficeTimeoutMs (Office only) + primaryTimeoutMs + fallbackTimeoutMs + KILL_GRACE_MS x kills` (Excel: `warmTimeoutMs + excelTimeoutMs + KILL_GRACE_MS`). There is no cap on image count, image bytes or workbook memory - deliberately; the per-tier timeouts and `maxOutputBytes` are the bounds.
|
|
290
|
+
|
|
265
291
|
### Migrating from flat keys
|
|
266
292
|
|
|
267
293
|
The flat top-level form (`"fastMode": ...` etc. directly under `settings.json`)
|
|
@@ -288,9 +314,9 @@ flat form to fall back to.
|
|
|
288
314
|
|
|
289
315
|
## Claude Code support
|
|
290
316
|
|
|
291
|
-
`fetch`
|
|
317
|
+
`fetch` and `doc_to_md` cores are also published through the CLI, so Claude Code can use the same routing or bundle-and-handle behavior as pi's native tools - without pi ever seeing Claude-only files.
|
|
292
318
|
|
|
293
|
-
**Exposed:** the `quiver` plugin, served from this repo's `.claude-plugin/marketplace.json`, with two skills: `fetch` (invoked as `quiver:fetch` / `/quiver:fetch`) and `doc-to-md` (invoked as `quiver:doc-to-md` / `/quiver:doc-to-md`). The `fetch` skill runs `npx -y pi-quiver@latest fetch <url> [flags]` via Bash - full parameter parity with the pi tool (`--method`, `--header`, `--body`, `--raw`, `--timeout-ms`), same GitHub `gh` routing (including failed-step logs on failed runs/jobs), same size gate, same binary-to-temp-file handling. See [doc/fetch.md](doc/fetch.md#claude-code-cli-pi-quiver-fetch) for exit codes and flags. The `doc-to-md` skill runs `npx -y pi-quiver@latest doc-to-md <path>`
|
|
319
|
+
**Exposed:** the `quiver` plugin, served from this repo's `.claude-plugin/marketplace.json`, with two skills: `fetch` (invoked as `quiver:fetch` / `/quiver:fetch`) and `doc-to-md` (invoked as `quiver:doc-to-md` / `/quiver:doc-to-md`). The `fetch` skill runs `npx -y pi-quiver@latest fetch <url> [flags]` via Bash - full parameter parity with the pi tool (`--method`, `--header`, `--body`, `--raw`, `--timeout-ms`), same GitHub `gh` routing (including failed-step logs on failed runs/jobs), same size gate, same binary-to-temp-file handling. See [doc/fetch.md](doc/fetch.md#claude-code-cli-pi-quiver-fetch) for exit codes and flags. The `doc-to-md` skill runs `npx -y pi-quiver@latest doc-to-md [flags] <path>` with full flag parity and the same handle output. See [doc/doc-to-md.md](doc/doc-to-md.md#cli-pi-quiver-doc-to-md) for exit codes and flags.
|
|
294
320
|
|
|
295
321
|
**Not exposed:** the other pi extensions in this package (`session-name`, `sword-header`, `fast-mode`, `provider-stall-watchdog`, `slack`) - the marketplace allowlists only `./skills/fetch` and `./skills/doc-to-md`, and the npm tarball never ships `skills/` or `.claude-plugin/` (pi's own `files` allowlist excludes them, and pi's explicit `pi.extensions` manifest makes them invisible to pi's convention-directory auto-discovery either way).
|
|
296
322
|
|