Skip to content
Closed
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,8 @@ LLM_Z_AI_API_KEY=your_zai_key_here

# AWS Bedrock
LLM_AWS_BEDROCK_API_KEY=your_aws_bedrock_key_here
# AWS Bedrock Region (options: us-east-1, us-west-2, eu-west-1, eu-central-1, ap-northeast-1, ap-southeast-1)
# LLM_AWS_BEDROCK_REGION=us-east-1

# Azure
LLM_AZURE_API_KEY=your_azure_key_here
Expand Down
20 changes: 20 additions & 0 deletions apps/api/src/routes/keys-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ const providerKeySchema = z.object({
options: z
.object({
aws_bedrock_region_prefix: z.enum(["us.", "global.", "eu."]).optional(),
aws_bedrock_region: z
.enum([
"us-east-1",
"us-west-2",
"eu-west-1",
"eu-central-1",
"ap-northeast-1",
"ap-southeast-1",
])
.optional(),
azure_resource: z.string().optional(),
azure_api_version: z.string().optional(),
azure_deployment_type: z.enum(["openai", "ai-foundry"]).optional(),
Expand Down Expand Up @@ -59,6 +69,16 @@ const createProviderKeySchema = z.object({
options: z
.object({
aws_bedrock_region_prefix: z.enum(["us.", "global.", "eu."]).optional(),
aws_bedrock_region: z
.enum([
"us-east-1",
"us-west-2",
"eu-west-1",
"eu-central-1",
"ap-northeast-1",
"ap-southeast-1",
])
.optional(),
azure_resource: z.string().optional(),
azure_api_version: z.string().optional(),
azure_deployment_type: z.enum(["openai", "ai-foundry"]).optional(),
Expand Down
8 changes: 8 additions & 0 deletions apps/code/src/lib/api/v1.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4770,6 +4770,8 @@ export interface paths {
options: {
/** @enum {string} */
aws_bedrock_region_prefix?: "us." | "global." | "eu.";
/** @enum {string} */
aws_bedrock_region?: "us-east-1" | "us-west-2" | "eu-west-1" | "eu-central-1" | "ap-northeast-1" | "ap-southeast-1";
azure_resource?: string;
azure_api_version?: string;
/** @enum {string} */
Expand Down Expand Up @@ -4807,6 +4809,8 @@ export interface paths {
options?: {
/** @enum {string} */
aws_bedrock_region_prefix?: "us." | "global." | "eu.";
/** @enum {string} */
aws_bedrock_region?: "us-east-1" | "us-west-2" | "eu-west-1" | "eu-central-1" | "ap-northeast-1" | "ap-southeast-1";
azure_resource?: string;
azure_api_version?: string;
/** @enum {string} */
Expand Down Expand Up @@ -4837,6 +4841,8 @@ export interface paths {
options: {
/** @enum {string} */
aws_bedrock_region_prefix?: "us." | "global." | "eu.";
/** @enum {string} */
aws_bedrock_region?: "us-east-1" | "us-west-2" | "eu-west-1" | "eu-central-1" | "ap-northeast-1" | "ap-southeast-1";
azure_resource?: string;
azure_api_version?: string;
/** @enum {string} */
Expand Down Expand Up @@ -4955,6 +4961,8 @@ export interface paths {
options: {
/** @enum {string} */
aws_bedrock_region_prefix?: "us." | "global." | "eu.";
/** @enum {string} */
aws_bedrock_region?: "us-east-1" | "us-west-2" | "eu-west-1" | "eu-central-1" | "ap-northeast-1" | "ap-southeast-1";
azure_resource?: string;
azure_api_version?: string;
/** @enum {string} */
Expand Down
10 changes: 10 additions & 0 deletions apps/gateway/src/lib/costs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,16 @@ export async function calculateCosts(
) as ModelDefinition;
}

// Fallback: search expanded providers for region-suffixed model names
// (e.g., "anthropic.claude-3-5-haiku-20241022-v1:0:us-east-1")
if (!modelInfo) {
modelInfo = models.find((m) =>
expandAllProviderRegions(m.providers as ProviderModelMapping[]).some(
(p) => p.modelName === model,
),
) as ModelDefinition;
}

if (!modelInfo) {
return {
inputCost: null,
Expand Down
19 changes: 17 additions & 2 deletions apps/playground/src/components/model-selector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -462,11 +462,26 @@ export function ModelSelector({
const [selectedProviderId, selectedModelIdRaw] = raw.includes("/")
? (raw.split("/") as [string, string])
: ["", raw];
// Strip :region suffix for root model lookup, keep raw for mapping match
// Strip :region suffix for root model lookup, keep raw for mapping match.
// Model names can contain colons (e.g., "anthropic.claude-3-5-haiku-20241022-v1:0"),
// so we first try a direct match, then fall back to stripping the last colon segment.
const selectedModelId = selectedModelIdRaw.includes(":")
? selectedModelIdRaw.split(":")[0]
: selectedModelIdRaw;
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
const selectedModel = models.find((m) => m.id === selectedModelId);
// Direct lookup by model.id, then fallback: search all models for a mapping
// that matches the raw provider model name (handles region-expanded names like
// "anthropic.claude-3-5-haiku-20241022-v1:0:us-east-1")
const selectedModel =
models.find((m) => m.id === selectedModelId) ??
(selectedProviderId
? models.find((m) =>
m.mappings.some(
(p) =>
p.providerId === selectedProviderId &&
p.modelName === selectedModelIdRaw,
),
)
: undefined);
const selectedProviderDef = providers.find(
(p) => p.id === selectedProviderId,
);
Expand Down
8 changes: 8 additions & 0 deletions apps/playground/src/lib/api/v1.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4770,6 +4770,8 @@ export interface paths {
options: {
/** @enum {string} */
aws_bedrock_region_prefix?: "us." | "global." | "eu.";
/** @enum {string} */
aws_bedrock_region?: "us-east-1" | "us-west-2" | "eu-west-1" | "eu-central-1" | "ap-northeast-1" | "ap-southeast-1";
azure_resource?: string;
azure_api_version?: string;
/** @enum {string} */
Expand Down Expand Up @@ -4807,6 +4809,8 @@ export interface paths {
options?: {
/** @enum {string} */
aws_bedrock_region_prefix?: "us." | "global." | "eu.";
/** @enum {string} */
aws_bedrock_region?: "us-east-1" | "us-west-2" | "eu-west-1" | "eu-central-1" | "ap-northeast-1" | "ap-southeast-1";
azure_resource?: string;
azure_api_version?: string;
/** @enum {string} */
Expand Down Expand Up @@ -4837,6 +4841,8 @@ export interface paths {
options: {
/** @enum {string} */
aws_bedrock_region_prefix?: "us." | "global." | "eu.";
/** @enum {string} */
aws_bedrock_region?: "us-east-1" | "us-west-2" | "eu-west-1" | "eu-central-1" | "ap-northeast-1" | "ap-southeast-1";
azure_resource?: string;
azure_api_version?: string;
/** @enum {string} */
Expand Down Expand Up @@ -4955,6 +4961,8 @@ export interface paths {
options: {
/** @enum {string} */
aws_bedrock_region_prefix?: "us." | "global." | "eu.";
/** @enum {string} */
aws_bedrock_region?: "us-east-1" | "us-west-2" | "eu-west-1" | "eu-central-1" | "ap-northeast-1" | "ap-southeast-1";
azure_resource?: string;
azure_api_version?: string;
/** @enum {string} */
Expand Down
3 changes: 2 additions & 1 deletion apps/ui/src/components/provider-keys/provider-keys-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ interface ProviderKeysListProps {

function formatOptionLabel(key: string, value: string): string {
const labels: Record<string, string> = {
aws_bedrock_region_prefix: "Region",
aws_bedrock_region_prefix: "Cross-Region Prefix",
aws_bedrock_region: "Region",
azure_resource: "Resource",
azure_api_version: "API Version",
azure_deployment_type: "Deployment",
Expand Down
8 changes: 8 additions & 0 deletions apps/ui/src/lib/api/v1.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4770,6 +4770,8 @@ export interface paths {
options: {
/** @enum {string} */
aws_bedrock_region_prefix?: "us." | "global." | "eu.";
/** @enum {string} */
aws_bedrock_region?: "us-east-1" | "us-west-2" | "eu-west-1" | "eu-central-1" | "ap-northeast-1" | "ap-southeast-1";
azure_resource?: string;
azure_api_version?: string;
/** @enum {string} */
Expand Down Expand Up @@ -4807,6 +4809,8 @@ export interface paths {
options?: {
/** @enum {string} */
aws_bedrock_region_prefix?: "us." | "global." | "eu.";
/** @enum {string} */
aws_bedrock_region?: "us-east-1" | "us-west-2" | "eu-west-1" | "eu-central-1" | "ap-northeast-1" | "ap-southeast-1";
azure_resource?: string;
azure_api_version?: string;
/** @enum {string} */
Expand Down Expand Up @@ -4837,6 +4841,8 @@ export interface paths {
options: {
/** @enum {string} */
aws_bedrock_region_prefix?: "us." | "global." | "eu.";
/** @enum {string} */
aws_bedrock_region?: "us-east-1" | "us-west-2" | "eu-west-1" | "eu-central-1" | "ap-northeast-1" | "ap-southeast-1";
azure_resource?: string;
azure_api_version?: string;
/** @enum {string} */
Expand Down Expand Up @@ -4955,6 +4961,8 @@ export interface paths {
options: {
/** @enum {string} */
aws_bedrock_region_prefix?: "us." | "global." | "eu.";
/** @enum {string} */
aws_bedrock_region?: "us-east-1" | "us-west-2" | "eu-west-1" | "eu-central-1" | "ap-northeast-1" | "ap-southeast-1";
azure_resource?: string;
azure_api_version?: string;
/** @enum {string} */
Expand Down
8 changes: 8 additions & 0 deletions ee/admin/src/lib/api/v1.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4770,6 +4770,8 @@ export interface paths {
options: {
/** @enum {string} */
aws_bedrock_region_prefix?: "us." | "global." | "eu.";
/** @enum {string} */
aws_bedrock_region?: "us-east-1" | "us-west-2" | "eu-west-1" | "eu-central-1" | "ap-northeast-1" | "ap-southeast-1";
azure_resource?: string;
azure_api_version?: string;
/** @enum {string} */
Expand Down Expand Up @@ -4807,6 +4809,8 @@ export interface paths {
options?: {
/** @enum {string} */
aws_bedrock_region_prefix?: "us." | "global." | "eu.";
/** @enum {string} */
aws_bedrock_region?: "us-east-1" | "us-west-2" | "eu-west-1" | "eu-central-1" | "ap-northeast-1" | "ap-southeast-1";
azure_resource?: string;
azure_api_version?: string;
/** @enum {string} */
Expand Down Expand Up @@ -4837,6 +4841,8 @@ export interface paths {
options: {
/** @enum {string} */
aws_bedrock_region_prefix?: "us." | "global." | "eu.";
/** @enum {string} */
aws_bedrock_region?: "us-east-1" | "us-west-2" | "eu-west-1" | "eu-central-1" | "ap-northeast-1" | "ap-southeast-1";
azure_resource?: string;
azure_api_version?: string;
/** @enum {string} */
Expand Down Expand Up @@ -4955,6 +4961,8 @@ export interface paths {
options: {
/** @enum {string} */
aws_bedrock_region_prefix?: "us." | "global." | "eu.";
/** @enum {string} */
aws_bedrock_region?: "us-east-1" | "us-west-2" | "eu-west-1" | "eu-central-1" | "ap-northeast-1" | "ap-southeast-1";
azure_resource?: string;
azure_api_version?: string;
/** @enum {string} */
Expand Down
42 changes: 37 additions & 5 deletions packages/actions/src/get-provider-endpoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,26 @@ import {

import type { ProviderKeyOptions } from "@llmgateway/db";

/**
* Derive the AWS Bedrock cross-region inference prefix from a region ID.
* Many newer models are only available through cross-region inference profiles.
*/
function bedrockRegionPrefix(region: string): string {
if (region.startsWith("us-")) {
return "us.";
}
if (region.startsWith("eu-")) {
return "eu.";
}
if (region.startsWith("ap-")) {
return "apac.";
}
if (region.startsWith("me-")) {
return "apac.";
}
return "us.";
}
Comment on lines +13 to +31
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

AWS Bedrock cross-region inference prefix Middle East region

💡 Result:

For AWS Bedrock cross-region inference in Middle East regions (me-central-1 UAE and me-south-1 Bahrain), the prefix for global cross-region inference profiles is "global.". These profiles route inference requests from the source Middle East region to optimal commercial AWS Regions worldwide for higher throughput. Example model ID from me-central-1: global.anthropic.claude-sonnet-4-6 Usage example (Python boto3): bedrock = boto3.client('bedrock-runtime', region_name='me-central-1') model_id = "global.anthropic.claude-sonnet-4-6" response = bedrock.converse(... , modelId=model_id) Supported models include Anthropic Claude Opus 4.6, Sonnet 4.6, Haiku 4.5, Sonnet 4.5, Opus 4.5 as source regions me-central-1 and me-south-1, destination: commercial regions. ARN pattern: arn:aws:bedrock:REGION:ACCOUNT:inference-profile/global.MODEL-NAME Geographic profiles use prefixes like "us.", "eu.", but for Middle East global CRIS, it's "global.". No specific "me." geographic prefix found; global provides worldwide routing.

Citations:


Middle East region should use "global." prefix, not "apac."

AWS Bedrock cross-region inference for Middle East regions (me-central-1, me-south-1) requires the "global." prefix to route requests globally, not "apac.". Update the mapping:

if (region.startsWith("me-")) {
    return "global.";
}

Additionally, regions like sa- (South America) and af- (Africa) will default to "us." and should either be explicitly mapped or handled based on their available inference profile configurations.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/actions/src/get-provider-endpoint.ts` around lines 13 - 31, The
bedrockRegionPrefix function incorrectly maps Middle East regions; update the
branch in bedrockRegionPrefix to return "global." when region.startsWith("me-")
instead of "apac.", leaving other prefixes unchanged; also consider explicitly
handling or documenting regions like "sa-" and "af-" (currently falling back to
"us.") if you want different routing behavior.

Comment on lines +17 to +31
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code does this kind of guess: us-east-1 -> us., eu-west-1 -> eu., ap-northeast-1 -> apac..

Why it is wrong: AWS prefixes are model-specific. Claude Sonnet 4.5 supports us., eu., au., jp., and global., not apac..

https://docs.aws.amazon.com/bedrock/latest/userguide/model-card-anthropic-claude-sonnet-4-5.html#model-card-anthropic-claude-sonnet-4-5-programmatic-access


function buildVertexCompatibleEndpoint(
provider: "google-vertex" | "quartz",
url: string,
Expand Down Expand Up @@ -220,12 +240,14 @@ export function getProviderEndpoint(
break;
case "aws-bedrock":
url =
regionBaseUrl ??
getProviderEnvValue(
"aws-bedrock",
"baseUrl",
configIndex,
"https://bedrock-runtime.us-east-1.amazonaws.com",
) ?? "https://bedrock-runtime.us-east-1.amazonaws.com";
) ??
"https://bedrock-runtime.us-east-1.amazonaws.com";
break;
case "azure": {
const resource =
Expand Down Expand Up @@ -330,10 +352,20 @@ export function getProviderEndpoint(
}
return `${url}/api/paas/v4/chat/completions`;
case "aws-bedrock": {
const prefix =
providerKeyOptions?.aws_bedrock_region_prefix ??
getProviderEnvValue("aws-bedrock", "region", configIndex, "global.") ??
"global.";
// When a specific region is selected (via regionConfig), derive the
// cross-region inference prefix from the region. Many newer models
// (Claude Sonnet 4, Opus 4.5, etc.) are CR-only and require a prefix.
// Fall back to the legacy explicit prefix for backward compatibility.
const prefix = region
? bedrockRegionPrefix(region)
: (providerKeyOptions?.aws_bedrock_region_prefix ??
getProviderEnvValue(
"aws-bedrock",
"region",
configIndex,
"global.",
) ??
"global.");
Copy link
Copy Markdown
Contributor

@RATCHAW RATCHAW May 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


const endpoint = stream ? "converse-stream" : "converse";
return `${url}/model/${prefix}${modelName}/${endpoint}`;
Expand Down
7 changes: 7 additions & 0 deletions packages/db/src/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,13 @@ export const apiKeyIamRule = pgTable(

export interface ProviderKeyOptions {
aws_bedrock_region_prefix?: "us." | "global." | "eu.";
aws_bedrock_region?:
| "us-east-1"
| "us-west-2"
| "eu-west-1"
| "eu-central-1"
| "ap-northeast-1"
| "ap-southeast-1";
azure_resource?: string;
azure_api_version?: string;
azure_deployment_type?: "openai" | "ai-foundry";
Expand Down
Loading
Loading