Skip to content

review fixes#1309

Merged
akshaydeo merged 1 commit intov1.4.0from
01-12-review_fixes
Jan 12, 2026
Merged

review fixes#1309
akshaydeo merged 1 commit intov1.4.0from
01-12-review_fixes

Conversation

@akshaydeo
Copy link
Copy Markdown
Contributor

@akshaydeo akshaydeo commented Jan 12, 2026

Summary

This PR fixes several type safety issues in provider implementations, improves error handling, and enhances stream accumulator thread safety to prevent race conditions.

Fixes

Closes #1306

Changes

  • Added proper type safety checks for Gemini provider's safety settings, labels, and request metadata
  • Fixed empty string check for Anthropic instructions parameter
  • Added mutex locks to stream accumulator methods to prevent race conditions
  • Improved deferred span cleanup to ensure proper resource release even during panics
  • Enhanced string map extraction with a new utility function SafeExtractStringMap
  • Updated file base64 test to use scenario-specific retry configuration
  • Fixed Gemini speech handler to safely check for nil params
  • Added proper cleanup for deferred spans and stream accumulators

Type of change

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

Affected areas

  • Core (Go)
  • Transports (HTTP)
  • Providers/Integrations
  • Plugins
  • UI (Next.js)
  • Docs

How to test

# Core/Transports
go version
go test ./...

# Test specific providers
go test ./core/providers/gemini/...
go test ./core/providers/anthropic/...
go test ./core/providers/bedrock/...

# Test streaming functionality
go test ./framework/streaming/...

Breaking changes

  • Yes
  • No

Related issues

Fixes type safety issues and race conditions in stream processing.

Security considerations

Improves type safety which helps prevent potential security issues from unexpected data types.

Checklist

  • I added/updated tests where appropriate
  • I verified builds succeed (Go and UI)
  • I verified the CI pipeline passes locally if applicable

Copy link
Copy Markdown
Contributor Author

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

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 12, 2026

📝 Walkthrough

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced OpenAI model listing functionality with additional metadata support including ownership and creation information.
  • Bug Fixes

    • Fixed potential crashes in speech request handling when configuration data is missing.
    • Improved numeric precision in pricing information display across inference endpoints.
  • Documentation

    • Clarified that WASM plugins do not support streaming functionality.
  • Chores

    • Improved system robustness through enhanced type safety and concurrent access protections.

✏️ Tip: You can customize this high-level summary in your review settings.

Walkthrough

Applies safer runtime extraction and per-scenario retry config, tightens nil/empty guards, and adds mutex synchronization to streaming accumulators and getters; also introduces OpenAI model conversion helpers and increases pricing output precision formatting.

Changes

Cohort / File(s) Summary
Streaming synchronization
framework/streaming/accumulator.go, framework/streaming/types.go, plugins/semanticcache/stream.go
Adds mu sync.Mutex to StreamAccumulator, initializes the mutex on creation, and wraps several getter methods with mu locks to prevent concurrent read/write races.
Safe extraction utilities
core/schemas/utils.go, core/providers/gemini/types.go
Adds SafeExtractStringMap and SafeExtractSafetySettings helpers (handle direct and JSON-deserialized shapes) and extends SafeExtractOrderedMap support; used to avoid unsafe type assertions.
Provider replacements of direct assertions
core/providers/gemini/chat.go, core/providers/gemini/responses.go, core/providers/gemini/transcription.go, core/providers/bedrock/utils.go
Replace direct type assertions for safety settings, labels, and request metadata with the new safe extraction helpers.
Defensive nil/empty guards
core/providers/gemini/gemini.go, core/providers/anthropic/responses.go
Add nil-check before accessing request.Params in Gemini speech path and require non-empty Instructions when deriving system content for Anthropic responses.
Dynamic retry construction
core/internal/testutil/file_base64.go
Replace static FileInputResponsesRetryConfig() with construction based on GetTestRetryConfigForScenario("FileInput", testConfig), wiring MaxAttempts/BaseDelay/MaxDelay/OnRetry/OnFinalFail.
OpenAI models conversion & types
core/providers/openai/types.go, core/providers/openai/models.go
Add OwnedBy, Created, Active fields to OpenAIModel, new OpenAIListModelsResponse type, and conversion helpers ToBifrostListModelsResponse and ToOpenAIListModelsResponse.
Pricing precision formatting
transports/bifrost-http/handlers/inference.go
Increase numeric precision in listModels output: use %.10f for token/image/cache pricing formatting.
Test behavior tweak
plugins/governance/advancedscenarios_test.go
Add budgetExhausted flag and assert that hierarchical budget exhaustion occurred during the exhaustion loop.
Minor comment/doc updates
core/schemas/plugin_wasm.go, core/providers/utils/utils.go
Clarify WASM plugin streaming not supported; minor comment-only change in post-hook timing.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Poem

