--- title: API Reference slug: api/reference public: true category: api template: api order: 1 description: Complete API reference for all Brainy methods β€” add, find, relate, update, delete, batch operations, the Db API (transactions, snapshots, time travel), VFS, neural API, and more. next: - getting-started/quick-start - guides/find-system --- # 🧠 Brainy API Reference > **Complete API documentation for Brainy** > Zero Configuration β€’ Triple Intelligence β€’ Database as a Value β€’ Atomic Transactions β€’ Time Travel **Updated:** 2026-06-11 **All APIs verified against actual code** --- ## Quick Start ```typescript import { Brainy, NounType, VerbType } from '@soulcraft/brainy' const brain = new Brainy() // Zero config! await brain.init() // VFS auto-initialized! // Add data (text auto-embeds!) const id = await brain.add({ data: 'The future of AI is here', type: NounType.Concept, metadata: { category: 'technology' } }) // Search with Triple Intelligence const results = await brain.find({ query: 'artificial intelligence', where: { year: { greaterThan: 2020 } }, connected: { from: id, depth: 2 } }) // Pin the current state as an immutable value const db = brain.now() // Commit an atomic multi-write batch (all-or-nothing) await brain.transact([ { op: 'update', id, metadata: { category: 'AI' } } ], { meta: { author: 'docs-example' } }) await db.get(id) // still sees the pre-transaction state β€” snapshot isolation await db.release() // Time travel: query any past state const yesterday = await brain.asOf(new Date(Date.now() - 86_400_000)) ``` --- ## Core Concepts ### 🧬 Entities (Nouns) Semantic vectors with metadata and relationships - the fundamental data unit in Brainy. ### πŸ”— Relationships (Verbs) Typed connections between entities with optional `data` and `metadata` - building knowledge graphs. ### πŸ“Š Data vs Metadata - **`data`**: Content embedded into vectors. Searchable via **semantic similarity** (vector index) and **hybrid text+semantic** search. NOT queryable via `where` filters. - **`metadata`**: Structured fields indexed by MetadataIndex. Queryable via `where` filters in `find()`. See **[Data Model](../DATA_MODEL.md)** for the full explanation. ### 🧠 Triple Intelligence Vector search + Graph traversal + Metadata filtering in one unified query. ### 🧊 Database Values (Db) The whole store pinned as an immutable value β€” snapshot isolation, atomic `transact()` batches, time travel with `asOf()`, instant hard-link snapshots with `persist()`. See the [consistency model](../concepts/consistency-model.md). --- ## Table of Contents - [Core CRUD Operations](#core-crud-operations) - [Search & Query](#search--query) - [Aggregation Engine](#aggregation-engine) - [Relationships](#relationships) - [Batch Operations](#batch-operations) - [Database Values & Time Travel (Db API)](#database-values--time-travel-db-api) - [Virtual Filesystem (VFS)](#virtual-filesystem-vfs) - [Neural API](#neural-api) - [Import & Export](#import--export) - [Configuration](#configuration) - [Storage Adapters](#storage-adapters) - [Utility Methods](#utility-methods) - [Embedding & Analysis APIs](#embedding--analysis-apis) - [Type System Reference](#type-system-reference) --- ## Core CRUD Operations ### `add(params)` β†’ `Promise` Add a single entity to the database. ```typescript const id = await brain.add({ data: 'JavaScript is a programming language', // Text or pre-computed vector type: NounType.Concept, // Required: Entity type subtype: 'language', // Optional: sub-classification metadata: { // Optional: queryable fields category: 'programming', year: 1995 } }) ``` **Parameters:** - `data`: `string | number[]` - Content to embed (text auto-embeds) or pre-computed vector - `type`: `NounType` - Entity type (required) - `subtype?`: `string` - Per-product sub-classification within the NounType (top-level standard field, indexed on the fast path). See [Subtypes & Facets](../guides/subtypes-and-facets.md). - `metadata?`: `object` - Structured queryable fields (indexed by MetadataIndex, used in `where` filters) - `id?`: `string` - Custom ID (auto-generated UUID if not provided) - `vector?`: `number[]` - Pre-computed vector (skips auto-embedding) - `confidence?`: `number` - Type classification confidence (0-1) - `weight?`: `number` - Entity importance/salience (0-1) - `ifAbsent?`: `boolean` - By-ID idempotent insert. When `true` AND a custom `id` is supplied AND an entity with that `id` already exists, returns the existing `id` without writing (no throw, no overwrite). Ignored without `id`. See [guides/optimistic-concurrency](../guides/optimistic-concurrency.md). > **`data`** is embedded into vectors for semantic search. **`metadata`** is indexed for `where` filters. See [Data Model](../DATA_MODEL.md). > **Strict-mode tip:** if a vocabulary is registered for your `type` (via `brain.requireSubtype()` or by an SDK that wraps Brainy), you must pass a matching `subtype`. Run `await brain.audit()` to inventory pre-existing gaps before enabling strict mode; see the [migration recipe](../guides/subtypes-and-facets.md#strict-mode-in-practice-for-sdk-style-vocabulary-consumers). **Returns:** `Promise` - Entity ID --- ### `get(id)` β†’ `Promise` Retrieve a single entity by ID. ```typescript const entity = await brain.get(id) console.log(entity?.data) // Original data console.log(entity?.metadata) // Metadata console.log(entity?.vector) // Embedding vector ``` **Parameters:** - `id`: `string` - Entity ID **Returns:** `Promise` - Entity or null if not found --- ### `update(params)` β†’ `Promise` Update an existing entity. ```typescript await brain.update({ id: entityId, data: 'Updated content', // Optional: new data subtype: 'archived', // Optional: change sub-classification metadata: { updated: true } // Optional: new metadata (merges) }) ``` **Parameters:** - `id`: `string` - Entity ID - `data?`: `string | number[]` - New data/vector - `type?`: `NounType` - Change entity type - `subtype?`: `string` - Change subtype (omit to preserve existing) - `metadata?`: `object` - Metadata to merge (or replace with `merge: false`) - `confidence?`: `number` - Update classification confidence - `weight?`: `number` - Update entity importance - `ifRev?`: `number` - Optimistic-concurrency check. When provided, the update throws `RevisionConflictError` if the persisted entity's `_rev` no longer equals `ifRev`. See [guides/optimistic-concurrency](../guides/optimistic-concurrency.md). **Returns:** `Promise` > **Tip β€” read-then-CAS.** Every entity returned by `get()` / `find()` / `search()` carries `entity._rev` (a monotonic counter Brainy auto-bumps on every successful `update()`). Pass it back as `ifRev` to make multi-writer coordination safe without an external lock service. Full guide: [guides/optimistic-concurrency](../guides/optimistic-concurrency.md). --- ### `remove(id)` β†’ `Promise` Remove a single entity (and every relationship where it is source or target). ```typescript await brain.remove(id) ``` **Parameters:** - `id`: `string` - Entity ID **Returns:** `Promise` --- ## Search & Query ### `find(query)` β†’ `Promise` **Triple Intelligence** - Vector + Graph + Metadata in ONE query. ```typescript // Simple text search const results = await brain.find('machine learning') // Advanced Triple Intelligence query const results = await brain.find({ query: 'artificial intelligence', // Vector similarity where: { // Metadata filtering year: { greaterThan: 2020 }, category: { oneOf: ['AI', 'ML'] } }, connected: { // Graph traversal to: conceptId, depth: 2, type: VerbType.RelatedTo }, limit: 10 }) ``` **Parameters:** - `query`: `string | FindParams` - **Simple:** Just text for vector search - **Advanced:** Object with vector + graph + metadata filters **FindParams:** - `query?`: `string` - Text for semantic + hybrid search (searches `data` via the vector index + text index) - `type?`: `NounType | NounType[]` - Filter by entity type(s). Alias for `where.noun`. - `subtype?`: `string | string[]` - Filter by sub-classification (top-level standard field, fast path). Single string for equality, array for set membership. - `where?`: `object` - Metadata filters. See **[Query Operators](../QUERY_OPERATORS.md)** for all operators. - `connected?`: `object` - Graph traversal options - `to?`: `string` - Target entity ID - `from?`: `string` - Source entity ID - `via?`: `VerbType | VerbType[]` - Relationship type(s) to traverse - `type?`: `VerbType | VerbType[]` - Alias for `via` - `depth?`: `number` - Traversal depth (default: 1) - `direction?`: `'in' | 'out' | 'both'` - Traversal direction (default: 'both') - `limit?`: `number` - Max results (default: 10) - `offset?`: `number` - Skip results - `orderBy?`: `string` - Field to sort by (e.g., 'createdAt', 'metadata.priority') - `order?`: `'asc' | 'desc'` - Sort direction (default: 'asc') - `searchMode?`: `'auto' | 'text' | 'semantic' | 'hybrid'` - Search strategy: - `'auto'` (default): Zero-config hybrid combining text + semantic search - `'text'`: Pure keyword/text matching - `'semantic'`/`'vector'`: Pure vector similarity - `'hybrid'`: Explicit hybrid mode - `hybridAlpha?`: `number` - Balance between text (0.0) and semantic (1.0) search. Auto-detected by query length if not specified. - `excludeVFS?`: `boolean` - Exclude VFS entities from results (default: false) > **`limit` tip:** Brainy caps `limit` against an auto-configured maximum (based on container/free memory, ~25 KB per result). Above the cap you get a one-time warning per call site; above 2Γ— the cap it throws. To raise the cap, pass `new Brainy({ maxQueryLimit: N })` or `{ reservedQueryMemory: bytes }`. For queries that need ALL matches, paginate with `{ limit, offset }` β€” that's the only pattern guaranteed to keep working across Brainy versions. See [Query Limits & Pagination](../guides/find-limits.md). **Returns:** `Promise` - Matching entities with scores --- ### Hybrid Search Brainy automatically combines text (keyword) and semantic (vector) search for optimal results. No configuration needed. ```typescript // Zero-config hybrid search (just works) const results = await brain.find({ query: 'David Smith' // Finds both exact text matches AND semantically similar }) // Force text-only search (exact keyword matching) const textResults = await brain.find({ query: 'exact keyword', searchMode: 'text' }) // Force semantic-only search (vector similarity) const semanticResults = await brain.find({ query: 'artificial intelligence concepts', searchMode: 'semantic' }) // Custom hybrid weighting (0 = text only, 1 = semantic only) const customResults = await brain.find({ query: 'David Smith', hybridAlpha: 0.3 // Favor text matching }) ``` **How it works:** - Short queries (1-2 words) automatically favor text matching - Long queries (5+ words) automatically favor semantic search - Results are combined using Reciprocal Rank Fusion (RRF) --- ### Match Visibility Search results include detailed match information: ```typescript const results = await brain.find({ query: 'david the warrior' }) // Each result now includes: results[0].textMatches // ["david", "warrior"] - exact query words found results[0].textScore // 0.25 - text match quality (0-1) results[0].semanticScore // 0.87 - semantic similarity (0-1) results[0].matchSource // 'both' | 'text' | 'semantic' ``` **Use cases:** - Highlight exact matches in UI (textMatches) - Explain why a result ranked high (matchSource) - Debug search behavior (separate scores) --- ### `highlight(params)` β†’ `Promise` ✨ Zero-config highlighting for both exact matches AND semantic concepts. Handles plain text, rich-text JSON (TipTap, Slate, Lexical, Draft.js, Quill), HTML, and Markdown automatically. ```typescript // Plain text (works as before) const highlights = await brain.highlight({ query: "david the warrior", text: "David Smith is a brave fighter who battles dragons" }) // [ // { text: "David", score: 1.0, position: [0, 5], matchType: 'text' }, // { text: "fighter", score: 0.78, position: [25, 32], matchType: 'semantic' }, // { text: "battles", score: 0.72, position: [37, 44], matchType: 'semantic' } // ] // Rich-text JSON (auto-detected) const highlights = await brain.highlight({ query: "david the warrior", text: JSON.stringify(tiptapDocument) // TipTap, Slate, Lexical, Draft.js, Quill }) // Extracts text from nodes, annotates with contentCategory: // [ // { text: "David", score: 1.0, matchType: 'text', contentCategory: 'title' }, // { text: "fighter", score: 0.78, matchType: 'semantic', contentCategory: 'content' } // ] // HTML input (auto-detected) const highlights = await brain.highlight({ query: "warrior", text: "

