Skip to main content

Interface: SqlSpendMeterOptions

Defined in: packages/agentos/src/safety/runtime/SqlSpendMeter.ts:184

Properties​

db​

db: StorageAdapter

Defined in: packages/agentos/src/safety/runtime/SqlSpendMeter.ts:185


ensureSchema?​

optional ensureSchema: boolean

Defined in: packages/agentos/src/safety/runtime/SqlSpendMeter.ts:234

Create the tables when they are missing, and on tables that exist the indexes they lack (see SqlSpendMeter.ensureSchema). Default true. With false the meter runs no DDL: the product's own migrations make the tables and their indexes.


leaseMs?​

optional leaseMs: number

Defined in: packages/agentos/src/safety/runtime/SqlSpendMeter.ts:202

How long a reservation lives without a heartbeat. Default 45 seconds.


maxAttemptsPerOperation?​

optional maxAttemptsPerOperation: number

Defined in: packages/agentos/src/safety/runtime/SqlSpendMeter.ts:204

Reservations an operation may take in all, its retries after a release included. Default 3.


requireShared?​

optional requireShared: boolean

Defined in: packages/agentos/src/safety/runtime/SqlSpendMeter.ts:228

Refuse a store that several processes cannot share (no transactions, no persistence or no concurrent access): a SQLite file per process would give every instance an allowance of its own. Default true; tests pass false.


retry?​

optional retry: SpendRetryPolicy

Defined in: packages/agentos/src/safety/runtime/SqlSpendMeter.ts:205


tablePrefix?​

optional tablePrefix: string

Defined in: packages/agentos/src/safety/runtime/SqlSpendMeter.ts:247

The start of the two tables' names: <prefix>_meter and <prefix>_reservations, their indexes named after them (idx_<prefix>_reservations_*). Default agentos_spend, the names SPEND_METER_DDL makes, whose indexes are idx_spend_reservations_*. Meters with different rules share one database each under a prefix of its own, so one's count and one's purge never reach another's rows; meters under one prefix share its tables.

A lower-case letter, then at most 37 lower-case letters, digits or underscores, and not spend, whose index names are the default prefix's. At 38 characters the longest names the meter gives, idx_<prefix>_reservations_account and idx_<prefix>_reservations_settled, take the 63 bytes Postgres keeps of an identifier. The constructor checks the prefix before any statement is built and throws on any other value, so nothing unchecked reaches the SQL text. spendMeterDdl makes the tables for a prefix.


unknownAfterLease?​

optional unknownAfterLease: "release" | "consume"

Defined in: packages/agentos/src/safety/runtime/SqlSpendMeter.ts:223

How an expired reservation settles when the product cannot tell. Default release: the person is not charged for a turn nobody saw finish.


windowMs?​

optional windowMs: number

Defined in: packages/agentos/src/safety/runtime/SqlSpendMeter.ts:200

A rolling window in milliseconds. The allowance then holds the units consumed in the windowMs before each reservation and every unit still reserved, counted from the reservations themselves under the account's row lock, and every row of the account carries the period window. A consumed unit has left the window once more than windowMs have passed since its reservation; one still reserved counts whatever its age, until it settles; a released one never counts.

Methods​

allowanceFor()​

allowanceFor(accountId, period): number | Promise<number>

Defined in: packages/agentos/src/safety/runtime/SqlSpendMeter.ts:187

The account's allowance for a period, in units. Read at every reservation, so a plan change applies at the next turn.

Parameters​

accountId​

string

period​

string

Returns​

number | Promise<number>


onWarning()?​

optional onWarning(warning): void

Defined in: packages/agentos/src/safety/runtime/SqlSpendMeter.ts:256

Told of each statement that failed while SqlSpendMeter.ensureSchema brought tables that exist up to the meter's indexes, with the statement and the error the store threw: the CREATE INDEX of an index the tables lack (refused, for example, to a role that does not own them, or stopped by a lock or statement timeout), or the read of the catalogue before them. Such a failure is not fatal: the indexes speed the meter's reads and change none of its answers, so the meter uses the tables as they are. An error the callback throws is dropped. Without a callback, nothing is reported.

Parameters​

warning​
error​

unknown

statement​

string

Returns​

void


periodOf()?​

optional periodOf(now, accountId): string | Promise<string>

Defined in: packages/agentos/src/safety/runtime/SqlSpendMeter.ts:192

The period a moment falls in for an account, e.g. its calendar month in its own time zone ("2026-10"). Required unless windowMs is set; with a window it is not read.

Parameters​

now​

number

accountId​

string

Returns​

string | Promise<string>


resolveExpired()?​

optional resolveExpired(reservation): SpendExpiryDecision | Promise<SpendExpiryDecision>

Defined in: packages/agentos/src/safety/runtime/SqlSpendMeter.ts:221

Asked by SqlSpendMeter.reconcile for each expired reservation, in place of resolveUnknown and unknownAfterLease: consumed, released, or deferred until retryAt with its evidence, which stays reserved and counted. A resolver that throws defers the reservation for one lease; it never falls through to a default outcome. An answer is written only to the attempt it was asked about and only while that attempt's lease is still out at the pass's now, so an operation released and retried while it is asked keeps the retry reserved under its own lease, and a lease a heartbeat renewed, or a deferral another pass made to a next check after now, stands meanwhile.

Parameters​

reservation​

SpendExpiredReservation

Returns​

SpendExpiryDecision | Promise<SpendExpiryDecision>


resolveUnknown()?​

optional resolveUnknown(reservation): SpendUnknownResolution | Promise<SpendUnknownResolution>

Defined in: packages/agentos/src/safety/runtime/SqlSpendMeter.ts:212

Asked by SqlSpendMeter.reconcile for each expired reservation on a meter without resolveExpired, except one made with requireFence or deferred before, which such a meter leaves reserved. Its answer settles the reservation only if, when the pass writes it, the reservation is still the attempt asked about, still past its lease and still unfenced: one an opted-in pass defers, or a heartbeat renews, while it is asked stays reserved.

Parameters​

reservation​
accountId​

string

operationId​

string

period​

string

units​

number

Returns​

SpendUnknownResolution | Promise<SpendUnknownResolution>