/** * 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; }