@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
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# Changelog - @lanonasis/cli
|
|
2
|
+
|
|
3
|
+
## [3.9.0] - 2026-02-01
|
|
4
|
+
|
|
5
|
+
### ๐จ CLI UX Revolution
|
|
6
|
+
|
|
7
|
+
#### Seamless Multi-Line Text Input
|
|
8
|
+
- **Inline Text Editor**: Professional multi-line text input without external editors
|
|
9
|
+
- Raw terminal mode for keystroke capture
|
|
10
|
+
- Full editing support (arrow keys, backspace, newlines)
|
|
11
|
+
- Visual feedback with line numbers and cursor indicators
|
|
12
|
+
- Submit with Ctrl+D, cancel with Ctrl+C
|
|
13
|
+
- Configurable fallback to external editors
|
|
14
|
+
|
|
15
|
+
#### Intelligent MCP Server Connection Management
|
|
16
|
+
- **Auto-Configuration**: Automatically detects and configures embedded MCP servers
|
|
17
|
+
- **Connection Lifecycle**: Smart server process management with health monitoring
|
|
18
|
+
- **Persistent Configuration**: Saves and loads user preferences across sessions
|
|
19
|
+
- **Connection Verification**: Validates server connectivity before operations
|
|
20
|
+
- **Graceful Error Handling**: Clear error messages with actionable resolution steps
|
|
21
|
+
|
|
22
|
+
#### First-Run Onboarding Experience
|
|
23
|
+
- **Guided Setup**: Interactive onboarding flow for new users
|
|
24
|
+
- **Connectivity Testing**: Automatic testing of API endpoints and services
|
|
25
|
+
- **Smart Defaults**: Configures optimal settings based on environment
|
|
26
|
+
- **User Preferences**: Captures and persists input mode, editor choice, and behavior preferences
|
|
27
|
+
- **Troubleshooting Guidance**: Context-aware help when issues are detected
|
|
28
|
+
|
|
29
|
+
### ๐ Critical Bug Fixes (PR #93)
|
|
30
|
+
|
|
31
|
+
#### P1: Connection Verification False Positive
|
|
32
|
+
- **Issue**: `verifyConnection()` returned `true` even when server was in error/stopped state
|
|
33
|
+
- **Fix**: Added explicit checks for error and stopped states before declaring success
|
|
34
|
+
- **Impact**: Users will now see accurate connection status instead of false positives
|
|
35
|
+
|
|
36
|
+
#### P2: Configuration Not Loaded Before Use
|
|
37
|
+
- **Issue**: `ConnectionManager.init()` method existed but was never called
|
|
38
|
+
- **Fix**: Added `init()` to ConnectionManager interface and call it before `connectLocal()`
|
|
39
|
+
- **Impact**: User configuration is now properly loaded and respected
|
|
40
|
+
|
|
41
|
+
#### P2: Empty Content Overwrites in Inline Updates
|
|
42
|
+
- **Issue**: When updating memories in inline mode, `defaultContent` wasn't passed to TextInputHandler
|
|
43
|
+
- **Fix**: Added `defaultContent` support throughout the text input pipeline
|
|
44
|
+
- **Impact**: Memory updates preserve existing content instead of starting with blank slate
|
|
45
|
+
|
|
46
|
+
### ๐งช Testing & Quality
|
|
47
|
+
|
|
48
|
+
- **Comprehensive Test Suite**: 168 passing tests including property-based tests
|
|
49
|
+
- **Zero TypeScript Errors**: All compilation errors resolved
|
|
50
|
+
- **No Regressions**: All existing tests continue to pass
|
|
51
|
+
- **Professional Documentation**: Complete inline documentation and type definitions
|
|
52
|
+
|
|
53
|
+
### ๐ฆ Package Cleanup
|
|
54
|
+
|
|
55
|
+
- **npmignore**: Excludes test files and development artifacts from published package
|
|
56
|
+
- **Directory Reorganization**: Cleaner structure with examples moved to `docs/examples/`
|
|
57
|
+
- **Build Optimization**: Reduced package size by excluding unnecessary files
|
|
58
|
+
|
|
59
|
+
### ๐ Breaking Changes
|
|
60
|
+
None - Fully backward compatible
|
|
61
|
+
|
|
62
|
+
### ๐ Technical Details
|
|
63
|
+
|
|
64
|
+
**New Implementations**:
|
|
65
|
+
- `TextInputHandlerImpl` ([cli/src/ux/implementations/TextInputHandlerImpl.ts](cli/src/ux/implementations/TextInputHandlerImpl.ts))
|
|
66
|
+
- `ConnectionManagerImpl` ([cli/src/ux/implementations/ConnectionManagerImpl.ts](cli/src/ux/implementations/ConnectionManagerImpl.ts))
|
|
67
|
+
- `OnboardingFlowImpl` ([cli/src/ux/implementations/OnboardingFlowImpl.ts](cli/src/ux/implementations/OnboardingFlowImpl.ts))
|
|
68
|
+
|
|
69
|
+
**Integration Points**:
|
|
70
|
+
- Memory commands now use inline text input by default ([cli/src/commands/memory.ts](cli/src/commands/memory.ts:116-119))
|
|
71
|
+
- MCP connect command uses ConnectionManager ([cli/src/commands/mcp.ts](cli/src/commands/mcp.ts:130-137))
|
|
72
|
+
- Init command includes onboarding flow ([cli/src/commands/init.ts](cli/src/commands/init.ts))
|
|
73
|
+
|
|
74
|
+
## [3.7.0] - 2025-11-23
|
|
75
|
+
|
|
76
|
+
### ๐ Security Infrastructure Upgrade
|
|
77
|
+
|
|
78
|
+
#### Enhanced API Key Security with SHA-256
|
|
79
|
+
- **Cross-Platform SHA-256 Hashing**: Unified hash utilities for consistent API key hashing across all platforms
|
|
80
|
+
- **Local Hash Implementation**: Isolated hash utilities (`src/utils/hash-utils.ts`) for CLI independence
|
|
81
|
+
- **Double-Hash Prevention**: Smart detection of pre-hashed keys to prevent double-hashing errors
|
|
82
|
+
- **Server-Side Validation**: Constant-time comparison for timing-attack prevention
|
|
83
|
+
- **Future NPM Package Ready**: Designed for eventual migration to `@lanonasis/security` npm package
|
|
84
|
+
|
|
85
|
+
#### Technical Improvements
|
|
86
|
+
- **Build Stability**: Fixed TypeScript `rootDir` compilation errors
|
|
87
|
+
- **Zero Deprecation Warnings**: All dependencies verified for production readiness
|
|
88
|
+
- **Cross-Platform Compatibility**: Node.js crypto for server-side, Web Crypto API fallback for browser contexts
|
|
89
|
+
- **Type Safety**: Full TypeScript support with exported hash types (`ApiKeyHash`, `ApiKey`)
|
|
90
|
+
|
|
91
|
+
#### Hash Utility Functions
|
|
92
|
+
```typescript
|
|
93
|
+
// Available in CLI
|
|
94
|
+
ensureApiKeyHash(apiKey: string): string // Smart hash normalization
|
|
95
|
+
hashApiKey(apiKey: string): string // SHA-256 hashing
|
|
96
|
+
isSha256Hash(value: string): boolean // Hash detection
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### ๐ก๏ธ Security Features
|
|
100
|
+
- โ
SHA-256 cryptographic hashing for all API keys
|
|
101
|
+
- โ
Prevents plaintext key transmission
|
|
102
|
+
- โ
Constant-time hash comparison
|
|
103
|
+
- โ
Automatic hash detection and normalization
|
|
104
|
+
- โ
Compatible with existing vendor key authentication
|
|
105
|
+
|
|
106
|
+
### ๐ Breaking Changes
|
|
107
|
+
None - Fully backward compatible
|
|
108
|
+
|
|
109
|
+
### ๐ฆ Dependencies
|
|
110
|
+
- No new external dependencies
|
|
111
|
+
- Uses native Node.js `crypto` module
|
|
112
|
+
- Clean build with zero deprecation warnings
|
|
113
|
+
|
|
114
|
+
## [3.0.1] - 2025-10-08
|
|
115
|
+
|
|
116
|
+
### ๐ Major Version Bump
|
|
117
|
+
This is a major version release (3.0) due to the significant MCP architectural changes and new capabilities that may affect existing integrations.
|
|
118
|
+
|
|
119
|
+
### ๐ Major Features
|
|
120
|
+
*Same as 2.0.9 but republished as 3.0.1 due to npm version conflict*
|
|
121
|
+
|
|
122
|
+
## [2.0.9] - 2025-10-08 (npm publish conflict)
|
|
123
|
+
|
|
124
|
+
### ๐ Major Features
|
|
125
|
+
|
|
126
|
+
#### Enhanced Model Context Protocol (MCP) Support
|
|
127
|
+
- **Multi-Server Connections**: Connect to multiple MCP servers simultaneously with automatic failover
|
|
128
|
+
- **Advanced Error Handling**: Exponential backoff retry logic and graceful degradation
|
|
129
|
+
- **Health Monitoring**: Automatic health checks with latency tracking and auto-reconnection
|
|
130
|
+
- **Connection Pooling**: Efficient resource management for multiple connections
|
|
131
|
+
- **Tool Chain Execution**: Support for sequential and parallel tool execution
|
|
132
|
+
|
|
133
|
+
#### New MCP Infrastructure
|
|
134
|
+
- **Enhanced MCP Client** (`src/mcp/client/enhanced-client.ts`)
|
|
135
|
+
- Multi-server management with priority-based selection
|
|
136
|
+
- Event-driven architecture with connection status tracking
|
|
137
|
+
- Automatic failover to backup servers
|
|
138
|
+
|
|
139
|
+
- **MCP Server Implementation** (`src/mcp/server/lanonasis-server.ts`)
|
|
140
|
+
- Full MCP protocol compliance (tools, resources, prompts)
|
|
141
|
+
- 16 registered tools for memory, topic, and system operations
|
|
142
|
+
- Resource providers for data access
|
|
143
|
+
- Interactive prompts for user guidance
|
|
144
|
+
|
|
145
|
+
- **Transport Support** (`src/mcp/transports/transport-manager.ts`)
|
|
146
|
+
- StdIO transport for local processes
|
|
147
|
+
- WebSocket transport with auto-reconnection
|
|
148
|
+
- SSE (Server-Sent Events) for streaming
|
|
149
|
+
- Authentication support (Bearer, API Key, Basic)
|
|
150
|
+
|
|
151
|
+
- **Schema Validation** (`src/mcp/schemas/tool-schemas.ts`)
|
|
152
|
+
- Zod-based validation for all MCP tools
|
|
153
|
+
- Type-safe operations with clear error messages
|
|
154
|
+
- Comprehensive schemas for memory, topic, API key, and system operations
|
|
155
|
+
|
|
156
|
+
### ๐ Technical Improvements
|
|
157
|
+
- **Build System**: New MCP-specific build scripts (`build:mcp`, `dev:mcp`, `test:mcp`)
|
|
158
|
+
- **Module Structure**: Dedicated `/src/mcp/` directory with clean separation of concerns
|
|
159
|
+
- **Error Recovery**: Improved error handling throughout the MCP stack
|
|
160
|
+
- **Type Safety**: Full TypeScript support with proper type definitions
|
|
161
|
+
|
|
162
|
+
### ๐ Bug Fixes
|
|
163
|
+
- Fixed authentication flow issues with proper token validation
|
|
164
|
+
- Resolved double slash URL construction in CLI auth
|
|
165
|
+
- Fixed memory command authentication requirements
|
|
166
|
+
- Corrected error messages to show correct authentication command
|
|
167
|
+
|
|
168
|
+
### ๐ Documentation
|
|
169
|
+
- Enhanced README with MCP usage examples
|
|
170
|
+
- Added MCP Server Mode documentation
|
|
171
|
+
- Updated command reference with new MCP features
|
|
172
|
+
- Created comprehensive MCP enhancement summary
|
|
173
|
+
|
|
174
|
+
### โ ๏ธ Breaking Changes
|
|
175
|
+
- HTTP transport temporarily disabled in favor of WebSocket/StdIO (more reliable)
|
|
176
|
+
- Some API key operations pending full implementation
|
|
177
|
+
|
|
178
|
+
### ๐ Dependencies
|
|
179
|
+
- Updated to latest @modelcontextprotocol/sdk
|
|
180
|
+
- Added ws for WebSocket support
|
|
181
|
+
- Added zod for schema validation
|
|
182
|
+
|
|
183
|
+
## [2.0.8] - Previous Version
|
|
184
|
+
- Authentication system improvements
|
|
185
|
+
- CLI guided setup enhancements
|
|
186
|
+
- Performance optimizations
|
|
187
|
+
|
|
188
|
+
## [2.0.7] - Previous Version
|
|
189
|
+
- Memory management improvements
|
|
190
|
+
- Topic organization features
|
|
191
|
+
- Bug fixes and stability improvements
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
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).
|
package/dist/commands/auth.js
CHANGED
|
@@ -707,7 +707,7 @@ async function handleOAuthFlow(config) {
|
|
|
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
|
-
await config.set('authMethod', '
|
|
710
|
+
await config.set('authMethod', 'oauth');
|
|
711
711
|
// The OAuth access token from auth-gateway works as the API token for all services
|
|
712
712
|
// Store it as the vendor key equivalent for MCP and API access
|
|
713
713
|
spinner.text = 'Configuring unified access...';
|
package/dist/commands/config.js
CHANGED
|
@@ -391,8 +391,9 @@ export function configCommands(program) {
|
|
|
391
391
|
else {
|
|
392
392
|
console.log(chalk.green(' โ Authentication credentials found'));
|
|
393
393
|
// Validate auth method consistency
|
|
394
|
-
|
|
395
|
-
|
|
394
|
+
// Note: OAuth users can have vendorKey stored (for MCP access) while authMethod is 'oauth'
|
|
395
|
+
if (vendorKey && authMethod !== 'vendor_key' && authMethod !== 'oauth') {
|
|
396
|
+
console.log(chalk.yellow(' โ Auth method mismatch (has vendor key but method is not vendor_key or oauth)'));
|
|
396
397
|
validation.issues.push('Auth method mismatch');
|
|
397
398
|
if (options.repair) {
|
|
398
399
|
config.set('authMethod', 'vendor_key');
|
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 = {
|
|
@@ -169,6 +196,7 @@ export function mcpCommands(program) {
|
|
|
169
196
|
const client = getMCPClient();
|
|
170
197
|
await client.disconnect();
|
|
171
198
|
console.log(chalk.green('โ Disconnected from MCP server'));
|
|
199
|
+
process.exit(0);
|
|
172
200
|
});
|
|
173
201
|
// Status command
|
|
174
202
|
mcp.command('status')
|
|
@@ -183,6 +211,7 @@ export function mcpCommands(program) {
|
|
|
183
211
|
await config.init();
|
|
184
212
|
let healthLabel = chalk.gray('Unknown');
|
|
185
213
|
let healthDetails;
|
|
214
|
+
let isServiceReachable = false;
|
|
186
215
|
try {
|
|
187
216
|
const axios = (await import('axios')).default;
|
|
188
217
|
// Derive MCP health URL from discovered REST base (e.g. https://mcp.lanonasis.com/api/v1 -> https://mcp.lanonasis.com/health)
|
|
@@ -207,14 +236,17 @@ export function mcpCommands(program) {
|
|
|
207
236
|
const overallStatus = String(response.data?.status ?? '').toLowerCase();
|
|
208
237
|
const ok = response.status === 200 && (!overallStatus || overallStatus === 'healthy');
|
|
209
238
|
if (ok) {
|
|
210
|
-
healthLabel = chalk.green('
|
|
239
|
+
healthLabel = chalk.green('Healthy');
|
|
240
|
+
isServiceReachable = true;
|
|
211
241
|
}
|
|
212
242
|
else {
|
|
213
243
|
healthLabel = chalk.yellow('Degraded');
|
|
244
|
+
isServiceReachable = true; // Service is reachable but degraded
|
|
214
245
|
}
|
|
215
246
|
}
|
|
216
247
|
catch (error) {
|
|
217
248
|
healthLabel = chalk.red('Unreachable');
|
|
249
|
+
isServiceReachable = false;
|
|
218
250
|
if (error instanceof Error) {
|
|
219
251
|
healthDetails = error.message;
|
|
220
252
|
}
|
|
@@ -224,7 +256,14 @@ export function mcpCommands(program) {
|
|
|
224
256
|
}
|
|
225
257
|
console.log(chalk.cyan('\n๐ MCP Connection Status'));
|
|
226
258
|
console.log(chalk.cyan('========================'));
|
|
227
|
-
|
|
259
|
+
// Show status based on service reachability, not in-memory connection state
|
|
260
|
+
// The CLI isn't a persistent daemon - "connected" means the service is available
|
|
261
|
+
if (isServiceReachable) {
|
|
262
|
+
console.log(`Status: ${chalk.green('Ready')} (service reachable)`);
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
console.log(`Status: ${chalk.red('Unavailable')} (service unreachable)`);
|
|
266
|
+
}
|
|
228
267
|
// Display mode with proper labels
|
|
229
268
|
let modeDisplay;
|
|
230
269
|
switch (status.mode) {
|
|
@@ -246,7 +285,8 @@ export function mcpCommands(program) {
|
|
|
246
285
|
if (healthDetails && process.env.CLI_VERBOSE === 'true') {
|
|
247
286
|
console.log(chalk.gray(`Health details: ${healthDetails}`));
|
|
248
287
|
}
|
|
249
|
-
|
|
288
|
+
// Show features when service is reachable
|
|
289
|
+
if (isServiceReachable) {
|
|
250
290
|
if (status.mode === 'remote') {
|
|
251
291
|
console.log(`\n${chalk.cyan('Features:')}`);
|
|
252
292
|
console.log('โข Real-time updates via SSE');
|
|
@@ -259,7 +299,12 @@ export function mcpCommands(program) {
|
|
|
259
299
|
console.log('โข Authenticated WebSocket connection');
|
|
260
300
|
console.log('โข Production-ready MCP server');
|
|
261
301
|
}
|
|
302
|
+
console.log(chalk.green('\nโ MCP tools are available. Run "lanonasis mcp tools" to see them.'));
|
|
303
|
+
}
|
|
304
|
+
else {
|
|
305
|
+
console.log(chalk.yellow('\nโ MCP service is not reachable. Run "lanonasis mcp diagnose" for troubleshooting.'));
|
|
262
306
|
}
|
|
307
|
+
process.exit(0);
|
|
263
308
|
});
|
|
264
309
|
// List tools command
|
|
265
310
|
mcp.command('tools')
|
|
@@ -456,6 +501,7 @@ export function mcpCommands(program) {
|
|
|
456
501
|
console.log(' --prefer-local : Use local stdio mode (development only)');
|
|
457
502
|
console.log(' --auto : Auto-detect based on configuration (default)');
|
|
458
503
|
}
|
|
504
|
+
process.exit(0);
|
|
459
505
|
});
|
|
460
506
|
// Start MCP server for external clients
|
|
461
507
|
mcp.command('start')
|
|
@@ -790,5 +836,6 @@ export function mcpCommands(program) {
|
|
|
790
836
|
console.log(chalk.gray(' โข Verify your network allows outbound HTTPS connections'));
|
|
791
837
|
console.log(chalk.gray(' โข Contact support if issues persist'));
|
|
792
838
|
}
|
|
839
|
+
process.exit(0);
|
|
793
840
|
});
|
|
794
841
|
}
|
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: 'editor',
|
|
35
|
-
name: 'content',
|
|
36
|
-
message: 'Memory content:',
|
|
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' ||
|
|
@@ -192,7 +192,7 @@ export class MemoryAccessControl {
|
|
|
192
192
|
const apiUrl = this.config.get('apiUrl') || 'https://api.lanonasis.com';
|
|
193
193
|
const token = this.config.get('token');
|
|
194
194
|
const axios = (await import('axios')).default;
|
|
195
|
-
const response = await axios.get(`${apiUrl}/api/v1/
|
|
195
|
+
const response = await axios.get(`${apiUrl}/api/v1/memories/${memoryId}`, {
|
|
196
196
|
headers: {
|
|
197
197
|
'Authorization': `Bearer ${token}`,
|
|
198
198
|
'Content-Type': 'application/json'
|
|
@@ -210,7 +210,7 @@ export class MemoryAccessControl {
|
|
|
210
210
|
const apiUrl = this.config.get('apiUrl') || 'https://api.lanonasis.com';
|
|
211
211
|
const token = this.config.get('token');
|
|
212
212
|
const axios = (await import('axios')).default;
|
|
213
|
-
const response = await axios.get(`${apiUrl}/api/v1/
|
|
213
|
+
const response = await axios.get(`${apiUrl}/api/v1/memories?user_id=${userId}`, {
|
|
214
214
|
headers: {
|
|
215
215
|
'Authorization': `Bearer ${token}`,
|
|
216
216
|
'Content-Type': 'application/json'
|