@devilsdev/rag-pipeline-utils 2.3.1 → 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 -369
  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
@@ -1,19 +1,18 @@
1
1
  /**
2
2
  * Advanced AI/ML CLI Commands
3
3
  * Command-line interface for model training, adaptive retrieval, multi-modal processing, and federated learning
4
+ *
5
+ * This module is a thin aggregator that delegates to domain-specific modules
6
+ * in the ai-ml/ directory.
4
7
  */
5
8
 
6
- const chalk = require('chalk');
9
+ const chalk = require("chalk");
7
10
  // eslint-disable-line global-require
8
- const ora = require('ora');
11
+ const ora = require("ora");
9
12
  // eslint-disable-line global-require
10
- const inquirer = require('inquirer');
13
+ const Table = require("cli-table3");
11
14
  // eslint-disable-line global-require
12
- const Table = require('cli-table3');
13
- // eslint-disable-line global-require
14
- const fs = require('fs').promises;
15
- // eslint-disable-line global-require
16
- const _path = require('path');
15
+ const fs = require("fs").promises;
17
16
  // eslint-disable-line global-require
18
17
 
19
18
  const {
@@ -21,9 +20,18 @@ const {
21
20
  AdaptiveRetrievalEngine,
22
21
  MultiModalProcessor,
23
22
  FederatedLearningCoordinator,
24
- } = require('../../ai');
23
+ } = require("../../ai");
25
24
  // eslint-disable-line global-require
26
25
 
