Skip to content

Conversation

Pratham-Mishra04
Copy link
Collaborator

Enhanced Gemini Chat Integration for Bifrost HTTP Transport

This PR enhances the Gemini AI integration by adding comprehensive support for Gemini's advanced features. The implementation now properly handles:

  • System instructions via the SystemInstruction field
  • Content caching with the CachedContent field
  • Response modality control through ResponseModalities
  • Improved multipart message handling for images, code, and other content types
  • Complete conversion of generation configuration parameters
  • Proper handling of safety settings and labels
  • Enhanced tool support with proper schema conversion
  • Support for thinking content in responses
  • Safety ratings extraction from response metadata

The changes significantly improve the fidelity of the Gemini API integration by ensuring all request and response fields are properly mapped between Bifrost's internal representation and Gemini's SDK types.

Copy link
Contributor

coderabbitai bot commented Jun 9, 2025

Caution

Review failed

The pull request is closed.

Summary by CodeRabbit

  • New Features

    • Enhanced support for system instructions and multipart chat content, including images and diverse content types.
    • Improved handling of tool integrations and response modalities.
    • Added support for extracting assistant thoughts and safety ratings from responses.
  • Bug Fixes

    • Improved model extraction from API endpoints to handle multiple possible suffixes.
  • Documentation

    • Updated usage instructions and added a note clarifying that streaming is not yet supported.

Summary by CodeRabbit

  • New Features

    • Enhanced chat requests with support for system instructions, cached content, and multiple response modalities.
    • Improved handling of multipart chat content, including text, images, code, and tool calls.
    • More detailed mapping of generation parameters and safety settings.
    • Responses now include assistant thought processes and safety ratings where available.
  • Refactor

    • Streamlined the conversion of chat content and configuration parameters for more accurate and flexible message handling.
  • Bug Fixes

    • Improved extraction of model names from API URLs by removing additional suffixes.
  • Documentation

    • Improved usage comments for better clarity and readability.
    • Added a note clarifying that streaming is not yet supported.

Walkthrough

The GeminiChatRequest struct and related methods in transports/bifrost-http/integrations/genai/types.go were expanded to support system instructions, multipart content, enhanced tool and parameter mapping, and richer response parsing. Several helper methods were introduced, and the conversion logic between GenAI and Bifrost schemas was refactored and extended. Additionally, the main.go file’s comment block was reformatted to improve readability and clarify that streaming is not yet supported. The router logic was updated to remove additional Google GenAI API suffixes from model strings.

Changes

File(s) Change Summary
transports/bifrost-http/integrations/genai/types.go Added fields to GeminiChatRequest; refactored and expanded ConvertToBifrostRequest; added helpers for content-to-messages conversion, generation config to model parameters, and schema-to-function parameters; enhanced response parsing to handle images, assistant thoughts, safety ratings, and tool calls.
transports/bifrost-http/main.go Reformatted top comment block for better readability; added note that streaming is not supported and related flags are ignored; no logic changes.
transports/bifrost-http/integrations/genai/router.go Extended removal of Google GenAI API endpoint suffixes from extracted model strings to include :streamGenerateContent and :countTokens.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant GeminiChatRequest
    participant BifrostRequest
    participant BifrostResponse

    Client->>GeminiChatRequest: Create request (with system instruction, content, config)
    GeminiChatRequest->>GeminiChatRequest: ConvertToBifrostRequest()
    GeminiChatRequest->>BifrostRequest: Build BifrostRequest (convert content, config, tools)
    BifrostRequest-->>GeminiChatRequest: BifrostRequest object
    BifrostRequest->>BifrostResponse: Send request, receive response
    BifrostResponse-->>GeminiChatRequest: Response with metadata
    GeminiChatRequest->>GeminiChatRequest: DeriveGenAIFromBifrostResponse()
    GeminiChatRequest-->>Client: GenerateContentResponse (includes thoughts, safety ratings)
Loading

Poem

In the code fields where the messages grow,
System thoughts and tools now flow.
Content parts, both text and art,
Safely mapped, each plays its part.
With helpers new and logic bright,
The chat hops forward—what a sight!
🐇✨


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0709d38 and b440cd4.

📒 Files selected for processing (3)
  • transports/bifrost-http/integrations/genai/router.go (1 hunks)
  • transports/bifrost-http/integrations/genai/types.go (5 hunks)
  • transports/bifrost-http/main.go (2 hunks)
✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Collaborator Author

Pratham-Mishra04 commented Jun 9, 2025

Copy link
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: 7

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b015950 and 70efb6c.

