[providers.bedrock]
display_name = "Amazon Bedrock"
adapter = "bedrock"
api_key_url = "https://docs.aws.amazon.com/bedrock/latest/userguide/api-keys.html"
base_url = "https://bedrock-runtime.us-east-1.amazonaws.com"
priority = 20
enabled = false

[providers.bedrock.auth]
# An explicit Bedrock API key wins (from the process env, or the server
# vault via `fabro secret set <name>`, matching every other provider's
# env-then-vault order); SigV4 (the AWS default credential chain, resolved
# at request time) is the fallback. `aws_sigv4` always resolves, which is
# why this provider ships disabled: enabling it is the operator's statement
# that AWS credentials are expected to work. The key is read from either
# `AWS_BEARER_TOKEN_BEDROCK` (the AWS-canonical name, also honored by the
# AWS SDKs/CLI) or `BEDROCK_API_KEY` (Fabro's `<PROVIDER>_API_KEY`
# convention); the env names are checked before the vault.
credentials = [
    "env:AWS_BEARER_TOKEN_BEDROCK",
    "env:BEDROCK_API_KEY",
    "vault:AWS_BEARER_TOKEN_BEDROCK",
    "vault:BEDROCK_API_KEY",
    "aws_sigv4",
]

# To enable Bedrock, add the following to ~/.fabro/settings.toml:
#
# [llm.providers.bedrock]
# enabled = true
# base_url = "https://bedrock-runtime.<your-region>.amazonaws.com"
#
# The signing region is derived from the base_url. Authenticate with
# either a Bedrock API key (AWS_BEARER_TOKEN_BEDROCK or BEDROCK_API_KEY) or
# any AWS default credential chain source (env keys, profile, IMDS, IRSA, SSO).
#
# Model ids use cross-region inference profiles (`us.` / `global.`
# prefixes) where on-demand access requires them. Pricing rows are
# best-effort estimates from June 2026 list prices.

# ---------- Anthropic Claude ----------
#
# Claude bills Anthropic-style cache reads/writes, so these rows override
# the provider's billing default. Claude 5 models appear at the end of this
# file because their Bedrock deployments pin sampling parameters and require
# extra endpoint-specific handling.

[providers.bedrock.models."claude-sonnet-4-6"]
api_id = "us.anthropic.claude-sonnet-4-6"
display_name = "Claude Sonnet 4.6 (Bedrock)"
family = "claude-4"
billing_policy = "anthropic"

[providers.bedrock.models."claude-sonnet-4-6".limits]
context_window = 1000000
max_output = 64000

[providers.bedrock.models."claude-sonnet-4-6".features]
tools = true
vision = true
reasoning = true
prompt_cache = true

[providers.bedrock.models."claude-sonnet-4-6".costs]
input_cost_per_mtok = 3.0
output_cost_per_mtok = 15.0
cache_input_cost_per_mtok = 0.3

[providers.bedrock.models."claude-opus-4-8"]
api_id = "us.anthropic.claude-opus-4-8"
display_name = "Claude Opus 4.8 (Bedrock)"
family = "claude-4"
billing_policy = "anthropic"

[providers.bedrock.models."claude-opus-4-8".limits]
context_window = 1000000
max_output = 128000

[providers.bedrock.models."claude-opus-4-8".features]
tools = true
vision = true
reasoning = true
prompt_cache = true

[providers.bedrock.models."claude-opus-4-8".costs]
input_cost_per_mtok = 5.0
output_cost_per_mtok = 25.0
cache_input_cost_per_mtok = 0.5

[providers.bedrock.models."claude-haiku-4-5"]
api_id = "us.anthropic.claude-haiku-4-5-20251001-v1:0"
display_name = "Claude Haiku 4.5 (Bedrock)"
family = "claude-4"
billing_policy = "anthropic"
small_default = true

[providers.bedrock.models."claude-haiku-4-5".limits]
context_window = 200000
max_output = 64000

[providers.bedrock.models."claude-haiku-4-5".features]
tools = true
vision = true
reasoning = false
prompt_cache = true

[providers.bedrock.models."claude-haiku-4-5".costs]
input_cost_per_mtok = 1.0
output_cost_per_mtok = 5.0
cache_input_cost_per_mtok = 0.1

# ---------- OpenAI open-weights ----------
#
# GPT-5.5/5.4 are NOT here: on Bedrock they are Responses-API-only on the
# bedrock-mantle endpoint (no Converse), a named follow-up route.

