Reference / @silo Ai

@silo-ai/silo

Functions

resolveWorkspace

Resolve a Git worktree to its Silo database.

export function resolveWorkspace(cwd?: string): Workspace;

Remarks

Repository-local state is stored in .git/silo.json under the common Git directory. Auto selection uses origin when present and otherwise uses the persisted detached UUID.

Parameters

  • cwd: Directory inside the Git worktree to resolve. Defaults to the current directory.

Returns

The Git root, workspace identity, origin marker, and local database path.

🔍 resolveWorkspace on GitHub

Classes

SiloDatabase

export class SiloDatabase {
  readonly workspace: Workspace;
  private readonly database;
  private readonly db;
  private readonly releaseWriterLock;
  private closed;
  private transactionActive;
  private observedDataVersion;
  private observedJournalSequence;
  private constructor();
  static open(workspace: Workspace, writable?: boolean, allowSyncLock?: boolean): SiloDatabase;
  /**
   * Create a local database with its schema and optional default read surfaces.
   * Queries are installed before reports so report scripts can execute them.
   * Invalid queries or reports roll back creation and remove the new database.
   */
  static createWithSchema(workspace: Workspace, schema: LogicalSchema, reports?: ReportDefinition[], queries?: SavedQueryDefinition[]): SiloDatabase;
  close(): void;
  getMetadata(): DatabaseMetadata;
  getSchema(): LogicalSchema;
  /**
   * Read SQLite's data-version counter for this connection.
   *
   * @returns The current `PRAGMA data_version` value.
   * @remarks The counter detects commits made by other connections but does not attribute them
   * to a resource. `readMutationJournal()` includes this value and compares it with the previous
   * read for the same long-lived `SiloDatabase` instance.
   */
  getDataVersion(): number;
  /**
   * Read committed local mutation entries after a database-local sequence cursor.
   *
   * @param afterSequence The last sequence already consumed. Use `0` to read from the beginning
   * of the retained window.
   * @param limit The requested page size. The response is always capped at
   * `MUTATION_JOURNAL_READ_LIMIT`.
   * @returns Journal entries, retention bounds, and fallback state for the observing connection.
   * @throws {SiloError} If the cursor or limit is not a valid non-negative or positive safe
   * integer, respectively.
   * @remarks Reuse the same `SiloDatabase` instance for polling. A data-version advance without
   * a matching journal window sets `unknown_change`, which means the consumer must invalidate
   * globally rather than attributing the change to the returned resource tags.
   */
  readMutationJournal(afterSequence?: number, limit?: number): MutationJournalRead;
  private readSavedQuery;
  getSavedQuery(name: string): StoredQuery;
  listSavedQueries(): SavedQuerySummary[];
  putSavedQuery(input: unknown): StoredQuery;
  private installTemplateQueries;
  private putSavedQueryInTransaction;
  runSavedQuery(name: string, input: Record<string, unknown> | unknown[]): QueryResult;
  deleteSavedQuery(name: string): void;
  private readReport;
  getReport(slug: string): StoredReport;
  listReports(): ReportSummary[];
  private installTemplateReports;
  private putReportInTransaction;
  /**
   * Validate and run a report definition without persisting report state.
   *
   * @param input The candidate report definition.
   * @returns The parsed definition after its script or legacy queries succeed.
   * @throws {SiloError} If the definition or execution fails.
   * @remarks This does not save a rendered snapshot, update refresh metadata, or create mutation
   * journal and synchronization entries. A trusted script can still cause external side effects.
   */
  validateReport(input: unknown): ReportDefinition;
  putReport(input: unknown): StoredReport;
  refreshReport(slug: string): StoredReport;
  deleteReport(slug: string): void;
  getSyncState(): SyncState | undefined;
  configureSync(remoteUrl: string, databaseId?: string): SyncState;
  pendingTransactions(): PendingTransaction[];
  setSyncConflict(transactionId: string | null): void;
  markSynchronized(generation: string, etag: string): void;
  backupCanonical(path: string, generation: string): Promise<void>;
  backupRecovery(path: string): Promise<void>;
  rebasePending(pending: PendingTransaction[], generation: string, etag: string, discardTransactionId?: string): string | undefined;
  private recordMutationJournal;
  private assertTransactionInactive;
  private runMutation;
  private mutateRows;
  private prepareSchemaMutation;
  private recordSchemaMutation;
  private replaceSchema;
  createTable(input: unknown): TableDefinition;
  addRelation(input: unknown): RelationDefinition;
  getRelation(tableName: string, name: string): RelationDefinition;
  listRelations(): RelationDefinition[];
  removeRelation(tableName: string, name: string): void;
  importTemplate(name: string, template: TemplateSchema): LogicalSchema;
  alterTable(name: string, input: unknown): TableDefinition;
  dropTable(name: string): void;
  private verify;
  table(name: string): TableDefinition;
  /**
   * Run several validated row mutations as one atomic database transaction.
   *
   * @param callback A synchronous callback that uses only the scoped user-table methods provided to
   * it. The callback may read and mutate multiple user tables, and its return value is returned
   * unchanged. Direct mutable `SiloDatabase` methods are rejected while the callback is active.
   * @param options Optional structured operation metadata for the mutation journal and, when
   * synchronization is configured, the corresponding outbox transaction.
   * @returns The callback's return value after the transaction commits.
   * @throws {SiloError} If validation, a constraint, an optimistic-revision check, or a direct
   * mutable API call fails. Every mutation and its journal/synchronization metadata are rolled
   * back together on failure.
   * @remarks A successful callback creates one journal entry and at most one synchronization
   * outbox entry. The generated operation metadata includes `command: 'row.batch'` by default,
   * the touched `tables`, and compact `mutations` metadata. A supplied `operation.command` is
   * preserved. Use `getRow()` or `listRows()` for reads within the transaction and
   * `_expected_revision` in `updateRow` requests for compare-and-set updates. An error thrown by
   * the callback is rethrown unchanged after the transaction rolls back.
   * @example
   * ```ts
   * database.transaction(
   *   (transaction) => {
   *     const [change] = transaction.addRows('changes', { kind: 'completed' })
   *     transaction.updateRow('summaries', summaryId, {
   *       state: 'complete',
   *       _expected_revision: summaryRevision,
   *     })
   *     return change
   *   },
   *   { operation: { command: 'change.apply' } },
   * )
   * ```
   */
  transaction<T>(callback: (transaction: SiloTransaction) => T, options?: SiloTransactionOptions): T;
  addRows(name: string, input: unknown, upsert?: boolean): Record<string, unknown>[];
  private addRowsInTransaction;
  private readPersistedRow;
  private findPersistedRow;
  private prepareRow;
  private keyWhere;
  getRow(name: string, key: unknown): Record<string, unknown>;
  listRows(name: string, limit: number, offset: number): Record<string, unknown>[];
  private renderRow;
  updateRow(name: string, key: unknown, input: unknown): number;
  private updateRowInTransaction;
  deleteRow(name: string, key: unknown): number;
  private deleteRowInTransaction;
  query(sql: string): {
    columns: string[];
    rows: unknown[][];
  };
  ddl(): string;
}

