@soulcraft/brainy 0.34.0 → 0.35.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.
@@ -312,7 +312,8 @@ export declare class BrainyData<T = any> implements BrainyDataInterface<T> {
312
312
  private checkReadOnly;
313
313
  /**
314
314
  * Check if the database is in write-only mode and throw an error if it is
315
- * @throws Error if the database is in write-only mode
315
+ * @param allowExistenceChecks If true, allows existence checks (get operations) in write-only mode
316
+ * @throws Error if the database is in write-only mode and operation is not allowed
316
317
  */
317
318
  private checkWriteOnly;
318
319
  /**
@@ -597,6 +598,7 @@ export declare class BrainyData<T = any> implements BrainyDataInterface<T> {
597
598
  * - id: Optional ID to use instead of generating a new one
598
599
  * - autoCreateMissingNouns: Automatically create missing nouns if they don't exist
599
600
  * - missingNounMetadata: Metadata to use when auto-creating missing nouns
601
+ * - writeOnlyMode: Skip noun existence checks for high-speed streaming (creates placeholder nouns)
600
602
  *
601
603
  * @returns The ID of the added verb
602
604
  *
@@ -611,6 +613,7 @@ export declare class BrainyData<T = any> implements BrainyDataInterface<T> {
611
613
  autoCreateMissingNouns?: boolean;
612
614
  missingNounMetadata?: any;
613
615
  service?: string;
616
+ writeOnlyMode?: boolean;
614
617
  }): Promise<string>;
615
618
  /**
616
619
  * Get a verb by ID
package/dist/unified.js CHANGED
@@ -15225,11 +15225,12 @@ class BrainyData {
15225
15225
  }
15226
15226
  /**
15227
15227
  * Check if the database is in write-only mode and throw an error if it is
15228
- * @throws Error if the database is in write-only mode
15228
+ * @param allowExistenceChecks If true, allows existence checks (get operations) in write-only mode
15229
+ * @throws Error if the database is in write-only mode and operation is not allowed
15229
15230
  */
15230
- checkWriteOnly() {
15231
- if (this.writeOnly) {
15232
- throw new Error('Cannot perform search operation: database is in write-only mode');
15231
+ checkWriteOnly(allowExistenceChecks = false) {
15232
+ if (this.writeOnly && !allowExistenceChecks) {
15233
+ throw new Error('Cannot perform search operation: database is in write-only mode. Use get() for existence checks.');
15233
15234
  }
15234
15235
  }
15235
15236
  /**
@@ -15761,12 +15762,65 @@ class BrainyData {
15761
15762
  (metadata && typeof metadata === 'object' && 'id' in metadata
15762
15763
  ? metadata.id
15763
15764
  : v4());
15764
- // Add to index
15765
- await this.index.addItem({ id, vector });
15766
- // Get the noun from the index
15767
- const noun = this.index.getNouns().get(id);
15768
- if (!noun) {
15769
- throw new Error(`Failed to retrieve newly created noun with ID ${id}`);
15765
+ // Check for existing noun (both write-only and normal modes)
15766
+ let existingNoun;
15767
+ if (options.id) {
15768
+ try {
15769
+ if (this.writeOnly) {
15770
+ // In write-only mode, check storage directly
15771
+ existingNoun = await this.storage.getNoun(options.id) ?? undefined;
15772
+ }
15773
+ else {
15774
+ // In normal mode, check index first, then storage
15775
+ existingNoun = this.index.getNouns().get(options.id);
15776
+ if (!existingNoun) {
15777
+ existingNoun = await this.storage.getNoun(options.id) ?? undefined;
15778
+ }
15779
+ }
15780
+ if (existingNoun) {
15781
+ // Check if existing noun is a placeholder
15782
+ const existingMetadata = await this.storage.getMetadata(options.id);
15783
+ const isPlaceholder = existingMetadata &&
15784
+ typeof existingMetadata === 'object' &&
15785
+ existingMetadata.isPlaceholder;
15786
+ if (isPlaceholder) {
15787
+ // Replace placeholder with real data
15788
+ if (this.loggingConfig?.verbose) {
15789
+ console.log(`Replacing placeholder noun ${options.id} with real data`);
15790
+ }
15791
+ }
15792
+ else {
15793
+ // Real noun already exists, update it
15794
+ if (this.loggingConfig?.verbose) {
15795
+ console.log(`Updating existing noun ${options.id}`);
15796
+ }
15797
+ }
15798
+ }
15799
+ }
15800
+ catch (storageError) {
15801
+ // Item doesn't exist, continue with add operation
15802
+ }
15803
+ }
15804
+ let noun;
15805
+ // In write-only mode, skip index operations since index is not loaded
15806
+ if (this.writeOnly) {
15807
+ // Create noun object directly without adding to index
15808
+ noun = {
15809
+ id,
15810
+ vector,
15811
+ connections: new Map(),
15812
+ metadata: undefined // Will be set separately
15813
+ };
15814
+ }
15815
+ else {
15816
+ // Normal mode: Add to index first
15817
+ await this.index.addItem({ id, vector });
15818
+ // Get the noun from the index
15819
+ const indexNoun = this.index.getNouns().get(id);
15820
+ if (!indexNoun) {
15821
+ throw new Error(`Failed to retrieve newly created noun with ID ${id}`);
15822
+ }
15823
+ noun = indexNoun;
15770
15824
  }
15771
15825
  // Save noun to storage
15772
15826
  await this.storage.saveNoun(noun);
@@ -16297,6 +16351,15 @@ class BrainyData {
16297
16351
  service: options.service
16298
16352
  });
16299
16353
  }
16354
+ // Filter out placeholder nouns from search results
16355
+ searchResults = searchResults.filter(result => {
16356
+ if (result.metadata && typeof result.metadata === 'object') {
16357
+ const metadata = result.metadata;
16358
+ // Exclude placeholder nouns from search results
16359
+ return !metadata.isPlaceholder;
16360
+ }
16361
+ return true;
16362
+ });
16300
16363
  // If includeVerbs is true, retrieve associated GraphVerbs for each result
16301
16364
  if (options.includeVerbs && this.storage) {
16302
16365
  for (const result of searchResults) {
@@ -16385,8 +16448,31 @@ class BrainyData {
16385
16448
  }
16386
16449
  await this.ensureInitialized();
16387
16450
  try {
16388
- // Get noun from index
16389
- const noun = this.index.getNouns().get(id);
16451
+ let noun;
16452
+ // In write-only mode, query storage directly since index is not loaded
16453
+ if (this.writeOnly) {
16454
+ try {
16455
+ noun = await this.storage.getNoun(id) ?? undefined;
16456
+ }
16457
+ catch (storageError) {
16458
+ // If storage lookup fails, return null (noun doesn't exist)
16459
+ return null;
16460
+ }
16461
+ }
16462
+ else {
16463
+ // Normal mode: Get noun from index first
16464
+ noun = this.index.getNouns().get(id);
16465
+ // If not found in index, fallback to storage (for race conditions)
16466
+ if (!noun && this.storage) {
16467
+ try {
16468
+ noun = await this.storage.getNoun(id) ?? undefined;
16469
+ }
16470
+ catch (storageError) {
16471
+ // Storage lookup failed, noun doesn't exist
16472
+ return null;
16473
+ }
16474
+ }
16475
+ }
16390
16476
  if (!noun) {
16391
16477
  return null;
16392
16478
  }
@@ -16720,6 +16806,7 @@ class BrainyData {
16720
16806
  * - id: Optional ID to use instead of generating a new one
16721
16807
  * - autoCreateMissingNouns: Automatically create missing nouns if they don't exist
16722
16808
  * - missingNounMetadata: Metadata to use when auto-creating missing nouns
16809
+ * - writeOnlyMode: Skip noun existence checks for high-speed streaming (creates placeholder nouns)
16723
16810
  *
16724
16811
  * @returns The ID of the added verb
16725
16812
  *
@@ -16737,9 +16824,102 @@ class BrainyData {
16737
16824
  throw new Error('Target ID cannot be null or undefined');
16738
16825
  }
16739
16826
  try {
16740
- // Check if source and target nouns exist
16741
- let sourceNoun = this.index.getNouns().get(sourceId);
16742
- let targetNoun = this.index.getNouns().get(targetId);
16827
+ let sourceNoun;
16828
+ let targetNoun;
16829
+ // In write-only mode, create placeholder nouns without checking existence
16830
+ if (options.writeOnlyMode) {
16831
+ // Create placeholder nouns for high-speed streaming
16832
+ const service = this.getServiceName(options);
16833
+ const now = new Date();
16834
+ const timestamp = {
16835
+ seconds: Math.floor(now.getTime() / 1000),
16836
+ nanoseconds: (now.getTime() % 1000) * 1000000
16837
+ };
16838
+ // Create placeholder source noun
16839
+ const sourcePlaceholderVector = new Array(this._dimensions).fill(0);
16840
+ const sourceMetadata = options.missingNounMetadata || {
16841
+ autoCreated: true,
16842
+ writeOnlyMode: true,
16843
+ isPlaceholder: true, // Mark as placeholder to exclude from search results
16844
+ createdAt: timestamp,
16845
+ updatedAt: timestamp,
16846
+ noun: NounType.Concept,
16847
+ createdBy: {
16848
+ augmentation: service,
16849
+ version: '1.0'
16850
+ }
16851
+ };
16852
+ sourceNoun = {
16853
+ id: sourceId,
16854
+ vector: sourcePlaceholderVector,
16855
+ connections: new Map(),
16856
+ metadata: sourceMetadata
16857
+ };
16858
+ // Create placeholder target noun
16859
+ const targetPlaceholderVector = new Array(this._dimensions).fill(0);
16860
+ const targetMetadata = options.missingNounMetadata || {
16861
+ autoCreated: true,
16862
+ writeOnlyMode: true,
16863
+ isPlaceholder: true, // Mark as placeholder to exclude from search results
16864
+ createdAt: timestamp,
16865
+ updatedAt: timestamp,
16866
+ noun: NounType.Concept,
16867
+ createdBy: {
16868
+ augmentation: service,
16869
+ version: '1.0'
16870
+ }
16871
+ };
16872
+ targetNoun = {
16873
+ id: targetId,
16874
+ vector: targetPlaceholderVector,
16875
+ connections: new Map(),
16876
+ metadata: targetMetadata
16877
+ };
16878
+ // Save placeholder nouns to storage (but skip indexing for speed)
16879
+ if (this.storage) {
16880
+ try {
16881
+ await this.storage.saveNoun(sourceNoun);
16882
+ await this.storage.saveNoun(targetNoun);
16883
+ }
16884
+ catch (storageError) {
16885
+ console.warn(`Failed to save placeholder nouns in write-only mode:`, storageError);
16886
+ }
16887
+ }
16888
+ }
16889
+ else {
16890
+ // Normal mode: Check if source and target nouns exist in index first
16891
+ sourceNoun = this.index.getNouns().get(sourceId);
16892
+ targetNoun = this.index.getNouns().get(targetId);
16893
+ // If not found in index, check storage directly (fallback for race conditions)
16894
+ if (!sourceNoun && this.storage) {
16895
+ try {
16896
+ const storageNoun = await this.storage.getNoun(sourceId);
16897
+ if (storageNoun) {
16898
+ // Found in storage but not in index - this indicates indexing delay
16899
+ sourceNoun = storageNoun;
16900
+ console.warn(`Found source noun ${sourceId} in storage but not in index - possible indexing delay`);
16901
+ }
16902
+ }
16903
+ catch (storageError) {
16904
+ // Storage lookup failed, continue with normal flow
16905
+ console.debug(`Storage lookup failed for source noun ${sourceId}:`, storageError);
16906
+ }
16907
+ }
16908
+ if (!targetNoun && this.storage) {
16909
+ try {
16910
+ const storageNoun = await this.storage.getNoun(targetId);
16911
+ if (storageNoun) {
16912
+ // Found in storage but not in index - this indicates indexing delay
16913
+ targetNoun = storageNoun;
16914
+ console.warn(`Found target noun ${targetId} in storage but not in index - possible indexing delay`);
16915
+ }
16916
+ }
16917
+ catch (storageError) {
16918
+ // Storage lookup failed, continue with normal flow
16919
+ console.debug(`Storage lookup failed for target noun ${targetId}:`, storageError);
16920
+ }
16921
+ }
16922
+ }
16743
16923
  // Auto-create missing nouns if option is enabled
16744
16924
  if (!sourceNoun && options.autoCreateMissingNouns) {
16745
16925
  try {
@@ -18068,8 +18248,8 @@ class BrainyData {
18068
18248
  if (this.storage) {
18069
18249
  // Update the statistics to match the actual number of items (2 for the test)
18070
18250
  await this.storage.saveStatistics({
18071
- nounCount: { 'test': data.nouns.length },
18072
- verbCount: { 'test': data.verbs.length },
18251
+ nounCount: { test: data.nouns.length },
18252
+ verbCount: { test: data.verbs.length },
18073
18253
  metadataCount: {},
18074
18254
  hnswIndexSize: 0,
18075
18255
  lastUpdated: new Date().toISOString()