[providers.bedrock.models."gpt-oss-120b"]
api_id = "openai.gpt-oss-120b-1:0"
display_name = "GPT-OSS 120B (Bedrock)"
family = "gpt-oss"
billing_policy = "openai"
agent_profile = "openai"

[providers.bedrock.models."gpt-oss-120b".limits]
context_window = 128000
max_output = 16384

[providers.bedrock.models."gpt-oss-120b".features]
tools = true
vision = false
reasoning = true

[providers.bedrock.models."gpt-oss-120b".costs]
input_cost_per_mtok = 0.15
output_cost_per_mtok = 0.60

[providers.bedrock.models."gpt-oss-20b"]
api_id = "openai.gpt-oss-20b-1:0"
display_name = "GPT-OSS 20B (Bedrock)"
family = "gpt-oss"
billing_policy = "openai"
agent_profile = "openai"

[providers.bedrock.models."gpt-oss-20b".limits]
context_window = 128000
max_output = 16384

[providers.bedrock.models."gpt-oss-20b".features]
tools = true
vision = false
reasoning = true

[providers.bedrock.models."gpt-oss-20b".costs]
input_cost_per_mtok = 0.07
output_cost_per_mtok = 0.30

# ---------- Amazon Nova ----------

[providers.bedrock.models."nova-2-lite"]
api_id = "global.amazon.nova-2-lite-v1:0"
display_name = "Nova 2 Lite (Bedrock)"
family = "nova-2"
billing_policy = "openai"
agent_profile = "openai"

[providers.bedrock.models."nova-2-lite".limits]
context_window = 1000000
# Bedrock caps Nova output at 65535 (2^16 - 1); 65536 trips
# "maximum tokens exceeds the model limit of 65535" since the prompt handler
# defaults max_tokens to max_output.
max_output = 65535

[providers.bedrock.models."nova-2-lite".features]
tools = true
vision = true
reasoning = false

[providers.bedrock.models."nova-2-lite".costs]
input_cost_per_mtok = 0.30
output_cost_per_mtok = 2.50

# ---------- Open-weights ----------

[providers.bedrock.models."llama-4-maverick"]
api_id = "us.meta.llama4-maverick-17b-instruct-v1:0"
display_name = "Llama 4 Maverick (Bedrock)"
family = "llama-4"
billing_policy = "openai"
agent_profile = "openai"

[providers.bedrock.models."llama-4-maverick".limits]
context_window = 1000000
max_output = 8192

[providers.bedrock.models."llama-4-maverick".features]
tools = true
vision = true
reasoning = false

[providers.bedrock.models."mistral-large-3"]
api_id = "mistral.mistral-large-3-675b-instruct"
display_name = "Mistral Large 3 (Bedrock)"
family = "mistral-large"
billing_policy = "openai"
agent_profile = "openai"

[providers.bedrock.models."mistral-large-3".limits]
context_window = 256000
max_output = 32768

[providers.bedrock.models."mistral-large-3".features]
tools = true
vision = true
reasoning = false

[providers.bedrock.models."mistral-large-3".costs]
input_cost_per_mtok = 0.50
output_cost_per_mtok = 1.50

[providers.bedrock.models."devstral-2"]
api_id = "mistral.devstral-2-123b"
display_name = "Devstral 2 (Bedrock)"
family = "devstral"
billing_policy = "openai"
agent_profile = "openai"

[providers.bedrock.models."devstral-2".limits]
context_window = 256000
max_output = 32768

[providers.bedrock.models."devstral-2".features]
tools = true
vision = false
reasoning = false

[providers.bedrock.models."deepseek-v3.2"]
api_id = "deepseek.v3.2"
display_name = "DeepSeek V3.2 (Bedrock)"
family = "deepseek-v3"
billing_policy = "openai"
agent_profile = "openai"

[providers.bedrock.models."deepseek-v3.2".limits]
context_window = 164000
max_output = 8192

[providers.bedrock.models."deepseek-v3.2".features]
tools = true
vision = false
reasoning = true

[providers.bedrock.models."deepseek-v3.2".costs]
input_cost_per_mtok = 0.62
output_cost_per_mtok = 1.85

# Qwen3 Coder Next: omitted pending a verified Bedrock model/inference-profile
# id. The fabro id is not itself a valid Bedrock identifier (Converse returns
# "The provided model identifier is invalid"), so this row needs an explicit
# `api_id` confirmed against `aws bedrock list-inference-profiles` before it
# ships. Re-add with:
#   [providers.bedrock.models."qwen3-coder-next"]
#   api_id = "<verified bedrock id>"
#   display_name = "Qwen3 Coder Next (Bedrock)"
#   family = "qwen3"
#   billing_policy = "openai"
#   agent_profile = "openai"
#   [providers.bedrock.models."qwen3-coder-next".limits]
#   context_window = 256000
#   max_output = 16384
#   [providers.bedrock.models."qwen3-coder-next".features]
#   tools = true

