fix: add includeVFS parameter to getRelations() - VFS now visible

CRITICAL BUG FIX - VFS Files Were Completely Invisible

Workshop Team Issue:
- Import created 569 VFS files
- vfs.readdir('/') returned 0 items
- VFS was 100% unusable

Root Cause:
v4.4.0 added includeVFS to brain.find() but FORGOT brain.getRelations().
PathResolver.getChildren() calls getRelations() to find VFS relationships,
but those were being excluded by default - making ALL VFS files invisible!

Fix:
1. Add includeVFS parameter to GetRelationsParams interface
2. Wire includeVFS filtering in brain.getRelations()
   - Excludes VFS relationships by default (metadata.isVFS != true)
   - Include them when includeVFS: true
3. Update VFS to mark all relationships with metadata: { isVFS: true }
   - 7 relate() calls updated in VirtualFileSystem.ts
4. Update PathResolver to use includeVFS: true
   - resolveChild() line 200
   - getChildren() line 229

Impact:
- VFS is now fully functional again
- Consistent with v4.4.0 architecture (VFS separate from knowledge graph)
- All APIs now have includeVFS where needed

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
David Snelling 2025-10-24 15:59:41 -07:00
parent 2b38f8caba
commit ae6fbd8c4c
4 changed files with 45 additions and 9 deletions

View file

@ -1016,6 +1016,14 @@ export class Brainy<T = any> implements BrainyInterface<T> {
filter.service = params.service
}
// v4.5.1: Exclude VFS relationships by default (same pattern as brain.find())
// VFS relationships have metadata.isVFS = true
// Only include VFS relationships if explicitly requested
if (params.includeVFS !== true) {
filter.metadata = filter.metadata || {}
filter.metadata.isVFS = { notEquals: true }
}
// Fetch from storage with pagination at storage layer (efficient!)
const result = await this.storage.getVerbs({
pagination: {

View file

@ -324,6 +324,17 @@ export interface GetRelationsParams {
* Only return relationships belonging to this service.
*/
service?: string
/**
* Include VFS relationships (v4.5.1)
*
* By default, getRelations() excludes VFS relationships (since v4.4.0).
* Set this to true when you need to traverse VFS structure.
*
* @default false
* @since v4.5.1
*/
includeVFS?: boolean
}
// ============= Batch Operations =============

View file

@ -199,7 +199,8 @@ export class PathResolver {
// Get all relationships where parentId contains other entities
const relations = await this.brain.getRelations({
from: parentId,
type: VerbType.Contains
type: VerbType.Contains,
includeVFS: true // v4.5.1: Required to see VFS relationships
})
// Find the child with matching name
@ -227,7 +228,8 @@ export class PathResolver {
// Production-ready: Use graph relationships (VFS creates these in mkdir/writeFile)
const relations = await this.brain.getRelations({
from: dirId,
type: VerbType.Contains
type: VerbType.Contains,
includeVFS: true // v4.5.1: Required to see VFS relationships
})
const validChildren: VFSEntity[] = []

View file

@ -422,7 +422,8 @@ export class VirtualFileSystem implements IVirtualFileSystem {
await this.brain.relate({
from: parentId,
to: existingId,
type: VerbType.Contains
type: VerbType.Contains,
metadata: { isVFS: true } // v4.5.1: Mark as VFS relationship
})
}
} else {
@ -440,7 +441,8 @@ export class VirtualFileSystem implements IVirtualFileSystem {
await this.brain.relate({
from: parentId,
to: entity,
type: VerbType.Contains
type: VerbType.Contains,
metadata: { isVFS: true } // v4.5.1: Mark as VFS relationship
})
// Update path resolver cache
@ -762,7 +764,8 @@ export class VirtualFileSystem implements IVirtualFileSystem {
await this.brain.relate({
from: parentId,
to: entity,
type: VerbType.Contains
type: VerbType.Contains,
metadata: { isVFS: true } // v4.5.1: Mark as VFS relationship
})
}
@ -1674,7 +1677,12 @@ export class VirtualFileSystem implements IVirtualFileSystem {
// Add to new parent
if (newParentPath && newParentPath !== '/') {
const newParentId = await this.pathResolver.resolve(newParentPath)
await this.brain.relate({ from: newParentId, to: entityId, type: VerbType.Contains })
await this.brain.relate({
from: newParentId,
to: entityId,
type: VerbType.Contains,
metadata: { isVFS: true } // v4.5.1: Mark as VFS relationship
})
}
}
@ -1747,7 +1755,12 @@ export class VirtualFileSystem implements IVirtualFileSystem {
const parentPath = this.getParentPath(destPath)
if (parentPath && parentPath !== '/') {
const parentId = await this.pathResolver.resolve(parentPath)
await this.brain.relate({ from: parentId, to: newEntity, type: VerbType.Contains })
await this.brain.relate({
from: parentId,
to: newEntity,
type: VerbType.Contains,
metadata: { isVFS: true } // v4.5.1: Mark as VFS relationship
})
}
// Update path cache
@ -1847,7 +1860,8 @@ export class VirtualFileSystem implements IVirtualFileSystem {
await this.brain.relate({
from: parentId,
to: entity,
type: VerbType.Contains
type: VerbType.Contains,
metadata: { isVFS: true } // v4.5.1: Mark as VFS relationship
})
// Update path resolver cache
@ -2056,7 +2070,8 @@ export class VirtualFileSystem implements IVirtualFileSystem {
await this.brain.relate({
from: fromEntityId,
to: toEntityId,
type: type as any // Convert string to VerbType
type: type as any, // Convert string to VerbType
metadata: { isVFS: true } // v4.5.1: Mark as VFS relationship
})
// Invalidate caches for both paths