🔍 SiloDatabase on GitHub

SiloError

export class SiloError extends Error {
  readonly exitCode: number;
  readonly code: string;
  readonly path: string;
  constructor(exitCode: number, code: string, message: string, path?: string);
}

🔍 SiloError on GitHub

Constants

MUTATION_JOURNAL_READ_LIMIT

Maximum number of local mutation entries returned by one journal read.

export const MUTATION_JOURNAL_READ_LIMIT = 100;

🔍 MUTATION_JOURNAL_READ_LIMIT on GitHub

MUTATION_JOURNAL_RETENTION

Maximum number of newest local mutation entries retained per database.

export const MUTATION_JOURNAL_RETENTION = 1000;

🔍 MUTATION_JOURNAL_RETENTION on GitHub

Types

CheckDefinition

interface CheckDefinition {
  name?: string;
  expression: string;
  comment?: string;
}

🔍 CheckDefinition on GitHub

ColumnDefinition

interface ColumnDefinition {
  name: string;
  type: string;
  type_options?: Record<string, unknown>;
  nullable?: boolean;
  default?: DefaultValue;
  comment: string;
  collate?: string;
  generated?: {
    expression: string;
    storage?: 'VIRTUAL' | 'STORED';
  };
}

🔍 ColumnDefinition on GitHub

DatabaseMetadata

interface DatabaseMetadata {
  identity: string;
  original_origin: string;
  created_at: string;
  updated_at: string;
  format_version: number;
  tool_version: string;
}

🔍 DatabaseMetadata on GitHub

DefaultValue

interface DefaultValue {
  literal?: Literal;
  expression?: string;
}

🔍 DefaultValue on GitHub

ForeignKeyDefinition

interface ForeignKeyDefinition {
  columns: string[];
  references: {
    table: string;
    columns: string[];
  };
  on_update?: string;
  on_delete?: string;
  deferrable?: boolean;
  initially_deferred?: boolean;
}

🔍 ForeignKeyDefinition on GitHub

IndexDefinition

interface IndexDefinition {
  name?: string;
  columns: IndexPart[];
  unique?: boolean;
  where?: string;
  comment?: string;
}

🔍 IndexDefinition on GitHub

IndexPart

interface IndexPart {
  column?: string;
  expression?: string;
  direction?: 'ASC' | 'DESC';
  collate?: string;
}

