@hasna/mementos 0.11.1 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/dist/cli/brains.d.ts +3 -0
  2. package/dist/cli/brains.d.ts.map +1 -0
  3. package/dist/cli/index.js +2064 -504
  4. package/dist/db/database.d.ts.map +1 -1
  5. package/dist/db/memories.d.ts.map +1 -1
  6. package/dist/db/tool-events.d.ts +27 -0
  7. package/dist/db/tool-events.d.ts.map +1 -0
  8. package/dist/index.d.ts +2 -0
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +172 -4
  11. package/dist/lib/activation-matcher.d.ts +16 -0
  12. package/dist/lib/activation-matcher.d.ts.map +1 -0
  13. package/dist/lib/asmr/categorizer.d.ts +31 -0
  14. package/dist/lib/asmr/categorizer.d.ts.map +1 -0
  15. package/dist/lib/asmr/context-agent.d.ts +4 -0
  16. package/dist/lib/asmr/context-agent.d.ts.map +1 -0
  17. package/dist/lib/asmr/ensemble.d.ts +23 -0
  18. package/dist/lib/asmr/ensemble.d.ts.map +1 -0
  19. package/dist/lib/asmr/fact-agent.d.ts +4 -0
  20. package/dist/lib/asmr/fact-agent.d.ts.map +1 -0
  21. package/dist/lib/asmr/index.d.ts +7 -0
  22. package/dist/lib/asmr/index.d.ts.map +1 -0
  23. package/dist/lib/asmr/orchestrator.d.ts +4 -0
  24. package/dist/lib/asmr/orchestrator.d.ts.map +1 -0
  25. package/dist/lib/asmr/temporal-agent.d.ts +4 -0
  26. package/dist/lib/asmr/temporal-agent.d.ts.map +1 -0
  27. package/dist/lib/asmr/types.d.ts +27 -0
  28. package/dist/lib/asmr/types.d.ts.map +1 -0
  29. package/dist/lib/auto-inject-orchestrator.d.ts +57 -0
  30. package/dist/lib/auto-inject-orchestrator.d.ts.map +1 -0
  31. package/dist/lib/built-in-hooks.d.ts.map +1 -1
  32. package/dist/lib/channel-pusher.d.ts +39 -0
  33. package/dist/lib/channel-pusher.d.ts.map +1 -0
  34. package/dist/lib/connectors/files.d.ts +8 -0
  35. package/dist/lib/connectors/files.d.ts.map +1 -0
  36. package/dist/lib/connectors/github.d.ts +7 -0
  37. package/dist/lib/connectors/github.d.ts.map +1 -0
  38. package/dist/lib/connectors/index.d.ts +12 -0
  39. package/dist/lib/connectors/index.d.ts.map +1 -0
  40. package/dist/lib/connectors/notion.d.ts +7 -0
  41. package/dist/lib/connectors/notion.d.ts.map +1 -0
  42. package/dist/lib/connectors/types.d.ts +27 -0
  43. package/dist/lib/connectors/types.d.ts.map +1 -0
  44. package/dist/lib/context-extractor.d.ts +14 -0
  45. package/dist/lib/context-extractor.d.ts.map +1 -0
  46. package/dist/lib/extractors/audio.d.ts +8 -0
  47. package/dist/lib/extractors/audio.d.ts.map +1 -0
  48. package/dist/lib/extractors/index.d.ts +12 -0
  49. package/dist/lib/extractors/index.d.ts.map +1 -0
  50. package/dist/lib/extractors/ocr.d.ts +7 -0
  51. package/dist/lib/extractors/ocr.d.ts.map +1 -0
  52. package/dist/lib/extractors/pdf.d.ts +7 -0
  53. package/dist/lib/extractors/pdf.d.ts.map +1 -0
  54. package/dist/lib/extractors/types.d.ts +12 -0
  55. package/dist/lib/extractors/types.d.ts.map +1 -0
  56. package/dist/lib/gatherer.d.ts +16 -0
  57. package/dist/lib/gatherer.d.ts.map +1 -0
  58. package/dist/lib/injector.d.ts +48 -1
  59. package/dist/lib/injector.d.ts.map +1 -1
  60. package/dist/lib/matryoshka.d.ts +50 -0
  61. package/dist/lib/matryoshka.d.ts.map +1 -0
  62. package/dist/lib/model-config.d.ts +14 -0
  63. package/dist/lib/model-config.d.ts.map +1 -0
  64. package/dist/lib/procedural-extractor.d.ts +21 -0
  65. package/dist/lib/procedural-extractor.d.ts.map +1 -0
  66. package/dist/lib/profile-synthesizer.d.ts +20 -0
  67. package/dist/lib/profile-synthesizer.d.ts.map +1 -0
  68. package/dist/lib/session-processor.d.ts.map +1 -1
  69. package/dist/lib/session-registry.d.ts +47 -0
  70. package/dist/lib/session-registry.d.ts.map +1 -0
  71. package/dist/lib/session-start-briefing.d.ts +10 -0
  72. package/dist/lib/session-start-briefing.d.ts.map +1 -0
  73. package/dist/lib/session-watcher.d.ts +30 -0
  74. package/dist/lib/session-watcher.d.ts.map +1 -0
  75. package/dist/lib/tool-lesson-extractor.d.ts +24 -0
  76. package/dist/lib/tool-lesson-extractor.d.ts.map +1 -0
  77. package/dist/lib/tool-memory-synthesizer.d.ts +28 -0
  78. package/dist/lib/tool-memory-synthesizer.d.ts.map +1 -0
  79. package/dist/lib/topic-clusterer.d.ts +21 -0
  80. package/dist/lib/topic-clusterer.d.ts.map +1 -0
  81. package/dist/lib/when-to-use-generator.d.ts +22 -0
  82. package/dist/lib/when-to-use-generator.d.ts.map +1 -0
  83. package/dist/mcp/index.d.ts +3 -1
  84. package/dist/mcp/index.d.ts.map +1 -1
  85. package/dist/mcp/index.js +3816 -383
  86. package/dist/server/index.d.ts.map +1 -1
  87. package/dist/server/index.js +873 -5
  88. package/dist/types/index.d.ts +57 -0
  89. package/dist/types/index.d.ts.map +1 -1
  90. package/package.json +3 -1
package/dist/cli/index.js CHANGED
@@ -2909,6 +2909,44 @@ CREATE INDEX IF NOT EXISTS idx_memory_embeddings_model ON memory_embeddings(mode
2909
2909
 
2910
2910
  PRAGMA foreign_keys = ON;
2911
2911
  INSERT OR IGNORE INTO _migrations (id) VALUES (29);
2912
+ `,
2913
+ `
2914
+ ALTER TABLE memories ADD COLUMN when_to_use TEXT DEFAULT NULL;
2915
+ CREATE INDEX IF NOT EXISTS idx_memories_when_to_use ON memories(when_to_use) WHERE when_to_use IS NOT NULL;
2916
+ ALTER TABLE memory_versions ADD COLUMN when_to_use TEXT;
2917
+ INSERT OR IGNORE INTO _migrations (id) VALUES (30);
2918
+ `,
2919
+ `
2920
+ CREATE TABLE IF NOT EXISTS tool_events (
2921
+ id TEXT PRIMARY KEY,
2922
+ tool_name TEXT NOT NULL,
2923
+ action TEXT,
2924
+ success INTEGER NOT NULL DEFAULT 1,
2925
+ error_type TEXT CHECK(error_type IS NULL OR error_type IN ('timeout', 'permission', 'not_found', 'syntax', 'rate_limit', 'other')),
2926
+ error_message TEXT,
2927
+ tokens_used INTEGER,
2928
+ latency_ms INTEGER,
2929
+ context TEXT,
2930
+ lesson TEXT,
2931
+ when_to_use TEXT,
2932
+ agent_id TEXT REFERENCES agents(id) ON DELETE SET NULL,
2933
+ project_id TEXT REFERENCES projects(id) ON DELETE SET NULL,
2934
+ session_id TEXT,
2935
+ metadata TEXT DEFAULT '{}',
2936
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
2937
+ );
2938
+ CREATE INDEX IF NOT EXISTS idx_tool_events_tool_name ON tool_events(tool_name);
2939
+ CREATE INDEX IF NOT EXISTS idx_tool_events_agent ON tool_events(agent_id);
2940
+ CREATE INDEX IF NOT EXISTS idx_tool_events_project ON tool_events(project_id);
2941
+ CREATE INDEX IF NOT EXISTS idx_tool_events_success ON tool_events(success);
2942
+ CREATE INDEX IF NOT EXISTS idx_tool_events_created ON tool_events(created_at);
2943
+ INSERT OR IGNORE INTO _migrations (id) VALUES (31);
2944
+ `,
2945
+ `
2946
+ ALTER TABLE memories ADD COLUMN sequence_group TEXT DEFAULT NULL;
2947
+ ALTER TABLE memories ADD COLUMN sequence_order INTEGER DEFAULT NULL;
2948
+ CREATE INDEX IF NOT EXISTS idx_memories_sequence_group ON memories(sequence_group) WHERE sequence_group IS NOT NULL;
2949
+ INSERT OR IGNORE INTO _migrations (id) VALUES (32);
2912
2950
  `
2913
2951
  ];
2914
2952
  });
@@ -3317,6 +3355,9 @@ function parseMemoryRow(row) {
3317
3355
  session_id: row["session_id"] || null,
3318
3356
  machine_id: row["machine_id"] || null,
3319
3357
  flag: row["flag"] || null,
3358
+ when_to_use: row["when_to_use"] || null,
3359
+ sequence_group: row["sequence_group"] || null,
3360
+ sequence_order: row["sequence_order"] ?? null,
3320
3361
  content_type: row["content_type"] || "text",
3321
3362
  namespace: row["namespace"] || null,
3322
3363
  created_by_agent: row["created_by_agent"] || null,
@@ -3375,6 +3416,7 @@ function createMemory(input, dedupeMode = "merge", db) {
3375
3416
  d.run(`UPDATE memories SET
3376
3417
  value = ?, category = ?, summary = ?, tags = ?,
3377
3418
  importance = ?, metadata = ?, expires_at = ?,
3419
+ when_to_use = ?,
3378
3420
  pinned = COALESCE(pinned, 0),
3379
3421
  version = version + 1, updated_at = ?
3380
3422
  WHERE id = ?`, [
@@ -3385,6 +3427,7 @@ function createMemory(input, dedupeMode = "merge", db) {
3385
3427
  input.importance ?? 5,
3386
3428
  metadataJson,
3387
3429
  expiresAt,
3430
+ input.when_to_use || null,
3388
3431
  timestamp,
3389
3432
  existing.id
3390
3433
  ]);
@@ -3409,8 +3452,8 @@ function createMemory(input, dedupeMode = "merge", db) {
3409
3452
  return merged;
3410
3453
  }
3411
3454
  }
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, ?, ?, ?, ?, ?, ?)`, [
3455
+ 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)
3456
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 'active', 0, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, 1, ?, ?, ?, ?, ?, ?)`, [
3414
3457
  id,
3415
3458
  input.key,
3416
3459
  input.value,
@@ -3426,6 +3469,9 @@ function createMemory(input, dedupeMode = "merge", db) {
3426
3469
  input.machine_id || null,
3427
3470
  input.namespace || null,
3428
3471
  input.agent_id || null,
3472
+ input.when_to_use || null,
3473
+ input.sequence_group || null,
3474
+ input.sequence_order ?? null,
3429
3475
  metadataJson,
3430
3476
  expiresAt,
3431
3477
  input.metadata?.valid_from ?? timestamp,
@@ -3636,8 +3682,8 @@ function updateMemory(id, input, db) {
3636
3682
  throw new VersionConflictError(id, input.version, existing.version);
3637
3683
  }
3638
3684
  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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
3685
+ 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)
3686
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
3641
3687
  uuid(),
3642
3688
  existing.id,
3643
3689
  existing.version,
@@ -3649,6 +3695,7 @@ function updateMemory(id, input, db) {
3649
3695
  existing.summary,
3650
3696
  existing.pinned ? 1 : 0,
3651
3697
  existing.status,
3698
+ existing.when_to_use || null,
3652
3699
  existing.updated_at
3653
3700
  ]);
3654
3701
  } catch {}
@@ -3694,6 +3741,10 @@ function updateMemory(id, input, db) {
3694
3741
  sets.push("flag = ?");
3695
3742
  params.push(input.flag ?? null);
3696
3743
  }
3744
+ if (input.when_to_use !== undefined) {
3745
+ sets.push("when_to_use = ?");
3746
+ params.push(input.when_to_use ?? null);
3747
+ }
3697
3748
  if (input.tags !== undefined) {
3698
3749
  sets.push("tags = ?");
3699
3750
  params.push(JSON.stringify(input.tags));
@@ -5965,6 +6016,311 @@ var init_synthesis = __esm(() => {
5965
6016
  init_database();
5966
6017
  });
5967
6018
 
6019
+ // src/lib/when-to-use-generator.ts
6020
+ var exports_when_to_use_generator = {};
6021
+ __export(exports_when_to_use_generator, {
6022
+ generateWhenToUse: () => generateWhenToUse,
6023
+ autoGenerateWhenToUse: () => autoGenerateWhenToUse
6024
+ });
6025
+ async function generateWhenToUse(key, value, category, tags) {
6026
+ if (process.env["MEMENTOS_AUTO_WHEN_TO_USE"] !== "true")
6027
+ return null;
6028
+ const apiKey = process.env["ANTHROPIC_API_KEY"];
6029
+ if (!apiKey)
6030
+ return null;
6031
+ try {
6032
+ const userMessage = `Key: "${key}"
6033
+ Value: "${value}"
6034
+ Category: ${category}
6035
+ Tags: ${tags.join(", ") || "none"}
6036
+
6037
+ Generate the when_to_use activation context (1-2 sentences):`;
6038
+ const response = await fetch("https://api.anthropic.com/v1/messages", {
6039
+ method: "POST",
6040
+ headers: {
6041
+ "x-api-key": apiKey,
6042
+ "anthropic-version": "2023-06-01",
6043
+ "content-type": "application/json"
6044
+ },
6045
+ body: JSON.stringify({
6046
+ model: "claude-haiku-4-5-20251001",
6047
+ max_tokens: 150,
6048
+ system: SYSTEM_PROMPT2,
6049
+ messages: [{ role: "user", content: userMessage }]
6050
+ })
6051
+ });
6052
+ if (!response.ok)
6053
+ return null;
6054
+ const data = await response.json();
6055
+ const text = data.content?.[0]?.text?.trim();
6056
+ return text || null;
6057
+ } catch {
6058
+ return null;
6059
+ }
6060
+ }
6061
+ async function autoGenerateWhenToUse(ctx) {
6062
+ if (ctx.memory.when_to_use)
6063
+ return;
6064
+ if (process.env["MEMENTOS_AUTO_WHEN_TO_USE"] !== "true")
6065
+ return;
6066
+ try {
6067
+ const whenToUse = await generateWhenToUse(ctx.memory.key, ctx.memory.value, ctx.memory.category, ctx.memory.tags);
6068
+ if (whenToUse) {
6069
+ const db = getDatabase();
6070
+ db.run("UPDATE memories SET when_to_use = ? WHERE id = ? AND when_to_use IS NULL", [whenToUse, ctx.memory.id]);
6071
+ }
6072
+ } catch {}
6073
+ }
6074
+ 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.
6075
+
6076
+ Rules:
6077
+ - Start with "When" or "If"
6078
+ - Describe the situation, not the content
6079
+ - Be specific enough to avoid false matches but general enough to catch relevant scenarios
6080
+ - Focus on the task/action the agent would be doing, not what the memory contains
6081
+
6082
+ Examples:
6083
+ - Key: "preferred-language", Value: "Always use TypeScript, never JavaScript" \u2192 "When choosing a programming language for a new file or project"
6084
+ - Key: "db-migration-order", Value: "Always run migrations before deploying" \u2192 "When deploying or updating database schema"
6085
+ - Key: "bash-chain-bug", Value: "Bash tool mangles && chains" \u2192 "When chaining commands with && in the Bash tool"`;
6086
+ var init_when_to_use_generator = __esm(() => {
6087
+ init_database();
6088
+ });
6089
+
6090
+ // src/lib/profile-synthesizer.ts
6091
+ var exports_profile_synthesizer = {};
6092
+ __export(exports_profile_synthesizer, {
6093
+ synthesizeProfile: () => synthesizeProfile,
6094
+ markProfileStale: () => markProfileStale,
6095
+ getProfileKey: () => getProfileKey
6096
+ });
6097
+ function getProfileKey(scope, id) {
6098
+ return `_profile_${scope}_${id}`;
6099
+ }
6100
+ async function synthesizeProfile(options) {
6101
+ const scope = options.scope || (options.project_id ? "project" : options.agent_id ? "agent" : "global");
6102
+ const id = options.project_id || options.agent_id || "global";
6103
+ const profileKey = getProfileKey(scope, id);
6104
+ if (!options.force_refresh) {
6105
+ const cached = getMemoryByKey(profileKey, "shared", undefined, options.project_id);
6106
+ if (cached) {
6107
+ const age = Date.now() - new Date(cached.updated_at).getTime();
6108
+ const maxAge = 24 * 60 * 60 * 1000;
6109
+ const isStale = cached.metadata?.stale === true;
6110
+ if (age < maxAge && !isStale) {
6111
+ return { profile: cached.value, memory_count: 0, from_cache: true };
6112
+ }
6113
+ }
6114
+ }
6115
+ const prefMemories = listMemories({
6116
+ category: "preference",
6117
+ project_id: options.project_id,
6118
+ status: "active",
6119
+ limit: 30
6120
+ });
6121
+ const factMemories = listMemories({
6122
+ category: "fact",
6123
+ project_id: options.project_id,
6124
+ status: "active",
6125
+ limit: 30
6126
+ });
6127
+ const allMemories = [...prefMemories, ...factMemories];
6128
+ if (allMemories.length === 0)
6129
+ return null;
6130
+ const apiKey = process.env["ANTHROPIC_API_KEY"];
6131
+ if (!apiKey) {
6132
+ const lines = allMemories.map((m) => `- ${m.key}: ${m.value}`).join(`
6133
+ `);
6134
+ const fallbackProfile = `## Profile
6135
+ ${lines}`;
6136
+ saveProfile(profileKey, fallbackProfile, allMemories.length, options);
6137
+ return { profile: fallbackProfile, memory_count: allMemories.length, from_cache: false };
6138
+ }
6139
+ try {
6140
+ const memoryList = allMemories.sort((a, b) => b.importance - a.importance).map((m) => `[${m.category}] ${m.key}: ${m.value}`).join(`
6141
+ `);
6142
+ const response = await fetch("https://api.anthropic.com/v1/messages", {
6143
+ method: "POST",
6144
+ headers: {
6145
+ "x-api-key": apiKey,
6146
+ "anthropic-version": "2023-06-01",
6147
+ "content-type": "application/json"
6148
+ },
6149
+ body: JSON.stringify({
6150
+ model: "claude-haiku-4-5-20251001",
6151
+ max_tokens: 500,
6152
+ system: PROFILE_PROMPT,
6153
+ messages: [{ role: "user", content: `Synthesize a profile from these ${allMemories.length} memories:
6154
+
6155
+ ${memoryList}` }]
6156
+ })
6157
+ });
6158
+ if (!response.ok)
6159
+ return null;
6160
+ const data = await response.json();
6161
+ const profile = data.content?.[0]?.text?.trim();
6162
+ if (!profile)
6163
+ return null;
6164
+ saveProfile(profileKey, profile, allMemories.length, options);
6165
+ return { profile, memory_count: allMemories.length, from_cache: false };
6166
+ } catch {
6167
+ return null;
6168
+ }
6169
+ }
6170
+ function saveProfile(key, value, memoryCount, options) {
6171
+ try {
6172
+ createMemory({
6173
+ key,
6174
+ value,
6175
+ category: "fact",
6176
+ scope: "shared",
6177
+ importance: 10,
6178
+ source: "auto",
6179
+ tags: ["profile", "synthesized"],
6180
+ when_to_use: "When needing to understand this agent's or project's preferences, style, and conventions",
6181
+ metadata: { memory_count: memoryCount, synthesized_at: new Date().toISOString(), stale: false },
6182
+ agent_id: options.agent_id,
6183
+ project_id: options.project_id
6184
+ });
6185
+ } catch {}
6186
+ }
6187
+ function markProfileStale(projectId, _agentId) {
6188
+ try {
6189
+ const { getDatabase: getDatabase2 } = (init_database(), __toCommonJS(exports_database));
6190
+ const db = getDatabase2();
6191
+ db.run(`UPDATE memories SET metadata = json_set(COALESCE(metadata, '{}'), '$.stale', json('true'))
6192
+ WHERE key LIKE '_profile_%' AND COALESCE(project_id, '') = ?`, [projectId || ""]);
6193
+ } catch {}
6194
+ }
6195
+ var PROFILE_PROMPT = `You synthesize a coherent agent/project profile from individual preference and fact memories.
6196
+
6197
+ Output a concise profile (200-300 words max) organized by:
6198
+ - **Stack & Tools**: Languages, frameworks, package managers, etc.
6199
+ - **Code Style**: Formatting, patterns, naming conventions
6200
+ - **Workflow**: Testing, deployment, git practices
6201
+ - **Communication**: Response style, verbosity, formatting preferences
6202
+ - **Key Facts**: Architecture decisions, constraints, team conventions
6203
+
6204
+ Only include sections that have relevant data. Be specific and actionable.
6205
+ Output in markdown format.`;
6206
+ var init_profile_synthesizer = __esm(() => {
6207
+ init_memories();
6208
+ });
6209
+
6210
+ // src/lib/contradiction.ts
6211
+ var exports_contradiction = {};
6212
+ __export(exports_contradiction, {
6213
+ invalidateFact: () => invalidateFact,
6214
+ detectContradiction: () => detectContradiction
6215
+ });
6216
+ function invalidateFact(oldMemoryId, newMemoryId, db) {
6217
+ const d = db || getDatabase();
6218
+ const timestamp = now();
6219
+ d.run("UPDATE memories SET valid_until = ?, updated_at = ? WHERE id = ?", [timestamp, timestamp, oldMemoryId]);
6220
+ if (newMemoryId) {
6221
+ const row = d.query("SELECT metadata FROM memories WHERE id = ?").get(newMemoryId);
6222
+ if (row) {
6223
+ const metadata = JSON.parse(row.metadata || "{}");
6224
+ metadata.supersedes_id = oldMemoryId;
6225
+ d.run("UPDATE memories SET metadata = ?, updated_at = ? WHERE id = ?", [JSON.stringify(metadata), timestamp, newMemoryId]);
6226
+ }
6227
+ }
6228
+ return {
6229
+ invalidated_memory_id: oldMemoryId,
6230
+ new_memory_id: newMemoryId || null,
6231
+ valid_until: timestamp,
6232
+ supersedes_id: oldMemoryId
6233
+ };
6234
+ }
6235
+ function heuristicContradictionScore(newValue, existingValue, newKey, existingKey) {
6236
+ if (newKey !== existingKey)
6237
+ return 0;
6238
+ const newLower = newValue.toLowerCase().trim();
6239
+ const existingLower = existingValue.toLowerCase().trim();
6240
+ if (newLower === existingLower)
6241
+ return 0;
6242
+ const newWords = new Set(newLower.split(/\s+/));
6243
+ const existingWords = new Set(existingLower.split(/\s+/));
6244
+ let overlap = 0;
6245
+ for (const w of newWords) {
6246
+ if (existingWords.has(w))
6247
+ overlap++;
6248
+ }
6249
+ const totalUnique = new Set([...newWords, ...existingWords]).size;
6250
+ const overlapRatio = totalUnique > 0 ? overlap / totalUnique : 0;
6251
+ if (overlapRatio < 0.3)
6252
+ return 0.7;
6253
+ if (overlapRatio < 0.5)
6254
+ return 0.4;
6255
+ return 0.1;
6256
+ }
6257
+ async function llmContradictionCheck(_newValue, _existingValue, _key) {
6258
+ const provider = providerRegistry.getAvailable();
6259
+ if (!provider) {
6260
+ return { contradicts: false, confidence: 0, reasoning: "No LLM provider available" };
6261
+ }
6262
+ try {
6263
+ return { contradicts: false, confidence: 0, reasoning: "LLM check skipped \u2014 using heuristic only" };
6264
+ } catch {
6265
+ return { contradicts: false, confidence: 0, reasoning: "LLM check failed" };
6266
+ }
6267
+ }
6268
+ async function detectContradiction(newKey, newValue, options = {}, db) {
6269
+ const d = db || getDatabase();
6270
+ const { scope, project_id, min_importance = 7, use_llm = false } = options;
6271
+ const conditions = ["key = ?", "status = 'active'", "importance >= ?"];
6272
+ const params = [newKey, min_importance];
6273
+ if (scope) {
6274
+ conditions.push("scope = ?");
6275
+ params.push(scope);
6276
+ }
6277
+ if (project_id) {
6278
+ conditions.push("project_id = ?");
6279
+ params.push(project_id);
6280
+ }
6281
+ conditions.push("(valid_until IS NULL OR valid_until > datetime('now'))");
6282
+ const sql = `SELECT * FROM memories WHERE ${conditions.join(" AND ")} ORDER BY importance DESC LIMIT 10`;
6283
+ const rows = d.query(sql).all(...params);
6284
+ if (rows.length === 0) {
6285
+ return { contradicts: false, conflicting_memory: null, confidence: 0, reasoning: "No existing memories with this key" };
6286
+ }
6287
+ let bestContradiction = {
6288
+ contradicts: false,
6289
+ conflicting_memory: null,
6290
+ confidence: 0,
6291
+ reasoning: "No contradiction detected"
6292
+ };
6293
+ for (const row of rows) {
6294
+ const existing = parseMemoryRow(row);
6295
+ const heuristicScore = heuristicContradictionScore(newValue, existing.value, newKey, existing.key);
6296
+ if (heuristicScore > bestContradiction.confidence) {
6297
+ bestContradiction = {
6298
+ contradicts: heuristicScore >= 0.5,
6299
+ conflicting_memory: existing,
6300
+ confidence: heuristicScore,
6301
+ 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}"`
6302
+ };
6303
+ }
6304
+ }
6305
+ if (use_llm && bestContradiction.confidence >= 0.3 && bestContradiction.confidence < 0.7 && bestContradiction.conflicting_memory) {
6306
+ const llmResult = await llmContradictionCheck(newValue, bestContradiction.conflicting_memory.value, newKey);
6307
+ if (llmResult.confidence > bestContradiction.confidence) {
6308
+ bestContradiction = {
6309
+ ...bestContradiction,
6310
+ contradicts: llmResult.contradicts,
6311
+ confidence: llmResult.confidence,
6312
+ reasoning: llmResult.reasoning
6313
+ };
6314
+ }
6315
+ }
6316
+ return bestContradiction;
6317
+ }
6318
+ var init_contradiction = __esm(() => {
6319
+ init_database();
6320
+ init_memories();
6321
+ init_registry();
6322
+ });
6323
+
5968
6324
  // src/lib/built-in-hooks.ts
5969
6325
  var exports_built_in_hooks = {};