📒 Files selected for processing (1)
  • transports/bifrost-http/integrations/genai/types.go (4 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
transports/bifrost-http/integrations/genai/types.go (1)
core/schemas/bifrost.go (11)
  • Tool (108-112)
  • ModelChatMessageRoleSystem (25-25)
  • ModelChatMessageRole (20-20)
  • ModelParameters (75-89)
  • Function (101-105)
  • BifrostMessage (143-152)
  • ToolCall (266-270)
  • ImageContent (174-179)
  • FunctionCall (260-263)
  • FunctionParameters (92-98)
  • AssistantMessage (166-171)
🔇 Additional comments (4)
transports/bifrost-http/integrations/genai/types.go (4)

37-42: LGTM! System instruction handling is correct.

The implementation properly converts system instructions to Bifrost messages with the system role and prepends them to the chat input as expected.


46-49: Improved message conversion with helper method.

Good refactoring to extract the content conversion logic into a dedicated helper method, improving code organization and reusability.


280-282: LGTM! Good use of reflection for empty struct check.

Using reflect.DeepEqual to check for empty GenerationConfig is a clean approach that avoids manual field-by-field checking.


421-426: Excellent addition of thinking content support!

The implementation correctly handles the "thinking" content from assistant messages by setting the Thought field in the Part struct.

@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-09-refactor_http_transport_gemini_integration_refactors branch from 70efb6c to 9bc0828 Compare June 9, 2025 11:23
Copy link
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: 4

♻️ Duplicate comments (2)
transports/bifrost-http/integrations/genai/types.go (2)

156-159: Previous feedback not addressed – log marshalling errors.

The json.Marshal error is still swallowed. At minimum emit a debug log so failures can be traced.
See prior review on the same lines.


441-455: Previous feedback not addressed – filter empty safety ratings and add defensive checks.

Safety ratings are appended even when all fields are zero values, and the nested assertions can still panic on malformed payloads.
This mirrors an earlier review that remains unresolved.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 70efb6c and 9bc0828.

📒 Files selected for processing (1)
  • transports/bifrost-http/integrations/genai/types.go (5 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
transports/bifrost-http/integrations/genai/types.go (2)
core/schemas/bifrost.go (16)
  • BifrostRequest (54-64)
  • ModelParameters (75-89)
  • Tool (108-112)
  • ModelChatMessageRoleSystem (25-25)
  • ModelChatMessageRole (20-20)
  • Function (101-105)
  • BifrostMessage (143-152)
  • ToolCall (266-270)
  • ImageContent (174-179)
  • FunctionCall (260-263)
  • AssistantMessage (166-171)
  • ModelChatMessageRoleUser (24-24)
  • UserMessage (155-157)
  • ModelChatMessageRoleTool (27-27)
  • ToolMessage (160-163)
  • FunctionParameters (92-98)
core/utils.go (1)
  • Ptr (3-5)

@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-09-refactor_http_transport_gemini_integration_refactors branch from 9bc0828 to e339c57 Compare June 9, 2025 11:42
@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-09-feat_openai_integration_added_to_http_transport branch from b015950 to 111399d Compare June 9, 2025 11:42
Copy link
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: 3

♻️ Duplicate comments (3)
transports/bifrost-http/integrations/genai/types.go (3)

282-284: TopK still hidden in ExtraParams

A dedicated TopK field exists on ModelParameters; stashing it in ExtraParams is inconsistent with how Temperature, TopP, and MaxTokens are handled. (See previous review.)


129-133: Expensive reflect.DeepEqual for zero-value check

Using reflection here is overkill and brittle. Prefer explicit field checks for ToolConfig as previously suggested.


224-229: ⚠️ Potential issue

Guard tool-call injection to assistant role only

AssistantMessage.ToolCalls is attached irrespective of the originating role. Embedding tool calls into user, tool, or system messages violates the Bifrost schema and risks upstream validation failures.

-if len(toolCalls) > 0 {
-    mainMsg.AssistantMessage = &schemas.AssistantMessage{
-        ToolCalls: &toolCalls,
-    }
-}
+if len(toolCalls) > 0 && role == schemas.ModelChatMessageRoleAssistant {
+    mainMsg.AssistantMessage = &schemas.AssistantMessage{
+        ToolCalls: &toolCalls,
+    }
+}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9bc0828 and e339c57.

📒 Files selected for processing (1)
  • transports/bifrost-http/integrations/genai/types.go (5 hunks)

@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-09-feat_openai_integration_added_to_http_transport branch from 111399d to 7ee161c Compare June 9, 2025 13:50
@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-09-refactor_http_transport_gemini_integration_refactors branch from e339c57 to 1618f5d Compare June 9, 2025 13:50
Copy link
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

♻️ Duplicate comments (6)
transports/bifrost-http/integrations/genai/types.go (6)

172-180: Inline image data is not base64-encoded

part.InlineData.Data contains raw bytes. Converting it with string() embeds arbitrary bytes into the data-URL and produces invalid output.

-import (
-    "encoding/json"
-    "fmt"
-    "reflect"
-    "strings"
+import (
+    "encoding/base64"
+    "encoding/json"
+    "fmt"
+    "reflect"
+    "strings"
 ...
-imageContent := schemas.ImageContent{
-    Type:      &imageType,
-    URL:       fmt.Sprintf("data:%s;base64,%s", part.InlineData.MIMEType, string(part.InlineData.Data)),
-    MediaType: &part.InlineData.MIMEType,
-}
+encoded := base64.StdEncoding.EncodeToString(part.InlineData.Data)
+imageContent := schemas.ImageContent{
+    Type:      &imageType,
+    URL:       fmt.Sprintf("data:%s;base64,%s", part.InlineData.MIMEType, encoded),
+    MediaType: &part.InlineData.MIMEType,
+}

243-254: Assistant & system images are silently dropped

The switch only handles user and tool. Images supplied by the assistant or in a system instruction are never forwarded.

 case schemas.ModelChatMessageRoleTool:
     imageMsg.ToolMessage = &schemas.ToolMessage{ ImageContent: &imageContent }
+case schemas.ModelChatMessageRoleAssistant:
+    imageMsg.AssistantMessage = &schemas.AssistantMessage{ ImageContent: &imageContent }
+case schemas.ModelChatMessageRoleSystem:
+    imageMsg.SystemMessage = &schemas.SystemMessage{ ImageContent: &imageContent }

283-285: Use the dedicated TopK field instead of ExtraParams

ModelParameters already has a TopK pointer. Stashing the value in ExtraParams is inconsistent with how Temperature, TopP, and MaxTokens are handled.

-if config.TopK != nil {
-    params.ExtraParams["top_k"] = *config.TopK
-}
+if config.TopK != nil {
+    v := int(*config.TopK)
+    params.TopK = &v
+}

131-134: Avoid reflect.DeepEqual for zero-value detection

Using reflection here is slow and brittle. An explicit field check is faster and doesn’t break when new fields are added.

-if !reflect.DeepEqual(r.ToolConfig, genai_sdk.ToolConfig{}) {
+if r.ToolConfig.Mode != "" || len(r.ToolConfig.FunctionCallParameters) > 0 {

475-499: convertImageContentToGenAIPart returns base64 text, not decoded bytes

InlineData.Data expects the raw binary payload, but the function currently passes the base64 string as-is.

-    base64Data := url[idx+1:]
-    return &genai_sdk.Part{
-        InlineData: &genai_sdk.Blob{
-            MIMEType: *imageContent.MediaType,
-            Data:     []byte(base64Data),
-        },
-    }
+    base64Data := url[idx+1:]
+    decoded, err := base64.StdEncoding.DecodeString(base64Data)
+    if err != nil {
+        return nil
+    }
+    return &genai_sdk.Part{
+        InlineData: &genai_sdk.Blob{
+            MIMEType: *imageContent.MediaType,
+            Data:     decoded,
+        },
+    }

Remember to keep encoding/base64 in the import block.


225-230: ⚠️ Potential issue

Guard tool-call injection to assistant messages only

toolCalls are blindly attached even when the original role is not assistant, which violates the Bifrost schema and can trigger upstream validation errors.

-if len(toolCalls) > 0 {
-    mainMsg.AssistantMessage = &schemas.AssistantMessage{
-        ToolCalls: &toolCalls,
-    }
-}
+if len(toolCalls) > 0 && role == schemas.ModelChatMessageRoleAssistant {
+    mainMsg.AssistantMessage = &schemas.AssistantMessage{
+        ToolCalls: &toolCalls,
+    }
+}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e339c57 and 1618f5d.

📒 Files selected for processing (1)
  • transports/bifrost-http/integrations/genai/types.go (5 hunks)

@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-09-feat_openai_integration_added_to_http_transport branch from 7ee161c to 4ad600d Compare June 9, 2025 14:20
@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-09-refactor_http_transport_gemini_integration_refactors branch 2 times, most recently from bb0425c to c664c44 Compare June 9, 2025 14:27
@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-09-feat_openai_integration_added_to_http_transport branch 2 times, most recently from fbd3a73 to e0e01b8 Compare June 9, 2025 14:32
@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-09-refactor_http_transport_gemini_integration_refactors branch 2 times, most recently from efe4ba6 to 46def42 Compare June 9, 2025 16:27
Copy link
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: 4

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bb0425c and 46def42.

📒 Files selected for processing (1)
  • transports/bifrost-http/integrations/genai/types.go (5 hunks)
🧰 Additional context used
🧠 Learnings (1)
transports/bifrost-http/integrations/genai/types.go (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#64
File: transports/bifrost-http/integrations/genai/types.go:383-395
Timestamp: 2025-06-09T16:26:05.727Z
Learning: In the Bifrost schema (core/schemas/bifrost.go), only UserMessage and ToolMessage structs have ImageContent fields. AssistantMessage does not have an ImageContent field and cannot contain images. The schema design intentionally limits image content to user and tool messages only.
🔇 Additional comments (1)
transports/bifrost-http/integrations/genai/types.go (1)

226-235: Main message may be silently dropped when tool-calls originate from non-assistant roles

toolCalls are only attached when role == assistant, but the guard that adds mainMsg checks either content or tool-calls.
If a (mis-labelled) request contains only a FunctionCall part under user or tool, you will end up discarding the information entirely.

Consider either:

  1. enforcing at parse time that FunctionCall parts only appear with assistant role, or
  2. relaxing the guard so the message is inserted whenever a FunctionCall was detected, regardless of role.

@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-09-refactor_http_transport_gemini_integration_refactors branch from 46def42 to 65a8762 Compare June 9, 2025 16:42
Copy link
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

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 46def42 and 65a8762.

📒 Files selected for processing (2)
  • transports/bifrost-http/integrations/genai/types.go (5 hunks)
  • transports/bifrost-http/main.go (2 hunks)
🧰 Additional context used
🧠 Learnings (1)
transports/bifrost-http/integrations/genai/types.go (2)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#64
File: transports/bifrost-http/integrations/genai/types.go:273-313
Timestamp: 2025-06-09T16:35:26.900Z
Learning: In convertGenerationConfigToParams method in transports/bifrost-http/integrations/genai/types.go, pre-allocating the ExtraParams map is preferred over lazy allocation because the method has multiple potential ExtraParams assignments, making the computational overhead of conditional checks exceed the memory savings of an empty map.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#64
File: transports/bifrost-http/integrations/genai/types.go:383-395
Timestamp: 2025-06-09T16:26:05.727Z
Learning: In the Bifrost schema (core/schemas/bifrost.go), only UserMessage and ToolMessage structs have ImageContent fields. AssistantMessage does not have an ImageContent field and cannot contain images. The schema design intentionally limits image content to user and tool messages only.
🧬 Code Graph Analysis (1)
transports/bifrost-http/integrations/genai/types.go (2)
core/schemas/bifrost.go (17)
  • BifrostRequest (54-64)
  • ModelParameters (75-89)
  • Tool (108-112)
  • ModelChatMessageRoleSystem (25-25)
  • ModelChatMessageRole (20-20)
  • Function (101-105)
  • BifrostMessage (143-152)
  • ToolCall (266-270)
  • ImageContent (174-179)
  • FunctionCall (260-263)
  • ModelChatMessageRoleAssistant (23-23)
  • AssistantMessage (166-171)
  • ModelChatMessageRoleUser (24-24)
  • UserMessage (155-157)
  • ModelChatMessageRoleTool (27-27)
  • ToolMessage (160-163)
  • FunctionParameters (92-98)
core/utils.go (1)
  • Ptr (3-5)
🔇 Additional comments (1)
transports/bifrost-http/main.go (1)

14-16: Documentation update looks good

Re-formatting the example usage and adding an explicit note about the lack of streaming support improves readability and sets correct expectations. No further action required.

Also applies to: 31-32

@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-09-feat_openai_integration_added_to_http_transport branch from e0e01b8 to 4cf3b95 Compare June 10, 2025 06:57
@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-09-refactor_http_transport_gemini_integration_refactors branch from 65a8762 to 4c35179 Compare June 10, 2025 06:57
Copy link
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

♻️ Duplicate comments (2)
transports/bifrost-http/integrations/genai/types.go (2)

424-447: 🧹 Nitpick (assertive)

Skip assigning empty safety-ratings slice

candidate.SafetyRatings = ratings is executed even when ratings is empty, emitting [] instead of null in JSON.
While harmless, omitting the field reduces payload size and mirrors how other optional fields are handled.

- candidate.SafetyRatings = ratings
+ if len(ratings) > 0 {
+     candidate.SafetyRatings = ratings
+ }

234-254: 💡 Verification agent

🧩 Analysis chain

Potential silent data-loss for images on unsupported roles

The switch appends image messages only for user and tool.
If the GenAI SDK ever emits images under other roles (e.g. system or a future role), they will be silently dropped.

 case schemas.ModelChatMessageRoleUser:
     ...
 case schemas.ModelChatMessageRoleTool:
     ...
+default:
+    // Consider logging / rejecting so the caller knows the image was ignored

Not urgent given today’s schema, but worth a TODO so future contributors aren’t surprised.


🏁 Script executed:

#!/bin/bash
# Search for ModelChatMessageRole type definition and associated constants
rg -n "^type ModelChatMessageRole" .
rg -n "^const .*ModelChatMessageRole" -A5 .

Length of output: 146


🏁 Script executed:

#!/bin/bash
# Display the type definition and constants for ModelChatMessageRole
rg -n 'type ModelChatMessageRole' -A5 core/schemas/bifrost.go
rg -n 'const (' -A20 core/schemas/bifrost.go

Length of output: 425


🏁 Script executed:

#!/bin/bash
# Show the full constant block for ModelChatMessageRole
rg -n 'type ModelChatMessageRole' -A15 core/schemas/bifrost.go

# Search for any reference to ModelChatMessageRoleTool in the repo
rg -n 'ModelChatMessageRoleTool' -n .

Length of output: 1914


Ensure images aren’t silently dropped for unexpected roles

Right now only user and tool roles append image messages. If the SDK ever emits images under assistant, system, chatbot, or any future role, they’ll be dropped without notice.

Locations to update:

  • transports/bifrost-http/integrations/genai/types.go (around lines 234–254)

Suggested diff:

   // Set image content based on role
   switch role {
   case schemas.ModelChatMessageRoleUser:
       imageMsg.UserMessage = &schemas.UserMessage{
           ImageContent: &imageContent,
       }
       messages = append(messages, imageMsg)

   case schemas.ModelChatMessageRoleTool:
       imageMsg.ToolMessage = &schemas.ToolMessage{
           ImageContent: &imageContent,
       }
       messages = append(messages, imageMsg)

+  default:
+      // TODO: log or return an error so we don’t silently drop images
+      log.Warnf("ignoring image for unsupported role %q", role)
   }

Adding a default ensures future roles don’t lose data unexpectedly.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 65a8762 and 4c35179.

📒 Files selected for processing (2)
  • transports/bifrost-http/integrations/genai/types.go (5 hunks)
  • transports/bifrost-http/main.go (2 hunks)
🧰 Additional context used
🧠 Learnings (1)
transports/bifrost-http/integrations/genai/types.go (2)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#64
File: transports/bifrost-http/integrations/genai/types.go:273-313
Timestamp: 2025-06-09T16:35:26.914Z
Learning: In convertGenerationConfigToParams method in transports/bifrost-http/integrations/genai/types.go, pre-allocating the ExtraParams map is preferred over lazy allocation because the method has multiple potential ExtraParams assignments, making the computational overhead of conditional checks exceed the memory savings of an empty map.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#64
File: transports/bifrost-http/integrations/genai/types.go:383-395
Timestamp: 2025-06-09T16:26:05.777Z
Learning: In the Bifrost schema (core/schemas/bifrost.go), only UserMessage and ToolMessage structs have ImageContent fields. AssistantMessage does not have an ImageContent field and cannot contain images. The schema design intentionally limits image content to user and tool messages only.
🔇 Additional comments (3)
transports/bifrost-http/main.go (1)

14-16: Documentation change looks good

Clearer example formatting and an explicit non-streaming disclaimer help avoid confusion.
No further action required.

Also applies to: 31-32

transports/bifrost-http/integrations/genai/types.go (2)

223-227: Good guard – tool calls restricted to assistant role only

Limiting tool-call injection to the assistant role prevents schema violations for user / system messages.
Nicely done.


261-307: 🧹 Nitpick (assertive)

Zero-value GenerationConfig always allocates a params struct

convertGenerationConfigToParams unconditionally returns a ModelParameters instance with an empty ExtraParams map.
That works, but it means every Gemini request – even when no config is supplied – carries an allocation.

If you want to avoid the extra object when nothing is set:

+empty := genai_sdk.GenerationConfig{}
+if r.GenerationConfig == empty {
+    return nil
+}

Then call ensureExtraParams later when you first need the map.
Minor; feel free to ignore if the current trade-off (one tiny map vs. several nil checks) is deliberate.

⛔ Skipped due to learnings
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#64
File: transports/bifrost-http/integrations/genai/types.go:273-313
Timestamp: 2025-06-09T16:35:26.914Z
Learning: In convertGenerationConfigToParams method in transports/bifrost-http/integrations/genai/types.go, pre-allocating the ExtraParams map is preferred over lazy allocation because the method has multiple potential ExtraParams assignments, making the computational overhead of conditional checks exceed the memory savings of an empty map.

@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-09-refactor_http_transport_gemini_integration_refactors branch from 4c35179 to 96ee207 Compare June 10, 2025 10:06
Copy link
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: 2

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4c35179 and 96ee207.

📒 Files selected for processing (3)
  • transports/bifrost-http/integrations/genai/router.go (1 hunks)
  • transports/bifrost-http/integrations/genai/types.go (5 hunks)
  • transports/bifrost-http/main.go (2 hunks)
🧰 Additional context used
🧠 Learnings (1)
transports/bifrost-http/integrations/genai/types.go (2)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#64
File: transports/bifrost-http/integrations/genai/types.go:273-313
Timestamp: 2025-06-09T16:35:26.914Z
Learning: In convertGenerationConfigToParams method in transports/bifrost-http/integrations/genai/types.go, pre-allocating the ExtraParams map is preferred over lazy allocation because the method has multiple potential ExtraParams assignments, making the computational overhead of conditional checks exceed the memory savings of an empty map.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#64
File: transports/bifrost-http/integrations/genai/types.go:383-395
Timestamp: 2025-06-09T16:26:05.777Z
Learning: In the Bifrost schema (core/schemas/bifrost.go), only UserMessage and ToolMessage structs have ImageContent fields. AssistantMessage does not have an ImageContent field and cannot contain images. The schema design intentionally limits image content to user and tool messages only.
🔇 Additional comments (4)
transports/bifrost-http/integrations/genai/router.go (1)

51-55: Replace hard-coded suffix stripping with a short loop for maintainability

The three strings.TrimSuffix calls work, but they scale poorly as soon as Google adds yet another verb.
A tiny helper slice + loop keeps the intent obvious and makes the next addition a one-liner.

-// Remove Google GenAI API endpoint suffixes if present
-modelStr = strings.TrimSuffix(modelStr, ":generateContent")
-modelStr = strings.TrimSuffix(modelStr, ":streamGenerateContent")
-modelStr = strings.TrimSuffix(modelStr, ":countTokens")
+// Strip known API verbs that may trail the model name.
+for _, sfx := range []string{
+	":generateContent",
+	":streamGenerateContent",
+	":countTokens",
+} {
+	modelStr = strings.TrimSuffix(modelStr, sfx)
+}

No functional change, just easier future upkeep.
[ suggest_optional_refactor ]

transports/bifrost-http/integrations/genai/types.go (2)

150-181: 👍 Correct base64 handling for inline images

Switching to base64.StdEncoding.EncodeToString fixes the RFC-2397 / binary-data bug from earlier iterations.
Looks good and aligns with the reverse conversion path.


236-255: Images for roles other than user/tool are intentionally skipped – please confirm

The switch appends image messages only for user and tool roles.
Given the schema (only UserMessage & ToolMessage have ImageContent), this is correct, but any future schema change (e.g. system images) will silently drop data.

Request verification that this behaviour is documented & covered by tests.

transports/bifrost-http/main.go (1)

14-17: Comment-only change – no action required

The re-flowed example block reads better; nothing else to note.

@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-09-feat_openai_integration_added_to_http_transport branch from 4cf3b95 to 72f5791 Compare June 10, 2025 10:25
@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-09-refactor_http_transport_gemini_integration_refactors branch from 96ee207 to 371e003 Compare June 10, 2025 10:25
Copy link
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: 2

♻️ Duplicate comments (2)
transports/bifrost-http/integrations/genai/types.go (2)

283-309: candidate_count is still written twice – please drop the duplicate block

This duplication was flagged previously and is still present.
Keeping both writes is harmless at runtime but clutters the param map and invites divergence during future edits.

@@
 	if config.CandidateCount > 0 {
 		params.ExtraParams["candidate_count"] = config.CandidateCount
 	}
@@
-	if config.CandidateCount > 0 {
-		params.ExtraParams["candidate_count"] = config.CandidateCount
-	}

470-475: 🧹 Nitpick (assertive)

Use a neutral fallback MIME type

image/png is image-specific. If non-image blobs (audio, pdf, etc.) ever flow through, the default becomes misleading.
application/octet-stream is the conventional catch-all for unknown binary data.

-	// Determine MIME type with fallback default
-	mimeType := "image/png" // Default MIME type for images
+	// Determine MIME type with neutral fallback
+	mimeType := "application/octet-stream"
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 96ee207 and 371e003.

📒 Files selected for processing (3)
  • transports/bifrost-http/integrations/genai/router.go (1 hunks)
  • transports/bifrost-http/integrations/genai/types.go (5 hunks)
  • transports/bifrost-http/main.go (2 hunks)
🧰 Additional context used
🧠 Learnings (1)
transports/bifrost-http/integrations/genai/types.go (2)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#64
File: transports/bifrost-http/integrations/genai/types.go:273-313
Timestamp: 2025-06-09T16:35:26.914Z
Learning: In convertGenerationConfigToParams method in transports/bifrost-http/integrations/genai/types.go, pre-allocating the ExtraParams map is preferred over lazy allocation because the method has multiple potential ExtraParams assignments, making the computational overhead of conditional checks exceed the memory savings of an empty map.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#64
File: transports/bifrost-http/integrations/genai/types.go:383-395
Timestamp: 2025-06-09T16:26:05.777Z
Learning: In the Bifrost schema (core/schemas/bifrost.go), only UserMessage and ToolMessage structs have ImageContent fields. AssistantMessage does not have an ImageContent field and cannot contain images. The schema design intentionally limits image content to user and tool messages only.
🧬 Code Graph Analysis (1)
transports/bifrost-http/integrations/genai/types.go (2)
core/schemas/bifrost.go (17)
  • BifrostRequest (54-64)
  • ModelParameters (75-89)
  • Tool (108-112)
  • ModelChatMessageRoleSystem (25-25)
  • ModelChatMessageRole (20-20)
  • Function (101-105)
  • BifrostMessage (143-152)
  • ToolCall (273-277)
  • ImageContent (181-186)
  • FunctionCall (267-270)
  • ModelChatMessageRoleTool (27-27)
  • ToolMessage (160-163)
  • ModelChatMessageRoleAssistant (23-23)
  • AssistantMessage (166-171)
  • ModelChatMessageRoleUser (24-24)
  • UserMessage (155-157)
  • FunctionParameters (92-98)
core/utils.go (1)
  • Ptr (3-5)

@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-09-refactor_http_transport_gemini_integration_refactors branch from 371e003 to d0f2c73 Compare June 10, 2025 11:04
@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-09-feat_openai_integration_added_to_http_transport branch from 72f5791 to d68ae37 Compare June 10, 2025 11:04
@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-09-refactor_http_transport_gemini_integration_refactors branch from d0f2c73 to e009a8b Compare June 10, 2025 11:09
Copy link
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.

Caution

Inline review comments failed to post. This is likely due to GitHub's 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: 1

♻️ Duplicate comments (4)
transports/bifrost-http/integrations/genai/types.go (2)

287-287: 🧹 Nitpick (assertive)

Consider using the original struct field for StopSequences.

While the current implementation works, taking the address of the slice from the original struct is clearer and avoids potential allocations.

-if len(config.StopSequences) > 0 {
-    params.StopSequences = &config.StopSequences
+if len(r.GenerationConfig.StopSequences) > 0 {
+    params.StopSequences = &r.GenerationConfig.StopSequences
 }

283-309: ⚠️ Potential issue

Remove duplicate candidate_count assignment.

The candidate_count parameter is assigned twice - at lines 283-285 and again at lines 307-309. This is redundant and could cause confusion.

 if config.CandidateCount > 0 {
     params.ExtraParams["candidate_count"] = config.CandidateCount
 }
 if len(config.StopSequences) > 0 {
     params.StopSequences = &config.StopSequences
 }
 if config.PresencePenalty != nil {
     params.PresencePenalty = bifrost.Ptr(float64(*config.PresencePenalty))
 }
 if config.FrequencyPenalty != nil {
     params.FrequencyPenalty = bifrost.Ptr(float64(*config.FrequencyPenalty))
 }
 if config.Seed != nil {
     params.ExtraParams["seed"] = *config.Seed
 }
 if config.ResponseMIMEType != "" {
     params.ExtraParams["response_mime_type"] = config.ResponseMIMEType
 }
 if config.ResponseLogprobs {
     params.ExtraParams["response_logprobs"] = config.ResponseLogprobs
 }
 if config.Logprobs != nil {
     params.ExtraParams["logprobs"] = *config.Logprobs
 }
-if config.CandidateCount > 0 {
-    params.ExtraParams["candidate_count"] = config.CandidateCount
-}
transports/bifrost-http/main.go (1)

15-15: Update example command to reference correct filename.

The command still references http.go, but the file is main.go. Update for documentation consistency.

transports/bifrost-http/integrations/genai/router.go (1)

51-54: Refactor hard-coded suffix removal for better maintainability.

The additional suffixes work correctly, but the manual approach becomes harder to maintain as more endpoints are added.

Consider using a loop over a slice of suffixes as suggested in the previous review to keep this DRY and extensible.

🛑 Comments failed to post (1)
transports/bifrost-http/integrations/genai/types.go (1)

472-472: 🧹 Nitpick (assertive)

Consider using application/octet-stream as the default MIME type.

While image/png works for images, using application/octet-stream as the default would be more generic and handle non-image binary data correctly if this code path is ever used for other content types.

-mimeType := "image/png" // Default MIME type for images
+mimeType := "application/octet-stream" // Default MIME type for binary data

Also update line 514:

-return "image/jpeg" // default
+return "application/octet-stream" // default

Also applies to: 514-514

🤖 Prompt for AI Agents
In transports/bifrost-http/integrations/genai/types.go at lines 472 and 514, the
default MIME type is set to "image/png", which is too specific. Change the
default MIME type to "application/octet-stream" to make it more generic and
suitable for handling various binary data types. Update both lines accordingly
to reflect this change.

@akshaydeo akshaydeo marked this pull request as ready for review June 10, 2025 11:38
cursor[bot]

This comment was marked as outdated.

Copy link
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

♻️ Duplicate comments (2)
transports/bifrost-http/integrations/genai/types.go (2)

157-160: Error silently swallowed – original remark still applies.
The marshal failure is still ignored without any trace; a debug/trace log would greatly aid troubleshooting malformed Args.


286-288: Pointer taken from a local copy – original nit unchanged.

params.StopSequences = &config.StopSequences still captures the slice header from the local config copy instead of r.GenerationConfig.
It’s harmless but allocates. Using the original struct is clearer.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d0f2c73 and e009a8b.

📒 Files selected for processing (3)
  • transports/bifrost-http/integrations/genai/router.go (1 hunks)
  • transports/bifrost-http/integrations/genai/types.go (5 hunks)
  • transports/bifrost-http/main.go (2 hunks)
🧰 Additional context used
🧠 Learnings (1)
transports/bifrost-http/integrations/genai/types.go (3)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#64
File: transports/bifrost-http/integrations/genai/types.go:273-313
Timestamp: 2025-06-09T16:35:26.914Z
Learning: In convertGenerationConfigToParams method in transports/bifrost-http/integrations/genai/types.go, pre-allocating the ExtraParams map is preferred over lazy allocation because the method has multiple potential ExtraParams assignments, making the computational overhead of conditional checks exceed the memory savings of an empty map.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#64
File: transports/bifrost-http/integrations/genai/types.go:383-395
Timestamp: 2025-06-09T16:26:05.777Z
Learning: In the Bifrost schema (core/schemas/bifrost.go), only UserMessage and ToolMessage structs have ImageContent fields. AssistantMessage does not have an ImageContent field and cannot contain images. The schema design intentionally limits image content to user and tool messages only.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#64
File: transports/bifrost-http/integrations/genai/types.go:470-515
Timestamp: 2025-06-10T11:06:57.681Z
Learning: Bifrost currently only supports images and does not support non-image blob types like audio, PDF, or other binary data formats.
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Graphite / mergeability_check
🔇 Additional comments (2)
transports/bifrost-http/integrations/genai/router.go (1)

51-58: Suffix-stripping now DRY & future-proof – looks good.

Looping over the slice eliminates the old duplication and keeps the logic maintainable as new endpoints appear.
No functional or performance concerns. 👍

transports/bifrost-http/main.go (1)

14-16: Documentation formatting improvement looks good.

The reformatting of the example usage section improves readability with proper indentation, and the command reference is correctly updated to main.go.

@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-09-refactor_http_transport_gemini_integration_refactors branch from e009a8b to 0709d38 Compare June 10, 2025 13:39
Copy link
Contributor

akshaydeo commented Jun 10, 2025

Merge activity

  • Jun 10, 4:28 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Jun 10, 4:29 PM UTC: Graphite rebased this pull request as part of a merge.
  • Jun 10, 4:31 PM UTC: @akshaydeo merged this pull request with Graphite.

@akshaydeo akshaydeo changed the base branch from 06-09-feat_openai_integration_added_to_http_transport to graphite-base/64 June 10, 2025 16:28
@akshaydeo akshaydeo changed the base branch from graphite-base/64 to main June 10, 2025 16:28
@akshaydeo akshaydeo force-pushed the 06-09-refactor_http_transport_gemini_integration_refactors branch from 0709d38 to b440cd4 Compare June 10, 2025 16:29
@akshaydeo akshaydeo merged commit e5b3e57 into main Jun 10, 2025
1 of 2 checks passed
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Bug: Image Handling Fails for Non-User Roles

Image content is silently dropped for assistant and system role messages in convertContentToBifrostMessages because the function's switch statement only appends images for user and tool roles, resulting in data loss.

transports/bifrost-http/integrations/genai/types.go#L235-L255

// Create separate messages for each image
for _, imageContent := range imageContents {
imageMsg := schemas.BifrostMessage{
Role: role,
}
// Set image content based on role
switch role {
case schemas.ModelChatMessageRoleUser:
imageMsg.UserMessage = &schemas.UserMessage{
ImageContent: &imageContent,
}
messages = append(messages, imageMsg)
case schemas.ModelChatMessageRoleTool:
imageMsg.ToolMessage = &schemas.ToolMessage{
ImageContent: &imageContent,
}
messages = append(messages, imageMsg)
}
}

Fix in Cursor


Bug: Gemini Content Parsing Prematurely Ends

The convertContentToBifrostMessages function returns prematurely when a FunctionResponse part is encountered within a Gemini content object. This causes any subsequent parts (e.g., text, images, or other function calls) in the same content object to be ignored, leading to incomplete message conversion and loss of valid content.

transports/bifrost-http/integrations/genai/types.go#L191-L207

case part.FunctionResponse != nil:
responseContent, err := json.Marshal(part.FunctionResponse.Response)
if err != nil {
responseContent = []byte(fmt.Sprintf("%v", part.FunctionResponse.Response))
}
toolResponseMsg := schemas.BifrostMessage{
Role: schemas.ModelChatMessageRoleTool,
Content: bifrost.Ptr(string(responseContent)),
ToolMessage: &schemas.ToolMessage{
ToolCallID: &part.FunctionResponse.Name,
},
}
return []schemas.BifrostMessage{toolResponseMsg}
}

Fix in Cursor


Was this report helpful? Give feedback by reacting with 👍 or 👎

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