Optimistic concurrency for multi-writer coordination — the read-then-CAS
lock pattern + idempotent-bootstrap singleton inserts. Lands the surface the
SDK scheduler asked for in BRAINY-EXPOSE-TRANSACTIONS, scoped to what ships
cleanly without painting the 8.0 transact() API into a corner.
A. PER-ENTITY _rev FIELD
- src/coreTypes.ts — HNSWNounWithMetadata gains optional `_rev?: number`;
STANDARD_ENTITY_FIELDS includes it so resolveEntityField routes correctly.
- src/types/brainy.types.ts — Entity<T> gains optional `_rev?: number`;
Result<T> mirrors it on the convenience flatten layer.
- src/brainy.ts add() — initializes `_rev: 1` in storageMetadata. New entities
always start at 1.
- src/brainy.ts update() — reads currentRev off the persisted metadata
(falls back to 1 for pre-7.31.0 entities with no _rev), writes
`_rev: currentRev + 1` into the updated metadata. Every successful update()
bumps by exactly 1.
- src/brainy.ts convertNounToEntity + convertMetadataToEntity — both pull
_rev out of the storage metadata and surface it at the top level of Entity.
Pre-7.31.0 entities (no _rev in storage) read as `_rev: 1` so consumers
see a consistent value.
- src/storage/baseStorage.ts — six destructure sites updated to pull _rev
out of the metadata bag so it doesn't leak into customMetadata. Noun-side
returns surface _rev; verb-side destructures correctly but doesn't expose
it on HNSWVerbWithMetadata (verb CAS is future work).
- src/brainy.ts createResult() — flattens entity._rev onto the Result for
backward compat with the existing convenience-field layer.
B. update({ ifRev }) OPTIMISTIC CONCURRENCY
- src/types/brainy.types.ts — UpdateParams<T> gains optional `ifRev?: number`.
- src/transaction/RevisionConflictError.ts (NEW) — carries `{ id, expected,
actual }`. Message names the recipe: refetch with brain.get() and retry
with the latest _rev. Subclass of Error.
- src/brainy.ts update() — when params.ifRev is provided, compares against
currentRev (the rev we just read) and throws RevisionConflictError on
mismatch before any storage write. Omitting ifRev keeps the prior
unconditional-update behavior; existing consumers see no change.
- src/transaction/index.ts — exports RevisionConflictError.
- src/index.ts — public export of RevisionConflictError.
C. add({ ifAbsent }) BY-ID IDEMPOTENT INSERT
- src/types/brainy.types.ts — AddParams<T> gains optional `ifAbsent?: boolean`;
AddManyParams<T> mirrors it as a batch-level flag.
- src/brainy.ts add() — when params.id AND params.ifAbsent, pre-reads
storage.getNounMetadata(id); if present, returns the existing id without
writing. No throw, no overwrite. Ignored when id is omitted (a fresh UUID
can never collide).
- src/brainy.ts addMany() — propagates the batch-level ifAbsent to each
item's add() call. Per-item ifAbsent takes precedence so callers can
override individual rows.
WHAT'S NOT SHIPPED (and why)
A public brain.transaction(fn) wrapper was on the table but was cut. The
internal TransactionManager exposes raw Operation classes (SaveNounMetadata,
etc.) that take StorageAdapter as a constructor argument. A clean high-level
facade in 7.31.0 would have meant either:
(a) Delegate to brain.add() / update() / relate(). Each of those opens its
own internal transaction and commits before the closure returns. Looks
atomic, isn't — a footgun.
(b) Thread an optional `tx?` through every internal write site in
brainy.ts (8 transactionManager.executeTransaction sites). ~2 days of
real refactor with regression surface, and the API shape changes again
in 8.0 anyway.
The SDK scheduler's actual ask (BRAINY-EXPOSE-TRANSACTIONS) is the
read-then-CAS lock pattern. _rev + ifRev solves it completely. Multi-write
atomicity is the 8.0 brain.transact() use case where the Datomic-style
immutable Db makes it atomic by construction — that's the right home.
TESTS
- New tests/integration/rev-and-ifabsent.test.ts (18 tests):
- _rev initialization (1 on add) and surface on get fast/full paths + find
- _rev auto-bump on update across multiple writes
- update({ ifRev }) pass / fail / message format / omitted / legacy-no-rev
- add({ ifAbsent }) writes when absent / no-op when present / id-required
- addMany({ ifAbsent }) propagation + per-item override
- SDK-scheduler scenario: two concurrent CAS updates, one wins one throws
- Unit suite unchanged: 1468/1468.
- All integration subtype + verb + strict + find-limits + new rev suites
pass: 96/96.
DOCS
- New docs/guides/optimistic-concurrency.md (public: true) — full reference:
the lock pattern, read-modify-write retry, idempotent bootstrap, how _rev
interacts with brain.versions, branches/fork, and VFS, what's coming in 8.0.
- docs/api/README.md — add() and update() entries get the new params + tips
pointing at the new guide.
- RELEASES.md v7.31.0 entry.
CORTEX COMPATIBILITY
Zero changes required. _rev is a metadata column already supported by
NativeColumnStore. The auto-bump runs in Brainy JS before any storage call;
Cortex never sees the per-entity counter.
8.0 FORWARD-COMPAT
_rev, ifRev, RevisionConflictError, and ifAbsent survive the 8.0 Db redesign
unchanged. 8.0 layers brain.transact(tx, { ifAtGeneration }) for whole-tx CAS
on top of the same per-entity mechanism — per-entity for single-record
patterns (job locks, idempotent state machines), generation-based for
"did the world move under me." Locked in .strategy/BRAINY-8.0-SUBTYPE-CONTRACT.md § C-6.
Verification
- npx tsc --noEmit: clean
- npm test: 1468 / 1468 unit
- All integration suites including new rev-and-ifabsent: 96/96
- npm run build: clean
- Closed-source product reference audit: clean
2634 lines
72 KiB
Markdown
2634 lines
72 KiB
Markdown
---
|
||
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, branching, entity versioning, 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 • Git-Style Branching • Entity Versioning • Candle WASM Embeddings
|
||
|
||
**Updated:** 2026-01-06
|
||
**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 }
|
||
})
|
||
|
||
// Fork for safe experimentation
|
||
const experiment = await brain.fork('test-feature')
|
||
await experiment.add({ data: 'test', type: NounType.Document })
|
||
await experiment.commit({ message: 'Add test data' })
|
||
|
||
// Entity versioning
|
||
await brain.versions.save(id, { tag: 'v1.0', description: 'Initial version' })
|
||
await brain.update(id, { category: 'AI' })
|
||
await brain.versions.save(id, { tag: 'v2.0' })
|
||
```
|
||
|
||
---
|
||
|
||
## 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** (HNSW) 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.
|
||
|
||
### 🌳 Git-Style Branching
|
||
Fork, experiment, and commit - Snowflake-style copy-on-write isolation.
|
||
|
||
### 📜 Entity Versioning
|
||
Time-travel and history tracking for individual entities - Git-like version control with content-addressable storage.
|
||
|
||
---
|
||
|
||
## Table of Contents
|
||
|
||
- [Core CRUD Operations](#core-crud-operations)
|
||
- [Search & Query](#search--query)
|
||
- [Aggregation Engine](#aggregation-engine)
|
||
- [Relationships](#relationships)
|
||
- [Batch Operations](#batch-operations)
|
||
- [Branch Management](#branch-management)
|
||
- [Entity Versioning](#entity-versioning)
|
||
- [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<string>`
|
||
|
||
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<string>` - Entity ID
|
||
|
||
---
|
||
|
||
### `get(id)` → `Promise<Entity | null>`
|
||
|
||
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 | null>` - Entity or null if not found
|
||
|
||
---
|
||
|
||
### `update(params)` → `Promise<void>`
|
||
|
||
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<void>`
|
||
|
||
> **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).
|
||
|
||
---
|
||
|
||
### `delete(id)` → `Promise<void>`
|
||
|
||
Delete a single entity.
|
||
|
||
```typescript
|
||
await brain.delete(id)
|
||
```
|
||
|
||
**Parameters:**
|
||
- `id`: `string` - Entity ID
|
||
|
||
**Returns:** `Promise<void>`
|
||
|
||
---
|
||
|
||
## Search & Query
|
||
|
||
### `find(query)` → `Promise<Result[]>`
|
||
|
||
**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 HNSW + 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<Result[]>` - 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<Highlight[]>` ✨
|
||
|
||
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: "<h1>David the Warrior</h1><p>A brave fighter.</p>"
|
||
})
|
||
|
||
// 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<Highlight[]>`
|
||
- `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 `<h1>`, `<p>`, `<code>` | 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', subtype: 'transaction' }
|
||
},
|
||
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<string, unknown>` | Metadata filter (same syntax as `find({ where })`) |
|
||
| `source.service` | `string` | Multi-tenancy filter |
|
||
| `groupBy` | `GroupByDimension[]` | Dimensions to group by — plain field names or `{ field, window }` for time bucketing |
|
||
| `metrics` | `Record<string, AggregateMetricDef>` | Named metrics with `op` (`sum`, `count`, `avg`, `min`, `max`, `stddev`, `variance`) and optional `field` |
|
||
| `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<T>[]` 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
|
||
}
|
||
```
|
||
|
||
### 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 **metadata conventions** on existing NounTypes — no custom types needed:
|
||
|
||
```typescript
|
||
// Transaction = NounType.Event + financial metadata
|
||
await brain.add({
|
||
data: 'Coffee at Blue Bottle',
|
||
type: NounType.Event,
|
||
metadata: {
|
||
domain: 'financial',
|
||
subtype: 'transaction',
|
||
amount: 5.50,
|
||
currency: 'USD',
|
||
category: 'food',
|
||
date: Date.now(),
|
||
merchant: 'Blue Bottle Coffee'
|
||
}
|
||
})
|
||
|
||
// Account = NounType.Collection + financial metadata
|
||
await brain.add({
|
||
data: 'Checking Account',
|
||
type: NounType.Collection,
|
||
metadata: {
|
||
domain: 'financial',
|
||
subtype: 'account',
|
||
accountType: 'checking',
|
||
currency: 'USD',
|
||
institution: 'Chase'
|
||
}
|
||
})
|
||
|
||
// Invoice = NounType.Document + financial metadata
|
||
await brain.add({
|
||
data: 'Invoice #1234 from Acme Corp',
|
||
type: NounType.Document,
|
||
metadata: {
|
||
domain: 'financial',
|
||
subtype: 'invoice',
|
||
amount: 15000,
|
||
currency: 'USD',
|
||
status: 'pending',
|
||
dueDate: Date.UTC(2024, 2, 15),
|
||
vendor: 'Acme Corp'
|
||
}
|
||
})
|
||
```
|
||
|
||
---
|
||
|
||
## Relationships
|
||
|
||
### `relate(params)` → `Promise<string>`
|
||
|
||
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<string>` - Relationship ID
|
||
|
||
---
|
||
|
||
### `updateRelation(params)` → `Promise<void>`
|
||
|
||
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<void>`
|
||
|
||
---
|
||
|
||
### `getRelations(params)` → `Promise<Relation[]>`
|
||
|
||
Get relationships for an entity.
|
||
|
||
```typescript
|
||
// Get all relationships FROM an entity
|
||
const outgoing = await brain.getRelations({ from: entityId })
|
||
|
||
// Get all relationships TO an entity
|
||
const incoming = await brain.getRelations({ to: entityId })
|
||
|
||
// Filter by type
|
||
const related = await brain.getRelations({
|
||
from: entityId,
|
||
type: VerbType.Contains
|
||
})
|
||
|
||
// Filter by subtype (fast path, column-store hit)
|
||
const direct = await brain.getRelations({
|
||
from: entityId,
|
||
type: VerbType.ReportsTo,
|
||
subtype: 'direct'
|
||
})
|
||
|
||
// Set membership on subtype
|
||
const all = await brain.getRelations({
|
||
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<Relation[]>` - Matching relationships (each with `subtype` at top level when set)
|
||
|
||
---
|
||
|
||
## Batch Operations
|
||
|
||
### `addMany(params)` → `Promise<BatchResult<string>>`
|
||
|
||
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<BatchResult<string>>` - Success/failure results
|
||
|
||
---
|
||
|
||
### `deleteMany(params)` → `Promise<BatchResult<string>>`
|
||
|
||
Delete multiple entities.
|
||
|
||
```typescript
|
||
const result = await brain.deleteMany({
|
||
ids: [id1, id2, id3]
|
||
})
|
||
```
|
||
|
||
---
|
||
|
||
### `updateMany(params)` → `Promise<BatchResult<string>>`
|
||
|
||
Update multiple entities.
|
||
|
||
```typescript
|
||
const result = await brain.updateMany({
|
||
updates: [
|
||
{ id: id1, metadata: { updated: true } },
|
||
{ id: id2, data: 'New content' }
|
||
]
|
||
})
|
||
```
|
||
|
||
---
|
||
|
||
### `relateMany(params)` → `Promise<string[]>`
|
||
|
||
Create multiple relationships.
|
||
|
||
```typescript
|
||
const ids = await brain.relateMany({
|
||
relations: [
|
||
{ from: id1, to: id2, type: VerbType.RelatedTo },
|
||
{ from: id1, to: id3, type: VerbType.Contains }
|
||
]
|
||
})
|
||
```
|
||
|
||
---
|
||
|
||
## Branch Management
|
||
|
||
Git-style branching with Snowflake-style copy-on-write.
|
||
|
||
### `fork(branch?, options?)` → `Promise<Brainy>`
|
||
|
||
Create an instant fork (<100ms) with full isolation.
|
||
|
||
```typescript
|
||
// Create a fork
|
||
const experiment = await brain.fork('test-feature')
|
||
|
||
// Make changes safely in isolation
|
||
await experiment.add({ data: 'Test entity', type: NounType.Document })
|
||
await experiment.update({ id: someId, metadata: { modified: true } })
|
||
|
||
// Parent is unaffected!
|
||
const parentData = await brain.find({}) // Original data unchanged
|
||
```
|
||
|
||
**Parameters:**
|
||
- `branch?`: `string` - Branch name (auto-generated if omitted)
|
||
- `options?`: `object`
|
||
- `description?`: `string` - Branch description
|
||
|
||
**Returns:** `Promise<Brainy>` - New Brainy instance on forked branch
|
||
|
||
**How it works:** Snowflake-style COW shares HNSW index, copies only modified nodes (10-20% memory overhead).
|
||
|
||
---
|
||
|
||
### `checkout(branch)` → `Promise<void>`
|
||
|
||
Switch to a different branch.
|
||
|
||
```typescript
|
||
await brain.checkout('main')
|
||
await brain.checkout('test-feature')
|
||
```
|
||
|
||
**Parameters:**
|
||
- `branch`: `string` - Branch name
|
||
|
||
---
|
||
|
||
### `listBranches()` → `Promise<string[]>`
|
||
|
||
List all branches.
|
||
|
||
```typescript
|
||
const branches = await brain.listBranches()
|
||
// ['main', 'test-feature', 'experiment-2']
|
||
```
|
||
|
||
---
|
||
|
||
### `getCurrentBranch()` → `Promise<string>`
|
||
|
||
Get current branch name.
|
||
|
||
```typescript
|
||
const current = await brain.getCurrentBranch()
|
||
// 'main'
|
||
```
|
||
|
||
---
|
||
|
||
### `commit(options?)` → `Promise<string>`
|
||
|
||
Create a commit snapshot.
|
||
|
||
```typescript
|
||
const commitId = await brain.commit({
|
||
message: 'Add new features',
|
||
author: 'dev@example.com',
|
||
metadata: { ticket: 'PROJ-123' }
|
||
})
|
||
```
|
||
|
||
**Parameters:**
|
||
- `message?`: `string` - Commit message
|
||
- `author?`: `string` - Author email
|
||
- `metadata?`: `object` - Additional commit metadata
|
||
|
||
**Returns:** `Promise<string>` - Commit ID
|
||
|
||
---
|
||
|
||
|
||
### `deleteBranch(branch)` → `Promise<void>`
|
||
|
||
Delete a branch (cannot delete 'main').
|
||
|
||
```typescript
|
||
await brain.deleteBranch('old-experiment')
|
||
```
|
||
|
||
---
|
||
|
||
### `getHistory(options?)` → `Promise<Commit[]>`
|
||
|
||
Get commit history.
|
||
|
||
```typescript
|
||
const history = await brain.getHistory({
|
||
branch: 'main',
|
||
limit: 10
|
||
})
|
||
```
|
||
|
||
---
|
||
|
||
### `asOf(commitId, options?)` → `Promise<Brainy>`
|
||
|
||
Create a read-only snapshot at a specific commit for time-travel queries.
|
||
|
||
```typescript
|
||
// Get commit ID from history
|
||
const commits = await brain.getHistory({ limit: 1 })
|
||
const commitId = commits[0].id
|
||
|
||
// Create snapshot (lazy-loading, no eager data loading)
|
||
const snapshot = await brain.asOf(commitId, {
|
||
cacheSize: 10000 // LRU cache size (default: 10000)
|
||
})
|
||
|
||
// Query historical state - full Triple Intelligence works!
|
||
const results = await snapshot.find({
|
||
query: 'AI research',
|
||
where: { category: 'technology' }
|
||
})
|
||
|
||
// Get historical relationships
|
||
const related = await snapshot.getRelated(entityId, { depth: 2 })
|
||
|
||
// MUST close when done to free memory
|
||
await snapshot.close()
|
||
```
|
||
|
||
**Parameters:**
|
||
- `commitId`: `string` - Commit hash to snapshot from
|
||
- `options?`: `object`
|
||
- `cacheSize?`: `number` - LRU cache size for lazy-loading (default: 10000)
|
||
|
||
**Returns:** `Promise<Brainy>` - Read-only Brainy instance with historical state
|
||
|
||
**Features:**
|
||
- **Lazy-Loading** - Loads entities on-demand, not eagerly
|
||
- **Bounded Memory** - LRU cache prevents memory bloat
|
||
- **Full Query Support** - All find(), getRelated(), etc. work on historical data
|
||
- **Read-Only** - Prevents accidental modifications to history
|
||
|
||
**Important:** Always call `snapshot.close()` when done to release resources.
|
||
|
||
---
|
||
|
||
## Entity Versioning
|
||
|
||
Git-style versioning for individual entities with content-addressable storage.
|
||
|
||
### Overview
|
||
|
||
Entity Versioning provides time-travel and history tracking for individual entities:
|
||
|
||
- **Content-Addressable Storage** - Deduplication via SHA-256 hashing
|
||
- **Zero-Config** - Lazy initialization, uses existing indexes
|
||
- **Branch-Isolated** - Versions isolated per branch
|
||
- **Selective Auto-Versioning** - Optional augmentation for automatic version creation
|
||
- **Production-Scale** - Designed for billions of entities
|
||
- **VFS File Support** - Full versioning for VFS files with actual blob content
|
||
|
||
---
|
||
|
||
### `versions.save(entityId, options?)` → `Promise<EntityVersion>`
|
||
|
||
Save a new version of an entity.
|
||
|
||
```typescript
|
||
// Save version with tag
|
||
const version = await brain.versions.save('user-123', {
|
||
tag: 'v1.0',
|
||
description: 'Initial user profile',
|
||
metadata: { author: 'dev@example.com' }
|
||
})
|
||
|
||
console.log(version.version) // 1
|
||
console.log(version.contentHash) // SHA-256 hash
|
||
console.log(version.createdAt) // Timestamp
|
||
```
|
||
|
||
**Parameters:**
|
||
- `entityId`: `string` - Entity ID to version
|
||
- `options?`: `object`
|
||
- `tag?`: `string` - Version tag (e.g., 'v1.0', 'beta')
|
||
- `description?`: `string` - Version description
|
||
- `metadata?`: `object` - Additional version metadata
|
||
|
||
**Returns:** `Promise<EntityVersion>` - Created version
|
||
|
||
**Features:**
|
||
- Automatic deduplication (identical content = same version)
|
||
- Sequential version numbering (1, 2, 3, ...)
|
||
- Content-addressable storage (SHA-256)
|
||
|
||
---
|
||
|
||
### `versions.list(entityId, options?)` → `Promise<EntityVersion[]>`
|
||
|
||
List all versions of an entity.
|
||
|
||
```typescript
|
||
const versions = await brain.versions.list('user-123', {
|
||
limit: 10,
|
||
offset: 0
|
||
})
|
||
|
||
versions.forEach(v => {
|
||
console.log(`Version ${v.version}: ${v.tag} - ${v.description}`)
|
||
})
|
||
```
|
||
|
||
**Parameters:**
|
||
- `entityId`: `string` - Entity ID
|
||
- `options?`: `object`
|
||
- `limit?`: `number` - Max versions to return
|
||
- `offset?`: `number` - Skip versions
|
||
|
||
**Returns:** `Promise<EntityVersion[]>` - Versions (newest first)
|
||
|
||
---
|
||
|
||
### `versions.restore(entityId, versionOrTag)` → `Promise<void>`
|
||
|
||
Restore entity to a previous version.
|
||
|
||
```typescript
|
||
// Restore by version number
|
||
await brain.versions.restore('user-123', 1)
|
||
|
||
// Restore by tag
|
||
await brain.versions.restore('user-123', 'beta')
|
||
```
|
||
|
||
**Parameters:**
|
||
- `entityId`: `string` - Entity ID
|
||
- `versionOrTag`: `number | string` - Version number or tag
|
||
|
||
---
|
||
|
||
### `versions.compare(entityId, version1, version2)` → `Promise<VersionDiff>`
|
||
|
||
Compare two versions.
|
||
|
||
```typescript
|
||
const diff = await brain.versions.compare('user-123', 1, 2)
|
||
|
||
console.log(diff.totalChanges) // Total changes
|
||
console.log(diff.modified) // Modified fields
|
||
console.log(diff.added) // Added fields
|
||
console.log(diff.removed) // Removed fields
|
||
|
||
// Check specific changes
|
||
const nameChange = diff.modified.find(c => c.path === 'metadata.name')
|
||
console.log(`${nameChange.oldValue} → ${nameChange.newValue}`)
|
||
```
|
||
|
||
**Returns:** `Promise<VersionDiff>` - Detailed diff with field-level changes
|
||
|
||
---
|
||
|
||
### `versions.getContent(entityId, versionOrTag)` → `Promise<EntitySnapshot>`
|
||
|
||
Get version content without restoring.
|
||
|
||
```typescript
|
||
// View old version without changing current state
|
||
const v1Content = await brain.versions.getContent('user-123', 1)
|
||
console.log(v1Content.metadata.name) // Old name
|
||
|
||
// Current state unchanged
|
||
const current = await brain.get('user-123')
|
||
console.log(current.metadata.name) // Current name
|
||
```
|
||
|
||
---
|
||
|
||
### `versions.undo(entityId)` → `Promise<void>`
|
||
|
||
Undo to previous version (shorthand for restore to latest-1).
|
||
|
||
```typescript
|
||
// Make a bad change
|
||
await brain.update('user-123', { status: 'deleted' })
|
||
|
||
// Undo immediately
|
||
await brain.versions.undo('user-123')
|
||
```
|
||
|
||
**Alias:** `versions.revert(entityId)`
|
||
|
||
---
|
||
|
||
### `versions.prune(entityId, options)` → `Promise<PruneResult>`
|
||
|
||
Clean up old versions.
|
||
|
||
```typescript
|
||
const result = await brain.versions.prune('user-123', {
|
||
keepRecent: 10, // Keep 10 most recent
|
||
keepTagged: true, // Always keep tagged versions
|
||
olderThan: Date.now() - 30 * 24 * 60 * 60 * 1000 // Older than 30 days
|
||
})
|
||
|
||
console.log(`Deleted ${result.deleted}, kept ${result.kept}`)
|
||
```
|
||
|
||
**Parameters:**
|
||
- `keepRecent?`: `number` - Keep N most recent versions
|
||
- `keepTagged?`: `boolean` - Always keep tagged versions (default: true)
|
||
- `olderThan?`: `number` - Only prune versions older than timestamp
|
||
|
||
---
|
||
|
||
### `versions.getLatest(entityId)` → `Promise<EntityVersion | null>`
|
||
|
||
Get latest version.
|
||
|
||
```typescript
|
||
const latest = await brain.versions.getLatest('user-123')
|
||
if (latest) {
|
||
console.log(`Latest: v${latest.version} (${latest.tag})`)
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### `versions.getVersionByTag(entityId, tag)` → `Promise<EntityVersion | null>`
|
||
|
||
Get version by tag.
|
||
|
||
```typescript
|
||
const beta = await brain.versions.getVersionByTag('user-123', 'beta')
|
||
```
|
||
|
||
---
|
||
|
||
### `versions.count(entityId)` → `Promise<number>`
|
||
|
||
Count versions for an entity.
|
||
|
||
```typescript
|
||
const count = await brain.versions.count('user-123')
|
||
console.log(`${count} versions saved`)
|
||
```
|
||
|
||
---
|
||
|
||
### `versions.hasVersions(entityId)` → `Promise<boolean>`
|
||
|
||
Check if entity has versions.
|
||
|
||
```typescript
|
||
if (await brain.versions.hasVersions('user-123')) {
|
||
console.log('Entity has version history')
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### Auto-Versioning Augmentation
|
||
|
||
Automatically create versions on entity updates.
|
||
|
||
```typescript
|
||
import { VersioningAugmentation } from '@soulcraft/brainy'
|
||
|
||
// Configure auto-versioning
|
||
const versioning = new VersioningAugmentation({
|
||
enabled: true,
|
||
onUpdate: true, // Version on update()
|
||
onDelete: false, // Don't version on delete
|
||
entities: ['user-*'], // Only version users
|
||
excludeEntities: ['temp-*'],
|
||
excludeTypes: ['temporary'],
|
||
keepRecent: 50, // Auto-prune old versions
|
||
keepTagged: true
|
||
})
|
||
|
||
// Apply augmentation
|
||
brain.augment(versioning)
|
||
|
||
// Now updates auto-create versions
|
||
await brain.update('user-123', { name: 'New Name' })
|
||
|
||
// Version automatically created!
|
||
const versions = await brain.versions.list('user-123')
|
||
console.log(`Auto-created version: ${versions[0].version}`)
|
||
```
|
||
|
||
**Configuration:**
|
||
- `enabled`: `boolean` - Enable/disable augmentation
|
||
- `onUpdate`: `boolean` - Version on entity updates
|
||
- `onDelete`: `boolean` - Version before deletion
|
||
- `entities`: `string[]` - Entity ID patterns (glob-style)
|
||
- `excludeEntities`: `string[]` - Exclusion patterns
|
||
- `types`: `string[]` - Entity types to version
|
||
- `excludeTypes`: `string[]` - Types to exclude
|
||
- `keepRecent`: `number` - Auto-prune to keep N versions
|
||
- `keepTagged`: `boolean` - Always keep tagged versions
|
||
|
||
**Pattern Matching:**
|
||
- `['*']` - All entities
|
||
- `['user-*']` - All IDs starting with "user-"
|
||
- `['*-prod']` - All IDs ending with "-prod"
|
||
- `['user-*', 'account-*']` - Multiple patterns
|
||
|
||
---
|
||
|
||
### Branch Isolation
|
||
|
||
Versions are isolated per branch.
|
||
|
||
```typescript
|
||
// Save version on main
|
||
await brain.versions.save('doc-1', { tag: 'main-v1' })
|
||
|
||
// Fork and create version
|
||
const feature = await brain.fork('feature')
|
||
await feature.update('doc-1', { content: 'Feature update' })
|
||
await feature.versions.save('doc-1', { tag: 'feature-v1' })
|
||
|
||
// Versions are isolated
|
||
const mainVersions = await brain.versions.list('doc-1')
|
||
const featureVersions = await feature.versions.list('doc-1')
|
||
|
||
console.log(mainVersions.length !== featureVersions.length) // true
|
||
```
|
||
|
||
---
|
||
|
||
### Architecture
|
||
|
||
**Content-Addressable Storage:**
|
||
- SHA-256 hashing for deduplication
|
||
- Identical content = single storage blob
|
||
- Efficient for entities with few changes
|
||
|
||
**Metadata Indexing:**
|
||
- Leverages existing MetadataIndexManager
|
||
- Fast lookups by entity ID
|
||
- Version number indexing
|
||
|
||
**Storage Structure:**
|
||
```
|
||
_version:{entityId}:{versionNum}:{branch} // Version metadata
|
||
_version_blob:{contentHash} // Content blob (deduplicated)
|
||
```
|
||
|
||
**Performance:**
|
||
- Version save: O(1) if duplicate, O(log N) for index update
|
||
- Version list: O(K) where K = version count
|
||
- Version restore: O(log N) lookup + O(1) restore
|
||
- Pruning: O(K) where K = versions pruned
|
||
|
||
---
|
||
|
||
### Examples
|
||
|
||
#### Basic Versioning Workflow
|
||
|
||
```typescript
|
||
// Create entity
|
||
await brain.add({
|
||
data: 'User profile',
|
||
id: 'user-123',
|
||
type: 'user',
|
||
metadata: { name: 'Alice', email: 'alice@example.com' }
|
||
})
|
||
|
||
// Save v1
|
||
await brain.versions.save('user-123', { tag: 'v1.0' })
|
||
|
||
// Make changes
|
||
await brain.update('user-123', { name: 'Alice Smith' })
|
||
|
||
// Save v2
|
||
await brain.versions.save('user-123', { tag: 'v2.0' })
|
||
|
||
// Compare versions
|
||
const diff = await brain.versions.compare('user-123', 1, 2)
|
||
|
||
// Restore to v1 if needed
|
||
await brain.versions.restore('user-123', 'v1.0')
|
||
```
|
||
|
||
#### Release Management
|
||
|
||
```typescript
|
||
// Development workflow
|
||
await brain.update('app-config', { version: '1.0.0-alpha' })
|
||
await brain.versions.save('app-config', { tag: 'alpha' })
|
||
|
||
await brain.update('app-config', { version: '1.0.0-beta' })
|
||
await brain.versions.save('app-config', { tag: 'beta' })
|
||
|
||
await brain.update('app-config', { version: '1.0.0' })
|
||
await brain.versions.save('app-config', { tag: 'release' })
|
||
|
||
// Rollback to beta if issues found
|
||
await brain.versions.restore('app-config', 'beta')
|
||
```
|
||
|
||
#### Audit Trail
|
||
|
||
```typescript
|
||
// Track all changes
|
||
const versioning = new VersioningAugmentation({
|
||
enabled: true,
|
||
onUpdate: true,
|
||
entities: ['audit-*'],
|
||
keepRecent: 100 // Keep 100 versions for audit
|
||
})
|
||
|
||
brain.augment(versioning)
|
||
|
||
// All updates now tracked
|
||
await brain.update('audit-record-1', { status: 'modified' })
|
||
await brain.update('audit-record-1', { status: 'approved' })
|
||
|
||
// View complete history
|
||
const versions = await brain.versions.list('audit-record-1')
|
||
versions.forEach(v => {
|
||
console.log(`${v.createdAt}: ${v.description}`)
|
||
})
|
||
```
|
||
|
||
#### VFS File Versioning
|
||
|
||
```typescript
|
||
// VFS files can be versioned with actual blob content
|
||
await brain.vfs.writeFile('/docs/readme.md', 'Version 1 content')
|
||
|
||
// Get the file's entity ID
|
||
const stat = await brain.vfs.stat('/docs/readme.md')
|
||
|
||
// Save version 1
|
||
await brain.versions.save(stat.entityId, { tag: 'v1', description: 'Initial draft' })
|
||
|
||
// Modify the file
|
||
await brain.vfs.writeFile('/docs/readme.md', 'Version 2 - updated content')
|
||
|
||
// Save version 2
|
||
await brain.versions.save(stat.entityId, { tag: 'v2', description: 'Updated docs' })
|
||
|
||
// Compare versions - content is DIFFERENT
|
||
const v1 = await brain.versions.getContent(stat.entityId, 1)
|
||
const v2 = await brain.versions.getContent(stat.entityId, 2)
|
||
console.log(v1.data !== v2.data) // true
|
||
|
||
// Restore to v1 - writes content back to blob storage
|
||
await brain.versions.restore(stat.entityId, 'v1')
|
||
|
||
// File is now back to v1
|
||
const content = await brain.vfs.readFile('/docs/readme.md')
|
||
console.log(content.toString()) // 'Version 1 content'
|
||
```
|
||
|
||
---
|
||
|
||
**[📖 Complete Versioning Guide →](../features/entity-versioning.md)**
|
||
|
||
---
|
||
|
||
## 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<Buffer>`
|
||
|
||
Read file content.
|
||
|
||
```typescript
|
||
const content = await brain.vfs.readFile('/docs/README.md')
|
||
console.log(content.toString())
|
||
```
|
||
|
||
---
|
||
|
||
#### `vfs.writeFile(path, data, options?)` → `Promise<void>`
|
||
|
||
Write file content.
|
||
|
||
```typescript
|
||
await brain.vfs.writeFile('/docs/README.md', 'New content', {
|
||
encoding: 'utf-8'
|
||
})
|
||
```
|
||
|
||
---
|
||
|
||
#### `vfs.unlink(path)` → `Promise<void>`
|
||
|
||
Delete a file.
|
||
|
||
```typescript
|
||
await brain.vfs.unlink('/docs/old-file.md')
|
||
```
|
||
|
||
---
|
||
|
||
### Directory Operations
|
||
|
||
#### `vfs.mkdir(path, options?)` → `Promise<void>`
|
||
|
||
Create directory.
|
||
|
||
```typescript
|
||
await brain.vfs.mkdir('/projects/new-app', { recursive: true })
|
||
```
|
||
|
||
---
|
||
|
||
#### `vfs.readdir(path, options?)` → `Promise<string[] | Dirent[]>`
|
||
|
||
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<void>`
|
||
|
||
Remove directory.
|
||
|
||
```typescript
|
||
await brain.vfs.rmdir('/old-project', { recursive: true })
|
||
```
|
||
|
||
---
|
||
|
||
#### `vfs.stat(path)` → `Promise<Stats>`
|
||
|
||
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<SearchResult[]>`
|
||
|
||
Semantic file search.
|
||
|
||
```typescript
|
||
const results = await brain.vfs.search('React components with hooks', {
|
||
path: '/src',
|
||
limit: 10
|
||
})
|
||
```
|
||
|
||
---
|
||
|
||
#### `vfs.findSimilar(path, options?)` → `Promise<SearchResult[]>`
|
||
|
||
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<TreeNode>`
|
||
|
||
Get directory tree (prevents infinite recursion).
|
||
|
||
```typescript
|
||
const tree = await brain.vfs.getTreeStructure('/projects', {
|
||
maxDepth: 3
|
||
})
|
||
```
|
||
|
||
---
|
||
|
||
#### `vfs.getDescendants(path, options?)` → `Promise<VFSEntity[]>`
|
||
|
||
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<Metadata>`
|
||
|
||
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<Relation[]>`
|
||
|
||
Get file relationships.
|
||
|
||
```typescript
|
||
const rels = await brain.vfs.getRelationships('/src/App.tsx')
|
||
// Returns: imports, references, dependencies
|
||
```
|
||
|
||
---
|
||
|
||
#### `vfs.getTodos(path)` → `Promise<Todo[]>`
|
||
|
||
Get TODOs from a file.
|
||
|
||
```typescript
|
||
const todos = await brain.vfs.getTodos('/src/App.tsx')
|
||
```
|
||
|
||
---
|
||
|
||
#### `vfs.getAllTodos(path?)` → `Promise<Todo[]>`
|
||
|
||
Get all TODOs from directory tree.
|
||
|
||
```typescript
|
||
const allTodos = await brain.vfs.getAllTodos('/src')
|
||
```
|
||
|
||
---
|
||
|
||
### Project Analysis
|
||
|
||
#### `vfs.getProjectStats(path?)` → `Promise<Stats>`
|
||
|
||
Get project statistics.
|
||
|
||
```typescript
|
||
const stats = await brain.vfs.getProjectStats('/projects/my-app')
|
||
console.log(stats.fileCount)
|
||
console.log(stats.totalSize)
|
||
console.log(stats.fileTypes) // Breakdown by extension
|
||
```
|
||
|
||
---
|
||
|
||
#### `vfs.searchEntities(query)` → `Promise<VFSEntity[]>`
|
||
|
||
Search for VFS entities by metadata.
|
||
|
||
```typescript
|
||
const tsxFiles = await brain.vfs.searchEntities({
|
||
type: 'file',
|
||
extension: '.tsx'
|
||
})
|
||
```
|
||
|
||
---
|
||
|
||
**[📖 Complete VFS Documentation →](../vfs/QUICK_START.md)**
|
||
|
||
---
|
||
|
||
## Neural API
|
||
|
||
Access advanced AI features via `brain.neural()` (method that returns NeuralAPI instance).
|
||
|
||
### `neural().similar(a, b, options?)` → `Promise<number | SimilarityResult>`
|
||
|
||
Calculate semantic similarity.
|
||
|
||
```typescript
|
||
// Simple similarity score
|
||
const score = await brain.neural().similar(
|
||
'renewable energy',
|
||
'sustainable power'
|
||
) // 0.87
|
||
|
||
// Detailed result
|
||
const result = await brain.neural().similar('text1', 'text2', {
|
||
detailed: true
|
||
})
|
||
console.log(result.score)
|
||
console.log(result.explanation)
|
||
```
|
||
|
||
---
|
||
|
||
### `neural().clusters(input?, options?)` → `Promise<Cluster[]>`
|
||
|
||
Automatic clustering.
|
||
|
||
```typescript
|
||
const clusters = await brain.neural().clusters({
|
||
algorithm: 'kmeans',
|
||
k: 5,
|
||
minSize: 3
|
||
})
|
||
|
||
clusters.forEach(cluster => {
|
||
console.log(cluster.label)
|
||
console.log(cluster.items)
|
||
console.log(cluster.centroid)
|
||
})
|
||
```
|
||
|
||
---
|
||
|
||
### `neural().neighbors(id, options?)` → `Promise<Neighbor[]>`
|
||
|
||
Find k-nearest neighbors.
|
||
|
||
```typescript
|
||
const neighbors = await brain.neural().neighbors(entityId, {
|
||
k: 10,
|
||
threshold: 0.7
|
||
})
|
||
```
|
||
|
||
---
|
||
|
||
### `neural().outliers(threshold?)` → `Promise<string[]>`
|
||
|
||
Detect outlier entities.
|
||
|
||
```typescript
|
||
const outliers = await brain.neural().outliers(0.3)
|
||
// Returns entity IDs that are outliers
|
||
```
|
||
|
||
---
|
||
|
||
### `neural().visualize(options?)` → `Promise<VizData>`
|
||
|
||
Generate visualization data.
|
||
|
||
```typescript
|
||
const vizData = await brain.neural().visualize({
|
||
maxNodes: 100,
|
||
dimensions: 3,
|
||
algorithm: 'force',
|
||
includeEdges: true
|
||
})
|
||
// Use with D3.js, Cytoscape, GraphML tools
|
||
```
|
||
|
||
---
|
||
|
||
### Performance Methods
|
||
|
||
#### `neural().clusterFast(options)` → `Promise<Cluster[]>`
|
||
|
||
Fast clustering for large datasets.
|
||
|
||
```typescript
|
||
const clusters = await brain.neural().clusterFast({
|
||
k: 10,
|
||
maxIterations: 50
|
||
})
|
||
```
|
||
|
||
---
|
||
|
||
#### `neural().clusterLarge(options)` → `Promise<Cluster[]>`
|
||
|
||
Streaming clustering for very large datasets.
|
||
|
||
```typescript
|
||
const clusters = await brain.neural().clusterLarge({
|
||
k: 20,
|
||
batchSize: 1000
|
||
})
|
||
```
|
||
|
||
---
|
||
|
||
## Import & Export
|
||
|
||
### `import(source, options?)` → `Promise<ImportResult>`
|
||
|
||
Smart import with auto-detection (CSV, Excel, PDF, JSON, URLs).
|
||
|
||
```typescript
|
||
// CSV import
|
||
await brain.import('data.csv', {
|
||
format: 'csv',
|
||
createEntities: true
|
||
})
|
||
|
||
// Excel import
|
||
await brain.import('sales.xlsx', {
|
||
format: 'excel',
|
||
sheets: ['Q1', 'Q2']
|
||
})
|
||
|
||
// PDF import
|
||
await brain.import('research.pdf', {
|
||
format: 'pdf',
|
||
extractTables: true
|
||
})
|
||
|
||
// 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?`: `'csv' | 'excel' | 'pdf' | 'json'` - Auto-detected if omitted
|
||
- `createEntities?`: `boolean` - Create entities from rows
|
||
- `sheets?`: `string[]` - Excel sheets to import
|
||
- `extractTables?`: `boolean` - Extract tables from PDF
|
||
|
||
**Returns:** `Promise<ImportResult>` - Import statistics
|
||
|
||
**Note:** Import always uses the current branch.
|
||
|
||
**[📖 Complete Import Guide →](../guides/import-anything.md)**
|
||
|
||
---
|
||
|
||
### Export & Snapshots
|
||
|
||
```typescript
|
||
// Export to file
|
||
await brain.export('/path/to/backup.brainy')
|
||
|
||
// Create instant snapshot using COW fork
|
||
await brain.fork('backup-2025-01-19')
|
||
|
||
// Time-travel to specific commit
|
||
const snapshot = await brain.asOf(commitId)
|
||
const entities = await snapshot.find({ limit: 100 })
|
||
```
|
||
|
||
---
|
||
|
||
## Configuration
|
||
|
||
### Constructor Options
|
||
|
||
```typescript
|
||
const brain = new Brainy({
|
||
// Storage configuration
|
||
storage: {
|
||
type: 'memory', // memory | opfs | filesystem | s3 | r2 | gcs | azure
|
||
path: './brainy-data', // For filesystem storage
|
||
compression: true, // Enable gzip compression (60-80% savings)
|
||
|
||
// Cloud storage configs (see Storage Adapters section)
|
||
s3Storage: { ... },
|
||
r2Storage: { ... },
|
||
gcsStorage: { ... },
|
||
azureStorage: { ... }
|
||
},
|
||
|
||
// HNSW vector index config
|
||
hnsw: {
|
||
M: 16, // Connections per layer
|
||
efConstruction: 200, // Construction quality
|
||
efSearch: 100, // Search quality
|
||
typeAware: true // Enable type-aware indexing
|
||
},
|
||
|
||
// Model configuration (embedded in WASM - zero config needed)
|
||
// Model: all-MiniLM-L6-v2 (384 dimensions)
|
||
// Device: CPU via WASM (works everywhere)
|
||
|
||
// Cache configuration
|
||
cache: {
|
||
enabled: true,
|
||
maxSize: 10000,
|
||
ttl: 3600000 // 1 hour in ms
|
||
}
|
||
})
|
||
|
||
await brain.init() // Required! VFS auto-initialized
|
||
```
|
||
|
||
---
|
||
|
||
## Storage Adapters
|
||
|
||
All 7 storage adapters support **copy-on-write branching**.
|
||
|
||
### Memory (Default)
|
||
|
||
```typescript
|
||
const brain = new Brainy({
|
||
storage: { type: 'memory' }
|
||
})
|
||
```
|
||
|
||
**Use case:** Development, testing, prototyping
|
||
|
||
---
|
||
|
||
### OPFS (Browser)
|
||
|
||
```typescript
|
||
const brain = new Brainy({
|
||
storage: { type: 'opfs' }
|
||
})
|
||
```
|
||
|
||
**Use case:** Browser applications with persistent storage
|
||
|
||
---
|
||
|
||
### Filesystem (Node.js)
|
||
|
||
```typescript
|
||
const brain = new Brainy({
|
||
storage: {
|
||
type: 'filesystem',
|
||
path: './brainy-data',
|
||
compression: true // 60-80% space savings
|
||
}
|
||
})
|
||
```
|
||
|
||
**Use case:** Node.js applications, local persistence
|
||
|
||
---
|
||
|
||
### AWS S3
|
||
|
||
```typescript
|
||
const brain = new Brainy({
|
||
storage: {
|
||
type: 's3',
|
||
s3Storage: {
|
||
bucketName: 'my-brainy-data',
|
||
region: 'us-east-1',
|
||
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
|
||
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
|
||
}
|
||
}
|
||
})
|
||
|
||
// Enable Intelligent-Tiering for 96% cost savings
|
||
await brain.storage.enableIntelligentTiering('entities/', 'auto-tier')
|
||
```
|
||
|
||
**Use case:** Production deployments, scalable storage
|
||
|
||
**[📖 AWS S3 Cost Optimization →](../operations/cost-optimization-aws-s3.md)**
|
||
|
||
---
|
||
|
||
### Cloudflare R2
|
||
|
||
```typescript
|
||
const brain = new Brainy({
|
||
storage: {
|
||
type: 'r2',
|
||
r2Storage: {
|
||
accountId: process.env.CF_ACCOUNT_ID,
|
||
bucketName: 'my-brainy-data',
|
||
accessKeyId: process.env.CF_ACCESS_KEY_ID,
|
||
secretAccessKey: process.env.CF_SECRET_ACCESS_KEY
|
||
}
|
||
}
|
||
})
|
||
```
|
||
|
||
**Use case:** Zero egress fees, cost-effective storage
|
||
|
||
**[📖 R2 Cost Optimization →](../operations/cost-optimization-cloudflare-r2.md)**
|
||
|
||
---
|
||
|
||
### Google Cloud Storage (GCS)
|
||
|
||
```typescript
|
||
const brain = new Brainy({
|
||
storage: {
|
||
type: 'gcs',
|
||
gcsStorage: {
|
||
bucketName: 'my-brainy-data',
|
||
projectId: process.env.GCP_PROJECT_ID,
|
||
keyFilename: './gcp-key.json'
|
||
}
|
||
}
|
||
})
|
||
|
||
// Enable auto-tiering
|
||
await brain.storage.enableAutoclass({
|
||
terminalStorageClass: 'ARCHIVE'
|
||
})
|
||
```
|
||
|
||
**Use case:** Google Cloud ecosystem, global distribution
|
||
|
||
**[📖 GCS Cost Optimization →](../operations/cost-optimization-gcs.md)**
|
||
|
||
---
|
||
|
||
### Azure Blob Storage
|
||
|
||
```typescript
|
||
const brain = new Brainy({
|
||
storage: {
|
||
type: 'azure',
|
||
azureStorage: {
|
||
accountName: process.env.AZURE_STORAGE_ACCOUNT,
|
||
accountKey: process.env.AZURE_STORAGE_KEY,
|
||
containerName: 'brainy-data'
|
||
}
|
||
}
|
||
})
|
||
```
|
||
|
||
**Use case:** Azure ecosystem, enterprise deployments
|
||
|
||
**[📖 Azure Cost Optimization →](../operations/cost-optimization-azure.md)**
|
||
|
||
---
|
||
|
||
## Utility Methods
|
||
|
||
### `clear()` → `Promise<void>`
|
||
|
||
Clear all data (entities and relationships).
|
||
|
||
```typescript
|
||
await brain.clear()
|
||
```
|
||
|
||
---
|
||
|
||
### `getNounCount()` → `Promise<number>`
|
||
|
||
Get total entity count.
|
||
|
||
```typescript
|
||
const count = await brain.getNounCount()
|
||
```
|
||
|
||
---
|
||
|
||
### `getVerbCount()` → `Promise<number>`
|
||
|
||
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<string, number> | 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<string, number> | 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<AuditReport>` (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.
|
||
|
||
Becomes the default in 8.0.0.
|
||
|
||
#### `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<Record<string, number>>`
|
||
|
||
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<MigrationSummary>`
|
||
|
||
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}> }`.
|
||
|
||
---
|
||
|
||
### `embed(data)` → `Promise<number[]>` ✨
|
||
|
||
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<number[][]>` ✨
|
||
|
||
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<number>` ✨
|
||
|
||
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<string[]>` ✨
|
||
|
||
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<DuplicateResult[]>` ✨
|
||
|
||
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<IndexStats>` ✨
|
||
|
||
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 HNSW 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<ClusterResult[]>` ✨
|
||
|
||
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()` → `Statistics`
|
||
|
||
Get comprehensive statistics.
|
||
|
||
```typescript
|
||
const stats = brain.getStats()
|
||
console.log(stats.entityCount)
|
||
console.log(stats.relationshipCount)
|
||
console.log(stats.cacheHitRate)
|
||
```
|
||
|
||
---
|
||
|
||
## 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.shutdown() // Graceful shutdown, flush caches
|
||
```
|
||
|
||
---
|
||
|
||
## 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 }
|
||
})
|
||
|
||
// Delete
|
||
await brain.delete(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
|
||
})
|
||
```
|
||
|
||
---
|
||
|
||
### Git-Style Workflow
|
||
|
||
```typescript
|
||
// Fork for experimentation
|
||
const experiment = await brain.fork('test-migration')
|
||
|
||
// Make changes in isolation
|
||
await experiment.add({
|
||
data: 'New feature',
|
||
type: NounType.Document
|
||
})
|
||
|
||
// Commit your work
|
||
await experiment.commit({
|
||
message: 'Add new feature',
|
||
author: 'dev@example.com'
|
||
})
|
||
|
||
// Switch to experimental branch to make it active
|
||
await brain.checkout('test-migration')
|
||
```
|
||
|
||
---
|
||
|
||
### 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
|
||
**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
|
||
|
||
- ✅ **Entity Versioning** - Git-style versioning for individual entities
|
||
- ✅ **Content-Addressable Storage** - SHA-256 deduplication for versions
|
||
- ✅ **Auto-Versioning Augmentation** - Automatic version creation on updates
|
||
- ✅ **Branch-Isolated Versions** - Versions isolated per branch
|
||
- ✅ **VFS Entity Filtering** - All VFS entities now have `isVFSEntity: true` flag
|
||
- ✅ **VFS Auto-Initialization** - No more separate `vfs.init()` calls
|
||
- ✅ **VFS Property Access** - Use `brain.vfs.method()` instead of `brain.vfs().method()`
|
||
- ✅ **Complete COW Support** - All 20 TypeAware methods use COW helpers
|
||
- ✅ **Verified Import/Export** - Work correctly with current branch
|
||
- ✅ **Instant Fork** - Snowflake-style copy-on-write (<100ms fork time)
|
||
- ✅ **Git-Style Branching** - fork, commit, checkout, listBranches
|
||
- ✅ **Full Branch Isolation** - Parent and fork fully isolated
|
||
- ✅ **Read-Through Inheritance** - Forks see parent + own data
|
||
- ✅ **Universal Storage Support** - All 7 adapters support branching
|
||
|
||
**[📖 Complete Changes →](../../.strategy/v5.1.0-CHANGES.md)**
|
||
|
||
---
|
||
|
||
## 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
|
||
- **[Cloud Deployment](../deployment/CLOUD_DEPLOYMENT_GUIDE.md)** - Production deployment
|
||
- **[Instant Fork](../features/instant-fork.md)** - Git-style branching guide
|
||
|
||
---
|
||
|
||
**License:** MIT © Brainy Contributors
|
||
|
||
---
|
||
|
||
*Brainy - The Knowledge Operating System*
|
||
*From prototype to planet-scale • Zero configuration • Triple Intelligence™ • Git-Style Branching*
|