@lanonasis/cli 3.9.3 → 3.9.4
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 +5 -0
- package/README.md +35 -10
- package/dist/utils/mcp-client.js +16 -8
- package/dist/ux/implementations/TextInputHandlerImpl.js +100 -26
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -16,6 +16,11 @@
|
|
|
16
16
|
- Path translation handles endpoint differences between API and MCP servers
|
|
17
17
|
- Vendor key authentication continues to route to main API server
|
|
18
18
|
|
|
19
|
+
- **Frozen Terminal During Text Input**: Fixed SSE/WebSocket event handlers interfering with inline text editor
|
|
20
|
+
- Real-time update messages (📡) now only display in verbose mode
|
|
21
|
+
- Prevents terminal freeze during interactive prompts (memory create, update)
|
|
22
|
+
- Raw terminal mode no longer conflicts with background MCP events
|
|
23
|
+
|
|
19
24
|
- **Missing CLI Option**: The `--vendor-key` option was defined in code but not exposed in CLI
|
|
20
25
|
- Now properly registered in command-line interface
|
|
21
26
|
|
package/README.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
# @lanonasis/cli v3.9.
|
|
1
|
+
# @lanonasis/cli v3.9.3 - Enterprise Security & Professional UX
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@lanonasis/cli)
|
|
4
4
|
[](https://www.npmjs.com/package/@lanonasis/cli)
|
|
5
5
|
[](https://opensource.org/licenses/MIT)
|
|
6
6
|
[](https://api.lanonasis.com/.well-known/onasis.json)
|
|
7
7
|
|
|
8
|
-
🎉 **NEW IN v3.9**:
|
|
8
|
+
🎉 **NEW IN v3.9.3**: Fixed JWT authentication routing for username/password login, resolved frozen terminal during interactive input, and added non-interactive vendor key authentication (`-k` flag). Professional CLI UX with seamless inline text editing, intelligent MCP connection management, and first-run onboarding.
|
|
9
9
|
|
|
10
10
|
## 🚀 Quick Start
|
|
11
11
|
|
|
@@ -151,7 +151,11 @@ onasis login --vendor-key pk_xxxxx.sk_xxxxx // ✅ Automatically hashed
|
|
|
151
151
|
Best for API integrations and automation. Copy the vendor key value exactly as shown in your LanOnasis dashboard (keys may vary in format):
|
|
152
152
|
|
|
153
153
|
```bash
|
|
154
|
-
|
|
154
|
+
# Full option
|
|
155
|
+
onasis auth login --vendor-key <your-vendor-key>
|
|
156
|
+
|
|
157
|
+
# Short form (for scripts and CI/CD)
|
|
158
|
+
onasis auth login -k <your-vendor-key>
|
|
155
159
|
```
|
|
156
160
|
|
|
157
161
|
### 2. OAuth Browser Authentication
|
|
@@ -179,6 +183,13 @@ onasis auth status # Check current authentication
|
|
|
179
183
|
onasis auth logout # Logout from current session
|
|
180
184
|
```
|
|
181
185
|
|
|
186
|
+
**Auth Login Options:**
|
|
187
|
+
| Short | Long | Description |
|
|
188
|
+
|-------|------|-------------|
|
|
189
|
+
| `-k` | `--vendor-key <key>` | Authenticate with vendor key (non-interactive) |
|
|
190
|
+
| `-e` | `--email <email>` | Email for credentials login |
|
|
191
|
+
| `-p` | `--password <pass>` | Password for credentials login |
|
|
192
|
+
|
|
182
193
|
## 💻 Shell Completions
|
|
183
194
|
|
|
184
195
|
### Installation Guide
|
|
@@ -224,24 +235,38 @@ onasis quickstart # Essential commands reference
|
|
|
224
235
|
|
|
225
236
|
```bash
|
|
226
237
|
# List memories
|
|
227
|
-
onasis memory list
|
|
228
|
-
onasis memory list --
|
|
238
|
+
onasis memory list # or: onasis memory ls
|
|
239
|
+
onasis memory list --type context --limit 20
|
|
240
|
+
|
|
241
|
+
# Create memories (non-interactive)
|
|
242
|
+
onasis memory create -t "Project Notes" -c "Important information"
|
|
243
|
+
onasis memory create -t "Reference" --type reference --tags "docs,api"
|
|
229
244
|
|
|
230
|
-
# Create memories
|
|
231
|
-
onasis memory create
|
|
232
|
-
onasis memory create
|
|
245
|
+
# Create memories (interactive)
|
|
246
|
+
onasis memory create -i # Interactive mode with inline editor
|
|
247
|
+
onasis memory create # Prompts for missing fields
|
|
233
248
|
|
|
234
249
|
# Search memories
|
|
235
250
|
onasis memory search "api integration"
|
|
236
|
-
onasis memory search "meeting notes" --
|
|
251
|
+
onasis memory search "meeting notes" --type context
|
|
237
252
|
|
|
238
253
|
# Memory operations
|
|
239
254
|
onasis memory get <id> # Get specific memory
|
|
240
|
-
onasis memory update <id>
|
|
255
|
+
onasis memory update <id> -t "New Title" # Update title
|
|
256
|
+
onasis memory update <id> -i # Interactive update
|
|
241
257
|
onasis memory delete <id> # Delete memory
|
|
242
258
|
onasis memory stats # Memory statistics
|
|
243
259
|
```
|
|
244
260
|
|
|
261
|
+
**Create/Update Options:**
|
|
262
|
+
| Short | Long | Description |
|
|
263
|
+
|-------|------|-------------|
|
|
264
|
+
| `-t` | `--title` | Memory title |
|
|
265
|
+
| `-c` | `--content` | Memory content |
|
|
266
|
+
| `-i` | `--interactive` | Interactive mode |
|
|
267
|
+
| | `--type` | Memory type (context, project, knowledge, etc.) |
|
|
268
|
+
| | `--tags` | Comma-separated tags |
|
|
269
|
+
|
|
245
270
|
### Topic Management
|
|
246
271
|
|
|
247
272
|
```bash
|
package/dist/utils/mcp-client.js
CHANGED
|
@@ -469,7 +469,10 @@ export class MCPClient {
|
|
|
469
469
|
this.sseConnection.onmessage = (event) => {
|
|
470
470
|
try {
|
|
471
471
|
const data = JSON.parse(event.data);
|
|
472
|
-
|
|
472
|
+
// Only show SSE updates in verbose mode to avoid interfering with interactive prompts
|
|
473
|
+
if (process.env.CLI_VERBOSE === 'true') {
|
|
474
|
+
console.log(chalk.blue('📡 Real-time update:'), data.type);
|
|
475
|
+
}
|
|
473
476
|
}
|
|
474
477
|
catch {
|
|
475
478
|
// Ignore parse errors
|
|
@@ -526,15 +529,20 @@ export class MCPClient {
|
|
|
526
529
|
this.wsConnection.on('message', (data) => {
|
|
527
530
|
try {
|
|
528
531
|
const message = JSON.parse(data.toString());
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
532
|
+
// Only show WebSocket messages in verbose mode to avoid interfering with interactive prompts
|
|
533
|
+
if (process.env.CLI_VERBOSE === 'true') {
|
|
534
|
+
const messageId = message.id ?? 'event';
|
|
535
|
+
const messageType = message.method
|
|
536
|
+
|| (message.error ? 'error' : undefined)
|
|
537
|
+
|| (message.result ? 'result' : undefined)
|
|
538
|
+
|| 'response';
|
|
539
|
+
console.log(chalk.blue('📡 MCP message:'), messageId, messageType);
|
|
540
|
+
}
|
|
535
541
|
}
|
|
536
542
|
catch (error) {
|
|
537
|
-
|
|
543
|
+
if (process.env.CLI_VERBOSE === 'true') {
|
|
544
|
+
console.error('Failed to parse WebSocket message:', error);
|
|
545
|
+
}
|
|
538
546
|
}
|
|
539
547
|
});
|
|
540
548
|
this.wsConnection.on('error', (error) => {
|
|
@@ -46,46 +46,113 @@ export class TextInputHandlerImpl {
|
|
|
46
46
|
options: mergedOptions,
|
|
47
47
|
status: 'active',
|
|
48
48
|
};
|
|
49
|
-
return new Promise((resolve, reject) => {
|
|
49
|
+
return new Promise(async (resolve, reject) => {
|
|
50
50
|
let handleKeypress = null;
|
|
51
|
+
let sigintHandler = null;
|
|
51
52
|
const cleanup = () => {
|
|
52
53
|
if (handleKeypress) {
|
|
53
54
|
process.stdin.removeListener('data', handleKeypress);
|
|
55
|
+
handleKeypress = null;
|
|
56
|
+
}
|
|
57
|
+
if (sigintHandler) {
|
|
58
|
+
process.removeListener('SIGINT', sigintHandler);
|
|
59
|
+
sigintHandler = null;
|
|
54
60
|
}
|
|
55
61
|
this.disableRawMode();
|
|
62
|
+
// Restore terminal state
|
|
63
|
+
process.stdout.write('\x1b[?25h'); // Show cursor
|
|
56
64
|
};
|
|
65
|
+
// Set up completion handlers first
|
|
66
|
+
const complete = (result) => {
|
|
67
|
+
cleanup();
|
|
68
|
+
if (this.currentSession) {
|
|
69
|
+
this.currentSession.status = 'completed';
|
|
70
|
+
}
|
|
71
|
+
resolve(result);
|
|
72
|
+
};
|
|
73
|
+
const cancel = () => {
|
|
74
|
+
cleanup();
|
|
75
|
+
if (this.currentSession) {
|
|
76
|
+
this.currentSession.status = 'cancelled';
|
|
77
|
+
}
|
|
78
|
+
reject(new Error('Input cancelled by user'));
|
|
79
|
+
};
|
|
80
|
+
// Store handlers for special key processing
|
|
81
|
+
this._completeHandler = complete;
|
|
82
|
+
this._cancelHandler = cancel;
|
|
57
83
|
try {
|
|
84
|
+
// Check if we can use raw mode
|
|
85
|
+
if (!process.stdin.isTTY) {
|
|
86
|
+
// Fall back to simple readline for non-TTY environments
|
|
87
|
+
console.log('\nNote: Interactive text input not available. Using simple input mode.');
|
|
88
|
+
console.log('Enter your text (empty line to finish):');
|
|
89
|
+
const readline = require('readline');
|
|
90
|
+
const rl = readline.createInterface({
|
|
91
|
+
input: process.stdin,
|
|
92
|
+
output: process.stdout
|
|
93
|
+
});
|
|
94
|
+
const lines = [];
|
|
95
|
+
rl.on('line', (line) => {
|
|
96
|
+
if (line === '') {
|
|
97
|
+
rl.close();
|
|
98
|
+
complete(lines.join('\n'));
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
lines.push(line);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
rl.on('close', () => {
|
|
105
|
+
complete(lines.join('\n'));
|
|
106
|
+
});
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
// Add SIGINT handler as fallback for Ctrl+C
|
|
110
|
+
sigintHandler = () => {
|
|
111
|
+
cancel();
|
|
112
|
+
};
|
|
113
|
+
process.on('SIGINT', sigintHandler);
|
|
114
|
+
// Safety: Add a way to escape via triple-ESC (sends 3 escape chars quickly)
|
|
115
|
+
let escapeCount = 0;
|
|
116
|
+
let escapeTimer = null;
|
|
117
|
+
// Try to claim stdin from any previous handlers
|
|
118
|
+
process.stdin.removeAllListeners('data');
|
|
119
|
+
process.stdin.removeAllListeners('readable');
|
|
120
|
+
process.stdin.removeAllListeners('end');
|
|
58
121
|
this.enableRawMode();
|
|
122
|
+
// Verify raw mode is working
|
|
123
|
+
if (!this.isRawModeEnabled) {
|
|
124
|
+
console.log('\nWarning: Could not enable raw mode. Falling back to editor mode.');
|
|
125
|
+
cleanup();
|
|
126
|
+
const { content } = await (await import('inquirer')).default.prompt([
|
|
127
|
+
{ type: 'editor', name: 'content', message: prompt, default: mergedOptions.defaultContent }
|
|
128
|
+
]);
|
|
129
|
+
resolve(content);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
59
132
|
this.displayInputPrompt(this.getCurrentContent());
|
|
60
133
|
handleKeypress = (chunk) => {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
134
|
+
try {
|
|
135
|
+
const key = this.parseKeyEvent(chunk);
|
|
136
|
+
if (this.handleSpecialKeys(key)) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
// Handle regular character input
|
|
140
|
+
if (key.sequence && this.currentSession) {
|
|
141
|
+
// Filter out control characters that shouldn't be added as text
|
|
142
|
+
if (key.sequence.charCodeAt(0) >= 32 || key.sequence === '\t') {
|
|
143
|
+
this.addCharacterToInput(key.sequence);
|
|
144
|
+
this.displayInputPrompt(this.getCurrentContent());
|
|
145
|
+
}
|
|
146
|
+
}
|
|
69
147
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
cleanup();
|
|
74
|
-
if (this.currentSession) {
|
|
75
|
-
this.currentSession.status = 'completed';
|
|
148
|
+
catch (err) {
|
|
149
|
+
// Don't let errors in key handling crash the input
|
|
150
|
+
console.error('Key handling error:', err);
|
|
76
151
|
}
|
|
77
|
-
resolve(result);
|
|
78
152
|
};
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
this.currentSession.status = 'cancelled';
|
|
83
|
-
}
|
|
84
|
-
reject(new Error('Input cancelled by user'));
|
|
85
|
-
};
|
|
86
|
-
// Store handlers for special key processing
|
|
87
|
-
this._completeHandler = complete;
|
|
88
|
-
this._cancelHandler = cancel;
|
|
153
|
+
// Ensure stdin is flowing before adding listener
|
|
154
|
+
// This is critical after inquirer prompts which may pause stdin
|
|
155
|
+
process.stdin.resume();
|
|
89
156
|
process.stdin.on('data', handleKeypress);
|
|
90
157
|
}
|
|
91
158
|
catch (error) {
|
|
@@ -101,8 +168,14 @@ export class TextInputHandlerImpl {
|
|
|
101
168
|
if (!this.isRawModeEnabled && process.stdin.isTTY) {
|
|
102
169
|
this.originalStdinMode = process.stdin.isRaw;
|
|
103
170
|
process.stdin.setRawMode(true);
|
|
171
|
+
process.stdin.resume(); // Ensure stdin is flowing to receive data events
|
|
104
172
|
this.isRawModeEnabled = true;
|
|
105
173
|
}
|
|
174
|
+
else if (!process.stdin.isTTY) {
|
|
175
|
+
// Non-TTY mode - can't use raw mode, fall back to line mode
|
|
176
|
+
console.error('Warning: Not a TTY, inline text input may not work correctly');
|
|
177
|
+
process.stdin.resume();
|
|
178
|
+
}
|
|
106
179
|
}
|
|
107
180
|
/**
|
|
108
181
|
* Disable raw mode and return to normal terminal behavior
|
|
@@ -112,6 +185,7 @@ export class TextInputHandlerImpl {
|
|
|
112
185
|
process.stdin.setRawMode(this.originalStdinMode || false);
|
|
113
186
|
this.isRawModeEnabled = false;
|
|
114
187
|
}
|
|
188
|
+
// Don't pause stdin here as other handlers may need it
|
|
115
189
|
}
|
|
116
190
|
/**
|
|
117
191
|
* Handle special keyboard events
|
package/package.json
CHANGED