claude-launchpad 0.12.2 → 0.13.1

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.
@@ -28,6 +28,7 @@ import "../../chunk-Z6FBT44W.js";
28
28
  import "../../chunk-RJGXPH7P.js";
29
29
 
30
30
  // src/commands/memory/server.ts
31
+ import { createRequire } from "module";
31
32
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
32
33
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
33
34
 
@@ -478,7 +479,7 @@ function registerStore(server, deps) {
478
479
  server.registerTool(
479
480
  "memory_store",
480
481
  {
481
- description: 'Store a new memory. Use memory_search first to check for duplicates. Prefer updating existing semantic/procedural memories over creating new ones. Types: episodic (events), semantic (facts), procedural (how-to), pattern (recurring), working (temporary). Importance: 0-0.3 ephemeral, 0.3-0.6 reference, 0.6-0.8 important, 0.8-1.0 critical. Suggested tags: #bug, #decision, #gotcha, #howto, #pattern, #architecture. Context is auto-detected from git (branch, recent files) if omitted. NOTE: A built-in dedup guard prevents identical content from being stored twice within 10 seconds. If you see "Skipped" responses, the memory was likely already stored by a parallel call. This is expected behavior, not an error. The data is saved correctly.',
482
+ description: 'Save something worth remembering to the knowledge base. Use when you learn a fact, make a decision, hit a bug, or discover a pattern that future sessions should know. Always search first to avoid duplicates \u2014 update existing memories when possible. Types: semantic (facts/decisions), procedural (how-to), episodic (what happened), pattern (recurring), working (scratch). Importance: 0.1 trivial, 0.5 useful, 0.8 important, 1.0 critical. Tags and git context are auto-detected if omitted. "Skipped" responses mean a duplicate was caught \u2014 not an error.',
482
483
  inputSchema,
483
484
  annotations: { idempotentHint: false }
484
485
  },
@@ -584,7 +585,7 @@ function registerSearch(server, deps) {
584
585
  server.registerTool(
585
586
  "memory_search",
586
587
  {
587
- description: "Search memories by keyword match, context relevance, and relation graph. Returns up to `limit` results ranked by composite score (text match, importance, recency, access frequency, git context). Related memories are automatically surfaced via 1-hop graph expansion. Pass `id` for direct lookup. Use `type` and `tags` to filter.",
588
+ description: "Look up what you already know. Query the knowledge base before solving a problem or storing new information. Use when: checking if something was already decided, finding how-to steps, recalling past bugs, or deduping before a store. Related memories are surfaced automatically. Pass `id` for direct lookup, or filter by `type` and `tags`.",
588
589
  inputSchema: inputSchema2,
589
590
  annotations: { readOnlyHint: true, idempotentHint: true }
590
591
  },
@@ -658,7 +659,7 @@ function registerForget(server, deps) {
658
659
  server.registerTool(
659
660
  "memory_forget",
660
661
  {
661
- description: "Forget a memory. By default, soft-deletes (sets importance to 0, allowing natural decay). Pass hard_delete=true to permanently remove. Use memory_search to find the ID first.",
662
+ description: "Remove outdated or wrong information from the knowledge base. Default: soft-delete (fades away naturally). Pass hard_delete=true to erase permanently. Use memory_search to find the ID first.",
662
663
  inputSchema: inputSchema3,
663
664
  annotations: { destructiveHint: true, idempotentHint: true }
664
665
  },
@@ -707,7 +708,7 @@ function registerRelate(server, deps) {
707
708
  server.registerTool(
708
709
  "memory_relate",
709
710
  {
710
- description: "Create a typed relation between two memories. Relations affect retrieval ranking (connected memories decay slower). Types: relates_to, depends_on, contradicts, extends, implements, derived_from.",
711
+ description: "Link two memories together so they surface as a group. Use when one memory extends, contradicts, depends on, or implements another. Linked memories stay relevant longer and appear together in search results.",
711
712
  inputSchema: inputSchema4,
712
713
  annotations: { idempotentHint: true }
713
714
  },
@@ -764,7 +765,7 @@ function registerStats(server, deps) {
764
765
  server.registerTool(
765
766
  "memory_stats",
766
767
  {
767
- description: "Show memory dashboard: total count, breakdown by type, storage size, and most-injected memories. No arguments needed.",
768
+ description: "See how much is in the knowledge base \u2014 total count, breakdown by type, storage size, and most-used memories.",
768
769
  annotations: { readOnlyHint: true, idempotentHint: true }
769
770
  },
770
771
  async () => {
@@ -810,7 +811,7 @@ function registerRecent(server, deps) {
810
811
  server.registerTool(
811
812
  "memory_recent",
812
813
  {
813
- description: "Load session context: returns context-matched, recent, and related memories. Call this at the start of every session to load context from previous work. Results are grouped into sections: contextMatched (matching current branch/files), recent (most recent), and related (connected via relations).",
814
+ description: "Get caught up on what happened before this session. Returns memories relevant to the current branch/files, recent activity, and related context. Typically called at session start to restore working context. No query needed \u2014 it uses git state to find what matters.",
814
815
  inputSchema: inputSchema5,
815
816
  annotations: { readOnlyHint: true, idempotentHint: true }
816
817
  },
@@ -865,7 +866,7 @@ function registerUpdate(server, deps) {
865
866
  server.registerTool(
866
867
  "memory_update",
867
868
  {
868
- description: "Update an existing memory in-place. Preserves access count, injection count, and creation date. Use memory_search to find the ID first. At least one field must be provided.",
869
+ description: "Correct or improve an existing memory instead of creating a duplicate. Use when information has changed, a decision was revised, or a memory needs more detail. Keeps the memory's history intact. Use memory_search to find the ID first.",
869
870
  inputSchema: inputSchema6,
870
871
  annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true }
871
872
  },
@@ -923,6 +924,8 @@ function registerTools(server, deps) {
923
924
  }
924
925
 
925
926
  // src/commands/memory/server.ts
927
+ var require2 = createRequire(import.meta.url);
928
+ var { version } = require2("../../../package.json");
926
929
  async function startServer(deps) {
927
930
  const config = deps?.config ?? loadConfig();
928
931
  const dataDir = resolveDataDir(config.dataDir);
@@ -937,9 +940,9 @@ async function startServer(deps) {
937
940
  searchRepo
938
941
  });
939
942
  const server = new McpServer(
940
- { name: "agentic-memory", version: "0.1.0" },
943
+ { name: "agentic-memory", version },
941
944
  {
942
- instructions: "Use memory_search before memory_store to check for duplicates. Use memory_update to modify existing memories instead of creating duplicates - it preserves access history. Store memories at the semantic level - capture WHY, not just WHAT happened. Only store knowledge worth remembering across sessions. NEVER store credentials, API keys, tokens, passwords, or secrets - memories may be synced to external storage. Memory context is automatically injected at session start via hook - no need to call memory_recent manually."
945
+ instructions: "This is your knowledge base \u2014 persistent context that survives across sessions. Search before storing to avoid duplicates. Update existing memories instead of creating new ones. Store decisions, patterns, and insights \u2014 capture WHY, not just WHAT. Only save what future sessions will need. NEVER store secrets, API keys, or passwords. Session context is injected automatically at startup \u2014 no need to call memory_recent."
943
946
  }
944
947
  );
945
948
  const project = detectProject(process.cwd());
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/memory/server.ts","../../../src/commands/memory/services/retrieval-service.ts","../../../src/commands/memory/tools/store.ts","../../../src/commands/memory/utils/content-validation.ts","../../../src/commands/memory/utils/contradiction.ts","../../../src/commands/memory/tools/search.ts","../../../src/commands/memory/tools/forget.ts","../../../src/commands/memory/utils/errors.ts","../../../src/commands/memory/tools/relate.ts","../../../src/commands/memory/tools/stats.ts","../../../src/commands/memory/tools/recent.ts","../../../src/commands/memory/tools/update.ts","../../../src/commands/memory/tools/register.ts"],"sourcesContent":["import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { createDatabase, closeDatabase } from './storage/database.js';\nimport { migrate } from './storage/migrator.js';\nimport { MemoryRepo } from './storage/memory-repo.js';\nimport { RelationRepo } from './storage/relation-repo.js';\nimport { SearchRepo } from './storage/search-repo.js';\nimport { RetrievalService } from './services/retrieval-service.js';\nimport { loadConfig, resolveDataDir } from './config.js';\nimport type { Config } from './config.js';\nimport { registerTools } from './tools/register.js';\nimport { detectProject } from './utils/project.js';\n\nexport interface ServerDeps {\n readonly config: Config;\n}\n\nexport async function startServer(deps?: Partial<ServerDeps>): Promise<void> {\n const config = deps?.config ?? loadConfig();\n const dataDir = resolveDataDir(config.dataDir);\n\n const db = createDatabase({ dataDir });\n migrate(db);\n\n const memoryRepo = new MemoryRepo(db);\n const relationRepo = new RelationRepo(db);\n const searchRepo = new SearchRepo(db);\n\n const retrievalService = new RetrievalService({\n memoryRepo,\n relationRepo,\n searchRepo,\n });\n\n const server = new McpServer(\n { name: 'agentic-memory', version: '0.1.0' },\n {\n instructions:\n 'Use memory_search before memory_store to check for duplicates. '\n + 'Use memory_update to modify existing memories instead of creating duplicates - it preserves access history. '\n + 'Store memories at the semantic level - capture WHY, not just WHAT happened. '\n + 'Only store knowledge worth remembering across sessions. '\n + 'NEVER store credentials, API keys, tokens, passwords, or secrets - memories may be synced to external storage. '\n + 'Memory context is automatically injected at session start via hook - no need to call memory_recent manually.',\n },\n );\n\n const project = detectProject(process.cwd());\n\n registerTools(server, { memoryRepo, relationRepo, retrievalService, dataDir, project });\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n\n const shutdown = async () => {\n await server.close();\n closeDatabase(db);\n process.exit(0);\n };\n process.on('SIGINT', () => void shutdown());\n process.on('SIGTERM', () => void shutdown());\n}\n\n// Auto-start when invoked directly as MCP server entry point\nstartServer().catch((err) => {\n process.stderr.write(`[agentic-memory] ${err}\\n`);\n process.exit(1);\n});\n","import type { Memory, MemoryType, SearchResult, SearchInput, RelationType } from '../types.js';\nimport type { MemoryRepo } from '../storage/memory-repo.js';\nimport type { RelationRepo } from '../storage/relation-repo.js';\nimport type { SearchRepo } from '../storage/search-repo.js';\nimport { SCORING_WEIGHTS } from '../config.js';\nimport { type GitContext, getGitContext, computeContextScore } from '../utils/git-context.js';\n\nconst STALENESS_THRESHOLDS = {\n working: 1,\n episodic: 7,\n pattern: 14,\n semantic: 30,\n procedural: 90,\n} as const;\n\nexport interface RetrievalDeps {\n readonly memoryRepo: MemoryRepo;\n readonly relationRepo: RelationRepo;\n readonly searchRepo: SearchRepo;\n readonly gitContext?: GitContext;\n}\n\nexport class RetrievalService {\n readonly #deps: RetrievalDeps;\n readonly #gitContext: GitContext;\n\n constructor(deps: RetrievalDeps) {\n this.#deps = deps;\n this.#gitContext = deps.gitContext ?? getGitContext();\n }\n\n /**\n * FTS5 keyword search with multi-signal scoring, context awareness,\n * and relation-based graph expansion.\n */\n async search(input: SearchInput): Promise<readonly SearchResult[]> {\n // Direct ID lookup\n if (input.id) {\n const memory = this.#deps.memoryRepo.getById(input.id);\n if (!memory) return [];\n this.#deps.memoryRepo.incrementAccess(input.id);\n return [{\n memory,\n score: 1.0,\n explanation: 'Direct lookup by ID',\n }];\n }\n\n // Phase 1: FTS5 keyword search\n const ftsResults = this.#deps.searchRepo.searchFts({\n query: input.query,\n limit: input.limit * 3,\n type: input.type,\n minImportance: input.min_importance,\n project: input.project,\n });\n\n const textScores = ftsOnlyScores(ftsResults);\n if (textScores.size === 0) return [];\n\n // Phase 2: Load memories and compute composite scores\n const candidates: { memory: Memory; composite: number; parts: ScoreParts }[] = [];\n\n for (const [memoryId, textScore] of textScores) {\n const memory = this.#deps.memoryRepo.getById(memoryId);\n if (!memory) continue;\n if (input.type && memory.type !== input.type) continue;\n if (memory.importance < input.min_importance) continue;\n if (input.tags?.length) {\n const memTags = new Set(memory.tags);\n if (!input.tags.every(t => memTags.has(t))) continue;\n }\n\n const parts = computeScoreParts(memory, textScore, this.#gitContext, input.query);\n const composite = computeComposite(parts);\n candidates.push({ memory, composite, parts });\n }\n\n // Phase 3: Sort by composite score\n candidates.sort((a, b) => b.composite - a.composite);\n let topN = candidates.slice(0, input.limit);\n\n // Phase 4: Relation expansion — surface connected memories\n const seenIds = new Set(topN.map(c => c.memory.id));\n const expanded = this.#expandWithRelations(topN, input.limit, seenIds, input.min_importance);\n if (expanded.length > 0) {\n topN = [...topN, ...expanded].sort((a, b) => b.composite - a.composite).slice(0, input.limit);\n }\n\n // Phase 5: Build results with explanations, increment access\n return topN.map(({ memory, composite, parts }) => {\n this.#deps.memoryRepo.incrementAccess(memory.id);\n return {\n memory,\n score: composite,\n explanation: parts.relationSource\n ? `Related (${parts.relationSource.type}) to: ${parts.relationSource.title ?? parts.relationSource.id}`\n : buildExplanation(parts, memory),\n };\n });\n }\n\n /**\n * Smart session loading: returns context-matched, recent, and related memories\n * for session start context injection.\n */\n loadSessionContext(input: {\n readonly limit: number;\n readonly project?: string;\n readonly type?: MemoryType;\n }): readonly SessionContextResult[] {\n const contextBudget = Math.floor(input.limit * 0.4);\n const recentBudget = Math.floor(input.limit * 0.4);\n const relatedBudget = input.limit - contextBudget - recentBudget;\n const seenIds = new Set<string>();\n\n const contextMatched = this.#loadContextMatched(contextBudget, input.project, input.type, seenIds);\n const recent = this.#loadRecent(recentBudget, input.project, input.type, seenIds);\n\n const sourceIds = [...contextMatched, ...recent].map(r => r.result.memory.id);\n const related = this.#loadRelatedExpansion(sourceIds, relatedBudget, seenIds);\n\n const all = [...contextMatched, ...recent, ...related];\n for (const entry of all) {\n this.#deps.memoryRepo.incrementInjection(entry.result.memory.id);\n }\n return all;\n }\n\n #loadContextMatched(\n budget: number, project?: string, type?: MemoryType, seenIds?: Set<string>,\n ): SessionContextResult[] {\n if (budget <= 0) return [];\n const candidates = this.#deps.memoryRepo.getRecent(budget * 5, project, type);\n const scored: { memory: Memory; ctxScore: number; composite: number }[] = [];\n\n for (const m of candidates) {\n const ctxScore = computeContextScore(m.context, this.#gitContext, '');\n if (ctxScore <= 0.1) continue;\n const composite = ctxScore * 0.5 + m.importance * 0.3 + computeRecencyScore(m.updatedAt) * 0.2;\n scored.push({ memory: m, ctxScore, composite });\n }\n\n scored.sort((a, b) => b.composite - a.composite);\n const results: SessionContextResult[] = [];\n for (const s of scored.slice(0, budget)) {\n seenIds?.add(s.memory.id);\n results.push({ section: 'context', result: { memory: s.memory, score: s.composite, explanation: 'Context match' } });\n }\n return results;\n }\n\n #loadRecent(\n budget: number, project?: string, type?: MemoryType, seenIds?: Set<string>,\n ): SessionContextResult[] {\n if (budget <= 0) return [];\n const candidates = this.#deps.memoryRepo.getRecent(budget * 2, project, type);\n const results: SessionContextResult[] = [];\n\n for (const m of candidates) {\n if (seenIds?.has(m.id)) continue;\n const score = m.importance * 0.4 + computeRecencyScore(m.updatedAt) * 0.6;\n seenIds?.add(m.id);\n results.push({ section: 'recent', result: { memory: m, score, explanation: 'Recent' } });\n if (results.length >= budget) break;\n }\n return results;\n }\n\n #loadRelatedExpansion(\n sourceIds: readonly string[], budget: number, seenIds: Set<string>,\n ): SessionContextResult[] {\n if (budget <= 0) return [];\n const results: SessionContextResult[] = [];\n\n for (const srcId of sourceIds) {\n const relations = this.#deps.relationRepo.getByMemory(srcId);\n for (const rel of relations) {\n const otherId = rel.sourceId === srcId ? rel.targetId : rel.sourceId;\n if (otherId === srcId || seenIds.has(otherId)) continue;\n\n const other = this.#deps.memoryRepo.getById(otherId);\n if (!other) continue;\n\n const src = this.#deps.memoryRepo.getById(srcId);\n const weight = RELATION_TYPE_WEIGHTS[rel.relationType] ?? 0.5;\n seenIds.add(otherId);\n results.push({\n section: 'related',\n result: {\n memory: other,\n score: other.importance * weight,\n explanation: `Related (${rel.relationType}) to: ${src?.title ?? srcId}`,\n },\n });\n if (results.length >= budget) return results;\n }\n }\n return results;\n }\n\n #expandWithRelations(\n topResults: readonly { memory: Memory; composite: number; parts: ScoreParts }[],\n limit: number,\n seenIds: Set<string>,\n minImportance: number,\n ): { memory: Memory; composite: number; parts: ScoreParts }[] {\n if (topResults.length >= limit) return [];\n\n const expanded: { memory: Memory; composite: number; parts: ScoreParts }[] = [];\n const remaining = limit - topResults.length;\n const sourcesToExpand = topResults.slice(0, 5);\n\n for (const parent of sourcesToExpand) {\n const relations = this.#deps.relationRepo.getByMemory(parent.memory.id);\n for (const rel of relations) {\n const otherId = rel.sourceId === parent.memory.id ? rel.targetId : rel.sourceId;\n if (otherId === parent.memory.id || seenIds.has(otherId)) continue;\n\n const other = this.#deps.memoryRepo.getById(otherId);\n if (!other || other.importance < minImportance) continue;\n\n const weight = RELATION_TYPE_WEIGHTS[rel.relationType] ?? 0.5;\n const composite = parent.composite * 0.7 * weight;\n const parts: ScoreParts = {\n textScore: 0,\n importanceScore: other.importance,\n recencyScore: computeRecencyScore(other.updatedAt),\n accessScore: computeAccessScore(other.accessCount, other.lastAccessed),\n contextScore: 0,\n relationSource: { id: parent.memory.id, title: parent.memory.title, type: rel.relationType },\n };\n\n seenIds.add(otherId);\n expanded.push({ memory: other, composite, parts });\n if (expanded.length >= remaining) return expanded;\n }\n }\n\n return expanded;\n }\n}\n\n// ── Relation Expansion ──────────────────────────────────────\n\nconst RELATION_TYPE_WEIGHTS: Record<RelationType, number> = {\n depends_on: 1.0,\n extends: 0.9,\n implements: 0.9,\n relates_to: 0.7,\n derived_from: 0.6,\n contradicts: 0.3,\n};\n\n// ── FTS5-Only Fallback ───────────────────────────────────────\n\nfunction ftsOnlyScores(ftsResults: readonly { memoryId: string; rank: number }[]): Map<string, number> {\n const scores = new Map<string, number>();\n for (const r of ftsResults) {\n const score = Math.min(1, -r.rank / 20);\n scores.set(r.memoryId, score);\n }\n return scores;\n}\n\n// ── Scoring ───────────────────────────────────────────────────\n\ninterface ScoreParts {\n readonly textScore: number;\n readonly importanceScore: number;\n readonly recencyScore: number;\n readonly accessScore: number;\n readonly contextScore: number;\n readonly relationSource?: { readonly id: string; readonly title: string | null; readonly type: RelationType };\n}\n\nfunction computeScoreParts(\n memory: Memory,\n textScore: number,\n gitContext: GitContext,\n query: string,\n): ScoreParts {\n return {\n textScore,\n importanceScore: memory.importance,\n recencyScore: computeRecencyScore(memory.updatedAt),\n accessScore: computeAccessScore(memory.accessCount, memory.lastAccessed),\n contextScore: computeContextScore(memory.context, gitContext, query),\n };\n}\n\nfunction computeComposite(parts: ScoreParts): number {\n return (\n parts.textScore * SCORING_WEIGHTS.text +\n parts.importanceScore * SCORING_WEIGHTS.importance +\n parts.recencyScore * SCORING_WEIGHTS.recency +\n parts.accessScore * SCORING_WEIGHTS.access +\n parts.contextScore * SCORING_WEIGHTS.context\n );\n}\n\n/**\n * Recency score: 1.0 for today, decays exponentially.\n * Uses a 30-day half-life.\n */\nfunction computeRecencyScore(updatedAt: string): number {\n const ageMs = Date.now() - new Date(updatedAt).getTime();\n const ageDays = ageMs / (1000 * 60 * 60 * 24);\n if (ageDays < 0) return 1.0;\n return Math.exp(-ageDays * Math.LN2 / 30);\n}\n\n/**\n * Access score: logarithmic count x recency of last access.\n */\nfunction computeAccessScore(accessCount: number, lastAccessed: string | null): number {\n if (accessCount <= 0) return 0;\n const countScore = Math.min(1.0, Math.log10(accessCount + 1) / Math.log10(31));\n if (!lastAccessed) return countScore * 0.5;\n const ageDays = (Date.now() - new Date(lastAccessed).getTime()) / 86_400_000;\n const recency = Math.exp(-ageDays * Math.LN2 / 30);\n return countScore * (0.5 + 0.5 * recency);\n}\n\n// ── Explanation ───────────────────────────────────────────────\n\nfunction buildExplanation(parts: ScoreParts, memory: Memory): string {\n const factors: string[] = [];\n\n if (parts.textScore > 0.7) {\n factors.push(`High text match (${(parts.textScore * 100).toFixed(0)}%)`);\n } else if (parts.textScore > 0.3) {\n factors.push(`Moderate text match (${(parts.textScore * 100).toFixed(0)}%)`);\n }\n\n if (memory.importance > 0.7) {\n factors.push('High importance');\n }\n\n if (parts.recencyScore > 0.8) {\n factors.push('Very recent');\n } else if (parts.recencyScore > 0.5) {\n factors.push('Recent');\n }\n\n if (memory.accessCount > 10) {\n factors.push(`Frequently accessed (${memory.accessCount}x)`);\n } else if (memory.accessCount > 3) {\n factors.push(`Accessed ${memory.accessCount}x`);\n }\n\n if (parts.contextScore > 0.3) {\n factors.push('Context match');\n }\n\n const ageDays = Math.floor((Date.now() - new Date(memory.createdAt).getTime()) / 86_400_000);\n const stalenessThreshold = STALENESS_THRESHOLDS[memory.type];\n if (stalenessThreshold !== undefined && ageDays > stalenessThreshold) {\n factors.push(`${ageDays}d old - verify before acting`);\n }\n\n return factors.length > 0 ? factors.join(' + ') : 'Matched query';\n}\n\n// ── Types ────────────────────────────────────────────────────\n\nexport interface SessionContextResult {\n readonly section: 'context' | 'recent' | 'related';\n readonly result: SearchResult;\n}\n\n// Exported for testing\nexport { computeRecencyScore, computeAccessScore, computeComposite, computeScoreParts, ftsOnlyScores };\nexport type { ScoreParts };\n","import { z } from 'zod';\nimport { createHash } from 'node:crypto';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ToolDeps } from './register.js';\nimport { MEMORY_TYPES, MEMORY_SOURCES } from '../types.js';\nimport { getGitContext } from '../utils/git-context.js';\nimport { validateMemoryContent } from '../utils/content-validation.js';\nimport { checkContradiction } from '../utils/contradiction.js';\n\n// In-memory dedup: content hash → timestamp. Catches parallel calls within same request.\nconst recentStores = new Map<string, number>();\nconst pendingStores = new Set<string>();\nconst DEDUP_WINDOW_MS = 10_000;\n\n// Tag normalization: lowercase, strip #, singularize common suffixes, apply aliases\nconst TAG_ALIASES: Record<string, string> = {\n bugs: 'bug', bugfix: 'bug', debugging: 'bug',\n decisions: 'decision', decided: 'decision',\n gotchas: 'gotcha', pitfall: 'gotcha', pitfalls: 'gotcha',\n howtos: 'howto', 'how-to': 'howto',\n patterns: 'pattern',\n todos: 'todo', fixme: 'todo',\n architectures: 'architecture', arch: 'architecture',\n};\n\nfunction normalizeTags(tags: readonly string[]): string[] {\n return [...new Set(tags.map((t) => {\n const stripped = t.replace(/^#/, '').toLowerCase().trim();\n return TAG_ALIASES[stripped] ?? stripped;\n }).filter(Boolean))];\n}\n\n// Auto-tag: detect common patterns in content\nconst AUTO_TAG_PATTERNS: readonly { readonly pattern: RegExp; readonly tag: string }[] = [\n { pattern: /\\b(bug|crash|error|fix(ed)?|broke)\\b/i, tag: 'bug' },\n { pattern: /\\b(decid|chose|decision|went with|picked)\\b/i, tag: 'decision' },\n { pattern: /\\b(gotcha|careful|watch out|trap|pitfall)\\b/i, tag: 'gotcha' },\n { pattern: /\\b(how to|steps to|run|install|deploy|command)\\b/i, tag: 'howto' },\n { pattern: /\\b(pattern|recurring|always|every time)\\b/i, tag: 'pattern' },\n];\n\nfunction autoTag(content: string, existingTags: readonly string[]): string[] {\n const existing = new Set(existingTags);\n const detected: string[] = [];\n for (const { pattern, tag } of AUTO_TAG_PATTERNS) {\n if (!existing.has(tag) && pattern.test(content)) {\n detected.push(tag);\n }\n }\n return detected;\n}\n\nconst inputSchema = {\n type: z.enum(MEMORY_TYPES).describe('Memory type: working, episodic, semantic, procedural, or pattern'),\n content: z.string().min(1).describe('The memory content (aim for ~2000 chars / ~500 tokens). Keep memories concise: capture the decision or insight, not the full context. Split large topics into separate memories.'),\n title: z.string().max(200).optional().describe('Short title for the memory'),\n tags: z.array(z.string()).max(20).default([]).describe('Tags for categorization. Suggested: #bug, #decision, #gotcha, #howto, #pattern'),\n importance: z.number().min(0).max(1).default(0.5).describe('0-0.3 ephemeral, 0.3-0.6 reference, 0.6-0.8 important, 0.8-1.0 critical'),\n context: z.string().optional().describe('JSON: {\"files\": [...], \"branch\": \"...\", \"intent\": \"...\"}. Auto-detected from git if omitted.'),\n source: z.enum(MEMORY_SOURCES).default('manual').describe('How this memory was created'),\n project: z.string().max(200).optional().describe('Project scope (auto-detected from CWD if omitted)'),\n};\n\nexport function registerStore(server: McpServer, deps: ToolDeps): void {\n server.registerTool(\n 'memory_store',\n {\n description:\n 'Store a new memory. Use memory_search first to check for duplicates. '\n + 'Prefer updating existing semantic/procedural memories over creating new ones. '\n + 'Types: episodic (events), semantic (facts), procedural (how-to), pattern (recurring), working (temporary). '\n + 'Importance: 0-0.3 ephemeral, 0.3-0.6 reference, 0.6-0.8 important, 0.8-1.0 critical. '\n + 'Suggested tags: #bug, #decision, #gotcha, #howto, #pattern, #architecture. '\n + 'Context is auto-detected from git (branch, recent files) if omitted. '\n + 'NOTE: A built-in dedup guard prevents identical content from being stored twice within 10 seconds. '\n + 'If you see \"Skipped\" responses, the memory was likely already stored by a parallel call. '\n + 'This is expected behavior, not an error. The data is saved correctly.',\n inputSchema,\n annotations: { idempotentHint: false },\n },\n async (args) => {\n const validation = validateMemoryContent(args.content);\n if (!validation.valid) {\n return {\n content: [{\n type: 'text' as const,\n text: `Rejected: ${validation.reason}`,\n }],\n isError: true,\n };\n }\n\n const context = args.context ?? JSON.stringify(getGitContext());\n const project = args.project ?? deps.project ?? undefined;\n\n // Dedup: in-memory guard catches parallel calls within same request.\n // Uses a pending Set to catch calls that arrive in the same tick.\n const contentHash = createHash('sha256').update(args.content).digest('hex');\n const now = Date.now();\n const lastStored = recentStores.get(contentHash);\n if (lastStored && (now - lastStored) < DEDUP_WINDOW_MS) {\n return {\n content: [{ type: 'text' as const, text: 'Skipped: identical memory already exists (stored moments ago).' }],\n };\n }\n if (pendingStores.has(contentHash)) {\n return {\n content: [{ type: 'text' as const, text: 'Skipped: identical memory is being stored by another call.' }],\n };\n }\n pendingStores.add(contentHash);\n // Prune old entries\n for (const [key, ts] of recentStores) {\n if (now - ts > DEDUP_WINDOW_MS) recentStores.delete(key);\n }\n\n // Contradiction detection\n const contradictions: { id: string; title: string | null }[] = [];\n try {\n const existing = await deps.retrievalService.search({\n query: args.content.slice(0, 200),\n limit: 3,\n min_importance: 0,\n project,\n });\n for (const result of existing) {\n if (result.score > 0.6 && checkContradiction(args.content, result.memory.content)) {\n contradictions.push({ id: result.memory.id, title: result.memory.title });\n }\n }\n } catch {\n // Contradiction check is best-effort\n }\n\n // Normalize tags + auto-tag from content\n const normalizedTags = normalizeTags(args.tags);\n const autoTags = autoTag(args.content, normalizedTags);\n const finalTags = [...new Set([...normalizedTags, ...autoTags])];\n\n const memory = deps.memoryRepo.create(\n {\n type: args.type,\n content: args.content,\n title: args.title,\n tags: finalTags,\n importance: args.importance,\n context,\n source: args.source,\n project,\n },\n null,\n );\n\n // Mark as stored (dedup window starts now)\n recentStores.set(contentHash, Date.now());\n pendingStores.delete(contentHash);\n\n // Create contradiction relations\n for (const c of contradictions) {\n try {\n deps.relationRepo.create(memory.id, c.id, 'contradicts');\n } catch {\n // Relation creation is best-effort\n }\n }\n\n const parts: string[] = [\n `Stored memory ${memory.id} (type: ${memory.type}, importance: ${memory.importance})`,\n ];\n\n for (const warning of validation.warnings) {\n parts.push(`Warning: ${warning}`);\n }\n\n for (const c of contradictions) {\n parts.push(`Warning: potential contradiction with memory ${c.id}${c.title ? ` (\"${c.title}\")` : ''}. Linked with 'contradicts' relation.`);\n }\n\n return {\n content: [{\n type: 'text' as const,\n text: parts.join('\\n'),\n }],\n };\n },\n );\n}\n","// ── Content Validation for memory_store ─────────────────────\n\nexport interface ValidationResult {\n readonly valid: boolean;\n readonly reason?: string;\n readonly warnings: readonly string[];\n}\n\nconst SOFT_LENGTH_LIMIT = 1500;\nconst HARD_LENGTH_LIMIT = 5000;\nconst CODE_RATIO_THRESHOLD = 0.5;\n\n/**\n * Validate memory content before storage.\n * Returns hard rejections (don't store) and soft warnings (store but warn).\n */\nexport function validateMemoryContent(content: string): ValidationResult {\n const warnings: string[] = [];\n\n // Hard reject: git log output\n if (isGitLog(content)) {\n return { valid: false, reason: 'Content looks like raw git log output. Use git log directly — don\\'t store it as memory.', warnings: [] };\n }\n\n // Hard reject: code-heavy content\n if (isCodeHeavy(content)) {\n return { valid: false, reason: 'Content is >50% code blocks. Code belongs in files, not memory. Store the insight or decision instead.', warnings: [] };\n }\n\n // Hard reject: too long\n if (content.length > HARD_LENGTH_LIMIT) {\n return { valid: false, reason: `Content is ${content.length} chars (limit: ${HARD_LENGTH_LIMIT}). Break it into smaller, atomic memories.`, warnings: [] };\n }\n\n // Soft warn: lengthy\n if (content.length > SOFT_LENGTH_LIMIT) {\n warnings.push(`Content is ${content.length} chars. Shorter memories (<${SOFT_LENGTH_LIMIT} chars) are easier to retrieve and less likely to decay.`);\n }\n\n return { valid: true, warnings };\n}\n\n/**\n * Content is >50% fenced code blocks.\n */\nexport function isCodeHeavy(content: string): boolean {\n const fencedBlockPattern = /```[\\s\\S]*?```/g;\n let codeChars = 0;\n let match: RegExpExecArray | null;\n\n while ((match = fencedBlockPattern.exec(content)) !== null) {\n codeChars += match[0].length;\n }\n\n return content.length > 0 && codeChars / content.length > CODE_RATIO_THRESHOLD;\n}\n\n/**\n * Content looks like raw git log output.\n * Matches patterns like \"commit abc123\\nAuthor: ...\\nDate: ...\"\n */\nexport function isGitLog(content: string): boolean {\n const lines = content.split('\\n');\n let gitLogLines = 0;\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (/^commit\\s+[0-9a-f]{7,40}$/i.test(trimmed)) gitLogLines++;\n else if (/^Author:\\s+.+/i.test(trimmed)) gitLogLines++;\n else if (/^Date:\\s+.+/i.test(trimmed)) gitLogLines++;\n else if (/^[0-9a-f]{7,12}\\s+\\S+/i.test(trimmed) && trimmed.length < 200) gitLogLines++;\n }\n\n // At least 3 git-log-like lines and they make up >30% of non-empty lines\n const nonEmptyLines = lines.filter(l => l.trim().length > 0).length;\n return gitLogLines >= 3 && nonEmptyLines > 0 && gitLogLines / nonEmptyLines > 0.3;\n}\n","// ── Contradiction Detection (keyword-overlap heuristic) ─────\n\nconst NEGATION_PATTERNS = [\n /\\bnot\\b/i,\n /\\bno longer\\b/i,\n /\\binstead of\\b/i,\n /\\breplaced\\b/i,\n /\\bremoved\\b/i,\n /\\bdon'?t\\b/i,\n /\\bwon'?t\\b/i,\n /\\bshouldn'?t\\b/i,\n /\\bdeprecated\\b/i,\n /\\bdisabled\\b/i,\n /\\bstopped\\b/i,\n /\\bavoid\\b/i,\n /\\bnever\\b/i,\n /\\bwithout\\b/i,\n];\n\nconst KEYWORD_OVERLAP_THRESHOLD = 0.4;\nconst MIN_KEYWORD_LENGTH = 3;\nconst STOP_WORDS = new Set([\n 'the', 'and', 'for', 'are', 'but', 'not', 'you', 'all', 'can', 'had',\n 'her', 'was', 'one', 'our', 'out', 'has', 'have', 'been', 'from', 'that',\n 'this', 'with', 'they', 'will', 'each', 'make', 'like', 'than', 'them',\n 'then', 'what', 'when', 'into', 'more', 'some', 'such', 'also', 'use',\n 'used', 'using', 'should', 'would', 'could', 'about', 'which', 'their',\n 'there', 'these', 'those', 'does', 'done', 'just', 'very',\n]);\n\n/**\n * Extract meaningful keywords from text.\n */\nfunction extractKeywords(text: string): ReadonlySet<string> {\n const words = text.toLowerCase().match(/[a-z][a-z0-9_-]+/g) ?? [];\n return new Set(\n words.filter(w => w.length >= MIN_KEYWORD_LENGTH && !STOP_WORDS.has(w)),\n );\n}\n\n/**\n * Check if new content potentially contradicts existing content.\n *\n * Heuristic: high keyword overlap + negation markers = likely contradiction.\n * Not perfect, but catches the common case of \"we used X\" vs \"we no longer use X\".\n */\nexport function checkContradiction(newContent: string, existingContent: string): boolean {\n const newKeywords = extractKeywords(newContent);\n const existingKeywords = extractKeywords(existingContent);\n\n if (newKeywords.size === 0 || existingKeywords.size === 0) return false;\n\n // Compute Jaccard-like overlap: |intersection| / |smaller set|\n let overlap = 0;\n for (const kw of newKeywords) {\n if (existingKeywords.has(kw)) overlap++;\n }\n\n const smallerSize = Math.min(newKeywords.size, existingKeywords.size);\n const overlapRatio = overlap / smallerSize;\n\n if (overlapRatio < KEYWORD_OVERLAP_THRESHOLD) return false;\n\n // High overlap — check for negation markers in the NEW content only.\n return NEGATION_PATTERNS.some(pattern => pattern.test(newContent));\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ToolDeps } from './register.js';\nimport { MEMORY_TYPES } from '../types.js';\n\nconst inputSchema = {\n query: z.string().min(1).max(500).describe('Search query (natural language or keywords)'),\n id: z.string().optional().describe('Direct lookup by memory ID (bypasses search)'),\n type: z.enum(MEMORY_TYPES).optional().describe('Filter by memory type'),\n tags: z.array(z.string()).max(10).optional().describe('Filter to memories containing ALL of these tags'),\n limit: z.number().int().min(1).max(50).default(10).describe('Maximum results to return'),\n min_importance: z.number().min(0).max(1).default(0).describe('Minimum importance threshold'),\n};\n\nexport function registerSearch(server: McpServer, deps: ToolDeps): void {\n server.registerTool(\n 'memory_search',\n {\n description:\n 'Search memories by keyword match, context relevance, and relation graph. '\n + 'Returns up to `limit` results ranked by composite score (text match, importance, recency, access frequency, git context). '\n + 'Related memories are automatically surfaced via 1-hop graph expansion. '\n + 'Pass `id` for direct lookup. Use `type` and `tags` to filter.',\n inputSchema,\n annotations: { readOnlyHint: true, idempotentHint: true },\n },\n async (args) => {\n const results = await deps.retrievalService.search({\n query: args.query,\n id: args.id,\n type: args.type,\n tags: args.tags,\n limit: args.limit,\n min_importance: args.min_importance,\n project: deps.project ?? undefined,\n });\n\n if (results.length === 0) {\n return {\n content: [{ type: 'text' as const, text: 'No memories found matching your query.' }],\n };\n }\n\n const formatted = results.map((r, i) => ({\n rank: i + 1,\n id: r.memory.id,\n type: r.memory.type,\n title: r.memory.title,\n content: r.memory.content,\n score: Math.round(r.score * 100) / 100,\n explanation: r.explanation,\n importance: r.memory.importance,\n tags: r.memory.tags,\n accessCount: r.memory.accessCount,\n createdAt: r.memory.createdAt,\n }));\n\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify(formatted, null, 2),\n }],\n };\n },\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ToolDeps } from './register.js';\nimport { memoryNotFound, formatMcpError } from '../utils/errors.js';\n\nconst inputSchema = {\n id: z.string().describe('ID of the memory to forget'),\n hard_delete: z.boolean().default(false).describe('true = permanent delete, false = set importance to 0 (soft delete)'),\n};\n\nexport function registerForget(server: McpServer, deps: ToolDeps): void {\n server.registerTool(\n 'memory_forget',\n {\n description:\n 'Forget a memory. By default, soft-deletes (sets importance to 0, allowing natural decay). '\n + 'Pass hard_delete=true to permanently remove. Use memory_search to find the ID first.',\n inputSchema,\n annotations: { destructiveHint: true, idempotentHint: true },\n },\n async (args) => {\n const memory = deps.memoryRepo.getById(args.id);\n if (!memory) {\n return formatMcpError(memoryNotFound(args.id));\n }\n\n if (deps.project && memory.project !== null && memory.project !== deps.project) {\n return formatMcpError({\n what: `Memory ${args.id} belongs to project \"${memory.project}\".`,\n why: `Current project is \"${deps.project}\". Cross-project deletion is not allowed.`,\n fix: 'Switch to the correct project or use a global context.',\n });\n }\n\n if (args.hard_delete) {\n deps.memoryRepo.hardDelete(args.id);\n return {\n content: [{\n type: 'text' as const,\n text: `Permanently deleted memory ${args.id} (\"${memory.title ?? memory.content.slice(0, 50)}\")`,\n }],\n };\n }\n\n deps.memoryRepo.softDelete(args.id);\n return {\n content: [{\n type: 'text' as const,\n text: `Soft-deleted memory ${args.id} (importance set to 0, will decay naturally)`,\n }],\n };\n },\n );\n}\n","// ── Structured Error Formatting ──────────────────────────────\n// Every error answers: What happened? Why? What to do?\n\nexport interface StructuredError {\n readonly what: string;\n readonly why: string;\n readonly fix: string;\n}\n\nexport function formatError(err: StructuredError): string {\n return `${err.what}\\nWhy: ${err.why}\\nFix: ${err.fix}`;\n}\n\nexport function formatMcpError(err: StructuredError): { isError: true; content: [{ type: 'text'; text: string }] } {\n return {\n isError: true,\n content: [{ type: 'text' as const, text: formatError(err) }],\n };\n}\n\n// ── Common Error Templates ───────────────────────────────────\n\nexport function memoryNotFound(id: string): StructuredError {\n return {\n what: `Memory \"${id}\" not found.`,\n why: 'The ID may be incorrect, or the memory was deleted or pruned.',\n fix: 'Use memory_search to find valid IDs.',\n };\n}\n\nexport function databaseLocked(): StructuredError {\n return {\n what: 'Database is temporarily locked.',\n why: 'Another process is writing to the database (SQLITE_BUSY).',\n fix: 'Retry in a moment. If persistent, run: claude-launchpad doctor --fix',\n };\n}\n\nexport function databaseCorrupt(): StructuredError {\n return {\n what: 'Database integrity check failed.',\n why: 'The database file may be corrupted (disk error, incomplete write).',\n fix: 'Run: claude-launchpad doctor --fix (creates backup, reinitializes DB)',\n };\n}\n\nexport function diskFull(): StructuredError {\n return {\n what: 'Disk write failed — not enough space.',\n why: 'The disk partition containing ~/.agentic-memory is full.',\n fix: 'Free disk space, then run: claude-launchpad doctor --fix',\n };\n}\n\nexport function invalidInput(field: string, reason: string): StructuredError {\n return {\n what: `Invalid input: ${field}`,\n why: reason,\n fix: 'Check the parameter value and try again.',\n };\n}\n\n// ── SQLite Retry Logic ───────────────────────────────────────\n\nconst RETRY_DELAYS = [100, 200, 400] as const;\n\nexport function withRetry<T>(fn: () => T, label: string): T {\n for (let attempt = 0; attempt < RETRY_DELAYS.length; attempt++) {\n try {\n return fn();\n } catch (err) {\n if (isSqliteBusy(err) && attempt < RETRY_DELAYS.length - 1) {\n const delay = RETRY_DELAYS[attempt]!;\n process.stderr.write(`[memory] ${label}: SQLITE_BUSY, retrying in ${delay}ms\\n`);\n sleepSync(delay);\n continue;\n }\n throw err;\n }\n }\n // Unreachable, but TypeScript needs it\n throw new Error(`${label}: exhausted retries`);\n}\n\nfunction isSqliteBusy(err: unknown): boolean {\n if (err instanceof Error) {\n return err.message.includes('SQLITE_BUSY') || err.message.includes('database is locked');\n }\n return false;\n}\n\nfunction sleepSync(ms: number): void {\n Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ToolDeps } from './register.js';\nimport { RELATION_TYPES } from '../types.js';\nimport { memoryNotFound, formatMcpError } from '../utils/errors.js';\n\nconst inputSchema = {\n source_id: z.string().describe('ID of the source memory'),\n target_id: z.string().describe('ID of the target memory'),\n relation_type: z.enum(RELATION_TYPES).describe(\n 'Type of relation: relates_to, depends_on, contradicts, extends, implements, derived_from'\n ),\n};\n\nexport function registerRelate(server: McpServer, deps: ToolDeps): void {\n server.registerTool(\n 'memory_relate',\n {\n description:\n 'Create a typed relation between two memories. '\n + 'Relations affect retrieval ranking (connected memories decay slower). '\n + 'Types: relates_to, depends_on, contradicts, extends, implements, derived_from.',\n inputSchema,\n annotations: { idempotentHint: true },\n },\n async (args) => {\n if (args.source_id === args.target_id) {\n return formatMcpError({\n what: 'Cannot create self-relation.',\n why: 'source_id and target_id are the same memory.',\n fix: 'Provide two different memory IDs.',\n });\n }\n\n const source = deps.memoryRepo.getById(args.source_id);\n if (!source) {\n return formatMcpError(memoryNotFound(args.source_id));\n }\n\n const target = deps.memoryRepo.getById(args.target_id);\n if (!target) {\n return formatMcpError(memoryNotFound(args.target_id));\n }\n\n if (deps.project) {\n for (const mem of [source, target]) {\n if (mem.project !== null && mem.project !== deps.project) {\n return formatMcpError({\n what: `Memory ${mem.id} belongs to project \"${mem.project}\".`,\n why: `Current project is \"${deps.project}\". Cross-project relations are not allowed.`,\n fix: 'Both memories must belong to the same project.',\n });\n }\n }\n }\n\n const created = deps.relationRepo.create(args.source_id, args.target_id, args.relation_type);\n\n if (!created) {\n return {\n content: [{\n type: 'text' as const,\n text: `Relation already exists: ${args.source_id} --[${args.relation_type}]--> ${args.target_id}`,\n }],\n };\n }\n\n return {\n content: [{\n type: 'text' as const,\n text: `Created relation: \"${source.title ?? source.content.slice(0, 40)}\" --[${args.relation_type}]--> \"${target.title ?? target.content.slice(0, 40)}\"`,\n }],\n };\n },\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ToolDeps } from './register.js';\nimport { MEMORY_TYPES } from '../types.js';\nimport type { MemoryStats } from '../types.js';\nimport { statSync } from 'node:fs';\nimport { join } from 'node:path';\n\nexport function registerStats(server: McpServer, deps: ToolDeps): void {\n server.registerTool(\n 'memory_stats',\n {\n description:\n 'Show memory dashboard: total count, breakdown by type, storage size, '\n + 'and most-injected memories. No arguments needed.',\n annotations: { readOnlyHint: true, idempotentHint: true },\n },\n async () => {\n const countByType = deps.memoryRepo.countByType();\n const total = deps.memoryRepo.count();\n const topInjected = deps.memoryRepo.topInjected(5);\n const totalRelations = deps.relationRepo.count();\n\n let dbSizeBytes = 0;\n try {\n const dbPath = join(deps.dataDir, 'memory.db');\n dbSizeBytes = statSync(dbPath).size;\n } catch {\n // :memory: or file not found\n }\n\n const { oldest, newest } = deps.memoryRepo.dateRange();\n\n const stats: MemoryStats = {\n totalMemories: total,\n byType: Object.fromEntries(\n MEMORY_TYPES.map(t => [t, countByType[t] ?? 0])\n ) as Record<string, number>,\n totalRelations,\n dbSizeBytes,\n oldestMemory: oldest,\n newestMemory: newest,\n topInjected,\n };\n\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify(stats, null, 2),\n }],\n };\n },\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ToolDeps } from './register.js';\nimport { MEMORY_TYPES } from '../types.js';\n\nconst inputSchema = {\n limit: z.number().int().min(1).max(50).default(10).describe('Maximum memories to return'),\n type: z.enum(MEMORY_TYPES).optional().describe('Filter by memory type'),\n};\n\nexport function registerRecent(server: McpServer, deps: ToolDeps): void {\n server.registerTool(\n 'memory_recent',\n {\n description:\n 'Load session context: returns context-matched, recent, and related memories. '\n + 'Call this at the start of every session to load context from previous work. '\n + 'Results are grouped into sections: contextMatched (matching current branch/files), '\n + 'recent (most recent), and related (connected via relations).',\n inputSchema,\n annotations: { readOnlyHint: true, idempotentHint: true },\n },\n async (args) => {\n const results = deps.retrievalService.loadSessionContext({\n limit: args.limit,\n project: deps.project ?? undefined,\n type: args.type,\n });\n\n if (results.length === 0) {\n return {\n content: [{ type: 'text' as const, text: 'No memories found for this project.' }],\n };\n }\n\n const formatEntry = (entry: typeof results[number], rank: number) => ({\n rank,\n section: entry.section,\n id: entry.result.memory.id,\n type: entry.result.memory.type,\n title: entry.result.memory.title,\n content: entry.result.memory.content,\n importance: entry.result.memory.importance,\n tags: entry.result.memory.tags,\n score: Math.round(entry.result.score * 100) / 100,\n explanation: entry.result.explanation,\n createdAt: entry.result.memory.createdAt,\n });\n\n const contextMatched = results.filter(r => r.section === 'context').map((r, i) => formatEntry(r, i + 1));\n const recent = results.filter(r => r.section === 'recent').map((r, i) => formatEntry(r, i + 1));\n const related = results.filter(r => r.section === 'related').map((r, i) => formatEntry(r, i + 1));\n\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify({ contextMatched, recent, related }, null, 2),\n }],\n };\n },\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ToolDeps } from './register.js';\n\nconst inputSchema = {\n id: z.string().describe('Memory ID to update (use memory_search to find it)'),\n title: z.string().max(200).optional().describe('Updated title'),\n content: z.string().min(1).max(10000).optional().describe('Updated content'),\n tags: z.array(z.string()).max(20).optional().describe('Updated tags'),\n importance: z.number().min(0).max(1).optional().describe('Updated importance (0-1)'),\n context: z.string().optional().describe('Updated context JSON'),\n};\n\nexport function registerUpdate(server: McpServer, deps: ToolDeps): void {\n server.registerTool(\n 'memory_update',\n {\n description:\n 'Update an existing memory in-place. Preserves access count, injection count, and creation date. '\n + 'Use memory_search to find the ID first. At least one field must be provided.',\n inputSchema,\n annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true },\n },\n async (args) => {\n const hasUpdate = args.title !== undefined || args.content !== undefined\n || args.tags !== undefined || args.importance !== undefined\n || args.context !== undefined;\n\n if (!hasUpdate) {\n return {\n content: [{ type: 'text' as const, text: 'No fields to update. Provide at least one of: title, content, tags, importance, context.' }],\n isError: true,\n };\n }\n\n const existing = deps.memoryRepo.getById(args.id);\n if (!existing) {\n return {\n content: [{ type: 'text' as const, text: `Memory ${args.id} not found.` }],\n isError: true,\n };\n }\n\n const updated = deps.memoryRepo.updateContent(args.id, {\n title: args.title,\n content: args.content,\n tags: args.tags,\n importance: args.importance,\n context: args.context,\n });\n\n if (!updated) {\n return {\n content: [{ type: 'text' as const, text: `Failed to update memory ${args.id}.` }],\n isError: true,\n };\n }\n\n const fields = [\n args.title !== undefined && 'title',\n args.content !== undefined && 'content',\n args.tags !== undefined && 'tags',\n args.importance !== undefined && 'importance',\n args.context !== undefined && 'context',\n ].filter(Boolean).join(', ');\n\n return {\n content: [{ type: 'text' as const, text: `Updated memory ${args.id} (fields: ${fields})` }],\n };\n },\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { MemoryRepo } from '../storage/memory-repo.js';\nimport type { RelationRepo } from '../storage/relation-repo.js';\nimport type { RetrievalService } from '../services/retrieval-service.js';\nimport { registerStore } from './store.js';\nimport { registerSearch } from './search.js';\nimport { registerForget } from './forget.js';\nimport { registerRelate } from './relate.js';\nimport { registerStats } from './stats.js';\nimport { registerRecent } from './recent.js';\nimport { registerUpdate } from './update.js';\n\nexport interface ToolDeps {\n readonly memoryRepo: MemoryRepo;\n readonly relationRepo: RelationRepo;\n readonly retrievalService: RetrievalService;\n readonly dataDir: string;\n readonly project: string | null;\n}\n\nexport function registerTools(server: McpServer, deps: ToolDeps): void {\n registerStore(server, deps);\n registerSearch(server, deps);\n registerRecent(server, deps);\n registerForget(server, deps);\n registerRelate(server, deps);\n registerStats(server, deps);\n registerUpdate(server, deps);\n}\n"],"mappings":"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","names":["z","inputSchema","z","z","inputSchema","z","z","inputSchema","z","z","inputSchema","z","z","inputSchema"]}
1
+ {"version":3,"sources":["../../../src/commands/memory/server.ts","../../../src/commands/memory/services/retrieval-service.ts","../../../src/commands/memory/tools/store.ts","../../../src/commands/memory/utils/content-validation.ts","../../../src/commands/memory/utils/contradiction.ts","../../../src/commands/memory/tools/search.ts","../../../src/commands/memory/tools/forget.ts","../../../src/commands/memory/utils/errors.ts","../../../src/commands/memory/tools/relate.ts","../../../src/commands/memory/tools/stats.ts","../../../src/commands/memory/tools/recent.ts","../../../src/commands/memory/tools/update.ts","../../../src/commands/memory/tools/register.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\n\nconst require = createRequire(import.meta.url);\nconst { version } = require('../../../package.json') as { version: string };\nimport { createDatabase, closeDatabase } from './storage/database.js';\nimport { migrate } from './storage/migrator.js';\nimport { MemoryRepo } from './storage/memory-repo.js';\nimport { RelationRepo } from './storage/relation-repo.js';\nimport { SearchRepo } from './storage/search-repo.js';\nimport { RetrievalService } from './services/retrieval-service.js';\nimport { loadConfig, resolveDataDir } from './config.js';\nimport type { Config } from './config.js';\nimport { registerTools } from './tools/register.js';\nimport { detectProject } from './utils/project.js';\n\nexport interface ServerDeps {\n readonly config: Config;\n}\n\nexport async function startServer(deps?: Partial<ServerDeps>): Promise<void> {\n const config = deps?.config ?? loadConfig();\n const dataDir = resolveDataDir(config.dataDir);\n\n const db = createDatabase({ dataDir });\n migrate(db);\n\n const memoryRepo = new MemoryRepo(db);\n const relationRepo = new RelationRepo(db);\n const searchRepo = new SearchRepo(db);\n\n const retrievalService = new RetrievalService({\n memoryRepo,\n relationRepo,\n searchRepo,\n });\n\n const server = new McpServer(\n { name: 'agentic-memory', version },\n {\n instructions:\n 'This is your knowledge base — persistent context that survives across sessions. '\n + 'Search before storing to avoid duplicates. Update existing memories instead of creating new ones. '\n + 'Store decisions, patterns, and insights — capture WHY, not just WHAT. '\n + 'Only save what future sessions will need. NEVER store secrets, API keys, or passwords. '\n + 'Session context is injected automatically at startup — no need to call memory_recent.',\n },\n );\n\n const project = detectProject(process.cwd());\n\n registerTools(server, { memoryRepo, relationRepo, retrievalService, dataDir, project });\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n\n const shutdown = async () => {\n await server.close();\n closeDatabase(db);\n process.exit(0);\n };\n process.on('SIGINT', () => void shutdown());\n process.on('SIGTERM', () => void shutdown());\n}\n\n// Auto-start when invoked directly as MCP server entry point\nstartServer().catch((err) => {\n process.stderr.write(`[agentic-memory] ${err}\\n`);\n process.exit(1);\n});\n","import type { Memory, MemoryType, SearchResult, SearchInput, RelationType } from '../types.js';\nimport type { MemoryRepo } from '../storage/memory-repo.js';\nimport type { RelationRepo } from '../storage/relation-repo.js';\nimport type { SearchRepo } from '../storage/search-repo.js';\nimport { SCORING_WEIGHTS } from '../config.js';\nimport { type GitContext, getGitContext, computeContextScore } from '../utils/git-context.js';\n\nconst STALENESS_THRESHOLDS = {\n working: 1,\n episodic: 7,\n pattern: 14,\n semantic: 30,\n procedural: 90,\n} as const;\n\nexport interface RetrievalDeps {\n readonly memoryRepo: MemoryRepo;\n readonly relationRepo: RelationRepo;\n readonly searchRepo: SearchRepo;\n readonly gitContext?: GitContext;\n}\n\nexport class RetrievalService {\n readonly #deps: RetrievalDeps;\n readonly #gitContext: GitContext;\n\n constructor(deps: RetrievalDeps) {\n this.#deps = deps;\n this.#gitContext = deps.gitContext ?? getGitContext();\n }\n\n /**\n * FTS5 keyword search with multi-signal scoring, context awareness,\n * and relation-based graph expansion.\n */\n async search(input: SearchInput): Promise<readonly SearchResult[]> {\n // Direct ID lookup\n if (input.id) {\n const memory = this.#deps.memoryRepo.getById(input.id);\n if (!memory) return [];\n this.#deps.memoryRepo.incrementAccess(input.id);\n return [{\n memory,\n score: 1.0,\n explanation: 'Direct lookup by ID',\n }];\n }\n\n // Phase 1: FTS5 keyword search\n const ftsResults = this.#deps.searchRepo.searchFts({\n query: input.query,\n limit: input.limit * 3,\n type: input.type,\n minImportance: input.min_importance,\n project: input.project,\n });\n\n const textScores = ftsOnlyScores(ftsResults);\n if (textScores.size === 0) return [];\n\n // Phase 2: Load memories and compute composite scores\n const candidates: { memory: Memory; composite: number; parts: ScoreParts }[] = [];\n\n for (const [memoryId, textScore] of textScores) {\n const memory = this.#deps.memoryRepo.getById(memoryId);\n if (!memory) continue;\n if (input.type && memory.type !== input.type) continue;\n if (memory.importance < input.min_importance) continue;\n if (input.tags?.length) {\n const memTags = new Set(memory.tags);\n if (!input.tags.every(t => memTags.has(t))) continue;\n }\n\n const parts = computeScoreParts(memory, textScore, this.#gitContext, input.query);\n const composite = computeComposite(parts);\n candidates.push({ memory, composite, parts });\n }\n\n // Phase 3: Sort by composite score\n candidates.sort((a, b) => b.composite - a.composite);\n let topN = candidates.slice(0, input.limit);\n\n // Phase 4: Relation expansion — surface connected memories\n const seenIds = new Set(topN.map(c => c.memory.id));\n const expanded = this.#expandWithRelations(topN, input.limit, seenIds, input.min_importance);\n if (expanded.length > 0) {\n topN = [...topN, ...expanded].sort((a, b) => b.composite - a.composite).slice(0, input.limit);\n }\n\n // Phase 5: Build results with explanations, increment access\n return topN.map(({ memory, composite, parts }) => {\n this.#deps.memoryRepo.incrementAccess(memory.id);\n return {\n memory,\n score: composite,\n explanation: parts.relationSource\n ? `Related (${parts.relationSource.type}) to: ${parts.relationSource.title ?? parts.relationSource.id}`\n : buildExplanation(parts, memory),\n };\n });\n }\n\n /**\n * Smart session loading: returns context-matched, recent, and related memories\n * for session start context injection.\n */\n loadSessionContext(input: {\n readonly limit: number;\n readonly project?: string;\n readonly type?: MemoryType;\n }): readonly SessionContextResult[] {\n const contextBudget = Math.floor(input.limit * 0.4);\n const recentBudget = Math.floor(input.limit * 0.4);\n const relatedBudget = input.limit - contextBudget - recentBudget;\n const seenIds = new Set<string>();\n\n const contextMatched = this.#loadContextMatched(contextBudget, input.project, input.type, seenIds);\n const recent = this.#loadRecent(recentBudget, input.project, input.type, seenIds);\n\n const sourceIds = [...contextMatched, ...recent].map(r => r.result.memory.id);\n const related = this.#loadRelatedExpansion(sourceIds, relatedBudget, seenIds);\n\n const all = [...contextMatched, ...recent, ...related];\n for (const entry of all) {\n this.#deps.memoryRepo.incrementInjection(entry.result.memory.id);\n }\n return all;\n }\n\n #loadContextMatched(\n budget: number, project?: string, type?: MemoryType, seenIds?: Set<string>,\n ): SessionContextResult[] {\n if (budget <= 0) return [];\n const candidates = this.#deps.memoryRepo.getRecent(budget * 5, project, type);\n const scored: { memory: Memory; ctxScore: number; composite: number }[] = [];\n\n for (const m of candidates) {\n const ctxScore = computeContextScore(m.context, this.#gitContext, '');\n if (ctxScore <= 0.1) continue;\n const composite = ctxScore * 0.5 + m.importance * 0.3 + computeRecencyScore(m.updatedAt) * 0.2;\n scored.push({ memory: m, ctxScore, composite });\n }\n\n scored.sort((a, b) => b.composite - a.composite);\n const results: SessionContextResult[] = [];\n for (const s of scored.slice(0, budget)) {\n seenIds?.add(s.memory.id);\n results.push({ section: 'context', result: { memory: s.memory, score: s.composite, explanation: 'Context match' } });\n }\n return results;\n }\n\n #loadRecent(\n budget: number, project?: string, type?: MemoryType, seenIds?: Set<string>,\n ): SessionContextResult[] {\n if (budget <= 0) return [];\n const candidates = this.#deps.memoryRepo.getRecent(budget * 2, project, type);\n const results: SessionContextResult[] = [];\n\n for (const m of candidates) {\n if (seenIds?.has(m.id)) continue;\n const score = m.importance * 0.4 + computeRecencyScore(m.updatedAt) * 0.6;\n seenIds?.add(m.id);\n results.push({ section: 'recent', result: { memory: m, score, explanation: 'Recent' } });\n if (results.length >= budget) break;\n }\n return results;\n }\n\n #loadRelatedExpansion(\n sourceIds: readonly string[], budget: number, seenIds: Set<string>,\n ): SessionContextResult[] {\n if (budget <= 0) return [];\n const results: SessionContextResult[] = [];\n\n for (const srcId of sourceIds) {\n const relations = this.#deps.relationRepo.getByMemory(srcId);\n for (const rel of relations) {\n const otherId = rel.sourceId === srcId ? rel.targetId : rel.sourceId;\n if (otherId === srcId || seenIds.has(otherId)) continue;\n\n const other = this.#deps.memoryRepo.getById(otherId);\n if (!other) continue;\n\n const src = this.#deps.memoryRepo.getById(srcId);\n const weight = RELATION_TYPE_WEIGHTS[rel.relationType] ?? 0.5;\n seenIds.add(otherId);\n results.push({\n section: 'related',\n result: {\n memory: other,\n score: other.importance * weight,\n explanation: `Related (${rel.relationType}) to: ${src?.title ?? srcId}`,\n },\n });\n if (results.length >= budget) return results;\n }\n }\n return results;\n }\n\n #expandWithRelations(\n topResults: readonly { memory: Memory; composite: number; parts: ScoreParts }[],\n limit: number,\n seenIds: Set<string>,\n minImportance: number,\n ): { memory: Memory; composite: number; parts: ScoreParts }[] {\n if (topResults.length >= limit) return [];\n\n const expanded: { memory: Memory; composite: number; parts: ScoreParts }[] = [];\n const remaining = limit - topResults.length;\n const sourcesToExpand = topResults.slice(0, 5);\n\n for (const parent of sourcesToExpand) {\n const relations = this.#deps.relationRepo.getByMemory(parent.memory.id);\n for (const rel of relations) {\n const otherId = rel.sourceId === parent.memory.id ? rel.targetId : rel.sourceId;\n if (otherId === parent.memory.id || seenIds.has(otherId)) continue;\n\n const other = this.#deps.memoryRepo.getById(otherId);\n if (!other || other.importance < minImportance) continue;\n\n const weight = RELATION_TYPE_WEIGHTS[rel.relationType] ?? 0.5;\n const composite = parent.composite * 0.7 * weight;\n const parts: ScoreParts = {\n textScore: 0,\n importanceScore: other.importance,\n recencyScore: computeRecencyScore(other.updatedAt),\n accessScore: computeAccessScore(other.accessCount, other.lastAccessed),\n contextScore: 0,\n relationSource: { id: parent.memory.id, title: parent.memory.title, type: rel.relationType },\n };\n\n seenIds.add(otherId);\n expanded.push({ memory: other, composite, parts });\n if (expanded.length >= remaining) return expanded;\n }\n }\n\n return expanded;\n }\n}\n\n// ── Relation Expansion ──────────────────────────────────────\n\nconst RELATION_TYPE_WEIGHTS: Record<RelationType, number> = {\n depends_on: 1.0,\n extends: 0.9,\n implements: 0.9,\n relates_to: 0.7,\n derived_from: 0.6,\n contradicts: 0.3,\n};\n\n// ── FTS5-Only Fallback ───────────────────────────────────────\n\nfunction ftsOnlyScores(ftsResults: readonly { memoryId: string; rank: number }[]): Map<string, number> {\n const scores = new Map<string, number>();\n for (const r of ftsResults) {\n const score = Math.min(1, -r.rank / 20);\n scores.set(r.memoryId, score);\n }\n return scores;\n}\n\n// ── Scoring ───────────────────────────────────────────────────\n\ninterface ScoreParts {\n readonly textScore: number;\n readonly importanceScore: number;\n readonly recencyScore: number;\n readonly accessScore: number;\n readonly contextScore: number;\n readonly relationSource?: { readonly id: string; readonly title: string | null; readonly type: RelationType };\n}\n\nfunction computeScoreParts(\n memory: Memory,\n textScore: number,\n gitContext: GitContext,\n query: string,\n): ScoreParts {\n return {\n textScore,\n importanceScore: memory.importance,\n recencyScore: computeRecencyScore(memory.updatedAt),\n accessScore: computeAccessScore(memory.accessCount, memory.lastAccessed),\n contextScore: computeContextScore(memory.context, gitContext, query),\n };\n}\n\nfunction computeComposite(parts: ScoreParts): number {\n return (\n parts.textScore * SCORING_WEIGHTS.text +\n parts.importanceScore * SCORING_WEIGHTS.importance +\n parts.recencyScore * SCORING_WEIGHTS.recency +\n parts.accessScore * SCORING_WEIGHTS.access +\n parts.contextScore * SCORING_WEIGHTS.context\n );\n}\n\n/**\n * Recency score: 1.0 for today, decays exponentially.\n * Uses a 30-day half-life.\n */\nfunction computeRecencyScore(updatedAt: string): number {\n const ageMs = Date.now() - new Date(updatedAt).getTime();\n const ageDays = ageMs / (1000 * 60 * 60 * 24);\n if (ageDays < 0) return 1.0;\n return Math.exp(-ageDays * Math.LN2 / 30);\n}\n\n/**\n * Access score: logarithmic count x recency of last access.\n */\nfunction computeAccessScore(accessCount: number, lastAccessed: string | null): number {\n if (accessCount <= 0) return 0;\n const countScore = Math.min(1.0, Math.log10(accessCount + 1) / Math.log10(31));\n if (!lastAccessed) return countScore * 0.5;\n const ageDays = (Date.now() - new Date(lastAccessed).getTime()) / 86_400_000;\n const recency = Math.exp(-ageDays * Math.LN2 / 30);\n return countScore * (0.5 + 0.5 * recency);\n}\n\n// ── Explanation ───────────────────────────────────────────────\n\nfunction buildExplanation(parts: ScoreParts, memory: Memory): string {\n const factors: string[] = [];\n\n if (parts.textScore > 0.7) {\n factors.push(`High text match (${(parts.textScore * 100).toFixed(0)}%)`);\n } else if (parts.textScore > 0.3) {\n factors.push(`Moderate text match (${(parts.textScore * 100).toFixed(0)}%)`);\n }\n\n if (memory.importance > 0.7) {\n factors.push('High importance');\n }\n\n if (parts.recencyScore > 0.8) {\n factors.push('Very recent');\n } else if (parts.recencyScore > 0.5) {\n factors.push('Recent');\n }\n\n if (memory.accessCount > 10) {\n factors.push(`Frequently accessed (${memory.accessCount}x)`);\n } else if (memory.accessCount > 3) {\n factors.push(`Accessed ${memory.accessCount}x`);\n }\n\n if (parts.contextScore > 0.3) {\n factors.push('Context match');\n }\n\n const ageDays = Math.floor((Date.now() - new Date(memory.createdAt).getTime()) / 86_400_000);\n const stalenessThreshold = STALENESS_THRESHOLDS[memory.type];\n if (stalenessThreshold !== undefined && ageDays > stalenessThreshold) {\n factors.push(`${ageDays}d old - verify before acting`);\n }\n\n return factors.length > 0 ? factors.join(' + ') : 'Matched query';\n}\n\n// ── Types ────────────────────────────────────────────────────\n\nexport interface SessionContextResult {\n readonly section: 'context' | 'recent' | 'related';\n readonly result: SearchResult;\n}\n\n// Exported for testing\nexport { computeRecencyScore, computeAccessScore, computeComposite, computeScoreParts, ftsOnlyScores };\nexport type { ScoreParts };\n","import { z } from 'zod';\nimport { createHash } from 'node:crypto';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ToolDeps } from './register.js';\nimport { MEMORY_TYPES, MEMORY_SOURCES } from '../types.js';\nimport { getGitContext } from '../utils/git-context.js';\nimport { validateMemoryContent } from '../utils/content-validation.js';\nimport { checkContradiction } from '../utils/contradiction.js';\n\n// In-memory dedup: content hash → timestamp. Catches parallel calls within same request.\nconst recentStores = new Map<string, number>();\nconst pendingStores = new Set<string>();\nconst DEDUP_WINDOW_MS = 10_000;\n\n// Tag normalization: lowercase, strip #, singularize common suffixes, apply aliases\nconst TAG_ALIASES: Record<string, string> = {\n bugs: 'bug', bugfix: 'bug', debugging: 'bug',\n decisions: 'decision', decided: 'decision',\n gotchas: 'gotcha', pitfall: 'gotcha', pitfalls: 'gotcha',\n howtos: 'howto', 'how-to': 'howto',\n patterns: 'pattern',\n todos: 'todo', fixme: 'todo',\n architectures: 'architecture', arch: 'architecture',\n};\n\nfunction normalizeTags(tags: readonly string[]): string[] {\n return [...new Set(tags.map((t) => {\n const stripped = t.replace(/^#/, '').toLowerCase().trim();\n return TAG_ALIASES[stripped] ?? stripped;\n }).filter(Boolean))];\n}\n\n// Auto-tag: detect common patterns in content\nconst AUTO_TAG_PATTERNS: readonly { readonly pattern: RegExp; readonly tag: string }[] = [\n { pattern: /\\b(bug|crash|error|fix(ed)?|broke)\\b/i, tag: 'bug' },\n { pattern: /\\b(decid|chose|decision|went with|picked)\\b/i, tag: 'decision' },\n { pattern: /\\b(gotcha|careful|watch out|trap|pitfall)\\b/i, tag: 'gotcha' },\n { pattern: /\\b(how to|steps to|run|install|deploy|command)\\b/i, tag: 'howto' },\n { pattern: /\\b(pattern|recurring|always|every time)\\b/i, tag: 'pattern' },\n];\n\nfunction autoTag(content: string, existingTags: readonly string[]): string[] {\n const existing = new Set(existingTags);\n const detected: string[] = [];\n for (const { pattern, tag } of AUTO_TAG_PATTERNS) {\n if (!existing.has(tag) && pattern.test(content)) {\n detected.push(tag);\n }\n }\n return detected;\n}\n\nconst inputSchema = {\n type: z.enum(MEMORY_TYPES).describe('Memory type: working, episodic, semantic, procedural, or pattern'),\n content: z.string().min(1).describe('The memory content (aim for ~2000 chars / ~500 tokens). Keep memories concise: capture the decision or insight, not the full context. Split large topics into separate memories.'),\n title: z.string().max(200).optional().describe('Short title for the memory'),\n tags: z.array(z.string()).max(20).default([]).describe('Tags for categorization. Suggested: #bug, #decision, #gotcha, #howto, #pattern'),\n importance: z.number().min(0).max(1).default(0.5).describe('0-0.3 ephemeral, 0.3-0.6 reference, 0.6-0.8 important, 0.8-1.0 critical'),\n context: z.string().optional().describe('JSON: {\"files\": [...], \"branch\": \"...\", \"intent\": \"...\"}. Auto-detected from git if omitted.'),\n source: z.enum(MEMORY_SOURCES).default('manual').describe('How this memory was created'),\n project: z.string().max(200).optional().describe('Project scope (auto-detected from CWD if omitted)'),\n};\n\nexport function registerStore(server: McpServer, deps: ToolDeps): void {\n server.registerTool(\n 'memory_store',\n {\n description:\n 'Save something worth remembering to the knowledge base. '\n + 'Use when you learn a fact, make a decision, hit a bug, or discover a pattern that future sessions should know. '\n + 'Always search first to avoid duplicates — update existing memories when possible. '\n + 'Types: semantic (facts/decisions), procedural (how-to), episodic (what happened), pattern (recurring), working (scratch). '\n + 'Importance: 0.1 trivial, 0.5 useful, 0.8 important, 1.0 critical. '\n + 'Tags and git context are auto-detected if omitted. \"Skipped\" responses mean a duplicate was caught — not an error.',\n inputSchema,\n annotations: { idempotentHint: false },\n },\n async (args) => {\n const validation = validateMemoryContent(args.content);\n if (!validation.valid) {\n return {\n content: [{\n type: 'text' as const,\n text: `Rejected: ${validation.reason}`,\n }],\n isError: true,\n };\n }\n\n const context = args.context ?? JSON.stringify(getGitContext());\n const project = args.project ?? deps.project ?? undefined;\n\n // Dedup: in-memory guard catches parallel calls within same request.\n // Uses a pending Set to catch calls that arrive in the same tick.\n const contentHash = createHash('sha256').update(args.content).digest('hex');\n const now = Date.now();\n const lastStored = recentStores.get(contentHash);\n if (lastStored && (now - lastStored) < DEDUP_WINDOW_MS) {\n return {\n content: [{ type: 'text' as const, text: 'Skipped: identical memory already exists (stored moments ago).' }],\n };\n }\n if (pendingStores.has(contentHash)) {\n return {\n content: [{ type: 'text' as const, text: 'Skipped: identical memory is being stored by another call.' }],\n };\n }\n pendingStores.add(contentHash);\n // Prune old entries\n for (const [key, ts] of recentStores) {\n if (now - ts > DEDUP_WINDOW_MS) recentStores.delete(key);\n }\n\n // Contradiction detection\n const contradictions: { id: string; title: string | null }[] = [];\n try {\n const existing = await deps.retrievalService.search({\n query: args.content.slice(0, 200),\n limit: 3,\n min_importance: 0,\n project,\n });\n for (const result of existing) {\n if (result.score > 0.6 && checkContradiction(args.content, result.memory.content)) {\n contradictions.push({ id: result.memory.id, title: result.memory.title });\n }\n }\n } catch {\n // Contradiction check is best-effort\n }\n\n // Normalize tags + auto-tag from content\n const normalizedTags = normalizeTags(args.tags);\n const autoTags = autoTag(args.content, normalizedTags);\n const finalTags = [...new Set([...normalizedTags, ...autoTags])];\n\n const memory = deps.memoryRepo.create(\n {\n type: args.type,\n content: args.content,\n title: args.title,\n tags: finalTags,\n importance: args.importance,\n context,\n source: args.source,\n project,\n },\n null,\n );\n\n // Mark as stored (dedup window starts now)\n recentStores.set(contentHash, Date.now());\n pendingStores.delete(contentHash);\n\n // Create contradiction relations\n for (const c of contradictions) {\n try {\n deps.relationRepo.create(memory.id, c.id, 'contradicts');\n } catch {\n // Relation creation is best-effort\n }\n }\n\n const parts: string[] = [\n `Stored memory ${memory.id} (type: ${memory.type}, importance: ${memory.importance})`,\n ];\n\n for (const warning of validation.warnings) {\n parts.push(`Warning: ${warning}`);\n }\n\n for (const c of contradictions) {\n parts.push(`Warning: potential contradiction with memory ${c.id}${c.title ? ` (\"${c.title}\")` : ''}. Linked with 'contradicts' relation.`);\n }\n\n return {\n content: [{\n type: 'text' as const,\n text: parts.join('\\n'),\n }],\n };\n },\n );\n}\n","// ── Content Validation for memory_store ─────────────────────\n\nexport interface ValidationResult {\n readonly valid: boolean;\n readonly reason?: string;\n readonly warnings: readonly string[];\n}\n\nconst SOFT_LENGTH_LIMIT = 1500;\nconst HARD_LENGTH_LIMIT = 5000;\nconst CODE_RATIO_THRESHOLD = 0.5;\n\n/**\n * Validate memory content before storage.\n * Returns hard rejections (don't store) and soft warnings (store but warn).\n */\nexport function validateMemoryContent(content: string): ValidationResult {\n const warnings: string[] = [];\n\n // Hard reject: git log output\n if (isGitLog(content)) {\n return { valid: false, reason: 'Content looks like raw git log output. Use git log directly — don\\'t store it as memory.', warnings: [] };\n }\n\n // Hard reject: code-heavy content\n if (isCodeHeavy(content)) {\n return { valid: false, reason: 'Content is >50% code blocks. Code belongs in files, not memory. Store the insight or decision instead.', warnings: [] };\n }\n\n // Hard reject: too long\n if (content.length > HARD_LENGTH_LIMIT) {\n return { valid: false, reason: `Content is ${content.length} chars (limit: ${HARD_LENGTH_LIMIT}). Break it into smaller, atomic memories.`, warnings: [] };\n }\n\n // Soft warn: lengthy\n if (content.length > SOFT_LENGTH_LIMIT) {\n warnings.push(`Content is ${content.length} chars. Shorter memories (<${SOFT_LENGTH_LIMIT} chars) are easier to retrieve and less likely to decay.`);\n }\n\n return { valid: true, warnings };\n}\n\n/**\n * Content is >50% fenced code blocks.\n */\nexport function isCodeHeavy(content: string): boolean {\n const fencedBlockPattern = /```[\\s\\S]*?```/g;\n let codeChars = 0;\n let match: RegExpExecArray | null;\n\n while ((match = fencedBlockPattern.exec(content)) !== null) {\n codeChars += match[0].length;\n }\n\n return content.length > 0 && codeChars / content.length > CODE_RATIO_THRESHOLD;\n}\n\n/**\n * Content looks like raw git log output.\n * Matches patterns like \"commit abc123\\nAuthor: ...\\nDate: ...\"\n */\nexport function isGitLog(content: string): boolean {\n const lines = content.split('\\n');\n let gitLogLines = 0;\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (/^commit\\s+[0-9a-f]{7,40}$/i.test(trimmed)) gitLogLines++;\n else if (/^Author:\\s+.+/i.test(trimmed)) gitLogLines++;\n else if (/^Date:\\s+.+/i.test(trimmed)) gitLogLines++;\n else if (/^[0-9a-f]{7,12}\\s+\\S+/i.test(trimmed) && trimmed.length < 200) gitLogLines++;\n }\n\n // At least 3 git-log-like lines and they make up >30% of non-empty lines\n const nonEmptyLines = lines.filter(l => l.trim().length > 0).length;\n return gitLogLines >= 3 && nonEmptyLines > 0 && gitLogLines / nonEmptyLines > 0.3;\n}\n","// ── Contradiction Detection (keyword-overlap heuristic) ─────\n\nconst NEGATION_PATTERNS = [\n /\\bnot\\b/i,\n /\\bno longer\\b/i,\n /\\binstead of\\b/i,\n /\\breplaced\\b/i,\n /\\bremoved\\b/i,\n /\\bdon'?t\\b/i,\n /\\bwon'?t\\b/i,\n /\\bshouldn'?t\\b/i,\n /\\bdeprecated\\b/i,\n /\\bdisabled\\b/i,\n /\\bstopped\\b/i,\n /\\bavoid\\b/i,\n /\\bnever\\b/i,\n /\\bwithout\\b/i,\n];\n\nconst KEYWORD_OVERLAP_THRESHOLD = 0.4;\nconst MIN_KEYWORD_LENGTH = 3;\nconst STOP_WORDS = new Set([\n 'the', 'and', 'for', 'are', 'but', 'not', 'you', 'all', 'can', 'had',\n 'her', 'was', 'one', 'our', 'out', 'has', 'have', 'been', 'from', 'that',\n 'this', 'with', 'they', 'will', 'each', 'make', 'like', 'than', 'them',\n 'then', 'what', 'when', 'into', 'more', 'some', 'such', 'also', 'use',\n 'used', 'using', 'should', 'would', 'could', 'about', 'which', 'their',\n 'there', 'these', 'those', 'does', 'done', 'just', 'very',\n]);\n\n/**\n * Extract meaningful keywords from text.\n */\nfunction extractKeywords(text: string): ReadonlySet<string> {\n const words = text.toLowerCase().match(/[a-z][a-z0-9_-]+/g) ?? [];\n return new Set(\n words.filter(w => w.length >= MIN_KEYWORD_LENGTH && !STOP_WORDS.has(w)),\n );\n}\n\n/**\n * Check if new content potentially contradicts existing content.\n *\n * Heuristic: high keyword overlap + negation markers = likely contradiction.\n * Not perfect, but catches the common case of \"we used X\" vs \"we no longer use X\".\n */\nexport function checkContradiction(newContent: string, existingContent: string): boolean {\n const newKeywords = extractKeywords(newContent);\n const existingKeywords = extractKeywords(existingContent);\n\n if (newKeywords.size === 0 || existingKeywords.size === 0) return false;\n\n // Compute Jaccard-like overlap: |intersection| / |smaller set|\n let overlap = 0;\n for (const kw of newKeywords) {\n if (existingKeywords.has(kw)) overlap++;\n }\n\n const smallerSize = Math.min(newKeywords.size, existingKeywords.size);\n const overlapRatio = overlap / smallerSize;\n\n if (overlapRatio < KEYWORD_OVERLAP_THRESHOLD) return false;\n\n // High overlap — check for negation markers in the NEW content only.\n return NEGATION_PATTERNS.some(pattern => pattern.test(newContent));\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ToolDeps } from './register.js';\nimport { MEMORY_TYPES } from '../types.js';\n\nconst inputSchema = {\n query: z.string().min(1).max(500).describe('Search query (natural language or keywords)'),\n id: z.string().optional().describe('Direct lookup by memory ID (bypasses search)'),\n type: z.enum(MEMORY_TYPES).optional().describe('Filter by memory type'),\n tags: z.array(z.string()).max(10).optional().describe('Filter to memories containing ALL of these tags'),\n limit: z.number().int().min(1).max(50).default(10).describe('Maximum results to return'),\n min_importance: z.number().min(0).max(1).default(0).describe('Minimum importance threshold'),\n};\n\nexport function registerSearch(server: McpServer, deps: ToolDeps): void {\n server.registerTool(\n 'memory_search',\n {\n description:\n 'Look up what you already know. Query the knowledge base before solving a problem or storing new information. '\n + 'Use when: checking if something was already decided, finding how-to steps, recalling past bugs, or deduping before a store. '\n + 'Related memories are surfaced automatically. Pass `id` for direct lookup, or filter by `type` and `tags`.',\n inputSchema,\n annotations: { readOnlyHint: true, idempotentHint: true },\n },\n async (args) => {\n const results = await deps.retrievalService.search({\n query: args.query,\n id: args.id,\n type: args.type,\n tags: args.tags,\n limit: args.limit,\n min_importance: args.min_importance,\n project: deps.project ?? undefined,\n });\n\n if (results.length === 0) {\n return {\n content: [{ type: 'text' as const, text: 'No memories found matching your query.' }],\n };\n }\n\n const formatted = results.map((r, i) => ({\n rank: i + 1,\n id: r.memory.id,\n type: r.memory.type,\n title: r.memory.title,\n content: r.memory.content,\n score: Math.round(r.score * 100) / 100,\n explanation: r.explanation,\n importance: r.memory.importance,\n tags: r.memory.tags,\n accessCount: r.memory.accessCount,\n createdAt: r.memory.createdAt,\n }));\n\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify(formatted, null, 2),\n }],\n };\n },\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ToolDeps } from './register.js';\nimport { memoryNotFound, formatMcpError } from '../utils/errors.js';\n\nconst inputSchema = {\n id: z.string().describe('ID of the memory to forget'),\n hard_delete: z.boolean().default(false).describe('true = permanent delete, false = set importance to 0 (soft delete)'),\n};\n\nexport function registerForget(server: McpServer, deps: ToolDeps): void {\n server.registerTool(\n 'memory_forget',\n {\n description:\n 'Remove outdated or wrong information from the knowledge base. '\n + 'Default: soft-delete (fades away naturally). Pass hard_delete=true to erase permanently. '\n + 'Use memory_search to find the ID first.',\n inputSchema,\n annotations: { destructiveHint: true, idempotentHint: true },\n },\n async (args) => {\n const memory = deps.memoryRepo.getById(args.id);\n if (!memory) {\n return formatMcpError(memoryNotFound(args.id));\n }\n\n if (deps.project && memory.project !== null && memory.project !== deps.project) {\n return formatMcpError({\n what: `Memory ${args.id} belongs to project \"${memory.project}\".`,\n why: `Current project is \"${deps.project}\". Cross-project deletion is not allowed.`,\n fix: 'Switch to the correct project or use a global context.',\n });\n }\n\n if (args.hard_delete) {\n deps.memoryRepo.hardDelete(args.id);\n return {\n content: [{\n type: 'text' as const,\n text: `Permanently deleted memory ${args.id} (\"${memory.title ?? memory.content.slice(0, 50)}\")`,\n }],\n };\n }\n\n deps.memoryRepo.softDelete(args.id);\n return {\n content: [{\n type: 'text' as const,\n text: `Soft-deleted memory ${args.id} (importance set to 0, will decay naturally)`,\n }],\n };\n },\n );\n}\n","// ── Structured Error Formatting ──────────────────────────────\n// Every error answers: What happened? Why? What to do?\n\nexport interface StructuredError {\n readonly what: string;\n readonly why: string;\n readonly fix: string;\n}\n\nexport function formatError(err: StructuredError): string {\n return `${err.what}\\nWhy: ${err.why}\\nFix: ${err.fix}`;\n}\n\nexport function formatMcpError(err: StructuredError): { isError: true; content: [{ type: 'text'; text: string }] } {\n return {\n isError: true,\n content: [{ type: 'text' as const, text: formatError(err) }],\n };\n}\n\n// ── Common Error Templates ───────────────────────────────────\n\nexport function memoryNotFound(id: string): StructuredError {\n return {\n what: `Memory \"${id}\" not found.`,\n why: 'The ID may be incorrect, or the memory was deleted or pruned.',\n fix: 'Use memory_search to find valid IDs.',\n };\n}\n\nexport function databaseLocked(): StructuredError {\n return {\n what: 'Database is temporarily locked.',\n why: 'Another process is writing to the database (SQLITE_BUSY).',\n fix: 'Retry in a moment. If persistent, run: claude-launchpad doctor --fix',\n };\n}\n\nexport function databaseCorrupt(): StructuredError {\n return {\n what: 'Database integrity check failed.',\n why: 'The database file may be corrupted (disk error, incomplete write).',\n fix: 'Run: claude-launchpad doctor --fix (creates backup, reinitializes DB)',\n };\n}\n\nexport function diskFull(): StructuredError {\n return {\n what: 'Disk write failed — not enough space.',\n why: 'The disk partition containing ~/.agentic-memory is full.',\n fix: 'Free disk space, then run: claude-launchpad doctor --fix',\n };\n}\n\nexport function invalidInput(field: string, reason: string): StructuredError {\n return {\n what: `Invalid input: ${field}`,\n why: reason,\n fix: 'Check the parameter value and try again.',\n };\n}\n\n// ── SQLite Retry Logic ───────────────────────────────────────\n\nconst RETRY_DELAYS = [100, 200, 400] as const;\n\nexport function withRetry<T>(fn: () => T, label: string): T {\n for (let attempt = 0; attempt < RETRY_DELAYS.length; attempt++) {\n try {\n return fn();\n } catch (err) {\n if (isSqliteBusy(err) && attempt < RETRY_DELAYS.length - 1) {\n const delay = RETRY_DELAYS[attempt]!;\n process.stderr.write(`[memory] ${label}: SQLITE_BUSY, retrying in ${delay}ms\\n`);\n sleepSync(delay);\n continue;\n }\n throw err;\n }\n }\n // Unreachable, but TypeScript needs it\n throw new Error(`${label}: exhausted retries`);\n}\n\nfunction isSqliteBusy(err: unknown): boolean {\n if (err instanceof Error) {\n return err.message.includes('SQLITE_BUSY') || err.message.includes('database is locked');\n }\n return false;\n}\n\nfunction sleepSync(ms: number): void {\n Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ToolDeps } from './register.js';\nimport { RELATION_TYPES } from '../types.js';\nimport { memoryNotFound, formatMcpError } from '../utils/errors.js';\n\nconst inputSchema = {\n source_id: z.string().describe('ID of the source memory'),\n target_id: z.string().describe('ID of the target memory'),\n relation_type: z.enum(RELATION_TYPES).describe(\n 'Type of relation: relates_to, depends_on, contradicts, extends, implements, derived_from'\n ),\n};\n\nexport function registerRelate(server: McpServer, deps: ToolDeps): void {\n server.registerTool(\n 'memory_relate',\n {\n description:\n 'Link two memories together so they surface as a group. '\n + 'Use when one memory extends, contradicts, depends on, or implements another. '\n + 'Linked memories stay relevant longer and appear together in search results.',\n inputSchema,\n annotations: { idempotentHint: true },\n },\n async (args) => {\n if (args.source_id === args.target_id) {\n return formatMcpError({\n what: 'Cannot create self-relation.',\n why: 'source_id and target_id are the same memory.',\n fix: 'Provide two different memory IDs.',\n });\n }\n\n const source = deps.memoryRepo.getById(args.source_id);\n if (!source) {\n return formatMcpError(memoryNotFound(args.source_id));\n }\n\n const target = deps.memoryRepo.getById(args.target_id);\n if (!target) {\n return formatMcpError(memoryNotFound(args.target_id));\n }\n\n if (deps.project) {\n for (const mem of [source, target]) {\n if (mem.project !== null && mem.project !== deps.project) {\n return formatMcpError({\n what: `Memory ${mem.id} belongs to project \"${mem.project}\".`,\n why: `Current project is \"${deps.project}\". Cross-project relations are not allowed.`,\n fix: 'Both memories must belong to the same project.',\n });\n }\n }\n }\n\n const created = deps.relationRepo.create(args.source_id, args.target_id, args.relation_type);\n\n if (!created) {\n return {\n content: [{\n type: 'text' as const,\n text: `Relation already exists: ${args.source_id} --[${args.relation_type}]--> ${args.target_id}`,\n }],\n };\n }\n\n return {\n content: [{\n type: 'text' as const,\n text: `Created relation: \"${source.title ?? source.content.slice(0, 40)}\" --[${args.relation_type}]--> \"${target.title ?? target.content.slice(0, 40)}\"`,\n }],\n };\n },\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ToolDeps } from './register.js';\nimport { MEMORY_TYPES } from '../types.js';\nimport type { MemoryStats } from '../types.js';\nimport { statSync } from 'node:fs';\nimport { join } from 'node:path';\n\nexport function registerStats(server: McpServer, deps: ToolDeps): void {\n server.registerTool(\n 'memory_stats',\n {\n description:\n 'See how much is in the knowledge base — total count, breakdown by type, storage size, and most-used memories.',\n annotations: { readOnlyHint: true, idempotentHint: true },\n },\n async () => {\n const countByType = deps.memoryRepo.countByType();\n const total = deps.memoryRepo.count();\n const topInjected = deps.memoryRepo.topInjected(5);\n const totalRelations = deps.relationRepo.count();\n\n let dbSizeBytes = 0;\n try {\n const dbPath = join(deps.dataDir, 'memory.db');\n dbSizeBytes = statSync(dbPath).size;\n } catch {\n // :memory: or file not found\n }\n\n const { oldest, newest } = deps.memoryRepo.dateRange();\n\n const stats: MemoryStats = {\n totalMemories: total,\n byType: Object.fromEntries(\n MEMORY_TYPES.map(t => [t, countByType[t] ?? 0])\n ) as Record<string, number>,\n totalRelations,\n dbSizeBytes,\n oldestMemory: oldest,\n newestMemory: newest,\n topInjected,\n };\n\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify(stats, null, 2),\n }],\n };\n },\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ToolDeps } from './register.js';\nimport { MEMORY_TYPES } from '../types.js';\n\nconst inputSchema = {\n limit: z.number().int().min(1).max(50).default(10).describe('Maximum memories to return'),\n type: z.enum(MEMORY_TYPES).optional().describe('Filter by memory type'),\n};\n\nexport function registerRecent(server: McpServer, deps: ToolDeps): void {\n server.registerTool(\n 'memory_recent',\n {\n description:\n 'Get caught up on what happened before this session. '\n + 'Returns memories relevant to the current branch/files, recent activity, and related context. '\n + 'Typically called at session start to restore working context. No query needed — it uses git state to find what matters.',\n inputSchema,\n annotations: { readOnlyHint: true, idempotentHint: true },\n },\n async (args) => {\n const results = deps.retrievalService.loadSessionContext({\n limit: args.limit,\n project: deps.project ?? undefined,\n type: args.type,\n });\n\n if (results.length === 0) {\n return {\n content: [{ type: 'text' as const, text: 'No memories found for this project.' }],\n };\n }\n\n const formatEntry = (entry: typeof results[number], rank: number) => ({\n rank,\n section: entry.section,\n id: entry.result.memory.id,\n type: entry.result.memory.type,\n title: entry.result.memory.title,\n content: entry.result.memory.content,\n importance: entry.result.memory.importance,\n tags: entry.result.memory.tags,\n score: Math.round(entry.result.score * 100) / 100,\n explanation: entry.result.explanation,\n createdAt: entry.result.memory.createdAt,\n });\n\n const contextMatched = results.filter(r => r.section === 'context').map((r, i) => formatEntry(r, i + 1));\n const recent = results.filter(r => r.section === 'recent').map((r, i) => formatEntry(r, i + 1));\n const related = results.filter(r => r.section === 'related').map((r, i) => formatEntry(r, i + 1));\n\n return {\n content: [{\n type: 'text' as const,\n text: JSON.stringify({ contextMatched, recent, related }, null, 2),\n }],\n };\n },\n );\n}\n","import { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ToolDeps } from './register.js';\n\nconst inputSchema = {\n id: z.string().describe('Memory ID to update (use memory_search to find it)'),\n title: z.string().max(200).optional().describe('Updated title'),\n content: z.string().min(1).max(10000).optional().describe('Updated content'),\n tags: z.array(z.string()).max(20).optional().describe('Updated tags'),\n importance: z.number().min(0).max(1).optional().describe('Updated importance (0-1)'),\n context: z.string().optional().describe('Updated context JSON'),\n};\n\nexport function registerUpdate(server: McpServer, deps: ToolDeps): void {\n server.registerTool(\n 'memory_update',\n {\n description:\n 'Correct or improve an existing memory instead of creating a duplicate. '\n + 'Use when information has changed, a decision was revised, or a memory needs more detail. '\n + 'Keeps the memory\\'s history intact. Use memory_search to find the ID first.',\n inputSchema,\n annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true },\n },\n async (args) => {\n const hasUpdate = args.title !== undefined || args.content !== undefined\n || args.tags !== undefined || args.importance !== undefined\n || args.context !== undefined;\n\n if (!hasUpdate) {\n return {\n content: [{ type: 'text' as const, text: 'No fields to update. Provide at least one of: title, content, tags, importance, context.' }],\n isError: true,\n };\n }\n\n const existing = deps.memoryRepo.getById(args.id);\n if (!existing) {\n return {\n content: [{ type: 'text' as const, text: `Memory ${args.id} not found.` }],\n isError: true,\n };\n }\n\n const updated = deps.memoryRepo.updateContent(args.id, {\n title: args.title,\n content: args.content,\n tags: args.tags,\n importance: args.importance,\n context: args.context,\n });\n\n if (!updated) {\n return {\n content: [{ type: 'text' as const, text: `Failed to update memory ${args.id}.` }],\n isError: true,\n };\n }\n\n const fields = [\n args.title !== undefined && 'title',\n args.content !== undefined && 'content',\n args.tags !== undefined && 'tags',\n args.importance !== undefined && 'importance',\n args.context !== undefined && 'context',\n ].filter(Boolean).join(', ');\n\n return {\n content: [{ type: 'text' as const, text: `Updated memory ${args.id} (fields: ${fields})` }],\n };\n },\n );\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { MemoryRepo } from '../storage/memory-repo.js';\nimport type { RelationRepo } from '../storage/relation-repo.js';\nimport type { RetrievalService } from '../services/retrieval-service.js';\nimport { registerStore } from './store.js';\nimport { registerSearch } from './search.js';\nimport { registerForget } from './forget.js';\nimport { registerRelate } from './relate.js';\nimport { registerStats } from './stats.js';\nimport { registerRecent } from './recent.js';\nimport { registerUpdate } from './update.js';\n\nexport interface ToolDeps {\n readonly memoryRepo: MemoryRepo;\n readonly relationRepo: RelationRepo;\n readonly retrievalService: RetrievalService;\n readonly dataDir: string;\n readonly project: string | null;\n}\n\nexport function registerTools(server: McpServer, deps: ToolDeps): void {\n registerStore(server, deps);\n registerSearch(server, deps);\n registerRecent(server, deps);\n registerForget(server, deps);\n registerRelate(server, deps);\n registerStats(server, deps);\n registerUpdate(server, deps);\n}\n"],"mappings":"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","names":["z","inputSchema","z","z","inputSchema","z","z","inputSchema","z","z","inputSchema","z","z","inputSchema","require"]}
@@ -21,54 +21,54 @@ import { join } from "path";
21
21
  import { execSync } from "child_process";
22
22
  async function runInstall(opts) {
23
23
  log.blank();
24
- log.step("Memory system - install");
24
+ log.step("Setting up your knowledge base");
25
25
  log.blank();
26
26
  await ensureNativeDeps();
27
27
  const config = loadConfig(opts.dbPath ? { dataDir: opts.dbPath } : void 0);
28
28
  const dataDir = resolveDataDir(config.dataDir);
29
- log.step("[1/4] Setting up database...");
29
+ log.step("[1/4] Creating knowledge base...");
30
30
  if (!existsSync(dataDir)) {
31
31
  mkdirSync(dataDir, { recursive: true });
32
32
  }
33
33
  const db = createDatabase({ dataDir });
34
34
  migrate(db);
35
35
  closeDatabase(db);
36
- log.success(`${dataDir}/memory.db ready`);
37
- log.step("[2/4] Configuring Claude Code...");
36
+ log.success(`Knowledge base created at ${dataDir}/memory.db`);
37
+ log.step("[2/4] Connecting to Claude Code...");
38
38
  await configureSettings(process.cwd());
39
- log.step("[3/4] Registering MCP server...");
39
+ log.step("[3/4] Enabling memory tools...");
40
40
  const registered = registerMcpServer();
41
41
  if (registered) {
42
- log.success("MCP server registered via `claude mcp add`");
42
+ log.success("Memory tools available in Claude Code");
43
43
  } else {
44
- log.warn("Could not register MCP server automatically.");
44
+ log.warn("Could not enable memory tools automatically.");
45
45
  log.info("Run: claude mcp add --scope user agentic-memory npx claude-launchpad memory serve");
46
46
  }
47
- log.step("[4/4] Injecting guidance...");
47
+ log.step("[4/4] Adding instructions...");
48
48
  const guidanceAdded = injectClaudeMdGuidance(process.cwd());
49
49
  if (guidanceAdded) {
50
- log.success("Memory guidance added to CLAUDE.md");
50
+ log.success("CLAUDE.md updated with memory instructions");
51
51
  }
52
52
  const skillsInstalled = installSkills(process.cwd());
53
53
  if (skillsInstalled > 0) {
54
54
  log.success(`Installed ${skillsInstalled} skill(s) to .claude/skills/`);
55
55
  }
56
56
  log.blank();
57
- log.success("Memory system installed.");
58
- log.info("Restart your Claude Code session for the MCP server to connect.");
57
+ log.success("Knowledge base is ready. Claude will now remember across sessions.");
58
+ log.info("Restart your Claude Code session to activate.");
59
59
  log.blank();
60
60
  }
61
61
  async function configureSettings(projectDir) {
62
62
  const settings = await readSettingsJson(projectDir);
63
63
  settings["autoMemoryEnabled"] = false;
64
- log.info("Built-in auto-memory disabled");
64
+ log.info("Built-in auto-memory disabled (replaced by knowledge base)");
65
65
  const hooks = settings["hooks"] ?? {};
66
66
  addSessionStartHook(hooks);
67
67
  addStopHook(hooks);
68
68
  settings["hooks"] = hooks;
69
69
  addToolPermissions(settings);
70
70
  await writeSettingsJson(projectDir, settings);
71
- log.success("settings.json updated");
71
+ log.success("Claude Code configured for knowledge base");
72
72
  }
73
73
  function addSessionStartHook(hooks) {
74
74
  const sessionStartHooks = hooks["SessionStart"] ?? [];
@@ -85,7 +85,7 @@ function addSessionStartHook(hooks) {
85
85
  hooks: [{ type: "command", command: hookCommand }]
86
86
  });
87
87
  hooks["SessionStart"] = sessionStartHooks;
88
- log.info("SessionStart hook added (injects memory context)");
88
+ log.info("Session start: Claude will recall relevant context automatically");
89
89
  }
90
90
  }
91
91
  function addStopHook(hooks) {
@@ -102,7 +102,7 @@ function addStopHook(hooks) {
102
102
  hooks: [{ type: "command", command: extractCommand, async: true }]
103
103
  });
104
104
  hooks["Stop"] = stopHooks;
105
- log.info("Stop hook added (extracts facts from transcript)");
105
+ log.info("Session end: Claude will save important facts from the conversation");
106
106
  }
107
107
  }
108
108
  function addToolPermissions(settings) {
@@ -127,7 +127,7 @@ function addToolPermissions(settings) {
127
127
  if (added > 0) {
128
128
  permissions["allow"] = allowList;
129
129
  settings["permissions"] = permissions;
130
- log.info(`Auto-allowed ${added} MCP tools`);
130
+ log.info(`${added} memory tools auto-approved`);
131
131
  }
132
132
  }
133
133
  async function ensureNativeDeps() {
@@ -137,17 +137,17 @@ async function ensureNativeDeps() {
137
137
  return;
138
138
  } catch {
139
139
  }
140
- log.step("Installing native dependencies (better-sqlite3, sqlite-vec)...");
140
+ log.step("Installing required database libraries...");
141
141
  try {
142
142
  execSync("npm install -g better-sqlite3 sqlite-vec", { stdio: "pipe", timeout: 12e4 });
143
- log.success("Native dependencies installed globally");
143
+ log.success("Database libraries installed");
144
144
  } catch {
145
- log.error("Failed to install native dependencies automatically.");
145
+ log.error("Could not install database libraries automatically.");
146
146
  log.blank();
147
147
  log.info("Install manually:");
148
148
  log.step(" npm install -g better-sqlite3 sqlite-vec");
149
149
  log.blank();
150
- log.info("This requires a C++ compiler (Xcode on macOS, build-essential on Linux).");
150
+ log.info("Requires a C++ compiler (Xcode on macOS, build-essential on Linux).");
151
151
  process.exit(1);
152
152
  }
153
153
  }
@@ -155,7 +155,7 @@ function registerMcpServer() {
155
155
  try {
156
156
  const existing = execSync("claude mcp list", { stdio: "pipe", timeout: 1e4, encoding: "utf-8" });
157
157
  if (existing.includes("agentic-memory")) {
158
- log.info("MCP server already registered globally");
158
+ log.info("Memory tools already registered");
159
159
  return true;
160
160
  }
161
161
  execSync(
@@ -255,4 +255,4 @@ function installSkills(projectDir) {
255
255
  export {
256
256
  runInstall
257
257
  };
258
- //# sourceMappingURL=install-C5XDWATE.js.map
258
+ //# sourceMappingURL=install-H6GW4P6K.js.map