@mnemosyne_os/forge 1.2.3 → 1.2.4
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/dist/cli.js +137 -2
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -667,9 +667,144 @@ chronicle
|
|
|
667
667
|
}
|
|
668
668
|
});
|
|
669
669
|
console.log('\n' + SEP + '\n');
|
|
670
|
-
console.log(chalk_1.default.gray(' Tip: ') + chalk_1.default.white('mnemoforge chronicle list -n 20') + chalk_1.default.gray(' to
|
|
670
|
+
console.log(chalk_1.default.gray(' Tip: ') + chalk_1.default.white('mnemoforge chronicle list -n 20') + chalk_1.default.gray(' · ') + chalk_1.default.white('mnemoforge chronicle open') + chalk_1.default.gray(' to browse interactively\n'));
|
|
671
|
+
});
|
|
672
|
+
// ── chronicle open — interactive picker + inline reader ───────────────────
|
|
673
|
+
chronicle
|
|
674
|
+
.command('open')
|
|
675
|
+
.description('Browse and read chronicles interactively (arrow keys + Enter)')
|
|
676
|
+
.option('-n, --count <n>', 'Max chronicles to show in picker', '20')
|
|
677
|
+
.action(async (opts) => {
|
|
678
|
+
const config = (0, vault_js_1.loadVaultConfig)();
|
|
679
|
+
if (!config) {
|
|
680
|
+
console.log(chalk_1.default.red('\n ✖ Not initialized. Run: mnemoforge chronicle init\n'));
|
|
681
|
+
process.exit(1);
|
|
682
|
+
}
|
|
683
|
+
const { resolveChronicleDir } = require('./lib/vault.js');
|
|
684
|
+
const dir = resolveChronicleDir(config);
|
|
685
|
+
const all = (0, vault_js_1.listChronicles)(config);
|
|
686
|
+
if (all.length === 0) {
|
|
687
|
+
console.log(chalk_1.default.yellow('\n No chronicles in vault yet.\n'));
|
|
688
|
+
return;
|
|
689
|
+
}
|
|
690
|
+
// ── Build picker choices ──────────────────────────────
|
|
691
|
+
const TYPE_ICONS = {
|
|
692
|
+
session: '◈', decision: '◆', reflection: '◇', sweep: '↻', narcissus: '✦',
|
|
693
|
+
};
|
|
694
|
+
const getType = (filename) => {
|
|
695
|
+
try {
|
|
696
|
+
const raw = fs_1.default.readFileSync(path_1.default.join(dir, filename), 'utf8').slice(0, 800);
|
|
697
|
+
const m = raw.match(/\*\*Type\*\*:\s*(\w+)/i) || raw.match(/^type:\s*(\w+)/im);
|
|
698
|
+
return m ? m[1].toLowerCase() : 'session';
|
|
699
|
+
}
|
|
700
|
+
catch {
|
|
701
|
+
return 'session';
|
|
702
|
+
}
|
|
703
|
+
};
|
|
704
|
+
const picks = all.slice(0, parseInt(opts.count || '20'));
|
|
705
|
+
const choices = picks.map((filename) => {
|
|
706
|
+
const dateMatch = filename.match(/CHRONICLE-(\d{4}-\d{2}-\d{2})/);
|
|
707
|
+
const date = dateMatch ? dateMatch[1] : '';
|
|
708
|
+
const slug = filename.replace(/^CHRONICLE-\d{4}-\d{2}-\d{2}-/, '').replace(/\.md$/, '').replace(/-/g, ' ');
|
|
709
|
+
const type = getType(filename);
|
|
710
|
+
const icon = TYPE_ICONS[type] ?? '○';
|
|
711
|
+
return {
|
|
712
|
+
name: ` ${icon} ${chalk_1.default.hex('#CBD5E1')(date)} ${chalk_1.default.white(slug)}`,
|
|
713
|
+
value: filename,
|
|
714
|
+
short: slug,
|
|
715
|
+
};
|
|
716
|
+
});
|
|
717
|
+
choices.push({ name: chalk_1.default.gray('\n ✖ Cancel'), value: '__cancel__', short: 'cancel' });
|
|
718
|
+
console.log(chalk_1.default.hex('#8B5CF6').bold('\n ⬡ MnemoChronicle — Open\n'));
|
|
719
|
+
const { selected } = await inquirer_1.default.prompt([{
|
|
720
|
+
type: 'list',
|
|
721
|
+
name: 'selected',
|
|
722
|
+
message: chalk_1.default.hex('#A78BFA')('Select a chronicle to read:'),
|
|
723
|
+
choices,
|
|
724
|
+
pageSize: 15,
|
|
725
|
+
}]);
|
|
726
|
+
if (selected === '__cancel__')
|
|
727
|
+
return;
|
|
728
|
+
// ── Render chronicle ─────────────────────────────────
|
|
729
|
+
const filePath = path_1.default.join(dir, selected);
|
|
730
|
+
const raw = fs_1.default.readFileSync(filePath, 'utf8');
|
|
731
|
+
const resonanceIdx = raw.indexOf('<!--resonance');
|
|
732
|
+
const content = resonanceIdx !== -1 ? raw.slice(0, resonanceIdx) : raw;
|
|
733
|
+
const lines = content.split('\n');
|
|
734
|
+
console.log('\n' + chalk_1.default.hex('#312E81')(' ' + '─'.repeat(72)));
|
|
735
|
+
console.log(chalk_1.default.gray(` ${filePath}`));
|
|
736
|
+
console.log(chalk_1.default.hex('#312E81')(' ' + '─'.repeat(72)) + '\n');
|
|
737
|
+
let inMeta = false;
|
|
738
|
+
let metaDone = false;
|
|
739
|
+
let dividerCount = 0;
|
|
740
|
+
for (const line of lines) {
|
|
741
|
+
const l = line.trim();
|
|
742
|
+
// Title
|
|
743
|
+
if (l.startsWith('# ')) {
|
|
744
|
+
console.log('\n ' + chalk_1.default.hex('#8B5CF6').bold(l.slice(2)));
|
|
745
|
+
continue;
|
|
746
|
+
}
|
|
747
|
+
// Section headers
|
|
748
|
+
if (l.startsWith('## ')) {
|
|
749
|
+
console.log('\n ' + chalk_1.default.hex('#A78BFA').bold(' ' + l.slice(3)));
|
|
750
|
+
continue;
|
|
751
|
+
}
|
|
752
|
+
if (l.startsWith('### ')) {
|
|
753
|
+
console.log(' ' + chalk_1.default.hex('#C084FC')(' ' + l.slice(4)));
|
|
754
|
+
continue;
|
|
755
|
+
}
|
|
756
|
+
// Dividers — dim, show once as meta separator
|
|
757
|
+
if (l === '---') {
|
|
758
|
+
dividerCount++;
|
|
759
|
+
if (dividerCount <= 2)
|
|
760
|
+
console.log(chalk_1.default.hex('#312E81')(' ' + '─'.repeat(60)));
|
|
761
|
+
continue;
|
|
762
|
+
}
|
|
763
|
+
// Bold metadata fields **Key**: value
|
|
764
|
+
if (l.match(/^\*\*[\w\s]+\*\*:/)) {
|
|
765
|
+
const parts = l.match(/^\*\*([\w\s]+)\*\*:\s*(.*)/) ?? [];
|
|
766
|
+
if (parts.length >= 3) {
|
|
767
|
+
console.log(' ' + chalk_1.default.hex('#64748B')(` ${parts[1].padEnd(14)} `) + chalk_1.default.hex('#94A3B8')(parts[2]));
|
|
768
|
+
}
|
|
769
|
+
continue;
|
|
770
|
+
}
|
|
771
|
+
// Blockquotes
|
|
772
|
+
if (l.startsWith('> ')) {
|
|
773
|
+
console.log(' ' + chalk_1.default.hex('#7C3AED')(' │ ') + chalk_1.default.hex('#DDD6FE').italic(l.slice(2)));
|
|
774
|
+
continue;
|
|
775
|
+
}
|
|
776
|
+
// List items
|
|
777
|
+
if (l.startsWith('- ') || l.startsWith('* ')) {
|
|
778
|
+
console.log(' ' + chalk_1.default.hex('#6B7280')(' • ') + chalk_1.default.white(l.slice(2)));
|
|
779
|
+
continue;
|
|
780
|
+
}
|
|
781
|
+
// Numbered list
|
|
782
|
+
if (l.match(/^\d+\. /)) {
|
|
783
|
+
console.log(' ' + chalk_1.default.hex('#6B7280')(' ') + chalk_1.default.white(l));
|
|
784
|
+
continue;
|
|
785
|
+
}
|
|
786
|
+
// Code blocks (single line inline or fence)
|
|
787
|
+
if (l.startsWith('```')) {
|
|
788
|
+
console.log(' ' + chalk_1.default.hex('#312E81')(' ' + '·'.repeat(50)));
|
|
789
|
+
continue;
|
|
790
|
+
}
|
|
791
|
+
// Tags line
|
|
792
|
+
if (l.match(/^#\w/) && !l.startsWith('# ')) {
|
|
793
|
+
const tags = l.match(/#\w+/g) ?? [];
|
|
794
|
+
console.log('\n ' + tags.map(t => chalk_1.default.hex('#7C3AED')(t)).join(' '));
|
|
795
|
+
continue;
|
|
796
|
+
}
|
|
797
|
+
// Regular text
|
|
798
|
+
if (l.length > 0) {
|
|
799
|
+
console.log(' ' + chalk_1.default.hex('#E2E8F0')(' ' + l));
|
|
800
|
+
}
|
|
801
|
+
else {
|
|
802
|
+
console.log();
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
console.log('\n' + chalk_1.default.hex('#312E81')(' ' + '─'.repeat(72)));
|
|
806
|
+
console.log(chalk_1.default.gray(`\n Tip: open in editor → `) + chalk_1.default.white(`code "${filePath}"`) + '\n');
|
|
671
807
|
});
|
|
672
|
-
// ── chronicle switch ───────────────────────────────────────────
|
|
673
808
|
chronicle
|
|
674
809
|
.command('switch')
|
|
675
810
|
.description('Switch the active profile to another registered one')
|
package/package.json
CHANGED