mneme-ai 2.19.69-lite → 2.19.70-lite
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/bin/mneme.js +106 -0
- package/package.json +5 -5
package/bin/mneme.js
CHANGED
|
@@ -78,6 +78,112 @@ const __mnemePhoenixBootstrap = async () => {
|
|
|
78
78
|
// load already sees the redirected env var.
|
|
79
79
|
await __mnemePhoenixBootstrap();
|
|
80
80
|
|
|
81
|
+
// ── v2.19.70 MUSCLE MEMORY 2.0 — WARM CALL fast path ────────────────────
|
|
82
|
+
// If the daemon is alive AND the user's command is on the WARM CALL
|
|
83
|
+
// allowlist, talk to the daemon over a UDS / named pipe and let IT run
|
|
84
|
+
// the command in its already-warm V8 heap. Empirically 13-40× faster
|
|
85
|
+
// than the cold path because we skip loading dist/index.js + 50+
|
|
86
|
+
// command modules + the commander tree.
|
|
87
|
+
//
|
|
88
|
+
// Idempotent + fail-safe: short connect timeout (75ms) means the
|
|
89
|
+
// fallback to the cold path is almost free if the daemon is dead.
|
|
90
|
+
//
|
|
91
|
+
// Set MNEME_WARMCALL=0 to disable + force the cold path (debugging).
|
|
92
|
+
async function __mnemeWarmCallAttempt() {
|
|
93
|
+
if (process.env.MNEME_WARMCALL === "0") return false;
|
|
94
|
+
const argv = process.argv.slice(2);
|
|
95
|
+
if (argv.length === 0) return false;
|
|
96
|
+
const head = argv[0];
|
|
97
|
+
// Inline allowlist — must match WARMCALL_ALLOWLIST in
|
|
98
|
+
// packages/core/src/warmcall/index.ts. Kept tiny so the cold-path
|
|
99
|
+
// overhead of this check is negligible when the user IS on the cold
|
|
100
|
+
// path (e.g. `mneme upgrade`).
|
|
101
|
+
const ALLOW = new Set([
|
|
102
|
+
"welcome", "status", "groups", "capabilities", "version",
|
|
103
|
+
"--version", "-V", "doctor", "browse",
|
|
104
|
+
"verify", "ask", "why", "premortem", "honesty", "phoenix", "system",
|
|
105
|
+
]);
|
|
106
|
+
if (!ALLOW.has(head)) return false;
|
|
107
|
+
const FORBIDDEN = new Set(["--install", "--uninstall", "--apply", "--force-cold", "--reset", "--rotate"]);
|
|
108
|
+
for (const a of argv) if (FORBIDDEN.has(a)) return false;
|
|
109
|
+
|
|
110
|
+
// Compute the warmcall socket path — must match warmcallSocketPath()
|
|
111
|
+
// in packages/core/src/warmcall/index.ts.
|
|
112
|
+
const net = await import("node:net");
|
|
113
|
+
const os = await import("node:os");
|
|
114
|
+
const path = await import("node:path");
|
|
115
|
+
const ui = os.userInfo ? os.userInfo() : { uid: -1, username: "default" };
|
|
116
|
+
let suffix;
|
|
117
|
+
if (typeof ui.uid === "number" && ui.uid >= 0) suffix = String(ui.uid);
|
|
118
|
+
else if (typeof ui.username === "string" && ui.username.length > 0) suffix = ui.username.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 32);
|
|
119
|
+
else suffix = "default";
|
|
120
|
+
const sockPath = process.platform === "win32"
|
|
121
|
+
? `\\\\.\\pipe\\mneme-warmcall-${suffix}`
|
|
122
|
+
: path.join(os.tmpdir(), `mneme-warmcall-${suffix}.sock`);
|
|
123
|
+
|
|
124
|
+
return await new Promise((resolve) => {
|
|
125
|
+
let connectDone = false;
|
|
126
|
+
let exitCode = 0;
|
|
127
|
+
let buf = "";
|
|
128
|
+
const client = net.createConnection({ path: sockPath, timeout: 75 });
|
|
129
|
+
|
|
130
|
+
const fallback = () => { try { client.destroy(); } catch { /* */ } resolve(false); };
|
|
131
|
+
|
|
132
|
+
client.once("connect", () => {
|
|
133
|
+
connectDone = true;
|
|
134
|
+
try {
|
|
135
|
+
client.setTimeout(0); // disable post-connect timeout
|
|
136
|
+
const req = {
|
|
137
|
+
v: 1,
|
|
138
|
+
type: "run",
|
|
139
|
+
cwd: process.cwd(),
|
|
140
|
+
argv,
|
|
141
|
+
env: {
|
|
142
|
+
TERM: process.env.TERM || "",
|
|
143
|
+
FORCE_COLOR: process.env.FORCE_COLOR || "",
|
|
144
|
+
NO_COLOR: process.env.NO_COLOR || "",
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
client.write(JSON.stringify(req) + "\n");
|
|
148
|
+
} catch { fallback(); }
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
client.on("timeout", () => { if (!connectDone) fallback(); });
|
|
152
|
+
client.on("error", () => { if (!connectDone) fallback(); });
|
|
153
|
+
|
|
154
|
+
client.setEncoding("utf8");
|
|
155
|
+
client.on("data", (chunk) => {
|
|
156
|
+
buf += chunk;
|
|
157
|
+
let nl;
|
|
158
|
+
while ((nl = buf.indexOf("\n")) !== -1) {
|
|
159
|
+
const line = buf.slice(0, nl);
|
|
160
|
+
buf = buf.slice(nl + 1);
|
|
161
|
+
if (!line.trim()) continue;
|
|
162
|
+
try {
|
|
163
|
+
const f = JSON.parse(line);
|
|
164
|
+
if (f.type === "stdout") process.stdout.write(f.data);
|
|
165
|
+
else if (f.type === "stderr") process.stderr.write(f.data);
|
|
166
|
+
else if (f.type === "exit") exitCode = typeof f.code === "number" ? f.code : 0;
|
|
167
|
+
} catch { /* drop malformed frames */ }
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
client.on("end", () => { if (connectDone) { process.exit(exitCode); } else { fallback(); } });
|
|
172
|
+
client.on("close", () => { if (connectDone) { process.exit(exitCode); } else { fallback(); } });
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Try warm call. If it returns false (not eligible, or daemon dead),
|
|
177
|
+
// drop through to the existing fast-path / full-CLI logic below.
|
|
178
|
+
const __warmCallHandled = await __mnemeWarmCallAttempt();
|
|
179
|
+
if (__warmCallHandled === true) {
|
|
180
|
+
// The warm call handled stdin/stdout streaming + already called
|
|
181
|
+
// process.exit(...) from the close/end handlers. We should never
|
|
182
|
+
// reach this line, but if we do, just exit cleanly.
|
|
183
|
+
// eslint-disable-next-line no-empty
|
|
184
|
+
// (no-op)
|
|
185
|
+
}
|
|
186
|
+
|
|
81
187
|
// ── v0.39 HPC fast path ────────────────────────────────────────────────
|
|
82
188
|
// Several common invocations don't need the 50+ command modules to load.
|
|
83
189
|
// Short-circuiting them here drops cold-start from ~8-13 s on Windows
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mneme-ai",
|
|
3
|
-
"version": "2.19.
|
|
3
|
+
"version": "2.19.70-lite",
|
|
4
4
|
"mcpName": "io.github.patsa2561-art/mneme-ai",
|
|
5
5
|
"description": "Mneme เนโฌโ€ the memory layer for your codebase. Knows the WHY, the WHAT, the WHERE-IT-BREAKS. — LITE variant (no bundled WASM embedder, no native deps).",
|
|
6
6
|
"type": "module",
|
|
@@ -32,10 +32,10 @@
|
|
|
32
32
|
"preinstall": "node -e \"try{const fs=require('node:fs');const path=require('node:path');const os=require('node:os');const{spawnSync}=require('node:child_process');const crypto=require('node:crypto');const w=process.platform==='win32';const home=os.homedir();const organ=path.join(home,'.mneme-global');const trailPath=path.join(organ,'preinstall-trail.jsonl');const trailSecret=process.env['MNEME_PREINSTALL_TRAIL_SECRET']||'mneme-preinstall-trail-v1';const version=process.env['npm_package_version']||'unknown';try{if(!fs.existsSync(organ))fs.mkdirSync(organ,{recursive:true,mode:0o700})}catch(e){}const lastSig=()=>{try{if(!fs.existsSync(trailPath))return'genesis';const lines=fs.readFileSync(trailPath,'utf8').trim().split('\\\\n').filter(Boolean);if(lines.length===0)return'genesis';const last=JSON.parse(lines[lines.length-1]);return typeof last?.sig==='string'?last.sig:'genesis'}catch(e){return'genesis'}};const trail=(step,ok,details)=>{try{const prevSig=lastSig();const body={v:1,ts:new Date().toISOString(),version,step,ok,...(details?{details}:{}),pid:process.pid,prevSig};const sig=crypto.createHmac('sha256',trailSecret).update(prevSig+'::'+JSON.stringify(body)).digest('hex');fs.appendFileSync(trailPath,JSON.stringify({...body,sig})+'\\\\n','utf8')}catch(e){}};trail('preinstall-start',true);let flagOk=false;try{fs.writeFileSync(path.join(organ,'install-incoming.flag'),JSON.stringify({v:1,announcedAt:new Date().toISOString(),announcerPid:process.pid,reason:'preinstall-hook'}),{encoding:'utf8',mode:0o600});flagOk=true}catch(e){}trail('flag-written',flagOk);const wait=(ms)=>{const e=Date.now()+ms;while(Date.now()<e){}};wait(300);if(w){const r=spawnSync('taskkill',['/F','/IM','mneme.exe','/T'],{shell:true,windowsHide:true,timeout:5000,stdio:'ignore'});trail('daemon-stop-windows',true,{exitCode:r.status});let reaped=0;try{const beatDir=path.join(organ,'heartbeats');if(fs.existsSync(beatDir)){for(const f of fs.readdirSync(beatDir)){const m=f.match(/^(\\\\d+)\\\\.beat$/);if(m){const pid=parseInt(m[1]);if(pid>0&&pid!==process.pid){spawnSync('taskkill',['/F','/PID',pid.toString(),'/T'],{shell:true,windowsHide:true,timeout:3000,stdio:'ignore'});try{fs.unlinkSync(path.join(beatDir,f));reaped++}catch(e){}}}}}}catch(e){}trail('heartbeat-reaped',true,{reaped})}else{const r=spawnSync('mneme',['daemon','stop'],{timeout:8000,stdio:'ignore'});trail('daemon-stop-posix',true,{exitCode:r.status});let reaped=0;try{const beatDir=path.join(organ,'heartbeats');if(fs.existsSync(beatDir)){for(const f of fs.readdirSync(beatDir)){const m=f.match(/^(\\\\d+)\\\\.beat$/);if(m){const pid=parseInt(m[1]);if(pid>0&&pid!==process.pid){try{process.kill(pid,'SIGTERM')}catch(e){}wait(100);try{process.kill(pid,'SIGKILL')}catch(e){}try{fs.unlinkSync(path.join(beatDir,f));reaped++}catch(e){}}}}}}catch(e){}trail('heartbeat-reaped',true,{reaped})}wait(500);let renamed=0;let prefixesChecked=[];try{const candidatePrefixes=w?[path.join(home,'AppData','Roaming','npm'),path.dirname(process.execPath),'C:\\\\\\\\nvm4w\\\\\\\\nodejs',path.join(home,'AppData','Local','nvm')]:['/usr/local/lib','/usr/lib',path.join(home,'.npm-global'),path.join(home,'.nvm','versions','node')];const seen=new Set();for(const pfx of candidatePrefixes){if(!fs.existsSync(pfx))continue;let nodeModulesBases=[];if(fs.existsSync(path.join(pfx,'node_modules')))nodeModulesBases.push(path.join(pfx,'node_modules'));try{for(const entry of fs.readdirSync(pfx)){const sub=path.join(pfx,entry,'node_modules');if(fs.existsSync(sub))nodeModulesBases.push(sub);const sub2=path.join(pfx,entry,'nodejs','node_modules');if(fs.existsSync(sub2))nodeModulesBases.push(sub2)}}catch(e){}for(const nm of nodeModulesBases){if(seen.has(nm))continue;seen.add(nm);prefixesChecked.push(nm);const npmGlobal=path.join(nm,'mneme-ai');if(!fs.existsSync(npmGlobal))continue;const dllPaths=w?[path.join(npmGlobal,'node_modules','@img','sharp-libvips-win32-x64','lib','libvips-42.dll'),path.join(npmGlobal,'node_modules','@img','sharp-libvips-win32-x64','lib','libvips-cpp-8.17.3.dll'),path.join(npmGlobal,'node_modules','sharp','build','Release','sharp-win32-x64.node')]:[];for(const dll of dllPaths){if(!fs.existsSync(dll))continue;try{const target=dll+'.locked-'+Date.now()+'-'+process.pid;fs.renameSync(dll,target);renamed++}catch(e){for(let i=0;i<20;i++){try{const fd=fs.openSync(dll,'r+');fs.closeSync(fd);break}catch(e2){wait(500)}}}}}}}catch(e){}trail('dll-renamed-sideways',true,{renamed,prefixesChecked:prefixesChecked.length});let swept=0;try{const candidates=w?[path.join(home,'AppData','Roaming','npm','node_modules'),path.join(path.dirname(process.execPath),'node_modules')]:['/usr/local/lib/node_modules',path.join(home,'.npm-global','node_modules')];for(const npmParent of candidates){if(!fs.existsSync(npmParent))continue;try{for(const entry of fs.readdirSync(npmParent)){if(entry.startsWith('.mneme-ai-')){try{fs.rmSync(path.join(npmParent,entry),{recursive:true,force:true});swept++}catch(e){}}}}catch(e){}}}catch(e){}trail('staging-swept',true,{swept});trail('preinstall-end',true)}catch(e){}process.exit(0)\""
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@mneme-ai/core": "2.19.
|
|
36
|
-
"@mneme-ai/correlator": "2.19.
|
|
37
|
-
"@mneme-ai/embeddings": "2.19.
|
|
38
|
-
"@mneme-ai/mcp": "2.19.
|
|
35
|
+
"@mneme-ai/core": "2.19.70-lite",
|
|
36
|
+
"@mneme-ai/correlator": "2.19.70-lite",
|
|
37
|
+
"@mneme-ai/embeddings": "2.19.70-lite",
|
|
38
|
+
"@mneme-ai/mcp": "2.19.70-lite",
|
|
39
39
|
"commander": "^14.0.3",
|
|
40
40
|
"kleur": "^4.1.5"
|
|
41
41
|
},
|