@lanonasis/cli 1.4.2 → 1.5.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 +357 -80
- package/dist/commands/auth.js +151 -1
- package/dist/commands/mcp.js +37 -30
- package/dist/commands/memory.js +78 -53
- package/dist/index-simple.js +189 -522
- package/dist/index.js +221 -327
- package/dist/utils/api.d.ts +2 -12
- package/dist/utils/api.js +0 -17
- package/dist/utils/completions.d.ts +28 -0
- package/dist/utils/completions.js +276 -0
- package/dist/utils/config.d.ts +2 -0
- package/dist/utils/config.js +15 -2
- package/dist/utils/formatting.d.ts +0 -2
- package/dist/utils/formatting.js +0 -13
- package/dist/utils/mcp-client.d.ts +6 -49
- package/dist/utils/mcp-client.js +82 -161
- package/dist/utils/mcp-client.test.d.ts +1 -0
- package/dist/utils/mcp-client.test.js +125 -0
- package/dist/utils/output.d.ts +23 -0
- package/dist/utils/output.js +97 -0
- package/dist/utils/websocket-mcp-client.d.ts +60 -0
- package/dist/utils/websocket-mcp-client.js +182 -0
- package/dist/utils/websocket-mcp-client.test.d.ts +1 -0
- package/dist/utils/websocket-mcp-client.test.js +126 -0
- package/package.json +10 -17
- package/dist/commands/api-keys.d.ts +0 -3
- package/dist/commands/api-keys.js +0 -812
- package/dist/mcp-server.d.ts +0 -2
- package/dist/mcp-server.js +0 -519
package/dist/commands/mcp.js
CHANGED
|
@@ -19,9 +19,10 @@ export function mcpCommands(program) {
|
|
|
19
19
|
const config = new CLIConfig();
|
|
20
20
|
const isAuthenticated = !!config.get('token');
|
|
21
21
|
if (isAuthenticated) {
|
|
22
|
-
console.log(chalk.green('✓ Authenticated - Using
|
|
23
|
-
console.log('
|
|
24
|
-
console.log('
|
|
22
|
+
console.log(chalk.green('✓ Authenticated - Using enterprise MCP modes'));
|
|
23
|
+
console.log(' SSE Mode: api.lanonasis.com (regular users)');
|
|
24
|
+
console.log(' WebSocket Mode: mcp.lanonasis.com (enterprise users)');
|
|
25
|
+
console.log(' with real-time updates enabled');
|
|
25
26
|
}
|
|
26
27
|
else {
|
|
27
28
|
console.log(chalk.yellow('⚠️ Not authenticated - Using local MCP mode'));
|
|
@@ -30,7 +31,8 @@ export function mcpCommands(program) {
|
|
|
30
31
|
console.log('');
|
|
31
32
|
console.log(chalk.cyan('Available MCP Commands:'));
|
|
32
33
|
console.log(' lanonasis mcp connect # Auto-connect to best mode');
|
|
33
|
-
console.log(' lanonasis mcp connect -r # Force remote mode');
|
|
34
|
+
console.log(' lanonasis mcp connect -r # Force remote SSE mode');
|
|
35
|
+
console.log(' lanonasis mcp connect -w # Force WebSocket mode (enterprise)');
|
|
34
36
|
console.log(' lanonasis mcp connect -l # Force local mode');
|
|
35
37
|
console.log(' lanonasis mcp status # Check connection status');
|
|
36
38
|
console.log(' lanonasis mcp tools # List available tools');
|
|
@@ -48,74 +50,79 @@ export function mcpCommands(program) {
|
|
|
48
50
|
spinner.fail('Failed to auto-connect to MCP');
|
|
49
51
|
}
|
|
50
52
|
}
|
|
51
|
-
catch {
|
|
53
|
+
catch (_error) {
|
|
52
54
|
spinner.fail('MCP auto-connect failed');
|
|
53
55
|
}
|
|
54
56
|
});
|
|
55
57
|
// Connect command
|
|
56
58
|
mcp.command('connect')
|
|
57
|
-
.description('Connect to MCP server (local, remote, or WebSocket)')
|
|
59
|
+
.description('Connect to MCP server (local, remote SSE, or WebSocket)')
|
|
58
60
|
.option('-l, --local', 'Connect to local MCP server')
|
|
59
|
-
.option('-r, --remote', 'Connect to remote
|
|
60
|
-
.option('-w, --websocket', 'Connect
|
|
61
|
+
.option('-r, --remote', 'Connect to remote SSE server (api.lanonasis.com)')
|
|
62
|
+
.option('-w, --websocket', 'Connect to WebSocket server (mcp.lanonasis.com) - Enterprise')
|
|
61
63
|
.option('-s, --server <path>', 'Local MCP server path')
|
|
62
|
-
.option('-u, --url <url>', 'Remote
|
|
64
|
+
.option('-u, --url <url>', 'Remote MCP server URL')
|
|
63
65
|
.action(async (options) => {
|
|
64
66
|
const spinner = ora('Connecting to MCP server...').start();
|
|
65
67
|
const config = new CLIConfig();
|
|
66
68
|
try {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
+
// Determine connection mode
|
|
70
|
+
let connectionMode = 'local';
|
|
69
71
|
if (options.websocket) {
|
|
70
72
|
connectionMode = 'websocket';
|
|
71
73
|
}
|
|
72
74
|
else if (options.remote) {
|
|
73
75
|
connectionMode = 'remote';
|
|
74
76
|
}
|
|
75
|
-
else if (options.local) {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
77
|
+
else if (!options.local && !options.remote && !options.websocket) {
|
|
78
|
+
// Auto-detect: WebSocket for enterprise, SSE for regular, local if not authenticated
|
|
79
|
+
const token = config.get('token');
|
|
80
|
+
if (token) {
|
|
81
|
+
// Check if enterprise user (simplified check)
|
|
82
|
+
connectionMode = 'remote'; // Default to SSE for now
|
|
83
|
+
}
|
|
81
84
|
}
|
|
82
|
-
// Save
|
|
85
|
+
// Save preference
|
|
83
86
|
config.set('mcpConnectionMode', connectionMode);
|
|
84
87
|
if (options.server) {
|
|
85
88
|
config.set('mcpServerPath', options.server);
|
|
86
89
|
}
|
|
87
90
|
if (options.url) {
|
|
88
|
-
|
|
89
|
-
config.set('mcpWebSocketUrl', options.url);
|
|
90
|
-
}
|
|
91
|
-
else {
|
|
92
|
-
config.set('mcpServerUrl', options.url);
|
|
93
|
-
}
|
|
91
|
+
config.set('mcpServerUrl', options.url);
|
|
94
92
|
}
|
|
95
93
|
const client = getMCPClient();
|
|
96
94
|
const connected = await client.connect({
|
|
97
|
-
connectionMode,
|
|
95
|
+
mode: connectionMode,
|
|
98
96
|
serverPath: options.server,
|
|
99
97
|
serverUrl: options.url
|
|
100
98
|
});
|
|
101
99
|
if (connected) {
|
|
102
|
-
|
|
100
|
+
const modeLabels = {
|
|
101
|
+
local: 'local',
|
|
102
|
+
remote: 'remote SSE',
|
|
103
|
+
websocket: 'WebSocket (Enterprise)'
|
|
104
|
+
};
|
|
105
|
+
spinner.succeed(chalk.green(`Connected to ${modeLabels[connectionMode]} MCP server`));
|
|
103
106
|
if (connectionMode === 'remote') {
|
|
104
107
|
console.log(chalk.cyan('ℹ️ Using remote MCP via api.lanonasis.com'));
|
|
105
108
|
console.log(chalk.cyan('📡 SSE endpoint active for real-time updates'));
|
|
106
109
|
}
|
|
107
110
|
else if (connectionMode === 'websocket') {
|
|
108
|
-
console.log(chalk.cyan('
|
|
109
|
-
console.log(chalk.cyan('
|
|
111
|
+
console.log(chalk.cyan('🚀 Using enterprise WebSocket MCP via mcp.lanonasis.com'));
|
|
112
|
+
console.log(chalk.cyan('⚡ Real-time WebSocket connection active'));
|
|
113
|
+
console.log(chalk.cyan('🏢 Enterprise features enabled'));
|
|
110
114
|
}
|
|
111
115
|
}
|
|
112
116
|
else {
|
|
113
117
|
spinner.fail('Failed to connect to MCP server');
|
|
118
|
+
if (connectionMode === 'websocket') {
|
|
119
|
+
console.log(chalk.yellow('💡 WebSocket mode requires enterprise access'));
|
|
120
|
+
console.log(chalk.yellow(' Try: lanonasis mcp connect -r (for SSE mode)'));
|
|
121
|
+
}
|
|
114
122
|
}
|
|
115
123
|
}
|
|
116
124
|
catch (error) {
|
|
117
125
|
spinner.fail(`Connection failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
118
|
-
process.exit(1);
|
|
119
126
|
}
|
|
120
127
|
});
|
|
121
128
|
// Disconnect command
|
|
@@ -215,7 +222,7 @@ export function mcpCommands(program) {
|
|
|
215
222
|
try {
|
|
216
223
|
args = JSON.parse(options.args);
|
|
217
224
|
}
|
|
218
|
-
catch {
|
|
225
|
+
catch (error) {
|
|
219
226
|
spinner.fail('Invalid JSON arguments');
|
|
220
227
|
process.exit(1);
|
|
221
228
|
}
|
package/dist/commands/memory.js
CHANGED
|
@@ -6,6 +6,8 @@ import wrap from 'word-wrap';
|
|
|
6
6
|
import { format } from 'date-fns';
|
|
7
7
|
import { apiClient } from '../utils/api.js';
|
|
8
8
|
import { formatBytes, truncateText } from '../utils/formatting.js';
|
|
9
|
+
import { output } from '../utils/output.js';
|
|
10
|
+
// Using GetMemoriesParams from api.ts
|
|
9
11
|
export function memoryCommands(program) {
|
|
10
12
|
// Create memory
|
|
11
13
|
program
|
|
@@ -21,7 +23,11 @@ export function memoryCommands(program) {
|
|
|
21
23
|
.action(async (options) => {
|
|
22
24
|
try {
|
|
23
25
|
let { title, content, type, tags, topicId, interactive } = options;
|
|
24
|
-
|
|
26
|
+
// Validate required fields in silent mode
|
|
27
|
+
if (output.isSilent() && (!title || !content)) {
|
|
28
|
+
throw new Error('Title and content are required when using --output json or --silent');
|
|
29
|
+
}
|
|
30
|
+
if ((interactive || (!title || !content)) && !output.isSilent()) {
|
|
25
31
|
const answers = await inquirer.prompt([
|
|
26
32
|
{
|
|
27
33
|
type: 'input',
|
|
@@ -56,7 +62,7 @@ export function memoryCommands(program) {
|
|
|
56
62
|
type = answers.type;
|
|
57
63
|
tags = answers.tags;
|
|
58
64
|
}
|
|
59
|
-
const spinner = ora('Creating memory...').start();
|
|
65
|
+
const spinner = output.isSilent() ? null : ora('Creating memory...').start();
|
|
60
66
|
const memoryData = {
|
|
61
67
|
title,
|
|
62
68
|
content,
|
|
@@ -69,19 +75,25 @@ export function memoryCommands(program) {
|
|
|
69
75
|
memoryData.topic_id = topicId;
|
|
70
76
|
}
|
|
71
77
|
const memory = await apiClient.createMemory(memoryData);
|
|
72
|
-
spinner
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
console.log(
|
|
78
|
+
if (spinner)
|
|
79
|
+
spinner.succeed('Memory created successfully');
|
|
80
|
+
if (output.isJsonOutput()) {
|
|
81
|
+
output.json(memory);
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
console.log();
|
|
85
|
+
console.log(chalk.green('✓ Memory created:'));
|
|
86
|
+
console.log(` ID: ${chalk.cyan(memory.id)}`);
|
|
87
|
+
console.log(` Title: ${memory.title}`);
|
|
88
|
+
console.log(` Type: ${memory.memory_type}`);
|
|
89
|
+
if (memory.tags && memory.tags.length > 0) {
|
|
90
|
+
console.log(` Tags: ${memory.tags.join(', ')}`);
|
|
91
|
+
}
|
|
80
92
|
}
|
|
81
93
|
}
|
|
82
94
|
catch (error) {
|
|
83
95
|
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
84
|
-
|
|
96
|
+
output.error(chalk.red('✖ Failed to create memory:'), errorMessage);
|
|
85
97
|
process.exit(1);
|
|
86
98
|
}
|
|
87
99
|
});
|
|
@@ -99,36 +111,41 @@ export function memoryCommands(program) {
|
|
|
99
111
|
.option('--order <order>', 'sort order (asc, desc)', 'desc')
|
|
100
112
|
.action(async (options) => {
|
|
101
113
|
try {
|
|
102
|
-
const spinner = ora('Fetching memories...').start();
|
|
114
|
+
const spinner = output.isSilent() ? null : ora('Fetching memories...').start();
|
|
103
115
|
const params = {
|
|
104
|
-
|
|
116
|
+
offset: (parseInt(options.page || '1') - 1) * parseInt(options.limit || '20'),
|
|
105
117
|
limit: parseInt(options.limit || '20'),
|
|
106
|
-
|
|
107
|
-
|
|
118
|
+
sort_by: (options.sort || 'created_at'),
|
|
119
|
+
sort_order: (options.order || 'desc')
|
|
108
120
|
};
|
|
109
121
|
if (options.type)
|
|
110
122
|
params.memory_type = options.type;
|
|
111
123
|
if (options.tags)
|
|
112
|
-
params.tags = options.tags;
|
|
113
|
-
|
|
114
|
-
params.user_id = options.userId;
|
|
124
|
+
params.tags = options.tags.split(',').map(t => t.trim());
|
|
125
|
+
// Note: user_id filtering removed as it's handled by authentication
|
|
115
126
|
const result = await apiClient.getMemories(params);
|
|
116
|
-
spinner
|
|
117
|
-
|
|
118
|
-
if (
|
|
119
|
-
|
|
127
|
+
if (spinner)
|
|
128
|
+
spinner.stop();
|
|
129
|
+
if (result.data.length === 0) {
|
|
130
|
+
if (output.isJsonOutput()) {
|
|
131
|
+
output.json({ data: [], pagination: result.pagination });
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
console.log(chalk.yellow('No memories found'));
|
|
135
|
+
}
|
|
120
136
|
return;
|
|
121
137
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
console.log();
|
|
125
|
-
const outputFormat = process.env.CLI_OUTPUT_FORMAT || 'table';
|
|
126
|
-
if (outputFormat === 'json') {
|
|
127
|
-
console.log(JSON.stringify(result, null, 2));
|
|
138
|
+
if (output.isJsonOutput()) {
|
|
139
|
+
output.json(result);
|
|
128
140
|
}
|
|
129
141
|
else {
|
|
142
|
+
console.log(chalk.blue.bold(`\n📚 Memories (${result.pagination.total} total)`));
|
|
143
|
+
const currentPage = Math.floor(result.pagination.offset / result.pagination.limit) + 1;
|
|
144
|
+
const totalPages = Math.ceil(result.pagination.total / result.pagination.limit);
|
|
145
|
+
console.log(chalk.gray(`Page ${currentPage} of ${totalPages}`));
|
|
146
|
+
console.log();
|
|
130
147
|
// Table format
|
|
131
|
-
const tableData =
|
|
148
|
+
const tableData = result.data.map((memory) => [
|
|
132
149
|
truncateText(memory.title, 30),
|
|
133
150
|
memory.memory_type,
|
|
134
151
|
memory.tags.slice(0, 3).join(', '),
|
|
@@ -136,7 +153,6 @@ export function memoryCommands(program) {
|
|
|
136
153
|
memory.access_count
|
|
137
154
|
]);
|
|
138
155
|
const tableConfig = {
|
|
139
|
-
header: ['Title', 'Type', 'Tags', 'Created', 'Access'],
|
|
140
156
|
columnDefault: {
|
|
141
157
|
width: 20,
|
|
142
158
|
wrapWord: true
|
|
@@ -149,13 +165,12 @@ export function memoryCommands(program) {
|
|
|
149
165
|
{ width: 8 }
|
|
150
166
|
]
|
|
151
167
|
};
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
columns: tableConfig.columns
|
|
155
|
-
}));
|
|
168
|
+
const tableHeaders = ['Title', 'Type', 'Tags', 'Created', 'Access'];
|
|
169
|
+
console.log(table([tableHeaders, ...tableData], tableConfig));
|
|
156
170
|
// Pagination info
|
|
157
|
-
if (result.pagination.
|
|
158
|
-
|
|
171
|
+
if (result.pagination.has_more) {
|
|
172
|
+
const nextPage = currentPage + 1;
|
|
173
|
+
console.log(chalk.gray(`\nUse --page ${nextPage} for next page`));
|
|
159
174
|
}
|
|
160
175
|
}
|
|
161
176
|
}
|
|
@@ -176,7 +191,7 @@ export function memoryCommands(program) {
|
|
|
176
191
|
.option('--tags <tags>', 'filter by tags (comma-separated)')
|
|
177
192
|
.action(async (query, options) => {
|
|
178
193
|
try {
|
|
179
|
-
const spinner = ora(`Searching for "${query}"...`).start();
|
|
194
|
+
const spinner = output.isSilent() ? null : ora(`Searching for "${query}"...`).start();
|
|
180
195
|
const searchOptions = {
|
|
181
196
|
limit: parseInt(options.limit || '20'),
|
|
182
197
|
threshold: parseFloat(options.threshold || '0.7')
|
|
@@ -188,25 +203,35 @@ export function memoryCommands(program) {
|
|
|
188
203
|
searchOptions.tags = options.tags.split(',').map((t) => t.trim());
|
|
189
204
|
}
|
|
190
205
|
const result = await apiClient.searchMemories(query, searchOptions);
|
|
191
|
-
spinner
|
|
192
|
-
|
|
193
|
-
if (
|
|
194
|
-
|
|
206
|
+
if (spinner)
|
|
207
|
+
spinner.stop();
|
|
208
|
+
if (result.data.length === 0) {
|
|
209
|
+
if (output.isJsonOutput()) {
|
|
210
|
+
output.json({ data: [], pagination: result.pagination, query });
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
console.log(chalk.yellow('No memories found matching your search'));
|
|
214
|
+
}
|
|
195
215
|
return;
|
|
196
216
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
console.log(chalk.
|
|
203
|
-
console.log(chalk.white(` ${truncateText(memory.content, 100)}`));
|
|
204
|
-
console.log(chalk.cyan(` ID: ${memory.id}`) + chalk.gray(` | Type: ${memory.memory_type}`));
|
|
205
|
-
if (memory.tags.length > 0) {
|
|
206
|
-
console.log(chalk.yellow(` Tags: ${memory.tags.join(', ')}`));
|
|
207
|
-
}
|
|
217
|
+
if (output.isJsonOutput()) {
|
|
218
|
+
output.json({ ...result, query });
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
console.log(chalk.blue.bold(`\n🔍 Search Results (${result.pagination.total} found)`));
|
|
222
|
+
console.log(chalk.gray(`Query: "${query}"`));
|
|
208
223
|
console.log();
|
|
209
|
-
|
|
224
|
+
result.data.forEach((memory, index) => {
|
|
225
|
+
const score = (memory.relevance_score * 100).toFixed(1);
|
|
226
|
+
console.log(chalk.green(`${index + 1}. ${memory.title}`) + chalk.gray(` (${score}% match)`));
|
|
227
|
+
console.log(chalk.white(` ${truncateText(memory.content, 100)}`));
|
|
228
|
+
console.log(chalk.cyan(` ID: ${memory.id}`) + chalk.gray(` | Type: ${memory.memory_type}`));
|
|
229
|
+
if (memory.tags.length > 0) {
|
|
230
|
+
console.log(chalk.yellow(` Tags: ${memory.tags.join(', ')}`));
|
|
231
|
+
}
|
|
232
|
+
console.log();
|
|
233
|
+
});
|
|
234
|
+
}
|
|
210
235
|
}
|
|
211
236
|
catch (error) {
|
|
212
237
|
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|