@nxuss/lemma 0.9.2 → 1.0.0
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/README.md +79 -12
- package/bin/cli.js +97 -0
- package/bin/init.js +307 -0
- package/cache-proxy.js +191 -0
- package/dist/cjs/cli/lemma-proxy.d.ts.map +1 -1
- package/dist/cjs/cli/lemma-proxy.js +2 -4
- package/dist/cjs/cli/lemma-proxy.js.map +1 -1
- package/dist/cjs/mcp/index.js +1 -1
- package/dist/cjs/mcp/tools.d.ts.map +1 -1
- package/dist/cjs/mcp/tools.js +911 -71
- package/dist/cjs/mcp/tools.js.map +1 -1
- package/dist/cjs/subconscious/TheBrainV2.d.ts +102 -0
- package/dist/cjs/subconscious/TheBrainV2.d.ts.map +1 -0
- package/dist/cjs/subconscious/TheBrainV2.js +444 -0
- package/dist/cjs/subconscious/TheBrainV2.js.map +1 -0
- package/dist/cjs/utils/ContextCollapser.d.ts +21 -0
- package/dist/cjs/utils/ContextCollapser.d.ts.map +1 -0
- package/dist/cjs/utils/ContextCollapser.js +132 -0
- package/dist/cjs/utils/ContextCollapser.js.map +1 -0
- package/dist/cjs/utils/ExecutiveReport.d.ts +29 -0
- package/dist/cjs/utils/ExecutiveReport.d.ts.map +1 -0
- package/dist/cjs/utils/ExecutiveReport.js +111 -0
- package/dist/cjs/utils/ExecutiveReport.js.map +1 -0
- package/dist/cjs/utils/SurgicalASTInsert.d.ts +21 -0
- package/dist/cjs/utils/SurgicalASTInsert.d.ts.map +1 -0
- package/dist/cjs/utils/SurgicalASTInsert.js +173 -0
- package/dist/cjs/utils/SurgicalASTInsert.js.map +1 -0
- package/dist/cjs/utils/SymbolSurgicalContext.d.ts +25 -0
- package/dist/cjs/utils/SymbolSurgicalContext.d.ts.map +1 -0
- package/dist/cjs/utils/SymbolSurgicalContext.js +265 -0
- package/dist/cjs/utils/SymbolSurgicalContext.js.map +1 -0
- package/dist/cjs/utils/WormholeCompressor.d.ts +22 -0
- package/dist/cjs/utils/WormholeCompressor.d.ts.map +1 -0
- package/dist/cjs/utils/WormholeCompressor.js +152 -0
- package/dist/cjs/utils/WormholeCompressor.js.map +1 -0
- package/dist/esm/cli/lemma-proxy.d.ts.map +1 -1
- package/dist/esm/cli/lemma-proxy.js +2 -4
- package/dist/esm/cli/lemma-proxy.js.map +1 -1
- package/dist/esm/mcp/index.js +1 -1
- package/dist/esm/mcp/tools.d.ts.map +1 -1
- package/dist/esm/mcp/tools.js +911 -71
- package/dist/esm/mcp/tools.js.map +1 -1
- package/dist/esm/subconscious/TheBrainV2.d.ts +102 -0
- package/dist/esm/subconscious/TheBrainV2.d.ts.map +1 -0
- package/dist/esm/subconscious/TheBrainV2.js +431 -0
- package/dist/esm/subconscious/TheBrainV2.js.map +1 -0
- package/dist/esm/utils/ContextCollapser.d.ts +21 -0
- package/dist/esm/utils/ContextCollapser.d.ts.map +1 -0
- package/dist/esm/utils/ContextCollapser.js +128 -0
- package/dist/esm/utils/ContextCollapser.js.map +1 -0
- package/dist/esm/utils/ExecutiveReport.d.ts +29 -0
- package/dist/esm/utils/ExecutiveReport.d.ts.map +1 -0
- package/dist/esm/utils/ExecutiveReport.js +105 -0
- package/dist/esm/utils/ExecutiveReport.js.map +1 -0
- package/dist/esm/utils/SurgicalASTInsert.d.ts +21 -0
- package/dist/esm/utils/SurgicalASTInsert.d.ts.map +1 -0
- package/dist/esm/utils/SurgicalASTInsert.js +134 -0
- package/dist/esm/utils/SurgicalASTInsert.js.map +1 -0
- package/dist/esm/utils/SymbolSurgicalContext.d.ts +25 -0
- package/dist/esm/utils/SymbolSurgicalContext.d.ts.map +1 -0
- package/dist/esm/utils/SymbolSurgicalContext.js +226 -0
- package/dist/esm/utils/SymbolSurgicalContext.js.map +1 -0
- package/dist/esm/utils/WormholeCompressor.d.ts +22 -0
- package/dist/esm/utils/WormholeCompressor.d.ts.map +1 -0
- package/dist/esm/utils/WormholeCompressor.js +148 -0
- package/dist/esm/utils/WormholeCompressor.js.map +1 -0
- package/lemma-proxy.cjs +31 -14
- package/mcp-server.js +220 -0
- package/package.json +5 -1
package/cache-proxy.js
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const http = require('http');
|
|
5
|
+
const https = require('https');
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const os = require('os');
|
|
9
|
+
|
|
10
|
+
const PORT = parseInt(process.env.LEMMA_PROXY_PORT || '9090', 10);
|
|
11
|
+
const UPSTREAM = process.env.LEMMA_UPSTREAM || 'https://api.openai.com';
|
|
12
|
+
const API_KEY = process.env.LEMMA_API_KEY || process.env.OPENAI_API_KEY || '';
|
|
13
|
+
const BRAIN_FILE = path.join(os.homedir(), '.lemma-cache', 'lemma_brain.json');
|
|
14
|
+
|
|
15
|
+
function loadBrain() {
|
|
16
|
+
try {
|
|
17
|
+
if (!fs.existsSync(BRAIN_FILE)) {
|
|
18
|
+
fs.mkdirSync(path.dirname(BRAIN_FILE), { recursive: true });
|
|
19
|
+
fs.writeFileSync(BRAIN_FILE, '[]', 'utf8');
|
|
20
|
+
return [];
|
|
21
|
+
}
|
|
22
|
+
return JSON.parse(fs.readFileSync(BRAIN_FILE, 'utf8'));
|
|
23
|
+
} catch (e) {
|
|
24
|
+
console.error('[cache-proxy] Failed to load brain:', e.message);
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function saveBrain(data) {
|
|
30
|
+
try {
|
|
31
|
+
fs.mkdirSync(path.dirname(BRAIN_FILE), { recursive: true });
|
|
32
|
+
fs.writeFileSync(BRAIN_FILE, JSON.stringify(data), 'utf8');
|
|
33
|
+
} catch (e) {
|
|
34
|
+
console.error('[cache-proxy] Failed to save brain:', e.message);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const STOP_WORDS = new Set(['the','a','an','is','are','was','were','be','been','being','have','has','had','do','does','did','will','would','could','should','may','might','shall','can','need','dare','ought','used','to','of','in','for','on','with','at','by','from','as','into','through','during','before','after','above','below','between','out','off','over','under','again','further','then','once','here','there','when','where','why','how','all','each','every','both','few','more','most','other','some','such','no','nor','not','only','own','same','so','than','too','very','just','because','but','and','or','if','while','although','since','until','unless','about','up','it','its','this','that','these','those','i','me','my','myself','we','our','ours','ourselves','you','your','yours','yourself','yourselves','he','him','his','himself','she','her','hers','herself','they','them','their','theirs','themselves','what','which','who','whom','this']);
|
|
39
|
+
|
|
40
|
+
function tokenize(text) {
|
|
41
|
+
return text.toLowerCase().replace(/[^a-z0-9\s]/g, '').split(/\s+/).filter(w => w.length > 1 && !STOP_WORDS.has(w));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function idf(corpusTokens) {
|
|
45
|
+
const df = {}, N = corpusTokens.length;
|
|
46
|
+
for (const tokens of corpusTokens) {
|
|
47
|
+
const seen = new Set(tokens);
|
|
48
|
+
for (const t of seen) df[t] = (df[t] || 0) + 1;
|
|
49
|
+
}
|
|
50
|
+
const scores = {};
|
|
51
|
+
for (const [t, count] of Object.entries(df)) scores[t] = Math.log(1 + (N - count + 0.5) / (count + 0.5));
|
|
52
|
+
return scores;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function bm25(queryTokens, docTokens, idfScores, avgDocLen) {
|
|
56
|
+
const k1 = 1.5, b = 0.75;
|
|
57
|
+
let score = 0;
|
|
58
|
+
const docLen = docTokens.length;
|
|
59
|
+
const tf = {};
|
|
60
|
+
for (const t of docTokens) tf[t] = (tf[t] || 0) + 1;
|
|
61
|
+
for (const q of queryTokens) {
|
|
62
|
+
const f = tf[q] || 0;
|
|
63
|
+
const idfVal = idfScores[q] || 0;
|
|
64
|
+
if (f === 0) continue;
|
|
65
|
+
score += idfVal * ((f * (k1 + 1)) / (f + k1 * (1 - b + b * (docLen / avgDocLen))));
|
|
66
|
+
}
|
|
67
|
+
return score;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function buildIndex(entries) {
|
|
71
|
+
if (!entries || entries.length === 0) return { corpusTokens: [], idfScores: {}, avgDocLen: 0 };
|
|
72
|
+
const corpusTokens = entries.map(e => tokenize(e.prompt || ''));
|
|
73
|
+
const avgDocLen = corpusTokens.reduce((s, t) => s + t.length, 0) / corpusTokens.length;
|
|
74
|
+
return { corpusTokens, idfScores: idf(corpusTokens), avgDocLen };
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function search(entries, query, threshold) {
|
|
78
|
+
if (!entries || entries.length === 0) return [];
|
|
79
|
+
const qt = tokenize(query);
|
|
80
|
+
if (qt.length === 0) return [];
|
|
81
|
+
const idx = buildIndex(entries);
|
|
82
|
+
const maxScore = bm25(qt, qt, idx.idfScores, idx.avgDocLen);
|
|
83
|
+
return entries.map((e, i) => {
|
|
84
|
+
const raw = bm25(qt, idx.corpusTokens[i], idx.idfScores, idx.avgDocLen);
|
|
85
|
+
return { entry: e, similarity: maxScore > 0 ? raw / maxScore : 0, index: i };
|
|
86
|
+
}).filter(r => r.similarity >= threshold).sort((a, b) => b.similarity - a.similarity);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function extractPrompt(body) {
|
|
90
|
+
try {
|
|
91
|
+
if (body.messages) {
|
|
92
|
+
return body.messages.map(m => `${m.role}: ${m.content}`).join('\n');
|
|
93
|
+
}
|
|
94
|
+
if (body.prompt) return body.prompt;
|
|
95
|
+
if (body.input) return typeof body.input === 'string' ? body.input : JSON.stringify(body.input);
|
|
96
|
+
} catch {}
|
|
97
|
+
return JSON.stringify(body).substring(0, 500);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function extractResponse(data) {
|
|
101
|
+
try {
|
|
102
|
+
if (data.choices && data.choices[0]) {
|
|
103
|
+
return data.choices[0].message?.content || data.choices[0].text || JSON.stringify(data);
|
|
104
|
+
}
|
|
105
|
+
return JSON.stringify(data);
|
|
106
|
+
} catch { return JSON.stringify(data); }
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function proxyRequest(body) {
|
|
110
|
+
return new Promise((resolve, reject) => {
|
|
111
|
+
const url = new URL(UPSTREAM + '/v1/chat/completions');
|
|
112
|
+
const data = JSON.stringify(body);
|
|
113
|
+
const opts = {
|
|
114
|
+
hostname: url.hostname, port: url.port || 443, path: url.pathname,
|
|
115
|
+
method: 'POST',
|
|
116
|
+
headers: {
|
|
117
|
+
'Content-Type': 'application/json',
|
|
118
|
+
'Authorization': `Bearer ${API_KEY}`,
|
|
119
|
+
'Content-Length': Buffer.byteLength(data)
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
const mod = url.protocol === 'https:' ? https : http;
|
|
123
|
+
const req = mod.request(opts, (res) => {
|
|
124
|
+
let chunks = '';
|
|
125
|
+
res.on('data', c => chunks += c);
|
|
126
|
+
res.on('end', () => {
|
|
127
|
+
try { resolve(JSON.parse(chunks)); }
|
|
128
|
+
catch { resolve({ choices: [{ message: { content: chunks } }] }); }
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
req.on('error', reject);
|
|
132
|
+
req.write(data);
|
|
133
|
+
req.end();
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const server = http.createServer((req, res) => {
|
|
138
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
139
|
+
res.setHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS');
|
|
140
|
+
res.setHeader('Access-Control-Allow-Headers', '*');
|
|
141
|
+
|
|
142
|
+
if (req.method === 'OPTIONS') { res.writeHead(200); res.end(); return; }
|
|
143
|
+
|
|
144
|
+
let body = '';
|
|
145
|
+
req.on('data', c => body += c);
|
|
146
|
+
req.on('end', async () => {
|
|
147
|
+
try {
|
|
148
|
+
const parsed = JSON.parse(body);
|
|
149
|
+
const prompt = extractPrompt(parsed);
|
|
150
|
+
|
|
151
|
+
if (req.url === '/v1/chat/completions' && prompt) {
|
|
152
|
+
const brain = loadBrain();
|
|
153
|
+
const results = search(brain, prompt, 0.85);
|
|
154
|
+
|
|
155
|
+
if (results.length > 0) {
|
|
156
|
+
const hit = results[0];
|
|
157
|
+
brain[hit.index].hits = (brain[hit.index].hits || 0) + 1;
|
|
158
|
+
saveBrain(brain);
|
|
159
|
+
const cached = JSON.parse(hit.entry.response);
|
|
160
|
+
console.error(`[cache-proxy] HIT (${(hit.similarity * 100).toFixed(1)}%) — returning cached (${hit.entry.hits} hits)`);
|
|
161
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
162
|
+
res.end(JSON.stringify(cached));
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
console.error('[cache-proxy] MISS — forwarding to upstream');
|
|
167
|
+
const upstreamResp = await proxyRequest(parsed);
|
|
168
|
+
const responseText = extractResponse(upstreamResp);
|
|
169
|
+
|
|
170
|
+
brain.push({ prompt, response: responseText, hits: 0, createdAt: Date.now() });
|
|
171
|
+
saveBrain(brain);
|
|
172
|
+
|
|
173
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
174
|
+
res.end(JSON.stringify(upstreamResp));
|
|
175
|
+
} else {
|
|
176
|
+
res.writeHead(404); res.end('Not found');
|
|
177
|
+
}
|
|
178
|
+
} catch (e) {
|
|
179
|
+
console.error('[cache-proxy] Error:', e.message);
|
|
180
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
181
|
+
res.end(JSON.stringify({ error: e.message }));
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
server.listen(PORT, () => {
|
|
187
|
+
console.error(`[cache-proxy] Lemma Cache Proxy on :${PORT}`);
|
|
188
|
+
console.error(`[cache-proxy] Upstream: ${UPSTREAM}`);
|
|
189
|
+
console.error(`[cache-proxy] Caching ANY provider via OpenAI-compatible endpoint`);
|
|
190
|
+
console.error(`[cache-proxy] Point your tool to: http://localhost:${PORT}/v1/chat/completions`);
|
|
191
|
+
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lemma-proxy.d.ts","sourceRoot":"","sources":["../../../src/cli/lemma-proxy.ts"],"names":[],"mappings":";AA2cA,wBAAgB,+BAA+B,CAAC,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CA4DvF;
|
|
1
|
+
{"version":3,"file":"lemma-proxy.d.ts","sourceRoot":"","sources":["../../../src/cli/lemma-proxy.ts"],"names":[],"mappings":";AA2cA,wBAAgB,+BAA+B,CAAC,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CA4DvF;AAogED,wBAAsB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA6KhL"}
|
|
@@ -2000,14 +2000,12 @@ Adjusted Answer:`;
|
|
|
2000
2000
|
console.log(`🔒 Privacy Firewall : \x1b[32m[ACTIVE]\x1b[0m`);
|
|
2001
2001
|
console.log(`🔀 Complexity Router : \x1b[32m[ACTIVE]\x1b[0m`);
|
|
2002
2002
|
console.log(`💾 Exact Cache : \x1b[32m[ACTIVE]\x1b[0m`);
|
|
2003
|
-
const ollamaOk = await checkDependency('http://localhost:11434/api/tags');
|
|
2004
|
-
const chromaOk = await checkDependency('http://localhost:8000/');
|
|
2005
2003
|
if (pro) {
|
|
2006
|
-
console.log(`🎯 Semantic Cache :
|
|
2004
|
+
console.log(`🎯 Semantic Cache : \x1b[32m[ACTIVE - Local TheBrainV2 Okapi BM25 Engine]\x1b[0m`);
|
|
2007
2005
|
console.log(`🌐 Hive Mind (Cloud) : \x1b[32m[ACTIVE]\x1b[0m`);
|
|
2008
2006
|
}
|
|
2009
2007
|
else {
|
|
2010
|
-
console.log(`🎯 Semantic Cache : \x1b[
|
|
2008
|
+
console.log(`🎯 Semantic Cache : \x1b[32m[ACTIVE - Local TheBrainV2 Okapi BM25 Engine]\x1b[0m`);
|
|
2011
2009
|
console.log(`🌐 Hive Mind (Cloud) : \x1b[90m[PRO ONLY]\x1b[0m -> https://lemma.nxus.studio/upgrade`);
|
|
2012
2010
|
}
|
|
2013
2011
|
const hasStackDir = fs_1.default.existsSync(path_1.default.join(process.cwd(), '.lemma'));
|