@soulcraft/brainy 3.6.0 β†’ 3.7.1

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.
@@ -3,7 +3,7 @@
3
3
  * Provides comprehensive audit trail for all Brainy operations
4
4
  */
5
5
  import { BaseAugmentation } from './brainyAugmentation.js';
6
- import { createHash } from 'node:crypto';
6
+ import { createHash } from '../universal/crypto.js';
7
7
  /**
8
8
  * Audit Log Augmentation
9
9
  */
@@ -3,6 +3,8 @@
3
3
  *
4
4
  * Discovers augmentations installed locally in node_modules
5
5
  * and built-in augmentations that ship with Brainy
6
+ *
7
+ * NOTE: This is a Node.js-only feature that requires filesystem access
6
8
  */
7
9
  import { AugmentationManifest } from '../manifest.js';
8
10
  export interface LocalAugmentation {
@@ -3,9 +3,27 @@
3
3
  *
4
4
  * Discovers augmentations installed locally in node_modules
5
5
  * and built-in augmentations that ship with Brainy
6
+ *
7
+ * NOTE: This is a Node.js-only feature that requires filesystem access
6
8
  */
7
- import { existsSync, readdirSync, readFileSync } from 'node:fs';
8
- import { join } from 'node:path';
9
+ // Node.js modules - dynamically imported to avoid bundler issues
10
+ let fs = null;
11
+ let path = null;
12
+ // Load Node.js modules if available
13
+ if (typeof window === 'undefined') {
14
+ try {
15
+ fs = await import('node:fs');
16
+ path = await import('node:path');
17
+ }
18
+ catch (e) {
19
+ // Will throw error in methods if not available
20
+ }
21
+ }
22
+ // Create compatibility layer for sync methods
23
+ const existsSync = fs?.existsSync || (() => { throw new Error('Filesystem not available'); });
24
+ const readdirSync = fs?.readdirSync || (() => { throw new Error('Filesystem not available'); });
25
+ const readFileSync = fs?.readFileSync || (() => { throw new Error('Filesystem not available'); });
26
+ const join = path?.join || ((...args) => args.join('/'));
9
27
  /**
10
28
  * Discovers augmentations installed locally
11
29
  */
@@ -10,9 +10,6 @@
10
10
  * 3. Model MUST produce consistent 384-dim embeddings
11
11
  * 4. System MUST fail fast if model unavailable in production
12
12
  */
13
- import { existsSync } from 'node:fs';
14
- import { stat } from 'node:fs/promises';
15
- import { join } from 'node:path';
16
13
  import { env } from '@huggingface/transformers';
17
14
  // CRITICAL: These values MUST NEVER CHANGE
18
15
  const CRITICAL_MODEL_CONFIG = {
@@ -87,8 +84,8 @@ export class ModelGuardian {
87
84
  this.configureTransformers();
88
85
  return;
89
86
  }
90
- // Step 2: In production, FAIL FAST
91
- if (process.env.NODE_ENV === 'production' && !process.env.BRAINY_ALLOW_RUNTIME_DOWNLOAD) {
87
+ // Step 2: In production, FAIL FAST (Node.js only)
88
+ if (typeof window === 'undefined' && process.env.NODE_ENV === 'production' && !process.env.BRAINY_ALLOW_RUNTIME_DOWNLOAD) {
92
89
  throw new Error('🚨 CRITICAL FAILURE: Transformer model not found in production!\n' +
93
90
  'The model is REQUIRED for Brainy to function.\n' +
94
91
  'Users CANNOT access their data without it.\n' +
@@ -124,7 +121,16 @@ export class ModelGuardian {
124
121
  * Verify the local model files exist and are correct
125
122
  */
126
123
  async verifyLocalModel() {
127
- const modelBasePath = join(this.modelPath, ...CRITICAL_MODEL_CONFIG.modelName.split('/'));
124
+ // Browser doesn't have local file access
125
+ if (typeof window !== 'undefined') {
126
+ console.log('⚠️ Model verification skipped in browser environment');
127
+ return false;
128
+ }
129
+ // Dynamically import Node.js modules
130
+ const fs = await import('node:fs');
131
+ const fsPromises = await import('node:fs/promises');
132
+ const path = await import('node:path');
133
+ const modelBasePath = path.join(this.modelPath, ...CRITICAL_MODEL_CONFIG.modelName.split('/'));
128
134
  console.log(`πŸ” Debug: Checking model at path: ${modelBasePath}`);
129
135
  console.log(`πŸ” Debug: Model path components: ${this.modelPath} + ${CRITICAL_MODEL_CONFIG.modelName.split('/')}`);
130
136
  // Check critical files
@@ -134,15 +140,15 @@ export class ModelGuardian {
134
140
  'config.json'
135
141
  ];
136
142
  for (const file of criticalFiles) {
137
- const filePath = join(modelBasePath, file);
143
+ const filePath = path.join(modelBasePath, file);
138
144
  console.log(`πŸ” Debug: Checking file: ${filePath}`);
139
- if (!existsSync(filePath)) {
145
+ if (!fs.existsSync(filePath)) {
140
146
  console.log(`❌ Missing critical file: ${file} at ${filePath}`);
141
147
  return false;
142
148
  }
143
149
  // Verify size for critical files
144
150
  if (CRITICAL_MODEL_CONFIG.modelSize[file]) {
145
- const stats = await stat(filePath);
151
+ const stats = await fsPromises.stat(filePath);
146
152
  const expectedSize = CRITICAL_MODEL_CONFIG.modelSize[file];
147
153
  if (Math.abs(stats.size - expectedSize) > 1000) { // Allow 1KB variance
148
154
  console.error(`❌ CRITICAL: Model file size mismatch!\n` +
@@ -220,22 +226,34 @@ export class ModelGuardian {
220
226
  * Detect where models should be stored
221
227
  */
222
228
  detectModelPath() {
223
- const candidates = [
224
- process.env.BRAINY_MODELS_PATH,
225
- './models',
226
- join(process.cwd(), 'models'),
227
- join(process.env.HOME || '', '.brainy', 'models'),
228
- '/opt/models', // Lambda/container path
229
- env.cacheDir
230
- ];
231
- for (const path of candidates) {
232
- if (path && existsSync(path)) {
233
- const modelPath = join(path, ...CRITICAL_MODEL_CONFIG.modelName.split('/'));
234
- if (existsSync(join(modelPath, 'onnx', 'model.onnx'))) {
235
- return path; // Return the models directory, not its parent
229
+ // Browser always uses default path
230
+ if (typeof window !== 'undefined') {
231
+ return './models';
232
+ }
233
+ // Use require for synchronous access in Node.js
234
+ try {
235
+ const fs = require('node:fs');
236
+ const path = require('node:path');
237
+ const candidates = [
238
+ process.env.BRAINY_MODELS_PATH,
239
+ './models',
240
+ path.join(process.cwd(), 'models'),
241
+ path.join(process.env.HOME || '', '.brainy', 'models'),
242
+ '/opt/models', // Lambda/container path
243
+ env.cacheDir
244
+ ];
245
+ for (const candidatePath of candidates) {
246
+ if (candidatePath && fs.existsSync(candidatePath)) {
247
+ const modelPath = path.join(candidatePath, ...CRITICAL_MODEL_CONFIG.modelName.split('/'));
248
+ if (fs.existsSync(path.join(modelPath, 'onnx', 'model.onnx'))) {
249
+ return candidatePath; // Return the models directory, not its parent
250
+ }
236
251
  }
237
252
  }
238
253
  }
254
+ catch (e) {
255
+ // If Node.js modules not available, return default
256
+ }
239
257
  // Default
240
258
  return './models';
241
259
  }
@@ -59,13 +59,44 @@ class NodeFS {
59
59
  await nodeFs.access(path, mode);
60
60
  }
61
61
  }
62
+ // Browser-safe no-op implementation
63
+ class BrowserFS {
64
+ async readFile(path, encoding = 'utf-8') {
65
+ throw new Error('File system operations not available in browser. Use OPFS, Memory, or S3 storage adapters instead.');
66
+ }
67
+ async writeFile(path, data, encoding = 'utf-8') {
68
+ throw new Error('File system operations not available in browser. Use OPFS, Memory, or S3 storage adapters instead.');
69
+ }
70
+ async mkdir(path, options = { recursive: true }) {
71
+ throw new Error('File system operations not available in browser. Use OPFS, Memory, or S3 storage adapters instead.');
72
+ }
73
+ async exists(path) {
74
+ return false; // Always return false in browser
75
+ }
76
+ async readdir(path, options) {
77
+ if (options?.withFileTypes) {
78
+ return [];
79
+ }
80
+ return [];
81
+ }
82
+ async unlink(path) {
83
+ throw new Error('File system operations not available in browser. Use OPFS, Memory, or S3 storage adapters instead.');
84
+ }
85
+ async stat(path) {
86
+ throw new Error('File system operations not available in browser. Use OPFS, Memory, or S3 storage adapters instead.');
87
+ }
88
+ async access(path, mode) {
89
+ throw new Error('File system operations not available in browser. Use OPFS, Memory, or S3 storage adapters instead.');
90
+ }
91
+ }
62
92
  // Create the appropriate filesystem implementation
63
93
  let fsImpl;
64
94
  if (isNode() && nodeFs) {
65
95
  fsImpl = new NodeFS();
66
96
  }
67
97
  else {
68
- throw new Error('File system operations not available. Framework bundlers should provide fs polyfills or use storage adapters like OPFS, Memory, or S3.');
98
+ // Use browser-safe no-op implementation instead of throwing
99
+ fsImpl = new BrowserFS();
69
100
  }
70
101
  // Export the filesystem operations
71
102
  export const readFile = fsImpl.readFile.bind(fsImpl);
@@ -161,8 +161,8 @@ export class TransformerEmbedding {
161
161
  // Use dynamic import instead of require for ES modules compatibility
162
162
  const { createRequire } = await import('module');
163
163
  const require = createRequire(import.meta.url);
164
- const path = require('path');
165
- const fs = require('fs');
164
+ const path = require('node:path');
165
+ const fs = require('node:fs');
166
166
  // Try to resolve the package location
167
167
  try {
168
168
  const brainyPackagePath = require.resolve('@soulcraft/brainy/package.json');
@@ -5,7 +5,31 @@
5
5
  * Only enforces universal truths, learns everything else
6
6
  */
7
7
  import { NounType, VerbType } from '../types/graphTypes.js';
8
- import * as os from 'node:os';
8
+ // Dynamic import for Node.js os module
9
+ let os = null;
10
+ if (typeof window === 'undefined') {
11
+ try {
12
+ os = await import('node:os');
13
+ }
14
+ catch (e) {
15
+ // OS module not available
16
+ }
17
+ }
18
+ // Browser-safe memory detection
19
+ const getSystemMemory = () => {
20
+ if (os) {
21
+ return os.totalmem();
22
+ }
23
+ // Browser fallback: assume 4GB
24
+ return 4 * 1024 * 1024 * 1024;
25
+ };
26
+ const getAvailableMemory = () => {
27
+ if (os) {
28
+ return os.freemem();
29
+ }
30
+ // Browser fallback: assume 2GB available
31
+ return 2 * 1024 * 1024 * 1024;
32
+ };
9
33
  /**
10
34
  * Auto-configured limits based on system resources
11
35
  * These adapt to available memory and observed performance
@@ -16,8 +40,8 @@ class ValidationConfig {
16
40
  this.avgQueryTime = 0;
17
41
  this.queryCount = 0;
18
42
  // Auto-configure based on system resources
19
- const totalMemory = os.totalmem();
20
- const availableMemory = os.freemem();
43
+ const totalMemory = getSystemMemory();
44
+ const availableMemory = getAvailableMemory();
21
45
  // Scale limits based on available memory
22
46
  // 1GB = 10K limit, 8GB = 80K limit, etc.
23
47
  this.maxLimit = Math.min(100000, // Absolute max for safety
@@ -179,8 +203,8 @@ export function getValidationConfig() {
179
203
  maxLimit: config.maxLimit,
180
204
  maxQueryLength: config.maxQueryLength,
181
205
  maxVectorDimensions: config.maxVectorDimensions,
182
- systemMemory: os.totalmem(),
183
- availableMemory: os.freemem()
206
+ systemMemory: getSystemMemory(),
207
+ availableMemory: getAvailableMemory()
184
208
  };
185
209
  }
186
210
  /**
@@ -4,8 +4,7 @@
4
4
  * performance tracking, and multiple transport support
5
5
  */
6
6
  import { performance } from 'perf_hooks';
7
- import { hostname } from 'node:os';
8
- import { randomUUID } from 'node:crypto';
7
+ import { randomUUID } from '../universal/crypto.js';
9
8
  export var LogLevel;
10
9
  (function (LogLevel) {
11
10
  LogLevel[LogLevel["SILENT"] = -1] = "SILENT";
@@ -214,9 +213,21 @@ export class StructuredLogger {
214
213
  };
215
214
  }
216
215
  if (this.config.includeHost) {
217
- entry.host = hostname();
216
+ // Use dynamic import for hostname (Node.js only)
217
+ if (typeof window === 'undefined') {
218
+ try {
219
+ const os = require('node:os');
220
+ entry.host = os.hostname();
221
+ }
222
+ catch {
223
+ entry.host = 'unknown';
224
+ }
225
+ }
226
+ else {
227
+ entry.host = window.location?.hostname || 'browser';
228
+ }
218
229
  }
219
- if (this.config.includeMemory) {
230
+ if (this.config.includeMemory && typeof process !== 'undefined' && process.memoryUsage) {
220
231
  const mem = process.memoryUsage();
221
232
  entry.performance = {
222
233
  memory: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@soulcraft/brainy",
3
- "version": "3.6.0",
3
+ "version": "3.7.1",
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",
@@ -41,6 +41,11 @@
41
41
  "types": "./dist/universal/index.d.ts"
42
42
  }
43
43
  },
44
+ "browser": {
45
+ "./dist/distributed": false,
46
+ "./dist/cli": false,
47
+ "./dist/scripts": false
48
+ },
44
49
  "engines": {
45
50
  "node": "22.x"
46
51
  },