@devilsdev/rag-pipeline-utils 2.1.11 → 2.2.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 +218 -0
- package/README.md +651 -393
- package/bin/cli.js +8 -14
- package/dist/index.d.ts +237 -0
- package/dist/index.mjs +22 -7
- package/package.json +17 -13
- package/src/ai/adaptive-retrieval.js +191 -0
- package/src/ai/federated-learning.js +214 -0
- package/src/ai/federation/federated-learning-coordinator.js +345 -0
- package/src/ai/federation.js +76 -0
- package/src/ai/index-fixed.js +509 -0
- package/src/ai/index.js +33 -0
- package/src/ai/model-trainer.js +217 -0
- package/src/ai/model-training.js +205 -0
- package/src/ai/module-template.js +37 -0
- package/src/ai/multimodal/multi-modal-processor.js +345 -0
- package/src/ai/multimodal-processing.js +268 -0
- package/src/ai/multimodal.js +71 -0
- package/src/ai/orchestrator.js +70 -0
- package/src/ai/retrieval/adaptive-retrieval-engine.js +398 -0
- package/src/ai/retrieval-engine.js +69 -0
- package/src/ai/training/model-training-orchestrator.js +228 -0
- package/src/ci/workflow-analyzer.js +71 -0
- package/src/cli/commands/ai-ml.js +967 -0
- package/src/cli/commands/docs.js +228 -0
- package/src/cli/commands/dx.js +538 -0
- package/src/cli/commands/plugin-hub.js +875 -0
- package/src/cli/doctor-command.js +639 -0
- package/src/cli/enhanced-cli-commands.js +945 -0
- package/src/cli/interactive-wizard.js +997 -0
- package/src/cli/plugin-marketplace-commands.js +869 -0
- package/src/cli.js +17 -0
- package/src/config/enhanced-ragrc-schema.js +632 -0
- package/src/config/load-config.js +54 -0
- package/src/config/load-plugin-config.js +69 -0
- package/src/config/normalize-config.js +105 -0
- package/src/config/schema-validator.js +315 -0
- package/src/config/validate-plugin-schema.js +35 -0
- package/src/config/validate-schema.js +113 -0
- package/src/contracts/plugin-contracts.js +33 -0
- package/src/core/create-pipeline.js +99 -0
- package/src/core/dependency-injection.js +242 -0
- package/src/core/observability/event-logger.js +241 -0
- package/src/core/observability/instrumented-pipeline.js +609 -0
- package/src/core/observability/metrics.js +497 -0
- package/src/core/observability/tracing.js +781 -0
- package/src/core/performance/benchmark.js +516 -0
- package/src/core/performance/parallel-processor.js +240 -0
- package/src/core/performance/streaming-safeguards.js +611 -0
- package/src/core/pipeline-factory.js +60 -0
- package/src/core/plugin-contracts.js +89 -0
- package/src/core/plugin-marketplace/plugin-metadata.js +485 -0
- package/src/core/plugin-marketplace/plugin-publisher.js +574 -0
- package/src/core/plugin-marketplace/plugin-registry-format.js +419 -0
- package/src/core/plugin-marketplace/version-resolver.js +61 -0
- package/src/core/plugin-registry.js +265 -0
- package/src/dag/dag-engine.js +954 -0
- package/src/dag/dag-node.js +76 -0
- package/src/dag/enhanced-dag-engine.js +822 -0
- package/src/dx/index.js +40 -0
- package/src/dx/integration-templates.js +665 -0
- package/src/dx/performance-profiler.js +968 -0
- package/src/dx/realtime-debugger.js +755 -0
- package/src/dx/visual-pipeline-builder.js +578 -0
- package/src/ecosystem/plugin-analytics-dashboard.js +778 -0
- package/src/ecosystem/plugin-certification.js +580 -0
- package/src/ecosystem/plugin-hub.js +821 -0
- package/src/enterprise/audit-logging.js +967 -0
- package/src/enterprise/data-governance.js +408 -0
- package/src/enterprise/multi-tenancy.js +496 -0
- package/src/enterprise/sso-integration.js +903 -0
- package/src/evaluate/evaluator.js +52 -0
- package/src/evaluate/scoring.js +91 -0
- package/src/index.js +67 -0
- package/src/ingest.js +59 -0
- package/src/loader/csv-loader.js +38 -0
- package/src/loader/directory-loader.js +48 -0
- package/src/loader/html-loader.js +62 -0
- package/src/loader/markdown-loader.js +67 -0
- package/src/mocks/openai-embedder.js +119 -0
- package/src/mocks/openai-llm.js +77 -0
- package/src/mocks/pdf-loader.js +21 -0
- package/src/mocks/pinecone-retriever.js +106 -0
- package/src/observability/audit-logger.js +758 -0
- package/src/observability/dashboard-config.json +675 -0
- package/src/observability/event-logger.js +310 -0
- package/src/observability/metrics.js +691 -0
- package/src/observability/security-monitor.js +830 -0
- package/src/observability/slo-monitor.js +319 -0
- package/src/observability/telemetry.js +686 -0
- package/src/pipeline/pipeline.js +18 -0
- package/src/plugins/sample-embedder.js +53 -0
- package/src/plugins/sample-llm.js +30 -0
- package/src/plugins/sample-loader.js +24 -0
- package/src/plugins/sample-retriever.js +84 -0
- package/src/query.js +117 -0
- package/src/reranker/llm-reranker.js +85 -0
- package/src/scripts/script-utilities.js +36 -0
- package/src/security/plugin-sandbox.js +586 -0
- package/src/security/plugin-signature-verifier.js +414 -0
- package/src/security/validator.js +36 -0
- package/src/utils/ci/diagnostic-reporter.js +57 -0
- package/src/utils/logger.js +211 -0
- package/src/utils/performance-monitor.js +561 -0
- package/src/utils/plugin-scaffolder.js +447 -0
- package/src/utils/retry-policy.js +443 -0
- package/src/utils/retry.js +107 -0
- package/src/utils/safe-expression-evaluator.js +579 -0
- package/src/utils/structured-logger.js +361 -0
- package/src/utils/validate-plugin-contract.js +42 -0
package/src/cli.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const { Command } = require('commander');
|
|
2
|
+
const { EnhancedCLI } = require('./cli/enhanced-cli-commands');
|
|
3
|
+
const pkg = require('../package.json');
|
|
4
|
+
|
|
5
|
+
function buildProgram() {
|
|
6
|
+
const enhancedCLI = new EnhancedCLI();
|
|
7
|
+
// Keep the program name consistent with package.json bin command
|
|
8
|
+
enhancedCLI.program.name('rag-pipeline');
|
|
9
|
+
return enhancedCLI.program;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async function run(argv = process.argv) {
|
|
13
|
+
const program = buildProgram();
|
|
14
|
+
await program.parseAsync(argv);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
module.exports = { buildProgram, run };
|
|
@@ -0,0 +1,632 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enhanced .ragrc.json Schema with Plugin Versioning Support
|
|
3
|
+
* Single source of truth for configuration validation
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const Ajv = require("ajv"); // eslint-disable-line global-require
|
|
7
|
+
const addFormats = require("ajv-formats"); // eslint-disable-line global-require
|
|
8
|
+
const { normalizeConfig } = require("./normalize-config");
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Plugin specification schema - supports both simple and versioned formats
|
|
12
|
+
*/
|
|
13
|
+
const pluginSpecSchema = {
|
|
14
|
+
oneOf: [
|
|
15
|
+
// Simple format: "plugin-name" (resolves to latest)
|
|
16
|
+
{ type: "string" },
|
|
17
|
+
// Versioned format: { "name": "plugin-name", "version": "1.0.0" }
|
|
18
|
+
{
|
|
19
|
+
type: "object",
|
|
20
|
+
required: ["name"],
|
|
21
|
+
properties: {
|
|
22
|
+
name: {
|
|
23
|
+
type: "string",
|
|
24
|
+
pattern: "^[a-z0-9-]+$",
|
|
25
|
+
description: "Plugin name",
|
|
26
|
+
},
|
|
27
|
+
version: {
|
|
28
|
+
type: "string",
|
|
29
|
+
description: "Version specification (exact, range, or tag)",
|
|
30
|
+
},
|
|
31
|
+
source: {
|
|
32
|
+
type: "string",
|
|
33
|
+
enum: ["registry", "local", "git", "npm"],
|
|
34
|
+
default: "registry",
|
|
35
|
+
description: "Plugin source type",
|
|
36
|
+
},
|
|
37
|
+
url: {
|
|
38
|
+
type: "string",
|
|
39
|
+
format: "uri",
|
|
40
|
+
description: "Custom plugin URL (for git/npm sources)",
|
|
41
|
+
},
|
|
42
|
+
path: {
|
|
43
|
+
type: "string",
|
|
44
|
+
description: "Local plugin path (for local source)",
|
|
45
|
+
},
|
|
46
|
+
config: {
|
|
47
|
+
type: "object",
|
|
48
|
+
description: "Plugin-specific configuration",
|
|
49
|
+
},
|
|
50
|
+
enabled: {
|
|
51
|
+
type: "boolean",
|
|
52
|
+
default: true,
|
|
53
|
+
description: "Whether plugin is enabled",
|
|
54
|
+
},
|
|
55
|
+
fallback: {
|
|
56
|
+
type: "string",
|
|
57
|
+
description: "Fallback plugin if this one fails to load",
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
additionalProperties: false,
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Plugin group schema - collection of plugins for a specific _type
|
|
67
|
+
*/
|
|
68
|
+
const pluginGroupSchema = {
|
|
69
|
+
type: "object",
|
|
70
|
+
minProperties: 1,
|
|
71
|
+
additionalProperties: pluginSpecSchema,
|
|
72
|
+
description: "Plugin group with name-to-spec mappings",
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Registry configuration schema
|
|
77
|
+
*/
|
|
78
|
+
const registryConfigSchema = {
|
|
79
|
+
type: "object",
|
|
80
|
+
properties: {
|
|
81
|
+
urls: {
|
|
82
|
+
type: "array",
|
|
83
|
+
items: { type: "string", format: "uri" },
|
|
84
|
+
description: "Plugin registry URLs",
|
|
85
|
+
},
|
|
86
|
+
cache: {
|
|
87
|
+
type: "object",
|
|
88
|
+
properties: {
|
|
89
|
+
enabled: { type: "boolean", default: true },
|
|
90
|
+
ttl: {
|
|
91
|
+
type: "number",
|
|
92
|
+
default: 3600,
|
|
93
|
+
description: "Cache TTL in seconds",
|
|
94
|
+
},
|
|
95
|
+
directory: { type: "string", description: "Custom cache directory" },
|
|
96
|
+
},
|
|
97
|
+
additionalProperties: false,
|
|
98
|
+
},
|
|
99
|
+
auth: {
|
|
100
|
+
type: "object",
|
|
101
|
+
properties: {
|
|
102
|
+
token: { type: "string", description: "Authentication token" },
|
|
103
|
+
username: { type: "string", description: "Username for basic auth" },
|
|
104
|
+
password: { type: "string", description: "Password for basic auth" },
|
|
105
|
+
},
|
|
106
|
+
additionalProperties: false,
|
|
107
|
+
},
|
|
108
|
+
timeout: {
|
|
109
|
+
type: "number",
|
|
110
|
+
default: 30000,
|
|
111
|
+
description: "Request timeout in milliseconds",
|
|
112
|
+
},
|
|
113
|
+
retries: {
|
|
114
|
+
type: "number",
|
|
115
|
+
default: 3,
|
|
116
|
+
description: "Number of retry attempts",
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
additionalProperties: false,
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Enhanced .ragrc.json schema with versioning support
|
|
124
|
+
*/
|
|
125
|
+
const enhancedRagrcSchema = {
|
|
126
|
+
type: "object",
|
|
127
|
+
required: ["plugins"],
|
|
128
|
+
properties: {
|
|
129
|
+
// Plugin specifications
|
|
130
|
+
plugins: {
|
|
131
|
+
type: "object",
|
|
132
|
+
required: ["loader", "embedder", "retriever", "llm"],
|
|
133
|
+
properties: {
|
|
134
|
+
loader: pluginGroupSchema,
|
|
135
|
+
embedder: pluginGroupSchema,
|
|
136
|
+
retriever: pluginGroupSchema,
|
|
137
|
+
llm: pluginGroupSchema,
|
|
138
|
+
reranker: pluginGroupSchema,
|
|
139
|
+
},
|
|
140
|
+
additionalProperties: false,
|
|
141
|
+
},
|
|
142
|
+
|
|
143
|
+
// Registry configuration
|
|
144
|
+
registry: registryConfigSchema,
|
|
145
|
+
|
|
146
|
+
// Pipeline configuration
|
|
147
|
+
pipeline: {
|
|
148
|
+
type: "object",
|
|
149
|
+
properties: {
|
|
150
|
+
stages: {
|
|
151
|
+
type: "array",
|
|
152
|
+
items: {
|
|
153
|
+
type: "string",
|
|
154
|
+
enum: ["loader", "embedder", "retriever", "llm", "reranker"],
|
|
155
|
+
},
|
|
156
|
+
default: ["loader", "embedder", "retriever", "llm"],
|
|
157
|
+
description: "Pipeline execution stages",
|
|
158
|
+
},
|
|
159
|
+
middleware: {
|
|
160
|
+
type: "array",
|
|
161
|
+
items: {
|
|
162
|
+
type: "object",
|
|
163
|
+
required: ["name"],
|
|
164
|
+
properties: {
|
|
165
|
+
name: { type: "string" },
|
|
166
|
+
_config: { type: "object" },
|
|
167
|
+
enabled: { type: "boolean", default: true },
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
description: "Pipeline middleware configuration",
|
|
171
|
+
},
|
|
172
|
+
retries: {
|
|
173
|
+
type: "object",
|
|
174
|
+
properties: {
|
|
175
|
+
enabled: { type: "boolean", default: true },
|
|
176
|
+
maxAttempts: { type: "number", default: 3 },
|
|
177
|
+
backoff: {
|
|
178
|
+
type: "string",
|
|
179
|
+
enum: ["linear", "exponential"],
|
|
180
|
+
default: "exponential",
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
timeout: {
|
|
185
|
+
type: "number",
|
|
186
|
+
description: "Pipeline timeout in milliseconds",
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
additionalProperties: false,
|
|
190
|
+
},
|
|
191
|
+
|
|
192
|
+
// Performance configuration
|
|
193
|
+
performance: {
|
|
194
|
+
type: "object",
|
|
195
|
+
properties: {
|
|
196
|
+
parallel: {
|
|
197
|
+
type: "object",
|
|
198
|
+
properties: {
|
|
199
|
+
enabled: { type: "boolean", default: false },
|
|
200
|
+
maxConcurrency: { type: "number", default: 3 },
|
|
201
|
+
batchSize: { type: "number", default: 10 },
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
streaming: {
|
|
205
|
+
type: "object",
|
|
206
|
+
properties: {
|
|
207
|
+
enabled: { type: "boolean", default: false },
|
|
208
|
+
maxMemoryMB: { type: "number", default: 512 },
|
|
209
|
+
bufferSize: { type: "number", default: 100 },
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
caching: {
|
|
213
|
+
type: "object",
|
|
214
|
+
properties: {
|
|
215
|
+
enabled: { type: "boolean", default: false },
|
|
216
|
+
ttl: { type: "number", default: 3600 },
|
|
217
|
+
maxSize: { type: "number", default: 1000 },
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
additionalProperties: false,
|
|
222
|
+
},
|
|
223
|
+
|
|
224
|
+
// Observability configuration
|
|
225
|
+
observability: {
|
|
226
|
+
type: "object",
|
|
227
|
+
properties: {
|
|
228
|
+
logging: {
|
|
229
|
+
type: "object",
|
|
230
|
+
properties: {
|
|
231
|
+
level: {
|
|
232
|
+
type: "string",
|
|
233
|
+
enum: ["debug", "info", "warn", "error"],
|
|
234
|
+
default: "info",
|
|
235
|
+
},
|
|
236
|
+
structured: { type: "boolean", default: true },
|
|
237
|
+
events: { type: "boolean", default: false },
|
|
238
|
+
},
|
|
239
|
+
},
|
|
240
|
+
tracing: {
|
|
241
|
+
type: "object",
|
|
242
|
+
properties: {
|
|
243
|
+
enabled: { type: "boolean", default: false },
|
|
244
|
+
exportUrl: { type: "string", format: "uri" },
|
|
245
|
+
sampleRate: { type: "number", minimum: 0, maximum: 1, default: 1 },
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
metrics: {
|
|
249
|
+
type: "object",
|
|
250
|
+
properties: {
|
|
251
|
+
enabled: { type: "boolean", default: false },
|
|
252
|
+
exportUrl: { type: "string", format: "uri" },
|
|
253
|
+
interval: { type: "number", default: 60000 },
|
|
254
|
+
},
|
|
255
|
+
},
|
|
256
|
+
},
|
|
257
|
+
additionalProperties: false,
|
|
258
|
+
},
|
|
259
|
+
|
|
260
|
+
// Environment-specific overrides
|
|
261
|
+
environments: {
|
|
262
|
+
type: "object",
|
|
263
|
+
additionalProperties: {
|
|
264
|
+
type: "object",
|
|
265
|
+
description: "Environment-specific configuration overrides",
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
|
|
269
|
+
// Metadata
|
|
270
|
+
metadata: {
|
|
271
|
+
type: "object",
|
|
272
|
+
properties: {
|
|
273
|
+
name: { type: "string", description: "Project name" },
|
|
274
|
+
version: { type: "string", description: "Project version" },
|
|
275
|
+
description: { type: "string", description: "Project description" },
|
|
276
|
+
author: { type: "string", description: "Project author" },
|
|
277
|
+
tags: {
|
|
278
|
+
type: "array",
|
|
279
|
+
items: { type: "string" },
|
|
280
|
+
description: "Project tags",
|
|
281
|
+
},
|
|
282
|
+
},
|
|
283
|
+
additionalProperties: false,
|
|
284
|
+
},
|
|
285
|
+
|
|
286
|
+
// Legacy support
|
|
287
|
+
namespace: {
|
|
288
|
+
type: "string",
|
|
289
|
+
description: "Legacy namespace field (deprecated)",
|
|
290
|
+
},
|
|
291
|
+
},
|
|
292
|
+
additionalProperties: false,
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Backward compatibility schema (original format)
|
|
297
|
+
*/
|
|
298
|
+
const legacyRagrcSchema = {
|
|
299
|
+
type: "object",
|
|
300
|
+
required: ["loader", "embedder", "retriever", "llm", "namespace", "pipeline"],
|
|
301
|
+
properties: {
|
|
302
|
+
loader: {
|
|
303
|
+
type: "object",
|
|
304
|
+
minProperties: 1,
|
|
305
|
+
additionalProperties: { type: "string" },
|
|
306
|
+
},
|
|
307
|
+
embedder: {
|
|
308
|
+
type: "object",
|
|
309
|
+
minProperties: 1,
|
|
310
|
+
additionalProperties: { type: "string" },
|
|
311
|
+
},
|
|
312
|
+
retriever: {
|
|
313
|
+
type: "object",
|
|
314
|
+
minProperties: 1,
|
|
315
|
+
additionalProperties: { type: "string" },
|
|
316
|
+
},
|
|
317
|
+
llm: {
|
|
318
|
+
type: "object",
|
|
319
|
+
minProperties: 1,
|
|
320
|
+
additionalProperties: { type: "string" },
|
|
321
|
+
},
|
|
322
|
+
reranker: {
|
|
323
|
+
type: "object",
|
|
324
|
+
additionalProperties: { type: "string" },
|
|
325
|
+
},
|
|
326
|
+
namespace: { type: "string", minLength: 1 },
|
|
327
|
+
pipeline: {
|
|
328
|
+
type: "array",
|
|
329
|
+
items: {
|
|
330
|
+
type: "string",
|
|
331
|
+
enum: ["loader", "embedder", "retriever"],
|
|
332
|
+
},
|
|
333
|
+
minItems: 1,
|
|
334
|
+
uniqueItems: true,
|
|
335
|
+
},
|
|
336
|
+
},
|
|
337
|
+
additionalProperties: false,
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Build the canonical .ragrc.json schema
|
|
342
|
+
* @returns {object} JSON Schema object
|
|
343
|
+
*/
|
|
344
|
+
function buildRagrcJsonSchema() {
|
|
345
|
+
return enhancedRagrcSchema;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Validate .ragrc.json configuration (single source of truth)
|
|
350
|
+
* @param {object} config - Configuration to validate
|
|
351
|
+
* @returns {{ valid: boolean, errors?: any[], normalized?: object }}
|
|
352
|
+
*/
|
|
353
|
+
function validateRagrc(config) {
|
|
354
|
+
let errors = [];
|
|
355
|
+
|
|
356
|
+
// Input validation before normalization
|
|
357
|
+
if (!config || typeof config !== "object") {
|
|
358
|
+
return {
|
|
359
|
+
valid: false,
|
|
360
|
+
errors: [{ message: "Configuration must be a non-null object" }],
|
|
361
|
+
normalized: undefined,
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Check for obviously invalid plugin configurations
|
|
366
|
+
const pluginTypes = ["loader", "embedder", "retriever", "llm", "reranker"];
|
|
367
|
+
for (const type of pluginTypes) {
|
|
368
|
+
if (config.hasOwnProperty(type)) {
|
|
369
|
+
const value = config[type];
|
|
370
|
+
// Plugin configs should be objects or strings, not primitives like true, 123, null
|
|
371
|
+
if (
|
|
372
|
+
value !== null &&
|
|
373
|
+
typeof value !== "string" &&
|
|
374
|
+
typeof value !== "object"
|
|
375
|
+
) {
|
|
376
|
+
errors.push({
|
|
377
|
+
message: `${type} must be an object or string, got ${typeof value}`,
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// Pipeline should be array or object if specified (object format will be normalized)
|
|
384
|
+
if (
|
|
385
|
+
config.hasOwnProperty("pipeline") &&
|
|
386
|
+
!Array.isArray(config.pipeline) &&
|
|
387
|
+
(typeof config.pipeline !== "object" || config.pipeline === null)
|
|
388
|
+
) {
|
|
389
|
+
errors.push({ message: "pipeline must be an array or object" });
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// Only return early for critical errors that prevent normalization
|
|
393
|
+
const criticalErrors = errors.filter(
|
|
394
|
+
(e) =>
|
|
395
|
+
e.message.includes("Configuration must be a non-null object") ||
|
|
396
|
+
e.message.includes("pipeline must be an array or object"),
|
|
397
|
+
);
|
|
398
|
+
|
|
399
|
+
if (criticalErrors.length > 0) {
|
|
400
|
+
return {
|
|
401
|
+
valid: false,
|
|
402
|
+
errors: criticalErrors,
|
|
403
|
+
normalized: undefined,
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// Try normalization
|
|
408
|
+
let normalized;
|
|
409
|
+
try {
|
|
410
|
+
normalized = normalizeConfig(config);
|
|
411
|
+
} catch (e) {
|
|
412
|
+
return {
|
|
413
|
+
valid: false,
|
|
414
|
+
errors: [{ message: e.message }],
|
|
415
|
+
normalized: undefined,
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// Post-normalization validation
|
|
420
|
+
if (!normalized || typeof normalized !== "object") {
|
|
421
|
+
errors.push({ message: "Normalized config invalid" });
|
|
422
|
+
}
|
|
423
|
+
if (typeof normalized.namespace !== "string") {
|
|
424
|
+
errors.push({ message: "namespace must be string" });
|
|
425
|
+
}
|
|
426
|
+
if (!Array.isArray(normalized.pipeline)) {
|
|
427
|
+
errors.push({ message: "pipeline must be array" });
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// Validate pipeline entries have valid names
|
|
431
|
+
if (Array.isArray(normalized.pipeline)) {
|
|
432
|
+
for (const entry of normalized.pipeline) {
|
|
433
|
+
if (!entry || typeof entry !== "object") {
|
|
434
|
+
errors.push({ message: "Pipeline entry must be object" });
|
|
435
|
+
} else if (typeof entry.name !== "string") {
|
|
436
|
+
errors.push({
|
|
437
|
+
message: `Pipeline entry name must be string, got ${typeof entry.name}`,
|
|
438
|
+
});
|
|
439
|
+
} else if (typeof entry.stage !== "string") {
|
|
440
|
+
errors.push({
|
|
441
|
+
message: `Pipeline entry stage must be string, got ${typeof entry.stage}`,
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// Check for normalization warnings (invalid entries that were filtered out)
|
|
448
|
+
if (normalized._warnings && Array.isArray(normalized._warnings)) {
|
|
449
|
+
for (const warning of normalized._warnings) {
|
|
450
|
+
errors.push({ message: warning });
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
return {
|
|
455
|
+
valid: errors.length === 0,
|
|
456
|
+
errors: errors.length ? errors : undefined,
|
|
457
|
+
normalized,
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Legacy function for backward compatibility
|
|
463
|
+
* @deprecated Use validateRagrc instead
|
|
464
|
+
*/
|
|
465
|
+
function validateEnhancedRagrcSchema(config) {
|
|
466
|
+
const result = validateRagrc(config);
|
|
467
|
+
return {
|
|
468
|
+
valid: result.valid,
|
|
469
|
+
errors: result.errors,
|
|
470
|
+
legacy: false,
|
|
471
|
+
};
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* Convert legacy _config to enhanced format
|
|
476
|
+
* @param {object} legacyConfig - Legacy configuration
|
|
477
|
+
* @returns {object} Enhanced configuration
|
|
478
|
+
*/
|
|
479
|
+
function convertLegacyConfig(legacyConfig) {
|
|
480
|
+
const enhanced = {
|
|
481
|
+
plugins: {
|
|
482
|
+
loader: {},
|
|
483
|
+
embedder: {},
|
|
484
|
+
retriever: {},
|
|
485
|
+
llm: {},
|
|
486
|
+
},
|
|
487
|
+
};
|
|
488
|
+
|
|
489
|
+
// Convert plugin specifications
|
|
490
|
+
for (const [_type, plugins] of Object.entries(legacyConfig)) {
|
|
491
|
+
if (
|
|
492
|
+
["loader", "embedder", "retriever", "llm", "reranker"].includes(_type)
|
|
493
|
+
) {
|
|
494
|
+
enhanced.plugins[_type] = {};
|
|
495
|
+
for (const [name, spec] of Object.entries(plugins)) {
|
|
496
|
+
enhanced.plugins[_type][name] = typeof spec === "string" ? spec : spec;
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
// Convert pipeline configuration
|
|
502
|
+
if (legacyConfig.pipeline) {
|
|
503
|
+
enhanced.pipeline = {
|
|
504
|
+
stages: legacyConfig.pipeline,
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// Add namespace as metadata
|
|
509
|
+
if (legacyConfig.namespace) {
|
|
510
|
+
enhanced.metadata = {
|
|
511
|
+
name: legacyConfig.namespace,
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
return enhanced;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
/**
|
|
519
|
+
* Normalize plugin specification to object format
|
|
520
|
+
* @param {string|object} spec - Plugin specification
|
|
521
|
+
* @returns {object} Normalized specification
|
|
522
|
+
*/
|
|
523
|
+
function normalizePluginSpec(spec) {
|
|
524
|
+
if (typeof spec === "string") {
|
|
525
|
+
return {
|
|
526
|
+
name: spec,
|
|
527
|
+
version: "latest",
|
|
528
|
+
source: "registry",
|
|
529
|
+
enabled: true,
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
return {
|
|
534
|
+
name: spec.name,
|
|
535
|
+
version: spec.version || "latest",
|
|
536
|
+
source: spec.source || "registry",
|
|
537
|
+
url: spec.url,
|
|
538
|
+
path: spec.path,
|
|
539
|
+
_config: spec._config || {},
|
|
540
|
+
enabled: spec.enabled !== false,
|
|
541
|
+
fallback: spec.fallback,
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
/**
|
|
546
|
+
* Extract plugin dependencies from configuration
|
|
547
|
+
* @param {object} _config - Enhanced configuration
|
|
548
|
+
* @returns {Array<{type: string, name: string, spec: object}>}
|
|
549
|
+
*/
|
|
550
|
+
function extractPluginDependencies(config) {
|
|
551
|
+
const dependencies = [];
|
|
552
|
+
|
|
553
|
+
if (!config.plugins) {
|
|
554
|
+
return dependencies;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
for (const [_type, plugins] of Object.entries(config.plugins)) {
|
|
558
|
+
for (const [name, spec] of Object.entries(plugins)) {
|
|
559
|
+
const normalizedSpec = normalizePluginSpec(spec);
|
|
560
|
+
dependencies.push({
|
|
561
|
+
_type,
|
|
562
|
+
name,
|
|
563
|
+
spec: normalizedSpec,
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
return dependencies;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
/**
|
|
572
|
+
* Validate plugin configuration consistency
|
|
573
|
+
* @param {object} config - Configuration to validate
|
|
574
|
+
* @returns {{ valid: boolean, issues: Array<string> }}
|
|
575
|
+
*/
|
|
576
|
+
function validateConfigConsistency(config) {
|
|
577
|
+
const issues = [];
|
|
578
|
+
// Check for required plugin types
|
|
579
|
+
const requiredTypes = ["loader", "embedder", "retriever", "llm"];
|
|
580
|
+
for (const _type of requiredTypes) {
|
|
581
|
+
if (
|
|
582
|
+
!config.plugins?.[_type] ||
|
|
583
|
+
Object.keys(config.plugins[_type]).length === 0
|
|
584
|
+
) {
|
|
585
|
+
issues.push(`Missing required plugin type: ${_type}`);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
// Check pipeline stages reference valid plugin types
|
|
590
|
+
if (config.pipeline?.stages) {
|
|
591
|
+
for (const stage of config.pipeline.stages) {
|
|
592
|
+
if (!config.plugins?.[stage]) {
|
|
593
|
+
issues.push(`Pipeline stage '${stage}' has no configured plugins`);
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
// Check fallback plugins exist
|
|
599
|
+
const dependencies = extractPluginDependencies(config);
|
|
600
|
+
for (const dep of dependencies) {
|
|
601
|
+
if (dep.spec.fallback) {
|
|
602
|
+
const fallbackExists = dependencies.some(
|
|
603
|
+
(d) => d._type === dep._type && d.name === dep.spec.fallback,
|
|
604
|
+
);
|
|
605
|
+
if (!fallbackExists) {
|
|
606
|
+
issues.push(
|
|
607
|
+
`Fallback plugin '${dep.spec.fallback}' not found for ${dep._type}:${dep.name}`,
|
|
608
|
+
);
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
return {
|
|
614
|
+
valid: issues.length === 0,
|
|
615
|
+
issues,
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
// Default export
|
|
620
|
+
|
|
621
|
+
module.exports = {
|
|
622
|
+
validateRagrc,
|
|
623
|
+
normalizeConfig,
|
|
624
|
+
buildRagrcJsonSchema,
|
|
625
|
+
validateEnhancedRagrcSchema, // Legacy compatibility
|
|
626
|
+
convertLegacyConfig,
|
|
627
|
+
normalizePluginSpec,
|
|
628
|
+
extractPluginDependencies,
|
|
629
|
+
validateConfigConsistency,
|
|
630
|
+
enhancedRagrcSchema,
|
|
631
|
+
legacyRagrcSchema,
|
|
632
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Version: 1.3.0
|
|
3
|
+
* Description: Loads and validates RAG pipeline configuration with proper error handling
|
|
4
|
+
* Author: Ali Kahwaji
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const fs = require("fs"); // eslint-disable-line global-require
|
|
8
|
+
const path = require("path"); // eslint-disable-line global-require
|
|
9
|
+
const { validateRagrc } = require("./enhanced-ragrc-schema.js"); // eslint-disable-line global-require
|
|
10
|
+
const { logger } = require("../utils/logger.js"); // eslint-disable-line global-require
|
|
11
|
+
|
|
12
|
+
// Use CommonJS __dirname (already available in Node.js CommonJS modules)
|
|
13
|
+
|
|
14
|
+
const CONFIG_FILENAME = ".ragrc.json";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Load and validate a RAG configuration file.
|
|
18
|
+
* @param {string} [cwd=process.cwd()] - Directory to resolve the config from
|
|
19
|
+
* @returns {object} Validated configuration object
|
|
20
|
+
*/
|
|
21
|
+
function loadRagConfig(cwd = process.cwd()) {
|
|
22
|
+
const configPath = path.resolve(cwd, CONFIG_FILENAME);
|
|
23
|
+
|
|
24
|
+
if (!fs.existsSync(configPath)) {
|
|
25
|
+
logger.error(`❌ Config file not found: ${configPath}`);
|
|
26
|
+
throw new Error(`Config file not found: ${configPath}`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const raw = fs.readFileSync(configPath, "utf-8");
|
|
30
|
+
let config;
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
config = JSON.parse(raw);
|
|
34
|
+
} catch (err) {
|
|
35
|
+
logger.error("❌ Failed to parse JSON configuration.");
|
|
36
|
+
throw new Error("Invalid JSON in config file.");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const { valid, errors, normalized } = validateRagrc(config);
|
|
40
|
+
|
|
41
|
+
if (!valid) {
|
|
42
|
+
logger.error(
|
|
43
|
+
`❌ Config validation failed:\n${JSON.stringify(errors, null, 2)}`,
|
|
44
|
+
);
|
|
45
|
+
throw new Error("Config validation failed");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
logger.info("✅ Configuration loaded and normalized successfully");
|
|
49
|
+
return normalized;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
module.exports = {
|
|
53
|
+
loadRagConfig,
|
|
54
|
+
};
|