5970
6326
  __export(exports_built_in_hooks, {
@@ -6091,10 +6447,76 @@ var init_built_in_hooks = __esm(() => {
6091
6447
  description: "Generate and store vector embedding for semantic memory search",
6092
6448
  handler: async (ctx) => {
6093
6449
  const { indexMemoryEmbedding: indexMemoryEmbedding2 } = await Promise.resolve().then(() => (init_memories(), exports_memories));
6094
- const text = [ctx.memory.value, ctx.memory.summary].filter(Boolean).join(" ");
6450
+ const text = ctx.memory.when_to_use || [ctx.memory.value, ctx.memory.summary].filter(Boolean).join(" ");
6095
6451
  indexMemoryEmbedding2(ctx.memory.id, text);
6096
6452
  }
6097
6453
  });
6454
+ hookRegistry.register({
6455
+ type: "PostMemorySave",
6456
+ blocking: false,
6457
+ builtin: true,
6458
+ priority: 60,
6459
+ description: "Auto-generate when_to_use activation context via LLM if missing",
6460
+ handler: async (ctx) => {
6461
+ const { autoGenerateWhenToUse: autoGenerateWhenToUse2 } = await Promise.resolve().then(() => (init_when_to_use_generator(), exports_when_to_use_generator));
6462
+ await autoGenerateWhenToUse2(ctx);
6463
+ }
6464
+ });
6465
+ hookRegistry.register({
6466
+ type: "PostMemorySave",
6467
+ blocking: false,
6468
+ builtin: true,
6469
+ priority: 65,
6470
+ description: "Mark synthesized profile as stale when a preference or fact memory is saved",
6471
+ handler: async (ctx) => {
6472
+ const category = ctx.memory?.category;
6473
+ if (category !== "preference" && category !== "fact")
6474
+ return;
6475
+ try {
6476
+ const { markProfileStale: markProfileStale2 } = await Promise.resolve().then(() => (init_profile_synthesizer(), exports_profile_synthesizer));
6477
+ markProfileStale2(ctx.projectId, ctx.agentId);
6478
+ } catch {}
6479
+ }
6480
+ });
6481
+ hookRegistry.register({
6482
+ type: "PostMemorySave",
6483
+ blocking: false,
6484
+ builtin: true,
6485
+ priority: 70,
6486
+ description: "Auto-decay importance of existing memories contradicted by the newly saved memory",
6487
+ handler: async (ctx) => {
6488
+ if (ctx.wasUpdated)
6489
+ return;
6490
+ const memory = ctx.memory;
6491
+ if (memory.category !== "fact" && memory.category !== "knowledge")
6492
+ return;
6493
+ try {
6494
+ const { detectContradiction: detectContradiction2 } = await Promise.resolve().then(() => (init_contradiction(), exports_contradiction));
6495
+ const { updateMemory: updateMemory2, getMemory: getMemory2 } = await Promise.resolve().then(() => (init_memories(), exports_memories));
6496
+ const result = await detectContradiction2(memory.key, memory.value, {
6497
+ scope: memory.scope,
6498
+ project_id: ctx.projectId,
6499
+ min_importance: 1
6500
+ });
6501
+ if (!result.contradicts || !result.conflicting_memory)
6502
+ return;
6503
+ const conflicting = result.conflicting_memory;
6504
+ if (conflicting.id === memory.id)
6505
+ return;
6506
+ const fresh = getMemory2(conflicting.id);
6507
+ if (!fresh || fresh.status !== "active")
6508
+ return;
6509
+ const halvedImportance = Math.max(1, Math.floor(fresh.importance / 2));
6510
+ const metadata = { ...fresh.metadata || {}, contradicted_by: memory.id };
6511
+ updateMemory2(fresh.id, {
6512
+ importance: halvedImportance,
6513
+ flag: "contradicted",
6514
+ metadata,
6515
+ version: fresh.version
6516
+ });
6517
+ } catch {}
6518
+ }
6519
+ });
6098
6520
  hookRegistry.register({
6099
6521
  type: "PostMemoryInject",
6100
6522
  blocking: false,
@@ -7163,44 +7585,417 @@ var init_session_jobs = __esm(() => {
7163
7585
  init_database();
7164
7586
  });
7165
7587
 
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;
7588
+ // src/db/tool-events.ts
7589
+ var exports_tool_events = {};
7590
+ __export(exports_tool_events, {
7591
+ saveToolEvent: () => saveToolEvent,
7592
+ getToolStats: () => getToolStats,
7593
+ getToolLessons: () => getToolLessons,
7594
+ getToolEvents: () => getToolEvents,
7595
+ getToolEvent: () => getToolEvent,
7596
+ deleteToolEvents: () => deleteToolEvents
7597
+ });
7598
+ function parseToolEventRow(row) {
7599
+ return {
7600
+ id: row["id"],
7601
+ tool_name: row["tool_name"],
7602
+ action: row["action"] || null,
7603
+ success: !!row["success"],
7604
+ error_type: row["error_type"] || null,
7605
+ error_message: row["error_message"] || null,
7606
+ tokens_used: row["tokens_used"] ?? null,
7607
+ latency_ms: row["latency_ms"] ?? null,
7608
+ context: row["context"] || null,
7609
+ lesson: row["lesson"] || null,
7610
+ when_to_use: row["when_to_use"] || null,
7611
+ agent_id: row["agent_id"] || null,
7612
+ project_id: row["project_id"] || null,
7613
+ session_id: row["session_id"] || null,
7614
+ metadata: JSON.parse(row["metadata"] || "{}"),
7615
+ created_at: row["created_at"]
7616
+ };
7617
+ }
7618
+ function saveToolEvent(input, db) {
7619
+ const d = db || getDatabase();
7620
+ const id = uuid();
7621
+ const timestamp = now();
7622
+ const metadataJson = JSON.stringify(input.metadata || {});
7623
+ 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)
7624
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
7625
+ id,
7626
+ input.tool_name,
7627
+ input.action || null,
7628
+ input.success ? 1 : 0,
7629
+ input.error_type || null,
7630
+ input.error_message || null,
7631
+ input.tokens_used ?? null,
7632
+ input.latency_ms ?? null,
7633
+ input.context || null,
7634
+ input.lesson || null,
7635
+ input.when_to_use || null,
7636
+ input.agent_id || null,
7637
+ input.project_id || null,
7638
+ input.session_id || null,
7639
+ metadataJson,
7640
+ timestamp
7641
+ ]);
7642
+ return getToolEvent(id, d);
7643
+ }
7644
+ function getToolEvent(id, db) {
7645
+ const d = db || getDatabase();
7646
+ const row = d.query("SELECT * FROM tool_events WHERE id = ?").get(id);
7647
+ if (!row)
7648
+ return null;
7649
+ return parseToolEventRow(row);
7650
+ }
7651
+ function getToolEvents(filters, db) {
7652
+ const d = db || getDatabase();
7653
+ const conditions = [];
7654
+ const params = [];
7655
+ if (filters.tool_name) {
7656
+ conditions.push("tool_name = ?");
7657
+ params.push(filters.tool_name);
7180
7658
  }
7181
- return chunks;
7659
+ if (filters.agent_id) {
7660
+ conditions.push("agent_id = ?");
7661
+ params.push(filters.agent_id);
7662
+ }
7663
+ if (filters.project_id) {
7664
+ conditions.push("project_id = ?");
7665
+ params.push(filters.project_id);
7666
+ }
7667
+ if (filters.success !== undefined) {
7668
+ conditions.push("success = ?");
7669
+ params.push(filters.success ? 1 : 0);
7670
+ }
7671
+ if (filters.from_date) {
7672
+ conditions.push("created_at >= ?");
7673
+ params.push(filters.from_date);
7674
+ }
7675
+ if (filters.to_date) {
7676
+ conditions.push("created_at <= ?");
7677
+ params.push(filters.to_date);
7678
+ }
7679
+ const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
7680
+ const limit = filters.limit || 50;
7681
+ const offset = filters.offset || 0;
7682
+ const rows = d.query(`SELECT * FROM tool_events ${where} ORDER BY created_at DESC LIMIT ? OFFSET ?`).all(...params, limit, offset);
7683
+ return rows.map(parseToolEventRow);
7182
7684
  }
7183
- async function extractMemoriesFromChunk(chunk, context, db) {
7184
- const provider = providerRegistry.getAvailable();
7185
- if (!provider)
7685
+ function getToolStats(tool_name, project_id, db) {
7686
+ const d = db || getDatabase();
7687
+ let where = "WHERE tool_name = ?";
7688
+ const params = [tool_name];
7689
+ if (project_id) {
7690
+ where += " AND project_id = ?";
7691
+ params.push(project_id);
7692
+ }
7693
+ const stats = d.query(`SELECT
7694
+ COUNT(*) as total_calls,
7695
+ SUM(CASE WHEN success = 1 THEN 1 ELSE 0 END) as success_count,
7696
+ SUM(CASE WHEN success = 0 THEN 1 ELSE 0 END) as failure_count,
7697
+ AVG(CASE WHEN tokens_used IS NOT NULL THEN tokens_used END) as avg_tokens,
7698
+ AVG(CASE WHEN latency_ms IS NOT NULL THEN latency_ms END) as avg_latency_ms,
7699
+ MAX(created_at) as last_used
7700
+ FROM tool_events ${where}`).get(...params);
7701
+ const total = stats["total_calls"] || 0;
7702
+ const successCount = stats["success_count"] || 0;
7703
+ const errorRows = d.query(`SELECT error_type, COUNT(*) as count
7704
+ FROM tool_events ${where} AND error_type IS NOT NULL
7705
+ GROUP BY error_type ORDER BY count DESC LIMIT 5`).all(...params);
7706
+ return {
7707
+ tool_name,
7708
+ total_calls: total,
7709
+ success_count: successCount,
7710
+ failure_count: stats["failure_count"] || 0,
7711
+ success_rate: total > 0 ? successCount / total : 0,
7712
+ avg_tokens: stats["avg_tokens"] ?? null,
7713
+ avg_latency_ms: stats["avg_latency_ms"] ?? null,
7714
+ common_errors: errorRows,
7715
+ last_used: stats["last_used"] || ""
7716
+ };
7717
+ }
7718
+ function getToolLessons(tool_name, project_id, limit, db) {
7719
+ const d = db || getDatabase();
7720
+ let where = "WHERE tool_name = ? AND lesson IS NOT NULL";
7721
+ const params = [tool_name];
7722
+ if (project_id) {
7723
+ where += " AND project_id = ?";
7724
+ params.push(project_id);
7725
+ }
7726
+ 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);
7727
+ return rows;
7728
+ }
7729
+ function deleteToolEvents(filters, db) {
7730
+ const d = db || getDatabase();
7731
+ const conditions = [];
7732
+ const params = [];
7733
+ if (filters.tool_name) {
7734
+ conditions.push("tool_name = ?");
7735
+ params.push(filters.tool_name);
7736
+ }
7737
+ if (filters.agent_id) {
7738
+ conditions.push("agent_id = ?");
7739
+ params.push(filters.agent_id);
7740
+ }
7741
+ if (filters.project_id) {
7742
+ conditions.push("project_id = ?");
7743
+ params.push(filters.project_id);
7744
+ }
7745
+ if (filters.before_date) {
7746
+ conditions.push("created_at < ?");
7747
+ params.push(filters.before_date);
7748
+ }
7749
+ if (conditions.length === 0)
7186
7750
  return 0;
7751
+ const result = d.run(`DELETE FROM tool_events WHERE ${conditions.join(" AND ")}`, params);
7752
+ return result.changes;
7753
+ }
7754
+ var init_tool_events = __esm(() => {
7755
+ init_database();
7756
+ });
7757
+
7758
+ // src/lib/tool-lesson-extractor.ts
7759
+ async function extractToolLessons(transcript, options) {
7760
+ const apiKey = process.env["ANTHROPIC_API_KEY"];
7761
+ if (!apiKey)
7762
+ return [];
7187
7763
  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
7764
+ const truncated = transcript.length > 8000 ? transcript.slice(0, 8000) + `
7765
+ [...truncated]` : transcript;
7766
+ const response = await fetch("https://api.anthropic.com/v1/messages", {
7767
+ method: "POST",
7768
+ headers: {
7769
+ "x-api-key": apiKey,
7770
+ "anthropic-version": "2023-06-01",
7771
+ "content-type": "application/json"
7772
+ },
7773
+ body: JSON.stringify({
7774
+ model: "claude-haiku-4-5-20251001",
7775
+ max_tokens: 1500,
7776
+ system: SYSTEM_PROMPT3,
7777
+ messages: [{ role: "user", content: `Extract tool lessons from this session transcript:
7778
+
7779
+ ${truncated}` }]
7780
+ })
7192
7781
  });
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())
7782
+ if (!response.ok)
7783
+ return [];
7784
+ const data = await response.json();
7785
+ const text = data.content?.[0]?.text?.trim();
7786
+ if (!text)
7787
+ return [];
7788
+ const lessons = JSON.parse(text);
7789
+ if (!Array.isArray(lessons))
7790
+ return [];
7791
+ for (const lesson of lessons) {
7792
+ if (!lesson.tool_name || !lesson.lesson)
7197
7793
  continue;
7794
+ try {
7795
+ saveToolEvent({
7796
+ tool_name: lesson.tool_name,
7797
+ success: lesson.success,
7798
+ error_type: lesson.error_type || undefined,
7799
+ lesson: lesson.lesson,
7800
+ when_to_use: lesson.when_to_use,
7801
+ context: "extracted from session transcript",
7802
+ agent_id: options?.agent_id,
7803
+ project_id: options?.project_id,
7804
+ session_id: options?.session_id
7805
+ });
7806
+ } catch {}
7198
7807
  try {
7199
7808
  createMemory({
7200
- key: memory.content.slice(0, 120).replace(/\s+/g, "-").toLowerCase(),
7201
- value: memory.content,
7202
- category: memory.category,
7203
- scope: memory.suggestedScope ?? "shared",
7809
+ key: `tool-lesson-${lesson.tool_name}-${Date.now()}`,
7810
+ value: lesson.lesson,
7811
+ category: "knowledge",
7812
+ scope: "shared",
7813
+ importance: 7,
7814
+ source: "auto",
7815
+ tags: ["tool-memory", lesson.tool_name, "auto-extracted"],
7816
+ when_to_use: lesson.when_to_use,
7817
+ agent_id: options?.agent_id,
7818
+ project_id: options?.project_id,
7819
+ session_id: options?.session_id
7820
+ });
7821
+ } catch {}
7822
+ }
7823
+ return lessons;
7824
+ } catch {
7825
+ return [];
7826
+ }
7827
+ }
7828
+ 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.
7829
+
7830
+ For each tool lesson, output a JSON array of objects with these fields:
7831
+ - tool_name: name of the tool
7832
+ - lesson: the insight (1-2 sentences)
7833
+ - when_to_use: activation context \u2014 when should an agent recall this lesson (start with "When" or "If")
7834
+ - success: boolean \u2014 was the tool call that taught this lesson successful?
7835
+ - error_type: if failed, one of: timeout, permission, not_found, syntax, rate_limit, other (or null if success)
7836
+
7837
+ Focus on:
7838
+ 1. Successful patterns: what worked and why
7839
+ 2. Failure lessons: what went wrong and how to avoid it
7840
+ 3. Parameter insights: optimal settings discovered
7841
+ 4. Alternative tools: when one tool is better than another
7842
+ 5. Error recovery: what to do when a specific error occurs
7843
+
7844
+ Only extract genuinely useful, non-obvious lessons. Skip trivial observations.
7845
+ Output ONLY the JSON array, no markdown or explanation.`;
7846
+ var init_tool_lesson_extractor = __esm(() => {
7847
+ init_tool_events();
7848
+ init_memories();
7849
+ });
7850
+
7851
+ // src/lib/procedural-extractor.ts
7852
+ async function extractProcedures(transcript, options) {
7853
+ const apiKey = process.env["ANTHROPIC_API_KEY"];
7854
+ if (!apiKey)
7855
+ return [];
7856
+ try {
7857
+ const truncated = transcript.length > 8000 ? transcript.slice(0, 8000) + `
7858
+ [...truncated]` : transcript;
7859
+ const response = await fetch("https://api.anthropic.com/v1/messages", {
7860
+ method: "POST",
7861
+ headers: {
7862
+ "x-api-key": apiKey,
7863
+ "anthropic-version": "2023-06-01",
7864
+ "content-type": "application/json"
7865
+ },
7866
+ body: JSON.stringify({
7867
+ model: "claude-haiku-4-5-20251001",
7868
+ max_tokens: 2000,
7869
+ system: SYSTEM_PROMPT4,
7870
+ messages: [{ role: "user", content: `Extract procedures from this session:
7871
+
7872
+ ${truncated}` }]
7873
+ })
7874
+ });
7875
+ if (!response.ok)
7876
+ return [];
7877
+ const data = await response.json();
7878
+ const text = data.content?.[0]?.text?.trim();
7879
+ if (!text)
7880
+ return [];
7881
+ const procedures = JSON.parse(text);
7882
+ if (!Array.isArray(procedures))
7883
+ return [];
7884
+ for (const proc of procedures) {
7885
+ if (!proc.title || !proc.steps?.length)
7886
+ continue;
7887
+ const sequenceGroup = `proc-${shortUuid()}`;
7888
+ for (let i = 0;i < proc.steps.length; i++) {
7889
+ const step = proc.steps[i];
7890
+ if (!step)
7891
+ continue;
7892
+ try {
7893
+ createMemory({
7894
+ key: `${sequenceGroup}-step-${i + 1}`,
7895
+ value: step.action,
7896
+ category: "procedural",
7897
+ scope: "shared",
7898
+ importance: 7,
7899
+ source: "auto",
7900
+ tags: ["procedure", "auto-extracted", proc.title.toLowerCase().replace(/\s+/g, "-")],
7901
+ when_to_use: step.when_to_use || proc.when_to_use,
7902
+ sequence_group: sequenceGroup,
7903
+ sequence_order: i + 1,
7904
+ agent_id: options?.agent_id,
7905
+ project_id: options?.project_id,
7906
+ session_id: options?.session_id
7907
+ });
7908
+ } catch {}
7909
+ }
7910
+ for (const pattern of proc.failure_patterns || []) {
7911
+ try {
7912
+ createMemory({
7913
+ key: `${sequenceGroup}-warning-${shortUuid()}`,
7914
+ value: `WARNING: ${pattern}`,
7915
+ category: "procedural",
7916
+ scope: "shared",
7917
+ importance: 8,
7918
+ source: "auto",
7919
+ tags: ["procedure", "failure-pattern", "auto-extracted"],
7920
+ when_to_use: proc.when_to_use,
7921
+ sequence_group: sequenceGroup,
7922
+ sequence_order: 999,
7923
+ agent_id: options?.agent_id,
7924
+ project_id: options?.project_id,
7925
+ session_id: options?.session_id
7926
+ });
7927
+ } catch {}
7928
+ }
7929
+ }
7930
+ return procedures;
7931
+ } catch {
7932
+ return [];
7933
+ }
7934
+ }
7935
+ var SYSTEM_PROMPT4 = `You extract procedural knowledge from session transcripts \u2014 workflows, step sequences, and problem-solution patterns.
7936
+
7937
+ For each procedure found, output a JSON array of objects:
7938
+ {
7939
+ "title": "short name for the workflow",
7940
+ "steps": [
7941
+ {"action": "what to do", "when_to_use": "activation context for this step"},
7942
+ {"action": "next step", "when_to_use": "activation context"}
7943
+ ],
7944
+ "failure_patterns": ["what to avoid and why"],
7945
+ "when_to_use": "overall activation context for the whole procedure"
7946
+ }
7947
+
7948
+ Focus on:
7949
+ 1. Multi-step workflows that were completed successfully
7950
+ 2. Step sequences where order matters
7951
+ 3. Failure \u2192 recovery patterns (what went wrong, how it was fixed)
7952
+ 4. Problem-solution pairs (when X happens, do Y)
7953
+
7954
+ Only extract non-trivial procedures (3+ steps or genuinely useful patterns).
7955
+ Output ONLY the JSON array.`;
7956
+ var init_procedural_extractor = __esm(() => {
7957
+ init_memories();
7958
+ init_database();
7959
+ });
7960
+
7961
+ // src/lib/session-processor.ts
7962
+ function chunkTranscript(transcript, chunkSize = 2000, overlap = 200) {
7963
+ if (!transcript || transcript.length === 0)
7964
+ return [];
7965
+ if (transcript.length <= chunkSize)
7966
+ return [transcript];
7967
+ const chunks = [];
7968
+ let start = 0;
7969
+ while (start < transcript.length) {
7970
+ const end = Math.min(start + chunkSize, transcript.length);
7971
+ chunks.push(transcript.slice(start, end));
7972
+ if (end === transcript.length)
7973
+ break;
7974
+ start += chunkSize - overlap;
7975
+ }
7976
+ return chunks;
7977
+ }
7978
+ async function extractMemoriesFromChunk(chunk, context, db) {
7979
+ const provider = providerRegistry.getAvailable();
7980
+ if (!provider)
7981
+ return 0;
7982
+ try {
7983
+ const extracted = await provider.extractMemories(SESSION_EXTRACTION_USER_TEMPLATE(chunk, context.sessionId), {
7984
+ sessionId: context.sessionId,
7985
+ agentId: context.agentId,
7986
+ projectId: context.projectId
7987
+ });
7988
+ let savedCount = 0;
7989
+ const sourceTag = context.source ? `source:${context.source}` : "source:manual";
7990
+ for (const memory of extracted) {
7991
+ if (!memory.content || !memory.content.trim())
7992
+ continue;
7993
+ try {
7994
+ createMemory({
7995
+ key: memory.content.slice(0, 120).replace(/\s+/g, "-").toLowerCase(),
7996
+ value: memory.content,
7997
+ category: memory.category,
7998
+ scope: memory.suggestedScope ?? "shared",
7204
7999
  importance: memory.importance,
7205
8000
  tags: [
7206
8001
  ...memory.tags,
@@ -7320,6 +8115,20 @@ async function processSessionJob(jobId, db) {
7320
8115
  }
7321
8116
  }
7322
8117
  result.memoriesExtracted = totalMemories;
8118
+ try {
8119
+ await extractToolLessons(job.transcript, {
8120
+ agent_id: job.agent_id ?? undefined,
8121
+ project_id: job.project_id ?? undefined,
8122
+ session_id: job.session_id
8123
+ });
8124
+ } catch {}
8125
+ try {
8126
+ await extractProcedures(job.transcript, {
8127
+ agent_id: job.agent_id ?? undefined,
8128
+ project_id: job.project_id ?? undefined,
8129
+ session_id: job.session_id
8130
+ });
8131
+ } catch {}
7323
8132
  try {
7324
8133
  if (result.errors.length > 0 && result.chunksProcessed === 0) {
7325
8134
  updateSessionJob(jobId, {
@@ -7351,6 +8160,8 @@ var init_session_processor = __esm(() => {
7351
8160
  init_memories();
7352
8161
  init_registry();
7353
8162
  init_session_jobs();
8163
+ init_tool_lesson_extractor();
8164
+ init_procedural_extractor();
7354
8165
  });
7355
8166
 
7356
8167
  // src/lib/session-queue.ts
@@ -7440,6 +8251,204 @@ var init_session_queue = __esm(() => {
7440
8251
  _pendingQueue = new Set;
7441
8252
  });
7442
8253
 
8254
+ // src/lib/session-registry.ts
8255
+ var exports_session_registry = {};
8256
+ __export(exports_session_registry, {
8257
+ updateSessionAgent: () => updateSessionAgent,
8258
+ unregisterSession: () => unregisterSession,
8259
+ registerSession: () => registerSession,
8260
+ listSessions: () => listSessions,
8261
+ heartbeatSession: () => heartbeatSession,
8262
+ getSessionsByProject: () => getSessionsByProject,
8263
+ getSessionByAgent: () => getSessionByAgent,
8264
+ getSession: () => getSession,
8265
+ closeRegistry: () => closeRegistry,
8266
+ cleanStaleSessions: () => cleanStaleSessions
8267
+ });
8268
+ import { Database as Database2 } from "bun:sqlite";
8269
+ import { existsSync as existsSync5, mkdirSync as mkdirSync5 } from "fs";
8270
+ import { dirname as dirname3, join as join5 } from "path";
8271
+ function getDb() {
8272
+ if (_db2)
8273
+ return _db2;
8274
+ const dir = dirname3(DB_PATH);
8275
+ if (!existsSync5(dir))
8276
+ mkdirSync5(dir, { recursive: true });
8277
+ _db2 = new Database2(DB_PATH, { create: true });
8278
+ _db2.run("PRAGMA journal_mode = WAL");
8279
+ _db2.run("PRAGMA busy_timeout = 3000");
8280
+ _db2.exec(`
8281
+ CREATE TABLE IF NOT EXISTS sessions (
8282
+ id TEXT PRIMARY KEY,
8283
+ pid INTEGER NOT NULL,
8284
+ cwd TEXT NOT NULL,
8285
+ git_root TEXT,
8286
+ agent_name TEXT,
8287
+ project_name TEXT,
8288
+ tty TEXT,
8289
+ mcp_server TEXT NOT NULL,
8290
+ metadata TEXT DEFAULT '{}',
8291
+ registered_at TEXT NOT NULL DEFAULT (datetime('now')),
8292
+ last_seen_at TEXT NOT NULL DEFAULT (datetime('now'))
8293
+ );
8294
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_sessions_pid_mcp
8295
+ ON sessions(pid, mcp_server);
8296
+ CREATE INDEX IF NOT EXISTS idx_sessions_project
8297
+ ON sessions(project_name);
8298
+ CREATE INDEX IF NOT EXISTS idx_sessions_agent
8299
+ ON sessions(agent_name);
8300
+ CREATE INDEX IF NOT EXISTS idx_sessions_git_root
8301
+ ON sessions(git_root);
8302
+ `);
8303
+ return _db2;
8304
+ }
8305
+ function generateId() {
8306
+ return crypto.randomUUID().slice(0, 8);
8307
+ }
8308
+ function now2() {
8309
+ return new Date().toISOString();
8310
+ }
8311
+ function parseRow2(row) {
8312
+ return {
8313
+ id: row["id"],
8314
+ pid: row["pid"],
8315
+ cwd: row["cwd"],
8316
+ git_root: row["git_root"] || null,
8317
+ agent_name: row["agent_name"] || null,
8318
+ project_name: row["project_name"] || null,
8319
+ tty: row["tty"] || null,
8320
+ mcp_server: row["mcp_server"],
8321
+ metadata: JSON.parse(row["metadata"] || "{}"),
8322
+ registered_at: row["registered_at"],
8323
+ last_seen_at: row["last_seen_at"]
8324
+ };
8325
+ }
8326
+ function isProcessAlive(pid) {
8327
+ try {
8328
+ process.kill(pid, 0);
8329
+ return true;
8330
+ } catch {
8331
+ return false;
8332
+ }
8333
+ }
8334
+ function registerSession(opts) {
8335
+ const db = getDb();
8336
+ const pid = process.pid;
8337
+ const cwd = opts.cwd || process.cwd();
8338
+ const id = generateId();
8339
+ const timestamp = now2();
8340
+ const existing = db.query("SELECT id FROM sessions WHERE pid = ? AND mcp_server = ?").get(pid, opts.mcp_server);
8341
+ if (existing) {
8342
+ db.run(`UPDATE sessions SET agent_name = ?, project_name = ?, cwd = ?,
8343
+ git_root = ?, tty = ?, metadata = ?, last_seen_at = ? WHERE id = ?`, [
8344
+ opts.agent_name || null,
8345
+ opts.project_name || null,
8346
+ cwd,
8347
+ opts.git_root || null,
8348
+ opts.tty || null,
8349
+ JSON.stringify(opts.metadata || {}),
8350
+ timestamp,
8351
+ existing.id
8352
+ ]);
8353
+ return getSession(existing.id);
8354
+ }
8355
+ db.run(`INSERT INTO sessions (id, pid, cwd, git_root, agent_name, project_name, tty, mcp_server, metadata, registered_at, last_seen_at)
8356
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
8357
+ id,
8358
+ pid,
8359
+ cwd,
8360
+ opts.git_root || null,
8361
+ opts.agent_name || null,
8362
+ opts.project_name || null,
8363
+ opts.tty || null,
8364
+ opts.mcp_server,
8365
+ JSON.stringify(opts.metadata || {}),
8366
+ timestamp,
8367
+ timestamp
8368
+ ]);
8369
+ return getSession(id);
8370
+ }
8371
+ function heartbeatSession(id) {
8372
+ const db = getDb();
8373
+ db.run("UPDATE sessions SET last_seen_at = ? WHERE id = ?", [now2(), id]);
8374
+ }
8375
+ function unregisterSession(id) {
8376
+ const db = getDb();
8377
+ db.run("DELETE FROM sessions WHERE id = ?", [id]);
8378
+ }
8379
+ function getSession(id) {
8380
+ const db = getDb();
8381
+ const row = db.query("SELECT * FROM sessions WHERE id = ?").get(id);
8382
+ return row ? parseRow2(row) : null;
8383
+ }
8384
+ function listSessions(filter) {
8385
+ const db = getDb();
8386
+ const conditions = [];
8387
+ const params = [];
8388
+ if (filter?.project_name) {
8389
+ conditions.push("project_name = ?");
8390
+ params.push(filter.project_name);
8391
+ }
8392
+ if (filter?.git_root) {
8393
+ conditions.push("git_root = ?");
8394
+ params.push(filter.git_root);
8395
+ }
8396
+ if (filter?.mcp_server) {
8397
+ conditions.push("mcp_server = ?");
8398
+ params.push(filter.mcp_server);
8399
+ }
8400
+ if (filter?.agent_name) {
8401
+ conditions.push("agent_name = ?");
8402
+ params.push(filter.agent_name);
8403
+ }
8404
+ if (filter?.exclude_pid) {
8405
+ conditions.push("pid != ?");
8406
+ params.push(filter.exclude_pid);
8407
+ }
8408
+ const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
8409
+ const rows = db.query(`SELECT * FROM sessions ${where} ORDER BY last_seen_at DESC`).all(...params);
8410
+ return rows.map(parseRow2).filter((s) => {
8411
+ if (isProcessAlive(s.pid))
8412
+ return true;
8413
+ db.run("DELETE FROM sessions WHERE id = ?", [s.id]);
8414
+ return false;
8415
+ });
8416
+ }
8417
+ function getSessionByAgent(agentName) {
8418
+ const sessions = listSessions({ agent_name: agentName });
8419
+ return sessions[0] || null;
8420
+ }
8421
+ function getSessionsByProject(projectName) {
8422
+ return listSessions({ project_name: projectName });
8423
+ }
8424
+ function cleanStaleSessions() {
8425
+ const db = getDb();
8426
+ const rows = db.query("SELECT id, pid FROM sessions").all();
8427
+ let cleaned = 0;
8428
+ for (const row of rows) {
8429
+ if (!isProcessAlive(row.pid)) {
8430
+ db.run("DELETE FROM sessions WHERE id = ?", [row.id]);
8431
+ cleaned++;
8432
+ }
8433
+ }
8434
+ return cleaned;
8435
+ }
8436
+ function updateSessionAgent(mcpServer, agentName) {
8437
+ const db = getDb();
8438
+ const pid = process.pid;
8439
+ db.run("UPDATE sessions SET agent_name = ?, last_seen_at = ? WHERE pid = ? AND mcp_server = ?", [agentName, now2(), pid, mcpServer]);
8440
+ }
8441
+ function closeRegistry() {
8442
+ if (_db2) {
8443
+ _db2.close();
8444
+ _db2 = null;
8445
+ }
8446
+ }
8447
+ var DB_PATH, _db2 = null;
8448
+ var init_session_registry = __esm(() => {
8449
+ DB_PATH = join5(process.env["HOME"] || process.env["USERPROFILE"] || "~", ".open-sessions-registry.db");
8450
+ });
8451
+
7443
8452
  // node_modules/commander/esm.mjs
