@lanonasis/cli 1.5.1 → 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,296 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Enhanced CLI Entry Point
4
+ * Integrates all the enhanced experience components
5
+ */
6
+ import { Command } from 'commander';
7
+ import chalk from 'chalk';
8
+ import { config } from 'dotenv';
9
+ import { createCLIArchitecture } from './core/architecture.js';
10
+ import { WelcomeExperience } from './core/welcome.js';
11
+ import { DashboardCommandCenter } from './core/dashboard.js';
12
+ import { ErrorHandler, ErrorBoundary } from './core/error-handler.js';
13
+ import { PowerUserMode } from './core/power-mode.js';
14
+ import { AchievementSystem } from './core/achievements.js';
15
+ import { ProgressIndicator } from './core/progress.js';
16
+ import { CLIConfig } from './utils/config.js';
17
+ // Load environment variables
18
+ config();
19
+ // Initialize the enhanced architecture
20
+ const architecture = createCLIArchitecture();
21
+ const { stateManager, interactionEngine, presentationLayer } = architecture;
22
+ // Initialize systems
23
+ const errorHandler = new ErrorHandler(stateManager);
24
+ const errorBoundary = new ErrorBoundary(errorHandler);
25
+ const achievementSystem = new AchievementSystem(stateManager);
26
+ const progressIndicator = new ProgressIndicator();
27
+ const cliConfig = new CLIConfig();
28
+ // Create the main program
29
+ const program = new Command();
30
+ program
31
+ .name('onasis')
32
+ .description(chalk.cyan('🧠 Onasis Memory Service - Enhanced CLI Experience'))
33
+ .version('2.0.0', '-v, --version', 'display version number')
34
+ .option('-V, --verbose', 'enable verbose logging')
35
+ .option('--api-url <url>', 'override API URL')
36
+ .option('--output <format>', 'output format (json, table, yaml, minimal)', 'table')
37
+ .option('--no-animations', 'disable animations')
38
+ .option('--expert', 'start in expert/power mode')
39
+ .option('--offline', 'work offline with cached data');
40
+ // Enhanced init command with interactive setup
41
+ program
42
+ .command('init')
43
+ .description('Initialize and configure Onasis CLI')
44
+ .action(errorBoundary.wrapAsync(async () => {
45
+ const welcome = new WelcomeExperience(stateManager);
46
+ await welcome.show();
47
+ }));
48
+ // Interactive dashboard command
49
+ program
50
+ .command('dashboard')
51
+ .alias('home')
52
+ .description('Open the interactive command center')
53
+ .action(errorBoundary.wrapAsync(async () => {
54
+ const dashboard = new DashboardCommandCenter(stateManager);
55
+ await dashboard.show();
56
+ }));
57
+ // Power mode for expert users
58
+ program
59
+ .command('power')
60
+ .alias('expert')
61
+ .description('Enter power user mode for streamlined operations')
62
+ .action(errorBoundary.wrapAsync(async () => {
63
+ const powerMode = new PowerUserMode(stateManager);
64
+ await powerMode.enter();
65
+ }));
66
+ // Enhanced memory commands with progress and feedback
67
+ program
68
+ .command('memory')
69
+ .alias('m')
70
+ .description('Memory operations')
71
+ .argument('[action]', 'action to perform (create, search, list, update, delete)')
72
+ .option('-t, --title <title>', 'memory title')
73
+ .option('-c, --content <content>', 'memory content')
74
+ .option('--tags <tags>', 'comma-separated tags')
75
+ .option('--type <type>', 'memory type (context, knowledge, reference, project)')
76
+ .option('--topic <topic>', 'topic to categorize under')
77
+ .option('-q, --query <query>', 'search query')
78
+ .option('--limit <n>', 'limit results')
79
+ .option('--interactive', 'use interactive mode')
80
+ .action(errorBoundary.wrapAsync(async (action, options) => {
81
+ const { InteractiveMemoryCreator, InteractiveSearch } = await import('./core/dashboard.js');
82
+ // Update stats for achievements
83
+ achievementSystem.updateStats({
84
+ totalMemories: achievementSystem.userStats.totalMemories + 1
85
+ });
86
+ switch (action) {
87
+ case 'create':
88
+ if (options.interactive || (!options.title && !options.content)) {
89
+ const creator = new InteractiveMemoryCreator(stateManager);
90
+ await creator.create();
91
+ }
92
+ else {
93
+ await progressIndicator.withSpinner(async () => {
94
+ // Create memory logic here
95
+ console.log(chalk.green('✓ Memory created successfully'));
96
+ }, 'Creating memory...');
97
+ }
98
+ break;
99
+ case 'search':
100
+ const search = new InteractiveSearch(stateManager);
101
+ await search.search(options.query || '');
102
+ achievementSystem.updateStats({
103
+ totalSearches: achievementSystem.userStats.totalSearches + 1
104
+ });
105
+ break;
106
+ case 'list':
107
+ await progressIndicator.withSpinner(async () => {
108
+ // List memories logic
109
+ console.log(chalk.cyan('Memories listed'));
110
+ }, 'Loading memories...');
111
+ break;
112
+ default:
113
+ // If no action specified, go to interactive mode
114
+ const dashboard = new DashboardCommandCenter(stateManager);
115
+ await dashboard.show();
116
+ }
117
+ }));
118
+ // Topic management with visual feedback
119
+ program
120
+ .command('topic')
121
+ .alias('t')
122
+ .description('Manage topics')
123
+ .argument('[action]', 'action to perform (create, list, delete)')
124
+ .argument('[name]', 'topic name')
125
+ .action(errorBoundary.wrapAsync(async (action, name) => {
126
+ switch (action) {
127
+ case 'create':
128
+ if (!name) {
129
+ const { default: inquirer } = await import('inquirer');
130
+ const { topicName } = await inquirer.prompt([
131
+ {
132
+ type: 'input',
133
+ name: 'topicName',
134
+ message: 'Topic name:',
135
+ validate: (input) => input.length > 0 || 'Topic name is required'
136
+ }
137
+ ]);
138
+ name = topicName;
139
+ }
140
+ console.log(chalk.green(`✓ Topic "${name}" created`));
141
+ break;
142
+ case 'list':
143
+ console.log(chalk.bold('📁 Topics:'));
144
+ console.log(' • Architecture');
145
+ console.log(' • API Documentation');
146
+ console.log(' • Meeting Notes');
147
+ break;
148
+ case 'delete':
149
+ console.log(chalk.red(`✓ Topic "${name}" deleted`));
150
+ break;
151
+ default:
152
+ console.log(chalk.yellow('Usage: onasis topic [create|list|delete] [name]'));
153
+ }
154
+ }));
155
+ // Achievement system
156
+ program
157
+ .command('achievements')
158
+ .alias('badges')
159
+ .description('View your achievements and progress')
160
+ .action(() => {
161
+ achievementSystem.showAchievements();
162
+ });
163
+ // Stats and analytics
164
+ program
165
+ .command('stats')
166
+ .alias('analytics')
167
+ .description('View usage statistics and analytics')
168
+ .action(errorBoundary.wrapAsync(async () => {
169
+ const { AnalyticsView } = await import('./core/dashboard.js');
170
+ const analytics = new AnalyticsView(stateManager);
171
+ await analytics.show();
172
+ }));
173
+ // Settings management
174
+ program
175
+ .command('settings')
176
+ .alias('config')
177
+ .description('Manage CLI settings and preferences')
178
+ .argument('[key]', 'setting key')
179
+ .argument('[value]', 'setting value')
180
+ .action(errorBoundary.wrapAsync(async (key, value) => {
181
+ if (!key) {
182
+ // Show all settings
183
+ const prefs = stateManager.getPreferences();
184
+ console.log(chalk.bold('⚙️ Settings:\n'));
185
+ Object.entries(prefs).forEach(([k, v]) => {
186
+ console.log(` ${chalk.cyan(k)}: ${v}`);
187
+ });
188
+ }
189
+ else if (value !== undefined) {
190
+ // Set a value
191
+ stateManager.updatePreference(key, value);
192
+ console.log(chalk.green(`✓ ${key} set to ${value}`));
193
+ }
194
+ else {
195
+ // Get a value
196
+ const prefs = stateManager.getPreferences();
197
+ console.log(`${key}: ${prefs[key]}`);
198
+ }
199
+ }));
200
+ // Help command with enhanced formatting
201
+ program
202
+ .command('help [command]')
203
+ .description('Show help for a specific command')
204
+ .action((command) => {
205
+ if (command) {
206
+ const cmd = program.commands.find(c => c.name() === command);
207
+ if (cmd) {
208
+ cmd.outputHelp();
209
+ }
210
+ else {
211
+ console.log(chalk.red(`Command "${command}" not found`));
212
+ }
213
+ }
214
+ else {
215
+ console.log(chalk.bold.cyan('\n🧠 Onasis Memory Service - Enhanced CLI\n'));
216
+ console.log('Available commands:\n');
217
+ program.commands.forEach(cmd => {
218
+ const name = cmd.name().padEnd(15);
219
+ const desc = cmd.description();
220
+ console.log(` ${chalk.cyan(name)} ${desc}`);
221
+ });
222
+ console.log('\nFor detailed help: onasis help [command]');
223
+ console.log('Interactive mode: onasis (no arguments)');
224
+ console.log('Power mode: onasis power');
225
+ }
226
+ });
227
+ // Status command
228
+ program
229
+ .command('status')
230
+ .description('Check service status and connectivity')
231
+ .action(errorBoundary.wrapAsync(async () => {
232
+ const spinner = progressIndicator;
233
+ await spinner.withSpinner(async () => {
234
+ // Check API connection
235
+ await new Promise(resolve => setTimeout(resolve, 1000));
236
+ }, 'Checking service status...');
237
+ console.log(chalk.green('✓ Service: Online'));
238
+ console.log(chalk.green('✓ API: Connected'));
239
+ console.log(chalk.green('✓ Auth: Valid'));
240
+ console.log(chalk.cyan(' Endpoint: api.lanonasis.com'));
241
+ console.log(chalk.cyan(' Version: 2.0.0'));
242
+ }));
243
+ // Default action - show interactive dashboard if no command
244
+ if (process.argv.length === 2) {
245
+ (async () => {
246
+ try {
247
+ // Check if first run
248
+ const isFirstRun = !(await cliConfig.isAuthenticated());
249
+ if (isFirstRun) {
250
+ const welcome = new WelcomeExperience(stateManager);
251
+ await welcome.show();
252
+ }
253
+ else {
254
+ const dashboard = new DashboardCommandCenter(stateManager);
255
+ await dashboard.show();
256
+ }
257
+ }
258
+ catch (error) {
259
+ errorHandler.handle(error);
260
+ process.exit(1);
261
+ }
262
+ })();
263
+ }
264
+ else {
265
+ // Parse command line arguments
266
+ program.parse(process.argv);
267
+ }
268
+ // Handle global options
269
+ const options = program.opts();
270
+ if (options.verbose) {
271
+ process.env.CLI_VERBOSE = 'true';
272
+ console.log(chalk.dim('Verbose mode enabled'));
273
+ }
274
+ if (options.apiUrl) {
275
+ process.env.MEMORY_API_URL = options.apiUrl;
276
+ console.log(chalk.dim(`API URL set to: ${options.apiUrl}`));
277
+ }
278
+ if (options.output) {
279
+ stateManager.updatePreference('outputFormat', options.output);
280
+ }
281
+ if (options.noAnimations) {
282
+ stateManager.updatePreference('animations', false);
283
+ }
284
+ if (options.expert) {
285
+ // Start directly in power mode
286
+ (async () => {
287
+ const powerMode = new PowerUserMode(stateManager);
288
+ await powerMode.enter();
289
+ })();
290
+ }
291
+ if (options.offline) {
292
+ process.env.CLI_OFFLINE = 'true';
293
+ console.log(chalk.yellow('⚠ Running in offline mode'));
294
+ }
295
+ // Export for testing and extension
296
+ export { architecture, stateManager, errorHandler, achievementSystem, progressIndicator };
@@ -10,8 +10,15 @@ import { configCommands } from './commands/config.js';
10
10
  import { orgCommands } from './commands/organization.js';
