/**
 * Smart model routing — heuristic message classifier.
 *
 * Classifies inbound messages into three tiers (simple / moderate / complex)
 * using zero-LLM-cost regex/keyword heuristics. When enabled, simple messages
 * are routed to a fast local model (e.g. 3B), moderate to a larger local model,
 * and complex to the configured API model (e.g. Claude).
 *
 * Inspired by LocalClaw's 3-tier routing system.
 *
 * @module
 */
export type MessageComplexity = "simple" | "moderate" | "complex";
/**
 * Routing profile — predefined bias presets that shift tier thresholds.
 *
 * - "balanced" (default): standard heuristic thresholds.
 * - "cost-optimized": aggressively routes to cheaper local models.
 * - "quality-first": biases toward the API/orchestrator model.
 * - "local-only": never routes to cloud — all messages stay on local models.
 */
export type RoutingProfile = "balanced" | "cost-optimized" | "quality-first" | "local-only";
export type AgentRoutingConfig = {
    /** Enable smart routing (default: false — zero behavior change without opt-in). */
    enabled?: boolean;
    /** Routing profile preset (default: "balanced"). */
    profile?: RoutingProfile;
    /** Fast-tier model for simple messages (e.g. "ollama/qwen3:1.7b"). */
    fastModel?: string;
    /** Local-tier model for moderate messages (e.g. "ollama/gemma3:12b"). */
    localModel?: string;
    /** Max message length (chars) for simple classification (default: 150). */
    maxSimpleLength?: number;
    /** Context token cap for fast model (default: 4096). */
    fastModelContextTokens?: number;
    /** ECO-tier model for ultra-short messages under 20 words (e.g. "gemini-2.5-flash-lite"). */
    ecoModel?: string;
    /**
     * Per-persona model overrides — maps persona name to a model string.
     * When the current agent persona matches a key, that model is used instead of tier routing.
     * @example { "Researcher": "anthropic/claude-opus-4-6", "Quick": "openai/gpt-4o-mini" }
     */
    personaModels?: Record<string, string>;
};
export type AgentOrchestratorConfig = {
    /** Enable orchestrator escalation for complex messages (default: false). */
    enabled?: boolean;
    /** Orchestrator model (e.g. "anthropic/claude-sonnet-4"). */
    model?: string;
    /** Routing strategy (default: "auto"). */
    strategy?: "auto" | "always" | "fallback-only";
};
export type SmartRoutingResult = {
    complexity: MessageComplexity;
    /** Provider override (undefined = use default). */
    provider?: string;
    /** Model override (undefined = use default). */
    model?: string;
    /** Whether tool calling should be disabled. */
    disableTools: boolean;
    /** Context token cap override (undefined = use default). */
    contextTokensCap?: number;
    /** Timeout in ms for the LLM call. When exceeded, caller should escalate to fallback. */
    timeoutMs?: number;
    /**
     * When true, the caller should reset the model back to the local/fast
     * tier after this turn completes. Prevents a single complex message from
     * locking all subsequent messages to the expensive orchestrator model.
     *
     * Inspired by LocalClaw's per-message model reset pattern.
     */
    resetModelAfterTurn?: boolean;
    /** Whether orchestrator was used for this routing decision. */
    orchestrated?: boolean;
    /** Estimated cost in cents for this routing decision (from pricing table). */
    estimatedCostCents?: number;
    /** Percentage savings vs routing to the default API model. */
    savingsPercent?: number;
};
/**
 * Classify a message's complexity using heuristic rules.
 * First match wins.
 */
export declare function classifyMessage(message: string, options?: {
    maxSimpleLength?: number;
}): MessageComplexity;
/**
 * Route a message to the appropriate model tier.
 *
 * Returns a routing result indicating model overrides, tool disabling,
 * and context token capping. Returns `undefined` when routing is disabled
 * or doesn't apply (caller should use default behavior).
 */
/**
 * Apply profile bias to shift the classified complexity tier.
 *
 * - "balanced": no change.
 * - "cost-optimized": downgrade moderate → simple, complex → moderate.
 * - "quality-first": upgrade simple → moderate, moderate → complex.
 * - "local-only": cap at moderate (never route to cloud API).
 */
export declare function applyProfileBias(complexity: MessageComplexity, profile: RoutingProfile | undefined): MessageComplexity;
export declare function routeMessage(params: {
    message: string;
    routing?: AgentRoutingConfig;
    orchestrator?: AgentOrchestratorConfig;
    /** Current agent persona name — used for per-persona model override lookup. */
    currentPersona?: string;
}): SmartRoutingResult | undefined;
/**
 * For the "always" strategy: route ANY message to the orchestrator, regardless
 * of classification tier. Local model is used as fallback only if orchestrator
 * is unreachable (handled by the caller).
 *
 * Returns undefined if the strategy isn't "always" or orchestrator isn't configured.
 */
export declare function routeAlwaysOrchestrator(orchestrator?: AgentOrchestratorConfig): SmartRoutingResult | undefined;
export type SessionPin = {
    provider: string;
    model: string;
    complexity: MessageComplexity;
    pinnedAt: number;
    /** Full routing result — preserved so callers can apply all routing properties (timeout, context cap, etc.). */
    routingResult: SmartRoutingResult;
};
/** Evict expired entries and enforce max-size cap. */
declare function evictStalePins(): void;
/**
 * Pin a session to a specific model routing result.
 */
export declare function pinSession(sessionKey: string, result: SmartRoutingResult): void;
/**
 * Get the current pin for a session, or undefined if not pinned / expired.
 */
export declare function getSessionPin(sessionKey: string): SessionPin | undefined;
/**
 * Remove a session's pin (e.g. on session reset or model change command).
 */
export declare function unpinSession(sessionKey: string): boolean;
/**
 * Clear all session pins (e.g. on config reload).
 */
export declare function clearAllSessionPins(): void;
/** @internal — exposed for tests only */
export declare const _sessionPinInternals: {
    readonly sessionPins: Map<string, SessionPin>;
    readonly evictStalePins: typeof evictStalePins;
    readonly SESSION_PIN_TTL_MS: number;
    readonly SESSION_PIN_MAX_ENTRIES: 10000;
};
/** System prompt suffix injected when routing to fast model (tools disabled). */
export declare const FAST_CHAT_SYSTEM_PROMPT = "IMPORTANT: You are in fast chat mode. Respond conversationally in plain text only.\nDo NOT output any JSON, tool calls, function calls, or code blocks.\nDo NOT attempt to use memory_get, read, email, or any other tool.\nJust reply naturally as a helpful assistant.";
/**
 * Read a concise memory snapshot for injection into the fast model's system prompt.
 *
 * Looks for `memory/state.md` in the workspace directory. Returns undefined if
 * the file is missing or empty. Truncates at 800 chars to stay within small
 * model context budgets.
 */
export declare function readMemorySnapshot(workspaceDir: string): Promise<string | undefined>;
export {};