7444
8453
  var import__ = __toESM(require_commander(), 1);
7445
8454
  var {
@@ -7459,10 +8468,10 @@ var {
7459
8468
  // src/cli/index.tsx
7460
8469
  init_database();
7461
8470
  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";
8471
+ import chalk2 from "chalk";
8472
+ 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";
8473
+ import { dirname as dirname4, join as join6, resolve as resolve3 } from "path";
8474
+ import { homedir as homedir4 } from "os";
7466
8475
  import { fileURLToPath } from "url";
7467
8476
 
7468
8477
  // src/db/agents.ts
@@ -7945,37 +8954,332 @@ var FORMAT_UNITS = [
7945
8954
  init_entities();
7946
8955
  init_relations();
7947
8956
  init_entity_memories();
8957
+
8958
+ // src/cli/brains.ts
8959
+ import {
8960
+ existsSync as existsSync4,
8961
+ mkdirSync as mkdirSync4,
8962
+ writeFileSync as writeFileSync3,
8963
+ readdirSync as readdirSync2
8964
+ } from "fs";
8965
+ import { homedir as homedir3 } from "os";
8966
+ import { join as join4 } from "path";
8967
+ import chalk from "chalk";
8968
+
8969
+ // src/lib/gatherer.ts
8970
+ init_memories();
8971
+ var SYSTEM_PROMPT = "You are an AI assistant with persistent memory that recalls and saves information across sessions.";
8972
+ function memoryToRecallExample(memory) {
8973
+ return {
8974
+ messages: [
8975
+ { role: "system", content: SYSTEM_PROMPT },
8976
+ {
8977
+ role: "user",
8978
+ content: `What do you remember about "${memory.key}"?`
8979
+ },
8980
+ {
8981
+ role: "assistant",
8982
+ content: memory.summary ? `${memory.value}
8983
+
8984
+ Summary: ${memory.summary}` : memory.value
8985
+ }
8986
+ ]
8987
+ };
8988
+ }
8989
+ function memoryToSaveExample(memory) {
8990
+ const tags = memory.tags ?? [];
8991
+ return {
8992
+ messages: [
8993
+ { role: "system", content: SYSTEM_PROMPT },
8994
+ {
8995
+ role: "user",
8996
+ content: `Remember this for me: ${memory.key} = ${memory.value}${tags.length ? ` (tags: ${tags.join(", ")})` : ""}`
8997
+ },
8998
+ {
8999
+ role: "assistant",
9000
+ content: `Saved to memory: "${memory.key}" with ${memory.category} category, importance ${memory.importance}/10, scope: ${memory.scope}.`
9001
+ }
9002
+ ]
9003
+ };
9004
+ }
9005
+ function memoryToSearchExample(memories, category) {
9006
+ const matched = memories.filter((m) => m.category === category && m.status === "active").slice(0, 5);
9007
+ return {
9008
+ messages: [
9009
+ { role: "system", content: SYSTEM_PROMPT },
9010
+ { role: "user", content: `What ${category} memories do you have?` },
9011
+ {
9012
+ role: "assistant",
9013
+ content: matched.length > 0 ? `Here are my ${category} memories:
9014
+ ${matched.map((m) => `- ${m.key}: ${m.value.slice(0, 120)}${m.value.length > 120 ? "..." : ""}`).join(`
9015
+ `)}` : `I don't have any ${category} memories stored yet.`
9016
+ }
9017
+ ]
9018
+ };
9019
+ }
9020
+ var gatherTrainingData = async (options = {}) => {
9021
+ const allMemories = listMemories({ status: "active" });
9022
+ const filtered = options.since ? allMemories.filter((m) => new Date(m.created_at) >= options.since) : allMemories;
9023
+ const sorted = filtered.slice().sort((a, b) => b.importance - a.importance);
9024
+ const fetchSet = options.limit ? sorted.slice(0, options.limit * 3) : sorted;
9025
+ const examples = [];
9026
+ for (const memory of fetchSet) {
9027
+ examples.push(memoryToRecallExample(memory));
9028
+ examples.push(memoryToSaveExample(memory));
9029
+ }
9030
+ const categories = [...new Set(fetchSet.map((m) => m.category))];
9031
+ for (const category of categories) {
9032
+ examples.push(memoryToSearchExample(fetchSet, category));
9033
+ }
9034
+ const finalExamples = options.limit ? examples.slice(0, options.limit) : examples;
9035
+ return {
9036
+ source: "mementos",
9037
+ examples: finalExamples,
9038
+ count: finalExamples.length
9039
+ };
9040
+ };
9041
+
9042
+ // src/lib/model-config.ts
9043
+ import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
9044
+ import { homedir as homedir2 } from "os";
9045
+ import { join as join3 } from "path";
9046
+ var DEFAULT_MODEL = "gpt-4o-mini";
9047
+ var CONFIG_DIR = join3(homedir2(), ".mementos");
9048
+ var CONFIG_PATH = join3(CONFIG_DIR, "config.json");
9049
+ function readConfig() {
9050
+ if (!existsSync3(CONFIG_PATH))
9051
+ return {};
9052
+ try {
9053
+ const raw = readFileSync2(CONFIG_PATH, "utf-8");
9054
+ return JSON.parse(raw);
9055
+ } catch {
9056
+ return {};
9057
+ }
9058
+ }
9059
+ function writeConfig(config) {
9060
+ if (!existsSync3(CONFIG_DIR)) {
9061
+ mkdirSync3(CONFIG_DIR, { recursive: true });
9062
+ }
9063
+ writeFileSync2(CONFIG_PATH, JSON.stringify(config, null, 2) + `
9064
+ `, "utf-8");
9065
+ }
9066
+ function getActiveModel() {
9067
+ const config = readConfig();
9068
+ return config.activeModel ?? DEFAULT_MODEL;
9069
+ }
9070
+ function setActiveModel(modelId) {
9071
+ const config = readConfig();
9072
+ config.activeModel = modelId;
9073
+ writeConfig(config);
9074
+ }
9075
+ function clearActiveModel() {
9076
+ const config = readConfig();
9077
+ delete config.activeModel;
9078
+ writeConfig(config);
9079
+ }
9080
+
9081
+ // src/cli/brains.ts
9082
+ function printSuccess(msg) {
9083
+ console.log(chalk.green("\u2713 " + msg));
9084
+ }
9085
+ function printError(msg) {
9086
+ console.error(chalk.red("\u2717 " + msg));
9087
+ }
9088
+ function printInfo(msg) {
9089
+ console.log(chalk.cyan("\u2139 " + msg));
9090
+ }
9091
+ function makeBrainsCommand() {
9092
+ const brains = new Command("brains");
9093
+ brains.description("Fine-tuned model training and management (via @hasna/brains)");
9094
+ 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) => {
9095
+ try {
9096
+ const since = opts.since ? new Date(opts.since) : undefined;
9097
+ if (since && isNaN(since.getTime())) {
9098
+ printError(`Invalid date: ${opts.since}`);
9099
+ process.exit(1);
9100
+ }
9101
+ if (!opts.json) {
9102
+ printInfo("Gathering training data from memories...");
9103
+ }
9104
+ const result = await gatherTrainingData({
9105
+ limit: opts.limit,
9106
+ since
9107
+ });
9108
+ const outputDir = opts.output ?? join4(homedir3(), ".mementos", "training");
9109
+ if (!existsSync4(outputDir)) {
9110
+ mkdirSync4(outputDir, { recursive: true });
9111
+ }
9112
+ const timestamp = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
9113
+ const outputPath = join4(outputDir, `mementos-training-${timestamp}.jsonl`);
9114
+ const jsonl = result.examples.map((ex) => JSON.stringify(ex)).join(`
9115
+ `);
9116
+ writeFileSync3(outputPath, jsonl + `
9117
+ `, "utf-8");
9118
+ if (opts.json) {
9119
+ console.log(JSON.stringify({
9120
+ source: result.source,
9121
+ count: result.count,
9122
+ path: outputPath
9123
+ }));
9124
+ } else {
9125
+ printSuccess(`Gathered ${result.count} training examples from memories`);
9126
+ console.log(chalk.dim(` Output: ${outputPath}`));
9127
+ }
9128
+ } catch (err) {
9129
+ printError(err instanceof Error ? err.message : String(err));
9130
+ process.exit(1);
9131
+ }
9132
+ });
9133
+ 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) => {
9134
+ try {
9135
+ let datasetPath = opts.dataset;
9136
+ if (!datasetPath) {
9137
+ const trainingDir = join4(homedir3(), ".mementos", "training");
9138
+ if (!existsSync4(trainingDir)) {
9139
+ printError("No training data found. Run `mementos brains gather` first.");
9140
+ process.exit(1);
9141
+ }
9142
+ const files = readdirSync2(trainingDir).filter((f) => f.endsWith(".jsonl")).sort().reverse();
9143
+ const latestFile = files[0];
9144
+ if (!latestFile) {
9145
+ printError("No JSONL training files found. Run `mementos brains gather` first.");
9146
+ process.exit(1);
9147
+ }
9148
+ datasetPath = join4(trainingDir, latestFile);
9149
+ }
9150
+ if (!datasetPath || !existsSync4(datasetPath)) {
9151
+ printError(`Dataset file not found: ${datasetPath ?? "(unresolved)"}`);
9152
+ process.exit(1);
9153
+ }
9154
+ if (!opts.json) {
9155
+ printInfo(`Starting fine-tuning job with dataset: ${datasetPath}`);
9156
+ }
9157
+ let brainsSDK;
9158
+ try {
9159
+ brainsSDK = await import("@hasna/brains");
9160
+ } catch {
9161
+ printError("@hasna/brains is not installed. Run `bun add @hasna/brains` to enable training.");
9162
+ process.exit(1);
9163
+ }
9164
+ const startFinetune = brainsSDK["startFinetune"];
9165
+ if (typeof startFinetune !== "function") {
9166
+ printError("@hasna/brains does not export startFinetune. Please update @hasna/brains.");
9167
+ process.exit(1);
9168
+ }
9169
+ const modelName = opts.name ?? `mementos-${new Date().toISOString().slice(0, 10)}`;
9170
+ const jobResult = await startFinetune({
9171
+ provider: opts.provider,
9172
+ baseModel: opts.baseModel,
9173
+ datasetPath,
9174
+ name: modelName
9175
+ });
9176
+ if (opts.json) {
9177
+ console.log(JSON.stringify(jobResult));
9178
+ } else {
9179
+ printSuccess(`Fine-tuning job started: ${String(jobResult["jobId"] ?? "(unknown)")}`);
9180
+ console.log(chalk.dim(` Provider: ${opts.provider}`));
9181
+ console.log(chalk.dim(` Base model: ${opts.baseModel}`));
9182
+ console.log(chalk.dim(` Name: ${modelName}`));
9183
+ if (jobResult["jobId"]) {
9184
+ console.log();
9185
+ printInfo(`Use \`mementos brains model set <model-id>\` once training completes.`);
9186
+ }
9187
+ }
9188
+ } catch (err) {
9189
+ printError(err instanceof Error ? err.message : String(err));
9190
+ process.exit(1);
9191
+ }
9192
+ });
9193
+ const modelCmd = brains.command("model").description("Manage the active fine-tuned model");
9194
+ modelCmd.command("get").description("Show the currently active fine-tuned model").option("--json", "Output as JSON").action((opts) => {
9195
+ try {
9196
+ const active = getActiveModel();
9197
+ const isDefault = active === DEFAULT_MODEL;
9198
+ if (opts.json) {
9199
+ console.log(JSON.stringify({ activeModel: active, isDefault }));
9200
+ } else {
9201
+ if (isDefault) {
9202
+ console.log(`Active model: ${chalk.cyan(active)} ${chalk.dim("(default)")}`);
9203
+ } else {
9204
+ console.log(`Active model: ${chalk.green(active)}`);
9205
+ }
9206
+ }
9207
+ } catch (err) {
9208
+ printError(err instanceof Error ? err.message : String(err));
9209
+ process.exit(1);
9210
+ }
9211
+ });
9212
+ modelCmd.command("set <modelId>").description("Set the active fine-tuned model ID").action((modelId) => {
9213
+ try {
9214
+ setActiveModel(modelId);
9215
+ printSuccess(`Active model set to: ${modelId}`);
9216
+ } catch (err) {
9217
+ printError(err instanceof Error ? err.message : String(err));
9218
+ process.exit(1);
9219
+ }
9220
+ });
9221
+ modelCmd.command("clear").description(`Clear the active fine-tuned model (reverts to ${DEFAULT_MODEL})`).action(() => {
9222
+ try {
9223
+ clearActiveModel();
9224
+ printSuccess(`Active model cleared. Using default: ${DEFAULT_MODEL}`);
9225
+ } catch (err) {
9226
+ printError(err instanceof Error ? err.message : String(err));
9227
+ process.exit(1);
9228
+ }
9229
+ });
9230
+ modelCmd.action((opts) => {
9231
+ try {
9232
+ const active = getActiveModel();
9233
+ const isDefault = active === DEFAULT_MODEL;
9234
+ if (opts.json) {
9235
+ console.log(JSON.stringify({ activeModel: active, isDefault }));
9236
+ } else {
9237
+ if (isDefault) {
9238
+ console.log(`Active model: ${chalk.cyan(active)} ${chalk.dim("(default)")}`);
9239
+ } else {
9240
+ console.log(`Active model: ${chalk.green(active)}`);
9241
+ }
9242
+ }
9243
+ } catch (err) {
9244
+ printError(err instanceof Error ? err.message : String(err));
9245
+ process.exit(1);
9246
+ }
9247
+ });
9248
+ return brains;
9249
+ }
9250
+
9251
+ // src/cli/index.tsx
7948
9252
  function getPackageVersion() {
7949
9253
  try {
7950
- const pkgPath = join3(dirname3(fileURLToPath(import.meta.url)), "..", "..", "package.json");
7951
- const pkg = JSON.parse(readFileSync2(pkgPath, "utf-8"));
9254
+ const pkgPath = join6(dirname4(fileURLToPath(import.meta.url)), "..", "..", "package.json");
9255
+ const pkg = JSON.parse(readFileSync3(pkgPath, "utf-8"));
7952
9256
  return pkg.version || "0.0.0";
7953
9257
  } catch {
7954
9258
  return "0.0.0";
7955
9259
  }
7956
9260
  }
7957
9261
  var scopeColor = {
7958
- global: chalk.cyan,
7959
- shared: chalk.yellow,
7960
- private: chalk.magenta,
7961
- working: chalk.gray
9262
+ global: chalk2.cyan,
9263
+ shared: chalk2.yellow,
9264
+ private: chalk2.magenta,
9265
+ working: chalk2.gray
7962
9266
  };
7963
9267
  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
9268
+ preference: chalk2.blue,
9269
+ fact: chalk2.green,
9270
+ knowledge: chalk2.yellow,
9271
+ history: chalk2.gray,
9272
+ procedural: chalk2.cyan,
9273
+ resource: chalk2.magenta
7970
9274
  };
7971
9275
  function importanceColor(importance) {
7972
9276
  if (importance >= 9)
7973
- return chalk.red.bold;
9277
+ return chalk2.red.bold;
7974
9278
  if (importance >= 7)
7975
- return chalk.yellow;
9279
+ return chalk2.yellow;
7976
9280
  if (importance >= 5)
7977
- return chalk.green;
7978
- return chalk.dim;
9281
+ return chalk2.green;
9282
+ return chalk2.dim;
7979
9283
  }
7980
9284
  function colorScope(scope) {
7981
9285
  return scopeColor[scope](scope);
@@ -7987,17 +9291,17 @@ function colorImportance(importance) {
7987
9291
  return importanceColor(importance)(String(importance));
7988
9292
  }
7989
9293
  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
9294
+ person: chalk2.cyan,
9295
+ project: chalk2.yellow,
9296
+ tool: chalk2.green,
9297
+ concept: chalk2.blue,
9298
+ file: chalk2.magenta,
9299
+ api: chalk2.red,
9300
+ pattern: chalk2.gray,
9301
+ organization: chalk2.white
7998
9302
  };
7999
9303
  function colorEntityType(type) {
8000
- const colorFn = entityTypeColor[type] || chalk.white;
9304
+ const colorFn = entityTypeColor[type] || chalk2.white;
8001
9305
  return colorFn(type);
8002
9306
  }
8003
9307
  function resolveEntityArg(nameOrId, type) {
@@ -8008,7 +9312,7 @@ function resolveEntityArg(nameOrId, type) {
8008
9312
  const id = resolvePartialId(db, "entities", nameOrId);
8009
9313
  if (id)
8010
9314
  return getEntity(id);
8011
- console.error(chalk.red(`Entity not found: ${nameOrId}`));
9315
+ console.error(chalk2.red(`Entity not found: ${nameOrId}`));
8012
9316
  process.exit(1);
8013
9317
  }
8014
9318
  function outputJson(data) {
@@ -8092,44 +9396,44 @@ ${formatObj({ [k]: v }, " ").replace(/^\s*\S+:\n/, "")}`);
8092
9396
  }
8093
9397
  }
8094
9398
  function formatMemoryLine(m) {
8095
- const id = chalk.dim(m.id.slice(0, 8));
9399
+ const id = chalk2.dim(m.id.slice(0, 8));
8096
9400
  const scope = colorScope(m.scope);
8097
9401
  const cat = colorCategory(m.category);
8098
9402
  const imp = colorImportance(m.importance);
8099
- const pin = m.pinned ? chalk.red(" *") : "";
9403
+ const pin = m.pinned ? chalk2.red(" *") : "";
8100
9404
  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}`;
9405
+ return `${id} [${scope}/${cat}] ${chalk2.bold(m.key)} = ${value} (${imp})${pin}`;
8102
9406
  }
8103
9407
  function formatMemoryDetail(m) {
8104
9408
  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"}`
9409
+ `${chalk2.bold("ID:")} ${m.id}`,
9410
+ `${chalk2.bold("Key:")} ${m.key}`,
9411
+ `${chalk2.bold("Value:")} ${m.value}`,
9412
+ `${chalk2.bold("Scope:")} ${colorScope(m.scope)}`,
9413
+ `${chalk2.bold("Category:")} ${colorCategory(m.category)}`,
9414
+ `${chalk2.bold("Importance:")} ${colorImportance(m.importance)}/10`,
9415
+ `${chalk2.bold("Source:")} ${m.source}`,
9416
+ `${chalk2.bold("Status:")} ${m.status}`,
9417
+ `${chalk2.bold("Pinned:")} ${m.pinned ? chalk2.red("yes") : "no"}`
8114
9418
  ];
8115
9419
  if (m.summary)
8116
- lines.push(`${chalk.bold("Summary:")} ${m.summary}`);
9420
+ lines.push(`${chalk2.bold("Summary:")} ${m.summary}`);
8117
9421
  if (m.tags.length > 0)
8118
- lines.push(`${chalk.bold("Tags:")} ${m.tags.join(", ")}`);
9422
+ lines.push(`${chalk2.bold("Tags:")} ${m.tags.join(", ")}`);
8119
9423
  if (m.agent_id)
8120
- lines.push(`${chalk.bold("Agent:")} ${m.agent_id}`);
9424
+ lines.push(`${chalk2.bold("Agent:")} ${m.agent_id}`);
8121
9425
  if (m.project_id)
8122
- lines.push(`${chalk.bold("Project:")} ${m.project_id}`);
9426
+ lines.push(`${chalk2.bold("Project:")} ${m.project_id}`);
8123
9427
  if (m.session_id)
8124
- lines.push(`${chalk.bold("Session:")} ${m.session_id}`);
9428
+ lines.push(`${chalk2.bold("Session:")} ${m.session_id}`);
8125
9429
  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}`);
9430
+ lines.push(`${chalk2.bold("Expires:")} ${m.expires_at}`);
9431
+ lines.push(`${chalk2.bold("Access:")} ${m.access_count}`);
9432
+ lines.push(`${chalk2.bold("Version:")} ${m.version}`);
9433
+ lines.push(`${chalk2.bold("Created:")} ${m.created_at}`);
9434
+ lines.push(`${chalk2.bold("Updated:")} ${m.updated_at}`);
8131
9435
  if (m.accessed_at)
8132
- lines.push(`${chalk.bold("Accessed:")} ${m.accessed_at}`);
9436
+ lines.push(`${chalk2.bold("Accessed:")} ${m.accessed_at}`);
8133
9437
  return lines.join(`
8134
9438
  `);
8135
9439
  }
@@ -8141,7 +9445,7 @@ function handleError(e) {
8141
9445
  error: e instanceof Error ? e.message : String(e)
8142
9446
  });
8143
9447
  } else {
8144
- console.error(chalk.red(e instanceof Error ? e.message : String(e)));
9448
+ console.error(chalk2.red(e instanceof Error ? e.message : String(e)));
8145
9449
  }
8146
9450
  process.exit(1);
8147
9451
  }
@@ -8149,7 +9453,7 @@ function resolveMemoryId(partialId) {
8149
9453
  const db = getDatabase();
8150
9454
  const id = resolvePartialId(db, "memories", partialId);
8151
9455
  if (!id) {
8152
- console.error(chalk.red(`Could not resolve memory ID: ${partialId}`));
9456
+ console.error(chalk2.red(`Could not resolve memory ID: ${partialId}`));
8153
9457
  process.exit(1);
8154
9458
  }
8155
9459
  return id;
@@ -8175,10 +9479,10 @@ function resolveKeyOrId(keyOrId, opts, globalOpts) {
8175
9479
  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
9480
  program2.command("init").description("One-command setup: register MCP, install stop hook, configure auto-start").action(async () => {
8177
9481
  const { platform } = process;
8178
- const home = homedir2();
9482
+ const home = homedir4();
8179
9483
  const isMac = platform === "darwin";
8180
9484
  console.log("");
8181
- console.log(chalk.bold(" mementos \u2014 setting up your memory layer"));
9485
+ console.log(chalk2.bold(" mementos \u2014 setting up your memory layer"));
8182
9486
  console.log("");
8183
9487
  async function run(cmd) {
8184
9488
  try {
@@ -8223,24 +9527,24 @@ program2.command("init").description("One-command setup: register MCP, install s
8223
9527
  mcpError = e instanceof Error ? e.message : String(e);
8224
9528
  }
8225
9529
  if (mcpAlreadyInstalled) {
8226
- console.log(chalk.dim(" \xB7 MCP already registered"));
9530
+ console.log(chalk2.dim(" \xB7 MCP already registered"));
8227
9531
  } 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)"));
9532
+ console.log(chalk2.red(` \u2717 Failed to register MCP: ${mcpError}`));
9533
+ console.log(chalk2.dim(" (Is Claude Code installed? Try: claude mcp add --transport stdio --scope user mementos -- mementos-mcp)"));
8230
9534
  } else {
8231
- console.log(chalk.green(" \u2713 MCP server registered with Claude Code"));
9535
+ console.log(chalk2.green(" \u2713 MCP server registered with Claude Code"));
8232
9536
  }
8233
- const hooksDir = join3(home, ".claude", "hooks");
8234
- const hookDest = join3(hooksDir, "mementos-stop-hook.ts");
8235
- const settingsPath = join3(home, ".claude", "settings.json");
9537
+ const hooksDir = join6(home, ".claude", "hooks");
9538
+ const hookDest = join6(hooksDir, "mementos-stop-hook.ts");
9539
+ const settingsPath = join6(home, ".claude", "settings.json");
8236
9540
  const hookCommand = `bun ${hookDest}`;
8237
9541
  let hookAlreadyInstalled = false;
8238
9542
  let hookError = null;
8239
9543
  try {
8240
9544
  let settings = {};
8241
- if (existsSync3(settingsPath)) {
9545
+ if (existsSync6(settingsPath)) {
8242
9546
  try {
8243
- settings = JSON.parse(readFileSync2(settingsPath, "utf-8"));
9547
+ settings = JSON.parse(readFileSync3(settingsPath, "utf-8"));
8244
9548
  } catch {
8245
9549
  settings = {};
8246
9550
  }
@@ -8251,19 +9555,19 @@ program2.command("init").description("One-command setup: register MCP, install s
8251
9555
  if (alreadyHasMementos) {
8252
9556
  hookAlreadyInstalled = true;
8253
9557
  } else {
8254
- if (!existsSync3(hooksDir)) {
8255
- mkdirSync3(hooksDir, { recursive: true });
9558
+ if (!existsSync6(hooksDir)) {
9559
+ mkdirSync6(hooksDir, { recursive: true });
8256
9560
  }
8257
- if (!existsSync3(hookDest)) {
8258
- const packageDir = dirname3(dirname3(fileURLToPath(import.meta.url)));
9561
+ if (!existsSync6(hookDest)) {
9562
+ const packageDir = dirname4(dirname4(fileURLToPath(import.meta.url)));
8259
9563
  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")
9564
+ join6(packageDir, "scripts", "hooks", "claude-stop-hook.ts"),
9565
+ join6(packageDir, "..", "scripts", "hooks", "claude-stop-hook.ts"),
9566
+ join6(home, ".bun", "install", "global", "node_modules", "@hasna", "mementos", "scripts", "hooks", "claude-stop-hook.ts")
8263
9567
  ];
8264
9568
  let hookSourceFound = false;
8265
9569
  for (const src of candidatePaths) {
8266
- if (existsSync3(src)) {
9570
+ if (existsSync6(src)) {
8267
9571
  copyFileSync(src, hookDest);
8268
9572
  hookSourceFound = true;
8269
9573
  break;
@@ -8303,7 +9607,7 @@ async function main() {
8303
9607
 
8304
9608
  main().catch(() => {});
8305
9609
  `;
