/**
 * BedrockAdapter -- AWS Bedrock transport adapter.
 *
 * Implements LlmProviderAdapter for AWS Bedrock InvokeModel and
 * InvokeModelWithResponseStream REST endpoints.
 *
 * Wire format:
 *   POST https://bedrock-runtime.<region>.amazonaws.com/model/<modelId>/invoke
 *   POST https://bedrock-runtime.<region>.amazonaws.com/model/<modelId>/invoke-with-response-stream
 *
 * Auth: AWS Signature Version 4 (inline -- no AWS SDK).
 *
 * Model families (LlmModelFamily):
 *   anthropic.*   -> 'claude'
 *   amazon.*      -> 'titan'
 *   meta.*        -> 'llama'
 *   mistral.*     -> 'mistral'
 *   <other>       -> 'unknown'
 *
 * Region: required at initialize(). No env fallback. Silent region
 * selection is a data-sovereignty risk (spec AC 10).
 *
 * No AWS SDK. All signing done inline per AWS SigV4 spec.
 *
 * Spec: P3-SUB-01 AC 8-11 (BedrockAdapter)
 *
 * @connexum/ai-governance
 */
import * as https from 'https';
import * as http from 'http';
import * as crypto from 'crypto';
import { URL } from 'url';
import { BaseProviderAdapter, registerProviderCompliance } from './base.js';
import { LlmProviderError, LlmAuthError, LlmRateLimitError, LlmModelNotFoundError, } from './index.js';
import { coerceTextContent, detectUnexpectedShape, normalizeToolUseRequest, normalizeToolUseResponse, parseRetryAfterMs, } from './shared.js';
// ---------------------------------------------------------------------------
// Constants (AC 26 -- version pinning)
// ---------------------------------------------------------------------------
/** Bedrock runtime API date-version this adapter was tested against */
export const TESTED_API_VERSION = '2023-05-31';
function httpRequest(urlStr, method, headers, body, timeoutMs) {
    return new Promise((resolve, reject) => {
        let url;
        try {
            url = new 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;
}
// ---------------------------------------------------------------------------
// AWS Signature Version 4 (inline -- no AWS SDK, per AC 9)
// ---------------------------------------------------------------------------
function hmacSha256(key, data) {
    return crypto.createHmac('sha256', key).update(data, 'utf-8').digest();
}
function sha256Hex(data) {
    return crypto.createHash('sha256').update(data, 'utf-8').digest('hex');
}
function isoDateTime(date) {
    return date.toISOString().replace(/[:\-]|\.\d{3}/g, '').slice(0, 15) + 'Z';
}
function isoDateShort(date) {
    return date.toISOString().slice(0, 10).replace(/-/g, '');
}
/**
 * Sign a request using AWS Signature Version 4.
 * Returns the Authorization header and supporting headers (x-amz-date, etc.).
 *
 * Reference: https://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
 */
function signV4(opts) {
    const now = new Date();
    const amzDate = isoDateTime(now);
    const dateShort = isoDateShort(now);
    const payloadHash = sha256Hex(opts.body);
    // Build canonical headers (sorted, lowercase)
    const canonicalHeadersMap = {
        'content-type': 'application/json',
        'host': opts.url.hostname,
        'x-amz-date': amzDate,
        'x-amz-content-sha256': payloadHash,
        ...Object.fromEntries(Object.entries(opts.extraHeaders ?? {}).map(([k, v]) => [k.toLowerCase(), v])),
    };
    if (opts.sessionToken) {
        canonicalHeadersMap['x-amz-security-token'] = opts.sessionToken;
    }
    const sortedKeys = Object.keys(canonicalHeadersMap).sort();
    const canonicalHeaders = sortedKeys.map((k) => `${k}:${canonicalHeadersMap[k]}`).join('\n') + '\n';
    const signedHeaders = sortedKeys.join(';');
    const canonicalPath = opts.url.pathname || '/';
    const canonicalQuery = opts.url.search ? opts.url.search.slice(1) : '';
    const canonicalRequest = [
        opts.method.toUpperCase(),
        canonicalPath,
        canonicalQuery,
        canonicalHeaders,
        signedHeaders,
        payloadHash,
    ].join('\n');
    const credentialScope = `${dateShort}/${opts.region}/${opts.service}/aws4_request`;
    const stringToSign = [
        'AWS4-HMAC-SHA256',
        amzDate,
        credentialScope,
        sha256Hex(canonicalRequest),
    ].join('\n');
    const kDate = hmacSha256(`AWS4${opts.secretAccessKey}`, dateShort);
    const kRegion = hmacSha256(kDate, opts.region);
    const kService = hmacSha256(kRegion, opts.service);
    const kSigning = hmacSha256(kService, 'aws4_request');
    const signature = crypto.createHmac('sha256', kSigning).update(stringToSign, 'utf-8').digest('hex');
    const authorization = `AWS4-HMAC-SHA256 Credential=${opts.accessKeyId}/${credentialScope}, ` +
        `SignedHeaders=${signedHeaders}, Signature=${signature}`;
    const result = {
        'Authorization': authorization,
        'Content-Type': 'application/json',
        'x-amz-date': amzDate,
        'x-amz-content-sha256': payloadHash,
    };
    if (opts.sessionToken) {
        result['x-amz-security-token'] = opts.sessionToken;
    }
    return result;
}
// ---------------------------------------------------------------------------
// Register Bedrock compliance metadata on module load (AC 11)
// ---------------------------------------------------------------------------
registerProviderCompliance({
    providerId: 'amazon',
    baa: true,
    gdprDpa: true,
    soc2Type2: true,
    sovereignty: 'multi',
    attestationUrl: 'https://aws.amazon.com/compliance/hipaa-compliance/',
    // TODO (Vera/Legal, Kai): Verify this date against the attestation URL above
    // before enabling HIPAA pack with amazon provider in any production deployment.
    // Set to spec implementation date as placeholder -- flag DEFERRED-BEDROCK-ATTEST.
    attestationDate: '2026-04-22',
    reviewCadence: '90d',
});
// ---------------------------------------------------------------------------
// Model family detection
// ---------------------------------------------------------------------------
export function detectModelFamily(modelId) {
    const lower = modelId.toLowerCase();
    if (lower.startsWith('anthropic.'))
        return 'claude';
    if (lower.startsWith('amazon.'))
        return 'titan';
    if (lower.startsWith('meta.'))
        return 'llama';
    if (lower.startsWith('mistral.'))
        return 'mistral';
    return 'unknown';
}
// ---------------------------------------------------------------------------
// BedrockAdapter
// ---------------------------------------------------------------------------
export class BedrockAdapter extends BaseProviderAdapter {
    adapterId = 'bedrock';
    providerId = 'amazon';
    bedrockConfig = null;
    // ---------------------------------------------------------------------------
    // Lifecycle
    // ---------------------------------------------------------------------------
    initialize(config) {
        const cfg = config;
        // AC 10: region is required, no env fallback
        if (!cfg.region) {
            throw new LlmAuthError({
                message: 'BedrockAdapter: region is required in config. ' +
                    'Do not rely on AWS_DEFAULT_REGION. Explicit region selection is ' +
                    'required for data-sovereignty compliance.',
                providerId: this.providerId,
                adapterId: this.adapterId,
            });
        }
        // Credentials: require either awsAccessKeyId/awsSecretAccessKey OR
        // leave them absent (caller is expected to use ambient credentials via
        // EC2 instance role or container credentials, which this adapter does
        // not implement -- callers must supply explicit keys in this version).
        if (!cfg.awsAccessKeyId || !cfg.awsSecretAccessKey) {
            throw new LlmAuthError({
                message: 'BedrockAdapter: awsAccessKeyId and awsSecretAccessKey are required. ' +
                    'This adapter does not fetch ambient instance-role credentials. ' +
                    'Supply explicit credentials in config.',
                providerId: this.providerId,
                adapterId: this.adapterId,
            });
        }
        super.initialize(config);
        this.bedrockConfig = cfg;
    }
    // ---------------------------------------------------------------------------
    // URL builder
    // ---------------------------------------------------------------------------
    buildUrl(modelId, path) {
        const cfg = this.bedrockConfig;
        if (cfg.baseUrl) {
            const base = cfg.baseUrl.replace(/\/$/, '');
            return `${base}/model/${encodeURIComponent(modelId)}/${path}`;
        }
        return `https://bedrock-runtime.${cfg.region}.amazonaws.com/model/${encodeURIComponent(modelId)}/${path}`;
    }
    // ---------------------------------------------------------------------------
    // Signed request headers
    // ---------------------------------------------------------------------------
    buildSignedHeaders(urlStr, body) {
        const cfg = this.bedrockConfig;
        const url = new URL(urlStr);
        // If there is a baseUrl override (test mode), skip signing because the
        // local mock server does not validate SigV4.
        if (cfg.baseUrl) {
            return { 'Content-Type': 'application/json' };
        }
        return signV4({
            method: 'POST',
            url,
            region: cfg.region,
            service: 'bedrock',
            accessKeyId: cfg.awsAccessKeyId,
            secretAccessKey: cfg.awsSecretAccessKey,
            sessionToken: cfg.awsSessionToken,
            body,
        });
    }
    // ---------------------------------------------------------------------------
    // Message conversion: LlmMessage[] -> BedrockConverseMessage[]
    // ---------------------------------------------------------------------------
    convertMessages(request) {
        const systemParts = [];
        const messages = [];
        // Collect system-role messages + systemPrompt
        if ('systemPrompt' in request && request.systemPrompt) {
            systemParts.push(request.systemPrompt);
        }
        for (const msg of request.messages) {
            // F-NEW-GEMMA-VISION 2026-05-09: bedrock converse-stream supports
            // multimodal but this adapter has not been extended yet. Reject
            // image_url parts at the boundary rather than silently drop.
            const text = coerceTextContent(msg, {
                providerId: this.providerId,
                adapterId: this.adapterId,
            });
            if (msg.role === 'system') {
                systemParts.push(text);
                continue;
            }
            const role = msg.role === 'assistant' ? 'assistant' : 'user';
            messages.push({
                role,
                content: [{ text }],
            });
        }
        return {
            system: systemParts.length > 0 ? systemParts.map((t) => ({ text: t })) : undefined,
            messages,
        };
    }
    // ---------------------------------------------------------------------------
    // Validate model ID (throw on unknown -- spec: no silent fallback)
    // ---------------------------------------------------------------------------
    validateModelId(modelId) {
        if (!modelId || typeof modelId !== 'string') {
            throw new LlmModelNotFoundError({
                message: `BedrockAdapter: invalid modelId '${modelId}'. Provide a non-empty string in AWS format (e.g. anthropic.claude-3-5-sonnet-20241022-v2:0).`,
                providerId: this.providerId,
                adapterId: this.adapterId,
                requestedModelId: String(modelId ?? ''),
            });
        }
        const family = detectModelFamily(modelId);
        if (family === 'unknown') {
            // Unknown prefix -- still allowed at the adapter level; Bedrock itself
            // will reject if truly invalid. We throw here per spec ("no neutral-pass
            // on unknown models").
            throw new LlmModelNotFoundError({
                message: `BedrockAdapter: modelId '${modelId}' does not match any known Bedrock model family ` +
                    `(anthropic.*, amazon.*, meta.*, mistral.*). Verify the modelId format.`,
                providerId: this.providerId,
                adapterId: this.adapterId,
                requestedModelId: modelId,
            });
        }
    }
    // ---------------------------------------------------------------------------
    // chat (AC 8 -- via Converse API)
    // ---------------------------------------------------------------------------
    async chat(request) {
        this.ensureInitialized();
        this.validateModelId(request.modelId);
        return this.withRetry(async () => this.chatOnce(request));
    }
    async chatOnce(request) {
        const { system, messages } = this.convertMessages(request);
        const payload = {
            messages,
            inferenceConfig: {
                maxTokens: request.maxTokens,
                temperature: request.temperature,
            },
        };
        if (system)
            payload.system = system;
        if (request.tools && request.tools.length > 0) {
            payload.toolConfig = {
                tools: normalizeToolUseRequest(request.tools, 'bedrock'),
            };
        }
        const url = this.buildUrl(request.modelId, 'converse');
        const rawBody = JSON.stringify(payload);
        const headers = this.buildSignedHeaders(url, rawBody);
        const timeoutMs = this.bedrockConfig?.timeoutMs ?? 30000;
        const response = await httpRequest(url, 'POST', headers, rawBody, timeoutMs);
        this.handleHttpErrors(response, request.modelId);
        let parsed;
        try {
            parsed = JSON.parse(response.body);
        }
        catch {
            throw new LlmProviderError({
                message: 'BedrockAdapter: failed to parse response as JSON',
                code: 'UNEXPECTED_RESPONSE_SHAPE',
                providerId: this.providerId,
                adapterId: this.adapterId,
                raw: response.body.slice(0, 200),
            });
        }
        detectUnexpectedShape(parsed, ['output'], this.providerId, this.adapterId);
        const outputContent = parsed.output?.message?.content ?? [];
        // Extract text
        const textParts = outputContent
            .filter((b) => typeof b.text === 'string')
            .map((b) => b.text);
        // Extract tool calls (Bedrock toolUse blocks)
        const toolUseBlocks = outputContent.filter((b) => b.toolUse != null);
        const toolCalls = toolUseBlocks.length > 0
            ? normalizeToolUseResponse(toolUseBlocks.map((b) => ({ toolUse: b.toolUse })), 'bedrock')
            : undefined;
        const usage = parsed.usage
            ? {
                inputTokens: parsed.usage.inputTokens ?? 0,
                outputTokens: parsed.usage.outputTokens ?? 0,
                totalTokens: parsed.usage.totalTokens ?? (parsed.usage.inputTokens ?? 0) + (parsed.usage.outputTokens ?? 0),
            }
            : undefined;
        return {
            modelId: request.modelId,
            content: textParts.join(''),
            finishReason: this.mapStopReason(parsed.stopReason),
            toolCalls,
            usage,
            _raw: parsed,
        };
    }
    // ---------------------------------------------------------------------------
    // chatStream (AC 8 -- InvokeModelWithResponseStream via Converse stream)
    // ---------------------------------------------------------------------------
    async *chatStream(request) {
        this.ensureInitialized();
        this.validateModelId(request.modelId);
        const { system, messages } = this.convertMessages(request);
        const payload = {
            messages,
            inferenceConfig: {
                maxTokens: request.maxTokens,
                temperature: request.temperature,
            },
        };
        if (system)
            payload.system = system;
        const url = this.buildUrl(request.modelId, 'converse-stream');
        const rawBody = JSON.stringify(payload);
        const headers = this.buildSignedHeaders(url, rawBody);
        const timeoutMs = this.bedrockConfig?.timeoutMs ?? 60000;
        const response = await httpRequest(url, 'POST', headers, rawBody, timeoutMs);
        this.handleHttpErrors(response, request.modelId);
        // Bedrock converse-stream returns a binary event stream (vnd.amazon.eventstream).
        // For governance testing purposes, we parse the response body as NDJSON where
        // each line is a JSON-encoded event. In production, a proper event-stream
        // frame parser would be needed. This implementation covers the governance
        // path (audit events, chunk accumulation) correctly.
        //
        // DEFERRED-BEDROCK-EVENTSTREAM: Replace with binary event-stream frame parser
        // for production use. Track as follow-up.
        const lines = response.body.split('\n');
        for (const line of lines) {
            const trimmed = line.trim();
            if (!trimmed || trimmed === '[' || trimmed === ']')
                continue;
            const cleaned = trimmed.replace(/,$/, '');
            if (!cleaned)
                continue;
            let event;
            try {
                event = JSON.parse(cleaned);
            }
            catch {
                continue;
            }
            if (event.contentBlockDelta?.delta?.text) {
                yield { delta: event.contentBlockDelta.delta.text };
            }
            if (event.messageStop) {
                yield {
                    delta: '',
                    finishReason: this.mapStopReason(event.messageStop.stopReason),
                };
            }
            if (event.metadata?.usage) {
                const u = event.metadata.usage;
                yield {
                    delta: '',
                    usage: {
                        inputTokens: u.inputTokens ?? 0,
                        outputTokens: u.outputTokens ?? 0,
                        totalTokens: u.totalTokens ?? (u.inputTokens ?? 0) + (u.outputTokens ?? 0),
                    },
                };
            }
        }
    }
    // ---------------------------------------------------------------------------
    // invokeToolUse (AC 8 -- tool use via Converse toolConfig)
    // ---------------------------------------------------------------------------
    async invokeToolUse(request) {
        this.ensureInitialized();
        this.validateModelId(request.modelId);
        return this.withRetry(async () => this.invokeToolUseOnce(request));
    }
    async invokeToolUseOnce(request) {
        if (!request.tools || request.tools.length === 0) {
            throw new LlmProviderError({
                message: 'BedrockAdapter.invokeToolUse: at least one tool definition is required.',
                code: 'TOOL_USE_FAILURE',
                providerId: this.providerId,
                adapterId: this.adapterId,
            });
        }
        const { system, messages } = this.convertMessages(request);
        const payload = {
            messages,
            toolConfig: {
                tools: normalizeToolUseRequest(request.tools, 'bedrock'),
            },
            inferenceConfig: {
                maxTokens: request.maxTokens,
                temperature: request.temperature,
            },
        };
        if (system)
            payload.system = system;
        const url = this.buildUrl(request.modelId, 'converse');
        const rawBody = JSON.stringify(payload);
        const headers = this.buildSignedHeaders(url, rawBody);
        const timeoutMs = this.bedrockConfig?.timeoutMs ?? 30000;
        const response = await httpRequest(url, 'POST', headers, rawBody, timeoutMs);
        this.handleHttpErrors(response, request.modelId);
        let parsed;
        try {
            parsed = JSON.parse(response.body);
        }
        catch {
            throw new LlmProviderError({
                message: 'BedrockAdapter: failed to parse tool-use response as JSON',
                code: 'UNEXPECTED_RESPONSE_SHAPE',
                providerId: this.providerId,
                adapterId: this.adapterId,
                raw: response.body.slice(0, 200),
            });
        }
        detectUnexpectedShape(parsed, ['output'], this.providerId, this.adapterId);
        const outputContent = parsed.output?.message?.content ?? [];
        const toolUseBlocks = outputContent.filter((b) => b.toolUse != null);
        const toolCalls = normalizeToolUseResponse(toolUseBlocks.map((b) => ({ toolUse: b.toolUse })), 'bedrock');
        const textParts = outputContent
            .filter((b) => typeof b.text === 'string')
            .map((b) => b.text);
        const usage = parsed.usage
            ? {
                inputTokens: parsed.usage.inputTokens ?? 0,
                outputTokens: parsed.usage.outputTokens ?? 0,
                totalTokens: parsed.usage.totalTokens ?? (parsed.usage.inputTokens ?? 0) + (parsed.usage.outputTokens ?? 0),
            }
            : undefined;
        return {
            modelId: request.modelId,
            toolCalls,
            content: textParts.join('') || undefined,
            finishReason: this.mapStopReason(parsed.stopReason),
            usage,
            _raw: parsed,
        };
    }
    // ---------------------------------------------------------------------------
    // enumerateModels
    // ---------------------------------------------------------------------------
    async enumerateModels() {
        this.ensureInitialized();
        // Bedrock provides ListFoundationModels but requires additional IAM
        // permissions. Return a representative set of known model families.
        // DEFERRED-BEDROCK-MODEL-LIST: Implement ListFoundationModels API call.
        const cfg = this.bedrockConfig;
        const defaultModelId = cfg.defaultModelId ?? 'anthropic.claude-3-5-sonnet-20241022-v2:0';
        return [
            {
                modelId: defaultModelId,
                family: detectModelFamily(defaultModelId),
                displayName: `AWS Bedrock: ${defaultModelId}`,
                deprecated: false,
            },
        ];
    }
    // ---------------------------------------------------------------------------
    // translateError (AC 22-24)
    // ---------------------------------------------------------------------------
    translateError(raw) {
        if (raw instanceof LlmProviderError)
            return raw;
        const isObj = (v) => typeof v === 'object' && v !== null;
        let httpStatus;
        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;
            errorCode = typeof raw['code'] === 'string' ? raw['code'] : undefined;
            errorMessage = typeof raw['message'] === 'string' ? raw['message'] : undefined;
        }
        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 || httpStatus === 403 || errorCode === 'AccessDeniedException' || errorCode === 'UnauthorizedException') {
            return new LlmAuthError({
                message: `AWS Bedrock auth failure: ${errorMessage ?? 'unauthorized'}`,
                providerId: this.providerId,
                adapterId: this.adapterId,
                httpStatus,
                raw: rawStr,
            });
        }
        if (httpStatus === 429 || errorCode === 'ThrottlingException') {
            return new LlmRateLimitError({
                message: `AWS Bedrock rate limit: ${errorMessage ?? 'too many requests'}`,
                providerId: this.providerId,
                adapterId: this.adapterId,
                httpStatus,
                retryAfterMs: retryAfterMs ?? 5000,
                raw: rawStr,
            });
        }
        if (httpStatus === 404 || errorCode === 'ResourceNotFoundException' || errorCode === 'ModelNotFoundException') {
            const requestedModelId = this.bedrockConfig?.defaultModelId ?? 'unknown';
            return new LlmModelNotFoundError({
                message: `AWS Bedrock model not found: ${errorMessage ?? errorCode}`,
                providerId: this.providerId,
                adapterId: this.adapterId,
                httpStatus,
                requestedModelId,
                raw: rawStr,
            });
        }
        return new LlmProviderError({
            message: errorMessage ?? `AWS Bedrock 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,
            baa: this.claimsBaa(),
        };
    }
    // ---------------------------------------------------------------------------
    // Private helpers
    // ---------------------------------------------------------------------------
    handleHttpErrors(response, requestedModelId) {
        if (response.statusCode >= 200 && response.statusCode < 300)
            return;
        const retryAfterHeader = getHeaderString(response.headers, 'retry-after');
        const retryAfterMs = parseRetryAfterMs(retryAfterHeader);
        let errorBody = null;
        try {
            errorBody = JSON.parse(response.body);
        }
        catch {
            // body may not be JSON on some error responses
        }
        const isObj = (v) => typeof v === 'object' && v !== null;
        // Bedrock error format: { message: '...', __type: 'ExceptionType' }
        const errorMessage = isObj(errorBody) && typeof errorBody['message'] === 'string'
            ? errorBody['message']
            : undefined;
        const errorType = isObj(errorBody) && typeof errorBody['__type'] === 'string'
            ? errorBody['__type']
            : undefined;
        const raw = response.body.slice(0, 500);
        if (response.statusCode === 401 || response.statusCode === 403 ||
            errorType === 'AccessDeniedException' || errorType === 'UnauthorizedException') {
            throw new LlmAuthError({
                message: `AWS Bedrock authentication failed: ${errorMessage ?? 'unauthorized'}`,
                providerId: this.providerId,
                adapterId: this.adapterId,
                httpStatus: response.statusCode,
                raw,
            });
        }
        if (response.statusCode === 429 || errorType === 'ThrottlingException') {
            this.emit({
                type: 'llm:rate-limit',
                severity: 'WARN',
                adapterId: this.adapterId,
                providerId: this.providerId,
                detail: `Rate limited by AWS Bedrock. Retry-After: ${retryAfterMs}ms`,
                timestamp: new Date().toISOString(),
                data: { retryAfterMs },
            });
            throw new LlmRateLimitError({
                message: `AWS Bedrock 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 ||
            errorType === 'ResourceNotFoundException' ||
            errorType === 'ModelNotFoundException') {
            throw new LlmModelNotFoundError({
                message: `AWS Bedrock model not found: ${requestedModelId}. ${errorMessage ?? ''}`.trim(),
                providerId: this.providerId,
                adapterId: this.adapterId,
                httpStatus: 404,
                requestedModelId,
                raw,
            });
        }
        throw new LlmProviderError({
            message: errorMessage ?? `AWS Bedrock error (HTTP ${response.statusCode})`,
            code: errorType ?? 'PROVIDER_ERROR',
            providerId: this.providerId,
            adapterId: this.adapterId,
            httpStatus: response.statusCode,
            raw,
        });
    }
    mapStopReason(reason) {
        switch (reason) {
            case 'end_turn': return 'stop';
            case 'max_tokens': return 'length';
            case 'tool_use': return 'tool_calls';
            case 'stop_sequence': return 'stop';
            case 'guardrail_intervened': return 'content_filter';
            default: return 'unknown';
        }
    }
}
//# sourceMappingURL=bedrock.js.map