@soulcraft/brainy 3.9.1 → 3.10.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 (43) hide show
  1. package/README.md +64 -6
  2. package/dist/augmentations/KnowledgeAugmentation.d.ts +40 -0
  3. package/dist/augmentations/KnowledgeAugmentation.js +251 -0
  4. package/dist/augmentations/defaultAugmentations.d.ts +1 -0
  5. package/dist/augmentations/defaultAugmentations.js +5 -0
  6. package/dist/brainy.d.ts +11 -0
  7. package/dist/brainy.js +87 -1
  8. package/dist/embeddings/EmbeddingManager.js +14 -2
  9. package/dist/utils/mutex.d.ts +2 -0
  10. package/dist/utils/mutex.js +14 -3
  11. package/dist/vfs/ConceptSystem.d.ts +202 -0
  12. package/dist/vfs/ConceptSystem.js +598 -0
  13. package/dist/vfs/EntityManager.d.ts +75 -0
  14. package/dist/vfs/EntityManager.js +216 -0
  15. package/dist/vfs/EventRecorder.d.ts +83 -0
  16. package/dist/vfs/EventRecorder.js +292 -0
  17. package/dist/vfs/FSCompat.d.ts +85 -0
  18. package/dist/vfs/FSCompat.js +257 -0
  19. package/dist/vfs/GitBridge.d.ts +167 -0
  20. package/dist/vfs/GitBridge.js +537 -0
  21. package/dist/vfs/KnowledgeAugmentation.d.ts +104 -0
  22. package/dist/vfs/KnowledgeAugmentation.js +146 -0
  23. package/dist/vfs/KnowledgeLayer.d.ts +35 -0
  24. package/dist/vfs/KnowledgeLayer.js +443 -0
  25. package/dist/vfs/PathResolver.d.ts +96 -0
  26. package/dist/vfs/PathResolver.js +362 -0
  27. package/dist/vfs/PersistentEntitySystem.d.ts +163 -0
  28. package/dist/vfs/PersistentEntitySystem.js +525 -0
  29. package/dist/vfs/SemanticVersioning.d.ts +105 -0
  30. package/dist/vfs/SemanticVersioning.js +318 -0
  31. package/dist/vfs/VirtualFileSystem.d.ts +246 -0
  32. package/dist/vfs/VirtualFileSystem.js +1927 -0
  33. package/dist/vfs/importers/DirectoryImporter.d.ts +86 -0
  34. package/dist/vfs/importers/DirectoryImporter.js +298 -0
  35. package/dist/vfs/index.d.ts +19 -0
  36. package/dist/vfs/index.js +26 -0
  37. package/dist/vfs/streams/VFSReadStream.d.ts +19 -0
  38. package/dist/vfs/streams/VFSReadStream.js +54 -0
  39. package/dist/vfs/streams/VFSWriteStream.d.ts +21 -0
  40. package/dist/vfs/streams/VFSWriteStream.js +70 -0
  41. package/dist/vfs/types.d.ts +330 -0
  42. package/dist/vfs/types.js +46 -0
  43. package/package.json +1 -1
