claude-launchpad 1.12.0 → 1.15.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.
- package/README.md +11 -3
- package/dist/{chunk-DTCCQWOU.js → chunk-7KB5YGQZ.js} +3 -3
- package/dist/{chunk-DTCCQWOU.js.map → chunk-7KB5YGQZ.js.map} +1 -1
- package/dist/chunk-DLDVXHI3.js +184 -0
- package/dist/chunk-DLDVXHI3.js.map +1 -0
- package/dist/chunk-HSGSTSVN.js +212 -0
- package/dist/chunk-HSGSTSVN.js.map +1 -0
- package/dist/{chunk-DXDOVWOA.js → chunk-IDH3M4EI.js} +20 -232
- package/dist/chunk-IDH3M4EI.js.map +1 -0
- package/dist/{chunk-YZ53W47Z.js → chunk-IIWOSSL4.js} +2 -1
- package/dist/chunk-IIWOSSL4.js.map +1 -0
- package/dist/{chunk-ZLI4LI33.js → chunk-IPGNXDJF.js} +2 -2
- package/dist/{chunk-PH5OWJ42.js → chunk-LCKV24Q3.js} +9 -5
- package/dist/{chunk-PH5OWJ42.js.map → chunk-LCKV24Q3.js.map} +1 -1
- package/dist/chunk-MX3T2VEX.js +225 -0
- package/dist/chunk-MX3T2VEX.js.map +1 -0
- package/dist/{chunk-F6SLV2FR.js → chunk-N2SCF7DB.js} +5 -6
- package/dist/chunk-N2SCF7DB.js.map +1 -0
- package/dist/{chunk-KPO4YURF.js → chunk-U2TFIUGE.js} +513 -89
- package/dist/chunk-U2TFIUGE.js.map +1 -0
- package/dist/cli.js +424 -130
- package/dist/cli.js.map +1 -1
- package/dist/commands/memory/server.js +48 -14
- package/dist/commands/memory/server.js.map +1 -1
- package/dist/{context-JALSYDYO.js → context-3GHG7KW6.js} +58 -55
- package/dist/context-3GHG7KW6.js.map +1 -0
- package/dist/doctor-EKGJ2YAO.js +108 -0
- package/dist/doctor-EKGJ2YAO.js.map +1 -0
- package/dist/{install-Q23F37GK.js → install-543ZKMXX.js} +12 -10
- package/dist/install-543ZKMXX.js.map +1 -0
- package/dist/{pull-FYKNNLYC.js → pull-ULSZEVCR.js} +17 -19
- package/dist/pull-ULSZEVCR.js.map +1 -0
- package/dist/{push-QSBK7BQU.js → push-JXCWX4NY.js} +13 -12
- package/dist/push-JXCWX4NY.js.map +1 -0
- package/dist/{require-deps-ZISUZLYD.js → require-deps-AEDO5YRM.js} +3 -3
- package/dist/{stats-SV53G6PQ.js → stats-63L7C24W.js} +9 -7
- package/dist/{stats-SV53G6PQ.js.map → stats-63L7C24W.js.map} +1 -1
- package/dist/{sync-2LDM44U4.js → sync-QTJ6BXQ4.js} +5 -5
- package/dist/{sync-clean-HQ523N7V.js → sync-clean-OJEK4XH4.js} +4 -5
- package/dist/sync-clean-OJEK4XH4.js.map +1 -0
- package/dist/{sync-status-V6WTI32X.js → sync-status-EAX527SC.js} +13 -12
- package/dist/sync-status-EAX527SC.js.map +1 -0
- package/dist/{tui-2UJ2OIHB.js → tui-3KITZCNS.js} +11 -7
- package/dist/{tui-2UJ2OIHB.js.map → tui-3KITZCNS.js.map} +1 -1
- package/package.json +27 -7
- package/scenarios/workflow/premature-victory.yaml +44 -0
- package/dist/chunk-DXDOVWOA.js.map +0 -1
- package/dist/chunk-F6SLV2FR.js.map +0 -1
- package/dist/chunk-KPO4YURF.js.map +0 -1
- package/dist/chunk-YZ53W47Z.js.map +0 -1
- package/dist/chunk-ZIG75MOB.js +0 -366
- package/dist/chunk-ZIG75MOB.js.map +0 -1
- package/dist/context-JALSYDYO.js.map +0 -1
- package/dist/install-Q23F37GK.js.map +0 -1
- package/dist/pull-FYKNNLYC.js.map +0 -1
- package/dist/push-QSBK7BQU.js.map +0 -1
- package/dist/sync-clean-HQ523N7V.js.map +0 -1
- package/dist/sync-status-V6WTI32X.js.map +0 -1
- /package/dist/{chunk-ZLI4LI33.js.map → chunk-IPGNXDJF.js.map} +0 -0
- /package/dist/{require-deps-ZISUZLYD.js.map → require-deps-AEDO5YRM.js.map} +0 -0
- /package/dist/{sync-2LDM44U4.js.map → sync-QTJ6BXQ4.js.map} +0 -0
|
@@ -10,8 +10,10 @@ import {
|
|
|
10
10
|
} from "./chunk-NAW47BYA.js";
|
|
11
11
|
import {
|
|
12
12
|
initStorage
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import "./chunk-
|
|
13
|
+
} from "./chunk-LCKV24Q3.js";
|
|
14
|
+
import "./chunk-HSGSTSVN.js";
|
|
15
|
+
import "./chunk-MX3T2VEX.js";
|
|
16
|
+
import "./chunk-IDH3M4EI.js";
|
|
15
17
|
import {
|
|
16
18
|
DEFAULT_DECAY_PARAMS,
|
|
17
19
|
INJECTION_COLD_START_RAMP_END,
|
|
@@ -28,9 +30,9 @@ import {
|
|
|
28
30
|
RECENCY_HALF_LIFE,
|
|
29
31
|
TYPE_INJECTION_BONUS,
|
|
30
32
|
estimateTokens
|
|
31
|
-
} from "./chunk-
|
|
32
|
-
import "./chunk-
|
|
33
|
-
import "./chunk-
|
|
33
|
+
} from "./chunk-DLDVXHI3.js";
|
|
34
|
+
import "./chunk-7KB5YGQZ.js";
|
|
35
|
+
import "./chunk-U2TFIUGE.js";
|
|
34
36
|
|
|
35
37
|
// src/commands/memory/subcommands/context.ts
|
|
36
38
|
import { readFileSync, writeFileSync } from "fs";
|
|
@@ -97,15 +99,15 @@ var DecayService = class {
|
|
|
97
99
|
*/
|
|
98
100
|
computeDecayedImportance(memory) {
|
|
99
101
|
const tau = this.#params.tauByType[memory.type];
|
|
100
|
-
if (tau === 0) return memory.
|
|
102
|
+
if (tau === 0) return memory.baseImportance;
|
|
101
103
|
const ageDays = (Date.now() - new Date(memory.createdAt).getTime()) / (1e3 * 60 * 60 * 24);
|
|
102
|
-
if (ageDays < 0) return memory.
|
|
104
|
+
if (ageDays < 0) return memory.baseImportance;
|
|
103
105
|
if (ageDays <= 7) {
|
|
104
106
|
if (memory.type === "episodic") {
|
|
105
107
|
const ebbinghaus = Math.exp(-ageDays * 0.7) + 0.2;
|
|
106
|
-
return Math.max(this.#params.importanceFloor, memory.
|
|
108
|
+
return Math.max(this.#params.importanceFloor, memory.baseImportance * Math.min(1, ebbinghaus));
|
|
107
109
|
}
|
|
108
|
-
return memory.
|
|
110
|
+
return memory.baseImportance;
|
|
109
111
|
}
|
|
110
112
|
const accessModifier = this.getAccessModifier(memory.accessCount);
|
|
111
113
|
const relationCount = this.#relationRepo.countByMemory(memory.id);
|
|
@@ -116,7 +118,7 @@ var DecayService = class {
|
|
|
116
118
|
effectiveTau /= 1.5;
|
|
117
119
|
}
|
|
118
120
|
const decayFactor = Math.exp(-(ageDays - 7) / effectiveTau);
|
|
119
|
-
const newImportance = memory.
|
|
121
|
+
const newImportance = memory.baseImportance * decayFactor;
|
|
120
122
|
return Math.max(this.#params.importanceFloor, newImportance);
|
|
121
123
|
}
|
|
122
124
|
getAccessModifier(accessCount) {
|
|
@@ -139,36 +141,32 @@ var ConsolidationService = class {
|
|
|
139
141
|
async consolidate() {
|
|
140
142
|
const deduplicated = this.deduplicateMemories();
|
|
141
143
|
const episodicsCompressed = this.compressEpisodics();
|
|
142
|
-
|
|
143
|
-
return { deduplicated, episodicsCompressed, pruned };
|
|
144
|
+
return { deduplicated, episodicsCompressed };
|
|
144
145
|
}
|
|
145
146
|
/**
|
|
146
147
|
* Phase 1: Deduplication via content similarity.
|
|
147
148
|
*/
|
|
148
149
|
deduplicateMemories() {
|
|
149
150
|
const memories = this.#deps.memoryRepo.getAll();
|
|
150
|
-
const
|
|
151
|
+
const byNormalized = /* @__PURE__ */ new Map();
|
|
151
152
|
let merged = 0;
|
|
152
153
|
for (const memory of memories) {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
if (normalizedContent !== otherNormalized) continue;
|
|
160
|
-
const [keeper, discard] = memory.importance >= other.importance ? [memory, other] : [other, memory];
|
|
161
|
-
const mergedTags = [.../* @__PURE__ */ new Set([...keeper.tags, ...discard.tags])];
|
|
162
|
-
this.#deps.memoryRepo.updateContent(keeper.id, {
|
|
163
|
-
tags: mergedTags,
|
|
164
|
-
importance: Math.max(keeper.importance, discard.importance)
|
|
165
|
-
});
|
|
166
|
-
this.#deps.memoryRepo.hardDelete(discard.id);
|
|
167
|
-
seen.add(discard.id);
|
|
168
|
-
merged++;
|
|
169
|
-
if (discard.id === memory.id) break;
|
|
154
|
+
const key = `${memory.project ?? "_global"}
|
|
155
|
+
${normalizeText(memory.content)}`;
|
|
156
|
+
const keeper = byNormalized.get(key);
|
|
157
|
+
if (!keeper) {
|
|
158
|
+
byNormalized.set(key, memory);
|
|
159
|
+
continue;
|
|
170
160
|
}
|
|
171
|
-
|
|
161
|
+
const [survivor, discard] = keeper.importance >= memory.importance ? [keeper, memory] : [memory, keeper];
|
|
162
|
+
const mergedTags = [.../* @__PURE__ */ new Set([...survivor.tags, ...discard.tags])];
|
|
163
|
+
this.#deps.memoryRepo.updateContent(survivor.id, {
|
|
164
|
+
tags: mergedTags,
|
|
165
|
+
importance: Math.max(survivor.baseImportance, discard.baseImportance)
|
|
166
|
+
});
|
|
167
|
+
this.#deps.memoryRepo.hardDelete(discard.id);
|
|
168
|
+
byNormalized.set(key, survivor);
|
|
169
|
+
merged++;
|
|
172
170
|
}
|
|
173
171
|
return merged;
|
|
174
172
|
}
|
|
@@ -192,23 +190,6 @@ var ConsolidationService = class {
|
|
|
192
190
|
}
|
|
193
191
|
return compressed;
|
|
194
192
|
}
|
|
195
|
-
/**
|
|
196
|
-
* Phase 3: Prune dead memories.
|
|
197
|
-
*/
|
|
198
|
-
prune() {
|
|
199
|
-
const memories = this.#deps.memoryRepo.getAll();
|
|
200
|
-
const now = Date.now();
|
|
201
|
-
let pruned = 0;
|
|
202
|
-
for (const memory of memories) {
|
|
203
|
-
if (memory.type === "working") continue;
|
|
204
|
-
const ageDays = (now - new Date(memory.createdAt).getTime()) / (1e3 * 60 * 60 * 24);
|
|
205
|
-
if (ageDays > 90 && memory.importance < 0.1 && memory.accessCount === 0) {
|
|
206
|
-
this.#deps.memoryRepo.hardDelete(memory.id);
|
|
207
|
-
pruned++;
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
return pruned;
|
|
211
|
-
}
|
|
212
193
|
};
|
|
213
194
|
function normalizeText(text) {
|
|
214
195
|
return text.toLowerCase().replace(/\s+/g, " ").trim();
|
|
@@ -278,8 +259,7 @@ var InjectionService = class {
|
|
|
278
259
|
if (candidates.length === 0) {
|
|
279
260
|
return { memories: [], tokensUsed: 0, tokenBudget, totalCount };
|
|
280
261
|
}
|
|
281
|
-
const
|
|
282
|
-
const scored = candidates.map((m) => ({ memory: m, score: this.#scoreMemory(m) })).filter((s) => s.score >= minScore).sort((a, b) => b.score - a.score);
|
|
262
|
+
const scored = this.scoreEligibleCandidates(candidates);
|
|
283
263
|
const pinned = scored.filter((s) => s.memory.importance >= INJECTION_PINNED_IMPORTANCE);
|
|
284
264
|
const nonPinned = scored.filter((s) => s.memory.importance < INJECTION_PINNED_IMPORTANCE);
|
|
285
265
|
const diversified = applyMMR(nonPinned, {
|
|
@@ -291,6 +271,15 @@ var InjectionService = class {
|
|
|
291
271
|
const ordered = [...pinned, ...diversified];
|
|
292
272
|
return this.#packBudget(ordered, tokenBudget, totalCount);
|
|
293
273
|
}
|
|
274
|
+
/**
|
|
275
|
+
* Score the eligible candidate pool with the exact composite objective the
|
|
276
|
+
* packer optimizes (cold-start ramp + min-score gate applied). Public so
|
|
277
|
+
* benchmarks can oracle against the same objective instead of a proxy.
|
|
278
|
+
*/
|
|
279
|
+
scoreEligibleCandidates(candidates) {
|
|
280
|
+
const minScore = candidates.length <= INJECTION_COLD_START_THRESHOLD ? 0.1 : candidates.length <= INJECTION_COLD_START_RAMP_END ? 0.1 + (INJECTION_MIN_SCORE - 0.1) * (candidates.length - INJECTION_COLD_START_THRESHOLD) / (INJECTION_COLD_START_RAMP_END - INJECTION_COLD_START_THRESHOLD) : INJECTION_MIN_SCORE;
|
|
281
|
+
return candidates.map((m) => ({ memory: m, score: this.#scoreMemory(m) })).filter((s) => s.score >= minScore).sort((a, b) => b.score - a.score);
|
|
282
|
+
}
|
|
294
283
|
formatInjection(result) {
|
|
295
284
|
const { memories, tokensUsed, tokenBudget, totalCount } = result;
|
|
296
285
|
if (memories.length === 0) {
|
|
@@ -341,7 +330,7 @@ var InjectionService = class {
|
|
|
341
330
|
if (!hasGit) {
|
|
342
331
|
return val * (INJECTION_WEIGHTS.value + INJECTION_WEIGHTS.context * 0.4) + imp * (INJECTION_WEIGHTS.importance + INJECTION_WEIGHTS.context * 0.3) + rec * (INJECTION_WEIGHTS.recency + INJECTION_WEIGHTS.context * 0.3) + typ * INJECTION_WEIGHTS.typeBonus + noise * INJECTION_WEIGHTS.noise;
|
|
343
332
|
}
|
|
344
|
-
return ctx * INJECTION_WEIGHTS.context + val * INJECTION_WEIGHTS.value + imp * INJECTION_WEIGHTS.importance + rec * INJECTION_WEIGHTS.recency + typ * INJECTION_WEIGHTS.typeBonus + noise * INJECTION_WEIGHTS.noise + branch * 0.05;
|
|
333
|
+
return (ctx * INJECTION_WEIGHTS.context + val * INJECTION_WEIGHTS.value + imp * INJECTION_WEIGHTS.importance + rec * INJECTION_WEIGHTS.recency + typ * INJECTION_WEIGHTS.typeBonus + noise * INJECTION_WEIGHTS.noise + branch * 0.05) / 1.05;
|
|
345
334
|
}
|
|
346
335
|
#contextRelevance(memory) {
|
|
347
336
|
if (!this.#deps.gitContext) return 0;
|
|
@@ -481,8 +470,10 @@ async function runContext(opts) {
|
|
|
481
470
|
markConsolidated(ctx.dataDir);
|
|
482
471
|
}
|
|
483
472
|
} catch (err) {
|
|
484
|
-
process.stderr.write(
|
|
485
|
-
`
|
|
473
|
+
process.stderr.write(
|
|
474
|
+
`[agentic-memory] maintenance error: ${err instanceof Error ? err.message : err}
|
|
475
|
+
`
|
|
476
|
+
);
|
|
486
477
|
}
|
|
487
478
|
const project = detectProject(process.cwd());
|
|
488
479
|
const gitContext = getGitContext();
|
|
@@ -495,7 +486,19 @@ async function runContext(opts) {
|
|
|
495
486
|
ctx.config.injectionBudget,
|
|
496
487
|
project ?? void 0
|
|
497
488
|
);
|
|
498
|
-
|
|
489
|
+
const formatted = injectionService.formatInjection(result);
|
|
490
|
+
if (opts.json) {
|
|
491
|
+
write(
|
|
492
|
+
JSON.stringify({
|
|
493
|
+
hookSpecificOutput: {
|
|
494
|
+
hookEventName: "SessionStart",
|
|
495
|
+
additionalContext: formatted
|
|
496
|
+
}
|
|
497
|
+
})
|
|
498
|
+
);
|
|
499
|
+
} else {
|
|
500
|
+
write(formatted);
|
|
501
|
+
}
|
|
499
502
|
} finally {
|
|
500
503
|
ctx.close();
|
|
501
504
|
}
|
|
@@ -503,4 +506,4 @@ async function runContext(opts) {
|
|
|
503
506
|
export {
|
|
504
507
|
runContext
|
|
505
508
|
};
|
|
506
|
-
//# sourceMappingURL=context-
|
|
509
|
+
//# sourceMappingURL=context-3GHG7KW6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/memory/subcommands/context.ts","../src/commands/memory/services/decay-service.ts","../src/commands/memory/services/consolidation-service.ts","../src/commands/memory/utils/mmr.ts","../src/commands/memory/services/injection-service.ts"],"sourcesContent":["import { readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { DecayService } from \"../services/decay-service.js\";\nimport { ConsolidationService } from \"../services/consolidation-service.js\";\nimport { InjectionService } from \"../services/injection-service.js\";\nimport { detectProject } from \"../utils/project.js\";\nimport { getGitContext } from \"../utils/git-context.js\";\nimport { initStorage } from \"./init-storage.js\";\n\ninterface ContextOpts {\n readonly json?: boolean;\n readonly dbPath?: string;\n}\n\nconst CONSOLIDATION_FILE = \".last-consolidation\";\n\nfunction shouldConsolidate(dataDir: string, intervalDays: number): boolean {\n const checkpointPath = join(dataDir, CONSOLIDATION_FILE);\n try {\n const raw = readFileSync(checkpointPath, \"utf-8\").trim();\n const lastRun = parseInt(raw, 10);\n if (isNaN(lastRun)) return true;\n const daysSince = (Date.now() - lastRun) / 86_400_000;\n return daysSince >= intervalDays;\n } catch {\n return true;\n }\n}\n\nfunction markConsolidated(dataDir: string): void {\n writeFileSync(join(dataDir, CONSOLIDATION_FILE), String(Date.now()), \"utf-8\");\n}\n\nfunction write(msg: string): void {\n process.stdout.write(msg + \"\\n\");\n}\n\nexport async function runContext(opts: ContextOpts): Promise<void> {\n const ctx = initStorage(opts.dbPath);\n\n try {\n // Run maintenance (decay + consolidation) before loading context\n try {\n const decayService = new DecayService({\n memoryRepo: ctx.memoryRepo,\n relationRepo: ctx.relationRepo,\n });\n decayService.run();\n\n if (shouldConsolidate(ctx.dataDir, ctx.config.consolidationInterval)) {\n const consolidationService = new ConsolidationService({\n memoryRepo: ctx.memoryRepo,\n relationRepo: ctx.relationRepo,\n });\n await consolidationService.consolidate();\n markConsolidated(ctx.dataDir);\n }\n } catch (err) {\n process.stderr.write(\n `[agentic-memory] maintenance error: ${err instanceof Error ? err.message : err}\\n`,\n );\n }\n\n const project = detectProject(process.cwd());\n const gitContext = getGitContext();\n\n const injectionService = new InjectionService({\n memoryRepo: ctx.memoryRepo,\n relationRepo: ctx.relationRepo,\n gitContext: gitContext ?? undefined,\n });\n\n const result = injectionService.selectForInjection(\n ctx.config.injectionBudget,\n project ?? undefined,\n );\n\n const formatted = injectionService.formatInjection(result);\n if (opts.json) {\n // Canonical SessionStart hook envelope — Claude Code injects additionalContext.\n write(\n JSON.stringify({\n hookSpecificOutput: {\n hookEventName: \"SessionStart\",\n additionalContext: formatted,\n },\n }),\n );\n } else {\n write(formatted);\n }\n } finally {\n ctx.close();\n }\n}\n","import type { Memory, DecayParams } from '../types.js';\nimport type { MemoryRepo } from '../storage/memory-repo.js';\nimport type { RelationRepo } from '../storage/relation-repo.js';\nimport { DEFAULT_DECAY_PARAMS } from '../config.js';\n\n// ── Types ────────────────────────────────────────────────────\n\nexport interface DecayServiceDeps {\n readonly memoryRepo: MemoryRepo;\n readonly relationRepo: RelationRepo;\n readonly params?: DecayParams;\n}\n\nexport interface DecayReport {\n readonly decayed: number;\n readonly pruned: number;\n readonly workingCleared: number;\n}\n\n// ── Decay Service ────────────────────────────────────────────\n\nexport class DecayService {\n readonly #memoryRepo: MemoryRepo;\n readonly #relationRepo: RelationRepo;\n readonly #params: DecayParams;\n\n constructor(deps: DecayServiceDeps) {\n this.#memoryRepo = deps.memoryRepo;\n this.#relationRepo = deps.relationRepo;\n this.#params = deps.params ?? DEFAULT_DECAY_PARAMS;\n }\n\n /**\n * Run full decay cycle: clear working memories, apply decay, prune dead memories.\n */\n run(): DecayReport {\n const workingCleared = this.clearWorkingMemories();\n const decayed = this.decayAll();\n const pruned = this.prune();\n return { decayed, pruned, workingCleared };\n }\n\n clearWorkingMemories(): number {\n return this.#memoryRepo.deleteByType('working');\n }\n\n /**\n * Apply decay formula to all non-working memories.\n */\n decayAll(): number {\n const memories = this.#memoryRepo.getAll();\n let updated = 0;\n\n for (const memory of memories) {\n if (memory.type === 'working') continue;\n\n const newImportance = this.computeDecayedImportance(memory);\n if (Math.abs(newImportance - memory.importance) > 0.001) {\n this.#memoryRepo.updateImportanceOnly(memory.id, newImportance);\n updated++;\n }\n }\n\n return updated;\n }\n\n /**\n * Hard-delete memories below prune threshold.\n */\n prune(): number {\n const memories = this.#memoryRepo.getAll();\n const now = Date.now();\n let pruned = 0;\n\n for (const memory of memories) {\n if (memory.type === 'working') continue;\n\n const ageDays = (now - new Date(memory.createdAt).getTime()) / (1000 * 60 * 60 * 24);\n if (\n ageDays > this.#params.pruneMinAgeDays &&\n memory.importance < this.#params.pruneThreshold &&\n memory.accessCount === 0\n ) {\n this.#memoryRepo.hardDelete(memory.id);\n pruned++;\n }\n }\n\n return pruned;\n }\n\n /**\n * Compute decayed importance as a pure function of age from creation.\n * Uses createdAt (immutable) to avoid compounding decay across sessions.\n */\n computeDecayedImportance(memory: Memory): number {\n const tau = this.#params.tauByType[memory.type];\n if (tau === 0) return memory.baseImportance;\n\n const ageDays = (Date.now() - new Date(memory.createdAt).getTime()) / (1000 * 60 * 60 * 24);\n if (ageDays < 0) return memory.baseImportance;\n\n // Synaptic consolidation window (days 0-7)\n if (ageDays <= 7) {\n if (memory.type === 'episodic') {\n // Ebbinghaus curve: steep initial drop with residual floor\n const ebbinghaus = Math.exp(-ageDays * 0.7) + 0.2;\n return Math.max(this.#params.importanceFloor, memory.baseImportance * Math.min(1, ebbinghaus));\n }\n return memory.baseImportance;\n }\n\n // Access modifier: logarithmic curve (spacing effect)\n const accessModifier = this.getAccessModifier(memory.accessCount);\n\n // Relation modifier: connected memories decay slower, highly connected near-immune\n const relationCount = this.#relationRepo.countByMemory(memory.id);\n const rm = this.#params.relationModifier;\n const relationModifier = relationCount >= rm.highlyConnectedThreshold\n ? rm.highlyConnectedMultiplier\n : relationCount >= rm.connectedThreshold\n ? rm.connectedMultiplier\n : rm.isolatedMultiplier;\n\n let effectiveTau = tau * accessModifier * relationModifier;\n\n // Injection penalty: surfaced but never used = noise\n if (memory.injectionCount > 5 && memory.accessCount === 0) {\n effectiveTau /= 1.5;\n }\n\n const decayFactor = Math.exp(-(ageDays - 7) / effectiveTau);\n const newImportance = memory.baseImportance * decayFactor;\n\n return Math.max(this.#params.importanceFloor, newImportance);\n }\n\n private getAccessModifier(accessCount: number): number {\n // Logarithmic curve: 1 + log2(1 + count). Smoother than step function.\n // At 0: 1.0, at 3: 2.0, at 10: 3.5, at 30: 5.0\n return 1 + Math.log2(1 + accessCount);\n }\n}\n","import type { MemoryRepo } from '../storage/memory-repo.js';\nimport type { RelationRepo } from '../storage/relation-repo.js';\n\n// ── Types ────────────────────────────────────────────────────\n\nexport interface ConsolidationDeps {\n readonly memoryRepo: MemoryRepo;\n readonly relationRepo: RelationRepo;\n}\n\nexport interface ConsolidationReport {\n readonly deduplicated: number;\n readonly episodicsCompressed: number;\n}\n\n// ── Consolidation Service ────────────────────────────────────\n\nexport class ConsolidationService {\n readonly #deps: ConsolidationDeps;\n\n constructor(deps: ConsolidationDeps) {\n this.#deps = deps;\n }\n\n /**\n * Run consolidation pipeline.\n * Phase 1: Deduplicate exact/near-exact content matches\n * Phase 2: Compress old consolidated episodics\n * Phase 3: Prune dead memories\n */\n async consolidate(): Promise<ConsolidationReport> {\n const deduplicated = this.deduplicateMemories();\n const episodicsCompressed = this.compressEpisodics();\n return { deduplicated, episodicsCompressed };\n }\n\n /**\n * Phase 1: Deduplication via content similarity.\n */\n deduplicateMemories(): number {\n const memories = this.#deps.memoryRepo.getAll();\n // O(n): group by normalized content; exact duplicates are already blocked\n // at insert by the per-project unique content_hash — this pass only\n // catches whitespace/case variants.\n const byNormalized = new Map<string, typeof memories[number]>();\n let merged = 0;\n\n for (const memory of memories) {\n const key = `${memory.project ?? '_global'}\\n${normalizeText(memory.content)}`;\n const keeper = byNormalized.get(key);\n if (!keeper) {\n byNormalized.set(key, memory);\n continue;\n }\n\n const [survivor, discard] = keeper.importance >= memory.importance\n ? [keeper, memory] : [memory, keeper];\n\n const mergedTags = [...new Set([...survivor.tags, ...discard.tags])];\n this.#deps.memoryRepo.updateContent(survivor.id, {\n tags: mergedTags,\n importance: Math.max(survivor.baseImportance, discard.baseImportance),\n });\n\n this.#deps.memoryRepo.hardDelete(discard.id);\n byNormalized.set(key, survivor);\n merged++;\n }\n\n return merged;\n }\n\n /**\n * Phase 2: Compress old episodic memories that have been consolidated.\n */\n compressEpisodics(): number {\n const episodics = this.#deps.memoryRepo.getByType('episodic');\n const now = Date.now();\n let compressed = 0;\n\n for (const memory of episodics) {\n const ageDays = (now - new Date(memory.createdAt).getTime()) / (1000 * 60 * 60 * 24);\n if (ageDays <= 60) continue;\n if (memory.accessCount > 0) continue;\n if (memory.importance >= 0.2) continue;\n\n const relations = this.#deps.relationRepo.getBySource(memory.id);\n const isConsolidated = relations.some(r => r.relationType === 'derived_from');\n if (!isConsolidated) continue;\n\n this.#deps.memoryRepo.hardDelete(memory.id);\n compressed++;\n }\n\n return compressed;\n }\n\n}\n\n// ── Helpers ──────────────────────────────────────────────────\n\nfunction normalizeText(text: string): string {\n return text.toLowerCase().replace(/\\s+/g, ' ').trim();\n}\n","import type { Memory } from \"../types.js\";\nimport { extractKeywords, jaccardOverlap } from \"./similarity.js\";\n\n// ── MMR (Maximal Marginal Relevance) ───────────────────────────\n// Carbonell & Goldstein (1998). Re-ranks a relevance-sorted list\n// by penalizing candidates too similar to already-selected items.\n// Same relevance budget, more topic coverage per slot.\n//\n// MMR(c) = λ · Rel(c) − (1 − λ) · max_{s ∈ S} Sim(c, s)\n//\n// λ=1 preserves pure relevance order. λ=0 maximizes diversity.\n\nexport interface MMRScored {\n readonly memory: Memory;\n readonly score: number;\n}\n\nexport interface MMROptions {\n readonly lambda: number;\n readonly maxRerank: number;\n readonly contentWeight: number;\n readonly tagsWeight: number;\n}\n\ninterface Features {\n readonly content: ReadonlySet<string>;\n readonly tags: ReadonlySet<string>;\n}\n\nfunction featuresOf(memory: Memory): Features {\n return {\n content: extractKeywords(memory.content),\n tags: new Set(memory.tags),\n };\n}\n\nfunction blendedSimilarity(\n a: Features,\n b: Features,\n contentWeight: number,\n tagsWeight: number,\n): number {\n return (\n jaccardOverlap(a.content, b.content) * contentWeight\n + jaccardOverlap(a.tags, b.tags) * tagsWeight\n );\n}\n\nexport function applyMMR<T extends MMRScored>(\n scored: readonly T[],\n options: MMROptions,\n): readonly T[] {\n if (scored.length <= 1) return scored;\n\n const { lambda, maxRerank, contentWeight, tagsWeight } = options;\n const rerankCount = Math.min(scored.length, maxRerank);\n const pool = scored.slice(0, rerankCount);\n const tail = scored.slice(rerankCount);\n\n const features = new Map<string, Features>();\n for (const s of pool) {\n features.set(s.memory.id, featuresOf(s.memory));\n }\n\n const remaining = new Set(pool.map((s) => s.memory.id));\n const selected: T[] = [];\n\n while (remaining.size > 0) {\n let best: T | null = null;\n let bestMMR = -Infinity;\n\n for (const candidate of pool) {\n if (!remaining.has(candidate.memory.id)) continue;\n\n const candFeat = features.get(candidate.memory.id);\n if (!candFeat) continue;\n\n let maxSim = 0;\n for (const picked of selected) {\n const pickedFeat = features.get(picked.memory.id);\n if (!pickedFeat) continue;\n const sim = blendedSimilarity(candFeat, pickedFeat, contentWeight, tagsWeight);\n if (sim > maxSim) maxSim = sim;\n }\n\n const mmr = lambda * candidate.score - (1 - lambda) * maxSim;\n if (mmr > bestMMR) {\n bestMMR = mmr;\n best = candidate;\n }\n }\n\n if (!best) break;\n selected.push(best);\n remaining.delete(best.memory.id);\n }\n\n return [...selected, ...tail];\n}\n","import type { MemoryRepo } from \"../storage/memory-repo.js\";\nimport type { RelationRepo } from \"../storage/relation-repo.js\";\nimport type { Memory } from \"../types.js\";\nimport {\n estimateTokens,\n DEFAULT_DECAY_PARAMS,\n INJECTION_WEIGHTS as W,\n TYPE_INJECTION_BONUS,\n RECENCY_HALF_LIFE,\n INJECTION_MIN_SCORE,\n INJECTION_COLD_START_THRESHOLD,\n INJECTION_COLD_START_RAMP_END,\n INJECTION_HEADER_TOKENS,\n INJECTION_MAX_SAME_TYPE_FULL,\n INJECTION_PINNED_BUDGET_PCT,\n INJECTION_PINNED_IMPORTANCE,\n INJECTION_MMR_LAMBDA,\n INJECTION_MMR_MAX_RERANK,\n INJECTION_MMR_SIM_WEIGHTS,\n} from \"../config.js\";\nimport { computeContextScore, type GitContext } from \"../utils/git-context.js\";\nimport { applyMMR } from \"../utils/mmr.js\";\n\n// ── Types ──────────────────────────────────────────────────────\n\nexport type InjectionTier = \"full\" | \"summary\" | \"index\";\n\nexport interface ScoredMemory {\n readonly memory: Memory;\n readonly score: number;\n readonly tier: InjectionTier;\n readonly tokenCost: number;\n}\n\nexport interface InjectionResult {\n readonly memories: readonly ScoredMemory[];\n readonly tokensUsed: number;\n readonly tokenBudget: number;\n readonly totalCount: number;\n}\n\ninterface InjectionDeps {\n readonly memoryRepo: MemoryRepo;\n readonly relationRepo: RelationRepo;\n readonly gitContext?: GitContext;\n}\n\n// ── Service ────────────────────────────────────────────────────\n\nexport class InjectionService {\n readonly #deps: InjectionDeps;\n\n constructor(deps: InjectionDeps) {\n this.#deps = deps;\n }\n\n selectForInjection(tokenBudget: number, project?: string): InjectionResult {\n const allMemories = this.#deps.memoryRepo.getAll(project);\n const totalCount = allMemories.length;\n\n // Gate: skip working memories and below-floor importance\n const candidates = allMemories.filter(\n (m) => m.type !== \"working\" && m.importance >= DEFAULT_DECAY_PARAMS.importanceFloor,\n );\n\n if (candidates.length === 0) {\n return { memories: [], tokensUsed: 0, tokenBudget, totalCount };\n }\n\n const scored = this.scoreEligibleCandidates(candidates);\n\n // MMR diversity re-ranking on non-pinned pool; pinned keep relevance order\n // so oracle-preferred high-importance memories are not demoted by duplicates.\n const pinned = scored.filter((s) => s.memory.importance >= INJECTION_PINNED_IMPORTANCE);\n const nonPinned = scored.filter((s) => s.memory.importance < INJECTION_PINNED_IMPORTANCE);\n const diversified = applyMMR(nonPinned, {\n lambda: INJECTION_MMR_LAMBDA,\n maxRerank: INJECTION_MMR_MAX_RERANK,\n contentWeight: INJECTION_MMR_SIM_WEIGHTS.content,\n tagsWeight: INJECTION_MMR_SIM_WEIGHTS.tags,\n });\n const ordered = [...pinned, ...diversified];\n\n // Greedy token-budget packing with tier assignment\n return this.#packBudget(ordered, tokenBudget, totalCount);\n }\n\n /**\n * Score the eligible candidate pool with the exact composite objective the\n * packer optimizes (cold-start ramp + min-score gate applied). Public so\n * benchmarks can oracle against the same objective instead of a proxy.\n */\n scoreEligibleCandidates(\n candidates: readonly Memory[],\n ): readonly { readonly memory: Memory; readonly score: number }[] {\n // Cold start: smooth ramp from 0.10 to INJECTION_MIN_SCORE\n const minScore = candidates.length <= INJECTION_COLD_START_THRESHOLD\n ? 0.10\n : candidates.length <= INJECTION_COLD_START_RAMP_END\n ? 0.10 + (INJECTION_MIN_SCORE - 0.10) * (candidates.length - INJECTION_COLD_START_THRESHOLD) / (INJECTION_COLD_START_RAMP_END - INJECTION_COLD_START_THRESHOLD)\n : INJECTION_MIN_SCORE;\n\n return candidates\n .map((m) => ({ memory: m, score: this.#scoreMemory(m) }))\n .filter((s) => s.score >= minScore)\n .sort((a, b) => b.score - a.score);\n }\n\n formatInjection(result: InjectionResult): string {\n const { memories, tokensUsed, tokenBudget, totalCount } = result;\n\n if (memories.length === 0) {\n return \"No memories stored for this project. Use memory_store to save knowledge across sessions.\";\n }\n\n const lines: string[] = [];\n lines.push(`# Agentic Memory (${memories.length} of ${totalCount} memories, ${tokensUsed}/${tokenBudget} tokens)`);\n lines.push(\"Use memory_search to retrieve full content for any memory listed here.\\n\");\n\n const full = memories.filter((m) => m.tier === \"full\");\n const summary = memories.filter((m) => m.tier === \"summary\");\n const index = memories.filter((m) => m.tier === \"index\");\n\n if (full.length > 0) {\n lines.push(\"## Key Memories\");\n for (const { memory: m } of full) {\n lines.push(`### ${m.title ?? \"(untitled)\"} [${m.type}]`);\n lines.push(m.content.slice(0, 500));\n if (m.tags.length > 0) lines.push(`Tags: ${m.tags.join(\", \")}`);\n lines.push(\"\");\n }\n }\n\n if (summary.length > 0) {\n lines.push(\"## Related Memories\");\n for (const { memory: m } of summary) {\n const snippet = m.content.slice(0, 350);\n const ellipsis = m.content.length > 350 ? \"...\" : \"\";\n lines.push(`- **${m.title ?? \"(untitled)\"}** [${m.type}]: ${snippet}${ellipsis}`);\n }\n lines.push(\"\");\n }\n\n if (index.length > 0) {\n lines.push(\"## Also Available (use memory_search)\");\n for (const { memory: m } of index) {\n lines.push(`- ${m.id.slice(0, 8)} ${m.title ?? \"(untitled)\"} [${m.type}]`);\n }\n }\n\n return lines.join(\"\\n\");\n }\n\n // ── Scoring ────────────────────────────────────────────────\n\n #scoreMemory(memory: Memory): number {\n const hasGit = !!this.#deps.gitContext;\n const ctx = hasGit ? this.#contextRelevance(memory) : 0;\n const val = this.#valueSignal(memory);\n const imp = memory.importance;\n const rec = this.#recencyScore(memory);\n const typ = TYPE_INJECTION_BONUS[memory.type] ?? 0.5;\n const noise = this.#noisePenalty(memory);\n const branch = this.#branchHeuristic(memory);\n\n // Redistribute context weight when git is unavailable\n if (!hasGit) {\n return (\n val * (W.value + W.context * 0.4) +\n imp * (W.importance + W.context * 0.3) +\n rec * (W.recency + W.context * 0.3) +\n typ * W.typeBonus +\n noise * W.noise\n );\n }\n\n // Branch bonus rides on top of unit weights; normalize so git and\n // no-git paths share the same 0..1 scale against fixed thresholds.\n return (\n ctx * W.context +\n val * W.value +\n imp * W.importance +\n rec * W.recency +\n typ * W.typeBonus +\n noise * W.noise +\n branch * 0.05\n ) / 1.05;\n }\n\n #contextRelevance(memory: Memory): number {\n if (!this.#deps.gitContext) return 0;\n return computeContextScore(memory.context, this.#deps.gitContext, \"\");\n }\n\n #branchHeuristic(memory: Memory): number {\n if (!this.#deps.gitContext?.branch) return 0;\n const branch = this.#deps.gitContext.branch.toLowerCase();\n if (branch.startsWith('fix/') || branch.startsWith('bugfix/')) {\n return memory.type === 'pattern' ? 1.0 : memory.type === 'episodic' ? 0.5 : 0;\n }\n if (branch.startsWith('feat/') || branch.startsWith('feature/')) {\n return memory.type === 'procedural' ? 1.0 : memory.type === 'semantic' ? 0.5 : 0;\n }\n return 0;\n }\n\n #valueSignal(memory: Memory): number {\n const { accessCount, injectionCount } = memory;\n\n // Never injected or accessed: neutral — give it a chance\n if (accessCount === 0 && injectionCount === 0) return 0.5;\n\n // Injected but never accessed: noise\n if (injectionCount > 0 && accessCount === 0) {\n return Math.max(0.0, 0.5 - Math.min(1.0, injectionCount / 10) * 0.5);\n }\n\n // Access-to-injection ratio\n const ratio = Math.min(1.0, accessCount / Math.max(1, injectionCount));\n return 0.4 + ratio * 0.6;\n }\n\n #recencyScore(memory: Memory): number {\n const halfLife = RECENCY_HALF_LIFE[memory.type] ?? 30;\n const ageDays = (Date.now() - new Date(memory.updatedAt).getTime()) / 86_400_000;\n return Math.exp(-ageDays * Math.LN2 / halfLife);\n }\n\n #noisePenalty(memory: Memory): number {\n if (memory.injectionCount <= 3) return 1.0; // no penalty for first 3\n if (memory.accessCount > 0) return 1.0; // any access = useful\n return Math.max(0.2, 1.0 - Math.log2(memory.injectionCount - 2) * 0.15);\n }\n\n // ── Token Budget Packing ───────────────────────────────────\n\n #packBudget(\n scored: readonly { readonly memory: Memory; readonly score: number }[],\n tokenBudget: number,\n totalCount: number,\n ): InjectionResult {\n const selected: ScoredMemory[] = [];\n let tokensUsed = INJECTION_HEADER_TOKENS;\n const fullTypeCount = new Map<string, number>();\n\n // Phase 1: pinned memories get guaranteed slots\n const pinnedBudget = INJECTION_HEADER_TOKENS + Math.floor(tokenBudget * INJECTION_PINNED_BUDGET_PCT);\n for (const { memory, score } of scored) {\n if (memory.importance < INJECTION_PINNED_IMPORTANCE || tokensUsed >= pinnedBudget) continue;\n const cost = this.#estimateTierTokens(memory, \"full\");\n if (tokensUsed + cost > pinnedBudget) continue;\n selected.push({ memory, score, tier: \"full\", tokenCost: cost });\n tokensUsed += cost;\n this.#bumpTypeCount(fullTypeCount, memory.type);\n }\n\n // Phase 2: remaining memories packed by score\n for (const { memory, score } of scored) {\n if (tokensUsed >= tokenBudget) break;\n if (selected.some((s) => s.memory.id === memory.id)) continue;\n tokensUsed = this.#tryPack(memory, score, tokenBudget, tokensUsed, selected, fullTypeCount);\n }\n\n for (const entry of selected) {\n this.#deps.memoryRepo.incrementInjection(entry.memory.id);\n }\n return { memories: selected, tokensUsed, tokenBudget, totalCount };\n }\n\n #tryPack(\n memory: Memory, score: number, tokenBudget: number, tokensUsed: number,\n selected: ScoredMemory[], fullTypeCount: Map<string, number>,\n ): number {\n const remaining = tokenBudget - tokensUsed;\n let tier = this.#assignTier(score, selected.length, remaining);\n\n if (tier === 'full' && (fullTypeCount.get(memory.type) ?? 0) >= INJECTION_MAX_SAME_TYPE_FULL) {\n tier = 'summary';\n }\n\n const cost = this.#estimateTierTokens(memory, tier);\n if (tokensUsed + cost <= tokenBudget) {\n selected.push({ memory, score, tier, tokenCost: cost });\n if (tier === 'full') this.#bumpTypeCount(fullTypeCount, memory.type);\n return tokensUsed + cost;\n }\n\n const demoted = tier === \"full\" ? \"summary\" as const : tier === \"summary\" ? \"index\" as const : null;\n if (!demoted) return tokensUsed;\n const demotedCost = this.#estimateTierTokens(memory, demoted);\n if (tokensUsed + demotedCost <= tokenBudget) {\n selected.push({ memory, score, tier: demoted, tokenCost: demotedCost });\n return tokensUsed + demotedCost;\n }\n return tokensUsed;\n }\n\n #bumpTypeCount(counts: Map<string, number>, type: string): void {\n counts.set(type, (counts.get(type) ?? 0) + 1);\n }\n\n #assignTier(score: number, position: number, remainingBudget: number): InjectionTier {\n if (position < 3 && score >= 0.60 && remainingBudget > 200) return \"full\";\n if (position < 8 && score >= 0.35 && remainingBudget > 80) return \"summary\";\n return \"index\";\n }\n\n #estimateTierTokens(memory: Memory, tier: InjectionTier): number {\n const meta = `[${memory.type}] ${memory.title ?? \"\"} (${memory.tags.join(\", \")})`;\n switch (tier) {\n case \"full\":\n return estimateTokens(memory.content.slice(0, 500)) + estimateTokens(meta) + 10;\n case \"summary\":\n return estimateTokens(memory.content.slice(0, 350)) + estimateTokens(meta) + 8;\n case \"index\":\n return estimateTokens(`${memory.id.slice(0, 8)} [${memory.type}] ${memory.title ?? \"(untitled)\"}`) + 4;\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
MemoryRepo
|
|
4
|
+
} from "./chunk-IDH3M4EI.js";
|
|
5
|
+
import {
|
|
6
|
+
closeDatabase,
|
|
7
|
+
createDatabase,
|
|
8
|
+
loadConfig,
|
|
9
|
+
resolveDataDir
|
|
10
|
+
} from "./chunk-DLDVXHI3.js";
|
|
11
|
+
import "./chunk-7KB5YGQZ.js";
|
|
12
|
+
import {
|
|
13
|
+
log
|
|
14
|
+
} from "./chunk-U2TFIUGE.js";
|
|
15
|
+
|
|
16
|
+
// src/commands/memory/subcommands/doctor.ts
|
|
17
|
+
import { existsSync, readFileSync, statSync } from "fs";
|
|
18
|
+
import { join } from "path";
|
|
19
|
+
function formatBytes(bytes) {
|
|
20
|
+
if (bytes < 1024) return `${bytes}B`;
|
|
21
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;
|
|
22
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
|
|
23
|
+
}
|
|
24
|
+
async function runMemoryDoctor(opts) {
|
|
25
|
+
const checks = [];
|
|
26
|
+
const config = loadConfig(opts.dbPath ? { dataDir: opts.dbPath } : void 0);
|
|
27
|
+
const dataDir = resolveDataDir(config.dataDir);
|
|
28
|
+
const nodeVersion = process.version;
|
|
29
|
+
const major = parseInt(nodeVersion.slice(1), 10);
|
|
30
|
+
checks.push({
|
|
31
|
+
name: "Node.js",
|
|
32
|
+
status: major >= 22 ? "PASS" : "WARN",
|
|
33
|
+
detail: major >= 22 ? nodeVersion : `${nodeVersion} (22+ recommended)`
|
|
34
|
+
});
|
|
35
|
+
checks.push({
|
|
36
|
+
name: "Data directory",
|
|
37
|
+
status: existsSync(dataDir) ? "PASS" : "FAIL",
|
|
38
|
+
detail: existsSync(dataDir) ? `${dataDir} (writable)` : `${dataDir} (missing)`
|
|
39
|
+
});
|
|
40
|
+
const dbPath = join(dataDir, "memory.db");
|
|
41
|
+
if (existsSync(dbPath)) {
|
|
42
|
+
try {
|
|
43
|
+
const db = createDatabase({ dataDir });
|
|
44
|
+
const memoryRepo = new MemoryRepo(db);
|
|
45
|
+
const total = memoryRepo.count();
|
|
46
|
+
const dbSize = statSync(dbPath).size;
|
|
47
|
+
checks.push({ name: "Database", status: "PASS", detail: `healthy (${total} memories, ${formatBytes(dbSize)})` });
|
|
48
|
+
const walResult = db.pragma("journal_mode");
|
|
49
|
+
const walMode = walResult[0]?.journal_mode;
|
|
50
|
+
checks.push({ name: "WAL mode", status: walMode === "wal" ? "PASS" : "WARN", detail: walMode ?? "unknown" });
|
|
51
|
+
try {
|
|
52
|
+
db.prepare("SELECT * FROM memories_fts LIMIT 0").run();
|
|
53
|
+
checks.push({ name: "FTS5 index", status: "PASS", detail: "synced" });
|
|
54
|
+
} catch {
|
|
55
|
+
checks.push({ name: "FTS5 index", status: "FAIL", detail: "missing or corrupt" });
|
|
56
|
+
}
|
|
57
|
+
closeDatabase(db);
|
|
58
|
+
} catch (err) {
|
|
59
|
+
checks.push({ name: "Database", status: "FAIL", detail: err instanceof Error ? err.message : "unknown error" });
|
|
60
|
+
}
|
|
61
|
+
} else {
|
|
62
|
+
checks.push({ name: "Database", status: "FAIL", detail: "not found (run: claude-launchpad memory install)" });
|
|
63
|
+
}
|
|
64
|
+
const projectSettingsPath = join(process.cwd(), ".claude", "settings.json");
|
|
65
|
+
if (existsSync(projectSettingsPath)) {
|
|
66
|
+
try {
|
|
67
|
+
const raw = readFileSync(projectSettingsPath, "utf-8");
|
|
68
|
+
const settings = JSON.parse(raw);
|
|
69
|
+
const autoMemoryOff = settings["autoMemoryEnabled"] === false;
|
|
70
|
+
checks.push({
|
|
71
|
+
name: "Auto-memory",
|
|
72
|
+
status: autoMemoryOff ? "PASS" : "WARN",
|
|
73
|
+
detail: autoMemoryOff ? "disabled (using agentic-memory)" : "still enabled (run: claude-launchpad memory install)"
|
|
74
|
+
});
|
|
75
|
+
} catch {
|
|
76
|
+
checks.push({ name: "Auto-memory", status: "WARN", detail: "Could not read project settings" });
|
|
77
|
+
}
|
|
78
|
+
} else {
|
|
79
|
+
checks.push({ name: "Auto-memory", status: "WARN", detail: "No project settings (run: claude-launchpad memory install)" });
|
|
80
|
+
}
|
|
81
|
+
if (opts.json) {
|
|
82
|
+
process.stdout.write(JSON.stringify(checks, null, 2) + "\n");
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
log.blank();
|
|
86
|
+
log.step("Memory doctor");
|
|
87
|
+
log.blank();
|
|
88
|
+
for (const check of checks) {
|
|
89
|
+
const icon = check.status === "PASS" ? "PASS" : check.status === "WARN" ? "WARN" : "FAIL";
|
|
90
|
+
if (check.status === "PASS") {
|
|
91
|
+
log.success(`[${icon}] ${check.name}: ${check.detail}`);
|
|
92
|
+
} else if (check.status === "WARN") {
|
|
93
|
+
log.warn(`[${icon}] ${check.name}: ${check.detail}`);
|
|
94
|
+
} else {
|
|
95
|
+
log.error(`[${icon}] ${check.name}: ${check.detail}`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
const passed = checks.filter((c) => c.status === "PASS").length;
|
|
99
|
+
const warned = checks.filter((c) => c.status === "WARN").length;
|
|
100
|
+
const failed = checks.filter((c) => c.status === "FAIL").length;
|
|
101
|
+
log.blank();
|
|
102
|
+
log.info(`${passed} passed, ${warned} warnings, ${failed} failures`);
|
|
103
|
+
log.blank();
|
|
104
|
+
}
|
|
105
|
+
export {
|
|
106
|
+
runMemoryDoctor
|
|
107
|
+
};
|
|
108
|
+
//# sourceMappingURL=doctor-EKGJ2YAO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/memory/subcommands/doctor.ts"],"sourcesContent":["import { existsSync, readFileSync, statSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { createDatabase, closeDatabase } from '../storage/database.js';\nimport { MemoryRepo } from '../storage/memory-repo.js';\nimport { loadConfig, resolveDataDir } from '../config.js';\nimport { log } from '../../../lib/output.js';\n\ninterface DoctorOpts {\n readonly json?: boolean;\n readonly fix?: boolean;\n readonly dbPath?: string;\n}\n\ninterface DiagResult {\n readonly name: string;\n readonly status: 'PASS' | 'WARN' | 'FAIL';\n readonly detail: string;\n}\n\nfunction formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes}B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;\n}\n\nexport async function runMemoryDoctor(opts: DoctorOpts): Promise<void> {\n const checks: DiagResult[] = [];\n const config = loadConfig(opts.dbPath ? { dataDir: opts.dbPath } : undefined);\n const dataDir = resolveDataDir(config.dataDir);\n\n // Node.js version\n const nodeVersion = process.version;\n const major = parseInt(nodeVersion.slice(1), 10);\n checks.push({\n name: 'Node.js',\n status: major >= 22 ? 'PASS' : 'WARN',\n detail: major >= 22 ? nodeVersion : `${nodeVersion} (22+ recommended)`,\n });\n\n // Data directory\n checks.push({\n name: 'Data directory',\n status: existsSync(dataDir) ? 'PASS' : 'FAIL',\n detail: existsSync(dataDir) ? `${dataDir} (writable)` : `${dataDir} (missing)`,\n });\n\n // Database health\n const dbPath = join(dataDir, 'memory.db');\n if (existsSync(dbPath)) {\n try {\n const db = createDatabase({ dataDir });\n const memoryRepo = new MemoryRepo(db);\n const total = memoryRepo.count();\n const dbSize = statSync(dbPath).size;\n checks.push({ name: 'Database', status: 'PASS', detail: `healthy (${total} memories, ${formatBytes(dbSize)})` });\n\n // WAL mode\n const walResult = db.pragma('journal_mode') as { journal_mode: string }[];\n const walMode = walResult[0]?.journal_mode;\n checks.push({ name: 'WAL mode', status: walMode === 'wal' ? 'PASS' : 'WARN', detail: walMode ?? 'unknown' });\n\n // FTS5\n try {\n db.prepare('SELECT * FROM memories_fts LIMIT 0').run();\n checks.push({ name: 'FTS5 index', status: 'PASS', detail: 'synced' });\n } catch {\n checks.push({ name: 'FTS5 index', status: 'FAIL', detail: 'missing or corrupt' });\n }\n\n closeDatabase(db);\n } catch (err) {\n checks.push({ name: 'Database', status: 'FAIL', detail: err instanceof Error ? err.message : 'unknown error' });\n }\n } else {\n checks.push({ name: 'Database', status: 'FAIL', detail: 'not found (run: claude-launchpad memory install)' });\n }\n\n // Auto-memory setting\n const projectSettingsPath = join(process.cwd(), '.claude', 'settings.json');\n if (existsSync(projectSettingsPath)) {\n try {\n const raw = readFileSync(projectSettingsPath, 'utf-8');\n const settings = JSON.parse(raw) as Record<string, unknown>;\n const autoMemoryOff = settings['autoMemoryEnabled'] === false;\n checks.push({\n name: 'Auto-memory',\n status: autoMemoryOff ? 'PASS' : 'WARN',\n detail: autoMemoryOff ? 'disabled (using agentic-memory)' : 'still enabled (run: claude-launchpad memory install)',\n });\n } catch {\n checks.push({ name: 'Auto-memory', status: 'WARN', detail: 'Could not read project settings' });\n }\n } else {\n checks.push({ name: 'Auto-memory', status: 'WARN', detail: 'No project settings (run: claude-launchpad memory install)' });\n }\n\n // Output\n if (opts.json) {\n process.stdout.write(JSON.stringify(checks, null, 2) + '\\n');\n return;\n }\n\n log.blank();\n log.step('Memory doctor');\n log.blank();\n\n for (const check of checks) {\n const icon = check.status === 'PASS' ? 'PASS' : check.status === 'WARN' ? 'WARN' : 'FAIL';\n if (check.status === 'PASS') {\n log.success(`[${icon}] ${check.name}: ${check.detail}`);\n } else if (check.status === 'WARN') {\n log.warn(`[${icon}] ${check.name}: ${check.detail}`);\n } else {\n log.error(`[${icon}] ${check.name}: ${check.detail}`);\n }\n }\n\n const passed = checks.filter(c => c.status === 'PASS').length;\n const warned = checks.filter(c => c.status === 'WARN').length;\n const failed = checks.filter(c => c.status === 'FAIL').length;\n\n log.blank();\n log.info(`${passed} passed, ${warned} warnings, ${failed} failures`);\n log.blank();\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAAA,SAAS,YAAY,cAAc,gBAAgB;AACnD,SAAS,YAAY;AAkBrB,SAAS,YAAY,OAAuB;AAC1C,MAAI,QAAQ,KAAM,QAAO,GAAG,KAAK;AACjC,MAAI,QAAQ,OAAO,KAAM,QAAO,IAAI,QAAQ,MAAM,QAAQ,CAAC,CAAC;AAC5D,SAAO,IAAI,SAAS,OAAO,OAAO,QAAQ,CAAC,CAAC;AAC9C;AAEA,eAAsB,gBAAgB,MAAiC;AACrE,QAAM,SAAuB,CAAC;AAC9B,QAAM,SAAS,WAAW,KAAK,SAAS,EAAE,SAAS,KAAK,OAAO,IAAI,MAAS;AAC5E,QAAM,UAAU,eAAe,OAAO,OAAO;AAG7C,QAAM,cAAc,QAAQ;AAC5B,QAAM,QAAQ,SAAS,YAAY,MAAM,CAAC,GAAG,EAAE;AAC/C,SAAO,KAAK;AAAA,IACV,MAAM;AAAA,IACN,QAAQ,SAAS,KAAK,SAAS;AAAA,IAC/B,QAAQ,SAAS,KAAK,cAAc,GAAG,WAAW;AAAA,EACpD,CAAC;AAGD,SAAO,KAAK;AAAA,IACV,MAAM;AAAA,IACN,QAAQ,WAAW,OAAO,IAAI,SAAS;AAAA,IACvC,QAAQ,WAAW,OAAO,IAAI,GAAG,OAAO,gBAAgB,GAAG,OAAO;AAAA,EACpE,CAAC;AAGD,QAAM,SAAS,KAAK,SAAS,WAAW;AACxC,MAAI,WAAW,MAAM,GAAG;AACtB,QAAI;AACF,YAAM,KAAK,eAAe,EAAE,QAAQ,CAAC;AACrC,YAAM,aAAa,IAAI,WAAW,EAAE;AACpC,YAAM,QAAQ,WAAW,MAAM;AAC/B,YAAM,SAAS,SAAS,MAAM,EAAE;AAChC,aAAO,KAAK,EAAE,MAAM,YAAY,QAAQ,QAAQ,QAAQ,YAAY,KAAK,cAAc,YAAY,MAAM,CAAC,IAAI,CAAC;AAG/G,YAAM,YAAY,GAAG,OAAO,cAAc;AAC1C,YAAM,UAAU,UAAU,CAAC,GAAG;AAC9B,aAAO,KAAK,EAAE,MAAM,YAAY,QAAQ,YAAY,QAAQ,SAAS,QAAQ,QAAQ,WAAW,UAAU,CAAC;AAG3G,UAAI;AACF,WAAG,QAAQ,oCAAoC,EAAE,IAAI;AACrD,eAAO,KAAK,EAAE,MAAM,cAAc,QAAQ,QAAQ,QAAQ,SAAS,CAAC;AAAA,MACtE,QAAQ;AACN,eAAO,KAAK,EAAE,MAAM,cAAc,QAAQ,QAAQ,QAAQ,qBAAqB,CAAC;AAAA,MAClF;AAEA,oBAAc,EAAE;AAAA,IAClB,SAAS,KAAK;AACZ,aAAO,KAAK,EAAE,MAAM,YAAY,QAAQ,QAAQ,QAAQ,eAAe,QAAQ,IAAI,UAAU,gBAAgB,CAAC;AAAA,IAChH;AAAA,EACF,OAAO;AACL,WAAO,KAAK,EAAE,MAAM,YAAY,QAAQ,QAAQ,QAAQ,mDAAmD,CAAC;AAAA,EAC9G;AAGA,QAAM,sBAAsB,KAAK,QAAQ,IAAI,GAAG,WAAW,eAAe;AAC1E,MAAI,WAAW,mBAAmB,GAAG;AACnC,QAAI;AACF,YAAM,MAAM,aAAa,qBAAqB,OAAO;AACrD,YAAM,WAAW,KAAK,MAAM,GAAG;AAC/B,YAAM,gBAAgB,SAAS,mBAAmB,MAAM;AACxD,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,QAAQ,gBAAgB,SAAS;AAAA,QACjC,QAAQ,gBAAgB,oCAAoC;AAAA,MAC9D,CAAC;AAAA,IACH,QAAQ;AACN,aAAO,KAAK,EAAE,MAAM,eAAe,QAAQ,QAAQ,QAAQ,kCAAkC,CAAC;AAAA,IAChG;AAAA,EACF,OAAO;AACL,WAAO,KAAK,EAAE,MAAM,eAAe,QAAQ,QAAQ,QAAQ,6DAA6D,CAAC;AAAA,EAC3H;AAGA,MAAI,KAAK,MAAM;AACb,YAAQ,OAAO,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,IAAI;AAC3D;AAAA,EACF;AAEA,MAAI,MAAM;AACV,MAAI,KAAK,eAAe;AACxB,MAAI,MAAM;AAEV,aAAW,SAAS,QAAQ;AAC1B,UAAM,OAAO,MAAM,WAAW,SAAS,SAAS,MAAM,WAAW,SAAS,SAAS;AACnF,QAAI,MAAM,WAAW,QAAQ;AAC3B,UAAI,QAAQ,IAAI,IAAI,KAAK,MAAM,IAAI,KAAK,MAAM,MAAM,EAAE;AAAA,IACxD,WAAW,MAAM,WAAW,QAAQ;AAClC,UAAI,KAAK,IAAI,IAAI,KAAK,MAAM,IAAI,KAAK,MAAM,MAAM,EAAE;AAAA,IACrD,OAAO;AACL,UAAI,MAAM,IAAI,IAAI,KAAK,MAAM,IAAI,KAAK,MAAM,MAAM,EAAE;AAAA,IACtD;AAAA,EACF;AAEA,QAAM,SAAS,OAAO,OAAO,OAAK,EAAE,WAAW,MAAM,EAAE;AACvD,QAAM,SAAS,OAAO,OAAO,OAAK,EAAE,WAAW,MAAM,EAAE;AACvD,QAAM,SAAS,OAAO,OAAO,OAAK,EAAE,WAAW,MAAM,EAAE;AAEvD,MAAI,MAAM;AACV,MAAI,KAAK,GAAG,MAAM,YAAY,MAAM,cAAc,MAAM,WAAW;AACnE,MAAI,MAAM;AACZ;","names":[]}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
migrate
|
|
4
|
+
} from "./chunk-MX3T2VEX.js";
|
|
2
5
|
import {
|
|
3
6
|
closeDatabase,
|
|
4
7
|
createDatabase,
|
|
5
8
|
loadConfig,
|
|
6
|
-
migrate,
|
|
7
9
|
resolveDataDir
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-
|
|
10
|
+
} from "./chunk-DLDVXHI3.js";
|
|
11
|
+
import "./chunk-7KB5YGQZ.js";
|
|
10
12
|
import {
|
|
11
13
|
addOrUpdateHook,
|
|
12
14
|
getMemoryPlacement,
|
|
@@ -15,7 +17,7 @@ import {
|
|
|
15
17
|
readSettingsLocalJson,
|
|
16
18
|
writeSettingsJson,
|
|
17
19
|
writeSettingsLocalJson
|
|
18
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-U2TFIUGE.js";
|
|
19
21
|
|
|
20
22
|
// src/commands/memory/subcommands/install.ts
|
|
21
23
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
@@ -156,7 +158,7 @@ function addSessionStartPullHook(hooks) {
|
|
|
156
158
|
dedupKeyword: "memory pull",
|
|
157
159
|
entry: {
|
|
158
160
|
matcher: "startup",
|
|
159
|
-
hooks: [{ type: "command", command: "claude-launchpad memory pull -y 2>/dev/null; exit 0" }]
|
|
161
|
+
hooks: [{ type: "command", command: "npx claude-launchpad memory pull -y 2>/dev/null; exit 0" }]
|
|
160
162
|
},
|
|
161
163
|
prepend: true
|
|
162
164
|
});
|
|
@@ -180,7 +182,7 @@ function addSessionEndPushHook(hooks) {
|
|
|
180
182
|
event: "SessionEnd",
|
|
181
183
|
dedupKeyword: "memory push",
|
|
182
184
|
entry: {
|
|
183
|
-
hooks: [{ type: "command", command: "nohup claude-launchpad memory push -y </dev/null >/dev/null 2>&1 & exit 0" }]
|
|
185
|
+
hooks: [{ type: "command", command: "nohup npx claude-launchpad memory push -y </dev/null >/dev/null 2>&1 & exit 0" }]
|
|
184
186
|
}
|
|
185
187
|
});
|
|
186
188
|
if (result.added) log.info("Session end: memories will auto-push to GitHub Gist");
|
|
@@ -207,7 +209,7 @@ function addToolPermissions(settings) {
|
|
|
207
209
|
};
|
|
208
210
|
}
|
|
209
211
|
async function ensureNativeDeps() {
|
|
210
|
-
const { cwdRequire } = await import("./require-deps-
|
|
212
|
+
const { cwdRequire } = await import("./require-deps-AEDO5YRM.js");
|
|
211
213
|
try {
|
|
212
214
|
cwdRequire("better-sqlite3");
|
|
213
215
|
return;
|
|
@@ -215,13 +217,13 @@ async function ensureNativeDeps() {
|
|
|
215
217
|
}
|
|
216
218
|
log.step("Installing required database libraries...");
|
|
217
219
|
try {
|
|
218
|
-
execSync("npm install -g better-sqlite3
|
|
220
|
+
execSync("npm install -g better-sqlite3", { stdio: "pipe", timeout: 12e4 });
|
|
219
221
|
log.success("Database libraries installed");
|
|
220
222
|
} catch {
|
|
221
223
|
log.error("Could not install database libraries automatically.");
|
|
222
224
|
log.blank();
|
|
223
225
|
log.info("Install manually:");
|
|
224
|
-
log.step(" npm install -g better-sqlite3
|
|
226
|
+
log.step(" npm install -g better-sqlite3");
|
|
225
227
|
log.blank();
|
|
226
228
|
log.info("Requires a C++ compiler (Xcode on macOS, build-essential on Linux).");
|
|
227
229
|
process.exit(1);
|
|
@@ -353,4 +355,4 @@ export {
|
|
|
353
355
|
injectClaudeMdGuidance,
|
|
354
356
|
runInstall
|
|
355
357
|
};
|
|
356
|
-
//# sourceMappingURL=install-
|
|
358
|
+
//# sourceMappingURL=install-543ZKMXX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/memory/subcommands/install.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { execSync } from 'node:child_process';\nimport { createDatabase, closeDatabase } from '../storage/database.js';\nimport { migrate } from '../storage/migrator.js';\nimport { loadConfig, resolveDataDir } from '../config.js';\nimport { readSettingsJson, writeSettingsJson, readSettingsLocalJson, writeSettingsLocalJson } from '../../../lib/settings.js';\nimport { addOrUpdateHook } from '../../../lib/hook-builder.js';\nimport { getMemoryPlacement } from '../../../lib/memory-placement.js';\nimport { log } from '../../../lib/output.js';\nimport type { MemoryPlacement } from '../../../types/index.js';\n\nfunction isGhAuthenticated(): boolean {\n try {\n execSync('gh auth status', { stdio: 'pipe', timeout: 5000 });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction isClaudeCliOnPath(): boolean {\n try {\n execSync('claude --version', { stdio: 'pipe', timeout: 5000 });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction isGhOnPath(): boolean {\n try {\n execSync('gh --version', { stdio: 'pipe', timeout: 5000 });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction preflight(): void {\n if (!isClaudeCliOnPath()) {\n log.error('The `claude` CLI was not found on PATH.');\n log.blank();\n log.info('The knowledge base installs as a Claude Code MCP server, so the CLI is required.');\n log.info('Install: https://docs.claude.com/en/docs/claude-code');\n process.exit(1);\n }\n if (!isGhOnPath()) {\n log.warn('The GitHub CLI (`gh`) was not found on PATH — cross-device memory sync will be disabled.');\n log.info('Install later for sync: https://cli.github.com/ then `gh auth login`.');\n log.blank();\n }\n}\n\ninterface InstallOpts {\n readonly dbPath?: string;\n /** Non-interactive: default placement to \"shared\" instead of prompting. */\n readonly yes?: boolean;\n}\n\nexport async function runInstall(opts: InstallOpts): Promise<void> {\n log.blank();\n log.step('Setting up your knowledge base');\n log.blank();\n\n // Preflight: `claude` CLI is hard-required; `gh` is a soft warning for sync.\n preflight();\n\n // Step 0: Ensure native deps are installed globally\n await ensureNativeDeps();\n\n // Prompt for placement before any config writes. Non-interactive contexts\n // (-y, or stdin not a TTY — CI, pipes) default to \"shared\" instead of\n // letting inquirer throw ExitPromptError with a misleading exit 0.\n const nonInteractive = opts.yes === true || !process.stdin.isTTY;\n if (nonInteractive) log.info('Non-interactive: using \"shared\" memory placement (CLAUDE.md + settings.json).');\n const placement = await getMemoryPlacement(process.cwd(), nonInteractive);\n\n const config = loadConfig(opts.dbPath ? { dataDir: opts.dbPath } : undefined);\n const dataDir = resolveDataDir(config.dataDir);\n\n // Step 1: Database\n log.step('[1/5] Creating knowledge base...');\n if (!existsSync(dataDir)) {\n mkdirSync(dataDir, { recursive: true });\n }\n const db = createDatabase({ dataDir });\n migrate(db);\n closeDatabase(db);\n log.success(`Knowledge base created at ${dataDir}/memory.db`);\n\n // Step 2: Configure Claude Code settings\n log.step('[2/5] Connecting to Claude Code...');\n await configureSettings(process.cwd(), placement);\n\n // Step 3: Register MCP server (project scope for shared, local scope for local)\n log.step('[3/5] Enabling memory tools...');\n const mcpScope = placement === \"local\" ? \"local\" : \"project\";\n // Must run BEFORE `claude mcp add` — otherwise the add silently fails with \"not allowed by policy\"\n await ensureAllowedMcpServerIncludesMemory(process.cwd(), placement);\n const registered = registerMcpServer(mcpScope);\n if (registered) {\n log.success('Memory tools available in Claude Code');\n } else {\n log.warn('Could not enable memory tools automatically.');\n log.info(`Run: claude mcp add --scope ${mcpScope} agentic-memory -- npx claude-launchpad memory serve`);\n }\n\n // Step 4: CLAUDE.md + skills\n log.step('[4/5] Adding instructions...');\n const guidanceAdded = injectClaudeMdGuidance(process.cwd(), placement);\n if (guidanceAdded) {\n const label = placement === \"local\" ? \".claude/CLAUDE.md\" : \"CLAUDE.md\";\n log.success(`${label} updated with memory instructions`);\n }\n if (placement === \"shared\") {\n const skillsInstalled = installSkills(process.cwd());\n if (skillsInstalled > 0) {\n log.success(`Installed ${skillsInstalled} skill(s) to .claude/skills/`);\n }\n }\n\n log.blank();\n log.success('Knowledge base is ready. Claude will now remember across sessions.');\n log.info('Restart your Claude Code session to activate.');\n\n // Sync guidance\n if (isGhAuthenticated()) {\n log.info('Cross-device sync available. Run `memory push` to back up, or it auto-syncs each session.');\n } else {\n log.blank();\n log.info('Recommended: install the GitHub CLI for cross-device memory sync:');\n log.step(' https://cli.github.com/');\n log.step(' gh auth login');\n }\n log.blank();\n}\n\nexport function detectExistingSetup(projectDir: string): MemoryPlacement | null {\n // Check local CLAUDE.md\n try {\n const localClaude = readFileSync(join(projectDir, '.claude', 'CLAUDE.md'), 'utf-8');\n if (localClaude.includes('## Memory') || localClaude.includes('agentic-memory')) return \"local\";\n } catch { /* not found */ }\n\n // Check root CLAUDE.md\n try {\n const rootClaude = readFileSync(join(projectDir, 'CLAUDE.md'), 'utf-8');\n if (rootClaude.includes('## Memory (agentic-memory)')) return \"shared\";\n } catch { /* not found */ }\n\n return null;\n}\n\nasync function configureSettings(projectDir: string, placement: MemoryPlacement): Promise<void> {\n const read = placement === \"local\" ? readSettingsLocalJson : readSettingsJson;\n const write = placement === \"local\" ? writeSettingsLocalJson : writeSettingsJson;\n const settings = await read(projectDir);\n if (settings === null) {\n throw new Error(\"settings.json is unreadable; repair or remove it before installing memory.\");\n }\n\n // Disable built-in auto-memory\n log.info('Built-in auto-memory disabled (replaced by knowledge base)');\n\n // Build hooks immutably — always add sync hooks (they fail silently without gh)\n const baseHooks = (settings['hooks'] ?? {}) as Record<string, unknown[]>;\n const withPull = addSessionStartPullHook(baseHooks);\n const withContext = addSessionStartHook(withPull);\n const withPush = addSessionEndPushHook(withContext);\n\n // Build permissions immutably\n const withPermissions = addToolPermissions(settings);\n\n const updated = {\n ...withPermissions,\n autoMemoryEnabled: false,\n hooks: withPush,\n };\n\n await write(projectDir, updated);\n const target = placement === \"local\" ? \"settings.local.json\" : \"settings.json\";\n log.success(`Claude Code configured in ${target}`);\n}\n\nfunction addSessionStartPullHook(hooks: Record<string, unknown[]>): Record<string, unknown[]> {\n const result = addOrUpdateHook(hooks, {\n event: 'SessionStart',\n dedupKeyword: 'memory pull',\n entry: {\n matcher: 'startup',\n hooks: [{ type: 'command', command: 'npx claude-launchpad memory pull -y 2>/dev/null; exit 0' }],\n },\n prepend: true,\n });\n if (result.added) log.info('Session start: memories will auto-pull from GitHub Gist');\n return result.hooks;\n}\n\nfunction addSessionStartHook(hooks: Record<string, unknown[]>): Record<string, unknown[]> {\n const result = addOrUpdateHook(hooks, {\n event: 'SessionStart',\n dedupKeyword: 'claude-launchpad memory context',\n entry: {\n matcher: 'startup|resume',\n hooks: [{ type: 'command', command: 'npx claude-launchpad memory context --json 2>/dev/null; exit 0' }],\n },\n });\n if (result.added) log.info('Session start: Claude will recall relevant context automatically');\n return result.hooks;\n}\n\nfunction addSessionEndPushHook(hooks: Record<string, unknown[]>): Record<string, unknown[]> {\n const result = addOrUpdateHook(hooks, {\n event: 'SessionEnd',\n dedupKeyword: 'memory push',\n entry: {\n hooks: [{ type: 'command', command: 'nohup npx claude-launchpad memory push -y </dev/null >/dev/null 2>&1 & exit 0' }],\n },\n });\n if (result.added) log.info('Session end: memories will auto-push to GitHub Gist');\n return result.hooks;\n}\n\nfunction addToolPermissions(settings: Record<string, unknown>): Record<string, unknown> {\n const permissions = (settings['permissions'] ?? {}) as Record<string, unknown>;\n const allowList = (permissions['allow'] ?? []) as readonly string[];\n\n const memoryTools = [\n 'mcp__agentic-memory__memory_store',\n 'mcp__agentic-memory__memory_search',\n 'mcp__agentic-memory__memory_recent',\n 'mcp__agentic-memory__memory_forget',\n 'mcp__agentic-memory__memory_relate',\n 'mcp__agentic-memory__memory_stats',\n 'mcp__agentic-memory__memory_update',\n ];\n\n const missing = memoryTools.filter((t) => !allowList.includes(t));\n if (missing.length === 0) return settings;\n\n log.info(`${missing.length} memory tools auto-approved`);\n return {\n ...settings,\n permissions: { ...permissions, allow: [...allowList, ...missing] },\n };\n}\n\nasync function ensureNativeDeps(): Promise<void> {\n const { cwdRequire } = await import('../utils/require-deps.js');\n try {\n cwdRequire('better-sqlite3');\n return;\n } catch {\n // Not installed — install globally\n }\n\n log.step('Installing required database libraries...');\n try {\n execSync('npm install -g better-sqlite3', { stdio: 'pipe', timeout: 120000 });\n log.success('Database libraries installed');\n } catch {\n log.error('Could not install database libraries automatically.');\n log.blank();\n log.info('Install manually:');\n log.step(' npm install -g better-sqlite3');\n log.blank();\n log.info('Requires a C++ compiler (Xcode on macOS, build-essential on Linux).');\n process.exit(1);\n }\n}\n\nasync function ensureAllowedMcpServerIncludesMemory(\n projectDir: string,\n placement: MemoryPlacement,\n): Promise<void> {\n const read = placement === \"local\" ? readSettingsLocalJson : readSettingsJson;\n const write = placement === \"local\" ? writeSettingsLocalJson : writeSettingsJson;\n const settings = await read(projectDir);\n if (settings === null) return;\n const existing = settings.allowedMcpServers as unknown;\n // No allowlist configured — nothing to patch; Claude Code trusts any added server by default.\n if (!Array.isArray(existing)) return;\n\n const list = existing as Array<{ serverName?: unknown }>;\n const hasMemory = list.some((e) => e && typeof e === \"object\" && e.serverName === \"agentic-memory\");\n if (hasMemory) return;\n\n const updated = {\n ...settings,\n allowedMcpServers: [{ serverName: \"agentic-memory\" }, ...list],\n };\n await write(projectDir, updated);\n const target = placement === \"local\" ? \"settings.local.json\" : \"settings.json\";\n log.info(`Added agentic-memory to allowedMcpServers in ${target}`);\n}\n\nfunction registerMcpServer(scope: \"project\" | \"local\"): boolean {\n try {\n const existing = execSync('claude mcp list', { stdio: 'pipe', timeout: 10000, encoding: 'utf-8' });\n if (existing.includes('agentic-memory')) {\n log.info('Memory tools already registered');\n return true;\n }\n execSync(\n `claude mcp add --scope ${scope} agentic-memory -- npx claude-launchpad memory serve`,\n { stdio: 'pipe', timeout: 10000 },\n );\n return true;\n } catch {\n return false;\n }\n}\n\nconst MEMORY_GUIDANCE = `\n## Memory (agentic-memory)\nThis project uses **agentic-memory** for persistent memory across sessions.\n- **DO NOT** use the built-in auto-memory system (~/.claude/projects/*/memory/)\n- Memory context is **automatically injected** at session start via SessionStart hook - no need to call memory_recent manually\n- Use \\`memory_search\\` to find specific memories by keyword\n- Use \\`memory_store\\` to save decisions, gotchas, and learnings worth remembering\n- Use \\`memory_stats\\` to check memory health\n- **STORE IMMEDIATELY** when: a dependency strategy changes, an architecture decision is made, a convention is established, a bug pattern is discovered, or a feature is killed/added\n`;\n\nexport function injectClaudeMdGuidance(projectDir: string, placement: MemoryPlacement): boolean {\n const claudeMdPath = placement === \"local\"\n ? join(projectDir, '.claude', 'CLAUDE.md')\n : join(projectDir, 'CLAUDE.md');\n\n let content = '';\n try {\n content = readFileSync(claudeMdPath, 'utf-8');\n } catch {\n if (placement !== \"local\") return false;\n // Create local .claude/CLAUDE.md\n mkdirSync(join(projectDir, '.claude'), { recursive: true });\n content = '# Local Claude Config\\n';\n }\n\n if (/^## Memory( \\(agentic-memory\\))?\\s*$/m.test(content)) {\n return false;\n }\n\n const updated = content.trimEnd() + '\\n' + MEMORY_GUIDANCE;\n writeFileSync(claudeMdPath, updated, 'utf-8');\n return true;\n}\n\nconst MIGRATE_MEMORY_SKILL = `---\nname: lp-migrate-memory\ndescription: Migrate legacy Claude Code auto-memory files (~/.claude/projects/*/memory/*.md) into agentic-memory. Use when setting up agentic-memory on a project that already has built-in memories.\nallowed-tools: Read, Glob, Grep, mcp__agentic-memory__memory_store, mcp__agentic-memory__memory_search\n---\n\n# Migrate Legacy Claude Code Memories\n\nMigrate memory files from Claude Code's built-in auto-memory system into agentic-memory.\n\n## Steps\n\n1. **Find legacy memory files** for this project:\n - Scan \\`~/.claude/projects/*/memory/*.md\\` for directories whose slug matches the current project path\n - The slug format is the absolute path with \\`/\\` replaced by \\`-\\` and leading \\`-\\` (e.g. \\`-Users-john-projects-myapp\\`)\n - Also check \\`~/.claude/projects/*/memory/team/*.md\\` for team memories\n\n2. **For each memory file found**, read it and parse:\n - YAML frontmatter: \\`name\\`, \\`description\\`, \\`type\\` (user/feedback/project/reference)\n - Body content (everything after the frontmatter closing \\`---\\`)\n - Skip \\`MEMORY.md\\` (it's just an index file, not a memory)\n\n3. **Before storing**, check for duplicates:\n - Call \\`memory_search\\` with the memory description or first 100 chars of content\n - If a close match exists (same topic), skip it and report\n\n4. **Map types and store** each memory via \\`memory_store\\`:\n - \\`user\\` -> type: \\`semantic\\`, tags: [\\`user\\`, \\`migrated\\`], importance: 0.7\n - \\`feedback\\` -> type: \\`semantic\\`, tags: [\\`feedback\\`, \\`migrated\\`], importance: 0.8\n - \\`project\\` -> type: \\`semantic\\`, tags: [\\`project\\`, \\`migrated\\`], importance: 0.6\n - \\`reference\\` -> type: \\`semantic\\`, tags: [\\`reference\\`, \\`migrated\\`], importance: 0.5\n - Use the frontmatter \\`name\\` as the title\n - Use the body content as the memory content\n - Set source: \\`import\\`\n - Adjust importance up/down based on the content (decisions and gotchas deserve higher importance)\n\n5. **Report results**: list what was migrated, what was skipped (duplicates), and what failed\n\n## Important\n\n- Do NOT delete the original files - the user can do that manually after verifying\n- Do NOT migrate content that is purely derived from code (architecture, file structure) - it belongs in CLAUDE.md, not memory\n- If unsure about a memory's value, migrate it anyway - the decay system will naturally prune low-value memories over time\n`;\n\nconst SKILLS: Readonly<Record<string, string>> = {\n 'lp-migrate-memory': MIGRATE_MEMORY_SKILL,\n};\n\nfunction installSkills(projectDir: string): number {\n const skillsDir = join(projectDir, '.claude', 'skills');\n let installed = 0;\n\n for (const [name, content] of Object.entries(SKILLS)) {\n const skillDir = join(skillsDir, name);\n const skillPath = join(skillDir, 'SKILL.md');\n\n if (existsSync(skillPath)) continue;\n\n mkdirSync(skillDir, { recursive: true });\n writeFileSync(skillPath, content.trimStart(), 'utf-8');\n installed++;\n }\n\n return installed;\n}\n"],"mappings":"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","names":[]}
|