claude-launchpad 0.7.2 → 0.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-CSLWJEGD.js +0 -0
- package/dist/{chunk-JE3BZ5S4.js → chunk-EU2OXNTI.js} +2 -2
- package/dist/{chunk-6ZVXZ4EF.js → chunk-FL3JGYDM.js} +14 -1
- package/dist/{chunk-6ZVXZ4EF.js.map → chunk-FL3JGYDM.js.map} +1 -1
- package/dist/{require-deps-EHWR6TVD.js → chunk-FQN5PHEU.js} +16 -4
- package/dist/chunk-FQN5PHEU.js.map +1 -0
- package/dist/chunk-NAW47BYA.js +0 -0
- package/dist/{chunk-EBM7RBPB.js → chunk-P77WV5BF.js} +2 -2
- package/dist/{chunk-IILH26C7.js → chunk-RKN3XZO4.js} +7 -4
- package/dist/chunk-RKN3XZO4.js.map +1 -0
- package/dist/chunk-TALTTAMW.js +0 -0
- package/dist/cli.js +8 -17
- package/dist/cli.js.map +1 -1
- package/dist/commands/memory/server.js +4 -3
- package/dist/commands/memory/server.js.map +1 -1
- package/dist/{context-LNUZ4GCF.js → context-ANYE6ORS.js} +6 -5
- package/dist/{context-LNUZ4GCF.js.map → context-ANYE6ORS.js.map} +1 -1
- package/dist/{extract-NVAXO5CK.js → extract-MVN35LES.js} +5 -4
- package/dist/{extract-NVAXO5CK.js.map → extract-MVN35LES.js.map} +1 -1
- package/dist/{install-EQEBGXQE.js → install-2HLCAZYU.js} +7 -7
- package/dist/require-deps-GVKDXPPE.js +11 -0
- package/dist/{stats-ZKET3Q4E.js → stats-OZ6S6GVG.js} +8 -8
- package/dist/{tui-R25NTQ4K.js → tui-YC74JC6L.js} +4 -3
- package/dist/{tui-R25NTQ4K.js.map → tui-YC74JC6L.js.map} +1 -1
- package/package.json +17 -24
- package/dist/chunk-2H7UOFLK.js +0 -11
- package/dist/chunk-IILH26C7.js.map +0 -1
- package/dist/require-deps-EHWR6TVD.js.map +0 -1
- /package/dist/{chunk-JE3BZ5S4.js.map → chunk-EU2OXNTI.js.map} +0 -0
- /package/dist/{chunk-EBM7RBPB.js.map → chunk-P77WV5BF.js.map} +0 -0
- /package/dist/{install-EQEBGXQE.js.map → install-2HLCAZYU.js.map} +0 -0
- /package/dist/{chunk-2H7UOFLK.js.map → require-deps-GVKDXPPE.js.map} +0 -0
- /package/dist/{stats-ZKET3Q4E.js.map → stats-OZ6S6GVG.js.map} +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
RetrievalService,
|
|
4
4
|
getGitContext
|
|
5
|
-
} from "../../chunk-
|
|
5
|
+
} from "../../chunk-EU2OXNTI.js";
|
|
6
6
|
import {
|
|
7
7
|
detectProject
|
|
8
8
|
} from "../../chunk-NAW47BYA.js";
|
|
@@ -17,8 +17,9 @@ import {
|
|
|
17
17
|
loadConfig,
|
|
18
18
|
migrate,
|
|
19
19
|
resolveDataDir
|
|
20
|
-
} from "../../chunk-
|
|
21
|
-
import "../../chunk-
|
|
20
|
+
} from "../../chunk-RKN3XZO4.js";
|
|
21
|
+
import "../../chunk-FQN5PHEU.js";
|
|
22
|
+
import "../../chunk-FL3JGYDM.js";
|
|
22
23
|
|
|
23
24
|
// src/commands/memory/server.ts
|
|
24
25
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/commands/memory/server.ts","../../../src/commands/memory/tools/store.ts","../../../src/commands/memory/types.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 + '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 { z } from 'zod';\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\nconst inputSchema = {\n type: z.enum(MEMORY_TYPES).describe('Memory type: working, episodic, semantic, procedural, or pattern'),\n content: z.string().min(1).max(10000).describe('The memory content to store'),\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 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 // 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 const memory = deps.memoryRepo.create(\n {\n type: args.type,\n content: args.content,\n title: args.title,\n tags: args.tags,\n importance: args.importance,\n context,\n source: args.source,\n project,\n },\n null,\n );\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","import { z } from 'zod';\n\n// ── Memory Types ──────────────────────────────────────────────\n\nexport const MEMORY_TYPES = ['working', 'episodic', 'semantic', 'procedural', 'pattern'] as const;\nexport type MemoryType = typeof MEMORY_TYPES[number];\n\nexport const MEMORY_SOURCES = ['manual', 'session_end', 'consolidation', 'hook', 'import'] as const;\nexport type MemorySource = typeof MEMORY_SOURCES[number];\n\nexport const RELATION_TYPES = [\n 'relates_to', 'depends_on', 'contradicts', 'extends', 'implements', 'derived_from',\n] as const;\nexport type RelationType = typeof RELATION_TYPES[number];\n\n// ── Core Entities ─────────────────────────────────────────────\n\nexport interface Memory {\n readonly id: string;\n readonly type: MemoryType;\n readonly title: string | null;\n readonly content: string;\n readonly context: string | null;\n readonly source: MemorySource | null;\n readonly project: string | null;\n readonly tags: readonly string[];\n readonly importance: number;\n readonly createdAt: string;\n readonly updatedAt: string;\n readonly accessCount: number;\n readonly lastAccessed: string | null;\n readonly injectionCount: number;\n}\n\nexport interface Relation {\n readonly sourceId: string;\n readonly targetId: string;\n readonly relationType: RelationType;\n readonly createdAt: string;\n}\n\n// ── Search Types ──────────────────────────────────────────────\n\nexport interface SearchResult {\n readonly memory: Memory;\n readonly score: number;\n readonly explanation: string;\n}\n\nexport interface FtsMatch {\n readonly rowid: number;\n readonly memoryId: string;\n readonly rank: number;\n}\n\nexport interface ScoredCandidate {\n readonly memoryId: string;\n readonly textScore: number;\n readonly importanceScore: number;\n readonly recencyScore: number;\n readonly accessScore: number;\n readonly contextScore: number;\n readonly composite: number;\n}\n\n// ── Decay Parameters ──────────────────────────────────────────\n\nexport interface DecayParams {\n readonly tauByType: Record<MemoryType, number>;\n readonly accessModifiers: readonly { readonly maxCount: number; readonly multiplier: number }[];\n readonly relationModifier: { readonly connectedThreshold: number; readonly connectedMultiplier: number; readonly isolatedMultiplier: number };\n readonly importanceFloor: number;\n readonly pruneThreshold: number;\n readonly pruneMinAgeDays: number;\n}\n\n// ── Input Schemas (for MCP tools) ─────────────────────────────\n\nexport const StoreInputSchema = z.object({\n type: z.enum(MEMORY_TYPES),\n content: z.string().min(1).max(10000),\n title: z.string().max(200).optional(),\n tags: z.array(z.string()).max(20).default([]),\n importance: z.number().min(0).max(1).default(0.5),\n context: z.string().optional(),\n source: z.enum(MEMORY_SOURCES).default('manual'),\n project: z.string().max(200).optional(),\n});\nexport type StoreInput = z.infer<typeof StoreInputSchema>;\n\nexport const SearchInputSchema = z.object({\n query: z.string().min(1).max(500),\n id: z.string().optional(),\n type: z.enum(MEMORY_TYPES).optional(),\n tags: z.array(z.string()).max(10).optional(),\n limit: z.number().int().min(1).max(50).default(10),\n min_importance: z.number().min(0).max(1).default(0),\n project: z.string().max(200).optional(),\n});\nexport type SearchInput = z.infer<typeof SearchInputSchema>;\n\nexport const ForgetInputSchema = z.object({\n id: z.string(),\n hard_delete: z.boolean().default(false),\n});\nexport type ForgetInput = z.infer<typeof ForgetInputSchema>;\n\nexport const RelateInputSchema = z.object({\n source_id: z.string(),\n target_id: z.string(),\n relation_type: z.enum(RELATION_TYPES),\n});\nexport type RelateInput = z.infer<typeof RelateInputSchema>;\n\n// ── Stats ─────────────────────────────────────────────────────\n\nexport interface MemoryStats {\n readonly totalMemories: number;\n readonly byType: Record<MemoryType, number>;\n readonly totalRelations: number;\n readonly dbSizeBytes: number;\n readonly oldestMemory: string | null;\n readonly newestMemory: string | null;\n readonly topInjected: readonly { readonly id: string; readonly title: string | null; readonly injectionCount: number }[];\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.slice(0, 500),\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.slice(0, 500),\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","z","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/tools/store.ts","../../../src/commands/memory/types.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 + '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 { z } from 'zod';\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\nconst inputSchema = {\n type: z.enum(MEMORY_TYPES).describe('Memory type: working, episodic, semantic, procedural, or pattern'),\n content: z.string().min(1).max(10000).describe('The memory content to store'),\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 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 // 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 const memory = deps.memoryRepo.create(\n {\n type: args.type,\n content: args.content,\n title: args.title,\n tags: args.tags,\n importance: args.importance,\n context,\n source: args.source,\n project,\n },\n null,\n );\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","import { z } from 'zod';\n\n// ── Memory Types ──────────────────────────────────────────────\n\nexport const MEMORY_TYPES = ['working', 'episodic', 'semantic', 'procedural', 'pattern'] as const;\nexport type MemoryType = typeof MEMORY_TYPES[number];\n\nexport const MEMORY_SOURCES = ['manual', 'session_end', 'consolidation', 'hook', 'import'] as const;\nexport type MemorySource = typeof MEMORY_SOURCES[number];\n\nexport const RELATION_TYPES = [\n 'relates_to', 'depends_on', 'contradicts', 'extends', 'implements', 'derived_from',\n] as const;\nexport type RelationType = typeof RELATION_TYPES[number];\n\n// ── Core Entities ─────────────────────────────────────────────\n\nexport interface Memory {\n readonly id: string;\n readonly type: MemoryType;\n readonly title: string | null;\n readonly content: string;\n readonly context: string | null;\n readonly source: MemorySource | null;\n readonly project: string | null;\n readonly tags: readonly string[];\n readonly importance: number;\n readonly createdAt: string;\n readonly updatedAt: string;\n readonly accessCount: number;\n readonly lastAccessed: string | null;\n readonly injectionCount: number;\n}\n\nexport interface Relation {\n readonly sourceId: string;\n readonly targetId: string;\n readonly relationType: RelationType;\n readonly createdAt: string;\n}\n\n// ── Search Types ──────────────────────────────────────────────\n\nexport interface SearchResult {\n readonly memory: Memory;\n readonly score: number;\n readonly explanation: string;\n}\n\nexport interface FtsMatch {\n readonly rowid: number;\n readonly memoryId: string;\n readonly rank: number;\n}\n\nexport interface ScoredCandidate {\n readonly memoryId: string;\n readonly textScore: number;\n readonly importanceScore: number;\n readonly recencyScore: number;\n readonly accessScore: number;\n readonly contextScore: number;\n readonly composite: number;\n}\n\n// ── Decay Parameters ──────────────────────────────────────────\n\nexport interface DecayParams {\n readonly tauByType: Record<MemoryType, number>;\n readonly accessModifiers: readonly { readonly maxCount: number; readonly multiplier: number }[];\n readonly relationModifier: { readonly connectedThreshold: number; readonly connectedMultiplier: number; readonly isolatedMultiplier: number };\n readonly importanceFloor: number;\n readonly pruneThreshold: number;\n readonly pruneMinAgeDays: number;\n}\n\n// ── Input Schemas (for MCP tools) ─────────────────────────────\n\nexport const StoreInputSchema = z.object({\n type: z.enum(MEMORY_TYPES),\n content: z.string().min(1).max(10000),\n title: z.string().max(200).optional(),\n tags: z.array(z.string()).max(20).default([]),\n importance: z.number().min(0).max(1).default(0.5),\n context: z.string().optional(),\n source: z.enum(MEMORY_SOURCES).default('manual'),\n project: z.string().max(200).optional(),\n});\nexport type StoreInput = z.infer<typeof StoreInputSchema>;\n\nexport const SearchInputSchema = z.object({\n query: z.string().min(1).max(500),\n id: z.string().optional(),\n type: z.enum(MEMORY_TYPES).optional(),\n tags: z.array(z.string()).max(10).optional(),\n limit: z.number().int().min(1).max(50).default(10),\n min_importance: z.number().min(0).max(1).default(0),\n project: z.string().max(200).optional(),\n});\nexport type SearchInput = z.infer<typeof SearchInputSchema>;\n\nexport const ForgetInputSchema = z.object({\n id: z.string(),\n hard_delete: z.boolean().default(false),\n});\nexport type ForgetInput = z.infer<typeof ForgetInputSchema>;\n\nexport const RelateInputSchema = z.object({\n source_id: z.string(),\n target_id: z.string(),\n relation_type: z.enum(RELATION_TYPES),\n});\nexport type RelateInput = z.infer<typeof RelateInputSchema>;\n\n// ── Stats ─────────────────────────────────────────────────────\n\nexport interface MemoryStats {\n readonly totalMemories: number;\n readonly byType: Record<MemoryType, number>;\n readonly totalRelations: number;\n readonly dbSizeBytes: number;\n readonly oldestMemory: string | null;\n readonly newestMemory: string | null;\n readonly topInjected: readonly { readonly id: string; readonly title: string | null; readonly injectionCount: number }[];\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.slice(0, 500),\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.slice(0, 500),\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","z","z","inputSchema","z","z","inputSchema","z","z","inputSchema","z","z","inputSchema","z","z","inputSchema"]}
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
RetrievalService
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-EU2OXNTI.js";
|
|
5
5
|
import {
|
|
6
6
|
detectProject
|
|
7
7
|
} from "./chunk-NAW47BYA.js";
|
|
8
8
|
import {
|
|
9
9
|
initStorage
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-P77WV5BF.js";
|
|
11
11
|
import "./chunk-TALTTAMW.js";
|
|
12
12
|
import {
|
|
13
13
|
DEFAULT_DECAY_PARAMS
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import "./chunk-
|
|
14
|
+
} from "./chunk-RKN3XZO4.js";
|
|
15
|
+
import "./chunk-FQN5PHEU.js";
|
|
16
|
+
import "./chunk-FL3JGYDM.js";
|
|
16
17
|
|
|
17
18
|
// src/commands/memory/subcommands/context.ts
|
|
18
19
|
import { readFileSync, writeFileSync } from "fs";
|
|
@@ -313,4 +314,4 @@ function formatGraphEntry(entry) {
|
|
|
313
314
|
export {
|
|
314
315
|
runContext
|
|
315
316
|
};
|
|
316
|
-
//# sourceMappingURL=context-
|
|
317
|
+
//# sourceMappingURL=context-ANYE6ORS.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/memory/subcommands/context.ts","../src/commands/memory/services/decay-service.ts","../src/commands/memory/services/consolidation-service.ts"],"sourcesContent":["import { readFileSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { RetrievalService } from '../services/retrieval-service.js';\nimport { DecayService } from '../services/decay-service.js';\nimport { ConsolidationService } from '../services/consolidation-service.js';\nimport { detectProject } from '../utils/project.js';\nimport { initStorage } from './init-storage.js';\nimport type { MemoryType } from '../types.js';\n\ninterface ContextOpts {\n readonly json?: boolean;\n readonly type?: string;\n readonly limit?: number;\n readonly dbPath?: string;\n}\n\nconst FULL_INJECT_THRESHOLD = 10;\nconst CONSOLIDATION_FILE = '.last-consolidation';\n\nfunction shouldConsolidate(dataDir: string, intervalDays: number): boolean {\n const checkpointPath = join(dataDir, CONSOLIDATION_FILE);\n try {\n const raw = readFileSync(checkpointPath, 'utf-8').trim();\n const lastRun = parseInt(raw, 10);\n if (isNaN(lastRun)) return true;\n const daysSince = (Date.now() - lastRun) / 86_400_000;\n return daysSince >= intervalDays;\n } catch {\n return true;\n }\n}\n\nfunction markConsolidated(dataDir: string): void {\n writeFileSync(join(dataDir, CONSOLIDATION_FILE), String(Date.now()), 'utf-8');\n}\n\nfunction write(msg: string): void {\n process.stdout.write(msg + '\\n');\n}\n\nexport async function runContext(opts: ContextOpts): Promise<void> {\n const ctx = initStorage(opts.dbPath);\n\n try {\n // Run maintenance (decay + consolidation) before loading context\n try {\n const decayService = new DecayService({\n memoryRepo: ctx.memoryRepo,\n relationRepo: ctx.relationRepo,\n });\n decayService.run();\n\n if (shouldConsolidate(ctx.dataDir, ctx.config.consolidationInterval)) {\n const consolidationService = new ConsolidationService({\n memoryRepo: ctx.memoryRepo,\n relationRepo: ctx.relationRepo,\n });\n await consolidationService.consolidate();\n markConsolidated(ctx.dataDir);\n }\n } catch (err) {\n process.stderr.write(`[agentic-memory] maintenance error: ${err instanceof Error ? err.message : err}\\n`);\n }\n\n const retrievalService = new RetrievalService({\n memoryRepo: ctx.memoryRepo,\n relationRepo: ctx.relationRepo,\n searchRepo: ctx.searchRepo,\n });\n\n const project = detectProject(process.cwd());\n const totalCount = ctx.memoryRepo.count(project ?? undefined);\n\n const results = retrievalService.loadSessionContext({\n limit: opts.limit ?? FULL_INJECT_THRESHOLD,\n project: project ?? undefined,\n type: opts.type as MemoryType | undefined,\n });\n\n if (results.length === 0) {\n write('No memories found for this project.');\n return;\n }\n\n const useGraph = totalCount > FULL_INJECT_THRESHOLD;\n\n if (opts.json) {\n write('# Agentic Memory - Session Context');\n if (useGraph) {\n write(`${totalCount} memories stored. Showing index only - use memory_search to get full content.\\n`);\n const graph = results.map(r => formatGraphEntry(r));\n write(JSON.stringify({ mode: 'graph', totalMemories: totalCount, memories: graph }, null, 2));\n } else {\n write('The following memories were loaded from previous sessions. Treat these as known facts.');\n write('When the user asks about something covered here, answer from these memories directly.\\n');\n const sections = {\n contextMatched: results.filter(r => r.section === 'context').map(formatFullEntry),\n recent: results.filter(r => r.section === 'recent').map(formatFullEntry),\n related: results.filter(r => r.section === 'related').map(formatFullEntry),\n };\n write(JSON.stringify({ mode: 'full', ...sections }, null, 2));\n }\n } else {\n write(`agentic-memory - Session context (${results.length}/${totalCount} memories)\\n`);\n for (const r of results) {\n const m = r.result.memory;\n write(` ${m.title ?? '(untitled)'} [${m.type}] - ${m.content.slice(0, 100)}${m.content.length > 100 ? '...' : ''}`);\n }\n }\n } finally {\n ctx.close();\n }\n}\n\ninterface ContextEntry {\n readonly section: string;\n readonly result: {\n readonly memory: {\n readonly id: string;\n readonly type: string;\n readonly title: string | null;\n readonly content: string;\n readonly importance: number;\n readonly tags: readonly string[];\n readonly createdAt: string;\n };\n readonly score: number;\n readonly explanation: string;\n };\n}\n\nfunction formatFullEntry(entry: ContextEntry) {\n const m = entry.result.memory;\n return {\n id: m.id,\n type: m.type,\n title: m.title,\n content: m.content.slice(0, 500),\n importance: m.importance,\n tags: m.tags,\n score: Math.round(entry.result.score * 100) / 100,\n createdAt: m.createdAt,\n };\n}\n\nfunction formatGraphEntry(entry: ContextEntry) {\n const m = entry.result.memory;\n return {\n id: m.id,\n type: m.type,\n title: m.title,\n importance: m.importance,\n tags: m.tags,\n section: entry.section,\n };\n}\n","import type { Memory, DecayParams } from '../types.js';\nimport type { MemoryRepo } from '../storage/memory-repo.js';\nimport type { RelationRepo } from '../storage/relation-repo.js';\nimport { DEFAULT_DECAY_PARAMS } from '../config.js';\n\n// ── Types ────────────────────────────────────────────────────\n\nexport interface DecayServiceDeps {\n readonly memoryRepo: MemoryRepo;\n readonly relationRepo: RelationRepo;\n readonly params?: DecayParams;\n}\n\nexport interface DecayReport {\n readonly decayed: number;\n readonly pruned: number;\n readonly workingCleared: number;\n}\n\n// ── Decay Service ────────────────────────────────────────────\n\nexport class DecayService {\n readonly #memoryRepo: MemoryRepo;\n readonly #relationRepo: RelationRepo;\n readonly #params: DecayParams;\n\n constructor(deps: DecayServiceDeps) {\n this.#memoryRepo = deps.memoryRepo;\n this.#relationRepo = deps.relationRepo;\n this.#params = deps.params ?? DEFAULT_DECAY_PARAMS;\n }\n\n /**\n * Run full decay cycle: clear working memories, apply decay, prune dead memories.\n */\n run(): DecayReport {\n const workingCleared = this.clearWorkingMemories();\n const decayed = this.decayAll();\n const pruned = this.prune();\n return { decayed, pruned, workingCleared };\n }\n\n clearWorkingMemories(): number {\n return this.#memoryRepo.deleteByType('working');\n }\n\n /**\n * Apply decay formula to all non-working memories.\n */\n decayAll(): number {\n const memories = this.#memoryRepo.getAll();\n let updated = 0;\n\n for (const memory of memories) {\n if (memory.type === 'working') continue;\n\n const newImportance = this.computeDecayedImportance(memory);\n if (Math.abs(newImportance - memory.importance) > 0.001) {\n this.#memoryRepo.updateImportanceOnly(memory.id, newImportance);\n updated++;\n }\n }\n\n return updated;\n }\n\n /**\n * Hard-delete memories below prune threshold.\n */\n prune(): number {\n const memories = this.#memoryRepo.getAll();\n const now = Date.now();\n let pruned = 0;\n\n for (const memory of memories) {\n if (memory.type === 'working') continue;\n\n const ageDays = (now - new Date(memory.createdAt).getTime()) / (1000 * 60 * 60 * 24);\n if (\n ageDays > this.#params.pruneMinAgeDays &&\n memory.importance < this.#params.pruneThreshold &&\n memory.accessCount === 0\n ) {\n this.#memoryRepo.hardDelete(memory.id);\n pruned++;\n }\n }\n\n return pruned;\n }\n\n /**\n * Compute decayed importance as a pure function of age from creation.\n * Uses createdAt (immutable) to avoid compounding decay across sessions.\n */\n computeDecayedImportance(memory: Memory): number {\n const tau = this.#params.tauByType[memory.type];\n if (tau === 0) return memory.importance;\n\n const ageDays = (Date.now() - new Date(memory.createdAt).getTime()) / (1000 * 60 * 60 * 24);\n if (ageDays < 0) return memory.importance;\n\n // Synaptic consolidation window (days 0-7)\n if (ageDays <= 7) {\n if (memory.type === 'episodic') {\n const ebbinghaus = Math.exp(-ageDays * 0.4);\n return Math.max(this.#params.importanceFloor, memory.importance * ebbinghaus);\n }\n return memory.importance;\n }\n\n // Access modifier: higher access count = larger tau = slower decay\n const accessModifier = this.getAccessModifier(memory.accessCount);\n\n // Relation modifier: connected memories decay slower\n const relationCount = this.#relationRepo.countByMemory(memory.id);\n const relationModifier = relationCount >= this.#params.relationModifier.connectedThreshold\n ? this.#params.relationModifier.connectedMultiplier\n : this.#params.relationModifier.isolatedMultiplier;\n\n let effectiveTau = tau * accessModifier * relationModifier;\n\n // Injection penalty: surfaced but never used = noise\n if (memory.injectionCount > 5 && memory.accessCount === 0) {\n effectiveTau /= 1.5;\n }\n\n const decayFactor = Math.exp(-(ageDays - 7) / effectiveTau);\n const newImportance = memory.importance * decayFactor;\n\n return Math.max(this.#params.importanceFloor, newImportance);\n }\n\n private getAccessModifier(accessCount: number): number {\n for (const tier of this.#params.accessModifiers) {\n if (accessCount <= tier.maxCount) return tier.multiplier;\n }\n return 1.0;\n }\n}\n","import type { MemoryRepo } from '../storage/memory-repo.js';\nimport type { RelationRepo } from '../storage/relation-repo.js';\n\n// ── Types ────────────────────────────────────────────────────\n\nexport interface ConsolidationDeps {\n readonly memoryRepo: MemoryRepo;\n readonly relationRepo: RelationRepo;\n}\n\nexport interface ConsolidationReport {\n readonly deduplicated: number;\n readonly episodicsCompressed: number;\n readonly pruned: number;\n}\n\n// ── Consolidation Service ────────────────────────────────────\n\nexport class ConsolidationService {\n readonly #deps: ConsolidationDeps;\n\n constructor(deps: ConsolidationDeps) {\n this.#deps = deps;\n }\n\n /**\n * Run consolidation pipeline.\n * Phase 1: Deduplicate exact/near-exact content matches\n * Phase 2: Compress old consolidated episodics\n * Phase 3: Prune dead memories\n */\n async consolidate(): Promise<ConsolidationReport> {\n const deduplicated = this.deduplicateMemories();\n const episodicsCompressed = this.compressEpisodics();\n const pruned = this.prune();\n return { deduplicated, episodicsCompressed, pruned };\n }\n\n /**\n * Phase 1: Deduplication via content similarity.\n */\n deduplicateMemories(): number {\n const memories = this.#deps.memoryRepo.getAll();\n const seen = new Set<string>();\n let merged = 0;\n\n for (const memory of memories) {\n if (seen.has(memory.id)) continue;\n\n const normalizedContent = normalizeText(memory.content);\n\n for (const other of memories) {\n if (other.id === memory.id) continue;\n if (seen.has(other.id)) continue;\n\n const otherNormalized = normalizeText(other.content);\n if (normalizedContent !== otherNormalized) continue;\n\n const [keeper, discard] = memory.importance >= other.importance\n ? [memory, other] : [other, memory];\n\n const mergedTags = [...new Set([...keeper.tags, ...discard.tags])];\n this.#deps.memoryRepo.updateContent(keeper.id, {\n tags: mergedTags,\n importance: Math.max(keeper.importance, discard.importance),\n });\n\n this.#deps.memoryRepo.hardDelete(discard.id);\n seen.add(discard.id);\n merged++;\n\n if (discard.id === memory.id) break;\n }\n\n seen.add(memory.id);\n }\n\n return merged;\n }\n\n /**\n * Phase 2: Compress old episodic memories that have been consolidated.\n */\n compressEpisodics(): number {\n const episodics = this.#deps.memoryRepo.getByType('episodic');\n const now = Date.now();\n let compressed = 0;\n\n for (const memory of episodics) {\n const ageDays = (now - new Date(memory.createdAt).getTime()) / (1000 * 60 * 60 * 24);\n if (ageDays <= 60) continue;\n if (memory.accessCount > 0) continue;\n if (memory.importance >= 0.2) continue;\n\n const relations = this.#deps.relationRepo.getBySource(memory.id);\n const isConsolidated = relations.some(r => r.relationType === 'derived_from');\n if (!isConsolidated) continue;\n\n this.#deps.memoryRepo.hardDelete(memory.id);\n compressed++;\n }\n\n return compressed;\n }\n\n /**\n * Phase 3: Prune dead memories.\n */\n prune(): number {\n const memories = this.#deps.memoryRepo.getAll();\n const now = Date.now();\n let pruned = 0;\n\n for (const memory of memories) {\n if (memory.type === 'working') continue;\n const ageDays = (now - new Date(memory.createdAt).getTime()) / (1000 * 60 * 60 * 24);\n if (ageDays > 90 && memory.importance < 0.1 && memory.accessCount === 0) {\n this.#deps.memoryRepo.hardDelete(memory.id);\n pruned++;\n }\n }\n\n return pruned;\n }\n}\n\n// ── Helpers ──────────────────────────────────────────────────\n\nfunction normalizeText(text: string): string {\n return text.toLowerCase().replace(/\\s+/g, ' ').trim();\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/commands/memory/subcommands/context.ts","../src/commands/memory/services/decay-service.ts","../src/commands/memory/services/consolidation-service.ts"],"sourcesContent":["import { readFileSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { RetrievalService } from '../services/retrieval-service.js';\nimport { DecayService } from '../services/decay-service.js';\nimport { ConsolidationService } from '../services/consolidation-service.js';\nimport { detectProject } from '../utils/project.js';\nimport { initStorage } from './init-storage.js';\nimport type { MemoryType } from '../types.js';\n\ninterface ContextOpts {\n readonly json?: boolean;\n readonly type?: string;\n readonly limit?: number;\n readonly dbPath?: string;\n}\n\nconst FULL_INJECT_THRESHOLD = 10;\nconst CONSOLIDATION_FILE = '.last-consolidation';\n\nfunction shouldConsolidate(dataDir: string, intervalDays: number): boolean {\n const checkpointPath = join(dataDir, CONSOLIDATION_FILE);\n try {\n const raw = readFileSync(checkpointPath, 'utf-8').trim();\n const lastRun = parseInt(raw, 10);\n if (isNaN(lastRun)) return true;\n const daysSince = (Date.now() - lastRun) / 86_400_000;\n return daysSince >= intervalDays;\n } catch {\n return true;\n }\n}\n\nfunction markConsolidated(dataDir: string): void {\n writeFileSync(join(dataDir, CONSOLIDATION_FILE), String(Date.now()), 'utf-8');\n}\n\nfunction write(msg: string): void {\n process.stdout.write(msg + '\\n');\n}\n\nexport async function runContext(opts: ContextOpts): Promise<void> {\n const ctx = initStorage(opts.dbPath);\n\n try {\n // Run maintenance (decay + consolidation) before loading context\n try {\n const decayService = new DecayService({\n memoryRepo: ctx.memoryRepo,\n relationRepo: ctx.relationRepo,\n });\n decayService.run();\n\n if (shouldConsolidate(ctx.dataDir, ctx.config.consolidationInterval)) {\n const consolidationService = new ConsolidationService({\n memoryRepo: ctx.memoryRepo,\n relationRepo: ctx.relationRepo,\n });\n await consolidationService.consolidate();\n markConsolidated(ctx.dataDir);\n }\n } catch (err) {\n process.stderr.write(`[agentic-memory] maintenance error: ${err instanceof Error ? err.message : err}\\n`);\n }\n\n const retrievalService = new RetrievalService({\n memoryRepo: ctx.memoryRepo,\n relationRepo: ctx.relationRepo,\n searchRepo: ctx.searchRepo,\n });\n\n const project = detectProject(process.cwd());\n const totalCount = ctx.memoryRepo.count(project ?? undefined);\n\n const results = retrievalService.loadSessionContext({\n limit: opts.limit ?? FULL_INJECT_THRESHOLD,\n project: project ?? undefined,\n type: opts.type as MemoryType | undefined,\n });\n\n if (results.length === 0) {\n write('No memories found for this project.');\n return;\n }\n\n const useGraph = totalCount > FULL_INJECT_THRESHOLD;\n\n if (opts.json) {\n write('# Agentic Memory - Session Context');\n if (useGraph) {\n write(`${totalCount} memories stored. Showing index only - use memory_search to get full content.\\n`);\n const graph = results.map(r => formatGraphEntry(r));\n write(JSON.stringify({ mode: 'graph', totalMemories: totalCount, memories: graph }, null, 2));\n } else {\n write('The following memories were loaded from previous sessions. Treat these as known facts.');\n write('When the user asks about something covered here, answer from these memories directly.\\n');\n const sections = {\n contextMatched: results.filter(r => r.section === 'context').map(formatFullEntry),\n recent: results.filter(r => r.section === 'recent').map(formatFullEntry),\n related: results.filter(r => r.section === 'related').map(formatFullEntry),\n };\n write(JSON.stringify({ mode: 'full', ...sections }, null, 2));\n }\n } else {\n write(`agentic-memory - Session context (${results.length}/${totalCount} memories)\\n`);\n for (const r of results) {\n const m = r.result.memory;\n write(` ${m.title ?? '(untitled)'} [${m.type}] - ${m.content.slice(0, 100)}${m.content.length > 100 ? '...' : ''}`);\n }\n }\n } finally {\n ctx.close();\n }\n}\n\ninterface ContextEntry {\n readonly section: string;\n readonly result: {\n readonly memory: {\n readonly id: string;\n readonly type: string;\n readonly title: string | null;\n readonly content: string;\n readonly importance: number;\n readonly tags: readonly string[];\n readonly createdAt: string;\n };\n readonly score: number;\n readonly explanation: string;\n };\n}\n\nfunction formatFullEntry(entry: ContextEntry) {\n const m = entry.result.memory;\n return {\n id: m.id,\n type: m.type,\n title: m.title,\n content: m.content.slice(0, 500),\n importance: m.importance,\n tags: m.tags,\n score: Math.round(entry.result.score * 100) / 100,\n createdAt: m.createdAt,\n };\n}\n\nfunction formatGraphEntry(entry: ContextEntry) {\n const m = entry.result.memory;\n return {\n id: m.id,\n type: m.type,\n title: m.title,\n importance: m.importance,\n tags: m.tags,\n section: entry.section,\n };\n}\n","import type { Memory, DecayParams } from '../types.js';\nimport type { MemoryRepo } from '../storage/memory-repo.js';\nimport type { RelationRepo } from '../storage/relation-repo.js';\nimport { DEFAULT_DECAY_PARAMS } from '../config.js';\n\n// ── Types ────────────────────────────────────────────────────\n\nexport interface DecayServiceDeps {\n readonly memoryRepo: MemoryRepo;\n readonly relationRepo: RelationRepo;\n readonly params?: DecayParams;\n}\n\nexport interface DecayReport {\n readonly decayed: number;\n readonly pruned: number;\n readonly workingCleared: number;\n}\n\n// ── Decay Service ────────────────────────────────────────────\n\nexport class DecayService {\n readonly #memoryRepo: MemoryRepo;\n readonly #relationRepo: RelationRepo;\n readonly #params: DecayParams;\n\n constructor(deps: DecayServiceDeps) {\n this.#memoryRepo = deps.memoryRepo;\n this.#relationRepo = deps.relationRepo;\n this.#params = deps.params ?? DEFAULT_DECAY_PARAMS;\n }\n\n /**\n * Run full decay cycle: clear working memories, apply decay, prune dead memories.\n */\n run(): DecayReport {\n const workingCleared = this.clearWorkingMemories();\n const decayed = this.decayAll();\n const pruned = this.prune();\n return { decayed, pruned, workingCleared };\n }\n\n clearWorkingMemories(): number {\n return this.#memoryRepo.deleteByType('working');\n }\n\n /**\n * Apply decay formula to all non-working memories.\n */\n decayAll(): number {\n const memories = this.#memoryRepo.getAll();\n let updated = 0;\n\n for (const memory of memories) {\n if (memory.type === 'working') continue;\n\n const newImportance = this.computeDecayedImportance(memory);\n if (Math.abs(newImportance - memory.importance) > 0.001) {\n this.#memoryRepo.updateImportanceOnly(memory.id, newImportance);\n updated++;\n }\n }\n\n return updated;\n }\n\n /**\n * Hard-delete memories below prune threshold.\n */\n prune(): number {\n const memories = this.#memoryRepo.getAll();\n const now = Date.now();\n let pruned = 0;\n\n for (const memory of memories) {\n if (memory.type === 'working') continue;\n\n const ageDays = (now - new Date(memory.createdAt).getTime()) / (1000 * 60 * 60 * 24);\n if (\n ageDays > this.#params.pruneMinAgeDays &&\n memory.importance < this.#params.pruneThreshold &&\n memory.accessCount === 0\n ) {\n this.#memoryRepo.hardDelete(memory.id);\n pruned++;\n }\n }\n\n return pruned;\n }\n\n /**\n * Compute decayed importance as a pure function of age from creation.\n * Uses createdAt (immutable) to avoid compounding decay across sessions.\n */\n computeDecayedImportance(memory: Memory): number {\n const tau = this.#params.tauByType[memory.type];\n if (tau === 0) return memory.importance;\n\n const ageDays = (Date.now() - new Date(memory.createdAt).getTime()) / (1000 * 60 * 60 * 24);\n if (ageDays < 0) return memory.importance;\n\n // Synaptic consolidation window (days 0-7)\n if (ageDays <= 7) {\n if (memory.type === 'episodic') {\n const ebbinghaus = Math.exp(-ageDays * 0.4);\n return Math.max(this.#params.importanceFloor, memory.importance * ebbinghaus);\n }\n return memory.importance;\n }\n\n // Access modifier: higher access count = larger tau = slower decay\n const accessModifier = this.getAccessModifier(memory.accessCount);\n\n // Relation modifier: connected memories decay slower\n const relationCount = this.#relationRepo.countByMemory(memory.id);\n const relationModifier = relationCount >= this.#params.relationModifier.connectedThreshold\n ? this.#params.relationModifier.connectedMultiplier\n : this.#params.relationModifier.isolatedMultiplier;\n\n let effectiveTau = tau * accessModifier * relationModifier;\n\n // Injection penalty: surfaced but never used = noise\n if (memory.injectionCount > 5 && memory.accessCount === 0) {\n effectiveTau /= 1.5;\n }\n\n const decayFactor = Math.exp(-(ageDays - 7) / effectiveTau);\n const newImportance = memory.importance * decayFactor;\n\n return Math.max(this.#params.importanceFloor, newImportance);\n }\n\n private getAccessModifier(accessCount: number): number {\n for (const tier of this.#params.accessModifiers) {\n if (accessCount <= tier.maxCount) return tier.multiplier;\n }\n return 1.0;\n }\n}\n","import type { MemoryRepo } from '../storage/memory-repo.js';\nimport type { RelationRepo } from '../storage/relation-repo.js';\n\n// ── Types ────────────────────────────────────────────────────\n\nexport interface ConsolidationDeps {\n readonly memoryRepo: MemoryRepo;\n readonly relationRepo: RelationRepo;\n}\n\nexport interface ConsolidationReport {\n readonly deduplicated: number;\n readonly episodicsCompressed: number;\n readonly pruned: number;\n}\n\n// ── Consolidation Service ────────────────────────────────────\n\nexport class ConsolidationService {\n readonly #deps: ConsolidationDeps;\n\n constructor(deps: ConsolidationDeps) {\n this.#deps = deps;\n }\n\n /**\n * Run consolidation pipeline.\n * Phase 1: Deduplicate exact/near-exact content matches\n * Phase 2: Compress old consolidated episodics\n * Phase 3: Prune dead memories\n */\n async consolidate(): Promise<ConsolidationReport> {\n const deduplicated = this.deduplicateMemories();\n const episodicsCompressed = this.compressEpisodics();\n const pruned = this.prune();\n return { deduplicated, episodicsCompressed, pruned };\n }\n\n /**\n * Phase 1: Deduplication via content similarity.\n */\n deduplicateMemories(): number {\n const memories = this.#deps.memoryRepo.getAll();\n const seen = new Set<string>();\n let merged = 0;\n\n for (const memory of memories) {\n if (seen.has(memory.id)) continue;\n\n const normalizedContent = normalizeText(memory.content);\n\n for (const other of memories) {\n if (other.id === memory.id) continue;\n if (seen.has(other.id)) continue;\n\n const otherNormalized = normalizeText(other.content);\n if (normalizedContent !== otherNormalized) continue;\n\n const [keeper, discard] = memory.importance >= other.importance\n ? [memory, other] : [other, memory];\n\n const mergedTags = [...new Set([...keeper.tags, ...discard.tags])];\n this.#deps.memoryRepo.updateContent(keeper.id, {\n tags: mergedTags,\n importance: Math.max(keeper.importance, discard.importance),\n });\n\n this.#deps.memoryRepo.hardDelete(discard.id);\n seen.add(discard.id);\n merged++;\n\n if (discard.id === memory.id) break;\n }\n\n seen.add(memory.id);\n }\n\n return merged;\n }\n\n /**\n * Phase 2: Compress old episodic memories that have been consolidated.\n */\n compressEpisodics(): number {\n const episodics = this.#deps.memoryRepo.getByType('episodic');\n const now = Date.now();\n let compressed = 0;\n\n for (const memory of episodics) {\n const ageDays = (now - new Date(memory.createdAt).getTime()) / (1000 * 60 * 60 * 24);\n if (ageDays <= 60) continue;\n if (memory.accessCount > 0) continue;\n if (memory.importance >= 0.2) continue;\n\n const relations = this.#deps.relationRepo.getBySource(memory.id);\n const isConsolidated = relations.some(r => r.relationType === 'derived_from');\n if (!isConsolidated) continue;\n\n this.#deps.memoryRepo.hardDelete(memory.id);\n compressed++;\n }\n\n return compressed;\n }\n\n /**\n * Phase 3: Prune dead memories.\n */\n prune(): number {\n const memories = this.#deps.memoryRepo.getAll();\n const now = Date.now();\n let pruned = 0;\n\n for (const memory of memories) {\n if (memory.type === 'working') continue;\n const ageDays = (now - new Date(memory.createdAt).getTime()) / (1000 * 60 * 60 * 24);\n if (ageDays > 90 && memory.importance < 0.1 && memory.accessCount === 0) {\n this.#deps.memoryRepo.hardDelete(memory.id);\n pruned++;\n }\n }\n\n return pruned;\n }\n}\n\n// ── Helpers ──────────────────────────────────────────────────\n\nfunction normalizeText(text: string): string {\n return text.toLowerCase().replace(/\\s+/g, ' ').trim();\n}\n"],"mappings":"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","names":[]}
|
|
@@ -4,10 +4,11 @@ import {
|
|
|
4
4
|
} from "./chunk-NAW47BYA.js";
|
|
5
5
|
import {
|
|
6
6
|
initStorage
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-P77WV5BF.js";
|
|
8
8
|
import "./chunk-TALTTAMW.js";
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-RKN3XZO4.js";
|
|
10
|
+
import "./chunk-FQN5PHEU.js";
|
|
11
|
+
import "./chunk-FL3JGYDM.js";
|
|
11
12
|
|
|
12
13
|
// src/commands/memory/subcommands/extract.ts
|
|
13
14
|
import { existsSync, readFileSync } from "fs";
|
|
@@ -214,4 +215,4 @@ function readStdin(timeoutMs) {
|
|
|
214
215
|
export {
|
|
215
216
|
runExtract
|
|
216
217
|
};
|
|
217
|
-
//# sourceMappingURL=extract-
|
|
218
|
+
//# sourceMappingURL=extract-MVN35LES.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/memory/subcommands/extract.ts","../src/commands/memory/services/session-service.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport { parseTranscript, extractFacts } from '../services/session-service.js';\nimport { detectProject } from '../utils/project.js';\nimport { initStorage } from './init-storage.js';\n\nexport async function runExtract(): Promise<void> {\n // Read hook input from stdin (Claude Code pipes JSON)\n let stdinData = '';\n try {\n stdinData = await readStdin(5000);\n } catch {\n process.stderr.write('[agentic-memory] extract: no stdin data received\\n');\n return;\n }\n\n if (!stdinData.trim()) {\n process.stderr.write('[agentic-memory] extract: empty stdin\\n');\n return;\n }\n\n let hookInput: { transcript_path?: string; cwd?: string };\n try {\n hookInput = JSON.parse(stdinData) as { transcript_path?: string; cwd?: string };\n } catch {\n process.stderr.write('[agentic-memory] extract: invalid JSON on stdin\\n');\n return;\n }\n\n const transcriptPath = hookInput.transcript_path;\n if (!transcriptPath || !existsSync(transcriptPath)) {\n process.stderr.write(`[agentic-memory] extract: transcript not found: ${transcriptPath}\\n`);\n return;\n }\n\n let transcriptContent: string;\n try {\n transcriptContent = readFileSync(transcriptPath, 'utf-8');\n } catch (err) {\n process.stderr.write(`[agentic-memory] extract: failed to read transcript: ${err instanceof Error ? err.message : err}\\n`);\n return;\n }\n\n const text = parseTranscript(transcriptContent);\n if (!text || text.length < 50) return;\n\n const facts = extractFacts(text);\n if (facts.length === 0) return;\n\n const ctx = initStorage();\n const project = detectProject(hookInput.cwd ?? process.cwd());\n\n try {\n let stored = 0;\n for (const fact of facts) {\n // Dedup: check if similar content already exists\n try {\n const existing = ctx.searchRepo.searchFts({\n query: fact.content.slice(0, 100),\n limit: 1,\n });\n if (existing.length > 0 && Math.abs(existing[0]!.rank) > 15) {\n continue; // Strong text match = likely duplicate\n }\n } catch {\n // Dedup is best-effort\n }\n\n ctx.memoryRepo.create(\n {\n type: fact.type,\n content: fact.content,\n tags: [...fact.tags],\n importance: fact.importance,\n source: 'hook',\n project: project ?? undefined,\n },\n null,\n );\n stored++;\n }\n\n if (stored > 0) {\n process.stderr.write(`[agentic-memory] extract: stored ${stored} facts from transcript\\n`);\n }\n } finally {\n ctx.close();\n }\n}\n\nfunction readStdin(timeoutMs: number): Promise<string> {\n if (process.stdin.isTTY) return Promise.resolve('');\n\n return new Promise((resolve, reject) => {\n let settled = false;\n const chunks: Buffer[] = [];\n\n const settle = (fn: () => void) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n process.stdin.removeListener('data', onData);\n process.stdin.removeListener('end', onEnd);\n process.stdin.removeListener('error', onError);\n fn();\n };\n\n const timer = setTimeout(() => {\n settle(() => resolve(chunks.length > 0 ? Buffer.concat(chunks).toString('utf-8') : ''));\n }, timeoutMs);\n\n const onData = (chunk: Buffer) => { chunks.push(chunk); };\n const onEnd = () => { settle(() => resolve(Buffer.concat(chunks).toString('utf-8'))); };\n const onError = (err: Error) => { settle(() => reject(err)); };\n\n process.stdin.on('data', onData);\n process.stdin.on('end', onEnd);\n process.stdin.on('error', onError);\n });\n}\n","// ── Transcript Parsing ──────────────────────────────────────\n\n/**\n * Parse a Claude Code JSONL transcript file into plain text.\n * Extracts text content from user and assistant messages.\n * Only processes the last `maxMessages` messages to stay focused.\n */\nexport function parseTranscript(jsonlContent: string, maxMessages = 50): string {\n const lines = jsonlContent.split('\\n').filter(l => l.trim().length > 0);\n const textParts: string[] = [];\n\n const startIdx = Math.max(0, lines.length - maxMessages);\n\n for (let i = startIdx; i < lines.length; i++) {\n try {\n const msg = JSON.parse(lines[i]!) as {\n type?: string;\n message?: { role?: string; content?: unknown };\n };\n\n if (msg.type !== 'user' && msg.type !== 'assistant') continue;\n\n const content = msg.message?.content;\n if (typeof content === 'string') {\n textParts.push(content);\n } else if (Array.isArray(content)) {\n for (const block of content) {\n if (typeof block === 'object' && block !== null && 'type' in block && block.type === 'text' && 'text' in block) {\n textParts.push(block.text as string);\n }\n }\n }\n } catch {\n // Skip malformed lines\n }\n }\n\n return textParts.join('\\n');\n}\n\n// ── Fact Extraction (for future session-end processing) ──────\n\nexport interface ExtractedFact {\n readonly type: 'episodic' | 'semantic' | 'procedural' | 'pattern';\n readonly content: string;\n readonly tags: readonly string[];\n readonly importance: number;\n}\n\nconst MIN_FACT_LENGTH = 30;\n\nfunction isNoiseLine(line: string): boolean {\n if (/<\\/?[a-z-]+>/i.test(line)) return true;\n if (/^\\|.*\\|$/.test(line)) return true;\n if (/^```/.test(line)) return true;\n const alphaRatio = (line.match(/[a-zA-Z]/g)?.length ?? 0) / line.length;\n if (alphaRatio < 0.4 && line.length > 20) return true;\n return false;\n}\n\nexport function extractFacts(transcript: string): readonly ExtractedFact[] {\n const facts: ExtractedFact[] = [];\n const lines = transcript.split('\\n');\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.length < 10) continue;\n\n if (isNoiseLine(trimmed)) continue;\n\n // Pattern: \"decided to X because Y\" -> semantic decision\n const decisionMatch = trimmed.match(/decided?\\s+(?:to\\s+)?(.+?)\\s+because\\s+(.+)/i);\n if (decisionMatch?.[1] && decisionMatch[2]) {\n facts.push({\n type: 'semantic',\n content: `Decision: ${decisionMatch[1].trim()}. Reason: ${decisionMatch[2].trim()}`,\n tags: ['decision'],\n importance: 0.7,\n });\n continue;\n }\n\n // Pattern: \"fixed X by Y\" -> episodic fix\n const fixMatch = trimmed.match(/(?:fixed|resolved|solved)\\s+(.+?)\\s+by\\s+(.+)/i);\n if (fixMatch?.[1] && fixMatch[2]) {\n facts.push({\n type: 'episodic',\n content: `Fixed: ${fixMatch[1].trim()}. Solution: ${fixMatch[2].trim()}`,\n tags: ['bugfix'],\n importance: 0.6,\n });\n continue;\n }\n\n // Pattern: \"learned that X\" -> semantic\n const learnMatch = trimmed.match(/(?:learned|discovered|found out|realized)\\s+(?:that\\s+)?(.+)/i);\n if (learnMatch?.[1]) {\n facts.push({\n type: 'semantic',\n content: learnMatch[1].trim(),\n tags: ['learning'],\n importance: 0.6,\n });\n continue;\n }\n\n // Pattern: \"to X, use Y\" -> procedural\n const proceduralMatch = trimmed.match(/(?:to\\s+(.+?),\\s+(?:use|run|execute|call)\\s+(.+))/i);\n if (proceduralMatch?.[1] && proceduralMatch[2]) {\n facts.push({\n type: 'procedural',\n content: `To ${proceduralMatch[1].trim()}: ${proceduralMatch[2].trim()}`,\n tags: ['howto'],\n importance: 0.6,\n });\n continue;\n }\n\n // Pattern: \"gotcha: X\" -> semantic gotcha\n const gotchaMatch = trimmed.match(/(?:gotcha|watch out|pitfall)[:!]\\s*(.+)/i);\n if (gotchaMatch?.[1] && gotchaMatch[1].trim().length >= MIN_FACT_LENGTH) {\n facts.push({\n type: 'semantic',\n content: `Gotcha: ${gotchaMatch[1].trim()}`,\n tags: ['gotcha'],\n importance: 0.7,\n });\n continue;\n }\n }\n\n return facts;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/commands/memory/subcommands/extract.ts","../src/commands/memory/services/session-service.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport { parseTranscript, extractFacts } from '../services/session-service.js';\nimport { detectProject } from '../utils/project.js';\nimport { initStorage } from './init-storage.js';\n\nexport async function runExtract(): Promise<void> {\n // Read hook input from stdin (Claude Code pipes JSON)\n let stdinData = '';\n try {\n stdinData = await readStdin(5000);\n } catch {\n process.stderr.write('[agentic-memory] extract: no stdin data received\\n');\n return;\n }\n\n if (!stdinData.trim()) {\n process.stderr.write('[agentic-memory] extract: empty stdin\\n');\n return;\n }\n\n let hookInput: { transcript_path?: string; cwd?: string };\n try {\n hookInput = JSON.parse(stdinData) as { transcript_path?: string; cwd?: string };\n } catch {\n process.stderr.write('[agentic-memory] extract: invalid JSON on stdin\\n');\n return;\n }\n\n const transcriptPath = hookInput.transcript_path;\n if (!transcriptPath || !existsSync(transcriptPath)) {\n process.stderr.write(`[agentic-memory] extract: transcript not found: ${transcriptPath}\\n`);\n return;\n }\n\n let transcriptContent: string;\n try {\n transcriptContent = readFileSync(transcriptPath, 'utf-8');\n } catch (err) {\n process.stderr.write(`[agentic-memory] extract: failed to read transcript: ${err instanceof Error ? err.message : err}\\n`);\n return;\n }\n\n const text = parseTranscript(transcriptContent);\n if (!text || text.length < 50) return;\n\n const facts = extractFacts(text);\n if (facts.length === 0) return;\n\n const ctx = initStorage();\n const project = detectProject(hookInput.cwd ?? process.cwd());\n\n try {\n let stored = 0;\n for (const fact of facts) {\n // Dedup: check if similar content already exists\n try {\n const existing = ctx.searchRepo.searchFts({\n query: fact.content.slice(0, 100),\n limit: 1,\n });\n if (existing.length > 0 && Math.abs(existing[0]!.rank) > 15) {\n continue; // Strong text match = likely duplicate\n }\n } catch {\n // Dedup is best-effort\n }\n\n ctx.memoryRepo.create(\n {\n type: fact.type,\n content: fact.content,\n tags: [...fact.tags],\n importance: fact.importance,\n source: 'hook',\n project: project ?? undefined,\n },\n null,\n );\n stored++;\n }\n\n if (stored > 0) {\n process.stderr.write(`[agentic-memory] extract: stored ${stored} facts from transcript\\n`);\n }\n } finally {\n ctx.close();\n }\n}\n\nfunction readStdin(timeoutMs: number): Promise<string> {\n if (process.stdin.isTTY) return Promise.resolve('');\n\n return new Promise((resolve, reject) => {\n let settled = false;\n const chunks: Buffer[] = [];\n\n const settle = (fn: () => void) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n process.stdin.removeListener('data', onData);\n process.stdin.removeListener('end', onEnd);\n process.stdin.removeListener('error', onError);\n fn();\n };\n\n const timer = setTimeout(() => {\n settle(() => resolve(chunks.length > 0 ? Buffer.concat(chunks).toString('utf-8') : ''));\n }, timeoutMs);\n\n const onData = (chunk: Buffer) => { chunks.push(chunk); };\n const onEnd = () => { settle(() => resolve(Buffer.concat(chunks).toString('utf-8'))); };\n const onError = (err: Error) => { settle(() => reject(err)); };\n\n process.stdin.on('data', onData);\n process.stdin.on('end', onEnd);\n process.stdin.on('error', onError);\n });\n}\n","// ── Transcript Parsing ──────────────────────────────────────\n\n/**\n * Parse a Claude Code JSONL transcript file into plain text.\n * Extracts text content from user and assistant messages.\n * Only processes the last `maxMessages` messages to stay focused.\n */\nexport function parseTranscript(jsonlContent: string, maxMessages = 50): string {\n const lines = jsonlContent.split('\\n').filter(l => l.trim().length > 0);\n const textParts: string[] = [];\n\n const startIdx = Math.max(0, lines.length - maxMessages);\n\n for (let i = startIdx; i < lines.length; i++) {\n try {\n const msg = JSON.parse(lines[i]!) as {\n type?: string;\n message?: { role?: string; content?: unknown };\n };\n\n if (msg.type !== 'user' && msg.type !== 'assistant') continue;\n\n const content = msg.message?.content;\n if (typeof content === 'string') {\n textParts.push(content);\n } else if (Array.isArray(content)) {\n for (const block of content) {\n if (typeof block === 'object' && block !== null && 'type' in block && block.type === 'text' && 'text' in block) {\n textParts.push(block.text as string);\n }\n }\n }\n } catch {\n // Skip malformed lines\n }\n }\n\n return textParts.join('\\n');\n}\n\n// ── Fact Extraction (for future session-end processing) ──────\n\nexport interface ExtractedFact {\n readonly type: 'episodic' | 'semantic' | 'procedural' | 'pattern';\n readonly content: string;\n readonly tags: readonly string[];\n readonly importance: number;\n}\n\nconst MIN_FACT_LENGTH = 30;\n\nfunction isNoiseLine(line: string): boolean {\n if (/<\\/?[a-z-]+>/i.test(line)) return true;\n if (/^\\|.*\\|$/.test(line)) return true;\n if (/^```/.test(line)) return true;\n const alphaRatio = (line.match(/[a-zA-Z]/g)?.length ?? 0) / line.length;\n if (alphaRatio < 0.4 && line.length > 20) return true;\n return false;\n}\n\nexport function extractFacts(transcript: string): readonly ExtractedFact[] {\n const facts: ExtractedFact[] = [];\n const lines = transcript.split('\\n');\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.length < 10) continue;\n\n if (isNoiseLine(trimmed)) continue;\n\n // Pattern: \"decided to X because Y\" -> semantic decision\n const decisionMatch = trimmed.match(/decided?\\s+(?:to\\s+)?(.+?)\\s+because\\s+(.+)/i);\n if (decisionMatch?.[1] && decisionMatch[2]) {\n facts.push({\n type: 'semantic',\n content: `Decision: ${decisionMatch[1].trim()}. Reason: ${decisionMatch[2].trim()}`,\n tags: ['decision'],\n importance: 0.7,\n });\n continue;\n }\n\n // Pattern: \"fixed X by Y\" -> episodic fix\n const fixMatch = trimmed.match(/(?:fixed|resolved|solved)\\s+(.+?)\\s+by\\s+(.+)/i);\n if (fixMatch?.[1] && fixMatch[2]) {\n facts.push({\n type: 'episodic',\n content: `Fixed: ${fixMatch[1].trim()}. Solution: ${fixMatch[2].trim()}`,\n tags: ['bugfix'],\n importance: 0.6,\n });\n continue;\n }\n\n // Pattern: \"learned that X\" -> semantic\n const learnMatch = trimmed.match(/(?:learned|discovered|found out|realized)\\s+(?:that\\s+)?(.+)/i);\n if (learnMatch?.[1]) {\n facts.push({\n type: 'semantic',\n content: learnMatch[1].trim(),\n tags: ['learning'],\n importance: 0.6,\n });\n continue;\n }\n\n // Pattern: \"to X, use Y\" -> procedural\n const proceduralMatch = trimmed.match(/(?:to\\s+(.+?),\\s+(?:use|run|execute|call)\\s+(.+))/i);\n if (proceduralMatch?.[1] && proceduralMatch[2]) {\n facts.push({\n type: 'procedural',\n content: `To ${proceduralMatch[1].trim()}: ${proceduralMatch[2].trim()}`,\n tags: ['howto'],\n importance: 0.6,\n });\n continue;\n }\n\n // Pattern: \"gotcha: X\" -> semantic gotcha\n const gotchaMatch = trimmed.match(/(?:gotcha|watch out|pitfall)[:!]\\s*(.+)/i);\n if (gotchaMatch?.[1] && gotchaMatch[1].trim().length >= MIN_FACT_LENGTH) {\n facts.push({\n type: 'semantic',\n content: `Gotcha: ${gotchaMatch[1].trim()}`,\n tags: ['gotcha'],\n importance: 0.7,\n });\n continue;\n }\n }\n\n return facts;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -3,24 +3,24 @@ import {
|
|
|
3
3
|
readSettingsJson,
|
|
4
4
|
writeSettingsJson
|
|
5
5
|
} from "./chunk-CSLWJEGD.js";
|
|
6
|
-
import {
|
|
7
|
-
log
|
|
8
|
-
} from "./chunk-6ZVXZ4EF.js";
|
|
9
6
|
import {
|
|
10
7
|
closeDatabase,
|
|
11
8
|
createDatabase,
|
|
12
9
|
loadConfig,
|
|
13
10
|
migrate,
|
|
14
11
|
resolveDataDir
|
|
15
|
-
} from "./chunk-
|
|
16
|
-
import "./chunk-
|
|
12
|
+
} from "./chunk-RKN3XZO4.js";
|
|
13
|
+
import "./chunk-FQN5PHEU.js";
|
|
14
|
+
import {
|
|
15
|
+
log
|
|
16
|
+
} from "./chunk-FL3JGYDM.js";
|
|
17
17
|
|
|
18
18
|
// src/commands/memory/subcommands/install.ts
|
|
19
19
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
20
20
|
import { join } from "path";
|
|
21
21
|
import { execSync } from "child_process";
|
|
22
22
|
async function runInstall(opts) {
|
|
23
|
-
const { requireMemoryDeps } = await import("./require-deps-
|
|
23
|
+
const { requireMemoryDeps } = await import("./require-deps-GVKDXPPE.js");
|
|
24
24
|
await requireMemoryDeps();
|
|
25
25
|
log.blank();
|
|
26
26
|
log.step("Memory system - install");
|
|
@@ -229,4 +229,4 @@ function installSkills(projectDir) {
|
|
|
229
229
|
export {
|
|
230
230
|
runInstall
|
|
231
231
|
};
|
|
232
|
-
//# sourceMappingURL=install-
|
|
232
|
+
//# sourceMappingURL=install-2HLCAZYU.js.map
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
log
|
|
4
|
-
} from "./chunk-6ZVXZ4EF.js";
|
|
5
2
|
import {
|
|
6
3
|
initStorage
|
|
7
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-P77WV5BF.js";
|
|
8
5
|
import "./chunk-TALTTAMW.js";
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
6
|
+
import "./chunk-RKN3XZO4.js";
|
|
7
|
+
import "./chunk-FQN5PHEU.js";
|
|
8
|
+
import {
|
|
9
|
+
log
|
|
10
|
+
} from "./chunk-FL3JGYDM.js";
|
|
11
11
|
|
|
12
12
|
// src/commands/memory/subcommands/stats.ts
|
|
13
13
|
import { existsSync, statSync } from "fs";
|
|
@@ -18,7 +18,7 @@ function formatBytes(bytes) {
|
|
|
18
18
|
return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
|
|
19
19
|
}
|
|
20
20
|
async function runStats(opts) {
|
|
21
|
-
const { requireMemoryDeps } = await import("./require-deps-
|
|
21
|
+
const { requireMemoryDeps } = await import("./require-deps-GVKDXPPE.js");
|
|
22
22
|
await requireMemoryDeps();
|
|
23
23
|
const ctx = initStorage(opts.dbPath);
|
|
24
24
|
try {
|
|
@@ -72,4 +72,4 @@ async function runStats(opts) {
|
|
|
72
72
|
export {
|
|
73
73
|
runStats
|
|
74
74
|
};
|
|
75
|
-
//# sourceMappingURL=stats-
|
|
75
|
+
//# sourceMappingURL=stats-OZ6S6GVG.js.map
|
|
@@ -11,8 +11,9 @@ import {
|
|
|
11
11
|
loadConfig,
|
|
12
12
|
migrate,
|
|
13
13
|
resolveDataDir
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import "./chunk-
|
|
14
|
+
} from "./chunk-RKN3XZO4.js";
|
|
15
|
+
import "./chunk-FQN5PHEU.js";
|
|
16
|
+
import "./chunk-FL3JGYDM.js";
|
|
16
17
|
|
|
17
18
|
// src/commands/memory/dashboard/tui.ts
|
|
18
19
|
import blessed9 from "blessed";
|
|
@@ -1097,4 +1098,4 @@ async function startTui(options) {
|
|
|
1097
1098
|
export {
|
|
1098
1099
|
startTui
|
|
1099
1100
|
};
|
|
1100
|
-
//# sourceMappingURL=tui-
|
|
1101
|
+
//# sourceMappingURL=tui-YC74JC6L.js.map
|