open-mem 0.14.0 → 0.14.2
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 +6 -0
- package/README.md +58 -1
- package/dist/claude-code.js +88 -87
- package/dist/cursor.js +88 -87
- package/dist/daemon/manager.d.ts +33 -5
- package/dist/daemon/manager.d.ts.map +1 -1
- package/dist/daemon/pid.d.ts +23 -0
- package/dist/daemon/pid.d.ts.map +1 -1
- package/dist/daemon.js +35 -34
- package/dist/db/advisory-lock.d.ts +40 -0
- package/dist/db/advisory-lock.d.ts.map +1 -0
- package/dist/db/database.d.ts +37 -4
- package/dist/db/database.d.ts.map +1 -1
- package/dist/doctor.js +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +99 -98
- package/dist/maintenance.js +48 -45
- package/dist/mcp.js +72 -71
- package/dist/platform-worker.d.ts.map +1 -1
- package/dist/runtime/queue-runtime.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/maintenance.js
CHANGED
|
@@ -1,78 +1,79 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// @bun
|
|
3
|
-
import{rmSync as m}from"fs";import{parseArgs as WM}from"util";import{existsSync as wV,readFileSync as jV}from"fs";import{join as xV}from"path";import{existsSync as AV,readdirSync as RV,readFileSync as CV}from"fs";import{join as FV}from"path";var k={id:"code",name:"Code",description:"Default coding workflow mode",observationTypes:["decision","bugfix","feature","refactor","discovery","change"],conceptVocabulary:["how-it-works","why-it-exists","what-changed","problem-solution","gotcha","pattern","trade-off"],entityTypes:["technology","library","pattern","concept","file","person","project","other"],relationshipTypes:["uses","depends_on","implements","extends","related_to","replaces","configures"]};function N(V){return{...V,observationTypes:[...V.observationTypes],conceptVocabulary:[...V.conceptVocabulary],entityTypes:[...V.entityTypes],relationshipTypes:[...V.relationshipTypes],promptOverrides:V.promptOverrides?{...V.promptOverrides}:void 0}}function DV(V){if(!V||typeof V!=="object")return!1;let M=V,$=(J)=>Array.isArray(J)&&J.every((Z)=>typeof Z==="string"),W=(J)=>typeof J==="object"&&J!==null&&!Array.isArray(J)&&Object.values(J).every((Z)=>typeof Z==="string");return typeof M.id==="string"&&(M.extends===void 0||typeof M.extends==="string")&&(M.locale===void 0||typeof M.locale==="string")&&(M.name===void 0||typeof M.name==="string")&&(M.description===void 0||typeof M.description==="string")&&(M.observationTypes===void 0||$(M.observationTypes))&&(M.conceptVocabulary===void 0||$(M.conceptVocabulary))&&(M.entityTypes===void 0||$(M.entityTypes))&&(M.relationshipTypes===void 0||$(M.relationshipTypes))&&(M.promptOverrides===void 0||W(M.promptOverrides))}function IV(V){return typeof V.name==="string"&&typeof V.description==="string"&&Array.isArray(V.observationTypes)&&Array.isArray(V.conceptVocabulary)&&Array.isArray(V.entityTypes)&&Array.isArray(V.relationshipTypes)}function d(V,M){return{...V,...M,id:M.id,name:M.name??V.name,description:M.description??V.description,observationTypes:M.observationTypes??V.observationTypes,conceptVocabulary:M.conceptVocabulary??V.conceptVocabulary,entityTypes:M.entityTypes??V.entityTypes,relationshipTypes:M.relationshipTypes??V.relationshipTypes,promptOverrides:{...V.promptOverrides??{},...M.promptOverrides??{}}}}class u{modesDir;constructor(V){this.modesDir=V}loadAllRaw(){let V=new Map;if(!AV(this.modesDir))return V;for(let M of RV(this.modesDir)){if(!M.endsWith(".json"))continue;let $=FV(this.modesDir,M);try{let W=CV($,"utf-8"),J=JSON.parse(W);if(!DV(J))continue;if(V.has(J.id))console.warn(`[open-mem] Duplicate mode id "${J.id}" in ${$}; overriding previous definition.`);V.set(J.id,J)}catch{}}return V}resolveById(V,M){let $=new Set,W=!1,J=(K)=>{if($.has(K))return W=!0,N(k);$.add(K);let X=M.get(K);if(!X)return N(k);if(!X.extends){if(!IV(X))return N(k);return d(N(k),X)}let H=J(X.extends);if(W)return N(k);return d(H,X)},Z=J(V);return W?N(k):N(Z)}}var qV=xV(import.meta.dir,"."),uV=new u(qV),C=null;function gV(){if(C)return C;return C=uV.loadAllRaw(),C}function n(){return[...gV().keys()].sort()}var vV={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,folderContextMode:"dispersed",folderContextFilename:"AGENTS.md",daemonEnabled:!1,dashboardEnabled:!1,dashboardPort:3737,platformOpenCodeEnabled:!0,platformClaudeCodeEnabled:!1,platformCursorEnabled:!1,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,fallbackProviders:void 0,mode:"code"};function pV(){let V={};if(process.env.OPEN_MEM_DB_PATH)V.dbPath=process.env.OPEN_MEM_DB_PATH;if(process.env.OPEN_MEM_PROVIDER)V.provider=process.env.OPEN_MEM_PROVIDER;if(process.env.OPEN_MEM_MODEL)V.model=process.env.OPEN_MEM_MODEL;if(process.env.OPEN_MEM_MAX_CONTEXT_TOKENS)V.maxContextTokens=Number.parseInt(process.env.OPEN_MEM_MAX_CONTEXT_TOKENS,10);if(process.env.OPEN_MEM_COMPRESSION==="false")V.compressionEnabled=!1;if(process.env.OPEN_MEM_CONTEXT_INJECTION==="false")V.contextInjectionEnabled=!1;if(process.env.OPEN_MEM_IGNORED_TOOLS)V.ignoredTools=process.env.OPEN_MEM_IGNORED_TOOLS.split(",").map((M)=>M.trim());if(process.env.OPEN_MEM_BATCH_SIZE)V.batchSize=Number.parseInt(process.env.OPEN_MEM_BATCH_SIZE,10);if(process.env.OPEN_MEM_RETENTION_DAYS)V.retentionDays=Number.parseInt(process.env.OPEN_MEM_RETENTION_DAYS,10);if(process.env.OPEN_MEM_LOG_LEVEL)V.logLevel=process.env.OPEN_MEM_LOG_LEVEL;if(process.env.OPEN_MEM_CONTEXT_SHOW_TOKEN_COSTS==="false")V.contextShowTokenCosts=!1;if(process.env.OPEN_MEM_CONTEXT_TYPES)V.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)V.contextFullObservationCount=Number.parseInt(process.env.OPEN_MEM_CONTEXT_FULL_COUNT,10);if(process.env.OPEN_MEM_MAX_OBSERVATIONS)V.maxObservations=Number.parseInt(process.env.OPEN_MEM_MAX_OBSERVATIONS,10);if(process.env.OPEN_MEM_CONTEXT_SHOW_LAST_SUMMARY==="false")V.contextShowLastSummary=!1;if(process.env.OPEN_MEM_RATE_LIMITING==="false")V.rateLimitingEnabled=!1;if(process.env.OPEN_MEM_FOLDER_CONTEXT==="false")V.folderContextEnabled=!1;if(process.env.OPEN_MEM_FOLDER_CONTEXT_MAX_DEPTH)V.folderContextMaxDepth=Number.parseInt(process.env.OPEN_MEM_FOLDER_CONTEXT_MAX_DEPTH,10);if(process.env.OPEN_MEM_FOLDER_CONTEXT_MODE==="single")V.folderContextMode="single";if(process.env.OPEN_MEM_FOLDER_CONTEXT_MODE==="dispersed")V.folderContextMode="dispersed";if(process.env.OPEN_MEM_FOLDER_CONTEXT_FILENAME)V.folderContextFilename=process.env.OPEN_MEM_FOLDER_CONTEXT_FILENAME;if(process.env.OPEN_MEM_DAEMON==="true")V.daemonEnabled=!0;if(process.env.OPEN_MEM_DASHBOARD==="true")V.dashboardEnabled=!0;if(process.env.OPEN_MEM_DASHBOARD_PORT)V.dashboardPort=Number.parseInt(process.env.OPEN_MEM_DASHBOARD_PORT,10);if(process.env.OPEN_MEM_PLATFORM_OPENCODE==="false")V.platformOpenCodeEnabled=!1;if(process.env.OPEN_MEM_PLATFORM_CLAUDE_CODE==="true")V.platformClaudeCodeEnabled=!0;if(process.env.OPEN_MEM_PLATFORM_CURSOR==="true")V.platformCursorEnabled=!0;if(process.env.OPEN_MEM_MCP_PROTOCOL_VERSION)V.mcpProtocolVersion=process.env.OPEN_MEM_MCP_PROTOCOL_VERSION;if(process.env.OPEN_MEM_MCP_SUPPORTED_PROTOCOLS)V.mcpSupportedProtocolVersions=process.env.OPEN_MEM_MCP_SUPPORTED_PROTOCOLS.split(",").map((M)=>M.trim()).filter(Boolean);if(process.env.OPEN_MEM_EMBEDDING_DIMENSION)V.embeddingDimension=Number.parseInt(process.env.OPEN_MEM_EMBEDDING_DIMENSION,10);if(process.env.OPEN_MEM_CONFLICT_RESOLUTION==="true")V.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))V.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))V.conflictSimilarityBandHigh=M}if(process.env.OPEN_MEM_USER_MEMORY==="true")V.userMemoryEnabled=!0;if(process.env.OPEN_MEM_USER_MEMORY_DB_PATH)V.userMemoryDbPath=process.env.OPEN_MEM_USER_MEMORY_DB_PATH;if(process.env.OPEN_MEM_USER_MEMORY_MAX_TOKENS)V.userMemoryMaxContextTokens=Number.parseInt(process.env.OPEN_MEM_USER_MEMORY_MAX_TOKENS,10);if(process.env.OPEN_MEM_RERANKING==="true")V.rerankingEnabled=!0;if(process.env.OPEN_MEM_RERANKING_MAX_CANDIDATES)V.rerankingMaxCandidates=Number.parseInt(process.env.OPEN_MEM_RERANKING_MAX_CANDIDATES,10);if(process.env.OPEN_MEM_ENTITY_EXTRACTION==="true")V.entityExtractionEnabled=!0;if(process.env.OPEN_MEM_FALLBACK_PROVIDERS)V.fallbackProviders=process.env.OPEN_MEM_FALLBACK_PROVIDERS.split(",").map((M)=>M.trim()).filter(Boolean);if(process.env.OPEN_MEM_MODE)V.mode=process.env.OPEN_MEM_MODE;return V}function fV(V){let M=`${V}/.open-mem/config.json`;if(!wV(M))return{};try{let $=jV(M,"utf-8"),W=JSON.parse($);if(!W||typeof W!=="object"||Array.isArray(W))return{};return W}catch{return{}}}function PV(V){switch(V){case"google":return 768;case"openai":return 1536;case"bedrock":return 1024;case"anthropic":return 0;case"openrouter":return 0;default:return 768}}function g(V,M){let $=fV(V),W=pV(),J={...vV,...$,...W,...M};if(!J.dbPath.startsWith("/"))J.dbPath=`${V}/${J.dbPath}`;if(!process.env.OPEN_MEM_PROVIDER&&!M?.provider){if(process.env.GOOGLE_GENERATIVE_AI_API_KEY||process.env.GEMINI_API_KEY)J.provider="google";else if(process.env.ANTHROPIC_API_KEY)J.provider="anthropic";else if(process.env.AWS_BEARER_TOKEN_BEDROCK||process.env.AWS_ACCESS_KEY_ID||process.env.AWS_PROFILE)J.provider="bedrock";else if(process.env.OPENROUTER_API_KEY)J.provider="openrouter"}if(!J.apiKey)switch(J.provider){case"google":J.apiKey=process.env.GOOGLE_GENERATIVE_AI_API_KEY||process.env.GEMINI_API_KEY;break;case"anthropic":J.apiKey=process.env.ANTHROPIC_API_KEY;break;case"openai":J.apiKey=process.env.OPENAI_API_KEY;break;case"openrouter":J.apiKey=process.env.OPENROUTER_API_KEY;break;case"bedrock":break}if(J.provider==="openrouter"&&J.model==="gemini-2.5-flash-lite")J.model="google/gemini-2.5-flash-lite";if(J.embeddingDimension===void 0)J.embeddingDimension=PV(J.provider);if(J.mode&&!n().includes(J.mode))J.mode="code";return J}import{Database as i}from"bun:sqlite";import{existsSync as w,mkdirSync as bV,unlinkSync as s}from"fs";import*as r from"sqlite-vec";class F{db;dbPath;_hasVectorExtension=!1;static enableExtensionSupport(){let V=["/opt/homebrew/opt/sqlite/lib/libsqlite3.dylib","/usr/local/opt/sqlite/lib/libsqlite3.dylib"];for(let M of V)try{if(w(M))return i.setCustomSQLite(M),!0}catch{return!1}return!1}constructor(V){this.dbPath=V,this.db=this.open(V),this.configure()}open(V){let M=V.lastIndexOf("/");if(M>0){let $=V.substring(0,M);bV($,{recursive:!0})}return new i(V,{create:!0})}configure(){try{this.applyPragmas(),this.loadExtensions()}catch(V){console.warn("[open-mem] Database configure failed, attempting recovery by removing WAL/SHM files:",V.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),V}}}}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{r.load(this.db),this._hasVectorExtension=!0}catch{this._hasVectorExtension=!1}}get hasVectorExtension(){return this._hasVectorExtension}deleteSidecarFiles(){for(let V of["-wal","-shm"]){let M=this.dbPath+V;try{if(w(M))s(M)}catch{}}}deleteDatabaseFiles(){this.deleteSidecarFiles();try{if(w(this.dbPath))s(this.dbPath)}catch{}}ensureMigrationTable(){this.db.exec(`
|
|
3
|
+
import{rmSync as b}from"fs";import{parseArgs as t$}from"util";import{existsSync as V$,readFileSync as $$}from"fs";import{join as oV}from"path";import{existsSync as lV,readdirSync as dV,readFileSync as nV}from"fs";import{join as iV}from"path";var C={id:"code",name:"Code",description:"Default coding workflow mode",observationTypes:["decision","bugfix","feature","refactor","discovery","change"],conceptVocabulary:["how-it-works","why-it-exists","what-changed","problem-solution","gotcha","pattern","trade-off"],entityTypes:["technology","library","pattern","concept","file","person","project","other"],relationshipTypes:["uses","depends_on","implements","extends","related_to","replaces","configures"]};function L(V){return{...V,observationTypes:[...V.observationTypes],conceptVocabulary:[...V.conceptVocabulary],entityTypes:[...V.entityTypes],relationshipTypes:[...V.relationshipTypes],promptOverrides:V.promptOverrides?{...V.promptOverrides}:void 0}}function sV(V){if(!V||typeof V!=="object")return!1;let $=V,J=(X)=>Array.isArray(X)&&X.every((H)=>typeof H==="string"),Z=(X)=>typeof X==="object"&&X!==null&&!Array.isArray(X)&&Object.values(X).every((H)=>typeof H==="string");return typeof $.id==="string"&&($.extends===void 0||typeof $.extends==="string")&&($.locale===void 0||typeof $.locale==="string")&&($.name===void 0||typeof $.name==="string")&&($.description===void 0||typeof $.description==="string")&&($.observationTypes===void 0||J($.observationTypes))&&($.conceptVocabulary===void 0||J($.conceptVocabulary))&&($.entityTypes===void 0||J($.entityTypes))&&($.relationshipTypes===void 0||J($.relationshipTypes))&&($.promptOverrides===void 0||Z($.promptOverrides))}function rV(V){return typeof V.name==="string"&&typeof V.description==="string"&&Array.isArray(V.observationTypes)&&Array.isArray(V.conceptVocabulary)&&Array.isArray(V.entityTypes)&&Array.isArray(V.relationshipTypes)}function VV(V,$){return{...V,...$,id:$.id,name:$.name??V.name,description:$.description??V.description,observationTypes:$.observationTypes??V.observationTypes,conceptVocabulary:$.conceptVocabulary??V.conceptVocabulary,entityTypes:$.entityTypes??V.entityTypes,relationshipTypes:$.relationshipTypes??V.relationshipTypes,promptOverrides:{...V.promptOverrides??{},...$.promptOverrides??{}}}}class m{modesDir;constructor(V){this.modesDir=V}loadAllRaw(){let V=new Map;if(!lV(this.modesDir))return V;for(let $ of dV(this.modesDir)){if(!$.endsWith(".json"))continue;let J=iV(this.modesDir,$);try{let Z=nV(J,"utf-8"),X=JSON.parse(Z);if(!sV(X))continue;if(V.has(X.id))console.warn(`[open-mem] Duplicate mode id "${X.id}" in ${J}; overriding previous definition.`);V.set(X.id,X)}catch{}}return V}resolveById(V,$){let J=new Set,Z=!1,X=(K)=>{if(J.has(K))return Z=!0,L(C);J.add(K);let Y=$.get(K);if(!Y)return L(C);if(!Y.extends){if(!rV(Y))return L(C);return VV(L(C),Y)}let Q=X(Y.extends);if(Z)return L(C);return VV(Q,Y)},H=X(V);return Z?L(C):L(H)}}var tV=oV(import.meta.dir,"."),aV=new m(tV),q=null;function eV(){if(q)return q;return q=aV.loadAllRaw(),q}function $V(){return[...eV().keys()].sort()}var J$={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,folderContextMode:"single",folderContextFilename:"AGENTS.md",daemonEnabled:!1,dashboardEnabled:!1,dashboardPort:3737,platformOpenCodeEnabled:!0,platformClaudeCodeEnabled:!1,platformCursorEnabled:!1,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,fallbackProviders:void 0,mode:"code"};function Z$(){let V={};if(process.env.OPEN_MEM_DB_PATH)V.dbPath=process.env.OPEN_MEM_DB_PATH;if(process.env.OPEN_MEM_PROVIDER)V.provider=process.env.OPEN_MEM_PROVIDER;if(process.env.OPEN_MEM_MODEL)V.model=process.env.OPEN_MEM_MODEL;if(process.env.OPEN_MEM_MAX_CONTEXT_TOKENS)V.maxContextTokens=Number.parseInt(process.env.OPEN_MEM_MAX_CONTEXT_TOKENS,10);if(process.env.OPEN_MEM_COMPRESSION==="false")V.compressionEnabled=!1;if(process.env.OPEN_MEM_CONTEXT_INJECTION==="false")V.contextInjectionEnabled=!1;if(process.env.OPEN_MEM_IGNORED_TOOLS)V.ignoredTools=process.env.OPEN_MEM_IGNORED_TOOLS.split(",").map(($)=>$.trim());if(process.env.OPEN_MEM_BATCH_SIZE)V.batchSize=Number.parseInt(process.env.OPEN_MEM_BATCH_SIZE,10);if(process.env.OPEN_MEM_RETENTION_DAYS)V.retentionDays=Number.parseInt(process.env.OPEN_MEM_RETENTION_DAYS,10);if(process.env.OPEN_MEM_LOG_LEVEL)V.logLevel=process.env.OPEN_MEM_LOG_LEVEL;if(process.env.OPEN_MEM_CONTEXT_SHOW_TOKEN_COSTS==="false")V.contextShowTokenCosts=!1;if(process.env.OPEN_MEM_CONTEXT_TYPES)V.contextObservationTypes=process.env.OPEN_MEM_CONTEXT_TYPES==="all"?"all":process.env.OPEN_MEM_CONTEXT_TYPES.split(",").map(($)=>$.trim());if(process.env.OPEN_MEM_CONTEXT_FULL_COUNT)V.contextFullObservationCount=Number.parseInt(process.env.OPEN_MEM_CONTEXT_FULL_COUNT,10);if(process.env.OPEN_MEM_MAX_OBSERVATIONS)V.maxObservations=Number.parseInt(process.env.OPEN_MEM_MAX_OBSERVATIONS,10);if(process.env.OPEN_MEM_CONTEXT_SHOW_LAST_SUMMARY==="false")V.contextShowLastSummary=!1;if(process.env.OPEN_MEM_RATE_LIMITING==="false")V.rateLimitingEnabled=!1;if(process.env.OPEN_MEM_FOLDER_CONTEXT==="false")V.folderContextEnabled=!1;if(process.env.OPEN_MEM_FOLDER_CONTEXT_MAX_DEPTH)V.folderContextMaxDepth=Number.parseInt(process.env.OPEN_MEM_FOLDER_CONTEXT_MAX_DEPTH,10);if(process.env.OPEN_MEM_FOLDER_CONTEXT_MODE==="single")V.folderContextMode="single";if(process.env.OPEN_MEM_FOLDER_CONTEXT_MODE==="dispersed")V.folderContextMode="dispersed";if(process.env.OPEN_MEM_FOLDER_CONTEXT_FILENAME)V.folderContextFilename=process.env.OPEN_MEM_FOLDER_CONTEXT_FILENAME;if(process.env.OPEN_MEM_DAEMON==="true")V.daemonEnabled=!0;if(process.env.OPEN_MEM_DASHBOARD==="true")V.dashboardEnabled=!0;if(process.env.OPEN_MEM_DASHBOARD_PORT)V.dashboardPort=Number.parseInt(process.env.OPEN_MEM_DASHBOARD_PORT,10);if(process.env.OPEN_MEM_PLATFORM_OPENCODE==="false")V.platformOpenCodeEnabled=!1;if(process.env.OPEN_MEM_PLATFORM_CLAUDE_CODE==="true")V.platformClaudeCodeEnabled=!0;if(process.env.OPEN_MEM_PLATFORM_CURSOR==="true")V.platformCursorEnabled=!0;if(process.env.OPEN_MEM_MCP_PROTOCOL_VERSION)V.mcpProtocolVersion=process.env.OPEN_MEM_MCP_PROTOCOL_VERSION;if(process.env.OPEN_MEM_MCP_SUPPORTED_PROTOCOLS)V.mcpSupportedProtocolVersions=process.env.OPEN_MEM_MCP_SUPPORTED_PROTOCOLS.split(",").map(($)=>$.trim()).filter(Boolean);if(process.env.OPEN_MEM_EMBEDDING_DIMENSION)V.embeddingDimension=Number.parseInt(process.env.OPEN_MEM_EMBEDDING_DIMENSION,10);if(process.env.OPEN_MEM_CONFLICT_RESOLUTION==="true")V.conflictResolutionEnabled=!0;if(process.env.OPEN_MEM_CONFLICT_BAND_LOW){let $=Number.parseFloat(process.env.OPEN_MEM_CONFLICT_BAND_LOW);if(!Number.isNaN($))V.conflictSimilarityBandLow=$}if(process.env.OPEN_MEM_CONFLICT_BAND_HIGH){let $=Number.parseFloat(process.env.OPEN_MEM_CONFLICT_BAND_HIGH);if(!Number.isNaN($))V.conflictSimilarityBandHigh=$}if(process.env.OPEN_MEM_USER_MEMORY==="true")V.userMemoryEnabled=!0;if(process.env.OPEN_MEM_USER_MEMORY_DB_PATH)V.userMemoryDbPath=process.env.OPEN_MEM_USER_MEMORY_DB_PATH;if(process.env.OPEN_MEM_USER_MEMORY_MAX_TOKENS)V.userMemoryMaxContextTokens=Number.parseInt(process.env.OPEN_MEM_USER_MEMORY_MAX_TOKENS,10);if(process.env.OPEN_MEM_RERANKING==="true")V.rerankingEnabled=!0;if(process.env.OPEN_MEM_RERANKING_MAX_CANDIDATES)V.rerankingMaxCandidates=Number.parseInt(process.env.OPEN_MEM_RERANKING_MAX_CANDIDATES,10);if(process.env.OPEN_MEM_ENTITY_EXTRACTION==="true")V.entityExtractionEnabled=!0;if(process.env.OPEN_MEM_FALLBACK_PROVIDERS)V.fallbackProviders=process.env.OPEN_MEM_FALLBACK_PROVIDERS.split(",").map(($)=>$.trim()).filter(Boolean);if(process.env.OPEN_MEM_MODE)V.mode=process.env.OPEN_MEM_MODE;return V}function X$(V){let $=`${V}/.open-mem/config.json`;if(!V$($))return{};try{let J=$$($,"utf-8"),Z=JSON.parse(J);if(!Z||typeof Z!=="object"||Array.isArray(Z))return{};return Z}catch{return{}}}function H$(V){switch(V){case"google":return 768;case"openai":return 1536;case"bedrock":return 1024;case"anthropic":return 0;case"openrouter":return 0;default:return 768}}function w(V,$){let J=X$(V),Z=Z$(),X={...J$,...J,...Z,...$};if(!X.dbPath.startsWith("/"))X.dbPath=`${V}/${X.dbPath}`;if(!process.env.OPEN_MEM_PROVIDER&&!$?.provider){if(process.env.GOOGLE_GENERATIVE_AI_API_KEY||process.env.GEMINI_API_KEY)X.provider="google";else if(process.env.ANTHROPIC_API_KEY)X.provider="anthropic";else if(process.env.AWS_BEARER_TOKEN_BEDROCK||process.env.AWS_ACCESS_KEY_ID||process.env.AWS_PROFILE)X.provider="bedrock";else if(process.env.OPENROUTER_API_KEY)X.provider="openrouter"}if(!X.apiKey)switch(X.provider){case"google":X.apiKey=process.env.GOOGLE_GENERATIVE_AI_API_KEY||process.env.GEMINI_API_KEY;break;case"anthropic":X.apiKey=process.env.ANTHROPIC_API_KEY;break;case"openai":X.apiKey=process.env.OPENAI_API_KEY;break;case"openrouter":X.apiKey=process.env.OPENROUTER_API_KEY;break;case"bedrock":break}if(X.provider==="openrouter"&&X.model==="gemini-2.5-flash-lite")X.model="google/gemini-2.5-flash-lite";if(X.embeddingDimension===void 0)X.embeddingDimension=H$(X.provider);if(X.mode&&!$V().includes(X.mode))X.mode="code";return X}import{existsSync as K$,mkdirSync as BJ,readFileSync as Y$,unlinkSync as U$,writeFileSync as GJ}from"fs";function h(V){if(!K$(V))return null;let $=Y$(V,"utf-8").trim(),J=Number.parseInt($,10);if(Number.isNaN(J))return null;return J}function v(V){try{return process.kill(V,0),!0}catch($){if($ instanceof Error&&"code"in $&&$.code==="EPERM")return!0;return!1}}function c(V,$){let J=h(V);if(J===null)return{state:"missing",pid:null,stalePid:null,stalePidRemoved:!1};if(v(J))return{state:"alive",pid:J,stalePid:null,stalePidRemoved:!1};if(!$)return{state:"dead",pid:null,stalePid:J,stalePidRemoved:!1};let Z=W$(V,J);return{state:"dead",pid:null,stalePid:J,stalePidRemoved:Z}}function W$(V,$){let J=h(V);if(J===null||J!==$)return!1;try{return U$(V),!0}catch{return!1}}function ZV(V){let $=V.lastIndexOf("/");if($>=0)return`${V.substring(0,$)}/worker.pid`;return"worker.pid"}function JV(V,$){let J=V.lastIndexOf("/");return`${J>=0?V.substring(0,J):"."}/platform-worker-${$}.pid`}function XV(V){return[{type:"daemon",pidPath:ZV(V)},{type:"platform-worker-claude",pidPath:JV(V,"claude")},{type:"platform-worker-cursor",pidPath:JV(V,"cursor")}]}function HV(V){let $=XV(V).map(({type:Z,pidPath:X})=>{if(Z==="daemon"){let K=Q$(X,!1);return{processType:Z,state:K.state,running:K.running,pidPath:X,pid:K.pid,stalePid:K.stalePid,stalePidRemoved:K.stalePidRemoved}}let H=c(X,!1);if(H.state==="alive")return{processType:Z,state:"running",running:!0,pidPath:X,pid:H.pid,stalePid:null,stalePidRemoved:!1};if(H.state==="dead")return{processType:Z,state:"dead",running:!1,pidPath:X,pid:null,stalePid:H.stalePid,stalePidRemoved:H.stalePidRemoved};return{processType:Z,state:"missing",running:!1,pidPath:X,pid:null,stalePid:null,stalePidRemoved:!1}}),J=$.filter((Z)=>Z.running);return{blocked:J.length>0,activeProcesses:J,checks:$}}function Q$(V,$){let J=c(V,$);if(J.state==="missing")return{state:"missing",running:!1,pid:null,stalePid:null,stalePidRemoved:!1};if(J.state==="dead")return{state:"dead",running:!1,pid:null,stalePid:J.stalePid,stalePidRemoved:J.stalePidRemoved};return{state:"running",running:!0,pid:J.pid,stalePid:null,stalePidRemoved:!1}}import{Database as GV}from"bun:sqlite";import{existsSync as F$,mkdirSync as R$}from"fs";import*as MV from"sqlite-vec";import{closeSync as z$,fsyncSync as B$,openSync as G$,readFileSync as N$,unlinkSync as YV,writeFileSync as M$}from"fs";import{hostname as UV}from"os";var WV="plugin";class g extends Error{lockPath;role;waitDurationMs;owner;constructor(V){super(`Timed out acquiring advisory write lock after ${V.waitDurationMs}ms (role=${V.role}, lockPath=${V.lockPath})`);this.name="AdvisoryLockTimeoutError",this.lockPath=V.lockPath,this.role=V.role,this.waitDurationMs=V.waitDurationMs,this.owner=V.owner}}var O$=5000,T$=50,F=new Map;function L$(V){if(V<=0)return;Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,V)}function KV(V,$){if(typeof V!=="number"||!Number.isFinite(V)||V<=0)return $;return Math.floor(V)}function QV(V){try{let $=N$(V,"utf8").trim();if(!$)return null;let J=JSON.parse($);if(typeof J!=="object"||J===null||typeof J.pid!=="number"||typeof J.role!=="string"||typeof J.hostname!=="string"||typeof J.acquiredAt!=="string")return null;return{pid:J.pid,role:J.role,hostname:J.hostname,acquiredAt:J.acquiredAt,ownerId:typeof J.ownerId==="string"?J.ownerId:void 0}}catch{return null}}function _$(V,$){if(!V||!$)return!1;return V.pid===$.pid&&V.role===$.role&&V.hostname===$.hostname&&V.acquiredAt===$.acquiredAt&&V.ownerId===$.ownerId}function A$(V,$){if(!$)return!1;if($.hostname!==UV())return!1;if(v($.pid))return!1;let J=QV(V);if(!_$(J,$))return!1;try{return YV(V),!0}catch(Z){if(Z.code==="ENOENT")return!1;throw Z}}function l(V,$){z$($);try{YV(V)}catch(J){if(J.code!=="ENOENT")throw J}}function zV(V){return`${V}.write.lock`}function C$(V,$){let J=$.now??Date.now,Z=KV($.timeoutMs,O$),X=KV($.retryIntervalMs,T$),H=F.get(V);if(H){H.count+=1;let U=!1;return{lockPath:V,role:$.role,waitDurationMs:0,reentrant:!0,release:()=>{if(U)return;U=!0;let W=F.get(V);if(!W)return;if(W.count-=1,W.count===0)F.delete(V),l(V,W.fd)}}}let K={pid:process.pid,role:$.role,hostname:UV(),acquiredAt:new Date(J()).toISOString(),ownerId:$.ownerId},Y=J(),Q=null;for(;;)try{let U=G$(V,"wx");try{M$(U,JSON.stringify(K),"utf8"),B$(U)}catch(z){throw l(V,U),z}F.set(V,{count:1,fd:U});let W=!1;return{lockPath:V,role:$.role,waitDurationMs:J()-Y,reentrant:!1,release:()=>{if(W)return;W=!0;let z=F.get(V);if(!z)return;if(z.count-=1,z.count===0)F.delete(V),l(V,z.fd)}}}catch(U){if(U.code!=="EEXIST")throw U;if(Q=QV(V),A$(V,Q))continue;let z=J()-Y;if(z>=Z)throw new g({lockPath:V,role:$.role,waitDurationMs:z,owner:Q});L$(Math.min(X,Z-z))}}function BV(V,$,J){let Z=C$(V,$);try{return J()}finally{Z.release()}}var D$=new Set(["SQLITE_BUSY","SQLITE_LOCKED","SQLITE_IOERR","SQLITE_IOERR_VNODE","SQLITE_IOERR_READ","SQLITE_IOERR_WRITE","SQLITE_IOERR_SHORT_READ","SQLITE_IOERR_FSYNC","SQLITE_PROTOCOL"]),y$=3,NV=50,E$=new Set(["INSERT","UPDATE","DELETE","REPLACE","CREATE","ALTER","DROP","VACUUM","REINDEX","ANALYZE","ATTACH","DETACH"]),I$=new Set(["WAL_CHECKPOINT","OPTIMIZE","INCREMENTAL_VACUUM","SHRINK_MEMORY"]),S$=/^(?:\s+|--[^\n]*(?:\n|$)|\/\*[\s\S]*?\*\/)+/;function k$(V){let $=V;for(;;){let J=$.replace(S$,"");if(J===$)return $.trimStart();$=J}}function x$(V){let $=[],J=0,Z=!1,X=!1,H=!1,K=!1,Y=!1,Q=!1;for(let W=0;W<V.length;W+=1){let z=V[W],N=V[W+1];if(Y){if(z===`
|
|
4
|
+
`)Y=!1;continue}if(Q){if(z==="*"&&N==="/")Q=!1,W+=1;continue}if(Z){if(z==="'")if(N==="'")W+=1;else Z=!1;continue}if(X){if(z==='"')if(N==='"')W+=1;else X=!1;continue}if(H){if(z==="`")H=!1;continue}if(K){if(z==="]")K=!1;continue}if(z==="-"&&N==="-"){Y=!0,W+=1;continue}if(z==="/"&&N==="*"){Q=!0,W+=1;continue}if(z==="'"){Z=!0;continue}if(z==='"'){X=!0;continue}if(z==="`"){H=!0;continue}if(z==="["){K=!0;continue}if(z===";"){let G=V.slice(J,W).trim();if(G.length>0)$.push(G);J=W+1}}let U=V.slice(J).trim();if(U.length>0)$.push(U);return $}function j$(V){let $=k$(V);if(!$)return!1;let J=$.toUpperCase();if(/\bRETURNING\b/.test(J))return!0;if(J.startsWith("PRAGMA")){if(/^PRAGMA\s+(?:[A-Z0-9_]+\.)?[A-Z0-9_]+\s*=/.test(J))return!0;let X=/^PRAGMA\s+(?:[A-Z0-9_]+\.)?([A-Z0-9_]+)/.exec(J)?.[1];if(!X)return!1;return I$.has(X)}let Z=/^[A-Z]+/.exec(J)?.[0];if(!Z)return!1;if(E$.has(Z))return!0;if(Z==="WITH")return/\b(INSERT|UPDATE|DELETE|REPLACE)\b/.test(J);return!1}function d(V){let $=x$(V);if($.length===0)return!1;for(let J of $)if(j$(J))return!0;return!1}var q$=new Set(["PASSIVE","FULL","RESTART","TRUNCATE"]);function S(V){if(V instanceof Error){let $=V.code;return{code:typeof $==="string"?$:"UNKNOWN",message:V.message}}return{code:"UNKNOWN",message:String(V)}}function w$(V){if(V&&typeof V==="object"&&"code"in V){let $=V.code;return D$.has($)}return!1}class k{db;dbPath;advisoryWriteLockPath;processRole;transactionDepth=0;_hasVectorExtension=!1;static enableExtensionSupport(){let V=["/opt/homebrew/opt/sqlite/lib/libsqlite3.dylib","/usr/local/opt/sqlite/lib/libsqlite3.dylib"];for(let $ of V)try{if(F$($))return GV.setCustomSQLite($),!0}catch{return!1}return!1}constructor(V,$={}){this.dbPath=V,this.processRole=$.processRole??WV,this.advisoryWriteLockPath=zV(V),this.db=this.open(V),this.configure()}open(V){let $=V.lastIndexOf("/");if($>0){let J=V.substring(0,$);R$(J,{recursive:!0})}return new GV(V,{create:!0})}configure(){this.runConfigureStage("applyPragmas",()=>this.applyPragmas()),this.runConfigureStage("loadExtensions",()=>this.loadExtensions())}runConfigureStage(V,$){try{$()}catch(J){this.throwConfigureFailure(V,J)}}throwConfigureFailure(V,$){let J=S($);try{this.db.close()}catch{}throw console.error("[open-mem] Database configure failed (non-destructive fail-safe)",{stage:V,dbPath:this.dbPath,sqliteCode:J.code,sqliteMessage:J.message,action:"startup-abort",deletionAttempted:!1}),Error(`Database startup failed during ${V} (fail-safe, non-destructive): [${J.code}] ${J.message}`)}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{MV.load(this.db),this._hasVectorExtension=!0}catch(V){let $=S(V);console.warn("[open-mem] SQLite extension load skipped",{stage:"loadExtensions",dbPath:this.dbPath,sqliteCode:$.code,sqliteMessage:$.message,action:"continue-without-extension"}),this._hasVectorExtension=!1}}get hasVectorExtension(){return this._hasVectorExtension}ensureMigrationTable(){this.db.exec(`
|
|
4
5
|
CREATE TABLE IF NOT EXISTS _migrations (
|
|
5
6
|
version INTEGER PRIMARY KEY,
|
|
6
7
|
name TEXT NOT NULL,
|
|
7
8
|
applied_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
8
9
|
)
|
|
9
|
-
`)}migrate(V){this.ensureMigrationTable();let
|
|
10
|
+
`)}migrate(V){this.withAdvisoryWriteLock(this.processRole,()=>{this.ensureMigrationTable();let $=this.withRetry("migrate.applied_versions",()=>{return this.db.query("SELECT version FROM _migrations ORDER BY version").all()}),J=new Set($.map((X)=>X.version)),Z=V.filter((X)=>!J.has(X.version)).sort((X,H)=>X.version-H.version);for(let X of Z)this.transaction(()=>{this.exec(X.up),this.run("INSERT INTO _migrations (version, name) VALUES ($version, $name)",[{$version:X.version,$name:X.name}])})})}withRetry(V,$){let J=this.transactionDepth>0?0:y$,Z;for(let X=0;X<=J;X++)try{return $()}catch(H){if(Z=H,!w$(H)||X===J)throw H;let K=NV*2**X+Math.random()*NV;Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,K);let Y=S(H);console.warn("[open-mem] Retrying after transient SQLite error",{attempt:X+1,maxRetries:J,operation:V,role:this.processRole,dbPath:this.dbPath,sqliteCode:Y.code,sqliteMessage:Y.message})}throw Z}run(V,$){this.withAdvisoryWriteLock(this.processRole,()=>{this.withRetry("run",()=>{let J=this.db.query(V);if($)J.run(...$);else J.run()})})}get(V,$){let J=()=>{let Z=this.db.query(V);return $?Z.get(...$):Z.get()};if(d(V))return this.withAdvisoryWriteLock(this.processRole,()=>this.withRetry("get",J));return this.withRetry("get",J)}all(V,$){let J=()=>{let Z=this.db.query(V);return $?Z.all(...$):Z.all()};if(d(V))return this.withAdvisoryWriteLock(this.processRole,()=>this.withRetry("all",J));return this.withRetry("all",J)}exec(V){let $=()=>this.withRetry("exec",()=>this.db.exec(V));if(d(V)){this.withAdvisoryWriteLock(this.processRole,$);return}$()}transaction(V){return this.withAdvisoryWriteLock(this.processRole,()=>{if(this.transactionDepth>0)return V();let $=this.db.transaction(V);if(typeof $.immediate==="function"){this.transactionDepth+=1;try{return $.immediate()}finally{this.transactionDepth-=1}}this.db.exec("BEGIN IMMEDIATE"),this.transactionDepth+=1;try{let J=V();return this.db.exec("COMMIT"),J}catch(J){let Z=J;try{this.db.exec("ROLLBACK")}catch(X){if(Z instanceof Error){let H=Z;if(H.cause===void 0)H.cause=X;else H.suppressed=[...H.suppressed??[],X]}console.warn("[open-mem] Transaction rollback failed after transaction error",{dbPath:this.dbPath,originalError:S(Z),rollbackError:S(X)})}throw Z}finally{this.transactionDepth-=1}})}get writeLockPath(){return this.advisoryWriteLockPath}withAdvisoryWriteLock(V,$,J){try{return BV(this.advisoryWriteLockPath,{...J,role:V},$)}catch(Z){if(Z instanceof g)console.error("[open-mem] Advisory write lock timeout",{role:V,dbPath:this.dbPath,lockPath:Z.lockPath,waitDurationMs:Z.waitDurationMs,owner:Z.owner});throw Z}}checkpointWal(V="PASSIVE"){let $=typeof V==="string"?V.toUpperCase():"";if(!q$.has($))throw Error(`Invalid wal_checkpoint mode: ${String(V)}`);return this.withAdvisoryWriteLock(this.processRole,()=>{return this.withRetry("maintenance.wal_checkpoint",()=>{let J=this.db.query(`PRAGMA wal_checkpoint(${$})`).get();if(!J)throw Error("wal_checkpoint returned no result row");return{mode:$,busy:J.busy??0,logFrames:J.log??0,checkpointedFrames:J.checkpointed??0}})})}integrityCheck(V=1){let $=Number.isFinite(V)?Math.max(1,Math.floor(V)):1;return this.withRetry("maintenance.integrity_check",()=>{let J=this.db.query(`PRAGMA integrity_check(${$})`).all();if(J.length===0)throw Error("integrity_check returned no result rows");let Z=J.map((X)=>Object.values(X).find((H)=>typeof H==="string")).filter((X)=>typeof X==="string").map((X)=>X.trim()).filter((X)=>X.length>0);if(Z.length===0)throw Error("integrity_check returned no diagnostic messages");return{ok:Z.length===1&&Z[0].toLowerCase()==="ok",messages:Z,maxErrors:$}})}close(){this.db.close()}get isOpen(){try{return this.db.query("SELECT 1").get(),!0}catch{return!1}}get raw(){return this.db}}function n(V,$){return new k(V,$)}import{randomUUID as v$}from"crypto";import{embed as kJ}from"ai";function OV(V,$){if(V.length!==$.length||V.length===0)return 0;let J=0,Z=0,X=0;for(let K=0;K<V.length;K++)J+=V[K]*$[K],Z+=V[K]*V[K],X+=$[K]*$[K];let H=Math.sqrt(Z)*Math.sqrt(X);if(H===0)return 0;return J/H}function g$(V){return V.replace(/[%_\\]/g,"\\$&")}class i{db;constructor(V){this.db=V}create(V){let $=v$(),J=new Date().toISOString(),Z=V.discoveryTokens??0,X=V.importance??3,H=V.scope??"project";return this.db.run(`INSERT INTO observations
|
|
10
11
|
(id, session_id, scope, type, title, subtitle, facts, narrative,
|
|
11
12
|
concepts, files_read, files_modified, raw_tool_output,
|
|
12
13
|
tool_name, created_at, token_count, discovery_tokens, importance, revision_of, deleted_at)
|
|
13
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[
|
|
14
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[$,V.sessionId,H,V.type,V.title,V.subtitle,JSON.stringify(V.facts),V.narrative,JSON.stringify(V.concepts),JSON.stringify(V.filesRead),JSON.stringify(V.filesModified),V.rawToolOutput,V.toolName,J,V.tokenCount,Z,X,null,null]),{...V,id:$,scope:H,createdAt:J,discoveryTokens:Z,importance:X,revisionOf:null,deletedAt:null,supersededBy:null,supersededAt:null}}importObservation(V){this.db.run(`INSERT INTO observations
|
|
14
15
|
(id, session_id, scope, type, title, subtitle, facts, narrative,
|
|
15
16
|
concepts, files_read, files_modified, raw_tool_output,
|
|
16
17
|
tool_name, created_at, token_count, discovery_tokens, importance, revision_of, deleted_at)
|
|
17
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[V.id,V.sessionId,V.scope??"project",V.type,V.title,V.subtitle,JSON.stringify(V.facts),V.narrative,JSON.stringify(V.concepts),JSON.stringify(V.filesRead),JSON.stringify(V.filesModified),V.rawToolOutput,V.toolName,V.createdAt,V.tokenCount,V.discoveryTokens??0,V.importance??3,V.revisionOf??null,V.deletedAt??null])}getById(V){let
|
|
18
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[V.id,V.sessionId,V.scope??"project",V.type,V.title,V.subtitle,JSON.stringify(V.facts),V.narrative,JSON.stringify(V.concepts),JSON.stringify(V.filesRead),JSON.stringify(V.filesModified),V.rawToolOutput,V.toolName,V.createdAt,V.tokenCount,V.discoveryTokens??0,V.importance??3,V.revisionOf??null,V.deletedAt??null])}getById(V){let $=this.db.get("SELECT * FROM observations WHERE id = ? AND superseded_by IS NULL AND deleted_at IS NULL",[V]);return $?this.mapRow($):null}getByIdIncludingArchived(V){let $=this.db.get("SELECT * FROM observations WHERE id = ?",[V]);return $?this.mapRow($):null}getBySession(V){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",[V]).map(($)=>this.mapRow($))}getCount(V){if(V)return this.db.get("SELECT COUNT(*) as count FROM observations WHERE session_id = ?",[V])?.count??0;return this.db.get("SELECT COUNT(*) as count FROM observations")?.count??0}getIndex(V,$=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
|
|
18
19
|
FROM observations o
|
|
19
20
|
JOIN sessions s ON o.session_id = s.id
|
|
20
21
|
WHERE s.project_path = ? AND o.superseded_by IS NULL AND o.deleted_at IS NULL
|
|
21
22
|
ORDER BY o.created_at DESC
|
|
22
|
-
LIMIT ?`,[V
|
|
23
|
+
LIMIT ?`,[V,$]).map((J)=>({id:J.id,sessionId:J.session_id,type:J.type,title:J.title,tokenCount:J.token_count,discoveryTokens:J.discovery_tokens??0,createdAt:J.created_at,importance:J.importance??3}))}getAroundTimestamp(V,$,J,Z){let X=$>0?this.db.all(`SELECT o.*
|
|
23
24
|
FROM observations o
|
|
24
25
|
JOIN sessions s ON o.session_id = s.id
|
|
25
26
|
WHERE s.project_path = ? AND o.created_at < ?
|
|
26
27
|
AND o.superseded_by IS NULL AND o.deleted_at IS NULL
|
|
27
28
|
ORDER BY o.created_at DESC
|
|
28
|
-
LIMIT ?`,[
|
|
29
|
+
LIMIT ?`,[Z,V,$]).reverse():[],H=J>0?this.db.all(`SELECT o.*
|
|
29
30
|
FROM observations o
|
|
30
31
|
JOIN sessions s ON o.session_id = s.id
|
|
31
32
|
WHERE s.project_path = ? AND o.created_at > ?
|
|
32
33
|
AND o.superseded_by IS NULL AND o.deleted_at IS NULL
|
|
33
34
|
ORDER BY o.created_at ASC
|
|
34
|
-
LIMIT ?`,[
|
|
35
|
+
LIMIT ?`,[Z,V,J]):[];return[...X,...H].map((K)=>this.mapRow(K))}listByProject(V,$={}){let{limit:J=50,offset:Z=0,type:X,state:H,sessionId:K}=$,Y=`SELECT o.*
|
|
35
36
|
FROM observations o
|
|
36
37
|
JOIN sessions s ON o.session_id = s.id
|
|
37
|
-
WHERE s.project_path = ?`,
|
|
38
|
+
WHERE s.project_path = ?`,Q=[V];if(K)Y+=" AND o.session_id = ?",Q.push(K);if(X)Y+=" AND o.type = ?",Q.push(X);if(H==="current")Y+=" AND o.superseded_by IS NULL AND o.deleted_at IS NULL";else if(H==="superseded")Y+=" AND o.superseded_by IS NOT NULL AND o.deleted_at IS NULL";else if(H==="tombstoned")Y+=" AND o.deleted_at IS NOT NULL";else Y+=" AND o.superseded_by IS NULL AND o.deleted_at IS NULL";return Y+=" ORDER BY o.created_at DESC LIMIT ? OFFSET ?",Q.push(J,Z),this.db.all(Y,Q).map((U)=>this.mapRow(U))}search(V){let $=!!V.projectPath,J=`
|
|
38
39
|
SELECT o.*, rank
|
|
39
40
|
FROM observations o
|
|
40
41
|
JOIN observations_fts fts ON o._rowid = fts.rowid
|
|
41
|
-
${
|
|
42
|
+
${$?"JOIN sessions s ON o.session_id = s.id":""}
|
|
42
43
|
WHERE observations_fts MATCH ? AND o.superseded_by IS NULL AND o.deleted_at IS NULL
|
|
43
|
-
`,
|
|
44
|
-
OR EXISTS (SELECT 1 FROM json_each(o.files_modified) WHERE LOWER(value) LIKE LOWER(?) ESCAPE '\\'))`)
|
|
44
|
+
`,Z=[V.query];if($&&V.projectPath)J+=" AND s.project_path = ?",Z.push(V.projectPath);if(V.sessionId)J+=" AND o.session_id = ?",Z.push(V.sessionId);if(V.type)J+=" AND o.type = ?",Z.push(V.type);if(V.importanceMin!==void 0)J+=" AND o.importance >= ?",Z.push(V.importanceMin);if(V.importanceMax!==void 0)J+=" AND o.importance <= ?",Z.push(V.importanceMax);if(V.createdAfter)J+=" AND o.created_at >= ?",Z.push(V.createdAfter);if(V.createdBefore)J+=" AND o.created_at <= ?",Z.push(V.createdBefore);if(V.concepts&&V.concepts.length>0){let X=V.concepts.map(()=>"EXISTS (SELECT 1 FROM json_each(o.concepts) WHERE LOWER(value) = LOWER(?))");J+=` AND (${X.join(" OR ")})`;for(let H of V.concepts)Z.push(H)}if(V.files&&V.files.length>0){let X=V.files.map(()=>`(EXISTS (SELECT 1 FROM json_each(o.files_read) WHERE LOWER(value) LIKE LOWER(?) ESCAPE '\\')
|
|
45
|
+
OR EXISTS (SELECT 1 FROM json_each(o.files_modified) WHERE LOWER(value) LIKE LOWER(?) ESCAPE '\\'))`);J+=` AND (${X.join(" OR ")})`;for(let H of V.files){let K=`%${g$(H)}%`;Z.push(K,K)}}return J+=" ORDER BY rank LIMIT ? OFFSET ?",Z.push(V.limit??10),Z.push(V.offset??0),this.db.all(J,Z).map((X)=>({observation:this.mapRow(X),rank:X.rank,snippet:X.title}))}searchByConcept(V,$=10,J){let Z=!!J,X=`SELECT o.*
|
|
45
46
|
FROM observations o
|
|
46
47
|
JOIN observations_fts fts ON o._rowid = fts.rowid
|
|
47
|
-
${
|
|
48
|
+
${Z?"JOIN sessions s ON o.session_id = s.id":""}
|
|
48
49
|
WHERE observations_fts MATCH ?
|
|
49
50
|
AND o.superseded_by IS NULL AND o.deleted_at IS NULL
|
|
50
|
-
${
|
|
51
|
+
${Z?"AND s.project_path = ?":""}
|
|
51
52
|
ORDER BY rank
|
|
52
|
-
LIMIT ?`,K=[`concepts:"${V.replace(/"/g,'""')}"`];if(
|
|
53
|
+
LIMIT ?`,K=[`concepts:"${V.replace(/"/g,'""')}"`];if(Z&&J)K.push(J);return K.push($),this.db.all(X,K).map((Y)=>this.mapRow(Y))}searchByFile(V,$=10,J){let Z=!!J,X=`SELECT o.*
|
|
53
54
|
FROM observations o
|
|
54
55
|
JOIN observations_fts fts ON o._rowid = fts.rowid
|
|
55
|
-
${
|
|
56
|
+
${Z?"JOIN sessions s ON o.session_id = s.id":""}
|
|
56
57
|
WHERE observations_fts MATCH ?
|
|
57
58
|
AND o.superseded_by IS NULL AND o.deleted_at IS NULL
|
|
58
|
-
${
|
|
59
|
+
${Z?"AND s.project_path = ?":""}
|
|
59
60
|
ORDER BY rank
|
|
60
|
-
LIMIT ?`,
|
|
61
|
+
LIMIT ?`,H=[`files_read:"${V.replace(/"/g,'""')}" OR files_modified:"${V.replace(/"/g,'""')}"`];if(Z&&J)H.push(J);return H.push($),this.db.all(X,H).map((K)=>this.mapRow(K))}setEmbedding(V,$){this.db.run("UPDATE observations SET embedding = ? WHERE id = ?",[JSON.stringify($),V])}getWithEmbeddings(V,$){return this.db.all(`SELECT o.id, o.embedding, o.title
|
|
61
62
|
FROM observations o
|
|
62
63
|
JOIN sessions s ON o.session_id = s.id
|
|
63
64
|
WHERE s.project_path = ? AND o.embedding IS NOT NULL AND o.superseded_by IS NULL AND o.deleted_at IS NULL
|
|
64
65
|
ORDER BY o.created_at DESC
|
|
65
|
-
LIMIT ?`,[V
|
|
66
|
+
LIMIT ?`,[V,$]).map((J)=>{try{return{id:J.id,embedding:JSON.parse(J.embedding),title:J.title}}catch{return null}}).filter((J)=>J!==null)}findSimilar(V,$,J,Z){let X=this.db.all(`SELECT id, embedding FROM observations
|
|
66
67
|
WHERE embedding IS NOT NULL AND type = ? AND superseded_by IS NULL AND deleted_at IS NULL
|
|
67
68
|
ORDER BY created_at DESC
|
|
68
|
-
LIMIT 200`,[
|
|
69
|
+
LIMIT 200`,[$]),H=[];for(let K of X)try{let Y=JSON.parse(K.embedding);if(!Array.isArray(Y)||Y.length!==V.length)continue;let Q=OV(V,Y);if(Q>=J)H.push({id:K.id,similarity:Q})}catch{}return H.sort((K,Y)=>Y.similarity-K.similarity).slice(0,Z)}insertVecEmbedding(V,$){let J=new Float32Array($);this.db.run("BEGIN");try{this.db.run("DELETE FROM observation_embeddings WHERE observation_id = ?",[V]),this.db.run("INSERT INTO observation_embeddings (observation_id, embedding) VALUES (?, ?)",[V,J]),this.db.run("COMMIT")}catch(Z){throw this.db.run("ROLLBACK"),Z}}migrateExistingEmbeddings(V){let $=this.db.all("SELECT id, embedding FROM observations WHERE embedding IS NOT NULL"),J=0,Z=0;for(let X of $)try{let H=JSON.parse(X.embedding);if(!Array.isArray(H)||H.length!==V){Z++;continue}this.insertVecEmbedding(X.id,H),J++}catch{Z++}return{migrated:J,skipped:Z}}getVecEmbeddingMatches(V,$){try{let J=new Float32Array(V);return this.db.all(`SELECT observation_id, distance
|
|
69
70
|
FROM observation_embeddings
|
|
70
|
-
WHERE embedding MATCH ? AND k = ?`,[
|
|
71
|
+
WHERE embedding MATCH ? AND k = ?`,[J,$]).map((Z)=>({observationId:Z.observation_id,distance:Z.distance}))}catch{return[]}}searchVecSubset(V,$,J){if($.length===0)return[];try{let Z=new Float32Array(V),X=Math.max(J*5,$.length),H=this.db.all(`SELECT observation_id, distance
|
|
71
72
|
FROM observation_embeddings
|
|
72
|
-
WHERE embedding MATCH ? AND k = ?`,[
|
|
73
|
+
WHERE embedding MATCH ? AND k = ?`,[Z,X]),K=new Set($);return H.filter((Y)=>K.has(Y.observation_id)).slice(0,J).map((Y)=>({observationId:Y.observation_id,distance:Y.distance}))}catch{return[]}}update(V,$){let J=this.getById(V);if(!J)return null;if(Object.keys($).length===0)return J;let Z=this.create({sessionId:J.sessionId,scope:J.scope??"project",type:$.type??J.type,title:$.title??J.title,subtitle:$.subtitle??J.subtitle,facts:$.facts??J.facts,narrative:$.narrative??J.narrative,concepts:$.concepts??J.concepts,filesRead:$.filesRead??J.filesRead,filesModified:$.filesModified??J.filesModified,rawToolOutput:J.rawToolOutput,toolName:"mem-revise",tokenCount:J.tokenCount,discoveryTokens:J.discoveryTokens,importance:$.importance??J.importance});return this.db.run("UPDATE observations SET revision_of = ? WHERE id = ?",[V,Z.id]),this.supersede(V,Z.id),this.getById(Z.id)}supersede(V,$){let J=new Date().toISOString();this.db.run("UPDATE observations SET superseded_by = ?, superseded_at = ? WHERE id = ?",[$,J,V])}delete(V){if(this.db.all("SELECT id FROM observations WHERE id = ?",[V]).length===0)return!1;let J=new Date().toISOString();return this.db.run("UPDATE observations SET deleted_at = ? WHERE id = ?",[J,V]),this.deleteEmbeddingsForObservations([V]),!0}getLineage(V){let $=this.getByIdIncludingArchived(V);if(!$)return[];let J=new Set([$.id]),Z=[$];while(Z[0].revisionOf){let X=this.getByIdIncludingArchived(Z[0].revisionOf);if(!X||J.has(X.id))break;Z.unshift(X),J.add(X.id)}while(Z[Z.length-1].supersededBy){let X=Z[Z.length-1].supersededBy;if(!X)break;let H=this.getByIdIncludingArchived(X);if(!H||J.has(H.id))break;Z.push(H),J.add(H.id)}return Z}deleteOlderThan(V){return this.db.all(`DELETE FROM observations
|
|
73
74
|
WHERE (created_at < datetime('now', '-' || ? || ' days') OR deleted_at IS NOT NULL)
|
|
74
75
|
AND session_id NOT IN (SELECT id FROM sessions WHERE status != 'completed')
|
|
75
|
-
RETURNING id`,[V]).length}deleteEmbeddingsForObservations(V){if(V.length===0)return;let
|
|
76
|
+
RETURNING id`,[V]).length}deleteEmbeddingsForObservations(V){if(V.length===0)return;let $=V.map(()=>"?").join(",");try{this.db.run(`DELETE FROM observation_embeddings WHERE observation_id IN (${$})`,V)}catch{}this.db.run(`UPDATE observations SET embedding = NULL WHERE id IN (${$})`,V)}mapRow(V){return{id:V.id,sessionId:V.session_id,scope:V.scope??"project",type:V.type,title:V.title,subtitle:V.subtitle,facts:JSON.parse(V.facts),narrative:V.narrative,concepts:JSON.parse(V.concepts),filesRead:JSON.parse(V.files_read),filesModified:JSON.parse(V.files_modified),rawToolOutput:V.raw_tool_output,toolName:V.tool_name,createdAt:V.created_at,tokenCount:V.token_count,discoveryTokens:V.discovery_tokens??0,importance:V.importance??3,revisionOf:V.revision_of??null,deletedAt:V.deleted_at??null,supersededBy:V.superseded_by??null,supersededAt:V.superseded_at??null}}}var f$=[{version:1,name:"create-schema",up:`
|
|
76
77
|
-- Sessions table
|
|
77
78
|
CREATE TABLE IF NOT EXISTS sessions (
|
|
78
79
|
_rowid INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
@@ -366,31 +367,33 @@ import{rmSync as m}from"fs";import{parseArgs as WM}from"util";import{existsSync
|
|
|
366
367
|
INSERT INTO entities_fts(rowid, name, entity_type)
|
|
367
368
|
VALUES (new._rowid, new.name, new.entity_type);
|
|
368
369
|
END;
|
|
369
|
-
`}];function
|
|
370
|
+
`}];function TV(V,$){if(V.migrate(f$),$?.hasVectorExtension&&$?.embeddingDimension&&$.embeddingDimension>0)u$(V,$.embeddingDimension)}function u$(V,$){if(V.get("SELECT name FROM sqlite_master WHERE type='table' AND name='observation_embeddings'")){let Z=V.get("SELECT value FROM _embedding_meta WHERE key = 'dimension'");if(Z&&Number(Z.value)!==$){console.warn(`[open-mem] vec0 table exists with dimension ${Z.value}, but config specifies ${$}. Drop observation_embeddings to re-create with new dimension.`);return}}else V.exec(`CREATE VIRTUAL TABLE observation_embeddings USING vec0(
|
|
370
371
|
observation_id TEXT PRIMARY KEY,
|
|
371
|
-
embedding float[${
|
|
372
|
-
)`);V.run("INSERT OR REPLACE INTO _embedding_meta (key, value) VALUES (?, ?)",["dimension",String(
|
|
373
|
-
VALUES (?, ?, ?, 'active')`,[V
|
|
374
|
-
`);await
|
|
375
|
-
`)}async function
|
|
376
|
-
${
|
|
377
|
-
${
|
|
378
|
-
`;let
|
|
379
|
-
${
|
|
380
|
-
${
|
|
372
|
+
embedding float[${$}] distance_metric=cosine
|
|
373
|
+
)`);V.run("INSERT OR REPLACE INTO _embedding_meta (key, value) VALUES (?, ?)",["dimension",String($)])}class s{db;constructor(V){this.db=V}create(V,$){let J=new Date().toISOString();return this.db.run(`INSERT INTO sessions (id, project_path, started_at, status)
|
|
374
|
+
VALUES (?, ?, ?, 'active')`,[V,$,J]),this.getById(V)}getOrCreate(V,$){let J=this.getById(V);if(J)return J;return this.create(V,$)}getById(V){let $=this.db.get("SELECT * FROM sessions WHERE id = ?",[V]);return $?this.mapRow($):null}getRecent(V,$=10){return this.db.all("SELECT * FROM sessions WHERE project_path = ? ORDER BY started_at DESC LIMIT ?",[V,$]).map((J)=>this.mapRow(J))}getAll(V){return this.db.all("SELECT * FROM sessions WHERE project_path = ? ORDER BY started_at DESC",[V]).map(($)=>this.mapRow($))}getActive(){return this.db.all("SELECT * FROM sessions WHERE status = 'active' ORDER BY started_at DESC").map((V)=>this.mapRow(V))}updateStatus(V,$){this.db.run("UPDATE sessions SET status = ? WHERE id = ?",[$,V])}markCompleted(V){this.db.run("UPDATE sessions SET status = 'completed', ended_at = datetime('now') WHERE id = ?",[V])}incrementObservationCount(V){this.db.run("UPDATE sessions SET observation_count = observation_count + 1 WHERE id = ?",[V])}setSummary(V,$){this.db.run("UPDATE sessions SET summary_id = ? WHERE id = ?",[$,V])}mapRow(V){return{id:V.id,projectPath:V.project_path,startedAt:V.started_at,endedAt:V.ended_at??null,status:V.status,observationCount:V.observation_count,summaryId:V.summary_id??null}}}import{existsSync as kV}from"fs";import{readdir as s$,readFile as yV,unlink as EV,writeFile as IV}from"fs/promises";import{join as xV,resolve as jV}from"path";import{existsSync as _V}from"fs";import{mkdir as b$,readFile as P$,rename as p$,unlink as m$,writeFile as h$}from"fs/promises";import{dirname as f,isAbsolute as t,join as x,normalize as c$,relative as a,resolve as D,sep as r}from"path";var R="<!-- open-mem-context -->",_="<!-- /open-mem-context -->",AV={bugfix:"\uD83D\uDD34",feature:"\uD83D\uDFE3",refactor:"\uD83D\uDD04",change:"\u2705",discovery:"\uD83D\uDD35",decision:"\u2696\uFE0F"},LV=new Map,l$=new Set(["node_modules",".git","dist","coverage",".open-mem","build","__pycache__",".next",".nuxt"]);async function CV(V,$,J){if($.length===0)return;if(J.mode==="single")return d$(V,$,J);let{maxDepth:Z,filename:X}=J,H=[];for(let Q of $){for(let U of Q.filesModified)H.push(U);for(let U of Q.filesRead)H.push(U)}let K=RV(H,V,Z);if(K.size===0)return;let Y=DV($,K,V);for(let[Q,U]of Y)try{let W=n$(Q,U,V);await FV(Q,W,X)}catch(W){console.error(`[open-mem] Failed to update AGENTS.md in ${Q}:`,W)}}async function d$(V,$,J){let{maxDepth:Z,filename:X}=J,H=$.filter(o);if(H.length===0)return;let K=[];for(let G of H){for(let M of G.filesModified)K.push(M);for(let M of G.filesRead)K.push(M)}let Y=RV(K,V,Z),Q=DV(H,Y,V),U=H.filter((G)=>{return[...G.filesModified,...G.filesRead].some((O)=>{if(!O)return!1;let E=t(O)?O:x(V,O);return D(f(E))===D(V)})});if(U.length>0)Q.set(D(V),U);if(Q.size===0)return;let W=[];W.push("## Project Activity (auto-generated by open-mem)"),W.push("");let z=[...Q.entries()].map(([G,M])=>({relPath:a(V,G)||".",observations:M})).sort((G,M)=>G.relPath.localeCompare(M.relPath));for(let{relPath:G,observations:M}of z){let O=M.filter(o).sort((B,I)=>I.createdAt.localeCompare(B.createdAt)).slice(0,10);if(O.length===0)continue;W.push(`### ${G}/`),W.push("| ID | Type | Title | Date |"),W.push("|----|------|-------|------|");for(let B of O){let I=AV[B.type]||"\uD83D\uDCDD",hV=B.createdAt.split("T")[0],cV=B.title.replace(/\|/g,"\\|");W.push(`| ${B.id} | ${I} ${B.type} | ${cV} | ${hV} |`)}let E=new Set;for(let B of O)for(let I of B.concepts)E.add(I);if(E.size>0){let B=[...E].slice(0,10).join(", ");W.push(""),W.push(`**Key concepts:** ${B}`)}let p=O.filter((B)=>B.type==="decision").map((B)=>B.title);if(p.length>0)W.push(""),W.push(`**Recent decisions:** ${p.slice(0,5).join("; ")}`);W.push("")}W.push("\uD83D\uDCA1 *Use `mem-find` to search full details. Use `mem-create` to save important decisions.*");let N=W.join(`
|
|
375
|
+
`);await FV(V,N,X)}function o(V){return!/^\w[\w-]*\s+execution$/i.test(V.title)}function n$(V,$,J){let Z=[...$].filter(o).sort((U,W)=>W.createdAt.localeCompare(U.createdAt)).slice(0,10),X=a(J,V)||".",H=[];H.push(`## Recent Activity in \`${X}/\` (auto-generated by open-mem)`),H.push(""),H.push("| ID | Type | Title | Date |"),H.push("|----|------|-------|------|");for(let U of Z){let W=AV[U.type]||"\uD83D\uDCDD",z=U.createdAt.split("T")[0],N=U.title.replace(/\|/g,"\\|");H.push(`| ${U.id} | ${W} ${U.type} | ${N} | ${z} |`)}let K=new Set;for(let U of Z)for(let W of U.concepts)K.add(W);if(K.size>0){let U=[...K].slice(0,10).join(", ");H.push(""),H.push(`**Key concepts:** ${U}`)}let Y=Z.filter((U)=>U.type==="decision").map((U)=>U.title);if(Y.length>0)H.push(""),H.push(`**Recent decisions:** ${Y.slice(0,5).join("; ")}`);let Q=Z.filter((U)=>U.type==="decision"&&U.narrative).slice(0,3);if(Q.length>0){H.push(""),H.push("**Decision details:**");for(let U of Q){let W=U.narrative.split(/[.!?]\s/)[0],z=W.length>120?`${W.slice(0,117)}...`:W;H.push(`- \u2696\uFE0F ${U.title}: ${z}`)}}return H.push(""),H.push("\uD83D\uDCA1 *Use `mem-find` to search full details across all sessions. Use `mem-create` to save important decisions.*"),H.join(`
|
|
376
|
+
`)}async function FV(V,$,J){if(!_V(V))return;let X=(LV.get(V)??Promise.resolve()).then(async()=>{let H=x(V,J),K=x(V,`.${J}.tmp`),Y="";try{Y=await P$(H,"utf-8")}catch{}let Q=i$(Y,$);try{await b$(f(K),{recursive:!0}),await h$(K,Q,"utf-8"),await p$(K,H)}catch(U){try{await m$(K)}catch{}throw U}});return LV.set(V,X.catch(()=>{})),X}function i$(V,$){if(!V)return`${R}
|
|
377
|
+
${$}
|
|
378
|
+
${_}
|
|
379
|
+
`;let J=V.indexOf(R),Z=V.indexOf(_);if(J!==-1&&Z!==-1&&Z>J){let H=V.substring(0,J),K=V.substring(Z+_.length);return`${H}${R}
|
|
380
|
+
${$}
|
|
381
|
+
${_}${K}`}let X=V;if(J!==-1&&Z===-1)X=X.replace(R,"").trim();else if(J===-1&&Z!==-1)X=X.replace(_,"").trim();else if(J!==-1&&Z!==-1&&Z<=J)X=X.replace(_,"").replace(R,"").trim();return`${X}
|
|
381
382
|
|
|
383
|
+
${R}
|
|
384
|
+
${$}
|
|
382
385
|
${_}
|
|
383
|
-
${
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
`:""}
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
`;if(!J)return`${W}
|
|
390
|
-
`;return`${W}
|
|
386
|
+
`}function RV(V,$,J){let Z=new Set,X=D($);for(let H of V){if(!H||!H.trim())continue;if(H.startsWith("~")||H.startsWith("http"))continue;let K=t(H)?H:x($,H),Y=f(K),Q=D(Y);if(!Q.startsWith(X+r)&&Q!==X)continue;if(Q===X)continue;let U=a(X,Q);if(U.split(r).length>J)continue;if(c$(U).split(r).some((N)=>l$.has(N)))continue;if(!_V(Q))continue;Z.add(Q)}return Z}function DV(V,$,J){let Z=new Map;for(let X of V){let H=[...X.filesModified,...X.filesRead],K=new Set;for(let Y of H){if(!Y)continue;let Q=t(Y)?Y:x(J,Y),U=D(f(Q));if($.has(U))K.add(U)}for(let Y of K){let Q=Z.get(Y)??[];Q.push(X),Z.set(Y,Q)}}return Z}var e="<!-- open-mem-context -->",u="<!-- /open-mem-context -->";async function qV(V,$,J){let Z;try{Z=await s$(V,{withFileTypes:!0,encoding:"utf8"})}catch{return}for(let X of Z){let H=String(X.name);if(H===".git"||H==="node_modules"||H===".open-mem"||H==="dist")continue;let K=xV(V,H);if(X.isDirectory())await qV(K,$,J);else if(X.isFile()&&H===$)J.push(K)}}async function wV(V,$){let J=jV(V),Z=[];return await qV(J,$,Z),Z}function SV(V){let $=V.indexOf(e),J=V.indexOf(u);if($===-1&&J===-1)return V;if($!==-1&&J===-1){let H=V.replace(e,"").trim();return H?`${H}
|
|
387
|
+
`:""}if($===-1&&J!==-1){let H=V.replace(u,"").trim();return H?`${H}
|
|
388
|
+
`:""}if(J<=$){let H=V.replace(e,"").replace(u,"").trim();return H?`${H}
|
|
389
|
+
`:""}let Z=V.slice(0,$).trimEnd(),X=V.slice(J+u.length).trimStart();if(!Z&&!X)return"";if(!Z)return`${X}
|
|
390
|
+
`;if(!X)return`${Z}
|
|
391
|
+
`;return`${Z}
|
|
391
392
|
|
|
392
|
-
${
|
|
393
|
-
`}async function
|
|
394
|
-
open-mem-maintenance reset-db --project <path>
|
|
393
|
+
${X}
|
|
394
|
+
`}async function vV(V,$,J=!1){let Z=await wV(V,$),X=0;for(let H of Z){let K=await yV(H,"utf-8"),Y=SV(K);if(Y!==K){if(X+=1,!J)if(Y==="")await EV(H);else await IV(H,Y,"utf-8")}}if($){let H=xV(jV(V),$);if(kV(H))try{let K=await yV(H,"utf-8"),Y=SV(K);if(Y!==K){if(X+=1,!J)if(Y==="")await EV(H);else await IV(H,Y,"utf-8")}if(!Z.includes(H))Z.push(H)}catch{}}return{files:Z,changed:X}}async function gV(V,$,J,Z,X=!1){let K=$.getAll(V).flatMap((Q)=>J.getBySession(Q.id));if(X){let Q=new Set;for(let U of K)for(let W of[...U.filesRead,...U.filesModified])Q.add(W);return{observations:K.length,filesTouched:Q.size}}if(!kV(V))return{observations:0,filesTouched:0};await CV(V,K,{maxDepth:Z.maxDepth,mode:Z.mode,filename:Z.filename});let Y=await wV(V,Z.filename);return{observations:K.length,filesTouched:Y.length}}import{spawnSync as fV}from"child_process";import{dirname as r$,resolve as uV}from"path";function o$(V){try{let $=fV("git",["rev-parse","--git-common-dir"],{cwd:V,encoding:"utf-8",timeout:5000});if($.status!==0||!$.stdout)return null;let J=$.stdout.trim();if(J===".git")return null;let Z=fV("git",["rev-parse","--git-dir"],{cwd:V,encoding:"utf-8",timeout:5000});if(Z.status!==0||!Z.stdout)return null;let X=Z.stdout.trim(),H=uV(V,J),K=uV(V,X);if(H===K)return null;let Y=r$(H);if(Y===H||Y==="/")return null;return Y}catch{return null}}function bV(V){return o$(V)??V}var{positionals:mV,values:T}=t$({args:Bun.argv.slice(2),options:{project:{type:"string",short:"p"},"dry-run":{type:"boolean",default:!1},force:{type:"boolean",default:!1},mode:{type:"string"},"max-errors":{type:"string"}},allowPositionals:!0,strict:!1}),y=mV[0]??"help",A=mV[1]??"",a$=typeof T.project==="string"?T.project:process.cwd(),j=bV(a$),e$=new Set(["PASSIVE","FULL","RESTART","TRUNCATE"]);function PV(){console.log(`Usage:
|
|
395
|
+
open-mem-maintenance reset-db --project <path> [--force]
|
|
396
|
+
open-mem-maintenance sqlite checkpoint --project <path> [--mode <PASSIVE|FULL|RESTART|TRUNCATE>]
|
|
397
|
+
open-mem-maintenance sqlite integrity --project <path> [--max-errors <n>]
|
|
395
398
|
open-mem-maintenance folder-context clean --project <path> [--dry-run]
|
|
396
|
-
open-mem-maintenance folder-context rebuild --project <path> [--dry-run]`)}async function
|
|
399
|
+
open-mem-maintenance folder-context rebuild --project <path> [--dry-run]`)}function pV(V){console.log(JSON.stringify(V,null,2))}function P(V){console.error(JSON.stringify(V,null,2)),process.exitCode=1}async function VJ(){if(y==="help"||y==="--help"||y==="-h"){PV();return}if(y==="reset-db"){let V=w(j),$=T.force===!0,J=HV(V.dbPath),Z=J.activeProcesses.map((X)=>{let H=X.pid!==null?` pid=${X.pid}`:"";return`${X.processType}${H}`});if(J.blocked&&!$){console.error("[open-mem] reset-db blocked: active processes detected."),console.error(`[open-mem] Detected process types: ${Z.join(", ")}`),console.error("[open-mem] Remediation:"),console.error(" 1) Stop daemon and platform workers for this project."),console.error(" 2) Retry reset-db after processes exit."),console.error(" 3) To override (destructive), rerun with --force."),process.exitCode=1;return}if(J.blocked&&$)console.warn("[open-mem] WARNING: --force set, continuing with destructive reset."),console.warn(`[open-mem] Active process types: ${Z.join(", ")}`);b(V.dbPath,{force:!0}),b(`${V.dbPath}-wal`,{force:!0}),b(`${V.dbPath}-shm`,{force:!0}),b(`${V.dbPath}.write.lock`,{force:!0}),console.log(`Removed database files for ${V.dbPath} (${V.dbPath}, ${V.dbPath}-wal, ${V.dbPath}-shm, ${V.dbPath}.write.lock)`);return}if(y==="sqlite"&&(A==="checkpoint"||A==="integrity")){let V=null,$=null;try{if($=w(j),k.enableExtensionSupport(),V=n($.dbPath,{processRole:"maintenance"}),A==="checkpoint"){let H=typeof T.mode==="string"?T.mode.toUpperCase():"PASSIVE";if(!e$.has(H)){P({operation:"wal_checkpoint",status:"failed",reason:`Invalid checkpoint mode: ${H}`,nextSteps:["Use one of: PASSIVE, FULL, RESTART, TRUNCATE"]});return}let K=V.checkpointWal(H);pV({operation:"wal_checkpoint",status:"ok",dbPath:$.dbPath,mode:K.mode,busy:K.busy,logFrames:K.logFrames,checkpointedFrames:K.checkpointedFrames,nextSteps:K.busy>0?["Some frames remain busy; retry during lower write activity or use --mode FULL."]:["Checkpoint completed without busy frames."]});return}let J=typeof T["max-errors"]==="string"?T["max-errors"]:"1",Z=Number.parseInt(J,10);if(!Number.isInteger(Z)||Z<1){P({operation:"integrity_check",status:"failed",reason:`Invalid --max-errors value: ${J}`,nextSteps:["Use a positive integer, for example --max-errors 10"]});return}let X=V.integrityCheck(Z);if(!X.ok){P({operation:"integrity_check",status:"failed",dbPath:$.dbPath,maxErrors:X.maxErrors,reason:"Integrity check returned SQLite issues.",details:X.messages,nextSteps:["Inspect reported pages/indices.","Restore from a known good backup if corruption is confirmed."]});return}pV({operation:"integrity_check",status:"ok",dbPath:$.dbPath,maxErrors:X.maxErrors,details:X.messages,nextSteps:["No integrity problems reported."]});return}catch(J){P({operation:A==="checkpoint"?"wal_checkpoint":"integrity_check",status:"failed",reason:J instanceof Error?J.message:String(J),nextSteps:["Ensure no external process is holding an exclusive lock.","Retry the maintenance command."]});return}finally{V?.close()}}if(y==="folder-context"&&(A==="clean"||A==="rebuild")){let V=T["dry-run"]===!0,$=w(j);if(A==="clean"){let Z=await vV(j,$.folderContextFilename,V);console.log(`${V?"[dry-run] ":""}Scanned ${Z.files.length} AGENTS.md files, changed ${Z.changed}.`);return}k.enableExtensionSupport();let J=n($.dbPath,{processRole:"maintenance"});try{TV(J,{hasVectorExtension:J.hasVectorExtension,embeddingDimension:$.embeddingDimension});let Z=new s(J),X=new i(J),H=await gV(j,Z,X,{maxDepth:$.folderContextMaxDepth,mode:$.folderContextMode,filename:$.folderContextFilename},V);console.log(`${V?"[dry-run] ":""}Rebuilt context from ${H.observations} observations, touched ${H.filesTouched} files.`);return}finally{J.close()}}PV(),process.exitCode=1}VJ();
|