@lanonasis/cli 3.9.7 → 3.9.9
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 +18 -0
- package/dist/commands/api-keys.js +7 -7
- package/dist/commands/auth.js +2 -2
- package/dist/commands/completion.js +10 -0
- package/dist/commands/guide.js +3 -3
- package/dist/commands/mcp.js +78 -11
- package/dist/commands/memory.js +544 -11
- package/dist/core/dashboard.js +4 -4
- package/dist/index.js +8 -1
- package/dist/mcp/schemas/tool-schemas.js +1 -1
- package/dist/mcp/server/lanonasis-server.js +2 -2
- package/dist/mcp-server-entry.js +0 -0
- package/dist/utils/api.d.ts +22 -1
- package/dist/utils/api.js +198 -12
- package/dist/utils/config.d.ts +10 -5
- package/dist/utils/config.js +66 -32
- package/dist/utils/mcp-client.d.ts +2 -0
- package/dist/utils/mcp-client.js +74 -46
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# Changelog - @lanonasis/cli
|
|
2
2
|
|
|
3
|
+
## [3.9.8] - 2026-02-25
|
|
4
|
+
|
|
5
|
+
### ✨ New Features
|
|
6
|
+
|
|
7
|
+
- **Issue #98 (CLI Memory UX Enhancements)**:
|
|
8
|
+
- Added `onasis memory create --json <json>` for direct JSON payload creation.
|
|
9
|
+
- Added `onasis memory create --content-file <path>` for file-based content ingestion.
|
|
10
|
+
- Added `onasis memory save-session` to persist branch/status/changed-files session context as memory.
|
|
11
|
+
- **Behavior methods via CLI commands**:
|
|
12
|
+
- Added `onasis memory intelligence` subcommands for health check, tag suggestions, related lookup, duplicate detection, insight extraction, and pattern analysis.
|
|
13
|
+
- Added `onasis memory behavior` subcommands for `record`, `recall`, and `suggest` workflow behavior operations.
|
|
14
|
+
|
|
15
|
+
### 🐛 Bug Fixes
|
|
16
|
+
|
|
17
|
+
- Normalized memory response handling for create/get/update wrappers (`{ data: ... }`) so CLI output fields like ID/Title/Type are consistently resolved.
|
|
18
|
+
- Ensured token refresh is executed before memory command paths to reduce intermittent re-auth prompts during active OAuth sessions.
|
|
19
|
+
- Aligned default semantic search thresholds to `0.55` across memory and MCP search command paths for consistent result behavior.
|
|
20
|
+
|
|
3
21
|
## [3.9.7] - 2026-02-21
|
|
4
22
|
|
|
5
23
|
### ✨ New Features
|
|
@@ -162,7 +162,7 @@ apiKeysCommand
|
|
|
162
162
|
validate: (input) => input.length > 0 || 'Value is required'
|
|
163
163
|
},
|
|
164
164
|
{
|
|
165
|
-
type: '
|
|
165
|
+
type: 'select',
|
|
166
166
|
name: 'keyType',
|
|
167
167
|
message: 'Key type:',
|
|
168
168
|
when: !keyData.keyType,
|
|
@@ -177,21 +177,21 @@ apiKeysCommand
|
|
|
177
177
|
]
|
|
178
178
|
},
|
|
179
179
|
{
|
|
180
|
-
type: '
|
|
180
|
+
type: 'select',
|
|
181
181
|
name: 'environment',
|
|
182
182
|
message: 'Environment:',
|
|
183
183
|
choices: ['development', 'staging', 'production'],
|
|
184
184
|
default: 'development'
|
|
185
185
|
},
|
|
186
186
|
{
|
|
187
|
-
type: '
|
|
187
|
+
type: 'select',
|
|
188
188
|
name: 'projectId',
|
|
189
189
|
message: 'Select project:',
|
|
190
190
|
when: !keyData.projectId && projects.length > 0,
|
|
191
191
|
choices: projects.map((p) => ({ name: `${p.name} (${p.id})`, value: p.id }))
|
|
192
192
|
},
|
|
193
193
|
{
|
|
194
|
-
type: '
|
|
194
|
+
type: 'select',
|
|
195
195
|
name: 'accessLevel',
|
|
196
196
|
message: 'Access level:',
|
|
197
197
|
choices: ['public', 'authenticated', 'team', 'admin', 'enterprise'],
|
|
@@ -543,7 +543,7 @@ mcpCommand
|
|
|
543
543
|
default: false
|
|
544
544
|
},
|
|
545
545
|
{
|
|
546
|
-
type: '
|
|
546
|
+
type: 'select',
|
|
547
547
|
name: 'riskLevel',
|
|
548
548
|
message: 'Risk level:',
|
|
549
549
|
choices: ['low', 'medium', 'high', 'critical'],
|
|
@@ -647,7 +647,7 @@ mcpCommand
|
|
|
647
647
|
const tools = await apiClient.get('/api-keys/mcp/tools');
|
|
648
648
|
const answers = await inquirer.prompt([
|
|
649
649
|
{
|
|
650
|
-
type: '
|
|
650
|
+
type: 'select',
|
|
651
651
|
name: 'toolId',
|
|
652
652
|
message: 'Select MCP tool:',
|
|
653
653
|
when: !requestData.toolId && tools.length > 0,
|
|
@@ -672,7 +672,7 @@ mcpCommand
|
|
|
672
672
|
validate: (input) => input.length > 0 || 'At least one key name is required'
|
|
673
673
|
},
|
|
674
674
|
{
|
|
675
|
-
type: '
|
|
675
|
+
type: 'select',
|
|
676
676
|
name: 'environment',
|
|
677
677
|
message: 'Environment:',
|
|
678
678
|
when: !requestData.environment,
|
package/dist/commands/auth.js
CHANGED
|
@@ -569,7 +569,7 @@ export async function loginCommand(options) {
|
|
|
569
569
|
// Show authentication options
|
|
570
570
|
const authChoice = await inquirer.prompt([
|
|
571
571
|
{
|
|
572
|
-
type: '
|
|
572
|
+
type: 'select',
|
|
573
573
|
name: 'method',
|
|
574
574
|
message: 'Choose authentication method:',
|
|
575
575
|
choices: [
|
|
@@ -821,7 +821,7 @@ async function handleCredentialsFlow(options, config) {
|
|
|
821
821
|
}
|
|
822
822
|
// Store JWT token for API authentication
|
|
823
823
|
await config.setToken(authToken);
|
|
824
|
-
await config.
|
|
824
|
+
await config.setAndSave('authMethod', 'jwt');
|
|
825
825
|
spinner.succeed('Login successful');
|
|
826
826
|
console.log();
|
|
827
827
|
console.log(chalk.green('✓ Authenticated successfully'));
|
|
@@ -132,6 +132,16 @@ export async function generateCompletionData() {
|
|
|
132
132
|
description: 'Show memory statistics',
|
|
133
133
|
options: []
|
|
134
134
|
},
|
|
135
|
+
{
|
|
136
|
+
name: 'intelligence',
|
|
137
|
+
description: 'Memory intelligence operations (use: memory intelligence --help)',
|
|
138
|
+
options: []
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
name: 'behavior',
|
|
142
|
+
description: 'Behavior pattern operations (use: memory behavior --help)',
|
|
143
|
+
options: []
|
|
144
|
+
},
|
|
135
145
|
{
|
|
136
146
|
name: 'bulk-delete',
|
|
137
147
|
description: 'Delete multiple memories',
|
package/dist/commands/guide.js
CHANGED
|
@@ -188,7 +188,7 @@ export class UserGuidanceSystem {
|
|
|
188
188
|
default: 'https://api.lanonasis.com/api/v1'
|
|
189
189
|
},
|
|
190
190
|
{
|
|
191
|
-
type: '
|
|
191
|
+
type: 'select',
|
|
192
192
|
name: 'outputFormat',
|
|
193
193
|
message: 'Preferred output format:',
|
|
194
194
|
choices: ['table', 'json', 'yaml', 'csv'],
|
|
@@ -206,7 +206,7 @@ export class UserGuidanceSystem {
|
|
|
206
206
|
console.log();
|
|
207
207
|
const { authMethod } = await inquirer.prompt([
|
|
208
208
|
{
|
|
209
|
-
type: '
|
|
209
|
+
type: 'select',
|
|
210
210
|
name: 'authMethod',
|
|
211
211
|
message: 'Choose authentication method:',
|
|
212
212
|
choices: [
|
|
@@ -335,7 +335,7 @@ export class UserGuidanceSystem {
|
|
|
335
335
|
console.log();
|
|
336
336
|
const { shell } = await inquirer.prompt([
|
|
337
337
|
{
|
|
338
|
-
type: '
|
|
338
|
+
type: 'select',
|
|
339
339
|
name: 'shell',
|
|
340
340
|
message: 'Which shell do you use?',
|
|
341
341
|
choices: [
|
package/dist/commands/mcp.js
CHANGED
|
@@ -4,9 +4,42 @@ import { table } from 'table';
|
|
|
4
4
|
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
|
+
import { apiClient } from '../utils/api.js';
|
|
7
8
|
import WebSocket from 'ws';
|
|
8
9
|
import { dirname, join } from 'path';
|
|
9
10
|
import { createConnectionManager } from '../ux/index.js';
|
|
11
|
+
const tokenizeQuery = (input) => input
|
|
12
|
+
.toLowerCase()
|
|
13
|
+
.split(/[^a-z0-9]+/g)
|
|
14
|
+
.map((token) => token.trim())
|
|
15
|
+
.filter((token) => token.length >= 2);
|
|
16
|
+
const lexicalScore = (query, memory) => {
|
|
17
|
+
const tokens = tokenizeQuery(query);
|
|
18
|
+
if (tokens.length === 0)
|
|
19
|
+
return 0;
|
|
20
|
+
const haystack = `${memory.title || ''} ${memory.content || ''} ${(memory.tags || []).join(' ')}`.toLowerCase();
|
|
21
|
+
const hits = tokens.filter((token) => haystack.includes(token)).length;
|
|
22
|
+
if (hits === 0)
|
|
23
|
+
return 0;
|
|
24
|
+
const ratio = hits / tokens.length;
|
|
25
|
+
return Math.max(0.35, Math.min(0.69, Number((ratio * 0.65).toFixed(3))));
|
|
26
|
+
};
|
|
27
|
+
const fallbackMemorySearch = async (query, limit) => {
|
|
28
|
+
const candidateLimit = Math.min(Math.max(limit * 8, 50), 200);
|
|
29
|
+
const memoriesResult = await apiClient.getMemories({ page: 1, limit: candidateLimit });
|
|
30
|
+
const candidates = (memoriesResult.memories || memoriesResult.data || []);
|
|
31
|
+
return candidates
|
|
32
|
+
.map((memory) => ({
|
|
33
|
+
id: memory.id,
|
|
34
|
+
title: memory.title,
|
|
35
|
+
memory_type: memory.memory_type,
|
|
36
|
+
similarity_score: lexicalScore(query, memory),
|
|
37
|
+
content: memory.content || ''
|
|
38
|
+
}))
|
|
39
|
+
.filter((memory) => memory.similarity_score > 0)
|
|
40
|
+
.sort((a, b) => b.similarity_score - a.similarity_score)
|
|
41
|
+
.slice(0, limit);
|
|
42
|
+
};
|
|
10
43
|
/**
|
|
11
44
|
* Register MCP-related CLI commands (mcp and mcp-server) on a Commander program.
|
|
12
45
|
*
|
|
@@ -460,25 +493,54 @@ export function mcpCommands(program) {
|
|
|
460
493
|
});
|
|
461
494
|
memory.command('search')
|
|
462
495
|
.description('Search memories via MCP')
|
|
463
|
-
.argument('<query
|
|
496
|
+
.argument('<query...>', 'Search query')
|
|
464
497
|
.option('-l, --limit <number>', 'Maximum results', '10')
|
|
465
|
-
.option('-t, --threshold <number>', 'Similarity threshold (0-1)', '0.
|
|
466
|
-
.action(async (
|
|
498
|
+
.option('-t, --threshold <number>', 'Similarity threshold (0-1)', '0.55')
|
|
499
|
+
.action(async (queryParts, options) => {
|
|
500
|
+
const query = Array.isArray(queryParts) ? queryParts.join(' ').trim() : String(queryParts || '').trim();
|
|
501
|
+
if (!query) {
|
|
502
|
+
console.error(chalk.red('Search query is required'));
|
|
503
|
+
process.exit(1);
|
|
504
|
+
}
|
|
467
505
|
const spinner = ora('Searching memories via MCP...').start();
|
|
506
|
+
const client = getMCPClient();
|
|
468
507
|
try {
|
|
469
|
-
const client = getMCPClient();
|
|
470
508
|
if (!client.isConnectedToServer()) {
|
|
471
509
|
spinner.info('Not connected. Attempting auto-connect...');
|
|
472
510
|
const config = new CLIConfig();
|
|
473
511
|
const useRemote = !!config.get('token');
|
|
474
512
|
await client.connect({ useRemote });
|
|
475
513
|
}
|
|
476
|
-
const
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
514
|
+
const limit = parseInt(options.limit);
|
|
515
|
+
const threshold = parseFloat(options.threshold);
|
|
516
|
+
let results = [];
|
|
517
|
+
let usedLexicalFallback = false;
|
|
518
|
+
try {
|
|
519
|
+
const rawResult = await client.callTool('memory_search_memories', {
|
|
520
|
+
query,
|
|
521
|
+
limit,
|
|
522
|
+
threshold
|
|
523
|
+
});
|
|
524
|
+
results = Array.isArray(rawResult)
|
|
525
|
+
? rawResult
|
|
526
|
+
: Array.isArray(rawResult?.results)
|
|
527
|
+
? rawResult.results
|
|
528
|
+
: Array.isArray(rawResult?.result)
|
|
529
|
+
? rawResult.result
|
|
530
|
+
: [];
|
|
531
|
+
}
|
|
532
|
+
catch (error) {
|
|
533
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
534
|
+
if (/vector dimensions|hybrid search failed|memory search failed/i.test(message)) {
|
|
535
|
+
spinner.info('Semantic search unavailable in MCP path, using lexical fallback...');
|
|
536
|
+
results = await fallbackMemorySearch(query, limit);
|
|
537
|
+
usedLexicalFallback = true;
|
|
538
|
+
}
|
|
539
|
+
else {
|
|
540
|
+
throw error;
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
spinner.succeed(`Found ${results.length} memories${usedLexicalFallback ? ' (lexical fallback)' : ''}`);
|
|
482
544
|
if (results.length === 0) {
|
|
483
545
|
console.log(chalk.yellow('\nNo memories found matching your query'));
|
|
484
546
|
return;
|
|
@@ -488,7 +550,7 @@ export function mcpCommands(program) {
|
|
|
488
550
|
console.log(`\n${chalk.bold(`${index + 1}. ${memory.title}`)}`);
|
|
489
551
|
console.log(` ID: ${chalk.gray(memory.id)}`);
|
|
490
552
|
console.log(` Type: ${chalk.blue(memory.memory_type)}`);
|
|
491
|
-
console.log(` Score: ${chalk.green((memory.
|
|
553
|
+
console.log(` Score: ${chalk.green((memory.similarity_score * 100).toFixed(1) + '%')}`);
|
|
492
554
|
console.log(` Content: ${memory.content.substring(0, 100)}...`);
|
|
493
555
|
});
|
|
494
556
|
}
|
|
@@ -496,6 +558,11 @@ export function mcpCommands(program) {
|
|
|
496
558
|
spinner.fail(`Search failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
497
559
|
process.exit(1);
|
|
498
560
|
}
|
|
561
|
+
finally {
|
|
562
|
+
if (client.isConnectedToServer()) {
|
|
563
|
+
await client.disconnect().catch(() => { });
|
|
564
|
+
}
|
|
565
|
+
}
|
|
499
566
|
});
|
|
500
567
|
// Configure MCP preferences
|
|
501
568
|
mcp.command('config')
|