"use strict";
/**
 * AzureOpenAIAdapter -- Azure OpenAI Service transport adapter.
 *
 * Implements LlmProviderAdapter for the Azure OpenAI REST wire format.
 * Does NOT extend or reuse OpenAIAdapter. The Azure wire format differs
 * on: URL structure, auth model, api-version query parameter, and
 * content_filter_results in the response.
 *
 * Wire format:
 *   POST https://<resource>.openai.azure.com/openai/deployments/<deployment>/
 *        chat/completions?api-version=<version>
 *
 * Auth options:
 *   - api-key header (API key auth)
 *   - Authorization: Bearer <token> (Azure AD OAuth)
 *
 * Spec: P3-SUB-01 AC 12-15 (AzureOpenAIAdapter)
 *
 * @connexum/ai-governance
 */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.AzureOpenAIAdapter = exports.TESTED_API_VERSION = void 0;
const https = __importStar(require("https"));
const http = __importStar(require("http"));
const url_1 = require("url");
const base_1 = require("./base");
const index_1 = require("./index");
const shared_1 = require("./shared");
// ---------------------------------------------------------------------------
// Constants (AC 26 -- version pinning)
// ---------------------------------------------------------------------------
/** Azure OpenAI API version this adapter was tested against */
exports.TESTED_API_VERSION = '2024-10-21';
function httpRequest(urlStr, method, headers, body, timeoutMs) {
    return new Promise((resolve, reject) => {
        let url;
        try {
            url = new url_1.URL(urlStr);
        }
        catch {
            reject(new Error(`Invalid URL: ${urlStr}`));
            return;
        }
        const isHttps = url.protocol === 'https:';
        const transport = isHttps ? https : http;
        const options = {
            hostname: url.hostname,
            port: url.port || (isHttps ? 443 : 80),
            path: url.pathname + url.search,
            method,
            headers: {
                ...headers,
                'Content-Length': Buffer.byteLength(body).toString(),
            },
        };
        const req = transport.request(options, (res) => {
            const chunks = [];
            res.on('data', (chunk) => chunks.push(chunk));
            res.on('end', () => {
                resolve({
                    statusCode: res.statusCode ?? 0,
                    headers: res.headers,
                    body: Buffer.concat(chunks).toString('utf-8'),
                });
            });
            res.on('error', reject);
        });
        req.setTimeout(timeoutMs, () => {
            req.destroy(new Error(`Request timed out after ${timeoutMs}ms`));
        });
        req.on('error', reject);
        req.write(body);
        req.end();
    });
}
function getHeaderString(headers, name) {
    const val = headers[name.toLowerCase()];
    if (Array.isArray(val))
        return val[0];
    return val ?? undefined;
}
// ---------------------------------------------------------------------------
// Register Azure OpenAI compliance metadata on module load (AC 15)
// ---------------------------------------------------------------------------
(0, base_1.registerProviderCompliance)({
    providerId: 'microsoft',
    baa: true,
    baaScope: 'text-modalities-only',
    gdprDpa: true,
    soc2Type2: true,
    sovereignty: 'multi',
    attestationUrl: 'https://learn.microsoft.com/en-us/azure/compliance/offerings/offering-hipaa-hitech',
    // attestationDate must be verified by governance team before production use.
    // Set to the date this spec was written as a placeholder; update after human
    // verification of the attestation URL above.
    attestationDate: '2026-04-21',
    reviewCadence: '90d',
    baaNote: 'Audio/realtime modalities are not covered under the current Microsoft BAA as of ' +
        '2026-04-21. Verify before enabling audio or realtime API routes under HIPAA pack.',
});
// ---------------------------------------------------------------------------
// AzureOpenAIAdapter
// ---------------------------------------------------------------------------
class AzureOpenAIAdapter extends base_1.BaseProviderAdapter {
    adapterId = 'azure-openai';
    providerId = 'microsoft';
    azureConfig = null;
    // ---------------------------------------------------------------------------
    // Lifecycle
    // ---------------------------------------------------------------------------
    initialize(config) {
        const azCfg = config;
        // Fail-closed: structurally required fields
        if (!azCfg.resourceName) {
            throw new index_1.LlmAuthError({
                message: 'AzureOpenAIAdapter: resourceName is required in config.',
                providerId: this.providerId,
                adapterId: this.adapterId,
            });
        }
        if (!azCfg.deploymentName) {
            throw new index_1.LlmAuthError({
                message: 'AzureOpenAIAdapter: deploymentName is required in config.',
                providerId: this.providerId,
                adapterId: this.adapterId,
            });
        }
        if (!azCfg.apiKey) {
            throw new index_1.LlmAuthError({
                message: 'AzureOpenAIAdapter: apiKey is required (API key for api-key auth, or Azure AD bearer token for azure-ad auth).',
                providerId: this.providerId,
                adapterId: this.adapterId,
            });
        }
        super.initialize(config);
        this.azureConfig = azCfg;
    }
    // ---------------------------------------------------------------------------
    // URL builder
    // ---------------------------------------------------------------------------
    buildUrl(path) {
        const cfg = this.azureConfig;
        const apiVersion = cfg.apiVersion ?? exports.TESTED_API_VERSION;
        const base = cfg.baseUrl
            ? cfg.baseUrl.replace(/\/$/, '')
            : `https://${cfg.resourceName}.openai.azure.com`;
        return `${base}/openai/deployments/${cfg.deploymentName}/${path}?api-version=${apiVersion}`;
    }
    // ---------------------------------------------------------------------------
    // Auth headers
    // ---------------------------------------------------------------------------
    buildAuthHeaders() {
        const cfg = this.azureConfig;
        const authType = cfg.authType ?? 'api-key';
        const headers = {
            'Content-Type': 'application/json',
        };
        if (authType === 'azure-ad') {
            headers['Authorization'] = `Bearer ${cfg.apiKey}`;
        }
        else {
            headers['api-key'] = cfg.apiKey;
        }
        return headers;
    }
    // ---------------------------------------------------------------------------
    // chat (AC 12)
    // ---------------------------------------------------------------------------
    async chat(request) {
        this.ensureInitialized();
        return this.withRetry(async () => this.chatOnce(request));
    }
    async chatOnce(request) {
        const cfg = this.azureConfig;
        const deploymentName = cfg.deploymentName;
        // AC 23: unknown model ID check -- Azure uses deploymentName, but if the
        // request explicitly specifies a modelId that differs wildly, surface it.
        // We validate that modelId is a non-empty string; Azure deployment name is
        // the effective model selector.
        if (!request.modelId || typeof request.modelId !== 'string') {
            throw new index_1.LlmModelNotFoundError({
                message: `AzureOpenAIAdapter: invalid modelId '${request.modelId}'. Provide a non-empty string.`,
                providerId: this.providerId,
                adapterId: this.adapterId,
                requestedModelId: String(request.modelId ?? ''),
            });
        }
        const body = {
            messages: request.messages,
            max_tokens: request.maxTokens,
            temperature: request.temperature,
        };
        if (request.tools && request.tools.length > 0) {
            body['tools'] = (0, shared_1.normalizeToolUseRequest)(request.tools, 'azure');
            body['tool_choice'] = 'auto';
        }
        const url = this.buildUrl('chat/completions');
        const rawBody = JSON.stringify(body);
        const headers = this.buildAuthHeaders();
        const timeoutMs = this.config?.timeoutMs ?? 30000;
        const response = await httpRequest(url, 'POST', headers, rawBody, timeoutMs);
        // Version mismatch check (AC 26)
        const observedVersion = getHeaderString(response.headers, 'api-version') ??
            getHeaderString(response.headers, 'x-ms-api-version');
        const pinnedVersion = cfg.apiVersion ?? exports.TESTED_API_VERSION;
        (0, shared_1.emitVersionMismatchIfNeeded)(observedVersion, pinnedVersion, this.adapterId, this.providerId, (evt) => this.emit(evt));
        this.handleHttpErrors(response, null);
        let parsed;
        try {
            parsed = JSON.parse(response.body);
        }
        catch {
            const rawShape = response.body.slice(0, 200);
            throw new index_1.LlmProviderError({
                message: `AzureOpenAIAdapter: failed to parse response as JSON`,
                code: 'UNEXPECTED_RESPONSE_SHAPE',
                providerId: this.providerId,
                adapterId: this.adapterId,
                raw: rawShape,
            });
        }
        (0, shared_1.detectUnexpectedShape)(parsed, ['choices', 'model'], this.providerId, this.adapterId);
        // AC 14: deployment-model substitution detection
        if (parsed.model && parsed.model !== deploymentName) {
            this.emit({
                type: 'llm:model-substitution',
                severity: 'INFO',
                adapterId: this.adapterId,
                providerId: this.providerId,
                detail: `Azure deployment '${deploymentName}' resolved to model '${parsed.model}'.`,
                timestamp: new Date().toISOString(),
                data: { deploymentName, actualModel: parsed.model },
            });
        }
        const actualModelId = parsed.model ?? deploymentName;
        const choice = parsed.choices?.[0];
        // AC 13: content filter results
        this.processContentFilterResults(choice?.content_filter_results ?? null, choice?.finish_reason ?? null);
        const toolCalls = choice?.message?.tool_calls
            ? (0, shared_1.normalizeToolUseResponse)(choice.message.tool_calls, 'azure')
            : undefined;
        const usage = parsed.usage
            ? {
                inputTokens: parsed.usage.prompt_tokens,
                outputTokens: parsed.usage.completion_tokens,
                totalTokens: parsed.usage.total_tokens,
            }
            : undefined;
        return {
            modelId: actualModelId,
            content: choice?.message?.content ?? '',
            finishReason: this.mapFinishReason(choice?.finish_reason),
            toolCalls,
            usage,
            _raw: parsed,
        };
    }
    // ---------------------------------------------------------------------------
    // chatStream (AC 12)
    // ---------------------------------------------------------------------------
    async *chatStream(request) {
        this.ensureInitialized();
        const cfg = this.azureConfig;
        const deploymentName = cfg.deploymentName;
        if (!request.modelId || typeof request.modelId !== 'string') {
            throw new index_1.LlmModelNotFoundError({
                message: `AzureOpenAIAdapter: invalid modelId '${request.modelId}'.`,
                providerId: this.providerId,
                adapterId: this.adapterId,
                requestedModelId: String(request.modelId ?? ''),
            });
        }
        const body = {
            messages: request.messages,
            max_tokens: request.maxTokens,
            temperature: request.temperature,
            stream: true,
        };
        if (request.tools && request.tools.length > 0) {
            body['tools'] = (0, shared_1.normalizeToolUseRequest)(request.tools, 'azure');
            body['tool_choice'] = 'auto';
        }
        const url = this.buildUrl('chat/completions');
        const rawBody = JSON.stringify(body);
        const headers = this.buildAuthHeaders();
        // For streaming we need a raw chunk-by-chunk response.
        // We collect the full response body then parse SSE lines.
        // Production usage should use a true streaming HTTP client;
        // this implementation is functionally correct for governance purposes.
        const timeoutMs = this.config?.timeoutMs ?? 60000;
        const response = await httpRequest(url, 'POST', headers, rawBody, timeoutMs);
        this.handleHttpErrors(response, null);
        // Parse Server-Sent Events
        const lines = response.body.split('\n');
        let substitutionEmitted = false;
        for (const line of lines) {
            const trimmed = line.trim();
            if (!trimmed.startsWith('data:'))
                continue;
            const data = trimmed.slice(5).trim();
            if (data === '[DONE]')
                break;
            let chunk;
            try {
                chunk = JSON.parse(data);
            }
            catch {
                continue;
            }
            // AC 14: model substitution detection on first chunk
            if (!substitutionEmitted && chunk.model && chunk.model !== deploymentName) {
                substitutionEmitted = true;
                this.emit({
                    type: 'llm:model-substitution',
                    severity: 'INFO',
                    adapterId: this.adapterId,
                    providerId: this.providerId,
                    detail: `Azure deployment '${deploymentName}' resolved to model '${chunk.model}'.`,
                    timestamp: new Date().toISOString(),
                    data: { deploymentName, actualModel: chunk.model },
                });
            }
            const choice = chunk.choices?.[0];
            if (!choice)
                continue;
            // AC 13: content filter on streaming chunks
            if (choice.content_filter_results) {
                this.processContentFilterResults(choice.content_filter_results, choice.finish_reason ?? null);
            }
            const delta = choice.delta?.content ?? '';
            const finishReason = choice.finish_reason
                ? this.mapFinishReason(choice.finish_reason)
                : undefined;
            yield {
                delta,
                finishReason,
            };
        }
    }
    // ---------------------------------------------------------------------------
    // invokeToolUse (AC 12)
    // ---------------------------------------------------------------------------
    async invokeToolUse(request) {
        this.ensureInitialized();
        return this.withRetry(async () => this.invokeToolUseOnce(request));
    }
    async invokeToolUseOnce(request) {
        const cfg = this.azureConfig;
        const deploymentName = cfg.deploymentName;
        if (!request.modelId || typeof request.modelId !== 'string') {
            throw new index_1.LlmModelNotFoundError({
                message: `AzureOpenAIAdapter: invalid modelId '${request.modelId}'.`,
                providerId: this.providerId,
                adapterId: this.adapterId,
                requestedModelId: String(request.modelId ?? ''),
            });
        }
        if (!request.tools || request.tools.length === 0) {
            throw new index_1.LlmProviderError({
                message: 'AzureOpenAIAdapter.invokeToolUse: at least one tool definition is required.',
                code: 'TOOL_USE_FAILURE',
                providerId: this.providerId,
                adapterId: this.adapterId,
            });
        }
        const body = {
            messages: request.messages,
            tools: (0, shared_1.normalizeToolUseRequest)(request.tools, 'azure'),
            tool_choice: 'auto',
            max_tokens: request.maxTokens,
            temperature: request.temperature,
        };
        const url = this.buildUrl('chat/completions');
        const rawBody = JSON.stringify(body);
        const headers = this.buildAuthHeaders();
        const timeoutMs = this.config?.timeoutMs ?? 30000;
        const response = await httpRequest(url, 'POST', headers, rawBody, timeoutMs);
        this.handleHttpErrors(response, null);
        let parsed;
        try {
            parsed = JSON.parse(response.body);
        }
        catch {
            throw new index_1.LlmProviderError({
                message: 'AzureOpenAIAdapter: failed to parse tool-use response as JSON',
                code: 'UNEXPECTED_RESPONSE_SHAPE',
                providerId: this.providerId,
                adapterId: this.adapterId,
                raw: response.body.slice(0, 200),
            });
        }
        (0, shared_1.detectUnexpectedShape)(parsed, ['choices', 'model'], this.providerId, this.adapterId);
        if (parsed.model && parsed.model !== deploymentName) {
            this.emit({
                type: 'llm:model-substitution',
                severity: 'INFO',
                adapterId: this.adapterId,
                providerId: this.providerId,
                detail: `Azure deployment '${deploymentName}' resolved to model '${parsed.model}' during tool use.`,
                timestamp: new Date().toISOString(),
                data: { deploymentName, actualModel: parsed.model },
            });
        }
        const actualModelId = parsed.model ?? deploymentName;
        const choice = parsed.choices?.[0];
        this.processContentFilterResults(choice?.content_filter_results ?? null, choice?.finish_reason ?? null);
        const rawToolCalls = choice?.message?.tool_calls ?? [];
        const toolCalls = (0, shared_1.normalizeToolUseResponse)(rawToolCalls, 'azure');
        const usage = parsed.usage
            ? {
                inputTokens: parsed.usage.prompt_tokens,
                outputTokens: parsed.usage.completion_tokens,
                totalTokens: parsed.usage.total_tokens,
            }
            : undefined;
        return {
            modelId: actualModelId,
            toolCalls,
            content: choice?.message?.content ?? undefined,
            finishReason: this.mapFinishReason(choice?.finish_reason),
            usage,
            _raw: parsed,
        };
    }
    // ---------------------------------------------------------------------------
    // enumerateModels
    // ---------------------------------------------------------------------------
    async enumerateModels() {
        this.ensureInitialized();
        // Azure OpenAI does not provide a generic model enumeration endpoint.
        // The deployed model is identified via the deployment name at config time.
        const cfg = this.azureConfig;
        return [
            {
                modelId: cfg.deploymentName,
                family: 'gpt',
                displayName: `Azure deployment: ${cfg.deploymentName}`,
                deprecated: false,
            },
        ];
    }
    // ---------------------------------------------------------------------------
    // translateError (AC 22-24)
    // ---------------------------------------------------------------------------
    translateError(raw) {
        if (raw instanceof index_1.LlmProviderError)
            return raw;
        const isObj = (v) => typeof v === 'object' && v !== null;
        let httpStatus;
        let errorBody;
        let errorCode;
        let errorMessage;
        let retryAfterMs;
        if (isObj(raw)) {
            httpStatus = typeof raw['status'] === 'number' ? raw['status'] : undefined;
            retryAfterMs = typeof raw['retryAfterMs'] === 'number' ? raw['retryAfterMs'] : undefined;
            const inner = isObj(raw['error']) ? raw['error'] : null;
            if (inner) {
                errorCode = typeof inner['code'] === 'string' ? inner['code'] : undefined;
                errorMessage = typeof inner['message'] === 'string' ? inner['message'] : undefined;
            }
            errorBody = raw;
        }
        else if (raw instanceof Error) {
            errorMessage = raw.message;
        }
        else {
            errorMessage = String(raw);
        }
        const rawStr = isObj(raw) ? JSON.stringify(raw).slice(0, 500) : String(raw).slice(0, 500);
        if (httpStatus === 401 || errorCode === 'PermissionDenied' || errorCode === 'Unauthorized') {
            return new index_1.LlmAuthError({
                message: `Azure OpenAI auth failure: ${errorMessage ?? 'unauthorized'}`,
                providerId: this.providerId,
                adapterId: this.adapterId,
                httpStatus,
                raw: rawStr,
            });
        }
        if (httpStatus === 429) {
            return new index_1.LlmRateLimitError({
                message: `Azure OpenAI rate limit: ${errorMessage ?? 'too many requests'}`,
                providerId: this.providerId,
                adapterId: this.adapterId,
                httpStatus,
                retryAfterMs: retryAfterMs ?? 5000,
                raw: rawStr,
            });
        }
        if (httpStatus === 404 || errorCode === 'DeploymentNotFound' || errorCode === 'ModelNotFound') {
            const requestedModelId = isObj(errorBody) && typeof errorBody['deploymentName'] === 'string'
                ? errorBody['deploymentName']
                : this.azureConfig?.deploymentName ?? 'unknown';
            return new index_1.LlmModelNotFoundError({
                message: `Azure OpenAI model/deployment not found: ${errorMessage ?? errorCode}`,
                providerId: this.providerId,
                adapterId: this.adapterId,
                httpStatus,
                requestedModelId,
                raw: rawStr,
            });
        }
        return new index_1.LlmProviderError({
            message: errorMessage ?? `Azure OpenAI error (HTTP ${httpStatus ?? 'unknown'})`,
            code: errorCode ?? 'PROVIDER_ERROR',
            providerId: this.providerId,
            adapterId: this.adapterId,
            httpStatus,
            raw: rawStr,
        });
    }
    // ---------------------------------------------------------------------------
    // getCapabilities
    // ---------------------------------------------------------------------------
    getCapabilities() {
        return {
            chat: true,
            streaming: true,
            toolUse: true,
            modelEnumeration: false, // Azure does not expose a public enumeration endpoint
            baa: this.claimsBaa(),
            baaScope: 'text-modalities-only',
        };
    }
    // ---------------------------------------------------------------------------
    // Private helpers
    // ---------------------------------------------------------------------------
    /**
     * Handle non-2xx HTTP responses.
     * Translates to typed error subclasses.
     * retryAfterHeader is extracted from the response when available.
     */
    handleHttpErrors(response, _requestModelId) {
        if (response.statusCode >= 200 && response.statusCode < 300)
            return;
        const retryAfterHeader = getHeaderString(response.headers, 'retry-after');
        const retryAfterMs = (0, shared_1.parseRetryAfterMs)(retryAfterHeader);
        let errorBody = null;
        try {
            errorBody = JSON.parse(response.body);
        }
        catch {
            // body may not be JSON on some error responses
        }
        const errorCode = typeof errorBody?.['error']?.['code'] === 'string'
            ? errorBody['error']['code']
            : undefined;
        const errorMessage = typeof errorBody?.['error']?.['message'] === 'string'
            ? errorBody['error']['message']
            : undefined;
        const raw = response.body.slice(0, 500);
        if (response.statusCode === 401) {
            throw new index_1.LlmAuthError({
                message: `Azure OpenAI authentication failed: ${errorMessage ?? 'unauthorized'}`,
                providerId: this.providerId,
                adapterId: this.adapterId,
                httpStatus: 401,
                raw,
            });
        }
        if (response.statusCode === 429) {
            this.emit({
                type: 'llm:rate-limit',
                severity: 'WARN',
                adapterId: this.adapterId,
                providerId: this.providerId,
                detail: `Rate limited by Azure OpenAI. Retry-After: ${retryAfterMs}ms`,
                timestamp: new Date().toISOString(),
                data: { retryAfterMs },
            });
            throw new index_1.LlmRateLimitError({
                message: `Azure OpenAI rate limit exceeded. Retry after ${retryAfterMs}ms.`,
                providerId: this.providerId,
                adapterId: this.adapterId,
                httpStatus: 429,
                retryAfterMs: retryAfterMs > 0 ? retryAfterMs : 5000,
                raw,
            });
        }
        if (response.statusCode === 404) {
            const deploymentName = this.azureConfig?.deploymentName ?? 'unknown';
            throw new index_1.LlmModelNotFoundError({
                message: `Azure OpenAI deployment not found: ${deploymentName}. ${errorMessage ?? ''}`.trim(),
                providerId: this.providerId,
                adapterId: this.adapterId,
                httpStatus: 404,
                requestedModelId: deploymentName,
                raw,
            });
        }
        // Unknown model error codes from Azure
        if (errorCode === 'DeploymentNotFound' || errorCode === 'ModelNotFound') {
            const deploymentName = this.azureConfig?.deploymentName ?? 'unknown';
            throw new index_1.LlmModelNotFoundError({
                message: `Azure OpenAI model/deployment not found: ${errorMessage ?? errorCode}`,
                providerId: this.providerId,
                adapterId: this.adapterId,
                httpStatus: response.statusCode,
                requestedModelId: deploymentName,
                raw,
            });
        }
        throw new index_1.LlmProviderError({
            message: errorMessage ?? `Azure OpenAI error (HTTP ${response.statusCode})`,
            code: errorCode ?? 'PROVIDER_ERROR',
            providerId: this.providerId,
            adapterId: this.adapterId,
            httpStatus: response.statusCode,
            raw,
        });
    }
    /**
     * Process Azure content_filter_results from a choice.
     * Emits audit event and throws LlmContentFilterError when filtered: true.
     * Spec AC 13: emit audit event regardless of return path.
     */
    processContentFilterResults(results, finishReason) {
        if (!results)
            return;
        const categories = Object.keys(results);
        let filtered = false;
        let filterCategory;
        for (const cat of categories) {
            const catResult = results[cat];
            if (catResult?.filtered === true) {
                filtered = true;
                filterCategory = cat;
                break;
            }
        }
        // Always emit to audit chain when content filter results are present (AC 13)
        this.emit({
            type: 'llm:content-filter-triggered',
            severity: filtered ? 'WARN' : 'INFO',
            adapterId: this.adapterId,
            providerId: this.providerId,
            detail: filtered
                ? `Content filtered by Azure content filter. Category: ${filterCategory ?? 'unknown'}`
                : `Content filter results present (no block). Categories: ${categories.join(', ')}`,
            timestamp: new Date().toISOString(),
            data: {
                filtered,
                filterCategory,
                finishReason,
                results: JSON.stringify(results).slice(0, 500),
            },
        });
        if (filtered) {
            throw new index_1.LlmContentFilterError({
                message: `Azure OpenAI content filter blocked the response. Category: ${filterCategory ?? 'unknown'}`,
                providerId: this.providerId,
                adapterId: this.adapterId,
                filterCategory,
            });
        }
    }
    mapFinishReason(reason) {
        switch (reason) {
            case 'stop': return 'stop';
            case 'length': return 'length';
            case 'tool_calls': return 'tool_calls';
            case 'content_filter': return 'content_filter';
            default: return 'unknown';
        }
    }
}
exports.AzureOpenAIAdapter = AzureOpenAIAdapter;
//# sourceMappingURL=azure-openai.js.map