Skip to content

feat: add RoutingInfo to response/error extra fields with fallback and key alias signals - #4020

Merged
akshaydeo merged 1 commit into
devfrom
06-03-feat_adds_routinginfo_in_respose_error_extra_fields
Jun 9, 2026
Merged

feat: add RoutingInfo to response/error extra fields with fallback and key alias signals#4020
akshaydeo merged 1 commit into
devfrom
06-03-feat_adds_routinginfo_in_respose_error_extra_fields

Conversation

@Pratham-Mishra04

@Pratham-Mishra04 Pratham-Mishra04 commented Jun 3, 2026

Copy link
Copy Markdown
Collaborator

Summary

Introduces a structured RoutingInfo field on both BifrostResponseExtraFields and BifrostErrorExtraFields that exposes per-attempt routing details (provider, model, key name, resolved key alias) alongside fallback signals (IsFallback, PrimaryProvider, PrimaryModel). Previously, callers had no way to determine which provider/model actually handled a request after fallback resolution, or whether a response came from a fallback path at all.

Changes

  • Added RoutingInfo and ResolvedKeyAlias schema types capturing the provider, model, key name, resolved alias metadata, fallback flag, and primary provider/model for fallback attempts.
  • Added BuildRoutingInfo helper on BifrostContext that constructs per-attempt RoutingInfo from the chosen provider, model, key, and resolved alias stashed in context.
  • Added PopulateRoutingInfo methods on BifrostResponse and BifrostError to stamp RoutingInfo onto responses and errors at the same call sites as PopulateExtraFields.
  • Added SetFallbackRoutingInfo methods on BifrostResponse and BifrostError, called by the orchestrator (handleRequest / handleStreamRequest) after a fallback attempt succeeds or fails, to layer on IsFallback, PrimaryProvider, and PrimaryModel. These signals belong to the orchestrator scope and are intentionally not set by per-attempt code.
  • For streaming, RoutingInfo is snapshotted per-attempt into a local variable (perAttemptRoutingInfo) before the async postHookRunner closure captures it, preventing a later retry's routing info from bleeding into an earlier attempt's chunks.
  • Added RoutingInfo field to ProcessedStreamResponse to carry routing context through the streaming pipeline.
  • Deprecated the flat Provider, OriginalModelRequested, and ResolvedModelUsed fields on both extra-fields structs in favor of RoutingInfo, while keeping them populated for backward compatibility.

Type of change

  • Bug fix
  • Feature
  • Refactor
  • Documentation
  • Chore/CI

Affected areas

  • Core (Go)
  • Transports (HTTP)
  • Providers/Integrations
  • Plugins
  • UI (React)
  • Docs

How to test

go version
go test ./...

Verify that responses and errors from both standard and streaming requests include a populated routing_info object in their extra fields. For fallback scenarios, confirm is_fallback is true and primary_provider/primary_model reflect the originally requested provider and model.

Screenshots/Recordings

N/A

Breaking changes

  • Yes
  • No

The previously flat Provider, OriginalModelRequested, and ResolvedModelUsed fields remain populated. The new routing_info object is additive.

Related issues

N/A

Security considerations

No auth, secrets, PII, or sandboxing implications. RoutingInfo surfaces key names (not key values) already present in other extra fields.

Checklist

  • I read docs/contributing/README.md and followed the guidelines
  • I added/updated tests where appropriate
  • I updated documentation where needed
  • I verified builds succeed (Go and UI)
  • I verified the CI pipeline passes locally if applicable

Summary by CodeRabbit

  • New Features
    • Routing metadata is now consistently captured and propagated across retries and fallback attempts (including streaming), so outcomes reliably carry routing attribution.
    • Responses and stream chunks include a unified routing info payload while preserving legacy provider/model fields for compatibility.
    • Fallback outcomes are explicitly tagged with the orchestrator’s primary provider/model to improve attribution clarity.

@coderabbitai

coderabbitai Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR centralizes request routing metadata by adding a RoutingInfo schema and BuildRoutingInfo helper, and propagates per-attempt and primary-attempt routing metadata through fallback and retry flows for streaming and non-streaming requests.

Changes

Request Routing Metadata Observability

Layer / File(s) Summary
RoutingInfo schema and population methods
core/schemas/bifrost.go
Introduces RoutingInfo and ResolvedKeyAlias types and adds PopulateRoutingInfo and SetFallbackRoutingInfo on BifrostResponse/BifrostError, plus syncDeprecatedFromRoutingInfo to backfill legacy fields.
BuildRoutingInfo construction helper
core/schemas/account.go
Implements BuildRoutingInfo(ctx, attemptProvider, attemptModel, attemptKey) to construct attempt-scoped RoutingInfo, copying resolved-alias fields when present.
Non-streaming fallback routing metadata
core/bifrost.go
After a fallback tryRequest, applies SetFallbackRoutingInfo(primaryProvider, primaryModel) to both successful result and fallbackErr.
Streaming fallback routing metadata
core/bifrost.go
After a fallback tryStreamRequest, applies SetFallbackRoutingInfo(primaryProvider, primaryModel) to fallbackErr (success path is an async stream and keeps per-chunk metadata).
Seed attemptRoutingInfo in requestWorker
core/bifrost.go
Introduces attemptRoutingInfo (pre-seeded) in the worker to preserve routing context across retries, including early failures.
Streaming retry routing metadata
core/bifrost.go
For streaming retries, snapshots per-attempt routing info into perAttemptRoutingInfo and uses it in postHookRunner to call PopulateRoutingInfo on per-chunk results/errors and on post-hook resp/bifrostErr.
Non-streaming retry routing metadata
core/bifrost.go
For non-streaming retries, updates attemptRoutingInfo per attempt and populates routing info on the final error or result before returning.
ProcessedStreamResponse RoutingInfo field
framework/streaming/types.go
Adds RoutingInfo schemas.RoutingInfo field to ProcessedStreamResponse.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • maximhq/bifrost#3930: Also modifies routing-related response attribution and uses resolved-provider context keys relevant to routing attribution.

Suggested reviewers

  • danpiths

Poem

🐰 I hop along each retry lane,
I mark the provider, model, and name—
When fallbacks come or streams race on,
RoutingInfo hums till the trace is drawn,
I carry context till the outcome's known.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding a RoutingInfo structure to response/error fields with fallback and key alias signal support.
Description check ✅ Passed The description comprehensively covers the purpose, changes, affected areas, testing approach, and breaking change status, matching the template structure.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 06-03-feat_adds_routinginfo_in_respose_error_extra_fields

Comment @coderabbitai help to get the list of available commands and usage tips.

@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

Pratham-Mishra04 commented Jun 3, 2026

Copy link
Copy Markdown
Collaborator Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@greptile-apps

greptile-apps Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Confidence Score: 3/5

The new RoutingInfo feature has incomplete coverage: multiple pre-queue error paths and the non-streaming post-hook path never call PopulateRoutingInfo, so consumers who have adopted the new API will silently receive empty routing data on those paths.

Two distinct gaps produce incorrect data for consumers who have migrated to RoutingInfo: early-exit errors (queue/tracer/context failures, short-circuit plugin responses) always return empty RoutingInfo while deprecated fields are correctly populated, and the non-streaming tryRequest path does not re-stamp RoutingInfo after RunPostLLMHooks, unlike the streaming postHookRunner. Both gaps are on the primary non-streaming request path.

core/bifrost.go — the pre-queue error returns and the post-RunPostLLMHooks branches in tryRequest need PopulateRoutingInfo calls to match the streaming postHookRunner pattern.

Important Files Changed

Filename Overview
core/bifrost.go Adds RoutingInfo stamping at per-attempt and fallback-orchestrator scopes. Pre-queue error paths and post-RunPostLLMHooks non-streaming paths omit PopulateRoutingInfo, leaving RoutingInfo empty while deprecated fields are populated.
core/schemas/bifrost.go Introduces RoutingInfo/ResolvedKeyAlias types, PopulateRoutingInfo, and SetFallbackRoutingInfo methods. SetFallbackRoutingInfo on BifrostResponse still uses GetExtraFields() whose fall-through returns an unreferenced temporary, so IsFallback/PrimaryProvider/PrimaryModel are silently discarded when no sub-type is active.
core/schemas/account.go Adds BuildRoutingInfo helper; reads ResolvedAlias from context and copies alias fields with defensive pointer clones. Logic is sound.
framework/streaming/types.go Adds RoutingInfo field to ProcessedStreamResponse struct; no existing factory functions populate it yet (flagged in a previous review thread).