11
11
  import { mcpCommands } from './commands/mcp.js';
12
12
  import apiKeysCommand from './commands/api-keys.js';
13
+ import { completionCommand, installCompletionsCommand } from './commands/completion.js';
14
+ import { guideCommand, quickStartCommand } from './commands/guide.js';
13
15
  import { CLIConfig } from './utils/config.js';
14
16
  import { getMCPClient } from './utils/mcp-client.js';
17
+ import * as fs from 'fs';
18
+ import * as path from 'path';
19
+ import { fileURLToPath } from 'url';
20
+ const __filename = fileURLToPath(import.meta.url);
21
+ const __dirname = path.dirname(__filename);
15
22
  // Load environment variables
16
23
  config();
17
24
  // Enhanced color scheme (VPS-style)
@@ -28,16 +35,21 @@ const colors = {
28
35
  const program = new Command();
29
36
  // CLI Configuration
30
37
  const cliConfig = new CLIConfig();
38
+ // Detect which command was used to invoke the CLI
39
+ const invocationName = process.argv[1] ? path.basename(process.argv[1]) : 'lanonasis';
40
+ const isOnasisInvocation = invocationName === 'onasis';
31
41
  program
32
- .name('lanonasis')
33
- .alias('memory')
34
- .alias('maas')
35
- .description(colors.info('🧠 LanOnasis Enterprise CLI - Memory as a Service, API Management & Infrastructure Orchestration'))
36
- .version('1.4.2', '-v, --version', 'display version number')
42
+ .name(isOnasisInvocation ? 'onasis' : 'lanonasis')
43
+ .alias(isOnasisInvocation ? 'lanonasis' : 'memory')
44
+ .alias(isOnasisInvocation ? 'memory' : 'maas')
45
+ .description(colors.info(`🧠 ${isOnasisInvocation ? 'Onasis-Core Golden Contract CLI' : 'LanOnasis Enterprise CLI'} - Memory as a Service, API Management & Infrastructure Orchestration`))
46
+ .version('2.0.0', '-v, --version', 'display version number')
37
47
  .option('-V, --verbose', 'enable verbose logging')
38
48
  .option('--api-url <url>', 'override API URL')
39
49
  .option('--output <format>', 'output format (json, table, yaml)', 'table')
40
50
  .option('--no-mcp', 'disable MCP and use direct API')
51
+ .option('--completion [shell]', 'generate shell completion script')
52
+ .option('--completion-data', 'output completion data as JSON')
41
53
  .hook('preAction', async (thisCommand, actionCommand) => {
42
54
  const opts = thisCommand.opts();
43
55
  if (opts.verbose) {
@@ -84,16 +96,31 @@ process.on('unhandledRejection', (reason, promise) => {
84
96
  });
85
97
  // Enhanced welcome message
86
98
  const showWelcome = () => {
99
+ const cmdName = isOnasisInvocation ? 'onasis' : 'lanonasis';
100
+ const title = isOnasisInvocation ? 'Onasis-Core Golden Contract CLI' : 'LanOnasis Enterprise CLI';
87
101
  console.log();
88
- console.log(colors.primary('🚀 LanOnasis Enterprise CLI v1.4.2'));
102
+ console.log(colors.primary(`🚀 ${title} v2.0.0`));
89
103
  console.log(colors.info('━'.repeat(50)));
90
104
  console.log(colors.highlight('Enterprise-grade Memory as a Service, API Management & Infrastructure Orchestration'));
105
+ if (isOnasisInvocation) {
106
+ console.log(colors.accent('✓ Golden Contract Compliant - Service Discovery Enabled'));
107
+ }
91
108
  console.log();
92
109
  console.log(colors.warning('🏁 Quick Start:'));
93
- console.log(` ${colors.success('lanonasis init')} ${colors.muted('# Initialize CLI configuration')}`);
94
- console.log(` ${colors.success('lanonasis login')} ${colors.muted('# Authenticate with your account')}`);
95
- console.log(` ${colors.success('lanonasis health')} ${colors.muted('# Check system health')}`);
96
- console.log(` ${colors.success('lanonasis --help')} ${colors.muted('# Show all available commands')}`);
110
+ console.log(` ${colors.success(`${cmdName} init`)} ${colors.muted('# Initialize CLI configuration')}`);
111
+ console.log(` ${colors.success(`${cmdName} login`)} ${colors.muted('# Authenticate with your account')}`);
112
+ console.log(` ${colors.success(`${cmdName} health`)} ${colors.muted('# Check system health')}`);
113
+ console.log(` ${colors.success(`${cmdName} --help`)} ${colors.muted('# Show all available commands')}`);
114
+ console.log();
115
+ if (isOnasisInvocation) {
116
+ console.log(colors.info('🔑 Golden Contract Authentication:'));
117
+ console.log(` ${colors.success(`${cmdName} login --vendor-key pk_xxx.sk_xxx`)} ${colors.muted('# Vendor key auth')}`);
118
+ console.log(` ${colors.success(`${cmdName} login --oauth`)} ${colors.muted('# Browser OAuth')}`);
119
+ console.log();
120
+ }
121
+ console.log(colors.info('🔧 Shell Completions:'));
122
+ console.log(` ${colors.success(`${cmdName} completion`)} ${colors.muted('# Installation guide')}`);
123
+ console.log(` ${colors.success(`source <(${cmdName} --completion bash)`)} ${colors.muted('# Bash completions')}`);
97
124
  console.log();
98
125
  console.log(colors.info('📚 Documentation: https://docs.lanonasis.com/memory-services'));
99
126
  console.log(colors.info('🌐 Dashboard: https://api.lanonasis.com/dashboard'));
@@ -190,6 +217,8 @@ authCmd
190
217
  .description('Login to your MaaS account')
191
218
  .option('-e, --email <email>', 'email address')
192
219
  .option('-p, --password <password>', 'password')
220
+ .option('--vendor-key <key>', 'vendor key (pk_xxx.sk_xxx format)')
221
+ .option('--oauth', 'use OAuth browser flow')
193
222
  .action(loginCommand);
194
223
  authCmd
195
224
  .command('logout')
@@ -493,6 +522,53 @@ program
493
522
  console.log(chalk.white(`Please visit: ${url}`));
494
523
  });
495
524
  });
525
+ // Completion commands
526
+ program
527
+ .command('completion')
528
+ .description('Generate shell completion scripts')
529
+ .argument('[shell]', 'shell type (bash, zsh, fish)')
530
+ .action(async (shell) => {
531
+ if (!shell) {
532
+ await installCompletionsCommand();
533
+ return;
534
+ }
535
+ const completionsDir = path.join(__dirname, 'completions');
536
+ let scriptPath;
537
+ switch (shell.toLowerCase()) {
538
+ case 'bash':
539
+ scriptPath = path.join(completionsDir, 'bash-completion.sh');
540
+ break;
541
+ case 'zsh':
542
+ scriptPath = path.join(completionsDir, 'zsh-completion.zsh');
543
+ break;
544
+ case 'fish':
545
+ scriptPath = path.join(completionsDir, 'fish-completion.fish');
546
+ break;
547
+ default:
548
+ console.error(colors.error(`Unsupported shell: ${shell}`));
549
+ console.log(colors.info('Supported shells: bash, zsh, fish'));
550
+ process.exit(1);
551
+ }
552
+ try {
553
+ const script = fs.readFileSync(scriptPath, 'utf8');
554
+ console.log(script);
555
+ }
556
+ catch (error) {
557
+ console.error(colors.error('Failed to read completion script:'), error instanceof Error ? error.message : String(error));
558
+ process.exit(1);
559
+ }
560
+ });
561
+ // User guidance commands
562
+ program
563
+ .command('guide')
564
+ .alias('setup')
565
+ .description('Interactive setup guide for new users')
566
+ .action(guideCommand);
567
+ program
568
+ .command('quickstart')
569
+ .alias('quick')
570
+ .description('Show essential commands for quick start')
571
+ .action(quickStartCommand);
496
572
  // Help customization
497
573
  program.configureHelp({
498
574
  formatHelp: (cmd, helper) => {
@@ -520,13 +596,54 @@ program.configureHelp({
520
596
  });
521
597
  help += '\n';
522
598
  }
523
- help += chalk.gray('For more help on a specific command, run: memory <command> --help\n');
599
+ const cmdName = isOnasisInvocation ? 'onasis' : program.name();
600
+ help += chalk.gray(`For more help on a specific command, run: ${cmdName} <command> --help\n`);
524
601
  help += chalk.gray('Documentation: https://api.lanonasis.com/docs\n');
602
+ if (isOnasisInvocation) {
603
+ help += chalk.gray('Golden Contract: Onasis-Core v0.1 Compliant\n');
604
+ }
525
605
  return help;
526
606
  }
527
607
  });
