@lincoln504/pi-research 1.3.2 → 1.3.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/dist/cli.mjs CHANGED
@@ -3565,7 +3565,7 @@ async function buildModelRegistry(apiKey, provider) {
3565
3565
  allowModelNetwork: false
3566
3566
  });
3567
3567
  if (apiKey && provider) {
3568
- await runtime.setRuntimeApiKey(provider, apiKey, { allowNetwork: false });
3568
+ await runtime.setRuntimeApiKey(provider, apiKey);
3569
3569
  }
3570
3570
  const registry = new ModelRegistry(runtime);
3571
3571
  registryRuntimes.set(registry, runtime);
package/docs/CHANGELOG.md CHANGED
@@ -5,6 +5,29 @@ 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.3.3] - 2026-08-07
9
+
10
+ pi 0.84.1 compatibility. Triggered by updating the local `pi` install and
11
+ auditing `@earendil-works/pi-coding-agent`'s CHANGELOG in full — not just
12
+ grepped — from 0.84.1 back through 0.79.2 (the full range since this
13
+ package's own last-tested line, plus further back for context) for anything
14
+ that requires a fix or is worth adopting.
15
+
16
+ ### Fixed
17
+
18
+ - **`ModelRuntime.setRuntimeApiKey()`'s `allowNetwork` option was removed in pi 0.84.0.** `buildModelRegistry`'s explicit-API-key path passed `{ allowNetwork: false }` to prevent a live model-catalog network connection from hanging indefinitely in network-restricted environments (verified previously). 0.84.0 narrowed `setRuntimeApiKey`'s own options to just `{ signal? }` — but its internal `synchronizeCredentialState()` now hardcodes that same `allowNetwork: false` unconditionally on every call, confirmed by reading pi-coding-agent's `model-runtime.js` directly rather than trusting the changelog prose alone. The now-invalid option is removed from the call; the behavior it protected is preserved by pi itself.
19
+ - **`getApiKeyAndHeaders()`'s returned headers can now legitimately be `null`-valued.** pi 0.84.0 widened `ProviderHeaders` to `Record<string, string | null>` (`null` suppresses a provider/API default header with that name) — pi-research's own structural mirror of the auth-result type (kept separate from importing the real pi-coding-agent type, so a host version skew can't break the build) still declared `Record<string, string>`, which both fails to compile against 0.84.x's real type and would have mishandled a `null` header value. Widened at the one source type and its three downstream consumers (`agentic-repair.ts`, `research-knowledge-search.ts`); the `null` values flow through to `completeSimple()`'s own `SimpleStreamOptions.headers`, which already documents and handles them.
20
+
21
+ ### Changed
22
+
23
+ - Raised the minimum supported pi version from 0.80.8 to 0.84.0 (`PI_MIN_VERSION` in `src/core/pi-version.ts`, and the `@earendil-works/pi-ai`/`pi-coding-agent`/`pi-tui` dependency floors in package.json) — the `setRuntimeApiKey` fix above only holds on 0.84.0+; an already-resolved older host would silently lose the network-hang protection. Bumped `PI_TESTED_MAX_VERSION` to 0.84.1 (actually installed and exercised: full unit + integration suite, including live SDK lifecycle tests against the real `ModelRuntime`).
24
+ - Cleared three now-resolved `npm audit` exceptions (two `brace-expansion` GHSAs, one location-scoped `undici` exception) from `config/tooling/audit-exceptions.json`: pi-coding-agent@0.84.1's `npm-shrinkwrap.json` now pins `brace-expansion@5.0.9` and `undici@8.9.0`, the exact versions each exception's own `clearsWhen` condition named — verified directly against the installed shrinkwrap, not assumed. The `sharp` (libvips) exception remains; it is unrelated to this pi bump and still unfixed upstream in `@huggingface/transformers`.
25
+
26
+ Patch, not minor: matches this project's established precedent for pi-floor
27
+ compatibility bumps (1.0.9, 1.0.10) — raising the floor changes which HOST/
28
+ dependency versions are supported, not pi-research's own CLI, tool, or SDK
29
+ contract.
30
+
8
31
  ## [1.3.2] - 2026-08-07
9
32
 
10
33
  A full-tree re-audit of 1.3.1: 10 independent reviews, each assigned a
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lincoln504/pi-research",
3
- "version": "1.3.2",
3
+ "version": "1.3.3",
4
4
  "description": "A set of web research tools (search, scrape, and others) and research agent system that uses them safely and efficiently.",
5
5
  "type": "module",
6
6
  "private": false,
@@ -111,9 +111,9 @@
111
111
  "image": "https://raw.githubusercontent.com/Lincoln504/pi-research/main/docs/media/hero.png"
112
112
  },
113
113
  "dependencies": {
114
- "@earendil-works/pi-ai": ">=0.80.8 <1",
115
- "@earendil-works/pi-coding-agent": ">=0.80.8 <1",
116
- "@earendil-works/pi-tui": ">=0.80.8 <1",
114
+ "@earendil-works/pi-ai": ">=0.84.0 <1",
115
+ "@earendil-works/pi-coding-agent": ">=0.84.0 <1",
116
+ "@earendil-works/pi-tui": ">=0.84.0 <1",
117
117
  "@huggingface/transformers": "4.2.0",
118
118
  "@kreuzberg/html-to-markdown-node": "^3.5.5",
119
119
  "@lancedb/lancedb": "0.29.0",
@@ -2,7 +2,7 @@
2
2
  name: pi-research
3
3
  description: "Multi-agent web research for any coding agent. Use for anything requiring current information from the internet — news, trends, product/service/company facts, statistics, people, places, events, APIs, library behavior, or 'what is X / how does X work' questions. Also use to search a local knowledge store of previously researched findings before doing live research. Powered by the pi-research engine (search, stealth scraping, security databases, Stack Exchange). Not for reading local files, running project commands, or analyzing this repository's own source."
4
4
  license: MIT
5
- metadata: { "author": "Lincoln Deen", "version": "1.3.2", "package": "@lincoln504/pi-research", "engine": "pi-research-sdk", "openclaw": { "requires": { "bins": ["node"] } } }
5
+ metadata: { "author": "Lincoln Deen", "version": "1.3.3", "package": "@lincoln504/pi-research", "engine": "pi-research-sdk", "openclaw": { "requires": { "bins": ["node"] } } }
6
6
  allowed-tools: Bash(node:*)
7
7
  ---
8
8
 
@@ -63,7 +63,11 @@ export type LlmCompleter = (
63
63
  export async function repairJsonWithLlm<T = any>(
64
64
  text: string,
65
65
  completer: LlmCompleter,
66
- auth: { apiKey: string; headers?: Record<string, string> },
66
+ // headers values are string | null to match pi-ai's ProviderHeaders — a null
67
+ // entry suppresses a provider/API default header with that name, and is
68
+ // forwarded to `completer`'s SimpleStreamOptions.headers unchanged, where
69
+ // pi-ai already treats it as documented.
70
+ auth: { apiKey: string; headers?: Record<string, string | null> },
67
71
  options: JsonRepairOptions
68
72
  ): Promise<T | null> {
69
73
  const { model, context, schema, serviceName = 'RepairService', signal, maxTokens = 16384, thinkingLevel = 'off' } = options;
@@ -36,9 +36,15 @@ export interface ModelRegistryLike {
36
36
  * Structural result of {@link ModelRegistryLike.getApiKeyAndHeaders}. Mirrors the
37
37
  * pi-coding-agent `ApiKeyAndHeaders` discriminated union without importing it, so
38
38
  * a host skew on the concrete type can't break our build.
39
+ *
40
+ * `headers` values are `string | null` (not just `string`) as of pi 0.84.0's
41
+ * `ProviderHeaders` type — `null` is a legitimate header-DELETION marker (e.g.
42
+ * stripping a placeholder credential before it reaches a gateway), not an
43
+ * absent value. Every consumer of `headers` below must treat `null` as "omit
44
+ * this header," not coerce it to the literal string `"null"`.
39
45
  */
40
46
  export type AuthResultLike =
41
- | { ok: true; apiKey?: string; headers?: Record<string, string> }
47
+ | { ok: true; apiKey?: string; headers?: Record<string, string | null> }
42
48
  | { ok: false; error: string };
43
49
 
44
50
  /** Safe `getAll()` — returns [] if the host registry lacks the method. */
@@ -156,12 +162,16 @@ export async function buildModelRegistry(apiKey?: string, provider?: string): Pr
156
162
  // with an explicit model (enforced in cli.ts pre-flight), so resolution never
157
163
  // falls back to "first available".
158
164
  if (apiKey && provider) {
159
- // allowNetwork:false is REQUIRED here, not just consistent with create():
160
- // setRuntimeApiKey triggers a model-catalog refresh for the newly configured
161
- // provider, and its default options open live catalog connections — verified
162
- // to hang indefinitely (no timeout at this layer) in network-restricted
163
- // environments, which would wedge every explicit-API-key pre-flight.
164
- await runtime.setRuntimeApiKey(provider, apiKey, { allowNetwork: false });
165
+ // pi 0.84.0 removed `allowNetwork` from setRuntimeApiKey's own options
166
+ // (AuthOperationOptions is now just `{ signal? }`) — but its internal
167
+ // synchronizeCredentialState() now hardcodes `refresh({ allowNetwork:
168
+ // false, ... })` unconditionally on every call, so the "no live catalog
169
+ // connection, no indefinite hang in network-restricted environments"
170
+ // guarantee this call originally needed still holds without asking for
171
+ // it. Confirmed by reading pi-coding-agent's model-runtime.js directly,
172
+ // not just the changelog prose — verify this again on the next pi bump
173
+ // before assuming it's still unconditional.
174
+ await runtime.setRuntimeApiKey(provider, apiKey);
165
175
  }
166
176
 
167
177
  // The sync facade all our resolvers consume. getAvailable()/getApiKeyAndHeaders()
@@ -61,8 +61,21 @@ export function compareVersions(a: SemverParts, b: SemverParts): number {
61
61
  * `ModelRegistry.create()`. `buildModelRegistry` calls `ModelRuntime.create()`
62
62
  * unconditionally, and `createAgentSession()` is invoked without the removed
63
63
  * `modelRegistry` option, relying on the 0.80.8+ host to build its own.
64
+ *
65
+ * 0.84.0 removed `allowNetwork` from `ModelRuntime.setRuntimeApiKey()`'s own
66
+ * options (`AuthOperationOptions` is now just `{ signal? }`) — but its
67
+ * internal `synchronizeCredentialState()` now hardcodes `refresh({
68
+ * allowNetwork: false, ... })` unconditionally on every call, so
69
+ * `buildModelRegistry`'s explicit-API-key path (model-registry-factory.ts)
70
+ * no longer passes `allowNetwork` at all, RELYING on 0.84.0+'s own
71
+ * unconditional internal guard against a live network catalog connection.
72
+ * On an already-resolved pre-0.84.0 host, `setRuntimeApiKey`'s default
73
+ * (unspecified) network behavior applies instead — reintroducing the
74
+ * indefinite-hang-in-network-restricted-environments bug that explicit
75
+ * option originally existed to prevent. The floor moved to close that gap,
76
+ * not just because the type changed.
64
77
  */
65
- export const PI_MIN_VERSION: SemverParts = { major: 0, minor: 80, patch: 8 };
78
+ export const PI_MIN_VERSION: SemverParts = { major: 0, minor: 84, patch: 0 };
66
79
 
67
80
  /**
68
81
  * Newest host line this release was actually exercised against (CI + a real run).
@@ -70,7 +83,7 @@ export const PI_MIN_VERSION: SemverParts = { major: 0, minor: 80, patch: 8 };
70
83
  * Compared on MAJOR.MINOR only: a patch bump within a tested line is not a new
71
84
  * surface, and warning on it would be noise.
72
85
  */
73
- export const PI_TESTED_MAX_VERSION: SemverParts = { major: 0, minor: 83, patch: 0 };
86
+ export const PI_TESTED_MAX_VERSION: SemverParts = { major: 0, minor: 84, patch: 1 };
74
87
 
75
88
  export type PiCompatibilityLevel = 'ok' | 'unparseable' | 'too-old' | 'untested';
76
89
 
@@ -412,7 +412,9 @@ export function isTransientSynthesisError(message: string): boolean {
412
412
  /** Exported for unit testing of the transient-retry loop. */
413
413
  export async function runBackgroundExtraction(
414
414
  model: Model<any>,
415
- auth: { apiKey: string; headers?: Record<string, string> },
415
+ // headers values are string | null (pi-ai's ProviderHeaders) — forwarded
416
+ // to completeSimple's own SimpleStreamOptions.headers unchanged.
417
+ auth: { apiKey: string; headers?: Record<string, string | null> },
416
418
  conversationHistory: string,
417
419
  queries: string[],
418
420
  referenceDocuments: string,
@@ -561,7 +563,9 @@ export async function runBackgroundExtraction(
561
563
  */
562
564
  export async function triageRelevantUrls(
563
565
  model: Model<any>,
564
- auth: { apiKey: string; headers?: Record<string, string> },
566
+ // headers values are string | null (pi-ai's ProviderHeaders) — forwarded
567
+ // to completeSimple's own SimpleStreamOptions.headers unchanged.
568
+ auth: { apiKey: string; headers?: Record<string, string | null> },
565
569
  conversationHistory: string,
566
570
  queries: string[],
567
571
  candidates: KnowledgeCandidate[],