Comments Outside Diff (1)

  1. core/bifrost.go, line 4904-4908 (link)

    P1 Early-exit errors in tryRequest / tryStreamRequest leave RoutingInfo as zero value

    All pre-queue error paths in tryRequest — provider queue not found, tracer nil, queue full, provider shutting down (pq.done), context cancelled — and the corresponding paths in tryStreamRequest call PopulateExtraFields but never PopulateRoutingInfo. Any BifrostError returned from these paths will have the deprecated Provider/OriginalModelRequested fields correctly set but ExtraFields.RoutingInfo entirely empty. The same gap applies to the short-circuit response/error path after RunLLMPreHooks (lines ~4939–4965 / ~5190–5200): plugin-generated short-circuit responses, such as governance-layer blocks or semantic-cache hits, also skip PopulateRoutingInfo. Consumers that have migrated off the deprecated fields to read RoutingInfo.Provider or RoutingInfo.Model will silently receive empty strings on all these paths.

Reviews (11): Last reviewed commit: "feat: adds routinginfo in respose/error ..." | Re-trigger Greptile

Comment thread framework/streaming/types.go
Comment thread core/schemas/bifrost.go
Comment thread core/schemas/bifrost.go
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-03-feat_adds_routinginfo_in_respose_error_extra_fields branch from 7f83e5f to 7795c41 Compare June 3, 2026 21:47
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-03-feat_adds_ui_for_alias_extensions branch from a01b109 to 2992112 Compare June 3, 2026 21:47
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-03-feat_adds_ui_for_alias_extensions branch from 2992112 to ddb8535 Compare June 4, 2026 20:49
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-03-feat_adds_routinginfo_in_respose_error_extra_fields branch from 7795c41 to 53ed5e5 Compare June 4, 2026 20:49
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-03-feat_adds_ui_for_alias_extensions branch from ddb8535 to f8f177d Compare June 5, 2026 09:48
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-03-feat_adds_routinginfo_in_respose_error_extra_fields branch from 53ed5e5 to 6fe1303 Compare June 5, 2026 09:48

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

🤖 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 6095-6100: The variable attemptRoutingInfo (type
schemas.RoutingInfo) must be initialized before the retry loop so post-retry
population doesn't overwrite existing ExtraFields with a zero-value when the
per-attempt closure never ran; set attemptRoutingInfo to the current routing
snapshot before retries begin (e.g., copy the resolved/current routing info used
to call PopulateExtraFields), keep updating it inside the per-attempt closure as
already implemented, and when applying it after retries (where
PopulateExtraFields/ExtraFields are touched) only overwrite routing-derived
ExtraFields if attemptRoutingInfo is non-zero/has meaningful fields —
alternatively check for a zero-value and skip the overwrite. Ensure changes
reference attemptRoutingInfo, PopulateExtraFields, and the post-retry apply
logic so the initial non-nil routing metadata is preserved when attempts never
run.
🪄 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: 25c0075d-ca6c-445d-92e1-db6cfe02ab42

📥 Commits

Reviewing files that changed from the base of the PR and between f8f177d and 6fe1303.

📒 Files selected for processing (4)
  • core/bifrost.go
  • core/schemas/account.go
  • core/schemas/bifrost.go
  • framework/streaming/types.go

Comment thread core/bifrost.go Outdated
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-03-feat_adds_ui_for_alias_extensions branch from f8f177d to bea64ee Compare June 5, 2026 10:43
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-03-feat_adds_routinginfo_in_respose_error_extra_fields branch from 6fe1303 to 3d70a3f Compare June 5, 2026 10:43
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-03-feat_adds_ui_for_alias_extensions branch from bea64ee to 768db39 Compare June 7, 2026 07:25
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-03-feat_adds_routinginfo_in_respose_error_extra_fields branch from 3d70a3f to 139c90d Compare June 7, 2026 07:25

