@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.
- package/README.md +12 -3
- package/dist/core/achievements.d.ts +102 -0
- package/dist/core/achievements.js +425 -0
- package/dist/core/architecture.d.ts +145 -0
- package/dist/core/architecture.js +355 -0
- package/dist/core/dashboard.d.ts +71 -0
- package/dist/core/dashboard.js +569 -0
- package/dist/core/error-handler.d.ts +97 -0
- package/dist/core/error-handler.js +380 -0
- package/dist/core/power-mode.d.ts +118 -0
- package/dist/core/power-mode.js +460 -0
- package/dist/core/progress.d.ts +160 -0
- package/dist/core/progress.js +428 -0
- package/dist/core/welcome.d.ts +40 -0
- package/dist/core/welcome.js +466 -0
- package/dist/enhanced-cli.d.ts +15 -0
- package/dist/enhanced-cli.js +296 -0
- package/dist/index-simple.js +2 -2
- package/dist/utils/mcp-client.js +1 -1
- package/package.json +6 -4
|
@@ -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
|
+
}
|