@lincoln504/pi-research 1.7.8 → 1.7.9
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/agent-skill/pi-research/README.md +3 -3
- package/agent-skill/pi-research/SKILL.md +1 -1
- package/dist/cli-bin.mjs +3 -0
- package/dist/cli.mjs +652 -380
- package/dist/pdf-extract-worker.mjs +1 -1
- package/dist/thread-worker.mjs +6 -6
- package/docs/AGENT-SKILL.md +3 -3
- package/docs/ARCHITECTURE.md +64 -50
- package/docs/CHANGELOG.md +21 -0
- package/docs/CONFIGURATION.md +2 -2
- package/docs/SDK.md +7 -6
- package/docs/THIRD-PARTY-NOTICES.md +11 -7
- package/package.json +10 -8
- package/scripts/camoufox-layout.cjs +455 -0
- package/scripts/cleanup.cjs +72 -29
- package/scripts/setup.cjs +72 -111
- package/src/cli-bin.mjs +3 -0
- package/src/cli.ts +12 -13
- package/src/healthcheck/index.ts +1 -1
- package/src/infrastructure/browser/browser-cleanup.ts +1 -1
- package/src/infrastructure/browser/browser-error-utils.ts +5 -4
- package/src/infrastructure/browser/camoufox-layout.ts +450 -0
- package/src/infrastructure/browser/config.ts +46 -103
- package/src/infrastructure/browser/ensure-browser.ts +63 -49
- package/src/infrastructure/browser/thread-worker-browser.ts +38 -42
- package/src/infrastructure/browser/thread-worker.mjs +6 -6
- package/src/infrastructure/knowledge-store-service.ts +6 -6
- package/src/orchestration/researcher-executor.ts +47 -1
- package/src/tui/research-health.ts +1 -1
- package/src/utils/log-utils.ts +1 -1
- package/src/web-research/browser-search.ts +8 -10
- package/src/web-research/pdf-extract-worker.mjs +1 -1
- package/src/web-research/scraper-utils.ts +11 -2
- package/src/web-research/web-scraper.ts +1 -1
|
@@ -221,7 +221,7 @@ var AUTH_SCHEME_PATTERN = new RegExp(
|
|
|
221
221
|
"gi"
|
|
222
222
|
);
|
|
223
223
|
var KNOWN_TOKEN_PATTERN = new RegExp(
|
|
224
|
-
`${B_LEFT}(sk-[A-Za-z0-9_-]{16,}|gh[posru]_[A-Za-z0-9]{16,}|github_pat_[A-Za-z0-9_]{20,}|AKIA[0-9A-Z]{16}|xox[baprs]-[A-Za-z0-9-]{10,})${B_RIGHT}`,
|
|
224
|
+
`${B_LEFT}(sk-[A-Za-z0-9_-]{16,}|gh[posru]_[A-Za-z0-9]{16,}|github_pat_[A-Za-z0-9_]{20,}|AKIA[0-9A-Z]{16}|AIza[0-9A-Za-z_-]{35}|npm_[A-Za-z0-9]{36}|hf_[A-Za-z0-9]{30,}|xox[baprs]-[A-Za-z0-9-]{10,})${B_RIGHT}`,
|
|
225
225
|
"g"
|
|
226
226
|
);
|
|
227
227
|
var JWT_PATTERN = new RegExp(
|
package/dist/thread-worker.mjs
CHANGED
|
@@ -107,7 +107,7 @@ var init_log_utils = __esm({
|
|
|
107
107
|
"gi"
|
|
108
108
|
);
|
|
109
109
|
KNOWN_TOKEN_PATTERN = new RegExp(
|
|
110
|
-
`${B_LEFT}(sk-[A-Za-z0-9_-]{16,}|gh[posru]_[A-Za-z0-9]{16,}|github_pat_[A-Za-z0-9_]{20,}|AKIA[0-9A-Z]{16}|xox[baprs]-[A-Za-z0-9-]{10,})${B_RIGHT}`,
|
|
110
|
+
`${B_LEFT}(sk-[A-Za-z0-9_-]{16,}|gh[posru]_[A-Za-z0-9]{16,}|github_pat_[A-Za-z0-9_]{20,}|AKIA[0-9A-Z]{16}|AIza[0-9A-Za-z_-]{35}|npm_[A-Za-z0-9]{36}|hf_[A-Za-z0-9]{30,}|xox[baprs]-[A-Za-z0-9-]{10,})${B_RIGHT}`,
|
|
111
111
|
"g"
|
|
112
112
|
);
|
|
113
113
|
JWT_PATTERN = new RegExp(
|
|
@@ -1761,9 +1761,9 @@ function formatErrorWithCause(err) {
|
|
|
1761
1761
|
function isPrivateIp(ip) {
|
|
1762
1762
|
const parts = ip.split(".").map(Number);
|
|
1763
1763
|
if (parts.length !== 4 || parts.some((p) => isNaN(p))) return false;
|
|
1764
|
-
const [a, b] = parts;
|
|
1764
|
+
const [a, b, c] = parts;
|
|
1765
1765
|
if (a === void 0 || b === void 0) return false;
|
|
1766
|
-
return a === 0 || a === 10 || a === 127 || a === 100 && b >= 64 && b <= 127 || a === 169 && b === 254 || a === 172 && b >= 16 && b <= 31 || a === 192 && b === 168 || a >= 224;
|
|
1766
|
+
return a === 0 || a === 10 || a === 127 || a === 100 && b >= 64 && b <= 127 || a === 169 && b === 254 || a === 172 && b >= 16 && b <= 31 || a === 192 && b === 168 || a === 198 && (b === 18 || b === 19) || a === 192 && b === 0 && (c === 0 || c === 2) || a === 198 && b === 51 && c === 100 || a === 203 && b === 0 && c === 113 || a >= 224;
|
|
1767
1767
|
}
|
|
1768
1768
|
function isPrivateIpv6(ip) {
|
|
1769
1769
|
const normalized = ip.toLowerCase().replace(/^\[|\]$/g, "");
|
|
@@ -3038,9 +3038,9 @@ async function initBrowser() {
|
|
|
3038
3038
|
logToDebugFile3("INFO", `[Worker-${workerId3}] Initializing browser instance...`);
|
|
3039
3039
|
let CamoufoxModule;
|
|
3040
3040
|
try {
|
|
3041
|
-
CamoufoxModule = await import("camoufox
|
|
3041
|
+
CamoufoxModule = await import("@camoufox/camoufox");
|
|
3042
3042
|
} catch (e) {
|
|
3043
|
-
throw new Error(`[Worker] camoufox
|
|
3043
|
+
throw new Error(`[Worker] @camoufox/camoufox not found in node_modules. Please run 'npm install'. Original error: ${e instanceof Error ? e.message : String(e)}`, { cause: e });
|
|
3044
3044
|
}
|
|
3045
3045
|
const { Camoufox } = CamoufoxModule;
|
|
3046
3046
|
const launchTimeoutMs = BROWSER_LAUNCH_TIMEOUT_MS;
|
|
@@ -3146,7 +3146,7 @@ async function initBrowser() {
|
|
|
3146
3146
|
browser = null;
|
|
3147
3147
|
const msg = e instanceof Error ? e.message : String(e);
|
|
3148
3148
|
if (msg.includes("Camoufox is not installed") || msg.includes("Version information not found")) {
|
|
3149
|
-
throw new Error(`[Worker] Browser binaries not found. Please run 'npx camoufox
|
|
3149
|
+
throw new Error(`[Worker] Browser binaries not found. Please run 'npx camoufox fetch' to install them.`, { cause: e });
|
|
3150
3150
|
}
|
|
3151
3151
|
const errName = e instanceof Error ? e.constructor?.name ?? "" : "";
|
|
3152
3152
|
if (errName === "CannotFindXvfb" || errName === "CannotExecuteXvfb" || msg.includes("Xvfb") || msg.includes("virtual display")) {
|
package/docs/AGENT-SKILL.md
CHANGED
|
@@ -22,9 +22,9 @@ pi-research skill install # link the skill into every detected ag
|
|
|
22
22
|
```
|
|
23
23
|
|
|
24
24
|
On npm ≥11.19 (and npm 12) dependency install scripts are skipped by default — and
|
|
25
|
-
none are needed:
|
|
26
|
-
stealth browser self-provisions on its first use (the first
|
|
27
|
-
minutes). No approval is required (see the [README](../README.md#install)).
|
|
25
|
+
none are needed: the only native piece on the launch path is `impit`, which ships
|
|
26
|
+
prebuilt binaries, and the stealth browser self-provisions on its first use (the first
|
|
27
|
+
scrape takes a few minutes). No approval is required (see the [README](../README.md#install)).
|
|
28
28
|
|
|
29
29
|
The global install also brings the `@earendil-works/pi-*` host packages in as peer
|
|
30
30
|
dependencies (npm ≥7 resolves them). If your install skips peers
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -308,43 +308,53 @@ directory".
|
|
|
308
308
|
Worker pool over direct browser — browser processes are isolated in workers so a crash
|
|
309
309
|
in one cannot affect the orchestrator or other sessions.
|
|
310
310
|
|
|
311
|
-
Pinned browser stack —
|
|
312
|
-
`camoufox-js` is pinned to its `0.12.0` line; the three are coupled and upgraded together,
|
|
311
|
+
Pinned browser stack — the three browser packages are coupled and upgraded together,
|
|
313
312
|
because each floating range broke fresh consumer installs that our lockfile masked.
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
exact pin is the only way to force a version downstream;
|
|
320
|
-
preinstall-guard incident (0.13.1/0.14.0, dropped in 0.14.1) is
|
|
321
|
-
not trusted here. Rationale in full:
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
313
|
+
`@camoufox/camoufox` is pinned to its `0.5` line (`^0.5.7`), `playwright-core` is exact at
|
|
314
|
+
`1.62.1` and `impit` exact at `0.14.5`. The playwright pin follows the launcher's declared
|
|
315
|
+
peer: `@camoufox/camoufox` declares
|
|
316
|
+
`peerDependencies: { "playwright-core": "<1.63" }` (`1.60.0` was the old `camoufox-js`
|
|
317
|
+
bound, which capped `<1.61.0`). `impit` stays exact because npm `overrides` do not
|
|
318
|
+
propagate to consumers, so an exact pin is the only way to force a version downstream;
|
|
319
|
+
impit's `only-allow pnpm` preinstall-guard incident (0.13.1/0.14.0, dropped in 0.14.1) is
|
|
320
|
+
why floating ranges are not trusted here. Rationale in full:
|
|
321
|
+
`src/infrastructure/browser/thread-worker-browser.ts`.
|
|
322
|
+
|
|
323
|
+
The launcher replacement (2026-10-05). `camoufox-js` `0.12.0` was replaced by
|
|
324
|
+
`@camoufox/camoufox` `0.5.7` after the former broke every fresh install. On 2026-10-03
|
|
325
|
+
`v156.0.1-beta.34` was published to the `daijro/camoufox` releases WITHOUT the prerelease
|
|
326
|
+
flag, and the 156-series browser schema had dropped `navigator.product` (with
|
|
327
|
+
`appName`/`appCodeName`). `camoufox-js` `0.12.0` still sent those properties, and its
|
|
328
|
+
`fetch` takes no version argument — it walks the releases newest-first and takes the first
|
|
329
|
+
NON-PRERELEASE asset for this OS/arch. Every install after 2026-10-03 therefore fetched
|
|
330
|
+
the 156 build and died on launch with `UnknownProperty: Unknown property
|
|
331
|
+
navigator.product in config`, while machines holding an older cached browser kept working:
|
|
332
|
+
which is why CI (a fresh cache) went red while local runs stayed green. There was no pin to
|
|
333
|
+
turn — the library had no version argument and no environment variable for the browser.
|
|
334
|
+
|
|
335
|
+
`@camoufox/camoufox` fixes that structurally: every published copy is stamped with the one
|
|
336
|
+
browser build compiled from the same sources (`browser-pin.json`; 0.5.7 pins
|
|
337
|
+
`v156.0.1-beta.34`), and it fetches and launches exactly that build by default. The two
|
|
338
|
+
halves of the stack are released together, so a schema change cannot reach a launcher that
|
|
339
|
+
does not understand it. The browser BINARY is PINNED now, where the old stack left it
|
|
340
|
+
floating, and the practical consequence runs the other way: a stale `@camoufox/camoufox`
|
|
341
|
+
means a stale Firefox, and the browser only moves when this dependency does.
|
|
342
|
+
|
|
343
|
+
The extra install layer this adds: `@camoufox/camoufox` installs under
|
|
344
|
+
`<INSTALL_DIR>/browsers/<repo>/<version>/` (multi-version, with `config.json`,
|
|
345
|
+
`repo_cache.json` and a `.0.5_FLAG` above it) where `camoufox-js` laid the browser flat
|
|
346
|
+
with a root `version.json`, and it derives `INSTALL_DIR` only from the platform cache
|
|
347
|
+
directory — it reads neither `CAMOUFOX_INSTALL_DIR` nor `PLAYWRIGHT_BROWSERS_PATH`.
|
|
348
|
+
`src/infrastructure/browser/camoufox-layout.ts` (install/uninstall twin:
|
|
349
|
+
`scripts/camoufox-layout.cjs`, both driven by the same fixtures in
|
|
350
|
+
`test/unit/infrastructure/camoufox-layout.test.ts`) is the single resolver for that
|
|
351
|
+
location and for the override the launcher does read (`XDG_CACHE_HOME` on Linux,
|
|
352
|
+
`LOCALAPPDATA` on Windows); it also recognises a legacy flat install, which matters
|
|
353
|
+
because `camoufox fetch` runs `rm -rf INSTALL_DIR` over a directory it does not recognise.
|
|
354
|
+
`@camoufox/camoufox` has no `better-sqlite3` dependency (the native surface on the launch
|
|
355
|
+
path is now only `impit`), so the old npm-install-script blocker on this stack is gone.
|
|
356
|
+
Re-verify a real launch when bumping it — the unit and integration suites mock the browser
|
|
357
|
+
and cannot catch a Juggler mismatch.
|
|
348
358
|
|
|
349
359
|
Pinned data stack — `apache-arrow` is a direct dependency at `21.1.0`, and `overrides`
|
|
350
360
|
forces the whole tree to that single version so LanceDB and Arrow share one Arrow instance
|
|
@@ -370,20 +380,24 @@ through 0.39 declares the same
|
|
|
370
380
|
`<=18.1.0` Arrow ceiling, so upgrading LanceDB does not resolve the override; it only
|
|
371
381
|
changes which pairing needs re-validating.
|
|
372
382
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
383
|
+
Validation library — `typebox` (TypeBox 1.x, unscoped package name) is a PEER dependency
|
|
384
|
+
(`>=1.3.27 <2`) and an exact `1.3.27` devDependency. It is host-provided: pi's extension loader
|
|
385
|
+
warns on every startup when a host-provided package (`typebox`, `@sinclair/typebox`, the
|
|
386
|
+
`@earendil-works/pi-*` packages) sits in `dependencies`, because an installed copy can bypass the
|
|
387
|
+
loader and create a second live module instance (`resource-loader.js`,
|
|
388
|
+
`collectExtensionPackageWarnings`; pi `docs/packages.md`). Under pi the host's own copy is used,
|
|
389
|
+
so the two agree on `Value.Check`/`Convert` by construction. `@earendil-works/pi-ai` and
|
|
390
|
+
`@earendil-works/pi-coding-agent` 1.0.0 through 1.0.3 all pin `1.3.27` (re-checked 2026-10-05 in
|
|
391
|
+
the installed packages' `package.json`), which is why the devDependency, and so every test run and
|
|
392
|
+
the type-check, stays on exactly that version: bump it in lockstep with the pi host, not
|
|
393
|
+
independently. A standalone CLI/SDK install resolves the peer automatically on npm >= 7; the
|
|
394
|
+
`pi-research` bin preflights it with the pi packages and exits 78 with the remedy when a
|
|
395
|
+
peer-skipping install lacks it. The range is bounded below 2 on purpose (the pi packages use
|
|
396
|
+
`>=0.99.0 <2` for the same reason) rather than pi's suggested `"*"`, so a standalone install cannot
|
|
397
|
+
silently pick up a future major. Known trade-off: on a standalone install the peer resolves to the newest 1.x (1.3.35 on 2026-10-05, measured by installing the packed tarball) while the pi packages nest their own exact `1.3.27`, so two TypeBox copies coexist there; under pi only the host's copy exists. Every tool's parameter schema is built with TypeBox here and
|
|
398
|
+
handed across the boundary to pi's tool system. (`undici`, by contrast, tracks the host's major —
|
|
399
|
+
the host is on undici 8, and pi-research only uses the stable `Agent` connector API, so it follows
|
|
400
|
+
`^8`.)
|
|
387
401
|
|
|
388
402
|
Pinned embedding runtime — `@huggingface/transformers` is exact at `4.3.0`. The hold at `4.2.0`
|
|
389
403
|
was lifted on 2026-10-01 for a security reason, not a feature one: `4.2.0` declares
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,27 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.7.9] - 2026-10-05
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- **The browser launcher moves from `camoufox-js` 0.12.0 to `@camoufox/camoufox` 0.5.7, and the browser build is now pinned.** This fixes the CI break that made every new PR red from 2026-10-03 and the fresh-install break behind it. `camoufox-js` took "the newest non-prerelease GitHub release", so when upstream flagged `v156.0.1-beta.34` non-prerelease (its neighbours `.33`/`.35` are prereleases) every fresh install got a browser whose schema dropped `navigator.product`, and every launch threw `UnknownProperty: navigator.product` (all three `integration-test` jobs; machines with an older cached browser, including the reporter's, never noticed). The new launcher ships `dist/data-files/browser-pin.json` naming the one build it was released and tested with and fetches exactly that, so a pi-research release moves the browser deliberately instead of on upstream's release timing. It is also **MIT** (camoufox-js was MPL-2.0), has **no `better-sqlite3`** (the native build that used to break toolchain-less installs), and adds multiversion support (`camoufox fetch <version>`, `set`, `list`, `remove`). `playwright-core` moves 1.60.0 → 1.62.1, inside the new package's `peerDependencies: "<1.63"`. **Verified by a real headless launch on 2026-10-05**: the pinned `156.0.1-beta.34` browser launched under `playwright-core` 1.62.1, loaded `https://example.com` and reported the expected `navigator` values (`product=Gecko`, `appName=Netscape`). The `ua-parser-js` 1.x override is kept (MIT, vs 2.x's AGPL-3.0-or-later) and was exercised by that same launch; see `docs/THIRD-PARTY-NOTICES.md`.
|
|
13
|
+
- **Install/update/uninstall no longer leaves dead browsers behind.** `@camoufox/camoufox` installs to `<cache>/camoufox/browsers/<repo>/<version>/` (the old layout was flat in that same directory) and never removes a superseded build, so a version bump used to leave a multi-GB browser nothing would ever launch. `src/infrastructure/browser/camoufox-layout.ts` (twinned with `scripts/camoufox-layout.cjs`, kept equivalent by `test/unit/infrastructure/camoufox-layout.test.ts`) is now the single source of truth for location and detection: `setup.cjs` detects the new layout rather than bare directory existence, stashes a legacy flat install aside and only removes it once the new build is in place (the upstream fetch runs `rm -rf` on a directory without its `.0.5_FLAG` BEFORE downloading, so a naive upgrade could destroy a working browser and leave none), prunes superseded versions on upgrade, and `cleanup.cjs` purges every installed build plus the legacy install and any crashed-upgrade stash under an ownership guard. A custom `CAMOUFOX_INSTALL_DIR`/`PLAYWRIGHT_BROWSERS_PATH` is translated into the variable the launcher actually reads (`XDG_CACHE_HOME`/`LOCALAPPDATA`) instead of being silently ignored, and on macOS, where the launcher cannot be relocated, the user is told rather than left with a setting that does nothing. `scripts/verify-package.cjs` gained `verifyLocalRequiresShipped`, which fails the publish gate if a shipped script requires an unshipped local file (the class of bug that would have shipped a `setup.cjs` unable to resolve `camoufox-layout.cjs`).
|
|
14
|
+
- **A provider's in-flight-budget 402 now waits instead of burning the retry budget.** OpenRouter refuses with `in_flight_budget_exhausted` and `Retry-After: 120` when an account's own requests are still open. That is transient and must stay retriable, but the researcher loop's exponential backoff is capped at `PI_RESEARCH_RETRY_DELAY_MS` (default 2000ms), so three attempts could never outlast the window: the run failed and the round degraded to a raw-compilation synthesis. The loop now recognizes the condition, honors the provider's `Retry-After` (clamped to 5-60s; 15s when absent) for the next attempt, and leaves the spent-balance class (`insufficient credits`) stopping immediately as before. Helpers and tests: `test/unit/orchestration/researcher-inflight-budget.test.ts`.
|
|
15
|
+
- **SSRF: three more reserved IPv4 ranges are blocked** — `198.18.0.0/15` (RFC 2544 benchmarking), `192.0.0.0/24` (RFC 6890 IETF protocol assignments) and the TEST-NET-1/2/3 documentation ranges `192.0.2.0/24`, `198.51.100.0/24`, `203.0.113.0/24`. Literal-screen tests (including the public neighbours of each range, so the guard cannot silently over-block) are in `test/unit/web-research/private-ip-ranges.test.ts`.
|
|
16
|
+
|
|
17
|
+
- **`typebox` moves from `dependencies` to `peerDependencies` (`>=1.3.27 <2`), with an exact `1.3.27` devDependency.** pi 1.x warns on every startup that host-provided packages must be peer dependencies and that an installed copy "can bypass the extension loader and create duplicate runtime modules" (`collectExtensionPackageWarnings` in pi's `resource-loader.js`); `typebox` is on that list and was the one package left behind when the `@earendil-works/*` trio moved in 1.7.3. The range is bounded below 2 instead of pi's suggested `"*"`, matching the trio. Credit: the proposal in PR #20 (lukey03). The lockfile here is regenerated cleanly (PR #20's lockfile also added `"peer": true` to unrelated packages).
|
|
18
|
+
- **The `pi-research` bin shim also preflights `typebox`.** `dist/cli.mjs` imports it directly, so a peer-skipping install (`--legacy-peer-deps`, yarn classic, pnpm `auto-install-peers=false`) that lacks it would otherwise die with a raw `ERR_MODULE_NOT_FOUND`. It now exits 78 with the remedy, like the pi packages. New test: `also guards typebox` in `test/unit/cli-bin.test.ts`.
|
|
19
|
+
- **Dev dependency refresh to pi 1.0.3** (`@earendil-works/pi-ai`, `pi-coding-agent`, `pi-tui`, plus the new `pi-agent-core`, `pi-codemode`, `pi-mcp`, `chord` and `quickjs-wasi` they pull in). This clears the one `npm audit` finding: pi 1.0.0 shipped an `npm-shrinkwrap.json` pinning the vulnerable `brace-expansion` 5.0.9 (GHSA-q2hr-2g5m-vwhr, GHSA-qhr7-859c-m2p7, GHSA-6j4f-fj2g-mc7p); pi 1.0.1 removed the shrinkwrap and pins 5.0.12. The lockfile drops 134 shrinkwrap-nested packages. `npm audit`: 0 vulnerabilities. Type-checks, lint and the full unit suite pass against 1.0.3. The public surface this package uses (extension API, tool `annotations` and `namespace`) is unchanged in 1.0.3, and the tested-ceiling check compares major.minor only, so 1.0.x raises no host notice and `PI_TESTED_MAX_VERSION` stays `1.0.0`. pi 1.0.4 landed the same day and the dev dependency and lock moved to it in-range: its public surface is additive (the MCP tool-name matcher and the resource-tool constants), and type-check (TypeScript 6 and 7), lint, `npm audit` (0) and the full unit suite (3303) pass against it.
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- **A Camoufox fetch that fails after the browser itself is installed no longer throws away a working browser.** The launcher extracts the pinned build and writes its `.0.5_FLAG` BEFORE it fetches its companion geoip database from a separate GitHub release, so a failure in that second download exits non-zero over a complete, launchable install. `provisionBrowser` treated any non-zero exit as "no browser": it restored the legacy stash on top of the new build, and `setup.cjs` printed "Camoufox browser install failed — pi-research will not work" (exit 1 under `PI_RESEARCH_STRICT_SETUP`, which turned `integration-test (ubuntu-latest)` red on three consecutive CI runs on 2026-10-05 with `UND_ERR_SOCKET other side closed`, while the same job passed on macOS and Windows). It now keeps the installed build when the paired version is usable, discards the legacy stash, and logs the companion-download remedy. Verified that a real headless launch succeeds with the mmdb removed. New cases in `camoufox-layout.test.ts` (both twins) and `browser-lifecycle.test.ts` (the real `setup.cjs`, including the strict-mode exit 0 CI relies on).
|
|
24
|
+
- **Install docs no longer name `better-sqlite3` as a dependency.** The 2026-10-05 launcher move removed it from the tree and lockfile entirely, so the "no install scripts are needed because better-sqlite3 13 ships prebuilt bindings" explanation in `docs/AGENT-SKILL.md`, `docs/SDK.md`, the skill README and the three `DOCUMENTATION-*` translations was describing a package that is no longer installed. It now gives the real reason — the only native piece on the launch path is `impit`, which ships prebuilt binaries — and keeps the `npm approve-scripts better-sqlite3` + `npm rebuild` remedy as historical context for releases before the launcher swap.
|
|
25
|
+
- **Log redaction masks three more bare credential formats.** A Google API key (`AIza` + 35 characters), an npm automation token (`npm_` + 36) and a Hugging Face token (`hf_` + 30 or more) were masked only when they followed a `key=` style name; appearing alone in free text they were logged in clear. They join the known-token pattern in `src/utils/log-utils.ts`, with assertions in `test/unit/utils/log-redaction.test.ts`.
|
|
26
|
+
- **`docs/AUDIT-GATE.md` consumer table re-measured (2026-10-05).** Packed tarball installed into scratch projects: 4 HIGH (one `sharp` 0.33.5 chain via `@lancedb/lancedb`) on both the plain and the `--legacy-peer-deps` shape, 0 with a consumer `sharp` override. The earlier 7 / 4 / 1 / 0 table had two rows that no longer exist (`adm-zip`, and the host-shrinkwrap `brace-expansion`, fixed at the source by pi 1.0.1).
|
|
27
|
+
- In-range refresh: `jsdom` 30.1.1 → 30.1.2, `vite` 8.3.1 → 8.3.2, `sharp` 0.35.4 → 0.35.5 (the `^0.35.0` override; the first release clear of the libvips/libheif advisories) and `webgpu` 0.6.1 → 0.6.2 (the WebGPU adapter probe's Dawn binding; verified on a real GPU, `PROBE_OK 384`). `npm audit` stays at 0.
|
|
28
|
+
|
|
8
29
|
## [1.7.8] - 2026-10-01
|
|
9
30
|
|
|
10
31
|
### Fixed
|
package/docs/CONFIGURATION.md
CHANGED
|
@@ -169,8 +169,8 @@ Diagnostics & platform
|
|
|
169
169
|
| `PI_RESEARCH_SKILL_DIR` | _(auto)_ | Override the bundled research-skill source directory used by the skill installer. |
|
|
170
170
|
| `PI_RESEARCH_PURGE_BROWSERS` | _(unset)_ | Read by the bundled `scripts/cleanup.cjs`: set `1` to also delete the shared camoufox browser cache (kept by default because other installs may use it). Note npm ≥7 does not run `preuninstall`, so that script does not fire on `npm uninstall` — see [AGENT-SKILL.md](AGENT-SKILL.md). |
|
|
171
171
|
| `PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD` | _(unset)_ | Set `1` during `npm install` to skip the camoufox browser download (fetched lazily on first use instead; standard Playwright convention). |
|
|
172
|
-
| `CAMOUFOX_INSTALL_DIR` | _(user cache)_ |
|
|
173
|
-
| `PLAYWRIGHT_BROWSERS_PATH` | _(user cache)_ | Alias for
|
|
172
|
+
| `CAMOUFOX_INSTALL_DIR` | _(user cache)_ | Relocates the browser download. Honoured by pi-research, not by the launcher: `@camoufox/camoufox` reads only the platform cache variable, so pi-research maps this value onto it — `XDG_CACHE_HOME` on Linux, `LOCALAPPDATA` on Windows — and exports that to the postinstall fetch and to browser workers, so install and lookup cannot drift. Ignored on macOS, where the launcher derives its cache from `$HOME`; pi-research prints a note there. See ARCHITECTURE.md. |
|
|
173
|
+
| `PLAYWRIGHT_BROWSERS_PATH` | _(user cache)_ | Alias for `CAMOUFOX_INSTALL_DIR`, accepted for compatibility. |
|
|
174
174
|
| `XDG_CACHE_HOME` | `~/.cache` | Standard XDG variable. When set, every `~/.cache/pi-research/...` path below is rooted at `$XDG_CACHE_HOME/pi-research/...` instead. |
|
|
175
175
|
| `PI_RESEARCH_BIN` (alias `PI_RESEARCH_PATH`) | _(auto)_ | Agent-skill launcher only: explicit path to the pi-research engine binary when auto-resolution (PATH → local install → npx) should be bypassed. See [agent-skill/pi-research/references/configuration.md](../agent-skill/pi-research/references/configuration.md). |
|
|
176
176
|
| `PLAYWRIGHT_INSTALL_DEPS` | _(unset)_ | Linux only. Set `true` during `npm install` to also install system libraries via `npx playwright install-deps` (same as `npm run install:system-deps`). |
|
package/docs/SDK.md
CHANGED
|
@@ -22,12 +22,13 @@ npm install @earendil-works/pi-coding-agent
|
|
|
22
22
|
```
|
|
23
23
|
|
|
24
24
|
On npm ≥11.19 (and npm 12), dependency install scripts are skipped by default. Nothing
|
|
25
|
-
here needs them:
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
install script —
|
|
30
|
-
make a skipped script run
|
|
25
|
+
here needs them: the only native piece on the launch path is `impit`, which ships
|
|
26
|
+
prebuilt binaries, and the stealth browser self-provisions on its first use. (The
|
|
27
|
+
`npm approve-scripts better-sqlite3` + `npm rebuild` pair documented by earlier
|
|
28
|
+
releases repaired the old `camoufox-js` launcher, whose `better-sqlite3` binding came
|
|
29
|
+
from an install script — the 2026-10-05 move to `@camoufox/camoufox` removed that
|
|
30
|
+
dependency entirely, and on npm 12.0.2 an approval does not make a skipped script run
|
|
31
|
+
anyway.)
|
|
31
32
|
|
|
32
33
|
Then pick the model: pass `model` to `initResearchSDK`, or set `PI_RESEARCH_MODEL`
|
|
33
34
|
(env or `~/.pi/research/config.env`). The SDK never follows the model selected
|
|
@@ -12,12 +12,12 @@ first-party sources, so no third-party code is inlined).
|
|
|
12
12
|
|
|
13
13
|
### Notable dependency licensing
|
|
14
14
|
|
|
15
|
-
camoufox
|
|
15
|
+
@camoufox/camoufox / Camoufox browser
|
|
16
16
|
|
|
17
|
-
The
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
The `@camoufox/camoufox` npm package itself is licensed under **MIT**. It is the
|
|
18
|
+
launcher that replaced `camoufox-js` 0.12.0 (MPL-2.0) in the current development line.
|
|
19
|
+
It is resolved at install time and **not bundled** into this package's artifacts (the
|
|
20
|
+
bundled entry points are built `--packages=external`). It is used in-process only to
|
|
21
21
|
configure and launch the Camoufox (Firefox-fork) browser **binary as a separate
|
|
22
22
|
operating-system process**, which this package then drives over the Playwright/Juggler
|
|
23
23
|
protocol. The Camoufox binary is downloaded and run separately and is subject to its
|
|
@@ -29,8 +29,12 @@ ua-parser-js
|
|
|
29
29
|
package free of AGPL-licensed code in its dependency tree, `package.json`
|
|
30
30
|
`overrides` pins `ua-parser-js` to the `1.x` line, which is MIT-licensed. The
|
|
31
31
|
1.x and 2.x APIs are compatible for the only surface our direct dependency
|
|
32
|
-
(
|
|
33
|
-
(
|
|
32
|
+
(`@camoufox/camoufox`, which declares `^2.0.2`) uses — it calls just
|
|
33
|
+
`new UAParser(ua).getBrowser().name` and `.getOS().name`, both present in 1.x and
|
|
34
|
+
verified against the pinned `1.0.41` — and the pin is behavior-neutral for this
|
|
35
|
+
package's usage (no custom `navigator.userAgent`/`fingerprint` is passed to Camoufox).
|
|
36
|
+
Re-check that surface on every `@camoufox/camoufox` bump: a 2.x-only call would make
|
|
37
|
+
this override a runtime break, not just a licensing choice.
|
|
34
38
|
|
|
35
39
|
youtubei.js / bgutils-js / jsdom (YouTube transcripts)
|
|
36
40
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lincoln504/pi-research",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.9",
|
|
4
4
|
"description": "Web research for your agents with smart and safe tooling + knowledge store",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"docs/ARCHITECTURE.md",
|
|
36
36
|
"scripts/setup.cjs",
|
|
37
37
|
"scripts/cleanup.cjs",
|
|
38
|
+
"scripts/camoufox-layout.cjs",
|
|
38
39
|
"scripts/build.cjs",
|
|
39
40
|
"scripts/prepare.cjs",
|
|
40
41
|
"LICENSE",
|
|
@@ -103,11 +104,13 @@
|
|
|
103
104
|
"cleanup": "node scripts/cleanup.cjs",
|
|
104
105
|
"setup": "node scripts/setup.cjs",
|
|
105
106
|
"install:system-deps": "node scripts/setup.cjs --system-deps",
|
|
107
|
+
"//deps:check": "dependency-cruiser 18.5 refuses Node 25 (supports ^22 || ^24 || >=26) while engines allows >=22.22.2: run this script under Node 22 or 24 (see .nvmrc).",
|
|
106
108
|
"deps:check": "depcruise --config config/tooling/dependency-cruiser.cjs --output-type err-long src",
|
|
107
109
|
"deps:generate": "npx --yes madge@8.0.0 --image docs/deps.svg src/index.ts",
|
|
108
110
|
"verify:changelog": "node scripts/verify-changelog.cjs",
|
|
109
111
|
"analyze:dependencies": "ncu",
|
|
110
|
-
"analyze:compatibility": "depngn"
|
|
112
|
+
"//analyze:compatibility": "depngn needs a node-version argument and a TTY (it calls stdout.clearLine): in CI or a pipe run it as: script -qec \"npx depngn 22.22.2\" /dev/null. Many entries report n/a (it cannot read engines for packages without the field).",
|
|
113
|
+
"analyze:compatibility": "depngn 22.22.2"
|
|
111
114
|
},
|
|
112
115
|
"pi": {
|
|
113
116
|
"extensions": [
|
|
@@ -120,32 +123,30 @@
|
|
|
120
123
|
"@lancedb/lancedb": "0.39.0",
|
|
121
124
|
"apache-arrow": "21.1.0",
|
|
122
125
|
"bgutils-js": "^4.0.3",
|
|
123
|
-
"camoufox
|
|
126
|
+
"@camoufox/camoufox": "^0.5.7",
|
|
124
127
|
"esbuild": "^0.28.2",
|
|
125
128
|
"impit": "0.14.5",
|
|
126
129
|
"jsdom": "^30.1.0",
|
|
127
130
|
"node-html-markdown": "^2.0.0",
|
|
128
131
|
"pdf-oxide-wasm": "^0.3.77",
|
|
129
|
-
"playwright-core": "1.
|
|
132
|
+
"playwright-core": "1.62.1",
|
|
130
133
|
"poolifier": "^5.3.2",
|
|
131
|
-
"typebox": "1.3.27",
|
|
132
134
|
"undici": "^8.11.2",
|
|
133
135
|
"youtubei.js": "^18.0.0"
|
|
134
136
|
},
|
|
135
137
|
"peerDependencies": {
|
|
136
138
|
"@earendil-works/pi-ai": ">=0.99.0 <2",
|
|
137
139
|
"@earendil-works/pi-coding-agent": ">=0.99.0 <2",
|
|
138
|
-
"@earendil-works/pi-tui": ">=0.99.0 <2"
|
|
140
|
+
"@earendil-works/pi-tui": ">=0.99.0 <2",
|
|
141
|
+
"typebox": ">=1.3.27 <2"
|
|
139
142
|
},
|
|
140
143
|
"optionalDependencies": {
|
|
141
144
|
"@huggingface/transformers": "4.3.0",
|
|
142
145
|
"webgpu": "^0.6.0"
|
|
143
146
|
},
|
|
144
147
|
"overrides": {
|
|
145
|
-
"lodash.isequal": "npm:fast-deep-equal@^3.1.3",
|
|
146
148
|
"brace-expansion": "^5.0.12",
|
|
147
149
|
"fast-uri": "^3.1.8",
|
|
148
|
-
"ip-address": "^10.2.0",
|
|
149
150
|
"apache-arrow": "21.1.0",
|
|
150
151
|
"onnxruntime-web": "1.24.3",
|
|
151
152
|
"node-domexception": "npm:@nolyfill/domexception@^1.0.28",
|
|
@@ -171,6 +172,7 @@
|
|
|
171
172
|
"depngn": "^0.6.0",
|
|
172
173
|
"eslint": "10.11.0",
|
|
173
174
|
"npm-check-updates": "^23.1.0",
|
|
175
|
+
"typebox": "1.3.27",
|
|
174
176
|
"typescript": ">=6.0.3 <6.1.0",
|
|
175
177
|
"vite": "^8.3.1",
|
|
176
178
|
"vitest": "^5.0.3"
|