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):
- Getting started · Writing plugins · Building a UI
- Drivers · Tenancy
- Architecture · Dependency graph · Research positioning
- Releasing · Quality gate · Benchmarking
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
| Need | Package |
|---|---|
| always | packages/baseline |
| a store | store-sqlite (Node ≥ 22.13, node:sqlite) · store-postgres (pg or PGlite) · store-do (Durable Objects) |
| a host | host-node · host-fastify · host-cloudflare |
| an executor | executor-quickjs (recommended, WASM boundary) · executor-node (worker threads, dev only) |
| a model | model-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 → http → collections → scheduler → auth → rbac
→ orm (+ the rbac→orm guard) → meta / rpc when enabled → judge → model → agent-loop → admin-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 plugin | Agent plugin | |
|---|---|---|
| Written by | you, in your repo | the model at run time (or a human through the same API) |
| Runs | in-process, activate(ctx) with ctx.kernel | in the executor, activate(cap), JSON-only bridge |
| Trust | system | agent — cannot touch system-only keys/points, needs the judge |
| Installed by | createBaseline({ 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>/contract — X_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
| Point | Owner | Item | Agent may contribute |
|---|---|---|---|
route | http | { method, path, handler(req) } — :param, *; return JSON or a Response; throw HttpError for a status | yes (needs a human by default) |
schedule | scheduler | { name, everyMs, handler({ name, now, lastRun }) } — runs when the host ticks; last run persisted | yes (needs a human by default) |
admin-authorizer | admin-api | { name, authorize(req) → boolean } — admits a request to mutating admin routes; @sms/plugin-auth contributes auth-session (an admin session) | no (system) |
group | rbac | { name, description?, implies?[] } — membership is data (rbac-admin.grant) | no (system) |
access | rbac | { model, group, read?, write?, create?, unlink? } — the access matrix | no (system) |
rule | rbac | { name, model, groups?, domain, ops? } — record rule; rbac.ruleDomain() ANDs global rules with the OR of the user’s group rules | no (system) |
model | orm | { name, fields: { name: spec }, displayField?, order? } — a table with relations, computed and related fields (see Models) | yes |
model-field | orm | { model, name, spec } — adds a column to a model declared elsewhere (waits for it if needed) | yes |
model-method | orm | { model, name, handler(env, ids, args), access? } — computes, buttons, RPC | yes (needs a human by default) |
model-hook | orm | { model, on: create/write/unlink, when: before/after, handler(env, { ids, values, records }) } | yes (needs a human by default) |
model-onchange | orm | { model, field, handler(env, values) → patch } | yes |
view | meta | { 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 |
action | meta | { id, name, model, views[], viewIds?, domain?, context?, groups? } — ids are global | yes |
menu | meta | { id, label, parent?, action?, sequence?, icon?, groups? } — roots are apps; empty branches are pruned | yes |
automation | automation | { id, label, model, trigger: create/write/create_or_write/unlink/schedule, watch?, filter?, everyMinutes?, action: { kind: method/update/message/handler, … }, active? } — actions run as sudo | yes (needs a human by default) |
audit-track | audit | { model, fields[] } — log field changes of that model as audit_message rows | yes |
collection | collections | { name, fields[] } — types text · integer · real · boolean · json | yes |
collection-field | collections | { collection, field } — adds a column | yes |
collection-hook | collections | { collection, on: create/update/remove, handler(record, previous) } | yes |
tool | agent-loop | { name, description, input_schema, handler(input) } | yes |
prompt | agent-loop | { section, text, order } | yes |
gate | judge | `{ name, run(ctx) → undefined | reason }` — runs before any agent plugin mounts |
invariant | judge | { name, check(kernel) } — runs after every mount; a throw rolls the mount back | no |
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)
| Route | Purpose | Token |
|---|---|---|
GET /api/state | everything 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/catalog | what 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/:id | live 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=100 | audit 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/:id | create / 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 }))
| Route | Body → 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/mine | messages, activities and followers of one record (@sms/plugin-audit); 404 when the record is not visible to the caller |
your own route contributions | anything 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.
| Route | Purpose |
|---|---|
POST /api/auth/login { login, password } | { user, token }; sets the sms_session HttpOnly cookie (Secure behind https) |
POST /api/auth/logout | ends 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)
| Route | Returns | Admin |
|---|---|---|
GET /api/rbac/groups | declared 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):
| event | payload | when |
|---|---|---|
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.
| Concern | Contract | Drivers |
|---|---|---|
| persistence | Store { db: Database, log, blobs, close } | store-sqlite · store-postgres · store-do · store-d1 (all built on the store-sql helper) |
| database for plugins | Database { dialect, exec, query, columns, close } (key database) | provided by every store |
| files / objects | ObjectStore { put, get, head, delete, list } (key objects) | objects-s3 (AWS S3, MinIO, R2 via S3 API) · objects-r2 (bucket binding) · createMemoryObjectStore (tests) |
| HTTP | Host { listen(handler) → HostServer } | host-node · host-fastify · host-cloudflare |
| tenancy | TenantResolver (request) → tenantId | tenantFromHeader, tenantFromSubdomain({ root, fallback, reserved }), your own |
| agent code | Executor { load(bundle, host, opts?) → ExecutorInstance } (in @sms/kernel) | executor-node · executor-quickjs |
| model | ModelService { 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.
- sqlite —
node:sqlite, one file per kernel (:memory:for tests), WAL on. - postgres —
pg.Poolfrom aconnectionString(creates the schema, pinssearch_pathper 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 increateCloudflareApp({ store }). Multi-line DDL is flattened becauseD1Database.execruns one statement per line. Use it when a tenant’s data must be reachable outside its Durable Object (dashboards,wrangler d1queries);store-dois 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.
- s3 —
createS3ObjectStore({ bucket, endpoint, region, accessKeyId, secretAccessKey, sessionToken, forcePathStyle }): Signature V4 over purefetch+ WebCrypto, no aws-sdk, runs in Node and Workers. One driver for AWS S3 (noendpoint), 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 areS3Error { status, code }. - r2 —
createR2ObjectStore(env.FILES)on a bucket binding inside a Worker / Durable Object: no credentials, streams pass straight through. StructuralR2BucketLiketype, 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.
- node —
createNodeHost({ port, host }).listen(handle);toRequest/sendResponseare exported for reuse. - fastify —
createFastifyHost({ app, prefix }).listen(handle)mounts a catch-all underprefixon your existing Fastify instance (raw bodies,reply.hijack()), or creates one. - cloudflare —
createCloudflareApp({ resolve, binding, tenant })returns the Workerfetchand a Durable Object class; each tenant’s DO opensstore-doon its SQLite and calls yourtenant({ tenantId, env, store }), which returns anything with ahandle(acreateBaseline()result). One traditional Worker, no Dynamic Workers.store: ({ tenantId, env, state }) => Storeswaps the DO SQLite for e.g.openD1Store(env.DB). The driver depends only on contracts, so it can host anyRequestHandler.
Executors
executor-node | executor-quickjs | |
|---|---|---|
| mechanism | worker_threads, code as a data: ESM import, ambient globals stripped | QuickJS interpreter compiled to WASM, one runtime per plugin |
| boundary | steering, not security (same process) | real: own heap, memoryLimitBytes, CPU deadline per slice (sliceMs), no I/O, no import |
| bridge | RPC channel (@sms/plugin-sdk) | JSON over one host function; cap built by an in-VM bootstrap |
| runs on | Node | Node, browsers, Workers (variant: import('@jitl/quickjs-singlefile-mjs-release-sync')) |
| use for | local dev, fastest | production |
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 (claudelogin). 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 eachcodex execat it. Onecodex execper turn, resumed by thread id;developer_instructionscarries 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 execforcesapproval_policy=neverand then only auto-approves MCP tools annotatedreadOnlyHint— 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 }); defaultclaude-opus-5, adaptive thinking). Thinking blocks are notModelContent, so the driver caches those that preceded a tool call and re-attaches them when the loop replays that assistant turn. Passclientto use a Bedrock/Vertex/Foundry client instead.@sms/model-gpt-api—openai, Responses API (createGptApiModel({ apiKey, model, effort }); defaultgpt-5.5,store: falsewith encrypted reasoning replayed the same way).@sms/model-openrouter—openaipointed athttps://openrouter.ai/api/v1, Chat Completions (createOpenRouterModel({ apiKey, model, effort, appName, siteUrl });modelis an OpenRouter slug, defaultanthropic/claude-sonnet-4.5;effortmaps to OpenRouter’s unifiedreasoning.effort,none…max). OpenRouter’s HTTP-200 errors (choices[0].error/finish_reason: 'error') are thrown. OpenRouter’sreasoning_detailsare 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 tokenscodex loginwrites to~/.codex/auth.jsonsent 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. Purefetch, so it runs in a Worker.createGptOauthModel({ unofficial: true, tokens, store?, model, effort });tokensis aCodexTokens, or the text ofauth.json(in Node:readCodexAuth()from@sms/model-gpt-oauth/node);store(kvTokenStore(kv), orfileTokenStore(path)from/node) persists refreshed tokens. Tokens are refreshed before expiry and once more on a 401.unofficial: trueis 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=1runs 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
- Implement the contract in a new package
packages/drivers/<kind>/<name>depending only on@sms/contracts(and@sms/kernelforExecutor). Never import a sibling driver — the gate (scripts/quality/layers.ts) allows only thestore-sqlhelper and the listed exceptions (host-fastify → host-node,host-cloudflare → store-do). - Reuse the shared tests: store drivers run
databaseContractandcollectionsContractTests; object stores runobjectsContract; executors copypackages/drivers/executor/quickjs/test/executor.test.ts; model drivers runmodelContractfrompackages/core/contracts/test. - Add it to
tsconfig.build.jsonreferences and keeppackage.jsonin the standard shape (exportswithsms-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’sBaseline(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)(bothcreateTenantPoolandcreateCloudflareApptake it) or a 400no tenantby default. - Postgres: one Pool per tenant with
search_pathpinned 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.com → acme, the bare root /
localhost / IPs → fallback, acme.localhost → acme (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:
| From | Taken | Changed |
|---|---|---|
| Linux | a small generic kernel; drivers behind contracts; everything else loadable | drivers are npm packages picked at composition time |
| Cordis / dsh | fiber 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 |
| dsh | everything is a plugin; human approves the visible half | approval is a judge policy (sensitiveScopes/Points), not baked in; there is no visible half — the baseline is headless |
| pi | the loader loop is enough — no “modify yourself” API beyond the tools the agent has | the loader is plugin_define → judge → kernel; no file system needed |
| DGM | a judge that is out of reach | trust tiers inside the kernel + authorization tokens, instead of hiding |
| Strapi / Directus | declarative collections with auto CRUD/REST/hooks | collections 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) | |
|---|---|---|
| holds | X_KEY/X_POINT constants, service + item types, validators, pure helpers | everything in the contract, plus createXPlugin() / xPlugin |
| imported by | other plugins (the only allowed subpath between plugins) | composition roots: baseline, apps, tests |
| may reach | contracts, kernel types, other contracts | anything 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:
| Contract | Used by | Drivers |
|---|---|---|
Database { dialect, exec, query(sql, ?-params), columns, close } | collections (key database), store-sql | sqlite (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 roots | node (node:http), fastify (mount under a prefix, encapsulated scope), cloudflare (Worker fetch + DO class) |
TenantResolver | createTenantPool, createCloudflareApp | tenantFromHeader, tenantFromSubdomain, custom |
Executor (kernel) | kernel, judge’s load gate | node (worker_threads), quickjs (WASM) |
ModelService | agent 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): manifest → trust → source-lint → load (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
| Executor | Boundary |
|---|---|
executor-node | worker_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-quickjs | QuickJS 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)
| Piece | Node | Cloudflare |
|---|---|---|
| Executor | executor-node / executor-quickjs | executor-quickjs (single-file WASM variant) |
| Store | store-sqlite / store-postgres | store-do (DO SQLite: same tables) / store-d1 (one D1 per tenant) |
| Objects | objects-s3 | objects-r2 (bucket binding) / objects-s3 |
| HTTP entry | host-node / host-fastify | host-cloudflare: Worker fetch → TENANT.get(idFromName(tenant)) → DO → app.handle |
| Everything else | unchanged | unchanged |
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
| Point | Owner | Item | Agent may contribute |
|---|---|---|---|
route | http | { method, path, handler(req) } | yes (human by default) |
schedule | scheduler | { name, everyMs, handler(run) } | yes (human by default) |
group | rbac | { name, implies? } | no (system) |
access | rbac | { model, group, read?, write?, create?, unlink? } | no (system) |
rule | rbac | { name, model, groups?, domain, ops? } | no (system) |
model | orm | { name, fields, displayField?, order? } | yes |
model-field | orm | { model, name, spec } | yes |
model-method | orm | { model, name, handler(env, ids, args), access? } | yes |
model-hook | orm | { model, on, when, handler(env, payload) } | yes |
model-onchange | orm | { model, field, handler(env, values) } | yes |
view / action / menu | meta | views with inheritance, actions, menu tree (opt-in) | yes |
automation | automation | { id, model, trigger, watch?, filter?, action } | yes (human by default) |
audit-track | audit | { model, fields[] } | yes |
admin-authorizer | admin-api | { name, authorize(req) } | no (system) |
collection | collections | { name, fields[] } | yes |
collection-field | collections | { collection, field } | yes |
collection-hook | collections | { collection, on, handler(record, previous) } | yes |
tool | agent-loop | { name, description, input_schema, handler(input) } | yes |
prompt | agent-loop | { section, text, order } | yes |
gate | judge | { name, run(ctx) } | no (system) |
| (auth) | auth | contributes route ×3 and admin-authorizer auth-session; keys identity / identity-admin | — |
invariant | judge | { 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
| Package | Ring | Depends on |
|---|---|---|
@sms/kernel | ring 0 · kernel | — |
@sms/contracts | ring 1 · contracts | @sms/kernel |
@sms/plugin-sdk | ring 1 · plugin-sdk | — |
@sms/executor-node | ring 2 · drivers | @sms/kernel, @sms/plugin-sdk |
@sms/executor-quickjs | ring 2 · drivers | @sms/kernel |
@sms/host-cloudflare | ring 2 · drivers | @sms/contracts, @sms/store-do |
@sms/host-fastify | ring 2 · drivers | @sms/contracts, @sms/host-node |
@sms/host-node | ring 2 · drivers | @sms/contracts |
@sms/model-claude | ring 2 · drivers | @sms/contracts, @sms/kernel |
@sms/model-claude-api | ring 2 · drivers | @sms/contracts, @sms/kernel |
@sms/model-gpt | ring 2 · drivers | @sms/contracts, @sms/kernel |
@sms/model-gpt-api | ring 2 · drivers | @sms/contracts, @sms/kernel |
@sms/model-gpt-oauth | ring 2 · drivers | @sms/contracts, @sms/kernel |
@sms/model-openrouter | ring 2 · drivers | @sms/contracts, @sms/kernel |
@sms/objects-r2 | ring 2 · drivers | @sms/contracts |
@sms/objects-s3 | ring 2 · drivers | @sms/contracts |
@sms/store-d1 | ring 2 · drivers | @sms/contracts, @sms/store-sql |
@sms/store-do | ring 2 · drivers | @sms/contracts, @sms/store-sql |
@sms/store-postgres | ring 2 · drivers | @sms/contracts, @sms/store-sql |
@sms/store-sql | ring 2 · drivers | @sms/contracts, @sms/kernel |
@sms/store-sqlite | ring 2 · drivers | @sms/contracts, @sms/store-sql |
@sms/plugin-admin-api | ring 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-loop | ring 2 · plugins | @sms/contracts, @sms/kernel, @sms/plugin-judge |
@sms/plugin-audit | ring 2 · plugins | @sms/kernel, @sms/plugin-http, @sms/plugin-orm |
@sms/plugin-auth | ring 2 · plugins | @sms/contracts, @sms/kernel, @sms/plugin-http |
@sms/plugin-automation | ring 2 · plugins | @sms/contracts, @sms/kernel, @sms/plugin-audit, @sms/plugin-orm |
@sms/plugin-collections | ring 2 · plugins | @sms/contracts, @sms/kernel, @sms/plugin-http |
@sms/plugin-http | ring 2 · plugins | @sms/kernel |
@sms/plugin-judge | ring 2 · plugins | @sms/kernel |
@sms/plugin-meta | ring 2 · plugins | @sms/kernel, @sms/plugin-orm |
@sms/plugin-orm | ring 2 · plugins | @sms/contracts, @sms/kernel, @sms/plugin-http |
@sms/plugin-rbac | ring 2 · plugins | @sms/contracts, @sms/kernel, @sms/plugin-auth, @sms/plugin-http |
@sms/plugin-rpc | ring 2 · plugins | @sms/kernel, @sms/plugin-auth, @sms/plugin-http, @sms/plugin-meta, @sms/plugin-orm, @sms/plugin-rbac |
@sms/plugin-scheduler | ring 2 · plugins | @sms/contracts, @sms/kernel |
@sms/baseline | ring 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-worker | ring 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-postgres | ring 4 · apps | @sms/baseline, @sms/executor-quickjs, @sms/host-fastify, @sms/model-claude, @sms/store-postgres |
@sms/example-reference-node-sqlite | ring 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 modified | the 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 proposes | the model, through plugin_define; humans through the same judge API |
| When | live, in the same conversation; Commit = the plugin/installed event + content-addressed blob; Serve = the fiber is active and reachable through http/agent/collections |
| Judge | the 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 judge | structural, 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 |
| Boundary | QuickJS-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. |
| Persistence | event-sourced (plugin/* fold into the target view), blobs by hash; SQLite, Postgres, D1, Durable Objects (drivers/store/*); files on S3 / R2 (drivers/objects/*) |
| Tenancy | kernel-per-tenant; the substrate never sees two tenants |
Concepts from the vault and where they live here
| Concept | Here |
|---|---|
revertible-effects | closed 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 requirements | closed 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-regression | mount = checkpoint (previous version in log) → act (activate) → judge (invariants) → commit or full undo. Batch size K = one plugin activation. |
objective-hacking / belief 6 | the 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-log | chat/*, judge/*, fiber/* events are audit; plugin/* are state |
evaluator-co-evolution | invariants 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).
| Surface | Attack | Where it is stopped |
|---|---|---|
inject: ['judge'] / provide: ['judge'] | reach or replace the judge | trust gate (E) and kernel trust check (S); test agent plugins cannot reach system-only keys |
contributes.gate / invariant | weaken the evaluator | minContributorTrust: system (E, S) |
id collision (judge, http, …) | replace a system fiber | RESERVED_ID (E, S); judge requires agent. prefix |
| forged / replayed authorization | mount without the judge | nonce bound to id+version+code hash, single-use (C) |
code escapes (process, fetch, import) | I/O from agent code | source-lint (E); QuickJS has none of them (S); Node executor strips them (steering only) |
| runaway CPU / memory | denial of service inside the process | QuickJS sliceMs interrupt + memoryLimitBytes; Node executor resourceLimits |
route contribution shadowing /api/* | hijack admin routes | routes 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 effects | emissions 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 contribution | steer 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 contamination | an agent-contributed collection/tool changes what an invariant reads | invariants should read kernel state (kernel.has, fibers), not collection data — documented rule, not enforced |
| cross-tenant | one tenant’s agent plugin affects another | kernel-per-tenant, separate stores; no shared executor instances |
Open questions (deliberately not solved here)
- Emissions.
activate()code cannot do I/O in QuickJS, but a system-provided service itinvokes 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. - 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.
- The human gate at scale.
needs-humanis a policy on scopes/points. Per-tenant approvers, quorum, and expiry are host concerns to build on/api/approvals. - 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 mechanism | Problem it solves there | Our analog today | Gap |
|---|---|---|---|
Loadable modules, module_get refcounts | Load/unload code at runtime; refuse unload while depended on | plugins, kernel-derived undo | No refcount: unloading a plugin whose provided key others hold |
EXPORT_SYMBOL_GPL, module signing, lockdown | Gate symbols on a property of the consumer; a global “only signed code” mode | minConsumerTrust, judge | No global lockdown bit |
| Taint flags | Permanent provenance on every bug report (“out-of-tree module was loaded”) | — | planned §1 |
| Livepatch transition model | Replace a function under load; abortable; never half-patched | observePoint({added, removed}) + derived undo | No sequencing/abort state machine — planned §2 |
| eBPF verifier + per-program-type helpers + maps | Untrusted programs inside the kernel; whitelisted calls per attach type; state only via kernel-owned maps | judge (runtime), Trust rank, collections | Rank is too coarse; no static pre-load pass — planned §3 |
Capabilities (CAP_*) | Root split into discrete privileges | Trust = 'system' | 'agent' | same as above |
| Seccomp | A process can only shrink its privileges | — | Monotonic trust for agent-authored plugins — folded into §3 |
| cgroups | Per-subtree resource budgets | per-call executor limits only (QuickJS sliceMs/memoryLimitBytes, Node resourceLimits) | later §4 |
| Namespaces | Per-process view of the system | kernel-per-tenant | done |
| LSM stacking | Every policy gets a veto on a canonical list of sensitive ops | judge | judge is a single LSM; the hook list is not published — later |
| Static keys / alternatives | Atomic feature flags; capability-driven implementation selection | driver composition at boot | later |
| Kprobes / tracepoints | Hook any function without author cooperation / declared hooks | extension points (declared) | rejected §5 |
Kconfig depends on/select | Configuration as a satisfiable object | manifest inject (hard) / optional (soft), gate rule plugin-inject | partial — no solver yet |
| sysfs/procfs | One introspection tree for tools, humans and programs | plugin-admin-api (/api/state, /api/catalog), plugin-meta | done in spirit |
| kexec / initramfs | Reboot into a new kernel or a minimal known-good state | — | later (“safe mode”: human-authored plugins only) |
| Stable userspace ABI, unstable internals | Decide 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:
| Flag | Set when |
|---|---|
AGENT_AUTHORED | a plugin whose author trust is agent was loaded |
JUDGE_OVERRIDDEN | a human approved something the judge rejected |
TRUST_ESCALATED | any path granted a consumer more trust than its author had |
LOAD_FORCED | a plugin was loaded despite a failed check (contract, verifier) |
UNVERIFIED | a 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.routecontributor getsdb.read,model.complete; anadmin.hookcontributor also getsplugin.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 assertTrust → assertCapabilities.
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.
completefires only when every pinned unit has reached a safe point;abortat any time returns toactive(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/contractsnever breaks;plugin-sdkinternals 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/xinstalls one subdirectory of a monorepo — but pnpm does not rewriteworkspace:*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, oneKernelclass in the process.- Node refuses to type-strip
.tsinsidenode_modules, so consumers need real.js+.d.ts:tsc -bemitsdist/per package (tsconfig.package.json→ per-packagetsconfig.build.json). - Development stays build-free: package
exportslistsms-source→src/index.tsfirst.tsconfig.json(customConditions),vitest.config.ts(resolve.conditions) and the app scripts (--conditions=sms-source) enable it; consumers never see it (default condition →dist/). mainnever carries build output (dist/and*.tsbuildinfoare gitignored). Release commits do; they are reachable only through their tag, so norelease/*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
mainwith a clean workspace layout. CD refuses a tag whose commit is not onmain(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 check → pnpm clean && pnpm build
→ pnpm 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/onmain. - Publish a package that imports a sibling driver; consumers must be able to install one driver alone.
Quality gate
pnpm check = typecheck → lint → quality → knip → test: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:
| Rule | Limit | Why |
|---|---|---|
noExcessiveCognitiveComplexity | 25 | A function you cannot hold in your head cannot be reviewed or tested exhaustively. |
noExcessiveNestedTestSuites | default | Tests are specs; deep nesting hides which behaviour a case documents. |
useConsistentArrayType | T[] | 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,contractsand 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 helperstore-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 typeand 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
| File | Surface | Workloads |
|---|---|---|
kernel.bench.ts | Kernel reconciler, in-memory backends | install 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.ts | NodeExecutor (worker thread) vs QuickJSExecutor (WASM) | mount + dispose; 100 tool-call round-trips agent → host → agent |
stores.bench.ts | store-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.ts | createJudgePlugin gate pipeline | boot cost (reference); a submission rejected by a static gate; a full submission through the load gate (throwaway sandbox) to mount |
host-node.bench.ts | createNodeHost over loopback | GET; 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/*.mdin this repo, plus the rootREADME.mdas 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
- Write
docs/your-page.md. - Add it to
docs/SUMMARY.md— that file is the book’s table of contents and the sidebar order. A page that is not inSUMMARY.mdis not in the book. - 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
- @sms/contracts
- @sms/executor-node
- @sms/executor-quickjs
- @sms/host-cloudflare
- @sms/host-fastify
- @sms/host-node
- @sms/kernel
- @sms/model-claude
- @sms/model-claude-api
- @sms/model-gpt
- @sms/model-gpt-api
- @sms/model-gpt-oauth
- @sms/model-openrouter
- @sms/objects-r2
- @sms/objects-s3
- @sms/plugin-admin-api
- @sms/plugin-agent-loop
- @sms/plugin-audit
- @sms/plugin-auth
- @sms/plugin-automation
- @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-d1
- @sms/store-do
- @sms/store-postgres
- @sms/store-sql
- @sms/store-sqlite
@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
| Parameter | Type |
|---|---|
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
| Parameter | Type |
|---|---|
…args | unknown[] |
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
| Parameter | Type |
|---|---|
kernel | Kernel |
Returns
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
| Parameter | Type |
|---|---|
tenantId | string |
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
| Parameter | Type |
|---|---|
tenantId | string |
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
| Parameter | Type |
|---|---|
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
| Parameter | Type |
|---|---|
request | Request |
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
| Parameter | Type |
|---|---|
tenantId | string |
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
| Parameter | Type |
|---|---|
opts | BaselineOptions |
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
| Parameter | Type |
|---|---|
opts | TenantPoolOptions |
Returns
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
MENU_POINT
Re-exports MENU_POINT
MenuNode
Re-exports MenuNode
MenuSpec
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
SESSION_COOKIE
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
| Parameter | Type |
|---|---|
v | T |
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
| Parameter | Type |
|---|---|
make | (bridge) => SessionBackend |
opts | SessionBridgeOptions |
Returns
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
| Parameter | Type |
|---|---|
req | ModelRequest |
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
| Parameter | Type |
|---|---|
err | unknown |
Returns
void
onText()
onText(text): void;
Defined in: packages/core/contracts/src/model-session.ts:124
Assistant text produced by the SDK.
Parameters
| Parameter | Type |
|---|---|
text | string |
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
| Parameter | Type |
|---|---|
id | string |
name | string |
input | unknown |
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
| Parameter | Type |
|---|---|
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
| Parameter | Type |
|---|---|
name | string |
input | unknown |
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
| Parameter | Type |
|---|---|
table | string |
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
| Parameter | Type |
|---|---|
sql | string |
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 Parameter | Default type |
|---|---|
T | Record<string, unknown> |
Parameters
| Parameter | Type |
|---|---|
sql | string |
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
| Parameter | Type |
|---|---|
e | unknown |
Returns
void
resolve
resolve: (v) => void;
Defined in: packages/core/contracts/src/model-session.ts:29
Parameters
| Parameter | Type |
|---|---|
v | T |
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
| Parameter | Type |
|---|---|
handler | RequestHandler |
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
| Parameter | Type |
|---|---|
req | ModelRequest |
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
| Parameter | Type |
|---|---|
req | ModelRequest |
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
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
key
key: string;
Defined in: packages/core/contracts/src/objects.ts:11
Inherited from
lastModified
lastModified: number;
Defined in: packages/core/contracts/src/objects.ts:15
Unix ms.
Inherited from
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
size
size: number;
Defined in: packages/core/contracts/src/objects.ts:13
Bytes.
Inherited from
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
| Parameter | Type |
|---|---|
key | string |
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
| Parameter | Type |
|---|---|
key | string |
Returns
Promise<ObjectContent | undefined>
head()
head(key): Promise<ObjectMeta | undefined>;
Defined in: packages/core/contracts/src/objects.ts:57
Parameters
| Parameter | Type |
|---|---|
key | string |
Returns
Promise<ObjectMeta | undefined>
list()
list(opts?): Promise<ObjectList>;
Defined in: packages/core/contracts/src/objects.ts:60
Parameters
| Parameter | Type |
|---|---|
opts? | ListObjectsOptions |
Returns
Promise<ObjectList>
put()
put(
key,
body,
opts?
): Promise<ObjectMeta>;
Defined in: packages/core/contracts/src/objects.ts:54
Parameters
| Parameter | Type |
|---|---|
key | string |
body | ObjectBody |
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
| Parameter | Type |
|---|---|
text | string |
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
| Parameter | Type |
|---|---|
tools | ModelTool[] |
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
| Parameter | Type |
|---|---|
system | string |
tools | ModelTool[] |
prior | ModelMessage[] |
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
| Parameter | Type |
|---|---|
…args | unknown[] |
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
| Parameter | Type |
|---|---|
request | Request |
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
| Parameter | Type |
|---|---|
request | Request |
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
| Parameter | Type |
|---|---|
key | string |
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
| Parameter | Type |
|---|---|
id | string |
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
| Parameter | Type |
|---|---|
body | ObjectBody |
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
| Parameter | Type |
|---|---|
req | ModelRequest |
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
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
| Parameter | Type |
|---|---|
id | string |
model | ModelService |
Returns
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
| Parameter | Type | Default value |
|---|---|---|
max | number | 256 |
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
| Parameter | Type |
|---|---|
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
| Parameter | Type |
|---|---|
name | string |
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
| Parameter | Type |
|---|---|
response | ModelResponse |
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
| Parameter | Type |
|---|---|
content | ModelContent[] |
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
| Parameter | Type |
|---|---|
entries | Iterable<ObjectMeta> |
opts | ListObjectsOptions |
Returns
lowerKeys()
function lowerKeys(m): Record<string, string>;
Defined in: packages/core/contracts/src/objects.ts:147
Parameters
| Parameter | Type |
|---|---|
m | Record<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
| Parameter | Type |
|---|---|
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
| Parameter | Type |
|---|---|
raw | string |
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
| Parameter | Type |
|---|---|
prior | ModelMessage[] |
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
| Parameter | Type |
|---|---|
dialect | Dialect |
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
| Parameter | Type |
|---|---|
model | ModelService |
req | ModelRequest |
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
| Parameter | Type | Default value |
|---|---|---|
header | string | 'x-tenant' |
fallback? | string | undefined |
Returns
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.com → acme). localhost, IPs and the
bare root resolve to fallback; acme.localhost → acme for local development without DNS.
tenantFromSubdomain('dev') is shorthand for { fallback: 'dev' }.
Parameters
| Parameter | Type |
|---|---|
opts | string | SubdomainOptions |
Returns
toolSignature()
function toolSignature(tools): string;
Defined in: packages/core/contracts/src/model-session.ts:275
Parameters
| Parameter | Type |
|---|---|
tools | ModelTool[] |
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
| Parameter | Type |
|---|---|
messages | ModelMessage[] |
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
| Parameter | Type |
|---|---|
opts | NodeExecutorOptions |
Returns
Methods
load()
load(
bundle,
host,
opts?
): Promise<ExecutorInstance>;
Defined in: packages/drivers/executor/node/src/index.ts:23
Parameters
| Parameter | Type |
|---|---|
bundle | PluginBundle |
host | HostBridge |
opts | { timeoutMs?: number; } |
opts.timeoutMs? | number |
Returns
Promise<ExecutorInstance>
Implementation of
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
| Parameter | Type |
|---|---|
opts | QuickJSExecutorOptions |
Returns
Methods
load()
load(
bundle,
host,
opts?
): Promise<ExecutorInstance>;
Defined in: packages/drivers/executor/quickjs/src/index.ts:108
Parameters
| Parameter | Type |
|---|---|
bundle | PluginBundle |
host | HostBridge |
opts | { timeoutMs?: number; } |
opts.timeoutMs? | number |
Returns
Promise<ExecutorInstance>
Implementation of
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
| Parameter | Type |
|---|---|
state | DurableObjectStateLike |
env | Env |
Returns
{
fetch: Promise<Response>;
}
fetch()
fetch(request): Promise<Response>;
Parameters
| Parameter | Type |
|---|---|
request | Request |
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
| Parameter | Type |
|---|---|
request | Request |
env | Env |
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
| Parameter | Type |
|---|---|
event | ScheduledEventLike |
env | Env |
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
| Parameter | Type |
|---|---|
request | Request |
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
| Parameter | Type |
|---|---|
request | Request |
env | Env |
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
| Parameter | Type |
|---|---|
ctx | { env: Env; state: DurableObjectStateLike; tenantId: string; } |
ctx.env | Env |
ctx.state | DurableObjectStateLike |
ctx.tenantId | string |
Returns
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
| Parameter | Type |
|---|---|
ctx | { env: Env; store: Store; tenantId: string; } |
ctx.env | Env |
ctx.store | Store |
ctx.tenantId | string |
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
| Parameter | Type |
|---|---|
env | Env |
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
| Parameter | Type |
|---|---|
id | unknown |
Returns
idFromName()
idFromName(name): unknown;
Defined in: packages/drivers/host/cloudflare/src/index.ts:25
Parameters
| Parameter | Type |
|---|---|
name | string |
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
| Parameter | Type |
|---|---|
request | Request |
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
| Parameter | Type |
|---|---|
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
| Parameter | Type |
|---|---|
opts | CloudflareAppOptions<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
| Parameter | Type |
|---|---|
opts | FastifyHostOptions |
Returns
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
| Parameter | Type | Default value |
|---|---|---|
app | FastifyInstance | undefined |
handler | RequestHandler | undefined |
prefix | string | '' |
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
| Parameter | Type |
|---|---|
opts | NodeHostOptions |
Returns
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
| Parameter | Type |
|---|---|
res | ServerResponse |
response | Response |
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
| Parameter | Type | Default value |
|---|---|---|
req | IncomingMessage | undefined |
fallbackHost | string | '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
| Parameter | Type |
|---|---|
opts | KernelOptions |
Returns
Properties
blobs
readonly blobs: BlobStore;
Defined in: packages/core/kernel/src/kernel.ts:41
Implementation of
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
log
readonly log: EventLog;
Defined in: packages/core/kernel/src/kernel.ts:40
Implementation of
name
readonly name: string;
Defined in: packages/core/kernel/src/kernel.ts:39
Implementation of
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
| Parameter | Type |
|---|---|
manifest | PluginManifest |
Returns
void
Implementation of
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
| Parameter | Type |
|---|---|
manifest | PluginManifest |
issuedBy | string |
Returns
Promise<MountAuthorization>
Implementation of
contributions()
contributions<T>(point): Contribution<T>[];
Defined in: packages/core/kernel/src/kernel.ts:105
Type Parameters
| Type Parameter | Default type |
|---|---|
T | unknown |
Parameters
| Parameter | Type |
|---|---|
point | string |
Returns
Contribution<T>[]
Implementation of
defineKey()
defineKey(meta): void;
Defined in: packages/core/kernel/src/kernel.ts:78
Parameters
| Parameter | Type |
|---|---|
meta | KeyMeta |
Returns
void
Implementation of
definePoint()
definePoint(meta): void;
Defined in: packages/core/kernel/src/kernel.ts:82
Parameters
| Parameter | Type |
|---|---|
meta | ExtensionPointMeta |
Returns
void
Implementation of
disable()
disable(id, reason?): Promise<FiberView>;
Defined in: packages/core/kernel/src/kernel.ts:302
Parameters
| Parameter | Type | Default value |
|---|---|---|
id | string | undefined |
reason | string | 'disabled' |
Returns
Promise<FiberView>
Implementation of
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
| Parameter | Type |
|---|---|
id | string |
Returns
Promise<FiberView>
Implementation of
fiber()
fiber(id): FiberView | undefined;
Defined in: packages/core/kernel/src/kernel.ts:130
Parameters
| Parameter | Type |
|---|---|
id | string |
Returns
FiberView | undefined
Implementation of
fibers()
fibers(): FiberView[];
Defined in: packages/core/kernel/src/kernel.ts:126
Returns
Implementation of
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 Parameter | Default type |
|---|---|
T | unknown |
Parameters
| Parameter | Type |
|---|---|
key | string |
Returns
T | undefined
Implementation of
has()
has(key): boolean;
Defined in: packages/core/kernel/src/kernel.ts:96
Parameters
| Parameter | Type |
|---|---|
key | string |
Returns
boolean
Implementation of
install()
install(plugin, opts?): Promise<FiberView>;
Defined in: packages/core/kernel/src/kernel.ts:164
Install an in-process, system-trust plugin.
Parameters
| Parameter | Type |
|---|---|
plugin | SystemPlugin |
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
observeKeys()
observeKeys(observer): () => void;
Defined in: packages/core/kernel/src/kernel.ts:119
Parameters
| Parameter | Type |
|---|---|
observer | KeyObserver |
Returns
() => void
Implementation of
observePoint()
observePoint<T>(point, observer): () => void;
Defined in: packages/core/kernel/src/kernel.ts:109
Type Parameters
| Type Parameter | Default type |
|---|---|
T | unknown |
Parameters
| Parameter | Type |
|---|---|
point | string |
observer | PointObserver<T> |
Returns
() => void
Implementation of
points()
points(): ExtensionPointMeta[];
Defined in: packages/core/kernel/src/kernel.ts:92
Returns
Implementation of
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
| Parameter | Type |
|---|---|
proposed | PluginManifest |
auth | MountAuthorization |
Returns
Promise<FiberView>
Implementation of
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
| Parameter | Type |
|---|---|
executor | Executor |
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
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
| Parameter | Type | Default value |
|---|---|---|
id | string | undefined |
reason | string | 'uninstalled' |
opts | { force?: boolean; } | {} |
opts.force? | boolean | undefined |
Returns
Promise<void>
Implementation of
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
| Parameter | Type |
|---|---|
code | KernelErrorCode |
message | string |
Returns
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
| Parameter | Type |
|---|---|
targetObject | object |
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
| Parameter | Type |
|---|---|
err | Error |
stackTraces | CallSite[] |
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
Methods
get()
get(hash): Promise<string | undefined>;
Defined in: packages/core/kernel/src/log.ts:25
Parameters
| Parameter | Type |
|---|---|
hash | string |
Returns
Promise<string | undefined>
Implementation of
put()
put(bytes): Promise<string>;
Defined in: packages/core/kernel/src/log.ts:20
Parameters
| Parameter | Type |
|---|---|
bytes | string |
Returns
Promise<string>
Implementation of
MemoryEventLog
Defined in: packages/core/kernel/src/log.ts:3
Implements
Constructors
Constructor
new MemoryEventLog(): MemoryEventLog;
Returns
Methods
all()
all(): Promise<KernelEvent[]>;
Defined in: packages/core/kernel/src/log.ts:10
Returns
Promise<KernelEvent[]>
Implementation of
append()
append(event): Promise<KernelEvent>;
Defined in: packages/core/kernel/src/log.ts:5
Parameters
| Parameter | Type |
|---|---|
event | Omit<KernelEvent, "seq" | "ts"> |
Returns
Promise<KernelEvent>
Implementation of
since()
since(seq): Promise<KernelEvent[]>;
Defined in: packages/core/kernel/src/log.ts:13
Parameters
| Parameter | Type |
|---|---|
seq | number |
Returns
Promise<KernelEvent[]>
Implementation of
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
| Parameter | Type |
|---|---|
hash | string |
Returns
Promise<string | undefined>
put()
put(bytes): Promise<string>;
Defined in: packages/core/kernel/src/types.ts:201
Parameters
| Parameter | Type |
|---|---|
bytes | string |
Returns
Promise<string>
Contribution
Defined in: packages/core/kernel/src/types.ts:34
Type Parameters
| Type Parameter | Default type |
|---|---|
T | unknown |
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
| Parameter | Type |
|---|---|
event | Omit<KernelEvent, "seq" | "ts"> |
Returns
Promise<KernelEvent>
since()
since(seq): Promise<KernelEvent[]>;
Defined in: packages/core/kernel/src/types.ts:196
Parameters
| Parameter | Type |
|---|---|
seq | number |
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
| Parameter | Type |
|---|---|
bundle | PluginBundle |
host | HostBridge |
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
| Parameter | Type |
|---|---|
method | string |
args | unknown |
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
| Parameter | Type |
|---|---|
item | unknown |
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
| Parameter | Type |
|---|---|
method | string |
args | unknown |
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
| Parameter | Type |
|---|---|
manifest | PluginManifest |
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
| Parameter | Type |
|---|---|
manifest | PluginManifest |
issuedBy | string |
Returns
Promise<MountAuthorization>
contributions()
contributions<T>(point): Contribution<T>[];
Defined in: packages/core/kernel/src/types.ts:144
Type Parameters
| Type Parameter | Default type |
|---|---|
T | unknown |
Parameters
| Parameter | Type |
|---|---|
point | string |
Returns
Contribution<T>[]
defineKey()
defineKey(meta): void;
Defined in: packages/core/kernel/src/types.ts:137
Parameters
| Parameter | Type |
|---|---|
meta | KeyMeta |
Returns
void
definePoint()
definePoint(meta): void;
Defined in: packages/core/kernel/src/types.ts:138
Parameters
| Parameter | Type |
|---|---|
meta | ExtensionPointMeta |
Returns
void
disable()
disable(id, reason?): Promise<FiberView>;
Defined in: packages/core/kernel/src/types.ts:156
Parameters
| Parameter | Type |
|---|---|
id | string |
reason? | string |
Returns
Promise<FiberView>
enable()
enable(id): Promise<FiberView>;
Defined in: packages/core/kernel/src/types.ts:155
Parameters
| Parameter | Type |
|---|---|
id | string |
Returns
Promise<FiberView>
fiber()
fiber(id): FiberView | undefined;
Defined in: packages/core/kernel/src/types.ts:148
Parameters
| Parameter | Type |
|---|---|
id | string |
Returns
FiberView | undefined
fibers()
fibers(): FiberView[];
Defined in: packages/core/kernel/src/types.ts:147
Returns
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 Parameter | Default type |
|---|---|
T | unknown |
Parameters
| Parameter | Type |
|---|---|
key | string |
Returns
T | undefined
has()
has(key): boolean;
Defined in: packages/core/kernel/src/types.ts:141
Parameters
| Parameter | Type |
|---|---|
key | string |
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
| Parameter | Type |
|---|---|
observer | KeyObserver |
Returns
() => void
observePoint()
observePoint<T>(point, observer): () => void;
Defined in: packages/core/kernel/src/types.ts:145
Type Parameters
| Type Parameter | Default type |
|---|---|
T | unknown |
Parameters
| Parameter | Type |
|---|---|
point | string |
observer | PointObserver<T> |
Returns
() => void
points()
points(): ExtensionPointMeta[];
Defined in: packages/core/kernel/src/types.ts:140
Returns
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
| Parameter | Type |
|---|---|
manifest | PluginManifest |
auth | MountAuthorization |
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
| Parameter | Type |
|---|---|
id | string |
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
| Parameter | Type |
|---|---|
…args | unknown[] |
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
| Parameter | Type |
|---|---|
point | string |
item | unknown |
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 Parameter | Default type |
|---|---|
T | unknown |
Parameters
| Parameter | Type |
|---|---|
key | string |
Returns
T
log()
log(...args): void;
Defined in: packages/core/kernel/src/types.ts:106
Parameters
| Parameter | Type |
|---|---|
…args | unknown[] |
Returns
void
provide()
provide(key, value): void;
Defined in: packages/core/kernel/src/types.ts:103
Provide a key (revertible effect).
Parameters
| Parameter | Type |
|---|---|
key | string |
value | unknown |
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 Parameter | Default type |
|---|---|
T | unknown |
Properties
added?
optional added?: (c) => void | Promise<void>;
Defined in: packages/core/kernel/src/types.ts:128
Parameters
| Parameter | Type |
|---|---|
c | Contribution<T> |
Returns
void | Promise<void>
removed?
optional removed?: (c) => void | Promise<void>;
Defined in: packages/core/kernel/src/types.ts:129
Parameters
| Parameter | Type |
|---|---|
c | Contribution<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
| Parameter | Type |
|---|---|
ctx | PluginContext |
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
| Parameter | Type |
|---|---|
event | "provided" | "withdrawn" |
key | string |
value | unknown |
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
Returns
void
foldTarget()
function foldTarget(events): Map<string, TargetEntry>;
Defined in: packages/core/kernel/src/log.ts:44
Parameters
| Parameter | Type |
|---|---|
events | KernelEvent[] |
Returns
Map<string, TargetEntry>
sha256()
function sha256(text): Promise<string>;
Defined in: packages/core/kernel/src/log.ts:30
Parameters
| Parameter | Type |
|---|---|
text | string |
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
| Parameter | Type |
|---|---|
value | unknown |
Returns
unknown
unmarshal()
function unmarshal(value, instance): unknown;
Defined in: packages/core/kernel/src/marshal.ts:10
Parameters
| Parameter | Type |
|---|---|
value | unknown |
instance | ExecutorInstance |
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
| Parameter | Type |
|---|---|
…args | unknown[] |
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
| Parameter | Type |
|---|---|
opts | ClaudeModelOptions |
Returns
ModelService & {
close: void;
}
createClaudeModelPlugin()
function createClaudeModelPlugin(opts?): SystemPlugin;
Defined in: packages/drivers/model/claude/src/index.ts:217
Parameters
| Parameter | Type |
|---|---|
opts | ClaudeModelOptions |
Returns
@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
| Parameter | Type |
|---|---|
…args | unknown[] |
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>;
Parameters
| Parameter | Type |
|---|---|
input | RequestInfo | URL |
init? | RequestInit |
Returns
Promise<Response>
Call Signature
(input, init?): Promise<Response>;
Parameters
| Parameter | Type |
|---|---|
input | string | 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
| Parameter | Type |
|---|---|
opts | ClaudeApiModelOptions |
Returns
createClaudeApiModel()
function createClaudeApiModel(opts?): ModelService;
Defined in: packages/drivers/model/claude-api/src/index.ts:136
Parameters
| Parameter | Type |
|---|---|
opts | ClaudeApiModelOptions |
Returns
@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
| Parameter | Type |
|---|---|
…args | unknown[] |
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
| Parameter | Type |
|---|---|
opts | GptModelOptions |
Returns
ModelService & {
close: void;
}
createGptModelPlugin()
function createGptModelPlugin(opts?): SystemPlugin;
Defined in: packages/drivers/model/gpt/src/index.ts:294
Parameters
| Parameter | Type |
|---|---|
opts | GptModelOptions |
Returns
@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
| Parameter | Type |
|---|---|
…args | unknown[] |
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>;
Parameters
| Parameter | Type |
|---|---|
input | RequestInfo | URL |
init? | RequestInit |
Returns
Promise<Response>
Call Signature
(input, init?): Promise<Response>;
Parameters
| Parameter | Type |
|---|---|
input | string | 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
| Parameter | Type |
|---|---|
opts | GptApiModelOptions |
Returns
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
| Parameter | Type |
|---|---|
opts | GptApiModelOptions |
Returns
@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
| Parameter | Type |
|---|---|
opts | TokenManagerOptions |
Returns
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
| Parameter | Type |
|---|---|
…args | unknown[] |
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>;
Parameters
| Parameter | Type |
|---|---|
input | RequestInfo | URL |
init? | RequestInit |
Returns
Promise<Response>
Call Signature
(input, init?): Promise<Response>;
Parameters
| Parameter | Type |
|---|---|
input | string | 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>;
Parameters
| Parameter | Type |
|---|---|
input | RequestInfo | URL |
init? | RequestInit |
Returns
Promise<Response>
Call Signature
(input, init?): Promise<Response>;
Parameters
| Parameter | Type |
|---|---|
input | string | 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
| Parameter | Type |
|---|---|
tokens | CodexTokens |
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
| Parameter | Type |
|---|---|
tokens | CodexTokens |
Returns
string | undefined
createGptOauthModel()
function createGptOauthModel(opts): ModelService;
Defined in: packages/drivers/model/gpt-oauth/src/index.ts:254
Parameters
| Parameter | Type |
|---|---|
opts | GptOauthModelOptions |
Returns
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
| Parameter | Type |
|---|---|
opts | GptOauthModelOptions |
Returns
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
| Parameter | Type |
|---|---|
token | string |
Returns
number | undefined
jwtPayload()
function jwtPayload(token): Record<string, unknown>;
Defined in: packages/drivers/model/gpt-oauth/src/auth.ts:34
Parameters
| Parameter | Type |
|---|---|
token | string |
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
| Parameter | Type | Default value |
|---|---|---|
kv | { get: string | Promise<string | null> | null; put: void | Promise<void>; } | undefined |
kv.get | undefined | |
kv.put | undefined | |
key | string | 'codex-oauth' |
Returns
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
| Parameter | Type |
|---|---|
json | string | Record<string, unknown> |
Returns
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
| Parameter | Type |
|---|---|
tokens | CodexTokens |
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
| Parameter | Type |
|---|---|
…args | unknown[] |
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>;
Parameters
| Parameter | Type |
|---|---|
input | RequestInfo | URL |
init? | RequestInit |
Returns
Promise<Response>
Call Signature
(input, init?): Promise<Response>;
Parameters
| Parameter | Type |
|---|---|
input | string | 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
| Parameter | Type |
|---|---|
opts | OpenRouterModelOptions |
Returns
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
| Parameter | Type |
|---|---|
opts | OpenRouterModelOptions |
Returns
@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
| Parameter | Type |
|---|---|
key | string |
Returns
Promise<void>
get()
get(key): Promise<R2ObjectBodyLike | null>;
Defined in: packages/drivers/objects/r2/src/index.ts:33
Parameters
| Parameter | Type |
|---|---|
key | string |
Returns
Promise<R2ObjectBodyLike | null>
head()
head(key): Promise<R2ObjectLike | null>;
Defined in: packages/drivers/objects/r2/src/index.ts:34
Parameters
| Parameter | Type |
|---|---|
key | string |
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
| Parameter | Type |
|---|---|
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
| Parameter | Type |
|---|---|
key | string |
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
etag
etag: string;
Defined in: packages/drivers/objects/r2/src/index.ts:19
Inherited from
httpMetadata?
optional httpMetadata?: {
contentType?: string;
};
Defined in: packages/drivers/objects/r2/src/index.ts:21
contentType?
optional contentType?: string;
Inherited from
key
key: string;
Defined in: packages/drivers/objects/r2/src/index.ts:17
Inherited from
size
size: number;
Defined in: packages/drivers/objects/r2/src/index.ts:18
Inherited from
uploaded
uploaded: Date;
Defined in: packages/drivers/objects/r2/src/index.ts:20
Inherited from
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
| Parameter | Type |
|---|---|
bucket | R2BucketLike |
Returns
@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
| Parameter | Type |
|---|---|
status | number |
body | string |
method | string |
key? | string |
Returns
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
| Parameter | Type |
|---|---|
targetObject | object |
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
| Parameter | Type |
|---|---|
err | Error |
stackTraces | CallSite[] |
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>;
Parameters
| Parameter | Type |
|---|---|
input | RequestInfo | URL |
init? | RequestInit |
Returns
Promise<Response>
Call Signature
(input, init?): Promise<Response>;
Parameters
| Parameter | Type |
|---|---|
input | string | 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
| Parameter | Type |
|---|---|
opts | S3Options |
Returns
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
| Parameter | Type |
|---|---|
creds | SigV4Credentials |
input | SignInput |
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
| Parameter | Type |
|---|---|
opts | AdminApiOptions |
Returns
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
| Parameter | Type |
|---|---|
sessionId | string |
text | string |
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
| Parameter | Type |
|---|---|
sessionId | string |
text | string |
Returns
AsyncIterable<AgentEvent>
history()
history(sessionId): ModelMessage[];
Defined in: packages/plugins/agent-loop/src/contract.ts:66
Parameters
| Parameter | Type |
|---|---|
sessionId | string |
Returns
reset()
reset(sessionId): void;
Defined in: packages/plugins/agent-loop/src/contract.ts:67
Parameters
| Parameter | Type |
|---|---|
sessionId | string |
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
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
| Parameter | Type |
|---|---|
sessionId | string |
messages | ModelMessage[] |
Returns
Promise<void>
load()
load(sessionId): Promise<
| ModelMessage[]
| undefined>;
Defined in: packages/plugins/agent-loop/src/contract.ts:78
Parameters
| Parameter | Type |
|---|---|
sessionId | string |
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
| Parameter | Type |
|---|---|
input | Record<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
| Parameter | Type |
|---|---|
kernel | KernelApi |
Returns
unknown
createAgentLoopPlugin()
function createAgentLoopPlugin(opts?): SystemPlugin;
Defined in: packages/plugins/agent-loop/src/index.ts:34
Parameters
| Parameter | Type |
|---|---|
opts | AgentLoopOptions |
Returns
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
| Parameter | Type |
|---|---|
req | RouteRequest |
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
| Parameter | Type |
|---|---|
model | string |
id | number |
opts | PostOptions |
ctx | OpContext |
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
| Parameter | Type |
|---|---|
opts | AuditOptions |
Returns
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
| Parameter | Type |
|---|---|
f | FieldSpec |
v | unknown |
Returns
string | null
validateAuditTrack()
function validateAuditTrack(item): void;
Defined in: packages/plugins/audit/src/tracking.ts:27
Parameters
| Parameter | Type |
|---|---|
item | unknown |
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
| Parameter | Type |
|---|---|
req | RouteRequest |
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
| Parameter | Type |
|---|---|
id | number |
Returns
Promise<void>
create()
create(input): Promise<User>;
Defined in: packages/plugins/auth/src/contract.ts:40
Parameters
| Parameter | Type |
|---|---|
input | { isAdmin?: boolean; login: string; name?: string; password: string; } |
input.isAdmin? | boolean |
input.login | string |
input.name? | string |
input.password | string |
Returns
Promise<User>
deactivate()
deactivate(id): Promise<void>;
Defined in: packages/plugins/auth/src/contract.ts:45
Also ends the user’s sessions.
Parameters
| Parameter | Type |
|---|---|
id | number |
Returns
Promise<void>
setAdmin()
setAdmin(id, isAdmin): Promise<void>;
Defined in: packages/plugins/auth/src/contract.ts:43
Parameters
| Parameter | Type |
|---|---|
id | number |
isAdmin | boolean |
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
| Parameter | Type |
|---|---|
id | number |
password | string |
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
| Parameter | Type |
|---|---|
login | string |
password | string |
Returns
Promise<Session | undefined>
logout()
logout(token): Promise<void>;
Defined in: packages/plugins/auth/src/contract.ts:33
Parameters
| Parameter | Type |
|---|---|
token | string |
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
| Parameter | Type |
|---|---|
token | string |
Returns
Promise<Session | undefined>
user()
user(id): Promise<User | undefined>;
Defined in: packages/plugins/auth/src/contract.ts:30
Parameters
| Parameter | Type |
|---|---|
id | number |
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
| Parameter | Type |
|---|---|
req | RouteRequest |
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
SESSION_COOKIE
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
| Parameter | Type |
|---|---|
opts | AuthOptions |
Returns
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
| Parameter | Type | Default value |
|---|---|---|
password | string | undefined |
iterations | number | PBKDF2_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
| Parameter | Type |
|---|---|
req | RouteRequest |
Returns
string | undefined
verifyPassword()
function verifyPassword(password, stored): Promise<boolean>;
Defined in: packages/plugins/auth/src/crypto.ts:44
Parameters
| Parameter | Type |
|---|---|
password | string |
stored | string |
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
| Parameter | Type |
|---|---|
opts | AutomationOptions |
Returns
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
| Parameter | Type |
|---|---|
item | unknown |
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
| Parameter | Type |
|---|---|
record | Record<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
| Parameter | Type |
|---|---|
name | string |
data | Record<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
| Parameter | Type |
|---|---|
name | string |
id | number |
Returns
Promise<Record<string, unknown> | undefined>
list()
list(name, opts?): Promise<Record<string, unknown>[]>;
Defined in: packages/plugins/collections/src/contract.ts:41
Parameters
| Parameter | Type |
|---|---|
name | string |
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
| Parameter | Type |
|---|---|
name | string |
id | number |
Returns
Promise<boolean>
schema()
schema(name): CollectionSchema | undefined;
Defined in: packages/plugins/collections/src/contract.ts:40
Parameters
| Parameter | Type |
|---|---|
name | string |
Returns
CollectionSchema | undefined
update()
update(
name,
id,
data
): Promise<Record<string, unknown>>;
Defined in: packages/plugins/collections/src/contract.ts:47
Parameters
| Parameter | Type |
|---|---|
name | string |
id | number |
data | Record<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
| Parameter | Type |
|---|---|
f | unknown |
Returns
asserts f is Field
validateSchema()
function validateSchema(s): asserts s is CollectionSchema;
Defined in: packages/plugins/collections/src/contract.ts:68
Parameters
| Parameter | Type |
|---|---|
s | unknown |
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
| Parameter | Type |
|---|---|
status | number |
message | string |
kind | string |
Returns
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
| Parameter | Type |
|---|---|
targetObject | object |
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
| Parameter | Type |
|---|---|
err | Error |
stackTraces | CallSite[] |
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
| Parameter | Type |
|---|---|
request | Request |
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
| Parameter | Type |
|---|---|
req | RouteRequest |
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
| Parameter | Type |
|---|---|
req | RouteRequest |
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
| Parameter | Type |
|---|---|
req | RouteRequest |
name | string |
Returns
string | undefined
errorJson()
function errorJson(
message,
status?,
kind?
): Response;
Defined in: packages/plugins/http/src/contract.ts:72
Parameters
| Parameter | Type | Default value |
|---|---|---|
message | string | undefined |
status | number | 500 |
kind | string | ... |
Returns
Response
html()
function html(body, status?): Response;
Defined in: packages/plugins/http/src/contract.ts:32
Parameters
| Parameter | Type | Default value |
|---|---|---|
body | string | undefined |
status | number | 200 |
Returns
Response
json()
function json(
body,
status?,
headers?
): Response;
Defined in: packages/plugins/http/src/contract.ts:30
Parameters
| Parameter | Type | Default value |
|---|---|---|
body | unknown | undefined |
status | number | 200 |
headers | Record<string, string> | {} |
Returns
Response
matchPath()
function matchPath(pattern, path): Record<string, string> | null;
Defined in: packages/plugins/http/src/contract.ts:151
Parameters
| Parameter | Type |
|---|---|
pattern | string |
path | string |
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
| Parameter | Type |
|---|---|
name | string |
value | string |
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
| Parameter | Type | Default value |
|---|---|---|
events | AsyncIterable<unknown> | undefined |
status | number | 200 |
Returns
Response
text()
function text(body, status?): Response;
Defined in: packages/plugins/http/src/contract.ts:34
Parameters
| Parameter | Type | Default value |
|---|---|---|
body | string | undefined |
status | number | 200 |
Returns
Response
toResponse()
function toResponse(result): Response;
Defined in: packages/plugins/http/src/contract.ts:168
Parameters
| Parameter | Type |
|---|---|
result | unknown |
Returns
Response
validateRoute()
function validateRoute(item): void;
Defined in: packages/plugins/http/src/contract.ts:138
Parameters
| Parameter | Type |
|---|---|
item | unknown |
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
| Parameter | Type |
|---|---|
ctx | GateContext |
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
| Parameter | Type |
|---|---|
kernel | KernelApi |
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
| Parameter | Type |
|---|---|
pluginId | string |
by | string |
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
reject()
reject(
pluginId,
by,
reason?
): Promise<Verdict>;
Defined in: packages/plugins/judge/src/contract.ts:61
Parameters
| Parameter | Type |
|---|---|
pluginId | string |
by | string |
reason? | string |
Returns
Promise<Verdict>
submit()
submit(manifest, submittedBy): Promise<Verdict>;
Defined in: packages/plugins/judge/src/contract.ts:58
Parameters
| Parameter | Type |
|---|---|
manifest | PluginManifest |
submittedBy | string |
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
| Parameter | Type |
|---|---|
opts | JudgeOptions |
Returns
@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
MenuNode
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
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
groups?
optional groups?: string[];
Defined in: packages/plugins/meta/src/types.ts:66
Inherited from
icon?
optional icon?: string;
Defined in: packages/plugins/meta/src/types.ts:64
Inherited from
id
id: string;
Defined in: packages/plugins/meta/src/types.ts:59
Inherited from
label
label: string;
Defined in: packages/plugins/meta/src/types.ts:60
Inherited from
parent?
optional parent?: string;
Defined in: packages/plugins/meta/src/types.ts:61
Inherited from
sequence?
optional sequence?: number;
Defined in: packages/plugins/meta/src/types.ts:63
Inherited from
MenuSpec
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
| Parameter | Type |
|---|---|
id | string |
Returns
ActionSpec | undefined
actions()
actions(): ActionSpec[];
Defined in: packages/plugins/meta/src/types.ts:87
Returns
actionsFor()
actionsFor(model): ActionSpec[];
Defined in: packages/plugins/meta/src/types.ts:88
Parameters
| Parameter | Type |
|---|---|
model | string |
Returns
menu()
menu(id): MenuSpec | undefined;
Defined in: packages/plugins/meta/src/types.ts:91
Parameters
| Parameter | Type |
|---|---|
id | string |
Returns
MenuSpec | undefined
menus()
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
| Parameter | Type |
|---|---|
ctx | { groups: string[]; } |
ctx.groups | string[] |
Returns
MenuNode[]
view()
view(
model,
kind,
id?
): CompiledView | undefined;
Defined in: packages/plugins/meta/src/types.ts:84
Parameters
| Parameter | Type |
|---|---|
model | string |
kind | ViewKind |
id? | string |
Returns
CompiledView | undefined
views()
views(model): Partial<Record<ViewKind, CompiledView>>;
Defined in: packages/plugins/meta/src/types.ts:85
Parameters
| Parameter | Type |
|---|---|
model | string |
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
MENU_POINT
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
Returns
buildMenuTree()
function buildMenuTree(input): MenuNode[];
Defined in: packages/plugins/meta/src/menus.ts:44
Parameters
| Parameter | Type |
|---|---|
input | MenuInput |
Returns
MenuNode[]
cloneNode()
function cloneNode(node): ViewNode;
Defined in: packages/plugins/meta/src/selector.ts:61
Parameters
| Parameter | Type |
|---|---|
node | ViewNode |
Returns
compileFromBase()
function compileFromBase(base, all): CompiledView;
Defined in: packages/plugins/meta/src/compile.ts:87
Parameters
Returns
createMetaService()
function createMetaService(regs): MetaService & {
invalidate: void;
};
Defined in: packages/plugins/meta/src/index.ts:35
Parameters
| Parameter | Type |
|---|---|
regs | Registries |
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
| Parameter | Type |
|---|---|
root | ViewNode |
sel | Selector |
Returns
Match | undefined
parseSelector()
function parseSelector(target): Selector;
Defined in: packages/plugins/meta/src/selector.ts:22
Parameters
| Parameter | Type |
|---|---|
target | string |
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
Returns
ViewSpec | undefined
validateAction()
function validateAction(item): asserts item is ActionSpec;
Defined in: packages/plugins/meta/src/validate.ts:57
Parameters
| Parameter | Type |
|---|---|
item | unknown |
Returns
asserts item is ActionSpec
validateMenu()
function validateMenu(item): asserts item is MenuSpec;
Defined in: packages/plugins/meta/src/validate.ts:68
Parameters
| Parameter | Type |
|---|---|
item | unknown |
Returns
asserts item is MenuSpec
validateView()
function validateView(item): asserts item is ViewSpec;
Defined in: packages/plugins/meta/src/validate.ts:37
Parameters
| Parameter | Type |
|---|---|
item | unknown |
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
| Parameter | Type |
|---|---|
kind | OrmErrorKind |
message | string |
Returns
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
| Parameter | Type |
|---|---|
targetObject | object |
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
| Parameter | Type |
|---|---|
err | Error |
stackTraces | CallSite[] |
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
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
index?
optional index?: boolean;
Defined in: packages/plugins/orm/src/types.ts:45
Inherited from
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
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
required?
optional required?: boolean;
Defined in: packages/plugins/orm/src/types.ts:41
Inherited from
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
description?
optional description?: string;
Defined in: packages/plugins/orm/src/types.ts:40
Inherited from
index?
optional index?: boolean;
Defined in: packages/plugins/orm/src/types.ts:45
Inherited from
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
readonly?
optional readonly?: boolean;
Defined in: packages/plugins/orm/src/types.ts:42
Inherited from
required?
optional required?: boolean;
Defined in: packages/plugins/orm/src/types.ts:41
Inherited from
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
description?
optional description?: string;
Defined in: packages/plugins/orm/src/types.ts:40
Inherited from
index?
optional index?: boolean;
Defined in: packages/plugins/orm/src/types.ts:45
Inherited from
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
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
required?
optional required?: boolean;
Defined in: packages/plugins/orm/src/types.ts:41
Inherited from
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
| Parameter | Type |
|---|---|
env | MethodEnv |
payload | HookPayload |
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
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
Returns
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
description?
optional description?: string;
Defined in: packages/plugins/orm/src/types.ts:40
Inherited from
index?
optional index?: boolean;
Defined in: packages/plugins/orm/src/types.ts:45
Inherited from
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
readonly?
optional readonly?: boolean;
Defined in: packages/plugins/orm/src/types.ts:42
Inherited from
required?
optional required?: boolean;
Defined in: packages/plugins/orm/src/types.ts:41
Inherited from
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
Returns
boolean | Promise<boolean>
domain()
domain(q): Domain | Promise<Domain>;
Defined in: packages/plugins/orm/src/types.ts:183
Parameters
Returns
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
| Parameter | Type |
|---|---|
req | RouteRequest |
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
| Parameter | Type |
|---|---|
model | string |
method | string |
req | CallRequest |
ctx | OpContext |
Returns
Promise<unknown>
count()
count(
model,
domain,
ctx
): Promise<number>;
Defined in: packages/plugins/orm/src/types.ts:201
Parameters
Returns
Promise<number>
create()
create(
model,
values,
ctx
): Promise<number>;
Defined in: packages/plugins/orm/src/types.ts:208
Parameters
Returns
Promise<number>
defaults()
defaults(model, ctx): Values;
Defined in: packages/plugins/orm/src/types.ts:214
Parameters
| Parameter | Type |
|---|---|
model | string |
ctx | OpContext |
Returns
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
| Parameter | Type |
|---|---|
event | OrmEvent |
listener | OrmListener |
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
Returns
Promise<Values>
read()
read(
model,
ids,
fields,
ctx
): Promise<Rec[]>;
Defined in: packages/plugins/orm/src/types.ts:202
Parameters
Returns
Promise<Rec[]>
readGroup()
readGroup(
model,
req,
ctx
): Promise<GroupRow[]>;
Defined in: packages/plugins/orm/src/types.ts:211
Parameters
| Parameter | Type |
|---|---|
model | string |
req | ReadGroupRequest |
ctx | OpContext |
Returns
Promise<GroupRow[]>
search()
search(
model,
domain,
ctx,
opts?
): Promise<number[]>;
Defined in: packages/plugins/orm/src/types.ts:200
Parameters
| Parameter | Type |
|---|---|
model | string |
domain | Domain |
ctx | OpContext |
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
| Parameter | Type |
|---|---|
model | string |
req | SearchReadRequest |
ctx | OpContext |
Returns
Promise<{
length: number;
records: Rec[];
}>
setGuard()
setGuard(guard): void;
Defined in: packages/plugins/orm/src/types.ts:217
Parameters
| Parameter | Type |
|---|---|
guard | OrmGuard | 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
| Parameter | Type |
|---|---|
model | string |
Returns
ModelSpec | undefined
unlink()
unlink(
model,
ids,
ctx
): Promise<void>;
Defined in: packages/plugins/orm/src/types.ts:210
Parameters
| Parameter | Type |
|---|---|
model | string |
ids | number[] |
ctx | OpContext |
Returns
Promise<void>
write()
write(
model,
ids,
values,
ctx
): Promise<void>;
Defined in: packages/plugins/orm/src/types.ts:209
Parameters
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
description?
optional description?: string;
Defined in: packages/plugins/orm/src/types.ts:40
Inherited from
index?
optional index?: boolean;
Defined in: packages/plugins/orm/src/types.ts:45
Inherited from
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
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
required?
optional required?: boolean;
Defined in: packages/plugins/orm/src/types.ts:41
Inherited from
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
description?
optional description?: string;
Defined in: packages/plugins/orm/src/types.ts:40
Inherited from
index?
optional index?: boolean;
Defined in: packages/plugins/orm/src/types.ts:45
Inherited from
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
readonly?
optional readonly?: boolean;
Defined in: packages/plugins/orm/src/types.ts:42
Inherited from
required?
optional required?: boolean;
Defined in: packages/plugins/orm/src/types.ts:41
Inherited from
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
offset?
optional offset?: number;
Defined in: packages/plugins/orm/src/types.ts:22
Inherited from
order?
optional order?: string;
Defined in: packages/plugins/orm/src/types.ts:24
'name asc, id desc'
Inherited from
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
description?
optional description?: string;
Defined in: packages/plugins/orm/src/types.ts:40
Inherited from
index?
optional index?: boolean;
Defined in: packages/plugins/orm/src/types.ts:45
Inherited from
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
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
required?
optional required?: boolean;
Defined in: packages/plugins/orm/src/types.ts:41
Inherited from
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
| Parameter | Type |
|---|---|
payload | OrmEventPayload |
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
| Parameter | Type |
|---|---|
opts | OrmOptions |
Returns
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
| Parameter | Type |
|---|---|
err | unknown |
Returns
unknown
sudo()
function sudo(ctx): OpContext;
Defined in: packages/plugins/orm/src/core.ts:42
Parameters
| Parameter | Type |
|---|---|
ctx | OpContext |
Returns
validateField()
function validateField(rawName, f): asserts f is FieldSpec;
Defined in: packages/plugins/orm/src/registry.ts:95
Parameters
| Parameter | Type |
|---|---|
rawName | unknown |
f | unknown |
Returns
asserts f is FieldSpec
validateModel()
function validateModel(m): asserts m is ModelSpec;
Defined in: packages/plugins/orm/src/registry.ts:139
Parameters
| Parameter | Type |
|---|---|
m | unknown |
Returns
asserts m is ModelSpec
validateModelField()
function validateModelField(item): asserts item is ModelFieldContribution;
Defined in: packages/plugins/orm/src/registry.ts:150
Parameters
| Parameter | Type |
|---|---|
item | unknown |
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
unlink?
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
| Parameter | Type |
|---|---|
userId | number |
Returns
Promise<string[]>
grant()
grant(userId, group): Promise<void>;
Defined in: packages/plugins/rbac/src/contract.ts:67
Parameters
| Parameter | Type |
|---|---|
userId | number |
group | string |
Returns
Promise<void>
members()
members(group): Promise<number[]>;
Defined in: packages/plugins/rbac/src/contract.ts:71
Parameters
| Parameter | Type |
|---|---|
group | string |
Returns
Promise<number[]>
revoke()
revoke(userId, group): Promise<void>;
Defined in: packages/plugins/rbac/src/contract.ts:68
Parameters
| Parameter | Type |
|---|---|
userId | number |
group | string |
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
| Parameter | Type |
|---|---|
q | Query |
Returns
Promise<void>
can()
can(q): Promise<boolean>;
Defined in: packages/plugins/rbac/src/contract.ts:58
Parameters
| Parameter | Type |
|---|---|
q | Query |
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
| Parameter | Type |
|---|---|
userId | number |
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
| Parameter | Type |
|---|---|
q | Query |
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
| Parameter | Type |
|---|---|
names | Iterable<string> |
groups | Map<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
| Parameter | Type |
|---|---|
ds | Domain[] |
Returns
validateAccess()
function validateAccess(item): void;
Defined in: packages/plugins/rbac/src/contract.ts:88
Parameters
| Parameter | Type |
|---|---|
item | unknown |
Returns
void
validateGroup()
function validateGroup(item): void;
Defined in: packages/plugins/rbac/src/contract.ts:82
Parameters
| Parameter | Type |
|---|---|
item | unknown |
Returns
void
validateRule()
function validateRule(item): void;
Defined in: packages/plugins/rbac/src/contract.ts:94
Parameters
| Parameter | Type |
|---|---|
item | unknown |
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
| Parameter | Type |
|---|---|
req | RouteRequest |
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
| Parameter | Type |
|---|---|
opts | RpcOptions |
Returns
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
Returns
Promise<string[]>
parseCall()
function parseCall(body): RpcCall;
Defined in: packages/plugins/rpc/src/methods.ts:50
Parse one raw call.
Parameters
| Parameter | Type |
|---|---|
body | unknown |
Returns
rightsOf()
function rightsOf(o): Promise<Rights>;
Defined in: packages/plugins/rpc/src/rights.ts:14
Parameters
| Parameter | Type |
|---|---|
o | { ctx: OpContext; kernel: KernelApi; model: string; } |
o.ctx | OpContext |
o.kernel | KernelApi |
o.model | string |
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
| Parameter | Type |
|---|---|
env | RpcEnv |
raw | unknown |
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
| Parameter | Type |
|---|---|
run | { lastRun?: number; name: string; now: number; } |
run.lastRun? | number |
run.name | string |
run.now | number |
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
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
| Parameter | Type |
|---|---|
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
| Parameter | Type |
|---|---|
item | unknown |
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
| Parameter | Type |
|---|---|
point | string |
item | unknown |
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 Parameter | Default type |
|---|---|
T | unknown |
Parameters
| Parameter | Type |
|---|---|
key | string |
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 Parameter | Default type |
|---|---|
T | unknown |
Parameters
| Parameter | Type |
|---|---|
key | string |
method | string |
…args | unknown[] |
Returns
Promise<T>
log()
log(...args): void;
Defined in: packages/core/plugin-sdk/src/runtime.ts:15
Parameters
| Parameter | Type |
|---|---|
…args | unknown[] |
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
| Parameter | Type |
|---|---|
key | string |
value | unknown |
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
| Parameter | Type |
|---|---|
method | string |
args | unknown |
timeoutMs? | number |
Returns
Promise<unknown>
close()
close(reason?): void;
Defined in: packages/core/plugin-sdk/src/channel.ts:13
Parameters
| Parameter | Type |
|---|---|
reason? | string |
Returns
void
receive()
receive(msg): void;
Defined in: packages/core/plugin-sdk/src/channel.ts:12
Parameters
| Parameter | Type |
|---|---|
msg | RpcMessage |
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
| Parameter | Type |
|---|---|
method | string |
args | unknown |
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
| Parameter | Type |
|---|---|
cap | Cap |
Returns
void | Promise<void>
Functions
createChannel()
function createChannel(post, handle): Channel;
Defined in: packages/core/plugin-sdk/src/channel.ts:16
Parameters
| Parameter | Type |
|---|---|
post | (msg) => void |
handle | (method, args) => Promise<unknown> |
Returns
createPluginRuntime()
function createPluginRuntime(hostCall, loadModule): PluginRuntime;
Defined in: packages/core/plugin-sdk/src/runtime.ts:31
Parameters
| Parameter | Type |
|---|---|
hostCall | (method, args) => Promise<unknown> |
loadModule | () => Promise<PluginModule> |
Returns
resolveActivate()
function resolveActivate(mod): Activate | undefined;
Defined in: packages/core/plugin-sdk/src/runtime.ts:89
Parameters
| Parameter | Type |
|---|---|
mod | PluginModule |
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
| Parameter | Type |
|---|---|
query | string |
Returns
Promise<unknown>
prepare()
prepare(query): D1StatementLike;
Defined in: packages/drivers/store/d1/src/index.ts:12
Parameters
| Parameter | Type |
|---|---|
query | string |
Returns
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 Parameter | Default type |
|---|---|
T | Record<string, unknown> |
Returns
Promise<{
results: T[];
}>
bind()
bind(...values): D1StatementLike;
Defined in: packages/drivers/store/d1/src/index.ts:16
Parameters
| Parameter | Type |
|---|---|
…values | unknown[] |
Returns
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
| Parameter | Type |
|---|---|
d1 | D1DatabaseLike |
Returns
openD1Store()
function openD1Store(d1): Promise<Store>;
Defined in: packages/drivers/store/d1/src/index.ts:50
Parameters
| Parameter | Type |
|---|---|
d1 | D1DatabaseLike |
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
| Parameter | Type |
|---|---|
query | string |
…bindings | unknown[] |
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
| Parameter | Type |
|---|---|
sql | SqlStorageLike |
Returns
openDurableObjectStore()
function openDurableObjectStore(sql): Promise<Store>;
Defined in: packages/drivers/store/do/src/index.ts:34
Parameters
| Parameter | Type |
|---|---|
sql | SqlStorageLike |
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
| Parameter | Type |
|---|---|
text | string |
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
| Parameter | Type |
|---|---|
opts | PostgresOptions |
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
| Parameter | Type |
|---|---|
client | PgClient |
opts | { owned?: boolean; schema?: string; } |
opts.owned? | boolean |
opts.schema? | string |
Returns
@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
| Parameter | Type |
|---|---|
v | unknown |
Returns
unknown
createSqlStore()
function createSqlStore(db): Promise<Store>;
Defined in: packages/drivers/store/sql/src/index.ts:20
Parameters
| Parameter | Type |
|---|---|
db | Database |
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
| Parameter | Type |
|---|---|
sql | string |
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
db
db: Database;
Defined in: packages/core/contracts/src/index.ts:46
Inherited from
log
log: EventLog;
Defined in: packages/core/contracts/src/index.ts:47
Inherited from
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
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
| Parameter | Type |
|---|---|
path | string |
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
| Parameter | Type |
|---|---|
db | DatabaseSync |