docs: comprehensive API documentation and examples overhaul

- Add comprehensive JSDoc @example tags to all core methods (add, get, relate, find, similar, embed)
- Add @deprecated warnings with migration paths for all v2.x APIs
- Create VFS Quick Start Guide addressing brain-cloud integration issues
- Create VFS Common Patterns guide preventing infinite recursion mistakes
- Create Core API Patterns guide with modern v3.x usage examples
- Create Neural API Patterns guide for AI-powered features
- Create comprehensive API Decision Tree for choosing right methods
- Update README with prominent VFS examples and file explorer patterns
- Follow 2025 npm package documentation standards throughout

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
David Snelling 2025-09-26 13:32:44 -07:00
parent f80ed5e8aa
commit 3c72afd41a
8 changed files with 3530 additions and 34 deletions

480
docs/API_DECISION_TREE.md Normal file
View file

@ -0,0 +1,480 @@
# 🧠 Brainy API Decision Tree
*Choose the right API for your use case with confidence*
This guide helps you navigate Brainy's comprehensive API surface by asking the right questions to find the perfect method for your specific needs.
## 🎯 Quick Start: What do you want to do?
### 📝 **Adding Data**
- **Single entity** → [`brainy.add()`](#adding-single-entities)
- **Multiple entities** → [`brainy.addMany()`](#adding-multiple-entities)
- **Streaming/real-time data** → [Streaming Pipeline](#streaming-data)
### 🔍 **Finding Data**
- **Natural language search** → [`brainy.find("search query")`](#natural-language-search)
- **Structured/filtered search** → [`brainy.find({ query, where, type })`](#structured-search)
- **Similar entities** → [`brainy.similar()`](#similarity-search)
- **Get by ID** → [`brainy.get()`](#retrieval-by-id)
### 🔗 **Relationships**
- **Create relationships** → [`brainy.relate()`](#creating-relationships)
- **Query relationships** → [`brainy.getRelations()`](#querying-relationships)
- **Graph traversal** → [Graph Navigation](#graph-operations)
### 📊 **Advanced Features**
- **File management** → [VFS (Virtual File System)](#file-operations)
- **AI-powered analysis** → [Neural API](#neural-analysis)
- **Clustering/insights** → [Intelligence Systems](#intelligence-systems)
---
## 🔀 Decision Tree Flow
```mermaid
graph TD
A[What are you trying to do?] --> B[Store Data]
A --> C[Find Data]
A --> D[Manage Relationships]
A --> E[Work with Files]
A --> F[AI Analysis]
B --> B1[Single Item]
B --> B2[Multiple Items]
B --> B3[Real-time Stream]
C --> C1[I know the ID]
C --> C2[Natural language query]
C --> C3[Complex filters]
C --> C4[Find similar items]
D --> D1[Create relationship]
D --> D2[Query relationships]
D --> D3[Graph traversal]
E --> E1[File operations]
E --> E2[Knowledge-enhanced files]
F --> F1[Clustering]
F --> F2[Similarity analysis]
F --> F3[Insights generation]
```
---
## 📝 Adding Data
### Adding Single Entities
**Use `brainy.add()` when:**
- Adding one entity at a time
- You need the ID immediately for further operations
- Working with user input or real-time data
```typescript
// ✅ Perfect for single entities
const id = await brainy.add({
data: "New research paper on quantum computing",
type: NounType.Document,
metadata: { category: "research", priority: "high" }
})
```
**Decision factors:**
- **Single item?**`add()`
- **Need immediate ID?**`add()`
- **Interactive application?**`add()`
### Adding Multiple Entities
**Use `brainy.addMany()` when:**
- Bulk importing data
- Processing batches (>10 items)
- Performance is critical
```typescript
// ✅ Perfect for bulk operations
const result = await brainy.addMany({
items: documents.map(doc => ({
data: doc.content,
type: NounType.Document,
metadata: doc.metadata
})),
chunkSize: 100,
parallel: true
})
```
**Decision factors:**
- **Multiple items (>10)?**`addMany()`
- **Batch processing?**`addMany()`
- **Can tolerate some failures?**`addMany()` with `continueOnError: true`
### Streaming Data
**Use Streaming Pipeline when:**
- Real-time data ingestion
- Processing large datasets that don't fit in memory
- Need transformation during ingestion
```typescript
// ✅ Perfect for streaming
const pipeline = brainy.streaming.pipeline()
.transform(data => ({ ...data, processed: true }))
.batch(50)
.into(brainy)
```
---
## 🔍 Finding Data
### Natural Language Search
**Use `brainy.find("query string")` when:**
- User is typing search queries
- You want semantic understanding
- Building search interfaces
```typescript
// ✅ Perfect for user searches
const results = await brainy.find("documents about machine learning")
```
**Decision factors:**
- **User-generated query?** → Natural language `find()`
- **Semantic understanding needed?** → Natural language `find()`
- **Search interface?** → Natural language `find()`
### Structured Search
**Use `brainy.find({ query, where, type })` when:**
- Complex filtering requirements
- Combining text search with metadata filters
- Performance-critical searches
```typescript
// ✅ Perfect for complex queries
const results = await brainy.find({
query: "neural networks",
type: NounType.Document,
where: {
status: "published",
year: { $gte: 2020 }
},
limit: 20
})
```
**Decision factors:**
- **Need metadata filtering?** → Structured `find()`
- **Performance critical?** → Structured `find()`
- **Complex criteria?** → Structured `find()`
### Similarity Search
**Use `brainy.similar()` when:**
- Finding "more like this" content
- Recommendation systems
- Duplicate detection
```typescript
// ✅ Perfect for recommendations
const similar = await brainy.similar({
to: "document-id-123",
limit: 10,
type: NounType.Document
})
```
**Decision factors:**
- **"More like this" feature?** → `similar()`
- **Recommendations?**`similar()`
- **Duplicate detection?**`similar()`
### Retrieval by ID
**Use `brainy.get()` when:**
- You know the exact ID
- Loading specific entities
- Following relationships
```typescript
// ✅ Perfect for direct access
const entity = await brainy.get("known-id-123")
```
**Decision factors:**
- **Known ID?**`get()`
- **Direct access needed?**`get()`
- **Following relationships?**`get()`
---
## 🔗 Relationships
### Creating Relationships
**Use `brainy.relate()` when:**
- Connecting two entities
- Building knowledge graphs
- Modeling real-world relationships
```typescript
// ✅ Perfect for connections
await brainy.relate({
from: "user-123",
to: "project-456",
type: VerbType.WorksOn,
metadata: { role: "lead", since: "2024-01-01" }
})
```
**Decision factors:**
- **Connecting entities?**`relate()`
- **Need relationship metadata?**`relate()`
- **Building graphs?**`relate()`
### Querying Relationships
**Use `brainy.getRelations()` when:**
- Finding all connections for an entity
- Exploring relationship patterns
- Building relationship views
```typescript
// ✅ Perfect for relationship queries
const relations = await brainy.getRelations({
from: "user-123",
type: VerbType.WorksOn
})
```
---
## 📁 File Operations
### Basic File Operations
**Use VFS when:**
- Managing files and directories
- Need hierarchical structure
- Building file explorers
```typescript
// ✅ Perfect for file management
const vfs = brainy.vfs({ storage: 'filesystem' })
await vfs.writeFile('/docs/readme.md', 'content')
const files = await vfs.getDirectChildren('/docs')
```
**Decision factors:**
- **File management?** → VFS
- **Directory structure?** → VFS
- **File explorer interface?** → VFS
### Knowledge-Enhanced Files
**Use VFS with Knowledge Layer when:**
- Need semantic file search
- Want AI-powered file insights
- Building smart file systems
```typescript
// ✅ Perfect for intelligent file systems
const knowledgeVFS = await vfs.withKnowledge(brainy)
const insights = await knowledgeVFS.getFileInsights('/project')
```
---
## 🧠 AI Analysis
### Clustering
**Use Neural API clustering when:**
- Discovering data patterns
- Organizing large datasets
- Creating automatic categories
```typescript
// ✅ Perfect for pattern discovery
const neural = brainy.neural()
const clusters = await neural.cluster({
entities: entityIds,
k: 5,
method: 'hierarchical'
})
```
### Intelligence Systems
**Use Triple Intelligence when:**
- Complex multi-criteria searches
- Advanced relationship queries
- Performance-critical operations
```typescript
// ✅ Perfect for complex queries
const intelligence = brainy.getTripleIntelligence()
const results = await intelligence.query({
vector: queryVector,
metadata: { category: 'research' },
graph: { connected: 'user-123' }
})
```
---
## 🚀 Performance Optimization Guide
### When Performance Matters
| Scenario | Best Choice | Why |
|----------|-------------|-----|
| **Bulk Import** | `addMany()` | Batched operations, parallel processing |
| **Metadata-only Search** | `find({ where: {...} })` | Skips vector computation |
| **Known ID Access** | `get()` | Direct index lookup |
| **Large Result Sets** | Pagination with `offset`/`limit` | Memory efficient |
| **Real-time Streams** | Streaming Pipeline | Memory efficient, scalable |
### Memory Usage Optimization
```typescript
// ❌ Memory intensive
const allResults = await brainy.find({ limit: 10000 })
// ✅ Memory efficient
for (let offset = 0; offset < total; offset += 100) {
const batch = await brainy.find({
query: "...",
limit: 100,
offset
})
await processBatch(batch)
}
```
---
## 🎯 Common Use Case Patterns
### Building a Search Interface
```typescript
// User types query → Natural language search
const searchResults = await brainy.find(userQuery)
// User applies filters → Structured search
const filteredResults = await brainy.find({
query: userQuery,
where: selectedFilters,
type: selectedTypes
})
// User clicks "more like this" → Similarity search
const similar = await brainy.similar({ to: selectedId })
```
### Building a Recommendation System
```typescript
// 1. Get user's interaction history
const user = await brainy.get(userId)
// 2. Find similar users
const similarUsers = await brainy.similar({ to: userId, type: NounType.Person })
// 3. Get their liked content
const recommendations = []
for (const similarUser of similarUsers) {
const relations = await brainy.getRelations({
from: similarUser.id,
type: VerbType.Likes
})
recommendations.push(...relations)
}
```
### Building a Knowledge Graph
```typescript
// 1. Add entities
const entities = await Promise.all([
brainy.add({ data: "Person: Alice", type: NounType.Person }),
brainy.add({ data: "Company: TechCorp", type: NounType.Organization }),
brainy.add({ data: "Project: AI Assistant", type: NounType.Thing })
])
// 2. Create relationships
await brainy.relate({
from: entities[0], // Alice
to: entities[1], // TechCorp
type: VerbType.WorksFor
})
await brainy.relate({
from: entities[0], // Alice
to: entities[2], // AI Assistant
type: VerbType.WorksOn
})
// 3. Query the graph
const aliceConnections = await brainy.getRelations({ from: entities[0] })
```
---
## 🔧 Migration Guide
### From v2.x to v3.x APIs
| v2.x (Deprecated) | v3.x (Current) | When to Use |
|-------------------|----------------|-------------|
| `brain.store()` | `brainy.add()` | Adding entities |
| `brain.search()` | `brainy.find()` | Searching content |
| `brain.query()` | `brainy.find({ ... })` | Complex queries |
| `brain.similar()` | `brainy.similar()` | ✅ Same API |
| `brain.connect()` | `brainy.relate()` | Creating relationships |
### Legacy Type Migration
```typescript
// ❌ v2.x way
import { ISenseAugmentation } from '@soulcraft/brainy/types/augmentations'
// ✅ v3.x way
import { BrainyAugmentation } from '@soulcraft/brainy'
```
---
## 🎪 Decision Quick Reference
**Need to add data?**
- 1 item → `add()`
- Many items → `addMany()`
- Streaming → Pipeline
**Need to find data?**
- Know ID → `get()`
- Natural search → `find("query")`
- Complex filters → `find({ query, where })`
- Similar items → `similar()`
**Need relationships?**
- Create → `relate()`
- Query → `getRelations()`
- Complex graph → Triple Intelligence
**Need files?**
- Basic → VFS
- Smart → VFS + Knowledge Layer
**Need AI analysis?**
- Patterns → Neural clustering
- Complex queries → Triple Intelligence
---
*This guide covers 95% of use cases. For edge cases or custom requirements, check the [Core API Patterns](./CORE_API_PATTERNS.md) and [Neural API Patterns](./NEURAL_API_PATTERNS.md) guides.*

643
docs/CORE_API_PATTERNS.md Normal file
View file

@ -0,0 +1,643 @@
# 🧠 Core API Patterns: Modern Brainy v3.x
> Learn the correct patterns for Brainy's core operations. Avoid v2.x confusion and use modern, efficient APIs.
## 🚨 Critical: Use v3.x APIs Only
### ❌ **WRONG - Deprecated v2.x APIs**
```typescript
// DON'T DO THIS - These methods don't exist in v3.x!
await brain.addNoun(text, type, metadata) // ❌ Removed
await brain.getNouns({ pagination }) // ❌ Removed
await brain.addVerb(source, target, type) // ❌ Removed
await brain.getVerbs() // ❌ Removed
await brain.deleteNoun(id) // ❌ Removed
await brain.deleteVerb(id) // ❌ Removed
```
### ✅ **CORRECT - Modern v3.x APIs**
```typescript
// ✅ Use these modern methods instead
await brain.add({ data, type, metadata }) // Modern unified add
await brain.find({ limit: 100 }) // Natural language search
await brain.relate({ from, to, type }) // Clean relationship creation
await brain.getRelations() // Modern relationship queries
await brain.delete(id) // Unified deletion
// Relationships auto-cascade when entities are deleted
```
## 📋 Entity Management Patterns
### ❌ **WRONG - v2.x Style**
```typescript
// DON'T DO THIS - Old API patterns
import { BrainyData } from 'old-brainy' // ❌ Wrong import
const brain = new BrainyData({ // ❌ Old class name
complexConfig: true
})
const id = await brain.addNoun( // ❌ Deprecated method
"John Smith is a developer",
"Person",
{ role: "engineer" }
)
```
### ✅ **CORRECT - Modern Patterns**
```typescript
// ✅ Pattern 1: Basic entity creation
import { Brainy, NounType } from '@soulcraft/brainy'
const brain = new Brainy() // ✅ Zero config
await brain.init()
const id = await brain.add({
data: "John Smith is a developer",
type: NounType.Person,
metadata: { role: "engineer", team: "backend" }
})
// ✅ Pattern 2: Bulk entity creation
const entities = [
{ data: "React framework", type: NounType.Technology },
{ data: "Vue.js framework", type: NounType.Technology },
{ data: "Angular framework", type: NounType.Technology }
]
const ids = await Promise.all(
entities.map(entity => brain.add(entity))
)
// ✅ Pattern 3: Entity with pre-computed vector
const customVector = await brain.embed("Custom text")
const vectorId = await brain.add({
data: "Optimized content",
type: NounType.Document,
vector: customVector, // Skip re-embedding
metadata: { source: "api", optimized: true }
})
```
## 🔍 Search & Discovery Patterns
### ❌ **WRONG - Confusing Old Patterns**
```typescript
// DON'T DO THIS - Mixing old and new APIs
const results1 = await brain.searchText("query") // ❌ Old method
const results2 = await brain.getNouns({ filter }) // ❌ Doesn't exist
const results3 = await brain.findSimilar(text) // ❌ Unclear naming
```
### ✅ **CORRECT - Clean Search Patterns**
```typescript
// ✅ Pattern 1: Natural language search
const results = await brain.find("React developers working on authentication")
// ✅ Pattern 2: Structured search with filters
const filteredResults = await brain.find({
like: "machine learning", // Vector similarity
where: { // Metadata filtering
type: NounType.Document,
year: { $gte: 2020 },
status: "published"
},
limit: 50,
orderBy: 'relevance'
})
// ✅ Pattern 3: Similarity search
const similarItems = await brain.similar({
to: existingEntityId, // Find items similar to this
threshold: 0.8, // Minimum similarity
limit: 10,
exclude: [existingEntityId] // Don't include the source
})
// ✅ Pattern 4: Advanced search with relationships
const connectedResults = await brain.find({
like: "frontend frameworks",
connected: {
to: reactId, // Connected to React
via: "related-to", // Through this relationship
depth: 2 // Up to 2 hops away
}
})
```
## 🔗 Relationship Patterns
### ❌ **WRONG - Old Relationship APIs**
```typescript
// DON'T DO THIS - Old relationship patterns
await brain.addVerb(sourceId, targetId, "uses", { strength: 0.9 }) // ❌ Old API
const verbs = await brain.getVerbsBySource(sourceId) // ❌ Removed
await brain.deleteVerb(verbId) // ❌ Old pattern
```
### ✅ **CORRECT - Modern Relationship Management**
```typescript
// ✅ Pattern 1: Create relationships
const relationId = await brain.relate({
from: developerId,
to: frameworkId,
type: VerbType.Uses,
metadata: {
since: "2023-01-01",
proficiency: "expert",
hours_per_week: 40
}
})
// ✅ Pattern 2: Query relationships
const relationships = await brain.getRelations({
from: developerId, // Relationships from this entity
type: VerbType.Uses, // Of this type
limit: 100
})
// ✅ Pattern 3: Bidirectional relationships
await brain.relate({
from: projectId,
to: developerId,
type: VerbType.AssignedTo,
bidirectional: true, // Creates reverse relationship
metadata: { role: "lead", start_date: "2024-01-01" }
})
// ✅ Pattern 4: Relationship-based discovery
const collaborators = await brain.find({
connected: {
to: currentProjectId,
via: VerbType.WorksOn,
direction: "incoming" // Who works on this project
}
})
```
## 🗃️ Data Retrieval Patterns
### ❌ **WRONG - Inefficient Patterns**
```typescript
// DON'T DO THIS - Loading everything
const everything = await brain.getNouns({ limit: 1000000 }) // ❌ Crashes
const allData = await brain.exportAll() // ❌ Memory explosion
```
### ✅ **CORRECT - Efficient Data Access**
```typescript
// ✅ Pattern 1: Paginated retrieval
async function getAllEntitiesPaginated() {
const pageSize = 100
let offset = 0
let allEntities = []
while (true) {
const page = await brain.find({
limit: pageSize,
offset: offset
})
if (page.length === 0) break
allEntities.push(...page)
offset += pageSize
// Optional: Progress reporting
console.log(`Loaded ${allEntities.length} entities...`)
}
return allEntities
}
// ✅ Pattern 2: Streaming large datasets
async function* streamEntities() {
const pageSize = 50
let offset = 0
while (true) {
const page = await brain.find({
limit: pageSize,
offset: offset
})
if (page.length === 0) break
for (const entity of page) {
yield entity
}
offset += pageSize
}
}
// Usage
for await (const entity of streamEntities()) {
await processEntity(entity)
}
// ✅ Pattern 3: Specific entity retrieval
const entity = await brain.get(entityId)
if (entity) {
console.log('Entity data:', entity.data)
console.log('Metadata:', entity.metadata)
} else {
console.log('Entity not found')
}
```
## 🔄 Update & Delete Patterns
### ❌ **WRONG - Manual Update Patterns**
```typescript
// DON'T DO THIS - Recreating entities
await brain.delete(oldId)
const newId = await brain.add(updatedData) // ❌ Loses relationships
```
### ✅ **CORRECT - Update Operations**
```typescript
// ✅ Pattern 1: Update entity data
await brain.update(entityId, {
data: "Updated content here",
metadata: {
lastModified: Date.now(),
version: "2.0"
}
})
// ✅ Pattern 2: Partial metadata updates
await brain.updateMetadata(entityId, {
status: "published",
tags: ["important", "featured"]
// Merges with existing metadata
})
// ✅ Pattern 3: Safe deletion with cascade options
await brain.delete(entityId, {
cascade: true, // Delete related relationships
backup: true // Create backup before deletion
})
// ✅ Pattern 4: Bulk operations
const updateOperations = entities.map(entity => ({
id: entity.id,
changes: { status: "processed" }
}))
await brain.updateMany(updateOperations)
```
## 🧮 Vector & Embedding Patterns
### ❌ **WRONG - Manual Vector Handling**
```typescript
// DON'T DO THIS - Manual embedding without understanding
const vector = await brain.embed(text)
// Store vector somewhere manually // ❌ Missing integration
```
### ✅ **CORRECT - Smart Vector Operations**
```typescript
// ✅ Pattern 1: Automatic embedding (recommended)
const id = await brain.add({
data: "Content to be embedded",
type: NounType.Document
// Vector computed automatically
})
// ✅ Pattern 2: Pre-computed vectors for optimization
const texts = ["Text 1", "Text 2", "Text 3"]
const vectors = await Promise.all(
texts.map(text => brain.embed(text))
)
const entities = await Promise.all(
texts.map((text, i) => brain.add({
data: text,
type: NounType.Document,
vector: vectors[i] // Skip re-embedding
}))
)
// ✅ Pattern 3: Vector similarity search
const queryVector = await brain.embed("search query")
const similar = await brain.similar({
vector: queryVector, // Use vector directly
threshold: 0.75,
limit: 20
})
// ✅ Pattern 4: Compare vectors directly
const vector1 = await brain.embed("First text")
const vector2 = await brain.embed("Second text")
const similarity = brain.computeSimilarity(vector1, vector2)
console.log(`Similarity: ${similarity}`)
```
## 🏗️ Configuration Patterns
### ❌ **WRONG - Over-Configuration**
```typescript
// DON'T DO THIS - Complex configurations that break
const brain = new Brainy({
storage: {
type: 'complex',
options: {
nested: {
configuration: true,
that: "breaks"
}
}
},
embedding: {
customModel: "broken-model",
dimensions: 999999
}
})
```
### ✅ **CORRECT - Smart Configuration**
```typescript
// ✅ Pattern 1: Zero configuration (recommended)
const brain = new Brainy() // Auto-detects everything
await brain.init()
// ✅ Pattern 2: Simple storage selection
const fsBrain = new Brainy({
storage: { type: 'filesystem', path: './data' }
})
const cloudBrain = new Brainy({
storage: { type: 's3', bucket: 'my-data' }
})
// ✅ Pattern 3: Production configuration
const prodBrain = new Brainy({
storage: {
type: 's3',
bucket: process.env.BRAINY_BUCKET,
region: process.env.AWS_REGION
},
silent: true, // No console output
distributed: true, // Enable clustering
cache: { maxSize: 10000 } // Larger cache
})
// ✅ Pattern 4: Development vs production
const isDev = process.env.NODE_ENV === 'development'
const brain = new Brainy({
storage: isDev
? { type: 'memory' } // Fast for dev
: { type: 'filesystem', path: './brainy-data' }, // Persistent for prod
silent: !isDev, // Verbose in dev, quiet in prod
cache: { maxSize: isDev ? 100 : 5000 }
})
```
## 🔄 Migration from v2.x
### ✅ **Migration Patterns**
```typescript
// If you have old v2.x code, here's how to migrate:
// OLD v2.x:
// await brain.addNoun(text, type, metadata)
// NEW v3.x:
await brain.add({ data: text, type, metadata })
// OLD v2.x:
// await brain.getNouns({ pagination: { limit: 100 } })
// NEW v3.x:
await brain.find({ limit: 100 })
// OLD v2.x:
// await brain.addVerb(sourceId, targetId, verbType, metadata)
// NEW v3.x:
await brain.relate({ from: sourceId, to: targetId, type: verbType, metadata })
// OLD v2.x:
// await brain.searchText(query)
// NEW v3.x:
await brain.find(query) // More powerful natural language search
```
## 🚀 Performance Patterns
### ✅ **High-Performance Patterns**
```typescript
// ✅ Pattern 1: Batch operations
const entities = [/* large array */]
const batchSize = 100
for (let i = 0; i < entities.length; i += batchSize) {
const batch = entities.slice(i, i + batchSize)
await Promise.all(
batch.map(entity => brain.add(entity))
)
// Optional: Rate limiting
await new Promise(resolve => setTimeout(resolve, 100))
}
// ✅ Pattern 2: Connection pooling for distributed
const brain = new Brainy({
distributed: true,
connectionPool: {
min: 5,
max: 50,
acquireTimeoutMillis: 30000
}
})
// ✅ Pattern 3: Efficient caching
const brain = new Brainy({
cache: {
maxSize: 10000, // Number of items
ttl: 300000, // 5 minutes
updateAgeOnGet: true // LRU behavior
}
})
// ✅ Pattern 4: Memory-conscious operations
const results = await brain.find({
query: "large dataset query",
limit: 1000, // Reasonable limit
includeVectors: false // Exclude vectors if not needed
})
```
## 🛡️ Error Handling Patterns
### ✅ **Robust Error Handling**
```typescript
// ✅ Pattern 1: Specific error handling
try {
const result = await brain.add({ data, type, metadata })
return result
} catch (error) {
if (error.code === 'DUPLICATE_ENTITY') {
console.log('Entity already exists, updating instead...')
return await brain.update(error.existingId, { data, metadata })
} else if (error.code === 'STORAGE_FULL') {
throw new Error('Storage capacity exceeded')
} else if (error.code === 'EMBEDDING_FAILED') {
console.warn('Embedding failed, retrying with simpler text...')
return await brain.add({
data: data.substring(0, 1000), // Truncate
type,
metadata
})
}
throw error
}
// ✅ Pattern 2: Retry with exponential backoff
async function resilientAdd(data: any, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await brain.add(data)
} catch (error) {
if (attempt === maxRetries) throw error
const delay = Math.pow(2, attempt) * 1000
console.warn(`Attempt ${attempt} failed, retrying in ${delay}ms...`)
await new Promise(resolve => setTimeout(resolve, delay))
}
}
}
// ✅ Pattern 3: Graceful degradation
async function robustSearch(query: string) {
try {
// Try advanced semantic search first
return await brain.find({
like: query,
threshold: 0.8,
limit: 50
})
} catch (error) {
console.warn('Semantic search failed, falling back to basic search:', error.message)
try {
// Fallback to simple text search
return await brain.find(query)
} catch (fallbackError) {
console.error('All search methods failed:', fallbackError.message)
return [] // Return empty results rather than crash
}
}
}
```
## 📊 Monitoring Patterns
### ✅ **Production Monitoring**
```typescript
// ✅ Pattern 1: Performance monitoring
const startTime = Date.now()
const result = await brain.add(data)
const duration = Date.now() - startTime
if (duration > 1000) {
console.warn(`Slow add operation: ${duration}ms`)
}
// ✅ Pattern 2: Health checks
async function healthCheck() {
try {
// Test basic operations
const testId = await brain.add({
data: "health check",
type: NounType.System,
metadata: { test: true }
})
await brain.get(testId)
await brain.delete(testId)
return { status: 'healthy', timestamp: Date.now() }
} catch (error) {
return {
status: 'unhealthy',
error: error.message,
timestamp: Date.now()
}
}
}
// ✅ Pattern 3: Metrics collection
class BrainyMetrics {
private metrics = {
operations: 0,
errors: 0,
totalTime: 0
}
async timedOperation<T>(operation: () => Promise<T>): Promise<T> {
const start = Date.now()
try {
const result = await operation()
this.metrics.operations++
this.metrics.totalTime += Date.now() - start
return result
} catch (error) {
this.metrics.errors++
throw error
}
}
getStats() {
return {
...this.metrics,
avgTime: this.metrics.totalTime / this.metrics.operations || 0,
errorRate: this.metrics.errors / this.metrics.operations || 0
}
}
}
```
## 🎯 Summary: Modern Brainy v3.x Best Practices
| ❌ **Avoid v2.x** | ✅ **Use v3.x** |
|------------------|----------------|
| `addNoun()` | `add()` |
| `getNouns()` | `find()` |
| `addVerb()` | `relate()` |
| `getVerbs()` | `getRelations()` |
| `deleteNoun()` | `delete()` |
| Complex configs | Zero-config with `new Brainy()` |
| Manual pagination | Built-in smart pagination |
| String-based search | Natural language queries |
---
**🎉 Following these patterns gives you:**
- 🚀 **Modern APIs** that are actively maintained
- ⚡ **Better performance** with intelligent defaults
- 🛡️ **Robust error handling** with specific error types
- 📈 **Scalable patterns** for production applications
- 🧠 **Natural language** search capabilities
**Next:** [Neural API Patterns →](./NEURAL_API_PATTERNS.md) | [VFS Patterns →](./vfs/COMMON_PATTERNS.md)

736
docs/NEURAL_API_PATTERNS.md Normal file
View file

@ -0,0 +1,736 @@
# 🧠 Neural API Patterns: AI-Powered Intelligence
> Learn the correct patterns for Brainy's Neural API. Avoid performance pitfalls and use AI features effectively.
## 🚨 Critical: Access Neural APIs Correctly
### ❌ **WRONG - Outdated Access Patterns**
```typescript
// DON'T DO THIS - Outdated documentation patterns
import { BrainyData } from '@soulcraft/brainy' // ❌ Wrong import
const brain = new BrainyData() // ❌ Old class name
// These may not work as expected:
const neural = brain.neural // ❌ May be undefined
```
### ✅ **CORRECT - Modern Neural Access**
```typescript
// ✅ Use modern Brainy class
import { Brainy } from '@soulcraft/brainy'
const brain = new Brainy()
await brain.init()
// ✅ Neural API is available after initialization
const clusters = await brain.neural.clusters()
const similarity = await brain.neural.similar('item1', 'item2')
```
## 🔍 Similarity Analysis Patterns
### ❌ **WRONG - Inefficient Similarity Checks**
```typescript
// DON'T DO THIS - N² comparisons
const items = await brain.find({ limit: 1000 })
const similarities = []
for (const item1 of items) {
for (const item2 of items) {
if (item1.id !== item2.id) {
const sim = await brain.neural.similar(item1.id, item2.id) // ❌ Millions of calls
similarities.push({ from: item1.id, to: item2.id, score: sim })
}
}
}
```
### ✅ **CORRECT - Efficient Similarity Patterns**
```typescript
// ✅ Pattern 1: Find neighbors (much more efficient)
const item = await brain.get('target-item-id')
const neighbors = await brain.neural.neighbors(item.id, {
limit: 10, // Top 10 most similar
threshold: 0.7, // Minimum similarity
includeScores: true // Include similarity scores
})
console.log(`Found ${neighbors.length} similar items`)
// ✅ Pattern 2: Batch similarity for specific pairs
const itemPairs = [
['item1', 'item2'],
['item1', 'item3'],
['item2', 'item3']
]
const similarities = await Promise.all(
itemPairs.map(async ([a, b]) => ({
from: a,
to: b,
score: await brain.neural.similar(a, b)
}))
)
// ✅ Pattern 3: Text-to-text similarity (no need for IDs)
const textSimilarity = await brain.neural.similar(
"Machine learning is fascinating",
"AI and deep learning are interesting",
{ detailed: true } // Get explanation of similarity
)
console.log(`Similarity: ${textSimilarity.score}`)
console.log(`Explanation: ${textSimilarity.explanation}`)
// ✅ Pattern 4: Vector-level similarity for optimization
const vector1 = await brain.embed("First concept")
const vector2 = await brain.embed("Second concept")
const vectorSimilarity = await brain.neural.similar(vector1, vector2)
```
## 🎯 Clustering Patterns
### ❌ **WRONG - Uncontrolled Clustering**
```typescript
// DON'T DO THIS - Clustering everything without limits
const everything = await brain.find({ limit: 100000 }) // ❌ Too much data
const clusters = await brain.neural.clusters() // ❌ May crash or timeout
```
### ✅ **CORRECT - Smart Clustering Patterns**
```typescript
// ✅ Pattern 1: Controlled clustering with limits
const recentItems = await brain.find({
where: {
createdAt: { $gte: Date.now() - 30 * 24 * 60 * 60 * 1000 } // Last 30 days
},
limit: 1000 // Reasonable limit
})
const clusters = await brain.neural.clusters(
recentItems.map(item => item.id),
{
algorithm: 'kmeans', // Reliable algorithm
maxClusters: 10, // Reasonable number
threshold: 0.75, // High similarity required
iterations: 50 // Convergence limit
}
)
// ✅ Pattern 2: Domain-specific clustering
const techDocs = await brain.find({
where: { category: 'technology', type: 'document' },
limit: 500
})
const techClusters = await brain.neural.clusterByDomain(
'category', // Group by this field
{
items: techDocs.map(doc => doc.id),
minClusterSize: 3, // Minimum items per cluster
maxClusters: 8
}
)
// ✅ Pattern 3: Temporal clustering for time-series data
const timebasedClusters = await brain.neural.clusterByTime(
'createdAt', // Time field
'week', // Time window (hour, day, week, month)
{
items: recentItems.map(item => item.id),
overlap: 0.2, // 20% overlap between windows
minPerWindow: 5 // Minimum items per time window
}
)
// ✅ Pattern 4: Streaming clustering for large datasets
async function clusterLargeDataset() {
const clusterStream = brain.neural.clusterStream({
batchSize: 100, // Process 100 items at a time
updateInterval: 1000, // Update clusters every 1000 items
maxMemory: 512 * 1024 * 1024 // 512MB memory limit
})
const allClusters = []
for await (const batch of clusterStream) {
console.log(`Processed ${batch.processed} items, found ${batch.clusters.length} clusters`)
allClusters.push(...batch.clusters)
}
return allClusters
}
```
## 🔍 Neighbor Discovery Patterns
### ❌ **WRONG - Manual Similarity Searches**
```typescript
// DON'T DO THIS - Reinventing neighbor search
async function findSimilarManually(targetId: string) {
const allItems = await brain.find({ limit: 10000 }) // ❌ Load everything
const similarities = []
for (const item of allItems) {
if (item.id !== targetId) {
const score = await brain.neural.similar(targetId, item.id) // ❌ Slow
if (score > 0.7) {
similarities.push({ id: item.id, score })
}
}
}
return similarities.sort((a, b) => b.score - a.score).slice(0, 10) // ❌ Inefficient
}
```
### ✅ **CORRECT - Optimized Neighbor Patterns**
```typescript
// ✅ Pattern 1: Basic neighbor search
const neighbors = await brain.neural.neighbors('target-item-id', {
limit: 20, // Top 20 neighbors
threshold: 0.6, // Minimum similarity
includeMetadata: true, // Include item metadata
includeDistances: true // Include exact similarity scores
})
// ✅ Pattern 2: Filtered neighbor search
const filteredNeighbors = await brain.neural.neighbors('article-id', {
limit: 10,
filter: {
type: 'document', // Only find similar documents
status: 'published', // Only published content
language: 'en' // Only English content
},
excludeIds: ['self-id', 'duplicate-id'] // Exclude specific items
})
// ✅ Pattern 3: Multi-level neighbor discovery
async function discoverNeighborNetwork(rootId: string, maxDepth = 2) {
const network = new Map()
const visited = new Set()
const queue = [{ id: rootId, depth: 0 }]
while (queue.length > 0) {
const { id, depth } = queue.shift()!
if (visited.has(id) || depth >= maxDepth) continue
visited.add(id)
const neighbors = await brain.neural.neighbors(id, {
limit: 5,
threshold: 0.8
})
network.set(id, neighbors)
// Add neighbors to queue for next depth level
if (depth < maxDepth - 1) {
neighbors.forEach(neighbor => {
queue.push({ id: neighbor.id, depth: depth + 1 })
})
}
}
return network
}
// ✅ Pattern 4: Recommendation engine
async function getRecommendations(userId: string) {
// Get user's liked items
const userItems = await brain.find({
connected: { to: userId, via: 'liked-by' }
})
// Find neighbors for each liked item
const allNeighbors = await Promise.all(
userItems.map(item =>
brain.neural.neighbors(item.id, {
limit: 10,
threshold: 0.7,
excludeConnected: { to: userId, via: 'liked-by' } // Exclude already liked
})
)
)
// Aggregate and rank recommendations
const recommendations = new Map()
allNeighbors.flat().forEach(neighbor => {
const current = recommendations.get(neighbor.id) || { score: 0, count: 0 }
current.score += neighbor.score
current.count += 1
recommendations.set(neighbor.id, current)
})
// Return top recommendations by average score
return Array.from(recommendations.entries())
.map(([id, stats]) => ({
id,
avgScore: stats.score / stats.count,
mentions: stats.count
}))
.sort((a, b) => b.avgScore - a.avgScore)
.slice(0, 10)
}
```
## 🏗️ Hierarchy & Structure Patterns
### ❌ **WRONG - Manual Hierarchy Building**
```typescript
// DON'T DO THIS - Building hierarchies manually
async function buildHierarchyManually(rootId: string) {
const root = await brain.get(rootId)
const allItems = await brain.find({ limit: 1000 }) // ❌ Load everything
// Manual tree building with nested loops
const hierarchy = { root, children: [] }
// ... complex manual logic
}
```
### ✅ **CORRECT - Semantic Hierarchy Patterns**
```typescript
// ✅ Pattern 1: Automatic semantic hierarchy
const hierarchy = await brain.neural.hierarchy('root-concept-id', {
maxDepth: 4, // Maximum tree depth
minSimilarity: 0.6, // Minimum similarity for inclusion
branchingFactor: 5, // Maximum children per node
algorithm: 'semantic' // Use semantic clustering
})
// ✅ Pattern 2: Domain-specific hierarchy
const techHierarchy = await brain.neural.hierarchy('technology-id', {
filter: { category: 'technology' },
weights: {
semantic: 0.7, // 70% based on content similarity
metadata: 0.3 // 30% based on metadata similarity
},
includeMetrics: true // Include hierarchy quality metrics
})
// ✅ Pattern 3: Multi-root hierarchy for complex domains
async function buildMultiRootHierarchy(rootIds: string[]) {
const hierarchies = await Promise.all(
rootIds.map(rootId =>
brain.neural.hierarchy(rootId, {
maxDepth: 3,
crossReference: true // Allow cross-hierarchy connections
})
)
)
// Merge hierarchies and find connections
const merged = {
roots: hierarchies,
connections: await findCrossHierarchyConnections(hierarchies)
}
return merged
}
async function findCrossHierarchyConnections(hierarchies: any[]) {
const connections = []
for (let i = 0; i < hierarchies.length; i++) {
for (let j = i + 1; j < hierarchies.length; j++) {
const leafNodes1 = extractLeafNodes(hierarchies[i])
const leafNodes2 = extractLeafNodes(hierarchies[j])
// Find connections between leaf nodes of different hierarchies
for (const leaf1 of leafNodes1) {
const neighbors = await brain.neural.neighbors(leaf1.id, {
limit: 5,
threshold: 0.8,
filter: { id: { $in: leafNodes2.map(l => l.id) } }
})
connections.push(...neighbors.map(n => ({
from: leaf1.id,
to: n.id,
hierarchyPair: [i, j],
similarity: n.score
})))
}
}
}
return connections
}
```
## 🚨 Outlier Detection Patterns
### ❌ **WRONG - Manual Outlier Detection**
```typescript
// DON'T DO THIS - Manual statistical outlier detection
async function findOutliersManually() {
const items = await brain.find({ limit: 1000 })
const similarities = []
// Calculate average similarity for each item (expensive)
for (const item of items) {
let totalSim = 0
let count = 0
for (const other of items) {
if (item.id !== other.id) {
totalSim += await brain.neural.similar(item.id, other.id) // ❌ N² operations
count++
}
}
similarities.push({ id: item.id, avgSimilarity: totalSim / count })
}
// Manual outlier calculation
const threshold = calculateManualThreshold(similarities) // ❌ Complex statistics
return similarities.filter(s => s.avgSimilarity < threshold)
}
```
### ✅ **CORRECT - AI-Powered Outlier Detection**
```typescript
// ✅ Pattern 1: Automatic outlier detection
const outliers = await brain.neural.outliers({
threshold: 0.3, // Items with < 30% avg similarity to others
method: 'isolation-forest', // AI-based outlier detection
contamination: 0.1, // Expect ~10% outliers
includeReasons: true // Explain why each item is an outlier
})
console.log(`Found ${outliers.length} outliers`)
outliers.forEach(outlier => {
console.log(`Outlier: ${outlier.id}, Score: ${outlier.score}`)
console.log(`Reason: ${outlier.reason}`)
})
// ✅ Pattern 2: Domain-specific outlier detection
const techOutliers = await brain.neural.outliers({
filter: { category: 'technology' },
features: ['content', 'metadata.tags', 'metadata.complexity'],
method: 'local-outlier-factor',
neighbors: 20 // Consider 20 nearest neighbors
})
// ✅ Pattern 3: Temporal outlier detection
const recentOutliers = await brain.neural.outliers({
timeWindow: '7days', // Look at last 7 days
baseline: '30days', // Compare to 30-day baseline
method: 'statistical', // Use statistical methods
autoThreshold: true // Automatically determine threshold
})
// ✅ Pattern 4: Streaming outlier detection
async function detectOutliersInStream() {
const outlierStream = brain.neural.outlierStream({
batchSize: 50,
updateInterval: 100, // Check every 100 new items
adaptiveThreshold: true // Threshold adapts as data changes
})
for await (const batch of outlierStream) {
console.log(`Batch ${batch.batchNumber}: ${batch.outliers.length} outliers detected`)
// Process outliers immediately
for (const outlier of batch.outliers) {
await handleOutlier(outlier)
}
}
}
async function handleOutlier(outlier: any) {
// Flag for manual review
await brain.update(outlier.id, {
metadata: {
flagged: true,
outlierScore: outlier.score,
outlierReason: outlier.reason,
flaggedAt: Date.now()
}
})
}
```
## 📊 Visualization Patterns
### ❌ **WRONG - Manual Visualization Data Preparation**
```typescript
// DON'T DO THIS - Manual coordinate calculation
async function prepareVisualizationManually() {
const items = await brain.find({ limit: 500 })
const coordinates = []
// Manual dimensionality reduction (complex math)
for (const item of items) {
const vector = await brain.embed(item.data)
// Complex PCA/t-SNE calculations manually
const x = complexMathFunction(vector) // ❌ Error-prone
const y = anotherComplexFunction(vector)
coordinates.push({ id: item.id, x, y })
}
return coordinates
}
```
### ✅ **CORRECT - AI-Powered Visualization**
```typescript
// ✅ Pattern 1: Automatic 2D visualization
const visualization = await brain.neural.visualize({
dimensions: 2, // 2D plot
algorithm: 'umap', // UMAP for better clustering preservation
maxItems: 1000, // Performance limit
includeMetadata: true, // Include item metadata in output
colorBy: 'cluster' // Color points by cluster membership
})
// Result format:
// {
// points: [{ id, x, y, cluster, metadata }, ...],
// clusters: [{ id, centroid: [x, y], members: [...] }, ...],
// stats: { stress, kruskalStress, trustworthiness }
// }
// ✅ Pattern 2: 3D visualization for complex data
const viz3D = await brain.neural.visualize({
dimensions: 3,
algorithm: 'tsne',
perplexity: 30, // t-SNE parameter
learningRate: 200, // t-SNE learning rate
iterations: 1000 // Number of optimization steps
})
// ✅ Pattern 3: Interactive visualization with filtering
const interactiveViz = await brain.neural.visualize({
filter: {
type: 'document',
createdAt: { $gte: Date.now() - 7 * 24 * 60 * 60 * 1000 }
},
groupBy: 'category', // Group points by metadata field
showLabels: true, // Include text labels
labelField: 'title', // Field to use for labels
includeEdges: true, // Show connections between similar items
edgeThreshold: 0.8 // Only show high-similarity connections
})
// ✅ Pattern 4: Real-time visualization updates
class LiveVisualization {
private visualization: any = null
private updateInterval: NodeJS.Timeout | null = null
async start() {
// Initial visualization
this.visualization = await brain.neural.visualize({
dimensions: 2,
algorithm: 'umap',
maxItems: 500,
includeMetadata: true
})
// Update every 30 seconds
this.updateInterval = setInterval(async () => {
await this.update()
}, 30000)
}
async update() {
// Get recent items
const recentItems = await brain.find({
where: {
createdAt: { $gte: Date.now() - 30000 } // Last 30 seconds
},
limit: 50
})
if (recentItems.length > 0) {
// Incrementally update visualization
const updates = await brain.neural.updateVisualization(
this.visualization.id,
{
newItems: recentItems.map(item => item.id),
algorithm: 'incremental' // Faster incremental updates
}
)
this.visualization = { ...this.visualization, ...updates }
this.onUpdate(updates)
}
}
onUpdate(updates: any) {
// Emit updates to frontend
console.log(`Visualization updated: ${updates.newPoints.length} new points`)
}
stop() {
if (this.updateInterval) {
clearInterval(this.updateInterval)
}
}
}
```
## 🚀 Performance Optimization Patterns
### ✅ **High-Performance Neural Operations**
```typescript
// ✅ Pattern 1: Batch processing for similarity
async function batchSimilarityCalculation(itemPairs: Array<[string, string]>) {
const batchSize = 100
const results = []
for (let i = 0; i < itemPairs.length; i += batchSize) {
const batch = itemPairs.slice(i, i + batchSize)
const batchResults = await Promise.all(
batch.map(async ([a, b]) => ({
from: a,
to: b,
similarity: await brain.neural.similar(a, b)
}))
)
results.push(...batchResults)
// Progress reporting
console.log(`Processed ${Math.min(i + batchSize, itemPairs.length)}/${itemPairs.length} pairs`)
}
return results
}
// ✅ Pattern 2: Caching expensive operations
class NeuralCache {
private clusterCache = new Map()
private similarityCache = new Map()
private readonly TTL = 5 * 60 * 1000 // 5 minutes
async getClusters(options: any) {
const key = JSON.stringify(options)
const cached = this.clusterCache.get(key)
if (cached && Date.now() - cached.timestamp < this.TTL) {
return cached.data
}
const clusters = await brain.neural.clusters(undefined, options)
this.clusterCache.set(key, {
data: clusters,
timestamp: Date.now()
})
return clusters
}
async getSimilarity(id1: string, id2: string) {
// Create consistent cache key regardless of order
const key = [id1, id2].sort().join('-')
const cached = this.similarityCache.get(key)
if (cached && Date.now() - cached.timestamp < this.TTL) {
return cached.data
}
const similarity = await brain.neural.similar(id1, id2)
this.similarityCache.set(key, {
data: similarity,
timestamp: Date.now()
})
return similarity
}
}
// ✅ Pattern 3: Memory-efficient streaming
async function processLargeDatasetEfficiently() {
const stream = brain.neural.clusterStream({
batchSize: 50, // Small batches for memory efficiency
maxMemoryMB: 256, // Memory limit
diskCache: true, // Use disk for temporary storage
compression: true // Compress cached data
})
const results = []
let totalProcessed = 0
for await (const batch of stream) {
// Process batch immediately, don't accumulate in memory
const processedBatch = await processBatch(batch)
// Save to disk or send to another service
await saveBatchToDisk(processedBatch)
totalProcessed += batch.items.length
console.log(`Processed ${totalProcessed} items`)
// Clear memory
batch.items = null
}
return { totalProcessed }
}
// ✅ Pattern 4: Parallel processing with worker threads
async function parallelNeuralProcessing(items: string[]) {
const numWorkers = require('os').cpus().length
const batchSize = Math.ceil(items.length / numWorkers)
const workers = []
for (let i = 0; i < numWorkers; i++) {
const batch = items.slice(i * batchSize, (i + 1) * batchSize)
if (batch.length > 0) {
workers.push(processWorkerBatch(batch))
}
}
const results = await Promise.all(workers)
return results.flat()
}
async function processWorkerBatch(batch: string[]) {
// This would run in a worker thread in real implementation
return Promise.all(
batch.map(async itemId => {
const neighbors = await brain.neural.neighbors(itemId, { limit: 5 })
return { itemId, neighbors }
})
)
}
```
## 🎯 Summary: Neural API Best Practices
| ❌ **Avoid These Patterns** | ✅ **Use These Instead** |
|---------------------------|------------------------|
| Manual similarity loops | `brain.neural.neighbors()` |
| Uncontrolled clustering | Limit items and set maxClusters |
| Manual outlier detection | `brain.neural.outliers()` |
| Manual visualization prep | `brain.neural.visualize()` |
| Loading entire datasets | Streaming and batch processing |
| No caching | Cache expensive operations |
| Blocking operations | Parallel and async patterns |
---
**🎉 Following these patterns gives you:**
- 🚀 **Optimized performance** with intelligent algorithms
- 🧠 **AI-powered insights** instead of manual statistics
- 📊 **Rich visualizations** for data exploration
- 🎯 **Accurate clustering** with semantic understanding
- 🚨 **Smart outlier detection** for quality control
- ⚡ **Scalable processing** for large datasets
**Next:** [Augmentation Patterns →](./AUGMENTATION_PATTERNS.md) | [Core API Patterns →](./CORE_API_PATTERNS.md)

582
docs/vfs/COMMON_PATTERNS.md Normal file
View file

@ -0,0 +1,582 @@
# 🎯 VFS Common Patterns: Do This, Not That
> Learn the correct patterns for using Brainy VFS. Avoid the mistakes that cause crashes, poor performance, and API confusion.
## 🚨 Critical Pattern: Safe Tree Operations
### ❌ **WRONG - Causes Infinite Recursion**
```typescript
// DON'T DO THIS - Directory appears as its own child!
function buildFileTree(allItems, parentPath) {
return allItems.filter(item => {
// This includes the parent directory itself!
return item.path.startsWith(parentPath)
})
}
// Result: /dir -> /dir -> /dir -> ∞ (crashes browser/server)
```
### ✅ **CORRECT - Tree-Aware Methods**
```typescript
// ✅ Pattern 1: Direct children for UI trees
async function loadDirectoryUI(path: string) {
const children = await vfs.getDirectChildren(path)
// Guaranteed: No self-inclusion, no recursion
return children.map(child => ({
name: child.metadata.name,
path: child.metadata.path,
type: child.metadata.vfsType,
hasChildren: child.metadata.vfsType === 'directory'
}))
}
// ✅ Pattern 2: Complete tree structure
async function buildCompleteTree(path: string) {
return await vfs.getTreeStructure(path, {
maxDepth: 5, // Prevent deep recursion
includeHidden: false, // Skip .hidden files
sort: 'name' // Organized output
})
}
// ✅ Pattern 3: Detailed inspection
async function inspectPath(path: string) {
const info = await vfs.inspect(path)
return {
current: info.node,
children: info.children, // Direct children only
parent: info.parent, // Parent directory
stats: info.stats // Size, permissions, etc.
}
}
```
## 🗃️ Storage Configuration Patterns
### ❌ **WRONG - Memory Storage for Files**
```typescript
// DON'T DO THIS - Data disappears when process exits!
const brain = new Brainy({
storage: { type: 'memory' } // ❌ Temporary only
})
// Files written here are lost forever on restart
await vfs.writeFile('/important.doc', content)
```
### ✅ **CORRECT - Persistent Storage**
```typescript
// ✅ Pattern 1: Filesystem storage (development)
const brain = new Brainy({
storage: {
type: 'filesystem',
path: './brainy-data' // Persisted to disk
}
})
// ✅ Pattern 2: Cloud storage (production)
const brain = new Brainy({
storage: {
type: 's3',
bucket: 'my-vfs-data',
region: 'us-west-2'
}
})
// ✅ Pattern 3: Auto-detection (recommended)
const brain = new Brainy() // Automatically chooses best storage
```
## 🔍 Search Patterns
### ❌ **WRONG - Manual String Matching**
```typescript
// DON'T DO THIS - Missing semantic understanding
async function findFilesOldWay(query: string) {
const allFiles = await vfs.readdir('/', { recursive: true })
return allFiles.filter(file =>
file.includes(query.toLowerCase()) // ❌ Basic string match
)
}
```
### ✅ **CORRECT - Semantic Search**
```typescript
// ✅ Pattern 1: Content-aware search
async function findFilesByContent(query: string) {
return await vfs.search(query, {
type: 'file', // Only search files
limit: 50, // Reasonable limit
threshold: 0.7 // Minimum relevance
})
}
// ✅ Pattern 2: Filtered search
async function findInDirectory(query: string, basePath: string) {
return await vfs.search(query, {
path: basePath, // Limit to specific directory
includeContent: true, // Include file content in results
sort: 'relevance' // Best matches first
})
}
// ✅ Pattern 3: Metadata-based search
async function findByAttributes(criteria: any) {
return await vfs.find({
where: criteria, // MongoDB-style queries
orderBy: 'modified', // Sort by last modified
limit: 100
})
}
```
## 🏗️ Initialization Patterns
### ❌ **WRONG - Race Conditions**
```typescript
// DON'T DO THIS - Not waiting for initialization
const brain = new Brainy()
const vfs = brain.vfs()
// ❌ Using VFS before it's ready
await vfs.writeFile('/file.txt', 'content') // May fail!
```
### ✅ **CORRECT - Proper Initialization**
```typescript
// ✅ Pattern 1: Sequential initialization
async function initializeVFS() {
const brain = new Brainy({
storage: { type: 'filesystem', path: './data' }
})
// Wait for brain to be ready
await brain.init()
// Then initialize VFS
const vfs = brain.vfs()
await vfs.init()
// Now safe to use
return vfs
}
// ✅ Pattern 2: With error handling
async function robustVFSInit() {
try {
const brain = new Brainy()
await brain.init()
const vfs = brain.vfs()
await vfs.init()
// Verify it's working
await vfs.stat('/') // Should not throw
return vfs
} catch (error) {
console.error('VFS initialization failed:', error)
throw new Error(`Cannot initialize VFS: ${error.message}`)
}
}
// ✅ Pattern 3: Singleton pattern for apps
class VFSManager {
private static instance: any = null
static async getInstance() {
if (!this.instance) {
const brain = new Brainy()
await brain.init()
this.instance = brain.vfs()
await this.instance.init()
}
return this.instance
}
}
```
## 📝 File Operation Patterns
### ❌ **WRONG - Blocking Operations**
```typescript
// DON'T DO THIS - Blocking the main thread
async function badFileProcessing(files: string[]) {
for (const file of files) {
const content = await vfs.readFile(file) // ❌ Sequential
await processContent(content) // ❌ Blocking
await vfs.writeFile(file + '.processed', result)
}
}
```
### ✅ **CORRECT - Efficient Operations**
```typescript
// ✅ Pattern 1: Parallel processing
async function efficientProcessing(files: string[]) {
const operations = files.map(async (file) => {
try {
const content = await vfs.readFile(file)
const result = await processContent(content)
await vfs.writeFile(file + '.processed', result)
return { file, success: true }
} catch (error) {
return { file, success: false, error: error.message }
}
})
return await Promise.allSettled(operations)
}
// ✅ Pattern 2: Batch operations with limits
async function batchProcessFiles(files: string[], batchSize = 10) {
const results = []
for (let i = 0; i < files.length; i += batchSize) {
const batch = files.slice(i, i + batchSize)
const batchResults = await Promise.all(
batch.map(file => processFile(file))
)
results.push(...batchResults)
// Optional: Add delay between batches
if (i + batchSize < files.length) {
await new Promise(resolve => setTimeout(resolve, 100))
}
}
return results
}
// ✅ Pattern 3: Streaming for large files
async function streamLargeFile(filePath: string) {
const stream = await vfs.createReadStream(filePath, {
highWaterMark: 64 * 1024 // 64KB chunks
})
return new Promise((resolve, reject) => {
let content = ''
stream.on('data', (chunk) => {
content += chunk.toString()
})
stream.on('end', () => resolve(content))
stream.on('error', reject)
})
}
```
## 🔗 Relationship Patterns
### ❌ **WRONG - Manual Relationship Tracking**
```typescript
// DON'T DO THIS - Reinventing the graph
const fileRelationships = new Map() // ❌ Manual tracking
function linkFiles(sourceFile: string, targetFile: string, relationship: string) {
if (!fileRelationships.has(sourceFile)) {
fileRelationships.set(sourceFile, [])
}
fileRelationships.get(sourceFile).push({ target: targetFile, type: relationship })
}
```
### ✅ **CORRECT - Use Built-in Relationships**
```typescript
// ✅ Pattern 1: Semantic relationships
async function createFileRelationships() {
// Link test to source file
await vfs.addRelationship(
'/src/auth.ts',
'/tests/auth.test.ts',
'tested-by'
)
// Link documentation to implementation
await vfs.addRelationship(
'/docs/api.md',
'/src/api.ts',
'documents'
)
// Link dependency relationships
await vfs.addRelationship(
'/src/index.ts',
'/src/utils.ts',
'imports'
)
}
// ✅ Pattern 2: Query relationships
async function findRelatedFiles(filePath: string) {
// Find all files related to this one
const related = await vfs.getRelated(filePath, {
depth: 2, // Include relationships of relationships
types: ['tests', 'documents', 'imports'], // Filter relationship types
direction: 'both' // Both incoming and outgoing
})
return related
}
// ✅ Pattern 3: Relationship-based search
async function findTestFiles(sourceFile: string) {
return await vfs.search('', {
connected: {
to: sourceFile,
via: 'tested-by',
direction: 'incoming'
}
})
}
```
## 🚀 Performance Patterns
### ❌ **WRONG - Loading Everything**
```typescript
// DON'T DO THIS - Loading massive directories
async function loadEntireProject() {
const allFiles = await vfs.getTreeStructure('/', {
// ❌ No limits, could be millions of files
})
return allFiles // ❌ Crashes on large projects
}
```
### ✅ **CORRECT - Smart Loading**
```typescript
// ✅ Pattern 1: Paginated loading
async function loadDirectoryPage(path: string, page = 0, size = 50) {
const children = await vfs.getDirectChildren(path, {
limit: size,
offset: page * size,
sort: 'name'
})
const total = await vfs.getChildrenCount(path)
return {
items: children,
page,
size,
total,
hasMore: (page + 1) * size < total
}
}
// ✅ Pattern 2: Lazy loading with caching
class FileTreeCache {
private cache = new Map()
async getDirectory(path: string) {
if (this.cache.has(path)) {
return this.cache.get(path)
}
const children = await vfs.getDirectChildren(path)
this.cache.set(path, children)
// Auto-expire cache after 5 minutes
setTimeout(() => this.cache.delete(path), 5 * 60 * 1000)
return children
}
}
// ✅ Pattern 3: Progressive disclosure
async function buildLazyTree(rootPath: string) {
const tree = await vfs.getTreeStructure(rootPath, {
maxDepth: 1, // Only immediate children
lazy: true // Enable lazy loading for subdirectories
})
// Expand directories on demand
tree.expandDirectory = async (path: string) => {
const subtree = await vfs.getTreeStructure(path, {
maxDepth: 1
})
return subtree.children
}
return tree
}
```
## 🔧 Error Handling Patterns
### ❌ **WRONG - Silent Failures**
```typescript
// DON'T DO THIS - Ignoring errors
async function badErrorHandling(path: string) {
try {
return await vfs.readFile(path)
} catch (error) {
return null // ❌ Silent failure
}
}
```
### ✅ **CORRECT - Robust Error Handling**
```typescript
// ✅ Pattern 1: Specific error handling
async function robustFileRead(path: string) {
try {
return await vfs.readFile(path)
} catch (error) {
if (error.code === 'ENOENT') {
throw new Error(`File not found: ${path}`)
} else if (error.code === 'EACCES') {
throw new Error(`Permission denied: ${path}`)
} else if (error.code === 'EISDIR') {
throw new Error(`Path is a directory, not a file: ${path}`)
} else {
throw new Error(`Failed to read ${path}: ${error.message}`)
}
}
}
// ✅ Pattern 2: Retry with backoff
async function resilientOperation(operation: () => Promise<any>, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await operation()
} catch (error) {
if (attempt === maxRetries) {
throw error
}
// Exponential backoff
const delay = Math.pow(2, attempt) * 1000
await new Promise(resolve => setTimeout(resolve, delay))
console.warn(`Attempt ${attempt} failed, retrying in ${delay}ms...`)
}
}
}
// ✅ Pattern 3: Graceful degradation
async function gracefulFileExplorer(path: string) {
try {
// Try the optimal method first
return await vfs.getDirectChildren(path)
} catch (error) {
console.warn('Direct children failed, trying basic readdir:', error.message)
try {
// Fallback to basic directory listing
const entries = await vfs.readdir(path)
return entries.map(name => ({
metadata: { name, path: `${path}/${name}` },
// Missing detailed metadata, but functional
}))
} catch (fallbackError) {
console.error('All methods failed:', fallbackError.message)
return [] // Empty result rather than crash
}
}
}
```
## 📚 Integration Patterns
### ✅ **React Hook Pattern**
```typescript
function useVFS() {
const [vfs, setVFS] = useState<any>(null)
const [loading, setLoading] = useState(true)
const [error, setError] = useState<string | null>(null)
useEffect(() => {
async function initVFS() {
try {
const brain = new Brainy({
storage: { type: 'filesystem', path: './brainy-data' }
})
await brain.init()
const vfsInstance = brain.vfs()
await vfsInstance.init()
setVFS(vfsInstance)
} catch (err) {
setError(err.message)
} finally {
setLoading(false)
}
}
initVFS()
}, [])
return { vfs, loading, error }
}
```
### ✅ **Express.js Middleware Pattern**
```typescript
function vfsMiddleware() {
let vfsInstance: any = null
return async (req: any, res: any, next: any) => {
if (!vfsInstance) {
try {
const brain = new Brainy()
await brain.init()
vfsInstance = brain.vfs()
await vfsInstance.init()
} catch (error) {
return res.status(500).json({ error: 'VFS initialization failed' })
}
}
req.vfs = vfsInstance
next()
}
}
```
## 🎯 Summary: Do This, Not That
| ❌ **Avoid These Patterns** | ✅ **Use These Instead** |
|---------------------------|------------------------|
| Manual tree filtering | `vfs.getDirectChildren()` |
| Memory storage for files | Filesystem or cloud storage |
| Sequential file operations | Parallel processing with limits |
| Manual relationship tracking | Built-in `vfs.addRelationship()` |
| Loading entire directories | Paginated/lazy loading |
| Silent error handling | Specific error types and fallbacks |
| Blocking synchronous calls | Async/await with proper error handling |
---
**🎉 Following these patterns will give you:**
- 🚫 **Zero infinite recursion** in file explorers
- ⚡ **Fast performance** even with large directories
- 🔄 **Reliable error recovery** and graceful degradation
- 🧠 **Semantic intelligence** for powerful file search
- 📈 **Scalable architecture** that grows with your needs
**Next Steps:** Check out the [VFS API Guide](./VFS_API_GUIDE.md) for complete method documentation.

332
docs/vfs/QUICK_START.md Normal file
View file

@ -0,0 +1,332 @@
# 🚀 VFS Quick Start: 5-Minute File Explorer Setup
> Get a working, production-ready file explorer with Brainy VFS in 5 minutes. Avoid common pitfalls and use the correct APIs.
## 📋 What You'll Build
A file explorer that:
- ✅ **Never crashes** from infinite recursion
- ✅ **Uses filesystem storage** correctly
- ✅ **Leverages semantic search** to find files by content
- ✅ **Handles large directories** efficiently
- ✅ **Follows modern Brainy v3.x APIs**
## ⚡ Step 1: Basic Setup (1 minute)
```bash
npm install @soulcraft/brainy
```
```typescript
import { Brainy } from '@soulcraft/brainy'
// ✅ CORRECT: Use filesystem storage for production
const brain = new Brainy({
storage: {
type: 'filesystem',
path: './brainy-data' // Your data directory
}
})
await brain.init()
// ✅ CORRECT: Initialize VFS
const vfs = brain.vfs()
await vfs.init()
console.log('🎉 VFS ready!')
```
> **🚨 Common Mistake**: Don't use `storage: { type: 'memory' }` for file explorers - your data will disappear when the process exits!
## 📁 Step 2: Safe Directory Listing (2 minutes)
**❌ WRONG - This causes infinite recursion:**
```typescript
// DON'T DO THIS - Causes directory to appear as its own child!
const badItems = allNodes.filter(node => node.path.startsWith(dirPath))
```
**✅ CORRECT - Use tree-aware methods:**
```typescript
// ✅ Method 1: Get direct children (recommended for UI)
async function loadDirectoryContents(path: string) {
try {
const children = await vfs.getDirectChildren(path)
// Sort directories first, then files
return children.sort((a, b) => {
if (a.metadata.vfsType === 'directory' && b.metadata.vfsType === 'file') return -1
if (a.metadata.vfsType === 'file' && b.metadata.vfsType === 'directory') return 1
return a.metadata.name.localeCompare(b.metadata.name)
})
} catch (error) {
console.error(`Failed to load ${path}:`, error.message)
return []
}
}
// ✅ Method 2: Get complete tree structure (for full trees)
async function loadFullTree(path: string) {
const tree = await vfs.getTreeStructure(path, {
maxDepth: 3, // Prevent deep recursion
includeHidden: false, // Skip hidden files
sort: 'name'
})
return tree
}
// ✅ Method 3: Get detailed path info
async function inspectPath(path: string) {
const info = await vfs.inspect(path)
return {
isDirectory: info.node.metadata.vfsType === 'directory',
children: info.children,
parent: info.parent,
stats: info.stats
}
}
```
## 🔍 Step 3: Add Semantic Search (1 minute)
```typescript
// ✅ Find files by content, not just filename
async function searchFiles(query: string, basePath: string = '/') {
const results = await vfs.search(query, {
path: basePath, // Limit search to specific directory
limit: 50, // Reasonable limit
type: 'file' // Only search files, not directories
})
return results.map(result => ({
path: result.path,
score: result.score,
type: result.type,
size: result.size,
modified: result.modified
}))
}
// Example usage
const reactFiles = await searchFiles('React components with hooks', '/src')
const docs = await searchFiles('API documentation', '/docs')
```
## 🖥️ Step 4: Complete File Explorer Component (1 minute)
Here's a complete React component using the correct patterns:
```tsx
import React, { useState, useEffect } from 'react'
import { Brainy } from '@soulcraft/brainy'
export function FileExplorer() {
const [vfs, setVfs] = useState(null)
const [currentPath, setCurrentPath] = useState('/')
const [items, setItems] = useState([])
const [loading, setLoading] = useState(true)
const [searchQuery, setSearchQuery] = useState('')
// Initialize VFS
useEffect(() => {
async function initVFS() {
const brain = new Brainy({
storage: { type: 'filesystem', path: './brainy-data' }
})
await brain.init()
const vfsInstance = brain.vfs()
await vfsInstance.init()
setVfs(vfsInstance)
setLoading(false)
}
initVFS()
}, [])
// Load directory contents
const loadDirectory = async (path: string) => {
if (!vfs) return
setLoading(true)
try {
// ✅ CORRECT: Use getDirectChildren to prevent recursion
const children = await vfs.getDirectChildren(path)
// Sort directories first
const sorted = children.sort((a, b) => {
if (a.metadata.vfsType === 'directory' && b.metadata.vfsType === 'file') return -1
if (a.metadata.vfsType === 'file' && b.metadata.vfsType === 'directory') return 1
return a.metadata.name.localeCompare(b.metadata.name)
})
setItems(sorted)
setCurrentPath(path)
} catch (error) {
console.error('Failed to load directory:', error)
setItems([])
} finally {
setLoading(false)
}
}
// Search files
const handleSearch = async () => {
if (!vfs || !searchQuery.trim()) {
loadDirectory(currentPath)
return
}
setLoading(true)
try {
const results = await vfs.search(searchQuery, {
path: currentPath,
limit: 100
})
setItems(results)
} catch (error) {
console.error('Search failed:', error)
} finally {
setLoading(false)
}
}
// Initial load
useEffect(() => {
if (vfs) {
loadDirectory('/')
}
}, [vfs])
if (loading && !vfs) {
return <div>Initializing VFS...</div>
}
return (
<div className="file-explorer">
{/* Search bar */}
<div className="search-bar">
<input
type="text"
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
placeholder="Search files by content..."
onKeyPress={(e) => e.key === 'Enter' && handleSearch()}
/>
<button onClick={handleSearch}>Search</button>
{searchQuery && (
<button onClick={() => { setSearchQuery(''); loadDirectory(currentPath) }}>
Clear
</button>
)}
</div>
{/* Current path */}
<div className="current-path">
📁 {currentPath}
{currentPath !== '/' && (
<button onClick={() => loadDirectory(currentPath.split('/').slice(0, -1).join('/') || '/')}>
⬆️ Up
</button>
)}
</div>
{/* File list */}
{loading ? (
<div>Loading...</div>
) : (
<div className="file-list">
{items.map((item) => (
<div
key={item.id}
className={`file-item ${item.metadata.vfsType}`}
onClick={() => {
if (item.metadata.vfsType === 'directory') {
loadDirectory(item.metadata.path)
} else {
console.log('Open file:', item.metadata.path)
// Add your file opening logic here
}
}}
>
<span className="icon">
{item.metadata.vfsType === 'directory' ? '📁' : '📄'}
</span>
<span className="name">{item.metadata.name}</span>
<span className="size">
{item.metadata.size ? `${Math.round(item.metadata.size / 1024)}KB` : ''}
</span>
</div>
))}
{items.length === 0 && (
<div className="empty">
{searchQuery ? 'No results found' : 'Empty directory'}
</div>
)}
</div>
)}
</div>
)
}
```
## 🎯 What We Just Avoided
By using this quick start, you avoided these common mistakes:
**Infinite Recursion**: Using naive filtering that includes directories as their own children
**Memory Storage**: Losing data when process restarts
**Old APIs**: Using deprecated `addNoun`, `getNouns`, `addVerb` methods
**Complex Fallbacks**: Implementing unnecessary fallback patterns when proper methods exist
**Poor Performance**: Not using tree-aware methods designed for file explorers
## 🚀 Next Steps
Your file explorer is now working! Here's what to explore next:
1. **[File Operations](./VFS_API_GUIDE.md#file-operations)** - Read, write, and manipulate files
2. **[Semantic Features](./VFS_KNOWLEDGE_LAYER.md)** - Connect files to concepts and entities
3. **[Performance Optimization](./building-file-explorers.md#performance)** - Handle large directories efficiently
4. **[Advanced Search](./VFS_API_GUIDE.md#search-operations)** - Complex queries and filters
## 🆘 Common Issues & Solutions
### "Module not found" errors
```bash
# Make sure you're using the right import
npm ls @soulcraft/brainy # Check version
npm install @soulcraft/brainy@latest # Update if needed
```
### "VFS not initialized" errors
```typescript
// Always await both init() calls
await brain.init()
const vfs = brain.vfs()
await vfs.init() // Don't forget this!
```
### Slow directory loading
```typescript
// Add pagination for large directories
const children = await vfs.getDirectChildren(path, {
limit: 100, // Load only first 100 items
offset: 0 // Start from beginning
})
```
### Search not finding files
```typescript
// Make sure files are imported into VFS first
await vfs.importDirectory('./my-files', {
recursive: true,
extractMetadata: true // Enable content understanding
})
```
---
**🎉 Congratulations!** You now have a working file explorer that uses modern Brainy APIs correctly. No more infinite recursion, no more deprecated methods, no more confusion.
**Need help?** Check out our [Complete VFS Guide](./VFS_API_GUIDE.md) or [Common Patterns](./COMMON_PATTERNS.md).