From 35b9d7ef43f6b974e152405f8e46c7c98053ba7b Mon Sep 17 00:00:00 2001 From: David Snelling Date: Mon, 15 Jun 2026 11:11:21 -0700 Subject: [PATCH] refactor(8.0)!: remove orphaned zero-config subsystem + dead cloud/progressive-init storage vestige MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The old config-generation subsystem (src/config/ + autoConfiguration.ts) was superseded during the 8.0 rework and never wired into init(): it emitted settings for a partitioning subsystem that no longer exists and probed deleted cloud env vars. The live zero-config path is inline — recall preset → HNSW knobs, storage auto-detect, auto persistMode, container-memory-aware cache sizing. The storage progressive-init / cloud-detection cluster was equally dead after the cloud adapters were dropped: isCloudStorage() is permanently false (no overriders), scheduleBackgroundInit/runBackgroundInit were never called (the latter an empty body), initMode was never assigned, and Brainy.isFullyInitialized()/ awaitBackgroundInit() were always-trivial with zero callers. scheduleCountPersist() collapses to its only-ever-taken immediate write-through path. Removed: - src/config/{index,zeroConfig,storageAutoConfig,modelAutoConfig,sharedConfigManager}.ts - src/utils/autoConfiguration.ts + the inert BrainyZeroConfig export - Brainy.isFullyInitialized()/awaitBackgroundInit() (+ BrainyInterface decls) - InitMode type, isCloudStorage/detectCloudEnvironment/resolveInitMode, scheduleBackgroundInit/runBackgroundInit/ensureValidatedForWrite and their state - Dead cloud env-var probes (K_SERVICE/K_REVISION/AWS_LAMBDA_FUNCTION_NAME/ FUNCTIONS_TARGET/AZURE_FUNCTIONS_ENVIRONMENT) Kept (verified live): production-detection logging (environment.ts), container- memory cache sizing (memoryDetection/paramValidation), on-disk hash bucketing (sharding.ts). Docs: scrubbed deleted-subsystem references (JS quantization knobs, cloud/OPFS adapters, partitioning, old zero-config API) across 14 files; deleted two wholly- obsolete feature docs (complete-feature-list, v3-features); rewrote architecture/zero-config for 8.0. ~3,700 LOC removed. Build clean; 1392 unit + 24 db-mvcc green. --- README.md | 3 +- docs/PERFORMANCE.md | 3 +- docs/SCALING.md | 23 +- docs/api/README.md | 3 +- docs/architecture/noun-verb-taxonomy.md | 15 +- docs/architecture/overview.md | 2 +- docs/architecture/zero-config.md | 813 +++------------------ docs/concepts/multi-process.md | 11 +- docs/concepts/storage-adapters.md | 2 +- docs/features/complete-feature-list.md | 414 ----------- docs/features/v3-features.md | 242 ------ docs/guides/framework-integration.md | 539 ++++++-------- docs/guides/import-flow.md | 4 +- docs/guides/installation.md | 2 +- docs/guides/quick-start.md | 2 +- docs/guides/schema-migrations.md | 2 +- docs/guides/vue-integration.md | 524 ++++++------- docs/vfs/README.md | 3 +- src/brainy.ts | 96 +-- src/config/index.ts | 54 -- src/config/modelAutoConfig.ts | 71 -- src/config/sharedConfigManager.ts | 266 ------- src/config/storageAutoConfig.ts | 113 --- src/config/zeroConfig.ts | 354 --------- src/index.ts | 5 - src/storage/adapters/baseStorageAdapter.ts | 343 +-------- src/types/brainyInterface.ts | 11 - src/utils/autoConfiguration.ts | 428 ----------- 28 files changed, 596 insertions(+), 3752 deletions(-) delete mode 100644 docs/features/complete-feature-list.md delete mode 100644 docs/features/v3-features.md delete mode 100644 src/config/index.ts delete mode 100644 src/config/modelAutoConfig.ts delete mode 100644 src/config/sharedConfigManager.ts delete mode 100644 src/config/storageAutoConfig.ts delete mode 100644 src/config/zeroConfig.ts delete mode 100644 src/utils/autoConfiguration.ts diff --git a/README.md b/README.md index 7597a680..56ee8b86 100644 --- a/README.md +++ b/README.md @@ -428,8 +428,7 @@ brainy inspect health /data/brain See [the multi-process model](docs/concepts/multi-process.md) and the [inspection guide](docs/guides/inspection.md) for the full story, including -stale-lock detection, the cross-process flush RPC, and what's not yet -enforced on cloud storage backends. +stale-lock detection and the cross-process flush RPC. ## Contributing diff --git a/docs/PERFORMANCE.md b/docs/PERFORMANCE.md index d11da2f1..0165c1e3 100644 --- a/docs/PERFORMANCE.md +++ b/docs/PERFORMANCE.md @@ -391,13 +391,12 @@ await brain.init() // Instant (0-10ms) ### Vector Index Tuning Knobs -Brainy 8.0 exposes exactly three knobs on `config.vector`: +Brainy 8.0 exposes two knobs on `config.vector`: ```javascript const brain = new Brainy({ vector: { recall: 'fast', // 'fast' | 'balanced' | 'accurate' - quantization: { bits: 8 }, // 4 | 8 (SQ4 / SQ8) persistMode: 'deferred' // 'immediate' | 'deferred' } }) diff --git a/docs/SCALING.md b/docs/SCALING.md index dd588006..681c54b5 100644 --- a/docs/SCALING.md +++ b/docs/SCALING.md @@ -35,10 +35,9 @@ Brainy 8.0 is a **single-node library**. There is no cluster, no peer discovery, The three knobs that matter most: 1. **`config.vector.recall`** — `'fast'`, `'balanced'`, or `'accurate'` (default `'balanced'`) -2. **`config.vector.quantization`** — `{ bits: 4 | 8 }` for memory savings on the open-core JS vector index -3. **`config.vector.persistMode`** — `'immediate'` for durability, `'deferred'` for throughput +2. **`config.vector.persistMode`** — `'immediate'` for durability, `'deferred'` for throughput -The native vector provider (via the optional `@soulcraft/cortex` package) extends this with a higher-performing index when installed. +The native vector provider (via the optional `@soulcraft/cortex` package) extends this with a higher-performing index — and its own at-scale acceleration such as on-disk compressed indexing — when installed. ## Storage Configurations @@ -95,7 +94,6 @@ const brain = new Brainy({ storage: { type: 'filesystem', rootDirectory: '/var/lib/brainy' }, vector: { recall: 'fast', // Trade recall for latency - quantization: { bits: 8 }, // SQ8 quantization persistMode: 'deferred' // Batch persistence } }) @@ -142,8 +140,7 @@ Your service layer handles routing and isolation; Brainy stays simple. const brain = new Brainy({ storage: { type: 'filesystem', rootDirectory: '/var/lib/brainy' }, vector: { - recall: 'accurate', - quantization: { bits: 8 } + recall: 'accurate' } }) ``` @@ -153,7 +150,6 @@ const brain = new Brainy({ | Setting | Values | When to change | |---------|--------|----------------| | `vector.recall` | `'fast'` / `'balanced'` / `'accurate'` | Trade recall for latency | -| `vector.quantization.bits` | `4` / `8` | Smaller index, lower memory | | `vector.persistMode` | `'immediate'` / `'deferred'` | Throughput vs. durability | | `storage.cache.maxSize` | integer | Hot-path read cache size | | `storage.cache.ttl` | ms | Cache freshness | @@ -174,14 +170,13 @@ const stats = await brain.stats() ### Issue: Slow queries 1. Switch to `vector.recall: 'fast'` -2. Enable SQ8 quantization -3. Increase the read cache (`storage.cache.maxSize`) -4. Consider the optional native vector provider via `@soulcraft/cortex` +2. Increase the read cache (`storage.cache.maxSize`) +3. Consider the optional native vector provider via `@soulcraft/cortex` ### Issue: Memory pressure -1. Enable `vector.quantization: { bits: 4 }` or `{ bits: 8 }` -2. Reduce `storage.cache.maxSize` -3. Move to `vector.persistMode: 'deferred'` to batch writes +1. Reduce `storage.cache.maxSize` +2. Move to `vector.persistMode: 'deferred'` to batch writes +3. Consider the optional native vector provider via `@soulcraft/cortex` for at-scale index acceleration ### Issue: Slow startup after a crash 1. Use `vector.persistMode: 'immediate'` so the index file stays in sync with storage @@ -198,5 +193,5 @@ const stats = await brain.stats() - Brainy 8.0 is a **library**, not a cluster - Storage adapters: `filesystem`, `memory`, `auto` -- Vector tuning: `recall`, `quantization`, `persistMode` +- Vector tuning: `recall`, `persistMode` - Backup is an operator-layer concern — snapshot `rootDirectory` diff --git a/docs/api/README.md b/docs/api/README.md index 75fc615c..e4b2b55c 100644 --- a/docs/api/README.md +++ b/docs/api/README.md @@ -1441,10 +1441,9 @@ const brain = new Brainy({ rootDirectory: './brainy-data' }, - // Vector index configuration (3 knobs) + // Vector index configuration (2 knobs) vector: { recall: 'balanced', // 'fast' | 'balanced' | 'accurate' - quantization: { bits: 8 }, // 4 | 8 (SQ4 / SQ8) persistMode: 'immediate' // 'immediate' | 'deferred' }, diff --git a/docs/architecture/noun-verb-taxonomy.md b/docs/architecture/noun-verb-taxonomy.md index 7cb7c16d..d896016d 100644 --- a/docs/architecture/noun-verb-taxonomy.md +++ b/docs/architecture/noun-verb-taxonomy.md @@ -47,16 +47,13 @@ await visualizationAugmentation.graphRelationships(authors) #### 2. **Data Portability** ```typescript -// Export from one Brainy instance -const data = await brain1.export() +// Snapshot from one Brainy instance, restore into another — +// types are universally understood +const pin = brain1.now() +await pin.persist('/snapshots/brain1') +await pin.release() -// Import to another—types are universally understood -await brain2.import(data) - -// Or sync between different storage backends -const cloudBrain = new Brainy({ storage: 's3' }) -const localBrain = new Brainy({ storage: 'filesystem' }) -await cloudBrain.sync(localBrain) // Types match perfectly +const brain2 = await Brainy.load('/snapshots/brain1') // Types match perfectly ``` #### 3. **AI Model Compatibility** diff --git a/docs/architecture/overview.md b/docs/architecture/overview.md index 796c0cc7..3f77e133 100644 --- a/docs/architecture/overview.md +++ b/docs/architecture/overview.md @@ -45,7 +45,7 @@ brainy-data/ ### Vector Index Pluggable vector index (`VectorIndexProvider`) for efficient nearest-neighbor search. The default JS implementation, `JsHnswVectorIndex`, uses a hierarchical graph: - **Performance**: O(log n) search complexity -- **Memory Efficient**: SQ4/SQ8 scalar quantization support +- **Configurable recall**: `fast` / `balanced` / `accurate` presets trade recall for latency - **Scalable**: Handles millions of vectors per process - **Persistent**: Serializable to storage - **Swappable**: Replace with a native implementation (such as `@soulcraft/cortex`) via the plugin system without changing application code diff --git a/docs/architecture/zero-config.md b/docs/architecture/zero-config.md index 1aa5a7c9..b72d1ee0 100644 --- a/docs/architecture/zero-config.md +++ b/docs/architecture/zero-config.md @@ -13,776 +13,145 @@ next: # Zero Configuration & Auto-Adaptation -> **Status (8.0):** This document predates Brainy 8.0 and needs a rewrite before -> republication. Large parts describe storage backends and environments that 8.0 -> removed (browser/OPFS/IndexedDB, edge KV, S3) or features that were never built -> (model auto-selection, workload detection). Brainy 8.0 is server-only (Node.js/Bun) -> with two storage adapters: `memory` and `filesystem` — see -> [Storage Adapters](../concepts/storage-adapters.md) for the accurate story. -> Basic zero-config (`new Brainy()` with auto-selected storage) works as described. +> **"Zero config by default, fully tunable when you need it."** Construct a +> `Brainy()` with no options and it picks sensible, environment-aware defaults. +> Every default below is overridable through the constructor — see the +> [API Reference](../api/README.md#configuration). ## Overview -Brainy is designed with **"Zero Config by Default, Infinite Tunability"** philosophy. It automatically detects your environment, adapts to available resources, learns from usage patterns, and optimizes itself for your specific workload—all without any configuration. +Brainy 8.0 is server-only (Node.js 22+ / Bun). With no configuration it: -## Zero Configuration Magic +- selects a storage adapter from the runtime, +- initializes the embedding model (all-MiniLM-L6-v2, 384 dimensions), +- builds and maintains the metadata, graph, and vector indexes, +- sizes its caches and write buffers to the detected memory budget, +- chooses a persistence mode that matches the storage backend, and +- quiets its own logging when it detects a production environment. -### Instant Start +There is no public config-generation function — adaptation happens inside the +constructor and `init()`. + +## Instant Start ```typescript -import { Brainy } from 'brainy' +import { Brainy } from '@soulcraft/brainy' // That's it. No config needed. const brain = new Brainy() await brain.init() -// Brainy automatically: -// ✓ Detects environment (Node.js, Browser, Edge, Deno) -// ✓ Chooses optimal storage (FileSystem, OPFS, Memory) -// ✓ Downloads required models (if needed) -// ✓ Configures vector dimensions (384 optimal) -// ✓ Sets up indexing strategies -// ✓ Enables appropriate augmentations -// ✓ Configures caching layers -// ✓ Optimizes for your hardware +await brain.add({ data: 'First entity', type: 'concept' }) +const results = await brain.find('first') ``` -### Environment Detection ✅ Available +## What Auto-Adaptation Covers -Brainy automatically detects and adapts to your runtime: +### 1. Storage auto-detection + +With no `storage` option, Brainy uses `type: 'auto'`: + +- **Filesystem** when running on a runtime with a writable Node filesystem and a + resolvable root directory. This is the default for typical Node/Bun servers and + persists across restarts. +- **In-memory** otherwise (no filesystem access, or an explicit memory request). + Fast, zero I/O, discarded on process exit — ideal for tests and ephemeral + caches. + +8.0 ships exactly two storage adapters — `memory` and `filesystem` — plus the +`auto` selector that resolves to one of them. See +[Storage Adapters](../concepts/storage-adapters.md) for the full contract. ```typescript -// Brainy's environment detection -const environment = { - // Runtime detection - isNode: typeof process !== 'undefined', - isBrowser: typeof window !== 'undefined', - isDeno: typeof Deno !== 'undefined', - isEdge: typeof EdgeRuntime !== 'undefined', - isWebWorker: typeof WorkerGlobalScope !== 'undefined', - - // Capability detection - hasFileSystem: /* auto-detected */, - hasIndexedDB: /* auto-detected */, - hasOPFS: /* auto-detected */, - hasWebGPU: /* auto-detected */, - hasWASM: /* auto-detected */, - - // Resource detection - cpuCores: /* auto-detected */, - memory: /* auto-detected */, - storage: /* auto-detected */ -} -``` - -## Auto-Adaptive Storage ✅ Available - -> **Current**: Brainy automatically selects the best storage adapter for your environment. - -### Storage Selection Logic - -```typescript -// Brainy's intelligent storage selection -async function autoSelectStorage() { - // Server environments - if (environment.isNode) { - if (await hasWritePermission('./data')) { - return 'filesystem' // Best for servers - } else if (process.env.S3_BUCKET) { - return 's3' // Cloud deployment - } else { - return 'memory' // Fallback for restricted environments - } - } - - // Browser environments - if (environment.isBrowser) { - if (await navigator.storage.estimate() > 1GB) { - return 'opfs' // Best for modern browsers - } else if (indexedDB) { - return 'indexeddb' // Fallback for older browsers - } else { - return 'memory' // In-memory for restricted contexts - } - } - - // Edge environments - if (environment.isEdge) { - return 'kv' // Use edge KV stores (Cloudflare, Vercel) - } -} -``` - -### Storage Migration - -Brainy seamlessly migrates between storage types: - -```typescript -// Start with memory storage (development) -const brain = new Brainy() // Auto-selects memory - -// Later, migrate to production storage -await brain.migrate({ - to: 'filesystem', - path: './production-data' +// Explicit override when you want a specific root +const brain = new Brainy({ + storage: { type: 'filesystem', rootDirectory: './brainy-data' } }) -// All data seamlessly transferred ``` -## Learning & Optimization 🚧 Coming Soon +### 2. HNSW quality from the `recall` preset -> **Note**: These features are planned for Q2 2025. Currently, Brainy uses static optimizations. - -### Query Pattern Learning 🚧 Planned - -Brainy learns from your query patterns and optimizes accordingly: +Vector-index quality comes from a single preset rather than hand-tuned graph +parameters. `config.vector.recall` accepts `'fast'`, `'balanced'`, or +`'accurate'` and defaults to `'balanced'`. The preset maps internally to the +HNSW construction and search parameters (`M` / `efConstruction` / `efSearch`), +so you trade recall against latency with one knob instead of three. ```typescript -// Brainy observes query patterns -class QueryPatternLearner { - analyze(queries: Query[]) { - return { - // Frequency analysis - mostCommonFields: this.getTopFields(queries), - avgResultSize: this.getAvgSize(queries), - temporalPatterns: this.getTimePatterns(queries), - - // Relationship analysis - commonTraversals: this.getGraphPatterns(queries), - typicalDepth: this.getAvgDepth(queries), - - // Performance analysis - slowQueries: this.getSlowQueries(queries), - cacheability: this.getCacheability(queries) - } - } -} - -// Automatic optimizations based on learning: -// - Creates indexes for frequently queried fields -// - Pre-computes common graph traversals -// - Adjusts cache sizes based on working set -// - Optimizes vector search parameters +const brain = new Brainy({ + vector: { recall: 'fast' } // favor latency over recall +}) ``` -### Auto-Indexing 🚧 Planned +The default JS index is `JsHnswVectorIndex`. An optional native acceleration +provider (the `@soulcraft/cortex` package) can replace it with a +higher-performing implementation; the public knobs stay the same. Quantization +and other index-internal acceleration are the native provider's concern, not a +Brainy configuration option. -Brainy automatically creates indexes based on usage: +### 3. Persistence mode follows the backend + +`config.vector.persistMode` accepts `'immediate'` or `'deferred'`. Left unset, +Brainy chooses for you: + +- **Immediate** on filesystem storage, so the index file stays in lock-step with + the data and survives a crash. +- **Deferred** on in-memory storage, where there is nothing durable to sync to, + so writes are batched for throughput. ```typescript -// No manual index configuration needed -await brain.find({ where: { category: "tech" } }) // First query -// Brainy notices 'category' field usage - -await brain.find({ where: { category: "science" } }) // Second query -// Pattern detected - auto-creates category index - -await brain.find({ where: { category: "tech" } }) // Third query -// Now using index - 100x faster! +const brain = new Brainy({ + vector: { persistMode: 'deferred' } // batch persistence for write-heavy loads +}) ``` -### Adaptive Caching 🚧 Planned +### 4. Memory-aware cache and buffer sizing -Cache strategies adapt to your access patterns: +Brainy reads the container's memory budget — `CLOUD_RUN_MEMORY`, `MEMORY_LIMIT`, +or the cgroup memory limit when running in a container — and sizes its read +caches and write buffers to fit. On a small instance it stays conservative; on a +large one it uses more of the available headroom. Query-result limits are capped +against the same budget (roughly 25 KB per result) to keep a single oversized +query from exhausting memory. + +You can pin the cache explicitly: ```typescript -class AdaptiveCache { - async adapt(metrics: AccessMetrics) { - if (metrics.hitRate < 0.3) { - // Low hit rate - switch strategy - this.strategy = 'lfu' // Least Frequently Used - } else if (metrics.workingSet > this.size) { - // Working set too large - increase size - this.size = Math.min(metrics.workingSet * 1.5, maxMemory) - } else if (metrics.temporalLocality > 0.8) { - // High temporal locality - use time-based eviction - this.strategy = 'ttl' - this.ttl = metrics.avgAccessInterval * 2 - } - } -} +const brain = new Brainy({ + cache: { maxSize: 10000, ttl: 3_600_000 } +}) ``` -## Performance Auto-Scaling 🚧 Coming Soon +### 5. Logging quiets in production -### Dynamic Batch Sizing - -Brainy adjusts batch sizes based on system load: - -```typescript -class DynamicBatcher { - calculateOptimalBatch() { - const cpuUsage = process.cpuUsage() - const memoryUsage = process.memoryUsage() - - if (cpuUsage < 30 && memoryUsage < 50) { - return 1000 // System idle - large batches - } else if (cpuUsage < 60 && memoryUsage < 70) { - return 100 // Moderate load - medium batches - } else { - return 10 // High load - small batches - } - } -} - -// Automatically applied during bulk operations -for (const item of millionItems) { - await brain.add(item) // Internally batched optimally -} -``` - -### Memory Management - -Automatic memory pressure handling: - -```typescript -class MemoryManager { - async handlePressure() { - const usage = process.memoryUsage() - const available = os.freemem() - - if (available < 100 * 1024 * 1024) { // Less than 100MB free - // Emergency mode - await this.flushCaches() - await this.compactIndexes() - await this.offloadToDisk() - } else if (usage.heapUsed / usage.heapTotal > 0.9) { - // Preventive mode - await this.reduceCacheSizes() - await this.pauseBackgroundTasks() - } - } -} -``` - -### Connection Pooling - -Automatic connection management for storage backends: - -```typescript -class ConnectionPool { - async getOptimalPoolSize() { - // Adapts based on workload - const metrics = await this.getMetrics() - - if (metrics.waitTime > 100) { - // Queries waiting - increase pool - this.size = Math.min(this.size * 1.5, this.maxSize) - } else if (metrics.idleConnections > this.size * 0.5) { - // Too many idle - decrease pool - this.size = Math.max(this.size * 0.7, this.minSize) - } - - return this.size - } -} -``` - -## Model Auto-Selection - -### Embedding Model Selection - -Brainy chooses the best embedding model for your use case: - -```typescript -async function autoSelectModel(data: Sample[]) { - const analysis = { - languages: detectLanguages(data), - domainSpecific: detectDomain(data), - averageLength: getAvgLength(data), - requiresMultilingual: languages.length > 1 - } - - if (analysis.requiresMultilingual) { - return 'multilingual-e5-base' // Handles 100+ languages - } else if (analysis.domainSpecific === 'code') { - return 'codebert-base' // Optimized for code - } else if (analysis.averageLength > 512) { - return 'all-mpnet-base-v2' // Better for long text - } else { - return 'all-MiniLM-L6-v2' // Fast and efficient default - } -} -``` - -### Model Downloading - -Models are automatically downloaded when needed: - -```typescript -// First use - model auto-downloads -const brain = new Brainy() -await brain.init() // Downloads model if not cached - -// Intelligent model caching -const modelCache = { - location: process.env.MODEL_CACHE || '~/.brainy/models', - maxSize: 5 * 1024 * 1024 * 1024, // 5GB max - strategy: 'lru', // Least recently used eviction - - // CDN selection based on location - cdn: await selectFastestCDN([ - 'https://cdn.brainy.io', - 'https://brainy.b-cdn.net', - 'https://models.huggingface.co' - ]) -} -``` - -## Workload Detection - -### Pattern Recognition - -Brainy identifies your workload type and optimizes: - -```typescript -enum WorkloadType { - OLTP = 'oltp', // Many small transactions - OLAP = 'olap', // Analytical queries - STREAMING = 'streaming', // Real-time ingestion - BATCH = 'batch', // Bulk processing - HYBRID = 'hybrid' // Mixed workload -} - -class WorkloadDetector { - detect(metrics: OperationMetrics): WorkloadType { - if (metrics.writesPerSecond > 1000 && metrics.avgWriteSize < 1024) { - return WorkloadType.STREAMING - } else if (metrics.avgQueryComplexity > 0.8 && metrics.avgResultSize > 10000) { - return WorkloadType.OLAP - } else if (metrics.batchOperations > metrics.singleOperations) { - return WorkloadType.BATCH - } else if (metrics.writeReadRatio > 0.3 && metrics.writeReadRatio < 0.7) { - return WorkloadType.HYBRID - } else { - return WorkloadType.OLTP - } - } -} -``` - -### Optimization Strategies - -Different optimizations for different workloads: - -```typescript -class WorkloadOptimizer { - optimize(workload: WorkloadType) { - switch (workload) { - case WorkloadType.STREAMING: - return { - entityRegistry: true, // Deduplication - batchSize: 1000, - walEnabled: true, - cacheSize: 'small', - indexStrategy: 'lazy' - } - - case WorkloadType.OLAP: - return { - entityRegistry: false, - batchSize: 10000, - walEnabled: false, - cacheSize: 'large', - indexStrategy: 'eager', - parallelQueries: true - } - - case WorkloadType.BATCH: - return { - entityRegistry: false, - batchSize: 50000, - walEnabled: false, - cacheSize: 'minimal', - indexStrategy: 'deferred' - } - - default: - return this.defaultConfig - } - } -} -``` - -## Hardware Adaptation 🚧 Coming Soon - -> **Note**: GPU acceleration and hardware optimization planned for Q3 2025. - -### CPU Optimization - -Adapts to available CPU resources: - -```typescript -class CPUAdapter { - async optimize() { - const cores = os.cpus().length - const type = os.cpus()[0].model - - // Parallel processing based on cores - this.parallelism = Math.max(1, cores - 1) // Leave one core free - - // SIMD detection for vector operations - if (type.includes('Intel') || type.includes('AMD')) { - this.enableSIMD = await checkSIMDSupport() - } - - // Thread pool sizing - this.threadPoolSize = cores * 2 // Optimal for I/O bound - - // Vector search optimization - if (cores >= 8) { - this.hnswConstruction = 200 // Higher quality index - this.hnswSearch = 100 // More accurate search - } else { - this.hnswConstruction = 100 // Balanced - this.hnswSearch = 50 // Faster search - } - } -} -``` - -### Memory Adaptation - -Intelligent memory allocation: - -```typescript -class MemoryAdapter { - async configure() { - const totalMemory = os.totalmem() - const availableMemory = os.freemem() - - // Allocate based on available memory - const allocation = { - cache: Math.min(availableMemory * 0.25, 2 * GB), - vectors: Math.min(availableMemory * 0.30, 4 * GB), - indexes: Math.min(availableMemory * 0.20, 2 * GB), - working: Math.min(availableMemory * 0.25, 2 * GB) - } - - // Adjust for low memory systems - if (totalMemory < 4 * GB) { - allocation.cache *= 0.5 - allocation.vectors *= 0.7 - this.enableSwapping = true - } - - return allocation - } -} -``` - -### GPU Acceleration - -Automatic GPU detection and utilization: - -```typescript -class GPUAdapter { - async detect() { - // WebGPU in browsers - if (navigator?.gpu) { - const adapter = await navigator.gpu.requestAdapter() - return { - available: true, - type: 'webgpu', - memory: adapter.limits.maxBufferSize, - compute: adapter.limits.maxComputeWorkgroupsPerDimension - } - } - - // CUDA in Node.js - if (process.platform === 'linux' || process.platform === 'win32') { - const hasCuda = await checkCudaSupport() - if (hasCuda) { - return { - available: true, - type: 'cuda', - memory: await getCudaMemory(), - compute: await getCudaCores() - } - } - } - - return { available: false } - } - - async optimize(gpu: GPUInfo) { - if (gpu.available) { - // Offload vector operations to GPU - this.vectorOps = 'gpu' - this.embeddingGeneration = 'gpu' - this.matrixMultiplication = 'gpu' - - // Larger batch sizes for GPU - this.batchSize = gpu.memory > 8 * GB ? 10000 : 1000 - } - } -} -``` - -## Network Adaptation - -### Bandwidth Detection - -Optimizes for available network bandwidth: - -```typescript -class NetworkAdapter { - async measureBandwidth() { - const testSize = 1 * MB - const start = Date.now() - await this.transfer(testSize) - const duration = Date.now() - start - - const bandwidth = (testSize / duration) * 1000 // bytes/sec - - if (bandwidth < 1 * MB) { - // Low bandwidth - optimize - this.compression = 'aggressive' - this.batchTransfers = true - this.cacheRemote = true - } else if (bandwidth > 100 * MB) { - // High bandwidth - this.compression = 'minimal' - this.parallelTransfers = true - } - } -} -``` - -### Latency Optimization - -Adapts to network latency: - -```typescript -class LatencyOptimizer { - async optimize() { - const latency = await this.measureLatency() - - if (latency > 100) { // High latency - // Batch operations - this.minBatchSize = 100 - - // Aggressive prefetching - this.prefetchDepth = 3 - - // Local caching - this.cacheStrategy = 'aggressive' - - // Connection pooling - this.connectionPool = Math.min(latency / 10, 50) - } - } -} -``` - -## Cloud Provider Detection 🚧 Coming Soon - -> **Note**: Cloud provider auto-detection planned for Q3 2025. - -### Automatic Cloud Optimization - -Detects and optimizes for cloud providers: - -```typescript -class CloudDetector { - async detect() { - // AWS Detection - if (process.env.AWS_REGION || await canReachMetadata('169.254.169.254')) { - return { - provider: 'aws', - instance: await getEC2InstanceType(), - region: process.env.AWS_REGION, - services: { - storage: 's3', - cache: 'elasticache', - compute: 'lambda' - } - } - } - - // Google Cloud Detection - if (process.env.GOOGLE_CLOUD_PROJECT || await canReachMetadata('metadata.google.internal')) { - return { - provider: 'gcp', - instance: await getGCEInstanceType(), - region: process.env.GOOGLE_CLOUD_REGION, - services: { - storage: 'gcs', - cache: 'memorystore', - compute: 'cloud-run' - } - } - } - - // Vercel Edge Detection - if (process.env.VERCEL) { - return { - provider: 'vercel', - region: process.env.VERCEL_REGION, - services: { - storage: 'vercel-kv', - cache: 'edge-config', - compute: 'edge-runtime' - } - } - } - } -} -``` - -## Development vs Production - -### Automatic Environment Detection - -```typescript -class EnvironmentDetector { - detect() { - const indicators = { - // Development indicators - isDevelopment: - process.env.NODE_ENV === 'development' || - process.env.DEBUG || - process.argv.includes('--dev') || - isLocalhost() || - hasDevTools(), - - // Test indicators - isTest: - process.env.NODE_ENV === 'test' || - process.env.CI || - isTestRunner(), - - // Production indicators - isProduction: - process.env.NODE_ENV === 'production' || - process.env.VERCEL || - process.env.NETLIFY || - !isLocalhost() - } - - return indicators - } -} - -// Different defaults for different environments -const config = environment.isProduction ? { - storage: 'filesystem', - wal: true, - monitoring: true, - compression: true, - caching: 'aggressive' -} : { - storage: 'memory', - wal: false, - monitoring: false, - compression: false, - caching: 'minimal' -} -``` - -## Error Recovery - -### Automatic Fallbacks - -Brainy automatically recovers from errors: - -```typescript -class AutoRecovery { - async handleStorageFailure() { - try { - await this.primaryStorage.write(data) - } catch (error) { - console.warn('Primary storage failed, trying fallback') - - // Try secondary storage - if (this.secondaryStorage) { - await this.secondaryStorage.write(data) - } else { - // Fall back to memory - await this.memoryStorage.write(data) - - // Schedule retry - this.scheduleRetry(data) - } - } - } - - async handleModelFailure() { - try { - return await this.primaryModel.embed(text) - } catch (error) { - // Fall back to simpler model - return await this.fallbackModel.embed(text) - } - } -} -``` +Brainy detects production-style environments (for example `NODE_ENV` set to a +non-development value) and reduces its own log verbosity automatically. This is +logging-only behavior — it does not change indexing, storage, or query results. ## Configuration Override -While zero-config is default, you can override when needed: +Zero-config is the default, not a ceiling. Every adaptive decision above has an +explicit constructor option: ```typescript -// Explicit configuration when needed const brain = new Brainy({ - // Override auto-detection - storage: { - type: 'filesystem', - path: '/custom/path' + storage: { type: 'filesystem', rootDirectory: '/var/lib/brainy' }, + vector: { + recall: 'accurate', + persistMode: 'immediate' }, - - // Override auto-optimization - optimization: { - autoIndex: false, - autoCache: false, - autoBatch: false - }, - - // Override auto-scaling - scaling: { - maxMemory: 2 * GB, - maxConnections: 100, - maxBatchSize: 1000 - } -}) -``` - -## Monitoring Auto-Adaptation - -Brainy provides visibility into its auto-adaptation: - -```typescript -brain.on('adaptation', (event) => { - console.log(`Brainy adapted: ${event.type}`) - console.log(`Reason: ${event.reason}`) - console.log(`Before: ${JSON.stringify(event.before)}`) - console.log(`After: ${JSON.stringify(event.after)}`) + cache: { maxSize: 50000, ttl: 600_000 } }) -// Example events: -// - Index created for frequently queried field -// - Cache strategy changed due to low hit rate -// - Batch size increased due to high throughput -// - Storage migrated due to space constraints -// - Model switched due to multilingual content +await brain.init() ``` -## Conclusion - -Brainy's zero-configuration and auto-adaptation capabilities mean you can focus on your application logic while Brainy handles: - -- Environment detection and optimization -- Storage selection and migration -- Performance tuning and scaling -- Resource management -- Error recovery -- Workload optimization - -Just create a Brainy instance and start using it. Brainy will learn, adapt, and optimize itself for your specific use case—no configuration required. +See the [API Reference](../api/README.md#configuration) for the complete option +list. ## See Also - [Architecture Overview](./overview.md) -- [Storage Architecture](./storage.md) -- [Performance Guide](../guides/performance.md) -- [Augmentations System](./augmentations.md) \ No newline at end of file +- [Storage Adapters](../concepts/storage-adapters.md) +- [Scaling Guide](../SCALING.md) +- [API Reference](../api/README.md) diff --git a/docs/concepts/multi-process.md b/docs/concepts/multi-process.md index c62cc575..bc473710 100644 --- a/docs/concepts/multi-process.md +++ b/docs/concepts/multi-process.md @@ -135,11 +135,12 @@ The CLI `brainy inspect` subcommands all do this for you by default ## What's not enforced (yet) -- **Cloud storage backends** (S3, GCS, R2, Azure) do not currently enforce - multi-process locking. Two processes pointing at the same bucket can both - succeed at `init()` in writer mode and clobber each other's writes. A - best-effort warning is logged in writer mode against a non-filesystem - backend. Lock semantics for cloud backends will land in a future release. +- **Non-filesystem backends** are out of scope in 8.0, which ships only the + filesystem and memory adapters. A custom `BaseStorage` subclass that is not + filesystem-backed does not enforce multi-process locking by default: two + processes can both succeed at `init()` in writer mode and clobber each + other's writes. A best-effort warning is logged in writer mode against a + non-filesystem backend. - **Long-running readers** do not automatically pick up new Cortex segments the writer publishes. One-shot inspector calls re-open the store and see fresh segments; a reader that stays open for hours sees its column store diff --git a/docs/concepts/storage-adapters.md b/docs/concepts/storage-adapters.md index a398b34c..e0f9b70d 100644 --- a/docs/concepts/storage-adapters.md +++ b/docs/concepts/storage-adapters.md @@ -75,7 +75,7 @@ That's the full ceremony for inheriting multi-process safety. ## When NOT to extend FileSystemStorage -If your storage is **not filesystem-backed** (S3, GCS, R2, Azure, a custom +If your storage is **not filesystem-backed** (a custom network backend), extend `BaseStorage` directly: ```typescript diff --git a/docs/features/complete-feature-list.md b/docs/features/complete-feature-list.md deleted file mode 100644 index 7b10b827..00000000 --- a/docs/features/complete-feature-list.md +++ /dev/null @@ -1,414 +0,0 @@ -# 🚀 Brainy 2.0 - Complete Feature List - -> **The Truth**: Brainy is MORE powerful than previously documented! This is the complete list of ALL implemented features. - -## 🧠 Core Intelligence Engine - -### Triple Intelligence System ✅ -Unified query system that automatically combines: -- **Vector Search**: HNSW-indexed semantic similarity (O(log n) performance) -- **Graph Traversal**: Relationship-based discovery -- **Field Filtering**: Metadata and attribute queries -- **Auto-optimization**: Queries are automatically optimized based on data patterns - -```typescript -// All three intelligences work together automatically -const results = await brain.find({ - like: 'AI research', // Vector search - where: { year: 2024 }, // Metadata filtering - connected: { to: authorId } // Graph traversal -}) -``` - -### Neural Query Understanding ✅ -- **220+ embedded patterns** for query intent detection -- Natural language query processing -- Automatic query type detection -- Query rewriting and optimization - -## 🔧 12+ Production Augmentations - -```typescript -// Full crash recovery, checkpointing, replay -``` - -### 2. Entity Registry ✅ -```typescript -import { EntityRegistryAugmentation } from 'brainy' -// Bloom filter-based deduplication for streaming data -// Handles millions of entities with minimal memory -``` - -### 3. Auto-Register Entities ✅ -```typescript -import { AutoRegisterEntitiesAugmentation } from 'brainy' -// Automatically extracts and registers entities from text -``` - -### 4. Intelligent Verb Scoring ✅ -```typescript -import { IntelligentVerbScoringAugmentation } from 'brainy' -// Multi-factor relationship strength: -// - Semantic similarity -// - Temporal decay -// - Frequency amplification -// - Context awareness -``` - -### 5. Batch Processing ✅ -```typescript -import { BatchProcessingAugmentation } from 'brainy' -// Adaptive batching with backpressure -// Dynamically adjusts batch size based on load -``` - -### 6. Connection Pool ✅ -```typescript -import { ConnectionPoolAugmentation } from 'brainy' -// Auto-scaling connection management -// Optimized for high-concurrency workloads -``` - -### 7. Request Deduplicator ✅ -```typescript -import { RequestDeduplicatorAugmentation } from 'brainy' -// In-flight request deduplication -// 3x performance boost for concurrent operations -``` - -### 8. WebSocket Conduit ✅ -```typescript -import { WebSocketConduitAugmentation } from 'brainy' -// Real-time bidirectional streaming -// Auto-reconnection and heartbeat -``` - -### 9. WebRTC Conduit ✅ -```typescript -import { WebRTCConduitAugmentation } from 'brainy' -// Peer-to-peer data channels -// Direct browser-to-browser communication -``` - -### 10. Memory Storage Optimization ✅ -```typescript -import { MemoryStorageAugmentation } from 'brainy' -// Memory-specific optimizations -// Circular buffers, compression -``` - -### 11. Server Search Conduit ✅ -```typescript -import { ServerSearchConduitAugmentation } from 'brainy' -// Forwards queries to a remote Brainy server -``` - -### 12. Neural Import ✅ -```typescript -import { NeuralImportAugmentation } from 'brainy' -// AI-powered data understanding -// Automatic entity detection and classification -// Relationship discovery -``` - -## 🤖 Neural Import Capabilities (FULLY IMPLEMENTED!) - -```typescript -const neuralImport = new NeuralImport(brain) - -// ALL of these work TODAY: -await neuralImport.neuralImport('data.csv') -await neuralImport.detectEntitiesWithNeuralAnalysis(data) -await neuralImport.detectNounType(entity) -await neuralImport.detectRelationships(entities) -await neuralImport.generateInsights(data) -``` - -### Features: -- **Auto-detects file format** (CSV, JSON, XML, etc.) -- **Identifies entity types** using AI -- **Discovers relationships** between entities -- **Generates insights** about the data -- **Creates optimal graph structure** automatically - -## 🎯 Zero-Config Model Loading Cascade - -Brainy automatically loads models with ZERO configuration required: - -```typescript -const brain = new Brainy() // That's it! -await brain.init() -// Models load automatically from best available source -``` - -### Loading Priority: -1. **Local Cache** (./models) - Instant, no network -2. **CDN** (models.soulcraft.com) - Fast, global [Coming Soon] -3. **GitHub Releases** - Reliable backup -4. **HuggingFace** - Ultimate fallback - -### Key Features: -- **Automatic fallback** if sources fail -- **Model verification** with checksums -- **Offline support** with bundled models -- **No environment variables needed** -- **Works in all environments** (Node, Browser, Workers) - -## 🏢 Operation Modes - -Run many reader processes against one shared on-disk store with a single writer. - -### Reader Mode ✅ -```typescript -const brain = new Brainy({ mode: 'reader' }) -// Optimized for read-heavy workloads -// 80% cache ratio, aggressive prefetch -// 1 hour TTL, minimal writes -``` - -### Writer Mode ✅ -```typescript -const brain = new Brainy({ mode: 'writer' }) -// Optimized for write-heavy workloads -// Large write buffers, batch writes -// Minimal caching, fast ingestion -``` - -### Hybrid Mode ✅ -```typescript -const brain = new Brainy({ mode: 'hybrid' }) -// Balanced for mixed workloads -// Adaptive caching and batching -``` - -## 💾 Advanced Caching System - -### 3-Level Cache Architecture ✅ -```typescript -const cacheConfig = { - hotCache: { - size: 1000, // L1 - RAM - ttl: 60000 // 1 minute - }, - warmCache: { - size: 10000, // L2 - Fast storage - ttl: 300000 // 5 minutes - }, - coldCache: { - size: 100000, // L3 - Persistent - ttl: null // No expiry - } -} -``` - -### Cache Features: -- **Automatic promotion/demotion** between levels -- **LRU eviction** within each level -- **Compression** for cold cache -- **Statistics tracking** for optimization - -## 📊 Comprehensive Statistics - -```typescript -const stats = await brain.getStats() -// Returns detailed metrics: -{ - nouns: { - count, created, updated, deleted, - size, avgSize - }, - verbs: { - count, created, types, - weights: { min, max, avg } - }, - vectors: { - dimensions: 384, - indexSize, partitions, - avgSearchTime - }, - cache: { - hits, misses, evictions, - hitRate, sizes - }, - performance: { - operations, avgTimes, - p95Latency, p99Latency - }, - storage: { - used, available, - compression, files - }, - throttling: { - delays, rateLimited, - backoffMs, retries - } -} -``` - -## 🚀 GPU Acceleration Support - -```typescript -// Automatic GPU detection -const device = await detectBestDevice() -// Returns: 'cpu' | 'webgpu' | 'cuda' - -// WebGPU in browser (when available) -if (device === 'webgpu') { - // Transformer models use WebGPU automatically -} - -// CUDA in Node.js (future GPU support) -if (device === 'cuda') { - // Future: GPU acceleration for embeddings -} -``` - -## 🔄 Adaptive Systems - -### Adaptive Backpressure ✅ -```typescript -// Automatically adjusts flow based on system load -// Prevents OOM and maintains throughput -``` - -### Adaptive Socket Manager ✅ -```typescript -// Dynamic connection pooling -// Scales connections based on traffic patterns -``` - -### Cache Auto-Configuration ✅ -```typescript -// Sizes cache based on available memory -// Adjusts strategies based on usage patterns -``` - -### S3 Throttling Protection ✅ -```typescript -// Built-in exponential backoff -// Rate limit detection and adaptation -// Automatic retry with jitter -``` - -## 🛠️ Storage Adapters - -All included, auto-selected based on environment: - -### FileSystem Storage ✅ -- Default for Node.js -- Efficient file-based storage -- Automatic directory management - -### Memory Storage ✅ -- Ultra-fast in-memory operations -- Perfect for testing and temporary data -- Circular buffer support - -### OPFS Storage ✅ -- Browser persistent storage -- Survives page refreshes -- Quota management - -### S3 Storage ✅ -- AWS S3 compatible -- Automatic multipart uploads -- Throttling protection -- Batch operations - -## 🎨 Natural Language Processing - -### Built-in Patterns (220+) -- Question types (what, why, how, when, where) -- Temporal queries (yesterday, last week, 2024) -- Comparative queries (better than, similar to) -- Aggregations (count, sum, average) -- Filters (only, except, without) -- Relationships (related to, connected with) - -### Coverage: 94-98% of typical queries! - -## 🔐 Security Features - -### Built-in Security ✅ -- Automatic input sanitization -- SQL injection prevention -- XSS protection for web contexts -- Rate limiting support - -### Encryption Ready ✅ -```typescript -import { crypto } from 'brainy/utils' -// AES-256-GCM encryption utilities -// Key derivation functions -// Secure random generation -``` - -## 🎯 Key Design Principles - -### 1. Zero Configuration -```typescript -const brain = new Brainy() -await brain.init() -// Everything else is automatic! -``` - -### 2. Fixed Dimensions (384) -- **ALWAYS** uses all-MiniLM-L6-v2 model -- **ALWAYS** 384 dimensions -- **NOT** configurable (by design) -- Ensures everything works together - -### 3. Progressive Enhancement -- Starts simple, scales automatically -- Adapts to workload patterns -- Optimizes based on usage - -### 4. Universal Compatibility -- Works in Node.js 18+ -- Works in modern browsers -- Works in Web Workers -- Works in Edge environments - -## 📦 What Ships in Core (MIT Licensed) - -**EVERYTHING** is included in the core package: -- ✅ All engines (vector, graph, field, neural) -- ✅ All augmentations (12+) -- ✅ All storage adapters -- ✅ Reader / writer / hybrid operation modes -- ✅ Complete statistics -- ✅ GPU support -- ✅ No feature limitations -- ✅ No premium tiers -- ✅ 100% MIT licensed - -## 🚀 Quick Start - -```typescript -import { Brainy } from 'brainy' - -// Zero config required! -const brain = new Brainy() -await brain.init() - -// Add data (auto-detects type) -await brain.add('Content here') - -// Search with natural language -const results = await brain.find('related content from last week') - -// Everything else is automatic! -``` - -## 📈 Performance Characteristics - -- **Vector Search**: O(log n) with HNSW indexing -- **Graph Traversal**: O(k) for k-hop queries -- **Field Filtering**: O(1) with metadata index -- **Memory Usage**: ~100MB base + data -- **Embedding Speed**: ~100ms for batch of 10 -- **Query Speed**: <10ms for most queries - -## 🎉 Summary - -Brainy 2.0 is a **complete**, **production-ready** AI database that requires **ZERO configuration**. Every feature listed here is **implemented and working** today. No configuration, no setup, no complexity - just powerful AI capabilities that work out of the box! \ No newline at end of file diff --git a/docs/features/v3-features.md b/docs/features/v3-features.md deleted file mode 100644 index 51125855..00000000 --- a/docs/features/v3-features.md +++ /dev/null @@ -1,242 +0,0 @@ -# 🚀 Brainy - Production-Ready Features - -> **Status**: All features listed here are IMPLEMENTED and TESTED - -## 📊 Performance Metrics -- **Search Latency**: <10ms for 10,000+ items -- **Write Throughput**: 10,000+ ops/sec -- **Memory Efficiency**: <500MB for 10K items -- **Concurrent Operations**: 100+ simultaneous operations - -## 🧠 Core Intelligence Features - -### Triple Intelligence System ✅ -Unified query system combining three types of intelligence: -```typescript -const results = await brain.find({ - like: 'AI research', // Vector similarity search - where: { year: 2024 }, // Metadata filtering - connected: { to: authorId } // Graph relationships -}) -``` - -### Intelligent Type Mapping ✅ -Prevents semantic degradation by intelligently inferring types: -```typescript -// Automatically infers 'person' from email field -brain.add({ name: "John", email: "john@example.com" }, 'entity') -// → Stored as type: 'person', not generic 'entity' -``` - -### Neural Query Understanding ✅ -- 220+ embedded patterns for intent detection -- Natural language query processing -- Automatic query optimization -- Pattern-based query rewriting - -## 🔐 Security & Compliance - -### Rate Limiting ✅ -Per-operation configurable limits: -```typescript -const rateLimiter = createRateLimitAugmentation({ - limits: { - searches: 1000, // per minute - writes: 100, - reads: 5000, - deletes: 50 - } -}) -``` - -### Audit Logging ✅ -Comprehensive operation tracking: -```typescript -const auditLogger = createAuditLogAugmentation({ - logLevel: 'detailed', - retention: 90, // days - includeMetadata: true -}) - -// Query audit logs -const logs = auditLogger.queryLogs({ - operation: 'add', - startTime: Date.now() - 3600000 -}) -``` - -## 📦 Storage & Persistence - -Full crash recovery and replay: -```typescript - enabled: true, - checkpointInterval: 1000, - maxLogSize: 100 * 1024 * 1024 // 100MB -})) -``` - -### Multi-Tenancy ✅ -Service-based data isolation: -```typescript -// Isolated data per service -await brain.add(data, 'document', { service: 'tenant-1' }) -await brain.find('query', { service: 'tenant-1' }) -``` - -### Write-Only Mode ✅ -For dedicated write nodes: -```typescript -const brain = new Brainy({ - mode: 'write-only', - storage: 's3://bucket/path' -}) -``` - -## 🚀 Performance Features - -### Batch Operations ✅ -Optimized bulk processing: -```typescript -// Parallel processing with automatic batching -await brain.addMany(items) // <10ms per item -await brain.updateMany(updates) -await brain.removeMany(filters) -``` - -### Request Deduplication ✅ -Automatic duplicate request handling: -```typescript -brain.use(new RequestDeduplicatorAugmentation()) -// Identical concurrent requests return same result -``` - -### Smart Caching ✅ -Intelligent search result caching: -```typescript -brain.use(new CacheAugmentation({ - maxSize: 10000, - ttl: 300000, // 5 minutes - invalidateOnWrite: true -})) -``` - -## 🔄 Data Processing - -### Entity Registry ✅ -Bloom filter-based deduplication: -```typescript -brain.use(new EntityRegistryAugmentation()) -// Handles millions of entities with minimal memory -``` - -### Neural Import ✅ -Intelligent data import with type inference: -```typescript -await brain.import({ - source: 'data.json', - autoDetectTypes: true, - batchSize: 1000 -}) -``` - -### Streaming Pipeline ✅ -Real-time data processing: -```typescript -brain.stream() - .pipe(transform) - .pipe(enrich) - .pipe(brain.writer()) -``` - -## 📊 Analytics & Monitoring - -### Metrics Collection ✅ -Built-in performance metrics: -```typescript -const metrics = brain.getMetrics() -// { -// operations: { add: 1000, find: 5000 }, -// performance: { p95: 8, p99: 12 }, -// cache: { hits: 4500, misses: 500 } -// } -``` - -### Health Monitoring ✅ -Automatic health checks: -```typescript -const health = brain.getHealth() -// { -// status: 'healthy', -// storage: 'connected', -// memory: { used: 245, limit: 512 } -// } -``` - -## 🛠️ Developer Experience - -### Zero Configuration ✅ -Works out of the box: -```typescript -import Brainy from '@soulcraft/brainy' -const brain = new Brainy() // Auto-configures everything -``` - -### TypeScript First ✅ -Full type safety and inference: -```typescript -// Types are automatically inferred -const results = await brain.find('query') -``` - -### Augmentation System ✅ -Extensible plugin architecture: -```typescript -class CustomAugmentation extends BaseAugmentation { - execute(operation, params, next) { - // Your custom logic - return next() - } -} -``` - -## 🔧 Operational Features - -### Graceful Shutdown ✅ -Clean shutdown with data persistence: -```typescript -process.on('SIGTERM', async () => { - await brain.shutdown() // Saves all pending data -}) -``` - -### Hot Reload ✅ -Configuration updates without restart: -```typescript -brain.updateConfig({ - cache: { enabled: false } -}) -``` - -### Backup & Restore ✅ -Full data backup capabilities: -```typescript -await brain.backup('backup.bin') -await brain.restore('backup.bin') -``` - -## 📈 Proven at Scale - -- **10,000+ items**: Sub-10ms search -- **1M+ operations**: Stable memory usage -- **100+ concurrent users**: No performance degradation - -## 🚫 NOT Implemented (Planned) - -These features are documented but NOT yet implemented: -- GraphQL API (use REST API instead) -- Kubernetes operators (use Docker) - ---- - -*Last Updated: Latest Version* -*All features listed above are production-ready and tested* \ No newline at end of file diff --git a/docs/guides/framework-integration.md b/docs/guides/framework-integration.md index fbd47608..47719ae9 100644 --- a/docs/guides/framework-integration.md +++ b/docs/guides/framework-integration.md @@ -1,15 +1,17 @@ # Framework Integration Guide -Brainy 3.0 is **framework-first** - designed from the ground up to work seamlessly with modern JavaScript frameworks. This guide shows you how to integrate Brainy into any framework. +Brainy is **framework-friendly** - designed to drop into the server side of any modern JavaScript framework. This guide shows you how to integrate Brainy into framework-based apps. -## 🎯 Why Framework-First? +> **Runtime**: Brainy 8.0 runs on Node.js 22+ and Bun (server-side only). It is not a browser library. In framework apps, run Brainy in API routes, server components, server actions, loaders, or a dedicated backend service - never in client-side bundles. -Traditional AI databases require complex browser polyfills and bundler configurations. Brainy 3.0 trusts your framework to handle this: +## 🎯 Why Server-Side? + +Brainy embeds an HNSW vector index, a graph engine, and a filesystem-backed persistence layer. These belong on the server: - **Zero configuration**: Just `import { Brainy } from '@soulcraft/brainy'` -- **Framework responsibility**: Let Next.js, Vite, Webpack handle Node.js polyfills -- **Cleaner code**: No browser-specific entry points or conditional imports -- **Better DX**: Same API everywhere - browser, server, edge +- **Auto storage detection**: `new Brainy()` auto-selects filesystem persistence on Node +- **Cleaner code**: No browser polyfills, no conditional client/server imports +- **Better DX**: One instance shared across your server routes ## 🚀 Quick Start @@ -24,7 +26,8 @@ npm install @soulcraft/brainy ```javascript import { Brainy } from '@soulcraft/brainy' -// Works in any framework! +// Run on the server (API route, server component, backend service) +// new Brainy() auto-detects filesystem persistence on Node const brain = new Brainy() await brain.init() @@ -41,52 +44,48 @@ const results = await brain.find("framework integration") ## ⚛️ React Integration +Brainy runs on the server, so a React client component talks to it through an API endpoint (see the Next.js API route below). The hook fetches results; it never instantiates Brainy in the browser. + ### Basic Hook Pattern ```jsx -import { useState, useEffect, useCallback } from 'react' -import { Brainy } from '@soulcraft/brainy' +import { useState, useCallback } from 'react' -function useBrainy() { - const [brain, setBrain] = useState(null) - const [isReady, setIsReady] = useState(false) +function useBrainySearch(endpoint = '/api/search') { + const [results, setResults] = useState([]) + const [loading, setLoading] = useState(false) - useEffect(() => { - const initBrain = async () => { - const newBrain = new Brainy({ - storage: { type: 'opfs' } // Browser storage + const search = useCallback(async (query) => { + if (!query) return + setLoading(true) + try { + const res = await fetch(endpoint, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ query }) }) - await newBrain.init() - setBrain(newBrain) - setIsReady(true) + const { results } = await res.json() + setResults(results) + } finally { + setLoading(false) } + }, [endpoint]) - initBrain() - }, []) - - return { brain, isReady } + return { results, loading, search } } // Usage in component function SearchComponent() { - const { brain, isReady } = useBrainy() - const [results, setResults] = useState([]) - - const handleSearch = useCallback(async (query) => { - if (!isReady) return - const searchResults = await brain.find(query) - setResults(searchResults) - }, [brain, isReady]) - - if (!isReady) return
Loading AI...
+ const { results, loading, search } = useBrainySearch() return (
handleSearch(e.target.value)} + onChange={(e) => search(e.target.value)} /> + {loading &&
Searching...
}
{results.map(result => (
@@ -100,48 +99,34 @@ function SearchComponent() { } ``` -### React Context Pattern +### Shared Server Instance -```jsx -import React, { createContext, useContext, useEffect, useState } from 'react' +On the server, create one Brainy instance and reuse it across requests. This module is imported only by server code (API routes, server components), never by client components: + +```javascript +// lib/brain.server.js import { Brainy } from '@soulcraft/brainy' -const BrainyContext = createContext() +let brainPromise -export function BrainyProvider({ children }) { - const [brain, setBrain] = useState(null) - const [isReady, setIsReady] = useState(false) - - useEffect(() => { - const initBrain = async () => { - const newBrain = new Brainy() - await newBrain.init() - setBrain(newBrain) - setIsReady(true) - } - - initBrain() - }, []) - - return ( - - {children} - - ) -} - -export function useBrainContext() { - const context = useContext(BrainyContext) - if (!context) { - throw new Error('useBrainContext must be used within BrainyProvider') +export function getBrain() { + if (!brainPromise) { + brainPromise = (async () => { + // new Brainy() auto-detects filesystem persistence on Node + const brain = new Brainy() + await brain.init() + return brain + })() } - return context + return brainPromise } ``` ## 🟢 Vue.js Integration -### Composition API +Vue components call a server endpoint (see the Nuxt server route in the [Vue.js Integration Guide](vue-integration.md)); Brainy itself runs on the server. + +### Composition API (client component) ```vue ``` -### Vue 3 Plugin +### Shared Server Instance + +On the server, create one Brainy instance and reuse it across requests: ```javascript -// plugins/brainy.js +// server/brain.js (server-only module) import { Brainy } from '@soulcraft/brainy' -export default { - install(app, options) { - const brain = new Brainy(options) +let brainPromise - app.config.globalProperties.$brain = brain - app.provide('brain', brain) - - // Initialize on app mount - brain.init() +export function getBrain() { + if (!brainPromise) { + brainPromise = (async () => { + // new Brainy() auto-detects filesystem persistence on Node + const brain = new Brainy() + await brain.init() + return brain + })() } + return brainPromise } - -// main.js -import { createApp } from 'vue' -import BrainyPlugin from './plugins/brainy' - -const app = createApp(App) -app.use(BrainyPlugin, { - storage: { type: 'opfs' } -}) ``` ## 🅰️ Angular Integration -### Service Pattern +The Angular service calls your backend over HTTP; Brainy lives in that backend, not in the browser. + +### Service Pattern (calls the backend) ```typescript // brainy.service.ts import { Injectable } from '@angular/core' -import { BehaviorSubject, Observable } from 'rxjs' -import { Brainy } from '@soulcraft/brainy' +import { HttpClient } from '@angular/common/http' +import { Observable } from 'rxjs' @Injectable({ providedIn: 'root' }) export class BrainyService { - private brain: Brainy - private readySubject = new BehaviorSubject(false) + constructor(private http: HttpClient) {} - ready$: Observable = this.readySubject.asObservable() - - constructor() { - this.initBrain() + search(query: string): Observable<{ results: any[] }> { + return this.http.post<{ results: any[] }>('/api/search', { query }) } - private async initBrain() { - this.brain = new Brainy({ - storage: { type: 'opfs' } - }) - await this.brain.init() - this.readySubject.next(true) - } - - async search(query: string): Promise { - if (!this.readySubject.value) { - throw new Error('Brain not ready') - } - return await this.brain.find(query) - } - - async add(data: any, type: string, metadata?: any): Promise { - if (!this.readySubject.value) { - throw new Error('Brain not ready') - } - return await this.brain.add({ data, type, metadata }) + add(data: any, type: string, metadata?: any): Observable<{ id: string }> { + return this.http.post<{ id: string }>('/api/add', { data, type, metadata }) } } ``` @@ -280,64 +235,52 @@ export class SearchComponent { constructor(private brainyService: BrainyService) {} - async search() { + search() { if (!this.query) return - this.results = await this.brainyService.search(this.query) + this.brainyService.search(this.query).subscribe(({ results }) => { + this.results = results + }) } } ``` +The matching backend endpoint uses Brainy directly (Node/Bun): + +```typescript +// server: api/search +import { Brainy } from '@soulcraft/brainy' + +const brain = new Brainy() // auto-detects filesystem persistence on Node +await brain.init() + +export async function handleSearch(query: string) { + return await brain.find(query) +} +``` + ## 🚀 Next.js Integration -### App Router (Next.js 13+) +In Next.js, Brainy lives in server code only: API routes, server components, or server actions. Create one shared instance in a server-only module. -```jsx -// app/providers.jsx -'use client' -import { createContext, useContext, useEffect, useState } from 'react' +### Shared Server Instance + +```javascript +// lib/brain.server.js (imported only by server code) import { Brainy } from '@soulcraft/brainy' -const BrainyContext = createContext() +let brainPromise -export function BrainyProvider({ children }) { - const [brain, setBrain] = useState(null) - const [isReady, setIsReady] = useState(false) - - useEffect(() => { - const initBrain = async () => { - const newBrain = new Brainy() - await newBrain.init() - setBrain(newBrain) - setIsReady(true) - } - - initBrain() - }, []) - - return ( - - {children} - - ) -} - -export const useBrainy = () => useContext(BrainyContext) -``` - -```jsx -// app/layout.jsx -import { BrainyProvider } from './providers' - -export default function RootLayout({ children }) { - return ( - - - - {children} - - - - ) +export function getBrain() { + if (!brainPromise) { + brainPromise = (async () => { + const brain = new Brainy({ + storage: { type: 'filesystem', rootDirectory: './data' } + }) + await brain.init() + return brain + })() + } + return brainPromise } ``` @@ -345,45 +288,78 @@ export default function RootLayout({ children }) { ```javascript // app/api/search/route.js -import { Brainy } from '@soulcraft/brainy' - -const brain = new Brainy({ - storage: { type: 'filesystem', rootDirectory: './data' } -}) -await brain.init() +import { getBrain } from '@/lib/brain.server' export async function POST(request) { const { query } = await request.json() + const brain = await getBrain() const results = await brain.find(query) return Response.json({ results }) } ``` -## 🔷 Svelte Integration +### Server Action + +```javascript +// app/actions.js +'use server' +import { getBrain } from '@/lib/brain.server' + +export async function search(query) { + const brain = await getBrain() + return await brain.find(query) +} +``` + +## 🔷 SvelteKit Integration + +Brainy runs in a server-only module (`*.server.js`); the component fetches results from an endpoint. + +```javascript +// src/lib/server/brain.js (server-only — note the .server suffix) +import { Brainy } from '@soulcraft/brainy' + +let brainPromise + +export function getBrain() { + if (!brainPromise) { + brainPromise = (async () => { + const brain = new Brainy() // auto-detects filesystem persistence + await brain.init() + return brain + })() + } + return brainPromise +} +``` + +```javascript +// src/routes/api/search/+server.js +import { json } from '@sveltejs/kit' +import { getBrain } from '$lib/server/brain' + +export async function POST({ request }) { + const { query } = await request.json() + const brain = await getBrain() + return json({ results: await brain.find(query) }) +} +``` ```svelte @@ -401,27 +377,23 @@ export async function POST(request) { ## 🌟 Solid.js Integration +The component calls a server endpoint (use SolidStart server routes, or any backend, to host Brainy): + ```jsx -import { createSignal, onMount } from 'solid-js' -import { Brainy } from '@soulcraft/brainy' +import { createSignal } from 'solid-js' function SearchComponent() { - const [brain, setBrain] = createSignal(null) - const [isReady, setIsReady] = createSignal(false) const [query, setQuery] = createSignal('') const [results, setResults] = createSignal([]) - onMount(async () => { - const newBrain = new Brainy() - await newBrain.init() - setBrain(newBrain) - setIsReady(true) - }) - const search = async () => { - if (!isReady() || !query()) return - const searchResults = await brain().find(query()) - setResults(searchResults) + if (!query()) return + const res = await fetch('/api/search', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ query: query() }) + }) + setResults((await res.json()).results) } return ( @@ -450,57 +422,25 @@ function SearchComponent() { ## 📦 Bundler Configuration -### Vite (Recommended) +Brainy is a server-side dependency, so keep it out of client bundles. Import it only from server-only modules (`*.server.js`, API routes, server components, server actions). If your bundler ever tries to pull Brainy into a client bundle, that's a sign it's being imported from a client component — move the import to a server module. + +For server builds, mark Brainy as external so the bundler doesn't inline it: ```javascript -// vite.config.js +// vite.config.js (SSR build) import { defineConfig } from 'vite' export default defineConfig({ - define: { - global: 'globalThis' - }, - optimizeDeps: { - include: ['@soulcraft/brainy'] + ssr: { + external: ['@soulcraft/brainy'] } }) ``` -### Webpack - ```javascript -// webpack.config.js -module.exports = { - resolve: { - fallback: { - "fs": false, - "path": require.resolve("path-browserify"), - "crypto": require.resolve("crypto-browserify") - } - }, - plugins: [ - new webpack.ProvidePlugin({ - global: 'global' - }) - ] -} -``` - -### Rollup - -```javascript -// rollup.config.js -import { nodeResolve } from '@rollup/plugin-node-resolve' -import commonjs from '@rollup/plugin-commonjs' - +// rollup.config.js (server bundle) export default { - plugins: [ - nodeResolve({ - browser: true, - preferBuiltins: false - }), - commonjs() - ] + external: ['@soulcraft/brainy', 'node:fs', 'node:path', 'node:crypto'] } ``` @@ -508,30 +448,24 @@ export default { ### Server-Side Rendering +Instantiate Brainy on the server and feed its results into the rendered page. Never construct it in client code. + ```javascript -// Check if running in browser -if (typeof window !== 'undefined') { - // Browser-only code - const brain = new Brainy({ - storage: { type: 'opfs' } - }) -} +// Server-side data loading (framework loader / getServerSideProps / load fn) +import { getBrain } from './brain.server' -// Or use dynamic imports -const initBrainForBrowser = async () => { - if (typeof window === 'undefined') return null - - const { Brainy } = await import('@soulcraft/brainy') - const brain = new Brainy() - await brain.init() - return brain +export async function load({ url }) { + const brain = await getBrain() + const query = url.searchParams.get('q') ?? '' + const results = query ? await brain.find(query) : [] + return { results } } ``` ### Static Site Generation ```javascript -// For build-time usage +// For build-time usage (runs in Node during the build) import { Brainy } from '@soulcraft/brainy' export async function generateStaticProps() { @@ -552,67 +486,46 @@ export async function generateStaticProps() { ## 🔧 Framework-Specific Tips ### React -- Use `useCallback` for search functions to prevent re-renders -- Consider `useMemo` for expensive brain operations -- Implement cleanup in `useEffect` for proper memory management +- Keep components client-side and call a Brainy-backed API route +- Use `useCallback` for fetch handlers to prevent re-renders +- Debounce keystroke-driven searches before hitting the endpoint ### Vue -- Use `shallowRef` for the brain instance (it's not reactive data) -- Consider Pinia for global brain state management -- Use `watchEffect` for reactive search queries +- Components call an endpoint; the shared instance lives in a server module +- Consider Pinia for caching results client-side +- Debounce reactive search queries ### Angular -- Implement proper dependency injection with services -- Use RxJS observables for reactive search -- Consider lazy loading brain in feature modules +- Use `HttpClient` and RxJS to call the backend +- Hold the shared Brainy instance in your Node backend, not the app +- Consider lazy loading search features in feature modules ### Next.js -- Use dynamic imports for client-side only features -- Consider API routes for server-side brain operations -- Implement proper error boundaries +- Put Brainy in server-only modules (`*.server.js`), API routes, or server actions +- Reuse one shared instance across requests +- Implement proper error boundaries for failed fetches ## 🚨 Common Issues & Solutions -### Issue: "crypto is not defined" -**Solution**: Your framework should handle this automatically. If not: -```javascript -// Add to your bundle config -define: { - global: 'globalThis' -} -``` +### Issue: "fs module not found" / "crypto is not defined" in the browser +**Cause**: Brainy was imported into a client bundle. Brainy 8.0 is a server-side library (Node 22+/Bun) and uses Node built-ins like `fs` and `crypto`. +**Solution**: Import Brainy only from server code — server-only modules (`*.server.js`), API routes, server components, or server actions. From client components, call those endpoints instead. -### Issue: "fs module not found" -**Solution**: This is expected in browsers. Use browser-compatible storage: -```javascript -const brain = new Brainy({ - storage: { type: 'opfs' } // Or 'memory' for development -}) -``` - -### Issue: Large bundle size -**Solution**: Use dynamic imports for optional features: -```javascript -const brain = await import('@soulcraft/brainy').then(m => new m.Brainy()) -``` +### Issue: Large client bundle size +**Cause**: A client module is pulling in Brainy. +**Solution**: Move the `import { Brainy } from '@soulcraft/brainy'` into a server-only module so it never reaches the browser bundle. ### Issue: SSR hydration mismatch -**Solution**: Initialize brain only on client: -```javascript -useEffect(() => { - // Browser-only initialization - initBrain() -}, []) -``` +**Solution**: Run the search on the server (loader / server action / API route) and pass the results down as props, so server and client render the same markup. ## 🎯 Best Practices -1. **Initialize Once**: Create brain instance at app level, not component level -2. **Use Context**: Share brain instance across components with context/providers -3. **Handle Loading**: Always show loading states during brain initialization -4. **Error Boundaries**: Implement proper error handling for brain operations -5. **Memory Management**: Clean up brain instances on unmount -6. **Storage Strategy**: Choose appropriate storage for your deployment target +1. **Initialize Once**: Create one shared Brainy instance per server process, not per request +2. **Server-Only**: Import Brainy only from server modules — never from client components +3. **Endpoint Boundary**: Expose search/add through API routes or server actions +4. **Handle Loading**: Show loading states in the client while the fetch is in flight +5. **Error Handling**: Catch and surface failed endpoint calls gracefully +6. **Storage**: Use `filesystem` for persistence (the default on Node) or `memory` for ephemeral/tests ## 📚 Next Steps diff --git a/docs/guides/import-flow.md b/docs/guides/import-flow.md index 549bce23..23e51ef7 100644 --- a/docs/guides/import-flow.md +++ b/docs/guides/import-flow.md @@ -1743,7 +1743,7 @@ For off-site backup, snapshot `rootDirectory` from your scheduler with `gsutil r - HNSW Index: O(log n) search (1B entities = ~30 hops) - Metadata Index: O(1) filtering - Graph Adjacency: O(1) relationship lookups -- Storage: Unlimited (cloud buckets) +- Storage: Bounded by the filesystem volume backing `rootDirectory` ### Optimization Tips @@ -1887,7 +1887,7 @@ groupBy: 'type' - ✅ O(1) metadata filtering - ✅ O(1) relationship traversal - ✅ Human-readable VFS structure -- ✅ Cloud storage support (GCS/S3/R2) +- ✅ Filesystem-backed persistence (snapshot/sync the directory for off-site backup) - ✅ Billion-scale performance - ✅ Zero mocks, production-ready! diff --git a/docs/guides/installation.md b/docs/guides/installation.md index 637af308..d574cebc 100644 --- a/docs/guides/installation.md +++ b/docs/guides/installation.md @@ -45,7 +45,7 @@ console.log('Brainy ready.') ## Native Acceleration (Optional) -For production workloads, add Cortex for Rust-accelerated SIMD distance calculations, vector quantization, and native embeddings: +For production workloads, add Cortex for Rust-accelerated SIMD distance calculations and native embeddings: ```bash npm install @soulcraft/cortex diff --git a/docs/guides/quick-start.md b/docs/guides/quick-start.md index a4e287f1..2a689bd3 100644 --- a/docs/guides/quick-start.md +++ b/docs/guides/quick-start.md @@ -108,4 +108,4 @@ await brain.find({ query: 'people who work at Anthropic' }) - [Triple Intelligence](/docs/concepts/triple-intelligence) — understand how the query engine works - [The Find System](/docs/guides/find-system) — advanced queries, operators, and graph traversal - [API Reference](/docs/api/reference) — complete method documentation -- [Storage Adapters](/docs/guides/storage-adapters) — S3, GCS, Azure, filesystem, OPFS +- [Storage Adapters](/docs/guides/storage-adapters) — filesystem, memory diff --git a/docs/guides/schema-migrations.md b/docs/guides/schema-migrations.md index 98ceedb4..007ecd8a 100644 --- a/docs/guides/schema-migrations.md +++ b/docs/guides/schema-migrations.md @@ -271,7 +271,7 @@ Progress is reported after each batch (batch size is determined by the storage a ## Storage Backend Compatibility -Migrations work identically across all storage backends (Memory, FileSystem, S3, R2, GCS, OPFS). The system uses `BaseStorage` methods (`getNouns`, `saveNounMetadata`, `getVerbs`, `saveVerbMetadata`) which are implemented by every adapter. +Migrations work identically across all storage backends (Memory, FileSystem). The system uses `BaseStorage` methods (`getNouns`, `saveNounMetadata`, `getVerbs`, `saveVerbMetadata`) which are implemented by every adapter. Batch size and rate limiting are automatically configured per adapter — no tuning required. diff --git a/docs/guides/vue-integration.md b/docs/guides/vue-integration.md index a38c92ed..7f7c6a06 100644 --- a/docs/guides/vue-integration.md +++ b/docs/guides/vue-integration.md @@ -2,6 +2,8 @@ Complete guide to integrating Brainy with Vue.js applications, covering Vue 3, Nuxt.js, Composition API, Options API, and advanced patterns. +> **Runtime**: Brainy 8.0 runs on Node.js 22+ and Bun, server-side only — it is not a browser library. In Vue apps, Brainy lives behind an HTTP endpoint (a Nuxt server route, or any Node/Bun backend), and your components call that endpoint. The composables, plugin, and store below are wrappers around `fetch`; the single Brainy instance is created once on the server (see [Nuxt Server Route](#nuxt-server-route)). + ## 🚀 Quick Start ### Installation @@ -15,34 +17,47 @@ npm install @soulcraft/brainy ### Basic Setup +The composable talks to a Brainy-backed endpoint (see [Nuxt Server Route](#nuxt-server-route)). It is always "ready" because there is no client-side initialization — the server owns the Brainy instance. + ```javascript // src/composables/useBrainy.js -import { ref, onMounted } from 'vue' -import { Brainy } from '@soulcraft/brainy' +import { ref } from 'vue' -const brain = ref(null) -const isReady = ref(false) -const error = ref(null) +export function useBrainy(endpoint = '/api/brain') { + const error = ref(null) -export function useBrainy() { - onMounted(async () => { + const search = async (query, options = {}) => { + error.value = null try { - brain.value = new Brainy({ - storage: { type: 'opfs' } // Browser storage + const res = await fetch(`${endpoint}/search`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ query, options }) }) - await brain.value.init() - isReady.value = true + if (!res.ok) throw new Error(`Search failed: ${res.status}`) + return (await res.json()).results } catch (err) { error.value = err.message - console.error('Brainy initialization failed:', err) + console.error('Brainy search failed:', err) + return [] } - }) - - return { - brain: readonly(brain), - isReady: readonly(isReady), - error: readonly(error) } + + const add = async (data, type, metadata) => { + const res = await fetch(`${endpoint}/add`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ data, type, metadata }) + }) + return (await res.json()).id + } + + const stats = async () => { + const res = await fetch(`${endpoint}/stats`) + return await res.json() + } + + return { search, add, stats, error: readonly(error) } } ``` @@ -54,43 +69,36 @@ export function useBrainy() {