Skip to content

Conversation

Pratham-Mishra04
Copy link
Collaborator

Update Message Content Structure for Multi-Modal Support

This PR refactors the message content structure to better support multi-modal interactions (text and images) across all providers. The key changes include:

  1. Replaced the simple Content *string field with a structured MessageContent type that can contain either a string or an array of content blocks
  2. Added new ContentBlock type to represent different content types (text or image)
  3. Removed the separate ImageContent type in favor of the more flexible ImageURLStruct
  4. Updated all providers (OpenAI, Anthropic, Bedrock, Azure, Cohere) to use the new content structure
  5. Enhanced image processing utilities with better URL sanitization and media type detection
  6. Updated the README example to use the new message structure
  7. Updated documentation and OpenAPI specs to reflect the new content structure

This change provides a more consistent way to handle multi-modal content across different providers and aligns better with OpenAI's content structure, making it easier to work with both text and image inputs in the same message.

Copy link
Contributor

coderabbitai bot commented Jun 11, 2025

Warning

Rate limit exceeded

@Pratham-Mishra04 has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 0 minutes and 1 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 72a4006 and e437920.

📒 Files selected for processing (12)
  • README.md (1 hunks)
  • core/providers/anthropic.go (7 hunks)
  • core/providers/azure.go (1 hunks)
  • core/providers/bedrock.go (10 hunks)
  • core/providers/cohere.go (5 hunks)
  • core/providers/openai.go (1 hunks)
  • core/providers/utils.go (2 hunks)
  • core/schemas/bifrost.go (3 hunks)
  • core/tests/e2e_tool_test.go (3 hunks)
  • core/tests/tests.go (10 hunks)
  • docs/http-transport-api.md (6 hunks)
  • docs/openapi.json (3 hunks)

Summary by CodeRabbit

  • New Features

    • Chat messages now support structured content, allowing a mix of text and images within a single message.
    • The API, documentation, and SDKs have been updated to accept and return messages with either plain text or arrays of content blocks (text and image types).
  • Bug Fixes

    • Improved validation and handling of image URLs, including support for base64 and HTTP/HTTPS images.
  • Documentation

    • Updated API documentation, OpenAPI schema, and code examples to reflect the new structured message content format.
  • Tests

    • Enhanced and unified test coverage for structured message content, including mixed text and image scenarios.

Summary by CodeRabbit

  • New Features

    • Introduced structured message content, allowing chat messages to include both text and images using content blocks.
    • Updated API and documentation to support and illustrate messages with mixed text and image content.
  • Bug Fixes

    • Improved image URL handling and validation for more robust and flexible image content support.
  • Documentation

    • Expanded API and integration examples to demonstrate the new structured content format.
    • Updated schema definitions and OpenAPI specification to reflect changes in message content structure.
  • Tests

    • Revised tests to align with the new message content structure, ensuring consistent handling of text and image blocks.

Walkthrough

This update introduces a new, structured approach to message content handling across the codebase and documentation. Messages now use a MessageContent type that supports both plain text and arrays of content blocks (including text and images). Provider logic, tests, and API documentation are updated to align with this flexible, extensible message format.

Changes

Files / Areas Changed Summary
core/schemas/bifrost.go Replaces simple string message content with MessageContent supporting text and content blocks; removes old image content types.
core/providers/anthropic.go, core/providers/azure.go, core/providers/bedrock.go, core/providers/cohere.go, core/providers/openai.go Refactors provider logic to use MessageContent and content blocks for message construction, parsing, and serialization.
core/providers/utils.go Adds robust image URL sanitization and metadata extraction utilities; removes legacy image content normalization functions.
docs/http-transport-api.md, docs/openapi.json Updates API documentation and OpenAPI spec for structured content blocks; adds new examples and schemas for images and text.
core/tests/e2e_tool_test.go, core/tests/tests.go Refactors tests to use MessageContent and content blocks; updates assertions and logging for new message format.
README.md Updates code examples to demonstrate new message content structure and usage.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant API
    participant Provider

    Client->>API: Send chat request with content blocks (text/image)
    API->>Provider: Prepare messages using MessageContent
    Provider->>Provider: Serialize/deserialize content blocks
    Provider-->>API: Return response with structured content
    API-->>Client: Respond with content blocks (text/image)
Loading

Possibly related PRs

Suggested reviewers

  • danpiths
  • akshaydeo

Poem

🐰
In fields of code where messages grow,
Now text and images together flow!
With blocks of content, neat and bright,
Our schemas leap to new delight.
Bifrost’s bridge is strong and wide—
Multi-modal dreams, come hop inside!
🌈

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate Unit Tests
  • Create PR with Unit Tests
  • Commit Unit Tests in branch 06-11-refactor_changed_content_schema_to_follow_openai
  • Post Copyable Unit Tests in Comment

🪧 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 auto-generate unit tests to generate unit tests for 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 11, 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: 6

🔭 Outside diff range comments (2)
core/providers/anthropic.go (2)

329-361: ⚠️ Potential issue

Fix potential null pointer dereference.

The function could panic if urlTypeInfo.MediaType is nil.

Apply this fix to handle nil MediaType:

 formattedImgContent := AnthropicImageContent{
     Type:      urlTypeInfo.Type,
-    MediaType: *urlTypeInfo.MediaType,
+    MediaType: coalesceString(urlTypeInfo.MediaType),
 }

368-410: ⚠️ Potential issue

Fix missing pointer dereference in tool message handling.

Line 407 attempts to use block.Text directly but it's a pointer that needs to be dereferenced.

Apply this fix:

 toolCallResultContent = append(toolCallResultContent, map[string]interface{}{
     "type": "text",
-    "text": block.Text,
+    "text": *block.Text,
 })
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between bc74f7d and 5c964ce.

📒 Files selected for processing (13)
  • README.md (1 hunks)
  • core/providers/anthropic.go (7 hunks)
  • core/providers/azure.go (1 hunks)
  • core/providers/bedrock.go (9 hunks)
  • core/providers/cohere.go (5 hunks)
  • core/providers/openai.go (1 hunks)
  • core/providers/utils.go (2 hunks)
  • core/schemas/bifrost.go (3 hunks)
  • core/tests/e2e_tool_test.go (3 hunks)
  • core/tests/openai_test.go (1 hunks)
  • core/tests/tests.go (10 hunks)
  • docs/http-transport-api.md (6 hunks)
  • docs/openapi.json (3 hunks)
