import type { SkillLike, SkillMeta, SkillStoreLike } from '../types/skills.js'; import { type SkillCatalogEntry } from './skillCatalog.js'; /** * Persisted shape of a live catalog, stored on `runState.state.__kuralle.skillCatalog` so a resumed * or replayed run restores the exact roster it had — added skills, withdrawals, and the * last-announced snapshot — and neither re-resolves a withdrawn skill nor re-narrates a * change it already narrated. */ export interface PersistedLiveSkillCatalog { added: SkillLike[]; removed: string[]; announced: SkillCatalogEntry[]; } /** * The mutable set of skills `load_skill` resolves against for the current run — distinct * from the frozen `skillPrompt` baseline, which lists only what was wired at startup and * must stay byte-identical (see `skillCatalog.ts` for why). * * Resolution order on a name: an added (live) skill wins; otherwise the baseline store * serves a baseline skill that has not been withdrawn; anything else is not available. So * a baseline skill's body still loads lazily through the store (progressive disclosure * preserved), and only added skills carry their body inline. * * The catalog is per-run instance state threaded through the run context (matching how * `skillActivations` is threaded), never module state. */ export declare class LiveSkillCatalog { private readonly store; private readonly baseline; private readonly added; private readonly removed; private announced; constructor(store: SkillStoreLike, baseline: readonly SkillMeta[]); /** The frozen baseline the prompt was built from. Rendered once into `skillPrompt`. */ frozenBaseline(): readonly SkillMeta[]; /** * The current live roster (baseline ∪ added − removed), sorted by name. This is what * `load_skill`'s availability list and the announcement roster are derived from. */ entries(): SkillCatalogEntry[]; /** Is `name` resolvable right now (added, or an un-withdrawn baseline skill)? */ has(name: string): boolean; /** * Metadata for `name`, for activation recording (`recordSkillActivation`). Added skills * surface their `allowedTools` so the a3 tool boundary composes with skills activated * mid-run; a withdrawn skill resolves to `undefined`. */ meta(name: string): SkillMeta | undefined; loadBody(name: string): Promise; listResources(name: string): Promise; loadResource(name: string, path: string): Promise; /** Add (or replace) a skill in the live roster. Re-adding a withdrawn baseline skill * un-withdraws it. */ add(skill: SkillLike): void; /** Withdraw `name` from the live roster. Returns false if it was never available. */ remove(name: string): boolean; /** The roster as it stood after the last announcement. Diff against `entries()` to decide * whether a change needs narrating. */ announcedSnapshot(): SkillCatalogEntry[]; /** Record that the current `entries()` has been announced. */ setAnnouncedSnapshot(entries: readonly SkillCatalogEntry[]): void; /** * Fold the current live roster into the announced baseline. Called at compaction — the * one place the cached prompt is already being rewritten — so the prompt can be rebased * to the live roster and the announcement note dropped, keeping announcement history * bounded instead of growing each turn. */ rebaseline(): void; serialize(): PersistedLiveSkillCatalog; /** Restore a previously serialized catalog. Used on run resume/replay so the live roster, * withdrawals, and last-announced snapshot survive across the run boundary. */ restore(state: PersistedLiveSkillCatalog): void; } /** Restore a catalog from persisted run state (`runState.state.__kuralle.skillCatalog`). No-op when the * agent has no skills or nothing was persisted, so a fresh run starts from the baseline. */ export declare function restoreLiveSkillCatalog(catalog: LiveSkillCatalog | undefined, state: Record | undefined): void;