8306
- writeFileSync2(hookDest, inlineHook, "utf-8");
9610
+ writeFileSync4(hookDest, inlineHook, "utf-8");
8307
9611
  }
8308
9612
  }
8309
9613
  const newStopEntry = {
@@ -8312,24 +9616,24 @@ main().catch(() => {});
8312
9616
  };
8313
9617
  hooksObj["Stop"] = [...stopHooks, newStopEntry];
8314
9618
  settings["hooks"] = hooksObj;
8315
- writeFileSync2(settingsPath, JSON.stringify(settings, null, 2), "utf-8");
9619
+ writeFileSync4(settingsPath, JSON.stringify(settings, null, 2), "utf-8");
8316
9620
  }
8317
9621
  } catch (e) {
8318
9622
  hookError = e instanceof Error ? e.message : String(e);
8319
9623
  }
8320
9624
  if (hookAlreadyInstalled) {
8321
- console.log(chalk.dim(" \xB7 Stop hook already installed"));
9625
+ console.log(chalk2.dim(" \xB7 Stop hook already installed"));
8322
9626
  } else if (hookError) {
8323
- console.log(chalk.red(` \u2717 Failed to install stop hook: ${hookError}`));
9627
+ console.log(chalk2.red(` \u2717 Failed to install stop hook: ${hookError}`));
8324
9628
  } else {
8325
- console.log(chalk.green(" \u2713 Stop hook installed (sessions \u2192 memories)"));
9629
+ console.log(chalk2.green(" \u2713 Stop hook installed (sessions \u2192 memories)"));
8326
9630
  }
8327
9631
  let autoStartAlreadyInstalled = false;
8328
9632
  let autoStartError = null;
8329
9633
  if (!isMac) {
8330
- console.log(chalk.dim(` \xB7 Auto-start skipped (not macOS \u2014 platform: ${platform})`));
9634
+ console.log(chalk2.dim(` \xB7 Auto-start skipped (not macOS \u2014 platform: ${platform})`));
8331
9635
  } else {
8332
- const plistPath = join3(home, "Library", "LaunchAgents", "com.hasna.mementos.plist");
9636
+ const plistPath = join6(home, "Library", "LaunchAgents", "com.hasna.mementos.plist");
8333
9637
  const plistContent = `<?xml version="1.0" encoding="UTF-8"?>
8334
9638
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
8335
9639
  <plist version="1.0">
@@ -8354,30 +9658,30 @@ main().catch(() => {});
8354
9658
  </plist>
8355
9659
  `;
8356
9660
  try {
8357
- if (existsSync3(plistPath)) {
9661
+ if (existsSync6(plistPath)) {
8358
9662
  autoStartAlreadyInstalled = true;
8359
9663
  } else {
8360
- const launchAgentsDir = join3(home, "Library", "LaunchAgents");
8361
- if (!existsSync3(launchAgentsDir)) {
8362
- mkdirSync3(launchAgentsDir, { recursive: true });
9664
+ const launchAgentsDir = join6(home, "Library", "LaunchAgents");
9665
+ if (!existsSync6(launchAgentsDir)) {
9666
+ mkdirSync6(launchAgentsDir, { recursive: true });
8363
9667
  }
8364
- writeFileSync2(plistPath, plistContent, "utf-8");
9668
+ writeFileSync4(plistPath, plistContent, "utf-8");
8365
9669
  }
8366
9670
  } catch (e) {
8367
9671
  autoStartError = e instanceof Error ? e.message : String(e);
8368
9672
  }
8369
9673
  if (autoStartAlreadyInstalled) {
8370
- console.log(chalk.dim(" \xB7 Auto-start already configured"));
9674
+ console.log(chalk2.dim(" \xB7 Auto-start already configured"));
8371
9675
  } else if (autoStartError) {
8372
- console.log(chalk.red(` \u2717 Failed to configure auto-start: ${autoStartError}`));
9676
+ console.log(chalk2.red(` \u2717 Failed to configure auto-start: ${autoStartError}`));
8373
9677
  } else {
8374
- console.log(chalk.green(" \u2713 Auto-start configured (starts on login)"));
9678
+ console.log(chalk2.green(" \u2713 Auto-start configured (starts on login)"));
8375
9679
  }
8376
9680
  if (!autoStartAlreadyInstalled && !autoStartError) {
8377
- const plistPath2 = join3(home, "Library", "LaunchAgents", "com.hasna.mementos.plist");
9681
+ const plistPath2 = join6(home, "Library", "LaunchAgents", "com.hasna.mementos.plist");
8378
9682
  const loadResult = await run(["launchctl", "load", plistPath2]);
8379
9683
  if (!loadResult.ok) {
8380
- console.log(chalk.dim(` \xB7 launchctl load: ${loadResult.output || "already loaded"}`));
9684
+ console.log(chalk2.dim(` \xB7 launchctl load: ${loadResult.output || "already loaded"}`));
8381
9685
  }
8382
9686
  }
8383
9687
  }
@@ -8389,18 +9693,18 @@ main().catch(() => {});
8389
9693
  serverRunning = res.ok;
8390
9694
  } catch {}
8391
9695
  if (serverRunning) {
8392
- console.log(chalk.green(" \u2713 Server running on http://127.0.0.1:19428"));
9696
+ console.log(chalk2.green(" \u2713 Server running on http://127.0.0.1:19428"));
8393
9697
  } 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)"));
9698
+ console.log(chalk2.dim(" \xB7 Server not yet running \u2014 it will start automatically on next login"));
9699
+ console.log(chalk2.dim(" (Or start it now: mementos-serve)"));
8396
9700
  }
8397
9701
  console.log("");
8398
- console.log(chalk.bold(" You're all set. Restart Claude Code to activate."));
9702
+ console.log(chalk2.bold(" You're all set. Restart Claude Code to activate."));
8399
9703
  console.log("");
8400
9704
  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")}`);
9705
+ console.log(` ${chalk2.cyan('mementos save "my-preference" "I prefer bun over npm"')}`);
9706
+ console.log(` ${chalk2.cyan("mementos list")}`);
9707
+ console.log(` ${chalk2.cyan("mementos doctor")}`);
8404
9708
  console.log("");
8405
9709
  });
8406
9710
  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 +9740,7 @@ program2.command("save <key> <value>").description("Save a memory (create or ups
8436
9740
  if (opts.template) {
8437
9741
  const tpl = templates[opts.template];
8438
9742
  if (!tpl) {
8439
- console.error(chalk.red(`Unknown template: ${opts.template}. Valid templates: ${Object.keys(templates).join(", ")}`));
9743
+ console.error(chalk2.red(`Unknown template: ${opts.template}. Valid templates: ${Object.keys(templates).join(", ")}`));
8440
9744
  process.exit(1);
8441
9745
  }
8442
9746
  templateDefaults = tpl;
@@ -8465,7 +9769,7 @@ program2.command("save <key> <value>").description("Save a memory (create or ups
8465
9769
  if (globalOpts.json) {
8466
9770
  outputJson(memory);
8467
9771
  } else {
8468
- console.log(chalk.green(`Saved: ${memory.key} (${memory.id.slice(0, 8)})`));
9772
+ console.log(chalk2.green(`Saved: ${memory.key} (${memory.id.slice(0, 8)})`));
8469
9773
  }
8470
9774
  } catch (e) {
8471
9775
  handleError(e);
@@ -8504,7 +9808,7 @@ program2.command("recall <key>").description("Recall a memory by key").option("-
8504
9808
  if (globalOpts.json) {
8505
9809
  outputJson({ fuzzy_match: true, score: best.score, match_type: best.match_type, memory: best.memory });
8506
9810
  } else {
8507
- console.log(chalk.yellow(`No exact match, showing best result (score: ${best.score.toFixed(2)}, match: ${best.match_type}):`));
9811
+ console.log(chalk2.yellow(`No exact match, showing best result (score: ${best.score.toFixed(2)}, match: ${best.match_type}):`));
8508
9812
  console.log(formatMemoryDetail(best.memory));
8509
9813
  }
8510
9814
  return;
@@ -8512,7 +9816,7 @@ program2.command("recall <key>").description("Recall a memory by key").option("-
8512
9816
  if (globalOpts.json) {
8513
9817
  outputJson({ error: `No memory found for key: ${key}` });
8514
9818
  } else {
8515
- console.error(chalk.yellow(`No memory found for key: ${key}`));
9819
+ console.error(chalk2.yellow(`No memory found for key: ${key}`));
8516
9820
  }
8517
9821
  process.exit(1);
8518
9822
  } catch (e) {
@@ -8562,10 +9866,10 @@ program2.command("list").description("List memories with optional filters").opti
8562
9866
  return;
8563
9867
  }
8564
9868
  if (memories.length === 0) {
8565
- console.log(chalk.yellow("No memories found."));
9869
+ console.log(chalk2.yellow("No memories found."));
8566
9870
  return;
8567
9871
  }
8568
- console.log(chalk.bold(`${memories.length} memor${memories.length === 1 ? "y" : "ies"}:`));
9872
+ console.log(chalk2.bold(`${memories.length} memor${memories.length === 1 ? "y" : "ies"}:`));
8569
9873
  for (const m of memories) {
8570
9874
  console.log(formatMemoryLine(m));
8571
9875
  }
@@ -8582,7 +9886,7 @@ program2.command("update <id>").description("Update a memory by ID").option("--v
8582
9886
  if (globalOpts.json) {
8583
9887
  outputJson({ error: `Memory not found: ${id}` });
8584
9888
  } else {
8585
- console.error(chalk.red(`Memory not found: ${id}`));
9889
+ console.error(chalk2.red(`Memory not found: ${id}`));
8586
9890
  }
8587
9891
  process.exit(1);
8588
9892
  }
@@ -8611,7 +9915,7 @@ program2.command("update <id>").description("Update a memory by ID").option("--v
8611
9915
  if (globalOpts.json) {
8612
9916
  outputJson(updated);
8613
9917
  } else {
8614
- console.log(chalk.green(`Updated: ${updated.key} (${updated.id.slice(0, 8)})`));
9918
+ console.log(chalk2.green(`Updated: ${updated.key} (${updated.id.slice(0, 8)})`));
8615
9919
  }
8616
9920
  } catch (e) {
8617
9921
  handleError(e);
@@ -8627,7 +9931,7 @@ program2.command("forget <keyOrId>").description("Delete a memory by key or ID")
8627
9931
  if (globalOpts.json) {
8628
9932
  outputJson({ deleted: idMatch });
8629
9933
  } else {
8630
- console.log(chalk.green(`Memory ${idMatch} deleted.`));
9934
+ console.log(chalk2.green(`Memory ${idMatch} deleted.`));
8631
9935
  }
8632
9936
  return;
8633
9937
  }
@@ -8636,7 +9940,7 @@ program2.command("forget <keyOrId>").description("Delete a memory by key or ID")
8636
9940
  if (globalOpts.json) {
8637
9941
  outputJson({ error: `No memory found: ${keyOrId}` });
8638
9942
  } else {
8639
- console.error(chalk.red(`No memory found: ${keyOrId}`));
9943
+ console.error(chalk2.red(`No memory found: ${keyOrId}`));
8640
9944
  }
8641
9945
  process.exit(1);
8642
9946
  }
@@ -8645,7 +9949,7 @@ program2.command("forget <keyOrId>").description("Delete a memory by key or ID")
8645
9949
  if (globalOpts.json) {
8646
9950
  outputJson({ deleted: matches[0].id, key: keyOrId });
8647
9951
  } else {
8648
- console.log(chalk.green(`Memory "${keyOrId}" (${matches[0].id}) deleted.`));
9952
+ console.log(chalk2.green(`Memory "${keyOrId}" (${matches[0].id}) deleted.`));
8649
9953
  }
8650
9954
  return;
8651
9955
  }
@@ -8656,7 +9960,7 @@ program2.command("forget <keyOrId>").description("Delete a memory by key or ID")
8656
9960
  if (globalOpts.json) {
8657
9961
  outputJson({ deleted: ids, key: keyOrId, count: ids.length });
8658
9962
  } else {
8659
- console.log(chalk.green(`Deleted ${ids.length} memories with key "${keyOrId}".`));
9963
+ console.log(chalk2.green(`Deleted ${ids.length} memories with key "${keyOrId}".`));
8660
9964
  }
8661
9965
  return;
8662
9966
  }
@@ -8672,7 +9976,7 @@ program2.command("forget <keyOrId>").description("Delete a memory by key or ID")
8672
9976
  }))
8673
9977
  });
8674
9978
  } else {
8675
- console.error(chalk.yellow(`Ambiguous: ${matches.length} memories match key "${keyOrId}":
9979
+ console.error(chalk2.yellow(`Ambiguous: ${matches.length} memories match key "${keyOrId}":
8676
9980
  `));
8677
9981
  for (const m of matches) {
8678
9982
  const parts = [
@@ -8684,7 +9988,7 @@ program2.command("forget <keyOrId>").description("Delete a memory by key or ID")
8684
9988
  ].filter(Boolean).join(" ");
8685
9989
  console.error(parts);
8686
9990
  }
8687
- console.error(chalk.cyan(`
9991
+ console.error(chalk2.cyan(`
8688
9992
  Use the full ID, or narrow with --scope, --agent, --project, or --all.`));
8689
9993
  }
8690
9994
  process.exit(1);
@@ -8702,12 +10006,12 @@ program2.command("search <query>").description("Full-text search across memories
8702
10006
  return;
8703
10007
  }
8704
10008
  if (history.length === 0) {
8705
- console.log(chalk.yellow("No search history."));
10009
+ console.log(chalk2.yellow("No search history."));
8706
10010
  return;
8707
10011
  }
8708
- console.log(chalk.bold("Recent searches:"));
10012
+ console.log(chalk2.bold("Recent searches:"));
8709
10013
  for (const h of history) {
8710
- console.log(` ${chalk.cyan(h.query)} ${chalk.dim(`(${h.result_count} results, ${h.created_at})`)}`);
10014
+ console.log(` ${chalk2.cyan(h.query)} ${chalk2.dim(`(${h.result_count} results, ${h.created_at})`)}`);
8711
10015
  }
8712
10016
  return;
8713
10017
  }
@@ -8719,12 +10023,12 @@ program2.command("search <query>").description("Full-text search across memories
8719
10023
  return;
8720
10024
  }
8721
10025
  if (popular.length === 0) {
8722
- console.log(chalk.yellow("No search history."));
10026
+ console.log(chalk2.yellow("No search history."));
8723
10027
  return;
8724
10028
  }
8725
- console.log(chalk.bold("Popular searches:"));
10029
+ console.log(chalk2.bold("Popular searches:"));
8726
10030
  for (const p of popular) {
8727
- console.log(` ${chalk.cyan(p.query)} ${chalk.dim(`(${p.count} times)`)}`);
10031
+ console.log(` ${chalk2.cyan(p.query)} ${chalk2.dim(`(${p.count} times)`)}`);
8728
10032
  }
8729
10033
  return;
8730
10034
  }
@@ -8771,16 +10075,16 @@ program2.command("search <query>").description("Full-text search across memories
8771
10075
  return;
8772
10076
  }
8773
10077
  if (results.length === 0) {
8774
- console.log(chalk.yellow(`No memories found matching "${query}".`));
10078
+ console.log(chalk2.yellow(`No memories found matching "${query}".`));
8775
10079
  return;
8776
10080
  }
8777
- console.log(chalk.bold(`${results.length} result${results.length === 1 ? "" : "s"} for "${query}":`));
10081
+ console.log(chalk2.bold(`${results.length} result${results.length === 1 ? "" : "s"} for "${query}":`));
8778
10082
  for (const r of results) {
8779
- const score = chalk.dim(`(score: ${r.score.toFixed(1)})`);
10083
+ const score = chalk2.dim(`(score: ${r.score.toFixed(1)})`);
8780
10084
  console.log(`${formatMemoryLine(r.memory)} ${score}`);
8781
10085
  if (r.highlights && r.highlights.length > 0) {
8782
10086
  for (const h of r.highlights) {
8783
- console.log(chalk.dim(` ${h.field}: ${h.snippet}`));
10087
+ console.log(chalk2.dim(` ${h.field}: ${h.snippet}`));
8784
10088
  }
8785
10089
  }
8786
10090
  }
@@ -8849,16 +10153,16 @@ program2.command("stats").description("Show memory statistics").option("--format
8849
10153
  console.log(`by_agent,${k},${v}`);
8850
10154
  return;
8851
10155
  }
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}`);
10156
+ console.log(chalk2.bold("Memory Statistics"));
10157
+ console.log(`${chalk2.bold("Total active:")} ${chalk2.white(String(total))}`);
10158
+ 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}`);
10159
+ 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}`);
10160
+ console.log(`${chalk2.bold("By status:")} active=${stats.by_status.active} archived=${stats.by_status.archived} expired=${stats.by_status.expired}`);
10161
+ console.log(`${chalk2.bold("Pinned:")} ${stats.pinned_count}`);
10162
+ console.log(`${chalk2.bold("Expired:")} ${stats.expired_count}`);
8859
10163
  if (Object.keys(stats.by_agent).length > 0) {
8860
10164
  const agentParts = Object.entries(stats.by_agent).map(([k, v]) => `${k}=${v}`).join(" ");
8861
- console.log(`${chalk.bold("By agent:")} ${agentParts}`);
10165
+ console.log(`${chalk2.bold("By agent:")} ${agentParts}`);
8862
10166
  }
8863
10167
  } catch (e) {
8864
10168
  handleError(e);
@@ -8923,30 +10227,30 @@ program2.command("report").description("Rich summary of memory activity and top
8923
10227
  const maxC = Math.max(...activityRows.map((x) => x.cnt), 1);
8924
10228
  return bars[Math.round(r.cnt / maxC * 7)] || "\u2581";
8925
10229
  }).join("");
8926
- console.log(chalk.bold(`
10230
+ console.log(chalk2.bold(`
8927
10231
  mementos report \u2014 last ${days} days
8928
10232
  `));
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}`);
10233
+ console.log(` ${chalk2.cyan("Total:")} ${total} memories (${chalk2.yellow(String(pinned))} pinned)`);
10234
+ console.log(` ${chalk2.cyan("Recent:")} ${recentTotal} new \xB7 ${chalk2.dim(`~${avgPerDay}/day`)}`);
10235
+ console.log(` ${chalk2.cyan("Activity:")} ${sparkline || chalk2.dim("no activity")}`);
10236
+ console.log(` ${chalk2.cyan("Scopes:")} global=${byScope["global"] || 0} shared=${byScope["shared"] || 0} private=${byScope["private"] || 0}`);
10237
+ console.log(` ${chalk2.cyan("Categories:")} knowledge=${byCat["knowledge"] || 0} fact=${byCat["fact"] || 0} preference=${byCat["preference"] || 0} history=${byCat["history"] || 0}`);
8934
10238
  if (topMems.length > 0) {
8935
10239
  console.log(`
8936
- ${chalk.bold("Top memories by importance:")}`);
10240
+ ${chalk2.bold("Top memories by importance:")}`);
8937
10241
  topMems.forEach((m) => {
8938
- console.log(` ${chalk.green(`[${m.importance}]`)} ${chalk.bold(m.key)} ${chalk.dim(`(${m.scope}/${m.category})`)}`);
10242
+ console.log(` ${chalk2.green(`[${m.importance}]`)} ${chalk2.bold(m.key)} ${chalk2.dim(`(${m.scope}/${m.category})`)}`);
8939
10243
  console.log(` ${m.value.slice(0, 90)}${m.value.length > 90 ? "..." : ""}`);
8940
10244
  });
8941
10245
  }
8942
10246
  if (topAgents.length > 0) {
8943
10247
  console.log(`
8944
- ${chalk.bold("Top agents:")}`);
10248
+ ${chalk2.bold("Top agents:")}`);
8945
10249
  topAgents.forEach((a) => console.log(` ${a.agent_id}: ${a.c} memories`));
8946
10250
  }
8947
10251
  console.log("");
8948
10252
  } catch (e) {
8949
- console.error(chalk.red(`report failed: ${e instanceof Error ? e.message : String(e)}`));
10253
+ console.error(chalk2.red(`report failed: ${e instanceof Error ? e.message : String(e)}`));
8950
10254
  process.exit(1);
8951
10255
  }
8952
10256
  });
@@ -8991,21 +10295,21 @@ program2.command("stale").description("Find memories not accessed recently (for
8991
10295
  return;
8992
10296
  }
8993
10297
  if (rows.length === 0) {
8994
- console.log(chalk.green(`No stale memories (not accessed in ${days}+ days).`));
10298
+ console.log(chalk2.green(`No stale memories (not accessed in ${days}+ days).`));
8995
10299
  return;
8996
10300
  }
8997
- console.log(chalk.bold(`
10301
+ console.log(chalk2.bold(`
8998
10302
  Stale memories (not accessed in ${days}+ days):
8999
10303
  `));
9000
10304
  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})`)}`);
10305
+ const lastAccess = m.accessed_at ? m.accessed_at.slice(0, 10) : chalk2.dim("never");
10306
+ console.log(` ${chalk2.dim(`[${m.importance}]`)} ${chalk2.bold(m.key)} ${chalk2.dim(`(${m.scope}/${m.category})`)}`);
9003
10307
  console.log(` Last accessed: ${lastAccess} \xB7 ${m.access_count} reads \xB7 ${m.value.slice(0, 80)}${m.value.length > 80 ? "..." : ""}`);
9004
10308
  }
9005
10309
  console.log(`
9006
- ${chalk.dim(`${rows.length} result(s). Run 'mementos archive <key>' or 'mementos forget <key>' to clean up.`)}`);
10310
+ ${chalk2.dim(`${rows.length} result(s). Run 'mementos archive <key>' or 'mementos forget <key>' to clean up.`)}`);
9007
10311
  } catch (e) {
9008
- console.error(chalk.red(`stale failed: ${e instanceof Error ? e.message : String(e)}`));
10312
+ console.error(chalk2.red(`stale failed: ${e instanceof Error ? e.message : String(e)}`));
9009
10313
  process.exit(1);
9010
10314
  }
9011
10315
  });
@@ -9040,9 +10344,9 @@ program2.command("import [file]").description("Import memories from a JSON file
9040
10344
  if (file === "-" || !file && !process.stdin.isTTY) {
9041
10345
  raw = await Bun.stdin.text();
9042
10346
  } else if (file) {
9043
- raw = readFileSync2(resolve3(file), "utf-8");
10347
+ raw = readFileSync3(resolve3(file), "utf-8");
9044
10348
  } else {
9045
- console.error(chalk.red("No input: provide a file path, use '-' for stdin, or pipe data."));
10349
+ console.error(chalk2.red("No input: provide a file path, use '-' for stdin, or pipe data."));
9046
10350
  process.exit(1);
9047
10351
  }
9048
10352
  const memories = JSON.parse(raw);
@@ -9058,7 +10362,7 @@ program2.command("import [file]").description("Import memories from a JSON file
9058
10362
  if (globalOpts.json) {
9059
10363
  outputJson({ imported });
9060
10364
  } else {
9061
- console.log(chalk.green(`Imported ${imported} memor${imported === 1 ? "y" : "ies"}.`));
10365
+ console.log(chalk2.green(`Imported ${imported} memor${imported === 1 ? "y" : "ies"}.`));
9062
10366
  }
9063
10367
  } catch (e) {
9064
10368
  handleError(e);
@@ -9072,12 +10376,12 @@ program2.command("clean").description("Remove expired memories and enforce quota
9072
10376
  if (globalOpts.json) {
9073
10377
  outputJson(result);
9074
10378
  } 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))}`);
10379
+ console.log(chalk2.bold("Cleanup complete:"));
10380
+ console.log(` Expired removed: ${chalk2.red(String(result.expired))}`);
10381
+ console.log(` Evicted (quota): ${chalk2.yellow(String(result.evicted))}`);
10382
+ console.log(` Archived (stale): ${chalk2.gray(String(result.archived))}`);
10383
+ console.log(` Archived (unused): ${chalk2.gray(String(result.unused_archived))}`);
10384
+ console.log(` Deprioritized: ${chalk2.blue(String(result.deprioritized))}`);
9081
10385
  }
9082
10386
  } catch (e) {
9083
10387
  handleError(e);
@@ -9090,11 +10394,11 @@ program2.command("register-agent <name>").alias("init-agent").description("Regis
9090
10394
  if (globalOpts.json) {
9091
10395
  outputJson(agent);
9092
10396
  } 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}`);
10397
+ console.log(chalk2.green("Agent registered:"));
10398
+ console.log(` ${chalk2.bold("ID:")} ${agent.id}`);
10399
+ console.log(` ${chalk2.bold("Name:")} ${agent.name}`);
10400
+ console.log(` ${chalk2.bold("Role:")} ${agent.role || "agent"}`);
10401
+ console.log(` ${chalk2.bold("Created:")} ${agent.created_at}`);
9098
10402
  }
9099
10403
  } catch (e) {
9100
10404
  handleError(e);
@@ -9109,12 +10413,12 @@ program2.command("agents").description("List all registered agents").action(() =
9109
10413
  return;
9110
10414
  }
9111
10415
  if (agents.length === 0) {
9112
- console.log(chalk.yellow("No agents registered."));
10416
+ console.log(chalk2.yellow("No agents registered."));
9113
10417
  return;
9114
10418
  }
9115
- console.log(chalk.bold(`${agents.length} agent${agents.length === 1 ? "" : "s"}:`));
10419
+ console.log(chalk2.bold(`${agents.length} agent${agents.length === 1 ? "" : "s"}:`));
9116
10420
  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}`)}`);
10421
+ console.log(` ${chalk2.dim(a.id)} ${chalk2.bold(a.name)} ${chalk2.gray(a.role || "agent")} ${chalk2.dim(`last seen: ${a.last_seen_at}`)}`);
9118
10422
  }
9119
10423
  } catch (e) {
9120
10424
  handleError(e);
@@ -9134,7 +10438,7 @@ program2.command("agent-update <id>").description("Update an agent's name, descr
9134
10438
  if (globalOpts.json) {
9135
10439
  outputJson({ error: "No updates provided. Use --name, --description, or --role." });
9136
10440
  } else {
9137
- console.error(chalk.red("No updates provided. Use --name, --description, or --role."));
10441
+ console.error(chalk2.red("No updates provided. Use --name, --description, or --role."));
9138
10442
  }
9139
10443
  process.exit(1);
9140
10444
  }
@@ -9143,19 +10447,19 @@ program2.command("agent-update <id>").description("Update an agent's name, descr
9143
10447
  if (globalOpts.json) {
9144
10448
  outputJson({ error: `Agent not found: ${id}` });
9145
10449
  } else {
9146
- console.error(chalk.red(`Agent not found: ${id}`));
10450
+ console.error(chalk2.red(`Agent not found: ${id}`));
9147
10451
  }
9148
10452
  process.exit(1);
9149
10453
  }
9150
10454
  if (globalOpts.json) {
9151
10455
  outputJson(agent);
9152
10456
  } 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}`);
