@lanonasis/cli 3.8.0 → 3.9.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/CHANGELOG.md +195 -0
- package/README.md +65 -2
- package/dist/commands/auth.js +1 -1
- package/dist/commands/config.js +3 -2
- package/dist/commands/init.js +12 -0
- package/dist/commands/mcp.js +50 -3
- package/dist/commands/memory.js +49 -23
- package/dist/index.js +20 -0
- package/dist/mcp/access-control.js +2 -2
- package/dist/mcp/schemas/tool-schemas.d.ts +4 -4
- package/dist/mcp/server/lanonasis-server.js +26 -3
- package/dist/utils/api.js +10 -10
- package/dist/utils/config.js +40 -6
- package/dist/utils/mcp-client.d.ts +2 -0
- package/dist/utils/mcp-client.js +33 -15
- package/dist/ux/implementations/ConnectionManagerImpl.d.ts +72 -0
- package/dist/ux/implementations/ConnectionManagerImpl.js +352 -0
- package/dist/ux/implementations/OnboardingFlowImpl.d.ts +72 -0
- package/dist/ux/implementations/OnboardingFlowImpl.js +415 -0
- package/dist/ux/implementations/TextInputHandlerImpl.d.ts +74 -0
- package/dist/ux/implementations/TextInputHandlerImpl.js +342 -0
- package/dist/ux/implementations/index.d.ts +11 -0
- package/dist/ux/implementations/index.js +11 -0
- package/dist/ux/index.d.ts +15 -0
- package/dist/ux/index.js +22 -0
- package/dist/ux/interfaces/ConnectionManager.d.ts +112 -0
- package/dist/ux/interfaces/ConnectionManager.js +7 -0
- package/dist/ux/interfaces/OnboardingFlow.d.ts +103 -0
- package/dist/ux/interfaces/OnboardingFlow.js +7 -0
- package/dist/ux/interfaces/TextInputHandler.d.ts +87 -0
- package/dist/ux/interfaces/TextInputHandler.js +7 -0
- package/dist/ux/interfaces/index.d.ts +10 -0
- package/dist/ux/interfaces/index.js +8 -0
- package/package.json +34 -4
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Text Input Handler Implementation
|
|
3
|
+
*
|
|
4
|
+
* Provides seamless multi-line text input without external editors
|
|
5
|
+
* Implementation of the TextInputHandler interface.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Default input options for the text input handler
|
|
9
|
+
*/
|
|
10
|
+
const DEFAULT_INPUT_OPTIONS = {
|
|
11
|
+
placeholder: 'Enter your text (Ctrl+D to finish, Ctrl+C to cancel):',
|
|
12
|
+
maxLines: 100,
|
|
13
|
+
submitKeys: ['ctrl+d'],
|
|
14
|
+
cancelKeys: ['ctrl+c'],
|
|
15
|
+
showLineNumbers: true,
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* TextInputHandlerImpl provides seamless multi-line text input without external editors
|
|
19
|
+
*
|
|
20
|
+
* This implementation uses process.stdin.setRawMode(true) to capture individual keystrokes
|
|
21
|
+
* and handles special characters manually to provide a smooth editing experience.
|
|
22
|
+
*/
|
|
23
|
+
export class TextInputHandlerImpl {
|
|
24
|
+
currentSession = null;
|
|
25
|
+
isRawModeEnabled = false;
|
|
26
|
+
originalStdinMode;
|
|
27
|
+
/**
|
|
28
|
+
* Collect multi-line text input from the user
|
|
29
|
+
*/
|
|
30
|
+
async collectMultilineInput(prompt, options) {
|
|
31
|
+
const mergedOptions = { ...DEFAULT_INPUT_OPTIONS, ...options };
|
|
32
|
+
// Initialize content with defaultContent if provided
|
|
33
|
+
const initialContent = mergedOptions.defaultContent
|
|
34
|
+
? mergedOptions.defaultContent.split('\n')
|
|
35
|
+
: [''];
|
|
36
|
+
// Create new input session
|
|
37
|
+
this.currentSession = {
|
|
38
|
+
id: `session_${Date.now()}`,
|
|
39
|
+
prompt,
|
|
40
|
+
content: initialContent,
|
|
41
|
+
cursorPosition: {
|
|
42
|
+
line: initialContent.length - 1,
|
|
43
|
+
column: initialContent[initialContent.length - 1].length
|
|
44
|
+
},
|
|
45
|
+
startTime: new Date(),
|
|
46
|
+
options: mergedOptions,
|
|
47
|
+
status: 'active',
|
|
48
|
+
};
|
|
49
|
+
return new Promise((resolve, reject) => {
|
|
50
|
+
try {
|
|
51
|
+
this.enableRawMode();
|
|
52
|
+
this.displayInputPrompt('');
|
|
53
|
+
const handleKeypress = (chunk) => {
|
|
54
|
+
const key = this.parseKeyEvent(chunk);
|
|
55
|
+
if (this.handleSpecialKeys(key)) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
// Handle regular character input
|
|
59
|
+
if (key.sequence && this.currentSession) {
|
|
60
|
+
this.addCharacterToInput(key.sequence);
|
|
61
|
+
this.displayInputPrompt(this.getCurrentContent());
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
const cleanup = () => {
|
|
65
|
+
process.stdin.removeListener('data', handleKeypress);
|
|
66
|
+
this.disableRawMode();
|
|
67
|
+
};
|
|
68
|
+
// Set up completion handlers
|
|
69
|
+
const complete = (result) => {
|
|
70
|
+
cleanup();
|
|
71
|
+
if (this.currentSession) {
|
|
72
|
+
this.currentSession.status = 'completed';
|
|
73
|
+
}
|
|
74
|
+
resolve(result);
|
|
75
|
+
};
|
|
76
|
+
const cancel = () => {
|
|
77
|
+
cleanup();
|
|
78
|
+
if (this.currentSession) {
|
|
79
|
+
this.currentSession.status = 'cancelled';
|
|
80
|
+
}
|
|
81
|
+
reject(new Error('Input cancelled by user'));
|
|
82
|
+
};
|
|
83
|
+
// Store handlers for special key processing
|
|
84
|
+
this._completeHandler = complete;
|
|
85
|
+
this._cancelHandler = cancel;
|
|
86
|
+
process.stdin.on('data', handleKeypress);
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
this.disableRawMode();
|
|
90
|
+
reject(error);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Enable raw mode for direct keystroke capture
|
|
96
|
+
*/
|
|
97
|
+
enableRawMode() {
|
|
98
|
+
if (!this.isRawModeEnabled && process.stdin.isTTY) {
|
|
99
|
+
this.originalStdinMode = process.stdin.isRaw;
|
|
100
|
+
process.stdin.setRawMode(true);
|
|
101
|
+
this.isRawModeEnabled = true;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Disable raw mode and return to normal terminal behavior
|
|
106
|
+
*/
|
|
107
|
+
disableRawMode() {
|
|
108
|
+
if (this.isRawModeEnabled && process.stdin.isTTY) {
|
|
109
|
+
process.stdin.setRawMode(this.originalStdinMode || false);
|
|
110
|
+
this.isRawModeEnabled = false;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Handle special keyboard events
|
|
115
|
+
*/
|
|
116
|
+
handleSpecialKeys(key) {
|
|
117
|
+
if (!this.currentSession)
|
|
118
|
+
return false;
|
|
119
|
+
const { options } = this.currentSession;
|
|
120
|
+
// Handle submit keys (default: Ctrl+D)
|
|
121
|
+
if (options.submitKeys?.some((submitKey) => this.matchesKey(key, submitKey))) {
|
|
122
|
+
const content = this.getCurrentContent();
|
|
123
|
+
this._completeHandler?.(content);
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
// Handle cancel keys (default: Ctrl+C)
|
|
127
|
+
if (options.cancelKeys?.some((cancelKey) => this.matchesKey(key, cancelKey))) {
|
|
128
|
+
this._cancelHandler?.();
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
// Handle Enter key (new line)
|
|
132
|
+
if (key.name === 'return' || key.name === 'enter') {
|
|
133
|
+
this.addNewLine();
|
|
134
|
+
this.displayInputPrompt(this.getCurrentContent());
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
// Handle Backspace
|
|
138
|
+
if (key.name === 'backspace') {
|
|
139
|
+
this.handleBackspace();
|
|
140
|
+
this.displayInputPrompt(this.getCurrentContent());
|
|
141
|
+
return true;
|
|
142
|
+
}
|
|
143
|
+
// Handle arrow keys
|
|
144
|
+
if (key.name === 'up' || key.name === 'down' || key.name === 'left' || key.name === 'right') {
|
|
145
|
+
this.handleArrowKey(key.name);
|
|
146
|
+
this.displayInputPrompt(this.getCurrentContent());
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Display the input prompt with current content
|
|
153
|
+
*/
|
|
154
|
+
displayInputPrompt(content) {
|
|
155
|
+
if (!this.currentSession)
|
|
156
|
+
return;
|
|
157
|
+
// Clear the screen and move cursor to top
|
|
158
|
+
process.stdout.write('\x1b[2J\x1b[H');
|
|
159
|
+
// Display prompt
|
|
160
|
+
console.log(this.currentSession.prompt);
|
|
161
|
+
console.log('─'.repeat(50));
|
|
162
|
+
// Display content with line numbers if enabled
|
|
163
|
+
const lines = content.split('\n');
|
|
164
|
+
if (this.currentSession.options.showLineNumbers) {
|
|
165
|
+
lines.forEach((line, index) => {
|
|
166
|
+
const lineNum = (index + 1).toString().padStart(3, ' ');
|
|
167
|
+
const cursor = this.currentSession.cursorPosition.line === index ? '→' : ' ';
|
|
168
|
+
console.log(`${lineNum}${cursor} ${line}`);
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
console.log(content);
|
|
173
|
+
}
|
|
174
|
+
// Display help text
|
|
175
|
+
console.log('─'.repeat(50));
|
|
176
|
+
console.log('Ctrl+D to finish, Ctrl+C to cancel, Enter for new line');
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Get the current input session
|
|
180
|
+
*/
|
|
181
|
+
getCurrentSession() {
|
|
182
|
+
return this.currentSession;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Cancel the current input session
|
|
186
|
+
*/
|
|
187
|
+
cancelInput() {
|
|
188
|
+
if (this.currentSession) {
|
|
189
|
+
this.currentSession.status = 'cancelled';
|
|
190
|
+
this._cancelHandler?.();
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Parse raw key event from buffer
|
|
195
|
+
*/
|
|
196
|
+
parseKeyEvent(chunk) {
|
|
197
|
+
const sequence = chunk.toString();
|
|
198
|
+
const key = { sequence };
|
|
199
|
+
// Parse common key combinations
|
|
200
|
+
if (sequence === '\u0003') {
|
|
201
|
+
key.name = 'c';
|
|
202
|
+
key.ctrl = true;
|
|
203
|
+
}
|
|
204
|
+
else if (sequence === '\u0004') {
|
|
205
|
+
key.name = 'd';
|
|
206
|
+
key.ctrl = true;
|
|
207
|
+
}
|
|
208
|
+
else if (sequence === '\r' || sequence === '\n') {
|
|
209
|
+
key.name = 'return';
|
|
210
|
+
}
|
|
211
|
+
else if (sequence === '\u007f' || sequence === '\b') {
|
|
212
|
+
key.name = 'backspace';
|
|
213
|
+
}
|
|
214
|
+
else if (sequence === '\u001b[A') {
|
|
215
|
+
key.name = 'up';
|
|
216
|
+
}
|
|
217
|
+
else if (sequence === '\u001b[B') {
|
|
218
|
+
key.name = 'down';
|
|
219
|
+
}
|
|
220
|
+
else if (sequence === '\u001b[C') {
|
|
221
|
+
key.name = 'right';
|
|
222
|
+
}
|
|
223
|
+
else if (sequence === '\u001b[D') {
|
|
224
|
+
key.name = 'left';
|
|
225
|
+
}
|
|
226
|
+
return key;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Check if a key event matches a key pattern
|
|
230
|
+
*/
|
|
231
|
+
matchesKey(key, pattern) {
|
|
232
|
+
if (pattern.startsWith('ctrl+')) {
|
|
233
|
+
const keyName = pattern.substring(5);
|
|
234
|
+
return key.ctrl === true && key.name === keyName;
|
|
235
|
+
}
|
|
236
|
+
return key.name === pattern;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Add a character to the current input
|
|
240
|
+
*/
|
|
241
|
+
addCharacterToInput(char) {
|
|
242
|
+
if (!this.currentSession)
|
|
243
|
+
return;
|
|
244
|
+
const { cursorPosition, content } = this.currentSession;
|
|
245
|
+
const currentLine = content[cursorPosition.line] || '';
|
|
246
|
+
const newLine = currentLine.slice(0, cursorPosition.column) + char + currentLine.slice(cursorPosition.column);
|
|
247
|
+
content[cursorPosition.line] = newLine;
|
|
248
|
+
cursorPosition.column += char.length;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Add a new line to the input
|
|
252
|
+
*/
|
|
253
|
+
addNewLine() {
|
|
254
|
+
if (!this.currentSession)
|
|
255
|
+
return;
|
|
256
|
+
const { cursorPosition, content, options } = this.currentSession;
|
|
257
|
+
// Check max lines limit
|
|
258
|
+
if (options.maxLines && content.length >= options.maxLines) {
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
const currentLine = content[cursorPosition.line] || '';
|
|
262
|
+
const beforeCursor = currentLine.slice(0, cursorPosition.column);
|
|
263
|
+
const afterCursor = currentLine.slice(cursorPosition.column);
|
|
264
|
+
content[cursorPosition.line] = beforeCursor;
|
|
265
|
+
content.splice(cursorPosition.line + 1, 0, afterCursor);
|
|
266
|
+
cursorPosition.line++;
|
|
267
|
+
cursorPosition.column = 0;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Handle backspace key
|
|
271
|
+
*/
|
|
272
|
+
handleBackspace() {
|
|
273
|
+
if (!this.currentSession)
|
|
274
|
+
return;
|
|
275
|
+
const { cursorPosition, content } = this.currentSession;
|
|
276
|
+
if (cursorPosition.column > 0) {
|
|
277
|
+
// Remove character from current line
|
|
278
|
+
const currentLine = content[cursorPosition.line];
|
|
279
|
+
const newLine = currentLine.slice(0, cursorPosition.column - 1) + currentLine.slice(cursorPosition.column);
|
|
280
|
+
content[cursorPosition.line] = newLine;
|
|
281
|
+
cursorPosition.column--;
|
|
282
|
+
}
|
|
283
|
+
else if (cursorPosition.line > 0) {
|
|
284
|
+
// Merge with previous line
|
|
285
|
+
const currentLine = content[cursorPosition.line];
|
|
286
|
+
const previousLine = content[cursorPosition.line - 1];
|
|
287
|
+
content[cursorPosition.line - 1] = previousLine + currentLine;
|
|
288
|
+
content.splice(cursorPosition.line, 1);
|
|
289
|
+
cursorPosition.line--;
|
|
290
|
+
cursorPosition.column = previousLine.length;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Handle arrow key navigation
|
|
295
|
+
*/
|
|
296
|
+
handleArrowKey(direction) {
|
|
297
|
+
if (!this.currentSession)
|
|
298
|
+
return;
|
|
299
|
+
const { cursorPosition, content } = this.currentSession;
|
|
300
|
+
switch (direction) {
|
|
301
|
+
case 'up':
|
|
302
|
+
if (cursorPosition.line > 0) {
|
|
303
|
+
cursorPosition.line--;
|
|
304
|
+
const newLineLength = content[cursorPosition.line]?.length || 0;
|
|
305
|
+
cursorPosition.column = Math.min(cursorPosition.column, newLineLength);
|
|
306
|
+
}
|
|
307
|
+
break;
|
|
308
|
+
case 'down':
|
|
309
|
+
if (cursorPosition.line < content.length - 1) {
|
|
310
|
+
cursorPosition.line++;
|
|
311
|
+
const newLineLength = content[cursorPosition.line]?.length || 0;
|
|
312
|
+
cursorPosition.column = Math.min(cursorPosition.column, newLineLength);
|
|
313
|
+
}
|
|
314
|
+
break;
|
|
315
|
+
case 'left':
|
|
316
|
+
if (cursorPosition.column > 0) {
|
|
317
|
+
cursorPosition.column--;
|
|
318
|
+
}
|
|
319
|
+
else if (cursorPosition.line > 0) {
|
|
320
|
+
cursorPosition.line--;
|
|
321
|
+
cursorPosition.column = content[cursorPosition.line]?.length || 0;
|
|
322
|
+
}
|
|
323
|
+
break;
|
|
324
|
+
case 'right':
|
|
325
|
+
const currentLineLength = content[cursorPosition.line]?.length || 0;
|
|
326
|
+
if (cursorPosition.column < currentLineLength) {
|
|
327
|
+
cursorPosition.column++;
|
|
328
|
+
}
|
|
329
|
+
else if (cursorPosition.line < content.length - 1) {
|
|
330
|
+
cursorPosition.line++;
|
|
331
|
+
cursorPosition.column = 0;
|
|
332
|
+
}
|
|
333
|
+
break;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Get the current content as a string
|
|
338
|
+
*/
|
|
339
|
+
getCurrentContent() {
|
|
340
|
+
return this.currentSession?.content.join('\n') || '';
|
|
341
|
+
}
|
|
342
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI UX Improvements - Core Implementations
|
|
3
|
+
*
|
|
4
|
+
* This module exports all the implementation classes for the CLI UX improvements
|
|
5
|
+
* as specified in the design document. These implementations provide the concrete
|
|
6
|
+
* functionality for the TextInputHandler, ConnectionManager, and OnboardingFlow interfaces.
|
|
7
|
+
*/
|
|
8
|
+
export { TextInputHandlerImpl } from './TextInputHandlerImpl.js';
|
|
9
|
+
export { ConnectionManagerImpl } from './ConnectionManagerImpl.js';
|
|
10
|
+
export { OnboardingFlowImpl } from './OnboardingFlowImpl.js';
|
|
11
|
+
export type { TextInputHandler, KeyEvent, CursorPosition, InputOptions, InputSession, ConnectionManager, ConnectionResult, ConfigResult, ServerInstance, ConnectionStatus, MCPConfig, OnboardingFlow, SetupResult, TestResult, UserPreferences, OnboardingState, } from '../interfaces/index.js';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI UX Improvements - Core Implementations
|
|
3
|
+
*
|
|
4
|
+
* This module exports all the implementation classes for the CLI UX improvements
|
|
5
|
+
* as specified in the design document. These implementations provide the concrete
|
|
6
|
+
* functionality for the TextInputHandler, ConnectionManager, and OnboardingFlow interfaces.
|
|
7
|
+
*/
|
|
8
|
+
// Implementation classes
|
|
9
|
+
export { TextInputHandlerImpl } from './TextInputHandlerImpl.js';
|
|
10
|
+
export { ConnectionManagerImpl } from './ConnectionManagerImpl.js';
|
|
11
|
+
export { OnboardingFlowImpl } from './OnboardingFlowImpl.js';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI UX Improvements - Main Module
|
|
3
|
+
*
|
|
4
|
+
* This is the main entry point for the CLI UX improvements module.
|
|
5
|
+
* It provides a clean API for accessing all the UX enhancement components
|
|
6
|
+
* including interfaces and implementations.
|
|
7
|
+
*/
|
|
8
|
+
export type { TextInputHandler, KeyEvent, CursorPosition, InputOptions, InputSession, ConnectionManager, ConnectionResult, ConfigResult, ServerInstance, ConnectionStatus, MCPConfig, OnboardingFlow, SetupResult, TestResult, UserPreferences, OnboardingState, } from './interfaces/index.js';
|
|
9
|
+
export { TextInputHandlerImpl, ConnectionManagerImpl, OnboardingFlowImpl, } from './implementations/index.js';
|
|
10
|
+
export declare function createTextInputHandler(): TextInputHandler;
|
|
11
|
+
export declare function createConnectionManager(configPath?: string): ConnectionManager;
|
|
12
|
+
export declare function createOnboardingFlow(configPath?: string): OnboardingFlow;
|
|
13
|
+
import type { TextInputHandler } from './interfaces/TextInputHandler.js';
|
|
14
|
+
import type { ConnectionManager } from './interfaces/ConnectionManager.js';
|
|
15
|
+
import type { OnboardingFlow } from './interfaces/OnboardingFlow.js';
|
package/dist/ux/index.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI UX Improvements - Main Module
|
|
3
|
+
*
|
|
4
|
+
* This is the main entry point for the CLI UX improvements module.
|
|
5
|
+
* It provides a clean API for accessing all the UX enhancement components
|
|
6
|
+
* including interfaces and implementations.
|
|
7
|
+
*/
|
|
8
|
+
// Export all implementations
|
|
9
|
+
export { TextInputHandlerImpl, ConnectionManagerImpl, OnboardingFlowImpl, } from './implementations/index.js';
|
|
10
|
+
// Convenience factory functions
|
|
11
|
+
export function createTextInputHandler() {
|
|
12
|
+
return new TextInputHandlerImpl();
|
|
13
|
+
}
|
|
14
|
+
export function createConnectionManager(configPath) {
|
|
15
|
+
return new ConnectionManagerImpl(configPath);
|
|
16
|
+
}
|
|
17
|
+
export function createOnboardingFlow(configPath) {
|
|
18
|
+
return new OnboardingFlowImpl(configPath);
|
|
19
|
+
}
|
|
20
|
+
import { TextInputHandlerImpl } from './implementations/TextInputHandlerImpl.js';
|
|
21
|
+
import { ConnectionManagerImpl } from './implementations/ConnectionManagerImpl.js';
|
|
22
|
+
import { OnboardingFlowImpl } from './implementations/OnboardingFlowImpl.js';
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Connection Manager Interface
|
|
3
|
+
*
|
|
4
|
+
* Manages MCP server discovery, configuration, and connection lifecycle
|
|
5
|
+
* for CLI UX improvements as specified in the design document.
|
|
6
|
+
*/
|
|
7
|
+
export interface ConnectionResult {
|
|
8
|
+
success: boolean;
|
|
9
|
+
serverPath?: string;
|
|
10
|
+
error?: string;
|
|
11
|
+
suggestions?: string[];
|
|
12
|
+
}
|
|
13
|
+
export interface ConfigResult {
|
|
14
|
+
success: boolean;
|
|
15
|
+
configPath?: string;
|
|
16
|
+
serverPath?: string;
|
|
17
|
+
error?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface ServerInstance {
|
|
20
|
+
pid: number;
|
|
21
|
+
port: number;
|
|
22
|
+
status: 'starting' | 'running' | 'stopped' | 'error';
|
|
23
|
+
startTime: Date;
|
|
24
|
+
logPath: string;
|
|
25
|
+
}
|
|
26
|
+
export interface ConnectionStatus {
|
|
27
|
+
isConnected: boolean;
|
|
28
|
+
serverPath?: string;
|
|
29
|
+
serverInstance?: ServerInstance;
|
|
30
|
+
lastConnected?: Date;
|
|
31
|
+
connectionAttempts: number;
|
|
32
|
+
lastError?: string;
|
|
33
|
+
}
|
|
34
|
+
export interface MCPConfig {
|
|
35
|
+
localServerPath: string;
|
|
36
|
+
serverPort?: number;
|
|
37
|
+
autoStart: boolean;
|
|
38
|
+
connectionTimeout: number;
|
|
39
|
+
retryAttempts: number;
|
|
40
|
+
logLevel: 'error' | 'warn' | 'info' | 'debug';
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* ConnectionManager manages MCP server discovery, configuration, and connection lifecycle
|
|
44
|
+
*
|
|
45
|
+
* Key Methods:
|
|
46
|
+
* - connectLocal(): Connect to the local embedded MCP server
|
|
47
|
+
* - autoConfigureLocalServer(): Automatically configure server paths
|
|
48
|
+
* - detectServerPath(): Find the embedded MCP server location
|
|
49
|
+
* - startLocalServer(): Start the server process automatically
|
|
50
|
+
* - verifyConnection(): Test server connectivity and functionality
|
|
51
|
+
* - getConnectionStatus(): Get current connection state
|
|
52
|
+
*
|
|
53
|
+
* Implementation Strategy:
|
|
54
|
+
* - Automatically detect embedded MCP server location within CLI package
|
|
55
|
+
* - Generate configuration files with correct server paths
|
|
56
|
+
* - Start server processes automatically when needed
|
|
57
|
+
* - Implement health checks and connection verification
|
|
58
|
+
*/
|
|
59
|
+
export interface ConnectionManager {
|
|
60
|
+
/**
|
|
61
|
+
* Initialize the connection manager by loading persisted configuration
|
|
62
|
+
* @returns Promise that resolves when initialization is complete
|
|
63
|
+
*/
|
|
64
|
+
init(): Promise<void>;
|
|
65
|
+
/**
|
|
66
|
+
* Connect to the local embedded MCP server
|
|
67
|
+
* @returns Promise that resolves to connection result
|
|
68
|
+
*/
|
|
69
|
+
connectLocal(): Promise<ConnectionResult>;
|
|
70
|
+
/**
|
|
71
|
+
* Automatically configure the local MCP server with correct paths
|
|
72
|
+
* @returns Promise that resolves to configuration result
|
|
73
|
+
*/
|
|
74
|
+
autoConfigureLocalServer(): Promise<ConfigResult>;
|
|
75
|
+
/**
|
|
76
|
+
* Detect the embedded MCP server path within the CLI package
|
|
77
|
+
* @returns Promise that resolves to server path or null if not found
|
|
78
|
+
*/
|
|
79
|
+
detectServerPath(): Promise<string | null>;
|
|
80
|
+
/**
|
|
81
|
+
* Start the local MCP server process
|
|
82
|
+
* @returns Promise that resolves to server instance
|
|
83
|
+
*/
|
|
84
|
+
startLocalServer(): Promise<ServerInstance>;
|
|
85
|
+
/**
|
|
86
|
+
* Verify that the MCP server connection is working
|
|
87
|
+
* @param serverPath Path to the server to verify
|
|
88
|
+
* @returns Promise that resolves to true if connection is valid
|
|
89
|
+
*/
|
|
90
|
+
verifyConnection(serverPath: string): Promise<boolean>;
|
|
91
|
+
/**
|
|
92
|
+
* Get the current connection status
|
|
93
|
+
* @returns Current connection status information
|
|
94
|
+
*/
|
|
95
|
+
getConnectionStatus(): ConnectionStatus;
|
|
96
|
+
/**
|
|
97
|
+
* Stop the local MCP server if running
|
|
98
|
+
* @returns Promise that resolves when server is stopped
|
|
99
|
+
*/
|
|
100
|
+
stopLocalServer(): Promise<void>;
|
|
101
|
+
/**
|
|
102
|
+
* Get the current MCP configuration
|
|
103
|
+
* @returns Current MCP configuration
|
|
104
|
+
*/
|
|
105
|
+
getConfig(): MCPConfig;
|
|
106
|
+
/**
|
|
107
|
+
* Update the MCP configuration
|
|
108
|
+
* @param config New configuration to apply
|
|
109
|
+
* @returns Promise that resolves when configuration is updated
|
|
110
|
+
*/
|
|
111
|
+
updateConfig(config: Partial<MCPConfig>): Promise<void>;
|
|
112
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Onboarding Flow Interface
|
|
3
|
+
*
|
|
4
|
+
* Guides new users through initial setup and configuration
|
|
5
|
+
* for CLI UX improvements as specified in the design document.
|
|
6
|
+
*/
|
|
7
|
+
export interface SetupResult {
|
|
8
|
+
completed: boolean;
|
|
9
|
+
mcpConfigured: boolean;
|
|
10
|
+
memorySystemReady: boolean;
|
|
11
|
+
issues?: string[];
|
|
12
|
+
}
|
|
13
|
+
export interface TestResult {
|
|
14
|
+
component: string;
|
|
15
|
+
status: 'pass' | 'fail' | 'warning';
|
|
16
|
+
message: string;
|
|
17
|
+
details?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface UserPreferences {
|
|
20
|
+
inputMode: 'inline' | 'editor';
|
|
21
|
+
preferredEditor?: string;
|
|
22
|
+
autoStartMCP: boolean;
|
|
23
|
+
showOnboardingTips: boolean;
|
|
24
|
+
verboseErrors: boolean;
|
|
25
|
+
}
|
|
26
|
+
export interface OnboardingState {
|
|
27
|
+
isFirstRun: boolean;
|
|
28
|
+
currentStep: number;
|
|
29
|
+
totalSteps: number;
|
|
30
|
+
completedSteps: string[];
|
|
31
|
+
skippedSteps: string[];
|
|
32
|
+
userPreferences: UserPreferences;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* OnboardingFlow guides new users through initial setup and configuration
|
|
36
|
+
*
|
|
37
|
+
* Key Methods:
|
|
38
|
+
* - runInitialSetup(): Execute the complete onboarding process
|
|
39
|
+
* - detectFirstRun(): Check if this is a first-time user
|
|
40
|
+
* - configureDefaults(): Set up working default configurations
|
|
41
|
+
* - testConnectivity(): Test all major functionality
|
|
42
|
+
* - showWelcomeDemo(): Demonstrate key features
|
|
43
|
+
*
|
|
44
|
+
* Implementation Strategy:
|
|
45
|
+
* - Detect first-run scenarios by checking for configuration files
|
|
46
|
+
* - Create working default configurations automatically
|
|
47
|
+
* - Test all major functionality and report status
|
|
48
|
+
* - Provide interactive demonstrations of key features
|
|
49
|
+
*/
|
|
50
|
+
export interface OnboardingFlow {
|
|
51
|
+
/**
|
|
52
|
+
* Run the complete initial setup process for new users
|
|
53
|
+
* @returns Promise that resolves to setup result
|
|
54
|
+
*/
|
|
55
|
+
runInitialSetup(): Promise<SetupResult>;
|
|
56
|
+
/**
|
|
57
|
+
* Detect if this is a first-run scenario
|
|
58
|
+
* @returns true if this appears to be a first run
|
|
59
|
+
*/
|
|
60
|
+
detectFirstRun(): boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Configure working default settings for immediate productivity
|
|
63
|
+
* @returns Promise that resolves when defaults are configured
|
|
64
|
+
*/
|
|
65
|
+
configureDefaults(): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* Test connectivity and functionality of all major components
|
|
68
|
+
* @returns Promise that resolves to array of test results
|
|
69
|
+
*/
|
|
70
|
+
testConnectivity(): Promise<TestResult[]>;
|
|
71
|
+
/**
|
|
72
|
+
* Show welcome demonstration of key features
|
|
73
|
+
* @returns Promise that resolves when demo is complete
|
|
74
|
+
*/
|
|
75
|
+
showWelcomeDemo(): Promise<void>;
|
|
76
|
+
/**
|
|
77
|
+
* Get the current onboarding state
|
|
78
|
+
* @returns Current onboarding state
|
|
79
|
+
*/
|
|
80
|
+
getOnboardingState(): OnboardingState;
|
|
81
|
+
/**
|
|
82
|
+
* Update user preferences during onboarding
|
|
83
|
+
* @param preferences New preferences to apply
|
|
84
|
+
* @returns Promise that resolves when preferences are updated
|
|
85
|
+
*/
|
|
86
|
+
updateUserPreferences(preferences: Partial<UserPreferences>): Promise<void>;
|
|
87
|
+
/**
|
|
88
|
+
* Skip the current onboarding step
|
|
89
|
+
* @param reason Optional reason for skipping
|
|
90
|
+
* @returns Promise that resolves when step is skipped
|
|
91
|
+
*/
|
|
92
|
+
skipCurrentStep(reason?: string): Promise<void>;
|
|
93
|
+
/**
|
|
94
|
+
* Complete the onboarding process
|
|
95
|
+
* @returns Promise that resolves when onboarding is complete
|
|
96
|
+
*/
|
|
97
|
+
completeOnboarding(): Promise<void>;
|
|
98
|
+
/**
|
|
99
|
+
* Reset onboarding state (for testing or re-running)
|
|
100
|
+
* @returns Promise that resolves when state is reset
|
|
101
|
+
*/
|
|
102
|
+
resetOnboarding(): Promise<void>;
|
|
103
|
+
}
|