@hasna/mementos 0.11.1 → 0.14.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.
Files changed (95) hide show
  1. package/dashboard/dist/assets/index-DqyMbv89.js +270 -0
  2. package/dashboard/dist/assets/index-UBCddFo_.css +1 -0
  3. package/dashboard/dist/index.html +2 -2
  4. package/dist/cli/brains.d.ts +3 -0
  5. package/dist/cli/brains.d.ts.map +1 -0
  6. package/dist/cli/index.js +2093 -512
  7. package/dist/db/database.d.ts.map +1 -1
  8. package/dist/db/memories.d.ts.map +1 -1
  9. package/dist/db/tool-events.d.ts +27 -0
  10. package/dist/db/tool-events.d.ts.map +1 -0
  11. package/dist/index.d.ts +2 -0
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +177 -5
  14. package/dist/lib/activation-matcher.d.ts +16 -0
  15. package/dist/lib/activation-matcher.d.ts.map +1 -0
  16. package/dist/lib/asmr/categorizer.d.ts +31 -0
  17. package/dist/lib/asmr/categorizer.d.ts.map +1 -0
  18. package/dist/lib/asmr/context-agent.d.ts +4 -0
  19. package/dist/lib/asmr/context-agent.d.ts.map +1 -0
  20. package/dist/lib/asmr/ensemble.d.ts +23 -0
  21. package/dist/lib/asmr/ensemble.d.ts.map +1 -0
  22. package/dist/lib/asmr/fact-agent.d.ts +4 -0
  23. package/dist/lib/asmr/fact-agent.d.ts.map +1 -0
  24. package/dist/lib/asmr/index.d.ts +7 -0
  25. package/dist/lib/asmr/index.d.ts.map +1 -0
  26. package/dist/lib/asmr/orchestrator.d.ts +4 -0
  27. package/dist/lib/asmr/orchestrator.d.ts.map +1 -0
  28. package/dist/lib/asmr/temporal-agent.d.ts +4 -0
  29. package/dist/lib/asmr/temporal-agent.d.ts.map +1 -0
  30. package/dist/lib/asmr/types.d.ts +27 -0
  31. package/dist/lib/asmr/types.d.ts.map +1 -0
  32. package/dist/lib/auto-inject-orchestrator.d.ts +57 -0
  33. package/dist/lib/auto-inject-orchestrator.d.ts.map +1 -0
  34. package/dist/lib/built-in-hooks.d.ts.map +1 -1
  35. package/dist/lib/channel-pusher.d.ts +39 -0
  36. package/dist/lib/channel-pusher.d.ts.map +1 -0
  37. package/dist/lib/connectors/files.d.ts +8 -0
  38. package/dist/lib/connectors/files.d.ts.map +1 -0
  39. package/dist/lib/connectors/github.d.ts +7 -0
  40. package/dist/lib/connectors/github.d.ts.map +1 -0
  41. package/dist/lib/connectors/index.d.ts +12 -0
  42. package/dist/lib/connectors/index.d.ts.map +1 -0
  43. package/dist/lib/connectors/notion.d.ts +7 -0
  44. package/dist/lib/connectors/notion.d.ts.map +1 -0
  45. package/dist/lib/connectors/types.d.ts +27 -0
  46. package/dist/lib/connectors/types.d.ts.map +1 -0
  47. package/dist/lib/context-extractor.d.ts +14 -0
  48. package/dist/lib/context-extractor.d.ts.map +1 -0
  49. package/dist/lib/extractors/audio.d.ts +8 -0
  50. package/dist/lib/extractors/audio.d.ts.map +1 -0
  51. package/dist/lib/extractors/index.d.ts +12 -0
  52. package/dist/lib/extractors/index.d.ts.map +1 -0
  53. package/dist/lib/extractors/ocr.d.ts +7 -0
  54. package/dist/lib/extractors/ocr.d.ts.map +1 -0
  55. package/dist/lib/extractors/pdf.d.ts +7 -0
  56. package/dist/lib/extractors/pdf.d.ts.map +1 -0
  57. package/dist/lib/extractors/types.d.ts +12 -0
  58. package/dist/lib/extractors/types.d.ts.map +1 -0
  59. package/dist/lib/gatherer.d.ts +16 -0
  60. package/dist/lib/gatherer.d.ts.map +1 -0
  61. package/dist/lib/injector.d.ts +48 -1
  62. package/dist/lib/injector.d.ts.map +1 -1
  63. package/dist/lib/matryoshka.d.ts +50 -0
  64. package/dist/lib/matryoshka.d.ts.map +1 -0
  65. package/dist/lib/model-config.d.ts +14 -0
  66. package/dist/lib/model-config.d.ts.map +1 -0
  67. package/dist/lib/procedural-extractor.d.ts +21 -0
  68. package/dist/lib/procedural-extractor.d.ts.map +1 -0
  69. package/dist/lib/profile-synthesizer.d.ts +20 -0
  70. package/dist/lib/profile-synthesizer.d.ts.map +1 -0
  71. package/dist/lib/session-processor.d.ts.map +1 -1
  72. package/dist/lib/session-registry.d.ts +47 -0
  73. package/dist/lib/session-registry.d.ts.map +1 -0
  74. package/dist/lib/session-start-briefing.d.ts +10 -0
  75. package/dist/lib/session-start-briefing.d.ts.map +1 -0
  76. package/dist/lib/session-watcher.d.ts +30 -0
  77. package/dist/lib/session-watcher.d.ts.map +1 -0
  78. package/dist/lib/tool-lesson-extractor.d.ts +24 -0
  79. package/dist/lib/tool-lesson-extractor.d.ts.map +1 -0
  80. package/dist/lib/tool-memory-synthesizer.d.ts +28 -0
  81. package/dist/lib/tool-memory-synthesizer.d.ts.map +1 -0
  82. package/dist/lib/topic-clusterer.d.ts +21 -0
  83. package/dist/lib/topic-clusterer.d.ts.map +1 -0
  84. package/dist/lib/when-to-use-generator.d.ts +22 -0
  85. package/dist/lib/when-to-use-generator.d.ts.map +1 -0
  86. package/dist/mcp/index.d.ts +3 -1
  87. package/dist/mcp/index.d.ts.map +1 -1
  88. package/dist/mcp/index.js +3825 -382
  89. package/dist/server/index.d.ts.map +1 -1
  90. package/dist/server/index.js +883 -18
  91. package/dist/types/index.d.ts +57 -0
  92. package/dist/types/index.d.ts.map +1 -1
  93. package/package.json +4 -1
  94. package/dashboard/dist/assets/index-B1yiOEw3.js +0 -290
  95. package/dashboard/dist/assets/index-DnpbasSl.css +0 -1
package/dist/cli/index.js CHANGED
@@ -6,39 +6,60 @@ var __defProp = Object.defineProperty;
6
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
7
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
8
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ function __accessProp(key) {
10
+ return this[key];
11
+ }
12
+ var __toESMCache_node;
13
+ var __toESMCache_esm;
9
14
  var __toESM = (mod, isNodeMode, target) => {
15
+ var canCache = mod != null && typeof mod === "object";
16
+ if (canCache) {
17
+ var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
18
+ var cached = cache.get(mod);
19
+ if (cached)
20
+ return cached;
21
+ }
10
22
  target = mod != null ? __create(__getProtoOf(mod)) : {};
11
23
  const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
12
24
  for (let key of __getOwnPropNames(mod))
13
25
  if (!__hasOwnProp.call(to, key))
14
26
  __defProp(to, key, {
15
- get: () => mod[key],
27
+ get: __accessProp.bind(mod, key),
16
28
  enumerable: true
17
29
  });
30
+ if (canCache)
31
+ cache.set(mod, to);
18
32
  return to;
19
33
  };
20
- var __moduleCache = /* @__PURE__ */ new WeakMap;
21
34
  var __toCommonJS = (from) => {
22
- var entry = __moduleCache.get(from), desc;
35
+ var entry = (__moduleCache ??= new WeakMap).get(from), desc;
23
36
  if (entry)
24
37
  return entry;
25
38
  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
- }));
39
+ if (from && typeof from === "object" || typeof from === "function") {
40
+ for (var key of __getOwnPropNames(from))
41
+ if (!__hasOwnProp.call(entry, key))
42
+ __defProp(entry, key, {
43
+ get: __accessProp.bind(from, key),
44
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
45
+ });
46
+ }
31
47
  __moduleCache.set(from, entry);
32
48
  return entry;
33
49
  };
50
+ var __moduleCache;
34
51
  var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
52
+ var __returnValue = (v) => v;
53
+ function __exportSetter(name, newValue) {
54
+ this[name] = __returnValue.bind(null, newValue);
55
+ }
35
56
  var __export = (target, all) => {
36
57
  for (var name in all)
37
58
  __defProp(target, name, {
38
59
  get: all[name],
39
60
  enumerable: true,
40
61
  configurable: true,
41
- set: (newValue) => all[name] = () => newValue
62
+ set: __exportSetter.bind(all, name)
42
63
  });
43
64
  };
44
65
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
@@ -2909,6 +2930,44 @@ CREATE INDEX IF NOT EXISTS idx_memory_embeddings_model ON memory_embeddings(mode
2909
2930
 
2910
2931
  PRAGMA foreign_keys = ON;
2911
2932
  INSERT OR IGNORE INTO _migrations (id) VALUES (29);
2933
+ `,
2934
+ `
2935
+ ALTER TABLE memories ADD COLUMN when_to_use TEXT DEFAULT NULL;
2936
+ CREATE INDEX IF NOT EXISTS idx_memories_when_to_use ON memories(when_to_use) WHERE when_to_use IS NOT NULL;
2937
+ ALTER TABLE memory_versions ADD COLUMN when_to_use TEXT;
2938
+ INSERT OR IGNORE INTO _migrations (id) VALUES (30);
2939
+ `,
2940
+ `
2941
+ CREATE TABLE IF NOT EXISTS tool_events (
2942
+ id TEXT PRIMARY KEY,
2943
+ tool_name TEXT NOT NULL,
2944
+ action TEXT,
2945
+ success INTEGER NOT NULL DEFAULT 1,
2946
+ error_type TEXT CHECK(error_type IS NULL OR error_type IN ('timeout', 'permission', 'not_found', 'syntax', 'rate_limit', 'other')),
2947
+ error_message TEXT,
2948
+ tokens_used INTEGER,
2949
+ latency_ms INTEGER,
2950
+ context TEXT,
2951
+ lesson TEXT,
2952
+ when_to_use TEXT,
2953
+ agent_id TEXT REFERENCES agents(id) ON DELETE SET NULL,
2954
+ project_id TEXT REFERENCES projects(id) ON DELETE SET NULL,
2955
+ session_id TEXT,
2956
+ metadata TEXT DEFAULT '{}',
2957
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
2958
+ );
2959
+ CREATE INDEX IF NOT EXISTS idx_tool_events_tool_name ON tool_events(tool_name);
2960
+ CREATE INDEX IF NOT EXISTS idx_tool_events_agent ON tool_events(agent_id);
2961
+ CREATE INDEX IF NOT EXISTS idx_tool_events_project ON tool_events(project_id);
2962
+ CREATE INDEX IF NOT EXISTS idx_tool_events_success ON tool_events(success);
2963
+ CREATE INDEX IF NOT EXISTS idx_tool_events_created ON tool_events(created_at);
2964
+ INSERT OR IGNORE INTO _migrations (id) VALUES (31);
2965
+ `,
2966
+ `
2967
+ ALTER TABLE memories ADD COLUMN sequence_group TEXT DEFAULT NULL;
2968
+ ALTER TABLE memories ADD COLUMN sequence_order INTEGER DEFAULT NULL;
2969
+ CREATE INDEX IF NOT EXISTS idx_memories_sequence_group ON memories(sequence_group) WHERE sequence_group IS NOT NULL;
2970
+ INSERT OR IGNORE INTO _migrations (id) VALUES (32);
2912
2971
  `
2913
2972
  ];
2914
2973
  });
@@ -3317,6 +3376,9 @@ function parseMemoryRow(row) {
3317
3376
  session_id: row["session_id"] || null,
3318
3377
  machine_id: row["machine_id"] || null,
3319
3378
  flag: row["flag"] || null,
3379
+ when_to_use: row["when_to_use"] || null,
3380
+ sequence_group: row["sequence_group"] || null,
3381
+ sequence_order: row["sequence_order"] ?? null,
3320
3382
  content_type: row["content_type"] || "text",
3321
3383
  namespace: row["namespace"] || null,
3322
3384
  created_by_agent: row["created_by_agent"] || null,
@@ -3375,6 +3437,7 @@ function createMemory(input, dedupeMode = "merge", db) {
3375
3437
  d.run(`UPDATE memories SET
3376
3438
  value = ?, category = ?, summary = ?, tags = ?,
3377
3439
  importance = ?, metadata = ?, expires_at = ?,
3440
+ when_to_use = ?,
3378
3441
  pinned = COALESCE(pinned, 0),
3379
3442
  version = version + 1, updated_at = ?
3380
3443
  WHERE id = ?`, [
@@ -3385,6 +3448,7 @@ function createMemory(input, dedupeMode = "merge", db) {
3385
3448
  input.importance ?? 5,
3386
3449
  metadataJson,
3387
3450
  expiresAt,
3451
+ input.when_to_use || null,
3388
3452
  timestamp,
3389
3453
  existing.id
3390
3454
  ]);
@@ -3409,8 +3473,8 @@ function createMemory(input, dedupeMode = "merge", db) {
3409
3473
  return merged;
3410
3474
  }
3411
3475
  }
3412
- d.run(`INSERT INTO memories (id, key, value, category, scope, summary, tags, importance, source, status, pinned, agent_id, project_id, session_id, machine_id, namespace, created_by_agent, metadata, access_count, version, expires_at, valid_from, valid_until, ingested_at, created_at, updated_at)
3413
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 'active', 0, ?, ?, ?, ?, ?, ?, ?, 0, 1, ?, ?, ?, ?, ?, ?)`, [
3476
+ d.run(`INSERT INTO memories (id, key, value, category, scope, summary, tags, importance, source, status, pinned, agent_id, project_id, session_id, machine_id, namespace, created_by_agent, when_to_use, sequence_group, sequence_order, metadata, access_count, version, expires_at, valid_from, valid_until, ingested_at, created_at, updated_at)
3477
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 'active', 0, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, 1, ?, ?, ?, ?, ?, ?)`, [
3414
3478
  id,
3415
3479
  input.key,
3416
3480
  input.value,
@@ -3426,6 +3490,9 @@ function createMemory(input, dedupeMode = "merge", db) {
3426
3490
  input.machine_id || null,
3427
3491
  input.namespace || null,
3428
3492
  input.agent_id || null,
3493
+ input.when_to_use || null,
3494
+ input.sequence_group || null,
3495
+ input.sequence_order ?? null,
3429
3496
  metadataJson,
3430
3497
  expiresAt,
3431
3498
  input.metadata?.valid_from ?? timestamp,
@@ -3636,8 +3703,8 @@ function updateMemory(id, input, db) {
3636
3703
  throw new VersionConflictError(id, input.version, existing.version);
3637
3704
  }
3638
3705
  try {
3639
- d.run(`INSERT OR IGNORE INTO memory_versions (id, memory_id, version, value, importance, scope, category, tags, summary, pinned, status, created_at)
3640
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
3706
+ d.run(`INSERT OR IGNORE INTO memory_versions (id, memory_id, version, value, importance, scope, category, tags, summary, pinned, status, when_to_use, created_at)
3707
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
3641
3708
  uuid(),
3642
3709
  existing.id,
3643
3710
  existing.version,
@@ -3649,6 +3716,7 @@ function updateMemory(id, input, db) {
3649
3716
  existing.summary,
3650
3717
  existing.pinned ? 1 : 0,
3651
3718
  existing.status,
3719
+ existing.when_to_use || null,
3652
3720
  existing.updated_at
3653
3721
  ]);
3654
3722
  } catch {}
@@ -3694,6 +3762,10 @@ function updateMemory(id, input, db) {
3694
3762
  sets.push("flag = ?");
3695
3763
  params.push(input.flag ?? null);
3696
3764
  }
3765
+ if (input.when_to_use !== undefined) {
3766
+ sets.push("when_to_use = ?");
3767
+ params.push(input.when_to_use ?? null);
3768
+ }
3697
3769
  if (input.tags !== undefined) {
3698
3770
  sets.push("tags = ?");
3699
3771
  params.push(JSON.stringify(input.tags));
@@ -5965,6 +6037,311 @@ var init_synthesis = __esm(() => {
5965
6037
  init_database();
5966
6038
  });
5967
6039
 
6040
+ // src/lib/when-to-use-generator.ts
6041
+ var exports_when_to_use_generator = {};
6042
+ __export(exports_when_to_use_generator, {
6043
+ generateWhenToUse: () => generateWhenToUse,
6044
+ autoGenerateWhenToUse: () => autoGenerateWhenToUse
6045
+ });
6046
+ async function generateWhenToUse(key, value, category, tags) {
6047
+ if (process.env["MEMENTOS_AUTO_WHEN_TO_USE"] !== "true")
6048
+ return null;
6049
+ const apiKey = process.env["ANTHROPIC_API_KEY"];
6050
+ if (!apiKey)
6051
+ return null;
6052
+ try {
6053
+ const userMessage = `Key: "${key}"
6054
+ Value: "${value}"
6055
+ Category: ${category}
6056
+ Tags: ${tags.join(", ") || "none"}
6057
+
6058
+ Generate the when_to_use activation context (1-2 sentences):`;
6059
+ const response = await fetch("https://api.anthropic.com/v1/messages", {
6060
+ method: "POST",
6061
+ headers: {
6062
+ "x-api-key": apiKey,
6063
+ "anthropic-version": "2023-06-01",
6064
+ "content-type": "application/json"
6065
+ },
6066
+ body: JSON.stringify({
6067
+ model: "claude-haiku-4-5-20251001",
6068
+ max_tokens: 150,
6069
+ system: SYSTEM_PROMPT2,
6070
+ messages: [{ role: "user", content: userMessage }]
6071
+ })
6072
+ });
6073
+ if (!response.ok)
6074
+ return null;
6075
+ const data = await response.json();
6076
+ const text = data.content?.[0]?.text?.trim();
6077
+ return text || null;
6078
+ } catch {
6079
+ return null;
6080
+ }
6081
+ }
6082
+ async function autoGenerateWhenToUse(ctx) {
6083
+ if (ctx.memory.when_to_use)
6084
+ return;
6085
+ if (process.env["MEMENTOS_AUTO_WHEN_TO_USE"] !== "true")
6086
+ return;
6087
+ try {
6088
+ const whenToUse = await generateWhenToUse(ctx.memory.key, ctx.memory.value, ctx.memory.category, ctx.memory.tags);
6089
+ if (whenToUse) {
6090
+ const db = getDatabase();
6091
+ db.run("UPDATE memories SET when_to_use = ? WHERE id = ? AND when_to_use IS NULL", [whenToUse, ctx.memory.id]);
6092
+ }
6093
+ } catch {}
6094
+ }
6095
+ var SYSTEM_PROMPT2 = `You generate activation contexts for memory records. Given a memory's key, value, category, and tags, output a 1-2 sentence "when to use" description that describes the SITUATION or CONDITION under which an AI agent should retrieve this memory.
6096
+
6097
+ Rules:
6098
+ - Start with "When" or "If"
6099
+ - Describe the situation, not the content
6100
+ - Be specific enough to avoid false matches but general enough to catch relevant scenarios
6101
+ - Focus on the task/action the agent would be doing, not what the memory contains
6102
+
6103
+ Examples:
6104
+ - Key: "preferred-language", Value: "Always use TypeScript, never JavaScript" \u2192 "When choosing a programming language for a new file or project"
6105
+ - Key: "db-migration-order", Value: "Always run migrations before deploying" \u2192 "When deploying or updating database schema"
6106
+ - Key: "bash-chain-bug", Value: "Bash tool mangles && chains" \u2192 "When chaining commands with && in the Bash tool"`;
6107
+ var init_when_to_use_generator = __esm(() => {
6108
+ init_database();
6109
+ });
6110
+
6111
+ // src/lib/profile-synthesizer.ts
6112
+ var exports_profile_synthesizer = {};
6113
+ __export(exports_profile_synthesizer, {
6114
+ synthesizeProfile: () => synthesizeProfile,
6115
+ markProfileStale: () => markProfileStale,
6116
+ getProfileKey: () => getProfileKey
6117
+ });
6118
+ function getProfileKey(scope, id) {
6119
+ return `_profile_${scope}_${id}`;
6120
+ }
6121
+ async function synthesizeProfile(options) {
6122
+ const scope = options.scope || (options.project_id ? "project" : options.agent_id ? "agent" : "global");
6123
+ const id = options.project_id || options.agent_id || "global";
6124
+ const profileKey = getProfileKey(scope, id);
6125
+ if (!options.force_refresh) {
6126
+ const cached = getMemoryByKey(profileKey, "shared", undefined, options.project_id);
6127
+ if (cached) {
6128
+ const age = Date.now() - new Date(cached.updated_at).getTime();
6129
+ const maxAge = 24 * 60 * 60 * 1000;
6130
+ const isStale = cached.metadata?.stale === true;
6131
+ if (age < maxAge && !isStale) {
6132
+ return { profile: cached.value, memory_count: 0, from_cache: true };
6133
+ }
6134
+ }
6135
+ }
6136
+ const prefMemories = listMemories({
6137
+ category: "preference",
6138
+ project_id: options.project_id,
6139
+ status: "active",
6140
+ limit: 30
6141
+ });
6142
+ const factMemories = listMemories({
6143
+ category: "fact",
6144
+ project_id: options.project_id,
6145
+ status: "active",
6146
+ limit: 30
6147
+ });
6148
+ const allMemories = [...prefMemories, ...factMemories];
6149
+ if (allMemories.length === 0)
6150
+ return null;
6151
+ const apiKey = process.env["ANTHROPIC_API_KEY"];
6152
+ if (!apiKey) {
6153
+ const lines = allMemories.map((m) => `- ${m.key}: ${m.value}`).join(`
6154
+ `);
6155
+ const fallbackProfile = `## Profile
6156
+ ${lines}`;
6157
+ saveProfile(profileKey, fallbackProfile, allMemories.length, options);
6158
+ return { profile: fallbackProfile, memory_count: allMemories.length, from_cache: false };
6159
+ }
6160
+ try {
6161
+ const memoryList = allMemories.sort((a, b) => b.importance - a.importance).map((m) => `[${m.category}] ${m.key}: ${m.value}`).join(`
6162
+ `);
6163
+ const response = await fetch("https://api.anthropic.com/v1/messages", {
6164
+ method: "POST",
6165
+ headers: {
6166
+ "x-api-key": apiKey,
6167
+ "anthropic-version": "2023-06-01",
6168
+ "content-type": "application/json"
6169
+ },
6170
+ body: JSON.stringify({
6171
+ model: "claude-haiku-4-5-20251001",
6172
+ max_tokens: 500,
6173
+ system: PROFILE_PROMPT,
6174
+ messages: [{ role: "user", content: `Synthesize a profile from these ${allMemories.length} memories:
6175
+
6176
+ ${memoryList}` }]
6177
+ })
6178
+ });
6179
+ if (!response.ok)
6180
+ return null;
6181
+ const data = await response.json();
6182
+ const profile = data.content?.[0]?.text?.trim();
6183
+ if (!profile)
6184
+ return null;
6185
+ saveProfile(profileKey, profile, allMemories.length, options);
6186
+ return { profile, memory_count: allMemories.length, from_cache: false };
6187
+ } catch {
6188
+ return null;
6189
+ }
6190
+ }
6191
+ function saveProfile(key, value, memoryCount, options) {
6192
+ try {
6193
+ createMemory({
6194
+ key,
6195
+ value,
6196
+ category: "fact",
6197
+ scope: "shared",
6198
+ importance: 10,
6199
+ source: "auto",
6200
+ tags: ["profile", "synthesized"],
6201
+ when_to_use: "When needing to understand this agent's or project's preferences, style, and conventions",
6202
+ metadata: { memory_count: memoryCount, synthesized_at: new Date().toISOString(), stale: false },
6203
+ agent_id: options.agent_id,
6204
+ project_id: options.project_id
6205
+ });
6206
+ } catch {}
6207
+ }
6208
+ function markProfileStale(projectId, _agentId) {
6209
+ try {
6210
+ const { getDatabase: getDatabase2 } = (init_database(), __toCommonJS(exports_database));
6211
+ const db = getDatabase2();
6212
+ db.run(`UPDATE memories SET metadata = json_set(COALESCE(metadata, '{}'), '$.stale', json('true'))
6213
+ WHERE key LIKE '_profile_%' AND COALESCE(project_id, '') = ?`, [projectId || ""]);
6214
+ } catch {}
6215
+ }
6216
+ var PROFILE_PROMPT = `You synthesize a coherent agent/project profile from individual preference and fact memories.
6217
+
6218
+ Output a concise profile (200-300 words max) organized by:
6219
+ - **Stack & Tools**: Languages, frameworks, package managers, etc.
6220
+ - **Code Style**: Formatting, patterns, naming conventions
6221
+ - **Workflow**: Testing, deployment, git practices
6222
+ - **Communication**: Response style, verbosity, formatting preferences
6223
+ - **Key Facts**: Architecture decisions, constraints, team conventions
6224
+
6225
+ Only include sections that have relevant data. Be specific and actionable.
6226
+ Output in markdown format.`;
6227
+ var init_profile_synthesizer = __esm(() => {
6228
+ init_memories();
6229
+ });
6230
+
6231
+ // src/lib/contradiction.ts
6232
+ var exports_contradiction = {};
6233
+ __export(exports_contradiction, {
6234
+ invalidateFact: () => invalidateFact,
6235
+ detectContradiction: () => detectContradiction
6236
+ });
6237
+ function invalidateFact(oldMemoryId, newMemoryId, db) {
6238
+ const d = db || getDatabase();
6239
+ const timestamp = now();
6240
+ d.run("UPDATE memories SET valid_until = ?, updated_at = ? WHERE id = ?", [timestamp, timestamp, oldMemoryId]);
6241
+ if (newMemoryId) {
6242
+ const row = d.query("SELECT metadata FROM memories WHERE id = ?").get(newMemoryId);
6243
+ if (row) {
6244
+ const metadata = JSON.parse(row.metadata || "{}");
6245
+ metadata.supersedes_id = oldMemoryId;
6246
+ d.run("UPDATE memories SET metadata = ?, updated_at = ? WHERE id = ?", [JSON.stringify(metadata), timestamp, newMemoryId]);
6247
+ }
6248
+ }
6249
+ return {
6250
+ invalidated_memory_id: oldMemoryId,
6251
+ new_memory_id: newMemoryId || null,
6252
+ valid_until: timestamp,
6253
+ supersedes_id: oldMemoryId
6254
+ };
6255
+ }
6256
+ function heuristicContradictionScore(newValue, existingValue, newKey, existingKey) {
6257
+ if (newKey !== existingKey)
6258
+ return 0;
6259
+ const newLower = newValue.toLowerCase().trim();
6260
+ const existingLower = existingValue.toLowerCase().trim();
6261
+ if (newLower === existingLower)
6262
+ return 0;
6263
+ const newWords = new Set(newLower.split(/\s+/));
6264
+ const existingWords = new Set(existingLower.split(/\s+/));
6265
+ let overlap = 0;
6266
+ for (const w of newWords) {
6267
+ if (existingWords.has(w))
6268
+ overlap++;
6269
+ }
6270
+ const totalUnique = new Set([...newWords, ...existingWords]).size;
6271
+ const overlapRatio = totalUnique > 0 ? overlap / totalUnique : 0;
6272
+ if (overlapRatio < 0.3)
6273
+ return 0.7;
6274
+ if (overlapRatio < 0.5)
6275
+ return 0.4;
6276
+ return 0.1;
6277
+ }
6278
+ async function llmContradictionCheck(_newValue, _existingValue, _key) {
6279
+ const provider = providerRegistry.getAvailable();
6280
+ if (!provider) {
6281
+ return { contradicts: false, confidence: 0, reasoning: "No LLM provider available" };
6282
+ }
6283
+ try {
6284
+ return { contradicts: false, confidence: 0, reasoning: "LLM check skipped \u2014 using heuristic only" };
6285
+ } catch {
6286
+ return { contradicts: false, confidence: 0, reasoning: "LLM check failed" };
6287
+ }
6288
+ }
6289
+ async function detectContradiction(newKey, newValue, options = {}, db) {
6290
+ const d = db || getDatabase();
6291
+ const { scope, project_id, min_importance = 7, use_llm = false } = options;
6292
+ const conditions = ["key = ?", "status = 'active'", "importance >= ?"];
6293
+ const params = [newKey, min_importance];
6294
+ if (scope) {
6295
+ conditions.push("scope = ?");
6296
+ params.push(scope);
6297
+ }
6298
+ if (project_id) {
6299
+ conditions.push("project_id = ?");
6300
+ params.push(project_id);
6301
+ }
6302
+ conditions.push("(valid_until IS NULL OR valid_until > datetime('now'))");
6303
+ const sql = `SELECT * FROM memories WHERE ${conditions.join(" AND ")} ORDER BY importance DESC LIMIT 10`;
6304
+ const rows = d.query(sql).all(...params);
6305
+ if (rows.length === 0) {
6306
+ return { contradicts: false, conflicting_memory: null, confidence: 0, reasoning: "No existing memories with this key" };
6307
+ }
6308
+ let bestContradiction = {
6309
+ contradicts: false,
6310
+ conflicting_memory: null,
6311
+ confidence: 0,
6312
+ reasoning: "No contradiction detected"
6313
+ };
6314
+ for (const row of rows) {
6315
+ const existing = parseMemoryRow(row);
6316
+ const heuristicScore = heuristicContradictionScore(newValue, existing.value, newKey, existing.key);
6317
+ if (heuristicScore > bestContradiction.confidence) {
6318
+ bestContradiction = {
6319
+ contradicts: heuristicScore >= 0.5,
6320
+ conflicting_memory: existing,
6321
+ confidence: heuristicScore,
6322
+ reasoning: heuristicScore >= 0.7 ? `New value for "${newKey}" significantly differs from existing high-importance memory (importance ${existing.importance})` : heuristicScore >= 0.5 ? `New value for "${newKey}" partially conflicts with existing memory (importance ${existing.importance})` : `Minor difference detected for "${newKey}"`
6323
+ };
6324
+ }
6325
+ }
6326
+ if (use_llm && bestContradiction.confidence >= 0.3 && bestContradiction.confidence < 0.7 && bestContradiction.conflicting_memory) {
6327
+ const llmResult = await llmContradictionCheck(newValue, bestContradiction.conflicting_memory.value, newKey);
6328
+ if (llmResult.confidence > bestContradiction.confidence) {
6329
+ bestContradiction = {
6330
+ ...bestContradiction,
6331
+ contradicts: llmResult.contradicts,
6332
+ confidence: llmResult.confidence,
6333
+ reasoning: llmResult.reasoning
6334
+ };
6335
+ }
6336
+ }
6337
+ return bestContradiction;
6338
+ }
6339
+ var init_contradiction = __esm(() => {
6340
+ init_database();
6341
+ init_memories();
6342
+ init_registry();
6343
+ });
6344
+
5968
6345
  // src/lib/built-in-hooks.ts
5969
6346
  var exports_built_in_hooks = {};
5970
6347
  __export(exports_built_in_hooks, {
@@ -6091,10 +6468,76 @@ var init_built_in_hooks = __esm(() => {
6091
6468
  description: "Generate and store vector embedding for semantic memory search",
6092
6469
  handler: async (ctx) => {
6093
6470
  const { indexMemoryEmbedding: indexMemoryEmbedding2 } = await Promise.resolve().then(() => (init_memories(), exports_memories));
6094
- const text = [ctx.memory.value, ctx.memory.summary].filter(Boolean).join(" ");
6471
+ const text = ctx.memory.when_to_use || [ctx.memory.value, ctx.memory.summary].filter(Boolean).join(" ");
6095
6472
  indexMemoryEmbedding2(ctx.memory.id, text);
6096
6473
  }
6097
6474
  });
6475
+ hookRegistry.register({
6476
+ type: "PostMemorySave",
6477
+ blocking: false,
6478
+ builtin: true,
6479
+ priority: 60,
6480
+ description: "Auto-generate when_to_use activation context via LLM if missing",
6481
+ handler: async (ctx) => {
6482
+ const { autoGenerateWhenToUse: autoGenerateWhenToUse2 } = await Promise.resolve().then(() => (init_when_to_use_generator(), exports_when_to_use_generator));
6483
+ await autoGenerateWhenToUse2(ctx);
6484
+ }
6485
+ });
6486
+ hookRegistry.register({
6487
+ type: "PostMemorySave",
6488
+ blocking: false,
6489
+ builtin: true,
6490
+ priority: 65,
6491
+ description: "Mark synthesized profile as stale when a preference or fact memory is saved",
6492
+ handler: async (ctx) => {
6493
+ const category = ctx.memory?.category;
6494
+ if (category !== "preference" && category !== "fact")
6495
+ return;
6496
+ try {
6497
+ const { markProfileStale: markProfileStale2 } = await Promise.resolve().then(() => (init_profile_synthesizer(), exports_profile_synthesizer));
6498
+ markProfileStale2(ctx.projectId, ctx.agentId);
6499
+ } catch {}
6500
+ }
6501
+ });
6502
+ hookRegistry.register({
6503
+ type: "PostMemorySave",
6504
+ blocking: false,
6505
+ builtin: true,
6506
+ priority: 70,
6507
+ description: "Auto-decay importance of existing memories contradicted by the newly saved memory",
6508
+ handler: async (ctx) => {
6509
+ if (ctx.wasUpdated)
6510
+ return;
6511
+ const memory = ctx.memory;
6512
+ if (memory.category !== "fact" && memory.category !== "knowledge")
6513
+ return;
6514
+ try {
6515
+ const { detectContradiction: detectContradiction2 } = await Promise.resolve().then(() => (init_contradiction(), exports_contradiction));
6516
+ const { updateMemory: updateMemory2, getMemory: getMemory2 } = await Promise.resolve().then(() => (init_memories(), exports_memories));
6517
+ const result = await detectContradiction2(memory.key, memory.value, {
6518
+ scope: memory.scope,
6519
+ project_id: ctx.projectId,
6520
+ min_importance: 1
6521
+ });
6522
+ if (!result.contradicts || !result.conflicting_memory)
6523
+ return;
6524
+ const conflicting = result.conflicting_memory;
6525
+ if (conflicting.id === memory.id)
6526
+ return;
6527
+ const fresh = getMemory2(conflicting.id);
6528
+ if (!fresh || fresh.status !== "active")
6529
+ return;
6530
+ const halvedImportance = Math.max(1, Math.floor(fresh.importance / 2));
6531
+ const metadata = { ...fresh.metadata || {}, contradicted_by: memory.id };
6532
+ updateMemory2(fresh.id, {
6533
+ importance: halvedImportance,
6534
+ flag: "contradicted",
6535
+ metadata,
6536
+ version: fresh.version
6537
+ });
6538
+ } catch {}
6539
+ }
6540
+ });
6098
6541
  hookRegistry.register({
6099
6542
  type: "PostMemoryInject",
6100
6543
  blocking: false,
@@ -7163,40 +7606,413 @@ var init_session_jobs = __esm(() => {
7163
7606
  init_database();
7164
7607
  });
7165
7608
 
7166
- // src/lib/session-processor.ts
7167
- function chunkTranscript(transcript, chunkSize = 2000, overlap = 200) {
7168
- if (!transcript || transcript.length === 0)
7169
- return [];
7170
- if (transcript.length <= chunkSize)
7171
- return [transcript];
7172
- const chunks = [];
7173
- let start = 0;
7174
- while (start < transcript.length) {
7175
- const end = Math.min(start + chunkSize, transcript.length);
7176
- chunks.push(transcript.slice(start, end));
7177
- if (end === transcript.length)
7178
- break;
7179
- start += chunkSize - overlap;
7609
+ // src/db/tool-events.ts
7610
+ var exports_tool_events = {};
7611
+ __export(exports_tool_events, {
7612
+ saveToolEvent: () => saveToolEvent,
7613
+ getToolStats: () => getToolStats,
7614
+ getToolLessons: () => getToolLessons,
7615
+ getToolEvents: () => getToolEvents,
7616
+ getToolEvent: () => getToolEvent,
7617
+ deleteToolEvents: () => deleteToolEvents
7618
+ });
7619
+ function parseToolEventRow(row) {
7620
+ return {
7621
+ id: row["id"],
7622
+ tool_name: row["tool_name"],
7623
+ action: row["action"] || null,
7624
+ success: !!row["success"],
7625
+ error_type: row["error_type"] || null,
7626
+ error_message: row["error_message"] || null,
7627
+ tokens_used: row["tokens_used"] ?? null,
7628
+ latency_ms: row["latency_ms"] ?? null,
7629
+ context: row["context"] || null,
7630
+ lesson: row["lesson"] || null,
7631
+ when_to_use: row["when_to_use"] || null,
7632
+ agent_id: row["agent_id"] || null,
7633
+ project_id: row["project_id"] || null,
7634
+ session_id: row["session_id"] || null,
7635
+ metadata: JSON.parse(row["metadata"] || "{}"),
7636
+ created_at: row["created_at"]
7637
+ };
7638
+ }
7639
+ function saveToolEvent(input, db) {
7640
+ const d = db || getDatabase();
7641
+ const id = uuid();
7642
+ const timestamp = now();
7643
+ const metadataJson = JSON.stringify(input.metadata || {});
7644
+ d.run(`INSERT INTO tool_events (id, tool_name, action, success, error_type, error_message, tokens_used, latency_ms, context, lesson, when_to_use, agent_id, project_id, session_id, metadata, created_at)
7645
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
7646
+ id,
7647
+ input.tool_name,
7648
+ input.action || null,
7649
+ input.success ? 1 : 0,
7650
+ input.error_type || null,
7651
+ input.error_message || null,
7652
+ input.tokens_used ?? null,
7653
+ input.latency_ms ?? null,
7654
+ input.context || null,
7655
+ input.lesson || null,
7656
+ input.when_to_use || null,
7657
+ input.agent_id || null,
7658
+ input.project_id || null,
7659
+ input.session_id || null,
7660
+ metadataJson,
7661
+ timestamp
7662
+ ]);
7663
+ return getToolEvent(id, d);
7664
+ }
7665
+ function getToolEvent(id, db) {
7666
+ const d = db || getDatabase();
7667
+ const row = d.query("SELECT * FROM tool_events WHERE id = ?").get(id);
7668
+ if (!row)
7669
+ return null;
7670
+ return parseToolEventRow(row);
7671
+ }
7672
+ function getToolEvents(filters, db) {
7673
+ const d = db || getDatabase();
7674
+ const conditions = [];
7675
+ const params = [];
7676
+ if (filters.tool_name) {
7677
+ conditions.push("tool_name = ?");
7678
+ params.push(filters.tool_name);
7180
7679
  }
7181
- return chunks;
7680
+ if (filters.agent_id) {
7681
+ conditions.push("agent_id = ?");
7682
+ params.push(filters.agent_id);
7683
+ }
7684
+ if (filters.project_id) {
7685
+ conditions.push("project_id = ?");
7686
+ params.push(filters.project_id);
7687
+ }
7688
+ if (filters.success !== undefined) {
7689
+ conditions.push("success = ?");
7690
+ params.push(filters.success ? 1 : 0);
7691
+ }
7692
+ if (filters.from_date) {
7693
+ conditions.push("created_at >= ?");
7694
+ params.push(filters.from_date);
7695
+ }
7696
+ if (filters.to_date) {
7697
+ conditions.push("created_at <= ?");
7698
+ params.push(filters.to_date);
7699
+ }
7700
+ const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
7701
+ const limit = filters.limit || 50;
7702
+ const offset = filters.offset || 0;
7703
+ const rows = d.query(`SELECT * FROM tool_events ${where} ORDER BY created_at DESC LIMIT ? OFFSET ?`).all(...params, limit, offset);
7704
+ return rows.map(parseToolEventRow);
7182
7705
  }
