@mnemosyne_os/forge 1.2.4 → 1.2.6
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/__tests__/chronicle-parser.test.js +91 -0
- package/dist/__tests__/renderer.test.js +79 -0
- package/dist/cli.js +32 -890
- package/dist/commands/canvas.js +160 -0
- package/dist/commands/chronicle/index.js +17 -0
- package/dist/commands/chronicle/reader.js +99 -0
- package/dist/commands/chronicle/vault.js +120 -0
- package/dist/commands/chronicle/writer.js +147 -0
- package/dist/commands/chronicle.js +514 -0
- package/dist/commands/workspace.js +129 -0
- package/dist/lib/canvas/canvas.js +100 -0
- package/dist/lib/canvas/renderer.js +41 -0
- package/dist/lib/canvas/templates/cli/files.js +288 -0
- package/dist/lib/chronicle-parser.js +90 -0
- package/dist/lib/chronicle-render.js +76 -0
- package/dist/lib/ui.js +67 -0
- package/package.json +6 -2
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.canvasCommand = void 0;
|
|
40
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
41
|
+
// MnemoForge — canvas commands
|
|
42
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
43
|
+
const commander_1 = require("commander");
|
|
44
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
45
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
46
|
+
const vault_js_1 = require("../lib/vault.js");
|
|
47
|
+
const canvas_js_1 = require("../lib/canvas/canvas.js");
|
|
48
|
+
const renderer_js_1 = require("../lib/canvas/renderer.js");
|
|
49
|
+
exports.canvasCommand = new commander_1.Command('canvas')
|
|
50
|
+
.description('Scaffold a full Mnemosyne-grade project from a template');
|
|
51
|
+
// ── canvas (interactive picker) ───────────────────────────────────────────
|
|
52
|
+
exports.canvasCommand
|
|
53
|
+
.action(async () => {
|
|
54
|
+
const config = (0, vault_js_1.loadVaultConfig)();
|
|
55
|
+
const defaultWorkspace = config?.workspace ?? 'Mnemosyne-OS';
|
|
56
|
+
console.log(chalk_1.default.hex('#8B5CF6').bold('\n ⬡ MnemoCanvas — Project Inception\n'));
|
|
57
|
+
const available = canvas_js_1.CANVAS_TEMPLATES.filter(t => t.files.length > 0);
|
|
58
|
+
const comingSoon = canvas_js_1.CANVAS_TEMPLATES.filter(t => t.files.length === 0);
|
|
59
|
+
const templateChoices = [
|
|
60
|
+
...available.map(t => ({
|
|
61
|
+
name: ` ${t.icon} ${chalk_1.default.white(t.name.padEnd(18))} ${chalk_1.default.gray(t.stack)}`,
|
|
62
|
+
value: t.id, short: t.name,
|
|
63
|
+
})),
|
|
64
|
+
new inquirer_1.default.Separator(chalk_1.default.hex('#312E81')(' ── Coming soon ──')),
|
|
65
|
+
...comingSoon.map(t => ({
|
|
66
|
+
name: ` ${t.icon} ${chalk_1.default.hex('#475569')(t.name.padEnd(18))} ${chalk_1.default.hex('#334155')(t.stack)}`,
|
|
67
|
+
value: `__soon__${t.id}`, short: t.name,
|
|
68
|
+
})),
|
|
69
|
+
new inquirer_1.default.Separator(),
|
|
70
|
+
{ name: chalk_1.default.hex('#475569')(' ✖ Cancel'), value: '__cancel__', short: 'cancel' },
|
|
71
|
+
];
|
|
72
|
+
const { templateId } = await inquirer_1.default.prompt([{
|
|
73
|
+
type: 'list', name: 'templateId',
|
|
74
|
+
message: chalk_1.default.hex('#A78BFA')('Select a template:'),
|
|
75
|
+
choices: templateChoices, pageSize: 12,
|
|
76
|
+
}]);
|
|
77
|
+
if (templateId === '__cancel__')
|
|
78
|
+
return;
|
|
79
|
+
if (String(templateId).startsWith('__soon__')) {
|
|
80
|
+
console.log(chalk_1.default.yellow(`\n ⏳ This template is not yet available. Coming soon!\n`));
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const { projectName, workspace, ecosystem, runInstall } = await inquirer_1.default.prompt([
|
|
84
|
+
{ type: 'input', name: 'projectName', message: chalk_1.default.hex('#A78BFA')('Project name:'), validate: (v) => v.trim().length > 0 || 'Required' },
|
|
85
|
+
{ type: 'input', name: 'workspace', message: chalk_1.default.hex('#A78BFA')('Workspace (Resonance):'), default: defaultWorkspace },
|
|
86
|
+
{ type: 'input', name: 'ecosystem', message: chalk_1.default.hex('#A78BFA')('Ecosystem name (white-label):'), default: 'Mnemosyne Neural OS' },
|
|
87
|
+
{ type: 'confirm', name: 'runInstall', message: chalk_1.default.hex('#A78BFA')('Run npm install?'), default: false },
|
|
88
|
+
]);
|
|
89
|
+
const slug = (0, renderer_js_1.toSlug)(projectName);
|
|
90
|
+
console.log(chalk_1.default.gray(`\n ⟳ Scaffolding ${chalk_1.default.white(projectName)} into ./${slug}...\n`));
|
|
91
|
+
try {
|
|
92
|
+
const result = (0, canvas_js_1.scaffold)({ projectName, workspace, ecosystem, template: templateId }, (file) => {
|
|
93
|
+
console.log(chalk_1.default.hex('#4ADE80')(' ✔ ') + chalk_1.default.hex('#6B7280')(file));
|
|
94
|
+
});
|
|
95
|
+
console.log(chalk_1.default.hex('#4ADE80').bold(`\n ✔ ${result.filesCreated.length} files created`));
|
|
96
|
+
if (runInstall) {
|
|
97
|
+
console.log(chalk_1.default.gray('\n ⟳ npm install...'));
|
|
98
|
+
const { execSync } = await Promise.resolve().then(() => __importStar(require('child_process')));
|
|
99
|
+
try {
|
|
100
|
+
execSync('npm install', { cwd: result.rootDir, stdio: 'inherit' });
|
|
101
|
+
console.log(chalk_1.default.hex('#4ADE80').bold(' ✔ Dependencies installed'));
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
console.log(chalk_1.default.yellow(' ⚠ npm install failed — run manually in the project folder'));
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (result.errors.length > 0) {
|
|
108
|
+
result.errors.forEach(e => console.log(chalk_1.default.red(` ${e}`)));
|
|
109
|
+
}
|
|
110
|
+
console.log(chalk_1.default.hex('#8B5CF6').bold(`\n ⬡ ${projectName} is ready.\n`));
|
|
111
|
+
console.log(chalk_1.default.gray(' Next steps:'));
|
|
112
|
+
console.log(' ' + chalk_1.default.white(`cd ${slug}`));
|
|
113
|
+
console.log(' ' + chalk_1.default.white('mnemoforge chronicle init') + chalk_1.default.gray(' ← link your vault'));
|
|
114
|
+
console.log(' ' + chalk_1.default.white('mnemoforge workspace show') + chalk_1.default.gray(' ← brief your agent'));
|
|
115
|
+
console.log(' ' + chalk_1.default.white('npm run dev') + '\n');
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
console.log(chalk_1.default.red(`\n ✖ ${err.message}\n`));
|
|
119
|
+
process.exit(1);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
// ── canvas list ───────────────────────────────────────────────────────────
|
|
123
|
+
exports.canvasCommand
|
|
124
|
+
.command('list')
|
|
125
|
+
.description('List all available canvas templates')
|
|
126
|
+
.action(() => {
|
|
127
|
+
console.log(chalk_1.default.hex('#8B5CF6').bold('\n ⬡ MnemoCanvas — Templates\n'));
|
|
128
|
+
for (const t of canvas_js_1.CANVAS_TEMPLATES) {
|
|
129
|
+
const a = t.files.length > 0;
|
|
130
|
+
const status = a ? chalk_1.default.hex('#4ADE80')('✔ available') : chalk_1.default.hex('#475569')('⏳ coming soon');
|
|
131
|
+
console.log(` ${t.icon} ${chalk_1.default.white(t.name.padEnd(20))} ${status}`);
|
|
132
|
+
console.log(chalk_1.default.gray(` ${t.description}`));
|
|
133
|
+
console.log(chalk_1.default.hex('#334155')(` ${t.stack}\n`));
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
// ── canvas deploy <template> ──────────────────────────────────────────────
|
|
137
|
+
exports.canvasCommand
|
|
138
|
+
.command('deploy <template>')
|
|
139
|
+
.description('Deploy a template directly (non-interactive)')
|
|
140
|
+
.option('--name <name>', 'Project name')
|
|
141
|
+
.option('--workspace <ws>', 'Workspace name', 'Mnemosyne-OS')
|
|
142
|
+
.option('--ecosystem <eco>', 'Ecosystem name (white-label)', 'Mnemosyne Neural OS')
|
|
143
|
+
.option('--dir <dir>', 'Target directory')
|
|
144
|
+
.option('--dry-run', 'Preview files without writing to disk')
|
|
145
|
+
.action(async (templateId, opts) => {
|
|
146
|
+
const projectName = opts.name ?? templateId;
|
|
147
|
+
const dryRun = opts.dryRun ?? false;
|
|
148
|
+
console.log(chalk_1.default.hex('#8B5CF6').bold('\n ⬡ MnemoCanvas — Deploy\n'));
|
|
149
|
+
if (dryRun)
|
|
150
|
+
console.log(chalk_1.default.yellow(' [dry-run] No files will be written.\n'));
|
|
151
|
+
try {
|
|
152
|
+
const result = (0, canvas_js_1.scaffold)({ projectName, workspace: opts.workspace, ecosystem: opts.ecosystem, targetDir: opts.dir, template: templateId, dryRun }, (file) => console.log(chalk_1.default.hex('#4ADE80')(' ✔ ') + chalk_1.default.hex('#6B7280')(file)));
|
|
153
|
+
const label = dryRun ? 'files would be created' : 'files created';
|
|
154
|
+
console.log(chalk_1.default.hex('#4ADE80').bold(`\n ✔ ${result.filesCreated.length} ${label} · ${result.rootDir}\n`));
|
|
155
|
+
}
|
|
156
|
+
catch (err) {
|
|
157
|
+
console.log(chalk_1.default.red(`\n ✖ ${err.message}\n`));
|
|
158
|
+
process.exit(1);
|
|
159
|
+
}
|
|
160
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.chronicleCommand = void 0;
|
|
4
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
5
|
+
// MnemoChronicle — Command assembler
|
|
6
|
+
// Registers all sub-commands onto the `chronicle` parent command
|
|
7
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
8
|
+
const commander_1 = require("commander");
|
|
9
|
+
const vault_js_1 = require("./vault.js");
|
|
10
|
+
const writer_js_1 = require("./writer.js");
|
|
11
|
+
const reader_js_1 = require("./reader.js");
|
|
12
|
+
exports.chronicleCommand = new commander_1.Command('chronicle')
|
|
13
|
+
.description('MnemoChronicle — multi-agent memory archiving system');
|
|
14
|
+
// Mount all sub-commands
|
|
15
|
+
for (const cmd of [...vault_js_1.vaultCmd.commands, ...writer_js_1.writerCmd.commands, ...reader_js_1.readerCmd.commands]) {
|
|
16
|
+
exports.chronicleCommand.addCommand(cmd);
|
|
17
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.readerCmd = void 0;
|
|
7
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
8
|
+
// MnemoChronicle — Reader commands: list · open
|
|
9
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
10
|
+
const commander_1 = require("commander");
|
|
11
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
12
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
13
|
+
const path_1 = __importDefault(require("path"));
|
|
14
|
+
const vault_js_1 = require("../../lib/vault.js");
|
|
15
|
+
const chronicle_parser_js_1 = require("../../lib/chronicle-parser.js");
|
|
16
|
+
const chronicle_render_js_1 = require("../../lib/chronicle-render.js");
|
|
17
|
+
const TYPE_COLORS = {
|
|
18
|
+
session: chalk_1.default.hex('#60A5FA'), decision: chalk_1.default.hex('#FB923C'),
|
|
19
|
+
reflection: chalk_1.default.hex('#C084FC'), sweep: chalk_1.default.hex('#94A3B8'), narcissus: chalk_1.default.hex('#FBBF24'),
|
|
20
|
+
};
|
|
21
|
+
const TYPE_ICONS = {
|
|
22
|
+
session: '◈', decision: '◆', reflection: '◇', sweep: '↻', narcissus: '✦',
|
|
23
|
+
};
|
|
24
|
+
exports.readerCmd = new commander_1.Command();
|
|
25
|
+
exports.readerCmd
|
|
26
|
+
.command('list')
|
|
27
|
+
.description('List recent Chronicles in the vault')
|
|
28
|
+
.option('-n, --count <n>', 'Number of chronicles to show', '10')
|
|
29
|
+
.action((opts) => {
|
|
30
|
+
const config = (0, vault_js_1.loadVaultConfig)();
|
|
31
|
+
if (!config) {
|
|
32
|
+
console.log(chalk_1.default.red('\n ✖ Not initialized.\n'));
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
const dir = (0, vault_js_1.resolveChronicleDir)(config);
|
|
36
|
+
const all = (0, vault_js_1.listChronicles)(config);
|
|
37
|
+
const items = all.slice(0, parseInt(opts.count || '10'));
|
|
38
|
+
const SEP = chalk_1.default.hex('#312E81')(' ' + '─'.repeat(72));
|
|
39
|
+
console.log(chalk_1.default.hex('#8B5CF6').bold(`\n ⬡ MnemoChronicle — Vault\n`));
|
|
40
|
+
if (config.workspace)
|
|
41
|
+
console.log(chalk_1.default.gray(' Workspace : ') + chalk_1.default.hex('#A78BFA')(config.workspace) + (config.resonanceProject ? chalk_1.default.gray(' · Project : ') + chalk_1.default.hex('#A78BFA')(config.resonanceProject) : ''));
|
|
42
|
+
console.log(chalk_1.default.gray(' Agent : ') + chalk_1.default.white(config.ide) + chalk_1.default.gray(' / ') + chalk_1.default.white(config.provider));
|
|
43
|
+
console.log(chalk_1.default.gray(` Vault : `) + chalk_1.default.hex('#64748B')(dir));
|
|
44
|
+
console.log(chalk_1.default.gray(` Total : `) + chalk_1.default.white(String(all.length)) + chalk_1.default.gray(` chronicles · showing ${items.length}\n`) + SEP);
|
|
45
|
+
items.forEach((filename, i) => {
|
|
46
|
+
const { title, type, tags, excerpt, date } = (0, chronicle_parser_js_1.parseChronicle)(filename, dir);
|
|
47
|
+
const color = TYPE_COLORS[type] ?? chalk_1.default.white;
|
|
48
|
+
const icon = TYPE_ICONS[type] ?? '○';
|
|
49
|
+
console.log(`\n ${chalk_1.default.hex('#6B7280')(String(i + 1).padStart(2, ' '))} ${color(`[${type}]`)} ` + chalk_1.default.hex('#CBD5E1')(date) + ' ' + color(icon));
|
|
50
|
+
console.log(chalk_1.default.white(` ${title}`));
|
|
51
|
+
if (excerpt)
|
|
52
|
+
console.log(chalk_1.default.hex('#64748B')(` "${excerpt}"`));
|
|
53
|
+
if (tags.length > 0)
|
|
54
|
+
console.log(' ' + tags.map(t => chalk_1.default.hex('#7C3AED')(t)).join(' '));
|
|
55
|
+
});
|
|
56
|
+
console.log('\n' + SEP + '\n');
|
|
57
|
+
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'));
|
|
58
|
+
});
|
|
59
|
+
exports.readerCmd
|
|
60
|
+
.command('open')
|
|
61
|
+
.description('Browse and read chronicles interactively (arrow keys + Enter)')
|
|
62
|
+
.option('-n, --count <n>', 'Max chronicles to show in picker', '20')
|
|
63
|
+
.action(async (opts) => {
|
|
64
|
+
const config = (0, vault_js_1.loadVaultConfig)();
|
|
65
|
+
if (!config) {
|
|
66
|
+
console.log(chalk_1.default.red('\n ✖ Not initialized.\n'));
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
const dir = (0, vault_js_1.resolveChronicleDir)(config);
|
|
70
|
+
const all = (0, vault_js_1.listChronicles)(config);
|
|
71
|
+
if (all.length === 0) {
|
|
72
|
+
console.log(chalk_1.default.yellow('\n No chronicles in vault yet.\n'));
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const picks = all.slice(0, parseInt(opts.count || '20'));
|
|
76
|
+
while (true) {
|
|
77
|
+
const choices = picks.map((filename) => {
|
|
78
|
+
const dateMatch = filename.match(/CHRONICLE-(\d{4}-\d{2}-\d{2})/);
|
|
79
|
+
const slug = filename.replace(/^CHRONICLE-\d{4}-\d{2}-\d{2}-/, '').replace(/\.md$/, '').replace(/-/g, ' ');
|
|
80
|
+
const type = (0, chronicle_parser_js_1.getChronicleType)(filename, dir);
|
|
81
|
+
return {
|
|
82
|
+
name: ` ${TYPE_ICONS[type] ?? '○'} ${chalk_1.default.hex('#CBD5E1')(dateMatch?.[1] ?? '')} ${chalk_1.default.white(slug)}`,
|
|
83
|
+
value: filename, short: slug,
|
|
84
|
+
};
|
|
85
|
+
});
|
|
86
|
+
choices.push({ name: chalk_1.default.hex('#475569')('\n ✖ Quitter'), value: '__exit__', short: 'exit' });
|
|
87
|
+
console.log(chalk_1.default.hex('#8B5CF6').bold('\n ⬡ MnemoChronicle — Vault\n'));
|
|
88
|
+
const { selected } = await inquirer_1.default.prompt([{
|
|
89
|
+
type: 'list', name: 'selected',
|
|
90
|
+
message: chalk_1.default.hex('#A78BFA')('Sélectionner une chronicle ') + chalk_1.default.gray('(↑↓ + Enter)'),
|
|
91
|
+
choices, pageSize: 15,
|
|
92
|
+
}]);
|
|
93
|
+
if (selected === '__exit__') {
|
|
94
|
+
console.log(chalk_1.default.gray('\n Vault fermé.\n'));
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
(0, chronicle_render_js_1.renderChronicle)(path_1.default.join(dir, selected));
|
|
98
|
+
}
|
|
99
|
+
});
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.vaultCmd = void 0;
|
|
7
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
8
|
+
// MnemoChronicle — Profile commands: init · switch · config
|
|
9
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
10
|
+
const commander_1 = require("commander");
|
|
11
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
12
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
13
|
+
const vault_js_1 = require("../../lib/vault.js");
|
|
14
|
+
const init_flow_js_1 = require("../../lib/init-flow.js");
|
|
15
|
+
const ui_js_1 = require("../../lib/ui.js");
|
|
16
|
+
exports.vaultCmd = new commander_1.Command();
|
|
17
|
+
exports.vaultCmd
|
|
18
|
+
.command('init')
|
|
19
|
+
.description('Initialize .cli_resonance vault — choose IDE / Provider / Model')
|
|
20
|
+
.action(async () => {
|
|
21
|
+
const existing = (0, vault_js_1.loadVaultConfig)();
|
|
22
|
+
console.log(chalk_1.default.hex('#8B5CF6').bold('\n⬡ MnemoChronicle — Vault Init\n'));
|
|
23
|
+
if (existing) {
|
|
24
|
+
console.log(chalk_1.default.yellow(' ⚠ Re-configuring vault:'));
|
|
25
|
+
console.log(chalk_1.default.gray(' IDE: ' + existing.ide + '\n Provider: ' + existing.provider + '\n'));
|
|
26
|
+
}
|
|
27
|
+
const profile = await (0, init_flow_js_1.askPrimaryProfile)(existing);
|
|
28
|
+
const reg = existing?.registeredModels ?? [];
|
|
29
|
+
if (existing && (existing.ide !== profile.ide || existing.provider !== profile.provider)) {
|
|
30
|
+
const old = { ide: existing.ide, provider: existing.provider, defaultChronicleStyle: existing.defaultChronicleStyle };
|
|
31
|
+
if (!reg.some(m => m.ide === old.ide && m.provider === old.provider))
|
|
32
|
+
reg.unshift(old);
|
|
33
|
+
}
|
|
34
|
+
let extra = await (0, init_flow_js_1.askExtraProfile)(reg.length);
|
|
35
|
+
while (extra) {
|
|
36
|
+
console.log(chalk_1.default.green(' ✔ Added: ' + extra.ide + ' / ' + extra.provider));
|
|
37
|
+
reg.push(extra);
|
|
38
|
+
extra = await (0, init_flow_js_1.askExtraProfile)(reg.length);
|
|
39
|
+
}
|
|
40
|
+
const config = { ...profile, registeredModels: reg };
|
|
41
|
+
(0, vault_js_1.saveVaultConfig)(config);
|
|
42
|
+
const dir = `${config.vaultPath}/.cli_resonance/${config.ide}/${config.provider}/`;
|
|
43
|
+
console.log(chalk_1.default.green('\n ✔ Vault configured!'));
|
|
44
|
+
console.log(chalk_1.default.gray(` IDE: ${config.ide} · Provider: ${config.provider} · Style: `) + chalk_1.default.hex('#A78BFA')(config.defaultChronicleStyle ?? 'session'));
|
|
45
|
+
if (reg.length > 0)
|
|
46
|
+
console.log(chalk_1.default.gray(' + ' + reg.length + ' extra profile(s)'));
|
|
47
|
+
console.log(chalk_1.default.gray('\n Chronicles → ') + chalk_1.default.hex('#A78BFA')(dir) + '\n');
|
|
48
|
+
});
|
|
49
|
+
exports.vaultCmd
|
|
50
|
+
.command('switch')
|
|
51
|
+
.description('Switch the active profile to another registered one')
|
|
52
|
+
.action(async () => {
|
|
53
|
+
const config = (0, vault_js_1.loadVaultConfig)();
|
|
54
|
+
if (!config) {
|
|
55
|
+
console.log(chalk_1.default.red('\n ✖ Not initialized.\n'));
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
const profiles = config.registeredModels ?? [];
|
|
59
|
+
if (profiles.length === 0) {
|
|
60
|
+
console.log(chalk_1.default.yellow('\n ⚠ No other profiles registered.\n'));
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const { idx } = await inquirer_1.default.prompt([{
|
|
64
|
+
type: 'list', name: 'idx', message: chalk_1.default.cyan('Which profile to make active?'),
|
|
65
|
+
choices: profiles.map((p, i) => ({ name: `${p.ide} / ${p.provider} · ${p.displayName}`, value: i })),
|
|
66
|
+
}]);
|
|
67
|
+
const sel = profiles[idx];
|
|
68
|
+
const displaced = { ide: config.ide, provider: config.provider, modelId: config.modelId, displayName: config.displayName, defaultChronicleStyle: config.defaultChronicleStyle };
|
|
69
|
+
const newReg = profiles.filter((_, i) => i !== idx);
|
|
70
|
+
newReg.push(displaced);
|
|
71
|
+
(0, vault_js_1.saveVaultConfig)({ ...config, ide: sel.ide, provider: sel.provider, modelId: sel.modelId, displayName: sel.displayName, defaultChronicleStyle: sel.defaultChronicleStyle ?? 'session', registeredModels: newReg });
|
|
72
|
+
console.log(chalk_1.default.green(`\n ✔ Switched to: ${sel.displayName} (${sel.provider})\n`));
|
|
73
|
+
(0, ui_js_1.showWelcome)();
|
|
74
|
+
});
|
|
75
|
+
exports.vaultCmd
|
|
76
|
+
.command('config')
|
|
77
|
+
.description('Edit settings (style, display name) of any registered profile')
|
|
78
|
+
.action(async () => {
|
|
79
|
+
const config = (0, vault_js_1.loadVaultConfig)();
|
|
80
|
+
if (!config) {
|
|
81
|
+
console.log(chalk_1.default.red('\n ✖ Not initialized.\n'));
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
const profiles = config.registeredModels ?? [];
|
|
85
|
+
let targetIdx = -1;
|
|
86
|
+
if (profiles.length > 0) {
|
|
87
|
+
const { which } = await inquirer_1.default.prompt([{
|
|
88
|
+
type: 'list', name: 'which', message: chalk_1.default.cyan('Which profile to edit?'),
|
|
89
|
+
choices: [
|
|
90
|
+
{ name: `★ ${config.ide} / ${config.provider} · ${config.displayName} [ACTIVE]`, value: -1 },
|
|
91
|
+
...profiles.map((p, i) => ({ name: `○ ${p.ide} / ${p.provider} · ${p.displayName}`, value: i })),
|
|
92
|
+
],
|
|
93
|
+
}]);
|
|
94
|
+
targetIdx = which;
|
|
95
|
+
}
|
|
96
|
+
const isActive = targetIdx === -1;
|
|
97
|
+
const curStyle = isActive ? (config.defaultChronicleStyle ?? 'session') : (profiles[targetIdx].defaultChronicleStyle ?? 'session');
|
|
98
|
+
const curName = isActive ? config.displayName : profiles[targetIdx].displayName;
|
|
99
|
+
const STYLE_CHOICES = [
|
|
100
|
+
{ name: 'Session — coding/work session', value: 'session' },
|
|
101
|
+
{ name: 'Reflection — deep thoughts', value: 'reflection' },
|
|
102
|
+
{ name: 'Decision — ADR-style record', value: 'decision' },
|
|
103
|
+
{ name: 'Sweep — daily digest', value: 'sweep' },
|
|
104
|
+
{ name: 'Narcissus — soul narrative', value: 'narcissus' },
|
|
105
|
+
];
|
|
106
|
+
const edit = await inquirer_1.default.prompt([
|
|
107
|
+
{ type: 'list', name: 'style', message: chalk_1.default.cyan('Chronicle style?'), default: curStyle, choices: STYLE_CHOICES },
|
|
108
|
+
{ type: 'input', name: 'displayName', message: chalk_1.default.cyan('Display name?'), default: curName },
|
|
109
|
+
]);
|
|
110
|
+
if (isActive) {
|
|
111
|
+
(0, vault_js_1.saveVaultConfig)({ ...config, defaultChronicleStyle: edit.style, displayName: edit.displayName });
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
const updated = [...profiles];
|
|
115
|
+
updated[targetIdx] = { ...updated[targetIdx], defaultChronicleStyle: edit.style, displayName: edit.displayName };
|
|
116
|
+
(0, vault_js_1.saveVaultConfig)({ ...config, registeredModels: updated });
|
|
117
|
+
}
|
|
118
|
+
console.log(chalk_1.default.green('\n ✔ Profile updated!\n'));
|
|
119
|
+
(0, ui_js_1.showWelcome)();
|
|
120
|
+
});
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.writerCmd = void 0;
|
|
40
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
41
|
+
// MnemoChronicle — Writer commands: commit · sweep · archive
|
|
42
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
43
|
+
const commander_1 = require("commander");
|
|
44
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
45
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
46
|
+
const fs_1 = __importDefault(require("fs"));
|
|
47
|
+
const path_1 = __importDefault(require("path"));
|
|
48
|
+
const vault_js_1 = require("../../lib/vault.js");
|
|
49
|
+
const chronicle_js_1 = require("../../lib/chronicle.js");
|
|
50
|
+
const index_js_1 = require("../../lib/sources/index.js");
|
|
51
|
+
exports.writerCmd = new commander_1.Command();
|
|
52
|
+
exports.writerCmd
|
|
53
|
+
.command('commit')
|
|
54
|
+
.description('Write a new Chronicle to the vault')
|
|
55
|
+
.option('-t, --title <title>', 'Chronicle title')
|
|
56
|
+
.option('--type <type>', 'Chronicle style: session | reflection | decision | sweep | narcissus')
|
|
57
|
+
.option('--tags <tags>', 'Comma-separated tags')
|
|
58
|
+
.option('--auto', 'Auto-generate draft and open in VS Code')
|
|
59
|
+
.action(async (opts) => {
|
|
60
|
+
const config = (0, vault_js_1.loadVaultConfig)();
|
|
61
|
+
if (!config) {
|
|
62
|
+
console.log(chalk_1.default.red('\n ✖ Not initialized. Run: mnemoforge chronicle init\n'));
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
console.log(chalk_1.default.hex('#8B5CF6').bold('\n⬡ MnemoChronicle — New Chronicle\n'));
|
|
66
|
+
const tags = opts.tags ? opts.tags.split(',').map((t) => t.trim()) : [];
|
|
67
|
+
if (opts.auto) {
|
|
68
|
+
console.log(chalk_1.default.cyan(' ⟳ Reading conversation source…'));
|
|
69
|
+
const ctx = (0, index_js_1.readSourceForConfig)(config);
|
|
70
|
+
let draftContent = '', draftTitle = opts.title ?? 'Session chronicle';
|
|
71
|
+
if (ctx) {
|
|
72
|
+
draftContent = (0, index_js_1.generateChronicleDraft)(ctx, config);
|
|
73
|
+
draftTitle = opts.title || ctx.sessionTitle.slice(0, 60) || draftTitle;
|
|
74
|
+
console.log(chalk_1.default.green(` ✔ Draft from: ${ctx.conversationId.slice(0, 8)}… · ${ctx.filesTouched.length} files · ${ctx.keyDecisions.length} decisions`));
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
console.log(chalk_1.default.yellow(' ⚠ No source — blank template.\n'));
|
|
78
|
+
draftContent = (0, index_js_1.generateChronicleDraft)({ conversationId: 'manual', startedAt: null, sessionTitle: draftTitle, filesTouched: [], commandsRun: [], keyDecisions: [], rawTurns: [], sourcePath: '' }, config);
|
|
79
|
+
}
|
|
80
|
+
const { filePath, filename } = (0, chronicle_js_1.writeChronicle)({ title: draftTitle, type: (opts.type ?? config.defaultChronicleStyle ?? 'session'), content: draftContent, tags, config });
|
|
81
|
+
console.log(chalk_1.default.green(`\n ✔ ${filename}`) + chalk_1.default.gray(`\n ${filePath}`));
|
|
82
|
+
console.log(chalk_1.default.cyan('\n Opening in VS Code…\n'));
|
|
83
|
+
try {
|
|
84
|
+
const { spawn } = await Promise.resolve().then(() => __importStar(require('child_process')));
|
|
85
|
+
spawn('code', [filePath], { detached: true, stdio: 'ignore', shell: true }).unref();
|
|
86
|
+
}
|
|
87
|
+
catch { /**/ }
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const answers = await inquirer_1.default.prompt([
|
|
91
|
+
{ type: 'input', name: 'title', message: chalk_1.default.cyan('Title?'), default: opts.title, when: !opts.title, validate: (v) => v.trim() !== '' || 'Required' },
|
|
92
|
+
{ type: 'input', name: 'content', message: chalk_1.default.cyan('Short summary') + chalk_1.default.gray(' (edit after)'), default: '' },
|
|
93
|
+
]);
|
|
94
|
+
const { filePath, filename } = (0, chronicle_js_1.writeChronicle)({ title: opts.title || answers.title, type: (opts.type ?? config.defaultChronicleStyle ?? 'session'), content: answers.content, tags, config });
|
|
95
|
+
console.log(chalk_1.default.green(`\n ✔ ${filename}`) + chalk_1.default.gray(`\n ${filePath}\n`));
|
|
96
|
+
console.log(chalk_1.default.gray(` Tip: use `) + chalk_1.default.white('--auto') + chalk_1.default.gray(' to generate a full draft automatically.\n'));
|
|
97
|
+
});
|
|
98
|
+
exports.writerCmd
|
|
99
|
+
.command('sweep')
|
|
100
|
+
.description('Create a daily sweep Chronicle from recent entries')
|
|
101
|
+
.action(async () => {
|
|
102
|
+
const config = (0, vault_js_1.loadVaultConfig)();
|
|
103
|
+
if (!config) {
|
|
104
|
+
console.log(chalk_1.default.red('\n ✖ Not initialized.\n'));
|
|
105
|
+
process.exit(1);
|
|
106
|
+
}
|
|
107
|
+
const today = new Date().toISOString().slice(0, 10);
|
|
108
|
+
const recent = (0, vault_js_1.listChronicles)(config).filter(f => f.includes(today));
|
|
109
|
+
console.log(chalk_1.default.hex('#8B5CF6').bold('\n⬡ MnemoChronicle — Daily Sweep\n'));
|
|
110
|
+
console.log(chalk_1.default.gray(` Found ${recent.length} chronicle(s) from today (${today})\n`));
|
|
111
|
+
if (recent.length === 0) {
|
|
112
|
+
console.log(chalk_1.default.yellow(' No chronicles today to sweep.\n'));
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
const { ok } = await inquirer_1.default.prompt([{ type: 'confirm', name: 'ok', message: `Create sweep from ${recent.length} chronicle(s)?`, default: true }]);
|
|
116
|
+
if (!ok)
|
|
117
|
+
return;
|
|
118
|
+
const sweepContent = (0, chronicle_js_1.buildSweepContent)(recent, config);
|
|
119
|
+
const { filePath, filename } = (0, chronicle_js_1.writeChronicle)({ title: `Daily Sweep — ${today}`, type: 'sweep', content: sweepContent, tags: ['sweep', today], config });
|
|
120
|
+
console.log(chalk_1.default.green(`\n ✔ ${filename}`) + chalk_1.default.gray(`\n ${filePath}\n`));
|
|
121
|
+
});
|
|
122
|
+
exports.writerCmd
|
|
123
|
+
.command('archive')
|
|
124
|
+
.description('Archive an agent-written .md file into the vault')
|
|
125
|
+
.option('-f, --file <path>', 'Path to the .md chronicle file')
|
|
126
|
+
.action(async (opts) => {
|
|
127
|
+
const config = (0, vault_js_1.loadVaultConfig)();
|
|
128
|
+
if (!config) {
|
|
129
|
+
console.log(chalk_1.default.red('\n ✖ Not initialized.\n'));
|
|
130
|
+
process.exit(1);
|
|
131
|
+
}
|
|
132
|
+
if (!opts.file) {
|
|
133
|
+
console.log(chalk_1.default.red('\n ✖ Specify --file <path>\n'));
|
|
134
|
+
process.exit(1);
|
|
135
|
+
}
|
|
136
|
+
const srcPath = path_1.default.resolve(opts.file);
|
|
137
|
+
if (!fs_1.default.existsSync(srcPath)) {
|
|
138
|
+
console.log(chalk_1.default.red(`\n ✖ File not found: ${srcPath}\n`));
|
|
139
|
+
process.exit(1);
|
|
140
|
+
}
|
|
141
|
+
const destDir = (0, vault_js_1.resolveChronicleDir)(config);
|
|
142
|
+
fs_1.default.mkdirSync(destDir, { recursive: true });
|
|
143
|
+
const filename = path_1.default.basename(srcPath);
|
|
144
|
+
fs_1.default.copyFileSync(srcPath, path_1.default.join(destDir, filename));
|
|
145
|
+
console.log(chalk_1.default.hex('#8B5CF6').bold('\n⬡ MnemoChronicle — Archived\n'));
|
|
146
|
+
console.log(chalk_1.default.green(` ✔ ${filename}`) + chalk_1.default.gray(`\n → ${path_1.default.join(destDir, filename)}\n`));
|
|
147
|
+
});
|