/**
 * Crewly Agent Model Manager
 *
 * Multi-provider model factory that creates AI SDK model instances
 * from configuration. Supports Anthropic, OpenAI, Google, DeepSeek, and
 * Ollama providers.
 *
 * API keys for cloud providers are resolved through the settings service
 * (skill → runtime → global → env var) and injected into process.env so the
 * provider SDKs can pick them up:
 * - ANTHROPIC_API_KEY
 * - OPENAI_API_KEY
 * - GOOGLE_GENERATIVE_AI_API_KEY
 * - DEEPSEEK_API_KEY (DeepSeek; served via OpenAI-compatible API)
 *
 * Ollama runs locally and does not require an API key.
 * Configure the Ollama base URL via OLLAMA_BASE_URL (default: http://localhost:11434).
 *
 * @module services/agent/crewly-agent/model-manager
 */
import type { LanguageModel } from 'ai';
import { type ModelConfig, type ModelProvider } from './types.js';
/**
 * Factory for creating AI SDK language model instances from configuration.
 *
 * Uses dynamic imports to avoid loading provider SDKs that aren't needed,
 * keeping the startup cost minimal when only one provider is used.
 *
 * @example
 * ```typescript
 * const manager = new ModelManager();
 * const model = await manager.getModel({ provider: 'anthropic', modelId: 'claude-sonnet-4-20250514' });
 * ```
 */
export declare class ModelManager {
    /** Cached provider module references to avoid re-importing */
    private providerCache;
    /**
     * Per-instance buffer of parsed DeepSeek-R1 reasoning_content from in-flight
     * and recently-completed HTTP calls. Each `streamText` call to a DeepSeek
     * model triggers one or more fetch calls (one per agentic step); each fetch
     * appends its parsed reasoning to this buffer. Consumer (agent-runner) reads
     * via `consumeDeepseekReasoning()` after `await streamResult` and the buffer
     * resets to `''` on read.
     *
     * **Concurrency:** AgentRunner uses one ModelManager per session and calls
     * streamText serially per session (the rate limiter enforces this).
     * Cross-session concurrency is not a concern because each AgentRunner gets
     * its own ModelManager via `new ModelManager()` in the constructor.
     */
    private deepseekReasoningBuffer;
    /** Tracks in-flight parsed-SSE handles so we can wait for drain on consume. */
    private deepseekParsedHandles;
    /**
     * Get an AI SDK language model instance for the given configuration.
     *
     * Resolves API keys from settings (with override chain) and injects them
     * into the environment before creating the model, so provider SDKs can find them.
     *
     * @param config - Model configuration specifying provider and model ID
     * @returns AI SDK LanguageModel instance ready for use with generateText
     * @throws Error if the provider is unknown or the SDK is not installed
     */
    getModel(config?: ModelConfig): Promise<LanguageModel>;
    /**
     * Get provider function, using cache for repeated calls.
     *
     * @param provider - Provider name
     * @returns Function that creates a model from a model ID string
     */
    private getProviderFunction;
    /**
     * Check which providers have API keys configured (settings + env vars).
     *
     * @returns Object indicating which providers are available
     */
    getAvailableProviders(): Promise<Record<ModelProvider, boolean>>;
    /**
     * Map model provider name to API key provider name.
     * Only applicable for cloud providers wired through the settings service
     * (anthropic, openai, google, deepseek). Ollama runs locally and is
     * excluded.
     *
     * @param provider - Cloud model provider
     * @returns Corresponding ApiKeyProvider name
     */
    private static providerToApiKeyProvider;
    /**
     * Ensure the API key for a provider is available in process.env
     * by resolving it from settings if not already present.
     *
     * No-op for 'ollama' (runs locally, no key required). All other providers —
     * including 'deepseek' — flow through the settings service so users can
     * configure them from the UI without touching env vars.
     *
     * @param provider - The model provider
     */
    private ensureApiKeyInEnv;
    /**
     * Clear the provider cache (useful for testing or reconfiguration).
     * Also clears any buffered DeepSeek reasoning so a fresh test/run starts clean.
     */
    clearCache(): void;
    /**
     * Build the custom fetch wrapper for the DeepSeek provider.
     *
     * Returns a function with the same signature as `globalThis.fetch` that:
     * 1. Calls native fetch with the supplied input/init.
     * 2. If the response is a streaming SSE body, tees it and parses one branch
     *    for `delta.reasoning_content`, accumulating into `this.deepseekReasoningBuffer`.
     * 3. Returns a new Response wrapping the un-tampered passthrough branch as
     *    its body, so AI SDK consumes exactly the bytes DeepSeek sent.
     *
     * If the response is not an SSE stream (e.g. error JSON, no body), it is
     * returned unchanged.
     *
     * **Why a method, not a free function:** the wrapper closes over `this` to
     * append to the per-instance reasoning buffer. Each ModelManager instance
     * has its own buffer (one per AgentRunner per session).
     */
    private makeDeepseekFetch;
    /**
     * Drain any in-flight DeepSeek SSE parser branches and return the accumulated
     * `reasoning_content` string. Resets the buffer to `''` on each call (consume
     * semantics).
     *
     * **Caller contract:** call AFTER `await streamResult` resolves in agent-runner.
     * The AI SDK consumer branch must have been fully drained for the parser branch
     * (which lags slightly due to tee buffering) to have caught up.
     *
     * **Multi-step accumulation:** if a single `streamText` call made multiple HTTP
     * calls (one per agentic step), reasoning from all steps is concatenated in
     * call order — not separated by step boundary. This matches the user-facing
     * mental model of "what was the model's full chain of thought for this turn."
     *
     * **Returns `null` if no reasoning was captured.** Empty string means a fetch
     * happened but produced no reasoning content (e.g. non-R1 DeepSeek model).
     */
    consumeDeepseekReasoning(): Promise<string | null>;
}
//# sourceMappingURL=model-manager.d.ts.map