@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,296 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Embedder Utilities
|
|
3
|
+
*
|
|
4
|
+
* Utility functions for the embedder module
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
import * as os from 'node:os';
|
|
9
|
+
|
|
10
|
+
import { logger } from '../logger.ts';
|
|
11
|
+
import { withTimeout as retryWithTimeout } from '../web-research/retry-utils.ts';
|
|
12
|
+
|
|
13
|
+
import { shutdownManager } from '../utils/shutdown-manager.ts';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Timeout wrapper for promises (re-exports from retry-utils.ts)
|
|
17
|
+
*/
|
|
18
|
+
export function withTimeout<T>(promise: Promise<T>, timeoutMs: number, errorMessage: string): Promise<T> {
|
|
19
|
+
// Normalize via Promise.resolve() to handle HuggingFace pipeline thenables
|
|
20
|
+
// that are not standard Promises (retry-utils calls .then() directly).
|
|
21
|
+
return retryWithTimeout(Promise.resolve(promise), timeoutMs, errorMessage, undefined);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Detect whether an embedding call failed because the embedding *leader* is
|
|
26
|
+
* transiently gone — a dead/stepped-down leader, a poisoned queue, or a
|
|
27
|
+
* connection that was reset when the leader tore down its HTTP server. In every
|
|
28
|
+
* case a fresh leader is immediately electable, so the caller should reconnect
|
|
29
|
+
* and retry rather than drop the work.
|
|
30
|
+
*
|
|
31
|
+
* Signatures, and why each must be matched:
|
|
32
|
+
* - "ECONNREFUSED" the leader's HTTP endpoint is gone (dead/stepped-down
|
|
33
|
+
* leader, or an assertServing() refusal after step-down).
|
|
34
|
+
* - "embedder poisoned" an in-flight/queued embed fast-failed when the leader
|
|
35
|
+
* poisoned its queue on a permanently-hung inference;
|
|
36
|
+
* this rejection carries NO ECONNREFUSED.
|
|
37
|
+
* - ECONNRESET / "socket hang up" / "aborted" / "other side closed":
|
|
38
|
+
* the leader closed the connection mid-request during an
|
|
39
|
+
* ORDINARY shutdown — EmbeddingServer.shutdown() calls
|
|
40
|
+
* closeAllConnections() not just on the poison path but on
|
|
41
|
+
* normal leadership loss and process teardown. Without these,
|
|
42
|
+
* a document in flight during a leader handoff is silently
|
|
43
|
+
* dropped instead of retried against the new leader.
|
|
44
|
+
*
|
|
45
|
+
* Pure string/code matching — safe to call from native-import-free modules.
|
|
46
|
+
*/
|
|
47
|
+
export function isEmbedderUnreachable(err: unknown): boolean {
|
|
48
|
+
const code = (err as NodeJS.ErrnoException)?.code;
|
|
49
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
50
|
+
if (code === 'ECONNREFUSED' || code === 'ECONNRESET' || code === 'ECONNABORTED') return true;
|
|
51
|
+
return (
|
|
52
|
+
msg.includes('ECONNREFUSED') ||
|
|
53
|
+
msg.includes('ECONNRESET') ||
|
|
54
|
+
msg.includes('embedder poisoned') ||
|
|
55
|
+
msg.includes('socket hang up') ||
|
|
56
|
+
msg.includes('other side closed') ||
|
|
57
|
+
/\baborted\b/i.test(msg)
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Detect whether an error indicates the native ML/vector stack is unavailable on
|
|
63
|
+
* this platform — i.e. a prebuilt native binding is genuinely missing, not a
|
|
64
|
+
* transient/logic failure. This is the case on platforms the upstream packages
|
|
65
|
+
* do not ship binaries for (e.g. Intel macOS / darwin-x64, where onnxruntime-node
|
|
66
|
+
* has no prebuilt and @lancedb/lancedb's optional native binding is absent).
|
|
67
|
+
*
|
|
68
|
+
* Such an error is a permanent capability gap, not a fault: callers should treat
|
|
69
|
+
* the knowledge store as DISABLED (degrade gracefully) rather than UNHEALTHY, so
|
|
70
|
+
* research still runs without the optional embedding/vector cache.
|
|
71
|
+
*
|
|
72
|
+
* Pure string matching — safe to call from native-import-free modules.
|
|
73
|
+
* Matched signatures (observed in the wild):
|
|
74
|
+
* - onnxruntime-node: "Cannot find module '.../bin/napi-v6/darwin/x64/onnxruntime_binding.node'"
|
|
75
|
+
* - @lancedb/lancedb: "Cannot find native binding. npm has a bug related to optional dependencies"
|
|
76
|
+
* - jiti-masked module-eval failure of the above surfaces as:
|
|
77
|
+
* "KnowledgeStoreService is not a constructor"
|
|
78
|
+
*/
|
|
79
|
+
export function isNativeStackUnavailableError(err: unknown): boolean {
|
|
80
|
+
if (!err) return false;
|
|
81
|
+
const msg = (err instanceof Error ? `${err.message} ${err.stack ?? ''}` : String(err)).toLowerCase();
|
|
82
|
+
|
|
83
|
+
// Prefer the error CODE where present: it is stable across upstream message
|
|
84
|
+
// rewording, unlike the substring checks below. A failed dlopen of a native
|
|
85
|
+
// .node addon is unambiguously a missing/broken native binding. A
|
|
86
|
+
// module-not-found is only treated as a native-stack gap when it names one of
|
|
87
|
+
// our native packages — an unrelated missing module must NOT be misclassified
|
|
88
|
+
// as "this platform has no native stack".
|
|
89
|
+
// `err` is already known truthy (guarded above), so no `err &&` here.
|
|
90
|
+
const code = (typeof err === 'object' && 'code' in err) ? String((err as { code?: unknown }).code) : '';
|
|
91
|
+
if (code === 'ERR_DLOPEN_FAILED') return true;
|
|
92
|
+
if ((code === 'ERR_MODULE_NOT_FOUND' || code === 'MODULE_NOT_FOUND') &&
|
|
93
|
+
(msg.includes('onnxruntime') || msg.includes('lancedb'))) {
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return (
|
|
98
|
+
msg.includes('cannot find native binding') ||
|
|
99
|
+
msg.includes('onnxruntime_binding.node') ||
|
|
100
|
+
/cannot find module '[^']*onnxruntime/.test(msg) ||
|
|
101
|
+
/cannot find module '[^']*lancedb/.test(msg) ||
|
|
102
|
+
msg.includes('knowledgestoreservice is not a constructor')
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Get the model cache directory
|
|
108
|
+
*/
|
|
109
|
+
export function getModelCacheDir(): string {
|
|
110
|
+
// Per the XDG spec, XDG_CACHE_HOME is honored only when set to an ABSOLUTE path; an empty or
|
|
111
|
+
// relative value must be ignored (an empty `??`-fallback would otherwise yield a cache dir
|
|
112
|
+
// relative to cwd, scattering/--rm-ing models under whatever directory the process started in).
|
|
113
|
+
const xdgCache = process.env['XDG_CACHE_HOME'];
|
|
114
|
+
const base = xdgCache && path.isAbsolute(xdgCache) ? xdgCache : path.join(os.homedir(), '.cache');
|
|
115
|
+
return path.join(base, 'pi-research', 'models');
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Module-level flag to track if any embedder instance has fallen back to CPU due to WebGPU errors
|
|
119
|
+
// This prevents retrying with WebGPU after it's been proven to fail
|
|
120
|
+
let hasWebGpuFallbackOccurred = false;
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Reset the WebGPU fallback flag (useful for testing or if WebGPU becomes available)
|
|
124
|
+
*/
|
|
125
|
+
export function resetWebGpuFallbackFlag(): void {
|
|
126
|
+
hasWebGpuFallbackOccurred = false;
|
|
127
|
+
dawnInitialized = false; // Allow Dawn re-initialization after reset
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Check if WebGPU fallback has occurred
|
|
132
|
+
*/
|
|
133
|
+
export function hasWebGpuFallback(): boolean {
|
|
134
|
+
return hasWebGpuFallbackOccurred;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Mark that WebGPU fallback has occurred
|
|
139
|
+
*/
|
|
140
|
+
export function markWebGpuFallback(): void {
|
|
141
|
+
hasWebGpuFallbackOccurred = true;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Global embedder reference for process-exit cleanup.
|
|
145
|
+
let globalEmbedderRef: { dispose: () => Promise<void> } | null = null;
|
|
146
|
+
|
|
147
|
+
// Instances that have already registered a shutdown-manager task. ShutdownManager
|
|
148
|
+
// dedups by task IDENTITY, and each registerGlobalEmbedder call would otherwise pass a
|
|
149
|
+
// fresh closure — so re-registering the same instance (e.g. on the idle→active revive
|
|
150
|
+
// that restores globalEmbedderRef) must NOT add a second, never-removed task. The
|
|
151
|
+
// WeakSet lets a disposed instance be GC'd without leaking an entry.
|
|
152
|
+
const embeddersWithShutdownTask = new WeakSet<object>();
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Register an Embedder instance for process-exit cleanup.
|
|
156
|
+
* Called by the Embedder constructor AND on each idle→active revive in initialize(),
|
|
157
|
+
* so it must be idempotent: the ref is always (re-)pointed, but the shutdown task is
|
|
158
|
+
* registered at most once per instance.
|
|
159
|
+
*/
|
|
160
|
+
export function registerGlobalEmbedder(e: { dispose: () => Promise<void> }): void {
|
|
161
|
+
globalEmbedderRef = e;
|
|
162
|
+
|
|
163
|
+
if (embeddersWithShutdownTask.has(e)) return;
|
|
164
|
+
embeddersWithShutdownTask.add(e);
|
|
165
|
+
|
|
166
|
+
// Register with shutdown manager for graceful extension shutdown.
|
|
167
|
+
shutdownManager.register(async () => {
|
|
168
|
+
if (globalEmbedderRef === e) {
|
|
169
|
+
const ref = globalEmbedderRef;
|
|
170
|
+
globalEmbedderRef = null;
|
|
171
|
+
try { await ref.dispose(); } catch { /* ignore */ }
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Unregister the global Embedder reference.
|
|
178
|
+
* Called by Embedder.dispose() once cleanup is complete.
|
|
179
|
+
*/
|
|
180
|
+
export function unregisterGlobalEmbedder(): void {
|
|
181
|
+
globalEmbedderRef = null;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Last-resort safety net: during beforeExit the C++ ORT LoggingManager is still
|
|
185
|
+
// alive, so async disposal is safe. session_shutdown should have already disposed
|
|
186
|
+
// the embedder; this only fires if somehow it didn't (e.g. a crash path).
|
|
187
|
+
// We do NOT register on 'exit' — by then C++ statics may already be destroyed.
|
|
188
|
+
const beforeExitHandler = () => {
|
|
189
|
+
if (globalEmbedderRef) {
|
|
190
|
+
const ref = globalEmbedderRef;
|
|
191
|
+
globalEmbedderRef = null;
|
|
192
|
+
// Fire async dispose — beforeExit allows scheduling async tasks.
|
|
193
|
+
ref.dispose().catch(() => {
|
|
194
|
+
// Silently ignore — process is shutting down, OS reclaims memory.
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Register the beforeExit safety-net handler.
|
|
201
|
+
* Must be called during each extension activation because deactivate()
|
|
202
|
+
* strips all registered event listeners. Module-level registration is
|
|
203
|
+
* insufficient — after a Pi reload the handler would be missing.
|
|
204
|
+
*/
|
|
205
|
+
export function registerBeforeExitSafetyNet(): void {
|
|
206
|
+
shutdownManager.registerEventListener(process, 'beforeExit', beforeExitHandler);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// ONNX / transformers.js env setup (getHFEnv, initializeONNXEnv) lives in
|
|
210
|
+
// ./onnx-env.ts so that this utility module stays free of the native
|
|
211
|
+
// @huggingface/transformers import — keeping it safe to load from src/index.ts.
|
|
212
|
+
|
|
213
|
+
let dawnInitialized = false;
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Names that identify a software / paravirtual / fallback GPU adapter — i.e. one
|
|
218
|
+
* on which onnxruntime-node's bundled Dawn will load but then SIGSEGV during the
|
|
219
|
+
* first compute dispatch. Matched case-insensitively against adapter info fields.
|
|
220
|
+
*/
|
|
221
|
+
const SOFTWARE_ADAPTER_PATTERNS = [
|
|
222
|
+
'llvmpipe',
|
|
223
|
+
'lavapipe',
|
|
224
|
+
'swiftshader',
|
|
225
|
+
'softpipe',
|
|
226
|
+
'basic render', // "Microsoft Basic Render Driver"
|
|
227
|
+
'microsoft basic',
|
|
228
|
+
'software',
|
|
229
|
+
'virtio', // virtio-gpu paravirtual (VMs)
|
|
230
|
+
'venus', // Mesa venus (virtio-gpu Vulkan)
|
|
231
|
+
'llvm',
|
|
232
|
+
];
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Verify WebGPU availability for the current Node.js environment.
|
|
236
|
+
*
|
|
237
|
+
* onnxruntime-node bundles Dawn natively as its WebGPU execution provider; on
|
|
238
|
+
* Linux this uses Vulkan. On hardware GPUs this works. On software/paravirtual
|
|
239
|
+
* Vulkan adapters (llvmpipe/lavapipe, virtio/venus, SwiftShader, ...) Dawn LOADS
|
|
240
|
+
* the pipeline but then crashes natively (SIGSEGV) on the first compute dispatch.
|
|
241
|
+
*
|
|
242
|
+
* This function is the in-process secondary guard for the FORCED 'webgpu' path
|
|
243
|
+
* (the 'auto' path is gated earlier by an out-of-process probe). When the
|
|
244
|
+
* optional 'webgpu' package is present we inspect the adapter and RETURN FALSE if
|
|
245
|
+
* it is a software/fallback adapter, so the caller can downgrade to CPU before
|
|
246
|
+
* any native compute runs. If the 'webgpu' package is absent we cannot inspect
|
|
247
|
+
* the adapter in-process and proceed (the out-of-process probe remains the real
|
|
248
|
+
* safeguard for 'auto').
|
|
249
|
+
*
|
|
250
|
+
* @returns true if WebGPU may proceed; false if a software/fallback adapter was
|
|
251
|
+
* detected and the caller should use CPU instead.
|
|
252
|
+
*/
|
|
253
|
+
export async function initializeDawnWebGPU(): Promise<boolean> {
|
|
254
|
+
if (dawnInitialized) return true;
|
|
255
|
+
|
|
256
|
+
try {
|
|
257
|
+
// @ts-ignore — optional dependency
|
|
258
|
+
const { create, globals } = await import('webgpu');
|
|
259
|
+
Object.assign(globalThis, globals);
|
|
260
|
+
// Use Object.defineProperty — Node.js defines navigator as a configurable getter
|
|
261
|
+
Object.defineProperty(globalThis, 'navigator', {
|
|
262
|
+
value: { gpu: create([]) },
|
|
263
|
+
writable: true,
|
|
264
|
+
configurable: true,
|
|
265
|
+
});
|
|
266
|
+
const adapter = await (globalThis as any).navigator.gpu.requestAdapter({ powerPreference: 'high-performance' });
|
|
267
|
+
|
|
268
|
+
if (!adapter) {
|
|
269
|
+
logger.warn('[embedder] No WebGPU adapter available — using CPU.');
|
|
270
|
+
return false;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const info = adapter.info ?? {};
|
|
274
|
+
const haystack = [info.vendor, info.architecture, info.device, info.description]
|
|
275
|
+
.filter(Boolean)
|
|
276
|
+
.join(' ')
|
|
277
|
+
.toLowerCase();
|
|
278
|
+
|
|
279
|
+
if (adapter.isFallbackAdapter === true || SOFTWARE_ADAPTER_PATTERNS.some((p) => haystack.includes(p))) {
|
|
280
|
+
logger.warn(
|
|
281
|
+
`[embedder] WebGPU adapter is software/paravirtual (${haystack || 'fallback'}) — Dawn would crash on compute; using CPU.`,
|
|
282
|
+
);
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
logger.info(`[embedder] WebGPU adapter: ${info.vendor ?? '?'} ${info.device ?? info.architecture ?? '?'}`);
|
|
287
|
+
} catch {
|
|
288
|
+
// 'webgpu' package not installed — cannot inspect the adapter in-process.
|
|
289
|
+
// onnxruntime-node's bundled Dawn EP still works without it on real hardware;
|
|
290
|
+
// for 'auto' the out-of-process probe already validated viability.
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
dawnInitialized = true;
|
|
294
|
+
logger.info('[embedder] WebGPU ready via onnxruntime-node bundled Dawn');
|
|
295
|
+
return true;
|
|
296
|
+
}
|