@soulcraft/brainy 3.17.0 → 3.18.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.
Files changed (38) hide show
  1. package/README.md +5 -6
  2. package/dist/augmentations/defaultAugmentations.d.ts +0 -1
  3. package/dist/augmentations/defaultAugmentations.js +0 -5
  4. package/dist/brainy.d.ts +46 -0
  5. package/dist/brainy.js +53 -0
  6. package/dist/neural/embeddedPatterns.d.ts +1 -1
  7. package/dist/neural/embeddedPatterns.js +1 -1
  8. package/dist/neural/naturalLanguageProcessor.js +0 -1
  9. package/dist/setup.js +0 -1
  10. package/dist/unified.js +0 -1
  11. package/dist/vfs/VirtualFileSystem.d.ts +6 -4
  12. package/dist/vfs/VirtualFileSystem.js +44 -21
  13. package/dist/vfs/index.d.ts +0 -5
  14. package/dist/vfs/index.js +0 -6
  15. package/dist/vfs/semantic/ProjectionRegistry.d.ts +84 -0
  16. package/dist/vfs/semantic/ProjectionRegistry.js +118 -0
  17. package/dist/vfs/semantic/ProjectionStrategy.d.ts +69 -0
  18. package/dist/vfs/semantic/ProjectionStrategy.js +40 -0
  19. package/dist/vfs/semantic/SemanticPathParser.d.ts +73 -0
  20. package/dist/vfs/semantic/SemanticPathParser.js +285 -0
  21. package/dist/vfs/semantic/SemanticPathResolver.d.ts +99 -0
  22. package/dist/vfs/semantic/SemanticPathResolver.js +242 -0
  23. package/dist/vfs/semantic/index.d.ts +17 -0
  24. package/dist/vfs/semantic/index.js +18 -0
  25. package/dist/vfs/semantic/projections/AuthorProjection.d.ts +35 -0
  26. package/dist/vfs/semantic/projections/AuthorProjection.js +74 -0
  27. package/dist/vfs/semantic/projections/ConceptProjection.d.ts +42 -0
  28. package/dist/vfs/semantic/projections/ConceptProjection.js +87 -0
  29. package/dist/vfs/semantic/projections/RelationshipProjection.d.ts +41 -0
  30. package/dist/vfs/semantic/projections/RelationshipProjection.js +101 -0
  31. package/dist/vfs/semantic/projections/SimilarityProjection.d.ts +36 -0
  32. package/dist/vfs/semantic/projections/SimilarityProjection.js +77 -0
  33. package/dist/vfs/semantic/projections/TagProjection.d.ts +34 -0
  34. package/dist/vfs/semantic/projections/TagProjection.js +73 -0
  35. package/dist/vfs/semantic/projections/TemporalProjection.d.ts +35 -0
  36. package/dist/vfs/semantic/projections/TemporalProjection.js +89 -0
  37. package/dist/vfs/types.d.ts +1 -8
  38. package/package.json +1 -1