7183
- async function extractMemoriesFromChunk(chunk, context, db) {
7184
- const provider = providerRegistry.getAvailable();
7185
- if (!provider)
7706
+ function getToolStats(tool_name, project_id, db) {
7707
+ const d = db || getDatabase();
7708
+ let where = "WHERE tool_name = ?";
7709
+ const params = [tool_name];
7710
+ if (project_id) {
7711
+ where += " AND project_id = ?";
7712
+ params.push(project_id);
7713
+ }
7714
+ const stats = d.query(`SELECT
7715
+ COUNT(*) as total_calls,
7716
+ SUM(CASE WHEN success = 1 THEN 1 ELSE 0 END) as success_count,
7717
+ SUM(CASE WHEN success = 0 THEN 1 ELSE 0 END) as failure_count,
7718
+ AVG(CASE WHEN tokens_used IS NOT NULL THEN tokens_used END) as avg_tokens,
7719
+ AVG(CASE WHEN latency_ms IS NOT NULL THEN latency_ms END) as avg_latency_ms,
7720
+ MAX(created_at) as last_used
7721
+ FROM tool_events ${where}`).get(...params);
7722
+ const total = stats["total_calls"] || 0;
7723
+ const successCount = stats["success_count"] || 0;
7724
+ const errorRows = d.query(`SELECT error_type, COUNT(*) as count
7725
+ FROM tool_events ${where} AND error_type IS NOT NULL
7726
+ GROUP BY error_type ORDER BY count DESC LIMIT 5`).all(...params);
7727
+ return {
7728
+ tool_name,
7729
+ total_calls: total,
7730
+ success_count: successCount,
7731
+ failure_count: stats["failure_count"] || 0,
7732
+ success_rate: total > 0 ? successCount / total : 0,
7733
+ avg_tokens: stats["avg_tokens"] ?? null,
7734
+ avg_latency_ms: stats["avg_latency_ms"] ?? null,
7735
+ common_errors: errorRows,
7736
+ last_used: stats["last_used"] || ""
7737
+ };
7738
+ }
7739
+ function getToolLessons(tool_name, project_id, limit, db) {
7740
+ const d = db || getDatabase();
7741
+ let where = "WHERE tool_name = ? AND lesson IS NOT NULL";
7742
+ const params = [tool_name];
7743
+ if (project_id) {
7744
+ where += " AND project_id = ?";
7745
+ params.push(project_id);
7746
+ }
7747
+ const rows = d.query(`SELECT lesson, when_to_use, created_at FROM tool_events ${where} ORDER BY created_at DESC LIMIT ?`).all(...params, limit || 20);
7748
+ return rows;
7749
+ }
7750
+ function deleteToolEvents(filters, db) {
7751
+ const d = db || getDatabase();
7752
+ const conditions = [];
7753
+ const params = [];
7754
+ if (filters.tool_name) {
7755
+ conditions.push("tool_name = ?");
7756
+ params.push(filters.tool_name);
7757
+ }
7758
+ if (filters.agent_id) {
7759
+ conditions.push("agent_id = ?");
7760
+ params.push(filters.agent_id);
7761
+ }
7762
+ if (filters.project_id) {
7763
+ conditions.push("project_id = ?");
7764
+ params.push(filters.project_id);
7765
+ }
7766
+ if (filters.before_date) {
7767
+ conditions.push("created_at < ?");
7768
+ params.push(filters.before_date);
7769
+ }
7770
+ if (conditions.length === 0)
7186
7771
  return 0;
7772
+ const result = d.run(`DELETE FROM tool_events WHERE ${conditions.join(" AND ")}`, params);
7773
+ return result.changes;
7774
+ }
7775
+ var init_tool_events = __esm(() => {
7776
+ init_database();
7777
+ });
7778
+
7779
+ // src/lib/tool-lesson-extractor.ts
7780
+ async function extractToolLessons(transcript, options) {
7781
+ const apiKey = process.env["ANTHROPIC_API_KEY"];
7782
+ if (!apiKey)
7783
+ return [];
7187
7784
  try {
7188
- const extracted = await provider.extractMemories(SESSION_EXTRACTION_USER_TEMPLATE(chunk, context.sessionId), {
7189
- sessionId: context.sessionId,
7190
- agentId: context.agentId,
7191
- projectId: context.projectId
7785
+ const truncated = transcript.length > 8000 ? transcript.slice(0, 8000) + `
7786
+ [...truncated]` : transcript;
7787
+ const response = await fetch("https://api.anthropic.com/v1/messages", {
7788
+ method: "POST",
7789
+ headers: {
7790
+ "x-api-key": apiKey,
7791
+ "anthropic-version": "2023-06-01",
7792
+ "content-type": "application/json"
7793
+ },
7794
+ body: JSON.stringify({
7795
+ model: "claude-haiku-4-5-20251001",
7796
+ max_tokens: 1500,
7797
+ system: SYSTEM_PROMPT3,
7798
+ messages: [{ role: "user", content: `Extract tool lessons from this session transcript:
7799
+
7800
+ ${truncated}` }]
7801
+ })
7192
7802
  });
7193
- let savedCount = 0;
7194
- const sourceTag = context.source ? `source:${context.source}` : "source:manual";
7195
- for (const memory of extracted) {
7196
- if (!memory.content || !memory.content.trim())
7197
- continue;
7198
- try {
7199
- createMemory({
7803
+ if (!response.ok)
7804
+ return [];
7805
+ const data = await response.json();
7806
+ const text = data.content?.[0]?.text?.trim();
7807
+ if (!text)
7808
+ return [];
7809
+ const lessons = JSON.parse(text);
7810
+ if (!Array.isArray(lessons))
7811
+ return [];
7812
+ for (const lesson of lessons) {
7813
+ if (!lesson.tool_name || !lesson.lesson)
7814
+ continue;
7815
+ try {
7816
+ saveToolEvent({
7817
+ tool_name: lesson.tool_name,
7818
+ success: lesson.success,
7819
+ error_type: lesson.error_type || undefined,
7820
+ lesson: lesson.lesson,
7821
+ when_to_use: lesson.when_to_use,
7822
+ context: "extracted from session transcript",
7823
+ agent_id: options?.agent_id,
7824
+ project_id: options?.project_id,
7825
+ session_id: options?.session_id
7826
+ });
7827
+ } catch {}
7828
+ try {
7829
+ createMemory({
7830
+ key: `tool-lesson-${lesson.tool_name}-${Date.now()}`,
7831
+ value: lesson.lesson,
7832
+ category: "knowledge",
7833
+ scope: "shared",
7834
+ importance: 7,
7835
+ source: "auto",
7836
+ tags: ["tool-memory", lesson.tool_name, "auto-extracted"],
7837
+ when_to_use: lesson.when_to_use,
7838
+ agent_id: options?.agent_id,
7839
+ project_id: options?.project_id,
7840
+ session_id: options?.session_id
7841
+ });
7842
+ } catch {}
7843
+ }
7844
+ return lessons;
7845
+ } catch {
7846
+ return [];
7847
+ }
7848
+ }
7849
+ var SYSTEM_PROMPT3 = `You are a tool usage analyst. Given a session transcript containing tool calls and their results, extract actionable lessons about tool usage.
7850
+
7851
+ For each tool lesson, output a JSON array of objects with these fields:
7852
+ - tool_name: name of the tool
7853
+ - lesson: the insight (1-2 sentences)
7854
+ - when_to_use: activation context \u2014 when should an agent recall this lesson (start with "When" or "If")
7855
+ - success: boolean \u2014 was the tool call that taught this lesson successful?
7856
+ - error_type: if failed, one of: timeout, permission, not_found, syntax, rate_limit, other (or null if success)
7857
+
7858
+ Focus on:
7859
+ 1. Successful patterns: what worked and why
7860
+ 2. Failure lessons: what went wrong and how to avoid it
7861
+ 3. Parameter insights: optimal settings discovered
7862
+ 4. Alternative tools: when one tool is better than another
7863
+ 5. Error recovery: what to do when a specific error occurs
7864
+
7865
+ Only extract genuinely useful, non-obvious lessons. Skip trivial observations.
7866
+ Output ONLY the JSON array, no markdown or explanation.`;
7867
+ var init_tool_lesson_extractor = __esm(() => {
7868
+ init_tool_events();
7869
+ init_memories();
7870
+ });
7871
+
7872
+ // src/lib/procedural-extractor.ts
7873
+ async function extractProcedures(transcript, options) {
7874
+ const apiKey = process.env["ANTHROPIC_API_KEY"];
7875
+ if (!apiKey)
7876
+ return [];
7877
+ try {
7878
+ const truncated = transcript.length > 8000 ? transcript.slice(0, 8000) + `
7879
+ [...truncated]` : transcript;
7880
+ const response = await fetch("https://api.anthropic.com/v1/messages", {
7881
+ method: "POST",
7882
+ headers: {
7883
+ "x-api-key": apiKey,
7884
+ "anthropic-version": "2023-06-01",
7885
+ "content-type": "application/json"
7886
+ },
7887
+ body: JSON.stringify({
7888
+ model: "claude-haiku-4-5-20251001",
7889
+ max_tokens: 2000,
7890
+ system: SYSTEM_PROMPT4,
7891
+ messages: [{ role: "user", content: `Extract procedures from this session:
7892
+
7893
+ ${truncated}` }]
7894
+ })
7895
+ });
7896
+ if (!response.ok)
7897
+ return [];
7898
+ const data = await response.json();
7899
+ const text = data.content?.[0]?.text?.trim();
7900
+ if (!text)
7901
+ return [];
7902
+ const procedures = JSON.parse(text);
7903
+ if (!Array.isArray(procedures))
7904
+ return [];
7905
+ for (const proc of procedures) {
7906
+ if (!proc.title || !proc.steps?.length)
7907
+ continue;
7908
+ const sequenceGroup = `proc-${shortUuid()}`;
7909
+ for (let i = 0;i < proc.steps.length; i++) {
7910
+ const step = proc.steps[i];
7911
+ if (!step)
7912
+ continue;
7913
+ try {
7914
+ createMemory({
7915
+ key: `${sequenceGroup}-step-${i + 1}`,
7916
+ value: step.action,
7917
+ category: "procedural",
7918
+ scope: "shared",
7919
+ importance: 7,
7920
+ source: "auto",
7921
+ tags: ["procedure", "auto-extracted", proc.title.toLowerCase().replace(/\s+/g, "-")],
7922
+ when_to_use: step.when_to_use || proc.when_to_use,
7923
+ sequence_group: sequenceGroup,
7924
+ sequence_order: i + 1,
7925
+ agent_id: options?.agent_id,
7926
+ project_id: options?.project_id,
7927
+ session_id: options?.session_id
7928
+ });
7929
+ } catch {}
7930
+ }
7931
+ for (const pattern of proc.failure_patterns || []) {
7932
+ try {
7933
+ createMemory({
7934
+ key: `${sequenceGroup}-warning-${shortUuid()}`,
7935
+ value: `WARNING: ${pattern}`,
7936
+ category: "procedural",
7937
+ scope: "shared",
7938
+ importance: 8,
7939
+ source: "auto",
7940
+ tags: ["procedure", "failure-pattern", "auto-extracted"],
7941
+ when_to_use: proc.when_to_use,
7942
+ sequence_group: sequenceGroup,
7943
+ sequence_order: 999,
7944
+ agent_id: options?.agent_id,
7945
+ project_id: options?.project_id,
7946
+ session_id: options?.session_id
7947
+ });
7948
+ } catch {}
7949
+ }
7950
+ }
7951
+ return procedures;
7952
+ } catch {
7953
+ return [];
7954
+ }
7955
+ }
7956
+ var SYSTEM_PROMPT4 = `You extract procedural knowledge from session transcripts \u2014 workflows, step sequences, and problem-solution patterns.
7957
+
7958
+ For each procedure found, output a JSON array of objects:
7959
+ {
7960
+ "title": "short name for the workflow",
7961
+ "steps": [
7962
+ {"action": "what to do", "when_to_use": "activation context for this step"},
7963
+ {"action": "next step", "when_to_use": "activation context"}
7964
+ ],
7965
+ "failure_patterns": ["what to avoid and why"],
7966
+ "when_to_use": "overall activation context for the whole procedure"
7967
+ }
7968
+
7969
+ Focus on:
7970
+ 1. Multi-step workflows that were completed successfully
7971
+ 2. Step sequences where order matters
7972
+ 3. Failure \u2192 recovery patterns (what went wrong, how it was fixed)
7973
+ 4. Problem-solution pairs (when X happens, do Y)
7974
+
7975
+ Only extract non-trivial procedures (3+ steps or genuinely useful patterns).
7976
+ Output ONLY the JSON array.`;
7977
+ var init_procedural_extractor = __esm(() => {
7978
+ init_memories();
7979
+ init_database();
7980
+ });
7981
+
7982
+ // src/lib/session-processor.ts
7983
+ function chunkTranscript(transcript, chunkSize = 2000, overlap = 200) {
7984
+ if (!transcript || transcript.length === 0)
7985
+ return [];
7986
+ if (transcript.length <= chunkSize)
7987
+ return [transcript];
7988
+ const chunks = [];
7989
+ let start = 0;
7990
+ while (start < transcript.length) {
7991
+ const end = Math.min(start + chunkSize, transcript.length);
7992
+ chunks.push(transcript.slice(start, end));
7993
+ if (end === transcript.length)
7994
+ break;
7995
+ start += chunkSize - overlap;
7996
+ }
7997
+ return chunks;
7998
+ }
7999
+ async function extractMemoriesFromChunk(chunk, context, db) {
8000
+ const provider = providerRegistry.getAvailable();
8001
+ if (!provider)
8002
+ return 0;
8003
+ try {
8004
+ const extracted = await provider.extractMemories(SESSION_EXTRACTION_USER_TEMPLATE(chunk, context.sessionId), {
8005
+ sessionId: context.sessionId,
8006
+ agentId: context.agentId,
8007
+ projectId: context.projectId
8008
+ });
8009
+ let savedCount = 0;
8010
+ const sourceTag = context.source ? `source:${context.source}` : "source:manual";
8011
+ for (const memory of extracted) {
8012
+ if (!memory.content || !memory.content.trim())
8013
+ continue;
8014
+ try {
8015
+ createMemory({
7200
8016
  key: memory.content.slice(0, 120).replace(/\s+/g, "-").toLowerCase(),
7201
8017
  value: memory.content,
7202
8018
  category: memory.category,
@@ -7320,6 +8136,20 @@ async function processSessionJob(jobId, db) {
7320
8136
  }
7321
8137
  }
7322
8138
  result.memoriesExtracted = totalMemories;
8139
+ try {
8140
+ await extractToolLessons(job.transcript, {
8141
+ agent_id: job.agent_id ?? undefined,
8142
+ project_id: job.project_id ?? undefined,
8143
+ session_id: job.session_id
8144
+ });
8145
+ } catch {}
8146
+ try {
8147
+ await extractProcedures(job.transcript, {
8148
+ agent_id: job.agent_id ?? undefined,
8149
+ project_id: job.project_id ?? undefined,
8150
+ session_id: job.session_id
8151
+ });
8152
+ } catch {}
7323
8153
  try {
7324
8154
  if (result.errors.length > 0 && result.chunksProcessed === 0) {
7325
8155
  updateSessionJob(jobId, {
@@ -7351,6 +8181,8 @@ var init_session_processor = __esm(() => {
7351
8181
  init_memories();
7352
8182
  init_registry();
7353
8183
  init_session_jobs();
8184
+ init_tool_lesson_extractor();
8185
+ init_procedural_extractor();
7354
8186
  });
7355
8187
 
7356
8188
  // src/lib/session-queue.ts
@@ -7440,6 +8272,204 @@ var init_session_queue = __esm(() => {
7440
8272
  _pendingQueue = new Set;
7441
8273
  });
7442
8274
 
8275
+ // src/lib/session-registry.ts
8276
+ var exports_session_registry = {};
8277
+ __export(exports_session_registry, {
8278
+ updateSessionAgent: () => updateSessionAgent,
8279
+ unregisterSession: () => unregisterSession,
8280
+ registerSession: () => registerSession,
8281
+ listSessions: () => listSessions,
8282
+ heartbeatSession: () => heartbeatSession,
8283
+ getSessionsByProject: () => getSessionsByProject,
8284
+ getSessionByAgent: () => getSessionByAgent,
8285
+ getSession: () => getSession,
8286
+ closeRegistry: () => closeRegistry,
8287
+ cleanStaleSessions: () => cleanStaleSessions
8288
+ });
8289
+ import { Database as Database2 } from "bun:sqlite";
8290
+ import { existsSync as existsSync5, mkdirSync as mkdirSync5 } from "fs";
8291
+ import { dirname as dirname3, join as join5 } from "path";
8292
+ function getDb() {
8293
+ if (_db2)
8294
+ return _db2;
8295
+ const dir = dirname3(DB_PATH);
8296
+ if (!existsSync5(dir))
8297
+ mkdirSync5(dir, { recursive: true });
8298
+ _db2 = new Database2(DB_PATH, { create: true });
8299
+ _db2.run("PRAGMA journal_mode = WAL");
8300
+ _db2.run("PRAGMA busy_timeout = 3000");
8301
+ _db2.exec(`
8302
+ CREATE TABLE IF NOT EXISTS sessions (
8303
+ id TEXT PRIMARY KEY,
8304
+ pid INTEGER NOT NULL,
8305
+ cwd TEXT NOT NULL,
8306
+ git_root TEXT,
8307
+ agent_name TEXT,
8308
+ project_name TEXT,
8309
+ tty TEXT,
8310
+ mcp_server TEXT NOT NULL,
8311
+ metadata TEXT DEFAULT '{}',
8312
+ registered_at TEXT NOT NULL DEFAULT (datetime('now')),
8313
+ last_seen_at TEXT NOT NULL DEFAULT (datetime('now'))
8314
+ );
8315
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_sessions_pid_mcp
8316
+ ON sessions(pid, mcp_server);
8317
+ CREATE INDEX IF NOT EXISTS idx_sessions_project
8318
+ ON sessions(project_name);
8319
+ CREATE INDEX IF NOT EXISTS idx_sessions_agent
8320
+ ON sessions(agent_name);
8321
+ CREATE INDEX IF NOT EXISTS idx_sessions_git_root
8322
+ ON sessions(git_root);
8323
+ `);
8324
+ return _db2;
8325
+ }
8326
+ function generateId() {
8327
+ return crypto.randomUUID().slice(0, 8);
8328
+ }
8329
+ function now2() {
8330
+ return new Date().toISOString();
8331
+ }
8332
+ function parseRow2(row) {
8333
+ return {
8334
+ id: row["id"],
8335
+ pid: row["pid"],
8336
+ cwd: row["cwd"],
8337
+ git_root: row["git_root"] || null,
8338
+ agent_name: row["agent_name"] || null,
8339
+ project_name: row["project_name"] || null,
8340
+ tty: row["tty"] || null,
8341
+ mcp_server: row["mcp_server"],
8342
+ metadata: JSON.parse(row["metadata"] || "{}"),
8343
+ registered_at: row["registered_at"],
8344
+ last_seen_at: row["last_seen_at"]
8345
+ };
8346
+ }
8347
+ function isProcessAlive(pid) {
8348
+ try {
8349
+ process.kill(pid, 0);
8350
+ return true;
8351
+ } catch {
8352
+ return false;
8353
+ }
8354
+ }
8355
+ function registerSession(opts) {
8356
+ const db = getDb();
8357
+ const pid = process.pid;
8358
+ const cwd = opts.cwd || process.cwd();
8359
+ const id = generateId();
8360
+ const timestamp = now2();
8361
+ const existing = db.query("SELECT id FROM sessions WHERE pid = ? AND mcp_server = ?").get(pid, opts.mcp_server);
8362
+ if (existing) {
8363
+ db.run(`UPDATE sessions SET agent_name = ?, project_name = ?, cwd = ?,
8364
+ git_root = ?, tty = ?, metadata = ?, last_seen_at = ? WHERE id = ?`, [
8365
+ opts.agent_name || null,
8366
+ opts.project_name || null,
8367
+ cwd,
8368
+ opts.git_root || null,
8369
+ opts.tty || null,
8370
+ JSON.stringify(opts.metadata || {}),
8371
+ timestamp,
8372
+ existing.id
8373
+ ]);
8374
+ return getSession(existing.id);
8375
+ }
8376
+ db.run(`INSERT INTO sessions (id, pid, cwd, git_root, agent_name, project_name, tty, mcp_server, metadata, registered_at, last_seen_at)
8377
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
8378
+ id,
8379
+ pid,
8380
+ cwd,
8381
+ opts.git_root || null,
8382
+ opts.agent_name || null,
8383
+ opts.project_name || null,
8384
+ opts.tty || null,
8385
+ opts.mcp_server,
8386
+ JSON.stringify(opts.metadata || {}),
8387
+ timestamp,
8388
+ timestamp
8389
+ ]);
8390
+ return getSession(id);
8391
+ }
8392
+ function heartbeatSession(id) {
8393
+ const db = getDb();
8394
+ db.run("UPDATE sessions SET last_seen_at = ? WHERE id = ?", [now2(), id]);
8395
+ }
8396
+ function unregisterSession(id) {
8397
+ const db = getDb();
8398
+ db.run("DELETE FROM sessions WHERE id = ?", [id]);
8399
+ }
8400
+ function getSession(id) {
8401
+ const db = getDb();
8402
+ const row = db.query("SELECT * FROM sessions WHERE id = ?").get(id);
8403
+ return row ? parseRow2(row) : null;
8404
+ }
8405
+ function listSessions(filter) {
8406
+ const db = getDb();
8407
+ const conditions = [];
8408
+ const params = [];
8409
+ if (filter?.project_name) {
8410
+ conditions.push("project_name = ?");
8411
+ params.push(filter.project_name);
8412
+ }
8413
+ if (filter?.git_root) {
8414
+ conditions.push("git_root = ?");
8415
+ params.push(filter.git_root);
8416
+ }
8417
+ if (filter?.mcp_server) {
8418
+ conditions.push("mcp_server = ?");
8419
+ params.push(filter.mcp_server);
8420
+ }
8421
+ if (filter?.agent_name) {
8422
+ conditions.push("agent_name = ?");
8423
+ params.push(filter.agent_name);
8424
+ }
8425
+ if (filter?.exclude_pid) {
8426
+ conditions.push("pid != ?");
8427
+ params.push(filter.exclude_pid);
8428
+ }
8429
+ const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
8430
+ const rows = db.query(`SELECT * FROM sessions ${where} ORDER BY last_seen_at DESC`).all(...params);
8431
+ return rows.map(parseRow2).filter((s) => {
8432
+ if (isProcessAlive(s.pid))
8433
+ return true;
8434
+ db.run("DELETE FROM sessions WHERE id = ?", [s.id]);
8435
+ return false;
8436
+ });
8437
+ }
8438
+ function getSessionByAgent(agentName) {
8439
+ const sessions = listSessions({ agent_name: agentName });
8440
+ return sessions[0] || null;
8441
+ }
8442
+ function getSessionsByProject(projectName) {
8443
+ return listSessions({ project_name: projectName });
8444
+ }
8445
+ function cleanStaleSessions() {
8446
+ const db = getDb();
8447
+ const rows = db.query("SELECT id, pid FROM sessions").all();
8448
+ let cleaned = 0;
8449
+ for (const row of rows) {
8450
+ if (!isProcessAlive(row.pid)) {
8451
+ db.run("DELETE FROM sessions WHERE id = ?", [row.id]);
8452
+ cleaned++;
8453
+ }
8454
+ }
8455
+ return cleaned;
8456
+ }
8457
+ function updateSessionAgent(mcpServer, agentName) {
8458
+ const db = getDb();
8459
+ const pid = process.pid;
8460
+ db.run("UPDATE sessions SET agent_name = ?, last_seen_at = ? WHERE pid = ? AND mcp_server = ?", [agentName, now2(), pid, mcpServer]);
8461
+ }
8462
+ function closeRegistry() {
8463
+ if (_db2) {
8464
+ _db2.close();
8465
+ _db2 = null;
8466
+ }
8467
+ }
8468
+ var DB_PATH, _db2 = null;
8469
+ var init_session_registry = __esm(() => {
8470
+ DB_PATH = join5(process.env["HOME"] || process.env["USERPROFILE"] || "~", ".open-sessions-registry.db");
8471
+ });
8472
+
7443
8473
  // node_modules/commander/esm.mjs
7444
8474
  var import__ = __toESM(require_commander(), 1);
7445
8475
  var {
@@ -7459,10 +8489,10 @@ var {
7459
8489
  // src/cli/index.tsx
7460
8490
  init_database();
7461
8491
  init_memories();
7462
- import chalk from "chalk";
7463
- import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, existsSync as existsSync3, unlinkSync as unlinkSync2, accessSync, statSync, copyFileSync, mkdirSync as mkdirSync3, readdirSync as readdirSync2, constants as fsConstants } from "fs";
7464
- import { dirname as dirname3, join as join3, resolve as resolve3 } from "path";
7465
- import { homedir as homedir2 } from "os";
8492
+ import chalk2 from "chalk";
8493
+ import { readFileSync as readFileSync3, writeFileSync as writeFileSync4, existsSync as existsSync6, unlinkSync as unlinkSync2, accessSync, statSync, copyFileSync, mkdirSync as mkdirSync6, readdirSync as readdirSync3, constants as fsConstants } from "fs";
8494
+ import { dirname as dirname4, join as join6, resolve as resolve3 } from "path";
8495
+ import { homedir as homedir4 } from "os";
7466
8496
  import { fileURLToPath } from "url";
7467
8497
 
7468
8498
  // src/db/agents.ts
@@ -7945,37 +8975,332 @@ var FORMAT_UNITS = [
7945
8975
  init_entities();
7946
8976
  init_relations();
7947
8977
  init_entity_memories();
8978
+
8979
+ // src/cli/brains.ts
8980
+ import {
8981
+ existsSync as existsSync4,
8982
+ mkdirSync as mkdirSync4,
8983
+ writeFileSync as writeFileSync3,
8984
+ readdirSync as readdirSync2
8985
+ } from "fs";
8986
+ import { homedir as homedir3 } from "os";
8987
+ import { join as join4 } from "path";
8988
+ import chalk from "chalk";
8989
+
8990
+ // src/lib/gatherer.ts
8991
+ init_memories();
8992
+ var SYSTEM_PROMPT = "You are an AI assistant with persistent memory that recalls and saves information across sessions.";
8993
+ function memoryToRecallExample(memory) {
8994
+ return {
8995
+ messages: [
8996
+ { role: "system", content: SYSTEM_PROMPT },
8997
+ {
8998
+ role: "user",
8999
+ content: `What do you remember about "${memory.key}"?`
9000
+ },
9001
+ {
9002
+ role: "assistant",
9003
+ content: memory.summary ? `${memory.value}
9004
+
9005
+ Summary: ${memory.summary}` : memory.value
9006
+ }
9007
+ ]
9008
+ };
9009
+ }
9010
+ function memoryToSaveExample(memory) {
9011
+ const tags = memory.tags ?? [];
9012
+ return {
9013
+ messages: [
9014
+ { role: "system", content: SYSTEM_PROMPT },
9015
+ {
9016
+ role: "user",
9017
+ content: `Remember this for me: ${memory.key} = ${memory.value}${tags.length ? ` (tags: ${tags.join(", ")})` : ""}`
9018
+ },
9019
+ {
9020
+ role: "assistant",
9021
+ content: `Saved to memory: "${memory.key}" with ${memory.category} category, importance ${memory.importance}/10, scope: ${memory.scope}.`
9022
+ }
9023
+ ]
9024
+ };
9025
+ }
9026
+ function memoryToSearchExample(memories, category) {
9027
+ const matched = memories.filter((m) => m.category === category && m.status === "active").slice(0, 5);
9028
+ return {
9029
+ messages: [
9030
+ { role: "system", content: SYSTEM_PROMPT },
9031
+ { role: "user", content: `What ${category} memories do you have?` },
9032
+ {
9033
+ role: "assistant",
9034
+ content: matched.length > 0 ? `Here are my ${category} memories:
9035
+ ${matched.map((m) => `- ${m.key}: ${m.value.slice(0, 120)}${m.value.length > 120 ? "..." : ""}`).join(`
9036
+ `)}` : `I don't have any ${category} memories stored yet.`
9037
+ }
9038
+ ]
9039
+ };
9040
+ }
9041
+ var gatherTrainingData = async (options = {}) => {
9042
+ const allMemories = listMemories({ status: "active" });
9043
+ const filtered = options.since ? allMemories.filter((m) => new Date(m.created_at) >= options.since) : allMemories;
9044
+ const sorted = filtered.slice().sort((a, b) => b.importance - a.importance);
9045
+ const fetchSet = options.limit ? sorted.slice(0, options.limit * 3) : sorted;
9046
+ const examples = [];
9047
+ for (const memory of fetchSet) {
9048
+ examples.push(memoryToRecallExample(memory));
9049
+ examples.push(memoryToSaveExample(memory));
9050
+ }
9051
+ const categories = [...new Set(fetchSet.map((m) => m.category))];
9052
+ for (const category of categories) {
9053
+ examples.push(memoryToSearchExample(fetchSet, category));
9054
+ }
9055
+ const finalExamples = options.limit ? examples.slice(0, options.limit) : examples;
9056
+ return {
9057
+ source: "mementos",
9058
+ examples: finalExamples,
9059
+ count: finalExamples.length
9060
+ };
9061
+ };
9062
+
9063
+ // src/lib/model-config.ts
9064
+ import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
9065
+ import { homedir as homedir2 } from "os";
9066
+ import { join as join3 } from "path";
9067
+ var DEFAULT_MODEL = "gpt-4o-mini";
9068
+ var CONFIG_DIR = join3(homedir2(), ".mementos");
9069
+ var CONFIG_PATH = join3(CONFIG_DIR, "config.json");
9070
+ function readConfig() {
9071
+ if (!existsSync3(CONFIG_PATH))
9072
+ return {};
9073
+ try {
9074
+ const raw = readFileSync2(CONFIG_PATH, "utf-8");
9075
+ return JSON.parse(raw);
9076
+ } catch {
9077
+ return {};
9078
+ }
9079
+ }
9080
+ function writeConfig(config) {
9081
+ if (!existsSync3(CONFIG_DIR)) {
9082
+ mkdirSync3(CONFIG_DIR, { recursive: true });
9083
+ }
9084
+ writeFileSync2(CONFIG_PATH, JSON.stringify(config, null, 2) + `
9085
+ `, "utf-8");
9086
+ }
9087
+ function getActiveModel() {
9088
+ const config = readConfig();
9089
+ return config.activeModel ?? DEFAULT_MODEL;
9090
+ }
9091
+ function setActiveModel(modelId) {
9092
+ const config = readConfig();
9093
+ config.activeModel = modelId;
9094
+ writeConfig(config);
9095
+ }
9096
+ function clearActiveModel() {
9097
+ const config = readConfig();
9098
+ delete config.activeModel;
9099
+ writeConfig(config);
9100
+ }
9101
+
9102
+ // src/cli/brains.ts
9103
+ function printSuccess(msg) {
9104
+ console.log(chalk.green("\u2713 " + msg));
9105
+ }
9106
+ function printError(msg) {
9107
+ console.error(chalk.red("\u2717 " + msg));
9108
+ }
9109
+ function printInfo(msg) {
9110
+ console.log(chalk.cyan("\u2139 " + msg));
9111
+ }
9112
+ function makeBrainsCommand() {
9113
+ const brains = new Command("brains");
9114
+ brains.description("Fine-tuned model training and management (via @hasna/brains)");
9115
+ brains.command("gather").description("Gather training data from memories and write to JSONL").option("--limit <n>", "Maximum number of examples to gather", parseInt).option("--since <date>", "Only include memories created since this date (ISO 8601)").option("--output <dir>", "Output directory (default: ~/.mementos/training/)").option("--json", "Output result summary as JSON").action(async (opts) => {
9116
+ try {
9117
+ const since = opts.since ? new Date(opts.since) : undefined;
9118
+ if (since && isNaN(since.getTime())) {
9119
+ printError(`Invalid date: ${opts.since}`);
9120
+ process.exit(1);
9121
+ }
9122
+ if (!opts.json) {
9123
+ printInfo("Gathering training data from memories...");
9124
+ }
9125
+ const result = await gatherTrainingData({
9126
+ limit: opts.limit,
9127
+ since
9128
+ });
9129
+ const outputDir = opts.output ?? join4(homedir3(), ".mementos", "training");
9130
+ if (!existsSync4(outputDir)) {
9131
+ mkdirSync4(outputDir, { recursive: true });
9132
+ }
9133
+ const timestamp = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
9134
+ const outputPath = join4(outputDir, `mementos-training-${timestamp}.jsonl`);
9135
+ const jsonl = result.examples.map((ex) => JSON.stringify(ex)).join(`
9136
+ `);
9137
+ writeFileSync3(outputPath, jsonl + `
9138
+ `, "utf-8");
9139
+ if (opts.json) {
9140
+ console.log(JSON.stringify({
9141
+ source: result.source,
9142
+ count: result.count,
9143
+ path: outputPath
9144
+ }));
9145
+ } else {
9146
+ printSuccess(`Gathered ${result.count} training examples from memories`);
9147
+ console.log(chalk.dim(` Output: ${outputPath}`));
9148
+ }
9149
+ } catch (err) {
9150
+ printError(err instanceof Error ? err.message : String(err));
9151
+ process.exit(1);
9152
+ }
9153
+ });
9154
+ brains.command("train").description("Start a fine-tuning job using gathered memory training data").option("--base-model <model>", "Base model to fine-tune", "gpt-4o-mini-2024-07-18").option("--provider <provider>", "Provider (openai|thinker-labs)", "openai").option("--dataset <path>", "Path to JSONL dataset (auto-detects latest if omitted)").option("--name <name>", "Display name for the fine-tuned model").option("--json", "Output result as JSON").action(async (opts) => {
9155
+ try {
9156
+ let datasetPath = opts.dataset;
9157
+ if (!datasetPath) {
9158
+ const trainingDir = join4(homedir3(), ".mementos", "training");
9159
+ if (!existsSync4(trainingDir)) {
9160
+ printError("No training data found. Run `mementos brains gather` first.");
9161
+ process.exit(1);
9162
+ }
9163
+ const files = readdirSync2(trainingDir).filter((f) => f.endsWith(".jsonl")).sort().reverse();
9164
+ const latestFile = files[0];
9165
+ if (!latestFile) {
9166
+ printError("No JSONL training files found. Run `mementos brains gather` first.");
9167
+ process.exit(1);
9168
+ }
9169
+ datasetPath = join4(trainingDir, latestFile);
9170
+ }
9171
+ if (!datasetPath || !existsSync4(datasetPath)) {
9172
+ printError(`Dataset file not found: ${datasetPath ?? "(unresolved)"}`);
9173
+ process.exit(1);
9174
+ }
9175
+ if (!opts.json) {
9176
+ printInfo(`Starting fine-tuning job with dataset: ${datasetPath}`);
9177
+ }
9178
+ let brainsSDK;
9179
+ try {
9180
+ brainsSDK = await import("@hasna/brains");
9181
+ } catch {
9182
+ printError("@hasna/brains is not installed. Run `bun add @hasna/brains` to enable training.");
9183
+ process.exit(1);
9184
+ }
9185
+ const startFinetune = brainsSDK["startFinetune"];
9186
+ if (typeof startFinetune !== "function") {
9187
+ printError("@hasna/brains does not export startFinetune. Please update @hasna/brains.");
9188
+ process.exit(1);
9189
+ }
9190
+ const modelName = opts.name ?? `mementos-${new Date().toISOString().slice(0, 10)}`;
9191
+ const jobResult = await startFinetune({
9192
+ provider: opts.provider,
9193
+ baseModel: opts.baseModel,
9194
+ datasetPath,
9195
+ name: modelName
9196
+ });
9197
+ if (opts.json) {
9198
+ console.log(JSON.stringify(jobResult));
9199
+ } else {
9200
+ printSuccess(`Fine-tuning job started: ${String(jobResult["jobId"] ?? "(unknown)")}`);
9201
+ console.log(chalk.dim(` Provider: ${opts.provider}`));
9202
+ console.log(chalk.dim(` Base model: ${opts.baseModel}`));
9203
+ console.log(chalk.dim(` Name: ${modelName}`));
9204
+ if (jobResult["jobId"]) {
9205
+ console.log();
9206
+ printInfo(`Use \`mementos brains model set <model-id>\` once training completes.`);
9207
+ }
9208
+ }
9209
+ } catch (err) {
9210
+ printError(err instanceof Error ? err.message : String(err));
9211
+ process.exit(1);
9212
+ }
9213
+ });
9214
+ const modelCmd = brains.command("model").description("Manage the active fine-tuned model");
9215
+ modelCmd.command("get").description("Show the currently active fine-tuned model").option("--json", "Output as JSON").action((opts) => {
9216
+ try {
9217
+ const active = getActiveModel();
9218
+ const isDefault = active === DEFAULT_MODEL;
9219
+ if (opts.json) {
9220
+ console.log(JSON.stringify({ activeModel: active, isDefault }));
9221
+ } else {
9222
+ if (isDefault) {
9223
+ console.log(`Active model: ${chalk.cyan(active)} ${chalk.dim("(default)")}`);
9224
+ } else {
9225
+ console.log(`Active model: ${chalk.green(active)}`);
9226
+ }
9227
+ }
9228
+ } catch (err) {
9229
+ printError(err instanceof Error ? err.message : String(err));
9230
+ process.exit(1);
9231
+ }
9232
+ });
9233
+ modelCmd.command("set <modelId>").description("Set the active fine-tuned model ID").action((modelId) => {
9234
+ try {
9235
+ setActiveModel(modelId);
9236
+ printSuccess(`Active model set to: ${modelId}`);
9237
+ } catch (err) {
9238
+ printError(err instanceof Error ? err.message : String(err));
9239
+ process.exit(1);
9240
+ }
9241
+ });
9242
+ modelCmd.command("clear").description(`Clear the active fine-tuned model (reverts to ${DEFAULT_MODEL})`).action(() => {
9243
+ try {
9244
+ clearActiveModel();
9245
+ printSuccess(`Active model cleared. Using default: ${DEFAULT_MODEL}`);
9246
+ } catch (err) {
9247
+ printError(err instanceof Error ? err.message : String(err));
9248
+ process.exit(1);
9249
+ }
9250
+ });
9251
+ modelCmd.action((opts) => {
9252
+ try {
9253
+ const active = getActiveModel();
9254
+ const isDefault = active === DEFAULT_MODEL;
9255
+ if (opts.json) {
9256
+ console.log(JSON.stringify({ activeModel: active, isDefault }));
9257
+ } else {
9258
+ if (isDefault) {
9259
+ console.log(`Active model: ${chalk.cyan(active)} ${chalk.dim("(default)")}`);
9260
+ } else {
9261
+ console.log(`Active model: ${chalk.green(active)}`);
9262
+ }
9263
+ }
9264
+ } catch (err) {
9265
+ printError(err instanceof Error ? err.message : String(err));
9266
+ process.exit(1);
9267
+ }
9268
+ });
9269
+ return brains;
9270
+ }
9271
+
9272
+ // src/cli/index.tsx
7948
9273
  function getPackageVersion() {
7949
9274
  try {
7950
- const pkgPath = join3(dirname3(fileURLToPath(import.meta.url)), "..", "..", "package.json");
7951
- const pkg = JSON.parse(readFileSync2(pkgPath, "utf-8"));
9275
+ const pkgPath = join6(dirname4(fileURLToPath(import.meta.url)), "..", "..", "package.json");
9276
+ const pkg = JSON.parse(readFileSync3(pkgPath, "utf-8"));
7952
9277
  return pkg.version || "0.0.0";
7953
9278
  } catch {
7954
9279
  return "0.0.0";
7955
9280
  }
7956
9281
  }
7957
9282
  var scopeColor = {
7958
- global: chalk.cyan,
7959
- shared: chalk.yellow,
7960
- private: chalk.magenta,
7961
- working: chalk.gray
9283
+ global: chalk2.cyan,
9284
+ shared: chalk2.yellow,
9285
+ private: chalk2.magenta,
9286
+ working: chalk2.gray
7962
9287
  };
7963
9288
  var categoryColor = {
7964
- preference: chalk.blue,
7965
- fact: chalk.green,
7966
- knowledge: chalk.yellow,
7967
- history: chalk.gray,
7968
- procedural: chalk.cyan,
7969
- resource: chalk.magenta
9289
+ preference: chalk2.blue,
9290
+ fact: chalk2.green,
9291
+ knowledge: chalk2.yellow,
9292
+ history: chalk2.gray,
9293
+ procedural: chalk2.cyan,
9294
+ resource: chalk2.magenta
7970
9295
  };
7971
9296
  function importanceColor(importance) {
7972
9297
  if (importance >= 9)
7973
- return chalk.red.bold;
9298
+ return chalk2.red.bold;
7974
9299
  if (importance >= 7)
7975
- return chalk.yellow;
9300
+ return chalk2.yellow;
7976
9301
  if (importance >= 5)
7977
- return chalk.green;
7978
- return chalk.dim;
9302
+ return chalk2.green;
9303
+ return chalk2.dim;
7979
9304
  }
7980
9305
  function colorScope(scope) {
7981
9306
  return scopeColor[scope](scope);
@@ -7987,17 +9312,17 @@ function colorImportance(importance) {
7987
9312
  return importanceColor(importance)(String(importance));
7988
9313
  }
7989
9314
  var entityTypeColor = {
7990
- person: chalk.cyan,
7991
- project: chalk.yellow,
7992
- tool: chalk.green,
7993
- concept: chalk.blue,
7994
- file: chalk.magenta,
7995
- api: chalk.red,
7996
- pattern: chalk.gray,
7997
- organization: chalk.white
9315
+ person: chalk2.cyan,
9316
+ project: chalk2.yellow,
9317
+ tool: chalk2.green,
9318
+ concept: chalk2.blue,
9319
+ file: chalk2.magenta,
9320
+ api: chalk2.red,
9321
+ pattern: chalk2.gray,
9322
+ organization: chalk2.white
7998
9323
  };
7999
9324
  function colorEntityType(type) {
8000
- const colorFn = entityTypeColor[type] || chalk.white;
9325
+ const colorFn = entityTypeColor[type] || chalk2.white;
8001
9326
  return colorFn(type);
8002
9327
  }
8003
9328
  function resolveEntityArg(nameOrId, type) {
@@ -8008,7 +9333,7 @@ function resolveEntityArg(nameOrId, type) {
8008
9333
  const id = resolvePartialId(db, "entities", nameOrId);
8009
9334
  if (id)
8010
9335
  return getEntity(id);
8011
- console.error(chalk.red(`Entity not found: ${nameOrId}`));
9336
+ console.error(chalk2.red(`Entity not found: ${nameOrId}`));
8012
9337
  process.exit(1);
8013
9338
  }
8014
9339
  function outputJson(data) {
@@ -8092,44 +9417,44 @@ ${formatObj({ [k]: v }, " ").replace(/^\s*\S+:\n/, "")}`);
8092
9417
  }
8093
9418
  }
8094
9419
  function formatMemoryLine(m) {
8095
- const id = chalk.dim(m.id.slice(0, 8));
9420
+ const id = chalk2.dim(m.id.slice(0, 8));
8096
9421
  const scope = colorScope(m.scope);
8097
9422
  const cat = colorCategory(m.category);
8098
9423
  const imp = colorImportance(m.importance);
8099
- const pin = m.pinned ? chalk.red(" *") : "";
9424
+ const pin = m.pinned ? chalk2.red(" *") : "";
8100
9425
  const value = m.value.length > 80 ? m.value.slice(0, 80) + "..." : m.value;
8101
- return `${id} [${scope}/${cat}] ${chalk.bold(m.key)} = ${value} (${imp})${pin}`;
9426
+ return `${id} [${scope}/${cat}] ${chalk2.bold(m.key)} = ${value} (${imp})${pin}`;
8102
9427
  }
8103
9428
  function formatMemoryDetail(m) {
8104
9429
  const lines = [
8105
- `${chalk.bold("ID:")} ${m.id}`,
8106
- `${chalk.bold("Key:")} ${m.key}`,
8107
- `${chalk.bold("Value:")} ${m.value}`,
8108
- `${chalk.bold("Scope:")} ${colorScope(m.scope)}`,
8109
- `${chalk.bold("Category:")} ${colorCategory(m.category)}`,
8110
- `${chalk.bold("Importance:")} ${colorImportance(m.importance)}/10`,
8111
- `${chalk.bold("Source:")} ${m.source}`,
8112
- `${chalk.bold("Status:")} ${m.status}`,
8113
- `${chalk.bold("Pinned:")} ${m.pinned ? chalk.red("yes") : "no"}`
9430
+ `${chalk2.bold("ID:")} ${m.id}`,
9431
+ `${chalk2.bold("Key:")} ${m.key}`,
9432
+ `${chalk2.bold("Value:")} ${m.value}`,
9433
+ `${chalk2.bold("Scope:")} ${colorScope(m.scope)}`,
9434
+ `${chalk2.bold("Category:")} ${colorCategory(m.category)}`,
9435
+ `${chalk2.bold("Importance:")} ${colorImportance(m.importance)}/10`,
9436
+ `${chalk2.bold("Source:")} ${m.source}`,
9437
+ `${chalk2.bold("Status:")} ${m.status}`,
9438
+ `${chalk2.bold("Pinned:")} ${m.pinned ? chalk2.red("yes") : "no"}`
8114
9439
  ];
8115
9440
  if (m.summary)
8116
- lines.push(`${chalk.bold("Summary:")} ${m.summary}`);
9441
+ lines.push(`${chalk2.bold("Summary:")} ${m.summary}`);
8117
9442
  if (m.tags.length > 0)
8118
- lines.push(`${chalk.bold("Tags:")} ${m.tags.join(", ")}`);
9443
+ lines.push(`${chalk2.bold("Tags:")} ${m.tags.join(", ")}`);
8119
9444
  if (m.agent_id)
8120
- lines.push(`${chalk.bold("Agent:")} ${m.agent_id}`);
9445
+ lines.push(`${chalk2.bold("Agent:")} ${m.agent_id}`);
8121
9446
  if (m.project_id)
8122
- lines.push(`${chalk.bold("Project:")} ${m.project_id}`);
9447
+ lines.push(`${chalk2.bold("Project:")} ${m.project_id}`);
8123
9448
  if (m.session_id)
8124
- lines.push(`${chalk.bold("Session:")} ${m.session_id}`);
9449
+ lines.push(`${chalk2.bold("Session:")} ${m.session_id}`);
8125
9450
  if (m.expires_at)
8126
- lines.push(`${chalk.bold("Expires:")} ${m.expires_at}`);
8127
- lines.push(`${chalk.bold("Access:")} ${m.access_count}`);
8128
- lines.push(`${chalk.bold("Version:")} ${m.version}`);
8129
- lines.push(`${chalk.bold("Created:")} ${m.created_at}`);
8130
- lines.push(`${chalk.bold("Updated:")} ${m.updated_at}`);
9451
+ lines.push(`${chalk2.bold("Expires:")} ${m.expires_at}`);
9452
+ lines.push(`${chalk2.bold("Access:")} ${m.access_count}`);
9453
+ lines.push(`${chalk2.bold("Version:")} ${m.version}`);
9454
+ lines.push(`${chalk2.bold("Created:")} ${m.created_at}`);
9455
+ lines.push(`${chalk2.bold("Updated:")} ${m.updated_at}`);
8131
9456
  if (m.accessed_at)
8132
- lines.push(`${chalk.bold("Accessed:")} ${m.accessed_at}`);
9457
+ lines.push(`${chalk2.bold("Accessed:")} ${m.accessed_at}`);
8133
9458
  return lines.join(`
8134
9459
  `);
8135
9460
  }
@@ -8141,7 +9466,7 @@ function handleError(e) {
8141
9466
  error: e instanceof Error ? e.message : String(e)
8142
9467
  });
8143
9468
  } else {
8144
- console.error(chalk.red(e instanceof Error ? e.message : String(e)));
9469
+ console.error(chalk2.red(e instanceof Error ? e.message : String(e)));
8145
9470
  }
8146
9471
  process.exit(1);
8147
9472
  }
@@ -8149,7 +9474,7 @@ function resolveMemoryId(partialId) {
8149
9474
  const db = getDatabase();
8150
9475
  const id = resolvePartialId(db, "memories", partialId);
8151
9476
  if (!id) {
8152
- console.error(chalk.red(`Could not resolve memory ID: ${partialId}`));
9477
+ console.error(chalk2.red(`Could not resolve memory ID: ${partialId}`));
8153
9478
  process.exit(1);
8154
9479
  }
8155
9480
  return id;
@@ -8175,10 +9500,10 @@ function resolveKeyOrId(keyOrId, opts, globalOpts) {
8175
9500
  program2.name("mementos").description("Universal memory system for AI agents").version(getPackageVersion()).option("--project <path>", "Project path for scoping").option("--json", "Output as JSON").option("--format <fmt>", "Output format: compact, json, csv, yaml").option("--agent <name>", "Agent name or ID").option("--session <id>", "Session ID");
8176
9501
  program2.command("init").description("One-command setup: register MCP, install stop hook, configure auto-start").action(async () => {
8177
9502
  const { platform } = process;
8178
- const home = homedir2();
9503
+ const home = homedir4();
8179
9504
  const isMac = platform === "darwin";
8180
9505
  console.log("");
8181
- console.log(chalk.bold(" mementos \u2014 setting up your memory layer"));
9506
+ console.log(chalk2.bold(" mementos \u2014 setting up your memory layer"));
8182
9507
  console.log("");
8183
9508
  async function run(cmd) {
8184
9509
  try {
@@ -8223,24 +9548,24 @@ program2.command("init").description("One-command setup: register MCP, install s
8223
9548
  mcpError = e instanceof Error ? e.message : String(e);
8224
9549
  }
8225
9550
  if (mcpAlreadyInstalled) {
8226
- console.log(chalk.dim(" \xB7 MCP already registered"));
9551
+ console.log(chalk2.dim(" \xB7 MCP already registered"));
8227
9552
  } else if (mcpError) {
8228
- console.log(chalk.red(` \u2717 Failed to register MCP: ${mcpError}`));
8229
- console.log(chalk.dim(" (Is Claude Code installed? Try: claude mcp add --transport stdio --scope user mementos -- mementos-mcp)"));
9553
+ console.log(chalk2.red(` \u2717 Failed to register MCP: ${mcpError}`));
9554
+ console.log(chalk2.dim(" (Is Claude Code installed? Try: claude mcp add --transport stdio --scope user mementos -- mementos-mcp)"));
8230
9555
  } else {
8231
- console.log(chalk.green(" \u2713 MCP server registered with Claude Code"));
9556
+ console.log(chalk2.green(" \u2713 MCP server registered with Claude Code"));
8232
9557
  }
8233
- const hooksDir = join3(home, ".claude", "hooks");
8234
- const hookDest = join3(hooksDir, "mementos-stop-hook.ts");
8235
- const settingsPath = join3(home, ".claude", "settings.json");
9558
+ const hooksDir = join6(home, ".claude", "hooks");
9559
+ const hookDest = join6(hooksDir, "mementos-stop-hook.ts");
9560
+ const settingsPath = join6(home, ".claude", "settings.json");
8236
9561
  const hookCommand = `bun ${hookDest}`;
8237
9562
  let hookAlreadyInstalled = false;
8238
9563
  let hookError = null;
8239
9564
  try {
8240
9565
  let settings = {};
8241
- if (existsSync3(settingsPath)) {
9566
+ if (existsSync6(settingsPath)) {
8242
9567
  try {
8243
- settings = JSON.parse(readFileSync2(settingsPath, "utf-8"));
9568
+ settings = JSON.parse(readFileSync3(settingsPath, "utf-8"));
8244
9569
  } catch {
8245
9570
  settings = {};
8246
9571
  }
@@ -8251,19 +9576,19 @@ program2.command("init").description("One-command setup: register MCP, install s
8251
9576
  if (alreadyHasMementos) {
8252
9577
  hookAlreadyInstalled = true;
8253
9578
  } else {
8254
- if (!existsSync3(hooksDir)) {
8255
- mkdirSync3(hooksDir, { recursive: true });
9579
+ if (!existsSync6(hooksDir)) {
9580
+ mkdirSync6(hooksDir, { recursive: true });
8256
9581
  }
8257
- if (!existsSync3(hookDest)) {
8258
- const packageDir = dirname3(dirname3(fileURLToPath(import.meta.url)));
9582
+ if (!existsSync6(hookDest)) {
9583
+ const packageDir = dirname4(dirname4(fileURLToPath(import.meta.url)));
8259
9584
  const candidatePaths = [
8260
- join3(packageDir, "scripts", "hooks", "claude-stop-hook.ts"),
8261
- join3(packageDir, "..", "scripts", "hooks", "claude-stop-hook.ts"),
8262
- join3(home, ".bun", "install", "global", "node_modules", "@hasna", "mementos", "scripts", "hooks", "claude-stop-hook.ts")
9585
+ join6(packageDir, "scripts", "hooks", "claude-stop-hook.ts"),
9586
+ join6(packageDir, "..", "scripts", "hooks", "claude-stop-hook.ts"),
9587
+ join6(home, ".bun", "install", "global", "node_modules", "@hasna", "mementos", "scripts", "hooks", "claude-stop-hook.ts")
8263
9588
  ];
8264
9589
  let hookSourceFound = false;
8265
9590
  for (const src of candidatePaths) {
8266
- if (existsSync3(src)) {
9591
+ if (existsSync6(src)) {
8267
9592
  copyFileSync(src, hookDest);
8268
9593
  hookSourceFound = true;
8269
9594
  break;
@@ -8303,7 +9628,7 @@ async function main() {
8303
9628
 
8304
9629
  main().catch(() => {});
8305
9630
  `;
8306
- writeFileSync2(hookDest, inlineHook, "utf-8");
9631
+ writeFileSync4(hookDest, inlineHook, "utf-8");
8307
9632
  }
8308
9633
  }
8309
9634
  const newStopEntry = {
@@ -8312,24 +9637,24 @@ main().catch(() => {});
8312
9637
  };
8313
9638
  hooksObj["Stop"] = [...stopHooks, newStopEntry];
8314
9639
  settings["hooks"] = hooksObj;
8315
- writeFileSync2(settingsPath, JSON.stringify(settings, null, 2), "utf-8");
9640
+ writeFileSync4(settingsPath, JSON.stringify(settings, null, 2), "utf-8");
8316
9641
  }
8317
9642
  } catch (e) {
8318
9643
  hookError = e instanceof Error ? e.message : String(e);
8319
9644
  }
8320
9645
  if (hookAlreadyInstalled) {
8321
- console.log(chalk.dim(" \xB7 Stop hook already installed"));
9646
+ console.log(chalk2.dim(" \xB7 Stop hook already installed"));
8322
9647
  } else if (hookError) {
8323
- console.log(chalk.red(` \u2717 Failed to install stop hook: ${hookError}`));
9648
+ console.log(chalk2.red(` \u2717 Failed to install stop hook: ${hookError}`));
8324
9649
  } else {
8325
- console.log(chalk.green(" \u2713 Stop hook installed (sessions \u2192 memories)"));
9650
+ console.log(chalk2.green(" \u2713 Stop hook installed (sessions \u2192 memories)"));
8326
9651
  }
8327
9652
  let autoStartAlreadyInstalled = false;
8328
9653
  let autoStartError = null;
8329
9654
  if (!isMac) {
8330
- console.log(chalk.dim(` \xB7 Auto-start skipped (not macOS \u2014 platform: ${platform})`));
9655
+ console.log(chalk2.dim(` \xB7 Auto-start skipped (not macOS \u2014 platform: ${platform})`));
8331
9656
  } else {
8332
- const plistPath = join3(home, "Library", "LaunchAgents", "com.hasna.mementos.plist");
9657
+ const plistPath = join6(home, "Library", "LaunchAgents", "com.hasna.mementos.plist");
8333
9658
  const plistContent = `<?xml version="1.0" encoding="UTF-8"?>
8334
9659
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
8335
9660
  <plist version="1.0">
@@ -8354,30 +9679,30 @@ main().catch(() => {});
8354
9679
  </plist>
8355
9680
  `;
8356
9681
  try {
8357
- if (existsSync3(plistPath)) {
9682
+ if (existsSync6(plistPath)) {
8358
9683
  autoStartAlreadyInstalled = true;
8359
9684
  } else {
8360
- const launchAgentsDir = join3(home, "Library", "LaunchAgents");
8361
- if (!existsSync3(launchAgentsDir)) {
8362
- mkdirSync3(launchAgentsDir, { recursive: true });
9685
+ const launchAgentsDir = join6(home, "Library", "LaunchAgents");
9686
+ if (!existsSync6(launchAgentsDir)) {
9687
+ mkdirSync6(launchAgentsDir, { recursive: true });
8363
9688
  }
8364
- writeFileSync2(plistPath, plistContent, "utf-8");
9689
+ writeFileSync4(plistPath, plistContent, "utf-8");
8365
9690
  }
8366
9691
  } catch (e) {
8367
9692
  autoStartError = e instanceof Error ? e.message : String(e);
8368
9693
  }
8369
9694
  if (autoStartAlreadyInstalled) {
8370
- console.log(chalk.dim(" \xB7 Auto-start already configured"));
9695
+ console.log(chalk2.dim(" \xB7 Auto-start already configured"));
8371
9696
  } else if (autoStartError) {
8372
- console.log(chalk.red(` \u2717 Failed to configure auto-start: ${autoStartError}`));
9697
+ console.log(chalk2.red(` \u2717 Failed to configure auto-start: ${autoStartError}`));
8373
9698
  } else {
8374
- console.log(chalk.green(" \u2713 Auto-start configured (starts on login)"));
9699
+ console.log(chalk2.green(" \u2713 Auto-start configured (starts on login)"));
8375
9700
  }
8376
9701
  if (!autoStartAlreadyInstalled && !autoStartError) {
8377
- const plistPath2 = join3(home, "Library", "LaunchAgents", "com.hasna.mementos.plist");
9702
+ const plistPath2 = join6(home, "Library", "LaunchAgents", "com.hasna.mementos.plist");
8378
9703
  const loadResult = await run(["launchctl", "load", plistPath2]);
8379
9704
  if (!loadResult.ok) {
8380
- console.log(chalk.dim(` \xB7 launchctl load: ${loadResult.output || "already loaded"}`));
9705
+ console.log(chalk2.dim(` \xB7 launchctl load: ${loadResult.output || "already loaded"}`));
8381
9706
  }
8382
9707
  }
8383
9708
  }
@@ -8389,18 +9714,18 @@ main().catch(() => {});
8389
9714
  serverRunning = res.ok;
8390
9715
  } catch {}
8391
9716
  if (serverRunning) {
8392
- console.log(chalk.green(" \u2713 Server running on http://127.0.0.1:19428"));
9717
+ console.log(chalk2.green(" \u2713 Server running on http://127.0.0.1:19428"));
8393
9718
  } else {
8394
- console.log(chalk.dim(" \xB7 Server not yet running \u2014 it will start automatically on next login"));
8395
- console.log(chalk.dim(" (Or start it now: mementos-serve)"));
9719
+ console.log(chalk2.dim(" \xB7 Server not yet running \u2014 it will start automatically on next login"));
9720
+ console.log(chalk2.dim(" (Or start it now: mementos-serve)"));
8396
9721
  }
8397
9722
  console.log("");
8398
- console.log(chalk.bold(" You're all set. Restart Claude Code to activate."));
9723
+ console.log(chalk2.bold(" You're all set. Restart Claude Code to activate."));
8399
9724
  console.log("");
8400
9725
  console.log(" Quick start:");
8401
- console.log(` ${chalk.cyan('mementos save "my-preference" "I prefer bun over npm"')}`);
8402
- console.log(` ${chalk.cyan("mementos list")}`);
8403
- console.log(` ${chalk.cyan("mementos doctor")}`);
9726
+ console.log(` ${chalk2.cyan('mementos save "my-preference" "I prefer bun over npm"')}`);
9727
+ console.log(` ${chalk2.cyan("mementos list")}`);
9728
+ console.log(` ${chalk2.cyan("mementos doctor")}`);
8404
9729
  console.log("");
8405
9730
  });
8406
9731
  program2.command("save <key> <value>").description("Save a memory (create or upsert)").option("-c, --category <cat>", "Category: preference, fact, knowledge, history").option("-s, --scope <scope>", "Scope: global, shared, private").option("--importance <n>", "Importance 1-10", parseInt).option("--tags <tags>", "Comma-separated tags").option("--summary <text>", "Brief summary").option("--ttl <duration>", "Time-to-live: 30s, 5m, 2h, 1d, 1w, or milliseconds").option("--source <src>", "Source: user, agent, system, auto, imported").option("--template <name>", "Apply a template: correction, preference, decision, learning").action((key, value, opts) => {
@@ -8436,7 +9761,7 @@ program2.command("save <key> <value>").description("Save a memory (create or ups
8436
9761
  if (opts.template) {
8437
9762
  const tpl = templates[opts.template];
8438
9763
  if (!tpl) {
8439
- console.error(chalk.red(`Unknown template: ${opts.template}. Valid templates: ${Object.keys(templates).join(", ")}`));
9764
+ console.error(chalk2.red(`Unknown template: ${opts.template}. Valid templates: ${Object.keys(templates).join(", ")}`));
8440
9765
  process.exit(1);
8441
9766
  }
8442
9767
  templateDefaults = tpl;
@@ -8465,7 +9790,7 @@ program2.command("save <key> <value>").description("Save a memory (create or ups
8465
9790
  if (globalOpts.json) {
8466
9791
  outputJson(memory);
8467
9792
  } else {
8468
- console.log(chalk.green(`Saved: ${memory.key} (${memory.id.slice(0, 8)})`));
9793
+ console.log(chalk2.green(`Saved: ${memory.key} (${memory.id.slice(0, 8)})`));
8469
9794
  }
8470
9795
  } catch (e) {
8471
9796
  handleError(e);
@@ -8504,7 +9829,7 @@ program2.command("recall <key>").description("Recall a memory by key").option("-
8504
9829
  if (globalOpts.json) {
8505
9830
  outputJson({ fuzzy_match: true, score: best.score, match_type: best.match_type, memory: best.memory });
8506
9831
  } else {
8507
- console.log(chalk.yellow(`No exact match, showing best result (score: ${best.score.toFixed(2)}, match: ${best.match_type}):`));
9832
+ console.log(chalk2.yellow(`No exact match, showing best result (score: ${best.score.toFixed(2)}, match: ${best.match_type}):`));
8508
9833
  console.log(formatMemoryDetail(best.memory));
8509
9834
  }
8510
9835
  return;
@@ -8512,7 +9837,7 @@ program2.command("recall <key>").description("Recall a memory by key").option("-
8512
9837
  if (globalOpts.json) {
8513
9838
  outputJson({ error: `No memory found for key: ${key}` });
8514
9839
  } else {
8515
- console.error(chalk.yellow(`No memory found for key: ${key}`));
9840
+ console.error(chalk2.yellow(`No memory found for key: ${key}`));
8516
9841
  }
8517
9842
  process.exit(1);
8518
9843
  } catch (e) {
@@ -8562,10 +9887,10 @@ program2.command("list").description("List memories with optional filters").opti
8562
9887
  return;
8563
9888
  }
8564
9889
  if (memories.length === 0) {
8565
- console.log(chalk.yellow("No memories found."));
9890
+ console.log(chalk2.yellow("No memories found."));
8566
9891
  return;
8567
9892
  }
8568
- console.log(chalk.bold(`${memories.length} memor${memories.length === 1 ? "y" : "ies"}:`));
9893
+ console.log(chalk2.bold(`${memories.length} memor${memories.length === 1 ? "y" : "ies"}:`));
8569
9894
  for (const m of memories) {
8570
9895
  console.log(formatMemoryLine(m));
8571
9896
  }
@@ -8582,7 +9907,7 @@ program2.command("update <id>").description("Update a memory by ID").option("--v
8582
9907
  if (globalOpts.json) {
8583
9908
  outputJson({ error: `Memory not found: ${id}` });
8584
9909
  } else {
8585
- console.error(chalk.red(`Memory not found: ${id}`));
9910
+ console.error(chalk2.red(`Memory not found: ${id}`));
8586
9911
  }
8587
9912
  process.exit(1);
8588
9913
  }
@@ -8611,7 +9936,7 @@ program2.command("update <id>").description("Update a memory by ID").option("--v
8611
9936
  if (globalOpts.json) {
8612
9937
  outputJson(updated);
8613
9938
  } else {
8614
- console.log(chalk.green(`Updated: ${updated.key} (${updated.id.slice(0, 8)})`));
9939
+ console.log(chalk2.green(`Updated: ${updated.key} (${updated.id.slice(0, 8)})`));
8615
9940
  }
8616
9941
  } catch (e) {
8617
9942
  handleError(e);
@@ -8627,7 +9952,7 @@ program2.command("forget <keyOrId>").description("Delete a memory by key or ID")
8627
9952
  if (globalOpts.json) {
8628
9953
  outputJson({ deleted: idMatch });
8629
9954
  } else {
8630
- console.log(chalk.green(`Memory ${idMatch} deleted.`));
9955
+ console.log(chalk2.green(`Memory ${idMatch} deleted.`));
8631
9956
  }
8632
9957
  return;
8633
9958
  }
@@ -8636,7 +9961,7 @@ program2.command("forget <keyOrId>").description("Delete a memory by key or ID")
8636
9961
  if (globalOpts.json) {
8637
9962
  outputJson({ error: `No memory found: ${keyOrId}` });
8638
9963
  } else {
8639
- console.error(chalk.red(`No memory found: ${keyOrId}`));
9964
+ console.error(chalk2.red(`No memory found: ${keyOrId}`));
8640
9965
  }
8641
9966
  process.exit(1);
8642
9967
  }
@@ -8645,7 +9970,7 @@ program2.command("forget <keyOrId>").description("Delete a memory by key or ID")
8645
9970
  if (globalOpts.json) {
8646
9971
  outputJson({ deleted: matches[0].id, key: keyOrId });
8647
9972
  } else {
8648
- console.log(chalk.green(`Memory "${keyOrId}" (${matches[0].id}) deleted.`));
9973
+ console.log(chalk2.green(`Memory "${keyOrId}" (${matches[0].id}) deleted.`));
8649
9974
  }
8650
9975
  return;
8651
9976
  }
@@ -8656,7 +9981,7 @@ program2.command("forget <keyOrId>").description("Delete a memory by key or ID")
8656
9981
  if (globalOpts.json) {
8657
9982
  outputJson({ deleted: ids, key: keyOrId, count: ids.length });
8658
9983
  } else {
8659
- console.log(chalk.green(`Deleted ${ids.length} memories with key "${keyOrId}".`));
9984
+ console.log(chalk2.green(`Deleted ${ids.length} memories with key "${keyOrId}".`));
8660
9985
  }
8661
9986
  return;
8662
9987
  }
@@ -8672,7 +9997,7 @@ program2.command("forget <keyOrId>").description("Delete a memory by key or ID")
8672
9997
  }))
8673
9998
  });
8674
9999
  } else {
8675
- console.error(chalk.yellow(`Ambiguous: ${matches.length} memories match key "${keyOrId}":
10000
+ console.error(chalk2.yellow(`Ambiguous: ${matches.length} memories match key "${keyOrId}":
8676
10001
  `));
8677
10002
  for (const m of matches) {
8678
10003
  const parts = [
@@ -8684,7 +10009,7 @@ program2.command("forget <keyOrId>").description("Delete a memory by key or ID")
8684
10009
  ].filter(Boolean).join(" ");
8685
10010
  console.error(parts);
8686
10011
  }
8687
- console.error(chalk.cyan(`
10012
+ console.error(chalk2.cyan(`
8688
10013
  Use the full ID, or narrow with --scope, --agent, --project, or --all.`));
8689
10014
  }
8690
10015
  process.exit(1);
@@ -8702,12 +10027,12 @@ program2.command("search <query>").description("Full-text search across memories
8702
10027
  return;
8703
10028
  }
8704
10029
  if (history.length === 0) {
8705
- console.log(chalk.yellow("No search history."));
10030
+ console.log(chalk2.yellow("No search history."));
8706
10031
  return;
8707
10032
  }
8708
- console.log(chalk.bold("Recent searches:"));
10033
+ console.log(chalk2.bold("Recent searches:"));
8709
10034
  for (const h of history) {
8710
- console.log(` ${chalk.cyan(h.query)} ${chalk.dim(`(${h.result_count} results, ${h.created_at})`)}`);
10035
+ console.log(` ${chalk2.cyan(h.query)} ${chalk2.dim(`(${h.result_count} results, ${h.created_at})`)}`);
8711
10036
  }
8712
10037
  return;
8713
10038
  }
@@ -8719,12 +10044,12 @@ program2.command("search <query>").description("Full-text search across memories
8719
10044
  return;
8720
10045
  }
8721
10046
  if (popular.length === 0) {
8722
- console.log(chalk.yellow("No search history."));
10047
+ console.log(chalk2.yellow("No search history."));
8723
10048
  return;
8724
10049
  }
8725
- console.log(chalk.bold("Popular searches:"));
10050
+ console.log(chalk2.bold("Popular searches:"));
8726
10051
  for (const p of popular) {
8727
- console.log(` ${chalk.cyan(p.query)} ${chalk.dim(`(${p.count} times)`)}`);
10052
+ console.log(` ${chalk2.cyan(p.query)} ${chalk2.dim(`(${p.count} times)`)}`);
8728
10053
  }
8729
10054
  return;
8730
10055
  }
@@ -8771,16 +10096,16 @@ program2.command("search <query>").description("Full-text search across memories
8771
10096
  return;
8772
10097
  }
8773
10098
  if (results.length === 0) {
8774
- console.log(chalk.yellow(`No memories found matching "${query}".`));
10099
+ console.log(chalk2.yellow(`No memories found matching "${query}".`));
8775
10100
  return;
8776
10101
  }
8777
- console.log(chalk.bold(`${results.length} result${results.length === 1 ? "" : "s"} for "${query}":`));
10102
+ console.log(chalk2.bold(`${results.length} result${results.length === 1 ? "" : "s"} for "${query}":`));
8778
10103
  for (const r of results) {
8779
- const score = chalk.dim(`(score: ${r.score.toFixed(1)})`);
10104
+ const score = chalk2.dim(`(score: ${r.score.toFixed(1)})`);
8780
10105
  console.log(`${formatMemoryLine(r.memory)} ${score}`);
8781
10106
  if (r.highlights && r.highlights.length > 0) {
8782
10107
  for (const h of r.highlights) {
8783
- console.log(chalk.dim(` ${h.field}: ${h.snippet}`));
10108
+ console.log(chalk2.dim(` ${h.field}: ${h.snippet}`));
8784
10109
  }
8785
10110
  }
8786
10111
  }
@@ -8849,16 +10174,16 @@ program2.command("stats").description("Show memory statistics").option("--format
8849
10174
  console.log(`by_agent,${k},${v}`);
8850
10175
  return;
8851
10176
  }
8852
- console.log(chalk.bold("Memory Statistics"));
8853
- console.log(`${chalk.bold("Total active:")} ${chalk.white(String(total))}`);
8854
- console.log(`${chalk.bold("By scope:")} ${chalk.cyan("global")}=${stats.by_scope.global} ${chalk.yellow("shared")}=${stats.by_scope.shared} ${chalk.magenta("private")}=${stats.by_scope.private} ${chalk.dim("working")}=${stats.by_scope.working}`);
8855
- console.log(`${chalk.bold("By category:")} ${chalk.blue("preference")}=${stats.by_category.preference} ${chalk.green("fact")}=${stats.by_category.fact} ${chalk.yellow("knowledge")}=${stats.by_category.knowledge} ${chalk.gray("history")}=${stats.by_category.history}`);
8856
- console.log(`${chalk.bold("By status:")} active=${stats.by_status.active} archived=${stats.by_status.archived} expired=${stats.by_status.expired}`);
8857
- console.log(`${chalk.bold("Pinned:")} ${stats.pinned_count}`);
8858
- console.log(`${chalk.bold("Expired:")} ${stats.expired_count}`);
10177
+ console.log(chalk2.bold("Memory Statistics"));
10178
+ console.log(`${chalk2.bold("Total active:")} ${chalk2.white(String(total))}`);
10179
+ console.log(`${chalk2.bold("By scope:")} ${chalk2.cyan("global")}=${stats.by_scope.global} ${chalk2.yellow("shared")}=${stats.by_scope.shared} ${chalk2.magenta("private")}=${stats.by_scope.private} ${chalk2.dim("working")}=${stats.by_scope.working}`);
10180
+ console.log(`${chalk2.bold("By category:")} ${chalk2.blue("preference")}=${stats.by_category.preference} ${chalk2.green("fact")}=${stats.by_category.fact} ${chalk2.yellow("knowledge")}=${stats.by_category.knowledge} ${chalk2.gray("history")}=${stats.by_category.history}`);
10181
+ console.log(`${chalk2.bold("By status:")} active=${stats.by_status.active} archived=${stats.by_status.archived} expired=${stats.by_status.expired}`);
10182
+ console.log(`${chalk2.bold("Pinned:")} ${stats.pinned_count}`);
10183
+ console.log(`${chalk2.bold("Expired:")} ${stats.expired_count}`);
8859
10184
  if (Object.keys(stats.by_agent).length > 0) {
8860
10185
  const agentParts = Object.entries(stats.by_agent).map(([k, v]) => `${k}=${v}`).join(" ");
8861
- console.log(`${chalk.bold("By agent:")} ${agentParts}`);
10186
+ console.log(`${chalk2.bold("By agent:")} ${agentParts}`);
8862
10187
  }
8863
10188
  } catch (e) {
8864
10189
  handleError(e);
@@ -8923,30 +10248,30 @@ program2.command("report").description("Rich summary of memory activity and top
8923
10248
  const maxC = Math.max(...activityRows.map((x) => x.cnt), 1);
8924
10249
  return bars[Math.round(r.cnt / maxC * 7)] || "\u2581";
8925
10250
  }).join("");
8926
- console.log(chalk.bold(`
10251
+ console.log(chalk2.bold(`
8927
10252
  mementos report \u2014 last ${days} days
8928
10253
  `));
8929
- console.log(` ${chalk.cyan("Total:")} ${total} memories (${chalk.yellow(String(pinned))} pinned)`);
8930
- console.log(` ${chalk.cyan("Recent:")} ${recentTotal} new \xB7 ${chalk.dim(`~${avgPerDay}/day`)}`);
8931
- console.log(` ${chalk.cyan("Activity:")} ${sparkline || chalk.dim("no activity")}`);
8932
- console.log(` ${chalk.cyan("Scopes:")} global=${byScope["global"] || 0} shared=${byScope["shared"] || 0} private=${byScope["private"] || 0}`);
8933
- console.log(` ${chalk.cyan("Categories:")} knowledge=${byCat["knowledge"] || 0} fact=${byCat["fact"] || 0} preference=${byCat["preference"] || 0} history=${byCat["history"] || 0}`);
10254
+ console.log(` ${chalk2.cyan("Total:")} ${total} memories (${chalk2.yellow(String(pinned))} pinned)`);
10255
+ console.log(` ${chalk2.cyan("Recent:")} ${recentTotal} new \xB7 ${chalk2.dim(`~${avgPerDay}/day`)}`);
10256
+ console.log(` ${chalk2.cyan("Activity:")} ${sparkline || chalk2.dim("no activity")}`);
10257
+ console.log(` ${chalk2.cyan("Scopes:")} global=${byScope["global"] || 0} shared=${byScope["shared"] || 0} private=${byScope["private"] || 0}`);
10258
+ console.log(` ${chalk2.cyan("Categories:")} knowledge=${byCat["knowledge"] || 0} fact=${byCat["fact"] || 0} preference=${byCat["preference"] || 0} history=${byCat["history"] || 0}`);
8934
10259
  if (topMems.length > 0) {
8935
10260
  console.log(`
8936
- ${chalk.bold("Top memories by importance:")}`);
10261
+ ${chalk2.bold("Top memories by importance:")}`);
8937
10262
  topMems.forEach((m) => {
8938
- console.log(` ${chalk.green(`[${m.importance}]`)} ${chalk.bold(m.key)} ${chalk.dim(`(${m.scope}/${m.category})`)}`);
10263
+ console.log(` ${chalk2.green(`[${m.importance}]`)} ${chalk2.bold(m.key)} ${chalk2.dim(`(${m.scope}/${m.category})`)}`);
8939
10264
  console.log(` ${m.value.slice(0, 90)}${m.value.length > 90 ? "..." : ""}`);
8940
10265
  });
8941
10266
  }
8942
10267
  if (topAgents.length > 0) {
8943
10268
  console.log(`
8944
- ${chalk.bold("Top agents:")}`);
10269
+ ${chalk2.bold("Top agents:")}`);
8945
10270
  topAgents.forEach((a) => console.log(` ${a.agent_id}: ${a.c} memories`));
8946
10271
  }
8947
10272
  console.log("");
8948
10273
  } catch (e) {
8949
- console.error(chalk.red(`report failed: ${e instanceof Error ? e.message : String(e)}`));
10274
+ console.error(chalk2.red(`report failed: ${e instanceof Error ? e.message : String(e)}`));
8950
10275
  process.exit(1);
8951
10276
  }
8952
10277
  });
@@ -8991,21 +10316,21 @@ program2.command("stale").description("Find memories not accessed recently (for
8991
10316
  return;
8992
10317
  }
8993
10318
  if (rows.length === 0) {
8994
- console.log(chalk.green(`No stale memories (not accessed in ${days}+ days).`));
10319
+ console.log(chalk2.green(`No stale memories (not accessed in ${days}+ days).`));
8995
10320
  return;
8996
10321
  }
8997
- console.log(chalk.bold(`
10322
+ console.log(chalk2.bold(`
8998
10323
  Stale memories (not accessed in ${days}+ days):
8999
10324
  `));
9000
10325
  for (const m of rows) {
9001
- const lastAccess = m.accessed_at ? m.accessed_at.slice(0, 10) : chalk.dim("never");
9002
- console.log(` ${chalk.dim(`[${m.importance}]`)} ${chalk.bold(m.key)} ${chalk.dim(`(${m.scope}/${m.category})`)}`);
10326
+ const lastAccess = m.accessed_at ? m.accessed_at.slice(0, 10) : chalk2.dim("never");
10327
+ console.log(` ${chalk2.dim(`[${m.importance}]`)} ${chalk2.bold(m.key)} ${chalk2.dim(`(${m.scope}/${m.category})`)}`);
9003
10328
  console.log(` Last accessed: ${lastAccess} \xB7 ${m.access_count} reads \xB7 ${m.value.slice(0, 80)}${m.value.length > 80 ? "..." : ""}`);
9004
10329
  }
9005
10330
  console.log(`
9006
- ${chalk.dim(`${rows.length} result(s). Run 'mementos archive <key>' or 'mementos forget <key>' to clean up.`)}`);
10331
+ ${chalk2.dim(`${rows.length} result(s). Run 'mementos archive <key>' or 'mementos forget <key>' to clean up.`)}`);
9007
10332
  } catch (e) {
9008
- console.error(chalk.red(`stale failed: ${e instanceof Error ? e.message : String(e)}`));
10333
+ console.error(chalk2.red(`stale failed: ${e instanceof Error ? e.message : String(e)}`));
9009
10334
  process.exit(1);
9010
10335
  }
9011
10336
  });
@@ -9040,9 +10365,9 @@ program2.command("import [file]").description("Import memories from a JSON file
9040
10365
  if (file === "-" || !file && !process.stdin.isTTY) {
9041
10366
  raw = await Bun.stdin.text();
9042
10367
  } else if (file) {
9043
- raw = readFileSync2(resolve3(file), "utf-8");
10368
+ raw = readFileSync3(resolve3(file), "utf-8");
9044
10369
  } else {
9045
- console.error(chalk.red("No input: provide a file path, use '-' for stdin, or pipe data."));
10370
+ console.error(chalk2.red("No input: provide a file path, use '-' for stdin, or pipe data."));
9046
10371
  process.exit(1);
9047
10372
  }
9048
10373
  const memories = JSON.parse(raw);
@@ -9058,7 +10383,7 @@ program2.command("import [file]").description("Import memories from a JSON file
9058
10383
  if (globalOpts.json) {
9059
10384
  outputJson({ imported });
9060
10385
  } else {
9061
- console.log(chalk.green(`Imported ${imported} memor${imported === 1 ? "y" : "ies"}.`));
10386
+ console.log(chalk2.green(`Imported ${imported} memor${imported === 1 ? "y" : "ies"}.`));
9062
10387
  }
9063
10388
  } catch (e) {
9064
10389
  handleError(e);
@@ -9072,12 +10397,12 @@ program2.command("clean").description("Remove expired memories and enforce quota
9072
10397
  if (globalOpts.json) {
9073
10398
  outputJson(result);
9074
10399
  } else {
9075
- console.log(chalk.bold("Cleanup complete:"));
9076
- console.log(` Expired removed: ${chalk.red(String(result.expired))}`);
9077
- console.log(` Evicted (quota): ${chalk.yellow(String(result.evicted))}`);
9078
- console.log(` Archived (stale): ${chalk.gray(String(result.archived))}`);
9079
- console.log(` Archived (unused): ${chalk.gray(String(result.unused_archived))}`);
9080
- console.log(` Deprioritized: ${chalk.blue(String(result.deprioritized))}`);
10400
+ console.log(chalk2.bold("Cleanup complete:"));
10401
+ console.log(` Expired removed: ${chalk2.red(String(result.expired))}`);
10402
+ console.log(` Evicted (quota): ${chalk2.yellow(String(result.evicted))}`);
10403
+ console.log(` Archived (stale): ${chalk2.gray(String(result.archived))}`);
10404
+ console.log(` Archived (unused): ${chalk2.gray(String(result.unused_archived))}`);
10405
+ console.log(` Deprioritized: ${chalk2.blue(String(result.deprioritized))}`);
9081
10406
  }
9082
10407
  } catch (e) {
9083
10408
  handleError(e);
@@ -9090,11 +10415,11 @@ program2.command("register-agent <name>").alias("init-agent").description("Regis
9090
10415
  if (globalOpts.json) {
9091
10416
  outputJson(agent);
9092
10417
  } else {
9093
- console.log(chalk.green("Agent registered:"));
9094
- console.log(` ${chalk.bold("ID:")} ${agent.id}`);
9095
- console.log(` ${chalk.bold("Name:")} ${agent.name}`);
9096
- console.log(` ${chalk.bold("Role:")} ${agent.role || "agent"}`);
9097
- console.log(` ${chalk.bold("Created:")} ${agent.created_at}`);
10418
+ console.log(chalk2.green("Agent registered:"));
10419
+ console.log(` ${chalk2.bold("ID:")} ${agent.id}`);
10420
+ console.log(` ${chalk2.bold("Name:")} ${agent.name}`);
10421
+ console.log(` ${chalk2.bold("Role:")} ${agent.role || "agent"}`);
10422
+ console.log(` ${chalk2.bold("Created:")} ${agent.created_at}`);
9098
10423
  }
9099
10424
  } catch (e) {
9100
10425
  handleError(e);
@@ -9109,12 +10434,12 @@ program2.command("agents").description("List all registered agents").action(() =
9109
10434
  return;
9110
10435
  }
9111
10436
  if (agents.length === 0) {
9112
- console.log(chalk.yellow("No agents registered."));
10437
+ console.log(chalk2.yellow("No agents registered."));
9113
10438
  return;
9114
10439
  }
9115
- console.log(chalk.bold(`${agents.length} agent${agents.length === 1 ? "" : "s"}:`));
10440
+ console.log(chalk2.bold(`${agents.length} agent${agents.length === 1 ? "" : "s"}:`));
9116
10441
  for (const a of agents) {
9117
- console.log(` ${chalk.dim(a.id)} ${chalk.bold(a.name)} ${chalk.gray(a.role || "agent")} ${chalk.dim(`last seen: ${a.last_seen_at}`)}`);
10442
+ console.log(` ${chalk2.dim(a.id)} ${chalk2.bold(a.name)} ${chalk2.gray(a.role || "agent")} ${chalk2.dim(`last seen: ${a.last_seen_at}`)}`);
9118
10443
  }
9119
10444
  } catch (e) {
9120
10445
  handleError(e);
@@ -9134,7 +10459,7 @@ program2.command("agent-update <id>").description("Update an agent's name, descr
9134
10459
  if (globalOpts.json) {
9135
10460
  outputJson({ error: "No updates provided. Use --name, --description, or --role." });
9136
10461
  } else {
9137
- console.error(chalk.red("No updates provided. Use --name, --description, or --role."));
10462
+ console.error(chalk2.red("No updates provided. Use --name, --description, or --role."));
9138
10463
  }
9139
10464
  process.exit(1);
9140
10465
  }
@@ -9143,19 +10468,19 @@ program2.command("agent-update <id>").description("Update an agent's name, descr
9143
10468
  if (globalOpts.json) {
9144
10469
  outputJson({ error: `Agent not found: ${id}` });
9145
10470
  } else {
9146
- console.error(chalk.red(`Agent not found: ${id}`));
10471
+ console.error(chalk2.red(`Agent not found: ${id}`));
9147
10472
  }
9148
10473
  process.exit(1);
9149
10474
  }
9150
10475
  if (globalOpts.json) {
9151
10476
  outputJson(agent);
9152
10477
  } else {
9153
- console.log(chalk.green("Agent updated:"));
9154
- console.log(` ${chalk.bold("ID:")} ${agent.id}`);
9155
- console.log(` ${chalk.bold("Name:")} ${agent.name}`);
9156
- console.log(` ${chalk.bold("Description:")} ${agent.description || "-"}`);
9157
- console.log(` ${chalk.bold("Role:")} ${agent.role || "agent"}`);
9158
- console.log(` ${chalk.bold("Last seen:")} ${agent.last_seen_at}`);
10478
+ console.log(chalk2.green("Agent updated:"));
10479
+ console.log(` ${chalk2.bold("ID:")} ${agent.id}`);
10480
+ console.log(` ${chalk2.bold("Name:")} ${agent.name}`);
10481
+ console.log(` ${chalk2.bold("Description:")} ${agent.description || "-"}`);
10482
+ console.log(` ${chalk2.bold("Role:")} ${agent.role || "agent"}`);
10483
+ console.log(` ${chalk2.bold("Last seen:")} ${agent.last_seen_at}`);
9159
10484
  }
9160
10485
  } catch (e) {
9161
10486
  handleError(e);
@@ -9168,17 +10493,17 @@ program2.command("projects").description("Manage projects").option("--add", "Add
9168
10493
  const name = opts.name;
9169
10494
  const path = opts.path;
9170
10495
  if (!name || !path) {
9171
- console.error(chalk.red("--name and --path are required when adding a project"));
10496
+ console.error(chalk2.red("--name and --path are required when adding a project"));
9172
10497
  process.exit(1);
9173
10498
  }
9174
10499
  const project = registerProject(name, resolve3(path), opts.description);
9175
10500
  if (globalOpts.json) {
9176
10501
  outputJson(project);
9177
10502
  } else {
9178
- console.log(chalk.green("Project registered:"));
9179
- console.log(` ${chalk.bold("ID:")} ${project.id}`);
9180
- console.log(` ${chalk.bold("Name:")} ${project.name}`);
9181
- console.log(` ${chalk.bold("Path:")} ${project.path}`);
10503
+ console.log(chalk2.green("Project registered:"));
10504
+ console.log(` ${chalk2.bold("ID:")} ${project.id}`);
10505
+ console.log(` ${chalk2.bold("Name:")} ${project.name}`);
10506
+ console.log(` ${chalk2.bold("Path:")} ${project.path}`);
9182
10507
  }
9183
10508
  return;
9184
10509
  }
@@ -9188,12 +10513,12 @@ program2.command("projects").description("Manage projects").option("--add", "Add
9188
10513
  return;
9189
10514
  }
9190
10515
  if (projects.length === 0) {
9191
- console.log(chalk.yellow("No projects registered."));
10516
+ console.log(chalk2.yellow("No projects registered."));
9192
10517
  return;
9193
10518
  }
9194
- console.log(chalk.bold(`${projects.length} project${projects.length === 1 ? "" : "s"}:`));
10519
+ console.log(chalk2.bold(`${projects.length} project${projects.length === 1 ? "" : "s"}:`));
9195
10520
  for (const p of projects) {
9196
- console.log(` ${chalk.dim(p.id.slice(0, 8))} ${chalk.bold(p.name)} ${chalk.gray(p.path)}${p.description ? chalk.dim(` \u2014 ${p.description}`) : ""}`);
10521
+ console.log(` ${chalk2.dim(p.id.slice(0, 8))} ${chalk2.bold(p.name)} ${chalk2.gray(p.path)}${p.description ? chalk2.dim(` \u2014 ${p.description}`) : ""}`);
9197
10522
  }
9198
10523
  } catch (e) {
9199
10524
  handleError(e);
@@ -9283,7 +10608,7 @@ program2.command("inject").description("Output injection context for agent syste
9283
10608
  if (globalOpts.json) {
9284
10609
  outputJson({ context: "", count: 0 });
9285
10610
  } else {
9286
- console.log(chalk.yellow("No relevant memories found for injection."));
10611
+ console.log(chalk2.yellow("No relevant memories found for injection."));
9287
10612
  }
9288
10613
  return;
9289
10614
  }
@@ -9323,7 +10648,7 @@ program2.command("bulk <action> <ids...>").description("Batch operations: forget
9323
10648
  "unpin"
9324
10649
  ];
9325
10650
  if (!validActions.includes(action)) {
9326
- console.error(chalk.red(`Invalid action: ${action}. Valid: ${validActions.join(", ")}`));
10651
+ console.error(chalk2.red(`Invalid action: ${action}. Valid: ${validActions.join(", ")}`));
9327
10652
  process.exit(1);
9328
10653
  }
9329
10654
  const resolvedIds = ids.map((id) => resolveMemoryId(id));
@@ -9376,7 +10701,7 @@ program2.command("bulk <action> <ids...>").description("Batch operations: forget
9376
10701
  if (globalOpts.json) {
9377
10702
  outputJson({ action, affected, ids: resolvedIds });
9378
10703
  } else {
9379
- console.log(chalk.green(`${action}: ${affected} memor${affected === 1 ? "y" : "ies"} affected.`));
10704
+ console.log(chalk2.green(`${action}: ${affected} memor${affected === 1 ? "y" : "ies"} affected.`));
9380
10705
  }
9381
10706
  } catch (e) {
9382
10707
  handleError(e);
@@ -9389,7 +10714,7 @@ program2.command("doctor").description("Diagnose common issues with the mementos
9389
10714
  checks.push({ name: "Version", status: "ok", detail: version });
9390
10715
  const dbPath = getDbPath();
9391
10716
  let db = null;
9392
- if (dbPath !== ":memory:" && existsSync3(dbPath)) {
10717
+ if (dbPath !== ":memory:" && existsSync6(dbPath)) {
9393
10718
  try {
9394
10719
  accessSync(dbPath, fsConstants.R_OK | fsConstants.W_OK);
9395
10720
  checks.push({ name: "Database file", status: "ok", detail: dbPath });
@@ -9408,7 +10733,7 @@ program2.command("doctor").description("Diagnose common issues with the mementos
9408
10733
  checks.push({ name: "Database connection", status: "fail", detail: e instanceof Error ? e.message : String(e) });
9409
10734
  }
9410
10735
  try {
9411
- if (dbPath !== ":memory:" && existsSync3(dbPath)) {
10736
+ if (dbPath !== ":memory:" && existsSync6(dbPath)) {
9412
10737
  const stats = statSync(dbPath);
9413
10738
  const sizeKb = (stats.size / 1024).toFixed(1);
9414
10739
  const sizeMb = (stats.size / (1024 * 1024)).toFixed(2);
@@ -9446,14 +10771,14 @@ program2.command("doctor").description("Diagnose common issues with the mementos
9446
10771
  const byScope = {};
9447
10772
  let expiredCount = 0;
9448
10773
  let staleCount = 0;
9449
- const now2 = Date.now();
10774
+ const now3 = Date.now();
9450
10775
  const staleThreshold = 14 * 24 * 60 * 60 * 1000;
9451
10776
  for (const m of all) {
9452
10777
  byScope[m.scope] = (byScope[m.scope] || 0) + 1;
9453
10778
  if (m.status === "expired")
9454
10779
  expiredCount++;
9455
10780
  const lastAccess = m.accessed_at ? new Date(m.accessed_at).getTime() : new Date(m.created_at).getTime();
9456
- if (now2 - lastAccess > staleThreshold && m.status === "active") {
10781
+ if (now3 - lastAccess > staleThreshold && m.status === "active") {
9457
10782
  staleCount++;
9458
10783
  }
9459
10784
  }
@@ -9544,9 +10869,9 @@ program2.command("doctor").description("Diagnose common issues with the mementos
9544
10869
  checks.push({ name: "MCP server", status: "warn", detail: "could not check (is claude CLI installed?)" });
9545
10870
  }
9546
10871
  try {
9547
- const settingsFilePath = join3(homedir2(), ".claude", "settings.json");
9548
- if (existsSync3(settingsFilePath)) {
9549
- const settings = JSON.parse(readFileSync2(settingsFilePath, "utf-8"));
10872
+ const settingsFilePath = join6(homedir4(), ".claude", "settings.json");
10873
+ if (existsSync6(settingsFilePath)) {
10874
+ const settings = JSON.parse(readFileSync3(settingsFilePath, "utf-8"));
9550
10875
  const hooksObj = settings["hooks"] || {};
9551
10876
  const stopHooks = hooksObj["Stop"] || [];
9552
10877
  const hasMementos = stopHooks.some((e) => e.hooks?.some((h) => h.command && h.command.includes("mementos")));
@@ -9562,11 +10887,11 @@ program2.command("doctor").description("Diagnose common issues with the mementos
9562
10887
  checks.push({ name: "Stop hook", status: "warn", detail: "could not check stop hook" });
9563
10888
  }
9564
10889
  if (process.platform === "darwin") {
9565
- const plistFilePath = join3(homedir2(), "Library", "LaunchAgents", "com.hasna.mementos.plist");
10890
+ const plistFilePath = join6(homedir4(), "Library", "LaunchAgents", "com.hasna.mementos.plist");
9566
10891
  checks.push({
9567
10892
  name: "Auto-start",
9568
- status: existsSync3(plistFilePath) ? "ok" : "warn",
9569
- detail: existsSync3(plistFilePath) ? "configured (starts on login)" : "not configured \u2192 run: mementos init"
10893
+ status: existsSync6(plistFilePath) ? "ok" : "warn",
10894
+ detail: existsSync6(plistFilePath) ? "configured (starts on login)" : "not configured \u2192 run: mementos init"
9570
10895
  });
9571
10896
  } else {
9572
10897
  checks.push({ name: "Auto-start", status: "ok", detail: `n/a on ${process.platform}` });
@@ -9577,24 +10902,24 @@ function outputDoctorResults(globalOpts, checks) {
9577
10902
  if (globalOpts.json) {
9578
10903
  outputJson({ checks, healthy: checks.every((c) => c.status === "ok") });
9579
10904
  } else {
9580
- console.log(chalk.bold(`
10905
+ console.log(chalk2.bold(`
9581
10906
  mementos doctor
9582
10907
  `));
9583
10908
  for (const check of checks) {
9584
- const icon = check.status === "ok" ? chalk.green("\u2713") : check.status === "warn" ? chalk.yellow("\u26A0") : chalk.red("\u2717");
9585
- console.log(` ${icon} ${chalk.bold(check.name)}: ${check.detail}`);
10909
+ const icon = check.status === "ok" ? chalk2.green("\u2713") : check.status === "warn" ? chalk2.yellow("\u26A0") : chalk2.red("\u2717");
10910
+ console.log(` ${icon} ${chalk2.bold(check.name)}: ${check.detail}`);
9586
10911
  }
9587
10912
  const healthy = checks.every((c) => c.status === "ok");
9588
10913
  const warnings = checks.filter((c) => c.status === "warn").length;
9589
10914
  const failures = checks.filter((c) => c.status === "fail").length;
9590
10915
  console.log("");
9591
10916
  if (healthy) {
9592
- console.log(chalk.green(" All checks passed."));
10917
+ console.log(chalk2.green(" All checks passed."));
9593
10918
  } else {
9594
10919
  if (failures > 0)
9595
- console.log(chalk.red(` ${failures} check(s) failed.`));
10920
+ console.log(chalk2.red(` ${failures} check(s) failed.`));
9596
10921
  if (warnings > 0)
9597
- console.log(chalk.yellow(` ${warnings} warning(s).`));
10922
+ console.log(chalk2.yellow(` ${warnings} warning(s).`));
9598
10923
  }
9599
10924
  console.log("");
9600
10925
  }
@@ -9608,7 +10933,7 @@ program2.command("show <id>").description("Show full detail of a memory by ID (s
9608
10933
  if (globalOpts.json) {
9609
10934
  outputJson({ error: `Memory not found: ${id}` });
9610
10935
  } else {
9611
- console.error(chalk.red(`Memory not found: ${id}`));
10936
+ console.error(chalk2.red(`Memory not found: ${id}`));
9612
10937
  }
9613
10938
  process.exit(1);
9614
10939
  }
@@ -9634,24 +10959,24 @@ program2.command("history").description("List memories sorted by most recently a
9634
10959
  return;
9635
10960
  }
9636
10961
  if (memories.length === 0) {
9637
- console.log(chalk.yellow("No recently accessed memories."));
10962
+ console.log(chalk2.yellow("No recently accessed memories."));
9638
10963
  return;
9639
10964
  }
9640
- console.log(chalk.bold(`${memories.length} recently accessed memor${memories.length === 1 ? "y" : "ies"}:`));
10965
+ console.log(chalk2.bold(`${memories.length} recently accessed memor${memories.length === 1 ? "y" : "ies"}:`));
9641
10966
  for (const m of memories) {
9642
- const id = chalk.dim(m.id.slice(0, 8));
10967
+ const id = chalk2.dim(m.id.slice(0, 8));
9643
10968
  const scope = colorScope(m.scope);
9644
10969
  const cat = colorCategory(m.category);
9645
10970
  const value = m.value.length > 60 ? m.value.slice(0, 60) + "..." : m.value;
9646
- const accessed = m.accessed_at ? chalk.dim(m.accessed_at) : chalk.dim("never");
9647
- console.log(`${id} [${scope}/${cat}] ${chalk.bold(m.key)} = ${value} ${accessed}`);
10971
+ const accessed = m.accessed_at ? chalk2.dim(m.accessed_at) : chalk2.dim("never");
10972
+ console.log(`${id} [${scope}/${cat}] ${chalk2.bold(m.key)} = ${value} ${accessed}`);
9648
10973
  }
9649
10974
  } catch (e) {
9650
10975
  handleError(e);
9651
10976
  }
9652
10977
  });
9653
10978
  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) => {
9654
- const { readFileSync: readFileSync3, writeFileSync: writeFileSync3, existsSync: fileExists } = __require("fs");
10979
+ const { readFileSync: readFileSync4, writeFileSync: writeFileSync5, existsSync: fileExists } = __require("fs");
9655
10980
  const { join: pathJoin } = __require("path");
9656
10981
  const { homedir: getHome } = __require("os");
9657
10982
  const home = getHome();
@@ -9662,8 +10987,8 @@ program2.command("mcp").description("Install mementos MCP server into Claude Cod
9662
10987
  opts.gemini ? "gemini" : null
9663
10988
  ].filter(Boolean);
9664
10989
  if (targets.length === 0) {
9665
- console.log(chalk.yellow("Specify a target: --claude, --codex, --gemini, or --all"));
9666
- console.log(chalk.gray("Example: mementos mcp --all"));
10990
+ console.log(chalk2.yellow("Specify a target: --claude, --codex, --gemini, or --all"));
10991
+ console.log(chalk2.gray("Example: mementos mcp --all"));
9667
10992
  return;
9668
10993
  }
9669
10994
  for (const target of targets) {
@@ -9673,25 +10998,25 @@ program2.command("mcp").description("Install mementos MCP server into Claude Cod
9673
10998
  if (opts.uninstall) {
9674
10999
  try {
9675
11000
  execSync(`claude mcp remove mementos`, { stdio: "pipe" });
9676
- console.log(chalk.green("Removed mementos from Claude Code MCP"));
11001
+ console.log(chalk2.green("Removed mementos from Claude Code MCP"));
9677
11002
  } catch {
9678
- console.log(chalk.yellow("mementos was not installed in Claude Code (or claude CLI not found)"));
11003
+ console.log(chalk2.yellow("mementos was not installed in Claude Code (or claude CLI not found)"));
9679
11004
  }
9680
11005
  } else {
9681
11006
  try {
9682
11007
  execSync(`claude mcp add --transport stdio --scope user mementos -- ${mementosCmd}`, { stdio: "pipe" });
9683
- console.log(chalk.green(`Installed mementos into Claude Code (user scope)`));
9684
- console.log(chalk.gray(" Restart Claude Code for the change to take effect."));
11008
+ console.log(chalk2.green(`Installed mementos into Claude Code (user scope)`));
11009
+ console.log(chalk2.gray(" Restart Claude Code for the change to take effect."));
9685
11010
  } catch (e) {
9686
- console.log(chalk.yellow("claude CLI not found. Run this manually:"));
9687
- console.log(chalk.white(` claude mcp add --transport stdio --scope user mementos -- ${mementosCmd}`));
11011
+ console.log(chalk2.yellow("claude CLI not found. Run this manually:"));
11012
+ console.log(chalk2.white(` claude mcp add --transport stdio --scope user mementos -- ${mementosCmd}`));
9688
11013
  }
9689
11014
  }
9690
11015
  }
9691
11016
  if (target === "codex") {
9692
11017
  const configPath = pathJoin(home, ".codex", "config.toml");
9693
11018
  if (fileExists(configPath)) {
9694
- let content = readFileSync3(configPath, "utf-8");
11019
+ let content = readFileSync4(configPath, "utf-8");
9695
11020
  if (opts.uninstall) {
9696
11021
  content = content.replace(/\n\[mcp_servers\.mementos\]\ncommand = "[^"]*"\nargs = \[\]\n?/g, `
9697
11022
  `);
@@ -9702,17 +11027,17 @@ command = "${mementosCmd}"
9702
11027
  args = []
9703
11028
  `;
9704
11029
  }
9705
- writeFileSync3(configPath, content, "utf-8");
9706
- console.log(chalk.green(`${opts.uninstall ? "Removed from" : "Installed into"} Codex: ${configPath}`));
11030
+ writeFileSync5(configPath, content, "utf-8");
11031
+ console.log(chalk2.green(`${opts.uninstall ? "Removed from" : "Installed into"} Codex: ${configPath}`));
9707
11032
  } else {
9708
- console.log(chalk.yellow(`Codex config not found: ${configPath}`));
11033
+ console.log(chalk2.yellow(`Codex config not found: ${configPath}`));
9709
11034
  }
9710
11035
  }
9711
11036
  if (target === "gemini") {
9712
11037
  const configPath = pathJoin(home, ".gemini", "settings.json");
9713
11038
  let config = {};
9714
11039
  if (fileExists(configPath)) {
9715
- config = JSON.parse(readFileSync3(configPath, "utf-8"));
11040
+ config = JSON.parse(readFileSync4(configPath, "utf-8"));
9716
11041
  }
9717
11042
  const servers = config["mcpServers"] || {};
9718
11043
  if (opts.uninstall) {
@@ -9721,12 +11046,12 @@ args = []
9721
11046
  servers["mementos"] = { command: mementosCmd, args: [] };
9722
11047
  }
9723
11048
  config["mcpServers"] = servers;
9724
- writeFileSync3(configPath, JSON.stringify(config, null, 2) + `
11049
+ writeFileSync5(configPath, JSON.stringify(config, null, 2) + `
9725
11050
  `, "utf-8");
9726
- console.log(chalk.green(`${opts.uninstall ? "Removed from" : "Installed into"} Gemini: ${configPath}`));
11051
+ console.log(chalk2.green(`${opts.uninstall ? "Removed from" : "Installed into"} Gemini: ${configPath}`));
9727
11052
  }
9728
11053
  } catch (e) {
9729
- console.error(chalk.red(`Failed for ${target}: ${e instanceof Error ? e.message : String(e)}`));
11054
+ console.error(chalk2.red(`Failed for ${target}: ${e instanceof Error ? e.message : String(e)}`));
9730
11055
  }
9731
11056
  }
9732
11057
  });
@@ -9742,20 +11067,20 @@ program2.command("watch").description("Watch for new and changed memories in rea
9742
11067
  projectId = project.id;
9743
11068
  }
9744
11069
  const intervalMs = opts.interval || 500;
9745
- console.log(chalk.bold.cyan("Watching memories...") + chalk.dim(" (Ctrl+C to stop)"));
11070
+ console.log(chalk2.bold.cyan("Watching memories...") + chalk2.dim(" (Ctrl+C to stop)"));
9746
11071
  const filters = [];
9747
11072
  if (opts.scope)
9748
11073
  filters.push(`scope=${colorScope(opts.scope)}`);
9749
11074
  if (opts.category)
9750
11075
  filters.push(`category=${colorCategory(opts.category)}`);
9751
11076
  if (agentId)
9752
- filters.push(`agent=${chalk.dim(agentId)}`);
11077
+ filters.push(`agent=${chalk2.dim(agentId)}`);
9753
11078
  if (projectId)
9754
- filters.push(`project=${chalk.dim(projectId)}`);
11079
+ filters.push(`project=${chalk2.dim(projectId)}`);
9755
11080
  if (filters.length > 0) {
9756
- console.log(chalk.dim("Filters: ") + filters.join(chalk.dim(" | ")));
11081
+ console.log(chalk2.dim("Filters: ") + filters.join(chalk2.dim(" | ")));
9757
11082
  }
9758
- console.log(chalk.dim(`Poll interval: ${intervalMs}ms`));
11083
+ console.log(chalk2.dim(`Poll interval: ${intervalMs}ms`));
9759
11084
  console.log();
9760
11085
  const filter = {
9761
11086
  scope: opts.scope,
@@ -9766,14 +11091,14 @@ program2.command("watch").description("Watch for new and changed memories in rea
9766
11091
  };
9767
11092
  const recent = listMemories(filter);
9768
11093
  if (recent.length > 0) {
9769
- console.log(chalk.bold.dim(`Recent (${recent.length}):`));
11094
+ console.log(chalk2.bold.dim(`Recent (${recent.length}):`));
9770
11095
  for (const m of recent.reverse()) {
9771
11096
  console.log(formatWatchLine(m));
9772
11097
  }
9773
11098
  } else {
9774
- console.log(chalk.dim("No recent memories."));
11099
+ console.log(chalk2.dim("No recent memories."));
9775
11100
  }
9776
- 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"));
11101
+ console.log(chalk2.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"));
9777
11102
  console.log();
9778
11103
  const { startPolling: startPolling2 } = (init_poll(), __toCommonJS(exports_poll));
9779
11104
  const handle = startPolling2({
@@ -9789,13 +11114,13 @@ program2.command("watch").description("Watch for new and changed memories in rea
9789
11114
  }
9790
11115
  },
9791
11116
  on_error: (err) => {
9792
- console.error(chalk.red(`Poll error: ${err.message}`));
11117
+ console.error(chalk2.red(`Poll error: ${err.message}`));
9793
11118
  }
9794
11119
  });
9795
11120
  const cleanup = () => {
9796
11121
  handle.stop();
9797
11122
  console.log();
9798
- console.log(chalk.dim("Stopped watching."));
11123
+ console.log(chalk2.dim("Stopped watching."));
9799
11124
  process.exit(0);
9800
11125
  };
9801
11126
  process.on("SIGINT", cleanup);
@@ -9812,7 +11137,7 @@ program2.command("pin <keyOrId>").description("Pin a memory by key or partial ID
9812
11137
  if (globalOpts.json) {
9813
11138
  outputJson({ error: `No memory found: ${keyOrId}` });
9814
11139
  } else {
9815
- console.error(chalk.red(`No memory found: ${keyOrId}`));
11140
+ console.error(chalk2.red(`No memory found: ${keyOrId}`));
9816
11141
  }
9817
11142
  process.exit(1);
9818
11143
  }
@@ -9823,7 +11148,7 @@ program2.command("pin <keyOrId>").description("Pin a memory by key or partial ID
9823
11148
  if (globalOpts.json) {
9824
11149
  outputJson(updated);
9825
11150
  } else {
9826
- console.log(chalk.green(`Pinned: ${updated.key} (${updated.id.slice(0, 8)})`));
11151
+ console.log(chalk2.green(`Pinned: ${updated.key} (${updated.id.slice(0, 8)})`));
9827
11152
  }
9828
11153
  } catch (e) {
9829
11154
  handleError(e);
@@ -9837,7 +11162,7 @@ program2.command("unpin <keyOrId>").description("Unpin a memory by key or partia
9837
11162
  if (globalOpts.json) {
9838
11163
  outputJson({ error: `No memory found: ${keyOrId}` });
9839
11164
  } else {
9840
- console.error(chalk.red(`No memory found: ${keyOrId}`));
11165
+ console.error(chalk2.red(`No memory found: ${keyOrId}`));
9841
11166
  }
9842
11167
  process.exit(1);
9843
11168
  }
@@ -9848,7 +11173,7 @@ program2.command("unpin <keyOrId>").description("Unpin a memory by key or partia
9848
11173
  if (globalOpts.json) {
9849
11174
  outputJson(updated);
9850
11175
  } else {
9851
- console.log(chalk.green(`Unpinned: ${updated.key} (${updated.id.slice(0, 8)})`));
11176
+ console.log(chalk2.green(`Unpinned: ${updated.key} (${updated.id.slice(0, 8)})`));
9852
11177
  }
9853
11178
  } catch (e) {
9854
11179
  handleError(e);
@@ -9859,17 +11184,17 @@ program2.command("archive <keyOrId>").description("Archive a memory by key or ID
9859
11184
  const globalOpts = program2.opts();
9860
11185
  let memory = getMemory(resolvePartialId(getDatabase(), "memories", keyOrId) || keyOrId) || getMemoryByKey(keyOrId, opts.scope, globalOpts.agent);
9861
11186
  if (!memory) {
9862
- console.error(chalk.red(`No memory found: ${keyOrId}`));
11187
+ console.error(chalk2.red(`No memory found: ${keyOrId}`));
9863
11188
  process.exit(1);
9864
11189
  }
9865
11190
  updateMemory(memory.id, { status: "archived", version: memory.version });
9866
11191
  if (globalOpts.json) {
9867
11192
  outputJson({ archived: true, id: memory.id, key: memory.key });
9868
11193
  } else {
9869
- console.log(chalk.green(`\u2713 Archived: ${chalk.bold(memory.key)} (${memory.id.slice(0, 8)})`));
11194
+ console.log(chalk2.green(`\u2713 Archived: ${chalk2.bold(memory.key)} (${memory.id.slice(0, 8)})`));
9870
11195
  }
9871
11196
  } catch (e) {
9872
- console.error(chalk.red(`archive failed: ${e instanceof Error ? e.message : String(e)}`));
11197
+ console.error(chalk2.red(`archive failed: ${e instanceof Error ? e.message : String(e)}`));
9873
11198
  process.exit(1);
9874
11199
  }
9875
11200
  });
@@ -9878,7 +11203,7 @@ program2.command("versions <keyOrId>").description("Show version history for a m
9878
11203
  const globalOpts = program2.opts();
9879
11204
  let memory = getMemory(resolvePartialId(getDatabase(), "memories", keyOrId) || keyOrId) || getMemoryByKey(keyOrId, opts.scope, globalOpts.agent);
9880
11205
  if (!memory) {
9881
- console.error(chalk.red(`No memory found: ${keyOrId}`));
11206
+ console.error(chalk2.red(`No memory found: ${keyOrId}`));
9882
11207
  process.exit(1);
9883
11208
  }
9884
11209
  const versions = getMemoryVersions(memory.id);
@@ -9886,20 +11211,20 @@ program2.command("versions <keyOrId>").description("Show version history for a m
9886
11211
  outputJson({ memory: { id: memory.id, key: memory.key, current_version: memory.version }, versions });
9887
11212
  return;
9888
11213
  }
9889
- console.log(chalk.bold(`
11214
+ console.log(chalk2.bold(`
9890
11215
  Version history: ${memory.key} (current: v${memory.version})
9891
11216
  `));
9892
11217
  if (versions.length === 0) {
9893
- console.log(chalk.dim(" No previous versions."));
11218
+ console.log(chalk2.dim(" No previous versions."));
9894
11219
  return;
9895
11220
  }
9896
11221
  for (const v of versions) {
9897
- console.log(` ${chalk.cyan(`v${v.version}`)} ${chalk.dim(v.created_at.slice(0, 16))} scope=${v.scope} imp=${v.importance}`);
11222
+ console.log(` ${chalk2.cyan(`v${v.version}`)} ${chalk2.dim(v.created_at.slice(0, 16))} scope=${v.scope} imp=${v.importance}`);
9898
11223
  console.log(` ${v.value.slice(0, 120)}${v.value.length > 120 ? "..." : ""}`);
9899
11224
  }
9900
11225
  console.log("");
9901
11226
  } catch (e) {
9902
- console.error(chalk.red(`versions failed: ${e instanceof Error ? e.message : String(e)}`));
11227
+ console.error(chalk2.red(`versions failed: ${e instanceof Error ? e.message : String(e)}`));
9903
11228
  process.exit(1);
9904
11229
  }
9905
11230
  });
@@ -9919,20 +11244,20 @@ program2.command("tail").description("Watch for new/updated memories in real-tim
9919
11244
  const notifyEnabled = !!opts.notify;
9920
11245
  const startTime = new Date().toISOString();
9921
11246
  if (!jsonMode) {
9922
- console.log(chalk.bold.cyan("Watching for memory changes...") + chalk.dim(" (Ctrl+C to stop)"));
11247
+ console.log(chalk2.bold.cyan("Watching for memory changes...") + chalk2.dim(" (Ctrl+C to stop)"));
9923
11248
  const filters = [];
9924
11249
  if (opts.scope)
9925
11250
  filters.push(`scope=${colorScope(opts.scope)}`);
9926
11251
  if (opts.category)
9927
11252
  filters.push(`category=${colorCategory(opts.category)}`);
9928
11253
  if (agentId)
9929
- filters.push(`agent=${chalk.dim(agentId)}`);
11254
+ filters.push(`agent=${chalk2.dim(agentId)}`);
9930
11255
  if (projectId)
9931
- filters.push(`project=${chalk.dim(projectId)}`);
11256
+ filters.push(`project=${chalk2.dim(projectId)}`);
9932
11257
  if (filters.length > 0) {
9933
- console.log(chalk.dim("Filters: ") + filters.join(chalk.dim(" | ")));
11258
+ console.log(chalk2.dim("Filters: ") + filters.join(chalk2.dim(" | ")));
9934
11259
  }
9935
- console.log(chalk.dim(`Poll interval: ${intervalMs}ms`));
11260
+ console.log(chalk2.dim(`Poll interval: ${intervalMs}ms`));
9936
11261
  console.log();
9937
11262
  }
9938
11263
  const { startPolling: startPolling2 } = (init_poll(), __toCommonJS(exports_poll));
@@ -9948,7 +11273,7 @@ program2.command("tail").description("Watch for new/updated memories in real-tim
9948
11273
  if (jsonMode) {
9949
11274
  console.log(JSON.stringify({ event: isNew ? "new" : "updated", memory: m }));
9950
11275
  } else {
9951
- const prefix = isNew ? chalk.green.bold("+ ") : chalk.yellow.bold("~ ");
11276
+ const prefix = isNew ? chalk2.green.bold("+ ") : chalk2.yellow.bold("~ ");
9952
11277
  console.log(prefix + formatWatchLine(m));
9953
11278
  }
9954
11279
  if (notifyEnabled)
@@ -9959,7 +11284,7 @@ program2.command("tail").description("Watch for new/updated memories in real-tim
9959
11284
  if (jsonMode) {
9960
11285
  console.error(JSON.stringify({ event: "error", message: err.message }));
9961
11286
  } else {
9962
- console.error(chalk.red(`Poll error: ${err.message}`));
11287
+ console.error(chalk2.red(`Poll error: ${err.message}`));
9963
11288
  }
9964
11289
  }
9965
11290
  });
@@ -9967,7 +11292,7 @@ program2.command("tail").description("Watch for new/updated memories in real-tim
9967
11292
  handle.stop();
9968
11293
  if (!jsonMode) {
9969
11294
  console.log();
9970
- console.log(chalk.dim("Stopped watching."));
11295
+ console.log(chalk2.dim("Stopped watching."));
9971
11296
  }
9972
11297
  process.exit(0);
9973
11298
  };
@@ -10059,7 +11384,7 @@ ${lines.join(`
10059
11384
  }
10060
11385
  if (lines.length === 0) {
10061
11386
  if (process.stdout.isTTY) {
10062
- console.log(chalk.yellow("No relevant memories found."));
11387
+ console.log(chalk2.yellow("No relevant memories found."));
10063
11388
  }
10064
11389
  return;
10065
11390
  }
@@ -10075,18 +11400,18 @@ program2.command("backup [path]").description("Backup the SQLite database to a f
10075
11400
  try {
10076
11401
  const globalOpts = program2.opts();
10077
11402
  const home = process.env["HOME"] || process.env["USERPROFILE"] || "~";
10078
- const backupsDir = join3(home, ".mementos", "backups");
11403
+ const backupsDir = join6(home, ".mementos", "backups");
10079
11404
  if (opts.list) {
10080
- if (!existsSync3(backupsDir)) {
11405
+ if (!existsSync6(backupsDir)) {
10081
11406
  if (globalOpts.json) {
10082
11407
  outputJson({ backups: [] });
10083
11408
  return;
10084
11409
  }
10085
- console.log(chalk.yellow("No backups directory found."));
11410
+ console.log(chalk2.yellow("No backups directory found."));
10086
11411
  return;
10087
11412
  }
10088
- const files = readdirSync2(backupsDir).filter((f) => f.endsWith(".db")).map((f) => {
10089
- const filePath = join3(backupsDir, f);
11413
+ const files = readdirSync3(backupsDir).filter((f) => f.endsWith(".db")).map((f) => {
11414
+ const filePath = join6(backupsDir, f);
10090
11415
  const st2 = statSync(filePath);
10091
11416
  return { name: f, path: filePath, size: st2.size, mtime: st2.mtime };
10092
11417
  }).sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
@@ -10095,7 +11420,7 @@ program2.command("backup [path]").description("Backup the SQLite database to a f
10095
11420
  outputJson({ backups: [] });
10096
11421
  return;
10097
11422
  }
10098
- console.log(chalk.yellow("No backups found."));
11423
+ console.log(chalk2.yellow("No backups found."));
10099
11424
  return;
10100
11425
  }
10101
11426
  if (globalOpts.json) {
@@ -10109,34 +11434,34 @@ program2.command("backup [path]").description("Backup the SQLite database to a f
10109
11434
  });
10110
11435
  return;
10111
11436
  }
10112
- console.log(chalk.bold(`Backups in ${backupsDir}:`));
11437
+ console.log(chalk2.bold(`Backups in ${backupsDir}:`));
10113
11438
  for (const f of files) {
10114
11439
  const date = f.mtime.toISOString().replace("T", " ").slice(0, 19);
10115
11440
  const sizeMB2 = (f.size / (1024 * 1024)).toFixed(1);
10116
11441
  const sizeStr2 = f.size >= 1024 * 1024 ? `${sizeMB2} MB` : `${(f.size / 1024).toFixed(1)} KB`;
10117
- console.log(` ${chalk.dim(date)} ${chalk.cyan(sizeStr2.padStart(8))} ${f.name}`);
11442
+ console.log(` ${chalk2.dim(date)} ${chalk2.cyan(sizeStr2.padStart(8))} ${f.name}`);
10118
11443
  }
10119
11444
  return;
10120
11445
  }
10121
11446
  const dbPath = getDbPath();
10122
- if (!existsSync3(dbPath)) {
10123
- console.error(chalk.red(`Database not found at ${dbPath}`));
11447
+ if (!existsSync6(dbPath)) {
11448
+ console.error(chalk2.red(`Database not found at ${dbPath}`));
10124
11449
  process.exit(1);
10125
11450
  }
10126
11451
  let dest;
10127
11452
  if (targetPath) {
10128
11453
  dest = resolve3(targetPath);
10129
11454
  } else {
10130
- if (!existsSync3(backupsDir)) {
10131
- mkdirSync3(backupsDir, { recursive: true });
11455
+ if (!existsSync6(backupsDir)) {
11456
+ mkdirSync6(backupsDir, { recursive: true });
10132
11457
  }
10133
- const now2 = new Date;
10134
- const ts = now2.toISOString().replace(/[-:T]/g, "").replace(/\..+/, "").slice(0, 15);
10135
- dest = join3(backupsDir, `mementos-${ts}.db`);
11458
+ const now3 = new Date;
11459
+ const ts = now3.toISOString().replace(/[-:T]/g, "").replace(/\..+/, "").slice(0, 15);
11460
+ dest = join6(backupsDir, `mementos-${ts}.db`);
10136
11461
  }
10137
- const destDir = dirname3(dest);
10138
- if (!existsSync3(destDir)) {
10139
- mkdirSync3(destDir, { recursive: true });
11462
+ const destDir = dirname4(dest);
11463
+ if (!existsSync6(destDir)) {
11464
+ mkdirSync6(destDir, { recursive: true });
10140
11465
  }
10141
11466
  copyFileSync(dbPath, dest);
10142
11467
  const st = statSync(dest);
@@ -10146,7 +11471,7 @@ program2.command("backup [path]").description("Backup the SQLite database to a f
10146
11471
  outputJson({ backed_up_to: dest, size: st.size, source: dbPath });
10147
11472
  return;
10148
11473
  }
10149
- console.log(`Backed up to: ${chalk.green(dest)} (size: ${sizeStr})`);
11474
+ console.log(`Backed up to: ${chalk2.green(dest)} (size: ${sizeStr})`);
10150
11475
  } catch (e) {
10151
11476
  handleError(e);
10152
11477
  }
@@ -10155,31 +11480,31 @@ program2.command("restore [file]").description("Restore the database from a back
10155
11480
  try {
10156
11481
  const globalOpts = program2.opts();
10157
11482
  const home = process.env["HOME"] || process.env["USERPROFILE"] || "~";
10158
- const backupsDir = join3(home, ".mementos", "backups");
11483
+ const backupsDir = join6(home, ".mementos", "backups");
10159
11484
  let source;
10160
11485
  if (opts.latest) {
10161
- if (!existsSync3(backupsDir)) {
10162
- console.error(chalk.red("No backups directory found."));
11486
+ if (!existsSync6(backupsDir)) {
11487
+ console.error(chalk2.red("No backups directory found."));
10163
11488
  process.exit(1);
10164
11489
  }
10165
- const files = readdirSync2(backupsDir).filter((f) => f.endsWith(".db")).map((f) => {
10166
- const fp = join3(backupsDir, f);
11490
+ const files = readdirSync3(backupsDir).filter((f) => f.endsWith(".db")).map((f) => {
11491
+ const fp = join6(backupsDir, f);
10167
11492
  const st = statSync(fp);
10168
11493
  return { path: fp, mtime: st.mtime };
10169
11494
  }).sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
10170
11495
  if (files.length === 0) {
10171
- console.error(chalk.red("No backups found in " + backupsDir));
11496
+ console.error(chalk2.red("No backups found in " + backupsDir));
10172
11497
  process.exit(1);
10173
11498
  }
10174
11499
  source = files[0].path;
10175
11500
  } else if (filePath) {
10176
11501
  source = resolve3(filePath);
10177
11502
  } else {
10178
- console.error(chalk.red("Provide a backup file path or use --latest"));
11503
+ console.error(chalk2.red("Provide a backup file path or use --latest"));
10179
11504
  process.exit(1);
10180
11505
  }
10181
- if (!existsSync3(source)) {
10182
- console.error(chalk.red(`Backup file not found: ${source}`));
11506
+ if (!existsSync6(source)) {
11507
+ console.error(chalk2.red(`Backup file not found: ${source}`));
10183
11508
  process.exit(1);
10184
11509
  }
10185
11510
  const dbPath = getDbPath();
@@ -10187,7 +11512,7 @@ program2.command("restore [file]").description("Restore the database from a back
10187
11512
  const backupSizeMB = (backupStat.size / (1024 * 1024)).toFixed(1);
10188
11513
  const backupSizeStr = backupStat.size >= 1024 * 1024 ? `${backupSizeMB} MB` : `${(backupStat.size / 1024).toFixed(1)} KB`;
10189
11514
  let currentCount = 0;
10190
- if (existsSync3(dbPath)) {
11515
+ if (existsSync6(dbPath)) {
10191
11516
  try {
10192
11517
  const db = getDatabase();
10193
11518
  const row = db.query("SELECT COUNT(*) as count FROM memories").get();
@@ -10196,8 +11521,8 @@ program2.command("restore [file]").description("Restore the database from a back
10196
11521
  }
10197
11522
  let backupCount = 0;
10198
11523
  try {
10199
- const { Database: Database2 } = __require("bun:sqlite");
10200
- const backupDb = new Database2(source, { readonly: true });
11524
+ const { Database: Database3 } = __require("bun:sqlite");
11525
+ const backupDb = new Database3(source, { readonly: true });
10201
11526
  const row = backupDb.query("SELECT COUNT(*) as count FROM memories").get();
10202
11527
  backupCount = row?.count ?? 0;
10203
11528
  backupDb.close();
@@ -10216,13 +11541,13 @@ program2.command("restore [file]").description("Restore the database from a back
10216
11541
  });
10217
11542
  return;
10218
11543
  }
10219
- console.log(chalk.bold("Restore preview:"));
10220
- console.log(` Source: ${chalk.cyan(source)} (${backupSizeStr})`);
10221
- console.log(` Target: ${chalk.cyan(dbPath)}`);
10222
- console.log(` Current memories: ${chalk.yellow(String(currentCount))}`);
10223
- console.log(` Backup memories: ${chalk.green(String(backupCount))}`);
11544
+ console.log(chalk2.bold("Restore preview:"));
11545
+ console.log(` Source: ${chalk2.cyan(source)} (${backupSizeStr})`);
11546
+ console.log(` Target: ${chalk2.cyan(dbPath)}`);
11547
+ console.log(` Current memories: ${chalk2.yellow(String(currentCount))}`);
11548
+ console.log(` Backup memories: ${chalk2.green(String(backupCount))}`);
10224
11549
  console.log();
10225
- console.log(chalk.yellow("Use --force to confirm restore"));
11550
+ console.log(chalk2.yellow("Use --force to confirm restore"));
10226
11551
  return;
10227
11552
  }
10228
11553
  copyFileSync(source, dbPath);
@@ -10245,9 +11570,9 @@ program2.command("restore [file]").description("Restore the database from a back
10245
11570
  });
10246
11571
  return;
10247
11572
  }
10248
- console.log(`Restored from: ${chalk.green(source)}`);
10249
- console.log(` Previous memories: ${chalk.yellow(String(currentCount))}`);
10250
- console.log(` Restored memories: ${chalk.green(String(newCount))}`);
11573
+ console.log(`Restored from: ${chalk2.green(source)}`);
11574
+ console.log(` Previous memories: ${chalk2.yellow(String(currentCount))}`);
11575
+ console.log(` Restored memories: ${chalk2.green(String(newCount))}`);
10251
11576
  } catch (e) {
10252
11577
  handleError(e);
10253
11578
  }
@@ -10260,7 +11585,7 @@ program2.command("diff <id>").description("Show diff between memory versions").o
10260
11585
  if (!memoryId) {
10261
11586
  const mem = resolveKeyOrId(idArg, {}, globalOpts);
10262
11587
  if (!mem) {
10263
- console.error(chalk.red(`Memory not found: ${idArg}`));
11588
+ console.error(chalk2.red(`Memory not found: ${idArg}`));
10264
11589
  process.exit(1);
10265
11590
  }
10266
11591
  memoryId = mem.id;
@@ -10273,7 +11598,7 @@ program2.command("diff <id>").description("Show diff between memory versions").o
10273
11598
  function diffMemory(memoryId, opts, globalOpts) {
10274
11599
  const current = getMemory(memoryId);
10275
11600
  if (!current) {
10276
- console.error(chalk.red(`Memory not found: ${memoryId}`));
11601
+ console.error(chalk2.red(`Memory not found: ${memoryId}`));
10277
11602
  process.exit(1);
10278
11603
  }
10279
11604
  const versions = getMemoryVersions(memoryId);
@@ -10281,8 +11606,8 @@ function diffMemory(memoryId, opts, globalOpts) {
10281
11606
  if (globalOpts.json) {
10282
11607
  outputJson({ error: "No version history available", memory_id: memoryId });
10283
11608
  } else {
10284
- console.log(chalk.yellow("No version history available."));
10285
- console.log(chalk.dim(`Memory "${current.key}" is at version ${current.version} but has no prior snapshots.`));
11609
+ console.log(chalk2.yellow("No version history available."));
11610
+ console.log(chalk2.dim(`Memory "${current.key}" is at version ${current.version} but has no prior snapshots.`));
10286
11611
  }
10287
11612
  return;
10288
11613
  }
@@ -10293,13 +11618,13 @@ function diffMemory(memoryId, opts, globalOpts) {
10293
11618
  if (opts.version) {
10294
11619
  const targetVersion = parseInt(opts.version, 10);
10295
11620
  if (isNaN(targetVersion) || targetVersion < 1) {
10296
- console.error(chalk.red("Version must be a positive integer."));
11621
+ console.error(chalk2.red("Version must be a positive integer."));
10297
11622
  process.exit(1);
10298
11623
  }
10299
11624
  if (targetVersion === current.version) {
10300
11625
  const prev = versions.find((v) => v.version === targetVersion - 1);
10301
11626
  if (!prev) {
10302
- console.error(chalk.red(`No version ${targetVersion - 1} found to compare against.`));
11627
+ console.error(chalk2.red(`No version ${targetVersion - 1} found to compare against.`));
10303
11628
  process.exit(1);
10304
11629
  }
10305
11630
  older = prev;
@@ -10315,10 +11640,10 @@ function diffMemory(memoryId, opts, globalOpts) {
10315
11640
  olderVersion = prevSnap.version;
10316
11641
  newerVersion = targetSnap.version;
10317
11642
  } else if (targetSnap && !prevSnap) {
10318
- console.error(chalk.red(`No version ${targetVersion - 1} found to compare against.`));
11643
+ console.error(chalk2.red(`No version ${targetVersion - 1} found to compare against.`));
10319
11644
  process.exit(1);
10320
11645
  } else {
10321
- console.error(chalk.red(`Version ${targetVersion} not found.`));
11646
+ console.error(chalk2.red(`Version ${targetVersion} not found.`));
10322
11647
  process.exit(1);
10323
11648
  }
10324
11649
  }
@@ -10357,8 +11682,8 @@ function diffMemory(memoryId, opts, globalOpts) {
10357
11682
  });
10358
11683
  return;
10359
11684
  }
10360
- console.log(chalk.bold(`Diff for "${current.key}" (${memoryId.slice(0, 8)})`));
10361
- console.log(chalk.dim(`Version ${olderVersion} \u2192 ${newerVersion}`));
11685
+ console.log(chalk2.bold(`Diff for "${current.key}" (${memoryId.slice(0, 8)})`));
11686
+ console.log(chalk2.dim(`Version ${olderVersion} \u2192 ${newerVersion}`));
10362
11687
  console.log();
10363
11688
  let hasChanges = false;
10364
11689
  const n = newer;
@@ -10366,7 +11691,7 @@ function diffMemory(memoryId, opts, globalOpts) {
10366
11691
  const newValue = n.value;
10367
11692
  if (oldValue !== newValue) {
10368
11693
  hasChanges = true;
10369
- console.log(chalk.bold(" value:"));
11694
+ console.log(chalk2.bold(" value:"));
10370
11695
  diffLines(oldValue, newValue);
10371
11696
  }
10372
11697
  const scalarFields = [
@@ -10380,7 +11705,7 @@ function diffMemory(memoryId, opts, globalOpts) {
10380
11705
  for (const field of scalarFields) {
10381
11706
  if (String(field.oldVal) !== String(field.newVal)) {
10382
11707
  hasChanges = true;
10383
- console.log(` ${chalk.bold(field.name + ":")} ${chalk.red(String(field.oldVal))} \u2192 ${chalk.green(String(field.newVal))}`);
11708
+ console.log(` ${chalk2.bold(field.name + ":")} ${chalk2.red(String(field.oldVal))} \u2192 ${chalk2.green(String(field.newVal))}`);
10384
11709
  }
10385
11710
  }
10386
11711
  const oldTags = older.tags;
@@ -10389,14 +11714,14 @@ function diffMemory(memoryId, opts, globalOpts) {
10389
11714
  hasChanges = true;
10390
11715
  const removed = oldTags.filter((t) => !newTags.includes(t));
10391
11716
  const added = newTags.filter((t) => !oldTags.includes(t));
10392
- console.log(` ${chalk.bold("tags:")}`);
11717
+ console.log(` ${chalk2.bold("tags:")}`);
10393
11718
  for (const t of removed)
10394
- console.log(chalk.red(` - ${t}`));
11719
+ console.log(chalk2.red(` - ${t}`));
10395
11720
  for (const t of added)
10396
- console.log(chalk.green(` + ${t}`));
11721
+ console.log(chalk2.green(` + ${t}`));
10397
11722
  }
10398
11723
  if (!hasChanges) {
10399
- console.log(chalk.dim(" No changes between these versions."));
11724
+ console.log(chalk2.dim(" No changes between these versions."));
10400
11725
  }
10401
11726
  }
10402
11727
  function diffLines(oldText, newText) {
@@ -10405,22 +11730,22 @@ function diffLines(oldText, newText) {
10405
11730
  const newLines = newText.split(`
10406
11731
  `);
10407
11732
  if (oldLines.length === 1 && newLines.length === 1) {
10408
- console.log(chalk.red(` - ${oldLines[0]}`));
10409
- console.log(chalk.green(` + ${newLines[0]}`));
11733
+ console.log(chalk2.red(` - ${oldLines[0]}`));
11734
+ console.log(chalk2.green(` + ${newLines[0]}`));
10410
11735
  return;
10411
11736
  }
10412
11737
  const oldSet = new Set(oldLines);
10413
11738
  const newSet = new Set(newLines);
10414
11739
  for (const line of oldLines) {
10415
11740
  if (!newSet.has(line)) {
10416
- console.log(chalk.red(` - ${line}`));
11741
+ console.log(chalk2.red(` - ${line}`));
10417
11742
  } else {
10418
- console.log(chalk.dim(` ${line}`));
11743
+ console.log(chalk2.dim(` ${line}`));
10419
11744
  }
10420
11745
  }
10421
11746
  for (const line of newLines) {
10422
11747
  if (!oldSet.has(line)) {
10423
- console.log(chalk.green(` + ${line}`));
11748
+ console.log(chalk2.green(` + ${line}`));
10424
11749
  }
10425
11750
  }
10426
11751
  }
@@ -10576,24 +11901,24 @@ function validateConfigKeyValue(key, value) {
10576
11901
  return null;
10577
11902
  }
10578
11903
  function getConfigPath() {
10579
- return join3(homedir2(), ".mementos", "config.json");
11904
+ return join6(homedir4(), ".mementos", "config.json");
10580
11905
  }
10581
11906
  function readFileConfig() {
10582
11907
  const configPath = getConfigPath();
10583
- if (!existsSync3(configPath))
11908
+ if (!existsSync6(configPath))
10584
11909
  return {};
10585
11910
  try {
10586
- return JSON.parse(readFileSync2(configPath, "utf-8"));
11911
+ return JSON.parse(readFileSync3(configPath, "utf-8"));
10587
11912
  } catch {
10588
11913
  return {};
10589
11914
  }
10590
11915
  }
10591
11916
  function writeFileConfig(data) {
10592
11917
  const configPath = getConfigPath();
10593
- const dir = dirname3(configPath);
10594
- if (!existsSync3(dir))
10595
- mkdirSync3(dir, { recursive: true });
10596
- writeFileSync2(configPath, JSON.stringify(data, null, 2) + `
11918
+ const dir = dirname4(configPath);
11919
+ if (!existsSync6(dir))
11920
+ mkdirSync6(dir, { recursive: true });
11921
+ writeFileSync4(configPath, JSON.stringify(data, null, 2) + `
10597
11922
  `, "utf-8");
10598
11923
  }
10599
11924
  program2.command("config [subcommand] [args...]").description("View or modify configuration. Subcommands: get <key>, set <key> <value>, reset [key], path").action((subcommand, args) => {
@@ -10621,13 +11946,13 @@ program2.command("config [subcommand] [args...]").description("View or modify co
10621
11946
  if (subcommand === "get") {
10622
11947
  const key = args[0];
10623
11948
  if (!key) {
10624
- console.error(chalk.red("Usage: mementos config get <key>"));
11949
+ console.error(chalk2.red("Usage: mementos config get <key>"));
10625
11950
  process.exit(1);
10626
11951
  }
10627
11952
  const config = loadConfig();
10628
11953
  const value = getNestedValue(config, key);
10629
11954
  if (value === undefined) {
10630
- console.error(chalk.red(`Unknown config key: ${key}`));
11955
+ console.error(chalk2.red(`Unknown config key: ${key}`));
10631
11956
  process.exit(1);
10632
11957
  }
10633
11958
  if (useJson) {
@@ -10643,13 +11968,13 @@ program2.command("config [subcommand] [args...]").description("View or modify co
10643
11968
  const key = args[0];
10644
11969
  const rawValue = args[1];
10645
11970
  if (!key || rawValue === undefined) {
10646
- console.error(chalk.red("Usage: mementos config set <key> <value>"));
11971
+ console.error(chalk2.red("Usage: mementos config set <key> <value>"));
10647
11972
  process.exit(1);
10648
11973
  }
10649
11974
  const value = parseConfigValue(rawValue);
10650
11975
  const err = validateConfigKeyValue(key, value);
10651
11976
  if (err) {
10652
- console.error(chalk.red(err));
11977
+ console.error(chalk2.red(err));
10653
11978
  process.exit(1);
10654
11979
  }
10655
11980
  const fileConfig = readFileConfig();
@@ -10658,7 +11983,7 @@ program2.command("config [subcommand] [args...]").description("View or modify co
10658
11983
  if (useJson) {
10659
11984
  outputJson({ key, value, saved: true });
10660
11985
  } else {
10661
- console.log(chalk.green(`Set ${key} = ${JSON.stringify(value)}`));
11986
+ console.log(chalk2.green(`Set ${key} = ${JSON.stringify(value)}`));
10662
11987
  }
10663
11988
  return;
10664
11989
  }
@@ -10667,7 +11992,7 @@ program2.command("config [subcommand] [args...]").description("View or modify co
10667
11992
  if (key) {
10668
11993
  const defaultVal = getNestedValue(DEFAULT_CONFIG, key);
10669
11994
  if (defaultVal === undefined) {
10670
- console.error(chalk.red(`Unknown config key: ${key}`));
11995
+ console.error(chalk2.red(`Unknown config key: ${key}`));
10671
11996
  process.exit(1);
10672
11997
  }
10673
11998
  const fileConfig = readFileConfig();
@@ -10676,22 +12001,22 @@ program2.command("config [subcommand] [args...]").description("View or modify co
10676
12001
  if (useJson) {
10677
12002
  outputJson({ key, reset: true, default_value: defaultVal });
10678
12003
  } else {
10679
- console.log(chalk.green(`Reset ${key} to default (${JSON.stringify(defaultVal)})`));
12004
+ console.log(chalk2.green(`Reset ${key} to default (${JSON.stringify(defaultVal)})`));
10680
12005
  }
10681
12006
  } else {
10682
12007
  const configPath = getConfigPath();
10683
- if (existsSync3(configPath)) {
12008
+ if (existsSync6(configPath)) {
10684
12009
  unlinkSync2(configPath);
10685
12010
  }
10686
12011
  if (useJson) {
10687
12012
  outputJson({ reset: true, all: true });
10688
12013
  } else {
10689
- console.log(chalk.green("Config reset to defaults (file removed)"));
12014
+ console.log(chalk2.green("Config reset to defaults (file removed)"));
10690
12015
  }
10691
12016
  }
10692
12017
  return;
10693
12018
  }
10694
- console.error(chalk.red(`Unknown config subcommand: ${subcommand}`));
12019
+ console.error(chalk2.red(`Unknown config subcommand: ${subcommand}`));
10695
12020
  console.error("Usage: mementos config [get|set|reset|path]");
10696
12021
  process.exit(1);
10697
12022
  } catch (e) {
@@ -10718,7 +12043,7 @@ entityCmd.command("create <name>").description("Create a knowledge graph entity"
10718
12043
  if (globalOpts.json || globalOpts.format === "json") {
10719
12044
  outputJson(entity);
10720
12045
  } else {
10721
- console.log(chalk.green(`Entity: ${entity.name} (${entity.id.slice(0, 8)})`));
12046
+ console.log(chalk2.green(`Entity: ${entity.name} (${entity.id.slice(0, 8)})`));
10722
12047
  }
10723
12048
  } catch (e) {
10724
12049
  handleError(e);
@@ -10734,28 +12059,28 @@ entityCmd.command("show <nameOrId>").description("Show entity details with relat
10734
12059
  outputJson({ ...entity, related, memories });
10735
12060
  return;
10736
12061
  }
10737
- console.log(`${chalk.bold("ID:")} ${entity.id}`);
10738
- console.log(`${chalk.bold("Name:")} ${entity.name}`);
10739
- console.log(`${chalk.bold("Type:")} ${colorEntityType(entity.type)}`);
12062
+ console.log(`${chalk2.bold("ID:")} ${entity.id}`);
12063
+ console.log(`${chalk2.bold("Name:")} ${entity.name}`);
12064
+ console.log(`${chalk2.bold("Type:")} ${colorEntityType(entity.type)}`);
10740
12065
  if (entity.description)
10741
- console.log(`${chalk.bold("Description:")} ${entity.description}`);
12066
+ console.log(`${chalk2.bold("Description:")} ${entity.description}`);
10742
12067
  if (entity.project_id)
10743
- console.log(`${chalk.bold("Project:")} ${entity.project_id}`);
10744
- console.log(`${chalk.bold("Created:")} ${entity.created_at}`);
10745
- console.log(`${chalk.bold("Updated:")} ${entity.updated_at}`);
12068
+ console.log(`${chalk2.bold("Project:")} ${entity.project_id}`);
12069
+ console.log(`${chalk2.bold("Created:")} ${entity.created_at}`);
12070
+ console.log(`${chalk2.bold("Updated:")} ${entity.updated_at}`);
10746
12071
  if (related.length > 0) {
10747
12072
  console.log(`
10748
- ${chalk.bold("Related entities:")}`);
12073
+ ${chalk2.bold("Related entities:")}`);
10749
12074
  for (const r of related) {
10750
- console.log(` ${chalk.dim(r.id.slice(0, 8))} [${colorEntityType(r.type)}] ${r.name}${r.description ? chalk.dim(` \u2014 ${r.description}`) : ""}`);
12075
+ console.log(` ${chalk2.dim(r.id.slice(0, 8))} [${colorEntityType(r.type)}] ${r.name}${r.description ? chalk2.dim(` \u2014 ${r.description}`) : ""}`);
10751
12076
  }
10752
12077
  }
10753
12078
  if (memories.length > 0) {
10754
12079
  console.log(`
10755
- ${chalk.bold("Linked memories:")}`);
12080
+ ${chalk2.bold("Linked memories:")}`);
10756
12081
  for (const m of memories) {
10757
12082
  const value = m.value.length > 60 ? m.value.slice(0, 60) + "..." : m.value;
10758
- console.log(` ${chalk.dim(m.id.slice(0, 8))} ${chalk.bold(m.key)} = ${value}`);
12083
+ console.log(` ${chalk2.dim(m.id.slice(0, 8))} ${chalk2.bold(m.key)} = ${value}`);
10759
12084
  }
10760
12085
  }
10761
12086
  } catch (e) {
@@ -10796,13 +12121,13 @@ entityCmd.command("list").description("List entities with optional filters").opt
10796
12121
  return;
10797
12122
  }
10798
12123
  if (entities.length === 0) {
10799
- console.log(chalk.yellow("No entities found."));
12124
+ console.log(chalk2.yellow("No entities found."));
10800
12125
  return;
10801
12126
  }
10802
- console.log(chalk.bold(`${entities.length} entit${entities.length === 1 ? "y" : "ies"}:`));
12127
+ console.log(chalk2.bold(`${entities.length} entit${entities.length === 1 ? "y" : "ies"}:`));
10803
12128
  for (const e of entities) {
10804
- const id = chalk.dim(e.id.slice(0, 8));
10805
- const desc = e.description ? chalk.dim(` (${e.description})`) : "";
12129
+ const id = chalk2.dim(e.id.slice(0, 8));
12130
+ const desc = e.description ? chalk2.dim(` (${e.description})`) : "";
10806
12131
  console.log(`${id} ${colorEntityType(e.type)} ${e.name}${desc}`);
10807
12132
  }
10808
12133
  } catch (e) {
@@ -10817,7 +12142,7 @@ entityCmd.command("delete <nameOrId>").description("Delete an entity and cascade
10817
12142
  if (globalOpts.json || globalOpts.format === "json") {
10818
12143
  outputJson({ deleted: entity.id, name: entity.name });
10819
12144
  } else {
10820
- console.log(chalk.green(`Deleted entity: ${entity.name} (${entity.id.slice(0, 8)}) \u2014 relations and memory links cascaded`));
12145
+ console.log(chalk2.green(`Deleted entity: ${entity.name} (${entity.id.slice(0, 8)}) \u2014 relations and memory links cascaded`));
10821
12146
  }
10822
12147
  } catch (e) {
10823
12148
  handleError(e);
@@ -10832,7 +12157,7 @@ entityCmd.command("merge <source> <target>").description("Merge source entity in
10832
12157
  if (globalOpts.json || globalOpts.format === "json") {
10833
12158
  outputJson(merged);
10834
12159
  } else {
10835
- console.log(chalk.green(`Merged: ${srcEntity.name} \u2192 ${merged.name} (${merged.id.slice(0, 8)})`));
12160
+ console.log(chalk2.green(`Merged: ${srcEntity.name} \u2192 ${merged.name} (${merged.id.slice(0, 8)})`));
10836
12161
  }
10837
12162
  } catch (e) {
10838
12163
  handleError(e);
@@ -10844,14 +12169,14 @@ entityCmd.command("link <entity> <memoryKeyOrId>").description("Link an entity t
10844
12169
  const entity = resolveEntityArg(entityArg, opts.type);
10845
12170
  const memory = resolveKeyOrId(memoryKeyOrId, {}, globalOpts);
10846
12171
  if (!memory) {
10847
- console.error(chalk.red(`Memory not found: ${memoryKeyOrId}`));
12172
+ console.error(chalk2.red(`Memory not found: ${memoryKeyOrId}`));
10848
12173
  process.exit(1);
10849
12174
  }
10850
12175
  const link = linkEntityToMemory(entity.id, memory.id, opts.role);
10851
12176
  if (globalOpts.json || globalOpts.format === "json") {
10852
12177
  outputJson(link);
10853
12178
  } else {
10854
- console.log(chalk.green(`Linked: ${entity.name} \u2194 ${memory.key} (role: ${link.role})`));
12179
+ console.log(chalk2.green(`Linked: ${entity.name} \u2194 ${memory.key} (role: ${link.role})`));
10855
12180
  }
10856
12181
  } catch (e) {
10857
12182
  handleError(e);
@@ -10872,7 +12197,7 @@ relationCmd.command("create <source> <target>").description("Create a relation b
10872
12197
  if (globalOpts.json || globalOpts.format === "json") {
10873
12198
  outputJson(relation);
10874
12199
  } else {
10875
- console.log(chalk.green(`Relation: ${srcEntity.name} \u2014[${relation.relation_type}]\u2192 ${tgtEntity.name} (${relation.id.slice(0, 8)})`));
12200
+ console.log(chalk2.green(`Relation: ${srcEntity.name} \u2014[${relation.relation_type}]\u2192 ${tgtEntity.name} (${relation.id.slice(0, 8)})`));
10876
12201
  }
10877
12202
  } catch (e) {
10878
12203
  handleError(e);
@@ -10903,7 +12228,7 @@ relationCmd.command("list <entityNameOrId>").description("List relations for an
10903
12228
  return;
10904
12229
  }
10905
12230
  if (relations.length === 0) {
10906
- console.log(chalk.yellow(`No relations found for: ${entity.name}`));
12231
+ console.log(chalk2.yellow(`No relations found for: ${entity.name}`));
10907
12232
  return;
10908
12233
  }
10909
12234
  const entityCache = new Map;
@@ -10919,13 +12244,13 @@ relationCmd.command("list <entityNameOrId>").description("List relations for an
10919
12244
  return id.slice(0, 8);
10920
12245
  }
10921
12246
  };
10922
- console.log(chalk.bold(`${relations.length} relation${relations.length === 1 ? "" : "s"} for ${entity.name}:`));
12247
+ console.log(chalk2.bold(`${relations.length} relation${relations.length === 1 ? "" : "s"} for ${entity.name}:`));
10923
12248
  for (const r of relations) {
10924
12249
  const src = resolveName(r.source_entity_id);
10925
12250
  const tgt = resolveName(r.target_entity_id);
10926
- const id = chalk.dim(r.id.slice(0, 8));
10927
- const weight = r.weight !== 1 ? chalk.dim(` w:${r.weight}`) : "";
10928
- console.log(`${id} ${src} \u2014[${chalk.cyan(r.relation_type)}]\u2192 ${tgt}${weight}`);
12251
+ const id = chalk2.dim(r.id.slice(0, 8));
12252
+ const weight = r.weight !== 1 ? chalk2.dim(` w:${r.weight}`) : "";
12253
+ console.log(`${id} ${src} \u2014[${chalk2.cyan(r.relation_type)}]\u2192 ${tgt}${weight}`);
10929
12254
  }
10930
12255
  } catch (e) {
10931
12256
  handleError(e);
@@ -10937,14 +12262,14 @@ relationCmd.command("delete <id>").description("Delete a relation by ID").action
10937
12262
  const db = getDatabase();
10938
12263
  const resolvedId = resolvePartialId(db, "relations", id);
10939
12264
  if (!resolvedId) {
10940
- console.error(chalk.red(`Relation not found: ${id}`));
12265
+ console.error(chalk2.red(`Relation not found: ${id}`));
10941
12266
  process.exit(1);
10942
12267
  }
10943
12268
  deleteRelation(resolvedId);
10944
12269
  if (globalOpts.json || globalOpts.format === "json") {
10945
12270
  outputJson({ deleted: resolvedId });
10946
12271
  } else {
10947
- console.log(chalk.green(`Deleted relation: ${resolvedId.slice(0, 8)}`));
12272
+ console.log(chalk2.green(`Deleted relation: ${resolvedId.slice(0, 8)}`));
10948
12273
  }
10949
12274
  } catch (e) {
10950
12275
  handleError(e);
@@ -10962,7 +12287,7 @@ graphCmd.command("show <entityNameOrId>").description("Show connected entities a
10962
12287
  return;
10963
12288
  }
10964
12289
  if (graph.entities.length === 0) {
10965
- console.log(chalk.yellow(`No graph data for: ${entity.name}`));
12290
+ console.log(chalk2.yellow(`No graph data for: ${entity.name}`));
10966
12291
  return;
10967
12292
  }
10968
12293
  const adj = new Map;
@@ -10994,7 +12319,7 @@ graphCmd.command("show <entityNameOrId>").description("Show connected entities a
10994
12319
  for (let i = 0;i < children.length; i++) {
10995
12320
  const child = children[i];
10996
12321
  const childIndent = indent + (indent === "" ? "" : isLast ? " " : "\u2502 ");
10997
- const relLabel = chalk.dim(` (${child.relation})`);
12322
+ const relLabel = chalk2.dim(` (${child.relation})`);
10998
12323
  const childPrefix = i === children.length - 1 ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
10999
12324
  visited.add(child.entity.id);
11000
12325
  console.log(`${childIndent}${childPrefix}[${colorEntityType(child.entity.type)}] ${child.entity.name}${relLabel}`);
@@ -11003,7 +12328,7 @@ graphCmd.command("show <entityNameOrId>").description("Show connected entities a
11003
12328
  const gc = grandChildren[j];
11004
12329
  const gcIndent = childIndent + (i === children.length - 1 ? " " : "\u2502 ");
11005
12330
  const gcPrefix = j === grandChildren.length - 1 ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
11006
- const gcRelLabel = chalk.dim(` (${gc.relation})`);
12331
+ const gcRelLabel = chalk2.dim(` (${gc.relation})`);
11007
12332
  visited.add(gc.entity.id);
11008
12333
  console.log(`${gcIndent}${gcPrefix}[${colorEntityType(gc.entity.type)}] ${gc.entity.name}${gcRelLabel}`);
11009
12334
  }
@@ -11025,10 +12350,10 @@ graphCmd.command("path <from> <to>").description("Show shortest path between two
11025
12350
  return;
11026
12351
  }
11027
12352
  if (!path) {
11028
- console.log(chalk.yellow(`No path found between ${fromEntity.name} and ${toEntity.name}`));
12353
+ console.log(chalk2.yellow(`No path found between ${fromEntity.name} and ${toEntity.name}`));
11029
12354
  return;
11030
12355
  }
11031
- console.log(chalk.bold(`Path (${path.length} hop${path.length === 1 ? "" : "s"}):`));
12356
+ console.log(chalk2.bold(`Path (${path.length} hop${path.length === 1 ? "" : "s"}):`));
11032
12357
  for (let i = 0;i < path.length; i++) {
11033
12358
  const e = path[i];
11034
12359
  const arrow = i < path.length - 1 ? " \u2192" : "";
@@ -11055,19 +12380,19 @@ graphCmd.command("stats").description("Show knowledge graph statistics").action(
11055
12380
  });
11056
12381
  return;
11057
12382
  }
11058
- console.log(chalk.bold("Knowledge Graph Stats"));
12383
+ console.log(chalk2.bold("Knowledge Graph Stats"));
11059
12384
  console.log();
11060
- console.log(chalk.bold(`Entities: ${totalEntities}`));
12385
+ console.log(chalk2.bold(`Entities: ${totalEntities}`));
11061
12386
  for (const r of entityRows) {
11062
12387
  console.log(` ${colorEntityType(r.type)}: ${r.count}`);
11063
12388
  }
11064
12389
  console.log();
11065
- console.log(chalk.bold(`Relations: ${totalRelations}`));
12390
+ console.log(chalk2.bold(`Relations: ${totalRelations}`));
11066
12391
  for (const r of relationRows) {
11067
- console.log(` ${chalk.cyan(r.relation_type)}: ${r.count}`);
12392
+ console.log(` ${chalk2.cyan(r.relation_type)}: ${r.count}`);
11068
12393
  }
11069
12394
  console.log();
11070
- console.log(chalk.bold(`Memory links: ${linkCount.count}`));
12395
+ console.log(chalk2.bold(`Memory links: ${linkCount.count}`));
11071
12396
  } catch (e) {
11072
12397
  handleError(e);
11073
12398
  }
@@ -11077,14 +12402,14 @@ function formatWatchLine(m) {
11077
12402
  const cat = colorCategory(m.category);
11078
12403
  const imp = colorImportance(m.importance);
11079
12404
  const value = m.value.length > 100 ? m.value.slice(0, 100) + "..." : m.value;
11080
- const main = ` [${scope}/${cat}] ${chalk.bold(m.key)} = ${value} ${chalk.dim(`(importance: ${imp})`)}`;
12405
+ const main = ` [${scope}/${cat}] ${chalk2.bold(m.key)} = ${value} ${chalk2.dim(`(importance: ${imp})`)}`;
11081
12406
  const parts = [];
11082
12407
  if (m.tags.length > 0)
11083
12408
  parts.push(`Tags: ${m.tags.join(", ")}`);
11084
12409
  if (m.agent_id)
11085
12410
  parts.push(`Agent: ${m.agent_id}`);
11086
12411
  parts.push(`Updated: ${m.updated_at}`);
11087
- const detail = chalk.dim(` ${parts.join(" | ")}`);
12412
+ const detail = chalk2.dim(` ${parts.join(" | ")}`);
11088
12413
  return `${main}
11089
12414
  ${detail}`;
11090
12415
  }
@@ -11104,73 +12429,73 @@ profileCmd.command("list").description("List all available profiles").action(()
11104
12429
  const profiles = listProfiles();
11105
12430
  const active = getActiveProfile();
11106
12431
  if (profiles.length === 0) {
11107
- console.log(chalk.dim("No profiles yet. Create one with: mementos profile set <name>"));
12432
+ console.log(chalk2.dim("No profiles yet. Create one with: mementos profile set <name>"));
11108
12433
  return;
11109
12434
  }
11110
- console.log(chalk.bold("Profiles:"));
12435
+ console.log(chalk2.bold("Profiles:"));
11111
12436
  for (const p of profiles) {
11112
- const marker = p === active ? chalk.green(" \u2713 (active)") : "";
12437
+ const marker = p === active ? chalk2.green(" \u2713 (active)") : "";
11113
12438
  console.log(` ${p}${marker}`);
11114
12439
  }
11115
12440
  if (!active) {
11116
- console.log(chalk.dim(`
12441
+ console.log(chalk2.dim(`
11117
12442
  (no active profile \u2014 using default DB)`));
11118
12443
  }
11119
12444
  });
11120
12445
  profileCmd.command("get").description("Show the currently active profile").action(() => {
11121
12446
  const active = getActiveProfile();
11122
12447
  if (active) {
11123
- console.log(chalk.green(`Active profile: ${active}`));
12448
+ console.log(chalk2.green(`Active profile: ${active}`));
11124
12449
  if (!process.env["MEMENTOS_PROFILE"]) {
11125
- console.log(chalk.dim("(persisted in ~/.mementos/config.json)"));
12450
+ console.log(chalk2.dim("(persisted in ~/.mementos/config.json)"));
11126
12451
  } else {
11127
- console.log(chalk.dim("(from MEMENTOS_PROFILE env var)"));
12452
+ console.log(chalk2.dim("(from MEMENTOS_PROFILE env var)"));
11128
12453
  }
11129
12454
  } else {
11130
- console.log(chalk.dim("No active profile \u2014 using default DB (~/.mementos/mementos.db)"));
12455
+ console.log(chalk2.dim("No active profile \u2014 using default DB (~/.mementos/mementos.db)"));
11131
12456
  }
11132
12457
  });
11133
12458
  profileCmd.command("set <name>").description("Switch to a named profile (creates the DB on first use)").action((name) => {
11134
12459
  const clean = name.trim().toLowerCase().replace(/[^a-z0-9_-]/g, "-");
11135
12460
  if (!clean) {
11136
- console.error(chalk.red("Invalid profile name. Use letters, numbers, hyphens, underscores."));
12461
+ console.error(chalk2.red("Invalid profile name. Use letters, numbers, hyphens, underscores."));
11137
12462
  process.exit(1);
11138
12463
  }
11139
12464
  setActiveProfile(clean);
11140
- console.log(chalk.green(`\u2713 Switched to profile: ${clean}`));
11141
- console.log(chalk.dim(` DB: ~/.mementos/profiles/${clean}.db (created on first use)`));
12465
+ console.log(chalk2.green(`\u2713 Switched to profile: ${clean}`));
12466
+ console.log(chalk2.dim(` DB: ~/.mementos/profiles/${clean}.db (created on first use)`));
11142
12467
  });
11143
12468
  profileCmd.command("unset").description("Clear the active profile (revert to default DB)").action(() => {
11144
12469
  const was = getActiveProfile();
11145
12470
  setActiveProfile(null);
11146
12471
  if (was) {
11147
- console.log(chalk.green(`\u2713 Cleared profile (was: ${was})`));
12472
+ console.log(chalk2.green(`\u2713 Cleared profile (was: ${was})`));
11148
12473
  } else {
11149
- console.log(chalk.dim("No active profile was set."));
12474
+ console.log(chalk2.dim("No active profile was set."));
11150
12475
  }
11151
- console.log(chalk.dim(" Now using default DB: ~/.mementos/mementos.db"));
12476
+ console.log(chalk2.dim(" Now using default DB: ~/.mementos/mementos.db"));
11152
12477
  });
11153
12478
  profileCmd.command("delete <name>").description("Delete a profile and its DB file (irreversible)").option("-y, --yes", "Skip confirmation prompt").action(async (name, opts) => {
11154
12479
  if (!opts.yes) {
11155
12480
  const profiles = listProfiles();
11156
12481
  if (!profiles.includes(name)) {
11157
- console.error(chalk.red(`Profile not found: ${name}`));
12482
+ console.error(chalk2.red(`Profile not found: ${name}`));
11158
12483
  process.exit(1);
11159
12484
  }
11160
- process.stdout.write(chalk.yellow(`Delete profile "${name}" and its DB? This cannot be undone. [y/N] `));
12485
+ process.stdout.write(chalk2.yellow(`Delete profile "${name}" and its DB? This cannot be undone. [y/N] `));
11161
12486
  const answer = await new Promise((resolve4) => {
11162
12487
  process.stdin.once("data", (d) => resolve4(d.toString().trim().toLowerCase()));
11163
12488
  });
11164
12489
  if (answer !== "y" && answer !== "yes") {
11165
- console.log(chalk.dim("Cancelled."));
12490
+ console.log(chalk2.dim("Cancelled."));
11166
12491
  return;
11167
12492
  }
11168
12493
  }
11169
12494
  const deleted = deleteProfile(name);
11170
12495
  if (deleted) {
11171
- console.log(chalk.green(`\u2713 Profile "${name}" deleted.`));
12496
+ console.log(chalk2.green(`\u2713 Profile "${name}" deleted.`));
11172
12497
  } else {
11173
- console.error(chalk.red(`Profile not found: ${name}`));
12498
+ console.error(chalk2.red(`Profile not found: ${name}`));
11174
12499
  process.exit(1);
11175
12500
  }
11176
12501
  });
@@ -11181,23 +12506,23 @@ autoMemory.command("process <turn>").description("Enqueue text for async LLM mem
11181
12506
  if (opts.sync) {
11182
12507
  const provider = providerRegistry2.getAvailable();
11183
12508
  if (!provider) {
11184
- console.error(chalk.red("No LLM provider configured. Set ANTHROPIC_API_KEY, OPENAI_API_KEY, CEREBRAS_API_KEY, or XAI_API_KEY."));
12509
+ console.error(chalk2.red("No LLM provider configured. Set ANTHROPIC_API_KEY, OPENAI_API_KEY, CEREBRAS_API_KEY, or XAI_API_KEY."));
11185
12510
  process.exit(1);
11186
12511
  }
11187
- console.log(chalk.dim(`Using ${provider.name} / ${provider.config.model}...`));
12512
+ console.log(chalk2.dim(`Using ${provider.name} / ${provider.config.model}...`));
11188
12513
  const memories = await provider.extractMemories(turn, {
11189
12514
  agentId: opts.agent,
11190
12515
  projectId: opts.project
11191
12516
  });
11192
12517
  if (memories.length === 0) {
11193
- console.log(chalk.dim("Nothing worth remembering extracted."));
12518
+ console.log(chalk2.dim("Nothing worth remembering extracted."));
11194
12519
  } else {
11195
12520
  memories.forEach((m, i) => {
11196
- console.log(chalk.bold(`
12521
+ console.log(chalk2.bold(`
11197
12522
  [${i + 1}] ${m.category} \xB7 importance ${m.importance}/10 \xB7 ${m.suggestedScope}`));
11198
12523
  console.log(` ${m.content}`);
11199
12524
  if (m.tags.length)
11200
- console.log(chalk.dim(` tags: ${m.tags.join(", ")}`));
12525
+ console.log(chalk2.dim(` tags: ${m.tags.join(", ")}`));
11201
12526
  });
11202
12527
  }
11203
12528
  } else {
@@ -11207,8 +12532,8 @@ autoMemory.command("process <turn>").description("Enqueue text for async LLM mem
11207
12532
  sessionId: opts.session
11208
12533
  });
11209
12534
  const stats = getAutoMemoryStats2();
11210
- console.log(chalk.green("\u2713 Queued for extraction"));
11211
- console.log(chalk.dim(`Queue: ${stats.pending} pending \xB7 ${stats.processed} processed \xB7 ${stats.failed} failed`));
12535
+ console.log(chalk2.green("\u2713 Queued for extraction"));
12536
+ console.log(chalk2.dim(`Queue: ${stats.pending} pending \xB7 ${stats.processed} processed \xB7 ${stats.failed} failed`));
11212
12537
  }
11213
12538
  });
11214
12539
  autoMemory.command("status").description("Show auto-memory queue stats and provider health").action(async () => {
@@ -11217,14 +12542,14 @@ autoMemory.command("status").description("Show auto-memory queue stats and provi
11217
12542
  const stats = getAutoMemoryStats2();
11218
12543
  const config = providerRegistry2.getConfig();
11219
12544
  const health = providerRegistry2.health();
11220
- console.log(chalk.bold("Auto-Memory Status"));
11221
- console.log(` Provider: ${config.enabled ? chalk.green(config.provider) : chalk.red("disabled")} / ${config.model ?? "default"}`);
12545
+ console.log(chalk2.bold("Auto-Memory Status"));
12546
+ console.log(` Provider: ${config.enabled ? chalk2.green(config.provider) : chalk2.red("disabled")} / ${config.model ?? "default"}`);
11222
12547
  console.log(` Queue: ${stats.pending} pending \xB7 ${stats.processing} processing \xB7 ${stats.processed} processed`);
11223
12548
  console.log(` Errors: ${stats.failed} failed \xB7 ${stats.dropped} dropped`);
11224
- console.log(chalk.bold(`
12549
+ console.log(chalk2.bold(`
11225
12550
  Provider Health`));
11226
12551
  for (const [name, info] of Object.entries(health)) {
11227
- const icon = info.available ? chalk.green("\u2713") : chalk.red("\u2717");
12552
+ const icon = info.available ? chalk2.green("\u2713") : chalk2.red("\u2717");
11228
12553
  console.log(` ${icon} ${name.padEnd(12)} ${info.model}`);
11229
12554
  }
11230
12555
  });
@@ -11237,35 +12562,35 @@ autoMemory.command("config").description("Show or update auto-memory provider co
11237
12562
  ...opts.model && { model: opts.model },
11238
12563
  ...opts.minImportance && { minImportance: Number(opts.minImportance) }
11239
12564
  });
11240
- console.log(chalk.green("\u2713 Config updated"));
12565
+ console.log(chalk2.green("\u2713 Config updated"));
11241
12566
  }
11242
12567
  const config = providerRegistry2.getConfig();
11243
- console.log(chalk.bold("Auto-Memory Config"));
12568
+ console.log(chalk2.bold("Auto-Memory Config"));
11244
12569
  console.log(JSON.stringify(config, null, 2));
11245
12570
  });
11246
12571
  autoMemory.command("test <turn>").description("Test extraction without saving (dry run)").option("--provider <name>", "force a specific provider").option("--agent <id>", "agent ID for context").option("--project <id>", "project ID for context").action(async (turn, opts) => {
11247
12572
  const { providerRegistry: providerRegistry2 } = await Promise.resolve().then(() => (init_registry(), exports_registry));
11248
12573
  const provider = opts.provider ? providerRegistry2.getProvider(opts.provider) : providerRegistry2.getAvailable();
11249
12574
  if (!provider) {
11250
- console.error(chalk.red("No LLM provider configured."));
12575
+ console.error(chalk2.red("No LLM provider configured."));
11251
12576
  process.exit(1);
11252
12577
  }
11253
- console.log(chalk.dim(`DRY RUN \u2014 ${provider.name} / ${provider.config.model} \u2014 nothing will be saved
12578
+ console.log(chalk2.dim(`DRY RUN \u2014 ${provider.name} / ${provider.config.model} \u2014 nothing will be saved
11254
12579
  `));
11255
12580
  const memories = await provider.extractMemories(turn, {
11256
12581
  agentId: opts.agent,
11257
12582
  projectId: opts.project
11258
12583
  });
11259
12584
  if (memories.length === 0) {
11260
- console.log(chalk.dim("Nothing extracted."));
12585
+ console.log(chalk2.dim("Nothing extracted."));
11261
12586
  } else {
11262
12587
  memories.forEach((m, i) => {
11263
- console.log(chalk.bold(`[${i + 1}] ${m.category.toUpperCase()} \xB7 importance ${m.importance}/10 \xB7 ${m.suggestedScope}`));
11264
- console.log(` ${chalk.white(m.content)}`);
12588
+ console.log(chalk2.bold(`[${i + 1}] ${m.category.toUpperCase()} \xB7 importance ${m.importance}/10 \xB7 ${m.suggestedScope}`));
12589
+ console.log(` ${chalk2.white(m.content)}`);
11265
12590
  if (m.tags.length)
11266
- console.log(chalk.dim(` tags: ${m.tags.join(", ")}`));
12591
+ console.log(chalk2.dim(` tags: ${m.tags.join(", ")}`));
11267
12592
  if (m.reasoning)
11268
- console.log(chalk.dim(` why: ${m.reasoning}`));
12593
+ console.log(chalk2.dim(` why: ${m.reasoning}`));
11269
12594
  console.log();
11270
12595
  });
11271
12596
  }
@@ -11273,38 +12598,38 @@ autoMemory.command("test <turn>").description("Test extraction without saving (d
11273
12598
  autoMemory.command("enable").description("Enable auto-memory extraction").action(async () => {
11274
12599
  const { configureAutoMemory: configureAutoMemory2 } = await Promise.resolve().then(() => (init_auto_memory(), exports_auto_memory));
11275
12600
  configureAutoMemory2({ enabled: true });
11276
- console.log(chalk.green("\u2713 Auto-memory enabled"));
12601
+ console.log(chalk2.green("\u2713 Auto-memory enabled"));
11277
12602
  });
11278
12603
  autoMemory.command("disable").description("Disable auto-memory extraction").action(async () => {
11279
12604
  const { configureAutoMemory: configureAutoMemory2 } = await Promise.resolve().then(() => (init_auto_memory(), exports_auto_memory));
11280
12605
  configureAutoMemory2({ enabled: false });
11281
- console.log(chalk.yellow("\u26A0 Auto-memory disabled"));
12606
+ console.log(chalk2.yellow("\u26A0 Auto-memory disabled"));
11282
12607
  });
11283
12608
  var hooksCmd = program2.command("hooks").description("Hook registry and webhook management");
11284
12609
  hooksCmd.command("list").description("List registered hooks in the in-memory registry").option("--type <type>", "Filter by hook type").action(async (opts) => {
11285
12610
  const { hookRegistry: hookRegistry2 } = await Promise.resolve().then(() => (init_hooks(), exports_hooks));
11286
12611
  const hooks = hookRegistry2.list(opts.type);
11287
12612
  if (hooks.length === 0) {
11288
- console.log(chalk.gray("No hooks registered."));
12613
+ console.log(chalk2.gray("No hooks registered."));
11289
12614
  return;
11290
12615
  }
11291
12616
  for (const h of hooks) {
11292
- const builtinTag = h.builtin ? chalk.blue(" [builtin]") : "";
11293
- const blockingTag = h.blocking ? chalk.red(" [blocking]") : chalk.gray(" [non-blocking]");
11294
- console.log(`${chalk.cyan(h.id)} ${chalk.bold(h.type)}${builtinTag}${blockingTag} priority=${h.priority}`);
12617
+ const builtinTag = h.builtin ? chalk2.blue(" [builtin]") : "";
12618
+ const blockingTag = h.blocking ? chalk2.red(" [blocking]") : chalk2.gray(" [non-blocking]");
12619
+ console.log(`${chalk2.cyan(h.id)} ${chalk2.bold(h.type)}${builtinTag}${blockingTag} priority=${h.priority}`);
11295
12620
  if (h.description)
11296
- console.log(` ${chalk.gray(h.description)}`);
12621
+ console.log(` ${chalk2.gray(h.description)}`);
11297
12622
  }
11298
12623
  });
11299
12624
  hooksCmd.command("stats").description("Show hook registry statistics").action(async () => {
11300
12625
  const { hookRegistry: hookRegistry2 } = await Promise.resolve().then(() => (init_hooks(), exports_hooks));
11301
12626
  const stats = hookRegistry2.stats();
11302
- console.log(chalk.bold("Hook Registry Stats"));
11303
- console.log(` Total: ${chalk.cyan(stats.total)}`);
11304
- console.log(` Blocking: ${chalk.red(stats.blocking)}`);
11305
- console.log(` Non-blocking:${chalk.green(stats.nonBlocking)}`);
12627
+ console.log(chalk2.bold("Hook Registry Stats"));
12628
+ console.log(` Total: ${chalk2.cyan(stats.total)}`);
12629
+ console.log(` Blocking: ${chalk2.red(stats.blocking)}`);
12630
+ console.log(` Non-blocking:${chalk2.green(stats.nonBlocking)}`);
11306
12631
  if (Object.keys(stats.byType).length > 0) {
11307
- console.log(chalk.bold(`
12632
+ console.log(chalk2.bold(`
11308
12633
  By type:`));
11309
12634
  for (const [type, count] of Object.entries(stats.byType)) {
11310
12635
  console.log(` ${type}: ${count}`);
@@ -11319,16 +12644,16 @@ webhooksCmd.command("list").description("List all persisted webhook hooks").opti
11319
12644
  enabled: opts.disabled ? false : undefined
11320
12645
  });
11321
12646
  if (webhooks.length === 0) {
11322
- console.log(chalk.gray("No webhooks registered."));
12647
+ console.log(chalk2.gray("No webhooks registered."));
11323
12648
  return;
11324
12649
  }
11325
12650
  for (const wh of webhooks) {
11326
- const enabledTag = wh.enabled ? chalk.green("enabled") : chalk.red("disabled");
11327
- const blockingTag = wh.blocking ? chalk.red("blocking") : chalk.gray("non-blocking");
11328
- console.log(`${chalk.cyan(wh.id)} [${enabledTag}] ${chalk.bold(wh.type)} \u2192 ${wh.handlerUrl}`);
12651
+ const enabledTag = wh.enabled ? chalk2.green("enabled") : chalk2.red("disabled");
12652
+ const blockingTag = wh.blocking ? chalk2.red("blocking") : chalk2.gray("non-blocking");
12653
+ console.log(`${chalk2.cyan(wh.id)} [${enabledTag}] ${chalk2.bold(wh.type)} \u2192 ${wh.handlerUrl}`);
11329
12654
  console.log(` ${blockingTag} | priority=${wh.priority} | invocations=${wh.invocationCount} failures=${wh.failureCount}`);
11330
12655
  if (wh.description)
11331
- console.log(` ${chalk.gray(wh.description)}`);
12656
+ console.log(` ${chalk2.gray(wh.description)}`);
11332
12657
  }
11333
12658
  });
11334
12659
  webhooksCmd.command("create <type> <url>").description("Create a persistent webhook hook").option("--blocking", "Block the operation until the webhook responds").option("--priority <n>", "Hook priority (default 50)", "50").option("--agent <id>", "Scope to specific agent").option("--project <id>", "Scope to specific project").option("--description <text>", "Human-readable description").action(async (type, url, opts) => {
@@ -11344,8 +12669,8 @@ webhooksCmd.command("create <type> <url>").description("Create a persistent webh
11344
12669
  description: opts.description
11345
12670
  });
11346
12671
  reloadWebhooks2();
11347
- console.log(chalk.green("\u2713 Webhook created"));
11348
- console.log(` ID: ${chalk.cyan(wh.id)}`);
12672
+ console.log(chalk2.green("\u2713 Webhook created"));
12673
+ console.log(` ID: ${chalk2.cyan(wh.id)}`);
11349
12674
  console.log(` Type: ${wh.type}`);
11350
12675
  console.log(` URL: ${wh.handlerUrl}`);
11351
12676
  });
@@ -11353,9 +12678,9 @@ webhooksCmd.command("delete <id>").description("Delete a webhook by ID").action(
11353
12678
  const { deleteWebhookHook: deleteWebhookHook2 } = await Promise.resolve().then(() => (init_webhook_hooks(), exports_webhook_hooks));
11354
12679
  const deleted = deleteWebhookHook2(id);
11355
12680
  if (deleted) {
11356
- console.log(chalk.green(`\u2713 Webhook ${id} deleted`));
12681
+ console.log(chalk2.green(`\u2713 Webhook ${id} deleted`));
11357
12682
  } else {
11358
- console.error(chalk.red(`Webhook not found: ${id}`));
12683
+ console.error(chalk2.red(`Webhook not found: ${id}`));
11359
12684
  process.exit(1);
11360
12685
  }
11361
12686
  });
@@ -11365,9 +12690,9 @@ webhooksCmd.command("enable <id>").description("Enable a webhook").action(async
11365
12690
  const updated = updateWebhookHook2(id, { enabled: true });
11366
12691
  if (updated) {
11367
12692
  reloadWebhooks2();
11368
- console.log(chalk.green(`\u2713 Webhook ${id} enabled`));
12693
+ console.log(chalk2.green(`\u2713 Webhook ${id} enabled`));
11369
12694
  } else {
11370
- console.error(chalk.red(`Webhook not found: ${id}`));
12695
+ console.error(chalk2.red(`Webhook not found: ${id}`));
11371
12696
  process.exit(1);
11372
12697
  }
11373
12698
  });
@@ -11377,16 +12702,16 @@ webhooksCmd.command("disable <id>").description("Disable a webhook (without dele
11377
12702
  const updated = updateWebhookHook2(id, { enabled: false });
11378
12703
  if (updated) {
11379
12704
  reloadWebhooks2();
11380
- console.log(chalk.yellow(`\u2298 Webhook ${id} disabled`));
12705
+ console.log(chalk2.yellow(`\u2298 Webhook ${id} disabled`));
11381
12706
  } else {
11382
- console.error(chalk.red(`Webhook not found: ${id}`));
12707
+ console.error(chalk2.red(`Webhook not found: ${id}`));
11383
12708
  process.exit(1);
11384
12709
  }
11385
12710
  });
11386
12711
  var synthesisCmd = program2.command("synthesis").alias("synth").description("ALMA memory synthesis \u2014 analyze and consolidate memories");
11387
12712
  synthesisCmd.command("run").description("Run memory synthesis on the corpus").option("--project <id>", "Project ID to synthesize").option("--dry-run", "Preview proposals without applying them").option("--max-proposals <n>", "Maximum proposals to generate", "20").option("--provider <name>", "LLM provider (anthropic, openai, cerebras, grok)").action(async (opts) => {
11388
12713
  const { runSynthesis: runSynthesis2 } = await Promise.resolve().then(() => (init_synthesis2(), exports_synthesis2));
11389
- console.log(chalk.blue("Running memory synthesis..."));
12714
+ console.log(chalk2.blue("Running memory synthesis..."));
11390
12715
  const result = await runSynthesis2({
11391
12716
  projectId: opts.project,
11392
12717
  dryRun: opts.dryRun ?? false,
@@ -11394,44 +12719,44 @@ synthesisCmd.command("run").description("Run memory synthesis on the corpus").op
11394
12719
  provider: opts.provider
11395
12720
  });
11396
12721
  if (result.dryRun) {
11397
- console.log(chalk.yellow(`DRY RUN \u2014 ${result.proposals.length} proposals generated (not applied)`));
12722
+ console.log(chalk2.yellow(`DRY RUN \u2014 ${result.proposals.length} proposals generated (not applied)`));
11398
12723
  } else {
11399
- console.log(chalk.green(`\u2713 Synthesis complete`));
12724
+ console.log(chalk2.green(`\u2713 Synthesis complete`));
11400
12725
  console.log(` Corpus: ${result.run.corpus_size} memories`);
11401
12726
  console.log(` Proposals: ${result.run.proposals_generated} generated, ${result.run.proposals_accepted} applied`);
11402
12727
  }
11403
12728
  if (result.metrics) {
11404
12729
  console.log(` Reduction: ${(result.metrics.corpusReduction * 100).toFixed(1)}%`);
11405
12730
  }
11406
- console.log(` Run ID: ${chalk.cyan(result.run.id)}`);
12731
+ console.log(` Run ID: ${chalk2.cyan(result.run.id)}`);
11407
12732
  });
11408
12733
  synthesisCmd.command("status").description("Show recent synthesis runs").option("--project <id>", "Filter by project").action(async (opts) => {
11409
12734
  const { listSynthesisRuns: listSynthesisRuns2 } = await Promise.resolve().then(() => (init_synthesis(), exports_synthesis));
11410
12735
  const runs = listSynthesisRuns2({ project_id: opts.project, limit: 10 });
11411
12736
  if (runs.length === 0) {
11412
- console.log(chalk.gray("No synthesis runs found."));
12737
+ console.log(chalk2.gray("No synthesis runs found."));
11413
12738
  return;
11414
12739
  }
11415
12740
  for (const run of runs) {
11416
- const statusColor = run.status === "completed" ? chalk.green : run.status === "failed" ? chalk.red : chalk.yellow;
11417
- console.log(`${chalk.cyan(run.id)} [${statusColor(run.status)}] corpus=${run.corpus_size} accepted=${run.proposals_accepted}/${run.proposals_generated} ${run.started_at.slice(0, 10)}`);
12741
+ const statusColor = run.status === "completed" ? chalk2.green : run.status === "failed" ? chalk2.red : chalk2.yellow;
12742
+ console.log(`${chalk2.cyan(run.id)} [${statusColor(run.status)}] corpus=${run.corpus_size} accepted=${run.proposals_accepted}/${run.proposals_generated} ${run.started_at.slice(0, 10)}`);
11418
12743
  }
11419
12744
  });
11420
12745
  synthesisCmd.command("rollback <runId>").description("Roll back a synthesis run").action(async (runId) => {
11421
12746
  const { rollbackSynthesis: rollbackSynthesis2 } = await Promise.resolve().then(() => (init_synthesis2(), exports_synthesis2));
11422
- console.log(chalk.yellow(`Rolling back synthesis run ${runId}...`));
12747
+ console.log(chalk2.yellow(`Rolling back synthesis run ${runId}...`));
11423
12748
  const result = await rollbackSynthesis2(runId);
11424
- console.log(chalk.green(`\u2713 Rolled back ${result.rolled_back} proposals`));
12749
+ console.log(chalk2.green(`\u2713 Rolled back ${result.rolled_back} proposals`));
11425
12750
  if (result.errors.length > 0) {
11426
- console.log(chalk.red(` Errors: ${result.errors.join(", ")}`));
12751
+ console.log(chalk2.red(` Errors: ${result.errors.join(", ")}`));
11427
12752
  }
11428
12753
  });
11429
12754
  var sessionCmd = program2.command("session").description("Session auto-memory \u2014 ingest session transcripts for memory extraction");
11430
12755
  sessionCmd.command("ingest <transcriptFile>").description("Ingest a session transcript file for memory extraction").option("--session-id <id>", "Session ID (default: auto-generated)").option("--agent <id>", "Agent ID").option("--project <id>", "Project ID").option("--source <source>", "Source (claude-code, codex, manual, open-sessions)", "manual").action(async (transcriptFile, opts) => {
11431
- const { readFileSync: readFileSync3 } = await import("fs");
12756
+ const { readFileSync: readFileSync4 } = await import("fs");
11432
12757
  const { createSessionJob: createSessionJob2 } = await Promise.resolve().then(() => (init_session_jobs(), exports_session_jobs));
11433
12758
  const { enqueueSessionJob: enqueueSessionJob2 } = await Promise.resolve().then(() => (init_session_queue(), exports_session_queue));
11434
- const transcript = readFileSync3(transcriptFile, "utf-8");
12759
+ const transcript = readFileSync4(transcriptFile, "utf-8");
11435
12760
  const sessionId = opts.sessionId ?? `cli-${Date.now()}`;
11436
12761
  const job = createSessionJob2({
11437
12762
  session_id: sessionId,
@@ -11441,7 +12766,7 @@ sessionCmd.command("ingest <transcriptFile>").description("Ingest a session tran
11441
12766
  project_id: opts.project
11442
12767
  });
11443
12768
  enqueueSessionJob2(job.id);
11444
- console.log(chalk.green(`\u2713 Session queued: ${chalk.cyan(job.id)}`));
12769
+ console.log(chalk2.green(`\u2713 Session queued: ${chalk2.cyan(job.id)}`));
11445
12770
  console.log(` Session: ${sessionId}`);
11446
12771
  console.log(` Length: ${transcript.length} chars`);
11447
12772
  });
@@ -11449,16 +12774,16 @@ sessionCmd.command("status <jobId>").description("Check status of a session extr
11449
12774
  const { getSessionJob: getSessionJob2 } = await Promise.resolve().then(() => (init_session_jobs(), exports_session_jobs));
11450
12775
  const job = getSessionJob2(jobId);
11451
12776
  if (!job) {
11452
- console.error(chalk.red(`Job not found: ${jobId}`));
12777
+ console.error(chalk2.red(`Job not found: ${jobId}`));
11453
12778
  process.exit(1);
11454
12779
  }
11455
- const statusColor = job.status === "completed" ? chalk.green : job.status === "failed" ? chalk.red : chalk.yellow;
11456
- console.log(`${chalk.cyan(job.id)} [${statusColor(job.status)}]`);
12780
+ const statusColor = job.status === "completed" ? chalk2.green : job.status === "failed" ? chalk2.red : chalk2.yellow;
12781
+ console.log(`${chalk2.cyan(job.id)} [${statusColor(job.status)}]`);
11457
12782
  console.log(` Session: ${job.session_id}`);
11458
12783
  console.log(` Chunks: ${job.chunk_count}`);
11459
12784
  console.log(` Extracted: ${job.memories_extracted} memories`);
11460
12785
  if (job.error)
11461
- console.log(chalk.red(` Error: ${job.error}`));
12786
+ console.log(chalk2.red(` Error: ${job.error}`));
11462
12787
  });
11463
12788
  sessionCmd.command("list").description("List session extraction jobs").option("--agent <id>", "Filter by agent").option("--project <id>", "Filter by project").option("--status <status>", "Filter by status").option("--limit <n>", "Max results", "20").action(async (opts) => {
11464
12789
  const { listSessionJobs: listSessionJobs2 } = await Promise.resolve().then(() => (init_session_jobs(), exports_session_jobs));
@@ -11469,12 +12794,12 @@ sessionCmd.command("list").description("List session extraction jobs").option("-
11469
12794
  limit: parseInt(opts.limit)
11470
12795
  });
11471
12796
  if (jobs.length === 0) {
11472
- console.log(chalk.gray("No session jobs found."));
12797
+ console.log(chalk2.gray("No session jobs found."));
11473
12798
  return;
11474
12799
  }
11475
12800
  for (const job of jobs) {
11476
- const statusColor = job.status === "completed" ? chalk.green : job.status === "failed" ? chalk.red : chalk.yellow;
11477
- console.log(`${chalk.cyan(job.id.slice(0, 8))} [${statusColor(job.status)}] ${job.memories_extracted} memories | ${job.created_at.slice(0, 10)}`);
12801
+ const statusColor = job.status === "completed" ? chalk2.green : job.status === "failed" ? chalk2.red : chalk2.yellow;
12802
+ console.log(`${chalk2.cyan(job.id.slice(0, 8))} [${statusColor(job.status)}] ${job.memories_extracted} memories | ${job.created_at.slice(0, 10)}`);
11478
12803
  }
11479
12804
  });
11480
12805
  sessionCmd.command("setup-hook").description("Install mementos session hook into Claude Code or Codex").option("--claude", "Install Claude Code stop hook").option("--codex", "Install Codex session hook").option("--show", "Print hook script instead of installing").action(async (opts) => {
@@ -11483,26 +12808,26 @@ sessionCmd.command("setup-hook").description("Install mementos session hook into
11483
12808
  if (opts.claude) {
11484
12809
  const script = `${hookPath}/claude-stop-hook.ts`;
11485
12810
  if (opts.show) {
11486
- const { readFileSync: readFileSync3 } = await import("fs");
11487
- console.log(readFileSync3(script, "utf-8"));
12811
+ const { readFileSync: readFileSync4 } = await import("fs");
12812
+ console.log(readFileSync4(script, "utf-8"));
11488
12813
  return;
11489
12814
  }
11490
- console.log(chalk.bold("Claude Code stop hook installation:"));
12815
+ console.log(chalk2.bold("Claude Code stop hook installation:"));
11491
12816
  console.log("");
11492
12817
  console.log("Add to your .claude/settings.json:");
11493
- console.log(chalk.cyan(JSON.stringify({
12818
+ console.log(chalk2.cyan(JSON.stringify({
11494
12819
  hooks: {
11495
12820
  Stop: [{ matcher: "", hooks: [{ type: "command", command: `bun ${script}` }] }]
11496
12821
  }
11497
12822
  }, null, 2)));
11498
12823
  console.log("");
11499
- console.log(`Or run: ${chalk.cyan(`claude hooks add Stop "bun ${script}"`)}`);
12824
+ console.log(`Or run: ${chalk2.cyan(`claude hooks add Stop "bun ${script}"`)}`);
11500
12825
  } else if (opts.codex) {
11501
12826
  const script = `${hookPath}/codex-stop-hook.ts`;
11502
- console.log(chalk.bold("Codex session hook installation:"));
12827
+ console.log(chalk2.bold("Codex session hook installation:"));
11503
12828
  console.log("");
11504
12829
  console.log("Add to ~/.codex/config.toml:");
11505
- console.log(chalk.cyan(`[hooks]
12830
+ console.log(chalk2.cyan(`[hooks]
11506
12831
  session_end = "bun ${script}"`));
11507
12832
  } else {
11508
12833
  console.log("Usage: mementos session setup-hook --claude | --codex");
@@ -11526,7 +12851,7 @@ program2.command("heartbeat [agent-id]").description("Update last_seen_at to sig
11526
12851
  if (globalOpts.json)
11527
12852
  console.log(JSON.stringify({ agent_id: agent.id, name: agent.name, last_seen_at: new Date().toISOString() }));
11528
12853
  else
11529
- console.log(chalk.green(`\u2665 ${agent.name} (${agent.id}) \u2014 heartbeat sent`));
12854
+ console.log(chalk2.green(`\u2665 ${agent.name} (${agent.id}) \u2014 heartbeat sent`));
11530
12855
  });
11531
12856
  program2.command("set-focus [project]").description("Focus this agent on a project (or clear focus if no project given)").option("--agent <id>", "Agent ID").action((project, opts) => {
11532
12857
  const globalOpts = program2.opts();
@@ -11538,9 +12863,9 @@ program2.command("set-focus [project]").description("Focus this agent on a proje
11538
12863
  }
11539
12864
  setFocus(agentId, project ?? null);
11540
12865
  if (project)
11541
- console.log(chalk.green(`Focused: ${agentId} \u2192 project ${project}`));
12866
+ console.log(chalk2.green(`Focused: ${agentId} \u2192 project ${project}`));
11542
12867
  else
11543
- console.log(chalk.dim(`Focus cleared for ${agentId}`));
12868
+ console.log(chalk2.dim(`Focus cleared for ${agentId}`));
11544
12869
  });
11545
12870
  program2.command("get-focus").description("Show the current project focus for an agent").option("--agent <id>", "Agent ID").action((opts) => {
11546
12871
  const globalOpts = program2.opts();
@@ -11552,9 +12877,9 @@ program2.command("get-focus").description("Show the current project focus for an
11552
12877
  }
11553
12878
  const focus = getFocus(agentId);
11554
12879
  if (focus)
11555
- console.log(chalk.cyan(`Focus: ${focus}`));
12880
+ console.log(chalk2.cyan(`Focus: ${focus}`));
11556
12881
  else
11557
- console.log(chalk.dim("No focus set."));
12882
+ console.log(chalk2.dim("No focus set."));
11558
12883
  });
11559
12884
  program2.command("remove <nameOrId>").description("Remove/delete a memory by name or ID (alias for memory delete)").option("--agent <id>", "Agent ID").action((nameOrId, opts) => {
11560
12885
  const globalOpts = program2.opts();
@@ -11570,15 +12895,271 @@ program2.command("remove <nameOrId>").description("Remove/delete a memory by nam
11570
12895
  id = mem.id;
11571
12896
  }
11572
12897
  if (!id) {
11573
- console.error(chalk.red(`Memory not found: ${nameOrId}`));
12898
+ console.error(chalk2.red(`Memory not found: ${nameOrId}`));
11574
12899
  process.exit(1);
11575
12900
  }
11576
12901
  const deleted = deleteMemory2(id);
11577
12902
  if (deleted)
11578
- console.log(chalk.green(`\u2713 Memory ${id.slice(0, 8)} removed`));
12903
+ console.log(chalk2.green(`\u2713 Memory ${id.slice(0, 8)} removed`));
11579
12904
  else {
11580
- console.error(chalk.red(`Memory not found: ${nameOrId}`));
12905
+ console.error(chalk2.red(`Memory not found: ${nameOrId}`));
11581
12906
  process.exit(1);
11582
12907
  }
11583
12908
  });
12909
+ program2.command("tool-events [tool_name]").description("List tool events, optionally filtered by tool name").option("--limit <n>", "Max results (default: 20)", parseInt).option("--project-id <id>", "Filter by project ID").action((toolName, opts) => {
12910
+ try {
12911
+ const globalOpts = program2.opts();
12912
+ const { getToolEvents: getToolEvents2 } = (init_tool_events(), __toCommonJS(exports_tool_events));
12913
+ const limit = opts.limit || 20;
12914
+ const events = getToolEvents2({
12915
+ tool_name: toolName,
12916
+ project_id: opts.projectId,
12917
+ limit
12918
+ });
12919
+ if (globalOpts.json) {
12920
+ outputJson(events);
12921
+ return;
12922
+ }
12923
+ if (events.length === 0) {
12924
+ console.log(chalk2.yellow("No tool events found."));
12925
+ return;
12926
+ }
12927
+ console.log(chalk2.bold(`${events.length} tool event${events.length === 1 ? "" : "s"}:`));
12928
+ console.log(` ${chalk2.dim("tool_name".padEnd(24))} ${chalk2.dim("action".padEnd(16))} ${chalk2.dim("success")} ${chalk2.dim("error_type".padEnd(20))} ${chalk2.dim("created_at")}`);
12929
+ for (const e of events) {
12930
+ const successStr = e.success ? chalk2.green("true ") : chalk2.red("false ");
12931
+ const errorType = (e.error_type || "").padEnd(20);
12932
+ const action = (e.action || "-").padEnd(16);
12933
+ console.log(` ${e.tool_name.padEnd(24)} ${action} ${successStr} ${errorType} ${chalk2.dim(e.created_at)}`);
12934
+ }
12935
+ } catch (e) {
12936
+ handleError(e);
12937
+ }
12938
+ });
12939
+ program2.command("tool-insights <tool_name>").description("Show tool guide/stats and lessons for a tool").option("--project-id <id>", "Filter by project ID").action((toolName, opts) => {
12940
+ try {
12941
+ const globalOpts = program2.opts();
12942
+ const { getToolStats: getToolStats2, getToolLessons: getToolLessons2 } = (init_tool_events(), __toCommonJS(exports_tool_events));
12943
+ const projectId = opts.projectId;
12944
+ const stats = getToolStats2(toolName, projectId);
12945
+ const lessons = getToolLessons2(toolName, projectId);
12946
+ if (globalOpts.json) {
12947
+ outputJson({ stats, lessons });
12948
+ return;
12949
+ }
12950
+ const successRate = (stats.success_rate * 100).toFixed(1);
12951
+ console.log(chalk2.bold(`Tool: ${toolName}`));
12952
+ console.log(` Calls: ${stats.total_calls} Success: ${chalk2.green(String(stats.success_count))} Failures: ${chalk2.red(String(stats.failure_count))} Rate: ${successRate}%` + (stats.avg_latency_ms !== null ? ` Avg latency: ${stats.avg_latency_ms.toFixed(0)}ms` : "") + (stats.last_used ? ` Last used: ${chalk2.dim(stats.last_used)}` : ""));
12953
+ if (stats.common_errors.length > 0) {
12954
+ console.log(chalk2.bold(`
12955
+ Common errors:`));
12956
+ for (const err of stats.common_errors) {
12957
+ console.log(` ${chalk2.red(err.error_type)}: ${err.count} times`);
12958
+ }
12959
+ }
12960
+ if (lessons.length === 0) {
12961
+ console.log(chalk2.dim(`
12962
+ No lessons recorded.`));
12963
+ return;
12964
+ }
12965
+ console.log(chalk2.bold(`
12966
+ Lessons (${lessons.length}):`));
12967
+ for (const l of lessons) {
12968
+ console.log(` ${chalk2.cyan("-")} ${l.lesson} ${chalk2.dim(`(${l.created_at.slice(0, 10)})`)}`);
12969
+ if (l.when_to_use) {
12970
+ console.log(` ${chalk2.dim("when_to_use:")} ${l.when_to_use}`);
12971
+ }
12972
+ }
12973
+ } catch (e) {
12974
+ handleError(e);
12975
+ }
12976
+ });
12977
+ program2.command("synthesized-profile").description("Show or refresh the synthesized agent/project profile").option("--project-id <id>", "Project ID").option("--refresh", "Force refresh the profile (re-synthesize from memories)").action(async (opts) => {
12978
+ try {
12979
+ const globalOpts = program2.opts();
12980
+ const { synthesizeProfile: synthesizeProfile2 } = await Promise.resolve().then(() => (init_profile_synthesizer(), exports_profile_synthesizer));
12981
+ let projectId = opts.projectId;
12982
+ if (!projectId && globalOpts.project) {
12983
+ const project = getProject(resolve3(globalOpts.project));
12984
+ if (project)
12985
+ projectId = project.id;
12986
+ }
12987
+ const result = await synthesizeProfile2({
12988
+ project_id: projectId,
12989
+ agent_id: globalOpts.agent,
12990
+ force_refresh: !!opts.refresh
12991
+ });
12992
+ if (!result) {
12993
+ if (globalOpts.json) {
12994
+ outputJson({ error: "No profile available (no preference/fact memories found)" });
12995
+ } else {
12996
+ console.log(chalk2.yellow("No profile available \u2014 save some preference or fact memories first."));
12997
+ }
12998
+ return;
12999
+ }
13000
+ if (globalOpts.json) {
13001
+ outputJson(result);
13002
+ return;
13003
+ }
13004
+ if (result.from_cache) {
13005
+ console.log(chalk2.dim(`(cached profile)
13006
+ `));
13007
+ } else {
13008
+ console.log(chalk2.dim(`(synthesized from ${result.memory_count} memories)
13009
+ `));
13010
+ }
13011
+ console.log(result.profile);
13012
+ } catch (e) {
13013
+ handleError(e);
13014
+ }
13015
+ });
13016
+ program2.command("chain <sequence_group>").description("Show a memory chain (memories linked by sequence_group, ordered by sequence_order)").action((sequenceGroup) => {
13017
+ try {
13018
+ const globalOpts = program2.opts();
13019
+ const db = getDatabase();
13020
+ const rows = db.query("SELECT * FROM memories WHERE sequence_group = ? AND status = 'active' ORDER BY sequence_order ASC").all(sequenceGroup);
13021
+ const memories = rows.map(parseMemoryRow);
13022
+ if (globalOpts.json) {
13023
+ outputJson(memories);
13024
+ return;
13025
+ }
13026
+ if (memories.length === 0) {
13027
+ console.log(chalk2.yellow(`No chain found for sequence group: ${sequenceGroup}`));
13028
+ return;
13029
+ }
13030
+ console.log(chalk2.bold(`Chain: ${sequenceGroup} (${memories.length} step${memories.length === 1 ? "" : "s"}):
13031
+ `));
13032
+ for (let i = 0;i < memories.length; i++) {
13033
+ const m = memories[i];
13034
+ const order = m.sequence_order !== null && m.sequence_order !== undefined ? m.sequence_order : i + 1;
13035
+ const value = m.value.length > 120 ? m.value.slice(0, 120) + "..." : m.value;
13036
+ console.log(` ${chalk2.cyan(String(order) + ".")} ${chalk2.bold(m.key)}: ${value}`);
13037
+ }
13038
+ } catch (e) {
13039
+ handleError(e);
13040
+ }
13041
+ });
13042
+ program2.command("when-to-use <memory_id>").description("Show the when_to_use guidance for a memory").action((memoryId) => {
13043
+ try {
13044
+ const globalOpts = program2.opts();
13045
+ const resolvedId = resolveMemoryId(memoryId);
13046
+ const memory = getMemory(resolvedId);
13047
+ if (!memory) {
13048
+ if (globalOpts.json) {
13049
+ outputJson({ error: `Memory not found: ${memoryId}` });
13050
+ } else {
13051
+ console.error(chalk2.red(`Memory not found: ${memoryId}`));
13052
+ }
13053
+ process.exit(1);
13054
+ }
13055
+ const whenToUse = memory.when_to_use ?? null;
13056
+ if (globalOpts.json) {
13057
+ outputJson({ id: memory.id, key: memory.key, when_to_use: whenToUse });
13058
+ return;
13059
+ }
13060
+ console.log(chalk2.bold(`${memory.key} (${memory.id.slice(0, 8)})`));
13061
+ if (whenToUse) {
13062
+ console.log(` ${chalk2.cyan("when_to_use:")} ${whenToUse}`);
13063
+ } else {
13064
+ console.log(chalk2.dim(" (not set)"));
13065
+ }
13066
+ } catch (e) {
13067
+ handleError(e);
13068
+ }
13069
+ });
13070
+ var sessionsCmd = program2.command("sessions").description("Session registry \u2014 list, clean, and inspect active Claude Code sessions");
13071
+ sessionsCmd.command("list").description("List all active sessions in the registry").option("--project <name>", "Filter by project name").option("--agent <name>", "Filter by agent name").option("--format <fmt>", "Output format: compact (default), json, yaml").action((opts) => {
13072
+ try {
13073
+ const globalOpts = program2.opts();
13074
+ const { listSessions: listSessions2 } = (init_session_registry(), __toCommonJS(exports_session_registry));
13075
+ const sessions = listSessions2({
13076
+ project_name: opts.project,
13077
+ agent_name: opts.agent || globalOpts.agent
13078
+ });
13079
+ const fmt = getOutputFormat(opts.format);
13080
+ if (fmt === "json") {
13081
+ outputJson(sessions);
13082
+ return;
13083
+ }
13084
+ if (fmt === "yaml") {
13085
+ outputYaml(sessions);
13086
+ return;
13087
+ }
13088
+ if (sessions.length === 0) {
13089
+ console.log(chalk2.yellow("No active sessions found."));
13090
+ return;
13091
+ }
13092
+ console.log(chalk2.bold(`${sessions.length} active session${sessions.length === 1 ? "" : "s"}:
13093
+ `));
13094
+ for (const s of sessions) {
13095
+ const pid = chalk2.dim(`pid:${s.pid}`);
13096
+ const agent = s.agent_name ? chalk2.cyan(s.agent_name) : chalk2.dim("(no agent)");
13097
+ const project = s.project_name ? chalk2.yellow(s.project_name) : chalk2.dim("(no project)");
13098
+ const mcp = chalk2.dim(s.mcp_server);
13099
+ const self = s.pid === process.pid ? chalk2.green(" (self)") : "";
13100
+ console.log(` ${chalk2.bold(s.id)} ${pid}${self} ${agent} ${project} ${mcp}`);
13101
+ console.log(` ${chalk2.dim(`cwd: ${s.cwd}`)} ${chalk2.dim(`last seen: ${s.last_seen_at}`)}`);
13102
+ }
13103
+ } catch (e) {
13104
+ handleError(e);
13105
+ }
13106
+ });
13107
+ sessionsCmd.command("send <message>").description("Send a message to sessions (use MCP tool memory_send_channel for full support)").option("--agent <name>", "Target agent name").option("--project <name>", "Target project name").option("--all", "Broadcast to all sessions").action((message, opts) => {
13108
+ try {
13109
+ const globalOpts = program2.opts();
13110
+ const { listSessions: listSessions2 } = (init_session_registry(), __toCommonJS(exports_session_registry));
13111
+ if (!opts.agent && !opts.project && !opts.all) {
13112
+ console.error(chalk2.red("Specify a target: --agent <name>, --project <name>, or --all"));
13113
+ process.exit(1);
13114
+ }
13115
+ const filter = {};
13116
+ if (opts.agent)
13117
+ filter.agent_name = opts.agent;
13118
+ if (opts.project)
13119
+ filter.project_name = opts.project;
13120
+ const sessions = listSessions2(opts.all ? undefined : filter);
13121
+ if (globalOpts.json) {
13122
+ outputJson({
13123
+ message: "Channel push requires MCP server context. Use the memory_send_channel MCP tool.",
13124
+ matching_sessions: sessions.length,
13125
+ sessions: sessions.map((s) => ({
13126
+ id: s.id,
13127
+ pid: s.pid,
13128
+ agent_name: s.agent_name,
13129
+ project_name: s.project_name
13130
+ }))
13131
+ });
13132
+ return;
13133
+ }
13134
+ console.log(chalk2.bold(`Found ${sessions.length} matching session${sessions.length === 1 ? "" : "s"}:`));
13135
+ for (const s of sessions) {
13136
+ const agent = s.agent_name ? chalk2.cyan(s.agent_name) : chalk2.dim("(no agent)");
13137
+ const project = s.project_name ? chalk2.yellow(s.project_name) : "";
13138
+ console.log(` ${s.id} pid:${s.pid} ${agent} ${project}`);
13139
+ }
13140
+ console.log();
13141
+ console.log(chalk2.dim("Channel push requires the MCP server context."));
13142
+ console.log(chalk2.dim("Use the MCP tool:"));
13143
+ console.log(chalk2.cyan(` memory_send_channel(content="${message.slice(0, 60)}${message.length > 60 ? "..." : ""}")`));
13144
+ } catch (e) {
13145
+ handleError(e);
13146
+ }
13147
+ });
13148
+ sessionsCmd.command("clean").description("Remove dead/stale sessions from the registry").action(() => {
13149
+ try {
13150
+ const globalOpts = program2.opts();
13151
+ const { cleanStaleSessions: cleanStaleSessions2 } = (init_session_registry(), __toCommonJS(exports_session_registry));
13152
+ const cleaned = cleanStaleSessions2();
13153
+ if (globalOpts.json) {
13154
+ outputJson({ cleaned });
13155
+ } else if (cleaned === 0) {
13156
+ console.log(chalk2.green("No stale sessions found \u2014 registry is clean."));
13157
+ } else {
13158
+ console.log(chalk2.green(`Cleaned ${cleaned} stale session${cleaned === 1 ? "" : "s"}.`));
13159
+ }
13160
+ } catch (e) {
13161
+ handleError(e);
13162
+ }
13163
+ });
13164
+ program2.addCommand(makeBrainsCommand());
11584
13165
  program2.parse(process.argv);