@lanonasis/cli 1.5.2 → 2.0.1

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,428 @@
1
+ /**
2
+ * Progress Indicators and Feedback System
3
+ * Provides real-time visual feedback for long-running operations
4
+ */
5
+ import ora from 'ora';
6
+ import chalk from 'chalk';
7
+ import cliProgress from 'cli-progress';
8
+ import { performance } from 'perf_hooks';
9
+ export class ProgressIndicator {
10
+ spinner;
11
+ progressBar;
12
+ startTime;
13
+ /**
14
+ * Show a spinner for indeterminate progress
15
+ */
16
+ startSpinner(message, options) {
17
+ this.startTime = performance.now();
18
+ this.spinner = ora({
19
+ text: message,
20
+ spinner: (options?.spinner || 'dots12'),
21
+ color: (options?.color || 'cyan'),
22
+ prefixText: options?.prefix,
23
+ indent: options?.indent || 0
24
+ }).start();
25
+ }
26
+ /**
27
+ * Update spinner text
28
+ */
29
+ updateSpinner(message) {
30
+ if (this.spinner) {
31
+ this.spinner.text = message;
32
+ }
33
+ }
34
+ /**
35
+ * Complete spinner with success
36
+ */
37
+ succeedSpinner(message) {
38
+ if (this.spinner) {
39
+ const elapsed = this.getElapsedTime();
40
+ const finalMessage = message || this.spinner.text;
41
+ this.spinner.succeed(`${finalMessage} ${chalk.dim(`(${elapsed}ms)`)}`);
42
+ this.spinner = undefined;
43
+ }
44
+ }
45
+ /**
46
+ * Complete spinner with failure
47
+ */
48
+ failSpinner(message) {
49
+ if (this.spinner) {
50
+ const elapsed = this.getElapsedTime();
51
+ const finalMessage = message || this.spinner.text;
52
+ this.spinner.fail(`${finalMessage} ${chalk.dim(`(${elapsed}ms)`)}`);
53
+ this.spinner = undefined;
54
+ }
55
+ }
56
+ /**
57
+ * Complete spinner with warning
58
+ */
59
+ warnSpinner(message) {
60
+ if (this.spinner) {
61
+ const elapsed = this.getElapsedTime();
62
+ const finalMessage = message || this.spinner.text;
63
+ this.spinner.warn(`${finalMessage} ${chalk.dim(`(${elapsed}ms)`)}`);
64
+ this.spinner = undefined;
65
+ }
66
+ }
67
+ /**
68
+ * Stop spinner without status
69
+ */
70
+ stopSpinner() {
71
+ if (this.spinner) {
72
+ this.spinner.stop();
73
+ this.spinner = undefined;
74
+ }
75
+ }
76
+ /**
77
+ * Show a progress bar for determinate progress
78
+ */
79
+ startProgressBar(total, options) {
80
+ this.startTime = performance.now();
81
+ const format = options?.format ||
82
+ '{title} |' + chalk.cyan('{bar}') + '| {percentage}% | {value}/{total} | {duration}s | {eta}s remaining';
83
+ this.progressBar = new cliProgress.SingleBar({
84
+ format,
85
+ barCompleteChar: '█',
86
+ barIncompleteChar: '░',
87
+ hideCursor: true,
88
+ clearOnComplete: options?.clearOnComplete || false,
89
+ stopOnComplete: true
90
+ }, cliProgress.Presets.shades_classic);
91
+ this.progressBar.start(total, 0, {
92
+ title: options?.title || 'Progress'
93
+ });
94
+ }
95
+ /**
96
+ * Update progress bar
97
+ */
98
+ updateProgressBar(current, payload) {
99
+ if (this.progressBar) {
100
+ this.progressBar.update(current, payload);
101
+ }
102
+ }
103
+ /**
104
+ * Increment progress bar
105
+ */
106
+ incrementProgressBar(amount = 1) {
107
+ if (this.progressBar) {
108
+ this.progressBar.increment(amount);
109
+ }
110
+ }
111
+ /**
112
+ * Complete progress bar
113
+ */
114
+ stopProgressBar() {
115
+ if (this.progressBar) {
116
+ this.progressBar.stop();
117
+ this.progressBar = undefined;
118
+ }
119
+ }
120
+ /**
121
+ * Execute operation with spinner
122
+ */
123
+ async withSpinner(operation, message, options) {
124
+ this.startSpinner(message, options);
125
+ try {
126
+ const result = await operation();
127
+ this.succeedSpinner();
128
+ return result;
129
+ }
130
+ catch (error) {
131
+ this.failSpinner();
132
+ throw error;
133
+ }
134
+ }
135
+ /**
136
+ * Execute operation with progress tracking
137
+ */
138
+ async withProgress(operation, total, options) {
139
+ this.startProgressBar(total, options);
140
+ const tracker = {
141
+ update: (current, payload) => {
142
+ this.updateProgressBar(current, payload);
143
+ },
144
+ increment: (amount) => {
145
+ this.incrementProgressBar(amount);
146
+ }
147
+ };
148
+ try {
149
+ const result = await operation(tracker);
150
+ this.stopProgressBar();
151
+ return result;
152
+ }
153
+ catch (error) {
154
+ this.stopProgressBar();
155
+ throw error;
156
+ }
157
+ }
158
+ /**
159
+ * Get elapsed time since start
160
+ */
161
+ getElapsedTime() {
162
+ if (!this.startTime)
163
+ return '0';
164
+ const elapsed = Math.round(performance.now() - this.startTime);
165
+ return elapsed.toString();
166
+ }
167
+ }
168
+ /**
169
+ * Multi-step progress indicator
170
+ */
171
+ export class MultiStepProgress {
172
+ steps;
173
+ currentStep = 0;
174
+ progressIndicator;
175
+ constructor(steps) {
176
+ this.steps = steps;
177
+ this.progressIndicator = new ProgressIndicator();
178
+ }
179
+ /**
180
+ * Start the multi-step process
181
+ */
182
+ start() {
183
+ this.render();
184
+ }
185
+ /**
186
+ * Complete current step and move to next
187
+ */
188
+ nextStep(success = true) {
189
+ if (this.currentStep < this.steps.length) {
190
+ this.steps[this.currentStep].status = success ? 'completed' : 'failed';
191
+ this.currentStep++;
192
+ this.render();
193
+ }
194
+ }
195
+ /**
196
+ * Complete all steps
197
+ */
198
+ complete() {
199
+ for (let i = this.currentStep; i < this.steps.length; i++) {
200
+ this.steps[i].status = 'completed';
201
+ }
202
+ this.currentStep = this.steps.length;
203
+ this.render();
204
+ }
205
+ /**
206
+ * Render the multi-step progress
207
+ */
208
+ render() {
209
+ console.clear();
210
+ const progressBar = this.renderProgressBar();
211
+ const stepList = this.renderStepList();
212
+ console.log(chalk.bold('Progress\n'));
213
+ console.log(progressBar);
214
+ console.log();
215
+ console.log(stepList);
216
+ if (this.currentStep < this.steps.length) {
217
+ console.log();
218
+ console.log(chalk.cyan(`→ ${this.steps[this.currentStep].name}...`));
219
+ }
220
+ }
221
+ /**
222
+ * Render progress bar
223
+ */
224
+ renderProgressBar() {
225
+ const completed = this.steps.filter(s => s.status === 'completed').length;
226
+ const total = this.steps.length;
227
+ const percentage = Math.round((completed / total) * 100);
228
+ const barLength = 40;
229
+ const filled = Math.round((completed / total) * barLength);
230
+ const bar = '█'.repeat(filled) + '░'.repeat(barLength - filled);
231
+ return `[${chalk.cyan(bar)}] ${percentage}%`;
232
+ }
233
+ /**
234
+ * Render step list
235
+ */
236
+ renderStepList() {
237
+ return this.steps.map((step, index) => {
238
+ let icon;
239
+ let color;
240
+ switch (step.status) {
241
+ case 'completed':
242
+ icon = chalk.green('✓');
243
+ color = chalk.green;
244
+ break;
245
+ case 'failed':
246
+ icon = chalk.red('✗');
247
+ color = chalk.red;
248
+ break;
249
+ case 'pending':
250
+ icon = chalk.gray('○');
251
+ color = chalk.gray;
252
+ break;
253
+ case 'active':
254
+ icon = chalk.blue('●');
255
+ color = chalk.blue;
256
+ break;
257
+ default:
258
+ icon = chalk.gray('○');
259
+ color = chalk.gray;
260
+ }
261
+ const stepNumber = `[${index + 1}]`;
262
+ const name = color(step.name);
263
+ const description = step.description ? chalk.dim(` - ${step.description}`) : '';
264
+ return `${icon} ${stepNumber} ${name}${description}`;
265
+ }).join('\n');
266
+ }
267
+ }
268
+ /**
269
+ * Smart suggestions system
270
+ */
271
+ export class SmartSuggestions {
272
+ userContext;
273
+ commandHistory = [];
274
+ constructor(userContext) {
275
+ this.userContext = userContext;
276
+ }
277
+ /**
278
+ * Get suggestions based on current context
279
+ */
280
+ getSuggestions(input) {
281
+ const suggestions = [];
282
+ // Command completion suggestions
283
+ if (input.startsWith('onasis ')) {
284
+ suggestions.push(...this.getCommandSuggestions(input));
285
+ }
286
+ // Natural language interpretation
287
+ if (!input.startsWith('onasis')) {
288
+ suggestions.push(...this.getNaturalLanguageSuggestions(input));
289
+ }
290
+ // Historical suggestions
291
+ suggestions.push(...this.getHistoricalSuggestions(input));
292
+ // Context-based suggestions
293
+ suggestions.push(...this.getContextualSuggestions());
294
+ return this.rankSuggestions(suggestions).slice(0, 5);
295
+ }
296
+ /**
297
+ * Get command-based suggestions
298
+ */
299
+ getCommandSuggestions(input) {
300
+ const commands = [
301
+ { command: 'memory create', description: 'Create a new memory' },
302
+ { command: 'memory search', description: 'Search memories' },
303
+ { command: 'memory list', description: 'List all memories' },
304
+ { command: 'topic create', description: 'Create a new topic' },
305
+ { command: 'api-keys create', description: 'Create API key' },
306
+ { command: 'auth login', description: 'Authenticate' },
307
+ { command: 'config set', description: 'Update configuration' }
308
+ ];
309
+ const partial = input.replace('onasis ', '').toLowerCase();
310
+ return commands
311
+ .filter(cmd => cmd.command.startsWith(partial))
312
+ .map(cmd => ({
313
+ text: `onasis ${cmd.command}`,
314
+ description: cmd.description,
315
+ type: 'command',
316
+ score: 0.8
317
+ }));
318
+ }
319
+ /**
320
+ * Get natural language suggestions
321
+ */
322
+ getNaturalLanguageSuggestions(input) {
323
+ const suggestions = [];
324
+ const lower = input.toLowerCase();
325
+ if (lower.includes('remember') || lower.includes('save')) {
326
+ suggestions.push({
327
+ text: 'onasis memory create',
328
+ description: 'Create a new memory from your input',
329
+ type: 'natural',
330
+ score: 0.9
331
+ });
332
+ }
333
+ if (lower.includes('find') || lower.includes('search')) {
334
+ suggestions.push({
335
+ text: `onasis memory search "${input.replace(/find|search/gi, '').trim()}"`,
336
+ description: 'Search for memories',
337
+ type: 'natural',
338
+ score: 0.9
339
+ });
340
+ }
341
+ if (lower.includes('help') || lower.includes('how')) {
342
+ suggestions.push({
343
+ text: 'onasis help',
344
+ description: 'Show help and documentation',
345
+ type: 'natural',
346
+ score: 0.85
347
+ });
348
+ }
349
+ return suggestions;
350
+ }
351
+ /**
352
+ * Get historical suggestions
353
+ */
354
+ getHistoricalSuggestions(input) {
355
+ return this.commandHistory
356
+ .filter(cmd => cmd.startsWith(input))
357
+ .map(cmd => ({
358
+ text: cmd,
359
+ description: 'Previously used command',
360
+ type: 'history',
361
+ score: 0.7
362
+ }));
363
+ }
364
+ /**
365
+ * Get contextual suggestions
366
+ */
367
+ getContextualSuggestions() {
368
+ const suggestions = [];
369
+ const now = new Date();
370
+ const hour = now.getHours();
371
+ // Time-based suggestions
372
+ if (hour >= 9 && hour <= 11) {
373
+ suggestions.push({
374
+ text: 'onasis memory create --type meeting',
375
+ description: 'Create morning meeting notes',
376
+ type: 'contextual',
377
+ score: 0.6
378
+ });
379
+ }
380
+ else if (hour >= 16 && hour <= 18) {
381
+ suggestions.push({
382
+ text: 'onasis memory list --today',
383
+ description: "Review today's memories",
384
+ type: 'contextual',
385
+ score: 0.6
386
+ });
387
+ }
388
+ // User behavior suggestions
389
+ if (!this.userContext.hasCreatedMemoryToday) {
390
+ suggestions.push({
391
+ text: 'onasis memory create',
392
+ description: "You haven't created a memory today",
393
+ type: 'contextual',
394
+ score: 0.75
395
+ });
396
+ }
397
+ return suggestions;
398
+ }
399
+ /**
400
+ * Rank suggestions by relevance
401
+ */
402
+ rankSuggestions(suggestions) {
403
+ return suggestions.sort((a, b) => b.score - a.score);
404
+ }
405
+ /**
406
+ * Add command to history
407
+ */
408
+ addToHistory(command) {
409
+ this.commandHistory.unshift(command);
410
+ if (this.commandHistory.length > 100) {
411
+ this.commandHistory.pop();
412
+ }
413
+ }
414
+ /**
415
+ * Display suggestions
416
+ */
417
+ displaySuggestions(suggestions) {
418
+ if (suggestions.length === 0)
419
+ return;
420
+ console.log(chalk.dim('\n💡 Suggestions:'));
421
+ suggestions.forEach((suggestion, index) => {
422
+ const number = chalk.cyan(`${index + 1}.`);
423
+ const text = chalk.bold(suggestion.text);
424
+ const desc = chalk.dim(suggestion.description);
425
+ console.log(` ${number} ${text} - ${desc}`);
426
+ });
427
+ }
428
+ }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Welcome and Onboarding Experience
3
+ * Provides first-time user experience and guided setup
4
+ */
5
+ import { StateManager } from './architecture.js';
6
+ export declare class WelcomeExperience {
7
+ private stateManager;
8
+ private isFirstRun;
9
+ constructor(stateManager: StateManager);
10
+ show(): Promise<void>;
11
+ private displayWelcomeBanner;
12
+ private showMainMenu;
13
+ private handleMenuChoice;
14
+ private startInteractiveSetup;
15
+ private goToDashboard;
16
+ private showDocumentation;
17
+ private showAbout;
18
+ private showSettings;
19
+ private showHelp;
20
+ private checkAuthentication;
21
+ }
22
+ /**
23
+ * Interactive Setup Flow
24
+ */
25
+ export declare class InteractiveSetup {
26
+ private stateManager;
27
+ private setupProgress;
28
+ constructor(stateManager: StateManager);
29
+ run(): Promise<void>;
30
+ private showProgressHeader;
31
+ private renderProgressBar;
32
+ private setupConnection;
33
+ private setupAuthentication;
34
+ private authenticateWithVendorKey;
35
+ private authenticateWithBrowser;
36
+ private authenticateWithEmail;
37
+ private setupConfiguration;
38
+ private showSetupComplete;
39
+ private simulateDelay;
40
+ }