@soulcraft/brainy 0.26.0 → 0.28.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/dist/unified.js CHANGED
@@ -8849,8 +8849,11 @@ class S3CompatibleStorage extends BaseStorage {
8849
8849
  }
8850
8850
  }
8851
8851
  catch (error) {
8852
- // If HeadObject fails with NoSuchKey, the lock doesn't exist, which is good
8853
- if (error.name !== 'NoSuchKey' && !error.message?.includes('NoSuchKey')) {
8852
+ // If HeadObject fails with NoSuchKey or NotFound, the lock doesn't exist, which is good
8853
+ if (error.name !== 'NoSuchKey' &&
8854
+ !error.message?.includes('NoSuchKey') &&
8855
+ error.name !== 'NotFound' &&
8856
+ !error.message?.includes('NotFound')) {
8854
8857
  throw error;
8855
8858
  }
8856
8859
  }
@@ -8907,7 +8910,10 @@ class S3CompatibleStorage extends BaseStorage {
8907
8910
  }
8908
8911
  catch (error) {
8909
8912
  // If lock doesn't exist, that's fine
8910
- if (error.name === 'NoSuchKey' || error.message?.includes('NoSuchKey')) {
8913
+ if (error.name === 'NoSuchKey' ||
8914
+ error.message?.includes('NoSuchKey') ||
8915
+ error.name === 'NotFound' ||
8916
+ error.message?.includes('NotFound')) {
8911
8917
  return;
8912
8918
  }
8913
8919
  throw error;
@@ -9916,40 +9922,251 @@ async function createStorage(options = {}) {
9916
9922
  return new MemoryStorage();
9917
9923
  }
9918
9924
 
9925
+ /**
9926
+ * Graph Types - Standardized Noun and Verb Type System
9927
+ *
9928
+ * This module defines a comprehensive, standardized set of noun and verb types
9929
+ * that can be used to model any kind of graph, semantic network, or data model.
9930
+ *
9931
+ * ## Purpose and Design Philosophy
9932
+ *
9933
+ * The type system is designed to be:
9934
+ * - **Universal**: Capable of representing any domain or use case
9935
+ * - **Hierarchical**: Organized into logical categories for easy navigation
9936
+ * - **Extensible**: Additional metadata can be attached to any entity or relationship
9937
+ * - **Semantic**: Types carry meaning that can be used for reasoning and inference
9938
+ *
9939
+ * ## Noun Types (Entities)
9940
+ *
9941
+ * Noun types represent entities in the graph and are organized into categories:
9942
+ *
9943
+ * ### Core Entity Types
9944
+ * - **Person**: Human entities and individuals
9945
+ * - **Organization**: Formal organizations, companies, institutions
9946
+ * - **Location**: Geographic locations, places, addresses
9947
+ * - **Thing**: Physical objects and tangible items
9948
+ * - **Concept**: Abstract ideas, concepts, and intangible entities
9949
+ * - **Event**: Occurrences with time and place dimensions
9950
+ *
9951
+ * ### Digital/Content Types
9952
+ * - **Document**: Text-based files and documents
9953
+ * - **Media**: Non-text media files (images, videos, audio)
9954
+ * - **File**: Generic digital files
9955
+ * - **Message**: Communication content
9956
+ * - **Content**: Generic content that doesn't fit other categories
9957
+ *
9958
+ * ### Collection Types
9959
+ * - **Collection**: Generic groupings of items
9960
+ * - **Dataset**: Structured collections of data
9961
+ *
9962
+ * ### Business/Application Types
9963
+ * - **Product**: Commercial products and offerings
9964
+ * - **Service**: Services and offerings
9965
+ * - **User**: User accounts and profiles
9966
+ * - **Task**: Actions, todos, and workflow items
9967
+ * - **Project**: Organized initiatives with goals and timelines
9968
+ *
9969
+ * ### Descriptive Types
9970
+ * - **Process**: Workflows, procedures, and sequences
9971
+ * - **State**: States, conditions, or statuses
9972
+ * - **Role**: Roles, positions, or responsibilities
9973
+ * - **Topic**: Subjects or themes
9974
+ * - **Language**: Languages or linguistic entities
9975
+ * - **Currency**: Currencies and monetary units
9976
+ * - **Measurement**: Measurements, metrics, or quantities
9977
+ *
9978
+ * ## Verb Types (Relationships)
9979
+ *
9980
+ * Verb types represent relationships between entities and are organized into categories:
9981
+ *
9982
+ * ### Core Relationship Types
9983
+ * - **RelatedTo**: Generic relationship (default fallback)
9984
+ * - **Contains**: Containment relationship
9985
+ * - **PartOf**: Part-whole relationship
9986
+ * - **LocatedAt**: Spatial relationship
9987
+ * - **References**: Reference or citation relationship
9988
+ *
9989
+ * ### Temporal/Causal Types
9990
+ * - **Precedes/Succeeds**: Temporal sequence relationships
9991
+ * - **Causes**: Causal relationships
9992
+ * - **DependsOn**: Dependency relationships
9993
+ * - **Requires**: Necessity relationships
9994
+ *
9995
+ * ### Creation/Transformation Types
9996
+ * - **Creates**: Creation relationships
9997
+ * - **Transforms**: Transformation relationships
9998
+ * - **Becomes**: State change relationships
9999
+ * - **Modifies**: Modification relationships
10000
+ * - **Consumes**: Consumption relationships
10001
+ *
10002
+ * ### Ownership/Attribution Types
10003
+ * - **Owns**: Ownership relationships
10004
+ * - **AttributedTo**: Attribution or authorship
10005
+ * - **CreatedBy**: Creation attribution
10006
+ * - **BelongsTo**: Belonging relationships
10007
+ *
10008
+ * ### Social/Organizational Types
10009
+ * - **MemberOf**: Membership or affiliation
10010
+ * - **WorksWith**: Professional relationships
10011
+ * - **FriendOf**: Friendship relationships
10012
+ * - **Follows**: Following relationships
10013
+ * - **Likes**: Liking relationships
10014
+ * - **ReportsTo**: Reporting relationships
10015
+ * - **Supervises**: Supervisory relationships
10016
+ * - **Mentors**: Mentorship relationships
10017
+ * - **Communicates**: Communication relationships
10018
+ *
10019
+ * ### Descriptive/Functional Types
10020
+ * - **Describes**: Descriptive relationships
10021
+ * - **Defines**: Definition relationships
10022
+ * - **Categorizes**: Categorization relationships
10023
+ * - **Measures**: Measurement relationships
10024
+ * - **Evaluates**: Evaluation or assessment relationships
10025
+ * - **Uses**: Utilization relationships
10026
+ * - **Implements**: Implementation relationships
10027
+ * - **Extends**: Extension relationships
10028
+ *
10029
+ * ## Usage with Additional Metadata
10030
+ *
10031
+ * While the type system provides a standardized vocabulary, additional metadata
10032
+ * can be attached to any entity or relationship to capture domain-specific
10033
+ * information:
10034
+ *
10035
+ * ```typescript
10036
+ * const person: GraphNoun = {
10037
+ * id: 'person-123',
10038
+ * noun: NounType.Person,
10039
+ * data: {
10040
+ * name: 'John Doe',
10041
+ * age: 30,
10042
+ * profession: 'Engineer'
10043
+ * }
10044
+ * }
10045
+ *
10046
+ * const worksFor: GraphVerb = {
10047
+ * id: 'verb-456',
10048
+ * source: 'person-123',
10049
+ * target: 'org-789',
10050
+ * verb: VerbType.MemberOf,
10051
+ * data: {
10052
+ * role: 'Senior Engineer',
10053
+ * startDate: '2020-01-01',
10054
+ * department: 'Engineering'
10055
+ * }
10056
+ * }
10057
+ * ```
10058
+ *
10059
+ * ## Modeling Different Graph Types
10060
+ *
10061
+ * This type system can model various graph structures:
10062
+ *
10063
+ * ### Knowledge Graphs
10064
+ * Use Person, Organization, Location, Concept entities with semantic relationships
10065
+ * like AttributedTo, LocatedAt, RelatedTo
10066
+ *
10067
+ * ### Social Networks
10068
+ * Use Person, User entities with social relationships like FriendOf, Follows,
10069
+ * WorksWith, Communicates
10070
+ *
10071
+ * ### Content Networks
10072
+ * Use Document, Media, Content entities with relationships like References,
10073
+ * CreatedBy, Contains, Categorizes
10074
+ *
10075
+ * ### Business Process Models
10076
+ * Use Task, Process, Role entities with relationships like Precedes, Requires,
10077
+ * DependsOn, Transforms
10078
+ *
10079
+ * ### Organizational Charts
10080
+ * Use Person, Role, Organization entities with relationships like ReportsTo,
10081
+ * Supervises, MemberOf
10082
+ *
10083
+ * The flexibility of this system allows it to represent any domain while
10084
+ * maintaining semantic consistency and enabling powerful graph operations
10085
+ * and reasoning capabilities.
10086
+ */
9919
10087
  /**
9920
10088
  * Defines valid noun types for graph entities
9921
10089
  * Used for categorizing different types of nodes
9922
10090
  */
9923
10091
  const NounType = {
9924
- Person: 'person', // Person entities
9925
- Place: 'place', // Physical locations
9926
- Thing: 'thing', // Physical or virtual objects
9927
- Event: 'event', // Events or occurrences
9928
- Concept: 'concept', // Abstract concepts or ideas
9929
- Content: 'content', // Content items
9930
- Group: 'group', // Groups of related entities
9931
- List: 'list', // Ordered collections of entities
9932
- Category: 'category' // Categories for content items including tags
10092
+ // Core Entity Types
10093
+ Person: 'person', // Human entities
10094
+ Organization: 'organization', // Formal organizations (companies, institutions, etc.)
10095
+ Location: 'location', // Geographic locations (merges previous Place and Location)
10096
+ Thing: 'thing', // Physical objects
10097
+ Concept: 'concept', // Abstract ideas, concepts, and intangible entities
10098
+ Event: 'event', // Occurrences with time and place
10099
+ // Digital/Content Types
10100
+ Document: 'document', // Text-based files and documents (reports, articles, etc.)
10101
+ Media: 'media', // Non-text media files (images, videos, audio)
10102
+ File: 'file', // Generic digital files (merges aspects of Digital with file-specific focus)
10103
+ Message: 'message', // Communication content (emails, chat messages, posts)
10104
+ Content: 'content', // Generic content that doesn't fit other categories
10105
+ // Collection Types
10106
+ Collection: 'collection', // Generic grouping of items (merges Group, List, and Category)
10107
+ Dataset: 'dataset', // Structured collections of data
10108
+ // Business/Application Types
10109
+ Product: 'product', // Commercial products and offerings
10110
+ Service: 'service', // Services and offerings
10111
+ User: 'user', // User accounts and profiles
10112
+ Task: 'task', // Actions, todos, and workflow items
10113
+ Project: 'project', // Organized initiatives with goals and timelines
10114
+ // Descriptive Types
10115
+ Process: 'process', // Workflows, procedures, and sequences
10116
+ State: 'state', // States, conditions, or statuses
10117
+ Role: 'role', // Roles, positions, or responsibilities
10118
+ Topic: 'topic', // Subjects or themes
10119
+ Language: 'language', // Languages or linguistic entities
10120
+ Currency: 'currency', // Currencies and monetary units
10121
+ Measurement: 'measurement' // Measurements, metrics, or quantities
9933
10122
  };
9934
10123
  /**
9935
10124
  * Defines valid verb types for relationships
9936
10125
  * Used for categorizing different types of connections
9937
10126
  */
9938
10127
  const VerbType = {
9939
- AttributedTo: 'attributedTo', // Indicates attribution or authorship
9940
- Controls: 'controls', // Indicates control or ownership
9941
- Created: 'created', // Indicates creation or authorship
9942
- Earned: 'earned', // Indicates achievement or acquisition
9943
- Owns: 'owns', // Indicates ownership
9944
- MemberOf: 'memberOf', // Indicates membership or affiliation
9945
- RelatedTo: 'relatedTo', // Indicates family relationship
9946
- WorksWith: 'worksWith', // Indicates professional relationship
9947
- FriendOf: 'friendOf', // Indicates friendship
9948
- ReportsTo: 'reportsTo', // Indicates reporting relationship
9949
- Supervises: 'supervises', // Indicates supervisory relationship
9950
- Mentors: 'mentors', // Indicates mentorship relationship
9951
- Follows: 'follows', // Indicates the following relationship
9952
- Likes: 'likes' // Indicates liking relationship
10128
+ // Core Relationship Types
10129
+ RelatedTo: 'relatedTo', // Generic relationship (default fallback)
10130
+ Contains: 'contains', // Containment relationship (parent contains child)
10131
+ PartOf: 'partOf', // Part-whole relationship (child is part of parent)
10132
+ LocatedAt: 'locatedAt', // Spatial relationship
10133
+ References: 'references', // Reference or citation relationship
10134
+ // Temporal/Causal Types
10135
+ Precedes: 'precedes', // Temporal sequence (comes before)
10136
+ Succeeds: 'succeeds', // Temporal sequence (comes after)
10137
+ Causes: 'causes', // Causal relationship (merges Influences and Causes)
10138
+ DependsOn: 'dependsOn', // Dependency relationship
10139
+ Requires: 'requires', // Necessity relationship (new)
10140
+ // Creation/Transformation Types
10141
+ Creates: 'creates', // Creation relationship (merges Created and Produces)
10142
+ Transforms: 'transforms', // Transformation relationship
10143
+ Becomes: 'becomes', // State change relationship
10144
+ Modifies: 'modifies', // Modification relationship
10145
+ Consumes: 'consumes', // Consumption relationship
10146
+ // Ownership/Attribution Types
10147
+ Owns: 'owns', // Ownership relationship (merges Controls and Owns)
10148
+ AttributedTo: 'attributedTo', // Attribution or authorship
10149
+ CreatedBy: 'createdBy', // Creation attribution (new, distinct from Creates)
10150
+ BelongsTo: 'belongsTo', // Belonging relationship (new)
10151
+ // Social/Organizational Types
10152
+ MemberOf: 'memberOf', // Membership or affiliation
10153
+ WorksWith: 'worksWith', // Professional relationship
10154
+ FriendOf: 'friendOf', // Friendship relationship
10155
+ Follows: 'follows', // Following relationship
10156
+ Likes: 'likes', // Liking relationship
10157
+ ReportsTo: 'reportsTo', // Reporting relationship
10158
+ Supervises: 'supervises', // Supervisory relationship
10159
+ Mentors: 'mentors', // Mentorship relationship
10160
+ Communicates: 'communicates', // Communication relationship (merges Communicates and Collaborates)
10161
+ // Descriptive/Functional Types
10162
+ Describes: 'describes', // Descriptive relationship
10163
+ Defines: 'defines', // Definition relationship
10164
+ Categorizes: 'categorizes', // Categorization relationship
10165
+ Measures: 'measures', // Measurement relationship
10166
+ Evaluates: 'evaluates', // Evaluation or assessment relationship
10167
+ Uses: 'uses', // Utilization relationship (new)
10168
+ Implements: 'implements', // Implementation relationship
10169
+ Extends: 'extends' // Extension relationship (merges Extends and Inherits)
9953
10170
  };
9954
10171
 
9955
10172
  /** Common types for the augmentation system */
@@ -12202,6 +12419,12 @@ class BrainyData {
12202
12419
  config.storage?.requestPersistentStorage || false;
12203
12420
  // Set read-only flag
12204
12421
  this.readOnly = config.readOnly || false;
12422
+ // Set write-only flag
12423
+ this.writeOnly = config.writeOnly || false;
12424
+ // Validate that readOnly and writeOnly are not both true
12425
+ if (this.readOnly && this.writeOnly) {
12426
+ throw new Error('Database cannot be both read-only and write-only');
12427
+ }
12205
12428
  // Store storage configuration for later use in init()
12206
12429
  this.storageConfig = config.storage || {};
12207
12430
  // Store timeout and retry configuration
@@ -12228,6 +12451,15 @@ class BrainyData {
12228
12451
  throw new Error('Cannot perform write operation: database is in read-only mode');
12229
12452
  }
12230
12453
  }
12454
+ /**
12455
+ * Check if the database is in write-only mode and throw an error if it is
12456
+ * @throws Error if the database is in write-only mode
12457
+ */
12458
+ checkWriteOnly() {
12459
+ if (this.writeOnly) {
12460
+ throw new Error('Cannot perform search operation: database is in write-only mode');
12461
+ }
12462
+ }
12231
12463
  /**
12232
12464
  * Start real-time updates if enabled in the configuration
12233
12465
  * This will periodically check for new data in storage and update the in-memory index and statistics
@@ -12242,14 +12474,16 @@ class BrainyData {
12242
12474
  return;
12243
12475
  }
12244
12476
  // Set the initial last known noun count
12245
- this.getNounCount().then(count => {
12477
+ this.getNounCount()
12478
+ .then((count) => {
12246
12479
  this.lastKnownNounCount = count;
12247
- }).catch(error => {
12480
+ })
12481
+ .catch((error) => {
12248
12482
  console.warn('Failed to get initial noun count for real-time updates:', error);
12249
12483
  });
12250
12484
  // Start the update timer
12251
12485
  this.updateTimerId = setInterval(() => {
12252
- this.checkForUpdates().catch(error => {
12486
+ this.checkForUpdates().catch((error) => {
12253
12487
  console.warn('Error during real-time update check:', error);
12254
12488
  });
12255
12489
  }, this.realtimeUpdateConfig.interval);
@@ -12415,7 +12649,8 @@ class BrainyData {
12415
12649
  // Continue with other changes
12416
12650
  }
12417
12651
  }
12418
- if (this.loggingConfig?.verbose && (addedCount > 0 || updatedCount > 0 || deletedCount > 0)) {
12652
+ if (this.loggingConfig?.verbose &&
12653
+ (addedCount > 0 || updatedCount > 0 || deletedCount > 0)) {
12419
12654
  console.log(`Real-time update: Added ${addedCount}, updated ${updatedCount}, deleted ${deletedCount} nouns using change log`);
12420
12655
  }
12421
12656
  // Update the last known noun count
@@ -12442,7 +12677,7 @@ class BrainyData {
12442
12677
  const indexNouns = this.index.getNouns();
12443
12678
  const indexNounIds = new Set(indexNouns.keys());
12444
12679
  // Find nouns that are in storage but not in the index
12445
- const newNouns = nouns.filter(noun => !indexNounIds.has(noun.id));
12680
+ const newNouns = nouns.filter((noun) => !indexNounIds.has(noun.id));
12446
12681
  // Add new nouns to the index
12447
12682
  for (const noun of newNouns) {
12448
12683
  // Check if the vector dimensions match the expected dimensions
@@ -12574,23 +12809,31 @@ class BrainyData {
12574
12809
  if (this.useOptimizedIndex && this.index instanceof HNSWIndexOptimized) {
12575
12810
  this.index.setStorage(this.storage);
12576
12811
  }
12577
- // Load all nouns from storage
12578
- const nouns = await this.storage.getAllNouns();
12579
- // Clear the index and add all nouns
12580
- this.index.clear();
12581
- for (const noun of nouns) {
12582
- // Check if the vector dimensions match the expected dimensions
12583
- if (noun.vector.length !== this._dimensions) {
12584
- console.warn(`Deleting noun ${noun.id} due to dimension mismatch: expected ${this._dimensions}, got ${noun.vector.length}`);
12585
- // Delete the mismatched noun from storage to prevent future issues
12586
- await this.storage.deleteNoun(noun.id);
12587
- continue;
12812
+ // In write-only mode, skip loading the index into memory
12813
+ if (this.writeOnly) {
12814
+ if (this.loggingConfig?.verbose) {
12815
+ console.log('Database is in write-only mode, skipping index loading');
12816
+ }
12817
+ }
12818
+ else {
12819
+ // Load all nouns from storage
12820
+ const nouns = await this.storage.getAllNouns();
12821
+ // Clear the index and add all nouns
12822
+ this.index.clear();
12823
+ for (const noun of nouns) {
12824
+ // Check if the vector dimensions match the expected dimensions
12825
+ if (noun.vector.length !== this._dimensions) {
12826
+ console.warn(`Deleting noun ${noun.id} due to dimension mismatch: expected ${this._dimensions}, got ${noun.vector.length}`);
12827
+ // Delete the mismatched noun from storage to prevent future issues
12828
+ await this.storage.deleteNoun(noun.id);
12829
+ continue;
12830
+ }
12831
+ // Add to index
12832
+ await this.index.addItem({
12833
+ id: noun.id,
12834
+ vector: noun.vector
12835
+ });
12588
12836
  }
12589
- // Add to index
12590
- await this.index.addItem({
12591
- id: noun.id,
12592
- vector: noun.vector
12593
- });
12594
12837
  }
12595
12838
  // Connect to remote server if configured with autoConnect
12596
12839
  if (this.remoteServerConfig && this.remoteServerConfig.autoConnect) {
@@ -12664,8 +12907,7 @@ class BrainyData {
12664
12907
  }
12665
12908
  }
12666
12909
  // Check if input is already a vector
12667
- if (Array.isArray(vectorOrData) &&
12668
- !options.forceEmbed) {
12910
+ if (Array.isArray(vectorOrData) && !options.forceEmbed) {
12669
12911
  // Input is already a vector (and we've validated it contains only numbers)
12670
12912
  vector = vectorOrData;
12671
12913
  }
@@ -12706,7 +12948,9 @@ class BrainyData {
12706
12948
  // Save metadata if provided and not empty
12707
12949
  if (metadata !== undefined) {
12708
12950
  // Skip saving if metadata is an empty object
12709
- if (metadata && typeof metadata === 'object' && Object.keys(metadata).length === 0) {
12951
+ if (metadata &&
12952
+ typeof metadata === 'object' &&
12953
+ Object.keys(metadata).length === 0) {
12710
12954
  // Don't save empty metadata
12711
12955
  // Explicitly save null to ensure no metadata is stored
12712
12956
  await this.storage.saveMetadata(id, null);
@@ -12938,7 +13182,7 @@ class BrainyData {
12938
13182
  filterResultsByService(results, service) {
12939
13183
  if (!service)
12940
13184
  return results;
12941
- return results.filter(result => {
13185
+ return results.filter((result) => {
12942
13186
  if (!result.metadata || typeof result.metadata !== 'object')
12943
13187
  return false;
12944
13188
  if (!('createdBy' in result.metadata))
@@ -12961,6 +13205,8 @@ class BrainyData {
12961
13205
  if (!this.isInitialized) {
12962
13206
  throw new Error('BrainyData must be initialized before searching. Call init() first.');
12963
13207
  }
13208
+ // Check if database is in write-only mode
13209
+ this.checkWriteOnly();
12964
13210
  try {
12965
13211
  let queryVector;
12966
13212
  // Check if input is already a vector
@@ -13087,6 +13333,8 @@ class BrainyData {
13087
13333
  if (!this.isInitialized) {
13088
13334
  throw new Error('BrainyData must be initialized before searching. Call init() first.');
13089
13335
  }
13336
+ // Check if database is in write-only mode
13337
+ this.checkWriteOnly();
13090
13338
  // If searching for verbs directly
13091
13339
  if (options.searchVerbs) {
13092
13340
  const verbResults = await this.searchVerbs(queryVectorOrData, k, {
@@ -13138,6 +13386,8 @@ class BrainyData {
13138
13386
  if (!this.isInitialized) {
13139
13387
  throw new Error('BrainyData must be initialized before searching. Call init() first.');
13140
13388
  }
13389
+ // Check if database is in write-only mode
13390
+ this.checkWriteOnly();
13141
13391
  // If input is a string and not a vector, automatically vectorize it
13142
13392
  let queryToUse = queryVectorOrData;
13143
13393
  if (typeof queryVectorOrData === 'string' && !options.forceEmbed) {
@@ -13202,9 +13452,9 @@ class BrainyData {
13202
13452
  // Get all verbs (relationships) from the source entity
13203
13453
  const outgoingVerbs = await this.storage.getVerbsBySource(id);
13204
13454
  // Filter to only include verbs of the specified type
13205
- const verbsOfType = outgoingVerbs.filter(verb => verb.type === options.relationType);
13455
+ const verbsOfType = outgoingVerbs.filter((verb) => verb.type === options.relationType);
13206
13456
  // Get the target IDs
13207
- const targetIds = verbsOfType.map(verb => verb.target);
13457
+ const targetIds = verbsOfType.map((verb) => verb.target);
13208
13458
  // Get the actual entities for these IDs
13209
13459
  const results = [];
13210
13460
  for (const targetId of targetIds) {
@@ -13382,7 +13632,7 @@ class BrainyData {
13382
13632
  const service = options.service || this.getCurrentAugmentation();
13383
13633
  const graphNoun = metadata;
13384
13634
  // Preserve existing createdBy and createdAt if they exist
13385
- const existingMetadata = await this.storage.getMetadata(id);
13635
+ const existingMetadata = (await this.storage.getMetadata(id));
13386
13636
  if (existingMetadata &&
13387
13637
  typeof existingMetadata === 'object' &&
13388
13638
  'createdBy' in existingMetadata) {
@@ -13791,7 +14041,7 @@ class BrainyData {
13791
14041
  // Get all verbs from storage
13792
14042
  const allVerbs = await this.storage.getAllVerbs();
13793
14043
  // Create a set of verb IDs for faster lookup
13794
- const verbIds = new Set(allVerbs.map(verb => verb.id));
14044
+ const verbIds = new Set(allVerbs.map((verb) => verb.id));
13795
14045
  // Get all nouns from the index
13796
14046
  const nouns = this.index.getNouns();
13797
14047
  // Count nouns that are not verbs
@@ -13853,8 +14103,14 @@ class BrainyData {
13853
14103
  };
13854
14104
  // Filter by service if specified
13855
14105
  const services = options.service
13856
- ? (Array.isArray(options.service) ? options.service : [options.service])
13857
- : Object.keys({ ...stats.nounCount, ...stats.verbCount, ...stats.metadataCount });
14106
+ ? Array.isArray(options.service)
14107
+ ? options.service
14108
+ : [options.service]
14109
+ : Object.keys({
14110
+ ...stats.nounCount,
14111
+ ...stats.verbCount,
14112
+ ...stats.metadataCount
14113
+ });
13858
14114
  // Calculate totals and service breakdown
13859
14115
  for (const service of services) {
13860
14116
  const nounCount = stats.nounCount[service] || 0;
@@ -13959,6 +14215,28 @@ class BrainyData {
13959
14215
  */
13960
14216
  setReadOnly(readOnly) {
13961
14217
  this.readOnly = readOnly;
14218
+ // Ensure readOnly and writeOnly are not both true
14219
+ if (readOnly && this.writeOnly) {
14220
+ this.writeOnly = false;
14221
+ }
14222
+ }
14223
+ /**
14224
+ * Check if the database is in write-only mode
14225
+ * @returns True if the database is in write-only mode, false otherwise
14226
+ */
14227
+ isWriteOnly() {
14228
+ return this.writeOnly;
14229
+ }
14230
+ /**
14231
+ * Set the database to write-only mode
14232
+ * @param writeOnly True to set the database to write-only mode, false to allow searches
14233
+ */
14234
+ setWriteOnly(writeOnly) {
14235
+ this.writeOnly = writeOnly;
14236
+ // Ensure readOnly and writeOnly are not both true
14237
+ if (writeOnly && this.readOnly) {
14238
+ this.readOnly = false;
14239
+ }
13962
14240
  }
13963
14241
  /**
13964
14242
  * Embed text or data into a vector using the same embedding function used by this instance
@@ -13986,6 +14264,8 @@ class BrainyData {
13986
14264
  */
13987
14265
  async searchVerbs(queryVectorOrData, k = 10, options = {}) {
13988
14266
  await this.ensureInitialized();
14267
+ // Check if database is in write-only mode
14268
+ this.checkWriteOnly();
13989
14269
  try {
13990
14270
  let queryVector;
13991
14271
  // Check if input is already a vector
@@ -14052,9 +14332,11 @@ class BrainyData {
14052
14332
  verbs = allVerbs;
14053
14333
  }
14054
14334
  // Calculate similarity for each verb not already in results
14055
- const existingIds = new Set(verbResults.map(v => v.id));
14335
+ const existingIds = new Set(verbResults.map((v) => v.id));
14056
14336
  for (const verb of verbs) {
14057
- if (!existingIds.has(verb.id) && verb.vector && verb.vector.length > 0) {
14337
+ if (!existingIds.has(verb.id) &&
14338
+ verb.vector &&
14339
+ verb.vector.length > 0) {
14058
14340
  const distance = this.index.getDistanceFunction()(queryVector, verb.vector);
14059
14341
  verbResults.push({
14060
14342
  ...verb,
@@ -14082,6 +14364,8 @@ class BrainyData {
14082
14364
  */
14083
14365
  async searchNounsByVerbs(queryVectorOrData, k = 10, options = {}) {
14084
14366
  await this.ensureInitialized();
14367
+ // Check if database is in write-only mode
14368
+ this.checkWriteOnly();
14085
14369
  try {
14086
14370
  // First, search for nouns
14087
14371
  const nounResults = await this.searchByNounTypes(queryVectorOrData, k * 2, // Get more results initially to account for filtering
@@ -14171,6 +14455,8 @@ class BrainyData {
14171
14455
  */
14172
14456
  async searchText(query, k = 10, options = {}) {
14173
14457
  await this.ensureInitialized();
14458
+ // Check if database is in write-only mode
14459
+ this.checkWriteOnly();
14174
14460
  try {
14175
14461
  // Embed the query text
14176
14462
  const queryVector = await this.embed(query);
@@ -14195,6 +14481,8 @@ class BrainyData {
14195
14481
  */
14196
14482
  async searchRemote(queryVectorOrData, k = 10, options = {}) {
14197
14483
  await this.ensureInitialized();
14484
+ // Check if database is in write-only mode
14485
+ this.checkWriteOnly();
14198
14486
  // Check if connected to a remote server
14199
14487
  if (!this.isConnectedToRemoteServer()) {
14200
14488
  throw new Error('Not connected to a remote server. Call connectToRemoteServer() first.');
@@ -14234,6 +14522,8 @@ class BrainyData {
14234
14522
  */
14235
14523
  async searchCombined(queryVectorOrData, k = 10, options = {}) {
14236
14524
  await this.ensureInitialized();
14525
+ // Check if database is in write-only mode
14526
+ this.checkWriteOnly();
14237
14527
  // Check if connected to a remote server
14238
14528
  if (!this.isConnectedToRemoteServer()) {
14239
14529
  // If not connected to a remote server, just search locally
@@ -14669,14 +14959,14 @@ class BrainyData {
14669
14959
  const nounIds = [];
14670
14960
  const nounDescriptions = {
14671
14961
  [NounType.Person]: 'A person with unique characteristics',
14672
- [NounType.Place]: 'A location with specific attributes',
14962
+ [NounType.Location]: 'A location with specific attributes',
14673
14963
  [NounType.Thing]: 'An object with distinct properties',
14674
14964
  [NounType.Event]: 'An occurrence with temporal aspects',
14675
14965
  [NounType.Concept]: 'An abstract idea or notion',
14676
14966
  [NounType.Content]: 'A piece of content or information',
14677
- [NounType.Group]: 'A collection of related entities',
14678
- [NounType.List]: 'An ordered sequence of items',
14679
- [NounType.Category]: 'A classification or grouping'
14967
+ [NounType.Collection]: 'A collection of related entities',
14968
+ [NounType.Organization]: 'An organization or institution',
14969
+ [NounType.Document]: 'A document or text-based file'
14680
14970
  };
14681
14971
  for (let i = 0; i < nounCount; i++) {
14682
14972
  // Select a random noun type
@@ -14702,10 +14992,10 @@ class BrainyData {
14702
14992
  const verbIds = [];
14703
14993
  const verbDescriptions = {
14704
14994
  [VerbType.AttributedTo]: 'Attribution relationship',
14705
- [VerbType.Controls]: 'Control relationship',
14706
- [VerbType.Created]: 'Creation relationship',
14707
- [VerbType.Earned]: 'Achievement relationship',
14708
14995
  [VerbType.Owns]: 'Ownership relationship',
14996
+ [VerbType.Creates]: 'Creation relationship',
14997
+ [VerbType.Uses]: 'Utilization relationship',
14998
+ [VerbType.BelongsTo]: 'Belonging relationship',
14709
14999
  [VerbType.MemberOf]: 'Membership relationship',
14710
15000
  [VerbType.RelatedTo]: 'General relationship',
14711
15001
  [VerbType.WorksWith]: 'Collaboration relationship',