@soulcraft/brainy 5.7.10 → 5.7.12

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 CHANGED
@@ -2,6 +2,20 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [5.7.12](https://github.com/soulcraftlabs/brainy/compare/v5.7.11...v5.7.12) (2025-11-13)
6
+
7
+
8
+ ### 🐛 Bug Fixes
9
+
10
+ * excludeVFS now only excludes VFS infrastructure entities (v5.7.12) ([99ac901](https://github.com/soulcraftlabs/brainy/commit/99ac901894bb81ad61b52d422f43cf30f07b6813))
11
+
12
+ ### [5.7.11](https://github.com/soulcraftlabs/brainy/compare/v5.7.10...v5.7.11) (2025-11-13)
13
+
14
+
15
+ ### 🐛 Bug Fixes
16
+
17
+ * resolve critical 378x pagination infinite loop bug (v5.7.11) ([e86f765](https://github.com/soulcraftlabs/brainy/commit/e86f765f3d30be41707e2ef7d07bb5c92d4ca3da))
18
+
5
19
  ### [5.7.9](https://github.com/soulcraftlabs/brainy/compare/v5.7.8...v5.7.9) (2025-11-13)
6
20
 
7
21
  - fix: implement exists: false and missing operators in MetadataIndexManager (b0f72ef)
package/dist/brainy.js CHANGED
@@ -1164,10 +1164,40 @@ export class Brainy {
1164
1164
  Object.assign(filter, params.where);
1165
1165
  if (params.service)
1166
1166
  filter.service = params.service;
1167
- // v4.7.0: excludeVFS helper for cleaner UX
1168
- // Use vfsType field (more semantic than isVFS)
1167
+ // v5.7.12: excludeVFS helper - ONLY exclude VFS infrastructure entities
1168
+ // Bug fix: Previously excluded entities with ANY vfsType field
1169
+ // Now ONLY excludes entities with isVFSEntity: true OR vfsType: 'file'/'directory'
1170
+ // This allows extracted entities (concepts/people/etc) to be included even if they
1171
+ // have vfsPath metadata showing where they were imported from
1169
1172
  if (params.excludeVFS === true) {
1170
- filter.vfsType = { exists: false };
1173
+ // Build filter: EXCLUDE WHERE (isVFSEntity == true) OR (vfsType IN ['file', 'directory'])
1174
+ // Implementation: INCLUDE WHERE (isVFSEntity missing/false) AND (vfsType missing/not file or directory)
1175
+ const existingFilter = { ...filter };
1176
+ filter = {
1177
+ allOf: [
1178
+ existingFilter,
1179
+ {
1180
+ // Only include entities WITHOUT isVFSEntity: true
1181
+ anyOf: [
1182
+ { isVFSEntity: { exists: false } },
1183
+ { isVFSEntity: { ne: true } }
1184
+ ]
1185
+ },
1186
+ {
1187
+ // Only include entities WITHOUT vfsType: 'file' or 'directory'
1188
+ // Since VFS files ALWAYS have vfsType set, we check it's missing OR not file/dir
1189
+ anyOf: [
1190
+ { vfsType: { exists: false } },
1191
+ {
1192
+ allOf: [
1193
+ { vfsType: { ne: 'file' } },
1194
+ { vfsType: { ne: 'directory' } }
1195
+ ]
1196
+ }
1197
+ ]
1198
+ }
1199
+ ]
1200
+ };
1171
1201
  }
1172
1202
  if (params.type) {
1173
1203
  const types = Array.isArray(params.type) ? params.type : [params.type];
@@ -858,12 +858,12 @@ export class HNSWIndex {
858
858
  // Cloud storage: Use pagination with native cloud APIs
859
859
  prodLog.info(`HNSW: Using cloud pagination strategy (${storageType})`);
860
860
  let hasMore = true;
861
- let cursor = undefined;
861
+ let offset = 0; // v5.7.11: Use offset-based pagination instead of cursor (bug fix for infinite loop)
862
862
  while (hasMore) {
863
863
  // Fetch batch of nouns from storage (cast needed as method is not in base interface)
864
864
  const result = await this.storage.getNounsWithPagination({
865
865
  limit: batchSize,
866
- cursor
866
+ offset // v5.7.11: Pass offset for proper pagination (previously passed cursor which was ignored)
867
867
  });
868
868
  // Set total count on first batch
869
869
  if (totalCount === undefined && result.totalCount !== undefined) {
@@ -912,7 +912,7 @@ export class HNSWIndex {
912
912
  }
913
913
  // Check for more data
914
914
  hasMore = result.hasMore;
915
- cursor = result.nextCursor;
915
+ offset += batchSize; // v5.7.11: Increment offset for next page
916
916
  }
917
917
  }
918
918
  const cacheInfo = shouldPreload
@@ -342,14 +342,14 @@ export class TypeAwareHNSWIndex {
342
342
  }
343
343
  // Load ALL nouns ONCE and route to correct type indexes
344
344
  // This is O(N) instead of O(42*N) from the previous parallel approach
345
- let cursor = undefined;
345
+ let offset = 0; // v5.7.11: Use offset-based pagination instead of cursor (bug fix for infinite loop)
346
346
  let hasMore = true;
347
347
  let totalLoaded = 0;
348
348
  const loadedByType = new Map();
349
349
  while (hasMore) {
350
350
  const result = await this.storage.getNounsWithPagination({
351
351
  limit: batchSize,
352
- cursor
352
+ offset // v5.7.11: Pass offset for proper pagination (previously passed cursor which was ignored)
353
353
  });
354
354
  // Route each noun to its type index
355
355
  for (const nounData of result.items) {
@@ -407,7 +407,7 @@ export class TypeAwareHNSWIndex {
407
407
  }
408
408
  }
409
409
  hasMore = result.hasMore;
410
- cursor = result.nextCursor;
410
+ offset += batchSize; // v5.7.11: Increment offset for next page
411
411
  // Progress logging
412
412
  if (totalLoaded % 1000 === 0) {
413
413
  prodLog.info(`Progress: ${totalLoaded.toLocaleString()} entities loaded...`);
@@ -48,7 +48,7 @@ export class OptimizedS3Search {
48
48
  }
49
49
  }
50
50
  // Determine if there are more items
51
- const hasMore = listResult.hasMore || nouns.length >= limit;
51
+ const hasMore = listResult.hasMore || nouns.length > limit; // v5.7.11: Fixed >= to > (was causing infinite loop)
52
52
  // Set next cursor
53
53
  let nextCursor;
54
54
  if (hasMore && nouns.length > 0) {
@@ -114,7 +114,7 @@ export class OptimizedS3Search {
114
114
  }
115
115
  }
116
116
  // Determine if there are more items
117
- const hasMore = listResult.hasMore || verbs.length >= limit;
117
+ const hasMore = listResult.hasMore || verbs.length > limit; // v5.7.11: Fixed >= to > (was causing infinite loop)
118
118
  // Set next cursor
119
119
  let nextCursor;
120
120
  if (hasMore && verbs.length > 0) {
@@ -879,7 +879,7 @@ export class BaseStorage extends BaseStorageAdapter {
879
879
  */
880
880
  async getNounsWithPagination(options) {
881
881
  await this.ensureInitialized();
882
- const { limit, offset = 0, filter } = options;
882
+ const { limit, offset = 0, filter } = options; // cursor intentionally not extracted (not yet implemented)
883
883
  const collectedNouns = [];
884
884
  const targetCount = offset + limit; // Early termination target
885
885
  // v5.5.0 BUG FIX: Only use optimization if counts are reliable
@@ -960,7 +960,7 @@ export class BaseStorage extends BaseStorageAdapter {
960
960
  }
961
961
  // Apply pagination (v5.5.0: Efficient slicing after early termination)
962
962
  const paginatedNouns = collectedNouns.slice(offset, offset + limit);
963
- const hasMore = collectedNouns.length >= targetCount;
963
+ const hasMore = collectedNouns.length > targetCount; // v5.7.11: Fixed >= to > (was causing infinite loop)
964
964
  return {
965
965
  items: paginatedNouns,
966
966
  totalCount: collectedNouns.length, // Accurate count of collected results
@@ -987,7 +987,7 @@ export class BaseStorage extends BaseStorageAdapter {
987
987
  */
988
988
  async getVerbsWithPagination(options) {
989
989
  await this.ensureInitialized();
990
- const { limit, offset = 0, filter } = options;
990
+ const { limit, offset = 0, filter } = options; // cursor intentionally not extracted (not yet implemented)
991
991
  const collectedVerbs = [];
992
992
  const targetCount = offset + limit; // Early termination target
993
993
  // v5.5.0 BUG FIX: Only use optimization if counts are reliable
@@ -1046,7 +1046,7 @@ export class BaseStorage extends BaseStorageAdapter {
1046
1046
  }
1047
1047
  // Apply pagination (v5.5.0: Efficient slicing after early termination)
1048
1048
  const paginatedVerbs = collectedVerbs.slice(offset, offset + limit);
1049
- const hasMore = collectedVerbs.length >= targetCount;
1049
+ const hasMore = collectedVerbs.length > targetCount; // v5.7.11: Fixed >= to > (was causing infinite loop)
1050
1050
  return {
1051
1051
  items: paginatedVerbs,
1052
1052
  totalCount: collectedVerbs.length, // Accurate count of collected results
@@ -1301,7 +1301,7 @@ export class BaseStorage extends BaseStorageAdapter {
1301
1301
  }
1302
1302
  // Apply pagination (slice for offset)
1303
1303
  const paginatedVerbs = collectedVerbs.slice(offset, offset + limit);
1304
- const hasMore = collectedVerbs.length >= targetCount;
1304
+ const hasMore = collectedVerbs.length > targetCount; // v5.7.11: Fixed >= to > (was causing infinite loop)
1305
1305
  return {
1306
1306
  items: paginatedVerbs,
1307
1307
  totalCount: collectedVerbs.length, // Accurate count of filtered results
@@ -39,9 +39,12 @@ export async function rebuildCounts(storage) {
39
39
  throw new Error('Storage adapter does not support getNounsWithPagination');
40
40
  }
41
41
  let hasMore = true;
42
- let cursor;
42
+ let offset = 0; // v5.7.11: Use offset-based pagination instead of cursor (bug fix for infinite loop)
43
43
  while (hasMore) {
44
- const result = await storageWithPagination.getNounsWithPagination({ limit: 100, cursor });
44
+ const result = await storageWithPagination.getNounsWithPagination({
45
+ limit: 100,
46
+ offset // v5.7.11: Pass offset for proper pagination (previously passed cursor which was ignored)
47
+ });
45
48
  for (const noun of result.items) {
46
49
  const metadata = await storage.getNounMetadata(noun.id);
47
50
  if (metadata?.noun) {
@@ -51,7 +54,7 @@ export async function rebuildCounts(storage) {
51
54
  }
52
55
  }
53
56
  hasMore = result.hasMore;
54
- cursor = result.nextCursor;
57
+ offset += 100; // v5.7.11: Increment offset for next page
55
58
  }
56
59
  console.log(` Found ${totalNouns} entities across ${entityCounts.size} types`);
57
60
  // Scan all verbs using pagination
@@ -60,9 +63,12 @@ export async function rebuildCounts(storage) {
60
63
  throw new Error('Storage adapter does not support getVerbsWithPagination');
61
64
  }
62
65
  hasMore = true;
63
- cursor = undefined;
66
+ offset = 0; // v5.7.11: Reset offset for verbs pagination
64
67
  while (hasMore) {
65
- const result = await storageWithPagination.getVerbsWithPagination({ limit: 100, cursor });
68
+ const result = await storageWithPagination.getVerbsWithPagination({
69
+ limit: 100,
70
+ offset // v5.7.11: Pass offset for proper pagination (previously passed cursor which was ignored)
71
+ });
66
72
  for (const verb of result.items) {
67
73
  if (verb.verb) {
68
74
  const verbType = verb.verb;
@@ -71,7 +77,7 @@ export async function rebuildCounts(storage) {
71
77
  }
72
78
  }
73
79
  hasMore = result.hasMore;
74
- cursor = result.nextCursor;
80
+ offset += 100; // v5.7.11: Increment offset for next page
75
81
  }
76
82
  console.log(` Found ${totalVerbs} relationships across ${verbCounts.size} types`);
77
83
  // Update storage adapter's in-memory counts FIRST
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@soulcraft/brainy",
3
- "version": "5.7.10",
3
+ "version": "5.7.12",
4
4
  "description": "Universal Knowledge Protocol™ - World's first Triple Intelligence database unifying vector, graph, and document search in one API. Stage 3 CANONICAL: 42 nouns × 127 verbs covering 96-97% of all human knowledge.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",