@nxuss/lemma 0.6.0 → 0.7.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.
@@ -96,6 +96,15 @@ async function writeJson(file, data) {
96
96
  function projectHash(name) {
97
97
  return crypto.createHash('sha1').update(name).digest('hex').slice(0, 12);
98
98
  }
99
+ function getCollectionName(projectName) {
100
+ let cleanName = projectName.replace(/[^a-zA-Z0-9._-]/g, '_');
101
+ cleanName = cleanName.replace(/^[^a-zA-Z0-9]+/, '');
102
+ cleanName = cleanName.replace(/[^a-zA-Z0-9]+$/, '');
103
+ if (cleanName.length < 3) {
104
+ cleanName = 'lemma_proj_' + cleanName;
105
+ }
106
+ return `lemma-cache-${cleanName}`;
107
+ }
99
108
  function detectProject() {
100
109
  const pkgPath = path.join(process.cwd(), 'package.json');
101
110
  if (fs.existsSync(pkgPath)) {
@@ -609,7 +618,7 @@ async function semanticGet(provider, prompt, projectName = 'global') {
609
618
  let localHit = null;
610
619
  try {
611
620
  const collection = await chroma.getOrCreateCollection({
612
- name: `lemma-cache-${projectName}`,
621
+ name: getCollectionName(projectName),
613
622
  embeddingFunction: dummyEmbeddingFunction,
614
623
  metadata: { "hnsw:space": "cosine" }
615
624
  });
@@ -648,7 +657,7 @@ async function semanticGet(provider, prompt, projectName = 'global') {
648
657
  // ─── Cross-Project Bug Telepathy Fallback ───
649
658
  try {
650
659
  const collections = await chroma.listCollections();
651
- const projectCollections = collections.filter((c) => c.name.startsWith('lemma-cache-') && c.name !== `lemma-cache-${projectName}`);
660
+ const projectCollections = collections.filter((c) => c.name.startsWith('lemma-cache-') && c.name !== getCollectionName(projectName));
652
661
  for (const colInfo of projectCollections) {
653
662
  try {
654
663
  const col = await chroma.getOrCreateCollection({
@@ -701,7 +710,7 @@ async function semanticSet(provider, prompt, data, projectName = 'global') {
701
710
  return;
702
711
  try {
703
712
  const collection = await chroma.getOrCreateCollection({
704
- name: `lemma-cache-${projectName}`,
713
+ name: getCollectionName(projectName),
705
714
  embeddingFunction: dummyEmbeddingFunction,
706
715
  metadata: { "hnsw:space": "cosine" }
707
716
  });
@@ -1092,7 +1101,7 @@ class LemmaServer {
1092
1101
  // Try to query ChromaDB for semantic cache count
1093
1102
  try {
1094
1103
  const collection = await chroma.getOrCreateCollection({
1095
- name: `lemma-cache-${this.projectName}`,
1104
+ name: getCollectionName(this.projectName),
1096
1105
  embeddingFunction: dummyEmbeddingFunction,
1097
1106
  metadata: { "hnsw:space": "cosine" }
1098
1107
  });
@@ -1148,28 +1157,46 @@ class LemmaServer {
1148
1157
  const emb = await getEmbedding(query);
1149
1158
  if (!emb)
1150
1159
  throw new Error('Failed to generate embedding');
1151
- const collection = await chroma.getOrCreateCollection({
1152
- name: `lemma-cache-${this.projectName}`,
1153
- embeddingFunction: dummyEmbeddingFunction,
1154
- metadata: { "hnsw:space": "cosine" }
1155
- });
1156
- const results = await collection.query({
1157
- queryEmbeddings: [emb],
1158
- nResults: 10
1159
- });
1160
- const formatted = (results.ids[0] || []).map((id, i) => {
1161
- const meta = results.metadatas[0][i];
1162
- const dists = results.distances;
1163
- const dist = (dists && dists[0] && dists[0][i] !== null && dists[0][i] !== undefined) ? dists[0][i] : 1.0;
1164
- return {
1165
- id,
1166
- prompt: meta.prompt,
1167
- response: JSON.parse(meta.response),
1168
- timestamp: meta.timestamp,
1169
- similarity: 1 - dist
1170
- };
1171
- });
1172
- res.json({ results: formatted });
1160
+ let allResults = [];
1161
+ // 1. Query all collections starting with 'lemma-cache' for cross-project search
1162
+ const collections = await chroma.listCollections();
1163
+ const targetCollections = collections.filter((c) => c.name.startsWith('lemma-cache'));
1164
+ for (const colInfo of targetCollections) {
1165
+ try {
1166
+ const collection = await chroma.getOrCreateCollection({
1167
+ name: colInfo.name,
1168
+ embeddingFunction: dummyEmbeddingFunction,
1169
+ metadata: { "hnsw:space": "cosine" }
1170
+ });
1171
+ const results = await collection.query({
1172
+ queryEmbeddings: [emb],
1173
+ nResults: 5
1174
+ });
1175
+ const originProject = colInfo.name === 'lemma-cache' ? 'global' : colInfo.name.replace('lemma-cache-', '');
1176
+ (results.ids[0] || []).forEach((id, i) => {
1177
+ const meta = results.metadatas[0][i];
1178
+ const dists = results.distances;
1179
+ const dist = (dists && dists[0] && dists[0][i] !== null && dists[0][i] !== undefined) ? dists[0][i] : 1.0;
1180
+ let parsedResponse = meta.response;
1181
+ try {
1182
+ parsedResponse = JSON.parse(meta.response);
1183
+ }
1184
+ catch { }
1185
+ allResults.push({
1186
+ id,
1187
+ prompt: meta.prompt,
1188
+ response: parsedResponse,
1189
+ timestamp: meta.timestamp,
1190
+ similarity: 1 - dist,
1191
+ project: originProject
1192
+ });
1193
+ });
1194
+ }
1195
+ catch { }
1196
+ }
1197
+ // 2. Sort all project results by similarity descending
1198
+ allResults.sort((a, b) => b.similarity - a.similarity);
1199
+ res.json({ results: allResults.slice(0, 10) });
1173
1200
  }
1174
1201
  catch (e) {
1175
1202
  res.status(500).json({ error: e.message });
@@ -1198,7 +1225,7 @@ class LemmaServer {
1198
1225
  }
1199
1226
  // Clear Chroma DB collection
1200
1227
  try {
1201
- await chroma.deleteCollection({ name: `lemma-cache-${this.projectName}` }).catch(() => { });
1228
+ await chroma.deleteCollection({ name: getCollectionName(this.projectName) }).catch(() => { });
1202
1229
  }
1203
1230
  catch (e) {
1204
1231
  console.error(`[CacheClear] Failed to clear Chroma collection: ${e.message}`);
@@ -1215,7 +1242,7 @@ class LemmaServer {
1215
1242
  // Selective delete from Chroma DB collection using provider metadata filter
1216
1243
  try {
1217
1244
  const collection = await chroma.getOrCreateCollection({
1218
- name: `lemma-cache-${this.projectName}`,
1245
+ name: getCollectionName(this.projectName),
1219
1246
  embeddingFunction: dummyEmbeddingFunction,
1220
1247
  metadata: { "hnsw:space": "cosine" }
1221
1248
  });
@@ -1283,7 +1310,7 @@ class LemmaServer {
1283
1310
  const emb = await getEmbedding("architectural design guidelines and core stack configuration decisions");
1284
1311
  if (emb) {
1285
1312
  const collection = await chroma.getOrCreateCollection({
1286
- name: `lemma-cache-${this.projectName}`,
1313
+ name: getCollectionName(this.projectName),
1287
1314
  embeddingFunction: dummyEmbeddingFunction,
1288
1315
  metadata: { "hnsw:space": "cosine" }
1289
1316
  });
@@ -1354,7 +1381,7 @@ class LemmaServer {
1354
1381
  return res.status(500).json({ error: 'Failed to generate embedding' });
1355
1382
  }
1356
1383
  const collection = await chroma.getOrCreateCollection({
1357
- name: `lemma-cache-${this.projectName}`,
1384
+ name: getCollectionName(this.projectName),
1358
1385
  embeddingFunction: dummyEmbeddingFunction,
1359
1386
  metadata: { "hnsw:space": "cosine" }
1360
1387
  });