@lincoln504/pi-research 0.1.12 → 1.0.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/LICENSE +1 -1
- package/README.md +64 -115
- package/dist/cli.mjs +23211 -0
- package/dist/prompts/research-knowledge-relevance-triage.md +35 -0
- package/dist/prompts/research-knowledge-search-extractor.md +41 -0
- package/dist/prompts/research-tool-usage.md +92 -0
- package/dist/prompts/researcher.md +89 -0
- package/dist/prompts/system-coordinator.md +75 -0
- package/dist/prompts/system-lead-evaluator.md +118 -0
- package/dist/thread-worker.mjs +2611 -0
- package/dist/webgpu-probe.mjs +80 -0
- package/docs/AGENT-SKILL.md +102 -0
- package/docs/ARCHITECTURE.md +306 -80
- package/docs/CONFIGURATION.md +249 -0
- package/docs/KNOWLEDGE-STORE.md +213 -0
- package/docs/PI-EXTENSION.md +91 -0
- package/docs/SDK.md +113 -0
- package/docs/THIRD-PARTY-NOTICES.md +64 -0
- package/package.json +102 -36
- package/scripts/build.cjs +140 -0
- package/scripts/cleanup.cjs +149 -0
- package/scripts/prepare.cjs +28 -0
- package/scripts/setup.cjs +134 -0
- package/skills/pi-research/README.md +90 -0
- package/skills/pi-research/SKILL.md +102 -0
- package/skills/pi-research/references/configuration.md +77 -0
- package/skills/pi-research/scripts/run.mjs +237 -0
- package/src/cleanup/research-cleanup.ts +140 -0
- package/src/cli.ts +1044 -0
- package/src/config.ts +1036 -147
- package/src/constants.ts +115 -84
- package/src/core/health-check-service.ts +265 -0
- package/src/core/interfaces/health-check-interfaces.ts +50 -0
- package/src/core/interfaces/knowledge-interfaces.ts +190 -0
- package/src/core/interfaces/observer-interfaces.ts +67 -0
- package/src/core/interfaces/orchestration-interfaces.ts +86 -0
- package/src/core/interfaces/planning-interfaces.ts +100 -0
- package/src/core/interfaces/process-interfaces.ts +37 -0
- package/src/core/interfaces/research-plan-types.ts +52 -0
- package/src/core/interfaces/scheduler-interfaces.ts +91 -0
- package/src/core/interfaces/service-names.ts +39 -0
- package/src/core/interfaces/state-manager-interfaces.ts +29 -0
- package/src/core/interfaces/steering-interfaces.ts +31 -0
- package/src/core/llm/agentic-repair.ts +169 -0
- package/src/core/llm/inject-date.ts +52 -0
- package/src/core/llm/llm-timeout.ts +64 -0
- package/src/core/llm/llm-utils.ts +86 -0
- package/src/core/llm/model-registry-factory.ts +287 -0
- package/src/core/llm/pi-ai-completion.ts +29 -0
- package/src/core/llm/prompts.ts +50 -0
- package/src/core/llm/research-model-resolver.ts +91 -0
- package/src/core/planning-constants.ts +13 -0
- package/src/core/planning-service.ts +649 -0
- package/src/core/planning-utils.ts +299 -0
- package/src/core/scheduler-factory.ts +48 -0
- package/src/core/scheduler-service.ts +123 -0
- package/src/core/service-initialization.ts +194 -0
- package/src/core/service-interfaces.ts +48 -0
- package/src/core/service-registry.ts +659 -0
- package/src/healthcheck/index.ts +271 -265
- package/src/healthcheck/registry.ts +130 -0
- package/src/index.ts +639 -50
- package/src/infrastructure/browser/browser-cleanup.ts +309 -0
- package/src/infrastructure/browser/browser-client.ts +199 -0
- package/src/infrastructure/browser/browser-error-utils.ts +160 -0
- package/src/infrastructure/browser/browser-lifecycle.ts +120 -0
- package/src/infrastructure/browser/browser-server.ts +174 -0
- package/src/infrastructure/browser/browser-task-scheduler.ts +461 -0
- package/src/infrastructure/browser/cleanup-utils.ts +155 -0
- package/src/infrastructure/browser/client-agent.ts +31 -0
- package/src/infrastructure/browser/config.ts +288 -0
- package/src/infrastructure/browser/ensure-browser.ts +205 -0
- package/src/infrastructure/browser/index.ts +37 -0
- package/src/infrastructure/browser/priority-task-queue.ts +226 -0
- package/src/infrastructure/browser/scheduler-factory.ts +354 -0
- package/src/infrastructure/browser/task-execution-service.ts +209 -0
- package/src/infrastructure/browser/thread-worker-browser.ts +282 -0
- package/src/infrastructure/browser/thread-worker-lifecycle.ts +323 -0
- package/src/infrastructure/browser/thread-worker-messaging.ts +662 -0
- package/src/infrastructure/browser/thread-worker-types.ts +25 -0
- package/src/infrastructure/browser/thread-worker.mjs +2611 -0
- package/src/infrastructure/browser/thread-worker.ts +168 -0
- package/src/infrastructure/browser/worker-pool-manager.ts +449 -0
- package/src/infrastructure/embedding/embedding-client.ts +205 -0
- package/src/infrastructure/embedding/embedding-factory.ts +324 -0
- package/src/infrastructure/embedding/embedding-server.ts +535 -0
- package/src/infrastructure/file-lock-service.ts +592 -0
- package/src/infrastructure/gpu-resource-service.ts +191 -0
- package/src/infrastructure/knowledge-store-service.ts +475 -0
- package/src/infrastructure/metrics-service.ts +129 -0
- package/src/infrastructure/process-lifecycle-service.ts +253 -0
- package/src/infrastructure/scheduler-factory-service.ts +58 -0
- package/src/infrastructure/service-initialization.ts +292 -0
- package/src/infrastructure/state/state-backup-manager.ts +290 -0
- package/src/infrastructure/state/state-browser-api.ts +62 -0
- package/src/infrastructure/state/state-browser-manager.ts +70 -0
- package/src/infrastructure/state/state-manager-service.ts +264 -0
- package/src/infrastructure/state/state-manager.ts +547 -0
- package/src/infrastructure/state/state-metrics.ts +92 -0
- package/src/infrastructure/state/state-migration.ts +103 -0
- package/src/infrastructure/state/state-path-configuration.ts +119 -0
- package/src/infrastructure/state/state-session-api.ts +94 -0
- package/src/infrastructure/state/state-session-manager.ts +127 -0
- package/src/infrastructure/state/state-validator.ts +93 -0
- package/src/infrastructure/types/state-types.ts +85 -0
- package/src/knowledge/chunker.ts +157 -0
- package/src/knowledge/embedder-init.ts +413 -0
- package/src/knowledge/embedder-utils.ts +296 -0
- package/src/knowledge/embedder.ts +592 -0
- package/src/knowledge/index.ts +126 -0
- package/src/knowledge/lancedb-loader.ts +35 -0
- package/src/knowledge/migration.ts +17 -0
- package/src/knowledge/model-config.ts +132 -0
- package/src/knowledge/onnx-env.ts +48 -0
- package/src/knowledge/store-operations.ts +291 -0
- package/src/knowledge/store-schema.ts +79 -0
- package/src/knowledge/store.ts +1251 -0
- package/src/knowledge/transformers-loader.ts +31 -0
- package/src/knowledge/webgpu-probe.mjs +80 -0
- package/src/knowledge/webgpu-viability.ts +255 -0
- package/src/knowledge/writer-queue.ts +252 -0
- package/src/logger.ts +316 -122
- package/src/observers/research-observer-impl.ts +459 -0
- package/src/orchestration/deep-research-orchestrator.ts +524 -773
- package/src/orchestration/deep-research-types.ts +47 -35
- package/src/orchestration/headless-observer.ts +114 -0
- package/src/orchestration/orchestration-types.ts +33 -0
- package/src/orchestration/quick-research-orchestrator.ts +463 -0
- package/src/orchestration/research-orchestration-service.ts +549 -0
- package/src/orchestration/research-session-service.ts +178 -0
- package/src/orchestration/research-synthesis-service.ts +348 -0
- package/src/orchestration/researcher-executor.ts +394 -0
- package/src/orchestration/researcher.ts +115 -42
- package/src/orchestration/service-initialization.ts +109 -0
- package/src/orchestration/session-context.ts +7 -3
- package/src/orchestration/session-state.ts +672 -0
- package/src/prompts/research-knowledge-relevance-triage.md +35 -0
- package/src/prompts/research-knowledge-search-extractor.md +41 -0
- package/src/prompts/research-tool-usage.md +63 -16
- package/src/prompts/researcher.md +59 -136
- package/src/prompts/system-coordinator.md +64 -13
- package/src/prompts/system-lead-evaluator.md +82 -189
- package/src/research-config.ts +872 -0
- package/src/sdk.ts +847 -0
- package/src/security/cisa-kev.ts +72 -9
- package/src/security/cvss.ts +92 -0
- package/src/security/ecosystem.ts +45 -0
- package/src/security/github-advisories.ts +168 -428
- package/src/security/github-advisory-types.ts +282 -0
- package/src/security/index.ts +63 -177
- package/src/security/nvd-client.ts +550 -0
- package/src/security/nvd-types.ts +179 -0
- package/src/security/osv-client.ts +246 -0
- package/src/security/osv-types.ts +285 -0
- package/src/security/types.ts +67 -53
- package/src/skill-install/skill-installer.ts +519 -0
- package/src/stackexchange/index.ts +81 -27
- package/src/stackexchange/output/compact.ts +7 -6
- package/src/stackexchange/output/table.ts +11 -7
- package/src/stackexchange/queries.ts +0 -10
- package/src/stackexchange/rest-client.ts +141 -66
- package/src/stackexchange/types.ts +0 -17
- package/src/tool.ts +15 -423
- package/src/tools/grep.ts +32 -310
- package/src/tools/health-tool-definition.ts +101 -0
- package/src/tools/index.ts +38 -9
- package/src/tools/research-knowledge-search.ts +974 -0
- package/src/tools/research-knowledge-types.ts +77 -0
- package/src/tools/research-tool-definition.ts +494 -0
- package/src/tools/scrape.ts +286 -388
- package/src/tools/search.ts +98 -153
- package/src/tools/security.ts +107 -80
- package/src/tools/stackexchange.ts +58 -35
- package/src/tools/youtube-transcript.ts +163 -0
- package/src/tui/knowledge-search-panel.ts +86 -0
- package/src/tui/pulse.ts +86 -0
- package/src/tui/research-health.ts +124 -0
- package/src/tui/research-panel-color-utils.ts +340 -0
- package/src/tui/research-panel-format.ts +54 -0
- package/src/tui/research-panel-state.ts +404 -0
- package/src/tui/research-panel-wave.ts +280 -0
- package/src/tui/research-panel.ts +339 -435
- package/src/tui/research-tui-manager.ts +233 -0
- package/src/tui/tui-controller.ts +137 -0
- package/src/types/extension-context.ts +18 -49
- package/src/types/index.ts +61 -0
- package/src/types/llm.ts +68 -29
- package/src/types/research-panel-types.ts +61 -0
- package/src/utils/circuit-breaker.ts +146 -0
- package/src/utils/citation-utils.ts +97 -0
- package/src/utils/disk-space-checker.ts +55 -0
- package/src/utils/error-tracker.ts +265 -0
- package/src/utils/host-config.ts +45 -0
- package/src/utils/input-validation.ts +8 -10
- package/src/utils/json-utils.ts +150 -16
- package/src/utils/llm-usage.ts +54 -0
- package/src/utils/log-rotation.ts +125 -0
- package/src/utils/log-utils.ts +159 -0
- package/src/utils/make-resource-loader.ts +3 -1
- package/src/utils/metrics-summary.ts +459 -0
- package/src/utils/metrics.ts +302 -0
- package/src/utils/research-export.ts +28 -12
- package/src/utils/safe-unref.ts +31 -0
- package/src/utils/shared-links.ts +195 -90
- package/src/utils/shutdown-manager.ts +65 -0
- package/src/utils/stdio-capture.ts +407 -0
- package/src/utils/text-utils.ts +264 -7
- package/src/utils/tool-usage-tracker.ts +83 -16
- package/src/utils/url-utils.ts +255 -0
- package/src/utils/user-agent.ts +28 -0
- package/src/web-research/browser-search.ts +179 -0
- package/src/web-research/retry-utils.ts +173 -77
- package/src/web-research/scraper-types.ts +72 -0
- package/src/web-research/scraper-utils.ts +434 -0
- package/src/web-research/search.ts +78 -218
- package/src/web-research/types.ts +9 -24
- package/src/web-research/utils.ts +2 -143
- package/src/web-research/web-scraper.ts +477 -0
- package/src/youtube/index.ts +154 -0
- package/src/youtube/potoken.ts +259 -0
- package/src/youtube/transcript-client.ts +390 -0
- package/src/youtube/video-id.ts +118 -0
- package/config/searxng/default-settings.yml +0 -189
- package/config/searxng/limiter.toml +0 -34
- package/config/tooling/eslint.config.js +0 -73
- package/config/tooling/vitest.config.integration.ts +0 -17
- package/config/tooling/vitest.config.ts +0 -40
- package/config/tooling/vitest.config.unit.ts +0 -12
- package/docs/assets/README-banner.jpg +0 -0
- package/scripts/setup.js +0 -174
- package/src/infrastructure/searxng-lifecycle.ts +0 -577
- package/src/infrastructure/searxng-manager.ts +0 -1183
- package/src/infrastructure/state-manager.ts +0 -918
- package/src/orchestration/deep-research-reducer.ts +0 -129
- package/src/orchestration/id-utils.ts +0 -63
- package/src/security/nvd.ts +0 -532
- package/src/security/osv.ts +0 -487
- package/src/stackexchange/cache.ts +0 -111
- package/src/stackexchange/output/index.ts +0 -7
- package/src/stackexchange/output/json.ts +0 -21
- package/src/tui/searxng-status.ts +0 -80
- package/src/utils/inject-date.ts +0 -29
- package/src/utils/research-error.ts +0 -205
- package/src/utils/searxng-config.ts +0 -94
- package/src/utils/session-state.ts +0 -295
- package/src/web-research/dependencies.ts +0 -20
- package/src/web-research/scrapers.ts +0 -935
- package/tsconfig.json +0 -40
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Out-of-process WebGPU viability probe (child process entry point).
|
|
3
|
+
*
|
|
4
|
+
* WHY THIS EXISTS: onnxruntime-node bundles Dawn as its WebGPU execution
|
|
5
|
+
* provider. On a host whose only Vulkan adapter is software/paravirtual
|
|
6
|
+
* (llvmpipe/lavapipe, virtio/venus, SwiftShader, "Microsoft Basic Render
|
|
7
|
+
* Driver", ...), Dawn happily *loads* the pipeline but then SIGSEGVs the moment
|
|
8
|
+
* it dispatches the first compute shader. A SIGSEGV is a process-level signal,
|
|
9
|
+
* not a JavaScript exception — no try/catch, no Promise rejection handler, and
|
|
10
|
+
* none of the embedder's WebGPU->CPU fallback logic can ever observe it. The
|
|
11
|
+
* V8 isolate simply dies.
|
|
12
|
+
*
|
|
13
|
+
* The only reliable way to learn "will WebGPU compute crash on this machine?"
|
|
14
|
+
* is to actually run one tiny embedding in a DISPOSABLE child process and read
|
|
15
|
+
* its exit code. A native crash here kills only this child; the parent reads a
|
|
16
|
+
* non-zero exit / fatal signal and chooses CPU. This converts an uncatchable
|
|
17
|
+
* native crash into an ordinary, catchable signal.
|
|
18
|
+
*
|
|
19
|
+
* Contract — the parent judges viability by the STDOUT SENTINEL, not the exit
|
|
20
|
+
* code. This is deliberate: onnxruntime-node's native teardown can itself abort
|
|
21
|
+
* (SIGABRT, "Attempt to use DefaultLogger but none has been registered") when the
|
|
22
|
+
* process exits with a live ORT session — even after a perfectly successful
|
|
23
|
+
* compute. So:
|
|
24
|
+
* argv[2] = model id (e.g. onnx-community/granite-embedding-small-english-r2-ONNX)
|
|
25
|
+
* argv[3] = HuggingFace cache directory (shared with the parent)
|
|
26
|
+
* prints "PROBE_OK <dims>" to STDOUT (written synchronously) => compute worked
|
|
27
|
+
* no "PROBE_OK" on stdout (crash during compute, load failure, ...) => not viable
|
|
28
|
+
* A SIGSEGV during the compute dispatch (the software/paravirtual-GPU case) kills
|
|
29
|
+
* the child BEFORE the sentinel is written, so its absence is the signal.
|
|
30
|
+
*
|
|
31
|
+
* This file is plain .mjs (no TypeScript, no bundling). It is shipped verbatim
|
|
32
|
+
* next to the bundled entry points (dist/) and resolves @huggingface/transformers
|
|
33
|
+
* from the installed package's node_modules, exactly like the other entry points.
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
import process from 'node:process';
|
|
37
|
+
import { writeSync } from 'node:fs';
|
|
38
|
+
|
|
39
|
+
async function main() {
|
|
40
|
+
const model = process.argv[2];
|
|
41
|
+
const cacheDir = process.argv[3];
|
|
42
|
+
if (!model || !cacheDir) {
|
|
43
|
+
process.stderr.write('webgpu-probe: missing model/cacheDir args\n');
|
|
44
|
+
process.exit(2);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const { pipeline, env } = await import('@huggingface/transformers');
|
|
48
|
+
env.cacheDir = cacheDir;
|
|
49
|
+
// Keep the probe quiet — we only care about the exit code, not Dawn chatter.
|
|
50
|
+
try {
|
|
51
|
+
if (env.backends && env.backends.onnx) env.backends.onnx.logLevel = 'error';
|
|
52
|
+
} catch {
|
|
53
|
+
/* best-effort */
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Load on the WebGPU EP exactly as the real embedder would, then run ONE embed.
|
|
57
|
+
// The crash (if any) happens on this first compute dispatch, after load.
|
|
58
|
+
const pipe = await pipeline('feature-extraction', model, {
|
|
59
|
+
device: 'webgpu',
|
|
60
|
+
session_options: { intraOpNumThreads: 2, interOpNumThreads: 1 },
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
const out = await pipe('webgpu viability probe', { pooling: 'mean', normalize: true });
|
|
64
|
+
|
|
65
|
+
// Touch the result so the compute cannot be optimized away.
|
|
66
|
+
if (out && out.data && out.data.length > 0) {
|
|
67
|
+
// Write the sentinel SYNCHRONOUSLY to fd 1 so it is guaranteed on the pipe
|
|
68
|
+
// before process teardown — which may itself abort the ORT native runtime.
|
|
69
|
+
// The parent keys off this sentinel, so a teardown abort here is harmless.
|
|
70
|
+
writeSync(1, 'PROBE_OK ' + out.data.length + '\n');
|
|
71
|
+
process.exit(0);
|
|
72
|
+
}
|
|
73
|
+
process.stderr.write('webgpu-probe: empty embedding output\n');
|
|
74
|
+
process.exit(3);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
main().catch((err) => {
|
|
78
|
+
process.stderr.write('webgpu-probe error: ' + (err && err.message ? err.message : String(err)) + '\n');
|
|
79
|
+
process.exit(1);
|
|
80
|
+
});
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
## Agent Skill
|
|
2
|
+
|
|
3
|
+
pi-research ships as a portable [Agent Skill](https://agentskills.io/specification)
|
|
4
|
+
so any skills-compatible coding agent (Claude, OpenAI Codex CLI, OpenClaw, and
|
|
5
|
+
others using the same `SKILL.md` directory model) can run web research through the
|
|
6
|
+
pi-research software.
|
|
7
|
+
|
|
8
|
+

|
|
9
|
+
|
|
10
|
+
### How it works
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
agent
|
|
14
|
+
│ shells out (Bash / exec)
|
|
15
|
+
▼
|
|
16
|
+
run.mjs — zero-dep launcher (skills/pi-research/scripts/)
|
|
17
|
+
│ locates the installed engine, or fails fast with guidance
|
|
18
|
+
▼
|
|
19
|
+
pi-research engine — the SDK (dist/cli.mjs)
|
|
20
|
+
│ init → run → shutdown
|
|
21
|
+
▼
|
|
22
|
+
cited Markdown report → stdout → back to the agent
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The agent matches the `description` in `SKILL.md` and shells out to the launcher.
|
|
26
|
+
`run.mjs` carries no dependencies; it locates the installed engine
|
|
27
|
+
(`PI_RESEARCH_BIN` pointing at the engine's `dist/cli.mjs`, then
|
|
28
|
+
`PI_RESEARCH_PATH` pointing at its package dir, then PATH / `node_modules` /
|
|
29
|
+
`~/.pi/bin`) and exits with an actionable
|
|
30
|
+
message — including config-file locations — if the package, a model, or an API key
|
|
31
|
+
is missing. It exposes four subcommands: `research "<query>"` (live research),
|
|
32
|
+
`knowledge "<query>"` (search past findings), `knowledge-config [set <mode>]`
|
|
33
|
+
(show/set the per-directory knowledge-store mode), and `status` (inspect detection/config).
|
|
34
|
+
|
|
35
|
+
### Installation flow
|
|
36
|
+
|
|
37
|
+
The skill source lives at `skills/pi-research/` inside the package. Installing means
|
|
38
|
+
linking that directory into each agent's skills folder.
|
|
39
|
+
|
|
40
|
+
One-click (recommended). From the `pi` extension, run `/research-config` →
|
|
41
|
+
Install in External Agents. The installer:
|
|
42
|
+
|
|
43
|
+
1. Detects which target agents are present under `$HOME` — currently Claude
|
|
44
|
+
(`~/.claude/skills`), OpenAI Codex CLI (`~/.codex/skills`), and OpenClaw
|
|
45
|
+
(`~/.openclaw/skills`, OpenClaw's managed skill root, which accepts symlinked
|
|
46
|
+
skill folders).
|
|
47
|
+
2. Symlinks `skills/pi-research/` into each present agent, never overwriting an
|
|
48
|
+
unrelated skill already in that slot.
|
|
49
|
+
3. Records what it created in a manifest, so Remove from External Agents
|
|
50
|
+
removes only its own links. Stale links are also garbage-collected on startup and
|
|
51
|
+
on `npm uninstall`.
|
|
52
|
+
|
|
53
|
+
**OpenClaw without `pi`**
|
|
54
|
+
|
|
55
|
+
If you run OpenClaw but not the `pi` extension, register the skill with OpenClaw's
|
|
56
|
+
own CLI after installing the engine — OpenClaw copies the `SKILL.md` folder into its
|
|
57
|
+
managed skill root and reads it on the next session:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
npm install -g @lincoln504/pi-research
|
|
61
|
+
openclaw skills install "$(npm root -g)/@lincoln504/pi-research/skills/pi-research" --global
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
OpenClaw drives the skill through its `exec` tool, gated on `node` being on `PATH`
|
|
65
|
+
(`metadata.openclaw.requires.bins`). A bare `openclaw skills install git:…` is *not*
|
|
66
|
+
used here: OpenClaw expects `SKILL.md` at a repo root, whereas this package nests it
|
|
67
|
+
under `skills/pi-research/` — install the engine from npm and point OpenClaw at that
|
|
68
|
+
folder, as above.
|
|
69
|
+
|
|
70
|
+
Cursor is intentionally excluded from the one-click flow — it has no global skills
|
|
71
|
+
directory and reads only project-level `.cursor/skills/`. Link it per project:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
ln -s "$(npm root -g)/@lincoln504/pi-research/skills/pi-research" .cursor/skills/pi-research
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Manual. Symlink the directory into any agent's skills folder yourself:
|
|
78
|
+
|
|
79
|
+
| Agent | Personal | Project |
|
|
80
|
+
|-------|----------|---------|
|
|
81
|
+
| Claude | `~/.claude/skills/pi-research/` | `<project>/.claude/skills/pi-research/` |
|
|
82
|
+
| OpenAI Codex CLI | `~/.codex/skills/pi-research/` | `<project>/.codex/skills/pi-research/` |
|
|
83
|
+
| OpenClaw | `~/.openclaw/skills/pi-research/` | `<workspace>/skills/pi-research/` |
|
|
84
|
+
| Cursor | — (no global dir) | `<project>/.cursor/skills/pi-research/` |
|
|
85
|
+
|
|
86
|
+
### Prerequisites
|
|
87
|
+
|
|
88
|
+
- Node.js >= 22.19.0
|
|
89
|
+
- `pi-research` installed where the launcher can find it, plus a model + API key.
|
|
90
|
+
See [Configuration](CONFIGURATION.md).
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
npm install -g @lincoln504/pi-research
|
|
94
|
+
node "<skill_dir>/scripts/run.mjs" status # verify the engine is detected
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+

|
|
98
|
+
|
|
99
|
+
Once installed, ask the agent to research something — its skill system activates
|
|
100
|
+
pi-research automatically. The in-package readme (`skills/pi-research/README.md`) and
|
|
101
|
+
`skills/pi-research/references/configuration.md` carry the same detail for anyone
|
|
102
|
+
browsing the skill directly.
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -1,109 +1,335 @@
|
|
|
1
|
-
|
|
1
|
+
## Architecture
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
pi-research is a pi TUI extension for multi-agent web research. It runs inside the pi
|
|
4
|
+
process, registers its tools and commands, and manages its own browser worker pool,
|
|
5
|
+
service registry, and local knowledge store. One engine backs every front-end: besides
|
|
6
|
+
the pi extension it is exposed as a standalone CLI, a portable agent skill — the same
|
|
7
|
+
skill any skills-aware host runs, including OpenClaw — and a programmatic SDK
|
|
8
|
+
(`src/sdk.ts`).
|
|
4
9
|
|
|
5
|
-
|
|
10
|
+
```
|
|
11
|
+
pi CLI
|
|
12
|
+
└── pi-research extension (src/index.ts)
|
|
13
|
+
├── Registered Tools research, health, research_knowledge_search (always registered; reports why when the store is disabled)
|
|
14
|
+
├── Commands /research, /research-config, /knowledge-store
|
|
15
|
+
├── Events input (mid-run steering), session_shutdown (cleanup)
|
|
16
|
+
└── Layers
|
|
17
|
+
├── Orchestration quick/deep research coordination
|
|
18
|
+
├── Agent Tools search, scrape, youtube_transcript, security_search, stackexchange, grep, read
|
|
19
|
+
├── Infrastructure browser pool, knowledge store, state manager
|
|
20
|
+
└── Core service registry, scheduler, health checks
|
|
21
|
+
```
|
|
6
22
|
|
|
7
|
-
|
|
8
|
-
|
|
23
|
+
1. A query enters through `runResearch` — the single internal entry point — with a depth.
|
|
24
|
+
Callers phrase the request in natural language: when the `research` tool is invoked
|
|
25
|
+
in-session, the calling agent picks the depth (1–3) from the user's wording and the
|
|
26
|
+
task's complexity, guided by the tool's usage prompt (`src/prompts/research-tool-usage.md`).
|
|
27
|
+
CLI and SDK callers pass the depth explicitly.
|
|
28
|
+
2. Depth 0 takes the quick path; depth 1–3 takes the deep path (below). The TUI and agent
|
|
29
|
+
skill are restricted to levels 1–3.
|
|
30
|
+
3. On the deep path the coordinator plans the research tracks and runs one initial
|
|
31
|
+
search burst, then hands each researcher a set of result URLs to start from.
|
|
32
|
+
4. Researchers scrape and read those pages through the scrape tooling and return cited
|
|
33
|
+
reports. They consider only what they scraped this session.
|
|
34
|
+
5. The evaluator reviews the round and either runs another round or synthesizes the
|
|
35
|
+
final report.
|
|
36
|
+
6. The result is returned as a single cited Markdown report; the cited URLs and their
|
|
37
|
+
summaries are queued into the knowledge store for future runs.
|
|
9
38
|
|
|
10
|
-
###
|
|
11
|
-
Uses a state machine to manage a three-status research lifecycle:
|
|
39
|
+
### Orchestration
|
|
12
40
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
- **Report Injection**: Collective knowledge is managed by the orchestrator. When a researcher completes its task, its full report (up to 50k chars) is **injected** into the context of siblings starting later, or **steered** into already running ones. This ensures researchers don't just know *what* was scraped, but also *what was found*.
|
|
17
|
-
- **Lead Evaluation**: When a round is complete, a **Lead Evaluator** agent call is triggered. It reviews all accumulated findings against the original agenda.
|
|
18
|
-
- **Decision Outcome**: The evaluator makes a binary choice:
|
|
19
|
-
- **Synthesize**: Generate a final, exhaustive Markdown report (transition to **Completed**).
|
|
20
|
-
- **Delegate**: Formulate new, targeted queries for a subsequent round (remain in **Researching**).
|
|
21
|
-
3. **Completed Status**: The final synthesis is returned as the tool result.
|
|
41
|
+
`runResearch` (`IResearchOrchestration`, implemented in
|
|
42
|
+
`src/orchestration/research-orchestration-service.ts`) is the single internal entry
|
|
43
|
+
point. It dispatches on depth.
|
|
22
44
|
|
|
23
|
-
|
|
45
|
+
Depth 0 — quick (`QuickResearchOrchestrator`): a single researcher runs directly with
|
|
46
|
+
all tools; there is no coordinator, no planning phase, and no rounds. Depth 0 is
|
|
47
|
+
reachable only through the SDK (`runQuickResearch`) or the CLI (`--depth 0`, which the
|
|
48
|
+
agent skill can pass). The pi extension's `research` tool has a minimum depth of 1, so
|
|
49
|
+
an in-session agent can never request quick mode.
|
|
24
50
|
|
|
25
|
-
|
|
51
|
+
Depth 1–3 — deep (`DeepResearchOrchestrator`): the run proceeds in **rounds**. A round
|
|
52
|
+
is one coordinate → research → evaluate cycle — the round's agenda is planned (by the
|
|
53
|
+
coordinator in round 1, by the evaluator thereafter), a batch of **researchers** runs it
|
|
54
|
+
in parallel, and the evaluator then decides whether to run another round or synthesize.
|
|
55
|
+
Two limits apply independently: how many researchers run *within* a round, and how many
|
|
56
|
+
rounds the run may take.
|
|
26
57
|
|
|
27
|
-
|
|
58
|
+
| Depth | Label | Researchers per round (max) | Rounds (max) |
|
|
59
|
+
|-------|--------|-----------------------------|--------------|
|
|
60
|
+
| 1 | normal | 2 | 2 |
|
|
61
|
+
| 2 | deep | 3 | 3 |
|
|
62
|
+
| 3 | ultra | 5 | 3 |
|
|
28
63
|
|
|
29
|
-
|
|
64
|
+
These are ceilings, not targets: the coordinator and evaluator use as many researchers
|
|
65
|
+
and rounds as the topic needs. A depth-2 run, for example, may spawn up to 3 researchers
|
|
66
|
+
in each of up to 3 rounds. Queued steering messages (Alt+Enter) can unlock a few extra
|
|
67
|
+
rounds past the cap (`MAX_EXTRA_ROUNDS_WITH_STEERING`).
|
|
30
68
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
- **Goal**: Breadth-first exploration and URL discovery.
|
|
69
|
+
The coordinator also runs the initial search burst and distributes its result URLs to
|
|
70
|
+
round 1's researchers (`distributeSearchResults`), so in deep mode the researchers
|
|
71
|
+
themselves do not call `search`.
|
|
35
72
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
73
|
+
LLM-call conventions. Coordinator, evaluator, synthesis, JSON-repair, and
|
|
74
|
+
knowledge-extraction calls go through `completeSimple` (`src/core/llm/pi-ai-completion.ts`)
|
|
75
|
+
with `buildSafeOptions` (`src/core/llm/llm-utils.ts`); researcher sub-agents go through
|
|
76
|
+
`createAgentSession`.
|
|
77
|
+
Two conventions apply:
|
|
41
78
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
-
|
|
79
|
+
- Thinking is off by default. These calls emit structured JSON or cited reports, so a
|
|
80
|
+
chain-of-thought block only spends output-token budget (and can truncate the answer).
|
|
81
|
+
`PI_RESEARCH_LLM_THINKING_LEVEL` (default `off`) controls it, clamped per provider.
|
|
82
|
+
- Output budgets are sized per role and clamped to the model's ceiling:
|
|
83
|
+
`PLANNING_MAX_TOKENS` for the plan/decision, `SYNTHESIS_MAX_TOKENS` for the final
|
|
84
|
+
report. A mid-round evaluation that cannot be parsed continues the existing agenda
|
|
85
|
+
rather than finalizing early, so a parse failure never truncates a run.
|
|
46
86
|
|
|
47
|
-
|
|
87
|
+
### Research tools
|
|
48
88
|
|
|
49
|
-
|
|
89
|
+
Each researcher has a fixed tool set and a shared budget of 12 gathering calls per phase
|
|
90
|
+
(`MAX_GATHERING_CALLS`).
|
|
50
91
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
92
|
+
| Tool | Quick | Deep | Backend |
|
|
93
|
+
|------|-------|------|---------|
|
|
94
|
+
| `search` | ✓ | — | DuckDuckGo Lite via the stealth browser |
|
|
95
|
+
| `scrape` | ✓ | ✓ | Batch page fetch → Markdown via the stealth browser (up to 6 URLs per call) |
|
|
96
|
+
| `youtube_transcript` | ✓ | ✓ | YouTube captions via youtubei.js + BotGuard PoToken (≤3 videos, one call per researcher) |
|
|
97
|
+
| `security_search` | ✓ | ✓ | NVD, CISA KEV, GitHub Advisories, OSV |
|
|
98
|
+
| `stackexchange` | ✓ | ✓ | Stack Exchange network |
|
|
99
|
+
| `grep` | — | ✓ | Local ripgrep (from pi-coding-agent) |
|
|
100
|
+
| `read` | ✓ | ✓ | Local file reads (from pi-coding-agent) |
|
|
58
101
|
|
|
59
|
-
|
|
60
|
-
|
|
102
|
+
In deep research `search` is excluded — the coordinator runs the search burst and hands
|
|
103
|
+
out URLs directly. In quick research `grep` is excluded — the single session is not
|
|
104
|
+
expected to traverse a local codebase. Researchers cannot write files, run shell
|
|
105
|
+
commands, or reach the network outside these tools.
|
|
61
106
|
|
|
62
|
-
|
|
63
|
-
2. **Batch 1**: Up to 3 URLs — primary broad scraping.
|
|
64
|
-
3. **Batch 2**: Up to 2 URLs — targeted follow-up, deduplicated against Batch 1.
|
|
65
|
-
4. **Batch 3**: Up to 3 URLs — deep-dive scraping.
|
|
107
|
+
### Browser infrastructure
|
|
66
108
|
|
|
67
|
-
|
|
68
|
-
|
|
109
|
+
All browser work (search, scrape, health checks) goes through a poolifier
|
|
110
|
+
`FixedClusterPool` of worker processes — each a Node.js child process running its own
|
|
111
|
+
camoufox (stealth Firefox) instance. Isolating the browser in workers means a crash in
|
|
112
|
+
one worker cannot take down the orchestrator or other sessions.
|
|
69
113
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
114
|
+
```
|
|
115
|
+
BrowserTaskScheduler
|
|
116
|
+
└── FixedClusterPool (poolifier)
|
|
117
|
+
├── Worker 1 → camoufox instance
|
|
118
|
+
├── Worker 2 → camoufox instance
|
|
119
|
+
└── Worker N → camoufox instance
|
|
120
|
+
```
|
|
77
121
|
|
|
78
|
-
|
|
122
|
+
Key files:
|
|
123
|
+
- `src/infrastructure/browser/browser-task-scheduler.ts` — dispatches tasks to the pool
|
|
124
|
+
- `src/infrastructure/browser/thread-worker.ts` — worker entry point (bundled separately by esbuild)
|
|
125
|
+
- `src/infrastructure/browser/thread-worker-messaging.ts` — IPC protocol
|
|
126
|
+
- `src/infrastructure/browser/config.ts` — pool configuration, binary path detection
|
|
79
127
|
|
|
80
|
-
|
|
128
|
+
### Knowledge store and data handling
|
|
81
129
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
130
|
+
The knowledge store is a local LanceDB vector table of past findings. It is optional
|
|
131
|
+
(research works without it) and is driven entirely by the orchestrator — researchers
|
|
132
|
+
never call it directly:
|
|
85
133
|
|
|
86
|
-
|
|
134
|
+
- Before each researcher starts, the orchestrator searches the store for that
|
|
135
|
+
researcher's goal and injects any matching historical URLs (with summaries) into its
|
|
136
|
+
prompt as starting points.
|
|
137
|
+
- After a run, the cited URLs and their descriptions are enqueued into the async writer
|
|
138
|
+
queue and stored in the background — writes never block a run.
|
|
87
139
|
|
|
88
|
-
|
|
140
|
+
On ingest, each source's summary and full scraped Markdown are split into chunks and
|
|
141
|
+
embedded into vectors. A SHA-256 content hash of the page dedupes re-ingested URLs:
|
|
142
|
+
an unchanged page is skipped, a changed page replaces its old rows. Each row carries the
|
|
143
|
+
vector, the normalized URL, the text and full content, a timestamp, and scope flags
|
|
144
|
+
(project vs. global) that are filtered at query time.
|
|
89
145
|
|
|
90
|
-
|
|
146
|
+
```
|
|
147
|
+
WriterQueue (async, non-blocking)
|
|
148
|
+
└── KnowledgeStore
|
|
149
|
+
├── Embedder (onnx-community/granite-embedding-small-english-r2-ONNX via @huggingface/transformers)
|
|
150
|
+
│ └── backend: auto (out-of-process WebGPU probe → webgpu or cpu) / webgpu / cpu
|
|
151
|
+
└── LanceDB (knowledge_db/ directory, Arrow-backed vector table)
|
|
152
|
+
```
|
|
91
153
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
3. **Round Budget**: It checks the round budget (`targetRounds + MAX_EXTRA_ROUNDS`). The hard limit is `targetRounds + 2` bonus rounds.
|
|
97
|
-
4. **Action Selection**: Produces either a Markdown synthesis (final result) or a JSON delegation object (`{"action": "delegate", "queries": [...]}`). Any non-JSON response is treated as a final synthesis to prevent the research from getting stuck.
|
|
154
|
+
Key files: `src/knowledge/store.ts` (LanceDB operations), `embedder.ts` (model load +
|
|
155
|
+
batched inference), `writer-queue.ts` (async writes + content-hash dedup), `chunker.ts`
|
|
156
|
+
(chunking), `webgpu-viability.ts` (out-of-process GPU probe + cached verdict),
|
|
157
|
+
`migration.ts` (model-change migration: drop / backup / re-embed).
|
|
98
158
|
|
|
99
|
-
|
|
159
|
+
The store needs native ONNX-runtime and LanceDB bindings. On platforms with no prebuilt
|
|
160
|
+
binary — notably Intel macOS (`darwin-x64`) — it is absent: the health check reports it
|
|
161
|
+
disabled-but-healthy and research runs without the cache. See
|
|
162
|
+
[KNOWLEDGE-STORE.md](KNOWLEDGE-STORE.md) for the full subsystem and platform matrix.
|
|
100
163
|
|
|
101
|
-
|
|
164
|
+
### Services and lifecycle
|
|
102
165
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
166
|
+
Services are registered with async factory functions and resolved through a registry
|
|
167
|
+
(`getService()`), initialized lazily or eagerly with dependencies wired at init time.
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
registerService(ServiceNames.FOO, async () => {
|
|
171
|
+
const dep = await getService<IBar>(ServiceNames.BAR);
|
|
172
|
+
return new FooService(dep);
|
|
173
|
+
}, { lazyInitialization: true });
|
|
174
|
+
|
|
175
|
+
const foo = await getService<IFoo>(ServiceNames.FOO);
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Services that hold resources implement `dispose()`; the registry disposes them in
|
|
179
|
+
reverse dependency order. Resolving through the registry (rather than direct imports)
|
|
180
|
+
enforces lifecycle discipline (init → use → dispose) and lets tests swap in mocks.
|
|
181
|
+
|
|
182
|
+
- Core (`src/core/`): `PlanningService`, `SchedulerService`, `HealthCheckService`
|
|
183
|
+
- Infrastructure (`src/infrastructure/`): `StateManagerService`, `KnowledgeStoreService`, `MetricsService`, `WorkerPoolManager`, `FileLockService`, `GPUResourceService` (plus `WriterQueue`, defined in `src/knowledge/` and registered here)
|
|
184
|
+
- Orchestration (`src/orchestration/`): `ResearchOrchestrationService`, `ResearchSessionService`, `ResearchSynthesisService`
|
|
185
|
+
|
|
186
|
+
Cross-session, cross-process state (active sessions, browser status, metrics) lives in
|
|
187
|
+
`StateManagerService` (`src/infrastructure/state/`), which serializes concurrent writes
|
|
188
|
+
with file-based locking (`FileLockService`).
|
|
189
|
+
|
|
190
|
+
### TUI
|
|
191
|
+
|
|
192
|
+
The live progress panel uses `@earendil-works/pi-tui`, which handles terminal state
|
|
193
|
+
(keyboard protocol, mouse tracking, bracketed paste). stdio capture (to keep stray
|
|
194
|
+
output from corrupting the panel and to guarantee a clean exit) lives in
|
|
195
|
+
`src/utils/stdio-capture.ts`.
|
|
196
|
+
|
|
197
|
+
### Project structure
|
|
198
|
+
|
|
199
|
+
```
|
|
200
|
+
src/
|
|
201
|
+
├── index.ts extension entry point (tools, commands, events, lifecycle)
|
|
202
|
+
├── cli.ts standalone CLI entry point
|
|
203
|
+
├── sdk.ts programmatic SDK (non-extension use)
|
|
204
|
+
├── config.ts env-var parsing, validation, singleton
|
|
205
|
+
├── constants.ts team sizes, round caps, tool budgets, batch limits
|
|
206
|
+
├── logger.ts structured logger (JSONL, TUI-safe)
|
|
207
|
+
├── tool.ts re-export barrel for the research + health tool definitions
|
|
208
|
+
├── research-config.ts /research-config TUI
|
|
209
|
+
├── core/
|
|
210
|
+
│ ├── llm/ prompts, model resolution, agentic JSON repair, inject-date
|
|
211
|
+
│ ├── interfaces/ abstraction contracts (observer, planning, orchestration)
|
|
212
|
+
│ ├── planning-service.ts, scheduler-service.ts
|
|
213
|
+
│ ├── service-registry.ts, service-interfaces.ts, service-initialization.ts
|
|
214
|
+
│ └── planning-utils.ts
|
|
215
|
+
├── infrastructure/
|
|
216
|
+
│ ├── browser/ worker pool, task scheduler, IPC, camoufox config
|
|
217
|
+
│ ├── state/ state manager, session tracking, metrics collector
|
|
218
|
+
│ ├── embedding/ local embedding server management
|
|
219
|
+
│ ├── knowledge-store-service.ts, metrics-service.ts, file-lock-service.ts
|
|
220
|
+
│ └── process-lifecycle-service.ts
|
|
221
|
+
├── orchestration/
|
|
222
|
+
│ ├── deep-research-orchestrator.ts, quick-research-orchestrator.ts
|
|
223
|
+
│ ├── research-orchestration-service.ts, research-synthesis-service.ts
|
|
224
|
+
│ ├── research-session-service.ts, session-state.ts, session-context.ts
|
|
225
|
+
│ ├── researcher-executor.ts, researcher.ts, headless-observer.ts
|
|
226
|
+
├── prompts/ Markdown prompt templates for all agents
|
|
227
|
+
├── tools/ search, scrape, youtube_transcript, security, stackexchange, grep, read, knowledge-search
|
|
228
|
+
├── knowledge/ embedder, store, writer queue, chunker, migration, webgpu probe
|
|
229
|
+
├── web-research/ DuckDuckGo search, scraper, retry logic
|
|
230
|
+
├── security/ NVD, CISA KEV, OSV, GitHub Advisory clients
|
|
231
|
+
├── stackexchange/ Stack Exchange API client
|
|
232
|
+
├── youtube/ YouTube transcript client (InnerTube + BotGuard PoToken)
|
|
233
|
+
├── skill-install/ research-skill installer for coding-agent harnesses
|
|
234
|
+
├── tui/ panels, layout, controller, wave animation, terminal utils
|
|
235
|
+
├── healthcheck/ health-check registry and checks
|
|
236
|
+
├── cleanup/ research-result cleanup
|
|
237
|
+
├── observers/ research-observer implementation
|
|
238
|
+
├── types/ shared index and TUI types
|
|
239
|
+
└── utils/ circuit breaker, text utils, shared-links, metrics, error tracking
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Key design decisions
|
|
243
|
+
|
|
244
|
+
Sandboxed researchers — researcher agents are limited to the tool set above. They cannot
|
|
245
|
+
write files, spawn processes, or make arbitrary network calls.
|
|
246
|
+
|
|
247
|
+
Worker pool over direct browser — browser processes are isolated in workers so a crash
|
|
248
|
+
in one cannot affect the orchestrator or other sessions.
|
|
249
|
+
|
|
250
|
+
Pinned browser stack — `playwright-core` and `impit` are pinned to exact versions and
|
|
251
|
+
`camoufox-js` to its `0.10.x` line (`^0.10.2`, which excludes the `0.11.x` alpha); the
|
|
252
|
+
three are coupled and upgraded together, because each floating range broke fresh consumer
|
|
253
|
+
installs that our lockfile masked. camoufox-js `0.10.2` fetches Firefox
|
|
254
|
+
135/beta.24, the newest camoufox with binaries for every supported OS (later builds
|
|
255
|
+
dropped Windows). playwright-core `1.60.0` is the newest the FF135 Juggler protocol
|
|
256
|
+
accepts (1.61 rejects it and fails every launch). impit `0.13.0` avoids the
|
|
257
|
+
`only-allow pnpm` preinstall guard that impit 0.13.1/0.14.0 shipped, which fails
|
|
258
|
+
`npm install -g`; a direct-dependency pin is required because npm `overrides` do not
|
|
259
|
+
propagate to consumers. Will upgrade all three together when camoufox ships stable
|
|
260
|
+
cross-platform binaries. Rationale in full:
|
|
261
|
+
`src/infrastructure/browser/thread-worker-browser.ts`.
|
|
262
|
+
|
|
263
|
+
Pinned data stack — `apache-arrow` is a direct dependency at `21.1.0`, and `overrides`
|
|
264
|
+
forces the whole tree to that single version so LanceDB and Arrow share one Arrow instance
|
|
265
|
+
(mismatched Arrow copies do not interoperate — arrays built by one are rejected by the
|
|
266
|
+
other). This sits above `@lancedb/lancedb` 0.29's declared Arrow peer ceiling
|
|
267
|
+
(`>=15.0.0 <=18.1.0`); it is verified working, but the override should be re-validated
|
|
268
|
+
whenever `@lancedb/lancedb` is upgraded.
|
|
269
|
+
|
|
270
|
+
Pinned validation library — `typebox` is pinned to the exact version the pi host packages
|
|
271
|
+
depend on (`@earendil-works/pi-ai` / `@earendil-works/pi-coding-agent` pin `1.1.38`). Every
|
|
272
|
+
tool's parameter schema is built with TypeBox here and handed across the boundary to pi's
|
|
273
|
+
tool system, so the two must agree on `Value.Check`/`Convert` semantics. A floating `^1.1.38`
|
|
274
|
+
range let a fresh consumer install resolve pi-research to a newer TypeBox than pi's, shipping
|
|
275
|
+
an untested cross-version pairing; the exact pin keeps pi-research on the same version pi
|
|
276
|
+
validates with. Bump it in lockstep with the pi host, not independently. (`undici`, by
|
|
277
|
+
contrast, tracks the host's major — the host is on undici 8, and pi-research only uses the
|
|
278
|
+
stable `Agent` connector API, so it follows `^8`.)
|
|
279
|
+
|
|
280
|
+
Transient-failure resilience — every LLM call is a potential single point of failure on a
|
|
281
|
+
streaming endpoint that can drop mid-response (undici surfaces this as `terminated`). The
|
|
282
|
+
coordinator and evaluator calls retry fast transient transport failures (socket aborts, 5xx,
|
|
283
|
+
429, provider overload) with bounded exponential backoff — mirroring the per-researcher retry
|
|
284
|
+
(`PI_RESEARCH_MAX_RETRIES`) — and, if still failing, degrade to a deterministic fallback plan
|
|
285
|
+
rather than aborting the run. An app-level LLM timeout is not retried (it already spent the
|
|
286
|
+
full budget); it degrades directly. Retry counts are internal constants, not configuration.
|
|
287
|
+
|
|
288
|
+
Registry over direct imports — services are registered and resolved through the registry
|
|
289
|
+
to support testing (mock replacement) and enforce init → use → dispose lifecycle.
|
|
290
|
+
|
|
291
|
+
Pure ESM — the codebase is ES Modules (`"type": "module"`). Worker bundles are built with
|
|
292
|
+
esbuild (`npm run build:worker`) before integration tests or publishing.
|
|
293
|
+
|
|
294
|
+
Enforced boundaries — `docs/deps.svg` is regenerated on every push (madge), and
|
|
295
|
+
architectural rules are enforced by dependency-cruiser
|
|
296
|
+
(`config/tooling/dependency-cruiser.cjs`).
|
|
297
|
+
|
|
298
|
+
### Built with
|
|
299
|
+
|
|
300
|
+
Browser & scraping
|
|
301
|
+
|
|
302
|
+
- [Camoufox](https://camoufox.com) — stealth Firefox (driven via [Playwright](https://playwright.dev)) for undetected search and scraping
|
|
303
|
+
- [poolifier](https://github.com/poolifier/poolifier) — the worker-process pool behind the browser workers
|
|
304
|
+
- [html-to-markdown](https://github.com/Goldziher/html-to-markdown) & [node-html-markdown](https://github.com/crosstype/node-html-markdown) — convert scraped HTML to Markdown
|
|
305
|
+
- `pdf-oxide-wasm` — PDF text extraction (Rust/WASM)
|
|
306
|
+
|
|
307
|
+
Knowledge store & embeddings
|
|
308
|
+
|
|
309
|
+
- [Transformers.js](https://github.com/huggingface/transformers.js) — local embedding inference (model execution via ONNX Runtime)
|
|
310
|
+
- Google [Dawn](https://dawn.googlesource.com/dawn) — the WebGPU backend, accessed through the `webgpu` Node binding
|
|
311
|
+
- [LanceDB](https://lancedb.com) — on-disk vector database
|
|
312
|
+
- [Apache Arrow](https://arrow.apache.org) — the columnar schema the vector table is built on
|
|
313
|
+
|
|
314
|
+
YouTube transcripts
|
|
315
|
+
|
|
316
|
+
- [youtubei.js](https://github.com/LuanRT/YouTube.js) — YouTube internal-API client
|
|
317
|
+
- [BgUtils](https://github.com/LuanRT/BgUtils) — BotGuard PoToken generation
|
|
318
|
+
- [jsdom](https://github.com/jsdom/jsdom) — DOM environment for minting the PoToken
|
|
319
|
+
|
|
320
|
+
Host & runtime
|
|
321
|
+
|
|
322
|
+
- [pi](https://github.com/earendil-works/pi) — the host runtime, agent SDK, and TUI toolkit
|
|
323
|
+
- [TypeBox](https://github.com/sinclairzx81/typebox) — runtime config schema and validation
|
|
324
|
+
|
|
325
|
+
### Development
|
|
326
|
+
|
|
327
|
+
```bash
|
|
328
|
+
npm run test:unit # unit tests, no browser required
|
|
329
|
+
npm run test:integration # requires camoufox (Xvfb only for the opt-in virtual-display tests)
|
|
330
|
+
npm run type-check # TypeScript strict mode (src)
|
|
331
|
+
npm run type-check:tests # TypeScript strict mode (tests)
|
|
332
|
+
npm run lint # ESLint
|
|
333
|
+
npm run deps:check # architectural rule enforcement
|
|
334
|
+
npm run build:worker # bundle the browser worker (required before integration tests / publish)
|
|
335
|
+
```
|