Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

sms-baseline

A headless baseline for self-modifying software driven by agentic AI. Users prompt a model; the software’s behaviour changes live — no rebuild, no restart — and stays reliable because every change is a plugin that is judged before it mounts, undone mechanically when it fails or is disabled, and persisted so it survives restarts.

It is a set of packages, not an app. A downstream project installs the baseline, brings its own plugins (domain modules) and its own UI (any frontend against the JSON admin API), picks the drivers for its stack, and gets self-modification for free.

ring 0  @sms/kernel                      loader · registry · fibers · derived undo · event log · trust tiers
ring 1  @sms/plugin-sdk | @sms/contracts what agent code sees | the driver contracts
ring 2  drivers | plugins                store · host · executor · model · objects | http · collections · judge · agent-loop · admin-api · …
ring 3  @sms/baseline                    createBaseline() · createTenantPool()
ring 4  examples/* — and your app

Quick start

pnpm add "github:<owner>/sms-baseline#vX.Y.Z&path:/packages/baseline"   # + the drivers you use (see docs/getting-started.md)
import { createBaseline } from "@sms/baseline";
import { QuickJSExecutor } from "@sms/executor-quickjs";
import { createNodeHost } from "@sms/host-node";
import { createClaudeModel } from "@sms/model-claude";
import { openSqliteStore } from "@sms/store-sqlite";

const app = await createBaseline({
  store: await openSqliteStore("app.db"),
  executor: new QuickJSExecutor(),
  model: createClaudeModel(),
  plugins: [/* your plugins */],
  adminToken: process.env.SMS_ADMIN_TOKEN,
});
await createNodeHost({ port: 8787 }).listen(app.handle);

Documentation

Everything lives in docs/ (also published as an mdBook site — see docs/documentation-site.md):

Developing the baseline

pnpm install
pnpm check                 # typecheck · lint · quality gate · knip · tests with coverage — run before every push (no CI on main)
pnpm --filter @sms/example-reference-node-sqlite demo
git tag vX.Y.Z && git push origin vX.Y.Z   # cut a release; CD does the rest (docs/releasing.md)

Agent notes for this repo are in CLAUDE.md at the repo root.

Getting started: the baseline inside your project

You are building sm-erp (or any app). You want users to be able to say “add a discount field to invoices and a tool that finds overdue ones” and have it happen — safely, live, persistently. This is how.

1. Install

The baseline is private and distributed as git tags with committed dist/. Pick the umbrella plus the drivers for your stack (every package is a separate git+path dependency; they all pin the same tag):

TAG=v0.2.0; REPO=github:<owner>/sms-baseline
pnpm add "$REPO#$TAG&path:/packages/baseline" \
         "$REPO#$TAG&path:/packages/drivers/store/sqlite" \
         "$REPO#$TAG&path:/packages/drivers/executor/quickjs" \
         "$REPO#$TAG&path:/packages/drivers/host/node" \
         "$REPO#$TAG&path:/packages/drivers/model/claude"   # or model-gpt
NeedPackage
alwayspackages/baseline
a storestore-sqlite (Node ≥ 22.13, node:sqlite) · store-postgres (pg or PGlite) · store-do (Durable Objects)
a hosthost-node · host-fastify · host-cloudflare
an executorexecutor-quickjs (recommended, WASM boundary) · executor-node (worker threads, dev only)
a modelmodel-claude (your claude login) · model-gpt (your codex login) · model-claude-api / model-gpt-api / model-openrouter (API keys; Worker-safe) · model-gpt-oauth (your codex login tokens, Worker-safe, opt-in with unofficial: true; readCodexAuth() from @sms/model-gpt-oauth/node) · or implement ModelService from @sms/contracts yourself
object storage (optional)objects-r2 · objects-s3 — the baseline defines the system-only objects key (OBJECTS_KEY); a system plugin of yours provides it (examples/cloudflare-worker)

Requirements: Node ≥ 22.13 (or Workers with nodejs_compat), pnpm, ESM ("type": "module"). TypeScript types ship in dist/.

2. Compose a kernel

// src/app.ts — your composition root
import { createBaseline } from '@sms/baseline'
import { QuickJSExecutor } from '@sms/executor-quickjs'
import { createClaudeModel } from '@sms/model-claude'
import { openSqliteStore } from '@sms/store-sqlite'
import { invoicesPlugin } from './plugins/invoices.ts'

export async function createApp() {
  return createBaseline({
    name: 'sm-erp',
    store: await openSqliteStore(process.env.SMS_DB ?? 'erp.db'),
    executor: new QuickJSExecutor(),
    model: createClaudeModel({ model: process.env.SMS_MODEL }), // or createGptModel() from @sms/model-gpt
    plugins: [invoicesPlugin],                       // your modules (docs/writing-plugins.md)
    identity: 'You are the assistant inside sm-erp. You can extend the ERP itself.',
    adminToken: process.env.SMS_ADMIN_TOKEN,         // mutating /api routes: this token, or an admin session
    auth: { bootstrapAdmin: { login: 'root', password: process.env.SMS_ROOT_PASSWORD! } }, // users + rbac + orm guard; `false` = dev only
    // what needs a human; default: scope 'net' and the points in DEFAULT_SENSITIVE_POINTS
    // ('route', 'schedule', 'model-method', 'model-hook', 'automation') — your list replaces it
    judge: { sensitiveScopes: ['net'], sensitivePoints: ['route', 'schedule'] },
    // rpc: true, meta: true — /api/rpc and the view/action/menu points (docs/building-a-ui.md); off by default
  })
}

createBaseline installs, in order: the database key → httpcollectionsschedulerauthrbacorm (+ the rbac→orm guard) → meta / rpc when enabled → judgemodelagent-loopadmin-api → your plugins; then settle()s and restore()s agent plugins from the log. It throws if a system plugin is not active. You get { kernel, store, http, handle, tick, close }tick() runs due schedules; the host decides the cadence.

3. Put it on the wire

// src/main.ts
import { createNodeHost } from '@sms/host-node'
import { createApp } from './app.ts'
const app = await createApp()
const server = await createNodeHost({ port: 8787 }).listen(app.handle)
console.log(server.url)

Fastify (your existing app keeps its routes): createFastifyHost({ app: fastify, prefix: '/sms' }).listen(app.handle). Cloudflare: see tenancy.md and examples/cloudflare-worker.

4. Talk to it

curl -s localhost:8787/api/state | jq '.plugins[].id'
curl -s -H "authorization: Bearer $SMS_ADMIN_TOKEN" -H 'content-type: application/json' \
     -d '{"text":"Add a discount field to invoices and a tool that lists overdue ones"}' localhost:8787/api/chat
curl -s localhost:8787/api/state | jq '.pending'          # anything waiting for a human?
curl -s -X POST -H "authorization: Bearer $SMS_ADMIN_TOKEN" localhost:8787/api/approvals/agent.invoice-discount/approve

Your UI does exactly this — building-a-ui.md.

5. Multi-tenant

Replace createBaseline with createTenantPool (one kernel per tenant, each on its own store) — see tenancy.md. examples/erp-fastify-postgres is the full picture on Postgres.

Layout of a downstream repo

sm-erp/
  package.json            @sms/* git deps pinned to one tag
  src/app.ts              composition root (createBaseline / createTenantPool)
  src/main.ts             host driver → listen
  src/plugins/*.ts        your modules (SystemPlugin objects)
  ui/                     your frontend, talks to /api/*
  test/                   boot createApp with createScriptedModel([...]) and assert

Testing tip: createTestBaseline({ plugins, turns }) from @sms/baseline/testkit (or createScriptedModel(turns) from @sms/baseline) replays canned model turns so the whole prompt → judge → mount → use → undo loop runs offline (see packages/baseline/test/baseline.test.ts, examples/reference-node-sqlite/src/demo.ts and writing-plugins.md → Testing).

Upgrading

Bump the tag in every @sms/* specifier (they must match) and pnpm install. Release notes live on the release tags; the event log format is append-only and versions fold forward.

Writing plugins

Everything in the baseline is a plugin, and so is everything you add. There are two kinds:

System pluginAgent plugin
Written byyou, in your repothe model at run time (or a human through the same API)
Runsin-process, activate(ctx) with ctx.kernelin the executor, activate(cap), JSON-only bridge
Trustsystemagent — cannot touch system-only keys/points, needs the judge
Installed bycreateBaseline({ plugins })judge.submit() via plugin_define / POST /api/chat

Both share the same manifest and the same two effects: provide(key, value) and contribute(point, item). The kernel records each and derives its inverse — never write teardown.

A system plugin

import { type CollectionsService, type SystemPlugin, json } from '@sms/baseline'

export const invoicesPlugin: SystemPlugin = {
  manifest: {
    id: 'erp.invoices',           // stable; agent plugins can never take a system id
    version: '0.1.0',
    inject: ['collections'],      // keys read via ctx.get — activation waits until they exist
    contributes: {                // declarative: applied by the kernel, no code needed
      collection: [{ name: 'invoice', fields: [
        { name: 'customer', type: 'text', required: true },
        { name: 'amount', type: 'real', required: true },
        { name: 'paid', type: 'boolean', default: false },
      ] }],
      prompt: [{ section: 'application', order: 20, text: 'Invoices live in the `invoice` collection.' }],
    },
  },
  async activate(ctx) {
    const collections = ctx.get<CollectionsService>('collections')
    await ctx.contribute('tool', {
      name: 'overdue_invoices', description: 'Unpaid invoices past due',
      input_schema: { type: 'object', properties: {} },
      handler: async () => (await collections.list('invoice', { where: { paid: false } })),
    })
    await ctx.contribute('route', {
      method: 'GET', path: '/api/invoices/summary',
      handler: async () => json({ count: (await collections.list('invoice', { limit: 1000 })).length }),
    })
  },
}

Rules that the kernel enforces: you may only get keys you inject, only provide keys you declare in provide, only during activation. Contributions are validated by the point owner and can be rejected (your fiber fails; siblings keep running). Disabling the plugin undoes everything in reverse order.

Depending on other plugins: contracts, inject, optional

A plugin never imports another plugin’s provider. Each one publishes its definitions at @sms/plugin-<x>/contractX_KEY, X_POINT constants, the service and item types, validators and pure helpers — and that is the only subpath a plugin may import from a sibling (pnpm quality enforces it). Your own plugins follow the same shape: src/contract.ts with the definitions, src/index.ts re-exporting it plus the provider. Composition roots (createBaseline, your app) import the roots.

import { ORM_KEY, type OrmService } from '@sms/plugin-orm/contract'
import { AUDIT_KEY, type AuditService } from '@sms/plugin-audit/contract'

manifest: {
  id: 'erp.invoices', version: '1',
  inject: [ORM_KEY],        // hard: activation waits for it, deactivation follows it
  optional: [AUDIT_KEY],    // soft: used when present — read with ctx.kernel.getValue(AUDIT_KEY)
}

inject is what the kernel reconciles on (a fiber activates only when every injected key exists and is unloaded before its provider). optional declares a soft dependency so it is visible — in FiberView, in the admin API, and to the gate, which fails a plugin that uses another plugin’s contract at runtime or calls getValue(key) without declaring the key in one of the two.

Extension points shipped

PointOwnerItemAgent may contribute
routehttp{ method, path, handler(req) }:param, *; return JSON or a Response; throw HttpError for a statusyes (needs a human by default)
schedulescheduler{ name, everyMs, handler({ name, now, lastRun }) } — runs when the host ticks; last run persistedyes (needs a human by default)
admin-authorizeradmin-api{ name, authorize(req) → boolean } — admits a request to mutating admin routes; @sms/plugin-auth contributes auth-session (an admin session)no (system)
grouprbac{ name, description?, implies?[] } — membership is data (rbac-admin.grant)no (system)
accessrbac{ model, group, read?, write?, create?, unlink? } — the access matrixno (system)
rulerbac{ name, model, groups?, domain, ops? } — record rule; rbac.ruleDomain() ANDs global rules with the OR of the user’s group rulesno (system)
modelorm{ name, fields: { name: spec }, displayField?, order? } — a table with relations, computed and related fields (see Models)yes
model-fieldorm{ model, name, spec } — adds a column to a model declared elsewhere (waits for it if needed)yes
model-methodorm{ model, name, handler(env, ids, args), access? } — computes, buttons, RPCyes (needs a human by default)
model-hookorm{ model, on: create/write/unlink, when: before/after, handler(env, { ids, values, records }) }yes (needs a human by default)
model-onchangeorm{ model, field, handler(env, values) → patch }yes
viewmeta{ id, model, kind: form/list/kanban/search, arch, priority? } or an extension { id, model, kind, inherit, ops: [{ target, position, nodes?, attrs? }] } (createBaseline({ meta: true }))yes
actionmeta{ id, name, model, views[], viewIds?, domain?, context?, groups? } — ids are globalyes
menumeta{ id, label, parent?, action?, sequence?, icon?, groups? } — roots are apps; empty branches are prunedyes
automationautomation{ id, label, model, trigger: create/write/create_or_write/unlink/schedule, watch?, filter?, everyMinutes?, action: { kind: method/update/message/handler, … }, active? } — actions run as sudoyes (needs a human by default)
audit-trackaudit{ model, fields[] } — log field changes of that model as audit_message rowsyes
collectioncollections{ name, fields[] } — types text · integer · real · boolean · jsonyes
collection-fieldcollections{ collection, field } — adds a columnyes
collection-hookcollections{ collection, on: create/update/remove, handler(record, previous) }yes
toolagent-loop{ name, description, input_schema, handler(input) }yes
promptagent-loop{ section, text, order }yes
gatejudge`{ name, run(ctx) → undefinedreason }` — runs before any agent plugin mounts
invariantjudge{ name, check(kernel) } — runs after every mount; a throw rolls the mount backno

Keys: database and objects (system↔system; the host provides them), http, collections, scheduler, model (system provides), judge, agent (system↔system), identity (auth; read-only, agent may inject), identity-admin (auth; system↔system), rbac / rbac-admin, orm, meta (compiled views, actions, menu tree — view() is undefined when nothing was contributed; there is no default view generation) and audit (post(model, id, { body, kind }, ctx)). Define your own with ctx.kernel.defineKey/definePoint and mark trust on them — that is how you keep the agent out of something (never by hiding an object).

Models

@sms/plugin-orm (createOrmPlugin({ contextOf?, prefix? }), install after httpPlugin) turns a model contribution into a table m_<name> on the database key, additively migrated on every boot:

contributes: {
  model: [{
    name: 'invoice',
    fields: {
      number: { kind: 'char', required: true },
      partner: { kind: 'many2one', target: 'contact', onDelete: 'restrict' },
      partner_email: { kind: 'related', path: 'partner.email' },
      state: { kind: 'selection', options: [{ value: 'draft' }, { value: 'paid' }], default: 'draft' },
      lines: { kind: 'one2many', target: 'invoice_line', inverse: 'invoice' },
      tags: { kind: 'many2many', target: 'tag' },
      total: { kind: 'computed', returns: 'float', depends: ['lines.subtotal'], compute: 'compute_total' },
    },
    displayField: 'number',
    order: 'number desc',
  }],
  'model-method': [{
    model: 'invoice', name: 'compute_total',
    // computes get `{ records }` (scalar values of `ids`) and answer `{ [id]: value }` — no I/O needed,
    // so an agent plugin can contribute one from inside the executor
    handler: (env, ids, { records }) => Object.fromEntries(records.map((r) => [r.id, /* … */ 0])),
  }],
}

Kinds: char text int float bool date datetime json selection many2one one2many many2many computed related. Every model has id, display (from displayField, default name), created_at/updated_at, created_by/updated_by. Defaults accept $uid, $now, $today.

System plugins talk to the orm key (system-only):

const orm = ctx.get<OrmService>('orm')
const ids = await orm.search('invoice', [['state', '=', 'draft'], '|', ['total', '>', 100], ['partner.name', 'ilike', 'acme']], ctx, { limit: 20 })
const [inv] = await orm.read('invoice', ids, { number: {}, partner: { email: {} }, lines: { subtotal: {} } }, ctx)
await orm.write('invoice', ids, { lines: [{ op: 'create', values: { qty: 2 } }] }, ctx)   // x2many commands: create/update/delete/link/unlink/set or a bare id list
await orm.readGroup('invoice', { domain: [], groupBy: ['state', 'created_at:month'], aggregates: { sum: 'sum:total' } }, ctx)
orm.on('write', ({ model, ids, values }) => { /* automation, audit */ })

Domains are prefix notation (& implicit, |, !), ops = != < <= > >= in not in like ilike (a like value without % is a literal substring — %, _, \ are escaped and it is wrapped in %…%; a value containing % is used as a raw pattern); dotted paths cross relations. ctx is { userId?, isAdmin?, sudo? }; sudo bypasses the guard. An access-control plugin narrows every operation with orm.setGuard({ can({ ctx, model, op }), domain({ ctx, model, op }) }). orm.spec(model) is the resolved schema a UI can render forms from; REST lives under /api/orm (docs/building-a-ui.md). Handlers owned by agent plugins run in the executor and get env = { model, ctx }; system handlers also get env.orm.

Automation and audit (@sms/plugin-automation, @sms/plugin-audit)

Both are ordinary plugins: [...] entries, installed after the ORM and rbac. createAutomationPlugin() owns the automation point: on create/write/unlink of a model (optionally only when a watched field changed and the record still matches filter) or every everyMinutes (the scheduler ticks automation.tick, last runs are kept in au_automation_run), it calls a model method, writes values, posts an audit note (when audit is provided — otherwise a no-op) or runs an inline handler — all as sudo, guarded against re-entering itself. createAuditPlugin({ contextOf, group? }) provides audit and the audit_message / audit_activity / audit_follower models (user references are plain ints), tracks the fields listed in audit-track contributions, cascades on unlink and serves /api/audit/.... group contributes the rbac access rows and the “own activities” rule for that group; without it, grant access yourself (under rbac the models are closed by default).

Your own extension point

activate(ctx) {
  const kernel = ctx.kernel!
  kernel.definePoint({
    name: 'report',
    description: 'A report the finance page shows: { title, query }',
    validate: (item) => { if (typeof (item as { title?: unknown }).title !== 'string') throw new Error('title required') },
  })
  kernel.observePoint<Report>('report', {
    added: (c) => reports.set(c.id, c.item),     // react
    removed: (c) => reports.delete(c.id),        // the exact inverse — the kernel calls it on undo
  })
}

removed must be a true inverse of added; the kernel does the bookkeeping, you do the reaction.

Gates and invariants: your safety policy

await ctx.contribute('gate', {
  name: 'no-finance-writes',
  run: ({ manifest }) => manifest.contributes?.['collection-hook']?.some((h) => (h as { collection: string }).collection === 'ledger')
    ? 'agent plugins may not hook the ledger' : undefined,
})
await ctx.contribute('invariant', {
  name: 'ledger-intact',
  check: (kernel) => { if (!kernel.has('ledger')) throw new Error('ledger service withdrawn') },
})

Both points are system-only: the agent cannot see, add or remove them. Pair them with judge.sensitiveScopes / sensitivePoints in createBaseline to decide what needs a human (default: scope net and DEFAULT_SENSITIVE_POINTS = route, schedule, model-method, model-hook, automation).

Agent plugins

The model defines them through the plugin_define tool; you can submit the same shape yourself with kernel.getValue<JudgeService>('judge').submit(manifest, 'me'). Ids must start with agent.. Code is an ES module with no imports:

export default async function activate(cap) {
  await cap.contribute('tool', {
    name: 'high_value_invoices', description: 'Invoices over 10k',
    input_schema: { type: 'object', properties: {} },
    handler: async () => (await cap.invoke('collections', 'list', 'invoice', { limit: 500 })).filter((i) => i.amount > 10000),
  })
}

cap.get / invoke return JSON snapshots; functions inside contributed items become host-callable refs and stop working the instant the plugin is disposed. In the QuickJS executor the code also has a memory limit and a CPU deadline per slice; there are no timers, no fetch, no process.

Testing your plugins

@sms/baseline/testkit boots a real baseline (in-memory SQLite, Node executor, scripted model, approvals skipped) and gives you a fetch-style call:

import { call, createTestBaseline } from '@sms/baseline/testkit'
const app = await createTestBaseline({ plugins: [invoicesPlugin], turns: [() => 'pong'] })
expect((await call(app, '/api/collections/invoice', { body: { total: 3 } })).status).toBe(200)
expect((await call(app, '/api/chat', { body: { text: 'hi' } })).json.reply).toBe('pong')
await app.tick() // run due schedules
await app.close()

Auth and rbac are off by default (open admin routes, sudo ORM); pass auth: { iterations: 1000, bootstrapAdmin } to test permissions. Pass store / executor to test on the exact drivers production uses — for Cloudflare, openDurableObjectStore(fakeSqlStorage()) from @sms/store-do/testing with QuickJSExecutor.

Persistence

Installed/enabled state is an event log; bundles are content-addressed blobs. Collection tables are kept when a declaration is withdrawn, so disable/enable never loses data. Your system plugins are re-installed on every boot from code; agent plugins are re-mounted from the log by kernel.restore().

Building a UI

The baseline ships no HTML. The admin-api plugin exposes JSON routes and your application owns the frontend — React, HTMX, a Slack bot, a CLI — whatever your product already is. This keeps the agent’s reach and the human’s approval surface identical no matter how you render them.

Routes (@sms/plugin-admin-api, prefix /api by default)

RoutePurposeToken
GET /api/stateeverything an admin screen needs: plugins[] (id, version, trust, state, enabled, error, waitingFor), pending[] (approvals with manifest + reason), collections[] (schemas), points[], keys[], routes[], schedules[] (name, owner, everyMs, lastRun, lastError), gates[]
GET /api/catalogwhat the model sees: keys, extension points with their contributions, plugins
POST /api/chat { session?, text }one turn: { reply, steps: [{ tool, input, output, error? }] }
POST /api/chat/stream { session?, text }the same turn as server-sent events (see below)
GET /api/chat/:session · DELETE …history / reset· / ✔
POST /api/plugins/:id/enable · /disable · DELETE /api/plugins/:idlive undo / redo / remove (agent plugins only; system ids are refused)
POST /api/approvals/:id/approve { by? } · /reject { by?, reason? }the human half of the judge
GET /api/events?limit=100audit log, newest first (plugin/*, fiber/*, judge/*, chat/*)
GET /api/collections[/name[/id]] (+ POST/PATCH/DELETE)generic CRUD from the collections plugin
GET /api/orm/meta[/:model]resolved model specs (fields, kinds, relations) — render forms and lists from these
GET /api/orm/:model?domain=[…]&fields={…}&limit=&offset=&order=search + read → { length, records }
POST /api/orm/:model { …values } · GET/PATCH/DELETE /api/orm/:model/:idcreate / read one (?fields=) / write / unlink
POST /api/orm/:model/group { domain, groupBy, aggregates } · /onchange { values, changed } · /call/:method { ids, args }readGroup, form onchange, model methods

The ORM routes take their OpContext from createOrmPlugin({ contextOf }) (an auth plugin’s session, for example); with the default {} every request is anonymous and only the guard decides.

One round-trip: /api/rpc (createBaseline({ rpc: true, meta: true }))

RouteBody → result
POST /api/rpc{ model, method, args?, kwargs? } or an array of them: the caller is resolved once, calls run in order, and the answer is always 200 with { result } / { error: { message, kind } } per call (an array in → an array out). Methods: search_read { domain, fields, limit, offset, order } · read { ids, fields } · create { values } · write { ids, values } · unlink { ids } · read_group · onchange { values, changed } · defaults · call { method, ids, args } · fields · rights (→ { read, write, create, unlink } as rbac will enforce them)
GET /api/rpc/meta{ models, menus, actions, user } — menus/actions come from @sms/plugin-meta (empty without it), user from auth
GET /api/rpc/meta/:model{ spec, views?, rights }views only when meta is on and something was contributed
/api/audit/:model/:id/messages · /activities[/:aid] · /followers · /follow · /unfollow · GET /api/audit/activities/minemessages, activities and followers of one record (@sms/plugin-audit); 404 when the record is not visible to the caller
your own route contributionsanything else

Token: authorization: Bearer <adminToken> or x-admin-token. Configure it in createBaseline({ adminToken }). When your app has its own users, a system plugin can admit its admin sessions instead of (or as well as) the token by contributing to the admin-authorizer point (system-only):

contributes: { 'admin-authorizer': [{ name: 'session', authorize: (req) => isAdminSession(cookieValue(req, 'sid')) }] }

With neither a token nor an authorizer, mutating routes are open (local development only). The baseline deliberately knows only “may mutate / may not” — per-user permissions live in your plugins.

Users and sessions (@sms/plugin-auth)

Install createAuthPlugin({ bootstrapAdmin: { login, password } }) and the baseline has users: PBKDF2 passwords (WebCrypto — works in a Worker), cookie sessions, and an admin-authorizer so an admin’s session drives every /api/* route above without the bearer token.

RoutePurpose
POST /api/auth/login { login, password }{ user, token }; sets the sms_session HttpOnly cookie (Secure behind https)
POST /api/auth/logoutends the session, clears the cookie
GET /api/auth/session{ user } or 401

Your own routes ask identity.whoami(req) (key identity, injectable by agent plugins too — it never returns secrets). User management (identity-admin: create, setPassword, setAdmin, deactivate, activate) is a system-only key. Groups and permissions are @sms/plugin-rbac’s job.

Groups and permissions (@sms/plugin-rbac)

RouteReturnsAdmin
GET /api/rbac/groupsdeclared groups { name, description?, implies?, owner }
GET /api/rbac/users/:id/groups{ direct: string[], all: string[] } (all expanded through implies)
PUT /api/rbac/users/:id/groups { groups }replaces the user’s direct groups

“Admin” here means the identity provider (your auth plugin) says isAdmin for the session — not the admin token. In your own routes: await rbac.assertCan({ userId, model, op }) (403 on failure) and AND await rbac.ruleDomain({ userId, model, op }) into the query.

Errors

Every baseline route answers errors as { error: { message, kind } } with a matching status (validation 400, auth 401, forbidden 403, not_found 404, conflict 409, internal 500 — the last one also carries plugin, the owner of the failing route). Use the same shape in your own routes: throw new HttpError(404, 'no such invoice') or return errorJson('bad id', 400) from @sms/plugin-http.

A minimal chat + approvals screen

const api = (path, init = {}) => fetch(path, { ...init, headers: { authorization: `Bearer ${token}`, 'content-type': 'application/json', ...init.headers } })
async function send(text) {
  const r = await (await api('/api/chat', { method: 'POST', body: JSON.stringify({ session: userId, text }) })).json()
  render(r.reply, r.steps)               // show tool calls: plugin_define → verdict, etc.
  refresh()
}
async function refresh() {
  const s = await (await fetch('/api/state')).json()
  renderPending(s.pending)               // approve/reject buttons → POST /api/approvals/:id/approve
  renderPlugins(s.plugins)               // enable/disable toggles for trust === 'agent'
  renderCollections(s.collections)       // tables from schema; rows from /api/collections/:name
}

Showing agent-made UI safely

Agent plugins cannot contribute HTML to the baseline (there is no such point). If your product wants agent-authored panels, define your own extension point in a system plugin (ui-panel: { title, html }), mark it sensitivePoints so a human approves each one, and render the HTML in a sandboxed iframe or through a strict sanitizer. The kernel will validate, record and undo those contributions like any other.

Streaming, long chats

POST /api/chat returns when the turn is done (tool loops included; maxSteps in the agent-loop options). POST /api/chat/stream is the same turn as text/event-stream: one data: <json> frame per AgentEvent (@sms/plugin-agent-loop):

eventpayloadwhen
message{ message: { role, content } }each transcript message as it is appended (user text, assistant turn, tool results)
text_delta / thinking_delta{ text }model output / reasoning as the driver streams it (drivers without stream() send the text in one delta; thinking only where the provider exposes it)
tool_use{ block }a complete tool call, before it runs
tool_start / tool_end{ id, name, input } / { id, step }around each tool handler
done / error{ result: { reply, steps } } / { message }terminal — exactly one of them ends the stream

Read it with fetch + ReadableStream (cookies and the bearer token work; EventSource cannot POST): split on blank lines, JSON.parse after data: . The turn keeps running server-side if the client disconnects, and turns on one session run one after another. Your own routes get the same stream from agent.chatStream(session, text) and can return sse(events) from @sms/plugin-http; the agent key is system-only, so such a route lives in one of your system plugins. For durable transcripts implement AgentSessionStore (load on a cache miss, append per message) and pass a factory as createBaseline({ sessionStore: (kernel) => store }) — it runs before your plugins install, so load() may read any key from the kernel it is given.

Drivers

Host specifics are drivers behind contracts in @sms/contracts (Linux device-driver style, and dsh’s “consumers depend on definitions, never providers”). Plugins and the baseline depend only on the contract; a downstream app picks a driver per concern.

ConcernContractDrivers
persistenceStore { db: Database, log, blobs, close }store-sqlite · store-postgres · store-do · store-d1 (all built on the store-sql helper)
database for pluginsDatabase { dialect, exec, query, columns, close } (key database)provided by every store
files / objectsObjectStore { put, get, head, delete, list } (key objects)objects-s3 (AWS S3, MinIO, R2 via S3 API) · objects-r2 (bucket binding) · createMemoryObjectStore (tests)
HTTPHost { listen(handler) → HostServer }host-node · host-fastify · host-cloudflare
tenancyTenantResolver (request) → tenantIdtenantFromHeader, tenantFromSubdomain({ root, fallback, reserved }), your own
agent codeExecutor { load(bundle, host, opts?) → ExecutorInstance } (in @sms/kernel)executor-node · executor-quickjs
modelModelService { name, complete(req), stream?(req) }model-claude · model-gpt (subscription CLIs) · model-claude-api · model-gpt-api · model-openrouter (API keys, Worker-safe) · model-gpt-oauth (ChatGPT subscription, Worker-safe, unofficial) · createScriptedModel (tests)

Store drivers

@sms/store-sql turns any Database into a Store (tables kernel_events, kernel_blobs). A driver is therefore just a Database:

export function myDatabase(conn): Database {
  return {
    dialect: 'postgres' | 'sqlite',
    exec: async (sql) => { /* DDL, may be several statements */ },
    query: async (sql, params = []) => rows,  // `?` placeholders; return rows (INSERT … RETURNING id)
    columns: async (table) => [...names],     // [] if the table does not exist
    close: async () => {},
  }
}
export const openMyStore = async (conn) => createSqlStore(myDatabase(conn))

Dialect rules the collections plugin relies on (sqlDialect(dialect) in store-sql): auto-increment id column, BOOLEAN vs INTEGER, DOUBLE PRECISION vs REAL, ?$n (use numberPlaceholders). All identifiers are validated against ^[a-z][a-z0-9_]{0,40}$ and double-quoted.

  • sqlitenode:sqlite, one file per kernel (:memory: for tests), WAL on.
  • postgrespg.Pool from a connectionString (creates the schema, pins search_path per connection) or any { query } client such as PGlite (in-process Postgres, used by the tests). schema = one per tenant.
  • do — a Durable Object’s ctx.storage.sql (structural type, no workers-types dependency).
  • d1 — a Cloudflare D1 binding (openD1Store(env.DB); structural type). D1 is SQLite without schemas and single-writer per database, so tenancy is one D1 database per tenant — pick the binding by tenant id in createCloudflareApp({ store }). Multi-line DDL is flattened because D1Database.exec runs one statement per line. Use it when a tenant’s data must be reachable outside its Durable Object (dashboards, wrangler d1 queries); store-do is otherwise simpler and faster.

Two suites run against every driver — run both against yours: packages/core/contracts/test/database-contract.ts (databaseContract(name, () => db): DDL, ? binding, columns(), quoting) and packages/plugins/collections/test/contract.ts, which boots the collections plugin on top.

Object storage drivers

ObjectStore is the file/attachment counterpart of Database: an S3-shaped key → bytes store the composition root provides under the key objects (OBJECTS_KEY; createBaseline defines it system ↔ system, same wall as database). Keys are /-separated paths (no leading /, no ..); put accepts a string, bytes or a ReadableStream; get returns metadata plus body (stream) / bytes() / text(); list({ prefix, delimiter, limit, cursor }) pages S3-style and groups folders into prefixes when a delimiter is given. No multipart, no presigned URLs.

  • s3createS3ObjectStore({ bucket, endpoint, region, accessKeyId, secretAccessKey, sessionToken, forcePathStyle }): Signature V4 over pure fetch + WebCrypto, no aws-sdk, runs in Node and Workers. One driver for AWS S3 (no endpoint), MinIO (endpoint: 'http://localhost:9000' — path style is on whenever an endpoint is set) and R2 from outside Cloudflare (endpoint: 'https://<account>.r2.cloudflarestorage.com', region: 'auto', an R2 API token). Errors are S3Error { status, code }.
  • r2createR2ObjectStore(env.FILES) on a bucket binding inside a Worker / Durable Object: no credentials, streams pass straight through. Structural R2BucketLike type, no workers-types dependency.

Provide it from your composition root exactly like the database:

{ manifest: { id: 'app.objects', version: '1', provide: [OBJECTS_KEY] },
  activate: (ctx) => ctx.provide(OBJECTS_KEY, createS3ObjectStore({ … })) }

The contract suite packages/core/contracts/test/objects-contract.ts (objectsContract(name, () => store)) runs offline against the memory store and both drivers’ fakes in pnpm test; SMS_LIVE_OBJECTS=1 S3_ENDPOINT=http://localhost:9000 S3_BUCKET=… S3_ACCESS_KEY_ID=… S3_SECRET_ACCESS_KEY=… pnpm test (optional S3_REGION) runs it against a real MinIO / R2 / S3 bucket (a fresh t-…/ prefix per run).

Host drivers

A host takes RequestHandler = (Request) → Promise<Response> and puts it on the wire.

  • nodecreateNodeHost({ port, host }).listen(handle); toRequest/sendResponse are exported for reuse.
  • fastifycreateFastifyHost({ app, prefix }).listen(handle) mounts a catch-all under prefix on your existing Fastify instance (raw bodies, reply.hijack()), or creates one.
  • cloudflarecreateCloudflareApp({ resolve, binding, tenant }) returns the Worker fetch and a Durable Object class; each tenant’s DO opens store-do on its SQLite and calls your tenant({ tenantId, env, store }), which returns anything with a handle (a createBaseline() result). One traditional Worker, no Dynamic Workers. store: ({ tenantId, env, state }) => Store swaps the DO SQLite for e.g. openD1Store(env.DB). The driver depends only on contracts, so it can host any RequestHandler.

Executors

executor-nodeexecutor-quickjs
mechanismworker_threads, code as a data: ESM import, ambient globals strippedQuickJS interpreter compiled to WASM, one runtime per plugin
boundarysteering, not security (same process)real: own heap, memoryLimitBytes, CPU deadline per slice (sliceMs), no I/O, no import
bridgeRPC channel (@sms/plugin-sdk)JSON over one host function; cap built by an in-VM bootstrap
runs onNodeNode, browsers, Workers (variant: import('@jitl/quickjs-singlefile-mjs-release-sync'))
use forlocal dev, fastestproduction

Both implement Executor.load(bundle, host, opts?) → { call, dispose } and both pass the same executor tests (packages/drivers/executor/{node,quickjs}/test/executor.test.ts). Guest limits in QuickJS: no timers, no fetch, no process; functions inside contributed items are marshalled as { $fn } refs; every value crossing is JSON.

Model drivers

ModelService.complete({ system, messages, tools }) → { content, stopReason } is stateless and mirrors the Messages API shape: the loop executes tool_use blocks and calls again with tool_results. A driver may also implement stream(req): AsyncIterable<ModelEvent> — the same turn as text_delta / thinking_delta (reasoning, where the provider exposes it) / tool_use (complete calls) events ending in done: { response }, which must equal what complete() returns. Consumers call streamOf(model, req) from @sms/contracts, which falls back to complete() for drivers without it. model-openrouter and model-gpt-oauth stream today; the CLI-backed drivers fall back.

Six drivers ship. Two run on a locally logged-in CLI — a subscription, no API key — which means a Node process that can spawn claude / codex, so neither works in a Worker:

  • @sms/model-claude — the Claude Agent SDK (claude login). Kernel tools become an in-process MCP server; one SDK session per conversation, resumed when the system prompt changes.
  • @sms/model-gpt — the Codex SDK (codex login). Codex has no in-process tool API, so the driver runs a localhost streamable-HTTP MCP server (bearer token per process) and points each codex exec at it. One codex exec per turn, resumed by thread id; developer_instructions carries the system prompt; read-only sandbox in an empty scratch dir, no network, no web search (Codex’s shell tools cannot be removed, only contained). codex exec forces approval_policy=never and then only auto-approves MCP tools annotated readOnlyHint — the driver marks the kernel’s tools so (they never touch the host; the judge is their gate).

Both are built on SessionBridge from @sms/contracts: an agent SDK runs its own loop and executes tools itself, so the bridge exposes the kernel’s tools to the SDK and makes each tool handler block until the next complete() delivers the matching tool_result, handing the accumulated assistant blocks back to the loop as one turn. A new agent-SDK driver implements SessionBackend (start / setTools / send / close) and calls bridge.onText / toolCall / onTurnEnd / onError from the SDK’s stream. A plain request/response provider (an HTTP model API) needs none of that: map messages and tools in complete() directly, as createScriptedModel does. The two API-key drivers are exactly that, and being pure fetch they run anywhere — Node, Cloudflare Workers, Durable Objects (so does model-openrouter):

  • @sms/model-claude-api@anthropic-ai/sdk, Messages API (createClaudeApiModel({ apiKey, model, effort }); default claude-opus-5, adaptive thinking). Thinking blocks are not ModelContent, so the driver caches those that preceded a tool call and re-attaches them when the loop replays that assistant turn. Pass client to use a Bedrock/Vertex/Foundry client instead.
  • @sms/model-gpt-apiopenai, Responses API (createGptApiModel({ apiKey, model, effort }); default gpt-5.5, store: false with encrypted reasoning replayed the same way).
  • @sms/model-openrouteropenai pointed at https://openrouter.ai/api/v1, Chat Completions (createOpenRouterModel({ apiKey, model, effort, appName, siteUrl }); model is an OpenRouter slug, default anthropic/claude-sonnet-4.5; effort maps to OpenRouter’s unified reasoning.effort, nonemax). OpenRouter’s HTTP-200 errors (choices[0].error / finish_reason: 'error') are thrown. OpenRouter’s reasoning_details are cached and replayed before tool calls the same way. One key, any vendor — the simplest way to try a model none of the other drivers cover.

Subscription vs API key: a personal Claude / ChatGPT subscription is officially usable only through the CLI drivers on a machine you log in on; anything serverless or multi-user needs the -api drivers and a key.

  • @sms/model-gpt-oauth — the exception, for personal single-user instances: the OAuth tokens codex login writes to ~/.codex/auth.json sent to Codex’s own backend (chatgpt.com/backend-api/codex, Responses-shaped, SSE) with Codex CLI’s headers — the same wiring OpenClaw, Hermes, pi and opencode use. Pure fetch, so it runs in a Worker. createGptOauthModel({ unofficial: true, tokens, store?, model, effort }); tokens is a CodexTokens, or the text of auth.json (in Node: readCodexAuth() from @sms/model-gpt-oauth/node); store (kvTokenStore(kv), or fileTokenStore(path) from /node) persists refreshed tokens. Tokens are refreshed before expiry and once more on a 401. unofficial: true is mandatory because the endpoint is undocumented, fingerprints clients and may change, and OpenAI’s docs say programmatic use should go through API keys and that tokens must not be pooled or shared — never put it behind a multi-user service. SMS_LIVE_MODELS=1 runs its contract on your login.

Any driver must pass packages/core/contracts/test/model-contract.ts (streaming drivers get an extra case that checks the deltas add up to done.response); the -api / -oauth drivers run it offline against a scripted fetch, and live behind SMS_LIVE_MODELS=1 (CLI and oauth drivers: the login; -api drivers: the key in ANTHROPIC_API_KEY / OPENAI_API_KEY / OPENROUTER_API_KEY).

Writing a new driver

  1. Implement the contract in a new package packages/drivers/<kind>/<name> depending only on @sms/contracts (and @sms/kernel for Executor). Never import a sibling driver — the gate (scripts/quality/layers.ts) allows only the store-sql helper and the listed exceptions (host-fastify → host-node, host-cloudflare → store-do).
  2. Reuse the shared tests: store drivers run databaseContract and collectionsContractTests; object stores run objectsContract; executors copy packages/drivers/executor/quickjs/test/executor.test.ts; model drivers run modelContract from packages/core/contracts/test.
  3. Add it to tsconfig.build.json references and keep package.json in the standard shape (exports with sms-source / types / import, files: ["dist"]).

Tenancy

The kernel is single-tenant on purpose. One kernel = one event log, one set of plugins, one database, one judge state. Multi-tenancy is a host concern: resolve the tenant from the request, give each tenant its own kernel on its own store. Nothing is shared between tenants except code, so an agent plugin that one tenant approves can never touch another tenant’s data or schema.

request ──resolve──▶ tenantId ──▶ kernel[tenantId] ──▶ http.handle(request)
                                     │
                                     └── store: sqlite file / postgres schema / durable object

On Node / Fastify: createTenantPool

import { createTenantPool, tenantFromHeader } from '@sms/baseline'
import { openPostgresStore } from '@sms/store-postgres'

const tenants = createTenantPool({
  resolve: tenantFromHeader('x-tenant'),                // or tenantFromSubdomain(), or (req) => jwt(req).org
  tenant: async (id) => ({                               // BaselineOptions for this tenant
    store: await openPostgresStore({ connectionString: DATABASE_URL, schema: `tenant_${id}` }),
    executor, model, plugins: [invoicesPlugin],
    adminToken: tokens[id],
  }),
  idleMs: 30 * 60_000,                                   // close kernels idle for 30 min; they re-boot on demand
})
await createFastifyHost({ app, prefix: '/sms' }).listen(tenants.handle)
  • Tenant ids are validated (^[a-z0-9][a-z0-9_-]{0,62}$) because they become file / schema names.
  • Booting is memoised per tenant; a failed boot is retried on the next request.
  • pool.get(id) returns the tenant’s Baseline (for jobs, migrations, tests); tenants() lists the booted ones; evict(id) closes one; close() closes all.
  • A request whose tenant does not resolve gets onMissing(request) (both createTenantPool and createCloudflareApp take it) or a 400 no tenant by default.
  • Postgres: one Pool per tenant with search_path pinned to the schema; the store creates the schema. SQLite: one file per tenant (openSqliteStore(data/${id}.db)).

Cost model: a warm kernel is a few objects plus the executor instances of its agent plugins (QuickJS: one small WASM runtime each). Thousands of idle tenants are fine with idleMs; keep hot ones warm.

On Cloudflare: one Durable Object per tenant

const app = createCloudflareApp<Env>({
  resolve: (req, env) => tenantFromSubdomain({ root: env.ROOT_DOMAIN, fallback: 'dev' })(req),
  binding: 'TENANT',
  tenants: (env) => (env.CRON_TENANTS ?? '').split(',').filter(Boolean), // who the cron trigger ticks
  tenant: ({ tenantId, env, store }) =>
    createBaseline({ name: tenantId, store, executor: new QuickJSExecutor({ variant: import('@jitl/quickjs-singlefile-mjs-release-sync') }), model, plugins }),
})
export const TenantKernel = app.DurableObject
export default { fetch: app.fetch, scheduled: app.scheduled }

tenantFromSubdomain({ root, fallback, reserved }) maps acme.example.comacme, the bare root / localhost / IPs → fallback, acme.localhostacme (local dev without DNS) and refuses reserved labels (www, api, …). resolve receives env, so root domains can come from wrangler vars.

Scheduled jobs (@sms/plugin-scheduler): a Durable Object cannot enumerate itself, so the Worker’s scheduled() ticks the tenants tenants(env) returns (a wrangler var, a KV list, a registry DO you keep). The tick travels as an internal request the public fetch can never forge. On Node, setInterval(() => pool.tick(), 60_000) does the same for every booted tenant.

The Worker’s fetch resolves the tenant and forwards to TENANT.get(idFromName(tenantId)); the DO opens @sms/store-do on its own SQLite (or whatever the store option returns, e.g. openD1Store(env.DB)), boots the kernel once and keeps it in memory until the platform evicts it (the log + blobs survive in DO storage; restore() re-mounts plugins on the next boot). Single-threaded per DO, transactional storage, global addressing — the Durable Object is the tenant pool.

Sharing across tenants

Share code (system plugins, drivers, the model) — pass the same objects to every tenant. Do not share a Store, an Executor instance’s plugin instances, or admin tokens. If you need cross-tenant features (a marketplace of approved agent plugins, say), implement them as a system plugin that talks to other kernels through the pool — never by pointing two kernels at one log.

Architecture

Where this comes from

The design follows the thesis in the companion research vault (../sms-research): safe live self-modification needs a substrate (revertible effects + reactive dependencies, from Cordis / the Spatiotemporal Composability paper), a judge the agent cannot reach (the lesson of the Darwin Gödel Machine’s objective hacking), and persistence (which DeepSeek Harness deliberately skipped: “scratch, not memory”). No shipped system had all three; this repo is an attempt to — packaged so that other applications can adopt it. docs/research-positioning.md maps every concept to code and carries the threat model.

What we copied, and from whom:

FromTakenChanged
Linuxa small generic kernel; drivers behind contracts; everything else loadabledrivers are npm packages picked at composition time
Cordis / dshfiber per plugin, dispose-on-failed-start, inject/provide keys, façade-style ctx, immutable versions with a moving current; “consumers depend on service definitions, never providers”effects are a closed vocabulary so undo is derived by the host, never written by the (LLM) author
dsheverything is a plugin; human approves the visible halfapproval is a judge policy (sensitiveScopes/Points), not baked in; there is no visible half — the baseline is headless
pithe loader loop is enough — no “modify yourself” API beyond the tools the agent hasthe loader is plugin_define → judge → kernel; no file system needed
DGMa judge that is out of reachtrust tiers inside the kernel + authorization tokens, instead of hiding
Strapi / Directusdeclarative collections with auto CRUD/REST/hookscollections are just an extension point owned by a plugin, on any SQL engine

Rings

Deeper is more abstract — the Linux kernel / OSI shape. A package imports its own ring or below; the tree is the diagram, and scripts/quality/layers.ts is the same model as code (pnpm quality enforces it, docs/dependency-graph.md is generated from it by pnpm graph).

ring 4  examples/*                    composition roots: pick drivers, add plugins, listen
ring 3  packages/baseline             @sms/baseline: createBaseline() · createTenantPool() · testkit · re-exports every plugin
ring 2  packages/plugins/*      │     packages/drivers/{store,host,executor,model,objects}/*
        features, platform-free │     one contract each, platform-specific; never import a plugin
        http · collections · judge · agent-loop · admin-api · scheduler · auth · rbac · orm · meta · rpc · automation · audit
ring 1  packages/core/plugin-sdk │    packages/core/contracts
        what agent code sees:    │    the waist: Database · Store · Host · TenantResolver · ModelService · ObjectStore
        cap.provide/contribute/  │    (kernel types only — never plugin-sdk)
        get/invoke/log + channel │
ring 0  packages/core/kernel          loader · registry · fibers · derived undo · event log · trust tiers · Executor interface

The kernel is the single root; every ring above it is a pair of siblings that never import each other and meet only in the ring above. Ring 1 splits ergonomics (plugin-sdk) from vocabulary (contracts); ring 2 is the hourglass: plugins and drivers are siblings on top of contracts, and neither column imports the other. Plugins are also platform-free (no node:*, no SDKs) so they run wherever the kernel runs.

Plugins depend on definitions, never providers (the Cordis rule; Linux modules link against exported symbols, not each other’s source). Each plugin has two faces:

@sms/plugin-x/contract (src/contract.ts)@sms/plugin-x (src/index.ts)
holdsX_KEY/X_POINT constants, service + item types, validators, pure helperseverything in the contract, plus createXPlugin() / xPlugin
imported byother plugins (the only allowed subpath between plugins)composition roots: baseline, apps, tests
may reachcontracts, kernel types, other contractsanything below ring 3

The manifest is the runtime counterpart: inject (hard — the reconciler waits for it and unloads the fiber before its provider) and optional (soft — read with ctx.kernel.getValue, present in FiberView). The gate cross-checks the three: a runtime import of a sibling’s contract, a getValue(key) call, and the manifest must agree. The plugin graph is a DAG.

The kernel

Kernel
├─ keys        name → { value, owner }          + KeyMeta { minProviderTrust, minConsumerTrust }
├─ points      name → Contribution[]            + ExtensionPointMeta { minContributorTrust, validate }
├─ fibers      id   → { manifest, trust, enabled, state, effects[] }
├─ settle()    reconciler: enabled ∧ inject satisfied → activate; disabled ∨ dependency gone → deactivate
├─ log         append-only events; foldTarget(events) = what should be installed/enabled
└─ executor    Executor.load(bundle, HostBridge) for code the kernel will not run in-process

Fiber lifecycle: inactive → loading → active → unloading → inactive, or loading → failed. Activation applies manifest.contributes first (declarative), then runs the plugin’s activate (in-process for system plugins; through the executor for agent plugins). Every provide/contribute pushes an AppliedEffect with its inverse. A throw anywhere unwinds what ran.

Ordering (Cordis Thm 63, “provider outlives consumers”): deactivating a fiber first deactivates every active fiber that injects one of its provided keys, recursively, then undoes its own effects. settle() then re-activates whatever became satisfiable again.

Trust tiers: system (installed by the composition root, in-process, holds ctx.kernel) and agent (proposed at run time; never holds KernelApi). Keys and points carry minimum trust; Registry.get/provide/ contribute check it every time. Kernel.propose() refuses an agent manifest without a MountAuthorization minted by Kernel.authorize() — which is only reachable through ctx.kernel, i.e. from system code. A forged or reused nonce, or a manifest whose code hash differs from the authorized one, is rejected. An agent manifest whose id belongs to a system fiber is rejected (RESERVED_ID) — otherwise “update” would replace the judge itself — and uninstall refuses system fibers unless the composition root passes force.

Executor boundary: plugin code never receives objects. It gets cap whose calls go over a bridge to the kernel’s HostBridge, which re-checks inject and trust on every get/invoke. Functions inside contributed items are marshalled as { $fn: id } and turned into async proxies by the kernel, so a tool handler written by the agent is callable by the host, and stops working the instant the fiber is disposed. Values flowing to plugin code are JSON snapshots.

Drivers (the “device” layer)

@sms/contracts defines what a host must supply; the baseline and plugins depend on that, never on an engine:

ContractUsed byDrivers
Database { dialect, exec, query(sql, ?-params), columns, close }collections (key database), store-sqlsqlite (node:sqlite), postgres (pg/PGlite; schema per tenant), do (Durable Object SqlStorage), d1 (one D1 per tenant)
Store { db, log, blobs, close }kernel (log, blobs)createSqlStore(db) in store-sql turns any Database into a Store
ObjectStore { put, get, head, delete, list }file-handling plugins (key objects)s3 (AWS / MinIO / R2 over S3, SigV4 on fetch), r2 (bucket binding), memory (tests)
Host { listen(handler) }composition rootsnode (node:http), fastify (mount under a prefix, encapsulated scope), cloudflare (Worker fetch + DO class)
TenantResolvercreateTenantPool, createCloudflareApptenantFromHeader, tenantFromSubdomain, custom
Executor (kernel)kernel, judge’s load gatenode (worker_threads), quickjs (WASM)
ModelServiceagent loop (key model)claude (Claude Agent SDK, claude login), gpt (Codex SDK, codex login), claude-api (Messages API), gpt-api (Responses API), openrouter (Chat Completions), gpt-oauth (Codex backend, personal login), scripted (tests)

Every store driver passes packages/core/contracts/test/database-contract.ts and the collections contract suite; object stores pass packages/core/contracts/test/objects-contract.ts; both executors pass the same executor tests; model drivers pass packages/core/contracts/test/model-contract.ts. See docs/drivers.md.

Persistence

The event log is the source of truth; mounted state is a cache. plugin/installed (with manifest and code hash), plugin/enabled, plugin/disabled, plugin/uninstalled fold into a target map. Kernel.restore() re-creates agent fibers from that map (fetching code from the blob store by hash) and settles. System plugins are re-installed by the composition root each boot; their enabled flag is taken from the log. fiber/*, judge/* and chat/* events are audit only. Tables: kernel_events, kernel_blobs, c_<collection>; withdrawing a collection or field keeps its table/column.

Tenancy

The kernel is single-tenant. createTenantPool({ resolve, tenant }) boots one baseline per tenant id on its own store (file / schema / DO) and routes each request; on Cloudflare the Durable Object is that pool entry. Tenant ids are validated because they become file and schema names. See docs/tenancy.md.

The judge (a plugin)

Gates (the gate point, system-only): manifesttrustsource-lintload (activate in a throwaway executor with a recording bridge; provided keys must be declared; unknown points fail). Then policy: sensitive scopes/points → pending human approval (/api/approvals). Then mount, then invariant contributions run against the live kernel; a violation rolls back and, for an update, restores the previous version from the log + blobs.

The judge is unreachable from agent code by four independent facts: judge is a system-only key; gate and invariant are system-only points; authorization minting lives on KernelApi; and system plugin ids are reserved (the judge additionally requires agent ids to start with agent.). The services other plugins rely on (http, collections, model, agent, database) can only be provided by system fibers. Tests: packages/core/kernel/test, packages/plugins/judge/test, packages/baseline/test.

Admin surface (headless)

plugin-admin-api contributes JSON routes only: /api/state, /api/catalog, /api/chat, plugin enable/disable/uninstall, approvals, /api/events. Users, groups and models come from @sms/plugin-auth, @sms/plugin-rbac and @sms/plugin-orm; createBaseline installs all three (auth: false opts out of the first two) and plugs rbac into the ORM’s guard: anonymous requests are denied, users pass the access matrix and record rules ($uid = caller), sudo contexts bypass. Mutating routes require the bearer token (createBaseline({ adminToken })) or the nod of an admin-authorizer contribution (system-only point — an auth plugin admitting its own admin sessions). There is no HTML and no UI extension point in the baseline; a consumer renders whatever it wants on top (docs/building-a-ui.md). Agent-authored UI, if a product wants it, is a consumer-defined extension point marked sensitive.

Containment

ExecutorBoundary
executor-nodeworker_threads: steering, not a security boundary (dsh’s label for node:vm). Removes process, fetch, require; shares nothing but the RPC port; the judge’s source-lint refuses obvious escapes. Dev use.
executor-quickjsQuickJS compiled to WASM: its own heap (memoryLimitBytes), CPU deadline per slice (sliceMs, interrupt handler), no I/O, no import, no timers; the only host function is __host(method, json). Runs on Node and, with the single-file variant, inside a Cloudflare Worker where eval/new Function are unavailable. Production use.

Neither executor can reach the judge or the kernel; that boundary is the trust tier, not the sandbox.

Cloudflare (one Worker, one Durable Object class)

PieceNodeCloudflare
Executorexecutor-node / executor-quickjsexecutor-quickjs (single-file WASM variant)
Storestore-sqlite / store-postgresstore-do (DO SQLite: same tables) / store-d1 (one D1 per tenant)
Objectsobjects-s3objects-r2 (bucket binding) / objects-s3
HTTP entryhost-node / host-fastifyhost-cloudflare: Worker fetchTENANT.get(idFromName(tenant)) → DO → app.handle
Everything elseunchangedunchanged

Dynamic Workers (worker_loader) would give a stronger per-plugin boundary but was ruled out for v1 to keep to one traditional Worker; QuickJS provides the per-plugin boundary inside the DO.

Packaging

Development runs TypeScript directly; releases are git tags pointing at detached release commits with dist/ committed and workspace:* rewritten to github:…#tag&path:/packages/x, cut by .github/workflows/cd.yml when a vX.Y.Z tag is pushed after pnpm check (scripts/release.ts, docs/releasing.md). Package exports carry an sms-source condition for in-repo source resolution and default to dist/.

Extension points shipped

PointOwnerItemAgent may contribute
routehttp{ method, path, handler(req) }yes (human by default)
schedulescheduler{ name, everyMs, handler(run) }yes (human by default)
grouprbac{ name, implies? }no (system)
accessrbac{ model, group, read?, write?, create?, unlink? }no (system)
rulerbac{ name, model, groups?, domain, ops? }no (system)
modelorm{ name, fields, displayField?, order? }yes
model-fieldorm{ model, name, spec }yes
model-methodorm{ model, name, handler(env, ids, args), access? }yes
model-hookorm{ model, on, when, handler(env, payload) }yes
model-onchangeorm{ model, field, handler(env, values) }yes
view / action / menumetaviews with inheritance, actions, menu tree (opt-in)yes
automationautomation{ id, model, trigger, watch?, filter?, action }yes (human by default)
audit-trackaudit{ model, fields[] }yes
admin-authorizeradmin-api{ name, authorize(req) }no (system)
collectioncollections{ name, fields[] }yes
collection-fieldcollections{ collection, field }yes
collection-hookcollections{ collection, on, handler(record, previous) }yes
toolagent-loop{ name, description, input_schema, handler(input) }yes
promptagent-loop{ section, text, order }yes
gatejudge{ name, run(ctx) }no (system)
(auth)authcontributes route ×3 and admin-authorizer auth-session; keys identity / identity-admin
invariantjudge{ name, check(kernel) }no (system)

Keys: database (system↔system), http, collections, model (system provides), judge (system↔system), agent (system↔system).

Dependency graph

Workspace packages by ring (deeper = more abstract; an edge points at what a package depends on). The layering rules that keep it this shape are in scripts/quality/layers.ts and docs/quality.md.

flowchart BT
  subgraph ring_kernel["ring 0 · kernel"]
    kernel["@sms/kernel"]
  end
  subgraph ring_contracts["ring 1 · contracts"]
    contracts["@sms/contracts"]
  end
  subgraph ring_plugin_sdk["ring 1 · plugin-sdk"]
    plugin_sdk["@sms/plugin-sdk"]
  end
  subgraph ring_driver["ring 2 · drivers"]
    executor_node["@sms/executor-node"]
    executor_quickjs["@sms/executor-quickjs"]
    host_cloudflare["@sms/host-cloudflare"]
    host_fastify["@sms/host-fastify"]
    host_node["@sms/host-node"]
    model_claude["@sms/model-claude"]
    model_claude_api["@sms/model-claude-api"]
    model_gpt["@sms/model-gpt"]
    model_gpt_api["@sms/model-gpt-api"]
    model_gpt_oauth["@sms/model-gpt-oauth"]
    model_openrouter["@sms/model-openrouter"]
    objects_r2["@sms/objects-r2"]
    objects_s3["@sms/objects-s3"]
    store_d1["@sms/store-d1"]
    store_do["@sms/store-do"]
    store_postgres["@sms/store-postgres"]
    store_sql["@sms/store-sql"]
    store_sqlite["@sms/store-sqlite"]
  end
  subgraph ring_plugin["ring 2 · plugins"]
    plugin_admin_api["@sms/plugin-admin-api"]
    plugin_agent_loop["@sms/plugin-agent-loop"]
    plugin_audit["@sms/plugin-audit"]
    plugin_auth["@sms/plugin-auth"]
    plugin_automation["@sms/plugin-automation"]
    plugin_collections["@sms/plugin-collections"]
    plugin_http["@sms/plugin-http"]
    plugin_judge["@sms/plugin-judge"]
    plugin_meta["@sms/plugin-meta"]
    plugin_orm["@sms/plugin-orm"]
    plugin_rbac["@sms/plugin-rbac"]
    plugin_rpc["@sms/plugin-rpc"]
    plugin_scheduler["@sms/plugin-scheduler"]
  end
  subgraph ring_baseline["ring 3 · baseline"]
    baseline["@sms/baseline"]
  end
  subgraph ring_app["ring 4 · apps"]
    example_cloudflare_worker["@sms/example-cloudflare-worker"]
    example_erp_fastify_postgres["@sms/example-erp-fastify-postgres"]
    example_reference_node_sqlite["@sms/example-reference-node-sqlite"]
  end
  contracts --> kernel
  executor_node --> kernel
  executor_node --> plugin_sdk
  executor_quickjs --> kernel
  host_cloudflare --> contracts
  host_cloudflare --> store_do
  host_fastify --> contracts
  host_fastify --> host_node
  host_node --> contracts
  model_claude --> contracts
  model_claude --> kernel
  model_claude_api --> contracts
  model_claude_api --> kernel
  model_gpt --> contracts
  model_gpt --> kernel
  model_gpt_api --> contracts
  model_gpt_api --> kernel
  model_gpt_oauth --> contracts
  model_gpt_oauth --> kernel
  model_openrouter --> contracts
  model_openrouter --> kernel
  objects_r2 --> contracts
  objects_s3 --> contracts
  store_d1 --> contracts
  store_d1 --> store_sql
  store_do --> contracts
  store_do --> store_sql
  store_postgres --> contracts
  store_postgres --> store_sql
  store_sql --> contracts
  store_sql --> kernel
  store_sqlite --> contracts
  store_sqlite --> store_sql
  plugin_admin_api --> kernel
  plugin_admin_api --> plugin_agent_loop
  plugin_admin_api --> plugin_auth
  plugin_admin_api --> plugin_collections
  plugin_admin_api --> plugin_http
  plugin_admin_api --> plugin_judge
  plugin_admin_api --> plugin_scheduler
  plugin_agent_loop --> contracts
  plugin_agent_loop --> kernel
  plugin_agent_loop --> plugin_judge
  plugin_audit --> kernel
  plugin_audit --> plugin_http
  plugin_audit --> plugin_orm
  plugin_auth --> contracts
  plugin_auth --> kernel
  plugin_auth --> plugin_http
  plugin_automation --> contracts
  plugin_automation --> kernel
  plugin_automation --> plugin_audit
  plugin_automation --> plugin_orm
  plugin_collections --> contracts
  plugin_collections --> kernel
  plugin_collections --> plugin_http
  plugin_http --> kernel
  plugin_judge --> kernel
  plugin_meta --> kernel
  plugin_meta --> plugin_orm
  plugin_orm --> contracts
  plugin_orm --> kernel
  plugin_orm --> plugin_http
  plugin_rbac --> contracts
  plugin_rbac --> kernel
  plugin_rbac --> plugin_auth
  plugin_rbac --> plugin_http
  plugin_rpc --> kernel
  plugin_rpc --> plugin_auth
  plugin_rpc --> plugin_http
  plugin_rpc --> plugin_meta
  plugin_rpc --> plugin_orm
  plugin_rpc --> plugin_rbac
  plugin_scheduler --> contracts
  plugin_scheduler --> kernel
  baseline --> contracts
  baseline --> executor_node
  baseline --> kernel
  baseline --> plugin_admin_api
  baseline --> plugin_agent_loop
  baseline --> plugin_auth
  baseline --> plugin_collections
  baseline --> plugin_http
  baseline --> plugin_judge
  baseline --> plugin_meta
  baseline --> plugin_orm
  baseline --> plugin_rbac
  baseline --> plugin_rpc
  baseline --> plugin_scheduler
  baseline --> plugin_sdk
  baseline --> store_sql
  baseline --> store_sqlite
  example_cloudflare_worker --> baseline
  example_cloudflare_worker --> executor_quickjs
  example_cloudflare_worker --> host_cloudflare
  example_cloudflare_worker --> model_claude_api
  example_cloudflare_worker --> model_gpt_api
  example_cloudflare_worker --> model_gpt_oauth
  example_cloudflare_worker --> model_openrouter
  example_cloudflare_worker --> objects_r2
  example_cloudflare_worker --> store_d1
  example_cloudflare_worker --> store_do
  example_erp_fastify_postgres --> baseline
  example_erp_fastify_postgres --> executor_quickjs
  example_erp_fastify_postgres --> host_fastify
  example_erp_fastify_postgres --> model_claude
  example_erp_fastify_postgres --> store_postgres
  example_reference_node_sqlite --> baseline
  example_reference_node_sqlite --> executor_node
  example_reference_node_sqlite --> host_node
  example_reference_node_sqlite --> model_claude
  example_reference_node_sqlite --> model_claude_api
  example_reference_node_sqlite --> model_gpt
  example_reference_node_sqlite --> model_gpt_api
  example_reference_node_sqlite --> model_gpt_oauth
  example_reference_node_sqlite --> model_openrouter
  example_reference_node_sqlite --> store_sqlite
PackageRingDepends on
@sms/kernelring 0 · kernel
@sms/contractsring 1 · contracts@sms/kernel
@sms/plugin-sdkring 1 · plugin-sdk
@sms/executor-nodering 2 · drivers@sms/kernel, @sms/plugin-sdk
@sms/executor-quickjsring 2 · drivers@sms/kernel
@sms/host-cloudflarering 2 · drivers@sms/contracts, @sms/store-do
@sms/host-fastifyring 2 · drivers@sms/contracts, @sms/host-node
@sms/host-nodering 2 · drivers@sms/contracts
@sms/model-claudering 2 · drivers@sms/contracts, @sms/kernel
@sms/model-claude-apiring 2 · drivers@sms/contracts, @sms/kernel
@sms/model-gptring 2 · drivers@sms/contracts, @sms/kernel
@sms/model-gpt-apiring 2 · drivers@sms/contracts, @sms/kernel
@sms/model-gpt-oauthring 2 · drivers@sms/contracts, @sms/kernel
@sms/model-openrouterring 2 · drivers@sms/contracts, @sms/kernel
@sms/objects-r2ring 2 · drivers@sms/contracts
@sms/objects-s3ring 2 · drivers@sms/contracts
@sms/store-d1ring 2 · drivers@sms/contracts, @sms/store-sql
@sms/store-doring 2 · drivers@sms/contracts, @sms/store-sql
@sms/store-postgresring 2 · drivers@sms/contracts, @sms/store-sql
@sms/store-sqlring 2 · drivers@sms/contracts, @sms/kernel
@sms/store-sqlitering 2 · drivers@sms/contracts, @sms/store-sql
@sms/plugin-admin-apiring 2 · plugins@sms/kernel, @sms/plugin-agent-loop, @sms/plugin-auth, @sms/plugin-collections, @sms/plugin-http, @sms/plugin-judge, @sms/plugin-scheduler
@sms/plugin-agent-loopring 2 · plugins@sms/contracts, @sms/kernel, @sms/plugin-judge
@sms/plugin-auditring 2 · plugins@sms/kernel, @sms/plugin-http, @sms/plugin-orm
@sms/plugin-authring 2 · plugins@sms/contracts, @sms/kernel, @sms/plugin-http
@sms/plugin-automationring 2 · plugins@sms/contracts, @sms/kernel, @sms/plugin-audit, @sms/plugin-orm
@sms/plugin-collectionsring 2 · plugins@sms/contracts, @sms/kernel, @sms/plugin-http
@sms/plugin-httpring 2 · plugins@sms/kernel
@sms/plugin-judgering 2 · plugins@sms/kernel
@sms/plugin-metaring 2 · plugins@sms/kernel, @sms/plugin-orm
@sms/plugin-ormring 2 · plugins@sms/contracts, @sms/kernel, @sms/plugin-http
@sms/plugin-rbacring 2 · plugins@sms/contracts, @sms/kernel, @sms/plugin-auth, @sms/plugin-http
@sms/plugin-rpcring 2 · plugins@sms/kernel, @sms/plugin-auth, @sms/plugin-http, @sms/plugin-meta, @sms/plugin-orm, @sms/plugin-rbac
@sms/plugin-schedulerring 2 · plugins@sms/contracts, @sms/kernel
@sms/baselinering 3 · baseline@sms/contracts, @sms/executor-node, @sms/kernel, @sms/plugin-admin-api, @sms/plugin-agent-loop, @sms/plugin-auth, @sms/plugin-collections, @sms/plugin-http, @sms/plugin-judge, @sms/plugin-meta, @sms/plugin-orm, @sms/plugin-rbac, @sms/plugin-rpc, @sms/plugin-scheduler, @sms/plugin-sdk, @sms/store-sql, @sms/store-sqlite
@sms/example-cloudflare-workerring 4 · apps@sms/baseline, @sms/executor-quickjs, @sms/host-cloudflare, @sms/model-claude-api, @sms/model-gpt-api, @sms/model-gpt-oauth, @sms/model-openrouter, @sms/objects-r2, @sms/store-d1, @sms/store-do
@sms/example-erp-fastify-postgresring 4 · apps@sms/baseline, @sms/executor-quickjs, @sms/host-fastify, @sms/model-claude, @sms/store-postgres
@sms/example-reference-node-sqlitering 4 · apps@sms/baseline, @sms/executor-node, @sms/host-node, @sms/model-claude, @sms/model-claude-api, @sms/model-gpt, @sms/model-gpt-api, @sms/model-gpt-oauth, @sms/model-openrouter, @sms/store-sqlite

Research positioning

The companion vault (../sms-research, see wiki/thesis.md) argues that safe live self-modification needs three things no shipped system combined: a substrate with revertible effects and reactive dependencies (Cordis / Spatiotemporal Composability), a judge outside the agent’s write set (the lesson of the Darwin Gödel Machine’s objective hacking), and persistence with an audit trail (what DeepSeek’s dsh deliberately skipped — “scratch, not memory”). sms-baseline is the attempt to have all three, packaged so that ordinary applications can adopt it.

The four questions, answered for sms-baseline

The vault compares systems along what / who / when / judge and the lifecycle Bootstrap → Propose → Evaluate → Commit → Serve. Our row:

sms-baseline
What is modifiedthe running application, as plugins: keys provided, extension-point contributions (routes, collections, fields, hooks, tools, prompts), and agent code. The unit of change is the fiber — exactly what the substrate can swap atomically (not functions like SelfEvolve, not whole containers like MOSS).
Who proposesthe model, through plugin_define; humans through the same judge API
Whenlive, in the same conversation; Commit = the plugin/installed event + content-addressed blob; Serve = the fiber is active and reachable through http/agent/collections
Judgethe judge system plugin: gates (manifest, trust, source-lint, load-in-throwaway-executor) → policy (sensitive scopes/points → human) → mount → invariants; rollback restores the previous version from log + blobs
Unreachability of the judgestructural, not hidden: judge key and gate/invariant points require system trust checked in the kernel on every access; MountAuthorization minted only via KernelApi, which agent contexts never receive; system ids reserved; the executor bridge re-checks inject and trust per call
BoundaryQuickJS-in-WASM executor: own heap, memory limit, CPU deadline, JSON-only bridge. The Node executor is labelled steering, not a security boundary, as dsh labels node:vm.
Persistenceevent-sourced (plugin/* fold into the target view), blobs by hash; SQLite, Postgres, D1, Durable Objects (drivers/store/*); files on S3 / R2 (drivers/objects/*)
Tenancykernel-per-tenant; the substrate never sees two tenants

Concepts from the vault and where they live here

ConceptHere
revertible-effectsclosed vocabulary provide/contribute; AppliedEffect.undo derived by the kernel; LIFO unwind (kernel.ts undoAll)
spatiotemporal-composability (Thm 63, provider outlives consumers)deactivate() unloads dependents first, settle() re-activates what became satisfiable
plugin-architecture five requirementsclosed effects, per-fiber isolation, reactive re-wiring, judge outside the write set, persistence as a separate axis
project-trust-gate (load-time trust is not enough)gates run at propose time and invariants run after every mount; trust is re-checked at every effect
transactional-no-regressionmount = checkpoint (previous version in log) → act (activate) → judge (invariants) → commit or full undo. Batch size K = one plugin activation.
objective-hacking / belief 6the judge’s inputs (gate, invariant) are system-only; but see Open questions on indirect contamination
dynamic-plugin-runtime (dsh)plugin_define → judge → kernel instead of a file loader; approval is a policy (sensitivePoints), not baked in
agent-operating-system (process boundary vs self-modification)one traditional Worker + DO per tenant; QuickJS inside; Dynamic Workers rejected for v1
event-sourced-session-logchat/*, judge/*, fiber/* events are audit; plugin/* are state
evaluator-co-evolutioninvariants are owned by system plugins; they can evolve only through a code release, never at run time

Threat model over the extension points (MLAS-style pass)

Stages: Propose (model calls plugin_define), Evaluate (gates/human), Commit (log + blob), Serve (fiber active).

SurfaceAttackWhere it is stopped
inject: ['judge'] / provide: ['judge']reach or replace the judgetrust gate (E) and kernel trust check (S); test agent plugins cannot reach system-only keys
contributes.gate / invariantweaken the evaluatorminContributorTrust: system (E, S)
id collision (judge, http, …)replace a system fiberRESERVED_ID (E, S); judge requires agent. prefix
forged / replayed authorizationmount without the judgenonce bound to id+version+code hash, single-use (C)
code escapes (process, fetch, import)I/O from agent codesource-lint (E); QuickJS has none of them (S); Node executor strips them (steering only)
runaway CPU / memorydenial of service inside the processQuickJS sliceMs interrupt + memoryLimitBytes; Node executor resourceLimits
route contribution shadowing /api/*hijack admin routesroutes match in contribution order (system first); add route to sensitivePoints if agents may add routes; the admin routes need the bearer token regardless
collection-hook with side effectsemissions outside the effect vocabulary (belief 8)not undoable by design; hooks run inside collections which catches and logs; keep external effects in system plugins
prompt contributionsteer the model’s later proposals (prompt injection from a plugin)recorded and visible in /api/catalog; treat prompt as sensitive if plugins come from untrusted tenants’ agents
indirect judge contaminationan agent-contributed collection/tool changes what an invariant readsinvariants should read kernel state (kernel.has, fibers), not collection data — documented rule, not enforced
cross-tenantone tenant’s agent plugin affects anotherkernel-per-tenant, separate stores; no shared executor instances

Open questions (deliberately not solved here)

  1. Emissions. activate() code cannot do I/O in QuickJS, but a system-provided service it invokes might. The vocabulary covers registry effects only; side effects through services are the plugin owner’s problem. A “compensating action” contract for services is future work.
  2. Evaluator co-evolution. Invariants are frozen per release. The vault’s RQGM answer (freeze per epoch, promote against held-out ground truth) would need a second, offline judge.
  3. The human gate at scale. needs-human is a policy on scopes/points. Per-tenant approvers, quorum, and expiry are host concerns to build on /api/approvals.
  4. Regulatory. A self-modifying production system is a substantial modification generator in EU AI Act terms; the event log is the evidence trail. Nothing here claims conformity.

Status (2026-08-28)

Implemented and tested: kernel guarantees (15 tests), both executors incl. interrupt/memory limits, judge gates/approval/rollback, collections contract on SQLite / Postgres (PGlite) / D1- and Durable-Object-shaped storage, object storage (S3, R2), node/fastify/cloudflare hosts, the system plugins (admin-api, agent-loop, audit, auth, automation, collections, http, judge, meta, orm, rbac, rpc, scheduler), createBaseline + createTenantPool, end-to-end prompt → judge → mount → restart → undo, and a real pnpm add git+…#tag&path: install of the built packages from a scratch clone. Not run by pnpm test: wrangler/workerd (Cloudflare pieces are tested against structural fakes) and a network Postgres (PGlite stands in), and the CLI/HTTP model drivers against live providers (SMS_LIVE_MODELS=1) or live buckets (SMS_LIVE_OBJECTS=1).

Roadmap: what the Linux kernel still has to teach us

The baseline already borrows the Linux module model (drivers, plugins, EXPORT_SYMBOL-style trust on keys). Linux has several other mechanisms for changing a running system safely that map directly onto the needs of self-modifying software. This doc records the mapping and the features we intend to build from it, so future work has a reference and a rationale.

Status legend: planned (agreed, not started) · later (worth doing, not scheduled) · rejected (with reason).

The mapping

Linux mechanismProblem it solves thereOur analog todayGap
Loadable modules, module_get refcountsLoad/unload code at runtime; refuse unload while depended onplugins, kernel-derived undoNo refcount: unloading a plugin whose provided key others hold
EXPORT_SYMBOL_GPL, module signing, lockdownGate symbols on a property of the consumer; a global “only signed code” modeminConsumerTrust, judgeNo global lockdown bit
Taint flagsPermanent provenance on every bug report (“out-of-tree module was loaded”)planned §1
Livepatch transition modelReplace a function under load; abortable; never half-patchedobservePoint({added, removed}) + derived undoNo sequencing/abort state machine — planned §2
eBPF verifier + per-program-type helpers + mapsUntrusted programs inside the kernel; whitelisted calls per attach type; state only via kernel-owned mapsjudge (runtime), Trust rank, collectionsRank is too coarse; no static pre-load pass — planned §3
Capabilities (CAP_*)Root split into discrete privilegesTrust = 'system' | 'agent'same as above
SeccompA process can only shrink its privilegesMonotonic trust for agent-authored plugins — folded into §3
cgroupsPer-subtree resource budgetsper-call executor limits only (QuickJS sliceMs/memoryLimitBytes, Node resourceLimits)later §4
NamespacesPer-process view of the systemkernel-per-tenantdone
LSM stackingEvery policy gets a veto on a canonical list of sensitive opsjudgejudge is a single LSM; the hook list is not published — later
Static keys / alternativesAtomic feature flags; capability-driven implementation selectiondriver composition at bootlater
Kprobes / tracepointsHook any function without author cooperation / declared hooksextension points (declared)rejected §5
Kconfig depends on/selectConfiguration as a satisfiable objectmanifest inject (hard) / optional (soft), gate rule plugin-injectpartial — no solver yet
sysfs/procfsOne introspection tree for tools, humans and programsplugin-admin-api (/api/state, /api/catalog), plugin-metadone in spirit
kexec / initramfsReboot into a new kernel or a minimal known-good statelater (“safe mode”: human-authored plugins only)
Stable userspace ABI, unstable internalsDecide which surface never breaks@sms/contracts, plugin-sdk, and every @sms/plugin-x/contract (definitions) vs. plugin roots (providers)contract subpaths done (2026-08-28, gate rule contract-surface); versioning policy still to write in releasing.md

Planned features (the 80% cut)

Three features give most of the value; each rides on state the kernel already tracks. Order: §1 → §3 → §2.

§1 Taint flags — planned, ~1 day

What. A sticky set of bits on the kernel, set for the kernel’s lifetime the first time something unusual happens:

FlagSet when
AGENT_AUTHOREDa plugin whose author trust is agent was loaded
JUDGE_OVERRIDDENa human approved something the judge rejected
TRUST_ESCALATEDany path granted a consumer more trust than its author had
LOAD_FORCEDa plugin was loaded despite a failed check (contract, verifier)
UNVERIFIEDa plugin loaded without a judge decision at all

The set is attached to every kernel error, every log line (packages/core/kernel/src/log.ts), and the admin-api status response.

Why. The first question in every incident with a self-modifying system is “did the agent do this, or did I?” Taint answers it on every failure report without anyone remembering to look. It also strengthens the judge tests: assert that no test path sets TRUST_ESCALATED.

Where. packages/core/kernel — a taint: Set<TaintFlag> on the kernel, set from the provide/contribute resolution path and from assertTrust; exported type in types.ts; surfaced by plugin-admin-api. No new package.

§3 Capability sets per extension point — planned, ~2 days

What. Augment the Trust rank with a set of named capabilities (db.read, db.write, model.complete, plugin.install, trust.grant, …) declared in @sms/contracts.

  • A provided key declares the capabilities a consumer needs (requires: ['db.write']).
  • A plugin’s capability set is derived from the points it contributes to (an http.route contributor gets db.read, model.complete; an admin.hook contributor also gets plugin.install) — the eBPF “helpers per program type” rule.
  • Monotonic: a plugin’s set is always a subset of its author’s set. An agent can write a plugin more restricted than itself, never less (seccomp rule).
  • minConsumerTrust: 'system' remains valid as shorthand for “the full set” — backward compatible.

Why. A rank forces “system vs not”. The interesting agent-authored plugins sit in between: may write rows, may not install plugins. Sets give that grain, and the judge’s unreachability tests become mechanical: no capability path from agent to plugin.install.

Where. @sms/contracts (capability names, requires on key metadata), kernel assertTrustassertCapabilities. Optional follow-up: a static pre-load pass (the eBPF verifier analog) that rejects a plugin source importing keys outside its set before the judge ever runs.

§2 Livepatch-style plugin transition — planned, ~2–3 days

What. Replacing plugin v1 with v2 becomes an explicit, abortable state machine:

active(v1) ──begin──▶ transitioning(v1→v2) ──complete──▶ active(v2)
                             │
                           abort
                             ▼
                          active(v1)
  • In-flight work pinned to v1 finishes on v1; new work takes v2.
  • “Safe point” = request boundary, signalled by the executor driver.
  • complete fires only when every pinned unit has reached a safe point; abort at any time returns to active(v1) using the kernel’s derived undo, so the system can never be half-patched.

Why. “The agent updated itself” is the central story, and it needs a swap that cannot strand the system between versions. We already own both halves (effect undo, observePoint added/removed); this only sequences them and adds a version pin per unit of work.

Where. Kernel (state + pinning); drivers/executor/* supply the safe-point signal; admin-api exposes the transition state and an abort. Builds on §1 (transitions taint on force) and §3 (v2’s capability set must be ⊆ v1’s author’s set).

Later

§4 cgroup-style budgets

Per-plugin / per-agent budgets (model tokens, wall time, rows written) enforced by the host, accounted in a hierarchy the judge can read. Real value, but needs metering in each driver — do after §1–§3.

Others

  • Publish the judge’s hook list (the LSM lesson: the canonical list of sensitive operations is the security model).
  • Module refcounts: refuse to unload a plugin while another holds its provided key.
  • Global lockdown bit: “agent-authored plugins must pass judge; human-authored may skip”.
  • Safe-mode boot (human-authored plugins only) and tenant-level kernel hot-swap (kexec).
  • Kconfig-style satisfiability for the plugin set.
  • Write the stable/unstable ABI policy in releasing.md (@sms/contracts never breaks; plugin-sdk internals may).

Rejected (for now)

§5 Kprobe-style undeclared hooks

Attaching to any plugin function without the plugin declaring an extension point. Useful for observability, but it undercuts the “declared points only” safety story that the judge’s unreachability tests rely on. Revisit only as an observation-only input to the judge, never as a way to alter behaviour.

Reading

  • eBPF verifier and helpers: Documentation/bpf/verifier.rst, include/uapi/linux/bpf.h
  • Livepatch consistency model: Documentation/livepatch/livepatch.rst
  • Taint flags: Documentation/admin-guide/tainted-kernels.rst
  • Capabilities: capabilities(7); seccomp: seccomp(2)
  • Positioning against the research thesis: research-positioning.md

Releasing

The baseline is private: no npm registry. Downstream repos install git tags; each tag points at a release commit (not on any branch) that carries built dist/ and package.jsons whose internal deps point back at the same tag.

Why this shape

  • pnpm add github:owner/repo#tag&path:/packages/x installs one subdirectory of a monorepo — but pnpm does not rewrite workspace:* ranges for git dependencies. So in the release commit every "@sms/kernel": "workspace:*" becomes "@sms/kernel": "github:owner/repo#v0.2.0&path:/packages/core/kernel". pnpm then resolves the whole @sms/* graph transitively, deduplicated, one Kernel class in the process.
  • Node refuses to type-strip .ts inside node_modules, so consumers need real .js + .d.ts: tsc -b emits dist/ per package (tsconfig.package.json → per-package tsconfig.build.json).
  • Development stays build-free: package exports list sms-sourcesrc/index.ts first. tsconfig.json (customConditions), vitest.config.ts (resolve.conditions) and the app scripts (--conditions=sms-source) enable it; consumers never see it (default condition → dist/).
  • main never carries build output (dist/ and *.tsbuildinfo are gitignored). Release commits do; they are reachable only through their tag, so no release/* branches exist.

Cutting a release: push a tag

pnpm check                          # no CI on main — the gate runs here first
git tag v0.2.0 && git push origin v0.2.0

That is the whole procedure. .github/workflows/cd.yml (the only workflow in the repo) runs pnpm check, builds, makes a detached release commit with rewritten package.jsons and committed dist/, moves the tag onto that commit, pushes it, and publishes a GitHub Release with the install line. The workflow pins Node 22.14 (newer 22.x changes .ts handling for the worker-thread executor).

Rules:

  • The tag must point at a commit on main with a clean workspace layout. CD refuses a tag whose commit is not on main (e.g. one that already points at a release commit).
  • Do not re-use a tag name after it has shipped; releases are lockstep (one version for every package).
  • Do not push tags from a local pnpm release --push. CD owns the tag: a locally-moved tag makes CD check out the release commit and fail on --frozen-lockfile. If that happens, the tag is still valid — create the GitHub Release by hand (gh release create vX.Y.Z).

Rehearsing locally

scripts/release.ts is what CD runs; you can run it without pushing to see what a release would contain:

pnpm release 0.2.0 --dry-run  # show what would be rewritten
pnpm release 0.2.0            # runs pnpm check, builds, makes a detached release commit, tags it locally
git tag -d v0.2.0                                   # discard the rehearsal
pnpm release 0.2.0 --repo other/fork   # for forks (default: parsed from `git remote get-url origin`)

What the script does: clean tree required → pnpm checkpnpm clean && pnpm buildpnpm check:pkg (publint + arethetypeswrong on the built packages, see docs/quality.md §6) → detach HEAD → for each non-private package: set version, rewrite workspace:* in dependencies/ peerDependencies to git+path specs, drop devDependencies and scripts, rewrite exports to dist only (every subpath kept — ./testkit, ./testing, ./node — just the sms-source condition dropped), git add -f dist → commit → annotated tag → switch back to your branch.

Verifying a release

mkdir /tmp/consumer && cd /tmp/consumer && pnpm init
pnpm add "github:owner/sms-baseline#v0.2.0&path:/packages/baseline" \
         "github:owner/sms-baseline#v0.2.0&path:/packages/drivers/store/sqlite" \
         "github:owner/sms-baseline#v0.2.0&path:/packages/drivers/executor/quickjs"
node -e "import('@sms/baseline').then(m => console.log(Object.keys(m).length, 'exports'))"

The same mechanics were validated with a git+file:// clone in this repo’s development (see the session notes in docs/research-positioning.md → “Status”).

Do not

  • Check out a release tag to develop on it (its package.jsons are not a valid workspace).
  • Commit dist/ on main.
  • Publish a package that imports a sibling driver; consumers must be able to install one driver alone.

Quality gate

pnpm check = typechecklintqualitykniptest:coverage. CD runs it before every release; there is no CI on main (private repo, limited Actions minutes), so run it locally before pushing. pnpm release adds check:pkg (§6) after the build. Benchmarks (pnpm bench, benchmarking.md) are deliberately not part of the gate. Each stage is described below with the reasoning, borrowed from projects that treat quality checks as executable specs rather than advice.

1. Typecheck — tsc --noEmit, strict + noUncheckedIndexedAccess + erasableSyntaxOnly

Unchanged. Types are the first spec.

2. Lint — Biome (biome.json)

Formatter + recommended rules, plus complexity limits in the spirit of ESLint’s complexity/max-params presets used by projects such as Node core and TypeScript-ESLint:

RuleLimitWhy
noExcessiveCognitiveComplexity25A function you cannot hold in your head cannot be reviewed or tested exhaustively.
noExcessiveNestedTestSuitesdefaultTests are specs; deep nesting hides which behaviour a case documents.
useConsistentArrayTypeT[]One spelling.

No function is currently grandfathered. If one must be, mark it inline with biome-ignore … grandfathered (score N, expires YYYY-MM-DD): the marker is the tech-debt list — split the function when you next touch it, and delete the marker. The date is enforced (§3, Expiry).

3. Structural rules — pnpm quality (scripts/quality.ts)

A dependency-free checker (TypeScript’s own parser, no build) — the same idea as dependency-cruiser / eslint-plugin-boundaries, but reading the layering straight out of CLAUDE.md so the rule and the doc cannot drift. Rules live in scripts/quality/rules.ts as pure functions with their own tests in scripts/test/, so changing a rule is itself TDD.

Rings (layering). Packages are assigned a ring from their path (scripts/quality/layers.ts is the model; docs/dependency-graph.md, generated by pnpm graph, is the picture — rule graph-doc fails when it is stale):

ring 0  kernel                       imports nothing
ring 1  plugin-sdk | contracts       two siblings over the kernel: what agent code sees | the waist (Database · Store · Host ·
                                     ModelService · ObjectStore, kernel types only); neither imports the other
ring 2  drivers    | plugins         two columns on top of contracts; neither imports the other
ring 3  baseline                     composition: picks plugins, exposes createBaseline / createTenantPool
ring 4  examples/*                   composition roots that also pick drivers

A runtime import may only point at the same ring or below. Additionally:

  • kernel, plugin-sdk, contracts and every plugin import no platform code at all (node:*, fastify, @anthropic-ai/*, …) — a plugin must run wherever the kernel runs (Node, Workers, tests).
  • Drivers never import each other, except host-fastify → host-node, host-cloudflare → store-do (composition-level, from CLAUDE.md) and the shared SQL helper store-sql.
  • Plugins import each other only through @sms/plugin-<x>/contract (below). LAYERING_EXCEPTIONS (dated, per package) exists for grandfathering and is currently empty — keep it that way.
  • import type and test files are ignored — types are free, and tests may compose anything.

Plugin contracts (contract-surface). Every plugin ships src/contract.ts (exported as ./contract): keys as export const X_KEY = 'x', point names, service and item types, validators, pure helpers. Nothing reachable from it through relative imports may be src/index.ts or declare a manifest: — a contract has no provider in it, so depending on one never drags a plugin body along (Cordis: “consumers depend on service definitions, never providers”; Linux: modules link against exported symbols, not each other’s source).

Manifest honesty (plugin-inject). The manifest is the dependency declaration the kernel reconciles on, and there are two ways around it that the kernel cannot see: importing another plugin’s contract at runtime, and ctx.kernel.getValue(key). The rule reads every inject/optional array in the plugin (string literals or *_KEY identifiers), and fails when a runtime-imported plugin’s keys appear in neither, or when a getValue() argument is undeclared. Manifests it cannot read statically (spreads, computed keys) are skipped.

Plugin DAG (plugin-cycle). The plugin-to-plugin import graph (runtime and type) must be acyclic.

Package metadata (deps, build-refs). package.json must tell the same story as the imports: every @sms/* in dependencies/peerDependencies obeys the rings (at package level — a plugin may depend on a plugin package; the /contract restriction is on import sites), is imported by src/, and everything src/ imports is declared; a workspace dependency only tests use belongs in devDependencies. Each package’s tsconfig.build.json references must equal its @sms/* dependencies, and the root tsconfig.build.json must list every buildable package.

File length (file-length): ≤ 400 non-blank lines per source file. LIMITS.fileLength.allow is empty; a grandfathered ceiling added there carries an expires date — lower the number as the file shrinks, never raise it.

Parameters (max-params): ≤ 4 per function/method/constructor. Beyond that, pass an options object (the codebase already does this everywhere — createBaseline(opts), createJudgePlugin(opts)).

Tests present (tests-present): every package with src/ ships test/*.test.ts. Exemptions (LIMITS.testsExempt) are type-only/helper packages (store-sql) and the sample apps under examples/. Model drivers (drivers/model/*) ship the live contract test (SMS_LIVE_MODELS=1) and are only excluded from coverage, since without a CLI login nothing in them executes.

Expiry (expired-exception): every grandfathered exception is a promise with a date, not configuration — LIMITS.fileLength.allow entries and LAYERING_EXCEPTIONS carry expires: 'YYYY-MM-DD', and each biome-ignore … grandfathered marker must say expires YYYY-MM-DD (a marker without a date fails). Once the date passes the gate fails until the debt is paid or the date is extended, deliberately, in a reviewed commit. Borrowed from Prisma’s expiring coverage exceptions.

Output is file:line [rule] message, exit 1 on any violation.

4. Dead code and dependencies — pnpm knip (knip.json)

knip walks the workspace graph from each package’s src/index.ts (and the app/example entrypoints, scripts/, bench/) and reports unused files, exports, dependencies and unlisted imports. Its first run here found four dead workspace dependencies. Exceptions are per-workspace in knip.json: the driver test packages list @sms/plugin-collections/@sms/plugin-http only so the shared contract test resolves; publint/attw are invoked via pnpm exec from scripts/check-pkg.ts. Add to ignore* only with a comment-worthy reason; prefer deleting the thing.

5. Tests and coverage — pnpm test:coverage

Vitest with V8 coverage. Tests are the spec of the system: they describe behaviour, change rarely, and the judge’s unreachability tests are load-bearing for safety (see CLAUDE.md).

TDD is enforced structurally, not by ceremony: a package cannot exist without tests (rule above), and coverage cannot go down (below). The habit that satisfies both is to write the failing test first.

Coverage ratchet. SQLite reaches 100% branch coverage by treating every uncovered line as a defect and never letting the number regress. We take the mechanism, not the number: vitest.config.ts holds thresholds with autoUpdate: true. A run that beats the thresholds rewrites them upward in the config (commit that change); a run below them fails. Never lower a threshold by hand — add a test. Current floor: ~93% lines, ~90% functions, ~89% statements, ~78% branches; the goal is to walk it toward 100.

The ratchet was re-baselined once, on 2026-08-24, when moving from Vitest 2 to 4. Vitest 2’s V8 remapping was non-deterministic — the same tree reported 1037 or 1038 total branches run to run, so a threshold sitting at an exact boundary failed spuriously — and Vitest 4’s AST-aware remapping counts statements and functions on a finer grain (arrow callbacks, per-statement). The numbers changed because the ruler changed; the measurement is now identical across runs, which is what makes a ratchet trustworthy.

Excluded from coverage, each for a stated reason (coverage.exclude): code running in a worker thread or isolate that V8 cannot observe (executor-node/src/worker.ts, plugin-sdk/src/runtime.ts), process entrypoints (main.ts, demo.ts), the credential-bound model adapters, and type-only modules. The HTML report is written to coverage/ (git-ignored) — open coverage/index.html to find the uncovered branches to test next.

6. Package shape — pnpm check:pkg (release only)

After pnpm build, scripts/check-pkg.ts runs publint --strict and arethetypeswrong --pack on every publishable package: package.json exports/types must match what is in dist/, and the packed tarball must resolve types under Node’s ESM resolution the way a consumer sees it (our custom sms-source condition is exactly the kind of thing attw catches when it leaks). It also asserts (scripts/release-exports.ts) that every subpath in the workspace exports survives the release rewrite with import/types present in dist/ — v0.1.1 shipped without @sms/baseline/testkit because release.ts replaced the map instead of rewriting it. pnpm release runs it right after the build; run pnpm build && pnpm check:pkg by hand when changing a package’s exports. It is not in pnpm check because dev has no build step.

Adding a package

Use .claude/skills/new-plugin or .claude/skills/new-driver (they scaffold the shape that passes every rule on the first run), or copy the package shape from CLAUDE.md, add test/<name>.test.ts before src/, run pnpm graph, then pnpm check. The ring is read from the path; if a new kind of package does not fit, extend layerOf in scripts/quality/layers.ts — with a test.

Benchmarks (local only)

pnpm bench runs micro-benchmarks under bench/*.bench.ts with Vitest’s bench (tinybench). They are a local signal, not a gate: they are not part of pnpm check and there is no CI on main (private repo). Shared-runner timings are too noisy to threshold anyway — the projects that gate on perf (Prisma, TanStack Router) do it with CPU-simulation services; everyone else (Node, Deno, Hono, Effect) treats benchmarks as informational. We do the same.

pnpm bench                  # run everything, print the tables
pnpm bench bench/kernel     # one file
pnpm bench:baseline         # write bench/.baseline.json (git-ignored: numbers are machine-specific)
pnpm bench:compare          # re-run and print the delta against the saved baseline

Workflow for a change that might affect performance: pnpm bench:baseline on the base commit, make the change, pnpm bench:compare. Read the mean/p99 columns and the rme (relative margin of error): a delta inside the rme of either run is noise.

What is measured

FileSurfaceWorkloads
kernel.bench.tsKernel reconciler, in-memory backendsinstall N-plugin dependency chains in order and reversed (every install re-settles); disable/enable a root provider under 99 dependents; 200 contributors with 0 and 5 observePoint observers; contributions() reads; dispose() undo of 200 fibers
executors.bench.tsNodeExecutor (worker thread) vs QuickJSExecutor (WASM)mount + dispose; 100 tool-call round-trips agent → host → agent
stores.bench.tsstore-sqlite, store-postgres (PGlite), store-do (fake SqlStorage)open/close; 100 log appends + all(); 50 blob puts (dedup) + gets; collections boot + CRUD through the plugin (bootCollections from the contract test)
judge.bench.tscreateJudgePlugin gate pipelineboot cost (reference); a submission rejected by a static gate; a full submission through the load gate (throwaway sandbox) to mount
host-node.bench.tscreateNodeHost over loopbackGET; POST with a 1 KiB body

Benchmarks live in a top-level bench/ directory, outside the package layering on purpose: they import every layer at once, which no package may do. scripts/quality.ts still applies file-length and parameter limits to them; tests-present and layering do not apply (no package.json, app layer).

Adding one

Copy the shape of the nearest file: describe per surface, bench per workload, do all setup inside the bench callback unless it is genuinely shared (then a top-level await plus afterAll teardown, as host-node.bench.ts does with its server). Prefer a workload with a stated N (x100) over a single call, so the number is above the timer’s resolution. Reuse test helpers by relative import (bootCollections, fakeSqlStorage) rather than duplicating boot code.

Known numbers worth watching

From the first run (Apple Silicon, Node 22): installing a 100-plugin chain costs ~40× a 10-plugin chain (settle is superlinear); a full judge submission is dominated by the load gate’s sandbox spin-up (tens of ms) versus microseconds for the static gates; QuickJS mounts an order of magnitude faster than a worker thread but its tool-call round-trip is slower per call. These are observations, not targets.

Vitest 4’s --outputJson/--compare are removed in Vitest 5 (replaced by an in-file bench.compare API); bench:baseline/bench:compare will need rewriting on that upgrade.

The documentation site

The docs you are reading are published as an mdBook site on Cloudflare Pages, deployed by hand from a checkout. The book has two halves:

  • Prose — the hand-written docs/*.md in this repo, plus the root README.md as the landing page.
  • API reference — generated from the package sources by TypeDoc at build time, never committed.

One-time setup

mdBook is a Rust binary, so pnpm install does not bring it in. Install it once:

cargo install mdbook          # or: brew install mdbook
mdbook --version              # 0.5 or newer

TypeDoc is a dev dependency, so nothing else is needed.

Working on the docs

pnpm docs:dev     # stage + build + serve on http://localhost:3000, opens a browser
pnpm docs:build   # stage + build into .docs-build/book

scripts/docs.ts stages everything into .docs-build/src and then runs mdBook over it (book.toml points src there). .docs-build/ is generated and gitignored — never edit anything under it; your changes are wiped on the next build. Because the sources are staged copies, pnpm docs:dev does not hot-reload edits to docs/*.md: re-run it.

Adding a page

  1. Write docs/your-page.md.
  2. Add it to docs/SUMMARY.md — that file is the book’s table of contents and the sidebar order. A page that is not in SUMMARY.md is not in the book.
  3. Add a row to the table in docs/README.md, which stays the index for people reading on GitHub.

Two entries in SUMMARY.md deliberately do not resolve when browsing docs/ on GitHub: index.md (the root README, staged under that name) and everything under api/ (generated). They resolve in the built book.

The API reference needs no maintenance — it follows the src/index.ts of every package under packages/. TypeDoc names modules after their path, so scripts/docs.ts retitles each page with the package name from its package.json.

Deployment

The docs are not deployed by CI (the only workflow is the release one, cd.yml); deploy from your machine (needs wrangler 4.x and wrangler login, or CLOUDFLARE_API_TOKEN + CLOUDFLARE_ACCOUNT_ID in the environment; Pages project sms-docs):

pnpm docs:build
wrangler pages deploy .docs-build/book --project-name=sms-docs --branch=main                          # production
wrangler pages deploy .docs-build/book --project-name=sms-docs --branch="$(git branch --show-current)" # preview

The publish-docs skill (.claude/skills/publish-docs) walks through the same steps plus the one-time Pages project setup and Cloudflare Access restrictions.

The docs build is deliberately not part of pnpm check: it needs a binary that is not in the lockfile, and a broken sidebar should not block a release.

API reference

Generated from the package sources by TypeDoc.

@sms/baseline

Interfaces

Baseline

Defined in: packages/baseline/src/create-baseline.ts:70

Properties

handle
handle: RequestHandler;

Defined in: packages/baseline/src/create-baseline.ts:75

http.handle bound — hand it to a Host driver.

http
http: HttpService;

Defined in: packages/baseline/src/create-baseline.ts:73

kernel
kernel: Kernel;

Defined in: packages/baseline/src/create-baseline.ts:71

store
store: Store;

Defined in: packages/baseline/src/create-baseline.ts:72

Methods

close()
close(): Promise<void>;

Defined in: packages/baseline/src/create-baseline.ts:78

Returns

Promise<void>

tick()
tick(now?): Promise<TickResult>;

Defined in: packages/baseline/src/create-baseline.ts:77

Run due scheduled jobs (@sms/plugin-scheduler). The host decides the cadence: cron trigger, interval…

Parameters
ParameterType
now?number
Returns

Promise<TickResult>


BaselineOptions

Defined in: packages/baseline/src/create-baseline.ts:23

Properties

admin?
optional admin?: Omit<AdminApiOptions, "token">;

Defined in: packages/baseline/src/create-baseline.ts:66

Admin API options beyond the token (prefix).

adminToken?
optional adminToken?: string;

Defined in: packages/baseline/src/create-baseline.ts:64

Bearer token for mutating admin routes. Omit to leave them open (local dev only).

auth?
optional auth?: false | AuthOptions;

Defined in: packages/baseline/src/create-baseline.ts:37

Users, sessions and permissions (@sms/plugin-auth + @sms/plugin-rbac, wired into the ORM’s guard). Default: installed, no users until bootstrapAdmin or identity-admin.create. false = no auth and no rbac: every ORM request runs as sudo — local development only.

autoApprove?
optional autoApprove?: boolean;

Defined in: packages/baseline/src/create-baseline.ts:62

Skip human approval entirely (tests / unattended). Shorthand for judge.autoApprove.

executor
executor: Executor;

Defined in: packages/baseline/src/create-baseline.ts:29

Runs agent-written code. @sms/executor-node (worker threads) or @sms/executor-quickjs (WASM interpreter).

identity?
optional identity?: string;

Defined in: packages/baseline/src/create-baseline.ts:48

First line of the agent’s system prompt.

judge?
optional judge?: Omit<JudgeOptions, "executor">;

Defined in: packages/baseline/src/create-baseline.ts:60

Judge policy. Default: scope net and the route / schedule points need a human (an agent plugin that answers HTTP or runs unattended is not metadata); nothing auto-approved. Pass your own sensitivePoints to replace the default list.

logger?
optional logger?: (...args) => void;

Defined in: packages/baseline/src/create-baseline.ts:67

Parameters
ParameterType
argsunknown[]
Returns

void

meta?
optional meta?: boolean;

Defined in: packages/baseline/src/create-baseline.ts:44

@sms/plugin-meta: headless views / actions / menus (view, action, menu points). Off by default.

model
model: ModelService;

Defined in: packages/baseline/src/create-baseline.ts:31

The language model behind agent.chat().

name?
optional name?: string;

Defined in: packages/baseline/src/create-baseline.ts:25

Kernel name (shows up in logs and /api/state).

plugins?
optional plugins?: SystemPlugin[];

Defined in: packages/baseline/src/create-baseline.ts:46

Your application’s own system-trust plugins (collections, routes, tools, prompts, gates, invariants…).

rpc?
optional rpc?: 
  | boolean
| Omit<RpcOptions, "contextOf">;

Defined in: packages/baseline/src/create-baseline.ts:42

@sms/plugin-rpc: batched JSON-RPC over the ORM at /api/rpc (+ /api/rpc/meta), sharing the ORM’s caller resolution. Off by default; true or options (prefix).

sessionStore?
optional sessionStore?: (kernel) => AgentSessionStore;

Defined in: packages/baseline/src/create-baseline.ts:54

Rehydrates chat sessions the agent loop does not hold in memory (fresh process, evicted Durable Object). A factory because the loop installs before your plugins: load() runs at chat time, after settle(), so it may read any key from the kernel it is given.

Parameters
ParameterType
kernelKernel
Returns

AgentSessionStore

store
store: Store;

Defined in: packages/baseline/src/create-baseline.ts:27

Persistence driver. The baseline owns it and closes it on close().


TenantPool

Defined in: packages/baseline/src/tenant-pool.ts:17

Properties

handle
handle: RequestHandler;

Defined in: packages/baseline/src/tenant-pool.ts:18

Methods

close()
close(): Promise<void>;

Defined in: packages/baseline/src/tenant-pool.ts:26

Returns

Promise<void>

evict()
evict(tenantId): Promise<void>;

Defined in: packages/baseline/src/tenant-pool.ts:25

Close one tenant’s kernel (it will boot again on the next request).

Parameters
ParameterType
tenantIdstring
Returns

Promise<void>

get()
get(tenantId): Promise<Baseline>;

Defined in: packages/baseline/src/tenant-pool.ts:20

Get (or boot) a tenant’s kernel.

Parameters
ParameterType
tenantIdstring
Returns

Promise<Baseline>

tenants()
tenants(): string[];

Defined in: packages/baseline/src/tenant-pool.ts:21

Returns

string[]

tick()
tick(now?): Promise<Record<string, TickResult>>;

Defined in: packages/baseline/src/tenant-pool.ts:23

Run due scheduled jobs on every booted tenant (idle tenants are not woken).

Parameters
ParameterType
now?number
Returns

Promise<Record<string, TickResult>>


TenantPoolOptions

Defined in: packages/baseline/src/tenant-pool.ts:6

Properties

idleMs?
optional idleMs?: number;

Defined in: packages/baseline/src/tenant-pool.ts:14

Close kernels idle for this long (ms). Default: never.

onMissing?
optional onMissing?: (request) => Response | Promise<Response>;

Defined in: packages/baseline/src/tenant-pool.ts:12

Response for requests with no tenant. Default: 400.

Parameters
ParameterType
requestRequest
Returns

Response | Promise<Response>

resolve
resolve: TenantResolver;

Defined in: packages/baseline/src/tenant-pool.ts:8

Which tenant a request belongs to.

tenant
tenant: (tenantId) => 
  | BaselineOptions
| Promise<BaselineOptions>;

Defined in: packages/baseline/src/tenant-pool.ts:10

Build the options for a tenant’s kernel: its own store (file / schema / DO), plugins, model…

Parameters
ParameterType
tenantIdstring
Returns

| BaselineOptions | Promise<BaselineOptions>

Variables

DEFAULT_SENSITIVE_POINTS

const DEFAULT_SENSITIVE_POINTS: string[];

Defined in: packages/baseline/src/create-baseline.ts:21

Extension points whose agent contributions need a human by default.

Functions

createBaseline()

function createBaseline(opts): Promise<Baseline>;

Defined in: packages/baseline/src/create-baseline.ts:114

Compose one kernel: database key → http → collections → scheduler → auth → rbac → orm → [meta, rpc] → judge → model → agent loop → admin api → your plugins, then settle and restore agent plugins from the log. Throws if any system plugin is not active.

Parameters

ParameterType
optsBaselineOptions

Returns

Promise<Baseline>


createTenantPool()

function createTenantPool(opts): TenantPool;

Defined in: packages/baseline/src/tenant-pool.ts:33

Kernel-per-tenant. The kernel itself is single-tenant by design (one log, one plugin set, one database); tenancy is a host concern. On Cloudflare a Durable Object plays this role instead.

Parameters

ParameterType
optsTenantPoolOptions

Returns

TenantPool

References

Access

Re-exports Access


ACCESS_POINT

Re-exports ACCESS_POINT


ACTION_POINT

Re-exports ACTION_POINT


ActionSpec

Re-exports ActionSpec


Activate

Re-exports Activate


ADMIN_AUTHORIZER_POINT

Re-exports ADMIN_AUTHORIZER_POINT


ADMIN_ROUTES

Re-exports ADMIN_ROUTES


AdminApiOptions

Re-exports AdminApiOptions


AdminAuthorizer

Re-exports AdminAuthorizer


AGENT_KEY

Re-exports AGENT_KEY


AgentEvent

Re-exports AgentEvent


AgentLoopOptions

Re-exports AgentLoopOptions


AgentService

Re-exports AgentService


AgentSessionStore

Re-exports AgentSessionStore


AppliedEffect

Re-exports AppliedEffect


applyOps

Re-exports applyOps


assertObjectKey

Re-exports assertObjectKey


assertTenantId

Re-exports assertTenantId


assertTrust

Re-exports assertTrust


AsyncQueue

Re-exports AsyncQueue


AuthOptions

Re-exports AuthOptions


BlobStore

Re-exports BlobStore


bodyOf

Re-exports bodyOf


bodyToBytes

Re-exports bodyToBytes


buildMenuTree

Re-exports buildMenuTree


CallRequest

Re-exports CallRequest


Cap

Re-exports Cap


catalog

Re-exports catalog


Channel

Re-exports Channel


ChatResult

Re-exports ChatResult


ChatStep

Re-exports ChatStep


cloneNode

Re-exports cloneNode


COLLECTION_FIELD_POINT

Re-exports COLLECTION_FIELD_POINT


COLLECTION_HOOK_POINT

Re-exports COLLECTION_HOOK_POINT


COLLECTION_POINT

Re-exports COLLECTION_POINT


CollectionFieldContribution

Re-exports CollectionFieldContribution


CollectionHook

Re-exports CollectionHook


COLLECTIONS_KEY

Re-exports COLLECTIONS_KEY


CollectionSchema

Re-exports CollectionSchema


collectionsPlugin

Re-exports collectionsPlugin


CollectionsService

Re-exports CollectionsService


Command

Re-exports Command


CompiledView

Re-exports CompiledView


compileFromBase

Re-exports compileFromBase


ComputedField

Re-exports ComputedField


ComputedReturns

Re-exports ComputedReturns


Contribution

Re-exports Contribution


conversationKey

Re-exports conversationKey


cookieValue

Re-exports cookieValue


createAdminApiPlugin

Re-exports createAdminApiPlugin


createAgentLoopPlugin

Re-exports createAgentLoopPlugin


createAuthPlugin

Re-exports createAuthPlugin


createChannel

Re-exports createChannel


createJudgePlugin

Re-exports createJudgePlugin


createMemoryObjectStore

Re-exports createMemoryObjectStore


createMetaService

Re-exports createMetaService


createModelPlugin

Re-exports createModelPlugin


createOrmPlugin

Re-exports createOrmPlugin


createPluginRuntime

Re-exports createPluginRuntime


createReasoningCache

Re-exports createReasoningCache


createRpcPlugin

Re-exports createRpcPlugin


createScriptedModel

Re-exports createScriptedModel


createSessionModel

Re-exports createSessionModel


createSqlStore

Re-exports createSqlStore


Database

Re-exports Database


DATABASE_KEY

Re-exports DATABASE_KEY


deferred

Re-exports deferred


Deferred

Re-exports Deferred


Dialect

Re-exports Dialect


Domain

Re-exports Domain


DomainLeaf

Re-exports DomainLeaf


DomainOp

Re-exports DomainOp


DSL_PROMPT

Re-exports DSL_PROMPT


EffectKind

Re-exports EffectKind


ErrorBody

Re-exports ErrorBody


errorJson

Re-exports errorJson


EventLog

Re-exports EventLog


eventsOf

Re-exports eventsOf


Executor

Re-exports Executor


ExecutorInstance

Re-exports ExecutorInstance


expandGroups

Re-exports expandGroups


ExtensionPointMeta

Re-exports ExtensionPointMeta


FiberState

Re-exports FiberState


FiberView

Re-exports FiberView


Field

Re-exports Field


FieldBase

Re-exports FieldBase


FieldKind

Re-exports FieldKind


FieldSpec

Re-exports FieldSpec


FieldType

Re-exports FieldType


findNode

Re-exports findNode


firstToolUseId

Re-exports firstToolUseId


FN_MARKER

Re-exports FN_MARKER


foldTarget

Re-exports foldTarget


Gate

Re-exports Gate


GATE_POINT

Re-exports GATE_POINT


GateContext

Re-exports GateContext


GateResult

Re-exports GateResult


Group

Re-exports Group


GROUP_POINT

Re-exports GROUP_POINT


GroupRow

Re-exports GroupRow


groupsOf

Re-exports groupsOf


hashPassword

Re-exports hashPassword


HOOK_POINT

Re-exports HOOK_POINT


HookEvent

Re-exports HookEvent


HookPayload

Re-exports HookPayload


Host

Re-exports Host


HostBridge

Re-exports HostBridge


HostServer

Re-exports HostServer


html

Re-exports html


HTTP_KEY

Re-exports HTTP_KEY


HttpError

Re-exports HttpError


httpErrorOf

Re-exports httpErrorOf


httpPlugin

Re-exports httpPlugin


HttpService

Re-exports HttpService


IDENTITY_ADMIN_KEY

Re-exports IDENTITY_ADMIN_KEY


IDENTITY_KEY

Re-exports IDENTITY_KEY


IdentityAdminService

Re-exports IdentityAdminService


IdentityService

Re-exports IdentityService


Invariant

Re-exports Invariant


INVARIANT_POINT

Re-exports INVARIANT_POINT


json

Re-exports json


JUDGE_KEY

Re-exports JUDGE_KEY


JudgeOptions

Re-exports JudgeOptions


JudgeService

Re-exports JudgeService


Kernel

Re-exports Kernel


KernelApi

Re-exports KernelApi


KernelError

Re-exports KernelError


KernelErrorCode

Re-exports KernelErrorCode


KernelEvent

Re-exports KernelEvent


KernelOptions

Re-exports KernelOptions


KeyMeta

Re-exports KeyMeta


KeyObserver

Re-exports KeyObserver


KINDS

Re-exports KINDS


listKeys

Re-exports listKeys


ListObjectsOptions

Re-exports ListObjectsOptions


lowerKeys

Re-exports lowerKeys


Many2manyField

Re-exports Many2manyField


Many2oneField

Re-exports Many2oneField


matchPath

Re-exports matchPath


MemoryBlobStore

Re-exports MemoryBlobStore


MemoryEventLog

Re-exports MemoryEventLog


Re-exports MENU_POINT


Re-exports MenuNode


Re-exports MenuSpec


META_KEY

Re-exports META_KEY


metaPlugin

Re-exports metaPlugin


MetaService

Re-exports MetaService


METHOD_POINT

Re-exports METHOD_POINT


MethodEnv

Re-exports MethodEnv


MODEL_FIELD_POINT

Re-exports MODEL_FIELD_POINT


MODEL_KEY

Re-exports MODEL_KEY


MODEL_POINT

Re-exports MODEL_POINT


ModelContent

Re-exports ModelContent


ModelEvent

Re-exports ModelEvent


ModelFieldContribution

Re-exports ModelFieldContribution


ModelHook

Re-exports ModelHook


ModelMessage

Re-exports ModelMessage


ModelMethod

Re-exports ModelMethod


ModelOnchange

Re-exports ModelOnchange


ModelRequest

Re-exports ModelRequest


ModelResponse

Re-exports ModelResponse


ModelService

Re-exports ModelService


ModelSpec

Re-exports ModelSpec


ModelTool

Re-exports ModelTool


MountAuthorization

Re-exports MountAuthorization


ObjectBody

Re-exports ObjectBody


objectContent

Re-exports objectContent


ObjectContent

Re-exports ObjectContent


ObjectList

Re-exports ObjectList


ObjectMeta

Re-exports ObjectMeta


OBJECTS_KEY

Re-exports OBJECTS_KEY


ObjectStore

Re-exports ObjectStore


ONCHANGE_POINT

Re-exports ONCHANGE_POINT


One2manyField

Re-exports One2manyField


Op

Re-exports Op


OpContext

Re-exports OpContext


OPS

Re-exports OPS


orDomains

Re-exports orDomains


ORM_KEY

Re-exports ORM_KEY


OrmError

Re-exports OrmError


OrmErrorKind

Re-exports OrmErrorKind


OrmEvent

Re-exports OrmEvent


OrmEventPayload

Re-exports OrmEventPayload


OrmGuard

Re-exports OrmGuard


OrmListener

Re-exports OrmListener


OrmOptions

Re-exports OrmOptions


ormPlugin

Re-exports ormPlugin


OrmService

Re-exports OrmService


parseCall

Re-exports parseCall


parseSelector

Re-exports parseSelector


parseToolArgs

Re-exports parseToolArgs


PendingApproval

Re-exports PendingApproval


pickBase

Re-exports pickBase


PluginBundle

Re-exports PluginBundle


PluginContext

Re-exports PluginContext


PluginManifest

Re-exports PluginManifest


PluginModule

Re-exports PluginModule


PluginRuntime

Re-exports PluginRuntime


PointObserver

Re-exports PointObserver


PROMPT_POINT

Re-exports PROMPT_POINT


PromptSection

Re-exports PromptSection


PutObjectOptions

Re-exports PutObjectOptions


Query

Re-exports Query


RBAC_ADMIN_KEY

Re-exports RBAC_ADMIN_KEY


RBAC_KEY

Re-exports RBAC_KEY


RbacAdminService

Re-exports RbacAdminService


rbacPlugin

Re-exports rbacPlugin


RbacService

Re-exports RbacService


ReadGroupRequest

Re-exports ReadGroupRequest


ReadSpec

Re-exports ReadSpec


Rec

Re-exports Rec


Record_

Re-exports Record_


RelatedField

Re-exports RelatedField


replayPrompt

Re-exports replayPrompt


RequestHandler

Re-exports RequestHandler


resolveActivate

Re-exports resolveActivate


Rights

Re-exports Rights


rightsOf

Re-exports rightsOf


Route

Re-exports Route


ROUTE_POINT

Re-exports ROUTE_POINT


RouteRequest

Re-exports RouteRequest


RouteResult

Re-exports RouteResult


RPC_METHODS

Re-exports RPC_METHODS


RpcCall

Re-exports RpcCall


RpcEnv

Re-exports RpcEnv


RpcMessage

Re-exports RpcMessage


RpcMethod

Re-exports RpcMethod


RpcOptions

Re-exports RpcOptions


rpcPlugin

Re-exports rpcPlugin


RpcResult

Re-exports RpcResult


Rule

Re-exports Rule


RULE_POINT

Re-exports RULE_POINT


runOne

Re-exports runOne


ScalarField

Re-exports ScalarField


ScalarKind

Re-exports ScalarKind


Schedule

Re-exports Schedule


SCHEDULE_POINT

Re-exports SCHEDULE_POINT


ScheduledJob

Re-exports ScheduledJob


SCHEDULER_KEY

Re-exports SCHEDULER_KEY


schedulerPlugin

Re-exports schedulerPlugin


SchedulerService

Re-exports SchedulerService


SearchOptions

Re-exports SearchOptions


SearchReadRequest

Re-exports SearchReadRequest


SelectionField

Re-exports SelectionField


serializeCookie

Re-exports serializeCookie


Session

Re-exports Session


Re-exports SESSION_COOKIE


SessionBackend

Re-exports SessionBackend


SessionBridge

Re-exports SessionBridge


SessionBridgeOptions

Re-exports SessionBridgeOptions


sha256

Re-exports sha256


sqlDialect

Re-exports sqlDialect


sse

Re-exports sse


Store

Re-exports Store


streamOf

Re-exports streamOf


SubdomainOptions

Re-exports SubdomainOptions


Subject

Re-exports Subject


sudo

Re-exports sudo


SystemPlugin

Re-exports SystemPlugin


TargetEntry

Re-exports TargetEntry


tenantFromHeader

Re-exports tenantFromHeader


tenantFromSubdomain

Re-exports tenantFromSubdomain


TenantResolver

Re-exports TenantResolver


text

Re-exports text


TickResult

Re-exports TickResult


toJson

Re-exports toJson


tokenOf

Re-exports tokenOf


Tool

Re-exports Tool


TOOL_POINT

Re-exports TOOL_POINT


ToolCallResult

Re-exports ToolCallResult


toolSignature

Re-exports toolSignature


toResponse

Re-exports toResponse


transcript

Re-exports transcript


Trust

Re-exports Trust


TRUST_RANK

Re-exports TRUST_RANK


unmarshal

Re-exports unmarshal


User

Re-exports User


validateAccess

Re-exports validateAccess


validateAction

Re-exports validateAction


validateField

Re-exports validateField


validateGroup

Re-exports validateGroup


validateMenu

Re-exports validateMenu


validateModel

Re-exports validateModel


validateModelField

Re-exports validateModelField


validateModelFieldSpec

Renames and re-exports validateField


validateRoute

Re-exports validateRoute


validateRule

Re-exports validateRule


validateSchedule

Re-exports validateSchedule


validateSchema

Re-exports validateSchema


validateView

Re-exports validateView


Values

Re-exports Values


Verdict

Re-exports Verdict


VerdictStatus

Re-exports VerdictStatus


verifyPassword

Re-exports verifyPassword


VIEW_POINT

Re-exports VIEW_POINT


ViewKind

Re-exports ViewKind


ViewNode

Re-exports ViewNode


ViewOp

Re-exports ViewOp


ViewSpec

Re-exports ViewSpec

@sms/contracts

Classes

AsyncQueue

Defined in: packages/core/contracts/src/model-session.ts:43

Push-based async iterable (a queue), e.g. as an SDK’s streaming prompt input.

Type Parameters

Type Parameter
T

Implements

  • AsyncIterable<T>

Constructors

Constructor
new AsyncQueue<T>(): AsyncQueue<T>;
Returns

AsyncQueue<T>

Methods

[asyncIterator]()
asyncIterator: AsyncIterator<T>;

Defined in: packages/core/contracts/src/model-session.ts:56

Returns

AsyncIterator<T>

Implementation of
AsyncIterable.[asyncIterator]
close()
close(): void;

Defined in: packages/core/contracts/src/model-session.ts:52

Returns

void

push()
push(v): void;

Defined in: packages/core/contracts/src/model-session.ts:47

Parameters
ParameterType
vT
Returns

void


SessionBridge

Defined in: packages/core/contracts/src/model-session.ts:91

Constructors

Constructor
new SessionBridge(make, opts?): SessionBridge;

Defined in: packages/core/contracts/src/model-session.ts:112

Parameters
ParameterType
make(bridge) => SessionBackend
optsSessionBridgeOptions
Returns

SessionBridge

Properties

historyLength
historyLength: number = 0;

Defined in: packages/core/contracts/src/model-session.ts:110

Length of the loop history at the last complete(); a shorter one means a reset.

Methods

close()
close(): void;

Defined in: packages/core/contracts/src/model-session.ts:265

Returns

void

complete()
complete(req): Promise<ModelResponse>;

Defined in: packages/core/contracts/src/model-session.ts:213

Parameters
ParameterType
reqModelRequest
Returns

Promise<ModelResponse>

onError()
onError(err): void;

Defined in: packages/core/contracts/src/model-session.ts:164

The SDK stream failed; rejects the in-flight complete() and every blocked tool handler.

Parameters
ParameterType
errunknown
Returns

void

onText()
onText(text): void;

Defined in: packages/core/contracts/src/model-session.ts:124

Assistant text produced by the SDK.

Parameters
ParameterType
textstring
Returns

void

onToolUse()
onToolUse(
   id, 
   name, 
   input
): void;

Defined in: packages/core/contracts/src/model-session.ts:129

The SDK announced a tool call (optional — toolCall synthesises one if it was not announced).

Parameters
ParameterType
idstring
namestring
inputunknown
Returns

void

onTurnEnd()
onTurnEnd(error?): void;

Defined in: packages/core/contracts/src/model-session.ts:158

The SDK finished its turn; error becomes a trailing text block.

Parameters
ParameterType
error?string
Returns

void

toolCall()
toolCall(name, input): Promise<ToolCallResult>;

Defined in: packages/core/contracts/src/model-session.ts:139

The SDK is executing a tool: hand the accumulated assistant blocks to the loop and block until the next complete() brings the result for it.

Parameters
ParameterType
namestring
inputunknown
Returns

Promise<ToolCallResult>

Interfaces

Database

Defined in: packages/core/contracts/src/index.ts:33

A relational database as the collections plugin and the SQL store see it. Placeholders are always ? — a driver rewrites them for its engine. Inserts return their id with RETURNING id (SQLite ≥ 3.35, Postgres, DO SQLite all support it).

Properties

dialect
readonly dialect: Dialect;

Defined in: packages/core/contracts/src/index.ts:34

Methods

close()
close(): Promise<void>;

Defined in: packages/core/contracts/src/index.ts:41

Returns

Promise<void>

columns()
columns(table): Promise<string[]>;

Defined in: packages/core/contracts/src/index.ts:40

Column names of a table; [] if it does not exist.

Parameters
ParameterType
tablestring
Returns

Promise<string[]>

exec()
exec(sql): Promise<void>;

Defined in: packages/core/contracts/src/index.ts:36

Run one or more statements without results (DDL).

Parameters
ParameterType
sqlstring
Returns

Promise<void>

query()
query<T>(sql, params?): Promise<T[]>;

Defined in: packages/core/contracts/src/index.ts:38

Run one statement with ? placeholders and return its rows.

Type Parameters
Type ParameterDefault type
TRecord<string, unknown>
Parameters
ParameterType
sqlstring
params?unknown[]
Returns

Promise<T[]>


Deferred

Defined in: packages/core/contracts/src/model-session.ts:27

Type Parameters

Type Parameter
T

Properties

promise
promise: Promise<T>;

Defined in: packages/core/contracts/src/model-session.ts:28

reject
reject: (e) => void;

Defined in: packages/core/contracts/src/model-session.ts:30

Parameters
ParameterType
eunknown
Returns

void

resolve
resolve: (v) => void;

Defined in: packages/core/contracts/src/model-session.ts:29

Parameters
ParameterType
vT
Returns

void


Host

Defined in: packages/core/contracts/src/index.ts:64

An HTTP host: takes a fetch-style handler and puts it on the wire.

Methods

listen()
listen(handler): Promise<HostServer>;

Defined in: packages/core/contracts/src/index.ts:65

Parameters
ParameterType
handlerRequestHandler
Returns

Promise<HostServer>


HostServer

Defined in: packages/core/contracts/src/index.ts:57

Properties

url?
optional url?: string;

Defined in: packages/core/contracts/src/index.ts:59

Base URL when the host listens on a socket (absent for serverless hosts).

Methods

close()
close(): Promise<void>;

Defined in: packages/core/contracts/src/index.ts:60

Returns

Promise<void>


ListObjectsOptions

Defined in: packages/core/contracts/src/objects.ts:28

Properties

cursor?
optional cursor?: string;

Defined in: packages/core/contracts/src/objects.ts:35

Opaque token from a previous page’s cursor.

delimiter?
optional delimiter?: string;

Defined in: packages/core/contracts/src/objects.ts:31

'/' groups keys under the next delimiter into prefixes (folder-style listing).

limit?
optional limit?: number;

Defined in: packages/core/contracts/src/objects.ts:33

Page size; the backend’s own maximum applies.

prefix?
optional prefix?: string;

Defined in: packages/core/contracts/src/objects.ts:29


ModelMessage

Defined in: packages/core/contracts/src/model.ts:14

Properties

content
content: ModelContent[];

Defined in: packages/core/contracts/src/model.ts:16

role
role: "user" | "assistant";

Defined in: packages/core/contracts/src/model.ts:15


ModelRequest

Defined in: packages/core/contracts/src/model.ts:26

Properties

messages
messages: ModelMessage[];

Defined in: packages/core/contracts/src/model.ts:28

system
system: string;

Defined in: packages/core/contracts/src/model.ts:27

tools
tools: ModelTool[];

Defined in: packages/core/contracts/src/model.ts:29


ModelResponse

Defined in: packages/core/contracts/src/model.ts:32

Properties

content
content: ModelContent[];

Defined in: packages/core/contracts/src/model.ts:33

stopReason
stopReason: string;

Defined in: packages/core/contracts/src/model.ts:35

'end_turn', 'tool_use', or a provider-specific reason. The loop only looks at content.


ModelService

Defined in: packages/core/contracts/src/model.ts:49

Properties

name
name: string;

Defined in: packages/core/contracts/src/model.ts:50

Methods

complete()
complete(req): Promise<ModelResponse>;

Defined in: packages/core/contracts/src/model.ts:51

Parameters
ParameterType
reqModelRequest
Returns

Promise<ModelResponse>

stream()?
optional stream(req): AsyncIterable<ModelEvent>;

Defined in: packages/core/contracts/src/model.ts:53

Optional: the same turn as complete(), incrementally. Consumers use streamOf() to not care.

Parameters
ParameterType
reqModelRequest
Returns

AsyncIterable<ModelEvent>


ModelTool

Defined in: packages/core/contracts/src/model.ts:19

Properties

description
description: string;

Defined in: packages/core/contracts/src/model.ts:21

input_schema
input_schema: Record<string, unknown>;

Defined in: packages/core/contracts/src/model.ts:23

JSON schema of the tool input (an object schema; type: 'object' is implied).

name
name: string;

Defined in: packages/core/contracts/src/model.ts:20


ObjectContent

Defined in: packages/core/contracts/src/objects.ts:47

A get() result: the metadata plus the bytes, as a stream or collected.

Extends

Properties

body
body: ReadableStream<Uint8Array<ArrayBufferLike>>;

Defined in: packages/core/contracts/src/objects.ts:48

contentType?
optional contentType?: string;

Defined in: packages/core/contracts/src/objects.ts:16

Inherited from

ObjectMeta.contentType

etag?
optional etag?: string;

Defined in: packages/core/contracts/src/objects.ts:18

Backend entity tag (unquoted); absent on backends that do not expose one.

Inherited from

ObjectMeta.etag

key
key: string;

Defined in: packages/core/contracts/src/objects.ts:11

Inherited from

ObjectMeta.key

lastModified
lastModified: number;

Defined in: packages/core/contracts/src/objects.ts:15

Unix ms.

Inherited from

ObjectMeta.lastModified

metadata
metadata: Record<string, string>;

Defined in: packages/core/contracts/src/objects.ts:20

User metadata (x-amz-meta-* / R2 customMetadata). Keys are lower-case.

Inherited from

ObjectMeta.metadata

size
size: number;

Defined in: packages/core/contracts/src/objects.ts:13

Bytes.

Inherited from

ObjectMeta.size

Methods

bytes()
bytes(): Promise<Uint8Array<ArrayBufferLike>>;

Defined in: packages/core/contracts/src/objects.ts:49

Returns

Promise<Uint8Array<ArrayBufferLike>>

text()
text(): Promise<string>;

Defined in: packages/core/contracts/src/objects.ts:50

Returns

Promise<string>


ObjectList

Defined in: packages/core/contracts/src/objects.ts:38

Properties

cursor?
optional cursor?: string;

Defined in: packages/core/contracts/src/objects.ts:43

Present when there is another page.

objects
objects: ObjectMeta[];

Defined in: packages/core/contracts/src/objects.ts:39

prefixes
prefixes: string[];

Defined in: packages/core/contracts/src/objects.ts:41

Only with delimiter.


ObjectMeta

Defined in: packages/core/contracts/src/objects.ts:10

Extended by

Properties

contentType?
optional contentType?: string;

Defined in: packages/core/contracts/src/objects.ts:16

etag?
optional etag?: string;

Defined in: packages/core/contracts/src/objects.ts:18

Backend entity tag (unquoted); absent on backends that do not expose one.

key
key: string;

Defined in: packages/core/contracts/src/objects.ts:11

lastModified
lastModified: number;

Defined in: packages/core/contracts/src/objects.ts:15

Unix ms.

metadata
metadata: Record<string, string>;

Defined in: packages/core/contracts/src/objects.ts:20

User metadata (x-amz-meta-* / R2 customMetadata). Keys are lower-case.

size
size: number;

Defined in: packages/core/contracts/src/objects.ts:13

Bytes.


ObjectStore

Defined in: packages/core/contracts/src/objects.ts:53

Methods

delete()
delete(key): Promise<void>;

Defined in: packages/core/contracts/src/objects.ts:59

Idempotent: deleting a missing key is not an error.

Parameters
ParameterType
keystring
Returns

Promise<void>

get()
get(key): Promise<ObjectContent | undefined>;

Defined in: packages/core/contracts/src/objects.ts:56

undefined when the key does not exist.

Parameters
ParameterType
keystring
Returns

Promise<ObjectContent | undefined>

head(key): Promise<ObjectMeta | undefined>;

Defined in: packages/core/contracts/src/objects.ts:57

Parameters
ParameterType
keystring
Returns

Promise<ObjectMeta | undefined>

list()
list(opts?): Promise<ObjectList>;

Defined in: packages/core/contracts/src/objects.ts:60

Parameters
ParameterType
opts?ListObjectsOptions
Returns

Promise<ObjectList>

put()
put(
   key, 
   body, 
   opts?
): Promise<ObjectMeta>;

Defined in: packages/core/contracts/src/objects.ts:54

Parameters
ParameterType
keystring
bodyObjectBody
opts?PutObjectOptions
Returns

Promise<ObjectMeta>


PutObjectOptions

Defined in: packages/core/contracts/src/objects.ts:23

Properties

contentType?
optional contentType?: string;

Defined in: packages/core/contracts/src/objects.ts:24

metadata?
optional metadata?: Record<string, string>;

Defined in: packages/core/contracts/src/objects.ts:25


SessionBackend

Defined in: packages/core/contracts/src/model-session.ts:69

What a driver supplies: the SDK-specific half of a session.

Methods

close()
close(): void;

Defined in: packages/core/contracts/src/model-session.ts:80

Returns

void

send()
send(text): void | Promise<void>;

Defined in: packages/core/contracts/src/model-session.ts:79

Deliver the user’s text for a new turn.

Parameters
ParameterType
textstring
Returns

void | Promise<void>

setTools()
setTools(tools): void | Promise<void>;

Defined in: packages/core/contracts/src/model-session.ts:77

The tool set changed (mid-turn or between turns).

Parameters
ParameterType
toolsModelTool[]
Returns

void | Promise<void>

start()
start(
   system, 
   tools, 
   prior
): void | Promise<void>;

Defined in: packages/core/contracts/src/model-session.ts:75

(Re)start the SDK session with this system prompt and tool set. Called before the first user turn and whenever the system prompt changes. prior is the loop’s history before the current message: replay it (see transcript) when the backend cannot resume an earlier session.

Parameters
ParameterType
systemstring
toolsModelTool[]
priorModelMessage[]
Returns

void | Promise<void>


SessionBridgeOptions

Defined in: packages/core/contracts/src/model-session.ts:83

Properties

debug?
optional debug?: (...args) => void;

Defined in: packages/core/contracts/src/model-session.ts:86

Parameters
ParameterType
argsunknown[]
Returns

void

flushDelayMs?
optional flushDelayMs?: number;

Defined in: packages/core/contracts/src/model-session.ts:88

Delay before handing a tool_use batch to the loop, so parallel calls arrive together.

tag?
optional tag?: string;

Defined in: packages/core/contracts/src/model-session.ts:85

Prefix for debug lines, e.g. the driver name.


Store

Defined in: packages/core/contracts/src/index.ts:45

Everything a kernel needs to persist: the event log, bundle blobs, and a database for plugins (key database).

Extended by

Properties

blobs
blobs: BlobStore;

Defined in: packages/core/contracts/src/index.ts:48

db
db: Database;

Defined in: packages/core/contracts/src/index.ts:46

log
log: EventLog;

Defined in: packages/core/contracts/src/index.ts:47

Methods

close()
close(): Promise<void>;

Defined in: packages/core/contracts/src/index.ts:49

Returns

Promise<void>


SubdomainOptions

Defined in: packages/core/contracts/src/index.ts:77

Properties

fallback?
optional fallback?: string;

Defined in: packages/core/contracts/src/index.ts:79

Tenant when the host has no tenant label (bare root domain, localhost, an IP).

reserved?
optional reserved?: Iterable<string, any, any>;

Defined in: packages/core/contracts/src/index.ts:83

Labels that are never tenants (www, api…): resolve to undefined.

root?
optional root?: string;

Defined in: packages/core/contracts/src/index.ts:81

The domain tenants live under (example.com). Without it the first label of any host is the tenant.


ToolCallResult

Defined in: packages/core/contracts/src/model-session.ts:22

Properties

content
content: string;

Defined in: packages/core/contracts/src/model-session.ts:23

isError?
optional isError?: boolean;

Defined in: packages/core/contracts/src/model-session.ts:24

Type Aliases

Dialect

type Dialect = "sqlite" | "postgres";

Defined in: packages/core/contracts/src/index.ts:14


ModelContent

type ModelContent = 
  | {
  text: string;
  type: "text";
}
  | {
  id: string;
  input: unknown;
  name: string;
  type: "tool_use";
}
  | {
  content: string;
  is_error?: boolean;
  tool_use_id: string;
  type: "tool_result";
};

Defined in: packages/core/contracts/src/model.ts:9


ModelEvent

type ModelEvent = 
  | {
  text: string;
  type: "text_delta";
}
  | {
  text: string;
  type: "thinking_delta";
}
  | {
  block: Extract<ModelContent, {
     type: "tool_use";
  }>;
  type: "tool_use";
}
  | {
  response: ModelResponse;
  type: "done";
};

Defined in: packages/core/contracts/src/model.ts:43

What a streaming driver emits while producing one turn. Deltas arrive as the provider sends them; tool_use is emitted once a call’s arguments are complete; done always ends the stream and carries the same ModelResponse that complete() would have returned for the request.


ObjectBody

type ObjectBody = string | Uint8Array | ArrayBuffer | ReadableStream<Uint8Array>;

Defined in: packages/core/contracts/src/objects.ts:8

Bytes going in: a string is UTF-8 encoded; a stream is passed through where the backend supports it.


RequestHandler

type RequestHandler = (request) => Promise<Response>;

Defined in: packages/core/contracts/src/index.ts:55

Parameters

ParameterType
requestRequest

Returns

Promise<Response>


TenantResolver

type TenantResolver = (request) => string | undefined | Promise<string | undefined>;

Defined in: packages/core/contracts/src/index.ts:69

Maps a request to a tenant id. undefined = no tenant (reject or use a default, host’s choice).

Parameters

ParameterType
requestRequest

Returns

string | undefined | Promise<string | undefined>

Variables

DATABASE_KEY

const DATABASE_KEY: "database" = 'database';

Defined in: packages/core/contracts/src/index.ts:53

The key under which the composition root provides the Database (system ↔ system).


MODEL_KEY

const MODEL_KEY: "model" = 'model';

Defined in: packages/core/contracts/src/model.ts:73

The key under which the model driver is provided (system → agent-loop).


OBJECTS_KEY

const OBJECTS_KEY: "objects" = 'objects';

Defined in: packages/core/contracts/src/objects.ts:64

The key under which the composition root provides the ObjectStore (system ↔ system, like database).

Functions

assertObjectKey()

function assertObjectKey(key): void;

Defined in: packages/core/contracts/src/objects.ts:69

Object keys are paths without a leading /, //, ./.. segments or control characters.

Parameters

ParameterType
keystring

Returns

void


assertTenantId()

function assertTenantId(id): void;

Defined in: packages/core/contracts/src/index.ts:114

Tenant ids become file names / schema names: keep them boring.

Parameters

ParameterType
idstring

Returns

void


bodyToBytes()

function bodyToBytes(body): Promise<Uint8Array<ArrayBufferLike>>;

Defined in: packages/core/contracts/src/objects.ts:75

Collect any ObjectBody into bytes (drivers that cannot stream use this).

Parameters

ParameterType
bodyObjectBody

Returns

Promise<Uint8Array<ArrayBufferLike>>


conversationKey()

function conversationKey(req): string;

Defined in: packages/core/contracts/src/model-session.ts:300

Sessions are identified by the first user message of the loop’s history.

Parameters

ParameterType
reqModelRequest

Returns

string


createMemoryObjectStore()

function createMemoryObjectStore(): ObjectStore;

Defined in: packages/core/contracts/src/objects.ts:151

In-memory reference implementation: tests, and the contract suite’s oracle.

Returns

ObjectStore


createModelPlugin()

function createModelPlugin(id, model): SystemPlugin;

Defined in: packages/core/contracts/src/model.ts:104

Wrap any ModelService as a system plugin providing model.

Parameters

ParameterType
idstring
modelModelService

Returns

SystemPlugin


createReasoningCache()

function createReasoningCache<T>(max?): Pick<Map<string, T>, "get"> & {
  set: void;
};

Defined in: packages/core/contracts/src/model.ts:90

Bounded FIFO map for provider-side reasoning items that must be replayed with the next tool call.

Type Parameters

Type Parameter
T

Parameters

ParameterTypeDefault value
maxnumber256

Returns

Pick<Map<string, T>, "get"> & { set: void; }


createScriptedModel()

function createScriptedModel(turns): ModelService & {
  calls: ModelRequest[];
  stream: AsyncIterable<ModelEvent>;
};

Defined in: packages/core/contracts/src/model.ts:115

A scripted model for tests and offline demos: each turn pops the next canned response. stream() replays the same turn as events, text split per word so consumers see several deltas.

Parameters

ParameterType
turns(req) => | string | ModelResponse | ModelContent[][]

Returns

ModelService & { calls: ModelRequest[]; stream: AsyncIterable<ModelEvent>; }


createSessionModel()

function createSessionModel(name, session): ModelService & {
  close: void;
};

Defined in: packages/core/contracts/src/model-session.ts:305

A ModelService with one SessionBridge per conversation.

Parameters

ParameterType
namestring
session() => SessionBridge

Returns

ModelService & { close: void; }


deferred()

function deferred<T>(): Deferred<T>;

Defined in: packages/core/contracts/src/model-session.ts:32

Type Parameters

Type Parameter
T

Returns

Deferred<T>


eventsOf()

function eventsOf(response): Iterable<ModelEvent>;

Defined in: packages/core/contracts/src/model.ts:64

Replay a finished response as events (text as one delta, each tool call, then done).

Parameters

ParameterType
responseModelResponse

Returns

Iterable<ModelEvent>


firstToolUseId()

function firstToolUseId(content): string | undefined;

Defined in: packages/core/contracts/src/model.ts:85

Id of the first tool_use block — the handle drivers key per-turn provider state (reasoning) on.

Parameters

ParameterType
contentModelContent[]

Returns

string | undefined


listKeys()

function listKeys(entries, opts?): ObjectList;

Defined in: packages/core/contracts/src/objects.ts:119

Shared S3-style listing over a set of objects; used by the memory store and the drivers’ fakes.

Parameters

ParameterType
entriesIterable<ObjectMeta>
optsListObjectsOptions

Returns

ObjectList


lowerKeys()

function lowerKeys(m): Record<string, string>;

Defined in: packages/core/contracts/src/objects.ts:147

Parameters

ParameterType
mRecord<string, string>

Returns

Record<string, string>


objectContent()

function objectContent(source): {
  body: ReadableStream<Uint8Array<ArrayBufferLike>>;
  bytes: () => Promise<Uint8Array<ArrayBufferLike>>;
  text: () => Promise<string>;
};

Defined in: packages/core/contracts/src/objects.ts:96

The body part of an ObjectContent from a stream (or bytes).

Parameters

ParameterType
source| Uint8Array<ArrayBufferLike> | ReadableStream<Uint8Array<ArrayBufferLike>>

Returns

{
  body: ReadableStream<Uint8Array<ArrayBufferLike>>;
  bytes: () => Promise<Uint8Array<ArrayBufferLike>>;
  text: () => Promise<string>;
}
body
body: ReadableStream<Uint8Array<ArrayBufferLike>>;
bytes
bytes: () => Promise<Uint8Array<ArrayBufferLike>> = collect;
Returns

Promise<Uint8Array<ArrayBufferLike>>

text
text: () => Promise<string>;
Returns

Promise<string>


parseToolArgs()

function parseToolArgs(raw): unknown;

Defined in: packages/core/contracts/src/model.ts:76

Parse a tool call’s JSON arguments string; unparsable text is kept as { _raw } so the tool sees it.

Parameters

ParameterType
rawstring

Returns

unknown


replayPrompt()

function replayPrompt(prior): string;

Defined in: packages/core/contracts/src/model-session.ts:295

transcript() framed as the opening message of an SDK session that cannot resume.

Parameters

ParameterType
priorModelMessage[]

Returns

string


sqlDialect()

function sqlDialect(dialect): {
  bigint: string;
  boolean: string;
  idColumn: string;
  real: string;
};

Defined in: packages/core/contracts/src/index.ts:17

Dialect-specific DDL fragments; pure, shared by store drivers and the collections plugin.

Parameters

ParameterType
dialectDialect

Returns

bigint
bigint: string;
boolean
boolean: string;
idColumn
idColumn: string;

auto-increment integer primary key

real
real: string;

streamOf()

function streamOf(model, req): AsyncIterable<ModelEvent>;

Defined in: packages/core/contracts/src/model.ts:57

Stream a turn from any driver: a driver without stream() yields its complete() as one text + done.

Parameters

ParameterType
modelModelService
reqModelRequest

Returns

AsyncIterable<ModelEvent>


tenantFromHeader()

function tenantFromHeader(header?, fallback?): TenantResolver;

Defined in: packages/core/contracts/src/index.ts:73

Tenant id from a header (default x-tenant), falling back to fallback.

Parameters

ParameterTypeDefault value
headerstring'x-tenant'
fallback?stringundefined

Returns

TenantResolver


tenantFromSubdomain()

function tenantFromSubdomain(opts?): TenantResolver;

Defined in: packages/core/contracts/src/index.ts:93

Tenant id from the host-name label under root (acme.example.comacme). localhost, IPs and the bare root resolve to fallback; acme.localhostacme for local development without DNS. tenantFromSubdomain('dev') is shorthand for { fallback: 'dev' }.

Parameters

ParameterType
optsstring | SubdomainOptions

Returns

TenantResolver


toolSignature()

function toolSignature(tools): string;

Defined in: packages/core/contracts/src/model-session.ts:275

Parameters

ParameterType
toolsModelTool[]

Returns

string


transcript()

function transcript(messages): string;

Defined in: packages/core/contracts/src/model-session.ts:280

Loop history as plain text, to seed a fresh SDK session that cannot resume.

Parameters

ParameterType
messagesModelMessage[]

Returns

string

@sms/executor-node

Classes

NodeExecutor

Defined in: packages/drivers/executor/node/src/index.ts:17

Runs each plugin bundle in its own worker thread. Local-dev executor.

Implements

Constructors

Constructor
new NodeExecutor(opts?): NodeExecutor;

Defined in: packages/drivers/executor/node/src/index.ts:19

Parameters
ParameterType
optsNodeExecutorOptions
Returns

NodeExecutor

Methods

load()
load(
   bundle, 
   host, 
   opts?
): Promise<ExecutorInstance>;

Defined in: packages/drivers/executor/node/src/index.ts:23

Parameters
ParameterType
bundlePluginBundle
hostHostBridge
opts{ timeoutMs?: number; }
opts.timeoutMs?number
Returns

Promise<ExecutorInstance>

Implementation of

Executor.load

Interfaces

NodeExecutorOptions

Defined in: packages/drivers/executor/node/src/index.ts:5

Properties

callTimeoutMs?
optional callTimeoutMs?: number;

Defined in: packages/drivers/executor/node/src/index.ts:7

Per-call timeout for calls into plugin code.

resourceLimits?
optional resourceLimits?: {
  maxOldGenerationSizeMb?: number;
  maxYoungGenerationSizeMb?: number;
};

Defined in: packages/drivers/executor/node/src/index.ts:9

Memory limits passed to the worker.

maxOldGenerationSizeMb?
optional maxOldGenerationSizeMb?: number;
maxYoungGenerationSizeMb?
optional maxYoungGenerationSizeMb?: number;

@sms/executor-quickjs

Classes

QuickJSExecutor

Defined in: packages/drivers/executor/quickjs/src/index.ts:90

Implements

Constructors

Constructor
new QuickJSExecutor(opts?): QuickJSExecutor;

Defined in: packages/drivers/executor/quickjs/src/index.ts:94

Parameters
ParameterType
optsQuickJSExecutorOptions
Returns

QuickJSExecutor

Methods

load()
load(
   bundle, 
   host, 
   opts?
): Promise<ExecutorInstance>;

Defined in: packages/drivers/executor/quickjs/src/index.ts:108

Parameters
ParameterType
bundlePluginBundle
hostHostBridge
opts{ timeoutMs?: number; }
opts.timeoutMs?number
Returns

Promise<ExecutorInstance>

Implementation of

Executor.load

Interfaces

QuickJSExecutorOptions

Defined in: packages/drivers/executor/quickjs/src/index.ts:24

Properties

callTimeoutMs?
optional callTimeoutMs?: number;

Defined in: packages/drivers/executor/quickjs/src/index.ts:37

Overall timeout for a call into the plugin (activate, tool handler…). Default 10 000 ms.

maxStackBytes?
optional maxStackBytes?: number;

Defined in: packages/drivers/executor/quickjs/src/index.ts:33

Stack limit per plugin. Default 1 MiB.

memoryLimitBytes?
optional memoryLimitBytes?: number;

Defined in: packages/drivers/executor/quickjs/src/index.ts:31

Heap limit per plugin. Default 64 MiB.

sliceMs?
optional sliceMs?: number;

Defined in: packages/drivers/executor/quickjs/src/index.ts:35

CPU time one synchronous slice of guest code may take before it is interrupted. Default 2000 ms.

variant?
optional variant?: 
  | QuickJSSyncVariant
  | Promise<
  | QuickJSSyncVariant
  | {
  default: QuickJSSyncVariant;
}>;

Defined in: packages/drivers/executor/quickjs/src/index.ts:29

WASM variant. Default: the Node/browser file-based release build. On Cloudflare Workers pass import('@jitl/quickjs-singlefile-mjs-release-sync') (WASM inlined, no filesystem).

@sms/host-cloudflare

Interfaces

CloudflareApp

Defined in: packages/drivers/host/cloudflare/src/index.ts:72

Type Parameters

Type Parameter
Env

Properties

DurableObject
DurableObject: (state, env) => {
  fetch: Promise<Response>;
};

Defined in: packages/drivers/host/cloudflare/src/index.ts:78

The Durable Object class: export { TenantKernel } under the name in wrangler.toml.

Parameters
ParameterType
stateDurableObjectStateLike
envEnv
Returns
{
  fetch: Promise<Response>;
}
fetch()
fetch(request): Promise<Response>;
Parameters
ParameterType
requestRequest
Returns

Promise<Response>

Methods

fetch()
fetch(request, env): Promise<Response>;

Defined in: packages/drivers/host/cloudflare/src/index.ts:74

The Worker’s fetch handler: export default { fetch, scheduled }.

Parameters
ParameterType
requestRequest
envEnv
Returns

Promise<Response>

scheduled()
scheduled(event, env): Promise<Record<string, unknown>>;

Defined in: packages/drivers/host/cloudflare/src/index.ts:76

The Worker’s cron handler: ticks every tenant from opts.tenants, in parallel. Returns per-tenant results.

Parameters
ParameterType
eventScheduledEventLike
envEnv
Returns

Promise<Record<string, unknown>>


CloudflareAppOptions

Defined in: packages/drivers/host/cloudflare/src/index.ts:39

Type Parameters

Type Parameter
Env

Properties

binding
binding: keyof Env & string;

Defined in: packages/drivers/host/cloudflare/src/index.ts:48

Name of the Durable Object binding in wrangler.toml, e.g. TENANT.

onMissing?
optional onMissing?: (request) => Response | Promise<Response>;

Defined in: packages/drivers/host/cloudflare/src/index.ts:62

Response for requests with no tenant. Default 400.

Parameters
ParameterType
requestRequest
Returns

Response | Promise<Response>

resolve
resolve: (request, env) => string | Promise<string | undefined> | undefined;

Defined in: packages/drivers/host/cloudflare/src/index.ts:41

Which tenant a request belongs to (header, subdomain, path, JWT…). env is there for ROOT_DOMAIN-style config.

Parameters
ParameterType
requestRequest
envEnv
Returns

string | Promise<string | undefined> | undefined

store?
optional store?: (ctx) => 
  | Store
| Promise<Store>;

Defined in: packages/drivers/host/cloudflare/src/index.ts:60

Open the tenant’s Store. Default: @sms/store-do on the Durable Object’s own SQLite. Override to put a tenant on D1 (openD1Store(env[binding]) from @sms/store-d1, one database per tenant) or anything else reachable from the DO; the DO still serialises the tenant’s requests.

Parameters
ParameterType
ctx{ env: Env; state: DurableObjectStateLike; tenantId: string; }
ctx.envEnv
ctx.stateDurableObjectStateLike
ctx.tenantIdstring
Returns

| Store | Promise<Store>

tenant
tenant: (ctx) => TenantApp | Promise<TenantApp>;

Defined in: packages/drivers/host/cloudflare/src/index.ts:54

Boot the tenant’s application on store (already open on the DO’s SQLite) and return its request handler — typically createBaseline({ store, executor, model, plugins, … }) from @sms/baseline. Called once per Durable Object lifetime.

Parameters
ParameterType
ctx{ env: Env; store: Store; tenantId: string; }
ctx.envEnv
ctx.storeStore
ctx.tenantIdstring
Returns

TenantApp | Promise<TenantApp>

tenants?
optional tenants?: (env) => string[] | Promise<string[]>;

Defined in: packages/drivers/host/cloudflare/src/index.ts:46

Tenants to tick from the Worker’s cron trigger (scheduled). Only these run scheduled jobs — a Durable Object cannot enumerate itself. Absent: scheduled is a no-op.

Parameters
ParameterType
envEnv
Returns

string[] | Promise<string[]>


DurableObjectNamespaceLike

Defined in: packages/drivers/host/cloudflare/src/index.ts:24

Methods

get()
get(id): DurableObjectStubLike;

Defined in: packages/drivers/host/cloudflare/src/index.ts:26

Parameters
ParameterType
idunknown
Returns

DurableObjectStubLike

idFromName()
idFromName(name): unknown;

Defined in: packages/drivers/host/cloudflare/src/index.ts:25

Parameters
ParameterType
namestring
Returns

unknown


DurableObjectStateLike

Defined in: packages/drivers/host/cloudflare/src/index.ts:17

Properties

id
id: {
  name?: string;
  toString: string;
};

Defined in: packages/drivers/host/cloudflare/src/index.ts:19

name?
optional name?: string;
toString()
toString(): string;
Returns

string

storage
storage: {
  sql: SqlStorageLike;
};

Defined in: packages/drivers/host/cloudflare/src/index.ts:18

sql
sql: SqlStorageLike;

DurableObjectStubLike

Defined in: packages/drivers/host/cloudflare/src/index.ts:21

Methods

fetch()
fetch(request): Promise<Response>;

Defined in: packages/drivers/host/cloudflare/src/index.ts:22

Parameters
ParameterType
requestRequest
Returns

Promise<Response>


ScheduledEventLike

Defined in: packages/drivers/host/cloudflare/src/index.ts:34

Properties

cron?
optional cron?: string;

Defined in: packages/drivers/host/cloudflare/src/index.ts:35

scheduledTime?
optional scheduledTime?: number;

Defined in: packages/drivers/host/cloudflare/src/index.ts:36


TenantApp

Defined in: packages/drivers/host/cloudflare/src/index.ts:66

What a tenant boot returns: at least a fetch-style handler (a Baseline satisfies this).

Properties

handle
handle: RequestHandler;

Defined in: packages/drivers/host/cloudflare/src/index.ts:67

Methods

tick()?
optional tick(now?): Promise<unknown>;

Defined in: packages/drivers/host/cloudflare/src/index.ts:69

Run due scheduled jobs; called by the cron trigger.

Parameters
ParameterType
now?number
Returns

Promise<unknown>

Variables

TENANT_HEADER

const TENANT_HEADER: "x-sms-tenant" = 'x-sms-tenant';

Defined in: packages/drivers/host/cloudflare/src/index.ts:29

Functions

createCloudflareApp()

function createCloudflareApp<Env>(opts): CloudflareApp<Env>;

Defined in: packages/drivers/host/cloudflare/src/index.ts:84

Type Parameters

Type Parameter
Env extends Record<string, unknown>

Parameters

ParameterType
optsCloudflareAppOptions<Env>

Returns

CloudflareApp<Env>

@sms/host-fastify

Interfaces

FastifyHostOptions

Defined in: packages/drivers/host/fastify/src/index.ts:5

Properties

app?
optional app?: FastifyInstance<RawServerDefault, IncomingMessage, ServerResponse<IncomingMessage>, FastifyBaseLogger, FastifyTypeProviderDefault>;

Defined in: packages/drivers/host/fastify/src/index.ts:7

Mount into an existing app instead of creating one (your routes/auth/plugins keep working beside it).

host?
optional host?: string;

Defined in: packages/drivers/host/fastify/src/index.ts:9

port?
optional port?: number;

Defined in: packages/drivers/host/fastify/src/index.ts:8

prefix?
optional prefix?: string;

Defined in: packages/drivers/host/fastify/src/index.ts:11

URL prefix to mount under, e.g. /sms. Default: everything not matched by your own routes.

Functions

createFastifyHost()

function createFastifyHost(opts?): Host;

Defined in: packages/drivers/host/fastify/src/index.ts:45

Parameters

ParameterType
optsFastifyHostOptions

Returns

Host


registerHandler()

function registerHandler(
   app, 
   handler, 
   prefix?
): Promise<void>;

Defined in: packages/drivers/host/fastify/src/index.ts:18

Register the handler as a catch-all under prefix, inside an encapsulated plugin scope so that the raw body handling does not leak into your own routes. The baseline’s content-type handling stays authoritative.

Parameters

ParameterTypeDefault value
appFastifyInstanceundefined
handlerRequestHandlerundefined
prefixstring''

Returns

Promise<void>

@sms/host-node

Interfaces

NodeHostOptions

Defined in: packages/drivers/host/node/src/index.ts:6

Properties

host?
optional host?: string;

Defined in: packages/drivers/host/node/src/index.ts:8

port?
optional port?: number;

Defined in: packages/drivers/host/node/src/index.ts:7

Functions

createNodeHost()

function createNodeHost(opts?): Host;

Defined in: packages/drivers/host/node/src/index.ts:41

node:http host. port: 0 picks a free port (tests).

Parameters

ParameterType
optsNodeHostOptions

Returns

Host


sendResponse()

function sendResponse(res, response): Promise<void>;

Defined in: packages/drivers/host/node/src/index.ts:29

Write a fetch Response to the socket, streaming the body chunk by chunk (SSE, large files). A client that goes away mid-stream ends the write quietly: that is not a failure of the request.

Parameters

ParameterType
resServerResponse
responseResponse

Returns

Promise<void>


toRequest()

function toRequest(req, fallbackHost?): Promise<Request>;

Defined in: packages/drivers/host/node/src/index.ts:12

Turn a Node request into a fetch Request. Exported so other Node-based hosts can reuse it.

Parameters

ParameterTypeDefault value
reqIncomingMessageundefined
fallbackHoststring'127.0.0.1'

Returns

Promise<Request>

@sms/kernel

Classes

Kernel

Defined in: packages/core/kernel/src/kernel.ts:38

The kernel: a loader + registry + effect tracker. Generic in the Linux-kernel sense — everything concrete is a plugin or an adapter handed in via options.

Implements

Constructors

Constructor
new Kernel(opts?): Kernel;

Defined in: packages/core/kernel/src/kernel.ts:52

Parameters
ParameterType
optsKernelOptions
Returns

Kernel

Properties

blobs
readonly blobs: BlobStore;

Defined in: packages/core/kernel/src/kernel.ts:41

Implementation of

KernelApi.blobs

executor
executor: Executor | undefined;

Defined in: packages/core/kernel/src/kernel.ts:42

Whether an Executor is configured (needed for agent plugins with code).

Implementation of

KernelApi.executor

log
readonly log: EventLog;

Defined in: packages/core/kernel/src/kernel.ts:40

Implementation of

KernelApi.log

name
readonly name: string;

Defined in: packages/core/kernel/src/kernel.ts:39

Implementation of

KernelApi.name

Methods

assertAgentManifest()
assertAgentManifest(manifest): void;

Defined in: packages/core/kernel/src/kernel.ts:247

Static trust checks on an agent manifest (defense in depth; effects re-check at apply time).

Parameters
ParameterType
manifestPluginManifest
Returns

void

Implementation of

KernelApi.assertAgentManifest

authorize()
authorize(manifest, issuedBy): Promise<MountAuthorization>;

Defined in: packages/core/kernel/src/kernel.ts:187

Mint an authorization for an agent plugin. Only system fibers hold a KernelApi.

Parameters
ParameterType
manifestPluginManifest
issuedBystring
Returns

Promise<MountAuthorization>

Implementation of

KernelApi.authorize

contributions()
contributions<T>(point): Contribution<T>[];

Defined in: packages/core/kernel/src/kernel.ts:105

Type Parameters
Type ParameterDefault type
Tunknown
Parameters
ParameterType
pointstring
Returns

Contribution<T>[]

Implementation of

KernelApi.contributions

defineKey()
defineKey(meta): void;

Defined in: packages/core/kernel/src/kernel.ts:78

Parameters
ParameterType
metaKeyMeta
Returns

void

Implementation of

KernelApi.defineKey

definePoint()
definePoint(meta): void;

Defined in: packages/core/kernel/src/kernel.ts:82

Parameters
ParameterType
metaExtensionPointMeta
Returns

void

Implementation of

KernelApi.definePoint

disable()
disable(id, reason?): Promise<FiberView>;

Defined in: packages/core/kernel/src/kernel.ts:302

Parameters
ParameterTypeDefault value
idstringundefined
reasonstring'disabled'
Returns

Promise<FiberView>

Implementation of

KernelApi.disable

dispose()
dispose(): Promise<void>;

Defined in: packages/core/kernel/src/kernel.ts:398

Returns

Promise<void>

enable()
enable(id): Promise<FiberView>;

Defined in: packages/core/kernel/src/kernel.ts:290

Parameters
ParameterType
idstring
Returns

Promise<FiberView>

Implementation of

KernelApi.enable

fiber()
fiber(id): FiberView | undefined;

Defined in: packages/core/kernel/src/kernel.ts:130

Parameters
ParameterType
idstring
Returns

FiberView | undefined

Implementation of

KernelApi.fiber

fibers()
fibers(): FiberView[];

Defined in: packages/core/kernel/src/kernel.ts:126

Returns

FiberView[]

Implementation of

KernelApi.fibers

getValue()
getValue<T>(key): T | undefined;

Defined in: packages/core/kernel/src/kernel.ts:101

Read a key from the host side (composition roots / tests). No trust check.

Type Parameters
Type ParameterDefault type
Tunknown
Parameters
ParameterType
keystring
Returns

T | undefined

Implementation of

KernelApi.getValue

has()
has(key): boolean;

Defined in: packages/core/kernel/src/kernel.ts:96

Parameters
ParameterType
keystring
Returns

boolean

Implementation of

KernelApi.has

install()
install(plugin, opts?): Promise<FiberView>;

Defined in: packages/core/kernel/src/kernel.ts:164

Install an in-process, system-trust plugin.

Parameters
ParameterType
pluginSystemPlugin
opts{ enabled?: boolean; settle?: boolean; }
opts.enabled?boolean
opts.settle?boolean
Returns

Promise<FiberView>

keys()
keys(): KeyMeta[];

Defined in: packages/core/kernel/src/kernel.ts:87

Returns

KeyMeta[]

Implementation of

KernelApi.keys

observeKeys()
observeKeys(observer): () => void;

Defined in: packages/core/kernel/src/kernel.ts:119

Parameters
ParameterType
observerKeyObserver
Returns

() => void

Implementation of

KernelApi.observeKeys

observePoint()
observePoint<T>(point, observer): () => void;

Defined in: packages/core/kernel/src/kernel.ts:109

Type Parameters
Type ParameterDefault type
Tunknown
Parameters
ParameterType
pointstring
observerPointObserver<T>
Returns

() => void

Implementation of

KernelApi.observePoint

points()
points(): ExtensionPointMeta[];

Defined in: packages/core/kernel/src/kernel.ts:92

Returns

ExtensionPointMeta[]

Implementation of

KernelApi.points

propose()
propose(proposed, auth): Promise<FiberView>;

Defined in: packages/core/kernel/src/kernel.ts:200

Install or update an agent-trust plugin. Requires an authorization minted by a system fiber.

Parameters
ParameterType
proposedPluginManifest
authMountAuthorization
Returns

Promise<FiberView>

Implementation of

KernelApi.propose

restore()
restore(): Promise<FiberView[]>;

Defined in: packages/core/kernel/src/kernel.ts:325

Re-mount agent plugins recorded in the log (persistence axis). System plugins must already be installed by the composition root; their enabled flag is taken from the log by install().

Returns

Promise<FiberView[]>

setExecutor()
setExecutor(executor): void;

Defined in: packages/core/kernel/src/kernel.ts:72

Parameters
ParameterType
executorExecutor
Returns

void

settle()
settle(): Promise<void>;

Defined in: packages/core/kernel/src/kernel.ts:367

Drive fibers toward the target: enabled + dependencies satisfied → active; disabled or a dependency withdrawn → inactive. Runs until nothing changes.

Returns

Promise<void>

Implementation of

KernelApi.settle

uninstall()
uninstall(
   id, 
   reason?, 
   opts?
): Promise<void>;

Defined in: packages/core/kernel/src/kernel.ts:310

Remove a plugin. System plugins are refused unless force (composition-root use only).

Parameters
ParameterTypeDefault value
idstringundefined
reasonstring'uninstalled'
opts{ force?: boolean; }{}
opts.force?booleanundefined
Returns

Promise<void>

Implementation of

KernelApi.uninstall


KernelError

Defined in: packages/core/kernel/src/errors.ts:15

Extends

  • Error

Constructors

Constructor
new KernelError(code, message): KernelError;

Defined in: packages/core/kernel/src/errors.ts:17

Parameters
ParameterType
codeKernelErrorCode
messagestring
Returns

KernelError

Overrides
Error.constructor

Properties

cause?
optional cause?: unknown;

Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.error.d.ts:26

Inherited from
Error.cause
code
readonly code: KernelErrorCode;

Defined in: packages/core/kernel/src/errors.ts:16

message
message: string;

Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es5.d.ts:1077

Inherited from
Error.message
name
name: string;

Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es5.d.ts:1076

Inherited from
Error.name
stack?
optional stack?: string;

Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es5.d.ts:1078

Inherited from
Error.stack
stackTraceLimit
static stackTraceLimit: number;

Defined in: node_modules/.pnpm/@types+node@22.20.1/node_modules/@types/node/globals.d.ts:68

The Error.stackTraceLimit property specifies the number of stack frames collected by a stack trace (whether generated by new Error().stack or Error.captureStackTrace(obj)).

The default value is 10 but may be set to any valid JavaScript number. Changes will affect any stack trace captured after the value has been changed.

If set to a non-number value, or set to a negative number, stack traces will not capture any frames.

Inherited from
Error.stackTraceLimit

Methods

captureStackTrace()
static captureStackTrace(targetObject, constructorOpt?): void;

Defined in: node_modules/.pnpm/@types+node@22.20.1/node_modules/@types/node/globals.d.ts:52

Creates a .stack property on targetObject, which when accessed returns a string representing the location in the code at which Error.captureStackTrace() was called.

const myObject = {};
Error.captureStackTrace(myObject);
myObject.stack;  // Similar to `new Error().stack`

The first line of the trace will be prefixed with ${myObject.name}: ${myObject.message}.

The optional constructorOpt argument accepts a function. If given, all frames above constructorOpt, including constructorOpt, will be omitted from the generated stack trace.

The constructorOpt argument is useful for hiding implementation details of error generation from the user. For instance:

function a() {
  b();
}

function b() {
  c();
}

function c() {
  // Create an error without stack trace to avoid calculating the stack trace twice.
  const { stackTraceLimit } = Error;
  Error.stackTraceLimit = 0;
  const error = new Error();
  Error.stackTraceLimit = stackTraceLimit;

  // Capture the stack trace above function b
  Error.captureStackTrace(error, b); // Neither function c, nor b is included in the stack trace
  throw error;
}

a();
Parameters
ParameterType
targetObjectobject
constructorOpt?Function
Returns

void

Inherited from
Error.captureStackTrace
prepareStackTrace()
static prepareStackTrace(err, stackTraces): any;

Defined in: node_modules/.pnpm/@types+node@22.20.1/node_modules/@types/node/globals.d.ts:56

Parameters
ParameterType
errError
stackTracesCallSite[]
Returns

any

See

https://v8.dev/docs/stack-trace-api#customizing-stack-traces

Inherited from
Error.prepareStackTrace

MemoryBlobStore

Defined in: packages/core/kernel/src/log.ts:18

Content-addressed storage for plugin bundles.

Implements

Constructors

Constructor
new MemoryBlobStore(): MemoryBlobStore;
Returns

MemoryBlobStore

Methods

get()
get(hash): Promise<string | undefined>;

Defined in: packages/core/kernel/src/log.ts:25

Parameters
ParameterType
hashstring
Returns

Promise<string | undefined>

Implementation of

BlobStore.get

put()
put(bytes): Promise<string>;

Defined in: packages/core/kernel/src/log.ts:20

Parameters
ParameterType
bytesstring
Returns

Promise<string>

Implementation of

BlobStore.put


MemoryEventLog

Defined in: packages/core/kernel/src/log.ts:3

Implements

Constructors

Constructor
new MemoryEventLog(): MemoryEventLog;
Returns

MemoryEventLog

Methods

all()
all(): Promise<KernelEvent[]>;

Defined in: packages/core/kernel/src/log.ts:10

Returns

Promise<KernelEvent[]>

Implementation of

EventLog.all

append()
append(event): Promise<KernelEvent>;

Defined in: packages/core/kernel/src/log.ts:5

Parameters
ParameterType
eventOmit<KernelEvent, "seq" | "ts">
Returns

Promise<KernelEvent>

Implementation of

EventLog.append

since()
since(seq): Promise<KernelEvent[]>;

Defined in: packages/core/kernel/src/log.ts:13

Parameters
ParameterType
seqnumber
Returns

Promise<KernelEvent[]>

Implementation of

EventLog.since

Interfaces

AppliedEffect

Defined in: packages/core/kernel/src/types.ts:74

Properties

kind
kind: EffectKind;

Defined in: packages/core/kernel/src/types.ts:75

label
label: string;

Defined in: packages/core/kernel/src/types.ts:76

undo
undo: () => void | Promise<void>;

Defined in: packages/core/kernel/src/types.ts:77

Returns

void | Promise<void>


BlobStore

Defined in: packages/core/kernel/src/types.ts:200

Content-addressed storage for plugin bundles.

Methods

get()
get(hash): Promise<string | undefined>;

Defined in: packages/core/kernel/src/types.ts:202

Parameters
ParameterType
hashstring
Returns

Promise<string | undefined>

put()
put(bytes): Promise<string>;

Defined in: packages/core/kernel/src/types.ts:201

Parameters
ParameterType
bytesstring
Returns

Promise<string>


Contribution

Defined in: packages/core/kernel/src/types.ts:34

Type Parameters

Type ParameterDefault type
Tunknown

Properties

id
id: string;

Defined in: packages/core/kernel/src/types.ts:35

item
item: T;

Defined in: packages/core/kernel/src/types.ts:38

owner
owner: string;

Defined in: packages/core/kernel/src/types.ts:37

point
point: string;

Defined in: packages/core/kernel/src/types.ts:36


EventLog

Defined in: packages/core/kernel/src/types.ts:193

Methods

all()
all(): Promise<KernelEvent[]>;

Defined in: packages/core/kernel/src/types.ts:195

Returns

Promise<KernelEvent[]>

append()
append(event): Promise<KernelEvent>;

Defined in: packages/core/kernel/src/types.ts:194

Parameters
ParameterType
eventOmit<KernelEvent, "seq" | "ts">
Returns

Promise<KernelEvent>

since()
since(seq): Promise<KernelEvent[]>;

Defined in: packages/core/kernel/src/types.ts:196

Parameters
ParameterType
seqnumber
Returns

Promise<KernelEvent[]>


Executor

Defined in: packages/core/kernel/src/types.ts:180

Methods

load()
load(
   bundle, 
   host, 
   opts?
): Promise<ExecutorInstance>;

Defined in: packages/core/kernel/src/types.ts:181

Parameters
ParameterType
bundlePluginBundle
hostHostBridge
opts?{ timeoutMs?: number; }
opts.timeoutMs?number
Returns

Promise<ExecutorInstance>


ExecutorInstance

Defined in: packages/core/kernel/src/types.ts:174

Methods

call()
call(method, args): Promise<unknown>;

Defined in: packages/core/kernel/src/types.ts:176

Call into plugin code: ‘activate’, ‘fn’ {id,args}, …

Parameters
ParameterType
methodstring
argsunknown
Returns

Promise<unknown>

dispose()
dispose(): Promise<void>;

Defined in: packages/core/kernel/src/types.ts:177

Returns

Promise<void>


ExtensionPointMeta

Defined in: packages/core/kernel/src/types.ts:25

A named bag of contributions (tools, routes, collections, ui slots, gates …).

Properties

description?
optional description?: string;

Defined in: packages/core/kernel/src/types.ts:27

minContributorTrust?
optional minContributorTrust?: Trust;

Defined in: packages/core/kernel/src/types.ts:29

Minimum trust a fiber needs to contribute here. Default: agent (open).

name
name: string;

Defined in: packages/core/kernel/src/types.ts:26

validate?
optional validate?: (item) => void;

Defined in: packages/core/kernel/src/types.ts:31

Host-side validation of an item; throw to reject (fails the contributor’s activation).

Parameters
ParameterType
itemunknown
Returns

void


FiberView

Defined in: packages/core/kernel/src/types.ts:82

Properties

effects
effects: number;

Defined in: packages/core/kernel/src/types.ts:92

enabled
enabled: boolean;

Defined in: packages/core/kernel/src/types.ts:87

error?
optional error?: string;

Defined in: packages/core/kernel/src/types.ts:88

id
id: string;

Defined in: packages/core/kernel/src/types.ts:83

inject
inject: string[];

Defined in: packages/core/kernel/src/types.ts:89

optional
optional: string[];

Defined in: packages/core/kernel/src/types.ts:90

provide
provide: string[];

Defined in: packages/core/kernel/src/types.ts:91

state
state: FiberState;

Defined in: packages/core/kernel/src/types.ts:86

trust
trust: Trust;

Defined in: packages/core/kernel/src/types.ts:85

version
version: string;

Defined in: packages/core/kernel/src/types.ts:84

waitingFor
waitingFor: string[];

Defined in: packages/core/kernel/src/types.ts:93


HostBridge

Defined in: packages/core/kernel/src/types.ts:170

Host side of the bridge: handles calls coming from plugin code.

Methods

call()
call(method, args): Promise<unknown>;

Defined in: packages/core/kernel/src/types.ts:171

Parameters
ParameterType
methodstring
argsunknown
Returns

Promise<unknown>


KernelApi

Defined in: packages/core/kernel/src/types.ts:135

What system-trust plugins can do to the kernel. Never reachable by agent code.

Properties

blobs
blobs: BlobStore;

Defined in: packages/core/kernel/src/types.ts:162

executor
executor: Executor | undefined;

Defined in: packages/core/kernel/src/types.ts:164

Whether an Executor is configured (needed for agent plugins with code).

log
log: EventLog;

Defined in: packages/core/kernel/src/types.ts:161

name
readonly name: string;

Defined in: packages/core/kernel/src/types.ts:136

Methods

assertAgentManifest()
assertAgentManifest(manifest): void;

Defined in: packages/core/kernel/src/types.ts:150

Static trust checks on a manifest that will be mounted with agent trust. Throws KernelError.

Parameters
ParameterType
manifestPluginManifest
Returns

void

authorize()
authorize(manifest, issuedBy): Promise<MountAuthorization>;

Defined in: packages/core/kernel/src/types.ts:152

Mint an authorization for an agent plugin. Only system fibers hold a KernelApi.

Parameters
ParameterType
manifestPluginManifest
issuedBystring
Returns

Promise<MountAuthorization>

contributions()
contributions<T>(point): Contribution<T>[];

Defined in: packages/core/kernel/src/types.ts:144

Type Parameters
Type ParameterDefault type
Tunknown
Parameters
ParameterType
pointstring
Returns

Contribution<T>[]

defineKey()
defineKey(meta): void;

Defined in: packages/core/kernel/src/types.ts:137

Parameters
ParameterType
metaKeyMeta
Returns

void

definePoint()
definePoint(meta): void;

Defined in: packages/core/kernel/src/types.ts:138

Parameters
ParameterType
metaExtensionPointMeta
Returns

void

disable()
disable(id, reason?): Promise<FiberView>;

Defined in: packages/core/kernel/src/types.ts:156

Parameters
ParameterType
idstring
reason?string
Returns

Promise<FiberView>

enable()
enable(id): Promise<FiberView>;

Defined in: packages/core/kernel/src/types.ts:155

Parameters
ParameterType
idstring
Returns

Promise<FiberView>

fiber()
fiber(id): FiberView | undefined;

Defined in: packages/core/kernel/src/types.ts:148

Parameters
ParameterType
idstring
Returns

FiberView | undefined

fibers()
fibers(): FiberView[];

Defined in: packages/core/kernel/src/types.ts:147

Returns

FiberView[]

getValue()
getValue<T>(key): T | undefined;

Defined in: packages/core/kernel/src/types.ts:143

Current value of a key, or undefined when nobody provides it (soft dependency — declare it in manifest.optional; no trust check).

Type Parameters
Type ParameterDefault type
Tunknown
Parameters
ParameterType
keystring
Returns

T | undefined

has()
has(key): boolean;

Defined in: packages/core/kernel/src/types.ts:141

Parameters
ParameterType
keystring
Returns

boolean

keys()
keys(): KeyMeta[];

Defined in: packages/core/kernel/src/types.ts:139

Returns

KeyMeta[]

observeKeys()
observeKeys(observer): () => void;

Defined in: packages/core/kernel/src/types.ts:146

Parameters
ParameterType
observerKeyObserver
Returns

() => void

observePoint()
observePoint<T>(point, observer): () => void;

Defined in: packages/core/kernel/src/types.ts:145

Type Parameters
Type ParameterDefault type
Tunknown
Parameters
ParameterType
pointstring
observerPointObserver<T>
Returns

() => void

points()
points(): ExtensionPointMeta[];

Defined in: packages/core/kernel/src/types.ts:140

Returns

ExtensionPointMeta[]

propose()
propose(manifest, auth): Promise<FiberView>;

Defined in: packages/core/kernel/src/types.ts:154

Install (or update to a new version) an agent plugin. Requires a valid authorization.

Parameters
ParameterType
manifestPluginManifest
authMountAuthorization
Returns

Promise<FiberView>

settle()
settle(): Promise<void>;

Defined in: packages/core/kernel/src/types.ts:160

Run the reconciler until quiescence.

Returns

Promise<void>

uninstall()
uninstall(
   id, 
   reason?, 
   opts?
): Promise<void>;

Defined in: packages/core/kernel/src/types.ts:158

Remove a plugin. System plugins are refused unless force (composition-root use only).

Parameters
ParameterType
idstring
reason?string
opts?{ force?: boolean; }
opts.force?boolean
Returns

Promise<void>


KernelEvent

Defined in: packages/core/kernel/src/types.ts:186

Indexable

[k: string]: unknown

Properties

seq
seq: number;

Defined in: packages/core/kernel/src/types.ts:187

ts
ts: number;

Defined in: packages/core/kernel/src/types.ts:188

type
type: string;

Defined in: packages/core/kernel/src/types.ts:189


KernelOptions

Defined in: packages/core/kernel/src/kernel.ts:23

Properties

blobs?
optional blobs?: BlobStore;

Defined in: packages/core/kernel/src/kernel.ts:26

executor?
optional executor?: Executor;

Defined in: packages/core/kernel/src/kernel.ts:27

log?
optional log?: EventLog;

Defined in: packages/core/kernel/src/kernel.ts:25

logger?
optional logger?: (...args) => void;

Defined in: packages/core/kernel/src/kernel.ts:29

Hook for kernel diagnostics (plugin logs, undo failures).

Parameters
ParameterType
argsunknown[]
Returns

void

name?
optional name?: string;

Defined in: packages/core/kernel/src/kernel.ts:24


KeyMeta

Defined in: packages/core/kernel/src/types.ts:15

A typed slot in the shared registry table (a Cordis “coeffect key”).

Properties

description?
optional description?: string;

Defined in: packages/core/kernel/src/types.ts:17

minConsumerTrust?
optional minConsumerTrust?: Trust;

Defined in: packages/core/kernel/src/types.ts:21

Minimum trust a fiber needs to inject/get/invoke this key. Default: agent (open).

minProviderTrust?
optional minProviderTrust?: Trust;

Defined in: packages/core/kernel/src/types.ts:19

Minimum trust a fiber needs to provide this key. Default: agent (open).

name
name: string;

Defined in: packages/core/kernel/src/types.ts:16


MountAuthorization

Defined in: packages/core/kernel/src/types.ts:118

A token proving a system-trust fiber vouched for mounting an agent plugin.

Properties

integrity
integrity: string | null;

Defined in: packages/core/kernel/src/types.ts:121

issuedBy
issuedBy: string;

Defined in: packages/core/kernel/src/types.ts:123

nonce
nonce: string;

Defined in: packages/core/kernel/src/types.ts:122

pluginId
pluginId: string;

Defined in: packages/core/kernel/src/types.ts:119

version
version: string;

Defined in: packages/core/kernel/src/types.ts:120


PluginBundle

Defined in: packages/core/kernel/src/types.ts:64

Properties

code
code: string;

Defined in: packages/core/kernel/src/types.ts:66

format
format: "esm";

Defined in: packages/core/kernel/src/types.ts:65

integrity?
optional integrity?: string;

Defined in: packages/core/kernel/src/types.ts:68

sha-256 hex of code, filled by the loader if absent.


PluginContext

Defined in: packages/core/kernel/src/types.ts:97

The only thing a plugin (in-process or remote) can do to the host.

Properties

id
readonly id: string;

Defined in: packages/core/kernel/src/types.ts:98

kernel?
readonly optional kernel?: KernelApi;

Defined in: packages/core/kernel/src/types.ts:108

Present only for system-trust fibers.

trust
readonly trust: Trust;

Defined in: packages/core/kernel/src/types.ts:99

Methods

contribute()
contribute(point, item): Promise<void>;

Defined in: packages/core/kernel/src/types.ts:105

Contribute an item to an extension point (revertible effect). Resolves once the point owner accepted it.

Parameters
ParameterType
pointstring
itemunknown
Returns

Promise<void>

get()
get<T>(key): T;

Defined in: packages/core/kernel/src/types.ts:101

Read a key declared in inject.

Type Parameters
Type ParameterDefault type
Tunknown
Parameters
ParameterType
keystring
Returns

T

log()
log(...args): void;

Defined in: packages/core/kernel/src/types.ts:106

Parameters
ParameterType
argsunknown[]
Returns

void

provide()
provide(key, value): void;

Defined in: packages/core/kernel/src/types.ts:103

Provide a key (revertible effect).

Parameters
ParameterType
keystring
valueunknown
Returns

void


PluginManifest

Defined in: packages/core/kernel/src/types.ts:42

What a plugin declares. Trust is NOT here — the loader assigns it.

Properties

contributes?
optional contributes?: Record<string, unknown[]>;

Defined in: packages/core/kernel/src/types.ts:59

Declarative contributions, applied by the kernel with no code execution.

description?
optional description?: string;

Defined in: packages/core/kernel/src/types.ts:45

entry?
optional entry?: PluginBundle;

Defined in: packages/core/kernel/src/types.ts:61

Optional code; executed through the Executor capability, never in-process.

id
id: string;

Defined in: packages/core/kernel/src/types.ts:43

inject?
optional inject?: string[];

Defined in: packages/core/kernel/src/types.ts:47

Keys this plugin needs. It activates only when all are provided (σ ⊨ d).

optional?
optional optional?: string[];

Defined in: packages/core/kernel/src/types.ts:53

Keys this plugin uses when present but can live without (soft dependency): read them with ctx.kernel.getValue(key), which returns undefined while nobody provides them. Declared so the dependency is visible to the kernel, the admin surface and the quality gate, not hidden in code.

provide?
optional provide?: string[];

Defined in: packages/core/kernel/src/types.ts:55

Keys this plugin promises to provide. Used for dependency ordering.

scopes?
optional scopes?: string[];

Defined in: packages/core/kernel/src/types.ts:57

Capability scopes requested (interpreted by the judge, e.g. ‘net’, ‘ui’, ‘collection:write’).

version
version: string;

Defined in: packages/core/kernel/src/types.ts:44


PointObserver

Defined in: packages/core/kernel/src/types.ts:127

Listener for extension point changes (the point owner reacts to contributions).

Type Parameters

Type ParameterDefault type
Tunknown

Properties

added?
optional added?: (c) => void | Promise<void>;

Defined in: packages/core/kernel/src/types.ts:128

Parameters
ParameterType
cContribution<T>
Returns

void | Promise<void>

removed?
optional removed?: (c) => void | Promise<void>;

Defined in: packages/core/kernel/src/types.ts:129

Parameters
ParameterType
cContribution<T>
Returns

void | Promise<void>


SystemPlugin

Defined in: packages/core/kernel/src/types.ts:112

An in-process (system-trust) plugin.

Properties

activate
activate: (ctx) => void | Promise<void>;

Defined in: packages/core/kernel/src/types.ts:114

Parameters
ParameterType
ctxPluginContext
Returns

void | Promise<void>

manifest
manifest: PluginManifest;

Defined in: packages/core/kernel/src/types.ts:113


TargetEntry

Defined in: packages/core/kernel/src/log.ts:37

The target view: what the log says should exist. A pure fold, order-independent in its terminal state.

Properties

enabled
enabled: boolean;

Defined in: packages/core/kernel/src/log.ts:41

integrity
integrity: string | null;

Defined in: packages/core/kernel/src/log.ts:40

manifest
manifest: PluginManifest;

Defined in: packages/core/kernel/src/log.ts:38

trust
trust: Trust;

Defined in: packages/core/kernel/src/log.ts:39

Type Aliases

EffectKind

type EffectKind = "provide" | "contribute";

Defined in: packages/core/kernel/src/types.ts:72

Closed effect vocabulary. Undo is derived by the kernel, never written by a plugin.


FiberState

type FiberState = "inactive" | "loading" | "active" | "unloading" | "failed";

Defined in: packages/core/kernel/src/types.ts:80


KernelErrorCode

type KernelErrorCode = 
  | "UNDECLARED_ACCESS"
  | "INACTIVE_ACCESS"
  | "TRUST_VIOLATION"
  | "ALREADY_PROVIDED"
  | "UNKNOWN_POINT"
  | "INVALID_ITEM"
  | "UNAUTHORIZED"
  | "NOT_FOUND"
  | "NO_EXECUTOR"
  | "RESERVED_ID";

Defined in: packages/core/kernel/src/errors.ts:3


KeyObserver

type KeyObserver = (event, key, value) => void;

Defined in: packages/core/kernel/src/types.ts:132

Parameters

ParameterType
event"provided" | "withdrawn"
keystring
valueunknown

Returns

void


Trust

type Trust = "system" | "agent";

Defined in: packages/core/kernel/src/types.ts:10

Who vouched for a plugin. Set by the loader, never by the manifest.

Variables

FN_MARKER

const FN_MARKER: "$fn" = '$fn';

Defined in: packages/core/kernel/src/marshal.ts:8


TRUST_RANK

const TRUST_RANK: Record<Trust, number>;

Defined in: packages/core/kernel/src/types.ts:12

Functions

assertTrust()

function assertTrust(
   actual, 
   required, 
   what
): void;

Defined in: packages/core/kernel/src/errors.ts:24

Parameters

ParameterType
actualTrust
requiredTrust | undefined
whatstring

Returns

void


foldTarget()

function foldTarget(events): Map<string, TargetEntry>;

Defined in: packages/core/kernel/src/log.ts:44

Parameters

ParameterType
eventsKernelEvent[]

Returns

Map<string, TargetEntry>


sha256()

function sha256(text): Promise<string>;

Defined in: packages/core/kernel/src/log.ts:30

Parameters

ParameterType
textstring

Returns

Promise<string>


toJson()

function toJson(value): unknown;

Defined in: packages/core/kernel/src/marshal.ts:24

Drop functions when sending host values to plugin code (they get undefined).

Parameters

ParameterType
valueunknown

Returns

unknown


unmarshal()

function unmarshal(value, instance): unknown;

Defined in: packages/core/kernel/src/marshal.ts:10

Parameters

ParameterType
valueunknown
instanceExecutorInstance

Returns

unknown

@sms/model-claude

Interfaces

ClaudeModelOptions

Defined in: packages/drivers/model/claude/src/index.ts:37

Properties

cwd?
optional cwd?: string;

Defined in: packages/drivers/model/claude/src/index.ts:42

Working directory for the CLI process (it has no filesystem tools here; cosmetic).

debug?
optional debug?: (...args) => void;

Defined in: packages/drivers/model/claude/src/index.ts:44

Optional debug logger.

Parameters
ParameterType
argsunknown[]
Returns

void

effort?
optional effort?: "low" | "medium" | "high" | "xhigh" | "max";

Defined in: packages/drivers/model/claude/src/index.ts:40

model?
optional model?: string;

Defined in: packages/drivers/model/claude/src/index.ts:39

Model alias or id understood by the claude CLI (e.g. ‘opus’, ‘sonnet’, ‘claude-opus-5’).

Functions

createClaudeModel()

function createClaudeModel(opts?): ModelService & {
  close: void;
};

Defined in: packages/drivers/model/claude/src/index.ts:206

Parameters

ParameterType
optsClaudeModelOptions

Returns

ModelService & { close: void; }


createClaudeModelPlugin()

function createClaudeModelPlugin(opts?): SystemPlugin;

Defined in: packages/drivers/model/claude/src/index.ts:217

Parameters

ParameterType
optsClaudeModelOptions

Returns

SystemPlugin

@sms/model-claude-api

Interfaces

ClaudeApiModelOptions

Defined in: packages/drivers/model/claude-api/src/index.ts:24

Properties

apiKey?
optional apiKey?: string;

Defined in: packages/drivers/model/claude-api/src/index.ts:26

Default: ANTHROPIC_API_KEY from the environment (Node). In a Worker pass env.ANTHROPIC_API_KEY.

baseURL?
optional baseURL?: string;

Defined in: packages/drivers/model/claude-api/src/index.ts:33

client?
optional client?: Pick<Anthropic, "messages">;

Defined in: packages/drivers/model/claude-api/src/index.ts:37

Bring your own client (Bedrock/Vertex/Foundry clients expose the same messages.create).

debug?
optional debug?: (...args) => void;

Defined in: packages/drivers/model/claude-api/src/index.ts:38

Parameters
ParameterType
argsunknown[]
Returns

void

effort?
optional effort?: "low" | "medium" | "high" | "xhigh" | "max";

Defined in: packages/drivers/model/claude-api/src/index.ts:32

output_config.effort; the API default is ‘high’.

fetch?
optional fetch?: {
  (input, init?): Promise<Response>;
  (input, init?): Promise<Response>;
};

Defined in: packages/drivers/model/claude-api/src/index.ts:35

Inject a fetch (tests, proxies).

Call Signature
(input, init?): Promise<Response>;

MDN Reference

Parameters
ParameterType
inputRequestInfo | URL
init?RequestInit
Returns

Promise<Response>

Call Signature
(input, init?): Promise<Response>;

MDN Reference

Parameters
ParameterType
inputstring | Request | URL
init?RequestInit
Returns

Promise<Response>

maxTokens?
optional maxTokens?: number;

Defined in: packages/drivers/model/claude-api/src/index.ts:30

Default: 16000.

model?
optional model?: string;

Defined in: packages/drivers/model/claude-api/src/index.ts:28

Default: ‘claude-opus-5’.

Functions

claudeApiModelPlugin()

function claudeApiModelPlugin(opts?): SystemPlugin;

Defined in: packages/drivers/model/claude-api/src/index.ts:141

createClaudeApiModel wrapped as the system plugin that provides model.

Parameters

ParameterType
optsClaudeApiModelOptions

Returns

SystemPlugin


createClaudeApiModel()

function createClaudeApiModel(opts?): ModelService;

Defined in: packages/drivers/model/claude-api/src/index.ts:136

Parameters

ParameterType
optsClaudeApiModelOptions

Returns

ModelService

@sms/model-gpt

Interfaces

GptModelOptions

Defined in: packages/drivers/model/gpt/src/index.ts:49

Properties

codexPath?
optional codexPath?: string;

Defined in: packages/drivers/model/gpt/src/index.ts:58

Path to a codex binary; default: the one bundled with @openai/codex-sdk.

cwd?
optional cwd?: string;

Defined in: packages/drivers/model/gpt/src/index.ts:54

Working directory for the CLI’s sandbox. Default: an empty temp directory.

debug?
optional debug?: (...args) => void;

Defined in: packages/drivers/model/gpt/src/index.ts:62

Optional debug logger.

Parameters
ParameterType
argsunknown[]
Returns

void

effort?
optional effort?: ModelReasoningEffort;

Defined in: packages/drivers/model/gpt/src/index.ts:52

env?
optional env?: Record<string, string | undefined>;

Defined in: packages/drivers/model/gpt/src/index.ts:60

Environment for the CLI process; default: process.env. Must contain the login (~/.codex).

model?
optional model?: string;

Defined in: packages/drivers/model/gpt/src/index.ts:51

Model id understood by the Codex CLI (e.g. ‘gpt-5.5’, ‘gpt-5.5-codex’). Default: the CLI’s.

sandbox?
optional sandbox?: SandboxMode;

Defined in: packages/drivers/model/gpt/src/index.ts:56

Codex sandbox for its built-in shell tools. Default: ‘read-only’.

Functions

createGptModel()

function createGptModel(opts?): ModelService & {
  close: void;
};

Defined in: packages/drivers/model/gpt/src/index.ts:274

Parameters

ParameterType
optsGptModelOptions

Returns

ModelService & { close: void; }


createGptModelPlugin()

function createGptModelPlugin(opts?): SystemPlugin;

Defined in: packages/drivers/model/gpt/src/index.ts:294

Parameters

ParameterType
optsGptModelOptions

Returns

SystemPlugin

@sms/model-gpt-api

Interfaces

GptApiModelOptions

Defined in: packages/drivers/model/gpt-api/src/index.ts:34

Properties

apiKey?
optional apiKey?: string;

Defined in: packages/drivers/model/gpt-api/src/index.ts:36

Default: OPENAI_API_KEY from the environment (Node). In a Worker pass env.OPENAI_API_KEY.

baseURL?
optional baseURL?: string;

Defined in: packages/drivers/model/gpt-api/src/index.ts:43

client?
optional client?: Pick<OpenAI, "responses">;

Defined in: packages/drivers/model/gpt-api/src/index.ts:47

Bring your own client (Azure etc. expose the same responses.create).

debug?
optional debug?: (...args) => void;

Defined in: packages/drivers/model/gpt-api/src/index.ts:48

Parameters
ParameterType
argsunknown[]
Returns

void

effort?
optional effort?: "low" | "medium" | "high" | "minimal";

Defined in: packages/drivers/model/gpt-api/src/index.ts:42

reasoning.effort.

fetch?
optional fetch?: {
  (input, init?): Promise<Response>;
  (input, init?): Promise<Response>;
};

Defined in: packages/drivers/model/gpt-api/src/index.ts:45

Inject a fetch (tests, proxies).

Call Signature
(input, init?): Promise<Response>;

MDN Reference

Parameters
ParameterType
inputRequestInfo | URL
init?RequestInit
Returns

Promise<Response>

Call Signature
(input, init?): Promise<Response>;

MDN Reference

Parameters
ParameterType
inputstring | Request | URL
init?RequestInit
Returns

Promise<Response>

maxOutputTokens?
optional maxOutputTokens?: number;

Defined in: packages/drivers/model/gpt-api/src/index.ts:40

Default: 16000.

model?
optional model?: string;

Defined in: packages/drivers/model/gpt-api/src/index.ts:38

Default: ‘gpt-5.5’.

Functions

createGptApiModel()

function createGptApiModel(opts?): ModelService;

Defined in: packages/drivers/model/gpt-api/src/index.ts:149

Parameters

ParameterType
optsGptApiModelOptions

Returns

ModelService


gptApiModelPlugin()

function gptApiModelPlugin(opts?): SystemPlugin;

Defined in: packages/drivers/model/gpt-api/src/index.ts:154

createGptApiModel wrapped as the system plugin that provides model.

Parameters

ParameterType
optsGptApiModelOptions

Returns

SystemPlugin

@sms/model-gpt-oauth

Classes

CodexTokenManager

Defined in: packages/drivers/model/gpt-oauth/src/auth.ts:99

Hands out a valid access token, refreshing (once, shared across concurrent callers) when it is about to expire.

Constructors

Constructor
new CodexTokenManager(opts): CodexTokenManager;

Defined in: packages/drivers/model/gpt-oauth/src/auth.ts:104

Parameters
ParameterType
optsTokenManagerOptions
Returns

CodexTokenManager

Methods

current()
current(): Promise<{
  accessToken: string;
  accountId: string | undefined;
}>;

Defined in: packages/drivers/model/gpt-oauth/src/auth.ts:109

Returns

Promise<{ accessToken: string; accountId: string | undefined; }>

refresh()
refresh(): Promise<CodexTokens>;

Defined in: packages/drivers/model/gpt-oauth/src/auth.ts:119

Force a refresh (after a 401). Concurrent calls share one request.

Returns

Promise<CodexTokens>

Interfaces

CodexTokens

Defined in: packages/drivers/model/gpt-oauth/src/auth.ts:10

Codex OAuth tokens: parsing, expiry, refresh. No Node APIs — runs in Workers.

The tokens come from codex login (~/.codex/auth.json, see ./node) or any store you give the driver. Access tokens are JWTs; the ChatGPT account id lives in their https://api.openai.com/auth claim. Refresh uses Codex CLI’s public OAuth client, so the refresh token from codex login keeps working here.

Properties

accessToken
accessToken: string;

Defined in: packages/drivers/model/gpt-oauth/src/auth.ts:11

accountId?
optional accountId?: string;

Defined in: packages/drivers/model/gpt-oauth/src/auth.ts:14

Defaults to the chatgpt_account_id claim of the access token.

idToken?
optional idToken?: string;

Defined in: packages/drivers/model/gpt-oauth/src/auth.ts:15

refreshToken
refreshToken: string;

Defined in: packages/drivers/model/gpt-oauth/src/auth.ts:12


GptOauthModelOptions

Defined in: packages/drivers/model/gpt-oauth/src/index.ts:45

Properties

baseURL?
optional baseURL?: string;

Defined in: packages/drivers/model/gpt-oauth/src/index.ts:59

Default: https://chatgpt.com/backend-api/codex

debug?
optional debug?: (...args) => void;

Defined in: packages/drivers/model/gpt-oauth/src/index.ts:62

Parameters
ParameterType
argsunknown[]
Returns

void

effort?
optional effort?: "low" | "medium" | "high" | "minimal";

Defined in: packages/drivers/model/gpt-oauth/src/index.ts:55

reasoning.effort.

fetch?
optional fetch?: {
  (input, init?): Promise<Response>;
  (input, init?): Promise<Response>;
};

Defined in: packages/drivers/model/gpt-oauth/src/index.ts:61

Inject a fetch (tests, proxies). Used for the model calls and the token refresh.

Call Signature
(input, init?): Promise<Response>;

MDN Reference

Parameters
ParameterType
inputRequestInfo | URL
init?RequestInit
Returns

Promise<Response>

Call Signature
(input, init?): Promise<Response>;

MDN Reference

Parameters
ParameterType
inputstring | Request | URL
init?RequestInit
Returns

Promise<Response>

maxOutputTokens?
optional maxOutputTokens?: number;

Defined in: packages/drivers/model/gpt-oauth/src/index.ts:57

Only sent when set; Codex itself does not send one.

model?
optional model?: string;

Defined in: packages/drivers/model/gpt-oauth/src/index.ts:53

Default: ‘gpt-5.5’.

store?
optional store?: TokenStore;

Defined in: packages/drivers/model/gpt-oauth/src/index.ts:51

Persist refreshed tokens (and seed them when tokens is not given).

tokens?
optional tokens?: string | Record<string, unknown> | CodexTokens;

Defined in: packages/drivers/model/gpt-oauth/src/index.ts:49

Tokens from codex login — a CodexTokens, or the text/object of ~/.codex/auth.json.

unofficial
unofficial: true;

Defined in: packages/drivers/model/gpt-oauth/src/index.ts:47

Acknowledge that this talks to an undocumented endpoint with your personal login. Required.


TokenManagerOptions

Defined in: packages/drivers/model/gpt-oauth/src/auth.ts:89

Properties

fetch?
optional fetch?: {
  (input, init?): Promise<Response>;
  (input, init?): Promise<Response>;
};

Defined in: packages/drivers/model/gpt-oauth/src/auth.ts:92

Call Signature
(input, init?): Promise<Response>;

MDN Reference

Parameters
ParameterType
inputRequestInfo | URL
init?RequestInit
Returns

Promise<Response>

Call Signature
(input, init?): Promise<Response>;

MDN Reference

Parameters
ParameterType
inputstring | Request | URL
init?RequestInit
Returns

Promise<Response>

now?
optional now?: () => number;

Defined in: packages/drivers/model/gpt-oauth/src/auth.ts:95

Returns

number

skewMs?
optional skewMs?: number;

Defined in: packages/drivers/model/gpt-oauth/src/auth.ts:94

Refresh this long before exp. Default 60s.

store?
optional store?: TokenStore;

Defined in: packages/drivers/model/gpt-oauth/src/auth.ts:91

tokens?
optional tokens?: CodexTokens;

Defined in: packages/drivers/model/gpt-oauth/src/auth.ts:90


TokenStore

Defined in: packages/drivers/model/gpt-oauth/src/auth.ts:19

Where refreshed tokens go (a KV namespace, a file, a DO…). load seeds the manager when no tokens were given.

Methods

load()
load(): 
  | CodexTokens
  | Promise<CodexTokens | undefined>
  | undefined;

Defined in: packages/drivers/model/gpt-oauth/src/auth.ts:20

Returns

| CodexTokens | Promise<CodexTokens | undefined> | undefined

save()
save(tokens): void | Promise<void>;

Defined in: packages/drivers/model/gpt-oauth/src/auth.ts:21

Parameters
ParameterType
tokensCodexTokens
Returns

void | Promise<void>

Variables

CODEX_BACKEND_URL

const CODEX_BACKEND_URL: "https://chatgpt.com/backend-api/codex" = 'https://chatgpt.com/backend-api/codex';

Defined in: packages/drivers/model/gpt-oauth/src/index.ts:65


CODEX_CLIENT_ID

const CODEX_CLIENT_ID: "app_EMoamEEZ73f0CkXaXp7hrann" = 'app_EMoamEEZ73f0CkXaXp7hrann';

Defined in: packages/drivers/model/gpt-oauth/src/auth.ts:24


CODEX_TOKEN_URL

const CODEX_TOKEN_URL: "https://auth.openai.com/oauth/token" = 'https://auth.openai.com/oauth/token';

Defined in: packages/drivers/model/gpt-oauth/src/auth.ts:25

Functions

accountIdOf()

function accountIdOf(tokens): string | undefined;

Defined in: packages/drivers/model/gpt-oauth/src/auth.ts:50

Parameters

ParameterType
tokensCodexTokens

Returns

string | undefined


createGptOauthModel()

function createGptOauthModel(opts): ModelService;

Defined in: packages/drivers/model/gpt-oauth/src/index.ts:254

Parameters

ParameterType
optsGptOauthModelOptions

Returns

ModelService


gptOauthModelPlugin()

function gptOauthModelPlugin(opts): SystemPlugin;

Defined in: packages/drivers/model/gpt-oauth/src/index.ts:259

createGptOauthModel wrapped as the system plugin that provides model.

Parameters

ParameterType
optsGptOauthModelOptions

Returns

SystemPlugin


jwtExpiresAt()

function jwtExpiresAt(token): number | undefined;

Defined in: packages/drivers/model/gpt-oauth/src/auth.ts:45

exp in ms, or undefined for a non-JWT token.

Parameters

ParameterType
tokenstring

Returns

number | undefined


jwtPayload()

function jwtPayload(token): Record<string, unknown>;

Defined in: packages/drivers/model/gpt-oauth/src/auth.ts:34

Parameters

ParameterType
tokenstring

Returns

Record<string, unknown>


kvTokenStore()

function kvTokenStore(kv, key?): TokenStore;

Defined in: packages/drivers/model/gpt-oauth/src/index.ts:264

A TokenStore on anything with a KV-style get/put of strings (Workers KV, a Map wrapper…).

Parameters

ParameterTypeDefault value
kv{ get: string | Promise<string | null> | null; put: void | Promise<void>; }undefined
kv.getundefined
kv.putundefined
keystring'codex-oauth'

Returns

TokenStore


parseCodexAuth()

function parseCodexAuth(json): CodexTokens;

Defined in: packages/drivers/model/gpt-oauth/src/auth.ts:57

Accepts ~/.codex/auth.json ({ tokens: { access_token, … } }) or a serialized CodexTokens.

Parameters

ParameterType
jsonstring | Record<string, unknown>

Returns

CodexTokens


toCodexAuthJson()

function toCodexAuthJson(tokens): string;

Defined in: packages/drivers/model/gpt-oauth/src/auth.ts:73

The shape codex itself writes, so a store can be shared with the CLI.

Parameters

ParameterType
tokensCodexTokens

Returns

string

@sms/model-openrouter

Interfaces

OpenRouterModelOptions

Defined in: packages/drivers/model/openrouter/src/index.ts:37

Properties

apiKey?
optional apiKey?: string;

Defined in: packages/drivers/model/openrouter/src/index.ts:39

Default: OPENROUTER_API_KEY from the environment (Node). In a Worker pass env.OPENROUTER_API_KEY.

appName?
optional appName?: string;

Defined in: packages/drivers/model/openrouter/src/index.ts:49

Sent as X-Title — shows your app on openrouter.ai rankings.

baseURL?
optional baseURL?: string;

Defined in: packages/drivers/model/openrouter/src/index.ts:47

Default: ‘https://openrouter.ai/api/v1’.

client?
optional client?: Pick<OpenAI, "chat">;

Defined in: packages/drivers/model/openrouter/src/index.ts:55

Bring your own client (anything exposing chat.completions.create).

debug?
optional debug?: (...args) => void;

Defined in: packages/drivers/model/openrouter/src/index.ts:56

Parameters
ParameterType
argsunknown[]
Returns

void

effort?
optional effort?: "low" | "medium" | "high" | "xhigh" | "max" | "minimal" | "none";

Defined in: packages/drivers/model/openrouter/src/index.ts:45

OpenRouter’s unified reasoning.effort (ignored by models without reasoning).

fetch?
optional fetch?: {
  (input, init?): Promise<Response>;
  (input, init?): Promise<Response>;
};

Defined in: packages/drivers/model/openrouter/src/index.ts:53

Inject a fetch (tests, proxies).

Call Signature
(input, init?): Promise<Response>;

MDN Reference

Parameters
ParameterType
inputRequestInfo | URL
init?RequestInit
Returns

Promise<Response>

Call Signature
(input, init?): Promise<Response>;

MDN Reference

Parameters
ParameterType
inputstring | Request | URL
init?RequestInit
Returns

Promise<Response>

maxOutputTokens?
optional maxOutputTokens?: number;

Defined in: packages/drivers/model/openrouter/src/index.ts:43

Default: 16000.

model?
optional model?: string;

Defined in: packages/drivers/model/openrouter/src/index.ts:41

OpenRouter model slug. Default: ‘anthropic/claude-sonnet-4.5’.

siteUrl?
optional siteUrl?: string;

Defined in: packages/drivers/model/openrouter/src/index.ts:51

Sent as HTTP-Referer (same purpose).

Functions

createOpenRouterModel()

function createOpenRouterModel(opts?): ModelService;

Defined in: packages/drivers/model/openrouter/src/index.ts:297

Parameters

ParameterType
optsOpenRouterModelOptions

Returns

ModelService


openRouterModelPlugin()

function openRouterModelPlugin(opts?): SystemPlugin;

Defined in: packages/drivers/model/openrouter/src/index.ts:302

createOpenRouterModel wrapped as the system plugin that provides model.

Parameters

ParameterType
optsOpenRouterModelOptions

Returns

SystemPlugin

@sms/objects-r2

Interfaces

R2BucketLike

Defined in: packages/drivers/objects/r2/src/index.ts:27

Methods

delete()
delete(key): Promise<void>;

Defined in: packages/drivers/objects/r2/src/index.ts:35

Parameters
ParameterType
keystring
Returns

Promise<void>

get()
get(key): Promise<R2ObjectBodyLike | null>;

Defined in: packages/drivers/objects/r2/src/index.ts:33

Parameters
ParameterType
keystring
Returns

Promise<R2ObjectBodyLike | null>

head()
head(key): Promise<R2ObjectLike | null>;

Defined in: packages/drivers/objects/r2/src/index.ts:34

Parameters
ParameterType
keystring
Returns

Promise<R2ObjectLike | null>

list()
list(options?): Promise<{
  cursor?: string;
  delimitedPrefixes: string[];
  objects: R2ObjectLike[];
  truncated: boolean;
}>;

Defined in: packages/drivers/objects/r2/src/index.ts:36

Parameters
ParameterType
options?{ cursor?: string; delimiter?: string; limit?: number; prefix?: string; }
options.cursor?string
options.delimiter?string
options.limit?number
options.prefix?string
Returns

Promise<{ cursor?: string; delimitedPrefixes: string[]; objects: R2ObjectLike[]; truncated: boolean; }>

put()
put(
   key, 
   value, 
   options?
): Promise<R2ObjectLike | null>;

Defined in: packages/drivers/objects/r2/src/index.ts:28

Parameters
ParameterType
keystring
value| string | ArrayBuffer | ArrayBufferView<ArrayBufferLike> | ReadableStream<any>
options?{ customMetadata?: Record<string, string>; httpMetadata?: { contentType?: string; }; }
options.customMetadata?Record<string, string>
options.httpMetadata?{ contentType?: string; }
options.httpMetadata.contentType?string
Returns

Promise<R2ObjectLike | null>


R2ObjectBodyLike

Defined in: packages/drivers/objects/r2/src/index.ts:24

Extends

Properties

body
body: ReadableStream<Uint8Array<ArrayBufferLike>>;

Defined in: packages/drivers/objects/r2/src/index.ts:25

customMetadata?
optional customMetadata?: Record<string, string>;

Defined in: packages/drivers/objects/r2/src/index.ts:22

Inherited from

R2ObjectLike.customMetadata

etag
etag: string;

Defined in: packages/drivers/objects/r2/src/index.ts:19

Inherited from

R2ObjectLike.etag

httpMetadata?
optional httpMetadata?: {
  contentType?: string;
};

Defined in: packages/drivers/objects/r2/src/index.ts:21

contentType?
optional contentType?: string;
Inherited from

R2ObjectLike.httpMetadata

key
key: string;

Defined in: packages/drivers/objects/r2/src/index.ts:17

Inherited from

R2ObjectLike.key

size
size: number;

Defined in: packages/drivers/objects/r2/src/index.ts:18

Inherited from

R2ObjectLike.size

uploaded
uploaded: Date;

Defined in: packages/drivers/objects/r2/src/index.ts:20

Inherited from

R2ObjectLike.uploaded


R2ObjectLike

Defined in: packages/drivers/objects/r2/src/index.ts:16

Extended by

Properties

customMetadata?
optional customMetadata?: Record<string, string>;

Defined in: packages/drivers/objects/r2/src/index.ts:22

etag
etag: string;

Defined in: packages/drivers/objects/r2/src/index.ts:19

httpMetadata?
optional httpMetadata?: {
  contentType?: string;
};

Defined in: packages/drivers/objects/r2/src/index.ts:21

contentType?
optional contentType?: string;
key
key: string;

Defined in: packages/drivers/objects/r2/src/index.ts:17

size
size: number;

Defined in: packages/drivers/objects/r2/src/index.ts:18

uploaded
uploaded: Date;

Defined in: packages/drivers/objects/r2/src/index.ts:20

Functions

createR2ObjectStore()

function createR2ObjectStore(bucket): ObjectStore;

Defined in: packages/drivers/objects/r2/src/index.ts:53

Parameters

ParameterType
bucketR2BucketLike

Returns

ObjectStore

@sms/objects-s3

Classes

S3Error

Defined in: packages/drivers/objects/s3/src/index.ts:38

Extends

  • Error

Constructors

Constructor
new S3Error(
   status, 
   body, 
   method, 
   key?
): S3Error;

Defined in: packages/drivers/objects/s3/src/index.ts:41

Parameters
ParameterType
statusnumber
bodystring
methodstring
key?string
Returns

S3Error

Overrides
Error.constructor

Properties

cause?
optional cause?: unknown;

Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.error.d.ts:26

Inherited from
Error.cause
code?
readonly optional code?: string;

Defined in: packages/drivers/objects/s3/src/index.ts:40

message
message: string;

Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es5.d.ts:1077

Inherited from
Error.message
name
name: string;

Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es5.d.ts:1076

Inherited from
Error.name
stack?
optional stack?: string;

Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es5.d.ts:1078

Inherited from
Error.stack
status
readonly status: number;

Defined in: packages/drivers/objects/s3/src/index.ts:39

stackTraceLimit
static stackTraceLimit: number;

Defined in: node_modules/.pnpm/@types+node@22.20.1/node_modules/@types/node/globals.d.ts:68

The Error.stackTraceLimit property specifies the number of stack frames collected by a stack trace (whether generated by new Error().stack or Error.captureStackTrace(obj)).

The default value is 10 but may be set to any valid JavaScript number. Changes will affect any stack trace captured after the value has been changed.

If set to a non-number value, or set to a negative number, stack traces will not capture any frames.

Inherited from
Error.stackTraceLimit

Methods

captureStackTrace()
static captureStackTrace(targetObject, constructorOpt?): void;

Defined in: node_modules/.pnpm/@types+node@22.20.1/node_modules/@types/node/globals.d.ts:52

Creates a .stack property on targetObject, which when accessed returns a string representing the location in the code at which Error.captureStackTrace() was called.

const myObject = {};
Error.captureStackTrace(myObject);
myObject.stack;  // Similar to `new Error().stack`

The first line of the trace will be prefixed with ${myObject.name}: ${myObject.message}.

The optional constructorOpt argument accepts a function. If given, all frames above constructorOpt, including constructorOpt, will be omitted from the generated stack trace.

The constructorOpt argument is useful for hiding implementation details of error generation from the user. For instance:

function a() {
  b();
}

function b() {
  c();
}

function c() {
  // Create an error without stack trace to avoid calculating the stack trace twice.
  const { stackTraceLimit } = Error;
  Error.stackTraceLimit = 0;
  const error = new Error();
  Error.stackTraceLimit = stackTraceLimit;

  // Capture the stack trace above function b
  Error.captureStackTrace(error, b); // Neither function c, nor b is included in the stack trace
  throw error;
}

a();
Parameters
ParameterType
targetObjectobject
constructorOpt?Function
Returns

void

Inherited from
Error.captureStackTrace
prepareStackTrace()
static prepareStackTrace(err, stackTraces): any;

Defined in: node_modules/.pnpm/@types+node@22.20.1/node_modules/@types/node/globals.d.ts:56

Parameters
ParameterType
errError
stackTracesCallSite[]
Returns

any

See

https://v8.dev/docs/stack-trace-api#customizing-stack-traces

Inherited from
Error.prepareStackTrace

Interfaces

S3Options

Defined in: packages/drivers/objects/s3/src/index.ts:23

Properties

accessKeyId
accessKeyId: string;

Defined in: packages/drivers/objects/s3/src/index.ts:25

bucket
bucket: string;

Defined in: packages/drivers/objects/s3/src/index.ts:24

endpoint?
optional endpoint?: string;

Defined in: packages/drivers/objects/s3/src/index.ts:31

Service URL without the bucket. Default AWS (https://s3.<region>.amazonaws.com).

fetch?
optional fetch?: {
  (input, init?): Promise<Response>;
  (input, init?): Promise<Response>;
};

Defined in: packages/drivers/objects/s3/src/index.ts:35

Injected for tests. Default global fetch.

Call Signature
(input, init?): Promise<Response>;

MDN Reference

Parameters
ParameterType
inputRequestInfo | URL
init?RequestInit
Returns

Promise<Response>

Call Signature
(input, init?): Promise<Response>;

MDN Reference

Parameters
ParameterType
inputstring | Request | URL
init?RequestInit
Returns

Promise<Response>

forcePathStyle?
optional forcePathStyle?: boolean;

Defined in: packages/drivers/objects/s3/src/index.ts:33

https://host/bucket/key instead of https://bucket.host/key. Needed for MinIO and local endpoints. Default: on when endpoint is set.

region?
optional region?: string;

Defined in: packages/drivers/objects/s3/src/index.ts:29

AWS region; auto for R2, anything (e.g. us-east-1) for MinIO. Default us-east-1.

secretAccessKey
secretAccessKey: string;

Defined in: packages/drivers/objects/s3/src/index.ts:26

sessionToken?
optional sessionToken?: string;

Defined in: packages/drivers/objects/s3/src/index.ts:27


SigV4Credentials

Defined in: packages/drivers/objects/s3/src/sigv4.ts:6

AWS Signature Version 4 for S3-style requests, over WebCrypto only (Node, Workers, browsers). Bodies are signed as UNSIGNED-PAYLOAD, which S3, MinIO and R2 all accept over HTTPS (and MinIO over plain HTTP).

Properties

accessKeyId
accessKeyId: string;

Defined in: packages/drivers/objects/s3/src/sigv4.ts:7

region
region: string;

Defined in: packages/drivers/objects/s3/src/sigv4.ts:10

secretAccessKey
secretAccessKey: string;

Defined in: packages/drivers/objects/s3/src/sigv4.ts:8

service?
optional service?: string;

Defined in: packages/drivers/objects/s3/src/sigv4.ts:11

sessionToken?
optional sessionToken?: string;

Defined in: packages/drivers/objects/s3/src/sigv4.ts:9

Functions

createS3ObjectStore()

function createS3ObjectStore(opts): ObjectStore;

Defined in: packages/drivers/objects/s3/src/index.ts:66

Parameters

ParameterType
optsS3Options

Returns

ObjectStore


signRequest()

function signRequest(creds, input): Promise<Record<string, string>>;

Defined in: packages/drivers/objects/s3/src/sigv4.ts:69

Returns the headers to send: the input’s plus host, x-amz-date, x-amz-content-sha256, authorization.

Parameters

ParameterType
credsSigV4Credentials
inputSignInput

Returns

Promise<Record<string, string>>

@sms/plugin-admin-api

Interfaces

AdminApiOptions

Defined in: packages/plugins/admin-api/src/index.ts:15

Properties

prefix?
optional prefix?: string;

Defined in: packages/plugins/admin-api/src/index.ts:22

Route prefix. Default /api.

token?
optional token?: string;

Defined in: packages/plugins/admin-api/src/index.ts:20

Bearer token (or x-admin-token header) required on mutating routes. Without it — and without any admin-authorizer contribution — those routes are open: local development only.

Variables

ADMIN_ROUTES

const ADMIN_ROUTES: readonly ["GET  {p}/state           plugins, pending approvals, collections, points, keys, routes, schedules", "GET  {p}/catalog         what the agent sees: keys, extension points, contributions", "POST {p}/chat            { session?, text } → { reply, steps }            [token]", "POST {p}/chat/stream     { session?, text } → SSE of agent events         [token]", "GET  {p}/chat/:session   message history", "POST {p}/plugins/:id/enable | /disable                                    [token]", "DELETE {p}/plugins/:id   uninstall an agent plugin                        [token]", "POST {p}/approvals/:id/approve | /reject   { by? }                        [token]", "GET  {p}/events?limit=   audit log, newest first"];

Defined in: packages/plugins/admin-api/src/contract.ts:9

Functions

createAdminApiPlugin()

function createAdminApiPlugin(opts?): SystemPlugin;

Defined in: packages/plugins/admin-api/src/index.ts:44

Parameters

ParameterType
optsAdminApiOptions

Returns

SystemPlugin

References

ADMIN_AUTHORIZER_POINT

Re-exports ADMIN_AUTHORIZER_POINT


AdminAuthorizer

Re-exports AdminAuthorizer

@sms/plugin-agent-loop

Interfaces

AgentLoopOptions

Defined in: packages/plugins/agent-loop/src/index.ts:24

Properties

identity?
optional identity?: string;

Defined in: packages/plugins/agent-loop/src/index.ts:27

Extra identity text placed at the top of the system prompt.

maxSteps?
optional maxSteps?: number;

Defined in: packages/plugins/agent-loop/src/index.ts:25

sessionStore?
optional sessionStore?: AgentSessionStore;

Defined in: packages/plugins/agent-loop/src/index.ts:29

Rehydrates a session on its first chat() in this process.


AgentService

Defined in: packages/plugins/agent-loop/src/contract.ts:57

Methods

chat()
chat(sessionId, text): Promise<ChatResult>;

Defined in: packages/plugins/agent-loop/src/contract.ts:59

Run one turn to completion. Turns on the same session run one after another.

Parameters
ParameterType
sessionIdstring
textstring
Returns

Promise<ChatResult>

chatStream()
chatStream(sessionId, text): AsyncIterable<AgentEvent>;

Defined in: packages/plugins/agent-loop/src/contract.ts:65

The same turn as live events: model deltas (text_delta, thinking_delta when the driver exposes reasoning), tool_start/tool_end, each transcript message, then done or error. The turn keeps running if the consumer stops reading.

Parameters
ParameterType
sessionIdstring
textstring
Returns

AsyncIterable<AgentEvent>

history()
history(sessionId): ModelMessage[];

Defined in: packages/plugins/agent-loop/src/contract.ts:66

Parameters
ParameterType
sessionIdstring
Returns

ModelMessage[]

reset()
reset(sessionId): void;

Defined in: packages/plugins/agent-loop/src/contract.ts:67

Parameters
ParameterType
sessionIdstring
Returns

void

systemPrompt()
systemPrompt(): string;

Defined in: packages/plugins/agent-loop/src/contract.ts:68

Returns

string

tools()
tools(): ModelTool[];

Defined in: packages/plugins/agent-loop/src/contract.ts:69

Returns

ModelTool[]


AgentSessionStore

Defined in: packages/plugins/agent-loop/src/contract.ts:77

Where a session’s prior turns come from when the loop does not have them in memory (a fresh process, an evicted Durable Object), and — through append — where they go as they are produced. Without append an application can still diff agent.history() after each chat().

Methods

append()?
optional append(sessionId, messages): Promise<void>;

Defined in: packages/plugins/agent-loop/src/contract.ts:80

Optional: called with each message as the loop appends it (user text, assistant turn, tool results).

Parameters
ParameterType
sessionIdstring
messagesModelMessage[]
Returns

Promise<void>

load()
load(sessionId): Promise<
  | ModelMessage[]
| undefined>;

Defined in: packages/plugins/agent-loop/src/contract.ts:78

Parameters
ParameterType
sessionIdstring
Returns

Promise< | ModelMessage[] | undefined>


ChatResult

Defined in: packages/plugins/agent-loop/src/contract.ts:52

Properties

reply
reply: string;

Defined in: packages/plugins/agent-loop/src/contract.ts:53

steps
steps: ChatStep[];

Defined in: packages/plugins/agent-loop/src/contract.ts:54


ChatStep

Defined in: packages/plugins/agent-loop/src/contract.ts:45

Properties

error?
optional error?: boolean;

Defined in: packages/plugins/agent-loop/src/contract.ts:49

input
input: unknown;

Defined in: packages/plugins/agent-loop/src/contract.ts:47

output
output: string;

Defined in: packages/plugins/agent-loop/src/contract.ts:48

tool
tool: string;

Defined in: packages/plugins/agent-loop/src/contract.ts:46


PromptSection

Defined in: packages/plugins/agent-loop/src/contract.ts:39

Properties

order?
optional order?: number;

Defined in: packages/plugins/agent-loop/src/contract.ts:42

section
section: string;

Defined in: packages/plugins/agent-loop/src/contract.ts:40

text
text: string | (() => string);

Defined in: packages/plugins/agent-loop/src/contract.ts:41


Tool

Defined in: packages/plugins/agent-loop/src/contract.ts:32

Properties

description
description: string;

Defined in: packages/plugins/agent-loop/src/contract.ts:34

handler
handler: (input) => unknown;

Defined in: packages/plugins/agent-loop/src/contract.ts:36

Parameters
ParameterType
inputRecord<string, unknown>
Returns

unknown

input_schema?
optional input_schema?: Record<string, unknown>;

Defined in: packages/plugins/agent-loop/src/contract.ts:35

name
name: string;

Defined in: packages/plugins/agent-loop/src/contract.ts:33

Type Aliases

AgentEvent

type AgentEvent = 
  | Exclude<ModelEvent, {
  type: "done";
}>
  | {
  id: string;
  input: unknown;
  name: string;
  type: "tool_start";
}
  | {
  id: string;
  step: ChatStep;
  type: "tool_end";
}
  | {
  message: ModelMessage;
  type: "message";
}
  | {
  result: ChatResult;
  type: "done";
}
  | {
  message: string;
  type: "error";
};

Defined in: packages/plugins/agent-loop/src/loop.ts:16

Union Members

Exclude<ModelEvent, { type: "done"; }>


Type Literal
{
  id: string;
  input: unknown;
  name: string;
  type: "tool_start";
}

Type Literal
{
  id: string;
  step: ChatStep;
  type: "tool_end";
}

Type Literal
{
  message: ModelMessage;
  type: "message";
}

A transcript message as it is appended (user text, assistant turn, tool results).


Type Literal
{
  result: ChatResult;
  type: "done";
}

Type Literal
{
  message: string;
  type: "error";
}

Variables

AGENT_KEY

const AGENT_KEY: "agent" = 'agent';

Defined in: packages/plugins/agent-loop/src/contract.ts:10

Key under which the agent loop provides AgentService (system-only).


PROMPT_POINT

const PROMPT_POINT: "prompt" = 'prompt';

Defined in: packages/plugins/agent-loop/src/contract.ts:14

Extension point for { section, text, order? } system prompt sections.


TOOL_POINT

const TOOL_POINT: "tool" = 'tool';

Defined in: packages/plugins/agent-loop/src/contract.ts:12

Extension point for { name, description, input_schema?, handler(input) } tools.

Functions

catalog()

function catalog(kernel): unknown;

Defined in: packages/plugins/agent-loop/src/catalog.ts:5

A JSON summary of the running system for the model. Functions are shown as “[function]”.

Parameters

ParameterType
kernelKernelApi

Returns

unknown


createAgentLoopPlugin()

function createAgentLoopPlugin(opts?): SystemPlugin;

Defined in: packages/plugins/agent-loop/src/index.ts:34

Parameters

ParameterType
optsAgentLoopOptions

Returns

SystemPlugin

References

createModelPlugin

Re-exports createModelPlugin


createScriptedModel

Re-exports createScriptedModel


MODEL_KEY

Re-exports MODEL_KEY


ModelContent

Re-exports ModelContent


ModelEvent

Re-exports ModelEvent


ModelMessage

Re-exports ModelMessage


ModelRequest

Re-exports ModelRequest


ModelResponse

Re-exports ModelResponse


ModelService

Re-exports ModelService


ModelTool

Re-exports ModelTool

@sms/plugin-audit

Interfaces

AuditOptions

Defined in: packages/plugins/audit/src/index.ts:23

Properties

contextOf?
optional contextOf?: (req) => 
  | OpContext
| Promise<OpContext>;

Defined in: packages/plugins/audit/src/index.ts:25

Who is calling (same shape as the ORM’s). Default: anonymous {}.

Parameters
ParameterType
reqRouteRequest
Returns

| OpContext | Promise<OpContext>

group?
optional group?: string;

Defined in: packages/plugins/audit/src/index.ts:29

rbac group to grant access to the audit models (only when the access/rule points exist).

prefix?
optional prefix?: string;

Defined in: packages/plugins/audit/src/index.ts:27

Route prefix. Default /api/audit.


AuditService

Defined in: packages/plugins/audit/src/service.ts:25

@sms/plugin-audit/contract — the audit key, the audit-track point, the audit model names and the AuditService / AuditTrack types plus their validators. No manifest, no plugin body (createAuditPlugin lives in index.ts).

Methods

post()
post(
   model, 
   id, 
   opts, 
   ctx
): Promise<number>;

Defined in: packages/plugins/audit/src/service.ts:27

Post a message on model#id; returns the message id. The record must exist and be visible to ctx.

Parameters
ParameterType
modelstring
idnumber
optsPostOptions
ctxOpContext
Returns

Promise<number>


AuditTrack

Defined in: packages/plugins/audit/src/tracking.ts:22

Point audit-track: log changes of these fields of model. Several contributions may target one model.

Properties

fields
fields: string[];

Defined in: packages/plugins/audit/src/tracking.ts:24

model
model: string;

Defined in: packages/plugins/audit/src/tracking.ts:23


PostOptions

Defined in: packages/plugins/audit/src/service.ts:15

@sms/plugin-audit/contract — the audit key, the audit-track point, the audit model names and the AuditService / AuditTrack types plus their validators. No manifest, no plugin body (createAuditPlugin lives in index.ts).

Properties

author?
optional author?: number | null;

Defined in: packages/plugins/audit/src/service.ts:22

Author user id; defaults to ctx.userId.

body?
optional body?: string;

Defined in: packages/plugins/audit/src/service.ts:16

kind?
optional kind?: MessageKind;

Defined in: packages/plugins/audit/src/service.ts:17

snapshot?
optional snapshot?: Values;

Defined in: packages/plugins/audit/src/service.ts:20

Internal: tracked values after this message.

tracking?
optional tracking?: TrackingEntry[];

Defined in: packages/plugins/audit/src/service.ts:18


TrackingEntry

Defined in: packages/plugins/audit/src/service.ts:8

@sms/plugin-audit/contract — the audit key, the audit-track point, the audit model names and the AuditService / AuditTrack types plus their validators. No manifest, no plugin body (createAuditPlugin lives in index.ts).

Properties

field
field: string;

Defined in: packages/plugins/audit/src/service.ts:9

from
from: string | null;

Defined in: packages/plugins/audit/src/service.ts:11

label
label: string;

Defined in: packages/plugins/audit/src/service.ts:10

to
to: string | null;

Defined in: packages/plugins/audit/src/service.ts:12

Type Aliases

MessageKind

type MessageKind = "comment" | "note" | "log" | "tracking";

Defined in: packages/plugins/audit/src/service.ts:6

@sms/plugin-audit/contract — the audit key, the audit-track point, the audit model names and the AuditService / AuditTrack types plus their validators. No manifest, no plugin body (createAuditPlugin lives in index.ts).

Variables

ACTIVITY_KINDS

const ACTIVITY_KINDS: readonly ["todo", "call", "meeting", "email"];

Defined in: packages/plugins/audit/src/models.ts:11


ACTIVITY_MODEL

const ACTIVITY_MODEL: "audit_activity" = 'audit_activity';

Defined in: packages/plugins/audit/src/models.ts:5


AUDIT_ACTIVITY

const AUDIT_ACTIVITY: ModelSpec;

Defined in: packages/plugins/audit/src/models.ts:37


AUDIT_FOLLOWER

const AUDIT_FOLLOWER: ModelSpec;

Defined in: packages/plugins/audit/src/models.ts:59


AUDIT_KEY

const AUDIT_KEY: "audit" = 'audit';

Defined in: packages/plugins/audit/src/contract.ts:21

Key under which the audit plugin provides AuditService.


AUDIT_MESSAGE

const AUDIT_MESSAGE: ModelSpec;

Defined in: packages/plugins/audit/src/models.ts:15


auditPlugin

const auditPlugin: SystemPlugin;

Defined in: packages/plugins/audit/src/index.ts:87


FOLLOWER_MODEL

const FOLLOWER_MODEL: "audit_follower" = 'audit_follower';

Defined in: packages/plugins/audit/src/models.ts:6


MESSAGE_MODEL

const MESSAGE_MODEL: "audit_message" = 'audit_message';

Defined in: packages/plugins/audit/src/models.ts:4


TRACK_POINT

const TRACK_POINT: "audit-track" = 'audit-track';

Defined in: packages/plugins/audit/src/tracking.ts:19


USER_KINDS

const USER_KINDS: readonly ["comment", "note"];

Defined in: packages/plugins/audit/src/models.ts:9

Kinds a user may post through the API; log and tracking are system-generated.

Functions

createAuditPlugin()

function createAuditPlugin(opts?): SystemPlugin;

Defined in: packages/plugins/audit/src/index.ts:38

Parameters

ParameterType
optsAuditOptions

Returns

SystemPlugin


labelOf()

function labelOf(f, v): string | null;

Defined in: packages/plugins/audit/src/tracking.ts:53

Human label of a value as stored in a snapshot.

Parameters

ParameterType
fFieldSpec
vunknown

Returns

string | null


validateAuditTrack()

function validateAuditTrack(item): void;

Defined in: packages/plugins/audit/src/tracking.ts:27

Parameters

ParameterType
itemunknown

Returns

void

@sms/plugin-auth

Interfaces

AdminAuthorizer

Defined in: packages/plugins/auth/src/contract.ts:57

Properties

name
name: string;

Defined in: packages/plugins/auth/src/contract.ts:58

Methods

authorize()
authorize(req): boolean | Promise<boolean>;

Defined in: packages/plugins/auth/src/contract.ts:59

Parameters
ParameterType
reqRouteRequest
Returns

boolean | Promise<boolean>


AuthOptions

Defined in: packages/plugins/auth/src/index.ts:28

Properties

bootstrapAdmin?
optional bootstrapAdmin?: {
  login: string;
  name?: string;
  password: string;
};

Defined in: packages/plugins/auth/src/index.ts:30

Created on first boot when the user table is empty.

login
login: string;
name?
optional name?: string;
password
password: string;
iterations?
optional iterations?: number;

Defined in: packages/plugins/auth/src/index.ts:36

PBKDF2 iterations for new hashes. Default 100k; lower only in tests.

prefix?
optional prefix?: string;

Defined in: packages/plugins/auth/src/index.ts:34

Route prefix. Default /api/auth.

sessionTtlMs?
optional sessionTtlMs?: number;

Defined in: packages/plugins/auth/src/index.ts:32

Session lifetime. Default 30 days.


IdentityAdminService

Defined in: packages/plugins/auth/src/contract.ts:39

Key identity-admin — system-only user management.

Methods

activate()
activate(id): Promise<void>;

Defined in: packages/plugins/auth/src/contract.ts:46

Parameters
ParameterType
idnumber
Returns

Promise<void>

create()
create(input): Promise<User>;

Defined in: packages/plugins/auth/src/contract.ts:40

Parameters
ParameterType
input{ isAdmin?: boolean; login: string; name?: string; password: string; }
input.isAdmin?boolean
input.loginstring
input.name?string
input.passwordstring
Returns

Promise<User>

deactivate()
deactivate(id): Promise<void>;

Defined in: packages/plugins/auth/src/contract.ts:45

Also ends the user’s sessions.

Parameters
ParameterType
idnumber
Returns

Promise<void>

setAdmin()
setAdmin(id, isAdmin): Promise<void>;

Defined in: packages/plugins/auth/src/contract.ts:43

Parameters
ParameterType
idnumber
isAdminboolean
Returns

Promise<void>

setPassword()
setPassword(id, password): Promise<void>;

Defined in: packages/plugins/auth/src/contract.ts:42

Also ends the user’s sessions.

Parameters
ParameterType
idnumber
passwordstring
Returns

Promise<void>


IdentityService

Defined in: packages/plugins/auth/src/contract.ts:26

Key identity — no secrets; agent plugins may inject it.

Methods

login()
login(login, password): Promise<Session | undefined>;

Defined in: packages/plugins/auth/src/contract.ts:32

Verify a password and open a session; undefined on bad credentials or an inactive user.

Parameters
ParameterType
loginstring
passwordstring
Returns

Promise<Session | undefined>

logout()
logout(token): Promise<void>;

Defined in: packages/plugins/auth/src/contract.ts:33

Parameters
ParameterType
tokenstring
Returns

Promise<void>

session()
session(token): Promise<Session | undefined>;

Defined in: packages/plugins/auth/src/contract.ts:35

The session behind a token, if live.

Parameters
ParameterType
tokenstring
Returns

Promise<Session | undefined>

user()
user(id): Promise<User | undefined>;

Defined in: packages/plugins/auth/src/contract.ts:30

Parameters
ParameterType
idnumber
Returns

Promise<User | undefined>

users()
users(): Promise<User[]>;

Defined in: packages/plugins/auth/src/contract.ts:29

Returns

Promise<User[]>

whoami()
whoami(req): Promise<User | undefined>;

Defined in: packages/plugins/auth/src/contract.ts:28

The user behind a request’s session cookie / bearer token; undefined when logged out, expired or deactivated.

Parameters
ParameterType
reqRouteRequest
Returns

Promise<User | undefined>


Session

Defined in: packages/plugins/auth/src/contract.ts:19

Properties

expiresAt
expiresAt: string;

Defined in: packages/plugins/auth/src/contract.ts:22

token
token: string;

Defined in: packages/plugins/auth/src/contract.ts:20

user
user: User;

Defined in: packages/plugins/auth/src/contract.ts:21


User

Defined in: packages/plugins/auth/src/contract.ts:10

Properties

active
active: boolean;

Defined in: packages/plugins/auth/src/contract.ts:15

createdAt
createdAt: string;

Defined in: packages/plugins/auth/src/contract.ts:16

id
id: number;

Defined in: packages/plugins/auth/src/contract.ts:11

isAdmin
isAdmin: boolean;

Defined in: packages/plugins/auth/src/contract.ts:14

login
login: string;

Defined in: packages/plugins/auth/src/contract.ts:12

name
name: string;

Defined in: packages/plugins/auth/src/contract.ts:13

Variables

ADMIN_AUTHORIZER_POINT

const ADMIN_AUTHORIZER_POINT: "admin-authorizer" = 'admin-authorizer';

Defined in: packages/plugins/auth/src/contract.ts:55

Extension point (system-only) for AdminAuthorizer items admitting requests to the mutating admin routes without the token. Owned by whichever of auth / admin-api activates first; auth contributes auth-session.


IDENTITY_ADMIN_KEY

const IDENTITY_ADMIN_KEY: "identity-admin" = 'identity-admin';

Defined in: packages/plugins/auth/src/contract.ts:50


IDENTITY_KEY

const IDENTITY_KEY: "identity" = 'identity';

Defined in: packages/plugins/auth/src/contract.ts:49


const SESSION_COOKIE: "sms_session" = 'sms_session';

Defined in: packages/plugins/auth/src/routes.ts:13

Functions

createAuthPlugin()

function createAuthPlugin(opts?): SystemPlugin;

Defined in: packages/plugins/auth/src/index.ts:78

Parameters

ParameterType
optsAuthOptions

Returns

SystemPlugin


hashPassword()

function hashPassword(password, iterations?): Promise<string>;

Defined in: packages/plugins/auth/src/crypto.ts:31

pbkdf2$<iterations>$<salt>$<hash> — self-describing so iterations can be raised later.

Parameters

ParameterTypeDefault value
passwordstringundefined
iterationsnumberPBKDF2_ITERATIONS

Returns

Promise<string>


tokenOf()

function tokenOf(req): string | undefined;

Defined in: packages/plugins/auth/src/routes.ts:20

The session token a request carries: cookie first, then authorization: Bearer.

Parameters

ParameterType
reqRouteRequest

Returns

string | undefined


verifyPassword()

function verifyPassword(password, stored): Promise<boolean>;

Defined in: packages/plugins/auth/src/crypto.ts:44

Parameters

ParameterType
passwordstring
storedstring

Returns

Promise<boolean>

@sms/plugin-automation

Interfaces

AutomationOptions

Defined in: packages/plugins/automation/src/types.ts:33

Properties

scheduleLimit?
optional scheduleLimit?: number;

Defined in: packages/plugins/automation/src/types.ts:37

Max records one scheduled run considers. Default 500.

tickEveryMs?
optional tickEveryMs?: number;

Defined in: packages/plugins/automation/src/types.ts:35

How often the host-driven scheduler checks for due scheduled automations. Default 60 000.


AutomationSpec

Defined in: packages/plugins/automation/src/types.ts:20

Runs after records of model are created/written/unlinked, or on a schedule. watch narrows write triggers to those fields; filter must match the record after the op (ignored on unlink). Actions run with a sudo context.

Properties

action
action: AutomationAction;

Defined in: packages/plugins/automation/src/types.ts:29

active?
optional active?: boolean;

Defined in: packages/plugins/automation/src/types.ts:30

everyMinutes?
optional everyMinutes?: number;

Defined in: packages/plugins/automation/src/types.ts:28

For trigger schedule: interval in minutes.

filter?
optional filter?: Domain;

Defined in: packages/plugins/automation/src/types.ts:26

id
id: string;

Defined in: packages/plugins/automation/src/types.ts:21

label
label: string;

Defined in: packages/plugins/automation/src/types.ts:22

model
model: string;

Defined in: packages/plugins/automation/src/types.ts:23

trigger
trigger: AutomationTrigger;

Defined in: packages/plugins/automation/src/types.ts:24

watch?
optional watch?: string[];

Defined in: packages/plugins/automation/src/types.ts:25

Type Aliases

AutomationAction

type AutomationAction = 
  | {
  args?: Values;
  kind: "method";
  method: string;
}
  | {
  kind: "update";
  values: Values;
}
  | {
  body: string;
  kind: "message";
}
  | {
  handler: (env, ids) => unknown | Promise<unknown>;
  kind: "handler";
};

Defined in: packages/plugins/automation/src/types.ts:8

Union Members

Type Literal
{
  args?: Values;
  kind: "method";
  method: string;
}

Type Literal
{
  kind: "update";
  values: Values;
}

Type Literal
{
  body: string;
  kind: "message";
}

Posts a note on every matching record through the audit key (no-op when audit is absent).


Type Literal
{
  handler: (env, ids) => unknown | Promise<unknown>;
  kind: "handler";
}

AutomationTrigger

type AutomationTrigger = "create" | "write" | "create_or_write" | "unlink" | "schedule";

Defined in: packages/plugins/automation/src/types.ts:6

Variables

AUTOMATION_POINT

const AUTOMATION_POINT: "automation" = 'automation';

Defined in: packages/plugins/automation/src/types.ts:4

@sms/plugin-automation/contract — the automation point, its item types and validator, and the table the scheduled runs live in. No manifest, no plugin body (createAutomationPlugin lives in index.ts).


AUTOMATION_RUN_TABLE

const AUTOMATION_RUN_TABLE: "au_automation_run" = 'au_automation_run';

Defined in: packages/plugins/automation/src/schedule.ts:10


automationPlugin

const automationPlugin: SystemPlugin;

Defined in: packages/plugins/automation/src/index.ts:83

Functions

createAutomationPlugin()

function createAutomationPlugin(opts?): SystemPlugin;

Defined in: packages/plugins/automation/src/index.ts:42

Parameters

ParameterType
optsAutomationOptions

Returns

SystemPlugin


validateAutomation()

function validateAutomation(item): void;

Defined in: packages/plugins/automation/src/types.ts:57

@sms/plugin-automation/contract — the automation point, its item types and validator, and the table the scheduled runs live in. No manifest, no plugin body (createAutomationPlugin lives in index.ts).

Parameters

ParameterType
itemunknown

Returns

void

@sms/plugin-collections

Interfaces

CollectionFieldContribution

Defined in: packages/plugins/collections/src/contract.ts:23

Properties

collection
collection: string;

Defined in: packages/plugins/collections/src/contract.ts:24

field
field: Field;

Defined in: packages/plugins/collections/src/contract.ts:25


CollectionHook

Defined in: packages/plugins/collections/src/contract.ts:30

Properties

collection
collection: string;

Defined in: packages/plugins/collections/src/contract.ts:31

handler
handler: (record, previous?) => unknown;

Defined in: packages/plugins/collections/src/contract.ts:33

Parameters
ParameterType
recordRecord<string, unknown>
previous?Record<string, unknown>
Returns

unknown

on
on: HookEvent;

Defined in: packages/plugins/collections/src/contract.ts:32


CollectionSchema

Defined in: packages/plugins/collections/src/contract.ts:17

Properties

description?
optional description?: string;

Defined in: packages/plugins/collections/src/contract.ts:19

fields
fields: Field[];

Defined in: packages/plugins/collections/src/contract.ts:20

name
name: string;

Defined in: packages/plugins/collections/src/contract.ts:18


CollectionsService

Defined in: packages/plugins/collections/src/contract.ts:38

Methods

create()
create(name, data): Promise<Record<string, unknown>>;

Defined in: packages/plugins/collections/src/contract.ts:46

Parameters
ParameterType
namestring
dataRecord<string, unknown>
Returns

Promise<Record<string, unknown>>

get()
get(name, id): Promise<Record<string, unknown> | undefined>;

Defined in: packages/plugins/collections/src/contract.ts:45

Parameters
ParameterType
namestring
idnumber
Returns

Promise<Record<string, unknown> | undefined>

list()
list(name, opts?): Promise<Record<string, unknown>[]>;

Defined in: packages/plugins/collections/src/contract.ts:41

Parameters
ParameterType
namestring
opts?{ desc?: boolean; limit?: number; orderBy?: string; where?: Record<string, unknown>; }
opts.desc?boolean
opts.limit?number
opts.orderBy?string
opts.where?Record<string, unknown>
Returns

Promise<Record<string, unknown>[]>

names()
names(): string[];

Defined in: packages/plugins/collections/src/contract.ts:39

Returns

string[]

remove()
remove(name, id): Promise<boolean>;

Defined in: packages/plugins/collections/src/contract.ts:48

Parameters
ParameterType
namestring
idnumber
Returns

Promise<boolean>

schema()
schema(name): CollectionSchema | undefined;

Defined in: packages/plugins/collections/src/contract.ts:40

Parameters
ParameterType
namestring
Returns

CollectionSchema | undefined

update()
update(
   name, 
   id, 
   data
): Promise<Record<string, unknown>>;

Defined in: packages/plugins/collections/src/contract.ts:47

Parameters
ParameterType
namestring
idnumber
dataRecord<string, unknown>
Returns

Promise<Record<string, unknown>>


Field

Defined in: packages/plugins/collections/src/contract.ts:9

Properties

default?
optional default?: unknown;

Defined in: packages/plugins/collections/src/contract.ts:13

description?
optional description?: string;

Defined in: packages/plugins/collections/src/contract.ts:14

name
name: string;

Defined in: packages/plugins/collections/src/contract.ts:10

required?
optional required?: boolean;

Defined in: packages/plugins/collections/src/contract.ts:12

type
type: FieldType;

Defined in: packages/plugins/collections/src/contract.ts:11

Type Aliases

FieldType

type FieldType = "text" | "integer" | "real" | "boolean" | "json";

Defined in: packages/plugins/collections/src/contract.ts:7


HookEvent

type HookEvent = "create" | "update" | "remove";

Defined in: packages/plugins/collections/src/contract.ts:28


Record_

type Record_ = Record<string, unknown>;

Defined in: packages/plugins/collections/src/contract.ts:36

Variables

COLLECTION_FIELD_POINT

const COLLECTION_FIELD_POINT: "collection-field" = 'collection-field';

Defined in: packages/plugins/collections/src/contract.ts:53


COLLECTION_HOOK_POINT

const COLLECTION_HOOK_POINT: "collection-hook" = 'collection-hook';

Defined in: packages/plugins/collections/src/contract.ts:54


COLLECTION_POINT

const COLLECTION_POINT: "collection" = 'collection';

Defined in: packages/plugins/collections/src/contract.ts:52


COLLECTIONS_KEY

const COLLECTIONS_KEY: "collections" = 'collections';

Defined in: packages/plugins/collections/src/contract.ts:51


collectionsPlugin

const collectionsPlugin: SystemPlugin;

Defined in: packages/plugins/collections/src/index.ts:30

Functions

validateField()

function validateField(f): asserts f is Field;

Defined in: packages/plugins/collections/src/contract.ts:59

Parameters

ParameterType
funknown

Returns

asserts f is Field


validateSchema()

function validateSchema(s): asserts s is CollectionSchema;

Defined in: packages/plugins/collections/src/contract.ts:68

Parameters

ParameterType
sunknown

Returns

asserts s is CollectionSchema

References

Contribution

Re-exports Contribution

@sms/plugin-http

Classes

HttpError

Defined in: packages/plugins/http/src/contract.ts:85

Throw from a route handler to answer with a specific status/kind instead of a 500.

Extends

  • Error

Constructors

Constructor
new HttpError(
   status, 
   message, 
   kind?
): HttpError;

Defined in: packages/plugins/http/src/contract.ts:88

Parameters
ParameterType
statusnumber
messagestring
kindstring
Returns

HttpError

Overrides
Error.constructor

Properties

cause?
optional cause?: unknown;

Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.error.d.ts:26

Inherited from
Error.cause
kind
readonly kind: string;

Defined in: packages/plugins/http/src/contract.ts:87

message
message: string;

Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es5.d.ts:1077

Inherited from
Error.message
name
name: string;

Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es5.d.ts:1076

Inherited from
Error.name
stack?
optional stack?: string;

Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es5.d.ts:1078

Inherited from
Error.stack
status
readonly status: number;

Defined in: packages/plugins/http/src/contract.ts:86

stackTraceLimit
static stackTraceLimit: number;

Defined in: node_modules/.pnpm/@types+node@22.20.1/node_modules/@types/node/globals.d.ts:68

The Error.stackTraceLimit property specifies the number of stack frames collected by a stack trace (whether generated by new Error().stack or Error.captureStackTrace(obj)).

The default value is 10 but may be set to any valid JavaScript number. Changes will affect any stack trace captured after the value has been changed.

If set to a non-number value, or set to a negative number, stack traces will not capture any frames.

Inherited from
Error.stackTraceLimit

Methods

captureStackTrace()
static captureStackTrace(targetObject, constructorOpt?): void;

Defined in: node_modules/.pnpm/@types+node@22.20.1/node_modules/@types/node/globals.d.ts:52

Creates a .stack property on targetObject, which when accessed returns a string representing the location in the code at which Error.captureStackTrace() was called.

const myObject = {};
Error.captureStackTrace(myObject);
myObject.stack;  // Similar to `new Error().stack`

The first line of the trace will be prefixed with ${myObject.name}: ${myObject.message}.

The optional constructorOpt argument accepts a function. If given, all frames above constructorOpt, including constructorOpt, will be omitted from the generated stack trace.

The constructorOpt argument is useful for hiding implementation details of error generation from the user. For instance:

function a() {
  b();
}

function b() {
  c();
}

function c() {
  // Create an error without stack trace to avoid calculating the stack trace twice.
  const { stackTraceLimit } = Error;
  Error.stackTraceLimit = 0;
  const error = new Error();
  Error.stackTraceLimit = stackTraceLimit;

  // Capture the stack trace above function b
  Error.captureStackTrace(error, b); // Neither function c, nor b is included in the stack trace
  throw error;
}

a();
Parameters
ParameterType
targetObjectobject
constructorOpt?Function
Returns

void

Inherited from
Error.captureStackTrace
prepareStackTrace()
static prepareStackTrace(err, stackTraces): any;

Defined in: node_modules/.pnpm/@types+node@22.20.1/node_modules/@types/node/globals.d.ts:56

Parameters
ParameterType
errError
stackTracesCallSite[]
Returns

any

See

https://v8.dev/docs/stack-trace-api#customizing-stack-traces

Inherited from
Error.prepareStackTrace

Interfaces

ErrorBody

Defined in: packages/plugins/http/src/contract.ts:68

The one error shape every baseline route speaks: { error: { message, kind } }. kind is a short machine-readable tag a client can switch on (auth, not_found, validation, internal, …).

Properties

error
error: {
  kind: string;
  message: string;
  plugin?: string;
};

Defined in: packages/plugins/http/src/contract.ts:69

kind
kind: string;
message
message: string;
plugin?
optional plugin?: string;

HttpService

Defined in: packages/plugins/http/src/contract.ts:131

Methods

handle()
handle(request): Promise<Response>;

Defined in: packages/plugins/http/src/contract.ts:132

Parameters
ParameterType
requestRequest
Returns

Promise<Response>

routes()
routes(): {
  description?: string;
  method: string;
  owner: string;
  path: string;
}[];

Defined in: packages/plugins/http/src/contract.ts:133

Returns

{ description?: string; method: string; owner: string; path: string; }[]


Route

Defined in: packages/plugins/http/src/contract.ts:124

Properties

description?
optional description?: string;

Defined in: packages/plugins/http/src/contract.ts:127

handler
handler: (req) => unknown;

Defined in: packages/plugins/http/src/contract.ts:128

Parameters
ParameterType
reqRouteRequest
Returns

unknown

method
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "*";

Defined in: packages/plugins/http/src/contract.ts:125

path
path: string;

Defined in: packages/plugins/http/src/contract.ts:126


RouteRequest

Defined in: packages/plugins/http/src/contract.ts:14

JSON-safe request view, so agent plugins (across the executor boundary) can handle routes too.

Properties

body
body: unknown;

Defined in: packages/plugins/http/src/contract.ts:20

headers
headers: Record<string, string>;

Defined in: packages/plugins/http/src/contract.ts:19

method
method: string;

Defined in: packages/plugins/http/src/contract.ts:15

params
params: Record<string, string>;

Defined in: packages/plugins/http/src/contract.ts:17

path
path: string;

Defined in: packages/plugins/http/src/contract.ts:16

query
query: Record<string, string>;

Defined in: packages/plugins/http/src/contract.ts:18

Type Aliases

RouteResult

type RouteResult = Response | unknown;

Defined in: packages/plugins/http/src/contract.ts:27

A handler returns a Response (use the json() / html() / text() helpers) or any JSON value, which is sent as 200 application/json. Handlers running in an executor can only return JSON values.

Variables

HTTP_KEY

const HTTP_KEY: "http" = 'http';

Defined in: packages/plugins/http/src/contract.ts:9

Key under which the http plugin provides HttpService.


httpPlugin

const httpPlugin: SystemPlugin;

Defined in: packages/plugins/http/src/index.ts:43


ROUTE_POINT

const ROUTE_POINT: "route" = 'route';

Defined in: packages/plugins/http/src/contract.ts:11

Extension point for { method, path, handler(req) } items.

Functions

bodyOf()

function bodyOf(req): Record<string, unknown>;

Defined in: packages/plugins/http/src/contract.ts:119

The JSON object body of a request, or {} — for handlers that take { ...fields }.

Parameters

ParameterType
reqRouteRequest

Returns

Record<string, unknown>


cookieValue()

function cookieValue(req, name): string | undefined;

Defined in: packages/plugins/http/src/contract.ts:97

Value of one cookie on a request view (cookie header), or undefined.

Parameters

ParameterType
reqRouteRequest
namestring

Returns

string | undefined


errorJson()

function errorJson(
   message, 
   status?, 
   kind?
): Response;

Defined in: packages/plugins/http/src/contract.ts:72

Parameters

ParameterTypeDefault value
messagestringundefined
statusnumber500
kindstring...

Returns

Response


html()

function html(body, status?): Response;

Defined in: packages/plugins/http/src/contract.ts:32

Parameters

ParameterTypeDefault value
bodystringundefined
statusnumber200

Returns

Response


json()

function json(
   body, 
   status?, 
   headers?
): Response;

Defined in: packages/plugins/http/src/contract.ts:30

Parameters

ParameterTypeDefault value
bodyunknownundefined
statusnumber200
headersRecord<string, string>{}

Returns

Response


matchPath()

function matchPath(pattern, path): Record<string, string> | null;

Defined in: packages/plugins/http/src/contract.ts:151

Parameters

ParameterType
patternstring
pathstring

Returns

Record<string, string> | null


serializeCookie()

function serializeCookie(
   name, 
   value, 
   opts?
): string;

Defined in: packages/plugins/http/src/contract.ts:106

A set-cookie header value. Defaults: HttpOnly, SameSite=Lax, Path=/. maxAge 0 deletes.

Parameters

ParameterType
namestring
valuestring
opts{ maxAge?: number; path?: string; sameSite?: "Lax" | "Strict" | "None"; secure?: boolean; }
opts.maxAge?number
opts.path?string
opts.sameSite?"Lax" | "Strict" | "None"
opts.secure?boolean

Returns

string


sse()

function sse(events, status?): Response;

Defined in: packages/plugins/http/src/contract.ts:47

Server-sent events: each item is one data: <json> frame, written as soon as it is produced. If the iterable throws, the stream ends with { type: 'error', message } so a client always sees a terminal frame. The producer is not cancelled when the client goes away — the loop keeps it running on purpose.

Parameters

ParameterTypeDefault value
eventsAsyncIterable<unknown>undefined
statusnumber200

Returns

Response


text()

function text(body, status?): Response;

Defined in: packages/plugins/http/src/contract.ts:34

Parameters

ParameterTypeDefault value
bodystringundefined
statusnumber200

Returns

Response


toResponse()

function toResponse(result): Response;

Defined in: packages/plugins/http/src/contract.ts:168

Parameters

ParameterType
resultunknown

Returns

Response


validateRoute()

function validateRoute(item): void;

Defined in: packages/plugins/http/src/contract.ts:138

Parameters

ParameterType
itemunknown

Returns

void

@sms/plugin-judge

Interfaces

Gate

Defined in: packages/plugins/judge/src/contract.ts:25

Properties

description?
optional description?: string;

Defined in: packages/plugins/judge/src/contract.ts:27

name
name: string;

Defined in: packages/plugins/judge/src/contract.ts:26

Methods

run()
run(ctx): 
  | string
  | GateResult
  | Promise<string | GateResult | undefined>
  | undefined;

Defined in: packages/plugins/judge/src/contract.ts:28

Parameters
ParameterType
ctxGateContext
Returns

| string | GateResult | Promise<string | GateResult | undefined> | undefined


GateContext

Defined in: packages/plugins/judge/src/contract.ts:15

Properties

executor?
optional executor?: Executor;

Defined in: packages/plugins/judge/src/contract.ts:18

kernel
kernel: KernelApi;

Defined in: packages/plugins/judge/src/contract.ts:17

manifest
manifest: PluginManifest;

Defined in: packages/plugins/judge/src/contract.ts:16


Invariant

Defined in: packages/plugins/judge/src/contract.ts:31

Properties

description?
optional description?: string;

Defined in: packages/plugins/judge/src/contract.ts:33

name
name: string;

Defined in: packages/plugins/judge/src/contract.ts:32

Methods

check()
check(kernel): void | Promise<void>;

Defined in: packages/plugins/judge/src/contract.ts:35

Throw to fail. Runs after every mount; a failure rolls the mount back.

Parameters
ParameterType
kernelKernelApi
Returns

void | Promise<void>


JudgeOptions

Defined in: packages/plugins/judge/src/index.ts:23

Properties

agentIdPrefix?
optional agentIdPrefix?: string;

Defined in: packages/plugins/judge/src/index.ts:31

Id prefix agent plugins must use. Default ‘agent.’.

autoApprove?
optional autoApprove?: boolean;

Defined in: packages/plugins/judge/src/index.ts:33

Skip human approval entirely (unattended mode).

executor?
optional executor?: Executor;

Defined in: packages/plugins/judge/src/index.ts:29

Executor for the load gate (throwaway instances). Defaults to the kernel’s executor.

gateTimeoutMs?
optional gateTimeoutMs?: number;

Defined in: packages/plugins/judge/src/index.ts:34

sensitivePoints?
optional sensitivePoints?: string[];

Defined in: packages/plugins/judge/src/index.ts:27

Extension points whose contributions require human approval (dsh approves the UI half).

sensitiveScopes?
optional sensitiveScopes?: string[];

Defined in: packages/plugins/judge/src/index.ts:25

Scopes that require human approval.


JudgeService

Defined in: packages/plugins/judge/src/contract.ts:57

Methods

approve()
approve(pluginId, by): Promise<Verdict>;

Defined in: packages/plugins/judge/src/contract.ts:60

Parameters
ParameterType
pluginIdstring
bystring
Returns

Promise<Verdict>

gates()
gates(): {
  description?: string;
  name: string;
  owner: string;
}[];

Defined in: packages/plugins/judge/src/contract.ts:62

Returns

{ description?: string; name: string; owner: string; }[]

pending()
pending(): PendingApproval[];

Defined in: packages/plugins/judge/src/contract.ts:59

Returns

PendingApproval[]

reject()
reject(
   pluginId, 
   by, 
   reason?
): Promise<Verdict>;

Defined in: packages/plugins/judge/src/contract.ts:61

Parameters
ParameterType
pluginIdstring
bystring
reason?string
Returns

Promise<Verdict>

submit()
submit(manifest, submittedBy): Promise<Verdict>;

Defined in: packages/plugins/judge/src/contract.ts:58

Parameters
ParameterType
manifestPluginManifest
submittedBystring
Returns

Promise<Verdict>


PendingApproval

Defined in: packages/plugins/judge/src/contract.ts:51

Properties

manifest
manifest: PluginManifest;

Defined in: packages/plugins/judge/src/contract.ts:52

submittedAt
submittedAt: number;

Defined in: packages/plugins/judge/src/contract.ts:54

verdict
verdict: Verdict;

Defined in: packages/plugins/judge/src/contract.ts:53


Verdict

Defined in: packages/plugins/judge/src/contract.ts:40

Properties

fiber?
optional fiber?: FiberView;

Defined in: packages/plugins/judge/src/contract.ts:47

gates
gates: GateResult[];

Defined in: packages/plugins/judge/src/contract.ts:44

pluginId
pluginId: string;

Defined in: packages/plugins/judge/src/contract.ts:41

reason?
optional reason?: string;

Defined in: packages/plugins/judge/src/contract.ts:45

sensitive?
optional sensitive?: string[];

Defined in: packages/plugins/judge/src/contract.ts:46

status
status: VerdictStatus;

Defined in: packages/plugins/judge/src/contract.ts:43

submittedBy
submittedBy: string;

Defined in: packages/plugins/judge/src/contract.ts:48

version
version: string;

Defined in: packages/plugins/judge/src/contract.ts:42

Type Aliases

GateResult

type GateResult = 
  | {
  gate: string;
  pass: true;
  report?: string;
}
  | {
  gate: string;
  pass: false;
  report: string;
};

Defined in: packages/plugins/judge/src/contract.ts:21


VerdictStatus

type VerdictStatus = "mounted" | "needs-human" | "rejected" | "failed";

Defined in: packages/plugins/judge/src/contract.ts:38

Variables

GATE_POINT

const GATE_POINT: "gate" = 'gate';

Defined in: packages/plugins/judge/src/contract.ts:11

Extension point for checks every agent plugin must pass before mounting (system-only).


INVARIANT_POINT

const INVARIANT_POINT: "invariant" = 'invariant';

Defined in: packages/plugins/judge/src/contract.ts:13

Extension point for properties re-checked after every mount (system-only).


JUDGE_KEY

const JUDGE_KEY: "judge" = 'judge';

Defined in: packages/plugins/judge/src/contract.ts:9

Key under which the judge provides JudgeService (system-only).

Functions

createJudgePlugin()

function createJudgePlugin(opts?): SystemPlugin;

Defined in: packages/plugins/judge/src/index.ts:37

Parameters

ParameterType
optsJudgeOptions

Returns

SystemPlugin

@sms/plugin-meta

Interfaces

ActionSpec

Defined in: packages/plugins/meta/src/types.ts:37

Point action. Opens a model in the given views.

Properties

context?
optional context?: Values;

Defined in: packages/plugins/meta/src/types.ts:47

defaultFilters?
optional defaultFilters?: string[];

Defined in: packages/plugins/meta/src/types.ts:49

Default filters/groupby to activate (search filter names).

domain?
optional domain?: Domain;

Defined in: packages/plugins/meta/src/types.ts:46

groups?
optional groups?: string[];

Defined in: packages/plugins/meta/src/types.ts:51

Only these groups see it.

help?
optional help?: string;

Defined in: packages/plugins/meta/src/types.ts:52

id
id: string;

Defined in: packages/plugins/meta/src/types.ts:38

kind?
optional kind?: string;

Defined in: packages/plugins/meta/src/types.ts:41

‘model’ (default) opens model in views; other kinds are consumer-defined (e.g. ‘report’).

model
model: string;

Defined in: packages/plugins/meta/src/types.ts:42

name
name: string;

Defined in: packages/plugins/meta/src/types.ts:39

target?
optional target?: "current" | "new";

Defined in: packages/plugins/meta/src/types.ts:54

‘new’ opens in a dialog. Default ‘current’.

viewIds?
optional viewIds?: Partial<Record<ViewKind, string>>;

Defined in: packages/plugins/meta/src/types.ts:45

Optional explicit view ids per kind.

views
views: ViewKind[];

Defined in: packages/plugins/meta/src/types.ts:43


CompiledView

Defined in: packages/plugins/meta/src/types.ts:75

A compiled view: base arch with all inherit ops applied.

Properties

arch
arch: ViewNode;

Defined in: packages/plugins/meta/src/types.ts:79

id
id: string;

Defined in: packages/plugins/meta/src/types.ts:76

kind
kind: ViewKind;

Defined in: packages/plugins/meta/src/types.ts:78

model
model: string;

Defined in: packages/plugins/meta/src/types.ts:77


Defined in: packages/plugins/meta/src/types.ts:70

The resolved menu tree.

Extends

Properties

action?
optional action?: string;

Defined in: packages/plugins/meta/src/types.ts:62

Inherited from

MenuSpec.action

children
children: MenuNode[];

Defined in: packages/plugins/meta/src/types.ts:71

color?
optional color?: string;

Defined in: packages/plugins/meta/src/types.ts:65

Inherited from

MenuSpec.color

groups?
optional groups?: string[];

Defined in: packages/plugins/meta/src/types.ts:66

Inherited from

MenuSpec.groups

icon?
optional icon?: string;

Defined in: packages/plugins/meta/src/types.ts:64

Inherited from

MenuSpec.icon

id
id: string;

Defined in: packages/plugins/meta/src/types.ts:59

Inherited from

MenuSpec.id

label
label: string;

Defined in: packages/plugins/meta/src/types.ts:60

Inherited from

MenuSpec.label

parent?
optional parent?: string;

Defined in: packages/plugins/meta/src/types.ts:61

Inherited from

MenuSpec.parent

sequence?
optional sequence?: number;

Defined in: packages/plugins/meta/src/types.ts:63

Inherited from

MenuSpec.sequence


Defined in: packages/plugins/meta/src/types.ts:58

Point menu. A root menu (no parent) is an “app”.

Extended by

Properties

action?
optional action?: string;

Defined in: packages/plugins/meta/src/types.ts:62

color?
optional color?: string;

Defined in: packages/plugins/meta/src/types.ts:65

groups?
optional groups?: string[];

Defined in: packages/plugins/meta/src/types.ts:66

icon?
optional icon?: string;

Defined in: packages/plugins/meta/src/types.ts:64

id
id: string;

Defined in: packages/plugins/meta/src/types.ts:59

label
label: string;

Defined in: packages/plugins/meta/src/types.ts:60

parent?
optional parent?: string;

Defined in: packages/plugins/meta/src/types.ts:61

sequence?
optional sequence?: number;

Defined in: packages/plugins/meta/src/types.ts:63


MetaService

Defined in: packages/plugins/meta/src/types.ts:83

The meta key. view() is undefined when nothing was contributed for that model/kind (no defaults).

Methods

action()
action(id): ActionSpec | undefined;

Defined in: packages/plugins/meta/src/types.ts:86

Parameters
ParameterType
idstring
Returns

ActionSpec | undefined

actions()
actions(): ActionSpec[];

Defined in: packages/plugins/meta/src/types.ts:87

Returns

ActionSpec[]

actionsFor()
actionsFor(model): ActionSpec[];

Defined in: packages/plugins/meta/src/types.ts:88

Parameters
ParameterType
modelstring
Returns

ActionSpec[]

menu(id): MenuSpec | undefined;

Defined in: packages/plugins/meta/src/types.ts:91

Parameters
ParameterType
idstring
Returns

MenuSpec | undefined

menus(ctx): MenuNode[];

Defined in: packages/plugins/meta/src/types.ts:90

Menu tree visible to a user with these groups, sorted by sequence then label.

Parameters
ParameterType
ctx{ groups: string[]; }
ctx.groupsstring[]
Returns

MenuNode[]

view()
view(
   model, 
   kind, 
   id?
): CompiledView | undefined;

Defined in: packages/plugins/meta/src/types.ts:84

Parameters
ParameterType
modelstring
kindViewKind
id?string
Returns

CompiledView | undefined

views()
views(model): Partial<Record<ViewKind, CompiledView>>;

Defined in: packages/plugins/meta/src/types.ts:85

Parameters
ParameterType
modelstring
Returns

Partial<Record<ViewKind, CompiledView>>


ViewNode

Defined in: packages/plugins/meta/src/types.ts:7

View arch: a JSON tree. Tags and attributes are the consumer UI’s vocabulary; the baseline only compiles.

Properties

attrs?
optional attrs?: Record<string, string | number | boolean | string[] | Domain>;

Defined in: packages/plugins/meta/src/types.ts:9

children?
optional children?: ViewNode[];

Defined in: packages/plugins/meta/src/types.ts:10

tag
tag: string;

Defined in: packages/plugins/meta/src/types.ts:8


ViewOp

Defined in: packages/plugins/meta/src/types.ts:29

Patch op for view inheritance. target is a tiny selector: tag, tag[attr=value] or [attr=value], e.g. field[name=email], page[label=Notes], notebook. First match in document order.

Properties

attrs?
optional attrs?: Record<string, string | number | boolean | string[] | Domain>;

Defined in: packages/plugins/meta/src/types.ts:33

nodes?
optional nodes?: ViewNode[];

Defined in: packages/plugins/meta/src/types.ts:32

position
position: "replace" | "remove" | "before" | "after" | "inside" | "attributes";

Defined in: packages/plugins/meta/src/types.ts:31

target
target: string;

Defined in: packages/plugins/meta/src/types.ts:30


ViewSpec

Defined in: packages/plugins/meta/src/types.ts:14

Point view. Either a base view (arch) or an extension (inherit + ops) of another view id.

Properties

arch?
optional arch?: ViewNode;

Defined in: packages/plugins/meta/src/types.ts:18

id
id: string;

Defined in: packages/plugins/meta/src/types.ts:15

inherit?
optional inherit?: string;

Defined in: packages/plugins/meta/src/types.ts:19

kind
kind: ViewKind;

Defined in: packages/plugins/meta/src/types.ts:17

model
model: string;

Defined in: packages/plugins/meta/src/types.ts:16

ops?
optional ops?: ViewOp[];

Defined in: packages/plugins/meta/src/types.ts:20

priority?
optional priority?: number;

Defined in: packages/plugins/meta/src/types.ts:22

Lower wins when several base views exist for the same model/kind. Default 16.

Type Aliases

ViewKind

type ViewKind = "form" | "list" | "kanban" | "search";

Defined in: packages/plugins/meta/src/types.ts:3

Variables

ACTION_POINT

const ACTION_POINT: "action" = 'action';

Defined in: packages/plugins/meta/src/contract.ts:15


KINDS

const KINDS: ViewKind[];

Defined in: packages/plugins/meta/src/types.ts:4


const MENU_POINT: "menu" = 'menu';

Defined in: packages/plugins/meta/src/contract.ts:16


META_KEY

const META_KEY: "meta" = 'meta';

Defined in: packages/plugins/meta/src/contract.ts:13

Key under which the meta plugin provides MetaService.


metaPlugin

const metaPlugin: SystemPlugin;

Defined in: packages/plugins/meta/src/index.ts:68


VIEW_POINT

const VIEW_POINT: "view" = 'view';

Defined in: packages/plugins/meta/src/contract.ts:14

Functions

applyOps()

function applyOps(
   arch, 
   ops, 
   viewId
): ViewNode;

Defined in: packages/plugins/meta/src/compile.ts:52

Parameters

ParameterType
archViewNode
opsViewOp[]
viewIdstring

Returns

ViewNode


buildMenuTree()

function buildMenuTree(input): MenuNode[];

Defined in: packages/plugins/meta/src/menus.ts:44

Parameters

ParameterType
inputMenuInput

Returns

MenuNode[]


cloneNode()

function cloneNode(node): ViewNode;

Defined in: packages/plugins/meta/src/selector.ts:61

Parameters

ParameterType
nodeViewNode

Returns

ViewNode


compileFromBase()

function compileFromBase(base, all): CompiledView;

Defined in: packages/plugins/meta/src/compile.ts:87

Parameters

ParameterType
baseViewSpec
allViewSpec[]

Returns

CompiledView


createMetaService()

function createMetaService(regs): MetaService & {
  invalidate: void;
};

Defined in: packages/plugins/meta/src/index.ts:35

Parameters

ParameterType
regsRegistries

Returns

MetaService & { invalidate: void; }


findNode()

function findNode(root, sel): Match | undefined;

Defined in: packages/plugins/meta/src/selector.ts:45

First match in document order (depth-first).

Parameters

ParameterType
rootViewNode
selSelector

Returns

Match | undefined


parseSelector()

function parseSelector(target): Selector;

Defined in: packages/plugins/meta/src/selector.ts:22

Parameters

ParameterType
targetstring

Returns

Selector


pickBase()

function pickBase(
   all, 
   model, 
   kind, 
   id?
): ViewSpec | undefined;

Defined in: packages/plugins/meta/src/compile.ts:59

Pick the base view: lowest priority, ties broken by contribution order.

Parameters

ParameterType
allViewSpec[]
modelstring
kindViewKind
id?string

Returns

ViewSpec | undefined


validateAction()

function validateAction(item): asserts item is ActionSpec;

Defined in: packages/plugins/meta/src/validate.ts:57

Parameters

ParameterType
itemunknown

Returns

asserts item is ActionSpec


validateMenu()

function validateMenu(item): asserts item is MenuSpec;

Defined in: packages/plugins/meta/src/validate.ts:68

Parameters

ParameterType
itemunknown

Returns

asserts item is MenuSpec


validateView()

function validateView(item): asserts item is ViewSpec;

Defined in: packages/plugins/meta/src/validate.ts:37

Parameters

ParameterType
itemunknown

Returns

asserts item is ViewSpec

@sms/plugin-orm

Classes

OrmError

Defined in: packages/plugins/orm/src/core.ts:21

Errors the ORM raises on purpose; the REST layer maps kind to a status.

Extends

  • Error

Constructors

Constructor
new OrmError(kind, message): OrmError;

Defined in: packages/plugins/orm/src/core.ts:23

Parameters
ParameterType
kindOrmErrorKind
messagestring
Returns

OrmError

Overrides
Error.constructor

Properties

cause?
optional cause?: unknown;

Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.error.d.ts:26

Inherited from
Error.cause
kind
readonly kind: OrmErrorKind;

Defined in: packages/plugins/orm/src/core.ts:22

message
message: string;

Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es5.d.ts:1077

Inherited from
Error.message
name
name: string;

Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es5.d.ts:1076

Inherited from
Error.name
stack?
optional stack?: string;

Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es5.d.ts:1078

Inherited from
Error.stack
stackTraceLimit
static stackTraceLimit: number;

Defined in: node_modules/.pnpm/@types+node@22.20.1/node_modules/@types/node/globals.d.ts:68

The Error.stackTraceLimit property specifies the number of stack frames collected by a stack trace (whether generated by new Error().stack or Error.captureStackTrace(obj)).

The default value is 10 but may be set to any valid JavaScript number. Changes will affect any stack trace captured after the value has been changed.

If set to a non-number value, or set to a negative number, stack traces will not capture any frames.

Inherited from
Error.stackTraceLimit

Methods

captureStackTrace()
static captureStackTrace(targetObject, constructorOpt?): void;

Defined in: node_modules/.pnpm/@types+node@22.20.1/node_modules/@types/node/globals.d.ts:52

Creates a .stack property on targetObject, which when accessed returns a string representing the location in the code at which Error.captureStackTrace() was called.

const myObject = {};
Error.captureStackTrace(myObject);
myObject.stack;  // Similar to `new Error().stack`

The first line of the trace will be prefixed with ${myObject.name}: ${myObject.message}.

The optional constructorOpt argument accepts a function. If given, all frames above constructorOpt, including constructorOpt, will be omitted from the generated stack trace.

The constructorOpt argument is useful for hiding implementation details of error generation from the user. For instance:

function a() {
  b();
}

function b() {
  c();
}

function c() {
  // Create an error without stack trace to avoid calculating the stack trace twice.
  const { stackTraceLimit } = Error;
  Error.stackTraceLimit = 0;
  const error = new Error();
  Error.stackTraceLimit = stackTraceLimit;

  // Capture the stack trace above function b
  Error.captureStackTrace(error, b); // Neither function c, nor b is included in the stack trace
  throw error;
}

a();
Parameters
ParameterType
targetObjectobject
constructorOpt?Function
Returns

void

Inherited from
Error.captureStackTrace
prepareStackTrace()
static prepareStackTrace(err, stackTraces): any;

Defined in: node_modules/.pnpm/@types+node@22.20.1/node_modules/@types/node/globals.d.ts:56

Parameters
ParameterType
errError
stackTracesCallSite[]
Returns

any

See

https://v8.dev/docs/stack-trace-api#customizing-stack-traces

Inherited from
Error.prepareStackTrace

Interfaces

CallRequest

Defined in: packages/plugins/orm/src/types.ts:172

Properties

args?
optional args?: Values;

Defined in: packages/plugins/orm/src/types.ts:174

ids?
optional ids?: number[];

Defined in: packages/plugins/orm/src/types.ts:173


ComputedField

Defined in: packages/plugins/orm/src/types.ts:75

Computed by the model-method named compute, called with { records } (the scalar values of the ids) and returning { [id]: value }. Stored by default (queryable); store: false computes on read.

Extends

Properties

compute
compute: string;

Defined in: packages/plugins/orm/src/types.ts:80

default?
optional default?: unknown;

Defined in: packages/plugins/orm/src/types.ts:44

Default value; $uid, $now, $today are substituted from the context.

Inherited from

FieldBase.default

depends
depends: string[];

Defined in: packages/plugins/orm/src/types.ts:79

Fields (dotted paths allowed, one hop) whose change triggers recompute.

description?
optional description?: string;

Defined in: packages/plugins/orm/src/types.ts:40

Inherited from

FieldBase.description

index?
optional index?: boolean;

Defined in: packages/plugins/orm/src/types.ts:45

Inherited from

FieldBase.index

kind
kind: "computed";

Defined in: packages/plugins/orm/src/types.ts:76

label?
optional label?: string;

Defined in: packages/plugins/orm/src/types.ts:39

Inherited from

FieldBase.label

options?
optional options?: {
  label?: string;
  value: string;
}[];

Defined in: packages/plugins/orm/src/types.ts:82

label?
optional label?: string;
value
value: string;
readonly?
optional readonly?: boolean;

Defined in: packages/plugins/orm/src/types.ts:42

Inherited from

FieldBase.readonly

required?
optional required?: boolean;

Defined in: packages/plugins/orm/src/types.ts:41

Inherited from

FieldBase.required

returns
returns: ComputedReturns;

Defined in: packages/plugins/orm/src/types.ts:77

store?
optional store?: boolean;

Defined in: packages/plugins/orm/src/types.ts:81

target?
optional target?: string;

Defined in: packages/plugins/orm/src/types.ts:83


FieldBase

Defined in: packages/plugins/orm/src/types.ts:38

Extended by

Properties

default?
optional default?: unknown;

Defined in: packages/plugins/orm/src/types.ts:44

Default value; $uid, $now, $today are substituted from the context.

description?
optional description?: string;

Defined in: packages/plugins/orm/src/types.ts:40

index?
optional index?: boolean;

Defined in: packages/plugins/orm/src/types.ts:45

label?
optional label?: string;

Defined in: packages/plugins/orm/src/types.ts:39

readonly?
optional readonly?: boolean;

Defined in: packages/plugins/orm/src/types.ts:42

required?
optional required?: boolean;

Defined in: packages/plugins/orm/src/types.ts:41


GroupRow

Defined in: packages/plugins/orm/src/types.ts:163

Extends

Indexable

[key: string]: unknown

Properties

__count
__count: number;

Defined in: packages/plugins/orm/src/types.ts:164

__domain
__domain: Domain;

Defined in: packages/plugins/orm/src/types.ts:166

Domain selecting the group’s records.


HookPayload

Defined in: packages/plugins/orm/src/types.ts:142

Properties

ids
ids: number[];

Defined in: packages/plugins/orm/src/types.ts:143

records
records: Rec[];

Defined in: packages/plugins/orm/src/types.ts:145

values
values: Values;

Defined in: packages/plugins/orm/src/types.ts:144


Many2manyField

Defined in: packages/plugins/orm/src/types.ts:65

Extends

Properties

default?
optional default?: unknown;

Defined in: packages/plugins/orm/src/types.ts:44

Default value; $uid, $now, $today are substituted from the context.

Inherited from

FieldBase.default

description?
optional description?: string;

Defined in: packages/plugins/orm/src/types.ts:40

Inherited from

FieldBase.description

index?
optional index?: boolean;

Defined in: packages/plugins/orm/src/types.ts:45

Inherited from

FieldBase.index

kind
kind: "many2many";

Defined in: packages/plugins/orm/src/types.ts:66

label?
optional label?: string;

Defined in: packages/plugins/orm/src/types.ts:39

Inherited from

FieldBase.label

readonly?
optional readonly?: boolean;

Defined in: packages/plugins/orm/src/types.ts:42

Inherited from

FieldBase.readonly

required?
optional required?: boolean;

Defined in: packages/plugins/orm/src/types.ts:41

Inherited from

FieldBase.required

target
target: string;

Defined in: packages/plugins/orm/src/types.ts:67

through?
optional through?: string;

Defined in: packages/plugins/orm/src/types.ts:69

Junction table; default m_<model>__<target>__<field>. Share it between both sides for symmetry.


Many2oneField

Defined in: packages/plugins/orm/src/types.ts:54

Extends

Properties

default?
optional default?: unknown;

Defined in: packages/plugins/orm/src/types.ts:44

Default value; $uid, $now, $today are substituted from the context.

Inherited from

FieldBase.default

description?
optional description?: string;

Defined in: packages/plugins/orm/src/types.ts:40

Inherited from

FieldBase.description

index?
optional index?: boolean;

Defined in: packages/plugins/orm/src/types.ts:45

Inherited from

FieldBase.index

kind
kind: "many2one";

Defined in: packages/plugins/orm/src/types.ts:55

label?
optional label?: string;

Defined in: packages/plugins/orm/src/types.ts:39

Inherited from

FieldBase.label

onDelete?
optional onDelete?: "set-null" | "cascade" | "restrict";

Defined in: packages/plugins/orm/src/types.ts:57

readonly?
optional readonly?: boolean;

Defined in: packages/plugins/orm/src/types.ts:42

Inherited from

FieldBase.readonly

required?
optional required?: boolean;

Defined in: packages/plugins/orm/src/types.ts:41

Inherited from

FieldBase.required

target
target: string;

Defined in: packages/plugins/orm/src/types.ts:56


MethodEnv

Defined in: packages/plugins/orm/src/types.ts:121

What a method / hook / onchange handler receives. orm is absent for handlers running in an executor.

Properties

ctx
ctx: OpContext;

Defined in: packages/plugins/orm/src/types.ts:123

model
model: string;

Defined in: packages/plugins/orm/src/types.ts:122

orm?
optional orm?: OrmService;

Defined in: packages/plugins/orm/src/types.ts:124


ModelFieldContribution

Defined in: packages/plugins/orm/src/types.ts:115

Point model-field: add a field to a model declared by someone else (now or later).

Properties

model
model: string;

Defined in: packages/plugins/orm/src/types.ts:116

name
name: string;

Defined in: packages/plugins/orm/src/types.ts:117

spec
spec: FieldSpec;

Defined in: packages/plugins/orm/src/types.ts:118


ModelHook

Defined in: packages/plugins/orm/src/types.ts:136

Point model-hook: before handlers may mutate values; after handlers see the saved records.

Properties

handler
handler: (env, payload) => unknown;

Defined in: packages/plugins/orm/src/types.ts:140

Parameters
ParameterType
envMethodEnv
payloadHookPayload
Returns

unknown

model
model: string;

Defined in: packages/plugins/orm/src/types.ts:137

on
on: "create" | "write" | "unlink";

Defined in: packages/plugins/orm/src/types.ts:138

when
when: "before" | "after";

Defined in: packages/plugins/orm/src/types.ts:139


ModelMethod

Defined in: packages/plugins/orm/src/types.ts:127

Point model-method: handler(env, ids, args). For computes args = { records } and the result is { [id]: value }.

Properties

access?
optional access?: Op;

Defined in: packages/plugins/orm/src/types.ts:133

Access needed to call it. Default write.

description?
optional description?: string;

Defined in: packages/plugins/orm/src/types.ts:130

handler
handler: (env, ids, args) => unknown;

Defined in: packages/plugins/orm/src/types.ts:131

Parameters
ParameterType
envMethodEnv
idsnumber[]
argsValues
Returns

unknown

model
model: string;

Defined in: packages/plugins/orm/src/types.ts:128

name
name: string;

Defined in: packages/plugins/orm/src/types.ts:129


ModelOnchange

Defined in: packages/plugins/orm/src/types.ts:148

Point model-onchange: when field changes in a form, handler(env, values) returns a patch.

Properties

field
field: string;

Defined in: packages/plugins/orm/src/types.ts:150

handler
handler: (env, values) => Values | Promise<Values>;

Defined in: packages/plugins/orm/src/types.ts:151

Parameters
ParameterType
envMethodEnv
valuesValues
Returns

Values | Promise<Values>

model
model: string;

Defined in: packages/plugins/orm/src/types.ts:149


ModelSpec

Defined in: packages/plugins/orm/src/types.ts:105

Point model. Every model also gets id, display, created_at, updated_at, created_by, updated_by.

Properties

description?
optional description?: string;

Defined in: packages/plugins/orm/src/types.ts:107

displayField?
optional displayField?: string;

Defined in: packages/plugins/orm/src/types.ts:110

Which field feeds display. Default name when present, else id.

fields
fields: Record<string, FieldSpec>;

Defined in: packages/plugins/orm/src/types.ts:108

name
name: string;

Defined in: packages/plugins/orm/src/types.ts:106

order?
optional order?: string;

Defined in: packages/plugins/orm/src/types.ts:112

Default order. Default id desc.


One2manyField

Defined in: packages/plugins/orm/src/types.ts:59

Extends

Properties

default?
optional default?: unknown;

Defined in: packages/plugins/orm/src/types.ts:44

Default value; $uid, $now, $today are substituted from the context.

Inherited from

FieldBase.default

description?
optional description?: string;

Defined in: packages/plugins/orm/src/types.ts:40

Inherited from

FieldBase.description

index?
optional index?: boolean;

Defined in: packages/plugins/orm/src/types.ts:45

Inherited from

FieldBase.index

inverse
inverse: string;

Defined in: packages/plugins/orm/src/types.ts:63

The many2one on target pointing back.

kind
kind: "one2many";

Defined in: packages/plugins/orm/src/types.ts:60

label?
optional label?: string;

Defined in: packages/plugins/orm/src/types.ts:39

Inherited from

FieldBase.label

readonly?
optional readonly?: boolean;

Defined in: packages/plugins/orm/src/types.ts:42

Inherited from

FieldBase.readonly

required?
optional required?: boolean;

Defined in: packages/plugins/orm/src/types.ts:41

Inherited from

FieldBase.required

target
target: string;

Defined in: packages/plugins/orm/src/types.ts:61


OpContext

Defined in: packages/plugins/orm/src/types.ts:28

Who is operating. sudo bypasses the guard (system code only).

Properties

isAdmin?
optional isAdmin?: boolean;

Defined in: packages/plugins/orm/src/types.ts:30

sudo?
optional sudo?: boolean;

Defined in: packages/plugins/orm/src/types.ts:31

userId?
optional userId?: number;

Defined in: packages/plugins/orm/src/types.ts:29


OrmEventPayload

Defined in: packages/plugins/orm/src/types.ts:187

Properties

ctx
ctx: OpContext;

Defined in: packages/plugins/orm/src/types.ts:191

ids
ids: number[];

Defined in: packages/plugins/orm/src/types.ts:189

model
model: string;

Defined in: packages/plugins/orm/src/types.ts:188

values
values: Values;

Defined in: packages/plugins/orm/src/types.ts:190


OrmGuard

Defined in: packages/plugins/orm/src/types.ts:181

Row-level access seam (an RBAC plugin calls orm.setGuard). can gates the operation; domain is AND-ed into every search/read/write/unlink. Absent → everything allowed.

Methods

can()
can(q): boolean | Promise<boolean>;

Defined in: packages/plugins/orm/src/types.ts:182

Parameters
ParameterType
q{ ctx: OpContext; model: string; op: Op; }
q.ctxOpContext
q.modelstring
q.opOp
Returns

boolean | Promise<boolean>

domain()
domain(q): Domain | Promise<Domain>;

Defined in: packages/plugins/orm/src/types.ts:183

Parameters
ParameterType
q{ ctx: OpContext; model: string; op: Op; }
q.ctxOpContext
q.modelstring
q.opOp
Returns

Domain | Promise<Domain>


OrmOptions

Defined in: packages/plugins/orm/src/index.ts:28

Properties

contextOf?
optional contextOf?: (req) => OpContext | Promise<OpContext>;

Defined in: packages/plugins/orm/src/index.ts:30

Who is calling a REST route. Default: an anonymous context {} (everything the guard allows anonymous users).

Parameters
ParameterType
reqRouteRequest
Returns

OpContext | Promise<OpContext>

prefix?
optional prefix?: string;

Defined in: packages/plugins/orm/src/index.ts:32

Route prefix. Default /api/orm.


OrmService

Defined in: packages/plugins/orm/src/types.ts:196

The orm key. Every call is guard-checked unless ctx.sudo.

Methods

call()
call(
   model, 
   method, 
   req, 
   ctx
): Promise<unknown>;

Defined in: packages/plugins/orm/src/types.ts:215

Parameters
ParameterType
modelstring
methodstring
reqCallRequest
ctxOpContext
Returns

Promise<unknown>

count()
count(
   model, 
   domain, 
   ctx
): Promise<number>;

Defined in: packages/plugins/orm/src/types.ts:201

Parameters
ParameterType
modelstring
domainDomain
ctxOpContext
Returns

Promise<number>

create()
create(
   model, 
   values, 
   ctx
): Promise<number>;

Defined in: packages/plugins/orm/src/types.ts:208

Parameters
ParameterType
modelstring
valuesValues
ctxOpContext
Returns

Promise<number>

defaults()
defaults(model, ctx): Values;

Defined in: packages/plugins/orm/src/types.ts:214

Parameters
ParameterType
modelstring
ctxOpContext
Returns

Values

models()
models(): string[];

Defined in: packages/plugins/orm/src/types.ts:197

Returns

string[]

on()
on(event, listener): () => void;

Defined in: packages/plugins/orm/src/types.ts:216

Parameters
ParameterType
eventOrmEvent
listenerOrmListener
Returns

() => void

onchange()
onchange(
   model, 
   values, 
   changed, 
   ctx
): Promise<Values>;

Defined in: packages/plugins/orm/src/types.ts:213

Run the onchange handlers of changed fields and recompute non-stored fields of a saved record.

Parameters
ParameterType
modelstring
valuesValues
changedstring[]
ctxOpContext
Returns

Promise<Values>

read()
read(
   model, 
   ids, 
   fields, 
   ctx
): Promise<Rec[]>;

Defined in: packages/plugins/orm/src/types.ts:202

Parameters
ParameterType
modelstring
idsnumber[]
fieldsReadSpec
ctxOpContext
Returns

Promise<Rec[]>

readGroup()
readGroup(
   model, 
   req, 
   ctx
): Promise<GroupRow[]>;

Defined in: packages/plugins/orm/src/types.ts:211

Parameters
ParameterType
modelstring
reqReadGroupRequest
ctxOpContext
Returns

Promise<GroupRow[]>

search(
   model, 
   domain, 
   ctx, 
   opts?
): Promise<number[]>;

Defined in: packages/plugins/orm/src/types.ts:200

Parameters
ParameterType
modelstring
domainDomain
ctxOpContext
opts?SearchOptions
Returns

Promise<number[]>

searchRead()
searchRead(
   model, 
   req, 
   ctx
): Promise<{
  length: number;
  records: Rec[];
}>;

Defined in: packages/plugins/orm/src/types.ts:203

Parameters
ParameterType
modelstring
reqSearchReadRequest
ctxOpContext
Returns

Promise<{ length: number; records: Rec[]; }>

setGuard()
setGuard(guard): void;

Defined in: packages/plugins/orm/src/types.ts:217

Parameters
ParameterType
guardOrmGuard | undefined
Returns

void

spec()
spec(model): ModelSpec | undefined;

Defined in: packages/plugins/orm/src/types.ts:199

Resolved spec: fields include the implicit ones and model-field extensions.

Parameters
ParameterType
modelstring
Returns

ModelSpec | undefined

unlink(
   model, 
   ids, 
   ctx
): Promise<void>;

Defined in: packages/plugins/orm/src/types.ts:210

Parameters
ParameterType
modelstring
idsnumber[]
ctxOpContext
Returns

Promise<void>

write()
write(
   model, 
   ids, 
   values, 
   ctx
): Promise<void>;

Defined in: packages/plugins/orm/src/types.ts:209

Parameters
ParameterType
modelstring
idsnumber[]
valuesValues
ctxOpContext
Returns

Promise<void>


ReadGroupRequest

Defined in: packages/plugins/orm/src/types.ts:154

Properties

aggregates?
optional aggregates?: Record<string, string>;

Defined in: packages/plugins/orm/src/types.ts:159

{ total: 'sum:amount', n: 'count' } — sum/avg/min/max/count.

domain
domain: Domain;

Defined in: packages/plugins/orm/src/types.ts:155

groupBy
groupBy: string[];

Defined in: packages/plugins/orm/src/types.ts:157

Field names; dates accept :month / :day.

limit?
optional limit?: number;

Defined in: packages/plugins/orm/src/types.ts:160

order?
optional order?: string;

Defined in: packages/plugins/orm/src/types.ts:161


Rec

Defined in: packages/plugins/orm/src/types.ts:13

A record as returned by read: id + display + requested fields; many2one → { id, display, … } | null.

Extends

Indexable

[key: string]: unknown

Properties

display
display: string;

Defined in: packages/plugins/orm/src/types.ts:15

id
id: number;

Defined in: packages/plugins/orm/src/types.ts:14


RelatedField

Defined in: packages/plugins/orm/src/types.ts:86

Read-through of a dotted path (partner.email). Never stored.

Extends

Properties

default?
optional default?: unknown;

Defined in: packages/plugins/orm/src/types.ts:44

Default value; $uid, $now, $today are substituted from the context.

Inherited from

FieldBase.default

description?
optional description?: string;

Defined in: packages/plugins/orm/src/types.ts:40

Inherited from

FieldBase.description

index?
optional index?: boolean;

Defined in: packages/plugins/orm/src/types.ts:45

Inherited from

FieldBase.index

kind
kind: "related";

Defined in: packages/plugins/orm/src/types.ts:87

label?
optional label?: string;

Defined in: packages/plugins/orm/src/types.ts:39

Inherited from

FieldBase.label

options?
optional options?: {
  label?: string;
  value: string;
}[];

Defined in: packages/plugins/orm/src/types.ts:92

label?
optional label?: string;
value
value: string;
path
path: string;

Defined in: packages/plugins/orm/src/types.ts:88

readonly?
optional readonly?: boolean;

Defined in: packages/plugins/orm/src/types.ts:42

Inherited from

FieldBase.readonly

required?
optional required?: boolean;

Defined in: packages/plugins/orm/src/types.ts:41

Inherited from

FieldBase.required

returns?
optional returns?: ComputedReturns;

Defined in: packages/plugins/orm/src/types.ts:90

Filled by the ORM when the path resolves.

target?
optional target?: string;

Defined in: packages/plugins/orm/src/types.ts:91


ScalarField

Defined in: packages/plugins/orm/src/types.ts:47

Extends

Properties

default?
optional default?: unknown;

Defined in: packages/plugins/orm/src/types.ts:44

Default value; $uid, $now, $today are substituted from the context.

Inherited from

FieldBase.default

description?
optional description?: string;

Defined in: packages/plugins/orm/src/types.ts:40

Inherited from

FieldBase.description

index?
optional index?: boolean;

Defined in: packages/plugins/orm/src/types.ts:45

Inherited from

FieldBase.index

kind
kind: ScalarKind;

Defined in: packages/plugins/orm/src/types.ts:48

label?
optional label?: string;

Defined in: packages/plugins/orm/src/types.ts:39

Inherited from

FieldBase.label

readonly?
optional readonly?: boolean;

Defined in: packages/plugins/orm/src/types.ts:42

Inherited from

FieldBase.readonly

required?
optional required?: boolean;

Defined in: packages/plugins/orm/src/types.ts:41

Inherited from

FieldBase.required


SearchOptions

Defined in: packages/plugins/orm/src/types.ts:20

Extended by

Properties

limit?
optional limit?: number;

Defined in: packages/plugins/orm/src/types.ts:21

offset?
optional offset?: number;

Defined in: packages/plugins/orm/src/types.ts:22

order?
optional order?: string;

Defined in: packages/plugins/orm/src/types.ts:24

'name asc, id desc'


SearchReadRequest

Defined in: packages/plugins/orm/src/types.ts:168

Extends

Properties

domain
domain: Domain;

Defined in: packages/plugins/orm/src/types.ts:169

fields
fields: ReadSpec;

Defined in: packages/plugins/orm/src/types.ts:170

limit?
optional limit?: number;

Defined in: packages/plugins/orm/src/types.ts:21

Inherited from

SearchOptions.limit

offset?
optional offset?: number;

Defined in: packages/plugins/orm/src/types.ts:22

Inherited from

SearchOptions.offset

order?
optional order?: string;

Defined in: packages/plugins/orm/src/types.ts:24

'name asc, id desc'

Inherited from

SearchOptions.order


SelectionField

Defined in: packages/plugins/orm/src/types.ts:50

Extends

Properties

default?
optional default?: unknown;

Defined in: packages/plugins/orm/src/types.ts:44

Default value; $uid, $now, $today are substituted from the context.

Inherited from

FieldBase.default

description?
optional description?: string;

Defined in: packages/plugins/orm/src/types.ts:40

Inherited from

FieldBase.description

index?
optional index?: boolean;

Defined in: packages/plugins/orm/src/types.ts:45

Inherited from

FieldBase.index

kind
kind: "selection";

Defined in: packages/plugins/orm/src/types.ts:51

label?
optional label?: string;

Defined in: packages/plugins/orm/src/types.ts:39

Inherited from

FieldBase.label

options
options: {
  label?: string;
  value: string;
}[];

Defined in: packages/plugins/orm/src/types.ts:52

label?
optional label?: string;
value
value: string;
readonly?
optional readonly?: boolean;

Defined in: packages/plugins/orm/src/types.ts:42

Inherited from

FieldBase.readonly

required?
optional required?: boolean;

Defined in: packages/plugins/orm/src/types.ts:41

Inherited from

FieldBase.required

Type Aliases

Command

type Command = 
  | {
  op: "create";
  values: Values;
}
  | {
  id: number;
  op: "update";
  values: Values;
}
  | {
  id: number;
  op: "delete";
}
  | {
  id: number;
  op: "link";
}
  | {
  id: number;
  op: "unlink";
}
  | {
  ids: number[];
  op: "set";
};

Defined in: packages/plugins/orm/src/x2many.ts:5


ComputedReturns

type ComputedReturns = ScalarKind | "selection" | "many2one";

Defined in: packages/plugins/orm/src/types.ts:36


Domain

type Domain = (DomainLeaf | "&" | "|" | "!")[];

Defined in: packages/plugins/orm/src/types.ts:9


DomainLeaf

type DomainLeaf = [string, DomainOp, unknown];

Defined in: packages/plugins/orm/src/types.ts:8


DomainOp

type DomainOp = "=" | "!=" | "<" | "<=" | ">" | ">=" | "in" | "not in" | "like" | "ilike";

Defined in: packages/plugins/orm/src/types.ts:7

Filter in prefix notation: leaves [field, op, value], operators & (implicit between leaves), |, !.


FieldKind

type FieldKind = FieldSpec["kind"];

Defined in: packages/plugins/orm/src/types.ts:102


FieldSpec

type FieldSpec = 
  | ScalarField
  | SelectionField
  | Many2oneField
  | One2manyField
  | Many2manyField
  | ComputedField
  | RelatedField;

Defined in: packages/plugins/orm/src/types.ts:94


Op

type Op = "read" | "write" | "create" | "unlink";

Defined in: packages/plugins/orm/src/types.ts:33


OrmErrorKind

type OrmErrorKind = "not_found" | "forbidden" | "validation";

Defined in: packages/plugins/orm/src/core.ts:18


OrmEvent

type OrmEvent = "create" | "write" | "unlink";

Defined in: packages/plugins/orm/src/types.ts:186


OrmListener

type OrmListener = (payload) => unknown | Promise<unknown>;

Defined in: packages/plugins/orm/src/types.ts:193

Parameters

ParameterType
payloadOrmEventPayload

Returns

unknown | Promise<unknown>


ReadSpec

type ReadSpec = {
[field: string]: ReadSpec;
};

Defined in: packages/plugins/orm/src/types.ts:18

Which fields to read; for relational fields, which sub-fields ({} = id + display / ids only).

Index Signature

[field: string]: ReadSpec

ScalarKind

type ScalarKind = "char" | "text" | "int" | "float" | "bool" | "date" | "datetime" | "json";

Defined in: packages/plugins/orm/src/types.ts:35


Values

type Values = Record<string, unknown>;

Defined in: packages/plugins/orm/src/types.ts:11

Variables

DSL_PROMPT

const DSL_PROMPT: "Models (point \"model\"): { name, description?, fields: { <field>: spec }, displayField?, order? }.\nField spec: { kind, label?, required?, readonly?, default?, index? } with kind one of char text int float bool date datetime json,\nselection { options: [{ value, label? }] }, many2one { target, onDelete? }, one2many { target, inverse }, many2many { target },\ncomputed { returns, depends: [fields], compute: <model-method name>, store? }, related { path: \"a.b\" }.\nEvery model also has id, display, created_at, updated_at. Add a field to an existing model with point \"model-field\":\n{ model, name, spec }. Add behaviour with point \"model-method\": { model, name, handler(env, ids, args) } — a compute\nmethod receives args.records (the rows' scalar values) and returns { [id]: value }.\nDomains filter records in prefix notation: [[\"state\",\"=\",\"open\"], \"|\", [\"name\",\"ilike\",\"a\"], [\"email\",\"ilike\",\"a\"]].";

Defined in: packages/plugins/orm/src/contract.ts:18


HOOK_POINT

const HOOK_POINT: "model-hook" = 'model-hook';

Defined in: packages/plugins/orm/src/methods.ts:17


METHOD_POINT

const METHOD_POINT: "model-method" = 'model-method';

Defined in: packages/plugins/orm/src/methods.ts:16


MODEL_FIELD_POINT

const MODEL_FIELD_POINT: "model-field" = 'model-field';

Defined in: packages/plugins/orm/src/contract.ts:16


MODEL_POINT

const MODEL_POINT: "model" = 'model';

Defined in: packages/plugins/orm/src/contract.ts:15


ONCHANGE_POINT

const ONCHANGE_POINT: "model-onchange" = 'model-onchange';

Defined in: packages/plugins/orm/src/methods.ts:18


ORM_KEY

const ORM_KEY: "orm" = 'orm';

Defined in: packages/plugins/orm/src/contract.ts:14

Key under which the orm plugin provides OrmService (system-only).


ormPlugin

const ormPlugin: SystemPlugin;

Defined in: packages/plugins/orm/src/index.ts:143

Functions

createOrmPlugin()

function createOrmPlugin(opts?): SystemPlugin;

Defined in: packages/plugins/orm/src/index.ts:63

Parameters

ParameterType
optsOrmOptions

Returns

SystemPlugin


httpErrorOf()

function httpErrorOf(err): unknown;

Defined in: packages/plugins/orm/src/routes.ts:15

An OrmError as the HttpError a route should throw; anything else comes back unchanged (a 500).

Parameters

ParameterType
errunknown

Returns

unknown


sudo()

function sudo(ctx): OpContext;

Defined in: packages/plugins/orm/src/core.ts:42

Parameters

ParameterType
ctxOpContext

Returns

OpContext


validateField()

function validateField(rawName, f): asserts f is FieldSpec;

Defined in: packages/plugins/orm/src/registry.ts:95

Parameters

ParameterType
rawNameunknown
funknown

Returns

asserts f is FieldSpec


validateModel()

function validateModel(m): asserts m is ModelSpec;

Defined in: packages/plugins/orm/src/registry.ts:139

Parameters

ParameterType
munknown

Returns

asserts m is ModelSpec


validateModelField()

function validateModelField(item): asserts item is ModelFieldContribution;

Defined in: packages/plugins/orm/src/registry.ts:150

Parameters

ParameterType
itemunknown

Returns

asserts item is ModelFieldContribution

@sms/plugin-rbac

Interfaces

Access

Defined in: packages/plugins/rbac/src/contract.ts:28

Properties

create?
optional create?: boolean;

Defined in: packages/plugins/rbac/src/contract.ts:33

group
group: string;

Defined in: packages/plugins/rbac/src/contract.ts:30

model
model: string;

Defined in: packages/plugins/rbac/src/contract.ts:29

read?
optional read?: boolean;

Defined in: packages/plugins/rbac/src/contract.ts:31

optional unlink?: boolean;

Defined in: packages/plugins/rbac/src/contract.ts:34

write?
optional write?: boolean;

Defined in: packages/plugins/rbac/src/contract.ts:32


Group

Defined in: packages/plugins/rbac/src/contract.ts:21

Properties

description?
optional description?: string;

Defined in: packages/plugins/rbac/src/contract.ts:23

implies?
optional implies?: string[];

Defined in: packages/plugins/rbac/src/contract.ts:25

Members of this group are also members of these (transitively).

name
name: string;

Defined in: packages/plugins/rbac/src/contract.ts:22


RbacAdminService

Defined in: packages/plugins/rbac/src/contract.ts:66

Methods

directGroupsOf()
directGroupsOf(userId): Promise<string[]>;

Defined in: packages/plugins/rbac/src/contract.ts:70

Direct (unexpanded) groups of a user.

Parameters
ParameterType
userIdnumber
Returns

Promise<string[]>

grant()
grant(userId, group): Promise<void>;

Defined in: packages/plugins/rbac/src/contract.ts:67

Parameters
ParameterType
userIdnumber
groupstring
Returns

Promise<void>

members()
members(group): Promise<number[]>;

Defined in: packages/plugins/rbac/src/contract.ts:71

Parameters
ParameterType
groupstring
Returns

Promise<number[]>

revoke()
revoke(userId, group): Promise<void>;

Defined in: packages/plugins/rbac/src/contract.ts:68

Parameters
ParameterType
userIdnumber
groupstring
Returns

Promise<void>


RbacService

Defined in: packages/plugins/rbac/src/contract.ts:55

Methods

assertCan()
assertCan(q): Promise<void>;

Defined in: packages/plugins/rbac/src/contract.ts:62

Throws HttpError(403, …, 'forbidden') when can is false.

Parameters
ParameterType
qQuery
Returns

Promise<void>

can()
can(q): Promise<boolean>;

Defined in: packages/plugins/rbac/src/contract.ts:58

Parameters
ParameterType
qQuery
Returns

Promise<boolean>

groups()
groups(): Group & {
  owner: string;
}[];

Defined in: packages/plugins/rbac/src/contract.ts:63

Returns

Group & { owner: string; }[]

groupsOf()
groupsOf(userId): Promise<string[]>;

Defined in: packages/plugins/rbac/src/contract.ts:57

Group names of a user, expanded through implies.

Parameters
ParameterType
userIdnumber
Returns

Promise<string[]>

ruleDomain()
ruleDomain(q): Promise<Domain>;

Defined in: packages/plugins/rbac/src/contract.ts:60

Restriction to AND into a query: global rules AND (OR of the user’s group rules). [] = none.

Parameters
ParameterType
qQuery
Returns

Promise<Domain>


Rule

Defined in: packages/plugins/rbac/src/contract.ts:37

Properties

domain
domain: Domain;

Defined in: packages/plugins/rbac/src/contract.ts:42

groups?
optional groups?: string[];

Defined in: packages/plugins/rbac/src/contract.ts:41

Applies to members of any of these groups; absent = to everyone (a global rule, AND-ed).

model
model: string;

Defined in: packages/plugins/rbac/src/contract.ts:39

name
name: string;

Defined in: packages/plugins/rbac/src/contract.ts:38

ops?
optional ops?: Op[];

Defined in: packages/plugins/rbac/src/contract.ts:44

Default: all ops.


Subject

Defined in: packages/plugins/rbac/src/contract.ts:47

Properties

isAdmin?
optional isAdmin?: boolean;

Defined in: packages/plugins/rbac/src/contract.ts:50

Admins bypass the matrix and the rules.

userId
userId: number;

Defined in: packages/plugins/rbac/src/contract.ts:48

Type Aliases

Domain

type Domain = (DomainLeaf | "&" | "|" | "!")[];

Defined in: packages/plugins/rbac/src/contract.ts:19


DomainLeaf

type DomainLeaf = [string, "=" | "!=" | "<" | "<=" | ">" | ">=" | "in" | "not in" | "like" | "ilike", unknown];

Defined in: packages/plugins/rbac/src/contract.ts:14

Odoo-style prefix domain (same shape as @sms/plugin-orm’s; duplicated so rbac stays independent).


Op

type Op = "read" | "write" | "create" | "unlink";

Defined in: packages/plugins/rbac/src/contract.ts:10


Query

type Query = Subject & {
  model: string;
  op: Op;
};

Defined in: packages/plugins/rbac/src/contract.ts:53

Type Declaration

model
model: string;
op
op: Op;

Variables

ACCESS_POINT

const ACCESS_POINT: "access" = 'access';

Defined in: packages/plugins/rbac/src/contract.ts:77


GROUP_POINT

const GROUP_POINT: "group" = 'group';

Defined in: packages/plugins/rbac/src/contract.ts:76


OPS

const OPS: Op[];

Defined in: packages/plugins/rbac/src/contract.ts:11


RBAC_ADMIN_KEY

const RBAC_ADMIN_KEY: "rbac-admin" = 'rbac-admin';

Defined in: packages/plugins/rbac/src/contract.ts:75


RBAC_KEY

const RBAC_KEY: "rbac" = 'rbac';

Defined in: packages/plugins/rbac/src/contract.ts:74


rbacPlugin

const rbacPlugin: SystemPlugin;

Defined in: packages/plugins/rbac/src/index.ts:66


RULE_POINT

const RULE_POINT: "rule" = 'rule';

Defined in: packages/plugins/rbac/src/contract.ts:78

Functions

expandGroups()

function expandGroups(names, groups): string[];

Defined in: packages/plugins/rbac/src/contract.ts:125

Expand names through implies, transitively and cycle-safe.

Parameters

ParameterType
namesIterable<string>
groupsMap<string, Group>

Returns

string[]


orDomains()

function orDomains(ds): Domain;

Defined in: packages/plugins/rbac/src/contract.ts:118

OR several domains in prefix notation: ['|', '|', ...a, ...b, ...c]. An empty domain means “no restriction”, so OR-ing one in yields the unrestricted domain []; multi-leaf (implicit-AND) domains are wrapped with & so each stays one operand.

Parameters

ParameterType
dsDomain[]

Returns

Domain


validateAccess()

function validateAccess(item): void;

Defined in: packages/plugins/rbac/src/contract.ts:88

Parameters

ParameterType
itemunknown

Returns

void


validateGroup()

function validateGroup(item): void;

Defined in: packages/plugins/rbac/src/contract.ts:82

Parameters

ParameterType
itemunknown

Returns

void


validateRule()

function validateRule(item): void;

Defined in: packages/plugins/rbac/src/contract.ts:94

Parameters

ParameterType
itemunknown

Returns

void

References

IDENTITY_KEY

Re-exports IDENTITY_KEY


IdentityService

Re-exports IdentityService

@sms/plugin-rpc

Interfaces

RpcCall

Defined in: packages/plugins/rpc/src/methods.ts:31

@sms/plugin-rpc/contract — the definitions other code depends on: the method table, call/result types and the pure parseCall / runOne / rightsOf helpers. No manifest, no plugin body: depending on this never drags in the provider (index.ts). The rpc plugin provides no key; it only contributes routes.

Properties

args
args: unknown[];

Defined in: packages/plugins/rpc/src/methods.ts:34

kwargs
kwargs: Record<string, unknown>;

Defined in: packages/plugins/rpc/src/methods.ts:35

method
method: string;

Defined in: packages/plugins/rpc/src/methods.ts:33

model
model: string;

Defined in: packages/plugins/rpc/src/methods.ts:32


RpcEnv

Defined in: packages/plugins/rpc/src/methods.ts:39

@sms/plugin-rpc/contract — the definitions other code depends on: the method table, call/result types and the pure parseCall / runOne / rightsOf helpers. No manifest, no plugin body: depending on this never drags in the provider (index.ts). The rpc plugin provides no key; it only contributes routes.

Properties

ctx
ctx: OpContext;

Defined in: packages/plugins/rpc/src/methods.ts:41

kernel
kernel: KernelApi;

Defined in: packages/plugins/rpc/src/methods.ts:42

orm
orm: OrmService;

Defined in: packages/plugins/rpc/src/methods.ts:40


RpcOptions

Defined in: packages/plugins/rpc/src/index.ts:29

Properties

contextOf?
optional contextOf?: (req) => 
  | OpContext
| Promise<OpContext>;

Defined in: packages/plugins/rpc/src/index.ts:31

Who is calling. Default: anonymous {} (the ORM guard, if any, decides what that may do).

Parameters
ParameterType
reqRouteRequest
Returns

| OpContext | Promise<OpContext>

prefix?
optional prefix?: string;

Defined in: packages/plugins/rpc/src/index.ts:33

Route prefix. Default /api/rpc.

Type Aliases

Rights

type Rights = Record<Op, boolean>;

Defined in: packages/plugins/rpc/src/rights.ts:10


RpcMethod

type RpcMethod = typeof RPC_METHODS[number];

Defined in: packages/plugins/rpc/src/methods.ts:29

@sms/plugin-rpc/contract — the definitions other code depends on: the method table, call/result types and the pure parseCall / runOne / rightsOf helpers. No manifest, no plugin body: depending on this never drags in the provider (index.ts). The rpc plugin provides no key; it only contributes routes.


RpcResult

type RpcResult = 
  | {
  result: unknown;
}
  | {
  error: {
     kind: string;
     message: string;
  };
};

Defined in: packages/plugins/rpc/src/methods.ts:37

@sms/plugin-rpc/contract — the definitions other code depends on: the method table, call/result types and the pure parseCall / runOne / rightsOf helpers. No manifest, no plugin body: depending on this never drags in the provider (index.ts). The rpc plugin provides no key; it only contributes routes.

Variables

RPC_METHODS

const RPC_METHODS: readonly ["search_read", "read", "create", "write", "unlink", "read_group", "onchange", "defaults", "call", "fields", "rights"];

Defined in: packages/plugins/rpc/src/methods.ts:16

@sms/plugin-rpc/contract — the definitions other code depends on: the method table, call/result types and the pure parseCall / runOne / rightsOf helpers. No manifest, no plugin body: depending on this never drags in the provider (index.ts). The rpc plugin provides no key; it only contributes routes.


rpcPlugin

const rpcPlugin: SystemPlugin;

Defined in: packages/plugins/rpc/src/index.ts:103

Functions

createRpcPlugin()

function createRpcPlugin(opts?): SystemPlugin;

Defined in: packages/plugins/rpc/src/index.ts:36

Parameters

ParameterType
optsRpcOptions

Returns

SystemPlugin


groupsOf()

function groupsOf(kernel, ctx): Promise<string[]>;

Defined in: packages/plugins/rpc/src/rights.ts:25

Groups of the caller through rbac, or none when rbac is absent / the caller is anonymous.

Parameters

ParameterType
kernelKernelApi
ctxOpContext

Returns

Promise<string[]>


parseCall()

function parseCall(body): RpcCall;

Defined in: packages/plugins/rpc/src/methods.ts:50

Parse one raw call.

Parameters

ParameterType
bodyunknown

Returns

RpcCall


rightsOf()

function rightsOf(o): Promise<Rights>;

Defined in: packages/plugins/rpc/src/rights.ts:14

Parameters

ParameterType
o{ ctx: OpContext; kernel: KernelApi; model: string; }
o.ctxOpContext
o.kernelKernelApi
o.modelstring

Returns

Promise<Rights>


runOne()

function runOne(env, raw): Promise<RpcResult>;

Defined in: packages/plugins/rpc/src/methods.ts:162

Run one call; never throws — every failure is a { error } result so batches keep going.

Parameters

ParameterType
envRpcEnv
rawunknown

Returns

Promise<RpcResult>

@sms/plugin-scheduler

Interfaces

Schedule

Defined in: packages/plugins/scheduler/src/contract.ts:6

@sms/plugin-scheduler/contract — the definitions other plugins depend on: the scheduler key, the schedule point, job / tick / service types and the validator. No manifest, no plugin body (schedulerPlugin lives in index.ts).

Properties

description?
optional description?: string;

Defined in: packages/plugins/scheduler/src/contract.ts:9

everyMs
everyMs: number;

Defined in: packages/plugins/scheduler/src/contract.ts:11

Minimum interval between runs. A job first runs on the first tick after it is contributed.

handler
handler: (run) => unknown;

Defined in: packages/plugins/scheduler/src/contract.ts:12

Parameters
ParameterType
run{ lastRun?: number; name: string; now: number; }
run.lastRun?number
run.namestring
run.nownumber
Returns

unknown

name
name: string;

Defined in: packages/plugins/scheduler/src/contract.ts:8

Unique across all plugins.


ScheduledJob

Defined in: packages/plugins/scheduler/src/contract.ts:15

Properties

description?
optional description?: string;

Defined in: packages/plugins/scheduler/src/contract.ts:18

everyMs
everyMs: number;

Defined in: packages/plugins/scheduler/src/contract.ts:19

lastError?
optional lastError?: string;

Defined in: packages/plugins/scheduler/src/contract.ts:21

lastRun?
optional lastRun?: number;

Defined in: packages/plugins/scheduler/src/contract.ts:20

name
name: string;

Defined in: packages/plugins/scheduler/src/contract.ts:16

owner
owner: string;

Defined in: packages/plugins/scheduler/src/contract.ts:17


SchedulerService

Defined in: packages/plugins/scheduler/src/contract.ts:32

Methods

jobs()
jobs(): ScheduledJob[];

Defined in: packages/plugins/scheduler/src/contract.ts:35

Returns

ScheduledJob[]

tick()
tick(now?): Promise<TickResult>;

Defined in: packages/plugins/scheduler/src/contract.ts:34

Run every due job. now defaults to Date.now(); jobs run one at a time.

Parameters
ParameterType
now?number
Returns

Promise<TickResult>


TickResult

Defined in: packages/plugins/scheduler/src/contract.ts:24

Properties

failed
failed: {
  error: string;
  name: string;
}[];

Defined in: packages/plugins/scheduler/src/contract.ts:29

Jobs that threw; the error is also kept on jobs() and logged.

error
error: string;
name
name: string;
now
now: number;

Defined in: packages/plugins/scheduler/src/contract.ts:25

ran
ran: string[];

Defined in: packages/plugins/scheduler/src/contract.ts:27

Names of the jobs that ran, in order.

Variables

SCHEDULE_POINT

const SCHEDULE_POINT: "schedule" = 'schedule';

Defined in: packages/plugins/scheduler/src/contract.ts:39


SCHEDULER_KEY

const SCHEDULER_KEY: "scheduler" = 'scheduler';

Defined in: packages/plugins/scheduler/src/contract.ts:38


schedulerPlugin

const schedulerPlugin: SystemPlugin;

Defined in: packages/plugins/scheduler/src/index.ts:25

Functions

validateSchedule()

function validateSchedule(item): void;

Defined in: packages/plugins/scheduler/src/contract.ts:42

Parameters

ParameterType
itemunknown

Returns

void

@sms/plugin-sdk

Interfaces

Cap

Defined in: packages/core/plugin-sdk/src/runtime.ts:6

The plugin-side runtime: builds the cap object handed to plugin code and answers the host’s calls (‘activate’, ‘fn’). Transport-agnostic — the executor supplies hostCall.

Methods

contribute()
contribute(point, item): Promise<void>;

Defined in: packages/core/plugin-sdk/src/runtime.ts:10

Contribute an item to an extension point. Functions in the item become callable from the host.

Parameters
ParameterType
pointstring
itemunknown
Returns

Promise<void>

get()
get<T>(key): Promise<T>;

Defined in: packages/core/plugin-sdk/src/runtime.ts:12

Read a JSON snapshot of an injected key.

Type Parameters
Type ParameterDefault type
Tunknown
Parameters
ParameterType
keystring
Returns

Promise<T>

invoke()
invoke<T>(
   key, 
   method, 
   ...args
): Promise<T>;

Defined in: packages/core/plugin-sdk/src/runtime.ts:14

Call a method on an injected service.

Type Parameters
Type ParameterDefault type
Tunknown
Parameters
ParameterType
keystring
methodstring
argsunknown[]
Returns

Promise<T>

log()
log(...args): void;

Defined in: packages/core/plugin-sdk/src/runtime.ts:15

Parameters
ParameterType
argsunknown[]
Returns

void

provide()
provide(key, value): Promise<void>;

Defined in: packages/core/plugin-sdk/src/runtime.ts:8

Provide a service. Methods on the value become callable from the host.

Parameters
ParameterType
keystring
valueunknown
Returns

Promise<void>


Channel

Defined in: packages/core/plugin-sdk/src/channel.ts:10

Methods

call()
call(
   method, 
   args, 
   timeoutMs?
): Promise<unknown>;

Defined in: packages/core/plugin-sdk/src/channel.ts:11

Parameters
ParameterType
methodstring
argsunknown
timeoutMs?number
Returns

Promise<unknown>

close()
close(reason?): void;

Defined in: packages/core/plugin-sdk/src/channel.ts:13

Parameters
ParameterType
reason?string
Returns

void

receive()
receive(msg): void;

Defined in: packages/core/plugin-sdk/src/channel.ts:12

Parameters
ParameterType
msgRpcMessage
Returns

void


PluginModule

Defined in: packages/core/plugin-sdk/src/runtime.ts:20

Properties

activate?
optional activate?: Activate;

Defined in: packages/core/plugin-sdk/src/runtime.ts:22

default?
optional default?: 
  | Activate
  | {
  activate?: Activate;
};

Defined in: packages/core/plugin-sdk/src/runtime.ts:21


PluginRuntime

Defined in: packages/core/plugin-sdk/src/runtime.ts:25

Properties

cap
cap: Cap;

Defined in: packages/core/plugin-sdk/src/runtime.ts:26

Methods

handle()
handle(method, args): Promise<unknown>;

Defined in: packages/core/plugin-sdk/src/runtime.ts:28

Handle a call coming from the host.

Parameters
ParameterType
methodstring
argsunknown
Returns

Promise<unknown>


RpcMessage

Defined in: packages/core/plugin-sdk/src/channel.ts:2

Tiny request/response multiplexer used on both sides of an Executor boundary.

Properties

args?
optional args?: unknown;

Defined in: packages/core/plugin-sdk/src/channel.ts:5

error?
optional error?: string;

Defined in: packages/core/plugin-sdk/src/channel.ts:7

id
id: number;

Defined in: packages/core/plugin-sdk/src/channel.ts:3

method?
optional method?: string;

Defined in: packages/core/plugin-sdk/src/channel.ts:4

result?
optional result?: unknown;

Defined in: packages/core/plugin-sdk/src/channel.ts:6

Type Aliases

Activate

type Activate = (cap) => void | Promise<void>;

Defined in: packages/core/plugin-sdk/src/runtime.ts:18

Parameters

ParameterType
capCap

Returns

void | Promise<void>

Functions

createChannel()

function createChannel(post, handle): Channel;

Defined in: packages/core/plugin-sdk/src/channel.ts:16

Parameters

ParameterType
post(msg) => void
handle(method, args) => Promise<unknown>

Returns

Channel


createPluginRuntime()

function createPluginRuntime(hostCall, loadModule): PluginRuntime;

Defined in: packages/core/plugin-sdk/src/runtime.ts:31

Parameters

ParameterType
hostCall(method, args) => Promise<unknown>
loadModule() => Promise<PluginModule>

Returns

PluginRuntime


resolveActivate()

function resolveActivate(mod): Activate | undefined;

Defined in: packages/core/plugin-sdk/src/runtime.ts:89

Parameters

ParameterType
modPluginModule

Returns

Activate | undefined

@sms/store-d1

Interfaces

D1DatabaseLike

Defined in: packages/drivers/store/d1/src/index.ts:11

Structural subset of Cloudflare’s D1Database (so this package needs no workers-types dependency).

Methods

exec()
exec(query): Promise<unknown>;

Defined in: packages/drivers/store/d1/src/index.ts:13

Parameters
ParameterType
querystring
Returns

Promise<unknown>

prepare()
prepare(query): D1StatementLike;

Defined in: packages/drivers/store/d1/src/index.ts:12

Parameters
ParameterType
querystring
Returns

D1StatementLike


D1StatementLike

Defined in: packages/drivers/store/d1/src/index.ts:15

Methods

all()
all<T>(): Promise<{
  results: T[];
}>;

Defined in: packages/drivers/store/d1/src/index.ts:17

Type Parameters
Type ParameterDefault type
TRecord<string, unknown>
Returns

Promise<{ results: T[]; }>

bind()
bind(...values): D1StatementLike;

Defined in: packages/drivers/store/d1/src/index.ts:16

Parameters
ParameterType
valuesunknown[]
Returns

D1StatementLike

Functions

d1Database()

function d1Database(d1): Database;

Defined in: packages/drivers/store/d1/src/index.ts:21

Wrap a D1 binding as a Database driver.

Parameters

ParameterType
d1D1DatabaseLike

Returns

Database


openD1Store()

function openD1Store(d1): Promise<Store>;

Defined in: packages/drivers/store/d1/src/index.ts:50

Parameters

ParameterType
d1D1DatabaseLike

Returns

Promise<Store>

@sms/store-do

Interfaces

SqlStorageLike

Defined in: packages/drivers/store/do/src/index.ts:5

Structural subset of Cloudflare’s SqlStorage (so this package needs no workers-types dependency).

Methods

exec()
exec(query, ...bindings): {
  toArray: Record<string, unknown>[];
};

Defined in: packages/drivers/store/do/src/index.ts:6

Parameters
ParameterType
querystring
bindingsunknown[]
Returns
{
  toArray: Record<string, unknown>[];
}
toArray()
toArray(): Record<string, unknown>[];
Returns

Record<string, unknown>[]

Functions

durableObjectDatabase()

function durableObjectDatabase(sql): Database;

Defined in: packages/drivers/store/do/src/index.ts:10

Wrap a Durable Object’s ctx.storage.sql as a Database driver.

Parameters

ParameterType
sqlSqlStorageLike

Returns

Database


openDurableObjectStore()

function openDurableObjectStore(sql): Promise<Store>;

Defined in: packages/drivers/store/do/src/index.ts:34

Parameters

ParameterType
sqlSqlStorageLike

Returns

Promise<Store>

@sms/store-postgres

Interfaces

PgClient

Defined in: packages/drivers/store/postgres/src/index.ts:6

The minimal client surface we need: pg.Pool, pg.Client and PGlite all have it.

Methods

close()?
optional close(): Promise<void>;

Defined in: packages/drivers/store/postgres/src/index.ts:9

Returns

Promise<void>

end()?
optional end(): Promise<void>;

Defined in: packages/drivers/store/postgres/src/index.ts:8

Returns

Promise<void>

query()
query(text, params?): Promise<{
  rows: Record<string, unknown>[];
}>;

Defined in: packages/drivers/store/postgres/src/index.ts:7

Parameters
ParameterType
textstring
params?unknown[]
Returns

Promise<{ rows: Record<string, unknown>[]; }>


PostgresOptions

Defined in: packages/drivers/store/postgres/src/index.ts:12

Properties

client?
optional client?: PgClient;

Defined in: packages/drivers/store/postgres/src/index.ts:14

A ready client (pg Pool/Client, PGlite). Either this or connectionString.

connectionString?
optional connectionString?: string;

Defined in: packages/drivers/store/postgres/src/index.ts:16

Creates a pg.Pool (pg must be installed).

schema?
optional schema?: string;

Defined in: packages/drivers/store/postgres/src/index.ts:18

Schema to hold this kernel’s tables — one per tenant. Default public.

Functions

openPostgresStore()

function openPostgresStore(opts): Promise<Store>;

Defined in: packages/drivers/store/postgres/src/index.ts:57

Open a Store on Postgres. With connectionString a dedicated pg.Pool is created whose connections have search_path set to the schema, so all kernels share one server safely. With a hand-made client (single connection, e.g. PGlite) the search_path is set on that connection.

Parameters

ParameterType
optsPostgresOptions

Returns

Promise<Store>


postgresDatabase()

function postgresDatabase(client, opts?): Database;

Defined in: packages/drivers/store/postgres/src/index.ts:22

Wrap a Postgres client as a Database driver.

Parameters

ParameterType
clientPgClient
opts{ owned?: boolean; schema?: string; }
opts.owned?boolean
opts.schema?string

Returns

Database

@sms/store-sql

Functions

bindSqliteParam()

function bindSqliteParam(v): unknown;

Defined in: packages/drivers/store/sql/src/index.ts:11

SQLite-family binding: booleans → 0/1, undefined → NULL.

Parameters

ParameterType
vunknown

Returns

unknown


createSqlStore()

function createSqlStore(db): Promise<Store>;

Defined in: packages/drivers/store/sql/src/index.ts:20

Parameters

ParameterType
dbDatabase

Returns

Promise<Store>


numberPlaceholders()

function numberPlaceholders(sql): string;

Defined in: packages/drivers/store/sql/src/index.ts:15

Rewrite ? placeholders to $1, $2 … (Postgres). Identifiers/literals in our SQL never contain ?.

Parameters

ParameterType
sqlstring

Returns

string

References

sqlDialect

Re-exports sqlDialect

@sms/store-sqlite

Interfaces

SqliteStore

Defined in: packages/drivers/store/sqlite/src/index.ts:5

Everything a kernel needs to persist: the event log, bundle blobs, and a database for plugins (key database).

Extends

Properties

blobs
blobs: BlobStore;

Defined in: packages/core/contracts/src/index.ts:48

Inherited from

Store.blobs

db
db: Database;

Defined in: packages/core/contracts/src/index.ts:46

Inherited from

Store.db

log
log: EventLog;

Defined in: packages/core/contracts/src/index.ts:47

Inherited from

Store.log

sqlite
sqlite: DatabaseSync;

Defined in: packages/drivers/store/sqlite/src/index.ts:7

The raw node:sqlite handle (system code only).

Methods

close()
close(): Promise<void>;

Defined in: packages/core/contracts/src/index.ts:49

Returns

Promise<void>

Inherited from

Store.close

Functions

openSqliteStore()

function openSqliteStore(path): Promise<SqliteStore>;

Defined in: packages/drivers/store/sqlite/src/index.ts:31

One SQLite file backs the event log, the bundle blobs and collection tables. Use ‘:memory:’ for tests.

Parameters

ParameterType
pathstring

Returns

Promise<SqliteStore>


sqliteDatabase()

function sqliteDatabase(db): Database;

Defined in: packages/drivers/store/sqlite/src/index.ts:11

Wrap a node:sqlite database as a Database driver.

Parameters

ParameterType
dbDatabaseSync

Returns

Database