diff --git a/README.md b/README.md index aad3814e..d1c79d7b 100644 --- a/README.md +++ b/README.md @@ -209,54 +209,65 @@ await brain.find("Popular JavaScript libraries similar to Vue") await brain.find("Documentation about authentication from last month") ``` -### 🧠🌐 **Knowledge Graph + Virtual Filesystem - Where Ideas Come Alive** +### 🧠🌐 **Virtual Filesystem - Intelligent File Management** -**Store ANY knowledge. Connect EVERYTHING. Files are optional.** +**Build file explorers, IDEs, and knowledge systems that never crash from infinite recursion.** -- **Living Knowledge**: Characters, concepts, and systems that exist independently of files -- **Universal Connections**: Link files to entities, entities to concepts, anything to anything -- **Semantic Intelligence**: Find knowledge by meaning, not by where it's stored -- **Optional Files**: Use filesystem operations when helpful, pure knowledge when not -- **Perfect Memory**: Every piece of knowledge remembers its entire history -- **Knowledge Evolution**: Watch ideas grow and connect across time and projects +- **Tree-Aware Operations**: Safe directory listing prevents recursive loops +- **Semantic Search**: Find files by content, not just filename +- **Production Storage**: Filesystem and cloud storage for real applications +- **Zero-Config**: Works out of the box with intelligent defaults ```javascript import { Brainy } from '@soulcraft/brainy' -const brain = new Brainy({ storage: { type: 'memory' } }) +// āœ… CORRECT: Use persistent storage for file systems +const brain = new Brainy({ + storage: { + type: 'filesystem', // Persisted to disk + path: './brainy-data' // Your file storage + } +}) await brain.init() + const vfs = brain.vfs() await vfs.init() -// Start with familiar files if you want -await vfs.writeFile('/story.txt', 'A tale of adventure...') +// āœ… Safe file operations +await vfs.writeFile('/projects/app/index.js', 'console.log("Hello")') +await vfs.mkdir('/docs') +await vfs.writeFile('/docs/README.md', '# My Project') -// But knowledge doesn't need files! -const alice = await vfs.createEntity({ - name: 'Alice', - type: 'character', - description: 'Brave explorer discovering quantum worlds' +// āœ… NEVER crashes: Tree-aware directory listing +const children = await vfs.getDirectChildren('/projects') +// Returns only direct children, never the directory itself + +// āœ… Build file explorers safely +const tree = await vfs.getTreeStructure('/projects', { + maxDepth: 3, // Prevent deep recursion + sort: 'name' // Organized results }) -const quantumPhysics = await vfs.createConcept({ - name: 'Quantum Entanglement', - domain: 'physics', - keywords: ['superposition', 'measurement', 'correlation'] +// āœ… Semantic file search +const reactFiles = await vfs.search('React components with hooks') +const docs = await vfs.search('API documentation', { + path: '/docs' // Search within specific directory }) -// Connect EVERYTHING - files, entities, concepts -await vfs.linkEntities(alice, quantumPhysics, 'studies') -await vfs.addRelationship('/story.txt', alice.id, 'features') +// āœ… Connect related files +await vfs.addRelationship('/src/auth.js', '/tests/auth.test.js', 'tested-by') -// Find knowledge by meaning, not location -const physics = await vfs.search('quantum mechanics') -// Returns: files, entities, concepts, relationships - ALL knowledge - -// Knowledge transcends boundaries -const aliceKnowledge = await vfs.getEntityGraph(alice) -// Her relationships, appearances, evolution - her entire existence +// Perfect for: File explorers, IDEs, documentation systems, code analysis ``` +**🚨 Prevents Common Mistakes:** +- āŒ No infinite recursion in file trees (like brain-cloud team experienced) +- āŒ No data loss from memory storage +- āŒ No performance issues with large directories +- āŒ No need for complex fallback patterns + +**[šŸ“– VFS Quick Start →](docs/vfs/QUICK_START.md)** | **[šŸŽÆ Common Patterns →](docs/vfs/COMMON_PATTERNS.md)** + **Your knowledge isn't trapped anymore.** Characters live beyond stories. APIs exist beyond code files. Concepts connect across domains. This is knowledge that happens to support files, not a filesystem that happens to store knowledge. ### šŸŽÆ Zero Configuration Philosophy diff --git a/docs/API_DECISION_TREE.md b/docs/API_DECISION_TREE.md new file mode 100644 index 00000000..c0a6f3a0 --- /dev/null +++ b/docs/API_DECISION_TREE.md @@ -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.* \ No newline at end of file diff --git a/docs/CORE_API_PATTERNS.md b/docs/CORE_API_PATTERNS.md new file mode 100644 index 00000000..403fc98b --- /dev/null +++ b/docs/CORE_API_PATTERNS.md @@ -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(operation: () => Promise): Promise { + 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) \ No newline at end of file diff --git a/docs/NEURAL_API_PATTERNS.md b/docs/NEURAL_API_PATTERNS.md new file mode 100644 index 00000000..7aa516b3 --- /dev/null +++ b/docs/NEURAL_API_PATTERNS.md @@ -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) \ No newline at end of file diff --git a/docs/vfs/COMMON_PATTERNS.md b/docs/vfs/COMMON_PATTERNS.md new file mode 100644 index 00000000..6b4d678a --- /dev/null +++ b/docs/vfs/COMMON_PATTERNS.md @@ -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, 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(null) + const [loading, setLoading] = useState(true) + const [error, setError] = useState(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. \ No newline at end of file diff --git a/docs/vfs/QUICK_START.md b/docs/vfs/QUICK_START.md new file mode 100644 index 00000000..2825402b --- /dev/null +++ b/docs/vfs/QUICK_START.md @@ -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
Initializing VFS...
+ } + + return ( +
+ {/* Search bar */} +
+ setSearchQuery(e.target.value)} + placeholder="Search files by content..." + onKeyPress={(e) => e.key === 'Enter' && handleSearch()} + /> + + {searchQuery && ( + + )} +
+ + {/* Current path */} +
+ šŸ“ {currentPath} + {currentPath !== '/' && ( + + )} +
+ + {/* File list */} + {loading ? ( +
Loading...
+ ) : ( +
+ {items.map((item) => ( +
{ + if (item.metadata.vfsType === 'directory') { + loadDirectory(item.metadata.path) + } else { + console.log('Open file:', item.metadata.path) + // Add your file opening logic here + } + }} + > + + {item.metadata.vfsType === 'directory' ? 'šŸ“' : 'šŸ“„'} + + {item.metadata.name} + + {item.metadata.size ? `${Math.round(item.metadata.size / 1024)}KB` : ''} + +
+ ))} + {items.length === 0 && ( +
+ {searchQuery ? 'No results found' : 'Empty directory'} +
+ )} +
+ )} +
+ ) +} +``` + +## šŸŽÆ 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). \ No newline at end of file diff --git a/src/brainy.ts b/src/brainy.ts index 85df3f18..9d23f22a 100644 --- a/src/brainy.ts +++ b/src/brainy.ts @@ -227,6 +227,50 @@ export class Brainy implements BrainyInterface { /** * Add an entity to the database + * + * @param params - Parameters for adding the entity + * @returns Promise that resolves to the entity ID + * + * @example Basic entity creation + * ```typescript + * const id = await brain.add({ + * data: "John Smith is a software engineer", + * type: NounType.Person, + * metadata: { role: "engineer", team: "backend" } + * }) + * console.log(`Created entity: ${id}`) + * ``` + * + * @example Adding with custom ID + * ```typescript + * const customId = await brain.add({ + * id: "user-12345", + * data: "Important document content", + * type: NounType.Document, + * metadata: { priority: "high", department: "legal" } + * }) + * ``` + * + * @example Using pre-computed vector (optimization) + * ```typescript + * const vector = await brain.embed("Optimized content") + * const id = await brain.add({ + * data: "Optimized content", + * type: NounType.Document, + * vector: vector, // Skip re-embedding + * metadata: { optimized: true } + * }) + * ``` + * + * @example Multi-tenant usage + * ```typescript + * const id = await brain.add({ + * data: "Customer feedback", + * type: NounType.Message, + * service: "customer-portal", // Multi-tenancy + * metadata: { rating: 5, verified: true } + * }) + * ``` */ async add(params: AddParams): Promise { await this.ensureInitialized() @@ -283,6 +327,74 @@ export class Brainy implements BrainyInterface { /** * Get an entity by ID + * + * @param id - The unique identifier of the entity to retrieve + * @returns Promise that resolves to the entity if found, null if not found + * + * @example + * // Basic entity retrieval + * const entity = await brainy.get('user-123') + * if (entity) { + * console.log('Found entity:', entity.data) + * console.log('Created at:', new Date(entity.createdAt)) + * } else { + * console.log('Entity not found') + * } + * + * @example + * // Working with typed entities + * interface User { + * name: string + * email: string + * } + * + * const brainy = new Brainy({ storage: 'filesystem' }) + * const user = await brainy.get('user-456') + * if (user) { + * // TypeScript knows user.metadata is of type User + * console.log(`Hello ${user.metadata.name}`) + * } + * + * @example + * // Safe retrieval with error handling + * try { + * const entity = await brainy.get('document-789') + * if (!entity) { + * throw new Error('Document not found') + * } + * + * // Process the entity + * return { + * id: entity.id, + * content: entity.data, + * type: entity.type, + * metadata: entity.metadata + * } + * } catch (error) { + * console.error('Failed to retrieve entity:', error) + * return null + * } + * + * @example + * // Batch retrieval pattern + * const ids = ['doc-1', 'doc-2', 'doc-3'] + * const entities = await Promise.all( + * ids.map(id => brainy.get(id)) + * ) + * const foundEntities = entities.filter(entity => entity !== null) + * console.log(`Found ${foundEntities.length} out of ${ids.length} entities`) + * + * @example + * // Using with async iteration + * const entityIds = ['user-1', 'user-2', 'user-3'] + * + * for (const id of entityIds) { + * const entity = await brainy.get(id) + * if (entity) { + * console.log(`Processing ${entity.type}: ${id}`) + * // Process entity... + * } + * } */ async get(id: string): Promise | null> { await this.ensureInitialized() @@ -431,6 +543,107 @@ export class Brainy implements BrainyInterface { /** * Create a relationship between entities + * + * @param params - Parameters for creating the relationship + * @returns Promise that resolves to the relationship ID + * + * @example + * // Basic relationship creation + * const userId = await brainy.add({ + * data: { name: 'John', role: 'developer' }, + * type: NounType.Person + * }) + * const projectId = await brainy.add({ + * data: { name: 'AI Assistant', status: 'active' }, + * type: NounType.Thing + * }) + * + * const relationId = await brainy.relate({ + * from: userId, + * to: projectId, + * type: VerbType.WorksOn + * }) + * + * @example + * // Bidirectional relationships + * const friendshipId = await brainy.relate({ + * from: 'user-1', + * to: 'user-2', + * type: VerbType.Knows, + * bidirectional: true // Creates both directions automatically + * }) + * + * @example + * // Weighted relationships for importance/strength + * const collaborationId = await brainy.relate({ + * from: 'team-lead', + * to: 'project-alpha', + * type: VerbType.LeadsOn, + * weight: 0.9, // High importance/strength + * metadata: { + * startDate: '2024-01-15', + * responsibility: 'technical leadership', + * hoursPerWeek: 40 + * } + * }) + * + * @example + * // Typed relationships with custom metadata + * interface CollaborationMeta { + * role: string + * startDate: string + * skillLevel: number + * } + * + * const brainy = new Brainy({ storage: 'filesystem' }) + * const relationId = await brainy.relate({ + * from: 'developer-123', + * to: 'project-456', + * type: VerbType.WorksOn, + * weight: 0.85, + * metadata: { + * role: 'frontend developer', + * startDate: '2024-03-01', + * skillLevel: 8 + * } + * }) + * + * @example + * // Creating complex relationship networks + * const entities = [] + * // Create entities + * for (let i = 0; i < 5; i++) { + * const id = await brainy.add({ + * data: { name: `Entity ${i}`, value: i * 10 }, + * type: NounType.Thing + * }) + * entities.push(id) + * } + * + * // Create hierarchical relationships + * for (let i = 0; i < entities.length - 1; i++) { + * await brainy.relate({ + * from: entities[i], + * to: entities[i + 1], + * type: VerbType.DependsOn, + * weight: (i + 1) / entities.length + * }) + * } + * + * @example + * // Error handling for invalid relationships + * try { + * await brainy.relate({ + * from: 'nonexistent-entity', + * to: 'another-entity', + * type: VerbType.RelatedTo + * }) + * } catch (error) { + * if (error.message.includes('not found')) { + * console.log('One or both entities do not exist') + * // Handle missing entities... + * } + * } */ async relate(params: RelateParams): Promise { await this.ensureInitialized() @@ -557,6 +770,142 @@ export class Brainy implements BrainyInterface { /** * Unified find method - supports natural language and structured queries * Implements Triple Intelligence with parallel search optimization + * + * @param query - Natural language string or structured FindParams object + * @returns Promise that resolves to array of search results with scores + * + * @example + * // Natural language queries (most common) + * const results = await brainy.find('users who work on AI projects') + * const docs = await brainy.find('documents about machine learning') + * const code = await brainy.find('JavaScript functions for data processing') + * + * @example + * // Structured queries with filtering + * const results = await brainy.find({ + * query: 'artificial intelligence', + * type: NounType.Document, + * limit: 5, + * where: { + * status: 'published', + * author: 'expert' + * } + * }) + * + * // Process results + * for (const result of results) { + * console.log(`Found: ${result.entity.data} (score: ${result.score})`) + * } + * + * @example + * // Metadata-only filtering (no vector search) + * const activeUsers = await brainy.find({ + * type: NounType.Person, + * where: { + * status: 'active', + * department: 'engineering' + * }, + * service: 'user-management' + * }) + * + * @example + * // Vector similarity search with custom vectors + * const queryVector = await brainy.embed('machine learning algorithms') + * const similar = await brainy.find({ + * vector: queryVector, + * limit: 10, + * type: [NounType.Document, NounType.Thing] + * }) + * + * @example + * // Proximity search (find entities similar to existing ones) + * const relatedContent = await brainy.find({ + * near: 'document-123', // Find entities similar to this one + * limit: 8, + * where: { + * published: true + * } + * }) + * + * @example + * // Pagination for large result sets + * const firstPage = await brainy.find({ + * query: 'research papers', + * limit: 20, + * offset: 0 + * }) + * + * const secondPage = await brainy.find({ + * query: 'research papers', + * limit: 20, + * offset: 20 + * }) + * + * @example + * // Complex search with multiple criteria + * const results = await brainy.find({ + * query: 'machine learning models', + * type: [NounType.Thing, NounType.Document], + * where: { + * accuracy: { $gte: 0.9 }, // Metadata filtering + * framework: { $in: ['tensorflow', 'pytorch'] } + * }, + * service: 'ml-pipeline', + * limit: 15 + * }) + * + * @example + * // Empty query returns all entities (paginated) + * const allEntities = await brainy.find({ + * limit: 50, + * offset: 0 + * }) + * + * @example + * // Performance-optimized search patterns + * // Fast metadata-only search (no vector computation) + * const fastResults = await brainy.find({ + * type: NounType.Person, + * where: { active: true }, + * limit: 100 + * }) + * + * // Combined vector + metadata for precision + * const preciseResults = await brainy.find({ + * query: 'senior developers', + * where: { + * experience: { $gte: 5 }, + * skills: { $includes: 'javascript' } + * }, + * limit: 10 + * }) + * + * @example + * // Error handling and result processing + * try { + * const results = await brainy.find('complex query here') + * + * if (results.length === 0) { + * console.log('No results found') + * return + * } + * + * // Filter by confidence threshold + * const highConfidence = results.filter(r => r.score > 0.7) + * + * // Sort by score (already sorted by default) + * const topResults = results.slice(0, 5) + * + * return topResults.map(r => ({ + * id: r.id, + * content: r.entity.data, + * confidence: r.score, + * metadata: r.entity.metadata + * })) + * } catch (error) { + * console.error('Search failed:', error) + * return [] + * } */ async find(query: string | FindParams): Promise[]> { await this.ensureInitialized() @@ -786,7 +1135,113 @@ export class Brainy implements BrainyInterface { } /** - * Find similar entities + * Find similar entities using vector similarity + * + * @param params - Parameters specifying the target for similarity search + * @returns Promise that resolves to array of similar entities with similarity scores + * + * @example + * // Find entities similar to a specific entity by ID + * const similarDocs = await brainy.similar({ + * to: 'document-123', + * limit: 10 + * }) + * + * // Process similarity results + * for (const result of similarDocs) { + * console.log(`Similar entity: ${result.entity.data} (similarity: ${result.score})`) + * } + * + * @example + * // Find similar entities with type filtering + * const similarUsers = await brainy.similar({ + * to: 'user-456', + * type: NounType.Person, + * limit: 5, + * where: { + * active: true, + * department: 'engineering' + * } + * }) + * + * @example + * // Find similar using a custom vector + * const customVector = await brainy.embed('artificial intelligence research') + * const similar = await brainy.similar({ + * to: customVector, + * limit: 8, + * type: [NounType.Document, NounType.Thing] + * }) + * + * @example + * // Find similar using an entity object + * const sourceEntity = await brainy.get('research-paper-789') + * if (sourceEntity) { + * const relatedPapers = await brainy.similar({ + * to: sourceEntity, + * limit: 12, + * where: { + * published: true, + * category: 'machine-learning' + * } + * }) + * } + * + * @example + * // Content recommendation system + * async function getRecommendations(userId: string) { + * // Get user's recent interactions + * const user = await brainy.get(userId) + * if (!user) return [] + * + * // Find similar content + * const recommendations = await brainy.similar({ + * to: userId, + * type: NounType.Document, + * limit: 20, + * where: { + * published: true, + * language: 'en' + * } + * }) + * + * // Filter out already seen content + * return recommendations.filter(rec => + * !user.metadata.viewedItems?.includes(rec.id) + * ) + * } + * + * @example + * // Duplicate detection system + * async function findPotentialDuplicates(entityId: string) { + * const duplicates = await brainy.similar({ + * to: entityId, + * limit: 10 + * }) + * + * // High similarity might indicate duplicates + * const highSimilarity = duplicates.filter(d => d.score > 0.95) + * + * if (highSimilarity.length > 0) { + * console.log('Potential duplicates found:', highSimilarity.map(d => d.id)) + * } + * + * return highSimilarity + * } + * + * @example + * // Error handling for missing entities + * try { + * const similar = await brainy.similar({ + * to: 'nonexistent-entity', + * limit: 5 + * }) + * } catch (error) { + * if (error.message.includes('not found')) { + * console.log('Source entity does not exist') + * // Handle missing source entity + * } + * } */ async similar(params: SimilarParams): Promise[]> { await this.ensureInitialized() @@ -1818,8 +2273,117 @@ export class Brainy implements BrainyInterface { } /** - * Embed data into vector - * Handles any data type by converting to string representation + * Embed data into vector representation + * Handles any data type by intelligently converting to string representation + * + * @param data - Any data to convert to vector (string, object, array, etc.) + * @returns Promise that resolves to a numerical vector representation + * + * @example + * // Basic string embedding + * const vector = await brainy.embed('machine learning algorithms') + * console.log('Vector dimensions:', vector.length) + * + * @example + * // Object embedding with intelligent field extraction + * const documentVector = await brainy.embed({ + * title: 'AI Research Paper', + * content: 'This paper discusses neural networks...', + * author: 'Dr. Smith', + * category: 'machine-learning' + * }) + * // Uses 'content' field for embedding by default + * + * @example + * // Different object field priorities + * // Priority: data > content > text > name > title > description + * const vectors = await Promise.all([ + * brainy.embed({ data: 'primary content' }), // Uses 'data' + * brainy.embed({ content: 'main content' }), // Uses 'content' + * brainy.embed({ text: 'text content' }), // Uses 'text' + * brainy.embed({ name: 'entity name' }), // Uses 'name' + * brainy.embed({ title: 'document title' }), // Uses 'title' + * brainy.embed({ description: 'description text' }) // Uses 'description' + * ]) + * + * @example + * // Array embedding for batch processing + * const batchVectors = await brainy.embed([ + * 'first document', + * 'second document', + * { content: 'third document as object' }, + * { title: 'fourth document' } + * ]) + * // Returns vector representing all items combined + * + * @example + * // Complex object handling + * const complexData = { + * user: { name: 'John', role: 'developer' }, + * project: { name: 'AI Assistant', status: 'active' }, + * metrics: { score: 0.95, performance: 'excellent' } + * } + * const vector = await brainy.embed(complexData) + * // Converts entire object to JSON for embedding + * + * @example + * // Pre-computing vectors for performance optimization + * const documents = [ + * { id: 'doc1', content: 'Document 1 content...' }, + * { id: 'doc2', content: 'Document 2 content...' }, + * { id: 'doc3', content: 'Document 3 content...' } + * ] + * + * // Pre-compute all vectors + * const vectors = await Promise.all( + * documents.map(doc => brainy.embed(doc.content)) + * ) + * + * // Add entities with pre-computed vectors (faster) + * for (let i = 0; i < documents.length; i++) { + * await brainy.add({ + * data: documents[i], + * type: NounType.Document, + * vector: vectors[i] // Skip embedding computation + * }) + * } + * + * @example + * // Custom embedding for search queries + * async function searchWithCustomEmbedding(query: string) { + * // Enhance query for better matching + * const enhancedQuery = `search: ${query} relevant information` + * const queryVector = await brainy.embed(enhancedQuery) + * + * // Use pre-computed vector for search + * return brainy.find({ + * vector: queryVector, + * limit: 10 + * }) + * } + * + * @example + * // Handling edge cases gracefully + * const edgeCases = await Promise.all([ + * brainy.embed(null), // Returns vector for empty string + * brainy.embed(undefined), // Returns vector for empty string + * brainy.embed(''), // Returns vector for empty string + * brainy.embed(42), // Converts number to string + * brainy.embed(true), // Converts boolean to string + * brainy.embed([]), // Empty array handling + * brainy.embed({}) // Empty object handling + * ]) + * + * @example + * // Using with similarity comparisons + * const doc1Vector = await brainy.embed('artificial intelligence research') + * const doc2Vector = await brainy.embed('machine learning algorithms') + * + * // Find entities similar to doc1Vector + * const similar = await brainy.find({ + * vector: doc1Vector, + * limit: 5 + * }) */ async embed(data: any): Promise { // Handle different data types intelligently diff --git a/src/types/augmentations.ts b/src/types/augmentations.ts index 6fcceccf..ef55e824 100644 --- a/src/types/augmentations.ts +++ b/src/types/augmentations.ts @@ -48,25 +48,173 @@ export type AugmentationContext = AC // REMOVED: Old augmentation type system for 2.0 clean architecture // All augmentations now use the unified BrainyAugmentation interface from brainyAugmentation.ts -// Temporary exports for compilation - TO BE REMOVED +/** + * @deprecated Use BrainyAugmentation from '../augmentations/brainyAugmentation.js' instead + * + * @example + * // āŒ Old way (v2.x): + * import { IAugmentation } from '@soulcraft/brainy/types/augmentations' + * + * // āœ… New way (v3.x): + * import { BrainyAugmentation } from '@soulcraft/brainy' + */ export type IAugmentation = BrainyAugmentation + +/** + * @deprecated Augmentation types are now unified under BrainyAugmentation interface + * + * @example + * // āŒ Old way (v2.x): + * import { AugmentationType } from '@soulcraft/brainy/types/augmentations' + * if (augmentation.type === AugmentationType.SENSE) { ... } + * + * // āœ… New way (v3.x): + * import { BrainyAugmentation } from '@soulcraft/brainy' + * // Use the unified BrainyAugmentation interface directly + */ export enum AugmentationType { SENSE = 'sense', CONDUIT = 'conduit', COGNITION = 'cognition', MEMORY = 'memory', PERCEPTION = 'perception', DIALOG = 'dialog', ACTIVATION = 'activation', WEBSOCKET = 'webSocket', SYNAPSE = 'synapse' } + +/** + * @deprecated Use BrainyAugmentation interface directly instead of namespace types + * + * @example + * // āŒ Old way (v2.x): + * import { BrainyAugmentations } from '@soulcraft/brainy/types/augmentations' + * class MyAugmentation implements BrainyAugmentations.ISenseAugmentation { ... } + * + * // āœ… New way (v3.x): + * import { BrainyAugmentation } from '@soulcraft/brainy' + * class MyAugmentation implements BrainyAugmentation { ... } + */ export namespace BrainyAugmentations { + /** @deprecated Use BrainyAugmentation instead */ export type ISenseAugmentation = BrainyAugmentation + /** @deprecated Use BrainyAugmentation instead */ export type IConduitAugmentation = BrainyAugmentation + /** @deprecated Use BrainyAugmentation instead */ export type ICognitionAugmentation = BrainyAugmentation + /** @deprecated Use BrainyAugmentation instead */ export type IMemoryAugmentation = BrainyAugmentation + /** @deprecated Use BrainyAugmentation instead */ export type IPerceptionAugmentation = BrainyAugmentation + /** @deprecated Use BrainyAugmentation instead */ export type IDialogAugmentation = BrainyAugmentation + /** @deprecated Use BrainyAugmentation instead */ export type IActivationAugmentation = BrainyAugmentation + /** @deprecated Use BrainyAugmentation instead */ export type ISynapseAugmentation = BrainyAugmentation } + +/** + * @deprecated Use BrainyAugmentation from '../augmentations/brainyAugmentation.js' instead + * + * @example + * // āŒ Old way (v2.x): + * import { ISenseAugmentation } from '@soulcraft/brainy/types/augmentations' + * class MySense implements ISenseAugmentation { ... } + * + * // āœ… New way (v3.x): + * import { BrainyAugmentation } from '@soulcraft/brainy' + * class MySense implements BrainyAugmentation { ... } + */ export type ISenseAugmentation = BrainyAugmentation + +/** + * @deprecated Use BrainyAugmentation from '../augmentations/brainyAugmentation.js' instead + * + * @example + * // āŒ Old way (v2.x): + * import { IConduitAugmentation } from '@soulcraft/brainy/types/augmentations' + * + * // āœ… New way (v3.x): + * import { BrainyAugmentation } from '@soulcraft/brainy' + */ export type IConduitAugmentation = BrainyAugmentation + +/** + * @deprecated Use BrainyAugmentation from '../augmentations/brainyAugmentation.js' instead + * + * @example + * // āŒ Old way (v2.x): + * import { ICognitionAugmentation } from '@soulcraft/brainy/types/augmentations' + * + * // āœ… New way (v3.x): + * import { BrainyAugmentation } from '@soulcraft/brainy' + */ export type ICognitionAugmentation = BrainyAugmentation + +/** + * @deprecated Use BrainyAugmentation from '../augmentations/brainyAugmentation.js' instead + * + * @example + * // āŒ Old way (v2.x): + * import { IMemoryAugmentation } from '@soulcraft/brainy/types/augmentations' + * + * // āœ… New way (v3.x): + * import { BrainyAugmentation } from '@soulcraft/brainy' + */ export type IMemoryAugmentation = BrainyAugmentation + +/** + * @deprecated Use BrainyAugmentation from '../augmentations/brainyAugmentation.js' instead + * + * @example + * // āŒ Old way (v2.x): + * import { IPerceptionAugmentation } from '@soulcraft/brainy/types/augmentations' + * + * // āœ… New way (v3.x): + * import { BrainyAugmentation } from '@soulcraft/brainy' + */ export type IPerceptionAugmentation = BrainyAugmentation + +/** + * @deprecated Use BrainyAugmentation from '../augmentations/brainyAugmentation.js' instead + * + * @example + * // āŒ Old way (v2.x): + * import { IDialogAugmentation } from '@soulcraft/brainy/types/augmentations' + * + * // āœ… New way (v3.x): + * import { BrainyAugmentation } from '@soulcraft/brainy' + */ export type IDialogAugmentation = BrainyAugmentation + +/** + * @deprecated Use BrainyAugmentation from '../augmentations/brainyAugmentation.js' instead + * + * @example + * // āŒ Old way (v2.x): + * import { IActivationAugmentation } from '@soulcraft/brainy/types/augmentations' + * + * // āœ… New way (v3.x): + * import { BrainyAugmentation } from '@soulcraft/brainy' + */ export type IActivationAugmentation = BrainyAugmentation + +/** + * @deprecated Use BrainyAugmentation from '../augmentations/brainyAugmentation.js' instead + * + * @example + * // āŒ Old way (v2.x): + * import { ISynapseAugmentation } from '@soulcraft/brainy/types/augmentations' + * + * // āœ… New way (v3.x): + * import { BrainyAugmentation } from '@soulcraft/brainy' + */ export type ISynapseAugmentation = BrainyAugmentation + +/** + * @deprecated WebSocket support is now built into BrainyAugmentation interface + * + * @example + * // āŒ Old way (v2.x): + * import { IWebSocketSupport } from '@soulcraft/brainy/types/augmentations' + * class MyAugmentation implements IWebSocketSupport { ... } + * + * // āœ… New way (v3.x): + * import { BrainyAugmentation } from '@soulcraft/brainy' + * class MyAugmentation implements BrainyAugmentation { + * // WebSocket functionality is now part of the unified interface + * } + */ export interface IWebSocketSupport {} \ No newline at end of file