@@ -0,0 +1,216 @@
1
+ /**
2
+ * EntityManager Base Class
3
+ *
4
+ * Provides standardized entity ID management for all Knowledge Layer components
5
+ * Solves the root cause of ID mismatch issues by establishing clear patterns
6
+ */
7
+ import { v4 as uuidv4 } from '../universal/uuid.js';
8
+ /**
9
+ * EntityManager Base Class
10
+ *
11
+ * All Knowledge Layer components should extend this to get standardized:
12
+ * - Entity storage and retrieval
13
+ * - ID management and mapping
14
+ * - Query patterns
15
+ * - Relationship creation
16
+ */
17
+ export class EntityManager {
18
+ constructor(brain, systemName) {
19
+ this.brain = brain;
20
+ this.systemName = systemName;
21
+ this.idMappings = new Map(); // domainId -> brainyId
22
+ this.brainyToMappings = new Map(); // brainyId -> domainId
23
+ }
24
+ /**
25
+ * Store an entity with proper ID management
26
+ */
27
+ async storeEntity(entity, nounType, embedding, data) {
28
+ // Generate domain ID if not provided
29
+ if (!entity.id) {
30
+ entity.id = uuidv4();
31
+ }
32
+ // Store in Brainy and get the Brainy entity ID
33
+ const brainyId = await this.brain.add({
34
+ type: nounType,
35
+ data: data || Buffer.from(JSON.stringify(entity)),
36
+ metadata: {
37
+ ...entity,
38
+ system: this.systemName,
39
+ domainId: entity.id, // Store the domain ID for reference
40
+ storedAt: Date.now()
41
+ },
42
+ vector: embedding
43
+ });
44
+ // Store ID mapping
45
+ this.idMappings.set(entity.id, brainyId);
46
+ this.brainyToMappings.set(brainyId, entity.id);
47
+ // Update entity with Brainy ID
48
+ entity.brainyId = brainyId;
49
+ return entity.id; // Return domain ID for external use
50
+ }
51
+ /**
52
+ * Update an existing entity
53
+ */
54
+ async updateEntity(entity, embedding) {
55
+ const brainyId = this.idMappings.get(entity.id);
56
+ if (!brainyId) {
57
+ throw new Error(`Entity ${entity.id} not found in mappings`);
58
+ }
59
+ await this.brain.update({
60
+ id: brainyId,
61
+ data: Buffer.from(JSON.stringify(entity)),
62
+ metadata: {
63
+ ...entity,
64
+ system: this.systemName,
65
+ domainId: entity.id,
66
+ updatedAt: Date.now()
67
+ },
68
+ vector: embedding
69
+ });
70
+ }
71
+ /**
72
+ * Retrieve entity by domain ID
73
+ */
74
+ async getEntity(domainId) {
75
+ // First try from cache
76
+ let brainyId = this.idMappings.get(domainId);
77
+ // If not in cache, search by domain ID in metadata
78
+ if (!brainyId) {
79
+ const results = await this.brain.find({
80
+ where: {
81
+ domainId,
82
+ system: this.systemName
83
+ },
84
+ limit: 1
85
+ });
86
+ if (results.length === 0) {
87
+ return null;
88
+ }
89
+ brainyId = results[0].entity.id;
90
+ // Cache the mapping
91
+ this.idMappings.set(domainId, brainyId);
92
+ this.brainyToMappings.set(brainyId, domainId);
93
+ }
94
+ // Get entity using Brainy ID
95
+ const brainyEntity = await this.brain.get(brainyId);
96
+ if (!brainyEntity) {
97
+ return null;
98
+ }
99
+ // Parse entity from metadata
100
+ const entity = brainyEntity.metadata;
101
+ entity.brainyId = brainyId;
102
+ return entity;
103
+ }
104
+ /**
105
+ * Find entities by metadata criteria
106
+ */
107
+ async findEntities(criteria, nounType, limit = 100) {
108
+ const query = {
109
+ ...criteria,
110
+ system: this.systemName
111
+ };
112
+ const results = await this.brain.find({
113
+ where: query,
114
+ type: nounType,
115
+ limit
116
+ });
117
+ const entities = [];
118
+ for (const result of results) {
119
+ const entity = result.entity.metadata;
120
+ entity.brainyId = result.entity.id;
121
+ // Update mappings cache
122
+ this.idMappings.set(entity.id, result.entity.id);
123
+ this.brainyToMappings.set(result.entity.id, entity.id);
124
+ entities.push(entity);
125
+ }
126
+ return entities;
127
+ }
128
+ /**
129
+ * Create relationship between entities using proper Brainy IDs
130
+ */
131
+ async createRelationship(fromDomainId, toDomainId, relationshipType, metadata) {
132
+ // Get Brainy IDs for both entities
133
+ const fromBrainyId = await this.getBrainyId(fromDomainId);
134
+ const toBrainyId = await this.getBrainyId(toDomainId);
135
+ if (!fromBrainyId || !toBrainyId) {
136
+ throw new Error(`Cannot find Brainy IDs for relationship: ${fromDomainId} -> ${toDomainId}`);
137
+ }
138
+ // Create relationship using Brainy IDs
139
+ await this.brain.relate({
140
+ from: fromBrainyId,
141
+ to: toBrainyId,
142
+ type: relationshipType,
143
+ metadata
144
+ });
145
+ }
146
+ /**
147
+ * Get Brainy ID for a domain ID
148
+ */
149
+ async getBrainyId(domainId) {
150
+ // Check cache first
151
+ let brainyId = this.idMappings.get(domainId);
152
+ if (!brainyId) {
153
+ // Search in Brainy
154
+ const results = await this.brain.find({
155
+ where: {
156
+ domainId,
157
+ system: this.systemName
158
+ },
159
+ limit: 1
160
+ });
161
+ if (results.length > 0) {
162
+ brainyId = results[0].entity.id;
163
+ // Cache the mapping
164
+ this.idMappings.set(domainId, brainyId);
165
+ this.brainyToMappings.set(brainyId, domainId);
166
+ }
167
+ }
168
+ return brainyId || null;
169
+ }
170
+ /**
171
+ * Get domain ID for a Brainy ID
172
+ */
173
+ getDomainId(brainyId) {
174
+ return this.brainyToMappings.get(brainyId) || null;
175
+ }
176
+ /**
177
+ * Delete entity by domain ID
178
+ */
179
+ async deleteEntity(domainId) {
180
+ const brainyId = await this.getBrainyId(domainId);
181
+ if (brainyId) {
182
+ await this.brain.delete(brainyId);
183
+ // Clean up mappings
184
+ this.idMappings.delete(domainId);
185
+ this.brainyToMappings.delete(brainyId);
186
+ }
187
+ }
188
+ /**
189
+ * Clear ID mapping cache (useful for tests)
190
+ */
191
+ clearMappingCache() {
192
+ this.idMappings.clear();
193
+ this.brainyToMappings.clear();
194
+ }
195
+ /**
196
+ * Batch load mappings for performance
197
+ */
198
+ async loadMappings(domainIds) {
199
+ const unknownIds = domainIds.filter(id => !this.idMappings.has(id));
200
+ if (unknownIds.length === 0)
201
+ return;
202
+ const results = await this.brain.find({
203
+ where: {
204
+ domainId: { $in: unknownIds },
205
+ system: this.systemName
206
+ },
207
+ limit: unknownIds.length
208
+ });
209
+ for (const result of results) {
210
+ const domainId = result.entity.metadata.domainId;
211
+ this.idMappings.set(domainId, result.entity.id);
212
+ this.brainyToMappings.set(result.entity.id, domainId);
213
+ }
214
+ }
215
+ }
216
+ //# sourceMappingURL=EntityManager.js.map
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Event Recording System for VFS
3
+ *
4
+ * Records every file operation as an event for complete history tracking
5
+ * PRODUCTION-READY: No mocks, real implementation
6
+ */
7
+ import { Brainy } from '../brainy.js';
8
+ /**
9
+ * File operation event
10
+ */
11
+ export interface FileEvent {
12
+ id: string;
13
+ type: 'create' | 'write' | 'append' | 'delete' | 'move' | 'rename' | 'mkdir' | 'rmdir';
14
+ path: string;
15
+ timestamp: number;
16
+ content?: Buffer;
17
+ size?: number;
18
+ hash?: string;
19
+ author?: string;
20
+ metadata?: Record<string, any>;
21
+ previousHash?: string;
22
+ oldPath?: string;
23
+ }
24
+ /**
25
+ * Event Recorder - Stores all file operations as searchable events
26
+ */
27
+ export declare class EventRecorder {
28
+ private brain;
29
+ constructor(brain: Brainy);
30
+ /**
31
+ * Record a file operation event
32
+ */
33
+ recordEvent(event: Omit<FileEvent, 'id' | 'timestamp'>): Promise<string>;
34
+ /**
35
+ * Get all events matching criteria
36
+ */
37
+ getEvents(options?: {
38
+ since?: number;
39
+ until?: number;
40
+ types?: string[];
41
+ limit?: number;
42
+ }): Promise<FileEvent[]>;
43
+ /**
44
+ * Get complete history for a file
45
+ */
46
+ getHistory(path: string, options?: {
47
+ limit?: number;
48
+ since?: number;
49
+ until?: number;
50
+ types?: FileEvent['type'][];
51
+ }): Promise<FileEvent[]>;
52
+ /**
53
+ * Replay events to reconstruct file state at a specific time
54
+ */
55
+ reconstructFileAtTime(path: string, timestamp: number): Promise<Buffer | null>;
56
+ /**
57
+ * Get file changes between two timestamps
58
+ */
59
+ getChanges(since: number, until?: number): Promise<FileEvent[]>;
60
+ /**
61
+ * Calculate statistics for a file or directory
62
+ */
63
+ getStatistics(path: string): Promise<{
64
+ totalEvents: number;
65
+ firstEvent: number | null;
66
+ lastEvent: number | null;
67
+ totalWrites: number;
68
+ totalBytes: number;
69
+ authors: string[];
70
+ }>;
71
+ /**
72
+ * Find files that changed together (temporal coupling)
73
+ */
74
+ findTemporalCoupling(path: string, windowMs?: number): Promise<Map<string, number>>;
75
+ /**
76
+ * Generate embedding for an event (for semantic search)
77
+ */
78
+ private generateEventEmbedding;
79
+ /**
80
+ * Prune old events (for storage management)
81
+ */
82
+ pruneEvents(olderThan: number, keepEvery?: number): Promise<number>;
83
+ }
@@ -0,0 +1,292 @@
1
+ /**
2
+ * Event Recording System for VFS
3
+ *
4
+ * Records every file operation as an event for complete history tracking
5
+ * PRODUCTION-READY: No mocks, real implementation
6
+ */
7
+ import { NounType } from '../types/graphTypes.js';
8
+ import { v4 as uuidv4 } from '../universal/uuid.js';
9
+ import { createHash } from 'crypto';
10
+ /**
11
+ * Event Recorder - Stores all file operations as searchable events
12
+ */
13
+ export class EventRecorder {
14
+ constructor(brain) {
15
+ this.brain = brain;
16
+ }
17
+ /**
18
+ * Record a file operation event
19
+ */
20
+ async recordEvent(event) {
21
+ const eventId = uuidv4();
22
+ const timestamp = Date.now();
23
+ // Calculate content hash if content provided
24
+ const hash = event.content
25
+ ? createHash('sha256').update(event.content).digest('hex')
26
+ : undefined;
27
+ // Store event as Brainy entity
28
+ const entity = await this.brain.add({
29
+ type: NounType.Event,
30
+ data: event.content || Buffer.from(JSON.stringify(event)),
31
+ metadata: {
32
+ ...event,
33
+ id: eventId,
34
+ timestamp,
35
+ hash,
36
+ eventType: 'file-operation',
37
+ system: 'vfs'
38
+ },
39
+ // Generate embedding for content-based events
40
+ vector: event.content && event.content.length < 100000
41
+ ? await this.generateEventEmbedding(event)
42
+ : undefined
43
+ });
44
+ return entity;
45
+ }
46
+ /**
47
+ * Get all events matching criteria
48
+ */
49
+ async getEvents(options) {
50
+ const limit = options?.limit || 100;
51
+ const since = options?.since || 0;
52
+ const until = options?.until || Date.now();
53
+ const query = {
54
+ eventType: 'file-operation'
55
+ };
56
+ // Add time filters
57
+ if (since || until) {
58
+ query.timestamp = {};
59
+ if (since)
60
+ query.timestamp.$gte = since;
61
+ if (until)
62
+ query.timestamp.$lte = until;
63
+ }
64
+ // Add type filter
65
+ if (options?.types && options.types.length > 0) {
66
+ query.type = { $in: options.types };
67
+ }
68
+ // Query events from Brainy
69
+ const results = await this.brain.find({
70
+ where: query,
71
+ type: NounType.Event,
72
+ limit
73
+ });
74
+ const events = [];
75
+ for (const result of results) {
76
+ if (result.entity?.metadata) {
77
+ events.push(result.entity.metadata);
78
+ }
79
+ }
80
+ return events.sort((a, b) => b.timestamp - a.timestamp);
81
+ }
82
+ /**
83
+ * Get complete history for a file
84
+ */
85
+ async getHistory(path, options) {
86
+ const query = {
87
+ path,
88
+ eventType: 'file-operation'
89
+ };
90
+ // Add time filters
91
+ if (options?.since || options?.until) {
92
+ query.timestamp = {};
93
+ if (options.since)
94
+ query.timestamp.$gte = options.since;
95
+ if (options.until)
96
+ query.timestamp.$lte = options.until;
97
+ }
98
+ // Add type filter
99
+ if (options?.types && options.types.length > 0) {
100
+ query.type = { $in: options.types };
101
+ }
102
+ // Query events from Brainy
103
+ const results = await this.brain.find({
104
+ where: query,
105
+ type: NounType.Event,
106
+ limit: options?.limit || 100,
107
+ // Sort by timestamp descending (newest first)
108
+ // Note: Sorting would need to be implemented in Brainy
109
+ });
110
+ // Convert results to FileEvent format
111
+ const events = results.map(r => ({
112
+ id: r.entity.metadata.id,
113
+ type: r.entity.metadata.type,
114
+ path: r.entity.metadata.path,
115
+ timestamp: r.entity.metadata.timestamp,
116
+ content: r.entity.metadata.content,
117
+ size: r.entity.metadata.size,
118
+ hash: r.entity.metadata.hash,
119
+ author: r.entity.metadata.author,
120
+ metadata: r.entity.metadata.metadata,
121
+ previousHash: r.entity.metadata.previousHash
122
+ }));
123
+ // Sort by timestamp (newest first)
124
+ return events.sort((a, b) => b.timestamp - a.timestamp);
125
+ }
126
+ /**
127
+ * Replay events to reconstruct file state at a specific time
128
+ */
129
+ async reconstructFileAtTime(path, timestamp) {
130
+ // Get all events up to the specified time
131
+ const events = await this.getHistory(path, {
132
+ until: timestamp,
133
+ types: ['create', 'write', 'append', 'delete']
134
+ });
135
+ // Sort chronologically for replay
136
+ const chronological = events.reverse();
137
+ // Find last write or create event
138
+ let lastContent = null;
139
+ let deleted = false;
140
+ for (const event of chronological) {
141
+ switch (event.type) {
142
+ case 'create':
143
+ case 'write':
144
+ lastContent = event.content || null;
145
+ deleted = false;
146
+ break;
147
+ case 'append':
148
+ if (lastContent && event.content) {
149
+ lastContent = Buffer.concat([lastContent, event.content]);
150
+ }
151
+ break;
152
+ case 'delete':
153
+ deleted = true;
154
+ lastContent = null;
155
+ break;
156
+ }
157
+ }
158
+ return deleted ? null : lastContent;
159
+ }
160
+ /**
161
+ * Get file changes between two timestamps
162
+ */
163
+ async getChanges(since, until) {
164
+ const query = {
165
+ eventType: 'file-operation',
166
+ timestamp: { $gte: since }
167
+ };
168
+ if (until) {
169
+ query.timestamp.$lte = until;
170
+ }
171
+ const results = await this.brain.find({
172
+ where: query,
173
+ type: NounType.Event,
174
+ limit: 1000
175
+ });
176
+ return results.map(r => ({
177
+ id: r.entity.metadata.id,
178
+ type: r.entity.metadata.type,
179
+ path: r.entity.metadata.path,
180
+ timestamp: r.entity.metadata.timestamp,
181
+ size: r.entity.metadata.size,
182
+ hash: r.entity.metadata.hash,
183
+ author: r.entity.metadata.author
184
+ }));
185
+ }
186
+ /**
187
+ * Calculate statistics for a file or directory
188
+ */
189
+ async getStatistics(path) {
190
+ const events = await this.getHistory(path, { limit: 10000 });
191
+ if (events.length === 0) {
192
+ return {
193
+ totalEvents: 0,
194
+ firstEvent: null,
195
+ lastEvent: null,
196
+ totalWrites: 0,
197
+ totalBytes: 0,
198
+ authors: []
199
+ };
200
+ }
201
+ const stats = {
202
+ totalEvents: events.length,
203
+ firstEvent: events[events.length - 1].timestamp, // Oldest
204
+ lastEvent: events[0].timestamp, // Newest
205
+ totalWrites: 0,
206
+ totalBytes: 0,
207
+ authors: new Set()
208
+ };
209
+ for (const event of events) {
210
+ if (event.type === 'write' || event.type === 'append') {
211
+ stats.totalWrites++;
212
+ stats.totalBytes += event.size || 0;
213
+ }
214
+ if (event.author) {
215
+ stats.authors.add(event.author);
216
+ }
217
+ }
218
+ return {
219
+ ...stats,
220
+ authors: Array.from(stats.authors)
221
+ };
222
+ }
223
+ /**
224
+ * Find files that changed together (temporal coupling)
225
+ */
226
+ async findTemporalCoupling(path, windowMs = 60000) {
227
+ const events = await this.getHistory(path);
228
+ const coupling = new Map();
229
+ for (const event of events) {
230
+ // Find other files changed within the time window
231
+ const related = await this.getChanges(event.timestamp - windowMs, event.timestamp + windowMs);
232
+ for (const relatedEvent of related) {
233
+ if (relatedEvent.path !== path) {
234
+ const count = coupling.get(relatedEvent.path) || 0;
235
+ coupling.set(relatedEvent.path, count + 1);
236
+ }
237
+ }
238
+ }
239
+ // Sort by coupling strength
240
+ return new Map(Array.from(coupling.entries())
241
+ .sort((a, b) => b[1] - a[1]));
242
+ }
243
+ /**
244
+ * Generate embedding for an event (for semantic search)
245
+ */
246
+ async generateEventEmbedding(event) {
247
+ try {
248
+ // Generate embedding based on event type and content
249
+ let textToEmbed;
250
+ if (event.type === 'write' || event.type === 'create') {
251
+ // For write/create events with content, embed the content
252
+ if (event.content && event.content.length < 100000) {
253
+ // Convert Buffer to string for text files
254
+ textToEmbed = Buffer.isBuffer(event.content)
255
+ ? event.content.toString('utf8', 0, Math.min(10240, event.content.length))
256
+ : String(event.content).slice(0, 10240);
257
+ }
258
+ else {
259
+ // For large files or no content, create descriptive text
260
+ textToEmbed = `File ${event.type} event at ${event.path}, size: ${event.size || 0} bytes`;
261
+ }
262
+ }
263
+ else {
264
+ // For other events (read, delete, rename, etc), create descriptive text
265
+ textToEmbed = `File ${event.type} event at ${event.path}${event.oldPath ? ` from ${event.oldPath}` : ''}`;
266
+ }
267
+ // Use Brainy's embed function
268
+ const vector = await this.brain.embed(textToEmbed);
269
+ return vector;
270
+ }
271
+ catch (error) {
272
+ console.error('Failed to generate event embedding:', error);
273
+ return undefined;
274
+ }
275
+ }
276
+ /**
277
+ * Prune old events (for storage management)
278
+ */
279
+ async pruneEvents(olderThan, keepEvery = 10) {
280
+ const events = await this.getChanges(0, Date.now() - olderThan);
281
+ let pruned = 0;
282
+ for (let i = 0; i < events.length; i++) {
283
+ // Keep every Nth event for history sampling
284
+ if (i % keepEvery !== 0) {
285
+ await this.brain.delete(events[i].id);
286
+ pruned++;
287
+ }
288
+ }
289
+ return pruned;
290
+ }
291
+ }
292
+ //# sourceMappingURL=EventRecorder.js.map
@@ -0,0 +1,85 @@
1
+ /**
2
+ * fs-Compatible Interface for VFS
3
+ *
4
+ * Provides a drop-in replacement for Node's fs module
5
+ * that uses VFS for storage instead of the real filesystem.
6
+ *
7
+ * Usage:
8
+ * import { FSCompat } from '@soulcraft/brainy/vfs'
9
+ * const fs = new FSCompat(brain.vfs())
10
+ *
11
+ * // Now use like Node's fs
12
+ * await fs.promises.readFile('/path')
13
+ * fs.createReadStream('/path').pipe(output)
14
+ */
15
+ import { VirtualFileSystem } from './VirtualFileSystem.js';
16
+ import type { VFSStats, VFSDirent } from './types.js';
17
+ export declare class FSCompat {
18
+ private vfs;
19
+ /**
20
+ * Promise-based API (like fs.promises)
21
+ */
22
+ readonly promises: FSPromises;
23
+ constructor(vfs: VirtualFileSystem);
24
+ readFile(path: string, callback: (err: Error | null, data?: Buffer) => void): void;
25
+ readFile(path: string, encoding: BufferEncoding, callback: (err: Error | null, data?: string) => void): void;
26
+ writeFile(path: string, data: Buffer | string, callback: (err: Error | null) => void): void;
27
+ mkdir(path: string, callback: (err: Error | null) => void): void;
28
+ rmdir(path: string, callback: (err: Error | null) => void): void;
29
+ readdir(path: string, callback: (err: Error | null, files?: string[]) => void): void;
30
+ stat(path: string, callback: (err: Error | null, stats?: VFSStats) => void): void;
31
+ lstat(path: string, callback: (err: Error | null, stats?: VFSStats) => void): void;
32
+ unlink(path: string, callback: (err: Error | null) => void): void;
33
+ rename(oldPath: string, newPath: string, callback: (err: Error | null) => void): void;
34
+ copyFile(src: string, dest: string, callback: (err: Error | null) => void): void;
35
+ copyFile(src: string, dest: string, flags: number, callback: (err: Error | null) => void): void;
36
+ exists(path: string, callback: (exists: boolean) => void): void;
37
+ access(path: string, callback: (err: Error | null) => void): void;
38
+ access(path: string, mode: number, callback: (err: Error | null) => void): void;
39
+ appendFile(path: string, data: Buffer | string, callback: (err: Error | null) => void): void;
40
+ createReadStream(path: string, options?: any): NodeJS.ReadableStream;
41
+ createWriteStream(path: string, options?: any): NodeJS.WritableStream;
42
+ watch(path: string, listener?: any): {
43
+ close(): void;
44
+ };
45
+ watchFile(path: string, listener: any): void;
46
+ unwatchFile(path: string): void;
47
+ /**
48
+ * Import a directory from real filesystem (VFS extension)
49
+ */
50
+ importDirectory(sourcePath: string, options?: any): Promise<any>;
51
+ /**
52
+ * Search files semantically (VFS extension)
53
+ */
54
+ search(query: string, options?: any): Promise<import("./types.js").SearchResult[]>;
55
+ }
56
+ /**
57
+ * Promise-based fs API (like fs.promises)
58
+ */
59
+ declare class FSPromises {
60
+ private vfs;
61
+ constructor(vfs: VirtualFileSystem);
62
+ readFile(path: string, options?: any): Promise<Buffer | string>;
63
+ writeFile(path: string, data: Buffer | string, options?: any): Promise<void>;
64
+ mkdir(path: string, options?: any): Promise<void>;
65
+ rmdir(path: string, options?: any): Promise<void>;
66
+ readdir(path: string, options?: any): Promise<string[] | VFSDirent[]>;
67
+ stat(path: string): Promise<VFSStats>;
68
+ lstat(path: string): Promise<VFSStats>;
69
+ unlink(path: string): Promise<void>;
70
+ rename(oldPath: string, newPath: string): Promise<void>;
71
+ copyFile(src: string, dest: string, flags?: number): Promise<void>;
72
+ access(path: string, mode?: number): Promise<void>;
73
+ appendFile(path: string, data: Buffer | string, options?: any): Promise<void>;
74
+ realpath(path: string): Promise<string>;
75
+ chmod(path: string, mode: number): Promise<void>;
76
+ chown(path: string, uid: number, gid: number): Promise<void>;
77
+ utimes(path: string, atime: Date, mtime: Date): Promise<void>;
78
+ symlink(target: string, path: string): Promise<void>;
79
+ readlink(path: string): Promise<string>;
80
+ search(query: string, options?: any): Promise<import("./types.js").SearchResult[]>;
81
+ findSimilar(path: string, options?: any): Promise<import("./types.js").SearchResult[]>;
82
+ importDirectory(sourcePath: string, options?: any): Promise<any>;
83
+ }
84
+ export declare function createFS(vfs: VirtualFileSystem): FSCompat;
85
+ export {};