@@ -0,0 +1,242 @@
1
+ /**
2
+ * Semantic Path Resolver
3
+ *
4
+ * Unified path resolver that handles BOTH:
5
+ * - Traditional hierarchical paths (/src/auth/login.ts)
6
+ * - Semantic projection paths (/by-concept/authentication/...)
7
+ *
8
+ * Uses EXISTING infrastructure:
9
+ * - PathResolver for traditional paths
10
+ * - ProjectionRegistry for semantic dimensions
11
+ * - SemanticPathParser for path type detection
12
+ */
13
+ import { PathResolver } from '../PathResolver.js';
14
+ import { VFSError, VFSErrorCode } from '../types.js';
15
+ import { SemanticPathParser } from './SemanticPathParser.js';
16
+ import { UnifiedCache } from '../../utils/unifiedCache.js';
17
+ /**
18
+ * Semantic Path Resolver
19
+ * Handles both traditional and semantic paths transparently
20
+ *
21
+ * Uses Brainy's UnifiedCache for optimal memory management and performance
22
+ */
23
+ export class SemanticPathResolver {
24
+ constructor(brain, vfs, rootEntityId, registry) {
25
+ this.brain = brain;
26
+ this.vfs = vfs;
27
+ this.registry = registry;
28
+ this.parser = new SemanticPathParser();
29
+ // Use Brainy's UnifiedCache for semantic path caching
30
+ // Zero-config: Uses 2GB default from UnifiedCache
31
+ this.cache = new UnifiedCache({
32
+ enableRequestCoalescing: true,
33
+ enableFairnessCheck: true
34
+ });
35
+ // Create traditional path resolver (uses its own optimized cache with defaults)
36
+ this.pathResolver = new PathResolver(brain, rootEntityId);
37
+ }
38
+ /**
39
+ * Resolve a path to entity ID(s)
40
+ * Handles BOTH traditional and semantic paths
41
+ *
42
+ * For traditional paths: Returns single entity ID
43
+ * For semantic paths: Returns first matching entity ID
44
+ *
45
+ * Uses UnifiedCache with request coalescing to prevent stampede
46
+ *
47
+ * @param path - Path to resolve (traditional or semantic)
48
+ * @param options - Resolution options
49
+ * @returns Entity ID
50
+ */
51
+ async resolve(path, options) {
52
+ // Parse the path to determine dimension
53
+ const parsed = this.parser.parse(path);
54
+ // Handle based on path dimension
55
+ if (parsed.dimension === 'traditional') {
56
+ // Use existing PathResolver for traditional paths
57
+ return await this.pathResolver.resolve(path, options);
58
+ }
59
+ // Semantic path - use UnifiedCache with request coalescing
60
+ const cacheKey = `semantic:${path}`;
61
+ if (options?.cache === false) {
62
+ // Skip cache if requested
63
+ const entityIds = await this.resolveSemanticPathInternal(parsed);
64
+ if (entityIds.length === 0) {
65
+ throw new VFSError(VFSErrorCode.ENOENT, `No entities found for semantic path: ${path}`, path, 'resolve');
66
+ }
67
+ return entityIds[0];
68
+ }
69
+ // Use UnifiedCache - automatically handles stampede prevention
70
+ const entityIds = await this.cache.get(cacheKey, async () => {
71
+ return await this.resolveSemanticPathInternal(parsed);
72
+ });
73
+ if (!entityIds || entityIds.length === 0) {
74
+ throw new VFSError(VFSErrorCode.ENOENT, `No entities found for semantic path: ${path}`, path, 'resolve');
75
+ }
76
+ return entityIds[0];
77
+ }
78
+ /**
79
+ * Resolve semantic path to multiple entity IDs
80
+ * This is the polymorphic resolution that returns ALL matches
81
+ *
82
+ * Uses UnifiedCache for performance
83
+ *
84
+ * @param path - Semantic path
85
+ * @param options - Resolution options
86
+ * @returns Array of entity IDs
87
+ */
88
+ async resolveAll(path, options) {
89
+ const parsed = this.parser.parse(path);
90
+ if (parsed.dimension === 'traditional') {
91
+ // Traditional paths resolve to single entity
92
+ const id = await this.pathResolver.resolve(path, options);
93
+ return [id];
94
+ }
95
+ // Use cache if enabled
96
+ const cacheKey = `semantic:${path}`;
97
+ if (options?.cache === false) {
98
+ return await this.resolveSemanticPathInternal(parsed, options?.limit);
99
+ }
100
+ // UnifiedCache with automatic stampede prevention
101
+ return await this.cache.get(cacheKey, async () => {
102
+ return await this.resolveSemanticPathInternal(parsed, options?.limit);
103
+ });
104
+ }
105
+ /**
106
+ * Internal semantic path resolution (called by cache)
107
+ * Estimates cost and size for UnifiedCache optimization
108
+ */
109
+ async resolveSemanticPathInternal(parsed, limit) {
110
+ // Resolve based on dimension
111
+ let entityIds = [];
112
+ switch (parsed.dimension) {
113
+ case 'concept':
114
+ entityIds = await this.registry.resolve('concept', parsed.value, this.brain, this.vfs);
115
+ break;
116
+ case 'author':
117
+ entityIds = await this.registry.resolve('author', parsed.value, this.brain, this.vfs);
118
+ break;
119
+ case 'time':
120
+ entityIds = await this.registry.resolve('time', parsed.value, this.brain, this.vfs);
121
+ break;
122
+ case 'relationship':
123
+ entityIds = await this.registry.resolve('relationship', parsed.value, this.brain, this.vfs);
124
+ break;
125
+ case 'similar':
126
+ entityIds = await this.registry.resolve('similar', parsed.value, this.brain, this.vfs);
127
+ break;
128
+ case 'tag':
129
+ // Tags use metadata filtering (concept-like)
130
+ entityIds = await this.registry.resolve('tag', parsed.value, this.brain, this.vfs);
131
+ break;
132
+ case 'traditional':
133
+ // Shouldn't reach here, but handle it gracefully
134
+ return [];
135
+ default:
136
+ throw new VFSError(VFSErrorCode.ENOTDIR, // Use existing error code
137
+ `Unsupported semantic path dimension: ${parsed.dimension}`, '', 'resolve');
138
+ }
139
+ // Apply subpath filter if specified
140
+ if (parsed.subpath) {
141
+ entityIds = await this.filterBySubpath(entityIds, parsed.subpath);
142
+ }
143
+ // Apply limit
144
+ if (limit && limit > 0) {
145
+ entityIds = entityIds.slice(0, limit);
146
+ }
147
+ // Result will be cached by UnifiedCache.get() automatically
148
+ return entityIds;
149
+ }
150
+ /**
151
+ * Filter entity IDs by subpath (filename or partial path)
152
+ */
153
+ async filterBySubpath(entityIds, subpath) {
154
+ const filtered = [];
155
+ for (const id of entityIds) {
156
+ const entity = await this.brain.get(id);
157
+ if (!entity)
158
+ continue;
159
+ const name = entity.metadata?.name;
160
+ const path = entity.metadata?.path;
161
+ // Check if name or path matches subpath
162
+ if (name === subpath || path?.endsWith(subpath)) {
163
+ filtered.push(id);
164
+ }
165
+ }
166
+ return filtered;
167
+ }
168
+ /**
169
+ * Get children of a directory
170
+ * Delegates to PathResolver for traditional directories
171
+ * For semantic paths, returns entities in that dimension
172
+ */
173
+ async getChildren(dirIdOrPath) {
174
+ // If it looks like a path, parse it
175
+ if (dirIdOrPath.startsWith('/')) {
176
+ const parsed = this.parser.parse(dirIdOrPath);
177
+ if (parsed.dimension !== 'traditional') {
178
+ // For semantic paths, list entities in that dimension
179
+ return await this.listSemanticDimension(parsed);
180
+ }
181
+ }
182
+ // Traditional directory - use PathResolver
183
+ return await this.pathResolver.getChildren(dirIdOrPath);
184
+ }
185
+ /**
186
+ * List entities in a semantic dimension
187
+ */
188
+ async listSemanticDimension(parsed) {
189
+ switch (parsed.dimension) {
190
+ case 'concept':
191
+ return await this.registry.list('concept', this.brain, this.vfs);
192
+ case 'author':
193
+ return await this.registry.list('author', this.brain, this.vfs);
194
+ case 'time':
195
+ return await this.registry.list('time', this.brain, this.vfs);
196
+ case 'tag':
197
+ return await this.registry.list('tag', this.brain, this.vfs);
198
+ default:
199
+ return [];
200
+ }
201
+ }
202
+ /**
203
+ * Create a path mapping (cache a path resolution)
204
+ * Only applies to traditional paths
205
+ */
206
+ async createPath(path, entityId) {
207
+ const parsed = this.parser.parse(path);
208
+ if (parsed.dimension === 'traditional') {
209
+ await this.pathResolver.createPath(path, entityId);
210
+ }
211
+ // Semantic paths are not cached via createPath
212
+ }
213
+ /**
214
+ * Invalidate path cache
215
+ */
216
+ invalidatePath(path, recursive = false) {
217
+ const parsed = this.parser.parse(path);
218
+ if (parsed.dimension === 'traditional') {
219
+ this.pathResolver.invalidatePath(path, recursive);
220
+ }
221
+ else {
222
+ // Invalidate semantic cache via UnifiedCache
223
+ const cacheKey = `semantic:${path}`;
224
+ this.cache.delete(cacheKey);
225
+ }
226
+ }
227
+ /**
228
+ * Clear all semantic caches
229
+ * Uses UnifiedCache's clear method
230
+ */
231
+ invalidateSemanticCache() {
232
+ this.cache.clear();
233
+ }
234
+ /**
235
+ * Cleanup resources
236
+ */
237
+ cleanup() {
238
+ this.pathResolver.cleanup();
239
+ this.cache.clear();
240
+ }
241
+ }
242
+ //# sourceMappingURL=SemanticPathResolver.js.map
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Semantic VFS - Index
3
+ *
4
+ * Central export point for all semantic VFS components
5
+ */
6
+ export { SemanticPathParser } from './SemanticPathParser.js';
7
+ export type { SemanticDimension, ParsedSemanticPath, RelationshipValue, SimilarityValue } from './SemanticPathParser.js';
8
+ export { ProjectionRegistry } from './ProjectionRegistry.js';
9
+ export type { ProjectionStrategy } from './ProjectionStrategy.js';
10
+ export { BaseProjectionStrategy } from './ProjectionStrategy.js';
11
+ export { SemanticPathResolver } from './SemanticPathResolver.js';
12
+ export { ConceptProjection } from './projections/ConceptProjection.js';
13
+ export { AuthorProjection } from './projections/AuthorProjection.js';
14
+ export { TemporalProjection } from './projections/TemporalProjection.js';
15
+ export { RelationshipProjection } from './projections/RelationshipProjection.js';
16
+ export { SimilarityProjection } from './projections/SimilarityProjection.js';
17
+ export { TagProjection } from './projections/TagProjection.js';
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Semantic VFS - Index
3
+ *
4
+ * Central export point for all semantic VFS components
5
+ */
6
+ // Core components
7
+ export { SemanticPathParser } from './SemanticPathParser.js';
8
+ export { ProjectionRegistry } from './ProjectionRegistry.js';
9
+ export { BaseProjectionStrategy } from './ProjectionStrategy.js';
10
+ export { SemanticPathResolver } from './SemanticPathResolver.js';
11
+ // Built-in projections
12
+ export { ConceptProjection } from './projections/ConceptProjection.js';
13
+ export { AuthorProjection } from './projections/AuthorProjection.js';
14
+ export { TemporalProjection } from './projections/TemporalProjection.js';
15
+ export { RelationshipProjection } from './projections/RelationshipProjection.js';
16
+ export { SimilarityProjection } from './projections/SimilarityProjection.js';
17
+ export { TagProjection } from './projections/TagProjection.js';
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Author Projection Strategy
3
+ *
4
+ * Maps author-based paths to files owned by that author
5
+ * Uses EXISTING MetadataIndexManager for O(log n) queries
6
+ */
7
+ import { Brainy } from '../../../brainy.js';
8
+ import { VirtualFileSystem } from '../../VirtualFileSystem.js';
9
+ import { FindParams } from '../../../types/brainy.types.js';
10
+ import { BaseProjectionStrategy } from '../ProjectionStrategy.js';
11
+ import { VFSEntity } from '../../types.js';
12
+ /**
13
+ * Author Projection: /by-author/<authorName>/<subpath>
14
+ *
15
+ * Uses EXISTING infrastructure:
16
+ * - Brainy.find() with metadata filters (REAL)
17
+ * - MetadataIndexManager for O(log n) owner queries (REAL)
18
+ * - VFSMetadata.owner field (REAL - types.ts line 44)
19
+ */
20
+ export declare class AuthorProjection extends BaseProjectionStrategy {
21
+ readonly name = "author";
22
+ /**
23
+ * Convert author name to Brainy FindParams
24
+ */
25
+ toQuery(authorName: string, subpath?: string): FindParams;
26
+ /**
27
+ * Resolve author to entity IDs using REAL Brainy.find()
28
+ */
29
+ resolve(brain: Brainy, vfs: VirtualFileSystem, authorName: string): Promise<string[]>;
30
+ /**
31
+ * List all unique authors
32
+ * Uses aggregation over metadata
33
+ */
34
+ list(brain: Brainy, vfs: VirtualFileSystem, limit?: number): Promise<VFSEntity[]>;
35
+ }
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Author Projection Strategy
3
+ *
4
+ * Maps author-based paths to files owned by that author
5
+ * Uses EXISTING MetadataIndexManager for O(log n) queries
6
+ */
7
+ import { BaseProjectionStrategy } from '../ProjectionStrategy.js';
8
+ /**
9
+ * Author Projection: /by-author/<authorName>/<subpath>
10
+ *
11
+ * Uses EXISTING infrastructure:
12
+ * - Brainy.find() with metadata filters (REAL)
13
+ * - MetadataIndexManager for O(log n) owner queries (REAL)
14
+ * - VFSMetadata.owner field (REAL - types.ts line 44)
15
+ */
16
+ export class AuthorProjection extends BaseProjectionStrategy {
17
+ constructor() {
18
+ super(...arguments);
19
+ this.name = 'author';
20
+ }
21
+ /**
22
+ * Convert author name to Brainy FindParams
23
+ */
24
+ toQuery(authorName, subpath) {
25
+ const query = {
26
+ where: {
27
+ vfsType: 'file',
28
+ owner: authorName
29
+ },
30
+ limit: 1000
31
+ };
32
+ // Filter by filename if subpath specified
33
+ if (subpath) {
34
+ query.where = {
35
+ ...query.where,
36
+ anyOf: [
37
+ { name: subpath },
38
+ { path: { endsWith: subpath } } // BFO operator (not $regex)
39
+ ]
40
+ };
41
+ }
42
+ return query;
43
+ }
44
+ /**
45
+ * Resolve author to entity IDs using REAL Brainy.find()
46
+ */
47
+ async resolve(brain, vfs, authorName) {
48
+ // Use REAL Brainy metadata filtering
49
+ const results = await brain.find({
50
+ where: {
51
+ vfsType: 'file',
52
+ owner: authorName
53
+ },
54
+ limit: 1000
55
+ });
56
+ return this.extractIds(results);
57
+ }
58
+ /**
59
+ * List all unique authors
60
+ * Uses aggregation over metadata
61
+ */
62
+ async list(brain, vfs, limit = 100) {
63
+ // Get all files with owner metadata
64
+ const results = await brain.find({
65
+ where: {
66
+ vfsType: 'file',
67
+ owner: { $exists: true }
68
+ },
69
+ limit
70
+ });
71
+ return results.map(r => r.entity);
72
+ }
73
+ }
74
+ //# sourceMappingURL=AuthorProjection.js.map
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Concept Projection Strategy
3
+ *
4
+ * Maps concept-based paths to files containing those concepts
5
+ * Uses EXISTING ConceptSystem and MetadataIndexManager
6
+ */
7
+ import { Brainy } from '../../../brainy.js';
8
+ import { VirtualFileSystem } from '../../VirtualFileSystem.js';
9
+ import { FindParams } from '../../../types/brainy.types.js';
10
+ import { BaseProjectionStrategy } from '../ProjectionStrategy.js';
11
+ import { VFSEntity } from '../../types.js';
12
+ /**
13
+ * Concept Projection: /by-concept/<conceptName>/<subpath>
14
+ *
15
+ * Uses EXISTING infrastructure:
16
+ * - Brainy.find() with metadata filters (REAL - line 580 in brainy.ts)
17
+ * - MetadataIndexManager for O(log n) concept queries (REAL)
18
+ * - ConceptSystem for concept extraction (REAL - ConceptSystem.ts)
19
+ */
20
+ export declare class ConceptProjection extends BaseProjectionStrategy {
21
+ readonly name = "concept";
22
+ /**
23
+ * Convert concept name to Brainy FindParams
24
+ * Uses EXISTING FindParams.where for metadata filtering
25
+ *
26
+ * Now uses flattened conceptNames array for O(log n) performance!
27
+ */
28
+ toQuery(conceptName: string, subpath?: string): FindParams;
29
+ /**
30
+ * Resolve concept to entity IDs using REAL Brainy.find()
31
+ * VERIFIED: brain.find() exists at line 580 in brainy.ts
32
+ *
33
+ * NOW OPTIMIZED: Uses flattened conceptNames for O(log n) indexed queries!
34
+ * No more post-filtering - direct index lookup
35
+ */
36
+ resolve(brain: Brainy, vfs: VirtualFileSystem, conceptName: string): Promise<string[]>;
37
+ /**
38
+ * List all files with concept metadata
39
+ * Uses REAL Brainy.find() with metadata filter
40
+ */
41
+ list(brain: Brainy, vfs: VirtualFileSystem, limit?: number): Promise<VFSEntity[]>;
42
+ }
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Concept Projection Strategy
3
+ *
4
+ * Maps concept-based paths to files containing those concepts
5
+ * Uses EXISTING ConceptSystem and MetadataIndexManager
6
+ */
7
+ import { BaseProjectionStrategy } from '../ProjectionStrategy.js';
8
+ /**
9
+ * Concept Projection: /by-concept/<conceptName>/<subpath>
10
+ *
11
+ * Uses EXISTING infrastructure:
12
+ * - Brainy.find() with metadata filters (REAL - line 580 in brainy.ts)
13
+ * - MetadataIndexManager for O(log n) concept queries (REAL)
14
+ * - ConceptSystem for concept extraction (REAL - ConceptSystem.ts)
15
+ */
16
+ export class ConceptProjection extends BaseProjectionStrategy {
17
+ constructor() {
18
+ super(...arguments);
19
+ this.name = 'concept';
20
+ }
21
+ /**
22
+ * Convert concept name to Brainy FindParams
23
+ * Uses EXISTING FindParams.where for metadata filtering
24
+ *
25
+ * Now uses flattened conceptNames array for O(log n) performance!
26
+ */
27
+ toQuery(conceptName, subpath) {
28
+ const query = {
29
+ where: {
30
+ vfsType: 'file',
31
+ conceptNames: { contains: conceptName } // O(log n) indexed query
32
+ },
33
+ limit: 1000
34
+ };
35
+ // If subpath specified, also filter by filename
36
+ if (subpath) {
37
+ query.where = {
38
+ ...query.where,
39
+ anyOf: [
40
+ { name: subpath },
41
+ { path: { endsWith: subpath } } // BFO operator
42
+ ]
43
+ };
44
+ }
45
+ return query;
46
+ }
47
+ /**
48
+ * Resolve concept to entity IDs using REAL Brainy.find()
49
+ * VERIFIED: brain.find() exists at line 580 in brainy.ts
50
+ *
51
+ * NOW OPTIMIZED: Uses flattened conceptNames for O(log n) indexed queries!
52
+ * No more post-filtering - direct index lookup
53
+ */
54
+ async resolve(brain, vfs, conceptName) {
55
+ // Verify brain.find is a function (safety check)
56
+ if (typeof brain.find !== 'function') {
57
+ throw new Error('VERIFICATION FAILED: brain.find is not a function');
58
+ }
59
+ // Direct O(log n) query using flattened conceptNames array
60
+ // VFS automatically flattens concepts to conceptNames on write
61
+ const results = await brain.find({
62
+ where: {
63
+ vfsType: 'file',
64
+ conceptNames: { contains: conceptName } // Indexed array query
65
+ },
66
+ limit: 1000
67
+ });
68
+ return this.extractIds(results);
69
+ }
70
+ /**
71
+ * List all files with concept metadata
72
+ * Uses REAL Brainy.find() with metadata filter
73
+ */
74
+ async list(brain, vfs, limit = 100) {
75
+ const results = await brain.find({
76
+ where: {
77
+ vfsType: 'file',
78
+ conceptNames: { exists: true } // Use flattened field
79
+ },
80
+ limit
81
+ });
82
+ // Convert to VFSEntity array
83
+ // VERIFIED: Result.entity exists in brainy.types.ts
84
+ return results.map(r => r.entity);
85
+ }
86
+ }
87
+ //# sourceMappingURL=ConceptProjection.js.map
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Relationship Projection Strategy
3
+ *
4
+ * Maps relationship-based paths to files connected in the knowledge graph
5
+ * Uses EXISTING GraphAdjacencyIndex for O(1) traversal
6
+ */
7
+ import { Brainy } from '../../../brainy.js';
8
+ import { VirtualFileSystem } from '../../VirtualFileSystem.js';
9
+ import { FindParams } from '../../../types/brainy.types.js';
10
+ import { BaseProjectionStrategy } from '../ProjectionStrategy.js';
11
+ import { RelationshipValue } from '../SemanticPathParser.js';
12
+ /**
13
+ * Relationship Projection: /related-to/<path>/depth-N/types-X,Y
14
+ *
15
+ * Uses EXISTING infrastructure:
16
+ * - Brainy.getRelations() for graph traversal (REAL - line 803 in brainy.ts)
17
+ * - GraphAdjacencyIndex for O(1) neighbor lookups (REAL)
18
+ * - VerbType enum for relationship types (REAL - graphTypes.ts)
19
+ */
20
+ export declare class RelationshipProjection extends BaseProjectionStrategy {
21
+ readonly name = "relationship";
22
+ /**
23
+ * Convert relationship value to Brainy FindParams
24
+ * Note: Graph queries don't use FindParams, but we provide this for consistency
25
+ */
26
+ toQuery(value: RelationshipValue, subpath?: string): FindParams;
27
+ /**
28
+ * Resolve relationships using REAL Brainy.getRelations()
29
+ * Uses GraphAdjacencyIndex for O(1) graph traversal
30
+ */
31
+ resolve(brain: Brainy, vfs: VirtualFileSystem, value: RelationshipValue): Promise<string[]>;
32
+ /**
33
+ * Recursive graph traversal using REAL Brainy.getRelations()
34
+ */
35
+ private traverseRelationships;
36
+ /**
37
+ * Resolve path to entity ID
38
+ * Helper to convert traditional path to entity ID
39
+ */
40
+ private resolvePathToId;
41
+ }
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Relationship Projection Strategy
3
+ *
4
+ * Maps relationship-based paths to files connected in the knowledge graph
5
+ * Uses EXISTING GraphAdjacencyIndex for O(1) traversal
6
+ */
7
+ import { BaseProjectionStrategy } from '../ProjectionStrategy.js';
8
+ /**
9
+ * Relationship Projection: /related-to/<path>/depth-N/types-X,Y
10
+ *
11
+ * Uses EXISTING infrastructure:
12
+ * - Brainy.getRelations() for graph traversal (REAL - line 803 in brainy.ts)
13
+ * - GraphAdjacencyIndex for O(1) neighbor lookups (REAL)
14
+ * - VerbType enum for relationship types (REAL - graphTypes.ts)
15
+ */
16
+ export class RelationshipProjection extends BaseProjectionStrategy {
17
+ constructor() {
18
+ super(...arguments);
19
+ this.name = 'relationship';
20
+ }
21
+ /**
22
+ * Convert relationship value to Brainy FindParams
23
+ * Note: Graph queries don't use FindParams, but we provide this for consistency
24
+ */
25
+ toQuery(value, subpath) {
26
+ // This is informational - actual resolution uses getRelations()
27
+ return {
28
+ where: {
29
+ vfsType: 'file'
30
+ },
31
+ connected: {
32
+ to: value.targetPath,
33
+ depth: value.depth || 1
34
+ },
35
+ limit: 1000
36
+ };
37
+ }
38
+ /**
39
+ * Resolve relationships using REAL Brainy.getRelations()
40
+ * Uses GraphAdjacencyIndex for O(1) graph traversal
41
+ */
42
+ async resolve(brain, vfs, value) {
43
+ // Step 1: Resolve target path to entity ID
44
+ const targetId = await this.resolvePathToId(vfs, value.targetPath);
45
+ if (!targetId) {
46
+ return [];
47
+ }
48
+ // Step 2: Get relationships using REAL Brainy graph
49
+ const depth = value.depth || 1;
50
+ const visited = new Set();
51
+ const results = [];
52
+ await this.traverseRelationships(brain, targetId, depth, visited, results, value.relationshipTypes);
53
+ // Filter to only files
54
+ return await this.filterFiles(brain, results);
55
+ }
56
+ /**
57
+ * Recursive graph traversal using REAL Brainy.getRelations()
58
+ */
59
+ async traverseRelationships(brain, entityId, remainingDepth, visited, results, types) {
60
+ if (remainingDepth <= 0 || visited.has(entityId)) {
61
+ return;
62
+ }
63
+ visited.add(entityId);
64
+ // Get outgoing relationships (REAL method - line 803 in brainy.ts)
65
+ const relations = await brain.getRelations({
66
+ from: entityId,
67
+ limit: 100
68
+ });
69
+ for (const relation of relations) {
70
+ // Filter by relationship type if specified
71
+ if (types && types.length > 0) {
72
+ const relationshipName = relation.type?.toLowerCase();
73
+ if (!types.some(t => t.toLowerCase() === relationshipName)) {
74
+ continue;
75
+ }
76
+ }
77
+ // Add to results
78
+ if (!results.includes(relation.to)) {
79
+ results.push(relation.to);
80
+ }
81
+ // Recurse if depth remaining
82
+ if (remainingDepth > 1) {
83
+ await this.traverseRelationships(brain, relation.to, remainingDepth - 1, visited, results, types);
84
+ }
85
+ }
86
+ }
87
+ /**
88
+ * Resolve path to entity ID
89
+ * Helper to convert traditional path to entity ID
90
+ */
91
+ async resolvePathToId(vfs, path) {
92
+ try {
93
+ // Use REAL VFS public method
94
+ return await vfs.resolvePath(path);
95
+ }
96
+ catch {
97
+ return null;
98
+ }
99
+ }
100
+ }
101
+ //# sourceMappingURL=RelationshipProjection.js.map