nlos 1.4.0 → 1.6.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 +183 -8
- package/package.json +1 -1
package/bin/nlos.js
CHANGED
|
@@ -112,6 +112,40 @@ function showTokens() {
|
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
+
// Minimal kernel for small models (~500 tokens)
|
|
116
|
+
const MINIMAL_KERNEL = `# YOU ARE NL-OS
|
|
117
|
+
|
|
118
|
+
You are NL-OS, a Natural Language Operating System. You help users think and work.
|
|
119
|
+
|
|
120
|
+
## YOUR FIRST RESPONSE
|
|
121
|
+
|
|
122
|
+
Say exactly: "NL-OS ready."
|
|
123
|
+
|
|
124
|
+
## COMMANDS
|
|
125
|
+
|
|
126
|
+
When user message starts with ">", it is a command. Execute it:
|
|
127
|
+
|
|
128
|
+
>hype = Give 1-2 sentences of encouragement about their work
|
|
129
|
+
>note TEXT = Say "Noted." (do not do anything with TEXT)
|
|
130
|
+
>help = Say "Commands: >hype >note >help >deep >assume"
|
|
131
|
+
>deep = Say "Deep mode on." Then think step-by-step
|
|
132
|
+
>assume NAME = Say "Now acting as NAME." Then roleplay as NAME
|
|
133
|
+
|
|
134
|
+
## RULES
|
|
135
|
+
|
|
136
|
+
1. ">" means command - execute it immediately
|
|
137
|
+
2. Be helpful, concise, no emojis
|
|
138
|
+
3. If unsure, ask for clarification
|
|
139
|
+
|
|
140
|
+
## EXAMPLE
|
|
141
|
+
|
|
142
|
+
User: >hype
|
|
143
|
+
Assistant: You're making real progress. Keep that momentum going.
|
|
144
|
+
|
|
145
|
+
User: hello
|
|
146
|
+
Assistant: Hello! How can I help you today?
|
|
147
|
+
`;
|
|
148
|
+
|
|
115
149
|
// Command preamble - explicit rules that help ALL models parse commands correctly
|
|
116
150
|
const COMMAND_PREAMBLE = `# YOU ARE NL-OS (Natural Language Operating System)
|
|
117
151
|
|
|
@@ -287,6 +321,7 @@ function chat(options = {}) {
|
|
|
287
321
|
const {
|
|
288
322
|
model = 'qwen2.5:3b',
|
|
289
323
|
full = false,
|
|
324
|
+
minimal = false,
|
|
290
325
|
profile = null,
|
|
291
326
|
} = options;
|
|
292
327
|
|
|
@@ -304,18 +339,24 @@ function chat(options = {}) {
|
|
|
304
339
|
|
|
305
340
|
log('blue', `Starting NL-OS chat session...`);
|
|
306
341
|
log('cyan', `Model: ${selectedModel}`);
|
|
307
|
-
log('cyan', `Tier: ${full ? 'FULL' : 'MANDATORY'}`);
|
|
342
|
+
log('cyan', `Tier: ${minimal ? 'MINIMAL' : full ? 'FULL' : 'MANDATORY'}`);
|
|
308
343
|
console.log();
|
|
309
344
|
|
|
310
345
|
// Generate the kernel payload
|
|
311
346
|
log('yellow', 'Building kernel payload...');
|
|
312
|
-
const payload = generatePayload(full ? 'full' : 'mandatory', 'markdown');
|
|
313
347
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
348
|
+
let payload;
|
|
349
|
+
let tokenEstimate;
|
|
350
|
+
|
|
351
|
+
if (minimal) {
|
|
352
|
+
// Use minimal kernel for small models
|
|
353
|
+
payload = MINIMAL_KERNEL;
|
|
354
|
+
tokenEstimate = '~500';
|
|
355
|
+
} else {
|
|
356
|
+
payload = generatePayload(full ? 'full' : 'mandatory', 'markdown');
|
|
357
|
+
tokenEstimate = full ? '~15,500' : '~10,600';
|
|
358
|
+
}
|
|
317
359
|
|
|
318
|
-
const tokenEstimate = full ? '~15,500' : '~10,600';
|
|
319
360
|
log('green', `Kernel payload ready (${tokenEstimate} tokens)`);
|
|
320
361
|
console.log();
|
|
321
362
|
|
|
@@ -337,6 +378,14 @@ function chat(options = {}) {
|
|
|
337
378
|
const modelfilePath = path.join(PACKAGE_ROOT, 'portable', '.Modelfile.nlos');
|
|
338
379
|
const nlosModelName = 'nlos-kernel:latest';
|
|
339
380
|
|
|
381
|
+
// Delete old model to ensure fresh kernel
|
|
382
|
+
try {
|
|
383
|
+
execSync(`ollama rm ${nlosModelName}`, { stdio: 'pipe' });
|
|
384
|
+
log('cyan', 'Removed old kernel model');
|
|
385
|
+
} catch {
|
|
386
|
+
// Model didn't exist, that's fine
|
|
387
|
+
}
|
|
388
|
+
|
|
340
389
|
const modelfileContent = `FROM ${selectedModel}
|
|
341
390
|
SYSTEM """${payload}"""
|
|
342
391
|
`;
|
|
@@ -428,6 +477,123 @@ function payload(options = {}) {
|
|
|
428
477
|
}
|
|
429
478
|
}
|
|
430
479
|
|
|
480
|
+
function init(options = {}) {
|
|
481
|
+
const targetDir = process.cwd();
|
|
482
|
+
|
|
483
|
+
log('blue', `Initializing NL-OS workspace in ${targetDir}...\n`);
|
|
484
|
+
|
|
485
|
+
// Files to copy from package to local workspace
|
|
486
|
+
const filesToCopy = [
|
|
487
|
+
{ src: 'memory.md', dest: 'memory.md', desc: 'Directive stack (customize this!)' },
|
|
488
|
+
{ src: 'KERNEL.md', dest: 'KERNEL.md', desc: 'Kernel entry point' },
|
|
489
|
+
{ src: 'AGENTS.md', dest: 'AGENTS.md', desc: 'Agent rules and invariants' },
|
|
490
|
+
{ src: 'axioms.yaml', dest: 'axioms.yaml', desc: 'Canonical definitions' },
|
|
491
|
+
{ src: 'personalities.md', dest: 'personalities.md', desc: 'Voice presets' },
|
|
492
|
+
];
|
|
493
|
+
|
|
494
|
+
const commandsToCopy = [
|
|
495
|
+
'hype.md',
|
|
496
|
+
'note.md',
|
|
497
|
+
'assume.md',
|
|
498
|
+
];
|
|
499
|
+
|
|
500
|
+
// Create directories
|
|
501
|
+
const commandsDir = path.join(targetDir, 'commands');
|
|
502
|
+
if (!fs.existsSync(commandsDir)) {
|
|
503
|
+
fs.mkdirSync(commandsDir, { recursive: true });
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
// Copy kernel files
|
|
507
|
+
log('yellow', 'Copying kernel files:');
|
|
508
|
+
for (const { src, dest, desc } of filesToCopy) {
|
|
509
|
+
const srcPath = path.join(PACKAGE_ROOT, src);
|
|
510
|
+
const destPath = path.join(targetDir, dest);
|
|
511
|
+
|
|
512
|
+
if (fs.existsSync(destPath)) {
|
|
513
|
+
log('cyan', ` [skip] ${dest} (already exists)`);
|
|
514
|
+
} else if (fs.existsSync(srcPath)) {
|
|
515
|
+
fs.copyFileSync(srcPath, destPath);
|
|
516
|
+
log('green', ` [created] ${dest} - ${desc}`);
|
|
517
|
+
} else {
|
|
518
|
+
log('red', ` [missing] ${src} not found in package`);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
// Copy command files
|
|
523
|
+
console.log();
|
|
524
|
+
log('yellow', 'Copying command files:');
|
|
525
|
+
for (const cmd of commandsToCopy) {
|
|
526
|
+
const srcPath = path.join(PACKAGE_ROOT, '.cursor', 'commands', cmd);
|
|
527
|
+
const destPath = path.join(commandsDir, cmd);
|
|
528
|
+
|
|
529
|
+
if (fs.existsSync(destPath)) {
|
|
530
|
+
log('cyan', ` [skip] commands/${cmd} (already exists)`);
|
|
531
|
+
} else if (fs.existsSync(srcPath)) {
|
|
532
|
+
fs.copyFileSync(srcPath, destPath);
|
|
533
|
+
log('green', ` [created] commands/${cmd}`);
|
|
534
|
+
} else {
|
|
535
|
+
log('red', ` [missing] ${cmd} not found in package`);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
// Create .nlos config file
|
|
540
|
+
const configPath = path.join(targetDir, '.nlos.yaml');
|
|
541
|
+
if (!fs.existsSync(configPath)) {
|
|
542
|
+
const config = `# NL-OS Workspace Configuration
|
|
543
|
+
# Generated: ${new Date().toISOString().split('T')[0]}
|
|
544
|
+
|
|
545
|
+
workspace:
|
|
546
|
+
name: "${path.basename(targetDir)}"
|
|
547
|
+
initialized: true
|
|
548
|
+
|
|
549
|
+
kernel:
|
|
550
|
+
# Use local files (set to false to use global package)
|
|
551
|
+
use_local: true
|
|
552
|
+
|
|
553
|
+
# Default model for this workspace
|
|
554
|
+
default_model: qwen2.5:3b
|
|
555
|
+
|
|
556
|
+
# Tier: minimal, mandatory, full
|
|
557
|
+
default_tier: minimal
|
|
558
|
+
|
|
559
|
+
# Add workspace-specific settings below
|
|
560
|
+
`;
|
|
561
|
+
fs.writeFileSync(configPath, config);
|
|
562
|
+
log('green', ` [created] .nlos.yaml - workspace config`);
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
// Create .gitignore addition
|
|
566
|
+
const gitignorePath = path.join(targetDir, '.gitignore');
|
|
567
|
+
const gitignoreContent = `# NL-OS
|
|
568
|
+
.nlos-cache/
|
|
569
|
+
`;
|
|
570
|
+
if (!fs.existsSync(gitignorePath)) {
|
|
571
|
+
fs.writeFileSync(gitignorePath, gitignoreContent);
|
|
572
|
+
log('green', ` [created] .gitignore`);
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
console.log();
|
|
576
|
+
log('green', 'Workspace initialized!\n');
|
|
577
|
+
|
|
578
|
+
console.log(`${colors.yellow}Next steps:${colors.reset}`);
|
|
579
|
+
console.log(` 1. Edit ${colors.cyan}memory.md${colors.reset} to customize your directives`);
|
|
580
|
+
console.log(` 2. Add commands to ${colors.cyan}commands/${colors.reset}`);
|
|
581
|
+
console.log(` 3. Run ${colors.cyan}nlos chat --minimal${colors.reset} to start\n`);
|
|
582
|
+
|
|
583
|
+
console.log(`${colors.yellow}Files created:${colors.reset}`);
|
|
584
|
+
console.log(` ${targetDir}/`);
|
|
585
|
+
console.log(` ├── KERNEL.md # Entry point`);
|
|
586
|
+
console.log(` ├── memory.md # Your directives (edit this!)`);
|
|
587
|
+
console.log(` ├── AGENTS.md # Agent rules`);
|
|
588
|
+
console.log(` ├── axioms.yaml # Definitions`);
|
|
589
|
+
console.log(` ├── personalities.md # Voice presets`);
|
|
590
|
+
console.log(` ├── commands/ # Your commands`);
|
|
591
|
+
console.log(` │ ├── hype.md`);
|
|
592
|
+
console.log(` │ ├── note.md`);
|
|
593
|
+
console.log(` │ └── assume.md`);
|
|
594
|
+
console.log(` └── .nlos.yaml # Workspace config`);
|
|
595
|
+
}
|
|
596
|
+
|
|
431
597
|
function showHelp() {
|
|
432
598
|
console.log(`
|
|
433
599
|
${colors.cyan}NL-OS${colors.reset} - Natural Language Operating System
|
|
@@ -436,6 +602,7 @@ ${colors.yellow}Usage:${colors.reset}
|
|
|
436
602
|
nlos <command> [options]
|
|
437
603
|
|
|
438
604
|
${colors.yellow}Commands:${colors.reset}
|
|
605
|
+
init Initialize NL-OS workspace in current directory
|
|
439
606
|
chat Interactive NL-OS chat session (recommended)
|
|
440
607
|
boot Boot NL-OS and verify kernel loads
|
|
441
608
|
payload Generate portable kernel payloads
|
|
@@ -443,9 +610,10 @@ ${colors.yellow}Commands:${colors.reset}
|
|
|
443
610
|
tokens Show token estimates
|
|
444
611
|
help Show this help message
|
|
445
612
|
|
|
446
|
-
${colors.yellow}Boot Options:${colors.reset}
|
|
613
|
+
${colors.yellow}Chat/Boot Options:${colors.reset}
|
|
447
614
|
--model <name> Model to use (default: qwen2.5:3b)
|
|
448
615
|
--profile <name> Use profile: speed, balanced, quality, memory_constrained
|
|
616
|
+
--minimal Use minimal ~500 token kernel (best for small models)
|
|
449
617
|
--full Load full kernel (includes personalities)
|
|
450
618
|
--dry-run Preview system prompt without launching
|
|
451
619
|
--runtime <name> Runtime: ollama, llama-cpp, lm-studio (default: ollama)
|
|
@@ -457,7 +625,8 @@ ${colors.yellow}Payload Options:${colors.reset}
|
|
|
457
625
|
--all Generate all variants
|
|
458
626
|
|
|
459
627
|
${colors.yellow}Examples:${colors.reset}
|
|
460
|
-
nlos
|
|
628
|
+
nlos init # Initialize workspace with kernel files
|
|
629
|
+
nlos chat --minimal # Use minimal kernel for small models (3B)
|
|
461
630
|
nlos chat --model llama3.1:8b # Chat with specific model
|
|
462
631
|
nlos chat --profile quality --full # Quality mode with full kernel
|
|
463
632
|
nlos boot # Verify kernel loads (one-shot)
|
|
@@ -494,6 +663,8 @@ function parseArgs(args) {
|
|
|
494
663
|
options.runtime = args[++i];
|
|
495
664
|
} else if (arg === '--full') {
|
|
496
665
|
options.full = true;
|
|
666
|
+
} else if (arg === '--minimal') {
|
|
667
|
+
options.minimal = true;
|
|
497
668
|
} else if (arg === '--dry-run') {
|
|
498
669
|
options.dryRun = true;
|
|
499
670
|
} else if (arg === '--all') {
|
|
@@ -512,6 +683,10 @@ const command = args[0];
|
|
|
512
683
|
const options = parseArgs(args.slice(1));
|
|
513
684
|
|
|
514
685
|
switch (command) {
|
|
686
|
+
case 'init':
|
|
687
|
+
init(options);
|
|
688
|
+
break;
|
|
689
|
+
|
|
515
690
|
case 'chat':
|
|
516
691
|
chat(options);
|
|
517
692
|
break;
|