@coderabbitai coderabbitai Bot left a comment

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.

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/bifrost.go`:
- Around line 4851-4858: The success path for fallback streaming doesn't mark
returned chunks as fallback: after calling bifrost.tryStreamRequest(ctx,
fallbackReq) you must apply SetFallbackRoutingInfo to the successful stream
result as well as to fallbackErr so that returned chunk messages carry
is_fallback=true and primary_* fields are nil; locate the call sites around
tryStreamRequest/ result / fallbackErr and invoke the same
SetFallbackRoutingInfo(provider, model) (or a helper that wraps the result
channel to annotate each emitted chunk) for the successful channel return path
(also repeat the same change at the other occurrence referenced near the
tryStreamRequest usage around the 6201-6219 region).
- Around line 4735-4740: The current code stamps fallback routing info using the
outer-scope variables `provider` and `model` immediately after calling
`tryRequest`/`tryStreamRequest`, which can be stale if a `PreLLMHook` rerouted
the request; update the logic in the `tryRequest`/`tryStreamRequest` handling
(where `result.SetFallbackRoutingInfo(provider, model)` and
`fallbackErr.SetFallbackRoutingInfo(provider, model)` are called) to first read
the completed primary attempt's `RoutingInfo` (from the returned `result` or
`fallbackErr`) for `primary_provider`/`primary_model` and use those values when
present, falling back to the outer `provider`/`model` only if the RoutingInfo
fields are empty; follow the same change for the equivalent `tryStreamRequest`
block and rely on how `BifrostRequest.UpdateProvider` mutates the inner request
(accessible via `preReq.GetRequestFields()`) so rerouted provider/model are
preserved in the completed response before stamping fallback metadata.
- Around line 939-950: The validation currently treats a non-nil
req.PreviousResponseID as present even if it's empty/whitespace, allowing empty
compaction requests through; update the condition that returns the "input not
provided" BifrostError to consider PreviousResponseID empty when it's nil OR
when strings.TrimSpace(*req.PreviousResponseID) == "" (i.e., treat
blank/whitespace previous_response_id as missing), and ensure you import/use the
strings package and preserve the existing isLargePayloadPassthrough(ctx) check.

In `@framework/streaming/types.go`:
- Line 247: The ProcessedStreamResponse struct's RoutingInfo field is never
copied into the outgoing extra_fields.routing_info during conversion; update the
ToBifrostResponse (and any other stream-to-response conversion helpers handling
ProcessedStreamResponse) to set the outgoing response's ExtraFields.RoutingInfo
(or ExtraFields["routing_info"] equivalent) from
ProcessedStreamResponse.RoutingInfo so fallback/alias routing metadata is
preserved; locate the conversion function named ToBifrostResponse and any
similar converters that build the final response and add a single assignment to
copy RoutingInfo into ExtraFields before returning the response.
🪄 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: 20d4ab02-785e-4b1a-a992-8335591664c4

📥 Commits

Reviewing files that changed from the base of the PR and between 6fe1303 and 139c90d.

📒 Files selected for processing (4)
  • core/bifrost.go
  • core/schemas/account.go
  • core/schemas/bifrost.go
  • framework/streaming/types.go

@coderabbitai coderabbitai Bot left a comment

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.

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

🤖 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 4851-4858: The success path for fallback streaming doesn't mark
returned chunks as fallback: after calling bifrost.tryStreamRequest(ctx,
fallbackReq) you must apply SetFallbackRoutingInfo to the successful stream
result as well as to fallbackErr so that returned chunk messages carry
is_fallback=true and primary_* fields are nil; locate the call sites around
tryStreamRequest/ result / fallbackErr and invoke the same
SetFallbackRoutingInfo(provider, model) (or a helper that wraps the result
channel to annotate each emitted chunk) for the successful channel return path
(also repeat the same change at the other occurrence referenced near the
tryStreamRequest usage around the 6201-6219 region).
- Around line 4735-4740: The current code stamps fallback routing info using the
outer-scope variables `provider` and `model` immediately after calling
`tryRequest`/`tryStreamRequest`, which can be stale if a `PreLLMHook` rerouted
the request; update the logic in the `tryRequest`/`tryStreamRequest` handling
(where `result.SetFallbackRoutingInfo(provider, model)` and
`fallbackErr.SetFallbackRoutingInfo(provider, model)` are called) to first read
the completed primary attempt's `RoutingInfo` (from the returned `result` or
`fallbackErr`) for `primary_provider`/`primary_model` and use those values when
present, falling back to the outer `provider`/`model` only if the RoutingInfo
fields are empty; follow the same change for the equivalent `tryStreamRequest`
block and rely on how `BifrostRequest.UpdateProvider` mutates the inner request
(accessible via `preReq.GetRequestFields()`) so rerouted provider/model are
preserved in the completed response before stamping fallback metadata.
- Around line 939-950: The validation currently treats a non-nil
req.PreviousResponseID as present even if it's empty/whitespace, allowing empty
compaction requests through; update the condition that returns the "input not
provided" BifrostError to consider PreviousResponseID empty when it's nil OR
when strings.TrimSpace(*req.PreviousResponseID) == "" (i.e., treat
blank/whitespace previous_response_id as missing), and ensure you import/use the
strings package and preserve the existing isLargePayloadPassthrough(ctx) check.

In `@framework/streaming/types.go`:
- Line 247: The ProcessedStreamResponse struct's RoutingInfo field is never
copied into the outgoing extra_fields.routing_info during conversion; update the
ToBifrostResponse (and any other stream-to-response conversion helpers handling
ProcessedStreamResponse) to set the outgoing response's ExtraFields.RoutingInfo
(or ExtraFields["routing_info"] equivalent) from
ProcessedStreamResponse.RoutingInfo so fallback/alias routing metadata is
preserved; locate the conversion function named ToBifrostResponse and any
similar converters that build the final response and add a single assignment to
copy RoutingInfo into ExtraFields before returning the response.
🪄 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: 20d4ab02-785e-4b1a-a992-8335591664c4

📥 Commits

Reviewing files that changed from the base of the PR and between 6fe1303 and 139c90d.

📒 Files selected for processing (4)
  • core/bifrost.go
  • core/schemas/account.go
  • core/schemas/bifrost.go
  • framework/streaming/types.go
🛑 Comments failed to post (4)
core/bifrost.go (3)

939-950: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Treat blank previous_response_id as missing input.

req.PreviousResponseID != nil lets "" or whitespace bypass validation when Input is empty, so an invalid compaction request is forwarded upstream instead of failing fast.

💡 Proposed fix
-	if len(req.Input) == 0 && req.PreviousResponseID == nil && !isLargePayloadPassthrough(ctx) {
+	hasPreviousResponseID := req.PreviousResponseID != nil && strings.TrimSpace(*req.PreviousResponseID) != ""
+	if len(req.Input) == 0 && !hasPreviousResponseID && !isLargePayloadPassthrough(ctx) {
🤖 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 939 - 950, The validation currently treats a
non-nil req.PreviousResponseID as present even if it's empty/whitespace,
allowing empty compaction requests through; update the condition that returns
the "input not provided" BifrostError to consider PreviousResponseID empty when
it's nil OR when strings.TrimSpace(*req.PreviousResponseID) == "" (i.e., treat
blank/whitespace previous_response_id as missing), and ensure you import/use the
strings package and preserve the existing isLargePayloadPassthrough(ctx) check.

4735-4740: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Stamp fallback metadata from the actual primary attempt.

provider / model here are captured before tryRequest / tryStreamRequest, but PreLLMHook can still reroute the primary attempt. When that happens, fallback outcomes report the wrong routing_info.primary_provider / primary_model. Read those values from the completed primary response/error RoutingInfo and only fall back to the outer variables when that metadata is empty.

Based on learnings, "provider switching from a PreLLMHook plugin is performed by calling BifrostRequest.UpdateProvider(provider), which mutates the inner request ... getProviderQueue reads the updated provider via preReq.GetRequestFields()."

Also applies to: 4851-4857

🤖 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 4735 - 4740, The current code stamps fallback
routing info using the outer-scope variables `provider` and `model` immediately
after calling `tryRequest`/`tryStreamRequest`, which can be stale if a
`PreLLMHook` rerouted the request; update the logic in the
`tryRequest`/`tryStreamRequest` handling (where
`result.SetFallbackRoutingInfo(provider, model)` and
`fallbackErr.SetFallbackRoutingInfo(provider, model)` are called) to first read
the completed primary attempt's `RoutingInfo` (from the returned `result` or
`fallbackErr`) for `primary_provider`/`primary_model` and use those values when
present, falling back to the outer `provider`/`model` only if the RoutingInfo
fields are empty; follow the same change for the equivalent `tryStreamRequest`
block and rely on how `BifrostRequest.UpdateProvider` mutates the inner request
(accessible via `preReq.GetRequestFields()`) so rerouted provider/model are
preserved in the completed response before stamping fallback metadata.

Source: Learnings


4851-4858: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Successful fallback streams never advertise that they are fallbacks.

Only fallbackErr gets SetFallbackRoutingInfo(...). On the success path the stream channel is returned unchanged, and the chunk post-hook runner only applies perAttemptRoutingInfo, so chunks from a fallback stream still carry is_fallback=false with nil primary_*. That breaks the new streaming routing-info contract for consumers and observability.

Also applies to: 6201-6219

🤖 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 4851 - 4858, The success path for fallback
streaming doesn't mark returned chunks as fallback: after calling
bifrost.tryStreamRequest(ctx, fallbackReq) you must apply SetFallbackRoutingInfo
to the successful stream result as well as to fallbackErr so that returned chunk
messages carry is_fallback=true and primary_* fields are nil; locate the call
sites around tryStreamRequest/ result / fallbackErr and invoke the same
SetFallbackRoutingInfo(provider, model) (or a helper that wraps the result
channel to annotate each emitted chunk) for the successful channel return path
(also repeat the same change at the other occurrence referenced near the
tryStreamRequest usage around the 6201-6219 region).
framework/streaming/types.go (1)

247-247: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Populate RoutingInfo in final stream-to-response conversion.

Line 247 introduces ProcessedStreamResponse.RoutingInfo, but ToBifrostResponse never writes it into extra_fields.routing_info. Final aggregated streaming responses therefore lose fallback/alias routing metadata even when it was captured upstream.

💡 Proposed fix
 func (p *ProcessedStreamResponse) ToBifrostResponse() *schemas.BifrostResponse {
 	if p.Data == nil {
 		return nil
 	}
@@
 	switch p.StreamType {
@@
 	}
+	resp.PopulateRoutingInfo(p.RoutingInfo)
 	return resp
 }

Also applies to: 253-459

🤖 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 `@framework/streaming/types.go` at line 247, The ProcessedStreamResponse
struct's RoutingInfo field is never copied into the outgoing
extra_fields.routing_info during conversion; update the ToBifrostResponse (and
any other stream-to-response conversion helpers handling
ProcessedStreamResponse) to set the outgoing response's ExtraFields.RoutingInfo
(or ExtraFields["routing_info"] equivalent) from
ProcessedStreamResponse.RoutingInfo so fallback/alias routing metadata is
preserved; locate the conversion function named ToBifrostResponse and any
similar converters that build the final response and add a single assignment to
copy RoutingInfo into ExtraFields before returning the response.

@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-03-feat_adds_routinginfo_in_respose_error_extra_fields branch from 139c90d to decab23 Compare June 8, 2026 06:54

@coderabbitai coderabbitai Bot left a comment

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.

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/bifrost.go`:
- Around line 4851-4858: The fallback success path only calls
SetFallbackRoutingInfo on fallbackErr, leaving successful streaming results (the
result chan returned from tryStreamRequest) without primary/fallback routing
metadata; to fix, when tryStreamRequest returns a non-nil result channel (the
result variable) wrap that channel with a forwarding goroutine that annotates
each emitted chunk with the same fallback/primary routing info (the metadata you
set via SetFallbackRoutingInfo) before sending it downstream, or alternatively
propagate the primary attempt data into postHookRunner so each chunk emitted
carries routing_info.is_fallback, primary_provider, and primary_model; update
the code around tryStreamRequest, the result handling, and any use of
postHookRunner/SetFallbackRoutingInfo to ensure both error and success streaming
paths attach the fallback routing metadata.
- Around line 939-951: The validation currently treats a non-nil
req.PreviousResponseID as present even when it is an empty or whitespace string;
update the compaction request check to treat blank/whitespace PreviousResponseID
as missing by using strings.TrimSpace on *req.PreviousResponseID (e.g. change
the if to require that PreviousResponseID is non-nil AND
strings.TrimSpace(*req.PreviousResponseID) != ""), and add the strings import if
missing; keep the existing BifrostError return logic (schemas.BifrostError /
schemas.ErrorField) when the input is effectively absent.

In `@core/schemas/account.go`:
- Around line 205-226: VLLMAliasCfg is defined but never included in
AliasConfig, so alias-level vLLM overrides cannot deserialize; add a pointer
field *VLLMAliasCfg to the AliasConfig struct (alongside *AzureAliasCfg,
*VertexAliasCfg, etc.), then update isLegacyShape() and Validate() to consider
this new field (accept its presence in legacy-shape checks and validate its
contents the same way other provider-specific alias cfgs are validated), and
ensure any JSON (un)marshaling or switch logic that handles alias overrides
includes VLLMAliasCfg as well.