David the Warrior

A brave fighter.

" }) // Custom extractor for proprietary formats const highlights = await brain.highlight({ query: "function", text: sourceCode, contentExtractor: (text) => treeSitterParse(text) // Your custom parser }) ``` **Parameters:** - `query`: `string` - The search query - `text`: `string` - Text to highlight (plain text, JSON, HTML, or Markdown) - `granularity?`: `'word' | 'phrase' | 'sentence'` - Highlight unit (default: 'word') - `threshold?`: `number` - Min similarity for semantic matches (default: 0.5) - `contentType?`: `ContentType` - Optional hint: `'plaintext' | 'richtext-json' | 'html' | 'markdown'`. Skips auto-detection when provided. - `contentExtractor?`: `(text: string) => ExtractedSegment[]` - Custom parser. Bypasses built-in detection entirely. **Returns:** `Promise` - `text` - The matched text - `score` - Match score (1.0 for text matches, varies for semantic) - `position` - [start, end] indices in extracted text - `matchType` - `'text'` (exact) or `'semantic'` (concept) - `contentCategory?` - `'title' | 'annotation' | 'content' | 'value' | 'code' | 'structural'` β€” Role of the source text. Built-in extractors produce `'title'`, `'content'`, `'code'`. All 6 categories are available for custom parsers. **Supported Rich-Text Formats:** | Format | Detection | Text nodes | |--------|-----------|------------| | TipTap / ProseMirror | `{ type: 'doc', content: [...] }` | `{ type: 'text', text }` | | Slate.js | `[{ type, children }]` | `{ text }` | | Lexical | `{ root: { children } }` | `{ type: 'text', text }` | | Draft.js | `{ blocks: [{ text }] }` | `{ text }` in block | | Quill Delta | `{ ops: [{ insert }] }` | `{ insert }` | | HTML | Tags like `

`, `

