@membank/cli 0.5.0 → 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.
Files changed (2) hide show
  1. package/dist/index.mjs +22 -17
  2. 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, resolveScope } from "@membank/core";
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
- scope: options.scope
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) && typeof rec.scope === "string" && rec.scope.length > 0;
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, type, and scope`);
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, scope, source, access_count, pinned, needs_review, created_at, updated_at)
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.scope, 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());
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 ?? await resolveScope();
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
- process.stdout.write(` ${chalk.dim("Tags:")} ${tags} ${chalk.dim("Scope:")} ${memory.scope}\n`);
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 meta = `${truncate(m.content, 45)}\n${chalk.dim(`${tags} · ${m.scope}`)}`;
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 meta = `${truncate(r.content, 45)}\n${chalk.dim(`${tags} · ${r.scope}`)}`;
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.5.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/dashboard": "0.2.2",
24
- "@membank/mcp": "0.5.0",
25
- "@membank/core": "0.5.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",