🔍 IndexPart on GitHub

InlineReportQueryDefinition

interface InlineReportQueryDefinition extends ReportQueryBase {
  sql: string;
}

🔍 InlineReportQueryDefinition on GitHub

LegacyReportDefinition

interface LegacyReportDefinition {
  slug: string;
  title: string;
  markdown: string;
  queries: ReportQueryDefinition[];
}

Deprecated. Use {@link ScriptedReportDefinition}.

🔍 LegacyReportDefinition on GitHub

Literal

type Literal = string | number | boolean | null | Literal[] | {
  [key: string]: Literal;
};

🔍 Literal on GitHub

LogicalSchema

interface LogicalSchema {
  format_version: 1;
  registry_version: 1;
  revision: number;
  tables: TableDefinition[];
  relations?: RelationDefinition[];
  template_imports?: Array<{
    name: string;
    imported_at: string;
  }>;
  agent_instructions?: Array<{
    source: string;
    content: string;
  }>;
}

🔍 LogicalSchema on GitHub

MutationJournalEntry

One committed, attributed mutation retained by the local invalidation journal.

export interface MutationJournalEntry {
  sequence: number;
  transaction_id: string;
  committed_at: string;
  operation: Record<string, unknown>;
  resource_tags: string[];
}

Properties

  • sequence Database-local monotonic sequence assigned to this journal entry.

  • transaction_id Unique transaction identity, shared with synchronization state when configured.

  • committed_at ISO timestamp recorded at the mutation's commit boundary.

  • operation Structured operation context; this metadata is not a replay command.

  • resource_tags Opaque consumer resource tags; * means that every resource may be stale.

🔍 MutationJournalEntry on GitHub

MutationJournalRead

A bounded journal page and observer state returned by readMutationJournal.

export interface MutationJournalRead {
  entries: MutationJournalEntry[];
  oldest_sequence: number | null;
  latest_sequence: number;
  next_sequence: number;
  full_refresh_required: boolean;
  data_version: number;
  unknown_change: boolean;
}

Properties

  • entries Entries after the requested cursor, capped by the journal read limit.

  • oldest_sequence Oldest sequence still retained, or null when the journal is empty.

  • latest_sequence Latest sequence currently retained.

  • next_sequence Cursor for the next page, or the latest sequence after a full refresh.

  • full_refresh_required The requested cursor is outside the retained window or the journal is unavailable.

  • data_version Current SQLite data version observed on this connection.

  • unknown_change A data-version advance without a matching journal window requires global invalidation.

🔍 MutationJournalRead on GitHub

PendingTransaction

interface PendingTransaction {
  sequence: number;
  transaction_id: string;
  kind: 'data' | 'schema';
  base_generation: string | null;
  schema_revision: number;
  operation: Record<string, unknown>;
  changeset: Uint8Array;
  created_at: string;
}

🔍 PendingTransaction on GitHub

PolicyDefinition

interface PolicyDefinition {
  type: 'generated_identity' | 'timestamps' | 'optimistic_revision' | 'immutable_rows' | 'immutable_columns' | 'append_only' | 'natural_key_upsert';
  [key: string]: unknown;
}

🔍 PolicyDefinition on GitHub

QueryParameterStyle

type QueryParameterStyle = 'named' | 'positional';

🔍 QueryParameterStyle on GitHub

QueryResult

interface QueryResult {
  columns: string[];
  rows: unknown[][];
  truncated: boolean;
}

🔍 QueryResult on GitHub

RelationDefinition

interface RelationDefinition {
  from: RelationEndpoint & {
    name: string;
  };
  to: RelationEndpoint;
  inverse_name?: string;
  comment: string;
  inverse_comment?: string;
}

🔍 RelationDefinition on GitHub

RelationEndpoint

interface RelationEndpoint {
  table: string;
  columns: string[];
}

🔍 RelationEndpoint on GitHub

ReportDefinition

type ReportDefinition = ScriptedReportDefinition | LegacyReportDefinition;

🔍 ReportDefinition on GitHub

ReportQueryBase

interface ReportQueryBase {
  name: string;
  empty_markdown?: string;
}

🔍 ReportQueryBase on GitHub

ReportQueryDefinition

type ReportQueryDefinition = InlineReportQueryDefinition | SavedReportQueryDefinition;

🔍 ReportQueryDefinition on GitHub

ReportSummary

interface ReportSummary {
  slug: string;
  title: string;
  refreshed_at: string;
  last_refresh_attempt_at: string;
  last_refresh_error: string | null;
}

🔍 ReportSummary on GitHub

SavedQueryDefinition

