@hasna/mementos 0.1.0 → 0.1.2

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.
@@ -4,7 +4,7 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>Mementos Dashboard</title>
7
- <script type="module" crossorigin src="/assets/index-Dnhl5e5q.js"></script>
7
+ <script type="module" crossorigin src="/assets/index-C5oRjtKB.js"></script>
8
8
  <link rel="stylesheet" crossorigin href="/assets/index-C8vbNL_5.css">
9
9
  </head>
10
10
  <body>
package/dist/cli/index.js CHANGED
@@ -4,6 +4,7 @@ var __create = Object.create;
4
4
  var __getProtoOf = Object.getPrototypeOf;
5
5
  var __defProp = Object.defineProperty;
6
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
9
  var __toESM = (mod, isNodeMode, target) => {
9
10
  target = mod != null ? __create(__getProtoOf(mod)) : {};
@@ -16,7 +17,31 @@ var __toESM = (mod, isNodeMode, target) => {
16
17
  });
17
18
  return to;
18
19
  };
20
+ var __moduleCache = /* @__PURE__ */ new WeakMap;
21
+ var __toCommonJS = (from) => {
22
+ var entry = __moduleCache.get(from), desc;
23
+ if (entry)
24
+ return entry;
25
+ entry = __defProp({}, "__esModule", { value: true });
26
+ if (from && typeof from === "object" || typeof from === "function")
27
+ __getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
28
+ get: () => from[key],
29
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
30
+ }));
31
+ __moduleCache.set(from, entry);
32
+ return entry;
33
+ };
19
34
  var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
35
+ var __export = (target, all) => {
36
+ for (var name in all)
37
+ __defProp(target, name, {
38
+ get: all[name],
39
+ enumerable: true,
40
+ configurable: true,
41
+ set: (newValue) => all[name] = () => newValue
42
+ });
43
+ };
44
+ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
20
45
  var __require = import.meta.require;
21
46
 
22
47
  // node_modules/commander/lib/error.js
@@ -2053,28 +2078,6 @@ var require_commander = __commonJS((exports) => {
2053
2078
  exports.InvalidOptionArgumentError = InvalidArgumentError;
2054
2079
  });
2055
2080
 
2056
- // node_modules/commander/esm.mjs
2057
- var import__ = __toESM(require_commander(), 1);
2058
- var {
2059
- program,
2060
- createCommand,
2061
- createArgument,
2062
- createOption,
2063
- CommanderError,
2064
- InvalidArgumentError,
2065
- InvalidOptionArgumentError,
2066
- Command,
2067
- Argument,
2068
- Option,
2069
- Help
2070
- } = import__.default;
2071
-
2072
- // src/cli/index.tsx
2073
- import chalk from "chalk";
2074
- import { readFileSync as readFileSync2 } from "fs";
2075
- import { dirname as dirname3, join as join3, resolve as resolve3 } from "path";
2076
- import { fileURLToPath } from "url";
2077
-
2078
2081
  // src/db/database.ts
2079
2082
  import { Database } from "bun:sqlite";
2080
2083
  import { existsSync, mkdirSync } from "fs";
@@ -2132,8 +2135,59 @@ function ensureDir(filePath) {
2132
2135
  mkdirSync(dir, { recursive: true });
2133
2136
  }
2134
2137
  }
