@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 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.0 - Enterprise Security & Professional UX
1
+ # @lanonasis/cli v3.9.3 - Enterprise Security & Professional UX
2
2
 
3
3
  [![NPM Version](https://img.shields.io/npm/v/@lanonasis/cli)](https://www.npmjs.com/package/@lanonasis/cli)
4
4
  [![Downloads](https://img.shields.io/npm/dt/@lanonasis/cli)](https://www.npmjs.com/package/@lanonasis/cli)
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
6
  [![Golden Contract](https://img.shields.io/badge/Onasis--Core-v0.1%20Compliant-gold)](https://api.lanonasis.com/.well-known/onasis.json)
7
7
 
8
- 🎉 **NEW IN v3.9**: Professional CLI UX with seamless inline text editing, intelligent MCP connection management, and first-run onboarding. Advanced Model Context Protocol (MCP) support with multi-server connections, enhanced error handling, and enterprise-grade transport protocols. Revolutionary interactive CLI experience with guided workflows and **Golden Contract compliance**.
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
- onasis login --vendor-key <your-vendor-key>
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 --memory-type context --limit 20 --sort-by created_at
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 --title "Project Notes" --content "Important information"
232
- onasis memory create --title "Reference" --memory-type reference --tags "docs,api"
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" --memory-types context,reference
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> --title "New Title"
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
@@ -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
- console.log(chalk.blue('📡 Real-time update:'), data.type);
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
- const messageId = message.id ?? 'event';
530
- const messageType = message.method
531
- || (message.error ? 'error' : undefined)
532
- || (message.result ? 'result' : undefined)
533
- || 'response';
534
- console.log(chalk.blue('📡 MCP message:'), messageId, messageType);
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
- console.error('Failed to parse WebSocket message:', error);
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
- const key = this.parseKeyEvent(chunk);
62
- if (this.handleSpecialKeys(key)) {
63
- return;
64
- }
65
- // Handle regular character input
66
- if (key.sequence && this.currentSession) {
67
- this.addCharacterToInput(key.sequence);
68
- this.displayInputPrompt(this.getCurrentContent());
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
- // Set up completion handlers
72
- const complete = (result) => {
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
- const cancel = () => {
80
- cleanup();
81
- if (this.currentSession) {
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lanonasis/cli",
3
- "version": "3.9.3",
3
+ "version": "3.9.4",
4
4
  "description": "Professional CLI for LanOnasis Memory as a Service (MaaS) with MCP support, seamless inline editing, and enterprise-grade security",
5
5
  "keywords": [
6
6
  "lanonasis",