import { DEFAULT_ANTHROPIC_MODEL, DEFAULT_OPENAI_MODEL } from '../../../core/config.js';
import { ModelCatalogService, OPENAI_ACCOUNT_SIGN_IN_MODELS } from './model-catalog.js';
export const OPENAI_API_KEY_COMPACTION_MODEL = 'gpt-5.1-codex-mini';
export const OPENAI_OAUTH_SYSTEM_MODEL = 'gpt-5.4';
export const ANTHROPIC_COMPACTION_MODEL = 'claude-haiku-4-5';
export const OPENAI_OAUTH_MODE_DESCRIPTION = 'OAuth mode supports a smaller OpenAI allowlist.';
const OPENAI_OAUTH_DISABLED_REASON = 'Not supported';
const OPENAI_OAUTH_IMAGE_MODEL_PREFERENCES = ['gpt-5.4', 'gpt-5.4-mini'];
const REASONING_EFFORT_CAPABLE_OPENAI_MODELS = [
    'gpt-5.4',
    'gpt-5.4-pro',
    'gpt-5.4-mini',
    'gpt-5.4-nano',
    'gpt-5.5',
    'gpt-5.5-pro',
];
const OPENAI_REQUEST_REASONING_EFFORT_COMPATIBLE_MODELS = [
    'gpt-5.4',
    'gpt-5.4-pro',
    'gpt-5.4-mini',
    'gpt-5.5',
    'gpt-5.5-pro',
];
const OPENAI_REQUEST_REASONING_EFFORTS_BY_MODEL = {
    'gpt-5.4': ['low', 'medium', 'high'],
    'gpt-5.4-pro': ['low', 'medium', 'high'],
    'gpt-5.4-mini': ['low', 'medium', 'high'],
    'gpt-5.5': ['low', 'medium', 'high', 'ultrahigh'],
    'gpt-5.5-pro': ['low', 'medium', 'high', 'ultrahigh'],
};
const DEFAULT_OPENAI_REASONING_EFFORT = {
    'gpt-5.4': 'medium',
    'gpt-5.4-pro': 'medium',
    'gpt-5.4-mini': 'medium',
    'gpt-5.4-nano': 'low',
    'gpt-5.5': 'medium',
    'gpt-5.5-pro': 'medium',
};
/**
 * Provider-neutral model policy facade. It centralizes model capability,
 * credential compatibility, and system-model selection used by hosts.
 */
