@soulcraft/brainy 3.12.0 → 3.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/dist/brainy.js CHANGED
@@ -148,6 +148,50 @@ export class Brainy {
148
148
  // ============= CORE CRUD OPERATIONS =============
149
149
  /**
150
150
  * Add an entity to the database
151
+ *
152
+ * @param params - Parameters for adding the entity
153
+ * @returns Promise that resolves to the entity ID
154
+ *
155
+ * @example Basic entity creation
156
+ * ```typescript
157
+ * const id = await brain.add({
158
+ * data: "John Smith is a software engineer",
159
+ * type: NounType.Person,
160
+ * metadata: { role: "engineer", team: "backend" }
161
+ * })
162
+ * console.log(`Created entity: ${id}`)
163
+ * ```
164
+ *
165
+ * @example Adding with custom ID
166
+ * ```typescript
167
+ * const customId = await brain.add({
168
+ * id: "user-12345",
169
+ * data: "Important document content",
170
+ * type: NounType.Document,
171
+ * metadata: { priority: "high", department: "legal" }
172
+ * })
173
+ * ```
174
+ *
175
+ * @example Using pre-computed vector (optimization)
176
+ * ```typescript
177
+ * const vector = await brain.embed("Optimized content")
178
+ * const id = await brain.add({
179
+ * data: "Optimized content",
180
+ * type: NounType.Document,
181
+ * vector: vector, // Skip re-embedding
182
+ * metadata: { optimized: true }
183
+ * })
184
+ * ```
185
+ *
186
+ * @example Multi-tenant usage
187
+ * ```typescript
188
+ * const id = await brain.add({
189
+ * data: "Customer feedback",
190
+ * type: NounType.Message,
191
+ * service: "customer-portal", // Multi-tenancy
192
+ * metadata: { rating: 5, verified: true }
193
+ * })
194
+ * ```
151
195
  */
152
196
  async add(params) {
153
197
  await this.ensureInitialized();
@@ -193,6 +237,74 @@ export class Brainy {
193
237
  }
194
238
  /**
195
239
  * Get an entity by ID
240
+ *
241
+ * @param id - The unique identifier of the entity to retrieve
242
+ * @returns Promise that resolves to the entity if found, null if not found
243
+ *
244
+ * @example
245
+ * // Basic entity retrieval
246
+ * const entity = await brainy.get('user-123')
247
+ * if (entity) {
248
+ * console.log('Found entity:', entity.data)
249
+ * console.log('Created at:', new Date(entity.createdAt))
250
+ * } else {
251
+ * console.log('Entity not found')
252
+ * }
253
+ *
254
+ * @example
255
+ * // Working with typed entities
256
+ * interface User {
257
+ * name: string
258
+ * email: string
259
+ * }
260
+ *
261
+ * const brainy = new Brainy<User>({ storage: 'filesystem' })
262
+ * const user = await brainy.get('user-456')
263
+ * if (user) {
264
+ * // TypeScript knows user.metadata is of type User
265
+ * console.log(`Hello ${user.metadata.name}`)
266
+ * }
267
+ *
268
+ * @example
269
+ * // Safe retrieval with error handling
270
+ * try {
271
+ * const entity = await brainy.get('document-789')
272
+ * if (!entity) {
273
+ * throw new Error('Document not found')
274
+ * }
275
+ *
276
+ * // Process the entity
277
+ * return {
278
+ * id: entity.id,
279
+ * content: entity.data,
280
+ * type: entity.type,
281
+ * metadata: entity.metadata
282
+ * }
283
+ * } catch (error) {
284
+ * console.error('Failed to retrieve entity:', error)
285
+ * return null
286
+ * }
287
+ *
288
+ * @example
289
+ * // Batch retrieval pattern
290
+ * const ids = ['doc-1', 'doc-2', 'doc-3']
291
+ * const entities = await Promise.all(
292
+ * ids.map(id => brainy.get(id))
293
+ * )
294
+ * const foundEntities = entities.filter(entity => entity !== null)
295
+ * console.log(`Found ${foundEntities.length} out of ${ids.length} entities`)
296
+ *
297
+ * @example
298
+ * // Using with async iteration
299
+ * const entityIds = ['user-1', 'user-2', 'user-3']
300
+ *
301
+ * for (const id of entityIds) {
302
+ * const entity = await brainy.get(id)
303
+ * if (entity) {
304
+ * console.log(`Processing ${entity.type}: ${id}`)
305
+ * // Process entity...
306
+ * }
307
+ * }
196
308
  */
197
309
  async get(id) {
198
310
  await this.ensureInitialized();
@@ -317,6 +429,107 @@ export class Brainy {
317
429
  // ============= RELATIONSHIP OPERATIONS =============
318
430
  /**
319
431
  * Create a relationship between entities
432
+ *
433
+ * @param params - Parameters for creating the relationship
434
+ * @returns Promise that resolves to the relationship ID
435
+ *
436
+ * @example
437
+ * // Basic relationship creation
438
+ * const userId = await brainy.add({
439
+ * data: { name: 'John', role: 'developer' },
440
+ * type: NounType.Person
441
+ * })
442
+ * const projectId = await brainy.add({
443
+ * data: { name: 'AI Assistant', status: 'active' },
444
+ * type: NounType.Thing
445
+ * })
446
+ *
447
+ * const relationId = await brainy.relate({
448
+ * from: userId,
449
+ * to: projectId,
450
+ * type: VerbType.WorksOn
451
+ * })
452
+ *
453
+ * @example
454
+ * // Bidirectional relationships
455
+ * const friendshipId = await brainy.relate({
456
+ * from: 'user-1',
457
+ * to: 'user-2',
458
+ * type: VerbType.Knows,
459
+ * bidirectional: true // Creates both directions automatically
460
+ * })
461
+ *
462
+ * @example
463
+ * // Weighted relationships for importance/strength
464
+ * const collaborationId = await brainy.relate({
465
+ * from: 'team-lead',
466
+ * to: 'project-alpha',
467
+ * type: VerbType.LeadsOn,
468
+ * weight: 0.9, // High importance/strength
469
+ * metadata: {
470
+ * startDate: '2024-01-15',
471
+ * responsibility: 'technical leadership',
472
+ * hoursPerWeek: 40
473
+ * }
474
+ * })
475
+ *
476
+ * @example
477
+ * // Typed relationships with custom metadata
478
+ * interface CollaborationMeta {
479
+ * role: string
480
+ * startDate: string
481
+ * skillLevel: number
482
+ * }
483
+ *
484
+ * const brainy = new Brainy<CollaborationMeta>({ storage: 'filesystem' })
485
+ * const relationId = await brainy.relate({
486
+ * from: 'developer-123',
487
+ * to: 'project-456',
488
+ * type: VerbType.WorksOn,
489
+ * weight: 0.85,
490
+ * metadata: {
491
+ * role: 'frontend developer',
492
+ * startDate: '2024-03-01',
493
+ * skillLevel: 8
494
+ * }
495
+ * })
496
+ *
497
+ * @example
498
+ * // Creating complex relationship networks
499
+ * const entities = []
500
+ * // Create entities
501
+ * for (let i = 0; i < 5; i++) {
502
+ * const id = await brainy.add({
503
+ * data: { name: `Entity ${i}`, value: i * 10 },
504
+ * type: NounType.Thing
505
+ * })
506
+ * entities.push(id)
507
+ * }
508
+ *
509
+ * // Create hierarchical relationships
510
+ * for (let i = 0; i < entities.length - 1; i++) {
511
+ * await brainy.relate({
512
+ * from: entities[i],
513
+ * to: entities[i + 1],
514
+ * type: VerbType.DependsOn,
515
+ * weight: (i + 1) / entities.length
516
+ * })
517
+ * }
518
+ *
519
+ * @example
520
+ * // Error handling for invalid relationships
521
+ * try {
522
+ * await brainy.relate({
523
+ * from: 'nonexistent-entity',
524
+ * to: 'another-entity',
525
+ * type: VerbType.RelatedTo
526
+ * })
527
+ * } catch (error) {
528
+ * if (error.message.includes('not found')) {
529
+ * console.log('One or both entities do not exist')
530
+ * // Handle missing entities...
531
+ * }
532
+ * }
320
533
  */
321
534
  async relate(params) {
322
535
  await this.ensureInitialized();
@@ -417,6 +630,142 @@ export class Brainy {
417
630
  /**
418
631
  * Unified find method - supports natural language and structured queries
419
632
  * Implements Triple Intelligence with parallel search optimization
633
+ *
634
+ * @param query - Natural language string or structured FindParams object
635
+ * @returns Promise that resolves to array of search results with scores
636
+ *
637
+ * @example
638
+ * // Natural language queries (most common)
639
+ * const results = await brainy.find('users who work on AI projects')
640
+ * const docs = await brainy.find('documents about machine learning')
641
+ * const code = await brainy.find('JavaScript functions for data processing')
642
+ *
643
+ * @example
644
+ * // Structured queries with filtering
645
+ * const results = await brainy.find({
646
+ * query: 'artificial intelligence',
647
+ * type: NounType.Document,
648
+ * limit: 5,
649
+ * where: {
650
+ * status: 'published',
651
+ * author: 'expert'
652
+ * }
653
+ * })
654
+ *
655
+ * // Process results
656
+ * for (const result of results) {
657
+ * console.log(`Found: ${result.entity.data} (score: ${result.score})`)
658
+ * }
659
+ *
660
+ * @example
661
+ * // Metadata-only filtering (no vector search)
662
+ * const activeUsers = await brainy.find({
663
+ * type: NounType.Person,
664
+ * where: {
665
+ * status: 'active',
666
+ * department: 'engineering'
667
+ * },
668
+ * service: 'user-management'
669
+ * })
670
+ *
671
+ * @example
672
+ * // Vector similarity search with custom vectors
673
+ * const queryVector = await brainy.embed('machine learning algorithms')
674
+ * const similar = await brainy.find({
675
+ * vector: queryVector,
676
+ * limit: 10,
677
+ * type: [NounType.Document, NounType.Thing]
678
+ * })
679
+ *
680
+ * @example
681
+ * // Proximity search (find entities similar to existing ones)
682
+ * const relatedContent = await brainy.find({
683
+ * near: 'document-123', // Find entities similar to this one
684
+ * limit: 8,
685
+ * where: {
686
+ * published: true
687
+ * }
688
+ * })
689
+ *
690
+ * @example
691
+ * // Pagination for large result sets
692
+ * const firstPage = await brainy.find({
693
+ * query: 'research papers',
694
+ * limit: 20,
695
+ * offset: 0
696
+ * })
697
+ *
698
+ * const secondPage = await brainy.find({
699
+ * query: 'research papers',
700
+ * limit: 20,
701
+ * offset: 20
702
+ * })
703
+ *
704
+ * @example
705
+ * // Complex search with multiple criteria
706
+ * const results = await brainy.find({
707
+ * query: 'machine learning models',
708
+ * type: [NounType.Thing, NounType.Document],
709
+ * where: {
710
+ * accuracy: { $gte: 0.9 }, // Metadata filtering
711
+ * framework: { $in: ['tensorflow', 'pytorch'] }
712
+ * },
713
+ * service: 'ml-pipeline',
714
+ * limit: 15
715
+ * })
716
+ *
717
+ * @example
718
+ * // Empty query returns all entities (paginated)
719
+ * const allEntities = await brainy.find({
720
+ * limit: 50,
721
+ * offset: 0
722
+ * })
723
+ *
724
+ * @example
725
+ * // Performance-optimized search patterns
726
+ * // Fast metadata-only search (no vector computation)
727
+ * const fastResults = await brainy.find({
728
+ * type: NounType.Person,
729
+ * where: { active: true },
730
+ * limit: 100
731
+ * })
732
+ *
733
+ * // Combined vector + metadata for precision
734
+ * const preciseResults = await brainy.find({
735
+ * query: 'senior developers',
736
+ * where: {
737
+ * experience: { $gte: 5 },
738
+ * skills: { $includes: 'javascript' }
739
+ * },
740
+ * limit: 10
741
+ * })
742
+ *
743
+ * @example
744
+ * // Error handling and result processing
745
+ * try {
746
+ * const results = await brainy.find('complex query here')
747
+ *
748
+ * if (results.length === 0) {
749
+ * console.log('No results found')
750
+ * return
751
+ * }
752
+ *
753
+ * // Filter by confidence threshold
754
+ * const highConfidence = results.filter(r => r.score > 0.7)
755
+ *
756
+ * // Sort by score (already sorted by default)
757
+ * const topResults = results.slice(0, 5)
758
+ *
759
+ * return topResults.map(r => ({
760
+ * id: r.id,
761
+ * content: r.entity.data,
762
+ * confidence: r.score,
763
+ * metadata: r.entity.metadata
764
+ * }))
765
+ * } catch (error) {
766
+ * console.error('Search failed:', error)
767
+ * return []
768
+ * }
420
769
  */
421
770
  async find(query) {
422
771
  await this.ensureInitialized();
@@ -616,7 +965,113 @@ export class Brainy {
616
965
  return result;
617
966
  }
618
967
  /**
619
- * Find similar entities
968
+ * Find similar entities using vector similarity
969
+ *
970
+ * @param params - Parameters specifying the target for similarity search
971
+ * @returns Promise that resolves to array of similar entities with similarity scores
972
+ *
973
+ * @example
974
+ * // Find entities similar to a specific entity by ID
975
+ * const similarDocs = await brainy.similar({
976
+ * to: 'document-123',
977
+ * limit: 10
978
+ * })
979
+ *
980
+ * // Process similarity results
981
+ * for (const result of similarDocs) {
982
+ * console.log(`Similar entity: ${result.entity.data} (similarity: ${result.score})`)
983
+ * }
984
+ *
985
+ * @example
986
+ * // Find similar entities with type filtering
987
+ * const similarUsers = await brainy.similar({
988
+ * to: 'user-456',
989
+ * type: NounType.Person,
990
+ * limit: 5,
991
+ * where: {
992
+ * active: true,
993
+ * department: 'engineering'
994
+ * }
995
+ * })
996
+ *
997
+ * @example
998
+ * // Find similar using a custom vector
999
+ * const customVector = await brainy.embed('artificial intelligence research')
1000
+ * const similar = await brainy.similar({
1001
+ * to: customVector,
1002
+ * limit: 8,
1003
+ * type: [NounType.Document, NounType.Thing]
1004
+ * })
1005
+ *
1006
+ * @example
1007
+ * // Find similar using an entity object
1008
+ * const sourceEntity = await brainy.get('research-paper-789')
1009
+ * if (sourceEntity) {
1010
+ * const relatedPapers = await brainy.similar({
1011
+ * to: sourceEntity,
1012
+ * limit: 12,
1013
+ * where: {
1014
+ * published: true,
1015
+ * category: 'machine-learning'
1016
+ * }
1017
+ * })
1018
+ * }
1019
+ *
1020
+ * @example
1021
+ * // Content recommendation system
1022
+ * async function getRecommendations(userId: string) {
1023
+ * // Get user's recent interactions
1024
+ * const user = await brainy.get(userId)
1025
+ * if (!user) return []
1026
+ *
1027
+ * // Find similar content
1028
+ * const recommendations = await brainy.similar({
1029
+ * to: userId,
1030
+ * type: NounType.Document,
1031
+ * limit: 20,
1032
+ * where: {
1033
+ * published: true,
1034
+ * language: 'en'
1035
+ * }
1036
+ * })
1037
+ *
1038
+ * // Filter out already seen content
1039
+ * return recommendations.filter(rec =>
1040
+ * !user.metadata.viewedItems?.includes(rec.id)
1041
+ * )
1042
+ * }
1043
+ *
1044
+ * @example
1045
+ * // Duplicate detection system
1046
+ * async function findPotentialDuplicates(entityId: string) {
1047
+ * const duplicates = await brainy.similar({
1048
+ * to: entityId,
1049
+ * limit: 10
1050
+ * })
1051
+ *
1052
+ * // High similarity might indicate duplicates
1053
+ * const highSimilarity = duplicates.filter(d => d.score > 0.95)
1054
+ *
1055
+ * if (highSimilarity.length > 0) {
1056
+ * console.log('Potential duplicates found:', highSimilarity.map(d => d.id))
1057
+ * }
1058
+ *
1059
+ * return highSimilarity
1060
+ * }
1061
+ *
1062
+ * @example
1063
+ * // Error handling for missing entities
1064
+ * try {
1065
+ * const similar = await brainy.similar({
1066
+ * to: 'nonexistent-entity',
1067
+ * limit: 5
1068
+ * })
1069
+ * } catch (error) {
1070
+ * if (error.message.includes('not found')) {
1071
+ * console.log('Source entity does not exist')
1072
+ * // Handle missing source entity
1073
+ * }
1074
+ * }
620
1075
  */
621
1076
  async similar(params) {
622
1077
  await this.ensureInitialized();
@@ -1463,8 +1918,117 @@ export class Brainy {
1463
1918
  }));
1464
1919
  }
1465
1920
  /**
1466
- * Embed data into vector
1467
- * Handles any data type by converting to string representation
1921
+ * Embed data into vector representation
1922
+ * Handles any data type by intelligently converting to string representation
1923
+ *
1924
+ * @param data - Any data to convert to vector (string, object, array, etc.)
1925
+ * @returns Promise that resolves to a numerical vector representation
1926
+ *
1927
+ * @example
1928
+ * // Basic string embedding
1929
+ * const vector = await brainy.embed('machine learning algorithms')
1930
+ * console.log('Vector dimensions:', vector.length)
1931
+ *
1932
+ * @example
1933
+ * // Object embedding with intelligent field extraction
1934
+ * const documentVector = await brainy.embed({
1935
+ * title: 'AI Research Paper',
1936
+ * content: 'This paper discusses neural networks...',
1937
+ * author: 'Dr. Smith',
1938
+ * category: 'machine-learning'
1939
+ * })
1940
+ * // Uses 'content' field for embedding by default
1941
+ *
1942
+ * @example
1943
+ * // Different object field priorities
1944
+ * // Priority: data > content > text > name > title > description
1945
+ * const vectors = await Promise.all([
1946
+ * brainy.embed({ data: 'primary content' }), // Uses 'data'
1947
+ * brainy.embed({ content: 'main content' }), // Uses 'content'
1948
+ * brainy.embed({ text: 'text content' }), // Uses 'text'
1949
+ * brainy.embed({ name: 'entity name' }), // Uses 'name'
1950
+ * brainy.embed({ title: 'document title' }), // Uses 'title'
1951
+ * brainy.embed({ description: 'description text' }) // Uses 'description'
1952
+ * ])
1953
+ *
1954
+ * @example
1955
+ * // Array embedding for batch processing
1956
+ * const batchVectors = await brainy.embed([
1957
+ * 'first document',
1958
+ * 'second document',
1959
+ * { content: 'third document as object' },
1960
+ * { title: 'fourth document' }
1961
+ * ])
1962
+ * // Returns vector representing all items combined
1963
+ *
1964
+ * @example
1965
+ * // Complex object handling
1966
+ * const complexData = {
1967
+ * user: { name: 'John', role: 'developer' },
1968
+ * project: { name: 'AI Assistant', status: 'active' },
1969
+ * metrics: { score: 0.95, performance: 'excellent' }
1970
+ * }
1971
+ * const vector = await brainy.embed(complexData)
1972
+ * // Converts entire object to JSON for embedding
1973
+ *
1974
+ * @example
1975
+ * // Pre-computing vectors for performance optimization
1976
+ * const documents = [
1977
+ * { id: 'doc1', content: 'Document 1 content...' },
1978
+ * { id: 'doc2', content: 'Document 2 content...' },
1979
+ * { id: 'doc3', content: 'Document 3 content...' }
1980
+ * ]
1981
+ *
1982
+ * // Pre-compute all vectors
1983
+ * const vectors = await Promise.all(
1984
+ * documents.map(doc => brainy.embed(doc.content))
1985
+ * )
1986
+ *
1987
+ * // Add entities with pre-computed vectors (faster)
1988
+ * for (let i = 0; i < documents.length; i++) {
1989
+ * await brainy.add({
1990
+ * data: documents[i],
1991
+ * type: NounType.Document,
1992
+ * vector: vectors[i] // Skip embedding computation
1993
+ * })
1994
+ * }
1995
+ *
1996
+ * @example
1997
+ * // Custom embedding for search queries
1998
+ * async function searchWithCustomEmbedding(query: string) {
1999
+ * // Enhance query for better matching
2000
+ * const enhancedQuery = `search: ${query} relevant information`
2001
+ * const queryVector = await brainy.embed(enhancedQuery)
2002
+ *
2003
+ * // Use pre-computed vector for search
2004
+ * return brainy.find({
2005
+ * vector: queryVector,
2006
+ * limit: 10
2007
+ * })
2008
+ * }
2009
+ *
2010
+ * @example
2011
+ * // Handling edge cases gracefully
2012
+ * const edgeCases = await Promise.all([
2013
+ * brainy.embed(null), // Returns vector for empty string
2014
+ * brainy.embed(undefined), // Returns vector for empty string
2015
+ * brainy.embed(''), // Returns vector for empty string
2016
+ * brainy.embed(42), // Converts number to string
2017
+ * brainy.embed(true), // Converts boolean to string
2018
+ * brainy.embed([]), // Empty array handling
2019
+ * brainy.embed({}) // Empty object handling
2020
+ * ])
2021
+ *
2022
+ * @example
2023
+ * // Using with similarity comparisons
2024
+ * const doc1Vector = await brainy.embed('artificial intelligence research')
2025
+ * const doc2Vector = await brainy.embed('machine learning algorithms')
2026
+ *
2027
+ * // Find entities similar to doc1Vector
2028
+ * const similar = await brainy.find({
2029
+ * vector: doc1Vector,
2030
+ * limit: 5
2031
+ * })
1468
2032
  */
1469
2033
  async embed(data) {
1470
2034
  // Handle different data types intelligently