@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.
Files changed (37) hide show
  1. package/README.md +284 -586
  2. package/dist/commands/api-keys.d.ts +3 -0
  3. package/dist/commands/api-keys.js +812 -0
  4. package/dist/commands/auth.d.ts +2 -0
  5. package/dist/commands/auth.js +127 -138
  6. package/dist/commands/completion.d.ts +33 -0
  7. package/dist/commands/completion.js +378 -0
  8. package/dist/commands/guide.d.ts +19 -0
  9. package/dist/commands/guide.js +446 -0
  10. package/dist/commands/mcp.js +30 -37
  11. package/dist/commands/memory.js +53 -78
  12. package/dist/completions/bash-completion.sh +88 -0
  13. package/dist/completions/fish-completion.fish +132 -0
  14. package/dist/completions/zsh-completion.zsh +196 -0
  15. package/dist/index-simple.js +633 -183
  16. package/dist/index.js +327 -221
  17. package/dist/mcp-server.d.ts +38 -0
  18. package/dist/mcp-server.js +154 -0
  19. package/dist/utils/api.d.ts +12 -2
  20. package/dist/utils/api.js +38 -4
  21. package/dist/utils/config.d.ts +5 -2
  22. package/dist/utils/config.js +39 -15
  23. package/dist/utils/formatting.d.ts +2 -0
  24. package/dist/utils/formatting.js +13 -0
  25. package/dist/utils/mcp-client.d.ts +49 -6
  26. package/dist/utils/mcp-client.js +159 -82
  27. package/package.json +22 -12
  28. package/dist/utils/completions.d.ts +0 -28
  29. package/dist/utils/completions.js +0 -276
  30. package/dist/utils/mcp-client.test.d.ts +0 -1
  31. package/dist/utils/mcp-client.test.js +0 -125
  32. package/dist/utils/output.d.ts +0 -23
  33. package/dist/utils/output.js +0 -97
  34. package/dist/utils/websocket-mcp-client.d.ts +0 -60
  35. package/dist/utils/websocket-mcp-client.js +0 -182
  36. package/dist/utils/websocket-mcp-client.test.d.ts +0 -1
  37. package/dist/utils/websocket-mcp-client.test.js +0 -126