interface SavedQueryDefinition {
  name: string;
  description: string;
  sql: string;
  parameter_style: QueryParameterStyle;
  parameters: SavedQueryParameter[];
}

🔍 SavedQueryDefinition on GitHub

SavedQueryParameter

interface SavedQueryParameter {
  name: string;
  type: string;
  type_options?: Record<string, unknown>;
  description: string;
  default?: unknown;
}

🔍 SavedQueryParameter on GitHub

SavedQuerySummary

interface SavedQuerySummary {
  name: string;
  description: string;
  parameter_style: QueryParameterStyle;
  parameters: number;
  updated_at: string;
}

🔍 SavedQuerySummary on GitHub

SavedReportQueryDefinition

interface SavedReportQueryDefinition extends ReportQueryBase {
  saved_query: string;
  parameters?: Record<string, unknown> | unknown[];
}

🔍 SavedReportQueryDefinition on GitHub

ScriptedReportDefinition

interface ScriptedReportDefinition {
  slug: string;
  title: string;
  script: string;
}

Properties

  • script A synchronous JavaScript function body. The script receives silo, markdown, and require arguments and must return the rendered Markdown string.

🔍 ScriptedReportDefinition on GitHub

SiloTransaction

Validated user-table methods available inside SiloDatabase.transaction().

The callback is synchronous and must use this scoped surface for every read or write that belongs to the transaction. It does not expose SQLite handles, SQL execution, or Silo's internal catalog tables.

export interface SiloTransaction {
  getRow(name: string, key: unknown): Record<string, unknown>;
  listRows(name: string, limit: number, offset: number): Record<string, unknown>[];
  addRows(name: string, input: unknown, upsert?: boolean): Record<string, unknown>[];
  updateRow(name: string, key: unknown, input: unknown): number;
  deleteRow(name: string, key: unknown): number;
}

Properties

  • getRow Read one keyed user row from the transaction's current snapshot.

  • listRows List user rows from the transaction's current snapshot.

  • addRows Insert one row or an array of rows into a user table.

  • updateRow Update one keyed row, optionally using _expected_revision for a CAS.

  • deleteRow Delete one keyed row from a user table.

🔍 SiloTransaction on GitHub

SiloTransactionOptions

Options for one atomic multi-table row mutation transaction.

export interface SiloTransactionOptions {
  operation?: Record<string, unknown>;
}

Properties

  • operation Structured context stored in the mutation journal and synchronization outbox. Silo adds the actual touched tables and compact mutations fields, replacing any values with those names.

🔍 SiloTransactionOptions on GitHub

StoredQuery

interface StoredQuery extends SavedQueryDefinition {
  created_at: string;
  updated_at: string;
}

🔍 StoredQuery on GitHub

StoredReport

type StoredReport = ReportDefinition & StoredReportMetadata;

🔍 StoredReport on GitHub

StoredReportMetadata

interface StoredReportMetadata {
  rendered_markdown: string;
  created_at: string;
  updated_at: string;
  refreshed_at: string;
  last_refresh_attempt_at: string;
  last_refresh_error: string | null;
}

🔍 StoredReportMetadata on GitHub

SyncState

interface SyncState {
  database_id: string;
  remote_url: string;
  base_generation: string | null;
  base_etag: string | null;
  conflict_transaction_id: string | null;
}

🔍 SyncState on GitHub

TableDefinition

interface TableDefinition {
  name: string;
  comment: string;
  columns: ColumnDefinition[];
  primary_key?: string[];
  foreign_keys?: ForeignKeyDefinition[];
  unique_constraints?: Array<{
    name?: string;
    columns: string[];
  }>;
  indexes?: IndexDefinition[];
  checks?: CheckDefinition[];
  policies?: PolicyDefinition[];
  strict?: boolean;
  without_rowid?: boolean;
}

🔍 TableDefinition on GitHub

TemplateSchema

interface TemplateSchema {
  format_version?: 1;
  agent_instructions?: string;
  tables: TableDefinition[];
  relations?: RelationDefinition[];
  queries?: SavedQueryDefinition[];
  reports?: ReportDefinition[];
}

🔍 TemplateSchema on GitHub

Workspace

Resolved Git identity and local database path used to open a Silo database.

export interface Workspace {
  root: string;
  identity: string;
  origin: string;
  databasePath: string;
  selection?: WorkspaceSelection;
}

Properties

  • origin Configured Git origin, or a detached:<uuid> marker before an origin exists.

  • selection Repository-local selection used to resolve this workspace.

🔍 Workspace on GitHub

WorkspaceSelection

Repository-local rule for selecting a detached or Git-remote workspace identity.

type WorkspaceSelection = {
  kind: 'auto';
} | {
  kind: 'detached';
} | {
  kind: 'remote';
  name: string;
};

🔍 WorkspaceSelection on GitHub