🐰
I hop through code with mutex cheer,
Safe extracts and guards appear.
Retries tuned per test I bring,
Prices precise — hear the spring!
A little rabbit, fixing things!

🚥 Pre-merge checks | ✅ 2 | ❌ 3
❌ Failed checks (1 warning, 2 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 78.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'review fixes' is too vague and generic to convey meaningful information about the changeset. Use a more descriptive title that captures the main focus, such as 'Fix type safety and add stream synchronization' or 'Improve provider type checks and stream accumulator thread safety'.
Out of Scope Changes check ❓ Inconclusive While most changes align with the stated objectives, some modifications (e.g., SafeExtractSafetySettings, mutex locking) appear to exceed the scope of the pricing precision bug fix in #1306.
✅ Passed checks (2 passed)
Check name Status Explanation
Description check ✅ Passed The PR description includes all required sections: Summary, Changes, Type of change, Affected areas, How to test, Breaking changes, Related issues, Security considerations, and Checklist completion.
Linked Issues check ✅ Passed The PR addresses the pricing precision issue in #1306 by changing float formatting from %f to %.10f in transports/bifrost-http/handlers/inference.go.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 01-12-review_fixes

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

@akshaydeo akshaydeo marked this pull request as ready for review January 12, 2026 07:54
Comment thread core/providers/utils/utils.go Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (2)
core/providers/utils/utils.go (1)

1623-1624: Redundant cleanup call - already handled by defer.

ClearDeferredSpan is already called via defer at line 1564, so this explicit call at line 1624 results in double invocation. The defer pattern alone is sufficient and preferable for cleanup.

🔧 Suggested fix - remove redundant call
 	} else {
 		tracer.EndSpan(handle, schemas.SpanStatusOk, "")
 	}
-
-	// Clear the deferred span from TraceStore
-	tracer.ClearDeferredSpan(traceID)
 }
framework/streaming/accumulator.go (1)

140-147: Fix non-atomic get-or-create to avoid duplicate accumulators under concurrency.

Load() + create() + Store() can return different *StreamAccumulators to concurrent callers for the same requestID, which breaks accumulation / ref-counting / cleanup correctness. Prefer LoadOrStore.

Proposed fix
 func (a *Accumulator) createStreamAccumulator(requestID string) *StreamAccumulator {
 	now := time.Now()
 	sc := &StreamAccumulator{
 		RequestID:                  requestID,
 		ChatStreamChunks:           make([]*ChatStreamChunk, 0),
 		ResponsesStreamChunks:      make([]*ResponsesStreamChunk, 0),
 		TranscriptionStreamChunks:  make([]*TranscriptionStreamChunk, 0),
 		AudioStreamChunks:          make([]*AudioStreamChunk, 0),
 		ChatChunksSeen:             make(map[int]struct{}),
 		ResponsesChunksSeen:        make(map[int]struct{}),
 		TranscriptionChunksSeen:    make(map[int]struct{}),
 		AudioChunksSeen:            make(map[int]struct{}),
 		MaxChatChunkIndex:          -1,
 		MaxResponsesChunkIndex:     -1,
 		MaxTranscriptionChunkIndex: -1,
 		MaxAudioChunkIndex:         -1,
 		IsComplete:                 false,
-		mu:                         sync.Mutex{},
 		Timestamp:                  now,
 		StartTimestamp:             now, // Set default StartTimestamp for proper TTFT/latency calculation
 	}
-	a.streamAccumulators.Store(requestID, sc)
 	return sc
 }
 
 func (a *Accumulator) getOrCreateStreamAccumulator(requestID string) *StreamAccumulator {
 	if accumulator, exists := a.streamAccumulators.Load(requestID); exists {
 		return accumulator.(*StreamAccumulator)
 	}
-	// Create new accumulator if it doesn't exist
-	return a.createStreamAccumulator(requestID)
+	// Create new accumulator if it doesn't exist (atomically)
+	sc := a.createStreamAccumulator(requestID)
+	actual, loaded := a.streamAccumulators.LoadOrStore(requestID, sc)
+	if loaded {
+		return actual.(*StreamAccumulator)
+	}
+	return sc
 }
🤖 Fix all issues with AI agents
In @core/schemas/plugin_wasm.go:
- Around line 6-7: The top-of-file comment in core/schemas/plugin_wasm.go
contains a minor grammar issue: remove the extra double space and insert "or"
between the two variants so the sentence reads something like "It can contain
either a response (success short-circuit) or an error (error short-circuit).
Streams are not supported in WASM plugins."; update that comment accordingly.
🧹 Nitpick comments (3)
plugins/governance/advancedscenarios_test.go (1)

458-497: LGTM! Explicit budget exhaustion tracking improves test reliability.

The addition of the budgetExhausted flag to explicitly track whether a budget rejection was observed is a solid improvement. This approach is more reliable than inferring exhaustion from consumed amounts, which could be affected by cost calculation discrepancies.

