feat: add per-alias Azure endpoint, API version, and Anthropic version overrides with context-aware family resolution - #4015
Conversation
|
Warning Review limit reached
More reviews will be available in 27 minutes and 36 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (7)
📝 WalkthroughWalkthroughAdds ResolvedAlias and a context key; bifrost now records per-attempt resolved-alias metadata. Introduces Azure resolver helpers (endpoint, api-version, Anthropic version) and applies them across Azure provider URL, header, and routing logic; adds tests for resolver precedence and passthrough behavior. ChangesAlias-aware context resolution for Azure provider
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
|
Confidence Score: 3/5The non-streaming Passthrough path will silently drop Anthropic token counts for any alias that maps to an opaque Azure deployment ID, because extractAzurePassthroughUsage was not updated alongside every other call site in this refactor. The refactor comprehensively replaced every IsAnthropicModel and direct endpoint call in the Azure provider except one: extractAzurePassthroughUsage (line 3841) still calls schemas.IsAnthropicModel on the already-resolved model string. For an alias like best-claude → 12345-azure-deployment, that check returns false and the OpenAI usage extractor silently swallows all Anthropic token counts on the non-streaming Passthrough path. The streaming PassthroughStream path was correctly updated. This missed call site was flagged in a prior review but remains unfixed. core/providers/azure/azure.go — specifically extractAzurePassthroughUsage and its call site around line 3673 Important Files Changed
|
c0e6a75 to
c6f574f
Compare
live model cache store and port keyconfig regression tests for alias/model isolation
#4034
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@core/providers/azure/azure.go`:
- Line 930: SpeechStream currently builds url :=
fmt.Sprintf("%s/openai/v1/audio/speech" , resolveAzureEndpoint(ctx, key))
without validating the resolved endpoint; mirror the check used in Speech by
calling resolveAzureEndpoint(ctx, key) first, verify it is non-empty, and return
an appropriate error if empty before formatting the URL, updating any error
messages to match the pattern used in Speech to avoid constructing a malformed
URL.
In `@core/schemas/account_test.go`:
- Line 257: Remove the unused variable familyAnthropic (and its blank identifier
silencing) which is assigned ModelFamilyAnthropic but never used in tests;
delete the declaration of familyAnthropic and the corresponding `_ =
familyAnthropic` lines so only the needed familyOpenAI stays in the test cases
(remove both occurrences where familyAnthropic/ModelFamilyAnthropic are
declared/silenced).
- Around line 378-379: Remove the duplicate helpers ptrStr and ptrFamily and
replace their usages with the existing Ptr helper: delete the functions ptrStr
and ptrFamily, then update all test cases that call ptrStr("...") to call
Ptr("...") instead, and change ptrFamily(x) calls to Ptr(ModelFamily(x)) (e.g.,
ptrFamily("") → Ptr(ModelFamily(""))); ensure any imports/types still compile
and run tests to confirm no pointer creation regressions.
In `@core/schemas/account.go`:
- Around line 241-247: The AliasConfig.MarshalJSON method currently calls
sonic.Marshal directly; change both sonic.Marshal calls to use the package-level
Marshal(...) wrapper so nested custom marshalers are respected. Specifically, in
AliasConfig.MarshalJSON, when ac.isLegacyShape() is true call
Marshal(ac.ModelID) and otherwise call Marshal(aliasConfigJSON(ac)); keep the
alias type aliasConfigJSON and the same return signatures but replace
sonic.Marshal with Marshal to follow core/schemas conventions.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 63d0ce67-0a35-4ad7-89f6-79310ffd7f69
📒 Files selected for processing (7)
core/bifrost.gocore/providers/azure/azure.gocore/providers/azure/azure_passthrough_test.gocore/providers/azure/utils.gocore/schemas/account.gocore/schemas/account_test.gocore/schemas/bifrost.go
71fedcc to
f407b57
Compare
c6f574f to
f172720
Compare
f407b57 to
c83f2c6
Compare
97b80bd to
8e6a6bb
Compare
c83f2c6 to
4439bc5
Compare
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
core/providers/azure/azure.go (1)
3575-3581:⚠️ Potential issue | 🟠 Major | ⚡ Quick winInject
anthropic-versionfor Azure Anthropic passthrough.These paths switch auth header shape for Anthropic families, but they never add the required
anthropic-versionheader or honor the alias-level override. Anthropic passthrough requests will still fail unless the caller remembers to send that header manually.Based on PR objectives, Anthropic version resolution is meant to be applied across Azure request headers, including alias overrides.
Also applies to: 3646-3652
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@core/providers/azure/azure.go` around lines 3575 - 3581, The auth header block calling provider.getAzureAuthHeaders(...) merges authHeaders into fasthttpReq but never injects the required "anthropic-version" header for Anthropic families; update this block so that when schemas.IsAnthropicModelFamily(ctx, req.Model) is true you resolve the Anthropic version (honoring alias-level override first, then provider/default) and set fasthttpReq.Header.Set("anthropic-version", resolvedVersion) after merging authHeaders; reuse or add a helper on provider (e.g., resolveAnthropicVersion(ctx, req) or getAnthropicVersion) that implements the alias override logic, ensure the header is only set when non-empty and that the same change is applied to the other similar block mentioned (the block around lines 3646-3652).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@core/bifrost.go`:
- Around line 6150-6156: The current alias resolution sets resolvedModel =
aliasConfig.ModelID whenever aliasConfig exists, which can blank the model if
ModelID is empty; change both the non-streaming and streaming closures that call
k.Aliases.ResolveConfig(originalModelRequested) so that resolvedModel is set to
aliasConfig.ModelID only when aliasConfig.ModelID is non-empty, otherwise leave
resolvedModel as originalModelRequested, and still call
req.Context.SetValue(schemas.BifrostContextKeyResolvedAlias,
&schemas.ResolvedAlias{Key: originalModelRequested, Config: aliasConfig}) (or
nil when no aliasConfig) to preserve alias metadata; update the same logic in
the second occurrence around lines 6215-6221 to keep behavior consistent.
In `@core/providers/azure/azure.go`:
- Around line 3758-3766: The extractAzurePassthroughUsage helper currently uses
schemas.IsAnthropicModel(model) which misclassifies opaque Azure deployment IDs;
change it to determine Anthropic routes by using resolved family info or the
request path (e.g., check for "/anthropic/" in path) instead of raw model
substrings. Update the logic in extractAzurePassthroughUsage to prefer the
resolved provider family (from alias/metadata) when available and fall back to a
path-based check, then call anthropic.ExtractAnthropicPassthroughUsage(path,
reqBody, body) for Anthropic requests and
openai.ExtractOpenAIPassthroughUsage(method, path, reqBody, body) otherwise.
Ensure the decision references the same parameters (model and path) so opaque
deployment IDs resolved via alias metadata route correctly.
- Around line 2691-2693: The code currently hardcodes AzureAPIVersionPreview for
the responses/compact route; replace that with the alias-aware resolver by
calling resolveAPIVersion(ctx, request.Model, AzureAPIVersionPreview) (or the
existing resolveAPIVersion signature used by other responses-family routes) and
use its returned value when building the path for "openai/v1/responses/compact";
ensure any error or fallback from resolveAPIVersion is handled the same way
other responses routes do before calling provider.completeRequest so alias
APIVersion overrides apply consistently.
In `@core/providers/azure/utils.go`:
- Around line 41-63: The functions resolveAnthropicVersion and resolveAPIVersion
currently treat any non-nil AzureAliasCfg.AnthropicVersion /
AzureAliasCfg.APIVersion as authoritative even when the string is empty; change
both functions to only return the override when it is non-nil AND non-empty
(e.g., check len(...) > 0 or != ""), otherwise fall back to
AzureAnthropicAPIVersionDefault (for resolveAnthropicVersion) or the provided
defaultVersion (for resolveAPIVersion); mirror the empty-check behavior used in
resolveAzureEndpoint so blank override values do not produce empty headers/query
params.
---
Outside diff comments:
In `@core/providers/azure/azure.go`:
- Around line 3575-3581: The auth header block calling
provider.getAzureAuthHeaders(...) merges authHeaders into fasthttpReq but never
injects the required "anthropic-version" header for Anthropic families; update
this block so that when schemas.IsAnthropicModelFamily(ctx, req.Model) is true
you resolve the Anthropic version (honoring alias-level override first, then
provider/default) and set fasthttpReq.Header.Set("anthropic-version",
resolvedVersion) after merging authHeaders; reuse or add a helper on provider
(e.g., resolveAnthropicVersion(ctx, req) or getAnthropicVersion) that implements
the alias override logic, ensure the header is only set when non-empty and that
the same change is applied to the other similar block mentioned (the block
around lines 3646-3652).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: e6701dd7-0f82-4e15-ad65-538b76369401
📒 Files selected for processing (7)
core/bifrost.gocore/providers/azure/azure.gocore/providers/azure/azure_passthrough_test.gocore/providers/azure/utils.gocore/schemas/account.gocore/schemas/account_test.gocore/schemas/bifrost.go
There was a problem hiding this comment.
Caution
Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
core/providers/azure/azure.go (1)
3575-3581:⚠️ Potential issue | 🟠 Major | ⚡ Quick winInject
anthropic-versionfor Azure Anthropic passthrough.These paths switch auth header shape for Anthropic families, but they never add the required
anthropic-versionheader or honor the alias-level override. Anthropic passthrough requests will still fail unless the caller remembers to send that header manually.Based on PR objectives, Anthropic version resolution is meant to be applied across Azure request headers, including alias overrides.
Also applies to: 3646-3652
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@core/providers/azure/azure.go` around lines 3575 - 3581, The auth header block calling provider.getAzureAuthHeaders(...) merges authHeaders into fasthttpReq but never injects the required "anthropic-version" header for Anthropic families; update this block so that when schemas.IsAnthropicModelFamily(ctx, req.Model) is true you resolve the Anthropic version (honoring alias-level override first, then provider/default) and set fasthttpReq.Header.Set("anthropic-version", resolvedVersion) after merging authHeaders; reuse or add a helper on provider (e.g., resolveAnthropicVersion(ctx, req) or getAnthropicVersion) that implements the alias override logic, ensure the header is only set when non-empty and that the same change is applied to the other similar block mentioned (the block around lines 3646-3652).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@core/bifrost.go`:
- Around line 6150-6156: The current alias resolution sets resolvedModel =
aliasConfig.ModelID whenever aliasConfig exists, which can blank the model if
ModelID is empty; change both the non-streaming and streaming closures that call
k.Aliases.ResolveConfig(originalModelRequested) so that resolvedModel is set to
aliasConfig.ModelID only when aliasConfig.ModelID is non-empty, otherwise leave
resolvedModel as originalModelRequested, and still call
req.Context.SetValue(schemas.BifrostContextKeyResolvedAlias,
&schemas.ResolvedAlias{Key: originalModelRequested, Config: aliasConfig}) (or
nil when no aliasConfig) to preserve alias metadata; update the same logic in
the second occurrence around lines 6215-6221 to keep behavior consistent.
In `@core/providers/azure/azure.go`:
- Around line 3758-3766: The extractAzurePassthroughUsage helper currently uses
schemas.IsAnthropicModel(model) which misclassifies opaque Azure deployment IDs;
change it to determine Anthropic routes by using resolved family info or the
request path (e.g., check for "/anthropic/" in path) instead of raw model
substrings. Update the logic in extractAzurePassthroughUsage to prefer the
resolved provider family (from alias/metadata) when available and fall back to a
path-based check, then call anthropic.ExtractAnthropicPassthroughUsage(path,
reqBody, body) for Anthropic requests and
openai.ExtractOpenAIPassthroughUsage(method, path, reqBody, body) otherwise.
Ensure the decision references the same parameters (model and path) so opaque
deployment IDs resolved via alias metadata route correctly.
- Around line 2691-2693: The code currently hardcodes AzureAPIVersionPreview for
the responses/compact route; replace that with the alias-aware resolver by
calling resolveAPIVersion(ctx, request.Model, AzureAPIVersionPreview) (or the
existing resolveAPIVersion signature used by other responses-family routes) and
use its returned value when building the path for "openai/v1/responses/compact";
ensure any error or fallback from resolveAPIVersion is handled the same way
other responses routes do before calling provider.completeRequest so alias
APIVersion overrides apply consistently.
In `@core/providers/azure/utils.go`:
- Around line 41-63: The functions resolveAnthropicVersion and resolveAPIVersion
currently treat any non-nil AzureAliasCfg.AnthropicVersion /
AzureAliasCfg.APIVersion as authoritative even when the string is empty; change
both functions to only return the override when it is non-nil AND non-empty
(e.g., check len(...) > 0 or != ""), otherwise fall back to
AzureAnthropicAPIVersionDefault (for resolveAnthropicVersion) or the provided
defaultVersion (for resolveAPIVersion); mirror the empty-check behavior used in
resolveAzureEndpoint so blank override values do not produce empty headers/query
params.
---
Outside diff comments:
In `@core/providers/azure/azure.go`:
- Around line 3575-3581: The auth header block calling
provider.getAzureAuthHeaders(...) merges authHeaders into fasthttpReq but never
injects the required "anthropic-version" header for Anthropic families; update
this block so that when schemas.IsAnthropicModelFamily(ctx, req.Model) is true
you resolve the Anthropic version (honoring alias-level override first, then
provider/default) and set fasthttpReq.Header.Set("anthropic-version",
resolvedVersion) after merging authHeaders; reuse or add a helper on provider
(e.g., resolveAnthropicVersion(ctx, req) or getAnthropicVersion) that implements
the alias override logic, ensure the header is only set when non-empty and that
the same change is applied to the other similar block mentioned (the block
around lines 3646-3652).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: e6701dd7-0f82-4e15-ad65-538b76369401
📒 Files selected for processing (7)
core/bifrost.gocore/providers/azure/azure.gocore/providers/azure/azure_passthrough_test.gocore/providers/azure/utils.gocore/schemas/account.gocore/schemas/account_test.gocore/schemas/bifrost.go
🛑 Comments failed to post (4)
core/bifrost.go (1)
6150-6156:
⚠️ Potential issue | 🟠 Major | ⚡ Quick winAvoid blanking model when alias config omits
ModelID.Line 6151 and Line 6216 assign
resolvedModelfromaliasConfig.ModelIDwhenever an alias config exists. This breaks aliases that only override endpoint/version/family and leaveModelIDempty, causing downstream provider calls with an empty model.💡 Suggested fix
- if aliasConfig := k.Aliases.ResolveConfig(originalModelRequested); aliasConfig != nil { - resolvedModel = aliasConfig.ModelID + if aliasConfig := k.Aliases.ResolveConfig(originalModelRequested); aliasConfig != nil { + resolvedModel = originalModelRequested + if aliasConfig.ModelID != "" { + resolvedModel = aliasConfig.ModelID + } req.Context.SetValue(schemas.BifrostContextKeyResolvedAlias, &schemas.ResolvedAlias{Key: originalModelRequested, Config: aliasConfig}) } else { resolvedModel = originalModelRequested req.Context.SetValue(schemas.BifrostContextKeyResolvedAlias, nil) }Apply the same adjustment in both streaming and non-streaming closures.
Also applies to: 6215-6221
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@core/bifrost.go` around lines 6150 - 6156, The current alias resolution sets resolvedModel = aliasConfig.ModelID whenever aliasConfig exists, which can blank the model if ModelID is empty; change both the non-streaming and streaming closures that call k.Aliases.ResolveConfig(originalModelRequested) so that resolvedModel is set to aliasConfig.ModelID only when aliasConfig.ModelID is non-empty, otherwise leave resolvedModel as originalModelRequested, and still call req.Context.SetValue(schemas.BifrostContextKeyResolvedAlias, &schemas.ResolvedAlias{Key: originalModelRequested, Config: aliasConfig}) (or nil when no aliasConfig) to preserve alias metadata; update the same logic in the second occurrence around lines 6215-6221 to keep behavior consistent.core/providers/azure/azure.go (2)
2691-2693:
⚠️ Potential issue | 🟠 Major | ⚡ Quick winCompaction skips the alias-aware
api-versionresolver.This path hardcodes
AzureAPIVersionPreviewwhile the other responses-family routes callresolveAPIVersion(ctx, ...). Any alias that overridesAPIVersionwill still hit/responses/compactwith the hardcoded preview value.Based on PR objectives, Azure alias
APIVersionoverrides should apply with route-specific fallbacks across Azure routes.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@core/providers/azure/azure.go` around lines 2691 - 2693, The code currently hardcodes AzureAPIVersionPreview for the responses/compact route; replace that with the alias-aware resolver by calling resolveAPIVersion(ctx, request.Model, AzureAPIVersionPreview) (or the existing resolveAPIVersion signature used by other responses-family routes) and use its returned value when building the path for "openai/v1/responses/compact"; ensure any error or fallback from resolveAPIVersion is handled the same way other responses routes do before calling provider.completeRequest so alias APIVersion overrides apply consistently.
3758-3766:
⚠️ Potential issue | 🟠 Major | ⚡ Quick winPassthrough usage extraction regresses opaque Anthropic aliases.
This helper falls back to
schemas.IsAnthropicModel(model), so opaque deployment IDs resolved through alias metadata are classified as OpenAI here. Non-stream Anthropic passthroughs will miss usage extraction and skew budgets/logging. Use resolved family information here, or at least the/anthropic/path, instead of raw model-name heuristics.Based on PR objectives, opaque Azure deployment IDs must resolve provider family from alias context rather than raw model substrings.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@core/providers/azure/azure.go` around lines 3758 - 3766, The extractAzurePassthroughUsage helper currently uses schemas.IsAnthropicModel(model) which misclassifies opaque Azure deployment IDs; change it to determine Anthropic routes by using resolved family info or the request path (e.g., check for "/anthropic/" in path) instead of raw model substrings. Update the logic in extractAzurePassthroughUsage to prefer the resolved provider family (from alias/metadata) when available and fall back to a path-based check, then call anthropic.ExtractAnthropicPassthroughUsage(path, reqBody, body) for Anthropic requests and openai.ExtractOpenAIPassthroughUsage(method, path, reqBody, body) otherwise. Ensure the decision references the same parameters (model and path) so opaque deployment IDs resolved via alias metadata route correctly.core/providers/azure/utils.go (1)
41-63:
⚠️ Potential issue | 🟠 Major | ⚡ Quick winFallback when alias version overrides are blank.
resolveAnthropicVersionandresolveAPIVersiontreat any non-nil override as authoritative, even when it is"". That turns an optional override into a broken request (anthropic-version: ""/?api-version=) instead of using the route default. MatchresolveAzureEndpointhere and only honor non-empty override values.Based on PR objectives, these alias-level fields are optional overrides with default fallbacks.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@core/providers/azure/utils.go` around lines 41 - 63, The functions resolveAnthropicVersion and resolveAPIVersion currently treat any non-nil AzureAliasCfg.AnthropicVersion / AzureAliasCfg.APIVersion as authoritative even when the string is empty; change both functions to only return the override when it is non-nil AND non-empty (e.g., check len(...) > 0 or != ""), otherwise fall back to AzureAnthropicAPIVersionDefault (for resolveAnthropicVersion) or the provided defaultVersion (for resolveAPIVersion); mirror the empty-check behavior used in resolveAzureEndpoint so blank override values do not produce empty headers/query params.
8e6a6bb to
f22ce96
Compare
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
core/providers/azure/azure.go (1)
3575-3581:⚠️ Potential issue | 🟠 Major | ⚡ Quick winAnthropic passthrough still ignores
resolveAnthropicVersion.These paths now select auth by
IsAnthropicModelFamily, but neither path adds the matchinganthropic-versionheader. For Azure-hosted Claude aliases, normal chat/responses requests use the resolved override while passthrough only works when the caller manually sends that header.Also applies to: 3646-3652
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@core/providers/azure/azure.go` around lines 3575 - 3581, Passthrough requests for Anthropic models are not adding the resolved override header; update both places where authHeaders are applied (the block using provider.getAzureAuthHeaders at getAzureAuthHeaders(...) and the similar block around lines 3646-3652) to include the resolved anthropic-version: when schemas.IsAnthropicModelFamily(ctx, req.Model) is true call provider.resolveAnthropicVersion(ctx) (or retrieve the existing resolved value), and add Header "anthropic-version" with that value to authHeaders (or directly call fasthttpReq.Header.Set("anthropic-version", resolvedVersion)) so Azure-hosted Claude aliases get the override in passthrough paths too.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@core/bifrost.go`:
- Around line 6150-6156: The current logic unconditionally assigns
aliasConfig.ModelID to resolvedModel which clears the model when an alias only
provides non-ModelID overrides; change both closures (the streaming and
non-streaming blocks that call k.Aliases.ResolveConfig) to only overwrite
resolvedModel when aliasConfig.ModelID is non-empty (e.g., check
aliasConfig.ModelID != "" before assigning); always set
req.Context.SetValue(schemas.BifrostContextKeyResolvedAlias,
&schemas.ResolvedAlias{Key: originalModelRequested, Config: aliasConfig}) (or
nil) as before, but preserve originalModelRequested in resolvedModel when
ModelID is empty so routing/provider calls keep the original model.
In `@core/providers/azure/azure.go`:
- Around line 2691-2693: The compaction request hardcodes AzureAPIVersionPreview
for the path (used in the Compaction flow) which bypasses alias-based
api_version overrides; update the code that builds the path (the variable named
path used with provider.completeRequest) to call resolveAPIVersion(ctx,
AzureAPIVersionPreview) and use the returned api version string instead of
AzureAPIVersionPreview so the /openai/v1/responses/compact path respects alias
overrides; ensure any error from resolveAPIVersion is handled consistently with
other /openai/v1/responses callers before calling provider.completeRequest.
- Around line 3599-3602: The passthrough usage extractor is not alias-aware:
change the calls in azure.go (the two spots calling extractAzurePassthroughUsage
around the success-response blocks) to pass the resolved/alias model identifier
instead of the raw req.Model (e.g., pass req.ModelResolved or the field that
contains the alias/context-resolved model), and update
extractAzurePassthroughUsage's signature/logic to use that resolved model when
deciding extractor behavior (so it no longer relies on
schemas.IsAnthropicModel(req.Model) but on the passed-in resolved/alias value);
apply this same change to both call sites (the block around resp.StatusCode() >=
200 && < 300 and the other similar block around lines ~3758-3766).
In `@core/providers/azure/utils.go`:
- Around line 45-46: The code in resolveAnthropicVersion (and similarly in
resolveAPIVersion) returns alias override strings even when they are empty;
update the checks so you only return ra.Config.AzureAliasCfg.AnthropicVersion
(and ra.Config.AzureAliasCfg.ApiVersion) when the pointer is non-nil and the
pointed-to string is non-empty (i.e., treat "" as unset), otherwise fall through
to the existing defaults; make the identical change in the ApiVersion branch
referenced around lines 59-60 so empty overrides don't produce empty
header/query values.
---
Outside diff comments:
In `@core/providers/azure/azure.go`:
- Around line 3575-3581: Passthrough requests for Anthropic models are not
adding the resolved override header; update both places where authHeaders are
applied (the block using provider.getAzureAuthHeaders at
getAzureAuthHeaders(...) and the similar block around lines 3646-3652) to
include the resolved anthropic-version: when schemas.IsAnthropicModelFamily(ctx,
req.Model) is true call provider.resolveAnthropicVersion(ctx) (or retrieve the
existing resolved value), and add Header "anthropic-version" with that value to
authHeaders (or directly call fasthttpReq.Header.Set("anthropic-version",
resolvedVersion)) so Azure-hosted Claude aliases get the override in passthrough
paths too.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 2d59912c-b33a-46ca-8112-e94fc7f6b8fb
📒 Files selected for processing (7)
core/bifrost.gocore/providers/azure/azure.gocore/providers/azure/azure_passthrough_test.gocore/providers/azure/utils.gocore/schemas/account.gocore/schemas/account_test.gocore/schemas/bifrost.go
There was a problem hiding this comment.
Caution
Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
core/providers/azure/azure.go (1)
3575-3581:⚠️ Potential issue | 🟠 Major | ⚡ Quick winAnthropic passthrough still ignores
resolveAnthropicVersion.These paths now select auth by
IsAnthropicModelFamily, but neither path adds the matchinganthropic-versionheader. For Azure-hosted Claude aliases, normal chat/responses requests use the resolved override while passthrough only works when the caller manually sends that header.Also applies to: 3646-3652
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@core/providers/azure/azure.go` around lines 3575 - 3581, Passthrough requests for Anthropic models are not adding the resolved override header; update both places where authHeaders are applied (the block using provider.getAzureAuthHeaders at getAzureAuthHeaders(...) and the similar block around lines 3646-3652) to include the resolved anthropic-version: when schemas.IsAnthropicModelFamily(ctx, req.Model) is true call provider.resolveAnthropicVersion(ctx) (or retrieve the existing resolved value), and add Header "anthropic-version" with that value to authHeaders (or directly call fasthttpReq.Header.Set("anthropic-version", resolvedVersion)) so Azure-hosted Claude aliases get the override in passthrough paths too.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@core/bifrost.go`:
- Around line 6150-6156: The current logic unconditionally assigns
aliasConfig.ModelID to resolvedModel which clears the model when an alias only
provides non-ModelID overrides; change both closures (the streaming and
non-streaming blocks that call k.Aliases.ResolveConfig) to only overwrite
resolvedModel when aliasConfig.ModelID is non-empty (e.g., check
aliasConfig.ModelID != "" before assigning); always set
req.Context.SetValue(schemas.BifrostContextKeyResolvedAlias,
&schemas.ResolvedAlias{Key: originalModelRequested, Config: aliasConfig}) (or
nil) as before, but preserve originalModelRequested in resolvedModel when
ModelID is empty so routing/provider calls keep the original model.
In `@core/providers/azure/azure.go`:
- Around line 2691-2693: The compaction request hardcodes AzureAPIVersionPreview
for the path (used in the Compaction flow) which bypasses alias-based
api_version overrides; update the code that builds the path (the variable named
path used with provider.completeRequest) to call resolveAPIVersion(ctx,
AzureAPIVersionPreview) and use the returned api version string instead of
AzureAPIVersionPreview so the /openai/v1/responses/compact path respects alias
overrides; ensure any error from resolveAPIVersion is handled consistently with
other /openai/v1/responses callers before calling provider.completeRequest.
- Around line 3599-3602: The passthrough usage extractor is not alias-aware:
change the calls in azure.go (the two spots calling extractAzurePassthroughUsage
around the success-response blocks) to pass the resolved/alias model identifier
instead of the raw req.Model (e.g., pass req.ModelResolved or the field that
contains the alias/context-resolved model), and update
extractAzurePassthroughUsage's signature/logic to use that resolved model when
deciding extractor behavior (so it no longer relies on
schemas.IsAnthropicModel(req.Model) but on the passed-in resolved/alias value);
apply this same change to both call sites (the block around resp.StatusCode() >=
200 && < 300 and the other similar block around lines ~3758-3766).
In `@core/providers/azure/utils.go`:
- Around line 45-46: The code in resolveAnthropicVersion (and similarly in
resolveAPIVersion) returns alias override strings even when they are empty;
update the checks so you only return ra.Config.AzureAliasCfg.AnthropicVersion
(and ra.Config.AzureAliasCfg.ApiVersion) when the pointer is non-nil and the
pointed-to string is non-empty (i.e., treat "" as unset), otherwise fall through
to the existing defaults; make the identical change in the ApiVersion branch
referenced around lines 59-60 so empty overrides don't produce empty
header/query values.
---
Outside diff comments:
In `@core/providers/azure/azure.go`:
- Around line 3575-3581: Passthrough requests for Anthropic models are not
adding the resolved override header; update both places where authHeaders are
applied (the block using provider.getAzureAuthHeaders at
getAzureAuthHeaders(...) and the similar block around lines 3646-3652) to
include the resolved anthropic-version: when schemas.IsAnthropicModelFamily(ctx,
req.Model) is true call provider.resolveAnthropicVersion(ctx) (or retrieve the
existing resolved value), and add Header "anthropic-version" with that value to
authHeaders (or directly call fasthttpReq.Header.Set("anthropic-version",
resolvedVersion)) so Azure-hosted Claude aliases get the override in passthrough
paths too.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 2d59912c-b33a-46ca-8112-e94fc7f6b8fb
📒 Files selected for processing (7)
core/bifrost.gocore/providers/azure/azure.gocore/providers/azure/azure_passthrough_test.gocore/providers/azure/utils.gocore/schemas/account.gocore/schemas/account_test.gocore/schemas/bifrost.go
🛑 Comments failed to post (4)
core/bifrost.go (1)
6150-6156:
⚠️ Potential issue | 🟠 Major | ⚡ Quick winPrevent empty
resolvedModelwhen alias config has overrides but noModelID.Line 6151 and Line 6216 unconditionally copy
aliasConfig.ModelID. If an alias is used only for Azure endpoint/version/family overrides and leavesModelIDempty, this clears the model and breaks routing/provider calls. Keep the original model unlessModelIDis non-empty.💡 Suggested fix
- if aliasConfig := k.Aliases.ResolveConfig(originalModelRequested); aliasConfig != nil { - resolvedModel = aliasConfig.ModelID + if aliasConfig := k.Aliases.ResolveConfig(originalModelRequested); aliasConfig != nil { + resolvedModel = originalModelRequested + if strings.TrimSpace(aliasConfig.ModelID) != "" { + resolvedModel = aliasConfig.ModelID + } req.Context.SetValue(schemas.BifrostContextKeyResolvedAlias, &schemas.ResolvedAlias{Key: originalModelRequested, Config: aliasConfig}) } else { resolvedModel = originalModelRequested req.Context.SetValue(schemas.BifrostContextKeyResolvedAlias, nil) }Apply the same change in both closures (streaming and non-streaming).
Also applies to: 6215-6221
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@core/bifrost.go` around lines 6150 - 6156, The current logic unconditionally assigns aliasConfig.ModelID to resolvedModel which clears the model when an alias only provides non-ModelID overrides; change both closures (the streaming and non-streaming blocks that call k.Aliases.ResolveConfig) to only overwrite resolvedModel when aliasConfig.ModelID is non-empty (e.g., check aliasConfig.ModelID != "" before assigning); always set req.Context.SetValue(schemas.BifrostContextKeyResolvedAlias, &schemas.ResolvedAlias{Key: originalModelRequested, Config: aliasConfig}) (or nil) as before, but preserve originalModelRequested in resolvedModel when ModelID is empty so routing/provider calls keep the original model.core/providers/azure/azure.go (2)
2691-2693:
⚠️ Potential issue | 🟠 Major | ⚡ Quick winCompaction bypasses alias
api_versionresolution.Every other
/openai/v1/responsespath in this file now goes throughresolveAPIVersion(ctx, AzureAPIVersionPreview), butCompactionhardcodesAzureAPIVersionPreview. Aliases that overrideapi_versionwill work forResponsesand passthrough, then fail on/responses/compact.♻️ Proposed fix
- path := fmt.Sprintf("openai/v1/responses/compact?api-version=%s", AzureAPIVersionPreview) + path := fmt.Sprintf("openai/v1/responses/compact?api-version=%s", resolveAPIVersion(ctx, AzureAPIVersionPreview))📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.path := fmt.Sprintf("openai/v1/responses/compact?api-version=%s", resolveAPIVersion(ctx, AzureAPIVersionPreview)) responseBody, latency, providerResponseHeaders, err := provider.completeRequest(ctx, jsonData, path, key, request.Model)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@core/providers/azure/azure.go` around lines 2691 - 2693, The compaction request hardcodes AzureAPIVersionPreview for the path (used in the Compaction flow) which bypasses alias-based api_version overrides; update the code that builds the path (the variable named path used with provider.completeRequest) to call resolveAPIVersion(ctx, AzureAPIVersionPreview) and use the returned api version string instead of AzureAPIVersionPreview so the /openai/v1/responses/compact path respects alias overrides; ensure any error from resolveAPIVersion is handled consistently with other /openai/v1/responses callers before calling provider.completeRequest.
3599-3602:
⚠️ Potential issue | 🟠 Major | ⚡ Quick winPassthrough usage extraction is not alias-aware.
extractAzurePassthroughUsagefalls back toschemas.IsAnthropicModel(model), so opaque deployment IDs still take the OpenAI extractor even when the request was already resolved as Anthropic by context. That drops usage/accounting for the exact alias-based routing this PR adds.♻️ Proposed fix
- passthroughUsage = extractAzurePassthroughUsage(req.Method, req.Path, req.Body, body, req.Model) + passthroughUsage = extractAzurePassthroughUsage(ctx, req.Method, req.Path, req.Body, body, req.Model) @@ -func extractAzurePassthroughUsage(method, path string, reqBody, body []byte, model string) *schemas.BifrostPassthroughUsage { - if schemas.IsAnthropicModel(model) { +func extractAzurePassthroughUsage(ctx *schemas.BifrostContext, method, path string, reqBody, body []byte, model string) *schemas.BifrostPassthroughUsage { + if schemas.IsAnthropicModelFamily(ctx, model) { return anthropic.ExtractAnthropicPassthroughUsage(path, reqBody, body) } return openai.ExtractOpenAIPassthroughUsage(method, path, reqBody, body) }Also applies to: 3758-3766
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@core/providers/azure/azure.go` around lines 3599 - 3602, The passthrough usage extractor is not alias-aware: change the calls in azure.go (the two spots calling extractAzurePassthroughUsage around the success-response blocks) to pass the resolved/alias model identifier instead of the raw req.Model (e.g., pass req.ModelResolved or the field that contains the alias/context-resolved model), and update extractAzurePassthroughUsage's signature/logic to use that resolved model when deciding extractor behavior (so it no longer relies on schemas.IsAnthropicModel(req.Model) but on the passed-in resolved/alias value); apply this same change to both call sites (the block around resp.StatusCode() >= 200 && < 300 and the other similar block around lines ~3758-3766).core/providers/azure/utils.go (1)
45-46:
⚠️ Potential issue | 🟠 Major | ⚡ Quick winIgnore empty alias override strings.
resolveAzureEndpointalready treats an empty alias endpoint as “unset”, butresolveAnthropicVersionandresolveAPIVersiondo not. If config decodesanthropic_version: ""orapi_version: "", Azure requests go out with an empty header/query value instead of falling back to the route default.♻️ Proposed fix
func resolveAnthropicVersion(ctx *schemas.BifrostContext) string { - if ra := schemas.GetResolvedAlias(ctx); ra != nil && ra.Config != nil && ra.Config.AzureAliasCfg != nil && ra.Config.AzureAliasCfg.AnthropicVersion != nil { + if ra := schemas.GetResolvedAlias(ctx); ra != nil && ra.Config != nil && ra.Config.AzureAliasCfg != nil && ra.Config.AzureAliasCfg.AnthropicVersion != nil && *ra.Config.AzureAliasCfg.AnthropicVersion != "" { return *ra.Config.AzureAliasCfg.AnthropicVersion } return AzureAnthropicAPIVersionDefault } @@ func resolveAPIVersion(ctx *schemas.BifrostContext, defaultVersion string) string { - if ra := schemas.GetResolvedAlias(ctx); ra != nil && ra.Config != nil && ra.Config.AzureAliasCfg != nil && ra.Config.AzureAliasCfg.APIVersion != nil { + if ra := schemas.GetResolvedAlias(ctx); ra != nil && ra.Config != nil && ra.Config.AzureAliasCfg != nil && ra.Config.AzureAliasCfg.APIVersion != nil && *ra.Config.AzureAliasCfg.APIVersion != "" { return *ra.Config.AzureAliasCfg.APIVersion } return defaultVersion }Also applies to: 59-60
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@core/providers/azure/utils.go` around lines 45 - 46, The code in resolveAnthropicVersion (and similarly in resolveAPIVersion) returns alias override strings even when they are empty; update the checks so you only return ra.Config.AzureAliasCfg.AnthropicVersion (and ra.Config.AzureAliasCfg.ApiVersion) when the pointer is non-nil and the pointed-to string is non-empty (i.e., treat "" as unset), otherwise fall through to the existing defaults; make the identical change in the ApiVersion branch referenced around lines 59-60 so empty overrides don't produce empty header/query values.
6a64d6d to
d18d03a
Compare
f22ce96 to
fcd9882
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
core/providers/azure/azure.go (1)
3599-3602:⚠️ Potential issue | 🟠 Major | ⚡ Quick winPassthrough usage extraction still ignores the resolved Anthropic family.
The request/auth path is family-aware now, but non-streaming usage extraction still branches on
schemas.IsAnthropicModel(model). Opaque Anthropic deployments will therefore route correctly yet have 2xx passthrough usage parsed as OpenAI, which drops Anthropic usage/budget metadata.Suggested fix
- passthroughUsage = extractAzurePassthroughUsage(req.Method, req.Path, req.Body, body, req.Model) + passthroughUsage = extractAzurePassthroughUsage( + schemas.IsAnthropicModelFamily(ctx, req.Model), + req.Method, + req.Path, + req.Body, + body, + )-func extractAzurePassthroughUsage(method, path string, reqBody, body []byte, model string) *schemas.BifrostPassthroughUsage { - if schemas.IsAnthropicModel(model) { +func extractAzurePassthroughUsage(isAnthropic bool, method, path string, reqBody, body []byte) *schemas.BifrostPassthroughUsage { + if isAnthropic { return anthropic.ExtractAnthropicPassthroughUsage(path, reqBody, body) } return openai.ExtractOpenAIPassthroughUsage(method, path, reqBody, body) }Also applies to: 3688-3691, 3762-3766
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@core/providers/azure/azure.go` around lines 3599 - 3602, The passthrough usage extraction currently calls extractAzurePassthroughUsage based on schemas.IsAnthropicModel(req.Model) which ignores resolved Anthropic family and causes Anthropic deployments to be parsed as OpenAI; update the branching logic used where passthroughUsage is set (the blocks that call extractAzurePassthroughUsage) to use the resolved model family instead (e.g., check the model's family or a helper like IsAnthropicFamily/req.Model.Family == "anthropic") so that Anthropic-family deployments are routed to the Anthropic usage parser; apply the same change to the other equivalent sites that set passthroughUsage to ensure Anthropic usage/budget metadata is preserved.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@core/bifrost.go`:
- Around line 6150-6156: The code currently overwrites resolvedModel with
aliasConfig.ModelID even when aliasConfig.ModelID is empty, causing req.Model to
become "" and breaking provider routing; change the logic in the block that
calls k.Aliases.ResolveConfig (and the similar block around lines 6215-6221) to
only set resolvedModel = aliasConfig.ModelID and store the ResolvedAlias in
req.Context when aliasConfig.ModelID is non-empty, otherwise keep resolvedModel
= originalModelRequested and set the context value to nil; reference
k.Aliases.ResolveConfig, aliasConfig.ModelID, resolvedModel,
originalModelRequested, req.Context.SetValue,
schemas.BifrostContextKeyResolvedAlias and schemas.ResolvedAlias when making the
conditional fix.
In `@core/providers/azure/azure.go`:
- Around line 2745-2746: The current guard rejects alias-only Azure keys because
it requires key.AzureConfig to be non-nil even when resolveAzureEndpoint(ctx,
key) returns a valid endpoint; change each check that reads "if
key.AzureKeyConfig == nil || resolveAzureEndpoint(ctx, key) == "" { ... }" to
only error when resolveAzureEndpoint(ctx, key) is empty (i.e., if
resolveAzureEndpoint(ctx, key) == "" { return
providerUtils.NewConfigurationError("endpoint not set") }), and keep separate,
appropriate authentication validation elsewhere; update all similar occurrences
that use key.AzureKeyConfig and resolveAzureEndpoint (including the other listed
spots) so alias-resolved endpoints are accepted even if AzureKeyConfig is nil.
- Line 318: The code builds request URIs by concatenating
resolveAzureEndpoint(ctx, key) with providerUtils.GetPathFromContext(..) even
when resolveAzureEndpoint returns "", causing opaque network errors; update each
call site (e.g., the req.SetRequestURI call around resolveAzureEndpoint(ctx,
key) + providerUtils.GetPathFromContext(ctx, "/openai/v1/models") and the other
similar sites listed) to first call resolveAzureEndpoint(ctx, key), check for an
empty result, and return the same configuration error path used in
completeRequest (an explicit "endpoint not set" config error) before attempting
to build or set the request URI. Ensure you reference resolveAzureEndpoint,
providerUtils.GetPathFromContext, and completeRequest when making the change so
every flow fails fast with a clear configuration error instead of constructing
an endpoint-less URL.
---
Outside diff comments:
In `@core/providers/azure/azure.go`:
- Around line 3599-3602: The passthrough usage extraction currently calls
extractAzurePassthroughUsage based on schemas.IsAnthropicModel(req.Model) which
ignores resolved Anthropic family and causes Anthropic deployments to be parsed
as OpenAI; update the branching logic used where passthroughUsage is set (the
blocks that call extractAzurePassthroughUsage) to use the resolved model family
instead (e.g., check the model's family or a helper like
IsAnthropicFamily/req.Model.Family == "anthropic") so that Anthropic-family
deployments are routed to the Anthropic usage parser; apply the same change to
the other equivalent sites that set passthroughUsage to ensure Anthropic
usage/budget metadata is preserved.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 9e7e294c-1367-4ead-aebd-d61a5cfbcc6d
📒 Files selected for processing (7)
core/bifrost.gocore/providers/azure/azure.gocore/providers/azure/azure_passthrough_test.gocore/providers/azure/utils.gocore/schemas/account.gocore/schemas/account_test.gocore/schemas/bifrost.go
d18d03a to
e82bb5b
Compare
fcd9882 to
ad191cb
Compare
e82bb5b to
cc297cb
Compare
ad191cb to
c34eafa
Compare
c34eafa to
e033c73
Compare
Merge activity
|

Summary
Introduces per-alias overrides for Azure-specific configuration fields (
Endpoint,APIVersion,AnthropicVersion) and a context-aware model family resolution system. This allows a single Azure credential to span deployments hosted on multiple Azure resources, and ensures that opaque Azure deployment IDs (which carry no model-name signal) are correctly routed to the right provider path (e.g. Anthropic vs. OpenAI) based on the alias name or explicit family declaration.Changes
ResolvedAliasstruct andBifrostContextKeyResolvedAliascontext key;bifrost.gonow stashes the matchedAliasConfig(and the user-facing alias key) into the request context after alias resolution for both streaming and non-streaming paths.ResolveFamily,IsAnthropicModelFamily, andGetResolvedAliashelpers inschemas/account.go.ResolveFamilywalks a four-tier precedence: explicitModelFamilyfield →ModelNamesubstring →ModelIDsubstring → alias key substring → fallback torequest.Modelsubstring. This fixes the case where an alias likebest-claudemaps to an opaque Azure deployment ID that contains noclaudesubstring.key.AzureKeyConfig.Endpoint.GetValue()calls in the Azure provider withresolveAzureEndpoint(ctx, key), which checks for a per-aliasAzureAliasCfg.Endpointoverride before falling back to the key-level endpoint.resolveAPIVersion(ctx, defaultVersion)andresolveAnthropicVersion(ctx)helpers that readAzureAliasCfg.APIVersionandAzureAliasCfg.AnthropicVersionoverrides from the resolved alias, falling back to route-specific defaults when absent.schemas.IsAnthropicModel(model)call sites in the Azure provider withschemas.IsAnthropicModelFamily(ctx, model)orschemas.ResolveFamily(ctx, model) == schemas.ModelFamilyAnthropicso family detection is alias-aware.buildContainerURLandbuildPassthroughURLnow accept*BifrostContextso alias-level endpoint and API version overrides are honored for container and passthrough routes.KeyAliasesJSON marshal/unmarshal andAliasConfig.MarshalJSONfromencoding/jsontosonicfor consistency with the rest of the codebase.Type of change
Affected areas
How to test
Key scenarios to validate:
best-claudemapping to an opaque Azure deployment ID routes to the Anthropic path (Anthropic URL,anthropic-versionheader, Anthropic request/response shape).azure_alias_cfg.endpointset routes all requests for that alias to the override endpoint rather than the key-level endpoint.azure_alias_cfg.api_versionset uses that version in theapi-versionquery parameter; a caller-suppliedapi-versioninrawQuerystill wins.azure_alias_cfg.anthropic_versionset uses that value for theanthropic-versionheader.request.Model).Breaking changes
Related issues
Security considerations
Per-alias endpoint overrides are resolved from
EnvVar, which supports environment variable indirection — secrets are not inlined in config. No new authentication surface is introduced.Checklist
docs/contributing/README.mdand followed the guidelinesSummary by CodeRabbit
New Features
Tests