@runflow-ai/cli 0.2.20 → 0.2.22

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 (37) hide show
  1. package/README.md +313 -113
  2. package/dist/commands/agents/agents.command.d.ts +1 -0
  3. package/dist/commands/agents/agents.command.js +39 -20
  4. package/dist/commands/agents/agents.command.js.map +1 -1
  5. package/dist/commands/agents/git.service.js +8 -2
  6. package/dist/commands/agents/git.service.js.map +1 -1
  7. package/dist/commands/agents/types.d.ts +1 -0
  8. package/dist/commands/agents/types.js.map +1 -1
  9. package/dist/commands/create/create.command.d.ts +19 -0
  10. package/dist/commands/create/create.command.js +316 -0
  11. package/dist/commands/create/create.command.js.map +1 -0
  12. package/dist/commands/kb/kb.command.d.ts +28 -0
  13. package/dist/commands/kb/kb.command.js +627 -0
  14. package/dist/commands/kb/kb.command.js.map +1 -0
  15. package/dist/commands/login/login.command.d.ts +2 -0
  16. package/dist/commands/login/login.command.js +26 -4
  17. package/dist/commands/login/login.command.js.map +1 -1
  18. package/dist/commands/profiles/profiles.command.d.ts +7 -0
  19. package/dist/commands/profiles/profiles.command.js +104 -0
  20. package/dist/commands/profiles/profiles.command.js.map +1 -0
  21. package/dist/commands/prompts/prompts.command.d.ts +17 -0
  22. package/dist/commands/prompts/prompts.command.js +497 -28
  23. package/dist/commands/prompts/prompts.command.js.map +1 -1
  24. package/dist/commands/switch/switch.command.d.ts +5 -0
  25. package/dist/commands/switch/switch.command.js +78 -0
  26. package/dist/commands/switch/switch.command.js.map +1 -0
  27. package/dist/commands/test/test.command.js +36 -22
  28. package/dist/commands/test/test.command.js.map +1 -1
  29. package/dist/common/config.d.ts +25 -2
  30. package/dist/common/config.js +94 -16
  31. package/dist/common/config.js.map +1 -1
  32. package/dist/common/help.d.ts +1 -1
  33. package/dist/common/help.js +4 -1
  34. package/dist/common/help.js.map +1 -1
  35. package/dist/index.js +11 -3
  36. package/dist/index.js.map +1 -1
  37. package/package.json +5 -1