Consider using sawBudgetRejection for naming consistency with the other tests in this file (e.g., TestVKBudgetUpdateAfterExhaustion at line 576, TestTeamBudgetUpdateAfterExhaustion at line 717). This is a minor nit and not required.

framework/streaming/accumulator.go (1)

113-138: mu: sync.Mutex{} initialization is redundant (but OK).

Go mutexes are usable as a zero value, so this explicit init isn’t required; keep it only if you want the clarity.

plugins/semanticcache/stream.go (1)

30-38: Consider LoadOrStore to make plugin accumulator creation atomic.

If getOrCreateStreamAccumulator can be hit concurrently per requestID, switch to LoadOrStore to avoid duplicate accumulators (same race as framework/streaming/accumulator.go).

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0a5f2af and 0649267.

📒 Files selected for processing (15)
  • core/internal/testutil/file_base64.go
  • core/providers/anthropic/responses.go
  • core/providers/bedrock/utils.go
  • core/providers/gemini/chat.go
  • core/providers/gemini/gemini.go
  • core/providers/gemini/responses.go
  • core/providers/gemini/transcription.go
  • core/providers/gemini/types.go
  • core/providers/utils/utils.go
  • core/schemas/plugin_wasm.go
  • core/schemas/utils.go
  • framework/streaming/accumulator.go
  • framework/streaming/types.go
  • plugins/governance/advancedscenarios_test.go
  • plugins/semanticcache/stream.go
🧰 Additional context used
📓 Path-based instructions (1)
**

⚙️ CodeRabbit configuration file

always check the stack if there is one for the current PR. do not give localized reviews for the PR, always see all changes in the light of the whole stack of PRs (if there is a stack, if there is no stack you can continue to make localized suggestions/reviews)

Files:

  • core/providers/bedrock/utils.go
  • core/providers/gemini/gemini.go
  • core/providers/gemini/types.go
  • framework/streaming/accumulator.go
  • core/providers/gemini/transcription.go
  • core/providers/gemini/chat.go
  • framework/streaming/types.go
  • core/internal/testutil/file_base64.go
  • plugins/governance/advancedscenarios_test.go
  • core/providers/gemini/responses.go
  • core/providers/utils/utils.go
  • plugins/semanticcache/stream.go
  • core/schemas/plugin_wasm.go
  • core/providers/anthropic/responses.go
  • core/schemas/utils.go
🧠 Learnings (10)
📚 Learning: 2025-12-09T17:07:42.007Z
Learnt from: qwerty-dvorak
Repo: maximhq/bifrost PR: 1006
File: core/schemas/account.go:9-18
Timestamp: 2025-12-09T17:07:42.007Z
Learning: In core/schemas/account.go, the HuggingFaceKeyConfig field within the Key struct is currently unused and reserved for future Hugging Face inference endpoint deployments. Do not flag this field as missing from OpenAPI documentation or require its presence in the API spec until the feature is actively implemented and used. When the feature is added, update the OpenAPI docs accordingly; otherwise, treat this field as non-breaking and not part of the current API surface.

Applied to files:

  • core/providers/bedrock/utils.go
  • core/providers/gemini/gemini.go
  • core/providers/gemini/types.go
  • framework/streaming/accumulator.go
  • core/providers/gemini/transcription.go
  • core/providers/gemini/chat.go
  • framework/streaming/types.go
  • core/internal/testutil/file_base64.go
  • plugins/governance/advancedscenarios_test.go
  • core/providers/gemini/responses.go
  • core/providers/utils/utils.go
  • plugins/semanticcache/stream.go
  • core/schemas/plugin_wasm.go
  • core/providers/anthropic/responses.go
  • core/schemas/utils.go
📚 Learning: 2025-12-29T11:54:55.836Z
Learnt from: akshaydeo
Repo: maximhq/bifrost PR: 1153
File: framework/configstore/rdb.go:2221-2246
Timestamp: 2025-12-29T11:54:55.836Z
Learning: In Go reviews, do not flag range-over-int patterns like for i := range n as compile-time errors, assuming Go 1.22+ semantics. Only flag actual range-capable values (slices, arrays, maps, channels, strings) and other compile-time issues. This applies to all Go files across the repository.

Applied to files:

  • core/providers/bedrock/utils.go
  • core/providers/gemini/gemini.go
  • core/providers/gemini/types.go
  • framework/streaming/accumulator.go
  • core/providers/gemini/transcription.go
  • core/providers/gemini/chat.go
  • framework/streaming/types.go
  • core/internal/testutil/file_base64.go
  • plugins/governance/advancedscenarios_test.go
  • core/providers/gemini/responses.go
  • core/providers/utils/utils.go
  • plugins/semanticcache/stream.go
  • core/schemas/plugin_wasm.go
  • core/providers/anthropic/responses.go
  • core/schemas/utils.go