export class ModelPolicyService {
    static credentialModeFromSource(source) {
        if (source?.type === 'oauth') {
            return 'oauth';
        }
        if (source?.type === 'missing') {
            return 'missing';
        }
        return 'api-key';
    }
    static resolveSystemSelectedModel(args) {
        if (args.provider === 'anthropic') {
            return args.purpose === 'chat-compaction' ? ANTHROPIC_COMPACTION_MODEL : DEFAULT_ANTHROPIC_MODEL;
        }
        if (args.provider === 'openai') {
            if (args.credentialMode === 'oauth') {
                return args.activeModel && ModelCatalogService.isOpenAiAccountSignInModel(args.activeModel) ? args.activeModel : OPENAI_OAUTH_SYSTEM_MODEL;
            }
            return args.purpose === 'chat-compaction' ? OPENAI_API_KEY_COMPACTION_MODEL : DEFAULT_OPENAI_MODEL;
        }
        return DEFAULT_OPENAI_MODEL;
    }
    static validateCredentialCompatibility(args) {
        if (args.provider === 'openai' && args.credentialMode === 'oauth' && !ModelCatalogService.isOpenAiAccountSignInModel(args.model)) {
            return {
                ok: false,
                error: `OpenAI account sign-in is not enabled for model ${args.model}. Use one of ${ModelPolicyService.formatOpenAiAccountSignInModels()}, or set OPENAI_API_KEY to use Platform API-key mode${args.usageLabel ? ` for ${args.usageLabel}` : ''}.`,
            };
        }
        return { ok: true };
    }
    static assertCredentialCompatibility(args) {
        const result = ModelPolicyService.validateCredentialCompatibility(args);
        if (!result.ok) {
            throw new Error(result.error);
        }
    }
    static resolveOpenAiOAuthImageCandidateModels(activeModel) {
        return ModelPolicyService.uniqueModels([activeModel, ...OPENAI_OAUTH_IMAGE_MODEL_PREFERENCES, ...OPENAI_ACCOUNT_SIGN_IN_MODELS]);
    }
    static buildCredentialAwareModelOption(args) {
        const compatibility = ModelPolicyService.validateCredentialCompatibility({
            model: args.model,
            provider: args.provider,
            credentialMode: args.credentialMode,
        });
        return {
            id: args.model,
            label: args.label,
            disabled: !compatibility.ok,
            disabledReason: compatibility.ok ? undefined : ModelPolicyService.summarizeCredentialCompatibilityError(args),
        };
    }
    static summarizeCredentialCompatibilityError(args) {
        if (args.provider === 'openai' && args.credentialMode === 'oauth' && !ModelCatalogService.isOpenAiAccountSignInModel(args.model)) {
            return OPENAI_OAUTH_DISABLED_REASON;
        }
        return undefined;
    }
    static resolveCompatibleActiveModel(args) {
        const compatibility = ModelPolicyService.validateCredentialCompatibility({
            model: args.activeModel,
            provider: args.provider,
            credentialMode: args.credentialMode,
        });
        if (compatibility.ok) {
            return { model: args.activeModel };
        }
        const fallback = ModelPolicyService.resolveSystemSelectedModel({
            purpose: 'session-title',
            provider: args.provider,
            activeModel: args.activeModel,
            credentialMode: args.credentialMode,
        });
        if (fallback === args.activeModel) {
            return {
                model: args.activeModel,
                warning: `Model ${args.activeModel} is not supported with OpenAI account sign-in. Pick a supported OAuth model with /model set or use API-key mode.`,
            };
        }
        return {
            model: fallback,
            warning: `Model ${args.activeModel} is not supported with OpenAI account sign-in. Switched to ${fallback} for this session.`,
        };
    }
    static supportsReasoningEffort(model) {
        return REASONING_EFFORT_CAPABLE_OPENAI_MODELS.includes(model);
    }
    static supportsOpenAiRequestReasoningEffort(model) {
        return ModelPolicyService.supportedOpenAiRequestReasoningEfforts(model).length > 0;
    }
    static supportsOpenAiRequestReasoningEffortLevel(model, effort) {
        return ModelPolicyService.supportedOpenAiRequestReasoningEfforts(model).includes(effort);
    }
    static supportedOpenAiRequestReasoningEfforts(model) {
        return OPENAI_REQUEST_REASONING_EFFORTS_BY_MODEL[model] ?? (OPENAI_REQUEST_REASONING_EFFORT_COMPATIBLE_MODELS.includes(model) ?
            ['low', 'medium', 'high']
            : []);
    }
    static buildReasoningEffortOptions(model) {
        const requestSupportedEfforts = new Set(ModelPolicyService.supportedOpenAiRequestReasoningEfforts(model));
        const reasoningSupported = ModelPolicyService.supportsReasoningEffort(model);
        const defaultEffort = ModelPolicyService.resolveDefaultReasoningEffort(model);
        const disabledReason = reasoningSupported ?
            'Not supported by request path'
            : 'Not supported';
        return [
            {
                id: 'default',
                label: 'default',
                description: defaultEffort ? `Use ${model} default (${defaultEffort})` : `Do not send reasoning effort for ${model}`,
                disabled: false,
            },
            ...['low', 'medium', 'high', 'ultrahigh'].map((effort) => ({
                id: effort,
                label: effort,
                description: `Set explicit ${effort} effort`,
                disabled: !requestSupportedEfforts.has(effort),
                disabledReason: requestSupportedEfforts.has(effort) ? undefined : disabledReason,
            })),
        ];
    }
    static resolveDefaultReasoningEffort(model) {
        return DEFAULT_OPENAI_REASONING_EFFORT[model];
    }
    static formatOpenAiAccountSignInModels() {
        return OPENAI_ACCOUNT_SIGN_IN_MODELS.join(', ');
    }
    static uniqueModels(models) {
        return [...new Set(models)];
    }
}
//# sourceMappingURL=model-policy-service.js.map