@@ -0,0 +1,627 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
19
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
20
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
21
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
22
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
23
+ };
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ var __metadata = (this && this.__metadata) || function (k, v) {
42
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
43
+ };
44
+ var __importDefault = (this && this.__importDefault) || function (mod) {
45
+ return (mod && mod.__esModule) ? mod : { "default": mod };
46
+ };
47
+ Object.defineProperty(exports, "__esModule", { value: true });
48
+ exports.KnowledgeBaseCommand = void 0;
49
+ const nest_commander_1 = require("nest-commander");
50
+ const prompts_1 = require("@clack/prompts");
51
+ const config_1 = require("../../common/config");
52
+ const api_client_1 = require("../../common/api-client");
53
+ const chalk_1 = __importDefault(require("chalk"));
54
+ const fs = __importStar(require("fs"));
55
+ const path = __importStar(require("path"));
56
+ const form_data_1 = __importDefault(require("form-data"));
57
+ const axios_1 = __importDefault(require("axios"));
58
+ const config_2 = require("../../common/config");
59
+ let KnowledgeBaseCommand = class KnowledgeBaseCommand extends nest_commander_1.CommandRunner {
60
+ async run(inputs, options) {
61
+ const [action, name, filePath] = inputs;
62
+ const actions = ['list', 'create', 'upload', 'status', 'delete', 'docs', 'remove-doc', 'search'];
63
+ if (!action) {
64
+ this.showHelp();
65
+ return;
66
+ }
67
+ if (!actions.includes(action)) {
68
+ console.log(chalk_1.default.red(`Unknown action: ${action}`));
69
+ this.showHelp();
70
+ return;
71
+ }
72
+ try {
73
+ const apiClient = (0, api_client_1.createApiClient)(options.api);
74
+ switch (action) {
75
+ case 'list':
76
+ await this.listKnowledgeBases(apiClient);
77
+ break;
78
+ case 'create':
79
+ await this.createKnowledgeBase(apiClient, name, options);
80
+ break;
81
+ case 'upload':
82
+ if (!name || !filePath) {
83
+ console.log(chalk_1.default.red('Usage: rf kb upload <kb-name> <file-or-directory>'));
84
+ return;
85
+ }
86
+ await this.upload(apiClient, name, filePath, options);
87
+ break;
88
+ case 'status':
89
+ if (!name) {
90
+ console.log(chalk_1.default.red('Usage: rf kb status <kb-name>'));
91
+ return;
92
+ }
93
+ await this.getStatus(apiClient, name);
94
+ break;
95
+ case 'delete':
96
+ if (!name) {
97
+ console.log(chalk_1.default.red('Usage: rf kb delete <kb-name>'));
98
+ return;
99
+ }
100
+ await this.deleteKnowledgeBase(apiClient, name, options);
101
+ break;
102
+ case 'docs':
103
+ if (!name) {
104
+ console.log(chalk_1.default.red('Usage: rf kb docs <kb-name>'));
105
+ return;
106
+ }
107
+ await this.listDocuments(apiClient, name);
108
+ break;
109
+ case 'remove-doc':
110
+ if (!name || !filePath) {
111
+ console.log(chalk_1.default.red('Usage: rf kb remove-doc <kb-name> <doc-id>'));
112
+ return;
113
+ }
114
+ await this.removeDocument(apiClient, name, filePath, options);
115
+ break;
116
+ case 'search':
117
+ if (!name || !filePath) {
118
+ console.log(chalk_1.default.red('Usage: rf kb search <kb-name> "<query>"'));
119
+ return;
120
+ }
121
+ await this.search(apiClient, name, filePath);
122
+ break;
123
+ }
124
+ }
125
+ catch (error) {
126
+ console.log(chalk_1.default.red('Error: ' + (error.response?.data?.message || error.message)));
127
+ }
128
+ }
129
+ async interactiveMode(options) {
130
+ console.log('');
131
+ (0, prompts_1.intro)(chalk_1.default.cyan.bold('📚 Runflow Knowledge Bases'));
132
+ const s = (0, prompts_1.spinner)();
133
+ s.start('Fetching knowledge bases...');
134
+ const apiClient = (0, api_client_1.createApiClient)(options.api);
135
+ const res = await apiClient.get('/vector-stores');
136
+ const kbs = res.data.data || [];
137
+ s.stop(chalk_1.default.green(`✓ Found ${kbs.length} knowledge bases`));
138
+ if (kbs.length === 0) {
139
+ const createNew = await (0, prompts_1.confirm)({
140
+ message: 'No knowledge bases found. Create one now?',
141
+ initialValue: true,
142
+ });
143
+ if (createNew) {
144
+ await this.createKnowledgeBase(apiClient);
145
+ }
146
+ (0, prompts_1.outro)(chalk_1.default.gray('Done'));
147
+ return;
148
+ }
149
+ const choices = [
150
+ ...kbs.map((kb) => ({
151
+ value: kb.id,
152
+ label: kb.name,
153
+ hint: `${kb.documentCount || 0} documents`,
154
+ })),
155
+ { value: '__create__', label: '+ Create new', hint: 'Create a knowledge base' },
156
+ ];
157
+ const selectedId = await (0, prompts_1.select)({
158
+ message: 'Select a knowledge base:',
159
+ options: choices,
160
+ });
161
+ if (typeof selectedId === 'symbol') {
162
+ (0, prompts_1.outro)(chalk_1.default.gray('Cancelled'));
163
+ return;
164
+ }
165
+ if (selectedId === '__create__') {
166
+ await this.createKnowledgeBase(apiClient);
167
+ (0, prompts_1.outro)(chalk_1.default.green('✓ Knowledge base created'));
168
+ return;
169
+ }
170
+ const selectedKb = kbs.find((kb) => kb.id === selectedId);
171
+ const actionChoice = await (0, prompts_1.select)({
172
+ message: `What would you like to do with "${selectedKb.name}"?`,
173
+ options: [
174
+ { value: 'status', label: '📊 View stats' },
175
+ { value: 'upload-file', label: '📤 Upload file' },
176
+ { value: 'upload-dir', label: '📂 Upload directory' },
177
+ { value: 'docs', label: '📄 List documents' },
178
+ { value: 'search', label: '🔍 Search' },
179
+ { value: 'delete', label: '🗑️ Delete' },
180
+ { value: 'cancel', label: '❌ Cancel' },
181
+ ],
182
+ });
183
+ if (typeof actionChoice === 'symbol' || actionChoice === 'cancel') {
184
+ (0, prompts_1.outro)(chalk_1.default.gray('Cancelled'));
185
+ return;
186
+ }
187
+ switch (actionChoice) {
188
+ case 'status':
189
+ await this.getStatus(apiClient, selectedKb.name);
190
+ break;
191
+ case 'upload-file':
192
+ const filePath = await (0, prompts_1.text)({
193
+ message: 'File path:',
194
+ placeholder: './document.pdf',
195
+ validate: (value) => {
196
+ if (!value)
197
+ return 'File path required';
198
+ if (!fs.existsSync(value))
199
+ return 'File not found';
200
+ return undefined;
201
+ },
202
+ });
203
+ if (typeof filePath === 'string') {
204
+ await this.upload(apiClient, selectedKb.name, filePath);
205
+ }
206
+ break;
207
+ case 'upload-dir':
208
+ const dirPath = await (0, prompts_1.text)({
209
+ message: 'Directory path:',
210
+ placeholder: './docs',
211
+ validate: (value) => {
212
+ if (!value)
213
+ return 'Directory path required';
214
+ if (!fs.existsSync(value))
215
+ return 'Directory not found';
216
+ if (!fs.statSync(value).isDirectory())
217
+ return 'Not a directory';
218
+ return undefined;
219
+ },
220
+ });
221
+ if (typeof dirPath === 'string') {
222
+ await this.upload(apiClient, selectedKb.name, dirPath);
223
+ }
224
+ break;
225
+ case 'docs':
226
+ await this.listDocuments(apiClient, selectedKb.name);
227
+ break;
228
+ case 'search':
229
+ const query = await (0, prompts_1.text)({
230
+ message: 'Search query:',
231
+ placeholder: 'How to configure authentication?',
232
+ });
233
+ if (typeof query === 'string') {
234
+ await this.search(apiClient, selectedKb.name, query);
235
+ }
236
+ break;
237
+ case 'delete':
238
+ await this.deleteKnowledgeBase(apiClient, selectedKb.name);
239
+ break;
240
+ }
241
+ (0, prompts_1.outro)(chalk_1.default.green('✓ Done'));
242
+ }
243
+ async listKnowledgeBases(apiClient) {
244
+ const res = await apiClient.get('/vector-stores');
245
+ const kbs = res.data.data || [];
246
+ console.log(chalk_1.default.cyan.bold(`\n📚 Knowledge Bases (${kbs.length} total)\n`));
247
+ if (kbs.length === 0) {
248
+ console.log(chalk_1.default.gray(' No knowledge bases found'));
249
+ console.log(chalk_1.default.gray(' Create one with: rf kb create\n'));
250
+ return;
251
+ }
252
+ kbs.forEach((kb) => {
253
+ console.log(chalk_1.default.white(` ${kb.name}`));
254
+ console.log(chalk_1.default.gray(` Documents: ${kb.documentCount || 0}`));
255
+ console.log(chalk_1.default.gray(` Embedding: ${kb.embeddingConfig?.name || 'Unknown'}`));
256
+ console.log('');
257
+ });
258
+ }
259
+ async createKnowledgeBase(apiClient, name, options) {
260
+ let kbName = name;
261
+ if (options?.embedding && !kbName) {
262
+ console.log(chalk_1.default.red('Name required with --embedding'));
263
+ console.log(chalk_1.default.gray('Usage: rf kb create <name> --embedding <config-id-or-name>'));
264
+ return;
265
+ }
266
+ if (!kbName) {
267
+ const nameInput = await (0, prompts_1.text)({
268
+ message: 'Knowledge base name:',
269
+ placeholder: 'product-docs',
270
+ validate: (value) => {
271
+ if (!value || !value.trim())
272
+ return 'Name is required';
273
+ if (!/^[a-z0-9-_]+$/i.test(value.trim())) {
274
+ return 'Use only letters, numbers, hyphens, and underscores';
275
+ }
276
+ return undefined;
277
+ },
278
+ });
279
+ if (typeof nameInput === 'symbol')
280
+ return;
281
+ kbName = nameInput.trim();
282
+ }
283
+ console.log(chalk_1.default.gray('Fetching embedding configurations...'));
284
+ const configsRes = await apiClient.get('/vector-stores/embedding-configs');
285
+ const configs = configsRes.data.data || [];
286
+ if (configs.length === 0) {
287
+ console.log(chalk_1.default.red('No embedding configurations available'));
288
+ return;
289
+ }
290
+ let embeddingConfigId;
291
+ if (options?.embedding) {
292
+ const matchedConfig = configs.find((c) => c.id === options.embedding ||
293
+ c.name.toLowerCase() === options.embedding?.toLowerCase() ||
294
+ c.name.toLowerCase().includes(options.embedding?.toLowerCase() || ''));
295
+ if (!matchedConfig) {
296
+ console.log(chalk_1.default.red(`Embedding config not found: ${options.embedding}`));
297
+ console.log(chalk_1.default.gray('Available configs:'));
298
+ configs.forEach((c) => {
299
+ console.log(chalk_1.default.gray(` - ${c.name} (${c.id})`));
300
+ });
301
+ return;
302
+ }
303
+ embeddingConfigId = matchedConfig.id;
304
+ console.log(chalk_1.default.gray(`Using embedding: ${matchedConfig.name}`));
305
+ }
306
+ else {
307
+ const selectedConfigId = await (0, prompts_1.select)({
308
+ message: 'Choose embedding configuration:',
309
+ options: configs.map((c) => ({
310
+ value: c.id,
311
+ label: c.name,
312
+ hint: `${c.provider} - ${c.model}`,
313
+ })),
314
+ });
315
+ if (typeof selectedConfigId === 'symbol')
316
+ return;
317
+ embeddingConfigId = selectedConfigId;
318
+ }
319
+ console.log(chalk_1.default.gray('Creating knowledge base...'));
320
+ await apiClient.post('/vector-stores', {
321
+ name: kbName,
322
+ embeddingConfigId,
323
+ type: 'KNOWLEDGE',
324
+ chunkSize: 1000,
325
+ chunkOverlap: 200,
326
+ chunkStrategy: 'recursive',
327
+ });
328
+ console.log(chalk_1.default.green('✓ Knowledge base created: ' + kbName));
329
+ console.log('');
330
+ console.log(chalk_1.default.cyan.bold('Use in your agent:'));
331
+ console.log(chalk_1.default.white(` rag: {`));
332
+ console.log(chalk_1.default.white(` vectorStore: '${kbName}',`));
333
+ console.log(chalk_1.default.white(` autoSearch: true,`));
334
+ console.log(chalk_1.default.white(` }`));
335
+ console.log('');
336
+ }
337
+ async upload(apiClient, kbName, targetPath, options) {
338
+ const stats = fs.statSync(targetPath);
339
+ if (stats.isDirectory()) {
340
+ await this.uploadDirectory(apiClient, kbName, targetPath, options);
341
+ }
342
+ else {
343
+ await this.uploadFile(apiClient, kbName, targetPath);
344
+ }
345
+ }
346
+ async uploadFile(apiClient, kbName, filePath) {
347
+ const s = (0, prompts_1.spinner)();
348
+ s.start(`Uploading ${path.basename(filePath)}...`);
349
+ try {
350
+ const { config } = (0, config_2.getValidatedConfig)();
351
+ const apiUrl = config.api || config_1.DEFAULT_API_URL;
352
+ const formData = new form_data_1.default();
353
+ formData.append('file', fs.createReadStream(filePath));
354
+ formData.append('vectorStore', kbName);
355
+ formData.append('title', path.basename(filePath));
356
+ await axios_1.default.post(`${apiUrl}/runtime/v1/vectors/upload`, formData, {
357
+ headers: {
358
+ ...formData.getHeaders(),
359
+ 'x-api-key': config.apiKey,
360
+ },
361
+ maxBodyLength: Infinity,
362
+ maxContentLength: Infinity,
363
+ });
364
+ s.stop(chalk_1.default.green('✓ File uploaded and processed'));
365
+ }
366
+ catch (error) {
367
+ s.stop(chalk_1.default.red('✗ Upload failed'));
368
+ throw error;
369
+ }
370
+ }
371
+ async uploadDirectory(apiClient, kbName, dirPath, options) {
372
+ const files = this.findFiles(dirPath);
373
+ if (files.length === 0) {
374
+ console.log(chalk_1.default.yellow('No files found in directory'));
375
+ return;
376
+ }
377
+ console.log(chalk_1.default.blue(`\nFound ${files.length} files`));
378
+ if (!options?.yes) {
379
+ const shouldContinue = await (0, prompts_1.confirm)({
380
+ message: `Upload ${files.length} files to "${kbName}"?`,
381
+ initialValue: true,
382
+ });
383
+ if (typeof shouldContinue !== 'boolean' || !shouldContinue) {
384
+ console.log(chalk_1.default.gray('Cancelled'));
385
+ return;
386
+ }
387
+ }
388
+ let uploaded = 0;
389
+ let failed = 0;
390
+ for (const file of files) {
391
+ const relativePath = path.relative(dirPath, file);
392
+ console.log(chalk_1.default.gray(`[${uploaded + failed + 1}/${files.length}] ${relativePath}`));
393
+ try {
394
+ const { config } = (0, config_2.getValidatedConfig)();
395
+ const apiUrl = config.api || config_1.DEFAULT_API_URL;
396
+ const formData = new form_data_1.default();
397
+ formData.append('file', fs.createReadStream(file));
398
+ formData.append('vectorStore', kbName);
399
+ formData.append('title', relativePath);
400
+ await axios_1.default.post(`${apiUrl}/runtime/v1/vectors/upload`, formData, {
401
+ headers: {
402
+ ...formData.getHeaders(),
403
+ 'x-api-key': config.apiKey,
404
+ },
405
+ maxBodyLength: Infinity,
406
+ maxContentLength: Infinity,
407
+ });
408
+ uploaded++;
409
+ console.log(chalk_1.default.green(' ✓ Uploaded'));
410
+ }
411
+ catch (error) {
412
+ failed++;
413
+ console.log(chalk_1.default.red(' ✗ Failed'));
414
+ }
415
+ }
416
+ console.log('');
417
+ console.log(chalk_1.default.green(`✓ Uploaded: ${uploaded}`));
418
+ if (failed > 0) {
419
+ console.log(chalk_1.default.red(`✗ Failed: ${failed}`));
420
+ }
421
+ console.log('');
422
+ }
423
+ async getStatus(apiClient, name) {
424
+ const res = await apiClient.get(`/vector-stores/${name}`);
425
+ const kb = res.data.data;
426
+ console.log(chalk_1.default.cyan.bold('\n📚 Knowledge Base Stats\n'));
427
+ console.log(chalk_1.default.gray('Name: ') + chalk_1.default.white(kb.name));
428
+ console.log(chalk_1.default.gray('ID: ') + chalk_1.default.white(kb.id));
429
+ console.log(chalk_1.default.gray('Documents: ') + chalk_1.default.white(kb.documentCount || 0));
430
+ console.log(chalk_1.default.gray('Embedding: ') + chalk_1.default.white(`${kb.embeddingConfig.provider} - ${kb.embeddingConfig.model}`));
431
+ console.log(chalk_1.default.gray('Dimensions: ') + chalk_1.default.white(kb.embeddingConfig.dimensions));
432
+ console.log(chalk_1.default.gray('Chunk size: ') + chalk_1.default.white(kb.chunkSize || 1000));
433
+ console.log('');
434
+ }
435
+ async deleteKnowledgeBase(apiClient, name, options) {
436
+ const res = await apiClient.get(`/vector-stores/${name}`);
437
+ const kb = res.data.data;
438
+ if (!options?.yes) {
439
+ const shouldDelete = await (0, prompts_1.confirm)({
440
+ message: `Delete "${kb.name}" (${kb.documentCount || 0} documents)?`,
441
+ initialValue: false,
442
+ });
443
+ if (typeof shouldDelete !== 'boolean' || !shouldDelete) {
444
+ console.log(chalk_1.default.gray('Cancelled'));
445
+ return;
446
+ }
447
+ }
448
+ console.log(chalk_1.default.gray('Deleting knowledge base...'));
449
+ await apiClient.delete(`/vector-stores/${name}`);
450
+ console.log(chalk_1.default.green('✓ Knowledge base deleted'));
451
+ }
452
+ async listDocuments(apiClient, kbName) {
453
+ const s = (0, prompts_1.spinner)();
454
+ s.start('Fetching documents...');
455
+ const res = await apiClient.get(`/vector-stores/${kbName}/documents`);
456
+ const docs = res.data.data?.documents || [];
457
+ s.stop(chalk_1.default.green(`✓ Found ${docs.length} documents`));
458
+ console.log(chalk_1.default.cyan.bold(`\n📄 Documents in "${kbName}"\n`));
459
+ if (docs.length === 0) {
460
+ console.log(chalk_1.default.gray(' No documents found'));
461
+ console.log(chalk_1.default.gray(` Upload with: rf kb upload ${kbName} <file>\n`));
462
+ return;
463
+ }
464
+ docs.forEach((doc, index) => {
465
+ const title = doc.metadata?.title || doc.metadata?.fileName || 'Untitled';
466
+ console.log(chalk_1.default.white(` ${index + 1}. ${title}`));
467
+ console.log(chalk_1.default.gray(` ID: ${doc.id}`));
468
+ if (doc.metadata?.fileSize) {
469
+ const sizeMB = (doc.metadata.fileSize / 1024 / 1024).toFixed(2);
470
+ console.log(chalk_1.default.gray(` Size: ${sizeMB} MB`));
471
+ }
472
+ console.log('');
473
+ });
474
+ }
475
+ async removeDocument(apiClient, kbName, docId, options) {
476
+ if (!options?.yes) {
477
+ const shouldDelete = await (0, prompts_1.confirm)({
478
+ message: `Delete document ${docId}?`,
479
+ initialValue: false,
480
+ });
481
+ if (typeof shouldDelete !== 'boolean' || !shouldDelete) {
482
+ console.log(chalk_1.default.gray('Cancelled'));
483
+ return;
484
+ }
485
+ }
486
+ console.log(chalk_1.default.gray('Deleting document...'));
487
+ await apiClient.delete(`/vector-stores/${kbName}/documents/${docId}`);
488
+ console.log(chalk_1.default.green('✓ Document deleted'));
489
+ }
490
+ async search(apiClient, kbName, query) {
491
+ const s = (0, prompts_1.spinner)();
492
+ s.start('Searching...');
493
+ const res = await apiClient.post(`/vector-stores/${kbName}/search`, {
494
+ query,
495
+ k: 5,
496
+ threshold: 0.7,
497
+ });
498
+ const results = res.data.data || [];
499
+ s.stop(chalk_1.default.green(`✓ Found ${results.length} results`));
500
+ console.log(chalk_1.default.cyan.bold(`\n🔍 Search Results for "${query}"\n`));
501
+ if (results.length === 0) {
502
+ console.log(chalk_1.default.gray(' No results found\n'));
503
+ return;
504
+ }
505
+ results.forEach((result, index) => {
506
+ const score = (result.score * 100).toFixed(1);
507
+ console.log(chalk_1.default.white(` ${index + 1}. Score: ${score}%`));
508
+ if (result.metadata?.title) {
509
+ console.log(chalk_1.default.gray(` Source: ${result.metadata.title}`));
510
+ }
511
+ const preview = result.content.substring(0, 150);
512
+ console.log(chalk_1.default.gray(` ${preview}${result.content.length > 150 ? '...' : ''}`));
513
+ console.log('');
514
+ });
515
+ }
516
+ findFiles(dirPath, extensions = ['.pdf', '.txt', '.md', '.docx', '.doc']) {
517
+ const files = [];
518
+ const traverse = (currentPath) => {
519
+ const items = fs.readdirSync(currentPath);
520
+ for (const item of items) {
521
+ const fullPath = path.join(currentPath, item);
522
+ const stat = fs.statSync(fullPath);
523
+ if (stat.isDirectory()) {
524
+ if (!['node_modules', '.git', 'dist', 'build'].includes(item)) {
525
+ traverse(fullPath);
526
+ }
527
+ }
528
+ else if (stat.isFile()) {
529
+ const ext = path.extname(item).toLowerCase();
530
+ if (extensions.includes(ext)) {
531
+ files.push(fullPath);
532
+ }
533
+ }
534
+ }
535
+ };
536
+ traverse(dirPath);
537
+ return files;
538
+ }
539
+ showHelp() {
540
+ console.log('');
541
+ console.log(chalk_1.default.cyan.bold('📚 Knowledge Base Management'));
542
+ console.log(chalk_1.default.gray('Manage vector stores for RAG (Retrieval Augmented Generation)\n'));
543
+ console.log(chalk_1.default.white.bold('Usage:'));
544
+ console.log(chalk_1.default.gray(' rf kb <action> [name] [path]\n'));
545
+ console.log(chalk_1.default.white.bold('Actions:'));
546
+ console.log(chalk_1.default.cyan(' list ') + chalk_1.default.gray('List all knowledge bases'));
547
+ console.log(chalk_1.default.cyan(' create <name> ') + chalk_1.default.gray('Create new knowledge base'));
548
+ console.log(chalk_1.default.cyan(' status <name> ') + chalk_1.default.gray('Show KB stats and info'));
549
+ console.log(chalk_1.default.cyan(' upload <name> <path> ') + chalk_1.default.gray('Upload file or directory'));
550
+ console.log(chalk_1.default.cyan(' docs <name> ') + chalk_1.default.gray('List documents in KB'));
551
+ console.log(chalk_1.default.cyan(' search <name> <query> ') + chalk_1.default.gray('Semantic search in KB'));
552
+ console.log(chalk_1.default.cyan(' remove-doc <name> <id> ') + chalk_1.default.gray('Remove document from KB'));
553
+ console.log(chalk_1.default.cyan(' delete <name> ') + chalk_1.default.gray('Delete knowledge base'));
554
+ console.log('');
555
+ console.log(chalk_1.default.white.bold('Options:'));
556
+ console.log(chalk_1.default.cyan(' -e, --embedding <config> ') + chalk_1.default.gray('Embedding config (non-interactive)'));
557
+ console.log(chalk_1.default.cyan(' -y, --yes ') + chalk_1.default.gray('Skip confirmation prompts'));
558
+ console.log('');
559
+ console.log(chalk_1.default.white.bold('Examples:'));
560
+ console.log(chalk_1.default.gray(' rf kb list'));
561
+ console.log(chalk_1.default.gray(' rf kb create product-docs'));
562
+ console.log(chalk_1.default.gray(' rf kb create docs --embedding "OpenAI Small"'));
563
+ console.log(chalk_1.default.gray(' rf kb upload product-docs ./manual.pdf'));
564
+ console.log(chalk_1.default.gray(' rf kb upload docs ./folder --yes'));
565
+ console.log(chalk_1.default.gray(' rf kb search product-docs "how to reset password"'));
566
+ console.log(chalk_1.default.gray(' rf kb delete old-kb --yes'));
567
+ console.log('');
568
+ }
569
+ parseApiKey(val) {
570
+ return val;
571
+ }
572
+ parseApi(val) {
573
+ return val;
574
+ }
575
+ parseEmbedding(val) {
576
+ return val;
577
+ }
578
+ parseYes() {
579
+ return true;
580
+ }
581
+ };
582
+ exports.KnowledgeBaseCommand = KnowledgeBaseCommand;
583
+ __decorate([
584
+ (0, nest_commander_1.Option)({
585
+ flags: '--api-key <key>',
586
+ description: 'API key override',
587
+ }),
588
+ __metadata("design:type", Function),
589
+ __metadata("design:paramtypes", [String]),
590
+ __metadata("design:returntype", String)
591
+ ], KnowledgeBaseCommand.prototype, "parseApiKey", null);
592
+ __decorate([
593
+ (0, nest_commander_1.Option)({
594
+ flags: '--api <url>',
595
+ description: `API URL override (default: ${config_1.DEFAULT_API_URL})`,
596
+ }),
597
+ __metadata("design:type", Function),
598
+ __metadata("design:paramtypes", [String]),
599
+ __metadata("design:returntype", String)
600
+ ], KnowledgeBaseCommand.prototype, "parseApi", null);
601
+ __decorate([
602
+ (0, nest_commander_1.Option)({
603
+ flags: '-e, --embedding <config>',
604
+ description: 'Embedding config ID or name (non-interactive mode)',
605
+ }),
606
+ __metadata("design:type", Function),
607
+ __metadata("design:paramtypes", [String]),
608
+ __metadata("design:returntype", String)
609
+ ], KnowledgeBaseCommand.prototype, "parseEmbedding", null);
610
+ __decorate([
611
+ (0, nest_commander_1.Option)({
612
+ flags: '-y, --yes',
613
+ description: 'Skip confirmation prompts',
614
+ }),
615
+ __metadata("design:type", Function),
616
+ __metadata("design:paramtypes", []),
617
+ __metadata("design:returntype", Boolean)
618
+ ], KnowledgeBaseCommand.prototype, "parseYes", null);
619
+ exports.KnowledgeBaseCommand = KnowledgeBaseCommand = __decorate([
620
+ (0, nest_commander_1.Command)({
621
+ name: 'kb',
622
+ aliases: ['knowledge'],
623
+ arguments: '[action] [name] [path]',
624
+ description: 'Manage knowledge bases for RAG (Retrieval Augmented Generation)',
625
+ })
626
+ ], KnowledgeBaseCommand);
627
+ //# sourceMappingURL=kb.command.js.map