[providers.bedrock.models."kimi-k2.5"]
api_id = "moonshotai.kimi-k2.5"
display_name = "Kimi K2.5 (Bedrock)"
family = "kimi-k2"
billing_policy = "openai"
agent_profile = "openai"

[providers.bedrock.models."kimi-k2.5".limits]
context_window = 262144
max_output = 16384

[providers.bedrock.models."kimi-k2.5".features]
tools = true
vision = true
reasoning = false

[providers.bedrock.models."kimi-k2.5".costs]
input_cost_per_mtok = 0.60
output_cost_per_mtok = 3.00

[providers.bedrock.models."glm-5"]
api_id = "zai.glm-5"
display_name = "GLM 5 (Bedrock)"
family = "glm"
billing_policy = "openai"
agent_profile = "openai"

[providers.bedrock.models."glm-5".limits]
context_window = 200000
max_output = 128000

[providers.bedrock.models."glm-5".features]
tools = true
vision = false
reasoning = false

[providers.bedrock.models."glm-5".costs]
input_cost_per_mtok = 1.00
output_cost_per_mtok = 3.20

[providers.bedrock.models."minimax-m2.5"]
api_id = "minimax.minimax-m2.5"
display_name = "MiniMax M2.5 (Bedrock)"
family = "minimax-m2"
billing_policy = "openai"
agent_profile = "openai"

[providers.bedrock.models."minimax-m2.5".limits]
context_window = 196000
max_output = 8192

[providers.bedrock.models."minimax-m2.5".features]
tools = true
vision = false
reasoning = false

[providers.bedrock.models."minimax-m2.5".costs]
input_cost_per_mtok = 0.30
output_cost_per_mtok = 1.20

[providers.bedrock.models."nemotron-3-super"]
api_id = "nvidia.nemotron-super-3-120b"
display_name = "Nemotron 3 Super (Bedrock)"
family = "nemotron-3"
billing_policy = "openai"
agent_profile = "openai"

[providers.bedrock.models."nemotron-3-super".limits]
context_window = 256000
max_output = 32768

[providers.bedrock.models."nemotron-3-super".features]
tools = true
vision = false
reasoning = false

# Claude Fable 5: adaptive thinking is always on server-side; the row pins
# sampling_params = false so the Converse encoder drops temperature/top_p
# (Bedrock rejects them for this model). Requires the account-level
# provider_data_share opt-in in the Bedrock console. Effort-level mapping
# through additionalModelRequestFields is a named follow-up, so
# reasoning_effort stays undeclared here (requests carrying one are
# rejected up front rather than silently dropped).

[providers.bedrock.models."claude-fable-5"]
api_id = "us.anthropic.claude-fable-5"
display_name = "Claude Fable 5 (Bedrock)"
family = "claude-5"
billing_policy = "anthropic"
agent_profile = "claude-5"

[providers.bedrock.models."claude-fable-5".limits]
context_window = 1000000
max_output = 128000

[providers.bedrock.models."claude-fable-5".features]
tools = true
vision = true
reasoning = true
reasoning_by_default = true
prompt_cache = true
sampling_params = false

[providers.bedrock.models."claude-fable-5".costs]
input_cost_per_mtok = 10.0
output_cost_per_mtok = 50.0
cache_input_cost_per_mtok = 1.0

# Claude Sonnet 5 uses adaptive thinking by default and rejects non-default
# sampling parameters. Effort-level mapping through
# additionalModelRequestFields is a named follow-up, as for Fable 5.

[providers.bedrock.models."claude-sonnet-5"]
api_id = "us.anthropic.claude-sonnet-5"
display_name = "Claude Sonnet 5 (Bedrock)"
family = "claude-5"
billing_policy = "anthropic"
default = true
agent_profile = "claude-5"

[providers.bedrock.models."claude-sonnet-5".limits]
context_window = 1000000
max_output = 128000

[providers.bedrock.models."claude-sonnet-5".features]
tools = true
vision = true
reasoning = true
reasoning_by_default = true
prompt_cache = true
sampling_params = false

# Introductory pricing through August 31, 2026.
[providers.bedrock.models."claude-sonnet-5".costs]
input_cost_per_mtok = 2.0
output_cost_per_mtok = 10.0
cache_input_cost_per_mtok = 0.2
