@andespindola/brainlink 0.1.0-beta.17 → 0.1.0-beta.18

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.
@@ -162,13 +162,19 @@ const bloomFromBase64 = (value) => {
162
162
  try {
163
163
  const decoded = Buffer.from(value, 'base64url');
164
164
  if (decoded.byteLength === bloomBytes) {
165
- return new Uint8Array(decoded);
165
+ return {
166
+ bloom: new Uint8Array(decoded),
167
+ valid: true
168
+ };
166
169
  }
167
170
  }
168
171
  catch {
169
172
  // fallback below
170
173
  }
171
- return createBloom();
174
+ return {
175
+ bloom: createBloom(),
176
+ valid: false
177
+ };
172
178
  };
173
179
  const computeTextScore = (row, tokens) => {
174
180
  if (tokens.length === 0) {
@@ -224,19 +230,21 @@ const writeRowsAsPrivatePacks = async (vaultPath, rows, clearExisting) => {
224
230
  .map((name) => rm(join(directory, name), { force: true })));
225
231
  }
226
232
  const chunks = chunkRows(rows, rowChunkSize);
227
- const packIndex = await Promise.all(chunks.map(async (chunk, index) => {
233
+ const packIndex = [];
234
+ for (let index = 0; index < chunks.length; index += 1) {
235
+ const chunk = chunks[index];
228
236
  const fileName = `pack-${String(index + 1).padStart(4, '0')}.blpk`;
229
237
  const serialized = `${chunk.map((row) => JSON.stringify(row)).join('\n')}\n`;
230
238
  const compressed = await encodePrivatePack(vaultPath, Buffer.from(serialized, 'utf8'));
231
239
  const tokenBloomB64 = bloomToBase64(bloomFromRows(chunk));
232
240
  await writeFile(join(directory, fileName), compressed);
233
- return {
241
+ packIndex.push({
234
242
  fileName,
235
243
  recordCount: chunk.length,
236
244
  agents: Array.from(new Set(chunk.map((row) => row.agentId))).sort((left, right) => left.localeCompare(right)),
237
245
  tokenBloomB64
238
- };
239
- }));
246
+ });
247
+ }
240
248
  await writeManifest(vaultPath, {
241
249
  version: 3,
242
250
  createdAt: new Date().toISOString(),
@@ -264,10 +272,19 @@ const selectCandidatePackFiles = async (vaultPath, tokens, agentId) => {
264
272
  if (tokens.length === 0) {
265
273
  return byAgent.map((entry) => entry.fileName);
266
274
  }
275
+ let hasInvalidBloomIndex = false;
267
276
  const byToken = byAgent.filter((entry) => {
268
- const bloom = bloomFromBase64(entry.tokenBloomB64);
269
- return tokens.some((token) => bloomMayContain(bloom, token));
277
+ const decoded = bloomFromBase64(entry.tokenBloomB64);
278
+ if (!decoded.valid) {
279
+ hasInvalidBloomIndex = true;
280
+ return true;
281
+ }
282
+ return tokens.some((token) => bloomMayContain(decoded.bloom, token));
270
283
  });
284
+ // Lossless guarantee: if compressed metadata is partially invalid, do not prune packs.
285
+ if (hasInvalidBloomIndex) {
286
+ return byAgent.map((entry) => entry.fileName);
287
+ }
271
288
  if (byToken.length > 0) {
272
289
  return byToken.map((entry) => entry.fileName);
273
290
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@andespindola/brainlink",
3
- "version": "0.1.0-beta.17",
3
+ "version": "0.1.0-beta.18",
4
4
  "description": "Local-first knowledge memory for agents with Markdown, backlinks, indexing and context retrieval.",
5
5
  "type": "module",
6
6
  "license": "MIT",