@devilsdev/rag-pipeline-utils 2.3.0 → 2.4.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.
Files changed (160) hide show
  1. package/README.md +293 -361
  2. package/contracts/loader-contract.json +11 -6
  3. package/contracts/reranker-contract.json +18 -26
  4. package/dist/index.cjs +21190 -47
  5. package/dist/index.d.ts +298 -68
  6. package/dist/index.mjs +9 -76
  7. package/package.json +20 -8
  8. package/src/agentic/agentic-pipeline.js +235 -0
  9. package/src/agentic/iterative-retriever.js +213 -0
  10. package/src/agentic/query-planner.js +208 -0
  11. package/src/agentic/self-critique.js +102 -0
  12. package/src/ai/adaptive-retrieval.js +0 -3
  13. package/src/ai/federated-learning.js +0 -3
  14. package/src/ai/federation.js +1 -6
  15. package/src/ai/index.js +9 -20
  16. package/src/ai/model-training.js +0 -3
  17. package/src/ai/multimodal-processing.js +0 -3
  18. package/src/ai/multimodal.js +1 -6
  19. package/src/ai/orchestrator.js +1 -6
  20. package/src/ai/retrieval-engine.js +1 -6
  21. package/src/chunking/chunking-engine.js +142 -0
  22. package/src/chunking/strategies/fixed-size.js +54 -0
  23. package/src/chunking/strategies/recursive.js +127 -0
  24. package/src/chunking/strategies/semantic.js +128 -0
  25. package/src/chunking/strategies/sentence.js +32 -0
  26. package/src/chunking/strategies/structure-aware.js +138 -0
  27. package/src/citation/citation-tracker.js +161 -0
  28. package/src/citation/hallucination-detector.js +74 -0
  29. package/src/citation/source-mapper.js +95 -0
  30. package/src/cli/commands/ai-ml/adaptive-commands.js +178 -0
  31. package/src/cli/commands/ai-ml/federated-commands.js +207 -0
  32. package/src/cli/commands/ai-ml/index.js +17 -0
  33. package/src/cli/commands/ai-ml/multimodal-commands.js +187 -0
  34. package/src/cli/commands/ai-ml/shared.js +51 -0
  35. package/src/cli/commands/ai-ml/training-commands.js +228 -0
  36. package/src/cli/commands/ai-ml.js +176 -757
  37. package/src/cli/commands/plugin-hub/certification-commands.js +221 -0
  38. package/src/cli/commands/plugin-hub/event-handlers.js +64 -0
  39. package/src/cli/commands/plugin-hub/hub-commands.js +290 -0
  40. package/src/cli/commands/plugin-hub/review-commands.js +78 -0
  41. package/src/cli/commands/plugin-hub.js +106 -782
  42. package/src/cli/diagnostics/config-checker.js +81 -0
  43. package/src/cli/diagnostics/dependency-checker.js +69 -0
  44. package/src/cli/diagnostics/environment-checker.js +45 -0
  45. package/src/cli/diagnostics/performance-checker.js +51 -0
  46. package/src/cli/diagnostics/plugin-checker.js +106 -0
  47. package/src/cli/diagnostics/security-checker.js +61 -0
  48. package/src/cli/doctor-command.js +70 -369
  49. package/src/cli/enhanced-cli-commands.js +162 -706
  50. package/src/cli/handlers/config-handler.js +126 -0
  51. package/src/cli/handlers/diagnostics-handler.js +113 -0
  52. package/src/cli/handlers/ingest-handler.js +42 -0
  53. package/src/cli/handlers/init-handler.js +51 -0
  54. package/src/cli/handlers/query-handler.js +45 -0
  55. package/src/cli/handlers/run-handler.js +181 -0
  56. package/src/cli/interactive-wizard.js +99 -723
  57. package/src/cli/shared/cli-utils.js +89 -0
  58. package/src/cli/wizard/configuration.js +148 -0
  59. package/src/cli/wizard/observability.js +79 -0
  60. package/src/cli/wizard/performance.js +76 -0
  61. package/src/cli/wizard/plugin-selection.js +297 -0
  62. package/src/cli/wizard/preview-save.js +172 -0
  63. package/src/cli/wizard/project-setup.js +66 -0
  64. package/src/config/memory-optimization.js +3 -3
  65. package/src/connectors/anthropic-connector.js +179 -0
  66. package/src/connectors/base-connector.js +94 -0
  67. package/src/connectors/cohere-connector.js +143 -0
  68. package/src/connectors/local-embedder.js +171 -0
  69. package/src/connectors/memory-retriever.js +150 -0
  70. package/src/connectors/ollama-connector.js +205 -0
  71. package/src/connectors/openai-connector.js +173 -0
  72. package/src/core/create-pipeline.js +21 -1
  73. package/src/core/observability/tracing.js +2 -1
  74. package/src/core/pipeline-factory.js +0 -1
  75. package/src/core/plugin-registry.js +14 -14
  76. package/src/cost/cost-calculator.js +146 -0
  77. package/src/cost/cost-tracker.js +260 -0
  78. package/src/cost/token-budget.js +245 -0
  79. package/src/dag/core/execution-scheduler.js +2 -1
  80. package/src/dag/core/topology-validation.js +0 -3
  81. package/src/dag/dag-engine.js +3 -5
  82. package/src/dag/dag-node.js +0 -1
  83. package/src/dag/enhanced-dag-engine.js +171 -99
  84. package/src/dashboard/dashboard-generator.js +642 -0
  85. package/src/dashboard/metrics-aggregator.js +409 -0
  86. package/src/debug/execution-tracer.js +210 -0
  87. package/src/debug/trace-inspector.js +281 -0
  88. package/src/dev/dev-server.js +5 -5
  89. package/src/dev/hot-reload.js +3 -2
  90. package/src/dx/integration-templates.js +0 -3
  91. package/src/ecosystem/plugin-analytics-dashboard.js +2 -2
  92. package/src/ecosystem/plugin-hub.js +2 -2
  93. package/src/enterprise/audit-logging.js +2 -2
  94. package/src/enterprise/sso-integration.js +52 -32
  95. package/src/evaluate/context-metrics.js +127 -0
  96. package/src/evaluate/evaluator.js +4 -2
  97. package/src/evaluate/faithfulness.js +117 -0
  98. package/src/evaluate/groundedness.js +60 -0
  99. package/src/evaluate/pipeline-evaluator.js +156 -0
  100. package/src/evaluate/relevance.js +129 -0
  101. package/src/evaluate/scoring.js +27 -0
  102. package/src/graph/entity-extractor.js +183 -0
  103. package/src/graph/graph-index.js +113 -0
  104. package/src/graph/graph-retriever.js +244 -0
  105. package/src/graph/knowledge-graph.js +256 -0
  106. package/src/guardrails/guardrails-pipeline.js +136 -0
  107. package/src/guardrails/post-generation-guard.js +170 -0
  108. package/src/guardrails/pre-retrieval-guard.js +161 -0
  109. package/src/guardrails/retrieval-guard.js +126 -0
  110. package/src/index.js +255 -9
  111. package/src/loader/html-loader.js +4 -15
  112. package/src/loader/markdown-loader.js +4 -15
  113. package/src/mcp/mcp-server.js +199 -0
  114. package/src/mcp/mcp-tool-builder.js +121 -0
  115. package/src/observability/audit-logger.js +0 -2
  116. package/src/observability/event-logger.js +2 -1
  117. package/src/observability/security-monitor.js +0 -2
  118. package/src/observability/telemetry.js +0 -2
  119. package/src/reranker/cascade-reranker.js +79 -0
  120. package/src/reranker/embedding-reranker.js +124 -0
  121. package/src/reranker/llm-reranker.js +6 -3
  122. package/src/reranker/scoring-reranker.js +123 -0
  123. package/src/retrieval/bm25-search.js +157 -0
  124. package/src/retrieval/hybrid-retriever.js +111 -0
  125. package/src/retrieval/rank-fusion.js +62 -0
  126. package/src/security/jwt-config.js +4 -3
  127. package/src/security/jwt-validator.js +2 -1
  128. package/src/security/plugin-sandbox.js +0 -3
  129. package/src/security/plugin-signature-verifier.js +4 -6
  130. package/src/security/validator.js +0 -2
  131. package/src/streaming/embedding-stream.js +197 -0
  132. package/src/streaming/sse-adapter.js +168 -0
  133. package/src/streaming/stream-router.js +210 -0
  134. package/src/streaming/streaming-embedder.js +231 -0
  135. package/src/streaming/websocket-adapter.js +171 -0
  136. package/src/templates/scaffold.js +147 -0
  137. package/src/templates/template-registry.js +272 -0
  138. package/src/utils/contract-validator.js +2 -1
  139. package/src/utils/input-sanitizer.js +80 -99
  140. package/src/utils/performance-monitor.js +0 -3
  141. package/src/utils/plugin-scaffolder.js +9 -16
  142. package/src/utils/rate-limiter.js +0 -1
  143. package/src/utils/retry-policy.js +0 -3
  144. package/src/utils/safe-expression-evaluator.js +0 -3
  145. package/src/utils/secure-logger-config.js +2 -4
  146. package/src/utils/secure-logging.js +0 -3
  147. package/src/utils/structured-logger.js +0 -3
  148. package/src/ai/index-fixed.js +0 -509
  149. package/src/ai/module-template.js +0 -37
  150. package/src/ci/workflow-analyzer.js +0 -71
  151. package/src/cli/plugin-marketplace-commands.js +0 -869
  152. package/src/dev/README.md +0 -126
  153. package/src/dev/examples/hot-reload-usage.js +0 -355
  154. package/src/mocks/openai-embedder.js +0 -119
  155. package/src/mocks/openai-llm.js +0 -77
  156. package/src/mocks/pdf-loader.js +0 -21
  157. package/src/mocks/pinecone-retriever.js +0 -106
  158. package/src/scripts/script-utilities.js +0 -36
  159. package/src/utils/ci/diagnostic-reporter.js +0 -57
  160. package/src/utils/examples/error-formatter-usage.js +0 -351
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Config command handlers
3
+ * Handles config show, set, and get commands
4
+ */
5
+
6
+ const fs = require("fs/promises");
7
+ const { logger } = require("../../utils/logger.js");
8
+
9
+ /**
10
+ * Handle config show command
11
+ * @param {object} globalOptions - Global CLI options from program.opts()
12
+ * @param {object} options - Command-specific options
13
+ */
14
+ async function handleConfigShow(globalOptions, options) {
15
+ try {
16
+ const config = JSON.parse(await fs.readFile(globalOptions.config, "utf-8"));
17
+
18
+ let output = config;
19
+ if (options.section) {
20
+ const sections = options.section.split(".");
21
+ for (const section of sections) {
22
+ output = output[section];
23
+ if (output === undefined) {
24
+ console.log(`❌ Section not found: ${options.section}`);
25
+ return;
26
+ }
27
+ }
28
+ }
29
+
30
+ console.log(JSON.stringify(output, null, 2));
31
+ } catch (error) {
32
+ logger.error("❌ Failed to show configuration:", error.message);
33
+ process.exit(1);
34
+ }
35
+ }
36
+
37
+ /**
38
+ * Handle config set command
39
+ * @param {object} globalOptions - Global CLI options from program.opts()
40
+ * @param {string} key - Configuration key (dot notation)
41
+ * @param {string} value - Configuration value
42
+ */
43
+ async function handleConfigSet(globalOptions, key, value) {
44
+ try {
45
+ const config = JSON.parse(await fs.readFile(globalOptions.config, "utf-8"));
46
+
47
+ // Parse value
48
+ let parsedValue;
49
+ try {
50
+ parsedValue = JSON.parse(value);
51
+ } catch (error) {
52
+ parsedValue = value; // Keep as string
53
+ }
54
+
55
+ // Validate key segments against prototype pollution
56
+ const keySegments = key.split(".");
57
+ const forbidden = new Set(["__proto__", "constructor", "prototype"]);
58
+ if (keySegments.some((k) => forbidden.has(k))) {
59
+ logger.error("Invalid configuration key: contains restricted property");
60
+ process.exit(1);
61
+ }
62
+
63
+ // Build a patch object from the key path, then merge via JSON round-trip
64
+ // This avoids dynamic property assignment entirely (no prototype pollution risk)
65
+ const patch = JSON.parse(
66
+ keySegments.reduceRight(
67
+ (val, seg) => JSON.stringify({ [seg]: JSON.parse(val) }),
68
+ JSON.stringify(parsedValue),
69
+ ),
70
+ );
71
+
72
+ // Shallow-merge at each level
73
+ function safeMerge(target, source) {
74
+ for (const k of Object.keys(source)) {
75
+ if (
76
+ source[k] &&
77
+ typeof source[k] === "object" &&
78
+ !Array.isArray(source[k]) &&
79
+ target[k] &&
80
+ typeof target[k] === "object"
81
+ ) {
82
+ safeMerge(target[k], source[k]);
83
+ } else {
84
+ target[k] = source[k];
85
+ }
86
+ }
87
+ }
88
+ safeMerge(config, patch);
89
+
90
+ // Save configuration
91
+ await fs.writeFile(globalOptions.config, JSON.stringify(config, null, 2));
92
+ console.log("✅ Configuration updated");
93
+ } catch (error) {
94
+ logger.error("❌ Failed to set configuration:", error.message);
95
+ process.exit(1);
96
+ }
97
+ }
98
+
99
+ /**
100
+ * Handle config get command
101
+ * @param {object} globalOptions - Global CLI options from program.opts()
102
+ * @param {string} key - Configuration key (dot notation)
103
+ */
104
+ async function handleConfigGet(globalOptions, key) {
105
+ try {
106
+ const config = JSON.parse(await fs.readFile(globalOptions.config, "utf-8"));
107
+
108
+ const keys = key.split(".");
109
+ let value = config;
110
+
111
+ for (const k of keys) {
112
+ value = value[k];
113
+ if (value === undefined) {
114
+ console.log("❌ Key not found");
115
+ return;
116
+ }
117
+ }
118
+
119
+ console.log(JSON.stringify(value, null, 2));
120
+ } catch (error) {
121
+ logger.error("❌ Failed to get configuration:", error.message);
122
+ process.exit(1);
123
+ }
124
+ }
125
+
126
+ module.exports = { handleConfigShow, handleConfigSet, handleConfigGet };
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Diagnostics command handlers
3
+ * Handles doctor, validate, and info commands
4
+ */
5
+
6
+ const fs = require("fs/promises");
7
+ const { logger } = require("../../utils/logger.js");
8
+
9
+ /**
10
+ * Handle doctor command
11
+ * @param {object} globalOptions - Global CLI options from program.opts()
12
+ * @param {object} options - Command-specific options
13
+ * @param {Function} pipelineDoctorFn - Pipeline doctor function
14
+ */
15
+ async function handleDoctor(globalOptions, options, pipelineDoctorFn) {
16
+ try {
17
+ const doctorOptions = {
18
+ configPath: globalOptions.config,
19
+ verbose: globalOptions.verbose,
20
+ autoFix: options.autoFix,
21
+ categories: options.category,
22
+ };
23
+
24
+ const report = await pipelineDoctorFn(doctorOptions);
25
+
26
+ if (options.report) {
27
+ await fs.writeFile(options.report, JSON.stringify(report, null, 2));
28
+ console.log(`📋 Diagnostic report saved to: ${options.report}`);
29
+ }
30
+ } catch (error) {
31
+ logger.error("❌ Doctor command failed:", error.message);
32
+ process.exit(1);
33
+ }
34
+ }
35
+
36
+ /**
37
+ * Handle validate command
38
+ * @param {object} globalOptions - Global CLI options from program.opts()
39
+ * @param {object} options - Command-specific options
40
+ * @param {Function} validateSchemaFn - Schema validation function
41
+ */
42
+ async function handleValidate(globalOptions, options, validateSchemaFn) {
43
+ try {
44
+ const configPath = globalOptions.config;
45
+
46
+ console.log(`🔍 Validating configuration: ${configPath}`);
47
+
48
+ // Load and validate configuration
49
+ const configContent = await fs.readFile(configPath, "utf-8");
50
+ const config = JSON.parse(configContent);
51
+
52
+ const validation = validateSchemaFn(config);
53
+
54
+ if (validation.valid) {
55
+ console.log("✅ Configuration is valid");
56
+
57
+ if (validation.legacy) {
58
+ console.log("⚠️ Using legacy format - consider upgrading");
59
+ }
60
+ } else {
61
+ console.log("❌ Configuration validation failed:");
62
+ validation.errors?.forEach((error) => {
63
+ console.log(` ${error.instancePath || "root"}: ${error.message}`);
64
+ });
65
+ }
66
+ } catch (error) {
67
+ logger.error("❌ Validation failed:", error.message);
68
+ process.exit(1);
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Handle info command
74
+ * @param {object} globalOptions - Global CLI options from program.opts()
75
+ * @param {object} options - Command-specific options
76
+ */
77
+ async function handleInfo(globalOptions, options) {
78
+ try {
79
+ console.log("📊 RAG Pipeline Information\n");
80
+
81
+ // System information
82
+ if ((!options.plugins && !options.config) || options.system) {
83
+ console.log("System:");
84
+ console.log(` Node.js: ${process.version}`);
85
+ console.log(` Platform: ${process.platform} ${process.arch}`);
86
+ console.log(
87
+ ` Memory: ${Math.round(process.memoryUsage().heapUsed / 1024 / 1024)}MB used`,
88
+ );
89
+ console.log("");
90
+ }
91
+
92
+ // Configuration summary
93
+ if ((!options.system && !options.plugins) || options.config) {
94
+ try {
95
+ const config = JSON.parse(
96
+ await fs.readFile(globalOptions.config, "utf-8"),
97
+ );
98
+ console.log("Configuration:");
99
+ console.log(` File: ${globalOptions.config}`);
100
+ console.log(` Format: ${config.plugins ? "Enhanced" : "Legacy"}`);
101
+ console.log("");
102
+ } catch (error) {
103
+ console.log("Configuration: Not found or invalid");
104
+ console.log("");
105
+ }
106
+ }
107
+ } catch (error) {
108
+ logger.error("❌ Failed to get system information:", error.message);
109
+ process.exit(1);
110
+ }
111
+ }
112
+
113
+ module.exports = { handleDoctor, handleValidate, handleInfo };
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Ingest command handler
3
+ * Handles document ingestion into the pipeline
4
+ */
5
+
6
+ const { logger } = require("../../utils/logger.js");
7
+
8
+ /**
9
+ * Handle ingest command
10
+ * @param {object} globalOptions - Global CLI options from program.opts()
11
+ * @param {string} file - Document file path
12
+ * @param {object} options - Command-specific options
13
+ */
14
+ async function handleIngest(globalOptions, file, options) {
15
+ try {
16
+ if (globalOptions.dryRun) {
17
+ console.log("🧪 Dry run: Would ingest document");
18
+ console.log(`File: ${file}`);
19
+ console.log(
20
+ `Parallel processing: ${options.parallel ? "enabled" : "disabled"}`,
21
+ );
22
+ console.log(`Streaming: ${options.streaming ? "enabled" : "disabled"}`);
23
+ console.log(`Tracing: ${options.trace ? "enabled" : "disabled"}`);
24
+
25
+ if (options.preview) {
26
+ console.log("📄 Document Preview:");
27
+ }
28
+ if (options.validate) {
29
+ console.log("File validation passed");
30
+ }
31
+ return;
32
+ }
33
+
34
+ console.log(`📄 Ingesting document: ${file}`);
35
+ console.log("✅ Document ingested successfully!");
36
+ } catch (error) {
37
+ logger.error("❌ Document ingestion failed:", error.message);
38
+ process.exit(1);
39
+ }
40
+ }
41
+
42
+ module.exports = { handleIngest };
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Init command handler
3
+ * Handles RAG pipeline configuration initialization
4
+ */
5
+
6
+ const fs = require("fs/promises");
7
+ const { logger } = require("../../utils/logger.js");
8
+
9
+ /**
10
+ * Handle init command
11
+ * @param {object} globalOptions - Global CLI options from program.opts()
12
+ * @param {object} options - Command-specific options
13
+ * @param {Function} createBasicConfigFn - Function to create basic config
14
+ */
15
+ async function handleInit(globalOptions, options, createBasicConfigFn) {
16
+ try {
17
+ if (globalOptions.dryRun) {
18
+ console.log("🧪 Dry run: Would initialize RAG pipeline configuration");
19
+ console.log(`Output file: ${options.output}`);
20
+ console.log(`Interactive mode: ${!options.noInteractive}`);
21
+ return;
22
+ }
23
+
24
+ // Check if config already exists
25
+ if (!options.force) {
26
+ try {
27
+ await fs.access(options.output);
28
+ console.log(`❌ Configuration file already exists: ${options.output}`);
29
+ console.log(
30
+ "Use --force to overwrite or choose a different output path.",
31
+ );
32
+ return;
33
+ } catch (error) {
34
+ // File doesn't exist, which is good
35
+ }
36
+ }
37
+
38
+ if (!options.noInteractive) {
39
+ console.log("🧙‍♂️ Starting interactive configuration wizard...\n");
40
+ // Mock interactive wizard
41
+ await createBasicConfigFn(options.output);
42
+ } else {
43
+ await createBasicConfigFn(options.output);
44
+ }
45
+ } catch (error) {
46
+ logger.error("❌ Initialization failed:", error.message);
47
+ process.exit(1);
48
+ }
49
+ }
50
+
51
+ module.exports = { handleInit };
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Query command handler
3
+ * Handles RAG pipeline queries
4
+ */
5
+
6
+ const { logger } = require("../../utils/logger.js");
7
+
8
+ /**
9
+ * Handle query command
10
+ * @param {object} globalOptions - Global CLI options from program.opts()
11
+ * @param {string} prompt - Query prompt
12
+ * @param {object} options - Command-specific options
13
+ */
14
+ async function handleQuery(globalOptions, prompt, options) {
15
+ try {
16
+ if (globalOptions.dryRun) {
17
+ console.log("🧪 Dry run: Would execute query");
18
+ console.log(
19
+ `Prompt: ${prompt.substring(0, 100)}${prompt.length > 100 ? "..." : ""}`,
20
+ );
21
+ console.log(`Streaming: ${options.stream ? "enabled" : "disabled"}`);
22
+
23
+ if (options.explain) {
24
+ console.log("🔍 Query Explanation:");
25
+ console.log("Processing steps:");
26
+ console.log(" 1. Text embedding generation");
27
+ console.log(" 2. Vector similarity search");
28
+ console.log(" 3. Context retrieval");
29
+ console.log(" 4. Language model generation");
30
+ }
31
+ return;
32
+ }
33
+
34
+ console.log(
35
+ `🤔 Processing query: ${prompt.substring(0, 100)}${prompt.length > 100 ? "..." : ""}`,
36
+ );
37
+ console.log("\n📝 Response:");
38
+ console.log("Mock response to query");
39
+ } catch (error) {
40
+ logger.error("❌ Query processing failed:", error.message);
41
+ process.exit(1);
42
+ }
43
+ }
44
+
45
+ module.exports = { handleQuery };
@@ -0,0 +1,181 @@
1
+ /**
2
+ * Run command handler
3
+ * Handles pipeline execution with streaming, abort, and progress support
4
+ */
5
+
6
+ const { logger } = require("../../utils/logger.js");
7
+ const { createProgressBar } = require("../shared/cli-utils.js");
8
+
9
+ /**
10
+ * Handle run command
11
+ * @param {object} globalOptions - Global CLI options from program.opts()
12
+ * @param {object} options - Command-specific options
13
+ */
14
+ async function handleRun(globalOptions, options) {
15
+ if (globalOptions.dryRun) {
16
+ logger.info("🧪 Dry run: Would execute pipeline operation");
17
+ if (options.ingest) logger.info(`Would ingest: ${options.ingest}`);
18
+ if (options.query)
19
+ logger.info(`Would query: ${options.query.substring(0, 100)}...`);
20
+ logger.info(`Streaming: ${options.stream ? "enabled" : "disabled"}`);
21
+ logger.info(`Parallel: ${options.parallel ? "enabled" : "disabled"}`);
22
+ if (options.abortTimeout)
23
+ logger.info(`Abort timeout: ${options.abortTimeout}ms`);
24
+ return;
25
+ }
26
+
27
+ try {
28
+ // Load configuration
29
+ const { loadRagConfig } = require("../../config/load-config.js");
30
+ const config = await loadRagConfig(globalOptions.config);
31
+
32
+ // Create AbortController for timeout handling
33
+ const abortController = new AbortController();
34
+ let timeoutId;
35
+
36
+ if (options.abortTimeout) {
37
+ timeoutId = setTimeout(() => {
38
+ logger.warn(
39
+ `Operation aborted after ${options.abortTimeout}ms timeout`,
40
+ );
41
+ abortController.abort();
42
+ }, options.abortTimeout);
43
+ }
44
+
45
+ // Setup SIGINT handling for clean shutdown
46
+ const sigintHandler = () => {
47
+ logger.info("Received SIGINT, aborting operation...");
48
+ abortController.abort();
49
+ if (timeoutId) clearTimeout(timeoutId);
50
+ };
51
+ process.once("SIGINT", sigintHandler);
52
+
53
+ try {
54
+ // Create pipeline with performance options
55
+ const { createRagPipeline } = require("../../core/create-pipeline.js");
56
+ const pipeline = createRagPipeline(config.pipeline[0], {
57
+ useParallelProcessing: options.parallel,
58
+ useStreamingSafeguards: options.stream,
59
+ useLogging: true,
60
+ useRetry: true,
61
+ });
62
+
63
+ // Execute operation based on options
64
+ if (options.ingest) {
65
+ logger.info(`Starting ingestion of: ${options.ingest}`);
66
+
67
+ if (options.stream) {
68
+ let lastProgressTime = Date.now();
69
+ for await (const progress of pipeline.ingestStream(options.ingest)) {
70
+ if (abortController.signal.aborted) {
71
+ logger.info("Ingestion aborted");
72
+ break;
73
+ }
74
+
75
+ const now = Date.now();
76
+ if (progress.type === "chunk_processed") {
77
+ // Show progress ticks every 500ms or every 10 chunks
78
+ if (
79
+ now - lastProgressTime > 500 ||
80
+ progress.progress.processed % 10 === 0
81
+ ) {
82
+ const percentage = Math.round(
83
+ (progress.progress.processed / progress.progress.total) * 100,
84
+ );
85
+ const progressBar = createProgressBar(percentage, 20);
86
+ process.stdout.write(
87
+ `\r${progressBar} ${percentage}% (${progress.progress.processed}/${progress.progress.total}) `,
88
+ );
89
+ lastProgressTime = now;
90
+ }
91
+ } else if (progress.type === "ingest_complete") {
92
+ process.stdout.write("\n");
93
+ logger.info(
94
+ `✅ Ingestion complete: ${progress.summary.processedChunks}/${progress.summary.totalChunks} chunks processed`,
95
+ );
96
+ if (progress.summary.failedChunks > 0) {
97
+ logger.warn(
98
+ `⚠️ ${progress.summary.failedChunks} chunks failed`,
99
+ );
100
+ }
101
+ } else if (progress.type === "chunk_failed") {
102
+ process.stdout.write("✗");
103
+ }
104
+ }
105
+ } else {
106
+ // Non-streaming ingestion with progress callback
107
+ let currentStage = "";
108
+ const progressCallback = (progress) => {
109
+ if (progress.stage !== currentStage) {
110
+ if (currentStage) process.stdout.write("\n");
111
+ currentStage = progress.stage;
112
+ logger.info(
113
+ `${progress.stage}: ${progress.message || "Processing..."}`,
114
+ );
115
+ }
116
+ if (
117
+ progress.completed !== undefined &&
118
+ progress.total !== undefined
119
+ ) {
120
+ const percentage = Math.round(
121
+ (progress.completed / progress.total) * 100,
122
+ );
123
+ const progressBar = createProgressBar(percentage, 20);
124
+ process.stdout.write(
125
+ `\r${progressBar} ${percentage}% (${progress.completed}/${progress.total}) `,
126
+ );
127
+ }
128
+ };
129
+
130
+ const pipelineWithProgress = createRagPipeline(config.pipeline[0], {
131
+ useParallelProcessing: options.parallel,
132
+ useStreamingSafeguards: false,
133
+ useLogging: true,
134
+ useRetry: true,
135
+ onProgress: progressCallback,
136
+ });
137
+
138
+ await pipelineWithProgress.ingest(options.ingest);
139
+ process.stdout.write("\n");
140
+ logger.info("✅ Ingestion completed successfully");
141
+ }
142
+ }
143
+
144
+ if (options.query) {
145
+ logger.info(`Executing query: ${options.query.substring(0, 100)}...`);
146
+
147
+ if (options.stream) {
148
+ process.stdout.write("\nResponse: ");
149
+ for await (const token of pipeline.queryStream(options.query)) {
150
+ if (abortController.signal.aborted) {
151
+ logger.info("\nQuery aborted");
152
+ break;
153
+ }
154
+ process.stdout.write(token);
155
+ }
156
+ process.stdout.write("\n\n");
157
+ } else {
158
+ const response = await pipeline.query(options.query);
159
+ logger.info("Query completed successfully");
160
+ console.log("\nResponse:", response);
161
+ }
162
+ }
163
+
164
+ if (!options.ingest && !options.query) {
165
+ logger.error(
166
+ "No operation specified. Use --ingest <file> or --query <prompt>",
167
+ );
168
+ process.exit(1);
169
+ }
170
+ } finally {
171
+ // Cleanup
172
+ process.removeListener("SIGINT", sigintHandler);
173
+ if (timeoutId) clearTimeout(timeoutId);
174
+ }
175
+ } catch (error) {
176
+ logger.error("Pipeline operation failed", { error: error.message });
177
+ process.exit(1);
178
+ }
179
+ }
180
+
181
+ module.exports = { handleRun };