In `@core/schemas/bifrost.go`:
- Around line 1098-1197: Add deterministic table-driven unit tests that exercise
syncDeprecatedFromRoutingInfo via the public helpers PopulateRoutingInfo and
SetFallbackRoutingInfo for both BifrostResponse and BifrostError: include cases
for non-fallback vs fallback (set PrimaryModel/PrimaryProvider) and alias vs
non-alias (ResolvedKeyAlias with ModelID vs no alias), asserting
ExtraFields.Provider, ExtraFields.OriginalModelRequested and
ExtraFields.ResolvedModelUsed match the documented derivation rules; cover
nil/empty pointers, and ensure tests call PopulateRoutingInfo before/after
SetFallbackRoutingInfo to validate both code paths. Use subtests or a table with
inputs (RoutingInfo variants) and expected deprecated-field outputs and
reference the functions syncDeprecatedFromRoutingInfo, PopulateRoutingInfo,
SetFallbackRoutingInfo, and the ExtraFields fields to locate code under test.
🪄 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: c43398ea-23f3-4898-b8c4-2b918261cc20

📥 Commits

Reviewing files that changed from the base of the PR and between 139c90d and decab23.

📒 Files selected for processing (4)
  • core/bifrost.go
  • core/schemas/account.go
  • core/schemas/bifrost.go
  • framework/streaming/types.go
💤 Files with no reviewable changes (1)
  • framework/streaming/types.go

@coderabbitai coderabbitai Bot left a comment

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.

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

🤖 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 4851-4858: The fallback success path only calls
SetFallbackRoutingInfo on fallbackErr, leaving successful streaming results (the
result chan returned from tryStreamRequest) without primary/fallback routing
metadata; to fix, when tryStreamRequest returns a non-nil result channel (the
result variable) wrap that channel with a forwarding goroutine that annotates
each emitted chunk with the same fallback/primary routing info (the metadata you
set via SetFallbackRoutingInfo) before sending it downstream, or alternatively
propagate the primary attempt data into postHookRunner so each chunk emitted
carries routing_info.is_fallback, primary_provider, and primary_model; update
the code around tryStreamRequest, the result handling, and any use of
postHookRunner/SetFallbackRoutingInfo to ensure both error and success streaming
paths attach the fallback routing metadata.
- Around line 939-951: The validation currently treats a non-nil
req.PreviousResponseID as present even when it is an empty or whitespace string;
update the compaction request check to treat blank/whitespace PreviousResponseID
as missing by using strings.TrimSpace on *req.PreviousResponseID (e.g. change
the if to require that PreviousResponseID is non-nil AND
strings.TrimSpace(*req.PreviousResponseID) != ""), and add the strings import if
missing; keep the existing BifrostError return logic (schemas.BifrostError /
schemas.ErrorField) when the input is effectively absent.

In `@core/schemas/account.go`:
- Around line 205-226: VLLMAliasCfg is defined but never included in
AliasConfig, so alias-level vLLM overrides cannot deserialize; add a pointer
field *VLLMAliasCfg to the AliasConfig struct (alongside *AzureAliasCfg,
*VertexAliasCfg, etc.), then update isLegacyShape() and Validate() to consider
this new field (accept its presence in legacy-shape checks and validate its
contents the same way other provider-specific alias cfgs are validated), and
ensure any JSON (un)marshaling or switch logic that handles alias overrides
includes VLLMAliasCfg as well.

In `@core/schemas/bifrost.go`:
- Around line 1098-1197: Add deterministic table-driven unit tests that exercise
syncDeprecatedFromRoutingInfo via the public helpers PopulateRoutingInfo and
SetFallbackRoutingInfo for both BifrostResponse and BifrostError: include cases
for non-fallback vs fallback (set PrimaryModel/PrimaryProvider) and alias vs
non-alias (ResolvedKeyAlias with ModelID vs no alias), asserting
ExtraFields.Provider, ExtraFields.OriginalModelRequested and
ExtraFields.ResolvedModelUsed match the documented derivation rules; cover
nil/empty pointers, and ensure tests call PopulateRoutingInfo before/after
SetFallbackRoutingInfo to validate both code paths. Use subtests or a table with
inputs (RoutingInfo variants) and expected deprecated-field outputs and
reference the functions syncDeprecatedFromRoutingInfo, PopulateRoutingInfo,
SetFallbackRoutingInfo, and the ExtraFields fields to locate code under test.
🪄 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: c43398ea-23f3-4898-b8c4-2b918261cc20

📥 Commits

Reviewing files that changed from the base of the PR and between 139c90d and decab23.

📒 Files selected for processing (4)
  • core/bifrost.go
  • core/schemas/account.go
  • core/schemas/bifrost.go
  • framework/streaming/types.go
💤 Files with no reviewable changes (1)
  • framework/streaming/types.go
🛑 Comments failed to post (4)
core/bifrost.go (2)

939-951: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Reject blank previous_response_id in compaction validation.

PreviousResponseID != nil currently counts as “present” even when it points to "", so a request with no input and an empty ID skips local validation and fails later at the provider boundary. Treat blank/whitespace IDs as missing here.