2135
- var MIGRATIONS = [
2136
- `
2138
+ function getDatabase(dbPath) {
2139
+ if (_db)
2140
+ return _db;
2141
+ const path = dbPath || getDbPath();
2142
+ ensureDir(path);
2143
+ _db = new Database(path, { create: true });
2144
+ _db.run("PRAGMA journal_mode = WAL");
2145
+ _db.run("PRAGMA busy_timeout = 5000");
2146
+ _db.run("PRAGMA foreign_keys = ON");
2147
+ runMigrations(_db);
2148
+ return _db;
2149
+ }
2150
+ function runMigrations(db) {
2151
+ try {
2152
+ const result = db.query("SELECT MAX(id) as max_id FROM _migrations").get();
2153
+ const currentLevel = result?.max_id ?? 0;
2154
+ for (let i = currentLevel;i < MIGRATIONS.length; i++) {
2155
+ try {
2156
+ db.exec(MIGRATIONS[i]);
2157
+ } catch {}
2158
+ }
2159
+ } catch {
2160
+ for (const migration of MIGRATIONS) {
2161
+ try {
2162
+ db.exec(migration);
2163
+ } catch {}
2164
+ }
2165
+ }
2166
+ }
2167
+ function now() {
2168
+ return new Date().toISOString();
2169
+ }
2170
+ function uuid() {
2171
+ return crypto.randomUUID();
2172
+ }
2173
+ function shortUuid() {
2174
+ return crypto.randomUUID().slice(0, 8);
2175
+ }
2176
+ function resolvePartialId(db, table, partialId) {
2177
+ if (partialId.length >= 36) {
2178
+ const row = db.query(`SELECT id FROM ${table} WHERE id = ?`).get(partialId);
2179
+ return row?.id ?? null;
2180
+ }
2181
+ const rows = db.query(`SELECT id FROM ${table} WHERE id LIKE ?`).all(`${partialId}%`);
2182
+ if (rows.length === 1) {
2183
+ return rows[0].id;
2184
+ }
2185
+ return null;
2186
+ }
2187
+ var MIGRATIONS, _db = null;
2188
+ var init_database = __esm(() => {
2189
+ MIGRATIONS = [
2190
+ `
2137
2191
  CREATE TABLE IF NOT EXISTS projects (
2138
2192
  id TEXT PRIMARY KEY,
2139
2193
  name TEXT NOT NULL,
@@ -2220,75 +2274,29 @@ var MIGRATIONS = [
2220
2274
 
2221
2275
  INSERT OR IGNORE INTO _migrations (id) VALUES (1);
2222
2276
  `
2223
- ];
2224
- var _db = null;
2225
- function getDatabase(dbPath) {
2226
- if (_db)
2227
- return _db;
2228
- const path = dbPath || getDbPath();
2229
- ensureDir(path);
2230
- _db = new Database(path, { create: true });
2231
- _db.run("PRAGMA journal_mode = WAL");
2232
- _db.run("PRAGMA busy_timeout = 5000");
2233
- _db.run("PRAGMA foreign_keys = ON");
2234
- runMigrations(_db);
2235
- return _db;
2236
- }
2237
- function runMigrations(db) {
2238
- try {
2239
- const result = db.query("SELECT MAX(id) as max_id FROM _migrations").get();
2240
- const currentLevel = result?.max_id ?? 0;
2241
- for (let i = currentLevel;i < MIGRATIONS.length; i++) {
2242
- try {
2243
- db.exec(MIGRATIONS[i]);
2244
- } catch {}
2245
- }
2246
- } catch {
2247
- for (const migration of MIGRATIONS) {
2248
- try {
2249
- db.exec(migration);
2250
- } catch {}
2251
- }
2252
- }
2253
- }
2254
- function now() {
2255
- return new Date().toISOString();
2256
- }
2257
- function uuid() {
2258
- return crypto.randomUUID();
2259
- }
2260
- function shortUuid() {
2261
- return crypto.randomUUID().slice(0, 8);
2262
- }
2263
- function resolvePartialId(db, table, partialId) {
2264
- if (partialId.length >= 36) {
2265
- const row = db.query(`SELECT id FROM ${table} WHERE id = ?`).get(partialId);
2266
- return row?.id ?? null;
2267
- }
2268
- const rows = db.query(`SELECT id FROM ${table} WHERE id LIKE ?`).all(`${partialId}%`);
2269
- if (rows.length === 1) {
2270
- return rows[0].id;
2271
- }
2272
- return null;
2273
- }
2277
+ ];
2278
+ });
2274
2279
 
2275
2280
  // src/types/index.ts
2276
- class MemoryNotFoundError extends Error {
2277
- constructor(id) {
2278
- super(`Memory not found: ${id}`);
2279
- this.name = "MemoryNotFoundError";
2280
- }
2281
- }
2282
- class VersionConflictError extends Error {
2283
- expected;
2284
- actual;
2285
- constructor(id, expected, actual) {
2286
- super(`Version conflict for memory ${id}: expected ${expected}, got ${actual}`);
2287
- this.name = "VersionConflictError";
2288
- this.expected = expected;
2289
- this.actual = actual;
2290
- }
2291
- }
2281
+ var MemoryNotFoundError, VersionConflictError;
2282
+ var init_types = __esm(() => {
2283
+ MemoryNotFoundError = class MemoryNotFoundError extends Error {
2284
+ constructor(id) {
2285
+ super(`Memory not found: ${id}`);
2286
+ this.name = "MemoryNotFoundError";
2287
+ }
2288
+ };
2289
+ VersionConflictError = class VersionConflictError extends Error {
2290
+ expected;
2291
+ actual;
2292
+ constructor(id, expected, actual) {
2293
+ super(`Version conflict for memory ${id}: expected ${expected}, got ${actual}`);
2294
+ this.name = "VersionConflictError";
2295
+ this.expected = expected;
2296
+ this.actual = actual;
2297
+ }
2298
+ };
2299
+ });
2292
2300
 
2293
2301
  // src/db/memories.ts
2294
2302
  function parseMemoryRow(row) {
@@ -2591,8 +2599,150 @@ function cleanExpiredMemories(db) {
2591
2599
  const result = d.run("DELETE FROM memories WHERE expires_at IS NOT NULL AND expires_at < ?", [timestamp]);
2592
2600
  return result.changes;
2593
2601
  }
2602
+ var init_memories = __esm(() => {
2603
+ init_types();
2604
+ init_database();
2605
+ });
2606
+
2607
+ // src/lib/poll.ts
2608
+ var exports_poll = {};
2609
+ __export(exports_poll, {
2610
+ startPolling: () => startPolling
2611
+ });
2612
+ function startPolling(opts) {
2613
+ const interval = opts.interval_ms ?? 500;
2614
+ const db = opts.db ?? getDatabase();
2615
+ let stopped = false;
2616
+ let inFlight = false;
2617
+ let lastSeen = null;
2618
+ const seedLastSeen = () => {
2619
+ try {
2620
+ const latest = listMemories({
2621
+ scope: opts.scope,
2622
+ category: opts.category,
2623
+ agent_id: opts.agent_id,
2624
+ project_id: opts.project_id,
2625
+ limit: 1
2626
+ }, db);
2627
+ if (latest.length > 0 && latest[0]) {
2628
+ lastSeen = latest[0].updated_at;
2629
+ }
2630
+ } catch (err) {
2631
+ opts.on_error?.(err instanceof Error ? err : new Error(String(err)));
2632
+ }
2633
+ };
2634
+ const poll = () => {
2635
+ if (stopped || inFlight)
2636
+ return;
2637
+ inFlight = true;
2638
+ try {
2639
+ const conditions = ["status = 'active'"];
2640
+ const params = [];
2641
+ if (lastSeen) {
2642
+ conditions.push("(updated_at > ? OR created_at > ?)");
2643
+ params.push(lastSeen, lastSeen);
2644
+ }
2645
+ if (opts.scope) {
2646
+ conditions.push("scope = ?");
2647
+ params.push(opts.scope);
2648
+ }
2649
+ if (opts.category) {
2650
+ conditions.push("category = ?");
2651
+ params.push(opts.category);
2652
+ }
2653
+ if (opts.agent_id) {
2654
+ conditions.push("agent_id = ?");
2655
+ params.push(opts.agent_id);
2656
+ }
2657
+ if (opts.project_id) {
2658
+ conditions.push("project_id = ?");
2659
+ params.push(opts.project_id);
2660
+ }
2661
+ const sql = `SELECT * FROM memories WHERE ${conditions.join(" AND ")} ORDER BY updated_at ASC`;
2662
+ const rows = db.query(sql).all(...params);
2663
+ if (rows.length > 0) {
2664
+ const memories = rows.map(parseMemoryRow3);
2665
+ const lastRow = memories[memories.length - 1];
2666
+ if (lastRow) {
2667
+ lastSeen = lastRow.updated_at;
2668
+ }
2669
+ try {
2670
+ opts.on_memories(memories);
2671
+ } catch (err) {
2672
+ opts.on_error?.(err instanceof Error ? err : new Error(String(err)));
2673
+ }
2674
+ }
2675
+ } catch (err) {
2676
+ opts.on_error?.(err instanceof Error ? err : new Error(String(err)));
2677
+ } finally {
2678
+ inFlight = false;
2679
+ }
2680
+ };
2681
+ seedLastSeen();
2682
+ const timer = setInterval(poll, interval);
2683
+ return {
2684
+ stop: () => {
2685
+ stopped = true;
2686
+ clearInterval(timer);
2687
+ }
2688
+ };
2689
+ }
2690
+ function parseMemoryRow3(row) {
2691
+ return {
2692
+ id: row["id"],
2693
+ key: row["key"],
2694
+ value: row["value"],
2695
+ category: row["category"],
2696
+ scope: row["scope"],
2697
+ summary: row["summary"] || null,
2698
+ tags: JSON.parse(row["tags"] || "[]"),
2699
+ importance: row["importance"],
2700
+ source: row["source"],
2701
+ status: row["status"],
2702
+ pinned: !!row["pinned"],
2703
+ agent_id: row["agent_id"] || null,
2704
+ project_id: row["project_id"] || null,
2705
+ session_id: row["session_id"] || null,
2706
+ metadata: JSON.parse(row["metadata"] || "{}"),
2707
+ access_count: row["access_count"],
2708
+ version: row["version"],
2709
+ expires_at: row["expires_at"] || null,
2710
+ created_at: row["created_at"],
2711
+ updated_at: row["updated_at"],
2712
+ accessed_at: row["accessed_at"] || null
2713
+ };
2714
+ }
2715
+ var init_poll = __esm(() => {
2716
+ init_memories();
2717
+ init_database();
2718
+ });
2719
+
2720
+ // node_modules/commander/esm.mjs
2721
+ var import__ = __toESM(require_commander(), 1);
2722
+ var {
2723
+ program,
2724
+ createCommand,
2725
+ createArgument,
2726
+ createOption,
2727
+ CommanderError,
2728
+ InvalidArgumentError,
2729
+ InvalidOptionArgumentError,
2730
+ Command,
2731
+ Argument,
2732
+ Option,
2733
+ Help
2734
+ } = import__.default;
2735
+
2736
+ // src/cli/index.tsx
2737
+ init_database();
2738
+ init_memories();
2739
+ import chalk from "chalk";
2740
+ import { readFileSync as readFileSync2 } from "fs";
2741
+ import { dirname as dirname3, join as join3, resolve as resolve3 } from "path";
2742
+ import { fileURLToPath } from "url";
2594
2743
 
2595
2744
  // src/db/agents.ts
2745
+ init_database();
2596
2746
  function parseAgentRow(row) {
2597
2747
  return {
2598
2748
  id: row["id"],
@@ -2650,8 +2800,34 @@ function listAgents(db) {
2650
2800
  const rows = d.query("SELECT * FROM agents ORDER BY last_seen_at DESC").all();
2651
2801
  return rows.map(parseAgentRow);
2652
2802
  }
2803
+ function updateAgent(id, updates, db) {
2804
+ const d = db || getDatabase();
2805
+ const agent = getAgent(id, d);
2806
+ if (!agent)
2807
+ return null;
2808
+ const timestamp = now();
2809
+ if (updates.name && updates.name !== agent.name) {
2810
+ const existing = d.query("SELECT id FROM agents WHERE name = ? AND id != ?").get(updates.name, agent.id);
2811
+ if (existing) {
2812
+ throw new Error(`Agent name already taken: ${updates.name}`);
2813
+ }
2814
+ d.run("UPDATE agents SET name = ? WHERE id = ?", [updates.name, agent.id]);
2815
+ }
2816
+ if (updates.description !== undefined) {
2817
+ d.run("UPDATE agents SET description = ? WHERE id = ?", [updates.description, agent.id]);
2818
+ }
2819
+ if (updates.role !== undefined) {
2820
+ d.run("UPDATE agents SET role = ? WHERE id = ?", [updates.role, agent.id]);
2821
+ }
2822
+ if (updates.metadata !== undefined) {
2823
+ d.run("UPDATE agents SET metadata = ? WHERE id = ?", [JSON.stringify(updates.metadata), agent.id]);
2824
+ }
2825
+ d.run("UPDATE agents SET last_seen_at = ? WHERE id = ?", [timestamp, agent.id]);
2826
+ return getAgent(agent.id, d);
2827
+ }
2653
2828
 
2654
2829
  // src/db/projects.ts
2830
+ init_database();
2655
2831
  function parseProjectRow(row) {
2656
2832
  return {
2657
2833
  id: row["id"],
@@ -2696,6 +2872,7 @@ function listProjects(db) {
2696
2872
  }
2697
2873
 
2698
2874
  // src/lib/search.ts
2875
+ init_database();
2699
2876
  function parseMemoryRow2(row) {
2700
2877
  return {
2701
2878
  id: row["id"],
@@ -2929,6 +3106,8 @@ function loadConfig() {
2929
3106
  }
2930
3107
 
2931
3108
  // src/lib/retention.ts
3109
+ init_database();
3110
+ init_memories();
2932
3111
  function enforceQuotas(config, db) {
2933
3112
  const d = db || getDatabase();
2934
3113
  let totalEvicted = 0;
@@ -3440,6 +3619,47 @@ program2.command("agents").description("List all registered agents").action(() =
3440
3619
  handleError(e);
3441
3620
  }
3442
3621
  });
3622
+ program2.command("agent-update <id>").description("Update an agent's name, description, or role").option("--name <name>", "New agent name").option("-d, --description <text>", "New description").option("-r, --role <role>", "New role").action((id, opts) => {
3623
+ try {
3624
+ const globalOpts = program2.opts();
3625
+ const updates = {};
3626
+ if (opts.name !== undefined)
3627
+ updates.name = opts.name;
3628
+ if (opts.description !== undefined)
3629
+ updates.description = opts.description;
3630
+ if (opts.role !== undefined)
3631
+ updates.role = opts.role;
3632
+ if (Object.keys(updates).length === 0) {
3633
+ if (globalOpts.json) {
3634
+ outputJson({ error: "No updates provided. Use --name, --description, or --role." });
3635
+ } else {
3636
+ console.error(chalk.red("No updates provided. Use --name, --description, or --role."));
3637
+ }
3638
+ process.exit(1);
3639
+ }
3640
+ const agent = updateAgent(id, updates);
3641
+ if (!agent) {
3642
+ if (globalOpts.json) {
3643
+ outputJson({ error: `Agent not found: ${id}` });
3644
+ } else {
3645
+ console.error(chalk.red(`Agent not found: ${id}`));
3646
+ }
3647
+ process.exit(1);
3648
+ }
3649
+ if (globalOpts.json) {
3650
+ outputJson(agent);
3651
+ } else {
3652
+ console.log(chalk.green("Agent updated:"));
3653
+ console.log(` ${chalk.bold("ID:")} ${agent.id}`);
3654
+ console.log(` ${chalk.bold("Name:")} ${agent.name}`);
3655
+ console.log(` ${chalk.bold("Description:")} ${agent.description || "-"}`);
3656
+ console.log(` ${chalk.bold("Role:")} ${agent.role || "agent"}`);
3657
+ console.log(` ${chalk.bold("Last seen:")} ${agent.last_seen_at}`);
3658
+ }
3659
+ } catch (e) {
3660
+ handleError(e);
3661
+ }
3662
+ });
3443
3663
  program2.command("projects").description("Manage projects").option("--add", "Add a new project").option("--name <name>", "Project name").option("--path <path>", "Project path").option("--description <text>", "Project description").action((opts) => {
3444
3664
  try {
3445
3665
  const globalOpts = program2.opts();
@@ -3640,4 +3860,182 @@ program2.command("bulk <action> <ids...>").description("Batch operations: forget
3640
3860
  handleError(e);
3641
3861
  }
3642
3862
  });
3863
+ program2.command("mcp").description("Install mementos MCP server into Claude Code, Codex, or Gemini").option("--claude", "Install into Claude Code (~/.claude/.mcp.json)").option("--codex", "Install into Codex (~/.codex/config.toml)").option("--gemini", "Install into Gemini (~/.gemini/settings.json)").option("--all", "Install into all supported agents").option("--uninstall", "Remove mementos MCP from config").action((opts) => {
3864
+ const { readFileSync: readFileSync3, writeFileSync, existsSync: fileExists } = __require("fs");
3865
+ const { join: pathJoin } = __require("path");
3866
+ const { homedir: getHome } = __require("os");
3867
+ const home = getHome();
3868
+ const mementosCmd = process.argv[0]?.includes("bun") ? pathJoin(home, ".bun", "bin", "mementos-mcp") : "mementos-mcp";
3869
+ const targets = opts.all ? ["claude", "codex", "gemini"] : [
3870
+ opts.claude ? "claude" : null,
3871
+ opts.codex ? "codex" : null,
3872
+ opts.gemini ? "gemini" : null
3873
+ ].filter(Boolean);
3874
+ if (targets.length === 0) {
3875
+ console.log(chalk.yellow("Specify a target: --claude, --codex, --gemini, or --all"));
3876
+ console.log(chalk.gray("Example: mementos mcp --all"));
3877
+ return;
3878
+ }
3879
+ for (const target of targets) {
3880
+ try {
3881
+ if (target === "claude") {
3882
+ const configPath = pathJoin(home, ".claude", ".mcp.json");
3883
+ let config = {};
3884
+ if (fileExists(configPath)) {
3885
+ config = JSON.parse(readFileSync3(configPath, "utf-8"));
3886
+ }
3887
+ const servers = config["mcpServers"] || {};
3888
+ if (opts.uninstall) {
3889
+ delete servers["mementos"];
3890
+ } else {
3891
+ servers["mementos"] = { command: mementosCmd, args: [] };
3892
+ }
3893
+ config["mcpServers"] = servers;
3894
+ writeFileSync(configPath, JSON.stringify(config, null, 2) + `
3895
+ `, "utf-8");
3896
+ console.log(chalk.green(`${opts.uninstall ? "Removed from" : "Installed into"} Claude Code: ${configPath}`));
3897
+ }
3898
+ if (target === "codex") {
3899
+ const configPath = pathJoin(home, ".codex", "config.toml");
3900
+ if (fileExists(configPath)) {
3901
+ let content = readFileSync3(configPath, "utf-8");
3902
+ if (opts.uninstall) {
3903
+ content = content.replace(/\n\[mcp_servers\.mementos\]\ncommand = "[^"]*"\nargs = \[\]\n?/g, `
3904
+ `);
3905
+ } else if (!content.includes("[mcp_servers.mementos]")) {
3906
+ content += `
3907
+ [mcp_servers.mementos]
3908
+ command = "${mementosCmd}"
3909
+ args = []
3910
+ `;
3911
+ }
3912
+ writeFileSync(configPath, content, "utf-8");
3913
+ console.log(chalk.green(`${opts.uninstall ? "Removed from" : "Installed into"} Codex: ${configPath}`));
3914
+ } else {
3915
+ console.log(chalk.yellow(`Codex config not found: ${configPath}`));
3916
+ }
3917
+ }
3918
+ if (target === "gemini") {
3919
+ const configPath = pathJoin(home, ".gemini", "settings.json");
3920
+ let config = {};
3921
+ if (fileExists(configPath)) {
3922
+ config = JSON.parse(readFileSync3(configPath, "utf-8"));
3923
+ }
3924
+ const servers = config["mcpServers"] || {};
3925
+ if (opts.uninstall) {
3926
+ delete servers["mementos"];
3927
+ } else {
3928
+ servers["mementos"] = { command: mementosCmd, args: [] };
3929
+ }
3930
+ config["mcpServers"] = servers;
3931
+ writeFileSync(configPath, JSON.stringify(config, null, 2) + `
3932
+ `, "utf-8");
3933
+ console.log(chalk.green(`${opts.uninstall ? "Removed from" : "Installed into"} Gemini: ${configPath}`));
3934
+ }
3935
+ } catch (e) {
3936
+ console.error(chalk.red(`Failed for ${target}: ${e instanceof Error ? e.message : String(e)}`));
3937
+ }
3938
+ }
3939
+ });
3940
+ program2.command("watch").description("Watch for new and changed memories in real-time").option("-s, --scope <scope>", "Scope filter: global, shared, private").option("-c, --category <cat>", "Category filter: preference, fact, knowledge, history").option("--agent <name>", "Agent filter").option("--project <path>", "Project filter").option("--interval <ms>", "Poll interval in milliseconds", parseInt).action((opts) => {
3941
+ try {
3942
+ const globalOpts = program2.opts();
3943
+ const agentId = opts.agent || globalOpts.agent;
3944
+ const projectPath = opts.project || globalOpts.project;
3945
+ let projectId;
3946
+ if (projectPath) {
3947
+ const project = getProject(resolve3(projectPath));
3948
+ if (project)
3949
+ projectId = project.id;
3950
+ }
3951
+ const intervalMs = opts.interval || 500;
3952
+ console.log(chalk.bold.cyan("Watching memories...") + chalk.dim(" (Ctrl+C to stop)"));
3953
+ const filters = [];
3954
+ if (opts.scope)
3955
+ filters.push(`scope=${colorScope(opts.scope)}`);
3956
+ if (opts.category)
3957
+ filters.push(`category=${colorCategory(opts.category)}`);
3958
+ if (agentId)
3959
+ filters.push(`agent=${chalk.dim(agentId)}`);
3960
+ if (projectId)
3961
+ filters.push(`project=${chalk.dim(projectId)}`);
3962
+ if (filters.length > 0) {
3963
+ console.log(chalk.dim("Filters: ") + filters.join(chalk.dim(" | ")));
3964
+ }
3965
+ console.log(chalk.dim(`Poll interval: ${intervalMs}ms`));
3966
+ console.log();
3967
+ const filter = {
3968
+ scope: opts.scope,
3969
+ category: opts.category,
3970
+ agent_id: agentId,
3971
+ project_id: projectId,
3972
+ limit: 20
3973
+ };
3974
+ const recent = listMemories(filter);
3975
+ if (recent.length > 0) {
3976
+ console.log(chalk.bold.dim(`Recent (${recent.length}):`));
3977
+ for (const m of recent.reverse()) {
3978
+ console.log(formatWatchLine(m));
3979
+ }
3980
+ } else {
3981
+ console.log(chalk.dim("No recent memories."));
3982
+ }
3983
+ console.log(chalk.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 Live \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
3984
+ console.log();
3985
+ const { startPolling: startPolling2 } = (init_poll(), __toCommonJS(exports_poll));
3986
+ const handle = startPolling2({
3987
+ interval_ms: intervalMs,
3988
+ scope: opts.scope,
3989
+ category: opts.category,
3990
+ agent_id: agentId,
3991
+ project_id: projectId,
3992
+ on_memories: (memories) => {
3993
+ for (const m of memories) {
3994
+ console.log(formatWatchLine(m));
3995
+ sendNotification(m);
3996
+ }
3997
+ },
3998
+ on_error: (err) => {
3999
+ console.error(chalk.red(`Poll error: ${err.message}`));
4000
+ }
4001
+ });
4002
+ const cleanup = () => {
4003
+ handle.stop();
4004
+ console.log();
4005
+ console.log(chalk.dim("Stopped watching."));
4006
+ process.exit(0);
4007
+ };
4008
+ process.on("SIGINT", cleanup);
4009
+ process.on("SIGTERM", cleanup);
4010
+ } catch (e) {
4011
+ handleError(e);
4012
+ }
4013
+ });
4014
+ function formatWatchLine(m) {
4015
+ const scope = colorScope(m.scope);
4016
+ const cat = colorCategory(m.category);
4017
+ const imp = colorImportance(m.importance);
4018
+ const value = m.value.length > 100 ? m.value.slice(0, 100) + "..." : m.value;
4019
+ const main = ` [${scope}/${cat}] ${chalk.bold(m.key)} = ${value} ${chalk.dim(`(importance: ${imp})`)}`;
4020
+ const parts = [];
4021
+ if (m.tags.length > 0)
4022
+ parts.push(`Tags: ${m.tags.join(", ")}`);
4023
+ if (m.agent_id)
4024
+ parts.push(`Agent: ${m.agent_id}`);
4025
+ parts.push(`Updated: ${m.updated_at}`);
4026
+ const detail = chalk.dim(` ${parts.join(" | ")}`);
4027
+ return `${main}
4028
+ ${detail}`;
4029
+ }
4030
+ function sendNotification(m) {
4031
+ if (process.platform !== "darwin")
4032
+ return;
4033
+ try {
4034
+ const title = "Mementos";
4035
+ const msg = `[${m.scope}/${m.category}] ${m.key} = ${m.value.slice(0, 60)}`;
4036
+ const escaped = msg.replace(/"/g, "\\\"");
4037
+ const { execSync } = __require("child_process");
4038
+ execSync(`osascript -e 'display notification "${escaped}" with title "${title}"'`, { stdio: "ignore", timeout: 2000 });
4039
+ } catch {}
4040
+ }
3643
4041
  program2.parse(process.argv);
@@ -3,4 +3,10 @@ import type { Agent } from "../types/index.js";
3
3
  export declare function registerAgent(name: string, description?: string, role?: string, db?: Database): Agent;
4
4
  export declare function getAgent(idOrName: string, db?: Database): Agent | null;
5
5
  export declare function listAgents(db?: Database): Agent[];
6
+ export declare function updateAgent(id: string, updates: {
7
+ name?: string;
8
+ description?: string;
9
+ role?: string;
10
+ metadata?: Record<string, unknown>;
11
+ }, db?: Database): Agent | null;
6
12
  //# sourceMappingURL=agents.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/db/agents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAe/C,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,WAAW,CAAC,EAAE,MAAM,EACpB,IAAI,CAAC,EAAE,MAAM,EACb,EAAE,CAAC,EAAE,QAAQ,GACZ,KAAK,CAqCP;AAED,wBAAgB,QAAQ,CACtB,QAAQ,EAAE,MAAM,EAChB,EAAE,CAAC,EAAE,QAAQ,GACZ,KAAK,GAAG,IAAI,CAsBd;AAED,wBAAgB,UAAU,CAAC,EAAE,CAAC,EAAE,QAAQ,GAAG,KAAK,EAAE,CAMjD"}
1
+ {"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/db/agents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAe/C,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,WAAW,CAAC,EAAE,MAAM,EACpB,IAAI,CAAC,EAAE,MAAM,EACb,EAAE,CAAC,EAAE,QAAQ,GACZ,KAAK,CAqCP;AAED,wBAAgB,QAAQ,CACtB,QAAQ,EAAE,MAAM,EAChB,EAAE,CAAC,EAAE,QAAQ,GACZ,KAAK,GAAG,IAAI,CAsBd;AAED,wBAAgB,UAAU,CAAC,EAAE,CAAC,EAAE,QAAQ,GAAG,KAAK,EAAE,CAMjD;AAED,wBAAgB,WAAW,CACzB,EAAE,EAAE,MAAM,EACV,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,EACnG,EAAE,CAAC,EAAE,QAAQ,GACZ,KAAK,GAAG,IAAI,CAkCd"}
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ export type { Memory, MemoryWithRelations, MemoryScope, MemoryCategory, MemorySo
2
2
  export { MemoryNotFoundError, DuplicateMemoryError, MemoryExpiredError, InvalidScopeError, VersionConflictError, } from "./types/index.js";
3
3
  export { getDatabase, closeDatabase, resetDatabase, getDbPath, resolvePartialId, now, uuid, shortUuid, } from "./db/database.js";
4
4
  export { createMemory, getMemory, getMemoryByKey, listMemories, updateMemory, deleteMemory, bulkDeleteMemories, touchMemory, cleanExpiredMemories, } from "./db/memories.js";
5
- export { registerAgent, getAgent, listAgents, } from "./db/agents.js";
5
+ export { registerAgent, getAgent, listAgents, updateAgent, } from "./db/agents.js";
6
6
  export { registerProject, getProject, listProjects, } from "./db/projects.js";
7
7
  export { searchMemories } from "./lib/search.js";
8
8
  export { loadConfig, DEFAULT_CONFIG } from "./lib/config.js";