nlos 1.7.0 → 1.8.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/bin/nlos.js +132 -4
- package/package.json +1 -1
package/bin/nlos.js
CHANGED
|
@@ -319,14 +319,26 @@ function boot(options = {}) {
|
|
|
319
319
|
|
|
320
320
|
function chat(options = {}) {
|
|
321
321
|
const {
|
|
322
|
-
model =
|
|
322
|
+
model = null, // null means check config
|
|
323
323
|
full = false,
|
|
324
324
|
minimal = false,
|
|
325
325
|
profile = null,
|
|
326
326
|
} = options;
|
|
327
327
|
|
|
328
|
-
// Resolve model
|
|
329
|
-
let selectedModel =
|
|
328
|
+
// Resolve model: CLI flag > config file > profile > default
|
|
329
|
+
let selectedModel = 'qwen2.5:3b';
|
|
330
|
+
|
|
331
|
+
// Check .nlos.yaml for default
|
|
332
|
+
const configPath = path.join(process.cwd(), '.nlos.yaml');
|
|
333
|
+
if (fs.existsSync(configPath)) {
|
|
334
|
+
const config = fs.readFileSync(configPath, 'utf-8');
|
|
335
|
+
const match = config.match(/default_model:\s*(\S+)/);
|
|
336
|
+
if (match) {
|
|
337
|
+
selectedModel = match[1];
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Profile overrides config
|
|
330
342
|
if (profile) {
|
|
331
343
|
const profiles = {
|
|
332
344
|
speed: 'qwen2.5:3b',
|
|
@@ -334,7 +346,12 @@ function chat(options = {}) {
|
|
|
334
346
|
quality: 'llama3.1:8b',
|
|
335
347
|
memory_constrained: 'qwen2.5:3b',
|
|
336
348
|
};
|
|
337
|
-
selectedModel = profiles[profile] ||
|
|
349
|
+
selectedModel = profiles[profile] || selectedModel;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// CLI flag overrides everything
|
|
353
|
+
if (model) {
|
|
354
|
+
selectedModel = model;
|
|
338
355
|
}
|
|
339
356
|
|
|
340
357
|
log('blue', `Starting NL-OS chat session...`);
|
|
@@ -477,6 +494,112 @@ function payload(options = {}) {
|
|
|
477
494
|
}
|
|
478
495
|
}
|
|
479
496
|
|
|
497
|
+
function model(args = []) {
|
|
498
|
+
const subcommand = args[0];
|
|
499
|
+
const modelName = args[1];
|
|
500
|
+
|
|
501
|
+
const configPath = path.join(process.cwd(), '.nlos.yaml');
|
|
502
|
+
const hasLocalConfig = fs.existsSync(configPath);
|
|
503
|
+
|
|
504
|
+
// Recommended models by capability
|
|
505
|
+
const recommended = {
|
|
506
|
+
'qwen2.5:3b': { size: '1.9GB', context: '32K', note: 'Fast, minimal capability' },
|
|
507
|
+
'qwen2.5:7b': { size: '4.4GB', context: '32K', note: 'Good balance' },
|
|
508
|
+
'llama3.1:8b': { size: '4.7GB', context: '128K', note: 'Strong reasoning' },
|
|
509
|
+
'mistral:7b': { size: '4.1GB', context: '32K', note: 'Fast, good quality' },
|
|
510
|
+
'llama3.2:3b': { size: '2.0GB', context: '128K', note: 'Newest small model' },
|
|
511
|
+
'deepseek-r1:8b': { size: '4.9GB', context: '64K', note: 'Strong reasoning' },
|
|
512
|
+
};
|
|
513
|
+
|
|
514
|
+
if (!subcommand || subcommand === 'list') {
|
|
515
|
+
log('blue', 'Recommended models for NL-OS:\n');
|
|
516
|
+
console.log(`${'Model'.padEnd(20)} ${'Size'.padEnd(10)} ${'Context'.padEnd(10)} Note`);
|
|
517
|
+
console.log('─'.repeat(60));
|
|
518
|
+
for (const [name, info] of Object.entries(recommended)) {
|
|
519
|
+
console.log(`${name.padEnd(20)} ${info.size.padEnd(10)} ${info.context.padEnd(10)} ${info.note}`);
|
|
520
|
+
}
|
|
521
|
+
console.log();
|
|
522
|
+
log('yellow', 'Commands:');
|
|
523
|
+
console.log(' nlos model use <name> Set as default and pull if needed');
|
|
524
|
+
console.log(' nlos model pull <name> Just pull the model');
|
|
525
|
+
console.log(' nlos model current Show current default');
|
|
526
|
+
return;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
if (subcommand === 'current') {
|
|
530
|
+
if (hasLocalConfig) {
|
|
531
|
+
const config = fs.readFileSync(configPath, 'utf-8');
|
|
532
|
+
const match = config.match(/default_model:\s*(\S+)/);
|
|
533
|
+
if (match) {
|
|
534
|
+
log('green', `Current model: ${match[1]}`);
|
|
535
|
+
} else {
|
|
536
|
+
log('yellow', 'No default model set. Using: qwen2.5:3b');
|
|
537
|
+
}
|
|
538
|
+
} else {
|
|
539
|
+
log('yellow', 'No .nlos.yaml found. Run "nlos init" first, or using default: qwen2.5:3b');
|
|
540
|
+
}
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
if (subcommand === 'pull') {
|
|
545
|
+
if (!modelName) {
|
|
546
|
+
log('red', 'Usage: nlos model pull <name>');
|
|
547
|
+
return;
|
|
548
|
+
}
|
|
549
|
+
log('blue', `Pulling ${modelName}...`);
|
|
550
|
+
try {
|
|
551
|
+
execSync(`ollama pull ${modelName}`, { stdio: 'inherit' });
|
|
552
|
+
log('green', `\nModel ${modelName} ready!`);
|
|
553
|
+
} catch (error) {
|
|
554
|
+
log('red', `Failed to pull: ${error.message}`);
|
|
555
|
+
}
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
if (subcommand === 'use' || subcommand === 'set') {
|
|
560
|
+
if (!modelName) {
|
|
561
|
+
log('red', 'Usage: nlos model use <name>');
|
|
562
|
+
return;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
// Pull model if not present
|
|
566
|
+
log('blue', `Setting up ${modelName}...\n`);
|
|
567
|
+
try {
|
|
568
|
+
execSync(`ollama list | grep -q "^${modelName.split(':')[0]}"`, { stdio: 'pipe' });
|
|
569
|
+
log('cyan', `Model ${modelName} already pulled`);
|
|
570
|
+
} catch {
|
|
571
|
+
log('yellow', `Pulling ${modelName}...`);
|
|
572
|
+
try {
|
|
573
|
+
execSync(`ollama pull ${modelName}`, { stdio: 'inherit' });
|
|
574
|
+
} catch (error) {
|
|
575
|
+
log('red', `Failed to pull: ${error.message}`);
|
|
576
|
+
return;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
// Update .nlos.yaml if it exists
|
|
581
|
+
if (hasLocalConfig) {
|
|
582
|
+
let config = fs.readFileSync(configPath, 'utf-8');
|
|
583
|
+
if (config.includes('default_model:')) {
|
|
584
|
+
config = config.replace(/default_model:\s*\S+/, `default_model: ${modelName}`);
|
|
585
|
+
} else {
|
|
586
|
+
config += `\nkernel:\n default_model: ${modelName}\n`;
|
|
587
|
+
}
|
|
588
|
+
fs.writeFileSync(configPath, config);
|
|
589
|
+
log('green', `\nDefault model set to: ${modelName}`);
|
|
590
|
+
console.log(`\nRun ${colors.cyan}nlos chat --minimal${colors.reset} to start`);
|
|
591
|
+
} else {
|
|
592
|
+
log('green', `\nModel ${modelName} ready!`);
|
|
593
|
+
console.log(`\nRun ${colors.cyan}nlos chat --minimal --model ${modelName}${colors.reset} to start`);
|
|
594
|
+
console.log(`Or run ${colors.cyan}nlos init${colors.reset} first to save as default`);
|
|
595
|
+
}
|
|
596
|
+
return;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
log('red', `Unknown subcommand: ${subcommand}`);
|
|
600
|
+
console.log('Use: nlos model list|use|pull|current');
|
|
601
|
+
}
|
|
602
|
+
|
|
480
603
|
function clean(options = {}) {
|
|
481
604
|
const { local = false, all = false } = options;
|
|
482
605
|
|
|
@@ -667,6 +790,7 @@ ${colors.yellow}Usage:${colors.reset}
|
|
|
667
790
|
${colors.yellow}Commands:${colors.reset}
|
|
668
791
|
init Initialize NL-OS workspace in current directory
|
|
669
792
|
chat Interactive NL-OS chat session (recommended)
|
|
793
|
+
model Manage models (list, use, pull, current)
|
|
670
794
|
clean Remove Ollama model and optionally local files
|
|
671
795
|
boot Boot NL-OS and verify kernel loads
|
|
672
796
|
payload Generate portable kernel payloads
|
|
@@ -757,6 +881,10 @@ switch (command) {
|
|
|
757
881
|
clean(options);
|
|
758
882
|
break;
|
|
759
883
|
|
|
884
|
+
case 'model':
|
|
885
|
+
model(args.slice(1));
|
|
886
|
+
break;
|
|
887
|
+
|
|
760
888
|
case 'chat':
|
|
761
889
|
chat(options);
|
|
762
890
|
break;
|