💡 Proposed fix
-	if len(req.Input) == 0 && req.PreviousResponseID == nil && !isLargePayloadPassthrough(ctx) {
+	hasPreviousResponseID := req.PreviousResponseID != nil && strings.TrimSpace(*req.PreviousResponseID) != ""
+	if len(req.Input) == 0 && !hasPreviousResponseID && !isLargePayloadPassthrough(ctx) {

As per coding guidelines, validate all untrusted input before provider calls.

🤖 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 939 - 951, The validation currently treats a
non-nil req.PreviousResponseID as present even when it is an empty or whitespace
string; update the compaction request check to treat blank/whitespace
PreviousResponseID as missing by using strings.TrimSpace on
*req.PreviousResponseID (e.g. change the if to require that PreviousResponseID
is non-nil AND strings.TrimSpace(*req.PreviousResponseID) != ""), and add the
strings import if missing; keep the existing BifrostError return logic
(schemas.BifrostError / schemas.ErrorField) when the input is effectively
absent.

Source: Coding guidelines


4851-4858: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Successful fallback streams never get fallback routing metadata.

This only annotates fallbackErr. When tryStreamRequest succeeds, the returned channel is passed through unchanged, and the worker-side postHookRunner only stamps perAttemptRoutingInfo. The emitted chunks therefore miss routing_info.is_fallback, primary_provider, and primary_model for successful fallback streams, so the new streaming contract is incomplete.

Thread the primary attempt metadata into the streaming chunk path as well, or wrap the returned channel and annotate each emitted chunk before returning it.

🤖 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 4851 - 4858, The fallback success path only
calls SetFallbackRoutingInfo on fallbackErr, leaving successful streaming
results (the result chan returned from tryStreamRequest) without
primary/fallback routing metadata; to fix, when tryStreamRequest returns a
non-nil result channel (the result variable) wrap that channel with a forwarding
goroutine that annotates each emitted chunk with the same fallback/primary
routing info (the metadata you set via SetFallbackRoutingInfo) before sending it
downstream, or alternatively propagate the primary attempt data into
postHookRunner so each chunk emitted carries routing_info.is_fallback,
primary_provider, and primary_model; update the code around tryStreamRequest,
the result handling, and any use of postHookRunner/SetFallbackRoutingInfo to
ensure both error and success streaming paths attach the fallback routing
metadata.
core/schemas/account.go (1)

205-226: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

VLLMAliasCfg is declared but never reachable from AliasConfig.

VLLMAliasCfg is added here, but AliasConfig has no field for it, and neither isLegacyShape() nor Validate() account for it. Any alias-level vLLM override therefore has nowhere to deserialize, so configs meant to steer one vLLM key across multiple served models will silently behave as if the override was never set.

Possible direction
 type AliasConfig struct {
 	ModelID     string       `json:"model_id"`
 	ModelName   *string      `json:"model_name,omitempty"`
 	ModelFamily *ModelFamily `json:"model_family,omitempty"`
 	Description string       `json:"description,omitempty"`
 	Region      *EnvVar      `json:"region,omitempty"`

 	*AzureAliasCfg
 	*VertexAliasCfg
 	*BedrockAliasCfg
 	*ReplicateAliasCfg
+	VLLM *VLLMAliasCfg `json:"vllm,omitempty"`
 }

 func (ac AliasConfig) isLegacyShape() bool {
 	return ac.ModelID != "" &&
 		ac.ModelName == nil &&
 		ac.ModelFamily == nil &&
 		ac.Description == "" &&
 		ac.Region == nil &&
 		ac.AzureAliasCfg == nil &&
 		ac.VertexAliasCfg == nil &&
 		ac.BedrockAliasCfg == nil &&
-		ac.ReplicateAliasCfg == nil
+		ac.ReplicateAliasCfg == nil &&
+		ac.VLLM == nil
 }

 func (ka KeyAliases) Validate(providerKey ModelProvider) error {
 	// ...
+		if ac.VLLM != nil && providerKey != VLLM {
+			return fmt.Errorf("alias %q: vllm sub-config is only valid on VLLM keys (got provider %q)", from, providerKey)
+		}
 	// ...
 }

Also applies to: 231-240, 276-315

🤖 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/schemas/account.go` around lines 205 - 226, VLLMAliasCfg is defined but
never included in AliasConfig, so alias-level vLLM overrides cannot deserialize;
add a pointer field *VLLMAliasCfg to the AliasConfig struct (alongside
*AzureAliasCfg, *VertexAliasCfg, etc.), then update isLegacyShape() and
Validate() to consider this new field (accept its presence in legacy-shape
checks and validate its contents the same way other provider-specific alias cfgs
are validated), and ensure any JSON (un)marshaling or switch logic that handles
alias overrides includes VLLMAliasCfg as well.
core/schemas/bifrost.go (1)

1098-1197: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Add table-driven coverage for routing/deprecated-field sync.

This block now defines the public routing_info contract and the deprecated compatibility fields for every response/error path, but the change set ships without schema-level tests for primary vs fallback and alias vs non-alias cases. A regression here will silently relabel responses across providers.

As per coding guidelines, “Apply standard Go review practices: … deterministic tests, and table-driven coverage for behavior changes.”

🤖 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/schemas/bifrost.go` around lines 1098 - 1197, Add deterministic
table-driven unit tests that exercise syncDeprecatedFromRoutingInfo via the
public helpers PopulateRoutingInfo and SetFallbackRoutingInfo for both
BifrostResponse and BifrostError: include cases for non-fallback vs fallback
(set PrimaryModel/PrimaryProvider) and alias vs non-alias (ResolvedKeyAlias with
ModelID vs no alias), asserting ExtraFields.Provider,
ExtraFields.OriginalModelRequested and ExtraFields.ResolvedModelUsed match the
documented derivation rules; cover nil/empty pointers, and ensure tests call
PopulateRoutingInfo before/after SetFallbackRoutingInfo to validate both code
paths. Use subtests or a table with inputs (RoutingInfo variants) and expected
deprecated-field outputs and reference the functions
syncDeprecatedFromRoutingInfo, PopulateRoutingInfo, SetFallbackRoutingInfo, and
the ExtraFields fields to locate code under test.

Source: Coding guidelines

@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-03-feat_adds_ui_for_alias_extensions branch from 46cb342 to a9be3a8 Compare June 8, 2026 07:18
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-03-feat_adds_routinginfo_in_respose_error_extra_fields branch from decab23 to 0f1ec91 Compare June 8, 2026 07:18

@coderabbitai coderabbitai Bot left a comment

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.

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)
framework/streaming/types.go (1)

253-459: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Transfer RoutingInfo to BifrostResponse in all stream-type branches.

ToBifrostResponse adds ProcessedStreamResponse.RoutingInfo at line 247 but never transfers it to the resulting BifrostResponse. All six stream-type branches (text, chat, responses, audio, transcription, image) create ExtraFields struct literals that omit RoutingInfo, so the routing metadata is lost when converting from ProcessedStreamResponse to BifrostResponse. This breaks the feature: clients won't see routing_info (attempt-level provider/model/key, fallback signals, primary-attempt attribution) in streaming responses.

Per the PopulateRoutingInfo method (context snippet 2), the recommended pattern is to call resp.XxxResponse.PopulateRoutingInfo(p.RoutingInfo) after setting ExtraFields, which both stamps RoutingInfo and syncs the deprecated Provider/OriginalModelRequested/ResolvedModelUsed fields automatically via syncDeprecatedFromRoutingInfo. This eliminates the need to manually set the deprecated fields in the struct literal.

🔧 Proposed fix to transfer RoutingInfo in all branches

Apply this pattern to all six stream-type branches (text, chat, responses, audio, transcription, image). Example for StreamTypeChat (lines 336-351):

 		resp.ChatResponse = chatResp
 		resp.ChatResponse.ExtraFields = schemas.BifrostResponseExtraFields{
 			RequestType:            schemas.ChatCompletionRequest,
-			Provider:               p.Provider,
-			OriginalModelRequested: p.RequestedModel,
-			ResolvedModelUsed:      p.ResolvedModel,
 			Latency:                p.Data.Latency,
 		}
+		resp.ChatResponse.PopulateRoutingInfo(p.RoutingInfo)
 		if p.RawRequest != nil {

Repeat the same transformation for StreamTypeText (lines 284–299), StreamTypeResponses (lines 361–377), StreamTypeAudio (lines 384–399), StreamTypeTranscription (lines 406–421), and StreamTypeImage (lines 440–456): remove the deprecated-field assignments (Provider, OriginalModelRequested, ResolvedModelUsed) from the struct literal and add resp.XxxResponse.PopulateRoutingInfo(p.RoutingInfo) immediately after the ExtraFields assignment.

🤖 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 `@framework/streaming/types.go` around lines 253 - 459, ToBifrostResponse is
not transferring ProcessedStreamResponse.RoutingInfo into the created
BifrostResponse, so routing metadata is lost; for each branch inside
ToBifrostResponse (StreamTypeText, StreamTypeChat, StreamTypeResponses,
StreamTypeAudio, StreamTypeTranscription, StreamTypeImage) remove setting the
deprecated Provider/OriginalModelRequested/ResolvedModelUsed fields in the
ExtraFields literal and instead call
resp.<Xxx>Response.PopulateRoutingInfo(p.RoutingInfo) immediately after
assigning ExtraFields (using the existing PopulateRoutingInfo helper to stamp
RoutingInfo and sync deprecated fields), e.g., after
resp.ChatResponse.ExtraFields = ... call
resp.ChatResponse.PopulateRoutingInfo(p.RoutingInfo); repeat for Text,
Responses, Speech, Transcription, and Image branches within the same
ToBifrostResponse function.
🤖 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 4851-4858: The fallback stream path currently only calls
SetFallbackRoutingInfo on fallbackErr and returns the raw result channel from
tryStreamRequest, so successful streamed chunks never receive
routing_info.is_fallback/primary_provider/primary_model; fix by wrapping the
returned channel from tryStreamRequest (the variable result) inside a new
goroutine/chan reader in bifrost.tryStreamRequest caller code that reads each
emitted chunk or error and calls SetFallbackRoutingInfo(provider, model) before
forwarding it, or alternatively ensure the per-attempt BuildRoutingInfo used by
the streaming post-hook includes the primary provider/model so emitted chunks
already contain the fallback fields; reference tryStreamRequest, result (the
returned chan), and SetFallbackRoutingInfo to locate and implement the change.

In `@core/schemas/account.go`:
- Around line 205-226: AliasConfig currently never includes VLLMAliasCfg and
both VLLMAliasCfg.ModelName and AliasConfig.ModelName share the same json tag,
making the vLLM override unreachable; fix by adding a nested vLLM field to
AliasConfig (e.g., add a pointer field like VLLM *VLLMAliasCfg
`json:"vllm,omitempty"`), leaving AliasConfig.ModelName as the canonical
top-level name, and keep VLLMAliasCfg.ModelName as-is so its JSON becomes
vllm.model_name (no tag rename required), ensuring callers can express the
vLLM-specific override separately from AliasConfig.ModelName.

In `@core/schemas/bifrost.go`:
- Around line 1103-1125: syncDeprecatedFromRoutingInfo currently only overwrites
non-empty branches and can leave prior values in pooled outputs; first clear the
outputs then re-derive them from info: at the top of
syncDeprecatedFromRoutingInfo, if provider != nil set *provider to the zero
value (empty), if originalModelRequested != nil set *originalModelRequested to
"", and if resolvedModelUsed != nil set *resolved_model_used (resolvedModelUsed)
to ""; then run the existing logic that sets provider, originalModelRequested,
and resolvedModelUsed from info so partial RoutingInfo cannot leak prior-request
data.

---

Outside diff comments:
In `@framework/streaming/types.go`:
- Around line 253-459: ToBifrostResponse is not transferring
ProcessedStreamResponse.RoutingInfo into the created BifrostResponse, so routing
metadata is lost; for each branch inside ToBifrostResponse (StreamTypeText,
StreamTypeChat, StreamTypeResponses, StreamTypeAudio, StreamTypeTranscription,
StreamTypeImage) remove setting the deprecated
Provider/OriginalModelRequested/ResolvedModelUsed fields in the ExtraFields
literal and instead call resp.<Xxx>Response.PopulateRoutingInfo(p.RoutingInfo)
immediately after assigning ExtraFields (using the existing PopulateRoutingInfo
helper to stamp RoutingInfo and sync deprecated fields), e.g., after
resp.ChatResponse.ExtraFields = ... call
resp.ChatResponse.PopulateRoutingInfo(p.RoutingInfo); repeat for Text,
Responses, Speech, Transcription, and Image branches within the same
ToBifrostResponse function.
🪄 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: 2e2a89b2-03f2-4b1b-ac60-df226003e56b

📥 Commits

Reviewing files that changed from the base of the PR and between decab23 and 0f1ec91.

📒 Files selected for processing (4)
  • core/bifrost.go
  • core/schemas/account.go
  • core/schemas/bifrost.go
  • framework/streaming/types.go

@coderabbitai coderabbitai Bot left a comment

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.

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: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
framework/streaming/types.go (1)

253-459: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Transfer RoutingInfo to BifrostResponse in all stream-type branches.

ToBifrostResponse adds ProcessedStreamResponse.RoutingInfo at line 247 but never transfers it to the resulting BifrostResponse. All six stream-type branches (text, chat, responses, audio, transcription, image) create ExtraFields struct literals that omit RoutingInfo, so the routing metadata is lost when converting from ProcessedStreamResponse to BifrostResponse. This breaks the feature: clients won't see routing_info (attempt-level provider/model/key, fallback signals, primary-attempt attribution) in streaming responses.

Per the PopulateRoutingInfo method (context snippet 2), the recommended pattern is to call resp.XxxResponse.PopulateRoutingInfo(p.RoutingInfo) after setting ExtraFields, which both stamps RoutingInfo and syncs the deprecated Provider/OriginalModelRequested/ResolvedModelUsed fields automatically via syncDeprecatedFromRoutingInfo. This eliminates the need to manually set the deprecated fields in the struct literal.

🔧 Proposed fix to transfer RoutingInfo in all branches

Apply this pattern to all six stream-type branches (text, chat, responses, audio, transcription, image). Example for StreamTypeChat (lines 336-351):

 		resp.ChatResponse = chatResp
 		resp.ChatResponse.ExtraFields = schemas.BifrostResponseExtraFields{
 			RequestType:            schemas.ChatCompletionRequest,
-			Provider:               p.Provider,
-			OriginalModelRequested: p.RequestedModel,
-			ResolvedModelUsed:      p.ResolvedModel,
 			Latency:                p.Data.Latency,
 		}
+		resp.ChatResponse.PopulateRoutingInfo(p.RoutingInfo)
 		if p.RawRequest != nil {

Repeat the same transformation for StreamTypeText (lines 284–299), StreamTypeResponses (lines 361–377), StreamTypeAudio (lines 384–399), StreamTypeTranscription (lines 406–421), and StreamTypeImage (lines 440–456): remove the deprecated-field assignments (Provider, OriginalModelRequested, ResolvedModelUsed) from the struct literal and add resp.XxxResponse.PopulateRoutingInfo(p.RoutingInfo) immediately after the ExtraFields assignment.

🤖 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 `@framework/streaming/types.go` around lines 253 - 459, ToBifrostResponse is
not transferring ProcessedStreamResponse.RoutingInfo into the created
BifrostResponse, so routing metadata is lost; for each branch inside
ToBifrostResponse (StreamTypeText, StreamTypeChat, StreamTypeResponses,
StreamTypeAudio, StreamTypeTranscription, StreamTypeImage) remove setting the
deprecated Provider/OriginalModelRequested/ResolvedModelUsed fields in the
ExtraFields literal and instead call
resp.<Xxx>Response.PopulateRoutingInfo(p.RoutingInfo) immediately after
assigning ExtraFields (using the existing PopulateRoutingInfo helper to stamp
RoutingInfo and sync deprecated fields), e.g., after
resp.ChatResponse.ExtraFields = ... call
resp.ChatResponse.PopulateRoutingInfo(p.RoutingInfo); repeat for Text,
Responses, Speech, Transcription, and Image branches within the same
ToBifrostResponse function.
🤖 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 4851-4858: The fallback stream path currently only calls
SetFallbackRoutingInfo on fallbackErr and returns the raw result channel from
tryStreamRequest, so successful streamed chunks never receive
routing_info.is_fallback/primary_provider/primary_model; fix by wrapping the
returned channel from tryStreamRequest (the variable result) inside a new
goroutine/chan reader in bifrost.tryStreamRequest caller code that reads each
emitted chunk or error and calls SetFallbackRoutingInfo(provider, model) before
forwarding it, or alternatively ensure the per-attempt BuildRoutingInfo used by
the streaming post-hook includes the primary provider/model so emitted chunks
already contain the fallback fields; reference tryStreamRequest, result (the
returned chan), and SetFallbackRoutingInfo to locate and implement the change.

In `@core/schemas/account.go`:
- Around line 205-226: AliasConfig currently never includes VLLMAliasCfg and
both VLLMAliasCfg.ModelName and AliasConfig.ModelName share the same json tag,
making the vLLM override unreachable; fix by adding a nested vLLM field to
AliasConfig (e.g., add a pointer field like VLLM *VLLMAliasCfg
`json:"vllm,omitempty"`), leaving AliasConfig.ModelName as the canonical
top-level name, and keep VLLMAliasCfg.ModelName as-is so its JSON becomes
vllm.model_name (no tag rename required), ensuring callers can express the
vLLM-specific override separately from AliasConfig.ModelName.

In `@core/schemas/bifrost.go`:
- Around line 1103-1125: syncDeprecatedFromRoutingInfo currently only overwrites
non-empty branches and can leave prior values in pooled outputs; first clear the
outputs then re-derive them from info: at the top of
syncDeprecatedFromRoutingInfo, if provider != nil set *provider to the zero
value (empty), if originalModelRequested != nil set *originalModelRequested to
"", and if resolvedModelUsed != nil set *resolved_model_used (resolvedModelUsed)
to ""; then run the existing logic that sets provider, originalModelRequested,
and resolvedModelUsed from info so partial RoutingInfo cannot leak prior-request
data.

---

Outside diff comments:
In `@framework/streaming/types.go`:
- Around line 253-459: ToBifrostResponse is not transferring
ProcessedStreamResponse.RoutingInfo into the created BifrostResponse, so routing
metadata is lost; for each branch inside ToBifrostResponse (StreamTypeText,
StreamTypeChat, StreamTypeResponses, StreamTypeAudio, StreamTypeTranscription,
StreamTypeImage) remove setting the deprecated
Provider/OriginalModelRequested/ResolvedModelUsed fields in the ExtraFields
literal and instead call resp.<Xxx>Response.PopulateRoutingInfo(p.RoutingInfo)
immediately after assigning ExtraFields (using the existing PopulateRoutingInfo
helper to stamp RoutingInfo and sync deprecated fields), e.g., after
resp.ChatResponse.ExtraFields = ... call
resp.ChatResponse.PopulateRoutingInfo(p.RoutingInfo); repeat for Text,
Responses, Speech, Transcription, and Image branches within the same
ToBifrostResponse function.
🪄 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: 2e2a89b2-03f2-4b1b-ac60-df226003e56b

📥 Commits

Reviewing files that changed from the base of the PR and between decab23 and 0f1ec91.

📒 Files selected for processing (4)
  • core/bifrost.go
  • core/schemas/account.go
  • core/schemas/bifrost.go
  • framework/streaming/types.go
🛑 Comments failed to post (3)
core/bifrost.go (1)

4851-4858: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Propagate fallback routing info onto successful stream chunks.

Line 4857 only annotates fallbackErr. When the fallback stream succeeds, the returned channel is forwarded unchanged, so chunk metadata never gets routing_info.is_fallback, primary_provider, or primary_model. The later chunk path only uses attempt-scoped BuildRoutingInfo snapshots (for example at Line 6186 and Line 6203), so it cannot recover the primary-attempt attribution afterward. That leaves streaming fallback responses short of the same contract the non-streaming path now provides.

Please either wrap the returned stream here and stamp each emitted response/error chunk with SetFallbackRoutingInfo(provider, model), or thread the primary provider/model into the per-attempt routing snapshot used by the streaming post-hook path so chunk-level serialization can emit the fallback fields directly.

🤖 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 4851 - 4858, The fallback stream path currently
only calls SetFallbackRoutingInfo on fallbackErr and returns the raw result
channel from tryStreamRequest, so successful streamed chunks never receive
routing_info.is_fallback/primary_provider/primary_model; fix by wrapping the
returned channel from tryStreamRequest (the variable result) inside a new
goroutine/chan reader in bifrost.tryStreamRequest caller code that reads each
emitted chunk or error and calls SetFallbackRoutingInfo(provider, model) before
forwarding it, or alternatively ensure the per-attempt BuildRoutingInfo used by
the streaming post-hook includes the primary provider/model so emitted chunks
already contain the fallback fields; reference tryStreamRequest, result (the
returned chan), and SetFallbackRoutingInfo to locate and implement the change.
core/schemas/account.go (1)

205-226: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

VLLMAliasCfg is unreachable in the current schema.

AliasConfig never stores VLLMAliasCfg, and both this type and AliasConfig.ModelName want the same json:"model_name" slot. So a config author cannot represent “canonical model name for pricing/logs” separately from “vLLM backend model override”; the latter is silently impossible to express or validate. Give the vLLM override its own nested field/tag, or rename one of the concepts before shipping this schema.

🤖 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/schemas/account.go` around lines 205 - 226, AliasConfig currently never
includes VLLMAliasCfg and both VLLMAliasCfg.ModelName and AliasConfig.ModelName
share the same json tag, making the vLLM override unreachable; fix by adding a
nested vLLM field to AliasConfig (e.g., add a pointer field like VLLM
*VLLMAliasCfg `json:"vllm,omitempty"`), leaving AliasConfig.ModelName as the
canonical top-level name, and keep VLLMAliasCfg.ModelName as-is so its JSON
becomes vllm.model_name (no tag rename required), ensuring callers can express
the vLLM-specific override separately from AliasConfig.ModelName.
core/schemas/bifrost.go (1)

1103-1125: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Clear the deprecated fields before re-deriving them.

syncDeprecatedFromRoutingInfo only overwrites non-empty branches. If the current RoutingInfo is partial, provider, original_model_requested, and resolved_model_used keep their previous values, so a reused response/error can emit stale routing metadata. Zero these outputs first, then derive them from info.

Suggested fix
 func syncDeprecatedFromRoutingInfo(info RoutingInfo, provider *ModelProvider, originalModelRequested, resolvedModelUsed *string) {
-	if provider != nil && info.Provider != "" {
-		*provider = info.Provider
+	if provider != nil {
+		*provider = ""
+		if info.Provider != "" {
+			*provider = info.Provider
+		}
 	}
@@
 	if originalModelRequested != nil {
+		*originalModelRequested = ""
 		if info.IsFallback && info.PrimaryModel != nil && *info.PrimaryModel != "" {
 			*originalModelRequested = *info.PrimaryModel
 		} else if info.Model != "" {
@@
 	if resolvedModelUsed != nil {
+		*resolvedModelUsed = ""
 		if info.ResolvedKeyAlias != nil && info.ResolvedKeyAlias.ModelID != "" {
 			*resolvedModelUsed = info.ResolvedKeyAlias.ModelID
 		} else if info.Model != "" {

As per coding guidelines, pooled objects must have every field reset before reuse so prior-request data cannot leak forward.

📝 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.

func syncDeprecatedFromRoutingInfo(info RoutingInfo, provider *ModelProvider, originalModelRequested, resolvedModelUsed *string) {
	if provider != nil {
		*provider = ""
		if info.Provider != "" {
			*provider = info.Provider
		}
	}
	// OriginalModelRequested: collapses to the caller-sent model. On a fallback
	// attempt that's the primary's model (the user never asked for the fallback's);
	// otherwise it's this attempt's model.
	if originalModelRequested != nil {
		*originalModelRequested = ""
		if info.IsFallback && info.PrimaryModel != nil && *info.PrimaryModel != "" {
			*originalModelRequested = *info.PrimaryModel
		} else if info.Model != "" {
			*originalModelRequested = info.Model
		}
	}
	// ResolvedModelUsed: the wire model. Alias's ModelID when an alias matched,
	// otherwise the attempt's Model.
	if resolvedModelUsed != nil {
		*resolvedModelUsed = ""
		if info.ResolvedKeyAlias != nil && info.ResolvedKeyAlias.ModelID != "" {
			*resolvedModelUsed = info.ResolvedKeyAlias.ModelID
		} else if info.Model != "" {
			*resolvedModelUsed = info.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/schemas/bifrost.go` around lines 1103 - 1125,
syncDeprecatedFromRoutingInfo currently only overwrites non-empty branches and
can leave prior values in pooled outputs; first clear the outputs then re-derive
them from info: at the top of syncDeprecatedFromRoutingInfo, if provider != nil
set *provider to the zero value (empty), if originalModelRequested != nil set
*originalModelRequested to "", and if resolvedModelUsed != nil set
*resolved_model_used (resolvedModelUsed) to ""; then run the existing logic that
sets provider, originalModelRequested, and resolvedModelUsed from info so
partial RoutingInfo cannot leak prior-request data.

Source: Coding guidelines

@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-03-feat_adds_routinginfo_in_respose_error_extra_fields branch from 0f1ec91 to dd0fa43 Compare June 8, 2026 11:55

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 3

🤖 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 4871-4878: The fallback stream returned from tryStreamRequest is
not being annotated with fallback/primary routing metadata: wrap the returned
stream channel from tryStreamRequest (the variable result) with a forwarding
goroutine that reads each emitted chunk/error, calls
SetFallbackRoutingInfo(provider, model) on the chunk/error (and preserves
existing per-attempt BuildRoutingInfo data), then sends the annotated item to
the client channel; ensure the wrapper also closes the output channel when the
input channel is closed and propagates cancellation; make the same change where
BuildRoutingInfo per-attempt stamping occurs (the block around
BuildRoutingInfo(...) at lines 6206-6239) so any successful fallback streams are
similarly wrapped and annotated before being returned.

In `@core/schemas/account.go`:
- Around line 537-576: Add deterministic, table-driven tests that exercise
KeyAliases.UnmarshalJSON (and the AliasConfig promotion) covering at minimum:
legacy string value (e.g. {"k":"model"} -> AliasConfig{ModelID:"model"}), object
value (e.g. {"k":{"model_id":"model"}}), null input, invalid-type (e.g.
{"k":123} expecting error), and empty-value (e.g. {"k":""} or empty raw message
expecting error). Implement a test function using testing.T with a slice of
cases {name, inputJSON, want KeyAliases or wantErr boolean/substring} and
iterate with t.Run to assert successful unmarshalling yields the expected
KeyAliases and failure cases return errors containing the descriptive text
produced by KeyAliases.UnmarshalJSON (like "empty value" or "value must be a
string"). Ensure you construct expected AliasConfig values for comparisons and
use reflection or cmp to compare results.

In `@core/schemas/bifrost.go`:
- Around line 1103-1197: The problem is that early failures can have the
deprecated provider/original_model_requested/resolved_model_used set while
ef.RoutingInfo stays zero, making routing_info unreliable; fix by ensuring
RoutingInfo is populated when PopulateRoutingInfo runs: in
BifrostResponse.PopulateRoutingInfo and BifrostError.PopulateRoutingInfo (and
when serializing), if the incoming info is zero-valued but the deprecated
triplet (ef.Provider, ef.OriginalModelRequested, ef.ResolvedModelUsed) is set,
synthesize a RoutingInfo from those fields (populate
Provider/Model/ResolvedKeyAlias.ModelID or PrimaryModel/PrimaryProvider as
appropriate) before assigning and calling syncDeprecatedFromRoutingInfo, or
alternatively seed attempt-scoped RoutingInfo earlier in
PopulateExtraFields/request-worker seeding so PopulateRoutingInfo always
receives a non-empty RoutingInfo.
🪄 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: 831bfb8c-2c53-40ac-9363-b5e5021e5ac4

📥 Commits

Reviewing files that changed from the base of the PR and between 0f1ec91 and dd0fa43.

📒 Files selected for processing (4)
  • core/bifrost.go
  • core/schemas/account.go
  • core/schemas/bifrost.go
  • framework/streaming/types.go

@coderabbitai coderabbitai Bot left a comment

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.

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: 3

🤖 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 4871-4878: The fallback stream returned from tryStreamRequest is
not being annotated with fallback/primary routing metadata: wrap the returned
stream channel from tryStreamRequest (the variable result) with a forwarding
goroutine that reads each emitted chunk/error, calls
SetFallbackRoutingInfo(provider, model) on the chunk/error (and preserves
existing per-attempt BuildRoutingInfo data), then sends the annotated item to
the client channel; ensure the wrapper also closes the output channel when the
input channel is closed and propagates cancellation; make the same change where
BuildRoutingInfo per-attempt stamping occurs (the block around
BuildRoutingInfo(...) at lines 6206-6239) so any successful fallback streams are
similarly wrapped and annotated before being returned.

In `@core/schemas/account.go`:
- Around line 537-576: Add deterministic, table-driven tests that exercise
KeyAliases.UnmarshalJSON (and the AliasConfig promotion) covering at minimum:
legacy string value (e.g. {"k":"model"} -> AliasConfig{ModelID:"model"}), object
value (e.g. {"k":{"model_id":"model"}}), null input, invalid-type (e.g.
{"k":123} expecting error), and empty-value (e.g. {"k":""} or empty raw message
expecting error). Implement a test function using testing.T with a slice of
cases {name, inputJSON, want KeyAliases or wantErr boolean/substring} and
iterate with t.Run to assert successful unmarshalling yields the expected
KeyAliases and failure cases return errors containing the descriptive text
produced by KeyAliases.UnmarshalJSON (like "empty value" or "value must be a
string"). Ensure you construct expected AliasConfig values for comparisons and
use reflection or cmp to compare results.

In `@core/schemas/bifrost.go`:
- Around line 1103-1197: The problem is that early failures can have the
deprecated provider/original_model_requested/resolved_model_used set while
ef.RoutingInfo stays zero, making routing_info unreliable; fix by ensuring
RoutingInfo is populated when PopulateRoutingInfo runs: in
BifrostResponse.PopulateRoutingInfo and BifrostError.PopulateRoutingInfo (and
when serializing), if the incoming info is zero-valued but the deprecated
triplet (ef.Provider, ef.OriginalModelRequested, ef.ResolvedModelUsed) is set,
synthesize a RoutingInfo from those fields (populate
Provider/Model/ResolvedKeyAlias.ModelID or PrimaryModel/PrimaryProvider as
appropriate) before assigning and calling syncDeprecatedFromRoutingInfo, or
alternatively seed attempt-scoped RoutingInfo earlier in
PopulateExtraFields/request-worker seeding so PopulateRoutingInfo always
receives a non-empty RoutingInfo.
🪄 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: 831bfb8c-2c53-40ac-9363-b5e5021e5ac4

📥 Commits

Reviewing files that changed from the base of the PR and between 0f1ec91 and dd0fa43.

📒 Files selected for processing (4)
  • core/bifrost.go
  • core/schemas/account.go
  • core/schemas/bifrost.go
  • framework/streaming/types.go
🛑 Comments failed to post (3)
core/bifrost.go (1)

4871-4878: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Successful fallback streams still miss is_fallback / primary_* routing metadata.

Line 4878 returns the fallback stream untouched, while Lines 6206-6239 only stamp per-attempt data from BuildRoutingInfo(...). That means a stream that succeeds on a fallback emits chunks with provider/model/key, but never gets routing_info.is_fallback, primary_provider, or primary_model, so the streaming path does not meet this PR’s fallback observability contract. You need to wrap the returned stream or otherwise inject SetFallbackRoutingInfo(...) into each emitted chunk/error before it reaches the client.

Also applies to: 6206-6239

🤖 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 4871 - 4878, The fallback stream returned from
tryStreamRequest is not being annotated with fallback/primary routing metadata:
wrap the returned stream channel from tryStreamRequest (the variable result)
with a forwarding goroutine that reads each emitted chunk/error, calls
SetFallbackRoutingInfo(provider, model) on the chunk/error (and preserves
existing per-attempt BuildRoutingInfo data), then sends the annotated item to
the client channel; ensure the wrapper also closes the output channel when the
input channel is closed and propagates cancellation; make the same change where
BuildRoutingInfo per-attempt stamping occurs (the block around
BuildRoutingInfo(...) at lines 6206-6239) so any successful fallback streams are
similarly wrapped and annotated before being returned.
core/schemas/account.go (1)

537-576: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Add table-driven tests for the dual-shape alias parser.

This method is now the backward-compat gate for both legacy string aliases and the new object form. Please cover at least string/object/null/invalid-type/empty-value cases before merge.

As per coding guidelines, Go behavior changes should have deterministic, table-driven coverage.

🤖 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/schemas/account.go` around lines 537 - 576, Add deterministic,
table-driven tests that exercise KeyAliases.UnmarshalJSON (and the AliasConfig
promotion) covering at minimum: legacy string value (e.g. {"k":"model"} ->
AliasConfig{ModelID:"model"}), object value (e.g. {"k":{"model_id":"model"}}),
null input, invalid-type (e.g. {"k":123} expecting error), and empty-value (e.g.
{"k":""} or empty raw message expecting error). Implement a test function using
testing.T with a slice of cases {name, inputJSON, want KeyAliases or wantErr
boolean/substring} and iterate with t.Run to assert successful unmarshalling
yields the expected KeyAliases and failure cases return errors containing the
descriptive text produced by KeyAliases.UnmarshalJSON (like "empty value" or
"value must be a string"). Ensure you construct expected AliasConfig values for
comparisons and use reflection or cmp to compare results.

Source: Coding guidelines

core/schemas/bifrost.go (1)

1103-1197: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Don't publish an empty routing_info on early retry/fallback failures.

These helpers only backfill the deprecated triplet from RoutingInfo. On the current error path, core already calls PopulateExtraFields(...) before PopulateRoutingInfo(attemptRoutingInfo), so an early failure can still have provider / original_model_requested / resolved_model_used populated while the new canonical routing_info stays zeroed. That makes routing_info unreliable for exactly the early-attempt failures this feature is trying to surface.

Please land the request-worker seeding of attempt-scoped routing info alongside this schema change, or synthesize the missing RoutingInfo before serializing it.

Based on the fallback/error call sites in core/bifrost.go, PopulateRoutingInfo(attemptRoutingInfo) runs after PopulateExtraFields(...), and the stack context already identifies a separate seed step for early failures.

🤖 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/schemas/bifrost.go` around lines 1103 - 1197, The problem is that early
failures can have the deprecated
provider/original_model_requested/resolved_model_used set while ef.RoutingInfo
stays zero, making routing_info unreliable; fix by ensuring RoutingInfo is
populated when PopulateRoutingInfo runs: in BifrostResponse.PopulateRoutingInfo
and BifrostError.PopulateRoutingInfo (and when serializing), if the incoming
info is zero-valued but the deprecated triplet (ef.Provider,
ef.OriginalModelRequested, ef.ResolvedModelUsed) is set, synthesize a
RoutingInfo from those fields (populate Provider/Model/ResolvedKeyAlias.ModelID
or PrimaryModel/PrimaryProvider as appropriate) before assigning and calling
syncDeprecatedFromRoutingInfo, or alternatively seed attempt-scoped RoutingInfo
earlier in PopulateExtraFields/request-worker seeding so PopulateRoutingInfo
always receives a non-empty RoutingInfo.

@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-03-feat_adds_ui_for_alias_extensions branch from 0645d6f to e0ae82e Compare June 8, 2026 12:24
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-03-feat_adds_routinginfo_in_respose_error_extra_fields branch 2 times, most recently from 48605b5 to d355ea9 Compare June 8, 2026 12:28
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-03-feat_adds_routinginfo_in_respose_error_extra_fields branch from d355ea9 to bdb85c8 Compare June 8, 2026 21:20
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-03-feat_adds_ui_for_alias_extensions branch from 42a7143 to 4715dbd Compare June 8, 2026 21:20

akshaydeo commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Merge activity

  • Jun 9, 5:17 AM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Jun 9, 5:28 AM UTC: @akshaydeo merged this pull request with Graphite.

@akshaydeo
akshaydeo changed the base branch from 06-03-feat_adds_ui_for_alias_extensions to graphite-base/4020 June 9, 2026 05:27
@akshaydeo
akshaydeo changed the base branch from graphite-base/4020 to dev June 9, 2026 05:27
@akshaydeo
akshaydeo merged commit a6da973 into dev Jun 9, 2026
10 of 11 checks passed
@akshaydeo
akshaydeo deleted the 06-03-feat_adds_routinginfo_in_respose_error_extra_fields branch June 9, 2026 05:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants