feat: implement complete VFS with Knowledge Layer integration

Add production-ready Virtual File System with intelligent Knowledge Layer:

Core VFS Features:
- Complete file system operations (read, write, mkdir, etc.)
- Intelligent PathResolver with 4-layer caching system
- Chunked storage for large files with real compression
- Embedding generation for semantic operations
- File relationships and metadata tracking
- Import functionality from local filesystem

Knowledge Layer Integration:
- EventRecorder for complete file history and temporal coupling
- SemanticVersioning with content-based change detection
- PersistentEntitySystem for character/entity tracking across files
- ConceptSystem for universal concept mapping and graphs
- GitBridge for import/export between VFS and Git repositories

Architecture:
- KnowledgeAugmentation properly integrated into Brainy augmentation system
- KnowledgeLayer wrapper provides real-time VFS operation interception
- Background processing ensures VFS operations remain fast
- All components use real Brainy embed() method for embeddings
- Support for creative writing, coding projects, and project management

Technical Implementation:
- Fixed all stub/mock implementations with real working code
- TypeScript compilation passes without errors
- Comprehensive test suite demonstrating all features
- Documentation covering architecture and usage patterns
- Backwards compatible with existing Brainy functionality

This enables scenarios like writing books with persistent characters,
managing coding projects with concept tracking, and complete project
coordination with intelligent file relationships.
This commit is contained in:
David Snelling 2025-09-24 17:31:48 -07:00
parent afd1d71d47
commit b3c4f348ab
27 changed files with 12679 additions and 0 deletions

333
src/vfs/FSCompat.ts Normal file
View file

@ -0,0 +1,333 @@
/**
* fs-Compatible Interface for VFS
*
* Provides a drop-in replacement for Node's fs module
* that uses VFS for storage instead of the real filesystem.
*
* Usage:
* import { FSCompat } from '@soulcraft/brainy/vfs'
* const fs = new FSCompat(brain.vfs())
*
* // Now use like Node's fs
* await fs.promises.readFile('/path')
* fs.createReadStream('/path').pipe(output)
*/
import { VirtualFileSystem } from './VirtualFileSystem.js'
import type {
ReadOptions,
WriteOptions,
MkdirOptions,
VFSStats,
VFSDirent
} from './types.js'
export class FSCompat {
/**
* Promise-based API (like fs.promises)
*/
public readonly promises: FSPromises
constructor(private vfs: VirtualFileSystem) {
this.promises = new FSPromises(vfs)
}
// ============= Callback-style methods (for compatibility) =============
readFile(path: string, callback: (err: Error | null, data?: Buffer) => void): void
readFile(path: string, encoding: BufferEncoding, callback: (err: Error | null, data?: string) => void): void
readFile(path: string, options: any, callback?: any): void {
if (typeof options === 'function') {
callback = options
options = {}
}
this.vfs.readFile(path, options)
.then(data => {
if (options?.encoding) {
callback(null, data.toString(options.encoding))
} else {
callback(null, data)
}
})
.catch(err => callback(err))
}
writeFile(path: string, data: Buffer | string, callback: (err: Error | null) => void): void
writeFile(path: string, data: Buffer | string, options: any, callback?: any): void {
if (typeof options === 'function') {
callback = options
options = {}
}
const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data, options?.encoding || 'utf8')
this.vfs.writeFile(path, buffer, options)
.then(() => callback(null))
.catch(err => callback(err))
}
mkdir(path: string, callback: (err: Error | null) => void): void
mkdir(path: string, options: any, callback?: any): void {
if (typeof options === 'function') {
callback = options
options = {}
}
this.vfs.mkdir(path, options)
.then(() => callback(null))
.catch(err => callback(err))
}
rmdir(path: string, callback: (err: Error | null) => void): void
rmdir(path: string, options: any, callback?: any): void {
if (typeof options === 'function') {
callback = options
options = {}
}
this.vfs.rmdir(path, options)
.then(() => callback(null))
.catch(err => callback(err))
}
readdir(path: string, callback: (err: Error | null, files?: string[]) => void): void
readdir(path: string, options: any, callback?: any): void {
if (typeof options === 'function') {
callback = options
options = {}
}
this.vfs.readdir(path, options)
.then(files => callback(null, files))
.catch(err => callback(err))
}
stat(path: string, callback: (err: Error | null, stats?: VFSStats) => void): void {
this.vfs.stat(path)
.then(stats => callback(null, stats))
.catch(err => callback(err))
}
lstat(path: string, callback: (err: Error | null, stats?: VFSStats) => void): void {
this.vfs.lstat(path)
.then(stats => callback(null, stats))
.catch(err => callback(err))
}
unlink(path: string, callback: (err: Error | null) => void): void {
this.vfs.unlink(path)
.then(() => callback(null))
.catch(err => callback(err))
}
rename(oldPath: string, newPath: string, callback: (err: Error | null) => void): void {
this.vfs.rename(oldPath, newPath)
.then(() => callback(null))
.catch(err => callback(err))
}
copyFile(src: string, dest: string, callback: (err: Error | null) => void): void
copyFile(src: string, dest: string, flags: number, callback: (err: Error | null) => void): void
copyFile(src: string, dest: string, flagsOrCallback: any, callback?: any): void {
if (typeof flagsOrCallback === 'function') {
callback = flagsOrCallback
} else {
// flags provided but not used
}
this.vfs.copy(src, dest)
.then(() => callback(null))
.catch(err => callback(err))
}
exists(path: string, callback: (exists: boolean) => void): void {
this.vfs.exists(path)
.then(exists => callback(exists))
.catch(() => callback(false))
}
access(path: string, callback: (err: Error | null) => void): void
access(path: string, mode: number, callback: (err: Error | null) => void): void
access(path: string, modeOrCallback: any, callback?: any): void {
if (typeof modeOrCallback === 'function') {
callback = modeOrCallback
} else {
// mode provided but not used
}
this.vfs.exists(path)
.then(exists => {
if (exists) {
callback(null)
} else {
const err: any = new Error('ENOENT: no such file or directory')
err.code = 'ENOENT'
callback(err)
}
})
.catch(err => callback(err))
}
appendFile(path: string, data: Buffer | string, callback: (err: Error | null) => void): void
appendFile(path: string, data: Buffer | string, options: any, callback?: any): void {
if (typeof options === 'function') {
callback = options
options = {}
}
const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data, options?.encoding || 'utf8')
this.vfs.appendFile(path, buffer, options)
.then(() => callback(null))
.catch(err => callback(err))
}
// ============= Stream methods =============
createReadStream(path: string, options?: any) {
return this.vfs.createReadStream(path, options)
}
createWriteStream(path: string, options?: any) {
return this.vfs.createWriteStream(path, options)
}
// ============= Watch methods =============
watch(path: string, listener?: any) {
return this.vfs.watch(path, listener)
}
watchFile(path: string, listener: any) {
return this.vfs.watchFile(path, listener)
}
unwatchFile(path: string) {
return this.vfs.unwatchFile(path)
}
// ============= Additional methods =============
/**
* Import a directory from real filesystem (VFS extension)
*/
async importDirectory(sourcePath: string, options?: any) {
return this.vfs.importDirectory(sourcePath, options)
}
/**
* Search files semantically (VFS extension)
*/
async search(query: string, options?: any) {
return this.vfs.search(query, options)
}
}
/**
* Promise-based fs API (like fs.promises)
*/
class FSPromises {
constructor(private vfs: VirtualFileSystem) {}
async readFile(path: string, options?: any): Promise<Buffer | string> {
const buffer = await this.vfs.readFile(path, options)
if (options?.encoding) {
return buffer.toString(options.encoding)
}
return buffer
}
async writeFile(path: string, data: Buffer | string, options?: any): Promise<void> {
const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data, options?.encoding || 'utf8')
return this.vfs.writeFile(path, buffer, options)
}
async mkdir(path: string, options?: any): Promise<void> {
return this.vfs.mkdir(path, options)
}
async rmdir(path: string, options?: any): Promise<void> {
return this.vfs.rmdir(path, options)
}
async readdir(path: string, options?: any): Promise<string[] | VFSDirent[]> {
return this.vfs.readdir(path, options)
}
async stat(path: string): Promise<VFSStats> {
return this.vfs.stat(path)
}
async lstat(path: string): Promise<VFSStats> {
return this.vfs.lstat(path)
}
async unlink(path: string): Promise<void> {
return this.vfs.unlink(path)
}
async rename(oldPath: string, newPath: string): Promise<void> {
return this.vfs.rename(oldPath, newPath)
}
async copyFile(src: string, dest: string, flags?: number): Promise<void> {
return this.vfs.copy(src, dest)
}
async access(path: string, mode?: number): Promise<void> {
const exists = await this.vfs.exists(path)
if (!exists) {
const err: any = new Error('ENOENT: no such file or directory')
err.code = 'ENOENT'
throw err
}
}
async appendFile(path: string, data: Buffer | string, options?: any): Promise<void> {
const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data, options?.encoding || 'utf8')
return this.vfs.appendFile(path, buffer, options)
}
async realpath(path: string): Promise<string> {
return this.vfs.realpath(path)
}
async chmod(path: string, mode: number): Promise<void> {
return this.vfs.chmod(path, mode)
}
async chown(path: string, uid: number, gid: number): Promise<void> {
return this.vfs.chown(path, uid, gid)
}
async utimes(path: string, atime: Date, mtime: Date): Promise<void> {
return this.vfs.utimes(path, atime, mtime)
}
async symlink(target: string, path: string): Promise<void> {
return this.vfs.symlink(target, path)
}
async readlink(path: string): Promise<string> {
return this.vfs.readlink(path)
}
// VFS Extensions
async search(query: string, options?: any) {
return this.vfs.search(query, options)
}
async findSimilar(path: string, options?: any) {
return this.vfs.findSimilar(path, options)
}
async importDirectory(sourcePath: string, options?: any) {
return this.vfs.importDirectory(sourcePath, options)
}
}
// Export a convenience function to create fs replacement
export function createFS(vfs: VirtualFileSystem): FSCompat {
return new FSCompat(vfs)
}