🧰 Additional context used
🧠 Learnings (6)
core/tests/e2e_tool_test.go (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/bedrock.go:443-468
Timestamp: 2025-06-04T09:32:15.826Z
Learning: In core/providers/bedrock.go, for tool call result messages (ModelChatMessageRoleTool), the Content field represents the actual tool call output. A tool result message should only be created when msg.Content is non-nil, as there's no semantic meaning to a tool result without output content.
core/tests/tests.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.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.
core/providers/cohere.go (2)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/bedrock.go:443-468
Timestamp: 2025-06-04T09:32:15.826Z
Learning: In core/providers/bedrock.go, for tool call result messages (ModelChatMessageRoleTool), the Content field represents the actual tool call output. A tool result message should only be created when msg.Content is non-nil, as there's no semantic meaning to a tool result without output content.
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.
core/providers/bedrock.go (3)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/bedrock.go:443-468
Timestamp: 2025-06-04T09:32:15.826Z
Learning: In core/providers/bedrock.go, for tool call result messages (ModelChatMessageRoleTool), the Content field represents the actual tool call output. A tool result message should only be created when msg.Content is non-nil, as there's no semantic meaning to a tool result without output content.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:526-550
Timestamp: 2025-06-04T09:29:46.287Z
Learning: In core/providers/anthropic.go, the content field in formattedMessages is always of type []interface{} because it's explicitly constructed that way upstream in the prepareAnthropicChatRequest function. Defensive type casting for multiple types is not needed since the type is guaranteed by the construction logic.
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.
core/providers/anthropic.go (3)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:526-550
Timestamp: 2025-06-04T09:29:46.287Z
Learning: In core/providers/anthropic.go, the content field in formattedMessages is always of type []interface{} because it's explicitly constructed that way upstream in the prepareAnthropicChatRequest function. Defensive type casting for multiple types is not needed since the type is guaranteed by the construction logic.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/bedrock.go:443-468
Timestamp: 2025-06-04T09:32:15.826Z
Learning: In core/providers/bedrock.go, for tool call result messages (ModelChatMessageRoleTool), the Content field represents the actual tool call output. A tool result message should only be created when msg.Content is non-nil, as there's no semantic meaning to a tool result without output content.
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.
core/schemas/bifrost.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.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 (5)
core/tests/e2e_tool_test.go (2)
core/schemas/bifrost.go (3)
  • ModelChatMessageRoleUser (29-29)
  • MessageContent (158-161)
  • ModelChatMessageRoleTool (32-32)
core/utils.go (1)
  • Ptr (3-5)
core/providers/azure.go (1)
core/schemas/bifrost.go (2)
  • ModelChatMessageRoleAssistant (28-28)
  • MessageContent (158-161)
core/tests/tests.go (3)
core/schemas/provider.go (1)
  • Provider (142-149)
core/schemas/bifrost.go (7)
  • ModelChatMessageRoleUser (29-29)
  • MessageContent (158-161)
  • ContentBlock (208-212)
  • ContentBlockTypeText (204-204)
  • ContentBlockTypeImage (205-205)
  • ImageURLStruct (228-231)
  • BifrostResponse (236-246)
core/utils.go (1)
  • Ptr (3-5)
core/providers/bedrock.go (3)
core/schemas/bifrost.go (3)
  • ModelChatMessageRoleAssistant (28-28)
  • MessageContent (158-161)
  • ContentBlock (208-212)
core/providers/utils.go (2)
  • SanitizeImageURL (339-385)
  • ExtractURLTypeInfo (390-395)
core/providers/anthropic.go (1)
  • AnthropicImageContent (72-76)
core/providers/anthropic.go (3)
core/providers/utils.go (4)
  • ImageContentType (34-34)
  • SanitizeImageURL (339-385)
  • ExtractURLTypeInfo (390-395)
  • ImageContentTypeURL (38-38)
core/schemas/bifrost.go (4)
  • ModelChatMessageRoleAssistant (28-28)
  • MessageContent (158-161)
  • ImageURLStruct (228-231)
  • ContentBlock (208-212)
core/providers/bedrock.go (1)
  • BedrockAnthropicSystemMessage (69-71)
🪛 golangci-lint (1.64.8)
core/providers/cohere.go

460-460: func processImageContent is unused

(unused)

🔇 Additional comments (27)
core/providers/azure.go (1)

272-276: Good adaptation to MessageContent

The assistant reply now wraps the text in MessageContent{ContentStr: &textCopy} – this avoids dangling pointers once the pooled Azure response is released. Looks correct and keeps allocations minimal. 👍

core/providers/openai.go (1)

226-237: ⚠️ Potential issue

Sanitised URL never written back – loop uses copy, losing the mutation

for _, block := range contentBlocks { … block.ImageURL.URL = sanitizedURL } iterates by value, so the slice elements are copied; the modified block isn’t stored, leaving the original URL unsanitised.

- for _, block := range contentBlocks {
-     if block.Type == schemas.ContentBlockTypeImage && block.ImageURL != nil {
-         sanitizedURL, _ := SanitizeImageURL(block.ImageURL.URL)
-         block.ImageURL.URL = sanitizedURL
-     }
- }
+ for i := range contentBlocks {
+     if contentBlocks[i].Type == schemas.ContentBlockTypeImage && contentBlocks[i].ImageURL != nil {
+         sanitizedURL, _ := SanitizeImageURL(contentBlocks[i].ImageURL.URL)
+         contentBlocks[i].ImageURL.URL = sanitizedURL
+     }
+ }

Without this fix, OpenAI receives unsanitised URLs, defeating the security measure.

Likely an incorrect or invalid review comment.

core/tests/e2e_tool_test.go (1)

94-98: 👍 Tool-result message created only when content present

Matches the learning from PR #55 – tool result messages are emitted only when ContentStr is non-nil. Implementation aligns with guideline.

core/tests/tests.go (1)

403-415: Good addition of the getResultContent helper function.

This function properly centralizes the logic for extracting text content from either ContentStr or ContentBlocks, improving code maintainability and consistency.

docs/openapi.json (1)

112-141: LGTM! OpenAPI spec correctly reflects the new message content structure.

The schema changes properly support both simple string content (backward compatibility) and structured content blocks with mixed text and images. The new example clearly demonstrates the usage pattern.

Also applies to: 447-461, 497-534

docs/http-transport-api.md (1)

81-110: Excellent documentation updates for the new message content structure.

The documentation comprehensively covers the new structured content format with clear examples across all integration languages. The schema definitions are well-documented, and the backward compatibility with simple string content is preserved.

Also applies to: 245-273, 486-505, 598-609, 634-649, 671-684

core/providers/bedrock.go (2)

409-426: Good addition of flexible content parsing for tool calls.

The parseBedrockAnthropicMessageToolCallContent function properly handles both JSON and plain text content, providing flexibility for different tool response formats.


538-547: Verify media type format handling for Bedrock's image format field.

The code removes the "image/" prefix from the media type, but this might not work correctly for all cases. For example, if MediaType is "image/png", the result would be "png", but if it's already "png" (without prefix), it would remain "png".

Consider using a more robust approach:

-Format: func() string {
-    if formattedImgContent.MediaType != "" {
-        mediaType := formattedImgContent.MediaType
-        // Remove "image/" prefix if present, since normalizeMediaType ensures full format
-        mediaType = strings.TrimPrefix(mediaType, "image/")
-        return mediaType
-    }
-    return ""
-}(),
+Format: func() string {
+    if formattedImgContent.MediaType != "" {
+        // Extract format from media type (e.g., "image/png" -> "png", "png" -> "png")
+        parts := strings.Split(formattedImgContent.MediaType, "/")
+        if len(parts) == 2 {
+            return parts[1]
+        }
+        return formattedImgContent.MediaType
+    }
+    return ""
+}(),
core/providers/cohere.go (1)

231-231: Message content handling correctly updated to use the new structure.

The changes properly handle both ContentStr and ContentBlocks throughout the provider, maintaining compatibility while supporting the new structured content format.

Also applies to: 238-291, 427-430, 512-514

core/schemas/bifrost.go (7)

4-8: LGTM!

The import additions are necessary for the custom JSON marshalling implementation.


149-151: Well-designed content structure change.

The change from *string to MessageContent enables support for multi-modal content while maintaining backward compatibility through custom JSON marshalling.


163-178: Robust JSON marshalling implementation.

The custom marshalling correctly handles both string and content block scenarios, with proper nil checks and empty object fallback.


183-199: Flexible JSON unmarshalling with good error handling.

The implementation correctly attempts to unmarshal as both direct string and array formats, providing clear error messages when neither format matches.


201-212: Well-structured content block definition.

The ContentBlock design with type discriminator and optional fields for text/image content aligns well with the multi-modal content objectives.


216-217: Appropriate simplification of ToolMessage.

Removing ImageContent from ToolMessage aligns with the learning that only UserMessage should contain images, not tool messages.


228-231: Clean ImageURLStruct design.

The simplified structure with URL and optional detail field provides a cleaner interface for image content.

core/providers/utils.go (6)

31-31: LGTM!

The regex pattern correctly matches data URI format with optional base64 encoding.


33-46: Well-defined type system for image content.

The ImageContentType enum and URLTypeInfo struct provide clear type definitions for image URL handling.


339-385: Comprehensive URL sanitization with excellent error handling.

The function properly handles:

  • Empty URL validation
  • Data URL format validation
  • Raw base64 detection and conversion
  • HTTP/HTTPS scheme validation
  • Host validation

The automatic detection and conversion of raw base64 data to proper data URLs is particularly useful.


390-464: Well-structured URL metadata extraction.

The functions properly extract media types from both data URLs and regular URLs, with good support for common image formats.


467-495: Thorough image type detection from base64 signatures.

The detection logic covers all major image formats by checking their base64-encoded file signatures. The fallback to JPEG for unknown formats is reasonable.


498-505: Clean base64 validation logic.

The function properly validates base64 format after removing whitespace.

core/providers/anthropic.go (5)

72-76: LGTM!

The struct properly represents Anthropic's image content format.


264-268: Correct usage of MessageContent structure.

The response properly constructs a MessageContent with ContentStr for text completion responses.


415-439: Excellent handling of multi-modal content blocks.

The code properly processes both text and image content blocks, correctly using the sanitized image URLs through buildAnthropicImageSourceMap.


597-607: Clean content block construction in response parsing.

The response parser correctly creates ContentBlock structures for text content.


648-651: Proper MessageContent structure in response.

The response correctly uses ContentBlocks for the assistant message content.

@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-11-refactor_changed_content_schema_to_follow_openai branch from 5c964ce to d28c2c1 Compare June 11, 2025 13:43
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: 8

🔭 Outside diff range comments (2)
core/providers/azure.go (1)

267-276: ⚠️ Potential issue

Pointer avoidance is incomplete – the string still aliases pooled bytes

textCopy is only a shallow copy of the string header; its underlying byte slice still points to response.Body(), which will be reused once the pooled AzureTextResponse is returned.
Dereferencing this after the function returns will access mutated data and can corrupt the caller’s view.

-        // Create a copy of the text to avoid dangling pointer to pooled object
-        textCopy := response.Choices[0].Text
+        // Deep-copy the bytes so the slice no longer aliases the pooled buffer
+        textCopy := string([]byte(response.Choices[0].Text))

If you prefer Go ≥1.20, strings.Clone is clearer:

import "strings"
// …
textCopy := strings.Clone(response.Choices[0].Text)

Either approach guarantees the returned pointer owns its own backing data.

core/providers/anthropic.go (1)

329-361: ⚠️ Potential issue

Fix potential nil pointer dereference.

On line 339, *urlTypeInfo.MediaType is dereferenced without checking if it's nil, but later on line 355 there's a check for empty string. This could cause a panic if MediaType is nil.

Apply this fix:

 	formattedImgContent := AnthropicImageContent{
 		Type:      urlTypeInfo.Type,
-		MediaType: *urlTypeInfo.MediaType,
+		MediaType: "",
 	}
+	if urlTypeInfo.MediaType != nil {
+		formattedImgContent.MediaType = *urlTypeInfo.MediaType
+	}
♻️ Duplicate comments (1)
core/providers/cohere.go (1)

460-480: Unused processImageContent function maintained for future use.

The function is correctly updated to use the new ImageURLStruct type and image URL utilities. As discussed in previous reviews, this is intentionally kept for future Cohere v2 support.

🧰 Tools
🪛 golangci-lint (1.64.8)

460-460: func processImageContent is unused

(unused)

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 5c964ce and d28c2c1.

📒 Files selected for processing (12)
  • README.md (1 hunks)
  • core/providers/anthropic.go (7 hunks)
  • core/providers/azure.go (1 hunks)
  • core/providers/bedrock.go (9 hunks)
  • core/providers/cohere.go (5 hunks)
  • core/providers/openai.go (1 hunks)
  • core/providers/utils.go (2 hunks)
  • core/schemas/bifrost.go (3 hunks)
  • core/tests/e2e_tool_test.go (3 hunks)
  • core/tests/tests.go (10 hunks)
  • docs/http-transport-api.md (6 hunks)
  • docs/openapi.json (3 hunks)
🧰 Additional context used
🧠 Learnings (6)
core/tests/e2e_tool_test.go (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/bedrock.go:443-468
Timestamp: 2025-06-04T09:32:15.826Z
Learning: In core/providers/bedrock.go, for tool call result messages (ModelChatMessageRoleTool), the Content field represents the actual tool call output. A tool result message should only be created when msg.Content is non-nil, as there's no semantic meaning to a tool result without output content.
core/tests/tests.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.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.
core/providers/cohere.go (3)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:526-550
Timestamp: 2025-06-04T09:29:46.287Z
Learning: In core/providers/anthropic.go, the content field in formattedMessages is always of type []interface{} because it's explicitly constructed that way upstream in the prepareAnthropicChatRequest function. Defensive type casting for multiple types is not needed since the type is guaranteed by the construction logic.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/bedrock.go:443-468
Timestamp: 2025-06-04T09:32:15.826Z
Learning: In core/providers/bedrock.go, for tool call result messages (ModelChatMessageRoleTool), the Content field represents the actual tool call output. A tool result message should only be created when msg.Content is non-nil, as there's no semantic meaning to a tool result without output content.
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.
core/schemas/bifrost.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.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.
core/providers/bedrock.go (3)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/bedrock.go:443-468
Timestamp: 2025-06-04T09:32:15.826Z
Learning: In core/providers/bedrock.go, for tool call result messages (ModelChatMessageRoleTool), the Content field represents the actual tool call output. A tool result message should only be created when msg.Content is non-nil, as there's no semantic meaning to a tool result without output content.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:526-550
Timestamp: 2025-06-04T09:29:46.287Z
Learning: In core/providers/anthropic.go, the content field in formattedMessages is always of type []interface{} because it's explicitly constructed that way upstream in the prepareAnthropicChatRequest function. Defensive type casting for multiple types is not needed since the type is guaranteed by the construction logic.
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.
core/providers/anthropic.go (3)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:526-550
Timestamp: 2025-06-04T09:29:46.287Z
Learning: In core/providers/anthropic.go, the content field in formattedMessages is always of type []interface{} because it's explicitly constructed that way upstream in the prepareAnthropicChatRequest function. Defensive type casting for multiple types is not needed since the type is guaranteed by the construction logic.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/bedrock.go:443-468
Timestamp: 2025-06-04T09:32:15.826Z
Learning: In core/providers/bedrock.go, for tool call result messages (ModelChatMessageRoleTool), the Content field represents the actual tool call output. A tool result message should only be created when msg.Content is non-nil, as there's no semantic meaning to a tool result without output content.
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 (4)
core/providers/openai.go (2)
core/schemas/bifrost.go (2)
  • AssistantMessage (220-225)
  • ContentBlockTypeImage (205-205)
core/providers/utils.go (1)
  • SanitizeImageURL (339-385)
core/providers/azure.go (1)
core/schemas/bifrost.go (2)
  • ModelChatMessageRoleAssistant (28-28)
  • MessageContent (158-161)
core/tests/tests.go (3)
core/schemas/provider.go (1)
  • Provider (142-149)
core/schemas/bifrost.go (7)
  • ModelChatMessageRoleUser (29-29)
  • MessageContent (158-161)
  • ContentBlock (208-212)
  • ContentBlockTypeText (204-204)
  • ContentBlockTypeImage (205-205)
  • ImageURLStruct (228-231)
  • BifrostResponse (236-246)
core/utils.go (1)
  • Ptr (3-5)
core/providers/bedrock.go (3)
core/schemas/bifrost.go (3)
  • ModelChatMessageRoleAssistant (28-28)
  • MessageContent (158-161)
  • ContentBlock (208-212)
core/providers/utils.go (2)
  • SanitizeImageURL (339-385)
  • ExtractURLTypeInfo (390-395)
core/providers/anthropic.go (1)
  • AnthropicImageContent (72-76)
🪛 golangci-lint (1.64.8)
core/providers/cohere.go

460-460: func processImageContent is unused

(unused)

🔇 Additional comments (21)
README.md (1)

152-157: Example aligns with new MessageContent API – looks good

The quick-start snippet correctly uses schemas.MessageContent{ContentStr: bifrost.Ptr(...)} and the updated role constant.

core/tests/e2e_tool_test.go (1)

121-124: Helpful comment and helper usage – no issues
Switching to getResultContent removes duplication and the accompanying comment is accurate.

docs/openapi.json (3)

113-141: Well-structured example for multi-modal content.

The "structured_content" example clearly demonstrates the new message format with both text and image content, including the optional "detail" parameter for image quality control.


447-461: Proper use of oneOf for flexible content types.

The schema correctly uses OpenAPI's oneOf to support both simple string content and structured content blocks, maintaining backward compatibility while enabling new functionality.


497-534: Well-designed schemas for content blocks and image URLs.

The ContentBlock and ImageURLStruct schemas are properly structured with:

  • Clear type discrimination using the type field
  • Appropriate use of required/optional fields
  • Good enum constraints for type and detail fields
docs/http-transport-api.md (3)

81-110: Clear example of structured content request.

The example effectively demonstrates how to send a message with both text and image content, matching the OpenAPI specification.


245-273: Comprehensive schema documentation for new content types.

The tables clearly document the new BifrostMessage.content field structure and the new ContentBlock and ImageURLStruct types with appropriate field descriptions and requirements.


592-609: Well-structured client examples across multiple languages.

The Python, Node.js, and Go examples are properly updated to demonstrate both simple text messages and structured content with images, providing clear guidance for API consumers.

Also applies to: 634-649, 671-684

core/providers/bedrock.go (3)

408-426: Well-implemented tool call content parser.

The function properly handles both JSON and plain text content, with appropriate fallback behavior and array wrapping for JSON arrays.


454-466: Comprehensive system message content extraction.

The code correctly handles both ContentStr and ContentBlocks, extracting text from all content blocks when present.


519-554: Proper integration with new image URL utilities.

The image content handling correctly uses the new SanitizeImageURL and ExtractURLTypeInfo utilities, with appropriate media type extraction and formatting for the Bedrock API.

core/providers/cohere.go (4)

231-231: Correct usage of ContentStr for tool results.

The code properly uses ContentStr to access the tool result content.


238-264: Proper handling of ContentBlocks in message history.

The code correctly processes both ContentStr and ContentBlocks, extracting text content from each block appropriately.


281-291: Correct extraction of last message content.

The code properly handles both content types, concatenating text from multiple content blocks when present.


427-430: Consistent use of MessageContent structure in responses.

Both the main response and chat history conversion correctly construct MessageContent with ContentStr.

Also applies to: 512-514

core/schemas/bifrost.go (2)

201-212: LGTM!

The ContentBlock structure is well-designed with proper type safety and JSON tags.


228-231: LGTM!

The simplified ImageURLStruct provides a cleaner interface for image URLs with optional detail level.

core/providers/anthropic.go (3)

72-76: LGTM!

The provider-specific image content structure appropriately handles Anthropic's API requirements.


264-267: LGTM!

The response correctly uses the new MessageContent structure with ContentStr for text completions.


597-651: LGTM!

The response parsing correctly maintains the structure of content blocks instead of losing information by concatenating text.

core/providers/utils.go (1)

31-46: LGTM!

The updated regex correctly handles both base64 and non-base64 data URLs, and the new types provide clear structure for URL metadata.

@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-11-refactor_changed_content_schema_to_follow_openai branch from d28c2c1 to ea464dd Compare June 11, 2025 14:02
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 (4)
core/tests/e2e_tool_test.go (2)

36-39: Pointer helper verbosity ‑ comment already made earlier

The repeated bifrost.Ptr("…") calls add noise. Previous review suggested a local helper/alias; author preferred current style, so re-raising would be redundant.


95-97: Same observation as above – no further action.

core/providers/openai.go (1)

226-238: Sanitisation errors still silently discarded (previously flagged)

SanitizeImageURL returns an error that’s ignored:

sanitizedURL, _ := SanitizeImageURL(block.ImageURL.URL)

If the URL is malformed we still forward it to OpenAI, risking a 400 that’s hard to trace. Earlier review discussed bubbling or logging the error and the decision was to defer. Just noting the unchanged behaviour.

core/providers/cohere.go (1)

460-480: Function updated correctly for future use.

The processImageContent function has been properly updated to use the new ImageURLStruct type, maintaining readiness for when Cohere adds image support.

🧰 Tools
🪛 golangci-lint (1.64.8)

460-460: func processImageContent is unused

(unused)

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between d28c2c1 and ea464dd.

📒 Files selected for processing (12)
  • README.md (1 hunks)
  • core/providers/anthropic.go (7 hunks)
  • core/providers/azure.go (1 hunks)
  • core/providers/bedrock.go (9 hunks)
  • core/providers/cohere.go (5 hunks)
  • core/providers/openai.go (1 hunks)
  • core/providers/utils.go (2 hunks)
  • core/schemas/bifrost.go (3 hunks)
  • core/tests/e2e_tool_test.go (3 hunks)
  • core/tests/tests.go (10 hunks)
  • docs/http-transport-api.md (6 hunks)
  • docs/openapi.json (3 hunks)
🧰 Additional context used
🧠 Learnings (7)
core/tests/e2e_tool_test.go (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/bedrock.go:443-468
Timestamp: 2025-06-04T09:32:15.826Z
Learning: In core/providers/bedrock.go, for tool call result messages (ModelChatMessageRoleTool), the Content field represents the actual tool call output. A tool result message should only be created when msg.Content is non-nil, as there's no semantic meaning to a tool result without output content.
core/providers/openai.go (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#63
File: transports/bifrost-http/integrations/openai/types.go:89-119
Timestamp: 2025-06-10T11:00:02.852Z
Learning: In the Bifrost OpenAI integration (transports/bifrost-http/integrations/openai/types.go), the convertOpenAIContent function currently only handles the last image URL when multiple images are present in a content array. The user Pratham-Mishra04 has acknowledged this limitation and indicated it's part of a larger architectural issue that will be addressed comprehensively later, rather than with piecemeal fixes.
core/tests/tests.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.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.
core/providers/bedrock.go (3)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/bedrock.go:443-468
Timestamp: 2025-06-04T09:32:15.826Z
Learning: In core/providers/bedrock.go, for tool call result messages (ModelChatMessageRoleTool), the Content field represents the actual tool call output. A tool result message should only be created when msg.Content is non-nil, as there's no semantic meaning to a tool result without output content.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:526-550
Timestamp: 2025-06-04T09:29:46.287Z
Learning: In core/providers/anthropic.go, the content field in formattedMessages is always of type []interface{} because it's explicitly constructed that way upstream in the prepareAnthropicChatRequest function. Defensive type casting for multiple types is not needed since the type is guaranteed by the construction logic.
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.
core/providers/cohere.go (3)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:526-550
Timestamp: 2025-06-04T09:29:46.287Z
Learning: In core/providers/anthropic.go, the content field in formattedMessages is always of type []interface{} because it's explicitly constructed that way upstream in the prepareAnthropicChatRequest function. Defensive type casting for multiple types is not needed since the type is guaranteed by the construction logic.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/bedrock.go:443-468
Timestamp: 2025-06-04T09:32:15.826Z
Learning: In core/providers/bedrock.go, for tool call result messages (ModelChatMessageRoleTool), the Content field represents the actual tool call output. A tool result message should only be created when msg.Content is non-nil, as there's no semantic meaning to a tool result without output content.
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.
core/providers/anthropic.go (3)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:526-550
Timestamp: 2025-06-04T09:29:46.287Z
Learning: In core/providers/anthropic.go, the content field in formattedMessages is always of type []interface{} because it's explicitly constructed that way upstream in the prepareAnthropicChatRequest function. Defensive type casting for multiple types is not needed since the type is guaranteed by the construction logic.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/bedrock.go:443-468
Timestamp: 2025-06-04T09:32:15.826Z
Learning: In core/providers/bedrock.go, for tool call result messages (ModelChatMessageRoleTool), the Content field represents the actual tool call output. A tool result message should only be created when msg.Content is non-nil, as there's no semantic meaning to a tool result without output content.
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.
core/schemas/bifrost.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.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 (4)
core/providers/azure.go (1)
core/schemas/bifrost.go (2)
  • ModelChatMessageRoleAssistant (28-28)
  • MessageContent (158-161)
core/tests/e2e_tool_test.go (2)
core/schemas/bifrost.go (3)
  • ModelChatMessageRoleUser (29-29)
  • MessageContent (158-161)
  • ModelChatMessageRoleTool (32-32)
core/utils.go (1)
  • Ptr (3-5)
core/providers/openai.go (2)
core/schemas/bifrost.go (2)
  • AssistantMessage (221-226)
  • ContentBlockTypeImage (206-206)
core/providers/utils.go (1)
  • SanitizeImageURL (343-389)
core/tests/tests.go (3)
core/schemas/provider.go (1)
  • Provider (142-149)
core/schemas/bifrost.go (7)
  • ModelChatMessageRoleUser (29-29)
  • MessageContent (158-161)
  • ContentBlock (209-213)
  • ContentBlockTypeText (205-205)
  • ContentBlockTypeImage (206-206)
  • ImageURLStruct (229-232)
  • BifrostResponse (237-247)
core/utils.go (1)
  • Ptr (3-5)
🪛 golangci-lint (1.64.8)
core/providers/cohere.go

460-460: func processImageContent is unused

(unused)

🔇 Additional comments (15)
core/providers/azure.go (1)

272-276: New MessageContent integration looks correct

The text completion branch now wraps the plain string inside the new schemas.MessageContent struct, which keeps the provider aligned with the global multimodal refactor. Copying the string into textCopy avoids holding a pointer to the pooled response buffer – nice touch.

README.md (1)

152-157: README snippet updated for multimodal refactor – LGTM

The example now uses the schemas.MessageContent wrapper and the canonical role constant. Nothing blocking.

core/tests/e2e_tool_test.go (1)

121-123: Good use of getResultContent helper

Switching to the shared helper eliminates duplicated pointer-deref logic.

docs/http-transport-api.md (1)

81-684: Documentation updates are comprehensive and well-structured.

The documentation clearly explains the new structured content format with:

  • Clear examples showing how to combine text and image content
  • Updated schema definitions for ContentBlock and ImageURLStruct
  • Practical examples in multiple languages (curl, Python, Node.js, Go)
  • Backward compatibility maintained with string content option
🧰 Tools
🪛 LanguageTool

[uncategorized] ~239-~239: Possible missing comma found.
Context: ... | *Either messages or text is required depending on the endpoint. ### Bifrost...

(AI_HYDRA_LEO_MISSING_COMMA)

docs/openapi.json (1)

112-534: OpenAPI specification correctly implements the new content structure.

The changes properly define the polymorphic content field using oneOf pattern and include:

  • Well-structured ContentBlock schema with required fields
  • ImageURLStruct with appropriate properties and enums for detail levels
  • Comprehensive example demonstrating the new structured content format
🧰 Tools
🪛 Checkov (3.2.334)

[MEDIUM] 384-390: Ensure that arrays have a maximum number of items

(CKV_OPENAPI_21)

core/providers/bedrock.go (3)

408-427: Well-designed helper function for tool call content parsing.

The parseBedrockAnthropicMessageToolCallContent function correctly handles both JSON and plain text content, providing a flexible approach to parsing tool results.


454-492: Correct handling of system and tool messages with new content structure.

The implementation properly extracts text content from both ContentStr and ContentBlocks for system messages, and correctly aggregates tool call results using the parsing helper function.


513-554: Proper implementation of image content processing and multi-modal response handling.

The changes correctly:

  • Process image URLs with sanitization and metadata extraction
  • Handle the Bedrock-specific image format requirements
  • Preserve multi-modal content in responses by using ContentBlocks instead of concatenating text

Also applies to: 909-961

core/providers/cohere.go (1)

231-291: Consistent implementation of the new MessageContent structure.

The Cohere provider correctly handles the new content structure:

  • Tool results properly access Content.ContentStr
  • Message content handling supports both ContentStr and ContentBlocks
  • Chat history conversion wraps strings in MessageContent

Note: The image content code is intentionally commented out as Cohere v1 doesn't support images.

Also applies to: 427-431, 511-515

core/schemas/bifrost.go (2)

158-179: Well-implemented polymorphic content structure with proper validation.

The MessageContent implementation correctly addresses the previous marshaling issues and includes validation to ensure only one field is set at a time. The direct marshaling without wrapper objects is the correct approach.


202-213: Clean discriminated union pattern for multi-modal content blocks.

The ContentBlock structure with its type discriminator is well-designed for handling different content types. The optional fields align properly with the content type.

core/providers/anthropic.go (2)

328-361: Proper integration with new image URL utilities.

The refactored buildAnthropicImageSourceMap correctly utilizes the new sanitization and type extraction utilities, providing consistent image URL handling across the codebase.


597-651: Correct adaptation to structured content blocks.

The response parsing now properly creates an array of ContentBlock elements instead of concatenating text, preserving the structured nature of the response content.

core/providers/utils.go (2)

340-389: Comprehensive URL sanitization with proper validation.

The SanitizeImageURL function provides thorough validation and sanitization for all supported URL types - data URLs, raw base64, and regular HTTP(S) URLs. The automatic detection and conversion of raw base64 to proper data URLs is a helpful feature.


470-508: Robust image type detection using header signatures and extensions.

The image type detection logic efficiently identifies common image formats using base64 header signatures and file extensions. The fallback to JPEG for unknown formats is a reasonable default. The pre-compiled regex for base64 validation addresses the previous performance concern.

@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-11-refactor_changed_content_schema_to_follow_openai branch from ea464dd to ead45eb Compare June 11, 2025 14:13
@Pratham-Mishra04 Pratham-Mishra04 marked this pull request as ready for review June 11, 2025 14:17
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 ea464dd and ead45eb.

📒 Files selected for processing (12)
  • README.md (1 hunks)
  • core/providers/anthropic.go (7 hunks)
  • core/providers/azure.go (1 hunks)
  • core/providers/bedrock.go (9 hunks)
  • core/providers/cohere.go (5 hunks)
  • core/providers/openai.go (1 hunks)
  • core/providers/utils.go (2 hunks)
  • core/schemas/bifrost.go (3 hunks)
  • core/tests/e2e_tool_test.go (3 hunks)
  • core/tests/tests.go (10 hunks)
  • docs/http-transport-api.md (6 hunks)
  • docs/openapi.json (3 hunks)
🧰 Additional context used
🧠 Learnings (7)
core/tests/e2e_tool_test.go (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/bedrock.go:443-468
Timestamp: 2025-06-04T09:32:15.826Z
Learning: In core/providers/bedrock.go, for tool call result messages (ModelChatMessageRoleTool), the Content field represents the actual tool call output. A tool result message should only be created when msg.Content is non-nil, as there's no semantic meaning to a tool result without output content.
core/tests/tests.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.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.
core/providers/bedrock.go (3)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/bedrock.go:443-468
Timestamp: 2025-06-04T09:32:15.826Z
Learning: In core/providers/bedrock.go, for tool call result messages (ModelChatMessageRoleTool), the Content field represents the actual tool call output. A tool result message should only be created when msg.Content is non-nil, as there's no semantic meaning to a tool result without output content.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:526-550
Timestamp: 2025-06-04T09:29:46.287Z
Learning: In core/providers/anthropic.go, the content field in formattedMessages is always of type []interface{} because it's explicitly constructed that way upstream in the prepareAnthropicChatRequest function. Defensive type casting for multiple types is not needed since the type is guaranteed by the construction logic.
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.
core/providers/openai.go (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#63
File: transports/bifrost-http/integrations/openai/types.go:89-119
Timestamp: 2025-06-10T11:00:02.852Z
Learning: In the Bifrost OpenAI integration (transports/bifrost-http/integrations/openai/types.go), the convertOpenAIContent function currently only handles the last image URL when multiple images are present in a content array. The user Pratham-Mishra04 has acknowledged this limitation and indicated it's part of a larger architectural issue that will be addressed comprehensively later, rather than with piecemeal fixes.
core/providers/cohere.go (3)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:526-550
Timestamp: 2025-06-04T09:29:46.287Z
Learning: In core/providers/anthropic.go, the content field in formattedMessages is always of type []interface{} because it's explicitly constructed that way upstream in the prepareAnthropicChatRequest function. Defensive type casting for multiple types is not needed since the type is guaranteed by the construction logic.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/bedrock.go:443-468
Timestamp: 2025-06-04T09:32:15.826Z
Learning: In core/providers/bedrock.go, for tool call result messages (ModelChatMessageRoleTool), the Content field represents the actual tool call output. A tool result message should only be created when msg.Content is non-nil, as there's no semantic meaning to a tool result without output content.
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.
core/providers/anthropic.go (3)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:526-550
Timestamp: 2025-06-04T09:29:46.287Z
Learning: In core/providers/anthropic.go, the content field in formattedMessages is always of type []interface{} because it's explicitly constructed that way upstream in the prepareAnthropicChatRequest function. Defensive type casting for multiple types is not needed since the type is guaranteed by the construction logic.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/bedrock.go:443-468
Timestamp: 2025-06-04T09:32:15.826Z
Learning: In core/providers/bedrock.go, for tool call result messages (ModelChatMessageRoleTool), the Content field represents the actual tool call output. A tool result message should only be created when msg.Content is non-nil, as there's no semantic meaning to a tool result without output content.
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.
core/schemas/bifrost.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.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 (5)
core/providers/azure.go (1)
core/schemas/bifrost.go (2)
  • ModelChatMessageRoleAssistant (28-28)
  • MessageContent (158-161)
core/tests/e2e_tool_test.go (2)
core/schemas/bifrost.go (3)
  • ModelChatMessageRoleUser (29-29)
  • MessageContent (158-161)
  • ModelChatMessageRoleTool (32-32)
core/utils.go (1)
  • Ptr (3-5)
core/tests/tests.go (3)
core/schemas/provider.go (1)
  • Provider (142-149)
core/schemas/bifrost.go (7)
  • ModelChatMessageRoleUser (29-29)
  • MessageContent (158-161)
  • ContentBlock (209-213)
  • ContentBlockTypeText (205-205)
  • ContentBlockTypeImage (206-206)
  • ImageURLStruct (229-232)
  • BifrostResponse (237-247)
core/utils.go (1)
  • Ptr (3-5)
core/providers/cohere.go (3)
core/schemas/bifrost.go (2)
  • MessageContent (158-161)
  • ImageURLStruct (229-232)
core/providers/utils.go (2)
  • SanitizeImageURL (343-389)
  • ExtractURLTypeInfo (394-399)
core/providers/anthropic.go (1)
  • AnthropicImageContent (72-76)
core/providers/anthropic.go (3)
core/providers/utils.go (4)
  • ImageContentType (38-38)
  • SanitizeImageURL (343-389)
  • ExtractURLTypeInfo (394-399)
  • ImageContentTypeURL (42-42)
core/schemas/bifrost.go (4)
  • ModelChatMessageRoleAssistant (28-28)
  • MessageContent (158-161)
  • ImageURLStruct (229-232)
  • ContentBlock (209-213)
core/providers/bedrock.go (1)
  • BedrockAnthropicSystemMessage (69-71)
🪛 golangci-lint (1.64.8)
core/providers/cohere.go

460-460: func processImageContent is unused

(unused)

🔇 Additional comments (23)
README.md (1)

152-157: Example compiles & matches new API

The quick-start snippet correctly demonstrates the MessageContent wrapper and the helper pointer function. ✅

core/tests/e2e_tool_test.go (3)

35-40: Message construction aligns with new schema

The test now wraps the prompt in MessageContent, preventing compilation mismatches with the refactor.
Looks good.


94-99: Tool result message correctly populated

Role: tool messages now carry the JSON result inside ContentStr; this matches the contract added in #55.
No issues spotted.


121-124: Helper usage improves readability

Using getResultContent removes duplication and centralises pointer-handling. Nice clean-up.

core/tests/tests.go (4)

112-117: Log output streamlined

Single call to getResultContent keeps the logging path consistent across tests.


147-152: Pointer helper keeps code terse

Good use of bifrost.Ptr for test messages – reduces boilerplate.


190-205: Image-input test matches multimodal contract

The URL & text blocks are constructed per spec; test should exercise provider handling correctly.


393-409: Guard-clause makes helper safe

The early-return prevents panics on malformed responses – thanks for adding it.

docs/http-transport-api.md (1)

81-109: Documentation updates are comprehensive and well-structured.

The additions clearly explain the new structured content format, provide helpful examples for text+image messages, and update all integration code samples consistently. The schema definitions for ContentBlock and ImageURLStruct are properly documented with all required fields marked.

Also applies to: 245-273, 486-505, 598-608, 634-649, 672-684

docs/openapi.json (1)

113-141: OpenAPI specification correctly reflects the new content structure.

The oneOf schema for message content properly supports both simple strings and structured content blocks. The example demonstrates the new format clearly, and the schema definitions are consistent with the API documentation.

Also applies to: 447-461, 497-534

core/providers/bedrock.go (4)

408-426: Well-designed helper function for flexible content parsing.

The function properly handles both JSON and plain text content, with appropriate fallback behavior. The special handling for arrays (wrapping in a content object) ensures consistent structure.


454-466: Content extraction properly handles all message formats.

The implementation correctly:

  • Extracts system message text from either single strings or multiple content blocks
  • Aggregates tool call results using the new parsing helper
  • Processes image content with proper URL sanitization and media type extraction

Also applies to: 480-490, 513-554


342-346: Text completion results correctly use the new MessageContent structure.

The response content is properly wrapped in MessageContent with ContentStr, maintaining consistency with the new content format.

Also applies to: 382-386


909-917: Chat completion response correctly uses content blocks.

The implementation properly collects text content as individual ContentBlock entries and sets the final message content using ContentBlocks instead of a single concatenated string.

Also applies to: 957-960

core/providers/cohere.go (2)

231-232: Other content handling changes are implemented correctly.

The code properly:

  • Uses ContentStr for tool message outputs
  • Handles last message content extraction from both formats
  • Wraps response messages in the new MessageContent structure

Also applies to: 281-291, 427-430, 511-514


245-257: ⚠️ Potential issue

Fix logic error in content block processing.

Inside the ContentBlocks iteration, the code incorrectly checks msg.Content.ContentStr instead of using the block's text content. This would add the message-level content string multiple times.

Apply this fix to correctly process content blocks:

 } else if msg.Content.ContentBlocks != nil {
 	for _, block := range *msg.Content.ContentBlocks {
 		if block.Text != nil {
 			contentArray = append(contentArray, map[string]interface{}{
 				"type": "text",
 				"text": *block.Text,
 			})
 		}
-		// Add image content using our helper function
-		// NOTE: Cohere v1 does not support image content
-		// if processedImageContent := processImageContent(block.ImageContent); processedImageContent != nil {
-		// 	contentArray = append(contentArray, processedImageContent)
-		// }
 	}
 }

Also remove the redundant outer condition:

-if msg.Content.ContentStr != nil {
-	contentArray = append(contentArray, map[string]interface{}{
-		"type": "text",
-		"text": *msg.Content.ContentStr,
-	})
-} else if msg.Content.ContentBlocks != nil {
+if msg.Content.ContentBlocks != nil {

Likely an incorrect or invalid review comment.

core/schemas/bifrost.go (4)

158-161: LGTM! Well-designed polymorphic content structure.

The MessageContent struct provides a clean way to represent either simple text or structured content blocks, aligning well with the multi-modal content requirements.


165-179: Excellent implementation addressing previous concerns.

The MarshalJSON method correctly:

  • Validates that only one field is set at a time
  • Marshals content directly without wrapping
  • Returns null for empty content

This addresses the previous review feedback perfectly.


183-200: Clean unmarshalling logic with proper type detection.

The UnmarshalJSON method correctly handles both string and array formats, providing clear error messages when the content doesn't match either expected type.


202-213: Well-structured content block definitions.

The ContentBlock type and structure provide a flexible foundation for multi-modal content, with clear type constants and proper JSON serialization tags.

core/providers/anthropic.go (2)

329-361: Excellent refactoring using centralized URL utilities.

The updated buildAnthropicImageSourceMap function now leverages the new SanitizeImageURL and ExtractURLTypeInfo utilities, improving consistency across providers and centralizing URL validation logic.


597-651: Good adaptation to structured content blocks.

The response parsing now properly creates an array of ContentBlock items instead of concatenating text, preserving the response structure and aligning with the new content model.

core/providers/utils.go (1)

343-389: Comprehensive URL sanitization with good error handling.

The SanitizeImageURL function provides thorough validation for all URL types:

  • Proper data URL format validation
  • Raw base64 detection and conversion
  • HTTP/HTTPS URL validation with scheme and host checks

The implementation handles edge cases well with clear error messages.

@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-11-refactor_changed_content_schema_to_follow_openai branch from ead45eb to fc217ab Compare June 11, 2025 14:28
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 (2)
core/providers/azure.go (1)

272-275: Prior suggestion already discussed – no further action

The manual &textCopy address-taking is still present. This mirrors the earlier discussion on using bifrost.Ptr(...); since you explicitly chose to keep the manual pointer last round, I’m not re-opening the topic.

core/providers/openai.go (1)

226-234: Sanitisation-error handling unchanged (see prior review)

The SanitizeImageURL error is still discarded and URL updates occur on a copy of the slice header—both points were covered in earlier feedback. No extra comments here.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between ead45eb and fc217ab.

📒 Files selected for processing (12)
  • README.md (1 hunks)
  • core/providers/anthropic.go (7 hunks)
  • core/providers/azure.go (1 hunks)
  • core/providers/bedrock.go (9 hunks)
  • core/providers/cohere.go (5 hunks)
  • core/providers/openai.go (1 hunks)
  • core/providers/utils.go (2 hunks)
  • core/schemas/bifrost.go (3 hunks)
  • core/tests/e2e_tool_test.go (3 hunks)
  • core/tests/tests.go (10 hunks)
  • docs/http-transport-api.md (6 hunks)
  • docs/openapi.json (3 hunks)
🧰 Additional context used
🧠 Learnings (7)
core/tests/e2e_tool_test.go (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/bedrock.go:443-468
Timestamp: 2025-06-04T09:32:15.826Z
Learning: In core/providers/bedrock.go, for tool call result messages (ModelChatMessageRoleTool), the Content field represents the actual tool call output. A tool result message should only be created when msg.Content is non-nil, as there's no semantic meaning to a tool result without output content.
core/providers/openai.go (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#63
File: transports/bifrost-http/integrations/openai/types.go:89-119
Timestamp: 2025-06-10T11:00:02.852Z
Learning: In the Bifrost OpenAI integration (transports/bifrost-http/integrations/openai/types.go), the convertOpenAIContent function currently only handles the last image URL when multiple images are present in a content array. The user Pratham-Mishra04 has acknowledged this limitation and indicated it's part of a larger architectural issue that will be addressed comprehensively later, rather than with piecemeal fixes.
core/tests/tests.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.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.
core/providers/bedrock.go (3)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/bedrock.go:443-468
Timestamp: 2025-06-04T09:32:15.826Z
Learning: In core/providers/bedrock.go, for tool call result messages (ModelChatMessageRoleTool), the Content field represents the actual tool call output. A tool result message should only be created when msg.Content is non-nil, as there's no semantic meaning to a tool result without output content.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:526-550
Timestamp: 2025-06-04T09:29:46.287Z
Learning: In core/providers/anthropic.go, the content field in formattedMessages is always of type []interface{} because it's explicitly constructed that way upstream in the prepareAnthropicChatRequest function. Defensive type casting for multiple types is not needed since the type is guaranteed by the construction logic.
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.
core/providers/anthropic.go (3)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:526-550
Timestamp: 2025-06-04T09:29:46.287Z
Learning: In core/providers/anthropic.go, the content field in formattedMessages is always of type []interface{} because it's explicitly constructed that way upstream in the prepareAnthropicChatRequest function. Defensive type casting for multiple types is not needed since the type is guaranteed by the construction logic.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/bedrock.go:443-468
Timestamp: 2025-06-04T09:32:15.826Z
Learning: In core/providers/bedrock.go, for tool call result messages (ModelChatMessageRoleTool), the Content field represents the actual tool call output. A tool result message should only be created when msg.Content is non-nil, as there's no semantic meaning to a tool result without output content.
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.
core/schemas/bifrost.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.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.
core/providers/cohere.go (3)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:526-550
Timestamp: 2025-06-04T09:29:46.287Z
Learning: In core/providers/anthropic.go, the content field in formattedMessages is always of type []interface{} because it's explicitly constructed that way upstream in the prepareAnthropicChatRequest function. Defensive type casting for multiple types is not needed since the type is guaranteed by the construction logic.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/bedrock.go:443-468
Timestamp: 2025-06-04T09:32:15.826Z
Learning: In core/providers/bedrock.go, for tool call result messages (ModelChatMessageRoleTool), the Content field represents the actual tool call output. A tool result message should only be created when msg.Content is non-nil, as there's no semantic meaning to a tool result without output content.
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 (5)
core/tests/e2e_tool_test.go (2)
core/schemas/bifrost.go (3)
  • ModelChatMessageRoleUser (29-29)
  • MessageContent (158-161)
  • ModelChatMessageRoleTool (32-32)
core/utils.go (1)
  • Ptr (3-5)
core/providers/azure.go (1)
core/schemas/bifrost.go (2)
  • ModelChatMessageRoleAssistant (28-28)
  • MessageContent (158-161)
core/providers/openai.go (2)
core/schemas/bifrost.go (2)
  • AssistantMessage (221-226)
  • ContentBlockTypeImage (206-206)
core/providers/utils.go (1)
  • SanitizeImageURL (355-401)
core/tests/tests.go (3)
core/schemas/provider.go (1)
  • Provider (142-149)
core/schemas/bifrost.go (7)
  • ModelChatMessageRoleUser (29-29)
  • MessageContent (158-161)
  • ContentBlock (209-213)
  • ContentBlockTypeText (205-205)
  • ContentBlockTypeImage (206-206)
  • ImageURLStruct (229-232)
  • BifrostResponse (237-247)
core/utils.go (1)
  • Ptr (3-5)
core/providers/anthropic.go (3)
core/providers/utils.go (4)
  • ImageContentType (50-50)
  • SanitizeImageURL (355-401)
  • ExtractURLTypeInfo (406-411)
  • ImageContentTypeURL (54-54)
core/schemas/bifrost.go (4)
  • ModelChatMessageRoleAssistant (28-28)
  • MessageContent (158-161)
  • ImageURLStruct (229-232)
  • ContentBlock (209-213)
core/providers/bedrock.go (1)
  • BedrockAnthropicSystemMessage (69-71)
🪛 golangci-lint (1.64.8)
core/providers/cohere.go

460-460: func processImageContent is unused

(unused)

🔇 Additional comments (12)
README.md (1)

152-157: Example aligns with new MessageContent API

Nice, the snippet now mirrors the struct-based content used in code. No issues spotted.

core/tests/e2e_tool_test.go (1)

121-126: getResultContent keeps the assertion concise

Switching to the helper removes pointer boiler-plate and reads well. Looks good.

docs/http-transport-api.md (1)

81-110: Documentation updates are comprehensive and well-structured.

The documentation clearly explains the new structured content format with appropriate examples demonstrating how to send messages with mixed text and image content. The schema definitions for ContentBlock and ImageURLStruct are properly documented with all required fields and descriptions.

Also applies to: 245-273, 487-505

docs/openapi.json (1)

113-141: OpenAPI specification correctly reflects the new content structure.

The schema changes properly define the polymorphic content field using oneOf, allowing both simple strings and structured content blocks. The new ContentBlock and ImageURLStruct schemas are well-defined with appropriate required fields and enums.

Also applies to: 447-462, 497-534

core/providers/bedrock.go (3)

409-426: Well-designed helper function for parsing tool call content.

The parseBedrockAnthropicMessageToolCallContent function elegantly handles both JSON and plain text content, providing a consistent interface for tool results.


454-466: Proper implementation of the new MessageContent structure.

The code correctly handles both ContentStr and ContentBlocks throughout the message preparation logic. The image URL sanitization and metadata extraction are properly integrated using the new utility functions.

Also applies to: 479-490, 513-554


909-917: Response content aggregation correctly uses ContentBlocks.

The change from string concatenation to collecting ContentBlock entries aligns with the new structured content format, providing better flexibility for multi-modal responses.

Also applies to: 957-960

core/schemas/bifrost.go (1)

166-179: Well-implemented validation in MarshalJSON!

The validation logic correctly ensures that only one of ContentStr or ContentBlocks is set at a time, preventing undefined behavior. The direct marshaling without wrapper objects is also correct.

core/providers/anthropic.go (2)

329-361: Excellent integration with the new image URL utilities!

The updated buildAnthropicImageSourceMap function correctly:

  • Sanitizes the image URL
  • Extracts URL type information
  • Handles both regular URLs and data URLs without prefixes
  • Properly maps the content based on the detected type

The implementation aligns perfectly with the new structured content model.


403-410: ⚠️ Potential issue

Potential nil pointer dereference in tool message content.

At line 407, block.Text is used directly without checking if it's nil. While text blocks should have text content, consider adding a nil check for defensive programming:

 } else if msg.Content.ContentBlocks != nil {
     for _, block := range *msg.Content.ContentBlocks {
-        toolCallResultContent = append(toolCallResultContent, map[string]interface{}{
-            "type": "text",
-            "text": block.Text,
-        })
+        if block.Text != nil {
+            toolCallResultContent = append(toolCallResultContent, map[string]interface{}{
+                "type": "text",
+                "text": *block.Text,
+            })
+        }
     }
 }
⛔ Skipped due to learnings
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/bedrock.go:443-468
Timestamp: 2025-06-04T09:32:15.826Z
Learning: In core/providers/bedrock.go, for tool call result messages (ModelChatMessageRoleTool), the Content field represents the actual tool call output. A tool result message should only be created when msg.Content is non-nil, as there's no semantic meaning to a tool result without output content.
core/providers/utils.go (2)

31-47: Great improvements addressing previous feedback!

The implementation successfully addresses all previous review comments:

  • ✓ Pre-compiled regex patterns for efficiency
  • ✓ File extension mapping extracted into a maintainable map
  • ✓ More precise WebP detection

The code is well-structured and efficient.


489-491: WebP detection properly checks exact header positions.

The WebP detection now correctly validates both the RIFF header at the start and the WEBP signature at the precise offset, ensuring accurate format detection.

@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-11-refactor_changed_content_schema_to_follow_openai branch from fc217ab to 05c93c4 Compare June 11, 2025 14:40
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

🔭 Outside diff range comments (1)
core/providers/cohere.go (1)

453-473: 💡 Verification agent

🧩 Analysis chain

Fix provider-specific type usage.

The processImageContent function creates an AnthropicImageContent struct within the Cohere provider. This cross-provider type usage is inconsistent and could cause confusion. Consider either:

  1. Creating a Cohere-specific image content type
  2. Using a generic/shared image content structure
  3. Removing the function entirely since it's unused (as indicated by static analysis)

🏁 Script executed:

#!/bin/bash
# Check if AnthropicImageContent is used elsewhere in cohere.go or if there's a Cohere-specific type
rg "AnthropicImageContent" core/providers/cohere.go
rg "CohereImageContent" core/providers/

Length of output: 138


Align image content type in the Cohere provider

  • In core/providers/cohere.go (lines 453–473), processImageContent is instantiating AnthropicImageContent inside the Cohere provider—even though no CohereImageContent or shared ImageContent type exists.
  • To resolve this inconsistency, choose one of the following:
    1. Define a CohereImageContent struct and use it here.
    2. Extract a generic/shared ImageContent type for all providers.
    3. Remove the unused processImageContent function (static analysis shows it’s not referenced elsewhere).
🧰 Tools
🪛 golangci-lint (1.64.8)

453-453: func processImageContent is unused

(unused)

♻️ Duplicate comments (1)
core/providers/cohere.go (1)

238-257: Logic correctly handles both content types.

The implementation properly handles both ContentStr and ContentBlocks cases without redundant checks. The commented image content code is appropriately preserved for future Cohere versions.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between fc217ab and 05c93c4.

📒 Files selected for processing (12)
  • README.md (1 hunks)
  • core/providers/anthropic.go (7 hunks)
  • core/providers/azure.go (1 hunks)
  • core/providers/bedrock.go (9 hunks)
  • core/providers/cohere.go (5 hunks)
  • core/providers/openai.go (1 hunks)
  • core/providers/utils.go (2 hunks)
  • core/schemas/bifrost.go (3 hunks)
  • core/tests/e2e_tool_test.go (3 hunks)
  • core/tests/tests.go (10 hunks)
  • docs/http-transport-api.md (6 hunks)
  • docs/openapi.json (3 hunks)
🧰 Additional context used
🧠 Learnings (7)
core/tests/e2e_tool_test.go (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/bedrock.go:443-468
Timestamp: 2025-06-04T09:32:15.826Z
Learning: In core/providers/bedrock.go, for tool call result messages (ModelChatMessageRoleTool), the Content field represents the actual tool call output. A tool result message should only be created when msg.Content is non-nil, as there's no semantic meaning to a tool result without output content.
core/tests/tests.go (2)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#74
File: core/tests/tests.go:393-409
Timestamp: 2025-06-11T14:35:19.121Z
Learning: In core/tests/tests.go, the helper function getResultContent is intentionally designed to extract content only from the first element of result.Choices; this is expected behavior for the current test strategy.
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.
core/providers/openai.go (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#63
File: transports/bifrost-http/integrations/openai/types.go:89-119
Timestamp: 2025-06-10T11:00:02.852Z
Learning: In the Bifrost OpenAI integration (transports/bifrost-http/integrations/openai/types.go), the convertOpenAIContent function currently only handles the last image URL when multiple images are present in a content array. The user Pratham-Mishra04 has acknowledged this limitation and indicated it's part of a larger architectural issue that will be addressed comprehensively later, rather than with piecemeal fixes.
core/providers/bedrock.go (3)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/bedrock.go:443-468
Timestamp: 2025-06-04T09:32:15.826Z
Learning: In core/providers/bedrock.go, for tool call result messages (ModelChatMessageRoleTool), the Content field represents the actual tool call output. A tool result message should only be created when msg.Content is non-nil, as there's no semantic meaning to a tool result without output content.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:526-550
Timestamp: 2025-06-04T09:29:46.287Z
Learning: In core/providers/anthropic.go, the content field in formattedMessages is always of type []interface{} because it's explicitly constructed that way upstream in the prepareAnthropicChatRequest function. Defensive type casting for multiple types is not needed since the type is guaranteed by the construction logic.
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.
core/providers/cohere.go (3)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:526-550
Timestamp: 2025-06-04T09:29:46.287Z
Learning: In core/providers/anthropic.go, the content field in formattedMessages is always of type []interface{} because it's explicitly constructed that way upstream in the prepareAnthropicChatRequest function. Defensive type casting for multiple types is not needed since the type is guaranteed by the construction logic.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/bedrock.go:443-468
Timestamp: 2025-06-04T09:32:15.826Z
Learning: In core/providers/bedrock.go, for tool call result messages (ModelChatMessageRoleTool), the Content field represents the actual tool call output. A tool result message should only be created when msg.Content is non-nil, as there's no semantic meaning to a tool result without output content.
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.
core/schemas/bifrost.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.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.
core/providers/anthropic.go (3)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:526-550
Timestamp: 2025-06-04T09:29:46.287Z
Learning: In core/providers/anthropic.go, the content field in formattedMessages is always of type []interface{} because it's explicitly constructed that way upstream in the prepareAnthropicChatRequest function. Defensive type casting for multiple types is not needed since the type is guaranteed by the construction logic.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/bedrock.go:443-468
Timestamp: 2025-06-04T09:32:15.826Z
Learning: In core/providers/bedrock.go, for tool call result messages (ModelChatMessageRoleTool), the Content field represents the actual tool call output. A tool result message should only be created when msg.Content is non-nil, as there's no semantic meaning to a tool result without output content.
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 (6)
core/providers/azure.go (1)
core/schemas/bifrost.go (2)
  • ModelChatMessageRoleAssistant (28-28)
  • MessageContent (158-161)
core/tests/e2e_tool_test.go (2)
core/schemas/bifrost.go (3)
  • ModelChatMessageRoleUser (29-29)
  • MessageContent (158-161)
  • ModelChatMessageRoleTool (32-32)
core/utils.go (1)
  • Ptr (3-5)
core/tests/tests.go (3)
core/schemas/provider.go (1)
  • Provider (142-149)
core/schemas/bifrost.go (7)
  • ModelChatMessageRoleUser (29-29)
  • MessageContent (158-161)
  • ContentBlock (209-213)
  • ContentBlockTypeText (205-205)
  • ContentBlockTypeImage (206-206)
  • ImageURLStruct (229-232)
  • BifrostResponse (237-247)
core/utils.go (1)
  • Ptr (3-5)
core/providers/openai.go (2)
core/schemas/bifrost.go (2)
  • AssistantMessage (221-226)
  • ContentBlockTypeImage (206-206)
core/providers/utils.go (1)
  • SanitizeImageURL (355-401)
core/providers/cohere.go (3)
core/schemas/bifrost.go (2)
  • MessageContent (158-161)
  • ImageURLStruct (229-232)
core/providers/utils.go (2)
  • SanitizeImageURL (355-401)
  • ExtractURLTypeInfo (406-411)
core/providers/anthropic.go (1)
  • AnthropicImageContent (72-76)
core/providers/anthropic.go (3)
core/providers/utils.go (4)
  • ImageContentType (50-50)
  • SanitizeImageURL (355-401)
  • ExtractURLTypeInfo (406-411)
  • ImageContentTypeURL (54-54)
core/schemas/bifrost.go (4)
  • ModelChatMessageRoleAssistant (28-28)
  • MessageContent (158-161)
  • ImageURLStruct (229-232)
  • ContentBlock (209-213)
core/providers/bedrock.go (1)
  • BedrockAnthropicSystemMessage (69-71)
🪛 golangci-lint (1.64.8)
core/providers/cohere.go

453-453: func processImageContent is unused

(unused)

🔇 Additional comments (23)
core/providers/utils.go (3)

29-47: Well-structured constants and pre-compiled patterns!

The pre-compiled regex patterns and the file extension map are well-implemented, addressing previous performance and maintainability concerns effectively.


352-401: Comprehensive URL sanitization implementation!

The function provides thorough validation for all URL types (data URLs, base64, HTTP/HTTPS) with clear error messages for each validation failure case.


470-499: Accurate image type detection with improved WebP handling!

The function correctly identifies image formats from base64 signatures, with precise WebP detection using exact header position and signature location as suggested in previous reviews.

core/providers/azure.go (1)

272-276: Correct implementation of the new MessageContent structure!

The change properly wraps the text content in the MessageContent struct, aligning with the refactored message content structure across the codebase.

README.md (1)

152-157: Example accurately reflects the new message content structure!

The updated example correctly demonstrates the new BifrostMessage type with MessageContent wrapper, providing users with an accurate reference for the current API.

core/tests/e2e_tool_test.go (1)

36-40: Test correctly updated to use the new MessageContent structure!

The test properly constructs messages with the MessageContent wrapper and uses the getResultContent helper for safe content extraction, ensuring compatibility with the refactored message structure.

Also applies to: 94-97, 121-123

core/tests/tests.go (2)

147-152: Consistent and correct message construction throughout tests!

All test messages properly use the new MessageContent structure:

  • Text-only messages correctly use ContentStr
  • Multi-modal messages properly use ContentBlocks with appropriate types
  • Image URLs (both HTTP and base64) are correctly wrapped in ImageURLStruct

Also applies to: 191-204, 233-246, 302-306


393-409: Well-implemented content extraction helper!

The getResultContent function properly handles both content formats (string and blocks) with appropriate nil checks, providing a clean abstraction for test result verification.

core/providers/openai.go (2)

215-215: LGTM! Correct content access for assistant messages.

The code properly uses ContentStr for assistant messages, which aligns with the schema design where assistant messages cannot contain images.


226-238: Well-implemented polymorphic content handling.

The code correctly handles both simple string content and structured content blocks. The index-based iteration properly modifies the underlying slice elements, and the image URL sanitization is applied as expected.

Note: Sanitization errors are intentionally ignored to let OpenAI handle invalid URLs, as per the design decision.

docs/openapi.json (1)

113-141: Excellent OpenAPI documentation updates!

The schema changes accurately reflect the new polymorphic content structure:

  • The oneOf schema properly documents that content can be either a string or an array of ContentBlock objects
  • The new structured_content example clearly demonstrates the usage
  • ContentBlock and ImageURLStruct schemas are well-defined with appropriate descriptions

Also applies to: 447-462, 497-534

docs/http-transport-api.md (1)

81-109: Outstanding documentation coverage for structured content!

The documentation comprehensively covers the new feature with:

  • Clear request/response examples showing structured content usage
  • Well-organized schema documentation for BifrostMessage, ContentBlock, and ImageURLStruct
  • Practical integration examples in multiple programming languages
  • Helpful curl examples demonstrating the API usage

Also applies to: 245-273, 486-505, 592-609, 634-649, 672-684

core/providers/bedrock.go (5)

408-426: Well-designed tool call content parser!

The function robustly handles both JSON and text content with:

  • Proper error handling and fallback to text
  • Special handling for JSON arrays (wrapped in a content object)
  • Clear return structure with either "json" or "text" key

454-466: Flexible system message content extraction.

The code properly handles both content formats:

  • Direct access via ContentStr for simple text
  • Iteration through ContentBlocks to extract text content
  • Graceful handling of nil values

480-492: Consistent tool call content handling.

Good use of the parseBedrockAnthropicMessageToolCallContent function to handle both content formats uniformly. The aggregation of multiple content blocks is implemented correctly.


519-554: Comprehensive image content processing!

Excellent implementation with:

  • Proper URL sanitization using the shared utility
  • Metadata extraction for format detection
  • Correct adaptation to Bedrock's expected image structure
  • Media type prefix removal for Bedrock compatibility

909-917: Correct transition to structured content blocks.

The response handling properly:

  • Builds an array of ContentBlock objects instead of concatenating strings
  • Wraps each text content in the appropriate ContentBlock structure
  • Sets the ContentBlocks field in the response message

Also applies to: 957-960

core/providers/cohere.go (3)

231-231: LGTM!

The change correctly accesses the ContentStr field of the new MessageContent structure for tool result outputs.


420-424: LGTM!

Correctly constructs BifrostMessage with the new MessageContent structure.


504-507: LGTM!

Correctly converts chat history messages to use the new MessageContent structure.

core/schemas/bifrost.go (3)

158-200: Well-implemented polymorphic content structure.

The MessageContent implementation correctly:

  • Validates that only one field is set during marshaling
  • Handles both string and array formats during unmarshaling
  • Marshals content directly without unnecessary wrapper objects

202-213: Clean content block design.

The ContentBlock structure provides a well-designed, extensible format for supporting different content types (text and images).


217-217: Good simplification of message structures.

The removal of ImageContent from ToolMessage and the introduction of ImageURLStruct simplifies the schema while maintaining functionality through the new ContentBlock system.

Also applies to: 229-232

@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-11-refactor_changed_content_schema_to_follow_openai branch from 05c93c4 to 72a4006 Compare June 11, 2025 14:54
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: 10

🔭 Outside diff range comments (2)
docs/openapi.json (1)

440-462: ⚠️ Potential issue

content should be declared as a required field in BifrostMessage

The markdown docs (table at lines 245-254 of http-transport-api.md) state that content is required, and the server code relies on its presence.
However, the OpenAPI schema still lists only "role" in the required array, leaving content optional. This divergence will break client-side validation / code-gen.

- "required": ["role"],
+ "required": ["role", "content"],

Update the required list (and regenerate client stubs) so that SDKs do not allow messages without content.

core/providers/cohere.go (1)

453-472: 🧹 Nitpick (assertive)

Consider documenting the unused function's purpose.

The processImageContent function is correctly updated but currently unused. Consider adding a comment explaining it's reserved for future Cohere image support.

Add documentation above the function:

+// processImageContent is reserved for future use when Cohere adds image support.
+// Currently unused as Cohere v1 does not support image content.
 // processImageContent processes image content for Cohere API format.
🧰 Tools
🪛 golangci-lint (1.64.8)

453-453: func processImageContent is unused

(unused)

♻️ Duplicate comments (7)
core/providers/azure.go (1)

272-275: Prefer bifrost.Ptr over taking the address manually

The code base conventionally uses the helper bifrost.Ptr(...) to create pointers to stack variables. Re-using the helper keeps style consistent and avoids accidental mistakes when the helper’s semantics evolve.

core/tests/tests.go (6)

148-152: Pointer helper usage repetition noted earlier – leaving as-is per author preference.


165-168: Same logging consideration as above; applies throughout similar log.Println sites.


222-225: Logging nit identical to the first comment – same refactor advice applies.


264-267: Logging nit identical to the first comment – same refactor advice applies.


302-305: Pointer helper repetition – acknowledged and intentionally kept as per earlier discussion.


318-318: Logging nit identical to the first comment – same refactor advice applies.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 05c93c4 and 72a4006.

📒 Files selected for processing (12)
  • README.md (1 hunks)
  • core/providers/anthropic.go (7 hunks)
  • core/providers/azure.go (1 hunks)
  • core/providers/bedrock.go (9 hunks)
  • core/providers/cohere.go (5 hunks)
  • core/providers/openai.go (1 hunks)
  • core/providers/utils.go (2 hunks)
  • core/schemas/bifrost.go (3 hunks)
  • core/tests/e2e_tool_test.go (3 hunks)
  • core/tests/tests.go (10 hunks)
  • docs/http-transport-api.md (6 hunks)
  • docs/openapi.json (3 hunks)
🧰 Additional context used
🧠 Learnings (7)
core/tests/e2e_tool_test.go (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/bedrock.go:443-468
Timestamp: 2025-06-04T09:32:15.826Z
Learning: In core/providers/bedrock.go, for tool call result messages (ModelChatMessageRoleTool), the Content field represents the actual tool call output. A tool result message should only be created when msg.Content is non-nil, as there's no semantic meaning to a tool result without output content.
core/providers/openai.go (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#63
File: transports/bifrost-http/integrations/openai/types.go:89-119
Timestamp: 2025-06-10T11:00:02.852Z
Learning: In the Bifrost OpenAI integration (transports/bifrost-http/integrations/openai/types.go), the convertOpenAIContent function currently only handles the last image URL when multiple images are present in a content array. The user Pratham-Mishra04 has acknowledged this limitation and indicated it's part of a larger architectural issue that will be addressed comprehensively later, rather than with piecemeal fixes.
core/tests/tests.go (2)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#74
File: core/tests/tests.go:393-409
Timestamp: 2025-06-11T14:35:19.121Z
Learning: In core/tests/tests.go, the helper function getResultContent is intentionally designed to extract content only from the first element of result.Choices; this is expected behavior for the current test strategy.
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.
core/providers/bedrock.go (3)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/bedrock.go:443-468
Timestamp: 2025-06-04T09:32:15.826Z
Learning: In core/providers/bedrock.go, for tool call result messages (ModelChatMessageRoleTool), the Content field represents the actual tool call output. A tool result message should only be created when msg.Content is non-nil, as there's no semantic meaning to a tool result without output content.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:526-550
Timestamp: 2025-06-04T09:29:46.287Z
Learning: In core/providers/anthropic.go, the content field in formattedMessages is always of type []interface{} because it's explicitly constructed that way upstream in the prepareAnthropicChatRequest function. Defensive type casting for multiple types is not needed since the type is guaranteed by the construction logic.
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.
core/providers/cohere.go (3)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:526-550
Timestamp: 2025-06-04T09:29:46.287Z
Learning: In core/providers/anthropic.go, the content field in formattedMessages is always of type []interface{} because it's explicitly constructed that way upstream in the prepareAnthropicChatRequest function. Defensive type casting for multiple types is not needed since the type is guaranteed by the construction logic.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/bedrock.go:443-468
Timestamp: 2025-06-04T09:32:15.826Z
Learning: In core/providers/bedrock.go, for tool call result messages (ModelChatMessageRoleTool), the Content field represents the actual tool call output. A tool result message should only be created when msg.Content is non-nil, as there's no semantic meaning to a tool result without output content.
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.
core/providers/anthropic.go (3)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:526-550
Timestamp: 2025-06-04T09:29:46.287Z
Learning: In core/providers/anthropic.go, the content field in formattedMessages is always of type []interface{} because it's explicitly constructed that way upstream in the prepareAnthropicChatRequest function. Defensive type casting for multiple types is not needed since the type is guaranteed by the construction logic.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/bedrock.go:443-468
Timestamp: 2025-06-04T09:32:15.826Z
Learning: In core/providers/bedrock.go, for tool call result messages (ModelChatMessageRoleTool), the Content field represents the actual tool call output. A tool result message should only be created when msg.Content is non-nil, as there's no semantic meaning to a tool result without output content.
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.
core/schemas/bifrost.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.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 (5)
core/providers/azure.go (1)
core/schemas/bifrost.go (2)
  • ModelChatMessageRoleAssistant (28-28)
  • MessageContent (158-161)
core/tests/e2e_tool_test.go (2)
core/schemas/bifrost.go (3)
  • ModelChatMessageRoleUser (29-29)
  • MessageContent (158-161)
  • ModelChatMessageRoleTool (32-32)
core/utils.go (1)
  • Ptr (3-5)
core/tests/tests.go (3)
core/schemas/provider.go (1)
  • Provider (142-149)
core/schemas/bifrost.go (7)
  • ModelChatMessageRoleUser (29-29)
  • MessageContent (158-161)
  • ContentBlock (209-213)
  • ContentBlockTypeText (205-205)
  • ContentBlockTypeImage (206-206)
  • ImageURLStruct (229-232)
  • BifrostResponse (237-247)
core/utils.go (1)
  • Ptr (3-5)
core/providers/cohere.go (3)
core/schemas/bifrost.go (2)
  • MessageContent (158-161)
  • ImageURLStruct (229-232)
core/providers/utils.go (2)
  • SanitizeImageURL (355-401)
  • ExtractURLTypeInfo (406-411)
core/providers/anthropic.go (1)
  • AnthropicImageContent (72-76)
core/providers/anthropic.go (3)
core/providers/utils.go (4)
  • ImageContentType (50-50)
  • SanitizeImageURL (355-401)
  • ExtractURLTypeInfo (406-411)
  • ImageContentTypeURL (54-54)
core/schemas/bifrost.go (4)
  • ModelChatMessageRoleAssistant (28-28)
  • MessageContent (158-161)
  • ImageURLStruct (229-232)
  • ContentBlock (209-213)
core/providers/bedrock.go (1)
  • BedrockAnthropicSystemMessage (69-71)
🪛 golangci-lint (1.64.8)
core/providers/cohere.go

453-453: func processImageContent is unused

(unused)

🔇 Additional comments (30)
core/providers/openai.go (1)

231-234: 👍 Slice-index assignment fixes the earlier copy-mutation bug

Using contentBlocks[i] instead of the loop variable ensures the sanitised URL is written back to the underlying slice. Nice catch.

docs/http-transport-api.md (1)

81-109: Great addition of a concrete structured-content example

The JSON sample clearly shows mixed text and image_url blocks and will be invaluable for integrators.

core/providers/cohere.go (5)

231-231: LGTM!

Correctly updated to access the string content from the new MessageContent structure.


238-261: Content handling correctly updated for the new structure.

The code properly handles both ContentStr and ContentBlocks, extracting text content appropriately for Cohere's API format.


273-284: Last message handling is correct.

Appropriately processes both content types, concatenating text blocks when needed for Cohere's single message string requirement.


420-423: Response construction updated correctly.

Properly wraps the response content in the new MessageContent structure.


504-507: Chat history conversion updated correctly.

Properly wraps message content in the new structure.

core/schemas/bifrost.go (7)

4-7: Necessary imports added.

The encoding/json and fmt packages are required for the custom JSON marshaling implementation.


150-150: Breaking change correctly implemented.

The Content field now supports the polymorphic MessageContent type, enabling multi-modal content as intended.


158-161: Well-designed polymorphic content structure.

The MessageContent struct appropriately supports both simple strings and structured content blocks.


163-179: Excellent JSON marshaling implementation.

The method correctly validates mutual exclusivity, marshals content directly without wrapping, and handles the nil case appropriately.


181-200: Robust JSON unmarshaling logic.

The method correctly attempts both content types in order and provides clear error messaging.


202-213: Content block types properly defined.

The enum and struct correctly support text and image URL content blocks for multi-modal messages.


217-217: Schema simplifications are appropriate.

The ToolMessage simplification and ImageURLStruct rename align well with the new content model.

Also applies to: 229-232

core/providers/anthropic.go (5)

72-76: Provider-specific image content struct added.

The AnthropicImageContent struct correctly models Anthropic's image content format requirements.


264-267: Text completion response correctly updated.

Properly wraps the completion text in the new MessageContent structure.


368-441: Comprehensive content handling implementation.

The code correctly handles all message types and content formats:

  • System messages extract text from both ContentStr and ContentBlocks
  • Tool messages properly handle content with nil checks
  • User/Assistant messages support both text and image content blocks

The pointer handling is correct throughout.


329-361: Image source mapping correctly updated.

The function properly utilizes the new image URL sanitization utilities and correctly builds source maps for both base64 and URL image types.


599-653: Response parsing preserves content structure.

The implementation correctly builds an array of ContentBlock items, preserving the structured nature of the response content.

core/providers/utils.go (7)

31-62: Well-structured utility foundations.

The pre-compiled regex patterns, file extension mappings, and type definitions provide a solid foundation for the image URL processing utilities.


355-401: Comprehensive URL sanitization implementation.

The function correctly handles all URL types: data URLs, raw base64 data, and HTTP/HTTPS URLs. The validation logic is thorough and the base64 detection/conversion is well-implemented.


406-411: Clean extraction logic.

Appropriately delegates to specialized functions based on URL type.


414-442: Data URL parsing is correct.

The function properly extracts media type, encoding, and data components from data URLs.


445-468: File extension inference implemented well.

The function correctly uses the map-based approach for media type inference from file extensions.


471-499: Image type detection is comprehensive.

The function correctly identifies image types from base64 prefixes, including the improved WebP detection that checks specific byte positions.


502-508: Efficient base64 validation.

The function correctly uses the pre-compiled regex for performance as suggested.

README.md (1)

152-157: Example snippet correctly reflects the new MessageContent API – no issues spotted.
The updated example compiles fine against the refactored schemas and clearly demonstrates the new ContentStr usage.

core/tests/e2e_tool_test.go (3)

36-40: User-message construction aligns with the new schema.
Switching to MessageContent{ContentStr: bifrost.Ptr(...)} is exactly what we need after the refactor.


94-98: Tool-result message adapted correctly.
The test now wraps the JSON string inside ContentStr; this will exercise the provider’s tool-result path as intended.


121-124: Assertion helper use looks solid.
getResultContent keeps the test concise and prevents pointer-boilerplate in the assertion block.

@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-11-refactor_changed_content_schema_to_follow_openai branch from 72a4006 to e437920 Compare June 11, 2025 15:13
Copy link
Contributor

akshaydeo commented Jun 11, 2025

Merge activity

  • Jun 11, 4:27 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Jun 11, 4:27 PM UTC: @akshaydeo merged this pull request with Graphite.

@akshaydeo akshaydeo merged commit 4e5da23 into main Jun 11, 2025
1 of 2 checks passed
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