@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,401 @@
1
+ import chalk from 'chalk';
2
+ import inquirer from 'inquirer';
3
+ import ora from 'ora';
4
+ import { table } from 'table';
5
+ import wrap from 'word-wrap';
6
+ import { format } from 'date-fns';
7
+ import { apiClient } from '../utils/api.js';
8
+ import { formatBytes, truncateText } from '../utils/formatting.js';
9
+ export function memoryCommands(program) {
10
+ // Create memory
11
+ program
12
+ .command('create')
13
+ .alias('add')
14
+ .description('Create a new memory entry')
15
+ .option('-t, --title <title>', 'memory title')
16
+ .option('-c, --content <content>', 'memory content')
17
+ .option('--type <type>', 'memory type (conversation, knowledge, project, context, reference)', 'context')
18
+ .option('--tags <tags>', 'comma-separated tags')
19
+ .option('--topic-id <id>', 'topic ID')
20
+ .option('-i, --interactive', 'interactive mode')
21
+ .action(async (options) => {
22
+ try {
23
+ let { title, content, type, tags, topicId, interactive } = options;
24
+ if (interactive || (!title || !content)) {
25
+ const answers = await inquirer.prompt([
26
+ {
27
+ type: 'input',
28
+ name: 'title',
29
+ message: 'Memory title:',
30
+ default: title,
31
+ validate: (input) => input.length > 0 || 'Title is required'
32
+ },
33
+ {
34
+ type: 'editor',
35
+ name: 'content',
36
+ message: 'Memory content:',
37
+ default: content,
38
+ validate: (input) => input.length > 0 || 'Content is required'
39
+ },
40
+ {
41
+ type: 'list',
42
+ name: 'type',
43
+ message: 'Memory type:',
44
+ choices: ['conversation', 'knowledge', 'project', 'context', 'reference'],
45
+ default: type || 'context'
46
+ },
47
+ {
48
+ type: 'input',
49
+ name: 'tags',
50
+ message: 'Tags (comma-separated):',
51
+ default: tags || ''
52
+ }
53
+ ]);
54
+ title = answers.title;
55
+ content = answers.content;
56
+ type = answers.type;
57
+ tags = answers.tags;
58
+ }
59
+ const spinner = ora('Creating memory...').start();
60
+ const memoryData = {
61
+ title,
62
+ content,
63
+ memory_type: type
64
+ };
65
+ if (tags) {
66
+ memoryData.tags = tags.split(',').map((tag) => tag.trim()).filter(Boolean);
67
+ }
68
+ if (topicId) {
69
+ memoryData.topic_id = topicId;
70
+ }
71
+ const memory = await apiClient.createMemory(memoryData);
72
+ spinner.succeed('Memory created successfully');
73
+ console.log();
74
+ console.log(chalk.green('✓ Memory created:'));
75
+ console.log(` ID: ${chalk.cyan(memory.id)}`);
76
+ console.log(` Title: ${memory.title}`);
77
+ console.log(` Type: ${memory.memory_type}`);
78
+ if (memory.tags && memory.tags.length > 0) {
79
+ console.log(` Tags: ${memory.tags.join(', ')}`);
80
+ }
81
+ }
82
+ catch (error) {
83
+ console.error(chalk.red('✖ Failed to create memory:'), error.message);
84
+ process.exit(1);
85
+ }
86
+ });
87
+ // List memories
88
+ program
89
+ .command('list')
90
+ .alias('ls')
91
+ .description('List memory entries')
92
+ .option('-p, --page <page>', 'page number', '1')
93
+ .option('-l, --limit <limit>', 'number of entries per page', '20')
94
+ .option('--type <type>', 'filter by memory type')
95
+ .option('--tags <tags>', 'filter by tags (comma-separated)')
96
+ .option('--user-id <id>', 'filter by user ID (admin only)')
97
+ .option('--sort <field>', 'sort by field (created_at, updated_at, title, last_accessed)', 'created_at')
98
+ .option('--order <order>', 'sort order (asc, desc)', 'desc')
99
+ .action(async (options) => {
100
+ try {
101
+ const spinner = ora('Fetching memories...').start();
102
+ const params = {
103
+ page: parseInt(options.page),
104
+ limit: parseInt(options.limit),
105
+ sort: options.sort,
106
+ order: options.order
107
+ };
108
+ if (options.type)
109
+ params.memory_type = options.type;
110
+ if (options.tags)
111
+ params.tags = options.tags;
112
+ if (options.userId)
113
+ params.user_id = options.userId;
114
+ const result = await apiClient.getMemories(params);
115
+ spinner.stop();
116
+ if (result.memories.length === 0) {
117
+ console.log(chalk.yellow('No memories found'));
118
+ return;
119
+ }
120
+ console.log(chalk.blue.bold(`\n📚 Memories (${result.pagination.total} total)`));
121
+ console.log(chalk.gray(`Page ${result.pagination.page} of ${result.pagination.pages}`));
122
+ console.log();
123
+ const outputFormat = process.env.CLI_OUTPUT_FORMAT || 'table';
124
+ if (outputFormat === 'json') {
125
+ console.log(JSON.stringify(result, null, 2));
126
+ }
127
+ else {
128
+ // Table format
129
+ const tableData = result.memories.map((memory) => [
130
+ truncateText(memory.title, 30),
131
+ memory.memory_type,
132
+ memory.tags.slice(0, 3).join(', '),
133
+ format(new Date(memory.created_at), 'MMM dd, yyyy'),
134
+ memory.access_count
135
+ ]);
136
+ const tableConfig = {
137
+ header: ['Title', 'Type', 'Tags', 'Created', 'Access'],
138
+ columnDefault: {
139
+ width: 20,
140
+ wrapWord: true
141
+ },
142
+ columns: [
143
+ { width: 30 },
144
+ { width: 12 },
145
+ { width: 20 },
146
+ { width: 12 },
147
+ { width: 8 }
148
+ ]
149
+ };
150
+ console.log(table([tableConfig.header, ...tableData], tableConfig));
151
+ // Pagination info
152
+ if (result.pagination.pages > 1) {
153
+ console.log(chalk.gray(`\nUse --page ${result.pagination.page + 1} for next page`));
154
+ }
155
+ }
156
+ }
157
+ catch (error) {
158
+ console.error(chalk.red('✖ Failed to list memories:'), error.message);
159
+ process.exit(1);
160
+ }
161
+ });
162
+ // Search memories
163
+ program
164
+ .command('search')
165
+ .description('Search memories using semantic search')
166
+ .argument('<query>', 'search query')
167
+ .option('-l, --limit <limit>', 'number of results', '20')
168
+ .option('--threshold <threshold>', 'similarity threshold (0-1)', '0.7')
169
+ .option('--type <types>', 'filter by memory types (comma-separated)')
170
+ .option('--tags <tags>', 'filter by tags (comma-separated)')
171
+ .action(async (query, options) => {
172
+ try {
173
+ const spinner = ora(`Searching for "${query}"...`).start();
174
+ const searchOptions = {
175
+ limit: parseInt(options.limit),
176
+ threshold: parseFloat(options.threshold)
177
+ };
178
+ if (options.type) {
179
+ searchOptions.memory_types = options.type.split(',').map((t) => t.trim());
180
+ }
181
+ if (options.tags) {
182
+ searchOptions.tags = options.tags.split(',').map((t) => t.trim());
183
+ }
184
+ const result = await apiClient.searchMemories(query, searchOptions);
185
+ spinner.stop();
186
+ if (result.results.length === 0) {
187
+ console.log(chalk.yellow('No memories found matching your search'));
188
+ return;
189
+ }
190
+ console.log(chalk.blue.bold(`\n🔍 Search Results (${result.total_results} found)`));
191
+ console.log(chalk.gray(`Query: "${query}" | Search time: ${result.search_time_ms}ms`));
192
+ console.log();
193
+ result.results.forEach((memory, index) => {
194
+ const score = (memory.relevance_score * 100).toFixed(1);
195
+ console.log(chalk.green(`${index + 1}. ${memory.title}`) + chalk.gray(` (${score}% match)`));
196
+ console.log(chalk.white(` ${truncateText(memory.content, 100)}`));
197
+ console.log(chalk.cyan(` ID: ${memory.id}`) + chalk.gray(` | Type: ${memory.memory_type}`));
198
+ if (memory.tags.length > 0) {
199
+ console.log(chalk.yellow(` Tags: ${memory.tags.join(', ')}`));
200
+ }
201
+ console.log();
202
+ });
203
+ }
204
+ catch (error) {
205
+ console.error(chalk.red('✖ Search failed:'), error.message);
206
+ process.exit(1);
207
+ }
208
+ });
209
+ // Get memory details
210
+ program
211
+ .command('get')
212
+ .alias('show')
213
+ .description('Get detailed information about a memory')
214
+ .argument('<id>', 'memory ID')
215
+ .action(async (id) => {
216
+ try {
217
+ const spinner = ora('Fetching memory...').start();
218
+ const memory = await apiClient.getMemory(id);
219
+ spinner.stop();
220
+ console.log(chalk.blue.bold('\n📄 Memory Details'));
221
+ console.log();
222
+ console.log(chalk.green('Title:'), memory.title);
223
+ console.log(chalk.green('ID:'), chalk.cyan(memory.id));
224
+ console.log(chalk.green('Type:'), memory.memory_type);
225
+ console.log(chalk.green('Created:'), format(new Date(memory.created_at), 'PPpp'));
226
+ console.log(chalk.green('Updated:'), format(new Date(memory.updated_at), 'PPpp'));
227
+ if (memory.last_accessed) {
228
+ console.log(chalk.green('Last Accessed:'), format(new Date(memory.last_accessed), 'PPpp'));
229
+ }
230
+ console.log(chalk.green('Access Count:'), memory.access_count);
231
+ if (memory.tags && memory.tags.length > 0) {
232
+ console.log(chalk.green('Tags:'), memory.tags.join(', '));
233
+ }
234
+ if (memory.topic_id) {
235
+ console.log(chalk.green('Topic ID:'), memory.topic_id);
236
+ }
237
+ console.log();
238
+ console.log(chalk.green('Content:'));
239
+ console.log(wrap(memory.content, { width: 80, indent: ' ' }));
240
+ if (memory.metadata && Object.keys(memory.metadata).length > 0) {
241
+ console.log();
242
+ console.log(chalk.green('Metadata:'));
243
+ console.log(JSON.stringify(memory.metadata, null, 2));
244
+ }
245
+ }
246
+ catch (error) {
247
+ console.error(chalk.red('✖ Failed to get memory:'), error.message);
248
+ process.exit(1);
249
+ }
250
+ });
251
+ // Update memory
252
+ program
253
+ .command('update')
254
+ .description('Update a memory entry')
255
+ .argument('<id>', 'memory ID')
256
+ .option('-t, --title <title>', 'new title')
257
+ .option('-c, --content <content>', 'new content')
258
+ .option('--type <type>', 'new memory type')
259
+ .option('--tags <tags>', 'new tags (comma-separated)')
260
+ .option('-i, --interactive', 'interactive mode')
261
+ .action(async (id, options) => {
262
+ try {
263
+ let updateData = {};
264
+ if (options.interactive) {
265
+ // First, get current memory data
266
+ const spinner = ora('Fetching current memory...').start();
267
+ const currentMemory = await apiClient.getMemory(id);
268
+ spinner.stop();
269
+ const answers = await inquirer.prompt([
270
+ {
271
+ type: 'input',
272
+ name: 'title',
273
+ message: 'Title:',
274
+ default: currentMemory.title
275
+ },
276
+ {
277
+ type: 'editor',
278
+ name: 'content',
279
+ message: 'Content:',
280
+ default: currentMemory.content
281
+ },
282
+ {
283
+ type: 'list',
284
+ name: 'type',
285
+ message: 'Memory type:',
286
+ choices: ['conversation', 'knowledge', 'project', 'context', 'reference'],
287
+ default: currentMemory.memory_type
288
+ },
289
+ {
290
+ type: 'input',
291
+ name: 'tags',
292
+ message: 'Tags (comma-separated):',
293
+ default: currentMemory.tags.join(', ')
294
+ }
295
+ ]);
296
+ updateData = {
297
+ title: answers.title,
298
+ content: answers.content,
299
+ memory_type: answers.type,
300
+ tags: answers.tags.split(',').map((tag) => tag.trim()).filter(Boolean)
301
+ };
302
+ }
303
+ else {
304
+ if (options.title)
305
+ updateData.title = options.title;
306
+ if (options.content)
307
+ updateData.content = options.content;
308
+ if (options.type)
309
+ updateData.memory_type = options.type;
310
+ if (options.tags) {
311
+ updateData.tags = options.tags.split(',').map((tag) => tag.trim()).filter(Boolean);
312
+ }
313
+ }
314
+ if (Object.keys(updateData).length === 0) {
315
+ console.log(chalk.yellow('No updates specified'));
316
+ return;
317
+ }
318
+ const spinner = ora('Updating memory...').start();
319
+ const memory = await apiClient.updateMemory(id, updateData);
320
+ spinner.succeed('Memory updated successfully');
321
+ console.log();
322
+ console.log(chalk.green('✓ Memory updated:'));
323
+ console.log(` ID: ${chalk.cyan(memory.id)}`);
324
+ console.log(` Title: ${memory.title}`);
325
+ }
326
+ catch (error) {
327
+ console.error(chalk.red('✖ Failed to update memory:'), error.message);
328
+ process.exit(1);
329
+ }
330
+ });
331
+ // Delete memory
332
+ program
333
+ .command('delete')
334
+ .alias('rm')
335
+ .description('Delete a memory entry')
336
+ .argument('<id>', 'memory ID')
337
+ .option('-f, --force', 'skip confirmation')
338
+ .action(async (id, options) => {
339
+ try {
340
+ if (!options.force) {
341
+ const memory = await apiClient.getMemory(id);
342
+ const answer = await inquirer.prompt([
343
+ {
344
+ type: 'confirm',
345
+ name: 'confirm',
346
+ message: `Are you sure you want to delete "${memory.title}"?`,
347
+ default: false
348
+ }
349
+ ]);
350
+ if (!answer.confirm) {
351
+ console.log(chalk.yellow('Deletion cancelled'));
352
+ return;
353
+ }
354
+ }
355
+ const spinner = ora('Deleting memory...').start();
356
+ await apiClient.deleteMemory(id);
357
+ spinner.succeed('Memory deleted successfully');
358
+ }
359
+ catch (error) {
360
+ console.error(chalk.red('✖ Failed to delete memory:'), error.message);
361
+ process.exit(1);
362
+ }
363
+ });
364
+ // Memory statistics
365
+ program
366
+ .command('stats')
367
+ .description('Show memory statistics (admin only)')
368
+ .action(async () => {
369
+ try {
370
+ const spinner = ora('Fetching statistics...').start();
371
+ const stats = await apiClient.getMemoryStats();
372
+ spinner.stop();
373
+ console.log(chalk.blue.bold('\n📊 Memory Statistics'));
374
+ console.log();
375
+ console.log(chalk.green('Total Memories:'), stats.total_memories.toLocaleString());
376
+ console.log(chalk.green('Total Size:'), formatBytes(stats.total_size_bytes));
377
+ console.log(chalk.green('Average Access Count:'), stats.avg_access_count);
378
+ console.log();
379
+ console.log(chalk.yellow('Memories by Type:'));
380
+ Object.entries(stats.memories_by_type).forEach(([type, count]) => {
381
+ console.log(` ${type}: ${count}`);
382
+ });
383
+ if (stats.most_accessed_memory) {
384
+ console.log();
385
+ console.log(chalk.yellow('Most Accessed Memory:'));
386
+ console.log(` ${stats.most_accessed_memory.title} (${stats.most_accessed_memory.access_count} times)`);
387
+ }
388
+ if (stats.recent_memories.length > 0) {
389
+ console.log();
390
+ console.log(chalk.yellow('Recent Memories:'));
391
+ stats.recent_memories.forEach((memory, index) => {
392
+ console.log(` ${index + 1}. ${truncateText(memory.title, 50)}`);
393
+ });
394
+ }
395
+ }
396
+ catch (error) {
397
+ console.error(chalk.red('✖ Failed to get statistics:'), error.message);
398
+ process.exit(1);
399
+ }
400
+ });
401
+ }
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function orgCommands(program: Command): void;
@@ -0,0 +1,41 @@
1
+ import chalk from 'chalk';
2
+ import { CLIConfig } from '../utils/config.js';
3
+ export function orgCommands(program) {
4
+ // Show organization info
5
+ program
6
+ .command('info')
7
+ .description('Show organization information')
8
+ .action(async () => {
9
+ const config = new CLIConfig();
10
+ await config.init();
11
+ const user = await config.getCurrentUser();
12
+ if (!user) {
13
+ console.error(chalk.red('✖ Not authenticated'));
14
+ process.exit(1);
15
+ }
16
+ console.log(chalk.blue.bold('🏢 Organization Information'));
17
+ console.log();
18
+ console.log(chalk.green('Organization ID:'), user.organization_id);
19
+ console.log(chalk.green('Your Role:'), user.role);
20
+ console.log(chalk.green('Plan:'), user.plan);
21
+ console.log(chalk.green('Email:'), user.email);
22
+ // In a full implementation, you'd fetch more org details from the API
23
+ console.log();
24
+ console.log(chalk.gray('Note: Use the web dashboard for full organization management'));
25
+ });
26
+ // Placeholder for future org management commands
27
+ program
28
+ .command('members')
29
+ .description('List organization members (admin only)')
30
+ .action(async () => {
31
+ console.log(chalk.yellow('⚠️ This feature is not yet implemented'));
32
+ console.log(chalk.gray('Use the web dashboard to manage organization members'));
33
+ });
34
+ program
35
+ .command('usage')
36
+ .description('Show organization usage statistics')
37
+ .action(async () => {
38
+ console.log(chalk.yellow('⚠️ This feature is not yet implemented'));
39
+ console.log(chalk.gray('Use the web dashboard to view usage statistics'));
40
+ });
41
+ }
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function topicCommands(program: Command): void;