@lanonasis/cli 3.8.1 โ 3.9.1
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 +224 -0
- package/README.md +68 -3
- package/dist/commands/auth.js +10 -11
- package/dist/commands/init.js +12 -0
- package/dist/commands/mcp.js +62 -5
- package/dist/commands/memory.js +49 -23
- package/dist/index.js +20 -0
- package/dist/mcp/schemas/tool-schemas.d.ts +4 -4
- package/dist/utils/api.js +11 -1
- package/dist/utils/mcp-client.d.ts +7 -0
- package/dist/utils/mcp-client.js +52 -18
- package/dist/ux/implementations/ConnectionManagerImpl.d.ts +72 -0
- package/dist/ux/implementations/ConnectionManagerImpl.js +356 -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 +347 -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
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
# Changelog - @lanonasis/cli
|
|
2
|
+
|
|
3
|
+
## [3.9.1] - 2026-02-01
|
|
4
|
+
|
|
5
|
+
### ๐ Authentication Fixes
|
|
6
|
+
|
|
7
|
+
- **OAuth Scope Clarification**: OAuth login now clearly states it enables MCP integration only
|
|
8
|
+
- **Improved Error Messages**: 401 errors for OAuth users include specific guidance for direct API access
|
|
9
|
+
- **Removed Misleading Storage**: OAuth tokens are no longer incorrectly stored as vendor keys
|
|
10
|
+
- **Documentation Updates**: README and in-CLI help clarify authentication method differences
|
|
11
|
+
|
|
12
|
+
### ๐ Bug Fixes
|
|
13
|
+
|
|
14
|
+
- Fixed confusing error message when OAuth users try to use direct CLI commands
|
|
15
|
+
- Removed `.lanonasis/mcp-config.json` from version control
|
|
16
|
+
|
|
17
|
+
## [3.9.0] - 2026-02-01
|
|
18
|
+
|
|
19
|
+
### ๐จ CLI UX Revolution
|
|
20
|
+
|
|
21
|
+
#### Seamless Multi-Line Text Input
|
|
22
|
+
- **Inline Text Editor**: Professional multi-line text input without external editors
|
|
23
|
+
- Raw terminal mode for keystroke capture
|
|
24
|
+
- Full editing support (arrow keys, backspace, newlines)
|
|
25
|
+
- Visual feedback with line numbers and cursor indicators
|
|
26
|
+
- Submit with Ctrl+D, cancel with Ctrl+C
|
|
27
|
+
- Configurable fallback to external editors
|
|
28
|
+
|
|
29
|
+
#### Intelligent MCP Server Connection Management
|
|
30
|
+
- **Auto-Configuration**: Automatically detects and configures embedded MCP servers
|
|
31
|
+
- **Connection Lifecycle**: Smart server process management with health monitoring
|
|
32
|
+
- **Persistent Configuration**: Saves and loads user preferences across sessions
|
|
33
|
+
- **Connection Verification**: Validates server connectivity before operations
|
|
34
|
+
- **Graceful Error Handling**: Clear error messages with actionable resolution steps
|
|
35
|
+
|
|
36
|
+
#### First-Run Onboarding Experience
|
|
37
|
+
- **Guided Setup**: Interactive onboarding flow for new users
|
|
38
|
+
- **Connectivity Testing**: Automatic testing of API endpoints and services
|
|
39
|
+
- **Smart Defaults**: Configures optimal settings based on environment
|
|
40
|
+
- **User Preferences**: Captures and persists input mode, editor choice, and behavior preferences
|
|
41
|
+
- **Troubleshooting Guidance**: Context-aware help when issues are detected
|
|
42
|
+
|
|
43
|
+
### ๐ Authentication Clarifications
|
|
44
|
+
|
|
45
|
+
#### OAuth vs Direct API Access
|
|
46
|
+
- **Clear Scope Documentation**: OAuth2 login now explicitly states it enables MCP integration
|
|
47
|
+
- **Improved Error Messages**: 401 errors for OAuth users include specific guidance for direct API access
|
|
48
|
+
- **Authentication Method Guidance**: CLI provides clear instructions for:
|
|
49
|
+
- **OAuth**: Use for MCP integration and real-time features
|
|
50
|
+
- **Vendor Key**: Obtain from dashboard for direct API access (`lanonasis auth login --vendor`)
|
|
51
|
+
- **Credentials**: Use username/password for direct API access (`lanonasis auth login --credentials`)
|
|
52
|
+
|
|
53
|
+
#### Secure Storage Fallback
|
|
54
|
+
- **Keytar Optional**: When keytar (native secure storage) is unavailable, CLI gracefully falls back to encrypted file storage
|
|
55
|
+
- **Cross-Platform**: Encrypted storage works consistently across all platforms
|
|
56
|
+
- **No Data Loss**: Credentials are preserved in `~/.lanonasis/api-key.enc` with AES-256-GCM encryption
|
|
57
|
+
|
|
58
|
+
### ๐ Critical Bug Fixes (PR #93)
|
|
59
|
+
|
|
60
|
+
#### P1: Connection Verification False Positive
|
|
61
|
+
- **Issue**: `verifyConnection()` returned `true` even when server was in error/stopped state
|
|
62
|
+
- **Fix**: Added explicit checks for error and stopped states before declaring success
|
|
63
|
+
- **Impact**: Users will now see accurate connection status instead of false positives
|
|
64
|
+
|
|
65
|
+
#### P2: Configuration Not Loaded Before Use
|
|
66
|
+
- **Issue**: `ConnectionManager.init()` method existed but was never called
|
|
67
|
+
- **Fix**: Added `init()` to ConnectionManager interface and call it before `connectLocal()`
|
|
68
|
+
- **Impact**: User configuration is now properly loaded and respected
|
|
69
|
+
|
|
70
|
+
#### P2: Empty Content Overwrites in Inline Updates
|
|
71
|
+
- **Issue**: When updating memories in inline mode, `defaultContent` wasn't passed to TextInputHandler
|
|
72
|
+
- **Fix**: Added `defaultContent` support throughout the text input pipeline
|
|
73
|
+
- **Impact**: Memory updates preserve existing content instead of starting with blank slate
|
|
74
|
+
|
|
75
|
+
### ๐งช Testing & Quality
|
|
76
|
+
|
|
77
|
+
- **Comprehensive Test Suite**: 168 passing tests including property-based tests
|
|
78
|
+
- **Zero TypeScript Errors**: All compilation errors resolved
|
|
79
|
+
- **No Regressions**: All existing tests continue to pass
|
|
80
|
+
- **Professional Documentation**: Complete inline documentation and type definitions
|
|
81
|
+
|
|
82
|
+
### ๐ฆ Package Cleanup
|
|
83
|
+
|
|
84
|
+
- **npmignore**: Excludes test files and development artifacts from published package
|
|
85
|
+
- **Directory Reorganization**: Cleaner structure with examples moved to `docs/examples/`
|
|
86
|
+
- **Build Optimization**: Reduced package size by excluding unnecessary files
|
|
87
|
+
|
|
88
|
+
### ๐ Breaking Changes
|
|
89
|
+
None - Fully backward compatible
|
|
90
|
+
|
|
91
|
+
### ๐ Technical Details
|
|
92
|
+
|
|
93
|
+
**New Implementations**:
|
|
94
|
+
- `TextInputHandlerImpl` ([cli/src/ux/implementations/TextInputHandlerImpl.ts](cli/src/ux/implementations/TextInputHandlerImpl.ts))
|
|
95
|
+
- `ConnectionManagerImpl` ([cli/src/ux/implementations/ConnectionManagerImpl.ts](cli/src/ux/implementations/ConnectionManagerImpl.ts))
|
|
96
|
+
- `OnboardingFlowImpl` ([cli/src/ux/implementations/OnboardingFlowImpl.ts](cli/src/ux/implementations/OnboardingFlowImpl.ts))
|
|
97
|
+
|
|
98
|
+
**Integration Points**:
|
|
99
|
+
- Memory commands now use inline text input by default ([cli/src/commands/memory.ts](cli/src/commands/memory.ts:116-119))
|
|
100
|
+
- MCP connect command uses ConnectionManager ([cli/src/commands/mcp.ts](cli/src/commands/mcp.ts:130-137))
|
|
101
|
+
- Init command includes onboarding flow ([cli/src/commands/init.ts](cli/src/commands/init.ts))
|
|
102
|
+
|
|
103
|
+
## [3.7.0] - 2025-11-23
|
|
104
|
+
|
|
105
|
+
### ๐ Security Infrastructure Upgrade
|
|
106
|
+
|
|
107
|
+
#### Enhanced API Key Security with SHA-256
|
|
108
|
+
- **Cross-Platform SHA-256 Hashing**: Unified hash utilities for consistent API key hashing across all platforms
|
|
109
|
+
- **Local Hash Implementation**: Isolated hash utilities (`src/utils/hash-utils.ts`) for CLI independence
|
|
110
|
+
- **Double-Hash Prevention**: Smart detection of pre-hashed keys to prevent double-hashing errors
|
|
111
|
+
- **Server-Side Validation**: Constant-time comparison for timing-attack prevention
|
|
112
|
+
- **Future NPM Package Ready**: Designed for eventual migration to `@lanonasis/security` npm package
|
|
113
|
+
|
|
114
|
+
#### Technical Improvements
|
|
115
|
+
- **Build Stability**: Fixed TypeScript `rootDir` compilation errors
|
|
116
|
+
- **Zero Deprecation Warnings**: All dependencies verified for production readiness
|
|
117
|
+
- **Cross-Platform Compatibility**: Node.js crypto for server-side, Web Crypto API fallback for browser contexts
|
|
118
|
+
- **Type Safety**: Full TypeScript support with exported hash types (`ApiKeyHash`, `ApiKey`)
|
|
119
|
+
|
|
120
|
+
#### Hash Utility Functions
|
|
121
|
+
```typescript
|
|
122
|
+
// Available in CLI
|
|
123
|
+
ensureApiKeyHash(apiKey: string): string // Smart hash normalization
|
|
124
|
+
hashApiKey(apiKey: string): string // SHA-256 hashing
|
|
125
|
+
isSha256Hash(value: string): boolean // Hash detection
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### ๐ก๏ธ Security Features
|
|
129
|
+
- โ
SHA-256 cryptographic hashing for all API keys
|
|
130
|
+
- โ
Prevents plaintext key transmission
|
|
131
|
+
- โ
Constant-time hash comparison
|
|
132
|
+
- โ
Automatic hash detection and normalization
|
|
133
|
+
- โ
Compatible with existing vendor key authentication
|
|
134
|
+
|
|
135
|
+
### ๐ Breaking Changes
|
|
136
|
+
None - Fully backward compatible
|
|
137
|
+
|
|
138
|
+
### ๐ฆ Dependencies
|
|
139
|
+
- No new external dependencies
|
|
140
|
+
- Uses native Node.js `crypto` module
|
|
141
|
+
- Clean build with zero deprecation warnings
|
|
142
|
+
|
|
143
|
+
## [3.0.1] - 2025-10-08
|
|
144
|
+
|
|
145
|
+
### ๐ Major Version Bump
|
|
146
|
+
This is a major version release (3.0) due to the significant MCP architectural changes and new capabilities that may affect existing integrations.
|
|
147
|
+
|
|
148
|
+
### ๐ Major Features
|
|
149
|
+
*Same as 2.0.9 but republished as 3.0.1 due to npm version conflict*
|
|
150
|
+
|
|
151
|
+
## [2.0.9] - 2025-10-08 (npm publish conflict)
|
|
152
|
+
|
|
153
|
+
### ๐ Major Features
|
|
154
|
+
|
|
155
|
+
#### Enhanced Model Context Protocol (MCP) Support
|
|
156
|
+
- **Multi-Server Connections**: Connect to multiple MCP servers simultaneously with automatic failover
|
|
157
|
+
- **Advanced Error Handling**: Exponential backoff retry logic and graceful degradation
|
|
158
|
+
- **Health Monitoring**: Automatic health checks with latency tracking and auto-reconnection
|
|
159
|
+
- **Connection Pooling**: Efficient resource management for multiple connections
|
|
160
|
+
- **Tool Chain Execution**: Support for sequential and parallel tool execution
|
|
161
|
+
|
|
162
|
+
#### New MCP Infrastructure
|
|
163
|
+
- **Enhanced MCP Client** (`src/mcp/client/enhanced-client.ts`)
|
|
164
|
+
- Multi-server management with priority-based selection
|
|
165
|
+
- Event-driven architecture with connection status tracking
|
|
166
|
+
- Automatic failover to backup servers
|
|
167
|
+
|
|
168
|
+
- **MCP Server Implementation** (`src/mcp/server/lanonasis-server.ts`)
|
|
169
|
+
- Full MCP protocol compliance (tools, resources, prompts)
|
|
170
|
+
- 16 registered tools for memory, topic, and system operations
|
|
171
|
+
- Resource providers for data access
|
|
172
|
+
- Interactive prompts for user guidance
|
|
173
|
+
|
|
174
|
+
- **Transport Support** (`src/mcp/transports/transport-manager.ts`)
|
|
175
|
+
- StdIO transport for local processes
|
|
176
|
+
- WebSocket transport with auto-reconnection
|
|
177
|
+
- SSE (Server-Sent Events) for streaming
|
|
178
|
+
- Authentication support (Bearer, API Key, Basic)
|
|
179
|
+
|
|
180
|
+
- **Schema Validation** (`src/mcp/schemas/tool-schemas.ts`)
|
|
181
|
+
- Zod-based validation for all MCP tools
|
|
182
|
+
- Type-safe operations with clear error messages
|
|
183
|
+
- Comprehensive schemas for memory, topic, API key, and system operations
|
|
184
|
+
|
|
185
|
+
### ๐ Technical Improvements
|
|
186
|
+
- **Build System**: New MCP-specific build scripts (`build:mcp`, `dev:mcp`, `test:mcp`)
|
|
187
|
+
- **Module Structure**: Dedicated `/src/mcp/` directory with clean separation of concerns
|
|
188
|
+
- **Error Recovery**: Improved error handling throughout the MCP stack
|
|
189
|
+
- **Type Safety**: Full TypeScript support with proper type definitions
|
|
190
|
+
|
|
191
|
+
### ๐ Bug Fixes
|
|
192
|
+
- Fixed authentication flow issues with proper token validation
|
|
193
|
+
- Resolved double slash URL construction in CLI auth
|
|
194
|
+
- Fixed memory command authentication requirements
|
|
195
|
+
- Corrected error messages to show correct authentication command
|
|
196
|
+
|
|
197
|
+
### ๐ Documentation
|
|
198
|
+
- Enhanced README with MCP usage examples
|
|
199
|
+
- Added MCP Server Mode documentation
|
|
200
|
+
- Updated command reference with new MCP features
|
|
201
|
+
- Created comprehensive MCP enhancement summary
|
|
202
|
+
|
|
203
|
+
### โ ๏ธ Breaking Changes
|
|
204
|
+
- HTTP transport temporarily disabled in favor of WebSocket/StdIO (more reliable)
|
|
205
|
+
- Some API key operations pending full implementation
|
|
206
|
+
|
|
207
|
+
### ๐ Dependencies
|
|
208
|
+
- Updated to latest @modelcontextprotocol/sdk
|
|
209
|
+
- Added ws for WebSocket support
|
|
210
|
+
- Added zod for schema validation
|
|
211
|
+
|
|
212
|
+
## [2.0.8] - Previous Version
|
|
213
|
+
- Authentication system improvements
|
|
214
|
+
- CLI guided setup enhancements
|
|
215
|
+
- Performance optimizations
|
|
216
|
+
|
|
217
|
+
## [2.0.7] - Previous Version
|
|
218
|
+
- Memory management improvements
|
|
219
|
+
- Topic organization features
|
|
220
|
+
- Bug fixes and stability improvements
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
For full release notes and migration guides, visit: https://docs.lanonasis.com/cli/changelog
|
package/README.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
# @lanonasis/cli v3.
|
|
1
|
+
# @lanonasis/cli v3.9.0 - 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
|
-
|
|
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**.
|
|
9
9
|
|
|
10
10
|
## ๐ Quick Start
|
|
11
11
|
|
|
@@ -34,6 +34,69 @@ onasis health # Verify system health
|
|
|
34
34
|
onasis memory create --title "Welcome" --content "My first memory"
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
+
## โจ Professional CLI UX (v3.9.0+)
|
|
38
|
+
|
|
39
|
+
### Seamless Inline Text Editing
|
|
40
|
+
No more external editor dependencies! Create and update memories with a professional inline text editor:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# Create memory with inline multi-line editor
|
|
44
|
+
onasis memory create --inline
|
|
45
|
+
# Type your content directly in the terminal
|
|
46
|
+
# Use arrow keys to navigate, Enter for new lines
|
|
47
|
+
# Ctrl+D to save, Ctrl+C to cancel
|
|
48
|
+
|
|
49
|
+
# Update existing memory
|
|
50
|
+
onasis memory update <id> --inline
|
|
51
|
+
# Your existing content is preserved and editable
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Features**:
|
|
55
|
+
- โจ Multi-line editing with visual feedback
|
|
56
|
+
- ๐ฏ Line numbers and cursor indicators
|
|
57
|
+
- โจ๏ธ Full keyboard navigation (arrows, backspace, etc.)
|
|
58
|
+
- ๐พ Auto-preserves existing content when updating
|
|
59
|
+
- ๐ซ No external editor configuration needed
|
|
60
|
+
|
|
61
|
+
### Intelligent MCP Connection
|
|
62
|
+
Automatic MCP server discovery and configuration:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
# Connect to local MCP server (auto-configured)
|
|
66
|
+
onasis mcp connect --local
|
|
67
|
+
# Server path detected automatically
|
|
68
|
+
# Configuration persisted for next time
|
|
69
|
+
|
|
70
|
+
# Check connection status
|
|
71
|
+
onasis mcp status
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**Features**:
|
|
75
|
+
- ๐ Auto-detects embedded MCP server
|
|
76
|
+
- ๐พ Saves configuration automatically
|
|
77
|
+
- ๐ Health monitoring and auto-reconnection
|
|
78
|
+
- โ
Connection verification before operations
|
|
79
|
+
- ๐ ๏ธ Clear error messages with fix suggestions
|
|
80
|
+
|
|
81
|
+
### First-Run Onboarding
|
|
82
|
+
Interactive setup for new users:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
onasis init
|
|
86
|
+
# Guided setup walks you through:
|
|
87
|
+
# - API configuration
|
|
88
|
+
# - Connectivity testing
|
|
89
|
+
# - Input mode preferences
|
|
90
|
+
# - Troubleshooting if needed
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**Features**:
|
|
94
|
+
- ๐ Step-by-step guided setup
|
|
95
|
+
- ๐งช Automatic connectivity tests
|
|
96
|
+
- โ๏ธ Smart default configuration
|
|
97
|
+
- ๐ก Context-aware troubleshooting
|
|
98
|
+
- ๐ Interactive help and tips
|
|
99
|
+
|
|
37
100
|
## ๐ค Claude Desktop Integration
|
|
38
101
|
|
|
39
102
|
For instant Claude Desktop MCP integration with OAuth2 authentication, see our [Claude Desktop Setup Guide](./CLAUDE_DESKTOP_SETUP.md).
|
|
@@ -93,12 +156,14 @@ onasis login --vendor-key <your-vendor-key>
|
|
|
93
156
|
|
|
94
157
|
### 2. OAuth Browser Authentication
|
|
95
158
|
|
|
96
|
-
Secure browser-based authentication:
|
|
159
|
+
Secure browser-based authentication for MCP integration:
|
|
97
160
|
|
|
98
161
|
```bash
|
|
99
162
|
onasis login --oauth
|
|
100
163
|
```
|
|
101
164
|
|
|
165
|
+
> **Note**: OAuth authentication enables MCP integration features (real-time updates, WebSocket connections). For direct CLI memory commands (`memory list`, `memory create`, etc.), use vendor key or credentials authentication.
|
|
166
|
+
|
|
102
167
|
### 3. Interactive Credentials
|
|
103
168
|
|
|
104
169
|
Traditional username/password authentication:
|
package/dist/commands/auth.js
CHANGED
|
@@ -702,23 +702,22 @@ async function handleOAuthFlow(config) {
|
|
|
702
702
|
}
|
|
703
703
|
const tokens = await exchangeCodeForTokens(code, pkce.verifier, authBase, redirectUri);
|
|
704
704
|
spinner.succeed('Access tokens received');
|
|
705
|
-
// Store OAuth tokens - these are
|
|
706
|
-
//
|
|
705
|
+
// Store OAuth tokens - these are auth-gateway tokens from /oauth/token
|
|
706
|
+
// Note: OAuth tokens are valid for MCP services but not for direct API access
|
|
707
707
|
await config.setToken(tokens.access_token);
|
|
708
708
|
await config.set('refresh_token', tokens.refresh_token);
|
|
709
709
|
await config.set('token_expires_at', Date.now() + (tokens.expires_in * 1000));
|
|
710
710
|
await config.set('authMethod', 'oauth');
|
|
711
|
-
|
|
712
|
-
// Store it as the vendor key equivalent for MCP and API access
|
|
713
|
-
spinner.text = 'Configuring unified access...';
|
|
714
|
-
spinner.start();
|
|
715
|
-
// Use the OAuth access token directly - it's already an auth-gateway token
|
|
716
|
-
await config.setVendorKey(tokens.access_token);
|
|
717
|
-
spinner.succeed('Unified authentication configured');
|
|
711
|
+
spinner.succeed('OAuth tokens stored');
|
|
718
712
|
console.log();
|
|
719
713
|
console.log(chalk.green('โ OAuth2 authentication successful'));
|
|
720
|
-
console.log(colors.info('You can now use
|
|
721
|
-
console.log(
|
|
714
|
+
console.log(colors.info('You can now use MCP integration features'));
|
|
715
|
+
console.log();
|
|
716
|
+
console.log(chalk.yellow('Note: ') + chalk.gray('OAuth login enables MCP integration.'));
|
|
717
|
+
console.log(chalk.gray('For direct CLI memory commands, use:'));
|
|
718
|
+
console.log(chalk.cyan(' lanonasis auth login --vendor') + chalk.gray(' (get a vendor key from dashboard)'));
|
|
719
|
+
console.log(chalk.gray(' OR'));
|
|
720
|
+
console.log(chalk.cyan(' lanonasis auth login --credentials') + chalk.gray(' (use username/password)'));
|
|
722
721
|
process.exit(0);
|
|
723
722
|
}
|
|
724
723
|
catch (error) {
|
package/dist/commands/init.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import inquirer from 'inquirer';
|
|
3
|
+
import { dirname, join } from 'path';
|
|
3
4
|
import { CLIConfig } from '../utils/config.js';
|
|
5
|
+
import { createOnboardingFlow } from '../ux/index.js';
|
|
4
6
|
export async function initCommand(options) {
|
|
5
7
|
const config = new CLIConfig();
|
|
8
|
+
await config.init();
|
|
6
9
|
console.log(chalk.blue.bold('๐ Initializing MaaS CLI'));
|
|
7
10
|
console.log();
|
|
8
11
|
// Check if config already exists
|
|
@@ -21,6 +24,15 @@ export async function initCommand(options) {
|
|
|
21
24
|
return;
|
|
22
25
|
}
|
|
23
26
|
}
|
|
27
|
+
const onboardingConfigPath = join(dirname(config.getConfigPath()), 'onboarding.json');
|
|
28
|
+
const onboardingFlow = createOnboardingFlow(onboardingConfigPath);
|
|
29
|
+
const setupResult = await onboardingFlow.runInitialSetup();
|
|
30
|
+
if (!setupResult.completed && setupResult.issues && setupResult.issues.length > 0) {
|
|
31
|
+
console.log(chalk.yellow('โ ๏ธ Onboarding completed with issues:'));
|
|
32
|
+
setupResult.issues.forEach((issue) => console.log(chalk.yellow(` โข ${issue}`)));
|
|
33
|
+
}
|
|
34
|
+
// Reload config after onboarding to preserve generated defaults
|
|
35
|
+
await config.load();
|
|
24
36
|
// Get configuration
|
|
25
37
|
const answers = await inquirer.prompt([
|
|
26
38
|
{
|
package/dist/commands/mcp.js
CHANGED
|
@@ -5,6 +5,8 @@ import { getMCPClient } from '../utils/mcp-client.js';
|
|
|
5
5
|
import { EnhancedMCPClient } from '../mcp/client/enhanced-client.js';
|
|
6
6
|
import { CLIConfig } from '../utils/config.js';
|
|
7
7
|
import WebSocket from 'ws';
|
|
8
|
+
import { dirname, join } from 'path';
|
|
9
|
+
import { createConnectionManager } from '../ux/index.js';
|
|
8
10
|
/**
|
|
9
11
|
* Register MCP-related CLI commands (mcp and mcp-server) on a Commander program.
|
|
10
12
|
*
|
|
@@ -79,6 +81,7 @@ export function mcpCommands(program) {
|
|
|
79
81
|
.action(async (options) => {
|
|
80
82
|
const spinner = ora('Connecting to MCP server...').start();
|
|
81
83
|
const config = new CLIConfig();
|
|
84
|
+
await config.init();
|
|
82
85
|
try {
|
|
83
86
|
let connectionMode;
|
|
84
87
|
// Determine connection mode - WebSocket takes precedence over remote and local
|
|
@@ -112,6 +115,30 @@ export function mcpCommands(program) {
|
|
|
112
115
|
let connected = false;
|
|
113
116
|
// Use Enhanced MCP Client for better connection handling
|
|
114
117
|
const enhancedClient = new EnhancedMCPClient();
|
|
118
|
+
if (connectionMode === 'local' && !options.localArgs && !options.url) {
|
|
119
|
+
const configDir = dirname(config.getConfigPath());
|
|
120
|
+
const manager = createConnectionManager(join(configDir, 'mcp-config.json'));
|
|
121
|
+
// Initialize manager to load persisted config
|
|
122
|
+
await manager.init();
|
|
123
|
+
if (options.server) {
|
|
124
|
+
await manager.updateConfig({ localServerPath: options.server });
|
|
125
|
+
}
|
|
126
|
+
const result = await manager.connectLocal();
|
|
127
|
+
if (result.success) {
|
|
128
|
+
spinner.succeed(chalk.green('Connected to local MCP server'));
|
|
129
|
+
process.exit(0);
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
spinner.fail(result.error || 'Failed to connect to local MCP server');
|
|
133
|
+
if (result.suggestions && result.suggestions.length > 0) {
|
|
134
|
+
result.suggestions.forEach((suggestion) => {
|
|
135
|
+
console.log(chalk.yellow(` โข ${suggestion}`));
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
process.exit(1);
|
|
139
|
+
}
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
115
142
|
if (options.url) {
|
|
116
143
|
// Connect to specific URL (WebSocket or remote)
|
|
117
144
|
const serverConfig = {
|
|
@@ -185,12 +212,38 @@ export function mcpCommands(program) {
|
|
|
185
212
|
let healthLabel = chalk.gray('Unknown');
|
|
186
213
|
let healthDetails;
|
|
187
214
|
let isServiceReachable = false;
|
|
215
|
+
let resolvedHealthUrl;
|
|
188
216
|
try {
|
|
189
217
|
const axios = (await import('axios')).default;
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
218
|
+
const normalizeMcpHealthUrl = (inputUrl) => {
|
|
219
|
+
const parsed = new URL(inputUrl);
|
|
220
|
+
if (parsed.protocol === 'wss:') {
|
|
221
|
+
parsed.protocol = 'https:';
|
|
222
|
+
}
|
|
223
|
+
else if (parsed.protocol === 'ws:') {
|
|
224
|
+
parsed.protocol = 'http:';
|
|
225
|
+
}
|
|
226
|
+
parsed.pathname = '/health';
|
|
227
|
+
parsed.search = '';
|
|
228
|
+
parsed.hash = '';
|
|
229
|
+
return parsed.toString();
|
|
230
|
+
};
|
|
231
|
+
// Prefer MCP host health based on active mode:
|
|
232
|
+
// - websocket: use configured websocket host (wss -> https)
|
|
233
|
+
// - remote: use configured MCP REST host
|
|
234
|
+
// - local/default: fall back to discovered MCP REST host
|
|
235
|
+
let healthProbeBase;
|
|
236
|
+
if (status.mode === 'websocket') {
|
|
237
|
+
healthProbeBase = config.get('mcpWebSocketUrl') ?? config.getMCPServerUrl();
|
|
238
|
+
}
|
|
239
|
+
else if (status.mode === 'remote') {
|
|
240
|
+
healthProbeBase = config.get('mcpServerUrl') ?? config.getMCPRestUrl();
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
healthProbeBase = config.getMCPRestUrl();
|
|
244
|
+
}
|
|
245
|
+
const healthUrl = normalizeMcpHealthUrl(healthProbeBase);
|
|
246
|
+
resolvedHealthUrl = healthUrl;
|
|
194
247
|
const token = config.getToken();
|
|
195
248
|
const vendorKey = await config.getVendorKeyAsync();
|
|
196
249
|
const headers = {};
|
|
@@ -207,7 +260,8 @@ export function mcpCommands(program) {
|
|
|
207
260
|
timeout: 5000
|
|
208
261
|
});
|
|
209
262
|
const overallStatus = String(response.data?.status ?? '').toLowerCase();
|
|
210
|
-
const
|
|
263
|
+
const okStatuses = new Set(['healthy', 'ok', 'up']);
|
|
264
|
+
const ok = response.status === 200 && (!overallStatus || okStatuses.has(overallStatus));
|
|
211
265
|
if (ok) {
|
|
212
266
|
healthLabel = chalk.green('Healthy');
|
|
213
267
|
isServiceReachable = true;
|
|
@@ -258,6 +312,9 @@ export function mcpCommands(program) {
|
|
|
258
312
|
if (healthDetails && process.env.CLI_VERBOSE === 'true') {
|
|
259
313
|
console.log(chalk.gray(`Health details: ${healthDetails}`));
|
|
260
314
|
}
|
|
315
|
+
if (resolvedHealthUrl && process.env.CLI_VERBOSE === 'true') {
|
|
316
|
+
console.log(chalk.gray(`Health probe URL: ${resolvedHealthUrl}`));
|
|
317
|
+
}
|
|
261
318
|
// Show features when service is reachable
|
|
262
319
|
if (isServiceReachable) {
|
|
263
320
|
if (status.mode === 'remote') {
|
package/dist/commands/memory.js
CHANGED
|
@@ -6,6 +6,33 @@ import wrap from 'word-wrap';
|
|
|
6
6
|
import { format } from 'date-fns';
|
|
7
7
|
import { apiClient } from '../utils/api.js';
|
|
8
8
|
import { formatBytes, truncateText } from '../utils/formatting.js';
|
|
9
|
+
import { CLIConfig } from '../utils/config.js';
|
|
10
|
+
import { createTextInputHandler } from '../ux/index.js';
|
|
11
|
+
const resolveInputMode = async () => {
|
|
12
|
+
const config = new CLIConfig();
|
|
13
|
+
await config.init();
|
|
14
|
+
const directMode = config.get('inputMode');
|
|
15
|
+
const userPrefs = config.get('userPreferences');
|
|
16
|
+
const resolved = (directMode || userPrefs?.inputMode);
|
|
17
|
+
return resolved === 'editor' ? 'editor' : 'inline';
|
|
18
|
+
};
|
|
19
|
+
const collectMemoryContent = async (prompt, inputMode, defaultContent) => {
|
|
20
|
+
if (inputMode === 'editor') {
|
|
21
|
+
const { content } = await inquirer.prompt([
|
|
22
|
+
{
|
|
23
|
+
type: 'editor',
|
|
24
|
+
name: 'content',
|
|
25
|
+
message: prompt,
|
|
26
|
+
default: defaultContent,
|
|
27
|
+
},
|
|
28
|
+
]);
|
|
29
|
+
return content;
|
|
30
|
+
}
|
|
31
|
+
const handler = createTextInputHandler();
|
|
32
|
+
return handler.collectMultilineInput(prompt, {
|
|
33
|
+
defaultContent,
|
|
34
|
+
});
|
|
35
|
+
};
|
|
9
36
|
export function memoryCommands(program) {
|
|
10
37
|
// Create memory
|
|
11
38
|
program
|
|
@@ -22,39 +49,42 @@ export function memoryCommands(program) {
|
|
|
22
49
|
try {
|
|
23
50
|
let { title, content, type, tags, topicId, interactive } = options;
|
|
24
51
|
if (interactive || (!title || !content)) {
|
|
52
|
+
const inputMode = await resolveInputMode();
|
|
25
53
|
const answers = await inquirer.prompt([
|
|
26
54
|
{
|
|
27
55
|
type: 'input',
|
|
28
56
|
name: 'title',
|
|
29
57
|
message: 'Memory title:',
|
|
30
58
|
default: title,
|
|
31
|
-
validate: (input) => input.length > 0 || 'Title is required'
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
type: 'input',
|
|
35
|
-
name: 'content',
|
|
36
|
-
message: 'Memory content (or use -c flag for multi-line):',
|
|
37
|
-
default: content,
|
|
38
|
-
validate: (input) => input.length > 0 || 'Content is required'
|
|
59
|
+
validate: (input) => input.length > 0 || 'Title is required',
|
|
39
60
|
},
|
|
40
61
|
{
|
|
41
62
|
type: 'list',
|
|
42
63
|
name: 'type',
|
|
43
64
|
message: 'Memory type:',
|
|
44
65
|
choices: ['conversation', 'knowledge', 'project', 'context', 'reference'],
|
|
45
|
-
default: type || 'context'
|
|
66
|
+
default: type || 'context',
|
|
46
67
|
},
|
|
47
68
|
{
|
|
48
69
|
type: 'input',
|
|
49
70
|
name: 'tags',
|
|
50
71
|
message: 'Tags (comma-separated):',
|
|
51
|
-
default: tags || ''
|
|
52
|
-
}
|
|
72
|
+
default: tags || '',
|
|
73
|
+
},
|
|
53
74
|
]);
|
|
54
75
|
title = answers.title;
|
|
55
|
-
content = answers.content;
|
|
56
76
|
type = answers.type;
|
|
57
77
|
tags = answers.tags;
|
|
78
|
+
const shouldPromptContent = !content || (interactive && inputMode === 'editor');
|
|
79
|
+
if (shouldPromptContent) {
|
|
80
|
+
content = await collectMemoryContent('Memory content:', inputMode, content);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (!title || title.trim().length === 0) {
|
|
84
|
+
throw new Error('Title is required');
|
|
85
|
+
}
|
|
86
|
+
if (!content || content.trim().length === 0) {
|
|
87
|
+
throw new Error('Content is required');
|
|
58
88
|
}
|
|
59
89
|
const spinner = ora('Creating memory...').start();
|
|
60
90
|
const memoryData = {
|
|
@@ -275,36 +305,32 @@ export function memoryCommands(program) {
|
|
|
275
305
|
const spinner = ora('Fetching current memory...').start();
|
|
276
306
|
const currentMemory = await apiClient.getMemory(id);
|
|
277
307
|
spinner.stop();
|
|
308
|
+
const inputMode = await resolveInputMode();
|
|
278
309
|
const answers = await inquirer.prompt([
|
|
279
310
|
{
|
|
280
311
|
type: 'input',
|
|
281
312
|
name: 'title',
|
|
282
313
|
message: 'Title:',
|
|
283
|
-
default: currentMemory.title
|
|
284
|
-
},
|
|
285
|
-
{
|
|
286
|
-
type: 'editor',
|
|
287
|
-
name: 'content',
|
|
288
|
-
message: 'Content:',
|
|
289
|
-
default: currentMemory.content
|
|
314
|
+
default: currentMemory.title,
|
|
290
315
|
},
|
|
291
316
|
{
|
|
292
317
|
type: 'list',
|
|
293
318
|
name: 'type',
|
|
294
319
|
message: 'Memory type:',
|
|
295
320
|
choices: ['conversation', 'knowledge', 'project', 'context', 'reference'],
|
|
296
|
-
default: currentMemory.memory_type
|
|
321
|
+
default: currentMemory.memory_type,
|
|
297
322
|
},
|
|
298
323
|
{
|
|
299
324
|
type: 'input',
|
|
300
325
|
name: 'tags',
|
|
301
326
|
message: 'Tags (comma-separated):',
|
|
302
|
-
default: currentMemory.tags
|
|
303
|
-
}
|
|
327
|
+
default: currentMemory.tags?.join(', ') || '',
|
|
328
|
+
},
|
|
304
329
|
]);
|
|
330
|
+
const content = await collectMemoryContent('Content:', inputMode, currentMemory.content);
|
|
305
331
|
updateData = {
|
|
306
332
|
title: answers.title,
|
|
307
|
-
content
|
|
333
|
+
content,
|
|
308
334
|
memory_type: answers.type,
|
|
309
335
|
tags: answers.tags.split(',').map((tag) => tag.trim()).filter(Boolean)
|
|
310
336
|
};
|
package/dist/index.js
CHANGED
|
@@ -12,6 +12,8 @@ import { mcpCommands } from './commands/mcp.js';
|
|
|
12
12
|
import apiKeysCommand from './commands/api-keys.js';
|
|
13
13
|
import { CLIConfig } from './utils/config.js';
|
|
14
14
|
import { getMCPClient } from './utils/mcp-client.js';
|
|
15
|
+
import { dirname, join } from 'path';
|
|
16
|
+
import { createOnboardingFlow } from './ux/index.js';
|
|
15
17
|
// Load environment variables
|
|
16
18
|
config();
|
|
17
19
|
import { createRequire } from 'module';
|
|
@@ -51,6 +53,24 @@ program
|
|
|
51
53
|
process.env.MEMORY_API_URL = opts.apiUrl;
|
|
52
54
|
}
|
|
53
55
|
process.env.CLI_OUTPUT_FORMAT = opts.output;
|
|
56
|
+
const skipOnboarding = actionCommand.name() === 'init' ||
|
|
57
|
+
actionCommand.name() === 'auth' ||
|
|
58
|
+
actionCommand.parent?.name?.() === 'auth';
|
|
59
|
+
if (!skipOnboarding) {
|
|
60
|
+
try {
|
|
61
|
+
const onboardingConfigPath = join(dirname(cliConfig.getConfigPath()), 'onboarding.json');
|
|
62
|
+
const onboardingFlow = createOnboardingFlow(onboardingConfigPath);
|
|
63
|
+
if (onboardingFlow.detectFirstRun()) {
|
|
64
|
+
await onboardingFlow.runInitialSetup();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
if (process.env.CLI_VERBOSE === 'true') {
|
|
69
|
+
console.log(colors.warning('Onboarding skipped due to error'));
|
|
70
|
+
console.log(colors.muted(`Error: ${error instanceof Error ? error.message : String(error)}`));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
54
74
|
// Auto-initialize MCP unless disabled
|
|
55
75
|
const isMcpFlow = actionCommand.name() === 'mcp' ||
|
|
56
76
|
actionCommand.parent?.name?.() === 'mcp' ||
|