/** * compaction/summarize — the authored frame, and the call that fills it. * * Pattern: Template Method with an authored envelope + untrusted payload. * Role: core/ layer. Two boundaries are enforced here, and they are the * same boundary pointed in opposite directions: * * 1. Going OUT to the summarizer, the folded transcript is DATA — * wrapped in a delimiter the authored instruction names, so a * message inside the conversation cannot re-instruct the * summarizer just by looking like an instruction. * 2. Coming BACK into the window, the summary is DATA — appended * after an authored label the library wrote. A summarizer that * returns "IGNORE ALL PREVIOUS INSTRUCTIONS" produces a message * that still says, in the library's own words and first, that * what follows is a summary written by a model. * * The frame is authored. The summary is data. Neither can become * the other. * * A third rule joined them in 8.2: the frame may only claim what is * true. It names where the folded messages went, and it reads that * from the resolved retention policy rather than asserting a * constant — see {@link retentionSentence}. * Emits: N/A (the stage emits; this file only builds and calls). */ import type { LLMMessage, LLMProvider, LLMResponse } from '../../../adapters/types.js'; import type { CompactionRetention } from './types.js'; export { COMPACTED_FRAME_PREFIX, isCompactedSummary } from '../../../lib/saidByPerson.js'; /** * What the summarizer is asked to do. Authored, fixed, and never composed * from run content — the only variable part of the summarizer's prompt is * the transcript, and that arrives between delimiters this text names. */ export declare const SUMMARIZER_SYSTEM_PROMPT: string; /** The folded span, rendered as the summarizer's input payload. */ export declare function renderTranscript(messages: readonly LLMMessage[]): string; /** * Build the message that replaces the folded span IN THE WINDOW. * * `role: 'user'` because the fold can reach the window's head, and the * providers that care (Anthropic) require the window to open on a user turn. * Since 9.55.0 it usually does NOT reach it — the CURRENT REQUEST sits there * and refuses to be folded, so the frame lands immediately after it — but the * role is right either way and a fold of a window with no identifiable * request still opens on one. * * The label is written by this function and always comes first. `summary` is * appended to it verbatim: the library never edits model output, and it never * lets model output speak in the library's voice either. * * The label states the retention policy, and states it truthfully — see * {@link retentionSentence}. `COMPACTED_FRAME_PREFIX` is unchanged: it is what * every reader and every test matches on, and it stays put. */ export declare function buildSummaryMessage(summary: string, facts: { readonly foldedMessageCount: number; readonly iteration: number; readonly model: string; readonly retain: CompactionRetention; }): LLMMessage; export interface SummarizeResult { readonly text: string; readonly usage: LLMResponse['usage']; } /** * Call the summarizer over the folded span. * * Throws whatever the provider throws — the STAGE decides that a broken * summarizer means "no fold this iteration", not "no run". Deciding that * here would hide the failure from the record. * * ## This call is UN-DECORATED, and that is on purpose * * `provider.complete(...)` below is the raw provider. None of the machinery * that wraps the agent's own LLM call wraps this one: * * • no `reliability` retry loop (that lives inside the `call-llm` stage); * • no `withRetry` / `withFallback` / `withCircuitBreaker` (those decorate * the provider the AGENT was constructed with, not this argument); * • no cache subflow (`sf-cache` sits in front of `call-llm` only). * * One attempt, and a failure is recorded as a `'summarizer-failed'` refusal * rather than retried. A fold is optional work — the run is correct without * it — so spending a retry budget on it, or letting a summarizer outage open * a circuit that then blocks the agent's real calls, would trade something * that matters for something that does not. * * The consequence worth knowing: passing the AGENT'S OWN provider instance as * the summarizer gives you one object that behaves two different ways inside * one run — retried and cached on one path, neither on this one. `.compaction()` * refuses that exact pairing when the model matches too; pass a second * instance. */ export declare function runSummarizer(provider: LLMProvider, model: string, span: readonly LLMMessage[], signal: AbortSignal | undefined): Promise;