@lanonasis/cli 1.5.0 → 1.5.2
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 +284 -586
- package/dist/commands/api-keys.d.ts +3 -0
- package/dist/commands/api-keys.js +812 -0
- package/dist/commands/auth.d.ts +2 -0
- package/dist/commands/auth.js +127 -138
- package/dist/commands/completion.d.ts +33 -0
- package/dist/commands/completion.js +378 -0
- package/dist/commands/guide.d.ts +19 -0
- package/dist/commands/guide.js +446 -0
- package/dist/commands/mcp.js +30 -37
- package/dist/commands/memory.js +53 -78
- package/dist/completions/bash-completion.sh +88 -0
- package/dist/completions/fish-completion.fish +132 -0
- package/dist/completions/zsh-completion.zsh +196 -0
- package/dist/index-simple.js +633 -183
- package/dist/index.js +327 -221
- package/dist/mcp-server.d.ts +38 -0
- package/dist/mcp-server.js +154 -0
- package/dist/utils/api.d.ts +12 -2
- package/dist/utils/api.js +38 -4
- package/dist/utils/config.d.ts +5 -2
- package/dist/utils/config.js +39 -15
- package/dist/utils/formatting.d.ts +2 -0
- package/dist/utils/formatting.js +13 -0
- package/dist/utils/mcp-client.d.ts +49 -6
- package/dist/utils/mcp-client.js +159 -82
- package/package.json +22 -12
- package/dist/utils/completions.d.ts +0 -28
- package/dist/utils/completions.js +0 -276
- package/dist/utils/mcp-client.test.d.ts +0 -1
- package/dist/utils/mcp-client.test.js +0 -125
- package/dist/utils/output.d.ts +0 -23
- package/dist/utils/output.js +0 -97
- package/dist/utils/websocket-mcp-client.d.ts +0 -60
- package/dist/utils/websocket-mcp-client.js +0 -182
- package/dist/utils/websocket-mcp-client.test.d.ts +0 -1
- package/dist/utils/websocket-mcp-client.test.js +0 -126
package/dist/commands/auth.d.ts
CHANGED
package/dist/commands/auth.js
CHANGED
|
@@ -1,41 +1,152 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import inquirer from 'inquirer';
|
|
3
3
|
import ora from 'ora';
|
|
4
|
-
import { createServer } from 'http';
|
|
5
|
-
import { URL } from 'url';
|
|
6
4
|
import open from 'open';
|
|
7
5
|
import { apiClient } from '../utils/api.js';
|
|
8
6
|
import { CLIConfig } from '../utils/config.js';
|
|
7
|
+
// Color scheme
|
|
8
|
+
const colors = {
|
|
9
|
+
primary: chalk.blue.bold,
|
|
10
|
+
success: chalk.green,
|
|
11
|
+
warning: chalk.yellow,
|
|
12
|
+
error: chalk.red,
|
|
13
|
+
info: chalk.cyan,
|
|
14
|
+
accent: chalk.magenta,
|
|
15
|
+
muted: chalk.gray,
|
|
16
|
+
highlight: chalk.white.bold
|
|
17
|
+
};
|
|
9
18
|
export async function loginCommand(options) {
|
|
10
19
|
const config = new CLIConfig();
|
|
11
20
|
await config.init();
|
|
12
|
-
console.log(chalk.blue.bold('🔐
|
|
21
|
+
console.log(chalk.blue.bold('🔐 Onasis-Core Golden Contract Authentication'));
|
|
22
|
+
console.log(colors.info('━'.repeat(50)));
|
|
13
23
|
console.log();
|
|
14
|
-
//
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
console.log(chalk.green('✓ Using API key authentication'));
|
|
18
|
-
await config.setApiKey(apiKey);
|
|
19
|
-
console.log(chalk.green('✓ Authentication configured successfully'));
|
|
24
|
+
// Enhanced authentication flow - check for vendor key first
|
|
25
|
+
if (options.vendorKey) {
|
|
26
|
+
await handleVendorKeyAuth(options.vendorKey, config);
|
|
20
27
|
return;
|
|
21
28
|
}
|
|
22
|
-
//
|
|
23
|
-
const
|
|
29
|
+
// Show authentication options
|
|
30
|
+
const authChoice = await inquirer.prompt([
|
|
24
31
|
{
|
|
25
32
|
type: 'list',
|
|
26
33
|
name: 'method',
|
|
27
34
|
message: 'Choose authentication method:',
|
|
28
35
|
choices: [
|
|
29
|
-
{
|
|
30
|
-
|
|
36
|
+
{
|
|
37
|
+
name: '🔑 Vendor Key (Recommended for API access)',
|
|
38
|
+
value: 'vendor'
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: '🌐 Web OAuth (Browser-based)',
|
|
42
|
+
value: 'oauth'
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: '⚙️ Username/Password (Direct credentials)',
|
|
46
|
+
value: 'credentials'
|
|
47
|
+
}
|
|
31
48
|
]
|
|
32
49
|
}
|
|
33
50
|
]);
|
|
34
|
-
|
|
35
|
-
|
|
51
|
+
switch (authChoice.method) {
|
|
52
|
+
case 'vendor':
|
|
53
|
+
await handleVendorKeyFlow(config);
|
|
54
|
+
break;
|
|
55
|
+
case 'oauth':
|
|
56
|
+
await handleOAuthFlow(config);
|
|
57
|
+
break;
|
|
58
|
+
case 'credentials':
|
|
59
|
+
await handleCredentialsFlow(options, config);
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async function handleVendorKeyAuth(vendorKey, config) {
|
|
64
|
+
const spinner = ora('Validating vendor key...').start();
|
|
65
|
+
try {
|
|
66
|
+
await config.setVendorKey(vendorKey);
|
|
67
|
+
// Test the vendor key with a health check
|
|
68
|
+
const response = await apiClient.get('/health');
|
|
69
|
+
spinner.succeed('Vendor key authentication successful');
|
|
70
|
+
console.log();
|
|
71
|
+
console.log(chalk.green('✓ Authenticated with vendor key'));
|
|
72
|
+
console.log(colors.info('Ready to use Onasis-Core services'));
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
spinner.fail('Vendor key validation failed');
|
|
76
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
77
|
+
console.error(chalk.red('✖ Invalid vendor key:'), errorMessage);
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
async function handleVendorKeyFlow(config) {
|
|
82
|
+
console.log();
|
|
83
|
+
console.log(chalk.yellow('🔑 Vendor Key Authentication'));
|
|
84
|
+
console.log(chalk.gray('Vendor keys provide secure API access with format: pk_xxx.sk_xxx'));
|
|
85
|
+
console.log();
|
|
86
|
+
const { vendorKey } = await inquirer.prompt([
|
|
87
|
+
{
|
|
88
|
+
type: 'password',
|
|
89
|
+
name: 'vendorKey',
|
|
90
|
+
message: 'Enter your vendor key (pk_xxx.sk_xxx):',
|
|
91
|
+
mask: '*',
|
|
92
|
+
validate: (input) => {
|
|
93
|
+
if (!input)
|
|
94
|
+
return 'Vendor key is required';
|
|
95
|
+
if (!input.match(/^pk_[a-zA-Z0-9]+\.sk_[a-zA-Z0-9]+$/)) {
|
|
96
|
+
return 'Invalid format. Expected: pk_xxx.sk_xxx';
|
|
97
|
+
}
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
]);
|
|
102
|
+
await handleVendorKeyAuth(vendorKey, config);
|
|
103
|
+
}
|
|
104
|
+
async function handleOAuthFlow(config) {
|
|
105
|
+
console.log();
|
|
106
|
+
console.log(chalk.yellow('🌐 Web OAuth Authentication'));
|
|
107
|
+
console.log(chalk.gray('This will open your browser for secure authentication'));
|
|
108
|
+
console.log();
|
|
109
|
+
const { proceed } = await inquirer.prompt([
|
|
110
|
+
{
|
|
111
|
+
type: 'confirm',
|
|
112
|
+
name: 'proceed',
|
|
113
|
+
message: 'Open browser for authentication?',
|
|
114
|
+
default: true
|
|
115
|
+
}
|
|
116
|
+
]);
|
|
117
|
+
if (!proceed) {
|
|
118
|
+
console.log(chalk.yellow('Authentication cancelled'));
|
|
36
119
|
return;
|
|
37
120
|
}
|
|
38
|
-
|
|
121
|
+
const authUrl = `${config.getDiscoveredApiUrl()}/auth/cli-login`;
|
|
122
|
+
try {
|
|
123
|
+
console.log(colors.info('Opening browser...'));
|
|
124
|
+
await open(authUrl);
|
|
125
|
+
console.log();
|
|
126
|
+
console.log(colors.info('Please complete authentication in your browser'));
|
|
127
|
+
console.log(colors.muted(`If browser doesn't open, visit: ${authUrl}`));
|
|
128
|
+
// TODO: Implement OAuth callback handling or polling mechanism
|
|
129
|
+
const { token } = await inquirer.prompt([
|
|
130
|
+
{
|
|
131
|
+
type: 'input',
|
|
132
|
+
name: 'token',
|
|
133
|
+
message: 'Paste the authentication token from browser:'
|
|
134
|
+
}
|
|
135
|
+
]);
|
|
136
|
+
if (token) {
|
|
137
|
+
await config.setToken(token);
|
|
138
|
+
console.log(chalk.green('✓ OAuth authentication successful'));
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
console.error(chalk.red('✖ Failed to open browser'));
|
|
143
|
+
console.log(colors.muted(`Please visit manually: ${authUrl}`));
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
async function handleCredentialsFlow(options, config) {
|
|
147
|
+
console.log();
|
|
148
|
+
console.log(chalk.yellow('⚙️ Username/Password Authentication'));
|
|
149
|
+
console.log();
|
|
39
150
|
let { email, password } = options;
|
|
40
151
|
// Get credentials if not provided
|
|
41
152
|
if (!email || !password) {
|
|
@@ -159,125 +270,3 @@ async function registerFlow(defaultEmail) {
|
|
|
159
270
|
process.exit(1);
|
|
160
271
|
}
|
|
161
272
|
}
|
|
162
|
-
async function oauthLoginFlow(config) {
|
|
163
|
-
console.log(chalk.blue('🌐 OAuth Authentication'));
|
|
164
|
-
console.log(chalk.gray('This will open your browser for secure authentication'));
|
|
165
|
-
console.log();
|
|
166
|
-
const port = 3721; // CLI callback port
|
|
167
|
-
const redirectUri = `http://localhost:${port}/callback`;
|
|
168
|
-
const state = Math.random().toString(36).substring(2, 15);
|
|
169
|
-
// Construct OAuth URL
|
|
170
|
-
const authUrl = new URL('https://api.lanonasis.com/v1/auth/oauth');
|
|
171
|
-
authUrl.searchParams.set('redirect_uri', redirectUri);
|
|
172
|
-
authUrl.searchParams.set('state', state);
|
|
173
|
-
authUrl.searchParams.set('project_scope', 'maas');
|
|
174
|
-
authUrl.searchParams.set('response_type', 'code');
|
|
175
|
-
const spinner = ora('Starting OAuth flow...').start();
|
|
176
|
-
try {
|
|
177
|
-
// Start local callback server
|
|
178
|
-
const server = createServer();
|
|
179
|
-
let authCode = null;
|
|
180
|
-
let authError = null;
|
|
181
|
-
server.on('request', (req, res) => {
|
|
182
|
-
const url = new URL(req.url, `http://localhost:${port}`);
|
|
183
|
-
if (url.pathname === '/callback') {
|
|
184
|
-
const code = url.searchParams.get('code');
|
|
185
|
-
const error = url.searchParams.get('error');
|
|
186
|
-
const returnedState = url.searchParams.get('state');
|
|
187
|
-
// Validate state parameter
|
|
188
|
-
if (returnedState !== state) {
|
|
189
|
-
authError = 'Invalid state parameter';
|
|
190
|
-
res.writeHead(400, { 'Content-Type': 'text/html' });
|
|
191
|
-
res.end('<h1>Authentication Failed</h1><p>Invalid state parameter</p>');
|
|
192
|
-
return;
|
|
193
|
-
}
|
|
194
|
-
if (error) {
|
|
195
|
-
authError = url.searchParams.get('error_description') || error;
|
|
196
|
-
res.writeHead(400, { 'Content-Type': 'text/html' });
|
|
197
|
-
res.end(`<h1>Authentication Failed</h1><p>${authError}</p>`);
|
|
198
|
-
}
|
|
199
|
-
else if (code) {
|
|
200
|
-
authCode = code;
|
|
201
|
-
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
202
|
-
res.end('<h1>Authentication Successful</h1><p>You can close this window and return to the CLI.</p>');
|
|
203
|
-
}
|
|
204
|
-
else {
|
|
205
|
-
authError = 'No authorization code received';
|
|
206
|
-
res.writeHead(400, { 'Content-Type': 'text/html' });
|
|
207
|
-
res.end('<h1>Authentication Failed</h1><p>No authorization code received</p>');
|
|
208
|
-
}
|
|
209
|
-
server.close();
|
|
210
|
-
}
|
|
211
|
-
});
|
|
212
|
-
// Start server
|
|
213
|
-
await new Promise((resolve, reject) => {
|
|
214
|
-
server.listen(port, (err) => {
|
|
215
|
-
if (err)
|
|
216
|
-
reject(err);
|
|
217
|
-
else
|
|
218
|
-
resolve();
|
|
219
|
-
});
|
|
220
|
-
});
|
|
221
|
-
spinner.text = 'Opening browser for authentication...';
|
|
222
|
-
// Open browser
|
|
223
|
-
await open(authUrl.toString());
|
|
224
|
-
console.log();
|
|
225
|
-
console.log(chalk.yellow('Browser opened for authentication'));
|
|
226
|
-
console.log(chalk.gray(`If browser doesn't open, visit: ${authUrl.toString()}`));
|
|
227
|
-
console.log();
|
|
228
|
-
spinner.text = 'Waiting for authentication...';
|
|
229
|
-
// Wait for callback
|
|
230
|
-
await new Promise((resolve, reject) => {
|
|
231
|
-
server.on('close', () => {
|
|
232
|
-
if (authCode)
|
|
233
|
-
resolve();
|
|
234
|
-
else
|
|
235
|
-
reject(new Error(authError || 'Authentication failed'));
|
|
236
|
-
});
|
|
237
|
-
// Timeout after 5 minutes
|
|
238
|
-
setTimeout(() => {
|
|
239
|
-
server.close();
|
|
240
|
-
reject(new Error('Authentication timeout'));
|
|
241
|
-
}, 300000);
|
|
242
|
-
});
|
|
243
|
-
if (!authCode) {
|
|
244
|
-
throw new Error(authError || 'No authorization code received');
|
|
245
|
-
}
|
|
246
|
-
spinner.text = 'Exchanging authorization code for session...';
|
|
247
|
-
// Exchange code for session
|
|
248
|
-
const response = await fetch('https://api.lanonasis.com/v1/auth/callback', {
|
|
249
|
-
method: 'POST',
|
|
250
|
-
headers: {
|
|
251
|
-
'Content-Type': 'application/json',
|
|
252
|
-
'x-project-scope': 'maas'
|
|
253
|
-
},
|
|
254
|
-
body: JSON.stringify({
|
|
255
|
-
code: authCode,
|
|
256
|
-
state: state,
|
|
257
|
-
project_scope: 'maas'
|
|
258
|
-
}),
|
|
259
|
-
credentials: 'include'
|
|
260
|
-
});
|
|
261
|
-
if (!response.ok) {
|
|
262
|
-
const errorData = await response.json().catch(() => ({ error: 'Unknown error' }));
|
|
263
|
-
throw new Error(errorData.error || `HTTP ${response.status}`);
|
|
264
|
-
}
|
|
265
|
-
const sessionData = await response.json();
|
|
266
|
-
// Store session token
|
|
267
|
-
await config.setToken(sessionData.access_token);
|
|
268
|
-
spinner.succeed('OAuth authentication successful');
|
|
269
|
-
console.log();
|
|
270
|
-
console.log(chalk.green('✓ Authenticated successfully via OAuth'));
|
|
271
|
-
console.log(`Welcome, ${sessionData.user.email}!`);
|
|
272
|
-
if (sessionData.user.organization_id) {
|
|
273
|
-
console.log(`Organization: ${sessionData.user.organization_id}`);
|
|
274
|
-
}
|
|
275
|
-
console.log(`Plan: ${sessionData.user.plan || 'free'}`);
|
|
276
|
-
}
|
|
277
|
-
catch (error) {
|
|
278
|
-
spinner.fail('OAuth authentication failed');
|
|
279
|
-
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
280
|
-
console.error(chalk.red('✖ OAuth failed:'), errorMessage);
|
|
281
|
-
process.exit(1);
|
|
282
|
-
}
|
|
283
|
-
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export interface CompletionData {
|
|
2
|
+
commands: Array<{
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
aliases?: string[];
|
|
6
|
+
subcommands?: Array<{
|
|
7
|
+
name: string;
|
|
8
|
+
description: string;
|
|
9
|
+
options?: Array<{
|
|
10
|
+
name: string;
|
|
11
|
+
description: string;
|
|
12
|
+
type: 'string' | 'boolean' | 'number' | 'choice';
|
|
13
|
+
choices?: string[];
|
|
14
|
+
required?: boolean;
|
|
15
|
+
}>;
|
|
16
|
+
}>;
|
|
17
|
+
}>;
|
|
18
|
+
globalOptions: Array<{
|
|
19
|
+
name: string;
|
|
20
|
+
description: string;
|
|
21
|
+
type: 'string' | 'boolean' | 'number' | 'choice';
|
|
22
|
+
choices?: string[];
|
|
23
|
+
}>;
|
|
24
|
+
contextualData: {
|
|
25
|
+
memoryTypes: string[];
|
|
26
|
+
outputFormats: string[];
|
|
27
|
+
sortOptions: string[];
|
|
28
|
+
authMethods: string[];
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export declare function generateCompletionData(): Promise<CompletionData>;
|
|
32
|
+
export declare function completionCommand(): Promise<void>;
|
|
33
|
+
export declare function installCompletionsCommand(): Promise<void>;
|