@lanonasis/cli 1.5.2 → 2.0.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.
@@ -0,0 +1,569 @@
1
+ /**
2
+ * Main Dashboard Command Center
3
+ * The central hub for all CLI operations after authentication
4
+ */
5
+ import chalk from 'chalk';
6
+ import inquirer from 'inquirer';
7
+ import boxen from 'boxen';
8
+ import Table from 'cli-table3';
9
+ export class DashboardCommandCenter {
10
+ stateManager;
11
+ stats;
12
+ constructor(stateManager) {
13
+ this.stateManager = stateManager;
14
+ this.stats = this.loadStats();
15
+ }
16
+ async show() {
17
+ console.clear();
18
+ await this.render();
19
+ await this.handleUserInput();
20
+ }
21
+ async render() {
22
+ const userContext = this.stateManager.getUserContext();
23
+ const email = userContext.email || 'user@example.com';
24
+ // Header
25
+ console.log(this.renderHeader(email));
26
+ // Stats and Activity sections
27
+ console.log(this.renderStatsAndActivity());
28
+ // Main menu
29
+ console.log(this.renderMainMenu());
30
+ // Footer with shortcuts
31
+ console.log(this.renderFooter());
32
+ }
33
+ renderHeader(email) {
34
+ const header = `Onasis Command Center`;
35
+ const userInfo = `◐ ${email}`;
36
+ const padding = 72 - header.length - userInfo.length - 4;
37
+ return boxen(chalk.bold(header) + ' '.repeat(padding) + chalk.dim(userInfo), {
38
+ borderStyle: 'round',
39
+ borderColor: 'cyan',
40
+ padding: 0
41
+ });
42
+ }
43
+ renderStatsAndActivity() {
44
+ const statsBox = this.renderQuickStats();
45
+ const activityBox = this.renderRecentActivity();
46
+ // Create side-by-side layout
47
+ const statsLines = statsBox.split('\n');
48
+ const activityLines = activityBox.split('\n');
49
+ const maxLines = Math.max(statsLines.length, activityLines.length);
50
+ let combined = '';
51
+ for (let i = 0; i < maxLines; i++) {
52
+ const statLine = (statsLines[i] || '').padEnd(35);
53
+ const activityLine = activityLines[i] || '';
54
+ combined += ` ${statLine} ${activityLine}\n`;
55
+ }
56
+ return combined;
57
+ }
58
+ renderQuickStats() {
59
+ const stats = [
60
+ `├─ ${chalk.bold(this.stats.totalMemories)} Memories`,
61
+ `├─ ${chalk.bold(this.stats.totalTopics)} Topics`,
62
+ `└─ ${chalk.bold(this.stats.apiKeys)} API Keys`
63
+ ];
64
+ return chalk.blue('📊 Quick Stats\n') + stats.join('\n');
65
+ }
66
+ renderRecentActivity() {
67
+ const activities = this.stats.recentActivity.slice(0, 3).map((activity, index) => {
68
+ const isLast = index === this.stats.recentActivity.slice(0, 3).length - 1;
69
+ const prefix = isLast ? '└─' : '├─';
70
+ return `${prefix} "${activity.target}" ${chalk.dim(`(${activity.timestamp})`)}`;
71
+ });
72
+ return chalk.green('🎯 Recent Activity\n') + activities.join('\n');
73
+ }
74
+ renderMainMenu() {
75
+ const menuItems = [
76
+ ['1. 📝 Create Memory', '4. 🔍 Search Everything'],
77
+ ['2. 📁 Browse Topics', '5. 🔑 Manage API Keys'],
78
+ ['3. 📊 View Analytics', '6. ⚙️ Settings']
79
+ ];
80
+ const menuContent = chalk.bold('What would you like to do?\n\n') +
81
+ menuItems.map(row => ` ${row[0]} ${row[1]}`).join('\n') +
82
+ '\n\n' +
83
+ chalk.dim('Type a number, command, or describe what you need...');
84
+ return boxen(menuContent, {
85
+ padding: 1,
86
+ borderStyle: 'single',
87
+ borderColor: 'gray'
88
+ });
89
+ }
90
+ renderFooter() {
91
+ return chalk.dim(' [↵] Smart Command [/] Search [Tab] Complete [?] Help');
92
+ }
93
+ async handleUserInput() {
94
+ const { input } = await inquirer.prompt({
95
+ type: 'input',
96
+ name: 'input',
97
+ message: chalk.green('>'),
98
+ transformer: (input) => {
99
+ // Real-time input transformation/hints
100
+ if (input.startsWith('/')) {
101
+ return chalk.cyan(input) + chalk.dim(' (search mode)');
102
+ }
103
+ return input;
104
+ }
105
+ });
106
+ await this.processInput(input);
107
+ }
108
+ async processInput(input) {
109
+ // Smart command parsing
110
+ const normalized = input.toLowerCase().trim();
111
+ // Check for numbered options
112
+ if (['1', '2', '3', '4', '5', '6'].includes(normalized)) {
113
+ await this.handleNumberedOption(normalized);
114
+ return;
115
+ }
116
+ // Check for natural language commands
117
+ if (normalized.includes('create') || normalized.includes('new')) {
118
+ await this.createMemory();
119
+ }
120
+ else if (normalized.includes('search') || normalized.startsWith('/')) {
121
+ await this.searchMemories(input.replace('/', ''));
122
+ }
123
+ else if (normalized.includes('browse') || normalized.includes('topics')) {
124
+ await this.browseTopics();
125
+ }
126
+ else if (normalized.includes('analytics') || normalized.includes('stats')) {
127
+ await this.viewAnalytics();
128
+ }
129
+ else if (normalized.includes('api') || normalized.includes('keys')) {
130
+ await this.manageApiKeys();
131
+ }
132
+ else if (normalized.includes('settings') || normalized.includes('config')) {
133
+ await this.openSettings();
134
+ }
135
+ else if (normalized === '?' || normalized === 'help') {
136
+ await this.showHelp();
137
+ }
138
+ else {
139
+ // Try to interpret as a smart command
140
+ await this.interpretSmartCommand(input);
141
+ }
142
+ }
143
+ async handleNumberedOption(option) {
144
+ switch (option) {
145
+ case '1':
146
+ await this.createMemory();
147
+ break;
148
+ case '2':
149
+ await this.browseTopics();
150
+ break;
151
+ case '3':
152
+ await this.viewAnalytics();
153
+ break;
154
+ case '4':
155
+ await this.searchMemories('');
156
+ break;
157
+ case '5':
158
+ await this.manageApiKeys();
159
+ break;
160
+ case '6':
161
+ await this.openSettings();
162
+ break;
163
+ }
164
+ }
165
+ async createMemory() {
166
+ const creator = new InteractiveMemoryCreator(this.stateManager);
167
+ await creator.create();
168
+ }
169
+ async searchMemories(query) {
170
+ const search = new InteractiveSearch(this.stateManager);
171
+ await search.search(query);
172
+ }
173
+ async browseTopics() {
174
+ console.log(chalk.yellow('Browse Topics - Coming soon...'));
175
+ }
176
+ async viewAnalytics() {
177
+ const analytics = new AnalyticsView(this.stateManager);
178
+ await analytics.show();
179
+ }
180
+ async manageApiKeys() {
181
+ console.log(chalk.yellow('API Key Management - Coming soon...'));
182
+ }
183
+ async openSettings() {
184
+ console.log(chalk.yellow('Settings - Coming soon...'));
185
+ }
186
+ async showHelp() {
187
+ console.log(boxen(chalk.bold('📚 Help & Commands\n\n') +
188
+ chalk.cyan('Creating Memories:\n') +
189
+ ' create, new, add - Start creating a new memory\n' +
190
+ ' "remember that..." - Natural language memory creation\n\n' +
191
+ chalk.cyan('Searching:\n') +
192
+ ' search, find, / - Search your memories\n' +
193
+ ' /keyword - Quick search for keyword\n\n' +
194
+ chalk.cyan('Navigation:\n') +
195
+ ' 1-6 - Select numbered menu options\n' +
196
+ ' back, exit - Return to previous screen\n' +
197
+ ' clear - Clear the screen\n\n' +
198
+ chalk.dim('Pro tip: Use Tab for auto-completion'), {
199
+ padding: 1,
200
+ borderStyle: 'single',
201
+ borderColor: 'gray'
202
+ }));
203
+ }
204
+ async interpretSmartCommand(input) {
205
+ // AI-powered command interpretation
206
+ console.log(chalk.dim(`Interpreting: "${input}"...`));
207
+ // Simulate smart interpretation
208
+ if (input.toLowerCase().includes('remember')) {
209
+ const content = input.replace(/remember( that)?/i, '').trim();
210
+ const creator = new InteractiveMemoryCreator(this.stateManager);
211
+ await creator.createQuick(content);
212
+ }
213
+ else {
214
+ console.log(chalk.yellow(`Command not recognized. Type '?' for help.`));
215
+ }
216
+ }
217
+ loadStats() {
218
+ // Load real stats from API or cache
219
+ return {
220
+ totalMemories: 247,
221
+ totalTopics: 12,
222
+ apiKeys: 3,
223
+ recentActivity: [
224
+ { action: 'created', target: 'Project Alpha specs', timestamp: '2 min ago' },
225
+ { action: 'searched', target: 'Meeting notes Q4', timestamp: '1 hour ago' },
226
+ { action: 'updated', target: 'Customer feedback', timestamp: 'today' }
227
+ ]
228
+ };
229
+ }
230
+ }
231
+ /**
232
+ * Interactive Memory Creator
233
+ */
234
+ export class InteractiveMemoryCreator {
235
+ stateManager;
236
+ constructor(stateManager) {
237
+ this.stateManager = stateManager;
238
+ }
239
+ async create() {
240
+ console.clear();
241
+ console.log(chalk.bold.blue('📝 Creating New Memory\n'));
242
+ console.log("Let's capture your knowledge. I'll guide you through it:\n");
243
+ // Title input with validation
244
+ const { title } = await inquirer.prompt([
245
+ {
246
+ type: 'input',
247
+ name: 'title',
248
+ message: 'Title: (What should we call this memory?)',
249
+ validate: (input) => {
250
+ if (input.length < 3) {
251
+ return 'Title must be at least 3 characters';
252
+ }
253
+ if (input.length > 100) {
254
+ return 'Title must be less than 100 characters';
255
+ }
256
+ return true;
257
+ },
258
+ transformer: (input) => {
259
+ if (input.length > 0) {
260
+ return input + chalk.dim(` (${input.length}/100)`);
261
+ }
262
+ return input;
263
+ }
264
+ }
265
+ ]);
266
+ console.log(chalk.green('✓ Great title! Clear and searchable.\n'));
267
+ // Content input
268
+ const { content } = await inquirer.prompt([
269
+ {
270
+ type: 'editor',
271
+ name: 'content',
272
+ message: 'Content: (Press Ctrl+E for editor, or type/paste below)',
273
+ default: '',
274
+ postfix: '.md'
275
+ }
276
+ ]);
277
+ // Analyze content and suggest metadata
278
+ const suggestions = this.analyzeContent(content);
279
+ if (suggestions.topic) {
280
+ console.log(chalk.cyan(`📎 I noticed this looks like ${suggestions.contentType}. Would you like to:`));
281
+ const { topicChoice } = await inquirer.prompt([
282
+ {
283
+ type: 'list',
284
+ name: 'topicChoice',
285
+ message: 'Select topic:',
286
+ choices: [
287
+ { name: `Add to "${suggestions.topic}" topic (recommended)`, value: suggestions.topic },
288
+ { name: 'Create new topic', value: 'new' },
289
+ { name: 'Skip categorization', value: 'skip' }
290
+ ]
291
+ }
292
+ ]);
293
+ if (topicChoice === 'new') {
294
+ const { newTopic } = await inquirer.prompt([
295
+ {
296
+ type: 'input',
297
+ name: 'newTopic',
298
+ message: 'New topic name:'
299
+ }
300
+ ]);
301
+ suggestions.topic = newTopic;
302
+ }
303
+ else if (topicChoice === 'skip') {
304
+ suggestions.topic = null;
305
+ }
306
+ }
307
+ // Tag selection
308
+ if (suggestions.tags.length > 0) {
309
+ console.log(chalk.cyan('🏷️ Suggested tags based on content:'));
310
+ const { selectedTags } = await inquirer.prompt([
311
+ {
312
+ type: 'checkbox',
313
+ name: 'selectedTags',
314
+ message: 'Select tags:',
315
+ choices: suggestions.tags.map(tag => ({
316
+ name: tag,
317
+ value: tag,
318
+ checked: true
319
+ })),
320
+ pageSize: 10
321
+ }
322
+ ]);
323
+ const { additionalTags } = await inquirer.prompt([
324
+ {
325
+ type: 'input',
326
+ name: 'additionalTags',
327
+ message: 'Additional tags (comma-separated):',
328
+ default: ''
329
+ }
330
+ ]);
331
+ if (additionalTags) {
332
+ selectedTags.push(...additionalTags.split(',').map((t) => t.trim()));
333
+ }
334
+ suggestions.tags = selectedTags;
335
+ }
336
+ // Memory type selection
337
+ const { memoryType } = await inquirer.prompt([
338
+ {
339
+ type: 'list',
340
+ name: 'memoryType',
341
+ message: 'Memory Type:',
342
+ choices: [
343
+ { name: '[C]ontext - Situational information', value: 'context' },
344
+ { name: '[K]nowledge - Facts and learnings', value: 'knowledge' },
345
+ { name: '[R]eference - Documentation and guides', value: 'reference' },
346
+ { name: '[P]roject - Project-specific information', value: 'project' }
347
+ ]
348
+ }
349
+ ]);
350
+ // Preview
351
+ this.showPreview({
352
+ title,
353
+ content,
354
+ topic: suggestions.topic,
355
+ tags: suggestions.tags,
356
+ type: memoryType
357
+ });
358
+ // Confirm save
359
+ const { action } = await inquirer.prompt([
360
+ {
361
+ type: 'list',
362
+ name: 'action',
363
+ message: 'Ready to save?',
364
+ choices: [
365
+ { name: '[S]ave', value: 'save' },
366
+ { name: '[E]dit', value: 'edit' },
367
+ { name: '[C]ancel', value: 'cancel' }
368
+ ]
369
+ }
370
+ ]);
371
+ if (action === 'save') {
372
+ console.log(chalk.green('\n✓ Memory saved successfully!'));
373
+ console.log(chalk.dim('ID: mem_abc123'));
374
+ }
375
+ else if (action === 'edit') {
376
+ // Restart the process
377
+ await this.create();
378
+ }
379
+ }
380
+ async createQuick(content) {
381
+ console.log(chalk.green(`✓ Quick memory created: "${content}"`));
382
+ }
383
+ analyzeContent(content) {
384
+ // Simple content analysis
385
+ const suggestions = {
386
+ contentType: 'a technical decision',
387
+ topic: null,
388
+ tags: []
389
+ };
390
+ // Detect content type and suggest metadata
391
+ if (content.toLowerCase().includes('architecture')) {
392
+ suggestions.topic = 'Architecture';
393
+ suggestions.tags = ['architecture'];
394
+ }
395
+ if (content.toLowerCase().includes('microservice')) {
396
+ suggestions.tags.push('microservices');
397
+ }
398
+ if (content.toLowerCase().includes('payment')) {
399
+ suggestions.tags.push('payments');
400
+ }
401
+ if (content.toLowerCase().includes('api')) {
402
+ suggestions.tags.push('api');
403
+ }
404
+ return suggestions;
405
+ }
406
+ showPreview(memory) {
407
+ const typeIcon = {
408
+ context: '🔍',
409
+ knowledge: '📚',
410
+ reference: '📖',
411
+ project: '🎯'
412
+ }[memory.type] || '📝';
413
+ console.log(boxen(`${typeIcon} ${chalk.bold(memory.type.charAt(0).toUpperCase() + memory.type.slice(1))} Memory\n\n` +
414
+ `${chalk.bold('Title:')} ${memory.title}\n` +
415
+ `${chalk.bold('Topic:')} ${memory.topic || 'None'}\n` +
416
+ `${chalk.bold('Tags:')} ${memory.tags.join(', ')}\n\n` +
417
+ chalk.dim(memory.content.substring(0, 100) + '...'), {
418
+ padding: 1,
419
+ borderStyle: 'single',
420
+ borderColor: 'green',
421
+ title: 'Preview',
422
+ titleAlignment: 'left'
423
+ }));
424
+ }
425
+ }
426
+ /**
427
+ * Interactive Search Experience
428
+ */
429
+ export class InteractiveSearch {
430
+ stateManager;
431
+ constructor(stateManager) {
432
+ this.stateManager = stateManager;
433
+ }
434
+ async search(initialQuery = '') {
435
+ console.clear();
436
+ console.log(chalk.bold.blue('🔍 Search Everything\n'));
437
+ const { query } = await inquirer.prompt([
438
+ {
439
+ type: 'input',
440
+ name: 'query',
441
+ message: 'Search:',
442
+ default: initialQuery,
443
+ transformer: (input) => {
444
+ if (input.length > 0) {
445
+ return chalk.cyan(input);
446
+ }
447
+ return input;
448
+ }
449
+ }
450
+ ]);
451
+ if (!query) {
452
+ return;
453
+ }
454
+ // Simulate search
455
+ console.log(chalk.dim(`\nSearching for "${query}"...`));
456
+ await this.simulateDelay(500);
457
+ // Display results
458
+ this.displayResults(query);
459
+ // Result actions
460
+ const { action } = await inquirer.prompt([
461
+ {
462
+ type: 'list',
463
+ name: 'action',
464
+ message: 'Actions:',
465
+ choices: [
466
+ { name: '[↵] View first result', value: 'view' },
467
+ { name: '[E]dit result', value: 'edit' },
468
+ { name: '[D]elete result', value: 'delete' },
469
+ { name: '[R]efine search', value: 'refine' },
470
+ { name: '[N]ew search', value: 'new' },
471
+ { name: '[B]ack to dashboard', value: 'back' }
472
+ ]
473
+ }
474
+ ]);
475
+ switch (action) {
476
+ case 'refine':
477
+ await this.search(query);
478
+ break;
479
+ case 'new':
480
+ await this.search('');
481
+ break;
482
+ case 'view':
483
+ console.log(chalk.green('Viewing result...'));
484
+ break;
485
+ }
486
+ }
487
+ displayResults(query) {
488
+ const results = [
489
+ { score: 94, title: 'Payment Gateway Integration Guide', age: '3 days ago', type: 'Knowledge', tags: 'api, payments, stripe' },
490
+ { score: 87, title: 'Payment Error Handling Strategy', age: '1 week ago', type: 'Context', tags: 'error-handling, payments' },
491
+ { score: 76, title: 'Q3 Payment Provider Comparison', age: '2 weeks ago', type: 'Reference', tags: 'analysis, vendors' }
492
+ ];
493
+ console.log(boxen(chalk.bold(`Found ${results.length} relevant memories`) + chalk.dim(' (137ms)\n\n') +
494
+ results.map((r, i) => {
495
+ const marker = i === 0 ? '▶' : ' ';
496
+ return `${marker} ${chalk.green(r.score + '%')} │ ${chalk.bold(r.title)}\n` +
497
+ ` │ ${chalk.dim(r.age + ' • ' + r.type + ' • ' + r.tags)}\n` +
498
+ ` │ ${chalk.dim('"...complete integration guide for Stripe payment..."')}`;
499
+ }).join('\n\n'), {
500
+ padding: 1,
501
+ borderStyle: 'single',
502
+ borderColor: 'cyan',
503
+ title: 'Search Results',
504
+ titleAlignment: 'left'
505
+ }));
506
+ }
507
+ async simulateDelay(ms) {
508
+ return new Promise(resolve => setTimeout(resolve, ms));
509
+ }
510
+ }
511
+ /**
512
+ * Analytics View
513
+ */
514
+ export class AnalyticsView {
515
+ stateManager;
516
+ constructor(stateManager) {
517
+ this.stateManager = stateManager;
518
+ }
519
+ async show() {
520
+ console.clear();
521
+ console.log(chalk.bold.blue('📊 Analytics Dashboard\n'));
522
+ // Create analytics table
523
+ const table = new Table({
524
+ head: ['Metric', 'Value', 'Change'],
525
+ colWidths: [25, 15, 15],
526
+ style: {
527
+ head: ['cyan'],
528
+ border: ['gray']
529
+ }
530
+ });
531
+ table.push(['Total Memories', '247', chalk.green('+12')], ['Topics', '12', chalk.green('+2')], ['Tags Used', '89', chalk.green('+8')], ['API Calls (Month)', '1,432', chalk.yellow('+5%')], ['Search Queries', '342', chalk.green('+18%')], ['Avg Response Time', '124ms', chalk.green('-8%')]);
532
+ console.log(table.toString());
533
+ // Memory growth chart
534
+ console.log('\n' + chalk.bold('Memory Growth (Last 7 Days)'));
535
+ this.renderChart();
536
+ // Top topics
537
+ console.log('\n' + chalk.bold('Top Topics'));
538
+ const topics = [
539
+ { name: 'Architecture', count: 45 },
540
+ { name: 'API', count: 38 },
541
+ { name: 'Documentation', count: 32 },
542
+ { name: 'Meetings', count: 28 },
543
+ { name: 'Projects', count: 24 }
544
+ ];
545
+ topics.forEach(topic => {
546
+ const bar = '█'.repeat(Math.floor(topic.count / 2));
547
+ console.log(` ${topic.name.padEnd(15)} ${chalk.cyan(bar)} ${topic.count}`);
548
+ });
549
+ }
550
+ renderChart() {
551
+ const data = [35, 38, 42, 39, 45, 48, 52];
552
+ const max = Math.max(...data);
553
+ const height = 5;
554
+ for (let row = height; row > 0; row--) {
555
+ let line = ' ';
556
+ for (const value of data) {
557
+ const barHeight = Math.round((value / max) * height);
558
+ if (barHeight >= row) {
559
+ line += chalk.cyan('█ ');
560
+ }
561
+ else {
562
+ line += ' ';
563
+ }
564
+ }
565
+ console.log(line);
566
+ }
567
+ console.log(' ' + chalk.dim('M T W T F S S'));
568
+ }
569
+ }
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Enhanced Error Handling and Recovery System
3
+ * Provides intelligent error messages and recovery suggestions
4
+ */
5
+ import { StateManager } from './architecture.js';
6
+ export interface CLIError extends Error {
7
+ code?: string;
8
+ severity?: 'error' | 'warning' | 'info';
9
+ suggestion?: string;
10
+ recoveryActions?: RecoveryAction[];
11
+ context?: Record<string, any>;
12
+ }
13
+ export interface RecoveryAction {
14
+ label: string;
15
+ command: string;
16
+ description?: string;
17
+ }
18
+ export declare class ErrorHandler {
19
+ private stateManager;
20
+ private errorHistory;
21
+ constructor(stateManager: StateManager);
22
+ /**
23
+ * Main error handling method
24
+ */
25
+ handle(error: CLIError | Error | unknown): void;
26
+ /**
27
+ * Normalize various error types into CLIError
28
+ */
29
+ private normalizeError;
30
+ /**
31
+ * Create specific error types with recovery suggestions
32
+ */
33
+ private createConnectionError;
34
+ private createAuthError;
35
+ private createNetworkError;
36
+ private createTimeoutError;
37
+ private createRateLimitError;
38
+ /**
39
+ * Display error in user-friendly format
40
+ */
41
+ private displayError;
42
+ /**
43
+ * Offer recovery actions to the user
44
+ */
45
+ private offerRecovery;
46
+ /**
47
+ * Log debug information for verbose mode
48
+ */
49
+ private logDebugInfo;
50
+ /**
51
+ * Get error icon based on severity
52
+ */
53
+ private getErrorIcon;
54
+ /**
55
+ * Get error color based on severity
56
+ */
57
+ private getErrorColor;
58
+ /**
59
+ * Get error history for debugging
60
+ */
61
+ getErrorHistory(): CLIError[];
62
+ /**
63
+ * Clear error history
64
+ */
65
+ clearHistory(): void;
66
+ /**
67
+ * Retry last failed operation
68
+ */
69
+ retryLastOperation(): Promise<void>;
70
+ }
71
+ /**
72
+ * Global error boundary for the CLI
73
+ */
74
+ export declare class ErrorBoundary {
75
+ private errorHandler;
76
+ constructor(errorHandler: ErrorHandler);
77
+ /**
78
+ * Setup global error handlers
79
+ */
80
+ private setupGlobalHandlers;
81
+ /**
82
+ * Cleanup before exit
83
+ */
84
+ private cleanup;
85
+ /**
86
+ * Wrap async functions with error handling
87
+ */
88
+ wrapAsync<T extends (...args: any[]) => Promise<any>>(fn: T): T;
89
+ }
90
+ /**
91
+ * Validation error for input validation
92
+ */
93
+ export declare class ValidationError extends Error implements CLIError {
94
+ severity: 'error' | 'warning' | 'info';
95
+ suggestion?: string;
96
+ constructor(message: string, field?: string, suggestion?: string);
97
+ }