/** * Per-user memory: the adapter, the store-backed default, and the one tool that * writes it. * * READS ARE AUTOMATIC, WRITES ARE DELIBERATE — the whole shape of the feature. * `recall` rides the per-turn prompt as a capped `[Memory]` block, so the model * never asks for what it was already told; nothing is ever inferred from a * transcript, because the only way a memory comes into being is the `remember` * tool below, which is listed, described, audited and guard-checked like every * other call. * * EVERY verb takes the principal it acts for and scopes on `principal.subject`. * The generic records door keys rows on (collection, id) alone * (`packages/vendo/src/store/records.ts:90-101`), so per-user isolation is this * module's to enforce: `refs.subject` is written on every row and filtered on * every read, the delete reads through that same filter before it removes * anything, and no verb — the tool least of all — takes a subject from its * caller's input. */ import { type Principal } from "../core/index.js"; import type { VendoStore } from "../store/index.js"; import { type HostTool } from "./tools.js"; /** One remembered fact. `at` is when it was first written — a listing shows it, * the prompt does not. */ export interface Memory { id: string; text: string; at: string; } /** * The BYO seam: five verbs, one subject axis. An adapter passed to * `agent({ memory })` is used verbatim, so a host that already knows its users' * preferences can answer `recall` from its own tables — the standard ladder, * where `memory: true` is only the rung this package ships. */ export interface MemoryAdapter { /** The `limit` most recent, OLDEST FIRST: the order they read in, and the * order that makes a cap drop the stalest fact rather than the newest one. */ recall(principal: Principal, limit: number): Promise; remember(principal: Principal, text: string): Promise; /** Everything this subject remembers, newest first — a settings list, not a * prompt, so it is complete and uncapped. */ list(principal: Principal): Promise; delete(principal: Principal, id: string): Promise; clear(principal: Principal): Promise; } /** * How many memories a TURN READS. A prompt budget, not a storage limit: the * store keeps every memory a person ever made and `list` still returns them * all — this is only how many of the most recent ride in `[Memory]`, so someone * who has remembered a hundred things does not spend a hundred facts of every * later turn on them. Twenty is the point past which the oldest fact has * stopped describing the person and become history — app memory's own number, * for its own reason (`APP_MEMORY_MAX_ASKS`). */ export declare const MEMORY_RECALL_LIMIT = 20; /** * How much of ONE memory is kept. A fact about a person is a sentence; the cap * exists because a model that ignores "keep it short" would otherwise put a * transcript into every future prompt (`APP_MEMORY_DECISIONS_MAX_BYTES`'s * reason). Counted in CODE POINTS, so a cut never splits a surrogate pair into * a lone half no jsonb column will accept. */ export declare const MEMORY_TEXT_MAX_CHARS = 500; /** * The default: this composition's own store, in the generic `vendo_records` * table — no collection of its own, so no schema change and no migration. * * `refs: { subject }` is doing two jobs. It is the scope every verb here * filters on, and it is what `erase.bySubject` sweeps generic rows by * (`packages/vendo/src/store/erase.ts:242`), so a forgotten person's memories go with * the rest of their data without this module being named anywhere in the * cascade. */ export declare function storeMemory(store: VendoStore): MemoryAdapter; /** * The write door, and the only one. * * `risk: "write"` is the honest grade: it creates durable per-user state that * every later turn reads, which is more than a `read` — and it is not * `destructive`, because a call APPENDS one row of the caller's own and * overwrites nothing. Forgetting belongs to the person, not the model, so there * is no tool for it. * * THE SUBJECT IS THE CTX'S, NEVER THE INPUT'S. A model that decides to remember * something "for user_b" writes to its own caller's memory, because the schema * gives it nothing to say so with. */ export declare const rememberTool: (memory: MemoryAdapter) => HostTool;