📚 Learning: 2025-12-19T09:26:54.961Z
Learnt from: qwerty-dvorak
Repo: maximhq/bifrost PR: 1006
File: core/providers/utils/utils.go:1050-1051
Timestamp: 2025-12-19T09:26:54.961Z
Learning: Update streaming end-marker handling so HuggingFace is treated as a non-[DONE] provider for backends that do not emit a DONE marker (e.g., meta llama on novita). In core/providers/utils/utils.go, adjust ProviderSendsDoneMarker() (or related logic) to detect providers that may not emit DONE and avoid relying on DONE as the sole end signal. Add tests to cover both DONE-emitting and non-DONE backends, with clear documentation in code comments explaining the rationale and any fallback behavior.

Applied to files:

  • core/providers/bedrock/utils.go
  • core/providers/gemini/gemini.go
  • core/providers/gemini/types.go
  • core/providers/gemini/transcription.go
  • core/providers/gemini/chat.go
  • core/providers/gemini/responses.go
  • core/providers/utils/utils.go
  • core/providers/anthropic/responses.go
📚 Learning: 2025-12-26T05:46:14.625Z
Learnt from: TejasGhatte
Repo: maximhq/bifrost PR: 1172
File: core/providers/bedrock/responses.go:2929-2985
Timestamp: 2025-12-26T05:46:14.625Z
Learning: In Bedrock file handling (core/providers/bedrock/responses.go and utils.go), ensure that the FileData field is treated as either a proper data URL (prefix 'data:') or as plain text. Do not expect or accept naked base64-encoded strings without the data URL prefix. The code should first check for the data URL prefix; if missing, process the value as plain text. This pattern applies to all Go files in the bedrock provider directory.

Applied to files:

  • core/providers/bedrock/utils.go
📚 Learning: 2026-01-10T11:27:47.535Z
Learnt from: Radheshg04
Repo: maximhq/bifrost PR: 1256
File: core/providers/openai/openai.go:2276-2385
Timestamp: 2026-01-10T11:27:47.535Z
Learning: Validate image generation requests for nil and missing prompts before dispatch. Follow the same pattern used here: core/bifrost.go validates nil/empty prompts, providerUtils.CheckContextAndGetRequestBody returns a structured error when the request converter yields nil, and apply this across all providers (including OpenAI) to avoid sending null bodies.

Applied to files:

  • core/providers/bedrock/utils.go
  • core/providers/gemini/gemini.go
  • core/providers/gemini/types.go
  • core/providers/gemini/transcription.go
  • core/providers/gemini/chat.go
  • core/providers/gemini/responses.go
  • core/providers/utils/utils.go
  • core/providers/anthropic/responses.go
📚 Learning: 2025-12-19T08:29:20.286Z
Learnt from: qwerty-dvorak
Repo: maximhq/bifrost PR: 1095
File: core/internal/testutil/count_tokens.go:30-67
Timestamp: 2025-12-19T08:29:20.286Z
Learning: In core/internal/testutil test files, enforce using GetTestRetryConfigForScenario() to obtain a generic retry config, then construct a typed retry config (e.g., CountTokensRetryConfig, EmbeddingRetryConfig, TranscriptionRetryConfig) with an empty Conditions slice. Copy only MaxAttempts, BaseDelay, MaxDelay, OnRetry, and OnFinalFail from the generic config. This convention should be consistently applied across all test files in this directory.

Applied to files:

  • core/internal/testutil/file_base64.go
📚 Learning: 2025-12-22T10:50:40.990Z
Learnt from: Pratham-Mishra04
Repo: maximhq/bifrost PR: 1154
File: plugins/governance/store.go:1165-1186
Timestamp: 2025-12-22T10:50:40.990Z
Learning: In the Bifrost governance plugin, budgets and rate limits have 1:1 relationships with their parent entities (virtual keys, teams, customers). Do not assume sharing; ensure cascade deletion logic only deletes budgets/rate limits when there are no shared references. Enforce invariants in code and add tests to verify no cross-entity sharing and that cascade deletes only remove the specific child of the parent. If a counterexample arises, adjust data model or add guards.

Applied to files:

  • plugins/governance/advancedscenarios_test.go
