@lincoln504/pi-research 1.7.5 → 1.7.6
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/SKILL.md +1 -1
- package/dist/cli-bin.mjs +48 -9
- package/docs/CHANGELOG.md +8 -0
- package/package.json +1 -1
- package/scripts/build.cjs +8 -0
- package/src/cli-bin.mjs +48 -9
|
@@ -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.7.
|
|
5
|
+
metadata: { "author": "Lincoln Deen", "version": "1.7.6", "package": "@lincoln504/pi-research", "engine": "pi-research-sdk", "openclaw": { "requires": { "bins": ["node"] } } }
|
|
6
6
|
allowed-tools: Bash(node:*)
|
|
7
7
|
---
|
|
8
8
|
|
package/dist/cli-bin.mjs
CHANGED
|
@@ -34,24 +34,62 @@
|
|
|
34
34
|
* the user reached for.
|
|
35
35
|
*/
|
|
36
36
|
|
|
37
|
+
import { existsSync } from 'node:fs';
|
|
37
38
|
import { fileURLToPath } from 'node:url';
|
|
38
39
|
|
|
39
40
|
const REQUIRED_PEERS = ['@earendil-works/pi-ai', '@earendil-works/pi-coding-agent'];
|
|
40
41
|
|
|
41
|
-
|
|
42
|
+
/**
|
|
43
|
+
* Probe one peer dependency.
|
|
44
|
+
*
|
|
45
|
+
* 'ok' — resolves, and the file it resolves to exists
|
|
46
|
+
* 'missing' — does not resolve at all (the --legacy-peer-deps case)
|
|
47
|
+
* 'broken' — resolves (its package.json and exports map are readable) but the
|
|
48
|
+
* file those point at is not on disk
|
|
49
|
+
*
|
|
50
|
+
* The 'broken' case is checked with existsSync rather than by importing the
|
|
51
|
+
* module. Resolving is not loading: an interrupted install, a pruned
|
|
52
|
+
* node_modules or a bad package-cache restore leaves a package that resolves
|
|
53
|
+
* perfectly and then fails to load, which would pass this preflight and die
|
|
54
|
+
* inside cli.mjs with the same raw ERR_MODULE_NOT_FOUND this shim exists to
|
|
55
|
+
* replace. Importing it here instead would work, but it runs the host
|
|
56
|
+
* package's module side effects before the CLI proper has decided to start, so
|
|
57
|
+
* the cheap existence check is the right trade.
|
|
58
|
+
*
|
|
59
|
+
* @returns {'ok' | 'missing' | 'broken'}
|
|
60
|
+
*/
|
|
61
|
+
function probePeer(name) {
|
|
62
|
+
let resolved;
|
|
42
63
|
try {
|
|
43
|
-
import.meta.resolve(name);
|
|
44
|
-
return false;
|
|
64
|
+
resolved = import.meta.resolve(name);
|
|
45
65
|
} catch {
|
|
46
|
-
return
|
|
66
|
+
return 'missing';
|
|
47
67
|
}
|
|
48
|
-
|
|
68
|
+
try {
|
|
69
|
+
return existsSync(fileURLToPath(resolved)) ? 'ok' : 'broken';
|
|
70
|
+
} catch {
|
|
71
|
+
// Resolved to something fileURLToPath cannot turn into a path (not a file:
|
|
72
|
+
// URL). It resolved, so treat it as present rather than inventing a failure.
|
|
73
|
+
return 'ok';
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const status = new Map(REQUIRED_PEERS.map((name) => [name, probePeer(name)]));
|
|
78
|
+
const missing = REQUIRED_PEERS.filter((name) => status.get(name) === 'missing');
|
|
79
|
+
const broken = REQUIRED_PEERS.filter((name) => status.get(name) === 'broken');
|
|
49
80
|
|
|
50
|
-
if (missing.length > 0) {
|
|
81
|
+
if (missing.length > 0 || broken.length > 0) {
|
|
82
|
+
// The remedy names the packages that are ACTUALLY absent. It used to hardcode
|
|
83
|
+
// `npm install -g @earendil-works/pi-coding-agent` with the comment "add just
|
|
84
|
+
// the missing host package", which was wrong whenever pi-ai was the missing
|
|
85
|
+
// one: the instruction named a package the user already had, and following it
|
|
86
|
+
// changed nothing. Reported by review 2026-10-01.
|
|
87
|
+
const needsInstall = [...missing, ...broken];
|
|
51
88
|
const lines = [
|
|
52
89
|
'',
|
|
53
90
|
'Error: pi-research cannot start — it is missing required runtime dependencies:',
|
|
54
91
|
...missing.map((name) => ` ${name}`),
|
|
92
|
+
...broken.map((name) => ` ${name} (installed, but its files are incomplete)`),
|
|
55
93
|
'',
|
|
56
94
|
'These are PEER dependencies. pi provides its own copies when it loads this',
|
|
57
95
|
'package as an extension, and npm >= 7 installs them automatically for a',
|
|
@@ -59,10 +97,11 @@ if (missing.length > 0) {
|
|
|
59
97
|
'what --legacy-peer-deps, yarn classic, and a pnpm config with',
|
|
60
98
|
'auto-install-peers=false do.',
|
|
61
99
|
'',
|
|
62
|
-
'
|
|
100
|
+
'Install the missing package(s), or reinstall this package, which resolves',
|
|
101
|
+
'them as peers:',
|
|
63
102
|
'',
|
|
64
|
-
|
|
65
|
-
' npm install -g @lincoln504/pi-research
|
|
103
|
+
` npm install -g ${needsInstall.join(' ')}`,
|
|
104
|
+
' npm install -g @lincoln504/pi-research',
|
|
66
105
|
'',
|
|
67
106
|
];
|
|
68
107
|
process.stderr.write(lines.join('\n'));
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,14 @@ 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.6] - 2026-10-01
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **The missing-peer remedy names the package that is actually missing.** The 1.7.5 shim's bullet list correctly enumerated every absent `@earendil-works/pi-*` package, but the command underneath it was hardcoded to `npm install -g @earendil-works/pi-coding-agent` with the comment "add just the missing host package". When `pi-ai` (and not `pi-coding-agent`) was the absent one, the instruction named a package the user already had and following it changed nothing. The remedy is now built from the detected set, so both peers are named when both are missing and only the absent one is named otherwise. Caught in review; pinned by a test that asserts the present package is never the one the remedy suggests installing.
|
|
13
|
+
- **The bin preflight detects an install whose files are incomplete, not just an absent package.** It resolved each peer and treated a successful resolve as healthy. Resolving is not loading: an interrupted install, a pruned `node_modules` or a bad package-cache restore leaves `package.json` and its `exports` map intact with the file they point at gone, so the preflight passed it through and the bundle died on that import with the raw `ERR_MODULE_NOT_FOUND` the shim exists to replace. The preflight now also checks that the resolved file exists and reports `installed, but its files are incomplete` with the same exit 78. Checked with `existsSync` rather than by importing the module, which would run the host packages' side effects before the CLI has decided to start. Verified by reverting each half in isolation: without the `argv[1]` rewrite the stub engine exits 97, with a resolve-only preflight a deliberately truncated peer produces `ERR_MODULE_NOT_FOUND`, and the fixed shim produces exit 78.
|
|
14
|
+
- **`dist/cli-bin.mjs` ships executable.** It was published at mode 644 against 755 for `dist/cli.mjs`, because the build copies it with `copyFileSync`, which preserves the committed source mode. Every package manager chmods the declared `bin` target itself, so no install was broken, but the shipped artifact should not depend on that. The build now chmods 755 and the source is committed executable.
|
|
15
|
+
|
|
8
16
|
## [1.7.5] - 2026-10-01
|
|
9
17
|
|
|
10
18
|
### Added
|
package/package.json
CHANGED
package/scripts/build.cjs
CHANGED
|
@@ -57,6 +57,14 @@ function copyWebGpuProbe() {
|
|
|
57
57
|
function copyCliBin() {
|
|
58
58
|
fs.mkdirSync(p('dist'), { recursive: true });
|
|
59
59
|
fs.copyFileSync(p('src', 'cli-bin.mjs'), p('dist', 'cli-bin.mjs'));
|
|
60
|
+
// copyFileSync preserves the SOURCE mode. The source is committed executable
|
|
61
|
+
// (100755) so this is belt-and-braces, but nothing about the shipped bin should
|
|
62
|
+
// depend on the source file's mode or on the umask of whatever builds it. The
|
|
63
|
+
// bin is what the OS executes, so ship it executable like dist/cli.mjs: every
|
|
64
|
+
// package manager does its own chmod on the declared bin target, but nothing
|
|
65
|
+
// should depend on that. (Flagged in review 2026-10-01: the packed 1.7.5 tarball
|
|
66
|
+
// had dist/cli.mjs at 755 and dist/cli-bin.mjs at 644.)
|
|
67
|
+
fs.chmodSync(p('dist', 'cli-bin.mjs'), 0o755);
|
|
60
68
|
}
|
|
61
69
|
|
|
62
70
|
// Build the browser worker bundle. Factored out so the cli target can guarantee
|
package/src/cli-bin.mjs
CHANGED
|
@@ -34,24 +34,62 @@
|
|
|
34
34
|
* the user reached for.
|
|
35
35
|
*/
|
|
36
36
|
|
|
37
|
+
import { existsSync } from 'node:fs';
|
|
37
38
|
import { fileURLToPath } from 'node:url';
|
|
38
39
|
|
|
39
40
|
const REQUIRED_PEERS = ['@earendil-works/pi-ai', '@earendil-works/pi-coding-agent'];
|
|
40
41
|
|
|
41
|
-
|
|
42
|
+
/**
|
|
43
|
+
* Probe one peer dependency.
|
|
44
|
+
*
|
|
45
|
+
* 'ok' — resolves, and the file it resolves to exists
|
|
46
|
+
* 'missing' — does not resolve at all (the --legacy-peer-deps case)
|
|
47
|
+
* 'broken' — resolves (its package.json and exports map are readable) but the
|
|
48
|
+
* file those point at is not on disk
|
|
49
|
+
*
|
|
50
|
+
* The 'broken' case is checked with existsSync rather than by importing the
|
|
51
|
+
* module. Resolving is not loading: an interrupted install, a pruned
|
|
52
|
+
* node_modules or a bad package-cache restore leaves a package that resolves
|
|
53
|
+
* perfectly and then fails to load, which would pass this preflight and die
|
|
54
|
+
* inside cli.mjs with the same raw ERR_MODULE_NOT_FOUND this shim exists to
|
|
55
|
+
* replace. Importing it here instead would work, but it runs the host
|
|
56
|
+
* package's module side effects before the CLI proper has decided to start, so
|
|
57
|
+
* the cheap existence check is the right trade.
|
|
58
|
+
*
|
|
59
|
+
* @returns {'ok' | 'missing' | 'broken'}
|
|
60
|
+
*/
|
|
61
|
+
function probePeer(name) {
|
|
62
|
+
let resolved;
|
|
42
63
|
try {
|
|
43
|
-
import.meta.resolve(name);
|
|
44
|
-
return false;
|
|
64
|
+
resolved = import.meta.resolve(name);
|
|
45
65
|
} catch {
|
|
46
|
-
return
|
|
66
|
+
return 'missing';
|
|
47
67
|
}
|
|
48
|
-
|
|
68
|
+
try {
|
|
69
|
+
return existsSync(fileURLToPath(resolved)) ? 'ok' : 'broken';
|
|
70
|
+
} catch {
|
|
71
|
+
// Resolved to something fileURLToPath cannot turn into a path (not a file:
|
|
72
|
+
// URL). It resolved, so treat it as present rather than inventing a failure.
|
|
73
|
+
return 'ok';
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const status = new Map(REQUIRED_PEERS.map((name) => [name, probePeer(name)]));
|
|
78
|
+
const missing = REQUIRED_PEERS.filter((name) => status.get(name) === 'missing');
|
|
79
|
+
const broken = REQUIRED_PEERS.filter((name) => status.get(name) === 'broken');
|
|
49
80
|
|
|
50
|
-
if (missing.length > 0) {
|
|
81
|
+
if (missing.length > 0 || broken.length > 0) {
|
|
82
|
+
// The remedy names the packages that are ACTUALLY absent. It used to hardcode
|
|
83
|
+
// `npm install -g @earendil-works/pi-coding-agent` with the comment "add just
|
|
84
|
+
// the missing host package", which was wrong whenever pi-ai was the missing
|
|
85
|
+
// one: the instruction named a package the user already had, and following it
|
|
86
|
+
// changed nothing. Reported by review 2026-10-01.
|
|
87
|
+
const needsInstall = [...missing, ...broken];
|
|
51
88
|
const lines = [
|
|
52
89
|
'',
|
|
53
90
|
'Error: pi-research cannot start — it is missing required runtime dependencies:',
|
|
54
91
|
...missing.map((name) => ` ${name}`),
|
|
92
|
+
...broken.map((name) => ` ${name} (installed, but its files are incomplete)`),
|
|
55
93
|
'',
|
|
56
94
|
'These are PEER dependencies. pi provides its own copies when it loads this',
|
|
57
95
|
'package as an extension, and npm >= 7 installs them automatically for a',
|
|
@@ -59,10 +97,11 @@ if (missing.length > 0) {
|
|
|
59
97
|
'what --legacy-peer-deps, yarn classic, and a pnpm config with',
|
|
60
98
|
'auto-install-peers=false do.',
|
|
61
99
|
'',
|
|
62
|
-
'
|
|
100
|
+
'Install the missing package(s), or reinstall this package, which resolves',
|
|
101
|
+
'them as peers:',
|
|
63
102
|
'',
|
|
64
|
-
|
|
65
|
-
' npm install -g @lincoln504/pi-research
|
|
103
|
+
` npm install -g ${needsInstall.join(' ')}`,
|
|
104
|
+
' npm install -g @lincoln504/pi-research',
|
|
66
105
|
'',
|
|
67
106
|
];
|
|
68
107
|
process.stderr.write(lines.join('\n'));
|