@soulcraft/brainy 0.12.0 → 0.14.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.
package/README.demo.md CHANGED
@@ -35,7 +35,7 @@ npx http-server
35
35
  If you see the error "Could not load Brainy library. Please ensure the project is built and served over HTTP", check the
36
36
  following:
37
37
 
38
- 1. Make sure you've built the project with `npm run build:all`
38
+ 1. Make sure you've built the project with `npm run build && npm run build:browser`
39
39
  2. Ensure you're accessing the demo through HTTP (not by opening the file directly)
40
40
  3. Check your browser's console for additional error messages
41
41
 
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
  [![Node.js](https://img.shields.io/badge/node-%3E%3D24.4.0-brightgreen.svg)](https://nodejs.org/)
7
7
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.4.5-blue.svg)](https://www.typescriptlang.org/)
8
8
  [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](CONTRIBUTING.md)
9
- [![npm](https://img.shields.io/badge/npm-v0.12.0-blue.svg)](https://www.npmjs.com/package/@soulcraft/brainy)
9
+ [![npm](https://img.shields.io/badge/npm-v0.14.0-blue.svg)](https://www.npmjs.com/package/@soulcraft/brainy)
10
10
 
11
11
  [//]: # ([![Cartographer](https://img.shields.io/badge/Cartographer-Official%20Standard-brightgreen)](https://github.com/sodal-project/cartographer))
12
12
 
@@ -62,12 +62,7 @@ GitHub Pages that showcases Brainy's main features.
62
62
  npm install @soulcraft/brainy
63
63
  ```
64
64
 
65
- TensorFlow.js packages are included as required dependencies and will be automatically installed. If you encounter
66
- dependency conflicts, you may need to use the `--legacy-peer-deps` flag:
67
-
68
- ```bash
69
- npm install @soulcraft/brainy --legacy-peer-deps
70
- ```
65
+ TensorFlow.js packages are included as bundled dependencies and will be automatically installed without any additional configuration.
71
66
 
72
67
  ## 🏁 Quick Start
73
68
 
@@ -110,14 +105,9 @@ import { BrainyData } from '@soulcraft/brainy'
110
105
 
111
106
  // Minified version for production
112
107
  import { BrainyData } from '@soulcraft/brainy/min'
113
-
114
- // CLI functionality (only imported when needed)
115
- import '@soulcraft/brainy/cli'
116
108
  ```
117
109
 
118
- > **Note**: The CLI functionality (4MB) is not included in the standard import, reducing the bundle size for browser and
119
- > Node.js applications. The CLI is only built and loaded when explicitly imported or when using the command-line
120
- > interface.
110
+ > **Note**: The CLI functionality is available as a separate package `@soulcraft/brainy-cli` to reduce the bundle size of the main package. Install it globally with `npm install -g @soulcraft/brainy-cli` to use the command-line interface.
121
111
 
122
112
  ### Browser Usage
123
113
 
@@ -417,18 +407,13 @@ brainy visualize --root <id> --depth 3
417
407
 
418
408
  ### Using the CLI in Your Code
419
409
 
420
- If you need to use the CLI functionality in your code, you can import it explicitly:
410
+ The CLI functionality is available as a separate package `@soulcraft/brainy-cli`. If you need CLI functionality in your application, install the CLI package:
421
411
 
422
- ```typescript
423
- // Import the CLI functionality
424
- import '@soulcraft/brainy/cli'
425
-
426
- // Now you can use the CLI programmatically
427
- // ...
412
+ ```bash
413
+ npm install @soulcraft/brainy-cli
428
414
  ```
429
415
 
430
- This will only build and load the CLI when you explicitly import it, keeping your bundle size small when you don't need
431
- the CLI.
416
+ Then you can use the CLI commands programmatically or through the command line interface.
432
417
 
433
418
  ### Available Commands
434
419
 
@@ -89,6 +89,17 @@ export interface BrainyDataConfig {
89
89
  */
90
90
  autoConnect?: boolean;
91
91
  };
92
+ /**
93
+ * Logging configuration
94
+ */
95
+ logging?: {
96
+ /**
97
+ * Whether to enable verbose logging
98
+ * When false, suppresses non-essential log messages like model loading progress
99
+ * Default: true
100
+ */
101
+ verbose?: boolean;
102
+ };
92
103
  }
93
104
  export declare class BrainyData<T = any> implements BrainyDataInterface<T> {
94
105
  private index;
@@ -102,6 +113,7 @@ export declare class BrainyData<T = any> implements BrainyDataInterface<T> {
102
113
  private storageConfig;
103
114
  private useOptimizedIndex;
104
115
  private _dimensions;
116
+ private loggingConfig;
105
117
  private remoteServerConfig;
106
118
  private serverSearchConduit;
107
119
  private serverConnection;
@@ -1 +1 @@
1
- {"version":3,"file":"fileSystemStorage.d.ts","sourceRoot":"","sources":["../../src/storage/fileSystemStorage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AA4DrE;;GAEG;AACH,qBAAa,iBAAkB,YAAW,cAAc;IACtD,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,WAAW,CAAQ;IAC3B,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,aAAa,CAAQ;gBAEjB,aAAa,CAAC,EAAE,MAAM;IAelC;;OAEG;IACU,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAoDpB,qBAAqB;IAWnC,OAAO,CAAC,WAAW;IA6BN,QAAQ,CACnB,IAAI,EAAE,QAAQ,GAAG;QAAE,QAAQ,CAAC,EAAE;YAAE,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,GAChD,OAAO,CAAC,IAAI,CAAC;IAQH,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAyB7C,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBrC,WAAW,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IA+B/C;;;;OAIG;IACU,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IA8CzD,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAMrD;;;;OAIG;IACU,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAc9C,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAMrE;;;;OAIG;IACU,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAMrE;;;;OAIG;IACU,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAMlD,WAAW,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAoBnC,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAalD;;;;OAIG;IACU,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAOnE;;;;OAIG;IACU,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC;IAc5C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA4DtB,gBAAgB,IAAI,OAAO,CAAC;QACvC,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,EAAE,MAAM,CAAA;QACZ,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;QACpB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;KAC9B,CAAC;CAyCH"}
1
+ {"version":3,"file":"fileSystemStorage.d.ts","sourceRoot":"","sources":["../../src/storage/fileSystemStorage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AA4DrE;;GAEG;AACH,qBAAa,iBAAkB,YAAW,cAAc;IACtD,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,WAAW,CAAQ;IAC3B,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,aAAa,CAAQ;gBAEjB,aAAa,CAAC,EAAE,MAAM;IAelC;;OAEG;IACU,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YA2DpB,qBAAqB;IAWnC,OAAO,CAAC,WAAW;IA6BN,QAAQ,CACnB,IAAI,EAAE,QAAQ,GAAG;QAAE,QAAQ,CAAC,EAAE;YAAE,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,GAChD,OAAO,CAAC,IAAI,CAAC;IAQH,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAyB7C,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBrC,WAAW,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IA+B/C;;;;OAIG;IACU,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IA8CzD,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAMrD;;;;OAIG;IACU,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAc9C,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAMrE;;;;OAIG;IACU,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAMrE;;;;OAIG;IACU,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAMlD,WAAW,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAoBnC,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAalD;;;;OAIG;IACU,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAOnE;;;;OAIG;IACU,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC;IAc5C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA4DtB,gBAAgB,IAAI,OAAO,CAAC;QACvC,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,EAAE,MAAM,CAAA;QACZ,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;QACpB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;KAC9B,CAAC;CAyCH"}
package/dist/unified.js CHANGED
@@ -3553,12 +3553,18 @@ function cleanupWorkerPools() {
3553
3553
  * falling back to CPU processing for compatibility across all environments.
3554
3554
  */
3555
3555
  let UniversalSentenceEncoder$1 = class UniversalSentenceEncoder {
3556
- constructor() {
3556
+ /**
3557
+ * Create a new UniversalSentenceEncoder instance
3558
+ * @param options Configuration options
3559
+ */
3560
+ constructor(options = {}) {
3557
3561
  this.model = null;
3558
3562
  this.initialized = false;
3559
3563
  this.tf = null;
3560
3564
  this.use = null;
3561
3565
  this.backend = 'cpu'; // Default to CPU
3566
+ this.verbose = true; // Whether to log non-essential messages
3567
+ this.verbose = options.verbose !== undefined ? options.verbose : true;
3562
3568
  }
3563
3569
  /**
3564
3570
  * Add polyfills and patches for TensorFlow.js compatibility
@@ -3624,10 +3630,12 @@ let UniversalSentenceEncoder$1 = class UniversalSentenceEncoder {
3624
3630
  process.argv.some((arg) => arg.includes('vitest')));
3625
3631
  }
3626
3632
  /**
3627
- * Log message only if not in test environment
3633
+ * Log message only if verbose mode is enabled or if it's an error
3634
+ * This helps suppress non-essential log messages
3628
3635
  */
3629
- logIfNotTest(level, message, ...args) {
3630
- if (!this.isTestEnvironment()) {
3636
+ logger(level, message, ...args) {
3637
+ // Always log errors, but only log other messages if verbose mode is enabled
3638
+ if (level === 'error' || this.verbose) {
3631
3639
  console[level](message, ...args);
3632
3640
  }
3633
3641
  }
@@ -3642,12 +3650,12 @@ let UniversalSentenceEncoder$1 = class UniversalSentenceEncoder {
3642
3650
  let lastError = null;
3643
3651
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
3644
3652
  try {
3645
- this.logIfNotTest('log', attempt === 0
3653
+ this.logger('log', attempt === 0
3646
3654
  ? 'Loading Universal Sentence Encoder model...'
3647
3655
  : `Retrying Universal Sentence Encoder model loading (attempt ${attempt + 1}/${maxRetries + 1})...`);
3648
3656
  const model = await loadFunction();
3649
3657
  if (attempt > 0) {
3650
- this.logIfNotTest('log', 'Universal Sentence Encoder model loaded successfully after retry');
3658
+ this.logger('log', 'Universal Sentence Encoder model loaded successfully after retry');
3651
3659
  }
3652
3660
  return model;
3653
3661
  }
@@ -3665,16 +3673,16 @@ let UniversalSentenceEncoder$1 = class UniversalSentenceEncoder {
3665
3673
  errorMessage.includes('model.json');
3666
3674
  if (attempt < maxRetries && isRetryableError) {
3667
3675
  const delay = baseDelay * Math.pow(2, attempt); // Exponential backoff
3668
- this.logIfNotTest('warn', `Universal Sentence Encoder model loading failed (attempt ${attempt + 1}): ${errorMessage}. Retrying in ${delay}ms...`);
3676
+ this.logger('warn', `Universal Sentence Encoder model loading failed (attempt ${attempt + 1}): ${errorMessage}. Retrying in ${delay}ms...`);
3669
3677
  await new Promise((resolve) => setTimeout(resolve, delay));
3670
3678
  }
3671
3679
  else {
3672
3680
  // Either we've exhausted retries or this is not a retryable error
3673
3681
  if (attempt >= maxRetries) {
3674
- this.logIfNotTest('error', `Universal Sentence Encoder model loading failed after ${maxRetries + 1} attempts. Last error: ${errorMessage}`);
3682
+ this.logger('error', `Universal Sentence Encoder model loading failed after ${maxRetries + 1} attempts. Last error: ${errorMessage}`);
3675
3683
  }
3676
3684
  else {
3677
- this.logIfNotTest('error', `Universal Sentence Encoder model loading failed with non-retryable error: ${errorMessage}`);
3685
+ this.logger('error', `Universal Sentence Encoder model loading failed with non-retryable error: ${errorMessage}`);
3678
3686
  }
3679
3687
  throw lastError;
3680
3688
  }
@@ -3718,7 +3726,9 @@ let UniversalSentenceEncoder$1 = class UniversalSentenceEncoder {
3718
3726
  if (globalObj) {
3719
3727
  // Try to use Node.js util module if available (Node.js environments)
3720
3728
  try {
3721
- if (typeof process !== 'undefined' && process.versions && process.versions.node) {
3729
+ if (typeof process !== 'undefined' &&
3730
+ process.versions &&
3731
+ process.versions.node) {
3722
3732
  const util = await Promise.resolve().then(function () { return _utilShim$1; });
3723
3733
  if (!globalObj.TextEncoder) {
3724
3734
  globalObj.TextEncoder = util.TextEncoder;
@@ -3774,15 +3784,14 @@ let UniversalSentenceEncoder$1 = class UniversalSentenceEncoder {
3774
3784
  this.use = await Promise.resolve().then(function () { return universalSentenceEncoder_esm; });
3775
3785
  }
3776
3786
  catch (error) {
3777
- this.logIfNotTest('error', 'Failed to initialize TensorFlow.js:', error);
3787
+ this.logger('error', 'Failed to initialize TensorFlow.js:', error);
3778
3788
  throw error;
3779
3789
  }
3780
3790
  // Set the backend
3781
3791
  if (this.tf.setBackend) {
3782
3792
  await this.tf.setBackend(this.backend);
3783
3793
  }
3784
- // Log the module structure to help with debugging
3785
- console.log('Universal Sentence Encoder module structure in main thread:', Object.keys(this.use), this.use.default ? Object.keys(this.use.default) : 'No default export');
3794
+ // Module structure available for debugging if needed
3786
3795
  // Try to find the load function in different possible module structures
3787
3796
  const loadFunction = findUSELoadFunction(this.use);
3788
3797
  if (!loadFunction) {
@@ -3795,7 +3804,7 @@ let UniversalSentenceEncoder$1 = class UniversalSentenceEncoder {
3795
3804
  console.warn = originalWarn;
3796
3805
  }
3797
3806
  catch (error) {
3798
- this.logIfNotTest('error', 'Failed to initialize Universal Sentence Encoder:', error);
3807
+ this.logger('error', 'Failed to initialize Universal Sentence Encoder:', error);
3799
3808
  throw new Error(`Failed to initialize Universal Sentence Encoder: ${error}`);
3800
3809
  }
3801
3810
  }
@@ -3842,7 +3851,7 @@ let UniversalSentenceEncoder$1 = class UniversalSentenceEncoder {
3842
3851
  return embeddingArray[0];
3843
3852
  }
3844
3853
  catch (error) {
3845
- this.logIfNotTest('error', 'Failed to embed text with Universal Sentence Encoder:', error);
3854
+ this.logger('error', 'Failed to embed text with Universal Sentence Encoder:', error);
3846
3855
  throw new Error(`Failed to embed text with Universal Sentence Encoder: ${error}`);
3847
3856
  }
3848
3857
  }
@@ -3891,7 +3900,7 @@ let UniversalSentenceEncoder$1 = class UniversalSentenceEncoder {
3891
3900
  return results;
3892
3901
  }
3893
3902
  catch (error) {
3894
- this.logIfNotTest('error', 'Failed to batch embed text with Universal Sentence Encoder:', error);
3903
+ this.logger('error', 'Failed to batch embed text with Universal Sentence Encoder:', error);
3895
3904
  throw new Error(`Failed to batch embed text with Universal Sentence Encoder: ${error}`);
3896
3905
  }
3897
3906
  }
@@ -3907,7 +3916,7 @@ let UniversalSentenceEncoder$1 = class UniversalSentenceEncoder {
3907
3916
  this.initialized = false;
3908
3917
  }
3909
3918
  catch (error) {
3910
- this.logIfNotTest('error', 'Failed to dispose Universal Sentence Encoder:', error);
3919
+ this.logger('error', 'Failed to dispose Universal Sentence Encoder:', error);
3911
3920
  }
3912
3921
  }
3913
3922
  return Promise.resolve();
@@ -3920,47 +3929,38 @@ let UniversalSentenceEncoder$1 = class UniversalSentenceEncoder {
3920
3929
  * @returns The load function or null if not found
3921
3930
  */
3922
3931
  function findUSELoadFunction(sentenceEncoderModule) {
3923
- // Log the module structure for debugging
3924
- console.log('Universal Sentence Encoder module structure:', Object.keys(sentenceEncoderModule), sentenceEncoderModule.default
3925
- ? Object.keys(sentenceEncoderModule.default)
3926
- : 'No default export');
3932
+ // Module structure available for debugging if needed
3927
3933
  let loadFunction = null;
3928
3934
  // Try sentenceEncoderModule.load first (direct export)
3929
3935
  if (sentenceEncoderModule.load &&
3930
3936
  typeof sentenceEncoderModule.load === 'function') {
3931
3937
  loadFunction = sentenceEncoderModule.load;
3932
- console.log('Using sentenceEncoderModule.load');
3933
3938
  }
3934
3939
  // Then try sentenceEncoderModule.default.load (default export)
3935
3940
  else if (sentenceEncoderModule.default &&
3936
3941
  sentenceEncoderModule.default.load &&
3937
3942
  typeof sentenceEncoderModule.default.load === 'function') {
3938
3943
  loadFunction = sentenceEncoderModule.default.load;
3939
- console.log('Using sentenceEncoderModule.default.load');
3940
3944
  }
3941
3945
  // Try sentenceEncoderModule.default directly if it's a function
3942
3946
  else if (sentenceEncoderModule.default &&
3943
3947
  typeof sentenceEncoderModule.default === 'function') {
3944
3948
  loadFunction = sentenceEncoderModule.default;
3945
- console.log('Using sentenceEncoderModule.default as function');
3946
3949
  }
3947
3950
  // Try sentenceEncoderModule directly if it's a function
3948
3951
  else if (typeof sentenceEncoderModule === 'function') {
3949
3952
  loadFunction = sentenceEncoderModule;
3950
- console.log('Using sentenceEncoderModule as function');
3951
3953
  }
3952
3954
  // Try additional common patterns
3953
3955
  else if (sentenceEncoderModule.UniversalSentenceEncoder &&
3954
3956
  typeof sentenceEncoderModule.UniversalSentenceEncoder.load === 'function') {
3955
3957
  loadFunction = sentenceEncoderModule.UniversalSentenceEncoder.load;
3956
- console.log('Using sentenceEncoderModule.UniversalSentenceEncoder.load');
3957
3958
  }
3958
3959
  else if (sentenceEncoderModule.default &&
3959
3960
  sentenceEncoderModule.default.UniversalSentenceEncoder &&
3960
3961
  typeof sentenceEncoderModule.default.UniversalSentenceEncoder.load ===
3961
3962
  'function') {
3962
3963
  loadFunction = sentenceEncoderModule.default.UniversalSentenceEncoder.load;
3963
- console.log('Using sentenceEncoderModule.default.UniversalSentenceEncoder.load');
3964
3964
  }
3965
3965
  // Try to find the load function in the module's properties
3966
3966
  else {
@@ -3971,7 +3971,6 @@ function findUSELoadFunction(sentenceEncoderModule) {
3971
3971
  const fnName = sentenceEncoderModule[key].name || key;
3972
3972
  if (fnName.toLowerCase().includes('load')) {
3973
3973
  loadFunction = sentenceEncoderModule[key];
3974
- console.log(`Using sentenceEncoderModule.${key} as load function`);
3975
3974
  break;
3976
3975
  }
3977
3976
  }
@@ -3983,7 +3982,6 @@ function findUSELoadFunction(sentenceEncoderModule) {
3983
3982
  const fnName = sentenceEncoderModule[key][nestedKey].name || nestedKey;
3984
3983
  if (fnName.toLowerCase().includes('load')) {
3985
3984
  loadFunction = sentenceEncoderModule[key][nestedKey];
3986
- console.log(`Using sentenceEncoderModule.${key}.${nestedKey} as load function`);
3987
3985
  break;
3988
3986
  }
3989
3987
  }
@@ -4008,9 +4006,14 @@ function isTestEnvironment() {
4008
4006
  process.argv.some((arg) => arg.includes('vitest')));
4009
4007
  }
4010
4008
  /**
4011
- * Log message only if not in test environment (standalone version)
4009
+ * Log message only if not in test environment and verbose mode is enabled (standalone version)
4010
+ * @param level Log level ('log', 'warn', 'error')
4011
+ * @param message Message to log
4012
+ * @param args Additional arguments to log
4013
+ * @param verbose Whether to log non-essential messages (default: true)
4012
4014
  */
4013
- function logIfNotTest(level, message, ...args) {
4015
+ function logIfNotTest(level, message, args = [], verbose = true) {
4016
+ // Always log errors, but only log other messages if verbose mode is enabled
4014
4017
  if (!isTestEnvironment()) {
4015
4018
  console[level](message, ...args);
4016
4019
  }
@@ -4032,11 +4035,22 @@ function createEmbeddingFunction(model) {
4032
4035
  * Creates a TensorFlow-based Universal Sentence Encoder embedding function
4033
4036
  * This is the required embedding function for all text embeddings
4034
4037
  * Uses a shared model instance for better performance across multiple calls
4038
+ * @param options Configuration options
4039
+ * @param options.verbose Whether to log non-essential messages (default: true)
4035
4040
  */
4036
4041
  // Create a single shared instance of the model that persists across all embedding calls
4037
- const sharedModel = new UniversalSentenceEncoder$1();
4042
+ let sharedModel = null;
4038
4043
  let sharedModelInitialized = false;
4039
- function createTensorFlowEmbeddingFunction() {
4044
+ let sharedModelVerbose = true;
4045
+ function createTensorFlowEmbeddingFunction(options = {}) {
4046
+ // Update verbose setting if provided
4047
+ if (options.verbose !== undefined) {
4048
+ sharedModelVerbose = options.verbose;
4049
+ }
4050
+ // Create the shared model if it doesn't exist yet
4051
+ if (!sharedModel) {
4052
+ sharedModel = new UniversalSentenceEncoder$1({ verbose: sharedModelVerbose });
4053
+ }
4040
4054
  return async (data) => {
4041
4055
  try {
4042
4056
  // Initialize the model if it hasn't been initialized yet
@@ -4054,7 +4068,7 @@ function createTensorFlowEmbeddingFunction() {
4054
4068
  return await sharedModel.embed(data);
4055
4069
  }
4056
4070
  catch (error) {
4057
- logIfNotTest('error', 'Failed to use TensorFlow embedding:', error);
4071
+ logIfNotTest('error', 'Failed to use TensorFlow embedding:', [error], sharedModelVerbose);
4058
4072
  throw new Error(`Universal Sentence Encoder is required but failed: ${error}`);
4059
4073
  }
4060
4074
  };
@@ -4064,32 +4078,73 @@ function createTensorFlowEmbeddingFunction() {
4064
4078
  * Uses UniversalSentenceEncoder for all text embeddings
4065
4079
  * TensorFlow.js is required for this to work
4066
4080
  * Uses CPU for compatibility
4081
+ * @param options Configuration options
4082
+ * @param options.verbose Whether to log non-essential messages (default: true)
4067
4083
  */
4068
- const defaultEmbeddingFunction = createTensorFlowEmbeddingFunction();
4084
+ function getDefaultEmbeddingFunction(options = {}) {
4085
+ return createTensorFlowEmbeddingFunction(options);
4086
+ }
4069
4087
  /**
4070
- * Default batch embedding function
4088
+ * Default embedding function with default options
4071
4089
  * Uses UniversalSentenceEncoder for all text embeddings
4072
4090
  * TensorFlow.js is required for this to work
4091
+ * Uses CPU for compatibility
4092
+ */
4093
+ const defaultEmbeddingFunction = getDefaultEmbeddingFunction();
4094
+ /**
4095
+ * Creates a batch embedding function that uses UniversalSentenceEncoder
4096
+ * TensorFlow.js is required for this to work
4073
4097
  * Processes all items in a single batch operation
4074
4098
  * Uses a shared model instance for better performance across multiple calls
4099
+ * @param options Configuration options
4100
+ * @param options.verbose Whether to log non-essential messages (default: true)
4075
4101
  */
4076
4102
  // Create a single shared instance of the model that persists across function calls
4077
- const sharedBatchModel = new UniversalSentenceEncoder$1();
4103
+ let sharedBatchModel = null;
4078
4104
  let sharedBatchModelInitialized = false;
4079
- const defaultBatchEmbeddingFunction = async (dataArray) => {
4080
- try {
4081
- // Initialize the model if it hasn't been initialized yet
4082
- if (!sharedBatchModelInitialized) {
4083
- await sharedBatchModel.init();
4084
- sharedBatchModelInitialized = true;
4085
- }
4086
- return await sharedBatchModel.embedBatch(dataArray);
4105
+ let sharedBatchModelVerbose = true;
4106
+ function createBatchEmbeddingFunction(options = {}) {
4107
+ // Update verbose setting if provided
4108
+ if (options.verbose !== undefined) {
4109
+ sharedBatchModelVerbose = options.verbose;
4087
4110
  }
4088
- catch (error) {
4089
- logIfNotTest('error', 'Failed to use TensorFlow batch embedding:', error);
4090
- throw new Error(`Universal Sentence Encoder batch embedding failed: ${error}`);
4111
+ // Create the shared model if it doesn't exist yet
4112
+ if (!sharedBatchModel) {
4113
+ sharedBatchModel = new UniversalSentenceEncoder$1({ verbose: sharedBatchModelVerbose });
4091
4114
  }
4092
- };
4115
+ return async (dataArray) => {
4116
+ try {
4117
+ // Initialize the model if it hasn't been initialized yet
4118
+ if (!sharedBatchModelInitialized) {
4119
+ await sharedBatchModel.init();
4120
+ sharedBatchModelInitialized = true;
4121
+ }
4122
+ return await sharedBatchModel.embedBatch(dataArray);
4123
+ }
4124
+ catch (error) {
4125
+ logIfNotTest('error', 'Failed to use TensorFlow batch embedding:', [error], sharedBatchModelVerbose);
4126
+ throw new Error(`Universal Sentence Encoder batch embedding failed: ${error}`);
4127
+ }
4128
+ };
4129
+ }
4130
+ /**
4131
+ * Get a batch embedding function with custom options
4132
+ * Uses UniversalSentenceEncoder for all text embeddings
4133
+ * TensorFlow.js is required for this to work
4134
+ * Processes all items in a single batch operation
4135
+ * @param options Configuration options
4136
+ * @param options.verbose Whether to log non-essential messages (default: true)
4137
+ */
4138
+ function getDefaultBatchEmbeddingFunction(options = {}) {
4139
+ return createBatchEmbeddingFunction(options);
4140
+ }
4141
+ /**
4142
+ * Default batch embedding function with default options
4143
+ * Uses UniversalSentenceEncoder for all text embeddings
4144
+ * TensorFlow.js is required for this to work
4145
+ * Processes all items in a single batch operation
4146
+ */
4147
+ const defaultBatchEmbeddingFunction = getDefaultBatchEmbeddingFunction();
4093
4148
  /**
4094
4149
  * Creates an embedding function that runs in a separate thread
4095
4150
  * This is a wrapper around createEmbeddingFunction that uses executeInThread
@@ -4108,11 +4163,14 @@ function createThreadedEmbeddingFunction(model) {
4108
4163
  var embedding = /*#__PURE__*/Object.freeze({
4109
4164
  __proto__: null,
4110
4165
  UniversalSentenceEncoder: UniversalSentenceEncoder$1,
4166
+ createBatchEmbeddingFunction: createBatchEmbeddingFunction,
4111
4167
  createEmbeddingFunction: createEmbeddingFunction,
4112
4168
  createTensorFlowEmbeddingFunction: createTensorFlowEmbeddingFunction,
4113
4169
  createThreadedEmbeddingFunction: createThreadedEmbeddingFunction,
4114
4170
  defaultBatchEmbeddingFunction: defaultBatchEmbeddingFunction,
4115
- defaultEmbeddingFunction: defaultEmbeddingFunction
4171
+ defaultEmbeddingFunction: defaultEmbeddingFunction,
4172
+ getDefaultBatchEmbeddingFunction: getDefaultBatchEmbeddingFunction,
4173
+ getDefaultEmbeddingFunction: getDefaultEmbeddingFunction
4116
4174
  });
4117
4175
 
4118
4176
  /**
@@ -8492,6 +8550,7 @@ class BrainyData {
8492
8550
  this.isInitializing = false;
8493
8551
  this.storageConfig = {};
8494
8552
  this.useOptimizedIndex = false;
8553
+ this.loggingConfig = { verbose: true };
8495
8554
  // Remote server properties
8496
8555
  this.remoteServerConfig = null;
8497
8556
  this.serverSearchConduit = null;
@@ -8516,9 +8575,22 @@ class BrainyData {
8516
8575
  }
8517
8576
  // Set storage if provided, otherwise it will be initialized in init()
8518
8577
  this.storage = config.storageAdapter || null;
8519
- // Set embedding function if provided, otherwise use default
8520
- this.embeddingFunction =
8521
- config.embeddingFunction || defaultEmbeddingFunction;
8578
+ // Store logging configuration
8579
+ if (config.logging !== undefined) {
8580
+ this.loggingConfig = {
8581
+ ...this.loggingConfig,
8582
+ ...config.logging
8583
+ };
8584
+ }
8585
+ // Set embedding function if provided, otherwise create one with the appropriate verbose setting
8586
+ if (config.embeddingFunction) {
8587
+ this.embeddingFunction = config.embeddingFunction;
8588
+ }
8589
+ else {
8590
+ this.embeddingFunction = getDefaultEmbeddingFunction({
8591
+ verbose: this.loggingConfig?.verbose
8592
+ });
8593
+ }
8522
8594
  // Set persistent storage request flag
8523
8595
  this.requestPersistentStorage =
8524
8596
  config.storage?.requestPersistentStorage || false;
@@ -8557,15 +8629,15 @@ class BrainyData {
8557
8629
  // Pre-load the embedding model early to ensure it's always available
8558
8630
  // This helps prevent issues with the Universal Sentence Encoder not being loaded
8559
8631
  try {
8560
- console.log('Pre-loading Universal Sentence Encoder model...');
8632
+ // Pre-loading Universal Sentence Encoder model
8561
8633
  // Call embedding function directly to avoid circular dependency with embed()
8562
8634
  await this.embeddingFunction('');
8563
- console.log('Universal Sentence Encoder model loaded successfully');
8635
+ // Universal Sentence Encoder model loaded successfully
8564
8636
  }
8565
8637
  catch (embedError) {
8566
8638
  console.warn('Failed to pre-load Universal Sentence Encoder:', embedError);
8567
8639
  // Try again with a retry mechanism
8568
- console.log('Retrying Universal Sentence Encoder initialization...');
8640
+ // Retrying Universal Sentence Encoder initialization
8569
8641
  try {
8570
8642
  // Wait a moment before retrying
8571
8643
  await new Promise((resolve) => setTimeout(resolve, 1000));
@@ -8947,7 +9019,11 @@ class BrainyData {
8947
9019
  if (!noun) {
8948
9020
  continue;
8949
9021
  }
8950
- const metadata = await this.storage.getMetadata(id);
9022
+ let metadata = await this.storage.getMetadata(id);
9023
+ // Initialize metadata to an empty object if it's null
9024
+ if (metadata === null) {
9025
+ metadata = {};
9026
+ }
8951
9027
  searchResults.push({
8952
9028
  id,
8953
9029
  score,
@@ -8983,7 +9059,11 @@ class BrainyData {
8983
9059
  if (!noun) {
8984
9060
  continue;
8985
9061
  }
8986
- const metadata = await this.storage.getMetadata(id);
9062
+ let metadata = await this.storage.getMetadata(id);
9063
+ // Initialize metadata to an empty object if it's null
9064
+ if (metadata === null) {
9065
+ metadata = {};
9066
+ }
8987
9067
  searchResults.push({
8988
9068
  id,
8989
9069
  score,
@@ -10316,7 +10396,13 @@ class FileSystemStorage {
10316
10396
  try {
10317
10397
  // Now set up the directory paths
10318
10398
  const rootDir = this.rootDir || process.cwd();
10319
- this.rootDir = path.resolve(rootDir, ROOT_DIR);
10399
+ // Check if rootDir already ends with ROOT_DIR to prevent duplication
10400
+ if (rootDir.endsWith(ROOT_DIR)) {
10401
+ this.rootDir = rootDir;
10402
+ }
10403
+ else {
10404
+ this.rootDir = path.resolve(rootDir, ROOT_DIR);
10405
+ }
10320
10406
  this.nounsDir = path.join(this.rootDir, NOUNS_DIR);
10321
10407
  this.verbsDir = path.join(this.rootDir, VERBS_DIR);
10322
10408
  this.metadataDir = path.join(this.rootDir, METADATA_DIR);