📚 Learning: 2026-01-10T15:52:10.995Z
Learnt from: akshaydeo
Repo: maximhq/bifrost PR: 1298
File: core/providers/utils/utils.go:983-1006
Timestamp: 2026-01-10T15:52:10.995Z
Learning: In Go with fasthttp v1.68.0, Response.BodyStream() returns an io.Reader, but the concrete type also implements io.Closer. In reviews, consider adding a safe type assertion pattern to close the stream when possible, e.g. if closer, ok := bodyStream.(io.Closer); ok { if err := closer.Close(); err != nil { // handle } }. This check should be applied in all code paths where BodyStream() is consumed, not only in this specific file, to ensure proper resource cleanup when the underlying reader supports closing.

Applied to files:

  • core/providers/utils/utils.go
📚 Learning: 2026-01-11T14:08:10.341Z
Learnt from: Pratham-Mishra04
Repo: maximhq/bifrost PR: 1298
File: core/providers/anthropic/anthropic.go:682-699
Timestamp: 2026-01-11T14:08:10.341Z
Learning: In Anthroplic streaming implementations (and analogous providers), ensure that the final 'summary' chunk, which carries usage information and metadata, is emitted after all delta chunks and uses a chunk index of last_delta_index + 1. This differentiates the summary chunk from content delta chunks. Apply this convention consistently in the anthropic provider code and in similar streaming providers, and consider adding a targeted test to assert the ordering and chunk index logic.

Applied to files:

  • core/providers/anthropic/responses.go
📚 Learning: 2026-01-12T06:41:13.643Z
Learnt from: TejasGhatte
Repo: maximhq/bifrost PR: 1153
File: core/schemas/utils.go:1159-1183
Timestamp: 2026-01-12T06:41:13.643Z
Learning: In core/schemas/utils.go, IsGrokReasoningModel (and the grokReasoningModels list) is the canonical utility for model matching. Treat it as the source of truth and not as a duplicate; if extending model support, update this file rather than introducing separate matching logic, and verify changes here to avoid diverging behavior.

Applied to files:

  • core/schemas/utils.go
🧬 Code graph analysis (5)
core/providers/bedrock/utils.go (1)
core/schemas/utils.go (1)
  • SafeExtractStringMap (527-547)
core/providers/gemini/transcription.go (2)
core/providers/gemini/types.go (1)
  • SafeExtractSafetySettings (103-133)
core/schemas/utils.go (1)
  • SafeExtractStringMap (527-547)
core/providers/gemini/chat.go (2)
core/providers/gemini/types.go (1)
  • SafeExtractSafetySettings (103-133)
core/schemas/utils.go (1)
  • SafeExtractStringMap (527-547)
core/internal/testutil/file_base64.go (1)
core/internal/testutil/test_retry_framework.go (3)
  • GetTestRetryConfigForScenario (1186-1222)
  • ResponsesRetryConfig (212-219)
  • ResponsesRetryCondition (138-141)
core/providers/gemini/responses.go (1)
core/providers/gemini/types.go (1)
  • SafeExtractSafetySettings (103-133)
🔇 Additional comments (12)
core/providers/anthropic/responses.go (1)

1505-1516: LGTM! Good defensive check for empty instructions.

The added *bifrostReq.Params.Instructions != "" check correctly prevents empty instruction strings from being converted into Anthropic system messages with empty text content. This avoids sending unnecessary empty system content blocks to the API.

Verify if similar patterns exist elsewhere that might benefit from the same empty string guard:

#!/bin/bash
# Search for similar instruction handling patterns that might need empty string checks
rg -n -A3 -B3 'Instructions\s*!=\s*nil' --type=go -g '!*_test.go' | head -80
core/providers/utils/utils.go (1)

1563-1566: LGTM on adding deferred cleanup for panic safety.

The defer statements ensure cleanup executes even if downstream code panics, which is a good defensive pattern.

core/schemas/utils.go (1)

525-547: LGTM!

The SafeExtractStringMap implementation is well-structured:

  • Handles both direct map[string]string and JSON-deserialized map[string]interface{} cases.
  • Properly fails fast if any value cannot be converted to string.
  • Follows the established pattern of other SafeExtract* utilities in this file.
core/providers/bedrock/utils.go (1)

278-282: LGTM!

Using SafeExtractStringMap instead of a direct type assertion improves type safety by gracefully handling both map[string]string and JSON-deserialized map[string]interface{} inputs. This aligns with the broader pattern of safe extraction utilities being adopted across providers.

core/internal/testutil/file_base64.go (1)

207-215: LGTM!

This change aligns with the established test convention of using GetTestRetryConfigForScenario() to obtain scenario-specific retry parameters, then constructing a typed ResponsesRetryConfig with an empty Conditions slice. This makes the Responses API test consistent with the Chat Completions test pattern already present in lines 99 and 127-134.

Based on learnings, this is the expected pattern for test files in this directory.

plugins/semanticcache/stream.go (1)

14-28: Mutex addition is good; explicit sync.Mutex{} init is optional.

The new mu field enables safe locking around accumulator mutations; the explicit sync.Mutex{} initializer can be omitted (zero value works).

core/providers/gemini/gemini.go (1)

1035-1037: Good nil-guard for request.Params in Speech.

This prevents a potential panic when Params is absent.

core/providers/gemini/transcription.go (1)

114-133: Safer ExtraParams parsing is a clear improvement; add coverage for mixed-type inputs.

Please ensure tests cover:

  • safety_settings coming in as []interface{} of map[string]any
  • labels coming in as map[string]any (and that invalid value types fail safely without panic)
core/providers/gemini/responses.go (1)

123-128: Good replacement of unsafe assertion with SafeExtractSafetySettings.

Please confirm there’s test coverage for ExtraParams["safety_settings"] arriving as []interface{} (e.g., from JSON/wasm) so we don’t regress silently.

core/providers/gemini/types.go (1)

101-133: LGTM! Well-structured safe extraction utility.

The function correctly handles multiple input types (direct []SafetySetting and JSON-deserialized []interface{}), with proper nil checks and type assertions. The pattern aligns well with SafeExtractStringMap in core/schemas/utils.go.

One observation: if a map[string]interface{} item has none of the expected keys (method, category, threshold), an empty SafetySetting{} will still be appended. This is likely acceptable since the fields are optional per the struct definition, but worth noting for documentation purposes.

core/providers/gemini/chat.go (1)

39-55: LGTM! Type safety improvements using centralized extraction utilities.

The changes replace direct type assertions with the safer SafeExtractSafetySettings and schemas.SafeExtractStringMap functions. This prevents potential panics from unexpected input types (e.g., JSON-deserialized []interface{} vs. direct []SafetySetting) and aligns with similar updates in transcription.go and responses.go.

framework/streaming/types.go (1)

126-183: Thread-safety is correctly implemented throughout.

The getter methods properly guard read access with mutex locks. Verification confirms that all write operations—appending to chunk slices and updating MaxXxxChunkIndex fields—also acquire the same mutex in addChatStreamChunk, addTranscriptionStreamChunk, addAudioStreamChunk, and addResponsesStreamChunk. The defer pattern ensures safe cleanup on early returns. Complete thread-safety is achieved.

Comment thread core/schemas/plugin_wasm.go
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @core/providers/openai/models.go:
- Around line 40-42: The response struct OpenAIListModelsResponse is missing the
required Object field value per the OpenAI spec; set Object to "list" when
constructing openaiResponse (e.g., initialize OpenAIListModelsResponse with
Object: "list" and Data: make(...), or assign openaiResponse.Object = "list"
after creation) so the returned payload includes the correct Object value.
🧹 Nitpick comments (1)
plugins/governance/advancedscenarios_test.go (1)

458-458: Improved test reliability with explicit budget exhaustion tracking.

The addition of the budgetExhausted flag provides a more robust assertion than relying on consumedBudget comparison. This directly verifies that the server returned a budget rejection, which is the actual behavior under test.

Minor consistency note: other similar tests in this file use sawBudgetRejection as the variable name (e.g., lines 576, 717, 876). Consider using consistent naming across tests for maintainability, though this is not blocking.

♻️ Optional: Rename for consistency with other tests
-	budgetExhausted := false
+	sawBudgetRejection := false
-			budgetExhausted = true
+			sawBudgetRejection = true
-	if !budgetExhausted {
+	if !sawBudgetRejection {
 		t.Fatalf("Budget should have been exhausted within 150 requests, but no budget rejection was observed (consumed: $%.6f)", consumedBudget)
 	}

Also applies to: 475-475, 495-497

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0649267 and bec61ed.

📒 Files selected for processing (18)
  • core/internal/testutil/file_base64.go
  • core/providers/anthropic/responses.go
  • core/providers/bedrock/utils.go
  • core/providers/gemini/chat.go
  • core/providers/gemini/gemini.go
  • core/providers/gemini/responses.go
  • core/providers/gemini/transcription.go
  • core/providers/gemini/types.go
  • core/providers/openai/models.go
  • core/providers/openai/types.go
  • core/providers/utils/utils.go
  • core/schemas/plugin_wasm.go
  • core/schemas/utils.go
  • framework/streaming/accumulator.go
  • framework/streaming/types.go
  • plugins/governance/advancedscenarios_test.go
  • plugins/semanticcache/stream.go
  • transports/bifrost-http/handlers/inference.go
✅ Files skipped from review due to trivial changes (1)
  • core/providers/utils/utils.go
🚧 Files skipped from review as they are similar to previous changes (11)
  • core/providers/anthropic/responses.go
  • framework/streaming/accumulator.go
  • core/providers/gemini/types.go
  • core/providers/bedrock/utils.go
  • core/internal/testutil/file_base64.go
  • core/schemas/utils.go
  • core/providers/gemini/gemini.go
  • core/schemas/plugin_wasm.go
  • plugins/semanticcache/stream.go
  • core/providers/gemini/responses.go
  • framework/streaming/types.go
🧰 Additional context used
📓 Path-based instructions (1)
**

⚙️ CodeRabbit configuration file

always check the stack if there is one for the current PR. do not give localized reviews for the PR, always see all changes in the light of the whole stack of PRs (if there is a stack, if there is no stack you can continue to make localized suggestions/reviews)

Files:

  • core/providers/gemini/chat.go
  • transports/bifrost-http/handlers/inference.go
  • core/providers/gemini/transcription.go
  • core/providers/openai/types.go
  • plugins/governance/advancedscenarios_test.go
  • core/providers/openai/models.go
🧠 Learnings (9)
📚 Learning: 2025-12-09T17:07:42.007Z
Learnt from: qwerty-dvorak
Repo: maximhq/bifrost PR: 1006
File: core/schemas/account.go:9-18
Timestamp: 2025-12-09T17:07:42.007Z
Learning: In core/schemas/account.go, the HuggingFaceKeyConfig field within the Key struct is currently unused and reserved for future Hugging Face inference endpoint deployments. Do not flag this field as missing from OpenAPI documentation or require its presence in the API spec until the feature is actively implemented and used. When the feature is added, update the OpenAPI docs accordingly; otherwise, treat this field as non-breaking and not part of the current API surface.

Applied to files:

  • core/providers/gemini/chat.go
  • transports/bifrost-http/handlers/inference.go
  • core/providers/gemini/transcription.go
  • core/providers/openai/types.go
  • plugins/governance/advancedscenarios_test.go
  • core/providers/openai/models.go
📚 Learning: 2025-12-29T11:54:55.836Z
Learnt from: akshaydeo
Repo: maximhq/bifrost PR: 1153
File: framework/configstore/rdb.go:2221-2246
Timestamp: 2025-12-29T11:54:55.836Z
Learning: In Go reviews, do not flag range-over-int patterns like for i := range n as compile-time errors, assuming Go 1.22+ semantics. Only flag actual range-capable values (slices, arrays, maps, channels, strings) and other compile-time issues. This applies to all Go files across the repository.

Applied to files:

  • core/providers/gemini/chat.go
  • transports/bifrost-http/handlers/inference.go
  • core/providers/gemini/transcription.go
  • core/providers/openai/types.go
  • plugins/governance/advancedscenarios_test.go
  • core/providers/openai/models.go
📚 Learning: 2025-12-19T09:26:54.961Z
Learnt from: qwerty-dvorak
Repo: maximhq/bifrost PR: 1006
File: core/providers/utils/utils.go:1050-1051
Timestamp: 2025-12-19T09:26:54.961Z
Learning: Update streaming end-marker handling so HuggingFace is treated as a non-[DONE] provider for backends that do not emit a DONE marker (e.g., meta llama on novita). In core/providers/utils/utils.go, adjust ProviderSendsDoneMarker() (or related logic) to detect providers that may not emit DONE and avoid relying on DONE as the sole end signal. Add tests to cover both DONE-emitting and non-DONE backends, with clear documentation in code comments explaining the rationale and any fallback behavior.

Applied to files:

  • core/providers/gemini/chat.go
  • core/providers/gemini/transcription.go
  • core/providers/openai/types.go
  • core/providers/openai/models.go
📚 Learning: 2026-01-10T11:27:47.535Z
Learnt from: Radheshg04
Repo: maximhq/bifrost PR: 1256
File: core/providers/openai/openai.go:2276-2385
Timestamp: 2026-01-10T11:27:47.535Z
Learning: Validate image generation requests for nil and missing prompts before dispatch. Follow the same pattern used here: core/bifrost.go validates nil/empty prompts, providerUtils.CheckContextAndGetRequestBody returns a structured error when the request converter yields nil, and apply this across all providers (including OpenAI) to avoid sending null bodies.

Applied to files:

  • core/providers/gemini/chat.go
  • core/providers/gemini/transcription.go
  • core/providers/openai/types.go
  • core/providers/openai/models.go
📚 Learning: 2025-12-12T08:25:02.629Z
Learnt from: Pratham-Mishra04
Repo: maximhq/bifrost PR: 1000
File: transports/bifrost-http/integrations/router.go:709-712
Timestamp: 2025-12-12T08:25:02.629Z
Learning: In transports/bifrost-http/**/*.go, update streaming response handling to align with OpenAI Responses API: use typed SSE events such as response.created, response.output_text.delta, response.done, etc., and do not rely on the legacy data: [DONE] termination marker. Note that data: [DONE] is only used by the older Chat Completions and Text Completions streaming APIs. Ensure parsers, writers, and tests distinguish SSE events from the [DONE] sentinel and handle each event type accordingly for correct stream termination and progress updates.

Applied to files:

  • transports/bifrost-http/handlers/inference.go
📚 Learning: 2025-12-29T09:14:16.633Z
Learnt from: akshaydeo
Repo: maximhq/bifrost PR: 888
File: transports/bifrost-http/handlers/middlewares.go:246-256
Timestamp: 2025-12-29T09:14:16.633Z
Learning: In the bifrost HTTP transport, fasthttp.RequestCtx is the primary context carrier and should be passed directly to functions that expect a context.Context. Do not convert to context.Context unless explicitly required. Ensure tracer implementations and related components are designed to accept fasthttp.RequestCtx directly, and document this architectural decision for maintainers.

Applied to files:

  • transports/bifrost-http/handlers/inference.go
📚 Learning: 2025-12-11T11:58:25.307Z
Learnt from: Pratham-Mishra04
Repo: maximhq/bifrost PR: 1000
File: core/providers/openai/responses.go:42-84
Timestamp: 2025-12-11T11:58:25.307Z
Learning: In core/providers/openai/responses.go (and related OpenAI response handling), document and enforce the API format constraint: if ResponsesReasoning != nil and the response contains content blocks, all content blocks should be treated as reasoning blocks by default. Implement type guards or parsing logic accordingly, and add unit tests to verify that when ResponsesReasoning is non-nil, content blocks are labeled as reasoning blocks. Include clear comments in the code explaining the rationale and ensure downstream consumers rely on this behavior.

Applied to files:

  • core/providers/openai/types.go
  • core/providers/openai/models.go
📚 Learning: 2025-12-14T14:43:30.902Z
Learnt from: Radheshg04
Repo: maximhq/bifrost PR: 980
File: core/providers/openai/images.go:10-22
Timestamp: 2025-12-14T14:43:30.902Z
Learning: Enforce the OpenAI image generation SSE event type values across the OpenAI image flow in the repository: use "image_generation.partial_image" for partial chunks, "image_generation.completed" for the final result, and "error" for errors. Apply this consistently in schemas, constants, tests, accumulator routing, and UI code within core/providers/openai (and related Go files) to ensure uniform event typing and avoid mismatches.

Applied to files:

  • core/providers/openai/types.go
  • core/providers/openai/models.go
📚 Learning: 2025-12-22T10:50:40.990Z
Learnt from: Pratham-Mishra04
Repo: maximhq/bifrost PR: 1154
File: plugins/governance/store.go:1165-1186
Timestamp: 2025-12-22T10:50:40.990Z
Learning: In the Bifrost governance plugin, budgets and rate limits have 1:1 relationships with their parent entities (virtual keys, teams, customers). Do not assume sharing; ensure cascade deletion logic only deletes budgets/rate limits when there are no shared references. Enforce invariants in code and add tests to verify no cross-entity sharing and that cascade deletes only remove the specific child of the parent. If a counterexample arises, adjust data model or add guards.

Applied to files:

  • plugins/governance/advancedscenarios_test.go
🧬 Code graph analysis (3)
core/providers/gemini/chat.go (2)
core/providers/gemini/types.go (1)
  • SafeExtractSafetySettings (103-133)
core/schemas/utils.go (1)
  • SafeExtractStringMap (527-547)
transports/bifrost-http/handlers/inference.go (2)
core/schemas/utils.go (1)
  • Ptr (14-16)
core/utils.go (1)
  • Ptr (56-58)
core/providers/gemini/transcription.go (2)
core/providers/gemini/types.go (1)
  • SafeExtractSafetySettings (103-133)
core/schemas/utils.go (1)
  • SafeExtractStringMap (527-547)
🔇 Additional comments (7)
core/providers/gemini/transcription.go (2)

117-121: LGTM! Proper use of safe extraction for safety settings.

The change from direct type assertion to SafeExtractSafetySettings handles multiple input types ([]SafetySetting and []interface{}) and prevents panics from malformed data. This is consistent with the same pattern applied in chat.go.


129-133: LGTM! Consistent safe extraction for labels.

Using schemas.SafeExtractStringMap correctly handles both map[string]string and map[string]interface{} inputs, providing robust conversion with graceful failure handling.

core/providers/gemini/chat.go (2)

39-43: LGTM! Safe extraction prevents runtime panics.

Replacing direct type assertion with SafeExtractSafetySettings is the correct approach. The helper function (from types.go:102-132) handles both native []SafetySetting and JSON-deserialized []interface{} inputs, which is essential when data passes through different serialization layers.


51-55: LGTM! Consistent with transcription.go and other Gemini handlers.

The schemas.SafeExtractStringMap helper ensures that labels can be extracted whether they come as map[string]string or map[string]interface{}, providing resilience against type variations from JSON unmarshaling.

transports/bifrost-http/handlers/inference.go (1)

509-516: LGTM! Pricing precision fix correctly addresses issue #1306.

The change from %f (6 decimal places) to %.10f (10 decimal places) ensures that very small per-token prices (e.g., 2e-7 = 0.0000002) are no longer truncated to "0.000000". The fix is applied consistently across all pricing fields.

core/providers/openai/types.go (1)

528-544: LGTM! Well-structured OpenAI model types.

The type definitions correctly model the OpenAI API response structure with appropriate optional fields using pointer types and omitempty tags. The GROQ-specific fields are properly documented.

core/providers/openai/models.go (1)

9-33: LGTM! Conversion logic is correct.

The function properly handles nil input, filters by allowed models when specified, and correctly maps all fields including the provider-prefixed ID.

Comment thread core/providers/openai/models.go
@akshaydeo akshaydeo merged commit d1c337f into v1.4.0 Jan 12, 2026
4 checks passed
@akshaydeo akshaydeo deleted the 01-12-review_fixes branch January 12, 2026 08:37
@coderabbitai coderabbitai Bot mentioned this pull request Jan 12, 2026
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.

2 participants