@hasna/mementos 0.14.17 → 0.14.18

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.js CHANGED
@@ -10142,6 +10142,35 @@ ALTER TABLE memories ADD COLUMN sequence_group TEXT DEFAULT NULL;
10142
10142
  ALTER TABLE memories ADD COLUMN sequence_order INTEGER DEFAULT NULL;
10143
10143
  CREATE INDEX IF NOT EXISTS idx_memories_sequence_group ON memories(sequence_group) WHERE sequence_group IS NOT NULL;
10144
10144
  INSERT OR IGNORE INTO _migrations (id) VALUES (32);
10145
+ `,
10146
+ `
10147
+ ALTER TABLE machines ADD COLUMN is_primary INTEGER NOT NULL DEFAULT 0;
10148
+ CREATE INDEX IF NOT EXISTS idx_machines_primary ON machines(is_primary);
10149
+ CREATE TRIGGER IF NOT EXISTS machines_single_primary_insert
10150
+ AFTER INSERT ON machines
10151
+ WHEN NEW.is_primary = 1
10152
+ BEGIN
10153
+ UPDATE machines
10154
+ SET is_primary = 0,
10155
+ last_seen_at = COALESCE(NEW.last_seen_at, datetime('now'))
10156
+ WHERE id != NEW.id AND is_primary = 1;
10157
+ END;
10158
+ CREATE TRIGGER IF NOT EXISTS machines_single_primary_update
10159
+ AFTER UPDATE OF is_primary ON machines
10160
+ WHEN NEW.is_primary = 1
10161
+ BEGIN
10162
+ UPDATE machines
10163
+ SET is_primary = 0,
10164
+ last_seen_at = COALESCE(NEW.last_seen_at, datetime('now'))
10165
+ WHERE id != NEW.id AND is_primary = 1;
10166
+ END;
10167
+ CREATE TRIGGER IF NOT EXISTS machines_prevent_delete_primary
10168
+ BEFORE DELETE ON machines
10169
+ WHEN OLD.is_primary = 1
10170
+ BEGIN
10171
+ SELECT RAISE(ABORT, 'Primary machine cannot be deleted');
10172
+ END;
10173
+ INSERT OR IGNORE INTO _migrations (id) VALUES (33);
10145
10174
  `
10146
10175
  ];
10147
10176
  });
@@ -10225,11 +10254,16 @@ function ensureDir(filePath) {
10225
10254
  }
10226
10255
  }
10227
10256
  function getDatabase(dbPath) {
10228
- if (_db)
10229
- return _db;
10230
10257
  const path = dbPath || getDbPath2();
10258
+ if (_db) {
10259
+ if (_dbPath === path)
10260
+ return _db;
10261
+ _db.close();
10262
+ _db = null;
10263
+ }
10264
+ _dbPath = path;
10231
10265
  ensureDir(path);
10232
- _db = new SqliteAdapter(path, { create: true });
10266
+ _db = new SqliteAdapter(path);
10233
10267
  _db.run("PRAGMA journal_mode = WAL");
10234
10268
  _db.run("PRAGMA busy_timeout = 5000");
10235
10269
  _db.run("PRAGMA foreign_keys = ON");
@@ -10253,13 +10287,17 @@ function runMigrations(db) {
10253
10287
  for (let i = currentLevel;i < MIGRATIONS.length; i++) {
10254
10288
  try {
10255
10289
  db.exec(MIGRATIONS[i]);
10256
- } catch {}
10290
+ } catch (e) {
10291
+ console.warn(`[mementos] Migration ${i + 1} failed: ${e instanceof Error ? e.message : String(e)}`);
10292
+ }
10257
10293
  }
10258
10294
  } catch {
10259
- for (const migration of MIGRATIONS) {
10295
+ for (let i = 0;i < MIGRATIONS.length; i++) {
10260
10296
  try {
10261
- db.exec(migration);
10262
- } catch {}
10297
+ db.exec(MIGRATIONS[i]);
10298
+ } catch (e) {
10299
+ console.warn(`[mementos] Migration ${i + 1} failed: ${e instanceof Error ? e.message : String(e)}`);
10300
+ }
10263
10301
  }
10264
10302
  }
10265
10303
  }
@@ -10282,6 +10320,9 @@ function shortUuid() {
10282
10320
  return crypto.randomUUID().slice(0, 8);
10283
10321
  }
10284
10322
  function resolvePartialId(db, table, partialId) {
10323
+ if (!ALLOWED_TABLES.has(table)) {
10324
+ throw new Error(`Invalid table name: ${table}`);
10325
+ }
10285
10326
  if (partialId.length >= 36) {
10286
10327
  const row = db.query(`SELECT id FROM ${table} WHERE id = ?`).get(partialId);
10287
10328
  return row?.id ?? null;
@@ -10292,10 +10333,25 @@ function resolvePartialId(db, table, partialId) {
10292
10333
  }
10293
10334
  return null;
10294
10335
  }
10295
- var _db = null;
10336
+ var _db = null, _dbPath = null, ALLOWED_TABLES;
10296
10337
  var init_database = __esm(() => {
10297
10338
  init_dist();
10298
10339
  init_migrations();
10340
+ ALLOWED_TABLES = new Set([
10341
+ "memories",
10342
+ "agents",
10343
+ "entities",
10344
+ "projects",
10345
+ "relations",
10346
+ "memory_audit_log",
10347
+ "locks",
10348
+ "sessions",
10349
+ "session_memory_jobs",
10350
+ "synthesis_runs",
10351
+ "synthesis_proposals",
10352
+ "tool_events",
10353
+ "webhook_hooks"
10354
+ ]);
10299
10355
  });
10300
10356
 
10301
10357
  // src/types/index.ts
@@ -10999,6 +11055,22 @@ function listMemories(filter, db) {
10999
11055
  conditions.push("session_id = ?");
11000
11056
  params.push(filter.session_id);
11001
11057
  }
11058
+ if ("machine_id" in filter) {
11059
+ if (filter.machine_id === null) {
11060
+ conditions.push("machine_id IS NULL");
11061
+ } else if (filter.machine_id) {
11062
+ conditions.push("machine_id = ?");
11063
+ params.push(filter.machine_id);
11064
+ }
11065
+ }
11066
+ if ("visible_to_machine_id" in filter) {
11067
+ if (filter.visible_to_machine_id === null) {
11068
+ conditions.push("machine_id IS NULL");
11069
+ } else if (filter.visible_to_machine_id !== undefined) {
11070
+ conditions.push("(machine_id IS NULL OR machine_id = ?)");
11071
+ params.push(filter.visible_to_machine_id);
11072
+ }
11073
+ }
11002
11074
  if (filter.min_importance) {
11003
11075
  conditions.push("importance >= ?");
11004
11076
  params.push(filter.min_importance);
@@ -11605,6 +11677,102 @@ function listProjects(db) {
11605
11677
  const rows = d.query("SELECT * FROM projects ORDER BY updated_at DESC").all();
11606
11678
  return rows.map(parseProjectRow);
11607
11679
  }
11680
+ // src/db/machines.ts
11681
+ init_database();
11682
+ import { hostname, platform as platform2 } from "os";
11683
+ function parseMachine(row) {
11684
+ if (!row)
11685
+ return null;
11686
+ return {
11687
+ ...row,
11688
+ is_primary: Boolean(row.is_primary)
11689
+ };
11690
+ }
11691
+ function registerMachine(name, db = getDatabase()) {
11692
+ const host = hostname();
11693
+ const plat = platform2();
11694
+ const machineName = name?.trim() || host;
11695
+ const existing = parseMachine(db.query("SELECT * FROM machines WHERE hostname = ?").get(host));
11696
+ if (existing) {
11697
+ db.run("UPDATE machines SET last_seen_at = ? WHERE id = ?", [now(), existing.id]);
11698
+ return parseMachine(db.query("SELECT * FROM machines WHERE id = ?").get(existing.id));
11699
+ }
11700
+ let finalName = machineName;
11701
+ let suffix = 2;
11702
+ while (db.query("SELECT id FROM machines WHERE name = ?").get(finalName)) {
11703
+ finalName = `${machineName}-${suffix++}`;
11704
+ }
11705
+ const id = uuid();
11706
+ db.run("INSERT INTO machines (id, name, hostname, platform) VALUES (?, ?, ?, ?)", [id, finalName, host, plat]);
11707
+ return parseMachine(db.query("SELECT * FROM machines WHERE id = ?").get(id));
11708
+ }
11709
+ function listMachines(db = getDatabase()) {
11710
+ const rows = db.query("SELECT * FROM machines ORDER BY is_primary DESC, last_seen_at DESC, created_at ASC").all();
11711
+ return rows.map((row) => parseMachine(row));
11712
+ }
11713
+ function getMachine(id, db = getDatabase()) {
11714
+ return parseMachine(db.query("SELECT * FROM machines WHERE id = ? OR name = ?").get(id, id));
11715
+ }
11716
+ function renameMachine(id, newName, db = getDatabase()) {
11717
+ const m = parseMachine(db.query("SELECT * FROM machines WHERE id = ?").get(id));
11718
+ if (!m)
11719
+ throw new Error(`Machine not found: ${id}`);
11720
+ const clash = db.query("SELECT id FROM machines WHERE name = ? AND id != ?").get(newName, id);
11721
+ if (clash)
11722
+ throw new Error(`Machine name already taken: ${newName}`);
11723
+ db.run("UPDATE machines SET name = ?, last_seen_at = ? WHERE id = ?", [newName, now(), id]);
11724
+ return parseMachine(db.query("SELECT * FROM machines WHERE id = ?").get(id));
11725
+ }
11726
+ function getPrimaryMachine(db = getDatabase()) {
11727
+ return parseMachine(db.query("SELECT * FROM machines WHERE is_primary = 1 LIMIT 1").get());
11728
+ }
11729
+ function getPrimaryMachineCandidate(db = getDatabase()) {
11730
+ if (getPrimaryMachine(db))
11731
+ return null;
11732
+ return parseMachine(db.query("SELECT * FROM machines ORDER BY created_at ASC, id ASC LIMIT 1").get());
11733
+ }
11734
+ function setPrimaryMachine(id, db = getDatabase()) {
11735
+ const machine = getMachine(id, db);
11736
+ if (!machine)
11737
+ throw new Error(`Machine not found: ${id}`);
11738
+ const updatedAt = now();
11739
+ db.run("UPDATE machines SET is_primary = 0, last_seen_at = ? WHERE is_primary = 1 AND id != ?", [updatedAt, machine.id]);
11740
+ db.run("UPDATE machines SET is_primary = 1, last_seen_at = ? WHERE id = ?", [updatedAt, machine.id]);
11741
+ return getMachine(machine.id, db);
11742
+ }
11743
+ function deleteMachine(id, db = getDatabase()) {
11744
+ const machine = getMachine(id, db);
11745
+ if (!machine)
11746
+ throw new Error(`Machine not found: ${id}`);
11747
+ if (machine.is_primary) {
11748
+ throw new Error(`Primary machine cannot be deleted: ${machine.name}`);
11749
+ }
11750
+ db.run("DELETE FROM machines WHERE id = ?", [machine.id]);
11751
+ }
11752
+ function getFallbackSyncTargetMachine(db = getDatabase()) {
11753
+ return getPrimaryMachine(db);
11754
+ }
11755
+ function getPrimaryMachineStartupWarning(db = getDatabase()) {
11756
+ if (getPrimaryMachine(db))
11757
+ return null;
11758
+ const candidate = getPrimaryMachineCandidate(db);
11759
+ if (!candidate) {
11760
+ return "No primary machine configured. Fallback sync target is unset because no machines are registered yet.";
11761
+ }
11762
+ return `No primary machine configured. Fallback sync target is unset. Candidate: ${candidate.name} (${candidate.id.slice(0, 8)} / ${candidate.hostname}). Confirm it with set_primary_machine.`;
11763
+ }
11764
+ function touchMachine(id, db = getDatabase()) {
11765
+ db.run("UPDATE machines SET last_seen_at = ? WHERE id = ?", [now(), id]);
11766
+ }
11767
+ function getCurrentMachineId(db = getDatabase()) {
11768
+ const host = hostname();
11769
+ const m = db.query("SELECT id FROM machines WHERE hostname = ?").get(host);
11770
+ if (m) {
11771
+ touchMachine(m.id, db);
11772
+ return m.id;
11773
+ }
11774
+ return registerMachine(undefined, db).id;
11775
+ }
11608
11776
  // src/lib/search.ts
11609
11777
  init_database();
11610
11778
 
@@ -12470,6 +12638,23 @@ function ensureDir2(dir) {
12470
12638
  mkdirSync5(dir, { recursive: true });
12471
12639
  }
12472
12640
  }
12641
+ // src/lib/machine-visibility.ts
12642
+ function resolveVisibleMachineId(machineId, db) {
12643
+ if (machineId !== undefined) {
12644
+ return machineId;
12645
+ }
12646
+ try {
12647
+ return getCurrentMachineId(db);
12648
+ } catch {
12649
+ return null;
12650
+ }
12651
+ }
12652
+ function visibleToMachineFilter(machineId, db) {
12653
+ return {
12654
+ visible_to_machine_id: resolveVisibleMachineId(machineId, db)
12655
+ };
12656
+ }
12657
+
12473
12658
  // src/db/tool-events.ts
12474
12659
  init_database();
12475
12660
 
@@ -12485,12 +12670,14 @@ class MemoryInjector {
12485
12670
  const minImportance = options.min_importance || this.config.injection.min_importance;
12486
12671
  const categories = options.categories || this.config.injection.categories;
12487
12672
  const db = options.db;
12673
+ const visibleMachineId = resolveVisibleMachineId(options.machine_id, db);
12488
12674
  const allMemories = [];
12489
12675
  const globalMems = listMemories({
12490
12676
  scope: "global",
12491
12677
  category: categories,
12492
12678
  min_importance: minImportance,
12493
12679
  status: "active",
12680
+ ...visibleToMachineFilter(visibleMachineId),
12494
12681
  limit: 100
12495
12682
  }, db);
12496
12683
  allMemories.push(...globalMems);
@@ -12501,6 +12688,7 @@ class MemoryInjector {
12501
12688
  min_importance: minImportance,
12502
12689
  status: "active",
12503
12690
  project_id: options.project_id,
12691
+ ...visibleToMachineFilter(visibleMachineId),
12504
12692
  limit: 100
12505
12693
  }, db);
12506
12694
  allMemories.push(...sharedMems);
@@ -12512,6 +12700,7 @@ class MemoryInjector {
12512
12700
  min_importance: minImportance,
12513
12701
  status: "active",
12514
12702
  agent_id: options.agent_id,
12703
+ ...visibleToMachineFilter(visibleMachineId),
12515
12704
  limit: 100
12516
12705
  }, db);
12517
12706
  allMemories.push(...privateMems);
@@ -12523,6 +12712,7 @@ class MemoryInjector {
12523
12712
  ...options.session_id ? { session_id: options.session_id } : {},
12524
12713
  ...options.agent_id ? { agent_id: options.agent_id } : {},
12525
12714
  ...options.project_id ? { project_id: options.project_id } : {},
12715
+ ...visibleToMachineFilter(visibleMachineId),
12526
12716
  limit: 100
12527
12717
  }, db);
12528
12718
  allMemories.push(...workingMems);
@@ -12630,12 +12820,14 @@ ${sections.join(`
12630
12820
  const minImportance = options.min_importance || this.config.injection.min_importance;
