@lincoln504/pi-research 0.1.13 → 1.0.1
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 +55 -138
- package/dist/cli.mjs +23375 -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 +130 -0
- package/docs/ARCHITECTURE.md +306 -80
- package/docs/CONFIGURATION.md +249 -0
- package/docs/KNOWLEDGE-STORE.md +211 -0
- package/docs/PI-EXTENSION.md +91 -0
- package/docs/SDK.md +122 -0
- package/docs/THIRD-PARTY-NOTICES.md +66 -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 +1195 -0
- package/src/config.ts +1032 -155
- 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 +258 -11
- 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 -212
- package/src/infrastructure/searxng-lifecycle.ts +0 -644
- 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,282 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub Advisory API Types
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
// ============================================================================
|
|
6
|
+
// Type Definitions for Fetch API
|
|
7
|
+
// ============================================================================
|
|
8
|
+
|
|
9
|
+
type FetchType = (
|
|
10
|
+
_input: string | Request,
|
|
11
|
+
_init?: RequestInit,
|
|
12
|
+
) => Promise<Response>;
|
|
13
|
+
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
15
|
+
declare const fetch: FetchType;
|
|
16
|
+
|
|
17
|
+
interface Headers {
|
|
18
|
+
append(_name: string, _value: string): void;
|
|
19
|
+
delete(_name: string): void;
|
|
20
|
+
get(_name: string): string | null;
|
|
21
|
+
has(_name: string): boolean;
|
|
22
|
+
set(_name: string, _value: string): void;
|
|
23
|
+
forEach(_callback: (_value: string, _name: string) => void): void;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface Response {
|
|
27
|
+
readonly headers: Headers;
|
|
28
|
+
readonly ok: boolean;
|
|
29
|
+
readonly redirected: boolean;
|
|
30
|
+
readonly status: number;
|
|
31
|
+
readonly statusText: string;
|
|
32
|
+
readonly type: 'basic' | 'cors' | 'default' | 'error' | 'opaque' | 'opaqueredirect';
|
|
33
|
+
readonly url: string;
|
|
34
|
+
readonly body: ReadableStream<Uint8Array> | null;
|
|
35
|
+
readonly bodyUsed: boolean;
|
|
36
|
+
clone(): Response;
|
|
37
|
+
arrayBuffer(): Promise<ArrayBuffer>;
|
|
38
|
+
blob(): Promise<Blob>;
|
|
39
|
+
formData(): Promise<FormData>;
|
|
40
|
+
json(): Promise<unknown>;
|
|
41
|
+
text(): Promise<string>;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// ============================================================================
|
|
45
|
+
// Type Definitions for GitHub API Responses
|
|
46
|
+
// ============================================================================
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* GitHub Advisory Vulnerability Package
|
|
50
|
+
*/
|
|
51
|
+
export interface GitHubAdvisoryPackage {
|
|
52
|
+
readonly ecosystem?: string;
|
|
53
|
+
readonly name?: string;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* GitHub Advisory Affected Entry
|
|
58
|
+
*/
|
|
59
|
+
export interface GitHubAdvisoryAffected {
|
|
60
|
+
readonly package?: GitHubAdvisoryPackage;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* GitHub Advisory Vulnerability
|
|
65
|
+
*/
|
|
66
|
+
export interface GitHubAdvisoryVulnerability {
|
|
67
|
+
readonly package?: GitHubAdvisoryPackage;
|
|
68
|
+
readonly affected?: readonly GitHubAdvisoryAffected[];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Raw GitHub Advisory from API response
|
|
73
|
+
*/
|
|
74
|
+
export interface GitHubAdvisoryRaw {
|
|
75
|
+
readonly ghsa_id?: string;
|
|
76
|
+
readonly id?: string;
|
|
77
|
+
readonly summary?: string;
|
|
78
|
+
readonly description?: string;
|
|
79
|
+
readonly severity?: string;
|
|
80
|
+
readonly published_at?: string;
|
|
81
|
+
readonly updated_at?: string;
|
|
82
|
+
readonly cve_id?: string;
|
|
83
|
+
readonly html_url?: string;
|
|
84
|
+
readonly advisory_url?: string;
|
|
85
|
+
readonly vulnerabilities?: readonly GitHubAdvisoryVulnerability[];
|
|
86
|
+
readonly affected?: readonly GitHubAdvisoryAffected[];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* GitHub API list response wrapper
|
|
91
|
+
*/
|
|
92
|
+
export interface GitHubAdvisoryListResponse {
|
|
93
|
+
readonly items?: readonly GitHubAdvisoryRaw[];
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// ============================================================================
|
|
97
|
+
// Type Guards
|
|
98
|
+
// ============================================================================
|
|
99
|
+
|
|
100
|
+
export function isGitHubAdvisoryRaw(value: unknown): value is GitHubAdvisoryRaw {
|
|
101
|
+
return typeof value === 'object' && value !== null;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function isArray(value: unknown): value is readonly unknown[] {
|
|
105
|
+
return Array.isArray(value);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function isString(value: unknown): value is string {
|
|
109
|
+
return typeof value === 'string';
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function isObject(value: unknown): value is Record<string, unknown> {
|
|
113
|
+
return typeof value === 'object' && value !== null && !isArray(value);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function isGitHubAdvisoryPackage(value: unknown): value is GitHubAdvisoryPackage {
|
|
117
|
+
if (!isObject(value)) {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function isGitHubAdvisoryAffected(value: unknown): value is GitHubAdvisoryAffected {
|
|
124
|
+
if (!isObject(value)) {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export function isGitHubAdvisoryVulnerability(value: unknown): value is GitHubAdvisoryVulnerability {
|
|
131
|
+
if (!isObject(value)) {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export function isGitHubAdvisoryListResponse(value: unknown): value is GitHubAdvisoryListResponse {
|
|
138
|
+
if (!isObject(value)) {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
return 'items' in value;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function isGitHubAdvisoryArray(value: unknown): value is GitHubAdvisoryRaw[] {
|
|
145
|
+
if (!isArray(value)) {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
return value.every(isGitHubAdvisoryRaw);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export function isSingleGitHubAdvisory(value: unknown): value is GitHubAdvisoryRaw {
|
|
152
|
+
if (!isGitHubAdvisoryRaw(value)) {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
// Single advisory typically has ghsa_id
|
|
156
|
+
return 'ghsa_id' in value || 'summary' in value;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
import { type Advisory } from './types.ts';
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Extract affected packages from an advisory item
|
|
163
|
+
*/
|
|
164
|
+
function extractAffectedPackages(item: GitHubAdvisoryRaw): string[] {
|
|
165
|
+
const affectedPackages: string[] = [];
|
|
166
|
+
|
|
167
|
+
// Check for vulnerabilities array
|
|
168
|
+
if (item.vulnerabilities !== undefined && isArray(item.vulnerabilities)) {
|
|
169
|
+
for (const vuln of item.vulnerabilities) {
|
|
170
|
+
if (!isGitHubAdvisoryVulnerability(vuln)) {
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Check for package in various possible locations
|
|
175
|
+
if (vuln.package !== undefined) {
|
|
176
|
+
if (isGitHubAdvisoryPackage(vuln.package)) {
|
|
177
|
+
const ecosystem = vuln.package.ecosystem ?? '';
|
|
178
|
+
const name = vuln.package.name;
|
|
179
|
+
|
|
180
|
+
if (isString(name) && name !== '') {
|
|
181
|
+
if (ecosystem !== '') {
|
|
182
|
+
affectedPackages.push(`${ecosystem}/${name}`);
|
|
183
|
+
} else {
|
|
184
|
+
affectedPackages.push(name);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
} else if (vuln.affected !== undefined && isArray(vuln.affected)) {
|
|
189
|
+
// Alternative structure with 'affected' array
|
|
190
|
+
for (const aff of vuln.affected) {
|
|
191
|
+
if (isGitHubAdvisoryAffected(aff) && aff.package !== undefined) {
|
|
192
|
+
const pkg = aff.package;
|
|
193
|
+
if (isGitHubAdvisoryPackage(pkg)) {
|
|
194
|
+
const ecosystem = pkg.ecosystem ?? '';
|
|
195
|
+
const name = pkg.name;
|
|
196
|
+
|
|
197
|
+
if (isString(name) && name !== '') {
|
|
198
|
+
if (ecosystem !== '') {
|
|
199
|
+
affectedPackages.push(`${ecosystem}/${name}`);
|
|
200
|
+
} else {
|
|
201
|
+
affectedPackages.push(name);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Check for direct 'affected' array at the top level
|
|
212
|
+
if (affectedPackages.length === 0 && item.affected !== undefined && isArray(item.affected)) {
|
|
213
|
+
for (const aff of item.affected) {
|
|
214
|
+
if (isGitHubAdvisoryAffected(aff) && aff.package !== undefined) {
|
|
215
|
+
const pkg = aff.package;
|
|
216
|
+
if (isGitHubAdvisoryPackage(pkg)) {
|
|
217
|
+
const ecosystem = pkg.ecosystem ?? '';
|
|
218
|
+
const name = pkg.name;
|
|
219
|
+
|
|
220
|
+
if (isString(name) && name !== '') {
|
|
221
|
+
if (ecosystem !== '') {
|
|
222
|
+
affectedPackages.push(`${ecosystem}/${name}`);
|
|
223
|
+
} else {
|
|
224
|
+
affectedPackages.push(name);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return affectedPackages;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Extract references from an advisory item
|
|
237
|
+
*/
|
|
238
|
+
export function extractReferences(item: GitHubAdvisoryRaw): string[] {
|
|
239
|
+
const references: string[] = [];
|
|
240
|
+
|
|
241
|
+
if (item.html_url !== undefined && item.html_url !== '') {
|
|
242
|
+
references.push(item.html_url);
|
|
243
|
+
}
|
|
244
|
+
if (item.advisory_url !== undefined && item.advisory_url !== '') {
|
|
245
|
+
references.push(item.advisory_url);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return references;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Map GitHub advisory to our Advisory interface
|
|
253
|
+
*/
|
|
254
|
+
export function mapGitHubAdvisory(item: GitHubAdvisoryRaw): Advisory {
|
|
255
|
+
const ghsaId = item.ghsa_id ?? item.id ?? '';
|
|
256
|
+
const summary = item.summary ?? '';
|
|
257
|
+
const description = item.description ?? '';
|
|
258
|
+
// Guard the type: isGitHubAdvisoryRaw validates only that the value is an object, so a
|
|
259
|
+
// non-string severity (schema drift / numeric code) would throw on .toUpperCase() inside
|
|
260
|
+
// the unguarded items.map(), failing the whole term in Promise.allSettled and discarding
|
|
261
|
+
// every advisory for it.
|
|
262
|
+
const severity = typeof item.severity === 'string' ? item.severity.toUpperCase() : 'UNKNOWN';
|
|
263
|
+
const published = item.published_at ?? '';
|
|
264
|
+
const modified = item.updated_at ?? '';
|
|
265
|
+
const cveId = item.cve_id ?? '';
|
|
266
|
+
|
|
267
|
+
const affectedPackages = extractAffectedPackages(item);
|
|
268
|
+
const references = extractReferences(item);
|
|
269
|
+
|
|
270
|
+
return {
|
|
271
|
+
id: ghsaId,
|
|
272
|
+
source: 'github',
|
|
273
|
+
severity,
|
|
274
|
+
summary,
|
|
275
|
+
description,
|
|
276
|
+
published,
|
|
277
|
+
modified,
|
|
278
|
+
cveId,
|
|
279
|
+
references,
|
|
280
|
+
affectedPackages,
|
|
281
|
+
};
|
|
282
|
+
}
|
package/src/security/index.ts
CHANGED
|
@@ -22,11 +22,12 @@ import type {
|
|
|
22
22
|
GitHubResult,
|
|
23
23
|
OSVResult,
|
|
24
24
|
} from './types.ts';
|
|
25
|
-
import {
|
|
26
|
-
import { searchNVD } from './nvd.ts';
|
|
25
|
+
import { REQUEST_DELAY_MS_NVD, REQUEST_DELAY_MS_OTHER } from '../constants.ts';
|
|
26
|
+
import { searchNVD } from './nvd-client.ts';
|
|
27
27
|
import { searchCisaKev } from './cisa-kev.ts';
|
|
28
28
|
import { searchGitHubAdvisories } from './github-advisories.ts';
|
|
29
|
-
import { searchOSV } from './osv.ts';
|
|
29
|
+
import { searchOSV } from './osv-client.ts';
|
|
30
|
+
import { safeUnref } from '../utils/safe-unref.ts';
|
|
30
31
|
|
|
31
32
|
// ============================================================================
|
|
32
33
|
// Type Definitions
|
|
@@ -50,9 +51,6 @@ interface DatabaseInfoEntry {
|
|
|
50
51
|
// Helper Functions
|
|
51
52
|
// ============================================================================
|
|
52
53
|
|
|
53
|
-
/**
|
|
54
|
-
* Type guard to check if a value is a valid Severity
|
|
55
|
-
*/
|
|
56
54
|
function isValidSeverity(value: unknown): value is Severity {
|
|
57
55
|
return (
|
|
58
56
|
typeof value === 'string' &&
|
|
@@ -60,64 +58,44 @@ function isValidSeverity(value: unknown): value is Severity {
|
|
|
60
58
|
);
|
|
61
59
|
}
|
|
62
60
|
|
|
63
|
-
/**
|
|
64
|
-
* Safely extract severity from params, returning undefined if invalid
|
|
65
|
-
*/
|
|
66
61
|
function getSeverityParam(params: SecuritySearchParams): Severity | undefined {
|
|
67
|
-
if (params.severity === undefined)
|
|
68
|
-
return undefined;
|
|
69
|
-
}
|
|
62
|
+
if (params.severity === undefined) return undefined;
|
|
70
63
|
return isValidSeverity(params.severity) ? params.severity : undefined;
|
|
71
64
|
}
|
|
72
65
|
|
|
73
|
-
/**
|
|
74
|
-
* Safely extract error message from unknown error
|
|
75
|
-
*/
|
|
76
66
|
function getErrorMessage(error: unknown): string {
|
|
77
|
-
if (error instanceof Error)
|
|
78
|
-
return error.message;
|
|
79
|
-
}
|
|
67
|
+
if (error instanceof Error) return error.message;
|
|
80
68
|
return String(error);
|
|
81
69
|
}
|
|
82
70
|
|
|
83
71
|
// ============================================================================
|
|
84
|
-
// Security Searcher Class
|
|
72
|
+
// Security Searcher Class
|
|
85
73
|
// ============================================================================
|
|
86
74
|
|
|
87
|
-
/**
|
|
88
|
-
* Configuration for SecuritySearcher
|
|
89
|
-
*/
|
|
90
75
|
export interface SecuritySearcherConfig {
|
|
91
76
|
readonly nvdClient?: INVDClient;
|
|
92
77
|
readonly cisaKevClient?: ICisaKevClient;
|
|
93
78
|
readonly githubAdvisoriesClient?: IGitHubAdvisoriesClient;
|
|
94
79
|
readonly osvClient?: IOSVClient;
|
|
95
|
-
readonly requestDelay?: number; //
|
|
80
|
+
readonly requestDelay?: number; // Override for testing
|
|
96
81
|
}
|
|
97
82
|
|
|
98
|
-
const DEFAULT_CONFIG:
|
|
99
|
-
nvdClient:
|
|
100
|
-
cisaKevClient:
|
|
101
|
-
githubAdvisoriesClient:
|
|
102
|
-
osvClient:
|
|
103
|
-
requestDelay:
|
|
83
|
+
const DEFAULT_CONFIG: SecuritySearcherConfig = {
|
|
84
|
+
nvdClient: undefined,
|
|
85
|
+
cisaKevClient: undefined,
|
|
86
|
+
githubAdvisoriesClient: undefined,
|
|
87
|
+
osvClient: undefined,
|
|
88
|
+
requestDelay: -1, // Use database-specific logic by default
|
|
104
89
|
};
|
|
105
90
|
|
|
106
|
-
/**
|
|
107
|
-
* SecuritySearcher - orchestrates searches across multiple security databases
|
|
108
|
-
* Uses dependency injection for testability
|
|
109
|
-
*/
|
|
110
91
|
export class SecuritySearcher {
|
|
111
|
-
private readonly config:
|
|
92
|
+
private readonly config: SecuritySearcherConfig;
|
|
112
93
|
|
|
113
94
|
constructor(config: Partial<SecuritySearcherConfig> = {}) {
|
|
114
95
|
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
115
96
|
}
|
|
116
97
|
|
|
117
|
-
|
|
118
|
-
* Main search function that queries multiple security databases
|
|
119
|
-
*/
|
|
120
|
-
async search(params: SecuritySearchParams): Promise<SecuritySearchResult> {
|
|
98
|
+
async search(params: SecuritySearchParams, signal?: AbortSignal): Promise<SecuritySearchResult> {
|
|
121
99
|
const startTime = Date.now();
|
|
122
100
|
const results: { nvd?: NVDResult; cisa_kev?: CisaKevResult; github?: GitHubResult; osv?: OSVResult } = {};
|
|
123
101
|
const errors: string[] = [];
|
|
@@ -125,24 +103,17 @@ export class SecuritySearcher {
|
|
|
125
103
|
|
|
126
104
|
const searchPromises: Promise<void>[] = [];
|
|
127
105
|
|
|
128
|
-
// Search each requested database in parallel
|
|
129
106
|
if (params.databases.includes('nvd')) {
|
|
130
107
|
searchPromises.push((async () => {
|
|
131
108
|
try {
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
params.terms,
|
|
135
|
-
{
|
|
136
|
-
severity: severity,
|
|
109
|
+
const nvdResult = await this.searchNVD(params.terms, {
|
|
110
|
+
severity: getSeverityParam(params),
|
|
137
111
|
maxResults: params.maxResults,
|
|
138
112
|
includeExploited: params.includeExploited,
|
|
139
|
-
|
|
140
|
-
);
|
|
113
|
+
signal,
|
|
114
|
+
});
|
|
141
115
|
results.nvd = nvdResult;
|
|
142
116
|
totalVulnerabilities += nvdResult.count;
|
|
143
|
-
if (nvdResult.error !== undefined) {
|
|
144
|
-
errors.push(`NVD: ${nvdResult.error}`);
|
|
145
|
-
}
|
|
146
117
|
} catch (err: unknown) {
|
|
147
118
|
errors.push(`NVD: ${getErrorMessage(err)}`);
|
|
148
119
|
}
|
|
@@ -152,14 +123,9 @@ export class SecuritySearcher {
|
|
|
152
123
|
if (params.databases.includes('cisa_kev')) {
|
|
153
124
|
searchPromises.push((async () => {
|
|
154
125
|
try {
|
|
155
|
-
const cisaResult = await this.searchCisaKev(params.terms, {
|
|
156
|
-
maxResults: params.maxResults,
|
|
157
|
-
});
|
|
126
|
+
const cisaResult = await this.searchCisaKev(params.terms, { maxResults: params.maxResults, signal });
|
|
158
127
|
results.cisa_kev = cisaResult;
|
|
159
128
|
totalVulnerabilities += cisaResult.count;
|
|
160
|
-
if (cisaResult.error !== undefined) {
|
|
161
|
-
errors.push(`CISA KEV: ${cisaResult.error}`);
|
|
162
|
-
}
|
|
163
129
|
} catch (err: unknown) {
|
|
164
130
|
errors.push(`CISA KEV: ${getErrorMessage(err)}`);
|
|
165
131
|
}
|
|
@@ -174,12 +140,10 @@ export class SecuritySearcher {
|
|
|
174
140
|
severity: params.severity,
|
|
175
141
|
maxResults: params.maxResults,
|
|
176
142
|
repo: params.githubRepo,
|
|
143
|
+
signal,
|
|
177
144
|
});
|
|
178
145
|
results.github = githubResult;
|
|
179
146
|
totalVulnerabilities += githubResult.count;
|
|
180
|
-
if (githubResult.error !== undefined) {
|
|
181
|
-
errors.push(`GitHub: ${githubResult.error}`);
|
|
182
|
-
}
|
|
183
147
|
} catch (err: unknown) {
|
|
184
148
|
errors.push(`GitHub: ${getErrorMessage(err)}`);
|
|
185
149
|
}
|
|
@@ -193,36 +157,45 @@ export class SecuritySearcher {
|
|
|
193
157
|
ecosystem: params.ecosystem,
|
|
194
158
|
severity: params.severity,
|
|
195
159
|
maxResults: params.maxResults,
|
|
160
|
+
signal,
|
|
196
161
|
});
|
|
197
162
|
results.osv = osvResult;
|
|
198
163
|
totalVulnerabilities += osvResult.count;
|
|
199
|
-
if (osvResult.error !== undefined) {
|
|
200
|
-
errors.push(`OSV: ${osvResult.error}`);
|
|
201
|
-
}
|
|
202
164
|
} catch (err: unknown) {
|
|
203
165
|
errors.push(`OSV: ${getErrorMessage(err)}`);
|
|
204
166
|
}
|
|
205
167
|
})());
|
|
206
168
|
}
|
|
207
169
|
|
|
208
|
-
// Wait for all searches to complete
|
|
209
170
|
await Promise.all(searchPromises);
|
|
210
171
|
|
|
211
|
-
// Apply delay
|
|
212
|
-
|
|
172
|
+
// Apply delay
|
|
173
|
+
let delay = this.config.requestDelay ?? -1;
|
|
174
|
+
if (delay === -1) {
|
|
175
|
+
delay = params.databases.includes('nvd') ? REQUEST_DELAY_MS_NVD : REQUEST_DELAY_MS_OTHER;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (delay > 0) {
|
|
179
|
+
// Abortable: a caller cancel must not sit through the post-sweep delay.
|
|
213
180
|
await new Promise<void>((resolve) => {
|
|
214
|
-
const timeoutId = setTimeout(
|
|
215
|
-
|
|
181
|
+
const timeoutId = setTimeout(() => {
|
|
182
|
+
signal?.removeEventListener('abort', onAbort);
|
|
183
|
+
resolve();
|
|
184
|
+
}, delay);
|
|
185
|
+
safeUnref(timeoutId);
|
|
186
|
+
const onAbort = () => { clearTimeout(timeoutId); resolve(); };
|
|
187
|
+
if (signal) signal.addEventListener('abort', onAbort, { once: true });
|
|
216
188
|
});
|
|
217
189
|
}
|
|
218
190
|
|
|
219
|
-
const duration = Date.now() - startTime;
|
|
220
|
-
|
|
221
191
|
return {
|
|
222
192
|
results,
|
|
223
193
|
totalDatabases: Object.keys(results).length,
|
|
224
194
|
totalVulnerabilities,
|
|
225
|
-
duration,
|
|
195
|
+
duration: Date.now() - startTime,
|
|
196
|
+
// Surface databases that threw (vs returned an error field) so a dropped source is visible
|
|
197
|
+
// rather than silently omitted and mistaken for a clean "no results" from that database.
|
|
198
|
+
...(errors.length > 0 ? { errors } : {}),
|
|
226
199
|
};
|
|
227
200
|
}
|
|
228
201
|
|
|
@@ -248,18 +221,13 @@ export class SecuritySearcher {
|
|
|
248
221
|
}
|
|
249
222
|
|
|
250
223
|
// ============================================================================
|
|
251
|
-
// Default Client Implementations
|
|
224
|
+
// Default Client Implementations
|
|
252
225
|
// ============================================================================
|
|
253
226
|
|
|
254
227
|
class DefaultNVDClient implements INVDClient {
|
|
255
|
-
async search(terms: readonly string[], options?: NVDSearchOptions): Promise<
|
|
228
|
+
async search(terms: readonly string[], options?: NVDSearchOptions): Promise<NVDResult> {
|
|
256
229
|
return searchNVD(terms as string[], options);
|
|
257
230
|
}
|
|
258
|
-
|
|
259
|
-
async getById(cveId: string): Promise<import('./types.ts').Vulnerability | null> {
|
|
260
|
-
const { getCVEById } = await import('./nvd.ts');
|
|
261
|
-
return getCVEById(cveId);
|
|
262
|
-
}
|
|
263
231
|
}
|
|
264
232
|
|
|
265
233
|
class DefaultCisaKevClient implements ICisaKevClient {
|
|
@@ -269,138 +237,56 @@ class DefaultCisaKevClient implements ICisaKevClient {
|
|
|
269
237
|
}
|
|
270
238
|
|
|
271
239
|
class DefaultGitHubClient implements IGitHubAdvisoriesClient {
|
|
272
|
-
async search(terms: readonly string[], options?: GitHubSearchOptions): Promise<
|
|
240
|
+
async search(terms: readonly string[], options?: GitHubSearchOptions): Promise<GitHubResult> {
|
|
273
241
|
return searchGitHubAdvisories(terms as string[], options);
|
|
274
242
|
}
|
|
275
|
-
|
|
276
|
-
async getById(id: string): Promise<import('./types.ts').Advisory | null> {
|
|
277
|
-
const { getAdvisoryById } = await import('./github-advisories.ts');
|
|
278
|
-
return getAdvisoryById(id);
|
|
279
|
-
}
|
|
280
243
|
}
|
|
281
244
|
|
|
282
245
|
class DefaultOSVClient implements IOSVClient {
|
|
283
|
-
async search(terms: readonly string[], options?: OSVSearchOptions): Promise<
|
|
246
|
+
async search(terms: readonly string[], options?: OSVSearchOptions): Promise<OSVResult> {
|
|
284
247
|
return searchOSV(terms as string[], options);
|
|
285
248
|
}
|
|
286
|
-
|
|
287
|
-
async getById(osvId: string): Promise<import('./types.ts').Vulnerability | null> {
|
|
288
|
-
const { getOSVById } = await import('./osv.ts');
|
|
289
|
-
return getOSVById(osvId);
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
// Default client factories
|
|
294
|
-
function createDefaultNVDClient(): INVDClient {
|
|
295
|
-
return new DefaultNVDClient();
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
function createDefaultCisaKevClient(): ICisaKevClient {
|
|
299
|
-
return new DefaultCisaKevClient();
|
|
300
249
|
}
|
|
301
250
|
|
|
302
|
-
function
|
|
303
|
-
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
function createDefaultOSVClient(): IOSVClient {
|
|
307
|
-
return new DefaultOSVClient();
|
|
308
|
-
}
|
|
251
|
+
function createDefaultNVDClient(): INVDClient { return new DefaultNVDClient(); }
|
|
252
|
+
function createDefaultCisaKevClient(): ICisaKevClient { return new DefaultCisaKevClient(); }
|
|
253
|
+
function createDefaultGitHubClient(): IGitHubAdvisoriesClient { return new DefaultGitHubClient(); }
|
|
254
|
+
function createDefaultOSVClient(): IOSVClient { return new DefaultOSVClient(); }
|
|
309
255
|
|
|
310
256
|
// ============================================================================
|
|
311
|
-
// Global State
|
|
257
|
+
// Global State
|
|
312
258
|
// ============================================================================
|
|
313
259
|
|
|
314
260
|
let globalSearcher: SecuritySearcher | null = null;
|
|
315
261
|
|
|
316
|
-
|
|
317
|
-
* Create a new security searcher instance
|
|
318
|
-
*/
|
|
319
|
-
export function createSecuritySearcher(
|
|
320
|
-
config: Partial<SecuritySearcherConfig> = {}
|
|
321
|
-
): SecuritySearcher {
|
|
262
|
+
export function createSecuritySearcher(config: Partial<SecuritySearcherConfig> = {}): SecuritySearcher {
|
|
322
263
|
return new SecuritySearcher(config);
|
|
323
264
|
}
|
|
324
265
|
|
|
325
|
-
/**
|
|
326
|
-
* Get the global security searcher instance
|
|
327
|
-
*/
|
|
328
266
|
export function getSecuritySearcher(): SecuritySearcher {
|
|
329
|
-
if (!globalSearcher)
|
|
330
|
-
globalSearcher = new SecuritySearcher();
|
|
331
|
-
}
|
|
267
|
+
if (!globalSearcher) globalSearcher = new SecuritySearcher();
|
|
332
268
|
return globalSearcher;
|
|
333
269
|
}
|
|
334
270
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
*/
|
|
338
|
-
export function setSecuritySearcher(searcher: SecuritySearcher | null): void {
|
|
339
|
-
globalSearcher = searcher;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
/**
|
|
343
|
-
* Reset the global security searcher instance (for testing)
|
|
344
|
-
*/
|
|
345
|
-
export function resetSecuritySearcher(): void {
|
|
346
|
-
globalSearcher = null;
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
// ============================================================================
|
|
350
|
-
// Backward Compatibility Functions
|
|
351
|
-
// ============================================================================
|
|
271
|
+
export function setSecuritySearcher(searcher: SecuritySearcher | null): void { globalSearcher = searcher; }
|
|
272
|
+
export function resetSecuritySearcher(): void { globalSearcher = null; }
|
|
352
273
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
* @deprecated Use SecuritySearcher class directly for better testability
|
|
356
|
-
*/
|
|
357
|
-
export async function searchSecurityDatabases(
|
|
358
|
-
params: SecuritySearchParams,
|
|
359
|
-
): Promise<SecuritySearchResult> {
|
|
360
|
-
const searcher = getSecuritySearcher();
|
|
361
|
-
return searcher.search(params);
|
|
274
|
+
export async function searchSecurityDatabases(params: SecuritySearchParams, signal?: AbortSignal): Promise<SecuritySearchResult> {
|
|
275
|
+
return getSecuritySearcher().search(params, signal);
|
|
362
276
|
}
|
|
363
277
|
|
|
364
|
-
/**
|
|
365
|
-
* Get database info for UI
|
|
366
|
-
*/
|
|
367
278
|
export function getDatabaseInfo(): DatabaseInfo {
|
|
368
279
|
return {
|
|
369
280
|
databases: [
|
|
370
|
-
{
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
url: 'https://nvd.nist.gov',
|
|
375
|
-
free: true,
|
|
376
|
-
},
|
|
377
|
-
{
|
|
378
|
-
id: 'cisa_kev',
|
|
379
|
-
name: 'CISA KEV Catalog',
|
|
380
|
-
description: 'Known Exploited Vulnerabilities - actively exploited vulnerabilities',
|
|
381
|
-
url: 'https://www.cisa.gov/known-exploited-vulnerabilities-catalog',
|
|
382
|
-
free: true,
|
|
383
|
-
},
|
|
384
|
-
{
|
|
385
|
-
id: 'github',
|
|
386
|
-
name: 'GitHub Advisory Database',
|
|
387
|
-
description: 'GitHub Security Advisories - open source security advisories',
|
|
388
|
-
url: 'https://github.com/advisories',
|
|
389
|
-
free: true,
|
|
390
|
-
},
|
|
391
|
-
{
|
|
392
|
-
id: 'osv',
|
|
393
|
-
name: 'Open Source Vulnerabilities',
|
|
394
|
-
description: 'OSV - open source package vulnerabilities',
|
|
395
|
-
url: 'https://osv.dev',
|
|
396
|
-
free: true,
|
|
397
|
-
},
|
|
281
|
+
{ id: 'nvd', name: 'NIST NVD', description: 'National Vulnerability Database', url: 'https://nvd.nist.gov', free: true },
|
|
282
|
+
{ id: 'cisa_kev', name: 'CISA KEV Catalog', description: 'Known Exploited Vulnerabilities', url: 'https://www.cisa.gov', free: true },
|
|
283
|
+
{ id: 'github', name: 'GitHub Advisory Database', description: 'GitHub Security Advisories', url: 'https://github.com/advisories', free: true },
|
|
284
|
+
{ id: 'osv', name: 'Open Source Vulnerabilities', description: 'OSV - open source package vulnerabilities', url: 'https://osv.dev', free: true },
|
|
398
285
|
] as const,
|
|
399
286
|
};
|
|
400
287
|
}
|
|
401
288
|
|
|
402
|
-
|
|
403
|
-
export { searchNVD } from './nvd.ts';
|
|
289
|
+
export { searchNVD } from './nvd-client.ts';
|
|
404
290
|
export { searchCisaKev } from './cisa-kev.ts';
|
|
405
291
|
export { searchGitHubAdvisories } from './github-advisories.ts';
|
|
406
|
-
export { searchOSV } from './osv.ts';
|
|
292
|
+
export { searchOSV } from './osv-client.ts';
|