@devilsdev/rag-pipeline-utils 2.4.4 → 2.5.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/.ragrc.schema.json +83 -192
- package/CHANGELOG.md +345 -0
- package/README.md +418 -117
- package/SECURITY.md +5 -5
- package/dist/experimental.cjs +2 -0
- package/dist/experimental.d.ts +1 -0
- package/dist/experimental.mjs +5 -0
- package/dist/index.cjs +4992 -1242
- package/dist/index.d.ts +80 -2
- package/dist/index.mjs +1 -1
- package/dist/types/agentic/agentic-pipeline.d.ts +103 -0
- package/dist/types/agentic/iterative-retriever.d.ts +85 -0
- package/dist/types/agentic/query-planner.d.ts +145 -0
- package/dist/types/agentic/self-critique.d.ts +45 -0
- package/dist/types/ai/adaptive-retrieval.d.ts +44 -0
- package/dist/types/ai/federation/federated-learning-coordinator.d.ts +62 -0
- package/dist/types/ai/multimodal-processing.d.ts +32 -0
- package/dist/types/ai/multimodal.d.ts +39 -0
- package/dist/types/ai/retrieval-engine.d.ts +37 -0
- package/dist/types/ai/training/model-training-orchestrator.d.ts +31 -0
- package/dist/types/chunking/chunking-engine.d.ts +70 -0
- package/dist/types/chunking/strategies/fixed-size.d.ts +17 -0
- package/dist/types/chunking/strategies/recursive.d.ts +20 -0
- package/dist/types/chunking/strategies/semantic.d.ts +19 -0
- package/dist/types/chunking/strategies/sentence.d.ts +13 -0
- package/dist/types/chunking/strategies/structure-aware.d.ts +19 -0
- package/dist/types/citation/citation-tracker.d.ts +64 -0
- package/dist/types/citation/hallucination-detector.d.ts +40 -0
- package/dist/types/citation/source-mapper.d.ts +37 -0
- package/dist/types/connectors/anthropic-connector.d.ts +92 -0
- package/dist/types/connectors/base-connector.d.ts +87 -0
- package/dist/types/connectors/cohere-connector.d.ts +89 -0
- package/dist/types/connectors/connector-utils.d.ts +110 -0
- package/dist/types/connectors/local-embedder.d.ts +86 -0
- package/dist/types/connectors/memory-retriever.d.ts +91 -0
- package/dist/types/connectors/ollama-connector.d.ts +110 -0
- package/dist/types/connectors/openai-connector.d.ts +114 -0
- package/dist/types/connectors/rag-prompt.d.ts +40 -0
- package/dist/types/cost/cost-calculator.d.ts +152 -0
- package/dist/types/cost/cost-tracker.d.ts +126 -0
- package/dist/types/cost/token-budget.d.ts +110 -0
- package/dist/types/dag/core/error-context.d.ts +239 -0
- package/dist/types/dag/core/execution-scheduler.d.ts +191 -0
- package/dist/types/dag/core/topology-validation.d.ts +226 -0
- package/dist/types/dag/dag-engine.d.ts +156 -0
- package/dist/types/dag/dag-node.d.ts +37 -0
- package/dist/types/dashboard/dashboard-generator.d.ts +127 -0
- package/dist/types/dashboard/metrics-aggregator.d.ts +218 -0
- package/dist/types/debug/execution-tracer.d.ts +57 -0
- package/dist/types/debug/trace-inspector.d.ts +31 -0
- package/dist/types/ecosystem/plugin-certification.d.ts +169 -0
- package/dist/types/enterprise/data-governance.d.ts +203 -0
- package/dist/types/enterprise/multi-tenancy.d.ts +137 -0
- package/dist/types/enterprise/sso-integration.d.ts +420 -0
- package/dist/types/evaluate/context-metrics.d.ts +55 -0
- package/dist/types/evaluate/faithfulness.d.ts +41 -0
- package/dist/types/evaluate/groundedness.d.ts +60 -0
- package/dist/types/evaluate/pipeline-evaluator.d.ts +88 -0
- package/dist/types/evaluate/relevance.d.ts +21 -0
- package/dist/types/evaluate/scoring.d.ts +123 -0
- package/dist/types/experimental.d.ts +15 -0
- package/dist/types/graph/entity-extractor.d.ts +84 -0
- package/dist/types/graph/graph-index.d.ts +49 -0
- package/dist/types/graph/graph-retriever.d.ts +81 -0
- package/dist/types/graph/knowledge-graph.d.ts +129 -0
- package/dist/types/guardrails/guardrails-pipeline.d.ts +63 -0
- package/dist/types/guardrails/injection-detector.d.ts +47 -0
- package/dist/types/guardrails/post-generation-guard.d.ts +61 -0
- package/dist/types/guardrails/pre-retrieval-guard.d.ts +64 -0
- package/dist/types/guardrails/retrieval-guard.d.ts +57 -0
- package/dist/types/mcp/mcp-server.d.ts +85 -0
- package/dist/types/mcp/mcp-tool-builder.d.ts +55 -0
- package/dist/types/reranker/cascade-reranker.d.ts +40 -0
- package/dist/types/reranker/embedding-reranker.d.ts +77 -0
- package/dist/types/reranker/scoring-reranker.d.ts +41 -0
- package/dist/types/retrieval/bm25-search.d.ts +43 -0
- package/dist/types/retrieval/file-vector-store.d.ts +87 -0
- package/dist/types/retrieval/hybrid-retriever.d.ts +35 -0
- package/dist/types/retrieval/rank-fusion.d.ts +10 -0
- package/dist/types/security/jwt-config.d.ts +80 -0
- package/dist/types/security/jwt-validator.d.ts +195 -0
- package/dist/types/security/plugin-sandbox.d.ts +158 -0
- package/dist/types/security/plugin-signature-verifier.d.ts +139 -0
- package/dist/types/security/validator.d.ts +5 -0
- package/dist/types/streaming/embedding-stream.d.ts +65 -0
- package/dist/types/streaming/sse-adapter.d.ts +59 -0
- package/dist/types/streaming/stream-router.d.ts +88 -0
- package/dist/types/streaming/streaming-embedder.d.ts +99 -0
- package/dist/types/streaming/websocket-adapter.d.ts +71 -0
- package/dist/types/templates/scaffold.d.ts +55 -0
- package/dist/types/templates/template-registry.d.ts +63 -0
- package/dist/types/utils/embed-query.d.ts +20 -0
- package/dist/types/utils/logger.d.ts +50 -0
- package/dist/types/utils/rate-limiter.d.ts +66 -0
- package/dist/types/utils/retry.d.ts +27 -0
- package/dist/types/utils/run-abort.d.ts +34 -0
- package/dist/types/utils/secure-logging.d.ts +51 -0
- package/dist/types/utils/structured-logger.d.ts +126 -0
- package/package.json +53 -29
- package/src/agentic/agentic-pipeline.js +75 -7
- package/src/agentic/iterative-retriever.js +47 -10
- package/src/agentic/query-planner.js +329 -78
- package/src/citation/citation-tracker.js +6 -4
- package/src/citation/hallucination-detector.js +2 -2
- package/src/citation/source-mapper.js +15 -28
- package/src/cli/commands/ai.js +101 -0
- package/src/cli/commands/plugin-hub/event-handlers.js +6 -0
- package/src/cli/commands/plugin-hub/hub-commands.js +0 -74
- package/src/cli/commands/plugin-hub/local-commands.js +143 -0
- package/src/cli/commands/plugin-hub.js +96 -36
- package/src/cli/diagnostics/config-checker.js +76 -63
- package/src/cli/diagnostics/environment-checker.js +62 -31
- package/src/cli/diagnostics/plugin-checker.js +36 -89
- package/src/cli/doctor-command.js +39 -5
- package/src/cli/enhanced-cli-commands.js +72 -217
- package/src/cli/handlers/ai-handler.js +364 -0
- package/src/cli/handlers/diagnostics-handler.js +78 -31
- package/src/cli/handlers/ingest-handler.js +28 -22
- package/src/cli/handlers/init-handler.js +148 -25
- package/src/cli/handlers/query-handler.js +41 -26
- package/src/cli/handlers/run-handler.js +16 -167
- package/src/cli/handlers/serve-handler.js +60 -0
- package/src/cli/services/bench-stats.js +54 -0
- package/src/cli/services/benchmark.js +161 -0
- package/src/cli/services/feedback.js +155 -0
- package/src/cli/services/rag-service.js +322 -0
- package/src/cli/shared/cli-utils.js +24 -7
- package/src/cli/shared/config-context.js +21 -0
- package/src/cli/wizard/config-builder.js +81 -0
- package/src/cli/wizard/init-wizard.js +617 -0
- package/src/config/component-factory.js +125 -0
- package/src/config/load-config.js +29 -10
- package/src/config/load-plugin-config.js +46 -2
- package/src/connectors/anthropic-connector.js +93 -55
- package/src/connectors/base-connector.js +74 -19
- package/src/connectors/cohere-connector.js +88 -32
- package/src/connectors/connector-utils.js +302 -0
- package/src/connectors/local-embedder.js +43 -5
- package/src/connectors/memory-retriever.js +108 -15
- package/src/connectors/ollama-connector.js +83 -49
- package/src/connectors/openai-connector.js +108 -44
- package/src/connectors/rag-prompt.js +88 -0
- package/src/core/create-pipeline.js +209 -60
- package/src/core/plugin-registry.js +87 -11
- package/src/cost/cost-calculator.js +205 -32
- package/src/dev/dev-server.js +166 -11
- package/src/dev/hot-reload.js +40 -1
- package/src/ecosystem/plugin-checks.js +181 -0
- package/src/ecosystem/plugin-hub.js +50 -125
- package/src/ecosystem/plugin-installer.js +298 -0
- package/src/ecosystem/plugin-probe.js +127 -0
- package/src/ecosystem/plugin-scanner.js +185 -0
- package/src/ecosystem/tar-extract.js +114 -0
- package/src/enterprise/audit-logging.js +158 -29
- package/src/enterprise/sso-integration.js +715 -228
- package/src/evaluate/context-metrics.js +28 -16
- package/src/evaluate/evaluator.js +3 -3
- package/src/evaluate/faithfulness.js +18 -14
- package/src/evaluate/groundedness.js +43 -12
- package/src/evaluate/pipeline-evaluator.js +35 -8
- package/src/evaluate/scoring.js +251 -3
- package/src/experimental.js +71 -0
- package/src/guardrails/guardrails-pipeline.js +69 -7
- package/src/guardrails/injection-detector.js +283 -0
- package/src/guardrails/post-generation-guard.js +19 -0
- package/src/guardrails/pre-retrieval-guard.js +36 -36
- package/src/guardrails/retrieval-guard.js +58 -8
- package/src/index.js +36 -1
- package/src/loader/document-reader.js +91 -0
- package/src/reranker/cascade-reranker.js +3 -0
- package/src/reranker/embedding-reranker.js +136 -21
- package/src/reranker/llm-reranker.js +79 -12
- package/src/reranker/scoring-reranker.js +3 -0
- package/src/retrieval/bm25-search.js +12 -6
- package/src/retrieval/file-vector-store.js +212 -0
- package/src/retrieval/hybrid-retriever.js +22 -19
- package/src/security/jwt-config.js +13 -2
- package/src/security/jwt-validator.js +134 -30
- package/src/security/plugin-sandbox.js +18 -1
- package/src/security/plugin-signature-verifier.js +245 -70
- package/src/utils/deprecate.js +69 -0
- package/src/utils/embed-query.js +33 -0
- package/src/utils/input-sanitizer.js +19 -4
- package/src/utils/logger.js +34 -4
- package/src/utils/run-abort.js +102 -0
- package/src/ai/federated-learning.js +0 -211
- package/src/ai/federation.js +0 -71
- package/src/ai/index.js +0 -22
- package/src/ai/model-trainer.js +0 -217
- package/src/ai/model-training.js +0 -202
- package/src/ai/multimodal/multi-modal-processor.js +0 -345
- package/src/ai/orchestrator.js +0 -65
- package/src/ai/retrieval/adaptive-retrieval-engine.js +0 -398
- package/src/cli/commands/ai-ml/adaptive-commands.js +0 -178
- package/src/cli/commands/ai-ml/federated-commands.js +0 -207
- package/src/cli/commands/ai-ml/index.js +0 -17
- package/src/cli/commands/ai-ml/multimodal-commands.js +0 -187
- package/src/cli/commands/ai-ml/shared.js +0 -51
- package/src/cli/commands/ai-ml/training-commands.js +0 -228
- package/src/cli/commands/ai-ml.js +0 -386
- package/src/cli/commands/docs.js +0 -228
- package/src/cli/commands/dx.js +0 -538
- package/src/cli/commands/wizard.js +0 -627
- package/src/cli/input-sanitization-middleware.js +0 -356
- package/src/cli/interactive-wizard.js +0 -373
- package/src/cli/templates/development.template.json +0 -64
- package/src/cli/templates/minimal.template.json +0 -33
- package/src/cli/templates/production.template.json +0 -104
- package/src/cli/templates/testing.template.json +0 -45
- package/src/cli/wizard/configuration.js +0 -148
- package/src/cli/wizard/observability.js +0 -79
- package/src/cli/wizard/performance.js +0 -76
- package/src/cli/wizard/plugin-selection.js +0 -297
- package/src/cli/wizard/preview-save.js +0 -172
- package/src/cli/wizard/project-setup.js +0 -66
- package/src/core/pipeline-factory.js +0 -59
- package/src/dag/enhanced-dag-engine.js +0 -894
- package/src/dx/index.js +0 -40
- package/src/dx/integration-templates.js +0 -662
- package/src/dx/performance-profiler.js +0 -968
- package/src/dx/realtime-debugger.js +0 -755
- package/src/dx/visual-pipeline-builder.js +0 -578
- package/src/ingest.js +0 -59
- package/src/pipeline/pipeline.js +0 -18
- package/src/query.js +0 -117
|
@@ -1,44 +1,75 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Environment
|
|
3
|
-
*
|
|
2
|
+
* Environment diagnostics: API keys the configured providers need, ${VAR}
|
|
3
|
+
* references in the config, and whether the file-store index exists yet.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
const fs = require("fs
|
|
6
|
+
const fs = require("fs");
|
|
7
|
+
const path = require("path");
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
const PROVIDER_KEYS = {
|
|
10
|
+
openai: "OPENAI_API_KEY",
|
|
11
|
+
anthropic: "ANTHROPIC_API_KEY",
|
|
12
|
+
cohere: "COHERE_API_KEY",
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
function missingVar(envVar, reason) {
|
|
16
|
+
return {
|
|
17
|
+
category: "environment",
|
|
18
|
+
severity: "error",
|
|
19
|
+
code: "ENV_VAR_MISSING",
|
|
20
|
+
message: `Required environment variable missing: ${envVar}${reason ? ` (${reason})` : ""}`,
|
|
21
|
+
fix: `Set environment variable: export ${envVar}=your_key`,
|
|
22
|
+
autoFixable: false,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
15
25
|
|
|
26
|
+
async function checkEnvironment(options) {
|
|
27
|
+
const configPath = path.resolve(options.configPath);
|
|
28
|
+
let config;
|
|
16
29
|
try {
|
|
17
|
-
|
|
18
|
-
|
|
30
|
+
config = JSON.parse(fs.readFileSync(configPath, "utf8"));
|
|
31
|
+
} catch {
|
|
32
|
+
return []; // reported by the configuration checker
|
|
33
|
+
}
|
|
19
34
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
const issues = [];
|
|
36
|
+
const seen = new Set();
|
|
37
|
+
for (const entry of Array.isArray(config.pipeline) ? config.pipeline : []) {
|
|
38
|
+
const envVar = PROVIDER_KEYS[entry?.name];
|
|
39
|
+
if (
|
|
40
|
+
envVar &&
|
|
41
|
+
!entry.config?.apiKey &&
|
|
42
|
+
!process.env[envVar] &&
|
|
43
|
+
!seen.has(envVar)
|
|
44
|
+
) {
|
|
45
|
+
seen.add(envVar);
|
|
46
|
+
issues.push(missingVar(envVar, `used by ${entry.stage} "${entry.name}"`));
|
|
47
|
+
}
|
|
48
|
+
if (entry?.stage === "retriever" && entry.name === "file-store") {
|
|
49
|
+
const indexPath = path.resolve(
|
|
50
|
+
path.dirname(configPath),
|
|
51
|
+
entry.config?.path || ".rag/index.json",
|
|
52
|
+
);
|
|
53
|
+
if (!fs.existsSync(indexPath)) {
|
|
54
|
+
issues.push({
|
|
55
|
+
category: "environment",
|
|
56
|
+
severity: "info",
|
|
57
|
+
code: "INDEX_MISSING",
|
|
58
|
+
message: `No index yet at ${path.relative(process.cwd(), indexPath)}`,
|
|
59
|
+
fix: "Run: rag-pipeline ingest <file-or-directory>",
|
|
60
|
+
autoFixable: false,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
37
63
|
}
|
|
38
|
-
} catch (error) {
|
|
39
|
-
// Config issues handled elsewhere
|
|
40
64
|
}
|
|
41
65
|
|
|
66
|
+
for (const match of JSON.stringify(config).match(/\$\{([^}]+)\}/g) || []) {
|
|
67
|
+
const envVar = match.slice(2, -1);
|
|
68
|
+
if (!process.env[envVar] && !seen.has(envVar)) {
|
|
69
|
+
seen.add(envVar);
|
|
70
|
+
issues.push(missingVar(envVar, "referenced in the config"));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
42
73
|
return issues;
|
|
43
74
|
}
|
|
44
75
|
|
|
@@ -1,105 +1,52 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Plugin
|
|
3
|
-
*
|
|
2
|
+
* Plugin diagnostics: every custom plugin path under `plugins` exists and
|
|
3
|
+
* loads. Checked locally; no registry is contacted.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
const fs = require("fs
|
|
6
|
+
const fs = require("fs");
|
|
7
7
|
const path = require("path");
|
|
8
8
|
|
|
9
|
-
/**
|
|
10
|
-
* Check plugin issues
|
|
11
|
-
* @param {object} options - Doctor options (must include configPath)
|
|
12
|
-
* @returns {Promise<Array>} Array of plugin issues
|
|
13
|
-
*/
|
|
14
9
|
async function checkPlugins(options) {
|
|
15
|
-
const
|
|
16
|
-
|
|
10
|
+
const configPath = path.resolve(options.configPath);
|
|
11
|
+
let config;
|
|
17
12
|
try {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const config = JSON.parse(configContent);
|
|
23
|
-
|
|
24
|
-
if (config.plugins) {
|
|
25
|
-
// Process plugins in the order expected by tests: loader first, then embedder
|
|
26
|
-
const categories = ["loader", "embedder"];
|
|
27
|
-
for (const category of categories) {
|
|
28
|
-
if (config.plugins[category]) {
|
|
29
|
-
const plugins = config.plugins[category];
|
|
30
|
-
const sortedPlugins = Object.keys(plugins).sort();
|
|
31
|
-
for (const pluginName of sortedPlugins) {
|
|
32
|
-
try {
|
|
33
|
-
// Check if plugin file exists (simplified check)
|
|
34
|
-
await fs.access(path.join("node_modules", pluginName));
|
|
35
|
-
} catch (error) {
|
|
36
|
-
issues.push({
|
|
37
|
-
category: "plugins",
|
|
38
|
-
severity: "error",
|
|
39
|
-
code: "PLUGIN_MISSING",
|
|
40
|
-
message: `Plugin not found: ${pluginName}`,
|
|
41
|
-
fix: `Install plugin: npm install ${pluginName}`,
|
|
42
|
-
autoFixable: true,
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
13
|
+
config = JSON.parse(fs.readFileSync(configPath, "utf8"));
|
|
14
|
+
} catch {
|
|
15
|
+
return []; // reported by the configuration checker
|
|
16
|
+
}
|
|
48
17
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
67
|
-
} catch (resolverError) {
|
|
68
|
-
// Version resolver not available, skip
|
|
18
|
+
const issues = [];
|
|
19
|
+
const configDir = path.dirname(configPath);
|
|
20
|
+
for (const [stage, plugins] of Object.entries(config.plugins || {})) {
|
|
21
|
+
if (!plugins || typeof plugins !== "object") continue;
|
|
22
|
+
for (const [name, modulePath] of Object.entries(plugins)) {
|
|
23
|
+
if (typeof modulePath !== "string") continue;
|
|
24
|
+
const resolved = path.resolve(configDir, modulePath);
|
|
25
|
+
if (!fs.existsSync(resolved)) {
|
|
26
|
+
issues.push({
|
|
27
|
+
category: "plugins",
|
|
28
|
+
severity: "error",
|
|
29
|
+
code: "PLUGIN_MISSING",
|
|
30
|
+
message: `Plugin ${stage}/${name} not found at ${modulePath}`,
|
|
31
|
+
fix: `Create ${modulePath} or fix the path in plugins.${stage}.${name}`,
|
|
32
|
+
autoFixable: false,
|
|
33
|
+
});
|
|
34
|
+
continue;
|
|
69
35
|
}
|
|
70
|
-
|
|
71
|
-
// Check for outdated plugins
|
|
72
36
|
try {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
category: "plugins",
|
|
84
|
-
severity: "info",
|
|
85
|
-
code: "PLUGIN_OUTDATED",
|
|
86
|
-
message: `Plugin outdated: ${pluginName}@${version} (latest: ${latest})`,
|
|
87
|
-
fix: `Update to latest version: rag-pipeline plugin install ${pluginName}@latest`,
|
|
88
|
-
autoFixable: true,
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
} catch (fetchError) {
|
|
96
|
-
// Registry not available, skip
|
|
37
|
+
require(resolved);
|
|
38
|
+
} catch (error) {
|
|
39
|
+
issues.push({
|
|
40
|
+
category: "plugins",
|
|
41
|
+
severity: "error",
|
|
42
|
+
code: "PLUGIN_LOAD_FAILED",
|
|
43
|
+
message: `Plugin ${stage}/${name} failed to load: ${error.message}`,
|
|
44
|
+
fix: `Fix the error in ${modulePath}`,
|
|
45
|
+
autoFixable: false,
|
|
46
|
+
});
|
|
97
47
|
}
|
|
98
48
|
}
|
|
99
|
-
} catch (configError) {
|
|
100
|
-
// Config issues handled in checkConfiguration
|
|
101
49
|
}
|
|
102
|
-
|
|
103
50
|
return issues;
|
|
104
51
|
}
|
|
105
52
|
|
|
@@ -38,6 +38,25 @@ const SEVERITY_LEVELS = {
|
|
|
38
38
|
SUCCESS: "success",
|
|
39
39
|
};
|
|
40
40
|
|
|
41
|
+
/**
|
|
42
|
+
* Locate npm's CLI script next to the running node binary (Windows layout:
|
|
43
|
+
* <node dir>/node_modules/npm/bin/npm-cli.js).
|
|
44
|
+
* @returns {string}
|
|
45
|
+
*/
|
|
46
|
+
function resolveNpmCli() {
|
|
47
|
+
const candidate = path.join(
|
|
48
|
+
path.dirname(process.execPath),
|
|
49
|
+
"node_modules",
|
|
50
|
+
"npm",
|
|
51
|
+
"bin",
|
|
52
|
+
"npm-cli.js",
|
|
53
|
+
);
|
|
54
|
+
if (!require("fs").existsSync(candidate)) {
|
|
55
|
+
throw new Error("npm not found next to node; run npm install manually");
|
|
56
|
+
}
|
|
57
|
+
return candidate;
|
|
58
|
+
}
|
|
59
|
+
|
|
41
60
|
/**
|
|
42
61
|
* Doctor command for pipeline diagnostics
|
|
43
62
|
*/
|
|
@@ -118,22 +137,32 @@ class PipelineDoctor {
|
|
|
118
137
|
throw new Error(`Command not allowed: ${command}`);
|
|
119
138
|
}
|
|
120
139
|
|
|
121
|
-
// Sanitize arguments
|
|
140
|
+
// Sanitize arguments. Backslashes are kept: there is no shell to
|
|
141
|
+
// interpret them, and they are path separators on Windows.
|
|
122
142
|
const sanitizedArgs = args.map((arg) => {
|
|
123
143
|
if (typeof arg !== "string") {
|
|
124
144
|
throw new Error("All arguments must be strings");
|
|
125
145
|
}
|
|
126
|
-
|
|
127
|
-
return arg.replace(/[;&|`$(){}[\]<>"'\\]/g, "");
|
|
146
|
+
return arg.replace(/[;&|`$(){}[\]<>"']/g, "");
|
|
128
147
|
});
|
|
129
148
|
|
|
130
149
|
const execOptions = {
|
|
131
|
-
shell: false, // Never use shell to prevent injection
|
|
132
150
|
timeout: options.timeout || 30000,
|
|
133
151
|
env: { ...process.env, PATH: process.env.PATH }, // Controlled environment
|
|
134
152
|
...options,
|
|
153
|
+
shell: false, // Never use a shell; set last so callers cannot override it
|
|
135
154
|
};
|
|
136
155
|
|
|
156
|
+
// npm is a .cmd shim on Windows, which execFile cannot run without a
|
|
157
|
+
// shell; run npm's JS entry point with node instead.
|
|
158
|
+
if (command === "npm" && process.platform === "win32") {
|
|
159
|
+
return await execFileAsync(
|
|
160
|
+
process.execPath,
|
|
161
|
+
[resolveNpmCli(), ...sanitizedArgs],
|
|
162
|
+
execOptions,
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
|
|
137
166
|
return await execFileAsync(command, sanitizedArgs, execOptions);
|
|
138
167
|
}
|
|
139
168
|
|
|
@@ -168,7 +197,12 @@ class PipelineDoctor {
|
|
|
168
197
|
// Validate config path is within project directory
|
|
169
198
|
const configPath = path.resolve(this.options.configPath);
|
|
170
199
|
const projectDir = path.resolve(".");
|
|
171
|
-
|
|
200
|
+
// Containment check: a bare startsWith(projectDir) also accepted
|
|
201
|
+
// sibling directories such as "/proj-evil".
|
|
202
|
+
const inside = ["/", "\\"].some((sep) =>
|
|
203
|
+
configPath.startsWith(projectDir + sep),
|
|
204
|
+
);
|
|
205
|
+
if (!inside) {
|
|
172
206
|
throw new Error("Config path outside project directory");
|
|
173
207
|
}
|
|
174
208
|
|