export type ToolDef = import("../types").ToolDef; /** * Build the stash reference skill + the trim function that executes its folds. * * @param {Object} [options] * @param {'summarize'|'stash'} [options.defaultStrategy='summarize'] - Strategy when the model omits one. * 'summarize' (OQ5 lean / §2.11) is lossy; 'stash' is lossless. 'summarize' degrades to a lossless park * when no `ctx.summarize` is wired (loud, never a silent detail-loss). * @param {string} [options.keyPrefix='stash:'] - Namespace for stash/episode ids. * @param {number} [options.maxLabels=128] - LRU backstop on DISTINCT live labels (§2.13) — visible, not silent. * @param {Object} [options.compaction] - AUTOMATIC token-pressure trigger (§2.11/D12, all bareagent — a * housekeeping threshold, NEVER a bareguard halt bound). Opt-in: omit, or omit `ceilingTokens`, → OFF * (no guessed model→window table). Fires on the NEXT round's trim when the Loop's measured * `ctx.usage.inputTokens / ceilingTokens > triggerAt`. * @param {number} [options.compaction.ceilingTokens] - OPERATOR-SET context ceiling (enables auto-trigger). * @param {number} [options.compaction.triggerAt=0.7] - Fraction of the ceiling that fires a fold. * @param {'summarize'|'stash'} [options.compaction.strategy] - Strategy for auto-folds (default: defaultStrategy). * @param {number} [options.compaction.keepHeadTurns=1] - Recent turns to keep at the START (initial context). * @param {number} [options.compaction.keepRecentTurns=3] - Recent turns to keep at the END (live working set). * @param {(msg: string) => void} [options.onNote=console.warn] - Sink for the loud one-time/backstop notes. * @returns {{ skill: { name: string, description: string, instructions: string, tools: ToolDef[] }, trim: (msgs: any[], ctx: any) => Promise, restoreHandles: () => string[] }} * @when you need compaction-first context hygiene — a registrable skill whose checkpoint/compact/restore tools fold the live transcript at round boundaries * @fails never throws for a fold; degrades LOUDLY to a lossless park when summarize is unwired. Preserves tool-pairing and role alternation by construction. * @example * const { skill, trim } = createStashSkill({ compaction: { ceilingTokens: 100000 } }); * const loop = new Loop({ provider, trim }); */ export function createStashSkill(options?: { defaultStrategy?: "summarize" | "stash" | undefined; keyPrefix?: string | undefined; maxLabels?: number | undefined; compaction?: { ceilingTokens?: number | undefined; triggerAt?: number | undefined; strategy?: "summarize" | "stash" | undefined; keepHeadTurns?: number | undefined; keepRecentTurns?: number | undefined; } | undefined; onNote?: ((msg: string) => void) | undefined; }): { skill: { name: string; description: string; instructions: string; tools: ToolDef[]; }; trim: (msgs: any[], ctx: any) => Promise; restoreHandles: () => string[]; };