26
+ const {
27
+ trainingCommands,
28
+ adaptiveCommands,
29
+ multimodalCommands,
30
+ federatedCommands,
31
+ } = require("./ai-ml/index");
32
+
33
+ const { colorizeStatus, detectContentType } = require("./ai-ml/shared");
34
+
27
35
  class AIMLCommands {
28
36
  constructor() {
29
37
  this.modelTrainer = new ModelTrainingOrchestrator();
@@ -37,844 +45,280 @@ class AIMLCommands {
37
45
  */
38
46
  registerCommands(program) {
39
47
  const aiCommand = program
40
- .command('ai')
41
- .description('Advanced AI/ML capabilities');
48
+ .command("ai")
49
+ .description("Advanced AI/ML capabilities");
42
50
 
43
51
  // Model Training Commands
44
52
  const trainCommand = aiCommand
45
- .command('train')
46
- .description('Model training and fine-tuning');
53
+ .command("train")
54
+ .description("Model training and fine-tuning");
47
55
 
48
56
  trainCommand
49
- .command('embedding')
50
- .description('Train custom embedding model')
51
- .option('-t, --tenant <id>', 'Tenant ID')
52
- .option('-d, --dataset <path>', 'Dataset path')
53
- .option('-a, --architecture <arch>', 'Model architecture', 'transformer')
54
- .option('-e, --epochs <num>', 'Number of epochs', '10')
55
- .option('-b, --batch-size <size>', 'Batch size', '32')
56
- .option('-l, --learning-rate <rate>', 'Learning rate', '0.001')
57
- .option('--optimize', 'Enable hyperparameter optimization')
57
+ .command("embedding")
58
+ .description("Train custom embedding model")
59
+ .option("-t, --tenant <id>", "Tenant ID")
60
+ .option("-d, --dataset <path>", "Dataset path")
61
+ .option("-a, --architecture <arch>", "Model architecture", "transformer")
62
+ .option("-e, --epochs <num>", "Number of epochs", "10")
63
+ .option("-b, --batch-size <size>", "Batch size", "32")
64
+ .option("-l, --learning-rate <rate>", "Learning rate", "0.001")
65
+ .option("--optimize", "Enable hyperparameter optimization")
58
66
  .action(this.trainEmbeddingModel.bind(this));
59
67
 
60
68
  trainCommand
61
- .command('llm')
62
- .description('Fine-tune language model')
63
- .option('-t, --tenant <id>', 'Tenant ID')
64
- .option('-d, --dataset <path>', 'Dataset path')
65
- .option('-m, --base-model <model>', 'Base model', 'gpt-3.5-turbo')
66
- .option('-e, --epochs <num>', 'Number of epochs', '5')
67
- .option('--lora', 'Use LoRA fine-tuning')
69
+ .command("llm")
70
+ .description("Fine-tune language model")
71
+ .option("-t, --tenant <id>", "Tenant ID")
72
+ .option("-d, --dataset <path>", "Dataset path")
73
+ .option("-m, --base-model <model>", "Base model", "gpt-3.5-turbo")
74
+ .option("-e, --epochs <num>", "Number of epochs", "5")
75
+ .option("--lora", "Use LoRA fine-tuning")
68
76
  .action(this.fineTuneLLM.bind(this));
69
77
 
70
78
  trainCommand
71
- .command('status <jobId>')
72
- .description('Check training job status')
79
+ .command("status <jobId>")
80
+ .description("Check training job status")
73
81
  .action(this.checkTrainingStatus.bind(this));
74
82
 
75
83
  trainCommand
76
- .command('deploy <jobId>')
77
- .description('Deploy trained model')
78
- .option('-e, --environment <env>', 'Deployment environment', 'staging')
79
- .option('--auto-scale', 'Enable auto-scaling')
84
+ .command("deploy <jobId>")
85
+ .description("Deploy trained model")
86
+ .option("-e, --environment <env>", "Deployment environment", "staging")
87
+ .option("--auto-scale", "Enable auto-scaling")
80
88
  .action(this.deployModel.bind(this));
81
89
 
82
90
  // Adaptive Retrieval Commands
83
91
  const adaptiveCommand = aiCommand
84
- .command('adaptive')
85
- .description('Adaptive retrieval system');
92
+ .command("adaptive")
93
+ .description("Adaptive retrieval system");
86
94
 
87
95
  adaptiveCommand
88
- .command('profile <userId>')
89
- .description('Initialize or view user profile')
90
- .option('-i, --interests <interests>', 'User interests (comma-separated)')
91
- .option('-e, --expertise <level>', 'Expertise level', 'intermediate')
96
+ .command("profile <userId>")
97
+ .description("Initialize or view user profile")
98
+ .option("-i, --interests <interests>", "User interests (comma-separated)")
99
+ .option("-e, --expertise <level>", "Expertise level", "intermediate")
92
100
  .action(this.manageUserProfile.bind(this));
93
101
 
94
102
  adaptiveCommand
95
- .command('search <userId> <query>')
96
- .description('Perform adaptive search')
97
- .option('-n, --max-results <num>', 'Maximum results', '10')
98
- .option('--explain', 'Show adaptation explanation')
103
+ .command("search <userId> <query>")
104
+ .description("Perform adaptive search")
105
+ .option("-n, --max-results <num>", "Maximum results", "10")
106
+ .option("--explain", "Show adaptation explanation")
99
107
  .action(this.adaptiveSearch.bind(this));
100
108
 
101
109
  adaptiveCommand
102
- .command('feedback <userId>')
103
- .description('Provide feedback for learning')
104
- .option('-q, --query <query>', 'Original query')
105
- .option('-r, --ratings <ratings>', 'Result ratings (comma-separated)')
110
+ .command("feedback <userId>")
111
+ .description("Provide feedback for learning")
112
+ .option("-q, --query <query>", "Original query")
113
+ .option("-r, --ratings <ratings>", "Result ratings (comma-separated)")
106
114
  .action(this.provideFeedback.bind(this));
107
115
 
108
116
  // Multi-modal Processing Commands
109
117
  const multimodalCommand = aiCommand
110
- .command('multimodal')
111
- .description('Multi-modal content processing');
118
+ .command("multimodal")
119
+ .description("Multi-modal content processing");
112
120
 
113
121
  multimodalCommand
114
- .command('process <contentPath>')
115
- .description('Process multi-modal content')
116
- .option('-t, --tenant <id>', 'Tenant ID')
117
- .option('-o, --output <path>', 'Output path for results')
118
- .option('--extract-text', 'Extract text from images/videos')
122
+ .command("process <contentPath>")
123
+ .description("Process multi-modal content")
124
+ .option("-t, --tenant <id>", "Tenant ID")
125
+ .option("-o, --output <path>", "Output path for results")
126
+ .option("--extract-text", "Extract text from images/videos")
119
127
  .action(this.processMultiModalContent.bind(this));
120
128
 
121
129
  multimodalCommand
122
- .command('search <tenantId>')
123
- .description('Multi-modal search')
124
- .option('-q, --query <query>', 'Text query')
125
- .option('-i, --image <path>', 'Image query path')
126
- .option('-a, --audio <path>', 'Audio query path')
127
- .option('-n, --max-results <num>', 'Maximum results', '10')
130
+ .command("search <tenantId>")
131
+ .description("Multi-modal search")
132
+ .option("-q, --query <query>", "Text query")
133
+ .option("-i, --image <path>", "Image query path")
134
+ .option("-a, --audio <path>", "Audio query path")
135
+ .option("-n, --max-results <num>", "Maximum results", "10")
128
136
  .action(this.multiModalSearch.bind(this));
129
137
 
130
138
  multimodalCommand
131
- .command('describe <contentId>')
132
- .description('Generate content description')
133
- .option('--detailed', 'Generate detailed description')
139
+ .command("describe <contentId>")
140
+ .description("Generate content description")
141
+ .option("--detailed", "Generate detailed description")
134
142
  .action(this.describeContent.bind(this));
135
143
 
136
144
  // Federated Learning Commands
137
145
  const federatedCommand = aiCommand
138
- .command('federated')
139
- .description('Federated learning coordination');
146
+ .command("federated")
147
+ .description("Federated learning coordination");
140
148
 
141
149
  federatedCommand
142
- .command('create-federation')
143
- .description('Create federated learning session')
144
- .option('-t, --tenant <id>', 'Tenant ID')
145
- .option('-m, --model-_type <_type>', 'Model _type', 'embedding')
146
- .option('-a, --architecture <arch>', 'Model architecture', 'transformer')
147
- .option('--min-participants <num>', 'Minimum participants', '3')
148
- .option('--max-participants <num>', 'Maximum participants', '10')
150
+ .command("create-federation")
151
+ .description("Create federated learning session")
152
+ .option("-t, --tenant <id>", "Tenant ID")
153
+ .option("-m, --model-_type <_type>", "Model _type", "embedding")
154
+ .option("-a, --architecture <arch>", "Model architecture", "transformer")
155
+ .option("--min-participants <num>", "Minimum participants", "3")
156
+ .option("--max-participants <num>", "Maximum participants", "10")
149
157
  .action(this.createFederation.bind(this));
150
158
 
151
159
  federatedCommand
152
- .command('join <federationId>')
153
- .description('Join federated learning session')
154
- .option('-t, --tenant <id>', 'Tenant ID')
155
- .option('-d, --data-size <size>', 'Data size')
156
- .option('-c, --compute-capacity <capacity>', 'Compute capacity (0-1)')
157
- .option('-p, --privacy-level <level>', 'Privacy level', 'standard')
160
+ .command("join <federationId>")
161
+ .description("Join federated learning session")
162
+ .option("-t, --tenant <id>", "Tenant ID")
163
+ .option("-d, --data-size <size>", "Data size")
164
+ .option("-c, --compute-capacity <capacity>", "Compute capacity (0-1)")
165
+ .option("-p, --privacy-level <level>", "Privacy level", "standard")
158
166
  .action(this.joinFederation.bind(this));
159
167
 
160
168
  federatedCommand
161
- .command('start-round <federationId>')
162
- .description('Start federated learning round')
169
+ .command("start-round <federationId>")
170
+ .description("Start federated learning round")
163
171
  .action(this.startFederatedRound.bind(this));
164
172
 
165
173
  federatedCommand
166
- .command('stats <federationId>')
167
- .description('Show federation statistics')
168
- .option('--detailed', 'Show detailed statistics')
174
+ .command("stats <federationId>")
175
+ .description("Show federation statistics")
176
+ .option("--detailed", "Show detailed statistics")
169
177
  .action(this.showFederationStats.bind(this));
170
178
 
171
179
  // General AI Commands
172
180
  aiCommand
173
- .command('benchmark')
174
- .description('Run AI/ML benchmarks')
175
- .option('-t, --tenant <id>', 'Tenant ID')
176
- .option('-m, --models <models>', 'Models to benchmark (comma-separated)')
177
- .option('-o, --output <path>', 'Output path for results')
181
+ .command("benchmark")
182
+ .description("Run AI/ML benchmarks")
183
+ .option("-t, --tenant <id>", "Tenant ID")
184
+ .option("-m, --models <models>", "Models to benchmark (comma-separated)")
185
+ .option("-o, --output <path>", "Output path for results")
178
186
  .action(this.runBenchmarks.bind(this));
179
187
 
180
188
  aiCommand
181
- .command('dashboard')
182
- .description('Launch AI/ML dashboard')
183
- .option('-p, --port <port>', 'Dashboard port', '3001')
184
- .option('--open', 'Open browser automatically')
189
+ .command("dashboard")
190
+ .description("Launch AI/ML dashboard")
191
+ .option("-p, --port <port>", "Dashboard port", "3001")
192
+ .option("--open", "Open browser automatically")
185
193
  .action(this.launchDashboard.bind(this));
186
194
  }
187
195
 
196
+ // --- Delegating methods ---
197
+
188
198
  // Model Training Commands
189
199
  async trainEmbeddingModel(_options) {
190
- const spinner = ora('Initializing embedding model training...').start();
191
-
192
- try {
193
- if (!_options.tenant) {
194
- spinner.fail('Tenant ID is required');
195
- return;
196
- }
197
-
198
- const trainingConfig = {
199
- modelType: 'embedding',
200
- architecture: _options.architecture,
201
- dataset: {
202
- path: _options.dataset,
203
- _type: 'text_pairs',
204
- },
205
- hyperparameters: {
206
- epochs: parseInt(_options.epochs),
207
- batchSize: parseInt(_options.batchSize),
208
- learningRate: parseFloat(_options.learningRate),
209
- },
210
- };
211
-
212
- spinner.text = 'Creating training job...';
213
- const jobId = await this.modelTrainer.createTrainingJob(
214
- _options.tenant,
215
- trainingConfig,
216
- );
217
-
218
- if (_options.optimize) {
219
- spinner.text = 'Starting hyperparameter optimization...';
220
- const optimizationConfig = {
221
- ...trainingConfig,
222
- hyperparameters: {
223
- learningRate: [0.0001, 0.001, 0.01],
224
- batchSize: [16, 32, 64],
225
- hiddenSize: [256, 512, 768],
226
- },
227
- optimization: {
228
- strategy: 'bayesian',
229
- maxTrials: 10,
230
- metric: 'accuracy',
231
- },
232
- };
233
-
234
- const optimizationId = await this.modelTrainer.optimizeHyperparameters(
235
- _options.tenant,
236
- optimizationConfig,
237
- );
238
-
239
- spinner.succeed(
240
- `Hyperparameter optimization started: ${optimizationId}`,
241
- );
242
- } else {
243
- spinner.text = 'Starting training...';
244
- await this.modelTrainer.startTraining(jobId);
245
- spinner.succeed(`Training started: ${jobId}`);
246
- }
247
-
248
- console.log(chalk.green('\n✓ Training initiated successfully'));
249
- // eslint-disable-line no-console
250
- console.log(chalk.blue(`Job ID: ${jobId}`));
251
- // eslint-disable-line no-console
252
- console.log(
253
- chalk.gray(
254
- `Use 'rag-pipeline ai train status ${jobId}' to check progress`,
255
- ),
256
- );
257
- // eslint-disable-line no-console
258
- } catch (error) {
259
- spinner.fail(`Training failed: ${error.message}`);
260
- }
200
+ return trainingCommands.trainEmbeddingModel(this.modelTrainer, _options);
261
201
  }
262
202
 
263
203
  async fineTuneLLM(_options) {
264
- const spinner = ora('Initializing LLM fine-tuning...').start();
265
-
266
- try {
267
- if (!_options.tenant) {
268
- spinner.fail('Tenant ID is required');
269
- return;
270
- }
271
-
272
- const trainingConfig = {
273
- modelType: 'llm',
274
- baseModel: _options.baseModel,
275
- dataset: {
276
- path: _options.dataset,
277
- _type: 'instruction_following',
278
- },
279
- fineTuning: {
280
- method: _options.lora ? 'lora' : 'full',
281
- epochs: parseInt(_options.epochs),
282
- learningRate: 0.0001,
283
- },
284
- };
285
-
286
- spinner.text = 'Creating fine-tuning job...';
287
- const jobId = await this.modelTrainer.createTrainingJob(
288
- _options.tenant,
289
- trainingConfig,
290
- );
291
-
292
- spinner.text = 'Starting fine-tuning...';
293
- await this.modelTrainer.startTraining(jobId);
294
-
295
- spinner.succeed(`Fine-tuning started: ${jobId}`);
296
- console.log(chalk.green('\n✓ LLM fine-tuning initiated'));
297
- // eslint-disable-line no-console
298
- console.log(chalk.blue(`Job ID: ${jobId}`));
299
- // eslint-disable-line no-console
300
- } catch (error) {
301
- spinner.fail(`Fine-tuning failed: ${error.message}`);
302
- }
204
+ return trainingCommands.fineTuneLLM(this.modelTrainer, _options);
303
205
  }
304
206
 
305
207
  async checkTrainingStatus(jobId) {
306
- const spinner = ora('Checking training status...').start();
307
-
308
- try {
309
- const status = await this.modelTrainer.getTrainingStatus(jobId);
310
- spinner.stop();
311
-
312
- const table = new Table({
313
- head: ['Property', 'Value'],
314
- colWidths: [20, 50],
315
- });
316
-
317
- table.push(
318
- ['Job ID', jobId],
319
- ['Status', this._colorizeStatus(status.status)],
320
- ['Progress', `${status.progress}%`],
321
- ['Current Epoch', `${status.currentEpoch}/${status.totalEpochs}`],
322
- ['Accuracy', status.metrics?.accuracy?.toFixed(4) || 'N/A'],
323
- ['Loss', status.metrics?.loss?.toFixed(4) || 'N/A'],
324
- ['Estimated Time', status.estimatedTimeRemaining || 'N/A'],
325
- );
326
-
327
- console.log(table.toString());
328
- // eslint-disable-line no-console
329
-
330
- if (status.status === 'completed') {
331
- console.log(chalk.green('\n✓ Training completed successfully!'));
332
- // eslint-disable-line no-console
333
- console.log(
334
- chalk.blue(
335
- `Use 'rag-pipeline ai train deploy ${jobId}' to deploy the model`,
336
- ),
337
- );
338
- // eslint-disable-line no-console
339
- } else if (status.status === 'failed') {
340
- console.log(chalk.red('\n✗ Training failed'));
341
- // eslint-disable-line no-console
342
- if (status.error) {
343
- console.log(chalk.gray(`Error: ${status.error}`));
344
- // eslint-disable-line no-console
345
- }
346
- }
347
- } catch (error) {
348
- spinner.fail(`Failed to get status: ${error.message}`);
349
- }
208
+ return trainingCommands.checkTrainingStatus(this.modelTrainer, jobId);
350
209
  }
351
210
 
352
211
  async deployModel(jobId, _options) {
353
- const spinner = ora('Deploying model...').start();
354
-
355
- try {
356
- const deploymentConfig = {
357
- environment: _options.environment,
358
- scalingConfig: {
359
- minInstances: 1,
360
- maxInstances: _options.autoScale ? 5 : 1,
361
- autoScale: !!_options.autoScale,
362
- },
363
- };
364
-
365
- const deploymentId = await this.modelTrainer.deployModel(
366
- jobId,
367
- deploymentConfig,
368
- );
369
-
370
- spinner.succeed(`Model deployed: ${deploymentId}`);
371
- console.log(chalk.green('\n✓ Model deployment successful'));
372
- // eslint-disable-line no-console
373
- console.log(chalk.blue(`Deployment ID: ${deploymentId}`));
374
- // eslint-disable-line no-console
375
- console.log(chalk.blue(`Environment: ${_options.environment}`));
376
- // eslint-disable-line no-console
377
- } catch (error) {
378
- spinner.fail(`Deployment failed: ${error.message}`);
379
- }
212
+ return trainingCommands.deployModel(this.modelTrainer, jobId, _options);
380
213
  }
381
214
 
382
215
  // Adaptive Retrieval Commands
383
216
  async manageUserProfile(userId, _options) {
384
- const spinner = ora('Managing user profile...').start();
385
-
386
- try {
387
- let profile;
388
-
389
- try {
390
- profile = await this.adaptiveRetrieval.getUserProfile(userId);
391
- spinner.succeed('User profile found');
392
- } catch {
393
- // Profile doesn't exist, create new one
394
- const profileData = {};
395
-
396
- if (_options.interests) {
397
- profileData.interests = _options.interests
398
- .split(',')
399
- .map((i) => i.trim());
400
- }
401
-
402
- if (_options.expertise) {
403
- profileData.expertise = _options.expertise;
404
- }
405
-
406
- profile = await this.adaptiveRetrieval.initializeUserProfile(
407
- userId,
408
- profileData,
409
- );
410
- spinner.succeed('User profile created');
411
- }
412
-
413
- const table = new Table({
414
- head: ['Property', 'Value'],
415
- colWidths: [20, 50],
416
- });
417
-
418
- table.push(
419
- ['User ID', profile.userId],
420
- ['Interests', profile.preferences?.interests?.join(', ') || 'None'],
421
- ['Expertise', profile.preferences?.expertise || 'Not set'],
422
- [
423
- 'Learning History',
424
- `${profile.learningHistory?.length || 0} interactions`,
425
- ],
426
- ['Created', profile.createdAt || 'Unknown'],
427
- );
428
-
429
- console.log(table.toString());
430
- // eslint-disable-line no-console
431
- } catch (error) {
432
- spinner.fail(`Profile management failed: ${error.message}`);
433
- }
217
+ return adaptiveCommands.manageUserProfile(
218
+ this.adaptiveRetrieval,
219
+ userId,
220
+ _options,
221
+ );
434
222
  }
435
223
 
436
224
  async adaptiveSearch(userId, query, _options) {
437
- const spinner = ora('Performing adaptive search...').start();
438
-
439
- try {
440
- const searchOptions = {
441
- maxResults: parseInt(_options.maxResults),
442
- explain: !!_options.explain,
443
- };
444
-
445
- const results = await this.adaptiveRetrieval.adaptiveRetrieve(
446
- userId,
447
- query,
448
- searchOptions,
449
- );
450
-
451
- spinner.succeed(`Found ${results.documents.length} results`);
452
-
453
- // Display results
454
- console.log(chalk.blue(`\nSearch Results for: "${query}"`));
455
- // eslint-disable-line no-console
456
- console.log(chalk.gray('='.repeat(50)));
457
- // eslint-disable-line no-console
458
-
459
- results.documents.forEach((doc, index) => {
460
- console.log(chalk.green(`\n${index + 1}. ${doc.title || doc.id}`));
461
- // eslint-disable-line no-console
462
- console.log(chalk.gray(` Score: ${doc.score?.toFixed(4) || 'N/A'}`));
463
- // eslint-disable-line no-console
464
- console.log(
465
- chalk.gray(
466
- ` Personalized Score: ${doc.personalizedScore?.toFixed(4) || 'N/A'}`,
467
- ),
468
- );
469
- // eslint-disable-line no-console
470
- console.log(` ${doc.content?.substring(0, 200)}...`);
471
- // eslint-disable-line no-console
472
- });
473
-
474
- if (_options.explain && results.adaptationMetadata) {
475
- console.log(chalk.blue('\nAdaptation Explanation:'));
476
- // eslint-disable-line no-console
477
- console.log(
478
- chalk.gray(JSON.stringify(results.adaptationMetadata, null, 2)),
479
- );
480
- // eslint-disable-line no-console
481
- }
482
- } catch (error) {
483
- spinner.fail(`Adaptive search failed: ${error.message}`);
484
- }
225
+ return adaptiveCommands.adaptiveSearch(
226
+ this.adaptiveRetrieval,
227
+ userId,
228
+ query,
229
+ _options,
230
+ );
485
231
  }
486
232
 
487
233
  async provideFeedback(userId, _options) {
488
- if (!_options.query) {
489
- const answers = await inquirer.prompt([
490
- {
491
- _type: 'input',
492
- name: 'query',
493
- message: 'Enter the original query:',
494
- },
495
- {
496
- _type: 'input',
497
- name: 'ratings',
498
- message: 'Enter ratings for results (comma-separated, 1-5):',
499
- },
500
- ]);
501
- _options.query = answers.query;
502
- _options.ratings = answers.ratings;
503
- }
504
-
505
- const spinner = ora('Processing feedback...').start();
506
-
507
- try {
508
- const ratings = _options.ratings
509
- .split(',')
510
- .map((r) => parseInt(r.trim()));
511
-
512
- const feedback = {
513
- query: _options.query,
514
- ratings,
515
- clickedResults: [0], // Assume first result was clicked
516
- dwellTime: [120], // Assume 2 minutes dwell time
517
- };
518
-
519
- await this.adaptiveRetrieval.processFeedback(userId, feedback);
520
-
521
- spinner.succeed('Feedback processed successfully');
522
- console.log(chalk.green('\n✓ User profile updated with feedback'));
523
- // eslint-disable-line no-console
524
- } catch (error) {
525
- spinner.fail(`Feedback processing failed: ${error.message}`);
526
- }
234
+ return adaptiveCommands.provideFeedback(
235
+ this.adaptiveRetrieval,
236
+ userId,
237
+ _options,
238
+ );
527
239
  }
528
240
 
529
241
  // Multi-modal Processing Commands
530
242
  async processMultiModalContent(contentPath, _options) {
531
- const spinner = ora('Processing multi-modal content...').start();
532
-
533
- try {
534
- if (!_options.tenant) {
535
- spinner.fail('Tenant ID is required');
536
- return;
537
- }
538
-
539
- // Read content file
540
- const stats = await fs.stat(contentPath);
541
- const content = {
542
- _type: this._detectContentType(contentPath),
543
- size: stats.size,
544
- path: contentPath,
545
- };
546
-
547
- // Add additional content based on type
548
- if (content._type.startsWith('text/')) {
549
- content.text = await fs.readFile(contentPath, 'utf-8');
550
- }
551
-
552
- spinner.text = 'Processing content...';
553
- const result = await this.multiModalProcessor.processContent(
554
- _options.tenant,
555
- content,
556
- );
557
-
558
- spinner.succeed('Content processed successfully');
559
-
560
- console.log(chalk.green('\n✓ Multi-modal processing completed'));
561
- // eslint-disable-line no-console
562
- console.log(chalk.blue(`Content ID: ${result.id}`));
563
- // eslint-disable-line no-console
564
- console.log(
565
- chalk.blue(
566
- `Modalities detected: ${Object.keys(result.modalities).join(', ')}`,
567
- ),
568
- );
569
- // eslint-disable-line no-console
570
- console.log(
571
- chalk.blue(`Processing time: ${result.metadata.processingTime}ms`),
572
- );
573
- // eslint-disable-line no-console
574
-
575
- if (_options.output) {
576
- await fs.writeFile(_options.output, JSON.stringify(result, null, 2));
577
- console.log(chalk.gray(`Results saved to: ${_options.output}`));
578
- // eslint-disable-line no-console
579
- }
580
- } catch (error) {
581
- spinner.fail(`Content processing failed: ${error.message}`);
582
- }
243
+ return multimodalCommands.processMultiModalContent(
244
+ this.multiModalProcessor,
245
+ contentPath,
246
+ _options,
247
+ );
583
248
  }
584
249
 
585
250
  async multiModalSearch(tenantId, _options) {
586
- const spinner = ora('Performing multi-modal search...').start();
587
-
588
- try {
589
- const query = {};
590
-
591
- if (_options.query) {
592
- query.text = _options.query;
593
- query._type = 'text';
594
- }
595
-
596
- if (_options.image) {
597
- query.image = await fs.readFile(_options.image);
598
- query._type = 'image';
599
- }
600
-
601
- if (_options.audio) {
602
- query.audio = await fs.readFile(_options.audio);
603
- query._type = 'audio';
604
- }
605
-
606
- if (Object.keys(query).length === 0) {
607
- spinner.fail('At least one query _type must be provided');
608
- return;
609
- }
610
-
611
- const searchOptions = {
612
- maxResults: parseInt(_options.maxResults),
613
- };
614
-
615
- const results = await this.multiModalProcessor.multiModalSearch(
616
- tenantId,
617
- query,
618
- searchOptions,
619
- );
620
-
621
- spinner.succeed(`Found ${results.results.length} results`);
622
-
623
- console.log(chalk.blue('\nMulti-modal Search Results:'));
624
- // eslint-disable-line no-console
625
- console.log(chalk.gray('='.repeat(50)));
626
- // eslint-disable-line no-console
627
-
628
- results.results.forEach((result, index) => {
629
- console.log(
630
- chalk.green(`\n${index + 1}. Content ID: ${result.contentId}`),
631
- );
632
- // eslint-disable-line no-console
633
- console.log(
634
- chalk.gray(
635
- ` Multi-modal Score: ${result.multiModalScore?.toFixed(4)}`,
636
- ),
637
- );
638
- // eslint-disable-line no-console
639
- console.log(
640
- chalk.gray(` Modalities: ${result.modalities?.join(', ')}`),
641
- );
642
- // eslint-disable-line no-console
643
- console.log(chalk.gray(` Rank: ${result.rank}`));
644
- // eslint-disable-line no-console
645
- });
646
- } catch (error) {
647
- spinner.fail(`Multi-modal search failed: ${error.message}`);
648
- }
251
+ return multimodalCommands.multiModalSearch(
252
+ this.multiModalProcessor,
253
+ tenantId,
254
+ _options,
255
+ );
649
256
  }
650
257
 
651
258
  async describeContent(contentId, _options) {
652
- const spinner = ora('Generating content description...').start();
653
-
654
- try {
655
- const descriptions =
656
- await this.multiModalProcessor.generateContentDescription(contentId, {
657
- detailed: !!_options.detailed,
658
- });
659
-
660
- spinner.succeed('Description generated');
661
-
662
- console.log(chalk.blue('\nContent Descriptions:'));
663
- // eslint-disable-line no-console
664
- console.log(chalk.gray('='.repeat(50)));
665
- // eslint-disable-line no-console
666
-
667
- for (const [modality, description] of Object.entries(descriptions)) {
668
- console.log(chalk.green(`\n${modality.toUpperCase()}:`));
669
- // eslint-disable-line no-console
670
- console.log(description);
671
- // eslint-disable-line no-console
672
- }
673
- } catch (error) {
674
- spinner.fail(`Description generation failed: ${error.message}`);
675
- }
259
+ return multimodalCommands.describeContent(
260
+ this.multiModalProcessor,
261
+ contentId,
262
+ _options,
263
+ );
676
264
  }
677
265
 
678
266
  // Federated Learning Commands
679
267
  async createFederation(_options) {
680
- const spinner = ora('Creating federated learning session...').start();
681
-
682
- try {
683
- if (!_options.tenant) {
684
- spinner.fail('Tenant ID is required');
685
- return;
686
- }
687
-
688
- const modelConfig = {
689
- _type: _options.modelType,
690
- architecture: _options.architecture,
691
- };
692
-
693
- const federationOptions = {
694
- minParticipants: parseInt(_options.minParticipants),
695
- maxParticipants: parseInt(_options.maxParticipants),
696
- };
697
-
698
- const federationId = await this.federatedLearning.createFederation(
699
- _options.tenant,
700
- modelConfig,
701
- federationOptions,
702
- );
703
-
704
- spinner.succeed('Federation created successfully');
705
-
706
- console.log(chalk.green('\n✓ Federated learning session created'));
707
- // eslint-disable-line no-console
708
- console.log(chalk.blue(`Federation ID: ${federationId}`));
709
- // eslint-disable-line no-console
710
- console.log(chalk.blue(`Model Type: ${_options.modelType}`));
711
- // eslint-disable-line no-console
712
- console.log(
713
- chalk.blue(
714
- `Min/Max Participants: ${_options.minParticipants}/${_options.maxParticipants}`,
715
- ),
716
- );
717
- // eslint-disable-line no-console
718
- } catch (error) {
719
- spinner.fail(`Federation creation failed: ${error.message}`);
720
- }
268
+ return federatedCommands.createFederation(this.federatedLearning, _options);
721
269
  }
722
270
 
723
271
  async joinFederation(federationId, _options) {
724
- const spinner = ora('Joining federated learning session...').start();
725
-
726
- try {
727
- if (!_options.tenant) {
728
- spinner.fail('Tenant ID is required');
729
- return;
730
- }
731
-
732
- const participantInfo = {
733
- tenantId: _options.tenant,
734
- dataSize: parseInt(_options.dataSize) || 1000,
735
- computeCapacity: parseFloat(_options.computeCapacity) || 0.8,
736
- networkBandwidth: 100,
737
- privacyLevel: _options.privacyLevel,
738
- };
739
-
740
- const participantId = await this.federatedLearning.registerParticipant(
741
- federationId,
742
- participantInfo,
743
- );
744
-
745
- spinner.succeed('Successfully joined federation');
746
-
747
- console.log(chalk.green('\n✓ Joined federated learning session'));
748
- // eslint-disable-line no-console
749
- console.log(chalk.blue(`Participant ID: ${participantId}`));
750
- // eslint-disable-line no-console
751
- console.log(chalk.blue(`Federation ID: ${federationId}`));
752
- // eslint-disable-line no-console
753
- } catch (error) {
754
- spinner.fail(`Failed to join federation: ${error.message}`);
755
- }
272
+ return federatedCommands.joinFederation(
273
+ this.federatedLearning,
274
+ federationId,
275
+ _options,
276
+ );
756
277
  }
757
278
 
758
279
  async startFederatedRound(federationId) {
759
- const spinner = ora('Starting federated learning round...').start();
760
-
761
- try {
762
- const result =
763
- await this.federatedLearning.startFederatedRound(federationId);
764
-
765
- spinner.succeed('Federated round completed');
766
-
767
- console.log(chalk.green('\n✓ Federated learning round completed'));
768
- // eslint-disable-line no-console
769
- console.log(chalk.blue(`Round: ${result.round}`));
770
- // eslint-disable-line no-console
771
- console.log(chalk.blue(`Participants: ${result.participants}`));
772
- // eslint-disable-line no-console
773
- console.log(
774
- chalk.blue(`Converged: ${result.convergence.converged ? 'Yes' : 'No'}`),
775
- );
776
- // eslint-disable-line no-console
777
- console.log(
778
- chalk.blue(
779
- `Global Accuracy: ${result.convergence.globalAccuracy?.toFixed(4)}`,
780
- ),
781
- );
782
- // eslint-disable-line no-console
783
- } catch (error) {
784
- spinner.fail(`Federated round failed: ${error.message}`);
785
- }
280
+ return federatedCommands.startFederatedRound(
281
+ this.federatedLearning,
282
+ federationId,
283
+ );
786
284
  }
787
285
 
788
286
  async showFederationStats(federationId, _options) {
789
- const spinner = ora('Fetching federation statistics...').start();
790
-
791
- try {
792
- const stats =
793
- await this.federatedLearning.getFederationStats(federationId);
794
-
795
- spinner.succeed('Statistics retrieved');
796
-
797
- const table = new Table({
798
- head: ['Property', 'Value'],
799
- colWidths: [25, 40],
800
- });
801
-
802
- table.push(
803
- ['Federation ID', stats.federation.id],
804
- ['Status', this._colorizeStatus(stats.federation.status)],
805
- ['Current Round', stats.federation.currentRound],
806
- ['Total Participants', stats.federation.totalParticipants],
807
- ['Active Participants', stats.federation.activeParticipants],
808
- ['Model Type', stats.federation.modelType],
809
- [
810
- 'Average Accuracy',
811
- stats.performance.averageAccuracy?.toFixed(4) || 'N/A',
812
- ],
813
- ['Total Data Size', stats.performance.totalDataSize],
814
- [
815
- 'Privacy Enabled',
816
- stats.privacy.differentialPrivacyEnabled ? 'Yes' : 'No',
817
- ],
818
- );
819
-
820
- console.log(table.toString());
821
- // eslint-disable-line no-console
822
-
823
- if (_options.detailed && stats.participants.length > 0) {
824
- console.log(chalk.blue('\nParticipant Details:'));
825
- // eslint-disable-line no-console
826
-
827
- const participantTable = new Table({
828
- head: ['Tenant ID', 'Data Size', 'Accuracy', 'Rounds', 'Status'],
829
- colWidths: [15, 12, 12, 8, 12],
830
- });
831
-
832
- stats.participants.forEach((participant) => {
833
- participantTable.push([
834
- participant.tenantId,
835
- participant.dataSize,
836
- participant.performance.accuracy?.toFixed(4) || 'N/A',
837
- participant.performance.rounds,
838
- participant.status,
839
- ]);
840
- });
841
-
842
- console.log(participantTable.toString());
843
- // eslint-disable-line no-console
844
- }
845
- } catch (error) {
846
- spinner.fail(`Failed to get statistics: ${error.message}`);
847
- }
287
+ return federatedCommands.showFederationStats(
288
+ this.federatedLearning,
289
+ federationId,
290
+ _options,
291
+ );
848
292
  }
849
293
 
850
- // Utility Commands
294
+ // Utility Commands (kept in aggregator as they don't belong to a specific domain)
851
295
  async runBenchmarks(_options) {
852
- const spinner = ora('Running AI/ML benchmarks...').start();
296
+ const spinner = ora("Running AI/ML benchmarks...").start();
853
297
 
854
298
  try {
855
299
  // Mock benchmark implementation
856
300
  const benchmarks = {
857
301
  embedding: {
858
- latency: '45ms',
859
- throughput: '2000 docs/sec',
302
+ latency: "45ms",
303
+ throughput: "2000 docs/sec",
860
304
  accuracy: 0.89,
861
305
  },
862
306
  retrieval: {
863
- latency: '12ms',
864
- throughput: '5000 queries/sec',
307
+ latency: "12ms",
308
+ throughput: "5000 queries/sec",
865
309
  recall: 0.92,
866
310
  },
867
311
  generation: {
868
- latency: '150ms',
869
- throughput: '500 tokens/sec',
312
+ latency: "150ms",
313
+ throughput: "500 tokens/sec",
870
314
  quality: 0.85,
871
315
  },
872
316
  };
873
317
 
874
- spinner.succeed('Benchmarks completed');
318
+ spinner.succeed("Benchmarks completed");
875
319
 
876
320
  const table = new Table({
877
- head: ['Model', 'Latency', 'Throughput', 'Quality Score'],
321
+ head: ["Model", "Latency", "Throughput", "Quality Score"],
878
322
  colWidths: [15, 15, 20, 15],
879
323
  });
880
324
 
@@ -904,63 +348,38 @@ class AIMLCommands {
904
348
  }
905
349
 
906
350
  async launchDashboard(_options) {
907
- console.log(chalk.blue('🚀 Launching AI/ML Dashboard...'));
351
+ console.log(chalk.blue("🚀 Launching AI/ML Dashboard..."));
908
352
  // eslint-disable-line no-console
909
353
  console.log(chalk.gray(`Port: ${_options.port}`));
910
354
  // eslint-disable-line no-console
911
355
  console.log(chalk.gray(`URL: http://localhost:${_options.port}`)); // eslint-disable-line no-console
912
356
 
913
357
  if (_options.open) {
914
- console.log(chalk.green('Opening browser...'));
358
+ console.log(chalk.green("Opening browser..."));
915
359
  // eslint-disable-line no-console
916
360
  }
917
361
 
918
- console.log(chalk.yellow('\nDashboard features:'));
362
+ console.log(chalk.yellow("\nDashboard features:"));
919
363
  // eslint-disable-line no-console
920
- console.log('• Model training monitoring');
364
+ console.log("• Model training monitoring");
921
365
  // eslint-disable-line no-console
922
- console.log('• Adaptive retrieval analytics');
366
+ console.log("• Adaptive retrieval analytics");
923
367
  // eslint-disable-line no-console
924
- console.log('• Multi-modal content explorer');
368
+ console.log("• Multi-modal content explorer");
925
369
  // eslint-disable-line no-console
926
- console.log('• Federated learning coordinator');
370
+ console.log("• Federated learning coordinator");
927
371
  // eslint-disable-line no-console
928
- console.log('• Performance benchmarks');
372
+ console.log("• Performance benchmarks");
929
373
  // eslint-disable-line no-console
930
374
  }
931
375
 
932
- // Helper methods
376
+ // Helper methods (delegated to shared module, kept here for backward compatibility)
933
377
  _colorizeStatus(status) {
934
- switch (status) {
935
- case 'completed':
936
- case 'ready':
937
- case 'active':
938
- return chalk.green(status);
939
- case 'failed':
940
- case 'error':
941
- return chalk.red(status);
942
- case 'running':
943
- case 'training':
944
- return chalk.yellow(status);
945
- default:
946
- return chalk.gray(status);
947
- }
378
+ return colorizeStatus(status);
948
379
  }
949
380
 
950
- _detectContentType(_filePath) {
951
- const ext = _path.extname(_filePath).toLowerCase();
952
-
953
- if (['.jpg', '.jpeg', '.png', '.gif', '.webp'].includes(ext)) {
954
- return 'image/jpeg';
955
- } else if (['.mp3', '.wav', '.flac', '.ogg'].includes(ext)) {
956
- return 'audio/mpeg';
957
- } else if (['.mp4', '.avi', '.mov', '.webm'].includes(ext)) {
958
- return 'video/mp4';
959
- } else if (['.txt', '.md', '.json'].includes(ext)) {
960
- return 'text/plain';
961
- }
962
-
963
- return 'application/octet-stream';
381
+ _detectContentType(filePath) {
382
+ return detectContentType(filePath);
964
383
  }
965
384
  }
966
385