528
608
  // Parse CLI arguments
529
609
  async function main() {
610
+ // Check for special flags first
611
+ if (process.argv.includes('--completion-data')) {
612
+ await completionCommand();
613
+ return;
614
+ }
615
+ if (process.argv.includes('--completion')) {
616
+ const shellIndex = process.argv.indexOf('--completion');
617
+ const shell = process.argv[shellIndex + 1];
618
+ if (shell && !shell.startsWith('-')) {
619
+ // Shell completion script request
620
+ const completionsDir = path.join(__dirname, 'completions');
621
+ let scriptPath;
622
+ switch (shell.toLowerCase()) {
623
+ case 'bash':
624
+ scriptPath = path.join(completionsDir, 'bash-completion.sh');
625
+ break;
626
+ case 'zsh':
627
+ scriptPath = path.join(completionsDir, 'zsh-completion.zsh');
628
+ break;
629
+ case 'fish':
630
+ scriptPath = path.join(completionsDir, 'fish-completion.fish');
631
+ break;
632
+ default:
633
+ console.error(colors.error(`Unsupported shell: ${shell}`));
634
+ process.exit(1);
635
+ }
636
+ try {
637
+ const script = fs.readFileSync(scriptPath, 'utf8');
638
+ console.log(script);
639
+ return;
640
+ }
641
+ catch (error) {
642
+ console.error(colors.error('Failed to read completion script'));
643
+ process.exit(1);
644
+ }
645
+ }
646
+ }
530
647
  // Show welcome message if no arguments provided
531
648
  if (process.argv.length <= 2) {
532
649
  showWelcome();
@@ -1,2 +1,38 @@
1
1
  #!/usr/bin/env node
2
- export {};
2
+ /**
3
+ * CLI-Embedded MCP Server
4
+ * Uses the same configuration and authentication as @lanonasis/cli v1.5.2+
5
+ * Can run standalone or be invoked by CLI commands
6
+ */
7
+ interface MCPServerOptions {
8
+ mode?: 'stdio' | 'http';
9
+ port?: number;
10
+ verbose?: boolean;
11
+ useRemote?: boolean;
12
+ }
13
+ export declare class CLIMCPServer {
14
+ private config;
15
+ constructor();
16
+ /**
17
+ * Start MCP server using CLI configuration
18
+ */
19
+ start(options?: MCPServerOptions): Promise<void>;
20
+ /**
21
+ * Start local MCP server using CLI auth config
22
+ */
23
+ private startLocalMCP;
24
+ /**
25
+ * Connect to remote MCP server
26
+ */
27
+ private startRemoteMCP;
28
+ /**
29
+ * Check if MCP server is available and configured
30
+ */
31
+ checkStatus(): Promise<{
32
+ available: boolean;
33
+ configured: boolean;
34
+ authMethod: string;
35
+ mode: 'local' | 'remote' | 'auto';
36
+ }>;
37
+ }
38
+ export default CLIMCPServer;