10457
+ console.log(chalk2.green("Agent updated:"));
10458
+ console.log(` ${chalk2.bold("ID:")} ${agent.id}`);
10459
+ console.log(` ${chalk2.bold("Name:")} ${agent.name}`);
10460
+ console.log(` ${chalk2.bold("Description:")} ${agent.description || "-"}`);
10461
+ console.log(` ${chalk2.bold("Role:")} ${agent.role || "agent"}`);
10462
+ console.log(` ${chalk2.bold("Last seen:")} ${agent.last_seen_at}`);
9159
10463
  }
9160
10464
  } catch (e) {
9161
10465
  handleError(e);
@@ -9168,17 +10472,17 @@ program2.command("projects").description("Manage projects").option("--add", "Add
9168
10472
  const name = opts.name;
9169
10473
  const path = opts.path;
9170
10474
  if (!name || !path) {
9171
- console.error(chalk.red("--name and --path are required when adding a project"));
10475
+ console.error(chalk2.red("--name and --path are required when adding a project"));
9172
10476
  process.exit(1);
9173
10477
  }
9174
10478
  const project = registerProject(name, resolve3(path), opts.description);
9175
10479
  if (globalOpts.json) {
9176
10480
  outputJson(project);
9177
10481
  } 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}`);
10482
+ console.log(chalk2.green("Project registered:"));
10483
+ console.log(` ${chalk2.bold("ID:")} ${project.id}`);
10484
+ console.log(` ${chalk2.bold("Name:")} ${project.name}`);
10485
+ console.log(` ${chalk2.bold("Path:")} ${project.path}`);
9182
10486
  }
9183
10487
  return;
9184
10488
  }
@@ -9188,12 +10492,12 @@ program2.command("projects").description("Manage projects").option("--add", "Add
9188
10492
  return;
9189
10493
  }
9190
10494
  if (projects.length === 0) {
9191
- console.log(chalk.yellow("No projects registered."));
10495
+ console.log(chalk2.yellow("No projects registered."));
9192
10496
  return;
9193
10497
  }
9194
- console.log(chalk.bold(`${projects.length} project${projects.length === 1 ? "" : "s"}:`));
10498
+ console.log(chalk2.bold(`${projects.length} project${projects.length === 1 ? "" : "s"}:`));
9195
10499
  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}`) : ""}`);
10500
+ 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
10501
  }
9198
10502
  } catch (e) {
9199
10503
  handleError(e);
@@ -9283,7 +10587,7 @@ program2.command("inject").description("Output injection context for agent syste
9283
10587
  if (globalOpts.json) {
9284
10588
  outputJson({ context: "", count: 0 });
9285
10589
  } else {
9286
- console.log(chalk.yellow("No relevant memories found for injection."));
10590
+ console.log(chalk2.yellow("No relevant memories found for injection."));
9287
10591
  }
9288
10592
  return;
9289
10593
  }
@@ -9323,7 +10627,7 @@ program2.command("bulk <action> <ids...>").description("Batch operations: forget
9323
10627
  "unpin"
9324
10628
  ];
9325
10629
  if (!validActions.includes(action)) {
9326
- console.error(chalk.red(`Invalid action: ${action}. Valid: ${validActions.join(", ")}`));
10630
+ console.error(chalk2.red(`Invalid action: ${action}. Valid: ${validActions.join(", ")}`));
9327
10631
  process.exit(1);
9328
10632
  }
9329
10633
  const resolvedIds = ids.map((id) => resolveMemoryId(id));
@@ -9376,7 +10680,7 @@ program2.command("bulk <action> <ids...>").description("Batch operations: forget
9376
10680
  if (globalOpts.json) {
9377
10681
  outputJson({ action, affected, ids: resolvedIds });
9378
10682
  } else {
9379
- console.log(chalk.green(`${action}: ${affected} memor${affected === 1 ? "y" : "ies"} affected.`));
10683
+ console.log(chalk2.green(`${action}: ${affected} memor${affected === 1 ? "y" : "ies"} affected.`));
9380
10684
  }
9381
10685
  } catch (e) {
9382
10686
  handleError(e);
@@ -9389,7 +10693,7 @@ program2.command("doctor").description("Diagnose common issues with the mementos
9389
10693
  checks.push({ name: "Version", status: "ok", detail: version });
9390
10694
  const dbPath = getDbPath();
9391
10695
  let db = null;
9392
- if (dbPath !== ":memory:" && existsSync3(dbPath)) {
10696
+ if (dbPath !== ":memory:" && existsSync6(dbPath)) {
9393
10697
  try {
9394
10698
  accessSync(dbPath, fsConstants.R_OK | fsConstants.W_OK);
9395
10699
  checks.push({ name: "Database file", status: "ok", detail: dbPath });
@@ -9408,7 +10712,7 @@ program2.command("doctor").description("Diagnose common issues with the mementos
9408
10712
  checks.push({ name: "Database connection", status: "fail", detail: e instanceof Error ? e.message : String(e) });
9409
10713
  }
9410
10714
  try {
9411
- if (dbPath !== ":memory:" && existsSync3(dbPath)) {
10715
+ if (dbPath !== ":memory:" && existsSync6(dbPath)) {
9412
10716
  const stats = statSync(dbPath);
9413
10717
  const sizeKb = (stats.size / 1024).toFixed(1);
9414
10718
  const sizeMb = (stats.size / (1024 * 1024)).toFixed(2);
@@ -9446,14 +10750,14 @@ program2.command("doctor").description("Diagnose common issues with the mementos
9446
10750
  const byScope = {};
9447
10751
  let expiredCount = 0;
9448
10752
  let staleCount = 0;
9449
- const now2 = Date.now();
10753
+ const now3 = Date.now();
9450
10754
  const staleThreshold = 14 * 24 * 60 * 60 * 1000;
9451
10755
  for (const m of all) {
9452
10756
  byScope[m.scope] = (byScope[m.scope] || 0) + 1;
9453
10757
  if (m.status === "expired")
9454
10758
  expiredCount++;
9455
10759
  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") {
10760
+ if (now3 - lastAccess > staleThreshold && m.status === "active") {
9457
10761
  staleCount++;
9458
10762
  }
9459
10763
  }
@@ -9544,9 +10848,9 @@ program2.command("doctor").description("Diagnose common issues with the mementos
9544
10848
  checks.push({ name: "MCP server", status: "warn", detail: "could not check (is claude CLI installed?)" });
9545
10849
  }
9546
10850
  try {
9547
- const settingsFilePath = join3(homedir2(), ".claude", "settings.json");
9548
- if (existsSync3(settingsFilePath)) {
9549
- const settings = JSON.parse(readFileSync2(settingsFilePath, "utf-8"));
10851
+ const settingsFilePath = join6(homedir4(), ".claude", "settings.json");
10852
+ if (existsSync6(settingsFilePath)) {
10853
+ const settings = JSON.parse(readFileSync3(settingsFilePath, "utf-8"));
9550
10854
  const hooksObj = settings["hooks"] || {};
9551
10855
  const stopHooks = hooksObj["Stop"] || [];
9552
10856
  const hasMementos = stopHooks.some((e) => e.hooks?.some((h) => h.command && h.command.includes("mementos")));
@@ -9562,11 +10866,11 @@ program2.command("doctor").description("Diagnose common issues with the mementos
9562
10866
  checks.push({ name: "Stop hook", status: "warn", detail: "could not check stop hook" });
9563
10867
  }
9564
10868
  if (process.platform === "darwin") {
9565
- const plistFilePath = join3(homedir2(), "Library", "LaunchAgents", "com.hasna.mementos.plist");
10869
+ const plistFilePath = join6(homedir4(), "Library", "LaunchAgents", "com.hasna.mementos.plist");
9566
10870
  checks.push({
9567
10871
  name: "Auto-start",
9568
- status: existsSync3(plistFilePath) ? "ok" : "warn",
9569
- detail: existsSync3(plistFilePath) ? "configured (starts on login)" : "not configured \u2192 run: mementos init"
10872
+ status: existsSync6(plistFilePath) ? "ok" : "warn",
10873
+ detail: existsSync6(plistFilePath) ? "configured (starts on login)" : "not configured \u2192 run: mementos init"
9570
10874
  });
9571
10875
  } else {
9572
10876
  checks.push({ name: "Auto-start", status: "ok", detail: `n/a on ${process.platform}` });
@@ -9577,24 +10881,24 @@ function outputDoctorResults(globalOpts, checks) {
9577
10881
  if (globalOpts.json) {
9578
10882
  outputJson({ checks, healthy: checks.every((c) => c.status === "ok") });
9579
10883
  } else {
9580
- console.log(chalk.bold(`
10884
+ console.log(chalk2.bold(`
9581
10885
  mementos doctor
9582
10886
  `));
9583
10887
  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}`);
10888
+ const icon = check.status === "ok" ? chalk2.green("\u2713") : check.status === "warn" ? chalk2.yellow("\u26A0") : chalk2.red("\u2717");
10889
+ console.log(` ${icon} ${chalk2.bold(check.name)}: ${check.detail}`);
9586
10890
  }
9587
10891
  const healthy = checks.every((c) => c.status === "ok");
9588
10892
  const warnings = checks.filter((c) => c.status === "warn").length;
9589
10893
  const failures = checks.filter((c) => c.status === "fail").length;
9590
10894
  console.log("");
9591
10895
  if (healthy) {
9592
- console.log(chalk.green(" All checks passed."));
10896
+ console.log(chalk2.green(" All checks passed."));
9593
10897
  } else {
9594
10898
  if (failures > 0)
9595
- console.log(chalk.red(` ${failures} check(s) failed.`));
10899
+ console.log(chalk2.red(` ${failures} check(s) failed.`));
9596
10900
  if (warnings > 0)
9597
- console.log(chalk.yellow(` ${warnings} warning(s).`));
10901
+ console.log(chalk2.yellow(` ${warnings} warning(s).`));
9598
10902
  }
9599
10903
  console.log("");
9600
10904
  }
@@ -9608,7 +10912,7 @@ program2.command("show <id>").description("Show full detail of a memory by ID (s
9608
10912
  if (globalOpts.json) {
9609
10913
  outputJson({ error: `Memory not found: ${id}` });
9610
10914
  } else {
9611
- console.error(chalk.red(`Memory not found: ${id}`));
10915
+ console.error(chalk2.red(`Memory not found: ${id}`));
9612
10916
  }
9613
10917
  process.exit(1);
9614
10918
  }
@@ -9634,24 +10938,24 @@ program2.command("history").description("List memories sorted by most recently a
9634
10938
  return;
9635
10939
  }
9636
10940
  if (memories.length === 0) {
9637
- console.log(chalk.yellow("No recently accessed memories."));
10941
+ console.log(chalk2.yellow("No recently accessed memories."));
9638
10942
  return;
9639
10943
  }
9640
- console.log(chalk.bold(`${memories.length} recently accessed memor${memories.length === 1 ? "y" : "ies"}:`));
10944
+ console.log(chalk2.bold(`${memories.length} recently accessed memor${memories.length === 1 ? "y" : "ies"}:`));
9641
10945
  for (const m of memories) {
9642
- const id = chalk.dim(m.id.slice(0, 8));
10946
+ const id = chalk2.dim(m.id.slice(0, 8));
9643
10947
  const scope = colorScope(m.scope);
9644
10948
  const cat = colorCategory(m.category);
9645
10949
  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}`);
10950
+ const accessed = m.accessed_at ? chalk2.dim(m.accessed_at) : chalk2.dim("never");
10951
+ console.log(`${id} [${scope}/${cat}] ${chalk2.bold(m.key)} = ${value} ${accessed}`);
9648
10952
  }
9649
10953
  } catch (e) {
9650
10954
  handleError(e);
9651
10955
  }
9652
10956
  });
9653
10957
  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");
10958
+ const { readFileSync: readFileSync4, writeFileSync: writeFileSync5, existsSync: fileExists } = __require("fs");
9655
10959
  const { join: pathJoin } = __require("path");
9656
10960
  const { homedir: getHome } = __require("os");
9657
10961
  const home = getHome();
@@ -9662,8 +10966,8 @@ program2.command("mcp").description("Install mementos MCP server into Claude Cod
9662
10966
  opts.gemini ? "gemini" : null
9663
10967
  ].filter(Boolean);
9664
10968
  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"));
10969
+ console.log(chalk2.yellow("Specify a target: --claude, --codex, --gemini, or --all"));
10970
+ console.log(chalk2.gray("Example: mementos mcp --all"));
9667
10971
  return;
9668
10972
  }
9669
10973
  for (const target of targets) {
@@ -9673,25 +10977,25 @@ program2.command("mcp").description("Install mementos MCP server into Claude Cod
9673
10977
  if (opts.uninstall) {
9674
10978
  try {
9675
10979
  execSync(`claude mcp remove mementos`, { stdio: "pipe" });
9676
- console.log(chalk.green("Removed mementos from Claude Code MCP"));
10980
+ console.log(chalk2.green("Removed mementos from Claude Code MCP"));
9677
10981
  } catch {
9678
- console.log(chalk.yellow("mementos was not installed in Claude Code (or claude CLI not found)"));
10982
+ console.log(chalk2.yellow("mementos was not installed in Claude Code (or claude CLI not found)"));
9679
10983
  }
9680
10984
  } else {
9681
10985
  try {
9682
10986
  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."));
10987
+ console.log(chalk2.green(`Installed mementos into Claude Code (user scope)`));
10988
+ console.log(chalk2.gray(" Restart Claude Code for the change to take effect."));
9685
10989
  } 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}`));
10990
+ console.log(chalk2.yellow("claude CLI not found. Run this manually:"));
10991
+ console.log(chalk2.white(` claude mcp add --transport stdio --scope user mementos -- ${mementosCmd}`));
9688
10992
  }
9689
10993
  }
9690
10994
  }
9691
10995
  if (target === "codex") {
9692
10996
  const configPath = pathJoin(home, ".codex", "config.toml");
9693
10997
  if (fileExists(configPath)) {
9694
- let content = readFileSync3(configPath, "utf-8");
10998
+ let content = readFileSync4(configPath, "utf-8");
9695
10999
  if (opts.uninstall) {
9696
11000
  content = content.replace(/\n\[mcp_servers\.mementos\]\ncommand = "[^"]*"\nargs = \[\]\n?/g, `
9697
11001
  `);
@@ -9702,17 +11006,17 @@ command = "${mementosCmd}"
9702
11006
  args = []
9703
11007
  `;
9704
11008
  }
9705
- writeFileSync3(configPath, content, "utf-8");
9706
- console.log(chalk.green(`${opts.uninstall ? "Removed from" : "Installed into"} Codex: ${configPath}`));
11009
+ writeFileSync5(configPath, content, "utf-8");
11010
+ console.log(chalk2.green(`${opts.uninstall ? "Removed from" : "Installed into"} Codex: ${configPath}`));
9707
11011
  } else {
9708
- console.log(chalk.yellow(`Codex config not found: ${configPath}`));
11012
+ console.log(chalk2.yellow(`Codex config not found: ${configPath}`));
9709
11013
  }
9710
11014
  }
9711
11015
  if (target === "gemini") {
9712
11016
  const configPath = pathJoin(home, ".gemini", "settings.json");
9713
11017
  let config = {};
9714
11018
  if (fileExists(configPath)) {
9715
- config = JSON.parse(readFileSync3(configPath, "utf-8"));
11019
+ config = JSON.parse(readFileSync4(configPath, "utf-8"));
9716
11020
  }
9717
11021
  const servers = config["mcpServers"] || {};
9718
11022
  if (opts.uninstall) {
@@ -9721,12 +11025,12 @@ args = []
9721
11025
  servers["mementos"] = { command: mementosCmd, args: [] };
9722
11026
  }
9723
11027
  config["mcpServers"] = servers;
9724
- writeFileSync3(configPath, JSON.stringify(config, null, 2) + `
11028
+ writeFileSync5(configPath, JSON.stringify(config, null, 2) + `
9725
11029
  `, "utf-8");
9726
- console.log(chalk.green(`${opts.uninstall ? "Removed from" : "Installed into"} Gemini: ${configPath}`));
11030
+ console.log(chalk2.green(`${opts.uninstall ? "Removed from" : "Installed into"} Gemini: ${configPath}`));
9727
11031
  }
9728
11032
  } catch (e) {
9729
- console.error(chalk.red(`Failed for ${target}: ${e instanceof Error ? e.message : String(e)}`));
11033
+ console.error(chalk2.red(`Failed for ${target}: ${e instanceof Error ? e.message : String(e)}`));
9730
11034
  }
9731
11035
  }
9732
11036
  });
@@ -9742,20 +11046,20 @@ program2.command("watch").description("Watch for new and changed memories in rea
9742
11046
  projectId = project.id;
9743
11047
  }
9744
11048
  const intervalMs = opts.interval || 500;
9745
- console.log(chalk.bold.cyan("Watching memories...") + chalk.dim(" (Ctrl+C to stop)"));
11049
+ console.log(chalk2.bold.cyan("Watching memories...") + chalk2.dim(" (Ctrl+C to stop)"));
9746
11050
  const filters = [];
9747
11051
  if (opts.scope)
9748
11052
  filters.push(`scope=${colorScope(opts.scope)}`);
9749
11053
  if (opts.category)
9750
11054
  filters.push(`category=${colorCategory(opts.category)}`);
9751
11055
  if (agentId)
9752
- filters.push(`agent=${chalk.dim(agentId)}`);
11056
+ filters.push(`agent=${chalk2.dim(agentId)}`);
9753
11057
  if (projectId)
9754
- filters.push(`project=${chalk.dim(projectId)}`);
11058
+ filters.push(`project=${chalk2.dim(projectId)}`);
9755
11059
  if (filters.length > 0) {
9756
- console.log(chalk.dim("Filters: ") + filters.join(chalk.dim(" | ")));
11060
+ console.log(chalk2.dim("Filters: ") + filters.join(chalk2.dim(" | ")));
9757
11061
  }
9758
- console.log(chalk.dim(`Poll interval: ${intervalMs}ms`));
11062
+ console.log(chalk2.dim(`Poll interval: ${intervalMs}ms`));
9759
11063
  console.log();
9760
11064
  const filter = {
9761
11065
  scope: opts.scope,
@@ -9766,14 +11070,14 @@ program2.command("watch").description("Watch for new and changed memories in rea
9766
11070
  };
9767
11071
  const recent = listMemories(filter);
9768
11072
  if (recent.length > 0) {
9769
- console.log(chalk.bold.dim(`Recent (${recent.length}):`));
11073
+ console.log(chalk2.bold.dim(`Recent (${recent.length}):`));
9770
11074
  for (const m of recent.reverse()) {
9771
11075
  console.log(formatWatchLine(m));
9772
11076
  }
9773
11077
  } else {
9774
- console.log(chalk.dim("No recent memories."));
11078
+ console.log(chalk2.dim("No recent memories."));
9775
11079
  }
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"));
11080
+ 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
11081
  console.log();
9778
11082
  const { startPolling: startPolling2 } = (init_poll(), __toCommonJS(exports_poll));
9779
11083
  const handle = startPolling2({
@@ -9789,13 +11093,13 @@ program2.command("watch").description("Watch for new and changed memories in rea
9789
11093
  }
9790
11094
  },
9791
11095
  on_error: (err) => {
9792
- console.error(chalk.red(`Poll error: ${err.message}`));
11096
+ console.error(chalk2.red(`Poll error: ${err.message}`));
9793
11097
  }
9794
11098
  });
9795
11099
  const cleanup = () => {
9796
11100
  handle.stop();
9797
11101
  console.log();
9798
- console.log(chalk.dim("Stopped watching."));
11102
+ console.log(chalk2.dim("Stopped watching."));
9799
11103
  process.exit(0);
9800
11104
  };
9801
11105
  process.on("SIGINT", cleanup);
@@ -9812,7 +11116,7 @@ program2.command("pin <keyOrId>").description("Pin a memory by key or partial ID
9812
11116
  if (globalOpts.json) {
9813
11117
  outputJson({ error: `No memory found: ${keyOrId}` });
9814
11118
  } else {
9815
- console.error(chalk.red(`No memory found: ${keyOrId}`));
11119
+ console.error(chalk2.red(`No memory found: ${keyOrId}`));
9816
11120
  }
9817
11121
  process.exit(1);
9818
11122
  }
@@ -9823,7 +11127,7 @@ program2.command("pin <keyOrId>").description("Pin a memory by key or partial ID
9823
11127
  if (globalOpts.json) {
9824
11128
  outputJson(updated);
9825
11129
  } else {
9826
- console.log(chalk.green(`Pinned: ${updated.key} (${updated.id.slice(0, 8)})`));
11130
+ console.log(chalk2.green(`Pinned: ${updated.key} (${updated.id.slice(0, 8)})`));
9827
11131
  }
9828
11132
  } catch (e) {
9829
11133
  handleError(e);
@@ -9837,7 +11141,7 @@ program2.command("unpin <keyOrId>").description("Unpin a memory by key or partia
9837
11141
  if (globalOpts.json) {
9838
11142
  outputJson({ error: `No memory found: ${keyOrId}` });
9839
11143
  } else {
9840
- console.error(chalk.red(`No memory found: ${keyOrId}`));
11144
+ console.error(chalk2.red(`No memory found: ${keyOrId}`));
9841
11145
  }
9842
11146
  process.exit(1);
9843
11147
  }
@@ -9848,7 +11152,7 @@ program2.command("unpin <keyOrId>").description("Unpin a memory by key or partia
9848
11152
  if (globalOpts.json) {
9849
11153
  outputJson(updated);
9850
11154
  } else {
9851
- console.log(chalk.green(`Unpinned: ${updated.key} (${updated.id.slice(0, 8)})`));
11155
+ console.log(chalk2.green(`Unpinned: ${updated.key} (${updated.id.slice(0, 8)})`));
9852
11156
  }
9853
11157
  } catch (e) {
9854
11158
  handleError(e);
@@ -9859,17 +11163,17 @@ program2.command("archive <keyOrId>").description("Archive a memory by key or ID
9859
11163
  const globalOpts = program2.opts();
9860
11164
  let memory = getMemory(resolvePartialId(getDatabase(), "memories", keyOrId) || keyOrId) || getMemoryByKey(keyOrId, opts.scope, globalOpts.agent);
9861
11165
  if (!memory) {
9862
- console.error(chalk.red(`No memory found: ${keyOrId}`));
11166
+ console.error(chalk2.red(`No memory found: ${keyOrId}`));
9863
11167
  process.exit(1);
9864
11168
  }
9865
11169
  updateMemory(memory.id, { status: "archived", version: memory.version });
9866
11170
  if (globalOpts.json) {
9867
11171
  outputJson({ archived: true, id: memory.id, key: memory.key });
9868
11172
  } else {
9869
- console.log(chalk.green(`\u2713 Archived: ${chalk.bold(memory.key)} (${memory.id.slice(0, 8)})`));
11173
+ console.log(chalk2.green(`\u2713 Archived: ${chalk2.bold(memory.key)} (${memory.id.slice(0, 8)})`));
9870
11174
  }
9871
11175
  } catch (e) {
9872
- console.error(chalk.red(`archive failed: ${e instanceof Error ? e.message : String(e)}`));
11176
+ console.error(chalk2.red(`archive failed: ${e instanceof Error ? e.message : String(e)}`));
9873
11177
  process.exit(1);
9874
11178
  }
9875
11179
  });
@@ -9878,7 +11182,7 @@ program2.command("versions <keyOrId>").description("Show version history for a m
9878
11182
  const globalOpts = program2.opts();
9879
11183
  let memory = getMemory(resolvePartialId(getDatabase(), "memories", keyOrId) || keyOrId) || getMemoryByKey(keyOrId, opts.scope, globalOpts.agent);
9880
11184
  if (!memory) {
9881
- console.error(chalk.red(`No memory found: ${keyOrId}`));
11185
+ console.error(chalk2.red(`No memory found: ${keyOrId}`));
9882
11186
  process.exit(1);
9883
11187
  }
9884
11188
  const versions = getMemoryVersions(memory.id);
@@ -9886,20 +11190,20 @@ program2.command("versions <keyOrId>").description("Show version history for a m
9886
11190
  outputJson({ memory: { id: memory.id, key: memory.key, current_version: memory.version }, versions });
9887
11191
  return;
9888
11192
  }
9889
- console.log(chalk.bold(`
11193
+ console.log(chalk2.bold(`
9890
11194
  Version history: ${memory.key} (current: v${memory.version})
9891
11195
  `));
9892
11196
  if (versions.length === 0) {
9893
- console.log(chalk.dim(" No previous versions."));
11197
+ console.log(chalk2.dim(" No previous versions."));
9894
11198
  return;
9895
11199
  }
9896
11200
  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}`);
11201
+ console.log(` ${chalk2.cyan(`v${v.version}`)} ${chalk2.dim(v.created_at.slice(0, 16))} scope=${v.scope} imp=${v.importance}`);
9898
11202
  console.log(` ${v.value.slice(0, 120)}${v.value.length > 120 ? "..." : ""}`);
9899
11203
  }
9900
11204
  console.log("");
9901
11205
  } catch (e) {
9902
- console.error(chalk.red(`versions failed: ${e instanceof Error ? e.message : String(e)}`));
11206
+ console.error(chalk2.red(`versions failed: ${e instanceof Error ? e.message : String(e)}`));
9903
11207
  process.exit(1);
9904
11208
  }
9905
11209
  });
@@ -9919,20 +11223,20 @@ program2.command("tail").description("Watch for new/updated memories in real-tim
9919
11223
  const notifyEnabled = !!opts.notify;
9920
11224
  const startTime = new Date().toISOString();
9921
11225
  if (!jsonMode) {
9922
- console.log(chalk.bold.cyan("Watching for memory changes...") + chalk.dim(" (Ctrl+C to stop)"));
11226
+ console.log(chalk2.bold.cyan("Watching for memory changes...") + chalk2.dim(" (Ctrl+C to stop)"));
9923
11227
  const filters = [];
9924
11228
  if (opts.scope)
9925
11229
  filters.push(`scope=${colorScope(opts.scope)}`);
9926
11230
  if (opts.category)
9927
11231
  filters.push(`category=${colorCategory(opts.category)}`);
9928
11232
  if (agentId)
9929
- filters.push(`agent=${chalk.dim(agentId)}`);
11233
+ filters.push(`agent=${chalk2.dim(agentId)}`);
9930
11234
  if (projectId)
9931
- filters.push(`project=${chalk.dim(projectId)}`);
11235
+ filters.push(`project=${chalk2.dim(projectId)}`);
9932
11236
  if (filters.length > 0) {
9933
- console.log(chalk.dim("Filters: ") + filters.join(chalk.dim(" | ")));
11237
+ console.log(chalk2.dim("Filters: ") + filters.join(chalk2.dim(" | ")));
9934
11238
  }
9935
- console.log(chalk.dim(`Poll interval: ${intervalMs}ms`));
11239
+ console.log(chalk2.dim(`Poll interval: ${intervalMs}ms`));
9936
11240
  console.log();
9937
11241
  }
9938
11242
  const { startPolling: startPolling2 } = (init_poll(), __toCommonJS(exports_poll));
@@ -9948,7 +11252,7 @@ program2.command("tail").description("Watch for new/updated memories in real-tim
9948
11252
  if (jsonMode) {
9949
11253
  console.log(JSON.stringify({ event: isNew ? "new" : "updated", memory: m }));
9950
11254
  } else {
9951
- const prefix = isNew ? chalk.green.bold("+ ") : chalk.yellow.bold("~ ");
11255
+ const prefix = isNew ? chalk2.green.bold("+ ") : chalk2.yellow.bold("~ ");
9952
11256
  console.log(prefix + formatWatchLine(m));
9953
11257
  }
9954
11258
  if (notifyEnabled)
@@ -9959,7 +11263,7 @@ program2.command("tail").description("Watch for new/updated memories in real-tim
9959
11263
  if (jsonMode) {
9960
11264
  console.error(JSON.stringify({ event: "error", message: err.message }));
9961
11265
  } else {
9962
- console.error(chalk.red(`Poll error: ${err.message}`));
11266
+ console.error(chalk2.red(`Poll error: ${err.message}`));
9963
11267
  }
9964
11268
  }
9965
11269
  });
@@ -9967,7 +11271,7 @@ program2.command("tail").description("Watch for new/updated memories in real-tim
9967
11271
  handle.stop();
9968
11272
  if (!jsonMode) {
9969
11273
  console.log();
9970
- console.log(chalk.dim("Stopped watching."));
11274
+ console.log(chalk2.dim("Stopped watching."));
9971
11275
  }
9972
11276
  process.exit(0);
9973
11277
  };
@@ -10059,7 +11363,7 @@ ${lines.join(`
10059
11363
  }
