open-mem 0.7.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -3
- package/README.md +77 -27
- package/dist/adapters/http/server.d.ts +15 -1
- package/dist/adapters/http/server.d.ts.map +1 -1
- package/dist/adapters/http/sse.d.ts +16 -1
- package/dist/adapters/http/sse.d.ts.map +1 -1
- package/dist/adapters/mcp/server.d.ts +25 -1
- package/dist/adapters/mcp/server.d.ts.map +1 -1
- package/dist/adapters/opencode/tools.d.ts.map +1 -1
- package/dist/adapters/platform/bridge-client.d.ts +32 -0
- package/dist/adapters/platform/bridge-client.d.ts.map +1 -0
- package/dist/adapters/platform/builtin.d.ts +6 -0
- package/dist/adapters/platform/builtin.d.ts.map +1 -0
- package/dist/adapters/platform/claude-code.d.ts +7 -0
- package/dist/adapters/platform/claude-code.d.ts.map +1 -0
- package/dist/adapters/platform/cursor.d.ts +7 -0
- package/dist/adapters/platform/cursor.d.ts.map +1 -0
- package/dist/adapters/platform/index.d.ts +9 -0
- package/dist/adapters/platform/index.d.ts.map +1 -0
- package/dist/adapters/platform/normalize.d.ts +14 -0
- package/dist/adapters/platform/normalize.d.ts.map +1 -0
- package/dist/adapters/platform/opencode.d.ts +7 -0
- package/dist/adapters/platform/opencode.d.ts.map +1 -0
- package/dist/adapters/platform/runtime.d.ts +27 -0
- package/dist/adapters/platform/runtime.d.ts.map +1 -0
- package/dist/adapters/platform/types.d.ts +53 -0
- package/dist/adapters/platform/types.d.ts.map +1 -0
- package/dist/ai/compressor.d.ts.map +1 -1
- package/dist/ai/conflict-evaluator.d.ts.map +1 -1
- package/dist/ai/entity-extractor.d.ts +2 -2
- package/dist/ai/entity-extractor.d.ts.map +1 -1
- package/dist/ai/parser.d.ts.map +1 -1
- package/dist/ai/prompts.d.ts.map +1 -1
- package/dist/ai/summarizer.d.ts.map +1 -1
- package/dist/claude-code.d.ts +3 -0
- package/dist/claude-code.d.ts.map +1 -0
- package/dist/claude-code.js +551 -0
- package/dist/config/store.d.ts.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/context/builder.d.ts.map +1 -1
- package/dist/contracts/api.d.ts +129 -0
- package/dist/contracts/api.d.ts.map +1 -0
- package/dist/core/contracts.d.ts +67 -1
- package/dist/core/contracts.d.ts.map +1 -1
- package/dist/core/memory-engine.d.ts +33 -2
- package/dist/core/memory-engine.d.ts.map +1 -1
- package/dist/cursor.d.ts +3 -0
- package/dist/cursor.d.ts.map +1 -0
- package/dist/cursor.js +551 -0
- package/dist/daemon.js +146 -122
- package/dist/dashboard/assets/index-BTEnO15N.js +63 -0
- package/dist/dashboard/assets/index-o3hCx7_v.css +1 -0
- package/dist/dashboard/index.html +2 -2
- package/dist/db/config-audit.d.ts +10 -0
- package/dist/db/config-audit.d.ts.map +1 -0
- package/dist/db/entities.d.ts.map +1 -1
- package/dist/db/maintenance-history.d.ts +9 -0
- package/dist/db/maintenance-history.d.ts.map +1 -0
- package/dist/db/observations.d.ts +12 -0
- package/dist/db/observations.d.ts.map +1 -1
- package/dist/db/schema.d.ts +3 -1
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/user-memory.d.ts.map +1 -1
- package/dist/hooks/chat-capture.d.ts +11 -0
- package/dist/hooks/chat-capture.d.ts.map +1 -1
- package/dist/hooks/context-inject.d.ts.map +1 -1
- package/dist/hooks/session-events.d.ts +10 -0
- package/dist/hooks/session-events.d.ts.map +1 -1
- package/dist/hooks/tool-capture.d.ts +12 -0
- package/dist/hooks/tool-capture.d.ts.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +223 -225
- package/dist/maintenance.js +130 -106
- package/dist/mcp.js +184 -187
- package/dist/platform-worker.d.ts +3 -0
- package/dist/platform-worker.d.ts.map +1 -0
- package/dist/queue/processor.d.ts +26 -1
- package/dist/queue/processor.d.ts.map +1 -1
- package/dist/runtime/metrics.d.ts +43 -0
- package/dist/runtime/metrics.d.ts.map +1 -0
- package/dist/search/graph.d.ts.map +1 -1
- package/dist/search/orchestrator.d.ts +1 -0
- package/dist/search/orchestrator.d.ts.map +1 -1
- package/dist/search/reranker.d.ts +1 -1
- package/dist/search/reranker.d.ts.map +1 -1
- package/dist/store/ports.d.ts +9 -0
- package/dist/store/ports.d.ts.map +1 -1
- package/dist/store/sqlite/adapters.d.ts.map +1 -1
- package/dist/tools/recall.d.ts.map +1 -1
- package/dist/tools/save.d.ts +1 -1
- package/dist/tools/save.d.ts.map +1 -1
- package/dist/types.d.ts +64 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/agents-md.d.ts.map +1 -1
- package/dist/utils/folder-context-maintenance.d.ts.map +1 -1
- package/package.json +27 -6
- package/dist/dashboard/assets/index-9JxqY10c.css +0 -1
- package/dist/dashboard/assets/index-DWbZtwHB.js +0 -60
- package/dist/dashboard/dist/assets/index-9JxqY10c.css +0 -1
- package/dist/dashboard/dist/assets/index-CGCNZcwT.js +0 -60
- package/dist/dashboard/dist/assets/index-CI60x_dC.css +0 -1
- package/dist/dashboard/dist/assets/index-CTwrdVhA.js +0 -60
- package/dist/dashboard/dist/assets/index-DWbZtwHB.js +0 -60
- package/dist/dashboard/dist/index.html +0 -19
- package/dist/servers/http-server.d.ts +0 -22
- package/dist/servers/http-server.d.ts.map +0 -1
- package/dist/servers/mcp-server.d.ts +0 -27
- package/dist/servers/mcp-server.d.ts.map +0 -1
- package/dist/servers/sse-broadcaster.d.ts +0 -27
- package/dist/servers/sse-broadcaster.d.ts.map +0 -1
package/dist/mcp.js
CHANGED
|
@@ -1,102 +1,106 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// @bun
|
|
3
|
-
var G=import.meta.require;import{readFileSync as S2}from"fs";import{join as M2}from"path";import{parseArgs as Q2}from"util";var b$={"claude-sonnet-4-20250514":"us.anthropic.claude-sonnet-4-20250514-v1:0","claude-opus-4-20250514":"us.anthropic.claude-opus-4-20250514-v1:0","claude-3-5-sonnet-20241022":"us.anthropic.claude-3-5-sonnet-20241022-v2:0","claude-3-5-haiku-20241022":"us.anthropic.claude-3-5-haiku-20241022-v1:0","claude-3-haiku-20240307":"anthropic.claude-3-haiku-20240307-v1:0"};function l$($){if($.includes("."))return $;return b$[$]||`us.anthropic.${$}-v1:0`}function e($){switch($.provider){case"anthropic":{let{createAnthropic:J}=G("@ai-sdk/anthropic");return J({apiKey:$.apiKey})($.model)}case"bedrock":{let{createAmazonBedrock:J}=G("@ai-sdk/amazon-bedrock");return J()(l$($.model))}case"openai":{let{createOpenAI:J}=G("@ai-sdk/openai");return J({apiKey:$.apiKey})($.model)}case"google":{let{createGoogleGenerativeAI:J}=G("@ai-sdk/google");return J({apiKey:$.apiKey})($.model)}default:throw Error(`Unknown provider: ${$.provider}. Supported: anthropic, bedrock, openai, google`)}}function o($){try{switch($.provider){case"google":{let{createGoogleGenerativeAI:J}=G("@ai-sdk/google");return J({apiKey:$.apiKey}).embedding("text-embedding-004")}case"openai":{let{createOpenAI:J}=G("@ai-sdk/openai");return J({apiKey:$.apiKey}).embedding("text-embedding-3-small")}case"bedrock":{let{createAmazonBedrock:J}=G("@ai-sdk/amazon-bedrock");return J().embedding("amazon.titan-embed-text-v2:0")}case"anthropic":return null;default:return null}}catch{return null}}import{existsSync as d$,readFileSync as i$}from"fs";var r$={dbPath:".open-mem/memory.db",provider:"google",apiKey:void 0,model:"gemini-2.5-flash-lite",maxTokensPerCompression:1024,compressionEnabled:!0,contextInjectionEnabled:!0,maxContextTokens:4000,batchSize:5,batchIntervalMs:30000,ignoredTools:[],minOutputLength:50,maxIndexEntries:20,sensitivePatterns:[],retentionDays:90,maxDatabaseSizeMb:500,logLevel:"warn",contextShowTokenCosts:!0,contextObservationTypes:"all",contextFullObservationCount:3,maxObservations:50,contextShowLastSummary:!0,rateLimitingEnabled:!0,folderContextEnabled:!0,folderContextMaxDepth:5,daemonEnabled:!1,dashboardEnabled:!1,dashboardPort:3737,embeddingDimension:void 0,conflictResolutionEnabled:!1,conflictSimilarityBandLow:0.7,conflictSimilarityBandHigh:0.92,userMemoryEnabled:!1,userMemoryDbPath:"~/.config/open-mem/user-memory.db",userMemoryMaxContextTokens:1000,rerankingEnabled:!1,rerankingMaxCandidates:20,entityExtractionEnabled:!1};function t$(){let $={};if(process.env.OPEN_MEM_DB_PATH)$.dbPath=process.env.OPEN_MEM_DB_PATH;if(process.env.OPEN_MEM_PROVIDER)$.provider=process.env.OPEN_MEM_PROVIDER;if(process.env.OPEN_MEM_MODEL)$.model=process.env.OPEN_MEM_MODEL;if(process.env.OPEN_MEM_MAX_CONTEXT_TOKENS)$.maxContextTokens=Number.parseInt(process.env.OPEN_MEM_MAX_CONTEXT_TOKENS,10);if(process.env.OPEN_MEM_COMPRESSION==="false")$.compressionEnabled=!1;if(process.env.OPEN_MEM_CONTEXT_INJECTION==="false")$.contextInjectionEnabled=!1;if(process.env.OPEN_MEM_IGNORED_TOOLS)$.ignoredTools=process.env.OPEN_MEM_IGNORED_TOOLS.split(",").map((J)=>J.trim());if(process.env.OPEN_MEM_BATCH_SIZE)$.batchSize=Number.parseInt(process.env.OPEN_MEM_BATCH_SIZE,10);if(process.env.OPEN_MEM_RETENTION_DAYS)$.retentionDays=Number.parseInt(process.env.OPEN_MEM_RETENTION_DAYS,10);if(process.env.OPEN_MEM_LOG_LEVEL)$.logLevel=process.env.OPEN_MEM_LOG_LEVEL;if(process.env.OPEN_MEM_CONTEXT_SHOW_TOKEN_COSTS==="false")$.contextShowTokenCosts=!1;if(process.env.OPEN_MEM_CONTEXT_TYPES)$.contextObservationTypes=process.env.OPEN_MEM_CONTEXT_TYPES==="all"?"all":process.env.OPEN_MEM_CONTEXT_TYPES.split(",").map((J)=>J.trim());if(process.env.OPEN_MEM_CONTEXT_FULL_COUNT)$.contextFullObservationCount=Number.parseInt(process.env.OPEN_MEM_CONTEXT_FULL_COUNT,10);if(process.env.OPEN_MEM_MAX_OBSERVATIONS)$.maxObservations=Number.parseInt(process.env.OPEN_MEM_MAX_OBSERVATIONS,10);if(process.env.OPEN_MEM_CONTEXT_SHOW_LAST_SUMMARY==="false")$.contextShowLastSummary=!1;if(process.env.OPEN_MEM_RATE_LIMITING==="false")$.rateLimitingEnabled=!1;if(process.env.OPEN_MEM_FOLDER_CONTEXT==="false")$.folderContextEnabled=!1;if(process.env.OPEN_MEM_FOLDER_CONTEXT_MAX_DEPTH)$.folderContextMaxDepth=Number.parseInt(process.env.OPEN_MEM_FOLDER_CONTEXT_MAX_DEPTH,10);if(process.env.OPEN_MEM_DAEMON==="true")$.daemonEnabled=!0;if(process.env.OPEN_MEM_DASHBOARD==="true")$.dashboardEnabled=!0;if(process.env.OPEN_MEM_DASHBOARD_PORT)$.dashboardPort=Number.parseInt(process.env.OPEN_MEM_DASHBOARD_PORT,10);if(process.env.OPEN_MEM_EMBEDDING_DIMENSION)$.embeddingDimension=Number.parseInt(process.env.OPEN_MEM_EMBEDDING_DIMENSION,10);if(process.env.OPEN_MEM_CONFLICT_RESOLUTION==="true")$.conflictResolutionEnabled=!0;if(process.env.OPEN_MEM_CONFLICT_BAND_LOW){let J=Number.parseFloat(process.env.OPEN_MEM_CONFLICT_BAND_LOW);if(!Number.isNaN(J))$.conflictSimilarityBandLow=J}if(process.env.OPEN_MEM_CONFLICT_BAND_HIGH){let J=Number.parseFloat(process.env.OPEN_MEM_CONFLICT_BAND_HIGH);if(!Number.isNaN(J))$.conflictSimilarityBandHigh=J}if(process.env.OPEN_MEM_USER_MEMORY==="true")$.userMemoryEnabled=!0;if(process.env.OPEN_MEM_USER_MEMORY_DB_PATH)$.userMemoryDbPath=process.env.OPEN_MEM_USER_MEMORY_DB_PATH;if(process.env.OPEN_MEM_USER_MEMORY_MAX_TOKENS)$.userMemoryMaxContextTokens=Number.parseInt(process.env.OPEN_MEM_USER_MEMORY_MAX_TOKENS,10);if(process.env.OPEN_MEM_RERANKING==="true")$.rerankingEnabled=!0;if(process.env.OPEN_MEM_RERANKING_MAX_CANDIDATES)$.rerankingMaxCandidates=Number.parseInt(process.env.OPEN_MEM_RERANKING_MAX_CANDIDATES,10);if(process.env.OPEN_MEM_ENTITY_EXTRACTION==="true")$.entityExtractionEnabled=!0;return $}function e$($){let J=`${$}/.open-mem/config.json`;if(!d$(J))return{};try{let S=i$(J,"utf-8"),M=JSON.parse(S);if(!M||typeof M!=="object"||Array.isArray(M))return{};return M}catch{return{}}}function o$($){switch($){case"google":return 768;case"openai":return 1536;case"bedrock":return 1024;case"anthropic":return 0;default:return 768}}function s($,J){let S=e$($),M=t$(),Q={...r$,...S,...M,...J};if(!Q.dbPath.startsWith("/"))Q.dbPath=`${$}/${Q.dbPath}`;if(!process.env.OPEN_MEM_PROVIDER&&!J?.provider){if(process.env.GOOGLE_GENERATIVE_AI_API_KEY||process.env.GEMINI_API_KEY)Q.provider="google";else if(process.env.ANTHROPIC_API_KEY)Q.provider="anthropic";else if(process.env.AWS_BEARER_TOKEN_BEDROCK||process.env.AWS_ACCESS_KEY_ID||process.env.AWS_PROFILE)Q.provider="bedrock"}if(!Q.apiKey)switch(Q.provider){case"google":Q.apiKey=process.env.GOOGLE_GENERATIVE_AI_API_KEY||process.env.GEMINI_API_KEY;break;case"anthropic":Q.apiKey=process.env.ANTHROPIC_API_KEY;break;case"openai":Q.apiKey=process.env.OPENAI_API_KEY;break;case"bedrock":break}if(Q.embeddingDimension===void 0)Q.embeddingDimension=o$(Q.provider);return Q}function s$($,J){let S=new RegExp(`<${J}[^>]*>([\\s\\S]*?)</${J}>`,"i"),M=$.match(S);return M?M[1].trim():""}function a$($,J){let S=new RegExp(`<${J}[^>]*>([\\s\\S]*?)</${J}>`,"gi"),M=[];for(let Q of $.matchAll(S)){let Z=Q[1].trim();if(Z)M.push(Z)}return M}function a($){let J=s$($,"reranked");if(!J)return null;let S=a$(J,"index");if(S.length===0)return null;let M=[];for(let Q of S){let Z=Number.parseInt(Q,10);if(Number.isNaN(Z)||Z<0)return null;M.push(Z)}return M}function N($){return Math.ceil($.length/4)}var $0={showTokenCosts:!0,observationTypes:"all",fullObservationCount:3,showLastSummary:!0},E={bugfix:"\uD83D\uDD34",feature:"\uD83D\uDFE3",refactor:"\uD83D\uDD04",change:"\u2705",discovery:"\uD83D\uDD35",decision:"\u2696\uFE0F"};function $$($,J=$0){let S=[];if(S.push("## open-mem: Past Session Memory"),S.push(""),S.push("**\uD83D\uDCA1 Progressive Disclosure:** This is a compact index showing WHAT was observed and retrieval COST."),S.push("Use `mem-search` to find observations by query, then `mem-recall` with IDs to fetch full details."),S.push(""),S.push("**3-Layer Memory Access:**"),S.push("- **Layer 1** `mem-search` \u2014 Find observations by query (returns IDs + summaries)"),S.push("- **Layer 2** `mem-timeline` \u2014 Browse session history and drill into sessions"),S.push("- **Layer 3** `mem-recall` \u2014 Get full details by ID (use IDs from search results or the index below)"),J.showLastSummary&&$.recentSummaries.length>0){S.push(""),S.push("### Recent Sessions"),S.push("| Session | Summary | Decisions |"),S.push("|---------|---------|-----------|");for(let X of $.recentSummaries){let U=X.keyDecisions.length>0?X.keyDecisions.join("; "):"\u2014";S.push(`| ${X.sessionId} | ${X.summary} | ${U} |`)}}let M=J.observationTypes==="all"?$.observationIndex:$.observationIndex.filter((X)=>J.observationTypes.includes(X.type));if(M.length>0){S.push(""),S.push(`### Recent Observations (${M.length} entries)`);let X=S0(M,$.fullObservations);for(let[U,K]of X){if(S.push(""),S.push(`**${U}**`),J.showTokenCosts)S.push("| ID | Type | Title | ~Tokens |"),S.push("|----|------|-------|---------|");else S.push("| ID | Type | Title |"),S.push("|----|------|-------|");for(let W of K){let V=E[W.type]||"\uD83D\uDCDD";if(J.showTokenCosts)S.push(`| ${W.id} | ${V} | ${W.title} | ~${W.tokenCount} |`);else S.push(`| ${W.id} | ${V} | ${W.title} |`)}}}let Q=$.fullObservations.slice(0,J.fullObservationCount);if(Q.length>0){S.push(""),S.push("### Full Details (most recent)");for(let X of Q){let U=E[X.type]||"\uD83D\uDCDD";if(S.push(""),S.push(`#### ${U} ${X.title} (${X.id})`),S.push(X.narrative),X.facts.length>0)S.push(`**Facts:** ${X.facts.map((W)=>`- ${W}`).join(" ")}`);if(X.concepts.length>0)S.push(`**Concepts:** ${X.concepts.join(", ")}`);let K=[...X.filesRead,...X.filesModified];if(K.length>0)S.push(`**Files:** ${K.join(", ")}`)}}let Z=J0($);if(Z)S.push(""),S.push(Z);return S.join(`
|
|
4
|
-
`)}function
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Recent
|
|
8
|
-
|
|
9
|
-
`)}function M
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
`)}
|
|
13
|
-
|
|
14
|
-
${
|
|
15
|
-
|
|
16
|
-
${
|
|
17
|
-
${
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
${
|
|
21
|
-
${
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
`;return`${
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
3
|
+
var fM=Object.defineProperty;var XM=(E,M)=>{for(var _ in M)fM(E,_,{get:M[_],enumerable:!0,configurable:!0,set:(N)=>M[_]=()=>N})};var $E=(E,M)=>()=>(E&&(M=E(E=0)),M);var Y=import.meta.require;import{existsSync as WM,readFileSync as YM}from"fs";function BM(){let E={};if(process.env.OPEN_MEM_DB_PATH)E.dbPath=process.env.OPEN_MEM_DB_PATH;if(process.env.OPEN_MEM_PROVIDER)E.provider=process.env.OPEN_MEM_PROVIDER;if(process.env.OPEN_MEM_MODEL)E.model=process.env.OPEN_MEM_MODEL;if(process.env.OPEN_MEM_MAX_CONTEXT_TOKENS)E.maxContextTokens=Number.parseInt(process.env.OPEN_MEM_MAX_CONTEXT_TOKENS,10);if(process.env.OPEN_MEM_COMPRESSION==="false")E.compressionEnabled=!1;if(process.env.OPEN_MEM_CONTEXT_INJECTION==="false")E.contextInjectionEnabled=!1;if(process.env.OPEN_MEM_IGNORED_TOOLS)E.ignoredTools=process.env.OPEN_MEM_IGNORED_TOOLS.split(",").map((M)=>M.trim());if(process.env.OPEN_MEM_BATCH_SIZE)E.batchSize=Number.parseInt(process.env.OPEN_MEM_BATCH_SIZE,10);if(process.env.OPEN_MEM_RETENTION_DAYS)E.retentionDays=Number.parseInt(process.env.OPEN_MEM_RETENTION_DAYS,10);if(process.env.OPEN_MEM_LOG_LEVEL)E.logLevel=process.env.OPEN_MEM_LOG_LEVEL;if(process.env.OPEN_MEM_CONTEXT_SHOW_TOKEN_COSTS==="false")E.contextShowTokenCosts=!1;if(process.env.OPEN_MEM_CONTEXT_TYPES)E.contextObservationTypes=process.env.OPEN_MEM_CONTEXT_TYPES==="all"?"all":process.env.OPEN_MEM_CONTEXT_TYPES.split(",").map((M)=>M.trim());if(process.env.OPEN_MEM_CONTEXT_FULL_COUNT)E.contextFullObservationCount=Number.parseInt(process.env.OPEN_MEM_CONTEXT_FULL_COUNT,10);if(process.env.OPEN_MEM_MAX_OBSERVATIONS)E.maxObservations=Number.parseInt(process.env.OPEN_MEM_MAX_OBSERVATIONS,10);if(process.env.OPEN_MEM_CONTEXT_SHOW_LAST_SUMMARY==="false")E.contextShowLastSummary=!1;if(process.env.OPEN_MEM_RATE_LIMITING==="false")E.rateLimitingEnabled=!1;if(process.env.OPEN_MEM_FOLDER_CONTEXT==="false")E.folderContextEnabled=!1;if(process.env.OPEN_MEM_FOLDER_CONTEXT_MAX_DEPTH)E.folderContextMaxDepth=Number.parseInt(process.env.OPEN_MEM_FOLDER_CONTEXT_MAX_DEPTH,10);if(process.env.OPEN_MEM_DAEMON==="true")E.daemonEnabled=!0;if(process.env.OPEN_MEM_DASHBOARD==="true")E.dashboardEnabled=!0;if(process.env.OPEN_MEM_DASHBOARD_PORT)E.dashboardPort=Number.parseInt(process.env.OPEN_MEM_DASHBOARD_PORT,10);if(process.env.OPEN_MEM_PLATFORM_OPENCODE==="false")E.platformOpenCodeEnabled=!1;if(process.env.OPEN_MEM_PLATFORM_CLAUDE_CODE==="true")E.platformClaudeCodeEnabled=!0;if(process.env.OPEN_MEM_PLATFORM_CURSOR==="true")E.platformCursorEnabled=!0;if(process.env.OPEN_MEM_MCP_COMPAT_MODE)E.mcpCompatibilityMode=process.env.OPEN_MEM_MCP_COMPAT_MODE;if(process.env.OPEN_MEM_MCP_PROTOCOL_VERSION)E.mcpProtocolVersion=process.env.OPEN_MEM_MCP_PROTOCOL_VERSION;if(process.env.OPEN_MEM_MCP_SUPPORTED_PROTOCOLS)E.mcpSupportedProtocolVersions=process.env.OPEN_MEM_MCP_SUPPORTED_PROTOCOLS.split(",").map((M)=>M.trim()).filter(Boolean);if(process.env.OPEN_MEM_EMBEDDING_DIMENSION)E.embeddingDimension=Number.parseInt(process.env.OPEN_MEM_EMBEDDING_DIMENSION,10);if(process.env.OPEN_MEM_CONFLICT_RESOLUTION==="true")E.conflictResolutionEnabled=!0;if(process.env.OPEN_MEM_CONFLICT_BAND_LOW){let M=Number.parseFloat(process.env.OPEN_MEM_CONFLICT_BAND_LOW);if(!Number.isNaN(M))E.conflictSimilarityBandLow=M}if(process.env.OPEN_MEM_CONFLICT_BAND_HIGH){let M=Number.parseFloat(process.env.OPEN_MEM_CONFLICT_BAND_HIGH);if(!Number.isNaN(M))E.conflictSimilarityBandHigh=M}if(process.env.OPEN_MEM_USER_MEMORY==="true")E.userMemoryEnabled=!0;if(process.env.OPEN_MEM_USER_MEMORY_DB_PATH)E.userMemoryDbPath=process.env.OPEN_MEM_USER_MEMORY_DB_PATH;if(process.env.OPEN_MEM_USER_MEMORY_MAX_TOKENS)E.userMemoryMaxContextTokens=Number.parseInt(process.env.OPEN_MEM_USER_MEMORY_MAX_TOKENS,10);if(process.env.OPEN_MEM_RERANKING==="true")E.rerankingEnabled=!0;if(process.env.OPEN_MEM_RERANKING_MAX_CANDIDATES)E.rerankingMaxCandidates=Number.parseInt(process.env.OPEN_MEM_RERANKING_MAX_CANDIDATES,10);if(process.env.OPEN_MEM_ENTITY_EXTRACTION==="true")E.entityExtractionEnabled=!0;return E}function UM(E){let M=`${E}/.open-mem/config.json`;if(!WM(M))return{};try{let _=YM(M,"utf-8"),N=JSON.parse(_);if(!N||typeof N!=="object"||Array.isArray(N))return{};return N}catch{return{}}}function FM(E){switch(E){case"google":return 768;case"openai":return 1536;case"bedrock":return 1024;case"anthropic":return 0;default:return 768}}function j(E,M){let _=UM(E),N=BM(),S={...ZE,..._,...N,...M};if(!S.dbPath.startsWith("/"))S.dbPath=`${E}/${S.dbPath}`;if(!process.env.OPEN_MEM_PROVIDER&&!M?.provider){if(process.env.GOOGLE_GENERATIVE_AI_API_KEY||process.env.GEMINI_API_KEY)S.provider="google";else if(process.env.ANTHROPIC_API_KEY)S.provider="anthropic";else if(process.env.AWS_BEARER_TOKEN_BEDROCK||process.env.AWS_ACCESS_KEY_ID||process.env.AWS_PROFILE)S.provider="bedrock"}if(!S.apiKey)switch(S.provider){case"google":S.apiKey=process.env.GOOGLE_GENERATIVE_AI_API_KEY||process.env.GEMINI_API_KEY;break;case"anthropic":S.apiKey=process.env.ANTHROPIC_API_KEY;break;case"openai":S.apiKey=process.env.OPENAI_API_KEY;break;case"bedrock":break}if(S.embeddingDimension===void 0)S.embeddingDimension=FM(S.provider);return S}function b(){return{...ZE}}var ZE;var i=$E(()=>{ZE={dbPath:".open-mem/memory.db",provider:"google",apiKey:void 0,model:"gemini-2.5-flash-lite",maxTokensPerCompression:1024,compressionEnabled:!0,contextInjectionEnabled:!0,maxContextTokens:4000,batchSize:5,batchIntervalMs:30000,ignoredTools:[],minOutputLength:50,maxIndexEntries:20,sensitivePatterns:[],retentionDays:90,maxDatabaseSizeMb:500,logLevel:"warn",contextShowTokenCosts:!0,contextObservationTypes:"all",contextFullObservationCount:3,maxObservations:50,contextShowLastSummary:!0,rateLimitingEnabled:!0,folderContextEnabled:!0,folderContextMaxDepth:5,daemonEnabled:!1,dashboardEnabled:!1,dashboardPort:3737,platformOpenCodeEnabled:!0,platformClaudeCodeEnabled:!1,platformCursorEnabled:!1,mcpCompatibilityMode:"strict",mcpProtocolVersion:"2024-11-05",mcpSupportedProtocolVersions:["2024-11-05"],embeddingDimension:void 0,conflictResolutionEnabled:!1,conflictSimilarityBandLow:0.7,conflictSimilarityBandHigh:0.92,userMemoryEnabled:!1,userMemoryDbPath:"~/.config/open-mem/user-memory.db",userMemoryMaxContextTokens:1000,rerankingEnabled:!1,rerankingMaxCandidates:20,entityExtractionEnabled:!1}});var hE={};XM(hE,{writeProjectConfig:()=>uE,validatePatch:()=>a,readProjectConfig:()=>v,previewConfig:()=>f0,patchConfig:()=>X0,getEffectiveConfig:()=>p,getConfigSchema:()=>R0});import{existsSync as N0}from"fs";import{mkdir as S0,readFile as O0,writeFile as A0}from"fs/promises";import{dirname as J0,join as C0}from"path";function PE(E){return C0(E,".open-mem","config.json")}function gE(E){return pE.find((M)=>M.key===E)}function $0(E,M){let _=gE(E);if(!_)return null;if(_.type==="string"&&typeof M!=="string")return`${String(E)} must be a string`;if(_.type==="number"&&typeof M!=="number")return`${String(E)} must be a number`;if(_.type==="boolean"&&typeof M!=="boolean")return`${String(E)} must be a boolean`;if(_.type==="array"&&!Array.isArray(M))return`${String(E)} must be an array`;if(_.enum&&typeof M==="string"&&!_.enum.includes(M))return`${String(E)} must be one of: ${_.enum.join(", ")}`;if(typeof M==="number"){if(_.min!==void 0&&M<_.min)return`${String(E)} must be >= ${_.min}`;if(_.max!==void 0&&M>_.max)return`${String(E)} must be <= ${_.max}`}return null}function R0(){return pE}async function v(E){let M=PE(E);if(!N0(M))return{};try{let _=await O0(M,"utf-8"),N=JSON.parse(_);if(!N||typeof N!=="object"||Array.isArray(N))return{};return N}catch{return{}}}async function uE(E,M){let _=PE(E),S={...await v(E),...M};await S0(J0(_),{recursive:!0}),await A0(_,JSON.stringify(S,null,2),"utf-8")}function a(E){let M=[];for(let[_,N]of Object.entries(E)){let O=$0(_,N);if(O)M.push(O)}return M}async function p(E){let M=b(),_=await v(E),N=j(E),S=[],O={};for(let[A,J]of Object.entries(M)){let C=A,V=gE(C),Z=(V0[C]??[]).some((F)=>typeof process.env[F]==="string"),W=Object.hasOwn(_,C),B="default";if(W)B="file";if(Z)B="env";if(O[C]={source:B,locked:Z,restartRequired:V?.restartRequired??!1,liveApply:V?.liveApply??!1},B==="env"&&W)S.push(`${String(C)} is overridden by environment variable.`);if(N[C]===void 0&&J!==void 0)S.push(`${String(C)} resolved to undefined unexpectedly.`)}return{config:N,meta:O,warnings:S}}async function f0(E,M){let _=a(M);if(_.length>0)return{...await p(E),warnings:_};let N=b(),S=await v(E),O={...N,...S,...M},J={...j(E,M),...O},C=(await p(E)).meta;return{config:J,meta:C,warnings:[]}}async function X0(E,M){let _=a(M);if(_.length>0)return{...await p(E),warnings:_};return await uE(E,M),p(E)}var pE,V0;var vE=$E(()=>{i();pE=[{key:"dbPath",label:"Database Path",type:"string",group:"Storage",liveApply:!1,restartRequired:!0},{key:"provider",label:"Provider",type:"string",group:"AI",liveApply:!1,restartRequired:!0,enum:["google","anthropic","openai","bedrock"]},{key:"model",label:"Model",type:"string",group:"AI",liveApply:!1,restartRequired:!0},{key:"maxTokensPerCompression",label:"Max Tokens Per Compression",type:"number",group:"AI",liveApply:!0,restartRequired:!1,min:128,max:8192},{key:"compressionEnabled",label:"Compression Enabled",type:"boolean",group:"Behavior",liveApply:!0,restartRequired:!1},{key:"contextInjectionEnabled",label:"Context Injection Enabled",type:"boolean",group:"Behavior",liveApply:!0,restartRequired:!1},{key:"maxContextTokens",label:"Max Context Tokens",type:"number",group:"Behavior",liveApply:!0,restartRequired:!1,min:500,max:64000},{key:"batchSize",label:"Batch Size",type:"number",group:"Behavior",liveApply:!0,restartRequired:!1,min:1,max:100},{key:"batchIntervalMs",label:"Batch Interval (ms)",type:"number",group:"Behavior",liveApply:!0,restartRequired:!1,min:1000,max:300000},{key:"ignoredTools",label:"Ignored Tools",type:"array",group:"Filtering",liveApply:!0,restartRequired:!1},{key:"minOutputLength",label:"Min Output Length",type:"number",group:"Filtering",liveApply:!0,restartRequired:!1,min:0,max:1e4},{key:"maxObservations",label:"Max Observations",type:"number",group:"Progressive Disclosure",liveApply:!0,restartRequired:!1,min:1,max:200},{key:"contextFullObservationCount",label:"Full Observation Count",type:"number",group:"Progressive Disclosure",liveApply:!0,restartRequired:!1,min:0,max:20},{key:"contextShowTokenCosts",label:"Show Token Costs",type:"boolean",group:"Progressive Disclosure",liveApply:!0,restartRequired:!1},{key:"sensitivePatterns",label:"Sensitive Patterns",type:"array",group:"Privacy",liveApply:!0,restartRequired:!1},{key:"retentionDays",label:"Retention Days",type:"number",group:"Data Retention",liveApply:!1,restartRequired:!0,min:0,max:3650},{key:"maxDatabaseSizeMb",label:"Max Database Size (MB)",type:"number",group:"Data Retention",liveApply:!1,restartRequired:!0,min:0,max:1e5},{key:"dashboardEnabled",label:"Dashboard Enabled",type:"boolean",group:"Dashboard",liveApply:!1,restartRequired:!0},{key:"dashboardPort",label:"Dashboard Port",type:"number",group:"Dashboard",liveApply:!1,restartRequired:!0,min:1,max:65535},{key:"platformOpenCodeEnabled",label:"OpenCode Adapter",type:"boolean",group:"Advanced",liveApply:!1,restartRequired:!0},{key:"platformClaudeCodeEnabled",label:"Claude Code Adapter",type:"boolean",group:"Advanced",liveApply:!1,restartRequired:!0},{key:"platformCursorEnabled",label:"Cursor Adapter",type:"boolean",group:"Advanced",liveApply:!1,restartRequired:!0},{key:"mcpCompatibilityMode",label:"MCP Compatibility Mode",type:"string",group:"Advanced",liveApply:!1,restartRequired:!0,enum:["strict","legacy"]},{key:"mcpProtocolVersion",label:"MCP Protocol Version",type:"string",group:"Advanced",liveApply:!1,restartRequired:!0},{key:"mcpSupportedProtocolVersions",label:"MCP Supported Protocols",type:"array",group:"Advanced",liveApply:!1,restartRequired:!0},{key:"rerankingEnabled",label:"Reranking Enabled",type:"boolean",group:"Advanced",liveApply:!0,restartRequired:!1},{key:"entityExtractionEnabled",label:"Entity Extraction Enabled",type:"boolean",group:"Advanced",liveApply:!0,restartRequired:!1},{key:"userMemoryEnabled",label:"User Memory Enabled",type:"boolean",group:"Advanced",liveApply:!1,restartRequired:!0},{key:"userMemoryMaxContextTokens",label:"User Memory Max Context Tokens",type:"number",group:"Advanced",liveApply:!0,restartRequired:!1,min:0,max:8000}],V0={dbPath:["OPEN_MEM_DB_PATH"],provider:["OPEN_MEM_PROVIDER"],model:["OPEN_MEM_MODEL"],compressionEnabled:["OPEN_MEM_COMPRESSION"],contextInjectionEnabled:["OPEN_MEM_CONTEXT_INJECTION"],maxContextTokens:["OPEN_MEM_MAX_CONTEXT_TOKENS"],ignoredTools:["OPEN_MEM_IGNORED_TOOLS"],batchSize:["OPEN_MEM_BATCH_SIZE"],retentionDays:["OPEN_MEM_RETENTION_DAYS"],contextShowTokenCosts:["OPEN_MEM_CONTEXT_SHOW_TOKEN_COSTS"],contextFullObservationCount:["OPEN_MEM_CONTEXT_FULL_COUNT"],maxObservations:["OPEN_MEM_MAX_OBSERVATIONS"],dashboardEnabled:["OPEN_MEM_DASHBOARD"],dashboardPort:["OPEN_MEM_DASHBOARD_PORT"],platformOpenCodeEnabled:["OPEN_MEM_PLATFORM_OPENCODE"],platformClaudeCodeEnabled:["OPEN_MEM_PLATFORM_CLAUDE_CODE"],platformCursorEnabled:["OPEN_MEM_PLATFORM_CURSOR"],mcpCompatibilityMode:["OPEN_MEM_MCP_COMPAT_MODE"],mcpProtocolVersion:["OPEN_MEM_MCP_PROTOCOL_VERSION"],mcpSupportedProtocolVersions:["OPEN_MEM_MCP_SUPPORTED_PROTOCOLS"],rerankingEnabled:["OPEN_MEM_RERANKING"],userMemoryEnabled:["OPEN_MEM_USER_MEMORY"]}});import{readFileSync as x0}from"fs";import{join as I0}from"path";import{parseArgs as q0}from"util";import{createInterface as ZM}from"readline";import{z as U}from"zod";import{z as R}from"zod";var P=R.enum(["decision","bugfix","feature","refactor","discovery","change"]);function H(E,M={}){return{data:E,error:null,meta:M}}function Q(E,M,_){return{data:null,error:{code:E,message:M,details:_},meta:{}}}var f={find:R.object({query:R.string().min(1),scope:R.enum(["project","user","all"]).optional().default("project"),types:R.array(P).optional(),limit:R.number().int().min(1).max(50).optional().default(10),cursor:R.string().optional(),include:R.object({snippets:R.boolean().optional(),scores:R.boolean().optional(),relations:R.boolean().optional()}).optional()}),history:R.object({limit:R.number().int().min(1).max(20).optional().default(5),cursor:R.string().optional(),sessionId:R.string().optional()}),get:R.object({ids:R.array(R.string()).min(1),includeHistory:R.boolean().optional().default(!1),limit:R.number().int().min(1).max(50).optional().default(10)}),create:R.object({title:R.string(),type:P,narrative:R.string(),concepts:R.array(R.string()).optional(),files:R.array(R.string()).optional(),importance:R.number().int().min(1).max(5).optional(),scope:R.enum(["project","user"]).optional().default("project")}),revise:R.object({id:R.string(),title:R.string().optional(),narrative:R.string().optional(),type:P.optional(),concepts:R.array(R.string()).optional(),importance:R.number().int().min(1).max(5).optional(),reason:R.string().optional()}),remove:R.object({id:R.string(),reason:R.string().optional()}),transferExport:R.object({scope:R.enum(["project"]).optional().default("project"),type:P.optional(),limit:R.number().int().min(1).optional(),format:R.enum(["json"]).optional().default("json")}),transferImport:R.object({payload:R.string(),mode:R.enum(["skip","merge","replace"]).optional().default("skip")}),maintenance:R.object({action:R.enum(["folderContextDryRun","folderContextClean","folderContextRebuild"])}),help:R.object({})};var HM="2024-11-05",KM=U.object({name:U.string().min(1),arguments:U.record(U.string(),U.unknown()).optional()});function LM(E){if(typeof E!=="object"||E===null)return!1;let M=E;return M.jsonrpc==="2.0"&&typeof M.method==="string"}function L(E){let _=U.toJSONSchema(E);return{type:"object",properties:_.properties??{},required:_.required??void 0,additionalProperties:!1}}function RE(E){return E.issues.map((M)=>{return`${M.path.length>0?M.path.join("."):"input"}: ${M.message}`}).join("; ")}class c{memoryEngine;version;compatibilityMode;protocolVersion;supportedProtocolVersions;initialized=!1;pendingOps=[];constructor(E){this.memoryEngine=E.memoryEngine,this.version=E.version,this.compatibilityMode=E.compatibilityMode??"strict",this.protocolVersion=E.protocolVersion??HM,this.supportedProtocolVersions=E.supportedProtocolVersions&&E.supportedProtocolVersions.length>0?E.supportedProtocolVersions:[this.protocolVersion]}start(){let E=ZM({input:process.stdin,terminal:!1});E.on("line",(M)=>{let _=M.trim();if(!_)return;try{let N=JSON.parse(_);if(!LM(N)){this.send({jsonrpc:"2.0",id:null,error:{code:-32600,message:"Invalid Request"}});return}this.handle(N)}catch{this.send({jsonrpc:"2.0",id:null,error:{code:-32700,message:"Parse error"}})}}),E.on("close",()=>{Promise.allSettled(this.pendingOps).then(()=>process.exit(0))})}handle(E){if(E.method==="notifications/initialized"){this.initialized=!0;return}if(E.id===void 0||E.id===null)return;if(E.method==="initialize"){this.handleInitialize(E);return}if(!this.initialized&&this.compatibilityMode==="strict"){this.send({jsonrpc:"2.0",id:E.id,error:{code:-32002,message:"Server not initialized"}});return}switch(E.method){case"tools/list":this.send({jsonrpc:"2.0",id:E.id,result:{tools:this.getToolDefinitions()}});return;case"tools/call":{let M=this.handleToolCall(E.id,E.params);this.pendingOps.push(M),M.finally(()=>{this.pendingOps=this.pendingOps.filter((_)=>_!==M)});return}case"ping":this.send({jsonrpc:"2.0",id:E.id,result:{}});return;default:this.send({jsonrpc:"2.0",id:E.id,error:{code:-32601,message:`Method not found: ${E.method}`}})}}handleInitialize(E){let M=typeof E.params?.protocolVersion==="string"?E.params.protocolVersion:this.protocolVersion;if(!this.supportedProtocolVersions.includes(M)){this.send({jsonrpc:"2.0",id:E.id??null,error:{code:-32602,message:`Unsupported protocol version: ${M}`,data:{supported:this.supportedProtocolVersions}}});return}this.initialized=!0,this.send({jsonrpc:"2.0",id:E.id??null,result:{protocolVersion:M,capabilities:{tools:{listChanged:!1}},serverInfo:{name:"open-mem",version:this.version}}})}getToolDefinitions(){return[{name:"memory.find",description:"Find relevant memory records.",inputSchema:L(f.find)},{name:"memory.history",description:"Browse session history.",inputSchema:L(f.history)},{name:"memory.get",description:"Fetch full memory records by id.",inputSchema:L(f.get)},{name:"memory.create",description:"Create a memory record.",inputSchema:L(f.create)},{name:"memory.revise",description:"Create a revised memory revision.",inputSchema:L(f.revise)},{name:"memory.remove",description:"Tombstone a memory record.",inputSchema:L(f.remove)},{name:"memory.transfer.export",description:"Export memory.",inputSchema:L(f.transferExport)},{name:"memory.transfer.import",description:"Import memory payload.",inputSchema:L(f.transferImport)},{name:"memory.maintenance",description:"Run maintenance action.",inputSchema:L(f.maintenance)},{name:"memory.help",description:"Show memory workflow guidance.",inputSchema:L(f.help)}]}async handleToolCall(E,M){let _=KM.safeParse(M??{});if(!_.success){this.send({jsonrpc:"2.0",id:E,result:{content:[{type:"text",text:JSON.stringify(Q("VALIDATION_ERROR",RE(_.error)),null,2)}],isError:!0}});return}let N=_.data.name,S=_.data.arguments??{};try{let O=await this.executeTool(N,S);this.send({jsonrpc:"2.0",id:E,result:O})}catch(O){this.send({jsonrpc:"2.0",id:E,result:{content:[{type:"text",text:JSON.stringify(Q("INTERNAL_ERROR",String(O)),null,2)}],isError:!0}})}}async executeTool(E,M){let _=async()=>{switch(E){case"memory.find":{let N=f.find.parse(M),S=await this.memoryEngine.search(N.query,{limit:N.limit,type:N.types?.[0]});return JSON.stringify(H({results:S}),null,2)}case"memory.history":{let N=f.history.parse(M);return JSON.stringify(H({items:await this.memoryEngine.timeline({limit:N.limit,sessionId:N.sessionId})}),null,2)}case"memory.get":{let N=f.get.parse(M);return JSON.stringify(H({observations:await this.memoryEngine.recall(N.ids,N.limit)}),null,2)}case"memory.create":{let N=f.create.parse(M),S=await this.memoryEngine.save({...N,sessionId:"mcp"});return JSON.stringify(S?H({observation:S}):Q("CONFLICT","Unable to create memory"),null,2)}case"memory.revise":{let N=f.revise.parse(M),S=await this.memoryEngine.update(N);return JSON.stringify(S?H({previousId:N.id,newId:S.id,observation:S}):Q("NOT_FOUND",`Observation ${N.id} not found`),null,2)}case"memory.remove":{let N=f.remove.parse(M),S=await this.memoryEngine.delete([N.id]);return JSON.stringify(S>0?H({id:N.id,tombstoned:!0}):Q("NOT_FOUND",`Observation ${N.id} not found`),null,2)}case"memory.transfer.export":{let N=f.transferExport.parse(M),S=await this.memoryEngine.export("project",{type:N.type,limit:N.limit});return JSON.stringify(H({payload:S,format:N.format}),null,2)}case"memory.transfer.import":{let N=f.transferImport.parse(M),S=N.mode==="replace"?"overwrite":"skip-duplicates",O=await this.memoryEngine.import(N.payload,{mode:S});return JSON.stringify(H({imported:O.imported,skipped:O.skipped,mode:N.mode}),null,2)}case"memory.maintenance":{let N=f.maintenance.parse(M);if(N.action==="folderContextDryRun")return JSON.stringify(H(await this.memoryEngine.maintainFolderContext("clean",!0)),null,2);if(N.action==="folderContextClean")return JSON.stringify(H(await this.memoryEngine.maintainFolderContext("clean",!1)),null,2);return JSON.stringify(H(await this.memoryEngine.maintainFolderContext("rebuild",!1)),null,2)}case"memory.help":return JSON.stringify(H({guide:this.memoryEngine.guide()}),null,2);default:return JSON.stringify(Q("NOT_FOUND",`Unknown tool: ${E}`),null,2)}};try{let N=await _(),S=N.includes('"error": {')&&!N.includes('"error": null');return{content:[{type:"text",text:N}],isError:S}}catch(N){if(N instanceof U.ZodError)return{content:[{type:"text",text:JSON.stringify(Q("VALIDATION_ERROR",RE(N)),null,2)}],isError:!0};return{content:[{type:"text",text:JSON.stringify(Q("INTERNAL_ERROR",String(N)),null,2)}],isError:!0}}}send(E){process.stdout.write(`${JSON.stringify(E)}
|
|
4
|
+
`)}}var QM={"claude-sonnet-4-20250514":"us.anthropic.claude-sonnet-4-20250514-v1:0","claude-opus-4-20250514":"us.anthropic.claude-opus-4-20250514-v1:0","claude-3-5-sonnet-20241022":"us.anthropic.claude-3-5-sonnet-20241022-v2:0","claude-3-5-haiku-20241022":"us.anthropic.claude-3-5-haiku-20241022-v1:0","claude-3-haiku-20240307":"anthropic.claude-3-haiku-20240307-v1:0"};function zM(E){if(E.includes("."))return E;return QM[E]||`us.anthropic.${E}-v1:0`}function fE(E){switch(E.provider){case"anthropic":{let{createAnthropic:M}=Y("@ai-sdk/anthropic");return M({apiKey:E.apiKey})(E.model)}case"bedrock":{let{createAmazonBedrock:M}=Y("@ai-sdk/amazon-bedrock");return M()(zM(E.model))}case"openai":{let{createOpenAI:M}=Y("@ai-sdk/openai");return M({apiKey:E.apiKey})(E.model)}case"google":{let{createGoogleGenerativeAI:M}=Y("@ai-sdk/google");return M({apiKey:E.apiKey})(E.model)}default:throw Error(`Unknown provider: ${E.provider}. Supported: anthropic, bedrock, openai, google`)}}function XE(E){try{switch(E.provider){case"google":{let{createGoogleGenerativeAI:M}=Y("@ai-sdk/google");return M({apiKey:E.apiKey}).embedding("text-embedding-004")}case"openai":{let{createOpenAI:M}=Y("@ai-sdk/openai");return M({apiKey:E.apiKey}).embedding("text-embedding-3-small")}case"bedrock":{let{createAmazonBedrock:M}=Y("@ai-sdk/amazon-bedrock");return M().embedding("amazon.titan-embed-text-v2:0")}case"anthropic":return null;default:return null}}catch{return null}}i();import{randomUUID as xE}from"crypto";function GM(E,M){let _=new RegExp(`<${M}[^>]*>([\\s\\S]*?)</${M}>`,"i"),N=E.match(_);return N?N[1].trim():""}function DM(E,M){let _=new RegExp(`<${M}[^>]*>([\\s\\S]*?)</${M}>`,"gi"),N=[];for(let S of E.matchAll(_)){let O=S[1].trim();if(O)N.push(O)}return N}function HE(E){let M=GM(E,"reranked");if(!M)return null;let _=DM(M,"index");if(_.length===0)return null;let N=[];for(let S of _){let O=Number.parseInt(S,10);if(Number.isNaN(O)||O<0)return null;N.push(O)}return N}function z(E){return Math.ceil(E.length/4)}var yM={showTokenCosts:!0,observationTypes:"all",fullObservationCount:3,showLastSummary:!0},k={bugfix:"\uD83D\uDD34",feature:"\uD83D\uDFE3",refactor:"\uD83D\uDD04",change:"\u2705",discovery:"\uD83D\uDD35",decision:"\u2696\uFE0F"};function KE(E,M=yM){let _=[];if(_.push("## open-mem: Past Session Memory"),_.push(""),_.push("**\uD83D\uDCA1 Progressive Disclosure:** This is a compact index showing WHAT was observed and retrieval COST."),_.push("Use `memory.find` to find observations by query, then `memory.get` with IDs to fetch full details."),_.push(""),_.push("**3-Layer Memory Access:**"),_.push("- **Layer 1** `memory.find` \u2014 Find observations by query (returns IDs + summaries)"),_.push("- **Layer 2** `memory.history` \u2014 Browse session history and drill into sessions"),_.push("- **Layer 3** `memory.get` \u2014 Get full details by ID (use IDs from search results or the index below)"),M.showLastSummary&&E.recentSummaries.length>0){_.push(""),_.push("### Recent Sessions"),_.push("| Session | Summary | Decisions |"),_.push("|---------|---------|-----------|");for(let A of E.recentSummaries){let J=A.keyDecisions.length>0?A.keyDecisions.join("; "):"\u2014";_.push(`| ${A.sessionId} | ${A.summary} | ${J} |`)}}let N=M.observationTypes==="all"?E.observationIndex:E.observationIndex.filter((A)=>M.observationTypes.includes(A.type));if(N.length>0){_.push(""),_.push(`### Recent Observations (${N.length} entries)`);let A=jM(N,E.fullObservations);for(let[J,C]of A){if(_.push(""),_.push(`**${J}**`),M.showTokenCosts)_.push("| ID | Type | Title | ~Tokens |"),_.push("|----|------|-------|---------|");else _.push("| ID | Type | Title |"),_.push("|----|------|-------|");for(let V of C){let $=k[V.type]||"\uD83D\uDCDD";if(M.showTokenCosts)_.push(`| ${V.id} | ${$} | ${V.title} | ~${V.tokenCount} |`);else _.push(`| ${V.id} | ${$} | ${V.title} |`)}}}let S=E.fullObservations.slice(0,M.fullObservationCount);if(S.length>0){_.push(""),_.push("### Full Details (most recent)");for(let A of S){let J=k[A.type]||"\uD83D\uDCDD";if(_.push(""),_.push(`#### ${J} ${A.title} (${A.id})`),_.push(A.narrative),A.facts.length>0)_.push(`**Facts:** ${A.facts.map((V)=>`- ${V}`).join(" ")}`);if(A.concepts.length>0)_.push(`**Concepts:** ${A.concepts.join(", ")}`);let C=[...A.filesRead,...A.filesModified];if(C.length>0)_.push(`**Files:** ${C.join(", ")}`)}}let O=mM(E);if(O)_.push(""),_.push(O);return _.join(`
|
|
5
|
+
`)}function mM(E){let M=0,_=0,N=new Set(E.observationIndex.map((A)=>A.id));for(let A of E.observationIndex)M+=A.tokenCount,_+=A.discoveryTokens;for(let A of E.fullObservations)if(!N.has(A.id))M+=A.tokenCount,_+=A.discoveryTokens;if(_===0)return null;let S=_-M,O=Math.max(0,Math.round(S/_*100));return`### \uD83D\uDCB0 Memory Economics
|
|
6
|
+
**Read cost:** ~${M}t | **Discovery cost:** ~${_}t | **Savings:** ${O}% (${S}t saved)`}function jM(E,M){let _=new Map;for(let S of M){let O=S.filesModified[0]||S.filesRead[0];if(O)_.set(S.id,O)}let N=new Map;for(let S of E){let O=_.get(S.id)??"General",A=N.get(O)??[];A.push(S),N.set(O,A)}return N}function LE(E){let M=[];if(M.push("[open-mem] Memory context:"),E.recentSummaries.length>0){M.push(`
|
|
7
|
+
Recent sessions:`);for(let _ of E.recentSummaries)M.push(`- ${_.summary}`)}if(E.observationIndex.length>0){M.push(`
|
|
8
|
+
Recent observations (${E.observationIndex.length} entries):`);for(let _ of E.observationIndex)M.push(`- ${k[_.type]||"\uD83D\uDCDD"} ${_.title}`)}return M.join(`
|
|
9
|
+
`)}function QE(E,M){if(E.length===0)return"";let _=M,N=[];for(let O of E){let A=O.tokenCount||z(O.title);if(_-A<0)break;N.push(O),_-=A}if(N.length===0)return"";let S=[];S.push("### Cross-Project Memory"),S.push(""),S.push("| ID | Type | Title | ~Tokens |"),S.push("|----|------|-------|---------|");for(let O of N){let A=k[O.type]||"\uD83D\uDCDD";S.push(`| ${O.id} | ${A} | ${O.title} | ~${O.tokenCount} |`)}return S.join(`
|
|
10
|
+
`)}function zE(E,M){if(E.length===0)return"";let _=M,N=[];for(let O of E){let A=O.tokenCount||z(O.title);if(_-A<0)break;N.push(O),_-=A}if(N.length===0)return"";let S=[];S.push(`
|
|
11
|
+
Cross-project observations (${N.length} entries):`);for(let O of N)S.push(`- ${k[O.type]||"\uD83D\uDCDD"} ${O.title}`);return S.join(`
|
|
12
|
+
`)}var g={recency:0.4,typeImportance:0.3,sessionAffinity:0.2,tokenEfficiency:0.1},kM={decision:1,bugfix:0.9,feature:0.8,refactor:0.6,discovery:0.5,change:0.4};function TM(E,M){let _=new Date(E),S=(M.getTime()-_.getTime())/3600000;if(S<0)return 1;if(S<24)return 1;if(S<48)return 0.8;if(S<168)return 0.5;return 0.2}function pM(E){return kM[E]??0.3}function PM(E,M){if(!M)return 0.5;return E===M?1:0.3}function gM(E){if(E<=10)return 1;if(E>=200)return 0.2;return 1-(E-10)/190*0.8}function uM(E,M){let _=TM(E.createdAt,M.now),N=pM(E.type),S=PM(E.sessionId,M.currentSessionId),O=gM(E.tokenCount);return _*g.recency+N*g.typeImportance+S*g.sessionAffinity+O*g.tokenEfficiency}function WE(E,M){let _=new Map;for(let N of E)_.set(N.id,uM(N,M));return[...E].sort((N,S)=>{let O=_.get(N.id)??0,A=_.get(S.id)??0;if(A!==O)return A-O;return new Date(S.createdAt).getTime()-new Date(N.createdAt).getTime()})}function YE(E,M,_,N,S=[],O){let A=N,J=[],C=[];for(let $ of M){let Z=$.tokenCount||z($.summary);if(A-Z<0)break;J.push($),A-=Z}let V=O?WE(_,O):_;for(let $ of V){let Z=$.tokenCount||z($.title);if(A-Z<0)break;C.push($),A-=Z}return{recentSummaries:J,observationIndex:C,fullObservations:[...S],totalTokens:N-A}}import{existsSync as oM}from"fs";import{readdir as aM,readFile as eM,writeFile as tM}from"fs/promises";import{join as sM,resolve as E0}from"path";import{existsSync as UE}from"fs";import{mkdir as hM,readFile as vM,rename as xM,unlink as IM,writeFile as qM}from"fs/promises";import{dirname as o,isAbsolute as FE,join as h,normalize as lM,relative as GE,resolve as d,sep as r}from"path";var u="<!-- open-mem-context -->",T="<!-- /open-mem-context -->",wM={bugfix:"\uD83D\uDD34",feature:"\uD83D\uDFE3",refactor:"\uD83D\uDD04",change:"\u2705",discovery:"\uD83D\uDD35",decision:"\u2696\uFE0F"},BE=new Map,nM=new Set(["node_modules",".git","dist","coverage",".open-mem","build","__pycache__",".next",".nuxt"]);async function DE(E,M,_=5){if(M.length===0)return;let N=[];for(let A of M){for(let J of A.filesModified)N.push(J);for(let J of A.filesRead)N.push(J)}let S=rM(N,E,_);if(S.size===0)return;let O=dM(M,S,E);for(let[A,J]of O)try{let C=cM(A,J,E);await bM(A,C)}catch(C){console.error(`[open-mem] Failed to update AGENTS.md in ${A}:`,C)}}function cM(E,M,_){let N=[...M].sort((C,V)=>V.createdAt.localeCompare(C.createdAt)).slice(0,10),S=GE(_,E)||".",O=[];O.push(`## Recent Activity in \`${S}/\` (auto-generated by open-mem)`),O.push(""),O.push("| Type | Title | Date |"),O.push("|------|-------|------|");for(let C of N){let V=wM[C.type]||"\uD83D\uDCDD",$=C.createdAt.split("T")[0],Z=C.title.replace(/\|/g,"\\|");O.push(`| ${V} ${C.type} | ${Z} | ${$} |`)}let A=new Set;for(let C of N)for(let V of C.concepts)A.add(V);if(A.size>0){let C=[...A].slice(0,10).join(", ");O.push(""),O.push(`**Key concepts:** ${C}`)}let J=N.filter((C)=>C.type==="decision").map((C)=>C.title);if(J.length>0)O.push(""),O.push(`**Recent decisions:** ${J.slice(0,5).join("; ")}`);return O.join(`
|
|
13
|
+
`)}async function bM(E,M){if(!UE(E))return;let N=(BE.get(E)??Promise.resolve()).then(async()=>{let S=h(E,"AGENTS.md"),O=h(E,".AGENTS.md.tmp"),A="";try{A=await vM(S,"utf-8")}catch{}let J=iM(A,M);try{await hM(o(O),{recursive:!0}),await qM(O,J,"utf-8"),await xM(O,S)}catch(C){try{await IM(O)}catch{}throw C}});return BE.set(E,N.catch(()=>{})),N}function iM(E,M){if(!E)return`${u}
|
|
14
|
+
${M}
|
|
15
|
+
${T}
|
|
16
|
+
`;let _=E.indexOf(u),N=E.indexOf(T);if(_!==-1&&N!==-1&&N>_){let S=E.substring(0,_),O=E.substring(N+T.length);return`${S}${u}
|
|
17
|
+
${M}
|
|
18
|
+
${T}${O}`}return`${E}
|
|
19
|
+
|
|
20
|
+
${u}
|
|
21
|
+
${M}
|
|
22
|
+
${T}
|
|
23
|
+
`}function rM(E,M,_){let N=new Set,S=d(M);for(let O of E){if(!O||!O.trim())continue;if(O.startsWith("~")||O.startsWith("http"))continue;let A=FE(O)?O:h(M,O),J=o(A),C=d(J);if(!C.startsWith(S+r)&&C!==S)continue;if(C===S)continue;let V=GE(S,C);if(V.split(r).length>_)continue;if(lM(V).split(r).some((W)=>nM.has(W)))continue;if(!UE(C))continue;N.add(C)}return N}function dM(E,M,_){let N=new Map;for(let S of E){let O=[...S.filesModified,...S.filesRead],A=new Set;for(let J of O){if(!J)continue;let C=FE(J)?J:h(_,J),V=d(o(C));if(M.has(V))A.add(V)}for(let J of A){let C=N.get(J)??[];C.push(S),N.set(J,C)}}return N}var M0="<!-- open-mem-context -->",yE="<!-- /open-mem-context -->";async function mE(E,M){let _;try{_=await aM(E,{withFileTypes:!0,encoding:"utf8"})}catch{return}for(let N of _){let S=String(N.name);if(S===".git"||S==="node_modules"||S===".open-mem"||S==="dist")continue;let O=sM(E,S);if(N.isDirectory())await mE(O,M);else if(N.isFile()&&S==="AGENTS.md")M.push(O)}}async function jE(E){let M=E0(E),_=[];return await mE(M,_),_}function _0(E){let M=E.indexOf(M0),_=E.indexOf(yE);if(M===-1||_===-1||_<=M)return E;let N=E.slice(0,M).trimEnd(),S=E.slice(_+yE.length).trimStart();if(!N&&!S)return"";if(!N)return`${S}
|
|
24
|
+
`;if(!S)return`${N}
|
|
25
|
+
`;return`${N}
|
|
26
|
+
|
|
27
|
+
${S}
|
|
28
|
+
`}async function kE(E,M=!1){let _=await jE(E),N=0;for(let S of _){let O=await eM(S,"utf-8"),A=_0(O);if(A!==O){if(N+=1,!M)await tM(S,A,"utf-8")}}return{files:_,changed:N}}async function TE(E,M,_,N,S=!1){let A=M.getAll(E).flatMap((C)=>_.getBySession(C.id));if(S){let C=new Set;for(let V of A)for(let $ of[...V.filesRead,...V.filesModified])C.add($);return{observations:A.length,filesTouched:C.size}}if(!oM(E))return{observations:0,filesTouched:0};await DE(E,A,N);let J=await jE(E);return{observations:A.length,filesTouched:J.length}}class e{observations;sessions;summaries;searchOrchestrator;projectPath;config;userObservationRepo;runtimeSnapshotProvider;configAuditStore;maintenanceHistoryStore;configAuditLogFallback=[];maintenanceLogFallback=[];constructor(E){this.observations=E.observations,this.sessions=E.sessions,this.summaries=E.summaries,this.searchOrchestrator=E.searchOrchestrator,this.projectPath=E.projectPath,this.config=E.config,this.userObservationRepo=E.userObservationRepo??null,this.runtimeSnapshotProvider=E.runtimeSnapshotProvider??null,this.configAuditStore=E.configAuditStore??null,this.maintenanceHistoryStore=E.maintenanceHistoryStore??null}getByIdIncludingArchived(E){let M=this.observations;return M.getByIdIncludingArchived?M.getByIdIncludingArchived(E):this.observations.getById(E)}listByProjectWithState(E){let M=this.observations;if(M.listByProject)return M.listByProject(this.projectPath,E);if(E.state!=="current")return[];return this.listObservations({limit:E.limit,offset:E.offset,type:E.type,sessionId:E.sessionId})}async ingest(E){}async processPending(E){return 0}async search(E,M={}){return this.searchOrchestrator.search(E,{type:M.type,limit:M.limit??10,projectPath:this.projectPath,importanceMin:M.importanceMin,importanceMax:M.importanceMax,createdAfter:M.after,createdBefore:M.before,concepts:M.concepts,files:M.files})}async timeline(E={}){if(E.sessionId){let _=this.sessions.getById(E.sessionId);if(!_)return[];return[{session:_,summary:this.summaries.getBySessionId(_.id),observations:this.observations.getBySession(_.id)}]}return this.sessions.getRecent(this.projectPath,E.limit??5).map((_)=>({session:_,summary:this.summaries.getBySessionId(_.id),observations:[]}))}async recall(E,M=10){let _=[];for(let N of E.slice(0,M)){let S=this.observations.getById(N);if(S){_.push(S);continue}if(!this.userObservationRepo)continue;let O=this.userObservationRepo.getById(N);if(!O)continue;_.push({...O,sessionId:"",rawToolOutput:"",discoveryTokens:0})}return _}async save(E){if(E.scope==="user"){if(!this.userObservationRepo)return null;return{...this.userObservationRepo.create({type:E.type,title:E.title,subtitle:"",facts:[],narrative:E.narrative,concepts:E.concepts??[],filesRead:[],filesModified:E.files??[],toolName:"memory.create",tokenCount:z(`${E.title} ${E.narrative}`),importance:E.importance??3,sourceProject:this.projectPath}),sessionId:"",rawToolOutput:"",discoveryTokens:0}}this.sessions.getOrCreate(E.sessionId,this.projectPath);let M=this.observations.create({sessionId:E.sessionId,type:E.type,title:E.title,subtitle:"",facts:[],narrative:E.narrative,concepts:E.concepts??[],filesRead:[],filesModified:E.files??[],rawToolOutput:`[Manual save] ${E.narrative}`,toolName:"memory.create",tokenCount:z(`${E.title} ${E.narrative}`),discoveryTokens:0,importance:E.importance??3});return this.sessions.incrementObservationCount(E.sessionId),M}async update(E){let M=this.observations.getById(E.id);if(!M)return null;let _=this.sessions.getById(M.sessionId);if(!_||_.projectPath!==this.projectPath)return null;let{id:N,...S}=E;return this.observations.update(E.id,S)??null}async delete(E){let M=0;for(let _ of E){let N=this.observations.getById(_);if(!N)continue;let S=this.sessions.getById(N.sessionId);if(!S||S.projectPath!==this.projectPath)continue;if(this.observations.delete(_))M+=1}return M}async export(E,M={}){if(E!=="project")throw Error("Only project scope export is supported.");let _=this.sessions.getAll(this.projectPath),N=[];for(let J of _)N.push(...this.observations.getBySession(J.id));if(M.type)N=N.filter((J)=>J.type===M.type);if(N.sort((J,C)=>new Date(J.createdAt).getTime()-new Date(C.createdAt).getTime()),M.limit&&M.limit<N.length)N=N.slice(0,M.limit);let S=N.map(({rawToolOutput:J,...C})=>C),O=_.map((J)=>this.summaries.getBySessionId(J.id)).filter((J)=>J!==null);return{version:1,exportedAt:new Date().toISOString(),project:this.projectPath,observations:S,summaries:O}}async import(E,M={}){let _;try{_=JSON.parse(E)}catch{throw Error("Invalid JSON payload.")}if(typeof _!=="object"||_===null)throw Error("Invalid import payload.");let N=_;if(N.version!==1||!Array.isArray(N.observations))throw Error("Unsupported export format.");let S=M.mode??"skip-duplicates",O=0,A=0;for(let J of N.observations){let C=this.observations.getById(J.id);if(C&&S==="skip-duplicates"){A+=1;continue}if(C&&S==="overwrite")this.observations.delete(J.id);this.sessions.getOrCreate(J.sessionId,this.projectPath),this.observations.importObservation({id:J.id,sessionId:J.sessionId,type:J.type,title:J.title,subtitle:J.subtitle??"",facts:J.facts??[],narrative:J.narrative??"",concepts:J.concepts??[],filesRead:J.filesRead??[],filesModified:J.filesModified??[],rawToolOutput:J.rawToolOutput??"",toolName:J.toolName??"unknown",createdAt:J.createdAt,tokenCount:J.tokenCount??0,discoveryTokens:J.discoveryTokens??0,importance:J.importance??3,supersededBy:J.supersededBy??null,supersededAt:J.supersededAt??null}),this.sessions.incrementObservationCount(J.sessionId),O+=1}for(let J of N.summaries??[]){let C=this.summaries.getBySessionId(J.sessionId);if(C&&S==="skip-duplicates")continue;if(C&&S==="overwrite")continue;this.sessions.getOrCreate(J.sessionId,this.projectPath),this.summaries.importSummary(J),this.sessions.setSummary(J.sessionId,J.id)}return{imported:O,skipped:A}}async buildContext(E,M="normal"){let _=this.sessions.getRecent(this.projectPath,5),N=_.map(($)=>$.summaryId?this.summaries.getBySessionId($.id):null).filter(($)=>$!==null),S=this.observations.getIndex(this.projectPath,this.config.maxObservations),A=S.slice(0,this.config.contextFullObservationCount).map(($)=>$.id).map(($)=>this.observations.getById($)).filter(($)=>$!==null),J=YE(_,N,S,this.config.maxContextTokens,A);if(M==="compaction"){let $=LE(J);if(this.config.userMemoryEnabled&&this.userObservationRepo)$+=zE(this.userObservationRepo.getIndex(this.config.maxObservations),this.config.userMemoryMaxContextTokens);return $}let C={showTokenCosts:this.config.contextShowTokenCosts,observationTypes:this.config.contextObservationTypes,fullObservationCount:this.config.contextFullObservationCount,showLastSummary:this.config.contextShowLastSummary},V=KE(J,C);if(this.config.userMemoryEnabled&&this.userObservationRepo){let $=QE(this.userObservationRepo.getIndex(this.config.maxObservations),this.config.userMemoryMaxContextTokens);if($)V+=`
|
|
29
|
+
|
|
30
|
+
${$}`}return V}guide(){return["open-mem workflow:","1) Use memory.find to find candidate observations by query.","2) Use memory.history to inspect session-level history and summaries.","3) Use memory.get with IDs from find/history to fetch full details.","Write/edit flow: memory.create (new), memory.revise (refine), memory.remove (tombstone).","Transfer flow: memory.transfer.export for backup/portability, memory.transfer.import to restore."].join(`
|
|
31
|
+
`)}listObservations(E){let{limit:M=50,offset:_=0,type:N,sessionId:S,state:O}=E;if(O)return this.listByProjectWithState({limit:M,offset:_,type:N,state:O,sessionId:S});if(S){let C=this.observations.getBySession(S);if(N)C=C.filter((V)=>V.type===N);return C.slice(_,_+M)}let J=this.observations.getIndex(this.projectPath,_+M).slice(_);if(N)J=J.filter((C)=>C.type===N);return J.map((C)=>this.observations.getById(C.id)).filter((C)=>C!==null)}getObservation(E){return this.observations.getById(E)}getLineage(E){let _=this.getByIdIncludingArchived(E);if(!_)return null;let N=_,S=0,O=new Set([_.id]);while(N.revisionOf&&S<256){let $=this.getByIdIncludingArchived(N.revisionOf);if(!$||O.has($.id))break;N=$,O.add($.id),S+=1}let A=[],J=N,C=new Set,V=0;while(J&&!C.has(J.id)&&V<256){C.add(J.id);let $=J.deletedAt?"tombstoned":J.supersededBy?"superseded":"current";A.push({id:J.id,revisionOf:J.revisionOf??null,supersededBy:J.supersededBy??null,supersededAt:J.supersededAt??null,deletedAt:J.deletedAt??null,state:$,observation:J}),J=J.supersededBy?this.getByIdIncludingArchived(J.supersededBy):null,V+=1}return A}listSessions(E){return this.sessions.getRecent(E.projectPath??this.projectPath,E.limit??20)}getSession(E){let M=this.sessions.getById(E);if(!M)return null;return{session:M,summary:this.summaries.getBySessionId(E),observations:this.observations.getBySession(E)}}stats(){let E=this.observations.getCount(),_=this.sessions.getAll(this.projectPath).length,N=this.observations.getIndex(this.projectPath,1e4),S=0,O=0,A={};for(let V of N)S+=V.tokenCount,O+=V.discoveryTokens,A[V.type]=(A[V.type]||0)+1;let J=O-S,C=N.length>0?Math.round(S/N.length):0;return{totalObservations:E,totalSessions:_,totalTokensSaved:J,averageObservationSize:C,typeBreakdown:A}}async maintainFolderContext(E,M){if(E==="rebuild"){let N=await TE(this.projectPath,this.sessions,this.observations,this.config.folderContextMaxDepth,M);return{action:E,dryRun:M,...N}}let _=await kE(this.projectPath,M);return{action:"clean",dryRun:M,..._}}getRevisionDiff(E,M){let _=this.getByIdIncludingArchived(E),N=this.getByIdIncludingArchived(M);if(!_||!N)return null;let S=[],O=(J,C,V)=>{if(JSON.stringify(C)!==JSON.stringify(V))S.push({field:J,before:C,after:V})};O("title",N.title,_.title),O("subtitle",N.subtitle,_.subtitle),O("narrative",N.narrative,_.narrative),O("type",N.type,_.type),O("facts",N.facts,_.facts),O("concepts",N.concepts,_.concepts),O("filesRead",N.filesRead,_.filesRead),O("filesModified",N.filesModified,_.filesModified),O("importance",N.importance,_.importance);let A=S.length===0?"No material changes between revisions.":`Changed ${S.length} field${S.length===1?"":"s"}: ${S.map((J)=>J.field).join(", ")}.`;return{fromId:M,toId:E,summary:A,changedFields:S}}getHealth(){let E=this.runtimeSnapshotProvider?.(),M=E&&E.queue.lastError?"degraded":"ok";return{status:E?.status??"ok",timestamp:E?.timestamp??new Date().toISOString(),components:{database:{status:"ok"},search:{status:"ok"},config:{status:"ok"},queue:{status:M,detail:E?.queue.lastError??void 0}}}}getMetrics(){let E=this.stats();return{timestamp:this.runtimeSnapshotProvider?.()?.timestamp??new Date().toISOString(),memory:{totalObservations:E.totalObservations,totalSessions:E.totalSessions,totalTokensSaved:E.totalTokensSaved,averageObservationSize:E.averageObservationSize}}}getPlatforms(){return{name:"open-mem",provider:this.config.provider,dashboardEnabled:this.config.dashboardEnabled,vectorEnabled:Boolean(this.config.embeddingDimension&&this.config.embeddingDimension>0)}}getAdapterStatuses(){let E={opencode:this.config.platformOpenCodeEnabled??!0,"claude-code":this.config.platformClaudeCodeEnabled??!1,cursor:this.config.platformCursorEnabled??!1};return[{name:"opencode",version:"1.0",capabilities:{nativeSessionLifecycle:!0,nativeToolCapture:!0,nativeChatCapture:!0,emulatedIdleFlush:!1}},{name:"claude-code",version:"0.1",capabilities:{nativeSessionLifecycle:!0,nativeToolCapture:!0,nativeChatCapture:!0,emulatedIdleFlush:!0}},{name:"cursor",version:"0.1",capabilities:{nativeSessionLifecycle:!1,nativeToolCapture:!0,nativeChatCapture:!0,emulatedIdleFlush:!0}}].map((_)=>({name:_.name,version:_.version,enabled:E[_.name]??!1,capabilities:_.capabilities}))}getConfigAuditTimeline(){if(this.configAuditStore)return this.configAuditStore.list();return[...this.configAuditLogFallback].reverse()}trackConfigAudit(E){if(this.configAuditStore){this.configAuditStore.append(E);return}this.configAuditLogFallback.push(E)}async rollbackConfig(E){let M=this.configAuditStore?this.configAuditStore.getById(E):this.configAuditLogFallback.find((O)=>O.id===E)??null;if(!M)return null;if(!M.previousValues||typeof M.previousValues!=="object")return null;let{patchConfig:_}=await Promise.resolve().then(() => (vE(),hE)),N=M.previousValues;try{await _(this.projectPath,N)}catch(O){let A={id:`rollback-failed-${xE()}`,timestamp:new Date().toISOString(),patch:M.previousValues,previousValues:M.patch,source:"rollback-failed"};throw this.trackConfigAudit(A),O}let S={id:`rollback-${xE()}`,timestamp:new Date().toISOString(),patch:M.previousValues,previousValues:M.patch,source:"rollback"};return this.trackConfigAudit(S),S}getMaintenanceHistory(){if(this.maintenanceHistoryStore)return this.maintenanceHistoryStore.list();return[...this.maintenanceLogFallback].reverse()}trackMaintenanceResult(E){if(this.maintenanceHistoryStore){this.maintenanceHistoryStore.append(E);return}this.maintenanceLogFallback.push(E)}}function x(E){try{let M=JSON.parse(E);return M&&typeof M==="object"?M:{}}catch{return{}}}class t{db;constructor(E){this.db=E}list(){return this.db.all("SELECT id, timestamp, patch, previous_values, source FROM config_audit_events ORDER BY timestamp DESC").map((E)=>({id:E.id,timestamp:E.timestamp,patch:x(E.patch),previousValues:x(E.previous_values),source:E.source}))}getById(E){let M=this.db.get("SELECT id, timestamp, patch, previous_values, source FROM config_audit_events WHERE id = ?",[E]);if(!M)return null;return{id:M.id,timestamp:M.timestamp,patch:x(M.patch),previousValues:x(M.previous_values),source:M.source}}append(E){this.db.run("INSERT INTO config_audit_events (id, timestamp, patch, previous_values, source) VALUES (?, ?, ?, ?, ?)",[E.id,E.timestamp,JSON.stringify(E.patch??{}),JSON.stringify(E.previousValues??{}),E.source])}}import{Database as IE}from"bun:sqlite";import{existsSync as s,mkdirSync as Z0,unlinkSync as qE}from"fs";import*as lE from"sqlite-vec";class I{db;dbPath;_hasVectorExtension=!1;static enableExtensionSupport(){let E=["/opt/homebrew/opt/sqlite/lib/libsqlite3.dylib","/usr/local/opt/sqlite/lib/libsqlite3.dylib"];for(let M of E)try{if(s(M))return IE.setCustomSQLite(M),!0}catch{return!1}return!1}constructor(E){this.dbPath=E,this.db=this.open(E),this.configure()}open(E){let M=E.lastIndexOf("/");if(M>0){let _=E.substring(0,M);Z0(_,{recursive:!0})}return new IE(E,{create:!0})}configure(){try{this.applyPragmas(),this.loadExtensions()}catch(E){console.warn("[open-mem] Database configure failed, attempting recovery by removing WAL/SHM files:",E.message);try{this.db.close()}catch{}this.deleteSidecarFiles();try{this.db=this.open(this.dbPath),this.applyPragmas(),this.loadExtensions(),console.warn("[open-mem] Recovery successful after removing WAL/SHM files");return}catch(M){console.warn("[open-mem] WAL/SHM cleanup insufficient, recreating database from scratch:",M.message);try{this.db.close()}catch{}this.deleteDatabaseFiles();try{this.db=this.open(this.dbPath),this.applyPragmas(),this.loadExtensions(),console.warn("[open-mem] Recovery successful after full database recreation");return}catch(_){throw console.warn("[open-mem] All recovery attempts failed, filesystem may be broken:",_.message),E}}}}applyPragmas(){this.db.exec("PRAGMA journal_mode = WAL"),this.db.exec("PRAGMA synchronous = NORMAL"),this.db.exec("PRAGMA foreign_keys = ON"),this.db.exec("PRAGMA busy_timeout = 5000")}loadExtensions(){try{lE.load(this.db),this._hasVectorExtension=!0}catch{this._hasVectorExtension=!1}}get hasVectorExtension(){return this._hasVectorExtension}deleteSidecarFiles(){for(let E of["-wal","-shm"]){let M=this.dbPath+E;try{if(s(M))qE(M)}catch{}}}deleteDatabaseFiles(){this.deleteSidecarFiles();try{if(s(this.dbPath))qE(this.dbPath)}catch{}}ensureMigrationTable(){this.db.exec(`
|
|
31
32
|
CREATE TABLE IF NOT EXISTS _migrations (
|
|
32
33
|
version INTEGER PRIMARY KEY,
|
|
33
34
|
name TEXT NOT NULL,
|
|
34
35
|
applied_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
35
36
|
)
|
|
36
|
-
`)}migrate(
|
|
37
|
+
`)}migrate(E){this.ensureMigrationTable();let M=this.db.query("SELECT version FROM _migrations ORDER BY version").all(),_=new Set(M.map((S)=>S.version)),N=E.filter((S)=>!_.has(S.version)).sort((S,O)=>S.version-O.version);for(let S of N)this.db.transaction(()=>{this.db.exec(S.up),this.db.query("INSERT INTO _migrations (version, name) VALUES ($version, $name)").run({$version:S.version,$name:S.name})})()}run(E,M){let _=this.db.query(E);if(M)_.run(...M);else _.run()}get(E,M){let _=this.db.query(E);return M?_.get(...M):_.get()}all(E,M){let _=this.db.query(E);return M?_.all(...M):_.all()}exec(E){this.db.exec(E)}transaction(E){return this.db.transaction(E)()}close(){this.db.close()}get isOpen(){try{return this.db.query("SELECT 1").get(),!0}catch{return!1}}get raw(){return this.db}}function q(E){return new I(E)}import{randomUUID as wE}from"crypto";class EE{db;constructor(E){this.db=E}upsertEntity(E,M){let _=wE(),N=new Date().toISOString();this.db.run(`INSERT INTO entities (id, name, entity_type, first_seen_at, last_seen_at, mention_count)
|
|
37
38
|
VALUES (?, ?, ?, ?, ?, 1)
|
|
38
39
|
ON CONFLICT(name, entity_type) DO UPDATE SET
|
|
39
40
|
mention_count = mention_count + 1,
|
|
40
|
-
last_seen_at = ?`,[
|
|
41
|
+
last_seen_at = ?`,[_,E,M,N,N,N]);let S=this.db.get("SELECT * FROM entities WHERE name = ? AND entity_type = ?",[E,M]);if(!S)throw Error(`Failed to upsert entity: ${E} (${M})`);return this.mapEntityRow(S)}createRelation(E,M,_,N){let S=wE(),O=new Date().toISOString();try{this.db.run(`INSERT OR IGNORE INTO entity_relations
|
|
41
42
|
(id, source_entity_id, target_entity_id, relationship, observation_id, created_at)
|
|
42
|
-
VALUES (?, ?, ?, ?, ?, ?)`,[
|
|
43
|
-
WHERE source_entity_id = ? AND target_entity_id = ? AND relationship = ?`,[
|
|
43
|
+
VALUES (?, ?, ?, ?, ?, ?)`,[S,E,M,_,N,O])}catch{return null}let A=this.db.get(`SELECT * FROM entity_relations
|
|
44
|
+
WHERE source_entity_id = ? AND target_entity_id = ? AND relationship = ?`,[E,M,_]);return A?this.mapRelationRow(A):null}linkObservation(E,M){this.db.run("INSERT OR IGNORE INTO entity_observations (entity_id, observation_id) VALUES (?, ?)",[E,M])}findByName(E){try{return this.db.all(`SELECT e.*
|
|
44
45
|
FROM entities e
|
|
45
46
|
JOIN entities_fts fts ON e._rowid = fts.rowid
|
|
46
47
|
WHERE entities_fts MATCH ?
|
|
47
|
-
ORDER BY rank`,[
|
|
48
|
-
WHERE source_entity_id = ? OR target_entity_id = ?`,[
|
|
48
|
+
ORDER BY rank`,[E]).map((_)=>this.mapEntityRow(_))}catch{return[]}}getRelationsFor(E){return this.db.all(`SELECT * FROM entity_relations
|
|
49
|
+
WHERE source_entity_id = ? OR target_entity_id = ?`,[E,E]).map((_)=>this.mapRelationRow(_))}traverseRelations(E,M=1){let _=Math.min(M,2),N=100,S=new Set,O=[{id:E,currentDepth:0}];S.add(E);while(O.length>0){if(S.size>=100)break;let A=O.shift();if(!A)continue;if(A.currentDepth>=_)continue;let J=this.getRelationsFor(A.id);for(let C of J){let V=C.sourceEntityId===A.id?C.targetEntityId:C.sourceEntityId;if(!S.has(V))S.add(V),O.push({id:V,currentDepth:A.currentDepth+1})}}return S}getObservationsForEntity(E){return this.db.all("SELECT observation_id FROM entity_observations WHERE entity_id = ?",[E]).map((_)=>_.observation_id)}getById(E){let M=this.db.get("SELECT * FROM entities WHERE id = ?",[E]);return M?this.mapEntityRow(M):null}mapEntityRow(E){return{id:E.id,name:E.name,entityType:E.entity_type,firstSeenAt:E.first_seen_at,lastSeenAt:E.last_seen_at,mentionCount:E.mention_count}}mapRelationRow(E){return{id:E.id,sourceEntityId:E.source_entity_id,targetEntityId:E.target_entity_id,relationship:E.relationship,observationId:E.observation_id,createdAt:E.created_at}}}function H0(E){try{let M=JSON.parse(E);return M&&typeof M==="object"?M:{}}catch{return{}}}class ME{db;constructor(E){this.db=E}list(){return this.db.all("SELECT id, timestamp, action, dry_run, result FROM maintenance_history ORDER BY timestamp DESC").map((E)=>({id:E.id,timestamp:E.timestamp,action:E.action,dryRun:E.dry_run===1,result:H0(E.result)}))}append(E){this.db.run("INSERT INTO maintenance_history (id, timestamp, action, dry_run, result) VALUES (?, ?, ?, ?, ?)",[E.id,E.timestamp,E.action,E.dryRun?1:0,JSON.stringify(E.result??{})])}}import{randomUUID as L0}from"crypto";import{embed as K0}from"ai";async function l(E,M){try{let{embedding:_}=await K0({model:E,value:M});return _}catch{return null}}function G(E,M){if(E.length!==M.length||E.length===0)return 0;let _=0,N=0,S=0;for(let A=0;A<E.length;A++)_+=E[A]*M[A],N+=E[A]*E[A],S+=M[A]*M[A];let O=Math.sqrt(N)*Math.sqrt(S);if(O===0)return 0;return _/O}function Q0(E){return E.replace(/[%_\\]/g,"\\$&")}class _E{db;constructor(E){this.db=E}create(E){let M=L0(),_=new Date().toISOString(),N=E.discoveryTokens??0,S=E.importance??3,O=E.scope??"project";return this.db.run(`INSERT INTO observations
|
|
49
50
|
(id, session_id, scope, type, title, subtitle, facts, narrative,
|
|
50
51
|
concepts, files_read, files_modified, raw_tool_output,
|
|
51
52
|
tool_name, created_at, token_count, discovery_tokens, importance, revision_of, deleted_at)
|
|
52
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[
|
|
53
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[M,E.sessionId,O,E.type,E.title,E.subtitle,JSON.stringify(E.facts),E.narrative,JSON.stringify(E.concepts),JSON.stringify(E.filesRead),JSON.stringify(E.filesModified),E.rawToolOutput,E.toolName,_,E.tokenCount,N,S,null,null]),{...E,id:M,scope:O,createdAt:_,discoveryTokens:N,importance:S,revisionOf:null,deletedAt:null,supersededBy:null,supersededAt:null}}importObservation(E){this.db.run(`INSERT INTO observations
|
|
53
54
|
(id, session_id, scope, type, title, subtitle, facts, narrative,
|
|
54
55
|
concepts, files_read, files_modified, raw_tool_output,
|
|
55
56
|
tool_name, created_at, token_count, discovery_tokens, importance, revision_of, deleted_at)
|
|
56
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[
|
|
57
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[E.id,E.sessionId,E.scope??"project",E.type,E.title,E.subtitle,JSON.stringify(E.facts),E.narrative,JSON.stringify(E.concepts),JSON.stringify(E.filesRead),JSON.stringify(E.filesModified),E.rawToolOutput,E.toolName,E.createdAt,E.tokenCount,E.discoveryTokens??0,E.importance??3,E.revisionOf??null,E.deletedAt??null])}getById(E){let M=this.db.get("SELECT * FROM observations WHERE id = ? AND superseded_by IS NULL AND deleted_at IS NULL",[E]);return M?this.mapRow(M):null}getByIdIncludingArchived(E){let M=this.db.get("SELECT * FROM observations WHERE id = ?",[E]);return M?this.mapRow(M):null}getBySession(E){return this.db.all("SELECT * FROM observations WHERE session_id = ? AND superseded_by IS NULL AND deleted_at IS NULL ORDER BY created_at ASC",[E]).map((M)=>this.mapRow(M))}getCount(E){if(E)return this.db.get("SELECT COUNT(*) as count FROM observations WHERE session_id = ?",[E])?.count??0;return this.db.get("SELECT COUNT(*) as count FROM observations")?.count??0}getIndex(E,M=20){return this.db.all(`SELECT o.id, o.session_id, o.type, o.title, o.token_count, o.discovery_tokens, o.created_at, o.importance
|
|
57
58
|
FROM observations o
|
|
58
59
|
JOIN sessions s ON o.session_id = s.id
|
|
59
60
|
WHERE s.project_path = ? AND o.superseded_by IS NULL AND o.deleted_at IS NULL
|
|
60
61
|
ORDER BY o.created_at DESC
|
|
61
|
-
LIMIT ?`,[
|
|
62
|
+
LIMIT ?`,[E,M]).map((_)=>({id:_.id,sessionId:_.session_id,type:_.type,title:_.title,tokenCount:_.token_count,discoveryTokens:_.discovery_tokens??0,createdAt:_.created_at,importance:_.importance??3}))}listByProject(E,M={}){let{limit:_=50,offset:N=0,type:S,state:O,sessionId:A}=M,J=`SELECT o.*
|
|
63
|
+
FROM observations o
|
|
64
|
+
JOIN sessions s ON o.session_id = s.id
|
|
65
|
+
WHERE s.project_path = ?`,C=[E];if(A)J+=" AND o.session_id = ?",C.push(A);if(S)J+=" AND o.type = ?",C.push(S);if(O==="current")J+=" AND o.superseded_by IS NULL AND o.deleted_at IS NULL";else if(O==="superseded")J+=" AND o.superseded_by IS NOT NULL AND o.deleted_at IS NULL";else if(O==="tombstoned")J+=" AND o.deleted_at IS NOT NULL";else J+=" AND o.superseded_by IS NULL AND o.deleted_at IS NULL";return J+=" ORDER BY o.created_at DESC LIMIT ? OFFSET ?",C.push(_,N),this.db.all(J,C).map((V)=>this.mapRow(V))}search(E){let M=!!E.projectPath,_=`
|
|
62
66
|
SELECT o.*, rank
|
|
63
67
|
FROM observations o
|
|
64
68
|
JOIN observations_fts fts ON o._rowid = fts.rowid
|
|
65
|
-
${
|
|
69
|
+
${M?"JOIN sessions s ON o.session_id = s.id":""}
|
|
66
70
|
WHERE observations_fts MATCH ? AND o.superseded_by IS NULL AND o.deleted_at IS NULL
|
|
67
|
-
`,
|
|
68
|
-
OR EXISTS (SELECT 1 FROM json_each(o.files_modified) WHERE LOWER(value) LIKE LOWER(?) ESCAPE '\\'))`);
|
|
71
|
+
`,N=[E.query];if(M&&E.projectPath)_+=" AND s.project_path = ?",N.push(E.projectPath);if(E.sessionId)_+=" AND o.session_id = ?",N.push(E.sessionId);if(E.type)_+=" AND o.type = ?",N.push(E.type);if(E.importanceMin!==void 0)_+=" AND o.importance >= ?",N.push(E.importanceMin);if(E.importanceMax!==void 0)_+=" AND o.importance <= ?",N.push(E.importanceMax);if(E.createdAfter)_+=" AND o.created_at >= ?",N.push(E.createdAfter);if(E.createdBefore)_+=" AND o.created_at <= ?",N.push(E.createdBefore);if(E.concepts&&E.concepts.length>0){let S=E.concepts.map(()=>"EXISTS (SELECT 1 FROM json_each(o.concepts) WHERE LOWER(value) = LOWER(?))");_+=` AND (${S.join(" OR ")})`;for(let O of E.concepts)N.push(O)}if(E.files&&E.files.length>0){let S=E.files.map(()=>`(EXISTS (SELECT 1 FROM json_each(o.files_read) WHERE LOWER(value) LIKE LOWER(?) ESCAPE '\\')
|
|
72
|
+
OR EXISTS (SELECT 1 FROM json_each(o.files_modified) WHERE LOWER(value) LIKE LOWER(?) ESCAPE '\\'))`);_+=` AND (${S.join(" OR ")})`;for(let O of E.files){let A=`%${Q0(O)}%`;N.push(A,A)}}return _+=" ORDER BY rank LIMIT ? OFFSET ?",N.push(E.limit??10),N.push(E.offset??0),this.db.all(_,N).map((S)=>({observation:this.mapRow(S),rank:S.rank,snippet:S.title}))}searchByConcept(E,M=10,_){let N=!!_,S=`SELECT o.*
|
|
69
73
|
FROM observations o
|
|
70
74
|
JOIN observations_fts fts ON o._rowid = fts.rowid
|
|
71
|
-
${
|
|
75
|
+
${N?"JOIN sessions s ON o.session_id = s.id":""}
|
|
72
76
|
WHERE observations_fts MATCH ?
|
|
73
77
|
AND o.superseded_by IS NULL AND o.deleted_at IS NULL
|
|
74
|
-
${
|
|
78
|
+
${N?"AND s.project_path = ?":""}
|
|
75
79
|
ORDER BY rank
|
|
76
|
-
LIMIT ?`,
|
|
80
|
+
LIMIT ?`,O=[`concepts:${E}`];if(N&&_)O.push(_);return O.push(M),this.db.all(S,O).map((A)=>this.mapRow(A))}searchByFile(E,M=10,_){let N=!!_,S=`SELECT o.*
|
|
77
81
|
FROM observations o
|
|
78
82
|
JOIN observations_fts fts ON o._rowid = fts.rowid
|
|
79
|
-
${
|
|
83
|
+
${N?"JOIN sessions s ON o.session_id = s.id":""}
|
|
80
84
|
WHERE observations_fts MATCH ?
|
|
81
85
|
AND o.superseded_by IS NULL AND o.deleted_at IS NULL
|
|
82
|
-
${
|
|
86
|
+
${N?"AND s.project_path = ?":""}
|
|
83
87
|
ORDER BY rank
|
|
84
|
-
LIMIT ?`,
|
|
88
|
+
LIMIT ?`,O=[`files_read:"${E.replace(/"/g,'""')}" OR files_modified:"${E.replace(/"/g,'""')}"`];if(N&&_)O.push(_);return O.push(M),this.db.all(S,O).map((A)=>this.mapRow(A))}setEmbedding(E,M){this.db.run("UPDATE observations SET embedding = ? WHERE id = ?",[JSON.stringify(M),E])}getWithEmbeddings(E,M){return this.db.all(`SELECT o.id, o.embedding, o.title
|
|
85
89
|
FROM observations o
|
|
86
90
|
JOIN sessions s ON o.session_id = s.id
|
|
87
91
|
WHERE s.project_path = ? AND o.embedding IS NOT NULL AND o.superseded_by IS NULL AND o.deleted_at IS NULL
|
|
88
92
|
ORDER BY o.created_at DESC
|
|
89
|
-
LIMIT ?`,[
|
|
93
|
+
LIMIT ?`,[E,M]).map((_)=>{try{return{id:_.id,embedding:JSON.parse(_.embedding),title:_.title}}catch{return null}}).filter((_)=>_!==null)}findSimilar(E,M,_,N){let S=this.db.all(`SELECT id, embedding FROM observations
|
|
90
94
|
WHERE embedding IS NOT NULL AND type = ? AND superseded_by IS NULL AND deleted_at IS NULL
|
|
91
95
|
ORDER BY created_at DESC
|
|
92
|
-
LIMIT 200`,[
|
|
96
|
+
LIMIT 200`,[M]),O=[];for(let A of S)try{let J=JSON.parse(A.embedding);if(!Array.isArray(J)||J.length!==E.length)continue;let C=G(E,J);if(C>=_)O.push({id:A.id,similarity:C})}catch{}return O.sort((A,J)=>J.similarity-A.similarity).slice(0,N)}insertVecEmbedding(E,M){let _=new Float32Array(M);this.db.run("BEGIN");try{this.db.run("DELETE FROM observation_embeddings WHERE observation_id = ?",[E]),this.db.run("INSERT INTO observation_embeddings (observation_id, embedding) VALUES (?, ?)",[E,_]),this.db.run("COMMIT")}catch(N){throw this.db.run("ROLLBACK"),N}}migrateExistingEmbeddings(E){let M=this.db.all("SELECT id, embedding FROM observations WHERE embedding IS NOT NULL"),_=0,N=0;for(let S of M)try{let O=JSON.parse(S.embedding);if(!Array.isArray(O)||O.length!==E){N++;continue}this.insertVecEmbedding(S.id,O),_++}catch{N++}return{migrated:_,skipped:N}}getVecEmbeddingMatches(E,M){try{let _=new Float32Array(E);return this.db.all(`SELECT observation_id, distance
|
|
93
97
|
FROM observation_embeddings
|
|
94
|
-
WHERE embedding MATCH ? AND k = ?`,[
|
|
98
|
+
WHERE embedding MATCH ? AND k = ?`,[_,M]).map((N)=>({observationId:N.observation_id,distance:N.distance}))}catch{return[]}}searchVecSubset(E,M,_){if(M.length===0)return[];try{let N=new Float32Array(E),S=Math.max(_*5,M.length),O=this.db.all(`SELECT observation_id, distance
|
|
95
99
|
FROM observation_embeddings
|
|
96
|
-
WHERE embedding MATCH ? AND k = ?`,[
|
|
100
|
+
WHERE embedding MATCH ? AND k = ?`,[N,S]),A=new Set(M);return O.filter((J)=>A.has(J.observation_id)).slice(0,_).map((J)=>({observationId:J.observation_id,distance:J.distance}))}catch{return[]}}update(E,M){let _=this.getById(E);if(!_)return null;if(Object.keys(M).length===0)return _;let N=this.create({sessionId:_.sessionId,scope:_.scope??"project",type:M.type??_.type,title:M.title??_.title,subtitle:M.subtitle??_.subtitle,facts:M.facts??_.facts,narrative:M.narrative??_.narrative,concepts:M.concepts??_.concepts,filesRead:M.filesRead??_.filesRead,filesModified:M.filesModified??_.filesModified,rawToolOutput:_.rawToolOutput,toolName:"memory.revise",tokenCount:_.tokenCount,discoveryTokens:_.discoveryTokens,importance:M.importance??_.importance});return this.db.run("UPDATE observations SET revision_of = ? WHERE id = ?",[E,N.id]),this.supersede(E,N.id),this.getById(N.id)}supersede(E,M){let _=new Date().toISOString();this.db.run("UPDATE observations SET superseded_by = ?, superseded_at = ? WHERE id = ?",[M,_,E])}delete(E){if(this.db.all("SELECT id FROM observations WHERE id = ?",[E]).length===0)return!1;let _=new Date().toISOString();return this.db.run("UPDATE observations SET deleted_at = ? WHERE id = ?",[_,E]),this.deleteEmbeddingsForObservations([E]),!0}getLineage(E){let M=this.getByIdIncludingArchived(E);if(!M)return[];let _=new Set([M.id]),N=[M];while(N[0].revisionOf){let S=this.getByIdIncludingArchived(N[0].revisionOf);if(!S||_.has(S.id))break;N.unshift(S),_.add(S.id)}while(N[N.length-1].supersededBy){let S=N[N.length-1].supersededBy;if(!S)break;let O=this.getByIdIncludingArchived(S);if(!O||_.has(O.id))break;N.push(O),_.add(O.id)}return N}deleteOlderThan(E){return this.db.all(`DELETE FROM observations
|
|
97
101
|
WHERE (created_at < datetime('now', '-' || ? || ' days') OR deleted_at IS NOT NULL)
|
|
98
102
|
AND session_id NOT IN (SELECT id FROM sessions WHERE status != 'completed')
|
|
99
|
-
RETURNING id`,[
|
|
103
|
+
RETURNING id`,[E]).length}deleteEmbeddingsForObservations(E){if(E.length===0)return;let M=E.map(()=>"?").join(",");try{this.db.run(`DELETE FROM observation_embeddings WHERE observation_id IN (${M})`,E)}catch{}this.db.run(`UPDATE observations SET embedding = NULL WHERE id IN (${M})`,E)}mapRow(E){return{id:E.id,sessionId:E.session_id,scope:E.scope??"project",type:E.type,title:E.title,subtitle:E.subtitle,facts:JSON.parse(E.facts),narrative:E.narrative,concepts:JSON.parse(E.concepts),filesRead:JSON.parse(E.files_read),filesModified:JSON.parse(E.files_modified),rawToolOutput:E.raw_tool_output,toolName:E.tool_name,createdAt:E.created_at,tokenCount:E.token_count,discoveryTokens:E.discovery_tokens??0,importance:E.importance??3,revisionOf:E.revision_of??null,deletedAt:E.deleted_at??null,supersededBy:E.superseded_by??null,supersededAt:E.superseded_at??null}}}var z0=[{version:1,name:"create-schema",up:`
|
|
100
104
|
-- Sessions table
|
|
101
105
|
CREATE TABLE IF NOT EXISTS sessions (
|
|
102
106
|
_rowid INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
@@ -135,6 +139,15 @@ ${V}`}return W}guide(){return["open-mem workflow:","1) Use mem-search to find ca
|
|
|
135
139
|
tool_name TEXT NOT NULL,
|
|
136
140
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
137
141
|
token_count INTEGER NOT NULL DEFAULT 0,
|
|
142
|
+
discovery_tokens INTEGER NOT NULL DEFAULT 0,
|
|
143
|
+
embedding TEXT,
|
|
144
|
+
importance INTEGER NOT NULL DEFAULT 3,
|
|
145
|
+
superseded_by TEXT,
|
|
146
|
+
superseded_at TEXT,
|
|
147
|
+
scope TEXT NOT NULL DEFAULT 'project'
|
|
148
|
+
CHECK (scope IN ('project','user')),
|
|
149
|
+
revision_of TEXT,
|
|
150
|
+
deleted_at TEXT,
|
|
138
151
|
FOREIGN KEY (session_id) REFERENCES sessions(id)
|
|
139
152
|
);
|
|
140
153
|
|
|
@@ -144,6 +157,23 @@ ${V}`}return W}guide(){return["open-mem workflow:","1) Use mem-search to find ca
|
|
|
144
157
|
ON observations(type);
|
|
145
158
|
CREATE INDEX IF NOT EXISTS idx_observations_created
|
|
146
159
|
ON observations(created_at DESC);
|
|
160
|
+
CREATE INDEX IF NOT EXISTS idx_observations_superseded
|
|
161
|
+
ON observations(superseded_by);
|
|
162
|
+
CREATE INDEX IF NOT EXISTS idx_observations_scope
|
|
163
|
+
ON observations(scope);
|
|
164
|
+
CREATE INDEX IF NOT EXISTS idx_observations_revision_of
|
|
165
|
+
ON observations(revision_of);
|
|
166
|
+
CREATE INDEX IF NOT EXISTS idx_observations_deleted_at
|
|
167
|
+
ON observations(deleted_at);
|
|
168
|
+
|
|
169
|
+
-- Clean up superseded_by when the superseding observation is deleted
|
|
170
|
+
CREATE TRIGGER IF NOT EXISTS trg_clear_superseded_by
|
|
171
|
+
AFTER DELETE ON observations
|
|
172
|
+
BEGIN
|
|
173
|
+
UPDATE observations
|
|
174
|
+
SET superseded_by = NULL, superseded_at = NULL
|
|
175
|
+
WHERE superseded_by = OLD.id;
|
|
176
|
+
END;
|
|
147
177
|
|
|
148
178
|
-- Session summaries table
|
|
149
179
|
CREATE TABLE IF NOT EXISTS session_summaries (
|
|
@@ -156,6 +186,11 @@ ${V}`}return W}guide(){return["open-mem workflow:","1) Use mem-search to find ca
|
|
|
156
186
|
concepts TEXT NOT NULL DEFAULT '[]',
|
|
157
187
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
158
188
|
token_count INTEGER NOT NULL DEFAULT 0,
|
|
189
|
+
request TEXT NOT NULL DEFAULT '',
|
|
190
|
+
investigated TEXT NOT NULL DEFAULT '',
|
|
191
|
+
learned TEXT NOT NULL DEFAULT '',
|
|
192
|
+
completed TEXT NOT NULL DEFAULT '',
|
|
193
|
+
next_steps TEXT NOT NULL DEFAULT '',
|
|
159
194
|
FOREIGN KEY (session_id) REFERENCES sessions(id)
|
|
160
195
|
);
|
|
161
196
|
|
|
@@ -179,8 +214,83 @@ ${V}`}return W}guide(){return["open-mem workflow:","1) Use mem-search to find ca
|
|
|
179
214
|
ON pending_messages(status);
|
|
180
215
|
CREATE INDEX IF NOT EXISTS idx_pending_session
|
|
181
216
|
ON pending_messages(session_id);
|
|
182
|
-
|
|
183
|
-
--
|
|
217
|
+
|
|
218
|
+
-- Embedding metadata
|
|
219
|
+
CREATE TABLE IF NOT EXISTS _embedding_meta (
|
|
220
|
+
key TEXT PRIMARY KEY,
|
|
221
|
+
value TEXT NOT NULL
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
-- Config audit events
|
|
225
|
+
CREATE TABLE IF NOT EXISTS config_audit_events (
|
|
226
|
+
_rowid INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
227
|
+
id TEXT UNIQUE NOT NULL,
|
|
228
|
+
timestamp TEXT NOT NULL,
|
|
229
|
+
patch TEXT NOT NULL,
|
|
230
|
+
previous_values TEXT NOT NULL,
|
|
231
|
+
source TEXT NOT NULL
|
|
232
|
+
CHECK (source IN ('api','mode','rollback','rollback-failed'))
|
|
233
|
+
);
|
|
234
|
+
CREATE INDEX IF NOT EXISTS idx_config_audit_timestamp
|
|
235
|
+
ON config_audit_events(timestamp DESC);
|
|
236
|
+
|
|
237
|
+
-- Maintenance history
|
|
238
|
+
CREATE TABLE IF NOT EXISTS maintenance_history (
|
|
239
|
+
_rowid INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
240
|
+
id TEXT UNIQUE NOT NULL,
|
|
241
|
+
timestamp TEXT NOT NULL,
|
|
242
|
+
action TEXT NOT NULL,
|
|
243
|
+
dry_run INTEGER NOT NULL DEFAULT 0,
|
|
244
|
+
result TEXT NOT NULL
|
|
245
|
+
);
|
|
246
|
+
CREATE INDEX IF NOT EXISTS idx_maintenance_history_timestamp
|
|
247
|
+
ON maintenance_history(timestamp DESC);
|
|
248
|
+
|
|
249
|
+
-- Entities table
|
|
250
|
+
CREATE TABLE IF NOT EXISTS entities (
|
|
251
|
+
_rowid INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
252
|
+
id TEXT UNIQUE NOT NULL,
|
|
253
|
+
name TEXT NOT NULL,
|
|
254
|
+
entity_type TEXT NOT NULL
|
|
255
|
+
CHECK (entity_type IN ('technology','library','pattern','concept','file','person','project','other')),
|
|
256
|
+
first_seen_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
257
|
+
last_seen_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
258
|
+
mention_count INTEGER NOT NULL DEFAULT 1,
|
|
259
|
+
UNIQUE(name, entity_type)
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
CREATE INDEX IF NOT EXISTS idx_entities_name ON entities(name);
|
|
263
|
+
CREATE INDEX IF NOT EXISTS idx_entities_type ON entities(entity_type);
|
|
264
|
+
|
|
265
|
+
-- Entity relations table
|
|
266
|
+
CREATE TABLE IF NOT EXISTS entity_relations (
|
|
267
|
+
_rowid INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
268
|
+
id TEXT UNIQUE NOT NULL,
|
|
269
|
+
source_entity_id TEXT NOT NULL,
|
|
270
|
+
target_entity_id TEXT NOT NULL,
|
|
271
|
+
relationship TEXT NOT NULL
|
|
272
|
+
CHECK (relationship IN ('uses','depends_on','implements','extends','related_to','replaces','configures')),
|
|
273
|
+
observation_id TEXT NOT NULL,
|
|
274
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
275
|
+
UNIQUE(source_entity_id, target_entity_id, relationship),
|
|
276
|
+
FOREIGN KEY (source_entity_id) REFERENCES entities(id) ON DELETE CASCADE,
|
|
277
|
+
FOREIGN KEY (target_entity_id) REFERENCES entities(id) ON DELETE CASCADE,
|
|
278
|
+
FOREIGN KEY (observation_id) REFERENCES observations(id) ON DELETE CASCADE
|
|
279
|
+
);
|
|
280
|
+
|
|
281
|
+
CREATE INDEX IF NOT EXISTS idx_entity_relations_source ON entity_relations(source_entity_id);
|
|
282
|
+
CREATE INDEX IF NOT EXISTS idx_entity_relations_target ON entity_relations(target_entity_id);
|
|
283
|
+
|
|
284
|
+
-- Entity-Observation junction table
|
|
285
|
+
CREATE TABLE IF NOT EXISTS entity_observations (
|
|
286
|
+
entity_id TEXT NOT NULL,
|
|
287
|
+
observation_id TEXT NOT NULL,
|
|
288
|
+
PRIMARY KEY (entity_id, observation_id),
|
|
289
|
+
FOREIGN KEY (entity_id) REFERENCES entities(id) ON DELETE CASCADE,
|
|
290
|
+
FOREIGN KEY (observation_id) REFERENCES observations(id) ON DELETE CASCADE
|
|
291
|
+
);
|
|
292
|
+
|
|
293
|
+
-- FTS5 for observations
|
|
184
294
|
CREATE VIRTUAL TABLE IF NOT EXISTS observations_fts USING fts5(
|
|
185
295
|
title,
|
|
186
296
|
subtitle,
|
|
@@ -194,7 +304,6 @@ ${V}`}return W}guide(){return["open-mem workflow:","1) Use mem-search to find ca
|
|
|
194
304
|
tokenize='porter unicode61'
|
|
195
305
|
);
|
|
196
306
|
|
|
197
|
-
-- Triggers to keep FTS5 in sync with observations table
|
|
198
307
|
CREATE TRIGGER observations_ai AFTER INSERT ON observations BEGIN
|
|
199
308
|
INSERT INTO observations_fts(
|
|
200
309
|
rowid, title, subtitle, narrative, facts, concepts,
|
|
@@ -251,88 +360,14 @@ ${V}`}return W}guide(){return["open-mem workflow:","1) Use mem-search to find ca
|
|
|
251
360
|
VALUES (new._rowid, new.summary, new.key_decisions, new.concepts);
|
|
252
361
|
END;
|
|
253
362
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
END;
|
|
262
|
-
`},{version:3,name:"add-structured-summary-columns",up:`
|
|
263
|
-
ALTER TABLE session_summaries ADD COLUMN request TEXT NOT NULL DEFAULT '';
|
|
264
|
-
ALTER TABLE session_summaries ADD COLUMN investigated TEXT NOT NULL DEFAULT '';
|
|
265
|
-
ALTER TABLE session_summaries ADD COLUMN learned TEXT NOT NULL DEFAULT '';
|
|
266
|
-
ALTER TABLE session_summaries ADD COLUMN completed TEXT NOT NULL DEFAULT '';
|
|
267
|
-
ALTER TABLE session_summaries ADD COLUMN next_steps TEXT NOT NULL DEFAULT '';
|
|
268
|
-
`},{version:4,name:"add-discovery-tokens",up:`
|
|
269
|
-
ALTER TABLE observations ADD COLUMN discovery_tokens INTEGER NOT NULL DEFAULT 0;
|
|
270
|
-
`},{version:5,name:"add-embedding-column",up:`
|
|
271
|
-
ALTER TABLE observations ADD COLUMN embedding TEXT;
|
|
272
|
-
`},{version:6,name:"create-embedding-meta-table",up:`
|
|
273
|
-
CREATE TABLE IF NOT EXISTS _embedding_meta (
|
|
274
|
-
key TEXT PRIMARY KEY,
|
|
275
|
-
value TEXT NOT NULL
|
|
276
|
-
);
|
|
277
|
-
`},{version:7,name:"add-importance-column",up:`
|
|
278
|
-
ALTER TABLE observations ADD COLUMN importance INTEGER NOT NULL DEFAULT 3;
|
|
279
|
-
`},{version:8,name:"add-conflict-resolution-columns",up:`
|
|
280
|
-
ALTER TABLE observations ADD COLUMN superseded_by TEXT;
|
|
281
|
-
ALTER TABLE observations ADD COLUMN superseded_at TEXT;
|
|
282
|
-
CREATE INDEX IF NOT EXISTS idx_observations_superseded ON observations(superseded_by);
|
|
283
|
-
|
|
284
|
-
-- Clean up superseded_by when the superseding observation is deleted
|
|
285
|
-
CREATE TRIGGER IF NOT EXISTS trg_clear_superseded_by
|
|
286
|
-
AFTER DELETE ON observations
|
|
287
|
-
BEGIN
|
|
288
|
-
UPDATE observations
|
|
289
|
-
SET superseded_by = NULL, superseded_at = NULL
|
|
290
|
-
WHERE superseded_by = OLD.id;
|
|
363
|
+
CREATE TRIGGER summaries_ad AFTER DELETE ON session_summaries BEGIN
|
|
364
|
+
INSERT INTO summaries_fts(
|
|
365
|
+
summaries_fts, rowid, summary, key_decisions, concepts
|
|
366
|
+
)
|
|
367
|
+
VALUES (
|
|
368
|
+
'delete', old._rowid, old.summary, old.key_decisions, old.concepts
|
|
369
|
+
);
|
|
291
370
|
END;
|
|
292
|
-
`},{version:9,name:"create-entity-graph-tables",up:`
|
|
293
|
-
-- Entities table
|
|
294
|
-
CREATE TABLE IF NOT EXISTS entities (
|
|
295
|
-
_rowid INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
296
|
-
id TEXT UNIQUE NOT NULL,
|
|
297
|
-
name TEXT NOT NULL,
|
|
298
|
-
entity_type TEXT NOT NULL
|
|
299
|
-
CHECK (entity_type IN ('technology','library','pattern','concept','file','person','project','other')),
|
|
300
|
-
first_seen_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
301
|
-
last_seen_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
302
|
-
mention_count INTEGER NOT NULL DEFAULT 1,
|
|
303
|
-
UNIQUE(name, entity_type)
|
|
304
|
-
);
|
|
305
|
-
|
|
306
|
-
CREATE INDEX IF NOT EXISTS idx_entities_name ON entities(name);
|
|
307
|
-
CREATE INDEX IF NOT EXISTS idx_entities_type ON entities(entity_type);
|
|
308
|
-
|
|
309
|
-
-- Entity relations table
|
|
310
|
-
CREATE TABLE IF NOT EXISTS entity_relations (
|
|
311
|
-
_rowid INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
312
|
-
id TEXT UNIQUE NOT NULL,
|
|
313
|
-
source_entity_id TEXT NOT NULL,
|
|
314
|
-
target_entity_id TEXT NOT NULL,
|
|
315
|
-
relationship TEXT NOT NULL
|
|
316
|
-
CHECK (relationship IN ('uses','depends_on','implements','extends','related_to','replaces','configures')),
|
|
317
|
-
observation_id TEXT NOT NULL,
|
|
318
|
-
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
319
|
-
UNIQUE(source_entity_id, target_entity_id, relationship),
|
|
320
|
-
FOREIGN KEY (source_entity_id) REFERENCES entities(id) ON DELETE CASCADE,
|
|
321
|
-
FOREIGN KEY (target_entity_id) REFERENCES entities(id) ON DELETE CASCADE,
|
|
322
|
-
FOREIGN KEY (observation_id) REFERENCES observations(id) ON DELETE CASCADE
|
|
323
|
-
);
|
|
324
|
-
|
|
325
|
-
CREATE INDEX IF NOT EXISTS idx_entity_relations_source ON entity_relations(source_entity_id);
|
|
326
|
-
CREATE INDEX IF NOT EXISTS idx_entity_relations_target ON entity_relations(target_entity_id);
|
|
327
|
-
|
|
328
|
-
-- Entity-Observation junction table
|
|
329
|
-
CREATE TABLE IF NOT EXISTS entity_observations (
|
|
330
|
-
entity_id TEXT NOT NULL,
|
|
331
|
-
observation_id TEXT NOT NULL,
|
|
332
|
-
PRIMARY KEY (entity_id, observation_id),
|
|
333
|
-
FOREIGN KEY (entity_id) REFERENCES entities(id) ON DELETE CASCADE,
|
|
334
|
-
FOREIGN KEY (observation_id) REFERENCES observations(id) ON DELETE CASCADE
|
|
335
|
-
);
|
|
336
371
|
|
|
337
372
|
-- FTS5 for entity search
|
|
338
373
|
CREATE VIRTUAL TABLE IF NOT EXISTS entities_fts USING fts5(
|
|
@@ -343,7 +378,6 @@ ${V}`}return W}guide(){return["open-mem workflow:","1) Use mem-search to find ca
|
|
|
343
378
|
tokenize='porter unicode61'
|
|
344
379
|
);
|
|
345
380
|
|
|
346
|
-
-- FTS5 sync triggers
|
|
347
381
|
CREATE TRIGGER entities_ai AFTER INSERT ON entities BEGIN
|
|
348
382
|
INSERT INTO entities_fts(rowid, name, entity_type)
|
|
349
383
|
VALUES (new._rowid, new.name, new.entity_type);
|
|
@@ -360,33 +394,24 @@ ${V}`}return W}guide(){return["open-mem workflow:","1) Use mem-search to find ca
|
|
|
360
394
|
INSERT INTO entities_fts(rowid, name, entity_type)
|
|
361
395
|
VALUES (new._rowid, new.name, new.entity_type);
|
|
362
396
|
END;
|
|
363
|
-
`},{
|
|
364
|
-
ALTER TABLE observations ADD COLUMN scope TEXT NOT NULL DEFAULT 'project'
|
|
365
|
-
CHECK (scope IN ('project','user'));
|
|
366
|
-
ALTER TABLE observations ADD COLUMN revision_of TEXT;
|
|
367
|
-
ALTER TABLE observations ADD COLUMN deleted_at TEXT;
|
|
368
|
-
|
|
369
|
-
CREATE INDEX IF NOT EXISTS idx_observations_scope ON observations(scope);
|
|
370
|
-
CREATE INDEX IF NOT EXISTS idx_observations_revision_of ON observations(revision_of);
|
|
371
|
-
CREATE INDEX IF NOT EXISTS idx_observations_deleted_at ON observations(deleted_at);
|
|
372
|
-
`}];function A$($,J){if($.migrate(I0),J?.hasVectorExtension&&J?.embeddingDimension&&J.embeddingDimension>0)P0($,J.embeddingDimension)}function P0($,J){if($.get("SELECT name FROM sqlite_master WHERE type='table' AND name='observation_embeddings'")){let M=$.get("SELECT value FROM _embedding_meta WHERE key = 'dimension'");if(M&&Number(M.value)!==J){console.warn(`[open-mem] vec0 table exists with dimension ${M.value}, but config specifies ${J}. Drop observation_embeddings to re-create with new dimension.`);return}}else $.exec(`CREATE VIRTUAL TABLE observation_embeddings USING vec0(
|
|
397
|
+
`}];function nE(E,M){if(E.migrate(z0),M?.hasVectorExtension&&M?.embeddingDimension&&M.embeddingDimension>0)W0(E,M.embeddingDimension)}function W0(E,M){if(E.get("SELECT name FROM sqlite_master WHERE type='table' AND name='observation_embeddings'")){let N=E.get("SELECT value FROM _embedding_meta WHERE key = 'dimension'");if(N&&Number(N.value)!==M){console.warn(`[open-mem] vec0 table exists with dimension ${N.value}, but config specifies ${M}. Drop observation_embeddings to re-create with new dimension.`);return}}else E.exec(`CREATE VIRTUAL TABLE observation_embeddings USING vec0(
|
|
373
398
|
observation_id TEXT PRIMARY KEY,
|
|
374
|
-
embedding float[${
|
|
375
|
-
)`)
|
|
376
|
-
VALUES (?, ?, ?, 'active')`,[
|
|
399
|
+
embedding float[${M}] distance_metric=cosine
|
|
400
|
+
)`);E.run("INSERT OR REPLACE INTO _embedding_meta (key, value) VALUES (?, ?)",["dimension",String(M)])}class NE{db;constructor(E){this.db=E}create(E,M){let _=new Date().toISOString();return this.db.run(`INSERT INTO sessions (id, project_path, started_at, status)
|
|
401
|
+
VALUES (?, ?, ?, 'active')`,[E,M,_]),this.getById(E)}getOrCreate(E,M){let _=this.getById(E);if(_)return _;return this.create(E,M)}getById(E){let M=this.db.get("SELECT * FROM sessions WHERE id = ?",[E]);return M?this.mapRow(M):null}getRecent(E,M=10){return this.db.all("SELECT * FROM sessions WHERE project_path = ? ORDER BY started_at DESC LIMIT ?",[E,M]).map((_)=>this.mapRow(_))}getAll(E){return this.db.all("SELECT * FROM sessions WHERE project_path = ? ORDER BY started_at DESC",[E]).map((M)=>this.mapRow(M))}getActive(){return this.db.all("SELECT * FROM sessions WHERE status = 'active' ORDER BY started_at DESC").map((E)=>this.mapRow(E))}updateStatus(E,M){this.db.run("UPDATE sessions SET status = ? WHERE id = ?",[M,E])}markCompleted(E){this.db.run("UPDATE sessions SET status = 'completed', ended_at = datetime('now') WHERE id = ?",[E])}incrementObservationCount(E){this.db.run("UPDATE sessions SET observation_count = observation_count + 1 WHERE id = ?",[E])}setSummary(E,M){this.db.run("UPDATE sessions SET summary_id = ? WHERE id = ?",[M,E])}mapRow(E){return{id:E.id,projectPath:E.project_path,startedAt:E.started_at,endedAt:E.ended_at??null,status:E.status,observationCount:E.observation_count,summaryId:E.summary_id??null}}}import{randomUUID as Y0}from"crypto";class SE{db;constructor(E){this.db=E}create(E){let M=Y0(),_=new Date().toISOString();return this.db.run(`INSERT INTO session_summaries
|
|
377
402
|
(id, session_id, summary, key_decisions, files_modified,
|
|
378
403
|
concepts, created_at, token_count,
|
|
379
404
|
request, investigated, learned, completed, next_steps)
|
|
380
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[
|
|
405
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[M,E.sessionId,E.summary,JSON.stringify(E.keyDecisions),JSON.stringify(E.filesModified),JSON.stringify(E.concepts),_,E.tokenCount,E.request??"",E.investigated??"",E.learned??"",E.completed??"",E.nextSteps??""]),{...E,id:M,createdAt:_}}importSummary(E){this.db.run(`INSERT INTO session_summaries
|
|
381
406
|
(id, session_id, summary, key_decisions, files_modified,
|
|
382
407
|
concepts, created_at, token_count,
|
|
383
408
|
request, investigated, learned, completed, next_steps)
|
|
384
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[
|
|
409
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[E.id,E.sessionId,E.summary,JSON.stringify(E.keyDecisions),JSON.stringify(E.filesModified),JSON.stringify(E.concepts),E.createdAt,E.tokenCount,E.request??"",E.investigated??"",E.learned??"",E.completed??"",E.nextSteps??""])}getBySessionId(E){let M=this.db.get("SELECT * FROM session_summaries WHERE session_id = ?",[E]);return M?this.mapRow(M):null}getRecent(E=10){return this.db.all("SELECT * FROM session_summaries ORDER BY created_at DESC LIMIT ?",[E]).map((M)=>this.mapRow(M))}search(E,M=10){return this.db.all(`SELECT ss.*
|
|
385
410
|
FROM session_summaries ss
|
|
386
411
|
JOIN summaries_fts fts ON ss._rowid = fts.rowid
|
|
387
412
|
WHERE summaries_fts MATCH ?
|
|
388
413
|
ORDER BY rank
|
|
389
|
-
LIMIT ?`,[
|
|
414
|
+
LIMIT ?`,[E,M]).map((_)=>this.mapRow(_))}mapRow(E){return{id:E.id,sessionId:E.session_id,summary:E.summary,keyDecisions:JSON.parse(E.key_decisions),filesModified:JSON.parse(E.files_modified),concepts:JSON.parse(E.concepts),createdAt:E.created_at,tokenCount:E.token_count,request:E.request||void 0,investigated:E.investigated||void 0,learned:E.learned||void 0,completed:E.completed||void 0,nextSteps:E.next_steps||void 0}}}import{randomUUID as B0}from"crypto";var U0=[{version:1,name:"create-user-observations",up:`
|
|
390
415
|
CREATE TABLE IF NOT EXISTS user_observations (
|
|
391
416
|
_rowid INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
392
417
|
id TEXT UNIQUE NOT NULL,
|
|
@@ -457,21 +482,21 @@ ${V}`}return W}guide(){return["open-mem workflow:","1) Use mem-search to find ca
|
|
|
457
482
|
new.facts, new.concepts, new.files_read, new.files_modified
|
|
458
483
|
);
|
|
459
484
|
END;
|
|
460
|
-
`}];class
|
|
485
|
+
`}];class OE{db;constructor(E){let M=F0(E);this.db=q(M),this.initializeUserSchema()}initializeUserSchema(){this.db.migrate(U0)}get database(){return this.db}close(){this.db.close()}}class AE{db;constructor(E){this.db=E}create(E){let M=B0(),_=new Date().toISOString();return this.db.run(`INSERT INTO user_observations
|
|
461
486
|
(id, type, title, subtitle, facts, narrative,
|
|
462
487
|
concepts, files_read, files_modified, tool_name,
|
|
463
488
|
created_at, token_count, importance, source_project)
|
|
464
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[
|
|
489
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[M,E.type,E.title,E.subtitle,JSON.stringify(E.facts),E.narrative,JSON.stringify(E.concepts),JSON.stringify(E.filesRead),JSON.stringify(E.filesModified),E.toolName,_,E.tokenCount,E.importance??3,E.sourceProject]),{...E,id:M,createdAt:_,importance:E.importance??3}}search(E){try{let M=`
|
|
465
490
|
SELECT o.*, rank
|
|
466
491
|
FROM user_observations o
|
|
467
492
|
JOIN user_observations_fts fts ON o._rowid = fts.rowid
|
|
468
493
|
WHERE user_observations_fts MATCH ?
|
|
469
|
-
`,
|
|
470
|
-
FROM user_observations`,
|
|
494
|
+
`,_=[E.query];if(E.sourceProject)M+=" AND o.source_project = ?",_.push(E.sourceProject);return M+=" ORDER BY rank LIMIT ?",_.push(E.limit??10),this.db.all(M,_).map((N)=>({observation:this.mapRow(N),rank:N.rank}))}catch{return[]}}getIndex(E,M){let _=`SELECT id, type, title, token_count, created_at, importance, source_project
|
|
495
|
+
FROM user_observations`,N=[];if(M)_+=" WHERE source_project = ?",N.push(M);return _+=" ORDER BY created_at DESC LIMIT ?",N.push(E??20),this.db.all(_,N).map((S)=>({id:S.id,sessionId:"",type:S.type,title:S.title,tokenCount:S.token_count,discoveryTokens:0,createdAt:S.created_at,importance:S.importance??3}))}getById(E){let M=this.db.get("SELECT * FROM user_observations WHERE id = ?",[E]);return M?this.mapRow(M):null}delete(E){return this.db.all("DELETE FROM user_observations WHERE id = ? RETURNING id",[E]).length>0}mapRow(E){return{id:E.id,type:E.type,title:E.title,subtitle:E.subtitle,facts:JSON.parse(E.facts),narrative:E.narrative,concepts:JSON.parse(E.concepts),filesRead:JSON.parse(E.files_read),filesModified:JSON.parse(E.files_modified),toolName:E.tool_name,createdAt:E.created_at,tokenCount:E.token_count,importance:E.importance??3,sourceProject:E.source_project}}}function F0(E){if(E.startsWith("~/")){let M=process.env.HOME||process.env.USERPROFILE||"";if(!M)throw Error("Cannot resolve user DB path: HOME environment variable is not set");let _=`${M}${E.slice(1)}`,N=_.substring(0,_.lastIndexOf("/"));return Y("fs").mkdirSync(N,{recursive:!0}),_}return E}function D(E,M){if(M.type&&E.type!==M.type)return!1;if(M.importanceMin!==void 0&&E.importance<M.importanceMin)return!1;if(M.importanceMax!==void 0&&E.importance>M.importanceMax)return!1;if(M.createdAfter&&E.createdAt<M.createdAfter)return!1;if(M.createdBefore&&E.createdAt>M.createdBefore)return!1;if(M.concepts&&M.concepts.length>0){if(!M.concepts.some((N)=>E.concepts.some((S)=>S.toLowerCase().includes(N.toLowerCase()))))return!1}if(M.files&&M.files.length>0){let _=[...E.filesRead,...E.filesModified];if(!M.files.some((S)=>_.some((O)=>O.toLowerCase().includes(S.toLowerCase()))))return!1}return!0}async function cE(E,M,_,N,S){if(!E.trim())return M;let O=G0(E),A=new Set;for(let V of O){let $=_.findByName(V);for(let Z of $){let W=_.traverseRelations(Z.id,1);for(let B of W){let F=_.getObservationsForEntity(B);for(let n of F)A.add(n)}}}if(A.size===0)return M;let J=new Set(M.map((V)=>V.observation.id)),C=[];for(let V of A){if(J.has(V))continue;let $=N.getById(V);if(!$)continue;if($.supersededBy)continue;C.push({observation:$,rank:0,snippet:$.title,source:"project",rankingSource:"graph",explain:{strategy:"hybrid",matchedBy:["graph"]}})}return[...M,...C].slice(0,S)}function G0(E){let M=E.split(/\s+/).filter((N)=>N.length>=2),_=[];for(let N of M)_.push(N);for(let N=0;N<M.length-1;N++)_.push(`${M[N]} ${M[N+1]}`);return _}var bE=60;async function iE(E,M,_,N){let S=N.limit??10,O=D0(M,E,N,S);if(!_)return O;let A=await l(_,E);if(!A)return O;let J=O.map((V)=>V.observation.id),C=y0(M,A,N.projectPath,N,S,N.hasVectorExtension??!1,J);if(C.length===0)return O;return k0(O,C,S)}function D0(E,M,_,N){try{return E.search({query:M,type:_.type,limit:N,projectPath:_.projectPath,importanceMin:_.importanceMin,importanceMax:_.importanceMax,createdAfter:_.createdAfter,createdBefore:_.createdBefore,concepts:_.concepts,files:_.files})}catch{return[]}}function y0(E,M,_,N,S,O,A){if(O)return m0(E,M,N,S,A);return j0(E,M,_,N,S)}function m0(E,M,_,N,S){try{let O;if(S.length>0){if(O=E.searchVecSubset(M,S,N*3),O.length===0)O=E.getVecEmbeddingMatches(M,N*3)}else O=E.getVecEmbeddingMatches(M,N*3);if(O.length===0)return[];let A=[];for(let{observationId:J,distance:C}of O){if(A.length>=N)break;let V=E.getById(J);if(!V)continue;if(!D(V,_))continue;A.push({observation:V,rank:C-1,snippet:V.title,rankingSource:"vector",explain:{strategy:"hybrid",matchedBy:["vector"],vectorDistance:C}})}return A}catch{return[]}}function j0(E,M,_,N,S){let O=E.getWithEmbeddings(_,S*10);if(O.length===0)return[];let A=O.map((C)=>({id:C.id,similarity:G(M,C.embedding)})).filter(({similarity:C})=>C>=0.3).sort((C,V)=>V.similarity-C.similarity),J=[];for(let{id:C,similarity:V}of A){if(J.length>=S)break;let $=E.getById(C);if(!$)continue;if(!D($,N))continue;J.push({observation:$,rank:-V,snippet:$.title,rankingSource:"vector",explain:{strategy:"hybrid",matchedBy:["vector"],vectorSimilarity:V}})}return J}function k0(E,M,_){let N=new Map;for(let S=0;S<E.length;S++){let O=E[S],A=1/(bE+S+1);N.set(O.observation.id,{score:A,result:{...O,rankingSource:"fts",explain:{strategy:"hybrid",matchedBy:["fts"],ftsRank:O.rank}}})}for(let S=0;S<M.length;S++){let O=M[S],A=1/(bE+S+1),J=N.get(O.observation.id);if(J)J.score+=A,J.result={...J.result,explain:{strategy:"hybrid",matchedBy:["fts","vector"],ftsRank:J.result.explain?.ftsRank??J.result.rank,vectorDistance:O.explain?.vectorDistance,vectorSimilarity:O.explain?.vectorSimilarity}};else N.set(O.observation.id,{score:A,result:{...O,explain:{strategy:"hybrid",matchedBy:["vector"],vectorDistance:O.explain?.vectorDistance,vectorSimilarity:O.explain?.vectorSimilarity}}})}return[...N.values()].sort((S,O)=>O.score-S.score).slice(0,_).map(({score:S,result:O})=>({...O,explain:{...O.explain??{strategy:"hybrid",matchedBy:[]},strategy:"hybrid",matchedBy:O.explain?.matchedBy??[],rrfScore:S,ftsRank:O.explain?.ftsRank,vectorDistance:O.explain?.vectorDistance,vectorSimilarity:O.explain?.vectorSimilarity}}))}class JE{observations;embeddingModel;hasVectorExtension;reranker;userObservationRepo;entityRepo;constructor(E,M,_,N=null,S=null,O=null){this.observations=E;this.embeddingModel=M;this.hasVectorExtension=_;this.reranker=N;this.userObservationRepo=S;this.entityRepo=O}async search(E,M){let _=M.strategy??"hybrid",N=M.limit??10,S;switch(_){case"filter-only":S=this.filterOnlySearch(E,M,N);break;case"semantic":S=await this.semanticSearch(E,M,N);break;case"hybrid":S=await this.hybridSearchStrategy(E,M,N);break}for(let O of S)O.source="project";if(this.entityRepo&&E.trim())S=await cE(E,S,this.entityRepo,this.observations,N);if(this.userObservationRepo){let O=this.searchUserMemory(E,M,N);S=this.mergeResults(S,O,N)}if(this.reranker&&S.length>1)return this.reranker.rerank(E,S,N);return S}filterOnlySearch(E,M,_){if(M.concept)return this.observations.searchByConcept(M.concept,_,M.projectPath).map((S)=>({observation:S,rank:0,snippet:S.title,rankingSource:"graph",explain:{strategy:"filter-only",matchedBy:["concept-filter"]}}));if(M.file)return this.observations.searchByFile(M.file,_,M.projectPath).map((S)=>({observation:S,rank:0,snippet:S.title,rankingSource:"graph",explain:{strategy:"filter-only",matchedBy:["file-filter"]}}));return this.observations.search({query:E,type:M.type,limit:_,projectPath:M.projectPath,importanceMin:M.importanceMin,importanceMax:M.importanceMax,createdAfter:M.createdAfter,createdBefore:M.createdBefore,concepts:M.concepts,files:M.files})}async semanticSearch(E,M,_){if(!this.embeddingModel)return this.filterOnlySearch(E,M,_);let N=await l(this.embeddingModel,E);if(!N)return this.filterOnlySearch(E,M,_);if(this.hasVectorExtension)return this.nativeVectorSearch(N,M,_);return this.jsFallbackVectorSearch(N,M,_)}async hybridSearchStrategy(E,M,_){return iE(E,this.observations,this.embeddingModel,{type:M.type,limit:_,projectPath:M.projectPath,hasVectorExtension:this.hasVectorExtension,importanceMin:M.importanceMin,importanceMax:M.importanceMax,createdAfter:M.createdAfter,createdBefore:M.createdBefore,concepts:M.concepts,files:M.files})}nativeVectorSearch(E,M,_){try{let N=this.observations.getVecEmbeddingMatches(E,_*3);if(N.length===0)return[];let S=[];for(let{observationId:O,distance:A}of N){if(S.length>=_)break;let J=this.observations.getById(O);if(!J)continue;if(!D(J,M))continue;S.push({observation:J,rank:A-1,snippet:J.title,rankingSource:"vector",explain:{strategy:"semantic",matchedBy:["vector"],vectorDistance:A}})}return S}catch{return[]}}jsFallbackVectorSearch(E,M,_){let N=this.observations.getWithEmbeddings(M.projectPath,_*10);if(N.length===0)return[];let S=N.map((A)=>({id:A.id,similarity:G(E,A.embedding)})).filter(({similarity:A})=>A>=0.3).sort((A,J)=>J.similarity-A.similarity),O=[];for(let{id:A,similarity:J}of S){if(O.length>=_)break;let C=this.observations.getById(A);if(!C)continue;if(!D(C,M))continue;O.push({observation:C,rank:-J,snippet:C.title,rankingSource:"vector",explain:{strategy:"semantic",matchedBy:["vector"],vectorSimilarity:J}})}return O}searchUserMemory(E,M,_){if(!this.userObservationRepo)return[];try{return this.userObservationRepo.search({query:E,limit:_}).map(({observation:S,rank:O})=>({observation:T0(S),rank:O,snippet:S.title,source:"user",rankingSource:"user-memory",explain:{strategy:"filter-only",matchedBy:["user-memory"]}}))}catch{return[]}}mergeResults(E,M,_){let N=new Set(E.map((A)=>A.observation.id)),S=new Set(E.map((A)=>`${A.observation.title}::${A.observation.narrative}`)),O=M.filter((A)=>{if(N.has(A.observation.id))return!1;let J=`${A.observation.title}::${A.observation.narrative}`;if(S.has(J))return!1;return S.add(J),!0});return[...E,...O].slice(0,_)}}function T0(E){return{id:E.id,sessionId:"",type:E.type,title:E.title,subtitle:E.subtitle,facts:E.facts,narrative:E.narrative,concepts:E.concepts,filesRead:E.filesRead,filesModified:E.filesModified,rawToolOutput:"",toolName:E.toolName,createdAt:E.createdAt,tokenCount:E.tokenCount,discoveryTokens:0,importance:E.importance}}import{generateText as P0}from"ai";function rE(E,M){let _=M.map((N,S)=>` <candidate index="${S}"><title>${N.title}</title><narrative>${N.narrative}</narrative></candidate>`).join(`
|
|
471
496
|
`);return`<rerank_request>
|
|
472
|
-
<query>${
|
|
497
|
+
<query>${E}</query>
|
|
473
498
|
<candidates>
|
|
474
|
-
${
|
|
499
|
+
${_}
|
|
475
500
|
</candidates>
|
|
476
501
|
<instructions>Reorder the candidates by relevance to the query. Return indices from most to least relevant.
|
|
477
502
|
|
|
@@ -482,32 +507,4 @@ Respond with EXACTLY this XML format:
|
|
|
482
507
|
<index>0</index>
|
|
483
508
|
</reranked>
|
|
484
509
|
</instructions>
|
|
485
|
-
</rerank_request>`}var
|
|
486
|
-
*Not found*`);continue}let K=[];if(K.push(`## [${U.type.toUpperCase()}] ${U.title}`),U.subtitle)K.push(`*${U.subtitle}*`);if(K.push(`
|
|
487
|
-
${U.narrative}`),U.facts.length>0){K.push(`
|
|
488
|
-
**Facts:**`);for(let W of U.facts)K.push(`- ${W}`)}if(U.concepts.length>0)K.push(`
|
|
489
|
-
**Concepts:** ${U.concepts.join(", ")}`);if(U.filesRead.length>0)K.push(`**Files read:** ${U.filesRead.join(", ")}`);if(U.filesModified.length>0)K.push(`**Files modified:** ${U.filesModified.join(", ")}`);K.push(`
|
|
490
|
-
*ID: ${U.id} | Created: ${U.createdAt} | Tokens: ${U.tokenCount}*`),Z.push(K.join(`
|
|
491
|
-
`))}return{content:[{type:"text",text:`Recalled ${Z.length} observation(s):
|
|
492
|
-
|
|
493
|
-
${Z.join(`
|
|
494
|
-
---
|
|
495
|
-
`)}`}]}}catch(M){return{content:[{type:"text",text:`Recall error: ${M}`}],isError:!0}}}async execTimeline($){let J=typeof $.limit==="number"?Math.max(1,Math.min($.limit,20)):5,S=typeof $.sessionId==="string"?$.sessionId:void 0;try{let M=await this.memoryEngine.timeline({limit:J,sessionId:S});if(S){if(M.length===0)return{content:[{type:"text",text:`Session ${S} not found.`}]};let Z=M[0],X=[`# Session Detail: ${Z.session.id}
|
|
496
|
-
`];if(X.push(`- **Started**: ${Z.session.startedAt}`),X.push(`- **Ended**: ${Z.session.endedAt??"Active"}`),X.push(`- **Status**: ${Z.session.status}`),X.push(`- **Observations**: ${Z.session.observationCount}`),Z.summary){if(X.push(`
|
|
497
|
-
## Summary
|
|
498
|
-
${Z.summary.summary}`),Z.summary.keyDecisions.length>0){X.push(`
|
|
499
|
-
**Key decisions:**`);for(let U of Z.summary.keyDecisions)X.push(`- ${U}`)}}if(Z.observations.length>0){X.push(`
|
|
500
|
-
## Observations`);for(let U of Z.observations)X.push(`
|
|
501
|
-
### [${U.type.toUpperCase()}] ${U.title}`),X.push(U.narrative)}return{content:[{type:"text",text:X.join(`
|
|
502
|
-
`)}]}}if(M.length===0)return{content:[{type:"text",text:"No past sessions found for this project."}]};let Q=[`# Session Timeline (${M.length} sessions)
|
|
503
|
-
`];for(let Z of M){if(Q.push(`## Session: ${Z.session.id}`),Q.push(`- **Started**: ${Z.session.startedAt}`),Q.push(`- **Status**: ${Z.session.status}`),Q.push(`- **Observations**: ${Z.session.observationCount}`),Z.summary){if(Q.push(`- **Summary**: ${Z.summary.summary}`),Z.summary.keyDecisions.length>0)Q.push(`- **Key decisions**: ${Z.summary.keyDecisions.join("; ")}`)}Q.push("")}return{content:[{type:"text",text:Q.join(`
|
|
504
|
-
`)}]}}catch(M){return{content:[{type:"text",text:`Timeline error: ${M}`}],isError:!0}}}async execSave($){let J=typeof $.title==="string"?$.title:void 0,S=i($.type),M=typeof $.narrative==="string"?$.narrative:void 0,Q=k($.concepts),Z=k($.files);if(!J||!S||!M)return{content:[{type:"text",text:"Missing required arguments: title, type, narrative"}],isError:!0};try{let X=`mcp-${new Date().toISOString().slice(0,10)}`,U=await this.memoryEngine.save({title:J,type:S,narrative:M,concepts:Q,files:Z,sessionId:X});if(!U)return{content:[{type:"text",text:"Save error: unable to save observation."}],isError:!0};return{content:[{type:"text",text:`Saved observation: [${S}] "${J}" (ID: ${U.id})`}]}}catch(X){return{content:[{type:"text",text:`Save error: ${X}`}],isError:!0}}}async execExport($){let J=i($.type),S=typeof $.limit==="number"?Math.max(1,$.limit):void 0;try{let M=await this.memoryEngine.export("project",{type:J,limit:S}),Q=M,Z=Q.observations?.length??0,X=Q.summaries?.length??0,U=JSON.stringify(M,null,2);return{content:[{type:"text",text:`Exported ${Z} observation(s) and ${X} summary(ies).
|
|
505
|
-
|
|
506
|
-
${U}`}]}}catch(M){return{content:[{type:"text",text:`Export error: ${M}`}],isError:!0}}}async execImport($){let J=typeof $.data==="string"?$.data:void 0;if(!J)return{content:[{type:"text",text:"Missing required argument: data"}],isError:!0};try{let S=await this.memoryEngine.import(J,{mode:"skip-duplicates"});return{content:[{type:"text",text:`Imported ${S.imported} observation(s). Skipped ${S.skipped} duplicate/invalid observation(s).`}]}}catch(S){return{content:[{type:"text",text:`Import error: ${S}`}],isError:!0}}}async execUpdate($){let J=typeof $.id==="string"?$.id:void 0;if(!J)return{content:[{type:"text",text:"Missing required argument: id"}],isError:!0};try{let S=await this.memoryEngine.update({id:J,title:typeof $.title==="string"?$.title:void 0,narrative:typeof $.narrative==="string"?$.narrative:void 0,type:typeof $.type==="string"&&k$.has($.type)?$.type:void 0,concepts:Array.isArray($.concepts)?k($.concepts):void 0,importance:typeof $.importance==="number"?$.importance:void 0});if(!S)return{content:[{type:"text",text:`Observation "${J}" not found.`}],isError:!0};let M=Object.keys($).filter((Q)=>Q!=="id");return{content:[{type:"text",text:`Updated observation "${S.title}" (new revision ID: ${S.id}, previous ID: ${J}). Changed: ${M.join(", ")||"nothing"}.`}]}}catch(S){return{content:[{type:"text",text:`Update error: ${S}`}],isError:!0}}}async execDelete($){let J=typeof $.id==="string"?$.id:void 0;if(!J)return{content:[{type:"text",text:"Missing required argument: id"}],isError:!0};try{if(await this.memoryEngine.delete([J])===0)return{content:[{type:"text",text:`Observation "${J}" not found.`}],isError:!0};return{content:[{type:"text",text:`Tombstoned observation (ID: ${J})`}]}}catch(S){return{content:[{type:"text",text:`Delete error: ${S}`}],isError:!0}}}sendResponse($){process.stdout.write(`${JSON.stringify($)}
|
|
507
|
-
`)}}function a0($){let J=[`Found ${$.length} observation(s):
|
|
508
|
-
`];for(let{observation:S}of $){if(J.push(`## [${S.type.toUpperCase()}] ${S.title}`),S.subtitle)J.push(`*${S.subtitle}*`);if(J.push(`
|
|
509
|
-
${S.narrative}`),S.facts.length>0){J.push(`
|
|
510
|
-
**Facts:**`);for(let M of S.facts)J.push(`- ${M}`)}if(S.concepts.length>0)J.push(`
|
|
511
|
-
**Concepts:** ${S.concepts.join(", ")}`);if(S.filesModified.length>0)J.push(`**Files modified:** ${S.filesModified.join(", ")}`);if(S.filesRead.length>0)J.push(`**Files read:** ${S.filesRead.join(", ")}`);J.push(`
|
|
512
|
-
*Session: ${S.sessionId} | ${S.createdAt}*`),J.push("---")}return J.join(`
|
|
513
|
-
`)}function T$($){return $}function y$($){return $}function v$($){return $}function I$($){if(!$)return null;return $}import{spawnSync as P$}from"child_process";import{dirname as $2,resolve as q$}from"path";function J2($){try{let J=P$("git",["rev-parse","--git-common-dir"],{cwd:$,encoding:"utf-8",timeout:5000});if(J.status!==0||!J.stdout)return null;let S=J.stdout.trim();if(S===".git")return null;let M=P$("git",["rev-parse","--git-dir"],{cwd:$,encoding:"utf-8",timeout:5000});if(M.status!==0||!M.stdout)return null;let Q=M.stdout.trim(),Z=q$($,S),X=q$($,Q);if(Z===X)return null;let U=$2(Z);if(U===Z||U==="/")return null;return U}catch{return null}}function p$($){return J2($)??$}var __dirname="/Users/clopca/dev/github/open-mem/src",{values:m$}=Q2({options:{project:{type:"string",short:"p"}},strict:!1}),Z2=typeof m$.project==="string"?m$.project:process.cwd(),u$=p$(Z2),Y=s(u$);C.enableExtensionSupport();var z=O(Y.dbPath);A$(z,{hasVectorExtension:z.hasVectorExtension,embeddingDimension:Y.embeddingDimension});var X2=new c(z),w$=new w(z),U2=new g(z),F=null,r=null;if(Y.userMemoryEnabled)try{F=new n(Y.userMemoryDbPath),r=new b(F.database)}catch($){console.error(`[open-mem-mcp] Failed to initialize user-level memory: ${$}`)}var c$=Y.provider!=="bedrock",K2=Y.compressionEnabled&&(!c$||Y.apiKey)?o({provider:Y.provider,model:Y.model,apiKey:Y.apiKey}):null,W2=x$(Y,Y.rerankingEnabled&&(!c$||Y.apiKey)?e({provider:Y.provider,model:Y.model,apiKey:Y.apiKey}):null),V2=new u(z),Y2=new l(w$,K2,z.hasVectorExtension,W2,r,V2),H2=JSON.parse(S2(M2(__dirname,"..","package.json"),"utf-8")),N2=new T({memoryEngine:new p({observations:T$(w$),sessions:y$(X2),summaries:v$(U2),searchOrchestrator:Y2,projectPath:u$,config:Y,userObservationRepo:I$(r)}),version:H2.version}),y=!1,g$=()=>{if(!y){if(y=!0,F)F.close();z.close()}process.exit(0)};process.on("SIGINT",g$);process.on("SIGTERM",g$);process.on("beforeExit",()=>{if(!y){if(y=!0,F)F.close();z.close()}});N2.start();
|
|
510
|
+
</rerank_request>`}var p0={"gemini-2.5-flash-lite":10,"gemini-2.5-flash":10,"gemini-2.5-pro":5,"gemini-2.0-flash":15,"gemini-2.0-flash-lite":30,"gemini-3-flash":5},dE=0;async function oE(E,M){if(!M)return;let _=p0[E]||5,N=Math.ceil(60000/_)+100,O=Date.now()-dE;if(O<N){let A=N-O;await new Promise((J)=>setTimeout(J,A))}dE=Date.now()}class aE{languageModel;maxCandidates;provider;modelName;rateLimitingEnabled;_generate=P0;constructor(E,M){this.languageModel=E,this.maxCandidates=M.rerankingMaxCandidates,this.provider=M.provider??"",this.modelName=M.model??"",this.rateLimitingEnabled=M.rateLimitingEnabled??!0}async rerank(E,M,_){if(M.length<=1)return M;let N=M.slice(0,this.maxCandidates),S=M.slice(this.maxCandidates),O=rE(E,N.map((J)=>({title:J.observation.title,narrative:J.observation.narrative}))),A=2;for(let J=0;J<=A;J++)try{if(this.provider==="google")await oE(this.modelName,this.rateLimitingEnabled);let{text:C}=await this._generate({model:this.languageModel,maxOutputTokens:512,prompt:O}),V=HE(C);if(!V)return M.slice(0,_);let $=this.applyReranking(N,V,_);for(let Z of S){if($.length>=_)break;$.push(Z)}return $}catch(C){if(g0(C)&&J<A){await u0(2**J*1000);continue}return M.slice(0,_)}return M.slice(0,_)}applyReranking(E,M,_){let N=[],S=new Set;for(let O of M)if(O>=0&&O<E.length&&!S.has(O)){if(S.add(O),N.push(E[O]),N.length>=_)break}if(N.length<_){for(let O=0;O<E.length&&N.length<_;O++)if(!S.has(O))N.push(E[O])}return N}}class eE{async rerank(E,M,_){if(M.length<=1)return M.slice(0,_);let N=CE(E),S=M.map((O)=>({result:O,score:this.scoreCandidate(O,N)}));return S.sort((O,A)=>A.score-O.score),S.slice(0,_).map((O)=>O.result)}scoreCandidate(E,M){let _=E.observation,N=CE(_.title),S=CE(_.narrative),O=new Set(_.concepts.map((m)=>m.toLowerCase())),A=0,J=0,C=0;for(let m of M){if(N.has(m))A++;if(S.has(m))J++;if(O.has(m))C++}let V=M.size||1,$=A/V*0.4,Z=J/V*0.3,W=C/V*0.15,F=(Date.now()-new Date(_.createdAt).getTime())/86400000,n=F<1?0.1:F<7?0.05:0,RM=_.importance/5*0.05;return $+Z+W+n+RM}}function tE(E,M){if(!E.rerankingEnabled)return null;if(M)return new aE(M,E);return new eE}function CE(E){return new Set(E.toLowerCase().split(/[\s\-_./\\,;:!?()[\]{}'"]+/).filter((M)=>M.length>1))}function g0(E){if(typeof E!=="object"||E===null)return!1;let M=E,_=M.status;if(_===429||_===500||_===503)return!0;let N=M.error;if(typeof N==="object"&&N!==null&&N.type==="overloaded_error")return!0;return!1}function u0(E){return new Promise((M)=>setTimeout(M,E))}function sE(E){return E}function EM(E){return E}function MM(E){return E}function _M(E){if(!E)return null;return E}import{spawnSync as NM}from"child_process";import{dirname as h0,resolve as SM}from"path";function v0(E){try{let M=NM("git",["rev-parse","--git-common-dir"],{cwd:E,encoding:"utf-8",timeout:5000});if(M.status!==0||!M.stdout)return null;let _=M.stdout.trim();if(_===".git")return null;let N=NM("git",["rev-parse","--git-dir"],{cwd:E,encoding:"utf-8",timeout:5000});if(N.status!==0||!N.stdout)return null;let S=N.stdout.trim(),O=SM(E,_),A=SM(E,S);if(O===A)return null;let J=h0(O);if(J===O||J==="/")return null;return J}catch{return null}}function OM(E){return v0(E)??E}var __dirname="/Users/clopca/dev/github/open-mem/src",{values:AM}=q0({options:{project:{type:"string",short:"p"}},strict:!1}),l0=typeof AM.project==="string"?AM.project:process.cwd(),JM=OM(l0),X=j(JM);I.enableExtensionSupport();var K=q(X.dbPath);nE(K,{hasVectorExtension:K.hasVectorExtension,embeddingDimension:X.embeddingDimension});var w0=new NE(K),CM=new _E(K),n0=new SE(K),c0=new t(K),b0=new ME(K),y=null,VE=null;if(X.userMemoryEnabled)try{y=new OE(X.userMemoryDbPath),VE=new AE(y.database)}catch(E){console.error(`[open-mem-mcp] Failed to initialize user-level memory: ${E}`)}var VM=X.provider!=="bedrock",i0=X.compressionEnabled&&(!VM||X.apiKey)?XE({provider:X.provider,model:X.model,apiKey:X.apiKey}):null,r0=tE(X,X.rerankingEnabled&&(!VM||X.apiKey)?fE({provider:X.provider,model:X.model,apiKey:X.apiKey}):null),d0=new EE(K),o0=new JE(CM,i0,K.hasVectorExtension,r0,VE,d0),a0=JSON.parse(x0(I0(__dirname,"..","package.json"),"utf-8")),e0=new c({memoryEngine:new e({observations:sE(CM),sessions:EM(w0),summaries:MM(n0),searchOrchestrator:o0,projectPath:JM,config:X,userObservationRepo:_M(VE),configAuditStore:c0,maintenanceHistoryStore:b0}),version:a0.version,compatibilityMode:X.mcpCompatibilityMode,protocolVersion:X.mcpProtocolVersion,supportedProtocolVersions:X.mcpSupportedProtocolVersions}),w=!1,$M=()=>{if(!w){if(w=!0,y)y.close();K.close()}process.exit(0)};process.on("SIGINT",$M);process.on("SIGTERM",$M);process.on("beforeExit",()=>{if(!w){if(w=!0,y)y.close();K.close()}});e0.start();
|