Brain identifier scoping every query through this Brain instance.
Subsystems (KnowledgeGraph, MemoryGraph, ConsolidationLoop) read this
to inject brain_id into their own SQL.
Opaque identity used to serialize same-process operations across separate Brain handles that address the same backing store.
Expose the raw storage adapter for advanced usage.
Code that needs the adapter itself reads it here; the brain's own
queries go through run, get, all and transaction.
Platform-aware feature bundle (dialect, FTS, BLOB codec, exporter). Consumers use this to generate cross-platform SQL instead of hardcoding SQLite-specific syntax.
Static openOpen a Brain backed by SQLite. Tries adapters in order: better-sqlite3 (Node native) -> sql.js (WASM) -> indexeddb (browser).
File path. Use :memory: for in-process testing.
Optional brainOptional explicit brainId; defaults to file basename
(or 'default' for :memory:).
Optional priority?: ("better-sqlite3" | "sqljs" | "indexeddb")[]Override the default adapter priority.
Optional coordinationOptional process-local identity for non-filesystem adapters whose resource name is adapter-specific.
A fully initialised Brain instance with the latest schema.
Static openOpen a Brain backed by PostgreSQL. Requires the pg npm package and
a reachable Postgres instance.
Every integer column of the Brain's schema is BIGINT on Postgres, and
this adapter reads BIGINT as a number, as SQLite returns its integers:
a trace's retrieval count, access and creation times and deleted flag
load as numbers on both dialects.
Standard Postgres connection URL.
REQUIRED. Used to scope every query so multiple brains can share one Postgres database without leaking rows.
Optional poolpg connection pool size. Defaults to 10.
Static openOpen a Brain with a pre-resolved StorageAdapter. Use when sharing an adapter across subsystems (e.g., wilds-ai foundation pool + brain) or when the consumer needs full control over adapter resolution.
CONCURRENCY CAVEAT (Postgres adapters): the underlying
PostgresAdapter tracks transactionalClient as instance-shared
mutable state. Two concurrent Brain.transaction(...) calls on the
same shared adapter (or any subsystem call that internally opens a
transaction) will overwrite each other's connection assignment, which
corrupts both transactions silently. If the consumer dispatches
concurrent writes through subsystems sharing one adapter, either:
PostgresAdapter per logical actor, ORAsyncLocalStorage-tracked transactional clients.
Non-transactional concurrent reads/writes against a shared adapter
are safe (the pool handles those correctly).INTEGER COLUMNS (Postgres adapters): the Brain's integer columns are
BIGINT on Postgres, which pg reads as strings unless the adapter is
opened with typeParsers: { int8: 'number' }, as Brain.openPostgres
opens its own. Read as strings, a trace's retrieval count and times load
as text, and an access appends to the count instead of adding to it.
Pre-built StorageAdapter instance.
Optional brainRequired for postgres-kind adapters; optional for
sqlite-kind adapters (defaults to 'default').
Optional coordinationOptional shared opaque token for separate adapter objects that address the same backing database and brain.
Execute a mutation statement (INSERT, UPDATE, DELETE).
SQL statement with ? positional placeholders.
Optional params: StorageParametersParameter array matching the placeholders.
Metadata about affected rows.
Check whether a given embedding dimension is compatible with this brain.
On first call (no stored embedding_dimensions), returns true and stores
the provided dimension for future compatibility checks.
Subsequent calls compare dimensions against the stored value.
Mismatches indicate that a different embedding model was used to encode
memories — mixing dimensions would corrupt vector similarity searches.
The embedding vector length to check (e.g. 1536 for OpenAI ada-002).
true if compatible (or no prior value), false on mismatch.
The statement that rebuilds this brain's full-text index from its traces,
for run() on the brain or on a transaction. SQLite keeps the index in
one FTS5 table per file and rebuilds it whole. Postgres keeps it in the
_tsv column of the memory_traces table every brain shares, so there
the statement updates this brain's rows only.
The SQL and its parameters.
Materialize this brain to a portable SQLite file at targetPath.
Source can be any backend (SQLite, Postgres, Capacitor, etc.); output
is always a fresh SQLite file. Used by .wildsoul-style export and
other portability flows.
Refuses to overwrite an existing file at targetPath so callers do
not silently lose data.
The rows come from one consistent view of the database where it gives
one, Postgres or a SQLite file in WAL mode as openSqlite opens it (see
_readSnapshot), so a write that lands while the export runs is wholly
in the file or wholly out of it. The brain's scope-id form record
(scope_id_form in brain_meta; see scopeIdForm.ts) is read before
the rows and again after them: on a brain with one connection, which
reads no snapshot, a re-file that commits while the export reads makes
the export copy again, so the file's record names the form its rows are
in. The file is written under a temporary name beside targetPath and
moved there once whole: a failed export leaves nothing at targetPath,
and a retry can run. A file that appears at targetPath while the
export runs is kept, and the export fails.
Forking semantics: rows are emitted with the source brainId. Importing the resulting file under a different brainId produces a fork.
Destination file path. File must not exist.
Bytes written to the destination file.
When anything exists at targetPath, before the export or once
it is written; or when the scope-id form record changed while the
export read the rows, on each of three passes.
Load a portable SQLite file into this Brain's adapter.
Forking semantics: rows from the source file are written under the
RECEIVING brain's brainId, not the brainId stored in the source
file. This means importing an alice snapshot into a Brain opened
with brainId: 'alice-fork' produces a fork with no shared identity.
CAVEAT: importing from a file an older release wrote MUTATES the
source file. Opening the source via Brain.openSqlite runs its pending
migrations in place: v1 to v2 for a file from before 0.3.0, and v2 to v3,
which adds memory_traces.scope_id and fills it, for a file from before
0.13.159. A release before 0.13.159 then fails to import the file into a
table without the column, since its import copies every column it reads.
The open also files the scope id of each source trace that a release
older than the column wrote. To preserve the source unchanged, copy the
file to a temp path before calling this method.
A trace's episodic copy the file holds under another node id than its
trace's key (a release older than keyed copies recorded it so) is filed
under the key once the rows are in, with the relations that name it, so
a delete by its trace id finds it (keyTraceCopies); a copy whose key the
brain's own copy of the trace holds is deleted.
A Brain a learning layer serves holds its plain user and persona scope
ids in the encoded form and records it in brain_meta (scope_id_form;
see scopeIdForm.ts). A source with the record whose user and
persona scope ids, in its traces and its knowledge-graph copies, hold
none of /, % and : reads the same in both forms and is taken as a
plain one: its record is not copied, so a Brain without the record stays
without it. A plain source goes into a Brain that holds the
record with its ids encoded as they are written, each trace's
knowledge-graph copy with it, merged or replaced. A source with the record
goes into a Brain without it, which gets the record, unless the Brain
holds a plain id the record would read as another, in a trace or a copy:
then nothing is written and the call throws, naming the record. A replace
empties the brain first, so only its form counts. The handshake and every
write share one transaction, so a re-file or another import of the brain
that commits first is followed (on Postgres the import waits for the
brain's form lock); the source's record is read before the copy and again
after it, and the copy is made again when a re-file of the source
committed in between.
Source SQLite file path (typically produced by
Brain.exportToSqlite).
Optional strategy?: "merge" | "replace"'merge' (default) upserts on PK collision;
'replace' wipes all rows for the receiving brainId first.
Counts of rows imported per table.
When the source holds several brain ids, or when the scope-id
form handshake refuses it, naming the record (scope_id_form).
Unified cross-platform connection manager for a single agent's persistent brain.
Uses the
StorageAdapterinterface from@framers/sql-storage-adapterto support multiple backends (better-sqlite3, sql.js, IndexedDB, Postgres, etc.) transparently. All methods are async.Usage:
Subsystems (KnowledgeGraph, MemoryGraph, ConsolidationLoop, etc.) receive the
Braininstance and call its async proxy methods (run,get,all,exec,transaction) for all database operations.