@@ -1,276 +0,0 @@
1
- import chalk from 'chalk';
2
- import { CLIConfig } from './config.js';
3
- export class TabCompletions {
4
- config;
5
- completionData;
6
- constructor() {
7
- this.config = new CLIConfig();
8
- this.completionData = {
9
- commands: [
10
- 'auth', 'login', 'logout', 'status',
11
- 'memory', 'mem', 'create', 'search', 'list', 'get', 'update', 'delete',
12
- 'topic', 'topics', 'org', 'organization',
13
- 'config', 'mcp', 'init', 'docs', 'help'
14
- ],
15
- memory: {
16
- types: ['context', 'project', 'knowledge', 'reference', 'personal', 'workflow'],
17
- tags: [],
18
- recentIds: []
19
- },
20
- topics: [],
21
- organizations: []
22
- };
23
- }
24
- async init() {
25
- await this.config.init();
26
- await this.loadDynamicCompletions();
27
- }
28
- async loadDynamicCompletions() {
29
- const isAuth = await this.config.isAuthenticated();
30
- if (!isAuth)
31
- return;
32
- try {
33
- // Load recent memory IDs, tags, topics from API
34
- // This would be enhanced with actual API calls
35
- await this.loadRecentMemories();
36
- await this.loadTopics();
37
- await this.loadTags();
38
- }
39
- catch (error) {
40
- // Fail silently for completions
41
- if (process.env.CLI_VERBOSE === 'true') {
42
- console.error(chalk.gray('Failed to load completions data'));
43
- }
44
- }
45
- }
46
- async loadRecentMemories() {
47
- // This would call the API to get recent memory IDs
48
- // For now, we'll use mock data
49
- this.completionData.memory.recentIds = [
50
- 'mem_12345', 'mem_67890', 'mem_abcdef'
51
- ];
52
- }
53
- async loadTopics() {
54
- // This would call the API to get user's topics
55
- this.completionData.topics = [
56
- 'work', 'personal', 'learning', 'projects'
57
- ];
58
- }
59
- async loadTags() {
60
- // This would call the API to get commonly used tags
61
- this.completionData.memory.tags = [
62
- 'important', 'todo', 'reference', 'meeting', 'idea'
63
- ];
64
- }
65
- getCompletions(line, position) {
66
- const words = line.trim().split(/\s+/);
67
- const currentWord = words[words.length - 1] || '';
68
- // If we're at the beginning or after a space, suggest commands
69
- if (words.length <= 1 || line.endsWith(' ')) {
70
- return this.completionData.commands.filter(cmd => cmd.startsWith(currentWord.toLowerCase()));
71
- }
72
- const command = words[0];
73
- const subcommand = words[1];
74
- // Context-aware completions
75
- switch (command) {
76
- case 'memory':
77
- case 'mem':
78
- return this.getMemoryCompletions(words, currentWord);
79
- case 'topic':
80
- case 'topics':
81
- return this.getTopicCompletions(words, currentWord);
82
- case 'auth':
83
- return ['login', 'logout', 'status'].filter(cmd => cmd.startsWith(currentWord));
84
- case 'config':
85
- return ['show', 'set', 'get', 'reset'].filter(cmd => cmd.startsWith(currentWord));
86
- default:
87
- return [];
88
- }
89
- }
90
- getMemoryCompletions(words, currentWord) {
91
- if (words.length === 2) {
92
- // Memory subcommands
93
- return ['create', 'search', 'list', 'get', 'update', 'delete', 'stats']
94
- .filter(cmd => cmd.startsWith(currentWord));
95
- }
96
- const subcommand = words[1];
97
- switch (subcommand) {
98
- case 'create':
99
- return this.getCreateCompletions(words, currentWord);
100
- case 'search':
101
- return this.getSearchCompletions(words, currentWord);
102
- case 'list':
103
- return this.getListCompletions(words, currentWord);
104
- case 'get':
105
- case 'update':
106
- case 'delete':
107
- return this.completionData.memory.recentIds.filter(id => id.startsWith(currentWord));
108
- default:
109
- return [];
110
- }
111
- }
112
- getCreateCompletions(words, currentWord) {
113
- // Look for flags
114
- const prevWord = words[words.length - 2];
115
- if (prevWord === '--type' || prevWord === '-t') {
116
- return this.completionData.memory.types.filter(type => type.startsWith(currentWord));
117
- }
118
- if (prevWord === '--tags') {
119
- return this.completionData.memory.tags.filter(tag => tag.startsWith(currentWord));
120
- }
121
- // Suggest flags
122
- if (currentWord.startsWith('-')) {
123
- return ['--title', '--content', '--type', '--tags', '--topic']
124
- .filter(flag => flag.startsWith(currentWord));
125
- }
126
- return [];
127
- }
128
- getSearchCompletions(words, currentWord) {
129
- const prevWord = words[words.length - 2];
130
- if (prevWord === '--type') {
131
- return this.completionData.memory.types.filter(type => type.startsWith(currentWord));
132
- }
133
- if (prevWord === '--topic') {
134
- return this.completionData.topics.filter(topic => topic.startsWith(currentWord));
135
- }
136
- if (currentWord.startsWith('-')) {
137
- return ['--limit', '--type', '--topic', '--tags']
138
- .filter(flag => flag.startsWith(currentWord));
139
- }
140
- return [];
141
- }
142
- getListCompletions(words, currentWord) {
143
- const prevWord = words[words.length - 2];
144
- if (prevWord === '--type') {
145
- return this.completionData.memory.types.filter(type => type.startsWith(currentWord));
146
- }
147
- if (currentWord.startsWith('-')) {
148
- return ['--limit', '--type', '--topic', '--tags']
149
- .filter(flag => flag.startsWith(currentWord));
150
- }
151
- return [];
152
- }
153
- getTopicCompletions(words, currentWord) {
154
- if (words.length === 2) {
155
- return ['list', 'create', 'get', 'update', 'delete']
156
- .filter(cmd => cmd.startsWith(currentWord));
157
- }
158
- const subcommand = words[1];
159
- if (['get', 'update', 'delete'].includes(subcommand)) {
160
- return this.completionData.topics.filter(topic => topic.startsWith(currentWord));
161
- }
162
- return [];
163
- }
164
- // Generate shell completion scripts
165
- generateBashCompletion() {
166
- return `
167
- _lanonasis_completion() {
168
- local cur prev opts
169
- COMPREPLY=()
170
- cur="\${COMP_WORDS[COMP_CWORD]}"
171
- prev="\${COMP_WORDS[COMP_CWORD-1]}"
172
-
173
- # Basic command completion
174
- if [[ \${COMP_CWORD} == 1 ]] ; then
175
- opts="auth login logout status memory mem topic topics config mcp init docs help"
176
- COMPREPLY=( \$(compgen -W "\${opts}" -- \${cur}) )
177
- return 0
178
- fi
179
-
180
- # Memory subcommands
181
- if [[ \${COMP_WORDS[1]} == "memory" || \${COMP_WORDS[1]} == "mem" ]] ; then
182
- if [[ \${COMP_CWORD} == 2 ]] ; then
183
- opts="create search list get update delete stats"
184
- COMPREPLY=( \$(compgen -W "\${opts}" -- \${cur}) )
185
- return 0
186
- fi
187
- fi
188
-
189
- # Topic subcommands
190
- if [[ \${COMP_WORDS[1]} == "topic" || \${COMP_WORDS[1]} == "topics" ]] ; then
191
- if [[ \${COMP_CWORD} == 2 ]] ; then
192
- opts="list create get update delete"
193
- COMPREPLY=( \$(compgen -W "\${opts}" -- \${cur}) )
194
- return 0
195
- fi
196
- fi
197
- }
198
-
199
- complete -F _lanonasis_completion lanonasis onasis memory maas
200
- `;
201
- }
202
- generateZshCompletion() {
203
- return `
204
- #compdef lanonasis onasis memory maas
205
-
206
- _lanonasis() {
207
- local context state line
208
- typeset -A opt_args
209
-
210
- _arguments -C \\
211
- '1: :_lanonasis_commands' \\
212
- '*::arg:->args'
213
-
214
- case $state in
215
- args)
216
- case $words[1] in
217
- memory|mem)
218
- _lanonasis_memory
219
- ;;
220
- topic|topics)
221
- _lanonasis_topic
222
- ;;
223
- auth)
224
- _arguments \\
225
- '1:(login logout status)'
226
- ;;
227
- esac
228
- ;;
229
- esac
230
- }
231
-
232
- _lanonasis_commands() {
233
- local commands
234
- commands=(
235
- 'auth:Authentication commands'
236
- 'memory:Memory management'
237
- 'topic:Topic management'
238
- 'config:Configuration'
239
- 'mcp:MCP server management'
240
- 'init:Initialize CLI'
241
- 'docs:Open documentation'
242
- 'help:Show help'
243
- )
244
- _describe 'commands' commands
245
- }
246
-
247
- _lanonasis_memory() {
248
- local subcommands
249
- subcommands=(
250
- 'create:Create new memory'
251
- 'search:Search memories'
252
- 'list:List memories'
253
- 'get:Get specific memory'
254
- 'update:Update memory'
255
- 'delete:Delete memory'
256
- 'stats:Memory statistics'
257
- )
258
- _describe 'memory commands' subcommands
259
- }
260
-
261
- _lanonasis_topic() {
262
- local subcommands
263
- subcommands=(
264
- 'list:List topics'
265
- 'create:Create topic'
266
- 'get:Get topic'
267
- 'update:Update topic'
268
- 'delete:Delete topic'
269
- )
270
- _describe 'topic commands' subcommands
271
- }
272
-
273
- _lanonasis
274
- `;
275
- }
276
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,125 +0,0 @@
1
- import { describe, it, expect, beforeEach } from 'bun:test';
2
- import { MCPClient } from './mcp-client';
3
- describe('MCPClient', () => {
4
- let client;
5
- beforeEach(() => {
6
- client = new MCPClient();
7
- });
8
- describe('constructor', () => {
9
- it('should create client instance', () => {
10
- expect(client).toBeDefined();
11
- expect(client.isConnected()).toBe(false);
12
- });
13
- });
14
- describe('connection modes', () => {
15
- it('should support local connection mode', async () => {
16
- const result = await client.connect({ mode: 'local' });
17
- // Local mode may fail without actual server, but should not throw
18
- expect(typeof result).toBe('boolean');
19
- });
20
- it('should support remote connection mode', async () => {
21
- const result = await client.connect({ mode: 'remote' });
22
- // Remote mode may fail without credentials, but should not throw
23
- expect(typeof result).toBe('boolean');
24
- });
25
- it('should support websocket connection mode', async () => {
26
- const result = await client.connect({ mode: 'websocket' });
27
- // WebSocket mode may fail without server, but should not throw
28
- expect(typeof result).toBe('boolean');
29
- });
30
- });
31
- describe('connection options', () => {
32
- it('should handle server path option', async () => {
33
- const options = {
34
- mode: 'local',
35
- serverPath: '/custom/path/to/server'
36
- };
37
- const result = await client.connect(options);
38
- expect(typeof result).toBe('boolean');
39
- });
40
- it('should handle server URL option', async () => {
41
- const options = {
42
- mode: 'websocket',
43
- serverUrl: 'ws://custom.server.com:8081'
44
- };
45
- const result = await client.connect(options);
46
- expect(typeof result).toBe('boolean');
47
- });
48
- });
49
- describe('tool operations', () => {
50
- it('should handle list tools request', async () => {
51
- // Mock successful connection first
52
- client.isConnected = () => true;
53
- try {
54
- const tools = await client.listTools();
55
- expect(Array.isArray(tools)).toBe(true);
56
- }
57
- catch (error) {
58
- // Expected if no actual connection
59
- expect(error).toBeDefined();
60
- }
61
- });
62
- it('should handle call tool request', async () => {
63
- // Mock successful connection first
64
- client.isConnected = () => true;
65
- try {
66
- const result = await client.callTool('test_tool', { param: 'value' });
67
- expect(result).toBeDefined();
68
- }
69
- catch (error) {
70
- // Expected if no actual connection
71
- expect(error).toBeDefined();
72
- }
73
- });
74
- });
75
- describe('memory operations', () => {
76
- it('should handle create memory request', async () => {
77
- // Mock successful connection first
78
- client.isConnected = () => true;
79
- try {
80
- const result = await client.createMemory({
81
- title: 'Test Memory',
82
- content: 'Test content',
83
- tags: ['test']
84
- });
85
- expect(result).toBeDefined();
86
- }
87
- catch (error) {
88
- // Expected if no actual connection
89
- expect(error).toBeDefined();
90
- }
91
- });
92
- it('should handle search memories request', async () => {
93
- // Mock successful connection first
94
- client.isConnected = () => true;
95
- try {
96
- const result = await client.searchMemories({
97
- query: 'test query',
98
- limit: 10
99
- });
100
- expect(result).toBeDefined();
101
- }
102
- catch (error) {
103
- // Expected if no actual connection
104
- expect(error).toBeDefined();
105
- }
106
- });
107
- });
108
- describe('error handling', () => {
109
- it('should handle connection failures gracefully', async () => {
110
- const result = await client.connect({
111
- mode: 'websocket',
112
- serverUrl: 'ws://nonexistent.server:9999'
113
- });
114
- expect(result).toBe(false);
115
- });
116
- it('should handle invalid connection modes', async () => {
117
- try {
118
- await client.connect({ mode: 'invalid' });
119
- }
120
- catch (error) {
121
- expect(error).toBeDefined();
122
- }
123
- });
124
- });
125
- });
@@ -1,23 +0,0 @@
1
- export interface OutputOptions {
2
- format?: string;
3
- silent?: boolean;
4
- json?: boolean;
5
- }
6
- export declare class OutputManager {
7
- private static instance;
8
- private options;
9
- static getInstance(): OutputManager;
10
- setOptions(options: OutputOptions): void;
11
- isJsonOutput(): boolean;
12
- isSilent(): boolean;
13
- log(...args: any[]): void;
14
- error(...args: any[]): void;
15
- json(data: any): void;
16
- table(data: any[]): void;
17
- success(message: string): void;
18
- warning(message: string): void;
19
- info(message: string): void;
20
- }
21
- export declare const output: OutputManager;
22
- export declare function showOutput(format?: string): boolean;
23
- export declare function formatOutput(data: any, format?: string): string;
@@ -1,97 +0,0 @@
1
- import chalk from 'chalk';
2
- export class OutputManager {
3
- static instance;
4
- options = {};
5
- static getInstance() {
6
- if (!OutputManager.instance) {
7
- OutputManager.instance = new OutputManager();
8
- }
9
- return OutputManager.instance;
10
- }
11
- setOptions(options) {
12
- this.options = { ...this.options, ...options };
13
- }
14
- isJsonOutput() {
15
- return this.options.format === 'json' ||
16
- this.options.json === true ||
17
- process.env.CLI_OUTPUT_FORMAT === 'json';
18
- }
19
- isSilent() {
20
- return this.options.silent === true ||
21
- this.isJsonOutput() ||
22
- process.env.CLI_SILENT === 'true';
23
- }
24
- log(...args) {
25
- if (!this.isSilent()) {
26
- console.log(...args);
27
- }
28
- }
29
- error(...args) {
30
- if (this.isJsonOutput()) {
31
- console.error(JSON.stringify({
32
- error: true,
33
- message: args.join(' ').replace(/\x1b\[[0-9;]*m/g, '') // Strip ANSI codes
34
- }));
35
- }
36
- else {
37
- console.error(...args);
38
- }
39
- }
40
- json(data) {
41
- console.log(JSON.stringify(data, null, 2));
42
- }
43
- table(data) {
44
- if (this.isJsonOutput()) {
45
- this.json(data);
46
- }
47
- else {
48
- console.table(data);
49
- }
50
- }
51
- success(message) {
52
- if (this.isJsonOutput()) {
53
- this.json({ success: true, message });
54
- }
55
- else {
56
- this.log(chalk.green('✓'), message);
57
- }
58
- }
59
- warning(message) {
60
- if (this.isJsonOutput()) {
61
- this.json({ warning: true, message });
62
- }
63
- else {
64
- this.log(chalk.yellow('⚠️'), message);
65
- }
66
- }
67
- info(message) {
68
- if (!this.isSilent()) {
69
- if (this.isJsonOutput()) {
70
- this.json({ info: true, message });
71
- }
72
- else {
73
- this.log(chalk.blue('ℹ'), message);
74
- }
75
- }
76
- }
77
- }
78
- export const output = OutputManager.getInstance();
79
- // Helper to conditionally show output
80
- export function showOutput(format) {
81
- return format !== 'json' && process.env.CLI_OUTPUT_FORMAT !== 'json';
82
- }
83
- // Helper to format output based on format
84
- export function formatOutput(data, format) {
85
- const outputFormat = format || process.env.CLI_OUTPUT_FORMAT || 'table';
86
- switch (outputFormat) {
87
- case 'json':
88
- return JSON.stringify(data, null, 2);
89
- case 'yaml':
90
- // Simple YAML-like format
91
- return Object.entries(data)
92
- .map(([key, value]) => `${key}: ${JSON.stringify(value)}`)
93
- .join('\n');
94
- default:
95
- return data;
96
- }
97
- }
@@ -1,60 +0,0 @@
1
- /**
2
- * WebSocket MCP Client for Enterprise Connections
3
- * Connects to mcp.lanonasis.com WebSocket server for real-time MCP operations
4
- */
5
- import { EventEmitter } from 'events';
6
- export interface MCPParams {
7
- [key: string]: unknown;
8
- }
9
- export interface MCPResult {
10
- [key: string]: unknown;
11
- }
12
- export interface MCPError {
13
- code: number;
14
- message: string;
15
- data?: unknown;
16
- }
17
- export interface MCPMessage {
18
- id?: string;
19
- type: 'request' | 'response' | 'notification' | 'error';
20
- method?: string;
21
- params?: MCPParams;
22
- result?: MCPResult;
23
- error?: MCPError;
24
- }
25
- export interface WebSocketMCPClientOptions {
26
- url?: string;
27
- apiKey: string;
28
- reconnectInterval?: number;
29
- maxReconnectAttempts?: number;
30
- timeout?: number;
31
- }
32
- export declare class WebSocketMCPClient extends EventEmitter {
33
- private ws;
34
- private url;
35
- private apiKey;
36
- private reconnectInterval;
37
- private maxReconnectAttempts;
38
- private timeout;
39
- private reconnectAttempts;
40
- private isConnected;
41
- private messageId;
42
- private pendingRequests;
43
- constructor(options: WebSocketMCPClientOptions);
44
- connect(): Promise<void>;
45
- private handleMessage;
46
- sendRequest(method: string, params?: MCPParams): Promise<MCPResult>;
47
- listTools(): Promise<MCPResult>;
48
- callTool(name: string, arguments_?: MCPParams): Promise<MCPResult>;
49
- deleteMemory(id: string): Promise<MCPResult>;
50
- searchMemories(args: MCPParams): Promise<MCPResult>;
51
- listResources(): Promise<MCPResult>;
52
- getMemories(query?: string): Promise<MCPResult>;
53
- disconnect(): void;
54
- getConnectionStatus(): {
55
- connected: boolean;
56
- url: string;
57
- reconnectAttempts: number;
58
- pendingRequests: number;
59
- };
60
- }