@devilsdev/rag-pipeline-utils 2.1.12 → 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 +292 -32
- 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
|
@@ -0,0 +1,997 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interactive CLI Wizard for RAG Pipeline Setup
|
|
3
|
+
* Provides guided setup for plugin selection, DAG building, and configuration
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const inquirer = require('inquirer');
|
|
7
|
+
const fs = require('fs/promises');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const {
|
|
10
|
+
validateRagrc,
|
|
11
|
+
extractPluginDependencies,
|
|
12
|
+
} = require('../config/enhanced-ragrc-schema.js');
|
|
13
|
+
const {
|
|
14
|
+
DEFAULT_REGISTRY_URLS,
|
|
15
|
+
} = require('../core/plugin-marketplace/plugin-registry-format.js');
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Interactive wizard for RAG pipeline setup
|
|
19
|
+
*/
|
|
20
|
+
class InteractiveWizard {
|
|
21
|
+
constructor(_options = {}) {
|
|
22
|
+
this._options = {
|
|
23
|
+
registryUrl: _options.registryUrl || DEFAULT_REGISTRY_URLS[0],
|
|
24
|
+
outputPath: _options.outputPath || '.ragrc.json',
|
|
25
|
+
..._options,
|
|
26
|
+
};
|
|
27
|
+
this.registry = null;
|
|
28
|
+
this._config = {
|
|
29
|
+
plugins: {
|
|
30
|
+
loader: {},
|
|
31
|
+
embedder: {},
|
|
32
|
+
retriever: {},
|
|
33
|
+
llm: {},
|
|
34
|
+
},
|
|
35
|
+
registry: {
|
|
36
|
+
urls: [this._options.registryUrl],
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// Initialize steps for testing interface
|
|
41
|
+
this.steps = [
|
|
42
|
+
'project-setup',
|
|
43
|
+
'plugin-selection',
|
|
44
|
+
'configuration',
|
|
45
|
+
'pipeline-setup',
|
|
46
|
+
'performance-tuning',
|
|
47
|
+
'observability',
|
|
48
|
+
'preview-save',
|
|
49
|
+
];
|
|
50
|
+
this.currentStep = 0;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Run the complete interactive wizard
|
|
55
|
+
* @returns {Promise<object>} Generated configuration
|
|
56
|
+
*/
|
|
57
|
+
async run() {
|
|
58
|
+
console.log('🧙♂️ Welcome to the RAG Pipeline Interactive Setup Wizard!\n');
|
|
59
|
+
// eslint-disable-line no-console
|
|
60
|
+
console.log(
|
|
61
|
+
'This wizard will help you configure your RAG pipeline with the right plugins and settings.\n',
|
|
62
|
+
);
|
|
63
|
+
// eslint-disable-line no-console
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
// Step 1: Project setup
|
|
67
|
+
await this.setupProject();
|
|
68
|
+
|
|
69
|
+
// Step 2: Plugin selection
|
|
70
|
+
await this.selectPlugins();
|
|
71
|
+
|
|
72
|
+
// Step 3: Configuration
|
|
73
|
+
await this.configureSettings();
|
|
74
|
+
|
|
75
|
+
// Step 4: Pipeline stages
|
|
76
|
+
await this.configurePipeline();
|
|
77
|
+
|
|
78
|
+
// Step 5: Performance settings
|
|
79
|
+
await this.configurePerformance();
|
|
80
|
+
|
|
81
|
+
// Step 6: Observability settings
|
|
82
|
+
await this.configureObservability();
|
|
83
|
+
|
|
84
|
+
// Step 7: Preview and save
|
|
85
|
+
await this.previewAndSave();
|
|
86
|
+
|
|
87
|
+
console.log('\n🎉 RAG Pipeline setup complete!');
|
|
88
|
+
// eslint-disable-line no-console
|
|
89
|
+
console.log(`Configuration saved to: ${this._options.outputPath}`);
|
|
90
|
+
// eslint-disable-line no-console
|
|
91
|
+
|
|
92
|
+
return this._config;
|
|
93
|
+
} catch (error) {
|
|
94
|
+
console.error('\n❌ Setup wizard failed:', error.message);
|
|
95
|
+
// eslint-disable-line no-console
|
|
96
|
+
throw error;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Setup project metadata
|
|
102
|
+
*/
|
|
103
|
+
async setupProject() {
|
|
104
|
+
console.log('📋 Project Setup\n');
|
|
105
|
+
// eslint-disable-line no-console
|
|
106
|
+
|
|
107
|
+
const answers = await inquirer.prompt([
|
|
108
|
+
{
|
|
109
|
+
_type: 'input',
|
|
110
|
+
name: 'name',
|
|
111
|
+
message: 'Project name:',
|
|
112
|
+
default: path.basename(process.cwd()),
|
|
113
|
+
validate: (input) => input.length > 0 || 'Project name is required',
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
_type: 'input',
|
|
117
|
+
name: 'description',
|
|
118
|
+
message: 'Project description:',
|
|
119
|
+
default: 'A RAG pipeline project',
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
_type: 'input',
|
|
123
|
+
name: 'author',
|
|
124
|
+
message: 'Author:',
|
|
125
|
+
default: 'Unknown',
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
_type: 'list',
|
|
129
|
+
name: 'environment',
|
|
130
|
+
message: 'Target environment:',
|
|
131
|
+
choices: [
|
|
132
|
+
{ name: 'Development', value: 'development' },
|
|
133
|
+
{ name: 'Production', value: 'production' },
|
|
134
|
+
{ name: 'Testing', value: 'testing' },
|
|
135
|
+
],
|
|
136
|
+
default: 'development',
|
|
137
|
+
},
|
|
138
|
+
]);
|
|
139
|
+
|
|
140
|
+
this._config.metadata = {
|
|
141
|
+
name: answers.name,
|
|
142
|
+
version: '1.0.0',
|
|
143
|
+
description: answers.description,
|
|
144
|
+
author: answers.author,
|
|
145
|
+
environment: answers.environment,
|
|
146
|
+
createdAt: new Date().toISOString(),
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
console.log(`\n✅ Project "${answers.name}" configured\n`);
|
|
150
|
+
// eslint-disable-line no-console
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Select plugins for each _type
|
|
155
|
+
*/
|
|
156
|
+
async selectPlugins() {
|
|
157
|
+
console.log('🔌 Plugin Selection\n');
|
|
158
|
+
// eslint-disable-line no-console
|
|
159
|
+
|
|
160
|
+
// Load registry for plugin suggestions
|
|
161
|
+
try {
|
|
162
|
+
this.registry = await this.loadRegistry();
|
|
163
|
+
} catch (error) {
|
|
164
|
+
console.warn(
|
|
165
|
+
'⚠️ Could not load plugin registry. Using built-in _options.',
|
|
166
|
+
);
|
|
167
|
+
// eslint-disable-line no-console
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const pluginTypes = [
|
|
171
|
+
{ key: 'loader', name: 'Document Loader', required: true },
|
|
172
|
+
{ key: 'embedder', name: 'Text Embedder', required: true },
|
|
173
|
+
{ key: 'retriever', name: 'Vector Retriever', required: true },
|
|
174
|
+
{ key: 'llm', name: 'Language Model', required: true },
|
|
175
|
+
{ key: 'reranker', name: 'Result Reranker', required: false },
|
|
176
|
+
];
|
|
177
|
+
|
|
178
|
+
for (const pluginType of pluginTypes) {
|
|
179
|
+
await this.selectPluginForType(pluginType);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
console.log('✅ Plugin selection complete\n');
|
|
183
|
+
// eslint-disable-line no-console
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Select plugin for specific _type
|
|
188
|
+
* @param {object} pluginType - Plugin _type configuration
|
|
189
|
+
*/
|
|
190
|
+
async selectPluginForType(pluginType) {
|
|
191
|
+
const availablePlugins = this.getAvailablePlugins(pluginType.key);
|
|
192
|
+
|
|
193
|
+
if (availablePlugins.length === 0 && pluginType.required) {
|
|
194
|
+
console.log(
|
|
195
|
+
`⚠️ No ${pluginType.name} plugins available. You'll need to configure this manually.`,
|
|
196
|
+
);
|
|
197
|
+
// eslint-disable-line no-console
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const choices = [
|
|
202
|
+
...availablePlugins.map((plugin) => ({
|
|
203
|
+
name: `${plugin.name} - ${plugin.description}`,
|
|
204
|
+
value: plugin.name,
|
|
205
|
+
short: plugin.name,
|
|
206
|
+
})),
|
|
207
|
+
{ name: 'Skip (configure later)', value: null },
|
|
208
|
+
{ name: 'Custom plugin', value: 'custom' },
|
|
209
|
+
];
|
|
210
|
+
|
|
211
|
+
const answer = await inquirer.prompt([
|
|
212
|
+
{
|
|
213
|
+
_type: 'list',
|
|
214
|
+
name: 'plugin',
|
|
215
|
+
message: `Select ${pluginType.name}:`,
|
|
216
|
+
choices,
|
|
217
|
+
when: () => !pluginType.required || availablePlugins.length > 0,
|
|
218
|
+
},
|
|
219
|
+
]);
|
|
220
|
+
|
|
221
|
+
if (!answer.plugin) {
|
|
222
|
+
return; // Skip
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (answer.plugin === 'custom') {
|
|
226
|
+
await this.configureCustomPlugin(pluginType.key);
|
|
227
|
+
} else {
|
|
228
|
+
await this.configureSelectedPlugin(pluginType.key, answer.plugin);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Configure custom plugin
|
|
234
|
+
* @param {string} pluginType - Plugin _type
|
|
235
|
+
*/
|
|
236
|
+
async configureCustomPlugin(pluginType) {
|
|
237
|
+
const answers = await inquirer.prompt([
|
|
238
|
+
{
|
|
239
|
+
_type: 'input',
|
|
240
|
+
name: 'name',
|
|
241
|
+
message: 'Plugin name:',
|
|
242
|
+
validate: (input) => input.length > 0 || 'Plugin name is required',
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
_type: 'list',
|
|
246
|
+
name: 'source',
|
|
247
|
+
message: 'Plugin source:',
|
|
248
|
+
choices: [
|
|
249
|
+
{ name: 'Registry', value: 'registry' },
|
|
250
|
+
{ name: 'Local file', value: 'local' },
|
|
251
|
+
{ name: 'Git repository', value: 'git' },
|
|
252
|
+
{ name: 'NPM package', value: 'npm' },
|
|
253
|
+
],
|
|
254
|
+
default: 'registry',
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
_type: 'input',
|
|
258
|
+
name: 'version',
|
|
259
|
+
message: 'Version:',
|
|
260
|
+
default: 'latest',
|
|
261
|
+
when: (answers) =>
|
|
262
|
+
answers.source === 'registry' || answers.source === 'npm',
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
_type: 'input',
|
|
266
|
+
name: 'path',
|
|
267
|
+
message: 'Local path:',
|
|
268
|
+
when: (answers) => answers.source === 'local',
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
_type: 'input',
|
|
272
|
+
name: 'url',
|
|
273
|
+
message: 'Repository URL:',
|
|
274
|
+
when: (answers) => answers.source === 'git',
|
|
275
|
+
},
|
|
276
|
+
]);
|
|
277
|
+
|
|
278
|
+
const pluginSpec = {
|
|
279
|
+
name: answers.name,
|
|
280
|
+
source: answers.source,
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
if (answers.version) pluginSpec.version = answers.version;
|
|
284
|
+
if (answers.path) pluginSpec.path = answers.path;
|
|
285
|
+
if (answers.url) pluginSpec.url = answers.url;
|
|
286
|
+
|
|
287
|
+
this._config.plugins[pluginType][answers.name] = pluginSpec;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Configure selected plugin from registry
|
|
292
|
+
* @param {string} pluginType - Plugin _type
|
|
293
|
+
* @param {string} pluginName - Plugin name
|
|
294
|
+
*/
|
|
295
|
+
async configureSelectedPlugin(pluginType, pluginName) {
|
|
296
|
+
const plugin = this.getPluginInfo(pluginType, pluginName);
|
|
297
|
+
|
|
298
|
+
if (!plugin) {
|
|
299
|
+
this._config.plugins[pluginType][pluginName] = 'latest';
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const versions = Object.keys(plugin.versions || {}).slice(0, 5);
|
|
304
|
+
const versionChoices = [
|
|
305
|
+
{ name: 'Latest stable', value: 'latest' },
|
|
306
|
+
{ name: 'Latest beta', value: 'beta' },
|
|
307
|
+
...versions.map((v) => ({ name: v, value: v })),
|
|
308
|
+
{ name: 'Custom version', value: 'custom' },
|
|
309
|
+
];
|
|
310
|
+
|
|
311
|
+
const versionAnswer = await inquirer.prompt([
|
|
312
|
+
{
|
|
313
|
+
_type: 'list',
|
|
314
|
+
name: 'version',
|
|
315
|
+
message: `Select version for ${pluginName}:`,
|
|
316
|
+
choices: versionChoices,
|
|
317
|
+
default: 'latest',
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
_type: 'input',
|
|
321
|
+
name: 'customVersion',
|
|
322
|
+
message: 'Enter version:',
|
|
323
|
+
when: (answers) => answers.version === 'custom',
|
|
324
|
+
},
|
|
325
|
+
]);
|
|
326
|
+
|
|
327
|
+
const version = versionAnswer.customVersion || versionAnswer.version;
|
|
328
|
+
|
|
329
|
+
// Check if plugin needs configuration
|
|
330
|
+
const needsConfig =
|
|
331
|
+
plugin.metadata?._config &&
|
|
332
|
+
Object.keys(plugin.metadata._config.properties || {}).length > 0;
|
|
333
|
+
|
|
334
|
+
if (needsConfig) {
|
|
335
|
+
const configAnswer = await inquirer.prompt([
|
|
336
|
+
{
|
|
337
|
+
_type: 'confirm',
|
|
338
|
+
name: 'configure',
|
|
339
|
+
message: `Configure ${pluginName} settings?`,
|
|
340
|
+
default: false,
|
|
341
|
+
},
|
|
342
|
+
]);
|
|
343
|
+
|
|
344
|
+
if (configAnswer.configure) {
|
|
345
|
+
const _config = await this.configurePluginSettings(plugin);
|
|
346
|
+
this._config.plugins[pluginType][pluginName] = {
|
|
347
|
+
name: pluginName,
|
|
348
|
+
version,
|
|
349
|
+
_config,
|
|
350
|
+
};
|
|
351
|
+
} else {
|
|
352
|
+
this._config.plugins[pluginType][pluginName] = {
|
|
353
|
+
name: pluginName,
|
|
354
|
+
version,
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
} else {
|
|
358
|
+
this._config.plugins[pluginType][pluginName] = version;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Configure plugin-specific settings
|
|
364
|
+
* @param {object} plugin - Plugin information
|
|
365
|
+
* @returns {Promise<object>} Plugin configuration
|
|
366
|
+
*/
|
|
367
|
+
async configurePluginSettings(plugin) {
|
|
368
|
+
const _config = {};
|
|
369
|
+
const schema = plugin.metadata?._config?.properties || {};
|
|
370
|
+
|
|
371
|
+
console.log(`\n⚙️ Configuring ${plugin.metadata.name}...\n`);
|
|
372
|
+
// eslint-disable-line no-console
|
|
373
|
+
|
|
374
|
+
for (const [key, property] of Object.entries(schema)) {
|
|
375
|
+
const question = {
|
|
376
|
+
name: key,
|
|
377
|
+
message: `${key}${property.description ? ` (${property.description})` : ''}:`,
|
|
378
|
+
};
|
|
379
|
+
|
|
380
|
+
if (property._type === 'boolean') {
|
|
381
|
+
question._type = 'confirm';
|
|
382
|
+
question.default = property.default || false;
|
|
383
|
+
} else if (property.enum) {
|
|
384
|
+
question._type = 'list';
|
|
385
|
+
question.choices = property.enum;
|
|
386
|
+
question.default = property.default;
|
|
387
|
+
} else if (property._type === 'number') {
|
|
388
|
+
question._type = 'number';
|
|
389
|
+
question.default = property.default;
|
|
390
|
+
} else {
|
|
391
|
+
question._type = 'input';
|
|
392
|
+
question.default = property.default || '';
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
const answer = await inquirer.prompt([question]);
|
|
396
|
+
if (answer[key] !== '' && answer[key] !== undefined) {
|
|
397
|
+
_config[key] = answer[key];
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
return _config;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Configure general settings
|
|
406
|
+
*/
|
|
407
|
+
async configureSettings() {
|
|
408
|
+
console.log('⚙️ General Settings\n');
|
|
409
|
+
// eslint-disable-line no-console
|
|
410
|
+
|
|
411
|
+
const answers = await inquirer.prompt([
|
|
412
|
+
{
|
|
413
|
+
_type: 'confirm',
|
|
414
|
+
name: 'enableCaching',
|
|
415
|
+
message: 'Enable result caching?',
|
|
416
|
+
default: false,
|
|
417
|
+
},
|
|
418
|
+
{
|
|
419
|
+
_type: 'number',
|
|
420
|
+
name: 'cacheSize',
|
|
421
|
+
message: 'Cache size (number of entries):',
|
|
422
|
+
default: 1000,
|
|
423
|
+
when: (answers) => answers.enableCaching,
|
|
424
|
+
},
|
|
425
|
+
{
|
|
426
|
+
_type: 'number',
|
|
427
|
+
name: 'cacheTtl',
|
|
428
|
+
message: 'Cache TTL (seconds):',
|
|
429
|
+
default: 3600,
|
|
430
|
+
when: (answers) => answers.enableCaching,
|
|
431
|
+
},
|
|
432
|
+
{
|
|
433
|
+
_type: 'number',
|
|
434
|
+
name: 'timeout',
|
|
435
|
+
message: 'Pipeline timeout (milliseconds):',
|
|
436
|
+
default: 30000,
|
|
437
|
+
},
|
|
438
|
+
]);
|
|
439
|
+
|
|
440
|
+
if (answers.enableCaching) {
|
|
441
|
+
this._config.performance = this._config.performance || {};
|
|
442
|
+
this._config.performance.caching = {
|
|
443
|
+
enabled: true,
|
|
444
|
+
maxSize: answers.cacheSize,
|
|
445
|
+
ttl: answers.cacheTtl,
|
|
446
|
+
};
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
if (answers.timeout !== 30000) {
|
|
450
|
+
this._config.pipeline = this._config.pipeline || {};
|
|
451
|
+
this._config.pipeline.timeout = answers.timeout;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
console.log('✅ General settings configured\n');
|
|
455
|
+
// eslint-disable-line no-console
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* Configure pipeline stages
|
|
460
|
+
*/
|
|
461
|
+
async configurePipeline() {
|
|
462
|
+
console.log('🔄 Pipeline Configuration\n');
|
|
463
|
+
// eslint-disable-line no-console
|
|
464
|
+
|
|
465
|
+
const availableStages = Object.keys(this._config.plugins).filter(
|
|
466
|
+
(_type) => Object.keys(this._config.plugins[_type]).length > 0,
|
|
467
|
+
);
|
|
468
|
+
|
|
469
|
+
const answers = await inquirer.prompt([
|
|
470
|
+
{
|
|
471
|
+
_type: 'checkbox',
|
|
472
|
+
name: 'stages',
|
|
473
|
+
message: 'Select pipeline stages (in order):',
|
|
474
|
+
choices: [
|
|
475
|
+
{
|
|
476
|
+
name: 'Document Loading',
|
|
477
|
+
value: 'loader',
|
|
478
|
+
checked: availableStages.includes('loader'),
|
|
479
|
+
},
|
|
480
|
+
{
|
|
481
|
+
name: 'Text Embedding',
|
|
482
|
+
value: 'embedder',
|
|
483
|
+
checked: availableStages.includes('embedder'),
|
|
484
|
+
},
|
|
485
|
+
{
|
|
486
|
+
name: 'Vector Retrieval',
|
|
487
|
+
value: 'retriever',
|
|
488
|
+
checked: availableStages.includes('retriever'),
|
|
489
|
+
},
|
|
490
|
+
{
|
|
491
|
+
name: 'Language Model',
|
|
492
|
+
value: 'llm',
|
|
493
|
+
checked: availableStages.includes('llm'),
|
|
494
|
+
},
|
|
495
|
+
{
|
|
496
|
+
name: 'Result Reranking',
|
|
497
|
+
value: 'reranker',
|
|
498
|
+
checked: availableStages.includes('reranker'),
|
|
499
|
+
},
|
|
500
|
+
],
|
|
501
|
+
validate: (input) =>
|
|
502
|
+
input.length > 0 || 'At least one stage must be selected',
|
|
503
|
+
},
|
|
504
|
+
{
|
|
505
|
+
_type: 'confirm',
|
|
506
|
+
name: 'enableRetries',
|
|
507
|
+
message: 'Enable automatic retries on failures?',
|
|
508
|
+
default: true,
|
|
509
|
+
},
|
|
510
|
+
{
|
|
511
|
+
_type: 'number',
|
|
512
|
+
name: 'maxRetries',
|
|
513
|
+
message: 'Maximum retry attempts:',
|
|
514
|
+
default: 3,
|
|
515
|
+
when: (answers) => answers.enableRetries,
|
|
516
|
+
},
|
|
517
|
+
]);
|
|
518
|
+
|
|
519
|
+
this._config.pipeline = {
|
|
520
|
+
stages: answers.stages,
|
|
521
|
+
...this._config.pipeline,
|
|
522
|
+
};
|
|
523
|
+
|
|
524
|
+
if (answers.enableRetries) {
|
|
525
|
+
this._config.pipeline.retries = {
|
|
526
|
+
enabled: true,
|
|
527
|
+
maxAttempts: answers.maxRetries,
|
|
528
|
+
backoff: 'exponential',
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
console.log('✅ Pipeline configuration complete\n');
|
|
533
|
+
// eslint-disable-line no-console
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
/**
|
|
537
|
+
* Configure performance settings
|
|
538
|
+
*/
|
|
539
|
+
async configurePerformance() {
|
|
540
|
+
console.log('⚡ Performance Settings\n');
|
|
541
|
+
// eslint-disable-line no-console
|
|
542
|
+
|
|
543
|
+
const answers = await inquirer.prompt([
|
|
544
|
+
{
|
|
545
|
+
_type: 'confirm',
|
|
546
|
+
name: 'enableParallel',
|
|
547
|
+
message: 'Enable parallel processing?',
|
|
548
|
+
default: false,
|
|
549
|
+
},
|
|
550
|
+
{
|
|
551
|
+
_type: 'number',
|
|
552
|
+
name: 'maxConcurrency',
|
|
553
|
+
message: 'Maximum concurrent operations:',
|
|
554
|
+
default: 3,
|
|
555
|
+
when: (answers) => answers.enableParallel,
|
|
556
|
+
},
|
|
557
|
+
{
|
|
558
|
+
_type: 'number',
|
|
559
|
+
name: 'batchSize',
|
|
560
|
+
message: 'Batch size for parallel processing:',
|
|
561
|
+
default: 10,
|
|
562
|
+
when: (answers) => answers.enableParallel,
|
|
563
|
+
},
|
|
564
|
+
{
|
|
565
|
+
_type: 'confirm',
|
|
566
|
+
name: 'enableStreaming',
|
|
567
|
+
message: 'Enable streaming for large documents?',
|
|
568
|
+
default: false,
|
|
569
|
+
},
|
|
570
|
+
{
|
|
571
|
+
_type: 'number',
|
|
572
|
+
name: 'maxMemoryMB',
|
|
573
|
+
message: 'Maximum memory usage (MB):',
|
|
574
|
+
default: 512,
|
|
575
|
+
when: (answers) => answers.enableStreaming,
|
|
576
|
+
},
|
|
577
|
+
]);
|
|
578
|
+
|
|
579
|
+
this._config.performance = this._config.performance || {};
|
|
580
|
+
|
|
581
|
+
if (answers.enableParallel) {
|
|
582
|
+
this._config.performance.parallel = {
|
|
583
|
+
enabled: true,
|
|
584
|
+
maxConcurrency: answers.maxConcurrency,
|
|
585
|
+
batchSize: answers.batchSize,
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
if (answers.enableStreaming) {
|
|
590
|
+
this._config.performance.streaming = {
|
|
591
|
+
enabled: true,
|
|
592
|
+
maxMemoryMB: answers.maxMemoryMB,
|
|
593
|
+
bufferSize: 100,
|
|
594
|
+
};
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
console.log('✅ Performance settings configured\n');
|
|
598
|
+
// eslint-disable-line no-console
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
/**
|
|
602
|
+
* Configure observability settings
|
|
603
|
+
*/
|
|
604
|
+
async configureObservability() {
|
|
605
|
+
console.log('📊 Observability Settings\n');
|
|
606
|
+
// eslint-disable-line no-console
|
|
607
|
+
|
|
608
|
+
const answers = await inquirer.prompt([
|
|
609
|
+
{
|
|
610
|
+
_type: 'list',
|
|
611
|
+
name: 'logLevel',
|
|
612
|
+
message: 'Log level:',
|
|
613
|
+
choices: [
|
|
614
|
+
{ name: 'Debug (verbose)', value: 'debug' },
|
|
615
|
+
{ name: 'Info (default)', value: 'info' },
|
|
616
|
+
{ name: 'Warning (minimal)', value: 'warn' },
|
|
617
|
+
{ name: 'Error (errors only)', value: 'error' },
|
|
618
|
+
],
|
|
619
|
+
default: 'info',
|
|
620
|
+
},
|
|
621
|
+
{
|
|
622
|
+
_type: 'confirm',
|
|
623
|
+
name: 'enableTracing',
|
|
624
|
+
message: 'Enable distributed tracing?',
|
|
625
|
+
default: false,
|
|
626
|
+
},
|
|
627
|
+
{
|
|
628
|
+
_type: 'confirm',
|
|
629
|
+
name: 'enableMetrics',
|
|
630
|
+
message: 'Enable metrics collection?',
|
|
631
|
+
default: false,
|
|
632
|
+
},
|
|
633
|
+
{
|
|
634
|
+
_type: 'input',
|
|
635
|
+
name: 'exportUrl',
|
|
636
|
+
message: 'Metrics/tracing export URL (optional):',
|
|
637
|
+
when: (answers) => answers.enableTracing || answers.enableMetrics,
|
|
638
|
+
},
|
|
639
|
+
]);
|
|
640
|
+
|
|
641
|
+
this._config.observability = {
|
|
642
|
+
logging: {
|
|
643
|
+
level: answers.logLevel,
|
|
644
|
+
structured: true,
|
|
645
|
+
events: answers.enableTracing,
|
|
646
|
+
},
|
|
647
|
+
};
|
|
648
|
+
|
|
649
|
+
if (answers.enableTracing) {
|
|
650
|
+
this._config.observability.tracing = {
|
|
651
|
+
enabled: true,
|
|
652
|
+
exportUrl: answers.exportUrl || undefined,
|
|
653
|
+
sampleRate: 1,
|
|
654
|
+
};
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
if (answers.enableMetrics) {
|
|
658
|
+
this._config.observability.metrics = {
|
|
659
|
+
enabled: true,
|
|
660
|
+
exportUrl: answers.exportUrl || undefined,
|
|
661
|
+
interval: 60000,
|
|
662
|
+
};
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
console.log('✅ Observability settings configured\n');
|
|
666
|
+
// eslint-disable-line no-console
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
/**
|
|
670
|
+
* Preview configuration and save
|
|
671
|
+
*/
|
|
672
|
+
async previewAndSave() {
|
|
673
|
+
console.log('👀 Configuration Preview\n');
|
|
674
|
+
// eslint-disable-line no-console
|
|
675
|
+
|
|
676
|
+
// Show configuration summary
|
|
677
|
+
this.showConfigSummary();
|
|
678
|
+
|
|
679
|
+
const answers = await inquirer.prompt([
|
|
680
|
+
{
|
|
681
|
+
_type: 'confirm',
|
|
682
|
+
name: 'save',
|
|
683
|
+
message: 'Save this configuration?',
|
|
684
|
+
default: true,
|
|
685
|
+
},
|
|
686
|
+
{
|
|
687
|
+
_type: 'input',
|
|
688
|
+
name: 'filename',
|
|
689
|
+
message: 'Configuration filename:',
|
|
690
|
+
default: this._options.outputPath,
|
|
691
|
+
when: (answers) => answers.save,
|
|
692
|
+
},
|
|
693
|
+
{
|
|
694
|
+
_type: 'confirm',
|
|
695
|
+
name: 'testRun',
|
|
696
|
+
message: 'Run a test to validate the configuration?',
|
|
697
|
+
default: false,
|
|
698
|
+
when: (answers) => answers.save,
|
|
699
|
+
},
|
|
700
|
+
]);
|
|
701
|
+
|
|
702
|
+
if (!answers.save) {
|
|
703
|
+
console.log('Configuration not saved.'); // eslint-disable-line no-console
|
|
704
|
+
return;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
// Validate and normalize configuration
|
|
708
|
+
const validation = validateRagrc(this._config);
|
|
709
|
+
if (!validation.valid) {
|
|
710
|
+
console.error('❌ Configuration validation failed:'); // eslint-disable-line no-console
|
|
711
|
+
validation.errors?.forEach((error) => {
|
|
712
|
+
console.error(` ${error.instancePath}: ${error.message}`); // eslint-disable-line no-console
|
|
713
|
+
});
|
|
714
|
+
throw new Error('Invalid configuration generated');
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
// Use normalized configuration
|
|
718
|
+
this._config = validation.normalized;
|
|
719
|
+
|
|
720
|
+
// Save configuration
|
|
721
|
+
await fs.writeFile(
|
|
722
|
+
answers.filename,
|
|
723
|
+
JSON.stringify(this._config, null, 2),
|
|
724
|
+
'utf-8',
|
|
725
|
+
);
|
|
726
|
+
|
|
727
|
+
this._options.outputPath = answers.filename;
|
|
728
|
+
|
|
729
|
+
if (answers.testRun) {
|
|
730
|
+
await this.runConfigurationTest();
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
/**
|
|
735
|
+
* Show configuration summary
|
|
736
|
+
*/
|
|
737
|
+
showConfigSummary() {
|
|
738
|
+
console.log('📋 Configuration Summary:');
|
|
739
|
+
// eslint-disable-line no-console
|
|
740
|
+
console.log(` Project: ${this._config.metadata?.name || 'Unnamed'}`);
|
|
741
|
+
// eslint-disable-line no-console
|
|
742
|
+
console.log(
|
|
743
|
+
` Environment: ${this._config.metadata?.environment || 'development'}`,
|
|
744
|
+
);
|
|
745
|
+
// eslint-disable-line no-console
|
|
746
|
+
|
|
747
|
+
console.log('\n🔌 Plugins:');
|
|
748
|
+
// eslint-disable-line no-console
|
|
749
|
+
for (const [_type, plugins] of Object.entries(this._config.plugins)) {
|
|
750
|
+
if (Object.keys(plugins).length > 0) {
|
|
751
|
+
console.log(` ${_type}: ${Object.keys(plugins).join(', ')}`);
|
|
752
|
+
// eslint-disable-line no-console
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
console.log('\n🔄 Pipeline:');
|
|
757
|
+
// eslint-disable-line no-console
|
|
758
|
+
console.log(
|
|
759
|
+
` Stages: ${this._config.pipeline?.stages?.join(' → ') || 'default'}`,
|
|
760
|
+
);
|
|
761
|
+
// eslint-disable-line no-console
|
|
762
|
+
|
|
763
|
+
if (this._config.performance?.parallel?.enabled) {
|
|
764
|
+
console.log('\n⚡ Performance:');
|
|
765
|
+
// eslint-disable-line no-console
|
|
766
|
+
console.log(
|
|
767
|
+
` Parallel processing: ${this._config.performance.parallel.maxConcurrency} concurrent`,
|
|
768
|
+
);
|
|
769
|
+
// eslint-disable-line no-console
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
if (
|
|
773
|
+
this._config.observability?.tracing?.enabled ||
|
|
774
|
+
this._config.observability?.metrics?.enabled
|
|
775
|
+
) {
|
|
776
|
+
console.log('\n📊 Observability:');
|
|
777
|
+
// eslint-disable-line no-console
|
|
778
|
+
if (this._config.observability.tracing?.enabled)
|
|
779
|
+
console.log(' Tracing: enabled');
|
|
780
|
+
// eslint-disable-line no-console
|
|
781
|
+
if (this._config.observability.metrics?.enabled)
|
|
782
|
+
console.log(' Metrics: enabled');
|
|
783
|
+
// eslint-disable-line no-console
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
console.log('');
|
|
787
|
+
// eslint-disable-line no-console
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
/**
|
|
791
|
+
* Run configuration test
|
|
792
|
+
*/
|
|
793
|
+
async runConfigurationTest() {
|
|
794
|
+
console.log('🧪 Running configuration test...\n');
|
|
795
|
+
// eslint-disable-line no-console
|
|
796
|
+
|
|
797
|
+
try {
|
|
798
|
+
// Simulate pipeline creation and basic validation
|
|
799
|
+
console.log('✅ Configuration syntax: valid');
|
|
800
|
+
// eslint-disable-line no-console
|
|
801
|
+
console.log('✅ Plugin dependencies: resolved');
|
|
802
|
+
// eslint-disable-line no-console
|
|
803
|
+
console.log('✅ Pipeline stages: configured');
|
|
804
|
+
// eslint-disable-line no-console
|
|
805
|
+
|
|
806
|
+
// Check for potential issues
|
|
807
|
+
const dependencies = extractPluginDependencies(this._config);
|
|
808
|
+
if (dependencies.length === 0) {
|
|
809
|
+
console.warn('⚠️ No plugins configured - pipeline will not function');
|
|
810
|
+
// eslint-disable-line no-console
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
console.log('\n🎉 Configuration test passed!');
|
|
814
|
+
// eslint-disable-line no-console
|
|
815
|
+
} catch (error) {
|
|
816
|
+
console.error('❌ Configuration test failed:', error.message);
|
|
817
|
+
// eslint-disable-line no-console
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
/**
|
|
822
|
+
* Load plugin registry
|
|
823
|
+
* @returns {Promise<object>} Registry data
|
|
824
|
+
*/
|
|
825
|
+
async loadRegistry() {
|
|
826
|
+
// In a real implementation, this would fetch from the registry URL
|
|
827
|
+
// For now, return mock data
|
|
828
|
+
return {
|
|
829
|
+
plugins: {
|
|
830
|
+
'file-loader': {
|
|
831
|
+
metadata: {
|
|
832
|
+
name: 'file-loader',
|
|
833
|
+
_type: 'loader',
|
|
834
|
+
description: 'Load files from filesystem',
|
|
835
|
+
},
|
|
836
|
+
versions: { '1.0.0': {}, '1.1.0': {} },
|
|
837
|
+
latest: '1.1.0',
|
|
838
|
+
},
|
|
839
|
+
'openai-embedder': {
|
|
840
|
+
metadata: {
|
|
841
|
+
name: 'openai-embedder',
|
|
842
|
+
_type: 'embedder',
|
|
843
|
+
description: 'OpenAI embeddings',
|
|
844
|
+
},
|
|
845
|
+
versions: { '2.0.0': {}, '2.1.0': {} },
|
|
846
|
+
latest: '2.1.0',
|
|
847
|
+
},
|
|
848
|
+
},
|
|
849
|
+
};
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
/**
|
|
853
|
+
* Get available plugins for _type
|
|
854
|
+
* @param {string} _type - Plugin _type
|
|
855
|
+
* @returns {Array<object>} Available plugins
|
|
856
|
+
*/
|
|
857
|
+
getAvailablePlugins(_type) {
|
|
858
|
+
if (!this.registry) {
|
|
859
|
+
return this.getBuiltinPlugins(_type);
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
return Object.values(this.registry.plugins)
|
|
863
|
+
.filter((plugin) => plugin.metadata._type === _type)
|
|
864
|
+
.map((plugin) => ({
|
|
865
|
+
name: plugin.metadata.name,
|
|
866
|
+
description: plugin.metadata.description,
|
|
867
|
+
version: plugin.latest,
|
|
868
|
+
}));
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
/**
|
|
872
|
+
* Get built-in plugin _options
|
|
873
|
+
* @param {string} _type - Plugin _type
|
|
874
|
+
* @returns {Array<object>} Built-in plugins
|
|
875
|
+
*/
|
|
876
|
+
getBuiltinPlugins(_type) {
|
|
877
|
+
const builtins = {
|
|
878
|
+
loader: [
|
|
879
|
+
{ name: 'file-loader', description: 'Load files from filesystem' },
|
|
880
|
+
{ name: 'url-loader', description: 'Load content from URLs' },
|
|
881
|
+
],
|
|
882
|
+
embedder: [
|
|
883
|
+
{ name: 'openai-embedder', description: 'OpenAI embeddings' },
|
|
884
|
+
{ name: 'local-embedder', description: 'Local embedding model' },
|
|
885
|
+
],
|
|
886
|
+
retriever: [
|
|
887
|
+
{ name: 'vector-retriever', description: 'Vector similarity search' },
|
|
888
|
+
{ name: 'keyword-retriever', description: 'Keyword-based search' },
|
|
889
|
+
],
|
|
890
|
+
llm: [
|
|
891
|
+
{ name: 'openai-llm', description: 'OpenAI language models' },
|
|
892
|
+
{ name: 'local-llm', description: 'Local language model' },
|
|
893
|
+
],
|
|
894
|
+
reranker: [
|
|
895
|
+
{
|
|
896
|
+
name: 'similarity-reranker',
|
|
897
|
+
description: 'Similarity-based reranking',
|
|
898
|
+
},
|
|
899
|
+
],
|
|
900
|
+
};
|
|
901
|
+
|
|
902
|
+
return builtins[_type] || [];
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
/**
|
|
906
|
+
* Get plugin information
|
|
907
|
+
* @param {string} _type - Plugin _type
|
|
908
|
+
* @param {string} name - Plugin name
|
|
909
|
+
* @returns {object|null} Plugin information
|
|
910
|
+
*/
|
|
911
|
+
getPluginInfo(_type, name) {
|
|
912
|
+
if (!this.registry) {
|
|
913
|
+
return null;
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
return this.registry.plugins[name] || null;
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
/**
|
|
920
|
+
* Load wizard configuration
|
|
921
|
+
* @returns {object} Current configuration
|
|
922
|
+
*/
|
|
923
|
+
loadConfig() {
|
|
924
|
+
return { ...this._config };
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
/**
|
|
928
|
+
* Navigate to next step
|
|
929
|
+
* @returns {string} Next step name
|
|
930
|
+
*/
|
|
931
|
+
nextStep() {
|
|
932
|
+
if (this.currentStep < this.steps.length - 1) {
|
|
933
|
+
this.currentStep++;
|
|
934
|
+
}
|
|
935
|
+
return this.steps[this.currentStep];
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
/**
|
|
939
|
+
* Navigate to previous step
|
|
940
|
+
* @returns {string} Previous step name
|
|
941
|
+
*/
|
|
942
|
+
previousStep() {
|
|
943
|
+
if (this.currentStep > 0) {
|
|
944
|
+
this.currentStep--;
|
|
945
|
+
}
|
|
946
|
+
return this.steps[this.currentStep];
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
/**
|
|
950
|
+
* Complete the wizard
|
|
951
|
+
* @returns {Promise<object>} Completion result
|
|
952
|
+
*/
|
|
953
|
+
async complete() {
|
|
954
|
+
return {
|
|
955
|
+
success: true,
|
|
956
|
+
config: this._config,
|
|
957
|
+
message: 'Wizard completed successfully',
|
|
958
|
+
};
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
/**
|
|
962
|
+
* Validate user input
|
|
963
|
+
* @param {string} input - Input to validate
|
|
964
|
+
* @returns {boolean} Whether input is valid
|
|
965
|
+
*/
|
|
966
|
+
validateInput(input) {
|
|
967
|
+
return typeof input === 'string' && input.trim().length > 0;
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
/**
|
|
971
|
+
* Process user selection
|
|
972
|
+
* @param {string} selection - User selection
|
|
973
|
+
* @returns {object} Processing result
|
|
974
|
+
*/
|
|
975
|
+
processSelection(selection) {
|
|
976
|
+
return {
|
|
977
|
+
selection,
|
|
978
|
+
processed: true,
|
|
979
|
+
timestamp: Date.now(),
|
|
980
|
+
};
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
/**
|
|
985
|
+
* Main wizard function for CLI usage
|
|
986
|
+
* @param {object} options - Wizard options
|
|
987
|
+
* @returns {Promise<object>} Generated configuration
|
|
988
|
+
*/
|
|
989
|
+
async function runInteractiveWizard(options = {}) {
|
|
990
|
+
const wizard = new InteractiveWizard(options);
|
|
991
|
+
return await wizard.run();
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
module.exports = {
|
|
995
|
+
InteractiveWizard,
|
|
996
|
+
runInteractiveWizard,
|
|
997
|
+
};
|