12631
12821
  const categories = options.categories || this.config.injection.categories;
12632
12822
  const db = options.db;
12823
+ const visibleMachineId = resolveVisibleMachineId(options.machine_id, db);
12633
12824
  const allMemories = [];
12634
12825
  const globalMems = listMemories({
12635
12826
  scope: "global",
12636
12827
  category: categories,
12637
12828
  min_importance: minImportance,
12638
12829
  status: "active",
12830
+ ...visibleToMachineFilter(visibleMachineId),
12639
12831
  limit: 100
12640
12832
  }, db);
12641
12833
  allMemories.push(...globalMems);
@@ -12646,6 +12838,7 @@ ${sections.join(`
12646
12838
  min_importance: minImportance,
12647
12839
  status: "active",
12648
12840
  project_id: options.project_id,
12841
+ ...visibleToMachineFilter(visibleMachineId),
12649
12842
  limit: 100
12650
12843
  }, db);
12651
12844
  allMemories.push(...sharedMems);
@@ -12657,6 +12850,7 @@ ${sections.join(`
12657
12850
  min_importance: minImportance,
12658
12851
  status: "active",
12659
12852
  agent_id: options.agent_id,
12853
+ ...visibleToMachineFilter(visibleMachineId),
12660
12854
  limit: 100
12661
12855
  }, db);
