createSmithers and friends) owns that store and hands
back a typed db handle, so you rarely touch this layer directly except to
build a custom backend, inspect a store outside a running workflow, or generate
tables from Zod schemas yourself.
SmithersDb is also re-exported from @smthrs/db/adapter for
callers pinning the subpath; the facade export above is supported.SmithersDb
The adapter: wraps a Drizzle database handle and exposes every persistence operation the engine needs. The factory constructs one and the scheduler drives it; only build your own for a custom control plane.BunSQLiteDatabase | PostgresDescriptor
required
The underlying Drizzle handle. SQLite uses Drizzle queries directly; the
Postgres/PGlite descriptor routes through the internal SQL message storage.
methods
insertRun, updateRun, getRun, listRuns, heartbeatRun,
requestRunCancel, requestRunHijack, claimRunForResume,
listStaleRunningRuns, plus ancestry helpers: track a run start-to-terminal
and support crash recovery.methods
insertNode / getNode / listNodes and insertAttempt / updateAttempt /
heartbeatAttempt record per-node execution and retries.methods
upsertOutputRow, deleteOutputRow, getRawNodeOutput, and hasPhysicalTable
read and write a workflow’s typed output tables, keyed by runId / nodeId /
iteration.methods
insertFrame, listFrameChainDesc, and reconstructFrameXml persist and
replay the delta-encoded UI frame stream (with an in-memory LRU XML cache).(writeGroup, operation) => RunnableEffect
withTransaction / withTransactionEffect run a write group atomically;
read(label, op) / write(label, op) wrap a single operation as a runnable
Effect with metrics and SQLite write-retry. SQLite serializes writes per
client, Postgres uses real transactions.(sql, params?) => RunnableEffect<unknown[]>
Read-only escape hatch: accepts only
SELECT / WITH / EXPLAIN / VALUES;
any DDL or mutation keyword is rejected before execution. For introspection,
never writes.SqlMessageStorage
Agent-message and event-history store behind the adapter, created from the
same handle. See
ensureSmithersTables.RunnableEffect: an Effect you can yield* inside an
Effect program, or await directly as a promise.
Source adapter.js · adapter/SmithersDb.js · Tests db-adapter.test.js · See also How it works, SchemaRegistryEntry
loadOutputs / loadOutputsEffect
Reads every persisted output row for a run, across all of a workflow’s output tables, in one call. Given the factory’stables map and a RUN_ID, returns a
snapshot keyed by both schema name and physical table name; boolean columns are
coerced back to JS booleans, and the reserved input table is skipped.
BunSQLiteDatabase | PostgresDescriptor
required
The same handle the adapter wraps: Drizzle for SQLite, a parameterized
$1
query for Postgres.Record<string, Table>
required
Map of output name to its Drizzle table (the
tables value from the factory).
Entries without a runId column, or the input entry, are skipped.string
required
The run to read. Placeholder:
RUN_ID.object
An object whose keys are both the schema name and the snake_case table name;
each value is the array of Drizzle-shaped rows (camelCase keys) for that run.
loadOutputsEffect is the same query returning an
Effect.Effect<OutputSnapshot, SmithersError> instead of a promise. Use it
inside an Effect pipeline; use loadOutputs for a one-off read.
snapshot.js · Tests db-snapshot-load.test.js · See also db-output-roundtrip.test.js
ensureSmithersTables
Creates the core Smithers tables (internal message and event-history storage the adapter depends on) on a fresh handle if they don’t already exist. Safe to call on every boot.BunSQLiteDatabase
required
The Drizzle handle to initialize. Runs synchronously for SQLite.
For a Postgres descriptor this synchronous helper is a no-op: Postgres schema
setup is async, so the Postgres/PGlite entry points await it before the engine
starts. Output tables are created separately by
syncZodTableSchema.ensure.js · Tests db-ensure.test.js
Zod -> table helpers
Turns a Zod object schema into a SQLite output table. Each table gets the fixedrun_id / node_id / iteration prefix and a composite primary key; field keys
are snake-cased and mapped to columns by Zod type (string/enum/literal -> TEXT,
z.number() / float -> REAL (fractions preserved), z.int() -> INTEGER,
boolean -> INTEGER boolean mode, arrays/objects/unions -> JSON TEXT). Pass
opts.isInput for the single-PK input-table shape. Output field names can’t
reuse the reserved key columns runId/nodeId/iteration (input reserves only
runId); a collision throws INVALID_INPUT at construction.
Table
Builds a Drizzle
sqliteTable from the schema; what the factory calls to
materialize tables.string
Emits
CREATE TABLE IF NOT EXISTS ...; pass opts.dialect (default
"sqlite") for Postgres-compatible column types instead.void
Creates the table and reconciles a drifted one: runs
CREATE TABLE, then
ALTER TABLE ADD COLUMN for fields missing from an older table, and records
column kinds in _smithers_output_schema_columns. Idempotent. sqlite must be
a bun:sqlite database (or compatible .run / .query handle).Array<{ name, sqliteType, kind }>
User-defined columns from the schema, excluding the fixed prefix. Each entry
carries the snake_case
name, the SQLite type, and the logical kind
(string / number / boolean / json).zodToTable.js · zodToCreateTableSQL.js · Tests zod-to-table-unit.test.js · zod-to-sql.test.js
Utilities
Small building blocks behind the helpers above, exported for the same custom-backend cases.string
Convert a
camelCase field name to snake_case, the column-naming rule used
throughout. "createdAtMs" -> "created_at_ms".ZodType
Strip the
optional / nullable / default wrappers off a Zod type to reach
its base type, so column mapping sees the underlying kind.string
Renders a Zod object schema as a pretty-printed JSON example string: field
descriptions become string placeholders, numbers
0, booleans false, arrays
a one-element sample, and enums use their first value. Handy for prompting an
agent with the exact output shape it must return.utils/camelToSnake.js · unwrapZodType.js · zod-to-example.js · Tests camel-to-snake.test.js · unwrap-zod-type.test.js · See also Authoring API, Types reference