/**
 * BuddyController — Frontend-agnostic controller for the buddy companion.
 *
 * Owns: context buffer, idle timer, reaction throttle, name-call detection.
 * Extracted from InteractiveMode so both TUI and Telegram can compose it
 * without duplicating ~150 lines of buddy wiring logic.
 *
 * The host (TUI or Telegram) provides callbacks for frontend-specific rendering:
 * - onSpeech(text) — display a speech bubble / message
 * - onThinkingStart() / onThinkingEnd() — show/hide thinking indicator
 *
 * Policies are configurable via BuddyControllerConfig so the TUI (no limits)
 * and Telegram (activity gating + reaction budget) can use different strategies.
 */
import { type BuddyManager } from "./buddy-manager.js";
import type { BuddyState } from "./buddy-types.js";
/** Frontend-provided callbacks for buddy rendering */
export interface BuddyCallbacks {
    /** Display a speech/reaction message from the buddy */
    onSpeech: (text: string) => void;
    /** Show a thinking/loading indicator */
    onThinkingStart: () => void;
    /** Hide the thinking/loading indicator */
    onThinkingEnd: () => void;
    /** Hatch a new buddy — frontend resolves API key and calls manager.hatch() */
    onHatch: (manager: BuddyManager) => Promise<BuddyState>;
    /** Reroll the buddy — frontend resolves API key and calls manager.reroll() */
    onReroll: (manager: BuddyManager) => Promise<BuddyState>;
}
/** Configuration for buddy behavior — differs between TUI and Telegram */
export interface BuddyControllerConfig {
    /** Max entries in the context buffer (default: 20) */
    contextMaxEntries?: number;
    /** Idle timeout in ms before buddy reacts to silence (default: 30000) */
    idleTimeoutMs?: number;
    /** Minimum ms between reactions (default: 60000) */
    reactionCooldownMs?: number;
    /** If set, pause idle timer when user has been inactive this many ms */
    activityGateMs?: number;
    /** If set, cap reactions to this many per hour */
    reactionsPerHour?: number;
}
/** Subcommand result for frontend to render */
export type BuddyCommandResult = {
    type: "hatch";
    state: BuddyState;
} | {
    type: "show";
    state: BuddyState;
} | {
    type: "reroll";
    state: BuddyState;
} | {
    type: "pet";
} | {
    type: "stats";
    state: BuddyState;
} | {
    type: "off";
} | {
    type: "model";
    message: string;
} | {
    type: "warning";
    message: string;
} | {
    type: "error";
    message: string;
};
export declare class BuddyController {
    private contextBuffer;
    private lastReactionTime;
    private idleTimer;
    private lastActivityTime;
    private reactionTimestamps;
    private pendingUtteranceId;
    /** When false, all active functionality is disabled: no reactions, name-calls,
     *  idle timer, or Ollama calls. Context capture (passive) still happens. */
    enabled: boolean;
    readonly manager: BuddyManager;
    private readonly callbacks;
    private readonly config;
    constructor(manager: BuddyManager, callbacks: BuddyCallbacks, config?: BuddyControllerConfig);
    private removeContextEntry;
    private replaceContextEntry;
    /** Append an entry to the buddy context buffer (evicts oldest if at capacity) */
    appendContext(entry: string): void;
    /** Build the context buffer into a string for LLM prompts */
    buildContext(): string;
    /** Mark that user activity occurred (for activity gating) */
    markActivity(): void;
    /** Reset the idle timer — called on every user message */
    resetIdleTimer(): void;
    /** Check if a reaction is allowed under current throttle and budget */
    private canReact;
    /**
     * Trigger a buddy reaction. Throttled by cooldown and budget.
     * Calls onThinkingStart/End and onSpeech callbacks.
     * No-op if disabled.
     */
    triggerReaction(event: string): Promise<void>;
    /**
     * Handle a name-call from the user.
     * No-op if disabled — returns immediately without calling Ollama.
     */
    handleNameCall(userMessage: string): Promise<void>;
    /** Check if a message contains the buddy's name (word-boundary matching).
     *  Returns false if disabled. */
    detectNameCall(text: string): boolean;
    /**
     * Process an agent event for buddy context capture and reaction triggers.
     * The host calls this from its event handler.
     *
     * Context capture always happens. Reactions are gated by `enabled`.
     */
    handleEvent(event: {
        type: string;
        [key: string]: any;
    }): void;
    /**
     * Process a user message — captures context, resets idle, checks name-call.
     * Context capture always happens. Active features gated by `enabled`.
     * Returns true if a name-call was detected and is being handled.
     */
    processUserMessage(text: string): boolean;
    /**
     * Handle a /buddy command. Returns a result object for the frontend to render.
     * Hatch/reroll are delegated to the frontend via onHatch/onReroll callbacks.
     */
    handleCommand(subcommand: string): Promise<BuddyCommandResult>;
    private handleModelCommand;
    /** Check if an Ollama model is configured, return a nudge message if not */
    getModelNudge(): string | null;
    /** Start the controller — auto-load buddy if one exists */
    start(): BuddyState | null;
    /** Stop the controller — clear timers */
    stop(): void;
    /** Full reset — clear context buffer, idle timer, reaction budget.
     *  Respects persisted hidden state so bridge reconnects don't undo /buddy off. */
    reset(): void;
}
//# sourceMappingURL=buddy-controller.d.ts.map