/**
 * Governed AI runtime — the single execution path that turns the Settings > AI
 * configuration into actual model calls.
 *
 * Everything that wants to run an LLM inside Actuate should go through here so
 * that one DB-backed config drives behavior end-to-end:
 *  - feature toggles are ENFORCED (a disabled feature can't run),
 *  - per-feature model routing is RESOLVED ({@link resolveFeatureModel}),
 *  - the API key is resolved from env or the encrypted store,
 *  - the monthly token budget is checked (when `disableWhenExceeded`),
 *  - real token usage is RECORDED so the usage meter reflects reality.
 *
 * It is intentionally provider-agnostic: the provider adapters
 * (`./providers/*`) speak HTTP, this module decides *whether* and *with what*
 * to call them.
 */
import type { AIProviderKey } from './types.js';
/** Why a feature could not run. Distinct codes let callers map to HTTP status. */
export type RuntimeErrorCode = 'feature_disabled' | 'no_provider' | 'no_model' | 'no_key' | 'budget_exceeded' | 'provider_error';
export interface RuntimeError {
    ok: false;
    code: RuntimeErrorCode;
    message: string;
}
/** A fully-resolved, ready-to-call runtime for a feature. */
export interface ResolvedFeatureRuntime {
    ok: true;
    featureKey: string;
    providerKey: AIProviderKey;
    connectionId: string;
    baseUrl?: string;
    apiKey: string;
    /** Catalog id (`provider:modelId`) selected for this feature. */
    modelId: string;
    /** Provider-native model id sent on the wire. */
    providerModelId: string;
    /** When true, omit temperature / top_p / top_k on the provider request. */
    disallowsSampling: boolean;
}
/**
 * Is a configured AI feature turned on? Unknown keys default to enabled so that
 * callers gating on a key the config doesn't track yet don't silently break.
 */
export declare function isAiFeatureEnabled(db: unknown, featureKey: string): Promise<boolean>;
/**
 * Resolve provider + model + key + budget for a feature, enforcing the toggle.
 * Pure resolution — performs no model call. Returns a discriminated result so
 * callers can branch (e.g. fall back to a legacy provider on `no_provider`).
 */
export declare function resolveFeatureRuntime(db: unknown, featureKey: string): Promise<ResolvedFeatureRuntime | RuntimeError>;
export interface GenerateForFeatureInput {
    prompt: string;
    system?: string;
    maxTokens?: number;
    temperature?: number;
    /** Recorded on the usage audit entry so spend is attributable. */
    userId?: string;
    /**
     * Prepend the active brand voice (if enabled) to the system prompt. Content
     * features (co-author, SEO copy) opt in; structured/metadata features leave
     * it off. Defaults to false so callers are explicit.
     */
    useBrandVoice?: boolean;
    /** Injectable fetch for tests; forwarded to the provider adapter. */
    fetchImpl?: typeof fetch;
    /** Per-call timeout override (ms). */
    timeoutMs?: number;
}
export interface GenerateForFeatureSuccess {
    ok: true;
    text: string;
    usage: {
        promptTokens: number;
        completionTokens: number;
        totalTokens: number;
    };
    modelId: string;
    providerModelId: string;
}
/**
 * Run a text generation for a feature through the governed path: resolve →
 * enforce → call → record usage. Returns a discriminated result; never throws
 * for the expected "not configured / disabled / budget" cases (those are
 * {@link RuntimeError}). Genuine provider/transport failures surface as a
 * `provider_error` RuntimeError too, so callers have a single shape to handle.
 */
export declare function generateTextForFeature(db: unknown, featureKey: string, input: GenerateForFeatureInput): Promise<GenerateForFeatureSuccess | RuntimeError>;
//# sourceMappingURL=runtime.d.ts.map