@soulcraft/brainy 4.11.1 → 5.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.
@@ -24,6 +24,30 @@ function getFileSystemPath(options) {
24
24
  './brainy-data' // Zero-config fallback
25
25
  );
26
26
  }
27
+ /**
28
+ * Wrap any storage adapter with TypeAwareStorageAdapter
29
+ * v5.0.0: TypeAware is now the standard interface for ALL storage adapters
30
+ * This provides type-first organization, fixed-size type counts, and efficient type queries
31
+ *
32
+ * @param underlying - The base storage adapter (memory, filesystem, S3, etc.)
33
+ * @param options - Storage options (for COW configuration)
34
+ * @param verbose - Optional verbose logging
35
+ * @returns TypeAwareStorageAdapter wrapping the underlying storage
36
+ */
37
+ async function wrapWithTypeAware(underlying, options, verbose = false) {
38
+ const wrapped = new TypeAwareStorageAdapter({
39
+ underlyingStorage: underlying,
40
+ verbose
41
+ });
42
+ // Initialize COW if enabled
43
+ if (options?.enableCOW && typeof wrapped.initializeCOW === 'function') {
44
+ await wrapped.initializeCOW({
45
+ branch: options.branch || 'main',
46
+ enableCompression: options.enableCompression !== false
47
+ });
48
+ }
49
+ return wrapped;
50
+ }
27
51
  /**
28
52
  * Create a storage adapter based on the environment and configuration
29
53
  * @param options Options for creating the storage adapter
@@ -32,70 +56,70 @@ function getFileSystemPath(options) {
32
56
  export async function createStorage(options = {}) {
33
57
  // If memory storage is forced, use it regardless of other options
34
58
  if (options.forceMemoryStorage) {
35
- console.log('Using memory storage (forced)');
36
- return new MemoryStorage();
59
+ console.log('Using memory storage (forced) + TypeAware wrapper');
60
+ return await wrapWithTypeAware(new MemoryStorage(), options);
37
61
  }
38
62
  // If file system storage is forced, use it regardless of other options
39
63
  if (options.forceFileSystemStorage) {
40
64
  if (isBrowser()) {
41
65
  console.warn('FileSystemStorage is not available in browser environments, falling back to memory storage');
42
- return new MemoryStorage();
66
+ return await wrapWithTypeAware(new MemoryStorage(), options);
43
67
  }
44
68
  const fsPath = getFileSystemPath(options);
45
- console.log(`Using file system storage (forced): ${fsPath}`);
69
+ console.log(`Using file system storage (forced): ${fsPath} + TypeAware wrapper`);
46
70
  try {
47
71
  const { FileSystemStorage } = await import('./adapters/fileSystemStorage.js');
48
- return new FileSystemStorage(fsPath);
72
+ return await wrapWithTypeAware(new FileSystemStorage(fsPath), options);
49
73
  }
50
74
  catch (error) {
51
75
  console.warn('Failed to load FileSystemStorage, falling back to memory storage:', error);
52
- return new MemoryStorage();
76
+ return await wrapWithTypeAware(new MemoryStorage(), options);
53
77
  }
54
78
  }
55
79
  // If a specific storage type is specified, use it
56
80
  if (options.type && options.type !== 'auto') {
57
81
  switch (options.type) {
58
82
  case 'memory':
59
- console.log('Using memory storage');
60
- return new MemoryStorage();
83
+ console.log('Using memory storage + TypeAware wrapper');
84
+ return await wrapWithTypeAware(new MemoryStorage(), options);
61
85
  case 'opfs': {
62
86
  // Check if OPFS is available
63
87
  const opfsStorage = new OPFSStorage();
64
88
  if (opfsStorage.isOPFSAvailable()) {
65
- console.log('Using OPFS storage');
89
+ console.log('Using OPFS storage + TypeAware wrapper');
66
90
  await opfsStorage.init();
67
91
  // Request persistent storage if specified
68
92
  if (options.requestPersistentStorage) {
69
93
  const isPersistent = await opfsStorage.requestPersistentStorage();
70
94
  console.log(`Persistent storage ${isPersistent ? 'granted' : 'denied'}`);
71
95
  }
72
- return opfsStorage;
96
+ return await wrapWithTypeAware(opfsStorage, options);
73
97
  }
74
98
  else {
75
99
  console.warn('OPFS storage is not available, falling back to memory storage');
76
- return new MemoryStorage();
100
+ return await wrapWithTypeAware(new MemoryStorage(), options);
77
101
  }
78
102
  }
79
103
  case 'filesystem': {
80
104
  if (isBrowser()) {
81
105
  console.warn('FileSystemStorage is not available in browser environments, falling back to memory storage');
82
- return new MemoryStorage();
106
+ return await wrapWithTypeAware(new MemoryStorage(), options);
83
107
  }
84
108
  const fsPath = getFileSystemPath(options);
85
- console.log(`Using file system storage: ${fsPath}`);
109
+ console.log(`Using file system storage: ${fsPath} + TypeAware wrapper`);
86
110
  try {
87
111
  const { FileSystemStorage } = await import('./adapters/fileSystemStorage.js');
88
- return new FileSystemStorage(fsPath);
112
+ return await wrapWithTypeAware(new FileSystemStorage(fsPath));
89
113
  }
90
114
  catch (error) {
91
115
  console.warn('Failed to load FileSystemStorage, falling back to memory storage:', error);
92
- return new MemoryStorage();
116
+ return await wrapWithTypeAware(new MemoryStorage(), options);
93
117
  }
94
118
  }
95
119
  case 's3':
96
120
  if (options.s3Storage) {
97
- console.log('Using Amazon S3 storage');
98
- return new S3CompatibleStorage({
121
+ console.log('Using Amazon S3 storage + TypeAware wrapper');
122
+ return await wrapWithTypeAware(new S3CompatibleStorage({
99
123
  bucketName: options.s3Storage.bucketName,
100
124
  region: options.s3Storage.region,
101
125
  accessKeyId: options.s3Storage.accessKeyId,
@@ -104,26 +128,26 @@ export async function createStorage(options = {}) {
104
128
  serviceType: 's3',
105
129
  operationConfig: options.operationConfig,
106
130
  cacheConfig: options.cacheConfig
107
- });
131
+ }));
108
132
  }
109
133
  else {
110
134
  console.warn('S3 storage configuration is missing, falling back to memory storage');
111
- return new MemoryStorage();
135
+ return await wrapWithTypeAware(new MemoryStorage(), options);
112
136
  }
113
137
  case 'r2':
114
138
  if (options.r2Storage) {
115
- console.log('Using Cloudflare R2 storage (dedicated adapter)');
116
- return new R2Storage({
139
+ console.log('Using Cloudflare R2 storage (dedicated adapter) + TypeAware wrapper');
140
+ return await wrapWithTypeAware(new R2Storage({
117
141
  bucketName: options.r2Storage.bucketName,
118
142
  accountId: options.r2Storage.accountId,
119
143
  accessKeyId: options.r2Storage.accessKeyId,
120
144
  secretAccessKey: options.r2Storage.secretAccessKey,
121
145
  cacheConfig: options.cacheConfig
122
- });
146
+ }));
123
147
  }
124
148
  else {
125
149
  console.warn('R2 storage configuration is missing, falling back to memory storage');
126
- return new MemoryStorage();
150
+ return await wrapWithTypeAware(new MemoryStorage(), options);
127
151
  }
128
152
  case 'gcs-native':
129
153
  // DEPRECATED: gcs-native is deprecated in favor of just 'gcs'
@@ -136,14 +160,14 @@ export async function createStorage(options = {}) {
136
160
  const gcsLegacy = options.gcsStorage;
137
161
  if (!gcsNative && !gcsLegacy) {
138
162
  console.warn('GCS storage configuration is missing, falling back to memory storage');
139
- return new MemoryStorage();
163
+ return await wrapWithTypeAware(new MemoryStorage(), options);
140
164
  }
141
165
  // If using legacy gcsStorage with HMAC keys, use S3-compatible adapter
142
166
  if (gcsLegacy && gcsLegacy.accessKeyId && gcsLegacy.secretAccessKey) {
143
167
  console.warn('⚠️ GCS with HMAC keys detected. Consider using gcsNativeStorage with ADC instead.');
144
168
  console.warn(' Native GCS with Application Default Credentials is recommended for better performance and security.');
145
169
  // Use S3-compatible storage for HMAC keys
146
- return new S3CompatibleStorage({
170
+ return await wrapWithTypeAware(new S3CompatibleStorage({
147
171
  bucketName: gcsLegacy.bucketName,
148
172
  region: gcsLegacy.region,
149
173
  endpoint: gcsLegacy.endpoint || 'https://storage.googleapis.com',
@@ -151,12 +175,12 @@ export async function createStorage(options = {}) {
151
175
  secretAccessKey: gcsLegacy.secretAccessKey,
152
176
  serviceType: 'gcs',
153
177
  cacheConfig: options.cacheConfig
154
- });
178
+ }));
155
179
  }
156
180
  // Use native GCS SDK (the correct default!)
157
181
  const config = gcsNative || gcsLegacy;
158
- console.log('Using Google Cloud Storage (native SDK)');
159
- return new GcsStorage({
182
+ console.log('Using Google Cloud Storage (native SDK) + TypeAware wrapper');
183
+ return await wrapWithTypeAware(new GcsStorage({
160
184
  bucketName: config.bucketName,
161
185
  keyFilename: gcsNative?.keyFilename,
162
186
  credentials: gcsNative?.credentials,
@@ -165,50 +189,43 @@ export async function createStorage(options = {}) {
165
189
  skipInitialScan: gcsNative?.skipInitialScan,
166
190
  skipCountsFile: gcsNative?.skipCountsFile,
167
191
  cacheConfig: options.cacheConfig
168
- });
192
+ }));
169
193
  }
170
194
  case 'azure':
171
195
  if (options.azureStorage) {
172
- console.log('Using Azure Blob Storage (native SDK)');
173
- return new AzureBlobStorage({
196
+ console.log('Using Azure Blob Storage (native SDK) + TypeAware wrapper');
197
+ return await wrapWithTypeAware(new AzureBlobStorage({
174
198
  containerName: options.azureStorage.containerName,
175
199
  accountName: options.azureStorage.accountName,
176
200
  accountKey: options.azureStorage.accountKey,
177
201
  connectionString: options.azureStorage.connectionString,
178
202
  sasToken: options.azureStorage.sasToken,
179
203
  cacheConfig: options.cacheConfig
180
- });
204
+ }));
181
205
  }
182
206
  else {
183
207
  console.warn('Azure storage configuration is missing, falling back to memory storage');
184
- return new MemoryStorage();
208
+ return await wrapWithTypeAware(new MemoryStorage(), options);
185
209
  }
186
- case 'type-aware': {
187
- console.log('Using Type-Aware Storage (type-first architecture)');
188
- // Create underlying storage adapter
189
- const underlyingType = options.typeAwareStorage?.underlyingType || 'auto';
190
- const underlyingOptions = options.typeAwareStorage?.underlyingOptions || {};
191
- // Recursively create the underlying storage
192
- const underlying = await createStorage({
193
- ...underlyingOptions,
194
- type: underlyingType
195
- });
196
- // Wrap with TypeAwareStorageAdapter
197
- // Cast to BaseStorage since all concrete storage adapters extend BaseStorage
198
- return new TypeAwareStorageAdapter({
199
- underlyingStorage: underlying,
200
- verbose: options.typeAwareStorage?.verbose || false
210
+ case 'type-aware':
211
+ // v5.0.0: TypeAware is now the default for ALL adapters
212
+ // Redirect to the underlying type instead
213
+ console.warn('⚠️ type-aware is deprecated in v5.0.0 - TypeAware is now always enabled.');
214
+ console.warn(' Just use the underlying storage type (e.g., "filesystem", "s3", etc.)');
215
+ // Recursively create storage with underlying type
216
+ return await createStorage({
217
+ ...options,
218
+ type: options.typeAwareStorage?.underlyingType || 'auto'
201
219
  });
202
- }
203
220
  default:
204
221
  console.warn(`Unknown storage type: ${options.type}, falling back to memory storage`);
205
- return new MemoryStorage();
222
+ return await wrapWithTypeAware(new MemoryStorage(), options);
206
223
  }
207
224
  }
208
225
  // If custom S3-compatible storage is specified, use it
209
226
  if (options.customS3Storage) {
210
- console.log(`Using custom S3-compatible storage: ${options.customS3Storage.serviceType || 'custom'}`);
211
- return new S3CompatibleStorage({
227
+ console.log(`Using custom S3-compatible storage: ${options.customS3Storage.serviceType || 'custom'} + TypeAware wrapper`);
228
+ return await wrapWithTypeAware(new S3CompatibleStorage({
212
229
  bucketName: options.customS3Storage.bucketName,
213
230
  region: options.customS3Storage.region,
214
231
  endpoint: options.customS3Storage.endpoint,
@@ -216,23 +233,23 @@ export async function createStorage(options = {}) {
216
233
  secretAccessKey: options.customS3Storage.secretAccessKey,
217
234
  serviceType: options.customS3Storage.serviceType || 'custom',
218
235
  cacheConfig: options.cacheConfig
219
- });
236
+ }));
220
237
  }
221
238
  // If R2 storage is specified, use it
222
239
  if (options.r2Storage) {
223
- console.log('Using Cloudflare R2 storage (dedicated adapter)');
224
- return new R2Storage({
240
+ console.log('Using Cloudflare R2 storage (dedicated adapter) + TypeAware wrapper');
241
+ return await wrapWithTypeAware(new R2Storage({
225
242
  bucketName: options.r2Storage.bucketName,
226
243
  accountId: options.r2Storage.accountId,
227
244
  accessKeyId: options.r2Storage.accessKeyId,
228
245
  secretAccessKey: options.r2Storage.secretAccessKey,
229
246
  cacheConfig: options.cacheConfig
230
- });
247
+ }));
231
248
  }
232
249
  // If S3 storage is specified, use it
233
250
  if (options.s3Storage) {
234
- console.log('Using Amazon S3 storage');
235
- return new S3CompatibleStorage({
251
+ console.log('Using Amazon S3 storage + TypeAware wrapper');
252
+ return await wrapWithTypeAware(new S3CompatibleStorage({
236
253
  bucketName: options.s3Storage.bucketName,
237
254
  region: options.s3Storage.region,
238
255
  accessKeyId: options.s3Storage.accessKeyId,
@@ -240,7 +257,7 @@ export async function createStorage(options = {}) {
240
257
  sessionToken: options.s3Storage.sessionToken,
241
258
  serviceType: 's3',
242
259
  cacheConfig: options.cacheConfig
243
- });
260
+ }));
244
261
  }
245
262
  // If GCS storage is specified (native or legacy S3-compatible)
246
263
  // Prefer gcsNativeStorage, but also accept gcsStorage for backward compatibility
@@ -252,8 +269,8 @@ export async function createStorage(options = {}) {
252
269
  console.warn('⚠️ GCS with HMAC keys detected. Consider using gcsNativeStorage with ADC instead.');
253
270
  console.warn(' Native GCS with Application Default Credentials is recommended for better performance and security.');
254
271
  // Use S3-compatible storage for HMAC keys
255
- console.log('Using Google Cloud Storage (S3-compatible with HMAC - auto-detected)');
256
- return new S3CompatibleStorage({
272
+ console.log('Using Google Cloud Storage (S3-compatible with HMAC - auto-detected) + TypeAware wrapper');
273
+ return await wrapWithTypeAware(new S3CompatibleStorage({
257
274
  bucketName: gcsLegacy.bucketName,
258
275
  region: gcsLegacy.region,
259
276
  endpoint: gcsLegacy.endpoint || 'https://storage.googleapis.com',
@@ -261,12 +278,12 @@ export async function createStorage(options = {}) {
261
278
  secretAccessKey: gcsLegacy.secretAccessKey,
262
279
  serviceType: 'gcs',
263
280
  cacheConfig: options.cacheConfig
264
- });
281
+ }));
265
282
  }
266
283
  // Use native GCS SDK (the correct default!)
267
284
  const config = gcsNative || gcsLegacy;
268
- console.log('Using Google Cloud Storage (native SDK - auto-detected)');
269
- return new GcsStorage({
285
+ console.log('Using Google Cloud Storage (native SDK - auto-detected) + TypeAware wrapper');
286
+ return await wrapWithTypeAware(new GcsStorage({
270
287
  bucketName: config.bucketName,
271
288
  keyFilename: gcsNative?.keyFilename,
272
289
  credentials: gcsNative?.credentials,
@@ -275,19 +292,19 @@ export async function createStorage(options = {}) {
275
292
  skipInitialScan: gcsNative?.skipInitialScan,
276
293
  skipCountsFile: gcsNative?.skipCountsFile,
277
294
  cacheConfig: options.cacheConfig
278
- });
295
+ }));
279
296
  }
280
297
  // If Azure storage is specified, use it
281
298
  if (options.azureStorage) {
282
- console.log('Using Azure Blob Storage (native SDK)');
283
- return new AzureBlobStorage({
299
+ console.log('Using Azure Blob Storage (native SDK) + TypeAware wrapper');
300
+ return await wrapWithTypeAware(new AzureBlobStorage({
284
301
  containerName: options.azureStorage.containerName,
285
302
  accountName: options.azureStorage.accountName,
286
303
  accountKey: options.azureStorage.accountKey,
287
304
  connectionString: options.azureStorage.connectionString,
288
305
  sasToken: options.azureStorage.sasToken,
289
306
  cacheConfig: options.cacheConfig
290
- });
307
+ }));
291
308
  }
292
309
  // Auto-detect the best storage adapter based on the environment
293
310
  // First, check if we're in Node.js (prioritize for test environments)
@@ -298,10 +315,10 @@ export async function createStorage(options = {}) {
298
315
  process.versions &&
299
316
  process.versions.node) {
300
317
  const fsPath = getFileSystemPath(options);
301
- console.log(`Using file system storage (auto-detected): ${fsPath}`);
318
+ console.log(`Using file system storage (auto-detected): ${fsPath} + TypeAware wrapper`);
302
319
  try {
303
320
  const { FileSystemStorage } = await import('./adapters/fileSystemStorage.js');
304
- return new FileSystemStorage(fsPath);
321
+ return await wrapWithTypeAware(new FileSystemStorage(fsPath));
305
322
  }
306
323
  catch (fsError) {
307
324
  console.warn('Failed to load FileSystemStorage, falling back to memory storage:', fsError);
@@ -317,19 +334,19 @@ export async function createStorage(options = {}) {
317
334
  if (isBrowser()) {
318
335
  const opfsStorage = new OPFSStorage();
319
336
  if (opfsStorage.isOPFSAvailable()) {
320
- console.log('Using OPFS storage (auto-detected)');
337
+ console.log('Using OPFS storage (auto-detected) + TypeAware wrapper');
321
338
  await opfsStorage.init();
322
339
  // Request persistent storage if specified
323
340
  if (options.requestPersistentStorage) {
324
341
  const isPersistent = await opfsStorage.requestPersistentStorage();
325
342
  console.log(`Persistent storage ${isPersistent ? 'granted' : 'denied'}`);
326
343
  }
327
- return opfsStorage;
344
+ return await wrapWithTypeAware(opfsStorage, options);
328
345
  }
329
346
  }
330
347
  // Finally, fall back to memory storage
331
- console.log('Using memory storage (auto-detected)');
332
- return new MemoryStorage();
348
+ console.log('Using memory storage (auto-detected) + TypeAware wrapper');
349
+ return await wrapWithTypeAware(new MemoryStorage(), options);
333
350
  }
334
351
  /**
335
352
  * Export storage adapters
@@ -458,6 +458,8 @@ export interface BrainyConfig {
458
458
  storage?: {
459
459
  type: 'auto' | 'memory' | 'filesystem' | 's3' | 'r2' | 'opfs' | 'gcs';
460
460
  options?: any;
461
+ branch?: string;
462
+ enableCOW?: boolean;
461
463
  };
462
464
  model?: {
463
465
  type: 'fast' | 'accurate' | 'balanced' | 'custom';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@soulcraft/brainy",
3
- "version": "4.11.1",
3
+ "version": "5.0.0",
4
4
  "description": "Universal Knowledge Protocol™ - World's first Triple Intelligence database unifying vector, graph, and document search in one API. 31 nouns × 40 verbs for infinite expressiveness.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",