UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

28 lines (27 loc) • 1.96 kB
import { type SessionStore } from "../session.js"; import { type ContractAssertionRunner } from "./contract-harness.js"; /** * The cross-backend contract for the SESSION INCARNATION face ({@link SessionStore.incarnationOf}): * the token naming WHICH occupant holds a session id. vitest-free (see `contract-harness.ts`); mount it * on every store that implements `incarnationOf` — the face is optional on the interface, so this kit * is a separate opt-in kit rather than a skipped case inside another one (a skipped case is how an * unimplemented face reads green). A store WITHOUT the face fails every case loudly. * * The law the cases pin: the token is a cell of the session ROW, minted once when the row comes into * existence and answered unchanged by every later read of that row — a cache forgetting the session or * a second store over the same rows does not change it, deleting the row and handing the id out again * does, a fork is a new occupant. A `SessionRepo` author runs it through the bundled cache layer * (`make: () => new TtlSessionStore({ repo })`, `reopen: () => new TtlSessionStore({ repo })`). * * `make()` must return a FRESH, empty store each call; each case disposes the store it built. */ export interface SessionStoreIncarnationContractHooks { /** Delete `sessionId`'s session ROW through the backend's own deletion path (history and all), so * that a later `acquire(sessionId)` creates a new session under the same id. */ deleteSession: (store: SessionStore, sessionId: string) => Promise<void>; /** A SECOND, independent store instance over the same rows as `store` — what a restarted process or * another replica constructs. The kit disposes it. */ reopen: (store: SessionStore) => SessionStore; runAssertion?: ContractAssertionRunner; } export declare function sessionStoreIncarnationContract(make: () => SessionStore, hooks: SessionStoreIncarnationContractHooks): Promise<void>;