Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughPrefer provider-root (no-region) mappings when selecting candidates, exclude fallback candidates by providerId only, add an optional includeProviderScoreRegions flag to omit regions from routing metadata, and only append :region to usedModel for direct-provider-specified selections. ChangesProvider selection & Gateway routing
Sequence Diagram(s)sequenceDiagram
participant Client as Client
participant Gateway as Gateway (chat.ts)
participant Selector as ProviderSelector (get-cheapest...)
participant Provider as ProviderPool
Client->>Gateway: Send generation request
Gateway->>Selector: Build candidates (preferProviderRootMappings) and call getCheapest(..., includeProviderScoreRegions: false)
Selector->>Provider: Request provider entries and scores
Provider-->>Selector: Return provider entries (root + regional variants)
Selector-->>Gateway: Return chosen provider + routingMetadata (providerScores with region omitted or present)
Gateway-->>Client: Route request to chosen provider
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a5ff8d0ea5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| } | ||
|
|
||
| if (routingMetadata) { | ||
| routingMetadata = normalizeRoutingMetadataForLogging(routingMetadata); |
There was a problem hiding this comment.
Normalize metadata only after fallback selection
This mutates routingMetadata.providerScores before the retry loop, but selectNextProvider later matches scores to model mappings using both provider and region (p.providerId === score.providerId && p.region === score.region in apps/gateway/src/chat/tools/retry-with-fallback.ts). For price-only-no-metrics, normalizeRoutingMetadataForLogging drops region for single-row providers, so any provider whose mapping has a concrete region (e.g. alibaba/singapore) can no longer be selected on retry, causing fallback to stop early and potentially fail requests that previously would have retried successfully.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Pull request overview
Adds a small normalization step to routing metadata specifically for logging, so “price-only-no-metrics” score tables don’t misleadingly show a single implicit region (while still preserving region labels when multiple regional rows are compared).
Changes:
- Introduce
normalizeRoutingMetadataForLogging()to hideregionon providerScores when a provider only has a single score row underprice-only-no-metrics. - Apply the normalization to
routingMetadatainchat.tsbefore it’s used for log entry creation. - Add a focused Vitest unit regression suite covering the normalization behavior.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| apps/gateway/src/chat/tools/normalize-routing-metadata.ts | Adds routing-metadata normalization logic for log output under price-only-no-metrics. |
| apps/gateway/src/chat/tools/normalize-routing-metadata.spec.ts | Adds unit tests verifying collapsed-region hiding and multi-region preservation. |
| apps/gateway/src/chat/chat.ts | Normalizes routing metadata before it’s passed into log entry creation paths. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| (score) => score.providerId === "alibaba", | ||
| ); | ||
|
|
||
| expect(alibabaScore?.region).toBeUndefined(); |
There was a problem hiding this comment.
This assertion can pass even if the provider score isn't found (e.g., if providerScores doesn’t contain an alibaba entry), because alibabaScore?.region will be undefined in that case. Add an explicit expectation that alibabaScore is defined (or use find(...)!) so the test actually validates the intended behavior.
| expect(alibabaScore?.region).toBeUndefined(); | |
| expect(alibabaScore).toBeDefined(); | |
| expect(alibabaScore!.region).toBeUndefined(); |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/gateway/src/chat/chat.ts`:
- Around line 1849-1851: The code overwrites runtime routing state by
reassigning routingMetadata with normalizeRoutingMetadataForLogging, which can
strip providerScores[*].region and break retry/region-failure dedupe; instead,
preserve the original routingMetadata and assign the normalized result to a
separate variable (e.g., routingMetadataForLogging) or pass a shallow/deep clone
into normalizeRoutingMetadataForLogging so retry selection logic still sees the
full providerScores with region; update places that log to use the new
logging-only variable and leave routingMetadata untouched for
retry/provider-region logic.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 3d085e2e-264c-4c8d-b3b1-6538d206c335
📒 Files selected for processing (3)
apps/gateway/src/chat/chat.tsapps/gateway/src/chat/tools/normalize-routing-metadata.spec.tsapps/gateway/src/chat/tools/normalize-routing-metadata.ts
| if (routingMetadata) { | ||
| routingMetadata = normalizeRoutingMetadataForLogging(routingMetadata); | ||
| } |
There was a problem hiding this comment.
Do not overwrite runtime routing state with logging-only normalization.
Reassigning routingMetadata here can remove providerScores[*].region before retry selection runs, which may break provider-region failure deduping and cause fallback to re-pick failed targets.
💡 Safer direction
-if (routingMetadata) {
- routingMetadata = normalizeRoutingMetadataForLogging(routingMetadata);
-}
+// Keep `routingMetadata` intact for retry/fallback logic.
+// Normalize only at log emission boundaries (e.g. inside `createLogEntry`
+// or immediately before passing metadata to it).🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/gateway/src/chat/chat.ts` around lines 1849 - 1851, The code overwrites
runtime routing state by reassigning routingMetadata with
normalizeRoutingMetadataForLogging, which can strip providerScores[*].region and
break retry/region-failure dedupe; instead, preserve the original
routingMetadata and assign the normalized result to a separate variable (e.g.,
routingMetadataForLogging) or pass a shallow/deep clone into
normalizeRoutingMetadataForLogging so retry selection logic still sees the full
providerScores with region; update places that log to use the new logging-only
variable and leave routingMetadata untouched for retry/provider-region logic.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/gateway/src/chat/chat.ts`:
- Around line 1827-1829: The current predicate sets includeProviderScoreRegions
whenever selectionReason === "direct-provider-specified", which leaks a single
implicit region; change the condition to only enable provider region emission
when there was an explicit region selection or there is an actual multi-region
comparison (e.g. selectionReason === "direct-provider-specified" &&
providerScoreRegions?.length > 1 OR an explicit-region flag is true). Update the
boolean expressions where includeProviderScoreRegions is computed (the instance
using selectionReason === "direct-provider-specified" and the other two
occurrences referenced in the comment) to check for explicit selection or
providerScoreRegions.length > 1 so single implicit rows no longer emit region
metadata.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 646f37a2-fc8a-4b6e-9bbc-0d778b5131ac
📒 Files selected for processing (4)
apps/gateway/src/chat/chat.tsapps/gateway/src/fallback.spec.tspackages/actions/src/get-cheapest-from-available-providers.tspackages/actions/src/models.spec.ts
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0711e8629e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| { | ||
| metricsMap, | ||
| isStreaming: stream, | ||
| includeProviderScoreRegions: false, |
There was a problem hiding this comment.
Preserve region in provider scores used for retries
Passing includeProviderScoreRegions: false here strips region data from routingMetadata.providerScores before the retry loop runs. In selectNextProvider (apps/gateway/src/chat/tools/retry-with-fallback.ts), the next mapping is resolved with p.providerId === score.providerId && p.region === score.region; when the chosen mappings are regional (for example alibaba with cn-beijing), score.region becomes undefined, no mapping matches, and fallback retries stop after the first retryable failure even when alternative providers exist.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2bc1bf05aa
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| // Filter model providers to only those eligible for this request | ||
| const availableModelProviders = filterEligibleModelProviders( | ||
| preferConcreteRegionalMappings(expandedIamFilteredModelProviders), | ||
| preferProviderRootMappings(expandedIamFilteredModelProviders), |
There was a problem hiding this comment.
Preserve regional rows when applying provider locks
Passing preferProviderRootMappings(expandedIamFilteredModelProviders) into filterEligibleModelProviders removes concrete region mappings before routing in the API-key/hybrid path, which makes providerLockedRegions effectively inert because that lock check only applies when provider.region is present. As a result, scoring and eligibility checks can run against the synthetic root row instead of the user’s locked region (e.g., cn-beijing), so routing decisions and pricing/capability filtering are based on the wrong region until execution-time token resolution.
Useful? React with 👍 / 👎.
| const providerIds = modelInfo.providers | ||
| .filter( | ||
| (p) => !(p.providerId === usedProvider && p.region === usedRegion), | ||
| ) // Exclude the exact low-uptime provider+region pair | ||
| .filter((p) => p.providerId !== usedProvider) | ||
| .map((p) => p.providerId); |
There was a problem hiding this comment.
Exclude only the failed provider-region in uptime fallback
This change drops all mappings for usedProvider during low-uptime rerouting, rather than excluding only the failing provider+region pair. In a model that has multiple regions for one provider, a low-uptime region can no longer fail over to a healthier region of the same provider, and if no other providers exist this path now silently skips fallback even though a viable regional alternative is available.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/gateway/src/chat/chat.ts (1)
1627-1638:⚠️ Potential issue | 🟠 MajorDon't collapse away provider-key region locks.
This block just built
providerLockedRegions, butpreferProviderRootMappings(...)runs first and drops the locked regional row whenever that provider also has a root mapping. The router can then score the provider on its root/default mapping and later execute against the DB-locked region, so price/uptime/capability selection can be wrong. Apply the root-mapping collapse only to providers that are not present inproviderLockedRegions.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/gateway/src/chat/chat.ts` around lines 1627 - 1638, The call to preferProviderRootMappings(expandedIamFilteredModelProviders) collapses provider root mappings and unintentionally drops providerLockedRegions entries when a provider has a root mapping; update the logic so you only apply preferProviderRootMappings to providers that are not present in providerLockedRegions (i.e., compute a filteredProviders = expandedIamFilteredModelProviders.filter(p => !providerLockedRegions.has(p.providerKey) or equivalent), pass that filtered list into preferProviderRootMappings, and then merge its results with the original providerLockedRegions so locked regional rows are preserved during scoring and selection (ensure you reference preferProviderRootMappings, expandedIamFilteredModelProviders, and providerLockedRegions in the change).
♻️ Duplicate comments (1)
apps/gateway/src/chat/chat.ts (1)
1822-1823:⚠️ Potential issue | 🟠 MajorDon't treat every direct-provider request as an explicit region choice.
Using
selectionReason === "direct-provider-specified"as the gate still emitsproviderScores[*].regionand appends:regiontousedModelFormattedwhen the flow resolved to a single implicit/default row. That recreates the leak this PR is trying to remove. Base the emitted-region flag ondirectProviderRegionWasExplicit || routingMetadataProviders.length > 1(or equivalent “actual multi-region comparison” logic) and reuse that same flag for the score rows and formatted used model. If retries still need raw region data internally, keep it in the pre-normalized state and only apply this gate to the emitted/logged copy.Also applies to: 1847-1857, 1929-1935, 2389-2394
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/gateway/src/chat/chat.ts` around lines 1822 - 1823, The emitted-region gating currently uses selectionReason === "direct-provider-specified", which still leaks region when the choice was implicit; change the logic that sets includeProviderScoreRegions (and any places that append :region to usedModelFormatted or emit providerScores[*].region) to use a new boolean computed from the actual multi-region condition (e.g., directProviderRegionWasExplicit || routingMetadataProviders.length > 1) and reuse that same flag for both score rows and the formatted usedModel string; keep raw region info available internally (pre-normalized) for retries but only attach region to emitted/logged copies when the new flag is true, and apply this change consistently to the other occurrences around the includeProviderScoreRegions usage and usedModelFormatted construction.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@apps/gateway/src/chat/chat.ts`:
- Around line 1627-1638: The call to
preferProviderRootMappings(expandedIamFilteredModelProviders) collapses provider
root mappings and unintentionally drops providerLockedRegions entries when a
provider has a root mapping; update the logic so you only apply
preferProviderRootMappings to providers that are not present in
providerLockedRegions (i.e., compute a filteredProviders =
expandedIamFilteredModelProviders.filter(p =>
!providerLockedRegions.has(p.providerKey) or equivalent), pass that filtered
list into preferProviderRootMappings, and then merge its results with the
original providerLockedRegions so locked regional rows are preserved during
scoring and selection (ensure you reference preferProviderRootMappings,
expandedIamFilteredModelProviders, and providerLockedRegions in the change).
---
Duplicate comments:
In `@apps/gateway/src/chat/chat.ts`:
- Around line 1822-1823: The emitted-region gating currently uses
selectionReason === "direct-provider-specified", which still leaks region when
the choice was implicit; change the logic that sets includeProviderScoreRegions
(and any places that append :region to usedModelFormatted or emit
providerScores[*].region) to use a new boolean computed from the actual
multi-region condition (e.g., directProviderRegionWasExplicit ||
routingMetadataProviders.length > 1) and reuse that same flag for both score
rows and the formatted usedModel string; keep raw region info available
internally (pre-normalized) for retries but only attach region to emitted/logged
copies when the new flag is true, and apply this change consistently to the
other occurrences around the includeProviderScoreRegions usage and
usedModelFormatted construction.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 65472ee1-bbc2-41c7-a961-c46aeeefee34
📒 Files selected for processing (2)
apps/gateway/src/chat/chat.tsapps/gateway/src/fallback.spec.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/gateway/src/fallback.spec.ts
2bc1bf0 to
6141a4e
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6141a4ed4d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| return providers.filter( | ||
| (mapping) => | ||
| !providersWithRegions.has(mapping.providerId) || Boolean(mapping.region), | ||
| !providersWithRootMappings.has(mapping.providerId) || !mapping.region, | ||
| ); |
There was a problem hiding this comment.
Preserve concrete mapping before resolving key region
This filter now drops concrete regional rows whenever a provider has a root row, so routing selects a root modelName (no :region) even for regional providers. In API-key/hybrid mode, usedRegion is later populated from the provider key, but downstream validation still matches mappings by exact (providerId, modelName, region) (e.g. finalModelInfo.providers.find(...) used for max token and supported-parameter checks), which no longer matches and silently skips those guards. For regional providers like Alibaba, this can let invalid max_tokens/unsupported params through to upstream instead of being rejected by the gateway.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/gateway/src/chat/chat.ts`:
- Around line 1477-1489: Root-mapping is currently applied before eligibility
filtering which lets providers with locked regions be returned with region
undefined; fix by ensuring region-locks are enforced before/while root-mapping:
either call filterEligibleModelProviders on expandedIamFilteredModelProviders
(and related calls at the other sites) before preferProviderRootMappings, or
modify preferProviderRootMappings to preserve/propagate any explicit region
property from provider keys so that filterEligibleModelProviders still rejects
mismatched regions; update the call sites using filterEligibleModelProviders and
preferProviderRootMappings (referencing expandedIamFilteredModelProviders,
modelInfo.providers, availableProviders, response_format, hasImages, max_tokens,
reasoning_effort) accordingly so region locks cannot be bypassed.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: a5a05fbc-93f1-4b46-85c9-c9e54a4cc105
📒 Files selected for processing (4)
apps/gateway/src/chat/chat.tsapps/gateway/src/fallback.spec.tspackages/actions/src/get-cheapest-from-available-providers.tspackages/actions/src/models.spec.ts
✅ Files skipped from review due to trivial changes (1)
- packages/actions/src/models.spec.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/gateway/src/fallback.spec.ts
| const availableModelProviders = filterEligibleModelProviders( | ||
| preferProviderRootMappings(expandedIamFilteredModelProviders), | ||
| { | ||
| allProviderVariants: modelInfo.providers, | ||
| availableProviders, | ||
| webSearchTool, | ||
| responseFormatType: response_format?.type, | ||
| hasImages, | ||
| maxTokens: max_tokens, | ||
| reasoningEffort: reasoning_effort, | ||
| }, | ||
| ).filter((provider) => provider.providerId !== usedProvider); | ||
|
|
There was a problem hiding this comment.
Provider-key region locks can be bypassed after root-mapping preference.
At Line 1781 (and similarly at Line 1478 and Line 1624), root mappings are preferred before eligibility filtering. Since filterEligibleModelProviders only rejects mismatched non-empty regions, a locked provider can still pass with region: undefined, which weakens explicit region pinning from provider keys.
💡 Suggested fix
diff --git a/apps/gateway/src/chat/chat.ts b/apps/gateway/src/chat/chat.ts
@@
const lockedRegion = options.providerLockedRegions?.get(
provider.providerId,
);
- if (lockedRegion && provider.region && provider.region !== lockedRegion) {
- return false;
- }
+ if (lockedRegion) {
+ // Enforce explicit provider-key region pin.
+ if (!provider.region || provider.region !== lockedRegion) {
+ return false;
+ }
+ }Also applies to: 1624-1634, 1781-1791
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/gateway/src/chat/chat.ts` around lines 1477 - 1489, Root-mapping is
currently applied before eligibility filtering which lets providers with locked
regions be returned with region undefined; fix by ensuring region-locks are
enforced before/while root-mapping: either call filterEligibleModelProviders on
expandedIamFilteredModelProviders (and related calls at the other sites) before
preferProviderRootMappings, or modify preferProviderRootMappings to
preserve/propagate any explicit region property from provider keys so that
filterEligibleModelProviders still rejects mismatched regions; update the call
sites using filterEligibleModelProviders and preferProviderRootMappings
(referencing expandedIamFilteredModelProviders, modelInfo.providers,
availableProviders, response_format, hasImages, max_tokens, reasoning_effort)
accordingly so region locks cannot be bypassed.
Resolved conflicts in chat.ts and get-cheapest-from-available-providers.ts by combining includeProviderScoreRegions (PR) with promptTokens and addContentFilterRoutingMetadata from main. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Resolved merge conflicts with origin/main. Conflicts in 2 files:
TypeScript compiles cleanly and all 95 unit tests pass. |
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (2)
apps/gateway/src/chat/chat.ts (2)
2460-2471:⚠️ Potential issue | 🟠 Major | ⚡ Quick winApply region locks before collapsing to provider-root mappings.
With a provider-key region pin, collapsing to
preferProviderRootMappings(...)here can leave only the root row, and the current lock check still acceptsregion: undefined. That means routing can ignore the pinned region’s price/metrics and even succeed when the locked region has no matching mapping.💡 Possible fix
- const availableModelProviders = filterEligibleModelProviders( - preferProviderRootMappings(expandedIamFilteredModelProviders), + const eligibleExpandedProviders = filterEligibleModelProviders( + expandedIamFilteredModelProviders, { allProviderVariants: modelInfo.providers, availableProviders, providerLockedRegions, webSearchTool, responseFormatType: response_format?.type, hasImages, maxTokens: max_tokens, reasoningEffort: reasoning_effort, }, ); + const availableModelProviders = preferProviderRootMappings( + eligibleExpandedProviders, + );🤖 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 `@apps/gateway/src/chat/chat.ts` around lines 2460 - 2471, The collapse to provider-root mappings via preferProviderRootMappings is happening before region lock checks, allowing region: undefined rows to pass; move the region-lock filtering to run against the full expanded provider list (expandedIamFilteredModelProviders) before calling preferProviderRootMappings, or alternatively apply providerLockedRegions filtering inside preferProviderRootMappings so that region-pinned provider keys are honored; update the call site around filterEligibleModelProviders/ preferProviderRootMappings so providerLockedRegions (and any region pin logic) filter out entries with mismatched regions prior to collapsing to root mappings.
2718-2773:⚠️ Potential issue | 🟠 Major | ⚡ Quick winSingle-row direct-provider scores still leak implicit regions.
includeProviderScoreRegionsandincludeRoutingScoreRegionsare still keyed only offselectionReason === "direct-provider-specified". After credits/hybrid filtering or capability filtering leaves one effective regional row,providerScores[*].regionexposes the implicit/default region again.💡 Possible fix
+ const regionalScoreRowCount = routingMetadataProviders.filter( + (provider) => Boolean(provider.region), + ).length; + const includeRoutingScoreRegions = + directProviderRegionWasExplicit || regionalScoreRowCount > 1; + const weightedScores = selectionReason === "direct-provider-specified" && directProviderRegionWasExplicit ? null : getCheapestFromAvailableProviders( routingMetadataProviders, modelInfo as ModelDefinition & { id: string; output?: string[]; }, { metricsMap, isStreaming: stream, - includeProviderScoreRegions: - selectionReason === "direct-provider-specified", + includeProviderScoreRegions: includeRoutingScoreRegions, promptTokens: routingPromptTokens, }, ); @@ - const includeRoutingScoreRegions = - selectionReason === "direct-provider-specified"; - routingMetadata = addContentFilterRoutingMetadata( { availableProviders: routingMetadataProviders.map((p) => p.providerId),🤖 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 `@apps/gateway/src/chat/chat.ts` around lines 2718 - 2773, The provider score regions leak because both includeProviderScoreRegions (passed into getCheapestFromAvailableProviders) and includeRoutingScoreRegions are only checking selectionReason === "direct-provider-specified" and not whether the region was actually explicit; change both checks to require directProviderRegionWasExplicit as well (i.e., selectionReason === "direct-provider-specified" && directProviderRegionWasExplicit), update the call site that passes includeProviderScoreRegions into getCheapestFromAvailableProviders and the local includeRoutingScoreRegions used when mapping providerScores so implicit/default regions are suppressed unless the region was explicitly specified.
🤖 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 `@apps/gateway/src/chat/chat.ts`:
- Around line 2850-2856: The formatted model string is including a region even
when that region was inferred; change the includeUsedModelRegion condition so it
is true only when the selection was explicitly provider-specified and the region
itself is explicitly set (not inferred). Concretely, update
includeUsedModelRegion to check both routingMetadata?.selectionReason ===
"direct-provider-specified" and a flag/property indicating the region was
explicit (e.g., routingMetadata?.regionIsExplicit or an equivalent boolean you
add when populating usedRegion), then use that boolean when calling
formatUsedModelForDisplay (same change also at the second occurrence around
usedModelFormatted at the other location).
---
Duplicate comments:
In `@apps/gateway/src/chat/chat.ts`:
- Around line 2460-2471: The collapse to provider-root mappings via
preferProviderRootMappings is happening before region lock checks, allowing
region: undefined rows to pass; move the region-lock filtering to run against
the full expanded provider list (expandedIamFilteredModelProviders) before
calling preferProviderRootMappings, or alternatively apply providerLockedRegions
filtering inside preferProviderRootMappings so that region-pinned provider keys
are honored; update the call site around filterEligibleModelProviders/
preferProviderRootMappings so providerLockedRegions (and any region pin logic)
filter out entries with mismatched regions prior to collapsing to root mappings.
- Around line 2718-2773: The provider score regions leak because both
includeProviderScoreRegions (passed into getCheapestFromAvailableProviders) and
includeRoutingScoreRegions are only checking selectionReason ===
"direct-provider-specified" and not whether the region was actually explicit;
change both checks to require directProviderRegionWasExplicit as well (i.e.,
selectionReason === "direct-provider-specified" &&
directProviderRegionWasExplicit), update the call site that passes
includeProviderScoreRegions into getCheapestFromAvailableProviders and the local
includeRoutingScoreRegions used when mapping providerScores so implicit/default
regions are suppressed unless the region was explicitly specified.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: e09dc792-7667-4343-adfb-6989a88d00b8
📒 Files selected for processing (2)
apps/gateway/src/chat/chat.tsapps/gateway/src/fallback.spec.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/gateway/src/fallback.spec.ts
| const includeUsedModelRegion = | ||
| routingMetadata?.selectionReason === "direct-provider-specified"; | ||
| let usedModelFormatted = formatUsedModelForDisplay( | ||
| usedProvider, | ||
| usedRegion ? `${baseModelName}:${usedRegion}` : baseModelName, | ||
| includeUsedModelRegion && usedRegion | ||
| ? `${baseModelName}:${usedRegion}` | ||
| : baseModelName, |
There was a problem hiding this comment.
Keep usedModelFormatted regionless when the region was inferred.
This boolean now follows direct-provider-specified alone, so once usedRegion is filled from a default/implicit region, logs still show model:region. That reintroduces the hidden-region leak even if providerScores get normalized.
💡 Possible fix
- const includeUsedModelRegion =
- routingMetadata?.selectionReason === "direct-provider-specified";
+ const includeUsedModelRegion =
+ routingMetadata?.selectionReason === "direct-provider-specified" &&
+ routingMetadata.providerScores.some(
+ (score) => score.providerId === usedProvider && Boolean(score.region),
+ );Also applies to: 3397-3402
🤖 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 `@apps/gateway/src/chat/chat.ts` around lines 2850 - 2856, The formatted model
string is including a region even when that region was inferred; change the
includeUsedModelRegion condition so it is true only when the selection was
explicitly provider-specified and the region itself is explicitly set (not
inferred). Concretely, update includeUsedModelRegion to check both
routingMetadata?.selectionReason === "direct-provider-specified" and a
flag/property indicating the region was explicit (e.g.,
routingMetadata?.regionIsExplicit or an equivalent boolean you add when
populating usedRegion), then use that boolean when calling
formatUsedModelForDisplay (same change also at the second occurrence around
usedModelFormatted at the other location).
Summary
Verification
Notes
Summary by CodeRabbit
New Features
Behavior Changes
Tests