@lanonasis/cli 1.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,297 @@
1
+ import chalk from 'chalk';
2
+ import inquirer from 'inquirer';
3
+ import ora from 'ora';
4
+ import { table } from 'table';
5
+ import { format } from 'date-fns';
6
+ import { apiClient } from '../utils/api.js';
7
+ import { truncateText } from '../utils/formatting.js';
8
+ export function topicCommands(program) {
9
+ // Create topic
10
+ program
11
+ .command('create')
12
+ .alias('add')
13
+ .description('Create a new topic')
14
+ .option('-n, --name <name>', 'topic name')
15
+ .option('-d, --description <description>', 'topic description')
16
+ .option('-c, --color <color>', 'topic color (hex format)')
17
+ .option('--icon <icon>', 'topic icon')
18
+ .option('--parent <parentId>', 'parent topic ID')
19
+ .option('-i, --interactive', 'interactive mode')
20
+ .action(async (options) => {
21
+ try {
22
+ let { name, description, color, icon, parent, interactive } = options;
23
+ if (interactive || !name) {
24
+ const answers = await inquirer.prompt([
25
+ {
26
+ type: 'input',
27
+ name: 'name',
28
+ message: 'Topic name:',
29
+ default: name,
30
+ validate: (input) => input.length > 0 || 'Name is required'
31
+ },
32
+ {
33
+ type: 'input',
34
+ name: 'description',
35
+ message: 'Description (optional):',
36
+ default: description || ''
37
+ },
38
+ {
39
+ type: 'input',
40
+ name: 'color',
41
+ message: 'Color (hex format, e.g., #3B82F6):',
42
+ default: color || '#3B82F6',
43
+ validate: (input) => {
44
+ if (!input)
45
+ return true;
46
+ return /^#[0-9A-Fa-f]{6}$/.test(input) || 'Please enter a valid hex color (e.g., #3B82F6)';
47
+ }
48
+ },
49
+ {
50
+ type: 'input',
51
+ name: 'icon',
52
+ message: 'Icon (optional):',
53
+ default: icon || ''
54
+ }
55
+ ]);
56
+ name = answers.name;
57
+ description = answers.description;
58
+ color = answers.color;
59
+ icon = answers.icon;
60
+ }
61
+ const spinner = ora('Creating topic...').start();
62
+ const topicData = { name };
63
+ if (description)
64
+ topicData.description = description;
65
+ if (color)
66
+ topicData.color = color;
67
+ if (icon)
68
+ topicData.icon = icon;
69
+ if (parent)
70
+ topicData.parent_topic_id = parent;
71
+ const topic = await apiClient.createTopic(topicData);
72
+ spinner.succeed('Topic created successfully');
73
+ console.log();
74
+ console.log(chalk.green('āœ“ Topic created:'));
75
+ console.log(` ID: ${chalk.cyan(topic.id)}`);
76
+ console.log(` Name: ${topic.name}`);
77
+ if (topic.description) {
78
+ console.log(` Description: ${topic.description}`);
79
+ }
80
+ if (topic.color) {
81
+ console.log(` Color: ${topic.color}`);
82
+ }
83
+ }
84
+ catch (error) {
85
+ console.error(chalk.red('āœ– Failed to create topic:'), error.message);
86
+ process.exit(1);
87
+ }
88
+ });
89
+ // List topics
90
+ program
91
+ .command('list')
92
+ .alias('ls')
93
+ .description('List topics')
94
+ .action(async () => {
95
+ try {
96
+ const spinner = ora('Fetching topics...').start();
97
+ const topics = await apiClient.getTopics();
98
+ spinner.stop();
99
+ if (topics.length === 0) {
100
+ console.log(chalk.yellow('No topics found'));
101
+ return;
102
+ }
103
+ console.log(chalk.blue.bold(`\nšŸ“ Topics (${topics.length} total)`));
104
+ console.log();
105
+ const outputFormat = process.env.CLI_OUTPUT_FORMAT || 'table';
106
+ if (outputFormat === 'json') {
107
+ console.log(JSON.stringify(topics, null, 2));
108
+ }
109
+ else {
110
+ // Table format
111
+ const tableData = topics.map((topic) => [
112
+ truncateText(topic.name, 25),
113
+ truncateText(topic.description || '', 40),
114
+ topic.color || '',
115
+ format(new Date(topic.created_at), 'MMM dd, yyyy'),
116
+ topic.parent_topic_id ? 'āœ“' : ''
117
+ ]);
118
+ const tableConfig = {
119
+ header: ['Name', 'Description', 'Color', 'Created', 'Child'],
120
+ columnDefault: {
121
+ width: 20,
122
+ wrapWord: true
123
+ },
124
+ columns: [
125
+ { width: 25 },
126
+ { width: 40 },
127
+ { width: 10 },
128
+ { width: 12 },
129
+ { width: 8 }
130
+ ]
131
+ };
132
+ console.log(table([tableConfig.header, ...tableData], tableConfig));
133
+ }
134
+ }
135
+ catch (error) {
136
+ console.error(chalk.red('āœ– Failed to list topics:'), error.message);
137
+ process.exit(1);
138
+ }
139
+ });
140
+ // Get topic details
141
+ program
142
+ .command('get')
143
+ .alias('show')
144
+ .description('Get detailed information about a topic')
145
+ .argument('<id>', 'topic ID')
146
+ .action(async (id) => {
147
+ try {
148
+ const spinner = ora('Fetching topic...').start();
149
+ const topic = await apiClient.getTopic(id);
150
+ spinner.stop();
151
+ console.log(chalk.blue.bold('\nšŸ“ Topic Details'));
152
+ console.log();
153
+ console.log(chalk.green('Name:'), topic.name);
154
+ console.log(chalk.green('ID:'), chalk.cyan(topic.id));
155
+ if (topic.description) {
156
+ console.log(chalk.green('Description:'), topic.description);
157
+ }
158
+ if (topic.color) {
159
+ console.log(chalk.green('Color:'), topic.color);
160
+ }
161
+ if (topic.icon) {
162
+ console.log(chalk.green('Icon:'), topic.icon);
163
+ }
164
+ if (topic.parent_topic_id) {
165
+ console.log(chalk.green('Parent Topic:'), topic.parent_topic_id);
166
+ }
167
+ console.log(chalk.green('System Topic:'), topic.is_system ? 'Yes' : 'No');
168
+ console.log(chalk.green('Created:'), format(new Date(topic.created_at), 'PPpp'));
169
+ console.log(chalk.green('Updated:'), format(new Date(topic.updated_at), 'PPpp'));
170
+ if (topic.metadata && Object.keys(topic.metadata).length > 0) {
171
+ console.log();
172
+ console.log(chalk.green('Metadata:'));
173
+ console.log(JSON.stringify(topic.metadata, null, 2));
174
+ }
175
+ }
176
+ catch (error) {
177
+ console.error(chalk.red('āœ– Failed to get topic:'), error.message);
178
+ process.exit(1);
179
+ }
180
+ });
181
+ // Update topic
182
+ program
183
+ .command('update')
184
+ .description('Update a topic')
185
+ .argument('<id>', 'topic ID')
186
+ .option('-n, --name <name>', 'new name')
187
+ .option('-d, --description <description>', 'new description')
188
+ .option('-c, --color <color>', 'new color (hex format)')
189
+ .option('--icon <icon>', 'new icon')
190
+ .option('-i, --interactive', 'interactive mode')
191
+ .action(async (id, options) => {
192
+ try {
193
+ let updateData = {};
194
+ if (options.interactive) {
195
+ // First, get current topic data
196
+ const spinner = ora('Fetching current topic...').start();
197
+ const currentTopic = await apiClient.getTopic(id);
198
+ spinner.stop();
199
+ const answers = await inquirer.prompt([
200
+ {
201
+ type: 'input',
202
+ name: 'name',
203
+ message: 'Name:',
204
+ default: currentTopic.name
205
+ },
206
+ {
207
+ type: 'input',
208
+ name: 'description',
209
+ message: 'Description:',
210
+ default: currentTopic.description || ''
211
+ },
212
+ {
213
+ type: 'input',
214
+ name: 'color',
215
+ message: 'Color (hex format):',
216
+ default: currentTopic.color || '',
217
+ validate: (input) => {
218
+ if (!input)
219
+ return true;
220
+ return /^#[0-9A-Fa-f]{6}$/.test(input) || 'Please enter a valid hex color';
221
+ }
222
+ },
223
+ {
224
+ type: 'input',
225
+ name: 'icon',
226
+ message: 'Icon:',
227
+ default: currentTopic.icon || ''
228
+ }
229
+ ]);
230
+ updateData = {
231
+ name: answers.name,
232
+ description: answers.description || undefined,
233
+ color: answers.color || undefined,
234
+ icon: answers.icon || undefined
235
+ };
236
+ }
237
+ else {
238
+ if (options.name)
239
+ updateData.name = options.name;
240
+ if (options.description)
241
+ updateData.description = options.description;
242
+ if (options.color)
243
+ updateData.color = options.color;
244
+ if (options.icon)
245
+ updateData.icon = options.icon;
246
+ }
247
+ if (Object.keys(updateData).length === 0) {
248
+ console.log(chalk.yellow('No updates specified'));
249
+ return;
250
+ }
251
+ const spinner = ora('Updating topic...').start();
252
+ const topic = await apiClient.updateTopic(id, updateData);
253
+ spinner.succeed('Topic updated successfully');
254
+ console.log();
255
+ console.log(chalk.green('āœ“ Topic updated:'));
256
+ console.log(` ID: ${chalk.cyan(topic.id)}`);
257
+ console.log(` Name: ${topic.name}`);
258
+ }
259
+ catch (error) {
260
+ console.error(chalk.red('āœ– Failed to update topic:'), error.message);
261
+ process.exit(1);
262
+ }
263
+ });
264
+ // Delete topic
265
+ program
266
+ .command('delete')
267
+ .alias('rm')
268
+ .description('Delete a topic')
269
+ .argument('<id>', 'topic ID')
270
+ .option('-f, --force', 'skip confirmation')
271
+ .action(async (id, options) => {
272
+ try {
273
+ if (!options.force) {
274
+ const topic = await apiClient.getTopic(id);
275
+ const answer = await inquirer.prompt([
276
+ {
277
+ type: 'confirm',
278
+ name: 'confirm',
279
+ message: `Are you sure you want to delete topic "${topic.name}"?`,
280
+ default: false
281
+ }
282
+ ]);
283
+ if (!answer.confirm) {
284
+ console.log(chalk.yellow('Deletion cancelled'));
285
+ return;
286
+ }
287
+ }
288
+ const spinner = ora('Deleting topic...').start();
289
+ await apiClient.deleteTopic(id);
290
+ spinner.succeed('Topic deleted successfully');
291
+ }
292
+ catch (error) {
293
+ console.error(chalk.red('āœ– Failed to delete topic:'), error.message);
294
+ process.exit(1);
295
+ }
296
+ });
297
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,215 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { readFileSync } from 'fs';
4
+ import { join, dirname } from 'path';
5
+ import { fileURLToPath } from 'url';
6
+ const __filename = fileURLToPath(import.meta.url);
7
+ const __dirname = dirname(__filename);
8
+ // Read package.json
9
+ const packagePath = join(__dirname, '..', 'package.json');
10
+ const packageJson = JSON.parse(readFileSync(packagePath, 'utf8'));
11
+ const program = new Command();
12
+ program
13
+ .name('lanonasis')
14
+ .description('Lanonasis Enterprise CLI - Memory as a Service and Infrastructure Management')
15
+ .version(packageJson.version);
16
+ program
17
+ .command('init')
18
+ .description('Initialize Lanonasis CLI configuration')
19
+ .action(() => {
20
+ console.log('šŸš€ Lanonasis CLI v' + packageJson.version);
21
+ console.log('');
22
+ console.log('Initialize your Lanonasis Enterprise Platform:');
23
+ console.log('');
24
+ console.log('1. Set up your service endpoint:');
25
+ console.log(' lanonasis config set api-url https://your-lanonasis-service.com');
26
+ console.log('');
27
+ console.log('2. Authenticate:');
28
+ console.log(' lanonasis auth login');
29
+ console.log('');
30
+ console.log('3. Start managing your services:');
31
+ console.log(' lanonasis create -t "My Memory" -c "Content here"');
32
+ console.log(' lanonasis search "search query"');
33
+ console.log(' lanonasis list');
34
+ console.log('');
35
+ console.log('šŸ“– Documentation: https://github.com/lanonasis/cli');
36
+ console.log('🌐 Platform: https://lanonasis.com');
37
+ });
38
+ program
39
+ .command('status')
40
+ .description('Show Lanonasis CLI status and configuration')
41
+ .action(() => {
42
+ console.log('šŸ“Š Lanonasis CLI Status');
43
+ console.log('========================');
44
+ console.log('Version:', packageJson.version);
45
+ console.log('Status: 🟢 Ready for configuration');
46
+ console.log('');
47
+ console.log('Next steps:');
48
+ console.log('• Run "lanonasis init" to get started');
49
+ console.log('• Configure your service endpoints');
50
+ console.log('• Authenticate with your platform');
51
+ });
52
+ program
53
+ .command('create')
54
+ .description('Create a new memory entry')
55
+ .option('-t, --title <title>', 'Memory title')
56
+ .option('-c, --content <content>', 'Memory content')
57
+ .option('--type <type>', 'Memory type (conversation, knowledge, project, context, reference)', 'context')
58
+ .action((options) => {
59
+ if (!options.title || !options.content) {
60
+ console.error('āŒ Error: Both --title and --content are required');
61
+ console.log('');
62
+ console.log('Usage: lanonasis create -t "Title" -c "Content"');
63
+ process.exit(1);
64
+ }
65
+ console.log('šŸ“ Creating memory...');
66
+ console.log('Title:', options.title);
67
+ console.log('Content:', options.content.substring(0, 100) + (options.content.length > 100 ? '...' : ''));
68
+ console.log('Type:', options.type);
69
+ console.log('');
70
+ console.log('āš ļø Please configure your Lanonasis service endpoint first:');
71
+ console.log(' lanonasis config set api-url https://your-service.com');
72
+ console.log(' lanonasis auth login');
73
+ });
74
+ program
75
+ .command('search')
76
+ .description('Search memories')
77
+ .argument('<query>', 'Search query')
78
+ .option('-l, --limit <limit>', 'Number of results', '10')
79
+ .action((query, options) => {
80
+ console.log('šŸ” Searching memories...');
81
+ console.log('Query:', query);
82
+ console.log('Limit:', options.limit);
83
+ console.log('');
84
+ console.log('āš ļø Please configure your Lanonasis service endpoint first:');
85
+ console.log(' lanonasis config set api-url https://your-service.com');
86
+ console.log(' lanonasis auth login');
87
+ });
88
+ program
89
+ .command('list')
90
+ .description('List all memories')
91
+ .option('-l, --limit <limit>', 'Number of results', '20')
92
+ .option('--type <type>', 'Filter by memory type')
93
+ .action((options) => {
94
+ console.log('šŸ“‹ Listing memories...');
95
+ console.log('Limit:', options.limit);
96
+ if (options.type)
97
+ console.log('Type filter:', options.type);
98
+ console.log('');
99
+ console.log('āš ļø Please configure your Lanonasis service endpoint first:');
100
+ console.log(' lanonasis config set api-url https://your-service.com');
101
+ console.log(' lanonasis auth login');
102
+ });
103
+ program
104
+ .command('config')
105
+ .description('Manage CLI configuration')
106
+ .argument('<action>', 'Action: set, get, list')
107
+ .argument('[key]', 'Configuration key')
108
+ .argument('[value]', 'Configuration value')
109
+ .action((action, key, value) => {
110
+ console.log('āš™ļø Memory CLI Configuration');
111
+ console.log('===========================');
112
+ switch (action) {
113
+ case 'set':
114
+ if (!key || !value) {
115
+ console.error('āŒ Usage: memory config set <key> <value>');
116
+ process.exit(1);
117
+ }
118
+ console.log(`Setting ${key} = ${value}`);
119
+ console.log('āœ… Configuration saved');
120
+ break;
121
+ case 'get':
122
+ if (!key) {
123
+ console.error('āŒ Usage: memory config get <key>');
124
+ process.exit(1);
125
+ }
126
+ console.log(`${key}: <not configured>`);
127
+ break;
128
+ case 'list':
129
+ console.log('Available configuration keys:');
130
+ console.log('• api-url: Your MaaS service endpoint');
131
+ console.log('• auth-token: Authentication token');
132
+ console.log('• default-type: Default memory type');
133
+ break;
134
+ default:
135
+ console.error('āŒ Unknown action. Use: set, get, or list');
136
+ process.exit(1);
137
+ }
138
+ });
139
+ program
140
+ .command('auth')
141
+ .description('Authentication commands')
142
+ .argument('<action>', 'Action: login, logout, status')
143
+ .action((action) => {
144
+ console.log('šŸ” Memory CLI Authentication');
145
+ console.log('============================');
146
+ switch (action) {
147
+ case 'login':
148
+ console.log('Please configure your API endpoint first:');
149
+ console.log(' memory config set api-url https://your-maas-service.com');
150
+ console.log('');
151
+ console.log('Then authenticate with your service credentials.');
152
+ break;
153
+ case 'logout':
154
+ console.log('āœ… Logged out successfully');
155
+ break;
156
+ case 'status':
157
+ console.log('Status: šŸ”“ Not authenticated');
158
+ console.log('Run "memory auth login" to authenticate');
159
+ break;
160
+ default:
161
+ console.error('āŒ Unknown action. Use: login, logout, or status');
162
+ process.exit(1);
163
+ }
164
+ });
165
+ // Help command
166
+ program
167
+ .command('help')
168
+ .description('Show detailed help information')
169
+ .action(() => {
170
+ console.log('šŸš€ Lanonasis Enterprise CLI');
171
+ console.log('============================');
172
+ console.log('');
173
+ console.log('The Lanonasis CLI provides unified access to your entire platform ecosystem.');
174
+ console.log('');
175
+ console.log('šŸš€ Quick Start:');
176
+ console.log('1. lanonasis init - Initialize and see setup instructions');
177
+ console.log('2. lanonasis config set api-url <url> - Set your service endpoint');
178
+ console.log('3. lanonasis auth login - Authenticate with your platform');
179
+ console.log('4. lanonasis create -t "Title" -c "Content" - Create your first memory');
180
+ console.log('');
181
+ console.log('šŸ“ Memory Operations:');
182
+ console.log('• lanonasis create -t "Title" -c "Content" --type knowledge');
183
+ console.log('• lanonasis search "query text"');
184
+ console.log('• lanonasis list --type project --limit 10');
185
+ console.log('');
186
+ console.log('āš™ļø Configuration:');
187
+ console.log('• lanonasis config set api-url https://your-service.com');
188
+ console.log('• lanonasis config list');
189
+ console.log('');
190
+ console.log('šŸ” Authentication:');
191
+ console.log('• lanonasis auth login');
192
+ console.log('• lanonasis auth status');
193
+ console.log('');
194
+ console.log('šŸ’” Alternative Commands:');
195
+ console.log('• memory <command> - Direct memory operations');
196
+ console.log('• maas <command> - Memory as a Service operations');
197
+ console.log('');
198
+ console.log('Memory Types: conversation, knowledge, project, context, reference');
199
+ console.log('');
200
+ console.log('šŸ“– Documentation: https://github.com/lanonasis/cli');
201
+ console.log('🌐 Platform: https://lanonasis.com');
202
+ console.log('šŸ› Issues: https://github.com/lanonasis/cli/issues');
203
+ });
204
+ // Handle unknown commands
205
+ program.on('command:*', () => {
206
+ console.error('āŒ Unknown command: %s', program.args.join(' '));
207
+ console.log('');
208
+ console.log('Run "lanonasis help" for available commands');
209
+ process.exit(1);
210
+ });
211
+ // Show help if no arguments provided
212
+ if (process.argv.length === 2) {
213
+ program.outputHelp();
214
+ }
215
+ program.parse();
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};