10060
11364
  if (lines.length === 0) {
10061
11365
  if (process.stdout.isTTY) {
10062
- console.log(chalk.yellow("No relevant memories found."));
11366
+ console.log(chalk2.yellow("No relevant memories found."));
10063
11367
  }
10064
11368
  return;
10065
11369
  }
@@ -10075,18 +11379,18 @@ program2.command("backup [path]").description("Backup the SQLite database to a f
10075
11379
  try {
10076
11380
  const globalOpts = program2.opts();
10077
11381
  const home = process.env["HOME"] || process.env["USERPROFILE"] || "~";
10078
- const backupsDir = join3(home, ".mementos", "backups");
11382
+ const backupsDir = join6(home, ".mementos", "backups");
10079
11383
  if (opts.list) {
10080
- if (!existsSync3(backupsDir)) {
11384
+ if (!existsSync6(backupsDir)) {
10081
11385
  if (globalOpts.json) {
10082
11386
  outputJson({ backups: [] });
10083
11387
  return;
10084
11388
  }
10085
- console.log(chalk.yellow("No backups directory found."));
11389
+ console.log(chalk2.yellow("No backups directory found."));
10086
11390
  return;
10087
11391
  }
10088
- const files = readdirSync2(backupsDir).filter((f) => f.endsWith(".db")).map((f) => {
10089
- const filePath = join3(backupsDir, f);
11392
+ const files = readdirSync3(backupsDir).filter((f) => f.endsWith(".db")).map((f) => {
11393
+ const filePath = join6(backupsDir, f);
10090
11394
  const st2 = statSync(filePath);
10091
11395
  return { name: f, path: filePath, size: st2.size, mtime: st2.mtime };
10092
11396
  }).sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
@@ -10095,7 +11399,7 @@ program2.command("backup [path]").description("Backup the SQLite database to a f
10095
11399
  outputJson({ backups: [] });
10096
11400
  return;
10097
11401
  }
10098
- console.log(chalk.yellow("No backups found."));
11402
+ console.log(chalk2.yellow("No backups found."));
10099
11403
  return;
10100
11404
  }
10101
11405
  if (globalOpts.json) {
@@ -10109,34 +11413,34 @@ program2.command("backup [path]").description("Backup the SQLite database to a f
10109
11413
  });
10110
11414
  return;
10111
11415
  }
10112
- console.log(chalk.bold(`Backups in ${backupsDir}:`));
11416
+ console.log(chalk2.bold(`Backups in ${backupsDir}:`));
10113
11417
  for (const f of files) {
10114
11418
  const date = f.mtime.toISOString().replace("T", " ").slice(0, 19);
10115
11419
  const sizeMB2 = (f.size / (1024 * 1024)).toFixed(1);
10116
11420
  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}`);
11421
+ console.log(` ${chalk2.dim(date)} ${chalk2.cyan(sizeStr2.padStart(8))} ${f.name}`);
10118
11422
  }
10119
11423
  return;
10120
11424
  }
10121
11425
  const dbPath = getDbPath();
10122
- if (!existsSync3(dbPath)) {
10123
- console.error(chalk.red(`Database not found at ${dbPath}`));
11426
+ if (!existsSync6(dbPath)) {
11427
+ console.error(chalk2.red(`Database not found at ${dbPath}`));
10124
11428
  process.exit(1);
10125
11429
  }
10126
11430
  let dest;
10127
11431
  if (targetPath) {
10128
11432
  dest = resolve3(targetPath);
10129
11433
  } else {
10130
- if (!existsSync3(backupsDir)) {
10131
- mkdirSync3(backupsDir, { recursive: true });
11434
+ if (!existsSync6(backupsDir)) {
11435
+ mkdirSync6(backupsDir, { recursive: true });
10132
11436
  }
10133
- const now2 = new Date;
10134
- const ts = now2.toISOString().replace(/[-:T]/g, "").replace(/\..+/, "").slice(0, 15);
10135
- dest = join3(backupsDir, `mementos-${ts}.db`);
11437
+ const now3 = new Date;
11438
+ const ts = now3.toISOString().replace(/[-:T]/g, "").replace(/\..+/, "").slice(0, 15);
11439
+ dest = join6(backupsDir, `mementos-${ts}.db`);
10136
11440
  }
10137
- const destDir = dirname3(dest);
10138
- if (!existsSync3(destDir)) {
10139
- mkdirSync3(destDir, { recursive: true });
11441
+ const destDir = dirname4(dest);
11442
+ if (!existsSync6(destDir)) {
11443
+ mkdirSync6(destDir, { recursive: true });
10140
11444
  }
10141
11445
  copyFileSync(dbPath, dest);
10142
11446
  const st = statSync(dest);
@@ -10146,7 +11450,7 @@ program2.command("backup [path]").description("Backup the SQLite database to a f
10146
11450
  outputJson({ backed_up_to: dest, size: st.size, source: dbPath });
10147
11451
  return;
10148
11452
  }
10149
- console.log(`Backed up to: ${chalk.green(dest)} (size: ${sizeStr})`);
11453
+ console.log(`Backed up to: ${chalk2.green(dest)} (size: ${sizeStr})`);
10150
11454
  } catch (e) {
10151
11455
  handleError(e);
10152
11456
  }
@@ -10155,31 +11459,31 @@ program2.command("restore [file]").description("Restore the database from a back
10155
11459
  try {
10156
11460
  const globalOpts = program2.opts();
10157
11461
  const home = process.env["HOME"] || process.env["USERPROFILE"] || "~";
10158
- const backupsDir = join3(home, ".mementos", "backups");
11462
+ const backupsDir = join6(home, ".mementos", "backups");
10159
11463
  let source;
10160
11464
  if (opts.latest) {
10161
- if (!existsSync3(backupsDir)) {
10162
- console.error(chalk.red("No backups directory found."));
11465
+ if (!existsSync6(backupsDir)) {
11466
+ console.error(chalk2.red("No backups directory found."));
10163
11467
  process.exit(1);
10164
11468
  }
10165
- const files = readdirSync2(backupsDir).filter((f) => f.endsWith(".db")).map((f) => {
10166
- const fp = join3(backupsDir, f);
11469
+ const files = readdirSync3(backupsDir).filter((f) => f.endsWith(".db")).map((f) => {
11470
+ const fp = join6(backupsDir, f);
10167
11471
  const st = statSync(fp);
10168
11472
  return { path: fp, mtime: st.mtime };
10169
11473
  }).sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
10170
11474
  if (files.length === 0) {
10171
- console.error(chalk.red("No backups found in " + backupsDir));
11475
+ console.error(chalk2.red("No backups found in " + backupsDir));
10172
11476
  process.exit(1);
10173
11477
  }
10174
11478
  source = files[0].path;
10175
11479
  } else if (filePath) {
10176
11480
  source = resolve3(filePath);
10177
11481
  } else {
10178
- console.error(chalk.red("Provide a backup file path or use --latest"));
11482
+ console.error(chalk2.red("Provide a backup file path or use --latest"));
10179
11483
  process.exit(1);
10180
11484
  }
10181
- if (!existsSync3(source)) {
10182
- console.error(chalk.red(`Backup file not found: ${source}`));
11485
+ if (!existsSync6(source)) {
11486
+ console.error(chalk2.red(`Backup file not found: ${source}`));
10183
11487
  process.exit(1);
10184
11488
  }
10185
11489
  const dbPath = getDbPath();
@@ -10187,7 +11491,7 @@ program2.command("restore [file]").description("Restore the database from a back
10187
11491
  const backupSizeMB = (backupStat.size / (1024 * 1024)).toFixed(1);
10188
11492
  const backupSizeStr = backupStat.size >= 1024 * 1024 ? `${backupSizeMB} MB` : `${(backupStat.size / 1024).toFixed(1)} KB`;
10189
11493
  let currentCount = 0;
10190
- if (existsSync3(dbPath)) {
11494
+ if (existsSync6(dbPath)) {
10191
11495
  try {
10192
11496
  const db = getDatabase();
10193
11497
  const row = db.query("SELECT COUNT(*) as count FROM memories").get();
@@ -10196,8 +11500,8 @@ program2.command("restore [file]").description("Restore the database from a back
10196
11500
  }
10197
11501
  let backupCount = 0;
10198
11502
  try {
10199
- const { Database: Database2 } = __require("bun:sqlite");
10200
- const backupDb = new Database2(source, { readonly: true });
11503
+ const { Database: Database3 } = __require("bun:sqlite");
11504
+ const backupDb = new Database3(source, { readonly: true });
10201
11505
  const row = backupDb.query("SELECT COUNT(*) as count FROM memories").get();
10202
11506
  backupCount = row?.count ?? 0;
10203
11507
  backupDb.close();
@@ -10216,13 +11520,13 @@ program2.command("restore [file]").description("Restore the database from a back
10216
11520
  });
10217
11521
  return;
10218
11522
  }
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))}`);
11523
+ console.log(chalk2.bold("Restore preview:"));
11524
+ console.log(` Source: ${chalk2.cyan(source)} (${backupSizeStr})`);
11525
+ console.log(` Target: ${chalk2.cyan(dbPath)}`);
11526
+ console.log(` Current memories: ${chalk2.yellow(String(currentCount))}`);
11527
+ console.log(` Backup memories: ${chalk2.green(String(backupCount))}`);
10224
11528
  console.log();
10225
- console.log(chalk.yellow("Use --force to confirm restore"));
11529
+ console.log(chalk2.yellow("Use --force to confirm restore"));
10226
11530
  return;
10227
11531
  }
10228
11532
  copyFileSync(source, dbPath);
@@ -10245,9 +11549,9 @@ program2.command("restore [file]").description("Restore the database from a back
10245
11549
  });
10246
11550
  return;
10247
11551
  }
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))}`);
11552
+ console.log(`Restored from: ${chalk2.green(source)}`);
11553
+ console.log(` Previous memories: ${chalk2.yellow(String(currentCount))}`);
11554
+ console.log(` Restored memories: ${chalk2.green(String(newCount))}`);
10251
11555
  } catch (e) {
10252
11556
  handleError(e);
10253
11557
  }
@@ -10260,7 +11564,7 @@ program2.command("diff <id>").description("Show diff between memory versions").o
10260
11564
  if (!memoryId) {
10261
11565
  const mem = resolveKeyOrId(idArg, {}, globalOpts);
10262
11566
  if (!mem) {
10263
- console.error(chalk.red(`Memory not found: ${idArg}`));
11567
+ console.error(chalk2.red(`Memory not found: ${idArg}`));
10264
11568
  process.exit(1);
10265
11569
  }
10266
11570
  memoryId = mem.id;
@@ -10273,7 +11577,7 @@ program2.command("diff <id>").description("Show diff between memory versions").o
10273
11577
  function diffMemory(memoryId, opts, globalOpts) {
10274
11578
  const current = getMemory(memoryId);
10275
11579
  if (!current) {
10276
- console.error(chalk.red(`Memory not found: ${memoryId}`));
11580
+ console.error(chalk2.red(`Memory not found: ${memoryId}`));
10277
11581
  process.exit(1);
10278
11582
  }
10279
11583
  const versions = getMemoryVersions(memoryId);
@@ -10281,8 +11585,8 @@ function diffMemory(memoryId, opts, globalOpts) {
10281
11585
  if (globalOpts.json) {
10282
11586
  outputJson({ error: "No version history available", memory_id: memoryId });
10283
11587
  } 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.`));
11588
+ console.log(chalk2.yellow("No version history available."));
11589
+ console.log(chalk2.dim(`Memory "${current.key}" is at version ${current.version} but has no prior snapshots.`));
10286
11590
  }
10287
11591
  return;
10288
11592
  }
@@ -10293,13 +11597,13 @@ function diffMemory(memoryId, opts, globalOpts) {
10293
11597
  if (opts.version) {
10294
11598
  const targetVersion = parseInt(opts.version, 10);
10295
11599
  if (isNaN(targetVersion) || targetVersion < 1) {
10296
- console.error(chalk.red("Version must be a positive integer."));
11600
+ console.error(chalk2.red("Version must be a positive integer."));
10297
11601
  process.exit(1);
10298
11602
  }
10299
11603
  if (targetVersion === current.version) {
10300
11604
  const prev = versions.find((v) => v.version === targetVersion - 1);
10301
11605
  if (!prev) {
10302
- console.error(chalk.red(`No version ${targetVersion - 1} found to compare against.`));
11606
+ console.error(chalk2.red(`No version ${targetVersion - 1} found to compare against.`));
10303
11607
  process.exit(1);
10304
11608
  }
10305
11609
  older = prev;
@@ -10315,10 +11619,10 @@ function diffMemory(memoryId, opts, globalOpts) {
10315
11619
  olderVersion = prevSnap.version;
10316
11620
  newerVersion = targetSnap.version;
10317
11621
  } else if (targetSnap && !prevSnap) {
10318
- console.error(chalk.red(`No version ${targetVersion - 1} found to compare against.`));
11622
+ console.error(chalk2.red(`No version ${targetVersion - 1} found to compare against.`));
10319
11623
  process.exit(1);
10320
11624
  } else {
10321
- console.error(chalk.red(`Version ${targetVersion} not found.`));
11625
+ console.error(chalk2.red(`Version ${targetVersion} not found.`));
10322
11626
  process.exit(1);
10323
11627
  }
10324
11628
  }
@@ -10357,8 +11661,8 @@ function diffMemory(memoryId, opts, globalOpts) {
10357
11661
  });
10358
11662
  return;
10359
11663
  }
10360
- console.log(chalk.bold(`Diff for "${current.key}" (${memoryId.slice(0, 8)})`));
10361
- console.log(chalk.dim(`Version ${olderVersion} \u2192 ${newerVersion}`));
11664
+ console.log(chalk2.bold(`Diff for "${current.key}" (${memoryId.slice(0, 8)})`));
11665
+ console.log(chalk2.dim(`Version ${olderVersion} \u2192 ${newerVersion}`));
10362
11666
  console.log();
10363
11667
  let hasChanges = false;
10364
11668
  const n = newer;
@@ -10366,7 +11670,7 @@ function diffMemory(memoryId, opts, globalOpts) {
10366
11670
  const newValue = n.value;
10367
11671
  if (oldValue !== newValue) {
10368
11672
  hasChanges = true;
10369
- console.log(chalk.bold(" value:"));
11673
+ console.log(chalk2.bold(" value:"));
10370
11674
  diffLines(oldValue, newValue);
10371
11675
  }
10372
11676
  const scalarFields = [
@@ -10380,7 +11684,7 @@ function diffMemory(memoryId, opts, globalOpts) {
10380
11684
  for (const field of scalarFields) {
10381
11685
  if (String(field.oldVal) !== String(field.newVal)) {
10382
11686
  hasChanges = true;
10383
- console.log(` ${chalk.bold(field.name + ":")} ${chalk.red(String(field.oldVal))} \u2192 ${chalk.green(String(field.newVal))}`);
11687
+ console.log(` ${chalk2.bold(field.name + ":")} ${chalk2.red(String(field.oldVal))} \u2192 ${chalk2.green(String(field.newVal))}`);
10384
11688
  }
10385
11689
  }
10386
11690
  const oldTags = older.tags;
@@ -10389,14 +11693,14 @@ function diffMemory(memoryId, opts, globalOpts) {
10389
11693
  hasChanges = true;
10390
11694
  const removed = oldTags.filter((t) => !newTags.includes(t));
10391
11695
  const added = newTags.filter((t) => !oldTags.includes(t));
10392
- console.log(` ${chalk.bold("tags:")}`);
11696
+ console.log(` ${chalk2.bold("tags:")}`);
10393
11697
  for (const t of removed)
10394
- console.log(chalk.red(` - ${t}`));
11698
+ console.log(chalk2.red(` - ${t}`));
10395
11699
  for (const t of added)
10396
- console.log(chalk.green(` + ${t}`));
11700
+ console.log(chalk2.green(` + ${t}`));
10397
11701
  }
10398
11702
  if (!hasChanges) {
10399
- console.log(chalk.dim(" No changes between these versions."));
11703
+ console.log(chalk2.dim(" No changes between these versions."));
10400
11704
  }
10401
11705
  }
10402
11706
  function diffLines(oldText, newText) {
@@ -10405,22 +11709,22 @@ function diffLines(oldText, newText) {
10405
11709
  const newLines = newText.split(`
10406
11710
  `);
10407
11711
  if (oldLines.length === 1 && newLines.length === 1) {
10408
- console.log(chalk.red(` - ${oldLines[0]}`));
10409
- console.log(chalk.green(` + ${newLines[0]}`));
11712
+ console.log(chalk2.red(` - ${oldLines[0]}`));
11713
+ console.log(chalk2.green(` + ${newLines[0]}`));
10410
11714
  return;
10411
11715
  }
10412
11716
  const oldSet = new Set(oldLines);
10413
11717
  const newSet = new Set(newLines);
10414
11718
  for (const line of oldLines) {
10415
11719
  if (!newSet.has(line)) {
10416
- console.log(chalk.red(` - ${line}`));
11720
+ console.log(chalk2.red(` - ${line}`));
10417
11721
  } else {
10418
- console.log(chalk.dim(` ${line}`));
11722
+ console.log(chalk2.dim(` ${line}`));
10419
11723
  }
10420
11724
  }
10421
11725
  for (const line of newLines) {
10422
11726
  if (!oldSet.has(line)) {
10423
- console.log(chalk.green(` + ${line}`));
11727
+ console.log(chalk2.green(` + ${line}`));
10424
11728
  }
10425
11729
  }
10426
11730
  }
@@ -10576,24 +11880,24 @@ function validateConfigKeyValue(key, value) {
10576
11880
  return null;
10577
11881
  }
10578
11882
  function getConfigPath() {
10579
- return join3(homedir2(), ".mementos", "config.json");
11883
+ return join6(homedir4(), ".mementos", "config.json");
10580
11884
  }
10581
11885
  function readFileConfig() {
10582
11886
  const configPath = getConfigPath();
10583
- if (!existsSync3(configPath))
11887
+ if (!existsSync6(configPath))
10584
11888
  return {};
10585
11889
  try {
10586
- return JSON.parse(readFileSync2(configPath, "utf-8"));
11890
+ return JSON.parse(readFileSync3(configPath, "utf-8"));
10587
11891
  } catch {
10588
11892
  return {};
10589
11893
  }
10590
11894
  }
10591
11895
  function writeFileConfig(data) {
10592
11896
  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) + `
11897
+ const dir = dirname4(configPath);
11898
+ if (!existsSync6(dir))
11899
+ mkdirSync6(dir, { recursive: true });
11900
+ writeFileSync4(configPath, JSON.stringify(data, null, 2) + `
10597
11901
  `, "utf-8");
10598
11902
  }
10599
11903
  program2.command("config [subcommand] [args...]").description("View or modify configuration. Subcommands: get <key>, set <key> <value>, reset [key], path").action((subcommand, args) => {
@@ -10621,13 +11925,13 @@ program2.command("config [subcommand] [args...]").description("View or modify co
10621
11925
  if (subcommand === "get") {
10622
11926
  const key = args[0];
10623
11927
  if (!key) {
10624
- console.error(chalk.red("Usage: mementos config get <key>"));
11928
+ console.error(chalk2.red("Usage: mementos config get <key>"));
10625
11929
  process.exit(1);
10626
11930
  }
10627
11931
  const config = loadConfig();
10628
11932
  const value = getNestedValue(config, key);
10629
11933
  if (value === undefined) {
10630
- console.error(chalk.red(`Unknown config key: ${key}`));
11934
+ console.error(chalk2.red(`Unknown config key: ${key}`));
10631
11935
  process.exit(1);
10632
11936
  }
10633
11937
  if (useJson) {
@@ -10643,13 +11947,13 @@ program2.command("config [subcommand] [args...]").description("View or modify co
10643
11947
  const key = args[0];
10644
11948
  const rawValue = args[1];
10645
11949
  if (!key || rawValue === undefined) {
10646
- console.error(chalk.red("Usage: mementos config set <key> <value>"));
11950
+ console.error(chalk2.red("Usage: mementos config set <key> <value>"));
10647
11951
  process.exit(1);
10648
11952
  }
10649
11953
  const value = parseConfigValue(rawValue);
10650
11954
  const err = validateConfigKeyValue(key, value);
10651
11955
  if (err) {
10652
- console.error(chalk.red(err));
11956
+ console.error(chalk2.red(err));
10653
11957
  process.exit(1);
10654
11958
  }
10655
11959
  const fileConfig = readFileConfig();
@@ -10658,7 +11962,7 @@ program2.command("config [subcommand] [args...]").description("View or modify co
10658
11962
  if (useJson) {
10659
11963
  outputJson({ key, value, saved: true });
10660
11964
  } else {
10661
- console.log(chalk.green(`Set ${key} = ${JSON.stringify(value)}`));
11965
+ console.log(chalk2.green(`Set ${key} = ${JSON.stringify(value)}`));
10662
11966
  }
10663
11967
  return;
10664
11968
  }
@@ -10667,7 +11971,7 @@ program2.command("config [subcommand] [args...]").description("View or modify co
10667
11971
  if (key) {
10668
11972
  const defaultVal = getNestedValue(DEFAULT_CONFIG, key);
10669
11973
  if (defaultVal === undefined) {
10670
- console.error(chalk.red(`Unknown config key: ${key}`));
11974
+ console.error(chalk2.red(`Unknown config key: ${key}`));
10671
11975
  process.exit(1);
10672
11976
  }
10673
11977
  const fileConfig = readFileConfig();
@@ -10676,22 +11980,22 @@ program2.command("config [subcommand] [args...]").description("View or modify co
10676
11980
  if (useJson) {
10677
11981
  outputJson({ key, reset: true, default_value: defaultVal });
10678
11982
  } else {
10679
- console.log(chalk.green(`Reset ${key} to default (${JSON.stringify(defaultVal)})`));
11983
+ console.log(chalk2.green(`Reset ${key} to default (${JSON.stringify(defaultVal)})`));
10680
11984
  }
10681
11985
  } else {
10682
11986
  const configPath = getConfigPath();
10683
- if (existsSync3(configPath)) {
11987
+ if (existsSync6(configPath)) {
10684
11988
  unlinkSync2(configPath);
10685
11989
  }
10686
11990
  if (useJson) {
10687
11991
  outputJson({ reset: true, all: true });
10688
11992
  } else {
10689
- console.log(chalk.green("Config reset to defaults (file removed)"));
11993
+ console.log(chalk2.green("Config reset to defaults (file removed)"));
10690
11994
  }
10691
11995
  }
10692
11996
  return;
10693
11997
  }
10694
- console.error(chalk.red(`Unknown config subcommand: ${subcommand}`));
11998
+ console.error(chalk2.red(`Unknown config subcommand: ${subcommand}`));
10695
11999
  console.error("Usage: mementos config [get|set|reset|path]");
10696
12000
  process.exit(1);
10697
12001
  } catch (e) {
@@ -10718,7 +12022,7 @@ entityCmd.command("create <name>").description("Create a knowledge graph entity"
10718
12022
  if (globalOpts.json || globalOpts.format === "json") {
10719
12023
  outputJson(entity);
10720
12024
  } else {
10721
- console.log(chalk.green(`Entity: ${entity.name} (${entity.id.slice(0, 8)})`));
12025
+ console.log(chalk2.green(`Entity: ${entity.name} (${entity.id.slice(0, 8)})`));
10722
12026
  }
10723
12027
  } catch (e) {
10724
12028
  handleError(e);
@@ -10734,28 +12038,28 @@ entityCmd.command("show <nameOrId>").description("Show entity details with relat
10734
12038
  outputJson({ ...entity, related, memories });
10735
12039
  return;
10736
12040
  }
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)}`);
12041
+ console.log(`${chalk2.bold("ID:")} ${entity.id}`);
12042
+ console.log(`${chalk2.bold("Name:")} ${entity.name}`);
12043
+ console.log(`${chalk2.bold("Type:")} ${colorEntityType(entity.type)}`);
10740
12044
  if (entity.description)
10741
- console.log(`${chalk.bold("Description:")} ${entity.description}`);
12045
+ console.log(`${chalk2.bold("Description:")} ${entity.description}`);
10742
12046
  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}`);
12047
+ console.log(`${chalk2.bold("Project:")} ${entity.project_id}`);
12048
+ console.log(`${chalk2.bold("Created:")} ${entity.created_at}`);
12049
+ console.log(`${chalk2.bold("Updated:")} ${entity.updated_at}`);
10746
12050
  if (related.length > 0) {
10747
12051
  console.log(`
10748
- ${chalk.bold("Related entities:")}`);
12052
+ ${chalk2.bold("Related entities:")}`);
10749
12053
  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}`) : ""}`);
12054
+ console.log(` ${chalk2.dim(r.id.slice(0, 8))} [${colorEntityType(r.type)}] ${r.name}${r.description ? chalk2.dim(` \u2014 ${r.description}`) : ""}`);
10751
12055
  }
10752
12056
  }
10753
12057
  if (memories.length > 0) {
10754
12058
  console.log(`
10755
- ${chalk.bold("Linked memories:")}`);
12059
+ ${chalk2.bold("Linked memories:")}`);
10756
12060
  for (const m of memories) {
10757
12061
  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}`);
12062
+ console.log(` ${chalk2.dim(m.id.slice(0, 8))} ${chalk2.bold(m.key)} = ${value}`);
10759
12063
  }
10760
12064
  }
10761
12065
  } catch (e) {
@@ -10796,13 +12100,13 @@ entityCmd.command("list").description("List entities with optional filters").opt
10796
12100
  return;
10797
12101
  }
10798
12102
  if (entities.length === 0) {
10799
- console.log(chalk.yellow("No entities found."));
12103
+ console.log(chalk2.yellow("No entities found."));
10800
12104
  return;
10801
12105
  }
