@membank/cli 0.5.1 → 0.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/dist/index.mjs +22 -17
- package/package.json +4 -4
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { cancel, confirm, intro, isCancel, multiselect, note, outro } from "@clack/prompts";
|
|
3
|
-
import { DatabaseManager, EmbeddingService, MEMORY_TYPE_VALUES, MemoryRepository, QueryEngine, SessionContextBuilder,
|
|
3
|
+
import { DatabaseManager, EmbeddingService, MEMORY_TYPE_VALUES, MemoryRepository, ProjectRepository, QueryEngine, SessionContextBuilder, resolveProject } from "@membank/core";
|
|
4
4
|
import { startServer } from "@membank/mcp";
|
|
5
5
|
import chalk from "chalk";
|
|
6
6
|
import { Command } from "commander";
|
|
@@ -20,14 +20,14 @@ async function addCommand(content, options, formatter, db, embeddingService) {
|
|
|
20
20
|
const ownDb = db === void 0;
|
|
21
21
|
const resolvedDb = db ?? DatabaseManager.open();
|
|
22
22
|
try {
|
|
23
|
-
const repo = new MemoryRepository(resolvedDb, embeddingService ?? new EmbeddingService());
|
|
23
|
+
const repo = new MemoryRepository(resolvedDb, embeddingService ?? new EmbeddingService(), new ProjectRepository(resolvedDb));
|
|
24
24
|
const tags = options.tags !== void 0 ? options.tags.split(",").map((t) => t.trim()) : [];
|
|
25
25
|
const spinner = formatter.isJson ? null : ora("Saving memory…").start();
|
|
26
26
|
const memory = await repo.save({
|
|
27
27
|
content,
|
|
28
28
|
type: options.type,
|
|
29
29
|
tags,
|
|
30
|
-
|
|
30
|
+
projectHash: options.scope
|
|
31
31
|
});
|
|
32
32
|
spinner?.succeed("Memory saved");
|
|
33
33
|
formatter.outputMemory(memory);
|
|
@@ -48,7 +48,7 @@ async function deleteCommand(id, db, formatter, prompt) {
|
|
|
48
48
|
process.exit(1);
|
|
49
49
|
}
|
|
50
50
|
if (!await prompt.confirm(`Delete memory ${id}?`)) return;
|
|
51
|
-
await new MemoryRepository(db, new EmbeddingService()).delete(id);
|
|
51
|
+
await new MemoryRepository(db, new EmbeddingService(), new ProjectRepository(db)).delete(id);
|
|
52
52
|
process.stdout.write(`${chalk.green("✓")} Deleted memory: ${chalk.dim(id)}\n`);
|
|
53
53
|
}
|
|
54
54
|
//#endregion
|
|
@@ -59,7 +59,6 @@ function exportCommand(db, formatter, opts) {
|
|
|
59
59
|
content: row.content,
|
|
60
60
|
type: row.type,
|
|
61
61
|
tags: JSON.parse(row.tags),
|
|
62
|
-
scope: row.scope,
|
|
63
62
|
sourceHarness: row.source,
|
|
64
63
|
accessCount: row.access_count,
|
|
65
64
|
pinned: row.pinned !== 0,
|
|
@@ -87,7 +86,7 @@ const MEMORY_TYPES = new Set(MEMORY_TYPE_VALUES);
|
|
|
87
86
|
function isValidRecord(r) {
|
|
88
87
|
if (typeof r !== "object" || r === null) return false;
|
|
89
88
|
const rec = r;
|
|
90
|
-
return typeof rec.id === "string" && rec.id.length > 0 && typeof rec.content === "string" && typeof rec.type === "string" && MEMORY_TYPES.has(rec.type)
|
|
89
|
+
return typeof rec.id === "string" && rec.id.length > 0 && typeof rec.content === "string" && typeof rec.type === "string" && MEMORY_TYPES.has(rec.type);
|
|
91
90
|
}
|
|
92
91
|
function isExportFile(parsed) {
|
|
93
92
|
if (typeof parsed !== "object" || parsed === null) return false;
|
|
@@ -115,19 +114,19 @@ async function importCommand(filePath, db, formatter, prompt) {
|
|
|
115
114
|
}
|
|
116
115
|
const invalidIndex = parsed.memories.findIndex((r) => !isValidRecord(r));
|
|
117
116
|
if (invalidIndex !== -1) {
|
|
118
|
-
formatter.error(`Invalid memory record at index ${invalidIndex}: must have id, content,
|
|
117
|
+
formatter.error(`Invalid memory record at index ${invalidIndex}: must have id, content, and type`);
|
|
119
118
|
process.exit(1);
|
|
120
119
|
}
|
|
121
120
|
const count = parsed.memories.length;
|
|
122
121
|
if (formatter.isJson) process.stdout.write(`${JSON.stringify({ found: count })}\n`);
|
|
123
122
|
else process.stdout.write(`Found ${count} memories to import.\n`);
|
|
124
123
|
if (!await prompt.confirm("Import?")) return;
|
|
125
|
-
const insertMemory = db.db.prepare(`INSERT OR REPLACE INTO memories (id, content, type, tags,
|
|
126
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?,
|
|
124
|
+
const insertMemory = db.db.prepare(`INSERT OR REPLACE INTO memories (id, content, type, tags, source, access_count, pinned, needs_review, created_at, updated_at)
|
|
125
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
|
|
127
126
|
const insertEmbedding = db.db.prepare(`INSERT OR REPLACE INTO embeddings (rowid, embedding) SELECT m.rowid, ? FROM memories m WHERE m.id = ?`);
|
|
128
127
|
db.db.transaction(() => {
|
|
129
128
|
for (const rec of parsed.memories) {
|
|
130
|
-
insertMemory.run(rec.id, rec.content, rec.type, JSON.stringify(rec.tags ?? []), rec.
|
|
129
|
+
insertMemory.run(rec.id, rec.content, rec.type, JSON.stringify(rec.tags ?? []), rec.sourceHarness ?? null, rec.accessCount ?? 0, rec.pinned ? 1 : 0, rec.needsReview ? 1 : 0, rec.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(), rec.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString());
|
|
131
130
|
if (rec.embedding !== null && rec.embedding !== void 0) {
|
|
132
131
|
const buf = Buffer.from(rec.embedding, "base64");
|
|
133
132
|
insertEmbedding.run(buf, rec.id);
|
|
@@ -166,7 +165,10 @@ function outputAdditionalContext(text, harness, eventName) {
|
|
|
166
165
|
process.stdout.write(`${text}\n`);
|
|
167
166
|
}
|
|
168
167
|
async function handleSessionStart(opts) {
|
|
169
|
-
const projectScope = opts.scope
|
|
168
|
+
const projectScope = (opts.scope !== void 0 ? {
|
|
169
|
+
hash: opts.scope,
|
|
170
|
+
name: opts.scope
|
|
171
|
+
} : await resolveProject()).hash;
|
|
170
172
|
const db = DatabaseManager.open();
|
|
171
173
|
let text;
|
|
172
174
|
try {
|
|
@@ -187,7 +189,7 @@ async function injectCommand(opts) {
|
|
|
187
189
|
async function listCommand(options, formatter) {
|
|
188
190
|
const db = DatabaseManager.open();
|
|
189
191
|
try {
|
|
190
|
-
const memories = new MemoryRepository(db, new EmbeddingService()).list({
|
|
192
|
+
const memories = new MemoryRepository(db, new EmbeddingService(), new ProjectRepository(db)).list({
|
|
191
193
|
type: options.type,
|
|
192
194
|
pinned: options.pinned
|
|
193
195
|
});
|
|
@@ -219,7 +221,7 @@ async function queryCommand(queryText, options, formatter) {
|
|
|
219
221
|
const db = DatabaseManager.open();
|
|
220
222
|
try {
|
|
221
223
|
const embedding = new EmbeddingService();
|
|
222
|
-
const engine = new QueryEngine(db, embedding, new MemoryRepository(db, embedding));
|
|
224
|
+
const engine = new QueryEngine(db, embedding, new MemoryRepository(db, embedding, new ProjectRepository(db)));
|
|
223
225
|
const limit = options.limit !== void 0 ? Number.parseInt(options.limit, 10) : 10;
|
|
224
226
|
const spinner = formatter.isJson ? null : ora("Searching memories…").start();
|
|
225
227
|
const results = await engine.query({
|
|
@@ -238,7 +240,7 @@ async function queryCommand(queryText, options, formatter) {
|
|
|
238
240
|
async function statsCommand(formatter) {
|
|
239
241
|
const db = DatabaseManager.open();
|
|
240
242
|
try {
|
|
241
|
-
const stats = new MemoryRepository(db, new EmbeddingService()).stats();
|
|
243
|
+
const stats = new MemoryRepository(db, new EmbeddingService(), new ProjectRepository(db)).stats();
|
|
242
244
|
formatter.outputStats(stats);
|
|
243
245
|
} finally {
|
|
244
246
|
db.close();
|
|
@@ -296,7 +298,8 @@ var Formatter = class Formatter {
|
|
|
296
298
|
process.stdout.write("\n");
|
|
297
299
|
process.stdout.write(` ${colorType(memory.type)} ${chalk.dim(memory.id)}\n`);
|
|
298
300
|
process.stdout.write(` ${memory.content}\n`);
|
|
299
|
-
|
|
301
|
+
const scope = memory.projects.length > 0 ? memory.projects.map((p) => p.name).join(", ") : "global";
|
|
302
|
+
process.stdout.write(` ${chalk.dim("Tags:")} ${tags} ${chalk.dim("Scope:")} ${scope}\n`);
|
|
300
303
|
process.stdout.write(`\n ${chalk.dim(`Hint: pin with membank pin ${memory.id}`)}\n\n`);
|
|
301
304
|
}
|
|
302
305
|
outputMemories(memories) {
|
|
@@ -322,7 +325,8 @@ var Formatter = class Formatter {
|
|
|
322
325
|
});
|
|
323
326
|
for (const m of memories) {
|
|
324
327
|
const tags = m.tags.length > 0 ? m.tags.join(", ") : "(none)";
|
|
325
|
-
const
|
|
328
|
+
const mScope = m.projects.length > 0 ? m.projects.map((p) => p.name).join(", ") : "global";
|
|
329
|
+
const meta = `${truncate(m.content, 45)}\n${chalk.dim(`${tags} · ${mScope}`)}`;
|
|
326
330
|
table.push([
|
|
327
331
|
colorType(m.type),
|
|
328
332
|
chalk.dim(m.id),
|
|
@@ -376,7 +380,8 @@ var Formatter = class Formatter {
|
|
|
376
380
|
const scoreStr = r.score.toFixed(4);
|
|
377
381
|
const score = r.score >= .85 ? chalk.bold(scoreStr) : r.score < .75 ? chalk.dim(scoreStr) : scoreStr;
|
|
378
382
|
const tags = r.tags.length > 0 ? r.tags.join(", ") : "(none)";
|
|
379
|
-
const
|
|
383
|
+
const rScope = r.projects.length > 0 ? r.projects.map((p) => p.name).join(", ") : "global";
|
|
384
|
+
const meta = `${truncate(r.content, 45)}\n${chalk.dim(`${tags} · ${rScope}`)}`;
|
|
380
385
|
table.push([
|
|
381
386
|
colorType(r.type),
|
|
382
387
|
chalk.dim(r.id),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@membank/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
"cli-table3": "^0.6.5",
|
|
21
21
|
"commander": "^14.0.3",
|
|
22
22
|
"ora": "^9.4.0",
|
|
23
|
-
"@membank/core": "0.
|
|
24
|
-
"@membank/dashboard": "0.
|
|
25
|
-
"@membank/mcp": "0.
|
|
23
|
+
"@membank/core": "0.6.0",
|
|
24
|
+
"@membank/dashboard": "0.3.0",
|
|
25
|
+
"@membank/mcp": "0.7.0"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/node": "^25.6.0",
|