12662
12856
  allMemories.push(...privateMems);
@@ -12668,6 +12862,7 @@ ${sections.join(`
12668
12862
  ...options.session_id ? { session_id: options.session_id } : {},
12669
12863
  ...options.agent_id ? { agent_id: options.agent_id } : {},
12670
12864
  ...options.project_id ? { project_id: options.project_id } : {},
12865
+ ...visibleToMachineFilter(visibleMachineId),
12671
12866
  limit: 100
12672
12867
  }, db);
12673
12868
  allMemories.push(...workingMems);
@@ -13975,9 +14170,11 @@ export {
13975
14170
  unlinkEntityFromMemory,
13976
14171
  unfocus,
13977
14172
  touchMemory,
14173
+ touchMachine,
13978
14174
  touchAgent,
13979
14175
  syncMemories,
13980
14176
  shortUuid,
14177
+ setPrimaryMachine,
13981
14178
  setFocus,
13982
14179
  setActiveProfile,
13983
14180
  setActiveModel,
@@ -13986,11 +14183,13 @@ export {
13986
14183
  resolveProjectId,
13987
14184
  resolvePartialId,
13988
14185
  resetDatabase,
14186
+ renameMachine,
13989
14187
  releaseResourceLocks,
13990
14188
  releaseMemoryWriteLock,
13991
14189
  releaseLock,
13992
14190
  releaseAllAgentLocks,
13993
14191
  registerProject,
14192
+ registerMachine,
13994
14193
  registerAgent,
13995
14194
  redactSecrets,
13996
14195
  providerRegistry,
@@ -14005,6 +14204,7 @@ export {
14005
14204
  listProjects,
14006
14205
  listProfiles,
14007
14206
  listMemories,
14207
+ listMachines,
14008
14208
  listEntities,
14009
14209
  listAgentsByProject,
14010
14210
  listAgents,
@@ -14014,12 +14214,17 @@ export {
14014
14214
  getRelation,
14015
14215
  getRelatedEntities,
14016
14216
  getProject,
14217
+ getPrimaryMachineStartupWarning,
14218
+ getPrimaryMachineCandidate,
14219
+ getPrimaryMachine,
14017
14220
  getMemoryVersions,
14018
14221
  getMemoryByKey,
14019
14222
  getMemory,
14020
14223
  getMemoriesForEntity,
14021
14224
  getMemoriesByKey,
14225
+ getMachine,
14022
14226
  getFocus,
14227
+ getFallbackSyncTargetMachine,
14023
14228
  getEntityMemoryLinks,
14024
14229
  getEntityGraph,
14025
14230
  getEntityByName,
@@ -14028,6 +14233,7 @@ export {
14028
14233
  getDedupStats,
14029
14234
  getDbPath2 as getDbPath,
14030
14235
  getDatabase,
14236
+ getCurrentMachineId,
14031
14237
  getAutoMemoryStats,
14032
14238
  getAgent,
14033
14239
  getActiveProfile,
@@ -14040,6 +14246,7 @@ export {
14040
14246
  deleteRelation,
14041
14247
  deleteProfile,
14042
14248
  deleteMemory,
14249
+ deleteMachine,
14043
14250
  deleteEntity,
14044
14251
  defaultSyncAgents,
14045
14252
  dedup,