@sema-agent/core
Version:
Stateless, task-oriented AI agent core
103 lines (102 loc) • 6.82 kB
TypeScript
/** What ONE landed compaction did to the transcript, recorded at its commit point. */
export interface CompactionEffect {
/** The entry ids that went into the summarized prefix (everything before `firstKeptEntryId`), or
* `"unknown"` when the kept-tail anchor could not be located in the branch — the conservative
* reading is that the whole branch was summarized, so a reader treats `"unknown"` as "every
* receipt this run holds is invalidated" (the same direction
* {@link import("./auto-compaction.js").countSummarizedCrossSessionMessages} already takes). */
readonly summarizedEntryIds: ReadonlySet<string> | "unknown";
}
/**
* One receipt ASK: the carrier a frame rides, and — for a frame that rides a TOOL RESULT — the
* text {@link frameSurvivesInToolResult} must find in that result as committed. An injected frame is its
* own carrier (the committed message IS the frame), so it carries no text to check.
*/
export interface FrameReceiptAsk {
/** The injection queue's dedup key of the frame itself, or {@link toolResultReceiptKey} of the call whose result carries it. */
readonly carrier: string;
readonly frameText?: string;
}
/**
* The leg's settlement seam, one cell per run.
*
* `awaiting` is an ASK, not a log: only keys a consumer registered are ever given a receipt, an ask
* leaves when its carrier commits, so a run that delivers thousands of ordinary notification frames
* does not accumulate one map entry per frame. The key is the consumer's per-frame key.
*/
export interface FrameSettlement {
/** Receipt asks a consumer is waiting on (key → ask). The receipt sink records nothing for any other key. */
readonly awaiting: Map<string, FrameReceiptAsk>;
/** Receipts collected for awaited keys: key → the transcript entry id the frame landed in. */
readonly receipts: Map<string, string>;
/** Awaited keys whose carrier COMMITTED WITHOUT the frame and nothing the HOST did explains it (an engine-side
* crop): shown nothing, so owed again — never a receipt. */
readonly withheld: Set<string>;
/** Carriers whose result a HOST hook rewrote (`postToolUse.updatedOutput`) before the commit — recorded only
* for a carrier some ask rides ({@link noteHostRewrite}), consumed by the receipt at its commit: a frame the
* rewrite kept gets an ordinary receipt, a frame it removed is host-withheld. */
readonly hostRewritten: Set<string>;
/** Awaited keys whose frame is not in the host's rewrite (removed, truncated, or reshaped beyond whitespace): the
* host decided what the model reads, so the consumer settles the record as the host's decision (terminal),
* discloses it loudly, and never hands it over again. */
readonly hostWithheld: Set<string>;
/** Compactions that LANDED this run and have not been consumed by a settlement pass yet, in landing
* order. Recorded only while {@link FrameSettlement.wantsEffects} says a record could still be
* broken by one, and cleared by the consumer's LOCAL settlement half — which needs no lease, so an
* unclaimable or empty box cannot leave them piling up for the whole leg. */
readonly compactions: CompactionEffect[];
/**
* #1036 — "is this engine frame's record still parked in a DURABLE box?" Set by the
* session-box drain when it binds. The terminal sweep hands back engine-note payloads that never
* drained and the runner pends them PER SESSION (an in-process copy); for a frame whose record the
* drain no longer acks on delivery, that copy would be a second source of truth — the box already
* re-serves it to the session's next run. Absent (no drain bound) ⇒ the pre-1036 behavior, which is
* correct there: nothing else holds those frames.
*/
boxBacked?: (payload: unknown) => boolean;
/**
* #1036 — "is there a record a landed compaction could still break?" Asked at the compaction
* COMMIT beat, before an effect is recorded at all. Absent (no drain bound) or `false` ⇒ the effect
* is not recorded: nothing would ever read it, and a leg that compacts many times would otherwise
* hold every landing's entry-id set until it ended.
*/
wantsEffects?: () => boolean;
}
export declare function createFrameSettlement(): FrameSettlement;
/** The carrier key of a TOOL RESULT (the `ReadInbox` pull face): its own domain, so it can never
* collide with an injection queue dedup key. One tool result can carry SEVERAL frames, each asked for
* under its own key with this carrier. */
export declare function toolResultReceiptKey(toolCallId: string): string;
/**
* THE rule for a frame that rides a TOOL RESULT: the result can be replaced (`postToolUse.updatedOutput`)
* or cropped (the aggregate result budget) after the frame was handed to it, so handing it over proves
* nothing — the frame counts as delivered only when its text is present in the result AS COMMITTED
* (a string, or the text blocks, each read whole), compared with every whitespace run on both sides folded
* to one space: a rewrite that only re-spaces, re-indents or re-wraps the frame kept it. Any other change
* (a word, an escape, the case) did not. Before the commit, nothing is proven. The inbox receipt
* below reads it; the listing ride (`prepare-listings.ts`) does not call it — it never commits announced
* state at ride time, the conservative answer for a frame whose commit has not happened yet.
*/
export declare function frameSurvivesInToolResult(committedContent: unknown, frameText: string): boolean;
/** The station that applies a HOST hook's `updatedOutput` marks the carrier — only when an ask rides it, so an
* ordinary rewritten result leaves nothing behind. */
export declare function noteHostRewrite(seam: FrameSettlement, toolCallId: string): void;
/** The receipt sink's ONE writer: every ask riding `carrier` is answered — a receipt when its frame is in
* the committed content (or it is its own carrier); when it is not, host-withheld if a host hook rewrote the
* carrier (the host's decision), withheld otherwise (owed again). */
export declare function recordFrameReceipt(seam: FrameSettlement, carrier: string, committedContent: unknown, entryId: string): void;
/** The carrier a committed frame was riding, as the harness reports it at the transcript append — a tool
* result with the content it was committed with (after every result transformation); a user-attachment frame by
* its delivery record's key (`inputId`, `ordinal`). */
export type CommittedFrameCarrier = {
kind: "engine_note";
payload: unknown;
} | {
kind: "tool_result";
toolCallId: string;
content: unknown;
} | {
kind: "attachment";
inputId: string;
ordinal: number;
};