/**
 * Per-session skill activation state.
 *
 * A skill activated via use_skill is pinned to its session: the tracker
 * holds the pinned instruction message until the turn is persisted
 * (drainPending → StoreConversationTurnOptions.skillMessages) and answers
 * "is this skill already loaded?" so re-invocations return a cheap
 * already_loaded note instead of the full body.
 *
 * The stored session history is the source of truth — pinned messages
 * carry `metadata.isSkill`. hydrate() rebuilds a session's active set from
 * stored messages on every activation attempt (use_skill is rare, one
 * history read per attempt), so dedup stays correct across process
 * restarts, multiple instances sharing a Redis memory backend, and failed
 * persistence: a pin that never reached storage simply re-activates on
 * the next turn instead of being falsely reported as loaded.
 */
import type { ChatMessage, SkillActivationRecord, SkillDefinition } from "../types/index.js";
/** Render the pinned history message for an activated skill. */
export declare function buildSkillActivationMessage(skill: SkillDefinition): ChatMessage;
export declare class SkillSessionTracker {
    /** sessionId → skillId → activation record. */
    private active;
    /** sessionId → pinned messages awaiting persistence into the session turn. */
    private pending;
    /** Whether the skill is already active (loaded) in this session. */
    isActive(sessionId: string, skillId: string, name: string): boolean;
    /** Activation record for an active skill (by id, falling back to name). */
    getActivation(sessionId: string, skillId: string, name?: string): SkillActivationRecord | undefined;
    /**
     * Record an activation: marks the skill active and queues its pinned
     * message for persistence when the turn is stored.
     */
    recordActivation(sessionId: string, skill: SkillDefinition): ChatMessage;
    /**
     * Rebuild the active set from stored session history, then merge the
     * in-process pending activations (this turn's pins, not yet stored).
     * Called before every dedup check — the rebuild keeps state truthful
     * when other instances pinned skills or when a past pin never reached
     * storage.
     */
    hydrate(sessionId: string, storedMessages: ChatMessage[]): void;
    /**
     * Remove and return the pinned messages queued for this session. Called
     * once per turn by the memory-store path; an empty result means nothing
     * was activated this turn.
     */
    drainPending(sessionId: string): ChatMessage[];
    /** Active skill records for a session (listing/debugging). */
    listActive(sessionId: string): SkillActivationRecord[];
    private recordsFor;
}