`, `` | Visible text content | | Markdown | `#` headings, ` ``` ` code blocks | Stripped markup | **Timeout Protection:** Semantic matching has a 10-second timeout. If embedding takes too long (e.g., WASM stall), `highlight()` returns text-only matches instead of hanging. **UI Pattern:** ```typescript // Style differently based on match type and content category highlights.forEach(h => { const style = h.matchType === 'text' ? 'font-weight: bold' : 'background: yellow' if (h.contentCategory === 'title') { /* render as heading highlight */ } if (h.contentCategory === 'code') { /* render with code styling */ } if (h.contentCategory === 'annotation') { /* render as comment/caption */ } // Apply style from h.position[0] to h.position[1] }) ``` --- ### Query Operators Brainy uses clean, readable operators (BFO β€” Brainy Field Operators): | Operator | Description | Example | |----------|-------------|---------| | `equals` / `eq` | Exact match | `{age: {equals: 25}}` | | `notEquals` / `ne` | Not equal | `{status: {notEquals: 'deleted'}}` | | `greaterThan` / `gt` | Greater than | `{age: {greaterThan: 18}}` | | `greaterEqual` / `gte` | Greater or equal | `{score: {greaterEqual: 90}}` | | `lessThan` / `lt` | Less than | `{price: {lessThan: 100}}` | | `lessEqual` / `lte` | Less or equal | `{rating: {lessEqual: 3}}` | | `between` | Inclusive range | `{year: {between: [2020, 2025]}}` | | `oneOf` / `in` | In array | `{color: {oneOf: ['red', 'blue']}}` | | `noneOf` | Not in array | `{status: {noneOf: ['deleted']}}` | | `contains` | Array contains value | `{tags: {contains: 'ai'}}` | | `exists` / `missing` | Field existence | `{email: {exists: true}}` | | `startsWith` | String prefix | `{name: {startsWith: 'John'}}` | | `endsWith` | String suffix | `{email: {endsWith: '@gmail.com'}}` | | `matches` | Pattern match | `{text: {matches: /^[A-Z]/}}` | | `allOf` | AND combinator | `{allOf: [{active: true}, {role: 'admin'}]}` | | `anyOf` | OR combinator | `{anyOf: [{role: 'admin'}, {role: 'owner'}]}` | **[Complete Operator Reference β†’](../QUERY_OPERATORS.md)** β€” all operators, aliases, indexed vs in-memory support matrix, and practical examples. --- ## Aggregation Engine Brainy's aggregation engine maintains **incremental running totals** at write time, delivering O(1) aggregate reads regardless of dataset size. Define aggregates once, and every `add()`, `update()`, and `delete()` automatically updates the running metrics. ### `defineAggregate(definition)` β†’ `void` Register a named aggregate for incremental computation. ```typescript brain.defineAggregate({ name: 'monthly_spending', source: { type: NounType.Event, where: { domain: 'financial' } // matches custom metadata fields }, groupBy: [ 'category', { field: 'date', window: 'month' } // Time-windowed dimension ], metrics: { total: { op: 'sum', field: 'amount' }, count: { op: 'count' }, average: { op: 'avg', field: 'amount' }, highest: { op: 'max', field: 'amount' }, lowest: { op: 'min', field: 'amount' }, spread: { op: 'stddev', field: 'amount' } // Welford's online algorithm }, materialize: true // Optional: write results as NounType.Measurement entities }) ``` **Parameters:** | Field | Type | Description | |-------|------|-------------| | `name` | `string` | Unique identifier for this aggregate | | `source.type` | `NounType \| NounType[]` | Entity types that feed into this aggregate | | `source.where` | `Record` | Filter on custom **metadata** fields (matched against the entity's `metadata` bag) | | `source.service` | `string` | Multi-tenancy filter | | `groupBy` | `GroupByDimension[]` | Dimensions to group by β€” plain field names, `{ field, window }` for time bucketing, or `{ field, unnest: true }` for array fields (one contribution per element) | | `metrics` | `Record` | Named metrics with `op` (`sum`, `count`, `avg`, `min`, `max`, `stddev`, `variance`, `percentile`, `distinctCount`) and optional `field`. `percentile` additionally requires `p` in `[0, 1]`. | | `materialize` | `boolean \| object` | Write results as `NounType.Measurement` entities (auto-visible in OData/Sheets/SSE) | **Time window granularities:** `'hour'`, `'day'`, `'week'`, `'month'`, `'quarter'`, `'year'`, or `{ seconds: number }` for custom intervals. ### `removeAggregate(name)` β†’ `void` Remove a named aggregate and clean up its state. ```typescript brain.removeAggregate('monthly_spending') ``` ### Querying Aggregates via `find()` Aggregate results are queried through the standard `find()` method using the `aggregate` parameter: ```typescript // Simple: query by name const results = await brain.find({ aggregate: 'monthly_spending' }) // With filtering on group keys const foodOnly = await brain.find({ aggregate: 'monthly_spending', where: { category: 'food' } }) // With sorting and pagination const topCategories = await brain.find({ aggregate: { name: 'monthly_spending', orderBy: 'total', order: 'desc', limit: 10 } }) // Combine find-level params (where, orderBy, limit, offset merge automatically) const recentFood = await brain.find({ aggregate: 'monthly_spending', where: { category: 'food' }, orderBy: 'total', order: 'desc', limit: 12 }) ``` **Result format:** Returns `Result[]` with `type: NounType.Measurement`. Each result contains: ```typescript { id: string, // Aggregate group ID (or materialized entity ID) score: 1.0, // Always 1.0 for aggregates type: NounType.Measurement, metadata: { __aggregate: 'monthly_spending', // Source aggregate name category: 'food', // Group key values date: '2024-01', // Time window bucket total: 342.50, // Computed metrics count: 28, average: 12.23, highest: 45.00, lowest: 2.50 }, entity: Entity // Full entity structure } ``` ### `queryAggregate(name, params?)` β†’ `Promise` The first-class analytics path β€” returns plain group rows (`{ groupKey, metrics, count }`) instead of `find()`-style `Result` wrappers. Supports `where` (group-key filter), `having` (SQL-HAVING metric filter), `orderBy`, `order`, `limit`, `offset`: ```typescript const rows = await brain.queryAggregate('monthly_spending', { having: { total: { greaterThan: 100 } }, // filter by computed metrics orderBy: 'total', order: 'desc', limit: 10 }) // [{ groupKey: { category: 'food', date: '2024-01' }, metrics: { total: 342.5, count: 28 }, count: 28 }, ...] ``` ### How It Works Aggregation hooks run **outside transactions** on every write operation: - **`add()`**: If the new entity matches any aggregate's `source` filter, its values are added to the matching group's running totals. - **`update()`**: The old entity's contribution is reversed and the new entity's contribution is applied (handles group key changes, source filter changes). - **`delete()`**: The deleted entity's contribution is reversed from its group. **Performance:** O(A Γ— G Γ— M) per write where A = matching aggregates, G = groupBy dimensions, M = metrics. For typical configurations (2-5 aggregates, 1-3 dimensions, 3-5 metrics), this is effectively O(1) β€” measured at **10,000 entities in 13ms** in unit tests. **Infinite loop prevention:** Materialized `NounType.Measurement` entities (with `service: 'brainy:aggregation'` or `metadata.__aggregate`) are automatically excluded from all aggregate source matching. **Persistence:** Definitions and running state are persisted to storage on `flush()`/`close()` and reloaded on `init()`. Definition changes are detected via FNV-1a hashing β€” only changed aggregates reset their state. **Native acceleration:** Register an `'aggregation'` provider via the plugin system to replace the TypeScript engine with a custom native implementation for higher throughput at scale. ### Financial Data Modeling Brainy supports financial analytics through **subtypes and metadata conventions** on existing NounTypes β€” no custom types needed: ```typescript // Transaction = NounType.Event + 'transaction' subtype + financial metadata await brain.add({ data: 'Coffee at Blue Bottle', type: NounType.Event, subtype: 'transaction', // top-level standard field (reserved β€” never in metadata) metadata: { domain: 'financial', amount: 5.50, currency: 'USD', category: 'food', date: Date.now(), merchant: 'Blue Bottle Coffee' } }) // Account = NounType.Collection + 'account' subtype + financial metadata await brain.add({ data: 'Checking Account', type: NounType.Collection, subtype: 'account', metadata: { domain: 'financial', accountType: 'checking', currency: 'USD', institution: 'Chase' } }) // Invoice = NounType.Document + 'invoice' subtype + financial metadata await brain.add({ data: 'Invoice #1234 from Acme Corp', type: NounType.Document, subtype: 'invoice', metadata: { domain: 'financial', amount: 15000, currency: 'USD', status: 'pending', dueDate: Date.UTC(2024, 2, 15), vendor: 'Acme Corp' } }) ``` --- ## Relationships ### `relate(params)` β†’ `Promise` Create a typed relationship between entities. ```typescript const relId = await brain.relate({ from: sourceId, to: targetId, type: VerbType.ReportsTo, subtype: 'direct', // Optional: sub-classification data: 'Collaborated on the research paper', // Optional: content for this edge metadata: { // Optional: structured edge fields strength: 0.9, role: 'primary author' } }) ``` **Parameters:** - `from`: `string` - Source entity ID (must exist) - `to`: `string` - Target entity ID (must exist) - `type`: `VerbType` - Relationship type - `subtype?`: `string` - Per-product sub-classification within the VerbType (top-level standard field, fast-path indexed). See [Subtypes & Facets](../guides/subtypes-and-facets.md). - `data?`: `any` - Content for the relationship (overrides auto-computed vector) - `metadata?`: `object` - Structured edge fields - `weight?`: `number` - Connection strength (0-1, default: 1.0) - `bidirectional?`: `boolean` - Create reverse edge too (default: false) - `confidence?`: `number` - Relationship certainty (0-1) > **Strict-mode tip:** same as `add()` β€” if a vocabulary is registered for your `type`, pass a matching `subtype`. Run `await brain.audit()` first to surface pre-existing gaps. **Returns:** `Promise` - Relationship ID --- ### `updateRelation(params)` β†’ `Promise` Update an existing relationship. Mirror of `update()` for verbs β€” closed a long-standing gap (verbs had no update path before 7.30). ```typescript // Change the subtype on an existing relationship await brain.updateRelation({ id: relId, subtype: 'dotted-line' }) // Update weight + confidence await brain.updateRelation({ id: relId, weight: 0.7, confidence: 0.9 }) // Change verb type (re-indexes in graph adjacency, id preserved) await brain.updateRelation({ id: relId, type: VerbType.WorksWith }) ``` **Parameters:** - `id`: `string` - Relationship ID (required) - `type?`: `VerbType` - Change verb type (re-indexes in graph adjacency) - `subtype?`: `string` - Change sub-classification (omit to preserve existing) - `weight?`: `number` - New weight (0-1) - `confidence?`: `number` - New confidence (0-1) - `data?`: `any` - New content - `metadata?`: `object` - Metadata to merge (or replace with `merge: false`) - `merge?`: `boolean` - Merge or replace metadata (default: true) **Returns:** `Promise` --- ### `related(params)` β†’ `Promise` Get relationships for an entity. Same name and surface as `db.related()` on a pinned `Db` view. ```typescript // Get all relationships FROM an entity const outgoing = await brain.related({ from: entityId }) // Get all relationships TO an entity const incoming = await brain.related({ to: entityId }) // Filter by type const contains = await brain.related({ from: entityId, type: VerbType.Contains }) // Filter by subtype (fast path, column-store hit) const direct = await brain.related({ from: entityId, type: VerbType.ReportsTo, subtype: 'direct' }) // Set membership on subtype const all = await brain.related({ from: entityId, type: VerbType.ReportsTo, subtype: ['direct', 'dotted-line'] }) ``` **Parameters:** - `from?`: `string` - Source entity ID - `to?`: `string` - Target entity ID - `type?`: `VerbType | VerbType[]` - Filter by relationship type - `subtype?`: `string | string[]` - Filter by VerbType subtype (top-level standard field, fast path) - `service?`: `string` - Multi-tenancy filter - `limit?`: `number` - Pagination limit (default: 100) - `offset?`: `number` - Pagination offset **Returns:** `Promise` - Matching relationships (each with `subtype` at top level when set) --- ## Batch Operations ### `addMany(params)` β†’ `Promise>` Add multiple entities in one operation. ```typescript const result = await brain.addMany({ items: [ { data: 'Entity 1', type: NounType.Document }, { data: 'Entity 2', type: NounType.Concept } ] }) console.log(result.successful) // Array of IDs console.log(result.failed) // Array of errors ``` **Returns:** `Promise>` - Success/failure results --- ### `removeMany(params)` β†’ `Promise>` Remove multiple entities. ```typescript const result = await brain.removeMany({ ids: [id1, id2, id3] }) ``` --- ### `updateMany(params)` β†’ `Promise>` Update multiple entities. ```typescript const result = await brain.updateMany({ items: [ { id: id1, metadata: { updated: true } }, { id: id2, data: 'New content' } ] }) ``` --- ### `relateMany(params)` β†’ `Promise` Create multiple relationships. ```typescript const ids = await brain.relateMany({ items: [ { from: id1, to: id2, type: VerbType.RelatedTo }, { from: id1, to: id3, type: VerbType.Contains } ] }) ``` --- ## Database Values & Time Travel (Db API) Brainy 8.0's generational MVCC exposes the whole store as an immutable value: the **`Db`**. Pin the current state in O(1), commit atomic multi-write batches, query any past generation with the full query surface, cut instant snapshots, and ask what-if questions in memory. The exact guarantees live in the **[consistency model](../concepts/consistency-model.md)**; recipes live in **[Snapshots & Time Travel](../guides/snapshots-and-time-travel.md)**. ### `generation()` β†’ `number` The store's current generation β€” a monotonic watermark advanced once per committed `transact()` batch and once per single-operation write. Never reissued, including across restarts and `restore()`. ```typescript const g = brain.generation() ``` --- ### `now()` β†’ `Db` Pin the current generation and return an immutable view β€” O(1), no I/O. The view keeps reading exactly this state no matter what commits afterwards. ```typescript const db = brain.now() await brain.update({ id, metadata: { v: 2 } }) await db.get(id) // still sees v: 1 β€” pinned await brain.get(id) // sees v: 2 β€” live await db.release() // unpin (enables history compaction) ``` **Returns:** `Db` β€” release it when done; pins gate `compactHistory()`. --- ### `transact(ops, options?)` β†’ `Promise` Execute a declarative operation batch **atomically**: either every operation applies and the store advances exactly one generation, or none apply and the store is byte-identical to its pre-transaction state. The commit point is an atomic manifest rename; a crash anywhere before it rolls back to the exact pre-transaction bytes on the next open. ```typescript const db = await brain.transact([ { op: 'add', id: orderId, type: NounType.Document, subtype: 'order', data: 'Order #1042' }, { op: 'update', id: customerId, metadata: { lastOrderAt: Date.now() }, ifRev: customer._rev }, { op: 'relate', from: customerId, to: orderId, type: VerbType.Creates, subtype: 'purchase' }, { op: 'remove', id: staleDraftId }, { op: 'unrelate', id: oldRelationId } ], { meta: { author: 'order-service', requestId: 'req-9f2' }, // reified, durable ifAtGeneration: expectedGeneration // whole-store CAS }) db.receipt.ids // resolved id per operation, in input order db.receipt.generation // the committed generation ``` **Operations** (`op` discriminates; parameters mirror the single-operation methods): - `{ op: 'add', ... }` β€” same parameters as `add()`; optional explicit `id` - `{ op: 'update', ... }` β€” same parameters as `update()`, including per-entity `ifRev` CAS - `{ op: 'remove', id }` β€” deletes the entity plus its relationships (same cascade as `delete()`) - `{ op: 'relate', ... }` β€” same parameters as `relate()`, including `bidirectional`; duplicates dedupe to the existing relationship id - `{ op: 'unrelate', id }` β€” deletes a relationship by id Operations may reference ids created earlier in the same batch. **Options:** - `meta?`: `Record` β€” transaction metadata, recorded durably in the transaction log (audit fields: author, reason, request id) - `ifAtGeneration?`: `number` β€” whole-store compare-and-swap; commits only if the store is still at this generation **Returns:** `Promise` β€” pinned at the freshly committed generation, carrying a `receipt`. **Throws:** - `GenerationConflictError` β€” `ifAtGeneration` did not match (nothing staged, generation unchanged) - `RevisionConflictError` β€” an `ifRev` did not match (whole batch rejected) --- ### `asOf(target)` β†’ `Promise` Open an immutable view of **past** state: ```typescript const atGen = await brain.asOf(1041) // generation number const lastWeek = await brain.asOf(new Date(Date.now() - 7 * 86_400_000)) // wall-clock const fromSnapshot = await brain.asOf('/backups/2026-06-01') // snapshot directory ``` - **`number`** β€” pins that generation; reads resolve through the immutable record layer. - **`Date`** β€” resolved via the transaction log to the newest generation committed at or before it. - **`string`** β€” a snapshot directory from `db.persist()`, opened as a self-contained read-only store (equivalent to `Brainy.load()`). Historical views serve the **full query surface**. Metadata-level reads are free; the first index-accelerated query (semantic search, traversal, cursors, aggregation) builds an in-memory index materialization β€” O(n at that generation), once per `Db`, freed on `release()`. **Throws:** `GenerationCompactedError` when the generation's records were reclaimed by `compactHistory()`. **History granularity:** only `transact()` batches produce historical records; single-operation writes advance the clock but stay visible through earlier pins. See the [consistency model](../concepts/consistency-model.md). --- ### `transactionLog(options?)` β†’ `Promise` Read the reified transaction log β€” one entry per committed `transact()` batch, newest first: `{ generation, timestamp, meta? }`. ```typescript const [latest] = await brain.transactionLog({ limit: 1 }) latest.meta // { author: 'order-service', requestId: 'req-9f2' } ``` --- ### `compactHistory(options?)` β†’ `Promise` Reclaim historical record-sets that no retention rule and no live `Db` pin protects. Pinned reads stay correct across compaction, always. ```typescript await brain.compactHistory({ retainGenerations: 100, // keep the 100 most recent commits retainMs: 7 * 24 * 60 * 60 * 1000 // and everything from the last 7 days }) ``` **Returns:** `{ removedGenerations, horizon }` β€” `asOf()` below the horizon throws `GenerationCompactedError`. --- ### `restore(path, { confirm: true })` β†’ `Promise` Replace the store's **entire** state from a snapshot directory. Destructive β€” requires `{ confirm: true }`. All indexes are rebuilt; the generation counter is floored so observed generation numbers are never reissued; live pins do not survive. ```typescript await brain.restore('/backups/2026-06-01', { confirm: true }) ``` --- ### `Brainy.load(path)` β†’ `Promise` (static) Open a persisted snapshot as a self-contained **read-only** store with the full query surface, including vector search. Releasing the returned `Db` closes the underlying instance. ```typescript const db = await Brainy.load('/backups/2026-06-01') const hits = await db.find({ query: 'quarterly invoices' }) await db.release() ``` --- ### The `Db` value Every `Db` is pinned at one generation and serves the full query surface at exactly that state. **Properties:** | Property | Type | Meaning | |---|---|---| | `generation` | `number` | The pinned generation | | `timestamp` | `number` | Pin time (`now()`), commit time (`transact()`), or resolved commit time (`asOf()`) | | `receipt` | `TransactReceipt?` | Present only on `transact()` results | | `speculative` | `boolean` | Whether this view carries a `with()` overlay | | `released` | `boolean` | Whether `release()` has been called | **Methods:** ```typescript await db.get(id) // entity as of this generation await db.find({ where: { status: 'open' } }) // full find() surface await db.find({ query: 'unpaid invoices' }) // semantic search as of this generation await db.related(entityId) // relationships as of this generation await db.since(olderDb) // ids changed between two views const whatIf = await db.with(ops) // speculative in-memory overlay await db.persist('/backups/today') // self-contained hard-link snapshot await db.release() // unpin + free cached materialization ``` - **`with(ops)`** β€” applies `transact()`-style operations **in memory** on top of the view; nothing touches disk, the generation counter, or index providers. Overlay entities carry no embeddings, so index-accelerated queries and `persist()` on overlays throw `SpeculativeOverlayError`; `get()`, metadata-filter `find()`, and filter-based `related()` work fully. Commit the same ops with `transact()` for the full surface. - **`persist(path)`** β€” cuts an instant snapshot (hard links on filesystem storage; byte copies across devices; in-memory stores serialize to the same layout). Requires the view to still be the store's latest generation β€” otherwise `GenerationConflictError`. - **`release()`** β€” idempotent; after release every read throws. A `FinalizationRegistry` backstop releases leaked pins at GC, but explicit release is what makes `compactHistory()` deterministic. ### Db API errors All exported from `@soulcraft/brainy`: | Error | Thrown by | Meaning | |---|---|---| | `GenerationConflictError` | `transact({ ifAtGeneration })`, `db.persist()` | The store moved past the expected generation β€” re-read and retry | | `RevisionConflictError` | `update({ ifRev })`, `transact()` update ops | Per-entity revision moved β€” see [optimistic concurrency](../guides/optimistic-concurrency.md) | | `GenerationCompactedError` | `asOf()` | The requested generation's records were reclaimed β€” persist what you must keep | | `SpeculativeOverlayError` | index-accelerated reads / `persist()` on `with()` overlays | Honest boundary: overlay entities carry no embeddings | --- ## Virtual Filesystem (VFS) Access via `brain.vfs` (property, not method). Auto-initialized during `brain.init()`. ### Filtering VFS Entities All VFS entities (files/folders) have `metadata.isVFSEntity: true` set automatically. Use this to filter VFS entities from semantic search results: ```typescript // Exclude VFS entities from semantic search const semanticOnly = await brain.find({ query: 'artificial intelligence', where: { isVFSEntity: { notEquals: true } // Only semantic entities } }) // Or filter to ONLY VFS entities const vfsOnly = await brain.find({ where: { isVFSEntity: { equals: true } // Only VFS files/folders } }) // Check if an entity is a VFS entity if (entity.metadata.isVFSEntity === true) { console.log('This is a VFS file or folder') } ``` **Why this matters:** Without filtering, VFS files/folders can appear in concept explorers and semantic search results where they don't belong. --- ### Basic File Operations #### `vfs.readFile(path, options?)` β†’ `Promise` Read file content. ```typescript const content = await brain.vfs.readFile('/docs/README.md') console.log(content.toString()) ``` --- #### `vfs.writeFile(path, data, options?)` β†’ `Promise` Write file content. ```typescript await brain.vfs.writeFile('/docs/README.md', 'New content', { encoding: 'utf-8' }) ``` --- #### `vfs.unlink(path)` β†’ `Promise` Delete a file. ```typescript await brain.vfs.unlink('/docs/old-file.md') ``` --- ### Directory Operations #### `vfs.mkdir(path, options?)` β†’ `Promise` Create directory. ```typescript await brain.vfs.mkdir('/projects/new-app', { recursive: true }) ``` --- #### `vfs.readdir(path, options?)` β†’ `Promise` List directory contents. ```typescript const files = await brain.vfs.readdir('/projects') // With file types const entries = await brain.vfs.readdir('/projects', { withFileTypes: true }) entries.forEach(entry => { console.log(entry.name, entry.isDirectory() ? 'DIR' : 'FILE') }) ``` --- #### `vfs.rmdir(path, options?)` β†’ `Promise` Remove directory. ```typescript await brain.vfs.rmdir('/old-project', { recursive: true }) ``` --- #### `vfs.stat(path)` β†’ `Promise` Get file/directory stats. ```typescript const stats = await brain.vfs.stat('/docs/README.md') console.log(stats.size) // File size console.log(stats.mtime) // Modified time console.log(stats.isDirectory()) // Is directory? ``` --- ### Semantic Operations #### `vfs.search(query, options?)` β†’ `Promise` Semantic file search. ```typescript const results = await brain.vfs.search('React components with hooks', { path: '/src', limit: 10 }) ``` --- #### `vfs.findSimilar(path, options?)` β†’ `Promise` Find similar files. ```typescript const similar = await brain.vfs.findSimilar('/src/App.tsx', { limit: 5, threshold: 0.7 }) ``` --- ### Tree Operations #### `vfs.getTreeStructure(path, options?)` β†’ `Promise` Get directory tree (prevents infinite recursion). ```typescript const tree = await brain.vfs.getTreeStructure('/projects', { maxDepth: 3 }) ``` --- #### `vfs.getDescendants(path, options?)` β†’ `Promise` Get all descendants with optional filtering. ```typescript const files = await brain.vfs.getDescendants('/src', { filter: (entity) => entity.name.endsWith('.tsx') }) ``` --- ### Metadata & Relationships #### `vfs.getMetadata(path)` β†’ `Promise` Get file metadata. ```typescript const meta = await brain.vfs.getMetadata('/src/App.tsx') console.log(meta.todos) // Extracted TODOs console.log(meta.tags) // Tags ``` --- #### `vfs.getRelationships(path)` β†’ `Promise` Get file relationships. ```typescript const rels = await brain.vfs.getRelationships('/src/App.tsx') // Returns: imports, references, dependencies ``` --- #### `vfs.getTodos(path)` β†’ `Promise` Get TODOs from a file. ```typescript const todos = await brain.vfs.getTodos('/src/App.tsx') ``` --- #### `vfs.searchEntities(query)` β†’ `Promise>` Search for semantic entities tracked by the VFS, filtered by type, name, or metadata. ```typescript const people = await brain.vfs.searchEntities({ type: 'person', // entity type filter name: 'Ada', // semantic name search where: { role: 'author' }, // metadata filters limit: 50 }) ``` --- **[πŸ“– Complete VFS Documentation β†’](../vfs/QUICK_START.md)** --- ## Import & Export ### `import(source, options?)` β†’ `Promise` Smart import with auto-detection (CSV, Excel, PDF, JSON, URLs). ```typescript // CSV import await brain.import('data.csv', { format: 'csv', createEntities: true }) // Excel import (all sheets processed automatically) await brain.import('sales.xlsx', { format: 'excel', vfsPath: '/imports/sales', // optional: mirror into the VFS groupBy: 'sheet' }) // PDF import (tables extracted automatically) await brain.import('research.pdf', { format: 'pdf' }) // URL import await brain.import('https://api.example.com/data.json') ``` **Parameters:** - `source`: `string | Buffer | object` - File path, URL, buffer, or object - `options?`: Import configuration - `format?`: `'excel' | 'pdf' | 'csv' | 'json' | 'markdown' | 'yaml' | 'docx' | 'image'` - Auto-detected if omitted - `vfsPath?`: `string` - Mirror imported content into the VFS at this path - `groupBy?`: `'type' | 'sheet' | 'flat' | 'custom'` - VFS grouping strategy - `createEntities?`: `boolean` - Create entities from rows - `createRelationships?`: `boolean` - Create relationships between extracted entities - `preserveSource?`: `boolean` - Save the original file in the VFS - `enableNeuralExtraction?`: `boolean` - Extract entity names via AI - `enableRelationshipInference?`: `boolean` - Infer relationships via AI - `enableConceptExtraction?`: `boolean` - Extract entity types via AI - `confidenceThreshold?`: `number` - Minimum confidence for extracted entities - `onProgress?`: `(progress) => void` - Progress callback (stage, counts, throughput, ETA) **Returns:** `Promise` - Import statistics **[πŸ“– Complete Import Guide β†’](../guides/import-anything.md)** --- ### Export & Import (portable) + Snapshots (native) **Portable graph export/import** β€” `brain.export()` / `brain.import()` (`PortableGraph` v1, versioned JSON, partial-or-whole, cross-version). `export()` lives on the immutable `Db`, so it composes with `now()`/`asOf()`/`with()`: ```typescript // Export part or all of the brain to a portable, versioned document const graph = await brain.export({ ids }, { includeVectors: true }) // Restore it β€” import() routes a PortableGraph to the graph round-trip (merge by id) await otherBrain.import(graph, { onConflict: 'merge' }) // Time-travel export (serialize a past generation) / what-if export (a speculative state) const past = await brain.asOf(gen) const asWas = await past.export({ collection: id }) await past.release() await brain.now().with(ops).export({ ids }) ``` Selectors: `{ ids }`, `{ collection }` (alias `memberOf`), `{ connected: { from, depth } }`, `{ vfsPath }`, predicate (`{ type, subtype, where, service }`), or whole brain (omit). See the **[Export & Import guide](../guides/export-and-import.md)**. Distinct from `brain.import(file)` (CSV/PDF/Excel/JSON ingestion β€” `import()` dispatches on whether you pass a `PortableGraph` or a file). **Native whole-brain snapshot** (generation-preserving, not portable JSON): ```typescript // Instant hard-link snapshot via the Db API const pin = brain.now() await pin.persist('/backups/2026-06-11') await pin.release() // Time-travel to a past generation or timestamp const snapshot = await brain.asOf(new Date('2026-06-01')) const entities = await snapshot.find({ limit: 100 }) await snapshot.release() ``` --- ## Configuration ### Constructor Options ```typescript const brain = new Brainy({ // Storage configuration storage: { type: 'filesystem', // 'memory' | 'filesystem' | 'auto' path: './brainy-data' }, // Vector index configuration (2 knobs) vector: { recall: 'balanced', // 'fast' | 'balanced' | 'accurate' persistMode: 'immediate' // 'immediate' | 'deferred' }, // Model configuration (embedded in WASM - zero config needed) // Model: all-MiniLM-L6-v2 (384 dimensions) // Device: CPU via WASM (works everywhere) // Cache configuration β€” `true`/`false`, or an options object cache: { maxSize: 10000, ttl: 3600000 // 1 hour in ms } }) await brain.init() // Required! VFS auto-initialized ``` --- ## Storage Adapters Brainy 8.0 ships two adapters β€” both support the full Db API (generational history, snapshots, restore). ### Memory (Default for Tests) ```typescript const brain = new Brainy({ storage: { type: 'memory' } }) ``` **Use case:** Development, testing, prototyping --- ### Filesystem (Default for Node) ```typescript const brain = new Brainy({ storage: { type: 'filesystem', path: './brainy-data' } }) ``` **Use case:** Node.js applications, single-node production deployments For off-site backup, snapshot `path` from your scheduler (`gsutil rsync`, `aws s3 sync`, `rclone`, or `tar`) β€” Brainy itself doesn't reach out to cloud object stores. --- ### Auto ```typescript const brain = new Brainy({ storage: { type: 'auto', path: './brainy-data' } }) ``` Picks `'filesystem'` on Node with a writable `path`, falls back to `'memory'` otherwise. --- ## Utility Methods ### `clear()` β†’ `Promise` Clear all data (entities and relationships). ```typescript await brain.clear() ``` --- ### `getNounCount()` β†’ `Promise` Get total entity count. ```typescript const count = await brain.getNounCount() ``` --- ### `getVerbCount()` β†’ `Promise` Get total relationship count. ```typescript const count = await brain.getVerbCount() ``` --- ### Subtype & facet APIs Full guide: **[Subtypes & Facets](../guides/subtypes-and-facets.md)**. #### `counts.bySubtype(type, subtype?)` β†’ `Record | number` O(1) subtype counts for a NounType (backed by the persisted rollup). ```typescript brain.counts.bySubtype(NounType.Person) // β†’ { employee: 12, customer: 847, vendor: 34 } brain.counts.bySubtype(NounType.Person, 'employee') // β†’ 12 ``` #### `counts.topSubtypes(type, n=10)` β†’ `Array<[subtype, count]>` Top N subtypes ranked by count. ```typescript brain.counts.topSubtypes(NounType.Person, 3) // β†’ [['customer', 847], ['employee', 12], ['vendor', 34]] ``` #### `subtypesOf(type)` β†’ `string[]` Sorted distinct subtypes seen for a NounType. ```typescript brain.subtypesOf(NounType.Person) // β†’ ['customer', 'employee', 'vendor'] ``` #### `counts.byRelationshipSubtype(verb, subtype?)` β†’ `Record | number` Verb-side mirror of `counts.bySubtype`. O(1) per-VerbType-per-subtype counts. ```typescript brain.counts.byRelationshipSubtype(VerbType.ReportsTo) // β†’ { direct: 12, 'dotted-line': 3 } brain.counts.byRelationshipSubtype(VerbType.ReportsTo, 'direct') // β†’ 12 ``` #### `counts.topRelationshipSubtypes(verb, n=10)` β†’ `Array<[subtype, count]>` Top N subtypes for a `VerbType` ranked by count. ```typescript brain.counts.topRelationshipSubtypes(VerbType.ReportsTo, 3) // β†’ [['direct', 12], ['dotted-line', 3]] ``` #### `relationshipSubtypesOf(verb)` β†’ `string[]` Sorted distinct subtypes seen for a `VerbType`. ```typescript brain.relationshipSubtypesOf(VerbType.ReportsTo) // β†’ ['direct', 'dotted-line'] ``` #### `audit(options?)` β†’ `Promise` (7.30.1+) Diagnostic β€” find entities and relationships missing a `subtype` value, grouped by type. The companion to `migrateField()` / `fillSubtypes()` β€” answers "what would break if I enabled strict subtype enforcement?". ```typescript const report = await brain.audit() // { // entitiesWithoutSubtype: { event: 24, document: 3 }, // relationshipsWithoutSubtype: { relatedTo: 1402 }, // total: 1429, // scanned: 8400, // recommendation: 'Found 1429 entries without subtype. ...' // } ``` **Parameters:** - `options.includeVFS?`: `boolean` β€” When `false` (default), VFS infrastructure entities (`metadata.isVFSEntity` / `metadata.isVFS`) are excluded. They bypass enforcement anyway, so counting them is noise. - `options.batchSize?`: `number` β€” Pagination batch size (default 200). - `options.onProgress?`: `(progress: { scanned, missingSubtype }) => void` β€” Progress callback per batch. Run before adopting an SDK that registers `requireSubtype()` rules, or before upgrading to Brainy 8.0 (which makes strict mode the default). See the [Strict mode in practice](../guides/subtypes-and-facets.md#strict-mode-in-practice-for-sdk-style-vocabulary-consumers) guide for the full migration recipe. #### `requireSubtype(type, options?)` β†’ `void` Register subtype enforcement for a specific `NounType` or `VerbType`. Unified API for nouns and verbs. Composes with the brain-wide `requireSubtype` constructor flag. ```typescript // Lock down Person sub-classification brain.requireSubtype(NounType.Person, { values: ['employee', 'customer', 'vendor'], required: true }) // Lock down management edges brain.requireSubtype(VerbType.ReportsTo, { values: ['direct', 'dotted-line'], required: true }) ``` **Parameters:** - `type`: `NounType | VerbType` - The type to register - `options.values?`: `string[]` - Vocabulary whitelist (rejects off-vocab values) - `options.required?`: `boolean` - Whether subtype is required (default: `true`) #### Brain-wide strict mode β€” `new Brainy({ requireSubtype })` Constructor option that enforces subtype on every `add()` / `addMany()` / `update()` / `relate()` / `relateMany()` / `updateRelation()` for every type: ```typescript // Every write must include subtype const brain = new Brainy({ requireSubtype: true }) // Exempt specific types (e.g. catch-all Thing) const brain2 = new Brainy({ requireSubtype: { except: [NounType.Thing, NounType.Custom] } }) ``` When strict mode is on: - Every public write path checks the pairing guarantee. - `addMany()` / `relateMany()` validate all items BEFORE any storage write β€” atomic-fail, no partial writes. - Brainy's own VFS infrastructure writes bypass via the `metadata.isVFSEntity: true` marker. - Per-type registrations always apply regardless of the brain-wide flag. The default since 8.0.0 β€” pass `requireSubtype: false` to opt out while migrating pre-8.0 data. #### `trackField(name, options?)` β†’ `void` Register a metadata field for cardinality + per-NounType breakdown stats. With `values: [...]`, validates against the whitelist on `add()`/`update()`. ```typescript brain.trackField('status') // basic brain.trackField('status', { perType: true }) // with per-NounType breakdown brain.trackField('priority', { values: ['low', 'med', 'high'] }) // strict vocabulary ``` #### `counts.byField(name, options?)` β†’ `Promise>` Counts by value for a tracked field. Requires `perType: true` registration if filtering by NounType. ```typescript await brain.counts.byField('status') // β†’ { todo: 12, doing: 3, done: 47 } await brain.counts.byField('status', { type: NounType.Task }) // β†’ { todo: 8, doing: 2, done: 30 } ``` #### `migrateField(options)` β†’ `Promise` Stream-and-rewrite a field across the brain. Supports `metadata.X`, `data.X`, and top-level paths. Idempotent. ```typescript // One-shot rewrite await brain.migrateField({ from: 'metadata.kind', to: 'subtype' }) // Deprecation window β€” keep source field readable await brain.migrateField({ from: 'data.kind', to: 'subtype', readBoth: true }) // With progress reporting await brain.migrateField({ from: 'metadata.kind', to: 'subtype', batchSize: 500, onProgress: ({ scanned, migrated }) => console.log(`${scanned} / ${migrated}`) }) ``` Returns `{ scanned: number, migrated: number, skipped: number, errors: Array<{id, error}> }`. #### `fillSubtypes(rules, options?)` β†’ `Promise` (8.0+) Back-fill missing `subtype` values across entities AND relationships in one streaming pass β€” the migration companion to `audit()`. Keys are `NounType`/`VerbType` values; each rule is a literal subtype string or a function deriving one from the entry (return `undefined` to decline). Idempotent: entries that already carry a subtype are never touched, so a crashed run is resumed safely by re-running. ```typescript const report = await brain.fillSubtypes({ [NounType.Person]: (e) => e.metadata?.kind ?? 'unspecified', // derived [NounType.Document]: 'general', // literal default [VerbType.RelatedTo]: 'unspecified' // relationship rule }) // β†’ { scanned, filled, skipped, errors, byType } ``` **Parameters:** - `rules`: `FillSubtypeRules` - Map of NounType/VerbType β†’ literal subtype or `(entry) => string | undefined` - `options.includeVFS?`: `boolean` - Also fill VFS infrastructure entries (default `false`) - `options.batchSize?`: `number` - Pagination batch size (default `200`) - `options.onProgress?`: `(progress: { scanned, filled, skipped }) => void` - Per-batch callback Returns `{ scanned, filled, skipped, errors, byType }`. After a clean run, `skipped` equals the remaining `audit().total`. See the [migration recipe](../guides/subtypes-and-facets.md). --- ### `embed(data)` β†’ `Promise` ✨ Generate embedding vector from text or data. ```typescript const vector = await brain.embed('Hello world') // 384-dimensional vector console.log(vector.length) // 384 ``` --- ### `embedBatch(texts)` β†’ `Promise` ✨ Batch embed multiple texts using native WASM batch API (single forward pass). ```typescript const embeddings = await brain.embedBatch([ 'Machine learning is fascinating', 'Deep neural networks', 'Natural language processing' ]) console.log(embeddings.length) // 3 console.log(embeddings[0].length) // 384 ``` > Uses the WASM engine's native `embed_batch()` for a single model forward pass instead of N individual calls. This is the same batch API used internally by `highlight()`. --- ### `similarity(textA, textB)` β†’ `Promise` ✨ Calculate semantic similarity between two texts. ```typescript const score = await brain.similarity( 'The cat sat on the mat', 'A feline was resting on the rug' ) console.log(score) // ~0.85 (high semantic similarity) ``` **Returns:** Score from 0 (different) to 1 (identical meaning) --- ### `neighbors(entityId, options?)` β†’ `Promise` ✨ Get graph neighbors of an entity. ```typescript // Get all connected entities const neighbors = await brain.neighbors(entityId) // Get outgoing connections only const outgoing = await brain.neighbors(entityId, { direction: 'outgoing', limit: 10 }) // Multi-hop traversal const extended = await brain.neighbors(entityId, { depth: 2, direction: 'both' }) ``` **Options:** - `direction`: `'outgoing' | 'incoming' | 'both'` (default: 'both') - `depth`: `number` - Traversal depth (default: 1) - `verbType`: `VerbType` - Filter by relationship type - `limit`: `number` - Maximum neighbors to return --- ### `findDuplicates(options?)` β†’ `Promise` ✨ Find semantic duplicates in the database. ```typescript // Find all duplicates const duplicates = await brain.findDuplicates() for (const group of duplicates) { console.log('Original:', group.entity.id) for (const dup of group.duplicates) { console.log(` Duplicate: ${dup.entity.id} (${dup.similarity.toFixed(2)})`) } } // Find person duplicates with higher threshold const personDupes = await brain.findDuplicates({ type: NounType.Person, threshold: 0.9, limit: 50 }) ``` **Options:** - `threshold`: `number` - Minimum similarity (default: 0.85) - `type`: `NounType` - Filter by entity type - `limit`: `number` - Maximum duplicate groups (default: 100) --- ### `indexStats()` β†’ `Promise` ✨ Get comprehensive index statistics. ```typescript const stats = await brain.indexStats() console.log(`Entities: ${stats.entities}`) console.log(`Vectors: ${stats.vectors}`) console.log(`Relationships: ${stats.relationships}`) console.log(`Memory: ${(stats.memoryUsage.total / 1024 / 1024).toFixed(1)}MB`) console.log(`Fields: ${stats.metadataFields.join(', ')}`) ``` **Returns:** - `entities` - Total entity count - `vectors` - Total vectors in the vector index - `relationships` - Total relationships in graph - `metadataFields` - Indexed metadata fields - `memoryUsage.vectors` - Vector memory (bytes) - `memoryUsage.graph` - Graph memory (bytes) - `memoryUsage.metadata` - Metadata index memory (bytes) - `memoryUsage.total` - Total memory usage --- ### `cluster(options?)` β†’ `Promise` ✨ Cluster entities by semantic similarity. ```typescript // Find all clusters const clusters = await brain.cluster() for (const cluster of clusters) { console.log(`${cluster.clusterId}: ${cluster.entities.length} entities`) } // Find document clusters with centroids const docClusters = await brain.cluster({ type: NounType.Document, threshold: 0.85, minClusterSize: 3, includeCentroid: true }) ``` **Options:** - `threshold`: `number` - Similarity threshold (default: 0.8) - `type`: `NounType` - Filter by entity type - `minClusterSize`: `number` - Minimum cluster size (default: 2) - `limit`: `number` - Maximum clusters to return (default: 100) - `includeCentroid`: `boolean` - Calculate cluster centroids (default: false) **Returns:** - `clusterId` - Unique cluster identifier - `entities` - Array of entities in the cluster - `centroid` - Average embedding vector (if includeCentroid is true) --- ### `getStats(options?)` β†’ `Promise` Get complete entity/relationship statistics (convenience wrapper over `brain.counts`). ```typescript const stats = await brain.getStats() console.log(stats.entities.total) // total entity count console.log(stats.entities.byType) // counts per NounType console.log(stats.relationships) // relationship stats console.log(stats.density) // relationships per entity // Exclude VFS infrastructure entities from the counts const semanticOnly = await brain.getStats({ excludeVFS: true }) ``` --- ## Lifecycle ### Initialization ```typescript const brain = new Brainy(config) await brain.init() // Required! VFS auto-initialized here ``` VFS is auto-initialized during `brain.init()` - no separate `vfs.init()` needed! --- ### Shutdown ```typescript await brain.close() // Graceful shutdown β€” flushes pending writes and releases the writer lock ``` --- ## Examples ### Basic CRUD ```typescript // Create const id = await brain.add({ data: 'Quantum computing breakthrough', type: NounType.Concept, metadata: { category: 'tech', year: 2024 } }) // Read const entity = await brain.get(id) // Update await brain.update({ id, metadata: { updated: true } }) // Remove await brain.remove(id) ``` --- ### Knowledge Graphs ```typescript // Create entities const ai = await brain.add({ data: 'Artificial Intelligence', type: NounType.Concept }) const ml = await brain.add({ data: 'Machine Learning', type: NounType.Concept }) // Create relationship await brain.relate({ from: ml, to: ai, type: VerbType.IsA }) // Traverse graph const results = await brain.find({ connected: { from: ai, depth: 2 } }) ``` --- ### Triple Intelligence Query ```typescript const results = await brain.find({ query: 'modern frontend frameworks', // πŸ” Vector where: { // πŸ“Š Document year: { greaterThan: 2020 }, category: { oneOf: ['framework', 'library'] } }, connected: { // πŸ•ΈοΈ Graph to: reactId, depth: 2, type: VerbType.BuiltOn }, limit: 10 }) ``` --- ### Database-as-a-Value Workflow ```typescript // Speculate: what would this change look like? (nothing touches disk) const base = brain.now() const whatIf = await base.with([ { op: 'add', type: NounType.Document, subtype: 'note', data: 'New feature', metadata: { draft: true } } ]) await whatIf.find({ where: { draft: true } }) await whatIf.release() await base.release() // Commit it for real β€” one atomic generation, with audit metadata await brain.transact( [{ op: 'add', type: NounType.Document, subtype: 'note', data: 'New feature', metadata: { draft: true } }], { meta: { author: 'dev@example.com', message: 'Add new feature' } } ) ``` --- ### VFS File Management ```typescript // Write files await brain.vfs.writeFile('/docs/README.md', 'Project documentation') await brain.vfs.mkdir('/src/components', { recursive: true }) // Read files const content = await brain.vfs.readFile('/docs/README.md') // Semantic search const reactFiles = await brain.vfs.search('React components with hooks', { path: '/src' }) // Get tree structure (safe, prevents infinite recursion) const tree = await brain.vfs.getTreeStructure('/projects', { maxDepth: 3 }) ``` --- ## Type System Reference Stage 3 CANONICAL taxonomy with 169 types (42 nouns + 127 verbs) ### Noun Types (42) Brainy uses a comprehensive noun type system covering 96-97% of human knowledge: **Core Entity Types (7)** - `NounType.Person` - Individual human entities - `NounType.Organization` - Companies, institutions, collectives - `NounType.Location` - Geographic and spatial entities - `NounType.Thing` - Physical objects and artifacts - `NounType.Concept` - Abstract ideas and principles - `NounType.Event` - Temporal occurrences - `NounType.Agent` - AI agents, bots, automated systems **Digital/Content Types (4)** - `NounType.Document` - Text-based files and written content - `NounType.Media` - Audio, video, images - `NounType.File` - Generic digital files - `NounType.Message` - Communication content **Business Types (4)** - `NounType.Product` - Commercial products - `NounType.Service` - Service offerings - `NounType.Task` - Actions, todos, work items - `NounType.Project` - Organized initiatives **Scientific Types (2)** - `NounType.Hypothesis` - Theories and propositions - `NounType.Experiment` - Studies and investigations **And 25 more types** including: `Organism`, `Substance`, `Quality`, `TimeInterval`, `Function`, `Proposition`, `Collection`, `Dataset`, `Process`, `State`, `Role`, `Language`, `Currency`, `Measurement`, `Contract`, `Regulation`, `Interface`, `Resource`, `Custom`, `SocialGroup`, `Institution`, `Norm`, `InformationContent`, `InformationBearer`, `Relationship` ### Verb Types (127) Brainy supports 127 relationship types organized into categories: **Foundational (7)** - `VerbType.InstanceOf`, `VerbType.SubclassOf`, `VerbType.ParticipatesIn` - `VerbType.RelatedTo`, `VerbType.Contains`, `VerbType.PartOf`, `VerbType.References` **Spatial & Temporal (14)** - Location: `LocatedAt`, `AdjacentTo`, `ContainsSpatially`, `OverlapsSpatially`, `Above`, `Below`, `Inside`, `Outside`, `Facing` - Time: `Precedes`, `During`, `OccursAt`, `Overlaps`, `ImmediatelyAfter`, `SimultaneousWith` **Causal & Dependency (11)** - Direct: `Causes`, `Enables`, `Prevents`, `DependsOn`, `Requires` - Modal: `CanCause`, `MustCause`, `WouldCauseIf`, `ProbablyCauses` - Variations: `RigidlyDependsOn`, `FunctionallyDependsOn`, `HistoricallyDependsOn` **Creation & Change (10)** - Lifecycle: `Creates`, `Transforms`, `Becomes`, `Modifies`, `Consumes`, `Destroys` - Properties: `GainsProperty`, `LosesProperty`, `RemainsSame`, `PersistsThrough` **Social & Communication (8)** - `MemberOf`, `WorksWith`, `FriendOf`, `Follows`, `Likes`, `ReportsTo`, `Mentors`, `Communicates` **Epistemic & Modal (14)** - Knowledge: `Knows`, `Doubts`, `Believes`, `Learns` - Mental states: `Desires`, `Intends`, `Fears`, `Loves`, `Hates`, `Hopes`, `Perceives` - Modality: `CouldBe`, `MustBe`, `Counterfactual` **Measurement & Comparison (9)** - `Measures`, `MeasuredIn`, `ConvertsTo`, `HasMagnitude`, `GreaterThan` - `SimilarityDegree`, `ApproximatelyEquals`, `MoreXThan`, `HasDegree` **And 54 more specialized verbs** including ownership, composition, uncertainty, deontic relationships (obligations/permissions), context-dependent truth, spatial/temporal variations, information theory, and meta-level relationships. ### Complete Reference For the full taxonomy with all 169 types and their descriptions, see: - **[Stage 3 CANONICAL Taxonomy](../STAGE3-CANONICAL-TAXONOMY.md)** - Complete list with categories - **[Noun-Verb Taxonomy Architecture](../architecture/noun-verb-taxonomy.md)** - Design rationale ### Migration from pre-Stage-3 taxonomies **Breaking Changes:** - `NounType.Content` removed β†’ Use `Document`, `Message`, or `InformationContent` - `NounType.User` removed β†’ Use `Person` or `Agent` - `NounType.Topic` removed β†’ Use `Concept` or `Category` **New Types Added:** - **+11 noun types**: Agent, Organism, Substance, Quality, TimeInterval, Function, Proposition, Custom, SocialGroup, Institution, Norm, InformationContent, InformationBearer, Relationship - **+87 verb types**: Extensive additions across all categories --- ## Key Features - βœ… **Database as a Value** - `brain.now()` pins the whole store as an immutable `Db` in O(1) - βœ… **Atomic Transactions** - `brain.transact()` commits multi-write batches all-or-nothing - βœ… **Two-Level CAS** - per-entity `ifRev` and whole-store `ifAtGeneration` - βœ… **Time Travel** - `brain.asOf()` serves the full query surface at any reachable past generation - βœ… **Instant Snapshots** - `db.persist()` cuts hard-link snapshots; `Brainy.load()` opens them read-only - βœ… **Speculative Writes** - `db.with()` answers what-if questions purely in memory - βœ… **Reified Transaction Metadata** - audit fields recorded durably, readable via `transactionLog()` - βœ… **VFS Entity Filtering** - All VFS entities have the `isVFSEntity: true` flag - βœ… **VFS Auto-Initialization** - No separate `vfs.init()` calls - βœ… **VFS Property Access** - Use `brain.vfs.method()` instead of `brain.vfs().method()` - βœ… **Universal Storage Support** - Filesystem and memory adapters share one on-disk contract --- ## Support & Resources - **πŸ“– Documentation:** [Full Documentation](../) - **πŸ› Issues:** [GitHub Issues](https://github.com/soulcraftlabs/brainy/issues) - **πŸ’¬ Discussions:** [GitHub Discussions](https://github.com/soulcraftlabs/brainy/discussions) - **πŸ“¦ NPM:** [@soulcraft/brainy](https://www.npmjs.com/package/@soulcraft/brainy) - **⭐ GitHub:** [Star us](https://github.com/soulcraftlabs/brainy) --- ## See Also - **[Data Model](../DATA_MODEL.md)** - Entity structure, data vs metadata, storage fields - **[Query Operators](../QUERY_OPERATORS.md)** - All BFO operators with examples and indexed vs in-memory matrix - **[Triple Intelligence Architecture](../architecture/triple-intelligence.md)** - How vector + graph + document work together - **[Find System](../FIND_SYSTEM.md)** - Natural language find() details - **[VFS Quick Start](../vfs/QUICK_START.md)** - Complete VFS documentation - **[Import Anything Guide](../guides/import-anything.md)** - CSV, Excel, PDF, URL imports - **[Consistency Model](../concepts/consistency-model.md)** - The guarantees behind the Db API - **[Snapshots & Time Travel](../guides/snapshots-and-time-travel.md)** - Backup, restore, what-if, audit recipes --- **License:** MIT Β© Brainy Contributors --- *Brainy - The Knowledge Operating System* *From prototype to planet-scale β€’ Zero configuration β€’ Triple Intelligenceβ„’ β€’ Database as a Value*