10802
- console.log(chalk.bold(`${entities.length} entit${entities.length === 1 ? "y" : "ies"}:`));
12106
+ console.log(chalk2.bold(`${entities.length} entit${entities.length === 1 ? "y" : "ies"}:`));
10803
12107
  for (const e of entities) {
10804
- const id = chalk.dim(e.id.slice(0, 8));
10805
- const desc = e.description ? chalk.dim(` (${e.description})`) : "";
12108
+ const id = chalk2.dim(e.id.slice(0, 8));
12109
+ const desc = e.description ? chalk2.dim(` (${e.description})`) : "";
10806
12110
  console.log(`${id} ${colorEntityType(e.type)} ${e.name}${desc}`);
10807
12111
  }
10808
12112
  } catch (e) {
@@ -10817,7 +12121,7 @@ entityCmd.command("delete <nameOrId>").description("Delete an entity and cascade
10817
12121
  if (globalOpts.json || globalOpts.format === "json") {
10818
12122
  outputJson({ deleted: entity.id, name: entity.name });
10819
12123
  } else {
10820
- console.log(chalk.green(`Deleted entity: ${entity.name} (${entity.id.slice(0, 8)}) \u2014 relations and memory links cascaded`));
12124
+ console.log(chalk2.green(`Deleted entity: ${entity.name} (${entity.id.slice(0, 8)}) \u2014 relations and memory links cascaded`));
10821
12125
  }
10822
12126
  } catch (e) {
10823
12127
  handleError(e);
@@ -10832,7 +12136,7 @@ entityCmd.command("merge <source> <target>").description("Merge source entity in
10832
12136
  if (globalOpts.json || globalOpts.format === "json") {
10833
12137
  outputJson(merged);
10834
12138
  } else {
10835
- console.log(chalk.green(`Merged: ${srcEntity.name} \u2192 ${merged.name} (${merged.id.slice(0, 8)})`));
12139
+ console.log(chalk2.green(`Merged: ${srcEntity.name} \u2192 ${merged.name} (${merged.id.slice(0, 8)})`));
10836
12140
  }
10837
12141
  } catch (e) {
10838
12142
  handleError(e);
@@ -10844,14 +12148,14 @@ entityCmd.command("link <entity> <memoryKeyOrId>").description("Link an entity t
10844
12148
  const entity = resolveEntityArg(entityArg, opts.type);
10845
12149
  const memory = resolveKeyOrId(memoryKeyOrId, {}, globalOpts);
10846
12150
  if (!memory) {
10847
- console.error(chalk.red(`Memory not found: ${memoryKeyOrId}`));
12151
+ console.error(chalk2.red(`Memory not found: ${memoryKeyOrId}`));
10848
12152
  process.exit(1);
10849
12153
  }
10850
12154
  const link = linkEntityToMemory(entity.id, memory.id, opts.role);
10851
12155
  if (globalOpts.json || globalOpts.format === "json") {
10852
12156
  outputJson(link);
10853
12157
  } else {
10854
- console.log(chalk.green(`Linked: ${entity.name} \u2194 ${memory.key} (role: ${link.role})`));
12158
+ console.log(chalk2.green(`Linked: ${entity.name} \u2194 ${memory.key} (role: ${link.role})`));
10855
12159
  }
10856
12160
  } catch (e) {
10857
12161
  handleError(e);
@@ -10872,7 +12176,7 @@ relationCmd.command("create <source> <target>").description("Create a relation b
10872
12176
  if (globalOpts.json || globalOpts.format === "json") {
10873
12177
  outputJson(relation);
10874
12178
  } else {
10875
- console.log(chalk.green(`Relation: ${srcEntity.name} \u2014[${relation.relation_type}]\u2192 ${tgtEntity.name} (${relation.id.slice(0, 8)})`));
12179
+ console.log(chalk2.green(`Relation: ${srcEntity.name} \u2014[${relation.relation_type}]\u2192 ${tgtEntity.name} (${relation.id.slice(0, 8)})`));
10876
12180
  }
10877
12181
  } catch (e) {
10878
12182
  handleError(e);
@@ -10903,7 +12207,7 @@ relationCmd.command("list <entityNameOrId>").description("List relations for an
10903
12207
  return;
10904
12208
  }
10905
12209
  if (relations.length === 0) {
10906
- console.log(chalk.yellow(`No relations found for: ${entity.name}`));
12210
+ console.log(chalk2.yellow(`No relations found for: ${entity.name}`));
10907
12211
  return;
10908
12212
  }
10909
12213
  const entityCache = new Map;
@@ -10919,13 +12223,13 @@ relationCmd.command("list <entityNameOrId>").description("List relations for an
10919
12223
  return id.slice(0, 8);
10920
12224
  }
10921
12225
  };
10922
- console.log(chalk.bold(`${relations.length} relation${relations.length === 1 ? "" : "s"} for ${entity.name}:`));
12226
+ console.log(chalk2.bold(`${relations.length} relation${relations.length === 1 ? "" : "s"} for ${entity.name}:`));
10923
12227
  for (const r of relations) {
10924
12228
  const src = resolveName(r.source_entity_id);
10925
12229
  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}`);
12230
+ const id = chalk2.dim(r.id.slice(0, 8));
12231
+ const weight = r.weight !== 1 ? chalk2.dim(` w:${r.weight}`) : "";
12232
+ console.log(`${id} ${src} \u2014[${chalk2.cyan(r.relation_type)}]\u2192 ${tgt}${weight}`);
10929
12233
  }
10930
12234
  } catch (e) {
10931
12235
  handleError(e);
@@ -10937,14 +12241,14 @@ relationCmd.command("delete <id>").description("Delete a relation by ID").action
10937
12241
  const db = getDatabase();
10938
12242
  const resolvedId = resolvePartialId(db, "relations", id);
10939
12243
  if (!resolvedId) {
10940
- console.error(chalk.red(`Relation not found: ${id}`));
12244
+ console.error(chalk2.red(`Relation not found: ${id}`));
10941
12245
  process.exit(1);
10942
12246
  }
10943
12247
  deleteRelation(resolvedId);
10944
12248
  if (globalOpts.json || globalOpts.format === "json") {
10945
12249
  outputJson({ deleted: resolvedId });
10946
12250
  } else {
10947
- console.log(chalk.green(`Deleted relation: ${resolvedId.slice(0, 8)}`));
12251
+ console.log(chalk2.green(`Deleted relation: ${resolvedId.slice(0, 8)}`));
10948
12252
  }
10949
12253
  } catch (e) {
10950
12254
  handleError(e);
@@ -10962,7 +12266,7 @@ graphCmd.command("show <entityNameOrId>").description("Show connected entities a
10962
12266
  return;
10963
12267
  }
10964
12268
  if (graph.entities.length === 0) {
10965
- console.log(chalk.yellow(`No graph data for: ${entity.name}`));
12269
+ console.log(chalk2.yellow(`No graph data for: ${entity.name}`));
10966
12270
  return;
10967
12271
  }
10968
12272
  const adj = new Map;
@@ -10994,7 +12298,7 @@ graphCmd.command("show <entityNameOrId>").description("Show connected entities a
10994
12298
  for (let i = 0;i < children.length; i++) {
10995
12299
  const child = children[i];
10996
12300
  const childIndent = indent + (indent === "" ? "" : isLast ? " " : "\u2502 ");
10997
- const relLabel = chalk.dim(` (${child.relation})`);
12301
+ const relLabel = chalk2.dim(` (${child.relation})`);
10998
12302
  const childPrefix = i === children.length - 1 ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
10999
12303
  visited.add(child.entity.id);
11000
12304
  console.log(`${childIndent}${childPrefix}[${colorEntityType(child.entity.type)}] ${child.entity.name}${relLabel}`);
@@ -11003,7 +12307,7 @@ graphCmd.command("show <entityNameOrId>").description("Show connected entities a
11003
12307
  const gc = grandChildren[j];
11004
12308
  const gcIndent = childIndent + (i === children.length - 1 ? " " : "\u2502 ");
11005
12309
  const gcPrefix = j === grandChildren.length - 1 ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
11006
- const gcRelLabel = chalk.dim(` (${gc.relation})`);
12310
+ const gcRelLabel = chalk2.dim(` (${gc.relation})`);
11007
12311
  visited.add(gc.entity.id);
11008
12312
  console.log(`${gcIndent}${gcPrefix}[${colorEntityType(gc.entity.type)}] ${gc.entity.name}${gcRelLabel}`);
11009
12313
  }
@@ -11025,10 +12329,10 @@ graphCmd.command("path <from> <to>").description("Show shortest path between two
11025
12329
  return;
11026
12330
  }
11027
12331
  if (!path) {
11028
- console.log(chalk.yellow(`No path found between ${fromEntity.name} and ${toEntity.name}`));
12332
+ console.log(chalk2.yellow(`No path found between ${fromEntity.name} and ${toEntity.name}`));
11029
12333
  return;
11030
12334
  }
11031
- console.log(chalk.bold(`Path (${path.length} hop${path.length === 1 ? "" : "s"}):`));
12335
+ console.log(chalk2.bold(`Path (${path.length} hop${path.length === 1 ? "" : "s"}):`));
11032
12336
  for (let i = 0;i < path.length; i++) {
11033
12337
  const e = path[i];
11034
12338
  const arrow = i < path.length - 1 ? " \u2192" : "";
@@ -11055,19 +12359,19 @@ graphCmd.command("stats").description("Show knowledge graph statistics").action(
11055
12359
  });
11056
12360
  return;
11057
12361
  }
11058
- console.log(chalk.bold("Knowledge Graph Stats"));
12362
+ console.log(chalk2.bold("Knowledge Graph Stats"));
11059
12363
  console.log();
11060
- console.log(chalk.bold(`Entities: ${totalEntities}`));
12364
+ console.log(chalk2.bold(`Entities: ${totalEntities}`));
11061
12365
  for (const r of entityRows) {
11062
12366
  console.log(` ${colorEntityType(r.type)}: ${r.count}`);
11063
12367
  }
11064
12368
  console.log();
11065
- console.log(chalk.bold(`Relations: ${totalRelations}`));
12369
+ console.log(chalk2.bold(`Relations: ${totalRelations}`));
11066
12370
  for (const r of relationRows) {
11067
- console.log(` ${chalk.cyan(r.relation_type)}: ${r.count}`);
12371
+ console.log(` ${chalk2.cyan(r.relation_type)}: ${r.count}`);
11068
12372
  }
11069
12373
  console.log();
11070
- console.log(chalk.bold(`Memory links: ${linkCount.count}`));
12374
+ console.log(chalk2.bold(`Memory links: ${linkCount.count}`));
11071
12375
  } catch (e) {
11072
12376
  handleError(e);
11073
12377
  }
@@ -11077,14 +12381,14 @@ function formatWatchLine(m) {
11077
12381
  const cat = colorCategory(m.category);
11078
12382
  const imp = colorImportance(m.importance);
11079
12383
  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})`)}`;
12384
+ const main = ` [${scope}/${cat}] ${chalk2.bold(m.key)} = ${value} ${chalk2.dim(`(importance: ${imp})`)}`;
11081
12385
  const parts = [];
11082
12386
  if (m.tags.length > 0)
11083
12387
  parts.push(`Tags: ${m.tags.join(", ")}`);
11084
12388
  if (m.agent_id)
11085
12389
  parts.push(`Agent: ${m.agent_id}`);
11086
12390
  parts.push(`Updated: ${m.updated_at}`);
11087
- const detail = chalk.dim(` ${parts.join(" | ")}`);
12391
+ const detail = chalk2.dim(` ${parts.join(" | ")}`);
11088
12392
  return `${main}
11089
12393
  ${detail}`;
11090
12394
  }
@@ -11104,73 +12408,73 @@ profileCmd.command("list").description("List all available profiles").action(()
11104
12408
  const profiles = listProfiles();
11105
12409
  const active = getActiveProfile();
11106
12410
  if (profiles.length === 0) {
11107
- console.log(chalk.dim("No profiles yet. Create one with: mementos profile set <name>"));
12411
+ console.log(chalk2.dim("No profiles yet. Create one with: mementos profile set <name>"));
11108
12412
  return;
11109
12413
  }
11110
- console.log(chalk.bold("Profiles:"));
12414
+ console.log(chalk2.bold("Profiles:"));
11111
12415
  for (const p of profiles) {
11112
- const marker = p === active ? chalk.green(" \u2713 (active)") : "";
12416
+ const marker = p === active ? chalk2.green(" \u2713 (active)") : "";
11113
12417
  console.log(` ${p}${marker}`);
11114
12418
  }
11115
12419
  if (!active) {
11116
- console.log(chalk.dim(`
12420
+ console.log(chalk2.dim(`
11117
12421
  (no active profile \u2014 using default DB)`));
11118
12422
  }
11119
12423
  });
11120
12424
  profileCmd.command("get").description("Show the currently active profile").action(() => {
11121
12425
  const active = getActiveProfile();
11122
12426
  if (active) {
11123
- console.log(chalk.green(`Active profile: ${active}`));
12427
+ console.log(chalk2.green(`Active profile: ${active}`));
11124
12428
  if (!process.env["MEMENTOS_PROFILE"]) {
11125
- console.log(chalk.dim("(persisted in ~/.mementos/config.json)"));
12429
+ console.log(chalk2.dim("(persisted in ~/.mementos/config.json)"));
11126
12430
  } else {
11127
- console.log(chalk.dim("(from MEMENTOS_PROFILE env var)"));
12431
+ console.log(chalk2.dim("(from MEMENTOS_PROFILE env var)"));
11128
12432
  }
11129
12433
  } else {
11130
- console.log(chalk.dim("No active profile \u2014 using default DB (~/.mementos/mementos.db)"));
12434
+ console.log(chalk2.dim("No active profile \u2014 using default DB (~/.mementos/mementos.db)"));
11131
12435
  }
11132
12436
  });
11133
12437
  profileCmd.command("set <name>").description("Switch to a named profile (creates the DB on first use)").action((name) => {
11134
12438
  const clean = name.trim().toLowerCase().replace(/[^a-z0-9_-]/g, "-");
11135
12439
  if (!clean) {
11136
- console.error(chalk.red("Invalid profile name. Use letters, numbers, hyphens, underscores."));
12440
+ console.error(chalk2.red("Invalid profile name. Use letters, numbers, hyphens, underscores."));
11137
12441
  process.exit(1);
11138
12442
  }
11139
12443
  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)`));
12444
+ console.log(chalk2.green(`\u2713 Switched to profile: ${clean}`));
12445
+ console.log(chalk2.dim(` DB: ~/.mementos/profiles/${clean}.db (created on first use)`));
11142
12446
  });
11143
12447
  profileCmd.command("unset").description("Clear the active profile (revert to default DB)").action(() => {
11144
12448
  const was = getActiveProfile();
11145
12449
  setActiveProfile(null);
11146
12450
  if (was) {
11147
- console.log(chalk.green(`\u2713 Cleared profile (was: ${was})`));
12451
+ console.log(chalk2.green(`\u2713 Cleared profile (was: ${was})`));
11148
12452
  } else {
11149
- console.log(chalk.dim("No active profile was set."));
12453
+ console.log(chalk2.dim("No active profile was set."));
11150
12454
  }
11151
- console.log(chalk.dim(" Now using default DB: ~/.mementos/mementos.db"));
12455
+ console.log(chalk2.dim(" Now using default DB: ~/.mementos/mementos.db"));
11152
12456
  });
11153
12457
  profileCmd.command("delete <name>").description("Delete a profile and its DB file (irreversible)").option("-y, --yes", "Skip confirmation prompt").action(async (name, opts) => {
11154
12458
  if (!opts.yes) {
11155
12459
  const profiles = listProfiles();
11156
12460
  if (!profiles.includes(name)) {
11157
- console.error(chalk.red(`Profile not found: ${name}`));
12461
+ console.error(chalk2.red(`Profile not found: ${name}`));
11158
12462
  process.exit(1);
11159
12463
  }
11160
- process.stdout.write(chalk.yellow(`Delete profile "${name}" and its DB? This cannot be undone. [y/N] `));
12464
+ process.stdout.write(chalk2.yellow(`Delete profile "${name}" and its DB? This cannot be undone. [y/N] `));
11161
12465
  const answer = await new Promise((resolve4) => {
11162
12466
  process.stdin.once("data", (d) => resolve4(d.toString().trim().toLowerCase()));
11163
12467
  });
11164
12468
  if (answer !== "y" && answer !== "yes") {
11165
- console.log(chalk.dim("Cancelled."));
12469
+ console.log(chalk2.dim("Cancelled."));
11166
12470
  return;
11167
12471
  }
11168
12472
  }
11169
12473
  const deleted = deleteProfile(name);
11170
12474
  if (deleted) {
11171
- console.log(chalk.green(`\u2713 Profile "${name}" deleted.`));
12475
+ console.log(chalk2.green(`\u2713 Profile "${name}" deleted.`));
11172
12476
  } else {
11173
- console.error(chalk.red(`Profile not found: ${name}`));
12477
+ console.error(chalk2.red(`Profile not found: ${name}`));
11174
12478
  process.exit(1);
11175
12479
  }
11176
12480
  });
@@ -11181,23 +12485,23 @@ autoMemory.command("process <turn>").description("Enqueue text for async LLM mem
11181
12485
  if (opts.sync) {
11182
12486
  const provider = providerRegistry2.getAvailable();
11183
12487
  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."));
12488
+ console.error(chalk2.red("No LLM provider configured. Set ANTHROPIC_API_KEY, OPENAI_API_KEY, CEREBRAS_API_KEY, or XAI_API_KEY."));
11185
12489
  process.exit(1);
11186
12490
  }
11187
- console.log(chalk.dim(`Using ${provider.name} / ${provider.config.model}...`));
12491
+ console.log(chalk2.dim(`Using ${provider.name} / ${provider.config.model}...`));
11188
12492
  const memories = await provider.extractMemories(turn, {
11189
12493
  agentId: opts.agent,
11190
12494
  projectId: opts.project
11191
12495
  });
11192
12496
  if (memories.length === 0) {
11193
- console.log(chalk.dim("Nothing worth remembering extracted."));
12497
+ console.log(chalk2.dim("Nothing worth remembering extracted."));
11194
12498
  } else {
11195
12499
  memories.forEach((m, i) => {
11196
- console.log(chalk.bold(`
12500
+ console.log(chalk2.bold(`
11197
12501
  [${i + 1}] ${m.category} \xB7 importance ${m.importance}/10 \xB7 ${m.suggestedScope}`));
11198
12502
  console.log(` ${m.content}`);
11199
12503
  if (m.tags.length)
11200
- console.log(chalk.dim(` tags: ${m.tags.join(", ")}`));
12504
+ console.log(chalk2.dim(` tags: ${m.tags.join(", ")}`));
11201
12505
  });
11202
12506
  }
11203
12507
  } else {
@@ -11207,8 +12511,8 @@ autoMemory.command("process <turn>").description("Enqueue text for async LLM mem
11207
12511
  sessionId: opts.session
11208
12512
  });
11209
12513
  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`));
12514
+ console.log(chalk2.green("\u2713 Queued for extraction"));
12515
+ console.log(chalk2.dim(`Queue: ${stats.pending} pending \xB7 ${stats.processed} processed \xB7 ${stats.failed} failed`));
11212
12516
  }
11213
12517
  });
11214
12518
  autoMemory.command("status").description("Show auto-memory queue stats and provider health").action(async () => {
@@ -11217,14 +12521,14 @@ autoMemory.command("status").description("Show auto-memory queue stats and provi
11217
12521
  const stats = getAutoMemoryStats2();
11218
12522
  const config = providerRegistry2.getConfig();
11219
12523
  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"}`);
12524
+ console.log(chalk2.bold("Auto-Memory Status"));
12525
+ console.log(` Provider: ${config.enabled ? chalk2.green(config.provider) : chalk2.red("disabled")} / ${config.model ?? "default"}`);
11222
12526
  console.log(` Queue: ${stats.pending} pending \xB7 ${stats.processing} processing \xB7 ${stats.processed} processed`);
11223
12527
  console.log(` Errors: ${stats.failed} failed \xB7 ${stats.dropped} dropped`);
11224
- console.log(chalk.bold(`
12528
+ console.log(chalk2.bold(`
11225
12529
  Provider Health`));
11226
12530
  for (const [name, info] of Object.entries(health)) {
11227
- const icon = info.available ? chalk.green("\u2713") : chalk.red("\u2717");
12531
+ const icon = info.available ? chalk2.green("\u2713") : chalk2.red("\u2717");
11228
12532
  console.log(` ${icon} ${name.padEnd(12)} ${info.model}`);
11229
12533
  }
11230
12534
  });
@@ -11237,35 +12541,35 @@ autoMemory.command("config").description("Show or update auto-memory provider co
11237
12541
  ...opts.model && { model: opts.model },
11238
12542
  ...opts.minImportance && { minImportance: Number(opts.minImportance) }
11239
12543
  });
11240
- console.log(chalk.green("\u2713 Config updated"));
12544
+ console.log(chalk2.green("\u2713 Config updated"));
11241
12545
  }
11242
12546
  const config = providerRegistry2.getConfig();
11243
- console.log(chalk.bold("Auto-Memory Config"));
12547
+ console.log(chalk2.bold("Auto-Memory Config"));
11244
12548
  console.log(JSON.stringify(config, null, 2));
11245
12549
  });
11246
12550
  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
12551
  const { providerRegistry: providerRegistry2 } = await Promise.resolve().then(() => (init_registry(), exports_registry));
11248
12552
  const provider = opts.provider ? providerRegistry2.getProvider(opts.provider) : providerRegistry2.getAvailable();
11249
12553
  if (!provider) {
11250
- console.error(chalk.red("No LLM provider configured."));
12554
+ console.error(chalk2.red("No LLM provider configured."));
11251
12555
  process.exit(1);
11252
12556
  }
11253
- console.log(chalk.dim(`DRY RUN \u2014 ${provider.name} / ${provider.config.model} \u2014 nothing will be saved
12557
+ console.log(chalk2.dim(`DRY RUN \u2014 ${provider.name} / ${provider.config.model} \u2014 nothing will be saved
11254
12558
  `));
11255
12559
  const memories = await provider.extractMemories(turn, {
11256
12560
  agentId: opts.agent,
11257
12561
  projectId: opts.project
11258
12562
  });
11259
12563
  if (memories.length === 0) {
11260
- console.log(chalk.dim("Nothing extracted."));
12564
+ console.log(chalk2.dim("Nothing extracted."));
11261
12565
  } else {
11262
12566
  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)}`);
12567
+ console.log(chalk2.bold(`[${i + 1}] ${m.category.toUpperCase()} \xB7 importance ${m.importance}/10 \xB7 ${m.suggestedScope}`));
12568
+ console.log(` ${chalk2.white(m.content)}`);
11265
12569
  if (m.tags.length)
11266
- console.log(chalk.dim(` tags: ${m.tags.join(", ")}`));
12570
+ console.log(chalk2.dim(` tags: ${m.tags.join(", ")}`));
11267
12571
  if (m.reasoning)
11268
- console.log(chalk.dim(` why: ${m.reasoning}`));
12572
+ console.log(chalk2.dim(` why: ${m.reasoning}`));
11269
12573
  console.log();
11270
12574
  });
11271
12575
  }
@@ -11273,38 +12577,38 @@ autoMemory.command("test <turn>").description("Test extraction without saving (d
11273
12577
  autoMemory.command("enable").description("Enable auto-memory extraction").action(async () => {
11274
12578
  const { configureAutoMemory: configureAutoMemory2 } = await Promise.resolve().then(() => (init_auto_memory(), exports_auto_memory));
11275
12579
  configureAutoMemory2({ enabled: true });
11276
- console.log(chalk.green("\u2713 Auto-memory enabled"));
12580
+ console.log(chalk2.green("\u2713 Auto-memory enabled"));
11277
12581
  });
11278
12582
  autoMemory.command("disable").description("Disable auto-memory extraction").action(async () => {
11279
12583
  const { configureAutoMemory: configureAutoMemory2 } = await Promise.resolve().then(() => (init_auto_memory(), exports_auto_memory));
11280
12584
  configureAutoMemory2({ enabled: false });
11281
- console.log(chalk.yellow("\u26A0 Auto-memory disabled"));
12585
+ console.log(chalk2.yellow("\u26A0 Auto-memory disabled"));
11282
12586
  });
11283
12587
  var hooksCmd = program2.command("hooks").description("Hook registry and webhook management");
11284
12588
  hooksCmd.command("list").description("List registered hooks in the in-memory registry").option("--type <type>", "Filter by hook type").action(async (opts) => {
11285
12589
  const { hookRegistry: hookRegistry2 } = await Promise.resolve().then(() => (init_hooks(), exports_hooks));
11286
12590
  const hooks = hookRegistry2.list(opts.type);
11287
12591
  if (hooks.length === 0) {
11288
- console.log(chalk.gray("No hooks registered."));
12592
+ console.log(chalk2.gray("No hooks registered."));
11289
12593
  return;
11290
12594
  }
11291
12595
  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}`);
12596
+ const builtinTag = h.builtin ? chalk2.blue(" [builtin]") : "";
12597
+ const blockingTag = h.blocking ? chalk2.red(" [blocking]") : chalk2.gray(" [non-blocking]");
12598
+ console.log(`${chalk2.cyan(h.id)} ${chalk2.bold(h.type)}${builtinTag}${blockingTag} priority=${h.priority}`);
11295
12599
  if (h.description)
11296
- console.log(` ${chalk.gray(h.description)}`);
12600
+ console.log(` ${chalk2.gray(h.description)}`);
11297
12601
  }
11298
12602
  });
11299
12603
  hooksCmd.command("stats").description("Show hook registry statistics").action(async () => {
11300
12604
  const { hookRegistry: hookRegistry2 } = await Promise.resolve().then(() => (init_hooks(), exports_hooks));
11301
12605
  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)}`);
12606
+ console.log(chalk2.bold("Hook Registry Stats"));
12607
+ console.log(` Total: ${chalk2.cyan(stats.total)}`);
12608
+ console.log(` Blocking: ${chalk2.red(stats.blocking)}`);
12609
+ console.log(` Non-blocking:${chalk2.green(stats.nonBlocking)}`);
11306
12610
  if (Object.keys(stats.byType).length > 0) {
11307
- console.log(chalk.bold(`
12611
+ console.log(chalk2.bold(`
11308
12612
  By type:`));
11309
12613
  for (const [type, count] of Object.entries(stats.byType)) {
11310
12614
  console.log(` ${type}: ${count}`);
@@ -11319,16 +12623,16 @@ webhooksCmd.command("list").description("List all persisted webhook hooks").opti
11319
12623
  enabled: opts.disabled ? false : undefined
11320
12624
  });
11321
12625
  if (webhooks.length === 0) {
11322
- console.log(chalk.gray("No webhooks registered."));
12626
+ console.log(chalk2.gray("No webhooks registered."));
11323
12627
  return;
11324
12628
  }
