diff --git a/docs/vfs/KNOWLEDGE_LAYER_API.md b/docs/vfs/KNOWLEDGE_LAYER_API.md index 862f5aa7..a371f367 100644 --- a/docs/vfs/KNOWLEDGE_LAYER_API.md +++ b/docs/vfs/KNOWLEDGE_LAYER_API.md @@ -7,28 +7,47 @@ The Knowledge Layer transforms Brainy's VFS from a simple filesystem into an int ## Quick Start ```typescript -import { Brainy, VirtualFileSystem, KnowledgeAugmentation } from '@soulcraft/brainy' +import { Brainy } from '@soulcraft/brainy' // Initialize Brainy with VFS const brain = new Brainy() await brain.init() -const vfs = new VirtualFileSystem(brain) +const vfs = brain.vfs() await vfs.init() -// Enable Knowledge Layer -const knowledge = new KnowledgeAugmentation({ - enabled: true, - eventRecording: { enabled: true }, - semanticVersioning: { enabled: true, threshold: 0.3 }, - persistentEntities: { enabled: true, autoExtract: true }, - concepts: { enabled: true, autoLink: true }, - gitBridge: { enabled: true } -}) - -await knowledge.init({ brain, vfs }) +// Enable Knowledge Layer - this augments VFS with intelligence features +await vfs.enableKnowledgeLayer() // Now your VFS has superpowers! 🚀 +// The Knowledge Layer dynamically adds new methods to the VFS instance: +// - Event Recording: getHistory(), reconstructAtTime() +// - Semantic Versioning: getVersions(), restoreVersion() +// - Entity System: createEntity(), linkEntities(), findEntityOccurrences() +// - Concepts: createConcept(), findByConcept() +// - Git Bridge: exportToGit(), importFromGit() +// - And many more... +``` + +## How It Works: Method Augmentation + +The Knowledge Layer uses a powerful augmentation pattern. When you call `enableKnowledgeLayer()`: + +1. **Wraps Core Methods**: Intercepts existing VFS methods to add intelligence +2. **Injects New Methods**: Dynamically adds new methods to the VFS instance +3. **Background Processing**: Runs intelligence extraction asynchronously +4. **Non-Breaking**: All existing code continues to work unchanged + +```typescript +// Before enableKnowledgeLayer() - Core VFS only +vfs.writeFile() ✅ // Works +vfs.readFile() ✅ // Works +vfs.createEntity() ❌ // Method doesn't exist + +// After enableKnowledgeLayer() - Enhanced VFS +vfs.writeFile() ✅ // Still works, now with event recording +vfs.readFile() ✅ // Still works, now tracks access patterns +vfs.createEntity() ✅ // New method available! ``` ## Core Components diff --git a/docs/vfs/USER_FUNCTIONS.md b/docs/vfs/USER_FUNCTIONS.md new file mode 100644 index 00000000..84258813 --- /dev/null +++ b/docs/vfs/USER_FUNCTIONS.md @@ -0,0 +1,728 @@ +# VFS User Functions - Templates and Examples + +This document provides template functions that you can implement for domain-specific needs. These functions combine VFS primitives to solve common problems. + +## Table of Contents +1. [Code Analysis Functions](#code-analysis-functions) +2. [Export Format Functions](#export-format-functions) +3. [Project Management Functions](#project-management-functions) +4. [Creative Writing Functions](#creative-writing-functions) +5. [Game Development Functions](#game-development-functions) + +## Code Analysis Functions + +### Get Dependency Graph +```javascript +/** + * Build a dependency graph for JavaScript/TypeScript projects + */ +async function getDependencyGraph(vfs, srcPath) { + const files = await vfs.readdir(srcPath, { recursive: true }) + const graph = {} + + for (const file of files) { + const filePath = `${srcPath}/${file}` + + // Only process JS/TS files + if (file.match(/\.(js|ts|jsx|tsx)$/)) { + const content = await vfs.readFile(filePath) + const text = content.toString() + + // Parse imports (basic regex, use proper AST parser for production) + const imports = [] + const importRegex = /import\s+.*?\s+from\s+['"](.+?)['"]/g + const requireRegex = /require\(['"](.+?)['"]\)/g + + let match + while ((match = importRegex.exec(text)) !== null) { + imports.push(match[1]) + } + while ((match = requireRegex.exec(text)) !== null) { + imports.push(match[1]) + } + + graph[filePath] = imports + } + } + + return graph +} + +// Use it +const deps = await getDependencyGraph(vfs, '/src') +``` + +### Find Circular Dependencies +```javascript +/** + * Detect circular dependencies in your code + */ +async function findCircularDependencies(vfs, srcPath) { + const graph = await getDependencyGraph(vfs, srcPath) + const cycles = [] + + function detectCycle(node, visited = new Set(), stack = []) { + if (stack.includes(node)) { + const cycleStart = stack.indexOf(node) + cycles.push(stack.slice(cycleStart)) + return + } + + if (visited.has(node)) return + visited.add(node) + stack.push(node) + + const dependencies = graph[node] || [] + for (const dep of dependencies) { + // Resolve relative imports + const resolvedDep = resolvePath(node, dep) + if (graph[resolvedDep]) { + detectCycle(resolvedDep, visited, [...stack]) + } + } + } + + Object.keys(graph).forEach(node => detectCycle(node)) + return cycles +} +``` + +### Find Untested Code +```javascript +/** + * Find source files without corresponding test files + */ +async function findUntestedCode(vfs, srcPath, testPath = null) { + testPath = testPath || srcPath.replace('/src', '/tests') + + const sourceFiles = await vfs.readdir(srcPath, { recursive: true }) + const testFiles = await vfs.readdir(testPath, { recursive: true }).catch(() => []) + + const untestedFiles = [] + + for (const sourceFile of sourceFiles) { + if (!sourceFile.match(/\.(js|ts|jsx|tsx)$/)) continue + + // Look for corresponding test file + const baseName = sourceFile.replace(/\.(js|ts|jsx|tsx)$/, '') + const hasTest = testFiles.some(testFile => + testFile.includes(baseName) && + testFile.match(/\.(test|spec)\.(js|ts|jsx|tsx)$/) + ) + + if (!hasTest) { + untestedFiles.push(`${srcPath}/${sourceFile}`) + } + } + + return untestedFiles +} +``` + +### Find Similar Code (Duplicate Detection) +```javascript +/** + * Find potentially duplicate code using similarity scoring + */ +async function findSimilarCode(vfs, filePath, options = {}) { + const threshold = options.threshold || 0.8 + const searchPath = options.searchPath || '/' + + // Get the reference file content + const referenceContent = await vfs.readFile(filePath) + const referenceText = referenceContent.toString() + + // Use VFS's semantic search + const similar = await vfs.findSimilar(filePath, { + limit: 10, + threshold + }) + + // Additionally, do structural comparison + const results = [] + for (const match of similar) { + const matchContent = await vfs.readFile(match.path) + const matchText = matchContent.toString() + + // Simple line-based similarity (use better algorithms in production) + const similarity = calculateSimilarity(referenceText, matchText) + + if (similarity > threshold) { + results.push({ + path: match.path, + similarity, + semanticScore: match.score + }) + } + } + + return results.sort((a, b) => b.similarity - a.similarity) +} + +function calculateSimilarity(text1, text2) { + // Simple Jaccard similarity on lines + const lines1 = new Set(text1.split('\n').map(l => l.trim()).filter(l => l)) + const lines2 = new Set(text2.split('\n').map(l => l.trim()).filter(l => l)) + + const intersection = new Set([...lines1].filter(x => lines2.has(x))) + const union = new Set([...lines1, ...lines2]) + + return intersection.size / union.size +} +``` + +## Export Format Functions + +### Export to EPUB (for novels) +```javascript +/** + * Export a directory of markdown files to EPUB format + */ +async function exportToEpub(vfs, path, metadata = {}) { + // First get the markdown export + const markdown = await vfs.exportToMarkdown(path) + + // You'll need an EPUB library like epub-gen + const Epub = require('epub-gen') + + // Convert markdown chapters to EPUB format + const chapters = [] + const files = await vfs.readdir(path, { recursive: true }) + + for (const file of files.sort()) { + if (file.endsWith('.md')) { + const content = await vfs.readFile(`${path}/${file}`) + const title = file.replace('.md', '').replace(/-/g, ' ') + + chapters.push({ + title: title, + data: content.toString() + }) + } + } + + const options = { + title: metadata.title || 'My Book', + author: metadata.author || 'Author', + chapters: chapters + } + + return new Epub(options) +} +``` + +### Export to Static Site +```javascript +/** + * Export VFS content to static HTML site + */ +async function exportToStaticSite(vfs, sourcePath, options = {}) { + const json = await vfs.exportToJSON(sourcePath) + const html = [] + + html.push('') + html.push('') + html.push(`${options.title || 'Documentation'}`) + html.push('') + html.push('') + + function renderNode(node, name, depth = 0) { + const indent = ' '.repeat(depth) + + if (node._meta?.type === 'file') { + html.push(`${indent}
`) + html.push(`${indent} ${name}`) + + if (typeof node._content === 'string') { + // Convert markdown to HTML if needed + html.push(`${indent}
${escapeHtml(node._content)}
`) + } + + html.push(`${indent}
`) + } else if (node._meta?.type === 'directory') { + html.push(`${indent}
`) + html.push(`${indent} ${name}`) + + for (const [childName, childNode] of Object.entries(node)) { + if (!childName.startsWith('_')) { + renderNode(childNode, childName, depth + 1) + } + } + + html.push(`${indent}
`) + } + } + + renderNode(json, options.title || 'Root') + + html.push('') + return html.join('\n') +} +``` + +### Export to GraphQL Schema +```javascript +/** + * Generate GraphQL schema from VFS entities + */ +async function exportToGraphQLSchema(vfs) { + const entities = await vfs.listEntities() + const types = new Map() + + // Group entities by type + for (const entity of entities) { + const type = entity.type || 'Unknown' + if (!types.has(type)) { + types.set(type, []) + } + types.get(type).push(entity) + } + + // Generate schema + let schema = 'type Query {\n' + + for (const [typeName, entities] of types) { + schema += ` get${typeName}(id: ID!): ${typeName}\n` + schema += ` list${typeName}s: [${typeName}!]!\n` + } + + schema += '}\n\n' + + // Generate types + for (const [typeName, entities] of types) { + schema += `type ${typeName} {\n` + schema += ' id: ID!\n' + + // Infer fields from first entity + if (entities.length > 0) { + const sample = entities[0] + for (const [key, value] of Object.entries(sample)) { + if (key !== 'id') { + const fieldType = inferGraphQLType(value) + schema += ` ${key}: ${fieldType}\n` + } + } + } + + schema += '}\n\n' + } + + return schema +} +``` + +## Project Management Functions + +### Get Project Insights +```javascript +/** + * Analyze project for insights and patterns + */ +async function getProjectInsights(vfs, projectPath) { + const stats = await vfs.getProjectStats(projectPath) + const todos = await vfs.getAllTodos(projectPath) + const timeline = await vfs.getTimeline({ limit: 100 }) + + // Analyze activity patterns + const activityByDay = {} + const activityByUser = {} + const activityByFile = {} + + for (const event of timeline) { + const day = event.timestamp.toISOString().split('T')[0] + activityByDay[day] = (activityByDay[day] || 0) + 1 + + const user = event.user || 'system' + activityByUser[user] = (activityByUser[user] || 0) + 1 + + activityByFile[event.path] = (activityByFile[event.path] || 0) + 1 + } + + // Find hotspots (most edited files) + const hotspots = Object.entries(activityByFile) + .sort(([,a], [,b]) => b - a) + .slice(0, 10) + .map(([path, count]) => ({ path, edits: count })) + + // Todo analysis + const todosByPriority = {} + const todosByStatus = {} + + for (const todo of todos) { + todosByPriority[todo.priority] = (todosByPriority[todo.priority] || 0) + 1 + todosByStatus[todo.status] = (todosByStatus[todo.status] || 0) + 1 + } + + return { + stats, + activity: { + byDay: activityByDay, + byUser: activityByUser, + hotspots + }, + todos: { + total: todos.length, + byPriority: todosByPriority, + byStatus: todosByStatus, + highPriority: todos.filter(t => t.priority === 'high' && t.status === 'pending') + }, + recommendations: generateRecommendations(stats, todos, hotspots) + } +} + +function generateRecommendations(stats, todos, hotspots) { + const recommendations = [] + + if (stats.largestFile && stats.largestFile.size > 1024 * 1024) { + recommendations.push({ + type: 'refactor', + message: `Consider splitting ${stats.largestFile.path} (${Math.round(stats.largestFile.size / 1024)}KB)` + }) + } + + if (todos.filter(t => t.priority === 'high' && t.status === 'pending').length > 5) { + recommendations.push({ + type: 'priority', + message: 'You have many high-priority pending todos' + }) + } + + if (hotspots.length > 0 && hotspots[0].edits > 50) { + recommendations.push({ + type: 'stability', + message: `${hotspots[0].path} changes frequently, consider stabilizing` + }) + } + + return recommendations +} +``` + +### Generate Sprint Report +```javascript +/** + * Generate a report for the current sprint + */ +async function generateSprintReport(vfs, sprintStart, sprintEnd = new Date()) { + const timeline = await vfs.getTimeline({ + from: sprintStart, + to: sprintEnd + }) + + const todos = await vfs.getAllTodos() + + // Group work by user + const workByUser = {} + for (const event of timeline) { + const user = event.user || 'system' + if (!workByUser[user]) { + workByUser[user] = { + commits: 0, + filesModified: new Set(), + linesChanged: 0 + } + } + + workByUser[user].commits++ + workByUser[user].filesModified.add(event.path) + } + + // Calculate completion rate + const completedTodos = todos.filter(t => t.status === 'completed').length + const totalTodos = todos.length + const completionRate = totalTodos > 0 ? (completedTodos / totalTodos * 100).toFixed(1) : 0 + + return { + period: { + start: sprintStart, + end: sprintEnd, + days: Math.ceil((sprintEnd - sprintStart) / (1000 * 60 * 60 * 24)) + }, + team: Object.entries(workByUser).map(([user, work]) => ({ + user, + commits: work.commits, + filesModified: work.filesModified.size + })), + todos: { + completed: completedTodos, + total: totalTodos, + completionRate: `${completionRate}%`, + remaining: todos.filter(t => t.status === 'pending') + }, + velocity: { + commitsPerDay: (timeline.length / 7).toFixed(1), + todosPerDay: (completedTodos / 7).toFixed(1) + } + } +} +``` + +## Creative Writing Functions + +### Track Character Arcs +```javascript +/** + * Track how characters evolve throughout a story + */ +async function trackCharacterArc(vfs, characterName, storyPath = '/') { + // Find the character entity + const entities = await vfs.searchEntities({ + type: 'character', + name: characterName + }) + + if (entities.length === 0) { + throw new Error(`Character ${characterName} not found`) + } + + const character = entities[0] + const occurrences = await vfs.findEntityOccurrences(character.id) + + // Analyze each appearance + const arc = [] + + for (const occurrence of occurrences) { + const content = await vfs.readFile(occurrence.path) + const text = content.toString() + + // Find mentions of the character (basic approach) + const mentions = text.split('\n').filter(line => + line.toLowerCase().includes(characterName.toLowerCase()) + ) + + arc.push({ + chapter: occurrence.path, + mentions: mentions.length, + // Analyze emotional tone (simplified) + mood: analyzeMood(mentions), + // Extract key actions + actions: extractActions(mentions, characterName) + }) + } + + return { + character: character.metadata, + arc: arc, + summary: summarizeArc(arc) + } +} + +function analyzeMood(mentions) { + const positiveWords = ['smiled', 'laughed', 'happy', 'joy', 'love', 'success'] + const negativeWords = ['cried', 'angry', 'sad', 'fear', 'fail', 'death'] + + let positive = 0, negative = 0 + + for (const mention of mentions) { + const lower = mention.toLowerCase() + positive += positiveWords.filter(w => lower.includes(w)).length + negative += negativeWords.filter(w => lower.includes(w)).length + } + + if (positive > negative) return 'positive' + if (negative > positive) return 'negative' + return 'neutral' +} +``` + +### Generate Story Bible +```javascript +/** + * Create a comprehensive reference for your story universe + */ +async function generateStoryBible(vfs, storyPath) { + const characters = await vfs.listEntities({ type: 'character' }) + const locations = await vfs.listEntities({ type: 'location' }) + const concepts = await vfs.findConcepts({ domain: 'narrative' }) + + const bible = { + title: 'Story Bible', + generated: new Date(), + characters: {}, + locations: {}, + plotThreads: {}, + timeline: [] + } + + // Document characters + for (const char of characters) { + const occurrences = await vfs.findEntityOccurrences(char.id) + bible.characters[char.metadata.name] = { + ...char.metadata, + appearances: occurrences.map(o => o.path), + relationships: await vfs.getEntityGraph(char.id, { depth: 1 }) + } + } + + // Document locations + for (const loc of locations) { + bible.locations[loc.metadata.name] = { + ...loc.metadata, + scenes: await vfs.findEntityOccurrences(loc.id) + } + } + + // Plot threads from concepts + for (const concept of concepts) { + if (concept.type === 'plot') { + bible.plotThreads[concept.name] = { + description: concept.description, + keywords: concept.keywords, + chapters: await vfs.findByConcept(concept.name) + } + } + } + + // Generate timeline + const events = await vfs.getTimeline({ limit: 1000 }) + bible.timeline = events.map(e => ({ + date: e.timestamp, + event: e.description, + chapter: e.path + })) + + return bible +} +``` + +## Game Development Functions + +### Validate Game Data +```javascript +/** + * Validate game configuration files for consistency + */ +async function validateGameData(vfs, gamePath) { + const errors = [] + const warnings = [] + + // Load all game data + const gameData = await vfs.exportToJSON(gamePath) + + // Check quest references + if (gameData.quests) { + for (const [questName, quest] of Object.entries(gameData.quests)) { + // Check NPC references + if (quest._content?.questGiver) { + const npcPath = `${gamePath}/npcs/${quest._content.questGiver}.json` + const exists = await vfs.exists(npcPath) + if (!exists) { + errors.push(`Quest ${questName} references missing NPC: ${quest._content.questGiver}`) + } + } + + // Check item rewards + if (quest._content?.rewards?.items) { + for (const item of quest._content.rewards.items) { + const itemPath = `${gamePath}/items/${item}.json` + const exists = await vfs.exists(itemPath) + if (!exists) { + warnings.push(`Quest ${questName} rewards missing item: ${item}`) + } + } + } + } + } + + // Check balance + if (gameData.items) { + const itemPowers = [] + for (const [itemName, item] of Object.entries(gameData.items)) { + if (item._content?.stats) { + const totalPower = Object.values(item._content.stats) + .reduce((a, b) => a + b, 0) + itemPowers.push({ name: itemName, power: totalPower }) + } + } + + // Find outliers + const avgPower = itemPowers.reduce((a, b) => a + b.power, 0) / itemPowers.length + const outliers = itemPowers.filter(i => Math.abs(i.power - avgPower) > avgPower * 2) + + for (const outlier of outliers) { + warnings.push(`Item ${outlier.name} may be imbalanced (power: ${outlier.power}, avg: ${avgPower})`) + } + } + + return { errors, warnings, valid: errors.length === 0 } +} +``` + +### Generate Loot Tables +```javascript +/** + * Generate weighted loot tables from item definitions + */ +async function generateLootTables(vfs, itemsPath) { + const items = await vfs.exportToJSON(itemsPath) + const tables = { + common: [], + uncommon: [], + rare: [], + epic: [], + legendary: [] + } + + for (const [itemName, item] of Object.entries(items)) { + if (item._meta?.type === 'file' && item._content?.rarity) { + const entry = { + name: itemName.replace('.json', ''), + weight: getWeight(item._content.rarity), + data: item._content + } + + tables[item._content.rarity.toLowerCase()].push(entry) + } + } + + // Normalize weights + for (const table of Object.values(tables)) { + const totalWeight = table.reduce((a, b) => a + b.weight, 0) + for (const entry of table) { + entry.probability = (entry.weight / totalWeight * 100).toFixed(2) + '%' + } + } + + return tables +} + +function getWeight(rarity) { + const weights = { + common: 100, + uncommon: 50, + rare: 20, + epic: 5, + legendary: 1 + } + return weights[rarity.toLowerCase()] || 10 +} +``` + +## Using These Functions + +All these functions are templates that you can customize for your specific needs. To use them: + +1. Copy the function you need +2. Modify it for your specific requirements +3. Use it with your VFS instance: + +```javascript +import { Brainy } from '@soulcraft/brainy' + +// Initialize VFS +const brain = new Brainy() +await brain.init() +const vfs = brain.vfs() +await vfs.init() + +// Use your custom function +const insights = await getProjectInsights(vfs, '/my-project') +console.log(insights.recommendations) + +// Combine multiple functions +const deps = await getDependencyGraph(vfs, '/src') +const cycles = await findCircularDependencies(vfs, '/src') +const untested = await findUntestedCode(vfs, '/src', '/tests') +``` + +Remember: These are starting points. The power of VFS is that you can combine its primitives to build exactly what you need for your domain! \ No newline at end of file diff --git a/docs/vfs/VFS_API_GUIDE.md b/docs/vfs/VFS_API_GUIDE.md index 650ce1be..8a2a6c29 100644 --- a/docs/vfs/VFS_API_GUIDE.md +++ b/docs/vfs/VFS_API_GUIDE.md @@ -7,7 +7,7 @@ Brainy's Virtual Filesystem (VFS) provides a POSIX-like filesystem interface tha ## Quick Start ```typescript -import { Brainy, VirtualFileSystem } from '@soulcraft/brainy' +import { Brainy } from '@soulcraft/brainy' // Initialize Brainy const brain = new Brainy({ @@ -16,7 +16,7 @@ const brain = new Brainy({ await brain.init() // Create VFS instance -const vfs = new VirtualFileSystem(brain) +const vfs = brain.vfs() await vfs.init() // Use like any filesystem @@ -140,8 +140,8 @@ await vfs.rmdir('/projects/my-app', { recursive: true }) // Rename/move file or directory await vfs.rename(oldPath: string, newPath: string): Promise -// Copy file (Note: Implementation needed) -// await vfs.copy(src: string, dest: string, options?: CopyOptions): Promise +// Copy file or directory +await vfs.copy(src: string, dest: string, options?: CopyOptions): Promise ``` **Example:** diff --git a/docs/vfs/VFS_CORE.md b/docs/vfs/VFS_CORE.md index 8bd43ef5..4cbd8d1d 100644 --- a/docs/vfs/VFS_CORE.md +++ b/docs/vfs/VFS_CORE.md @@ -273,23 +273,39 @@ await vfs.importDirectory('/local/project', { targetPath: '/vfs/project' }) // - Preserved metadata (timestamps, permissions) ``` -### GitBridge Export +### GitBridge Integration +GitBridge provides Git import/export capabilities. It can be used in two ways: + +#### Option 1: Via Knowledge Layer (Recommended) ```javascript -// Enable GitBridge -const gitBridge = vfs.gitBridge +// Enable Knowledge Layer to get Git methods +await vfs.enableKnowledgeLayer() -// Export relationships as .brainy/relationships.json -const rels = await gitBridge.exportRelationships('/project') +// Now Git methods are available on VFS +await vfs.exportToGit('/project', '/local/git/repo') +await vfs.importFromGit('/local/git/repo', '/project') +``` -// Export events as .brainy/events.json -const events = await gitBridge.exportEvents('/project') +#### Option 2: Direct GitBridge Usage +```javascript +// Import and instantiate GitBridge +import { GitBridge } from '@soulcraft/brainy' +const gitBridge = new GitBridge(vfs, brain) -// Export entities as .brainy/entities.json -const entities = await gitBridge.exportEntities() +// Export VFS to Git repository structure +await gitBridge.exportToGit('/project', '/local/git/repo', { + preserveMetadata: true, // Export VFS metadata as .vfs-metadata.json + preserveRelationships: true, // Export relationships as .vfs-relationships.json + preserveHistory: true // Export event history as .vfs-history.json +}) -// Export concepts as .brainy/concepts.json -const concepts = await gitBridge.exportConcepts() +// Import Git repository into VFS +await gitBridge.importFromGit('/local/git/repo', '/project', { + preserveGitHistory: true, // Import Git commits as VFS events + extractMetadata: true, // Extract metadata from .vfs-metadata.json + restoreRelationships: true // Restore relationships from .vfs-relationships.json +}) ``` ## Performance Optimizations @@ -355,6 +371,49 @@ VFS scales to millions of files: - Distributed storage backend support - Vector search scales with HNSW index +## Method Availability + +### Core VFS Methods (Always Available) + +These methods are available immediately after VFS initialization: + +```javascript +const vfs = brain.vfs() +await vfs.init() + +// ✅ All these work without Knowledge Layer: +await vfs.writeFile() // File operations +await vfs.readFile() +await vfs.mkdir() // Directory operations +await vfs.readdir() +await vfs.stat() // Metadata +await vfs.search() // Semantic search +await vfs.addRelationship() // Relationships +await vfs.addTodo() // Todo management +await vfs.exportToJSON() // Export +await vfs.bulkWrite() // Bulk operations +``` + +### Knowledge Layer Methods (Require Enablement) + +These methods are only available after enabling the Knowledge Layer: + +```javascript +await vfs.enableKnowledgeLayer() + +// 🔮 Now these methods are available: +await vfs.createEntity() // Entity management +await vfs.linkEntities() +await vfs.createConcept() // Concept system +await vfs.findByConcept() +await vfs.getVersions() // Versioning +await vfs.getHistory() // History tracking +await vfs.exportToGit() // Git integration (wrapper) +await vfs.importFromGit() +await vfs.exportToMarkdown()// Export formats +await vfs.getTimeline() // Timeline analysis +``` + ## Complete Example ```javascript diff --git a/docs/vfs/VFS_EXAMPLES_SCENARIOS.md b/docs/vfs/VFS_EXAMPLES_SCENARIOS.md index 77512c37..21dabcb7 100644 --- a/docs/vfs/VFS_EXAMPLES_SCENARIOS.md +++ b/docs/vfs/VFS_EXAMPLES_SCENARIOS.md @@ -2,7 +2,14 @@ ## Real-World Scenarios -This document demonstrates how VFS with Knowledge Layer enables powerful real-world applications. All examples show actual working code. +This document demonstrates how VFS with Knowledge Layer enables powerful real-world applications. + +### Legend +- ✅ **Real VFS methods** - Fully implemented and working +- 📝 **User functions** - Templates available in [USER_FUNCTIONS.md](./USER_FUNCTIONS.md) +- 🔮 **Future features** - Not yet available (AI augmentations) + +**Note:** All ✅ marked methods are production-ready. For 📝 methods, see USER_FUNCTIONS.md for implementation templates. ## Scenario 1: Collaborative Novel Writing @@ -19,13 +26,13 @@ async function novelWritingProject() { await vfs.init() await vfs.enableKnowledgeLayer() - // Create project structure + // Create project structure ✅ await vfs.mkdir('/novel') await vfs.mkdir('/novel/chapters') await vfs.mkdir('/novel/characters') await vfs.mkdir('/novel/worldbuilding') - // Define main characters as persistent entities + // Define main characters as persistent entities ✅ const protagonist = await vfs.createEntity({ name: 'Elena Blackwood', type: 'character', @@ -61,7 +68,7 @@ async function novelWritingProject() { } }) - // Link entities + // Link entities ✅ await vfs.linkEntities(protagonist.id, city.id, 'lives_in') await vfs.linkEntities(protagonist.id, antagonist.id, 'investigates') @@ -77,7 +84,7 @@ async function novelWritingProject() { infiltrate the Crypto Quarter facility. `) - // Multiple authors can work simultaneously + // Multiple authors can work simultaneously ✅ vfs.setUser('author-alice') await vfs.writeFile('/novel/chapters/chapter2.md', ` # Chapter 2: The Void Industries Tower @@ -92,17 +99,17 @@ async function novelWritingProject() { He smiled. Let her come. The trap was already set. `) - // Track character appearances across chapters + // Track character appearances across chapters ✅ const elenaAppearances = await vfs.findEntityOccurrences(protagonist.id) console.log('Elena appears in:', elenaAppearances.map(f => f.path)) - // Find all locations mentioned + // Find all locations mentioned ✅ const locations = await vfs.listEntities({ type: 'location' }) - // Generate character relationship graph + // Generate character relationship graph ✅ const relationships = await vfs.getEntityGraph(protagonist.id, { depth: 2 }) - // Track plot threads using concepts + // Track plot threads using concepts ✅ await vfs.createConcept({ name: 'The Void Conspiracy', type: 'plot', @@ -111,17 +118,17 @@ async function novelWritingProject() { keywords: ['scientists', 'experiments', 'void industries', 'conspiracy'] }) - // Find all chapters related to the conspiracy + // Find all chapters related to the conspiracy ✅ const conspiracyChapters = await vfs.findByConcept('The Void Conspiracy') - // Version control for revisions + // Version control for revisions ✅ const chapterVersions = await vfs.getVersions('/novel/chapters/chapter1.md') - // Collaborative editing history + // Collaborative editing history ✅ const history = await vfs.getCollaborationHistory('/novel/chapters/chapter2.md') console.log('Chapter 2 edited by:', history.map(h => h.user)) - // Export for publishing + // Export for publishing ✅ const manuscript = await vfs.exportToMarkdown('/novel/chapters') await vfs.close() @@ -234,7 +241,7 @@ async function gameDevProject() { export default CombatSystem `) - // Asset management + // Asset management ✅ await vfs.writeFile('/game/assets/sprites/elder_sage.png', spriteData) await vfs.setMetadata('/game/assets/sprites/elder_sage.png', { dimensions: '64x64', @@ -243,23 +250,23 @@ async function gameDevProject() { license: 'CC-BY-4.0' }) - // Track dependencies + // Track dependencies ✅ await vfs.addRelationship('/game/quests/main_quest.json', '/game/npcs/elder_sage.json', 'uses') await vfs.addRelationship('/game/scripts/combat.js', '/game/systems/stats.js', 'imports') - // Find all content related to combat + // Find all content related to combat ✅ const combatFiles = await vfs.findByConcept('Combat System') - // Get all NPCs in a specific location + // Get all NPCs in a specific location ✅ const villageNPCs = await vfs.searchEntities({ type: 'npc', where: { 'attributes.location': 'Village Square' } }) - // Track game balance changes + // Track game balance changes ✅ const balanceHistory = await vfs.getHistory('/game/data/balance.json') - // Collaborative development tracking + // Collaborative development tracking ✅ await vfs.addTodo('/game/quests/main_quest.json', { task: 'Add voice dialogue triggers', priority: 'medium', @@ -267,7 +274,7 @@ async function gameDevProject() { assignee: 'audio-team' }) - // Export for build system + // Export for build system ✅ const gameData = await vfs.exportToJSON('/game') await vfs.close() @@ -288,7 +295,7 @@ async function softwareProject() { await vfs.init() await vfs.enableKnowledgeLayer() - // Import existing git repository + // Import existing git repository ✅ (Knowledge Layer provides wrapper) await vfs.importFromGit('/local/repos/webapp', '/project') // Define architectural concepts @@ -397,43 +404,43 @@ async function softwareProject() { \`\`\` `) - // Find all files needing security review + // Find all files needing security review ✅ const securityFiles = await vfs.search('authentication password jwt oauth', { path: '/project/src', type: 'file' }) - // Get project insights - const insights = await vfs.getInsights('/project') + // Get project insights 📝 (see USER_FUNCTIONS.md for getProjectInsights) + const insights = await getProjectInsights(vfs, '/project') // User function console.log('Most modified files:', insights.hotspots) console.log('Key concepts:', insights.concepts) console.log('Team activity:', insights.contributors) - // Find circular dependencies - const circularDeps = await vfs.findCircularDependencies('/project/src') + // Find circular dependencies 📝 (see USER_FUNCTIONS.md) + const circularDeps = await findCircularDependencies(vfs, '/project/src') // User function - // Get test coverage relationships - const untested = await vfs.findUntestedCode('/project/src') + // Get test coverage relationships 📝 (see USER_FUNCTIONS.md) + const untested = await findUntestedCode(vfs, '/project/src') // User function - // Track technical debt + // Track technical debt ✅ const todos = await vfs.getAllTodos('/project') const highPriorityDebt = todos.filter(t => t.priority === 'high' && t.status === 'pending') - // Generate dependency graph - const depGraph = await vfs.getDependencyGraph('/project/src') + // Generate dependency graph 📝 (see USER_FUNCTIONS.md) + const depGraph = await getDependencyGraph(vfs, '/project/src') // User function - // Find similar code (potential refactoring) - const similarCode = await vfs.findSimilarCode('/project/src/auth/login.ts', { + // Find similar code (potential refactoring) 📝 (see USER_FUNCTIONS.md) + const similarCode = await findSimilarCode(vfs, '/project/src/auth/login.ts', { threshold: 0.8, minLines: 10 - }) + }) // User function - // Export for CI/CD + // Export for CI/CD ✅ (Knowledge Layer provides wrapper) await vfs.exportToGit('/project', '/tmp/build-output') - // Collaborative features - vfs.setUser('developer-alice') - const conflicts = await vfs.detectConflicts('/project/src/auth/login.ts') + // Collaborative features ✅ / 🔮 + vfs.setUser('developer-alice') // ✅ Real method + // const conflicts = await vfs.detectConflicts('/project/src/auth/login.ts') // 🔮 Future feature await vfs.close() await brain.close() @@ -486,7 +493,7 @@ async function unifiedKnowledgeBase() { role: 'detective' }])) - // Cross-project entity tracking + // Cross-project entity tracking ✅ const elenaOccurrences = await vfs.findEntityOccurrences(sharedCharacter.id) console.log('Elena appears across projects:', elenaOccurrences) @@ -497,36 +504,36 @@ async function unifiedKnowledgeBase() { domain: 'software' }) - // Find auth implementations across all projects + // Find auth implementations across all projects ✅ const authImplementations = await vfs.findByConcept('Authentication') // Returns: /webapp/src/auth.js, /game/scripts/player-auth.js, etc. - // Cross-project relationships + // Cross-project relationships ✅ await vfs.addRelationship('/novel/chapter1.md', '/game/story/intro.txt', 'inspires') await vfs.addRelationship('/game/npcs/elena.json', '/novel/characters/elena.md', 'based_on') - // Universal search across all projects + // Universal search across all projects ✅ const results = await vfs.search('Elena Blackwood authentication', { path: '/', recursive: true }) - // Project statistics - const novelStats = await vfs.getProjectStats('/novel') - const gameStats = await vfs.getProjectStats('/game') - const webappStats = await vfs.getProjectStats('/webapp') + // Project statistics 📝 (see USER_FUNCTIONS.md for getProjectStats) + const novelStats = await getProjectStats(vfs, '/novel') // User function + const gameStats = await getProjectStats(vfs, '/game') // User function + const webappStats = await getProjectStats(vfs, '/webapp') // User function console.log('Total files:', novelStats.fileCount + gameStats.fileCount + webappStats.fileCount) console.log('Total size:', novelStats.totalSize + gameStats.totalSize + webappStats.totalSize) - // Knowledge graph visualization data - const knowledgeGraph = await vfs.getGlobalKnowledgeGraph() + // Knowledge graph visualization data 🔮 (future feature) + // const knowledgeGraph = await vfs.getGlobalKnowledgeGraph() // Not yet implemented // Returns nodes (files, entities, concepts) and edges (relationships) - // Find connections between projects - const crossProjectLinks = await vfs.findCrossProjectLinks() + // Find connections between projects 🔮 (future feature) + // const crossProjectLinks = await vfs.findCrossProjectLinks() // Not yet implemented - // Unified timeline + // Unified timeline ✅ const timeline = await vfs.getTimeline({ from: '2025-01-01', to: '2025-12-31' @@ -539,101 +546,135 @@ async function unifiedKnowledgeBase() { ## Advanced Features -### Semantic Code Analysis +### Semantic Code Analysis 📝 + +These are user functions - see [USER_FUNCTIONS.md](./USER_FUNCTIONS.md) for implementation templates: ```javascript -// Find security vulnerabilities -const vulnerabilities = await vfs.findPatterns([ +// Find security vulnerabilities (user function example) +const vulnerabilities = await findPatterns(vfs, [ 'eval(', 'innerHTML =', 'SQL injection', 'hardcoded password' ]) -// Find code smells -const codeSmells = await vfs.analyzeCodeQuality('/src', { +// Find code smells (user function example) +const codeSmells = await analyzeCodeQuality(vfs, '/src', { checkDuplication: true, checkComplexity: true, checkNaming: true }) ``` -### AI-Powered Features +### AI-Powered Features 🔮 + +**Note:** These features require AI integration and are not yet available. ```javascript -// Generate documentation -const docs = await vfs.generateDocumentation('/src/auth/login.ts') +// Future: Generate documentation +// const docs = await vfs.generateDocumentation('/src/auth/login.ts') -// Suggest refactorings -const refactorings = await vfs.suggestRefactorings('/src/utils.js') +// Future: Suggest refactorings +// const refactorings = await vfs.suggestRefactorings('/src/utils.js') -// Auto-complete code -const completion = await vfs.completeCode('/src/api.ts', { line: 42, column: 10 }) +// Future: Auto-complete code +// const completion = await vfs.completeCode('/src/api.ts', { line: 42, column: 10 }) ``` -### Migration and Backup +### Migration and Backup 🔮 + +**Note:** These features are planned but not yet implemented. ```javascript -// Backup with full history -await vfs.createBackup('/backup/2025-01-20.brainy') +// Future: Backup with full history +// await vfs.createBackup('/backup/2025-01-20.brainy') -// Migrate between storage backends -const migration = await vfs.migrate({ - from: { type: 'file', path: './old-data' }, - to: { type: 's3', bucket: 'new-bucket' } -}) +// Future: Migrate between storage backends +// const migration = await vfs.migrate({ +// from: { type: 'file', path: './old-data' }, +// to: { type: 's3', bucket: 'new-bucket' } +// }) -// Incremental sync -await vfs.sync('/local/path', '/vfs/path', { - bidirectional: true, - conflictStrategy: 'newest' -}) +// Future: Incremental sync +// await vfs.sync('/local/path', '/vfs/path', { +// bidirectional: true, +// conflictStrategy: 'newest' +// }) ``` ### Performance at Scale ```javascript -// Handle millions of files +// Handle millions of files ✅ for (let i = 0; i < 1000000; i++) { await vfs.writeFile(`/data/file${i}.txt`, `Content ${i}`) // Uses chunking, compression, and efficient indexing } -// Fast parallel operations +// Fast parallel operations ✅ await Promise.all([ vfs.writeFile('/file1.txt', 'data1'), vfs.writeFile('/file2.txt', 'data2'), vfs.writeFile('/file3.txt', 'data3') ]) -// Bulk imports -await vfs.bulkImport('/massive/dataset', { - parallel: 10, - batchSize: 1000, - progress: (count, total) => console.log(`${count}/${total}`) -}) +// Bulk write operations ✅ +const files = [ + { path: '/data/file1.txt', content: 'Content 1' }, + { path: '/data/file2.txt', content: 'Content 2' }, + // ... more files +] +await vfs.bulkWrite(files) + +// Bulk imports 🔮 (future feature) +// await vfs.bulkImport('/massive/dataset', { +// parallel: 10, +// batchSize: 1000, +// progress: (count, total) => console.log(`${count}/${total}`) +// }) ``` -## Real Implementation Notes +## Implementation Status -All examples in this document use actual VFS APIs that are fully implemented: +### ✅ Fully Implemented Features -1. **Storage**: Real Brainy entities, not mock data -2. **Embeddings**: Real vector embeddings via brain.embed() -3. **Relationships**: Real graph relationships via brain.relate() -4. **Search**: Real semantic search via brain.search() -5. **Events**: Real event recording in Knowledge Layer -6. **Versions**: Real semantic versioning based on similarity -7. **Entities**: Real persistent entity tracking -8. **Concepts**: Real concept detection and management -9. **Git**: Real GitBridge import/export functionality +All methods marked with ✅ are production-ready: -This is production-ready code with: -- No stubs or mocks -- Complete error handling -- Full async/await support -- Proper resource cleanup -- Thread-safe operations -- Scalable architecture +1. **Core VFS Operations**: mkdir, writeFile, readFile, appendFile, stat, readdir, etc. +2. **Entity System**: createEntity, linkEntities, findEntityOccurrences, updateEntity, getEntityGraph +3. **Concept System**: createConcept, findByConcept +4. **Knowledge Layer**: Event recording, semantic versioning, collaboration tracking +5. **Search**: Triple Intelligence (vector + field + graph) +6. **Git Integration**: importFromGit, exportToGit +7. **Export Formats**: exportToMarkdown, exportToJSON +8. **Bulk Operations**: bulkWrite for efficient batch processing +9. **Project Management**: todos, metadata, relationships -The VFS + Knowledge Layer combination enables these scenarios and more, providing a foundation for intelligent applications that understand and manage knowledge. \ No newline at end of file +### 📝 User Functions + +Methods marked with 📝 are domain-specific functions that you can implement using VFS primitives. See [USER_FUNCTIONS.md](./USER_FUNCTIONS.md) for ready-to-use templates: + +- **Code Analysis**: getDependencyGraph, findCircularDependencies, findUntestedCode, findSimilarCode +- **Creative Writing**: trackCharacterArc, generateStoryBible +- **Game Development**: validateGameData, generateLootTables +- **Project Management**: getProjectInsights, generateSprintReport +- **Export Formats**: exportToEpub, exportToStaticSite + +### 🔮 Future Features + +Methods marked with 🔮 require AI integration or are planned for future releases: + +- **AI-Powered**: generateDocumentation, suggestRefactorings, completeCode +- **Advanced Analysis**: detectConflicts, getGlobalKnowledgeGraph, findCrossProjectLinks +- **Migration Tools**: createBackup, migrate, sync, bulkImport + +## Real Implementation Guarantees + +- **No Mocks**: Every ✅ method is fully functional +- **Real Storage**: Uses Brainy entities with embeddings +- **Real Search**: Triple Intelligence combining vectors, fields, and graphs +- **Real Relationships**: Graph-based connections via brain.relate() +- **Production Ready**: Complete error handling, async/await, resource cleanup + +The VFS + Knowledge Layer combination provides a solid foundation for intelligent applications. Use the ✅ methods directly, implement 📝 functions as needed for your domain, and stay tuned for 🔮 features. \ No newline at end of file diff --git a/src/vfs/VirtualFileSystem.ts b/src/vfs/VirtualFileSystem.ts index 3bf01fd5..6f557b12 100644 --- a/src/vfs/VirtualFileSystem.ts +++ b/src/vfs/VirtualFileSystem.ts @@ -1908,6 +1908,178 @@ export class VirtualFileSystem implements IVirtualFileSystem { return allTodos } + /** + * Export directory structure to JSON + */ + async exportToJSON(path: string = '/'): Promise { + await this.ensureInitialized() + + const result: any = {} + + const traverse = async (currentPath: string, target: any) => { + try { + const entityId = await this.pathResolver.resolve(currentPath) + const entity = await this.getEntityById(entityId) + + if (entity.metadata.vfsType === 'directory') { + // Add directory metadata + target._meta = { + type: 'directory', + path: currentPath, + modified: entity.metadata.modified ? new Date(entity.metadata.modified) : undefined + } + + // Traverse children + const children = await this.readdir(currentPath) + for (const child of children) { + const childPath = currentPath === '/' ? `/${child}` : `${currentPath}/${child}` + target[child] = {} + await traverse(childPath, target[child]) + } + } else if (entity.metadata.vfsType === 'file') { + // For files, include content and metadata + try { + const content = await this.readFile(currentPath) + const textContent = content.toString('utf8') + + // Try to parse JSON files + if (currentPath.endsWith('.json')) { + try { + target._content = JSON.parse(textContent) + } catch { + target._content = textContent + } + } else { + target._content = textContent + } + } catch { + // Binary or unreadable file + target._content = '[binary]' + } + + target._meta = { + type: 'file', + path: currentPath, + size: entity.metadata.size || 0, + mimeType: entity.metadata.mimeType, + modified: entity.metadata.modified ? new Date(entity.metadata.modified) : undefined, + todos: entity.metadata.todos || [] + } + } + } catch (error) { + // Skip inaccessible paths + target._error = 'inaccessible' + } + } + + await traverse(path, result) + return result + } + + /** + * Search for entities with filters + */ + async searchEntities(query: { + type?: string + name?: string + where?: Record + limit?: number + }): Promise> { + await this.ensureInitialized() + + // Build query for brain.find() + const searchQuery: any = { + where: { + ...query.where, + vfsType: 'entity' + }, + limit: query.limit || 100 + } + + if (query.type) { + searchQuery.where.entityType = query.type + } + + if (query.name) { + searchQuery.query = query.name + } + + const results = await this.brain.find(searchQuery) + + return results.map(result => ({ + id: result.id, + path: result.entity?.metadata?.path || '', + type: result.entity?.metadata?.type || result.entity?.metadata?.entityType || 'unknown', + metadata: result.entity?.metadata || {} + })) + } + + /** + * Bulk write operations for performance + */ + async bulkWrite(operations: Array<{ + type: 'write' | 'delete' | 'mkdir' | 'update' + path: string + data?: Buffer | string + options?: any + }>): Promise<{ + successful: number + failed: Array<{ operation: any, error: string }> + }> { + await this.ensureInitialized() + + const result = { + successful: 0, + failed: [] as Array<{ operation: any, error: string }> + } + + // Process operations in batches for better performance + const batchSize = 10 + for (let i = 0; i < operations.length; i += batchSize) { + const batch = operations.slice(i, i + batchSize) + + // Process batch in parallel + const promises = batch.map(async (op) => { + try { + switch (op.type) { + case 'write': + await this.writeFile(op.path, op.data || '', op.options) + break + case 'delete': + await this.unlink(op.path) + break + case 'mkdir': + await this.mkdir(op.path, op.options) + break + case 'update': + // Update only metadata without changing content + const entityId = await this.pathResolver.resolve(op.path) + await this.brain.update({ + id: entityId, + metadata: op.options?.metadata + }) + break + } + result.successful++ + } catch (error: any) { + result.failed.push({ + operation: op, + error: error.message || 'Unknown error' + }) + } + }) + + await Promise.all(promises) + } + + return result + } + /** * Get project statistics for a path */