@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,40 @@
1
+ /**
2
+ * Projection Strategy Interface
3
+ *
4
+ * Defines how to map semantic path dimensions to Brainy queries
5
+ * Each strategy uses EXISTING Brainy indexes and methods
6
+ */
7
+ /**
8
+ * Base class for projection strategies with common utilities
9
+ */
10
+ export class BaseProjectionStrategy {
11
+ /**
12
+ * Convert Brainy Results to entity IDs
13
+ * Helper method for subclasses
14
+ */
15
+ extractIds(results) {
16
+ return results.map(r => r.id);
17
+ }
18
+ /**
19
+ * Verify that an entity is a file (not directory)
20
+ * Uses REAL Brainy.get() method
21
+ */
22
+ async isFile(brain, entityId) {
23
+ const entity = await brain.get(entityId);
24
+ return entity?.metadata?.vfsType === 'file';
25
+ }
26
+ /**
27
+ * Filter entity IDs to only include files
28
+ * Uses REAL Brainy.get() for each entity
29
+ */
30
+ async filterFiles(brain, entityIds) {
31
+ const files = [];
32
+ for (const id of entityIds) {
33
+ if (await this.isFile(brain, id)) {
34
+ files.push(id);
35
+ }
36
+ }
37
+ return files;
38
+ }
39
+ }
40
+ //# sourceMappingURL=ProjectionStrategy.js.map
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Semantic Path Parser
3
+ *
4
+ * Parses semantic filesystem paths into structured queries
5
+ * PURE LOGIC - No external dependencies, no async operations
6
+ *
7
+ * Supported path formats:
8
+ * - Traditional: /src/auth.ts
9
+ * - By Concept: /by-concept/authentication/login.ts
10
+ * - By Author: /by-author/alice/file.ts
11
+ * - By Time: /as-of/2024-03-15/file.ts
12
+ * - By Relationship: /related-to/src/auth.ts/depth-2
13
+ * - By Similarity: /similar-to/src/auth.ts/threshold-0.8
14
+ * - By Tag: /by-tag/security/file.ts
15
+ */
16
+ export type SemanticDimension = 'traditional' | 'concept' | 'author' | 'time' | 'relationship' | 'similar' | 'tag';
17
+ export interface ParsedSemanticPath {
18
+ dimension: SemanticDimension;
19
+ value: string | Date | RelationshipValue | SimilarityValue;
20
+ subpath?: string;
21
+ filters?: Record<string, any>;
22
+ }
23
+ export interface RelationshipValue {
24
+ targetPath: string;
25
+ depth?: number;
26
+ relationshipTypes?: string[];
27
+ }
28
+ export interface SimilarityValue {
29
+ targetPath: string;
30
+ threshold?: number;
31
+ }
32
+ /**
33
+ * Semantic Path Parser
34
+ * Parses various semantic path formats into structured data
35
+ */
36
+ export declare class SemanticPathParser {
37
+ private static readonly PATTERNS;
38
+ /**
39
+ * Parse a path into semantic components
40
+ * PURE FUNCTION - no external calls, no async
41
+ */
42
+ parse(path: string): ParsedSemanticPath;
43
+ /**
44
+ * Check if a path is semantic (non-traditional)
45
+ */
46
+ isSemanticPath(path: string): boolean;
47
+ /**
48
+ * Get the dimension type from a path
49
+ */
50
+ getDimension(path: string): SemanticDimension;
51
+ /**
52
+ * Normalize a path - remove trailing slashes, collapse multiple slashes
53
+ * PURE FUNCTION
54
+ */
55
+ private normalizePath;
56
+ /**
57
+ * Parse date string (YYYY-MM-DD) into Date object
58
+ * PURE FUNCTION
59
+ */
60
+ private parseDate;
61
+ /**
62
+ * Validate parsed path structure
63
+ */
64
+ validate(parsed: ParsedSemanticPath): boolean;
65
+ /**
66
+ * Parse relationship paths: /related-to/<path>/depth-N/types-X,Y/<subpath>
67
+ */
68
+ private parseRelationshipPath;
69
+ /**
70
+ * Parse similarity paths: /similar-to/<path>/threshold-N/<subpath>
71
+ */
72
+ private parseSimilarityPath;
73
+ }
@@ -0,0 +1,285 @@
1
+ /**
2
+ * Semantic Path Parser
3
+ *
4
+ * Parses semantic filesystem paths into structured queries
5
+ * PURE LOGIC - No external dependencies, no async operations
6
+ *
7
+ * Supported path formats:
8
+ * - Traditional: /src/auth.ts
9
+ * - By Concept: /by-concept/authentication/login.ts
10
+ * - By Author: /by-author/alice/file.ts
11
+ * - By Time: /as-of/2024-03-15/file.ts
12
+ * - By Relationship: /related-to/src/auth.ts/depth-2
13
+ * - By Similarity: /similar-to/src/auth.ts/threshold-0.8
14
+ * - By Tag: /by-tag/security/file.ts
15
+ */
16
+ /**
17
+ * Semantic Path Parser
18
+ * Parses various semantic path formats into structured data
19
+ */
20
+ export class SemanticPathParser {
21
+ /**
22
+ * Parse a path into semantic components
23
+ * PURE FUNCTION - no external calls, no async
24
+ */
25
+ parse(path) {
26
+ if (!path || typeof path !== 'string') {
27
+ throw new Error('Path must be a non-empty string');
28
+ }
29
+ // Normalize path
30
+ const normalized = this.normalizePath(path);
31
+ // Try concept dimension
32
+ const conceptMatch = normalized.match(SemanticPathParser.PATTERNS.concept);
33
+ if (conceptMatch) {
34
+ return {
35
+ dimension: 'concept',
36
+ value: conceptMatch[1],
37
+ subpath: conceptMatch[2]
38
+ };
39
+ }
40
+ // Try author dimension
41
+ const authorMatch = normalized.match(SemanticPathParser.PATTERNS.author);
42
+ if (authorMatch) {
43
+ return {
44
+ dimension: 'author',
45
+ value: authorMatch[1],
46
+ subpath: authorMatch[2]
47
+ };
48
+ }
49
+ // Try time dimension
50
+ const timeMatch = normalized.match(SemanticPathParser.PATTERNS.time);
51
+ if (timeMatch) {
52
+ const dateStr = timeMatch[1];
53
+ const date = this.parseDate(dateStr);
54
+ return {
55
+ dimension: 'time',
56
+ value: date,
57
+ subpath: timeMatch[2]
58
+ };
59
+ }
60
+ // Try relationship dimension
61
+ if (normalized.startsWith('/related-to/')) {
62
+ return this.parseRelationshipPath(normalized);
63
+ }
64
+ // Try similarity dimension
65
+ if (normalized.startsWith('/similar-to/')) {
66
+ return this.parseSimilarityPath(normalized);
67
+ }
68
+ // Try tag dimension
69
+ const tagMatch = normalized.match(SemanticPathParser.PATTERNS.tag);
70
+ if (tagMatch) {
71
+ return {
72
+ dimension: 'tag',
73
+ value: tagMatch[1],
74
+ subpath: tagMatch[2]
75
+ };
76
+ }
77
+ // Default to traditional path
78
+ return {
79
+ dimension: 'traditional',
80
+ value: normalized
81
+ };
82
+ }
83
+ /**
84
+ * Check if a path is semantic (non-traditional)
85
+ */
86
+ isSemanticPath(path) {
87
+ if (!path || typeof path !== 'string') {
88
+ return false;
89
+ }
90
+ const normalized = this.normalizePath(path);
91
+ // Check if matches any semantic pattern
92
+ return (normalized.startsWith('/by-concept/') ||
93
+ normalized.startsWith('/by-author/') ||
94
+ normalized.startsWith('/as-of/') ||
95
+ normalized.startsWith('/related-to/') ||
96
+ normalized.startsWith('/similar-to/') ||
97
+ normalized.startsWith('/by-tag/'));
98
+ }
99
+ /**
100
+ * Get the dimension type from a path
101
+ */
102
+ getDimension(path) {
103
+ return this.parse(path).dimension;
104
+ }
105
+ /**
106
+ * Normalize a path - remove trailing slashes, collapse multiple slashes
107
+ * PURE FUNCTION
108
+ */
109
+ normalizePath(path) {
110
+ // Remove trailing slash (except for root)
111
+ let normalized = path.replace(/\/+$/, '');
112
+ // Collapse multiple slashes
113
+ normalized = normalized.replace(/\/+/g, '/');
114
+ // Ensure starts with /
115
+ if (!normalized.startsWith('/')) {
116
+ normalized = '/' + normalized;
117
+ }
118
+ // Special case: empty path becomes /
119
+ if (normalized === '') {
120
+ normalized = '/';
121
+ }
122
+ return normalized;
123
+ }
124
+ /**
125
+ * Parse date string (YYYY-MM-DD) into Date object
126
+ * PURE FUNCTION
127
+ */
128
+ parseDate(dateStr) {
129
+ const parts = dateStr.split('-');
130
+ if (parts.length !== 3) {
131
+ throw new Error(`Invalid date format: ${dateStr}. Expected YYYY-MM-DD`);
132
+ }
133
+ const year = parseInt(parts[0], 10);
134
+ const month = parseInt(parts[1], 10) - 1; // Months are 0-indexed in JS
135
+ const day = parseInt(parts[2], 10);
136
+ if (isNaN(year) || isNaN(month) || isNaN(day)) {
137
+ throw new Error(`Invalid date format: ${dateStr}. Expected YYYY-MM-DD`);
138
+ }
139
+ if (year < 1900 || year > 2100) {
140
+ throw new Error(`Invalid year: ${year}. Expected 1900-2100`);
141
+ }
142
+ if (month < 0 || month > 11) {
143
+ throw new Error(`Invalid month: ${month + 1}. Expected 1-12`);
144
+ }
145
+ if (day < 1 || day > 31) {
146
+ throw new Error(`Invalid day: ${day}. Expected 1-31`);
147
+ }
148
+ return new Date(year, month, day);
149
+ }
150
+ /**
151
+ * Validate parsed path structure
152
+ */
153
+ validate(parsed) {
154
+ if (!parsed || typeof parsed !== 'object') {
155
+ return false;
156
+ }
157
+ if (!parsed.dimension) {
158
+ return false;
159
+ }
160
+ if (parsed.value === undefined || parsed.value === null) {
161
+ return false;
162
+ }
163
+ // Dimension-specific validation
164
+ switch (parsed.dimension) {
165
+ case 'time':
166
+ return parsed.value instanceof Date && !isNaN(parsed.value.getTime());
167
+ case 'relationship':
168
+ const relValue = parsed.value;
169
+ return typeof relValue.targetPath === 'string' && relValue.targetPath.length > 0;
170
+ case 'similar':
171
+ const simValue = parsed.value;
172
+ return typeof simValue.targetPath === 'string' && simValue.targetPath.length > 0;
173
+ default:
174
+ return typeof parsed.value === 'string' && parsed.value.length > 0;
175
+ }
176
+ }
177
+ /**
178
+ * Parse relationship paths: /related-to/<path>/depth-N/types-X,Y/<subpath>
179
+ */
180
+ parseRelationshipPath(path) {
181
+ // Remove /related-to/ prefix
182
+ const withoutPrefix = path.substring('/related-to/'.length);
183
+ // Split into segments
184
+ const segments = withoutPrefix.split('/');
185
+ let targetPath = '';
186
+ let depth;
187
+ let types;
188
+ let subpath;
189
+ let i = 0;
190
+ // Collect path segments until we hit depth-, types-, or end
191
+ while (i < segments.length) {
192
+ const segment = segments[i];
193
+ if (segment.startsWith('depth-')) {
194
+ depth = parseInt(segment.substring('depth-'.length), 10);
195
+ i++;
196
+ continue;
197
+ }
198
+ if (segment.startsWith('types-')) {
199
+ types = segment.substring('types-'.length).split(',');
200
+ i++;
201
+ continue;
202
+ }
203
+ // If we've already collected the target path and found depth/types,
204
+ // rest is subpath
205
+ if (targetPath && (depth !== undefined || types !== undefined)) {
206
+ subpath = segments.slice(i).join('/');
207
+ break;
208
+ }
209
+ // Add to target path
210
+ if (targetPath) {
211
+ targetPath += '/' + segment;
212
+ }
213
+ else {
214
+ targetPath = segment;
215
+ }
216
+ i++;
217
+ }
218
+ const value = {
219
+ targetPath,
220
+ depth,
221
+ relationshipTypes: types
222
+ };
223
+ return {
224
+ dimension: 'relationship',
225
+ value,
226
+ subpath
227
+ };
228
+ }
229
+ /**
230
+ * Parse similarity paths: /similar-to/<path>/threshold-N/<subpath>
231
+ */
232
+ parseSimilarityPath(path) {
233
+ // Remove /similar-to/ prefix
234
+ const withoutPrefix = path.substring('/similar-to/'.length);
235
+ // Split into segments
236
+ const segments = withoutPrefix.split('/');
237
+ let targetPath = '';
238
+ let threshold;
239
+ let subpath;
240
+ let i = 0;
241
+ // Collect path segments until we hit threshold- or end
242
+ while (i < segments.length) {
243
+ const segment = segments[i];
244
+ if (segment.startsWith('threshold-')) {
245
+ threshold = parseFloat(segment.substring('threshold-'.length));
246
+ i++;
247
+ // Rest is subpath
248
+ if (i < segments.length) {
249
+ subpath = segments.slice(i).join('/');
250
+ }
251
+ break;
252
+ }
253
+ // Add to target path
254
+ if (targetPath) {
255
+ targetPath += '/' + segment;
256
+ }
257
+ else {
258
+ targetPath = segment;
259
+ }
260
+ i++;
261
+ }
262
+ const value = {
263
+ targetPath,
264
+ threshold
265
+ };
266
+ return {
267
+ dimension: 'similar',
268
+ value,
269
+ subpath
270
+ };
271
+ }
272
+ }
273
+ // Regex patterns for each dimension
274
+ SemanticPathParser.PATTERNS = {
275
+ concept: /^\/by-concept\/([^\/]+)(?:\/(.+))?$/,
276
+ author: /^\/by-author\/([^\/]+)(?:\/(.+))?$/,
277
+ time: /^\/as-of\/(\d{4}-\d{2}-\d{2})(?:\/(.+))?$/,
278
+ // Relationship: /related-to/<path>/depth-N/types-X,Y/<subpath>
279
+ // Must handle paths with slashes, so capture everything before /depth- or /types-
280
+ relationship: /^\/related-to\/(.+?)(?:\/depth-(\d+)|\/types-([^\/]+)|\/(.+))*$/,
281
+ // Similarity: /similar-to/<path>/threshold-N/<subpath>
282
+ similar: /^\/similar-to\/(.+?)(?:\/threshold-([\d.]+)|\/(.+))*$/,
283
+ tag: /^\/by-tag\/([^\/]+)(?:\/(.+))?$/
284
+ };
285
+ //# sourceMappingURL=SemanticPathParser.js.map
@@ -0,0 +1,99 @@
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 { Brainy } from '../../brainy.js';
14
+ import { VirtualFileSystem } from '../VirtualFileSystem.js';
15
+ import { VFSEntity } from '../types.js';
16
+ import { ProjectionRegistry } from './ProjectionRegistry.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 declare class SemanticPathResolver {
24
+ private brain;
25
+ private vfs;
26
+ private pathResolver;
27
+ private parser;
28
+ private registry;
29
+ private cache;
30
+ constructor(brain: Brainy, vfs: VirtualFileSystem, rootEntityId: string, registry: ProjectionRegistry);
31
+ /**
32
+ * Resolve a path to entity ID(s)
33
+ * Handles BOTH traditional and semantic paths
34
+ *
35
+ * For traditional paths: Returns single entity ID
36
+ * For semantic paths: Returns first matching entity ID
37
+ *
38
+ * Uses UnifiedCache with request coalescing to prevent stampede
39
+ *
40
+ * @param path - Path to resolve (traditional or semantic)
41
+ * @param options - Resolution options
42
+ * @returns Entity ID
43
+ */
44
+ resolve(path: string, options?: {
45
+ followSymlinks?: boolean;
46
+ cache?: boolean;
47
+ }): Promise<string>;
48
+ /**
49
+ * Resolve semantic path to multiple entity IDs
50
+ * This is the polymorphic resolution that returns ALL matches
51
+ *
52
+ * Uses UnifiedCache for performance
53
+ *
54
+ * @param path - Semantic path
55
+ * @param options - Resolution options
56
+ * @returns Array of entity IDs
57
+ */
58
+ resolveAll(path: string, options?: {
59
+ cache?: boolean;
60
+ limit?: number;
61
+ }): Promise<string[]>;
62
+ /**
63
+ * Internal semantic path resolution (called by cache)
64
+ * Estimates cost and size for UnifiedCache optimization
65
+ */
66
+ private resolveSemanticPathInternal;
67
+ /**
68
+ * Filter entity IDs by subpath (filename or partial path)
69
+ */
70
+ private filterBySubpath;
71
+ /**
72
+ * Get children of a directory
73
+ * Delegates to PathResolver for traditional directories
74
+ * For semantic paths, returns entities in that dimension
75
+ */
76
+ getChildren(dirIdOrPath: string): Promise<VFSEntity[]>;
77
+ /**
78
+ * List entities in a semantic dimension
79
+ */
80
+ private listSemanticDimension;
81
+ /**
82
+ * Create a path mapping (cache a path resolution)
83
+ * Only applies to traditional paths
84
+ */
85
+ createPath(path: string, entityId: string): Promise<void>;
86
+ /**
87
+ * Invalidate path cache
88
+ */
89
+ invalidatePath(path: string, recursive?: boolean): void;
90
+ /**
91
+ * Clear all semantic caches
92
+ * Uses UnifiedCache's clear method
93
+ */
94
+ invalidateSemanticCache(): void;
95
+ /**
96
+ * Cleanup resources
97
+ */
98
+ cleanup(): void;
99
+ }