11325
12629
  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}`);
12630
+ const enabledTag = wh.enabled ? chalk2.green("enabled") : chalk2.red("disabled");
12631
+ const blockingTag = wh.blocking ? chalk2.red("blocking") : chalk2.gray("non-blocking");
12632
+ console.log(`${chalk2.cyan(wh.id)} [${enabledTag}] ${chalk2.bold(wh.type)} \u2192 ${wh.handlerUrl}`);
11329
12633
  console.log(` ${blockingTag} | priority=${wh.priority} | invocations=${wh.invocationCount} failures=${wh.failureCount}`);
11330
12634
  if (wh.description)
11331
- console.log(` ${chalk.gray(wh.description)}`);
12635
+ console.log(` ${chalk2.gray(wh.description)}`);
11332
12636
  }
11333
12637
  });
11334
12638
  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 +12648,8 @@ webhooksCmd.command("create <type> <url>").description("Create a persistent webh
11344
12648
  description: opts.description
11345
12649
  });
11346
12650
  reloadWebhooks2();
11347
- console.log(chalk.green("\u2713 Webhook created"));
11348
- console.log(` ID: ${chalk.cyan(wh.id)}`);
12651
+ console.log(chalk2.green("\u2713 Webhook created"));
12652
+ console.log(` ID: ${chalk2.cyan(wh.id)}`);
11349
12653
  console.log(` Type: ${wh.type}`);
11350
12654
  console.log(` URL: ${wh.handlerUrl}`);
11351
12655
  });
@@ -11353,9 +12657,9 @@ webhooksCmd.command("delete <id>").description("Delete a webhook by ID").action(
11353
12657
  const { deleteWebhookHook: deleteWebhookHook2 } = await Promise.resolve().then(() => (init_webhook_hooks(), exports_webhook_hooks));
11354
12658
  const deleted = deleteWebhookHook2(id);
11355
12659
  if (deleted) {
11356
- console.log(chalk.green(`\u2713 Webhook ${id} deleted`));
12660
+ console.log(chalk2.green(`\u2713 Webhook ${id} deleted`));
11357
12661
  } else {
11358
- console.error(chalk.red(`Webhook not found: ${id}`));
12662
+ console.error(chalk2.red(`Webhook not found: ${id}`));
11359
12663
  process.exit(1);
11360
12664
  }
11361
12665
  });
@@ -11365,9 +12669,9 @@ webhooksCmd.command("enable <id>").description("Enable a webhook").action(async
11365
12669
  const updated = updateWebhookHook2(id, { enabled: true });
11366
12670
  if (updated) {
11367
12671
  reloadWebhooks2();
11368
- console.log(chalk.green(`\u2713 Webhook ${id} enabled`));
12672
+ console.log(chalk2.green(`\u2713 Webhook ${id} enabled`));
11369
12673
  } else {
11370
- console.error(chalk.red(`Webhook not found: ${id}`));
12674
+ console.error(chalk2.red(`Webhook not found: ${id}`));
11371
12675
  process.exit(1);
11372
12676
  }
11373
12677
  });
@@ -11377,16 +12681,16 @@ webhooksCmd.command("disable <id>").description("Disable a webhook (without dele
11377
12681
  const updated = updateWebhookHook2(id, { enabled: false });
11378
12682
  if (updated) {
11379
12683
  reloadWebhooks2();
11380
- console.log(chalk.yellow(`\u2298 Webhook ${id} disabled`));
12684
+ console.log(chalk2.yellow(`\u2298 Webhook ${id} disabled`));
11381
12685
  } else {
11382
- console.error(chalk.red(`Webhook not found: ${id}`));
12686
+ console.error(chalk2.red(`Webhook not found: ${id}`));
11383
12687
  process.exit(1);
11384
12688
  }
11385
12689
  });
11386
12690
  var synthesisCmd = program2.command("synthesis").alias("synth").description("ALMA memory synthesis \u2014 analyze and consolidate memories");
11387
12691
  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
12692
  const { runSynthesis: runSynthesis2 } = await Promise.resolve().then(() => (init_synthesis2(), exports_synthesis2));
11389
- console.log(chalk.blue("Running memory synthesis..."));
12693
+ console.log(chalk2.blue("Running memory synthesis..."));
11390
12694
  const result = await runSynthesis2({
11391
12695
  projectId: opts.project,
11392
12696
  dryRun: opts.dryRun ?? false,
@@ -11394,44 +12698,44 @@ synthesisCmd.command("run").description("Run memory synthesis on the corpus").op
11394
12698
  provider: opts.provider
11395
12699
  });
11396
12700
  if (result.dryRun) {
11397
- console.log(chalk.yellow(`DRY RUN \u2014 ${result.proposals.length} proposals generated (not applied)`));
12701
+ console.log(chalk2.yellow(`DRY RUN \u2014 ${result.proposals.length} proposals generated (not applied)`));
11398
12702
  } else {
11399
- console.log(chalk.green(`\u2713 Synthesis complete`));
12703
+ console.log(chalk2.green(`\u2713 Synthesis complete`));
11400
12704
  console.log(` Corpus: ${result.run.corpus_size} memories`);
11401
12705
  console.log(` Proposals: ${result.run.proposals_generated} generated, ${result.run.proposals_accepted} applied`);
11402
12706
  }
11403
12707
  if (result.metrics) {
11404
12708
  console.log(` Reduction: ${(result.metrics.corpusReduction * 100).toFixed(1)}%`);
11405
12709
  }
11406
- console.log(` Run ID: ${chalk.cyan(result.run.id)}`);
12710
+ console.log(` Run ID: ${chalk2.cyan(result.run.id)}`);
11407
12711
  });
11408
12712
  synthesisCmd.command("status").description("Show recent synthesis runs").option("--project <id>", "Filter by project").action(async (opts) => {
11409
12713
  const { listSynthesisRuns: listSynthesisRuns2 } = await Promise.resolve().then(() => (init_synthesis(), exports_synthesis));
11410
12714
  const runs = listSynthesisRuns2({ project_id: opts.project, limit: 10 });
11411
12715
  if (runs.length === 0) {
11412
- console.log(chalk.gray("No synthesis runs found."));
12716
+ console.log(chalk2.gray("No synthesis runs found."));
11413
12717
  return;
11414
12718
  }
11415
12719
  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)}`);
12720
+ const statusColor = run.status === "completed" ? chalk2.green : run.status === "failed" ? chalk2.red : chalk2.yellow;
12721
+ 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
12722
  }
11419
12723
  });
11420
12724
  synthesisCmd.command("rollback <runId>").description("Roll back a synthesis run").action(async (runId) => {
11421
12725
  const { rollbackSynthesis: rollbackSynthesis2 } = await Promise.resolve().then(() => (init_synthesis2(), exports_synthesis2));
11422
- console.log(chalk.yellow(`Rolling back synthesis run ${runId}...`));
12726
+ console.log(chalk2.yellow(`Rolling back synthesis run ${runId}...`));
11423
12727
  const result = await rollbackSynthesis2(runId);
11424
- console.log(chalk.green(`\u2713 Rolled back ${result.rolled_back} proposals`));
12728
+ console.log(chalk2.green(`\u2713 Rolled back ${result.rolled_back} proposals`));
11425
12729
  if (result.errors.length > 0) {
11426
- console.log(chalk.red(` Errors: ${result.errors.join(", ")}`));
12730
+ console.log(chalk2.red(` Errors: ${result.errors.join(", ")}`));
11427
12731
  }
11428
12732
  });
11429
12733
  var sessionCmd = program2.command("session").description("Session auto-memory \u2014 ingest session transcripts for memory extraction");
11430
12734
  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");
12735
+ const { readFileSync: readFileSync4 } = await import("fs");
11432
12736
  const { createSessionJob: createSessionJob2 } = await Promise.resolve().then(() => (init_session_jobs(), exports_session_jobs));
11433
12737
  const { enqueueSessionJob: enqueueSessionJob2 } = await Promise.resolve().then(() => (init_session_queue(), exports_session_queue));
11434
- const transcript = readFileSync3(transcriptFile, "utf-8");
12738
+ const transcript = readFileSync4(transcriptFile, "utf-8");
11435
12739
  const sessionId = opts.sessionId ?? `cli-${Date.now()}`;
11436
12740
  const job = createSessionJob2({
11437
12741
  session_id: sessionId,
@@ -11441,7 +12745,7 @@ sessionCmd.command("ingest <transcriptFile>").description("Ingest a session tran
11441
12745
  project_id: opts.project
11442
12746
  });
11443
12747
  enqueueSessionJob2(job.id);
11444
- console.log(chalk.green(`\u2713 Session queued: ${chalk.cyan(job.id)}`));
12748
+ console.log(chalk2.green(`\u2713 Session queued: ${chalk2.cyan(job.id)}`));
11445
12749
  console.log(` Session: ${sessionId}`);
11446
12750
  console.log(` Length: ${transcript.length} chars`);
11447
12751
  });
@@ -11449,16 +12753,16 @@ sessionCmd.command("status <jobId>").description("Check status of a session extr
11449
12753
  const { getSessionJob: getSessionJob2 } = await Promise.resolve().then(() => (init_session_jobs(), exports_session_jobs));
11450
12754
  const job = getSessionJob2(jobId);
11451
12755
  if (!job) {
11452
- console.error(chalk.red(`Job not found: ${jobId}`));
12756
+ console.error(chalk2.red(`Job not found: ${jobId}`));
11453
12757
  process.exit(1);
11454
12758
  }
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)}]`);
12759
+ const statusColor = job.status === "completed" ? chalk2.green : job.status === "failed" ? chalk2.red : chalk2.yellow;
12760
+ console.log(`${chalk2.cyan(job.id)} [${statusColor(job.status)}]`);
11457
12761
  console.log(` Session: ${job.session_id}`);
11458
12762
  console.log(` Chunks: ${job.chunk_count}`);
11459
12763
  console.log(` Extracted: ${job.memories_extracted} memories`);
11460
12764
  if (job.error)
11461
- console.log(chalk.red(` Error: ${job.error}`));
12765
+ console.log(chalk2.red(` Error: ${job.error}`));
11462
12766
  });
11463
12767
  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
12768
  const { listSessionJobs: listSessionJobs2 } = await Promise.resolve().then(() => (init_session_jobs(), exports_session_jobs));
@@ -11469,12 +12773,12 @@ sessionCmd.command("list").description("List session extraction jobs").option("-
11469
12773
  limit: parseInt(opts.limit)
11470
12774
  });
11471
12775
  if (jobs.length === 0) {
11472
- console.log(chalk.gray("No session jobs found."));
12776
+ console.log(chalk2.gray("No session jobs found."));
11473
12777
  return;
11474
12778
  }
11475
12779
  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)}`);
12780
+ const statusColor = job.status === "completed" ? chalk2.green : job.status === "failed" ? chalk2.red : chalk2.yellow;
12781
+ console.log(`${chalk2.cyan(job.id.slice(0, 8))} [${statusColor(job.status)}] ${job.memories_extracted} memories | ${job.created_at.slice(0, 10)}`);
11478
12782
  }
11479
12783
  });
11480
12784
  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 +12787,26 @@ sessionCmd.command("setup-hook").description("Install mementos session hook into
11483
12787
  if (opts.claude) {
11484
12788
  const script = `${hookPath}/claude-stop-hook.ts`;
11485
12789
  if (opts.show) {
11486
- const { readFileSync: readFileSync3 } = await import("fs");
11487
- console.log(readFileSync3(script, "utf-8"));
12790
+ const { readFileSync: readFileSync4 } = await import("fs");
12791
+ console.log(readFileSync4(script, "utf-8"));
11488
12792
  return;
11489
12793
  }
11490
- console.log(chalk.bold("Claude Code stop hook installation:"));
12794
+ console.log(chalk2.bold("Claude Code stop hook installation:"));
11491
12795
  console.log("");
11492
12796
  console.log("Add to your .claude/settings.json:");
11493
- console.log(chalk.cyan(JSON.stringify({
12797
+ console.log(chalk2.cyan(JSON.stringify({
11494
12798
  hooks: {
11495
12799
  Stop: [{ matcher: "", hooks: [{ type: "command", command: `bun ${script}` }] }]
11496
12800
  }
11497
12801
  }, null, 2)));
11498
12802
  console.log("");
11499
- console.log(`Or run: ${chalk.cyan(`claude hooks add Stop "bun ${script}"`)}`);
12803
+ console.log(`Or run: ${chalk2.cyan(`claude hooks add Stop "bun ${script}"`)}`);
11500
12804
  } else if (opts.codex) {
11501
12805
  const script = `${hookPath}/codex-stop-hook.ts`;
11502
- console.log(chalk.bold("Codex session hook installation:"));
12806
+ console.log(chalk2.bold("Codex session hook installation:"));
11503
12807
  console.log("");
11504
12808
  console.log("Add to ~/.codex/config.toml:");
11505
- console.log(chalk.cyan(`[hooks]
12809
+ console.log(chalk2.cyan(`[hooks]
11506
12810
  session_end = "bun ${script}"`));
11507
12811
  } else {
11508
12812
  console.log("Usage: mementos session setup-hook --claude | --codex");
@@ -11526,7 +12830,7 @@ program2.command("heartbeat [agent-id]").description("Update last_seen_at to sig
11526
12830
  if (globalOpts.json)
11527
12831
  console.log(JSON.stringify({ agent_id: agent.id, name: agent.name, last_seen_at: new Date().toISOString() }));
11528
12832
  else
11529
- console.log(chalk.green(`\u2665 ${agent.name} (${agent.id}) \u2014 heartbeat sent`));
12833
+ console.log(chalk2.green(`\u2665 ${agent.name} (${agent.id}) \u2014 heartbeat sent`));
11530
12834
  });
11531
12835
  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
12836
  const globalOpts = program2.opts();
@@ -11538,9 +12842,9 @@ program2.command("set-focus [project]").description("Focus this agent on a proje
11538
12842
  }
11539
12843
  setFocus(agentId, project ?? null);
11540
12844
  if (project)
11541
- console.log(chalk.green(`Focused: ${agentId} \u2192 project ${project}`));
12845
+ console.log(chalk2.green(`Focused: ${agentId} \u2192 project ${project}`));
11542
12846
  else
11543
- console.log(chalk.dim(`Focus cleared for ${agentId}`));
12847
+ console.log(chalk2.dim(`Focus cleared for ${agentId}`));
11544
12848
  });
11545
12849
  program2.command("get-focus").description("Show the current project focus for an agent").option("--agent <id>", "Agent ID").action((opts) => {
11546
12850
  const globalOpts = program2.opts();
@@ -11552,9 +12856,9 @@ program2.command("get-focus").description("Show the current project focus for an
11552
12856
  }
11553
12857
  const focus = getFocus(agentId);
11554
12858
  if (focus)
11555
- console.log(chalk.cyan(`Focus: ${focus}`));
12859
+ console.log(chalk2.cyan(`Focus: ${focus}`));
11556
12860
  else
11557
- console.log(chalk.dim("No focus set."));
12861
+ console.log(chalk2.dim("No focus set."));
11558
12862
  });
11559
12863
  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
12864
  const globalOpts = program2.opts();
@@ -11570,15 +12874,271 @@ program2.command("remove <nameOrId>").description("Remove/delete a memory by nam
11570
12874
  id = mem.id;
11571
12875
  }
11572
12876
  if (!id) {
11573
- console.error(chalk.red(`Memory not found: ${nameOrId}`));
12877
+ console.error(chalk2.red(`Memory not found: ${nameOrId}`));
11574
12878
  process.exit(1);
11575
12879
  }
11576
12880
  const deleted = deleteMemory2(id);
11577
12881
  if (deleted)
11578
- console.log(chalk.green(`\u2713 Memory ${id.slice(0, 8)} removed`));
12882
+ console.log(chalk2.green(`\u2713 Memory ${id.slice(0, 8)} removed`));
11579
12883
  else {
11580
- console.error(chalk.red(`Memory not found: ${nameOrId}`));
12884
+ console.error(chalk2.red(`Memory not found: ${nameOrId}`));
11581
12885
  process.exit(1);
11582
12886
  }
11583
12887
  });
12888
+ 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) => {
12889
+ try {
12890
+ const globalOpts = program2.opts();
12891
+ const { getToolEvents: getToolEvents2 } = (init_tool_events(), __toCommonJS(exports_tool_events));
12892
+ const limit = opts.limit || 20;
12893
+ const events = getToolEvents2({
12894
+ tool_name: toolName,
12895
+ project_id: opts.projectId,
12896
+ limit
12897
+ });
12898
+ if (globalOpts.json) {
12899
+ outputJson(events);
12900
+ return;
12901
+ }
12902
+ if (events.length === 0) {
12903
+ console.log(chalk2.yellow("No tool events found."));
12904
+ return;
12905
+ }
12906
+ console.log(chalk2.bold(`${events.length} tool event${events.length === 1 ? "" : "s"}:`));
12907
+ 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")}`);
12908
+ for (const e of events) {
12909
+ const successStr = e.success ? chalk2.green("true ") : chalk2.red("false ");
12910
+ const errorType = (e.error_type || "").padEnd(20);
12911
+ const action = (e.action || "-").padEnd(16);
12912
+ console.log(` ${e.tool_name.padEnd(24)} ${action} ${successStr} ${errorType} ${chalk2.dim(e.created_at)}`);
12913
+ }
12914
+ } catch (e) {
12915
+ handleError(e);
12916
+ }
12917
+ });
12918
+ 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) => {
12919
+ try {
12920
+ const globalOpts = program2.opts();
12921
+ const { getToolStats: getToolStats2, getToolLessons: getToolLessons2 } = (init_tool_events(), __toCommonJS(exports_tool_events));
12922
+ const projectId = opts.projectId;
12923
+ const stats = getToolStats2(toolName, projectId);
12924
+ const lessons = getToolLessons2(toolName, projectId);
12925
+ if (globalOpts.json) {
12926
+ outputJson({ stats, lessons });
12927
+ return;
12928
+ }
12929
+ const successRate = (stats.success_rate * 100).toFixed(1);
12930
+ console.log(chalk2.bold(`Tool: ${toolName}`));
12931
+ 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)}` : ""));
12932
+ if (stats.common_errors.length > 0) {
12933
+ console.log(chalk2.bold(`
12934
+ Common errors:`));
12935
+ for (const err of stats.common_errors) {
12936
+ console.log(` ${chalk2.red(err.error_type)}: ${err.count} times`);
12937
+ }
12938
+ }
12939
+ if (lessons.length === 0) {
12940
+ console.log(chalk2.dim(`
12941
+ No lessons recorded.`));
12942
+ return;
12943
+ }
12944
+ console.log(chalk2.bold(`
12945
+ Lessons (${lessons.length}):`));
12946
+ for (const l of lessons) {
12947
+ console.log(` ${chalk2.cyan("-")} ${l.lesson} ${chalk2.dim(`(${l.created_at.slice(0, 10)})`)}`);
12948
+ if (l.when_to_use) {
12949
+ console.log(` ${chalk2.dim("when_to_use:")} ${l.when_to_use}`);
12950
+ }
12951
+ }
12952
+ } catch (e) {
12953
+ handleError(e);
12954
+ }
12955
+ });
12956
+ 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) => {
12957
+ try {
12958
+ const globalOpts = program2.opts();
12959
+ const { synthesizeProfile: synthesizeProfile2 } = await Promise.resolve().then(() => (init_profile_synthesizer(), exports_profile_synthesizer));
12960
+ let projectId = opts.projectId;
12961
+ if (!projectId && globalOpts.project) {
12962
+ const project = getProject(resolve3(globalOpts.project));
12963
+ if (project)
12964
+ projectId = project.id;
12965
+ }
12966
+ const result = await synthesizeProfile2({
12967
+ project_id: projectId,
12968
+ agent_id: globalOpts.agent,
12969
+ force_refresh: !!opts.refresh
12970
+ });
12971
+ if (!result) {
12972
+ if (globalOpts.json) {
12973
+ outputJson({ error: "No profile available (no preference/fact memories found)" });
12974
+ } else {
12975
+ console.log(chalk2.yellow("No profile available \u2014 save some preference or fact memories first."));
12976
+ }
12977
+ return;
12978
+ }
12979
+ if (globalOpts.json) {
12980
+ outputJson(result);
12981
+ return;
12982
+ }
12983
+ if (result.from_cache) {
12984
+ console.log(chalk2.dim(`(cached profile)
12985
+ `));
12986
+ } else {
12987
+ console.log(chalk2.dim(`(synthesized from ${result.memory_count} memories)
12988
+ `));
12989
+ }
12990
+ console.log(result.profile);
12991
+ } catch (e) {
12992
+ handleError(e);
12993
+ }
12994
+ });
12995
+ program2.command("chain <sequence_group>").description("Show a memory chain (memories linked by sequence_group, ordered by sequence_order)").action((sequenceGroup) => {
12996
+ try {
12997
+ const globalOpts = program2.opts();
12998
+ const db = getDatabase();
12999
+ const rows = db.query("SELECT * FROM memories WHERE sequence_group = ? AND status = 'active' ORDER BY sequence_order ASC").all(sequenceGroup);
13000
+ const memories = rows.map(parseMemoryRow);
13001
+ if (globalOpts.json) {
13002
+ outputJson(memories);
13003
+ return;
13004
+ }
13005
+ if (memories.length === 0) {
13006
+ console.log(chalk2.yellow(`No chain found for sequence group: ${sequenceGroup}`));
13007
+ return;
13008
+ }
13009
+ console.log(chalk2.bold(`Chain: ${sequenceGroup} (${memories.length} step${memories.length === 1 ? "" : "s"}):
13010
+ `));
13011
+ for (let i = 0;i < memories.length; i++) {
13012
+ const m = memories[i];
13013
+ const order = m.sequence_order !== null && m.sequence_order !== undefined ? m.sequence_order : i + 1;
13014
+ const value = m.value.length > 120 ? m.value.slice(0, 120) + "..." : m.value;
13015
+ console.log(` ${chalk2.cyan(String(order) + ".")} ${chalk2.bold(m.key)}: ${value}`);
13016
+ }
13017
+ } catch (e) {
13018
+ handleError(e);
13019
+ }
13020
+ });
13021
+ program2.command("when-to-use <memory_id>").description("Show the when_to_use guidance for a memory").action((memoryId) => {
13022
+ try {
13023
+ const globalOpts = program2.opts();
13024
+ const resolvedId = resolveMemoryId(memoryId);
13025
+ const memory = getMemory(resolvedId);
13026
+ if (!memory) {
13027
+ if (globalOpts.json) {
13028
+ outputJson({ error: `Memory not found: ${memoryId}` });
13029
+ } else {
13030
+ console.error(chalk2.red(`Memory not found: ${memoryId}`));
13031
+ }
13032
+ process.exit(1);
13033
+ }
13034
+ const whenToUse = memory.when_to_use ?? null;
13035
+ if (globalOpts.json) {
13036
+ outputJson({ id: memory.id, key: memory.key, when_to_use: whenToUse });
13037
+ return;
13038
+ }
13039
+ console.log(chalk2.bold(`${memory.key} (${memory.id.slice(0, 8)})`));
13040
+ if (whenToUse) {
13041
+ console.log(` ${chalk2.cyan("when_to_use:")} ${whenToUse}`);
13042
+ } else {
13043
+ console.log(chalk2.dim(" (not set)"));
13044
+ }
13045
+ } catch (e) {
13046
+ handleError(e);
13047
+ }
13048
+ });
13049
+ var sessionsCmd = program2.command("sessions").description("Session registry \u2014 list, clean, and inspect active Claude Code sessions");
13050
+ 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) => {
13051
+ try {
13052
+ const globalOpts = program2.opts();
13053
+ const { listSessions: listSessions2 } = (init_session_registry(), __toCommonJS(exports_session_registry));
13054
+ const sessions = listSessions2({
13055
+ project_name: opts.project,
13056
+ agent_name: opts.agent || globalOpts.agent
13057
+ });
13058
+ const fmt = getOutputFormat(opts.format);
13059
+ if (fmt === "json") {
13060
+ outputJson(sessions);
13061
+ return;
13062
+ }
13063
+ if (fmt === "yaml") {
13064
+ outputYaml(sessions);
13065
+ return;
13066
+ }
13067
+ if (sessions.length === 0) {
13068
+ console.log(chalk2.yellow("No active sessions found."));
13069
+ return;
13070
+ }
13071
+ console.log(chalk2.bold(`${sessions.length} active session${sessions.length === 1 ? "" : "s"}:
13072
+ `));
13073
+ for (const s of sessions) {
13074
+ const pid = chalk2.dim(`pid:${s.pid}`);
13075
+ const agent = s.agent_name ? chalk2.cyan(s.agent_name) : chalk2.dim("(no agent)");
13076
+ const project = s.project_name ? chalk2.yellow(s.project_name) : chalk2.dim("(no project)");
13077
+ const mcp = chalk2.dim(s.mcp_server);
13078
+ const self = s.pid === process.pid ? chalk2.green(" (self)") : "";
13079
+ console.log(` ${chalk2.bold(s.id)} ${pid}${self} ${agent} ${project} ${mcp}`);
13080
+ console.log(` ${chalk2.dim(`cwd: ${s.cwd}`)} ${chalk2.dim(`last seen: ${s.last_seen_at}`)}`);
13081
+ }
13082
+ } catch (e) {
13083
+ handleError(e);
13084
+ }
13085
+ });
13086
+ 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) => {
13087
+ try {
13088
+ const globalOpts = program2.opts();
13089
+ const { listSessions: listSessions2 } = (init_session_registry(), __toCommonJS(exports_session_registry));
13090
+ if (!opts.agent && !opts.project && !opts.all) {
13091
+ console.error(chalk2.red("Specify a target: --agent <name>, --project <name>, or --all"));
13092
+ process.exit(1);
13093
+ }
13094
+ const filter = {};
13095
+ if (opts.agent)
13096
+ filter.agent_name = opts.agent;
13097
+ if (opts.project)
13098
+ filter.project_name = opts.project;
13099
+ const sessions = listSessions2(opts.all ? undefined : filter);
13100
+ if (globalOpts.json) {
13101
+ outputJson({
13102
+ message: "Channel push requires MCP server context. Use the memory_send_channel MCP tool.",
13103
+ matching_sessions: sessions.length,
13104
+ sessions: sessions.map((s) => ({
13105
+ id: s.id,
13106
+ pid: s.pid,
13107
+ agent_name: s.agent_name,
13108
+ project_name: s.project_name
13109
+ }))
13110
+ });
13111
+ return;
13112
+ }
13113
+ console.log(chalk2.bold(`Found ${sessions.length} matching session${sessions.length === 1 ? "" : "s"}:`));
13114
+ for (const s of sessions) {
13115
+ const agent = s.agent_name ? chalk2.cyan(s.agent_name) : chalk2.dim("(no agent)");
13116
+ const project = s.project_name ? chalk2.yellow(s.project_name) : "";
13117
+ console.log(` ${s.id} pid:${s.pid} ${agent} ${project}`);
13118
+ }
13119
+ console.log();
13120
+ console.log(chalk2.dim("Channel push requires the MCP server context."));
13121
+ console.log(chalk2.dim("Use the MCP tool:"));
13122
+ console.log(chalk2.cyan(` memory_send_channel(content="${message.slice(0, 60)}${message.length > 60 ? "..." : ""}")`));
13123
+ } catch (e) {
13124
+ handleError(e);
13125
+ }
13126
+ });
13127
+ sessionsCmd.command("clean").description("Remove dead/stale sessions from the registry").action(() => {
13128
+ try {
13129
+ const globalOpts = program2.opts();
13130
+ const { cleanStaleSessions: cleanStaleSessions2 } = (init_session_registry(), __toCommonJS(exports_session_registry));
13131
+ const cleaned = cleanStaleSessions2();
13132
+ if (globalOpts.json) {
13133
+ outputJson({ cleaned });
13134
+ } else if (cleaned === 0) {
13135
+ console.log(chalk2.green("No stale sessions found \u2014 registry is clean."));
13136
+ } else {
13137
+ console.log(chalk2.green(`Cleaned ${cleaned} stale session${cleaned === 1 ? "" : "s"}.`));
13138
+ }
13139
+ } catch (e) {
13140
+ handleError(e);
13141
+ }
13142
+ });
13143
+ program2.addCommand(makeBrainsCommand());
11584
13144
  program2.parse(process.argv);